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

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 coded size, shm handle Created 5 years, 9 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 // XXX
42 #undef DLOG
43 #define DLOG LOG
44 namespace content {
45
46 // DebugAutoLock works like AutoLock but only acquires the lock when
47 // DCHECK is on.
48 #if DCHECK_IS_ON
49 typedef base::AutoLock DebugAutoLock;
50 #else
51 class DebugAutoLock {
52 public:
53 explicit DebugAutoLock(base::Lock&) {}
54 };
55 #endif
56
57 class GpuJpegDecodeAccelerator::MessageFilter : public IPC::MessageFilter {
58 public:
59 MessageFilter(GpuJpegDecodeAccelerator* owner, int32 host_route_id)
60 : owner_(owner), host_route_id_(host_route_id) {}
61
62 void OnChannelError() override { sender_ = NULL; }
63
64 void OnChannelClosing() override { sender_ = NULL; }
65
66 void OnFilterAdded(IPC::Sender* sender) override {
67 sender_ = sender;
68 }
69
70 void OnFilterRemoved() override {
71 // This will delete |owner_| and |this|.
72 owner_->OnFilterRemoved();
73 }
74
75 bool OnMessageReceived(const IPC::Message& msg) override {
76 if (msg.routing_id() != host_route_id_)
77 return false;
78 LOG(ERROR) << __func__;
79
80 IPC_BEGIN_MESSAGE_MAP(MessageFilter, msg)
81 IPC_MESSAGE_FORWARD(AcceleratedJpegDecoderMsg_Decode, owner_,
82 GpuJpegDecodeAccelerator::OnDecode)
83 IPC_MESSAGE_UNHANDLED(return false;)
84 IPC_END_MESSAGE_MAP()
85 return true;
86 }
87
88 bool SendOnIOThread(IPC::Message* message) {
89 DCHECK(!message->is_sync());
90 if (!sender_) {
91 delete message;
92 return false;
93 }
94 return sender_->Send(message);
95 }
96
97 protected:
98 virtual ~MessageFilter() {}
99
100 private:
101 GpuJpegDecodeAccelerator* owner_;
102 int32 host_route_id_;
103 // The sender to which this filter was added.
104 IPC::Sender* sender_;
105 };
106
107 GpuJpegDecodeAccelerator::GpuJpegDecodeAccelerator(
108 GpuChannel* channel,
109 int32 host_route_id,
110 const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
111 : channel_(channel),
112 host_route_id_(host_route_id),
113 filter_removed_(true, false),
114 io_message_loop_(io_message_loop)
115 /*,
116 weak_factory_for_io_(this)*/ {
117 child_message_loop_ = base::MessageLoopProxy::current();
118 }
119
120 GpuJpegDecodeAccelerator::~GpuJpegDecodeAccelerator() {
121 // This class can only be self-deleted from OnWillDestroyStub(), which means
122 // the VDA has already been destroyed in there.
123 DCHECK(!jpeg_decode_accelerator_);
124 }
125
126 bool GpuJpegDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) {
127 bool handled = true;
128 IPC_BEGIN_MESSAGE_MAP(GpuJpegDecodeAccelerator, msg)
129 IPC_MESSAGE_HANDLER(AcceleratedJpegDecoderMsg_Decode, OnDecode)
130 IPC_MESSAGE_HANDLER(AcceleratedJpegDecoderMsg_Destroy, OnDestroy)
131 IPC_MESSAGE_UNHANDLED(handled = false)
132 IPC_END_MESSAGE_MAP()
133 return handled;
134 }
135
136 bool GpuJpegDecodeAccelerator::Initialize() {
wuchengli 2015/03/23 06:30:15 DCHECK this runs on child_message_loop_. Same for
kcwu 2015/04/16 14:38:26 Done.
137 LOG(ERROR) << __func__;
138 DCHECK(!jpeg_decode_accelerator_.get());
139
140 if (!channel_->AddRoute(host_route_id_, this)) {
141 DLOG(ERROR) << "GpuJpegDecodeAccelerator::Initialize(): "
142 "failed to add route";
143 return false;
144 }
145
146 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
147 jpeg_decode_accelerator_.reset(
148 new VaapiJpegDecodeAccelerator());
149 #else
150 NOTIMPLEMENTED() << "HW JPEG decode acceleration not available.";
wuchengli 2015/03/23 06:30:14 This shouldn't be an error. DLOG or DVLOG
kcwu 2015/04/14 20:02:34 Done.
151 return false;
152 #endif
153
154 if (!jpeg_decode_accelerator_->Initialize(this)) {
155 return false;
156 }
157 return true;
158 }
159
160 void GpuJpegDecodeAccelerator::NotifyError(
161 int32_t buffer_id,
162 media::JpegDecodeAccelerator::Error error) {
163 Send(new AcceleratedJpegDecoderHostMsg_NotifyError(
164 host_route_id_, buffer_id, error));
165 }
166
167 void GpuJpegDecodeAccelerator::VideoFrameReady(int32_t bitstream_buffer_id) {
168 Send(new AcceleratedJpegDecoderHostMsg_VideoFrameReady(
169 host_route_id_, bitstream_buffer_id));
170 }
171
172 void DecodeFinished(scoped_ptr<base::SharedMemory> shm) {
173 // do nothing
174 LOG(ERROR) << "DecodeFinished";
175 }
176
177 // Runs on IO thread if jpeg_decode_accelerator_->CanDecodeOnIOThread() is
178 // true, otherwise on the main thread.
179 void GpuJpegDecodeAccelerator::OnDecode(
180 const AcceleratedJpegDecoderMsg_Decode_Params& params) {
181 LOG(ERROR) << __func__;
wuchengli 2015/03/23 06:30:15 Add DCHECK to make sure this runs on IO thread.
kcwu 2015/04/14 20:02:34 Done.
182 #if 0
183 DCHECK(jpeg_decode_accelerator_.get());
184 #endif
185
186 // TODO(kcwu) validate input values
187 #if 0
188 if (id < 0) {
189 DLOG(ERROR) << "BitstreamBuffer id " << id << " out of range";
190 if (child_message_loop_->BelongsToCurrentThread()) {
wuchengli 2015/03/23 06:30:15 remove because this only runs on IO thread.
kcwu 2015/03/30 18:12:14 Done.
191 NotifyDecodeError(media::JpegDecodeAccelerator::INVALID_ARGUMENT);
192 } else {
193 child_message_loop_->PostTask(
194 FROM_HERE,
195 base::Bind(&GpuJpegDecodeAccelerator::NotifyError,
196 base::Unretained(this),
197 media::JpegDecodeAccelerator::INVALID_ARGUMENT));
198 }
199 return;
200 }
201 #endif
202 media::BitstreamBuffer input_buffer(params.input_buffer_id,
203 params.input_buffer_handle,
204 params.input_buffer_size);
205
206
207 scoped_ptr<base::SharedMemory> output_shm(
208 new base::SharedMemory(params.output_video_frame_handle, false));
209 if (!output_shm->Map(params.output_buffer_size)) {
wuchengli 2015/03/23 06:30:15 Can we do Map in VaapiJDA::DecodeTask so this won'
kcwu 2015/04/14 20:02:34 VaapiJDA::Decode expect VideoFrame, so we have to
210 DLOG(ERROR) << "GpuJpegDecodeAccelerator::OnDecode(): "
211 "could not map frame_id=" << 0; // TODO(kcwu)
212 NotifyError(params.input_buffer_id,
213 media::JpegDecodeAccelerator::PLATFORM_FAILURE);
214 return;
215 }
216
217 uint8* shm_memory = reinterpret_cast<uint8*>(output_shm->memory());
218 scoped_refptr<media::VideoFrame> frame =
219 media::VideoFrame::WrapExternalPackedMemory(
220 media::VideoFrame::I420,
221 params.coded_size,
222 gfx::Rect(params.coded_size),
223 params.coded_size,
224 shm_memory,
225 params.output_buffer_size,
226 params.output_video_frame_handle,
227 0,
228 base::TimeDelta(),
229 base::Bind(DecodeFinished,
230 base::Passed(&output_shm)));
231
232 if (!frame.get()) {
233 DLOG(ERROR) << "GpuJpegDecodeAccelerator::OnDecode(): "
234 << "could not create VideoFrame for buffer_id="
235 << params.input_buffer_id;
236 NotifyError(params.input_buffer_id,
237 media::JpegDecodeAccelerator::PLATFORM_FAILURE);
238 return;
239 }
240
241 jpeg_decode_accelerator_->Decode(input_buffer, frame);
242 }
243
244 void GpuJpegDecodeAccelerator::OnDestroy() {
245 LOG(ERROR) << __func__;
246 DCHECK(jpeg_decode_accelerator_.get());
247 //OnWillDestroyStub();
248 }
249
250 void GpuJpegDecodeAccelerator::OnFilterRemoved() {
251 // We're destroying; cancel all callbacks.
252 // weak_factory_for_io_.InvalidateWeakPtrs();
253 filter_removed_.Signal();
254 }
255
256 #if 0
257 void GpuJpegDecodeAccelerator::OnWillDestroyStub() {
258 // The stub is going away, so we have to stop and destroy VDA here, before
259 // returning, because the VDA may need the GL context to run and/or do its
260 // cleanup. We cannot destroy the VDA before the IO thread message filter is
261 // removed however, since we cannot service incoming messages with VDA gone.
262 // We cannot simply check for existence of VDA on IO thread though, because
263 // we don't want to synchronize the IO thread with the ChildThread.
264 // So we have to wait for the RemoveFilter callback here instead and remove
265 // the VDA after it arrives and before returning.
266 if (filter_.get()) {
267 filter_removed_.Wait();
268 }
269
270
271 jpeg_decode_accelerator_.reset();
272 delete this;
273 }
274 #endif
275
276 bool GpuJpegDecodeAccelerator::Send(IPC::Message* message) {
277 if (filter_.get() && io_message_loop_->BelongsToCurrentThread())
278 return filter_->SendOnIOThread(message);
279 DCHECK(child_message_loop_->BelongsToCurrentThread());
280 return channel_->Send(message);
281 }
282
283 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698