summaryrefslogtreecommitdiffstats
path: root/media/filters
diff options
context:
space:
mode:
authoracolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-10 23:26:07 +0000
committeracolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-10 23:26:07 +0000
commitc851cd6fb95e44c4208e0db3cc86822ce8b09144 (patch)
treef3d1ca6a36fc2d73823f4692f0978ba82a03cb91 /media/filters
parent40c4cbb72decbe9b5c66c6753dddeb3b683a2562 (diff)
downloadchromium_src-c851cd6fb95e44c4208e0db3cc86822ce8b09144.zip
chromium_src-c851cd6fb95e44c4208e0db3cc86822ce8b09144.tar.gz
chromium_src-c851cd6fb95e44c4208e0db3cc86822ce8b09144.tar.bz2
Move WebM specific code from ChunkDemuxer to WebMStreamParser.
BUG=108329 TEST=Existing ChunkDemuxer unittests TBR=acolwell@chromium.org Review URL: http://codereview.chromium.org/9170002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@117113 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/filters')
-rw-r--r--media/filters/chunk_demuxer.cc402
-rw-r--r--media/filters/chunk_demuxer.h61
-rw-r--r--media/filters/ffmpeg_audio_decoder_unittest.cc5
-rw-r--r--media/filters/ffmpeg_video_decoder_unittest.cc4
4 files changed, 128 insertions, 344 deletions
diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc
index 79f6178..ba3224b 100644
--- a/media/filters/chunk_demuxer.cc
+++ b/media/filters/chunk_demuxer.cc
@@ -2,10 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Implements a Demuxer that can switch among different data sources mid-stream.
-// Uses FFmpegDemuxer under the covers, so see the caveats at the top of
-// ffmpeg_demuxer.h.
-
#include "media/filters/chunk_demuxer.h"
#include "base/bind.h"
@@ -14,47 +10,11 @@
#include "media/base/audio_decoder_config.h"
#include "media/base/data_buffer.h"
#include "media/base/video_decoder_config.h"
-#include "media/ffmpeg/ffmpeg_common.h"
#include "media/filters/chunk_demuxer_client.h"
-#include "media/filters/ffmpeg_glue.h"
-#include "media/filters/in_memory_url_protocol.h"
-#include "media/webm/webm_cluster_parser.h"
-#include "media/webm/webm_constants.h"
-#include "media/webm/webm_info_parser.h"
-#include "media/webm/webm_tracks_parser.h"
+#include "media/webm/webm_stream_parser.h"
namespace media {
-// WebM File Header. This is prepended to the INFO & TRACKS
-// data passed to Init() before handing it to FFmpeg. Essentially
-// we are making the INFO & TRACKS data look like a small WebM
-// file so we can use FFmpeg to initialize the AVFormatContext.
-//
-// TODO(acolwell): Remove this when we construct AudioDecoderConfig and
-// VideoDecoderConfig without requiring an AVStream object.
-static const uint8 kWebMHeader[] = {
- 0x1A, 0x45, 0xDF, 0xA3, 0x9F, // EBML (size = 0x1f)
- 0x42, 0x86, 0x81, 0x01, // EBMLVersion = 1
- 0x42, 0xF7, 0x81, 0x01, // EBMLReadVersion = 1
- 0x42, 0xF2, 0x81, 0x04, // EBMLMaxIDLength = 4
- 0x42, 0xF3, 0x81, 0x08, // EBMLMaxSizeLength = 8
- 0x42, 0x82, 0x84, 0x77, 0x65, 0x62, 0x6D, // DocType = "webm"
- 0x42, 0x87, 0x81, 0x02, // DocTypeVersion = 2
- 0x42, 0x85, 0x81, 0x02, // DocTypeReadVersion = 2
- // EBML end
- 0x18, 0x53, 0x80, 0x67, // Segment
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // segment(size = 0)
- // INFO goes here.
-};
-
-// Offset of the segment size field in kWebMHeader. Used to update
-// the segment size field before handing the buffer to FFmpeg.
-static const int kSegmentSizeOffset = sizeof(kWebMHeader) - 8;
-
-static const uint8 kEmptyCluster[] = {
- 0x1F, 0x43, 0xB6, 0x75, 0x80 // CLUSTER (size = 0)
-};
-
// Create an "end of stream" buffer.
static Buffer* CreateEOSBuffer() {
return new DataBuffer(0);
@@ -65,7 +25,8 @@ class ChunkDemuxerStream : public DemuxerStream {
typedef std::deque<scoped_refptr<Buffer> > BufferQueue;
typedef std::deque<ReadCallback> ReadCBQueue;
- ChunkDemuxerStream(Type type, AVStream* stream);
+ explicit ChunkDemuxerStream(const AudioDecoderConfig& audio_config);
+ explicit ChunkDemuxerStream(const VideoDecoderConfig& video_config);
virtual ~ChunkDemuxerStream();
void Flush();
@@ -87,7 +48,6 @@ class ChunkDemuxerStream : public DemuxerStream {
private:
Type type_;
- AVStream* av_stream_;
AudioDecoderConfig audio_config_;
VideoDecoderConfig video_config_;
@@ -105,23 +65,27 @@ class ChunkDemuxerStream : public DemuxerStream {
DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream);
};
-ChunkDemuxerStream::ChunkDemuxerStream(Type type, AVStream* stream)
- : type_(type),
- av_stream_(stream),
+ChunkDemuxerStream::ChunkDemuxerStream(const AudioDecoderConfig& audio_config)
+ : type_(AUDIO),
shutdown_called_(false),
received_end_of_stream_(false),
last_buffer_timestamp_(kNoTimestamp) {
- if (type_ == AUDIO) {
- AVCodecContextToAudioDecoderConfig(stream->codec, &audio_config_);
- } else if (type_ == VIDEO) {
- AVStreamToVideoDecoderConfig(stream, &video_config_);
- }
+ audio_config_.CopyFrom(audio_config);
+}
+
+
+ChunkDemuxerStream::ChunkDemuxerStream(const VideoDecoderConfig& video_config)
+ : type_(VIDEO),
+ shutdown_called_(false),
+ received_end_of_stream_(false),
+ last_buffer_timestamp_(kNoTimestamp) {
+ video_config_.CopyFrom(video_config);
}
ChunkDemuxerStream::~ChunkDemuxerStream() {}
void ChunkDemuxerStream::Flush() {
- VLOG(1) << "Flush()";
+ DVLOG(1) << "Flush()";
base::AutoLock auto_lock(lock_);
buffers_.clear();
received_end_of_stream_ = false;
@@ -289,7 +253,6 @@ const VideoDecoderConfig& ChunkDemuxerStream::video_decoder_config() {
ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client)
: state_(WAITING_FOR_INIT),
client_(client),
- format_context_(NULL),
buffered_bytes_(0),
seek_waits_for_data_(true) {
DCHECK(client);
@@ -297,28 +260,21 @@ ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client)
ChunkDemuxer::~ChunkDemuxer() {
DCHECK_NE(state_, INITIALIZED);
-
- if (!format_context_)
- return;
-
- DestroyAVFormatContext(format_context_);
- format_context_ = NULL;
-
- if (url_protocol_.get()) {
- FFmpegGlue::GetInstance()->RemoveProtocol(url_protocol_.get());
- url_protocol_.reset();
- url_protocol_buffer_.reset();
- }
}
void ChunkDemuxer::Init(const PipelineStatusCB& cb) {
- VLOG(1) << "Init()";
+ DVLOG(1) << "Init()";
{
base::AutoLock auto_lock(lock_);
DCHECK_EQ(state_, WAITING_FOR_INIT);
ChangeState_Locked(INITIALIZING);
init_cb_ = cb;
+ stream_parser_.reset(new WebMStreamParser());
+
+ stream_parser_->Init(
+ base::Bind(&ChunkDemuxer::OnStreamParserInitDone, this),
+ this);
}
client_->DemuxerOpened(this);
@@ -332,13 +288,13 @@ void ChunkDemuxer::set_host(DemuxerHost* host) {
}
void ChunkDemuxer::Stop(const base::Closure& callback) {
- VLOG(1) << "Stop()";
+ DVLOG(1) << "Stop()";
Shutdown();
callback.Run();
}
void ChunkDemuxer::Seek(base::TimeDelta time, const PipelineStatusCB& cb) {
- VLOG(1) << "Seek(" << time.InSecondsF() << ")";
+ DVLOG(1) << "Seek(" << time.InSecondsF() << ")";
PipelineStatus status = PIPELINE_ERROR_INVALID_STATE;
{
@@ -346,7 +302,7 @@ void ChunkDemuxer::Seek(base::TimeDelta time, const PipelineStatusCB& cb) {
if (state_ == INITIALIZED || state_ == ENDED) {
if (seek_waits_for_data_) {
- VLOG(1) << "Seek() : waiting for more data to arrive.";
+ DVLOG(1) << "Seek() : waiting for more data to arrive.";
seek_cb_ = cb;
return;
}
@@ -393,13 +349,13 @@ scoped_refptr<DemuxerStream> ChunkDemuxer::GetStream(
}
base::TimeDelta ChunkDemuxer::GetStartTime() const {
- VLOG(1) << "GetStartTime()";
+ DVLOG(1) << "GetStartTime()";
// TODO(acolwell) : Fix this so it uses the time on the first packet.
return base::TimeDelta();
}
void ChunkDemuxer::FlushData() {
- VLOG(1) << "FlushData()";
+ DVLOG(1) << "FlushData()";
base::AutoLock auto_lock(lock_);
DCHECK(state_ == INITIALIZED || state_ == ENDED || state_ == SHUTDOWN);
@@ -413,14 +369,14 @@ void ChunkDemuxer::FlushData() {
video_->Flush();
byte_queue_.Reset();
- cluster_parser_->Reset();
+ stream_parser_->Flush();
seek_waits_for_data_ = true;
ChangeState_Locked(INITIALIZED);
}
bool ChunkDemuxer::AppendData(const uint8* data, size_t length) {
- VLOG(1) << "AppendData(" << length << ")";
+ DVLOG(1) << "AppendData(" << length << ")";
if (!data || length == 0u)
return false;
@@ -438,40 +394,37 @@ bool ChunkDemuxer::AppendData(const uint8* data, size_t length) {
int cur_size = 0;
int bytes_parsed = 0;
int result = -1;
- bool can_complete_seek = false;
+
+ // Capture |seek_waits_for_data_| state before we start parsing.
+ // Its state can be changed by OnAudioBuffers() or OnVideoBuffers()
+ // calls during the parse.
+ bool old_seek_waits_for_data = seek_waits_for_data_;
byte_queue_.Peek(&cur, &cur_size);
do {
switch(state_) {
case INITIALIZING:
- result = ParseInfoAndTracks_Locked(cur, cur_size);
+ result = stream_parser_->Parse(cur, cur_size);
if (result < 0) {
- VLOG(1) << "AppendData(): parsing info & tracks failed";
ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
return true;
}
break;
case INITIALIZED: {
- bool buffers_added = false;
- result = ParseCluster_Locked(cur, cur_size, &buffers_added);
+ result = stream_parser_->Parse(cur, cur_size);
if (result < 0) {
- VLOG(1) << "AppendData(): parsing data failed";
ReportError_Locked(PIPELINE_ERROR_DECODE);
return true;
}
-
- // We can complete the seek if we have successfully parsed
- // some data and buffers were added to one of the DemuxerStreams.
- can_complete_seek |= (result > 0 && buffers_added);
} break;
case WAITING_FOR_INIT:
case ENDED:
case PARSE_ERROR:
case SHUTDOWN:
- VLOG(1) << "AppendData(): called in unexpected state " << state_;
+ DVLOG(1) << "AppendData(): called in unexpected state " << state_;
return false;
}
@@ -484,11 +437,11 @@ bool ChunkDemuxer::AppendData(const uint8* data, size_t length) {
byte_queue_.Pop(bytes_parsed);
- if (can_complete_seek && seek_waits_for_data_) {
- seek_waits_for_data_ = false;
-
- if (!seek_cb_.is_null())
- std::swap(cb, seek_cb_);
+ // Check to see if parsing triggered seek_waits_for_data_ to go from true to
+ // false. This indicates we have parsed enough data to complete the seek.
+ if (old_seek_waits_for_data && !seek_waits_for_data_ &&
+ !seek_cb_.is_null()) {
+ std::swap(cb, seek_cb_);
}
base::TimeDelta tmp;
@@ -523,7 +476,7 @@ bool ChunkDemuxer::AppendData(const uint8* data, size_t length) {
}
void ChunkDemuxer::EndOfStream(PipelineStatus status) {
- VLOG(1) << "EndOfStream(" << status << ")";
+ DVLOG(1) << "EndOfStream(" << status << ")";
base::AutoLock auto_lock(lock_);
DCHECK_NE(state_, WAITING_FOR_INIT);
DCHECK_NE(state_, ENDED);
@@ -560,7 +513,7 @@ bool ChunkDemuxer::HasEnded() {
}
void ChunkDemuxer::Shutdown() {
- VLOG(1) << "Shutdown()";
+ DVLOG(1) << "Shutdown()";
PipelineStatusCB cb;
{
base::AutoLock auto_lock(lock_);
@@ -576,6 +529,8 @@ void ChunkDemuxer::Shutdown() {
if (video_.get())
video_->Shutdown();
+ stream_parser_.reset();
+
ChangeState_Locked(SHUTDOWN);
}
@@ -590,207 +545,6 @@ void ChunkDemuxer::ChangeState_Locked(State new_state) {
state_ = new_state;
}
-int ChunkDemuxer::ParseInfoAndTracks_Locked(const uint8* data, int size) {
- lock_.AssertAcquired();
- DCHECK(data);
- DCHECK_GT(size, 0);
-
- DCHECK_EQ(state_, INITIALIZING);
-
- const uint8* cur = data;
- int cur_size = size;
- int bytes_parsed = 0;
-
- int id;
- int64 element_size;
- int result = WebMParseElementHeader(cur, cur_size, &id, &element_size);
-
- if (result <= 0)
- return result;
-
- switch (id) {
- case kWebMIdEBML :
- case kWebMIdSeekHead :
- case kWebMIdVoid :
- case kWebMIdCRC32 :
- case kWebMIdCues :
- if (cur_size < (result + element_size)) {
- // We don't have the whole element yet. Signal we need more data.
- return 0;
- }
- // Skip the element.
- return result + element_size;
- break;
- case kWebMIdSegment :
- // Just consume the segment header.
- return result;
- break;
- case kWebMIdInfo :
- // We've found the element we are looking for.
- break;
- default:
- VLOG(1) << "Unexpected ID 0x" << std::hex << id;
- return -1;
- }
-
- WebMInfoParser info_parser;
- result = info_parser.Parse(cur, cur_size);
-
- if (result <= 0)
- return result;
-
- cur += result;
- cur_size -= result;
- bytes_parsed += result;
-
- WebMTracksParser tracks_parser(info_parser.timecode_scale());
- result = tracks_parser.Parse(cur, cur_size);
-
- if (result <= 0)
- return result;
-
- bytes_parsed += result;
-
- double mult = info_parser.timecode_scale() / 1000.0;
- duration_ = base::TimeDelta::FromMicroseconds(info_parser.duration() * mult);
-
- cluster_parser_.reset(new WebMClusterParser(
- info_parser.timecode_scale(),
- tracks_parser.audio_track_num(),
- tracks_parser.audio_default_duration(),
- tracks_parser.video_track_num(),
- tracks_parser.video_default_duration()));
-
- format_context_ = CreateFormatContext(data, bytes_parsed);
- if (!format_context_ || !SetupStreams())
- return -1;
-
- ChangeState_Locked(INITIALIZED);
- init_cb_.Run(PIPELINE_OK);
- init_cb_.Reset();
- return bytes_parsed;
-}
-
-AVFormatContext* ChunkDemuxer::CreateFormatContext(const uint8* data,
- int size) {
- DCHECK(!url_protocol_.get());
- DCHECK(!url_protocol_buffer_.get());
-
- int segment_size = size + sizeof(kEmptyCluster);
- int buf_size = sizeof(kWebMHeader) + segment_size;
- url_protocol_buffer_.reset(new uint8[buf_size]);
- uint8* buf = url_protocol_buffer_.get();
- memcpy(buf, kWebMHeader, sizeof(kWebMHeader));
- memcpy(buf + sizeof(kWebMHeader), data, size);
- memcpy(buf + sizeof(kWebMHeader) + size, kEmptyCluster,
- sizeof(kEmptyCluster));
-
- // Update the segment size in the buffer.
- int64 tmp = (segment_size & GG_LONGLONG(0x00FFFFFFFFFFFFFF)) |
- GG_LONGLONG(0x0100000000000000);
- for (int i = 0; i < 8; i++) {
- buf[kSegmentSizeOffset + i] = (tmp >> (8 * (7 - i))) & 0xff;
- }
-
- url_protocol_.reset(new InMemoryUrlProtocol(buf, buf_size, true));
- std::string key = FFmpegGlue::GetInstance()->AddProtocol(url_protocol_.get());
-
- // Open FFmpeg AVFormatContext.
- AVFormatContext* context = NULL;
- int result = av_open_input_file(&context, key.c_str(), NULL, 0, NULL);
-
- if (result < 0)
- return NULL;
-
- return context;
-}
-
-bool ChunkDemuxer::SetupStreams() {
- int result = av_find_stream_info(format_context_);
-
- if (result < 0)
- return false;
-
- bool no_supported_streams = true;
- for (size_t i = 0; i < format_context_->nb_streams; ++i) {
- AVStream* stream = format_context_->streams[i];
- AVCodecContext* codec_context = stream->codec;
- AVMediaType codec_type = codec_context->codec_type;
-
- if (codec_type == AVMEDIA_TYPE_AUDIO &&
- stream->codec->codec_id == CODEC_ID_VORBIS &&
- !audio_.get()) {
- audio_ = new ChunkDemuxerStream(DemuxerStream::AUDIO, stream);
- no_supported_streams = false;
- continue;
- }
-
- if (codec_type == AVMEDIA_TYPE_VIDEO &&
- stream->codec->codec_id == CODEC_ID_VP8 &&
- !video_.get()) {
- video_ = new ChunkDemuxerStream(DemuxerStream::VIDEO, stream);
- no_supported_streams = false;
- continue;
- }
- }
-
- return !no_supported_streams;
-}
-
-int ChunkDemuxer::ParseCluster_Locked(const uint8* data, int size,
- bool* buffers_added) {
- lock_.AssertAcquired();
- if (!cluster_parser_.get())
- return -1;
-
- int id;
- int64 element_size;
- int result = WebMParseElementHeader(data, size, &id, &element_size);
-
- if (result <= 0)
- return result;
-
- if (id == kWebMIdCues) {
- if (size < (result + element_size)) {
- // We don't have the whole element yet. Signal we need more data.
- return 0;
- }
- // Skip the element.
- return result + element_size;
- }
-
- int bytes_parsed = cluster_parser_->Parse(data, size);
-
- if (bytes_parsed <= 0)
- return bytes_parsed;
-
- if (!cluster_parser_->audio_buffers().empty() ||
- !cluster_parser_->video_buffers().empty()) {
- // Make sure we can add the buffers to both streams before we actually
- // add them. This allows us to accept all of the data or none of it.
- if ((audio_.get() &&
- !audio_->CanAddBuffers(cluster_parser_->audio_buffers())) ||
- (video_.get() &&
- !video_->CanAddBuffers(cluster_parser_->video_buffers()))) {
- return -1;
- }
-
- if (audio_.get())
- audio_->AddBuffers(cluster_parser_->audio_buffers());
-
- if (video_.get())
- video_->AddBuffers(cluster_parser_->video_buffers());
-
- *buffers_added = true;
- }
-
- // TODO(acolwell) : make this more representative of what is actually
- // buffered.
- buffered_bytes_ += bytes_parsed;
-
- return bytes_parsed;
-}
-
void ChunkDemuxer::ReportError_Locked(PipelineStatus error) {
lock_.AssertAcquired();
DCHECK_NE(error, PIPELINE_OK);
@@ -822,4 +576,68 @@ void ChunkDemuxer::ReportError_Locked(PipelineStatus error) {
}
}
+void ChunkDemuxer::OnStreamParserInitDone(bool success,
+ base::TimeDelta duration) {
+ lock_.AssertAcquired();
+ DCHECK_EQ(state_, INITIALIZING);
+ if (!success || (!audio_.get() && !video_.get())) {
+ ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
+ return;
+ }
+
+ duration_ = duration;
+
+ ChangeState_Locked(INITIALIZED);
+ PipelineStatusCB cb;
+ std::swap(cb, init_cb_);
+ cb.Run(PIPELINE_OK);
+}
+
+bool ChunkDemuxer::OnNewAudioConfig(const AudioDecoderConfig& config) {
+ lock_.AssertAcquired();
+ // Only allow a single audio config for now.
+ if (audio_.get())
+ return false;
+
+ audio_ = new ChunkDemuxerStream(config);
+ return true;
+}
+
+bool ChunkDemuxer::OnNewVideoConfig(const VideoDecoderConfig& config) {
+ lock_.AssertAcquired();
+ // Only allow a single video config for now.
+ if (video_.get())
+ return false;
+
+ video_ = new ChunkDemuxerStream(config);
+ return true;
+}
+
+
+bool ChunkDemuxer::OnAudioBuffers(const BufferQueue& buffers) {
+ if (!audio_.get())
+ return false;
+
+ if (!audio_->CanAddBuffers(buffers))
+ return false;
+
+ audio_->AddBuffers(buffers);
+ seek_waits_for_data_ = false;
+
+ return true;
+}
+
+bool ChunkDemuxer::OnVideoBuffers(const BufferQueue& buffers) {
+ if (!video_.get())
+ return false;
+
+ if (!video_->CanAddBuffers(buffers))
+ return false;
+
+ video_->AddBuffers(buffers);
+ seek_waits_for_data_ = false;
+
+ return true;
+}
+
} // namespace media
diff --git a/media/filters/chunk_demuxer.h b/media/filters/chunk_demuxer.h
index 3313c11..9ce5845 100644
--- a/media/filters/chunk_demuxer.h
+++ b/media/filters/chunk_demuxer.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -10,9 +10,7 @@
#include "base/synchronization/lock.h"
#include "media/base/byte_queue.h"
#include "media/base/demuxer.h"
-#include "media/webm/webm_cluster_parser.h"
-
-struct AVFormatContext;
+#include "media/base/stream_parser.h"
namespace media {
@@ -20,9 +18,9 @@ class ChunkDemuxerClient;
class ChunkDemuxerStream;
class FFmpegURLProtocol;
-// Demuxer implementation that allows chunks of WebM media data to be passed
+// Demuxer implementation that allows chunks of media data to be passed
// from JavaScript to the media stack.
-class MEDIA_EXPORT ChunkDemuxer : public Demuxer {
+class MEDIA_EXPORT ChunkDemuxer : public Demuxer, public StreamParserHost {
public:
explicit ChunkDemuxer(ChunkDemuxerClient* client);
virtual ~ChunkDemuxer();
@@ -64,40 +62,18 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer {
void ChangeState_Locked(State new_state);
- // Parses a buffer that contains an INFO & TRACKS element. This method handles
- // calling & clearing |init_cb_| before it returns.
- //
- // Returns -1 if the parse fails.
- // Returns 0 if more data is needed.
- // Returns the number of bytes parsed on success.
- int ParseInfoAndTracks_Locked(const uint8* data, int size);
-
- // Generates an AVFormatContext for the INFO & TRACKS elements contained
- // in |data|. Returns NULL if parsing |data| fails.
- AVFormatContext* CreateFormatContext(const uint8* data, int size);
-
- // Sets up |audio_| & |video_| DemuxerStreams based on the data in
- // |format_context_|. Returns false if no valid audio or video stream were
- // found.
- bool SetupStreams();
-
- // Parse a cluster and add the buffers to the appropriate DemuxerStream. This
- // method also skips over CUES elements if it happens to encounter them.
- //
- // |data| is expected to point to the beginning of an element.
- //
- // |buffers_added| - Indicates whether Buffers were added to DemuxerStreams
- // during the call. This is only valid if the return value > 0.
- //
- // Returns -1 if the parse fails.
- // Returns 0 if more data is needed.
- // Returns the number of bytes parsed on success.
- int ParseCluster_Locked(const uint8* data, int size, bool* buffers_added);
-
// Reports an error and puts the demuxer in a state where it won't accept more
// data.
void ReportError_Locked(PipelineStatus error);
+ void OnStreamParserInitDone(bool success, base::TimeDelta duration);
+
+ // StreamParserHost implementation.
+ virtual bool OnNewAudioConfig(const AudioDecoderConfig& config) OVERRIDE;
+ virtual bool OnNewVideoConfig(const VideoDecoderConfig& config) OVERRIDE;
+ virtual bool OnAudioBuffers(const BufferQueue& buffer) OVERRIDE;
+ virtual bool OnVideoBuffers(const BufferQueue& buffer) OVERRIDE;
+
base::Lock lock_;
State state_;
@@ -108,22 +84,11 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer {
scoped_refptr<ChunkDemuxerStream> audio_;
scoped_refptr<ChunkDemuxerStream> video_;
- // Backing buffer for |url_protocol_|.
- scoped_array<uint8> url_protocol_buffer_;
-
- // Protocol used by |format_context_|. It must outlive the context object.
- scoped_ptr<FFmpegURLProtocol> url_protocol_;
-
- // FFmpeg format context for this demuxer. It is created by
- // av_open_input_file() during demuxer initialization and cleaned up with
- // DestroyAVFormatContext() in the destructor.
- AVFormatContext* format_context_;
-
int64 buffered_bytes_;
base::TimeDelta duration_;
- scoped_ptr<WebMClusterParser> cluster_parser_;
+ scoped_ptr<StreamParser> stream_parser_;
// Should a Seek() call wait for more data before calling the
// callback.
diff --git a/media/filters/ffmpeg_audio_decoder_unittest.cc b/media/filters/ffmpeg_audio_decoder_unittest.cc
index f8ba102..12e2ce6 100644
--- a/media/filters/ffmpeg_audio_decoder_unittest.cc
+++ b/media/filters/ffmpeg_audio_decoder_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -59,7 +59,8 @@ class FFmpegAudioDecoderTest : public testing::Test {
CHANNEL_LAYOUT_STEREO,
44100,
vorbis_extradata_.get(),
- vorbis_extradata_size_);
+ vorbis_extradata_size_,
+ true);
}
virtual ~FFmpegAudioDecoderTest() {}
diff --git a/media/filters/ffmpeg_video_decoder_unittest.cc b/media/filters/ffmpeg_video_decoder_unittest.cc
index b072993..d9c1fd4 100644
--- a/media/filters/ffmpeg_video_decoder_unittest.cc
+++ b/media/filters/ffmpeg_video_decoder_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -62,7 +62,7 @@ class FFmpegVideoDecoderTest : public testing::Test {
kVideoFormat, kCodedSize, kVisibleRect,
kFrameRate.num, kFrameRate.den,
kAspectRatio.num, kAspectRatio.den,
- NULL, 0);
+ NULL, 0, true);
}
virtual ~FFmpegVideoDecoderTest() {}