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

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

Issue 2601003002: Android: Fix random crash in HW encode accelerator (Closed)
Patch Set: address comments Created 3 years, 11 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
« no previous file with comments | « media/gpu/android_video_encode_accelerator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « media/gpu/android_video_encode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698