summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-28 17:44:43 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-28 17:44:43 +0000
commit61374e50e3714c93ef130aea5f0b35cd4b8bca3e (patch)
tree51dd300566914d486039a1fbebe9ea008e472100 /media
parent94a14a2f6a1b59065278b2e2fb812a98040c8416 (diff)
downloadchromium_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.cc13
-rw-r--r--media/filters/ffmpeg_demuxer.h10
-rw-r--r--media/filters/ffmpeg_demuxer_unittest.cc50
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.