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

Side by Side Diff: content/common/gpu/media/gpu_video_encode_accelerator.cc

Issue 20632002: Add media::VideoEncodeAccelerator with WebRTC integration (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@git-svn
Patch Set: 9830db80 Missing changes from last patchset Created 7 years, 4 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 (c) 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.
4
5 #include "content/common/gpu/media/gpu_video_encode_accelerator.h"
6
7 #include "base/callback.h"
8 #include "base/logging.h"
9 #include "base/memory/shared_memory.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "content/common/gpu/gpu_channel.h"
12 #include "content/common/gpu/gpu_messages.h"
13 #include "ipc/ipc_message_macros.h"
14 #include "media/base/video_frame.h"
15
16 namespace content {
17
18 GpuVideoEncodeAccelerator::GpuVideoEncodeAccelerator(GpuChannel* gpu_channel,
19 int32 route_id)
20 : weak_this_factory_(this),
21 channel_(gpu_channel),
22 route_id_(route_id),
23 input_format_(media::VideoFrame::INVALID),
24 output_buffer_size_(0) {}
25
26 GpuVideoEncodeAccelerator::~GpuVideoEncodeAccelerator() {
27 if (encoder_)
28 encoder_.release()->Destroy();
29 }
30
31 bool GpuVideoEncodeAccelerator::OnMessageReceived(const IPC::Message& message) {
32 bool handled = true;
33 IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAccelerator, message)
34 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Initialize, OnInitialize)
35 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Encode, OnEncode)
36 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer,
37 OnUseOutputBitstreamBuffer)
38 IPC_MESSAGE_HANDLER(
39 AcceleratedVideoEncoderMsg_RequestEncodingParametersChange,
40 OnRequestEncodingParametersChange)
41 IPC_MESSAGE_UNHANDLED(handled = false)
42 IPC_END_MESSAGE_MAP()
43 return handled;
44 }
45
46 void GpuVideoEncodeAccelerator::OnChannelError() {
47 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
48 if (channel_)
49 channel_ = NULL;
50 }
51
52 void GpuVideoEncodeAccelerator::NotifyInitializeDone() {
53 Send(new AcceleratedVideoEncoderHostMsg_NotifyInitializeDone(route_id_));
54 }
55
56 void GpuVideoEncodeAccelerator::RequireBitstreamBuffers(
57 int input_count,
58 const gfx::Size& input_coded_size,
59 size_t output_buffer_size) {
60 Send(new AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers(
61 route_id_, input_count, input_coded_size, output_buffer_size));
62 input_coded_size_ = input_coded_size;
63 output_buffer_size_ = output_buffer_size;
64 }
65
66 void GpuVideoEncodeAccelerator::BitstreamBufferReady(int32 bitstream_buffer_id,
67 size_t payload_size,
68 bool key_frame) {
69 Send(new AcceleratedVideoEncoderHostMsg_BitstreamBufferReady(
70 route_id_, bitstream_buffer_id, payload_size, key_frame));
71 }
72
73 void GpuVideoEncodeAccelerator::NotifyError(
74 media::VideoEncodeAccelerator::Error error) {
75 Send(new AcceleratedVideoEncoderHostMsg_NotifyError(route_id_, error));
76 }
77
78 // static
79 std::vector<media::VideoEncodeAccelerator::SupportedProfile>
80 GpuVideoEncodeAccelerator::GetSupportedProfiles() {
81 std::vector<media::VideoEncodeAccelerator::SupportedProfile> profiles;
82
83 // TODO(sheu): return platform-specific profiles.
84 return profiles;
85 }
86
87 void GpuVideoEncodeAccelerator::CreateEncoder() {
88 // TODO(sheu): actual create the encoder.
89 }
90
91 void GpuVideoEncodeAccelerator::OnInitialize(
92 media::VideoFrame::Format input_format,
93 const gfx::Size& input_visible_size,
94 media::VideoCodecProfile output_profile,
95 uint32 initial_bitrate) {
96 DVLOG(2) << "GpuVideoEncodeAccelerator::OnInitialize(): "
97 "input_format=" << input_format
98 << ", input_visible_size=" << input_visible_size.ToString()
99 << ", output_profile=" << output_profile
100 << ", initial_bitrate=" << initial_bitrate;
101 DCHECK(!encoder_);
102
103 if (input_visible_size.width() > kint32max / input_visible_size.height()) {
104 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnInitialize(): "
105 "input_visible_size too large";
106 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
107 return;
108 }
109
110 CreateEncoder();
111 if (!encoder_) {
112 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnInitialize(): VEA creation "
113 "failed";
114 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
115 return;
116 }
117 encoder_->Initialize(
118 input_format, input_visible_size, output_profile, initial_bitrate);
119 input_format_ = input_format;
120 input_visible_size_ = input_visible_size;
121 }
122
123 void GpuVideoEncodeAccelerator::OnEncode(int32 frame_id,
124 base::SharedMemoryHandle buffer_handle,
125 uint32 buffer_size,
126 bool force_keyframe) {
127 DVLOG(3) << "GpuVideoEncodeAccelerator::OnEncode(): frame_id=" << frame_id
128 << ", buffer_size=" << buffer_size
129 << ", force_keyframe=" << force_keyframe;
130 if (!encoder_)
131 return;
132 if (frame_id < 0) {
133 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnEncode(): invalid frame_id="
134 << frame_id;
135 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
136 return;
137 }
138
139 scoped_ptr<base::SharedMemory> shm(
140 new base::SharedMemory(buffer_handle, true));
141 if (!shm->Map(buffer_size)) {
142 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnEncode(): "
143 "could not map frame_id=" << frame_id;
144 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
145 return;
146 }
147
148 scoped_refptr<media::VideoFrame> frame;
149 switch (input_format_) {
150 case media::VideoFrame::I420: {
151 if (buffer_size <
152 static_cast<size_t>(input_coded_size_.GetArea() * 3 / 2)) {
153 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnEncode(): "
154 "buffer too small for frame_id=" << frame_id;
155 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
156 return;
157 }
158 uint8* data = reinterpret_cast<uint8*>(shm->memory());
159 frame = media::VideoFrame::WrapExternalYuvData(
160 media::VideoFrame::I420,
161 input_coded_size_,
162 gfx::Rect(input_visible_size_),
163 input_visible_size_,
164 input_coded_size_.width(),
165 input_coded_size_.width() / 2,
166 input_coded_size_.width() / 2,
167 data,
168 data + input_coded_size_.GetArea(),
169 data + (input_coded_size_.GetArea() * 5 / 4),
170 base::TimeDelta(),
171 buffer_handle,
172 // It's turtles all the way down...
173 base::Bind(base::IgnoreResult(&base::MessageLoopProxy::PostTask),
174 base::MessageLoopProxy::current(),
175 FROM_HERE,
176 base::Bind(&GpuVideoEncodeAccelerator::EncodeFrameFinished,
177 weak_this_factory_.GetWeakPtr(),
178 frame_id,
179 base::Passed(&shm))));
180 break;
181 }
182 default:
183 NOTREACHED();
184 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
185 return;
186 }
187
188 encoder_->Encode(frame, force_keyframe);
189 }
190
191 void GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(
192 int32 buffer_id,
193 base::SharedMemoryHandle buffer_handle,
194 uint32 buffer_size) {
195 DVLOG(3) << "GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(): "
196 "buffer_id=" << buffer_id
197 << ", buffer_size=" << buffer_size;
198 if (!encoder_)
199 return;
200 if (buffer_id < 0) {
201 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(): "
202 "invalid buffer_id=" << buffer_id;
203 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
204 return;
205 }
206 if (buffer_size < output_buffer_size_) {
207 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(): "
208 "buffer too small for buffer_id=" << buffer_id;
209 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
210 return;
211 }
212 encoder_->UseOutputBitstreamBuffer(
213 media::BitstreamBuffer(buffer_id, buffer_handle, buffer_size));
214 }
215
216 void GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange(
217 uint32 bitrate,
218 uint32 framerate) {
219 DVLOG(2) << "GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange(): "
220 "bitrate=" << bitrate
221 << ", framerate=" << framerate;
222 if (!encoder_)
223 return;
224 encoder_->RequestEncodingParametersChange(bitrate, framerate);
225 }
226
227 void GpuVideoEncodeAccelerator::EncodeFrameFinished(
228 int32 frame_id,
229 scoped_ptr<base::SharedMemory> shm) {
230 Send(new AcceleratedVideoEncoderHostMsg_NotifyInputDone(route_id_, frame_id));
231 // Just let shm fall out of scope.
232 }
233
234 void GpuVideoEncodeAccelerator::Send(IPC::Message* message) {
235 if (!channel_) {
236 DLOG(ERROR) << "GpuVideoEncodeAccelerator::Send(): no channel";
237 delete message;
238 return;
239 } else if (!channel_->Send(message)) {
240 DLOG(ERROR) << "GpuVideoEncodeAccelerator::Send(): sending failed: "
241 "message->type()=" << message->type();
242 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
243 return;
244 }
245 }
246
247 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698