1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
|
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_V4L2_V4L2_MJPEG_DECODE_ACCELERATOR_H_
#define MEDIA_GPU_V4L2_V4L2_MJPEG_DECODE_ACCELERATOR_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <vector>
#include "base/containers/queue.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/threading/thread.h"
#include "components/chromeos_camera/mjpeg_decode_accelerator.h"
#include "media/gpu/media_gpu_export.h"
#include "media/gpu/v4l2/v4l2_device.h"
namespace base {
class SingleThreadTaskRunner;
class SequencedTaskRunner;
} // namespace base
namespace media {
class VideoFrame;
class MEDIA_GPU_EXPORT V4L2MjpegDecodeAccelerator
: public chromeos_camera::MjpegDecodeAccelerator {
public:
// Job record. Jobs are processed in a FIFO order. This is separate from
// BufferRecord of input, because a BufferRecord of input may be returned
// before we dequeue the corresponding output buffer. It can't always be
// associated with a BufferRecord of output immediately either, because at
// the time of submission we may not have one available (and don't need one
// to submit input to the device).
class JobRecord;
V4L2MjpegDecodeAccelerator(
const scoped_refptr<V4L2Device>& device,
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
V4L2MjpegDecodeAccelerator(const V4L2MjpegDecodeAccelerator&) = delete;
V4L2MjpegDecodeAccelerator& operator=(const V4L2MjpegDecodeAccelerator&) =
delete;
~V4L2MjpegDecodeAccelerator() override;
// MjpegDecodeAccelerator implementation.
void InitializeAsync(
chromeos_camera::MjpegDecodeAccelerator::Client* client,
chromeos_camera::MjpegDecodeAccelerator::InitCB init_cb) override;
void Decode(BitstreamBuffer bitstream_buffer,
scoped_refptr<VideoFrame> video_frame) override;
void Decode(int32_t task_id,
base::ScopedFD src_dmabuf_fd,
size_t src_size,
off_t src_offset,
scoped_refptr<media::VideoFrame> dst_frame) override;
bool IsSupported() override;
private:
// Record for input/output buffers.
struct BufferRecord {
BufferRecord() = default;
~BufferRecord() = default;
void* address[VIDEO_MAX_PLANES] = {}; // mmap() address.
size_t length[VIDEO_MAX_PLANES] = {}; // mmap() length.
// Set true during QBUF and DQBUF. |address| will be accessed by hardware.
bool at_device = false;
};
void EnqueueInput();
void EnqueueOutput();
void Dequeue();
bool EnqueueInputRecord();
bool EnqueueOutputRecord();
bool CreateInputBuffers();
bool CreateOutputBuffers();
void DestroyInputBuffers();
void DestroyOutputBuffers();
void InitializeOnDecoderTaskRunner(
chromeos_camera::MjpegDecodeAccelerator::Client* client,
InitCB init_cb);
// Convert |output_buffer| to |dst_frame|. The function supports the following
// formats:
// - All formats that libyuv::ConvertToI420 can handle.
// - V4L2_PIX_FMT_YUV_420M, V4L2_PIX_FMT_YUV_422M to I420, YV12, and NV12.
bool ConvertOutputImage(const BufferRecord& output_buffer,
scoped_refptr<VideoFrame> dst_frame);
// Return the number of input/output buffers enqueued to the device.
size_t InputBufferQueuedCount();
size_t OutputBufferQueuedCount();
// Return true if input buffer size is not enough.
bool ShouldRecreateInputBuffers();
// Destroy and create input buffers. Return false on error.
bool RecreateInputBuffers();
// Destroy and create output buffers. Return false on error.
bool RecreateOutputBuffers();
void VideoFrameReady(int32_t task_id);
void NotifyError(int32_t task_id, Error error);
void PostNotifyError(int32_t task_id, Error error);
// Run on |decoder_task_runner_| to enqueue the coming frame.
void DecodeTask(std::unique_ptr<JobRecord> job_record);
// Run on |decoder_task_runner_| to dequeue last frame and enqueue next frame.
// This task is triggered by DevicePollTask. |event_pending| means that device
// has resolution change event or pixelformat change event.
void ServiceDeviceTask(bool event_pending);
// Dequeue source change event. Return false on error.
bool DequeueSourceChangeEvent();
// Start/Stop |device_poll_thread_|.
void StartDevicePoll();
bool StopDevicePoll();
// Run on |device_poll_thread_| to wait for device events.
void DevicePollTask();
// Run on |decoder_task_runner_| to destroy input and output buffers.
void DestroyTask(base::WaitableEvent* waiter);
// The number of input buffers and output buffers.
const size_t kBufferCount = 2;
// Coded size of output buffer.
gfx::Size output_buffer_coded_size_ GUARDED_BY_CONTEXT(decoder_sequence_);
// Pixel format of output buffer.
uint32_t output_buffer_pixelformat_ GUARDED_BY_CONTEXT(decoder_sequence_);
// Number of physical planes the output buffers have.
size_t output_buffer_num_planes_ GUARDED_BY_CONTEXT(decoder_sequence_);
// Strides of the output buffers.
size_t output_strides_[VIDEO_MAX_PLANES] GUARDED_BY_CONTEXT(
decoder_sequence_);
// GPU IO task runner.
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
// The client of this class.
chromeos_camera::MjpegDecodeAccelerator::Client* client_;
// The V4L2Device this class is operating upon. This is accessed on
// |decoder_task_runner_| and |device_poll_task_runner_|.
scoped_refptr<V4L2Device> device_;
// Decode task runner.
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner_;
// Thread used to poll the V4L2 for events only.
base::Thread device_poll_thread_ GUARDED_BY_CONTEXT(decoder_sequence_);
// Device poll task runner.
scoped_refptr<base::SingleThreadTaskRunner> device_poll_task_runner_;
// All the below members except |weak_factory_| are accessed from
// |decoder_task_runner_| only (if it's running).
base::queue<std::unique_ptr<JobRecord>> input_jobs_
GUARDED_BY_CONTEXT(decoder_sequence_);
base::queue<std::unique_ptr<JobRecord>> running_jobs_
GUARDED_BY_CONTEXT(decoder_sequence_);
// Input queue state.
bool input_streamon_ GUARDED_BY_CONTEXT(decoder_sequence_);
// Mapping of int index to an input buffer record.
std::vector<BufferRecord> input_buffer_map_
GUARDED_BY_CONTEXT(decoder_sequence_);
// Indices of input buffers ready to use; LIFO since we don't care about
// ordering.
std::vector<int> free_input_buffers_ GUARDED_BY_CONTEXT(decoder_sequence_);
// Output queue state.
bool output_streamon_ GUARDED_BY_CONTEXT(decoder_sequence_);
// Mapping of int index to an output buffer record.
std::vector<BufferRecord> output_buffer_map_
GUARDED_BY_CONTEXT(decoder_sequence_);
// Indices of output buffers ready to use; LIFO since we don't care about
// ordering.
std::vector<int> free_output_buffers_ GUARDED_BY_CONTEXT(decoder_sequence_);
SEQUENCE_CHECKER(decoder_sequence_);
// Point to |this| for use in posting tasks to |decoder_task_runner_|.
// |weak_ptr_for_decoder_| is required, even though we synchronously destroy
// variables on |decoder_task_runner_| in destructor, because a task can
// be posted to |decoder_task_runner_| within DestroyTask().
base::WeakPtr<V4L2MjpegDecodeAccelerator> weak_ptr_for_decoder_;
base::WeakPtrFactory<V4L2MjpegDecodeAccelerator> weak_factory_for_decoder_;
// Point to |this| for use in posting tasks from the decoder thread back to
// |io_task_runner_|.
base::WeakPtr<V4L2MjpegDecodeAccelerator> weak_ptr_;
base::WeakPtrFactory<V4L2MjpegDecodeAccelerator> weak_factory_;
};
} // namespace media
#endif // MEDIA_GPU_V4L2_V4L2_MJPEG_DECODE_ACCELERATOR_H_
|