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 <algorithm> | 5 #include <algorithm> |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
| 9 #include "base/strings/string_number_conversions.h" | |
| 10 #include "base/strings/string_split.h" | |
| 11 #include "base/strings/string_util.h" | |
| 9 #include "media/base/audio_decoder_config.h" | 12 #include "media/base/audio_decoder_config.h" |
| 10 #include "media/base/decoder_buffer.h" | 13 #include "media/base/decoder_buffer.h" |
| 11 #include "media/base/decrypt_config.h" | 14 #include "media/base/decrypt_config.h" |
| 12 #include "media/base/mock_demuxer_host.h" | 15 #include "media/base/mock_demuxer_host.h" |
| 13 #include "media/base/test_data_util.h" | 16 #include "media/base/test_data_util.h" |
| 14 #include "media/base/test_helpers.h" | 17 #include "media/base/test_helpers.h" |
| 15 #include "media/filters/chunk_demuxer.h" | 18 #include "media/filters/chunk_demuxer.h" |
| 16 #include "media/webm/cluster_builder.h" | 19 #include "media/webm/cluster_builder.h" |
| 17 #include "media/webm/webm_constants.h" | 20 #include "media/webm/webm_constants.h" |
| 18 #include "media/webm/webm_crypto_helpers.h" | 21 #include "media/webm/webm_crypto_helpers.h" |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 AppendData(kSourceId, data, length); | 285 AppendData(kSourceId, data, length); |
| 283 } | 286 } |
| 284 | 287 |
| 285 void AppendCluster(int timecode, int block_count) { | 288 void AppendCluster(int timecode, int block_count) { |
| 286 scoped_ptr<Cluster> cluster(GenerateCluster(timecode, block_count)); | 289 scoped_ptr<Cluster> cluster(GenerateCluster(timecode, block_count)); |
| 287 AppendData(kSourceId, cluster->data(), cluster->size()); | 290 AppendData(kSourceId, cluster->data(), cluster->size()); |
| 288 } | 291 } |
| 289 | 292 |
| 290 void AppendSingleStreamCluster(const std::string& source_id, int track_number, | 293 void AppendSingleStreamCluster(const std::string& source_id, int track_number, |
| 291 int timecode, int block_count) { | 294 int timecode, int block_count) { |
| 292 static const int kVideoTrackNum = 1; | |
| 293 static const int kAudioTrackNum = 2; | |
| 294 | |
| 295 static const int kAudioBlockDuration = 23; | |
| 296 static const int kVideoBlockDuration = 33; | |
| 297 | |
| 298 int block_duration = 0; | 295 int block_duration = 0; |
| 299 switch(track_number) { | 296 switch(track_number) { |
| 300 case kVideoTrackNum: | 297 case kVideoTrackNum: |
| 301 block_duration = kVideoBlockDuration; | 298 block_duration = kVideoBlockDuration; |
| 302 break; | 299 break; |
| 303 case kAudioTrackNum: | 300 case kAudioTrackNum: |
| 304 block_duration = kAudioBlockDuration; | 301 block_duration = kAudioBlockDuration; |
| 305 break; | 302 break; |
| 306 } | 303 } |
| 307 ASSERT_NE(block_duration, 0); | 304 ASSERT_NE(block_duration, 0); |
| 308 int end_timecode = timecode + block_count * block_duration; | 305 int end_timecode = timecode + block_count * block_duration; |
| 309 scoped_ptr<Cluster> cluster(GenerateSingleStreamCluster( | 306 scoped_ptr<Cluster> cluster(GenerateSingleStreamCluster( |
| 310 timecode, end_timecode, track_number, block_duration)); | 307 timecode, end_timecode, track_number, block_duration)); |
| 311 AppendData(source_id, cluster->data(), cluster->size()); | 308 AppendData(source_id, cluster->data(), cluster->size()); |
| 312 } | 309 } |
| 313 | 310 |
| 311 void AppendSingleStreamCluster(const std::string& source_id, int track_number, | |
| 312 const std::string& cluster_description) { | |
| 313 std::vector<std::string> timestamps; | |
| 314 base::SplitString(cluster_description, ' ', ×tamps); | |
| 315 | |
| 316 ClusterBuilder cb; | |
| 317 std::vector<uint8> data(10); | |
| 318 for (size_t i = 0; i < timestamps.size(); ++i) { | |
| 319 std::string timestampStr = timestamps[i]; | |
|
scherkus (not reviewing)
2013/07/24 22:47:41
unix_hacker for timestampStr
acolwell GONE FROM CHROMIUM
2013/07/25 20:39:33
Done.
| |
| 320 int block_flags = 0; | |
| 321 if (EndsWith(timestampStr, "K", true)) { | |
| 322 block_flags = kWebMFlagKeyframe; | |
| 323 // Remove the "K" off of the token. | |
| 324 timestampStr = timestampStr.substr(0, timestamps[i].length() - 1); | |
| 325 } | |
| 326 int timestamp_in_ms; | |
| 327 CHECK(base::StringToInt(timestampStr, ×tamp_in_ms)); | |
| 328 | |
| 329 if (i == 0) | |
| 330 cb.SetClusterTimecode(timestamp_in_ms); | |
| 331 | |
| 332 cb.AddSimpleBlock(track_number, timestamp_in_ms, block_flags, | |
| 333 &data[0], data.size()); | |
| 334 } | |
| 335 scoped_ptr<Cluster> cluster(cb.Finish()); | |
|
scherkus (not reviewing)
2013/07/24 22:47:41
allocate on stack?
acolwell GONE FROM CHROMIUM
2013/07/25 20:39:33
That would actually require changing the ClusterBu
| |
| 336 AppendData(source_id, cluster->data(), cluster->size()); | |
| 337 } | |
| 314 | 338 |
| 315 void AppendData(const std::string& source_id, | 339 void AppendData(const std::string& source_id, |
| 316 const uint8* data, size_t length) { | 340 const uint8* data, size_t length) { |
| 317 EXPECT_CALL(host_, AddBufferedTimeRange(_, _)).Times(AnyNumber()); | 341 EXPECT_CALL(host_, AddBufferedTimeRange(_, _)).Times(AnyNumber()); |
| 318 demuxer_->AppendData(source_id, data, length); | 342 demuxer_->AppendData(source_id, data, length); |
| 319 } | 343 } |
| 320 | 344 |
| 321 void AppendDataInPieces(const uint8* data, size_t length) { | 345 void AppendDataInPieces(const uint8* data, size_t length) { |
| 322 AppendDataInPieces(data, length, 7); | 346 AppendDataInPieces(data, length, 7); |
| 323 } | 347 } |
| (...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 726 message_loop_.RunUntilIdle(); | 750 message_loop_.RunUntilIdle(); |
| 727 } | 751 } |
| 728 | 752 |
| 729 void ExpectConfigChanged(DemuxerStream::Type type) { | 753 void ExpectConfigChanged(DemuxerStream::Type type) { |
| 730 EXPECT_CALL(*this, ReadDone(DemuxerStream::kConfigChanged, _)); | 754 EXPECT_CALL(*this, ReadDone(DemuxerStream::kConfigChanged, _)); |
| 731 demuxer_->GetStream(type)->Read(base::Bind( | 755 demuxer_->GetStream(type)->Read(base::Bind( |
| 732 &ChunkDemuxerTest::ReadDone, base::Unretained(this))); | 756 &ChunkDemuxerTest::ReadDone, base::Unretained(this))); |
| 733 message_loop_.RunUntilIdle(); | 757 message_loop_.RunUntilIdle(); |
| 734 } | 758 } |
| 735 | 759 |
| 760 void CheckExpectedBuffers(DemuxerStream* stream, const std::string expected) { | |
|
scherkus (not reviewing)
2013/07/24 22:47:41
missing & From std::string
acolwell GONE FROM CHROMIUM
2013/07/25 20:39:33
Done.
| |
| 761 std::vector<std::string> timestamps; | |
| 762 base::SplitString(expected, ' ', ×tamps); | |
| 763 std::stringstream ss; | |
| 764 for (size_t i = 0; i < timestamps.size(); ++i) { | |
| 765 DemuxerStream::Status status; | |
| 766 scoped_refptr<DecoderBuffer> buffer; | |
| 767 stream->Read(base::Bind(&ChunkDemuxerTest::StoreStatusAndBuffer, | |
| 768 base::Unretained(this), &status, &buffer)); | |
| 769 base::MessageLoop::current()->RunUntilIdle(); | |
| 770 if (status != DemuxerStream::kOk || buffer->end_of_stream()) | |
| 771 break; | |
| 772 | |
| 773 if (i > 0) | |
| 774 ss << " "; | |
| 775 ss << buffer->timestamp().InMilliseconds(); | |
| 776 } | |
| 777 EXPECT_EQ(expected, ss.str()); | |
| 778 } | |
| 779 | |
| 736 MOCK_METHOD1(Checkpoint, void(int id)); | 780 MOCK_METHOD1(Checkpoint, void(int id)); |
| 737 | 781 |
| 738 struct BufferTimestamps { | 782 struct BufferTimestamps { |
| 739 int video_time_ms; | 783 int video_time_ms; |
| 740 int audio_time_ms; | 784 int audio_time_ms; |
| 741 }; | 785 }; |
| 742 static const int kSkip = -1; | 786 static const int kSkip = -1; |
| 743 | 787 |
| 744 // Test parsing a WebM file. | 788 // Test parsing a WebM file. |
| 745 // |filename| - The name of the file in media/test/data to parse. | 789 // |filename| - The name of the file in media/test/data to parse. |
| (...skipping 1917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2663 EXPECT_CALL(*this, DemuxerOpened()); | 2707 EXPECT_CALL(*this, DemuxerOpened()); |
| 2664 demuxer_->Initialize( | 2708 demuxer_->Initialize( |
| 2665 &host_, CreateInitDoneCB(kNoTimestamp(), PIPELINE_OK)); | 2709 &host_, CreateInitDoneCB(kNoTimestamp(), PIPELINE_OK)); |
| 2666 | 2710 |
| 2667 EXPECT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, true, true)); | 2711 EXPECT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, true, true)); |
| 2668 | 2712 |
| 2669 demuxer_->Remove(kSourceId, base::TimeDelta::FromMilliseconds(0), | 2713 demuxer_->Remove(kSourceId, base::TimeDelta::FromMilliseconds(0), |
| 2670 base::TimeDelta::FromMilliseconds(1)); | 2714 base::TimeDelta::FromMilliseconds(1)); |
| 2671 } | 2715 } |
| 2672 | 2716 |
| 2717 TEST_F(ChunkDemuxerTest, AppendWindow) { | |
| 2718 ASSERT_TRUE(InitDemuxer(false, true)); | |
| 2719 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); | |
| 2720 | |
| 2721 // Set the append window to [20,280) | |
|
scherkus (not reviewing)
2013/07/24 22:47:41
period
acolwell GONE FROM CHROMIUM
2013/07/25 20:39:33
Done.
| |
| 2722 demuxer_->SetAppendWindowStart(kSourceId, | |
| 2723 base::TimeDelta::FromMilliseconds(20)); | |
| 2724 demuxer_->SetAppendWindowEnd(kSourceId, | |
| 2725 base::TimeDelta::FromMilliseconds(280)); | |
| 2726 | |
| 2727 // Append a cluster that starts before and ends after the append window. | |
| 2728 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, | |
| 2729 "0K 30 60 90 120K 150 180 210 240K 270 300 330K"); | |
| 2730 | |
| 2731 // Verify that GOPs that start outside the window are not included | |
| 2732 // in the buffer. Also verify that buffers that extend beyond the | |
| 2733 // window are not included. | |
| 2734 CheckExpectedRanges(kSourceId, "{ [120,300) }"); | |
| 2735 CheckExpectedBuffers(stream, "120 150 180 210 240 270"); | |
| 2736 | |
| 2737 // Extend the append window to [20,650). | |
| 2738 demuxer_->SetAppendWindowEnd(kSourceId, | |
| 2739 base::TimeDelta::FromMilliseconds(650)); | |
| 2740 | |
| 2741 // Append more data and verify that adding buffers start at the next | |
| 2742 // keyframe. | |
| 2743 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, | |
| 2744 "360 390 420K 450 480 510 540K 570 600 630K"); | |
| 2745 CheckExpectedRanges(kSourceId, "{ [120,300) [420,660) }"); | |
| 2746 } | |
| 2747 | |
| 2673 } // namespace media | 2748 } // namespace media |
| OLD | NEW |