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

Side by Side Diff: content/common/gpu/client/gpu_jpeg_decode_accelerator_host.cc

Issue 1165943008: MJPEG acceleration for video capture using VAAPI, the GPU host part (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mjpeg-2-gpu
Patch Set: rebase and fix compile on mac Created 5 years, 6 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/client/gpu_jpeg_decode_accelerator_host.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/memory/shared_memory_handle.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/synchronization/waitable_event.h"
12 #include "content/common/gpu/client/gpu_channel_host.h"
13 #include "content/common/gpu/gpu_messages.h"
14 #include "ipc/ipc_listener.h"
15 #include "ipc/ipc_message_macros.h"
16 #include "ipc/ipc_message_utils.h"
17
18 namespace content {
19
20 // Class to receive AcceleratedJpegDecoderHostMsg_DecodeAck IPC message on IO
21 // thread. This does very similar what MessageFilter usually does. It is not
22 // MessageFilter because GpuChannelHost doesn't support AddFilter.
23 class GpuJpegDecodeAcceleratorHost::Receiver : public IPC::Listener,
24 public base::NonThreadSafe {
25 public:
26 Receiver(Client* client,
27 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
28 : client_(client),
29 io_task_runner_(io_task_runner),
30 weak_factory_for_io_(this) {
31 DCHECK(CalledOnValidThread());
32 }
33
34 ~Receiver() override { DCHECK(CalledOnValidThread()); }
35
36 void InvalidateWeakPtr(base::WaitableEvent* event) {
37 DCHECK(io_task_runner_->BelongsToCurrentThread());
38 weak_factory_for_io_.InvalidateWeakPtrs();
39 event->Signal();
40 }
41
42 // IPC::Listener implementation.
43 void OnChannelError() override {
44 DCHECK(io_task_runner_->BelongsToCurrentThread());
45
46 OnDecodeAck(kInvalidBitstreamBufferId, PLATFORM_FAILURE);
47 }
48
49 bool OnMessageReceived(const IPC::Message& msg) override {
50 DCHECK(io_task_runner_->BelongsToCurrentThread());
51
52 bool handled = true;
53 IPC_BEGIN_MESSAGE_MAP(GpuJpegDecodeAcceleratorHost::Receiver, msg)
54 IPC_MESSAGE_HANDLER(AcceleratedJpegDecoderHostMsg_DecodeAck, OnDecodeAck)
55 IPC_MESSAGE_UNHANDLED(handled = false)
56 IPC_END_MESSAGE_MAP()
57 DCHECK(handled);
58 return handled;
59 }
60
61 base::WeakPtr<IPC::Listener> AsWeakPtrForIO() {
62 return weak_factory_for_io_.GetWeakPtr();
63 }
64
65 private:
66 void OnDecodeAck(int32_t bitstream_buffer_id, Error error) {
67 DCHECK(io_task_runner_->BelongsToCurrentThread());
68
69 if (!client_)
70 return;
71
72 if (error == media::JpegDecodeAccelerator::NO_ERRORS) {
73 client_->VideoFrameReady(bitstream_buffer_id);
74 } else {
75 // Only NotifyError once.
76 // Client::NotifyError() may trigger deletion of |this| (on another
77 // thread), so calling it needs to be the last thing done on this stack!
78 media::JpegDecodeAccelerator::Client* client = nullptr;
79 std::swap(client, client_);
80 client->NotifyError(bitstream_buffer_id, error);
81 }
82 }
83
84 Client* client_;
85
86 // GPU IO task runner.
87 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
88
89 // Weak pointers will be invalidated on IO thread.
90 base::WeakPtrFactory<Receiver> weak_factory_for_io_;
91
92 DISALLOW_COPY_AND_ASSIGN(Receiver);
93 };
94
95 GpuJpegDecodeAcceleratorHost::GpuJpegDecodeAcceleratorHost(
96 GpuChannelHost* channel,
97 int32 route_id,
98 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
99 : channel_(channel),
100 decoder_route_id_(route_id),
101 io_task_runner_(io_task_runner) {
102 DCHECK(channel_);
103 DCHECK_NE(decoder_route_id_, MSG_ROUTING_NONE);
104 }
105
106 GpuJpegDecodeAcceleratorHost::~GpuJpegDecodeAcceleratorHost() {
107 DCHECK(CalledOnValidThread());
108 Send(new AcceleratedJpegDecoderMsg_Destroy(decoder_route_id_));
109
110 channel_->RemoveRoute(decoder_route_id_);
111
112 // Invalidate weak ptr of |receiver_|. After that, no more messages will be
113 // routed to |receiver_| on IO thread.
114 base::WaitableEvent event(false, false);
115 io_task_runner_->PostTask(
116 FROM_HERE,
117 base::Bind(&Receiver::InvalidateWeakPtr,
118 base::Unretained(receiver_.get()), base::Unretained(&event)));
119 event.Wait();
120 }
121
122 bool GpuJpegDecodeAcceleratorHost::Initialize(
123 media::JpegDecodeAccelerator::Client* client) {
124 DCHECK(CalledOnValidThread());
125
126 bool succeeded = false;
127 // This cannot be on IO thread because the msg is synchronous.
128 Send(new GpuMsg_CreateJpegDecoder(decoder_route_id_, &succeeded));
129
130 if (!succeeded) {
131 DLOG(ERROR) << "Send(GpuMsg_CreateJpegDecoder()) failed";
132 return false;
133 }
134
135 receiver_.reset(new Receiver(client, io_task_runner_));
136
137 return true;
138 }
139
140 void GpuJpegDecodeAcceleratorHost::Decode(
141 const media::BitstreamBuffer& bitstream_buffer,
142 const scoped_refptr<media::VideoFrame>& video_frame) {
143 DCHECK(CalledOnValidThread());
144
145 DCHECK(
146 base::SharedMemory::IsHandleValid(video_frame->shared_memory_handle()));
147
148 base::SharedMemoryHandle input_handle =
149 channel_->ShareToGpuProcess(bitstream_buffer.handle());
150 if (!base::SharedMemory::IsHandleValid(input_handle)) {
151 DLOG(ERROR) << "Failed to duplicate handle of BitstreamBuffer";
152 return;
153 }
154 base::SharedMemoryHandle output_handle =
155 channel_->ShareToGpuProcess(video_frame->shared_memory_handle());
156 if (!base::SharedMemory::IsHandleValid(output_handle)) {
157 DLOG(ERROR) << "Failed to duplicate handle of VideoFrame";
158 #if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
159 if (input_handle.auto_close) {
160 // Defer closing task to the ScopedFD.
161 base::ScopedFD(input_handle.fd);
162 }
163 #else
164 // TODO(kcwu) fix the handle leak after crbug.com/493414 resolved.
165 #endif
166 return;
167 }
168
169 size_t output_buffer_size = media::VideoFrame::AllocationSize(
170 video_frame->format(), video_frame->coded_size());
171
172 AcceleratedJpegDecoderMsg_Decode_Params decode_params;
173 decode_params.coded_size = video_frame->coded_size();
174 decode_params.input_buffer_id = bitstream_buffer.id();
175 decode_params.input_buffer_handle = input_handle;
176 decode_params.input_buffer_size = bitstream_buffer.size();
177 decode_params.output_video_frame_handle = output_handle;
178 decode_params.output_buffer_size = output_buffer_size;
179 Send(new AcceleratedJpegDecoderMsg_Decode(decoder_route_id_, decode_params));
180 }
181
182 void GpuJpegDecodeAcceleratorHost::Send(IPC::Message* message) {
183 DCHECK(CalledOnValidThread());
184
185 if (!channel_->Send(message)) {
186 DLOG(ERROR) << "Send(" << message->type() << ") failed";
187 }
188 }
189
190 base::WeakPtr<IPC::Listener> GpuJpegDecodeAcceleratorHost::GetReceiver() {
191 return receiver_->AsWeakPtrForIO();
192 }
193
194 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/client/gpu_jpeg_decode_accelerator_host.h ('k') | content/content_common.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698