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"
16 GpuVideoEncodeAcceleratorHost::GpuVideoEncodeAcceleratorHost(
17 media::VideoEncodeAccelerator::Client
* client
,
18 const scoped_refptr
<GpuChannelHost
>& gpu_channel_host
,
21 client_ptr_factory_(client_
),
22 channel_(gpu_channel_host
),
25 channel_
->AddRoute(route_id_
, AsWeakPtr());
28 GpuVideoEncodeAcceleratorHost::~GpuVideoEncodeAcceleratorHost() {
30 channel_
->RemoveRoute(route_id_
);
34 std::vector
<media::VideoEncodeAccelerator::SupportedProfile
>
35 GpuVideoEncodeAcceleratorHost::GetSupportedProfiles() {
36 return GpuVideoEncodeAccelerator::GetSupportedProfiles();
39 bool GpuVideoEncodeAcceleratorHost::OnMessageReceived(
40 const IPC::Message
& message
) {
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
,
49 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_BitstreamBufferReady
,
50 OnBitstreamBufferReady
)
51 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyError
,
53 IPC_MESSAGE_UNHANDLED(handled
= false)
56 // See OnNotifyError for why |this| mustn't be used after OnNotifyError might
57 // have been called above.
61 void GpuVideoEncodeAcceleratorHost::OnChannelError() {
62 DLOG(ERROR
) << "OnChannelError()";
64 channel_
->RemoveRoute(route_id_
);
67 // See OnNotifyError for why this needs to be the last thing in this
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_
,
84 void GpuVideoEncodeAcceleratorHost::Encode(
85 const scoped_refptr
<media::VideoFrame
>& frame
,
86 bool force_keyframe
) {
89 if (!base::SharedMemory::IsHandleValid(frame
->shared_memory_handle())) {
90 DLOG(ERROR
) << "Encode(): cannot encode frame not backed by shared memory";
91 NotifyError(kPlatformFailureError
);
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 "
99 NotifyError(kPlatformFailureError
);
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
)))
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
) {
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
);
134 Send(new AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer(
135 route_id_
, buffer
.id(), handle
, buffer
.size()));
138 void GpuVideoEncodeAcceleratorHost::RequestEncodingParametersChange(
141 Send(new AcceleratedVideoEncoderMsg_RequestEncodingParametersChange(
142 route_id_
, bitrate
, framerate
));
145 void GpuVideoEncodeAcceleratorHost::Destroy() {
146 Send(new GpuChannelMsg_DestroyVideoEncoder(route_id_
));
150 void GpuVideoEncodeAcceleratorHost::NotifyError(Error error
) {
151 DVLOG(2) << "NotifyError(): error=" << error
;
152 base::MessageLoopProxy::current()->PostTask(
154 base::Bind(&media::VideoEncodeAccelerator::Client::NotifyError
,
155 client_ptr_factory_
.GetWeakPtr(),
159 void GpuVideoEncodeAcceleratorHost::OnNotifyInitializeDone() {
160 DVLOG(2) << "OnNotifyInitializeDone()";
162 client_
->NotifyInitializeDone();
165 void GpuVideoEncodeAcceleratorHost::OnRequireBitstreamBuffers(
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
;
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
185 OnNotifyError(kPlatformFailureError
);
190 void GpuVideoEncodeAcceleratorHost::OnBitstreamBufferReady(
191 int32 bitstream_buffer_id
,
194 DVLOG(3) << "OnBitstreamBufferReady(): "
195 "bitstream_buffer_id=" << bitstream_buffer_id
196 << ", payload_size=" << payload_size
197 << ", key_frame=" << key_frame
;
199 client_
->BitstreamBufferReady(bitstream_buffer_id
, payload_size
, key_frame
);
202 void GpuVideoEncodeAcceleratorHost::OnNotifyError(Error error
) {
203 DVLOG(2) << "OnNotifyError(): error=" << error
;
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
) {
217 DLOG(ERROR
) << "Send(): no channel";
219 NotifyError(kPlatformFailureError
);
220 } else if (!channel_
->Send(message
)) {
221 DLOG(ERROR
) << "Send(): sending failed: message->type()="
223 NotifyError(kPlatformFailureError
);
227 } // namespace content