Index: media/filters/chunk_demuxer.cc |
diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc |
index 8862ad15fa50cf4f3d07f7716a68f017be04c686..5efc64673b2df998091b546c4b45537dd6759fbe 100644 |
--- a/media/filters/chunk_demuxer.cc |
+++ b/media/filters/chunk_demuxer.cc |
@@ -362,9 +362,7 @@ ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client) |
: state_(WAITING_FOR_INIT), |
host_(NULL), |
client_(client), |
- buffered_bytes_(0), |
- has_audio_(false), |
- has_video_(false) { |
+ buffered_bytes_(0) { |
DCHECK(client); |
} |
@@ -465,6 +463,10 @@ ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, |
const std::string& type, |
std::vector<std::string>& codecs) { |
DCHECK_GT(codecs.size(), 0u); |
+ base::AutoLock auto_lock(lock_); |
+ |
+ if (state_ != WAITING_FOR_INIT && state_ != INITIALIZING) |
+ return kReachedIdLimit; |
bool has_audio = false; |
bool has_video = false; |
@@ -472,55 +474,59 @@ ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, |
if (!IsSupported(type, codecs, &factory_function, &has_audio, &has_video)) |
return kNotSupported; |
- // TODO(acolwell): Support for more than one ID |
- // will be added as part of http://crbug.com/122909 |
- if (!source_id_.empty() || |
- (has_audio && has_audio_) || |
- (has_video && has_video_)) |
+ if ((has_audio && !source_id_audio_.empty()) || |
+ (has_video && !source_id_video_.empty())) |
return kReachedIdLimit; |
- source_id_ = id; |
- |
StreamParser::NewBuffersCB audio_cb; |
StreamParser::NewBuffersCB video_cb; |
if (has_audio) { |
- has_audio_ = true; |
+ source_id_audio_ = id; |
audio_cb = base::Bind(&ChunkDemuxer::OnAudioBuffers, |
base::Unretained(this)); |
} |
if (has_video) { |
- has_video_ = true; |
+ source_id_video_ = id; |
video_cb = base::Bind(&ChunkDemuxer::OnVideoBuffers, |
base::Unretained(this)); |
} |
- stream_parser_.reset(factory_function()); |
- CHECK(stream_parser_.get()); |
+ scoped_ptr<StreamParser> stream_parser(factory_function()); |
+ CHECK(stream_parser.get()); |
- stream_parser_->Init( |
+ stream_parser->Init( |
base::Bind(&ChunkDemuxer::OnStreamParserInitDone, this), |
- base::Bind(&ChunkDemuxer::OnNewConfigs, base::Unretained(this)), |
+ base::Bind(&ChunkDemuxer::OnNewConfigs, base::Unretained(this), |
+ has_audio, has_video), |
audio_cb, |
video_cb, |
base::Bind(&ChunkDemuxer::OnKeyNeeded, base::Unretained(this))); |
+ stream_parser_map_[id] = stream_parser.release(); |
+ |
return kOk; |
} |
void ChunkDemuxer::RemoveId(const std::string& id) { |
- CHECK(!source_id_.empty()); |
- CHECK_EQ(source_id_, id); |
- source_id_ = ""; |
- has_audio_ = false; |
- has_video_ = false; |
+ CHECK_GT(stream_parser_map_.count(id), 0u); |
+ base::AutoLock auto_lock(lock_); |
+ |
+ delete stream_parser_map_[id]; |
+ stream_parser_map_.erase(id); |
+ |
+ if (source_id_audio_ == id && audio_) |
+ audio_->Shutdown(); |
+ |
+ if (source_id_video_ == id && video_) |
+ video_->Shutdown(); |
} |
bool ChunkDemuxer::GetBufferedRanges(const std::string& id, |
Ranges* ranges_out) const { |
DCHECK(!id.empty()); |
- DCHECK_EQ(source_id_, id); |
+ DCHECK_GT(stream_parser_map_.count(id), 0u); |
DCHECK(ranges_out); |
base::AutoLock auto_lock(lock_); |
@@ -535,15 +541,14 @@ bool ChunkDemuxer::AppendData(const std::string& id, |
DVLOG(1) << "AppendData(" << id << ", " << length << ")"; |
// TODO(acolwell): Remove when http://webk.it/83788 fix lands. |
- if (source_id_.empty()) { |
+ if (stream_parser_map_.count(id) == 0) { |
std::vector<std::string> codecs(2); |
codecs[0] = "vp8"; |
codecs[1] = "vorbis"; |
AddId(id, "video/webm", codecs); |
} |
- DCHECK(!source_id_.empty()); |
- DCHECK_EQ(source_id_, id); |
+ DCHECK_GT(stream_parser_map_.count(id), 0u); |
DCHECK(!id.empty()); |
DCHECK(data); |
DCHECK_GT(length, 0u); |
@@ -559,7 +564,7 @@ bool ChunkDemuxer::AppendData(const std::string& id, |
switch (state_) { |
case INITIALIZING: |
- if (!stream_parser_->Parse(data, length)) { |
+ if (!stream_parser_map_[id]->Parse(data, length)) { |
DCHECK_EQ(state_, INITIALIZING); |
ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
return true; |
@@ -567,7 +572,7 @@ bool ChunkDemuxer::AppendData(const std::string& id, |
break; |
case INITIALIZED: { |
- if (!stream_parser_->Parse(data, length)) { |
+ if (!stream_parser_map_[id]->Parse(data, length)) { |
ReportError_Locked(PIPELINE_ERROR_DECODE); |
return true; |
} |
@@ -606,9 +611,9 @@ bool ChunkDemuxer::AppendData(const std::string& id, |
void ChunkDemuxer::Abort(const std::string& id) { |
DVLOG(1) << "Abort(" << id << ")"; |
DCHECK(!id.empty()); |
- DCHECK_EQ(source_id_, id); |
+ DCHECK_GT(stream_parser_map_.count(id), 0u); |
- stream_parser_->Flush(); |
+ stream_parser_map_[id]->Flush(); |
} |
bool ChunkDemuxer::EndOfStream(PipelineStatus status) { |
@@ -659,7 +664,10 @@ void ChunkDemuxer::Shutdown() { |
if (video_) |
video_->Shutdown(); |
- stream_parser_.reset(); |
+ for (StreamParserMap::iterator it = stream_parser_map_.begin(); |
+ it != stream_parser_map_.end(); ++it) |
+ delete it->second; |
acolwell GONE FROM CHROMIUM
2012/06/11 16:09:33
nit: Add {} since this spans multiple lines.
annacc
2012/06/11 19:23:08
Done.
|
+ stream_parser_map_.clear(); |
ChangeState_Locked(SHUTDOWN); |
} |
@@ -679,6 +687,10 @@ void ChunkDemuxer::ChangeState_Locked(State new_state) { |
ChunkDemuxer::~ChunkDemuxer() { |
DCHECK_NE(state_, INITIALIZED); |
+ for (StreamParserMap::iterator it = stream_parser_map_.begin(); |
+ it != stream_parser_map_.end(); ++it) |
+ delete it->second; |
acolwell GONE FROM CHROMIUM
2012/06/11 16:09:33
nit: Add {} since this spans multiple lines.
annacc
2012/06/11 19:23:08
Done.
|
+ stream_parser_map_.clear(); |
} |
void ChunkDemuxer::ReportError_Locked(PipelineStatus error) { |
@@ -743,7 +755,14 @@ void ChunkDemuxer::OnStreamParserInitDone(bool success, |
return; |
} |
- duration_ = duration; |
+ if (duration > duration_) |
+ duration_ = duration; |
+ |
+ // Wait until all streams have initialized. |
+ if ((!source_id_audio_.empty() && !audio_) || |
+ (!source_id_video_.empty() && !video_)) |
+ return; |
+ |
host_->SetDuration(duration_); |
ChangeState_Locked(INITIALIZED); |
@@ -752,7 +771,8 @@ void ChunkDemuxer::OnStreamParserInitDone(bool success, |
cb.Run(PIPELINE_OK); |
} |
-bool ChunkDemuxer::OnNewConfigs(const AudioDecoderConfig& audio_config, |
+bool ChunkDemuxer::OnNewConfigs(bool has_audio, bool has_video, |
+ const AudioDecoderConfig& audio_config, |
const VideoDecoderConfig& video_config) { |
CHECK(audio_config.IsValidConfig() || video_config.IsValidConfig()); |
lock_.AssertAcquired(); |
@@ -760,11 +780,11 @@ bool ChunkDemuxer::OnNewConfigs(const AudioDecoderConfig& audio_config, |
// Signal an error if we get configuration info for stream types that weren't |
// specified in AddId() or more configs after a stream is initialized. |
// Only allow a single audio config for now. |
- if (audio_config.IsValidConfig() && (!has_audio_ || audio_)) |
+ if (audio_config.IsValidConfig() && (!has_audio || audio_)) |
return false; |
// Only allow a single video config for now. |
- if (video_config.IsValidConfig() && (!has_video_ || video_)) |
+ if (video_config.IsValidConfig() && (!has_video || video_)) |
return false; |
if (audio_config.IsValidConfig()) |