diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-28 17:44:43 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-28 17:44:43 +0000 |
commit | 61374e50e3714c93ef130aea5f0b35cd4b8bca3e (patch) | |
tree | 51dd300566914d486039a1fbebe9ea008e472100 /media | |
parent | 94a14a2f6a1b59065278b2e2fb812a98040c8416 (diff) | |
download | chromium_src-61374e50e3714c93ef130aea5f0b35cd4b8bca3e.zip chromium_src-61374e50e3714c93ef130aea5f0b35cd4b8bca3e.tar.gz chromium_src-61374e50e3714c93ef130aea5f0b35cd4b8bca3e.tar.bz2 |
Adds a second vector of streams to FFmpegDemuxer to handle re-mapped audio/video streams.
For media containing non-audio/video streams we were properly exposing the correct streams via Demuxer::GetStream() (i.e., no data streams were exposed) however we weren't properly re-routing the packets to the correct streams during demuxing.
Before:
Media contains [DATA, AUDIO, VIDEO]
We create supported vector [AUDIO, VIDEO]
When demuxing a packet who says they are from stream 1 (AUDIO), we would incorrectly assign it to VIDEO
After:
Media contains [DATA, AUDIO, VIDEO]
We create supported vector [AUDIO, VIDEO]
We create extra packet vector [NULL, AUDIO, VIDEO]
When demuxing, we now correctly assign it to the proper stream and automatically free unused packets
Review URL: http://codereview.chromium.org/100085
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@14742 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/filters/ffmpeg_demuxer.cc | 13 | ||||
-rw-r--r-- | media/filters/ffmpeg_demuxer.h | 10 | ||||
-rw-r--r-- | media/filters/ffmpeg_demuxer_unittest.cc | 50 |
3 files changed, 51 insertions, 22 deletions
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc index 08433b5..e6c08954 100644 --- a/media/filters/ffmpeg_demuxer.cc +++ b/media/filters/ffmpeg_demuxer.cc @@ -278,7 +278,10 @@ void FFmpegDemuxer::InititalizeTask(DataSource* data_source) { = new FFmpegDemuxerStream(this, stream); DCHECK(demuxer_stream); streams_.push_back(demuxer_stream); + packet_streams_.push_back(demuxer_stream); max_duration = std::max(max_duration, demuxer_stream->duration()); + } else { + packet_streams_.push_back(NULL); } } if (streams_.empty()) { @@ -332,9 +335,13 @@ void FFmpegDemuxer::DemuxTask() { // worried about downstream filters (i.e., decoders) executing on this // thread. DCHECK(packet->stream_index >= 0); - DCHECK(packet->stream_index < static_cast<int>(streams_.size())); - FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index]; - current_timestamp_ = demuxer_stream->EnqueuePacket(packet.release()); + DCHECK(packet->stream_index < static_cast<int>(packet_streams_.size())); + FFmpegDemuxerStream* demuxer_stream = packet_streams_[packet->stream_index]; + if (demuxer_stream) { + current_timestamp_ = demuxer_stream->EnqueuePacket(packet.release()); + } else { + av_free_packet(packet.get()); + } // Create a loop by posting another task. This allows seek and message loop // quit tasks to get processed. diff --git a/media/filters/ffmpeg_demuxer.h b/media/filters/ffmpeg_demuxer.h index 2c113be..640f9cc 100644 --- a/media/filters/ffmpeg_demuxer.h +++ b/media/filters/ffmpeg_demuxer.h @@ -149,9 +149,17 @@ class FFmpegDemuxer : public Demuxer { // Latest timestamp read on the demuxer thread. base::TimeDelta current_timestamp_; - // Vector of streams. + // Two vector of streams: + // - |streams_| is indexed for the Demuxer interface GetStream(), which only + // contains supported streams and no NULL entries. + // - |packet_streams_| is indexed to mirror AVFormatContext when dealing + // with AVPackets returned from av_read_frame() and contain NULL entries + // representing unsupported streams where we throw away the data. + // + // Ownership is handled via reference counting. typedef std::vector< scoped_refptr<FFmpegDemuxerStream> > StreamVector; StreamVector streams_; + StreamVector packet_streams_; // Thread handle. base::Thread thread_; diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc index 167a212..e0fa404 100644 --- a/media/filters/ffmpeg_demuxer_unittest.cc +++ b/media/filters/ffmpeg_demuxer_unittest.cc @@ -409,21 +409,30 @@ TEST(FFmpegDemuxerTest, DISABLED_InitializeStreams) { // TODO(scherkus): http://crbug.com/10863 TEST(FFmpegDemuxerTest, DISABLED_ReadAndSeek) { // Prepare some test data. + const int kPacketData = 0; + const int kPacketAudio = 1; + const int kPacketVideo = 2; const int kAudio = 0; const int kVideo = 1; const size_t kDataSize = 4; uint8 audio_data[kDataSize] = {0, 1, 2, 3}; uint8 video_data[kDataSize] = {4, 5, 6, 7}; - // Simulate media with a an audio stream and video stream. + // Simulate media with a data stream, audio stream and video stream. Having + // the data stream first forces the audio and video streams to get remapped + // from indices {1,2} to {0,1} respectively, which covers an important test + // case. InitializeFFmpegMocks(); - g_format.nb_streams = 2; - g_format.streams[kAudio] = &g_streams[kAudio]; - g_format.streams[kVideo] = &g_streams[kVideo]; - g_streams[kAudio].duration = 10; - g_streams[kAudio].codec = &g_audio_codec; - g_streams[kVideo].duration = 10; - g_streams[kVideo].codec = &g_video_codec; + g_format.nb_streams = 3; + g_format.streams[kPacketData] = &g_streams[0]; + g_format.streams[kPacketAudio] = &g_streams[1]; + g_format.streams[kPacketVideo] = &g_streams[2]; + g_streams[0].duration = 10; + g_streams[0].codec = &g_data_codec; + g_streams[1].duration = 10; + g_streams[1].codec = &g_audio_codec; + g_streams[2].duration = 10; + g_streams[2].codec = &g_video_codec; // Create our pipeline. MockPipeline pipeline; @@ -455,8 +464,13 @@ TEST(FFmpegDemuxerTest, DISABLED_ReadAndSeek) { ASSERT_TRUE(audio_stream); ASSERT_TRUE(video_stream); + // Prepare data packets, which should all get immediately released. + PacketQueue::get()->Enqueue(kPacketData, kDataSize, audio_data); + PacketQueue::get()->Enqueue(kPacketData, kDataSize, audio_data); + PacketQueue::get()->Enqueue(kPacketData, kDataSize, audio_data); + // Prepare our test audio packet. - PacketQueue::get()->Enqueue(kAudio, kDataSize, audio_data); + PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); // Attempt a read from the audio stream and run the message loop until done. scoped_refptr<TestReader> reader(new TestReader()); @@ -470,7 +484,7 @@ TEST(FFmpegDemuxerTest, DISABLED_ReadAndSeek) { EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); // Prepare our test video packet. - PacketQueue::get()->Enqueue(kVideo, kDataSize, video_data); + PacketQueue::get()->Enqueue(kPacketVideo, kDataSize, video_data); // Attempt a read from the video stream and run the message loop until done. reader->Reset(); @@ -502,8 +516,8 @@ TEST(FFmpegDemuxerTest, DISABLED_ReadAndSeek) { // reads should not. // Prepare our test audio packet. - PacketQueue::get()->Enqueue(kAudio, kDataSize, audio_data); - PacketQueue::get()->Enqueue(kAudio, kDataSize, audio_data); + PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); + PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); // Audio read #1, should be discontinuous. reader = new TestReader(); @@ -528,8 +542,8 @@ TEST(FFmpegDemuxerTest, DISABLED_ReadAndSeek) { EXPECT_EQ(kDataSize, reader->buffer()->GetDataSize()); // Prepare our test video packet. - PacketQueue::get()->Enqueue(kVideo, kDataSize, video_data); - PacketQueue::get()->Enqueue(kVideo, kDataSize, video_data); + PacketQueue::get()->Enqueue(kPacketVideo, kDataSize, video_data); + PacketQueue::get()->Enqueue(kPacketVideo, kDataSize, video_data); // Video read #1, should be discontinuous. reader->Reset(); @@ -559,10 +573,10 @@ TEST(FFmpegDemuxerTest, DISABLED_ReadAndSeek) { // Let's trigger another simple forward seek, but with outstanding packets. // The outstanding packets should get freed after the Seek() is issued. - PacketQueue::get()->Enqueue(kAudio, kDataSize, audio_data); - PacketQueue::get()->Enqueue(kAudio, kDataSize, audio_data); - PacketQueue::get()->Enqueue(kAudio, kDataSize, audio_data); - PacketQueue::get()->Enqueue(kVideo, kDataSize, video_data); + PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); + PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); + PacketQueue::get()->Enqueue(kPacketAudio, kDataSize, audio_data); + PacketQueue::get()->Enqueue(kPacketVideo, kDataSize, video_data); // Attempt a read from video stream, which will force the demuxer to queue // the audio packets preceding the video packet. |