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 (client_ptr_factory_->GetWeakPtr()) { \ |
watk
2016/12/28 01:01:51
It's not possible for this to be null AFAICT. Shou
braveyao
2016/12/28 01:28:18
Done.
| |
51 client_ptr_factory_->GetWeakPtr()->NotifyError(error); \ | 51 client_ptr_factory_->GetWeakPtr()->NotifyError(error); \ |
52 client_ptr_factory_.reset(); \ | |
53 } \ | 52 } \ |
53 error_occurred_ = true; \ | |
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. |
63 // Mirrors android_video_decode_accelerator.cc::DecodePollDelay(). | 63 // Mirrors android_video_decode_accelerator.cc::DecodePollDelay(). |
(...skipping 23 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 | 153 |
154 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); | 154 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); |
watk
2016/12/28 01:01:51
I'd suggest adding a DCHECK(client) or if (!client
braveyao
2016/12/28 01:28:18
Done.
| |
155 error_occurred_ = false; | |
watk
2016/12/28 01:01:51
Initialize() cannot be called more than once so th
braveyao
2016/12/28 01:28:18
Done.
| |
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; |
163 VideoCodec codec; | 164 VideoCodec codec; |
164 // The client should be prepared to feed at least this many frames into the | 165 // The client should be prepared to feed at least this many frames into the |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
278 // Note: Android's MediaCodec doesn't allow mid-stream adjustments to | 279 // Note: Android's MediaCodec doesn't allow mid-stream adjustments to |
279 // framerate, so we ignore that here. This is OK because Android only uses | 280 // framerate, so we ignore that here. This is OK because Android only uses |
280 // the framerate value from MediaFormat during configure() as a proxy for | 281 // the framerate value from MediaFormat during configure() as a proxy for |
281 // bitrate, and we set that explicitly. | 282 // bitrate, and we set that explicitly. |
282 } | 283 } |
283 | 284 |
284 void AndroidVideoEncodeAccelerator::Destroy() { | 285 void AndroidVideoEncodeAccelerator::Destroy() { |
285 DVLOG(3) << __PRETTY_FUNCTION__; | 286 DVLOG(3) << __PRETTY_FUNCTION__; |
286 DCHECK(thread_checker_.CalledOnValidThread()); | 287 DCHECK(thread_checker_.CalledOnValidThread()); |
287 client_ptr_factory_.reset(); | 288 client_ptr_factory_.reset(); |
289 error_occurred_ = false; | |
watk
2016/12/28 01:01:51
No need to reset this, we're deleting below. (The
braveyao
2016/12/28 01:28:18
Done.
| |
288 if (media_codec_) { | 290 if (media_codec_) { |
289 if (io_timer_.IsRunning()) | 291 if (io_timer_.IsRunning()) |
290 io_timer_.Stop(); | 292 io_timer_.Stop(); |
291 media_codec_->Stop(); | 293 media_codec_->Stop(); |
292 } | 294 } |
293 delete this; | 295 delete this; |
294 } | 296 } |
295 | 297 |
296 void AndroidVideoEncodeAccelerator::DoIOTask() { | 298 void AndroidVideoEncodeAccelerator::DoIOTask() { |
297 QueueInput(); | 299 QueueInput(); |
298 DequeueOutput(); | 300 DequeueOutput(); |
299 MaybeStartIOTimer(); | 301 MaybeStartIOTimer(); |
300 MaybeStopIOTimer(); | 302 MaybeStopIOTimer(); |
301 } | 303 } |
302 | 304 |
303 void AndroidVideoEncodeAccelerator::QueueInput() { | 305 void AndroidVideoEncodeAccelerator::QueueInput() { |
304 if (!client_ptr_factory_->GetWeakPtr() || pending_frames_.empty()) | 306 if (error_occurred_ || pending_frames_.empty()) |
305 return; | 307 return; |
306 | 308 |
307 int input_buf_index = 0; | 309 int input_buf_index = 0; |
308 MediaCodecStatus status = | 310 MediaCodecStatus status = |
309 media_codec_->DequeueInputBuffer(NoWaitTimeOut(), &input_buf_index); | 311 media_codec_->DequeueInputBuffer(NoWaitTimeOut(), &input_buf_index); |
310 if (status != MEDIA_CODEC_OK) { | 312 if (status != MEDIA_CODEC_OK) { |
311 DCHECK(status == MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER || | 313 DCHECK(status == MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER || |
312 status == MEDIA_CODEC_ERROR); | 314 status == MEDIA_CODEC_ERROR); |
313 RETURN_ON_FAILURE(status != MEDIA_CODEC_ERROR, "MediaCodec error", | 315 RETURN_ON_FAILURE(status != MEDIA_CODEC_ERROR, "MediaCodec error", |
314 kPlatformFailureError); | 316 kPlatformFailureError); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
361 UMA_HISTOGRAM_TIMES("Media.AVDA.InputQueueTime", | 363 UMA_HISTOGRAM_TIMES("Media.AVDA.InputQueueTime", |
362 base::Time::Now() - std::get<2>(input)); | 364 base::Time::Now() - std::get<2>(input)); |
363 RETURN_ON_FAILURE(status == MEDIA_CODEC_OK, | 365 RETURN_ON_FAILURE(status == MEDIA_CODEC_OK, |
364 "Failed to QueueInputBuffer: " << status, | 366 "Failed to QueueInputBuffer: " << status, |
365 kPlatformFailureError); | 367 kPlatformFailureError); |
366 ++num_buffers_at_codec_; | 368 ++num_buffers_at_codec_; |
367 pending_frames_.pop(); | 369 pending_frames_.pop(); |
368 } | 370 } |
369 | 371 |
370 void AndroidVideoEncodeAccelerator::DequeueOutput() { | 372 void AndroidVideoEncodeAccelerator::DequeueOutput() { |
371 if (!client_ptr_factory_->GetWeakPtr() || | 373 if (error_occurred_ || available_bitstream_buffers_.empty() || |
372 available_bitstream_buffers_.empty() || num_buffers_at_codec_ == 0) { | 374 num_buffers_at_codec_ == 0) { |
373 return; | 375 return; |
374 } | 376 } |
375 | 377 |
376 int32_t buf_index = 0; | 378 int32_t buf_index = 0; |
377 size_t offset = 0; | 379 size_t offset = 0; |
378 size_t size = 0; | 380 size_t size = 0; |
379 bool key_frame = false; | 381 bool key_frame = false; |
380 | 382 |
381 MediaCodecStatus status = | 383 MediaCodecStatus status = |
382 media_codec_->DequeueOutputBuffer(NoWaitTimeOut(), &buf_index, &offset, | 384 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_; | 424 --num_buffers_at_codec_; |
423 | 425 |
424 base::ThreadTaskRunnerHandle::Get()->PostTask( | 426 base::ThreadTaskRunnerHandle::Get()->PostTask( |
425 FROM_HERE, | 427 FROM_HERE, |
426 base::Bind(&VideoEncodeAccelerator::Client::BitstreamBufferReady, | 428 base::Bind(&VideoEncodeAccelerator::Client::BitstreamBufferReady, |
427 client_ptr_factory_->GetWeakPtr(), bitstream_buffer.id(), size, | 429 client_ptr_factory_->GetWeakPtr(), bitstream_buffer.id(), size, |
428 key_frame, base::Time::Now() - base::Time())); | 430 key_frame, base::Time::Now() - base::Time())); |
429 } | 431 } |
430 | 432 |
431 } // namespace media | 433 } // namespace media |
OLD | NEW |