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

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: 7dec70f6 Whoops, one last linker thing I missed 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/logging.h"
8 #include "base/memory/shared_memory.h"
9 #include "content/common/gpu/gpu_channel.h"
10 #include "content/common/gpu/gpu_messages.h"
11 #include "ipc/ipc_message_macros.h"
12 #include "media/base/video_frame.h"
13
14 namespace content {
15
16 GpuVideoEncodeAccelerator::GpuVideoEncodeAccelerator(GpuChannel* gpu_channel,
17 int32 route_id)
18 : channel_(gpu_channel),
19 route_id_(route_id),
20 input_format_(media::VideoFrame::INVALID),
21 output_buffer_size_(0) {}
22
23 GpuVideoEncodeAccelerator::~GpuVideoEncodeAccelerator() {
24 if (encoder_)
25 encoder_.release()->Destroy();
26 }
27
28 bool GpuVideoEncodeAccelerator::OnMessageReceived(const IPC::Message& message) {
29 bool handled = true;
30 IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAccelerator, message)
31 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Initialize, OnInitialize)
32 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Encode, OnEncode)
33 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer,
34 OnUseOutputBitstreamBuffer)
35 IPC_MESSAGE_HANDLER(
36 AcceleratedVideoEncoderMsg_RequestEncodingParametersChange,
37 OnRequestEncodingParametersChange)
38 IPC_MESSAGE_UNHANDLED(handled = false)
39 IPC_END_MESSAGE_MAP()
40 return handled;
41 }
42
43 void GpuVideoEncodeAccelerator::OnChannelError() {
44 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
45 if (channel_)
46 channel_ = NULL;
47 }
48
49 void GpuVideoEncodeAccelerator::NotifyInitializeDone() {
50 Send(new AcceleratedVideoEncoderHostMsg_NotifyInitializeDone(route_id_));
51 }
52
53 void GpuVideoEncodeAccelerator::RequireBitstreamBuffers(
54 int input_count,
55 const gfx::Size& input_coded_size,
56 size_t output_buffer_size) {
57 Send(new AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers(
58 route_id_, input_count, input_coded_size, output_buffer_size));
59 input_coded_size_ = input_coded_size;
60 output_buffer_size_ = output_buffer_size;
61 }
62
63 void GpuVideoEncodeAccelerator::BitstreamBufferReady(int32 bitstream_buffer_id,
64 size_t payload_size,
65 bool key_frame) {
66 Send(new AcceleratedVideoEncoderHostMsg_BitstreamBufferReady(
67 route_id_, bitstream_buffer_id, payload_size, key_frame));
68 }
69
70 void GpuVideoEncodeAccelerator::NotifyError(
71 media::VideoEncodeAccelerator::Error error) {
72 Send(new AcceleratedVideoEncoderHostMsg_NotifyError(route_id_, error));
73 }
74
75 // static
76 std::vector<media::VideoEncodeAccelerator::SupportedProfile>
77 GpuVideoEncodeAccelerator::GetSupportedProfiles() {
78 std::vector<media::VideoEncodeAccelerator::SupportedProfile> profiles;
79
80 // TODO(sheu): return platform-specific profiles.
81 return profiles;
82 }
83
84 void GpuVideoEncodeAccelerator::CreateEncoder() {
85 // TODO(sheu): actual create the encoder.
86 }
87
88 void GpuVideoEncodeAccelerator::OnInitialize(
89 media::VideoFrame::Format input_format,
90 const gfx::Size& input_visible_size,
91 media::VideoCodecProfile output_profile,
92 int32 initial_bitrate) {
93 DVLOG(2) << "GpuVideoEncodeAccelerator::OnInitialize(): "
94 "input_format=" << input_format
95 << ", input_visible_size=" << input_visible_size.ToString()
96 << ", output_profile=" << output_profile
97 << ", initial_bitrate=" << initial_bitrate;
98 DCHECK(!encoder_);
99
100 CreateEncoder();
101 if (!encoder_) {
102 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnInitialize(): VEA creation "
103 "failed";
104 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
105 return;
106 }
107 encoder_->Initialize(
108 input_format, input_visible_size, output_profile, initial_bitrate);
109 input_format_ = input_format;
110 input_visible_size_ = input_visible_size;
111 }
112
113 void GpuVideoEncodeAccelerator::OnEncode(int32 frame_id,
114 base::SharedMemoryHandle buffer_handle,
115 uint32 buffer_size,
116 bool force_keyframe) {
117 DVLOG(3) << "GpuVideoEncodeAccelerator::OnEncode(): frame_id=" << frame_id
118 << ", buffer_size=" << buffer_size
119 << ", force_keyframe=" << force_keyframe;
120 if (!encoder_)
121 return;
122 if (frame_id < 0) {
123 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnEncode(): invalid frame_id="
124 << frame_id;
125 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
126 return;
127 }
128
129 scoped_ptr<base::SharedMemory> shm(
130 new base::SharedMemory(buffer_handle, true));
131 if (!shm->Map(buffer_size)) {
132 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnEncode(): "
133 "could not map frame_id=" << frame_id;
134 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
135 return;
136 }
137
138 scoped_refptr<media::VideoFrame> frame;
139 switch (input_format_) {
140 case media::VideoFrame::I420: {
141 if (buffer_size <
142 static_cast<size_t>(input_coded_size_.GetArea() * 3 / 2)) {
143 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnEncode(): "
144 "buffer too small for frame_id=" << frame_id;
145 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
146 return;
147 }
148 uint8* data = reinterpret_cast<uint8*>(shm->memory());
149 frame = media::VideoFrame::WrapExternalYuvData(
150 media::VideoFrame::I420,
151 input_coded_size_,
152 gfx::Rect(input_visible_size_),
153 input_visible_size_,
154 input_coded_size_.width(),
155 input_coded_size_.width() / 2,
156 input_coded_size_.width() / 2,
157 data,
158 data + input_coded_size_.GetArea(),
159 data + (input_coded_size_.GetArea() * 5 / 4),
160 base::TimeDelta(),
161 buffer_handle,
162 base::Bind(&GpuVideoEncodeAccelerator::EncodeFrameFinished,
163 base::Unretained(this),
piman 2013/08/09 04:04:58 what makes this Unretained safe?
sheu 2013/08/09 08:26:41 That's an interesting question, I guess. I was as
piman 2013/08/12 21:43:40 Why do you then need the extra PostTask?
sheu 2013/08/12 21:58:18 The VideoFrame destructor will call the callback,
piman 2013/08/13 01:00:04 Ok.
164 frame_id,
165 base::Passed(&shm)));
166 break;
167 }
168 default:
169 NOTREACHED();
piman 2013/08/09 04:04:58 This comes from the untrusted renderer, so it can
sheu 2013/08/09 08:26:41 Right, if it's reached, we proceed to return an er
piman 2013/08/12 21:43:40 It can give a false sense of security, which, for
sheu 2013/08/12 21:58:18 Sure -- in any case though this has been pulled in
170 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
171 return;
172 }
173
174 encoder_->Encode(frame, force_keyframe);
175 }
176
177 void GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(
178 int32 buffer_id,
179 base::SharedMemoryHandle buffer_handle,
180 uint32 buffer_size) {
181 DVLOG(3) << "GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(): "
182 "buffer_id=" << buffer_id
183 << ", buffer_size=" << buffer_size;
184 if (!encoder_)
185 return;
186 if (buffer_id < 0) {
187 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(): "
188 "invalid buffer_id=" << buffer_id;
189 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
190 return;
191 }
192 if (buffer_size < output_buffer_size_) {
193 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(): "
194 "buffer too small for buffer_id=" << buffer_id;
195 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
196 return;
197 }
198 encoder_->UseOutputBitstreamBuffer(
199 media::BitstreamBuffer(buffer_id, buffer_handle, buffer_size));
piman 2013/08/09 04:04:58 what happens if buffer_handle is invalid, or doesn
sheu 2013/08/09 08:26:41 If the buffer handle is invalid, mapping it will f
piman 2013/08/12 21:43:40 We want to make sure this is properly communicated
sheu 2013/08/12 21:58:18 Right, but how do we know the buffer size? It's g
piman 2013/08/13 01:00:04 You have no way of knowing it (well, fstat would o
sheu 2013/08/13 01:07:08 Right, and the solution adopted elsewhere (i.e. th
200 }
201
202 void GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange(
203 int32 bitrate,
204 uint32 framerate) {
205 DVLOG(2) << "GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange(): "
206 "bitrate=" << bitrate
207 << ", framerate=" << framerate;
208 if (!encoder_)
209 return;
210 encoder_->RequestEncodingParametersChange(bitrate, framerate);
211 }
212
213 void GpuVideoEncodeAccelerator::EncodeFrameFinished(
214 int32 frame_id,
215 scoped_ptr<base::SharedMemory> shm) {
216 Send(new AcceleratedVideoEncoderHostMsg_NotifyInputDone(route_id_, frame_id));
217 // Just let shm fall out of scope.
218 }
219
220 void GpuVideoEncodeAccelerator::Send(IPC::Message* message) {
221 if (!channel_) {
222 DLOG(ERROR) << "GpuVideoEncodeAccelerator::Send(): no channel";
223 delete message;
224 return;
225 } else if (!channel_->Send(message)) {
226 DLOG(ERROR) << "GpuVideoEncodeAccelerator::Send(): sending failed: "
227 "message->type()=" << message->type();
228 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
229 return;
230 }
231 }
232
233 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698