Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "media/gpu/android_video_encode_accelerator.h" | 5 #include "media/gpu/android_video_encode_accelerator.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <set> | 8 #include <set> |
| 9 #include <tuple> | 9 #include <tuple> |
| 10 | 10 |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 133 } | 133 } |
| 134 return profiles; | 134 return profiles; |
| 135 } | 135 } |
| 136 | 136 |
| 137 bool AndroidVideoEncodeAccelerator::Initialize( | 137 bool AndroidVideoEncodeAccelerator::Initialize( |
| 138 VideoPixelFormat format, | 138 VideoPixelFormat format, |
| 139 const gfx::Size& input_visible_size, | 139 const gfx::Size& input_visible_size, |
| 140 VideoCodecProfile output_profile, | 140 VideoCodecProfile output_profile, |
| 141 uint32_t initial_bitrate, | 141 uint32_t initial_bitrate, |
| 142 Client* client) { | 142 Client* client) { |
| 143 DVLOG(3) << __PRETTY_FUNCTION__ << " format: " << format | 143 DVLOG(3) << __func__ << " format: " << VideoPixelFormatToString(format) |
| 144 << ", input_visible_size: " << input_visible_size.ToString() | 144 << ", input_visible_size: " << input_visible_size.ToString() |
| 145 << ", output_profile: " << output_profile | 145 << ", output_profile: " << GetProfileName(output_profile) |
| 146 << ", initial_bitrate: " << initial_bitrate; | 146 << ", initial_bitrate: " << initial_bitrate; |
| 147 DCHECK(!media_codec_); | 147 DCHECK(!media_codec_); |
| 148 DCHECK(thread_checker_.CalledOnValidThread()); | 148 DCHECK(thread_checker_.CalledOnValidThread()); |
| 149 | 149 |
| 150 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); | 150 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); |
| 151 | 151 |
| 152 if (!(MediaCodecUtil::SupportsSetParameters() && | 152 if (!(MediaCodecUtil::SupportsSetParameters() && |
| 153 format == PIXEL_FORMAT_I420)) { | 153 format == PIXEL_FORMAT_I420)) { |
| 154 DLOG(ERROR) << "Unexpected combo: " << format << ", " << output_profile; | 154 DLOG(ERROR) << "Unexpected combo: " << format << ", " << output_profile; |
| 155 return false; | 155 return false; |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 312 bool is_key_frame = std::get<1>(input); | 312 bool is_key_frame = std::get<1>(input); |
| 313 if (is_key_frame) { | 313 if (is_key_frame) { |
| 314 // Ideally MediaCodec would honor BUFFER_FLAG_SYNC_FRAME so we could | 314 // Ideally MediaCodec would honor BUFFER_FLAG_SYNC_FRAME so we could |
| 315 // indicate this in the QueueInputBuffer() call below and guarantee _this_ | 315 // indicate this in the QueueInputBuffer() call below and guarantee _this_ |
| 316 // frame be encoded as a key frame, but sadly that flag is ignored. | 316 // frame be encoded as a key frame, but sadly that flag is ignored. |
| 317 // Instead, we request a key frame "soon". | 317 // Instead, we request a key frame "soon". |
| 318 media_codec_->RequestKeyFrameSoon(); | 318 media_codec_->RequestKeyFrameSoon(); |
| 319 } | 319 } |
| 320 scoped_refptr<VideoFrame> frame = std::get<0>(input); | 320 scoped_refptr<VideoFrame> frame = std::get<0>(input); |
| 321 | 321 |
| 322 uint8_t* buffer = NULL; | 322 uint8_t* buffer = NULL; |
|
watk
2016/08/18 18:12:15
s/NULL/nullptr
mcasas
2016/08/18 19:24:40
Done.
| |
| 323 size_t capacity = 0; | 323 size_t capacity = 0; |
| 324 status = media_codec_->GetInputBuffer(input_buf_index, &buffer, &capacity); | 324 status = media_codec_->GetInputBuffer(input_buf_index, &buffer, &capacity); |
| 325 RETURN_ON_FAILURE(status == MEDIA_CODEC_OK, "GetInputBuffer failed.", | 325 RETURN_ON_FAILURE(status == MEDIA_CODEC_OK, "GetInputBuffer failed.", |
| 326 kPlatformFailureError); | 326 kPlatformFailureError); |
| 327 | 327 |
| 328 size_t queued_size = | 328 size_t queued_size = |
| 329 VideoFrame::AllocationSize(PIXEL_FORMAT_I420, frame->coded_size()); | 329 VideoFrame::AllocationSize(PIXEL_FORMAT_I420, frame->coded_size()); |
| 330 RETURN_ON_FAILURE(capacity >= queued_size, | 330 RETURN_ON_FAILURE(capacity >= queued_size, |
| 331 "Failed to get input buffer: " << input_buf_index, | 331 "Failed to get input buffer: " << input_buf_index, |
| 332 kPlatformFailureError); | 332 kPlatformFailureError); |
| 333 | 333 |
| 334 uint8_t* dst_y = buffer; | 334 uint8_t* dst_y = buffer; |
| 335 int dst_stride_y = frame->stride(VideoFrame::kYPlane); | 335 int dst_stride_y = frame->stride(VideoFrame::kYPlane); |
| 336 uint8_t* dst_uv = | 336 uint8_t* dst_uv = |
| 337 buffer + | 337 buffer + |
| 338 frame->stride(VideoFrame::kYPlane) * frame->rows(VideoFrame::kYPlane); | 338 frame->stride(VideoFrame::kYPlane) * frame->rows(VideoFrame::kYPlane); |
| 339 int dst_stride_uv = frame->stride(VideoFrame::kUPlane) * 2; | 339 int dst_stride_uv = frame->stride(VideoFrame::kUPlane) * 2; |
| 340 // Why NV12? Because COLOR_FORMAT_YUV420_SEMIPLANAR. See comment at other | 340 // Why NV12? Because COLOR_FORMAT_YUV420_SEMIPLANAR. See comment at other |
| 341 // mention of that constant. | 341 // mention of that constant. |
| 342 bool converted = !libyuv::I420ToNV12( | 342 bool converted = !libyuv::I420ToNV12( |
| 343 frame->data(VideoFrame::kYPlane), frame->stride(VideoFrame::kYPlane), | 343 frame->data(VideoFrame::kYPlane), frame->stride(VideoFrame::kYPlane), |
| 344 frame->data(VideoFrame::kUPlane), frame->stride(VideoFrame::kUPlane), | 344 frame->data(VideoFrame::kUPlane), frame->stride(VideoFrame::kUPlane), |
| 345 frame->data(VideoFrame::kVPlane), frame->stride(VideoFrame::kVPlane), | 345 frame->data(VideoFrame::kVPlane), frame->stride(VideoFrame::kVPlane), |
| 346 dst_y, dst_stride_y, dst_uv, dst_stride_uv, frame->coded_size().width(), | 346 dst_y, dst_stride_y, dst_uv, dst_stride_uv, frame->coded_size().width(), |
| 347 frame->coded_size().height()); | 347 frame->coded_size().height()); |
| 348 RETURN_ON_FAILURE(converted, "Failed to I420ToNV12!", kPlatformFailureError); | 348 RETURN_ON_FAILURE(converted, "Failed to I420ToNV12!", kPlatformFailureError); |
| 349 | 349 |
| 350 fake_input_timestamp_ += base::TimeDelta::FromMicroseconds(1); | 350 fake_input_timestamp_ += base::TimeDelta::FromMicroseconds(1); |
| 351 status = media_codec_->QueueInputBuffer(input_buf_index, NULL, queued_size, | 351 status = media_codec_->QueueInputBuffer(input_buf_index, NULL, queued_size, |
|
watk
2016/08/18 18:12:15
s/NULL/nullptr
mcasas
2016/08/18 19:24:40
Done.
| |
| 352 fake_input_timestamp_); | 352 fake_input_timestamp_); |
| 353 UMA_HISTOGRAM_TIMES("Media.AVDA.InputQueueTime", | 353 UMA_HISTOGRAM_TIMES("Media.AVDA.InputQueueTime", |
| 354 base::Time::Now() - std::get<2>(input)); | 354 base::Time::Now() - std::get<2>(input)); |
| 355 RETURN_ON_FAILURE(status == MEDIA_CODEC_OK, | 355 RETURN_ON_FAILURE(status == MEDIA_CODEC_OK, |
| 356 "Failed to QueueInputBuffer: " << status, | 356 "Failed to QueueInputBuffer: " << status, |
| 357 kPlatformFailureError); | 357 kPlatformFailureError); |
| 358 ++num_buffers_at_codec_; | 358 ++num_buffers_at_codec_; |
| 359 pending_frames_.pop(); | 359 pending_frames_.pop(); |
| 360 } | 360 } |
| 361 | 361 |
| 362 void AndroidVideoEncodeAccelerator::DequeueOutput() { | 362 void AndroidVideoEncodeAccelerator::DequeueOutput() { |
| 363 if (!client_ptr_factory_->GetWeakPtr() || | 363 if (!client_ptr_factory_->GetWeakPtr() || |
| 364 available_bitstream_buffers_.empty() || num_buffers_at_codec_ == 0) { | 364 available_bitstream_buffers_.empty() || num_buffers_at_codec_ == 0) { |
| 365 return; | 365 return; |
| 366 } | 366 } |
| 367 | 367 |
| 368 int32_t buf_index = 0; | 368 int32_t buf_index = 0; |
| 369 size_t offset = 0; | 369 size_t offset = 0; |
| 370 size_t size = 0; | 370 size_t size = 0; |
| 371 bool key_frame = false; | 371 bool key_frame = false; |
| 372 do { | 372 do { |
| 373 MediaCodecStatus status = media_codec_->DequeueOutputBuffer( | 373 MediaCodecStatus status = media_codec_->DequeueOutputBuffer( |
| 374 NoWaitTimeOut(), &buf_index, &offset, &size, NULL, NULL, &key_frame); | 374 NoWaitTimeOut(), &buf_index, &offset, &size, NULL, NULL, &key_frame); |
|
watk
2016/08/18 18:12:15
s/NULL/nullptr
mcasas
2016/08/18 19:24:40
Done.
| |
| 375 switch (status) { | 375 switch (status) { |
| 376 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: | 376 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: |
| 377 return; | 377 return; |
| 378 | 378 |
| 379 case MEDIA_CODEC_ERROR: | 379 case MEDIA_CODEC_ERROR: |
| 380 RETURN_ON_FAILURE(false, "Codec error", kPlatformFailureError); | 380 RETURN_ON_FAILURE(false, "Codec error", kPlatformFailureError); |
| 381 // Unreachable because of previous statement, but included for clarity. | 381 // Unreachable because of previous statement, but included for clarity. |
| 382 return; | 382 return; |
| 383 | 383 |
| 384 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: | 384 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 416 --num_buffers_at_codec_; | 416 --num_buffers_at_codec_; |
| 417 | 417 |
| 418 base::ThreadTaskRunnerHandle::Get()->PostTask( | 418 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 419 FROM_HERE, | 419 FROM_HERE, |
| 420 base::Bind(&VideoEncodeAccelerator::Client::BitstreamBufferReady, | 420 base::Bind(&VideoEncodeAccelerator::Client::BitstreamBufferReady, |
| 421 client_ptr_factory_->GetWeakPtr(), bitstream_buffer.id(), size, | 421 client_ptr_factory_->GetWeakPtr(), bitstream_buffer.id(), size, |
| 422 key_frame, base::Time::Now() - base::Time())); | 422 key_frame, base::Time::Now() - base::Time())); |
| 423 } | 423 } |
| 424 | 424 |
| 425 } // namespace media | 425 } // namespace media |
| OLD | NEW |