Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: content/common/gpu/media/v4l2_jpeg_decode_accelerator.cc

Issue 1541353002: Add offset support to BitstreamBuffer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Handle the offset with a helper class Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <errno.h> 5 #include <errno.h>
6 #include <linux/videodev2.h> 6 #include <linux/videodev2.h>
7 #include <sys/mman.h> 7 #include <sys/mman.h>
8 8
9 #include "base/big_endian.h" 9 #include "base/big_endian.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 }; 104 };
105 105
106 V4L2JpegDecodeAccelerator::BufferRecord::BufferRecord() 106 V4L2JpegDecodeAccelerator::BufferRecord::BufferRecord()
107 : address(nullptr), length(0), at_device(false) { 107 : address(nullptr), length(0), at_device(false) {
108 } 108 }
109 109
110 V4L2JpegDecodeAccelerator::BufferRecord::~BufferRecord() { 110 V4L2JpegDecodeAccelerator::BufferRecord::~BufferRecord() {
111 } 111 }
112 112
113 V4L2JpegDecodeAccelerator::JobRecord::JobRecord( 113 V4L2JpegDecodeAccelerator::JobRecord::JobRecord(
114 media::BitstreamBuffer bitstream_buffer, 114 const media::BitstreamBuffer& bitstream_buffer,
115 scoped_refptr<media::VideoFrame> video_frame) 115 scoped_refptr<media::VideoFrame> video_frame)
116 : bitstream_buffer(bitstream_buffer), out_frame(video_frame) { 116 : bitstream_buffer_id(bitstream_buffer.id()),
117 } 117 shm(bitstream_buffer, true),
118 out_frame(video_frame) {}
118 119
119 V4L2JpegDecodeAccelerator::JobRecord::~JobRecord() { 120 V4L2JpegDecodeAccelerator::JobRecord::~JobRecord() {
120 } 121 }
121 122
122 V4L2JpegDecodeAccelerator::V4L2JpegDecodeAccelerator( 123 V4L2JpegDecodeAccelerator::V4L2JpegDecodeAccelerator(
123 const scoped_refptr<V4L2Device>& device, 124 const scoped_refptr<V4L2Device>& device,
124 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) 125 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
125 : output_buffer_pixelformat_(0), 126 : output_buffer_pixelformat_(0),
126 child_task_runner_(base::ThreadTaskRunnerHandle::Get()), 127 child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
127 io_task_runner_(io_task_runner), 128 io_task_runner_(io_task_runner),
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 253
253 for (; device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) { 254 for (; device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) {
254 if (fmtdesc.pixelformat == V4L2_PIX_FMT_JPEG) 255 if (fmtdesc.pixelformat == V4L2_PIX_FMT_JPEG)
255 return true; 256 return true;
256 } 257 }
257 return false; 258 return false;
258 } 259 }
259 260
260 void V4L2JpegDecodeAccelerator::DecodeTask(scoped_ptr<JobRecord> job_record) { 261 void V4L2JpegDecodeAccelerator::DecodeTask(scoped_ptr<JobRecord> job_record) {
261 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 262 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
262 job_record->shm.reset( 263 if (!job_record->shm.Map()) {
263 new base::SharedMemory(job_record->bitstream_buffer.handle(), true));
264 if (!job_record->shm->Map(job_record->bitstream_buffer.size())) {
265 PLOG(ERROR) << __func__ << ": could not map bitstream_buffer"; 264 PLOG(ERROR) << __func__ << ": could not map bitstream_buffer";
266 PostNotifyError(job_record->bitstream_buffer.id(), UNREADABLE_INPUT); 265 PostNotifyError(job_record->bitstream_buffer_id, UNREADABLE_INPUT);
267 return; 266 return;
268 } 267 }
269 input_jobs_.push(make_linked_ptr(job_record.release())); 268 input_jobs_.push(make_linked_ptr(job_record.release()));
270 269
271 ServiceDeviceTask(false); 270 ServiceDeviceTask(false);
272 } 271 }
273 272
274 size_t V4L2JpegDecodeAccelerator::InputBufferQueuedCount() { 273 size_t V4L2JpegDecodeAccelerator::InputBufferQueuedCount() {
275 return input_buffer_map_.size() - free_input_buffers_.size(); 274 return input_buffer_map_.size() - free_input_buffers_.size();
276 } 275 }
277 276
278 size_t V4L2JpegDecodeAccelerator::OutputBufferQueuedCount() { 277 size_t V4L2JpegDecodeAccelerator::OutputBufferQueuedCount() {
279 return output_buffer_map_.size() - free_output_buffers_.size(); 278 return output_buffer_map_.size() - free_output_buffers_.size();
280 } 279 }
281 280
282 bool V4L2JpegDecodeAccelerator::ShouldRecreateInputBuffers() { 281 bool V4L2JpegDecodeAccelerator::ShouldRecreateInputBuffers() {
283 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 282 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
284 if (input_jobs_.empty()) 283 if (input_jobs_.empty())
285 return false; 284 return false;
286 285
287 linked_ptr<JobRecord> job_record = input_jobs_.front(); 286 linked_ptr<JobRecord> job_record = input_jobs_.front();
288 // Check input buffer size is enough 287 // Check input buffer size is enough
289 return (input_buffer_map_.empty() || 288 return (input_buffer_map_.empty() ||
290 (job_record->bitstream_buffer.size() + sizeof(kDefaultDhtSeg)) > 289 (job_record->shm.size() + sizeof(kDefaultDhtSeg)) >
291 input_buffer_map_.front().length); 290 input_buffer_map_.front().length);
292 } 291 }
293 292
294 bool V4L2JpegDecodeAccelerator::RecreateInputBuffers() { 293 bool V4L2JpegDecodeAccelerator::RecreateInputBuffers() {
295 DVLOG(3) << __func__; 294 DVLOG(3) << __func__;
296 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 295 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
297 296
298 // If running queue is not empty, we should wait until pending frames finish. 297 // If running queue is not empty, we should wait until pending frames finish.
299 if (!running_jobs_.empty()) 298 if (!running_jobs_.empty())
300 return true; 299 return true;
(...skipping 24 matching lines...) Expand all
325 324
326 bool V4L2JpegDecodeAccelerator::CreateInputBuffers() { 325 bool V4L2JpegDecodeAccelerator::CreateInputBuffers() {
327 DVLOG(3) << __func__; 326 DVLOG(3) << __func__;
328 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 327 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
329 DCHECK(!input_streamon_); 328 DCHECK(!input_streamon_);
330 DCHECK(!input_jobs_.empty()); 329 DCHECK(!input_jobs_.empty());
331 linked_ptr<JobRecord> job_record = input_jobs_.front(); 330 linked_ptr<JobRecord> job_record = input_jobs_.front();
332 // The input image may miss huffman table. We didn't parse the image before, 331 // The input image may miss huffman table. We didn't parse the image before,
333 // so we create more to avoid the situation of not enough memory. 332 // so we create more to avoid the situation of not enough memory.
334 // Reserve twice size to avoid recreating input buffer frequently. 333 // Reserve twice size to avoid recreating input buffer frequently.
335 size_t reserve_size = 334 size_t reserve_size = (job_record->shm.size() + sizeof(kDefaultDhtSeg)) * 2;
336 (job_record->bitstream_buffer.size() + sizeof(kDefaultDhtSeg)) * 2;
337 struct v4l2_format format; 335 struct v4l2_format format;
338 memset(&format, 0, sizeof(format)); 336 memset(&format, 0, sizeof(format));
339 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 337 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
340 format.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; 338 format.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
341 format.fmt.pix.sizeimage = reserve_size; 339 format.fmt.pix.sizeimage = reserve_size;
342 format.fmt.pix.field = V4L2_FIELD_ANY; 340 format.fmt.pix.field = V4L2_FIELD_ANY;
343 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format); 341 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
344 342
345 struct v4l2_requestbuffers reqbufs; 343 struct v4l2_requestbuffers reqbufs;
346 memset(&reqbufs, 0, sizeof(reqbufs)); 344 memset(&reqbufs, 0, sizeof(reqbufs));
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
703 701
704 if (dqbuf.flags & V4L2_BUF_FLAG_ERROR) { 702 if (dqbuf.flags & V4L2_BUF_FLAG_ERROR) {
705 DVLOG(1) << "Dequeue output buffer error."; 703 DVLOG(1) << "Dequeue output buffer error.";
706 PostNotifyError(kInvalidBitstreamBufferId, UNSUPPORTED_JPEG); 704 PostNotifyError(kInvalidBitstreamBufferId, UNSUPPORTED_JPEG);
707 } else { 705 } else {
708 // Copy the decoded data from output buffer to the buffer provided by the 706 // Copy the decoded data from output buffer to the buffer provided by the
709 // client. Do format conversion when output format is not 707 // client. Do format conversion when output format is not
710 // V4L2_PIX_FMT_YUV420. 708 // V4L2_PIX_FMT_YUV420.
711 if (!CopyOutputImage(output_buffer_pixelformat_, output_record.address, 709 if (!CopyOutputImage(output_buffer_pixelformat_, output_record.address,
712 output_buffer_coded_size_, job_record->out_frame)) { 710 output_buffer_coded_size_, job_record->out_frame)) {
713 PostNotifyError(job_record->bitstream_buffer.id(), PLATFORM_FAILURE); 711 PostNotifyError(job_record->bitstream_buffer_id, PLATFORM_FAILURE);
714 return; 712 return;
715 } 713 }
716 714
717 DVLOG(3) << "Decoding finished, returning bitstream buffer, id=" 715 DVLOG(3) << "Decoding finished, returning bitstream buffer, id="
718 << job_record->bitstream_buffer.id(); 716 << job_record->bitstream_buffer_id;
719 717
720 child_task_runner_->PostTask( 718 child_task_runner_->PostTask(
721 FROM_HERE, 719 FROM_HERE, base::Bind(&V4L2JpegDecodeAccelerator::VideoFrameReady,
722 base::Bind(&V4L2JpegDecodeAccelerator::VideoFrameReady, weak_ptr_, 720 weak_ptr_, job_record->bitstream_buffer_id));
723 job_record->bitstream_buffer.id()));
724 } 721 }
725 } 722 }
726 } 723 }
727 724
728 static bool AddHuffmanTable(const void* input_ptr, 725 static bool AddHuffmanTable(const void* input_ptr,
729 size_t input_size, 726 size_t input_size,
730 void* output_ptr, 727 void* output_ptr,
731 size_t output_size) { 728 size_t output_size) {
732 DCHECK(input_ptr); 729 DCHECK(input_ptr);
733 DCHECK(output_ptr); 730 DCHECK(output_ptr);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 DCHECK(!free_input_buffers_.empty()); 808 DCHECK(!free_input_buffers_.empty());
812 809
813 // Enqueue an input (VIDEO_OUTPUT) buffer for an input video frame. 810 // Enqueue an input (VIDEO_OUTPUT) buffer for an input video frame.
814 linked_ptr<JobRecord> job_record = input_jobs_.front(); 811 linked_ptr<JobRecord> job_record = input_jobs_.front();
815 input_jobs_.pop(); 812 input_jobs_.pop();
816 const int index = free_input_buffers_.back(); 813 const int index = free_input_buffers_.back();
817 BufferRecord& input_record = input_buffer_map_[index]; 814 BufferRecord& input_record = input_buffer_map_[index];
818 DCHECK(!input_record.at_device); 815 DCHECK(!input_record.at_device);
819 816
820 // It will add default huffman segment if it's missing. 817 // It will add default huffman segment if it's missing.
821 if (!AddHuffmanTable(job_record->shm->memory(), 818 if (!AddHuffmanTable(job_record->shm.memory(), job_record->shm.size(),
822 job_record->bitstream_buffer.size(),
823 input_record.address, input_record.length)) { 819 input_record.address, input_record.length)) {
824 PostNotifyError(job_record->bitstream_buffer.id(), PARSE_JPEG_FAILED); 820 PostNotifyError(job_record->bitstream_buffer_id, PARSE_JPEG_FAILED);
825 return false; 821 return false;
826 } 822 }
827 823
828 struct v4l2_buffer qbuf; 824 struct v4l2_buffer qbuf;
829 memset(&qbuf, 0, sizeof(qbuf)); 825 memset(&qbuf, 0, sizeof(qbuf));
830 qbuf.index = index; 826 qbuf.index = index;
831 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 827 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
832 qbuf.memory = V4L2_MEMORY_MMAP; 828 qbuf.memory = V4L2_MEMORY_MMAP;
833 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf); 829 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
834 input_record.at_device = true; 830 input_record.at_device = true;
835 running_jobs_.push(job_record); 831 running_jobs_.push(job_record);
836 free_input_buffers_.pop_back(); 832 free_input_buffers_.pop_back();
837 833
838 DVLOG(3) << __func__ << ": enqueued frame id=" 834 DVLOG(3) << __func__
839 << job_record->bitstream_buffer.id() << " to device."; 835 << ": enqueued frame id=" << job_record->bitstream_buffer_id
836 << " to device.";
840 return true; 837 return true;
841 } 838 }
842 839
843 bool V4L2JpegDecodeAccelerator::EnqueueOutputRecord() { 840 bool V4L2JpegDecodeAccelerator::EnqueueOutputRecord() {
844 DCHECK(!free_output_buffers_.empty()); 841 DCHECK(!free_output_buffers_.empty());
845 842
846 // Enqueue an output (VIDEO_CAPTURE) buffer. 843 // Enqueue an output (VIDEO_CAPTURE) buffer.
847 const int index = free_output_buffers_.back(); 844 const int index = free_output_buffers_.back();
848 BufferRecord& output_record = output_buffer_map_[index]; 845 BufferRecord& output_record = output_buffer_map_[index];
849 DCHECK(!output_record.at_device); 846 DCHECK(!output_record.at_device);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 device_poll_thread_.Stop(); 880 device_poll_thread_.Stop();
884 881
885 // Clear the interrupt now, to be sure. 882 // Clear the interrupt now, to be sure.
886 if (!device_->ClearDevicePollInterrupt()) 883 if (!device_->ClearDevicePollInterrupt())
887 return false; 884 return false;
888 885
889 return true; 886 return true;
890 } 887 }
891 888
892 } // namespace content 889 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698