From c68ee655740ce93d1269b766f650e6b3cda8a825 Mon Sep 17 00:00:00 2001 From: "annacc@chromium.org" Date: Tue, 5 Jun 2012 00:55:16 +0000 Subject: Reorganize so that ChunkDemuxerStreams create and own SourceBufferStreams. This patch moves SourceBufferStream into ChunkDemuxerStream and removes SourceBuffer altogether. ChunkDemuxer now manages a StreamParser and passes data along to ChunkDemuxerStreams when new data is parsed. BUG=130876 TEST=ChunkDemuxerTest.* Review URL: https://chromiumcodereview.appspot.com/10505009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@140453 0039d316-1c4b-4281-b951-d872f2087c98 --- media/filters/chunk_demuxer.cc | 259 ++++++++++++++++++++++------------------- media/filters/chunk_demuxer.h | 45 +++---- media/filters/source_buffer.cc | 173 --------------------------- media/filters/source_buffer.h | 99 ---------------- media/media.gyp | 2 - 5 files changed, 155 insertions(+), 423 deletions(-) delete mode 100644 media/filters/source_buffer.cc delete mode 100644 media/filters/source_buffer.h (limited to 'media') diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc index 3852704..3e3326d 100644 --- a/media/filters/chunk_demuxer.cc +++ b/media/filters/chunk_demuxer.cc @@ -121,14 +121,20 @@ class ChunkDemuxerStream : public DemuxerStream { typedef std::deque ReadCBQueue; typedef std::deque ClosureQueue; - ChunkDemuxerStream(Type type, ChunkDemuxer* chunk_demuxer); + explicit ChunkDemuxerStream(const AudioDecoderConfig& audio_config); + explicit ChunkDemuxerStream(const VideoDecoderConfig& video_config); void StartWaitingForSeek(); void Seek(base::TimeDelta time); + bool IsSeekPending() const; - // Notifies this stream of new buffers. - void OnBuffersAvailable(); + // Add buffers to this stream. Buffers are stored in SourceBufferStreams, + // which handle ordering and overlap resolution. + // Returns true if buffers were successfully added. + bool Append(const StreamParser::BufferQueue& buffers); + void EndOfStream(); + bool CanEndOfStream() const; void Shutdown(); // DemuxerStream methods. @@ -162,9 +168,7 @@ class ChunkDemuxerStream : public DemuxerStream { // Specifies the type of the stream (must be AUDIO or VIDEO for now). Type type_; - // Pointer to the ChunkDemuxer that owns this ChunkDemuxerStream. Used for - // read requests to SourceBuffer. - ChunkDemuxer* chunk_demuxer_; + scoped_ptr stream_; mutable base::Lock lock_; State state_; @@ -173,10 +177,17 @@ class ChunkDemuxerStream : public DemuxerStream { DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); }; -ChunkDemuxerStream::ChunkDemuxerStream(Type type, ChunkDemuxer* chunk_demuxer) - : type_(type), - chunk_demuxer_(chunk_demuxer), - state_(RETURNING_DATA_FOR_READS) {} +ChunkDemuxerStream::ChunkDemuxerStream(const AudioDecoderConfig& audio_config) + : type_(AUDIO), + state_(RETURNING_DATA_FOR_READS) { + stream_.reset(new SourceBufferStream(audio_config)); +} + +ChunkDemuxerStream::ChunkDemuxerStream(const VideoDecoderConfig& video_config) + : type_(VIDEO), + state_(RETURNING_DATA_FOR_READS) { + stream_.reset(new SourceBufferStream(video_config)); +} void ChunkDemuxerStream::StartWaitingForSeek() { DVLOG(1) << "StartWaitingForSeek()"; @@ -197,20 +208,51 @@ void ChunkDemuxerStream::Seek(base::TimeDelta time) { DCHECK(read_cbs_.empty()); + stream_->Seek(time); + if (state_ == WAITING_FOR_SEEK) ChangeState_Locked(RETURNING_DATA_FOR_READS); } -void ChunkDemuxerStream::OnBuffersAvailable() { +bool ChunkDemuxerStream::IsSeekPending() const { + base::AutoLock auto_lock(lock_); + return stream_->IsSeekPending(); +} + +bool ChunkDemuxerStream::Append(const StreamParser::BufferQueue& buffers) { + if (buffers.empty()) + return false; + ClosureQueue closures; { base::AutoLock auto_lock(lock_); DCHECK_NE(state_, SHUTDOWN); + if (!stream_->Append(buffers)) + return false; CreateReadDoneClosures_Locked(&closures); } for (ClosureQueue::iterator it = closures.begin(); it != closures.end(); ++it) it->Run(); + + return true; +} + +void ChunkDemuxerStream::EndOfStream() { + ClosureQueue closures; + { + base::AutoLock auto_lock(lock_); + stream_->EndOfStream(); + CreateReadDoneClosures_Locked(&closures); + } + + for (ClosureQueue::iterator it = closures.begin(); it != closures.end(); ++it) + it->Run(); +} + +bool ChunkDemuxerStream::CanEndOfStream() const { + base::AutoLock auto_lock(lock_); + return stream_->CanEndOfStream(); } void ChunkDemuxerStream::Shutdown() { @@ -218,7 +260,6 @@ void ChunkDemuxerStream::Shutdown() { { base::AutoLock auto_lock(lock_); ChangeState_Locked(SHUTDOWN); - chunk_demuxer_ = NULL; std::swap(read_cbs_, read_cbs); } @@ -249,40 +290,12 @@ void ChunkDemuxerStream::Read(const ReadCB& read_cb) { switch (state_) { case RETURNING_DATA_FOR_READS: - // If we already have pending reads, then defer this read. - if (!read_cbs_.empty()) { + // If we already have pending reads or we don't have any buffers ready, + // then defer this read. + if (!read_cbs_.empty() || !stream_->GetNextBuffer(&buffer)) { DeferRead_Locked(read_cb); return; } - - bool read_success; - { - // Hold a reference to |chunk_demuxer_| just in case we get a - // Shutdown() call while unlocked. - scoped_refptr chunk_demuxer = chunk_demuxer_; - - // Unlock is necessary to avoid deadlock with OnBuffersAvailable(). - base::AutoUnlock auto_unlock(lock_); - read_success = chunk_demuxer->SourceBufferRead(type_, &buffer); - } - - // Check whether the state may have changed during the unlock. - switch (state_) { - case RETURNING_DATA_FOR_READS: - if (!read_success) { - DeferRead_Locked(read_cb); - return; - } - break; - case WAITING_FOR_SEEK: - DCHECK(read_cbs_.empty()); - buffer = NULL; - break; - case SHUTDOWN: - DCHECK(read_cbs_.empty()); - buffer = StreamParserBuffer::CreateEOSBuffer(); - } - break; case WAITING_FOR_SEEK: // Null buffers should be returned in this state since we are waiting @@ -305,12 +318,14 @@ void ChunkDemuxerStream::EnableBitstreamConverter() {} const AudioDecoderConfig& ChunkDemuxerStream::audio_decoder_config() { CHECK_EQ(type_, AUDIO); - return chunk_demuxer_->GetCurrentAudioDecoderConfig(); + base::AutoLock auto_lock(lock_); + return stream_->GetCurrentAudioDecoderConfig(); } const VideoDecoderConfig& ChunkDemuxerStream::video_decoder_config() { CHECK_EQ(type_, VIDEO); - return chunk_demuxer_->GetCurrentVideoDecoderConfig(); + base::AutoLock auto_lock(lock_); + return stream_->GetCurrentVideoDecoderConfig(); } void ChunkDemuxerStream::ChangeState_Locked(State state) { @@ -336,7 +351,7 @@ void ChunkDemuxerStream::CreateReadDoneClosures_Locked(ClosureQueue* closures) { scoped_refptr buffer; while (!read_cbs_.empty()) { - if (!chunk_demuxer_->SourceBufferRead_Locked(type_, &buffer)) + if (!stream_->GetNextBuffer(&buffer)) return; closures->push_back(base::Bind(read_cbs_.front(), buffer)); read_cbs_.pop_front(); @@ -347,7 +362,9 @@ ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client) : state_(WAITING_FOR_INIT), host_(NULL), client_(client), - buffered_bytes_(0) { + buffered_bytes_(0), + has_audio_(false), + has_video_(false) { DCHECK(client); } @@ -386,9 +403,7 @@ void ChunkDemuxer::Seek(base::TimeDelta time, const PipelineStatusCB& cb) { if (video_) video_->Seek(time); - source_buffer_->Seek(time); - - if (source_buffer_->IsSeekPending()) { + if (IsSeekPending_Locked()) { DVLOG(1) << "Seek() : waiting for more data to arrive."; seek_cb_ = cb; return; @@ -437,13 +452,13 @@ void ChunkDemuxer::StartWaitingForSeek() { if (state_ == SHUTDOWN) return; - if (audio_.get()) + if (audio_) audio_->StartWaitingForSeek(); - if (video_.get()) + if (video_) video_->StartWaitingForSeek(); - source_buffer_->ResetParser(); + stream_parser_->Flush(); ChangeState_Locked(INITIALIZED); } @@ -461,32 +476,33 @@ ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, // TODO(acolwell): Support for more than one ID // will be added as part of http://crbug.com/122909 - if (!source_id_.empty()) + if (!source_id_.empty() || + (has_audio && has_audio_) || + (has_video && has_video_)) return kReachedIdLimit; source_id_ = id; - SourceBuffer::NewBuffersCB audio_cb; - SourceBuffer::NewBuffersCB video_cb; + StreamParser::NewBuffersCB audio_cb; + StreamParser::NewBuffersCB video_cb; if (has_audio) { + has_audio_ = true; audio_cb = base::Bind(&ChunkDemuxer::OnAudioBuffers, base::Unretained(this)); } if (has_video) { + has_video_ = true; video_cb = base::Bind(&ChunkDemuxer::OnVideoBuffers, base::Unretained(this)); } - scoped_ptr stream_parser(factory_function()); - - CHECK(stream_parser.get()); + stream_parser_.reset(factory_function()); + CHECK(stream_parser_.get()); - source_buffer_.reset(new SourceBuffer()); - source_buffer_->Init( - stream_parser.Pass(), - base::Bind(&ChunkDemuxer::OnSourceBufferInitDone, this), + stream_parser_->Init( + base::Bind(&ChunkDemuxer::OnStreamParserInitDone, this), base::Bind(&ChunkDemuxer::OnNewConfigs, base::Unretained(this)), audio_cb, video_cb, @@ -509,7 +525,8 @@ bool ChunkDemuxer::GetBufferedRanges(const std::string& id, base::AutoLock auto_lock(lock_); - return source_buffer_->GetBufferedRanges(ranges_out); + // TODO(annacc): Calculate buffered ranges (http://crbug.com/129852 ). + return false; } bool ChunkDemuxer::AppendData(const std::string& id, @@ -538,11 +555,11 @@ bool ChunkDemuxer::AppendData(const std::string& id, base::AutoLock auto_lock(lock_); // Capture if the SourceBuffer has a pending seek before we start parsing. - bool old_seek_pending = source_buffer_->IsSeekPending(); + bool old_seek_pending = IsSeekPending_Locked(); switch (state_) { case INITIALIZING: - if (!source_buffer_->AppendData(data, length)) { + if (!stream_parser_->Parse(data, length)) { DCHECK_EQ(state_, INITIALIZING); ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); return true; @@ -550,7 +567,7 @@ bool ChunkDemuxer::AppendData(const std::string& id, break; case INITIALIZED: { - if (!source_buffer_->AppendData(data, length)) { + if (!stream_parser_->Parse(data, length)) { ReportError_Locked(PIPELINE_ERROR_DECODE); return true; } @@ -566,8 +583,7 @@ bool ChunkDemuxer::AppendData(const std::string& id, // Check to see if data was appended at the pending seek point. This // indicates we have parsed enough data to complete the seek. - if (old_seek_pending && !source_buffer_->IsSeekPending() && - !seek_cb_.is_null()) { + if (old_seek_pending && !IsSeekPending_Locked() && !seek_cb_.is_null()) { std::swap(cb, seek_cb_); } @@ -591,31 +607,7 @@ void ChunkDemuxer::Abort(const std::string& id) { DCHECK(!id.empty()); DCHECK_EQ(source_id_, id); - source_buffer_->ResetParser(); -} - -const AudioDecoderConfig& ChunkDemuxer::GetCurrentAudioDecoderConfig() { - base::AutoLock auto_lock(lock_); - return source_buffer_->GetCurrentAudioDecoderConfig(); -} - -const VideoDecoderConfig& ChunkDemuxer::GetCurrentVideoDecoderConfig() { - base::AutoLock auto_lock(lock_); - return source_buffer_->GetCurrentVideoDecoderConfig(); -} - -bool ChunkDemuxer::SourceBufferRead(DemuxerStream::Type type, - scoped_refptr* out_buffer) { - base::AutoLock auto_lock(lock_); - return SourceBufferRead_Locked(type, out_buffer); -} - -bool ChunkDemuxer::SourceBufferRead_Locked(DemuxerStream::Type type, - scoped_refptr* out_buffer) { - lock_.AssertAcquired(); - if (!source_buffer_.get()) - return false; - return source_buffer_->Read(type, out_buffer); + stream_parser_->Flush(); } bool ChunkDemuxer::EndOfStream(PipelineStatus status) { @@ -632,9 +624,15 @@ bool ChunkDemuxer::EndOfStream(PipelineStatus status) { return true; } - if (!source_buffer_->EndOfStream() && status == PIPELINE_OK) + if (!CanEndOfStream_Locked() && status == PIPELINE_OK) return false; + if (audio_) + audio_->EndOfStream(); + + if (video_) + video_->EndOfStream(); + ChangeState_Locked(ENDED); if (status != PIPELINE_OK) @@ -654,13 +652,13 @@ void ChunkDemuxer::Shutdown() { std::swap(cb, seek_cb_); - if (audio_.get()) + if (audio_) audio_->Shutdown(); - if (video_.get()) + if (video_) video_->Shutdown(); - source_buffer_.reset(); + stream_parser_.reset(); ChangeState_Locked(SHUTDOWN); } @@ -694,10 +692,10 @@ void ChunkDemuxer::ReportError_Locked(PipelineStatus error) { if (!seek_cb_.is_null()) std::swap(cb, seek_cb_); - if (audio_.get()) + if (audio_) audio_->Shutdown(); - if (video_.get()) + if (video_) video_->Shutdown(); } @@ -711,11 +709,30 @@ void ChunkDemuxer::ReportError_Locked(PipelineStatus error) { host_->OnDemuxerError(error); } -void ChunkDemuxer::OnSourceBufferInitDone(bool success, +bool ChunkDemuxer::IsSeekPending_Locked() const { + lock_.AssertAcquired(); + bool seek_pending = false; + + if (audio_) + seek_pending = audio_->IsSeekPending(); + + if (!seek_pending && video_) + seek_pending = video_->IsSeekPending(); + + return seek_pending; +} + +bool ChunkDemuxer::CanEndOfStream_Locked() const { + lock_.AssertAcquired(); + return (!audio_ || audio_->CanEndOfStream()) && + (!video_ || video_->CanEndOfStream()); +} + +void ChunkDemuxer::OnStreamParserInitDone(bool success, base::TimeDelta duration) { lock_.AssertAcquired(); DCHECK_EQ(state_, INITIALIZING); - if (!success || (!audio_.get() && !video_.get())) { + if (!success || (!audio_ && !video_)) { ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); return; } @@ -734,45 +751,41 @@ bool ChunkDemuxer::OnNewConfigs(const AudioDecoderConfig& audio_config, CHECK(audio_config.IsValidConfig() || video_config.IsValidConfig()); lock_.AssertAcquired(); + // 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()) { - if (audio_.get()) - return false; - - audio_ = new ChunkDemuxerStream(DemuxerStream::AUDIO, this); - } + if (audio_config.IsValidConfig() && (!has_audio_ || audio_)) + return false; // Only allow a single video config for now. - if (video_config.IsValidConfig()) { - if (video_.get()) - return false; + if (video_config.IsValidConfig() && (!has_video_ || video_)) + return false; - video_ = new ChunkDemuxerStream(DemuxerStream::VIDEO, this); - } + if (audio_config.IsValidConfig()) + audio_ = new ChunkDemuxerStream(audio_config); + + if (video_config.IsValidConfig()) + video_ = new ChunkDemuxerStream(video_config); return true; } -bool ChunkDemuxer::OnAudioBuffers() { +bool ChunkDemuxer::OnAudioBuffers(const StreamParser::BufferQueue& buffers) { DCHECK_NE(state_, SHUTDOWN); - if (!audio_.get()) + if (!audio_) return false; - audio_->OnBuffersAvailable(); - - return true; + return audio_->Append(buffers); } -bool ChunkDemuxer::OnVideoBuffers() { +bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) { DCHECK_NE(state_, SHUTDOWN); - if (!video_.get()) + if (!video_) return false; - video_->OnBuffersAvailable(); - - return true; + return video_->Append(buffers); } bool ChunkDemuxer::OnKeyNeeded(scoped_array init_data, diff --git a/media/filters/chunk_demuxer.h b/media/filters/chunk_demuxer.h index d57ec7d..d657585 100644 --- a/media/filters/chunk_demuxer.h +++ b/media/filters/chunk_demuxer.h @@ -13,7 +13,8 @@ #include "base/synchronization/lock.h" #include "media/base/byte_queue.h" #include "media/base/demuxer.h" -#include "media/filters/source_buffer.h" +#include "media/base/stream_parser.h" +#include "media/filters/source_buffer_stream.h" namespace media { @@ -77,26 +78,6 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer { // it can accept a new segment. void Abort(const std::string& id); - // Accesses the configs associated with the current playback buffers. - const AudioDecoderConfig& GetCurrentAudioDecoderConfig(); - const VideoDecoderConfig& GetCurrentVideoDecoderConfig(); - - // Fills |out_buffer| with a new buffer from the current SourceBufferStream - // indicated by |type|. - // Returns true if |out_buffer| is filled with a valid buffer. - // Returns false if SourceBuffer can not fulfill the request or if |type| is - // not AUDIO or VIDEO. - // Two versions needed (Locked and not Locked) because this method is called - // during a Read() when ChunkDemuxer IS NOT locked and from - // ChunkDemuxerStream::CreateReadDoneClosures_Locked() when - // OnBuffersAvailable() is called and ChunkDemuxer IS locked. - // TODO(acolwell): Investigate a cleaner solution to SourceBufferRead locking - // requirements. crbug.com/129849 - bool SourceBufferRead_Locked(DemuxerStream::Type type, - scoped_refptr* out_buffer); - bool SourceBufferRead(DemuxerStream::Type type, - scoped_refptr* out_buffer); - // Signals an EndOfStream request. // Returns false if called in an unexpected state or if there is a gap between // the current position and the end of the buffered data. @@ -122,12 +103,19 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer { // data. void ReportError_Locked(PipelineStatus error); - // SourceBuffer callbacks. - void OnSourceBufferInitDone(bool success, base::TimeDelta duration); + // Returns true if any stream has seeked to a time without buffered data. + bool IsSeekPending_Locked() const; + + // Returns true if all streams can successfully call EndOfStream, + // false if any can not. + bool CanEndOfStream_Locked() const; + + // StreamParser callbacks. + void OnStreamParserInitDone(bool success, base::TimeDelta duration); bool OnNewConfigs(const AudioDecoderConfig& audio_config, const VideoDecoderConfig& video_config); - bool OnAudioBuffers(); - bool OnVideoBuffers(); + bool OnAudioBuffers(const StreamParser::BufferQueue& buffers); + bool OnVideoBuffers(const StreamParser::BufferQueue& buffers); bool OnKeyNeeded(scoped_array init_data, int init_data_size); mutable base::Lock lock_; @@ -145,7 +133,12 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer { base::TimeDelta duration_; - scoped_ptr source_buffer_; + scoped_ptr stream_parser_; + + // TODO(annacc): Remove these when fixing: http://crbug.com/122909 + // Used to ensure config data matches the type and codec provided in AddId(). + bool has_audio_; + bool has_video_; // TODO(acolwell): Remove this when fixing http://crbug.com/122909 std::string source_id_; diff --git a/media/filters/source_buffer.cc b/media/filters/source_buffer.cc deleted file mode 100644 index 84efa91..0000000 --- a/media/filters/source_buffer.cc +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/filters/source_buffer.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "media/webm/webm_stream_parser.h" - -namespace media { - -SourceBuffer::SourceBuffer() {} - -SourceBuffer::~SourceBuffer() {} - -void SourceBuffer::Init(scoped_ptr parser, - const InitCB& init_cb, - const NewConfigCB& config_cb, - const NewBuffersCB& audio_cb, - const NewBuffersCB& video_cb, - const KeyNeededCB& key_needed_cb) { - DCHECK(init_cb_.is_null()); - DCHECK(parser.get()); - DCHECK(!init_cb.is_null()); - DCHECK(!config_cb.is_null()); - DCHECK(!audio_cb.is_null() || !video_cb.is_null()); - DCHECK(!key_needed_cb.is_null()); - - init_cb_ = init_cb; - config_cb_ = config_cb; - audio_cb_ = audio_cb; - video_cb_ = video_cb; - key_needed_cb_ = key_needed_cb; - - stream_parser_.reset(parser.release()); - - stream_parser_->Init( - base::Bind(&SourceBuffer::OnStreamParserInitDone, base::Unretained(this)), - base::Bind(&SourceBuffer::OnNewConfigs, base::Unretained(this)), - base::Bind(&SourceBuffer::OnAudioBuffers, base::Unretained(this)), - base::Bind(&SourceBuffer::OnVideoBuffers, base::Unretained(this)), - base::Bind(&SourceBuffer::OnKeyNeeded, base::Unretained(this))); -} - -bool SourceBuffer::AppendData(const uint8* data, size_t length) { - return stream_parser_->Parse(data, length); -} - -bool SourceBuffer::Read(DemuxerStream::Type type, - scoped_refptr* out_buffer) { - if (type == DemuxerStream::AUDIO) { - return audio_->GetNextBuffer(out_buffer); - } else if (type == DemuxerStream::VIDEO) { - return video_->GetNextBuffer(out_buffer); - } - return false; -} - -void SourceBuffer::Seek(base::TimeDelta time) { - if (audio_.get()) - audio_->Seek(time); - - if (video_.get()) - video_->Seek(time); -} - -bool SourceBuffer::IsSeekPending() const { - bool seek_pending = false; - - if (audio_.get()) - seek_pending = audio_->IsSeekPending(); - - if (!seek_pending && video_.get()) - seek_pending = video_->IsSeekPending(); - - return seek_pending; -} - -void SourceBuffer::ResetParser() { - stream_parser_->Flush(); -} - -bool SourceBuffer::GetBufferedRanges(Ranges* ranges_out) const { - // TODO(annacc): calculate buffered ranges. (crbug.com/129852) - return false; -} - -bool SourceBuffer::EndOfStream() { - - if ((audio_.get() && !audio_->CanEndOfStream()) || - (video_.get() && !video_->CanEndOfStream())) - return false; - - if (audio_.get()) - audio_->EndOfStream(); - - if (video_.get()) - video_->EndOfStream(); - - // Run callbacks so that any pending read requests can be fulfilled. - if (!audio_cb_.is_null()) - audio_cb_.Run(); - - if (!video_cb_.is_null()) - video_cb_.Run(); - - return true; -} - -const AudioDecoderConfig& SourceBuffer::GetCurrentAudioDecoderConfig() { - return audio_->GetCurrentAudioDecoderConfig(); -} - -const VideoDecoderConfig& SourceBuffer::GetCurrentVideoDecoderConfig() { - return video_->GetCurrentVideoDecoderConfig(); -} - -void SourceBuffer::OnStreamParserInitDone(bool success, - base::TimeDelta duration) { - init_cb_.Run(success, duration); - init_cb_.Reset(); -} - -bool SourceBuffer::OnNewConfigs(const AudioDecoderConfig& audio_config, - const VideoDecoderConfig& video_config) { - CHECK(audio_config.IsValidConfig() || video_config.IsValidConfig()); - - // Signal an error if we get configuration info for stream types - // we don't have a callback to handle. - if (audio_config.IsValidConfig()) { - // Disallow multiple audio configs and new audio configs after stream is - // initialized. - if (audio_cb_.is_null() || audio_.get()) - return false; - - audio_.reset(new SourceBufferStream(audio_config)); - } - - if (video_config.IsValidConfig()) { - // Disallow multiple video configs and new video configs after stream is - // initialized. - if (video_cb_.is_null() || video_.get()) - return false; - - video_.reset(new SourceBufferStream(video_config)); - } - - return config_cb_.Run(audio_config, video_config); -} - -bool SourceBuffer::OnAudioBuffers(const StreamParser::BufferQueue& buffer) { - if (!audio_.get()) - return false; - audio_->Append(buffer); - - return audio_cb_.Run(); -} - -bool SourceBuffer::OnVideoBuffers(const StreamParser::BufferQueue& buffer) { - if (!video_.get()) - return false; - video_->Append(buffer); - - return video_cb_.Run(); -} - -bool SourceBuffer::OnKeyNeeded(scoped_array init_data, - int init_data_size) { - return key_needed_cb_.Run(init_data.Pass(), init_data_size); -} - -} // namespace media diff --git a/media/filters/source_buffer.h b/media/filters/source_buffer.h deleted file mode 100644 index 78e02ec..0000000 --- a/media/filters/source_buffer.h +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_FILTERS_SOURCE_BUFFER_H_ -#define MEDIA_FILTERS_SOURCE_BUFFER_H_ - -#include "media/base/demuxer_stream.h" -#include "media/base/stream_parser.h" -#include "media/filters/source_buffer_stream.h" - -namespace media { - -// SourceBuffer stores media segments and initialization segments that are -// dynamically appended to a particular source ID, hands them to a StreamParser -// to be parsed, and provides buffers to ChunkDemuxerStreams during playback. -class MEDIA_EXPORT SourceBuffer { - public: - typedef std::vector > Ranges; - - SourceBuffer(); - ~SourceBuffer(); - - typedef base::Callback InitCB; - typedef base::Callback NewConfigCB; - typedef base::Callback NewBuffersCB; - typedef base::Callback, int)> KeyNeededCB; - - void Init(scoped_ptr parser, - const InitCB& init_cb, - const NewConfigCB& config_cb, - const NewBuffersCB& audio_cb, - const NewBuffersCB& video_cb, - const KeyNeededCB& key_needed_cb); - - // Add buffers to this source. Incoming data is parsed and stored in - // SourceBufferStreams, which handle ordering and overlap resolution. - // Returns true if parsing was successful. - bool AppendData(const uint8* data, size_t length); - - // Fills |out_buffer| with a new buffer from the SourceBufferStream indicated - // by |type|. - // Returns true if |out_buffer| is filled with a valid buffer, false if - // there is not enough data buffered to fulfill the request or if |type| is - // not a supported stream type. - bool Read(DemuxerStream::Type type, - scoped_refptr* out_buffer); - - // Seeks the SourceBufferStreams to a new |time|. - void Seek(base::TimeDelta time); - - // Returns true if this SourceBuffer has seeked to a time without buffered - // data and is waiting for more data to be appended. - bool IsSeekPending() const; - - // Resets StreamParser so it can accept a new segment. - void ResetParser(); - - // Fills |ranges_out| with the Ranges that are currently buffered. - // Returns false if no data is buffered. - bool GetBufferedRanges(Ranges* ranges_out) const; - - // Notifies all the streams in this SourceBuffer that EndOfStream has been - // called so that they can return EOS buffers for reads requested after the - // last buffer in the stream. - // Returns false if called when there is a gap between the current position - // and the end of the buffered data. - bool EndOfStream(); - - const AudioDecoderConfig& GetCurrentAudioDecoderConfig(); - const VideoDecoderConfig& GetCurrentVideoDecoderConfig(); - - private: - // StreamParser callbacks. - void OnStreamParserInitDone(bool success, base::TimeDelta duration); - bool OnNewConfigs(const AudioDecoderConfig& audio_config, - const VideoDecoderConfig& video_config); - bool OnAudioBuffers(const StreamParser::BufferQueue& buffer); - bool OnVideoBuffers(const StreamParser::BufferQueue& buffer); - bool OnKeyNeeded(scoped_array init_data, int init_data_size); - - scoped_ptr stream_parser_; - - InitCB init_cb_; - NewConfigCB config_cb_; - NewBuffersCB audio_cb_; - NewBuffersCB video_cb_; - KeyNeededCB key_needed_cb_; - - scoped_ptr audio_; - scoped_ptr video_; - - DISALLOW_COPY_AND_ASSIGN(SourceBuffer); -}; - -} // namespace media - -#endif // MEDIA_FILTERS_SOURCE_BUFFER_H_ diff --git a/media/media.gyp b/media/media.gyp index 8c5a3b7..f1ac284 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -226,8 +226,6 @@ 'filters/gpu_video_decoder.h', 'filters/in_memory_url_protocol.cc', 'filters/in_memory_url_protocol.h', - 'filters/source_buffer.cc', - 'filters/source_buffer.h', 'filters/source_buffer_stream.cc', 'filters/source_buffer_stream.h', 'filters/video_frame_generator.cc', -- cgit v1.1