[SyncFS] Build indexes from FileTracker entries on disk.
[chromium-blink-merge.git] / content / common / gpu / client / gpu_video_encode_accelerator_host.cc
blobfafa7eb00da568b982ab397b3c77097d7cf9ebcc
1 // Copyright 2013 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.
5 #include "content/common/gpu/client/gpu_video_encode_accelerator_host.h"
7 #include "base/logging.h"
8 #include "base/message_loop/message_loop_proxy.h"
9 #include "content/common/gpu/client/gpu_channel_host.h"
10 #include "content/common/gpu/gpu_messages.h"
11 #include "content/common/gpu/media/gpu_video_encode_accelerator.h"
12 #include "media/base/video_frame.h"
14 namespace content {
16 #define NOTIFY_ERROR(error) \
17 PostNotifyError(error); \
18 DLOG(ERROR)
20 GpuVideoEncodeAcceleratorHost::GpuVideoEncodeAcceleratorHost(
21 GpuChannelHost* channel,
22 CommandBufferProxyImpl* impl)
23 : channel_(channel),
24 encoder_route_id_(MSG_ROUTING_NONE),
25 client_(NULL),
26 impl_(impl),
27 next_frame_id_(0),
28 weak_this_factory_(this) {
29 DCHECK(channel_);
30 DCHECK(impl_);
31 impl_->AddDeletionObserver(this);
34 GpuVideoEncodeAcceleratorHost::~GpuVideoEncodeAcceleratorHost() {
35 DCHECK(CalledOnValidThread());
36 if (channel_ && encoder_route_id_ != MSG_ROUTING_NONE)
37 channel_->RemoveRoute(encoder_route_id_);
38 if (impl_)
39 impl_->RemoveDeletionObserver(this);
42 // static
43 std::vector<media::VideoEncodeAccelerator::SupportedProfile>
44 GpuVideoEncodeAcceleratorHost::GetSupportedProfiles() {
45 return GpuVideoEncodeAccelerator::GetSupportedProfiles();
48 bool GpuVideoEncodeAcceleratorHost::OnMessageReceived(
49 const IPC::Message& message) {
50 bool handled = true;
51 IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAcceleratorHost, message)
52 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers,
53 OnRequireBitstreamBuffers)
54 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyInputDone,
55 OnNotifyInputDone)
56 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_BitstreamBufferReady,
57 OnBitstreamBufferReady)
58 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyError,
59 OnNotifyError)
60 IPC_MESSAGE_UNHANDLED(handled = false)
61 IPC_END_MESSAGE_MAP()
62 DCHECK(handled);
63 // See OnNotifyError for why |this| mustn't be used after OnNotifyError might
64 // have been called above.
65 return handled;
68 void GpuVideoEncodeAcceleratorHost::OnChannelError() {
69 DCHECK(CalledOnValidThread());
70 if (channel_) {
71 if (encoder_route_id_ != MSG_ROUTING_NONE)
72 channel_->RemoveRoute(encoder_route_id_);
73 channel_ = NULL;
75 NOTIFY_ERROR(kPlatformFailureError) << "OnChannelError()";
78 bool GpuVideoEncodeAcceleratorHost::Initialize(
79 media::VideoFrame::Format input_format,
80 const gfx::Size& input_visible_size,
81 media::VideoCodecProfile output_profile,
82 uint32 initial_bitrate,
83 Client* client) {
84 DCHECK(CalledOnValidThread());
85 client_ = client;
86 if (!impl_) {
87 DLOG(ERROR) << "impl_ destroyed";
88 return false;
91 int32 route_id = channel_->GenerateRouteID();
92 channel_->AddRoute(route_id, weak_this_factory_.GetWeakPtr());
94 bool succeeded = false;
95 Send(new GpuCommandBufferMsg_CreateVideoEncoder(impl_->GetRouteID(),
96 input_format,
97 input_visible_size,
98 output_profile,
99 initial_bitrate,
100 route_id,
101 &succeeded));
102 if (!succeeded) {
103 DLOG(ERROR) << "Send(GpuCommandBufferMsg_CreateVideoEncoder()) failed";
104 channel_->RemoveRoute(route_id);
105 return false;
107 encoder_route_id_ = route_id;
108 return true;
111 void GpuVideoEncodeAcceleratorHost::Encode(
112 const scoped_refptr<media::VideoFrame>& frame,
113 bool force_keyframe) {
114 DCHECK(CalledOnValidThread());
115 if (!channel_)
116 return;
118 if (!base::SharedMemory::IsHandleValid(frame->shared_memory_handle())) {
119 NOTIFY_ERROR(kPlatformFailureError)
120 << "Encode(): cannot encode frame not backed by shared memory";
121 return;
123 base::SharedMemoryHandle handle =
124 channel_->ShareToGpuProcess(frame->shared_memory_handle());
125 if (!base::SharedMemory::IsHandleValid(handle)) {
126 NOTIFY_ERROR(kPlatformFailureError)
127 << "Encode(): failed to duplicate buffer handle for GPU process";
128 return;
131 // We assume that planar frame data passed here is packed and contiguous.
132 const size_t plane_count = media::VideoFrame::NumPlanes(frame->format());
133 size_t frame_size = 0;
134 for (size_t i = 0; i < plane_count; ++i) {
135 // Cast DCHECK parameters to void* to avoid printing uint8* as a string.
136 DCHECK_EQ(reinterpret_cast<void*>(frame->data(i)),
137 reinterpret_cast<void*>((frame->data(0) + frame_size)))
138 << "plane=" << i;
139 frame_size += frame->stride(i) * frame->rows(i);
142 Send(new AcceleratedVideoEncoderMsg_Encode(
143 encoder_route_id_, next_frame_id_, handle, frame_size, force_keyframe));
144 frame_map_[next_frame_id_] = frame;
146 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
147 next_frame_id_ = (next_frame_id_ + 1) & 0x3FFFFFFF;
150 void GpuVideoEncodeAcceleratorHost::UseOutputBitstreamBuffer(
151 const media::BitstreamBuffer& buffer) {
152 DCHECK(CalledOnValidThread());
153 if (!channel_)
154 return;
156 base::SharedMemoryHandle handle =
157 channel_->ShareToGpuProcess(buffer.handle());
158 if (!base::SharedMemory::IsHandleValid(handle)) {
159 NOTIFY_ERROR(kPlatformFailureError)
160 << "UseOutputBitstreamBuffer(): failed to duplicate buffer handle "
161 "for GPU process: buffer.id()=" << buffer.id();
162 return;
164 Send(new AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer(
165 encoder_route_id_, buffer.id(), handle, buffer.size()));
168 void GpuVideoEncodeAcceleratorHost::RequestEncodingParametersChange(
169 uint32 bitrate,
170 uint32 framerate) {
171 DCHECK(CalledOnValidThread());
172 if (!channel_)
173 return;
175 Send(new AcceleratedVideoEncoderMsg_RequestEncodingParametersChange(
176 encoder_route_id_, bitrate, framerate));
179 void GpuVideoEncodeAcceleratorHost::Destroy() {
180 DCHECK(CalledOnValidThread());
181 if (channel_)
182 Send(new AcceleratedVideoEncoderMsg_Destroy(encoder_route_id_));
183 client_ = NULL;
184 delete this;
187 void GpuVideoEncodeAcceleratorHost::OnWillDeleteImpl() {
188 DCHECK(CalledOnValidThread());
189 impl_ = NULL;
191 // The CommandBufferProxyImpl is going away; error out this VEA.
192 OnChannelError();
195 void GpuVideoEncodeAcceleratorHost::PostNotifyError(Error error) {
196 DCHECK(CalledOnValidThread());
197 DVLOG(2) << "PostNotifyError(): error=" << error;
198 // Post the error notification back to this thread, to avoid re-entrancy.
199 base::MessageLoopProxy::current()->PostTask(
200 FROM_HERE,
201 base::Bind(&GpuVideoEncodeAcceleratorHost::OnNotifyError,
202 weak_this_factory_.GetWeakPtr(),
203 error));
206 void GpuVideoEncodeAcceleratorHost::Send(IPC::Message* message) {
207 DCHECK(CalledOnValidThread());
208 uint32 message_type = message->type();
209 if (!channel_->Send(message)) {
210 NOTIFY_ERROR(kPlatformFailureError) << "Send(" << message_type
211 << ") failed";
215 void GpuVideoEncodeAcceleratorHost::OnRequireBitstreamBuffers(
216 uint32 input_count,
217 const gfx::Size& input_coded_size,
218 uint32 output_buffer_size) {
219 DCHECK(CalledOnValidThread());
220 DVLOG(2) << "OnRequireBitstreamBuffers(): input_count=" << input_count
221 << ", input_coded_size=" << input_coded_size.ToString()
222 << ", output_buffer_size=" << output_buffer_size;
223 if (client_) {
224 client_->RequireBitstreamBuffers(
225 input_count, input_coded_size, output_buffer_size);
229 void GpuVideoEncodeAcceleratorHost::OnNotifyInputDone(int32 frame_id) {
230 DCHECK(CalledOnValidThread());
231 DVLOG(3) << "OnNotifyInputDone(): frame_id=" << frame_id;
232 // Fun-fact: std::hash_map is not spec'd to be re-entrant; since freeing a
233 // frame can trigger a further encode to be kicked off and thus an .insert()
234 // back into the map, we separate the frame's dtor running from the .erase()
235 // running by holding on to the frame temporarily. This isn't "just
236 // theoretical" - Android's std::hash_map crashes if we don't do this.
237 scoped_refptr<media::VideoFrame> frame = frame_map_[frame_id];
238 if (!frame_map_.erase(frame_id)) {
239 DLOG(ERROR) << "OnNotifyInputDone(): "
240 "invalid frame_id=" << frame_id;
241 // See OnNotifyError for why this needs to be the last thing in this
242 // function.
243 OnNotifyError(kPlatformFailureError);
244 return;
246 frame = NULL; // Not necessary but nice to be explicit; see fun-fact above.
249 void GpuVideoEncodeAcceleratorHost::OnBitstreamBufferReady(
250 int32 bitstream_buffer_id,
251 uint32 payload_size,
252 bool key_frame) {
253 DCHECK(CalledOnValidThread());
254 DVLOG(3) << "OnBitstreamBufferReady(): "
255 "bitstream_buffer_id=" << bitstream_buffer_id
256 << ", payload_size=" << payload_size
257 << ", key_frame=" << key_frame;
258 if (client_)
259 client_->BitstreamBufferReady(bitstream_buffer_id, payload_size, key_frame);
262 void GpuVideoEncodeAcceleratorHost::OnNotifyError(Error error) {
263 DCHECK(CalledOnValidThread());
264 DVLOG(2) << "OnNotifyError(): error=" << error;
265 if (!client_)
266 return;
267 weak_this_factory_.InvalidateWeakPtrs();
269 // Client::NotifyError() may Destroy() |this|, so calling it needs to be the
270 // last thing done on this stack!
271 media::VideoEncodeAccelerator::Client* client = NULL;
272 std::swap(client_, client);
273 client->NotifyError(error);
276 } // namespace content