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 <limits> | 8 #include <limits> |
9 #include <list> | 9 #include <list> |
10 #include <utility> | 10 #include <utility> |
(...skipping 20 matching lines...) Expand all Loading... |
31 namespace media { | 31 namespace media { |
32 | 32 |
33 ChunkDemuxerStream::ChunkDemuxerStream(Type type, | 33 ChunkDemuxerStream::ChunkDemuxerStream(Type type, |
34 bool splice_frames_enabled, | 34 bool splice_frames_enabled, |
35 MediaTrack::Id media_track_id) | 35 MediaTrack::Id media_track_id) |
36 : type_(type), | 36 : type_(type), |
37 liveness_(DemuxerStream::LIVENESS_UNKNOWN), | 37 liveness_(DemuxerStream::LIVENESS_UNKNOWN), |
38 media_track_id_(media_track_id), | 38 media_track_id_(media_track_id), |
39 state_(UNINITIALIZED), | 39 state_(UNINITIALIZED), |
40 splice_frames_enabled_(splice_frames_enabled), | 40 splice_frames_enabled_(splice_frames_enabled), |
41 partial_append_window_trimming_enabled_(false) {} | 41 partial_append_window_trimming_enabled_(false), |
| 42 is_enabled_(true) {} |
42 | 43 |
43 void ChunkDemuxerStream::StartReturningData() { | 44 void ChunkDemuxerStream::StartReturningData() { |
44 DVLOG(1) << "ChunkDemuxerStream::StartReturningData()"; | 45 DVLOG(1) << "ChunkDemuxerStream::StartReturningData()"; |
45 base::AutoLock auto_lock(lock_); | 46 base::AutoLock auto_lock(lock_); |
46 DCHECK(read_cb_.is_null()); | 47 DCHECK(read_cb_.is_null()); |
47 ChangeState_Locked(RETURNING_DATA_FOR_READS); | 48 ChangeState_Locked(RETURNING_DATA_FOR_READS); |
48 } | 49 } |
49 | 50 |
50 void ChunkDemuxerStream::AbortReads() { | 51 void ChunkDemuxerStream::AbortReads() { |
51 DVLOG(1) << "ChunkDemuxerStream::AbortReads()"; | 52 DVLOG(1) << "ChunkDemuxerStream::AbortReads()"; |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 stream_->UnmarkEndOfStream(); | 242 stream_->UnmarkEndOfStream(); |
242 } | 243 } |
243 | 244 |
244 // DemuxerStream methods. | 245 // DemuxerStream methods. |
245 void ChunkDemuxerStream::Read(const ReadCB& read_cb) { | 246 void ChunkDemuxerStream::Read(const ReadCB& read_cb) { |
246 base::AutoLock auto_lock(lock_); | 247 base::AutoLock auto_lock(lock_); |
247 DCHECK_NE(state_, UNINITIALIZED); | 248 DCHECK_NE(state_, UNINITIALIZED); |
248 DCHECK(read_cb_.is_null()); | 249 DCHECK(read_cb_.is_null()); |
249 | 250 |
250 read_cb_ = BindToCurrentLoop(read_cb); | 251 read_cb_ = BindToCurrentLoop(read_cb); |
| 252 |
| 253 if (!is_enabled_) { |
| 254 DVLOG(1) << "Read from disabled stream, returning EOS"; |
| 255 base::ResetAndReturn(&read_cb_).Run(kOk, |
| 256 StreamParserBuffer::CreateEOSBuffer()); |
| 257 return; |
| 258 } |
| 259 |
251 CompletePendingReadIfPossible_Locked(); | 260 CompletePendingReadIfPossible_Locked(); |
252 } | 261 } |
253 | 262 |
254 DemuxerStream::Type ChunkDemuxerStream::type() const { return type_; } | 263 DemuxerStream::Type ChunkDemuxerStream::type() const { return type_; } |
255 | 264 |
256 DemuxerStream::Liveness ChunkDemuxerStream::liveness() const { | 265 DemuxerStream::Liveness ChunkDemuxerStream::liveness() const { |
257 base::AutoLock auto_lock(lock_); | 266 base::AutoLock auto_lock(lock_); |
258 return liveness_; | 267 return liveness_; |
259 } | 268 } |
260 | 269 |
261 AudioDecoderConfig ChunkDemuxerStream::audio_decoder_config() { | 270 AudioDecoderConfig ChunkDemuxerStream::audio_decoder_config() { |
262 CHECK_EQ(type_, AUDIO); | 271 CHECK_EQ(type_, AUDIO); |
263 base::AutoLock auto_lock(lock_); | 272 base::AutoLock auto_lock(lock_); |
264 return stream_->GetCurrentAudioDecoderConfig(); | 273 return stream_->GetCurrentAudioDecoderConfig(); |
265 } | 274 } |
266 | 275 |
267 VideoDecoderConfig ChunkDemuxerStream::video_decoder_config() { | 276 VideoDecoderConfig ChunkDemuxerStream::video_decoder_config() { |
268 CHECK_EQ(type_, VIDEO); | 277 CHECK_EQ(type_, VIDEO); |
269 base::AutoLock auto_lock(lock_); | 278 base::AutoLock auto_lock(lock_); |
270 return stream_->GetCurrentVideoDecoderConfig(); | 279 return stream_->GetCurrentVideoDecoderConfig(); |
271 } | 280 } |
272 | 281 |
273 bool ChunkDemuxerStream::SupportsConfigChanges() { return true; } | 282 bool ChunkDemuxerStream::SupportsConfigChanges() { return true; } |
274 | 283 |
275 VideoRotation ChunkDemuxerStream::video_rotation() { | 284 VideoRotation ChunkDemuxerStream::video_rotation() { |
276 return VIDEO_ROTATION_0; | 285 return VIDEO_ROTATION_0; |
277 } | 286 } |
278 | 287 |
| 288 bool ChunkDemuxerStream::enabled() const { |
| 289 base::AutoLock auto_lock(lock_); |
| 290 return is_enabled_; |
| 291 } |
| 292 |
| 293 void ChunkDemuxerStream::set_enabled(bool enabled, base::TimeDelta timestamp) { |
| 294 base::AutoLock auto_lock(lock_); |
| 295 |
| 296 if (enabled == is_enabled_) |
| 297 return; |
| 298 |
| 299 is_enabled_ = enabled; |
| 300 if (enabled) { |
| 301 DCHECK(stream_); |
| 302 stream_->Seek(timestamp); |
| 303 if (!stream_restarted_cb_.is_null()) |
| 304 stream_restarted_cb_.Run(this, timestamp); |
| 305 } else if (!read_cb_.is_null()) { |
| 306 DVLOG(1) << "Read from disabled stream, returning EOS"; |
| 307 base::ResetAndReturn(&read_cb_).Run(kOk, |
| 308 StreamParserBuffer::CreateEOSBuffer()); |
| 309 } |
| 310 } |
| 311 |
| 312 void ChunkDemuxerStream::SetStreamRestartedCB(const StreamRestartedCB& cb) { |
| 313 DCHECK(!cb.is_null()); |
| 314 stream_restarted_cb_ = BindToCurrentLoop(cb); |
| 315 } |
| 316 |
279 TextTrackConfig ChunkDemuxerStream::text_track_config() { | 317 TextTrackConfig ChunkDemuxerStream::text_track_config() { |
280 CHECK_EQ(type_, TEXT); | 318 CHECK_EQ(type_, TEXT); |
281 base::AutoLock auto_lock(lock_); | 319 base::AutoLock auto_lock(lock_); |
282 return stream_->GetCurrentTextTrackConfig(); | 320 return stream_->GetCurrentTextTrackConfig(); |
283 } | 321 } |
284 | 322 |
285 void ChunkDemuxerStream::SetStreamMemoryLimit(size_t memory_limit) { | 323 void ChunkDemuxerStream::SetStreamMemoryLimit(size_t memory_limit) { |
286 stream_->set_memory_limit(memory_limit); | 324 stream_->set_memory_limit(memory_limit); |
287 } | 325 } |
288 | 326 |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 const std::string& id) const { | 639 const std::string& id) const { |
602 base::AutoLock auto_lock(lock_); | 640 base::AutoLock auto_lock(lock_); |
603 DCHECK(!id.empty()); | 641 DCHECK(!id.empty()); |
604 | 642 |
605 MediaSourceStateMap::const_iterator itr = source_state_map_.find(id); | 643 MediaSourceStateMap::const_iterator itr = source_state_map_.find(id); |
606 | 644 |
607 DCHECK(itr != source_state_map_.end()); | 645 DCHECK(itr != source_state_map_.end()); |
608 return itr->second->GetHighestPresentationTimestamp(); | 646 return itr->second->GetHighestPresentationTimestamp(); |
609 } | 647 } |
610 | 648 |
| 649 void ChunkDemuxer::OnEnabledAudioTracksChanged( |
| 650 const std::vector<MediaTrack::Id>& track_ids, |
| 651 base::TimeDelta currTime) { |
| 652 // Note: We intentionally don't lock here, since we are not accessing any |
| 653 // members directly. |
| 654 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO); |
| 655 bool enabled = false; |
| 656 CHECK(audio_stream); |
| 657 DCHECK_LE(track_ids.size(), 1u); |
| 658 if (track_ids.size() > 0) { |
| 659 #if DCHECK_IS_ON() |
| 660 base::AutoLock auto_lock(lock_); |
| 661 DCHECK(track_id_to_demux_stream_map_[track_ids[0]] == audio_stream); |
| 662 #endif |
| 663 enabled = true; |
| 664 } |
| 665 DVLOG(1) << __FUNCTION__ << ": " << (enabled ? "enabling" : "disabling") |
| 666 << " audio stream"; |
| 667 audio_stream->set_enabled(enabled, currTime); |
| 668 } |
| 669 |
| 670 void ChunkDemuxer::OnSelectedVideoTrackChanged( |
| 671 const std::vector<MediaTrack::Id>& track_ids, |
| 672 base::TimeDelta currTime) { |
| 673 // Note: We intentionally don't lock here, since we are not accessing any |
| 674 // members directly. |
| 675 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO); |
| 676 bool enabled = false; |
| 677 CHECK(video_stream); |
| 678 DCHECK_LE(track_ids.size(), 1u); |
| 679 if (track_ids.size() > 0) { |
| 680 #if DCHECK_IS_ON() |
| 681 base::AutoLock auto_lock(lock_); |
| 682 DCHECK(track_id_to_demux_stream_map_[track_ids[0]] == video_stream); |
| 683 #endif |
| 684 enabled = true; |
| 685 } |
| 686 DVLOG(1) << __FUNCTION__ << ": " << (enabled ? "enabling" : "disabling") |
| 687 << " video stream"; |
| 688 video_stream->set_enabled(enabled, currTime); |
| 689 } |
| 690 |
611 bool ChunkDemuxer::EvictCodedFrames(const std::string& id, | 691 bool ChunkDemuxer::EvictCodedFrames(const std::string& id, |
612 base::TimeDelta currentMediaTime, | 692 base::TimeDelta currentMediaTime, |
613 size_t newDataSize) { | 693 size_t newDataSize) { |
614 DVLOG(1) << __FUNCTION__ << "(" << id << ")" | 694 DVLOG(1) << __FUNCTION__ << "(" << id << ")" |
615 << " media_time=" << currentMediaTime.InSecondsF() | 695 << " media_time=" << currentMediaTime.InSecondsF() |
616 << " newDataSize=" << newDataSize; | 696 << " newDataSize=" << newDataSize; |
617 base::AutoLock auto_lock(lock_); | 697 base::AutoLock auto_lock(lock_); |
618 | 698 |
619 // Note: The direct conversion from PTS to DTS is safe here, since we don't | 699 // Note: The direct conversion from PTS to DTS is safe here, since we don't |
620 // need to know currentTime precisely for GC. GC only needs to know which GOP | 700 // need to know currentTime precisely for GC. GC only needs to know which GOP |
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1040 lock_.AssertAcquired(); | 1120 lock_.AssertAcquired(); |
1041 | 1121 |
1042 MediaTrack::Id media_track_id = GenerateMediaTrackId(); | 1122 MediaTrack::Id media_track_id = GenerateMediaTrackId(); |
1043 | 1123 |
1044 switch (type) { | 1124 switch (type) { |
1045 case DemuxerStream::AUDIO: | 1125 case DemuxerStream::AUDIO: |
1046 if (audio_) | 1126 if (audio_) |
1047 return NULL; | 1127 return NULL; |
1048 audio_.reset(new ChunkDemuxerStream( | 1128 audio_.reset(new ChunkDemuxerStream( |
1049 DemuxerStream::AUDIO, splice_frames_enabled_, media_track_id)); | 1129 DemuxerStream::AUDIO, splice_frames_enabled_, media_track_id)); |
| 1130 DCHECK(track_id_to_demux_stream_map_.find(media_track_id) == |
| 1131 track_id_to_demux_stream_map_.end()); |
| 1132 track_id_to_demux_stream_map_[media_track_id] = audio_.get(); |
1050 return audio_.get(); | 1133 return audio_.get(); |
1051 break; | 1134 break; |
1052 case DemuxerStream::VIDEO: | 1135 case DemuxerStream::VIDEO: |
1053 if (video_) | 1136 if (video_) |
1054 return NULL; | 1137 return NULL; |
1055 video_.reset(new ChunkDemuxerStream( | 1138 video_.reset(new ChunkDemuxerStream( |
1056 DemuxerStream::VIDEO, splice_frames_enabled_, media_track_id)); | 1139 DemuxerStream::VIDEO, splice_frames_enabled_, media_track_id)); |
| 1140 DCHECK(track_id_to_demux_stream_map_.find(media_track_id) == |
| 1141 track_id_to_demux_stream_map_.end()); |
| 1142 track_id_to_demux_stream_map_[media_track_id] = video_.get(); |
1057 return video_.get(); | 1143 return video_.get(); |
1058 break; | 1144 break; |
1059 case DemuxerStream::TEXT: { | 1145 case DemuxerStream::TEXT: { |
1060 return new ChunkDemuxerStream(DemuxerStream::TEXT, splice_frames_enabled_, | 1146 return new ChunkDemuxerStream(DemuxerStream::TEXT, splice_frames_enabled_, |
1061 media_track_id); | 1147 media_track_id); |
1062 break; | 1148 break; |
1063 } | 1149 } |
1064 case DemuxerStream::UNKNOWN: | 1150 case DemuxerStream::UNKNOWN: |
1065 case DemuxerStream::NUM_TYPES: | 1151 case DemuxerStream::NUM_TYPES: |
1066 NOTREACHED(); | 1152 NOTREACHED(); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1176 } | 1262 } |
1177 | 1263 |
1178 void ChunkDemuxer::ShutdownAllStreams() { | 1264 void ChunkDemuxer::ShutdownAllStreams() { |
1179 for (MediaSourceStateMap::iterator itr = source_state_map_.begin(); | 1265 for (MediaSourceStateMap::iterator itr = source_state_map_.begin(); |
1180 itr != source_state_map_.end(); ++itr) { | 1266 itr != source_state_map_.end(); ++itr) { |
1181 itr->second->Shutdown(); | 1267 itr->second->Shutdown(); |
1182 } | 1268 } |
1183 } | 1269 } |
1184 | 1270 |
1185 } // namespace media | 1271 } // namespace media |
OLD | NEW |