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 duration_microseconds, | |
63 time_microseconds, | |
64 "") { | |
65 return CONTAINS_STRING(arg, "Generated splice of overlap duration " + | |
66 base::IntToString(duration_microseconds) + | |
67 "us into new buffer at " + | |
68 base::IntToString(time_microseconds) + "us."); | |
69 } | |
70 | |
71 class SourceBufferStreamTest : public testing::Test { | 62 class SourceBufferStreamTest : public testing::Test { |
72 protected: | 63 protected: |
73 SourceBufferStreamTest() : media_log_(new StrictMock<MockMediaLog>()) { | 64 SourceBufferStreamTest() : media_log_(new StrictMock<MockMediaLog>()) { |
74 video_config_ = TestVideoConfig::Normal(); | 65 video_config_ = TestVideoConfig::Normal(); |
75 SetStreamInfo(kDefaultFramesPerSecond, kDefaultKeyframesPerSecond); | 66 SetStreamInfo(kDefaultFramesPerSecond, kDefaultKeyframesPerSecond); |
76 stream_.reset(new SourceBufferStream(video_config_, media_log_, true)); | 67 stream_.reset(new SourceBufferStream(video_config_, media_log_)); |
77 } | 68 } |
78 | 69 |
79 void SetMemoryLimit(size_t buffers_of_data) { | 70 void SetMemoryLimit(size_t buffers_of_data) { |
80 stream_->set_memory_limit(buffers_of_data * kDataSize); | 71 stream_->set_memory_limit(buffers_of_data * kDataSize); |
81 } | 72 } |
82 | 73 |
83 void SetStreamInfo(int frames_per_second, int keyframes_per_second) { | 74 void SetStreamInfo(int frames_per_second, int keyframes_per_second) { |
84 frames_per_second_ = frames_per_second; | 75 frames_per_second_ = frames_per_second; |
85 keyframes_per_second_ = keyframes_per_second; | 76 keyframes_per_second_ = keyframes_per_second; |
86 frame_duration_ = ConvertToFrameDuration(frames_per_second); | 77 frame_duration_ = ConvertToFrameDuration(frames_per_second); |
87 } | 78 } |
88 | 79 |
89 void SetTextStream() { | 80 void SetTextStream() { |
90 video_config_ = TestVideoConfig::Invalid(); | 81 video_config_ = TestVideoConfig::Invalid(); |
91 TextTrackConfig config(kTextSubtitles, "", "", ""); | 82 TextTrackConfig config(kTextSubtitles, "", "", ""); |
92 stream_.reset(new SourceBufferStream(config, media_log_, true)); | 83 stream_.reset(new SourceBufferStream(config, media_log_)); |
93 SetStreamInfo(2, 2); | 84 SetStreamInfo(2, 2); |
94 } | 85 } |
95 | 86 |
96 void SetAudioStream() { | 87 void SetAudioStream() { |
97 video_config_ = TestVideoConfig::Invalid(); | 88 video_config_ = TestVideoConfig::Invalid(); |
98 audio_config_.Initialize(kCodecVorbis, kSampleFormatPlanarF32, | 89 audio_config_.Initialize(kCodecVorbis, kSampleFormatPlanarF32, |
99 CHANNEL_LAYOUT_STEREO, 1000, EmptyExtraData(), | 90 CHANNEL_LAYOUT_STEREO, 1000, EmptyExtraData(), |
100 Unencrypted(), base::TimeDelta(), 0); | 91 Unencrypted(), base::TimeDelta(), 0); |
101 stream_.reset(new SourceBufferStream(audio_config_, media_log_, true)); | 92 stream_.reset(new SourceBufferStream(audio_config_, media_log_)); |
102 | 93 |
103 // Equivalent to 2ms per frame. | 94 // Equivalent to 2ms per frame. |
104 SetStreamInfo(500, 500); | 95 SetStreamInfo(500, 500); |
105 } | 96 } |
106 | 97 |
107 void NewCodedFrameGroupAppend(int starting_position, int number_of_buffers) { | 98 void NewCodedFrameGroupAppend(int starting_position, int number_of_buffers) { |
108 AppendBuffers(starting_position, number_of_buffers, true, | 99 AppendBuffers(starting_position, number_of_buffers, true, |
109 base::TimeDelta(), true, &kDataA, kDataSize); | 100 base::TimeDelta(), true, &kDataA, kDataSize); |
110 } | 101 } |
111 | 102 |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 } | 290 } |
300 | 291 |
301 EXPECT_EQ(ending_position + 1, current_position); | 292 EXPECT_EQ(ending_position + 1, current_position); |
302 } | 293 } |
303 | 294 |
304 void CheckExpectedBuffers(const std::string& expected) { | 295 void CheckExpectedBuffers(const std::string& expected) { |
305 std::vector<std::string> timestamps = base::SplitString( | 296 std::vector<std::string> timestamps = base::SplitString( |
306 expected, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 297 expected, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
307 std::stringstream ss; | 298 std::stringstream ss; |
308 const SourceBufferStream::Type type = stream_->GetType(); | 299 const SourceBufferStream::Type type = stream_->GetType(); |
309 base::TimeDelta active_splice_timestamp = kNoTimestamp; | |
310 for (size_t i = 0; i < timestamps.size(); i++) { | 300 for (size_t i = 0; i < timestamps.size(); i++) { |
311 scoped_refptr<StreamParserBuffer> buffer; | 301 scoped_refptr<StreamParserBuffer> buffer; |
312 SourceBufferStream::Status status = stream_->GetNextBuffer(&buffer); | 302 SourceBufferStream::Status status = stream_->GetNextBuffer(&buffer); |
313 | 303 |
314 if (i > 0) | 304 if (i > 0) |
315 ss << " "; | 305 ss << " "; |
316 | 306 |
317 if (status == SourceBufferStream::kConfigChange) { | 307 if (status == SourceBufferStream::kConfigChange) { |
318 switch (type) { | 308 switch (type) { |
319 case SourceBufferStream::kVideo: | 309 case SourceBufferStream::kVideo: |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
373 ASSERT_EQ(buffer->GetDecodeTimestamp(), | 363 ASSERT_EQ(buffer->GetDecodeTimestamp(), |
374 preroll_buffer->GetDecodeTimestamp()); | 364 preroll_buffer->GetDecodeTimestamp()); |
375 ASSERT_EQ(kInfiniteDuration, preroll_buffer->discard_padding().first); | 365 ASSERT_EQ(kInfiniteDuration, preroll_buffer->discard_padding().first); |
376 ASSERT_EQ(base::TimeDelta(), preroll_buffer->discard_padding().second); | 366 ASSERT_EQ(base::TimeDelta(), preroll_buffer->discard_padding().second); |
377 ASSERT_TRUE(buffer->is_key_frame()); | 367 ASSERT_TRUE(buffer->is_key_frame()); |
378 | 368 |
379 ss << "P"; | 369 ss << "P"; |
380 } else if (buffer->is_key_frame()) { | 370 } else if (buffer->is_key_frame()) { |
381 ss << "K"; | 371 ss << "K"; |
382 } | 372 } |
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 } | 373 } |
395 EXPECT_EQ(expected, ss.str()); | 374 EXPECT_EQ(expected, ss.str()); |
396 } | 375 } |
397 | 376 |
398 void CheckNoNextBuffer() { | 377 void CheckNoNextBuffer() { |
399 scoped_refptr<StreamParserBuffer> buffer; | 378 scoped_refptr<StreamParserBuffer> buffer; |
400 EXPECT_EQ(SourceBufferStream::kNeedBuffer, stream_->GetNextBuffer(&buffer)); | 379 EXPECT_EQ(SourceBufferStream::kNeedBuffer, stream_->GetNextBuffer(&buffer)); |
401 } | 380 } |
402 | 381 |
403 void CheckEOSReached() { | 382 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* | 499 // Indicates that the buffer should be marked as containing an *estimated* |
521 // duration. E.g., "0D20E 20 25E 30" | 500 // duration. E.g., "0D20E 20 25E 30" |
522 // | 501 // |
523 // P: | 502 // P: |
524 // Indicates the buffer with will also have a preroll buffer | 503 // Indicates the buffer with will also have a preroll buffer |
525 // associated with it. The preroll buffer will just be dummy data. | 504 // associated with it. The preroll buffer will just be dummy data. |
526 // E.g. "0P 5 10" | 505 // E.g. "0P 5 10" |
527 // | 506 // |
528 // K: | 507 // K: |
529 // Indicates the buffer is a keyframe. E.g., "0K 1|2K 2|4D2K 6 8". | 508 // 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 | |
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) { | 509 BufferQueue StringToBufferQueue(const std::string& buffers_to_append) { |
538 std::vector<std::string> timestamps = base::SplitString( | 510 std::vector<std::string> timestamps = base::SplitString( |
539 buffers_to_append, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 511 buffers_to_append, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
540 | 512 |
541 CHECK_GT(timestamps.size(), 0u); | 513 CHECK_GT(timestamps.size(), 0u); |
542 | 514 |
543 bool splice_frame = false; | |
544 size_t splice_config_id = stream_->append_config_index_; | |
545 BufferQueue pre_splice_buffers; | |
546 BufferQueue buffers; | 515 BufferQueue buffers; |
547 for (size_t i = 0; i < timestamps.size(); i++) { | 516 for (size_t i = 0; i < timestamps.size(); i++) { |
548 bool is_keyframe = false; | 517 bool is_keyframe = false; |
549 bool has_preroll = false; | 518 bool has_preroll = false; |
550 bool last_splice_frame = false; | |
551 bool is_duration_estimated = false; | 519 bool is_duration_estimated = false; |
552 | 520 |
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)) { | 521 if (base::EndsWith(timestamps[i], "K", base::CompareCase::SENSITIVE)) { |
577 is_keyframe = true; | 522 is_keyframe = true; |
578 // Remove the "K" off of the token. | 523 // Remove the "K" off of the token. |
579 timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1); | 524 timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1); |
580 } | 525 } |
581 // Handle preroll buffers. | 526 // Handle preroll buffers. |
582 if (base::EndsWith(timestamps[i], "P", base::CompareCase::SENSITIVE)) { | 527 if (base::EndsWith(timestamps[i], "P", base::CompareCase::SENSITIVE)) { |
583 is_keyframe = true; | 528 is_keyframe = true; |
584 has_preroll = true; | 529 has_preroll = true; |
585 // Remove the "P" off of the token. | 530 // Remove the "P" off of the token. |
586 timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1); | 531 timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1); |
587 } | 532 } |
588 | 533 |
589 if (base::EndsWith(timestamps[i], "E", base::CompareCase::SENSITIVE)) { | 534 if (base::EndsWith(timestamps[i], "E", base::CompareCase::SENSITIVE)) { |
590 is_duration_estimated = true; | 535 is_duration_estimated = true; |
591 // Remove the "E" off of the token. | 536 // Remove the "E" off of the token. |
592 timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1); | 537 timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1); |
593 } | 538 } |
594 | 539 |
595 int duration_in_ms = 0; | 540 int duration_in_ms = -1; |
596 size_t duration_pos = timestamps[i].find('D'); | 541 size_t duration_pos = timestamps[i].find('D'); |
597 if (duration_pos != std::string::npos) { | 542 if (duration_pos != std::string::npos) { |
598 CHECK(base::StringToInt(timestamps[i].substr(duration_pos + 1), | 543 CHECK(base::StringToInt(timestamps[i].substr(duration_pos + 1), |
599 &duration_in_ms)); | 544 &duration_in_ms)); |
600 timestamps[i] = timestamps[i].substr(0, duration_pos); | 545 timestamps[i] = timestamps[i].substr(0, duration_pos); |
601 } | 546 } |
602 | 547 |
603 std::vector<std::string> buffer_timestamps = base::SplitString( | 548 std::vector<std::string> buffer_timestamps = base::SplitString( |
604 timestamps[i], "|", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 549 timestamps[i], "|", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
605 | 550 |
(...skipping 12 matching lines...) Expand all Loading... |
618 StreamParserBuffer::CopyFrom(&kDataA, kDataSize, is_keyframe, | 563 StreamParserBuffer::CopyFrom(&kDataA, kDataSize, is_keyframe, |
619 DemuxerStream::AUDIO, 0); | 564 DemuxerStream::AUDIO, 0); |
620 buffer->set_timestamp(base::TimeDelta::FromMilliseconds(pts_in_ms)); | 565 buffer->set_timestamp(base::TimeDelta::FromMilliseconds(pts_in_ms)); |
621 buffer->set_is_duration_estimated(is_duration_estimated); | 566 buffer->set_is_duration_estimated(is_duration_estimated); |
622 | 567 |
623 if (dts_in_ms != pts_in_ms) { | 568 if (dts_in_ms != pts_in_ms) { |
624 buffer->SetDecodeTimestamp( | 569 buffer->SetDecodeTimestamp( |
625 DecodeTimestamp::FromMilliseconds(dts_in_ms)); | 570 DecodeTimestamp::FromMilliseconds(dts_in_ms)); |
626 } | 571 } |
627 | 572 |
628 if (duration_in_ms) | 573 if (duration_in_ms >= 0) |
629 buffer->set_duration(base::TimeDelta::FromMilliseconds(duration_in_ms)); | 574 buffer->set_duration(base::TimeDelta::FromMilliseconds(duration_in_ms)); |
630 | 575 |
631 // Simulate preroll buffers by just generating another buffer and sticking | 576 // Simulate preroll buffers by just generating another buffer and sticking |
632 // it as the preroll. | 577 // it as the preroll. |
633 if (has_preroll) { | 578 if (has_preroll) { |
634 scoped_refptr<StreamParserBuffer> preroll_buffer = | 579 scoped_refptr<StreamParserBuffer> preroll_buffer = |
635 StreamParserBuffer::CopyFrom( | 580 StreamParserBuffer::CopyFrom( |
636 &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0); | 581 &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0); |
637 preroll_buffer->set_duration(frame_duration_); | 582 preroll_buffer->set_duration(frame_duration_); |
638 buffer->SetPrerollBuffer(preroll_buffer); | 583 buffer->SetPrerollBuffer(preroll_buffer); |
639 } | 584 } |
640 | 585 |
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); | 586 UpdateLastBufferDuration(buffer->GetDecodeTimestamp(), &buffers); |
671 buffers.push_back(buffer); | 587 buffers.push_back(buffer); |
672 } | 588 } |
673 | 589 |
674 // If the last buffer doesn't have a duration, assume it is the | 590 // If the last buffer doesn't have a duration, assume it is the |
675 // same as the second to last buffer. | 591 // same as the second to last buffer. |
676 if (buffers.size() >= 2 && | 592 if (buffers.size() >= 2 && buffers.back()->duration() == kNoTimestamp) { |
677 buffers.back()->duration() <= base::TimeDelta()) { | |
678 buffers.back()->set_duration( | 593 buffers.back()->set_duration( |
679 buffers[buffers.size() - 2]->duration()); | 594 buffers[buffers.size() - 2]->duration()); |
680 } | 595 } |
681 | 596 |
682 return buffers; | 597 return buffers; |
683 } | 598 } |
684 | 599 |
685 void AppendBuffers(const std::string& buffers_to_append, | 600 void AppendBuffers(const std::string& buffers_to_append, |
686 bool start_new_coded_frame_group, | 601 bool start_new_coded_frame_group, |
687 base::TimeDelta coded_frame_group_start_timestamp, | 602 base::TimeDelta coded_frame_group_start_timestamp, |
(...skipping 2971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3659 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_SingleAppend) { | 3574 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_SingleAppend) { |
3660 Seek(0); | 3575 Seek(0); |
3661 NewCodedFrameGroupAppend("0K 30 30 60 90 120K 150"); | 3576 NewCodedFrameGroupAppend("0K 30 30 60 90 120K 150"); |
3662 CheckExpectedBuffers("0K 30 30 60 90 120K 150"); | 3577 CheckExpectedBuffers("0K 30 30 60 90 120K 150"); |
3663 } | 3578 } |
3664 | 3579 |
3665 // Verify that non-keyframes with the same timestamp can occur | 3580 // Verify that non-keyframes with the same timestamp can occur |
3666 // in different appends. | 3581 // in different appends. |
3667 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_TwoAppends) { | 3582 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_TwoAppends) { |
3668 Seek(0); | 3583 Seek(0); |
3669 NewCodedFrameGroupAppend("0K 30"); | 3584 NewCodedFrameGroupAppend("0K 30D0"); |
3670 AppendBuffers("30 60 90 120K 150"); | 3585 AppendBuffers("30 60 90 120K 150"); |
3671 CheckExpectedBuffers("0K 30 30 60 90 120K 150"); | 3586 CheckExpectedBuffers("0K 30 30 60 90 120K 150"); |
3672 } | 3587 } |
3673 | 3588 |
3674 // Verify that a non-keyframe followed by a keyframe with the same timestamp | 3589 // Verify that a non-keyframe followed by a keyframe with the same timestamp |
3675 // is allowed, but also results in a MediaLog. | 3590 // is allowed, but also results in a MediaLog. |
3676 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_SingleAppend_Warning) { | 3591 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_SingleAppend_Warning) { |
3677 EXPECT_MEDIA_LOG(ContainsSameTimestampAt30MillisecondsLog()); | 3592 EXPECT_MEDIA_LOG(ContainsSameTimestampAt30MillisecondsLog()); |
3678 | 3593 |
3679 Seek(0); | 3594 Seek(0); |
3680 NewCodedFrameGroupAppend("0K 30 30K 60"); | 3595 NewCodedFrameGroupAppend("0K 30 30K 60"); |
3681 CheckExpectedBuffers("0K 30 30K 60"); | 3596 CheckExpectedBuffers("0K 30 30K 60"); |
3682 } | 3597 } |
3683 | 3598 |
3684 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_TwoAppends_Warning) { | 3599 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_TwoAppends_Warning) { |
3685 EXPECT_MEDIA_LOG(ContainsSameTimestampAt30MillisecondsLog()); | 3600 EXPECT_MEDIA_LOG(ContainsSameTimestampAt30MillisecondsLog()); |
3686 | 3601 |
3687 Seek(0); | 3602 Seek(0); |
3688 NewCodedFrameGroupAppend("0K 30"); | 3603 NewCodedFrameGroupAppend("0K 30D0"); |
3689 AppendBuffers("30K 60"); | 3604 AppendBuffers("30K 60"); |
3690 CheckExpectedBuffers("0K 30 30K 60"); | 3605 CheckExpectedBuffers("0K 30 30K 60"); |
3691 } | 3606 } |
3692 | 3607 |
3693 // Verify that a keyframe followed by a non-keyframe with the same timestamp | 3608 // Verify that a keyframe followed by a non-keyframe with the same timestamp |
3694 // is allowed. | 3609 // is allowed. |
3695 TEST_F(SourceBufferStreamTest, SameTimestamp_VideoKeyFrame_TwoAppends) { | 3610 TEST_F(SourceBufferStreamTest, SameTimestamp_VideoKeyFrame_TwoAppends) { |
3696 Seek(0); | 3611 Seek(0); |
3697 NewCodedFrameGroupAppend("0K 30K"); | 3612 NewCodedFrameGroupAppend("0K 30D0K"); |
3698 AppendBuffers("30 60"); | 3613 AppendBuffers("30 60"); |
3699 CheckExpectedBuffers("0K 30K 30 60"); | 3614 CheckExpectedBuffers("0K 30K 30 60"); |
3700 } | 3615 } |
3701 | 3616 |
3702 TEST_F(SourceBufferStreamTest, SameTimestamp_VideoKeyFrame_SingleAppend) { | 3617 TEST_F(SourceBufferStreamTest, SameTimestamp_VideoKeyFrame_SingleAppend) { |
3703 Seek(0); | 3618 Seek(0); |
3704 NewCodedFrameGroupAppend("0K 30K 30 60"); | 3619 NewCodedFrameGroupAppend("0K 30K 30 60"); |
3705 CheckExpectedBuffers("0K 30K 30 60"); | 3620 CheckExpectedBuffers("0K 30K 30 60"); |
3706 } | 3621 } |
3707 | 3622 |
3708 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_1) { | 3623 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_1) { |
3709 Seek(0); | 3624 Seek(0); |
3710 NewCodedFrameGroupAppend("0K 30 60 60 90 120K 150"); | 3625 NewCodedFrameGroupAppend("0K 30 60 60 90 120K 150"); |
3711 | 3626 |
3712 NewCodedFrameGroupAppend("60K 91 121K 151"); | 3627 NewCodedFrameGroupAppend("60K 91 121K 151"); |
3713 CheckExpectedBuffers("0K 30 60K 91 121K 151"); | 3628 CheckExpectedBuffers("0K 30 60K 91 121K 151"); |
3714 } | 3629 } |
3715 | 3630 |
3716 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_2) { | 3631 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_2) { |
3717 Seek(0); | 3632 Seek(0); |
3718 NewCodedFrameGroupAppend("0K 30 60 60 90 120K 150"); | 3633 NewCodedFrameGroupAppend("0K 30 60 60 90 120K 150"); |
3719 NewCodedFrameGroupAppend("0K 30 61"); | 3634 NewCodedFrameGroupAppend("0K 30 61"); |
3720 CheckExpectedBuffers("0K 30 61 120K 150"); | 3635 CheckExpectedBuffers("0K 30 61 120K 150"); |
3721 } | 3636 } |
3722 | 3637 |
3723 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_3) { | 3638 TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_3) { |
3724 Seek(0); | 3639 Seek(0); |
3725 NewCodedFrameGroupAppend("0K 20 40 60 80 100K 101 102 103K"); | 3640 NewCodedFrameGroupAppend("0K 20 40 60 80 100K 101 102 103K"); |
3726 NewCodedFrameGroupAppend("0K 20 40 60 80 90"); | 3641 NewCodedFrameGroupAppend("0K 20 40 60 80 90D0"); |
3727 CheckExpectedBuffers("0K 20 40 60 80 90 100K 101 102 103K"); | 3642 CheckExpectedBuffers("0K 20 40 60 80 90 100K 101 102 103K"); |
3728 AppendBuffers("90 110K 150"); | 3643 AppendBuffers("90 110K 150"); |
3729 Seek(0); | 3644 Seek(0); |
3730 CheckExpectedBuffers("0K 20 40 60 80 90 90 110K 150"); | 3645 CheckExpectedBuffers("0K 20 40 60 80 90 90 110K 150"); |
3731 CheckNoNextBuffer(); | 3646 CheckNoNextBuffer(); |
3732 CheckExpectedRangesByTimestamp("{ [0,190) }"); | 3647 CheckExpectedRangesByTimestamp("{ [0,190) }"); |
3733 } | 3648 } |
3734 | 3649 |
3735 // Test all the valid same timestamp cases for audio. | 3650 // Test all the valid same timestamp cases for audio. |
3736 TEST_F(SourceBufferStreamTest, SameTimestamp_Audio) { | 3651 TEST_F(SourceBufferStreamTest, SameTimestamp_Audio) { |
3737 AudioDecoderConfig config(kCodecMP3, kSampleFormatF32, CHANNEL_LAYOUT_STEREO, | 3652 AudioDecoderConfig config(kCodecMP3, kSampleFormatF32, CHANNEL_LAYOUT_STEREO, |
3738 44100, EmptyExtraData(), Unencrypted()); | 3653 44100, EmptyExtraData(), Unencrypted()); |
3739 stream_.reset(new SourceBufferStream(config, media_log_, true)); | 3654 stream_.reset(new SourceBufferStream(config, media_log_)); |
3740 Seek(0); | 3655 Seek(0); |
3741 NewCodedFrameGroupAppend("0K 0K 30K 30 60 60"); | 3656 NewCodedFrameGroupAppend("0K 0K 30K 30 60 60"); |
3742 CheckExpectedBuffers("0K 0K 30K 30 60 60"); | 3657 CheckExpectedBuffers("0K 0K 30K 30 60 60"); |
3743 } | 3658 } |
3744 | 3659 |
3745 TEST_F(SourceBufferStreamTest, SameTimestamp_Audio_SingleAppend_Warning) { | 3660 TEST_F(SourceBufferStreamTest, SameTimestamp_Audio_SingleAppend_Warning) { |
3746 EXPECT_MEDIA_LOG(ContainsSameTimestampAt30MillisecondsLog()); | 3661 EXPECT_MEDIA_LOG(ContainsSameTimestampAt30MillisecondsLog()); |
3747 | 3662 |
3748 AudioDecoderConfig config(kCodecMP3, kSampleFormatF32, CHANNEL_LAYOUT_STEREO, | 3663 AudioDecoderConfig config(kCodecMP3, kSampleFormatF32, CHANNEL_LAYOUT_STEREO, |
3749 44100, EmptyExtraData(), Unencrypted()); | 3664 44100, EmptyExtraData(), Unencrypted()); |
3750 stream_.reset(new SourceBufferStream(config, media_log_, true)); | 3665 stream_.reset(new SourceBufferStream(config, media_log_)); |
3751 Seek(0); | 3666 Seek(0); |
3752 | 3667 |
3753 // Note, in reality, a non-keyframe audio frame is rare or perhaps not | 3668 // Note, in reality, a non-keyframe audio frame is rare or perhaps not |
3754 // possible. | 3669 // possible. |
3755 NewCodedFrameGroupAppend("0K 30 30K 60"); | 3670 NewCodedFrameGroupAppend("0K 30 30K 60"); |
3756 CheckExpectedBuffers("0K 30 30K 60"); | 3671 CheckExpectedBuffers("0K 30 30K 60"); |
3757 } | 3672 } |
3758 | 3673 |
3759 // If seeking past any existing range and the seek is pending | 3674 // If seeking past any existing range and the seek is pending |
3760 // because no data has been provided for that position, | 3675 // because no data has been provided for that position, |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4132 SetTextStream(); | 4047 SetTextStream(); |
4133 NewCodedFrameGroupAppend("1500K 2000K 2500K 3000K 3500K"); | 4048 NewCodedFrameGroupAppend("1500K 2000K 2500K 3000K 3500K"); |
4134 CheckExpectedRangesByTimestamp("{ [1500,4000) }"); | 4049 CheckExpectedRangesByTimestamp("{ [1500,4000) }"); |
4135 NewCodedFrameGroupAppend("0K 501K 1001K 1501K 2001K"); | 4050 NewCodedFrameGroupAppend("0K 501K 1001K 1501K 2001K"); |
4136 CheckExpectedRangesByTimestamp("{ [0,4000) }"); | 4051 CheckExpectedRangesByTimestamp("{ [0,4000) }"); |
4137 | 4052 |
4138 Seek(0); | 4053 Seek(0); |
4139 CheckExpectedBuffers("0K 501K 1001K 1501K 2001K 3000K 3500K"); | 4054 CheckExpectedBuffers("0K 501K 1001K 1501K 2001K 3000K 3500K"); |
4140 } | 4055 } |
4141 | 4056 |
4142 TEST_F(SourceBufferStreamTest, SpliceFrame_Basic) { | 4057 TEST_F(SourceBufferStreamTest, Audio_SpliceTrimmingForOverlap) { |
4143 Seek(0); | |
4144 NewCodedFrameGroupAppend("0K S(3K 6 9D3 10D5) 15 20 S(25K 30D5 35D5) 40"); | |
4145 CheckExpectedBuffers("0K 3K 6 9 C 10 15 20 25K 30 C 35 40"); | |
4146 CheckNoNextBuffer(); | |
4147 } | |
4148 | |
4149 TEST_F(SourceBufferStreamTest, SpliceFrame_SeekClearsSplice) { | |
4150 Seek(0); | |
4151 NewCodedFrameGroupAppend("0K S(3K 6 9D3 10D5) 15K 20"); | |
4152 CheckExpectedBuffers("0K 3K 6"); | |
4153 | |
4154 SeekToTimestampMs(15); | |
4155 CheckExpectedBuffers("15K 20"); | |
4156 CheckNoNextBuffer(); | |
4157 } | |
4158 | |
4159 TEST_F(SourceBufferStreamTest, SpliceFrame_SeekClearsSpliceFromTrackBuffer) { | |
4160 Seek(0); | |
4161 NewCodedFrameGroupAppend("0K 2K S(3K 6 9D3 10D5) 15K 20"); | |
4162 CheckExpectedBuffers("0K 2K"); | |
4163 | |
4164 // Overlap the existing coded frame group. | |
4165 NewCodedFrameGroupAppend("5K 15K 20"); | |
4166 CheckExpectedBuffers("3K 6"); | |
4167 | |
4168 SeekToTimestampMs(15); | |
4169 CheckExpectedBuffers("15K 20"); | |
4170 CheckNoNextBuffer(); | |
4171 } | |
4172 | |
4173 TEST_F(SourceBufferStreamTest, SpliceFrame_ConfigChangeWithinSplice) { | |
4174 VideoDecoderConfig new_config = TestVideoConfig::Large(); | |
4175 ASSERT_FALSE(new_config.Matches(video_config_)); | |
4176 | |
4177 // Add a new video config, then reset the config index back to the original. | |
4178 stream_->UpdateVideoConfig(new_config); | |
4179 stream_->UpdateVideoConfig(video_config_); | |
4180 | |
4181 Seek(0); | |
4182 CheckVideoConfig(video_config_); | |
4183 NewCodedFrameGroupAppend("0K S(3K 6C 9D3 10D5) 15"); | |
4184 | |
4185 CheckExpectedBuffers("0K 3K C"); | |
4186 CheckVideoConfig(new_config); | |
4187 CheckExpectedBuffers("6 9 C"); | |
4188 CheckExpectedBuffers("10 C"); | |
4189 CheckVideoConfig(video_config_); | |
4190 CheckExpectedBuffers("15"); | |
4191 CheckNoNextBuffer(); | |
4192 } | |
4193 | |
4194 TEST_F(SourceBufferStreamTest, SpliceFrame_BasicFromTrackBuffer) { | |
4195 Seek(0); | |
4196 NewCodedFrameGroupAppend("0K 5K S(8K 9D1 10D10) 20"); | |
4197 CheckExpectedBuffers("0K 5K"); | |
4198 | |
4199 // Overlap the existing coded frame group. | |
4200 NewCodedFrameGroupAppend("5K 20"); | |
4201 CheckExpectedBuffers("8K 9 C 10 20"); | |
4202 CheckNoNextBuffer(); | |
4203 } | |
4204 | |
4205 TEST_F(SourceBufferStreamTest, | |
4206 SpliceFrame_ConfigChangeWithinSpliceFromTrackBuffer) { | |
4207 VideoDecoderConfig new_config = TestVideoConfig::Large(); | |
4208 ASSERT_FALSE(new_config.Matches(video_config_)); | |
4209 | |
4210 // Add a new video config, then reset the config index back to the original. | |
4211 stream_->UpdateVideoConfig(new_config); | |
4212 stream_->UpdateVideoConfig(video_config_); | |
4213 | |
4214 Seek(0); | |
4215 CheckVideoConfig(video_config_); | |
4216 NewCodedFrameGroupAppend("0K 5K S(7K 8C 9D1 10D10) 20"); | |
4217 CheckExpectedBuffers("0K 5K"); | |
4218 | |
4219 // Overlap the existing coded frame group. | |
4220 NewCodedFrameGroupAppend("5K 20"); | |
4221 CheckExpectedBuffers("7K C"); | |
4222 CheckVideoConfig(new_config); | |
4223 CheckExpectedBuffers("8 9 C"); | |
4224 CheckExpectedBuffers("10 C"); | |
4225 CheckVideoConfig(video_config_); | |
4226 CheckExpectedBuffers("20"); | |
4227 CheckNoNextBuffer(); | |
4228 } | |
4229 | |
4230 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_Basic) { | |
4231 EXPECT_MEDIA_LOG(ContainsGeneratedSpliceLog(3000, 11000)); | |
4232 | |
4233 SetAudioStream(); | 4058 SetAudioStream(); |
4234 Seek(0); | 4059 Seek(0); |
4235 NewCodedFrameGroupAppend("0K 2K 4K 6K 8K 10K 12K"); | 4060 NewCodedFrameGroupAppend("0K 2K 4K 6K 8K 10K 12K"); |
4236 NewCodedFrameGroupAppend("11K 13K 15K 17K"); | 4061 CheckExpectedRangesByTimestamp("{ [0,14) }"); |
4237 CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 12K C 11K 13K 15K 17K"); | 4062 // Note that duration of frame at time 10 is verified to be 2 ms. |
| 4063 CheckExpectedBuffers("0K 2K 4K 6K 8K 10D2K 12K"); |
4238 CheckNoNextBuffer(); | 4064 CheckNoNextBuffer(); |
4239 } | |
4240 | 4065 |
4241 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoExactSplices) { | 4066 // Append new group with front slightly overlapping existing buffer at 10ms. |
4242 EXPECT_MEDIA_LOG( | 4067 EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(11000, 10000, 1000)); |
4243 HasSubstr("Skipping splice frame generation: first new buffer at 10000us " | |
4244 "begins at or before existing buffer at 10000us.")); | |
4245 | |
4246 SetAudioStream(); | |
4247 Seek(0); | |
4248 NewCodedFrameGroupAppend("0K 2K 4K 6K 8K 10K 12K"); | |
4249 NewCodedFrameGroupAppend("10K 14K"); | |
4250 CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 14K"); | |
4251 CheckNoNextBuffer(); | |
4252 } | |
4253 | |
4254 // Do not allow splices on top of splices. | |
4255 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoDoubleSplice) { | |
4256 InSequence s; | |
4257 EXPECT_MEDIA_LOG(ContainsGeneratedSpliceLog(3000, 11000)); | |
4258 EXPECT_MEDIA_LOG( | |
4259 HasSubstr("Skipping splice frame generation: overlapped buffers at " | |
4260 "10000us are in a previously buffered splice.")); | |
4261 | |
4262 SetAudioStream(); | |
4263 Seek(0); | |
4264 NewCodedFrameGroupAppend("0K 2K 4K 6K 8K 10K 12K"); | |
4265 NewCodedFrameGroupAppend("11K 13K 15K 17K"); | 4068 NewCodedFrameGroupAppend("11K 13K 15K 17K"); |
4266 | 4069 |
4267 // Verify the splice was created. | 4070 // Cross-fade splicing is no longer implemented. Instead we should expect |
4268 CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 12K C 11K 13K 15K 17K"); | 4071 // wholly overlapped buffers to be removed (12K). If a buffer is partially |
4269 CheckNoNextBuffer(); | 4072 // overlapped (e.g. last millisecond of 10K), the existing buffer should be |
| 4073 // trimmed to perfectly abut the newly appended buffers. |
4270 Seek(0); | 4074 Seek(0); |
4271 | 4075 |
4272 // Create a splice before the first splice which would include it. | 4076 CheckExpectedRangesByTimestamp("{ [0,19) }"); |
4273 NewCodedFrameGroupAppend("9D2K"); | 4077 CheckExpectedBuffers("0K 2K 4K 6K 8K 10D1K 11D2K 13K 15K 17K"); |
4274 | |
4275 // A splice on top of a splice should result in a discard of the original | |
4276 // splice and no new splice frame being generated. | |
4277 CheckExpectedBuffers("0K 2K 4K 6K 8K 9K 13K 15K 17K"); | |
4278 CheckNoNextBuffer(); | 4078 CheckNoNextBuffer(); |
4279 } | 4079 } |
4280 | 4080 |
4281 // Test that a splice is not created if an end timestamp and start timestamp | 4081 // Test that a splice is not created if an end timestamp and start timestamp |
4282 // overlap. | 4082 // perfectly overlap. |
4283 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoSplice) { | 4083 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoSplice) { |
4284 SetAudioStream(); | 4084 SetAudioStream(); |
4285 Seek(0); | 4085 Seek(0); |
| 4086 |
| 4087 // Add 10 frames across 2 *non-overlapping* appends. |
4286 NewCodedFrameGroupAppend("0K 2K 4K 6K 8K 10K"); | 4088 NewCodedFrameGroupAppend("0K 2K 4K 6K 8K 10K"); |
4287 NewCodedFrameGroupAppend("12K 14K 16K 18K"); | 4089 NewCodedFrameGroupAppend("12K 14K 16K 18K"); |
4288 CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 12K 14K 16K 18K"); | 4090 |
| 4091 // Manually inspect the buffers at the no-splice boundary to verify duration |
| 4092 // and lack of discard padding (set when splicing). |
| 4093 scoped_refptr<StreamParserBuffer> buffer; |
| 4094 const DecoderBuffer::DiscardPadding kEmptyDiscardPadding; |
| 4095 for (int i = 0; i < 10; i++) { |
| 4096 // Verify buffer timestamps and durations are preserved and no buffers have |
| 4097 // discard padding (indicating no splice trimming). |
| 4098 EXPECT_EQ(SourceBufferStream::kSuccess, stream_->GetNextBuffer(&buffer)); |
| 4099 EXPECT_EQ(base::TimeDelta::FromMilliseconds(i * 2), buffer->timestamp()); |
| 4100 EXPECT_EQ(base::TimeDelta::FromMilliseconds(2), buffer->duration()); |
| 4101 EXPECT_EQ(kEmptyDiscardPadding, buffer->discard_padding()); |
| 4102 } |
| 4103 |
4289 CheckNoNextBuffer(); | 4104 CheckNoNextBuffer(); |
4290 } | 4105 } |
4291 | 4106 |
4292 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_CorrectGroupStartTime) { | 4107 TEST_F(SourceBufferStreamTest, Audio_SpliceTrimming_ExistingTrimming) { |
4293 EXPECT_MEDIA_LOG(ContainsGeneratedSpliceLog(5000, 1000)); | 4108 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(4); |
4294 | 4109 const base::TimeDelta kNoDiscard = base::TimeDelta(); |
4295 SetAudioStream(); | 4110 const bool is_keyframe = true; |
4296 Seek(0); | |
4297 NewCodedFrameGroupAppend("0K 2K 4K"); | |
4298 CheckExpectedRangesByTimestamp("{ [0,6) }"); | |
4299 NewCodedFrameGroupAppend("6K 8K 10K"); | |
4300 CheckExpectedRangesByTimestamp("{ [0,12) }"); | |
4301 NewCodedFrameGroupAppend("1K 4D2K"); | |
4302 CheckExpectedRangesByTimestamp("{ [0,12) }"); | |
4303 CheckExpectedBuffers("0K 2K 4K C 1K 4K 6K 8K 10K"); | |
4304 CheckNoNextBuffer(); | |
4305 } | |
4306 | |
4307 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_ConfigChange) { | |
4308 EXPECT_MEDIA_LOG(ContainsGeneratedSpliceLog(3000, 5000)); | |
4309 | |
4310 SetAudioStream(); | |
4311 | |
4312 AudioDecoderConfig new_config(kCodecVorbis, kSampleFormatPlanarF32, | |
4313 CHANNEL_LAYOUT_MONO, 1000, EmptyExtraData(), | |
4314 Unencrypted()); | |
4315 ASSERT_NE(new_config.channel_layout(), audio_config_.channel_layout()); | |
4316 | |
4317 Seek(0); | |
4318 CheckAudioConfig(audio_config_); | |
4319 NewCodedFrameGroupAppend("0K 2K 4K 6K"); | |
4320 stream_->UpdateAudioConfig(new_config); | |
4321 NewCodedFrameGroupAppend("5K 8K 12K"); | |
4322 CheckExpectedBuffers("0K 2K 4K 6K C 5K 8K 12K"); | |
4323 CheckAudioConfig(new_config); | |
4324 CheckNoNextBuffer(); | |
4325 } | |
4326 | |
4327 // Ensure splices are not created if there are not enough frames to crossfade. | |
4328 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoTinySplices) { | |
4329 EXPECT_MEDIA_LOG(HasSubstr( | |
4330 "Skipping splice frame generation: not enough samples for splicing new " | |
4331 "buffer at 1000us. Have 1000us, but need 2000us.")); | |
4332 | 4111 |
4333 SetAudioStream(); | 4112 SetAudioStream(); |
4334 Seek(0); | 4113 Seek(0); |
4335 | 4114 |
4336 // Overlap the range [0, 2) with [1, 3). Since each frame has a duration of | 4115 // Make two BufferQueues with a mix of buffers containing start/end discard. |
4337 // 2ms this results in an overlap of 1ms between the ranges. A splice frame | 4116 // Buffer PTS and duration have been adjusted to reflect discard. A_buffers |
4338 // should not be generated since it requires at least 2 frames, or 2ms in this | 4117 // will be appended first, then B_buffers. The start of B will overlap A |
4339 // case, of data to crossfade. | 4118 // to generate a splice. |
4340 NewCodedFrameGroupAppend("0D2K"); | 4119 BufferQueue A_buffers; |
4341 CheckExpectedRangesByTimestamp("{ [0,2) }"); | 4120 BufferQueue B_buffers; |
4342 NewCodedFrameGroupAppend("1D2K"); | 4121 |
4343 CheckExpectedRangesByTimestamp("{ [0,3) }"); | 4122 // Buffer A1: PTS = 0, front discard = 2ms, duration = 2ms. |
4344 CheckExpectedBuffers("0K 1K"); | 4123 scoped_refptr<StreamParserBuffer> bufferA1 = StreamParserBuffer::CopyFrom( |
| 4124 &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0); |
| 4125 bufferA1->set_timestamp(base::TimeDelta::FromMilliseconds(0)); |
| 4126 bufferA1->set_duration(kDuration / 2); |
| 4127 const DecoderBuffer::DiscardPadding discardA1 = |
| 4128 std::make_pair(kDuration / 2, kNoDiscard); |
| 4129 bufferA1->set_discard_padding(discardA1); |
| 4130 A_buffers.push_back(bufferA1); |
| 4131 |
| 4132 // Buffer A2: PTS = 2, end discard = 2ms, duration = 2ms. |
| 4133 scoped_refptr<StreamParserBuffer> bufferA2 = StreamParserBuffer::CopyFrom( |
| 4134 &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0); |
| 4135 bufferA2->set_timestamp(base::TimeDelta::FromMilliseconds(2)); |
| 4136 bufferA2->set_duration(kDuration / 2); |
| 4137 const DecoderBuffer::DiscardPadding discardA2 = |
| 4138 std::make_pair(kNoDiscard, kDuration / 2); |
| 4139 bufferA2->set_discard_padding(discardA2); |
| 4140 A_buffers.push_back(bufferA2); |
| 4141 |
| 4142 // Buffer B1: PTS = 3, front discard = 2ms, duration = 2ms. |
| 4143 scoped_refptr<StreamParserBuffer> bufferB1 = StreamParserBuffer::CopyFrom( |
| 4144 &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0); |
| 4145 bufferB1->set_timestamp(base::TimeDelta::FromMilliseconds(3)); |
| 4146 bufferB1->set_duration(kDuration / 2); |
| 4147 const DecoderBuffer::DiscardPadding discardB1 = |
| 4148 std::make_pair(kDuration / 2, kNoDiscard); |
| 4149 bufferB1->set_discard_padding(discardB1); |
| 4150 B_buffers.push_back(bufferB1); |
| 4151 |
| 4152 // Buffer B2: PTS = 5, no discard padding, duration = 4ms. |
| 4153 scoped_refptr<StreamParserBuffer> bufferB2 = StreamParserBuffer::CopyFrom( |
| 4154 &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0); |
| 4155 bufferB2->set_timestamp(base::TimeDelta::FromMilliseconds(5)); |
| 4156 bufferB2->set_duration(kDuration); |
| 4157 B_buffers.push_back(bufferB2); |
| 4158 |
| 4159 // Append buffers, trigger splice trimming. |
| 4160 stream_->OnStartOfCodedFrameGroup(bufferA1->GetDecodeTimestamp()); |
| 4161 stream_->Append(A_buffers); |
| 4162 EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(3000, 2000, 1000)); |
| 4163 stream_->Append(B_buffers); |
| 4164 |
| 4165 // Verify buffers. |
| 4166 scoped_refptr<StreamParserBuffer> read_buffer; |
| 4167 |
| 4168 // Buffer A1 was not spliced, should be unchanged. |
| 4169 EXPECT_EQ(SourceBufferStream::kSuccess, stream_->GetNextBuffer(&read_buffer)); |
| 4170 EXPECT_EQ(base::TimeDelta::FromMilliseconds(0), read_buffer->timestamp()); |
| 4171 EXPECT_EQ(kDuration / 2, read_buffer->duration()); |
| 4172 EXPECT_EQ(discardA1, read_buffer->discard_padding()); |
| 4173 |
| 4174 // Buffer A2 was overlapped by buffer B1 1ms. Splice trimming should trim A2's |
| 4175 // duration and increase its discard padding by 1ms. |
| 4176 const base::TimeDelta overlap = base::TimeDelta::FromMilliseconds(1); |
| 4177 EXPECT_EQ(SourceBufferStream::kSuccess, stream_->GetNextBuffer(&read_buffer)); |
| 4178 EXPECT_EQ(base::TimeDelta::FromMilliseconds(2), read_buffer->timestamp()); |
| 4179 EXPECT_EQ((kDuration / 2) - overlap, read_buffer->duration()); |
| 4180 const DecoderBuffer::DiscardPadding overlap_discard = |
| 4181 std::make_pair(discardA2.first, discardA2.second + overlap); |
| 4182 EXPECT_EQ(overlap_discard, read_buffer->discard_padding()); |
| 4183 |
| 4184 // Buffer B1 is overlapping A2, but B1 should be unchanged - splice trimming |
| 4185 // only modifies the earlier buffer (A1). |
| 4186 EXPECT_EQ(SourceBufferStream::kSuccess, stream_->GetNextBuffer(&read_buffer)); |
| 4187 EXPECT_EQ(base::TimeDelta::FromMilliseconds(3), read_buffer->timestamp()); |
| 4188 EXPECT_EQ(kDuration / 2, read_buffer->duration()); |
| 4189 EXPECT_EQ(discardB1, read_buffer->discard_padding()); |
| 4190 |
| 4191 // Buffer B2 is not spliced, should be unchanged. |
| 4192 EXPECT_EQ(SourceBufferStream::kSuccess, stream_->GetNextBuffer(&read_buffer)); |
| 4193 EXPECT_EQ(base::TimeDelta::FromMilliseconds(5), read_buffer->timestamp()); |
| 4194 EXPECT_EQ(kDuration, read_buffer->duration()); |
| 4195 EXPECT_EQ(std::make_pair(kNoDiscard, kNoDiscard), |
| 4196 read_buffer->discard_padding()); |
| 4197 |
4345 CheckNoNextBuffer(); | 4198 CheckNoNextBuffer(); |
4346 } | 4199 } |
4347 | 4200 |
4348 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoMillisecondSplices) { | 4201 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoMillisecondSplices) { |
4349 EXPECT_MEDIA_LOG( | 4202 EXPECT_MEDIA_LOG( |
4350 HasSubstr("Skipping splice frame generation: not enough samples for " | 4203 HasSubstr("Skipping audio splice trimming at PTS=1250us. Found only 250us" |
4351 "splicing new buffer at 1250us. Have 750us, but need 1000us.")); | 4204 " of overlap, need at least 1000us.")); |
4352 | 4205 |
4353 video_config_ = TestVideoConfig::Invalid(); | 4206 video_config_ = TestVideoConfig::Invalid(); |
4354 audio_config_.Initialize(kCodecVorbis, kSampleFormatPlanarF32, | 4207 audio_config_.Initialize(kCodecVorbis, kSampleFormatPlanarF32, |
4355 CHANNEL_LAYOUT_STEREO, 4000, EmptyExtraData(), | 4208 CHANNEL_LAYOUT_STEREO, 4000, EmptyExtraData(), |
4356 Unencrypted(), base::TimeDelta(), 0); | 4209 Unencrypted(), base::TimeDelta(), 0); |
4357 stream_.reset(new SourceBufferStream(audio_config_, media_log_, true)); | 4210 stream_.reset(new SourceBufferStream(audio_config_, media_log_)); |
4358 // Equivalent to 0.5ms per frame. | 4211 // Equivalent to 0.5ms per frame. |
4359 SetStreamInfo(2000, 2000); | 4212 SetStreamInfo(2000, 2000); |
4360 Seek(0); | 4213 Seek(0); |
4361 | 4214 |
4362 // Append four buffers with a 0.5ms duration each. | 4215 // Append four buffers with a 0.5ms duration each. |
4363 NewCodedFrameGroupAppend(0, 4); | 4216 NewCodedFrameGroupAppend(0, 4); |
4364 CheckExpectedRangesByTimestamp("{ [0,2) }"); | 4217 CheckExpectedRangesByTimestamp("{ [0,2) }"); |
4365 | 4218 |
4366 // Overlap the range [0, 2) with [1.25, 2); this results in an overlap of | 4219 // Overlap the range [0, 2) with [1.25, 2); this results in an overlap of |
4367 // 0.75ms between the ranges. | 4220 // 0.25ms between the original buffer at time 1.0 and the new buffer at time |
| 4221 // 1.25. |
4368 NewCodedFrameGroupAppend_OffsetFirstBuffer( | 4222 NewCodedFrameGroupAppend_OffsetFirstBuffer( |
4369 2, 2, base::TimeDelta::FromMillisecondsD(0.25)); | 4223 2, 2, base::TimeDelta::FromMillisecondsD(0.25)); |
4370 CheckExpectedRangesByTimestamp("{ [0,2) }"); | 4224 CheckExpectedRangesByTimestamp("{ [0,2) }"); |
4371 | 4225 |
4372 // A splice frame should not be generated (indicated by the lack of a config | 4226 // A splice frame should not be generated since it requires at least 1ms of |
4373 // change in the expected buffer string) since it requires at least 1ms of | |
4374 // data to crossfade. | 4227 // data to crossfade. |
4375 CheckExpectedBuffers("0K 0K 1K 1K"); | 4228 CheckExpectedBuffers("0K 0K 1K 1K"); |
4376 CheckNoNextBuffer(); | 4229 CheckNoNextBuffer(); |
4377 } | 4230 } |
4378 | 4231 |
4379 TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_Preroll) { | |
4380 EXPECT_MEDIA_LOG(ContainsGeneratedSpliceLog(3000, 11000)); | |
4381 | |
4382 SetAudioStream(); | |
4383 Seek(0); | |
4384 NewCodedFrameGroupAppend("0K 2K 4K 6K 8K 10K 12K"); | |
4385 NewCodedFrameGroupAppend("11P 13K 15K 17K"); | |
4386 CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 12K C 11P 13K 15K 17K"); | |
4387 CheckNoNextBuffer(); | |
4388 } | |
4389 | |
4390 TEST_F(SourceBufferStreamTest, Audio_PrerollFrame) { | 4232 TEST_F(SourceBufferStreamTest, Audio_PrerollFrame) { |
4391 Seek(0); | 4233 Seek(0); |
4392 NewCodedFrameGroupAppend("0K 3P 6K"); | 4234 NewCodedFrameGroupAppend("0K 3P 6K"); |
4393 CheckExpectedBuffers("0K 3P 6K"); | 4235 CheckExpectedBuffers("0K 3P 6K"); |
4394 CheckNoNextBuffer(); | 4236 CheckNoNextBuffer(); |
4395 } | 4237 } |
4396 | 4238 |
| 4239 TEST_F(SourceBufferStreamTest, Audio_ConfigChangeWithPreroll) { |
| 4240 AudioDecoderConfig new_config(kCodecVorbis, kSampleFormatPlanarF32, |
| 4241 CHANNEL_LAYOUT_MONO, 2000, EmptyExtraData(), |
| 4242 Unencrypted()); |
| 4243 SetAudioStream(); |
| 4244 Seek(0); |
| 4245 |
| 4246 // Append some audio using the default configuration. |
| 4247 CheckAudioConfig(audio_config_); |
| 4248 NewCodedFrameGroupAppend("0K 3K 6K"); |
| 4249 |
| 4250 // Update the configuration. |
| 4251 stream_->UpdateAudioConfig(new_config); |
| 4252 |
| 4253 // We haven't read any buffers at this point, so the config for the next |
| 4254 // buffer at time 0 should still be the original config. |
| 4255 CheckAudioConfig(audio_config_); |
| 4256 |
| 4257 // Append new audio containing preroll and using the new config. |
| 4258 EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(7000, 6000, 2000)); |
| 4259 NewCodedFrameGroupAppend("7P 8K"); |
| 4260 |
| 4261 // Check buffers from the first append. |
| 4262 CheckExpectedBuffers("0K 3K 6K"); |
| 4263 |
| 4264 // Verify the next attempt to get a buffer will signal that a config change |
| 4265 // has happened. |
| 4266 scoped_refptr<StreamParserBuffer> buffer; |
| 4267 EXPECT_EQ(SourceBufferStream::kConfigChange, stream_->GetNextBuffer(&buffer)); |
| 4268 |
| 4269 // Verify upcoming buffers will use the new config. |
| 4270 CheckAudioConfig(new_config); |
| 4271 |
| 4272 // Check buffers from the second append, including preroll. |
| 4273 // CheckExpectedBuffers("6P 7K 8K"); |
| 4274 CheckExpectedBuffers("7P 8K"); |
| 4275 |
| 4276 CheckNoNextBuffer(); |
| 4277 } |
| 4278 |
4397 TEST_F(SourceBufferStreamTest, BFrames) { | 4279 TEST_F(SourceBufferStreamTest, BFrames) { |
4398 Seek(0); | 4280 Seek(0); |
4399 NewCodedFrameGroupAppend("0K 120|30 30|60 60|90 90|120"); | 4281 NewCodedFrameGroupAppend("0K 120|30 30|60 60|90 90|120"); |
4400 CheckExpectedRangesByTimestamp("{ [0,150) }"); | 4282 CheckExpectedRangesByTimestamp("{ [0,150) }"); |
4401 | 4283 |
4402 CheckExpectedBuffers("0K 120|30 30|60 60|90 90|120"); | 4284 CheckExpectedBuffers("0K 120|30 30|60 60|90 90|120"); |
4403 CheckNoNextBuffer(); | 4285 CheckNoNextBuffer(); |
4404 } | 4286 } |
4405 | 4287 |
4406 TEST_F(SourceBufferStreamTest, RemoveShouldAlwaysExcludeEnd) { | |
4407 NewCodedFrameGroupAppend("10D2K 12D2 14D2"); | |
4408 CheckExpectedRangesByTimestamp("{ [10,16) }"); | |
4409 | |
4410 // Start new coded frame group, appending KF to abut the start of previous | |
4411 // group. | |
4412 NewCodedFrameGroupAppend("0D10K"); | |
4413 Seek(0); | |
4414 CheckExpectedRangesByTimestamp("{ [0,16) }"); | |
4415 CheckExpectedBuffers("0K 10K 12 14"); | |
4416 CheckNoNextBuffer(); | |
4417 | |
4418 // Append another buffer with the same timestamp as the last KF. This triggers | |
4419 // special logic that allows two buffers to have the same timestamp. When | |
4420 // preparing for this new append, there is no reason to remove the later GOP | |
4421 // starting at timestamp 10. This verifies the fix for http://crbug.com/469325 | |
4422 // where the decision *not* to remove the start of the overlapped range was | |
4423 // erroneously triggering buffers with a timestamp matching the end | |
4424 // of the append (and any later dependent frames) to be removed. | |
4425 AppendBuffers("0D10"); | |
4426 Seek(0); | |
4427 CheckExpectedRangesByTimestamp("{ [0,16) }"); | |
4428 CheckExpectedBuffers("0K 0 10K 12 14"); | |
4429 CheckNoNextBuffer(); | |
4430 } | |
4431 | |
4432 TEST_F(SourceBufferStreamTest, RefinedDurationEstimates_BackOverlap) { | 4288 TEST_F(SourceBufferStreamTest, RefinedDurationEstimates_BackOverlap) { |
4433 // Append a few buffers, the last one having estimated duration. | 4289 // Append a few buffers, the last one having estimated duration. |
4434 NewCodedFrameGroupAppend("0K 5 10 20D10E"); | 4290 NewCodedFrameGroupAppend("0K 5 10 20D10E"); |
4435 CheckExpectedRangesByTimestamp("{ [0,30) }"); | 4291 CheckExpectedRangesByTimestamp("{ [0,30) }"); |
4436 Seek(0); | 4292 Seek(0); |
4437 CheckExpectedBuffers("0K 5 10 20D10E"); | 4293 CheckExpectedBuffers("0K 5 10 20D10E"); |
4438 CheckNoNextBuffer(); | 4294 CheckNoNextBuffer(); |
4439 | 4295 |
4440 // Append a buffer to the end that overlaps the *back* of the existing range. | 4296 // Append a buffer to the end that overlaps the *back* of the existing range. |
4441 // This should trigger the estimated duration to be recomputed as a timestamp | 4297 // 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... |
4870 EXPECT_EQ(base::TimeDelta(), stream_->GetHighestPresentationTimestamp()); | 4726 EXPECT_EQ(base::TimeDelta(), stream_->GetHighestPresentationTimestamp()); |
4871 } | 4727 } |
4872 | 4728 |
4873 // TODO(vrk): Add unit tests where keyframes are unaligned between streams. | 4729 // TODO(vrk): Add unit tests where keyframes are unaligned between streams. |
4874 // (crbug.com/133557) | 4730 // (crbug.com/133557) |
4875 | 4731 |
4876 // TODO(vrk): Add unit tests with end of stream being called at interesting | 4732 // TODO(vrk): Add unit tests with end of stream being called at interesting |
4877 // times. | 4733 // times. |
4878 | 4734 |
4879 } // namespace media | 4735 } // namespace media |
OLD | NEW |