OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/filters/chunk_demuxer.h" | 5 #include "media/filters/chunk_demuxer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <deque> | 8 #include <deque> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
160 // |type| didn't match any of the supported types. | 160 // |type| didn't match any of the supported types. |
161 return false; | 161 return false; |
162 } | 162 } |
163 | 163 |
164 class ChunkDemuxerStream : public DemuxerStream { | 164 class ChunkDemuxerStream : public DemuxerStream { |
165 public: | 165 public: |
166 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; | 166 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; |
167 typedef std::deque<ReadCB> ReadCBQueue; | 167 typedef std::deque<ReadCB> ReadCBQueue; |
168 typedef std::deque<base::Closure> ClosureQueue; | 168 typedef std::deque<base::Closure> ClosureQueue; |
169 | 169 |
170 explicit ChunkDemuxerStream(const AudioDecoderConfig& audio_config); | 170 ChunkDemuxerStream(const AudioDecoderConfig& audio_config, bool is_encrypted); |
171 explicit ChunkDemuxerStream(const VideoDecoderConfig& video_config); | 171 ChunkDemuxerStream(const VideoDecoderConfig& video_config, bool is_encrypted); |
172 | 172 |
173 void StartWaitingForSeek(); | 173 void StartWaitingForSeek(); |
174 void Seek(TimeDelta time); | 174 void Seek(TimeDelta time); |
175 void CancelPendingSeek(); | 175 void CancelPendingSeek(); |
176 bool IsSeekPending() const; | 176 bool IsSeekPending() const; |
177 | 177 |
178 // Add buffers to this stream. Buffers are stored in SourceBufferStreams, | 178 // Add buffers to this stream. Buffers are stored in SourceBufferStreams, |
179 // which handle ordering and overlap resolution. | 179 // which handle ordering and overlap resolution. |
180 // Returns true if buffers were successfully added. | 180 // Returns true if buffers were successfully added. |
181 bool Append(const StreamParser::BufferQueue& buffers); | 181 bool Append(const StreamParser::BufferQueue& buffers); |
182 | 182 |
183 // Signal to the stream that duration has changed to |duration|. | 183 // Signal to the stream that duration has changed to |duration|. |
184 void OnSetDuration(base::TimeDelta duration); | 184 void OnSetDuration(base::TimeDelta duration); |
185 | 185 |
186 // Returns the range of buffered data in this stream, capped at |duration|. | 186 // Returns the range of buffered data in this stream, capped at |duration|. |
187 Ranges<TimeDelta> GetBufferedRanges(base::TimeDelta duration) const; | 187 Ranges<TimeDelta> GetBufferedRanges(base::TimeDelta duration) const; |
188 | 188 |
189 // Signal to the stream that buffers handed in through subsequent calls to | 189 // Signal to the stream that buffers handed in through subsequent calls to |
190 // Append() belong to a media segment that starts at |start_timestamp|. | 190 // Append() belong to a media segment that starts at |start_timestamp|. |
191 void OnNewMediaSegment(TimeDelta start_timestamp); | 191 void OnNewMediaSegment(TimeDelta start_timestamp); |
192 | 192 |
193 // Called when mid-stream config updates occur. | 193 // Called when mid-stream config updates occur. |
194 // Returns true if the new config is accepted. | 194 // Returns true if the new config is accepted. |
195 // Returns false if the new config should trigger an error. | 195 // Returns false if the new config should trigger an error. |
196 bool UpdateAudioConfig(const AudioDecoderConfig& config); | 196 bool UpdateAudioConfig(const AudioDecoderConfig& config, bool is_encrypted); |
197 bool UpdateVideoConfig(const VideoDecoderConfig& config); | 197 bool UpdateVideoConfig(const VideoDecoderConfig& config, bool is_encrypted); |
198 | 198 |
199 void EndOfStream(); | 199 void EndOfStream(); |
200 bool CanEndOfStream() const; | 200 bool CanEndOfStream() const; |
201 void Shutdown(); | 201 void Shutdown(); |
202 | 202 |
203 // DemuxerStream methods. | 203 // DemuxerStream methods. |
204 virtual void Read(const ReadCB& read_cb) OVERRIDE; | 204 virtual void Read(const ReadCB& read_cb) OVERRIDE; |
205 virtual Type type() OVERRIDE; | 205 virtual Type type() OVERRIDE; |
206 virtual void EnableBitstreamConverter() OVERRIDE; | 206 virtual void EnableBitstreamConverter() OVERRIDE; |
207 virtual const AudioDecoderConfig& audio_decoder_config() OVERRIDE; | 207 virtual const AudioDecoderConfig& audio_decoder_config() OVERRIDE; |
208 virtual const VideoDecoderConfig& video_decoder_config() OVERRIDE; | 208 virtual const VideoDecoderConfig& video_decoder_config() OVERRIDE; |
209 virtual bool is_encrypted() OVERRIDE; | |
209 | 210 |
210 protected: | 211 protected: |
211 virtual ~ChunkDemuxerStream(); | 212 virtual ~ChunkDemuxerStream(); |
212 | 213 |
213 private: | 214 private: |
214 enum State { | 215 enum State { |
215 RETURNING_DATA_FOR_READS, | 216 RETURNING_DATA_FOR_READS, |
216 WAITING_FOR_SEEK, | 217 WAITING_FOR_SEEK, |
217 CANCELED, | 218 CANCELED, |
218 SHUTDOWN, | 219 SHUTDOWN, |
219 }; | 220 }; |
220 | 221 |
221 // Assigns |state_| to |state| | 222 // Assigns |state_| to |state| |
222 void ChangeState_Locked(State state); | 223 void ChangeState_Locked(State state); |
223 | 224 |
224 // Adds the callback to |read_cbs_| so it can be called later when we | 225 // Adds the callback to |read_cbs_| so it can be called later when we |
225 // have data. | 226 // have data. |
226 void DeferRead_Locked(const ReadCB& read_cb); | 227 void DeferRead_Locked(const ReadCB& read_cb); |
227 | 228 |
228 // Creates closures that bind ReadCBs in |read_cbs_| to data in | 229 // Creates closures that bind ReadCBs in |read_cbs_| to data in |
229 // |buffers_| and pops the callbacks & buffers from the respecive queues. | 230 // |buffers_| and pops the callbacks & buffers from the respective queues. |
230 void CreateReadDoneClosures_Locked(ClosureQueue* closures); | 231 void CreateReadDoneClosures_Locked(ClosureQueue* closures); |
231 | 232 |
232 // Gets the value to pass to the next Read() callback. Returns true if | 233 // Gets the value to pass to the next Read() callback. Returns true if |
233 // |status| and |buffer| should be passed to the callback. False indicates | 234 // |status| and |buffer| should be passed to the callback. False indicates |
234 // that |status| and |buffer| were not set and more data is needed. | 235 // that |status| and |buffer| were not set and more data is needed. |
235 bool GetNextBuffer_Locked(DemuxerStream::Status* status, | 236 bool GetNextBuffer_Locked(DemuxerStream::Status* status, |
236 scoped_refptr<StreamParserBuffer>* buffer); | 237 scoped_refptr<StreamParserBuffer>* buffer); |
237 | 238 |
238 // Specifies the type of the stream (must be AUDIO or VIDEO for now). | 239 // Specifies the type of the stream (must be AUDIO or VIDEO for now). |
239 Type type_; | 240 Type type_; |
240 | 241 |
241 scoped_ptr<SourceBufferStream> stream_; | 242 scoped_ptr<SourceBufferStream> stream_; |
242 | 243 |
243 mutable base::Lock lock_; | 244 mutable base::Lock lock_; |
244 State state_; | 245 State state_; |
245 ReadCBQueue read_cbs_; | 246 ReadCBQueue read_cbs_; |
246 bool end_of_stream_; | 247 bool end_of_stream_; |
248 bool is_encrypted_; | |
247 | 249 |
248 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); | 250 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); |
249 }; | 251 }; |
250 | 252 |
251 ChunkDemuxerStream::ChunkDemuxerStream(const AudioDecoderConfig& audio_config) | 253 ChunkDemuxerStream::ChunkDemuxerStream(const AudioDecoderConfig& audio_config, |
254 bool is_encrypted) | |
252 : type_(AUDIO), | 255 : type_(AUDIO), |
253 state_(RETURNING_DATA_FOR_READS), | 256 state_(RETURNING_DATA_FOR_READS), |
254 end_of_stream_(false) { | 257 end_of_stream_(false), |
258 is_encrypted_(is_encrypted) { | |
255 stream_.reset(new SourceBufferStream(audio_config)); | 259 stream_.reset(new SourceBufferStream(audio_config)); |
256 } | 260 } |
257 | 261 |
258 ChunkDemuxerStream::ChunkDemuxerStream(const VideoDecoderConfig& video_config) | 262 ChunkDemuxerStream::ChunkDemuxerStream(const VideoDecoderConfig& video_config, |
263 bool is_encrypted) | |
259 : type_(VIDEO), | 264 : type_(VIDEO), |
260 state_(RETURNING_DATA_FOR_READS), | 265 state_(RETURNING_DATA_FOR_READS), |
261 end_of_stream_(false) { | 266 end_of_stream_(false), |
267 is_encrypted_(is_encrypted) { | |
262 stream_.reset(new SourceBufferStream(video_config)); | 268 stream_.reset(new SourceBufferStream(video_config)); |
263 } | 269 } |
264 | 270 |
265 void ChunkDemuxerStream::StartWaitingForSeek() { | 271 void ChunkDemuxerStream::StartWaitingForSeek() { |
266 DVLOG(1) << "StartWaitingForSeek()"; | 272 DVLOG(1) << "StartWaitingForSeek()"; |
267 ReadCBQueue read_cbs; | 273 ReadCBQueue read_cbs; |
268 { | 274 { |
269 base::AutoLock auto_lock(lock_); | 275 base::AutoLock auto_lock(lock_); |
270 ChangeState_Locked(WAITING_FOR_SEEK); | 276 ChangeState_Locked(WAITING_FOR_SEEK); |
271 end_of_stream_ = false; | 277 end_of_stream_ = false; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
351 return range; | 357 return range; |
352 | 358 |
353 // Clamp the end of the stream's buffered ranges to fit within the duration. | 359 // Clamp the end of the stream's buffered ranges to fit within the duration. |
354 // This can be done by intersecting the stream's range with the valid time | 360 // This can be done by intersecting the stream's range with the valid time |
355 // range. | 361 // range. |
356 Ranges<TimeDelta> valid_time_range; | 362 Ranges<TimeDelta> valid_time_range; |
357 valid_time_range.Add(range.start(0), duration); | 363 valid_time_range.Add(range.start(0), duration); |
358 return range.IntersectionWith(valid_time_range); | 364 return range.IntersectionWith(valid_time_range); |
359 } | 365 } |
360 | 366 |
361 bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config) { | 367 bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config, |
368 bool is_encrypted) { | |
362 DCHECK(config.IsValidConfig()); | 369 DCHECK(config.IsValidConfig()); |
363 DCHECK_EQ(type_, AUDIO); | 370 DCHECK_EQ(type_, AUDIO); |
371 is_encrypted_ = is_encrypted; | |
acolwell GONE FROM CHROMIUM
2012/09/15 00:25:24
This is not correct. It will cause the is_encrypte
| |
364 return stream_->UpdateAudioConfig(config); | 372 return stream_->UpdateAudioConfig(config); |
365 } | 373 } |
366 | 374 |
367 bool ChunkDemuxerStream::UpdateVideoConfig(const VideoDecoderConfig& config) { | 375 bool ChunkDemuxerStream::UpdateVideoConfig(const VideoDecoderConfig& config, |
376 bool is_encrypted) { | |
368 DCHECK(config.IsValidConfig()); | 377 DCHECK(config.IsValidConfig()); |
369 DCHECK_EQ(type_, VIDEO); | 378 DCHECK_EQ(type_, VIDEO); |
379 is_encrypted_ = is_encrypted; | |
acolwell GONE FROM CHROMIUM
2012/09/15 00:25:24
ditto
| |
370 return stream_->UpdateVideoConfig(config); | 380 return stream_->UpdateVideoConfig(config); |
371 } | 381 } |
372 | 382 |
373 void ChunkDemuxerStream::EndOfStream() { | 383 void ChunkDemuxerStream::EndOfStream() { |
374 ClosureQueue closures; | 384 ClosureQueue closures; |
375 { | 385 { |
376 base::AutoLock auto_lock(lock_); | 386 base::AutoLock auto_lock(lock_); |
377 DCHECK(!end_of_stream_); | 387 DCHECK(!end_of_stream_); |
378 DCHECK(stream_->IsEndSelected()); | 388 DCHECK(stream_->IsEndSelected()); |
379 end_of_stream_ = true; | 389 end_of_stream_ = true; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
450 } | 460 } |
451 | 461 |
452 void ChunkDemuxerStream::ChangeState_Locked(State state) { | 462 void ChunkDemuxerStream::ChangeState_Locked(State state) { |
453 lock_.AssertAcquired(); | 463 lock_.AssertAcquired(); |
454 DVLOG(1) << "ChunkDemuxerStream::ChangeState_Locked() : " | 464 DVLOG(1) << "ChunkDemuxerStream::ChangeState_Locked() : " |
455 << "type " << type_ | 465 << "type " << type_ |
456 << " - " << state_ << " -> " << state; | 466 << " - " << state_ << " -> " << state; |
457 state_ = state; | 467 state_ = state; |
458 } | 468 } |
459 | 469 |
470 bool ChunkDemuxerStream::is_encrypted() { | |
471 base::AutoLock auto_lock(lock_); | |
472 return is_encrypted_; | |
473 } | |
474 | |
460 ChunkDemuxerStream::~ChunkDemuxerStream() {} | 475 ChunkDemuxerStream::~ChunkDemuxerStream() {} |
461 | 476 |
462 void ChunkDemuxerStream::DeferRead_Locked(const ReadCB& read_cb) { | 477 void ChunkDemuxerStream::DeferRead_Locked(const ReadCB& read_cb) { |
463 lock_.AssertAcquired(); | 478 lock_.AssertAcquired(); |
464 // Wrap & store |read_cb| so that it will | 479 // Wrap & store |read_cb| so that it will |
465 // get called on the current MessageLoop. | 480 // get called on the current MessageLoop. |
466 read_cbs_.push_back(base::Bind(&RunOnMessageLoop, read_cb, | 481 read_cbs_.push_back(base::Bind(&RunOnMessageLoop, read_cb, |
467 base::MessageLoopProxy::current())); | 482 base::MessageLoopProxy::current())); |
468 } | 483 } |
469 | 484 |
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1012 duration_ = kInfiniteDuration(); | 1027 duration_ = kInfiniteDuration(); |
1013 | 1028 |
1014 // The demuxer is now initialized after the |start_timestamp_| was set. | 1029 // The demuxer is now initialized after the |start_timestamp_| was set. |
1015 ChangeState_Locked(INITIALIZED); | 1030 ChangeState_Locked(INITIALIZED); |
1016 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 1031 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
1017 | 1032 |
1018 } | 1033 } |
1019 | 1034 |
1020 bool ChunkDemuxer::OnNewConfigs(bool has_audio, bool has_video, | 1035 bool ChunkDemuxer::OnNewConfigs(bool has_audio, bool has_video, |
1021 const AudioDecoderConfig& audio_config, | 1036 const AudioDecoderConfig& audio_config, |
1022 const VideoDecoderConfig& video_config) { | 1037 const VideoDecoderConfig& video_config, |
1038 bool is_audio_encrypted, | |
1039 bool is_video_encrypted) { | |
1023 DVLOG(1) << "OnNewConfigs(" << has_audio << ", " << has_video | 1040 DVLOG(1) << "OnNewConfigs(" << has_audio << ", " << has_video |
1024 << ", " << audio_config.IsValidConfig() | 1041 << ", " << audio_config.IsValidConfig() |
1025 << ", " << video_config.IsValidConfig() << ")"; | 1042 << ", " << video_config.IsValidConfig() << ")"; |
1026 lock_.AssertAcquired(); | 1043 lock_.AssertAcquired(); |
1027 | 1044 |
1028 if (!audio_config.IsValidConfig() && !video_config.IsValidConfig()) { | 1045 if (!audio_config.IsValidConfig() && !video_config.IsValidConfig()) { |
1029 DVLOG(1) << "OnNewConfigs() : Audio & video config are not valid!"; | 1046 DVLOG(1) << "OnNewConfigs() : Audio & video config are not valid!"; |
1030 return false; | 1047 return false; |
1031 } | 1048 } |
1032 | 1049 |
1033 // Signal an error if we get configuration info for stream types that weren't | 1050 // Signal an error if we get configuration info for stream types that weren't |
1034 // specified in AddId() or more configs after a stream is initialized. | 1051 // specified in AddId() or more configs after a stream is initialized. |
1035 // Only allow a single audio config for now. | 1052 // Only allow a single audio config for now. |
1036 if (has_audio != audio_config.IsValidConfig()) { | 1053 if (has_audio != audio_config.IsValidConfig()) { |
1037 DVLOG(1) << "OnNewConfigs() : Got unexpected audio config."; | 1054 DVLOG(1) << "OnNewConfigs() : Got unexpected audio config."; |
1038 return false; | 1055 return false; |
1039 } | 1056 } |
1040 | 1057 |
1041 // Only allow a single video config for now. | 1058 // Only allow a single video config for now. |
1042 if (has_video != video_config.IsValidConfig()) { | 1059 if (has_video != video_config.IsValidConfig()) { |
1043 DVLOG(1) << "OnNewConfigs() : Got unexpected video config."; | 1060 DVLOG(1) << "OnNewConfigs() : Got unexpected video config."; |
1044 return false; | 1061 return false; |
1045 } | 1062 } |
1046 | 1063 |
1047 bool success = true; | 1064 bool success = true; |
1048 if (audio_config.IsValidConfig()) { | 1065 if (audio_config.IsValidConfig()) { |
1049 if (audio_) { | 1066 if (audio_) { |
1050 success &= audio_->UpdateAudioConfig(audio_config); | 1067 success &= audio_->UpdateAudioConfig(audio_config, is_audio_encrypted); |
1051 } else { | 1068 } else { |
1052 audio_ = new ChunkDemuxerStream(audio_config); | 1069 audio_ = new ChunkDemuxerStream(audio_config, is_audio_encrypted); |
1053 } | 1070 } |
1054 } | 1071 } |
1055 | 1072 |
1056 if (video_config.IsValidConfig()) { | 1073 if (video_config.IsValidConfig()) { |
1057 if (video_) { | 1074 if (video_) { |
1058 success &= video_->UpdateVideoConfig(video_config); | 1075 success &= video_->UpdateVideoConfig(video_config, is_video_encrypted); |
1059 } else { | 1076 } else { |
1060 video_ = new ChunkDemuxerStream(video_config); | 1077 video_ = new ChunkDemuxerStream(video_config, is_video_encrypted); |
1061 } | 1078 } |
1062 } | 1079 } |
1063 | 1080 |
1064 DVLOG(1) << "OnNewConfigs() : success " << success; | 1081 DVLOG(1) << "OnNewConfigs() : success " << success; |
1065 return success; | 1082 return success; |
1066 } | 1083 } |
1067 | 1084 |
1068 bool ChunkDemuxer::OnAudioBuffers(const StreamParser::BufferQueue& buffers) { | 1085 bool ChunkDemuxer::OnAudioBuffers(const StreamParser::BufferQueue& buffers) { |
1069 lock_.AssertAcquired(); | 1086 lock_.AssertAcquired(); |
1070 DCHECK_NE(state_, SHUTDOWN); | 1087 DCHECK_NE(state_, SHUTDOWN); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1187 | 1204 |
1188 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { | 1205 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { |
1189 if (audio_ && !video_) | 1206 if (audio_ && !video_) |
1190 return audio_->GetBufferedRanges(duration_); | 1207 return audio_->GetBufferedRanges(duration_); |
1191 else if (!audio_ && video_) | 1208 else if (!audio_ && video_) |
1192 return video_->GetBufferedRanges(duration_); | 1209 return video_->GetBufferedRanges(duration_); |
1193 return ComputeIntersection(); | 1210 return ComputeIntersection(); |
1194 } | 1211 } |
1195 | 1212 |
1196 } // namespace media | 1213 } // namespace media |
OLD | NEW |