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

Side by Side Diff: media/base/android/media_codec_decoder.cc

Issue 1254293003: MediaCodecPlayer implementation (stage 4 - preroll) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mtplayer-browserseek
Patch Set: Rebased Created 5 years, 4 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/base/android/media_codec_decoder.h" 5 #include "media/base/android/media_codec_decoder.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/callback_helpers.h" 9 #include "base/callback_helpers.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 28 matching lines...) Expand all
39 const base::Closure& error_cb, 39 const base::Closure& error_cb,
40 const char* decoder_thread_name) 40 const char* decoder_thread_name)
41 : media_task_runner_(media_task_runner), 41 : media_task_runner_(media_task_runner),
42 decoder_thread_(decoder_thread_name), 42 decoder_thread_(decoder_thread_name),
43 needs_reconfigure_(false), 43 needs_reconfigure_(false),
44 external_request_data_cb_(external_request_data_cb), 44 external_request_data_cb_(external_request_data_cb),
45 starvation_cb_(starvation_cb), 45 starvation_cb_(starvation_cb),
46 stop_done_cb_(stop_done_cb), 46 stop_done_cb_(stop_done_cb),
47 error_cb_(error_cb), 47 error_cb_(error_cb),
48 state_(kStopped), 48 state_(kStopped),
49 needs_preroll_(true),
49 eos_enqueued_(false), 50 eos_enqueued_(false),
50 completed_(false), 51 completed_(false),
51 last_frame_posted_(false), 52 last_frame_posted_(false),
52 is_data_request_in_progress_(false), 53 is_data_request_in_progress_(false),
53 is_incoming_data_invalid_(false), 54 is_incoming_data_invalid_(false),
54 #ifndef NDEBUG 55 #ifndef NDEBUG
55 verify_next_frame_is_key_(false), 56 verify_next_frame_is_key_(false),
56 #endif 57 #endif
57 weak_factory_(this) { 58 weak_factory_(this) {
58 DCHECK(media_task_runner_->BelongsToCurrentThread()); 59 DCHECK(media_task_runner_->BelongsToCurrentThread());
59 60
60 DVLOG(1) << "Decoder::Decoder() " << decoder_thread_name; 61 DVLOG(1) << "Decoder::Decoder() " << decoder_thread_name;
61 62
62 internal_error_cb_ = 63 internal_error_cb_ =
63 base::Bind(&MediaCodecDecoder::OnCodecError, weak_factory_.GetWeakPtr()); 64 base::Bind(&MediaCodecDecoder::OnCodecError, weak_factory_.GetWeakPtr());
65 internal_preroll_done_cb_ =
66 base::Bind(&MediaCodecDecoder::OnPrerollDone, weak_factory_.GetWeakPtr());
64 request_data_cb_ = 67 request_data_cb_ =
65 base::Bind(&MediaCodecDecoder::RequestData, weak_factory_.GetWeakPtr()); 68 base::Bind(&MediaCodecDecoder::RequestData, weak_factory_.GetWeakPtr());
66 } 69 }
67 70
68 MediaCodecDecoder::~MediaCodecDecoder() { 71 MediaCodecDecoder::~MediaCodecDecoder() {}
69 DCHECK(media_task_runner_->BelongsToCurrentThread());
70
71 DVLOG(1) << "Decoder::~Decoder()";
72
73 // NB: ReleaseDecoderResources() is virtual
74 ReleaseDecoderResources();
75 }
76 72
77 const char* MediaCodecDecoder::class_name() const { 73 const char* MediaCodecDecoder::class_name() const {
78 return "Decoder"; 74 return "Decoder";
79 } 75 }
80 76
81 void MediaCodecDecoder::ReleaseDecoderResources() {
82 DCHECK(media_task_runner_->BelongsToCurrentThread());
83
84 DVLOG(1) << class_name() << "::" << __FUNCTION__;
85
86 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame().
87 SetState(kInEmergencyStop);
88
89 decoder_thread_.Stop(); // synchronous
90
91 SetState(kStopped);
92 media_codec_bridge_.reset();
93 }
94
95 void MediaCodecDecoder::Flush() { 77 void MediaCodecDecoder::Flush() {
96 DCHECK(media_task_runner_->BelongsToCurrentThread()); 78 DCHECK(media_task_runner_->BelongsToCurrentThread());
97 79
98 DVLOG(1) << class_name() << "::" << __FUNCTION__; 80 DVLOG(1) << class_name() << "::" << __FUNCTION__;
99 81
100 DCHECK_EQ(GetState(), kStopped); 82 DCHECK_EQ(GetState(), kStopped);
101 83
102 // Flush() is a part of the Seek request. Whenever we request a seek we need 84 // Flush() is a part of the Seek request. Whenever we request a seek we need
103 // to invalidate the current data request. 85 // to invalidate the current data request.
104 if (is_data_request_in_progress_) 86 if (is_data_request_in_progress_)
105 is_incoming_data_invalid_ = true; 87 is_incoming_data_invalid_ = true;
106 88
107 eos_enqueued_ = false; 89 eos_enqueued_ = false;
108 completed_ = false; 90 completed_ = false;
109 au_queue_.Flush(); 91 au_queue_.Flush();
110 92
111 #ifndef NDEBUG 93 #ifndef NDEBUG
112 // We check and reset |verify_next_frame_is_key_| on Decoder thread. 94 // We check and reset |verify_next_frame_is_key_| on Decoder thread.
113 // This DCHECK ensures we won't need to lock this variable. 95 // This DCHECK ensures we won't need to lock this variable.
114 DCHECK(!decoder_thread_.IsRunning()); 96 DCHECK(!decoder_thread_.IsRunning());
115 97
116 // For video the first frame after flush must be key frame. 98 // For video the first frame after flush must be key frame.
117 verify_next_frame_is_key_ = true; 99 verify_next_frame_is_key_ = true;
118 #endif 100 #endif
119 101
102 needs_preroll_ = true;
103
120 if (media_codec_bridge_) { 104 if (media_codec_bridge_) {
121 // MediaCodecBridge::Reset() performs MediaCodecBridge.flush() 105 // MediaCodecBridge::Reset() performs MediaCodecBridge.flush()
122 MediaCodecStatus flush_status = media_codec_bridge_->Reset(); 106 MediaCodecStatus flush_status = media_codec_bridge_->Reset();
123 if (flush_status != MEDIA_CODEC_OK) { 107 if (flush_status != MEDIA_CODEC_OK) {
124 DVLOG(0) << class_name() << "::" << __FUNCTION__ 108 DVLOG(0) << class_name() << "::" << __FUNCTION__
125 << "MediaCodecBridge::Reset() failed"; 109 << "MediaCodecBridge::Reset() failed";
126 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); 110 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
127 } 111 }
128 } 112 }
129 } 113 }
130 114
131 void MediaCodecDecoder::ReleaseMediaCodec() { 115 void MediaCodecDecoder::ReleaseMediaCodec() {
132 DCHECK(media_task_runner_->BelongsToCurrentThread()); 116 DCHECK(media_task_runner_->BelongsToCurrentThread());
133 117
134 DVLOG(1) << class_name() << "::" << __FUNCTION__; 118 DVLOG(1) << class_name() << "::" << __FUNCTION__;
135 119
136 media_codec_bridge_.reset(); 120 media_codec_bridge_.reset();
121 needs_preroll_ = true;
137 } 122 }
138 123
139 bool MediaCodecDecoder::IsPrefetchingOrPlaying() const { 124 bool MediaCodecDecoder::IsPrefetchingOrPlaying() const {
140 DCHECK(media_task_runner_->BelongsToCurrentThread()); 125 DCHECK(media_task_runner_->BelongsToCurrentThread());
141 126
127 // Whether decoder needs to be stopped.
142 base::AutoLock lock(state_lock_); 128 base::AutoLock lock(state_lock_);
143 return state_ == kPrefetching || state_ == kRunning; 129 switch (state_) {
130 case kPrefetching:
131 case kPrefetched:
132 case kPrerolling:
133 case kPrerolled:
134 case kRunning:
135 return true;
136 case kStopped:
137 case kStopping:
138 case kInEmergencyStop:
139 case kError:
140 return false;
141 }
142 NOTREACHED();
143 return false;
144 } 144 }
145 145
146 bool MediaCodecDecoder::IsStopped() const { 146 bool MediaCodecDecoder::IsStopped() const {
147 DCHECK(media_task_runner_->BelongsToCurrentThread()); 147 DCHECK(media_task_runner_->BelongsToCurrentThread());
148 148
149 return GetState() == kStopped; 149 return GetState() == kStopped;
150 } 150 }
151 151
152 bool MediaCodecDecoder::IsCompleted() const { 152 bool MediaCodecDecoder::IsCompleted() const {
153 DCHECK(media_task_runner_->BelongsToCurrentThread()); 153 DCHECK(media_task_runner_->BelongsToCurrentThread());
154 154
155 return completed_; 155 return completed_;
156 } 156 }
157 157
158 bool MediaCodecDecoder::NotCompletedAndNeedsPreroll() const {
159 DCHECK(media_task_runner_->BelongsToCurrentThread());
160
161 return HasStream() && needs_preroll_ && !completed_;
162 }
163
158 base::android::ScopedJavaLocalRef<jobject> MediaCodecDecoder::GetMediaCrypto() { 164 base::android::ScopedJavaLocalRef<jobject> MediaCodecDecoder::GetMediaCrypto() {
159 base::android::ScopedJavaLocalRef<jobject> media_crypto; 165 base::android::ScopedJavaLocalRef<jobject> media_crypto;
160 166
161 // TODO(timav): implement DRM. 167 // TODO(timav): implement DRM.
162 // drm_bridge_ is not implemented 168 // drm_bridge_ is not implemented
163 // if (drm_bridge_) 169 // if (drm_bridge_)
164 // media_crypto = drm_bridge_->GetMediaCrypto(); 170 // media_crypto = drm_bridge_->GetMediaCrypto();
165 return media_crypto; 171 return media_crypto;
166 } 172 }
167 173
(...skipping 17 matching lines...) Expand all
185 191
186 if (GetState() == kError) { 192 if (GetState() == kError) {
187 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError"; 193 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError";
188 return kConfigFailure; 194 return kConfigFailure;
189 } 195 }
190 196
191 if (needs_reconfigure_) { 197 if (needs_reconfigure_) {
192 DVLOG(1) << class_name() << "::" << __FUNCTION__ 198 DVLOG(1) << class_name() << "::" << __FUNCTION__
193 << ": needs reconfigure, deleting MediaCodec"; 199 << ": needs reconfigure, deleting MediaCodec";
194 needs_reconfigure_ = false; 200 needs_reconfigure_ = false;
195 media_codec_bridge_.reset(); 201 ReleaseMediaCodec();
196
197 // No need to release these buffers since the MediaCodec is deleted, just
198 // remove their indexes from |delayed_buffers_|.
199
200 ClearDelayedBuffers(false);
201 } 202 }
202 203
203 MediaCodecDecoder::ConfigStatus result; 204 MediaCodecDecoder::ConfigStatus result;
204 if (media_codec_bridge_) { 205 if (media_codec_bridge_) {
205 DVLOG(1) << class_name() << "::" << __FUNCTION__ 206 DVLOG(1) << class_name() << "::" << __FUNCTION__
206 << ": reconfiguration is not required, ignoring"; 207 << ": reconfiguration is not required, ignoring";
207 result = kConfigOk; 208 result = kConfigOk;
208 } else { 209 } else {
209 result = ConfigureInternal(); 210 result = ConfigureInternal();
210 211
211 #ifndef NDEBUG 212 #ifndef NDEBUG
212 // We check and reset |verify_next_frame_is_key_| on Decoder thread. 213 // We check and reset |verify_next_frame_is_key_| on Decoder thread.
213 // This DCHECK ensures we won't need to lock this variable. 214 // This DCHECK ensures we won't need to lock this variable.
214 DCHECK(!decoder_thread_.IsRunning()); 215 DCHECK(!decoder_thread_.IsRunning());
215 216
216 // For video the first frame after reconfiguration must be key frame. 217 // For video the first frame after reconfiguration must be key frame.
217 if (result == kConfigOk) 218 if (result == kConfigOk)
218 verify_next_frame_is_key_ = true; 219 verify_next_frame_is_key_ = true;
219 #endif 220 #endif
220 } 221 }
221 222
222 return result; 223 return result;
223 } 224 }
224 225
225 bool MediaCodecDecoder::Start(base::TimeDelta current_time) { 226 bool MediaCodecDecoder::Preroll(base::TimeDelta preroll_timestamp,
227 const base::Closure& preroll_done_cb) {
226 DCHECK(media_task_runner_->BelongsToCurrentThread()); 228 DCHECK(media_task_runner_->BelongsToCurrentThread());
227 229
228 DVLOG(1) << class_name() << "::" << __FUNCTION__ 230 DVLOG(1) << class_name() << "::" << __FUNCTION__
229 << " current_time:" << current_time; 231 << " preroll_timestamp:" << preroll_timestamp;
230 232
231 DecoderState state = GetState(); 233 DecoderState state = GetState();
232 if (state == kRunning) {
233 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": already started";
234 return true; // already started
235 }
236
237 if (state != kPrefetched) { 234 if (state != kPrefetched) {
238 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state " 235 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state "
239 << AsString(state) << ", ignoring"; 236 << AsString(state) << ", ignoring";
240 return false; 237 return false;
241 } 238 }
242 239
243 if (!media_codec_bridge_) { 240 if (!media_codec_bridge_) {
244 DVLOG(0) << class_name() << "::" << __FUNCTION__ 241 DVLOG(0) << class_name() << "::" << __FUNCTION__
245 << ": not configured, ignoring"; 242 << ": not configured, ignoring";
246 return false; 243 return false;
247 } 244 }
248 245
249 DCHECK(!decoder_thread_.IsRunning()); 246 DCHECK(!decoder_thread_.IsRunning());
247 DCHECK(needs_preroll_);
248
249 preroll_done_cb_ = preroll_done_cb;
250 250
251 // We only synchronize video stream. 251 // We only synchronize video stream.
252 // When audio is present, the |current_time| is audio time. 252 DissociatePTSFromTime(); // associaton will happen after preroll is done.
253 SynchronizePTSWithTime(current_time); 253 preroll_timestamp_ = preroll_timestamp;
254 254
255 last_frame_posted_ = false; 255 last_frame_posted_ = false;
256 256
257 // Start the decoder thread 257 // Start the decoder thread
258 if (!decoder_thread_.Start()) { 258 if (!decoder_thread_.Start()) {
259 DVLOG(0) << class_name() << "::" << __FUNCTION__ 259 DVLOG(0) << class_name() << "::" << __FUNCTION__
260 << ": cannot start decoder thread"; 260 << ": cannot start decoder thread";
261 return false; 261 return false;
262 } 262 }
263 263
264 DVLOG(0) << class_name() << "::" << __FUNCTION__ << " decoder thread started"; 264 SetState(kPrerolling);
265
266 decoder_thread_.task_runner()->PostTask(
267 FROM_HERE,
268 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this)));
269
270 return true;
271 }
272
273 bool MediaCodecDecoder::Start(base::TimeDelta start_timestamp) {
274 DCHECK(media_task_runner_->BelongsToCurrentThread());
275
276 DVLOG(1) << class_name() << "::" << __FUNCTION__
277 << " start_timestamp:" << start_timestamp;
278
279 DecoderState state = GetState();
280
281 if (state != kPrefetched && state != kPrerolled) {
282 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state "
283 << AsString(state) << ", ignoring";
284 return false;
285 }
286
287 if (!media_codec_bridge_) {
288 DVLOG(0) << class_name() << "::" << __FUNCTION__
289 << ": not configured, ignoring";
290 return false;
291 }
292
293 // We only synchronize video stream.
294 AssociateCurrentTimeWithPTS(start_timestamp);
295 preroll_timestamp_ = base::TimeDelta();
296
297 // Start the decoder thread
298 if (!decoder_thread_.IsRunning()) {
299 last_frame_posted_ = false;
300 if (!decoder_thread_.Start()) {
301 DVLOG(1) << class_name() << "::" << __FUNCTION__
302 << ": cannot start decoder thread";
303 return false;
304 }
305 }
265 306
266 SetState(kRunning); 307 SetState(kRunning);
267 308
268 decoder_thread_.task_runner()->PostTask( 309 decoder_thread_.task_runner()->PostTask(
269 FROM_HERE, 310 FROM_HERE,
270 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this))); 311 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this)));
271 312
272 return true; 313 return true;
273 } 314 }
274 315
275 void MediaCodecDecoder::SyncStop() { 316 void MediaCodecDecoder::SyncStop() {
276 DCHECK(media_task_runner_->BelongsToCurrentThread()); 317 DCHECK(media_task_runner_->BelongsToCurrentThread());
277 318
278 DVLOG(1) << class_name() << "::" << __FUNCTION__; 319 DVLOG(1) << class_name() << "::" << __FUNCTION__;
279 320
280 if (GetState() == kError) { 321 if (GetState() == kError) {
281 DVLOG(0) << class_name() << "::" << __FUNCTION__ 322 DVLOG(0) << class_name() << "::" << __FUNCTION__
282 << ": wrong state kError, ignoring"; 323 << ": wrong state kError, ignoring";
283 return; 324 return;
284 } 325 }
285 326
286 // After this method returns, decoder thread will not be running. 327 DoEmergencyStop();
287 328
288 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). 329 ReleaseDelayedBuffers();
289 SetState(kInEmergencyStop);
290
291 decoder_thread_.Stop(); // synchronous
292
293 SetState(kStopped);
294
295 ClearDelayedBuffers(true); // release prior to clearing |delayed_buffers_|.
296 } 330 }
297 331
298 void MediaCodecDecoder::RequestToStop() { 332 void MediaCodecDecoder::RequestToStop() {
299 DCHECK(media_task_runner_->BelongsToCurrentThread()); 333 DCHECK(media_task_runner_->BelongsToCurrentThread());
300 334
301 DVLOG(1) << class_name() << "::" << __FUNCTION__; 335 DVLOG(1) << class_name() << "::" << __FUNCTION__;
302 336
303 DecoderState state = GetState(); 337 DecoderState state = GetState();
304 switch (state) { 338 switch (state) {
305 case kError: 339 case kError:
306 DVLOG(0) << class_name() << "::" << __FUNCTION__ 340 DVLOG(0) << class_name() << "::" << __FUNCTION__
307 << ": wrong state kError, ignoring"; 341 << ": wrong state kError, ignoring";
308 break; 342 break;
309 case kRunning: 343 case kRunning:
310 SetState(kStopping); 344 SetState(kStopping);
311 break; 345 break;
346 case kPrerolling:
347 case kPrerolled:
348 DCHECK(decoder_thread_.IsRunning());
349 // Synchronous stop.
350 decoder_thread_.Stop();
351 SetState(kStopped);
352 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
353 break;
312 case kStopping: 354 case kStopping:
313 break; // ignore 355 break; // ignore
314 case kStopped: 356 case kStopped:
315 case kPrefetching: 357 case kPrefetching:
316 case kPrefetched: 358 case kPrefetched:
317 // There is nothing to wait for, we can sent nofigication right away. 359 // There is nothing to wait for, we can sent nofigication right away.
318 DCHECK(!decoder_thread_.IsRunning()); 360 DCHECK(!decoder_thread_.IsRunning());
319 SetState(kStopped); 361 SetState(kStopped);
320 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); 362 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
321 break; 363 break;
322 default: 364 default:
323 NOTREACHED(); 365 NOTREACHED();
324 break; 366 break;
325 } 367 }
326 } 368 }
327 369
328 void MediaCodecDecoder::OnLastFrameRendered(bool completed) { 370 void MediaCodecDecoder::OnLastFrameRendered(bool completed) {
329 DCHECK(media_task_runner_->BelongsToCurrentThread()); 371 DCHECK(media_task_runner_->BelongsToCurrentThread());
330 372
331 DVLOG(0) << class_name() << "::" << __FUNCTION__ 373 DVLOG(0) << class_name() << "::" << __FUNCTION__
332 << " completed:" << completed; 374 << " completed:" << completed;
333 375
334 decoder_thread_.Stop(); // synchronous 376 decoder_thread_.Stop(); // synchronous
335 377
336 SetState(kStopped); 378 SetState(kStopped);
337 completed_ = completed; 379 completed_ = completed;
338 380
381 if (completed_ && !preroll_done_cb_.is_null())
382 media_task_runner_->PostTask(FROM_HERE,
383 base::ResetAndReturn(&preroll_done_cb_));
384
339 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); 385 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
340 } 386 }
341 387
388 void MediaCodecDecoder::OnPrerollDone() {
389 DCHECK(media_task_runner_->BelongsToCurrentThread());
390
391 DVLOG(1) << class_name() << "::" << __FUNCTION__;
392
393 if (GetState() == kPrerolling) {
394 SetState(kPrerolled);
395 needs_preroll_ = false;
396 media_task_runner_->PostTask(FROM_HERE,
397 base::ResetAndReturn(&preroll_done_cb_));
398 }
399 }
400
342 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) { 401 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) {
343 DCHECK(media_task_runner_->BelongsToCurrentThread()); 402 DCHECK(media_task_runner_->BelongsToCurrentThread());
344 403
345 // If |data| contains an aborted data, the last AU will have kAborted status. 404 // If |data| contains an aborted data, the last AU will have kAborted status.
346 bool aborted_data = 405 bool aborted_data =
347 !data.access_units.empty() && 406 !data.access_units.empty() &&
348 data.access_units.back().status == DemuxerStream::kAborted; 407 data.access_units.back().status == DemuxerStream::kAborted;
349 408
350 #ifndef NDEBUG 409 #ifndef NDEBUG
351 const char* explain_if_skipped = 410 const char* explain_if_skipped =
(...skipping 12 matching lines...) Expand all
364 423
365 is_incoming_data_invalid_ = false; 424 is_incoming_data_invalid_ = false;
366 is_data_request_in_progress_ = false; 425 is_data_request_in_progress_ = false;
367 426
368 // Do not request data if we got kAborted. There is no point to request the 427 // Do not request data if we got kAborted. There is no point to request the
369 // data after kAborted and before the OnDemuxerSeekDone. 428 // data after kAborted and before the OnDemuxerSeekDone.
370 if (GetState() == kPrefetching && !aborted_data) 429 if (GetState() == kPrefetching && !aborted_data)
371 PrefetchNextChunk(); 430 PrefetchNextChunk();
372 } 431 }
373 432
433 bool MediaCodecDecoder::IsPrerollingForTests() const {
434 // UI task runner.
435 return GetState() == kPrerolling;
436 }
437
374 int MediaCodecDecoder::NumDelayedRenderTasks() const { 438 int MediaCodecDecoder::NumDelayedRenderTasks() const {
375 return 0; 439 return 0;
376 } 440 }
377 441
442 void MediaCodecDecoder::DoEmergencyStop() {
443 DCHECK(media_task_runner_->BelongsToCurrentThread());
444 DVLOG(1) << class_name() << "::" << __FUNCTION__;
445
446 // After this method returns, decoder thread will not be running.
447
448 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame().
449 SetState(kInEmergencyStop);
450
451 decoder_thread_.Stop(); // synchronous
452
453 SetState(kStopped);
454 }
455
378 void MediaCodecDecoder::CheckLastFrame(bool eos_encountered, 456 void MediaCodecDecoder::CheckLastFrame(bool eos_encountered,
379 bool has_delayed_tasks) { 457 bool has_delayed_tasks) {
380 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 458 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
381 459
382 bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks; 460 bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks;
383 461
384 if (last_frame_when_stopping || eos_encountered) { 462 if (last_frame_when_stopping || eos_encountered) {
385 media_task_runner_->PostTask( 463 media_task_runner_->PostTask(
386 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered, 464 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered,
387 weak_factory_.GetWeakPtr(), eos_encountered)); 465 weak_factory_.GetWeakPtr(), eos_encountered));
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 request_data_cb_.Run(); 511 request_data_cb_.Run();
434 } 512 }
435 513
436 void MediaCodecDecoder::ProcessNextFrame() { 514 void MediaCodecDecoder::ProcessNextFrame() {
437 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 515 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
438 516
439 DVLOG(2) << class_name() << "::" << __FUNCTION__; 517 DVLOG(2) << class_name() << "::" << __FUNCTION__;
440 518
441 DecoderState state = GetState(); 519 DecoderState state = GetState();
442 520
443 if (state != kRunning && state != kStopping) { 521 if (state != kPrerolling && state != kRunning && state != kStopping) {
444 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": not running"; 522 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": not running";
445 return; 523 return;
446 } 524 }
447 525
448 if (state == kStopping) { 526 if (state == kStopping) {
449 if (NumDelayedRenderTasks() == 0 && !last_frame_posted_) { 527 if (NumDelayedRenderTasks() == 0 && !last_frame_posted_) {
450 DVLOG(1) << class_name() << "::" << __FUNCTION__ 528 DVLOG(1) << class_name() << "::" << __FUNCTION__
451 << ": kStopping, posting OnLastFrameRendered"; 529 << ": kStopping, posting OnLastFrameRendered";
452 media_task_runner_->PostTask( 530 media_task_runner_->PostTask(
453 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered, 531 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered,
454 weak_factory_.GetWeakPtr(), false)); 532 weak_factory_.GetWeakPtr(), false));
455 last_frame_posted_ = true; 533 last_frame_posted_ = true;
456 } 534 }
457 535
458 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze. 536 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze.
459 // We only need to let finish the delayed rendering tasks. 537 // We only need to let finish the delayed rendering tasks.
460 return; 538 return;
461 } 539 }
462 540
463 DCHECK(state == kRunning); 541 DCHECK(state == kPrerolling || state == kRunning);
464 542
465 if (!EnqueueInputBuffer()) 543 if (!EnqueueInputBuffer())
466 return; 544 return;
467 545
468 if (!DepleteOutputBufferQueue()) 546 if (!DepleteOutputBufferQueue())
469 return; 547 return;
470 548
471 // We need a small delay if we want to stop this thread by 549 // We need a small delay if we want to stop this thread by
472 // decoder_thread_.Stop() reliably. 550 // decoder_thread_.Stop() reliably.
473 // The decoder thread message loop processes all pending 551 // The decoder thread message loop processes all pending
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 676
599 DVLOG(2) << class_name() << "::" << __FUNCTION__; 677 DVLOG(2) << class_name() << "::" << __FUNCTION__;
600 678
601 int buffer_index = 0; 679 int buffer_index = 0;
602 size_t offset = 0; 680 size_t offset = 0;
603 size_t size = 0; 681 size_t size = 0;
604 base::TimeDelta pts; 682 base::TimeDelta pts;
605 MediaCodecStatus status; 683 MediaCodecStatus status;
606 bool eos_encountered = false; 684 bool eos_encountered = false;
607 685
686 RenderMode render_mode;
687
608 base::TimeDelta timeout = 688 base::TimeDelta timeout =
609 base::TimeDelta::FromMilliseconds(kOutputBufferTimeout); 689 base::TimeDelta::FromMilliseconds(kOutputBufferTimeout);
610 690
611 // Extract all output buffers that are available. 691 // Extract all output buffers that are available.
612 // Usually there will be only one, but sometimes it is preceeded by 692 // Usually there will be only one, but sometimes it is preceeded by
613 // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED. 693 // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED.
614 do { 694 do {
615 status = media_codec_bridge_->DequeueOutputBuffer( 695 status = media_codec_bridge_->DequeueOutputBuffer(
616 timeout, &buffer_index, &offset, &size, &pts, &eos_encountered, 696 timeout, &buffer_index, &offset, &size, &pts, &eos_encountered,
617 nullptr); 697 nullptr);
618 698
619 // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls 699 // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls
620 // to quickly break the loop after we got all currently available buffers. 700 // to quickly break the loop after we got all currently available buffers.
621 timeout = base::TimeDelta::FromMilliseconds(0); 701 timeout = base::TimeDelta::FromMilliseconds(0);
622 702
623 switch (status) { 703 switch (status) {
624 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: 704 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
625 // Output buffers are replaced in MediaCodecBridge, nothing to do. 705 // Output buffers are replaced in MediaCodecBridge, nothing to do.
626 break; 706 break;
627 707
628 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: 708 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED:
629 DVLOG(2) << class_name() << "::" << __FUNCTION__ 709 DVLOG(2) << class_name() << "::" << __FUNCTION__
630 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED"; 710 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED";
631 OnOutputFormatChanged(); 711 OnOutputFormatChanged();
632 break; 712 break;
633 713
634 case MEDIA_CODEC_OK: 714 case MEDIA_CODEC_OK:
635 // We got the decoded frame 715 // We got the decoded frame.
636 Render(buffer_index, offset, size, true, pts, eos_encountered); 716
717 if (pts < preroll_timestamp_)
718 render_mode = kRenderSkip;
719 else if (GetState() == kPrerolling)
720 render_mode = kRenderAfterPreroll;
721 else
722 render_mode = kRenderNow;
723
724 Render(buffer_index, offset, size, render_mode, pts, eos_encountered);
725
726 if (render_mode == kRenderAfterPreroll) {
727 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " pts:" << pts
728 << " preroll done, stopping frame processing";
729 media_task_runner_->PostTask(FROM_HERE, internal_preroll_done_cb_);
730 return false;
731 }
637 break; 732 break;
638 733
639 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: 734 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
640 // Nothing to do. 735 // Nothing to do.
641 break; 736 break;
642 737
643 case MEDIA_CODEC_ERROR: 738 case MEDIA_CODEC_ERROR:
644 DVLOG(0) << class_name() << "::" << __FUNCTION__ 739 DVLOG(0) << class_name() << "::" << __FUNCTION__
645 << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer"; 740 << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer";
646 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); 741 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
679 774
680 base::AutoLock lock(state_lock_); 775 base::AutoLock lock(state_lock_);
681 state_ = state; 776 state_ = state;
682 } 777 }
683 778
684 #undef RETURN_STRING 779 #undef RETURN_STRING
685 #define RETURN_STRING(x) \ 780 #define RETURN_STRING(x) \
686 case x: \ 781 case x: \
687 return #x; 782 return #x;
688 783
784 const char* MediaCodecDecoder::AsString(RenderMode render_mode) {
785 switch (render_mode) {
786 RETURN_STRING(kRenderSkip);
787 RETURN_STRING(kRenderAfterPreroll);
788 RETURN_STRING(kRenderNow);
789 }
790 return nullptr; // crash early
791 }
792
689 const char* MediaCodecDecoder::AsString(DecoderState state) { 793 const char* MediaCodecDecoder::AsString(DecoderState state) {
690 switch (state) { 794 switch (state) {
691 RETURN_STRING(kStopped); 795 RETURN_STRING(kStopped);
692 RETURN_STRING(kPrefetching); 796 RETURN_STRING(kPrefetching);
693 RETURN_STRING(kPrefetched); 797 RETURN_STRING(kPrefetched);
798 RETURN_STRING(kPrerolling);
799 RETURN_STRING(kPrerolled);
694 RETURN_STRING(kRunning); 800 RETURN_STRING(kRunning);
695 RETURN_STRING(kStopping); 801 RETURN_STRING(kStopping);
696 RETURN_STRING(kInEmergencyStop); 802 RETURN_STRING(kInEmergencyStop);
697 RETURN_STRING(kError); 803 RETURN_STRING(kError);
698 default:
699 return "Unknown DecoderState";
700 } 804 }
805 return nullptr; // crash early
701 } 806 }
702 807
703 #undef RETURN_STRING 808 #undef RETURN_STRING
704 809
705 } // namespace media 810 } // namespace media
OLDNEW
« no previous file with comments | « media/base/android/media_codec_decoder.h ('k') | media/base/android/media_codec_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698