Chromium Code Reviews| 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/source_buffer_stream.h" | 5 #include "media/filters/source_buffer_stream.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/bind_helpers.h" | 13 #include "base/bind_helpers.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/macros.h" | 15 #include "base/macros.h" |
| 16 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
| 17 #include "base/strings/string_split.h" | 17 #include "base/strings/string_split.h" |
| 18 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 19 #include "media/base/data_buffer.h" | 19 #include "media/base/data_buffer.h" |
| 20 #include "media/base/decoder_buffer.h" | |
| 20 #include "media/base/media_log.h" | 21 #include "media/base/media_log.h" |
| 21 #include "media/base/media_util.h" | 22 #include "media/base/media_util.h" |
| 22 #include "media/base/mock_media_log.h" | 23 #include "media/base/mock_media_log.h" |
| 23 #include "media/base/test_helpers.h" | 24 #include "media/base/test_helpers.h" |
| 24 #include "media/base/text_track_config.h" | 25 #include "media/base/text_track_config.h" |
| 25 #include "media/base/timestamp_constants.h" | 26 #include "media/base/timestamp_constants.h" |
| 26 #include "media/filters/webvtt_util.h" | 27 #include "media/filters/webvtt_util.h" |
| 27 #include "testing/gtest/include/gtest/gtest.h" | 28 #include "testing/gtest/include/gtest/gtest.h" |
| 28 | 29 |
| 29 using ::testing::HasSubstr; | 30 using ::testing::HasSubstr; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 51 MATCHER_P(ContainsTrackBufferExhaustionSkipLog, skip_milliseconds, "") { | 52 MATCHER_P(ContainsTrackBufferExhaustionSkipLog, skip_milliseconds, "") { |
| 52 return CONTAINS_STRING(arg, | 53 return CONTAINS_STRING(arg, |
| 53 "Media append that overlapped current playback " | 54 "Media append that overlapped current playback " |
| 54 "position caused time gap in playing VIDEO stream " | 55 "position caused time gap in playing VIDEO stream " |
| 55 "because the next keyframe is " + | 56 "because the next keyframe is " + |
| 56 base::IntToString(skip_milliseconds) + | 57 base::IntToString(skip_milliseconds) + |
| 57 "ms beyond last overlapped frame. Media may " | 58 "ms beyond last overlapped frame. Media may " |
| 58 "appear temporarily frozen."); | 59 "appear temporarily frozen."); |
| 59 } | 60 } |
| 60 | 61 |
| 61 MATCHER_P2(ContainsGeneratedSpliceLog, | 62 MATCHER_P3(TrimmedSpliceOverlap, |
| 62 duration_microseconds, | 63 splice_time_us, |
| 63 time_microseconds, | 64 overlapped_start_us, |
| 65 trim_duration_us, | |
| 64 "") { | 66 "") { |
| 65 return CONTAINS_STRING(arg, "Generated splice of overlap duration " + | 67 return CONTAINS_STRING( |
| 66 base::IntToString(duration_microseconds) + | 68 arg, "Audio buffer splice at PTS=" + base::IntToString(splice_time_us) + |
| 67 "us into new buffer at " + | 69 "us. Trimmed tail of overlapped buffer (PTS=" + |
| 68 base::IntToString(time_microseconds) + "us."); | 70 base::IntToString(overlapped_start_us) + "us) by " + |
| 71 base::IntToString(trim_duration_us)); | |
| 69 } | 72 } |
| 70 | 73 |
| 71 class SourceBufferStreamTest : public testing::Test { | 74 class SourceBufferStreamTest : public testing::Test { |
| 72 protected: | 75 protected: |
| 73 SourceBufferStreamTest() : media_log_(new StrictMock<MockMediaLog>()) { | 76 SourceBufferStreamTest() : media_log_(new StrictMock<MockMediaLog>()) { |
| 74 video_config_ = TestVideoConfig::Normal(); | 77 video_config_ = TestVideoConfig::Normal(); |
| 75 SetStreamInfo(kDefaultFramesPerSecond, kDefaultKeyframesPerSecond); | 78 SetStreamInfo(kDefaultFramesPerSecond, kDefaultKeyframesPerSecond); |
| 76 stream_.reset(new SourceBufferStream(video_config_, media_log_, true)); | 79 stream_.reset(new SourceBufferStream(video_config_, media_log_)); |
| 77 } | 80 } |
| 78 | 81 |
| 79 void SetMemoryLimit(size_t buffers_of_data) { | 82 void SetMemoryLimit(size_t buffers_of_data) { |
| 80 stream_->set_memory_limit(buffers_of_data * kDataSize); | 83 stream_->set_memory_limit(buffers_of_data * kDataSize); |
| 81 } | 84 } |
| 82 | 85 |
| 83 void SetStreamInfo(int frames_per_second, int keyframes_per_second) { | 86 void SetStreamInfo(int frames_per_second, int keyframes_per_second) { |
| 84 frames_per_second_ = frames_per_second; | 87 frames_per_second_ = frames_per_second; |
| 85 keyframes_per_second_ = keyframes_per_second; | 88 keyframes_per_second_ = keyframes_per_second; |
| 86 frame_duration_ = ConvertToFrameDuration(frames_per_second); | 89 frame_duration_ = ConvertToFrameDuration(frames_per_second); |
| 87 } | 90 } |
| 88 | 91 |
| 89 void SetTextStream() { | 92 void SetTextStream() { |
| 90 video_config_ = TestVideoConfig::Invalid(); | 93 video_config_ = TestVideoConfig::Invalid(); |
| 91 TextTrackConfig config(kTextSubtitles, "", "", ""); | 94 TextTrackConfig config(kTextSubtitles, "", "", ""); |
| 92 stream_.reset(new SourceBufferStream(config, media_log_, true)); | 95 stream_.reset(new SourceBufferStream(config, media_log_)); |
| 93 SetStreamInfo(2, 2); | 96 SetStreamInfo(2, 2); |
| 94 } | 97 } |
| 95 | 98 |
| 96 void SetAudioStream() { | 99 void SetAudioStream() { |
| 97 video_config_ = TestVideoConfig::Invalid(); | 100 video_config_ = TestVideoConfig::Invalid(); |
| 98 audio_config_.Initialize(kCodecVorbis, kSampleFormatPlanarF32, | 101 audio_config_.Initialize(kCodecVorbis, kSampleFormatPlanarF32, |
| 99 CHANNEL_LAYOUT_STEREO, 1000, EmptyExtraData(), | 102 CHANNEL_LAYOUT_STEREO, 1000, EmptyExtraData(), |
| 100 Unencrypted(), base::TimeDelta(), 0); | 103 Unencrypted(), base::TimeDelta(), 0); |
| 101 stream_.reset(new SourceBufferStream(audio_config_, media_log_, true)); | 104 stream_.reset(new SourceBufferStream(audio_config_, media_log_)); |
| 102 | 105 |
| 103 // Equivalent to 2ms per frame. | 106 // Equivalent to 2ms per frame. |
| 104 SetStreamInfo(500, 500); | 107 SetStreamInfo(500, 500); |
| 105 } | 108 } |
| 106 | 109 |
| 107 void NewCodedFrameGroupAppend(int starting_position, int number_of_buffers) { | 110 void NewCodedFrameGroupAppend(int starting_position, int number_of_buffers) { |
| 108 AppendBuffers(starting_position, number_of_buffers, true, | 111 AppendBuffers(starting_position, number_of_buffers, true, |
| 109 base::TimeDelta(), true, &kDataA, kDataSize); | 112 base::TimeDelta(), true, &kDataA, kDataSize); |
| 110 } | 113 } |
| 111 | 114 |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 299 } | 302 } |
| 300 | 303 |
| 301 EXPECT_EQ(ending_position + 1, current_position); | 304 EXPECT_EQ(ending_position + 1, current_position); |
| 302 } | 305 } |
| 303 | 306 |
| 304 void CheckExpectedBuffers(const std::string& expected) { | 307 void CheckExpectedBuffers(const std::string& expected) { |
| 305 std::vector<std::string> timestamps = base::SplitString( | 308 std::vector<std::string> timestamps = base::SplitString( |
| 306 expected, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 309 expected, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| 307 std::stringstream ss; | 310 std::stringstream ss; |
| 308 const SourceBufferStream::Type type = stream_->GetType(); | 311 const SourceBufferStream::Type type = stream_->GetType(); |
| 309 base::TimeDelta active_splice_timestamp = kNoTimestamp; | |
| 310 for (size_t i = 0; i < timestamps.size(); i++) { | 312 for (size_t i = 0; i < timestamps.size(); i++) { |
| 311 scoped_refptr<StreamParserBuffer> buffer; | 313 scoped_refptr<StreamParserBuffer> buffer; |
| 312 SourceBufferStream::Status status = stream_->GetNextBuffer(&buffer); | 314 SourceBufferStream::Status status = stream_->GetNextBuffer(&buffer); |
| 313 | 315 |
| 314 if (i > 0) | 316 if (i > 0) |
| 315 ss << " "; | 317 ss << " "; |
| 316 | 318 |
| 317 if (status == SourceBufferStream::kConfigChange) { | 319 if (status == SourceBufferStream::kConfigChange) { |
| 318 switch (type) { | 320 switch (type) { |
| 319 case SourceBufferStream::kVideo: | 321 case SourceBufferStream::kVideo: |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 373 ASSERT_EQ(buffer->GetDecodeTimestamp(), | 375 ASSERT_EQ(buffer->GetDecodeTimestamp(), |
| 374 preroll_buffer->GetDecodeTimestamp()); | 376 preroll_buffer->GetDecodeTimestamp()); |
| 375 ASSERT_EQ(kInfiniteDuration, preroll_buffer->discard_padding().first); | 377 ASSERT_EQ(kInfiniteDuration, preroll_buffer->discard_padding().first); |
| 376 ASSERT_EQ(base::TimeDelta(), preroll_buffer->discard_padding().second); | 378 ASSERT_EQ(base::TimeDelta(), preroll_buffer->discard_padding().second); |
| 377 ASSERT_TRUE(buffer->is_key_frame()); | 379 ASSERT_TRUE(buffer->is_key_frame()); |
| 378 | 380 |
| 379 ss << "P"; | 381 ss << "P"; |
| 380 } else if (buffer->is_key_frame()) { | 382 } else if (buffer->is_key_frame()) { |
| 381 ss << "K"; | 383 ss << "K"; |
| 382 } | 384 } |
| 383 | |
| 384 // Until the last splice frame is seen, indicated by a matching timestamp, | |
| 385 // all buffers must have the same splice_timestamp(). | |
| 386 if (buffer->timestamp() == active_splice_timestamp) { | |
| 387 ASSERT_EQ(buffer->splice_timestamp(), kNoTimestamp); | |
| 388 } else { | |
| 389 ASSERT_TRUE(active_splice_timestamp == kNoTimestamp || | |
| 390 active_splice_timestamp == buffer->splice_timestamp()); | |
| 391 } | |
| 392 | |
| 393 active_splice_timestamp = buffer->splice_timestamp(); | |
| 394 } | 385 } |
| 395 EXPECT_EQ(expected, ss.str()); | 386 EXPECT_EQ(expected, ss.str()); |
| 396 } | 387 } |
| 397 | 388 |
| 398 void CheckNoNextBuffer() { | 389 void CheckNoNextBuffer() { |
| 399 scoped_refptr<StreamParserBuffer> buffer; | 390 scoped_refptr<StreamParserBuffer> buffer; |
| 400 EXPECT_EQ(SourceBufferStream::kNeedBuffer, stream_->GetNextBuffer(&buffer)); | 391 EXPECT_EQ(SourceBufferStream::kNeedBuffer, stream_->GetNextBuffer(&buffer)); |
| 401 } | 392 } |
| 402 | 393 |
| 403 void CheckEOSReached() { | 394 void CheckEOSReached() { |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 520 // Indicates that the buffer should be marked as containing an *estimated* | 511 // Indicates that the buffer should be marked as containing an *estimated* |
| 521 // duration. E.g., "0D20E 20 25E 30" | 512 // duration. E.g., "0D20E 20 25E 30" |
| 522 // | 513 // |
| 523 // P: | 514 // P: |
| 524 // Indicates the buffer with will also have a preroll buffer | 515 // Indicates the buffer with will also have a preroll buffer |
| 525 // associated with it. The preroll buffer will just be dummy data. | 516 // associated with it. The preroll buffer will just be dummy data. |
| 526 // E.g. "0P 5 10" | 517 // E.g. "0P 5 10" |
| 527 // | 518 // |
| 528 // K: | 519 // K: |
| 529 // Indicates the buffer is a keyframe. E.g., "0K 1|2K 2|4D2K 6 8". | 520 // Indicates the buffer is a keyframe. E.g., "0K 1|2K 2|4D2K 6 8". |
| 530 // | |
| 531 // S(a# ... y# z#) | |
| 532 // Indicates a splice frame buffer should be created with timestamp z#. The | |
| 533 // preceding timestamps a# ... y# will be treated as the fade out preroll for | |
| 534 // the splice frame. If a timestamp within the preroll ends with C the config | |
|
wolenetz
2016/09/26 23:52:37
I think we still need some configchange testing (s
chcunningham
2016/10/27 23:36:06
See new test, SourceBufferStreamTest.Audio_ConfigC
wolenetz
2016/10/28 23:08:19
Acknowledged.
| |
| 535 // id to use for that and subsequent preroll appends is incremented by one. | |
| 536 // The config id for non-splice frame appends will not be affected. | |
| 537 BufferQueue StringToBufferQueue(const std::string& buffers_to_append) { | 521 BufferQueue StringToBufferQueue(const std::string& buffers_to_append) { |
| 538 std::vector<std::string> timestamps = base::SplitString( | 522 std::vector<std::string> timestamps = base::SplitString( |
| 539 buffers_to_append, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 523 buffers_to_append, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| 540 | 524 |
| 541 CHECK_GT(timestamps.size(), 0u); | 525 CHECK_GT(timestamps.size(), 0u); |
| 542 | 526 |
| 543 bool splice_frame = false; | |
| 544 size_t splice_config_id = stream_->append_config_index_; | |
| 545 BufferQueue pre_splice_buffers; | |
| 546 BufferQueue buffers; | 527 BufferQueue buffers; |
| 547 for (size_t i = 0; i < timestamps.size(); i++) { | 528 for (size_t i = 0; i < timestamps.size(); i++) { |
| 548 bool is_keyframe = false; | 529 bool is_keyframe = false; |
| 549 bool has_preroll = false; | 530 bool has_preroll = false; |
| 550 bool last_splice_frame = false; | |
| 551 bool is_duration_estimated = false; | 531 bool is_duration_estimated = false; |
| 552 | 532 |
| 553 // Handle splice frame starts. | |
| 554 if (base::StartsWith(timestamps[i], "S(", base::CompareCase::SENSITIVE)) { | |
| 555 CHECK(!splice_frame); | |
| 556 splice_frame = true; | |
| 557 // Remove the "S(" off of the token. | |
| 558 timestamps[i] = timestamps[i].substr(2, timestamps[i].length()); | |
| 559 } | |
| 560 if (splice_frame && | |
| 561 base::EndsWith(timestamps[i], ")", base::CompareCase::SENSITIVE)) { | |
| 562 splice_frame = false; | |
| 563 last_splice_frame = true; | |
| 564 // Remove the ")" off of the token. | |
| 565 timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1); | |
| 566 } | |
| 567 // Handle config changes within the splice frame. | |
| 568 if (splice_frame && | |
| 569 base::EndsWith(timestamps[i], "C", base::CompareCase::SENSITIVE)) { | |
| 570 splice_config_id++; | |
| 571 CHECK(splice_config_id < stream_->audio_configs_.size() || | |
| 572 splice_config_id < stream_->video_configs_.size()); | |
| 573 // Remove the "C" off of the token. | |
| 574 timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1); | |
| 575 } | |
| 576 if (base::EndsWith(timestamps[i], "K", base::CompareCase::SENSITIVE)) { | 533 if (base::EndsWith(timestamps[i], "K", base::CompareCase::SENSITIVE)) { |
| 577 is_keyframe = true; | 534 is_keyframe = true; |
| 578 // Remove the "K" off of the token. | 535 // Remove the "K" off of the token. |
| 579 timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1); | 536 timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1); |
| 580 } | 537 } |
| 581 // Handle preroll buffers. | 538 // Handle preroll buffers. |
| 582 if (base::EndsWith(timestamps[i], "P", base::CompareCase::SENSITIVE)) { | 539 if (base::EndsWith(timestamps[i], "P", base::CompareCase::SENSITIVE)) { |
| 583 is_keyframe = true; | 540 is_keyframe = true; |
| 584 has_preroll = true; | 541 has_preroll = true; |
| 585 // Remove the "P" off of the token. | 542 // Remove the "P" off of the token. |
| 586 timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1); | 543 timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1); |
| 587 } | 544 } |
| 588 | 545 |
| 589 if (base::EndsWith(timestamps[i], "E", base::CompareCase::SENSITIVE)) { | 546 if (base::EndsWith(timestamps[i], "E", base::CompareCase::SENSITIVE)) { |
| 590 is_duration_estimated = true; | 547 is_duration_estimated = true; |
| 591 // Remove the "E" off of the token. | 548 // Remove the "E" off of the token. |
| 592 timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1); | 549 timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1); |
| 593 } | 550 } |
| 594 | 551 |
| 595 int duration_in_ms = 0; | 552 int duration_in_ms = -1; |
| 596 size_t duration_pos = timestamps[i].find('D'); | 553 size_t duration_pos = timestamps[i].find('D'); |
| 597 if (duration_pos != std::string::npos) { | 554 if (duration_pos != std::string::npos) { |
| 598 CHECK(base::StringToInt(timestamps[i].substr(duration_pos + 1), | 555 CHECK(base::StringToInt(timestamps[i].substr(duration_pos + 1), |
| 599 &duration_in_ms)); | 556 &duration_in_ms)); |
| 600 timestamps[i] = timestamps[i].substr(0, duration_pos); | 557 timestamps[i] = timestamps[i].substr(0, duration_pos); |
| 601 } | 558 } |
| 602 | 559 |
| 603 std::vector<std::string> buffer_timestamps = base::SplitString( | 560 std::vector<std::string> buffer_timestamps = base::SplitString( |
| 604 timestamps[i], "|", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 561 timestamps[i], "|", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| 605 | 562 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 618 StreamParserBuffer::CopyFrom(&kDataA, kDataSize, is_keyframe, | 575 StreamParserBuffer::CopyFrom(&kDataA, kDataSize, is_keyframe, |
| 619 DemuxerStream::AUDIO, 0); | 576 DemuxerStream::AUDIO, 0); |
| 620 buffer->set_timestamp(base::TimeDelta::FromMilliseconds(pts_in_ms)); | 577 buffer->set_timestamp(base::TimeDelta::FromMilliseconds(pts_in_ms)); |
| 621 buffer->set_is_duration_estimated(is_duration_estimated); | 578 buffer->set_is_duration_estimated(is_duration_estimated); |
| 622 | 579 |
| 623 if (dts_in_ms != pts_in_ms) { | 580 if (dts_in_ms != pts_in_ms) { |
| 624 buffer->SetDecodeTimestamp( | 581 buffer->SetDecodeTimestamp( |
| 625 DecodeTimestamp::FromMilliseconds(dts_in_ms)); | 582 DecodeTimestamp::FromMilliseconds(dts_in_ms)); |
| 626 } | 583 } |
| 627 | 584 |
| 628 if (duration_in_ms) | 585 if (duration_in_ms >= 0) |
| 629 buffer->set_duration(base::TimeDelta::FromMilliseconds(duration_in_ms)); | 586 buffer->set_duration(base::TimeDelta::FromMilliseconds(duration_in_ms)); |
| 630 | 587 |
| 631 // Simulate preroll buffers by just generating another buffer and sticking | 588 // Simulate preroll buffers by just generating another buffer and sticking |
| 632 // it as the preroll. | 589 // it as the preroll. |
| 633 if (has_preroll) { | 590 if (has_preroll) { |
| 634 scoped_refptr<StreamParserBuffer> preroll_buffer = | 591 scoped_refptr<StreamParserBuffer> preroll_buffer = |
| 635 StreamParserBuffer::CopyFrom( | 592 StreamParserBuffer::CopyFrom( |
| 636 &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0); | 593 &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0); |
| 637 preroll_buffer->set_duration(frame_duration_); | 594 preroll_buffer->set_duration(frame_duration_); |
| 638 buffer->SetPrerollBuffer(preroll_buffer); | 595 buffer->SetPrerollBuffer(preroll_buffer); |
| 639 } | 596 } |
| 640 | 597 |
| 641 if (splice_frame) { | |
| 642 // Make sure that splice frames aren't used with content where decode | |
| 643 // and presentation timestamps can differ. (i.e., B-frames) | |
| 644 CHECK_EQ(buffer->GetDecodeTimestamp().InMicroseconds(), | |
| 645 buffer->timestamp().InMicroseconds()); | |
| 646 if (!pre_splice_buffers.empty()) { | |
| 647 // Enforce strictly monotonically increasing timestamps. | |
| 648 CHECK_GT( | |
| 649 buffer->timestamp().InMicroseconds(), | |
| 650 pre_splice_buffers.back()->timestamp().InMicroseconds()); | |
| 651 CHECK_GT( | |
| 652 buffer->GetDecodeTimestamp().InMicroseconds(), | |
| 653 pre_splice_buffers.back()->GetDecodeTimestamp().InMicroseconds()); | |
| 654 } | |
| 655 buffer->SetConfigId(splice_config_id); | |
| 656 UpdateLastBufferDuration(buffer->GetDecodeTimestamp(), | |
| 657 &pre_splice_buffers); | |
| 658 pre_splice_buffers.push_back(buffer); | |
| 659 continue; | |
| 660 } | |
| 661 | |
| 662 if (last_splice_frame) { | |
| 663 // Require at least one additional buffer for a splice. | |
| 664 CHECK(!pre_splice_buffers.empty()); | |
| 665 buffer->SetConfigId(splice_config_id); | |
| 666 buffer->ConvertToSpliceBuffer(pre_splice_buffers); | |
| 667 pre_splice_buffers.clear(); | |
| 668 } | |
| 669 | |
| 670 UpdateLastBufferDuration(buffer->GetDecodeTimestamp(), &buffers); | 598 UpdateLastBufferDuration(buffer->GetDecodeTimestamp(), &buffers); |
| 671 buffers.push_back(buffer); | 599 buffers.push_back(buffer); |
| 672 } | 600 } |
| 673 | 601 |
| 674 // If the last buffer doesn't have a duration, assume it is the | 602 // If the last buffer doesn't have a duration, assume it is the |
| 675 // same as the second to last buffer. | 603 // same as the second to last buffer. |
| 676 if (buffers.size() >= 2 && | 604 if (buffers.size() >= 2 && buffers.back()->duration() == kNoTimestamp) { |
| 677 buffers.back()->duration() <= base::TimeDelta()) { | |
| 678 buffers.back()->set_duration( | 605 buffers.back()->set_duration( |
| 679 buffers[buffers.size() - 2]->duration()); | 606 buffers[buffers.size() - 2]->duration()); |
| 680 } | 607 } |
| 681 | 608 |
| 682 return buffers; | 609 return buffers; |
| 683 } | 610 } |
| 684 | 611 |
| 685 void AppendBuffers(const std::string& buffers_to_append, | 612 void AppendBuffers(const std::string& buffers_to_append, |
| 686 bool start_new_coded_frame_group, | 613 bool start_new_coded_frame_group, |
| 687 base::TimeDelta coded_frame_group_start_timestamp, | 614 base::TimeDelta coded_frame_group_start_timestamp, |
| (...skipping 2921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3609 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_SingleAppend) { | 3536 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_SingleAppend) { |
| 3610 Seek(0); | 3537 Seek(0); |
| 3611 NewCodedFrameGroupAppend("0K 30 30 60 90 120K 150"); | 3538 NewCodedFrameGroupAppend("0K 30 30 60 90 120K 150"); |
| 3612 CheckExpectedBuffers("0K 30 30 60 90 120K 150"); | 3539 CheckExpectedBuffers("0K 30 30 60 90 120K 150"); |
| 3613 } | 3540 } |
| 3614 | 3541 |
| 3615 // Verify that non-keyframes with the same timestamp can occur | 3542 // Verify that non-keyframes with the same timestamp can occur |
| 3616 // in different appends. | 3543 // in different appends. |
| 3617 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_TwoAppends) { | 3544 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_TwoAppends) { |
| 3618 Seek(0); | 3545 Seek(0); |
| 3619 NewCodedFrameGroupAppend("0K 30"); | 3546 NewCodedFrameGroupAppend("0K 30D0"); |
| 3620 AppendBuffers("30 60 90 120K 150"); | 3547 AppendBuffers("30 60 90 120K 150"); |
| 3621 CheckExpectedBuffers("0K 30 30 60 90 120K 150"); | 3548 CheckExpectedBuffers("0K 30 30 60 90 120K 150"); |
| 3622 } | 3549 } |
| 3623 | 3550 |
| 3624 // Verify that a non-keyframe followed by a keyframe with the same timestamp | 3551 // Verify that a non-keyframe followed by a keyframe with the same timestamp |
| 3625 // is allowed, but also results in a MediaLog. | 3552 // is allowed, but also results in a MediaLog. |
| 3626 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_SingleAppend_Warning) { | 3553 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_SingleAppend_Warning) { |
| 3627 EXPECT_MEDIA_LOG(ContainsSameTimestampAt30MillisecondsLog()); | 3554 EXPECT_MEDIA_LOG(ContainsSameTimestampAt30MillisecondsLog()); |
| 3628 | 3555 |
| 3629 Seek(0); | 3556 Seek(0); |
| 3630 NewCodedFrameGroupAppend("0K 30 30K 60"); | 3557 NewCodedFrameGroupAppend("0K 30 30K 60"); |
| 3631 CheckExpectedBuffers("0K 30 30K 60"); | 3558 CheckExpectedBuffers("0K 30 30K 60"); |
| 3632 } | 3559 } |
| 3633 | 3560 |
| 3634 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_TwoAppends_Warning) { | 3561 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_TwoAppends_Warning) { |
| 3635 EXPECT_MEDIA_LOG(ContainsSameTimestampAt30MillisecondsLog()); | 3562 EXPECT_MEDIA_LOG(ContainsSameTimestampAt30MillisecondsLog()); |
| 3636 | 3563 |
| 3637 Seek(0); | 3564 Seek(0); |
| 3638 NewCodedFrameGroupAppend("0K 30"); | 3565 NewCodedFrameGroupAppend("0K 30D0"); |
| 3639 AppendBuffers("30K 60"); | 3566 AppendBuffers("30K 60"); |
| 3640 CheckExpectedBuffers("0K 30 30K 60"); | 3567 CheckExpectedBuffers("0K 30 30K 60"); |
| 3641 } | 3568 } |
| 3642 | 3569 |
| 3643 // Verify that a keyframe followed by a non-keyframe with the same timestamp | 3570 // Verify that a keyframe followed by a non-keyframe with the same timestamp |
| 3644 // is allowed. | 3571 // is allowed. |
| 3645 TEST_F(SourceBufferStreamTest, SameTimestamp_VideoKeyFrame_TwoAppends) { | 3572 TEST_F(SourceBufferStreamTest, SameTimestamp_VideoKeyFrame_TwoAppends) { |
| 3646 Seek(0); | 3573 Seek(0); |
| 3647 NewCodedFrameGroupAppend("0K 30K"); | 3574 NewCodedFrameGroupAppend("0K 30D0K"); |
| 3648 AppendBuffers("30 60"); | 3575 AppendBuffers("30 60"); |
| 3649 CheckExpectedBuffers("0K 30K 30 60"); | 3576 CheckExpectedBuffers("0K 30K 30 60"); |
| 3650 } | 3577 } |
| 3651 | 3578 |
| 3652 TEST_F(SourceBufferStreamTest, SameTimestamp_VideoKeyFrame_SingleAppend) { | 3579 TEST_F(SourceBufferStreamTest, SameTimestamp_VideoKeyFrame_SingleAppend) { |
| 3653 Seek(0); | 3580 Seek(0); |
| 3654 NewCodedFrameGroupAppend("0K 30K 30 60"); | 3581 NewCodedFrameGroupAppend("0K 30K 30 60"); |
| 3655 CheckExpectedBuffers("0K 30K 30 60"); | 3582 CheckExpectedBuffers("0K 30K 30 60"); |
| 3656 } | 3583 } |
| 3657 | 3584 |
| 3658 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_1) { | 3585 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_1) { |
| 3659 Seek(0); | 3586 Seek(0); |
| 3660 NewCodedFrameGroupAppend("0K 30 60 60 90 120K 150"); | 3587 NewCodedFrameGroupAppend("0K 30 60 60 90 120K 150"); |
| 3661 | 3588 |
| 3662 NewCodedFrameGroupAppend("60K 91 121K 151"); | 3589 NewCodedFrameGroupAppend("60K 91 121K 151"); |
| 3663 CheckExpectedBuffers("0K 30 60K 91 121K 151"); | 3590 CheckExpectedBuffers("0K 30 60K 91 121K 151"); |
| 3664 } | 3591 } |
| 3665 | 3592 |
| 3666 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_2) { | 3593 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_2) { |
| 3667 Seek(0); | 3594 Seek(0); |
| 3668 NewCodedFrameGroupAppend("0K 30 60 60 90 120K 150"); | 3595 NewCodedFrameGroupAppend("0K 30 60 60 90 120K 150"); |
| 3669 NewCodedFrameGroupAppend("0K 30 61"); | 3596 NewCodedFrameGroupAppend("0K 30 61"); |
| 3670 CheckExpectedBuffers("0K 30 61 120K 150"); | 3597 CheckExpectedBuffers("0K 30 61 120K 150"); |
| 3671 } | 3598 } |
| 3672 | 3599 |
| 3673 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_3) { | 3600 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_3) { |
| 3674 Seek(0); | 3601 Seek(0); |
| 3675 NewCodedFrameGroupAppend("0K 20 40 60 80 100K 101 102 103K"); | 3602 NewCodedFrameGroupAppend("0K 20 40 60 80 100K 101 102 103K"); |
| 3676 NewCodedFrameGroupAppend("0K 20 40 60 80 90"); | 3603 NewCodedFrameGroupAppend("0K 20 40 60 80 90D0"); |
| 3677 CheckExpectedBuffers("0K 20 40 60 80 90 100K 101 102 103K"); | 3604 CheckExpectedBuffers("0K 20 40 60 80 90 100K 101 102 103K"); |
| 3678 AppendBuffers("90 110K 150"); | 3605 AppendBuffers("90 110K 150"); |
| 3679 Seek(0); | 3606 Seek(0); |
| 3680 CheckExpectedBuffers("0K 20 40 60 80 90 90 110K 150"); | 3607 CheckExpectedBuffers("0K 20 40 60 80 90 90 110K 150"); |
| 3681 CheckNoNextBuffer(); | 3608 CheckNoNextBuffer(); |
| 3682 CheckExpectedRangesByTimestamp("{ [0,190) }"); | 3609 CheckExpectedRangesByTimestamp("{ [0,190) }"); |
| 3683 } | 3610 } |
| 3684 | 3611 |
| 3685 // Test all the valid same timestamp cases for audio. | 3612 // Test all the valid same timestamp cases for audio. |
| 3686 TEST_F(SourceBufferStreamTest, SameTimestamp_Audio) { | 3613 TEST_F(SourceBufferStreamTest, SameTimestamp_Audio) { |
| 3687 AudioDecoderConfig config(kCodecMP3, kSampleFormatF32, CHANNEL_LAYOUT_STEREO, | 3614 AudioDecoderConfig config(kCodecMP3, kSampleFormatF32, CHANNEL_LAYOUT_STEREO, |
| 3688 44100, EmptyExtraData(), Unencrypted()); | 3615 44100, EmptyExtraData(), Unencrypted()); |
| 3689 stream_.reset(new SourceBufferStream(config, media_log_, true)); | 3616 stream_.reset(new SourceBufferStream(config, media_log_)); |
| 3690 Seek(0); | 3617 Seek(0); |
| 3691 NewCodedFrameGroupAppend("0K 0K 30K 30 60 60"); | 3618 NewCodedFrameGroupAppend("0K 0K 30K 30 60 60"); |
| 3692 CheckExpectedBuffers("0K 0K 30K 30 60 60"); | 3619 CheckExpectedBuffers("0K 0K 30K 30 60 60"); |
| 3693 } | 3620 } |
| 3694 | 3621 |
| 3695 TEST_F(SourceBufferStreamTest, SameTimestamp_Audio_SingleAppend_Warning) { | 3622 TEST_F(SourceBufferStreamTest, SameTimestamp_Audio_SingleAppend_Warning) { |
| 3696 EXPECT_MEDIA_LOG(ContainsSameTimestampAt30MillisecondsLog()); | 3623 EXPECT_MEDIA_LOG(ContainsSameTimestampAt30MillisecondsLog()); |
| 3697 | 3624 |
| 3698 AudioDecoderConfig config(kCodecMP3, kSampleFormatF32, CHANNEL_LAYOUT_STEREO, | 3625 AudioDecoderConfig config(kCodecMP3, kSampleFormatF32, CHANNEL_LAYOUT_STEREO, |
| 3699 44100, EmptyExtraData(), Unencrypted()); | 3626 44100, EmptyExtraData(), Unencrypted()); |
| 3700 stream_.reset(new SourceBufferStream(config, media_log_, true)); | 3627 stream_.reset(new SourceBufferStream(config, media_log_)); |
| 3701 Seek(0); | 3628 Seek(0); |
| 3702 | 3629 |
| 3703 // Note, in reality, a non-keyframe audio frame is rare or perhaps not | 3630 // Note, in reality, a non-keyframe audio frame is rare or perhaps not |
| 3704 // possible. | 3631 // possible. |
| 3705 NewCodedFrameGroupAppend("0K 30 30K 60"); | 3632 NewCodedFrameGroupAppend("0K 30 30K 60"); |
| 3706 CheckExpectedBuffers("0K 30 30K 60"); | 3633 CheckExpectedBuffers("0K 30 30K 60"); |
| 3707 } | 3634 } |
| 3708 | 3635 |
| 3709 // If seeking past any existing range and the seek is pending | 3636 // If seeking past any existing range and the seek is pending |
| 3710 // because no data has been provided for that position, | 3637 // because no data has been provided for that position, |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4082 SetTextStream(); | 4009 SetTextStream(); |
| 4083 NewCodedFrameGroupAppend("1500K 2000K 2500K 3000K 3500K"); | 4010 NewCodedFrameGroupAppend("1500K 2000K 2500K 3000K 3500K"); |
| 4084 CheckExpectedRangesByTimestamp("{ [1500,4000) }"); | 4011 CheckExpectedRangesByTimestamp("{ [1500,4000) }"); |
| 4085 NewCodedFrameGroupAppend("0K 501K 1001K 1501K 2001K"); | 4012 NewCodedFrameGroupAppend("0K 501K 1001K 1501K 2001K"); |
| 4086 CheckExpectedRangesByTimestamp("{ [0,4000) }"); | 4013 CheckExpectedRangesByTimestamp("{ [0,4000) }"); |
| 4087 | 4014 |
| 4088 Seek(0); | 4015 Seek(0); |
| 4089 CheckExpectedBuffers("0K 501K 1001K 1501K 2001K 3000K 3500K"); | 4016 CheckExpectedBuffers("0K 501K 1001K 1501K 2001K 3000K 3500K"); |
| 4090 } | 4017 } |
| 4091 | 4018 |
| 4092 TEST_F(SourceBufferStreamTest, SpliceFrame_Basic) { | 4019 TEST_F(SourceBufferStreamTest, Audio_SpliceTrimmingForOverlap) { |
| 4093 Seek(0); | |
| 4094 NewCodedFrameGroupAppend("0K S(3K 6 9D3 10D5) 15 20 S(25K 30D5 35D5) 40"); | |
| 4095 CheckExpectedBuffers("0K 3K 6 9 C 10 15 20 25K 30 C 35 40"); | |
| 4096 CheckNoNextBuffer(); | |
| 4097 } | |
| 4098 | |
| 4099 TEST_F(SourceBufferStreamTest, SpliceFrame_SeekClearsSplice) { | |
| 4100 Seek(0); | |
| 4101 NewCodedFrameGroupAppend("0K S(3K 6 9D3 10D5) 15K 20"); | |
| 4102 CheckExpectedBuffers("0K 3K 6"); | |
| 4103 | |
| 4104 SeekToTimestampMs(15); | |
| 4105 CheckExpectedBuffers("15K 20"); | |
| 4106 CheckNoNextBuffer(); | |
| 4107 } | |
| 4108 | |
| 4109 TEST_F(SourceBufferStreamTest, SpliceFrame_SeekClearsSpliceFromTrackBuffer) { | |
| 4110 Seek(0); | |
| 4111 NewCodedFrameGroupAppend("0K 2K S(3K 6 9D3 10D5) 15K 20"); | |
| 4112 CheckExpectedBuffers("0K 2K"); | |
| 4113 | |
| 4114 // Overlap the existing coded frame group. | |
| 4115 NewCodedFrameGroupAppend("5K 15K 20"); | |
| 4116 CheckExpectedBuffers("3K 6"); | |
| 4117 | |
| 4118 SeekToTimestampMs(15); | |
| 4119 CheckExpectedBuffers("15K 20"); | |
| 4120 CheckNoNextBuffer(); | |
| 4121 } | |
| 4122 | |
| 4123 TEST_F(SourceBufferStreamTest, SpliceFrame_ConfigChangeWithinSplice) { | |
| 4124 VideoDecoderConfig new_config = TestVideoConfig::Large(); | |
| 4125 ASSERT_FALSE(new_config.Matches(video_config_)); | |
| 4126 | |
| 4127 // Add a new video config, then reset the config index back to the original. | |
| 4128 stream_->UpdateVideoConfig(new_config); | |
| 4129 stream_->UpdateVideoConfig(video_config_); | |
| 4130 | |
| 4131 Seek(0); | |
| 4132 CheckVideoConfig(video_config_); | |
| 4133 NewCodedFrameGroupAppend("0K S(3K 6C 9D3 10D5) 15"); | |
| 4134 | |
| 4135 CheckExpectedBuffers("0K 3K C"); | |
| 4136 CheckVideoConfig(new_config); | |
| 4137 CheckExpectedBuffers("6 9 C"); | |
| 4138 CheckExpectedBuffers("10 C"); | |
| 4139 CheckVideoConfig(video_config_); | |
| 4140 CheckExpectedBuffers("15"); | |
| 4141 CheckNoNextBuffer(); | |
| 4142 } | |
| 4143 | |
| 4144 TEST_F(SourceBufferStreamTest, SpliceFrame_BasicFromTrackBuffer) { | |
| 4145 Seek(0); | |
| 4146 NewCodedFrameGroupAppend("0K 5K S(8K 9D1 10D10) 20"); | |
| 4147 CheckExpectedBuffers("0K 5K"); | |
| 4148 | |
| 4149 // Overlap the existing coded frame group. | |
| 4150 NewCodedFrameGroupAppend("5K 20"); | |
| 4151 CheckExpectedBuffers("8K 9 C 10 20"); | |
| 4152 CheckNoNextBuffer(); | |
| 4153 } | |
| 4154 | |
| 4155 TEST_F(SourceBufferStreamTest, | |
| 4156 SpliceFrame_ConfigChangeWithinSpliceFromTrackBuffer) { | |
| 4157 VideoDecoderConfig new_config = TestVideoConfig::Large(); | |
| 4158 ASSERT_FALSE(new_config.Matches(video_config_)); | |
| 4159 | |
| 4160 // Add a new video config, then reset the config index back to the original. | |
| 4161 stream_->UpdateVideoConfig(new_config); | |
| 4162 stream_->UpdateVideoConfig(video_config_); | |
| 4163 | |
| 4164 Seek(0); | |
| 4165 CheckVideoConfig(video_config_); | |
| 4166 NewCodedFrameGroupAppend("0K 5K S(7K 8C 9D1 10D10) 20"); | |
| 4167 CheckExpectedBuffers("0K 5K"); | |
| 4168 | |
| 4169 // Overlap the existing coded frame group. | |
| 4170 NewCodedFrameGroupAppend("5K 20"); | |
| 4171 CheckExpectedBuffers("7K C"); | |
| 4172 CheckVideoConfig(new_config); | |
| 4173 CheckExpectedBuffers("8 9 C"); | |
| 4174 CheckExpectedBuffers("10 C"); | |
| 4175 CheckVideoConfig(video_config_); | |
| 4176 CheckExpectedBuffers("20"); | |
| 4177 CheckNoNextBuffer(); | |
| 4178 } | |
| 4179 | |
| 4180 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_Basic) { | |
| 4181 EXPECT_MEDIA_LOG(ContainsGeneratedSpliceLog(3000, 11000)); | |
| 4182 | |
| 4183 SetAudioStream(); | 4020 SetAudioStream(); |
| 4184 Seek(0); | 4021 Seek(0); |
| 4185 NewCodedFrameGroupAppend("0K 2K 4K 6K 8K 10K 12K"); | 4022 NewCodedFrameGroupAppend("0K 2K 4K 6K 8K 10K 12K"); |
| 4186 NewCodedFrameGroupAppend("11K 13K 15K 17K"); | 4023 CheckExpectedRangesByTimestamp("{ [0,14) }"); |
| 4187 CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 12K C 11K 13K 15K 17K"); | 4024 // Note that duration of frame at time 10 is verified to be 2 ms. |
| 4025 CheckExpectedBuffers("0K 2K 4K 6K 8K 10D2K 12K"); | |
| 4188 CheckNoNextBuffer(); | 4026 CheckNoNextBuffer(); |
| 4189 } | |
| 4190 | 4027 |
| 4191 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoExactSplices) { | 4028 // Append new group with front slightly overlapping existing buffer at 10ms. |
| 4192 EXPECT_MEDIA_LOG( | 4029 EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(11000, 10000, 1000)); |
| 4193 HasSubstr("Skipping splice frame generation: first new buffer at 10000us " | |
| 4194 "begins at or before existing buffer at 10000us.")); | |
| 4195 | |
| 4196 SetAudioStream(); | |
| 4197 Seek(0); | |
| 4198 NewCodedFrameGroupAppend("0K 2K 4K 6K 8K 10K 12K"); | |
| 4199 NewCodedFrameGroupAppend("10K 14K"); | |
| 4200 CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 14K"); | |
| 4201 CheckNoNextBuffer(); | |
| 4202 } | |
| 4203 | |
| 4204 // Do not allow splices on top of splices. | |
| 4205 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoDoubleSplice) { | |
| 4206 InSequence s; | |
| 4207 EXPECT_MEDIA_LOG(ContainsGeneratedSpliceLog(3000, 11000)); | |
| 4208 EXPECT_MEDIA_LOG( | |
| 4209 HasSubstr("Skipping splice frame generation: overlapped buffers at " | |
| 4210 "10000us are in a previously buffered splice.")); | |
| 4211 | |
| 4212 SetAudioStream(); | |
| 4213 Seek(0); | |
| 4214 NewCodedFrameGroupAppend("0K 2K 4K 6K 8K 10K 12K"); | |
| 4215 NewCodedFrameGroupAppend("11K 13K 15K 17K"); | 4030 NewCodedFrameGroupAppend("11K 13K 15K 17K"); |
| 4216 | 4031 |
| 4217 // Verify the splice was created. | 4032 // Cross-fade splicing is no longer implemented. Instead we should expect |
| 4218 CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 12K C 11K 13K 15K 17K"); | 4033 // wholly overlapped buffers to be removed (12K). If a buffer is partially |
| 4219 CheckNoNextBuffer(); | 4034 // overlapped (e.g. last millisecond of 10K), the existing buffer should be |
| 4035 // trimmed to perfectly abut the newly appended buffers. | |
| 4220 Seek(0); | 4036 Seek(0); |
| 4221 | 4037 |
| 4222 // Create a splice before the first splice which would include it. | 4038 CheckExpectedRangesByTimestamp("{ [0,19) }"); |
| 4223 NewCodedFrameGroupAppend("9D2K"); | 4039 CheckExpectedBuffers("0K 2K 4K 6K 8K 10D1K 11D2K 13K 15K 17K"); |
| 4224 | |
| 4225 // A splice on top of a splice should result in a discard of the original | |
| 4226 // splice and no new splice frame being generated. | |
| 4227 CheckExpectedBuffers("0K 2K 4K 6K 8K 9K 13K 15K 17K"); | |
| 4228 CheckNoNextBuffer(); | 4040 CheckNoNextBuffer(); |
| 4229 } | 4041 } |
| 4230 | 4042 |
| 4231 // Test that a splice is not created if an end timestamp and start timestamp | 4043 // Test that a splice is not created if an end timestamp and start timestamp |
| 4232 // overlap. | 4044 // perfectly overlap. |
| 4233 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoSplice) { | 4045 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoSplice) { |
| 4234 SetAudioStream(); | 4046 SetAudioStream(); |
| 4235 Seek(0); | 4047 Seek(0); |
| 4048 | |
| 4049 // Add 10 frames across 2 *non-overlapping* appends. | |
| 4236 NewCodedFrameGroupAppend("0K 2K 4K 6K 8K 10K"); | 4050 NewCodedFrameGroupAppend("0K 2K 4K 6K 8K 10K"); |
| 4237 NewCodedFrameGroupAppend("12K 14K 16K 18K"); | 4051 NewCodedFrameGroupAppend("12K 14K 16K 18K"); |
| 4238 CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 12K 14K 16K 18K"); | 4052 |
| 4053 // Manually inspect the buffers at the no-splice boundary to verify duration | |
| 4054 // and lack of discard padding (set when splicing). | |
| 4055 scoped_refptr<StreamParserBuffer> buffer; | |
| 4056 const DecoderBuffer::DiscardPadding kEmptyDiscardPadding; | |
| 4057 for (int i = 0; i < 10; i++) { | |
| 4058 // Verify buffer timestamps and durations are preserved and no buffers have | |
| 4059 // discard padding (indicating no splice trimming). | |
| 4060 EXPECT_EQ(SourceBufferStream::kSuccess, stream_->GetNextBuffer(&buffer)); | |
| 4061 EXPECT_EQ(base::TimeDelta::FromMilliseconds(i * 2), buffer->timestamp()); | |
| 4062 EXPECT_EQ(base::TimeDelta::FromMilliseconds(2), buffer->duration()); | |
| 4063 EXPECT_EQ(kEmptyDiscardPadding, buffer->discard_padding()); | |
| 4064 } | |
| 4065 | |
| 4239 CheckNoNextBuffer(); | 4066 CheckNoNextBuffer(); |
| 4240 } | 4067 } |
| 4241 | 4068 |
| 4242 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_CorrectGroupStartTime) { | 4069 TEST_F(SourceBufferStreamTest, Audio_SpliceTrimming_ExistingTrimming) { |
| 4243 EXPECT_MEDIA_LOG(ContainsGeneratedSpliceLog(5000, 1000)); | 4070 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(4); |
| 4244 | 4071 const base::TimeDelta kNoDiscard = base::TimeDelta(); |
| 4245 SetAudioStream(); | 4072 const bool is_keyframe = true; |
| 4246 Seek(0); | |
| 4247 NewCodedFrameGroupAppend("0K 2K 4K"); | |
| 4248 CheckExpectedRangesByTimestamp("{ [0,6) }"); | |
| 4249 NewCodedFrameGroupAppend("6K 8K 10K"); | |
| 4250 CheckExpectedRangesByTimestamp("{ [0,12) }"); | |
| 4251 NewCodedFrameGroupAppend("1K 4D2K"); | |
| 4252 CheckExpectedRangesByTimestamp("{ [0,12) }"); | |
| 4253 CheckExpectedBuffers("0K 2K 4K C 1K 4K 6K 8K 10K"); | |
| 4254 CheckNoNextBuffer(); | |
| 4255 } | |
| 4256 | |
| 4257 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_ConfigChange) { | |
| 4258 EXPECT_MEDIA_LOG(ContainsGeneratedSpliceLog(3000, 5000)); | |
| 4259 | |
| 4260 SetAudioStream(); | |
| 4261 | |
| 4262 AudioDecoderConfig new_config(kCodecVorbis, kSampleFormatPlanarF32, | |
| 4263 CHANNEL_LAYOUT_MONO, 1000, EmptyExtraData(), | |
| 4264 Unencrypted()); | |
| 4265 ASSERT_NE(new_config.channel_layout(), audio_config_.channel_layout()); | |
| 4266 | |
| 4267 Seek(0); | |
| 4268 CheckAudioConfig(audio_config_); | |
| 4269 NewCodedFrameGroupAppend("0K 2K 4K 6K"); | |
| 4270 stream_->UpdateAudioConfig(new_config); | |
| 4271 NewCodedFrameGroupAppend("5K 8K 12K"); | |
| 4272 CheckExpectedBuffers("0K 2K 4K 6K C 5K 8K 12K"); | |
| 4273 CheckAudioConfig(new_config); | |
| 4274 CheckNoNextBuffer(); | |
| 4275 } | |
| 4276 | |
| 4277 // Ensure splices are not created if there are not enough frames to crossfade. | |
| 4278 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoTinySplices) { | |
| 4279 EXPECT_MEDIA_LOG(HasSubstr( | |
| 4280 "Skipping splice frame generation: not enough samples for splicing new " | |
| 4281 "buffer at 1000us. Have 1000us, but need 2000us.")); | |
| 4282 | 4073 |
| 4283 SetAudioStream(); | 4074 SetAudioStream(); |
| 4284 Seek(0); | 4075 Seek(0); |
| 4285 | 4076 |
| 4286 // Overlap the range [0, 2) with [1, 3). Since each frame has a duration of | 4077 // Make a 2 BufferQueues with a mix of buffers containing of start/end |
|
wolenetz
2016/09/26 23:52:37
nit: Make a 2? containing of?
chcunningham
2016/10/27 23:36:06
Done.
| |
| 4287 // 2ms this results in an overlap of 1ms between the ranges. A splice frame | 4078 // discard. Buffer PTS and duration have been adjusted to reflect discard. |
| 4288 // should not be generated since it requires at least 2 frames, or 2ms in this | 4079 // Buffers A will be appended first, then B. The start of B will overlap A |
| 4289 // case, of data to crossfade. | 4080 // to generate a splice. |
| 4290 NewCodedFrameGroupAppend("0D2K"); | 4081 BufferQueue A_buffers; |
| 4291 CheckExpectedRangesByTimestamp("{ [0,2) }"); | 4082 BufferQueue B_buffers; |
| 4292 NewCodedFrameGroupAppend("1D2K"); | 4083 |
| 4293 CheckExpectedRangesByTimestamp("{ [0,3) }"); | 4084 // Buffer A1: PTS = 0, front discard = 2ms, duration = 2ms. |
| 4294 CheckExpectedBuffers("0K 1K"); | 4085 scoped_refptr<StreamParserBuffer> bufferA1 = StreamParserBuffer::CopyFrom( |
| 4086 &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0); | |
| 4087 bufferA1->set_timestamp(base::TimeDelta::FromMilliseconds(0)); | |
| 4088 bufferA1->set_duration(kDuration / 2); | |
| 4089 const DecoderBuffer::DiscardPadding discardA1 = | |
| 4090 std::make_pair(kDuration / 2, kNoDiscard); | |
| 4091 bufferA1->set_discard_padding(discardA1); | |
| 4092 A_buffers.push_back(bufferA1); | |
| 4093 | |
| 4094 // Buffer A2: PTS = 2, end discard = 2ms, duration = 2ms. | |
| 4095 scoped_refptr<StreamParserBuffer> bufferA2 = StreamParserBuffer::CopyFrom( | |
| 4096 &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0); | |
| 4097 bufferA2->set_timestamp(base::TimeDelta::FromMilliseconds(2)); | |
| 4098 bufferA2->set_duration(kDuration / 2); | |
| 4099 const DecoderBuffer::DiscardPadding discardA2 = | |
| 4100 std::make_pair(kNoDiscard, kDuration / 2); | |
| 4101 bufferA2->set_discard_padding(discardA2); | |
| 4102 A_buffers.push_back(bufferA2); | |
| 4103 | |
| 4104 // Buffer B1: PTS = 3, front discard = 2ms, duration = 2ms. | |
| 4105 scoped_refptr<StreamParserBuffer> bufferB1 = StreamParserBuffer::CopyFrom( | |
| 4106 &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0); | |
| 4107 bufferB1->set_timestamp(base::TimeDelta::FromMilliseconds(3)); | |
| 4108 bufferB1->set_duration(kDuration / 2); | |
| 4109 const DecoderBuffer::DiscardPadding discardB1 = | |
| 4110 std::make_pair(kDuration / 2, kNoDiscard); | |
| 4111 bufferB1->set_discard_padding(discardB1); | |
| 4112 B_buffers.push_back(bufferB1); | |
| 4113 | |
| 4114 // Buffer B2: PTS = 5, no discard padding, duration = 4ms. | |
| 4115 scoped_refptr<StreamParserBuffer> bufferB2 = StreamParserBuffer::CopyFrom( | |
| 4116 &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0); | |
| 4117 bufferB2->set_timestamp(base::TimeDelta::FromMilliseconds(5)); | |
| 4118 bufferB2->set_duration(kDuration); | |
| 4119 B_buffers.push_back(bufferB2); | |
| 4120 | |
| 4121 // Append buffers, trigger splice trimming. | |
| 4122 stream_->OnStartOfCodedFrameGroup(bufferA1->GetDecodeTimestamp()); | |
| 4123 stream_->Append(A_buffers); | |
| 4124 EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(3000, 2000, 1000)); | |
| 4125 stream_->Append(B_buffers); | |
| 4126 | |
| 4127 // Verify buffers. | |
| 4128 scoped_refptr<StreamParserBuffer> read_buffer; | |
| 4129 | |
| 4130 // Buffer A1 was not spliced, should be unchanged. | |
| 4131 EXPECT_EQ(SourceBufferStream::kSuccess, stream_->GetNextBuffer(&read_buffer)); | |
| 4132 EXPECT_EQ(base::TimeDelta::FromMilliseconds(0), read_buffer->timestamp()); | |
| 4133 EXPECT_EQ(kDuration / 2, read_buffer->duration()); | |
| 4134 EXPECT_EQ(discardA1, read_buffer->discard_padding()); | |
| 4135 | |
| 4136 // Buffer A2 was overlapped by buffer B1 1ms. Splice trimming should trim A2's | |
| 4137 // duration and increase its discard padding by 1ms. | |
| 4138 const base::TimeDelta overlap = base::TimeDelta::FromMilliseconds(1); | |
| 4139 EXPECT_EQ(SourceBufferStream::kSuccess, stream_->GetNextBuffer(&read_buffer)); | |
| 4140 EXPECT_EQ(base::TimeDelta::FromMilliseconds(2), read_buffer->timestamp()); | |
| 4141 EXPECT_EQ((kDuration / 2) - overlap, read_buffer->duration()); | |
| 4142 const DecoderBuffer::DiscardPadding overlap_discard = | |
| 4143 std::make_pair(discardA2.first, discardA2.second + overlap); | |
| 4144 EXPECT_EQ(overlap_discard, read_buffer->discard_padding()); | |
| 4145 | |
| 4146 // Buffer B1 is overlapping A2, but B1 should be unchanged - splice trimming | |
| 4147 // only modifies the earlier buffer (A1). | |
| 4148 EXPECT_EQ(SourceBufferStream::kSuccess, stream_->GetNextBuffer(&read_buffer)); | |
| 4149 EXPECT_EQ(base::TimeDelta::FromMilliseconds(3), read_buffer->timestamp()); | |
| 4150 EXPECT_EQ(kDuration / 2, read_buffer->duration()); | |
| 4151 EXPECT_EQ(discardA1, read_buffer->discard_padding()); | |
|
wolenetz
2016/09/26 23:52:38
nit: s/discardA1/discardB1/
chcunningham
2016/10/27 23:36:06
Done.
| |
| 4152 | |
| 4153 // Buffer B2 is not spliced, should be unchanged. | |
| 4154 EXPECT_EQ(SourceBufferStream::kSuccess, stream_->GetNextBuffer(&read_buffer)); | |
| 4155 EXPECT_EQ(base::TimeDelta::FromMilliseconds(5), read_buffer->timestamp()); | |
| 4156 EXPECT_EQ(kDuration, read_buffer->duration()); | |
| 4157 EXPECT_EQ(std::make_pair(kNoDiscard, kNoDiscard), | |
| 4158 read_buffer->discard_padding()); | |
| 4159 | |
| 4295 CheckNoNextBuffer(); | 4160 CheckNoNextBuffer(); |
| 4296 } | 4161 } |
| 4297 | 4162 |
| 4298 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoMillisecondSplices) { | 4163 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoMillisecondSplices) { |
| 4299 EXPECT_MEDIA_LOG( | 4164 EXPECT_MEDIA_LOG( |
| 4300 HasSubstr("Skipping splice frame generation: not enough samples for " | 4165 HasSubstr("Skipping audio splice trimming at PTS=1250us. Found only 250us" |
| 4301 "splicing new buffer at 1250us. Have 750us, but need 1000us.")); | 4166 " of overlap, need at least 1000us.")); |
| 4302 | 4167 |
| 4303 video_config_ = TestVideoConfig::Invalid(); | 4168 video_config_ = TestVideoConfig::Invalid(); |
| 4304 audio_config_.Initialize(kCodecVorbis, kSampleFormatPlanarF32, | 4169 audio_config_.Initialize(kCodecVorbis, kSampleFormatPlanarF32, |
| 4305 CHANNEL_LAYOUT_STEREO, 4000, EmptyExtraData(), | 4170 CHANNEL_LAYOUT_STEREO, 4000, EmptyExtraData(), |
| 4306 Unencrypted(), base::TimeDelta(), 0); | 4171 Unencrypted(), base::TimeDelta(), 0); |
| 4307 stream_.reset(new SourceBufferStream(audio_config_, media_log_, true)); | 4172 stream_.reset(new SourceBufferStream(audio_config_, media_log_)); |
| 4308 // Equivalent to 0.5ms per frame. | 4173 // Equivalent to 0.5ms per frame. |
| 4309 SetStreamInfo(2000, 2000); | 4174 SetStreamInfo(2000, 2000); |
| 4310 Seek(0); | 4175 Seek(0); |
| 4311 | 4176 |
| 4312 // Append four buffers with a 0.5ms duration each. | 4177 // Append four buffers with a 0.5ms duration each. |
| 4313 NewCodedFrameGroupAppend(0, 4); | 4178 NewCodedFrameGroupAppend(0, 4); |
| 4314 CheckExpectedRangesByTimestamp("{ [0,2) }"); | 4179 CheckExpectedRangesByTimestamp("{ [0,2) }"); |
| 4315 | 4180 |
| 4316 // Overlap the range [0, 2) with [1.25, 2); this results in an overlap of | 4181 // Overlap the range [0, 2) with [1.25, 2); this results in an overlap of |
| 4317 // 0.75ms between the ranges. | 4182 // 0.75ms between the ranges. |
|
wolenetz
2016/09/26 23:52:38
nit: s/ranges./ranges, but only 0.25ms end-overlap
chcunningham
2016/10/27 23:36:06
Done, but a little different wording.
| |
| 4318 NewCodedFrameGroupAppend_OffsetFirstBuffer( | 4183 NewCodedFrameGroupAppend_OffsetFirstBuffer( |
| 4319 2, 2, base::TimeDelta::FromMillisecondsD(0.25)); | 4184 2, 2, base::TimeDelta::FromMillisecondsD(0.25)); |
| 4320 CheckExpectedRangesByTimestamp("{ [0,2) }"); | 4185 CheckExpectedRangesByTimestamp("{ [0,2) }"); |
| 4321 | 4186 |
| 4322 // A splice frame should not be generated (indicated by the lack of a config | 4187 // A splice frame should not be generated (indicated by the lack of a config |
|
wolenetz
2016/09/26 23:52:38
nit: this "lack of config change" would occur even
chcunningham
2016/10/27 23:36:06
Done.
| |
| 4323 // change in the expected buffer string) since it requires at least 1ms of | 4188 // change in the expected buffer string) since it requires at least 1ms of |
| 4324 // data to crossfade. | 4189 // data to crossfade. |
| 4325 CheckExpectedBuffers("0K 0K 1K 1K"); | 4190 CheckExpectedBuffers("0K 0K 1K 1K"); |
| 4326 CheckNoNextBuffer(); | 4191 CheckNoNextBuffer(); |
| 4327 } | 4192 } |
| 4328 | 4193 |
| 4329 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_Preroll) { | |
| 4330 EXPECT_MEDIA_LOG(ContainsGeneratedSpliceLog(3000, 11000)); | |
| 4331 | |
| 4332 SetAudioStream(); | |
| 4333 Seek(0); | |
| 4334 NewCodedFrameGroupAppend("0K 2K 4K 6K 8K 10K 12K"); | |
| 4335 NewCodedFrameGroupAppend("11P 13K 15K 17K"); | |
| 4336 CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 12K C 11P 13K 15K 17K"); | |
|
wolenetz
2016/09/26 23:52:37
We should still test that config change across dif
chcunningham
2016/10/27 23:36:06
Done.
| |
| 4337 CheckNoNextBuffer(); | |
| 4338 } | |
| 4339 | |
| 4340 TEST_F(SourceBufferStreamTest, Audio_PrerollFrame) { | 4194 TEST_F(SourceBufferStreamTest, Audio_PrerollFrame) { |
| 4341 Seek(0); | 4195 Seek(0); |
| 4342 NewCodedFrameGroupAppend("0K 3P 6K"); | 4196 NewCodedFrameGroupAppend("0K 3P 6K"); |
| 4343 CheckExpectedBuffers("0K 3P 6K"); | 4197 CheckExpectedBuffers("0K 3P 6K"); |
| 4344 CheckNoNextBuffer(); | 4198 CheckNoNextBuffer(); |
| 4345 } | 4199 } |
| 4346 | 4200 |
| 4347 TEST_F(SourceBufferStreamTest, BFrames) { | 4201 TEST_F(SourceBufferStreamTest, BFrames) { |
| 4348 Seek(0); | 4202 Seek(0); |
| 4349 NewCodedFrameGroupAppend("0K 120|30 30|60 60|90 90|120"); | 4203 NewCodedFrameGroupAppend("0K 120|30 30|60 60|90 90|120"); |
| 4350 CheckExpectedRangesByTimestamp("{ [0,150) }"); | 4204 CheckExpectedRangesByTimestamp("{ [0,150) }"); |
| 4351 | 4205 |
| 4352 CheckExpectedBuffers("0K 120|30 30|60 60|90 90|120"); | 4206 CheckExpectedBuffers("0K 120|30 30|60 60|90 90|120"); |
| 4353 CheckNoNextBuffer(); | 4207 CheckNoNextBuffer(); |
| 4354 } | 4208 } |
| 4355 | 4209 |
| 4356 TEST_F(SourceBufferStreamTest, RemoveShouldAlwaysExcludeEnd) { | |
| 4357 NewCodedFrameGroupAppend("10D2K 12D2 14D2"); | |
| 4358 CheckExpectedRangesByTimestamp("{ [10,16) }"); | |
| 4359 | |
| 4360 // Start new coded frame group, appending KF to abut the start of previous | |
| 4361 // group. | |
| 4362 NewCodedFrameGroupAppend("0D10K"); | |
| 4363 Seek(0); | |
| 4364 CheckExpectedRangesByTimestamp("{ [0,16) }"); | |
| 4365 CheckExpectedBuffers("0K 10K 12 14"); | |
| 4366 CheckNoNextBuffer(); | |
|
wolenetz
2016/09/26 23:52:37
Why remove this?
chcunningham
2016/10/27 23:36:07
See explanation in earlier patch set:
https://code
wolenetz
2016/10/28 23:08:19
I see. I commented now on that https://codereview.
| |
| 4367 | |
| 4368 // Append another buffer with the same timestamp as the last KF. This triggers | |
| 4369 // special logic that allows two buffers to have the same timestamp. When | |
| 4370 // preparing for this new append, there is no reason to remove the later GOP | |
| 4371 // starting at timestamp 10. This verifies the fix for http://crbug.com/469325 | |
| 4372 // where the decision *not* to remove the start of the overlapped range was | |
| 4373 // erroneously triggering buffers with a timestamp matching the end | |
| 4374 // of the append (and any later dependent frames) to be removed. | |
| 4375 AppendBuffers("0D10"); | |
| 4376 Seek(0); | |
| 4377 CheckExpectedRangesByTimestamp("{ [0,16) }"); | |
| 4378 CheckExpectedBuffers("0K 0 10K 12 14"); | |
| 4379 CheckNoNextBuffer(); | |
| 4380 } | |
| 4381 | |
| 4382 TEST_F(SourceBufferStreamTest, RefinedDurationEstimates_BackOverlap) { | 4210 TEST_F(SourceBufferStreamTest, RefinedDurationEstimates_BackOverlap) { |
| 4383 // Append a few buffers, the last one having estimated duration. | 4211 // Append a few buffers, the last one having estimated duration. |
| 4384 NewCodedFrameGroupAppend("0K 5 10 20D10E"); | 4212 NewCodedFrameGroupAppend("0K 5 10 20D10E"); |
| 4385 CheckExpectedRangesByTimestamp("{ [0,30) }"); | 4213 CheckExpectedRangesByTimestamp("{ [0,30) }"); |
| 4386 Seek(0); | 4214 Seek(0); |
| 4387 CheckExpectedBuffers("0K 5 10 20D10E"); | 4215 CheckExpectedBuffers("0K 5 10 20D10E"); |
| 4388 CheckNoNextBuffer(); | 4216 CheckNoNextBuffer(); |
| 4389 | 4217 |
| 4390 // Append a buffer to the end that overlaps the *back* of the existing range. | 4218 // Append a buffer to the end that overlaps the *back* of the existing range. |
| 4391 // This should trigger the estimated duration to be recomputed as a timestamp | 4219 // This should trigger the estimated duration to be recomputed as a timestamp |
| (...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4820 EXPECT_EQ(base::TimeDelta(), stream_->GetHighestPresentationTimestamp()); | 4648 EXPECT_EQ(base::TimeDelta(), stream_->GetHighestPresentationTimestamp()); |
| 4821 } | 4649 } |
| 4822 | 4650 |
| 4823 // TODO(vrk): Add unit tests where keyframes are unaligned between streams. | 4651 // TODO(vrk): Add unit tests where keyframes are unaligned between streams. |
| 4824 // (crbug.com/133557) | 4652 // (crbug.com/133557) |
| 4825 | 4653 |
| 4826 // TODO(vrk): Add unit tests with end of stream being called at interesting | 4654 // TODO(vrk): Add unit tests with end of stream being called at interesting |
| 4827 // times. | 4655 // times. |
| 4828 | 4656 |
| 4829 } // namespace media | 4657 } // namespace media |
| OLD | NEW |