| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/singleton.h" | 7 #include "base/singleton.h" |
| 8 #include "base/tuple.h" | 8 #include "base/tuple.h" |
| 9 #include "media/base/filter_host.h" | 9 #include "media/base/filter_host.h" |
| 10 #include "media/base/filters.h" | 10 #include "media/base/filters.h" |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 g_seek_event->Signal(); | 158 g_seek_event->Signal(); |
| 159 return g_av_seek_frame; | 159 return g_av_seek_frame; |
| 160 } | 160 } |
| 161 | 161 |
| 162 } // extern "C" | 162 } // extern "C" |
| 163 | 163 |
| 164 using namespace media; | 164 using namespace media; |
| 165 | 165 |
| 166 namespace { | 166 namespace { |
| 167 | 167 |
| 168 void InitializeFFmpegMocks() { | |
| 169 // Initialize function return codes. | |
| 170 g_av_open_input_file = 0; | |
| 171 g_av_find_stream_info = 0; | |
| 172 g_av_read_frame = 0; | |
| 173 | |
| 174 // Initialize AVFormatContext structure. | |
| 175 memset(&g_format, 0, sizeof(g_format)); | |
| 176 | |
| 177 // Initialize AVStream structures. | |
| 178 for (size_t i = 0; i < kMaxStreams; ++i) { | |
| 179 memset(&g_streams[i], 0, sizeof(g_streams[i])); | |
| 180 g_streams[i].time_base.den = 1 * base::Time::kMicrosecondsPerSecond; | |
| 181 g_streams[i].time_base.num = 1; | |
| 182 } | |
| 183 | |
| 184 // Initialize AVCodexContext structures. | |
| 185 memset(&g_audio_codec, 0, sizeof(g_audio_codec)); | |
| 186 g_audio_codec.codec_type = CODEC_TYPE_AUDIO; | |
| 187 g_audio_codec.codec_id = CODEC_ID_VORBIS; | |
| 188 g_audio_codec.channels = 2; | |
| 189 g_audio_codec.sample_rate = 44100; | |
| 190 | |
| 191 memset(&g_video_codec, 0, sizeof(g_video_codec)); | |
| 192 g_video_codec.codec_type = CODEC_TYPE_VIDEO; | |
| 193 g_video_codec.codec_id = CODEC_ID_THEORA; | |
| 194 g_video_codec.height = 720; | |
| 195 g_video_codec.width = 1280; | |
| 196 | |
| 197 memset(&g_data_codec, 0, sizeof(g_data_codec)); | |
| 198 g_data_codec.codec_type = CODEC_TYPE_DATA; | |
| 199 g_data_codec.codec_id = CODEC_ID_NONE; | |
| 200 } | |
| 201 | |
| 202 // Ref counted object so we can create callbacks to call DemuxerStream::Read(). | 168 // Ref counted object so we can create callbacks to call DemuxerStream::Read(). |
| 203 class TestReader : public base::RefCountedThreadSafe<TestReader> { | 169 class TestReader : public base::RefCountedThreadSafe<TestReader> { |
| 204 public: | 170 public: |
| 205 TestReader() | 171 TestReader() |
| 206 : called_(false), | 172 : called_(false), |
| 207 expecting_call_(false), | 173 expecting_call_(false), |
| 208 wait_for_read_(false, false) { | 174 wait_for_read_(false, false) { |
| 209 } | 175 } |
| 210 | 176 |
| 211 virtual ~TestReader() {} | 177 virtual ~TestReader() {} |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 bool called() { return called_; } | 209 bool called() { return called_; } |
| 244 bool expecting_call() { return expecting_call_; } | 210 bool expecting_call() { return expecting_call_; } |
| 245 | 211 |
| 246 private: | 212 private: |
| 247 scoped_refptr<Buffer> buffer_; | 213 scoped_refptr<Buffer> buffer_; |
| 248 bool called_; | 214 bool called_; |
| 249 bool expecting_call_; | 215 bool expecting_call_; |
| 250 base::WaitableEvent wait_for_read_; | 216 base::WaitableEvent wait_for_read_; |
| 251 }; | 217 }; |
| 252 | 218 |
| 219 // Fixture class to facilitate writing tests. Takes care of setting up the |
| 220 // FFmpeg, pipeline and filter host mocks. |
| 221 class FFmpegDemuxerTest : public testing::Test { |
| 222 protected: |
| 223 FFmpegDemuxerTest() {} |
| 224 virtual ~FFmpegDemuxerTest() {} |
| 225 |
| 226 virtual void SetUp() { |
| 227 InitializeFFmpegMocks(); |
| 228 |
| 229 // Create an FFmpegDemuxer. |
| 230 factory_ = FFmpegDemuxer::CreateFilterFactory(); |
| 231 MediaFormat media_format; |
| 232 media_format.SetAsString(MediaFormat::kMimeType, |
| 233 mime_type::kApplicationOctetStream); |
| 234 demuxer_ = factory_->Create<Demuxer>(media_format); |
| 235 DCHECK(demuxer_); |
| 236 |
| 237 // Prepare a filter host and data source for the demuxer. |
| 238 pipeline_.reset(new MockPipeline()); |
| 239 filter_host_.reset(new MockFilterHost<Demuxer>(pipeline_.get(), demuxer_)); |
| 240 MockFilterConfig config; |
| 241 data_source_ = new MockDataSource(&config); |
| 242 } |
| 243 |
| 244 virtual void TearDown() { |
| 245 // Call Stop() to shut down internal threads. |
| 246 demuxer_->Stop(); |
| 247 } |
| 248 |
| 249 // Fixture members. |
| 250 scoped_refptr<FilterFactory> factory_; |
| 251 scoped_refptr<Demuxer> demuxer_; |
| 252 scoped_ptr<MockPipeline> pipeline_; |
| 253 scoped_ptr< MockFilterHost<Demuxer> > filter_host_; |
| 254 scoped_refptr<MockDataSource> data_source_; |
| 255 |
| 256 private: |
| 257 static void InitializeFFmpegMocks() { |
| 258 // Initialize function return codes. |
| 259 g_av_open_input_file = 0; |
| 260 g_av_find_stream_info = 0; |
| 261 g_av_read_frame = 0; |
| 262 |
| 263 // Initialize AVFormatContext structure. |
| 264 memset(&g_format, 0, sizeof(g_format)); |
| 265 |
| 266 // Initialize AVStream structures. |
| 267 for (size_t i = 0; i < kMaxStreams; ++i) { |
| 268 memset(&g_streams[i], 0, sizeof(g_streams[i])); |
| 269 g_streams[i].time_base.den = 1 * base::Time::kMicrosecondsPerSecond; |
| 270 g_streams[i].time_base.num = 1; |
| 271 } |
| 272 |
| 273 // Initialize AVCodexContext structures. |
| 274 memset(&g_audio_codec, 0, sizeof(g_audio_codec)); |
| 275 g_audio_codec.codec_type = CODEC_TYPE_AUDIO; |
| 276 g_audio_codec.codec_id = CODEC_ID_VORBIS; |
| 277 g_audio_codec.channels = 2; |
| 278 g_audio_codec.sample_rate = 44100; |
| 279 |
| 280 memset(&g_video_codec, 0, sizeof(g_video_codec)); |
| 281 g_video_codec.codec_type = CODEC_TYPE_VIDEO; |
| 282 g_video_codec.codec_id = CODEC_ID_THEORA; |
| 283 g_video_codec.height = 720; |
| 284 g_video_codec.width = 1280; |
| 285 |
| 286 memset(&g_data_codec, 0, sizeof(g_data_codec)); |
| 287 g_data_codec.codec_type = CODEC_TYPE_DATA; |
| 288 g_data_codec.codec_id = CODEC_ID_NONE; |
| 289 } |
| 290 |
| 291 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest); |
| 292 }; |
| 293 |
| 253 } // namespace | 294 } // namespace |
| 254 | 295 |
| 255 // TODO(scherkus): http://crbug.com/10863 | 296 TEST(FFmpegDemuxerFactoryTest, Create) { |
| 256 TEST(FFmpegDemuxerTest, DISABLED_InitializeFailure) { | 297 // Should only accept application/octet-stream type. |
| 257 InitializeFFmpegMocks(); | |
| 258 | |
| 259 // Get FFmpegDemuxer's filter factory. | |
| 260 scoped_refptr<FilterFactory> factory = FFmpegDemuxer::CreateFilterFactory(); | 298 scoped_refptr<FilterFactory> factory = FFmpegDemuxer::CreateFilterFactory(); |
| 261 | |
| 262 // Should only accept application/octet-stream type. | |
| 263 MediaFormat media_format; | 299 MediaFormat media_format; |
| 264 media_format.SetAsString(MediaFormat::kMimeType, "foo/x-bar"); | 300 media_format.SetAsString(MediaFormat::kMimeType, "foo/x-bar"); |
| 265 scoped_refptr<Demuxer> demuxer(factory->Create<Demuxer>(media_format)); | 301 scoped_refptr<Demuxer> demuxer(factory->Create<Demuxer>(media_format)); |
| 266 ASSERT_FALSE(demuxer); | 302 ASSERT_FALSE(demuxer); |
| 303 |
| 304 // Try again with application/octet-stream mime type. |
| 267 media_format.Clear(); | 305 media_format.Clear(); |
| 268 media_format.SetAsString(MediaFormat::kMimeType, | 306 media_format.SetAsString(MediaFormat::kMimeType, |
| 269 mime_type::kApplicationOctetStream); | 307 mime_type::kApplicationOctetStream); |
| 270 demuxer = factory->Create<Demuxer>(media_format); | 308 demuxer = factory->Create<Demuxer>(media_format); |
| 271 ASSERT_TRUE(demuxer); | 309 ASSERT_TRUE(demuxer); |
| 310 } |
| 272 | 311 |
| 273 // Prepare a filter host and data source for the demuxer. | 312 TEST_F(FFmpegDemuxerTest, InitializeCouldNotOpen) { |
| 274 MockPipeline pipeline; | |
| 275 scoped_ptr< MockFilterHost<Demuxer> > filter_host; | |
| 276 filter_host.reset(new MockFilterHost<Demuxer>(&pipeline, demuxer)); | |
| 277 MockFilterConfig config; | |
| 278 scoped_refptr<MockDataSource> data_source(new MockDataSource(&config)); | |
| 279 | |
| 280 // Simulate av_open_input_fail failing. | 313 // Simulate av_open_input_fail failing. |
| 281 g_av_open_input_file = AVERROR_IO; | 314 g_av_open_input_file = AVERROR_IO; |
| 282 g_av_find_stream_info = 0; | 315 g_av_find_stream_info = 0; |
| 283 EXPECT_TRUE(demuxer->Initialize(data_source)); | 316 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); |
| 284 EXPECT_TRUE(filter_host->WaitForError(DEMUXER_ERROR_COULD_NOT_OPEN)); | 317 EXPECT_TRUE(filter_host_->WaitForError(DEMUXER_ERROR_COULD_NOT_OPEN)); |
| 285 EXPECT_FALSE(filter_host->IsInitialized()); | 318 EXPECT_FALSE(filter_host_->IsInitialized()); |
| 319 } |
| 286 | 320 |
| 321 TEST_F(FFmpegDemuxerTest, InitializeCouldNotParse) { |
| 287 // Simulate av_find_stream_info failing. | 322 // Simulate av_find_stream_info failing. |
| 288 g_av_open_input_file = 0; | 323 g_av_open_input_file = 0; |
| 289 g_av_find_stream_info = AVERROR_IO; | 324 g_av_find_stream_info = AVERROR_IO; |
| 290 pipeline.Reset(false); | |
| 291 demuxer = factory->Create<Demuxer>(media_format); | |
| 292 filter_host.reset(new MockFilterHost<Demuxer>(&pipeline, demuxer)); | |
| 293 EXPECT_TRUE(demuxer->Initialize(data_source)); | |
| 294 EXPECT_TRUE(filter_host->WaitForError(DEMUXER_ERROR_COULD_NOT_PARSE)); | |
| 295 EXPECT_FALSE(filter_host->IsInitialized()); | |
| 296 | 325 |
| 326 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); |
| 327 EXPECT_TRUE(filter_host_->WaitForError(DEMUXER_ERROR_COULD_NOT_PARSE)); |
| 328 EXPECT_FALSE(filter_host_->IsInitialized()); |
| 329 } |
| 330 |
| 331 TEST_F(FFmpegDemuxerTest, InitializeNoStreams) { |
| 297 // Simulate media with no parseable streams. | 332 // Simulate media with no parseable streams. |
| 298 InitializeFFmpegMocks(); | 333 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); |
| 299 pipeline.Reset(false); | 334 EXPECT_TRUE(filter_host_->WaitForError(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); |
| 300 demuxer = factory->Create<Demuxer>(media_format); | 335 EXPECT_FALSE(filter_host_->IsInitialized()); |
| 301 filter_host.reset(new MockFilterHost<Demuxer>(&pipeline, demuxer)); | 336 } |
| 302 EXPECT_TRUE(demuxer->Initialize(data_source)); | |
| 303 EXPECT_TRUE(filter_host->WaitForError(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); | |
| 304 EXPECT_FALSE(filter_host->IsInitialized()); | |
| 305 | 337 |
| 338 TEST_F(FFmpegDemuxerTest, InitializeDataStreamOnly) { |
| 306 // Simulate media with a data stream but no audio or video streams. | 339 // Simulate media with a data stream but no audio or video streams. |
| 307 g_format.nb_streams = 1; | 340 g_format.nb_streams = 1; |
| 308 g_format.streams[0] = &g_streams[0]; | 341 g_format.streams[0] = &g_streams[0]; |
| 309 g_streams[0].codec = &g_data_codec; | 342 g_streams[0].codec = &g_data_codec; |
| 310 g_streams[0].duration = 10; | 343 g_streams[0].duration = 10; |
| 311 pipeline.Reset(false); | 344 |
| 312 demuxer = factory->Create<Demuxer>(media_format); | 345 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); |
| 313 filter_host.reset(new MockFilterHost<Demuxer>(&pipeline, demuxer)); | 346 EXPECT_TRUE(filter_host_->WaitForError(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); |
| 314 EXPECT_TRUE(demuxer->Initialize(data_source)); | 347 EXPECT_FALSE(filter_host_->IsInitialized()); |
| 315 EXPECT_TRUE(filter_host->WaitForError(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); | |
| 316 EXPECT_FALSE(filter_host->IsInitialized()); | |
| 317 } | 348 } |
| 318 | 349 |
| 319 // TODO(scherkus): http://crbug.com/10863 | 350 TEST_F(FFmpegDemuxerTest, InitializeStreams) { |
| 320 TEST(FFmpegDemuxerTest, DISABLED_InitializeStreams) { | |
| 321 // Simulate media with a data stream, a video stream and audio stream. | 351 // Simulate media with a data stream, a video stream and audio stream. |
| 322 InitializeFFmpegMocks(); | |
| 323 g_format.nb_streams = 3; | 352 g_format.nb_streams = 3; |
| 324 g_format.streams[0] = &g_streams[0]; | 353 g_format.streams[0] = &g_streams[0]; |
| 325 g_format.streams[1] = &g_streams[1]; | 354 g_format.streams[1] = &g_streams[1]; |
| 326 g_format.streams[2] = &g_streams[2]; | 355 g_format.streams[2] = &g_streams[2]; |
| 327 g_streams[0].duration = 1000; | 356 g_streams[0].duration = 1000; |
| 328 g_streams[0].codec = &g_data_codec; | 357 g_streams[0].codec = &g_data_codec; |
| 329 g_streams[1].duration = 100; | 358 g_streams[1].duration = 100; |
| 330 g_streams[1].codec = &g_video_codec; | 359 g_streams[1].codec = &g_video_codec; |
| 331 g_streams[2].duration = 10; | 360 g_streams[2].duration = 10; |
| 332 g_streams[2].codec = &g_audio_codec; | 361 g_streams[2].codec = &g_audio_codec; |
| 333 | 362 |
| 334 // Create our pipeline. | 363 // Initialize the demuxer. |
| 335 MockPipeline pipeline; | 364 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); |
| 336 | 365 EXPECT_TRUE(filter_host_->WaitForInitialized()); |
| 337 // Create our data source. | 366 EXPECT_TRUE(filter_host_->IsInitialized()); |
| 338 MockFilterConfig config; | 367 EXPECT_EQ(PIPELINE_OK, pipeline_->GetError()); |
| 339 scoped_refptr<MockDataSource> data_source = new MockDataSource(&config); | |
| 340 MockFilterHost<DataSource> filter_host_a(&pipeline, data_source); | |
| 341 EXPECT_TRUE(data_source->Initialize("foo")); | |
| 342 EXPECT_TRUE(filter_host_a.IsInitialized()); | |
| 343 | |
| 344 // Create our demuxer. | |
| 345 scoped_refptr<FilterFactory> factory = FFmpegDemuxer::CreateFilterFactory(); | |
| 346 scoped_refptr<Demuxer> demuxer | |
| 347 = factory->Create<Demuxer>(data_source->media_format()); | |
| 348 EXPECT_TRUE(demuxer); | |
| 349 MockFilterHost<Demuxer> filter_host_b(&pipeline, demuxer); | |
| 350 EXPECT_TRUE(demuxer->Initialize(data_source)); | |
| 351 EXPECT_TRUE(filter_host_b.WaitForInitialized()); | |
| 352 EXPECT_TRUE(filter_host_b.IsInitialized()); | |
| 353 EXPECT_EQ(PIPELINE_OK, pipeline.GetError()); | |
| 354 | 368 |
| 355 // Since we ignore data streams, the duration should be equal to the video | 369 // Since we ignore data streams, the duration should be equal to the video |
| 356 // stream's duration. | 370 // stream's duration. |
| 357 EXPECT_EQ(g_streams[1].duration, pipeline.GetDuration().InMicroseconds()); | 371 EXPECT_EQ(g_streams[1].duration, pipeline_->GetDuration().InMicroseconds()); |
| 358 | 372 |
| 359 // Verify that 2 out of 3 streams were created. | 373 // Verify that 2 out of 3 streams were created. |
| 360 EXPECT_EQ(2, demuxer->GetNumberOfStreams()); | 374 EXPECT_EQ(2, demuxer_->GetNumberOfStreams()); |
| 361 | 375 |
| 362 // First stream should be video and support FFmpegDemuxerStream interface. | 376 // First stream should be video and support FFmpegDemuxerStream interface. |
| 363 scoped_refptr<DemuxerStream> stream = demuxer->GetStream(0); | 377 scoped_refptr<DemuxerStream> stream = demuxer_->GetStream(0); |
| 364 scoped_refptr<FFmpegDemuxerStream> ffmpeg_demuxer_stream; | 378 scoped_refptr<FFmpegDemuxerStream> ffmpeg_demuxer_stream; |
| 365 ASSERT_TRUE(stream); | 379 ASSERT_TRUE(stream); |
| 366 std::string mime_type; | 380 std::string mime_type; |
| 367 EXPECT_TRUE( | 381 EXPECT_TRUE( |
| 368 stream->media_format().GetAsString(MediaFormat::kMimeType, &mime_type)); | 382 stream->media_format().GetAsString(MediaFormat::kMimeType, &mime_type)); |
| 369 EXPECT_STREQ(mime_type::kFFmpegVideo, mime_type.c_str()); | 383 EXPECT_STREQ(mime_type::kFFmpegVideo, mime_type.c_str()); |
| 370 EXPECT_TRUE(stream->QueryInterface(&ffmpeg_demuxer_stream)); | 384 EXPECT_TRUE(stream->QueryInterface(&ffmpeg_demuxer_stream)); |
| 371 EXPECT_TRUE(ffmpeg_demuxer_stream); | 385 EXPECT_TRUE(ffmpeg_demuxer_stream); |
| 372 EXPECT_EQ(&g_streams[1], ffmpeg_demuxer_stream->av_stream()); | 386 EXPECT_EQ(&g_streams[1], ffmpeg_demuxer_stream->av_stream()); |
| 373 | 387 |
| 374 // Second stream should be audio and support FFmpegDemuxerStream interface. | 388 // Second stream should be audio and support FFmpegDemuxerStream interface. |
| 375 stream = demuxer->GetStream(1); | 389 stream = demuxer_->GetStream(1); |
| 376 ffmpeg_demuxer_stream = NULL; | 390 ffmpeg_demuxer_stream = NULL; |
| 377 ASSERT_TRUE(stream); | 391 ASSERT_TRUE(stream); |
| 378 EXPECT_TRUE( | 392 EXPECT_TRUE(stream->media_format().GetAsString(MediaFormat::kMimeType, |
| 379 stream->media_format().GetAsString(MediaFormat::kMimeType, &mime_type)); | 393 &mime_type)); |
| 380 EXPECT_STREQ(mime_type::kFFmpegAudio, mime_type.c_str()); | 394 EXPECT_STREQ(mime_type::kFFmpegAudio, mime_type.c_str()); |
| 381 EXPECT_TRUE(stream->QueryInterface(&ffmpeg_demuxer_stream)); | 395 EXPECT_TRUE(stream->QueryInterface(&ffmpeg_demuxer_stream)); |
| 382 EXPECT_TRUE(ffmpeg_demuxer_stream); | 396 EXPECT_TRUE(ffmpeg_demuxer_stream); |
| 383 EXPECT_EQ(&g_streams[2], ffmpeg_demuxer_stream->av_stream()); | 397 EXPECT_EQ(&g_streams[2], ffmpeg_demuxer_stream->av_stream()); |
| 384 } | 398 } |
| 385 | 399 |
| 386 // TODO(scherkus): as we keep refactoring and improving our mocks (both FFmpeg | 400 TEST_F(FFmpegDemuxerTest, ReadAndSeek) { |
| 387 // and pipeline/filters), try to break this test into two. Big issue right now | |
| 388 // is that it takes ~50 lines of code just to set up FFmpegDemuxer. | |
| 389 // | |
| 390 // TODO(scherkus): http://crbug.com/10863 | |
| 391 TEST(FFmpegDemuxerTest, DISABLED_ReadAndSeek) { | |
| 392 // Prepare some test data. | 401 // Prepare some test data. |
| 393 const int kPacketData = 0; | 402 const int kPacketData = 0; |
| 394 const int kPacketAudio = 1; | 403 const int kPacketAudio = 1; |
| 395 const int kPacketVideo = 2; | 404 const int kPacketVideo = 2; |
| 396 const int kAudio = 0; | 405 const int kAudio = 0; |
| 397 const int kVideo = 1; | 406 const int kVideo = 1; |
| 398 const size_t kDataSize = 4; | 407 const size_t kDataSize = 4; |
| 399 uint8 audio_data[kDataSize] = {0, 1, 2, 3}; | 408 uint8 audio_data[kDataSize] = {0, 1, 2, 3}; |
| 400 uint8 video_data[kDataSize] = {4, 5, 6, 7}; | 409 uint8 video_data[kDataSize] = {4, 5, 6, 7}; |
| 401 | 410 |
| 402 // Simulate media with a data stream, audio stream and video stream. Having | 411 // Simulate media with a data stream, audio stream and video stream. Having |
| 403 // the data stream first forces the audio and video streams to get remapped | 412 // the data stream first forces the audio and video streams to get remapped |
| 404 // from indices {1,2} to {0,1} respectively, which covers an important test | 413 // from indices {1,2} to {0,1} respectively, which covers an important test |
| 405 // case. | 414 // case. |
| 406 InitializeFFmpegMocks(); | |
| 407 g_format.nb_streams = 3; | 415 g_format.nb_streams = 3; |
| 408 g_format.streams[kPacketData] = &g_streams[0]; | 416 g_format.streams[kPacketData] = &g_streams[0]; |
| 409 g_format.streams[kPacketAudio] = &g_streams[1]; | 417 g_format.streams[kPacketAudio] = &g_streams[1]; |
| 410 g_format.streams[kPacketVideo] = &g_streams[2]; | 418 g_format.streams[kPacketVideo] = &g_streams[2]; |
| 411 g_streams[0].duration = 10; | 419 g_streams[0].duration = 10; |
| 412 g_streams[0].codec = &g_data_codec; | 420 g_streams[0].codec = &g_data_codec; |
| 413 g_streams[1].duration = 10; | 421 g_streams[1].duration = 10; |
| 414 g_streams[1].codec = &g_audio_codec; | 422 g_streams[1].codec = &g_audio_codec; |
| 415 g_streams[2].duration = 10; | 423 g_streams[2].duration = 10; |
| 416 g_streams[2].codec = &g_video_codec; | 424 g_streams[2].codec = &g_video_codec; |
| 417 | 425 |
| 418 // Create our pipeline. | 426 // Initialize the demuxer. |
| 419 MockPipeline pipeline; | 427 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); |
| 420 | 428 EXPECT_TRUE(filter_host_->WaitForInitialized()); |
| 421 // Create our data source. | 429 EXPECT_TRUE(filter_host_->IsInitialized()); |
| 422 MockFilterConfig config; | 430 EXPECT_EQ(PIPELINE_OK, pipeline_->GetError()); |
| 423 scoped_refptr<MockDataSource> data_source = new MockDataSource(&config); | |
| 424 MockFilterHost<DataSource> filter_host_a(&pipeline, data_source); | |
| 425 EXPECT_TRUE(data_source->Initialize("foo")); | |
| 426 EXPECT_TRUE(filter_host_a.IsInitialized()); | |
| 427 | |
| 428 // Create our demuxer. | |
| 429 scoped_refptr<FilterFactory> factory = FFmpegDemuxer::CreateFilterFactory(); | |
| 430 scoped_refptr<Demuxer> demuxer | |
| 431 = factory->Create<Demuxer>(data_source->media_format()); | |
| 432 EXPECT_TRUE(demuxer); | |
| 433 MockFilterHost<Demuxer> filter_host_b(&pipeline, demuxer); | |
| 434 EXPECT_TRUE(demuxer->Initialize(data_source)); | |
| 435 EXPECT_TRUE(filter_host_b.WaitForInitialized()); | |
| 436 EXPECT_TRUE(filter_host_b.IsInitialized()); | |
| 437 EXPECT_EQ(PIPELINE_OK, pipeline.GetError()); | |
| 438 | 431 |
| 439 // Verify both streams were created. | 432 // Verify both streams were created. |
| 440 EXPECT_EQ(2, demuxer->GetNumberOfStreams()); | 433 EXPECT_EQ(2, demuxer_->GetNumberOfStreams()); |
| 441 | 434 |
| 442 // Get our streams. | 435 // Get our streams. |
| 443 scoped_refptr<DemuxerStream> audio_stream = demuxer->GetStream(kAudio); | 436 scoped_refptr<DemuxerStream> audio_stream = demuxer_->GetStream(kAudio); |
| 444 scoped_refptr<DemuxerStream> video_stream = demuxer->GetStream(kVideo); | 437 scoped_refptr<DemuxerStream> video_stream = demuxer_->GetStream(kVideo); |
| 445 ASSERT_TRUE(audio_stream); | 438 ASSERT_TRUE(audio_stream); |
| 446 ASSERT_TRUE(video_stream); | 439 ASSERT_TRUE(video_stream); |
| 447 | 440 |
| 448 // Prepare data packets, which should all get immediately released. | 441 // Prepare data packets, which should all get immediately released. |
| 449 PacketQueue::get()->Enqueue(kPacketData, kDataSize, audio_data); | 442 PacketQueue::get()->Enqueue(kPacketData, kDataSize, audio_data); |
| 450 PacketQueue::get()->Enqueue(kPacketData, kDataSize, audio_data); | 443 PacketQueue::get()->Enqueue(kPacketData, kDataSize, audio_data); |
| 451 PacketQueue::get()->Enqueue(kPacketData, kDataSize, audio_data); | 444 PacketQueue::get()->Enqueue(kPacketData, kDataSize, audio_data); |
| 452 | 445 |
| 453 // Prepare our test audio packet. | 446 // Prepare our test audio packet. |
| 454 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); | 447 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); |
| 455 | 448 |
| 456 // Attempt a read from the audio stream and run the message loop until done. | 449 // Attempt a read from the audio stream and run the message loop until done. |
| 457 scoped_refptr<TestReader> reader(new TestReader()); | 450 scoped_refptr<TestReader> reader(new TestReader()); |
| 458 reader->Read(audio_stream); | 451 reader->Read(audio_stream); |
| 459 pipeline.RunAllTasks(); | 452 pipeline_->RunAllTasks(); |
| 460 EXPECT_TRUE(reader->WaitForRead()); | 453 EXPECT_TRUE(reader->WaitForRead()); |
| 461 EXPECT_TRUE(reader->called()); | 454 EXPECT_TRUE(reader->called()); |
| 462 ASSERT_TRUE(reader->buffer()); | 455 ASSERT_TRUE(reader->buffer()); |
| 463 EXPECT_FALSE(reader->buffer()->IsDiscontinuous()); | 456 EXPECT_FALSE(reader->buffer()->IsDiscontinuous()); |
| 464 EXPECT_EQ(audio_data, reader->buffer()->GetData()); | 457 EXPECT_EQ(audio_data, reader->buffer()->GetData()); |
| 465 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); | 458 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); |
| 466 | 459 |
| 467 // Prepare our test video packet. | 460 // Prepare our test video packet. |
| 468 PacketQueue::get()->Enqueue(kPacketVideo, kDataSize, video_data); | 461 PacketQueue::get()->Enqueue(kPacketVideo, kDataSize, video_data); |
| 469 | 462 |
| 470 // Attempt a read from the video stream and run the message loop until done. | 463 // Attempt a read from the video stream and run the message loop until done. |
| 471 reader->Reset(); | 464 reader->Reset(); |
| 472 reader->Read(video_stream); | 465 reader->Read(video_stream); |
| 473 pipeline.RunAllTasks(); | 466 pipeline_->RunAllTasks(); |
| 474 EXPECT_TRUE(reader->WaitForRead()); | 467 EXPECT_TRUE(reader->WaitForRead()); |
| 475 EXPECT_TRUE(reader->called()); | 468 EXPECT_TRUE(reader->called()); |
| 476 ASSERT_TRUE(reader->buffer()); | 469 ASSERT_TRUE(reader->buffer()); |
| 477 EXPECT_FALSE(reader->buffer()->IsDiscontinuous()); | 470 EXPECT_FALSE(reader->buffer()->IsDiscontinuous()); |
| 478 EXPECT_EQ(video_data, reader->buffer()->GetData()); | 471 EXPECT_EQ(video_data, reader->buffer()->GetData()); |
| 479 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); | 472 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); |
| 480 | 473 |
| 481 // Manually release buffer, which should release any remaining AVPackets. | 474 // Manually release buffer, which should release any remaining AVPackets. |
| 482 reader = NULL; | 475 reader = NULL; |
| 483 EXPECT_TRUE(PacketQueue::get()->WaitForOutstandingPackets(0)); | 476 EXPECT_TRUE(PacketQueue::get()->WaitForOutstandingPackets(0)); |
| 484 | 477 |
| 485 //---------------------------------------------------------------------------- | 478 //---------------------------------------------------------------------------- |
| 486 // Seek tests. | 479 // Seek tests. |
| 487 EXPECT_FALSE(g_seek_event); | 480 EXPECT_FALSE(g_seek_event); |
| 488 g_seek_event = new base::WaitableEvent(false, false); | 481 g_seek_event = new base::WaitableEvent(false, false); |
| 489 | 482 |
| 490 // Let's trigger a simple forward seek with no outstanding packets. | 483 // Let's trigger a simple forward seek with no outstanding packets. |
| 491 g_expected_seek_timestamp = 1234; | 484 g_expected_seek_timestamp = 1234; |
| 492 g_expected_seek_flags = 0; | 485 g_expected_seek_flags = 0; |
| 493 demuxer->Seek(base::TimeDelta::FromMicroseconds(g_expected_seek_timestamp)); | 486 demuxer_->Seek(base::TimeDelta::FromMicroseconds(g_expected_seek_timestamp)); |
| 494 EXPECT_TRUE(g_seek_event->TimedWait(base::TimeDelta::FromSeconds(1))); | 487 EXPECT_TRUE(g_seek_event->TimedWait(base::TimeDelta::FromSeconds(1))); |
| 495 | 488 |
| 496 // The next read from each stream should now be discontinuous, but subsequent | 489 // The next read from each stream should now be discontinuous, but subsequent |
| 497 // reads should not. | 490 // reads should not. |
| 498 | 491 |
| 499 // Prepare our test audio packet. | 492 // Prepare our test audio packet. |
| 500 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); | 493 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); |
| 501 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); | 494 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); |
| 502 | 495 |
| 503 // Audio read #1, should be discontinuous. | 496 // Audio read #1, should be discontinuous. |
| 504 reader = new TestReader(); | 497 reader = new TestReader(); |
| 505 reader->Read(audio_stream); | 498 reader->Read(audio_stream); |
| 506 pipeline.RunAllTasks(); | 499 pipeline_->RunAllTasks(); |
| 507 EXPECT_TRUE(reader->WaitForRead()); | 500 EXPECT_TRUE(reader->WaitForRead()); |
| 508 EXPECT_TRUE(reader->called()); | 501 EXPECT_TRUE(reader->called()); |
| 509 ASSERT_TRUE(reader->buffer()); | 502 ASSERT_TRUE(reader->buffer()); |
| 510 EXPECT_TRUE(reader->buffer()->IsDiscontinuous()); | 503 EXPECT_TRUE(reader->buffer()->IsDiscontinuous()); |
| 511 EXPECT_EQ(audio_data, reader->buffer()->GetData()); | 504 EXPECT_EQ(audio_data, reader->buffer()->GetData()); |
| 512 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); | 505 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); |
| 513 | 506 |
| 514 // Audio read #2, should not be discontinuous. | 507 // Audio read #2, should not be discontinuous. |
| 515 reader->Reset(); | 508 reader->Reset(); |
| 516 reader->Read(audio_stream); | 509 reader->Read(audio_stream); |
| 517 pipeline.RunAllTasks(); | 510 pipeline_->RunAllTasks(); |
| 518 EXPECT_TRUE(reader->WaitForRead()); | 511 EXPECT_TRUE(reader->WaitForRead()); |
| 519 EXPECT_TRUE(reader->called()); | 512 EXPECT_TRUE(reader->called()); |
| 520 ASSERT_TRUE(reader->buffer()); | 513 ASSERT_TRUE(reader->buffer()); |
| 521 EXPECT_FALSE(reader->buffer()->IsDiscontinuous()); | 514 EXPECT_FALSE(reader->buffer()->IsDiscontinuous()); |
| 522 EXPECT_EQ(audio_data, reader->buffer()->GetData()); | 515 EXPECT_EQ(audio_data, reader->buffer()->GetData()); |
| 523 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); | 516 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); |
| 524 | 517 |
| 525 // Prepare our test video packet. | 518 // Prepare our test video packet. |
| 526 PacketQueue::get()->Enqueue(kPacketVideo, kDataSize, video_data); | 519 PacketQueue::get()->Enqueue(kPacketVideo, kDataSize, video_data); |
| 527 PacketQueue::get()->Enqueue(kPacketVideo, kDataSize, video_data); | 520 PacketQueue::get()->Enqueue(kPacketVideo, kDataSize, video_data); |
| 528 | 521 |
| 529 // Video read #1, should be discontinuous. | 522 // Video read #1, should be discontinuous. |
| 530 reader->Reset(); | 523 reader->Reset(); |
| 531 reader->Read(video_stream); | 524 reader->Read(video_stream); |
| 532 pipeline.RunAllTasks(); | 525 pipeline_->RunAllTasks(); |
| 533 EXPECT_TRUE(reader->WaitForRead()); | 526 EXPECT_TRUE(reader->WaitForRead()); |
| 534 EXPECT_TRUE(reader->called()); | 527 EXPECT_TRUE(reader->called()); |
| 535 ASSERT_TRUE(reader->buffer()); | 528 ASSERT_TRUE(reader->buffer()); |
| 536 EXPECT_TRUE(reader->buffer()->IsDiscontinuous()); | 529 EXPECT_TRUE(reader->buffer()->IsDiscontinuous()); |
| 537 EXPECT_EQ(video_data, reader->buffer()->GetData()); | 530 EXPECT_EQ(video_data, reader->buffer()->GetData()); |
| 538 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); | 531 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); |
| 539 | 532 |
| 540 // Video read #2, should not be discontinuous. | 533 // Video read #2, should not be discontinuous. |
| 541 reader->Reset(); | 534 reader->Reset(); |
| 542 reader->Read(video_stream); | 535 reader->Read(video_stream); |
| 543 pipeline.RunAllTasks(); | 536 pipeline_->RunAllTasks(); |
| 544 EXPECT_TRUE(reader->WaitForRead()); | 537 EXPECT_TRUE(reader->WaitForRead()); |
| 545 EXPECT_TRUE(reader->called()); | 538 EXPECT_TRUE(reader->called()); |
| 546 ASSERT_TRUE(reader->buffer()); | 539 ASSERT_TRUE(reader->buffer()); |
| 547 EXPECT_FALSE(reader->buffer()->IsDiscontinuous()); | 540 EXPECT_FALSE(reader->buffer()->IsDiscontinuous()); |
| 548 EXPECT_EQ(video_data, reader->buffer()->GetData()); | 541 EXPECT_EQ(video_data, reader->buffer()->GetData()); |
| 549 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); | 542 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); |
| 550 | 543 |
| 551 // Manually release buffer, which should release any remaining AVPackets. | 544 // Manually release buffer, which should release any remaining AVPackets. |
| 552 reader = NULL; | 545 reader = NULL; |
| 553 EXPECT_TRUE(PacketQueue::get()->WaitForOutstandingPackets(0)); | 546 EXPECT_TRUE(PacketQueue::get()->WaitForOutstandingPackets(0)); |
| 554 | 547 |
| 555 // Let's trigger another simple forward seek, but with outstanding packets. | 548 // Let's trigger another simple forward seek, but with outstanding packets. |
| 556 // The outstanding packets should get freed after the Seek() is issued. | 549 // The outstanding packets should get freed after the Seek() is issued. |
| 557 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); | 550 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); |
| 558 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); | 551 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); |
| 559 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); | 552 PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); |
| 560 PacketQueue::get()->Enqueue(kPacketVideo, kDataSize, video_data); | 553 PacketQueue::get()->Enqueue(kPacketVideo, kDataSize, video_data); |
| 561 | 554 |
| 562 // Attempt a read from video stream, which will force the demuxer to queue | 555 // Attempt a read from video stream, which will force the demuxer to queue |
| 563 // the audio packets preceding the video packet. | 556 // the audio packets preceding the video packet. |
| 564 reader = new TestReader(); | 557 reader = new TestReader(); |
| 565 reader->Read(video_stream); | 558 reader->Read(video_stream); |
| 566 pipeline.RunAllTasks(); | 559 pipeline_->RunAllTasks(); |
| 567 EXPECT_TRUE(reader->WaitForRead()); | 560 EXPECT_TRUE(reader->WaitForRead()); |
| 568 EXPECT_TRUE(reader->called()); | 561 EXPECT_TRUE(reader->called()); |
| 569 ASSERT_TRUE(reader->buffer()); | 562 ASSERT_TRUE(reader->buffer()); |
| 570 EXPECT_FALSE(reader->buffer()->IsDiscontinuous()); | 563 EXPECT_FALSE(reader->buffer()->IsDiscontinuous()); |
| 571 EXPECT_EQ(video_data, reader->buffer()->GetData()); | 564 EXPECT_EQ(video_data, reader->buffer()->GetData()); |
| 572 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); | 565 EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); |
| 573 | 566 |
| 574 // Manually release video buffer, remaining audio packets are outstanding. | 567 // Manually release video buffer, remaining audio packets are outstanding. |
| 575 reader = NULL; | 568 reader = NULL; |
| 576 EXPECT_TRUE(PacketQueue::get()->WaitForOutstandingPackets(3)); | 569 EXPECT_TRUE(PacketQueue::get()->WaitForOutstandingPackets(3)); |
| 577 | 570 |
| 578 // Trigger the seek. | 571 // Trigger the seek. |
| 579 g_expected_seek_timestamp = 1234; | 572 g_expected_seek_timestamp = 1234; |
| 580 g_expected_seek_flags = 0; | 573 g_expected_seek_flags = 0; |
| 581 demuxer->Seek(base::TimeDelta::FromMicroseconds(g_expected_seek_timestamp)); | 574 demuxer_->Seek(base::TimeDelta::FromMicroseconds(g_expected_seek_timestamp)); |
| 582 EXPECT_TRUE(g_seek_event->TimedWait(base::TimeDelta::FromSeconds(1))); | 575 EXPECT_TRUE(g_seek_event->TimedWait(base::TimeDelta::FromSeconds(1))); |
| 583 | 576 |
| 584 // All outstanding packets should have been freed. | 577 // All outstanding packets should have been freed. |
| 585 EXPECT_TRUE(PacketQueue::get()->WaitForOutstandingPackets(0)); | 578 EXPECT_TRUE(PacketQueue::get()->WaitForOutstandingPackets(0)); |
| 586 | 579 |
| 587 // Clean up. | 580 // Clean up. |
| 588 delete g_seek_event; | 581 delete g_seek_event; |
| 589 g_seek_event = NULL; | 582 g_seek_event = NULL; |
| 590 | 583 |
| 591 //---------------------------------------------------------------------------- | 584 //---------------------------------------------------------------------------- |
| 592 // End of stream tests. | 585 // End of stream tests. |
| 593 | 586 |
| 594 // Simulate end of stream. | 587 // Simulate end of stream. |
| 595 g_av_read_frame = AVERROR_IO; | 588 g_av_read_frame = AVERROR_IO; |
| 596 | 589 |
| 597 // Attempt a read from the audio stream and run the message loop until done. | 590 // Attempt a read from the audio stream and run the message loop until done. |
| 598 reader = new TestReader(); | 591 reader = new TestReader(); |
| 599 reader->Read(audio_stream); | 592 reader->Read(audio_stream); |
| 600 pipeline.RunAllTasks(); | 593 pipeline_->RunAllTasks(); |
| 601 EXPECT_FALSE(reader->WaitForRead()); | 594 EXPECT_FALSE(reader->WaitForRead()); |
| 602 EXPECT_FALSE(reader->called()); | 595 EXPECT_FALSE(reader->called()); |
| 603 EXPECT_FALSE(reader->buffer()); | 596 EXPECT_FALSE(reader->buffer()); |
| 604 | 597 |
| 605 // Manually release buffer, which should release any remaining AVPackets. | 598 // Manually release buffer, which should release any remaining AVPackets. |
| 606 reader = NULL; | 599 reader = NULL; |
| 607 EXPECT_TRUE(PacketQueue::get()->WaitForOutstandingPackets(0)); | 600 EXPECT_TRUE(PacketQueue::get()->WaitForOutstandingPackets(0)); |
| 608 } | 601 } |
| OLD | NEW |