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 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
185 // processing decoder configurations. | 185 // processing decoder configurations. |
186 bool OnNewConfigs(bool allow_audio, bool allow_video, | 186 bool OnNewConfigs(bool allow_audio, bool allow_video, |
187 const AudioDecoderConfig& audio_config, | 187 const AudioDecoderConfig& audio_config, |
188 const VideoDecoderConfig& video_config, | 188 const VideoDecoderConfig& video_config, |
189 const StreamParser::TextTrackConfigMap& text_configs); | 189 const StreamParser::TextTrackConfigMap& text_configs); |
190 | 190 |
191 // Called by the |stream_parser_| at the beginning of a new media segment. | 191 // Called by the |stream_parser_| at the beginning of a new media segment. |
192 void OnNewMediaSegment(); | 192 void OnNewMediaSegment(); |
193 | 193 |
194 // Called by the |stream_parser_| at the end of a media segment. | 194 // Called by the |stream_parser_| at the end of a media segment. |
195 void OnEndOfMediaSegment(); | 195 bool OnEndOfMediaSegment(); |
196 | 196 |
197 // Called by the |stream_parser_| when new buffers have been parsed. | 197 // Called by the |stream_parser_| when new buffers have been parsed. |
198 // It processes the new buffers using |frame_processor_|, which includes | 198 // It processes the new buffers using |frame_processor_|, which includes |
199 // appending the processed frames to associated demuxer streams for each | 199 // appending the processed frames to associated demuxer streams for each |
200 // frame's track. | 200 // frame's track. |
201 // Returns true on a successful call. Returns false if an error occurred while | 201 // Returns true on a successful call. Returns false if an error occurred while |
202 // processing the buffers. | 202 // processing the buffers. |
203 bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers, | 203 bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers, |
204 const StreamParser::BufferQueue& video_buffers, | 204 const StreamParser::BufferQueue& video_buffers, |
205 const StreamParser::TextBufferQueueMap& text_map); | 205 const StreamParser::TextBufferQueueMap& text_map); |
(...skipping 27 matching lines...) Expand all Loading... | |
233 // appended. The flag is set on actual media segment boundaries and | 233 // appended. The flag is set on actual media segment boundaries and |
234 // when the "append window" filtering causes discontinuities in the | 234 // when the "append window" filtering causes discontinuities in the |
235 // appended data. | 235 // appended data. |
236 // TODO(wolenetz/acolwell): Investigate if we need this, or if coded frame | 236 // TODO(wolenetz/acolwell): Investigate if we need this, or if coded frame |
237 // processing's discontinuity logic is enough. See http://crbug.com/351489. | 237 // processing's discontinuity logic is enough. See http://crbug.com/351489. |
238 bool new_media_segment_; | 238 bool new_media_segment_; |
239 | 239 |
240 // Keeps track of whether a media segment is being parsed. | 240 // Keeps track of whether a media segment is being parsed. |
241 bool parsing_media_segment_; | 241 bool parsing_media_segment_; |
242 | 242 |
243 // Valid only while |parsing_media_segment_| is true. These flags are to | |
244 // enforce adherence to MSE spec's requirement of at least one frame for each | |
245 // A/V track in each media segment. | |
246 bool media_segment_contained_audio_frame_; | |
247 bool media_segment_contained_video_frame_; | |
248 | |
243 // The object used to parse appended data. | 249 // The object used to parse appended data. |
244 scoped_ptr<StreamParser> stream_parser_; | 250 scoped_ptr<StreamParser> stream_parser_; |
245 | 251 |
246 ChunkDemuxerStream* audio_; // Not owned by |this|. | 252 ChunkDemuxerStream* audio_; // Not owned by |this|. |
247 ChunkDemuxerStream* video_; // Not owned by |this|. | 253 ChunkDemuxerStream* video_; // Not owned by |this|. |
248 | 254 |
249 typedef std::map<StreamParser::TrackId, ChunkDemuxerStream*> TextStreamMap; | 255 typedef std::map<StreamParser::TrackId, ChunkDemuxerStream*> TextStreamMap; |
250 TextStreamMap text_stream_map_; // |this| owns the map's stream pointers. | 256 TextStreamMap text_stream_map_; // |this| owns the map's stream pointers. |
251 | 257 |
252 scoped_ptr<FrameProcessor> frame_processor_; | 258 scoped_ptr<FrameProcessor> frame_processor_; |
(...skipping 17 matching lines...) Expand all Loading... | |
270 }; | 276 }; |
271 | 277 |
272 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, | 278 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, |
273 scoped_ptr<FrameProcessor> frame_processor, | 279 scoped_ptr<FrameProcessor> frame_processor, |
274 const CreateDemuxerStreamCB& create_demuxer_stream_cb, | 280 const CreateDemuxerStreamCB& create_demuxer_stream_cb, |
275 const scoped_refptr<MediaLog>& media_log) | 281 const scoped_refptr<MediaLog>& media_log) |
276 : create_demuxer_stream_cb_(create_demuxer_stream_cb), | 282 : create_demuxer_stream_cb_(create_demuxer_stream_cb), |
277 timestamp_offset_during_append_(NULL), | 283 timestamp_offset_during_append_(NULL), |
278 new_media_segment_(false), | 284 new_media_segment_(false), |
279 parsing_media_segment_(false), | 285 parsing_media_segment_(false), |
286 media_segment_contained_audio_frame_(false), | |
287 media_segment_contained_video_frame_(false), | |
280 stream_parser_(stream_parser.release()), | 288 stream_parser_(stream_parser.release()), |
281 audio_(NULL), | 289 audio_(NULL), |
282 video_(NULL), | 290 video_(NULL), |
283 frame_processor_(frame_processor.release()), | 291 frame_processor_(frame_processor.release()), |
284 media_log_(media_log), | 292 media_log_(media_log), |
285 auto_update_timestamp_offset_(false) { | 293 auto_update_timestamp_offset_(false) { |
286 DCHECK(!create_demuxer_stream_cb_.is_null()); | 294 DCHECK(!create_demuxer_stream_cb_.is_null()); |
287 DCHECK(frame_processor_); | 295 DCHECK(frame_processor_); |
288 } | 296 } |
289 | 297 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
350 << __FUNCTION__ << ": stream parsing failed." | 358 << __FUNCTION__ << ": stream parsing failed." |
351 << " Data size=" << length | 359 << " Data size=" << length |
352 << " append_window_start=" << append_window_start.InSecondsF() | 360 << " append_window_start=" << append_window_start.InSecondsF() |
353 << " append_window_end=" << append_window_end.InSecondsF(); | 361 << " append_window_end=" << append_window_end.InSecondsF(); |
354 } | 362 } |
355 timestamp_offset_during_append_ = NULL; | 363 timestamp_offset_during_append_ = NULL; |
356 init_segment_received_cb_.Reset(); | 364 init_segment_received_cb_.Reset(); |
357 return result; | 365 return result; |
358 } | 366 } |
359 | 367 |
360 void SourceState::ResetParserState(TimeDelta append_window_start, | 368 void SourceState::ResetParserState(TimeDelta append_window_start, |
chcunningham
2016/01/07 22:23:56
Should you set media_segment_contained_{video|audi
wolenetz
2016/01/16 01:23:35
Good idea for at least maintainability. Done (in M
| |
361 TimeDelta append_window_end, | 369 TimeDelta append_window_end, |
362 base::TimeDelta* timestamp_offset) { | 370 base::TimeDelta* timestamp_offset) { |
363 DCHECK(timestamp_offset); | 371 DCHECK(timestamp_offset); |
364 DCHECK(!timestamp_offset_during_append_); | 372 DCHECK(!timestamp_offset_during_append_); |
365 timestamp_offset_during_append_ = timestamp_offset; | 373 timestamp_offset_during_append_ = timestamp_offset; |
366 append_window_start_during_append_ = append_window_start; | 374 append_window_start_during_append_ = append_window_start; |
367 append_window_end_during_append_ = append_window_end; | 375 append_window_end_during_append_ = append_window_end; |
368 | 376 |
369 stream_parser_->Flush(); | 377 stream_parser_->Flush(); |
370 timestamp_offset_during_append_ = NULL; | 378 timestamp_offset_during_append_ = NULL; |
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
818 if (success) | 826 if (success) |
819 init_segment_received_cb_.Run(); | 827 init_segment_received_cb_.Run(); |
820 | 828 |
821 return success; | 829 return success; |
822 } | 830 } |
823 | 831 |
824 void SourceState::OnNewMediaSegment() { | 832 void SourceState::OnNewMediaSegment() { |
825 DVLOG(2) << "OnNewMediaSegment()"; | 833 DVLOG(2) << "OnNewMediaSegment()"; |
826 parsing_media_segment_ = true; | 834 parsing_media_segment_ = true; |
827 new_media_segment_ = true; | 835 new_media_segment_ = true; |
836 media_segment_contained_audio_frame_ = false; | |
837 media_segment_contained_video_frame_ = false; | |
828 } | 838 } |
829 | 839 |
830 void SourceState::OnEndOfMediaSegment() { | 840 bool SourceState::OnEndOfMediaSegment() { |
831 DVLOG(2) << "OnEndOfMediaSegment()"; | 841 DVLOG(2) << "OnEndOfMediaSegment()"; |
832 parsing_media_segment_ = false; | 842 parsing_media_segment_ = false; |
833 new_media_segment_ = false; | 843 new_media_segment_ = false; |
844 | |
845 const bool missing_audio = audio_ && !media_segment_contained_audio_frame_; | |
846 const bool missing_video = video_ && !media_segment_contained_video_frame_; | |
847 if (missing_audio || missing_video) { | |
848 MEDIA_LOG(ERROR, media_log_) | |
849 << "Media segment did not contain any " | |
850 << (missing_audio && missing_video ? "audio or video" | |
851 : missing_audio ? "audio" : "video") | |
852 << " coded frames, mismatching initialization segment"; | |
853 return false; | |
854 } | |
855 | |
856 return true; | |
834 } | 857 } |
835 | 858 |
836 bool SourceState::OnNewBuffers( | 859 bool SourceState::OnNewBuffers( |
837 const StreamParser::BufferQueue& audio_buffers, | 860 const StreamParser::BufferQueue& audio_buffers, |
838 const StreamParser::BufferQueue& video_buffers, | 861 const StreamParser::BufferQueue& video_buffers, |
839 const StreamParser::TextBufferQueueMap& text_map) { | 862 const StreamParser::TextBufferQueueMap& text_map) { |
840 DVLOG(2) << "OnNewBuffers()"; | 863 DVLOG(2) << "OnNewBuffers()"; |
841 DCHECK(timestamp_offset_during_append_); | 864 DCHECK(timestamp_offset_during_append_); |
842 DCHECK(parsing_media_segment_); | 865 DCHECK(parsing_media_segment_); |
843 | 866 |
867 media_segment_contained_audio_frame_ |= !audio_buffers.empty(); | |
868 media_segment_contained_video_frame_ |= !video_buffers.empty(); | |
869 | |
844 const TimeDelta timestamp_offset_before_processing = | 870 const TimeDelta timestamp_offset_before_processing = |
845 *timestamp_offset_during_append_; | 871 *timestamp_offset_during_append_; |
846 | 872 |
847 // Calculate the new timestamp offset for audio/video tracks if the stream | 873 // Calculate the new timestamp offset for audio/video tracks if the stream |
848 // parser has requested automatic updates. | 874 // parser has requested automatic updates. |
849 TimeDelta new_timestamp_offset = timestamp_offset_before_processing; | 875 TimeDelta new_timestamp_offset = timestamp_offset_before_processing; |
850 if (auto_update_timestamp_offset_) { | 876 if (auto_update_timestamp_offset_) { |
851 const bool have_audio_buffers = !audio_buffers.empty(); | 877 const bool have_audio_buffers = !audio_buffers.empty(); |
852 const bool have_video_buffers = !video_buffers.empty(); | 878 const bool have_video_buffers = !video_buffers.empty(); |
853 if (have_audio_buffers && have_video_buffers) { | 879 if (have_audio_buffers && have_video_buffers) { |
(...skipping 1113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1967 } | 1993 } |
1968 | 1994 |
1969 void ChunkDemuxer::ShutdownAllStreams() { | 1995 void ChunkDemuxer::ShutdownAllStreams() { |
1970 for (SourceStateMap::iterator itr = source_state_map_.begin(); | 1996 for (SourceStateMap::iterator itr = source_state_map_.begin(); |
1971 itr != source_state_map_.end(); ++itr) { | 1997 itr != source_state_map_.end(); ++itr) { |
1972 itr->second->Shutdown(); | 1998 itr->second->Shutdown(); |
1973 } | 1999 } |
1974 } | 2000 } |
1975 | 2001 |
1976 } // namespace media | 2002 } // namespace media |
OLD | NEW |