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

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

Issue 1242913004: MediaCodecPlayer implementation (stage 3 - browser seek and surface change) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mtplayer-seek
Patch Set: Rebased, changed DCHECKs. 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_player.h" 5 #include "media/base/android/media_codec_player.h"
6 6
7 #include "base/barrier_closure.h" 7 #include "base/barrier_closure.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/lazy_instance.h" 9 #include "base/lazy_instance.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 base::WeakPtr<MediaPlayerManager> manager, 51 base::WeakPtr<MediaPlayerManager> manager,
52 const RequestMediaResourcesCB& request_media_resources_cb, 52 const RequestMediaResourcesCB& request_media_resources_cb,
53 scoped_ptr<DemuxerAndroid> demuxer, 53 scoped_ptr<DemuxerAndroid> demuxer,
54 const GURL& frame_url) 54 const GURL& frame_url)
55 : MediaPlayerAndroid(player_id, 55 : MediaPlayerAndroid(player_id,
56 manager.get(), 56 manager.get(),
57 request_media_resources_cb, 57 request_media_resources_cb,
58 frame_url), 58 frame_url),
59 ui_task_runner_(base::ThreadTaskRunnerHandle::Get()), 59 ui_task_runner_(base::ThreadTaskRunnerHandle::Get()),
60 demuxer_(demuxer.Pass()), 60 demuxer_(demuxer.Pass()),
61 state_(STATE_PAUSED), 61 state_(kStatePaused),
62 interpolator_(&default_tick_clock_), 62 interpolator_(&default_tick_clock_),
63 pending_start_(false), 63 pending_start_(false),
64 pending_seek_(kNoTimestamp()), 64 pending_seek_(kNoTimestamp()),
65 media_weak_factory_(this) { 65 media_weak_factory_(this) {
66 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 66 DCHECK(ui_task_runner_->BelongsToCurrentThread());
67 67
68 DVLOG(1) << "MediaCodecPlayer::MediaCodecPlayer: player_id:" << player_id; 68 DVLOG(1) << "MediaCodecPlayer::MediaCodecPlayer: player_id:" << player_id;
69 69
70 request_resources_cb_ = base::Bind(request_media_resources_cb_, player_id); 70 request_resources_cb_ = base::Bind(request_media_resources_cb_, player_id);
71 71
72 completion_cb_ = 72 completion_cb_ =
73 base::Bind(&MediaPlayerManager::OnPlaybackComplete, manager, player_id); 73 base::Bind(&MediaPlayerManager::OnPlaybackComplete, manager, player_id);
74 seek_done_cb_ = 74 seek_done_cb_ =
75 base::Bind(&MediaPlayerManager::OnSeekComplete, manager, player_id); 75 base::Bind(&MediaPlayerManager::OnSeekComplete, manager, player_id);
76 error_cb_ = base::Bind(&MediaPlayerManager::OnError, manager, player_id);
76 attach_listener_cb_ = base::Bind(&MediaPlayerAndroid::AttachListener, 77 attach_listener_cb_ = base::Bind(&MediaPlayerAndroid::AttachListener,
77 WeakPtrForUIThread(), nullptr); 78 WeakPtrForUIThread(), nullptr);
78 detach_listener_cb_ = 79 detach_listener_cb_ =
79 base::Bind(&MediaPlayerAndroid::DetachListener, WeakPtrForUIThread()); 80 base::Bind(&MediaPlayerAndroid::DetachListener, WeakPtrForUIThread());
80 metadata_changed_cb_ = base::Bind(&MediaPlayerAndroid::OnMediaMetadataChanged, 81 metadata_changed_cb_ = base::Bind(&MediaPlayerAndroid::OnMediaMetadataChanged,
81 WeakPtrForUIThread()); 82 WeakPtrForUIThread());
82 time_update_cb_ = 83 time_update_cb_ =
83 base::Bind(&MediaPlayerAndroid::OnTimeUpdate, WeakPtrForUIThread()); 84 base::Bind(&MediaPlayerAndroid::OnTimeUpdate, WeakPtrForUIThread());
84 85
85 media_weak_this_ = media_weak_factory_.GetWeakPtr(); 86 media_weak_this_ = media_weak_factory_.GetWeakPtr();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 124
124 // Post deletion onto Media thread 125 // Post deletion onto Media thread
125 GetMediaTaskRunner()->DeleteSoon(FROM_HERE, this); 126 GetMediaTaskRunner()->DeleteSoon(FROM_HERE, this);
126 } 127 }
127 128
128 void MediaCodecPlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { 129 void MediaCodecPlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) {
129 RUN_ON_MEDIA_THREAD(SetVideoSurface, base::Passed(&surface)); 130 RUN_ON_MEDIA_THREAD(SetVideoSurface, base::Passed(&surface));
130 131
131 DVLOG(1) << __FUNCTION__ << (surface.IsEmpty() ? " empty" : " non-empty"); 132 DVLOG(1) << __FUNCTION__ << (surface.IsEmpty() ? " empty" : " non-empty");
132 133
133 // I assume that if video decoder already has the surface, 134 // Save the empty-ness before we pass the surface to the decoder.
134 // there will be two calls: 135 bool surface_is_empty = surface.IsEmpty();
135 // (1) SetVideoSurface(0)
136 // (2) SetVideoSurface(new_surface)
137 video_decoder_->SetPendingSurface(surface.Pass());
138 136
139 if (video_decoder_->HasPendingSurface() && 137 // Apparently RemoveVideoSurface() can be called several times in a row,
140 state_ == STATE_WAITING_FOR_SURFACE) { 138 // ignore the second and subsequent calls.
141 SetState(STATE_PLAYING); 139 if (surface_is_empty && !video_decoder_->HasVideoSurface()) {
142 StartPlaybackDecoders(); 140 DVLOG(1) << __FUNCTION__ << ": surface already removed, ignoring";
141 return;
142 }
143
144 video_decoder_->SetVideoSurface(surface.Pass());
145
146 if (surface_is_empty) {
147 // Remove video surface.
148 switch (state_) {
149 case kStatePlaying:
150 if (VideoFinished())
151 break;
152
153 DVLOG(1) << __FUNCTION__ << ": stopping and restarting";
154 // Stop decoders as quickly as possible.
155 StopDecoders(); // synchronous stop
156
157 // Prefetch or wait for initial configuration.
158 if (HasAudio() || HasVideo()) {
159 SetState(kStatePrefetching);
160 StartPrefetchDecoders();
161 } else {
162 SetState(kStateWaitingForConfig);
163 }
164 break;
165
166 default:
167 break; // ignore
168 }
169 } else {
170 // Replace video surface.
171 switch (state_) {
172 case kStateWaitingForSurface:
173 SetState(kStatePlaying);
174 StartPlaybackOrBrowserSeek();
175 break;
176
177 case kStatePlaying:
178 if (VideoFinished())
179 break;
180
181 DVLOG(1) << __FUNCTION__ << ": requesting to stop and restart";
182 SetState(kStateStopping);
183 RequestToStopDecoders();
184 SetPendingStart(true);
185 break;
186
187 default:
188 break; // ignore
189 }
143 } 190 }
144 } 191 }
145 192
146 void MediaCodecPlayer::Start() { 193 void MediaCodecPlayer::Start() {
147 RUN_ON_MEDIA_THREAD(Start); 194 RUN_ON_MEDIA_THREAD(Start);
148 195
149 DVLOG(1) << __FUNCTION__; 196 DVLOG(1) << __FUNCTION__;
150 197
151 switch (state_) { 198 switch (state_) {
152 case STATE_PAUSED: 199 case kStatePaused:
153 // Prefetch or wait for initial configuration. 200 // Prefetch or wait for initial configuration.
154 if (HasAudio() || HasVideo()) { 201 if (HasAudio() || HasVideo()) {
155 SetState(STATE_PREFETCHING); 202 SetState(kStatePrefetching);
156 StartPrefetchDecoders(); 203 StartPrefetchDecoders();
157 } else { 204 } else {
158 SetState(STATE_WAITING_FOR_CONFIG); 205 SetState(kStateWaitingForConfig);
159 } 206 }
160 break; 207 break;
161 case STATE_STOPPING: 208 case kStateStopping:
162 case STATE_WAITING_FOR_SEEK: 209 case kStateWaitingForSeek:
163 SetPendingStart(true); 210 SetPendingStart(true);
164 break; 211 break;
165 case STATE_WAITING_FOR_CONFIG: 212 case kStateWaitingForConfig:
166 case STATE_PREFETCHING: 213 case kStatePrefetching:
167 case STATE_PLAYING: 214 case kStatePlaying:
168 case STATE_WAITING_FOR_SURFACE: 215 case kStateWaitingForSurface:
169 case STATE_ERROR: 216 case kStateError:
170 break; // Ignore 217 break; // Ignore
171 default: 218 default:
172 NOTREACHED(); 219 NOTREACHED();
173 break; 220 break;
174 } 221 }
175 } 222 }
176 223
177 void MediaCodecPlayer::Pause(bool is_media_related_action) { 224 void MediaCodecPlayer::Pause(bool is_media_related_action) {
178 RUN_ON_MEDIA_THREAD(Pause, is_media_related_action); 225 RUN_ON_MEDIA_THREAD(Pause, is_media_related_action);
179 226
180 DVLOG(1) << __FUNCTION__; 227 DVLOG(1) << __FUNCTION__;
181 228
182 SetPendingStart(false); 229 SetPendingStart(false);
183 230
184 switch (state_) { 231 switch (state_) {
185 case STATE_WAITING_FOR_CONFIG: 232 case kStateWaitingForConfig:
186 case STATE_PREFETCHING: 233 case kStatePrefetching:
187 case STATE_WAITING_FOR_SURFACE: 234 case kStateWaitingForSurface:
188 SetState(STATE_PAUSED); 235 SetState(kStatePaused);
189 StopDecoders(); 236 StopDecoders();
190 break; 237 break;
191 case STATE_PLAYING: 238 case kStatePlaying:
192 SetState(STATE_STOPPING); 239 SetState(kStateStopping);
193 RequestToStopDecoders(); 240 RequestToStopDecoders();
194 break; 241 break;
195 case STATE_PAUSED: 242 case kStatePaused:
196 case STATE_STOPPING: 243 case kStateStopping:
197 case STATE_WAITING_FOR_SEEK: 244 case kStateWaitingForSeek:
198 case STATE_ERROR: 245 case kStateError:
199 break; // Ignore 246 break; // Ignore
200 default: 247 default:
201 NOTREACHED(); 248 NOTREACHED();
202 break; 249 break;
203 } 250 }
204 } 251 }
205 252
206 void MediaCodecPlayer::SeekTo(base::TimeDelta timestamp) { 253 void MediaCodecPlayer::SeekTo(base::TimeDelta timestamp) {
207 RUN_ON_MEDIA_THREAD(SeekTo, timestamp); 254 RUN_ON_MEDIA_THREAD(SeekTo, timestamp);
208 255
209 DVLOG(1) << __FUNCTION__ << " " << timestamp; 256 DVLOG(1) << __FUNCTION__ << " " << timestamp;
210 257
211 switch (state_) { 258 switch (state_) {
212 case STATE_PAUSED: 259 case kStatePaused:
213 SetState(STATE_WAITING_FOR_SEEK); 260 SetState(kStateWaitingForSeek);
214 RequestDemuxerSeek(timestamp); 261 RequestDemuxerSeek(timestamp);
215 break; 262 break;
216 case STATE_WAITING_FOR_CONFIG: 263 case kStateWaitingForConfig:
217 case STATE_PREFETCHING: 264 case kStatePrefetching:
218 case STATE_WAITING_FOR_SURFACE: 265 case kStateWaitingForSurface:
219 SetState(STATE_WAITING_FOR_SEEK); 266 SetState(kStateWaitingForSeek);
220 StopDecoders(); 267 StopDecoders();
221 SetPendingStart(true); 268 SetPendingStart(true);
222 RequestDemuxerSeek(timestamp); 269 RequestDemuxerSeek(timestamp);
223 break; 270 break;
224 case STATE_PLAYING: 271 case kStatePlaying:
225 SetState(STATE_STOPPING); 272 SetState(kStateStopping);
226 RequestToStopDecoders(); 273 RequestToStopDecoders();
227 SetPendingStart(true); 274 SetPendingStart(true);
228 SetPendingSeek(timestamp); 275 SetPendingSeek(timestamp);
229 break; 276 break;
230 case STATE_STOPPING: 277 case kStateStopping:
231 SetPendingSeek(timestamp); 278 SetPendingSeek(timestamp);
232 break; 279 break;
233 case STATE_WAITING_FOR_SEEK: 280 case kStateWaitingForSeek:
234 SetPendingSeek(timestamp); 281 SetPendingSeek(timestamp);
235 break; 282 break;
236 case STATE_ERROR: 283 case kStateError:
237 break; // ignore 284 break; // ignore
238 default: 285 default:
239 NOTREACHED(); 286 NOTREACHED();
240 break; 287 break;
241 } 288 }
242 } 289 }
243 290
244 void MediaCodecPlayer::Release() { 291 void MediaCodecPlayer::Release() {
245 RUN_ON_MEDIA_THREAD(Release); 292 RUN_ON_MEDIA_THREAD(Release);
246 293
247 DVLOG(1) << __FUNCTION__; 294 DVLOG(1) << __FUNCTION__;
248 295
249 SetState(STATE_PAUSED); 296 // Stop decoding threads and delete MediaCodecs, but keep IPC between browser
297 // and renderer processes going. Seek should work across and after Release().
298
250 ReleaseDecoderResources(); 299 ReleaseDecoderResources();
300
301 SetPendingStart(false);
302
303 if (state_ != kStateWaitingForSeek)
304 SetState(kStatePaused);
305
306 base::TimeDelta pending_seek_time = GetPendingSeek();
307 if (pending_seek_time != kNoTimestamp()) {
308 SetPendingSeek(kNoTimestamp());
309 SetState(kStateWaitingForSeek);
310 RequestDemuxerSeek(pending_seek_time);
311 }
251 } 312 }
252 313
253 void MediaCodecPlayer::SetVolume(double volume) { 314 void MediaCodecPlayer::SetVolume(double volume) {
254 RUN_ON_MEDIA_THREAD(SetVolume, volume); 315 RUN_ON_MEDIA_THREAD(SetVolume, volume);
255 316
256 DVLOG(1) << __FUNCTION__ << " " << volume; 317 DVLOG(1) << __FUNCTION__ << " " << volume;
257 audio_decoder_->SetVolume(volume); 318 audio_decoder_->SetVolume(volume);
258 } 319 }
259 320
260 int MediaCodecPlayer::GetVideoWidth() { 321 int MediaCodecPlayer::GetVideoWidth() {
(...skipping 14 matching lines...) Expand all
275 base::TimeDelta MediaCodecPlayer::GetDuration() { 336 base::TimeDelta MediaCodecPlayer::GetDuration() {
276 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 337 DCHECK(ui_task_runner_->BelongsToCurrentThread());
277 return metadata_cache_.duration; 338 return metadata_cache_.duration;
278 } 339 }
279 340
280 bool MediaCodecPlayer::IsPlaying() { 341 bool MediaCodecPlayer::IsPlaying() {
281 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 342 DCHECK(ui_task_runner_->BelongsToCurrentThread());
282 343
283 // TODO(timav): Use another variable since |state_| should only be accessed on 344 // TODO(timav): Use another variable since |state_| should only be accessed on
284 // Media thread. 345 // Media thread.
285 return state_ == STATE_PLAYING || state_ == STATE_STOPPING; 346 return state_ == kStatePlaying || state_ == kStateStopping;
286 } 347 }
287 348
288 bool MediaCodecPlayer::CanPause() { 349 bool MediaCodecPlayer::CanPause() {
289 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 350 DCHECK(ui_task_runner_->BelongsToCurrentThread());
290 NOTIMPLEMENTED(); 351 NOTIMPLEMENTED();
291 return false; 352 return false;
292 } 353 }
293 354
294 bool MediaCodecPlayer::CanSeekForward() { 355 bool MediaCodecPlayer::CanSeekForward() {
295 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 356 DCHECK(ui_task_runner_->BelongsToCurrentThread());
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 if (data.type == DemuxerStream::VIDEO) 408 if (data.type == DemuxerStream::VIDEO)
348 video_decoder_->OnDemuxerDataAvailable(data); 409 video_decoder_->OnDemuxerDataAvailable(data);
349 } 410 }
350 411
351 void MediaCodecPlayer::OnDemuxerSeekDone( 412 void MediaCodecPlayer::OnDemuxerSeekDone(
352 base::TimeDelta actual_browser_seek_time) { 413 base::TimeDelta actual_browser_seek_time) {
353 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 414 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
354 415
355 DVLOG(1) << __FUNCTION__ << " actual_time:" << actual_browser_seek_time; 416 DVLOG(1) << __FUNCTION__ << " actual_time:" << actual_browser_seek_time;
356 417
357 if (state_ != STATE_WAITING_FOR_SEEK)
358 return; // ignore
359
360 DCHECK(seek_info_.get()); 418 DCHECK(seek_info_.get());
361 DCHECK(seek_info_->seek_time != kNoTimestamp()); 419 DCHECK(seek_info_->seek_time != kNoTimestamp());
362 420
363 // A browser seek must not jump into the past. Ideally, it seeks to the 421 // A browser seek must not jump into the past. Ideally, it seeks to the
364 // requested time, but it might jump into the future. 422 // requested time, but it might jump into the future.
365 DCHECK(!seek_info_->is_browser_seek || 423 DCHECK(!seek_info_->is_browser_seek ||
366 seek_info_->seek_time <= actual_browser_seek_time); 424 seek_info_->seek_time <= actual_browser_seek_time);
367 425
368 // Restrict the current time to be equal to seek_time 426 // Restrict the current time to be equal to seek_time
369 // for the next StartPlaybackDecoders() call. 427 // for the next StartPlaybackDecoders() call.
370 428
371 base::TimeDelta seek_time = seek_info_->is_browser_seek 429 base::TimeDelta seek_time = seek_info_->is_browser_seek
372 ? actual_browser_seek_time 430 ? actual_browser_seek_time
373 : seek_info_->seek_time; 431 : seek_info_->seek_time;
374 432
375 interpolator_.SetBounds(seek_time, seek_time); 433 interpolator_.SetBounds(seek_time, seek_time);
376 audio_decoder_->SetBaseTimestamp(seek_time); 434 audio_decoder_->SetBaseTimestamp(seek_time);
377 435
436 // The Flush() might set the state to kStateError.
437 if (state_ == kStateError) {
438 // Notify the Renderer.
439 if (!seek_info_->is_browser_seek)
440 ui_task_runner_->PostTask(FROM_HERE,
441 base::Bind(seek_done_cb_, seek_time));
442
443 seek_info_.reset();
444 return;
445 }
446
447 DCHECK_EQ(kStateWaitingForSeek, state_);
448
378 base::TimeDelta pending_seek_time = GetPendingSeek(); 449 base::TimeDelta pending_seek_time = GetPendingSeek();
379 if (pending_seek_time != kNoTimestamp()) { 450 if (pending_seek_time != kNoTimestamp()) {
380 // Keep STATE_WAITING_FOR_SEEK 451 // Keep kStateWaitingForSeek
381 SetPendingSeek(kNoTimestamp()); 452 SetPendingSeek(kNoTimestamp());
382 RequestDemuxerSeek(pending_seek_time); 453 RequestDemuxerSeek(pending_seek_time);
383 return; 454 return;
384 } 455 }
385 456
386 if (HasPendingStart()) { 457 if (HasPendingStart()) {
387 SetPendingStart(false); 458 SetPendingStart(false);
388 // Prefetch or wait for initial configuration. 459 // Prefetch or wait for initial configuration.
389 if (HasAudio() || HasVideo()) { 460 if (HasAudio() || HasVideo()) {
390 SetState(STATE_PREFETCHING); 461 SetState(kStatePrefetching);
391 StartPrefetchDecoders(); 462 StartPrefetchDecoders();
392 } else { 463 } else {
393 SetState(STATE_WAITING_FOR_CONFIG); 464 SetState(kStateWaitingForConfig);
394 } 465 }
395 } else { 466 } else {
396 SetState(STATE_PAUSED); 467 SetState(kStatePaused);
397 } 468 }
398 469
399 // Notify the Renderer. 470 // Notify the Renderer.
400 if (!seek_info_->is_browser_seek) 471 if (!seek_info_->is_browser_seek)
401 ui_task_runner_->PostTask(FROM_HERE, base::Bind(seek_done_cb_, seek_time)); 472 ui_task_runner_->PostTask(FROM_HERE, base::Bind(seek_done_cb_, seek_time));
402 473
403 seek_info_.reset(); 474 seek_info_.reset();
404 } 475 }
405 476
406 void MediaCodecPlayer::OnDemuxerDurationChanged( 477 void MediaCodecPlayer::OnDemuxerDurationChanged(
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 // 4. RequestDemuxerData is processed by the media thread queue. Since the 522 // 4. RequestDemuxerData is processed by the media thread queue. Since the
452 // weak_ptr was invalidated in (3), this is a no-op. If we used 523 // weak_ptr was invalidated in (3), this is a no-op. If we used
453 // DemuxerAndroid::RequestDemuxerData() it would arrive and will try to 524 // DemuxerAndroid::RequestDemuxerData() it would arrive and will try to
454 // call the client, but the client (i.e. this player) would not exist. 525 // call the client, but the client (i.e. this player) would not exist.
455 demuxer_->RequestDemuxerData(stream_type); 526 demuxer_->RequestDemuxerData(stream_type);
456 } 527 }
457 528
458 void MediaCodecPlayer::OnPrefetchDone() { 529 void MediaCodecPlayer::OnPrefetchDone() {
459 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 530 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
460 531
461 if (state_ != STATE_PREFETCHING) { 532 if (state_ != kStatePrefetching) {
462 DVLOG(1) << __FUNCTION__ << " wrong state " << AsString(state_) 533 DVLOG(1) << __FUNCTION__ << " wrong state " << AsString(state_)
463 << " ignoring"; 534 << " ignoring";
464 return; // Ignore 535 return; // Ignore
465 } 536 }
466 537
467 DVLOG(1) << __FUNCTION__; 538 DVLOG(1) << __FUNCTION__;
468 539
469 if (!HasAudio() && !HasVideo()) { 540 if (!HasAudio() && !HasVideo()) {
470 // No configuration at all after prefetching. 541 // No configuration at all after prefetching.
471 // This is an error, initial configuration is expected 542 // This is an error, initial configuration is expected
472 // before the first data chunk. 543 // before the first data chunk.
473 GetMediaTaskRunner()->PostTask(FROM_HERE, error_cb_); 544 DCHECK(!internal_error_cb_.is_null());
545 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_);
474 return; 546 return;
475 } 547 }
476 548
477 if (HasVideo() && !HasPendingSurface()) { 549 if (HasVideo() && !video_decoder_->HasVideoSurface()) {
478 SetState(STATE_WAITING_FOR_SURFACE); 550 SetState(kStateWaitingForSurface);
479 return; 551 return;
480 } 552 }
481 553
482 SetState(STATE_PLAYING); 554 SetState(kStatePlaying);
483 StartPlaybackDecoders(); 555 StartPlaybackOrBrowserSeek();
484 } 556 }
485 557
486 void MediaCodecPlayer::OnStopDone() { 558 void MediaCodecPlayer::OnStopDone() {
487 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 559 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
488 DVLOG(1) << __FUNCTION__; 560 DVLOG(1) << __FUNCTION__;
489 561
490 if (!(audio_decoder_->IsStopped() && video_decoder_->IsStopped())) 562 if (!(audio_decoder_->IsStopped() && video_decoder_->IsStopped()))
491 return; // Wait until other stream is stopped 563 return; // Wait until other stream is stopped
492 564
493 // At this point decoder threads should not be running 565 // At this point decoder threads should not be running
494 if (interpolator_.interpolating()) 566 if (interpolator_.interpolating())
495 interpolator_.StopInterpolating(); 567 interpolator_.StopInterpolating();
496 568
497 base::TimeDelta seek_time; 569 base::TimeDelta seek_time;
498 switch (state_) { 570 switch (state_) {
499 case STATE_STOPPING: { 571 case kStateStopping: {
500 base::TimeDelta seek_time = GetPendingSeek(); 572 base::TimeDelta seek_time = GetPendingSeek();
501 if (seek_time != kNoTimestamp()) { 573 if (seek_time != kNoTimestamp()) {
502 SetState(STATE_WAITING_FOR_SEEK); 574 SetState(kStateWaitingForSeek);
503 SetPendingSeek(kNoTimestamp()); 575 SetPendingSeek(kNoTimestamp());
504 RequestDemuxerSeek(seek_time); 576 RequestDemuxerSeek(seek_time);
505 } else if (HasPendingStart()) { 577 } else if (HasPendingStart()) {
506 SetPendingStart(false); 578 SetPendingStart(false);
507 SetState(STATE_PREFETCHING); 579 SetState(kStatePrefetching);
508 StartPrefetchDecoders(); 580 StartPrefetchDecoders();
509 } else { 581 } else {
510 SetState(STATE_PAUSED); 582 SetState(kStatePaused);
511 } 583 }
512 } break; 584 } break;
513 case STATE_PLAYING: 585 case kStatePlaying:
514 // Unexpected stop means completion 586 // Unexpected stop means completion
515 SetState(STATE_PAUSED); 587 SetState(kStatePaused);
516 break; 588 break;
517 default: 589 default:
518 // DVLOG(0) << __FUNCTION__ << " illegal state: " << AsString(state_); 590 // DVLOG(0) << __FUNCTION__ << " illegal state: " << AsString(state_);
519 // NOTREACHED(); 591 // NOTREACHED();
520 // Ignore! There can be a race condition: audio posts OnStopDone, 592 // Ignore! There can be a race condition: audio posts OnStopDone,
521 // then video posts, then first OnStopDone arrives at which point 593 // then video posts, then first OnStopDone arrives at which point
522 // both streams are already stopped, then second OnStopDone arrives. When 594 // both streams are already stopped, then second OnStopDone arrives. When
523 // the second one arrives, the state us not STATE_STOPPING any more. 595 // the second one arrives, the state us not kStateStopping any more.
524 break; 596 break;
525 } 597 }
526 598
527 // DetachListener to UI thread 599 // DetachListener to UI thread
528 ui_task_runner_->PostTask(FROM_HERE, detach_listener_cb_); 600 ui_task_runner_->PostTask(FROM_HERE, detach_listener_cb_);
529 601
530 if (AudioFinished() && VideoFinished()) 602 if (AudioFinished() && VideoFinished())
531 ui_task_runner_->PostTask(FROM_HERE, completion_cb_); 603 ui_task_runner_->PostTask(FROM_HERE, completion_cb_);
532 } 604 }
533 605
534 void MediaCodecPlayer::OnError() { 606 void MediaCodecPlayer::OnError() {
535 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 607 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
536 DVLOG(1) << __FUNCTION__; 608 DVLOG(1) << __FUNCTION__;
537 609
538 // STATE_ERROR blocks all events 610 // kStateError blocks all events
539 SetState(STATE_ERROR); 611 SetState(kStateError);
540 612
541 ReleaseDecoderResources(); 613 ReleaseDecoderResources();
614
615 ui_task_runner_->PostTask(FROM_HERE,
616 base::Bind(error_cb_, MEDIA_ERROR_DECODE));
542 } 617 }
543 618
544 void MediaCodecPlayer::OnStarvation(DemuxerStream::Type type) { 619 void MediaCodecPlayer::OnStarvation(DemuxerStream::Type type) {
545 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 620 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
546 DVLOG(1) << __FUNCTION__ << " stream type:" << type; 621 DVLOG(1) << __FUNCTION__ << " stream type:" << type;
547 622
548 if (state_ != STATE_PLAYING) 623 if (state_ != kStatePlaying)
549 return; // Ignore 624 return; // Ignore
550 625
551 SetState(STATE_STOPPING); 626 SetState(kStateStopping);
552 RequestToStopDecoders(); 627 RequestToStopDecoders();
553 SetPendingStart(true); 628 SetPendingStart(true);
554 } 629 }
555 630
556 void MediaCodecPlayer::OnTimeIntervalUpdate(DemuxerStream::Type type, 631 void MediaCodecPlayer::OnTimeIntervalUpdate(DemuxerStream::Type type,
557 base::TimeDelta now_playing, 632 base::TimeDelta now_playing,
558 base::TimeDelta last_buffered) { 633 base::TimeDelta last_buffered) {
559 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 634 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
560 635
561 DVLOG(2) << __FUNCTION__ << ": stream type:" << type << " [" << now_playing 636 DVLOG(2) << __FUNCTION__ << ": stream type:" << type << " [" << now_playing
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 673
599 // State machine operations, called on Media thread 674 // State machine operations, called on Media thread
600 675
601 void MediaCodecPlayer::SetState(PlayerState new_state) { 676 void MediaCodecPlayer::SetState(PlayerState new_state) {
602 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 677 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
603 678
604 DVLOG(1) << "SetState:" << AsString(state_) << " -> " << AsString(new_state); 679 DVLOG(1) << "SetState:" << AsString(state_) << " -> " << AsString(new_state);
605 state_ = new_state; 680 state_ = new_state;
606 } 681 }
607 682
608 void MediaCodecPlayer::SetPendingSurface(gfx::ScopedJavaSurface surface) {
609 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
610 DVLOG(1) << __FUNCTION__;
611
612 video_decoder_->SetPendingSurface(surface.Pass());
613 }
614
615 bool MediaCodecPlayer::HasPendingSurface() const {
616 return video_decoder_->HasPendingSurface();
617 }
618
619 void MediaCodecPlayer::SetPendingStart(bool need_to_start) { 683 void MediaCodecPlayer::SetPendingStart(bool need_to_start) {
620 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 684 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
621 DVLOG(1) << __FUNCTION__ << ": " << need_to_start; 685 DVLOG(1) << __FUNCTION__ << ": " << need_to_start;
622 pending_start_ = need_to_start; 686 pending_start_ = need_to_start;
623 } 687 }
624 688
625 bool MediaCodecPlayer::HasPendingStart() const { 689 bool MediaCodecPlayer::HasPendingStart() const {
626 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 690 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
627 return pending_start_; 691 return pending_start_;
628 } 692 }
(...skipping 29 matching lines...) Expand all
658 // At least one valid codec must be present. 722 // At least one valid codec must be present.
659 DCHECK(configs.audio_codec != kUnknownAudioCodec || 723 DCHECK(configs.audio_codec != kUnknownAudioCodec ||
660 configs.video_codec != kUnknownVideoCodec); 724 configs.video_codec != kUnknownVideoCodec);
661 725
662 if (configs.audio_codec != kUnknownAudioCodec) 726 if (configs.audio_codec != kUnknownAudioCodec)
663 audio_decoder_->SetDemuxerConfigs(configs); 727 audio_decoder_->SetDemuxerConfigs(configs);
664 728
665 if (configs.video_codec != kUnknownVideoCodec) 729 if (configs.video_codec != kUnknownVideoCodec)
666 video_decoder_->SetDemuxerConfigs(configs); 730 video_decoder_->SetDemuxerConfigs(configs);
667 731
668 if (state_ == STATE_WAITING_FOR_CONFIG) { 732 if (state_ == kStateWaitingForConfig) {
669 SetState(STATE_PREFETCHING); 733 SetState(kStatePrefetching);
670 StartPrefetchDecoders(); 734 StartPrefetchDecoders();
671 } 735 }
672 } 736 }
673 737
674 void MediaCodecPlayer::StartPrefetchDecoders() { 738 void MediaCodecPlayer::StartPrefetchDecoders() {
675 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 739 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
676 DVLOG(1) << __FUNCTION__; 740 DVLOG(1) << __FUNCTION__;
677 741
678 bool do_audio = false; 742 bool do_audio = false;
679 bool do_video = false; 743 bool do_video = false;
(...skipping 12 matching lines...) Expand all
692 base::Closure prefetch_cb = base::BarrierClosure( 756 base::Closure prefetch_cb = base::BarrierClosure(
693 count, base::Bind(&MediaCodecPlayer::OnPrefetchDone, media_weak_this_)); 757 count, base::Bind(&MediaCodecPlayer::OnPrefetchDone, media_weak_this_));
694 758
695 if (do_audio) 759 if (do_audio)
696 audio_decoder_->Prefetch(prefetch_cb); 760 audio_decoder_->Prefetch(prefetch_cb);
697 761
698 if (do_video) 762 if (do_video)
699 video_decoder_->Prefetch(prefetch_cb); 763 video_decoder_->Prefetch(prefetch_cb);
700 } 764 }
701 765
702 void MediaCodecPlayer::StartPlaybackDecoders() { 766 void MediaCodecPlayer::StartPlaybackOrBrowserSeek() {
703 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 767 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
704 DVLOG(1) << __FUNCTION__; 768 DVLOG(1) << __FUNCTION__;
705 769
706 // Configure all streams before the start since 770 // TODO(timav): consider replacing this method with posting a
707 // we may discover that browser seek is required. 771 // browser seek task (i.e. generate an event) from StartPlaybackDecoders().
772
773 StartStatus status = StartPlaybackDecoders();
774
775 switch (status) {
776 case kStartBrowserSeekRequired:
777 // Browser seek
778 SetState(kStateWaitingForSeek);
779 SetPendingStart(true);
780 StopDecoders();
781 RequestDemuxerSeek(GetInterpolatedTime(), true);
782 break;
783 case kStartFailed:
784 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_);
785 break;
786 case kStartOk:
787 break;
788 }
789 }
790
791 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartPlaybackDecoders() {
792 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
793 DVLOG(1) << __FUNCTION__;
708 794
709 bool do_audio = !AudioFinished(); 795 bool do_audio = !AudioFinished();
710 bool do_video = !VideoFinished(); 796 bool do_video = !VideoFinished();
711 797
712 // If there is nothing to play, the state machine should determine 798 // If there is nothing to play, the state machine should determine this at the
713 // this at the prefetch state and never call this method. 799 // prefetch state and never call this method.
714 DCHECK(do_audio || do_video); 800 DCHECK(do_audio || do_video);
715 801
802 // Configure all streams before the start since we may discover that browser
803 // seek is required. Start with video: if browser seek is required it would
804 // not make sense to configure audio.
805
806 if (do_video) {
807 MediaCodecDecoder::ConfigStatus status = video_decoder_->Configure();
808 switch (status) {
809 case MediaCodecDecoder::kConfigOk:
810 break;
811 case MediaCodecDecoder::kConfigKeyFrameRequired:
812 // TODO(timav): post a task or return the status?
813 return kStartBrowserSeekRequired;
814 case MediaCodecDecoder::kConfigFailure:
815 return kStartFailed;
816 }
817 }
818
716 if (do_audio) { 819 if (do_audio) {
717 MediaCodecDecoder::ConfigStatus status = audio_decoder_->Configure(); 820 MediaCodecDecoder::ConfigStatus status = audio_decoder_->Configure();
718 if (status != MediaCodecDecoder::CONFIG_OK) { 821 if (status != MediaCodecDecoder::kConfigOk) {
719 GetMediaTaskRunner()->PostTask(FROM_HERE, error_cb_); 822 return kStartFailed;
720 return;
721 } 823 }
722 } 824 }
723 825
724 if (do_video) {
725 MediaCodecDecoder::ConfigStatus status = video_decoder_->Configure();
726 if (status != MediaCodecDecoder::CONFIG_OK) {
727 GetMediaTaskRunner()->PostTask(FROM_HERE, error_cb_);
728 return;
729 }
730 }
731
732 // At this point decoder threads should not be running. 826 // At this point decoder threads should not be running.
733 if (!interpolator_.interpolating()) 827 if (!interpolator_.interpolating())
734 interpolator_.StartInterpolating(); 828 interpolator_.StartInterpolating();
735 829
736 base::TimeDelta current_time = GetInterpolatedTime(); 830 base::TimeDelta current_time = GetInterpolatedTime();
737 831
738 if (do_audio) { 832 if (do_audio) {
739 if (!audio_decoder_->Start(current_time)) { 833 if (!audio_decoder_->Start(current_time)) {
740 GetMediaTaskRunner()->PostTask(FROM_HERE, error_cb_); 834 return kStartFailed;
741 return;
742 } 835 }
743 836
744 // Attach listener on UI thread 837 // Attach listener on UI thread
745 ui_task_runner_->PostTask(FROM_HERE, attach_listener_cb_); 838 ui_task_runner_->PostTask(FROM_HERE, attach_listener_cb_);
746 } 839 }
747 840
748 if (do_video) { 841 if (do_video) {
749 if (!video_decoder_->Start(current_time)) { 842 if (!video_decoder_->Start(current_time)) {
750 GetMediaTaskRunner()->PostTask(FROM_HERE, error_cb_); 843 return kStartFailed;
751 return;
752 } 844 }
753 } 845 }
846
847 return kStartOk;
754 } 848 }
755 849
756 void MediaCodecPlayer::StopDecoders() { 850 void MediaCodecPlayer::StopDecoders() {
757 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 851 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
758 DVLOG(1) << __FUNCTION__; 852 DVLOG(1) << __FUNCTION__;
759 853
854 video_decoder_->SyncStop();
760 audio_decoder_->SyncStop(); 855 audio_decoder_->SyncStop();
761 video_decoder_->SyncStop();
762 } 856 }
763 857
764 void MediaCodecPlayer::RequestToStopDecoders() { 858 void MediaCodecPlayer::RequestToStopDecoders() {
765 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 859 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
766 DVLOG(1) << __FUNCTION__; 860 DVLOG(1) << __FUNCTION__;
767 861
768 bool do_audio = false; 862 bool do_audio = false;
769 bool do_video = false; 863 bool do_video = false;
770 864
771 if (audio_decoder_->IsPrefetchingOrPlaying()) 865 if (audio_decoder_->IsPrefetchingOrPlaying())
(...skipping 10 matching lines...) Expand all
782 if (do_audio) 876 if (do_audio)
783 audio_decoder_->RequestToStop(); 877 audio_decoder_->RequestToStop();
784 if (do_video) 878 if (do_video)
785 video_decoder_->RequestToStop(); 879 video_decoder_->RequestToStop();
786 } 880 }
787 881
788 void MediaCodecPlayer::RequestDemuxerSeek(base::TimeDelta seek_time, 882 void MediaCodecPlayer::RequestDemuxerSeek(base::TimeDelta seek_time,
789 bool is_browser_seek) { 883 bool is_browser_seek) {
790 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 884 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
791 DVLOG(1) << __FUNCTION__ << " " << seek_time 885 DVLOG(1) << __FUNCTION__ << " " << seek_time
792 << (is_browser_seek ? " browser_seek" : ""); 886 << (is_browser_seek ? " BROWSER_SEEK" : "");
793 887
794 // Flush decoders before requesting demuxer. 888 // Flush decoders before requesting demuxer.
795 audio_decoder_->Flush(); 889 audio_decoder_->Flush();
796 video_decoder_->Flush(); 890 video_decoder_->Flush();
797 891
798 // Save active seek data. Logically it is attached to STATE_WAITING_FOR_SEEK. 892 // Save active seek data. Logically it is attached to kStateWaitingForSeek.
799 DCHECK(state_ == STATE_WAITING_FOR_SEEK); 893 DCHECK_EQ(kStateWaitingForSeek, state_);
800 seek_info_.reset(new SeekInfo(seek_time, is_browser_seek)); 894 seek_info_.reset(new SeekInfo(seek_time, is_browser_seek));
801 895
802 demuxer_->RequestDemuxerSeek(seek_time, is_browser_seek); 896 demuxer_->RequestDemuxerSeek(seek_time, is_browser_seek);
803 } 897 }
804 898
805 void MediaCodecPlayer::ReleaseDecoderResources() { 899 void MediaCodecPlayer::ReleaseDecoderResources() {
806 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 900 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
807 DVLOG(1) << __FUNCTION__; 901 DVLOG(1) << __FUNCTION__;
808 902
809 if (audio_decoder_) 903 if (audio_decoder_)
810 audio_decoder_->ReleaseDecoderResources(); 904 audio_decoder_->ReleaseDecoderResources();
811 905
812 if (video_decoder_) 906 if (video_decoder_)
813 video_decoder_->ReleaseDecoderResources(); 907 video_decoder_->ReleaseDecoderResources();
814 908
815 // At this point decoder threads should not be running 909 // At this point decoder threads should not be running
816 if (interpolator_.interpolating()) 910 if (interpolator_.interpolating())
817 interpolator_.StopInterpolating(); 911 interpolator_.StopInterpolating();
818 } 912 }
819 913
820 void MediaCodecPlayer::CreateDecoders() { 914 void MediaCodecPlayer::CreateDecoders() {
821 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 915 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
822 DVLOG(1) << __FUNCTION__; 916 DVLOG(1) << __FUNCTION__;
823 917
824 error_cb_ = base::Bind(&MediaCodecPlayer::OnError, media_weak_this_); 918 internal_error_cb_ = base::Bind(&MediaCodecPlayer::OnError, media_weak_this_);
825 919
826 audio_decoder_.reset(new MediaCodecAudioDecoder( 920 audio_decoder_.reset(new MediaCodecAudioDecoder(
827 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, 921 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData,
828 media_weak_this_, DemuxerStream::AUDIO), 922 media_weak_this_, DemuxerStream::AUDIO),
829 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, 923 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_,
830 DemuxerStream::AUDIO), 924 DemuxerStream::AUDIO),
831 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_), error_cb_, 925 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_),
926 internal_error_cb_,
832 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, 927 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_,
833 DemuxerStream::AUDIO))); 928 DemuxerStream::AUDIO)));
834 929
835 video_decoder_.reset(new MediaCodecVideoDecoder( 930 video_decoder_.reset(new MediaCodecVideoDecoder(
836 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, 931 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData,
837 media_weak_this_, DemuxerStream::VIDEO), 932 media_weak_this_, DemuxerStream::VIDEO),
838 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, 933 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_,
839 DemuxerStream::VIDEO), 934 DemuxerStream::VIDEO),
840 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_), error_cb_, 935 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_),
936 internal_error_cb_,
841 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, 937 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_,
842 DemuxerStream::VIDEO), 938 DemuxerStream::VIDEO),
843 base::Bind(&MediaCodecPlayer::OnVideoResolutionChanged, media_weak_this_), 939 base::Bind(&MediaCodecPlayer::OnVideoResolutionChanged, media_weak_this_),
844 base::Bind(&MediaCodecPlayer::OnVideoCodecCreated, media_weak_this_))); 940 base::Bind(&MediaCodecPlayer::OnVideoCodecCreated, media_weak_this_)));
845 } 941 }
846 942
847 bool MediaCodecPlayer::AudioFinished() const { 943 bool MediaCodecPlayer::AudioFinished() const {
848 return audio_decoder_->IsCompleted() || !audio_decoder_->HasStream(); 944 return audio_decoder_->IsCompleted() || !audio_decoder_->HasStream();
849 } 945 }
850 946
851 bool MediaCodecPlayer::VideoFinished() const { 947 bool MediaCodecPlayer::VideoFinished() const {
852 return video_decoder_->IsCompleted() || !video_decoder_->HasStream(); 948 return video_decoder_->IsCompleted() || !video_decoder_->HasStream();
853 } 949 }
854 950
855 base::TimeDelta MediaCodecPlayer::GetInterpolatedTime() { 951 base::TimeDelta MediaCodecPlayer::GetInterpolatedTime() {
856 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 952 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
857 953
858 base::TimeDelta interpolated_time = interpolator_.GetInterpolatedTime(); 954 base::TimeDelta interpolated_time = interpolator_.GetInterpolatedTime();
859 return std::min(interpolated_time, duration_); 955 return std::min(interpolated_time, duration_);
860 } 956 }
861 957
862 #undef RETURN_STRING 958 #undef RETURN_STRING
863 #define RETURN_STRING(x) \ 959 #define RETURN_STRING(x) \
864 case x: \ 960 case x: \
865 return #x; 961 return #x;
866 962
867 const char* MediaCodecPlayer::AsString(PlayerState state) { 963 const char* MediaCodecPlayer::AsString(PlayerState state) {
868 switch (state) { 964 switch (state) {
869 RETURN_STRING(STATE_PAUSED); 965 RETURN_STRING(kStatePaused);
870 RETURN_STRING(STATE_WAITING_FOR_CONFIG); 966 RETURN_STRING(kStateWaitingForConfig);
871 RETURN_STRING(STATE_PREFETCHING); 967 RETURN_STRING(kStatePrefetching);
872 RETURN_STRING(STATE_PLAYING); 968 RETURN_STRING(kStatePlaying);
873 RETURN_STRING(STATE_STOPPING); 969 RETURN_STRING(kStateStopping);
874 RETURN_STRING(STATE_WAITING_FOR_SURFACE); 970 RETURN_STRING(kStateWaitingForSurface);
875 RETURN_STRING(STATE_WAITING_FOR_SEEK); 971 RETURN_STRING(kStateWaitingForSeek);
876 RETURN_STRING(STATE_ERROR); 972 RETURN_STRING(kStateError);
877 } 973 }
878 return nullptr; // crash early 974 return nullptr; // crash early
879 } 975 }
880 976
881 #undef RETURN_STRING 977 #undef RETURN_STRING
882 978
883 } // namespace media 979 } // namespace media
OLDNEW
« no previous file with comments | « media/base/android/media_codec_player.h ('k') | media/base/android/media_codec_player_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698