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

Side by Side Diff: content/common/gpu/media/gpu_jpeg_decode_accelerator.cc

Issue 1016773002: MJPEG acceleration for video capture using VAAPI (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix many thread issues Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/common/gpu/media/gpu_jpeg_decode_accelerator.h"
6
7 #include <stdint.h>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/logging.h"
13 #include "base/message_loop/message_loop_proxy.h"
14 #include "base/stl_util.h"
15 #include "content/common/gpu/gpu_channel.h"
16 #include "content/common/gpu/gpu_messages.h"
17 #include "content/public/common/content_switches.h"
18 #include "gpu/command_buffer/common/command_buffer.h"
19 #include "ipc/ipc_message_macros.h"
20 #include "ipc/ipc_message_utils.h"
21 #include "ipc/message_filter.h"
22 #include "media/base/limits.h"
23 #include "media/filters/jpeg_parser.h"
24
25 #if defined(OS_WIN)
26 #elif defined(OS_MACOSX)
27 #elif defined(OS_CHROMEOS)
28 #if defined(ARCH_CPU_ARMEL)
29 //#include "content/common/gpu/media/v4l2_jpeg_decode_accelerator.h"
30 //#include "content/common/gpu/media/v4l2_jpeg_device.h"
31 #endif // defined(ARCH_CPU_ARMEL)
32 #if defined(ARCH_CPU_X86_FAMILY)
33 #include "content/common/gpu/media/vaapi_jpeg_decode_accelerator.h"
34 #endif // defined(ARCH_CPU_X86_FAMILY)
35 #elif defined(USE_OZONE)
36 #elif defined(OS_ANDROID)
37 #endif
38
39 #include "ui/gfx/geometry/size.h"
40
41 namespace base {
42
43 void DefaultDeleter<content::GpuJpegDecodeAccelerator>::operator()(
44 void* jpeg_decode_accelerator) const {
45 static_cast<content::GpuJpegDecodeAccelerator*>(jpeg_decode_accelerator)->
46 Destroy();
47 }
48
49 } // namespace base
50 namespace content {
51
52 class GpuJpegDecodeAccelerator::MessageFilter : public IPC::MessageFilter {
53 public:
54 MessageFilter(GpuJpegDecodeAccelerator* owner, int32 host_route_id)
55 : owner_(owner), host_route_id_(host_route_id) {}
56
57 void OnChannelError() override { sender_ = NULL; }
58
59 void OnChannelClosing() override { sender_ = NULL; }
60
61 void OnFilterAdded(IPC::Sender* sender) override {
62 sender_ = sender;
63 }
64
65 void OnFilterRemoved() override {
66 // This will delete |owner_| and |this|.
67 owner_->OnFilterRemoved();
68 }
69
70 bool OnMessageReceived(const IPC::Message& msg) override {
71 if (msg.routing_id() != host_route_id_)
72 return false;
73 DVLOG(3) << __func__;
74
75 IPC_BEGIN_MESSAGE_MAP(MessageFilter, msg)
76 IPC_MESSAGE_FORWARD(AcceleratedJpegDecoderMsg_Decode, owner_,
77 GpuJpegDecodeAccelerator::OnDecode)
78 IPC_MESSAGE_UNHANDLED(return false;)
79 IPC_END_MESSAGE_MAP()
80 return true;
81 }
82
83 bool SendOnIOThread(IPC::Message* message) {
84 DCHECK(!message->is_sync());
85 if (!sender_) {
86 delete message;
87 return false;
88 }
89 return sender_->Send(message);
90 }
91
92 protected:
93 virtual ~MessageFilter() {}
94
95 private:
96 GpuJpegDecodeAccelerator* owner_;
97 int32 host_route_id_;
98 // The sender to which this filter was added.
99 IPC::Sender* sender_;
100 };
101
102 GpuJpegDecodeAccelerator::GpuJpegDecodeAccelerator(
103 GpuChannel* channel,
104 int32 host_route_id,
105 const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
106 : channel_(channel),
107 host_route_id_(host_route_id),
108 filter_removed_(true, false),
109 io_message_loop_(io_message_loop) {
110 child_message_loop_ = base::MessageLoopProxy::current();
111 }
112
113 GpuJpegDecodeAccelerator::~GpuJpegDecodeAccelerator() {
114 }
115
116 bool GpuJpegDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) {
117 bool handled = true;
118 IPC_BEGIN_MESSAGE_MAP(GpuJpegDecodeAccelerator, msg)
119 #if 0
120 IPC_MESSAGE_HANDLER(AcceleratedJpegDecoderMsg_Decode, OnDecode)
121 #endif
122 #if 1
123 IPC_MESSAGE_HANDLER(AcceleratedJpegDecoderMsg_Destroy, OnDestroy)
124 #endif
125 IPC_MESSAGE_UNHANDLED(handled = false)
126 IPC_END_MESSAGE_MAP()
127 return handled;
128 }
129
130 bool GpuJpegDecodeAccelerator::Initialize() {
131 DVLOG(3) << __func__;
132 DCHECK(child_message_loop_->BelongsToCurrentThread());
133 DCHECK(!jpeg_decode_accelerator_.get());
134
135 if (!channel_->AddRoute(host_route_id_, this)) {
136 DLOG(ERROR) << "GpuJpegDecodeAccelerator::Initialize(): "
137 "failed to add route";
138 return false;
139 }
140
141 filter_ = new MessageFilter(this, host_route_id_);
142 channel_->AddFilter(filter_.get());
143
144 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
145 jpeg_decode_accelerator_.reset(
146 new VaapiJpegDecodeAccelerator());
147 #else
148 NOTIMPLEMENTED() << "HW JPEG decode acceleration not available.";
149 return false;
150 #endif
151
152 if (!jpeg_decode_accelerator_->Initialize(this)) {
153 return false;
154 }
155 return true;
156 }
157
158 void GpuJpegDecodeAccelerator::NotifyError(
159 int32_t buffer_id,
160 media::JpegDecodeAccelerator::Error error) {
161 DVLOG(3) << __func__;
162 Send(new AcceleratedJpegDecoderHostMsg_NotifyError(
163 host_route_id_, buffer_id, error));
164 }
165
166 void GpuJpegDecodeAccelerator::VideoFrameReady(int32_t bitstream_buffer_id) {
167 DVLOG(3) << __func__;
168 // This is called from JDA's decode thread.
169 Send(new AcceleratedJpegDecoderHostMsg_VideoFrameReady(
170 host_route_id_, bitstream_buffer_id));
171 }
172
173 void DecodeFinished(scoped_ptr<base::SharedMemory> shm) {
174 // Do nothing. The purpose of this function is just to keep life-cycle of
175 // SharedMemory as VideoFrame
176 DVLOG(3) << "DecodeFinished";
177 }
178
179 void GpuJpegDecodeAccelerator::OnDecode(
180 const AcceleratedJpegDecoderMsg_Decode_Params& params) {
181 DVLOG(3) << __func__;
182 DCHECK(io_message_loop_->BelongsToCurrentThread());
183 DCHECK(jpeg_decode_accelerator_.get());
184
185 if (params.input_buffer_id < 0) {
186 DLOG(ERROR) << "BitstreamBuffer id " << params.input_buffer_id << " out of r ange";
187 NotifyError(params.input_buffer_id,
188 media::JpegDecodeAccelerator::INVALID_ARGUMENT);
189 return;
190 }
191
192 media::BitstreamBuffer input_buffer(params.input_buffer_id,
193 params.input_buffer_handle,
194 params.input_buffer_size);
195
196 scoped_ptr<base::SharedMemory> output_shm(
197 new base::SharedMemory(params.output_video_frame_handle, false));
198 if (!output_shm->Map(params.output_buffer_size)) {
199 DLOG(ERROR) << "Could not map output shared memory for input buffer id "
200 << params.input_buffer_id;
201 NotifyError(params.input_buffer_id,
202 media::JpegDecodeAccelerator::PLATFORM_FAILURE);
203 return;
204 }
205
206 uint8* shm_memory = reinterpret_cast<uint8*>(output_shm->memory());
207 scoped_refptr<media::VideoFrame> frame =
208 media::VideoFrame::WrapExternalPackedMemory(
209 media::VideoFrame::I420,
210 params.coded_size,
211 gfx::Rect(params.coded_size),
212 params.coded_size,
213 shm_memory,
214 params.output_buffer_size,
215 params.output_video_frame_handle,
216 0,
217 base::TimeDelta(),
218 base::Bind(DecodeFinished,
219 base::Passed(&output_shm)));
220
221 if (!frame.get()) {
222 DLOG(ERROR) << "Could not create VideoFrame for input buffer id "
223 << params.input_buffer_id;
224 NotifyError(params.input_buffer_id,
225 media::JpegDecodeAccelerator::PLATFORM_FAILURE);
226 return;
227 }
228
229 jpeg_decode_accelerator_->Decode(input_buffer, frame);
230 }
231
232 void GpuJpegDecodeAccelerator::OnDestroy() {
233 DVLOG(3) << __func__;
234 DCHECK(jpeg_decode_accelerator_.get());
235 Destroy();
236 }
237
238 void GpuJpegDecodeAccelerator::OnFilterRemoved() {
239 // We're destroying; cancel all callbacks.
240 filter_removed_.Signal();
241 }
242
243 void GpuJpegDecodeAccelerator::Destroy() {
244 // We cannot destroy the JDA before the IO thread message filter is
245 // removed however, since we cannot service incoming messages with JDA gone.
246 // We cannot simply check for existence of VDA on IO thread though, because
247 // we don't want to synchronize the IO thread with the ChildThread.
248 // So we have to wait for the RemoveFilter callback here instead and remove
249 // the VDA after it arrives and before returning.
250 if (filter_.get()) {
251 channel_->RemoveFilter(filter_.get());
252 filter_removed_.Wait();
253 }
254
255 channel_->RemoveRoute(host_route_id_);
256 channel_->ReleaseJpegDecoder();
257 jpeg_decode_accelerator_.reset();
258
259 delete this;
260 }
261
262 bool GpuJpegDecodeAccelerator::Send(IPC::Message* message) {
263 if (filter_.get() && io_message_loop_->BelongsToCurrentThread())
264 return filter_->SendOnIOThread(message);
265 return channel_->Send(message);
266 }
267
268 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698