Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chromecast/media/cma/pipeline/video_pipeline_impl.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "chromecast/media/cma/backend/video_pipeline_device.h" | |
| 9 #include "chromecast/media/cma/base/buffering_defs.h" | |
| 10 #include "chromecast/media/cma/base/cma_logging.h" | |
| 11 #include "chromecast/media/cma/base/coded_frame_provider.h" | |
| 12 #include "chromecast/media/cma/pipeline/av_pipeline_impl.h" | |
| 13 #include "media/base/video_decoder_config.h" | |
| 14 | |
| 15 namespace chromecast { | |
| 16 namespace media { | |
| 17 | |
| 18 namespace { | |
| 19 const size_t kMaxVideoFrameSize = 1024 * 1024; | |
| 20 } | |
| 21 | |
| 22 VideoPipelineImpl::VideoPipelineImpl(VideoPipelineDevice* video_device) | |
| 23 : video_device_(video_device), | |
| 24 weak_factory_(this) { | |
| 25 weak_this_ = weak_factory_.GetWeakPtr(); | |
| 26 av_pipeline_impl_.reset(new AvPipelineImpl( | |
| 27 video_device_, | |
| 28 base::Bind(&VideoPipelineImpl::OnUpdateConfig, base::Unretained(this)))); | |
| 29 } | |
| 30 | |
| 31 VideoPipelineImpl::~VideoPipelineImpl() { | |
| 32 } | |
| 33 | |
| 34 void VideoPipelineImpl::SetCodedFrameProvider( | |
| 35 scoped_ptr<CodedFrameProvider> frame_provider) { | |
| 36 av_pipeline_impl_->SetCodedFrameProvider( | |
| 37 frame_provider.Pass(), kAppVideoBufferSize, kMaxVideoFrameSize); | |
| 38 } | |
| 39 | |
| 40 bool VideoPipelineImpl::StartPlayingFrom( | |
| 41 base::TimeDelta time, | |
| 42 const scoped_refptr<BufferingState>& buffering_state) { | |
| 43 CMALOG(kLogControl) << "VideoPipelineImpl::StartPlayingFrom t0=" | |
| 44 << time.InMilliseconds(); | |
| 45 | |
| 46 // Reset the pipeline statistics. | |
| 47 previous_stats_ = ::media::PipelineStatistics(); | |
| 48 | |
| 49 // Start playing. | |
| 50 if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError) | |
| 51 return false; | |
| 52 DCHECK_EQ(av_pipeline_impl_->GetState(), AvPipelineImpl::kFlushed); | |
| 53 | |
| 54 if (!av_pipeline_impl_->StartPlayingFrom(time, buffering_state)) { | |
| 55 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kError); | |
| 56 return false; | |
| 57 } | |
| 58 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kPlaying); | |
| 59 | |
| 60 return true; | |
| 61 } | |
| 62 | |
| 63 void VideoPipelineImpl::Flush(const ::media::PipelineStatusCB& status_cb) { | |
| 64 CMALOG(kLogControl) << "VideoPipelineImpl::Flush"; | |
| 65 | |
| 66 // Pause the pipeline first. | |
| 67 if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError || | |
| 68 !av_pipeline_impl_->Pause()) { | |
| 69 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kError); | |
| 70 status_cb.Run(::media::PIPELINE_ERROR_ABORT); | |
| 71 return; | |
| 72 } | |
| 73 | |
| 74 // Then flush. | |
| 75 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushing); | |
| 76 av_pipeline_impl_->Flush( | |
| 77 base::Bind(&VideoPipelineImpl::OnFlushDone, base::Unretained(this), | |
| 78 status_cb)); | |
| 79 } | |
| 80 | |
| 81 void VideoPipelineImpl::OnFlushDone( | |
| 82 const ::media::PipelineStatusCB& status_cb) { | |
| 83 CMALOG(kLogControl) << "VideoPipelineImpl::OnFlushDone"; | |
| 84 if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError) { | |
| 85 status_cb.Run(::media::PIPELINE_ERROR_ABORT); | |
| 86 return; | |
| 87 } | |
| 88 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushed); | |
| 89 status_cb.Run(::media::PIPELINE_OK); | |
| 90 } | |
| 91 | |
| 92 void VideoPipelineImpl::Stop() { | |
| 93 CMALOG(kLogControl) << "VideoPipelineImpl::Stop"; | |
| 94 av_pipeline_impl_->Stop(); | |
| 95 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kStopped); | |
| 96 } | |
| 97 | |
| 98 void VideoPipelineImpl::SetCdm(BrowserCdmCast* media_keys) { | |
| 99 av_pipeline_impl_->SetCdm(media_keys); | |
| 100 } | |
| 101 | |
| 102 void VideoPipelineImpl::SetClient(const VideoPipelineClient& client) { | |
| 103 video_client_ = client; | |
| 104 av_pipeline_impl_->SetClient(client.av_pipeline_client); | |
| 105 } | |
| 106 | |
| 107 void VideoPipelineImpl::Initialize( | |
| 108 const ::media::VideoDecoderConfig& video_config, | |
| 109 scoped_ptr<CodedFrameProvider> frame_provider, | |
| 110 const ::media::PipelineStatusCB& status_cb) { | |
| 111 CMALOG(kLogControl) << "VideoPipelineImpl::Initialize " | |
| 112 << video_config.AsHumanReadableString(); | |
| 113 VideoPipelineDevice::VideoClient client; | |
| 114 client.natural_size_changed_cb = | |
| 115 base::Bind(&VideoPipelineImpl::OnNaturalSizeChanged, weak_this_); | |
| 116 video_device_->SetVideoClient(client); | |
| 117 if (frame_provider) | |
| 118 SetCodedFrameProvider(frame_provider.Pass()); | |
| 119 | |
| 120 if (!video_device_->SetConfig(video_config) || | |
| 121 !av_pipeline_impl_->Initialize()) { | |
| 122 status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED); | |
| 123 return; | |
| 124 } | |
| 125 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushed); | |
| 126 status_cb.Run(::media::PIPELINE_OK); | |
| 127 } | |
| 128 | |
| 129 void VideoPipelineImpl::OnUpdateConfig( | |
| 130 const ::media::AudioDecoderConfig& audio_config, | |
| 131 const ::media::VideoDecoderConfig& video_config) { | |
| 132 if (video_config.IsValidConfig()) { | |
| 133 CMALOG(kLogControl) << "VideoPipelineImpl::OnUpdateConfig " | |
| 134 << video_config.AsHumanReadableString(); | |
| 135 | |
| 136 bool success = video_device_->SetConfig(video_config); | |
| 137 if (!success && | |
| 138 !video_client_.av_pipeline_client.playback_error_cb.is_null()) | |
|
damienv1
2014/11/20 17:28:28
nit: multiple line "if" statement => should have c
gunsch
2014/11/20 19:50:27
Done. (not in AudioPipelineImpl, it's a single lin
| |
| 139 video_client_.av_pipeline_client.playback_error_cb.Run( | |
| 140 ::media::PIPELINE_ERROR_DECODE); | |
| 141 } | |
| 142 } | |
| 143 | |
| 144 void VideoPipelineImpl::OnNaturalSizeChanged(const gfx::Size& size) { | |
| 145 if (av_pipeline_impl_->GetState() != AvPipelineImpl::kPlaying) | |
| 146 return; | |
| 147 | |
| 148 if (!video_client_.natural_size_changed_cb.is_null()) | |
| 149 video_client_.natural_size_changed_cb.Run(size); | |
| 150 } | |
| 151 | |
| 152 void VideoPipelineImpl::UpdateStatistics() { | |
| 153 if (video_client_.av_pipeline_client.statistics_cb.is_null()) | |
| 154 return; | |
| 155 | |
| 156 MediaComponentDevice::Statistics device_stats; | |
| 157 if (!video_device_->GetStatistics(&device_stats)) | |
| 158 return; | |
| 159 | |
| 160 ::media::PipelineStatistics current_stats; | |
| 161 current_stats.video_bytes_decoded = device_stats.decoded_bytes; | |
| 162 current_stats.video_frames_decoded = device_stats.decoded_samples; | |
| 163 current_stats.video_frames_dropped = device_stats.dropped_samples; | |
| 164 | |
| 165 ::media::PipelineStatistics delta_stats; | |
| 166 delta_stats.video_bytes_decoded = | |
| 167 current_stats.video_bytes_decoded - previous_stats_.video_bytes_decoded; | |
| 168 delta_stats.video_frames_decoded = | |
| 169 current_stats.video_frames_decoded - previous_stats_.video_frames_decoded; | |
| 170 delta_stats.video_frames_dropped = | |
| 171 current_stats.video_frames_dropped - previous_stats_.video_frames_dropped; | |
| 172 | |
| 173 previous_stats_ = current_stats; | |
| 174 | |
| 175 video_client_.av_pipeline_client.statistics_cb.Run(delta_stats); | |
| 176 } | |
| 177 | |
| 178 } // namespace media | |
| 179 } // namespace chromecast | |
| OLD | NEW |