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

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

Issue 1681613002: Remove MediaCodecBridge::GetOutputBuffersCount() and GetOutputBuffersCapacity() (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 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
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/common/gpu/media/android_video_encode_accelerator.h" 5 #include "content/common/gpu/media/android_video_encode_accelerator.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 else if (formats.count(COLOR_FORMAT_YUV420_PLANAR) > 0) 88 else if (formats.count(COLOR_FORMAT_YUV420_PLANAR) > 0)
89 *pixel_format = COLOR_FORMAT_YUV420_PLANAR; 89 *pixel_format = COLOR_FORMAT_YUV420_PLANAR;
90 else 90 else
91 return false; 91 return false;
92 92
93 return true; 93 return true;
94 } 94 }
95 95
96 AndroidVideoEncodeAccelerator::AndroidVideoEncodeAccelerator() 96 AndroidVideoEncodeAccelerator::AndroidVideoEncodeAccelerator()
97 : num_buffers_at_codec_(0), 97 : num_buffers_at_codec_(0),
98 num_output_buffers_(-1),
99 output_buffers_capacity_(0),
100 last_set_bitrate_(0) {} 98 last_set_bitrate_(0) {}
101 99
102 AndroidVideoEncodeAccelerator::~AndroidVideoEncodeAccelerator() { 100 AndroidVideoEncodeAccelerator::~AndroidVideoEncodeAccelerator() {
103 DCHECK(thread_checker_.CalledOnValidThread()); 101 DCHECK(thread_checker_.CalledOnValidThread());
104 } 102 }
105 103
106 media::VideoEncodeAccelerator::SupportedProfiles 104 media::VideoEncodeAccelerator::SupportedProfiles
107 AndroidVideoEncodeAccelerator::GetSupportedProfiles() { 105 AndroidVideoEncodeAccelerator::GetSupportedProfiles() {
108 SupportedProfiles profiles; 106 SupportedProfiles profiles;
109 107
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); 155 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client));
158 156
159 if (!(media::MediaCodecUtil::SupportsSetParameters() && 157 if (!(media::MediaCodecUtil::SupportsSetParameters() &&
160 format == media::PIXEL_FORMAT_I420)) { 158 format == media::PIXEL_FORMAT_I420)) {
161 DLOG(ERROR) << "Unexpected combo: " << format << ", " << output_profile; 159 DLOG(ERROR) << "Unexpected combo: " << format << ", " << output_profile;
162 return false; 160 return false;
163 } 161 }
164 162
165 std::string mime_type; 163 std::string mime_type;
166 media::VideoCodec codec; 164 media::VideoCodec codec;
165 // The client should be prepared to feed at least this many frames into the
166 // encoder before being returned any output frames, since the encoder may
167 // need to hold onto some subset of inputs as reference pictures.
168 unsigned int frame_input_count;
DaleCurtis 2016/02/10 17:52:48 We don't use unsigned in Chromium code, this shoul
magjed_chromium 2016/02/10 20:25:12 Done, changed to uint32_t. The reason I used 'unsi
167 if (output_profile == media::VP8PROFILE_ANY) { 169 if (output_profile == media::VP8PROFILE_ANY) {
168 codec = media::kCodecVP8; 170 codec = media::kCodecVP8;
169 mime_type = "video/x-vnd.on2.vp8"; 171 mime_type = "video/x-vnd.on2.vp8";
172 frame_input_count = 1;
170 } else if (output_profile == media::H264PROFILE_BASELINE || 173 } else if (output_profile == media::H264PROFILE_BASELINE ||
171 output_profile == media::H264PROFILE_MAIN) { 174 output_profile == media::H264PROFILE_MAIN) {
172 codec = media::kCodecH264; 175 codec = media::kCodecH264;
173 mime_type = "video/avc"; 176 mime_type = "video/avc";
177 frame_input_count = 30;
174 } else { 178 } else {
175 return false; 179 return false;
176 } 180 }
177 181
182 frame_size_ = input_visible_size;
178 last_set_bitrate_ = initial_bitrate; 183 last_set_bitrate_ = initial_bitrate;
179 184
180 // Only consider using MediaCodec if it's likely backed by hardware. 185 // Only consider using MediaCodec if it's likely backed by hardware.
181 if (media::VideoCodecBridge::IsKnownUnaccelerated( 186 if (media::VideoCodecBridge::IsKnownUnaccelerated(
182 codec, media::MEDIA_CODEC_ENCODER)) { 187 codec, media::MEDIA_CODEC_ENCODER)) {
183 DLOG(ERROR) << "No HW support"; 188 DLOG(ERROR) << "No HW support";
184 return false; 189 return false;
185 } 190 }
186 191
187 PixelFormat pixel_format = COLOR_FORMAT_YUV420_SEMIPLANAR; 192 PixelFormat pixel_format = COLOR_FORMAT_YUV420_SEMIPLANAR;
188 if (!GetSupportedColorFormatForMime(mime_type, &pixel_format)) { 193 if (!GetSupportedColorFormatForMime(mime_type, &pixel_format)) {
189 DLOG(ERROR) << "No color format support."; 194 DLOG(ERROR) << "No color format support.";
190 return false; 195 return false;
191 } 196 }
192 media_codec_.reset(media::VideoCodecBridge::CreateEncoder(codec, 197 media_codec_.reset(media::VideoCodecBridge::CreateEncoder(codec,
193 input_visible_size, 198 input_visible_size,
194 initial_bitrate, 199 initial_bitrate,
195 INITIAL_FRAMERATE, 200 INITIAL_FRAMERATE,
196 IFRAME_INTERVAL, 201 IFRAME_INTERVAL,
197 pixel_format)); 202 pixel_format));
198 203
199 if (!media_codec_) { 204 if (!media_codec_) {
200 DLOG(ERROR) << "Failed to create/start the codec: " 205 DLOG(ERROR) << "Failed to create/start the codec: "
201 << input_visible_size.ToString(); 206 << input_visible_size.ToString();
202 return false; 207 return false;
203 } 208 }
204 209
205 num_output_buffers_ = media_codec_->GetOutputBuffersCount(); 210 // Conservative upper bound for output buffer size: decoded size + 2KB.
206 output_buffers_capacity_ = media_codec_->GetOutputBuffersCapacity(); 211 const size_t output_buffer_capacity =
212 VideoFrame::AllocationSize(format, input_visible_size) + 2048;
207 base::MessageLoop::current()->PostTask( 213 base::MessageLoop::current()->PostTask(
208 FROM_HERE, 214 FROM_HERE,
209 base::Bind(&VideoEncodeAccelerator::Client::RequireBitstreamBuffers, 215 base::Bind(&VideoEncodeAccelerator::Client::RequireBitstreamBuffers,
210 client_ptr_factory_->GetWeakPtr(), 216 client_ptr_factory_->GetWeakPtr(),
211 num_output_buffers_, 217 frame_input_count,
212 input_visible_size, 218 input_visible_size,
213 output_buffers_capacity_)); 219 output_buffer_capacity));
214 return true; 220 return true;
215 } 221 }
216 222
217 void AndroidVideoEncodeAccelerator::MaybeStartIOTimer() { 223 void AndroidVideoEncodeAccelerator::MaybeStartIOTimer() {
218 if (!io_timer_.IsRunning() && 224 if (!io_timer_.IsRunning() &&
219 (num_buffers_at_codec_ > 0 || !pending_frames_.empty())) { 225 (num_buffers_at_codec_ > 0 || !pending_frames_.empty())) {
220 io_timer_.Start(FROM_HERE, 226 io_timer_.Start(FROM_HERE,
221 EncodePollDelay(), 227 EncodePollDelay(),
222 this, 228 this,
223 &AndroidVideoEncodeAccelerator::DoIOTask); 229 &AndroidVideoEncodeAccelerator::DoIOTask);
224 } 230 }
225 } 231 }
226 232
227 void AndroidVideoEncodeAccelerator::MaybeStopIOTimer() { 233 void AndroidVideoEncodeAccelerator::MaybeStopIOTimer() {
228 if (io_timer_.IsRunning() && 234 if (io_timer_.IsRunning() &&
229 (num_buffers_at_codec_ == 0 && pending_frames_.empty())) { 235 (num_buffers_at_codec_ == 0 && pending_frames_.empty())) {
230 io_timer_.Stop(); 236 io_timer_.Stop();
231 } 237 }
232 } 238 }
233 239
234 void AndroidVideoEncodeAccelerator::Encode( 240 void AndroidVideoEncodeAccelerator::Encode(
235 const scoped_refptr<VideoFrame>& frame, 241 const scoped_refptr<VideoFrame>& frame,
236 bool force_keyframe) { 242 bool force_keyframe) {
237 DVLOG(3) << __PRETTY_FUNCTION__ << ": " << force_keyframe; 243 DVLOG(3) << __PRETTY_FUNCTION__ << ": " << force_keyframe;
238 DCHECK(thread_checker_.CalledOnValidThread()); 244 DCHECK(thread_checker_.CalledOnValidThread());
239 RETURN_ON_FAILURE(frame->format() == media::PIXEL_FORMAT_I420, 245 RETURN_ON_FAILURE(frame->format() == media::PIXEL_FORMAT_I420,
240 "Unexpected format", kInvalidArgumentError); 246 "Unexpected format", kInvalidArgumentError);
241 247 RETURN_ON_FAILURE(frame->visible_rect().size() == frame_size_,
248 "Unexpected resolution", kInvalidArgumentError);
242 // MediaCodec doesn't have a way to specify stride for non-Packed formats, so 249 // MediaCodec doesn't have a way to specify stride for non-Packed formats, so
243 // we insist on being called with packed frames and no cropping :( 250 // we insist on being called with packed frames and no cropping :(
244 RETURN_ON_FAILURE(frame->row_bytes(VideoFrame::kYPlane) == 251 RETURN_ON_FAILURE(frame->row_bytes(VideoFrame::kYPlane) ==
245 frame->stride(VideoFrame::kYPlane) && 252 frame->stride(VideoFrame::kYPlane) &&
246 frame->row_bytes(VideoFrame::kUPlane) == 253 frame->row_bytes(VideoFrame::kUPlane) ==
247 frame->stride(VideoFrame::kUPlane) && 254 frame->stride(VideoFrame::kUPlane) &&
248 frame->row_bytes(VideoFrame::kVPlane) == 255 frame->row_bytes(VideoFrame::kVPlane) ==
249 frame->stride(VideoFrame::kVPlane) && 256 frame->stride(VideoFrame::kVPlane) &&
250 frame->coded_size() == frame->visible_rect().size(), 257 frame->coded_size() == frame->visible_rect().size(),
251 "Non-packed frame, or visible_rect != coded_size", 258 "Non-packed frame, or visible_rect != coded_size",
252 kInvalidArgumentError); 259 kInvalidArgumentError);
253 260
254 pending_frames_.push( 261 pending_frames_.push(
255 base::MakeTuple(frame, force_keyframe, base::Time::Now())); 262 base::MakeTuple(frame, force_keyframe, base::Time::Now()));
256 DoIOTask(); 263 DoIOTask();
257 } 264 }
258 265
259 void AndroidVideoEncodeAccelerator::UseOutputBitstreamBuffer( 266 void AndroidVideoEncodeAccelerator::UseOutputBitstreamBuffer(
260 const media::BitstreamBuffer& buffer) { 267 const media::BitstreamBuffer& buffer) {
261 DVLOG(3) << __PRETTY_FUNCTION__ << ": bitstream_buffer_id=" << buffer.id(); 268 DVLOG(3) << __PRETTY_FUNCTION__ << ": bitstream_buffer_id=" << buffer.id();
262 DCHECK(thread_checker_.CalledOnValidThread()); 269 DCHECK(thread_checker_.CalledOnValidThread());
263 RETURN_ON_FAILURE(buffer.size() >= media_codec_->GetOutputBuffersCapacity(),
264 "Output buffers too small!",
265 kInvalidArgumentError);
266 available_bitstream_buffers_.push_back(buffer); 270 available_bitstream_buffers_.push_back(buffer);
267 DoIOTask(); 271 DoIOTask();
268 } 272 }
269 273
270 void AndroidVideoEncodeAccelerator::RequestEncodingParametersChange( 274 void AndroidVideoEncodeAccelerator::RequestEncodingParametersChange(
271 uint32_t bitrate, 275 uint32_t bitrate,
272 uint32_t framerate) { 276 uint32_t framerate) {
273 DVLOG(3) << __PRETTY_FUNCTION__ << ": bitrate: " << bitrate 277 DVLOG(3) << __PRETTY_FUNCTION__ << ": bitrate: " << bitrate
274 << ", framerate: " << framerate; 278 << ", framerate: " << framerate;
275 DCHECK(thread_checker_.CalledOnValidThread()); 279 DCHECK(thread_checker_.CalledOnValidThread());
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 input_buf_index, NULL, queued_size, fake_input_timestamp_); 370 input_buf_index, NULL, queued_size, fake_input_timestamp_);
367 UMA_HISTOGRAM_TIMES("Media.AVEA.InputQueueTime", 371 UMA_HISTOGRAM_TIMES("Media.AVEA.InputQueueTime",
368 base::Time::Now() - base::get<2>(input)); 372 base::Time::Now() - base::get<2>(input));
369 RETURN_ON_FAILURE(status == media::MEDIA_CODEC_OK, 373 RETURN_ON_FAILURE(status == media::MEDIA_CODEC_OK,
370 "Failed to QueueInputBuffer: " << status, 374 "Failed to QueueInputBuffer: " << status,
371 kPlatformFailureError); 375 kPlatformFailureError);
372 ++num_buffers_at_codec_; 376 ++num_buffers_at_codec_;
373 pending_frames_.pop(); 377 pending_frames_.pop();
374 } 378 }
375 379
376 bool AndroidVideoEncodeAccelerator::DoOutputBuffersSuffice() {
377 // If this returns false ever, then the VEA::Client interface will need to
378 // grow a DismissBitstreamBuffer() call, and VEA::Client impls will have to be
379 // prepared to field multiple requests to RequireBitstreamBuffers().
380 int count = media_codec_->GetOutputBuffersCount();
381 size_t capacity = media_codec_->GetOutputBuffersCapacity();
382 bool ret = count <= num_output_buffers_ &&
383 capacity <= output_buffers_capacity_;
384 LOG_IF(ERROR, !ret) << "Need more/bigger buffers; before: "
385 << num_output_buffers_ << "x" << output_buffers_capacity_
386 << ", now: " << count << "x" << capacity;
387 UMA_HISTOGRAM_BOOLEAN("Media.AVEA.OutputBuffersSuffice", ret);
388 return ret;
389 }
390
391 void AndroidVideoEncodeAccelerator::DequeueOutput() { 380 void AndroidVideoEncodeAccelerator::DequeueOutput() {
392 if (!client_ptr_factory_->GetWeakPtr() || 381 if (!client_ptr_factory_->GetWeakPtr() ||
393 available_bitstream_buffers_.empty() || num_buffers_at_codec_ == 0) { 382 available_bitstream_buffers_.empty() || num_buffers_at_codec_ == 0) {
394 return; 383 return;
395 } 384 }
396 385
397 int32_t buf_index = 0; 386 int32_t buf_index = 0;
398 size_t offset = 0; 387 size_t offset = 0;
399 size_t size = 0; 388 size_t size = 0;
400 bool key_frame = false; 389 bool key_frame = false;
401 do { 390 do {
402 media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer( 391 media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer(
403 NoWaitTimeOut(), &buf_index, &offset, &size, NULL, NULL, &key_frame); 392 NoWaitTimeOut(), &buf_index, &offset, &size, NULL, NULL, &key_frame);
404 switch (status) { 393 switch (status) {
405 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: 394 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
406 return; 395 return;
407 396
408 case media::MEDIA_CODEC_ERROR: 397 case media::MEDIA_CODEC_ERROR:
409 RETURN_ON_FAILURE(false, "Codec error", kPlatformFailureError); 398 RETURN_ON_FAILURE(false, "Codec error", kPlatformFailureError);
410 // Unreachable because of previous statement, but included for clarity. 399 // Unreachable because of previous statement, but included for clarity.
411 return; 400 return;
412 401
413 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: // Fall-through. 402 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED:
403 int width;
404 int height;
405 media_codec_->GetOutputFormat(&width, &height);
liberato (no reviews please) 2016/02/10 18:40:09 i don't understand the goal of asking for output s
magjed_chromium 2016/02/10 20:25:12 It's just a sanity check to make sure the resoluti
406 RETURN_ON_FAILURE(
407 width == frame_size_.width() && height == frame_size_.height(),
408 "Unexpected resolution change. input: "
409 << frame_size_.width() << "x" << frame_size_.height()
410 << ", output: " << width << "x" << height,
411 kPlatformFailureError);
412 break;
413
414 case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: 414 case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
415 RETURN_ON_FAILURE(DoOutputBuffersSuffice(),
416 "Bitstream now requires more/larger buffers",
417 kPlatformFailureError);
418 break; 415 break;
419 416
420 case media::MEDIA_CODEC_OK: 417 case media::MEDIA_CODEC_OK:
421 DCHECK_GE(buf_index, 0); 418 DCHECK_GE(buf_index, 0);
422 break; 419 break;
423 420
424 default: 421 default:
425 NOTREACHED(); 422 NOTREACHED();
426 break; 423 break;
427 } 424 }
(...skipping 19 matching lines...) Expand all
447 base::MessageLoop::current()->PostTask( 444 base::MessageLoop::current()->PostTask(
448 FROM_HERE, 445 FROM_HERE,
449 base::Bind(&VideoEncodeAccelerator::Client::BitstreamBufferReady, 446 base::Bind(&VideoEncodeAccelerator::Client::BitstreamBufferReady,
450 client_ptr_factory_->GetWeakPtr(), 447 client_ptr_factory_->GetWeakPtr(),
451 bitstream_buffer.id(), 448 bitstream_buffer.id(),
452 size, 449 size,
453 key_frame)); 450 key_frame));
454 } 451 }
455 452
456 } // namespace content 453 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698