| 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 "media/base/filters.h" | 7 #include "media/base/filters.h" |
| 8 #include "media/base/mock_ffmpeg.h" | 8 #include "media/base/mock_ffmpeg.h" |
| 9 #include "media/base/mock_filter_host.h" | 9 #include "media/base/mock_filter_host.h" |
| 10 #include "media/base/mock_filters.h" | 10 #include "media/base/mock_filters.h" |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 | 59 |
| 60 FFmpegDemuxerTest() { | 60 FFmpegDemuxerTest() { |
| 61 // Create an FFmpegDemuxer. | 61 // Create an FFmpegDemuxer. |
| 62 factory_ = FFmpegDemuxer::CreateFilterFactory(); | 62 factory_ = FFmpegDemuxer::CreateFilterFactory(); |
| 63 MediaFormat media_format; | 63 MediaFormat media_format; |
| 64 media_format.SetAsString(MediaFormat::kMimeType, | 64 media_format.SetAsString(MediaFormat::kMimeType, |
| 65 mime_type::kApplicationOctetStream); | 65 mime_type::kApplicationOctetStream); |
| 66 demuxer_ = factory_->Create<FFmpegDemuxer>(media_format); | 66 demuxer_ = factory_->Create<FFmpegDemuxer>(media_format); |
| 67 DCHECK(demuxer_); | 67 DCHECK(demuxer_); |
| 68 | 68 |
| 69 // Provide a message loop. | 69 // Inject a filter host and message loop and prepare a data source. |
| 70 demuxer_->SetFilterHost(&host_); |
| 70 demuxer_->SetMessageLoop(&message_loop_); | 71 demuxer_->SetMessageLoop(&message_loop_); |
| 71 | |
| 72 // Prepare a filter host and data source for the demuxer. | |
| 73 pipeline_.reset(new MockPipeline()); | |
| 74 filter_host_.reset(new old_mocks::MockFilterHost<Demuxer>(pipeline_.get(), | |
| 75 demuxer_)); | |
| 76 data_source_ = new StrictMock<MockDataSource>(); | 72 data_source_ = new StrictMock<MockDataSource>(); |
| 77 | 73 |
| 78 // Initialize FFmpeg fixtures. | 74 // Initialize FFmpeg fixtures. |
| 79 memset(&format_context_, 0, sizeof(format_context_)); | 75 memset(&format_context_, 0, sizeof(format_context_)); |
| 80 memset(&streams_, 0, sizeof(streams_)); | 76 memset(&streams_, 0, sizeof(streams_)); |
| 81 memset(&codecs_, 0, sizeof(codecs_)); | 77 memset(&codecs_, 0, sizeof(codecs_)); |
| 82 | 78 |
| 83 // Initialize AVCodexContext structures. | 79 // Initialize AVCodexContext structures. |
| 84 codecs_[AV_STREAM_DATA].codec_type = CODEC_TYPE_DATA; | 80 codecs_[AV_STREAM_DATA].codec_type = CODEC_TYPE_DATA; |
| 85 codecs_[AV_STREAM_DATA].codec_id = CODEC_ID_NONE; | 81 codecs_[AV_STREAM_DATA].codec_id = CODEC_ID_NONE; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 112 virtual ~FFmpegDemuxerTest() { | 108 virtual ~FFmpegDemuxerTest() { |
| 113 // Call Stop() to shut down internal threads. | 109 // Call Stop() to shut down internal threads. |
| 114 demuxer_->Stop(); | 110 demuxer_->Stop(); |
| 115 | 111 |
| 116 // Finish up any remaining tasks. | 112 // Finish up any remaining tasks. |
| 117 message_loop_.RunAllPending(); | 113 message_loop_.RunAllPending(); |
| 118 | 114 |
| 119 // Release the reference to the demuxer. | 115 // Release the reference to the demuxer. |
| 120 demuxer_ = NULL; | 116 demuxer_ = NULL; |
| 121 | 117 |
| 122 // Filter host also holds a reference to demuxer, destroy it. | |
| 123 filter_host_.reset(); | |
| 124 | |
| 125 // Reset MockFFmpeg. | 118 // Reset MockFFmpeg. |
| 126 MockFFmpeg::set(NULL); | 119 MockFFmpeg::set(NULL); |
| 127 } | 120 } |
| 128 | 121 |
| 129 // Sets up MockFFmpeg to allow FFmpegDemuxer to successfully initialize. | 122 // Sets up MockFFmpeg to allow FFmpegDemuxer to successfully initialize. |
| 130 void InitializeDemuxerMocks() { | 123 void InitializeDemuxerMocks() { |
| 131 EXPECT_CALL(*MockFFmpeg::get(), AVOpenInputFile(_, _, NULL, 0, NULL)) | 124 EXPECT_CALL(*MockFFmpeg::get(), AVOpenInputFile(_, _, NULL, 0, NULL)) |
| 132 .WillOnce(DoAll(SetArgumentPointee<0>(&format_context_), Return(0))); | 125 .WillOnce(DoAll(SetArgumentPointee<0>(&format_context_), Return(0))); |
| 133 EXPECT_CALL(*MockFFmpeg::get(), AVFindStreamInfo(&format_context_)) | 126 EXPECT_CALL(*MockFFmpeg::get(), AVFindStreamInfo(&format_context_)) |
| 134 .WillOnce(Return(0)); | 127 .WillOnce(Return(0)); |
| 135 EXPECT_CALL(*MockFFmpeg::get(), AVCloseInputFile(&format_context_)); | 128 EXPECT_CALL(*MockFFmpeg::get(), AVCloseInputFile(&format_context_)); |
| 136 } | 129 } |
| 137 | 130 |
| 138 // Initializes both MockFFmpeg and FFmpegDemuxer. | 131 // Initializes both MockFFmpeg and FFmpegDemuxer. |
| 139 void InitializeDemuxer() { | 132 void InitializeDemuxer() { |
| 140 InitializeDemuxerMocks(); | 133 InitializeDemuxerMocks(); |
| 134 |
| 135 // We expect a successful initialization. |
| 136 EXPECT_CALL(host_, InitializationComplete()); |
| 137 |
| 138 // Since we ignore data streams, the duration should be equal to the longest |
| 139 // supported stream's duration (audio, in this case). |
| 140 base::TimeDelta expected_duration = |
| 141 base::TimeDelta::FromMicroseconds(kDurations[AV_STREAM_AUDIO]); |
| 142 EXPECT_CALL(host_, SetDuration(expected_duration)); |
| 143 |
| 141 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); | 144 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); |
| 142 message_loop_.RunAllPending(); | 145 message_loop_.RunAllPending(); |
| 143 EXPECT_TRUE(filter_host_->WaitForInitialized()); | |
| 144 EXPECT_TRUE(filter_host_->IsInitialized()); | |
| 145 EXPECT_EQ(PIPELINE_OK, pipeline_->GetError()); | |
| 146 } | 146 } |
| 147 | 147 |
| 148 // Fixture members. | 148 // Fixture members. |
| 149 scoped_refptr<FilterFactory> factory_; | 149 scoped_refptr<FilterFactory> factory_; |
| 150 scoped_refptr<FFmpegDemuxer> demuxer_; | 150 scoped_refptr<FFmpegDemuxer> demuxer_; |
| 151 scoped_ptr<MockPipeline> pipeline_; | |
| 152 scoped_ptr<old_mocks::MockFilterHost<Demuxer> > filter_host_; | |
| 153 scoped_refptr<StrictMock<MockDataSource> > data_source_; | 151 scoped_refptr<StrictMock<MockDataSource> > data_source_; |
| 152 StrictMock<MockFilterHost> host_; |
| 154 MessageLoop message_loop_; | 153 MessageLoop message_loop_; |
| 155 | 154 |
| 156 // FFmpeg fixtures. | 155 // FFmpeg fixtures. |
| 157 AVFormatContext format_context_; | 156 AVFormatContext format_context_; |
| 158 AVCodecContext codecs_[AV_STREAM_MAX]; | 157 AVCodecContext codecs_[AV_STREAM_MAX]; |
| 159 AVStream streams_[AV_STREAM_MAX]; | 158 AVStream streams_[AV_STREAM_MAX]; |
| 160 MockFFmpeg mock_ffmpeg_; | 159 MockFFmpeg mock_ffmpeg_; |
| 161 | 160 |
| 162 private: | 161 private: |
| 163 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest); | 162 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 189 media_format.SetAsString(MediaFormat::kMimeType, | 188 media_format.SetAsString(MediaFormat::kMimeType, |
| 190 mime_type::kApplicationOctetStream); | 189 mime_type::kApplicationOctetStream); |
| 191 demuxer = factory->Create<Demuxer>(media_format); | 190 demuxer = factory->Create<Demuxer>(media_format); |
| 192 ASSERT_TRUE(demuxer); | 191 ASSERT_TRUE(demuxer); |
| 193 } | 192 } |
| 194 | 193 |
| 195 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) { | 194 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) { |
| 196 // Simulate av_open_input_file() failing. | 195 // Simulate av_open_input_file() failing. |
| 197 EXPECT_CALL(*MockFFmpeg::get(), AVOpenInputFile(_, _, NULL, 0, NULL)) | 196 EXPECT_CALL(*MockFFmpeg::get(), AVOpenInputFile(_, _, NULL, 0, NULL)) |
| 198 .WillOnce(Return(-1)); | 197 .WillOnce(Return(-1)); |
| 198 EXPECT_CALL(host_, Error(DEMUXER_ERROR_COULD_NOT_OPEN)); |
| 199 | 199 |
| 200 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); | 200 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); |
| 201 message_loop_.RunAllPending(); | 201 message_loop_.RunAllPending(); |
| 202 EXPECT_TRUE(filter_host_->WaitForError(DEMUXER_ERROR_COULD_NOT_OPEN)); | |
| 203 EXPECT_FALSE(filter_host_->IsInitialized()); | |
| 204 } | 202 } |
| 205 | 203 |
| 206 TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) { | 204 TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) { |
| 207 // Simulate av_find_stream_info() failing. | 205 // Simulate av_find_stream_info() failing. |
| 208 EXPECT_CALL(*MockFFmpeg::get(), AVOpenInputFile(_, _, NULL, 0, NULL)) | 206 EXPECT_CALL(*MockFFmpeg::get(), AVOpenInputFile(_, _, NULL, 0, NULL)) |
| 209 .WillOnce(DoAll(SetArgumentPointee<0>(&format_context_), Return(0))); | 207 .WillOnce(DoAll(SetArgumentPointee<0>(&format_context_), Return(0))); |
| 210 EXPECT_CALL(*MockFFmpeg::get(), AVFindStreamInfo(&format_context_)) | 208 EXPECT_CALL(*MockFFmpeg::get(), AVFindStreamInfo(&format_context_)) |
| 211 .WillOnce(Return(AVERROR_IO)); | 209 .WillOnce(Return(AVERROR_IO)); |
| 212 EXPECT_CALL(*MockFFmpeg::get(), AVCloseInputFile(&format_context_)); | 210 EXPECT_CALL(*MockFFmpeg::get(), AVCloseInputFile(&format_context_)); |
| 211 EXPECT_CALL(host_, Error(DEMUXER_ERROR_COULD_NOT_PARSE)); |
| 213 | 212 |
| 214 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); | 213 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); |
| 215 message_loop_.RunAllPending(); | 214 message_loop_.RunAllPending(); |
| 216 EXPECT_TRUE(filter_host_->WaitForError(DEMUXER_ERROR_COULD_NOT_PARSE)); | |
| 217 EXPECT_FALSE(filter_host_->IsInitialized()); | |
| 218 } | 215 } |
| 219 | 216 |
| 220 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) { | 217 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) { |
| 221 // Simulate media with no parseable streams. | 218 // Simulate media with no parseable streams. |
| 222 { | 219 { |
| 223 SCOPED_TRACE(""); | 220 SCOPED_TRACE(""); |
| 224 InitializeDemuxerMocks(); | 221 InitializeDemuxerMocks(); |
| 225 } | 222 } |
| 223 EXPECT_CALL(host_, Error(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); |
| 226 format_context_.nb_streams = 0; | 224 format_context_.nb_streams = 0; |
| 227 | 225 |
| 228 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); | 226 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); |
| 229 message_loop_.RunAllPending(); | 227 message_loop_.RunAllPending(); |
| 230 EXPECT_TRUE(filter_host_->WaitForError(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); | |
| 231 EXPECT_FALSE(filter_host_->IsInitialized()); | |
| 232 } | 228 } |
| 233 | 229 |
| 234 TEST_F(FFmpegDemuxerTest, Initialize_DataStreamOnly) { | 230 TEST_F(FFmpegDemuxerTest, Initialize_DataStreamOnly) { |
| 235 // Simulate media with a data stream but no audio or video streams. | 231 // Simulate media with a data stream but no audio or video streams. |
| 236 { | 232 { |
| 237 SCOPED_TRACE(""); | 233 SCOPED_TRACE(""); |
| 238 InitializeDemuxerMocks(); | 234 InitializeDemuxerMocks(); |
| 239 } | 235 } |
| 236 EXPECT_CALL(host_, Error(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); |
| 240 EXPECT_EQ(format_context_.streams[0], &streams_[AV_STREAM_DATA]); | 237 EXPECT_EQ(format_context_.streams[0], &streams_[AV_STREAM_DATA]); |
| 241 format_context_.nb_streams = 1; | 238 format_context_.nb_streams = 1; |
| 242 | 239 |
| 243 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); | 240 EXPECT_TRUE(demuxer_->Initialize(data_source_.get())); |
| 244 message_loop_.RunAllPending(); | 241 message_loop_.RunAllPending(); |
| 245 EXPECT_TRUE(filter_host_->WaitForError(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); | |
| 246 EXPECT_FALSE(filter_host_->IsInitialized()); | |
| 247 } | 242 } |
| 248 | 243 |
| 249 TEST_F(FFmpegDemuxerTest, Initialize_Successful) { | 244 TEST_F(FFmpegDemuxerTest, Initialize_Successful) { |
| 250 { | 245 { |
| 251 SCOPED_TRACE(""); | 246 SCOPED_TRACE(""); |
| 252 InitializeDemuxer(); | 247 InitializeDemuxer(); |
| 253 } | 248 } |
| 254 | 249 |
| 255 // Verify that our demuxer streams were created from our AVStream structures. | 250 // Verify that our demuxer streams were created from our AVStream structures. |
| 256 EXPECT_EQ(DS_STREAM_MAX, static_cast<int>(demuxer_->GetNumberOfStreams())); | 251 EXPECT_EQ(DS_STREAM_MAX, static_cast<int>(demuxer_->GetNumberOfStreams())); |
| 257 | 252 |
| 258 // Since we ignore data streams, the duration should be equal to the longest | |
| 259 // supported stream's duration (audio, in this case). | |
| 260 EXPECT_EQ(kDurations[AV_STREAM_AUDIO], | |
| 261 pipeline_->GetDuration().InMicroseconds()); | |
| 262 | |
| 263 // First stream should be video and support the FFmpegDemuxerStream interface. | 253 // First stream should be video and support the FFmpegDemuxerStream interface. |
| 264 scoped_refptr<DemuxerStream> stream = demuxer_->GetStream(DS_STREAM_VIDEO); | 254 scoped_refptr<DemuxerStream> stream = demuxer_->GetStream(DS_STREAM_VIDEO); |
| 265 AVStreamProvider* av_stream_provider = NULL; | 255 AVStreamProvider* av_stream_provider = NULL; |
| 266 ASSERT_TRUE(stream); | 256 ASSERT_TRUE(stream); |
| 267 std::string mime_type; | 257 std::string mime_type; |
| 268 EXPECT_TRUE( | 258 EXPECT_TRUE( |
| 269 stream->media_format().GetAsString(MediaFormat::kMimeType, &mime_type)); | 259 stream->media_format().GetAsString(MediaFormat::kMimeType, &mime_type)); |
| 270 EXPECT_STREQ(mime_type::kFFmpegVideo, mime_type.c_str()); | 260 EXPECT_STREQ(mime_type::kFFmpegVideo, mime_type.c_str()); |
| 271 EXPECT_TRUE(stream->QueryInterface(&av_stream_provider)); | 261 EXPECT_TRUE(stream->QueryInterface(&av_stream_provider)); |
| 272 EXPECT_TRUE(av_stream_provider); | 262 EXPECT_TRUE(av_stream_provider); |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 | 640 |
| 651 // Attempt the read... | 641 // Attempt the read... |
| 652 audio->Read(callback.release()); | 642 audio->Read(callback.release()); |
| 653 message_loop_.RunAllPending(); | 643 message_loop_.RunAllPending(); |
| 654 | 644 |
| 655 // ...and verify that |callback| was deleted. | 645 // ...and verify that |callback| was deleted. |
| 656 MockFFmpeg::get()->CheckPoint(1); | 646 MockFFmpeg::get()->CheckPoint(1); |
| 657 } | 647 } |
| 658 | 648 |
| 659 } // namespace media | 649 } // namespace media |
| OLD | NEW |