| Index: media/filters/source_buffer_stream_unittest.cc
|
| diff --git a/media/filters/source_buffer_stream_unittest.cc b/media/filters/source_buffer_stream_unittest.cc
|
| index 3d03ccd16867f6c662ee0fa28e3e2e31fcf045bb..8f518766472019feeb22b8a3db31858c459fc0bf 100644
|
| --- a/media/filters/source_buffer_stream_unittest.cc
|
| +++ b/media/filters/source_buffer_stream_unittest.cc
|
| @@ -15,11 +15,21 @@
|
| #include "base/strings/string_util.h"
|
| #include "media/base/data_buffer.h"
|
| #include "media/base/media_log.h"
|
| +#include "media/base/mock_media_log.h"
|
| #include "media/base/test_helpers.h"
|
| #include "media/base/text_track_config.h"
|
| #include "media/filters/webvtt_util.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| +using ::testing::HasSubstr;
|
| +using ::testing::InSequence;
|
| +using ::testing::StrictMock;
|
| +
|
| +// Helper macros to reduce boilerplate when verifying media log entries.
|
| +#define EXPECT_MEDIA_LOG_STRING(x) \
|
| + EXPECT_CALL(*media_log_, DoAddEventLogString((x)))
|
| +#define CONTAINS_STRING(arg, x) (std::string::npos != (arg).find(x))
|
| +
|
| namespace media {
|
|
|
| typedef StreamParser::BufferQueue BufferQueue;
|
| @@ -30,12 +40,46 @@ static const uint8 kDataA = 0x11;
|
| static const uint8 kDataB = 0x33;
|
| static const int kDataSize = 1;
|
|
|
| +// Matchers for verifying common media log entry strings.
|
| +MATCHER(ContainsMissingKeyframeLog, "") {
|
| + return CONTAINS_STRING(arg,
|
| + "Media segment did not begin with key frame. Support "
|
| + "for such segments will be available in a future "
|
| + "version. Please see https://crbug.com/229412.");
|
| +}
|
| +
|
| +MATCHER(ContainsSameTimestampAt30MillisecondsLog, "") {
|
| + return CONTAINS_STRING(arg,
|
| + "Unexpected combination of buffers with the same "
|
| + "timestamp detected at 0.03");
|
| +}
|
| +
|
| +MATCHER_P(ContainsTrackBufferExhaustionSkipLog, skip_milliseconds, "") {
|
| + return CONTAINS_STRING(arg,
|
| + "Media append that overlapped current playback "
|
| + "position caused time gap in playing VIDEO stream "
|
| + "because the next keyframe is " +
|
| + base::IntToString(skip_milliseconds) +
|
| + "ms beyond last overlapped frame. Media may "
|
| + "appear temporarily frozen.");
|
| +}
|
| +
|
| +MATCHER_P2(ContainsGeneratedSpliceLog,
|
| + duration_microseconds,
|
| + time_microseconds,
|
| + "") {
|
| + return CONTAINS_STRING(arg, "Generated splice of overlap duration " +
|
| + base::IntToString(duration_microseconds) +
|
| + "us into new buffer at " +
|
| + base::IntToString(time_microseconds) + "us.");
|
| +}
|
| +
|
| class SourceBufferStreamTest : public testing::Test {
|
| protected:
|
| - SourceBufferStreamTest() {
|
| + SourceBufferStreamTest() : media_log_(new StrictMock<MockMediaLog>()) {
|
| video_config_ = TestVideoConfig::Normal();
|
| SetStreamInfo(kDefaultFramesPerSecond, kDefaultKeyframesPerSecond);
|
| - stream_.reset(new SourceBufferStream(video_config_, new MediaLog(), true));
|
| + stream_.reset(new SourceBufferStream(video_config_, media_log_, true));
|
| }
|
|
|
| void SetMemoryLimit(size_t buffers_of_data) {
|
| @@ -51,7 +95,7 @@ class SourceBufferStreamTest : public testing::Test {
|
| void SetTextStream() {
|
| video_config_ = TestVideoConfig::Invalid();
|
| TextTrackConfig config(kTextSubtitles, "", "", "");
|
| - stream_.reset(new SourceBufferStream(config, new MediaLog(), true));
|
| + stream_.reset(new SourceBufferStream(config, media_log_, true));
|
| SetStreamInfo(2, 2);
|
| }
|
|
|
| @@ -67,7 +111,7 @@ class SourceBufferStreamTest : public testing::Test {
|
| false,
|
| base::TimeDelta(),
|
| 0);
|
| - stream_.reset(new SourceBufferStream(audio_config_, new MediaLog(), true));
|
| + stream_.reset(new SourceBufferStream(audio_config_, media_log_, true));
|
|
|
| // Equivalent to 2ms per frame.
|
| SetStreamInfo(500, 500);
|
| @@ -375,6 +419,7 @@ class SourceBufferStreamTest : public testing::Test {
|
| scoped_ptr<SourceBufferStream> stream_;
|
| VideoDecoderConfig video_config_;
|
| AudioDecoderConfig audio_config_;
|
| + scoped_refptr<StrictMock<MockMediaLog>> media_log_;
|
|
|
| private:
|
| base::TimeDelta ConvertToFrameDuration(int frames_per_second) {
|
| @@ -726,6 +771,8 @@ TEST_F(SourceBufferStreamTest, Append_AdjacentRanges) {
|
| }
|
|
|
| TEST_F(SourceBufferStreamTest, Append_DoesNotBeginWithKeyframe) {
|
| + EXPECT_MEDIA_LOG_STRING(ContainsMissingKeyframeLog()).Times(2);
|
| +
|
| // Append fails because the range doesn't begin with a keyframe.
|
| NewSegmentAppend_ExpectFailure(3, 2);
|
|
|
| @@ -747,6 +794,8 @@ TEST_F(SourceBufferStreamTest, Append_DoesNotBeginWithKeyframe) {
|
| }
|
|
|
| TEST_F(SourceBufferStreamTest, Append_DoesNotBeginWithKeyframe_Adjacent) {
|
| + EXPECT_MEDIA_LOG_STRING(ContainsMissingKeyframeLog());
|
| +
|
| // Append 8 buffers at positions 0 through 7.
|
| NewSegmentAppend(0, 8);
|
|
|
| @@ -1412,6 +1461,8 @@ TEST_F(SourceBufferStreamTest, End_Overlap_Selected_NoKeyframeAfterNew) {
|
| // after: |A a a a a A| |B b b b b B|
|
| // track: |a|
|
| TEST_F(SourceBufferStreamTest, End_Overlap_Selected_NoKeyframeAfterNew2) {
|
| + EXPECT_MEDIA_LOG_STRING(ContainsTrackBufferExhaustionSkipLog(133));
|
| +
|
| // Append 7 buffers at positions 10 through 16.
|
| NewSegmentAppend(10, 7, &kDataA);
|
|
|
| @@ -1676,6 +1727,8 @@ TEST_F(SourceBufferStreamTest, Overlap_OneByOne_BetweenMediaSegments) {
|
| // new : 0K 30 60 90 120K
|
| // after: 0K 30 60 90 *120K* 130K
|
| TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer) {
|
| + EXPECT_MEDIA_LOG_STRING(ContainsTrackBufferExhaustionSkipLog(50));
|
| +
|
| NewSegmentAppendOneByOne("10K 40 70 100K 125 130D30K");
|
| CheckExpectedRangesByTimestamp("{ [10,160) }");
|
|
|
| @@ -1706,6 +1759,8 @@ TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer) {
|
| // new : 110K 130
|
| // after: 0K 30 60 90 *110K* 130
|
| TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer2) {
|
| + EXPECT_MEDIA_LOG_STRING(ContainsTrackBufferExhaustionSkipLog(40));
|
| +
|
| NewSegmentAppendOneByOne("10K 40 70 100K 125 130D30K");
|
| CheckExpectedRangesByTimestamp("{ [10,160) }");
|
|
|
| @@ -1736,6 +1791,8 @@ TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer2) {
|
| // after: 0K 30 50K 80 110 140 * (waiting for keyframe)
|
| // track: 70
|
| TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer3) {
|
| + EXPECT_MEDIA_LOG_STRING(ContainsTrackBufferExhaustionSkipLog(80));
|
| +
|
| NewSegmentAppendOneByOne("10K 40 70 100K 125 130D30K");
|
| CheckExpectedRangesByTimestamp("{ [10,160) }");
|
|
|
| @@ -1831,6 +1888,8 @@ TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer5) {
|
| // after: 0K 30 60 90 *120K* 130K ... 200K 230 260K 290
|
| // track: 70
|
| TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer6) {
|
| + EXPECT_MEDIA_LOG_STRING(ContainsTrackBufferExhaustionSkipLog(50));
|
| +
|
| NewSegmentAppendOneByOne("10K 40 70 100K 125 130D30K");
|
| NewSegmentAppendOneByOne("200K 230");
|
| CheckExpectedRangesByTimestamp("{ [10,160) [200,260) }");
|
| @@ -2603,6 +2662,8 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_NeedsMoreData) {
|
| }
|
|
|
| TEST_F(SourceBufferStreamTest, GarbageCollection_TrackBuffer) {
|
| + EXPECT_MEDIA_LOG_STRING(ContainsTrackBufferExhaustionSkipLog(99));
|
| +
|
| // Set memory limit to 3 buffers.
|
| SetMemoryLimit(3);
|
|
|
| @@ -3352,12 +3413,16 @@ TEST_F(SourceBufferStreamTest, SameTimestamp_Video_TwoAppends) {
|
| // Verify that a non-keyframe followed by a keyframe with the same timestamp
|
| // is not allowed.
|
| TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Invalid_1) {
|
| + EXPECT_MEDIA_LOG_STRING(ContainsSameTimestampAt30MillisecondsLog());
|
| +
|
| Seek(0);
|
| NewSegmentAppend("0K 30");
|
| AppendBuffers_ExpectFailure("30K 60");
|
| }
|
|
|
| TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Invalid_2) {
|
| + EXPECT_MEDIA_LOG_STRING(ContainsSameTimestampAt30MillisecondsLog());
|
| +
|
| Seek(0);
|
| NewSegmentAppend_ExpectFailure("0K 30 30K 60");
|
| }
|
| @@ -3408,16 +3473,18 @@ TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_3) {
|
| TEST_F(SourceBufferStreamTest, SameTimestamp_Audio) {
|
| AudioDecoderConfig config(kCodecMP3, kSampleFormatF32, CHANNEL_LAYOUT_STEREO,
|
| 44100, NULL, 0, false);
|
| - stream_.reset(new SourceBufferStream(config, new MediaLog(), true));
|
| + stream_.reset(new SourceBufferStream(config, media_log_, true));
|
| Seek(0);
|
| NewSegmentAppend("0K 0K 30K 30 60 60");
|
| CheckExpectedBuffers("0K 0K 30K 30 60 60");
|
| }
|
|
|
| TEST_F(SourceBufferStreamTest, SameTimestamp_Audio_Invalid_1) {
|
| + EXPECT_MEDIA_LOG_STRING(ContainsSameTimestampAt30MillisecondsLog());
|
| +
|
| AudioDecoderConfig config(kCodecMP3, kSampleFormatF32, CHANNEL_LAYOUT_STEREO,
|
| 44100, NULL, 0, false);
|
| - stream_.reset(new SourceBufferStream(config, new MediaLog(), true));
|
| + stream_.reset(new SourceBufferStream(config, media_log_, true));
|
| Seek(0);
|
| NewSegmentAppend_ExpectFailure("0K 30 30K 60");
|
| }
|
| @@ -3894,6 +3961,8 @@ TEST_F(SourceBufferStreamTest,
|
| }
|
|
|
| TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_Basic) {
|
| + EXPECT_MEDIA_LOG_STRING(ContainsGeneratedSpliceLog(3000, 11000));
|
| +
|
| SetAudioStream();
|
| Seek(0);
|
| NewSegmentAppend("0K 2K 4K 6K 8K 10K 12K");
|
| @@ -3903,6 +3972,10 @@ TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_Basic) {
|
| }
|
|
|
| TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoExactSplices) {
|
| + EXPECT_MEDIA_LOG_STRING(
|
| + HasSubstr("Skipping splice frame generation: first new buffer at 10000us "
|
| + "begins at or before existing buffer at 10000us."));
|
| +
|
| SetAudioStream();
|
| Seek(0);
|
| NewSegmentAppend("0K 2K 4K 6K 8K 10K 12K");
|
| @@ -3913,6 +3986,12 @@ TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoExactSplices) {
|
|
|
| // Do not allow splices on top of splices.
|
| TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoDoubleSplice) {
|
| + InSequence s;
|
| + EXPECT_MEDIA_LOG_STRING(ContainsGeneratedSpliceLog(3000, 11000));
|
| + EXPECT_MEDIA_LOG_STRING(
|
| + HasSubstr("Skipping splice frame generation: overlapped buffers at "
|
| + "10000us are in a previously buffered splice."));
|
| +
|
| SetAudioStream();
|
| Seek(0);
|
| NewSegmentAppend("0K 2K 4K 6K 8K 10K 12K");
|
| @@ -3944,6 +4023,8 @@ TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoSplice) {
|
| }
|
|
|
| TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_CorrectMediaSegmentStartTime) {
|
| + EXPECT_MEDIA_LOG_STRING(ContainsGeneratedSpliceLog(5000, 1000));
|
| +
|
| SetAudioStream();
|
| Seek(0);
|
| NewSegmentAppend("0K 2K 4K");
|
| @@ -3957,6 +4038,8 @@ TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_CorrectMediaSegmentStartTime) {
|
| }
|
|
|
| TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_ConfigChange) {
|
| + EXPECT_MEDIA_LOG_STRING(ContainsGeneratedSpliceLog(3000, 5000));
|
| +
|
| SetAudioStream();
|
|
|
| AudioDecoderConfig new_config(kCodecVorbis,
|
| @@ -3980,6 +4063,10 @@ TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_ConfigChange) {
|
|
|
| // Ensure splices are not created if there are not enough frames to crossfade.
|
| TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoTinySplices) {
|
| + EXPECT_MEDIA_LOG_STRING(HasSubstr(
|
| + "Skipping splice frame generation: not enough samples for splicing new "
|
| + "buffer at 1000us. Have 1000us, but need 2000us."));
|
| +
|
| SetAudioStream();
|
| Seek(0);
|
|
|
| @@ -3996,11 +4083,15 @@ TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoTinySplices) {
|
| }
|
|
|
| TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoMillisecondSplices) {
|
| + EXPECT_MEDIA_LOG_STRING(
|
| + HasSubstr("Skipping splice frame generation: not enough samples for "
|
| + "splicing new buffer at 1250us. Have 750us, but need 1000us."));
|
| +
|
| video_config_ = TestVideoConfig::Invalid();
|
| audio_config_.Initialize(kCodecVorbis, kSampleFormatPlanarF32,
|
| CHANNEL_LAYOUT_STEREO, 4000, NULL, 0, false, false,
|
| base::TimeDelta(), 0);
|
| - stream_.reset(new SourceBufferStream(audio_config_, new MediaLog(), true));
|
| + stream_.reset(new SourceBufferStream(audio_config_, media_log_, true));
|
| // Equivalent to 0.5ms per frame.
|
| SetStreamInfo(2000, 2000);
|
| Seek(0);
|
| @@ -4023,6 +4114,8 @@ TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoMillisecondSplices) {
|
| }
|
|
|
| TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_Preroll) {
|
| + EXPECT_MEDIA_LOG_STRING(ContainsGeneratedSpliceLog(3000, 11000));
|
| +
|
| SetAudioStream();
|
| Seek(0);
|
| NewSegmentAppend("0K 2K 4K 6K 8K 10K 12K");
|
| @@ -4285,6 +4378,64 @@ TEST_F(SourceBufferStreamTest, ConfigChange_ReSeek) {
|
| CheckVideoConfig(new_config);
|
| }
|
|
|
| +TEST_F(SourceBufferStreamTest, TrackBuffer_ExhaustionWithSkipForward) {
|
| + NewSegmentAppend("0K 10 20 30 40");
|
| +
|
| + // Read the first 4 buffers, so next buffer is at time 40.
|
| + Seek(0);
|
| + CheckExpectedRangesByTimestamp("{ [0,50) }");
|
| + CheckExpectedBuffers("0K 10 20 30");
|
| +
|
| + // Overlap-append, populating track buffer with timestamp 40 from original
|
| + // append. Confirm there could be a large jump in time until the next key
|
| + // frame after exhausting the track buffer.
|
| + NewSegmentAppend(
|
| + "31K 41 51 61 71 81 91 101 111 121 "
|
| + "131K 141");
|
| + CheckExpectedRangesByTimestamp("{ [0,151) }");
|
| +
|
| + // Confirm the large jump occurs and warning log is generated.
|
| + // If this test is changed, update
|
| + // TrackBufferExhaustion_ImmediateNewTrackBuffer accordingly.
|
| + EXPECT_MEDIA_LOG_STRING(ContainsTrackBufferExhaustionSkipLog(91));
|
| +
|
| + CheckExpectedBuffers("40 131K 141");
|
| + CheckNoNextBuffer();
|
| +}
|
| +
|
| +TEST_F(SourceBufferStreamTest,
|
| + TrackBuffer_ExhaustionAndImmediateNewTrackBuffer) {
|
| + NewSegmentAppend("0K 10 20 30 40");
|
| +
|
| + // Read the first 4 buffers, so next buffer is at time 40.
|
| + Seek(0);
|
| + CheckExpectedRangesByTimestamp("{ [0,50) }");
|
| + CheckExpectedBuffers("0K 10 20 30");
|
| +
|
| + // Overlap-append
|
| + NewSegmentAppend(
|
| + "31K 41 51 61 71 81 91 101 111 121 "
|
| + "131K 141");
|
| + CheckExpectedRangesByTimestamp("{ [0,151) }");
|
| +
|
| + // Exhaust the track buffer, but don't read any of the overlapping append yet.
|
| + CheckExpectedBuffers("40");
|
| +
|
| + // Selected range's next buffer is now the 131K buffer from the overlapping
|
| + // append. (See TrackBuffer_ExhaustionWithSkipForward for that verification.)
|
| + // Do another overlap-append to immediately create another track buffer and
|
| + // verify both track buffer exhaustions skip forward and emit log warnings.
|
| + NewSegmentAppend("22K 32 42 52 62 72 82 92 102 112 122K 132 142 152K 162");
|
| + CheckExpectedRangesByTimestamp("{ [0,172) }");
|
| +
|
| + InSequence s;
|
| + EXPECT_MEDIA_LOG_STRING(ContainsTrackBufferExhaustionSkipLog(91));
|
| + EXPECT_MEDIA_LOG_STRING(ContainsTrackBufferExhaustionSkipLog(11));
|
| +
|
| + CheckExpectedBuffers("131K 141 152K 162");
|
| + CheckNoNextBuffer();
|
| +}
|
| +
|
| // TODO(vrk): Add unit tests where keyframes are unaligned between streams.
|
| // (crbug.com/133557)
|
|
|
|
|