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 <deque> | 5 #include <deque> |
| 6 | 6 |
| 7 #include "base/file_path.h" | 7 #include "base/file_path.h" |
| 8 #include "base/path_service.h" | 8 #include "base/path_service.h" |
| 9 #include "base/threading/thread.h" | 9 #include "base/threading/thread.h" |
| 10 #include "media/base/filters.h" | 10 #include "media/base/filters.h" |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 34 MATCHER(IsEndOfStreamBuffer, | 34 MATCHER(IsEndOfStreamBuffer, |
| 35 std::string(negation ? "isn't" : "is") + " end of stream") { | 35 std::string(negation ? "isn't" : "is") + " end of stream") { |
| 36 return arg->IsEndOfStream(); | 36 return arg->IsEndOfStream(); |
| 37 } | 37 } |
| 38 | 38 |
| 39 // Fixture class to facilitate writing tests. Takes care of setting up the | 39 // Fixture class to facilitate writing tests. Takes care of setting up the |
| 40 // FFmpeg, pipeline and filter host mocks. | 40 // FFmpeg, pipeline and filter host mocks. |
| 41 class FFmpegDemuxerTest : public testing::Test { | 41 class FFmpegDemuxerTest : public testing::Test { |
| 42 protected: | 42 protected: |
| 43 | 43 |
| 44 FFmpegDemuxerTest() { | 44 FFmpegDemuxerTest() {} |
| 45 // Create an FFmpegDemuxer with local data source. | |
| 46 demuxer_ = new FFmpegDemuxer(&message_loop_, true); | |
| 47 demuxer_->disable_first_seek_hack_for_testing(); | |
| 48 | |
| 49 // Inject a filter host and message loop and prepare a data source. | |
| 50 demuxer_->set_host(&host_); | |
| 51 | |
| 52 EXPECT_CALL(host_, SetTotalBytes(_)).Times(AnyNumber()); | |
| 53 EXPECT_CALL(host_, SetBufferedBytes(_)).Times(AnyNumber()); | |
| 54 EXPECT_CALL(host_, SetCurrentReadPosition(_)) | |
| 55 .WillRepeatedly(SaveArg<0>(¤t_read_position_)); | |
| 56 } | |
| 57 | 45 |
| 58 virtual ~FFmpegDemuxerTest() { | 46 virtual ~FFmpegDemuxerTest() { |
| 59 if (demuxer_) { | 47 if (demuxer_) { |
| 60 // Call Stop() to shut down internal threads. | 48 // Call Stop() to shut down internal threads. |
| 61 demuxer_->Stop(NewExpectedClosure()); | 49 demuxer_->Stop(NewExpectedClosure()); |
| 62 } | 50 } |
| 63 | 51 |
| 64 // Finish up any remaining tasks. | 52 // Finish up any remaining tasks. |
| 65 message_loop_.RunAllPending(); | 53 message_loop_.RunAllPending(); |
| 66 // Release the reference to the demuxer. | 54 // Release the reference to the demuxer. |
| 67 demuxer_ = NULL; | 55 demuxer_ = NULL; |
| 68 } | 56 } |
| 69 | 57 |
| 70 scoped_refptr<FileDataSource> CreateDataSource(const std::string& name) { | 58 void CreateDemuxer(const std::string& name) { |
| 71 return CreateDataSource(name, false); | 59 CreateDemuxer(name, false); |
| 72 } | 60 } |
| 73 | 61 |
| 74 scoped_refptr<FileDataSource> CreateDataSource(const std::string& name, | 62 void CreateDemuxer(const std::string& name, bool disable_file_size) { |
| 75 bool disable_file_size) { | 63 CHECK(!demuxer_); |
| 76 FilePath file_path; | |
| 77 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path)); | |
| 78 | 64 |
| 79 file_path = file_path.Append(FILE_PATH_LITERAL("media")) | 65 EXPECT_CALL(host_, SetTotalBytes(_)).Times(AnyNumber()); |
| 80 .Append(FILE_PATH_LITERAL("test")) | 66 EXPECT_CALL(host_, SetBufferedBytes(_)).Times(AnyNumber()); |
| 81 .Append(FILE_PATH_LITERAL("data")) | 67 EXPECT_CALL(host_, SetCurrentReadPosition(_)) |
| 82 .AppendASCII(name); | 68 .WillRepeatedly(SaveArg<0>(¤t_read_position_)); |
| 83 | 69 |
| 84 scoped_refptr<FileDataSource> data_source = new FileDataSource( | 70 CreateDataSource(name, disable_file_size); |
| 85 disable_file_size); | |
| 86 | 71 |
| 87 EXPECT_EQ(PIPELINE_OK, data_source->Initialize(file_path.MaybeAsASCII())); | 72 // Create an FFmpegDemuxer with local data source. |
| 73 demuxer_ = new FFmpegDemuxer(&message_loop_, data_source_, true); | |
| 74 demuxer_->disable_first_seek_hack_for_testing(); | |
| 88 | 75 |
| 89 return data_source.get(); | 76 // Inject a filter host and message loop and prepare a data source. |
| 77 demuxer_->set_host(&host_); | |
| 90 } | 78 } |
| 91 | 79 |
| 92 MOCK_METHOD1(CheckPoint, void(int v)); | 80 MOCK_METHOD1(CheckPoint, void(int v)); |
| 93 | 81 |
| 94 // Initializes FFmpegDemuxer. | 82 void InitializeDemuxer() { |
| 95 void InitializeDemuxer(const scoped_refptr<DataSource>& data_source) { | |
| 96 EXPECT_CALL(host_, SetDuration(_)); | 83 EXPECT_CALL(host_, SetDuration(_)); |
| 97 demuxer_->Initialize(data_source, NewExpectedStatusCB(PIPELINE_OK)); | 84 demuxer_->Initialize(NewExpectedStatusCB(PIPELINE_OK)); |
| 98 message_loop_.RunAllPending(); | 85 message_loop_.RunAllPending(); |
| 99 } | 86 } |
| 100 | 87 |
| 101 // Verifies that |buffer| has a specific |size| and |timestamp|. | 88 // Verifies that |buffer| has a specific |size| and |timestamp|. |
| 102 // |location| simply indicates where the call to this function was made. | 89 // |location| simply indicates where the call to this function was made. |
| 103 // This makes it easier to track down where test failures occur. | 90 // This makes it easier to track down where test failures occur. |
| 104 void ValidateBuffer(const tracked_objects::Location& location, | 91 void ValidateBuffer(const tracked_objects::Location& location, |
| 105 const scoped_refptr<Buffer>& buffer, | 92 const scoped_refptr<Buffer>& buffer, |
| 106 int size, int64 timestampInMicroseconds) { | 93 int size, int64 timestampInMicroseconds) { |
| 107 std::string location_str; | 94 std::string location_str; |
| 108 location.Write(true, false, &location_str); | 95 location.Write(true, false, &location_str); |
| 109 location_str += "\n"; | 96 location_str += "\n"; |
| 110 SCOPED_TRACE(location_str); | 97 SCOPED_TRACE(location_str); |
| 111 EXPECT_TRUE(buffer.get() != NULL); | 98 EXPECT_TRUE(buffer.get() != NULL); |
| 112 EXPECT_EQ(size, buffer->GetDataSize()); | 99 EXPECT_EQ(size, buffer->GetDataSize()); |
| 113 EXPECT_EQ(base::TimeDelta::FromMicroseconds(timestampInMicroseconds), | 100 EXPECT_EQ(base::TimeDelta::FromMicroseconds(timestampInMicroseconds), |
| 114 buffer->GetTimestamp()); | 101 buffer->GetTimestamp()); |
| 115 } | 102 } |
| 116 | 103 |
| 117 // Creates a data source with the given |file_name|. If |disable_file_size| | 104 // Creates a data source with the given |file_name|. If |disable_file_size| |
| 118 // then the data source pretends it does not know the file size (e.g. often | 105 // then the data source pretends it does not know the file size (e.g. often |
| 119 // when streaming video). Uses this data source to initialize a demuxer, then | 106 // when streaming video). Uses this data source to initialize a demuxer, then |
| 120 // returns true if the bitrate is valid, false otherwise. | 107 // returns true if the bitrate is valid, false otherwise. |
| 121 bool VideoHasValidBitrate( | 108 bool VideoHasValidBitrate( |
| 122 const std::string& file_name, bool disable_file_size) { | 109 const std::string& file_name, bool disable_file_size) { |
| 123 scoped_refptr<FileDataSource> data_source = | 110 CreateDemuxer(file_name, disable_file_size); |
| 124 CreateDataSource(file_name, disable_file_size); | 111 InitializeDemuxer(); |
| 125 InitializeDemuxer(data_source); | |
| 126 return demuxer_->GetBitrate() > 0; | 112 return demuxer_->GetBitrate() > 0; |
| 127 } | 113 } |
| 128 | 114 |
| 129 bool IsStreamStopped(DemuxerStream::Type type) { | 115 bool IsStreamStopped(DemuxerStream::Type type) { |
| 130 DemuxerStream* stream = demuxer_->GetStream(type); | 116 DemuxerStream* stream = demuxer_->GetStream(type); |
| 131 CHECK(stream); | 117 CHECK(stream); |
| 132 return static_cast<FFmpegDemuxerStream*>(stream)->stopped_; | 118 return static_cast<FFmpegDemuxerStream*>(stream)->stopped_; |
| 133 } | 119 } |
| 134 | 120 |
| 135 // Fixture members. | 121 // Fixture members. |
| 122 scoped_refptr<FileDataSource> data_source_; | |
| 136 scoped_refptr<FFmpegDemuxer> demuxer_; | 123 scoped_refptr<FFmpegDemuxer> demuxer_; |
| 137 StrictMock<MockDemuxerHost> host_; | 124 StrictMock<MockDemuxerHost> host_; |
| 138 MessageLoop message_loop_; | 125 MessageLoop message_loop_; |
| 139 | 126 |
| 140 int64 current_read_position_; | 127 int64 current_read_position_; |
| 141 | 128 |
| 142 private: | 129 private: |
| 130 void CreateDataSource(const std::string& name, bool disable_file_size) { | |
| 131 CHECK(!data_source_); | |
| 132 | |
| 133 FilePath file_path; | |
| 134 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path)); | |
| 135 | |
| 136 file_path = file_path.Append(FILE_PATH_LITERAL("media")) | |
| 137 .Append(FILE_PATH_LITERAL("test")) | |
| 138 .Append(FILE_PATH_LITERAL("data")) | |
| 139 .AppendASCII(name); | |
| 140 | |
| 141 data_source_ = new FileDataSource(disable_file_size); | |
| 142 EXPECT_EQ(PIPELINE_OK, data_source_->Initialize(file_path.MaybeAsASCII())); | |
| 143 } | |
| 144 | |
| 143 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest); | 145 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest); |
| 144 }; | 146 }; |
| 145 | 147 |
| 146 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) { | 148 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) { |
| 147 // Simulate avformat_open_input() failing. | 149 // Simulate avformat_open_input() failing. |
| 150 CreateDemuxer("ten_byte_file"), | |
| 148 EXPECT_CALL(host_, SetCurrentReadPosition(_)); | 151 EXPECT_CALL(host_, SetCurrentReadPosition(_)); |
| 149 demuxer_->Initialize(CreateDataSource("ten_byte_file"), | 152 demuxer_->Initialize(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); |
| 150 NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); | |
| 151 | 153 |
| 152 message_loop_.RunAllPending(); | 154 message_loop_.RunAllPending(); |
| 153 } | 155 } |
| 154 | 156 |
| 155 // TODO(acolwell): Uncomment this test when we discover a file that passes | 157 // TODO(acolwell): Uncomment this test when we discover a file that passes |
| 156 // avformat_open_input(), but has avformat_find_stream_info() fail. | 158 // avformat_open_input(), but has avformat_find_stream_info() fail. |
| 157 // | 159 // |
| 158 //TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) { | 160 //TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) { |
| 161 // CreateDemuxer("find_stream_info_fail.webm"); | |
| 159 // demuxer_->Initialize( | 162 // demuxer_->Initialize( |
| 160 // CreateDataSource("find_stream_info_fail.webm"), | |
| 161 // NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE)); | 163 // NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE)); |
| 162 // message_loop_.RunAllPending(); | 164 // message_loop_.RunAllPending(); |
| 163 //} | 165 //} |
| 164 | 166 |
| 165 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) { | 167 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) { |
| 166 // Open a file with no streams whatsoever. | 168 // Open a file with no streams whatsoever. |
| 169 CreateDemuxer("no_streams.webm"); | |
| 167 EXPECT_CALL(host_, SetCurrentReadPosition(_)); | 170 EXPECT_CALL(host_, SetCurrentReadPosition(_)); |
| 168 demuxer_->Initialize( | 171 demuxer_->Initialize( |
| 169 CreateDataSource("no_streams.webm"), | |
| 170 NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); | 172 NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); |
| 171 message_loop_.RunAllPending(); | 173 message_loop_.RunAllPending(); |
| 172 } | 174 } |
| 173 | 175 |
| 174 TEST_F(FFmpegDemuxerTest, Initialize_NoAudioVideo) { | 176 TEST_F(FFmpegDemuxerTest, Initialize_NoAudioVideo) { |
| 175 // Open a file containing streams but none of which are audio/video streams. | 177 // Open a file containing streams but none of which are audio/video streams. |
| 178 CreateDemuxer("no_audio_video.webm"); | |
| 176 demuxer_->Initialize( | 179 demuxer_->Initialize( |
| 177 CreateDataSource("no_audio_video.webm"), | |
| 178 NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); | 180 NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); |
| 179 message_loop_.RunAllPending(); | 181 message_loop_.RunAllPending(); |
| 180 } | 182 } |
| 181 | 183 |
| 182 TEST_F(FFmpegDemuxerTest, Initialize_Successful) { | 184 TEST_F(FFmpegDemuxerTest, Initialize_Successful) { |
| 183 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); | 185 CreateDemuxer("bear-320x240.webm"); |
| 186 InitializeDemuxer(); | |
| 184 | 187 |
| 185 // Video stream should be present. | 188 // Video stream should be present. |
| 186 scoped_refptr<DemuxerStream> stream = | 189 scoped_refptr<DemuxerStream> stream = |
| 187 demuxer_->GetStream(DemuxerStream::VIDEO); | 190 demuxer_->GetStream(DemuxerStream::VIDEO); |
| 188 ASSERT_TRUE(stream); | 191 ASSERT_TRUE(stream); |
| 189 EXPECT_EQ(DemuxerStream::VIDEO, stream->type()); | 192 EXPECT_EQ(DemuxerStream::VIDEO, stream->type()); |
| 190 | 193 |
| 191 const VideoDecoderConfig& video_config = stream->video_decoder_config(); | 194 const VideoDecoderConfig& video_config = stream->video_decoder_config(); |
| 192 EXPECT_EQ(kCodecVP8, video_config.codec()); | 195 EXPECT_EQ(kCodecVP8, video_config.codec()); |
| 193 EXPECT_EQ(VideoFrame::YV12, video_config.format()); | 196 EXPECT_EQ(VideoFrame::YV12, video_config.format()); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 223 | 226 |
| 224 TEST_F(FFmpegDemuxerTest, Initialize_Multitrack) { | 227 TEST_F(FFmpegDemuxerTest, Initialize_Multitrack) { |
| 225 // Open a file containing the following streams: | 228 // Open a file containing the following streams: |
| 226 // Stream #0: Video (VP8) | 229 // Stream #0: Video (VP8) |
| 227 // Stream #1: Audio (Vorbis) | 230 // Stream #1: Audio (Vorbis) |
| 228 // Stream #2: Subtitles (SRT) | 231 // Stream #2: Subtitles (SRT) |
| 229 // Stream #3: Video (Theora) | 232 // Stream #3: Video (Theora) |
| 230 // Stream #4: Audio (16-bit signed little endian PCM) | 233 // Stream #4: Audio (16-bit signed little endian PCM) |
| 231 // | 234 // |
| 232 // We should only pick the first audio/video streams we come across. | 235 // We should only pick the first audio/video streams we come across. |
| 233 InitializeDemuxer(CreateDataSource("bear-320x240-multitrack.webm")); | 236 CreateDemuxer("bear-320x240-multitrack.webm"); |
| 237 InitializeDemuxer(); | |
| 234 | 238 |
| 235 // Video stream should be VP8. | 239 // Video stream should be VP8. |
| 236 scoped_refptr<DemuxerStream> stream = | 240 scoped_refptr<DemuxerStream> stream = |
| 237 demuxer_->GetStream(DemuxerStream::VIDEO); | 241 demuxer_->GetStream(DemuxerStream::VIDEO); |
| 238 ASSERT_TRUE(stream); | 242 ASSERT_TRUE(stream); |
| 239 EXPECT_EQ(DemuxerStream::VIDEO, stream->type()); | 243 EXPECT_EQ(DemuxerStream::VIDEO, stream->type()); |
| 240 EXPECT_EQ(kCodecVP8, stream->video_decoder_config().codec()); | 244 EXPECT_EQ(kCodecVP8, stream->video_decoder_config().codec()); |
| 241 | 245 |
| 242 // Audio stream should be Vorbis. | 246 // Audio stream should be Vorbis. |
| 243 stream = demuxer_->GetStream(DemuxerStream::AUDIO); | 247 stream = demuxer_->GetStream(DemuxerStream::AUDIO); |
| 244 ASSERT_TRUE(stream); | 248 ASSERT_TRUE(stream); |
| 245 EXPECT_EQ(DemuxerStream::AUDIO, stream->type()); | 249 EXPECT_EQ(DemuxerStream::AUDIO, stream->type()); |
| 246 EXPECT_EQ(kCodecVorbis, stream->audio_decoder_config().codec()); | 250 EXPECT_EQ(kCodecVorbis, stream->audio_decoder_config().codec()); |
| 247 | 251 |
| 248 // Unknown stream should never be present. | 252 // Unknown stream should never be present. |
| 249 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::UNKNOWN)); | 253 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::UNKNOWN)); |
| 250 } | 254 } |
| 251 | 255 |
| 252 TEST_F(FFmpegDemuxerTest, Read_Audio) { | 256 TEST_F(FFmpegDemuxerTest, Read_Audio) { |
| 253 // We test that on a successful audio packet read. | 257 // We test that on a successful audio packet read. |
| 254 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); | 258 CreateDemuxer("bear-320x240.webm"); |
| 259 InitializeDemuxer(); | |
| 255 | 260 |
| 256 // Attempt a read from the audio stream and run the message loop until done. | 261 // Attempt a read from the audio stream and run the message loop until done. |
| 257 scoped_refptr<DemuxerStream> audio = | 262 scoped_refptr<DemuxerStream> audio = |
| 258 demuxer_->GetStream(DemuxerStream::AUDIO); | 263 demuxer_->GetStream(DemuxerStream::AUDIO); |
| 259 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); | 264 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); |
| 260 reader->Read(audio); | 265 reader->Read(audio); |
| 261 message_loop_.RunAllPending(); | 266 message_loop_.RunAllPending(); |
| 262 EXPECT_TRUE(reader->called()); | 267 EXPECT_TRUE(reader->called()); |
| 263 ValidateBuffer(FROM_HERE, reader->buffer(), 29, 0); | 268 ValidateBuffer(FROM_HERE, reader->buffer(), 29, 0); |
| 264 | 269 |
| 265 reader->Reset(); | 270 reader->Reset(); |
| 266 reader->Read(audio); | 271 reader->Read(audio); |
| 267 message_loop_.RunAllPending(); | 272 message_loop_.RunAllPending(); |
| 268 EXPECT_TRUE(reader->called()); | 273 EXPECT_TRUE(reader->called()); |
| 269 ValidateBuffer(FROM_HERE, reader->buffer(), 27, 3000); | 274 ValidateBuffer(FROM_HERE, reader->buffer(), 27, 3000); |
| 270 } | 275 } |
| 271 | 276 |
| 272 TEST_F(FFmpegDemuxerTest, Read_Video) { | 277 TEST_F(FFmpegDemuxerTest, Read_Video) { |
| 273 // We test that on a successful video packet read. | 278 // We test that on a successful video packet read. |
| 274 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); | 279 CreateDemuxer("bear-320x240.webm"); |
| 280 InitializeDemuxer(); | |
| 275 | 281 |
| 276 // Attempt a read from the video stream and run the message loop until done. | 282 // Attempt a read from the video stream and run the message loop until done. |
| 277 scoped_refptr<DemuxerStream> video = | 283 scoped_refptr<DemuxerStream> video = |
| 278 demuxer_->GetStream(DemuxerStream::VIDEO); | 284 demuxer_->GetStream(DemuxerStream::VIDEO); |
| 279 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); | 285 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); |
| 280 | 286 |
| 281 reader->Read(video); | 287 reader->Read(video); |
| 282 message_loop_.RunAllPending(); | 288 message_loop_.RunAllPending(); |
| 283 EXPECT_TRUE(reader->called()); | 289 EXPECT_TRUE(reader->called()); |
| 284 ValidateBuffer(FROM_HERE, reader->buffer(), 22084, 0); | 290 ValidateBuffer(FROM_HERE, reader->buffer(), 22084, 0); |
| 285 | 291 |
| 286 reader->Reset(); | 292 reader->Reset(); |
| 287 reader->Read(video); | 293 reader->Read(video); |
| 288 message_loop_.RunAllPending(); | 294 message_loop_.RunAllPending(); |
| 289 EXPECT_TRUE(reader->called()); | 295 EXPECT_TRUE(reader->called()); |
| 290 ValidateBuffer(FROM_HERE, reader->buffer(), 1057, 33000); | 296 ValidateBuffer(FROM_HERE, reader->buffer(), 1057, 33000); |
| 291 } | 297 } |
| 292 | 298 |
| 293 TEST_F(FFmpegDemuxerTest, Read_VideoNonZeroStart) { | 299 TEST_F(FFmpegDemuxerTest, Read_VideoNonZeroStart) { |
| 294 // Test the start time is the first timestamp of the video and audio stream. | 300 // Test the start time is the first timestamp of the video and audio stream. |
| 295 InitializeDemuxer(CreateDataSource("nonzero-start-time.webm")); | 301 CreateDemuxer("nonzero-start-time.webm"); |
| 302 InitializeDemuxer(); | |
| 296 | 303 |
| 297 // Attempt a read from the video stream and run the message loop until done. | 304 // Attempt a read from the video stream and run the message loop until done. |
| 298 scoped_refptr<DemuxerStream> video = | 305 scoped_refptr<DemuxerStream> video = |
| 299 demuxer_->GetStream(DemuxerStream::VIDEO); | 306 demuxer_->GetStream(DemuxerStream::VIDEO); |
| 300 scoped_refptr<DemuxerStream> audio = | 307 scoped_refptr<DemuxerStream> audio = |
| 301 demuxer_->GetStream(DemuxerStream::AUDIO); | 308 demuxer_->GetStream(DemuxerStream::AUDIO); |
| 302 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); | 309 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); |
| 303 | 310 |
| 304 // Check first buffer in video stream. | 311 // Check first buffer in video stream. |
| 305 reader->Read(video); | 312 reader->Read(video); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 316 ValidateBuffer(FROM_HERE, reader->buffer(), 165, 396000); | 323 ValidateBuffer(FROM_HERE, reader->buffer(), 165, 396000); |
| 317 const base::TimeDelta audio_timestamp = reader->buffer()->GetTimestamp(); | 324 const base::TimeDelta audio_timestamp = reader->buffer()->GetTimestamp(); |
| 318 | 325 |
| 319 // Verify that the start time is equal to the lowest timestamp. | 326 // Verify that the start time is equal to the lowest timestamp. |
| 320 EXPECT_EQ(std::min(audio_timestamp, video_timestamp), | 327 EXPECT_EQ(std::min(audio_timestamp, video_timestamp), |
| 321 demuxer_->GetStartTime()); | 328 demuxer_->GetStartTime()); |
| 322 } | 329 } |
| 323 | 330 |
| 324 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) { | 331 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) { |
| 325 // Verify that end of stream buffers are created. | 332 // Verify that end of stream buffers are created. |
| 326 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); | 333 CreateDemuxer("bear-320x240.webm"); |
| 334 InitializeDemuxer(); | |
| 327 | 335 |
| 328 // We should now expect an end of stream buffer. | 336 // We should now expect an end of stream buffer. |
| 329 scoped_refptr<DemuxerStream> audio = | 337 scoped_refptr<DemuxerStream> audio = |
| 330 demuxer_->GetStream(DemuxerStream::AUDIO); | 338 demuxer_->GetStream(DemuxerStream::AUDIO); |
| 331 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); | 339 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader()); |
| 332 | 340 |
| 333 bool got_eos_buffer = false; | 341 bool got_eos_buffer = false; |
| 334 const int kMaxBuffers = 170; | 342 const int kMaxBuffers = 170; |
| 335 for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) { | 343 for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) { |
| 336 reader->Read(audio); | 344 reader->Read(audio); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 349 EXPECT_GT(reader->buffer()->GetDataSize(), 0); | 357 EXPECT_GT(reader->buffer()->GetDataSize(), 0); |
| 350 reader->Reset(); | 358 reader->Reset(); |
| 351 } | 359 } |
| 352 | 360 |
| 353 EXPECT_TRUE(got_eos_buffer); | 361 EXPECT_TRUE(got_eos_buffer); |
| 354 } | 362 } |
| 355 | 363 |
| 356 TEST_F(FFmpegDemuxerTest, Seek) { | 364 TEST_F(FFmpegDemuxerTest, Seek) { |
| 357 // We're testing that the demuxer frees all queued packets when it receives | 365 // We're testing that the demuxer frees all queued packets when it receives |
| 358 // a Seek(). | 366 // a Seek(). |
| 359 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); | 367 CreateDemuxer("bear-320x240.webm"); |
| 368 InitializeDemuxer(); | |
| 360 | 369 |
| 361 // Get our streams. | 370 // Get our streams. |
| 362 scoped_refptr<DemuxerStream> video = | 371 scoped_refptr<DemuxerStream> video = |
| 363 demuxer_->GetStream(DemuxerStream::VIDEO); | 372 demuxer_->GetStream(DemuxerStream::VIDEO); |
| 364 scoped_refptr<DemuxerStream> audio = | 373 scoped_refptr<DemuxerStream> audio = |
| 365 demuxer_->GetStream(DemuxerStream::AUDIO); | 374 demuxer_->GetStream(DemuxerStream::AUDIO); |
| 366 ASSERT_TRUE(video); | 375 ASSERT_TRUE(video); |
| 367 ASSERT_TRUE(audio); | 376 ASSERT_TRUE(audio); |
| 368 | 377 |
| 369 // Read a video packet and release it. | 378 // Read a video packet and release it. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 427 MOCK_METHOD0(OnDelete, void()); | 436 MOCK_METHOD0(OnDelete, void()); |
| 428 MOCK_METHOD1(Run, void(const scoped_refptr<Buffer>& buffer)); | 437 MOCK_METHOD1(Run, void(const scoped_refptr<Buffer>& buffer)); |
| 429 | 438 |
| 430 private: | 439 private: |
| 431 DISALLOW_COPY_AND_ASSIGN(MockReadCB); | 440 DISALLOW_COPY_AND_ASSIGN(MockReadCB); |
| 432 }; | 441 }; |
| 433 | 442 |
| 434 TEST_F(FFmpegDemuxerTest, Stop) { | 443 TEST_F(FFmpegDemuxerTest, Stop) { |
| 435 // Tests that calling Read() on a stopped demuxer stream immediately deletes | 444 // Tests that calling Read() on a stopped demuxer stream immediately deletes |
| 436 // the callback. | 445 // the callback. |
| 437 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); | 446 CreateDemuxer("bear-320x240.webm"); |
| 447 InitializeDemuxer(); | |
| 438 | 448 |
| 439 // Get our stream. | 449 // Get our stream. |
| 440 scoped_refptr<DemuxerStream> audio = | 450 scoped_refptr<DemuxerStream> audio = |
| 441 demuxer_->GetStream(DemuxerStream::AUDIO); | 451 demuxer_->GetStream(DemuxerStream::AUDIO); |
| 442 ASSERT_TRUE(audio); | 452 ASSERT_TRUE(audio); |
| 443 | 453 |
| 444 demuxer_->Stop(NewExpectedClosure()); | 454 demuxer_->Stop(NewExpectedClosure()); |
| 445 | 455 |
| 446 // Expect all calls in sequence. | 456 // Expect all calls in sequence. |
| 447 InSequence s; | 457 InSequence s; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 463 | 473 |
| 464 // ...and verify that |callback| was deleted. | 474 // ...and verify that |callback| was deleted. |
| 465 CheckPoint(1); | 475 CheckPoint(1); |
| 466 } | 476 } |
| 467 | 477 |
| 468 // The streams can outlive the demuxer because the streams may still be in use | 478 // The streams can outlive the demuxer because the streams may still be in use |
| 469 // by the decoder when the demuxer is destroyed. | 479 // by the decoder when the demuxer is destroyed. |
| 470 // This test verifies that DemuxerStream::Read() does not use an invalid demuxer | 480 // This test verifies that DemuxerStream::Read() does not use an invalid demuxer |
| 471 // pointer (no crash occurs) and calls the callback with an EndOfStream buffer. | 481 // pointer (no crash occurs) and calls the callback with an EndOfStream buffer. |
| 472 TEST_F(FFmpegDemuxerTest, StreamReadAfterStopAndDemuxerDestruction) { | 482 TEST_F(FFmpegDemuxerTest, StreamReadAfterStopAndDemuxerDestruction) { |
| 473 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); | 483 CreateDemuxer("bear-320x240.webm"); |
| 484 InitializeDemuxer(); | |
| 474 | 485 |
| 475 // Get our stream. | 486 // Get our stream. |
| 476 scoped_refptr<DemuxerStream> audio = | 487 scoped_refptr<DemuxerStream> audio = |
| 477 demuxer_->GetStream(DemuxerStream::AUDIO); | 488 demuxer_->GetStream(DemuxerStream::AUDIO); |
| 478 ASSERT_TRUE(audio); | 489 ASSERT_TRUE(audio); |
| 479 | 490 |
| 480 demuxer_->Stop(NewExpectedClosure()); | 491 demuxer_->Stop(NewExpectedClosure()); |
| 481 | 492 |
| 482 // Finish up any remaining tasks. | 493 // Finish up any remaining tasks. |
| 483 message_loop_.RunAllPending(); | 494 message_loop_.RunAllPending(); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 506 | 517 |
| 507 // ...and verify that |callback| was deleted. | 518 // ...and verify that |callback| was deleted. |
| 508 CheckPoint(1); | 519 CheckPoint(1); |
| 509 } | 520 } |
| 510 | 521 |
| 511 TEST_F(FFmpegDemuxerTest, DisableAudioStream) { | 522 TEST_F(FFmpegDemuxerTest, DisableAudioStream) { |
| 512 // We are doing the following things here: | 523 // We are doing the following things here: |
| 513 // 1. Initialize the demuxer with audio and video stream. | 524 // 1. Initialize the demuxer with audio and video stream. |
| 514 // 2. Send a "disable audio stream" message to the demuxer. | 525 // 2. Send a "disable audio stream" message to the demuxer. |
| 515 // 3. Demuxer will free audio packets even if audio stream was initialized. | 526 // 3. Demuxer will free audio packets even if audio stream was initialized. |
| 516 InitializeDemuxer(CreateDataSource("bear-320x240.webm")); | 527 CreateDemuxer("bear-320x240.webm"); |
| 528 InitializeDemuxer(); | |
| 517 | 529 |
| 518 // Submit a "disable audio stream" message to the demuxer. | 530 // Submit a "disable audio stream" message to the demuxer. |
| 519 demuxer_->OnAudioRendererDisabled(); | 531 demuxer_->OnAudioRendererDisabled(); |
| 520 message_loop_.RunAllPending(); | 532 message_loop_.RunAllPending(); |
| 521 | 533 |
| 522 // Get our streams. | 534 // Get our streams. |
| 523 scoped_refptr<DemuxerStream> video = | 535 scoped_refptr<DemuxerStream> video = |
| 524 demuxer_->GetStream(DemuxerStream::VIDEO); | 536 demuxer_->GetStream(DemuxerStream::VIDEO); |
| 525 scoped_refptr<DemuxerStream> audio = | 537 scoped_refptr<DemuxerStream> audio = |
| 526 demuxer_->GetStream(DemuxerStream::AUDIO); | 538 demuxer_->GetStream(DemuxerStream::AUDIO); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 541 // Attempt a read from the audio stream: it should immediately return end of | 553 // Attempt a read from the audio stream: it should immediately return end of |
| 542 // stream without requiring the message loop to read data. | 554 // stream without requiring the message loop to read data. |
| 543 reader->Reset(); | 555 reader->Reset(); |
| 544 reader->Read(audio); | 556 reader->Read(audio); |
| 545 ASSERT_TRUE(reader->called()); | 557 ASSERT_TRUE(reader->called()); |
| 546 EXPECT_TRUE(reader->buffer()->IsEndOfStream()); | 558 EXPECT_TRUE(reader->buffer()->IsEndOfStream()); |
| 547 } | 559 } |
| 548 | 560 |
| 549 class MockFFmpegDemuxer : public FFmpegDemuxer { | 561 class MockFFmpegDemuxer : public FFmpegDemuxer { |
| 550 public: | 562 public: |
| 551 explicit MockFFmpegDemuxer(MessageLoop* message_loop) | 563 MockFFmpegDemuxer(MessageLoop* message_loop, |
| 552 : FFmpegDemuxer(message_loop, true) { | 564 const scoped_refptr<DataSource>& data_source) |
| 565 : FFmpegDemuxer(message_loop, data_source, true) { | |
| 553 } | 566 } |
| 554 virtual ~MockFFmpegDemuxer() {} | 567 virtual ~MockFFmpegDemuxer() {} |
| 555 | 568 |
| 556 MOCK_METHOD0(WaitForRead, int()); | 569 MOCK_METHOD0(WaitForRead, int()); |
| 557 MOCK_METHOD1(SignalReadCompleted, void(int size)); | 570 MOCK_METHOD1(SignalReadCompleted, void(int size)); |
| 558 | 571 |
| 559 private: | 572 private: |
| 560 DISALLOW_COPY_AND_ASSIGN(MockFFmpegDemuxer); | 573 DISALLOW_COPY_AND_ASSIGN(MockFFmpegDemuxer); |
| 561 }; | 574 }; |
| 562 | 575 |
| 563 // A gmock helper method to execute the callback and deletes it. | 576 // A gmock helper method to execute the callback and deletes it. |
| 564 void RunCallback(int size, const DataSource::ReadCB& callback) { | 577 void RunCallback(int size, const DataSource::ReadCB& callback) { |
| 565 DCHECK(!callback.is_null()); | 578 DCHECK(!callback.is_null()); |
| 566 callback.Run(size); | 579 callback.Run(size); |
| 567 } | 580 } |
| 568 | 581 |
| 569 TEST_F(FFmpegDemuxerTest, ProtocolRead) { | 582 TEST_F(FFmpegDemuxerTest, ProtocolRead) { |
| 570 scoped_refptr<StrictMock<MockDataSource> > data_source = | 583 scoped_refptr<StrictMock<MockDataSource> > data_source = |
| 571 new StrictMock<MockDataSource>(); | 584 new StrictMock<MockDataSource>(); |
| 572 | 585 |
| 573 EXPECT_CALL(*data_source, Stop(_)) | 586 EXPECT_CALL(*data_source, Stop(_)) |
| 574 .WillRepeatedly(Invoke(&RunStopFilterCallback)); | 587 .WillRepeatedly(Invoke(&RunStopFilterCallback)); |
| 575 | 588 |
| 576 // Creates a demuxer. | 589 // Creates a demuxer. |
| 577 scoped_refptr<MockFFmpegDemuxer> demuxer( | 590 scoped_refptr<MockFFmpegDemuxer> demuxer( |
| 578 new MockFFmpegDemuxer(&message_loop_)); | 591 new MockFFmpegDemuxer(&message_loop_, data_source)); |
| 579 ASSERT_TRUE(demuxer); | |
| 580 demuxer->set_host(&host_); | 592 demuxer->set_host(&host_); |
| 581 demuxer->data_source_ = data_source; | |
| 582 | 593 |
| 583 uint8 kBuffer[1]; | 594 uint8 kBuffer[1]; |
| 584 InSequence s; | 595 InSequence s; |
| 585 // Actions taken in the first read. | 596 // Actions taken in the first read. |
| 586 EXPECT_CALL(*data_source, GetSize(_)) | 597 EXPECT_CALL(*data_source, GetSize(_)) |
| 587 .WillOnce(DoAll(SetArgPointee<0>(1024), Return(true))); | 598 .WillOnce(DoAll(SetArgPointee<0>(1024), Return(true))); |
| 588 EXPECT_CALL(*data_source, Read(0, 512, kBuffer, _)) | 599 EXPECT_CALL(*data_source, Read(0, 512, kBuffer, _)) |
| 589 .WillOnce(WithArgs<1, 3>(Invoke(&RunCallback))); | 600 .WillOnce(WithArgs<1, 3>(Invoke(&RunCallback))); |
| 590 EXPECT_CALL(*demuxer, SignalReadCompleted(512)); | 601 EXPECT_CALL(*demuxer, SignalReadCompleted(512)); |
| 591 EXPECT_CALL(*demuxer, WaitForRead()) | 602 EXPECT_CALL(*demuxer, WaitForRead()) |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 636 | 647 |
| 637 TEST_F(FFmpegDemuxerTest, GetBitrate_SetInContainer_NoFileSize) { | 648 TEST_F(FFmpegDemuxerTest, GetBitrate_SetInContainer_NoFileSize) { |
| 638 EXPECT_TRUE(VideoHasValidBitrate("bear.ogv", true)); | 649 EXPECT_TRUE(VideoHasValidBitrate("bear.ogv", true)); |
| 639 } | 650 } |
| 640 | 651 |
| 641 TEST_F(FFmpegDemuxerTest, GetBitrate_UnsetInContainer_NoFileSize) { | 652 TEST_F(FFmpegDemuxerTest, GetBitrate_UnsetInContainer_NoFileSize) { |
| 642 EXPECT_TRUE(VideoHasValidBitrate("bear-320x240.webm", true)); | 653 EXPECT_TRUE(VideoHasValidBitrate("bear-320x240.webm", true)); |
| 643 } | 654 } |
| 644 | 655 |
| 645 TEST_F(FFmpegDemuxerTest, ProtocolGetSetPosition) { | 656 TEST_F(FFmpegDemuxerTest, ProtocolGetSetPosition) { |
| 646 scoped_refptr<DataSource> data_source = CreateDataSource("bear-320x240.webm"); | 657 CreateDemuxer("bear-320x240.webm"); |
| 647 InitializeDemuxer(data_source); | 658 InitializeDemuxer(); |
| 648 | 659 |
| 649 InSequence s; | 660 InSequence s; |
| 650 | 661 |
| 651 int64 size; | 662 int64 size; |
| 652 int64 position; | 663 int64 position; |
| 653 EXPECT_TRUE(demuxer_->GetSize(&size)); | 664 EXPECT_TRUE(demuxer_->GetSize(&size)); |
| 654 EXPECT_TRUE(demuxer_->GetPosition(&position)); | 665 EXPECT_TRUE(demuxer_->GetPosition(&position)); |
| 655 EXPECT_EQ(current_read_position_, position); | 666 EXPECT_EQ(current_read_position_, position); |
| 656 | 667 |
| 657 EXPECT_TRUE(demuxer_->SetPosition(512)); | 668 EXPECT_TRUE(demuxer_->SetPosition(512)); |
| 658 EXPECT_FALSE(demuxer_->SetPosition(size)); | 669 EXPECT_FALSE(demuxer_->SetPosition(size)); |
| 659 EXPECT_FALSE(demuxer_->SetPosition(size + 1)); | 670 EXPECT_FALSE(demuxer_->SetPosition(size + 1)); |
| 660 EXPECT_FALSE(demuxer_->SetPosition(-1)); | 671 EXPECT_FALSE(demuxer_->SetPosition(-1)); |
| 661 EXPECT_TRUE(demuxer_->GetPosition(&position)); | 672 EXPECT_TRUE(demuxer_->GetPosition(&position)); |
| 662 EXPECT_EQ(512, position); | 673 EXPECT_EQ(512, position); |
| 663 } | 674 } |
| 664 | 675 |
| 665 TEST_F(FFmpegDemuxerTest, ProtocolGetSize) { | 676 TEST_F(FFmpegDemuxerTest, ProtocolGetSize) { |
| 666 scoped_refptr<DataSource> data_source = CreateDataSource("bear-320x240.webm"); | 677 CreateDemuxer("bear-320x240.webm"); |
| 667 InitializeDemuxer(data_source); | 678 InitializeDemuxer(); |
| 668 | 679 |
| 669 int64 data_source_size = 0; | 680 int64 data_source_size = 0; |
| 670 int64 demuxer_size = 0; | 681 int64 demuxer_size = 0; |
| 671 EXPECT_TRUE(data_source->GetSize(&data_source_size)); | 682 EXPECT_TRUE(data_source_->GetSize(&data_source_size)); |
| 672 EXPECT_TRUE(demuxer_->GetSize(&demuxer_size)); | 683 EXPECT_TRUE(demuxer_->GetSize(&demuxer_size)); |
| 673 EXPECT_NE(0, data_source_size); | 684 EXPECT_NE(0, data_source_size); |
| 674 EXPECT_EQ(data_source_size, demuxer_size); | 685 EXPECT_EQ(data_source_size, demuxer_size); |
| 675 } | 686 } |
| 676 | 687 |
| 677 TEST_F(FFmpegDemuxerTest, ProtocolIsStreaming) { | 688 TEST_F(FFmpegDemuxerTest, ProtocolIsStreaming) { |
| 678 scoped_refptr<DataSource> data_source = CreateDataSource("bear-320x240.webm"); | 689 CreateDemuxer("bear-320x240.webm"); |
| 679 InitializeDemuxer(data_source); | 690 InitializeDemuxer(); |
| 680 | 691 |
| 681 EXPECT_FALSE(data_source->IsStreaming()); | 692 EXPECT_FALSE(data_source_->IsStreaming()); |
| 682 EXPECT_FALSE(demuxer_->IsStreaming()); | 693 EXPECT_FALSE(demuxer_->IsStreaming()); |
| 683 } | 694 } |
| 684 | 695 |
| 685 // Verify that seek works properly when the WebM cues data is at the start of | 696 // Verify that seek works properly when the WebM cues data is at the start of |
| 686 // the file instead of at the end. | 697 // the file instead of at the end. |
| 687 TEST_F(FFmpegDemuxerTest, SeekWithCuesBeforeFirstCluster) { | 698 TEST_F(FFmpegDemuxerTest, SeekWithCuesBeforeFirstCluster) { |
| 688 InitializeDemuxer(CreateDataSource("bear-320x240-cues-in-front.webm")); | 699 CreateDemuxer("bear-320x240-cues-in-front.webm"); |
| 700 InitializeDemuxer(); | |
|
acolwell GONE FROM CHROMIUM
2012/03/27 20:11:35
nit: How about making InitializeDemuxer() just tak
| |
| 689 | 701 |
| 690 // Get our streams. | 702 // Get our streams. |
| 691 scoped_refptr<DemuxerStream> video = | 703 scoped_refptr<DemuxerStream> video = |
| 692 demuxer_->GetStream(DemuxerStream::VIDEO); | 704 demuxer_->GetStream(DemuxerStream::VIDEO); |
| 693 scoped_refptr<DemuxerStream> audio = | 705 scoped_refptr<DemuxerStream> audio = |
| 694 demuxer_->GetStream(DemuxerStream::AUDIO); | 706 demuxer_->GetStream(DemuxerStream::AUDIO); |
| 695 ASSERT_TRUE(video); | 707 ASSERT_TRUE(video); |
| 696 ASSERT_TRUE(audio); | 708 ASSERT_TRUE(audio); |
| 697 | 709 |
| 698 // Read a video packet and release it. | 710 // Read a video packet and release it. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 737 message_loop_.RunAllPending(); | 749 message_loop_.RunAllPending(); |
| 738 EXPECT_TRUE(reader->called()); | 750 EXPECT_TRUE(reader->called()); |
| 739 ValidateBuffer(FROM_HERE, reader->buffer(), 1740, 2436000); | 751 ValidateBuffer(FROM_HERE, reader->buffer(), 1740, 2436000); |
| 740 | 752 |
| 741 // Manually release the last reference to the buffer and verify it was freed. | 753 // Manually release the last reference to the buffer and verify it was freed. |
| 742 reader->Reset(); | 754 reader->Reset(); |
| 743 message_loop_.RunAllPending(); | 755 message_loop_.RunAllPending(); |
| 744 } | 756 } |
| 745 | 757 |
| 746 } // namespace media | 758 } // namespace media |
| OLD | NEW |