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 |