Chromium Code Reviews| 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 | 10 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 DemuxerStream::Type)> CreateDemuxerStreamCB; | 91 DemuxerStream::Type)> CreateDemuxerStreamCB; |
| 92 | 92 |
| 93 typedef ChunkDemuxer::InitSegmentReceivedCB InitSegmentReceivedCB; | 93 typedef ChunkDemuxer::InitSegmentReceivedCB InitSegmentReceivedCB; |
| 94 | 94 |
| 95 typedef base::Callback<void( | 95 typedef base::Callback<void( |
| 96 ChunkDemuxerStream*, const TextTrackConfig&)> NewTextTrackCB; | 96 ChunkDemuxerStream*, const TextTrackConfig&)> NewTextTrackCB; |
| 97 | 97 |
| 98 SourceState( | 98 SourceState( |
| 99 scoped_ptr<StreamParser> stream_parser, | 99 scoped_ptr<StreamParser> stream_parser, |
| 100 scoped_ptr<FrameProcessor> frame_processor, const LogCB& log_cb, | 100 scoped_ptr<FrameProcessor> frame_processor, const LogCB& log_cb, |
| 101 const CreateDemuxerStreamCB& create_demuxer_stream_cb); | 101 const CreateDemuxerStreamCB& create_demuxer_stream_cb, |
| 102 const scoped_refptr<MediaLog>& media_log); | |
| 102 | 103 |
| 103 ~SourceState(); | 104 ~SourceState(); |
| 104 | 105 |
| 105 void Init(const StreamParser::InitCB& init_cb, | 106 void Init(const StreamParser::InitCB& init_cb, |
| 106 bool allow_audio, | 107 bool allow_audio, |
| 107 bool allow_video, | 108 bool allow_video, |
| 108 const StreamParser::NeedKeyCB& need_key_cb, | 109 const StreamParser::NeedKeyCB& need_key_cb, |
| 109 const NewTextTrackCB& new_text_track_cb); | 110 const NewTextTrackCB& new_text_track_cb); |
| 110 | 111 |
| 111 // Appends new data to the StreamParser. | 112 // Appends new data to the StreamParser. |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 228 scoped_ptr<StreamParser> stream_parser_; | 229 scoped_ptr<StreamParser> stream_parser_; |
| 229 | 230 |
| 230 ChunkDemuxerStream* audio_; // Not owned by |this|. | 231 ChunkDemuxerStream* audio_; // Not owned by |this|. |
| 231 ChunkDemuxerStream* video_; // Not owned by |this|. | 232 ChunkDemuxerStream* video_; // Not owned by |this|. |
| 232 | 233 |
| 233 typedef std::map<StreamParser::TrackId, ChunkDemuxerStream*> TextStreamMap; | 234 typedef std::map<StreamParser::TrackId, ChunkDemuxerStream*> TextStreamMap; |
| 234 TextStreamMap text_stream_map_; // |this| owns the map's stream pointers. | 235 TextStreamMap text_stream_map_; // |this| owns the map's stream pointers. |
| 235 | 236 |
| 236 scoped_ptr<FrameProcessor> frame_processor_; | 237 scoped_ptr<FrameProcessor> frame_processor_; |
| 237 LogCB log_cb_; | 238 LogCB log_cb_; |
| 239 scoped_refptr<MediaLog> media_log_; | |
| 238 StreamParser::InitCB init_cb_; | 240 StreamParser::InitCB init_cb_; |
| 239 | 241 |
| 240 // During Append(), OnNewConfigs() will trigger the initialization segment | 242 // During Append(), OnNewConfigs() will trigger the initialization segment |
| 241 // received algorithm. This callback is only non-NULL during the lifetime of | 243 // received algorithm. This callback is only non-NULL during the lifetime of |
| 242 // an Append() call. Note, the MSE spec explicitly disallows this algorithm | 244 // an Append() call. Note, the MSE spec explicitly disallows this algorithm |
| 243 // during an Abort(), since Abort() is allowed only to emit coded frames, and | 245 // during an Abort(), since Abort() is allowed only to emit coded frames, and |
| 244 // only if the parser is PARSING_MEDIA_SEGMENT (not an INIT segment). | 246 // only if the parser is PARSING_MEDIA_SEGMENT (not an INIT segment). |
| 245 InitSegmentReceivedCB init_segment_received_cb_; | 247 InitSegmentReceivedCB init_segment_received_cb_; |
| 246 | 248 |
| 247 // Indicates that timestampOffset should be updated automatically during | 249 // Indicates that timestampOffset should be updated automatically during |
| 248 // OnNewBuffers() based on the earliest end timestamp of the buffers provided. | 250 // OnNewBuffers() based on the earliest end timestamp of the buffers provided. |
| 249 // TODO(wolenetz): Refactor this function while integrating April 29, 2014 | 251 // TODO(wolenetz): Refactor this function while integrating April 29, 2014 |
| 250 // changes to MSE spec. See http://crbug.com/371499. | 252 // changes to MSE spec. See http://crbug.com/371499. |
| 251 bool auto_update_timestamp_offset_; | 253 bool auto_update_timestamp_offset_; |
| 252 | 254 |
| 253 DISALLOW_COPY_AND_ASSIGN(SourceState); | 255 DISALLOW_COPY_AND_ASSIGN(SourceState); |
| 254 }; | 256 }; |
| 255 | 257 |
| 256 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, | 258 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, |
| 257 scoped_ptr<FrameProcessor> frame_processor, | 259 scoped_ptr<FrameProcessor> frame_processor, |
| 258 const LogCB& log_cb, | 260 const LogCB& log_cb, |
| 259 const CreateDemuxerStreamCB& create_demuxer_stream_cb) | 261 const CreateDemuxerStreamCB& create_demuxer_stream_cb, |
| 262 const scoped_refptr<MediaLog>& media_log) | |
| 260 : create_demuxer_stream_cb_(create_demuxer_stream_cb), | 263 : create_demuxer_stream_cb_(create_demuxer_stream_cb), |
| 261 timestamp_offset_during_append_(NULL), | 264 timestamp_offset_during_append_(NULL), |
| 262 new_media_segment_(false), | 265 new_media_segment_(false), |
| 263 parsing_media_segment_(false), | 266 parsing_media_segment_(false), |
| 264 stream_parser_(stream_parser.release()), | 267 stream_parser_(stream_parser.release()), |
| 265 audio_(NULL), | 268 audio_(NULL), |
| 266 video_(NULL), | 269 video_(NULL), |
| 267 frame_processor_(frame_processor.release()), | 270 frame_processor_(frame_processor.release()), |
| 268 log_cb_(log_cb), | 271 log_cb_(log_cb), |
| 272 media_log_(media_log), | |
| 269 auto_update_timestamp_offset_(false) { | 273 auto_update_timestamp_offset_(false) { |
| 270 DCHECK(!create_demuxer_stream_cb_.is_null()); | 274 DCHECK(!create_demuxer_stream_cb_.is_null()); |
| 271 DCHECK(frame_processor_); | 275 DCHECK(frame_processor_); |
| 272 } | 276 } |
| 273 | 277 |
| 274 SourceState::~SourceState() { | 278 SourceState::~SourceState() { |
| 275 Shutdown(); | 279 Shutdown(); |
| 276 | 280 |
| 277 STLDeleteValues(&text_stream_map_); | 281 STLDeleteValues(&text_stream_map_); |
| 278 } | 282 } |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 585 << (video_config.IsValidConfig() ? " has" : " does not have") | 589 << (video_config.IsValidConfig() ? " has" : " does not have") |
| 586 << " a video track, but the mimetype" | 590 << " a video track, but the mimetype" |
| 587 << (allow_video ? " specifies" : " does not specify") | 591 << (allow_video ? " specifies" : " does not specify") |
| 588 << " a video codec."; | 592 << " a video codec."; |
| 589 return false; | 593 return false; |
| 590 } | 594 } |
| 591 | 595 |
| 592 bool success = true; | 596 bool success = true; |
| 593 if (audio_config.IsValidConfig()) { | 597 if (audio_config.IsValidConfig()) { |
| 594 if (!audio_) { | 598 if (!audio_) { |
| 599 media_log_->SetBooleanProperty("found_audio_stream", true); | |
| 600 media_log_->SetStringProperty( | |
|
DaleCurtis
2014/11/19 00:03:57
This works today since we don't allow codec switch
watk
2014/11/19 19:18:09
Good point. I did talk to wolenetz@ about this, an
| |
| 601 "audio_codec_name", | |
| 602 AudioCodecName(audio_config.codec(), audio_config.sample_format())); | |
| 595 audio_ = create_demuxer_stream_cb_.Run(DemuxerStream::AUDIO); | 603 audio_ = create_demuxer_stream_cb_.Run(DemuxerStream::AUDIO); |
| 596 | 604 |
| 597 if (!audio_) { | 605 if (!audio_) { |
| 598 DVLOG(1) << "Failed to create an audio stream."; | 606 DVLOG(1) << "Failed to create an audio stream."; |
| 599 return false; | 607 return false; |
| 600 } | 608 } |
| 601 | 609 |
| 602 if (!frame_processor_->AddTrack(FrameProcessor::kAudioTrackId, audio_)) { | 610 if (!frame_processor_->AddTrack(FrameProcessor::kAudioTrackId, audio_)) { |
| 603 DVLOG(1) << "Failed to add audio track to frame processor."; | 611 DVLOG(1) << "Failed to add audio track to frame processor."; |
| 604 return false; | 612 return false; |
| 605 } | 613 } |
| 606 } | 614 } |
| 607 | 615 |
| 608 frame_processor_->OnPossibleAudioConfigUpdate(audio_config); | 616 frame_processor_->OnPossibleAudioConfigUpdate(audio_config); |
| 609 success &= audio_->UpdateAudioConfig(audio_config, log_cb_); | 617 success &= audio_->UpdateAudioConfig(audio_config, log_cb_); |
| 610 } | 618 } |
| 611 | 619 |
| 612 if (video_config.IsValidConfig()) { | 620 if (video_config.IsValidConfig()) { |
| 613 if (!video_) { | 621 if (!video_) { |
| 622 media_log_->SetBooleanProperty("found_video_stream", true); | |
| 623 media_log_->SetStringProperty("video_codec_name", | |
| 624 VideoCodecName(video_config.codec())); | |
| 614 video_ = create_demuxer_stream_cb_.Run(DemuxerStream::VIDEO); | 625 video_ = create_demuxer_stream_cb_.Run(DemuxerStream::VIDEO); |
| 615 | 626 |
| 616 if (!video_) { | 627 if (!video_) { |
| 617 DVLOG(1) << "Failed to create a video stream."; | 628 DVLOG(1) << "Failed to create a video stream."; |
| 618 return false; | 629 return false; |
| 619 } | 630 } |
| 620 | 631 |
| 621 if (!frame_processor_->AddTrack(FrameProcessor::kVideoTrackId, video_)) { | 632 if (!frame_processor_->AddTrack(FrameProcessor::kVideoTrackId, video_)) { |
| 622 DVLOG(1) << "Failed to add video track to frame processor."; | 633 DVLOG(1) << "Failed to add video track to frame processor."; |
| 623 return false; | 634 return false; |
| 624 } | 635 } |
| 625 } | 636 } |
| 626 | |
| 627 success &= video_->UpdateVideoConfig(video_config, log_cb_); | 637 success &= video_->UpdateVideoConfig(video_config, log_cb_); |
| 628 } | 638 } |
| 629 | 639 |
| 630 typedef StreamParser::TextTrackConfigMap::const_iterator TextConfigItr; | 640 typedef StreamParser::TextTrackConfigMap::const_iterator TextConfigItr; |
| 631 if (text_stream_map_.empty()) { | 641 if (text_stream_map_.empty()) { |
| 632 for (TextConfigItr itr = text_configs.begin(); | 642 for (TextConfigItr itr = text_configs.begin(); |
| 633 itr != text_configs.end(); ++itr) { | 643 itr != text_configs.end(); ++itr) { |
| 634 ChunkDemuxerStream* const text_stream = | 644 ChunkDemuxerStream* const text_stream = |
| 635 create_demuxer_stream_cb_.Run(DemuxerStream::TEXT); | 645 create_demuxer_stream_cb_.Run(DemuxerStream::TEXT); |
| 636 if (!frame_processor_->AddTrack(itr->first, text_stream)) { | 646 if (!frame_processor_->AddTrack(itr->first, text_stream)) { |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1058 buffer = StreamParserBuffer::CreateEOSBuffer(); | 1068 buffer = StreamParserBuffer::CreateEOSBuffer(); |
| 1059 break; | 1069 break; |
| 1060 } | 1070 } |
| 1061 | 1071 |
| 1062 base::ResetAndReturn(&read_cb_).Run(status, buffer); | 1072 base::ResetAndReturn(&read_cb_).Run(status, buffer); |
| 1063 } | 1073 } |
| 1064 | 1074 |
| 1065 ChunkDemuxer::ChunkDemuxer(const base::Closure& open_cb, | 1075 ChunkDemuxer::ChunkDemuxer(const base::Closure& open_cb, |
| 1066 const NeedKeyCB& need_key_cb, | 1076 const NeedKeyCB& need_key_cb, |
| 1067 const LogCB& log_cb, | 1077 const LogCB& log_cb, |
| 1078 const scoped_refptr<MediaLog>& media_log, | |
| 1068 bool splice_frames_enabled) | 1079 bool splice_frames_enabled) |
| 1069 : state_(WAITING_FOR_INIT), | 1080 : state_(WAITING_FOR_INIT), |
| 1070 cancel_next_seek_(false), | 1081 cancel_next_seek_(false), |
| 1071 host_(NULL), | 1082 host_(NULL), |
| 1072 open_cb_(open_cb), | 1083 open_cb_(open_cb), |
| 1073 need_key_cb_(need_key_cb), | 1084 need_key_cb_(need_key_cb), |
| 1074 enable_text_(false), | 1085 enable_text_(false), |
| 1075 log_cb_(log_cb), | 1086 log_cb_(log_cb), |
| 1087 media_log_(media_log), | |
| 1076 duration_(kNoTimestamp()), | 1088 duration_(kNoTimestamp()), |
| 1077 user_specified_duration_(-1), | 1089 user_specified_duration_(-1), |
| 1078 liveness_(DemuxerStream::LIVENESS_UNKNOWN), | 1090 liveness_(DemuxerStream::LIVENESS_UNKNOWN), |
| 1079 splice_frames_enabled_(splice_frames_enabled) { | 1091 splice_frames_enabled_(splice_frames_enabled) { |
| 1080 DCHECK(!open_cb_.is_null()); | 1092 DCHECK(!open_cb_.is_null()); |
| 1081 DCHECK(!need_key_cb_.is_null()); | 1093 DCHECK(!need_key_cb_.is_null()); |
| 1082 } | 1094 } |
| 1083 | 1095 |
| 1084 void ChunkDemuxer::Initialize( | 1096 void ChunkDemuxer::Initialize( |
| 1085 DemuxerHost* host, | 1097 DemuxerHost* host, |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1224 source_id_video_ = id; | 1236 source_id_video_ = id; |
| 1225 | 1237 |
| 1226 scoped_ptr<FrameProcessor> frame_processor( | 1238 scoped_ptr<FrameProcessor> frame_processor( |
| 1227 new FrameProcessor(base::Bind(&ChunkDemuxer::IncreaseDurationIfNecessary, | 1239 new FrameProcessor(base::Bind(&ChunkDemuxer::IncreaseDurationIfNecessary, |
| 1228 base::Unretained(this)))); | 1240 base::Unretained(this)))); |
| 1229 | 1241 |
| 1230 scoped_ptr<SourceState> source_state( | 1242 scoped_ptr<SourceState> source_state( |
| 1231 new SourceState(stream_parser.Pass(), | 1243 new SourceState(stream_parser.Pass(), |
| 1232 frame_processor.Pass(), log_cb_, | 1244 frame_processor.Pass(), log_cb_, |
| 1233 base::Bind(&ChunkDemuxer::CreateDemuxerStream, | 1245 base::Bind(&ChunkDemuxer::CreateDemuxerStream, |
| 1234 base::Unretained(this)))); | 1246 base::Unretained(this)), |
| 1247 media_log_)); | |
| 1235 | 1248 |
| 1236 SourceState::NewTextTrackCB new_text_track_cb; | 1249 SourceState::NewTextTrackCB new_text_track_cb; |
| 1237 | 1250 |
| 1238 if (enable_text_) { | 1251 if (enable_text_) { |
| 1239 new_text_track_cb = base::Bind(&ChunkDemuxer::OnNewTextTrack, | 1252 new_text_track_cb = base::Bind(&ChunkDemuxer::OnNewTextTrack, |
| 1240 base::Unretained(this)); | 1253 base::Unretained(this)); |
| 1241 } | 1254 } |
| 1242 | 1255 |
| 1243 source_state->Init( | 1256 source_state->Init( |
| 1244 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)), | 1257 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)), |
| (...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1805 } | 1818 } |
| 1806 | 1819 |
| 1807 void ChunkDemuxer::ShutdownAllStreams() { | 1820 void ChunkDemuxer::ShutdownAllStreams() { |
| 1808 for (SourceStateMap::iterator itr = source_state_map_.begin(); | 1821 for (SourceStateMap::iterator itr = source_state_map_.begin(); |
| 1809 itr != source_state_map_.end(); ++itr) { | 1822 itr != source_state_map_.end(); ++itr) { |
| 1810 itr->second->Shutdown(); | 1823 itr->second->Shutdown(); |
| 1811 } | 1824 } |
| 1812 } | 1825 } |
| 1813 | 1826 |
| 1814 } // namespace media | 1827 } // namespace media |
| OLD | NEW |