Index: media/filters/chunk_demuxer.cc |
diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc |
index 224abc430b697570bc8d05545417da950c9d1b71..c03de799e4e310994b4186ca801e9d65cd6e8cbd 100644 |
--- a/media/filters/chunk_demuxer.cc |
+++ b/media/filters/chunk_demuxer.cc |
@@ -192,7 +192,7 @@ class SourceState { |
void OnNewMediaSegment(); |
// Called by the |stream_parser_| at the end of a media segment. |
- void OnEndOfMediaSegment(); |
+ bool OnEndOfMediaSegment(); |
// Called by the |stream_parser_| when new buffers have been parsed. |
// It processes the new buffers using |frame_processor_|, which includes |
@@ -240,6 +240,12 @@ class SourceState { |
// Keeps track of whether a media segment is being parsed. |
bool parsing_media_segment_; |
+ // Valid only while |parsing_media_segment_| is true. These flags are to |
+ // enforce adherence to MSE spec's requirement of at least one frame for each |
+ // A/V track in each media segment. |
+ bool media_segment_contained_audio_frame_; |
+ bool media_segment_contained_video_frame_; |
+ |
// The object used to parse appended data. |
scoped_ptr<StreamParser> stream_parser_; |
@@ -277,6 +283,8 @@ SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, |
timestamp_offset_during_append_(NULL), |
new_media_segment_(false), |
parsing_media_segment_(false), |
+ media_segment_contained_audio_frame_(false), |
+ media_segment_contained_video_frame_(false), |
stream_parser_(stream_parser.release()), |
audio_(NULL), |
video_(NULL), |
@@ -825,12 +833,27 @@ void SourceState::OnNewMediaSegment() { |
DVLOG(2) << "OnNewMediaSegment()"; |
parsing_media_segment_ = true; |
new_media_segment_ = true; |
+ media_segment_contained_audio_frame_ = false; |
+ media_segment_contained_video_frame_ = false; |
} |
-void SourceState::OnEndOfMediaSegment() { |
+bool SourceState::OnEndOfMediaSegment() { |
DVLOG(2) << "OnEndOfMediaSegment()"; |
parsing_media_segment_ = false; |
new_media_segment_ = false; |
+ |
+ const bool missing_audio = audio_ && !media_segment_contained_audio_frame_; |
+ const bool missing_video = video_ && !media_segment_contained_video_frame_; |
+ if (missing_audio || missing_video) { |
+ MEDIA_LOG(ERROR, media_log_) |
+ << "Media segment did not contain any " |
+ << (missing_audio && missing_video ? "audio or video" |
+ : missing_audio ? "audio" : "video") |
+ << " coded frames, mismatching initialization segment"; |
+ return false; |
+ } |
+ |
+ return true; |
} |
bool SourceState::OnNewBuffers( |
@@ -841,6 +864,9 @@ bool SourceState::OnNewBuffers( |
DCHECK(timestamp_offset_during_append_); |
DCHECK(parsing_media_segment_); |
+ media_segment_contained_audio_frame_ |= !audio_buffers.empty(); |
+ media_segment_contained_video_frame_ |= !video_buffers.empty(); |
+ |
const TimeDelta timestamp_offset_before_processing = |
*timestamp_offset_during_append_; |