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

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

Issue 2559423002: media/gpu: switch v4l2_jpeg_decode_accelerator to use multi-planar APIs (Closed)
Patch Set: fix a typo in comments Created 4 years 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
« no previous file with comments | « media/gpu/v4l2_jpeg_decode_accelerator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "media/gpu/v4l2_jpeg_decode_accelerator.h" 5 #include "media/gpu/v4l2_jpeg_decode_accelerator.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <linux/videodev2.h> 8 #include <linux/videodev2.h>
9 #include <string.h> 9 #include <string.h>
10 #include <sys/mman.h> 10 #include <sys/mman.h>
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 100 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
101 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 101 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
102 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 102 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
103 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 103 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94,
104 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 104 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
105 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 105 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA,
106 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 106 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4,
107 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 107 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
108 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA}; 108 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA};
109 109
110 V4L2JpegDecodeAccelerator::BufferRecord::BufferRecord() 110 V4L2JpegDecodeAccelerator::BufferRecord::BufferRecord() : at_device(false) {
111 : address(nullptr), length(0), at_device(false) {} 111 memset(address, 0, sizeof(address));
112 memset(length, 0, sizeof(length));
113 }
112 114
113 V4L2JpegDecodeAccelerator::BufferRecord::~BufferRecord() {} 115 V4L2JpegDecodeAccelerator::BufferRecord::~BufferRecord() {}
114 116
115 V4L2JpegDecodeAccelerator::JobRecord::JobRecord( 117 V4L2JpegDecodeAccelerator::JobRecord::JobRecord(
116 const BitstreamBuffer& bitstream_buffer, 118 const BitstreamBuffer& bitstream_buffer,
117 scoped_refptr<VideoFrame> video_frame) 119 scoped_refptr<VideoFrame> video_frame)
118 : bitstream_buffer_id(bitstream_buffer.id()), 120 : bitstream_buffer_id(bitstream_buffer.id()),
119 shm(bitstream_buffer, true), 121 shm(bitstream_buffer, true),
120 out_frame(video_frame) {} 122 out_frame(video_frame) {}
121 123
122 V4L2JpegDecodeAccelerator::JobRecord::~JobRecord() {} 124 V4L2JpegDecodeAccelerator::JobRecord::~JobRecord() {}
123 125
124 V4L2JpegDecodeAccelerator::V4L2JpegDecodeAccelerator( 126 V4L2JpegDecodeAccelerator::V4L2JpegDecodeAccelerator(
125 const scoped_refptr<V4L2Device>& device, 127 const scoped_refptr<V4L2Device>& device,
126 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) 128 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
127 : output_buffer_pixelformat_(0), 129 : output_buffer_pixelformat_(0),
130 output_buffer_num_planes_(0),
128 child_task_runner_(base::ThreadTaskRunnerHandle::Get()), 131 child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
129 io_task_runner_(io_task_runner), 132 io_task_runner_(io_task_runner),
130 client_(nullptr), 133 client_(nullptr),
131 device_(device), 134 device_(device),
132 decoder_thread_("V4L2JpegDecodeThread"), 135 decoder_thread_("V4L2JpegDecodeThread"),
133 device_poll_thread_("V4L2JpegDecodeDevicePollThread"), 136 device_poll_thread_("V4L2JpegDecodeDevicePollThread"),
134 input_streamon_(false), 137 input_streamon_(false),
135 output_streamon_(false), 138 output_streamon_(false),
136 weak_factory_(this) { 139 weak_factory_(this) {
137 weak_ptr_ = weak_factory_.GetWeakPtr(); 140 weak_ptr_ = weak_factory_.GetWeakPtr();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 bool V4L2JpegDecodeAccelerator::Initialize(Client* client) { 190 bool V4L2JpegDecodeAccelerator::Initialize(Client* client) {
188 DCHECK(child_task_runner_->BelongsToCurrentThread()); 191 DCHECK(child_task_runner_->BelongsToCurrentThread());
189 192
190 if (!device_->Open(V4L2Device::Type::kJpegDecoder, V4L2_PIX_FMT_JPEG)) { 193 if (!device_->Open(V4L2Device::Type::kJpegDecoder, V4L2_PIX_FMT_JPEG)) {
191 LOG(ERROR) << "Failed to open device"; 194 LOG(ERROR) << "Failed to open device";
192 return false; 195 return false;
193 } 196 }
194 197
195 // Capabilities check. 198 // Capabilities check.
196 struct v4l2_capability caps; 199 struct v4l2_capability caps;
197 const __u32 kCapsRequired = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M; 200 const __u32 kCapsRequired = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
198 memset(&caps, 0, sizeof(caps)); 201 memset(&caps, 0, sizeof(caps));
199 if (device_->Ioctl(VIDIOC_QUERYCAP, &caps) != 0) { 202 if (device_->Ioctl(VIDIOC_QUERYCAP, &caps) != 0) {
200 PLOG(ERROR) << __func__ << ": ioctl() failed: VIDIOC_QUERYCAP"; 203 PLOG(ERROR) << __func__ << ": ioctl() failed: VIDIOC_QUERYCAP";
201 return false; 204 return false;
202 } 205 }
203 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { 206 if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
204 LOG(ERROR) << __func__ << ": VIDIOC_QUERYCAP, caps check failed: 0x" 207 LOG(ERROR) << __func__ << ": VIDIOC_QUERYCAP, caps check failed: 0x"
205 << std::hex << caps.capabilities; 208 << std::hex << caps.capabilities;
206 return false; 209 return false;
207 } 210 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 293
291 bool V4L2JpegDecodeAccelerator::ShouldRecreateInputBuffers() { 294 bool V4L2JpegDecodeAccelerator::ShouldRecreateInputBuffers() {
292 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 295 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
293 if (input_jobs_.empty()) 296 if (input_jobs_.empty())
294 return false; 297 return false;
295 298
296 linked_ptr<JobRecord> job_record = input_jobs_.front(); 299 linked_ptr<JobRecord> job_record = input_jobs_.front();
297 // Check input buffer size is enough 300 // Check input buffer size is enough
298 return (input_buffer_map_.empty() || 301 return (input_buffer_map_.empty() ||
299 (job_record->shm.size() + sizeof(kDefaultDhtSeg)) > 302 (job_record->shm.size() + sizeof(kDefaultDhtSeg)) >
300 input_buffer_map_.front().length); 303 input_buffer_map_.front().length[0]);
301 } 304 }
302 305
303 bool V4L2JpegDecodeAccelerator::RecreateInputBuffers() { 306 bool V4L2JpegDecodeAccelerator::RecreateInputBuffers() {
304 DVLOG(3) << __func__; 307 DVLOG(3) << __func__;
305 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 308 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
306 309
307 // If running queue is not empty, we should wait until pending frames finish. 310 // If running queue is not empty, we should wait until pending frames finish.
308 if (!running_jobs_.empty()) 311 if (!running_jobs_.empty())
309 return true; 312 return true;
310 313
(...skipping 26 matching lines...) Expand all
337 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 340 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
338 DCHECK(!input_streamon_); 341 DCHECK(!input_streamon_);
339 DCHECK(!input_jobs_.empty()); 342 DCHECK(!input_jobs_.empty());
340 linked_ptr<JobRecord> job_record = input_jobs_.front(); 343 linked_ptr<JobRecord> job_record = input_jobs_.front();
341 // The input image may miss huffman table. We didn't parse the image before, 344 // 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. 345 // so we create more to avoid the situation of not enough memory.
343 // Reserve twice size to avoid recreating input buffer frequently. 346 // Reserve twice size to avoid recreating input buffer frequently.
344 size_t reserve_size = (job_record->shm.size() + sizeof(kDefaultDhtSeg)) * 2; 347 size_t reserve_size = (job_record->shm.size() + sizeof(kDefaultDhtSeg)) * 2;
345 struct v4l2_format format; 348 struct v4l2_format format;
346 memset(&format, 0, sizeof(format)); 349 memset(&format, 0, sizeof(format));
347 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 350 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
348 format.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; 351 format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_JPEG;
349 format.fmt.pix.sizeimage = reserve_size; 352 format.fmt.pix_mp.plane_fmt[0].sizeimage = reserve_size;
350 format.fmt.pix.field = V4L2_FIELD_ANY; 353 format.fmt.pix_mp.field = V4L2_FIELD_ANY;
354 format.fmt.pix_mp.num_planes = kMaxInputPlanes;
351 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format); 355 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
352 356
353 struct v4l2_requestbuffers reqbufs; 357 struct v4l2_requestbuffers reqbufs;
354 memset(&reqbufs, 0, sizeof(reqbufs)); 358 memset(&reqbufs, 0, sizeof(reqbufs));
355 reqbufs.count = kBufferCount; 359 reqbufs.count = kBufferCount;
356 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 360 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
357 reqbufs.memory = V4L2_MEMORY_MMAP; 361 reqbufs.memory = V4L2_MEMORY_MMAP;
358 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); 362 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);
359 363
360 DCHECK(input_buffer_map_.empty()); 364 DCHECK(input_buffer_map_.empty());
361 input_buffer_map_.resize(reqbufs.count); 365 input_buffer_map_.resize(reqbufs.count);
362 366
363 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { 367 for (size_t i = 0; i < input_buffer_map_.size(); ++i) {
364 free_input_buffers_.push_back(i); 368 free_input_buffers_.push_back(i);
365 369
366 struct v4l2_buffer buffer; 370 struct v4l2_buffer buffer;
371 struct v4l2_plane plane;
367 memset(&buffer, 0, sizeof(buffer)); 372 memset(&buffer, 0, sizeof(buffer));
373 memset(&plane, 0, sizeof(plane));
368 buffer.index = i; 374 buffer.index = i;
369 buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 375 buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
376 buffer.m.planes = &plane;
377 buffer.length = kMaxInputPlanes;
370 buffer.memory = V4L2_MEMORY_MMAP; 378 buffer.memory = V4L2_MEMORY_MMAP;
371 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer); 379 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer);
372 void* address = device_->Mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, 380 DCHECK_EQ(1u, buffer.length);
373 MAP_SHARED, buffer.m.offset); 381 void* address = device_->Mmap(NULL, plane.length, PROT_READ | PROT_WRITE,
374 if (address == MAP_FAILED) { 382 MAP_SHARED, plane.m.mem_offset);
375 PLOG(ERROR) << __func__ << ": mmap() failed"; 383 input_buffer_map_[i].address[0] = address;
henryhsu 2016/12/19 07:07:27 Can we also change this like output buffer? Becaus
jcliang 2016/12/19 07:26:02 It's a known fact that the input can only be V4L2_
376 PostNotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE); 384 input_buffer_map_[i].length[0] = plane.length;
377 return false;
378 }
379 input_buffer_map_[i].address = address;
380 input_buffer_map_[i].length = buffer.length;
381 } 385 }
382 386
383 return true; 387 return true;
384 } 388 }
385 389
386 bool V4L2JpegDecodeAccelerator::CreateOutputBuffers() { 390 bool V4L2JpegDecodeAccelerator::CreateOutputBuffers() {
387 DVLOG(3) << __func__; 391 DVLOG(3) << __func__;
388 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 392 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
389 DCHECK(!output_streamon_); 393 DCHECK(!output_streamon_);
390 DCHECK(!running_jobs_.empty()); 394 DCHECK(!running_jobs_.empty());
391 linked_ptr<JobRecord> job_record = running_jobs_.front(); 395 linked_ptr<JobRecord> job_record = running_jobs_.front();
392 396
393 size_t frame_size = VideoFrame::AllocationSize( 397 size_t frame_size = VideoFrame::AllocationSize(
394 PIXEL_FORMAT_I420, job_record->out_frame->coded_size()); 398 PIXEL_FORMAT_I420, job_record->out_frame->coded_size());
395 struct v4l2_format format; 399 struct v4l2_format format;
396 memset(&format, 0, sizeof(format)); 400 memset(&format, 0, sizeof(format));
397 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 401 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
398 format.fmt.pix.width = job_record->out_frame->coded_size().width(); 402 format.fmt.pix_mp.width = job_record->out_frame->coded_size().width();
399 format.fmt.pix.height = job_record->out_frame->coded_size().height(); 403 format.fmt.pix_mp.height = job_record->out_frame->coded_size().height();
400 format.fmt.pix.sizeimage = frame_size; 404 format.fmt.pix_mp.num_planes = 1;
401 format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; 405 format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420;
402 format.fmt.pix.field = V4L2_FIELD_ANY; 406 format.fmt.pix_mp.plane_fmt[0].sizeimage = frame_size;
407 format.fmt.pix_mp.field = V4L2_FIELD_ANY;
403 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format); 408 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
404 output_buffer_pixelformat_ = format.fmt.pix.pixelformat; 409 output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat;
405 output_buffer_coded_size_.SetSize(format.fmt.pix.width, 410 output_buffer_coded_size_.SetSize(format.fmt.pix_mp.width,
406 format.fmt.pix.height); 411 format.fmt.pix_mp.height);
412 output_buffer_num_planes_ = format.fmt.pix_mp.num_planes;
407 413
408 struct v4l2_requestbuffers reqbufs; 414 struct v4l2_requestbuffers reqbufs;
409 memset(&reqbufs, 0, sizeof(reqbufs)); 415 memset(&reqbufs, 0, sizeof(reqbufs));
410 reqbufs.count = kBufferCount; 416 reqbufs.count = kBufferCount;
411 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 417 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
412 reqbufs.memory = V4L2_MEMORY_MMAP; 418 reqbufs.memory = V4L2_MEMORY_MMAP;
413 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); 419 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);
414 420
415 DCHECK(output_buffer_map_.empty()); 421 DCHECK(output_buffer_map_.empty());
416 output_buffer_map_.resize(reqbufs.count); 422 output_buffer_map_.resize(reqbufs.count);
417 423
418 VideoPixelFormat output_format = 424 VideoPixelFormat output_format =
419 V4L2Device::V4L2PixFmtToVideoPixelFormat(output_buffer_pixelformat_); 425 V4L2Device::V4L2PixFmtToVideoPixelFormat(output_buffer_pixelformat_);
420 426
421 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { 427 for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
422 free_output_buffers_.push_back(i); 428 free_output_buffers_.push_back(i);
423 429
424 struct v4l2_buffer buffer; 430 struct v4l2_buffer buffer;
431 struct v4l2_plane planes[output_buffer_num_planes_];
425 memset(&buffer, 0, sizeof(buffer)); 432 memset(&buffer, 0, sizeof(buffer));
433 memset(planes, 0, sizeof(planes));
426 buffer.index = i; 434 buffer.index = i;
427 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 435 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
428 buffer.memory = V4L2_MEMORY_MMAP; 436 buffer.memory = V4L2_MEMORY_MMAP;
437 buffer.m.planes = planes;
438 buffer.length = output_buffer_num_planes_;
429 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer); 439 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer);
430 440
431 DCHECK_GE(buffer.length, 441 DCHECK_EQ(output_buffer_num_planes_, buffer.length);
432 VideoFrame::AllocationSize( 442 for (size_t j = 0; j < buffer.length; ++j) {
433 output_format, 443 DCHECK_GE(static_cast<int64_t>(planes[j].length),
434 gfx::Size(format.fmt.pix.width, format.fmt.pix.height))); 444 VideoFrame::PlaneSize(output_format, j,
435 445 gfx::Size(format.fmt.pix_mp.width,
436 void* address = device_->Mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, 446 format.fmt.pix_mp.height))
437 MAP_SHARED, buffer.m.offset); 447 .GetArea());
438 if (address == MAP_FAILED) { 448 void* address =
439 PLOG(ERROR) << __func__ << ": mmap() failed"; 449 device_->Mmap(NULL, planes[j].length, PROT_READ | PROT_WRITE,
440 PostNotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE); 450 MAP_SHARED, planes[j].m.mem_offset);
441 return false; 451 if (address == MAP_FAILED) {
452 PLOG(ERROR) << __func__ << ": mmap() failed";
453 PostNotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE);
454 return false;
455 }
456 output_buffer_map_[i].address[j] = address;
457 output_buffer_map_[i].length[j] = planes[j].length;
442 } 458 }
443 output_buffer_map_[i].address = address;
444 output_buffer_map_[i].length = buffer.length;
445 } 459 }
446 460
447 return true; 461 return true;
448 } 462 }
449 463
450 void V4L2JpegDecodeAccelerator::DestroyInputBuffers() { 464 void V4L2JpegDecodeAccelerator::DestroyInputBuffers() {
451 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 465 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
452 466
453 free_input_buffers_.clear(); 467 free_input_buffers_.clear();
454 468
455 if (input_buffer_map_.empty()) 469 if (input_buffer_map_.empty())
456 return; 470 return;
457 471
458 if (input_streamon_) { 472 if (input_streamon_) {
459 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 473 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
460 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMOFF, &type); 474 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMOFF, &type);
461 input_streamon_ = false; 475 input_streamon_ = false;
462 } 476 }
463 477
464 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { 478 for (const auto& input_record : input_buffer_map_) {
465 BufferRecord& input_record = input_buffer_map_[i]; 479 device_->Munmap(input_record.address[0], input_record.length[0]);
466 device_->Munmap(input_record.address, input_record.length);
467 } 480 }
468 481
469 struct v4l2_requestbuffers reqbufs; 482 struct v4l2_requestbuffers reqbufs;
470 memset(&reqbufs, 0, sizeof(reqbufs)); 483 memset(&reqbufs, 0, sizeof(reqbufs));
471 reqbufs.count = 0; 484 reqbufs.count = 0;
472 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 485 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
473 reqbufs.memory = V4L2_MEMORY_MMAP; 486 reqbufs.memory = V4L2_MEMORY_MMAP;
474 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); 487 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
475 488
476 input_buffer_map_.clear(); 489 input_buffer_map_.clear();
477 } 490 }
478 491
479 void V4L2JpegDecodeAccelerator::DestroyOutputBuffers() { 492 void V4L2JpegDecodeAccelerator::DestroyOutputBuffers() {
480 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 493 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
481 494
482 free_output_buffers_.clear(); 495 free_output_buffers_.clear();
483 496
484 if (output_buffer_map_.empty()) 497 if (output_buffer_map_.empty())
485 return; 498 return;
486 499
487 if (output_streamon_) { 500 if (output_streamon_) {
488 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 501 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
489 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMOFF, &type); 502 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMOFF, &type);
490 output_streamon_ = false; 503 output_streamon_ = false;
491 } 504 }
492 505
493 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { 506 for (const auto& output_record : output_buffer_map_) {
494 BufferRecord& output_record = output_buffer_map_[i]; 507 for (size_t i = 0; i < output_buffer_num_planes_; ++i) {
495 device_->Munmap(output_record.address, output_record.length); 508 device_->Munmap(output_record.address[i], output_record.length[i]);
509 }
496 } 510 }
497 511
498 struct v4l2_requestbuffers reqbufs; 512 struct v4l2_requestbuffers reqbufs;
499 memset(&reqbufs, 0, sizeof(reqbufs)); 513 memset(&reqbufs, 0, sizeof(reqbufs));
500 reqbufs.count = 0; 514 reqbufs.count = 0;
501 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 515 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
502 reqbufs.memory = V4L2_MEMORY_MMAP; 516 reqbufs.memory = V4L2_MEMORY_MMAP;
503 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); 517 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
504 518
505 output_buffer_map_.clear(); 519 output_buffer_map_.clear();
520 output_buffer_num_planes_ = 0;
506 } 521 }
507 522
508 void V4L2JpegDecodeAccelerator::DevicePollTask() { 523 void V4L2JpegDecodeAccelerator::DevicePollTask() {
509 DCHECK(device_poll_task_runner_->BelongsToCurrentThread()); 524 DCHECK(device_poll_task_runner_->BelongsToCurrentThread());
510 525
511 bool event_pending; 526 bool event_pending;
512 if (!device_->Poll(true, &event_pending)) { 527 if (!device_->Poll(true, &event_pending)) {
513 PLOG(ERROR) << __func__ << ": Poll device error."; 528 PLOG(ERROR) << __func__ << ": Poll device error.";
514 PostNotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE); 529 PostNotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE);
515 return; 530 return;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 // If input buffers are required to re-create, do not enqueue input record 605 // If input buffers are required to re-create, do not enqueue input record
591 // until all pending frames are handled by device. 606 // until all pending frames are handled by device.
592 if (ShouldRecreateInputBuffers()) 607 if (ShouldRecreateInputBuffers())
593 break; 608 break;
594 if (!EnqueueInputRecord()) 609 if (!EnqueueInputRecord())
595 return; 610 return;
596 } 611 }
597 // Check here because we cannot STREAMON before QBUF in earlier kernel. 612 // Check here because we cannot STREAMON before QBUF in earlier kernel.
598 // (kernel version < 3.14) 613 // (kernel version < 3.14)
599 if (!input_streamon_ && InputBufferQueuedCount()) { 614 if (!input_streamon_ && InputBufferQueuedCount()) {
600 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 615 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
601 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type); 616 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type);
602 input_streamon_ = true; 617 input_streamon_ = true;
603 } 618 }
604 } 619 }
605 620
606 void V4L2JpegDecodeAccelerator::EnqueueOutput() { 621 void V4L2JpegDecodeAccelerator::EnqueueOutput() {
607 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 622 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
608 // Output record can be enqueued because the output coded sizes of the frames 623 // Output record can be enqueued because the output coded sizes of the frames
609 // currently in the pipeline are all the same. 624 // currently in the pipeline are all the same.
610 while (running_jobs_.size() > OutputBufferQueuedCount() && 625 while (running_jobs_.size() > OutputBufferQueuedCount() &&
611 !free_output_buffers_.empty()) { 626 !free_output_buffers_.empty()) {
612 if (!EnqueueOutputRecord()) 627 if (!EnqueueOutputRecord())
613 return; 628 return;
614 } 629 }
615 // Check here because we cannot STREAMON before QBUF in earlier kernel. 630 // Check here because we cannot STREAMON before QBUF in earlier kernel.
616 // (kernel version < 3.14) 631 // (kernel version < 3.14)
617 if (!output_streamon_ && OutputBufferQueuedCount()) { 632 if (!output_streamon_ && OutputBufferQueuedCount()) {
618 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 633 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
619 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type); 634 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type);
620 output_streamon_ = true; 635 output_streamon_ = true;
621 } 636 }
622 } 637 }
623 638
624 static bool CopyOutputImage(const uint32_t src_pixelformat, 639 bool V4L2JpegDecodeAccelerator::ConvertOutputImage(
625 const void* src_addr, 640 const BufferRecord& output_buffer,
626 const gfx::Size& src_coded_size, 641 const scoped_refptr<VideoFrame>& dst_frame) {
627 const scoped_refptr<VideoFrame>& dst_frame) {
628 VideoPixelFormat format =
629 V4L2Device::V4L2PixFmtToVideoPixelFormat(src_pixelformat);
630 size_t src_size = VideoFrame::AllocationSize(format, src_coded_size);
631 uint8_t* dst_y = dst_frame->data(VideoFrame::kYPlane); 642 uint8_t* dst_y = dst_frame->data(VideoFrame::kYPlane);
632 uint8_t* dst_u = dst_frame->data(VideoFrame::kUPlane); 643 uint8_t* dst_u = dst_frame->data(VideoFrame::kUPlane);
633 uint8_t* dst_v = dst_frame->data(VideoFrame::kVPlane); 644 uint8_t* dst_v = dst_frame->data(VideoFrame::kVPlane);
634 size_t dst_y_stride = dst_frame->stride(VideoFrame::kYPlane); 645 size_t dst_y_stride = dst_frame->stride(VideoFrame::kYPlane);
635 size_t dst_u_stride = dst_frame->stride(VideoFrame::kUPlane); 646 size_t dst_u_stride = dst_frame->stride(VideoFrame::kUPlane);
636 size_t dst_v_stride = dst_frame->stride(VideoFrame::kVPlane); 647 size_t dst_v_stride = dst_frame->stride(VideoFrame::kVPlane);
637 648
638 // If the source format is I420, ConvertToI420 will simply copy the frame. 649 if (output_buffer_num_planes_ == 1) {
639 if (libyuv::ConvertToI420(static_cast<uint8_t*>(const_cast<void*>(src_addr)), 650 // Use ConvertToI420 to convert all splane buffers.
640 src_size, 651 // If the source format is I420, ConvertToI420 will simply copy the frame.
641 dst_y, dst_y_stride, 652 VideoPixelFormat format =
642 dst_u, dst_u_stride, 653 V4L2Device::V4L2PixFmtToVideoPixelFormat(output_buffer_pixelformat_);
643 dst_v, dst_v_stride, 654 size_t src_size =
644 0, 0, 655 VideoFrame::AllocationSize(format, output_buffer_coded_size_);
645 src_coded_size.width(), 656 if (libyuv::ConvertToI420(
646 src_coded_size.height(), 657 static_cast<uint8_t*>(output_buffer.address[0]), src_size, dst_y,
647 dst_frame->coded_size().width(), 658 dst_y_stride, dst_u, dst_u_stride, dst_v, dst_v_stride, 0, 0,
648 dst_frame->coded_size().height(), 659 output_buffer_coded_size_.width(),
649 libyuv::kRotate0, 660 output_buffer_coded_size_.height(), dst_frame->coded_size().width(),
650 src_pixelformat)) { 661 dst_frame->coded_size().height(), libyuv::kRotate0,
651 LOG(ERROR) << "ConvertToI420 failed. Source format: " << src_pixelformat; 662 output_buffer_pixelformat_)) {
663 LOG(ERROR) << "ConvertToI420 failed. Source format: "
664 << output_buffer_pixelformat_;
665 return false;
666 }
667 } else if (output_buffer_pixelformat_ == V4L2_PIX_FMT_YUV420M ||
668 output_buffer_pixelformat_ == V4L2_PIX_FMT_YUV422M) {
669 uint8_t* src_y = static_cast<uint8_t*>(output_buffer.address[0]);
670 uint8_t* src_u = static_cast<uint8_t*>(output_buffer.address[1]);
671 uint8_t* src_v = static_cast<uint8_t*>(output_buffer.address[2]);
672 size_t src_y_stride = output_buffer_coded_size_.width();
673 size_t src_u_stride = output_buffer_coded_size_.width() / 2;
674 size_t src_v_stride = output_buffer_coded_size_.width() / 2;
675 if (output_buffer_pixelformat_ == V4L2_PIX_FMT_YUV420M) {
676 if (libyuv::I420Copy(src_y, src_y_stride, src_u, src_u_stride, src_v,
677 src_v_stride, dst_y, dst_y_stride, dst_u,
678 dst_u_stride, dst_v, dst_v_stride,
679 output_buffer_coded_size_.width(),
680 output_buffer_coded_size_.height())) {
681 LOG(ERROR) << "I420Copy failed";
682 return false;
683 }
684 } else { // output_buffer_pixelformat_ == V4L2_PIX_FMT_YUV422M
685 if (libyuv::I422ToI420(src_y, src_y_stride, src_u, src_u_stride, src_v,
686 src_v_stride, dst_y, dst_y_stride, dst_u,
687 dst_u_stride, dst_v, dst_v_stride,
688 output_buffer_coded_size_.width(),
689 output_buffer_coded_size_.height())) {
690 LOG(ERROR) << "I422ToI420 failed";
691 return false;
692 }
693 }
694 } else {
695 LOG(ERROR) << "Unsupported source buffer format: "
696 << output_buffer_pixelformat_;
652 return false; 697 return false;
653 } 698 }
654 return true; 699 return true;
655 } 700 }
656 701
657 void V4L2JpegDecodeAccelerator::Dequeue() { 702 void V4L2JpegDecodeAccelerator::Dequeue() {
658 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 703 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
704 DCHECK_GE(output_buffer_num_planes_, 0u);
659 705
660 // Dequeue completed input (VIDEO_OUTPUT) buffers, 706 // Dequeue completed input (VIDEO_OUTPUT) buffers,
661 // and recycle to the free list. 707 // and recycle to the free list.
662 struct v4l2_buffer dqbuf; 708 struct v4l2_buffer dqbuf;
709 struct v4l2_plane input_plane;
663 while (InputBufferQueuedCount() > 0) { 710 while (InputBufferQueuedCount() > 0) {
664 DCHECK(input_streamon_); 711 DCHECK(input_streamon_);
665 memset(&dqbuf, 0, sizeof(dqbuf)); 712 memset(&dqbuf, 0, sizeof(dqbuf));
666 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 713 memset(&input_plane, 0, sizeof(input_plane));
714 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
667 dqbuf.memory = V4L2_MEMORY_MMAP; 715 dqbuf.memory = V4L2_MEMORY_MMAP;
716 dqbuf.length = kMaxInputPlanes;
717 dqbuf.m.planes = &input_plane;
668 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { 718 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
669 if (errno == EAGAIN) { 719 if (errno == EAGAIN) {
670 // EAGAIN if we're just out of buffers to dequeue. 720 // EAGAIN if we're just out of buffers to dequeue.
671 break; 721 break;
672 } 722 }
673 PLOG(ERROR) << "ioctl() failed: input buffer VIDIOC_DQBUF failed."; 723 PLOG(ERROR) << "ioctl() failed: input buffer VIDIOC_DQBUF failed.";
674 PostNotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE); 724 PostNotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE);
675 return; 725 return;
676 } 726 }
677 BufferRecord& input_record = input_buffer_map_[dqbuf.index]; 727 BufferRecord& input_record = input_buffer_map_[dqbuf.index];
678 DCHECK(input_record.at_device); 728 DCHECK(input_record.at_device);
679 input_record.at_device = false; 729 input_record.at_device = false;
680 free_input_buffers_.push_back(dqbuf.index); 730 free_input_buffers_.push_back(dqbuf.index);
681 731
682 if (dqbuf.flags & V4L2_BUF_FLAG_ERROR) { 732 if (dqbuf.flags & V4L2_BUF_FLAG_ERROR) {
683 DVLOG(1) << "Dequeue input buffer error."; 733 DVLOG(1) << "Dequeue input buffer error.";
684 PostNotifyError(kInvalidBitstreamBufferId, UNSUPPORTED_JPEG); 734 PostNotifyError(kInvalidBitstreamBufferId, UNSUPPORTED_JPEG);
685 running_jobs_.pop(); 735 running_jobs_.pop();
686 } 736 }
687 } 737 }
688 738
689 // Dequeue completed output (VIDEO_CAPTURE) buffers, recycle to the free list. 739 // Dequeue completed output (VIDEO_CAPTURE) buffers, recycle to the free list.
690 // Return the finished buffer to the client via the job ready callback. 740 // Return the finished buffer to the client via the job ready callback.
691 // If dequeued input buffer has an error, the error frame has removed from 741 // If dequeued input buffer has an error, the error frame has removed from
692 // |running_jobs_|. We only have to dequeue output buffer when we actually 742 // |running_jobs_|. We only have to dequeue output buffer when we actually
693 // have pending frames in |running_jobs_| and also enqueued output buffers. 743 // have pending frames in |running_jobs_| and also enqueued output buffers.
744 struct v4l2_plane output_planes[output_buffer_num_planes_];
694 while (!running_jobs_.empty() && OutputBufferQueuedCount() > 0) { 745 while (!running_jobs_.empty() && OutputBufferQueuedCount() > 0) {
695 DCHECK(output_streamon_); 746 DCHECK(output_streamon_);
696 memset(&dqbuf, 0, sizeof(dqbuf)); 747 memset(&dqbuf, 0, sizeof(dqbuf));
697 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 748 memset(output_planes, 0, sizeof(output_planes));
749 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
698 // From experiments, using MMAP and memory copy is still faster than 750 // From experiments, using MMAP and memory copy is still faster than
699 // USERPTR. Also, client doesn't need to consider the buffer alignment and 751 // USERPTR. Also, client doesn't need to consider the buffer alignment and
700 // JpegDecodeAccelerator API will be simpler. 752 // JpegDecodeAccelerator API will be simpler.
701 dqbuf.memory = V4L2_MEMORY_MMAP; 753 dqbuf.memory = V4L2_MEMORY_MMAP;
754 dqbuf.length = output_buffer_num_planes_;
755 dqbuf.m.planes = output_planes;
702 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { 756 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
703 if (errno == EAGAIN) { 757 if (errno == EAGAIN) {
704 // EAGAIN if we're just out of buffers to dequeue. 758 // EAGAIN if we're just out of buffers to dequeue.
705 break; 759 break;
706 } 760 }
707 PLOG(ERROR) << "ioctl() failed: output buffer VIDIOC_DQBUF failed."; 761 PLOG(ERROR) << "ioctl() failed: output buffer VIDIOC_DQBUF failed.";
708 PostNotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE); 762 PostNotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE);
709 return; 763 return;
710 } 764 }
711 BufferRecord& output_record = output_buffer_map_[dqbuf.index]; 765 BufferRecord& output_record = output_buffer_map_[dqbuf.index];
712 DCHECK(output_record.at_device); 766 DCHECK(output_record.at_device);
713 output_record.at_device = false; 767 output_record.at_device = false;
714 free_output_buffers_.push_back(dqbuf.index); 768 free_output_buffers_.push_back(dqbuf.index);
715 769
716 // Jobs are always processed in FIFO order. 770 // Jobs are always processed in FIFO order.
717 linked_ptr<JobRecord> job_record = running_jobs_.front(); 771 linked_ptr<JobRecord> job_record = running_jobs_.front();
718 running_jobs_.pop(); 772 running_jobs_.pop();
719 773
720 if (dqbuf.flags & V4L2_BUF_FLAG_ERROR) { 774 if (dqbuf.flags & V4L2_BUF_FLAG_ERROR) {
721 DVLOG(1) << "Dequeue output buffer error."; 775 DVLOG(1) << "Dequeue output buffer error.";
722 PostNotifyError(kInvalidBitstreamBufferId, UNSUPPORTED_JPEG); 776 PostNotifyError(kInvalidBitstreamBufferId, UNSUPPORTED_JPEG);
723 } else { 777 } else {
724 // Copy the decoded data from output buffer to the buffer provided by the 778 // Copy the decoded data from output buffer to the buffer provided by the
725 // client. Do format conversion when output format is not 779 // client. Do format conversion when output format is not
726 // V4L2_PIX_FMT_YUV420. 780 // V4L2_PIX_FMT_YUV420.
727 if (!CopyOutputImage(output_buffer_pixelformat_, output_record.address, 781 if (!ConvertOutputImage(output_record, job_record->out_frame)) {
728 output_buffer_coded_size_, job_record->out_frame)) {
729 PostNotifyError(job_record->bitstream_buffer_id, PLATFORM_FAILURE); 782 PostNotifyError(job_record->bitstream_buffer_id, PLATFORM_FAILURE);
730 return; 783 return;
731 } 784 }
732
733 DVLOG(3) << "Decoding finished, returning bitstream buffer, id=" 785 DVLOG(3) << "Decoding finished, returning bitstream buffer, id="
734 << job_record->bitstream_buffer_id; 786 << job_record->bitstream_buffer_id;
735 787
736 child_task_runner_->PostTask( 788 child_task_runner_->PostTask(
737 FROM_HERE, base::Bind(&V4L2JpegDecodeAccelerator::VideoFrameReady, 789 FROM_HERE, base::Bind(&V4L2JpegDecodeAccelerator::VideoFrameReady,
738 weak_ptr_, job_record->bitstream_buffer_id)); 790 weak_ptr_, job_record->bitstream_buffer_id));
739 } 791 }
740 } 792 }
741 } 793 }
742 794
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 879
828 // Enqueue an input (VIDEO_OUTPUT) buffer for an input video frame. 880 // Enqueue an input (VIDEO_OUTPUT) buffer for an input video frame.
829 linked_ptr<JobRecord> job_record = input_jobs_.front(); 881 linked_ptr<JobRecord> job_record = input_jobs_.front();
830 input_jobs_.pop(); 882 input_jobs_.pop();
831 const int index = free_input_buffers_.back(); 883 const int index = free_input_buffers_.back();
832 BufferRecord& input_record = input_buffer_map_[index]; 884 BufferRecord& input_record = input_buffer_map_[index];
833 DCHECK(!input_record.at_device); 885 DCHECK(!input_record.at_device);
834 886
835 // It will add default huffman segment if it's missing. 887 // It will add default huffman segment if it's missing.
836 if (!AddHuffmanTable(job_record->shm.memory(), job_record->shm.size(), 888 if (!AddHuffmanTable(job_record->shm.memory(), job_record->shm.size(),
837 input_record.address, input_record.length)) { 889 input_record.address[0], input_record.length[0])) {
henryhsu 2016/12/19 07:07:27 This also assume the kMaxInputPlanes is 1. I'm sta
jcliang 2016/12/19 07:26:02 Sure. Let's add a static_assert.
838 PostNotifyError(job_record->bitstream_buffer_id, PARSE_JPEG_FAILED); 890 PostNotifyError(job_record->bitstream_buffer_id, PARSE_JPEG_FAILED);
839 return false; 891 return false;
840 } 892 }
841 893
842 struct v4l2_buffer qbuf; 894 struct v4l2_buffer qbuf;
895 struct v4l2_plane plane;
843 memset(&qbuf, 0, sizeof(qbuf)); 896 memset(&qbuf, 0, sizeof(qbuf));
897 memset(&plane, 0, sizeof(plane));
844 qbuf.index = index; 898 qbuf.index = index;
845 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 899 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
846 qbuf.memory = V4L2_MEMORY_MMAP; 900 qbuf.memory = V4L2_MEMORY_MMAP;
901 qbuf.length = kMaxInputPlanes;
902 plane.bytesused = input_record.length[0];
903 qbuf.m.planes = &plane;
847 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf); 904 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
848 input_record.at_device = true; 905 input_record.at_device = true;
849 running_jobs_.push(job_record); 906 running_jobs_.push(job_record);
850 free_input_buffers_.pop_back(); 907 free_input_buffers_.pop_back();
851 908
852 DVLOG(3) << __func__ 909 DVLOG(3) << __func__
853 << ": enqueued frame id=" << job_record->bitstream_buffer_id 910 << ": enqueued frame id=" << job_record->bitstream_buffer_id
854 << " to device."; 911 << " to device.";
855 return true; 912 return true;
856 } 913 }
857 914
858 bool V4L2JpegDecodeAccelerator::EnqueueOutputRecord() { 915 bool V4L2JpegDecodeAccelerator::EnqueueOutputRecord() {
859 DCHECK(!free_output_buffers_.empty()); 916 DCHECK(!free_output_buffers_.empty());
917 DCHECK_GE(output_buffer_num_planes_, 0u);
860 918
861 // Enqueue an output (VIDEO_CAPTURE) buffer. 919 // Enqueue an output (VIDEO_CAPTURE) buffer.
862 const int index = free_output_buffers_.back(); 920 const int index = free_output_buffers_.back();
863 BufferRecord& output_record = output_buffer_map_[index]; 921 BufferRecord& output_record = output_buffer_map_[index];
864 DCHECK(!output_record.at_device); 922 DCHECK(!output_record.at_device);
865 struct v4l2_buffer qbuf; 923 struct v4l2_buffer qbuf;
924 struct v4l2_plane planes[output_buffer_num_planes_];
866 memset(&qbuf, 0, sizeof(qbuf)); 925 memset(&qbuf, 0, sizeof(qbuf));
926 memset(&planes, 0, sizeof(planes));
867 qbuf.index = index; 927 qbuf.index = index;
868 qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 928 qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
869 qbuf.memory = V4L2_MEMORY_MMAP; 929 qbuf.memory = V4L2_MEMORY_MMAP;
930 qbuf.length = output_buffer_num_planes_;
931 qbuf.m.planes = planes;
870 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf); 932 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
871 output_record.at_device = true; 933 output_record.at_device = true;
872 free_output_buffers_.pop_back(); 934 free_output_buffers_.pop_back();
873 return true; 935 return true;
874 } 936 }
875 937
876 void V4L2JpegDecodeAccelerator::StartDevicePoll() { 938 void V4L2JpegDecodeAccelerator::StartDevicePoll() {
877 DVLOG(3) << __func__ << ": starting device poll"; 939 DVLOG(3) << __func__ << ": starting device poll";
878 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); 940 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
879 DCHECK(!device_poll_thread_.IsRunning()); 941 DCHECK(!device_poll_thread_.IsRunning());
(...skipping 18 matching lines...) Expand all
898 device_poll_thread_.Stop(); 960 device_poll_thread_.Stop();
899 961
900 // Clear the interrupt now, to be sure. 962 // Clear the interrupt now, to be sure.
901 if (!device_->ClearDevicePollInterrupt()) 963 if (!device_->ClearDevicePollInterrupt())
902 return false; 964 return false;
903 965
904 return true; 966 return true;
905 } 967 }
906 968
907 } // namespace media 969 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/v4l2_jpeg_decode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698