OLD | NEW |
---|---|
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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
43 decoder_thread_(decoder_thread_name), | 43 decoder_thread_(decoder_thread_name), |
44 needs_reconfigure_(false), | 44 needs_reconfigure_(false), |
45 drain_decoder_(false), | 45 drain_decoder_(false), |
46 always_reconfigure_for_tests_(false), | 46 always_reconfigure_for_tests_(false), |
47 external_request_data_cb_(external_request_data_cb), | 47 external_request_data_cb_(external_request_data_cb), |
48 starvation_cb_(starvation_cb), | 48 starvation_cb_(starvation_cb), |
49 decoder_drained_cb_(decoder_drained_cb), | 49 decoder_drained_cb_(decoder_drained_cb), |
50 stop_done_cb_(stop_done_cb), | 50 stop_done_cb_(stop_done_cb), |
51 error_cb_(error_cb), | 51 error_cb_(error_cb), |
52 state_(kStopped), | 52 state_(kStopped), |
53 preroll_mode_(kPrerollTillPTS), | 53 is_prepared_(false), |
54 eos_enqueued_(false), | 54 eos_enqueued_(false), |
55 completed_(false), | 55 completed_(false), |
56 last_frame_posted_(false), | 56 last_frame_posted_(false), |
57 is_data_request_in_progress_(false), | 57 is_data_request_in_progress_(false), |
58 is_incoming_data_invalid_(false), | 58 is_incoming_data_invalid_(false), |
59 #ifndef NDEBUG | 59 #ifndef NDEBUG |
60 verify_next_frame_is_key_(false), | 60 verify_next_frame_is_key_(false), |
61 #endif | 61 #endif |
62 weak_factory_(this) { | 62 weak_factory_(this) { |
63 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 63 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
(...skipping 24 matching lines...) Expand all Loading... | |
88 // Flush() is a part of the Seek request. Whenever we request a seek we need | 88 // Flush() is a part of the Seek request. Whenever we request a seek we need |
89 // to invalidate the current data request. | 89 // to invalidate the current data request. |
90 if (is_data_request_in_progress_) | 90 if (is_data_request_in_progress_) |
91 is_incoming_data_invalid_ = true; | 91 is_incoming_data_invalid_ = true; |
92 | 92 |
93 eos_enqueued_ = false; | 93 eos_enqueued_ = false; |
94 completed_ = false; | 94 completed_ = false; |
95 drain_decoder_ = false; | 95 drain_decoder_ = false; |
96 au_queue_.Flush(); | 96 au_queue_.Flush(); |
97 | 97 |
98 // |is_prepared_| is set on the decoder thread, it shouldn't be running now. | |
99 DCHECK(!decoder_thread_.IsRunning()); | |
100 is_prepared_ = false; | |
101 | |
98 #ifndef NDEBUG | 102 #ifndef NDEBUG |
99 // We check and reset |verify_next_frame_is_key_| on Decoder thread. | 103 // We check and reset |verify_next_frame_is_key_| on Decoder thread. |
100 // This DCHECK ensures we won't need to lock this variable. | 104 // We have just DCHECKed that decoder thread is not running. |
101 DCHECK(!decoder_thread_.IsRunning()); | |
102 | 105 |
103 // For video the first frame after flush must be key frame. | 106 // For video the first frame after flush must be key frame. |
104 verify_next_frame_is_key_ = true; | 107 verify_next_frame_is_key_ = true; |
105 #endif | 108 #endif |
106 | 109 |
107 preroll_mode_ = kPrerollTillPTS; | |
108 | |
109 if (media_codec_bridge_) { | 110 if (media_codec_bridge_) { |
110 // MediaCodecBridge::Reset() performs MediaCodecBridge.flush() | 111 // MediaCodecBridge::Reset() performs MediaCodecBridge.flush() |
111 MediaCodecStatus flush_status = media_codec_bridge_->Reset(); | 112 MediaCodecStatus flush_status = media_codec_bridge_->Reset(); |
112 if (flush_status != MEDIA_CODEC_OK) { | 113 if (flush_status != MEDIA_CODEC_OK) { |
113 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 114 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
114 << "MediaCodecBridge::Reset() failed"; | 115 << "MediaCodecBridge::Reset() failed"; |
115 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); | 116 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); |
116 } | 117 } |
117 } | 118 } |
118 } | 119 } |
119 | 120 |
120 void MediaCodecDecoder::ReleaseMediaCodec() { | 121 void MediaCodecDecoder::ReleaseMediaCodec() { |
121 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 122 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
122 | 123 |
123 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 124 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
124 | 125 |
126 DCHECK(!decoder_thread_.IsRunning()); | |
127 | |
125 media_codec_bridge_.reset(); | 128 media_codec_bridge_.reset(); |
126 preroll_mode_ = kPrerollTillPTS; | 129 |
130 // |is_prepared_| is set on the decoder thread, it shouldn't be running now. | |
131 is_prepared_ = false; | |
127 } | 132 } |
128 | 133 |
129 bool MediaCodecDecoder::IsPrefetchingOrPlaying() const { | 134 bool MediaCodecDecoder::IsPrefetchingOrPlaying() const { |
130 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 135 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
131 | 136 |
132 // Whether decoder needs to be stopped. | 137 // Whether decoder needs to be stopped. |
133 base::AutoLock lock(state_lock_); | 138 base::AutoLock lock(state_lock_); |
134 switch (state_) { | 139 switch (state_) { |
135 case kPrefetching: | 140 case kPrefetching: |
136 case kPrefetched: | 141 case kPrefetched: |
(...skipping 19 matching lines...) Expand all Loading... | |
156 | 161 |
157 bool MediaCodecDecoder::IsCompleted() const { | 162 bool MediaCodecDecoder::IsCompleted() const { |
158 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 163 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
159 | 164 |
160 return completed_; | 165 return completed_; |
161 } | 166 } |
162 | 167 |
163 bool MediaCodecDecoder::NotCompletedAndNeedsPreroll() const { | 168 bool MediaCodecDecoder::NotCompletedAndNeedsPreroll() const { |
164 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 169 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
165 | 170 |
166 return HasStream() && preroll_mode_ != kNoPreroll && !completed_; | 171 return HasStream() && !completed_ && |
172 (!is_prepared_ || preroll_timestamp_ != base::TimeDelta()); | |
167 } | 173 } |
168 | 174 |
169 void MediaCodecDecoder::SetDecodingUntilOutputIsPresent() { | 175 void MediaCodecDecoder::SetPrerollTimestamp(base::TimeDelta preroll_timestamp) { |
170 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 176 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
171 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 177 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": " << preroll_timestamp; |
172 | 178 |
173 preroll_mode_ = kPrerollTillOutputIsPresent; | 179 preroll_timestamp_ = preroll_timestamp; |
174 } | 180 } |
175 | 181 |
176 base::android::ScopedJavaLocalRef<jobject> MediaCodecDecoder::GetMediaCrypto() { | 182 base::android::ScopedJavaLocalRef<jobject> MediaCodecDecoder::GetMediaCrypto() { |
177 base::android::ScopedJavaLocalRef<jobject> media_crypto; | 183 base::android::ScopedJavaLocalRef<jobject> media_crypto; |
178 | 184 |
179 // TODO(timav): implement DRM. | 185 // TODO(timav): implement DRM. |
180 // drm_bridge_ is not implemented | 186 // drm_bridge_ is not implemented |
181 // if (drm_bridge_) | 187 // if (drm_bridge_) |
182 // media_crypto = drm_bridge_->GetMediaCrypto(); | 188 // media_crypto = drm_bridge_->GetMediaCrypto(); |
183 return media_crypto; | 189 return media_crypto; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
235 DCHECK(!decoder_thread_.IsRunning()); | 241 DCHECK(!decoder_thread_.IsRunning()); |
236 | 242 |
237 // For video the first frame after reconfiguration must be key frame. | 243 // For video the first frame after reconfiguration must be key frame. |
238 if (result == kConfigOk) | 244 if (result == kConfigOk) |
239 verify_next_frame_is_key_ = true; | 245 verify_next_frame_is_key_ = true; |
240 #endif | 246 #endif |
241 | 247 |
242 return result; | 248 return result; |
243 } | 249 } |
244 | 250 |
245 bool MediaCodecDecoder::Preroll(base::TimeDelta preroll_timestamp, | 251 bool MediaCodecDecoder::Preroll(const base::Closure& preroll_done_cb) { |
246 const base::Closure& preroll_done_cb) { | |
247 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 252 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
248 | 253 |
249 DVLOG(1) << class_name() << "::" << __FUNCTION__ | 254 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
250 << " preroll_timestamp:" << preroll_timestamp; | 255 << " preroll_timestamp:" << preroll_timestamp_; |
251 | 256 |
252 DecoderState state = GetState(); | 257 DecoderState state = GetState(); |
253 if (state != kPrefetched) { | 258 if (state != kPrefetched) { |
254 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state " | 259 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state " |
255 << AsString(state) << ", ignoring"; | 260 << AsString(state) << ", ignoring"; |
256 return false; | 261 return false; |
257 } | 262 } |
258 | 263 |
259 if (!media_codec_bridge_) { | 264 if (!media_codec_bridge_) { |
260 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 265 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
261 << ": not configured, ignoring"; | 266 << ": not configured, ignoring"; |
262 return false; | 267 return false; |
263 } | 268 } |
264 | 269 |
265 DCHECK(!decoder_thread_.IsRunning()); | 270 DCHECK(!decoder_thread_.IsRunning()); |
266 DCHECK(preroll_mode_ != kNoPreroll); | |
267 | 271 |
268 preroll_done_cb_ = preroll_done_cb; | 272 preroll_done_cb_ = preroll_done_cb; |
269 | 273 |
270 // We only synchronize video stream. | 274 // We only synchronize video stream. |
271 DissociatePTSFromTime(); // associaton will happen after preroll is done. | 275 DissociatePTSFromTime(); // associaton will happen after preroll is done. |
272 | 276 |
273 preroll_timestamp_ = (preroll_mode_ == kPrerollTillPTS) ? preroll_timestamp | |
274 : base::TimeDelta(); | |
275 | |
276 last_frame_posted_ = false; | 277 last_frame_posted_ = false; |
277 | 278 |
278 // Start the decoder thread | 279 // Start the decoder thread |
279 if (!decoder_thread_.Start()) { | 280 if (!decoder_thread_.Start()) { |
280 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 281 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
281 << ": cannot start decoder thread"; | 282 << ": cannot start decoder thread"; |
282 return false; | 283 return false; |
283 } | 284 } |
284 | 285 |
285 SetState(kPrerolling); | 286 SetState(kPrerolling); |
(...skipping 20 matching lines...) Expand all Loading... | |
306 } | 307 } |
307 | 308 |
308 if (!media_codec_bridge_) { | 309 if (!media_codec_bridge_) { |
309 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 310 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
310 << ": not configured, ignoring"; | 311 << ": not configured, ignoring"; |
311 return false; | 312 return false; |
312 } | 313 } |
313 | 314 |
314 // We only synchronize video stream. | 315 // We only synchronize video stream. |
315 AssociateCurrentTimeWithPTS(start_timestamp); | 316 AssociateCurrentTimeWithPTS(start_timestamp); |
316 preroll_timestamp_ = base::TimeDelta(); | 317 |
318 DCHECK(preroll_timestamp_ == base::TimeDelta()); | |
317 | 319 |
318 // Start the decoder thread | 320 // Start the decoder thread |
319 if (!decoder_thread_.IsRunning()) { | 321 if (!decoder_thread_.IsRunning()) { |
320 last_frame_posted_ = false; | 322 last_frame_posted_ = false; |
321 if (!decoder_thread_.Start()) { | 323 if (!decoder_thread_.Start()) { |
322 DVLOG(1) << class_name() << "::" << __FUNCTION__ | 324 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
323 << ": cannot start decoder thread"; | 325 << ": cannot start decoder thread"; |
324 return false; | 326 return false; |
325 } | 327 } |
326 } | 328 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
366 break; | 368 break; |
367 case kPrerolling: | 369 case kPrerolling: |
368 case kPrerolled: | 370 case kPrerolled: |
369 DCHECK(decoder_thread_.IsRunning()); | 371 DCHECK(decoder_thread_.IsRunning()); |
370 // Synchronous stop. | 372 // Synchronous stop. |
371 decoder_thread_.Stop(); | 373 decoder_thread_.Stop(); |
372 SetState(kStopped); | 374 SetState(kStopped); |
373 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); | 375 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); |
374 break; | 376 break; |
375 case kStopping: | 377 case kStopping: |
378 case kStopped: | |
Tima Vaisburd
2015/09/03 19:55:27
Moved kStopped here so RequestToStop will be ignor
| |
376 break; // ignore | 379 break; // ignore |
377 case kStopped: | |
378 case kPrefetching: | 380 case kPrefetching: |
379 case kPrefetched: | 381 case kPrefetched: |
380 // There is nothing to wait for, we can sent notification right away. | 382 // There is nothing to wait for, we can sent notification right away. |
381 DCHECK(!decoder_thread_.IsRunning()); | 383 DCHECK(!decoder_thread_.IsRunning()); |
382 SetState(kStopped); | 384 SetState(kStopped); |
383 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); | 385 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); |
384 break; | 386 break; |
385 default: | 387 default: |
386 NOTREACHED(); | 388 NOTREACHED(); |
387 break; | 389 break; |
388 } | 390 } |
389 } | 391 } |
390 | 392 |
391 void MediaCodecDecoder::OnLastFrameRendered(bool eos_encountered) { | 393 void MediaCodecDecoder::OnLastFrameRendered(bool eos_encountered) { |
392 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 394 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
393 | 395 |
394 DVLOG(1) << class_name() << "::" << __FUNCTION__ | 396 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
395 << " eos_encountered:" << eos_encountered; | 397 << " eos_encountered:" << eos_encountered; |
396 | 398 |
397 decoder_thread_.Stop(); // synchronous | 399 decoder_thread_.Stop(); // synchronous |
398 | 400 |
399 SetState(kStopped); | 401 SetState(kStopped); |
400 completed_ = (eos_encountered && !drain_decoder_); | 402 completed_ = (eos_encountered && !drain_decoder_); |
401 | 403 |
404 // If the stream is completed during preroll we need to report it since | |
405 // another stream might be running and the player waits for two callbacks. | |
402 if (completed_ && !preroll_done_cb_.is_null()) { | 406 if (completed_ && !preroll_done_cb_.is_null()) { |
407 preroll_timestamp_ = base::TimeDelta(); | |
liberato (no reviews please)
2015/09/04 21:59:13
there's a kNoTimestamp that you might want to cons
Tima Vaisburd
2015/09/04 23:17:35
Zero timestamp compares nicely at line 807, it was
| |
403 media_task_runner_->PostTask(FROM_HERE, | 408 media_task_runner_->PostTask(FROM_HERE, |
404 base::ResetAndReturn(&preroll_done_cb_)); | 409 base::ResetAndReturn(&preroll_done_cb_)); |
405 } | 410 } |
406 | 411 |
407 if (eos_encountered && drain_decoder_) { | 412 if (eos_encountered && drain_decoder_) { |
408 ReleaseMediaCodec(); | |
409 drain_decoder_ = false; | 413 drain_decoder_ = false; |
410 eos_enqueued_ = false; | 414 eos_enqueued_ = false; |
411 preroll_mode_ = kPrerollTillOutputIsPresent; | 415 ReleaseMediaCodec(); |
412 media_task_runner_->PostTask(FROM_HERE, decoder_drained_cb_); | 416 media_task_runner_->PostTask(FROM_HERE, decoder_drained_cb_); |
413 } | 417 } |
414 | 418 |
415 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); | 419 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); |
416 } | 420 } |
417 | 421 |
418 void MediaCodecDecoder::OnPrerollDone() { | 422 void MediaCodecDecoder::OnPrerollDone() { |
419 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 423 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
420 | 424 |
421 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 425 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
422 | 426 |
423 preroll_mode_ = kNoPreroll; | 427 preroll_timestamp_ = base::TimeDelta(); |
424 | 428 |
425 // The state might be kStopping. | 429 // The state might be kStopping (?) |
426 if (GetState() == kPrerolling) { | 430 if (GetState() == kPrerolling) |
427 SetState(kPrerolled); | 431 SetState(kPrerolled); |
428 media_task_runner_->PostTask(FROM_HERE, | 432 |
429 base::ResetAndReturn(&preroll_done_cb_)); | 433 if (!preroll_done_cb_.is_null()) |
430 } | 434 base::ResetAndReturn(&preroll_done_cb_).Run(); |
431 } | 435 } |
432 | 436 |
433 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) { | 437 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) { |
434 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 438 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
435 | 439 |
436 // If |data| contains an aborted data, the last AU will have kAborted status. | 440 // If |data| contains an aborted data, the last AU will have kAborted status. |
437 bool aborted_data = | 441 bool aborted_data = |
438 !data.access_units.empty() && | 442 !data.access_units.empty() && |
439 data.access_units.back().status == DemuxerStream::kAborted; | 443 data.access_units.back().status == DemuxerStream::kAborted; |
440 | 444 |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
571 DVLOG(1) << class_name() << "::" << __FUNCTION__ | 575 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
572 << ": kStopping, posting OnLastFrameRendered"; | 576 << ": kStopping, posting OnLastFrameRendered"; |
573 media_task_runner_->PostTask( | 577 media_task_runner_->PostTask( |
574 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered, | 578 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered, |
575 weak_factory_.GetWeakPtr(), false)); | 579 weak_factory_.GetWeakPtr(), false)); |
576 last_frame_posted_ = true; | 580 last_frame_posted_ = true; |
577 } | 581 } |
578 | 582 |
579 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze. | 583 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze. |
580 // We only need to let finish the delayed rendering tasks. | 584 // We only need to let finish the delayed rendering tasks. |
585 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " kStopping, returning"; | |
581 return; | 586 return; |
582 } | 587 } |
583 | 588 |
584 DCHECK(state == kPrerolling || state == kRunning); | 589 DCHECK(state == kPrerolling || state == kRunning); |
585 | 590 |
586 if (!EnqueueInputBuffer()) | 591 if (!EnqueueInputBuffer()) |
587 return; | 592 return; |
588 | 593 |
589 if (!DepleteOutputBufferQueue()) | 594 if (!DepleteOutputBufferQueue()) |
590 return; | 595 return; |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
790 | 795 |
791 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: | 796 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: |
792 DVLOG(2) << class_name() << "::" << __FUNCTION__ | 797 DVLOG(2) << class_name() << "::" << __FUNCTION__ |
793 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED"; | 798 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED"; |
794 OnOutputFormatChanged(); | 799 OnOutputFormatChanged(); |
795 break; | 800 break; |
796 | 801 |
797 case MEDIA_CODEC_OK: | 802 case MEDIA_CODEC_OK: |
798 // We got the decoded frame. | 803 // We got the decoded frame. |
799 | 804 |
805 is_prepared_ = true; | |
806 | |
800 if (pts < preroll_timestamp_) | 807 if (pts < preroll_timestamp_) |
801 render_mode = kRenderSkip; | 808 render_mode = kRenderSkip; |
802 else if (GetState() == kPrerolling) | 809 else if (GetState() == kPrerolling) |
803 render_mode = kRenderAfterPreroll; | 810 render_mode = kRenderAfterPreroll; |
804 else | 811 else |
805 render_mode = kRenderNow; | 812 render_mode = kRenderNow; |
806 | 813 |
807 Render(buffer_index, offset, size, render_mode, pts, eos_encountered); | 814 Render(buffer_index, offset, size, render_mode, pts, eos_encountered); |
808 | 815 |
809 if (render_mode == kRenderAfterPreroll) { | 816 if (render_mode == kRenderAfterPreroll) { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
885 RETURN_STRING(kStopping); | 892 RETURN_STRING(kStopping); |
886 RETURN_STRING(kInEmergencyStop); | 893 RETURN_STRING(kInEmergencyStop); |
887 RETURN_STRING(kError); | 894 RETURN_STRING(kError); |
888 } | 895 } |
889 return nullptr; // crash early | 896 return nullptr; // crash early |
890 } | 897 } |
891 | 898 |
892 #undef RETURN_STRING | 899 #undef RETURN_STRING |
893 | 900 |
894 } // namespace media | 901 } // namespace media |
OLD | NEW |