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

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 (!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
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
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
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
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
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
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