Respond with QuotaExceededError when IndexedDB has no disk space on open.
[chromium-blink-merge.git] / content / common / gpu / client / gpu_video_encode_accelerator_host.cc
blob36d99e80efb3e571540a808ac981f6fe8bb2916c
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 GpuVideoEncodeAcceleratorHost::GpuVideoEncodeAcceleratorHost(
17 media::VideoEncodeAccelerator::Client* client,
18 const scoped_refptr<GpuChannelHost>& gpu_channel_host,
19 int32 route_id)
20 : client_(client),
21 client_ptr_factory_(client_),
22 channel_(gpu_channel_host),
23 route_id_(route_id),
24 next_frame_id_(0) {
25 channel_->AddRoute(route_id_, AsWeakPtr());
28 GpuVideoEncodeAcceleratorHost::~GpuVideoEncodeAcceleratorHost() {
29 if (channel_)
30 channel_->RemoveRoute(route_id_);
33 // static
34 std::vector<media::VideoEncodeAccelerator::SupportedProfile>
35 GpuVideoEncodeAcceleratorHost::GetSupportedProfiles() {
36 return GpuVideoEncodeAccelerator::GetSupportedProfiles();
39 bool GpuVideoEncodeAcceleratorHost::OnMessageReceived(
40 const IPC::Message& message) {
41 bool handled = true;
42 IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAcceleratorHost, message)
43 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyInitializeDone,
44 OnNotifyInitializeDone)
45 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers,
46 OnRequireBitstreamBuffers)
47 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyInputDone,
48 OnNotifyInputDone)
49 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_BitstreamBufferReady,
50 OnBitstreamBufferReady)
51 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyError,
52 OnNotifyError)
53 IPC_MESSAGE_UNHANDLED(handled = false)
54 IPC_END_MESSAGE_MAP()
55 DCHECK(handled);
56 // See OnNotifyError for why |this| mustn't be used after OnNotifyError might
57 // have been called above.
58 return handled;
61 void GpuVideoEncodeAcceleratorHost::OnChannelError() {
62 DLOG(ERROR) << "OnChannelError()";
63 if (channel_) {
64 channel_->RemoveRoute(route_id_);
65 channel_ = NULL;
67 // See OnNotifyError for why this needs to be the last thing in this
68 // function.
69 OnNotifyError(kPlatformFailureError);
72 void GpuVideoEncodeAcceleratorHost::Initialize(
73 media::VideoFrame::Format input_format,
74 const gfx::Size& input_visible_size,
75 media::VideoCodecProfile output_profile,
76 uint32 initial_bitrate) {
77 Send(new AcceleratedVideoEncoderMsg_Initialize(route_id_,
78 input_format,
79 input_visible_size,
80 output_profile,
81 initial_bitrate));
84 void GpuVideoEncodeAcceleratorHost::Encode(
85 const scoped_refptr<media::VideoFrame>& frame,
86 bool force_keyframe) {
87 if (!channel_)
88 return;
89 if (!base::SharedMemory::IsHandleValid(frame->shared_memory_handle())) {
90 DLOG(ERROR) << "Encode(): cannot encode frame not backed by shared memory";
91 NotifyError(kPlatformFailureError);
92 return;
94 base::SharedMemoryHandle handle =
95 channel_->ShareToGpuProcess(frame->shared_memory_handle());
96 if (!base::SharedMemory::IsHandleValid(handle)) {
97 DLOG(ERROR) << "Encode(): failed to duplicate buffer handle for GPU "
98 "process";
99 NotifyError(kPlatformFailureError);
100 return;
103 // We assume that planar frame data passed here is packed and contiguous.
104 const size_t plane_count = media::VideoFrame::NumPlanes(frame->format());
105 size_t frame_size = 0;
106 for (size_t i = 0; i < plane_count; ++i) {
107 // Cast DCHECK parameters to void* to avoid printing uint8* as a string.
108 DCHECK_EQ(reinterpret_cast<void*>(frame->data(i)),
109 reinterpret_cast<void*>((frame->data(0) + frame_size)))
110 << "plane=" << i;
111 frame_size += frame->stride(i) * frame->rows(i);
114 Send(new AcceleratedVideoEncoderMsg_Encode(
115 route_id_, next_frame_id_, handle, frame_size, force_keyframe));
116 frame_map_[next_frame_id_] = frame;
118 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
119 next_frame_id_ = (next_frame_id_ + 1) & 0x3FFFFFFF;
122 void GpuVideoEncodeAcceleratorHost::UseOutputBitstreamBuffer(
123 const media::BitstreamBuffer& buffer) {
124 if (!channel_)
125 return;
126 base::SharedMemoryHandle handle =
127 channel_->ShareToGpuProcess(buffer.handle());
128 if (!base::SharedMemory::IsHandleValid(handle)) {
129 DLOG(ERROR) << "UseOutputBitstreamBuffer(): failed to duplicate buffer "
130 "handle for GPU process: buffer.id()=" << buffer.id();
131 NotifyError(kPlatformFailureError);
132 return;
134 Send(new AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer(
135 route_id_, buffer.id(), handle, buffer.size()));
138 void GpuVideoEncodeAcceleratorHost::RequestEncodingParametersChange(
139 uint32 bitrate,
140 uint32 framerate) {
141 Send(new AcceleratedVideoEncoderMsg_RequestEncodingParametersChange(
142 route_id_, bitrate, framerate));
145 void GpuVideoEncodeAcceleratorHost::Destroy() {
146 Send(new GpuChannelMsg_DestroyVideoEncoder(route_id_));
147 delete this;
150 void GpuVideoEncodeAcceleratorHost::NotifyError(Error error) {
151 DVLOG(2) << "NotifyError(): error=" << error;
152 base::MessageLoopProxy::current()->PostTask(
153 FROM_HERE,
154 base::Bind(&media::VideoEncodeAccelerator::Client::NotifyError,
155 client_ptr_factory_.GetWeakPtr(),
156 error));
159 void GpuVideoEncodeAcceleratorHost::OnNotifyInitializeDone() {
160 DVLOG(2) << "OnNotifyInitializeDone()";
161 if (client_)
162 client_->NotifyInitializeDone();
165 void GpuVideoEncodeAcceleratorHost::OnRequireBitstreamBuffers(
166 uint32 input_count,
167 const gfx::Size& input_coded_size,
168 uint32 output_buffer_size) {
169 DVLOG(2) << "OnRequireBitstreamBuffers(): input_count=" << input_count
170 << ", input_coded_size=" << input_coded_size.ToString()
171 << ", output_buffer_size=" << output_buffer_size;
172 if (client_) {
173 client_->RequireBitstreamBuffers(
174 input_count, input_coded_size, output_buffer_size);
178 void GpuVideoEncodeAcceleratorHost::OnNotifyInputDone(int32 frame_id) {
179 DVLOG(3) << "OnNotifyInputDone(): frame_id=" << frame_id;
180 if (!frame_map_.erase(frame_id)) {
181 DLOG(ERROR) << "OnNotifyInputDone(): "
182 "invalid frame_id=" << frame_id;
183 // See OnNotifyError for why this needs to be the last thing in this
184 // function.
185 OnNotifyError(kPlatformFailureError);
186 return;
190 void GpuVideoEncodeAcceleratorHost::OnBitstreamBufferReady(
191 int32 bitstream_buffer_id,
192 uint32 payload_size,
193 bool key_frame) {
194 DVLOG(3) << "OnBitstreamBufferReady(): "
195 "bitstream_buffer_id=" << bitstream_buffer_id
196 << ", payload_size=" << payload_size
197 << ", key_frame=" << key_frame;
198 if (client_)
199 client_->BitstreamBufferReady(bitstream_buffer_id, payload_size, key_frame);
202 void GpuVideoEncodeAcceleratorHost::OnNotifyError(Error error) {
203 DVLOG(2) << "OnNotifyError(): error=" << error;
204 if (!client_)
205 return;
206 client_ptr_factory_.InvalidateWeakPtrs();
208 // Client::NotifyError() may Destroy() |this|, so calling it needs to be the
209 // last thing done on this stack!
210 media::VideoEncodeAccelerator::Client* client = NULL;
211 std::swap(client_, client);
212 client->NotifyError(error);
215 void GpuVideoEncodeAcceleratorHost::Send(IPC::Message* message) {
216 if (!channel_) {
217 DLOG(ERROR) << "Send(): no channel";
218 delete message;
219 NotifyError(kPlatformFailureError);
220 } else if (!channel_->Send(message)) {
221 DLOG(ERROR) << "Send(): sending failed: message->type()="
222 << message->type();
223 NotifyError(kPlatformFailureError);
227 } // namespace content