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

Side by Side Diff: media/base/pipeline_impl.cc

Issue 7584013: Log PipelineImpl events to MediaLog. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase atop _and_diff_against_ 759001. Created 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 // TODO(scherkus): clean up PipelineImpl... too many crazy function names, 5 // TODO(scherkus): clean up PipelineImpl... too many crazy function names,
6 // potential deadlocks, etc... 6 // potential deadlocks, etc...
7 7
8 #include "media/base/pipeline_impl.h" 8 #include "media/base/pipeline_impl.h"
9 9
10 #include <algorithm> 10 #include <algorithm>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/callback.h" 13 #include "base/callback.h"
14 #include "base/compiler_specific.h" 14 #include "base/compiler_specific.h"
15 #include "base/stl_util.h" 15 #include "base/stl_util.h"
16 #include "base/string_util.h" 16 #include "base/string_util.h"
17 #include "base/synchronization/condition_variable.h" 17 #include "base/synchronization/condition_variable.h"
18 #include "media/base/clock.h" 18 #include "media/base/clock.h"
19 #include "media/base/filter_collection.h" 19 #include "media/base/filter_collection.h"
20 #include "media/base/media_log.h"
20 21
21 namespace media { 22 namespace media {
22 23
23 const char kRawMediaScheme[] = "x-raw-media"; 24 const char kRawMediaScheme[] = "x-raw-media";
24 25
25 PipelineStatusNotification::PipelineStatusNotification() 26 PipelineStatusNotification::PipelineStatusNotification()
26 : cv_(&lock_), status_(PIPELINE_OK), notified_(false) { 27 : cv_(&lock_), status_(PIPELINE_OK), notified_(false) {
27 callback_.reset(NewCallback(this, &PipelineStatusNotification::Notify)); 28 callback_.reset(NewCallback(this, &PipelineStatusNotification::Notify));
28 } 29 }
29 30
(...skipping 25 matching lines...) Expand all
55 return status_; 56 return status_;
56 } 57 }
57 58
58 class PipelineImpl::PipelineInitState { 59 class PipelineImpl::PipelineInitState {
59 public: 60 public:
60 scoped_refptr<AudioDecoder> audio_decoder_; 61 scoped_refptr<AudioDecoder> audio_decoder_;
61 scoped_refptr<VideoDecoder> video_decoder_; 62 scoped_refptr<VideoDecoder> video_decoder_;
62 scoped_refptr<CompositeFilter> composite_; 63 scoped_refptr<CompositeFilter> composite_;
63 }; 64 };
64 65
65 PipelineImpl::PipelineImpl(MessageLoop* message_loop) 66 PipelineImpl::PipelineImpl(MessageLoop* message_loop, MediaLog* media_log)
66 : message_loop_(message_loop), 67 : message_loop_(message_loop),
68 media_log_(media_log),
67 clock_(new Clock(&base::Time::Now)), 69 clock_(new Clock(&base::Time::Now)),
68 waiting_for_clock_update_(false), 70 waiting_for_clock_update_(false),
69 state_(kCreated), 71 state_(kCreated),
70 current_bytes_(0) { 72 current_bytes_(0) {
73 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated));
71 ResetState(); 74 ResetState();
75 media_log_->AddEvent(
76 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED));
72 } 77 }
73 78
74 PipelineImpl::~PipelineImpl() { 79 PipelineImpl::~PipelineImpl() {
75 base::AutoLock auto_lock(lock_); 80 base::AutoLock auto_lock(lock_);
76 DCHECK(!running_) << "Stop() must complete before destroying object"; 81 DCHECK(!running_) << "Stop() must complete before destroying object";
77 DCHECK(!stop_pending_); 82 DCHECK(!stop_pending_);
78 DCHECK(!seek_pending_); 83 DCHECK(!seek_pending_);
84
85 media_log_->AddEvent(
86 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED));
79 } 87 }
80 88
81 void PipelineImpl::Init(PipelineStatusCallback* ended_callback, 89 void PipelineImpl::Init(PipelineStatusCallback* ended_callback,
82 PipelineStatusCallback* error_callback, 90 PipelineStatusCallback* error_callback,
83 PipelineStatusCallback* network_callback) { 91 PipelineStatusCallback* network_callback) {
84 DCHECK(!IsRunning()) 92 DCHECK(!IsRunning())
85 << "Init() should be called before the pipeline has started"; 93 << "Init() should be called before the pipeline has started";
86 ended_callback_.reset(ended_callback); 94 ended_callback_.reset(ended_callback);
87 error_callback_.reset(error_callback); 95 error_callback_.reset(error_callback);
88 network_callback_.reset(network_callback); 96 network_callback_.reset(network_callback);
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 playback_rate_ = 0.0f; 382 playback_rate_ = 0.0f;
375 pending_playback_rate_ = 0.0f; 383 pending_playback_rate_ = 0.0f;
376 status_ = PIPELINE_OK; 384 status_ = PIPELINE_OK;
377 has_audio_ = false; 385 has_audio_ = false;
378 has_video_ = false; 386 has_video_ = false;
379 waiting_for_clock_update_ = false; 387 waiting_for_clock_update_ = false;
380 audio_disabled_ = false; 388 audio_disabled_ = false;
381 clock_->SetTime(kZero); 389 clock_->SetTime(kZero);
382 } 390 }
383 391
384 void PipelineImpl::set_state(State next_state) { 392 void PipelineImpl::SetState(State next_state) {
385 state_ = next_state; 393 state_ = next_state;
394 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(next_state));
386 } 395 }
387 396
388 bool PipelineImpl::IsPipelineOk() { 397 bool PipelineImpl::IsPipelineOk() {
389 base::AutoLock auto_lock(lock_); 398 base::AutoLock auto_lock(lock_);
390 return status_ == PIPELINE_OK; 399 return status_ == PIPELINE_OK;
391 } 400 }
392 401
393 bool PipelineImpl::IsPipelineStopped() { 402 bool PipelineImpl::IsPipelineStopped() {
394 DCHECK_EQ(MessageLoop::current(), message_loop_); 403 DCHECK_EQ(MessageLoop::current(), message_loop_);
395 return state_ == kStopped || state_ == kError; 404 return state_ == kStopped || state_ == kError;
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 seek_callback_.reset(start_callback); 623 seek_callback_.reset(start_callback);
615 624
616 // Kick off initialization. 625 // Kick off initialization.
617 pipeline_init_state_.reset(new PipelineInitState()); 626 pipeline_init_state_.reset(new PipelineInitState());
618 pipeline_init_state_->composite_ = new CompositeFilter(message_loop_); 627 pipeline_init_state_->composite_ = new CompositeFilter(message_loop_);
619 pipeline_init_state_->composite_->set_host(this); 628 pipeline_init_state_->composite_->set_host(this);
620 629
621 bool raw_media = (base::strncasecmp(url.c_str(), kRawMediaScheme, 630 bool raw_media = (base::strncasecmp(url.c_str(), kRawMediaScheme,
622 strlen(kRawMediaScheme)) == 0); 631 strlen(kRawMediaScheme)) == 0);
623 if (raw_media) { 632 if (raw_media) {
624 set_state(kInitVideoDecoder); 633 SetState(kInitVideoDecoder);
625 InitializeVideoDecoder(NULL); 634 InitializeVideoDecoder(NULL);
626 } else { 635 } else {
627 set_state(kInitDemuxer); 636 SetState(kInitDemuxer);
628 InitializeDemuxer(); 637 InitializeDemuxer();
629 } 638 }
630 } 639 }
631 640
632 // Main initialization method called on the pipeline thread. This code attempts 641 // Main initialization method called on the pipeline thread. This code attempts
633 // to use the specified filter factory to build a pipeline. 642 // to use the specified filter factory to build a pipeline.
634 // Initialization step performed in this method depends on current state of this 643 // Initialization step performed in this method depends on current state of this
635 // object, indicated by |state_|. After each step of initialization, this 644 // object, indicated by |state_|. After each step of initialization, this
636 // object transits to the next stage. It starts by creating a Demuxer, and then 645 // object transits to the next stage. It starts by creating a Demuxer, and then
637 // connects the Demuxer's audio stream to an AudioDecoder which is then 646 // connects the Demuxer's audio stream to an AudioDecoder which is then
(...skipping 17 matching lines...) Expand all
655 664
656 DCHECK(state_ == kInitDemuxer || 665 DCHECK(state_ == kInitDemuxer ||
657 state_ == kInitAudioDecoder || 666 state_ == kInitAudioDecoder ||
658 state_ == kInitAudioRenderer || 667 state_ == kInitAudioRenderer ||
659 state_ == kInitVideoDecoder || 668 state_ == kInitVideoDecoder ||
660 state_ == kInitVideoRenderer); 669 state_ == kInitVideoRenderer);
661 670
662 671
663 // Demuxer created, create audio decoder. 672 // Demuxer created, create audio decoder.
664 if (state_ == kInitDemuxer) { 673 if (state_ == kInitDemuxer) {
665 set_state(kInitAudioDecoder); 674 SetState(kInitAudioDecoder);
666 // If this method returns false, then there's no audio stream. 675 // If this method returns false, then there's no audio stream.
667 if (InitializeAudioDecoder(demuxer_)) 676 if (InitializeAudioDecoder(demuxer_))
668 return; 677 return;
669 } 678 }
670 679
671 // Assuming audio decoder was created, create audio renderer. 680 // Assuming audio decoder was created, create audio renderer.
672 if (state_ == kInitAudioDecoder) { 681 if (state_ == kInitAudioDecoder) {
673 set_state(kInitAudioRenderer); 682 SetState(kInitAudioRenderer);
683
674 // Returns false if there's no audio stream. 684 // Returns false if there's no audio stream.
675 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder_)) { 685 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder_)) {
676 base::AutoLock auto_lock(lock_); 686 base::AutoLock auto_lock(lock_);
677 has_audio_ = true; 687 has_audio_ = true;
678 return; 688 return;
679 } 689 }
680 } 690 }
681 691
682 // Assuming audio renderer was created, create video decoder. 692 // Assuming audio renderer was created, create video decoder.
683 if (state_ == kInitAudioRenderer) { 693 if (state_ == kInitAudioRenderer) {
684 // Then perform the stage of initialization, i.e. initialize video decoder. 694 // Then perform the stage of initialization, i.e. initialize video decoder.
685 set_state(kInitVideoDecoder); 695 SetState(kInitVideoDecoder);
686 if (InitializeVideoDecoder(demuxer_)) 696 if (InitializeVideoDecoder(demuxer_))
687 return; 697 return;
688 } 698 }
689 699
690 // Assuming video decoder was created, create video renderer. 700 // Assuming video decoder was created, create video renderer.
691 if (state_ == kInitVideoDecoder) { 701 if (state_ == kInitVideoDecoder) {
692 set_state(kInitVideoRenderer); 702 SetState(kInitVideoRenderer);
693 if (InitializeVideoRenderer(pipeline_init_state_->video_decoder_)) { 703 if (InitializeVideoRenderer(pipeline_init_state_->video_decoder_)) {
694 base::AutoLock auto_lock(lock_); 704 base::AutoLock auto_lock(lock_);
695 has_video_ = true; 705 has_video_ = true;
696 return; 706 return;
697 } 707 }
698 } 708 }
699 709
700 if (state_ == kInitVideoRenderer) { 710 if (state_ == kInitVideoRenderer) {
701 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) { 711 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) {
702 SetError(PIPELINE_ERROR_COULD_NOT_RENDER); 712 SetError(PIPELINE_ERROR_COULD_NOT_RENDER);
(...skipping 15 matching lines...) Expand all
718 } 728 }
719 729
720 // Initialization was successful, we are now considered paused, so it's safe 730 // Initialization was successful, we are now considered paused, so it's safe
721 // to set the initial playback rate and volume. 731 // to set the initial playback rate and volume.
722 PreloadChangedTask(GetPreload()); 732 PreloadChangedTask(GetPreload());
723 PlaybackRateChangedTask(GetPlaybackRate()); 733 PlaybackRateChangedTask(GetPlaybackRate());
724 VolumeChangedTask(GetVolume()); 734 VolumeChangedTask(GetVolume());
725 735
726 // Fire the seek request to get the filters to preroll. 736 // Fire the seek request to get the filters to preroll.
727 seek_pending_ = true; 737 seek_pending_ = true;
728 set_state(kSeeking); 738 SetState(kSeeking);
729 if (demuxer_) 739 if (demuxer_)
730 seek_timestamp_ = demuxer_->GetStartTime(); 740 seek_timestamp_ = demuxer_->GetStartTime();
731 else 741 else
732 seek_timestamp_ = base::TimeDelta(); 742 seek_timestamp_ = base::TimeDelta();
733 743
734 pipeline_filter_->Seek( 744 pipeline_filter_->Seek(
735 seek_timestamp_, 745 seek_timestamp_,
736 base::Bind(&PipelineImpl::OnFilterStateTransitionWithStatus, this)); 746 base::Bind(&PipelineImpl::OnFilterStateTransitionWithStatus, this));
737 } 747 }
738 } 748 }
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 DCHECK(!seek_pending_); 867 DCHECK(!seek_pending_);
858 seek_pending_ = true; 868 seek_pending_ = true;
859 869
860 // We'll need to pause every filter before seeking. The state transition 870 // We'll need to pause every filter before seeking. The state transition
861 // is as follows: 871 // is as follows:
862 // kStarted/kEnded 872 // kStarted/kEnded
863 // kPausing (for each filter) 873 // kPausing (for each filter)
864 // kSeeking (for each filter) 874 // kSeeking (for each filter)
865 // kStarting (for each filter) 875 // kStarting (for each filter)
866 // kStarted 876 // kStarted
867 set_state(kPausing); 877 SetState(kPausing);
868 seek_timestamp_ = time; 878 seek_timestamp_ = time;
869 seek_callback_.reset(seek_callback); 879 seek_callback_.reset(seek_callback);
870 880
871 // Kick off seeking! 881 // Kick off seeking!
872 { 882 {
873 base::AutoLock auto_lock(lock_); 883 base::AutoLock auto_lock(lock_);
874 // If we are waiting for a clock update, the clock hasn't been played yet. 884 // If we are waiting for a clock update, the clock hasn't been played yet.
875 if (!waiting_for_clock_update_) 885 if (!waiting_for_clock_update_)
876 clock_->Pause(); 886 clock_->Pause();
877 } 887 }
(...skipping 23 matching lines...) Expand all
901 waiting_for_clock_update_ = false; 911 waiting_for_clock_update_ = false;
902 clock_->Play(); 912 clock_->Play();
903 } 913 }
904 } 914 }
905 915
906 if (video_renderer_ && !video_renderer_->HasEnded()) { 916 if (video_renderer_ && !video_renderer_->HasEnded()) {
907 return; 917 return;
908 } 918 }
909 919
910 // Transition to ended, executing the callback if present. 920 // Transition to ended, executing the callback if present.
911 set_state(kEnded); 921 SetState(kEnded);
912 if (ended_callback_.get()) { 922 if (ended_callback_.get()) {
913 ended_callback_->Run(status_); 923 ended_callback_->Run(status_);
914 } 924 }
915 } 925 }
916 926
917 void PipelineImpl::NotifyNetworkEventTask() { 927 void PipelineImpl::NotifyNetworkEventTask() {
918 DCHECK_EQ(MessageLoop::current(), message_loop_); 928 DCHECK_EQ(MessageLoop::current(), message_loop_);
919 if (network_callback_.get()) { 929 if (network_callback_.get()) {
920 network_callback_->Run(status_); 930 network_callback_->Run(status_);
921 } 931 }
(...skipping 29 matching lines...) Expand all
951 } 961 }
952 962
953 if (!TransientState(state_)) { 963 if (!TransientState(state_)) {
954 NOTREACHED() << "Invalid current state: " << state_; 964 NOTREACHED() << "Invalid current state: " << state_;
955 SetError(PIPELINE_ERROR_ABORT); 965 SetError(PIPELINE_ERROR_ABORT);
956 return; 966 return;
957 } 967 }
958 968
959 // Decrement the number of remaining transitions, making sure to transition 969 // Decrement the number of remaining transitions, making sure to transition
960 // to the next state if needed. 970 // to the next state if needed.
961 set_state(FindNextState(state_)); 971 SetState(FindNextState(state_));
962 if (state_ == kSeeking) { 972 if (state_ == kSeeking) {
963 base::AutoLock auto_lock(lock_); 973 base::AutoLock auto_lock(lock_);
964 clock_->SetTime(seek_timestamp_); 974 clock_->SetTime(seek_timestamp_);
965 } 975 }
966 976
967 // Carry out the action for the current state. 977 // Carry out the action for the current state.
968 if (TransientState(state_)) { 978 if (TransientState(state_)) {
969 if (state_ == kPausing) { 979 if (state_ == kPausing) {
970 pipeline_filter_->Pause( 980 pipeline_filter_->Pause(
971 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); 981 NewCallback(this, &PipelineImpl::OnFilterStateTransition));
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1011 } 1021 }
1012 } else { 1022 } else {
1013 NOTREACHED() << "Unexpected state: " << state_; 1023 NOTREACHED() << "Unexpected state: " << state_;
1014 } 1024 }
1015 } 1025 }
1016 1026
1017 void PipelineImpl::TeardownStateTransitionTask() { 1027 void PipelineImpl::TeardownStateTransitionTask() {
1018 DCHECK(IsPipelineTearingDown()); 1028 DCHECK(IsPipelineTearingDown());
1019 switch (state_) { 1029 switch (state_) {
1020 case kStopping: 1030 case kStopping:
1021 set_state(error_caused_teardown_ ? kError : kStopped); 1031 SetState(error_caused_teardown_ ? kError : kStopped);
1022 FinishDestroyingFiltersTask(); 1032 FinishDestroyingFiltersTask();
1023 break; 1033 break;
1024 case kPausing: 1034 case kPausing:
1025 set_state(kFlushing); 1035 SetState(kFlushing);
1026 pipeline_filter_->Flush( 1036 pipeline_filter_->Flush(
1027 NewCallback(this, &PipelineImpl::OnTeardownStateTransition)); 1037 NewCallback(this, &PipelineImpl::OnTeardownStateTransition));
1028 break; 1038 break;
1029 case kFlushing: 1039 case kFlushing:
1030 set_state(kStopping); 1040 SetState(kStopping);
1031 pipeline_filter_->Stop( 1041 pipeline_filter_->Stop(
1032 NewCallback(this, &PipelineImpl::OnTeardownStateTransition)); 1042 NewCallback(this, &PipelineImpl::OnTeardownStateTransition));
1033 break; 1043 break;
1034 1044
1035 case kCreated: 1045 case kCreated:
1036 case kError: 1046 case kError:
1037 case kInitDemuxer: 1047 case kInitDemuxer:
1038 case kInitAudioDecoder: 1048 case kInitAudioDecoder:
1039 case kInitAudioRenderer: 1049 case kInitAudioRenderer:
1040 case kInitVideoDecoder: 1050 case kInitVideoDecoder:
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
1247 DCHECK(!tearing_down_ || // Teardown on Stop(). 1257 DCHECK(!tearing_down_ || // Teardown on Stop().
1248 (tearing_down_ && error_caused_teardown_) || // Teardown on error. 1258 (tearing_down_ && error_caused_teardown_) || // Teardown on error.
1249 (tearing_down_ && stop_pending_)); // Stop during teardown by error. 1259 (tearing_down_ && stop_pending_)); // Stop during teardown by error.
1250 1260
1251 // Mark that we already start tearing down operation. 1261 // Mark that we already start tearing down operation.
1252 tearing_down_ = true; 1262 tearing_down_ = true;
1253 1263
1254 switch (state_) { 1264 switch (state_) {
1255 case kCreated: 1265 case kCreated:
1256 case kError: 1266 case kError:
1257 set_state(kStopped); 1267 SetState(kStopped);
1258 // Need to put this in the message loop to make sure that it comes 1268 // Need to put this in the message loop to make sure that it comes
1259 // after any pending callback tasks that are already queued. 1269 // after any pending callback tasks that are already queued.
1260 message_loop_->PostTask(FROM_HERE, 1270 message_loop_->PostTask(FROM_HERE,
1261 NewRunnableMethod(this, &PipelineImpl::FinishDestroyingFiltersTask)); 1271 NewRunnableMethod(this, &PipelineImpl::FinishDestroyingFiltersTask));
1262 break; 1272 break;
1263 1273
1264 case kInitDemuxer: 1274 case kInitDemuxer:
1265 case kInitAudioDecoder: 1275 case kInitAudioDecoder:
1266 case kInitAudioRenderer: 1276 case kInitAudioRenderer:
1267 case kInitVideoDecoder: 1277 case kInitVideoDecoder:
1268 case kInitVideoRenderer: 1278 case kInitVideoRenderer:
1269 // Make it look like initialization was successful. 1279 // Make it look like initialization was successful.
1270 pipeline_filter_ = pipeline_init_state_->composite_; 1280 pipeline_filter_ = pipeline_init_state_->composite_;
1271 pipeline_init_state_.reset(); 1281 pipeline_init_state_.reset();
1272 filter_collection_.reset(); 1282 filter_collection_.reset();
1273 1283
1274 set_state(kStopping); 1284 SetState(kStopping);
1275 pipeline_filter_->Stop( 1285 pipeline_filter_->Stop(
1276 NewCallback(this, &PipelineImpl::OnTeardownStateTransition)); 1286 NewCallback(this, &PipelineImpl::OnTeardownStateTransition));
1277 1287
1278 FinishInitialization(); 1288 FinishInitialization();
1279 break; 1289 break;
1280 1290
1281 case kPausing: 1291 case kPausing:
1282 case kSeeking: 1292 case kSeeking:
1283 case kFlushing: 1293 case kFlushing:
1284 case kStarting: 1294 case kStarting:
1285 set_state(kStopping); 1295 SetState(kStopping);
1286 pipeline_filter_->Stop( 1296 pipeline_filter_->Stop(
1287 NewCallback(this, &PipelineImpl::OnTeardownStateTransition)); 1297 NewCallback(this, &PipelineImpl::OnTeardownStateTransition));
1288 1298
1289 if (seek_pending_) { 1299 if (seek_pending_) {
1290 seek_pending_ = false; 1300 seek_pending_ = false;
1291 FinishInitialization(); 1301 FinishInitialization();
1292 } 1302 }
1293 1303
1294 break; 1304 break;
1295 1305
1296 case kStarted: 1306 case kStarted:
1297 case kEnded: 1307 case kEnded:
1298 set_state(kPausing); 1308 SetState(kPausing);
1299 pipeline_filter_->Pause( 1309 pipeline_filter_->Pause(
1300 NewCallback(this, &PipelineImpl::OnTeardownStateTransition)); 1310 NewCallback(this, &PipelineImpl::OnTeardownStateTransition));
1301 break; 1311 break;
1302 1312
1303 case kStopping: 1313 case kStopping:
1304 case kStopped: 1314 case kStopped:
1305 NOTREACHED() << "Unexpected state for teardown: " << state_; 1315 NOTREACHED() << "Unexpected state for teardown: " << state_;
1306 break; 1316 break;
1307 // default: intentionally left out to force new states to cause compiler 1317 // default: intentionally left out to force new states to cause compiler
1308 // errors. 1318 // errors.
1309 }; 1319 };
1310 } 1320 }
1311 1321
1312 } // namespace media 1322 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698