Home | History | Annotate | Download | only in media
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <fcntl.h>
      6 #include <linux/videodev2.h>
      7 #include <poll.h>
      8 #include <sys/eventfd.h>
      9 #include <sys/ioctl.h>
     10 #include <sys/mman.h>
     11 
     12 #include "base/callback.h"
     13 #include "base/command_line.h"
     14 #include "base/debug/trace_event.h"
     15 #include "base/message_loop/message_loop_proxy.h"
     16 #include "base/numerics/safe_conversions.h"
     17 #include "content/common/gpu/media/v4l2_video_encode_accelerator.h"
     18 #include "content/public/common/content_switches.h"
     19 #include "media/base/bitstream_buffer.h"
     20 
     21 #define NOTIFY_ERROR(x)                            \
     22   do {                                             \
     23     SetEncoderState(kError);                       \
     24     DLOG(ERROR) << "calling NotifyError(): " << x; \
     25     NotifyError(x);                                \
     26   } while (0)
     27 
     28 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value)              \
     29   do {                                                             \
     30     if (device_->Ioctl(type, arg) != 0) {                          \
     31       DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
     32       NOTIFY_ERROR(kPlatformFailureError);                         \
     33       return value;                                                \
     34     }                                                              \
     35   } while (0)
     36 
     37 #define IOCTL_OR_ERROR_RETURN(type, arg) \
     38   IOCTL_OR_ERROR_RETURN_VALUE(type, arg, ((void)0))
     39 
     40 #define IOCTL_OR_ERROR_RETURN_FALSE(type, arg) \
     41   IOCTL_OR_ERROR_RETURN_VALUE(type, arg, false)
     42 
     43 #define IOCTL_OR_LOG_ERROR(type, arg)                              \
     44   do {                                                             \
     45     if (device_->Ioctl(type, arg) != 0)                            \
     46       DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
     47   } while (0)
     48 
     49 namespace content {
     50 
     51 struct V4L2VideoEncodeAccelerator::BitstreamBufferRef {
     52   BitstreamBufferRef(int32 id, scoped_ptr<base::SharedMemory> shm, size_t size)
     53       : id(id), shm(shm.Pass()), size(size) {}
     54   const int32 id;
     55   const scoped_ptr<base::SharedMemory> shm;
     56   const size_t size;
     57 };
     58 
     59 V4L2VideoEncodeAccelerator::InputRecord::InputRecord() : at_device(false) {
     60 }
     61 
     62 V4L2VideoEncodeAccelerator::OutputRecord::OutputRecord()
     63     : at_device(false), address(NULL), length(0) {
     64 }
     65 
     66 V4L2VideoEncodeAccelerator::V4L2VideoEncodeAccelerator(
     67     scoped_ptr<V4L2Device> device)
     68     : child_message_loop_proxy_(base::MessageLoopProxy::current()),
     69       weak_this_ptr_factory_(this),
     70       weak_this_(weak_this_ptr_factory_.GetWeakPtr()),
     71       output_buffer_byte_size_(0),
     72       device_input_format_(media::VideoFrame::UNKNOWN),
     73       input_planes_count_(0),
     74       output_format_fourcc_(0),
     75       encoder_thread_("V4L2EncoderThread"),
     76       encoder_state_(kUninitialized),
     77       stream_header_size_(0),
     78       device_(device.Pass()),
     79       input_streamon_(false),
     80       input_buffer_queued_count_(0),
     81       input_memory_type_(V4L2_MEMORY_USERPTR),
     82       output_streamon_(false),
     83       output_buffer_queued_count_(0),
     84       device_poll_thread_("V4L2EncoderDevicePollThread") {
     85 }
     86 
     87 V4L2VideoEncodeAccelerator::~V4L2VideoEncodeAccelerator() {
     88   DCHECK(!encoder_thread_.IsRunning());
     89   DCHECK(!device_poll_thread_.IsRunning());
     90   DVLOG(4) << __func__;
     91 
     92   DestroyInputBuffers();
     93   DestroyOutputBuffers();
     94 }
     95 
     96 bool V4L2VideoEncodeAccelerator::Initialize(
     97     media::VideoFrame::Format input_format,
     98     const gfx::Size& input_visible_size,
     99     media::VideoCodecProfile output_profile,
    100     uint32 initial_bitrate,
    101     Client* client) {
    102   DVLOG(3) << __func__ << ": input_format="
    103            << media::VideoFrame::FormatToString(input_format)
    104            << ", input_visible_size=" << input_visible_size.ToString()
    105            << ", output_profile=" << output_profile
    106            << ", initial_bitrate=" << initial_bitrate;
    107 
    108   visible_size_ = input_visible_size;
    109 
    110   client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client));
    111   client_ = client_ptr_factory_->GetWeakPtr();
    112 
    113   DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
    114   DCHECK_EQ(encoder_state_, kUninitialized);
    115 
    116   struct v4l2_capability caps;
    117   memset(&caps, 0, sizeof(caps));
    118   const __u32 kCapsRequired = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
    119                               V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING;
    120   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps);
    121   if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
    122     DLOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP: "
    123                    "caps check failed: 0x" << std::hex << caps.capabilities;
    124     return false;
    125   }
    126 
    127   if (!SetFormats(input_format, output_profile)) {
    128     DLOG(ERROR) << "Failed setting up formats";
    129     return false;
    130   }
    131 
    132   if (input_format != device_input_format_) {
    133     DVLOG(1) << "Input format not supported by the HW, will convert to "
    134              << media::VideoFrame::FormatToString(device_input_format_);
    135 
    136     scoped_ptr<V4L2Device> device =
    137         V4L2Device::Create(V4L2Device::kImageProcessor);
    138     image_processor_.reset(new V4L2ImageProcessor(device.Pass()));
    139 
    140     // Convert from input_format to device_input_format_, keeping the size
    141     // at visible_size_ and requiring the output buffers to be of at least
    142     // input_allocated_size_.
    143     if (!image_processor_->Initialize(
    144             input_format,
    145             device_input_format_,
    146             visible_size_,
    147             visible_size_,
    148             input_allocated_size_,
    149             base::Bind(&V4L2VideoEncodeAccelerator::ImageProcessorError,
    150                        weak_this_))) {
    151       DLOG(ERROR) << "Failed initializing image processor";
    152       return false;
    153     }
    154   }
    155 
    156   if (!InitControls())
    157     return false;
    158 
    159   if (!CreateOutputBuffers())
    160     return false;
    161 
    162   if (!encoder_thread_.Start()) {
    163     DLOG(ERROR) << "Initialize(): encoder thread failed to start";
    164     return false;
    165   }
    166 
    167   RequestEncodingParametersChange(initial_bitrate, kInitialFramerate);
    168 
    169   SetEncoderState(kInitialized);
    170 
    171   child_message_loop_proxy_->PostTask(
    172       FROM_HERE,
    173       base::Bind(&Client::RequireBitstreamBuffers,
    174                  client_,
    175                  kInputBufferCount,
    176                  image_processor_.get() ?
    177                      image_processor_->input_allocated_size() :
    178                      input_allocated_size_,
    179                  output_buffer_byte_size_));
    180   return true;
    181 }
    182 
    183 void V4L2VideoEncodeAccelerator::ImageProcessorError() {
    184   DVLOG(1) << "Image processor error";
    185   NOTIFY_ERROR(kPlatformFailureError);
    186 }
    187 
    188 void V4L2VideoEncodeAccelerator::Encode(
    189     const scoped_refptr<media::VideoFrame>& frame,
    190     bool force_keyframe) {
    191   DVLOG(3) << "Encode(): force_keyframe=" << force_keyframe;
    192   DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
    193 
    194   if (image_processor_) {
    195     image_processor_->Process(
    196         frame,
    197         base::Bind(&V4L2VideoEncodeAccelerator::FrameProcessed,
    198                    weak_this_,
    199                    force_keyframe));
    200   } else {
    201     encoder_thread_.message_loop()->PostTask(
    202         FROM_HERE,
    203         base::Bind(&V4L2VideoEncodeAccelerator::EncodeTask,
    204                    base::Unretained(this),
    205                    frame,
    206                    force_keyframe));
    207   }
    208 }
    209 
    210 void V4L2VideoEncodeAccelerator::UseOutputBitstreamBuffer(
    211     const media::BitstreamBuffer& buffer) {
    212   DVLOG(3) << "UseOutputBitstreamBuffer(): id=" << buffer.id();
    213   DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
    214 
    215   if (buffer.size() < output_buffer_byte_size_) {
    216     NOTIFY_ERROR(kInvalidArgumentError);
    217     return;
    218   }
    219 
    220   scoped_ptr<base::SharedMemory> shm(
    221       new base::SharedMemory(buffer.handle(), false));
    222   if (!shm->Map(buffer.size())) {
    223     NOTIFY_ERROR(kPlatformFailureError);
    224     return;
    225   }
    226 
    227   scoped_ptr<BitstreamBufferRef> buffer_ref(
    228       new BitstreamBufferRef(buffer.id(), shm.Pass(), buffer.size()));
    229   encoder_thread_.message_loop()->PostTask(
    230       FROM_HERE,
    231       base::Bind(&V4L2VideoEncodeAccelerator::UseOutputBitstreamBufferTask,
    232                  base::Unretained(this),
    233                  base::Passed(&buffer_ref)));
    234 }
    235 
    236 void V4L2VideoEncodeAccelerator::RequestEncodingParametersChange(
    237     uint32 bitrate,
    238     uint32 framerate) {
    239   DVLOG(3) << "RequestEncodingParametersChange(): bitrate=" << bitrate
    240            << ", framerate=" << framerate;
    241   DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
    242 
    243   encoder_thread_.message_loop()->PostTask(
    244       FROM_HERE,
    245       base::Bind(
    246           &V4L2VideoEncodeAccelerator::RequestEncodingParametersChangeTask,
    247           base::Unretained(this),
    248           bitrate,
    249           framerate));
    250 }
    251 
    252 void V4L2VideoEncodeAccelerator::Destroy() {
    253   DVLOG(3) << "Destroy()";
    254   DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
    255 
    256   // We're destroying; cancel all callbacks.
    257   client_ptr_factory_.reset();
    258 
    259   if (image_processor_.get())
    260     image_processor_.release()->Destroy();
    261 
    262   // If the encoder thread is running, destroy using posted task.
    263   if (encoder_thread_.IsRunning()) {
    264     encoder_thread_.message_loop()->PostTask(
    265         FROM_HERE,
    266         base::Bind(&V4L2VideoEncodeAccelerator::DestroyTask,
    267                    base::Unretained(this)));
    268     // DestroyTask() will put the encoder into kError state and cause all tasks
    269     // to no-op.
    270     encoder_thread_.Stop();
    271   } else {
    272     // Otherwise, call the destroy task directly.
    273     DestroyTask();
    274   }
    275 
    276   // Set to kError state just in case.
    277   SetEncoderState(kError);
    278 
    279   delete this;
    280 }
    281 
    282 // static
    283 std::vector<media::VideoEncodeAccelerator::SupportedProfile>
    284 V4L2VideoEncodeAccelerator::GetSupportedProfiles() {
    285   std::vector<SupportedProfile> profiles;
    286   SupportedProfile profile;
    287 
    288   const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
    289   if (cmd_line->HasSwitch(switches::kEnableWebRtcHWVp8Encoding)) {
    290     profile.profile = media::VP8PROFILE_MAIN;
    291     profile.max_resolution.SetSize(1920, 1088);
    292     profile.max_framerate.numerator = 30;
    293     profile.max_framerate.denominator = 1;
    294     profiles.push_back(profile);
    295   } else {
    296     profile.profile = media::H264PROFILE_MAIN;
    297     profile.max_resolution.SetSize(1920, 1088);
    298     profile.max_framerate.numerator = 30;
    299     profile.max_framerate.denominator = 1;
    300     profiles.push_back(profile);
    301   }
    302 
    303   return profiles;
    304 }
    305 
    306 void V4L2VideoEncodeAccelerator::FrameProcessed(
    307     bool force_keyframe,
    308     const scoped_refptr<media::VideoFrame>& frame) {
    309   DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
    310   DVLOG(3) << "FrameProcessed(): force_keyframe=" << force_keyframe;
    311 
    312   encoder_thread_.message_loop()->PostTask(
    313       FROM_HERE,
    314       base::Bind(&V4L2VideoEncodeAccelerator::EncodeTask,
    315                  base::Unretained(this),
    316                  frame,
    317                  force_keyframe));
    318 }
    319 
    320 void V4L2VideoEncodeAccelerator::EncodeTask(
    321     const scoped_refptr<media::VideoFrame>& frame,
    322     bool force_keyframe) {
    323   DVLOG(3) << "EncodeTask(): force_keyframe=" << force_keyframe;
    324   DCHECK_EQ(encoder_thread_.message_loop(), base::MessageLoop::current());
    325   DCHECK_NE(encoder_state_, kUninitialized);
    326 
    327   if (encoder_state_ == kError) {
    328     DVLOG(2) << "EncodeTask(): early out: kError state";
    329     return;
    330   }
    331 
    332   encoder_input_queue_.push_back(frame);
    333   Enqueue();
    334 
    335   if (force_keyframe) {
    336     // TODO(posciak): this presently makes for slightly imprecise encoding
    337     // parameters updates.  To precisely align the parameter updates with the
    338     // incoming input frame, we should queue the parameters together with the
    339     // frame onto encoder_input_queue_ and apply them when the input is about
    340     // to be queued to the codec.
    341     struct v4l2_ext_control ctrls[1];
    342     struct v4l2_ext_controls control;
    343     memset(&ctrls, 0, sizeof(ctrls));
    344     memset(&control, 0, sizeof(control));
    345     ctrls[0].id = V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE;
    346     ctrls[0].value = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME;
    347     control.ctrl_class = V4L2_CTRL_CLASS_MPEG;
    348     control.count = 1;
    349     control.controls = ctrls;
    350     IOCTL_OR_ERROR_RETURN(VIDIOC_S_EXT_CTRLS, &control);
    351   }
    352 }
    353 
    354 void V4L2VideoEncodeAccelerator::UseOutputBitstreamBufferTask(
    355     scoped_ptr<BitstreamBufferRef> buffer_ref) {
    356   DVLOG(3) << "UseOutputBitstreamBufferTask(): id=" << buffer_ref->id;
    357   DCHECK_EQ(encoder_thread_.message_loop(), base::MessageLoop::current());
    358 
    359   encoder_output_queue_.push_back(
    360       linked_ptr<BitstreamBufferRef>(buffer_ref.release()));
    361   Enqueue();
    362 
    363   if (encoder_state_ == kInitialized) {
    364     // Finish setting up our OUTPUT queue.  See: Initialize().
    365     // VIDIOC_REQBUFS on OUTPUT queue.
    366     if (!CreateInputBuffers())
    367       return;
    368     if (!StartDevicePoll())
    369       return;
    370     encoder_state_ = kEncoding;
    371   }
    372 }
    373 
    374 void V4L2VideoEncodeAccelerator::DestroyTask() {
    375   DVLOG(3) << "DestroyTask()";
    376 
    377   // DestroyTask() should run regardless of encoder_state_.
    378 
    379   // Stop streaming and the device_poll_thread_.
    380   StopDevicePoll();
    381 
    382   // Set our state to kError, and early-out all tasks.
    383   encoder_state_ = kError;
    384 }
    385 
    386 void V4L2VideoEncodeAccelerator::ServiceDeviceTask() {
    387   DVLOG(3) << "ServiceDeviceTask()";
    388   DCHECK_EQ(encoder_thread_.message_loop(), base::MessageLoop::current());
    389   DCHECK_NE(encoder_state_, kUninitialized);
    390   DCHECK_NE(encoder_state_, kInitialized);
    391 
    392   if (encoder_state_ == kError) {
    393     DVLOG(2) << "ServiceDeviceTask(): early out: kError state";
    394     return;
    395   }
    396 
    397   Dequeue();
    398   Enqueue();
    399 
    400   // Clear the interrupt fd.
    401   if (!device_->ClearDevicePollInterrupt())
    402     return;
    403 
    404   // Device can be polled as soon as either input or output buffers are queued.
    405   bool poll_device =
    406       (input_buffer_queued_count_ + output_buffer_queued_count_ > 0);
    407 
    408   // ServiceDeviceTask() should only ever be scheduled from DevicePollTask(),
    409   // so either:
    410   // * device_poll_thread_ is running normally
    411   // * device_poll_thread_ scheduled us, but then a DestroyTask() shut it down,
    412   //   in which case we're in kError state, and we should have early-outed
    413   //   already.
    414   DCHECK(device_poll_thread_.message_loop());
    415   // Queue the DevicePollTask() now.
    416   device_poll_thread_.message_loop()->PostTask(
    417       FROM_HERE,
    418       base::Bind(&V4L2VideoEncodeAccelerator::DevicePollTask,
    419                  base::Unretained(this),
    420                  poll_device));
    421 
    422   DVLOG(2) << __func__ << ": buffer counts: ENC["
    423            << encoder_input_queue_.size() << "] => DEVICE["
    424            << free_input_buffers_.size() << "+"
    425            << input_buffer_queued_count_ << "/"
    426            << input_buffer_map_.size() << "->"
    427            << free_output_buffers_.size() << "+"
    428            << output_buffer_queued_count_ << "/"
    429            << output_buffer_map_.size() << "] => OUT["
    430            << encoder_output_queue_.size() << "]";
    431 }
    432 
    433 void V4L2VideoEncodeAccelerator::Enqueue() {
    434   DCHECK_EQ(encoder_thread_.message_loop(), base::MessageLoop::current());
    435 
    436   DVLOG(3) << "Enqueue() "
    437            << "free_input_buffers: " << free_input_buffers_.size()
    438            << "input_queue: " << encoder_input_queue_.size();
    439 
    440   // Enqueue all the inputs we can.
    441   const int old_inputs_queued = input_buffer_queued_count_;
    442   // while (!ready_input_buffers_.empty()) {
    443   while (!encoder_input_queue_.empty() && !free_input_buffers_.empty()) {
    444     if (!EnqueueInputRecord())
    445       return;
    446   }
    447   if (old_inputs_queued == 0 && input_buffer_queued_count_ != 0) {
    448     // We just started up a previously empty queue.
    449     // Queue state changed; signal interrupt.
    450     if (!device_->SetDevicePollInterrupt())
    451       return;
    452     // Start VIDIOC_STREAMON if we haven't yet.
    453     if (!input_streamon_) {
    454       __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    455       IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type);
    456       input_streamon_ = true;
    457     }
    458   }
    459 
    460   // Enqueue all the outputs we can.
    461   const int old_outputs_queued = output_buffer_queued_count_;
    462   while (!free_output_buffers_.empty() && !encoder_output_queue_.empty()) {
    463     if (!EnqueueOutputRecord())
    464       return;
    465   }
    466   if (old_outputs_queued == 0 && output_buffer_queued_count_ != 0) {
    467     // We just started up a previously empty queue.
    468     // Queue state changed; signal interrupt.
    469     if (!device_->SetDevicePollInterrupt())
    470       return;
    471     // Start VIDIOC_STREAMON if we haven't yet.
    472     if (!output_streamon_) {
    473       __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    474       IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type);
    475       output_streamon_ = true;
    476     }
    477   }
    478 }
    479 
    480 void V4L2VideoEncodeAccelerator::Dequeue() {
    481   DVLOG(3) << "Dequeue()";
    482   DCHECK_EQ(encoder_thread_.message_loop(), base::MessageLoop::current());
    483 
    484   // Dequeue completed input (VIDEO_OUTPUT) buffers, and recycle to the free
    485   // list.
    486   struct v4l2_buffer dqbuf;
    487   struct v4l2_plane planes[VIDEO_MAX_PLANES];
    488   while (input_buffer_queued_count_ > 0) {
    489     DVLOG(4) << "inputs queued: " << input_buffer_queued_count_;
    490     DCHECK(input_streamon_);
    491     memset(&dqbuf, 0, sizeof(dqbuf));
    492     memset(&planes, 0, sizeof(planes));
    493     dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    494     dqbuf.memory = V4L2_MEMORY_MMAP;
    495     dqbuf.m.planes = planes;
    496     dqbuf.length = input_planes_count_;
    497     if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
    498       if (errno == EAGAIN) {
    499         // EAGAIN if we're just out of buffers to dequeue.
    500         break;
    501       }
    502       DPLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF";
    503       NOTIFY_ERROR(kPlatformFailureError);
    504       return;
    505     }
    506     InputRecord& input_record = input_buffer_map_[dqbuf.index];
    507     DCHECK(input_record.at_device);
    508     input_record.at_device = false;
    509 
    510     input_record.frame = NULL;
    511     free_input_buffers_.push_back(dqbuf.index);
    512     input_buffer_queued_count_--;
    513   }
    514 
    515   // Dequeue completed output (VIDEO_CAPTURE) buffers, and recycle to the
    516   // free list.  Notify the client that an output buffer is complete.
    517   while (output_buffer_queued_count_ > 0) {
    518     DCHECK(output_streamon_);
    519     memset(&dqbuf, 0, sizeof(dqbuf));
    520     memset(planes, 0, sizeof(planes));
    521     dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    522     dqbuf.memory = V4L2_MEMORY_MMAP;
    523     dqbuf.m.planes = planes;
    524     dqbuf.length = 1;
    525     if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
    526       if (errno == EAGAIN) {
    527         // EAGAIN if we're just out of buffers to dequeue.
    528         break;
    529       }
    530       DPLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF";
    531       NOTIFY_ERROR(kPlatformFailureError);
    532       return;
    533     }
    534     const bool key_frame = ((dqbuf.flags & V4L2_BUF_FLAG_KEYFRAME) != 0);
    535     OutputRecord& output_record = output_buffer_map_[dqbuf.index];
    536     DCHECK(output_record.at_device);
    537     DCHECK(output_record.buffer_ref.get());
    538 
    539     void* output_data = output_record.address;
    540     size_t output_size = dqbuf.m.planes[0].bytesused;
    541     // This shouldn't happen, but just in case. We should be able to recover
    542     // after next keyframe after showing some corruption.
    543     DCHECK_LE(output_size, output_buffer_byte_size_);
    544     if (output_size > output_buffer_byte_size_)
    545       output_size = output_buffer_byte_size_;
    546     uint8* target_data =
    547         reinterpret_cast<uint8*>(output_record.buffer_ref->shm->memory());
    548     if (output_format_fourcc_ == V4L2_PIX_FMT_H264) {
    549       if (stream_header_size_ == 0) {
    550         // Assume that the first buffer dequeued is the stream header.
    551         stream_header_size_ = output_size;
    552         stream_header_.reset(new uint8[stream_header_size_]);
    553         memcpy(stream_header_.get(), output_data, stream_header_size_);
    554       }
    555       if (key_frame &&
    556           output_buffer_byte_size_ - stream_header_size_ >= output_size) {
    557         // Insert stream header before every keyframe.
    558         memcpy(target_data, stream_header_.get(), stream_header_size_);
    559         memcpy(target_data + stream_header_size_, output_data, output_size);
    560         output_size += stream_header_size_;
    561       } else {
    562         memcpy(target_data, output_data, output_size);
    563       }
    564     } else {
    565       memcpy(target_data, output_data, output_size);
    566     }
    567 
    568     DVLOG(3) << "Dequeue(): returning "
    569                 "bitstream_buffer_id=" << output_record.buffer_ref->id
    570              << ", size=" << output_size << ", key_frame=" << key_frame;
    571     child_message_loop_proxy_->PostTask(
    572         FROM_HERE,
    573         base::Bind(&Client::BitstreamBufferReady,
    574                    client_,
    575                    output_record.buffer_ref->id,
    576                    output_size,
    577                    key_frame));
    578     output_record.at_device = false;
    579     output_record.buffer_ref.reset();
    580     free_output_buffers_.push_back(dqbuf.index);
    581     output_buffer_queued_count_--;
    582   }
    583 }
    584 
    585 bool V4L2VideoEncodeAccelerator::EnqueueInputRecord() {
    586   DVLOG(3) << "EnqueueInputRecord()";
    587   DCHECK(!free_input_buffers_.empty());
    588   DCHECK(!encoder_input_queue_.empty());
    589 
    590   // Enqueue an input (VIDEO_OUTPUT) buffer.
    591   scoped_refptr<media::VideoFrame> frame = encoder_input_queue_.front();
    592   const int index = free_input_buffers_.back();
    593   InputRecord& input_record = input_buffer_map_[index];
    594   DCHECK(!input_record.at_device);
    595   struct v4l2_buffer qbuf;
    596   struct v4l2_plane qbuf_planes[VIDEO_MAX_PLANES];
    597   memset(&qbuf, 0, sizeof(qbuf));
    598   memset(qbuf_planes, 0, sizeof(qbuf_planes));
    599   qbuf.index = index;
    600   qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    601   qbuf.m.planes = qbuf_planes;
    602 
    603   DCHECK_EQ(device_input_format_, frame->format());
    604   for (size_t i = 0; i < input_planes_count_; ++i) {
    605     qbuf.m.planes[i].bytesused =
    606         base::checked_cast<__u32>(media::VideoFrame::PlaneAllocationSize(
    607             frame->format(), i, input_allocated_size_));
    608 
    609     switch (input_memory_type_) {
    610       case V4L2_MEMORY_USERPTR:
    611         qbuf.m.planes[i].m.userptr =
    612             reinterpret_cast<unsigned long>(frame->data(i));
    613         DCHECK(qbuf.m.planes[i].m.userptr);
    614         break;
    615 
    616       case V4L2_MEMORY_DMABUF:
    617         qbuf.m.planes[i].m.fd = frame->dmabuf_fd(i);
    618         DCHECK_NE(qbuf.m.planes[i].m.fd, -1);
    619         break;
    620 
    621       default:
    622         NOTREACHED();
    623         return false;
    624     }
    625   }
    626 
    627   qbuf.memory = input_memory_type_;
    628   qbuf.length = input_planes_count_;
    629 
    630   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
    631   input_record.at_device = true;
    632   input_record.frame = frame;
    633   encoder_input_queue_.pop_front();
    634   free_input_buffers_.pop_back();
    635   input_buffer_queued_count_++;
    636   return true;
    637 }
    638 
    639 bool V4L2VideoEncodeAccelerator::EnqueueOutputRecord() {
    640   DVLOG(3) << "EnqueueOutputRecord()";
    641   DCHECK(!free_output_buffers_.empty());
    642   DCHECK(!encoder_output_queue_.empty());
    643 
    644   // Enqueue an output (VIDEO_CAPTURE) buffer.
    645   linked_ptr<BitstreamBufferRef> output_buffer = encoder_output_queue_.back();
    646   const int index = free_output_buffers_.back();
    647   OutputRecord& output_record = output_buffer_map_[index];
    648   DCHECK(!output_record.at_device);
    649   DCHECK(!output_record.buffer_ref.get());
    650   struct v4l2_buffer qbuf;
    651   struct v4l2_plane qbuf_planes[1];
    652   memset(&qbuf, 0, sizeof(qbuf));
    653   memset(qbuf_planes, 0, sizeof(qbuf_planes));
    654   qbuf.index = index;
    655   qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    656   qbuf.memory = V4L2_MEMORY_MMAP;
    657   qbuf.m.planes = qbuf_planes;
    658   qbuf.length = 1;
    659   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
    660   output_record.at_device = true;
    661   output_record.buffer_ref = output_buffer;
    662   encoder_output_queue_.pop_back();
    663   free_output_buffers_.pop_back();
    664   output_buffer_queued_count_++;
    665   return true;
    666 }
    667 
    668 bool V4L2VideoEncodeAccelerator::StartDevicePoll() {
    669   DVLOG(3) << "StartDevicePoll()";
    670   DCHECK_EQ(encoder_thread_.message_loop(), base::MessageLoop::current());
    671   DCHECK(!device_poll_thread_.IsRunning());
    672 
    673   // Start up the device poll thread and schedule its first DevicePollTask().
    674   if (!device_poll_thread_.Start()) {
    675     DLOG(ERROR) << "StartDevicePoll(): Device thread failed to start";
    676     NOTIFY_ERROR(kPlatformFailureError);
    677     return false;
    678   }
    679   // Enqueue a poll task with no devices to poll on -- it will wait only on the
    680   // interrupt fd.
    681   device_poll_thread_.message_loop()->PostTask(
    682       FROM_HERE,
    683       base::Bind(&V4L2VideoEncodeAccelerator::DevicePollTask,
    684                  base::Unretained(this),
    685                  false));
    686 
    687   return true;
    688 }
    689 
    690 bool V4L2VideoEncodeAccelerator::StopDevicePoll() {
    691   DVLOG(3) << "StopDevicePoll()";
    692 
    693   // Signal the DevicePollTask() to stop, and stop the device poll thread.
    694   if (!device_->SetDevicePollInterrupt())
    695     return false;
    696   device_poll_thread_.Stop();
    697   // Clear the interrupt now, to be sure.
    698   if (!device_->ClearDevicePollInterrupt())
    699     return false;
    700 
    701   if (input_streamon_) {
    702     __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    703     IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type);
    704   }
    705   input_streamon_ = false;
    706 
    707   if (output_streamon_) {
    708     __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    709     IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type);
    710   }
    711   output_streamon_ = false;
    712 
    713   // Reset all our accounting info.
    714   encoder_input_queue_.clear();
    715   free_input_buffers_.clear();
    716   for (size_t i = 0; i < input_buffer_map_.size(); ++i) {
    717     InputRecord& input_record = input_buffer_map_[i];
    718     input_record.at_device = false;
    719     input_record.frame = NULL;
    720     free_input_buffers_.push_back(i);
    721   }
    722   input_buffer_queued_count_ = 0;
    723 
    724   free_output_buffers_.clear();
    725   for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
    726     OutputRecord& output_record = output_buffer_map_[i];
    727     output_record.at_device = false;
    728     output_record.buffer_ref.reset();
    729     free_output_buffers_.push_back(i);
    730   }
    731   output_buffer_queued_count_ = 0;
    732 
    733   encoder_output_queue_.clear();
    734 
    735   DVLOG(3) << "StopDevicePoll(): device poll stopped";
    736   return true;
    737 }
    738 
    739 void V4L2VideoEncodeAccelerator::DevicePollTask(bool poll_device) {
    740   DVLOG(3) << "DevicePollTask()";
    741   DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current());
    742 
    743   bool event_pending;
    744   if (!device_->Poll(poll_device, &event_pending)) {
    745     NOTIFY_ERROR(kPlatformFailureError);
    746     return;
    747   }
    748 
    749   // All processing should happen on ServiceDeviceTask(), since we shouldn't
    750   // touch encoder state from this thread.
    751   encoder_thread_.message_loop()->PostTask(
    752       FROM_HERE,
    753       base::Bind(&V4L2VideoEncodeAccelerator::ServiceDeviceTask,
    754                  base::Unretained(this)));
    755 }
    756 
    757 void V4L2VideoEncodeAccelerator::NotifyError(Error error) {
    758   DVLOG(1) << "NotifyError(): error=" << error;
    759 
    760   if (!child_message_loop_proxy_->BelongsToCurrentThread()) {
    761     child_message_loop_proxy_->PostTask(
    762         FROM_HERE,
    763         base::Bind(
    764             &V4L2VideoEncodeAccelerator::NotifyError, weak_this_, error));
    765     return;
    766   }
    767 
    768   if (client_) {
    769     client_->NotifyError(error);
    770     client_ptr_factory_.reset();
    771   }
    772 }
    773 
    774 void V4L2VideoEncodeAccelerator::SetEncoderState(State state) {
    775   DVLOG(3) << "SetEncoderState(): state=" << state;
    776 
    777   // We can touch encoder_state_ only if this is the encoder thread or the
    778   // encoder thread isn't running.
    779   if (encoder_thread_.message_loop() != NULL &&
    780       encoder_thread_.message_loop() != base::MessageLoop::current()) {
    781     encoder_thread_.message_loop()->PostTask(
    782         FROM_HERE,
    783         base::Bind(&V4L2VideoEncodeAccelerator::SetEncoderState,
    784                    base::Unretained(this),
    785                    state));
    786   } else {
    787     encoder_state_ = state;
    788   }
    789 }
    790 
    791 void V4L2VideoEncodeAccelerator::RequestEncodingParametersChangeTask(
    792     uint32 bitrate,
    793     uint32 framerate) {
    794   DVLOG(3) << "RequestEncodingParametersChangeTask(): bitrate=" << bitrate
    795            << ", framerate=" << framerate;
    796   DCHECK_EQ(encoder_thread_.message_loop(), base::MessageLoop::current());
    797 
    798   if (bitrate < 1)
    799     bitrate = 1;
    800   if (framerate < 1)
    801     framerate = 1;
    802 
    803   struct v4l2_ext_control ctrls[1];
    804   struct v4l2_ext_controls control;
    805   memset(&ctrls, 0, sizeof(ctrls));
    806   memset(&control, 0, sizeof(control));
    807   ctrls[0].id = V4L2_CID_MPEG_VIDEO_BITRATE;
    808   ctrls[0].value = bitrate;
    809   control.ctrl_class = V4L2_CTRL_CLASS_MPEG;
    810   control.count = arraysize(ctrls);
    811   control.controls = ctrls;
    812   IOCTL_OR_ERROR_RETURN(VIDIOC_S_EXT_CTRLS, &control);
    813 
    814   struct v4l2_streamparm parms;
    815   memset(&parms, 0, sizeof(parms));
    816   parms.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    817   // Note that we are provided "frames per second" but V4L2 expects "time per
    818   // frame"; hence we provide the reciprocal of the framerate here.
    819   parms.parm.output.timeperframe.numerator = 1;
    820   parms.parm.output.timeperframe.denominator = framerate;
    821   IOCTL_OR_ERROR_RETURN(VIDIOC_S_PARM, &parms);
    822 }
    823 
    824 bool V4L2VideoEncodeAccelerator::SetOutputFormat(
    825     media::VideoCodecProfile output_profile) {
    826   DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
    827   DCHECK(!input_streamon_);
    828   DCHECK(!output_streamon_);
    829 
    830   output_format_fourcc_ =
    831       V4L2Device::VideoCodecProfileToV4L2PixFmt(output_profile);
    832   if (!output_format_fourcc_) {
    833     DLOG(ERROR) << "Initialize(): invalid output_profile=" << output_profile;
    834     return false;
    835   }
    836 
    837   output_buffer_byte_size_ = kOutputBufferSize;
    838 
    839   struct v4l2_format format;
    840   memset(&format, 0, sizeof(format));
    841   format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    842   format.fmt.pix_mp.width = visible_size_.width();
    843   format.fmt.pix_mp.height = visible_size_.height();
    844   format.fmt.pix_mp.pixelformat = output_format_fourcc_;
    845   format.fmt.pix_mp.plane_fmt[0].sizeimage =
    846       base::checked_cast<__u32>(output_buffer_byte_size_);
    847   format.fmt.pix_mp.num_planes = 1;
    848   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
    849 
    850   // Device might have adjusted the required output size.
    851   size_t adjusted_output_buffer_size =
    852       base::checked_cast<size_t>(format.fmt.pix_mp.plane_fmt[0].sizeimage);
    853   DCHECK_GE(adjusted_output_buffer_size, output_buffer_byte_size_);
    854   output_buffer_byte_size_ = adjusted_output_buffer_size;
    855 
    856   return true;
    857 }
    858 
    859 bool V4L2VideoEncodeAccelerator::NegotiateInputFormat(
    860     media::VideoFrame::Format input_format) {
    861   DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
    862   DCHECK(!input_streamon_);
    863   DCHECK(!output_streamon_);
    864 
    865   device_input_format_ = media::VideoFrame::UNKNOWN;
    866   input_planes_count_ = 0;
    867 
    868   uint32 input_format_fourcc =
    869       V4L2Device::VideoFrameFormatToV4L2PixFmt(input_format);
    870   if (!input_format_fourcc) {
    871     DVLOG(1) << "Unsupported input format";
    872     return false;
    873   }
    874 
    875   size_t input_planes_count = media::VideoFrame::NumPlanes(input_format);
    876   DCHECK_LE(input_planes_count, static_cast<size_t>(VIDEO_MAX_PLANES));
    877 
    878   // First see if we the device can use the provided input_format directly.
    879   struct v4l2_format format;
    880   memset(&format, 0, sizeof(format));
    881   format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    882   format.fmt.pix_mp.width = visible_size_.width();
    883   format.fmt.pix_mp.height = visible_size_.height();
    884   format.fmt.pix_mp.pixelformat = input_format_fourcc;
    885   format.fmt.pix_mp.num_planes = input_planes_count;
    886   if (device_->Ioctl(VIDIOC_S_FMT, &format) != 0) {
    887     // Error or format unsupported by device, try to negotiate a fallback.
    888     input_format_fourcc = device_->PreferredInputFormat();
    889     input_format =
    890         V4L2Device::V4L2PixFmtToVideoFrameFormat(input_format_fourcc);
    891     if (input_format == media::VideoFrame::UNKNOWN)
    892       return false;
    893 
    894     input_planes_count = media::VideoFrame::NumPlanes(input_format);
    895     DCHECK_LE(input_planes_count, static_cast<size_t>(VIDEO_MAX_PLANES));
    896 
    897     // Device might have adjusted parameters, reset them along with the format.
    898     memset(&format, 0, sizeof(format));
    899     format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    900     format.fmt.pix_mp.width = visible_size_.width();
    901     format.fmt.pix_mp.height = visible_size_.height();
    902     format.fmt.pix_mp.pixelformat = input_format_fourcc;
    903     format.fmt.pix_mp.num_planes = input_planes_count;
    904     IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
    905     DCHECK_EQ(format.fmt.pix_mp.num_planes, input_planes_count);
    906   }
    907 
    908   // Take device-adjusted sizes for allocated size.
    909   input_allocated_size_ = V4L2Device::CodedSizeFromV4L2Format(format);
    910   DCHECK(gfx::Rect(input_allocated_size_).Contains(gfx::Rect(visible_size_)));
    911 
    912   device_input_format_ = input_format;
    913   input_planes_count_ = input_planes_count;
    914   return true;
    915 }
    916 
    917 bool V4L2VideoEncodeAccelerator::SetFormats(
    918     media::VideoFrame::Format input_format,
    919     media::VideoCodecProfile output_profile) {
    920   DVLOG(3) << "SetFormats()";
    921   DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
    922   DCHECK(!input_streamon_);
    923   DCHECK(!output_streamon_);
    924 
    925   if (!SetOutputFormat(output_profile))
    926     return false;
    927 
    928   if (!NegotiateInputFormat(input_format))
    929     return false;
    930 
    931   struct v4l2_crop crop;
    932   memset(&crop, 0, sizeof(crop));
    933   crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
    934   crop.c.left = 0;
    935   crop.c.top = 0;
    936   crop.c.width = visible_size_.width();
    937   crop.c.height = visible_size_.height();
    938   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_CROP, &crop);
    939 
    940   return true;
    941 }
    942 
    943 bool V4L2VideoEncodeAccelerator::InitControls() {
    944   struct v4l2_ext_control ctrls[9];
    945   struct v4l2_ext_controls control;
    946   memset(&ctrls, 0, sizeof(ctrls));
    947   memset(&control, 0, sizeof(control));
    948   // No B-frames, for lowest decoding latency.
    949   ctrls[0].id = V4L2_CID_MPEG_VIDEO_B_FRAMES;
    950   ctrls[0].value = 0;
    951   // Enable frame-level bitrate control.
    952   ctrls[1].id = V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE;
    953   ctrls[1].value = 1;
    954   // Enable "tight" bitrate mode. For this to work properly, frame- and mb-level
    955   // bitrate controls have to be enabled as well.
    956   ctrls[2].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF;
    957   ctrls[2].value = 1;
    958   // Force bitrate control to average over a GOP (for tight bitrate
    959   // tolerance).
    960   ctrls[3].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT;
    961   ctrls[3].value = 1;
    962   // Quantization parameter maximum value (for variable bitrate control).
    963   ctrls[4].id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP;
    964   ctrls[4].value = 51;
    965   // Separate stream header so we can cache it and insert into the stream.
    966   ctrls[5].id = V4L2_CID_MPEG_VIDEO_HEADER_MODE;
    967   ctrls[5].value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE;
    968   // Enable macroblock-level bitrate control.
    969   ctrls[6].id = V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE;
    970   ctrls[6].value = 1;
    971   // Use H.264 level 4.0 to match the supported max resolution.
    972   ctrls[7].id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
    973   ctrls[7].value = V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
    974   // Disable periodic key frames.
    975   ctrls[8].id = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
    976   ctrls[8].value = 0;
    977   control.ctrl_class = V4L2_CTRL_CLASS_MPEG;
    978   control.count = arraysize(ctrls);
    979   control.controls = ctrls;
    980   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_EXT_CTRLS, &control);
    981 
    982   return true;
    983 }
    984 
    985 bool V4L2VideoEncodeAccelerator::CreateInputBuffers() {
    986   DVLOG(3) << "CreateInputBuffers()";
    987   // This function runs on encoder_thread_ after output buffers have been
    988   // provided by the client.
    989   DCHECK_EQ(encoder_thread_.message_loop(), base::MessageLoop::current());
    990   DCHECK(!input_streamon_);
    991 
    992   struct v4l2_requestbuffers reqbufs;
    993   memset(&reqbufs, 0, sizeof(reqbufs));
    994   // Driver will modify to the appropriate number of buffers.
    995   reqbufs.count = 1;
    996   reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    997   // TODO(posciak): Once we start doing zero-copy, we should decide based on
    998   // the current pipeline setup which memory type to use. This should probably
    999   // be decided based on an argument to Initialize().
   1000   if (image_processor_.get())
   1001     input_memory_type_ = V4L2_MEMORY_DMABUF;
   1002   else
   1003     input_memory_type_ = V4L2_MEMORY_USERPTR;
   1004 
   1005   reqbufs.memory = input_memory_type_;
   1006   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);
   1007 
   1008   DCHECK(input_buffer_map_.empty());
   1009   input_buffer_map_.resize(reqbufs.count);
   1010   for (size_t i = 0; i < input_buffer_map_.size(); ++i)
   1011     free_input_buffers_.push_back(i);
   1012 
   1013   return true;
   1014 }
   1015 
   1016 bool V4L2VideoEncodeAccelerator::CreateOutputBuffers() {
   1017   DVLOG(3) << "CreateOutputBuffers()";
   1018   DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
   1019   DCHECK(!output_streamon_);
   1020 
   1021   struct v4l2_requestbuffers reqbufs;
   1022   memset(&reqbufs, 0, sizeof(reqbufs));
   1023   reqbufs.count = kOutputBufferCount;
   1024   reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   1025   reqbufs.memory = V4L2_MEMORY_MMAP;
   1026   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);
   1027 
   1028   DCHECK(output_buffer_map_.empty());
   1029   output_buffer_map_.resize(reqbufs.count);
   1030   for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
   1031     struct v4l2_plane planes[1];
   1032     struct v4l2_buffer buffer;
   1033     memset(&buffer, 0, sizeof(buffer));
   1034     memset(planes, 0, sizeof(planes));
   1035     buffer.index = i;
   1036     buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   1037     buffer.memory = V4L2_MEMORY_MMAP;
   1038     buffer.m.planes = planes;
   1039     buffer.length = arraysize(planes);
   1040     IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer);
   1041     void* address = device_->Mmap(NULL,
   1042                                   buffer.m.planes[0].length,
   1043                                   PROT_READ | PROT_WRITE,
   1044                                   MAP_SHARED,
   1045                                   buffer.m.planes[0].m.mem_offset);
   1046     if (address == MAP_FAILED) {
   1047       DPLOG(ERROR) << "CreateOutputBuffers(): mmap() failed";
   1048       return false;
   1049     }
   1050     output_buffer_map_[i].address = address;
   1051     output_buffer_map_[i].length = buffer.m.planes[0].length;
   1052     free_output_buffers_.push_back(i);
   1053   }
   1054 
   1055   return true;
   1056 }
   1057 
   1058 void V4L2VideoEncodeAccelerator::DestroyInputBuffers() {
   1059   DVLOG(3) << "DestroyInputBuffers()";
   1060   DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
   1061   DCHECK(!input_streamon_);
   1062 
   1063   struct v4l2_requestbuffers reqbufs;
   1064   memset(&reqbufs, 0, sizeof(reqbufs));
   1065   reqbufs.count = 0;
   1066   reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
   1067   reqbufs.memory = input_memory_type_;
   1068   IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
   1069 
   1070   input_buffer_map_.clear();
   1071   free_input_buffers_.clear();
   1072 }
   1073 
   1074 void V4L2VideoEncodeAccelerator::DestroyOutputBuffers() {
   1075   DVLOG(3) << "DestroyOutputBuffers()";
   1076   DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
   1077   DCHECK(!output_streamon_);
   1078 
   1079   for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
   1080     if (output_buffer_map_[i].address != NULL)
   1081       device_->Munmap(output_buffer_map_[i].address,
   1082                       output_buffer_map_[i].length);
   1083   }
   1084 
   1085   struct v4l2_requestbuffers reqbufs;
   1086   memset(&reqbufs, 0, sizeof(reqbufs));
   1087   reqbufs.count = 0;
   1088   reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   1089   reqbufs.memory = V4L2_MEMORY_MMAP;
   1090   IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
   1091 
   1092   output_buffer_map_.clear();
   1093   free_output_buffers_.clear();
   1094 }
   1095 
   1096 }  // namespace content
   1097