Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(354)

Side by Side Diff: media/filters/chunk_demuxer.cc

Issue 1564983003: MSE: Log a warning if muxed AV media segment has no A or has no V block (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698