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

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: address review comments and rebase Created 4 years, 9 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 <string.h> 7 #include <string.h>
8 #include <sys/mman.h> 8 #include <sys/mman.h>
9 9
10 #include "base/big_endian.h" 10 #include "base/big_endian.h"
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 }; 105 };
106 106
107 V4L2JpegDecodeAccelerator::BufferRecord::BufferRecord() 107 V4L2JpegDecodeAccelerator::BufferRecord::BufferRecord()
108 : address(nullptr), length(0), at_device(false) { 108 : address(nullptr), length(0), at_device(false) {
109 } 109 }
110 110
111 V4L2JpegDecodeAccelerator::BufferRecord::~BufferRecord() { 111 V4L2JpegDecodeAccelerator::BufferRecord::~BufferRecord() {
112 } 112 }
113 113
114 V4L2JpegDecodeAccelerator::JobRecord::JobRecord( 114 V4L2JpegDecodeAccelerator::JobRecord::JobRecord(
115 media::BitstreamBuffer bitstream_buffer, 115 const media::BitstreamBuffer& bitstream_buffer,
116 scoped_refptr<media::VideoFrame> video_frame) 116 scoped_refptr<media::VideoFrame> video_frame)
117 : bitstream_buffer(bitstream_buffer), out_frame(video_frame) { 117 : bitstream_buffer_id(bitstream_buffer.id()),
118 } 118 shm(bitstream_buffer, true),
119 out_frame(video_frame) {}
119 120
120 V4L2JpegDecodeAccelerator::JobRecord::~JobRecord() { 121 V4L2JpegDecodeAccelerator::JobRecord::~JobRecord() {
121 } 122 }
122 123
123 V4L2JpegDecodeAccelerator::V4L2JpegDecodeAccelerator( 124 V4L2JpegDecodeAccelerator::V4L2JpegDecodeAccelerator(
124 const scoped_refptr<V4L2Device>& device, 125 const scoped_refptr<V4L2Device>& device,
125 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) 126 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
126 : output_buffer_pixelformat_(0), 127 : output_buffer_pixelformat_(0),
127 child_task_runner_(base::ThreadTaskRunnerHandle::Get()), 128 child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
128 io_task_runner_(io_task_runner), 129 io_task_runner_(io_task_runner),
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 262
262 for (; device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) { 263 for (; device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) {
263 if (fmtdesc.pixelformat == V4L2_PIX_FMT_JPEG) 264 if (fmtdesc.pixelformat == V4L2_PIX_FMT_JPEG)
264 return true; 265 return true;
265 } 266 }
266 return false; 267 return false;
267 } 268 }
268 269
269 void V4L2JpegDecodeAccelerator::DecodeTask(scoped_ptr<JobRecord> job_record) { 270 void V4L2JpegDecodeAccelerator::DecodeTask(scoped_ptr<JobRecord> job_record) {
270 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 271 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
271 job_record->shm.reset( 272 if (!job_record->shm.Map()) {
272 new base::SharedMemory(job_record->bitstream_buffer.handle(), true));
273 if (!job_record->shm->Map(job_record->bitstream_buffer.size())) {
274 PLOG(ERROR) << __func__ << ": could not map bitstream_buffer"; 273 PLOG(ERROR) << __func__ << ": could not map bitstream_buffer";
275 PostNotifyError(job_record->bitstream_buffer.id(), UNREADABLE_INPUT); 274 PostNotifyError(job_record->bitstream_buffer_id, UNREADABLE_INPUT);
276 return; 275 return;
277 } 276 }
278 input_jobs_.push(make_linked_ptr(job_record.release())); 277 input_jobs_.push(make_linked_ptr(job_record.release()));
279 278
280 ServiceDeviceTask(false); 279 ServiceDeviceTask(false);
281 } 280 }
282 281
283 size_t V4L2JpegDecodeAccelerator::InputBufferQueuedCount() { 282 size_t V4L2JpegDecodeAccelerator::InputBufferQueuedCount() {
284 return input_buffer_map_.size() - free_input_buffers_.size(); 283 return input_buffer_map_.size() - free_input_buffers_.size();
285 } 284 }
286 285
287 size_t V4L2JpegDecodeAccelerator::OutputBufferQueuedCount() { 286 size_t V4L2JpegDecodeAccelerator::OutputBufferQueuedCount() {
288 return output_buffer_map_.size() - free_output_buffers_.size(); 287 return output_buffer_map_.size() - free_output_buffers_.size();
289 } 288 }
290 289
291 bool V4L2JpegDecodeAccelerator::ShouldRecreateInputBuffers() { 290 bool V4L2JpegDecodeAccelerator::ShouldRecreateInputBuffers() {
292 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 291 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
293 if (input_jobs_.empty()) 292 if (input_jobs_.empty())
294 return false; 293 return false;
295 294
296 linked_ptr<JobRecord> job_record = input_jobs_.front(); 295 linked_ptr<JobRecord> job_record = input_jobs_.front();
297 // Check input buffer size is enough 296 // Check input buffer size is enough
298 return (input_buffer_map_.empty() || 297 return (input_buffer_map_.empty() ||
299 (job_record->bitstream_buffer.size() + sizeof(kDefaultDhtSeg)) > 298 (job_record->shm.size() + sizeof(kDefaultDhtSeg)) >
300 input_buffer_map_.front().length); 299 input_buffer_map_.front().length);
301 } 300 }
302 301
303 bool V4L2JpegDecodeAccelerator::RecreateInputBuffers() { 302 bool V4L2JpegDecodeAccelerator::RecreateInputBuffers() {
304 DVLOG(3) << __func__; 303 DVLOG(3) << __func__;
305 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 304 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
306 305
307 // If running queue is not empty, we should wait until pending frames finish. 306 // If running queue is not empty, we should wait until pending frames finish.
308 if (!running_jobs_.empty()) 307 if (!running_jobs_.empty())
309 return true; 308 return true;
(...skipping 24 matching lines...) Expand all
334 333
335 bool V4L2JpegDecodeAccelerator::CreateInputBuffers() { 334 bool V4L2JpegDecodeAccelerator::CreateInputBuffers() {
336 DVLOG(3) << __func__; 335 DVLOG(3) << __func__;
337 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 336 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
338 DCHECK(!input_streamon_); 337 DCHECK(!input_streamon_);
339 DCHECK(!input_jobs_.empty()); 338 DCHECK(!input_jobs_.empty());
340 linked_ptr<JobRecord> job_record = input_jobs_.front(); 339 linked_ptr<JobRecord> job_record = input_jobs_.front();
341 // The input image may miss huffman table. We didn't parse the image before, 340 // The input image may miss huffman table. We didn't parse the image before,
342 // so we create more to avoid the situation of not enough memory. 341 // so we create more to avoid the situation of not enough memory.
343 // Reserve twice size to avoid recreating input buffer frequently. 342 // Reserve twice size to avoid recreating input buffer frequently.
344 size_t reserve_size = 343 size_t reserve_size = (job_record->shm.size() + sizeof(kDefaultDhtSeg)) * 2;
345 (job_record->bitstream_buffer.size() + sizeof(kDefaultDhtSeg)) * 2;
346 struct v4l2_format format; 344 struct v4l2_format format;
347 memset(&format, 0, sizeof(format)); 345 memset(&format, 0, sizeof(format));
348 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 346 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
349 format.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; 347 format.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
350 format.fmt.pix.sizeimage = reserve_size; 348 format.fmt.pix.sizeimage = reserve_size;
351 format.fmt.pix.field = V4L2_FIELD_ANY; 349 format.fmt.pix.field = V4L2_FIELD_ANY;
352 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format); 350 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
353 351
354 struct v4l2_requestbuffers reqbufs; 352 struct v4l2_requestbuffers reqbufs;
355 memset(&reqbufs, 0, sizeof(reqbufs)); 353 memset(&reqbufs, 0, sizeof(reqbufs));
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 710
713 if (dqbuf.flags & V4L2_BUF_FLAG_ERROR) { 711 if (dqbuf.flags & V4L2_BUF_FLAG_ERROR) {
714 DVLOG(1) << "Dequeue output buffer error."; 712 DVLOG(1) << "Dequeue output buffer error.";
715 PostNotifyError(kInvalidBitstreamBufferId, UNSUPPORTED_JPEG); 713 PostNotifyError(kInvalidBitstreamBufferId, UNSUPPORTED_JPEG);
716 } else { 714 } else {
717 // Copy the decoded data from output buffer to the buffer provided by the 715 // Copy the decoded data from output buffer to the buffer provided by the
718 // client. Do format conversion when output format is not 716 // client. Do format conversion when output format is not
719 // V4L2_PIX_FMT_YUV420. 717 // V4L2_PIX_FMT_YUV420.
720 if (!CopyOutputImage(output_buffer_pixelformat_, output_record.address, 718 if (!CopyOutputImage(output_buffer_pixelformat_, output_record.address,
721 output_buffer_coded_size_, job_record->out_frame)) { 719 output_buffer_coded_size_, job_record->out_frame)) {
722 PostNotifyError(job_record->bitstream_buffer.id(), PLATFORM_FAILURE); 720 PostNotifyError(job_record->bitstream_buffer_id, PLATFORM_FAILURE);
723 return; 721 return;
724 } 722 }
725 723
726 DVLOG(3) << "Decoding finished, returning bitstream buffer, id=" 724 DVLOG(3) << "Decoding finished, returning bitstream buffer, id="
727 << job_record->bitstream_buffer.id(); 725 << job_record->bitstream_buffer_id;
728 726
729 child_task_runner_->PostTask( 727 child_task_runner_->PostTask(
730 FROM_HERE, 728 FROM_HERE, base::Bind(&V4L2JpegDecodeAccelerator::VideoFrameReady,
731 base::Bind(&V4L2JpegDecodeAccelerator::VideoFrameReady, weak_ptr_, 729 weak_ptr_, job_record->bitstream_buffer_id));
732 job_record->bitstream_buffer.id()));
733 } 730 }
734 } 731 }
735 } 732 }
736 733
737 static bool AddHuffmanTable(const void* input_ptr, 734 static bool AddHuffmanTable(const void* input_ptr,
738 size_t input_size, 735 size_t input_size,
739 void* output_ptr, 736 void* output_ptr,
740 size_t output_size) { 737 size_t output_size) {
741 DCHECK(input_ptr); 738 DCHECK(input_ptr);
742 DCHECK(output_ptr); 739 DCHECK(output_ptr);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 DCHECK(!free_input_buffers_.empty()); 817 DCHECK(!free_input_buffers_.empty());
821 818
822 // Enqueue an input (VIDEO_OUTPUT) buffer for an input video frame. 819 // Enqueue an input (VIDEO_OUTPUT) buffer for an input video frame.
823 linked_ptr<JobRecord> job_record = input_jobs_.front(); 820 linked_ptr<JobRecord> job_record = input_jobs_.front();
824 input_jobs_.pop(); 821 input_jobs_.pop();
825 const int index = free_input_buffers_.back(); 822 const int index = free_input_buffers_.back();
826 BufferRecord& input_record = input_buffer_map_[index]; 823 BufferRecord& input_record = input_buffer_map_[index];
827 DCHECK(!input_record.at_device); 824 DCHECK(!input_record.at_device);
828 825
829 // It will add default huffman segment if it's missing. 826 // It will add default huffman segment if it's missing.
830 if (!AddHuffmanTable(job_record->shm->memory(), 827 if (!AddHuffmanTable(job_record->shm.memory(), job_record->shm.size(),
831 job_record->bitstream_buffer.size(),
832 input_record.address, input_record.length)) { 828 input_record.address, input_record.length)) {
833 PostNotifyError(job_record->bitstream_buffer.id(), PARSE_JPEG_FAILED); 829 PostNotifyError(job_record->bitstream_buffer_id, PARSE_JPEG_FAILED);
834 return false; 830 return false;
835 } 831 }
836 832
837 struct v4l2_buffer qbuf; 833 struct v4l2_buffer qbuf;
838 memset(&qbuf, 0, sizeof(qbuf)); 834 memset(&qbuf, 0, sizeof(qbuf));
839 qbuf.index = index; 835 qbuf.index = index;
840 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 836 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
841 qbuf.memory = V4L2_MEMORY_MMAP; 837 qbuf.memory = V4L2_MEMORY_MMAP;
842 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf); 838 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
843 input_record.at_device = true; 839 input_record.at_device = true;
844 running_jobs_.push(job_record); 840 running_jobs_.push(job_record);
845 free_input_buffers_.pop_back(); 841 free_input_buffers_.pop_back();
846 842
847 DVLOG(3) << __func__ << ": enqueued frame id=" 843 DVLOG(3) << __func__
848 << job_record->bitstream_buffer.id() << " to device."; 844 << ": enqueued frame id=" << job_record->bitstream_buffer_id
845 << " to device.";
849 return true; 846 return true;
850 } 847 }
851 848
852 bool V4L2JpegDecodeAccelerator::EnqueueOutputRecord() { 849 bool V4L2JpegDecodeAccelerator::EnqueueOutputRecord() {
853 DCHECK(!free_output_buffers_.empty()); 850 DCHECK(!free_output_buffers_.empty());
854 851
855 // Enqueue an output (VIDEO_CAPTURE) buffer. 852 // Enqueue an output (VIDEO_CAPTURE) buffer.
856 const int index = free_output_buffers_.back(); 853 const int index = free_output_buffers_.back();
857 BufferRecord& output_record = output_buffer_map_[index]; 854 BufferRecord& output_record = output_buffer_map_[index];
858 DCHECK(!output_record.at_device); 855 DCHECK(!output_record.at_device);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
892 device_poll_thread_.Stop(); 889 device_poll_thread_.Stop();
893 890
894 // Clear the interrupt now, to be sure. 891 // Clear the interrupt now, to be sure.
895 if (!device_->ClearDevicePollInterrupt()) 892 if (!device_->ClearDevicePollInterrupt())
896 return false; 893 return false;
897 894
898 return true; 895 return true;
899 } 896 }
900 897
901 } // namespace content 898 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698