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 29 matching lines...) Expand all Loading... |
40 COLOR_FORMAT_YUV420_PLANAR = 19, | 40 COLOR_FORMAT_YUV420_PLANAR = 19, |
41 COLOR_FORMAT_YUV420_SEMIPLANAR = 21, | 41 COLOR_FORMAT_YUV420_SEMIPLANAR = 21, |
42 }; | 42 }; |
43 | 43 |
44 // Helper macros for dealing with failure. If |result| evaluates false, emit | 44 // Helper macros for dealing with failure. If |result| evaluates false, emit |
45 // |log| to DLOG(ERROR), register |error| with the client, and return. | 45 // |log| to DLOG(ERROR), register |error| with the client, and return. |
46 #define RETURN_ON_FAILURE(result, log, error) \ | 46 #define RETURN_ON_FAILURE(result, log, error) \ |
47 do { \ | 47 do { \ |
48 if (!(result)) { \ | 48 if (!(result)) { \ |
49 DLOG(ERROR) << log; \ | 49 DLOG(ERROR) << log; \ |
50 if (client_ptr_factory_->GetWeakPtr()) { \ | 50 if (!error_occurred_) { \ |
51 client_ptr_factory_->GetWeakPtr()->NotifyError(error); \ | 51 client_ptr_factory_->GetWeakPtr()->NotifyError(error); \ |
52 client_ptr_factory_.reset(); \ | 52 error_occurred_ = true; \ |
53 } \ | 53 } \ |
54 return; \ | 54 return; \ |
55 } \ | 55 } \ |
56 } while (0) | 56 } while (0) |
57 | 57 |
58 // Because MediaCodec is thread-hostile (must be poked on a single thread) and | 58 // Because MediaCodec is thread-hostile (must be poked on a single thread) and |
59 // has no callback mechanism (b/11990118), we must drive it by polling for | 59 // has no callback mechanism (b/11990118), we must drive it by polling for |
60 // complete frames (and available input buffers, when the codec is fully | 60 // complete frames (and available input buffers, when the codec is fully |
61 // saturated). This function defines the polling delay. The value used is an | 61 // saturated). This function defines the polling delay. The value used is an |
62 // arbitrary choice that trades off CPU utilization (spinning) against latency. | 62 // arbitrary choice that trades off CPU utilization (spinning) against latency. |
(...skipping 24 matching lines...) Expand all Loading... |
87 *pixel_format = COLOR_FORMAT_YUV420_SEMIPLANAR; | 87 *pixel_format = COLOR_FORMAT_YUV420_SEMIPLANAR; |
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), last_set_bitrate_(0) {} | 97 : num_buffers_at_codec_(0), last_set_bitrate_(0), error_occurred_(false) {} |
98 | 98 |
99 AndroidVideoEncodeAccelerator::~AndroidVideoEncodeAccelerator() { | 99 AndroidVideoEncodeAccelerator::~AndroidVideoEncodeAccelerator() { |
100 DCHECK(thread_checker_.CalledOnValidThread()); | 100 DCHECK(thread_checker_.CalledOnValidThread()); |
101 } | 101 } |
102 | 102 |
103 VideoEncodeAccelerator::SupportedProfiles | 103 VideoEncodeAccelerator::SupportedProfiles |
104 AndroidVideoEncodeAccelerator::GetSupportedProfiles() { | 104 AndroidVideoEncodeAccelerator::GetSupportedProfiles() { |
105 SupportedProfiles profiles; | 105 SupportedProfiles profiles; |
106 | 106 |
107 const struct { | 107 const struct { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 const gfx::Size& input_visible_size, | 143 const gfx::Size& input_visible_size, |
144 VideoCodecProfile output_profile, | 144 VideoCodecProfile output_profile, |
145 uint32_t initial_bitrate, | 145 uint32_t initial_bitrate, |
146 Client* client) { | 146 Client* client) { |
147 DVLOG(3) << __func__ << " format: " << VideoPixelFormatToString(format) | 147 DVLOG(3) << __func__ << " format: " << VideoPixelFormatToString(format) |
148 << ", input_visible_size: " << input_visible_size.ToString() | 148 << ", input_visible_size: " << input_visible_size.ToString() |
149 << ", output_profile: " << GetProfileName(output_profile) | 149 << ", output_profile: " << GetProfileName(output_profile) |
150 << ", initial_bitrate: " << initial_bitrate; | 150 << ", initial_bitrate: " << initial_bitrate; |
151 DCHECK(!media_codec_); | 151 DCHECK(!media_codec_); |
152 DCHECK(thread_checker_.CalledOnValidThread()); | 152 DCHECK(thread_checker_.CalledOnValidThread()); |
| 153 DCHECK(client); |
153 | 154 |
154 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); | 155 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); |
155 | 156 |
156 if (!(MediaCodecUtil::SupportsSetParameters() && | 157 if (!(MediaCodecUtil::SupportsSetParameters() && |
157 format == PIXEL_FORMAT_I420)) { | 158 format == PIXEL_FORMAT_I420)) { |
158 DLOG(ERROR) << "Unexpected combo: " << format << ", " << output_profile; | 159 DLOG(ERROR) << "Unexpected combo: " << format << ", " << output_profile; |
159 return false; | 160 return false; |
160 } | 161 } |
161 | 162 |
162 std::string mime_type; | 163 std::string mime_type; |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 } | 295 } |
295 | 296 |
296 void AndroidVideoEncodeAccelerator::DoIOTask() { | 297 void AndroidVideoEncodeAccelerator::DoIOTask() { |
297 QueueInput(); | 298 QueueInput(); |
298 DequeueOutput(); | 299 DequeueOutput(); |
299 MaybeStartIOTimer(); | 300 MaybeStartIOTimer(); |
300 MaybeStopIOTimer(); | 301 MaybeStopIOTimer(); |
301 } | 302 } |
302 | 303 |
303 void AndroidVideoEncodeAccelerator::QueueInput() { | 304 void AndroidVideoEncodeAccelerator::QueueInput() { |
304 if (!client_ptr_factory_->GetWeakPtr() || pending_frames_.empty()) | 305 if (error_occurred_ || pending_frames_.empty()) |
305 return; | 306 return; |
306 | 307 |
307 int input_buf_index = 0; | 308 int input_buf_index = 0; |
308 MediaCodecStatus status = | 309 MediaCodecStatus status = |
309 media_codec_->DequeueInputBuffer(NoWaitTimeOut(), &input_buf_index); | 310 media_codec_->DequeueInputBuffer(NoWaitTimeOut(), &input_buf_index); |
310 if (status != MEDIA_CODEC_OK) { | 311 if (status != MEDIA_CODEC_OK) { |
311 DCHECK(status == MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER || | 312 DCHECK(status == MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER || |
312 status == MEDIA_CODEC_ERROR); | 313 status == MEDIA_CODEC_ERROR); |
313 RETURN_ON_FAILURE(status != MEDIA_CODEC_ERROR, "MediaCodec error", | 314 RETURN_ON_FAILURE(status != MEDIA_CODEC_ERROR, "MediaCodec error", |
314 kPlatformFailureError); | 315 kPlatformFailureError); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 UMA_HISTOGRAM_TIMES("Media.AVDA.InputQueueTime", | 362 UMA_HISTOGRAM_TIMES("Media.AVDA.InputQueueTime", |
362 base::Time::Now() - std::get<2>(input)); | 363 base::Time::Now() - std::get<2>(input)); |
363 RETURN_ON_FAILURE(status == MEDIA_CODEC_OK, | 364 RETURN_ON_FAILURE(status == MEDIA_CODEC_OK, |
364 "Failed to QueueInputBuffer: " << status, | 365 "Failed to QueueInputBuffer: " << status, |
365 kPlatformFailureError); | 366 kPlatformFailureError); |
366 ++num_buffers_at_codec_; | 367 ++num_buffers_at_codec_; |
367 pending_frames_.pop(); | 368 pending_frames_.pop(); |
368 } | 369 } |
369 | 370 |
370 void AndroidVideoEncodeAccelerator::DequeueOutput() { | 371 void AndroidVideoEncodeAccelerator::DequeueOutput() { |
371 if (!client_ptr_factory_->GetWeakPtr() || | 372 if (error_occurred_ || available_bitstream_buffers_.empty() || |
372 available_bitstream_buffers_.empty() || num_buffers_at_codec_ == 0) { | 373 num_buffers_at_codec_ == 0) { |
373 return; | 374 return; |
374 } | 375 } |
375 | 376 |
376 int32_t buf_index = 0; | 377 int32_t buf_index = 0; |
377 size_t offset = 0; | 378 size_t offset = 0; |
378 size_t size = 0; | 379 size_t size = 0; |
379 bool key_frame = false; | 380 bool key_frame = false; |
380 | 381 |
381 MediaCodecStatus status = | 382 MediaCodecStatus status = |
382 media_codec_->DequeueOutputBuffer(NoWaitTimeOut(), &buf_index, &offset, | 383 media_codec_->DequeueOutputBuffer(NoWaitTimeOut(), &buf_index, &offset, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 --num_buffers_at_codec_; | 423 --num_buffers_at_codec_; |
423 | 424 |
424 base::ThreadTaskRunnerHandle::Get()->PostTask( | 425 base::ThreadTaskRunnerHandle::Get()->PostTask( |
425 FROM_HERE, | 426 FROM_HERE, |
426 base::Bind(&VideoEncodeAccelerator::Client::BitstreamBufferReady, | 427 base::Bind(&VideoEncodeAccelerator::Client::BitstreamBufferReady, |
427 client_ptr_factory_->GetWeakPtr(), bitstream_buffer.id(), size, | 428 client_ptr_factory_->GetWeakPtr(), bitstream_buffer.id(), size, |
428 key_frame, base::Time::Now() - base::Time())); | 429 key_frame, base::Time::Now() - base::Time())); |
429 } | 430 } |
430 | 431 |
431 } // namespace media | 432 } // namespace media |
OLD | NEW |