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

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 dcheng's comments 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 <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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 254
254 for (; device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) { 255 for (; device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) {
255 if (fmtdesc.pixelformat == V4L2_PIX_FMT_JPEG) 256 if (fmtdesc.pixelformat == V4L2_PIX_FMT_JPEG)
256 return true; 257 return true;
257 } 258 }
258 return false; 259 return false;
259 } 260 }
260 261
261 void V4L2JpegDecodeAccelerator::DecodeTask(scoped_ptr<JobRecord> job_record) { 262 void V4L2JpegDecodeAccelerator::DecodeTask(scoped_ptr<JobRecord> job_record) {
262 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 263 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
263 job_record->shm.reset( 264 if (!job_record->shm.Map()) {
264 new base::SharedMemory(job_record->bitstream_buffer.handle(), true));
265 if (!job_record->shm->Map(job_record->bitstream_buffer.size())) {
266 PLOG(ERROR) << __func__ << ": could not map bitstream_buffer"; 265 PLOG(ERROR) << __func__ << ": could not map bitstream_buffer";
267 PostNotifyError(job_record->bitstream_buffer.id(), UNREADABLE_INPUT); 266 PostNotifyError(job_record->bitstream_buffer_id, UNREADABLE_INPUT);
268 return; 267 return;
269 } 268 }
270 input_jobs_.push(make_linked_ptr(job_record.release())); 269 input_jobs_.push(make_linked_ptr(job_record.release()));
271 270
272 ServiceDeviceTask(false); 271 ServiceDeviceTask(false);
273 } 272 }
274 273
275 size_t V4L2JpegDecodeAccelerator::InputBufferQueuedCount() { 274 size_t V4L2JpegDecodeAccelerator::InputBufferQueuedCount() {
276 return input_buffer_map_.size() - free_input_buffers_.size(); 275 return input_buffer_map_.size() - free_input_buffers_.size();
277 } 276 }
278 277
279 size_t V4L2JpegDecodeAccelerator::OutputBufferQueuedCount() { 278 size_t V4L2JpegDecodeAccelerator::OutputBufferQueuedCount() {
280 return output_buffer_map_.size() - free_output_buffers_.size(); 279 return output_buffer_map_.size() - free_output_buffers_.size();
281 } 280 }
282 281
283 bool V4L2JpegDecodeAccelerator::ShouldRecreateInputBuffers() { 282 bool V4L2JpegDecodeAccelerator::ShouldRecreateInputBuffers() {
284 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 283 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
285 if (input_jobs_.empty()) 284 if (input_jobs_.empty())
286 return false; 285 return false;
287 286
288 linked_ptr<JobRecord> job_record = input_jobs_.front(); 287 linked_ptr<JobRecord> job_record = input_jobs_.front();
289 // Check input buffer size is enough 288 // Check input buffer size is enough
290 return (input_buffer_map_.empty() || 289 return (input_buffer_map_.empty() ||
291 (job_record->bitstream_buffer.size() + sizeof(kDefaultDhtSeg)) > 290 (job_record->shm.size() + sizeof(kDefaultDhtSeg)) >
292 input_buffer_map_.front().length); 291 input_buffer_map_.front().length);
293 } 292 }
294 293
295 bool V4L2JpegDecodeAccelerator::RecreateInputBuffers() { 294 bool V4L2JpegDecodeAccelerator::RecreateInputBuffers() {
296 DVLOG(3) << __func__; 295 DVLOG(3) << __func__;
297 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 296 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
298 297
299 // If running queue is not empty, we should wait until pending frames finish. 298 // If running queue is not empty, we should wait until pending frames finish.
300 if (!running_jobs_.empty()) 299 if (!running_jobs_.empty())
301 return true; 300 return true;
(...skipping 24 matching lines...) Expand all
326 325
327 bool V4L2JpegDecodeAccelerator::CreateInputBuffers() { 326 bool V4L2JpegDecodeAccelerator::CreateInputBuffers() {
328 DVLOG(3) << __func__; 327 DVLOG(3) << __func__;
329 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 328 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
330 DCHECK(!input_streamon_); 329 DCHECK(!input_streamon_);
331 DCHECK(!input_jobs_.empty()); 330 DCHECK(!input_jobs_.empty());
332 linked_ptr<JobRecord> job_record = input_jobs_.front(); 331 linked_ptr<JobRecord> job_record = input_jobs_.front();
333 // The input image may miss huffman table. We didn't parse the image before, 332 // The input image may miss huffman table. We didn't parse the image before,
334 // so we create more to avoid the situation of not enough memory. 333 // so we create more to avoid the situation of not enough memory.
335 // Reserve twice size to avoid recreating input buffer frequently. 334 // Reserve twice size to avoid recreating input buffer frequently.
336 size_t reserve_size = 335 size_t reserve_size = (job_record->shm.size() + sizeof(kDefaultDhtSeg)) * 2;
337 (job_record->bitstream_buffer.size() + sizeof(kDefaultDhtSeg)) * 2;
338 struct v4l2_format format; 336 struct v4l2_format format;
339 memset(&format, 0, sizeof(format)); 337 memset(&format, 0, sizeof(format));
340 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 338 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
341 format.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; 339 format.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
342 format.fmt.pix.sizeimage = reserve_size; 340 format.fmt.pix.sizeimage = reserve_size;
343 format.fmt.pix.field = V4L2_FIELD_ANY; 341 format.fmt.pix.field = V4L2_FIELD_ANY;
344 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format); 342 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
345 343
346 struct v4l2_requestbuffers reqbufs; 344 struct v4l2_requestbuffers reqbufs;
347 memset(&reqbufs, 0, sizeof(reqbufs)); 345 memset(&reqbufs, 0, sizeof(reqbufs));
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
704 702
705 if (dqbuf.flags & V4L2_BUF_FLAG_ERROR) { 703 if (dqbuf.flags & V4L2_BUF_FLAG_ERROR) {
706 DVLOG(1) << "Dequeue output buffer error."; 704 DVLOG(1) << "Dequeue output buffer error.";
707 PostNotifyError(kInvalidBitstreamBufferId, UNSUPPORTED_JPEG); 705 PostNotifyError(kInvalidBitstreamBufferId, UNSUPPORTED_JPEG);
708 } else { 706 } else {
709 // Copy the decoded data from output buffer to the buffer provided by the 707 // Copy the decoded data from output buffer to the buffer provided by the
710 // client. Do format conversion when output format is not 708 // client. Do format conversion when output format is not
711 // V4L2_PIX_FMT_YUV420. 709 // V4L2_PIX_FMT_YUV420.
712 if (!CopyOutputImage(output_buffer_pixelformat_, output_record.address, 710 if (!CopyOutputImage(output_buffer_pixelformat_, output_record.address,
713 output_buffer_coded_size_, job_record->out_frame)) { 711 output_buffer_coded_size_, job_record->out_frame)) {
714 PostNotifyError(job_record->bitstream_buffer.id(), PLATFORM_FAILURE); 712 PostNotifyError(job_record->bitstream_buffer_id, PLATFORM_FAILURE);
715 return; 713 return;
716 } 714 }
717 715
718 DVLOG(3) << "Decoding finished, returning bitstream buffer, id=" 716 DVLOG(3) << "Decoding finished, returning bitstream buffer, id="
719 << job_record->bitstream_buffer.id(); 717 << job_record->bitstream_buffer_id;
720 718
721 child_task_runner_->PostTask( 719 child_task_runner_->PostTask(
722 FROM_HERE, 720 FROM_HERE, base::Bind(&V4L2JpegDecodeAccelerator::VideoFrameReady,
723 base::Bind(&V4L2JpegDecodeAccelerator::VideoFrameReady, weak_ptr_, 721 weak_ptr_, job_record->bitstream_buffer_id));
724 job_record->bitstream_buffer.id()));
725 } 722 }
726 } 723 }
727 } 724 }
728 725
729 static bool AddHuffmanTable(const void* input_ptr, 726 static bool AddHuffmanTable(const void* input_ptr,
730 size_t input_size, 727 size_t input_size,
731 void* output_ptr, 728 void* output_ptr,
732 size_t output_size) { 729 size_t output_size) {
733 DCHECK(input_ptr); 730 DCHECK(input_ptr);
734 DCHECK(output_ptr); 731 DCHECK(output_ptr);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
812 DCHECK(!free_input_buffers_.empty()); 809 DCHECK(!free_input_buffers_.empty());
813 810
814 // Enqueue an input (VIDEO_OUTPUT) buffer for an input video frame. 811 // Enqueue an input (VIDEO_OUTPUT) buffer for an input video frame.
815 linked_ptr<JobRecord> job_record = input_jobs_.front(); 812 linked_ptr<JobRecord> job_record = input_jobs_.front();
816 input_jobs_.pop(); 813 input_jobs_.pop();
817 const int index = free_input_buffers_.back(); 814 const int index = free_input_buffers_.back();
818 BufferRecord& input_record = input_buffer_map_[index]; 815 BufferRecord& input_record = input_buffer_map_[index];
819 DCHECK(!input_record.at_device); 816 DCHECK(!input_record.at_device);
820 817
821 // It will add default huffman segment if it's missing. 818 // It will add default huffman segment if it's missing.
822 if (!AddHuffmanTable(job_record->shm->memory(), 819 if (!AddHuffmanTable(job_record->shm.memory(), job_record->shm.size(),
823 job_record->bitstream_buffer.size(),
824 input_record.address, input_record.length)) { 820 input_record.address, input_record.length)) {
825 PostNotifyError(job_record->bitstream_buffer.id(), PARSE_JPEG_FAILED); 821 PostNotifyError(job_record->bitstream_buffer_id, PARSE_JPEG_FAILED);
826 return false; 822 return false;
827 } 823 }
828 824
829 struct v4l2_buffer qbuf; 825 struct v4l2_buffer qbuf;
830 memset(&qbuf, 0, sizeof(qbuf)); 826 memset(&qbuf, 0, sizeof(qbuf));
831 qbuf.index = index; 827 qbuf.index = index;
832 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 828 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
833 qbuf.memory = V4L2_MEMORY_MMAP; 829 qbuf.memory = V4L2_MEMORY_MMAP;
834 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf); 830 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
835 input_record.at_device = true; 831 input_record.at_device = true;
836 running_jobs_.push(job_record); 832 running_jobs_.push(job_record);
837 free_input_buffers_.pop_back(); 833 free_input_buffers_.pop_back();
838 834
839 DVLOG(3) << __func__ << ": enqueued frame id=" 835 DVLOG(3) << __func__
840 << job_record->bitstream_buffer.id() << " to device."; 836 << ": enqueued frame id=" << job_record->bitstream_buffer_id
837 << " to device.";
841 return true; 838 return true;
842 } 839 }
843 840
844 bool V4L2JpegDecodeAccelerator::EnqueueOutputRecord() { 841 bool V4L2JpegDecodeAccelerator::EnqueueOutputRecord() {
845 DCHECK(!free_output_buffers_.empty()); 842 DCHECK(!free_output_buffers_.empty());
846 843
847 // Enqueue an output (VIDEO_CAPTURE) buffer. 844 // Enqueue an output (VIDEO_CAPTURE) buffer.
848 const int index = free_output_buffers_.back(); 845 const int index = free_output_buffers_.back();
849 BufferRecord& output_record = output_buffer_map_[index]; 846 BufferRecord& output_record = output_buffer_map_[index];
850 DCHECK(!output_record.at_device); 847 DCHECK(!output_record.at_device);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 device_poll_thread_.Stop(); 881 device_poll_thread_.Stop();
885 882
886 // Clear the interrupt now, to be sure. 883 // Clear the interrupt now, to be sure.
887 if (!device_->ClearDevicePollInterrupt()) 884 if (!device_->ClearDevicePollInterrupt())
888 return false; 885 return false;
889 886
890 return true; 887 return true;
891 } 888 }
892 889
893 } // namespace content 890 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698