blob: 5b8069d31a8340d8a1b0be521ba6eb1f1c28f2e6 (
plain)
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
|
// Copyright 2014 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.
#ifndef CONTENT_COMMON_GPU_MEDIA_V4L2_IMAGE_PROCESSOR_H_
#define CONTENT_COMMON_GPU_MEDIA_V4L2_IMAGE_PROCESSOR_H_
#include <queue>
#include <vector>
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
#include "content/common/gpu/media/v4l2_device.h"
#include "media/base/video_frame.h"
namespace content {
// Handles image processing accelerators that expose a V4L2 memory-to-memory
// interface. The threading model of this class is the same as for other V4L2
// hardware accelerators (see V4L2VideoDecodeAccelerator) for more details.
class CONTENT_EXPORT V4L2ImageProcessor {
public:
explicit V4L2ImageProcessor(const scoped_refptr<V4L2Device>& device);
virtual ~V4L2ImageProcessor();
// Initializes the processor to convert from |input_format| to |output_format|
// and/or scale from |input_visible_size| to |output_visible_size|.
// Request the output buffers to be of at least |output_allocated_size|.
// Provided |error_cb| will be called if an error occurs.
// Return true if the requested configuration is supported.
bool Initialize(media::VideoFrame::Format input_format,
media::VideoFrame::Format output_format,
gfx::Size input_visible_size,
gfx::Size output_visible_size,
gfx::Size output_allocated_size,
const base::Closure& error_cb);
// Returns allocated size required by the processor to be fed with.
gfx::Size input_allocated_size() { return input_allocated_size_; }
// Callback to be used to return a processed image to the client. The client
// should drop references to |frame| once it's done with it.
typedef base::Callback<void(const scoped_refptr<media::VideoFrame>& frame)>
FrameReadyCB;
// Called by client to process |frame|. The resulting processed frame will
// be returned via |cb|. The processor will drop all its references to |frame|
// after it finishes accessing it.
void Process(const scoped_refptr<media::VideoFrame>& frame,
const FrameReadyCB& cb);
// Stop all processing and clean up.
void Destroy();
private:
// Record for input buffers.
struct InputRecord {
InputRecord();
~InputRecord();
scoped_refptr<media::VideoFrame> frame;
bool at_device;
};
// Record for output buffers.
struct OutputRecord {
OutputRecord();
~OutputRecord();
bool at_device;
bool at_client;
std::vector<int> fds;
};
// Job record. Jobs are processed in a FIFO order. This is separate from
// InputRecord, because an InputRecord may be returned before we dequeue
// the corresponding output buffer. It can't always be associated with
// an OutputRecord 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).
struct JobRecord {
JobRecord();
~JobRecord();
scoped_refptr<media::VideoFrame> frame;
FrameReadyCB ready_cb;
};
enum {
// Arbitrarily tuned.
kInputBufferCount = 2,
kOutputBufferCount = 2,
};
void ReuseOutputBuffer(int index);
void Enqueue();
void Dequeue();
bool EnqueueInputRecord();
bool EnqueueOutputRecord();
bool CreateInputBuffers();
bool CreateOutputBuffers();
void DestroyInputBuffers();
void DestroyOutputBuffers();
void NotifyError();
void DestroyTask();
void ProcessTask(scoped_ptr<JobRecord> job_record);
void ServiceDeviceTask();
// Attempt to start/stop device_poll_thread_.
bool StartDevicePoll();
bool StopDevicePoll();
// Ran on device_poll_thread_ to wait for device events.
void DevicePollTask(bool poll_device);
// Size and format-related members remain constant after initialization.
// The visible/allocated sizes of the input frame.
gfx::Size input_visible_size_;
gfx::Size input_allocated_size_;
// The visible/allocated sizes of the destination frame.
gfx::Size output_visible_size_;
gfx::Size output_allocated_size_;
media::VideoFrame::Format input_format_;
media::VideoFrame::Format output_format_;
uint32 input_format_fourcc_;
uint32 output_format_fourcc_;
size_t input_planes_count_;
size_t output_planes_count_;
// Our original calling task runner for the child thread.
const scoped_refptr<base::SingleThreadTaskRunner> child_task_runner_;
// V4L2 device in use.
scoped_refptr<V4L2Device> device_;
// Thread to communicate with the device on.
base::Thread device_thread_;
// Thread used to poll the V4L2 for events only.
base::Thread device_poll_thread_;
// All the below members are to be accessed from device_thread_ only
// (if it's running).
std::queue<linked_ptr<JobRecord> > input_queue_;
std::queue<linked_ptr<JobRecord> > running_jobs_;
// Input queue state.
bool input_streamon_;
// Number of input buffers enqueued to the device.
int input_buffer_queued_count_;
// Input buffers ready to use; LIFO since we don't care about ordering.
std::vector<int> free_input_buffers_;
// Mapping of int index to an input buffer record.
std::vector<InputRecord> input_buffer_map_;
// Output queue state.
bool output_streamon_;
// Number of output buffers enqueued to the device.
int output_buffer_queued_count_;
// Output buffers ready to use; LIFO since we don't care about ordering.
std::vector<int> free_output_buffers_;
// Mapping of int index to an output buffer record.
std::vector<OutputRecord> output_buffer_map_;
// Error callback to the client.
base::Closure error_cb_;
// Weak factory for producing weak pointers on the device_thread_
base::WeakPtrFactory<V4L2ImageProcessor> device_weak_factory_;
DISALLOW_COPY_AND_ASSIGN(V4L2ImageProcessor);
};
} // namespace content
#endif // CONTENT_COMMON_GPU_MEDIA_V4L2_IMAGE_PROCESSOR_H_
|