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 |