OLD | NEW |
---|---|
(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_RequestEncodingParameterChange, | |
37 OnRequestEncodingParameterChange) | |
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::NotifyInputDone(int32 bitstream_buffer_id) { | |
Ami GONE FROM CHROMIUM
2013/08/05 18:44:38
This is dead code (no callers).
Which makes me won
Ami GONE FROM CHROMIUM
2013/08/05 18:44:38
If this undeads, it probably wants to be renamed t
Ami GONE FROM CHROMIUM
2013/08/05 18:44:38
s/bitstream_buffer_id/frame_id/ here and below.
sheu
2013/08/06 06:16:36
(see comment below, which I posted when uploading
| |
64 Send(new AcceleratedVideoEncoderHostMsg_NotifyEncodeDone( | |
65 route_id_, bitstream_buffer_id)); | |
66 } | |
sheu
2013/08/03 02:37:01
Whoops, I missed updating this to account for the
| |
67 | |
68 void GpuVideoEncodeAccelerator::BitstreamBufferReady(int32 bitstream_buffer_id, | |
69 size_t payload_size, | |
70 bool key_frame) { | |
71 Send(new AcceleratedVideoEncoderHostMsg_BitstreamBufferReady( | |
72 route_id_, bitstream_buffer_id, payload_size, key_frame)); | |
73 } | |
74 | |
75 void GpuVideoEncodeAccelerator::NotifyError( | |
76 media::VideoEncodeAccelerator::Error error) { | |
77 Send(new AcceleratedVideoEncoderHostMsg_NotifyError(route_id_, error)); | |
78 } | |
79 | |
80 // static | |
81 std::vector<media::VideoEncodeAccelerator::SupportedProfile> | |
82 GpuVideoEncodeAccelerator::GetSupportedProfiles() { | |
83 std::vector<media::VideoEncodeAccelerator::SupportedProfile> profiles; | |
84 | |
85 // TODO(sheu): return platform-specific profiles. | |
86 return profiles; | |
87 } | |
88 | |
89 void GpuVideoEncodeAccelerator::CreateEncoder() { | |
90 // TODO(sheu): actual create the encoder. | |
91 } | |
92 | |
93 void GpuVideoEncodeAccelerator::OnInitialize( | |
94 media::VideoFrame::Format input_format, | |
95 const gfx::Size& input_visible_size, | |
96 media::VideoCodecProfile output_profile, | |
97 int32 initial_bitrate) { | |
98 DVLOG(2) << "GpuVideoEncodeAccelerator::OnInitialize(): " | |
99 "input_format=" << input_format | |
100 << ", input_visible_size=" << input_visible_size.ToString() | |
101 << ", output_profile=" << output_profile | |
102 << ", initial_bitrate=" << initial_bitrate; | |
103 DCHECK(!encoder_); | |
104 | |
105 CreateEncoder(); | |
106 if (!encoder_) { | |
107 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnInitialize(): VEA creation " | |
108 "failed"; | |
109 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); | |
110 return; | |
111 } | |
112 encoder_->Initialize( | |
113 input_format, input_visible_size, output_profile, initial_bitrate); | |
114 input_format_ = input_format; | |
115 input_visible_size_ = input_visible_size; | |
116 } | |
117 | |
118 void GpuVideoEncodeAccelerator::OnEncode(int32 frame_id, | |
119 base::SharedMemoryHandle buffer_handle, | |
120 uint32 buffer_size, | |
121 bool force_keyframe) { | |
122 DVLOG(3) << "GpuVideoEncodeAccelerator::OnEncode(): frame_id=" << frame_id | |
123 << ", buffer_size=" << buffer_size | |
124 << ", force_keyframe=" << force_keyframe; | |
125 if (!encoder_) | |
126 return; | |
127 if (frame_id < 0) { | |
128 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnEncode(): invalid frame_id=" | |
129 << frame_id; | |
130 NotifyError(media::VideoEncodeAccelerator::kInvalidArgumentError); | |
131 return; | |
132 } | |
133 | |
134 scoped_ptr<base::SharedMemory> shm( | |
Ami GONE FROM CHROMIUM
2013/08/05 18:44:38
Can stack-allocate instead of heap-allocate.
sheu
2013/08/06 06:16:36
It gets passed to EncodeFrameFinished. Stack-allo
| |
135 new base::SharedMemory(buffer_handle, true)); | |
136 if (!shm->Map(buffer_size)) { | |
137 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnEncode(): " | |
138 "could not map frame_id=" << frame_id; | |
139 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); | |
140 return; | |
141 } | |
142 | |
143 scoped_refptr<media::VideoFrame> frame; | |
144 switch (input_format_) { | |
145 case media::VideoFrame::I420: { | |
146 if (buffer_size < | |
147 static_cast<size_t>(input_coded_size_.GetArea() * 3 / 2)) { | |
148 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnEncode(): " | |
149 "buffer too small for frame_id=" << frame_id; | |
150 NotifyError(media::VideoEncodeAccelerator::kInvalidArgumentError); | |
151 return; | |
152 } | |
153 uint8* data = reinterpret_cast<uint8*>(shm->memory()); | |
154 frame = media::VideoFrame::WrapExternalYuvData( | |
155 media::VideoFrame::I420, | |
156 input_coded_size_, | |
157 gfx::Rect(input_visible_size_), | |
158 input_visible_size_, | |
159 input_coded_size_.width(), | |
160 input_coded_size_.width() / 2, | |
161 input_coded_size_.width() / 2, | |
162 data, | |
163 data + input_coded_size_.GetArea(), | |
164 data + (input_coded_size_.GetArea() * 5 / 4), | |
165 base::TimeDelta(), | |
166 buffer_handle, | |
167 base::Bind(&GpuVideoEncodeAccelerator::EncodeFrameFinished, | |
168 base::Unretained(this), | |
169 base::Passed(&shm))); | |
170 } | |
Ami GONE FROM CHROMIUM
2013/08/05 18:44:38
How does this fall-through not completely break yo
sheu
2013/08/06 06:16:36
Easy -- I didn't test :-P
Fixed now that I actual
| |
171 default: | |
172 NOTREACHED(); | |
Ami GONE FROM CHROMIUM
2013/08/05 18:44:38
It's kind of silly to have a single-case switch st
sheu
2013/08/06 06:16:36
It's silly but I intend to be taking more formats
Ami GONE FROM CHROMIUM
2013/08/06 20:41:13
If this alleged future is in less than 30d, then o
| |
173 NotifyError(media::VideoEncodeAccelerator::kInvalidArgumentError); | |
174 return; | |
175 } | |
176 | |
177 encoder_->Encode(frame, force_keyframe); | |
178 } | |
179 | |
180 void GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer( | |
181 int32 buffer_id, | |
182 base::SharedMemoryHandle buffer_handle, | |
183 uint32 buffer_size) { | |
184 DVLOG(3) << "GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(): " | |
185 "buffer_id=" << buffer_id | |
186 << ", buffer_size=" << buffer_size; | |
187 if (!encoder_) | |
188 return; | |
189 if (buffer_id < 0) { | |
190 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(): " | |
Ami GONE FROM CHROMIUM
2013/08/05 18:44:38
nit: DLOG will emit the file:line pair for this; h
sheu
2013/08/06 06:16:36
I suppose. Search-replace time.
| |
191 "invalid buffer_id=" << buffer_id; | |
192 NotifyError(media::VideoEncodeAccelerator::kInvalidArgumentError); | |
193 return; | |
194 } | |
195 if (buffer_size < output_buffer_size_) { | |
196 DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(): " | |
197 "buffer too small for buffer_id=" << buffer_id; | |
198 NotifyError(media::VideoEncodeAccelerator::kInvalidArgumentError); | |
199 return; | |
200 } | |
201 encoder_->UseOutputBitstreamBuffer( | |
202 media::BitstreamBuffer(buffer_id, buffer_handle, buffer_size)); | |
203 } | |
204 | |
205 void GpuVideoEncodeAccelerator::OnRequestEncodingParameterChange( | |
206 int32 bitrate) { | |
207 DVLOG(2) << "GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange(): " | |
208 "bitrate=" << bitrate; | |
209 if (!encoder_) | |
210 return; | |
211 encoder_->RequestEncodingParameterChange(bitrate); | |
212 } | |
213 | |
214 void GpuVideoEncodeAccelerator::Send(IPC::Message* message) { | |
215 if (!channel_) { | |
216 DLOG(ERROR) << "GpuVideoEncodeAccelerator::Send(): no channel"; | |
217 delete message; | |
218 return; | |
219 } else if (!channel_->Send(message)) { | |
220 DLOG(ERROR) << "GpuVideoEncodeAccelerator::Send(): sending failed: " | |
221 "message->type()=" << message->type(); | |
222 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); | |
223 return; | |
224 } | |
225 } | |
226 | |
227 void GpuVideoEncodeAccelerator::EncodeFrameFinished( | |
228 scoped_ptr<base::SharedMemory> shm) { | |
229 // Just let shm fall out of scope. | |
230 } | |
231 | |
232 } // namespace content | |
OLD | NEW |