Commit 491a2c2c authored by Matt Wolenetz's avatar Matt Wolenetz Committed by Commit Bot

MSE: Drop empty AV buffers emitted by Stream Parser

Since FFmpeg decode of 0-byte audio and video buffers is now disallowed,
and FFmpegDemuxer skips enqueuing such packets into its DemuxerStream,
this change does similar for MSE:

Any 0-byte |data| audio or video buffers are dropped during initial
processing in FrameProcessor::ProcessFrames(). No 0-byte |data| text
buffers are dropped, because:
* We don't use FFmpeg to decode in-band MSE text, and
* In-band MSE text buffers' |side_data| may contain meaningful
  information. (This assumption isn't asserted by this change).

Note, this change takes the simpler route of dropping 0-byte AV buffers
before they're buffered by the coded frame processing algorithm. A more
complex alternative to skip them when reading from SourceBufferStream
was rejected in hopes this simpler change is sufficient.

Includes ability in ChunkDemuxerTest to vary |block_size_| instead of
always using |kBlockSize|. While the product change is closer to
FrameProcessor, FrameProcessorTests always encode the coded frame's
timestamp as the coded frame contents to enable precise verification of
processing results, so the test of this change is done via
ChunkDemuxerTest instead.

BUG=823375,663438
TEST=ChunkDemuxerTest.ZeroLengthFramesDropped

Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: Ie6a802ba64a576f0219ca7c400fc7dec3a45fbf6
Reviewed-on: https://chromium-review.googlesource.com/974427
Commit-Queue: Matthew Wolenetz <wolenetz@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#546159}
parent 0ad845d3
...@@ -381,6 +381,13 @@ MATCHER_P3(NegativeDtsFailureWhenByDts, frame_type, pts_us, dts_us, "") { ...@@ -381,6 +381,13 @@ MATCHER_P3(NegativeDtsFailureWhenByDts, frame_type, pts_us, dts_us, "") {
"and filtering against append window"); "and filtering against append window");
} }
MATCHER_P2(DiscardingEmptyFrame, pts_us, dts_us, "") {
return CONTAINS_STRING(arg,
"Discarding empty audio or video coded frame, PTS=" +
base::IntToString(pts_us) +
"us, DTS=" + base::IntToString(dts_us) + "us");
}
} // namespace media } // namespace media
#endif // MEDIA_BASE_TEST_HELPERS_H_ #endif // MEDIA_BASE_TEST_HELPERS_H_
This diff is collapsed.
...@@ -20,6 +20,7 @@ const int kMaxDtsBeyondPtsWarnings = 10; ...@@ -20,6 +20,7 @@ const int kMaxDtsBeyondPtsWarnings = 10;
const int kMaxAudioNonKeyframeWarnings = 10; const int kMaxAudioNonKeyframeWarnings = 10;
const int kMaxNumKeyframeTimeGreaterThanDependantWarnings = 1; const int kMaxNumKeyframeTimeGreaterThanDependantWarnings = 1;
const int kMaxMuxedSequenceModeWarnings = 1; const int kMaxMuxedSequenceModeWarnings = 1;
const int kMaxSkippedEmptyFrameWarnings = 5;
// Helper class to capture per-track details needed by a frame processor. Some // Helper class to capture per-track details needed by a frame processor. Some
// of this information may be duplicated in the short-term in the associated // of this information may be duplicated in the short-term in the associated
...@@ -370,9 +371,21 @@ bool FrameProcessor::ProcessFrames( ...@@ -370,9 +371,21 @@ bool FrameProcessor::ProcessFrames(
// https://rawgit.com/w3c/media-source/d8f901f22/ // https://rawgit.com/w3c/media-source/d8f901f22/
// index.html#sourcebuffer-coded-frame-processing // index.html#sourcebuffer-coded-frame-processing
// 1. For each coded frame in the media segment run the following steps: // 1. For each coded frame in the media segment run the following steps:
for (StreamParser::BufferQueue::const_iterator frames_itr = frames.begin(); for (const auto& frame : frames) {
frames_itr != frames.end(); ++frames_itr) { // Skip any 0-byte audio or video buffers, since they cannot produce any
if (!ProcessFrame(*frames_itr, append_window_start, append_window_end, // valid decode output (and are rejected by FFmpeg A/V decode.) Retain
// 0-byte text buffers because their |side_data| just might be useful, and
// we don't feed them to FFmpeg later.
if (!frame->data_size() && frame->type() != DemuxerStream::TEXT) {
LIMITED_MEDIA_LOG(DEBUG, media_log_, num_skipped_empty_frame_warnings_,
kMaxSkippedEmptyFrameWarnings)
<< "Discarding empty audio or video coded frame, PTS="
<< frame->timestamp().InMicroseconds()
<< "us, DTS=" << frame->GetDecodeTimestamp().InMicroseconds() << "us";
continue;
}
if (!ProcessFrame(frame, append_window_start, append_window_end,
timestamp_offset)) { timestamp_offset)) {
FlushProcessedFrames(); FlushProcessedFrames();
return false; return false;
......
...@@ -190,6 +190,7 @@ class MEDIA_EXPORT FrameProcessor { ...@@ -190,6 +190,7 @@ class MEDIA_EXPORT FrameProcessor {
int num_dts_beyond_pts_warnings_ = 0; int num_dts_beyond_pts_warnings_ = 0;
int num_audio_non_keyframe_warnings_ = 0; int num_audio_non_keyframe_warnings_ = 0;
int num_muxed_sequence_mode_warnings_ = 0; int num_muxed_sequence_mode_warnings_ = 0;
int num_skipped_empty_frame_warnings_ = 0;
DISALLOW_COPY_AND_ASSIGN(FrameProcessor); DISALLOW_COPY_AND_ASSIGN(FrameProcessor);
}; };
......
...@@ -191,7 +191,7 @@ void ClusterBuilder::WriteBlock(uint8_t* buf, ...@@ -191,7 +191,7 @@ void ClusterBuilder::WriteBlock(uint8_t* buf,
DCHECK_GE(flags, 0); DCHECK_GE(flags, 0);
DCHECK_LE(flags, 0xff); DCHECK_LE(flags, 0xff);
DCHECK(data); DCHECK(data);
DCHECK_GT(size, 0); DCHECK_GE(size, 0); // For testing, allow 0-byte coded frames.
DCHECK_NE(cluster_timecode_, -1); DCHECK_NE(cluster_timecode_, -1);
int64_t timecode_delta = timecode - cluster_timecode_; int64_t timecode_delta = timecode - cluster_timecode_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment