summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authoracolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-21 20:54:26 +0000
committeracolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-21 20:54:26 +0000
commit50464198dea18732a8baeacd4fb01f9c93d41a85 (patch)
tree5cf56b0cf940eeed23f36d80fac17973a82b505a /media
parent91fdfe2fe39c1fb55708f2d65203caecdbdbfa34 (diff)
downloadchromium_src-50464198dea18732a8baeacd4fb01f9c93d41a85.zip
chromium_src-50464198dea18732a8baeacd4fb01f9c93d41a85.tar.gz
chromium_src-50464198dea18732a8baeacd4fb01f9c93d41a85.tar.bz2
Revert 152622 - Add support for config changes during playback to FFmpegVideoDecoder.
Also fixed a minor config change related bug in SourceBufferStream. BUG=122913 TEST=PipelineIntegrationTest.MediaSource_MP4ConfigChange, SourceBufferStreamTest.ConfigChange_Basic, PipelineIntegrationTest.MediaSource_Seek Review URL: https://chromiumcodereview.appspot.com/10836304 TBR=acolwell@chromium.org Review URL: https://chromiumcodereview.appspot.com/10866002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@152629 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/filters/chunk_demuxer_unittest.cc14
-rw-r--r--media/filters/ffmpeg_video_decoder.cc85
-rw-r--r--media/filters/ffmpeg_video_decoder.h4
-rw-r--r--media/filters/pipeline_integration_test.cc113
-rw-r--r--media/filters/source_buffer_stream.cc39
-rw-r--r--media/filters/source_buffer_stream.h8
-rw-r--r--media/filters/source_buffer_stream_unittest.cc103
-rw-r--r--media/mp4/mp4_stream_parser.cc9
-rw-r--r--media/mp4/mp4_stream_parser_unittest.cc5
9 files changed, 103 insertions, 277 deletions
diff --git a/media/filters/chunk_demuxer_unittest.cc b/media/filters/chunk_demuxer_unittest.cc
index c1cec58..2d04f51 100644
--- a/media/filters/chunk_demuxer_unittest.cc
+++ b/media/filters/chunk_demuxer_unittest.cc
@@ -2056,6 +2056,10 @@ TEST_F(ChunkDemuxerTest, TestConfigChange_Video) {
ASSERT_EQ(status, DemuxerStream::kConfigChanged);
EXPECT_EQ(last_timestamp.InMilliseconds(), 501);
+ // Verify that another read will result in kConfigChanged being returned
+ // again.
+ ExpectConfigChanged(stream);
+
// Fetch the new decoder config.
const VideoDecoderConfig& video_config_2 = stream->video_decoder_config();
ASSERT_TRUE(video_config_2.IsValidConfig());
@@ -2069,6 +2073,9 @@ TEST_F(ChunkDemuxerTest, TestConfigChange_Video) {
ASSERT_EQ(status, DemuxerStream::kConfigChanged);
EXPECT_EQ(last_timestamp.InMilliseconds(), 793);
+ // Verify we get another ConfigChanged status.
+ ExpectConfigChanged(stream);
+
// Get the new config and verify that it matches the first one.
ASSERT_TRUE(video_config_1.Matches(stream->video_decoder_config()));
@@ -2103,6 +2110,10 @@ TEST_F(ChunkDemuxerTest, TestConfigChange_Audio) {
ASSERT_EQ(status, DemuxerStream::kConfigChanged);
EXPECT_EQ(last_timestamp.InMilliseconds(), 524);
+ // Verify that another read will result in kConfigChanged being returned
+ // again.
+ ExpectConfigChanged(stream);
+
// Fetch the new decoder config.
const AudioDecoderConfig& audio_config_2 = stream->audio_decoder_config();
ASSERT_TRUE(audio_config_2.IsValidConfig());
@@ -2116,6 +2127,9 @@ TEST_F(ChunkDemuxerTest, TestConfigChange_Audio) {
ASSERT_EQ(status, DemuxerStream::kConfigChanged);
EXPECT_EQ(last_timestamp.InMilliseconds(), 759);
+ // Verify we get another ConfigChanged status.
+ ExpectConfigChanged(stream);
+
// Get the new config and verify that it matches the first one.
ASSERT_TRUE(audio_config_1.Matches(stream->audio_decoder_config()));
diff --git a/media/filters/ffmpeg_video_decoder.cc b/media/filters/ffmpeg_video_decoder.cc
index 7bfd4e8..6c9387a 100644
--- a/media/filters/ffmpeg_video_decoder.cc
+++ b/media/filters/ffmpeg_video_decoder.cc
@@ -158,13 +158,44 @@ void FFmpegVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream,
demuxer_stream_ = stream;
statistics_cb_ = statistics_cb;
- if (!ConfigureDecoder()) {
+ const VideoDecoderConfig& config = stream->video_decoder_config();
+
+ // TODO(scherkus): this check should go in Pipeline prior to creating
+ // decoder objects.
+ if (!config.IsValidConfig()) {
+ DLOG(ERROR) << "Invalid video stream - " << config.AsHumanReadableString();
+ status_cb.Run(PIPELINE_ERROR_DECODE);
+ return;
+ }
+
+ // Initialize AVCodecContext structure.
+ codec_context_ = avcodec_alloc_context3(NULL);
+ VideoDecoderConfigToAVCodecContext(config, codec_context_);
+
+ // Enable motion vector search (potentially slow), strong deblocking filter
+ // for damaged macroblocks, and set our error detection sensitivity.
+ codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
+ codec_context_->err_recognition = AV_EF_CAREFUL;
+ codec_context_->thread_count = GetThreadCount(codec_context_->codec_id);
+ codec_context_->opaque = this;
+ codec_context_->flags |= CODEC_FLAG_EMU_EDGE;
+ codec_context_->get_buffer = GetVideoBufferImpl;
+ codec_context_->release_buffer = ReleaseVideoBufferImpl;
+
+ AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
+ if (!codec) {
+ status_cb.Run(PIPELINE_ERROR_DECODE);
+ return;
+ }
+
+ if (avcodec_open2(codec_context_, codec, NULL) < 0) {
status_cb.Run(PIPELINE_ERROR_DECODE);
return;
}
// Success!
state_ = kNormal;
+ av_frame_ = avcodec_alloc_frame();
status_cb.Run(PIPELINE_OK);
}
@@ -289,18 +320,10 @@ void FFmpegVideoDecoder::DoDecryptOrDecodeBuffer(
return;
}
- if (status == DemuxerStream::kAborted) {
- base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
- return;
- }
-
- if (status == DemuxerStream::kConfigChanged) {
- if (!ConfigureDecoder()) {
- base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
- return;
- }
-
- ReadFromDemuxerStream();
+ if (status != DemuxerStream::kOk) {
+ Status decoder_status =
+ (status == DemuxerStream::kAborted) ? kOk : kDecodeError;
+ base::ResetAndReturn(&read_cb_).Run(decoder_status, NULL);
return;
}
@@ -501,40 +524,4 @@ void FFmpegVideoDecoder::ReleaseFFmpegResources() {
}
}
-bool FFmpegVideoDecoder::ConfigureDecoder() {
- const VideoDecoderConfig& config = demuxer_stream_->video_decoder_config();
-
- if (!config.IsValidConfig()) {
- DLOG(ERROR) << "Invalid video stream - " << config.AsHumanReadableString();
- return false;
- }
-
- // Release existing decoder resources if necessary.
- ReleaseFFmpegResources();
-
- // Initialize AVCodecContext structure.
- codec_context_ = avcodec_alloc_context3(NULL);
- VideoDecoderConfigToAVCodecContext(config, codec_context_);
-
- // Enable motion vector search (potentially slow), strong deblocking filter
- // for damaged macroblocks, and set our error detection sensitivity.
- codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
- codec_context_->err_recognition = AV_EF_CAREFUL;
- codec_context_->thread_count = GetThreadCount(codec_context_->codec_id);
- codec_context_->opaque = this;
- codec_context_->flags |= CODEC_FLAG_EMU_EDGE;
- codec_context_->get_buffer = GetVideoBufferImpl;
- codec_context_->release_buffer = ReleaseVideoBufferImpl;
-
- AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
- if (!codec)
- return false;
-
- if (avcodec_open2(codec_context_, codec, NULL) < 0)
- return false;
-
- av_frame_ = avcodec_alloc_frame();
- return true;
-}
-
} // namespace media
diff --git a/media/filters/ffmpeg_video_decoder.h b/media/filters/ffmpeg_video_decoder.h
index 340864d..a48e3b4 100644
--- a/media/filters/ffmpeg_video_decoder.h
+++ b/media/filters/ffmpeg_video_decoder.h
@@ -80,10 +80,6 @@ class MEDIA_EXPORT FFmpegVideoDecoder : public VideoDecoder {
bool Decode(const scoped_refptr<DecoderBuffer>& buffer,
scoped_refptr<VideoFrame>* video_frame);
- // Handles (re-)initializing the decoder with a (new) config.
- // Returns true if initialization was successful.
- bool ConfigureDecoder();
-
// Releases resources associated with |codec_context_| and |av_frame_|
// and resets them to NULL.
void ReleaseFFmpegResources();
diff --git a/media/filters/pipeline_integration_test.cc b/media/filters/pipeline_integration_test.cc
index 3f00b09..c5353f3 100644
--- a/media/filters/pipeline_integration_test.cc
+++ b/media/filters/pipeline_integration_test.cc
@@ -5,7 +5,6 @@
#include "media/filters/pipeline_integration_test_base.h"
#include "base/bind.h"
-#include "base/string_util.h"
#include "media/base/decoder_buffer.h"
#include "media/base/decryptor_client.h"
#include "media/base/test_data_util.h"
@@ -18,34 +17,25 @@ static const char kSourceId[] = "SourceId";
static const char kClearKeySystem[] = "org.w3.clearkey";
static const uint8 kInitData[] = { 0x69, 0x6e, 0x69, 0x74 };
-static const char kWebM[] = "video/webm; codecs=\"vp8,vorbis\"";
-static const char kAudioOnlyWebM[] = "video/webm; codecs=\"vorbis\"";
-static const char kVideoOnlyWebM[] = "video/webm; codecs=\"vp8\"";
-static const char kMP4[] = "video/mp4; codecs=\"avc1.4D4041,mp4a.40.2\"";
-
// Key used to encrypt video track in test file "bear-320x240-encrypted.webm".
static const uint8 kSecretKey[] = {
0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b,
0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c
};
-static const int kAppendWholeFile = -1;
-
// Helper class that emulates calls made on the ChunkDemuxer by the
// Media Source API.
class MockMediaSource : public ChunkDemuxerClient {
public:
- MockMediaSource(const std::string& filename, const std::string& mimetype,
- int initial_append_size)
+ MockMediaSource(const std::string& filename, int initial_append_size,
+ bool has_audio, bool has_video)
: url_(GetTestDataURL(filename)),
current_position_(0),
initial_append_size_(initial_append_size),
- mimetype_(mimetype) {
+ has_audio_(has_audio),
+ has_video_(has_video) {
file_data_ = ReadTestDataFile(filename);
- if (initial_append_size_ == kAppendWholeFile)
- initial_append_size_ = file_data_->GetDataSize();
-
DCHECK_GT(initial_append_size_, 0);
DCHECK_LE(initial_append_size_, file_data_->GetDataSize());
}
@@ -77,13 +67,6 @@ class MockMediaSource : public ChunkDemuxerClient {
current_position_ += size;
}
- void AppendAtTime(const base::TimeDelta& timestampOffset,
- const uint8* pData, int size) {
- CHECK(chunk_demuxer_->SetTimestampOffset(kSourceId, timestampOffset));
- CHECK(chunk_demuxer_->AppendData(kSourceId, pData, size));
- CHECK(chunk_demuxer_->SetTimestampOffset(kSourceId, base::TimeDelta()));
- }
-
void EndOfStream() {
chunk_demuxer_->EndOfStream(PIPELINE_OK);
}
@@ -98,15 +81,14 @@ class MockMediaSource : public ChunkDemuxerClient {
virtual void DemuxerOpened(ChunkDemuxer* demuxer) {
chunk_demuxer_ = demuxer;
- size_t semicolon = mimetype_.find(";");
- std::string type = mimetype_.substr(0, semicolon);
- size_t quote1 = mimetype_.find("\"");
- size_t quote2 = mimetype_.find("\"", quote1 + 1);
- std::string codecStr = mimetype_.substr(quote1 + 1, quote2 - quote1 - 1);
std::vector<std::string> codecs;
- Tokenize(codecStr, ",", &codecs);
+ if (has_audio_)
+ codecs.push_back("vorbis");
- CHECK_EQ(chunk_demuxer_->AddId(kSourceId, type, codecs), ChunkDemuxer::kOk);
+ if (has_video_)
+ codecs.push_back("vp8");
+
+ chunk_demuxer_->AddId(kSourceId, "video/webm", codecs);
AppendData(initial_append_size_);
}
@@ -127,7 +109,8 @@ class MockMediaSource : public ChunkDemuxerClient {
scoped_refptr<DecoderBuffer> file_data_;
int current_position_;
int initial_append_size_;
- std::string mimetype_;
+ bool has_audio_;
+ bool has_video_;
scoped_refptr<ChunkDemuxer> chunk_demuxer_;
DecryptorClient* decryptor_client_;
};
@@ -236,13 +219,14 @@ class PipelineIntegrationTest
// seek happens while there is a pending read on the ChunkDemuxer
// and no data is available.
bool TestSeekDuringRead(const std::string& filename,
- const std::string& mimetype,
int initial_append_size,
base::TimeDelta start_seek_time,
base::TimeDelta seek_time,
int seek_file_position,
- int seek_append_size) {
- MockMediaSource source(filename, mimetype, initial_append_size);
+ int seek_append_size,
+ bool has_audio,
+ bool has_video) {
+ MockMediaSource source(filename, initial_append_size, has_audio, has_video);
StartPipelineWithMediaSource(&source);
if (pipeline_status_ != PIPELINE_OK)
@@ -285,7 +269,7 @@ TEST_F(PipelineIntegrationTest, BasicPlaybackHashed) {
}
TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource) {
- MockMediaSource source("bear-320x240.webm", kWebM, 219229);
+ MockMediaSource source("bear-320x240.webm", 219229, true, true);
StartPipelineWithMediaSource(&source);
source.EndOfStream();
ASSERT_EQ(pipeline_status_, PIPELINE_OK);
@@ -301,57 +285,6 @@ TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource) {
Stop();
}
-TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_WebM) {
- MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM,
- kAppendWholeFile);
- StartPipelineWithMediaSource(&source);
-
- scoped_refptr<DecoderBuffer> second_file =
- ReadTestDataFile("bear-640x360.webm");
-
- source.AppendAtTime(base::TimeDelta::FromSeconds(2),
- second_file->GetData(), second_file->GetDataSize());
-
- source.EndOfStream();
- ASSERT_EQ(pipeline_status_, PIPELINE_OK);
-
- EXPECT_EQ(pipeline_->GetBufferedTimeRanges().size(), 1u);
- EXPECT_EQ(pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds(), 0);
- EXPECT_EQ(pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds(), 4763);
-
- Play();
-
- ASSERT_TRUE(WaitUntilOnEnded());
- source.Abort();
- Stop();
-}
-
-#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
-TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_MP4) {
- MockMediaSource source("bear.640x360_dash.mp4", kMP4, kAppendWholeFile);
- StartPipelineWithMediaSource(&source);
-
- scoped_refptr<DecoderBuffer> second_file =
- ReadTestDataFile("bear.1280x720_dash.mp4");
-
- source.AppendAtTime(base::TimeDelta::FromSeconds(2),
- second_file->GetData(), second_file->GetDataSize());
-
- source.EndOfStream();
- ASSERT_EQ(pipeline_status_, PIPELINE_OK);
-
- EXPECT_EQ(pipeline_->GetBufferedTimeRanges().size(), 1u);
- EXPECT_EQ(pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds(), 0);
- EXPECT_EQ(pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds(), 4736);
-
- Play();
-
- ASSERT_TRUE(WaitUntilOnEnded());
- source.Abort();
- Stop();
-}
-#endif
-
TEST_F(PipelineIntegrationTest, BasicPlayback_16x9AspectRatio) {
ASSERT_TRUE(Start(GetTestDataURL("bear-320x240-16x9-aspect.webm"),
PIPELINE_OK));
@@ -360,7 +293,7 @@ TEST_F(PipelineIntegrationTest, BasicPlayback_16x9AspectRatio) {
}
TEST_F(PipelineIntegrationTest, EncryptedPlayback) {
- MockMediaSource source("bear-320x240-encrypted.webm", kWebM, 220788);
+ MockMediaSource source("bear-320x240-encrypted.webm", 220788, true, true);
FakeDecryptorClient encrypted_media;
StartPipelineWithEncryptedMedia(&source, &encrypted_media);
@@ -420,20 +353,18 @@ TEST_F(PipelineIntegrationTest, DISABLED_SeekWhilePlaying) {
// Verify audio decoder & renderer can handle aborted demuxer reads.
TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_AudioOnly) {
- ASSERT_TRUE(TestSeekDuringRead("bear-320x240-audio-only.webm", kAudioOnlyWebM,
- 8192,
+ ASSERT_TRUE(TestSeekDuringRead("bear-320x240-audio-only.webm", 8192,
base::TimeDelta::FromMilliseconds(464),
base::TimeDelta::FromMilliseconds(617),
- 0x10CA, 19730));
+ 0x10CA, 19730, true, false));
}
// Verify video decoder & renderer can handle aborted demuxer reads.
TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) {
- ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", kVideoOnlyWebM,
- 32768,
+ ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", 32768,
base::TimeDelta::FromMilliseconds(200),
base::TimeDelta::FromMilliseconds(1668),
- 0x1C896, 65536));
+ 0x1C896, 65536, false, true));
}
} // namespace media
diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc
index c92b5fe..c768423 100644
--- a/media/filters/source_buffer_stream.cc
+++ b/media/filters/source_buffer_stream.cc
@@ -270,6 +270,8 @@ namespace media {
SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config)
: current_config_index_(0),
append_config_index_(0),
+ audio_configs_(1),
+ video_configs_(0),
stream_start_time_(kNoTimestamp()),
seek_pending_(false),
seek_buffer_timestamp_(kNoTimestamp()),
@@ -280,14 +282,15 @@ SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config)
last_buffer_timestamp_(kNoTimestamp()),
max_interbuffer_distance_(kNoTimestamp()),
memory_limit_(kDefaultAudioMemoryLimit) {
- DCHECK(audio_config.IsValidConfig());
- audio_configs_.push_back(new AudioDecoderConfig());
- audio_configs_.back()->CopyFrom(audio_config);
+ audio_configs_[0] = new AudioDecoderConfig();
+ audio_configs_[0]->CopyFrom(audio_config);
}
SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config)
: current_config_index_(0),
append_config_index_(0),
+ audio_configs_(0),
+ video_configs_(1),
stream_start_time_(kNoTimestamp()),
seek_pending_(false),
seek_buffer_timestamp_(kNoTimestamp()),
@@ -298,9 +301,8 @@ SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config)
last_buffer_timestamp_(kNoTimestamp()),
max_interbuffer_distance_(kNoTimestamp()),
memory_limit_(kDefaultVideoMemoryLimit) {
- DCHECK(video_config.IsValidConfig());
- video_configs_.push_back(new VideoDecoderConfig());
- video_configs_.back()->CopyFrom(video_config);
+ video_configs_[0] = new VideoDecoderConfig();
+ video_configs_[0]->CopyFrom(video_config);
}
SourceBufferStream::~SourceBufferStream() {
@@ -734,7 +736,6 @@ void SourceBufferStream::Seek(base::TimeDelta timestamp) {
DCHECK(timestamp >= stream_start_time_);
SetSelectedRange(NULL);
track_buffer_.clear();
- config_change_pending_ = false;
if (ShouldSeekToStartOfBuffered(timestamp)) {
SetSelectedRange(ranges_.front());
@@ -766,13 +767,9 @@ bool SourceBufferStream::IsSeekPending() const {
SourceBufferStream::Status SourceBufferStream::GetNextBuffer(
scoped_refptr<StreamParserBuffer>* out_buffer) {
- CHECK(!config_change_pending_);
-
if (!track_buffer_.empty()) {
- if (track_buffer_.front()->GetConfigId() != current_config_index_) {
- config_change_pending_ = true;
+ if (track_buffer_.front()->GetConfigId() != current_config_index_)
return kConfigChange;
- }
*out_buffer = track_buffer_.front();
track_buffer_.pop_front();
@@ -782,10 +779,8 @@ SourceBufferStream::Status SourceBufferStream::GetNextBuffer(
if (!selected_range_ || !selected_range_->HasNextBuffer())
return kNeedBuffer;
- if (selected_range_->GetNextConfigId() != current_config_index_) {
- config_change_pending_ = true;
+ if (selected_range_->GetNextConfigId() != current_config_index_)
return kConfigChange;
- }
CHECK(selected_range_->GetNextBuffer(out_buffer));
return kSuccess;
@@ -857,14 +852,12 @@ bool SourceBufferStream::IsEndSelected() const {
}
const AudioDecoderConfig& SourceBufferStream::GetCurrentAudioDecoderConfig() {
- if (config_change_pending_)
- CompleteConfigChange();
+ CompleteConfigChange();
return *audio_configs_[current_config_index_];
}
const VideoDecoderConfig& SourceBufferStream::GetCurrentVideoDecoderConfig() {
- if (config_change_pending_)
- CompleteConfigChange();
+ CompleteConfigChange();
return *video_configs_[current_config_index_];
}
@@ -940,15 +933,15 @@ bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config) {
}
void SourceBufferStream::CompleteConfigChange() {
- config_change_pending_ = false;
-
if (!track_buffer_.empty()) {
current_config_index_ = track_buffer_.front()->GetConfigId();
return;
}
- if (selected_range_ && selected_range_->HasNextBuffer())
- current_config_index_ = selected_range_->GetNextConfigId();
+ if (!selected_range_ || !selected_range_->HasNextBuffer())
+ return;
+
+ current_config_index_ = selected_range_->GetNextConfigId();
}
SourceBufferRange::SourceBufferRange(
diff --git a/media/filters/source_buffer_stream.h b/media/filters/source_buffer_stream.h
index 0e08327..e67a84d 100644
--- a/media/filters/source_buffer_stream.h
+++ b/media/filters/source_buffer_stream.h
@@ -258,15 +258,9 @@ class MEDIA_EXPORT SourceBufferStream {
// Stores the largest distance between two adjacent buffers in this stream.
base::TimeDelta max_interbuffer_distance_;
- // The maximum amount of data in bytes the stream will keep in memory.
+// The maximum amount of data in bytes the stream will keep in memory.
int memory_limit_;
- // Indicates that a kConfigChanged status has been reported by GetNextBuffer()
- // and GetCurrentXXXDecoderConfig() must be called to update the current
- // config. GetNextBuffer() must not be called again until
- // GetCurrentXXXDecoderConfig() has been called.
- bool config_change_pending_;
-
DISALLOW_COPY_AND_ASSIGN(SourceBufferStream);
};
diff --git a/media/filters/source_buffer_stream_unittest.cc b/media/filters/source_buffer_stream_unittest.cc
index 1f46d0f..4033869 100644
--- a/media/filters/source_buffer_stream_unittest.cc
+++ b/media/filters/source_buffer_stream_unittest.cc
@@ -15,14 +15,10 @@ static const int kDefaultKeyframesPerSecond = 6;
static const uint8 kDataA = 0x11;
static const uint8 kDataB = 0x33;
static const int kDataSize = 1;
-static const gfx::Size kCodedSize(320, 240);
class SourceBufferStreamTest : public testing::Test {
protected:
SourceBufferStreamTest() {
- config_.Initialize(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN,
- VideoFrame::YV12, kCodedSize, gfx::Rect(kCodedSize),
- kCodedSize, NULL, 0, false);
stream_.reset(new SourceBufferStream(config_));
SetStreamInfo(kDefaultFramesPerSecond, kDefaultKeyframesPerSecond);
@@ -123,10 +119,7 @@ class SourceBufferStreamTest : public testing::Test {
int current_position = starting_position;
for (; current_position <= ending_position; current_position++) {
scoped_refptr<StreamParserBuffer> buffer;
- SourceBufferStream::Status status = stream_->GetNextBuffer(&buffer);
-
- EXPECT_NE(status, SourceBufferStream::kConfigChange);
- if (status != SourceBufferStream::kSuccess)
+ if (stream_->GetNextBuffer(&buffer) == SourceBufferStream::kNeedBuffer)
break;
if (expect_keyframe && current_position == starting_position)
@@ -153,13 +146,6 @@ class SourceBufferStreamTest : public testing::Test {
EXPECT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kNeedBuffer);
}
- void CheckConfig(const VideoDecoderConfig& config) {
- const VideoDecoderConfig& actual = stream_->GetCurrentVideoDecoderConfig();
- EXPECT_TRUE(actual.Matches(config))
- << "Expected: " << config.AsHumanReadableString()
- << "\nActual: " << actual.AsHumanReadableString();
- }
-
base::TimeDelta frame_duration() const { return frame_duration_; }
scoped_ptr<SourceBufferStream> stream_;
@@ -1836,93 +1822,6 @@ TEST_F(SourceBufferStreamTest, DISABLED_GarbageCollection_WaitingForKeyframe) {
CheckExpectedRanges("{ [15,15) [20,28) }");
}
-TEST_F(SourceBufferStreamTest, ConfigChange_Basic) {
- gfx::Size kNewCodedSize(kCodedSize.width() * 2, kCodedSize.height() * 2);
- VideoDecoderConfig new_config(
- kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN, VideoFrame::YV12, kNewCodedSize,
- gfx::Rect(kNewCodedSize), kNewCodedSize, NULL, 0);
- ASSERT_FALSE(new_config.Matches(config_));
-
- Seek(0);
- CheckConfig(config_);
-
- // Append 5 buffers at positions 0 through 4
- NewSegmentAppend(0, 5, &kDataA);
-
- CheckConfig(config_);
-
- // Signal a config change.
- stream_->UpdateVideoConfig(new_config);
-
- // Make sure updating the config doesn't change anything since new_config
- // should not be associated with the buffer GetNextBuffer() will return.
- CheckConfig(config_);
-
- // Append 5 buffers at positions 5 through 9.
- NewSegmentAppend(5, 5, &kDataB);
-
- // Consume the buffers associated with the initial config.
- scoped_refptr<StreamParserBuffer> buffer;
- for (int i = 0; i < 5; i++) {
- EXPECT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kSuccess);
- CheckConfig(config_);
- }
-
- // Verify the next attempt to get a buffer will signal that a config change
- // has happened.
- EXPECT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kConfigChange);
-
- // Verify that the new config is now returned.
- CheckConfig(new_config);
-
- // Consume the remaining buffers associated with the new config.
- for (int i = 0; i < 5; i++) {
- CheckConfig(new_config);
- EXPECT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kSuccess);
- }
-}
-
-TEST_F(SourceBufferStreamTest, ConfigChange_Seek) {
- scoped_refptr<StreamParserBuffer> buffer;
- gfx::Size kNewCodedSize(kCodedSize.width() * 2, kCodedSize.height() * 2);
- VideoDecoderConfig new_config(
- kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN, VideoFrame::YV12, kNewCodedSize,
- gfx::Rect(kNewCodedSize), kNewCodedSize, NULL, 0);
-
- Seek(0);
- NewSegmentAppend(0, 5, &kDataA);
- stream_->UpdateVideoConfig(new_config);
- NewSegmentAppend(5, 5, &kDataB);
-
- // Seek to the start of the buffers with the new config and make sure a
- // config change is signalled.
- CheckConfig(config_);
- Seek(5);
- CheckConfig(config_);
- EXPECT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kConfigChange);
- CheckConfig(new_config);
- CheckExpectedBuffers(5, 9, &kDataB);
-
-
- // Seek to the start which has a different config. Don't fetch any buffers and
- // seek back to buffers with the current config. Make sure a config change
- // isn't signalled in this case.
- CheckConfig(new_config);
- Seek(0);
- Seek(7);
- CheckExpectedBuffers(5, 9, &kDataB);
-
-
- // Seek to the start and make sure a config change is signalled.
- CheckConfig(new_config);
- Seek(0);
- CheckConfig(new_config);
- EXPECT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kConfigChange);
- CheckConfig(config_);
- CheckExpectedBuffers(0, 4, &kDataA);
-}
-
-
// TODO(vrk): Add unit tests where keyframes are unaligned between streams.
// (crbug.com/133557)
diff --git a/media/mp4/mp4_stream_parser.cc b/media/mp4/mp4_stream_parser.cc
index b025b7a..1aa8c70 100644
--- a/media/mp4/mp4_stream_parser.cc
+++ b/media/mp4/mp4_stream_parser.cc
@@ -237,7 +237,14 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
}
}
- RCHECK(config_cb_.Run(audio_config, video_config));
+ // TODO(strobe): For now, we avoid sending new configs on a new
+ // reinitialization segment, and instead simply embed the updated parameter
+ // sets into the video stream. The conditional should be removed when
+ // http://crbug.com/122913 is fixed. (We detect whether we've already sent
+ // configs by looking at init_cb_ instead of config_cb_, because init_cb_
+ // should only be fired once even after that bug is fixed.)
+ if (!init_cb_.is_null())
+ RCHECK(config_cb_.Run(audio_config, video_config));
base::TimeDelta duration;
if (moov_->extends.header.fragment_duration > 0) {
diff --git a/media/mp4/mp4_stream_parser_unittest.cc b/media/mp4/mp4_stream_parser_unittest.cc
index 20c32f1..830f35b 100644
--- a/media/mp4/mp4_stream_parser_unittest.cc
+++ b/media/mp4/mp4_stream_parser_unittest.cc
@@ -62,6 +62,11 @@ class MP4StreamParserTest : public testing::Test {
const VideoDecoderConfig& vc) {
DVLOG(1) << "NewConfigF: audio=" << ac.IsValidConfig()
<< ", video=" << vc.IsValidConfig();
+
+ // TODO(strobe): Until http://crbug.com/122913 is fixed, we want to make
+ // sure that this callback isn't called more than once per stream. Remove
+ // when that bug is fixed.
+ EXPECT_FALSE(configs_received_);
configs_received_ = true;
return true;
}