// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/gpu/v4l2/v4l2_mjpeg_decode_accelerator.h"

#include <errno.h>
#include <linux/videodev2.h>
#include <string.h>
#include <sys/mman.h>

#include <array>
#include <memory>
#include <utility>

#include "base/big_endian.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/cxx17_backports.h"
#include "base/files/scoped_file.h"
#include "base/memory/page_size.h"
#include "base/numerics/safe_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/bitstream_buffer.h"
#include "media/base/unaligned_shared_memory.h"
#include "media/base/video_frame.h"
#include "media/base/video_types.h"
#include "media/gpu/chromeos/fourcc.h"
#include "media/gpu/chromeos/platform_video_frame_utils.h"
#include "media/gpu/macros.h"
#include "media/gpu/video_frame_mapper.h"
#include "media/gpu/video_frame_mapper_factory.h"
#include "media/parsers/jpeg_parser.h"
#include "third_party/libyuv/include/libyuv.h"

#define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_name) \
  do {                                                           \
    if (device_->Ioctl(type, arg) != 0) {                        \
      VPLOGF(1) << "ioctl() failed: " << type_name;              \
      PostNotifyError(kInvalidTaskId, PLATFORM_FAILURE);         \
      return value;                                              \
    }                                                            \
  } while (0)

#define IOCTL_OR_ERROR_RETURN(type, arg) \
  IOCTL_OR_ERROR_RETURN_VALUE(type, arg, ((void)0), #type)

#define IOCTL_OR_ERROR_RETURN_FALSE(type, arg) \
  IOCTL_OR_ERROR_RETURN_VALUE(type, arg, false, #type)

#define IOCTL_OR_LOG_ERROR(type, arg)                    \
  do {                                                   \
    if (device_->Ioctl(type, arg) != 0) {                \
      VPLOGF(1) << "ioctl() failed: " << #type;          \
      PostNotifyError(kInvalidTaskId, PLATFORM_FAILURE); \
    }                                                    \
  } while (0)

#define READ_U8_OR_RETURN_FALSE(reader, out)                               \
  do {                                                                     \
    uint8_t _out;                                                          \
    if (!reader.ReadU8(&_out)) {                                           \
      DVLOGF(1)                                                            \
          << "Error in stream: unexpected EOS while trying to read " #out; \
      return false;                                                        \
    }                                                                      \
    *(out) = _out;                                                         \
  } while (0)

#define READ_U16_OR_RETURN_FALSE(reader, out)                              \
  do {                                                                     \
    uint16_t _out;                                                         \
    if (!reader.ReadU16(&_out)) {                                          \
      DVLOGF(1)                                                            \
          << "Error in stream: unexpected EOS while trying to read " #out; \
      return false;                                                        \
    }                                                                      \
    *(out) = _out;                                                         \
  } while (0)

namespace {

// Input pixel format (i.e. V4L2_PIX_FMT_JPEG) has only one physical plane.
const size_t kMaxInputPlanes = 1;

// This class can only handle V4L2_PIX_FMT_JPEG as input, so kMaxInputPlanes
// can only be 1.
static_assert(kMaxInputPlanes == 1,
              "kMaxInputPlanes must be 1 as input must be V4L2_PIX_FMT_JPEG");
}  // namespace

namespace media {

// This is default huffman segment for 8-bit precision luminance and
// chrominance. The default huffman segment is constructed with the tables from
// JPEG standard section K.3. Actually there are no default tables. They are
// typical tables. These tables are useful for many applications. Lots of
// softwares use them as standard tables such as ffmpeg.
const uint8_t kDefaultDhtSeg[] = {
    0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
    0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x01, 0x00, 0x03,
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
    0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05,
    0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04,
    0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22,
    0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15,
    0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
    0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36,
    0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
    0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
    0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
    0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95,
    0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
    0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2,
    0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5,
    0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
    0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9,
    0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
    0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
    0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22,
    0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33,
    0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
    0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36,
    0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
    0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
    0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
    0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94,
    0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
    0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA,
    0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4,
    0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
    0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA};

class V4L2MjpegDecodeAccelerator::JobRecord {
 public:
  JobRecord(const JobRecord&) = delete;
  JobRecord& operator=(const JobRecord&) = delete;

  virtual ~JobRecord() = default;

  // Task ID passed from Decode() call.
  virtual int32_t task_id() const = 0;
  // Input buffer size.
  virtual size_t size() const = 0;
  // Input buffer offset.
  virtual off_t offset() const = 0;
  // Maps input buffer.
  virtual bool map() = 0;
  // Pointer to the input content. Only valid if map() is already called.
  virtual const void* memory() const = 0;

  // Output frame buffer.
  virtual const scoped_refptr<VideoFrame>& out_frame() = 0;

 protected:
  JobRecord() = default;
};

// Job record when the client uses BitstreamBuffer as input in Decode().
class JobRecordBitstreamBuffer : public V4L2MjpegDecodeAccelerator::JobRecord {
 public:
  JobRecordBitstreamBuffer(BitstreamBuffer bitstream_buffer,
                           scoped_refptr<VideoFrame> video_frame)
      : task_id_(bitstream_buffer.id()),
        shm_(bitstream_buffer.TakeRegion(),
             bitstream_buffer.size(),
             false /* read_only */),
        offset_(bitstream_buffer.offset()),
        out_frame_(video_frame) {}

  int32_t task_id() const override { return task_id_; }
  size_t size() const override { return shm_.size(); }
  off_t offset() const override { return offset_; }
  bool map() override { return shm_.MapAt(offset(), size()); }
  const void* memory() const override { return shm_.memory(); }

  const scoped_refptr<VideoFrame>& out_frame() override { return out_frame_; }

 private:
  int32_t task_id_;
  UnalignedSharedMemory shm_;
  off_t offset_;
  scoped_refptr<VideoFrame> out_frame_;

  DISALLOW_COPY_AND_ASSIGN(JobRecordBitstreamBuffer);
};

// Job record when the client uses DMA buffer as input in Decode().
class JobRecordDmaBuf : public V4L2MjpegDecodeAccelerator::JobRecord {
 public:
  JobRecordDmaBuf(int32_t task_id,
                  base::ScopedFD src_dmabuf_fd,
                  size_t src_size,
                  off_t src_offset,
                  scoped_refptr<VideoFrame> dst_frame)
      : task_id_(task_id),
        dmabuf_fd_(std::move(src_dmabuf_fd)),
        size_(src_size),
        offset_(src_offset),
        mapped_addr_(nullptr),
        out_frame_(std::move(dst_frame)) {}

  JobRecordDmaBuf(const JobRecordDmaBuf&) = delete;
  JobRecordDmaBuf& operator=(const JobRecordDmaBuf&) = delete;

  ~JobRecordDmaBuf() {
    if (mapped_addr_) {
      const int ret = munmap(mapped_addr_, size());
      DPCHECK(ret == 0);
    }
  }

  int32_t task_id() const override { return task_id_; }
  size_t size() const override { return size_; }
  off_t offset() const override { return offset_; }

  bool map() override {
    if (mapped_addr_)
      return true;
    // The DMA-buf FD should be mapped as read-only since it may only have read
    // permission, e.g. when it comes from camera driver.
    DCHECK(dmabuf_fd_.is_valid());
    DCHECK_GT(size(), 0u);
    void* addr = mmap(nullptr, size(), PROT_READ, MAP_SHARED, dmabuf_fd_.get(),
                      offset());
    if (addr == MAP_FAILED)
      return false;
    mapped_addr_ = addr;
    return true;
  }

  const void* memory() const override {
    DCHECK(mapped_addr_);
    return mapped_addr_;
  }

  const scoped_refptr<VideoFrame>& out_frame() override { return out_frame_; }

 private:
  int32_t task_id_;
  base::ScopedFD dmabuf_fd_;
  size_t size_;
  off_t offset_;
  void* mapped_addr_;
  scoped_refptr<VideoFrame> out_frame_;
};

V4L2MjpegDecodeAccelerator::BufferRecord::BufferRecord() : at_device(false) {
  memset(address, 0, sizeof(address));
  memset(length, 0, sizeof(length));
}

V4L2MjpegDecodeAccelerator::BufferRecord::~BufferRecord() {}

V4L2MjpegDecodeAccelerator::V4L2MjpegDecodeAccelerator(
    const scoped_refptr<V4L2Device>& device,
    const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
    : output_buffer_pixelformat_(0),
      output_buffer_num_planes_(0),
      child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
      io_task_runner_(io_task_runner),
      client_(nullptr),
      device_(device),
      decoder_thread_("V4L2MjpegDecodeThread"),
      device_poll_thread_("V4L2MjpegDecodeDevicePollThread"),
      input_streamon_(false),
      output_streamon_(false),
      weak_factory_(this) {
  weak_ptr_ = weak_factory_.GetWeakPtr();
}

V4L2MjpegDecodeAccelerator::~V4L2MjpegDecodeAccelerator() {
  DCHECK(child_task_runner_->BelongsToCurrentThread());

  if (decoder_thread_.IsRunning()) {
    decoder_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&V4L2MjpegDecodeAccelerator::DestroyTask,
                                  base::Unretained(this)));
    decoder_thread_.Stop();
  }
  weak_factory_.InvalidateWeakPtrs();
  DCHECK(!device_poll_thread_.IsRunning());
}

void V4L2MjpegDecodeAccelerator::DestroyTask() {
  DCHECK(decoder_task_runner_->BelongsToCurrentThread());
  while (!input_jobs_.empty())
    input_jobs_.pop();
  while (!running_jobs_.empty())
    running_jobs_.pop();

  // Stop streaming and the device_poll_thread_.
  StopDevicePoll();

  DestroyInputBuffers();
  DestroyOutputBuffers();
}

void V4L2MjpegDecodeAccelerator::VideoFrameReady(int32_t task_id) {
  DCHECK(child_task_runner_->BelongsToCurrentThread());
  client_->VideoFrameReady(task_id);
}

void V4L2MjpegDecodeAccelerator::NotifyError(int32_t task_id, Error error) {
  DCHECK(child_task_runner_->BelongsToCurrentThread());
  VLOGF(1) << "Notifying of error " << error << " for task id " << task_id;
  client_->NotifyError(task_id, error);
}

void V4L2MjpegDecodeAccelerator::PostNotifyError(int32_t task_id, Error error) {
  child_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&V4L2MjpegDecodeAccelerator::NotifyError,
                                weak_ptr_, task_id, error));
}

void V4L2MjpegDecodeAccelerator::InitializeOnTaskRunner(
    chromeos_camera::MjpegDecodeAccelerator::Client* client,
    chromeos_camera::MjpegDecodeAccelerator::InitCB init_cb) {
  DCHECK(child_task_runner_->BelongsToCurrentThread());
  if (!device_->Open(V4L2Device::Type::kJpegDecoder, V4L2_PIX_FMT_JPEG)) {
    VLOGF(1) << "Failed to open device";
    std::move(init_cb).Run(false);
    return;
  }

  // Capabilities check.
  struct v4l2_capability caps;
  const __u32 kCapsRequired = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
  memset(&caps, 0, sizeof(caps));
  if (device_->Ioctl(VIDIOC_QUERYCAP, &caps) != 0) {
    VPLOGF(1) << "ioctl() failed: VIDIOC_QUERYCAP";
    std::move(init_cb).Run(false);
    return;
  }
  if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
    VLOGF(1) << "VIDIOC_QUERYCAP, caps check failed: 0x" << std::hex
             << caps.capabilities;
    std::move(init_cb).Run(false);
    return;
  }

  // Subscribe to the source change event.
  struct v4l2_event_subscription sub;
  memset(&sub, 0, sizeof(sub));
  sub.type = V4L2_EVENT_SOURCE_CHANGE;
  if (device_->Ioctl(VIDIOC_SUBSCRIBE_EVENT, &sub) != 0) {
    VPLOGF(1) << "ioctl() failed: VIDIOC_SUBSCRIBE_EVENT";
    std::move(init_cb).Run(false);
    return;
  }

  if (!decoder_thread_.Start()) {
    VLOGF(1) << "decoder thread failed to start";
    std::move(init_cb).Run(false);
    return;
  }
  client_ = client;
  decoder_task_runner_ = decoder_thread_.task_runner();

  decoder_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&V4L2MjpegDecodeAccelerator::StartDevicePoll,
                                base::Unretained(this)));

  VLOGF(2) << "V4L2MjpegDecodeAccelerator initialized.";
  std::move(init_cb).Run(true);
}

void V4L2MjpegDecodeAccelerator::InitializeAsync(
    chromeos_camera::MjpegDecodeAccelerator::Client* client,
    chromeos_camera::MjpegDecodeAccelerator::InitCB init_cb) {
  DCHECK(child_task_runner_->BelongsToCurrentThread());

  // To guarantee that the caller receives an asynchronous call after the
  // return path, we are making use of InitializeOnTaskRunner.
  child_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&V4L2MjpegDecodeAccelerator::InitializeOnTaskRunner,
                     weak_factory_.GetWeakPtr(), client,
                     BindToCurrentLoop(std::move(init_cb))));
}

void V4L2MjpegDecodeAccelerator::Decode(BitstreamBuffer bitstream_buffer,
                                        scoped_refptr<VideoFrame> video_frame) {
  DVLOGF(4) << "input_id=" << bitstream_buffer.id()
            << ", size=" << bitstream_buffer.size();
  DCHECK(io_task_runner_->BelongsToCurrentThread());

  if (bitstream_buffer.id() < 0) {
    VLOGF(1) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id();
    PostNotifyError(bitstream_buffer.id(), INVALID_ARGUMENT);
    return;
  }

  // Validate output video frame.
  if (!video_frame->IsMappable() && !video_frame->HasDmaBufs()) {
    VLOGF(1) << "Unsupported output frame storage type";
    PostNotifyError(bitstream_buffer.id(), INVALID_ARGUMENT);
    return;
  }
  if ((video_frame->visible_rect().width() & 1) ||
      (video_frame->visible_rect().height() & 1)) {
    VLOGF(1) << "Output frame visible size has odd dimension";
    PostNotifyError(bitstream_buffer.id(), PLATFORM_FAILURE);
    return;
  }

  std::unique_ptr<JobRecord> job_record(new JobRecordBitstreamBuffer(
      std::move(bitstream_buffer), std::move(video_frame)));

  decoder_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&V4L2MjpegDecodeAccelerator::DecodeTask,
                                base::Unretained(this), std::move(job_record)));
}

void V4L2MjpegDecodeAccelerator::Decode(
    int32_t task_id,
    base::ScopedFD src_dmabuf_fd,
    size_t src_size,
    off_t src_offset,
    scoped_refptr<media::VideoFrame> dst_frame) {
  DVLOGF(4) << "task_id=" << task_id;
  DCHECK(io_task_runner_->BelongsToCurrentThread());

  if (task_id < 0) {
    VLOGF(1) << "Invalid task id: " << task_id;
    PostNotifyError(task_id, INVALID_ARGUMENT);
    return;
  }

  // Validate input arguments.
  if (!src_dmabuf_fd.is_valid()) {
    VLOGF(1) << "Invalid input buffer FD";
    PostNotifyError(task_id, INVALID_ARGUMENT);
    return;
  }
  if (src_size == 0) {
    VLOGF(1) << "Input buffer size is zero";
    PostNotifyError(task_id, INVALID_ARGUMENT);
    return;
  }
  const size_t page_size = base::GetPageSize();
  if (src_offset < 0 || src_offset % page_size != 0) {
    VLOGF(1) << "Input buffer offset (" << src_offset
             << ") should be non-negative and aligned to page size ("
             << page_size << ")";
    PostNotifyError(task_id, INVALID_ARGUMENT);
    return;
  }

  // Validate output video frame.
  if (!dst_frame->IsMappable() && !dst_frame->HasDmaBufs()) {
    VLOGF(1) << "Unsupported output frame storage type";
    PostNotifyError(task_id, INVALID_ARGUMENT);
    return;
  }
  if ((dst_frame->visible_rect().width() & 1) ||
      (dst_frame->visible_rect().height() & 1)) {
    VLOGF(1) << "Output frame visible size has odd dimension";
    PostNotifyError(task_id, PLATFORM_FAILURE);
    return;
  }

  std::unique_ptr<JobRecord> job_record(
      new JobRecordDmaBuf(task_id, std::move(src_dmabuf_fd), src_size,
                          src_offset, std::move(dst_frame)));

  decoder_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&V4L2MjpegDecodeAccelerator::DecodeTask,
                                base::Unretained(this), std::move(job_record)));
}

// static
bool V4L2MjpegDecodeAccelerator::IsSupported() {
  scoped_refptr<V4L2Device> device = V4L2Device::Create();
  if (!device)
    return false;

  return device->IsJpegDecodingSupported();
}

void V4L2MjpegDecodeAccelerator::DecodeTask(
    std::unique_ptr<JobRecord> job_record) {
  DCHECK(decoder_task_runner_->BelongsToCurrentThread());
  if (!job_record->map()) {
    VPLOGF(1) << "could not map input buffer";
    PostNotifyError(job_record->task_id(), UNREADABLE_INPUT);
    return;
  }
  input_jobs_.push(std::move(job_record));

  ServiceDeviceTask(false);
}

size_t V4L2MjpegDecodeAccelerator::InputBufferQueuedCount() {
  return input_buffer_map_.size() - free_input_buffers_.size();
}

size_t V4L2MjpegDecodeAccelerator::OutputBufferQueuedCount() {
  return output_buffer_map_.size() - free_output_buffers_.size();
}

bool V4L2MjpegDecodeAccelerator::ShouldRecreateInputBuffers() {
  DCHECK(decoder_task_runner_->BelongsToCurrentThread());
  if (input_jobs_.empty())
    return false;

  JobRecord* job_record = input_jobs_.front().get();
  // Check input buffer size is enough
  // TODO(kamesan): use safe arithmetic to handle overflows.
  return (input_buffer_map_.empty() ||
          (job_record->size() + sizeof(kDefaultDhtSeg)) >
              input_buffer_map_.front().length[0]);
}

bool V4L2MjpegDecodeAccelerator::RecreateInputBuffers() {
  VLOGF(2);
  DCHECK(decoder_task_runner_->BelongsToCurrentThread());

  // If running queue is not empty, we should wait until pending frames finish.
  if (!running_jobs_.empty())
    return true;

  DestroyInputBuffers();

  if (!CreateInputBuffers()) {
    VLOGF(1) << "Create input buffers failed.";
    return false;
  }

  return true;
}

bool V4L2MjpegDecodeAccelerator::RecreateOutputBuffers() {
  VLOGF(2);
  DCHECK(decoder_task_runner_->BelongsToCurrentThread());

  DestroyOutputBuffers();

  if (!CreateOutputBuffers()) {
    VLOGF(1) << "Create output buffers failed.";
    return false;
  }

  return true;
}

bool V4L2MjpegDecodeAccelerator::CreateInputBuffers() {
  VLOGF(2);
  DCHECK(decoder_task_runner_->BelongsToCurrentThread());
  DCHECK(!input_streamon_);
  DCHECK(!input_jobs_.empty());
  JobRecord* job_record = input_jobs_.front().get();
  // The input image may miss huffman table. We didn't parse the image before,
  // so we create more to avoid the situation of not enough memory.
  // Reserve twice size to avoid recreating input buffer frequently.
  // TODO(kamesan): use safe arithmetic to handle overflows.
  size_t reserve_size = (job_record->size() + sizeof(kDefaultDhtSeg)) * 2;
  struct v4l2_format format;
  memset(&format, 0, sizeof(format));
  format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
  format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_JPEG;
  format.fmt.pix_mp.plane_fmt[0].sizeimage = reserve_size;
  format.fmt.pix_mp.field = V4L2_FIELD_ANY;
  format.fmt.pix_mp.num_planes = kMaxInputPlanes;
  IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
  DCHECK_EQ(format.fmt.pix_mp.pixelformat, V4L2_PIX_FMT_JPEG);

  struct v4l2_requestbuffers reqbufs;
  memset(&reqbufs, 0, sizeof(reqbufs));
  reqbufs.count = kBufferCount;
  reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
  reqbufs.memory = V4L2_MEMORY_MMAP;
  IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);

  DCHECK(input_buffer_map_.empty());
  input_buffer_map_.resize(reqbufs.count);

  for (size_t i = 0; i < input_buffer_map_.size(); ++i) {
    free_input_buffers_.push_back(i);

    struct v4l2_buffer buffer;
    struct v4l2_plane planes[VIDEO_MAX_PLANES];
    memset(&buffer, 0, sizeof(buffer));
    memset(planes, 0, sizeof(planes));
    buffer.index = i;
    buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    buffer.m.planes = planes;
    buffer.length = base::size(planes);
    buffer.memory = V4L2_MEMORY_MMAP;
    IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer);
    if (buffer.length != kMaxInputPlanes) {
      return false;
    }
    for (size_t j = 0; j < buffer.length; ++j) {
      void* address =
          device_->Mmap(NULL, planes[j].length, PROT_READ | PROT_WRITE,
                        MAP_SHARED, planes[j].m.mem_offset);
      if (address == MAP_FAILED) {
        VPLOGF(1) << "mmap() failed";
        PostNotifyError(kInvalidTaskId, PLATFORM_FAILURE);
        return false;
      }
      input_buffer_map_[i].address[j] = address;
      input_buffer_map_[i].length[j] = planes[j].length;
    }
  }

  return true;
}

bool V4L2MjpegDecodeAccelerator::CreateOutputBuffers() {
  VLOGF(2);
  DCHECK(decoder_task_runner_->BelongsToCurrentThread());
  DCHECK(!output_streamon_);
  DCHECK(!running_jobs_.empty());
  JobRecord* job_record = running_jobs_.front().get();

  size_t frame_size = VideoFrame::AllocationSize(
      PIXEL_FORMAT_I420, job_record->out_frame()->coded_size());
  struct v4l2_format format;
  memset(&format, 0, sizeof(format));
  format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
  format.fmt.pix_mp.width = job_record->out_frame()->coded_size().width();
  format.fmt.pix_mp.height = job_record->out_frame()->coded_size().height();
  format.fmt.pix_mp.num_planes = 1;
  format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420;
  format.fmt.pix_mp.plane_fmt[0].sizeimage = frame_size;
  format.fmt.pix_mp.field = V4L2_FIELD_ANY;
  IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
  output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat;
  output_buffer_coded_size_.SetSize(format.fmt.pix_mp.width,
                                    format.fmt.pix_mp.height);
  output_buffer_num_planes_ = format.fmt.pix_mp.num_planes;
  for (size_t i = 0; i < output_buffer_num_planes_; ++i)
    output_strides_[i] = format.fmt.pix_mp.plane_fmt[i].bytesperline;

  auto output_format = Fourcc::FromV4L2PixFmt(output_buffer_pixelformat_);
  if (!output_format) {
    VLOGF(1) << "unknown V4L2 pixel format: "
             << FourccToString(output_buffer_pixelformat_);
    PostNotifyError(kInvalidTaskId, PLATFORM_FAILURE);
    return false;
  }

  struct v4l2_requestbuffers reqbufs;
  memset(&reqbufs, 0, sizeof(reqbufs));
  reqbufs.count = kBufferCount;
  reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
  reqbufs.memory = V4L2_MEMORY_MMAP;
  IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);

  DCHECK(output_buffer_map_.empty());
  output_buffer_map_.resize(reqbufs.count);

  for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
    free_output_buffers_.push_back(i);

    struct v4l2_buffer buffer;
    struct v4l2_plane planes[VIDEO_MAX_PLANES];
    memset(&buffer, 0, sizeof(buffer));
    memset(planes, 0, sizeof(planes));
    buffer.index = i;
    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    buffer.memory = V4L2_MEMORY_MMAP;
    buffer.m.planes = planes;
    buffer.length = base::size(planes);
    IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer);

    if (output_buffer_num_planes_ != buffer.length) {
      return false;
    }
    for (size_t j = 0; j < buffer.length; ++j) {
      if (base::checked_cast<int64_t>(planes[j].length) <
          VideoFrame::PlaneSize(
              output_format->ToVideoPixelFormat(), j,
              gfx::Size(format.fmt.pix_mp.width, format.fmt.pix_mp.height))
              .GetArea()) {
        return false;
      }
      void* address =
          device_->Mmap(NULL, planes[j].length, PROT_READ | PROT_WRITE,
                        MAP_SHARED, planes[j].m.mem_offset);
      if (address == MAP_FAILED) {
        VPLOGF(1) << "mmap() failed";
        PostNotifyError(kInvalidTaskId, PLATFORM_FAILURE);
        return false;
      }
      output_buffer_map_[i].address[j] = address;
      output_buffer_map_[i].length[j] = planes[j].length;
    }
  }

  return true;
}

void V4L2MjpegDecodeAccelerator::DestroyInputBuffers() {
  DCHECK(decoder_task_runner_->BelongsToCurrentThread());

  free_input_buffers_.clear();

  if (input_buffer_map_.empty())
    return;

  if (input_streamon_) {
    __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMOFF, &type);
    input_streamon_ = false;
  }

  for (const auto& input_record : input_buffer_map_) {
    for (size_t i = 0; i < kMaxInputPlanes; ++i) {
      device_->Munmap(input_record.address[i], input_record.length[i]);
    }
  }

  struct v4l2_requestbuffers reqbufs;
  memset(&reqbufs, 0, sizeof(reqbufs));
  reqbufs.count = 0;
  reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
  reqbufs.memory = V4L2_MEMORY_MMAP;
  IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);

  input_buffer_map_.clear();
}

void V4L2MjpegDecodeAccelerator::DestroyOutputBuffers() {
  DCHECK(decoder_task_runner_->BelongsToCurrentThread());

  free_output_buffers_.clear();

  if (output_buffer_map_.empty())
    return;

  if (output_streamon_) {
    __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMOFF, &type);
    output_streamon_ = false;
  }

  for (const auto& output_record : output_buffer_map_) {
    for (size_t i = 0; i < output_buffer_num_planes_; ++i) {
      device_->Munmap(output_record.address[i], output_record.length[i]);
    }
  }

  struct v4l2_requestbuffers reqbufs;
  memset(&reqbufs, 0, sizeof(reqbufs));
  reqbufs.count = 0;
  reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
  reqbufs.memory = V4L2_MEMORY_MMAP;
  IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);

  output_buffer_map_.clear();
  output_buffer_num_planes_ = 0;
}

void V4L2MjpegDecodeAccelerator::DevicePollTask() {
  DCHECK(device_poll_task_runner_->BelongsToCurrentThread());

  bool event_pending;
  if (!device_->Poll(true, &event_pending)) {
    VPLOGF(1) << "Poll device error.";
    PostNotifyError(kInvalidTaskId, PLATFORM_FAILURE);
    return;
  }

  // All processing should happen on ServiceDeviceTask(), since we shouldn't
  // touch decoder state from this thread.
  decoder_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&V4L2MjpegDecodeAccelerator::ServiceDeviceTask,
                                base::Unretained(this), event_pending));
}

bool V4L2MjpegDecodeAccelerator::DequeueSourceChangeEvent() {
  DCHECK(decoder_task_runner_->BelongsToCurrentThread());

  if (absl::optional<struct v4l2_event> event = device_->DequeueEvent()) {
    if (event->type == V4L2_EVENT_SOURCE_CHANGE) {
      VLOGF(2) << ": got source change event: " << event->u.src_change.changes;
      if (event->u.src_change.changes & V4L2_EVENT_SRC_CH_RESOLUTION) {
        return true;
      }
      VLOGF(1) << "unexpected source change event.";
    } else {
      VLOGF(1) << "got an event (" << event->type
               << ") we haven't subscribed to.";
    }
  } else {
    VLOGF(1) << "dequeue event failed.";
  }
  PostNotifyError(kInvalidTaskId, PLATFORM_FAILURE);
  return false;
}

void V4L2MjpegDecodeAccelerator::ServiceDeviceTask(bool event_pending) {
  DCHECK(decoder_task_runner_->BelongsToCurrentThread());
  // If DestroyTask() shuts |device_poll_thread_| down, we should early-out.
  if (!device_poll_thread_.IsRunning())
    return;

  if (!running_jobs_.empty())
    Dequeue();

  if (ShouldRecreateInputBuffers() && !RecreateInputBuffers())
    return;

  if (event_pending) {
    if (!DequeueSourceChangeEvent())
      return;
    if (!RecreateOutputBuffers())
      return;
  }

  EnqueueInput();
  EnqueueOutput();

  if (!running_jobs_.empty()) {
    device_poll_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&V4L2MjpegDecodeAccelerator::DevicePollTask,
                                  base::Unretained(this)));
  }

  DVLOGF(3) << "buffer counts: INPUT[" << input_jobs_.size() << "] => DEVICE["
            << free_input_buffers_.size() << "/" << input_buffer_map_.size()
            << "->" << free_output_buffers_.size() << "/"
            << output_buffer_map_.size() << "]";
}

void V4L2MjpegDecodeAccelerator::EnqueueInput() {
  DCHECK(decoder_task_runner_->BelongsToCurrentThread());
  while (!input_jobs_.empty() && !free_input_buffers_.empty()) {
    // If input buffers are required to re-create, do not enqueue input record
    // until all pending frames are handled by device.
    if (ShouldRecreateInputBuffers())
      break;
    if (!EnqueueInputRecord())
      return;
  }
  // Check here because we cannot STREAMON before QBUF in earlier kernel.
  // (kernel version < 3.14)
  if (!input_streamon_ && InputBufferQueuedCount()) {
    __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type);
    input_streamon_ = true;
  }
}

void V4L2MjpegDecodeAccelerator::EnqueueOutput() {
  DCHECK(decoder_task_runner_->BelongsToCurrentThread());
  // Output record can be enqueued because the output coded sizes of the frames
  // currently in the pipeline are all the same.
  while (running_jobs_.size() > OutputBufferQueuedCount() &&
         !free_output_buffers_.empty()) {
    if (!EnqueueOutputRecord())
      return;
  }
  // Check here because we cannot STREAMON before QBUF in earlier kernel.
  // (kernel version < 3.14)
  if (!output_streamon_ && OutputBufferQueuedCount()) {
    __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type);
    output_streamon_ = true;
  }
}

bool V4L2MjpegDecodeAccelerator::ConvertOutputImage(
    const BufferRecord& output_buffer,
    scoped_refptr<VideoFrame> dst_frame) {
  // The coded size of the hardware buffer should be at least as large as the
  // video frame's visible size.
  const int dst_width = dst_frame->visible_rect().width();
  const int dst_height = dst_frame->visible_rect().height();
  DCHECK_GE(output_buffer_coded_size_.width(), dst_width);
  DCHECK_GE(output_buffer_coded_size_.height(), dst_height);

  // Dmabuf-backed frame needs to be mapped for SW access.
  if (dst_frame->HasDmaBufs()) {
    std::unique_ptr<VideoFrameMapper> frame_mapper =
        VideoFrameMapperFactory::CreateMapper(dst_frame->format(),
                                              VideoFrame::STORAGE_DMABUFS);
    if (!frame_mapper) {
      VLOGF(1) << "Failed to create video frame mapper";
      return false;
    }
    dst_frame = frame_mapper->Map(std::move(dst_frame));
    if (!dst_frame) {
      VLOGF(1) << "Failed to map DMA-buf video frame";
      return false;
    }
  }

  // Extract destination pointers and strides.
  std::array<uint8_t*, VideoFrame::kMaxPlanes> dst_ptrs{};
  std::array<int, VideoFrame::kMaxPlanes> dst_strides{};
  for (size_t i = 0; i < dst_frame->layout().num_planes(); i++) {
    dst_ptrs[i] = dst_frame->visible_data(i);
    dst_strides[i] = base::checked_cast<int>(dst_frame->stride(i));
  }

  // Use ConvertToI420 to convert all splane formats to I420.
  if (output_buffer_num_planes_ == 1 &&
      dst_frame->format() == PIXEL_FORMAT_I420) {
    DCHECK_EQ(dst_frame->layout().num_planes(), 3u);
    const auto format = Fourcc::FromV4L2PixFmt(output_buffer_pixelformat_);
    if (!format) {
      VLOGF(1) << "Unknown V4L2 format: "
               << FourccToString(output_buffer_pixelformat_);
      return false;
    }
    const size_t src_size = VideoFrame::AllocationSize(
        format->ToVideoPixelFormat(), output_buffer_coded_size_);
    if (libyuv::ConvertToI420(
            static_cast<uint8_t*>(output_buffer.address[0]), src_size,
            dst_ptrs[0], dst_strides[0], dst_ptrs[1], dst_strides[1],
            dst_ptrs[2], dst_strides[2], 0 /*x*/, 0 /*y*/,
            output_buffer_coded_size_.width(),
            output_buffer_coded_size_.height(), dst_width, dst_height,
            libyuv::kRotate0, output_buffer_pixelformat_)) {
      VLOGF(1) << "ConvertToI420 failed. Source format: "
               << FourccToString(output_buffer_pixelformat_);
      return false;
    }
    return true;
  }

  // Extract source pointers and strides.
  std::array<const uint8_t*, VideoFrame::kMaxPlanes> src_ptrs{};
  std::array<int, VideoFrame::kMaxPlanes> src_strides{};
  for (size_t i = 0; i < output_buffer_num_planes_; i++) {
    src_ptrs[i] = static_cast<uint8_t*>(output_buffer.address[i]);
    src_strides[i] = output_strides_[i];
  }

  if (output_buffer_pixelformat_ == V4L2_PIX_FMT_YUV420M) {
    DCHECK_EQ(output_buffer_num_planes_, 3u);
    switch (dst_frame->format()) {
      case PIXEL_FORMAT_I420:
        DCHECK_EQ(dst_frame->layout().num_planes(), 3u);
        if (libyuv::I420Copy(src_ptrs[0], src_strides[0], src_ptrs[1],
                             src_strides[1], src_ptrs[2], src_strides[2],
                             dst_ptrs[0], dst_strides[0], dst_ptrs[1],
                             dst_strides[1], dst_ptrs[2], dst_strides[2],
                             dst_width, dst_height)) {
          VLOGF(1) << "I420Copy failed";
          return false;
        }
        break;
      case PIXEL_FORMAT_YV12:
        DCHECK_EQ(dst_frame->layout().num_planes(), 3u);
        if (libyuv::I420Copy(src_ptrs[0], src_strides[0], src_ptrs[1],
                             src_strides[1], src_ptrs[2], src_strides[2],
                             dst_ptrs[0], dst_strides[0], dst_ptrs[2],
                             dst_strides[2], dst_ptrs[1], dst_strides[1],
                             dst_width, dst_height)) {
          VLOGF(1) << "I420Copy failed";
          return false;
        }
        break;
      case PIXEL_FORMAT_NV12:
        DCHECK_EQ(dst_frame->layout().num_planes(), 2u);
        if (libyuv::I420ToNV12(src_ptrs[0], src_strides[0], src_ptrs[1],
                               src_strides[1], src_ptrs[2], src_strides[2],
                               dst_ptrs[0], dst_strides[0], dst_ptrs[1],
                               dst_strides[1], dst_width, dst_height)) {
          VLOGF(1) << "I420ToNV12 failed";
          return false;
        }
        break;
      default:
        VLOGF(1) << "Can't convert image from I420 to " << dst_frame->format();
        return false;
    }
  } else if (output_buffer_pixelformat_ == V4L2_PIX_FMT_YUV422M) {
    DCHECK_EQ(output_buffer_num_planes_, 3u);
    switch (dst_frame->format()) {
      case PIXEL_FORMAT_I420:
        DCHECK_EQ(dst_frame->layout().num_planes(), 3u);
        if (libyuv::I422ToI420(src_ptrs[0], src_strides[0], src_ptrs[1],
                               src_strides[1], src_ptrs[2], src_strides[2],
                               dst_ptrs[0], dst_strides[0], dst_ptrs[1],
                               dst_strides[1], dst_ptrs[2], dst_strides[2],
                               dst_width, dst_height)) {
          VLOGF(1) << "I422ToI420 failed";
          return false;
        }
        break;
      case PIXEL_FORMAT_YV12:
        DCHECK_EQ(dst_frame->layout().num_planes(), 3u);
        if (libyuv::I422ToI420(src_ptrs[0], src_strides[0], src_ptrs[1],
                               src_strides[1], src_ptrs[2], src_strides[2],
                               dst_ptrs[0], dst_strides[0], dst_ptrs[2],
                               dst_strides[2], dst_ptrs[1], dst_strides[1],
                               dst_width, dst_height)) {
          VLOGF(1) << "I422ToI420 failed";
          return false;
        }
        break;
      case PIXEL_FORMAT_NV12:
        DCHECK_EQ(dst_frame->layout().num_planes(), 2u);
        if (libyuv::I422ToNV21(src_ptrs[0], src_strides[0], src_ptrs[2],
                               src_strides[2], src_ptrs[1], src_strides[1],
                               dst_ptrs[0], dst_strides[0], dst_ptrs[1],
                               dst_strides[1], dst_width, dst_height)) {
          VLOGF(1) << "I422ToNV21 failed";
          return false;
        }
        break;
      default:
        VLOGF(1) << "Can't convert image from I422 to " << dst_frame->format();
        return false;
    }
  } else {
    VLOGF(1) << "Unsupported source buffer format: "
             << FourccToString(output_buffer_pixelformat_);
    return false;
  }
  return true;
}

void V4L2MjpegDecodeAccelerator::Dequeue() {
  DCHECK(decoder_task_runner_->BelongsToCurrentThread());

  // Dequeue completed input (VIDEO_OUTPUT) buffers,
  // and recycle to the free list.
  struct v4l2_buffer dqbuf;
  struct v4l2_plane planes[VIDEO_MAX_PLANES];
  while (InputBufferQueuedCount() > 0) {
    DCHECK(input_streamon_);
    memset(&dqbuf, 0, sizeof(dqbuf));
    memset(planes, 0, sizeof(planes));
    dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    dqbuf.memory = V4L2_MEMORY_MMAP;
    dqbuf.length = base::size(planes);
    dqbuf.m.planes = planes;
    if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
      if (errno == EAGAIN) {
        // EAGAIN if we're just out of buffers to dequeue.
        break;
      }
      VPLOGF(1) << "ioctl() failed: input buffer VIDIOC_DQBUF failed.";
      PostNotifyError(kInvalidTaskId, PLATFORM_FAILURE);
      return;
    }
    BufferRecord& input_record = input_buffer_map_[dqbuf.index];
    DCHECK(input_record.at_device);
    input_record.at_device = false;
    free_input_buffers_.push_back(dqbuf.index);

    if (dqbuf.flags & V4L2_BUF_FLAG_ERROR) {
      VLOGF(1) << "Error in dequeued input buffer.";
      PostNotifyError(kInvalidTaskId, UNSUPPORTED_JPEG);
      running_jobs_.pop();
    }
  }

  // Dequeue completed output (VIDEO_CAPTURE) buffers, recycle to the free list.
  // Return the finished buffer to the client via the job ready callback.
  // If dequeued input buffer has an error, the error frame has removed from
  // |running_jobs_|. We only have to dequeue output buffer when we actually
  // have pending frames in |running_jobs_| and also enqueued output buffers.
  while (!running_jobs_.empty() && OutputBufferQueuedCount() > 0) {
    DCHECK(output_streamon_);
    memset(&dqbuf, 0, sizeof(dqbuf));
    memset(planes, 0, sizeof(planes));
    dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    // From experiments, using MMAP and memory copy is still faster than
    // USERPTR. Also, client doesn't need to consider the buffer alignment and
    // MjpegDecodeAccelerator API will be simpler.
    dqbuf.memory = V4L2_MEMORY_MMAP;
    dqbuf.length = base::size(planes);
    dqbuf.m.planes = planes;
    if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
      if (errno == EAGAIN) {
        // EAGAIN if we're just out of buffers to dequeue.
        break;
      }
      VPLOGF(1) << "ioctl() failed: output buffer VIDIOC_DQBUF failed.";
      PostNotifyError(kInvalidTaskId, PLATFORM_FAILURE);
      return;
    }
    BufferRecord& output_record = output_buffer_map_[dqbuf.index];
    DCHECK(output_record.at_device);
    output_record.at_device = false;
    free_output_buffers_.push_back(dqbuf.index);

    // Jobs are always processed in FIFO order.
    std::unique_ptr<JobRecord> job_record = std::move(running_jobs_.front());
    running_jobs_.pop();

    if (dqbuf.flags & V4L2_BUF_FLAG_ERROR) {
      VLOGF(1) << "Error in dequeued output buffer.";
      PostNotifyError(kInvalidTaskId, UNSUPPORTED_JPEG);
    } else {
      // Copy the decoded data from output buffer to the buffer provided by the
      // client. Do format conversion when output format is not
      // V4L2_PIX_FMT_YUV420.
      if (!ConvertOutputImage(output_record, job_record->out_frame())) {
        PostNotifyError(job_record->task_id(), PLATFORM_FAILURE);
        return;
      }
      DVLOGF(4) << "Decoding finished, returning bitstream buffer, id="
                << job_record->task_id();

      // Destroy |job_record| before posting VideoFrameReady to the client to
      // prevent race condition on the buffers.
      const int32_t task_id = job_record->task_id();
      job_record.reset();
      child_task_runner_->PostTask(
          FROM_HERE,
          base::BindOnce(&V4L2MjpegDecodeAccelerator::VideoFrameReady,
                         weak_ptr_, task_id));
    }
  }
}

static bool AddHuffmanTable(const void* input_ptr,
                            size_t input_size,
                            void* output_ptr,
                            size_t output_size) {
  DCHECK(input_ptr);
  DCHECK(output_ptr);
  DCHECK_LE((input_size + sizeof(kDefaultDhtSeg)), output_size);

  base::BigEndianReader reader(static_cast<const char*>(input_ptr), input_size);
  bool has_marker_dht = false;
  bool has_marker_sos = false;
  uint8_t marker1, marker2;
  READ_U8_OR_RETURN_FALSE(reader, &marker1);
  READ_U8_OR_RETURN_FALSE(reader, &marker2);
  if (marker1 != JPEG_MARKER_PREFIX || marker2 != JPEG_SOI) {
    DVLOGF(1) << "The input is not a Jpeg";
    return false;
  }

  // copy SOI marker (0xFF, 0xD8)
  memcpy(output_ptr, input_ptr, 2);
  size_t current_offset = 2;

  while (!has_marker_sos && !has_marker_dht) {
    const char* start_addr = reader.ptr();
    READ_U8_OR_RETURN_FALSE(reader, &marker1);
    if (marker1 != JPEG_MARKER_PREFIX) {
      DVLOGF(1) << "marker1 != 0xFF";
      return false;
    }
    do {
      READ_U8_OR_RETURN_FALSE(reader, &marker2);
    } while (marker2 == JPEG_MARKER_PREFIX);  // skip fill bytes

    uint16_t size;
    READ_U16_OR_RETURN_FALSE(reader, &size);
    // The size includes the size field itself.
    if (size < sizeof(size)) {
      DVLOGF(1) << ": Ill-formed JPEG. Segment size (" << size
                << ") is smaller than size field (" << sizeof(size) << ")";
      return false;
    }
    size -= sizeof(size);

    switch (marker2) {
      case JPEG_DHT: {
        has_marker_dht = true;
        break;
      }
      case JPEG_SOS: {
        if (!has_marker_dht) {
          memcpy(static_cast<uint8_t*>(output_ptr) + current_offset,
                 kDefaultDhtSeg, sizeof(kDefaultDhtSeg));
          current_offset += sizeof(kDefaultDhtSeg);
        }
        has_marker_sos = true;
        break;
      }
      default:
        break;
    }

    if (!reader.Skip(size)) {
      DVLOGF(1) << "Ill-formed JPEG. Remaining size (" << reader.remaining()
                << ") is smaller than header specified (" << size << ")";
      return false;
    }

    size_t segment_size = static_cast<size_t>(reader.ptr() - start_addr);
    memcpy(static_cast<uint8_t*>(output_ptr) + current_offset, start_addr,
           segment_size);
    current_offset += segment_size;
  }
  if (reader.remaining()) {
    memcpy(static_cast<uint8_t*>(output_ptr) + current_offset, reader.ptr(),
           reader.remaining());
  }
  return true;
}

bool V4L2MjpegDecodeAccelerator::EnqueueInputRecord() {
  DCHECK(!input_jobs_.empty());
  DCHECK(!free_input_buffers_.empty());

  // Enqueue an input (VIDEO_OUTPUT) buffer for an input video frame.
  std::unique_ptr<JobRecord> job_record = std::move(input_jobs_.front());
  input_jobs_.pop();
  const int index = free_input_buffers_.back();
  BufferRecord& input_record = input_buffer_map_[index];
  DCHECK(!input_record.at_device);

  // It will add default huffman segment if it's missing.
  if (!AddHuffmanTable(job_record->memory(), job_record->size(),
                       input_record.address[0], input_record.length[0])) {
    PostNotifyError(job_record->task_id(), PARSE_JPEG_FAILED);
    return false;
  }

  struct v4l2_buffer qbuf;
  struct v4l2_plane planes[VIDEO_MAX_PLANES];
  memset(&qbuf, 0, sizeof(qbuf));
  memset(planes, 0, sizeof(planes));
  qbuf.index = index;
  qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
  qbuf.memory = V4L2_MEMORY_MMAP;
  qbuf.length = base::size(planes);
  // There is only one plane for V4L2_PIX_FMT_JPEG.
  planes[0].bytesused = input_record.length[0];
  qbuf.m.planes = planes;
  IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
  input_record.at_device = true;

  DVLOGF(3) << "enqueued frame id=" << job_record->task_id() << " to device.";
  running_jobs_.push(std::move(job_record));
  free_input_buffers_.pop_back();
  return true;
}

bool V4L2MjpegDecodeAccelerator::EnqueueOutputRecord() {
  DCHECK(!free_output_buffers_.empty());
  DCHECK_GT(output_buffer_num_planes_, 0u);

  // Enqueue an output (VIDEO_CAPTURE) buffer.
  const int index = free_output_buffers_.back();
  BufferRecord& output_record = output_buffer_map_[index];
  DCHECK(!output_record.at_device);
  struct v4l2_buffer qbuf;
  struct v4l2_plane planes[VIDEO_MAX_PLANES];
  memset(&qbuf, 0, sizeof(qbuf));
  memset(planes, 0, sizeof(planes));
  qbuf.index = index;
  qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
  qbuf.memory = V4L2_MEMORY_MMAP;
  qbuf.length = base::size(planes);
  qbuf.m.planes = planes;
  IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
  output_record.at_device = true;
  free_output_buffers_.pop_back();
  return true;
}

void V4L2MjpegDecodeAccelerator::StartDevicePoll() {
  DVLOGF(3) << ": starting device poll";
  DCHECK(decoder_task_runner_->BelongsToCurrentThread());
  DCHECK(!device_poll_thread_.IsRunning());

  if (!device_poll_thread_.Start()) {
    VLOGF(1) << "Device thread failed to start";
    PostNotifyError(kInvalidTaskId, PLATFORM_FAILURE);
    return;
  }
  device_poll_task_runner_ = device_poll_thread_.task_runner();
}

bool V4L2MjpegDecodeAccelerator::StopDevicePoll() {
  DVLOGF(3) << "stopping device poll";
  // Signal the DevicePollTask() to stop, and stop the device poll thread.
  if (!device_->SetDevicePollInterrupt()) {
    VLOGF(1) << "SetDevicePollInterrupt failed.";
    PostNotifyError(kInvalidTaskId, PLATFORM_FAILURE);
    return false;
  }

  device_poll_thread_.Stop();

  // Clear the interrupt now, to be sure.
  if (!device_->ClearDevicePollInterrupt())
    return false;

  return true;
}

}  // namespace media
