diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-30 20:10:07 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-30 20:10:07 +0000 |
commit | 4c616fa594f093134d0124bc782d702d003c4566 (patch) | |
tree | ff6f6d390fd46424e9306e6a2ea92d606f41638a /media | |
parent | 23b357b59e5eb192d6c747c9ff19c3d91e1556e1 (diff) | |
download | chromium_src-4c616fa594f093134d0124bc782d702d003c4566.zip chromium_src-4c616fa594f093134d0124bc782d702d003c4566.tar.gz chromium_src-4c616fa594f093134d0124bc782d702d003c4566.tar.bz2 |
FFmpeg Audio decoder glue code
Implementation of FFmpegAudioDecoder which is the glue code
providing access to ffmpeg decoder functions for the media
pipeline.
Review URL: http://codereview.chromium.org/56035
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12800 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/filters/ffmpeg_audio_decoder.cc | 81 | ||||
-rw-r--r-- | media/filters/ffmpeg_audio_decoder.h | 14 | ||||
-rw-r--r-- | media/filters/ffmpeg_demuxer.cc | 2 |
3 files changed, 90 insertions, 7 deletions
diff --git a/media/filters/ffmpeg_audio_decoder.cc b/media/filters/ffmpeg_audio_decoder.cc index 74559d3..54ff1cc 100644 --- a/media/filters/ffmpeg_audio_decoder.cc +++ b/media/filters/ffmpeg_audio_decoder.cc @@ -2,32 +2,99 @@ // source code is governed by a BSD-style license that can be found in the // LICENSE file. +#include "media/base/data_buffer.h" #include "media/filters/ffmpeg_audio_decoder.h" +#include "media/filters/ffmpeg_common.h" +#include "media/filters/ffmpeg_demuxer.h" namespace media { +const size_t FFmpegAudioDecoder::kOutputBufferSize = + AVCODEC_MAX_AUDIO_FRAME_SIZE; + FFmpegAudioDecoder::FFmpegAudioDecoder() - : DecoderBase<AudioDecoder, Buffer>(NULL) { - NOTIMPLEMENTED(); + : DecoderBase<AudioDecoder, Buffer>(NULL), + codec_context_(NULL), + output_buffer_(NULL) { } FFmpegAudioDecoder::~FFmpegAudioDecoder() { - NOTIMPLEMENTED(); } // static bool FFmpegAudioDecoder::IsMediaFormatSupported(const MediaFormat& format) { - NOTIMPLEMENTED(); + int channels, sample_bits, sample_rate; + std::string mime_type; + if (format.GetAsInteger(MediaFormat::kChannels, &channels) && + format.GetAsInteger(MediaFormat::kSampleBits, &sample_bits) && + format.GetAsInteger(MediaFormat::kSampleRate, &sample_rate) && + format.GetAsString(MediaFormat::kMimeType, &mime_type) && + mime_type::kFFmpegAudio == mime_type) { + return true; + } return false; } bool FFmpegAudioDecoder::OnInitialize(DemuxerStream* demuxer_stream) { - NOTIMPLEMENTED(); - return false; + scoped_refptr<FFmpegDemuxerStream> ffmpeg_demuxer_stream; + + // Try to obtain a reference to FFmpegDemuxer. + if (!demuxer_stream-> + QueryInterface<FFmpegDemuxerStream>(&ffmpeg_demuxer_stream)) + return false; + + // Setting the media format. + // TODO(hclam): Reuse the information provided by the demuxer for now, we may + // need to wait until the first buffer is decoded to know the correct + // information. + media_format_.SetAsInteger(MediaFormat::kChannels, + ffmpeg_demuxer_stream->av_stream()->codec->channels); + media_format_.SetAsInteger(MediaFormat::kSampleBits, + ffmpeg_demuxer_stream->av_stream()->codec->bits_per_raw_sample); + media_format_.SetAsInteger(MediaFormat::kSampleRate, + ffmpeg_demuxer_stream->av_stream()->codec->sample_rate); + media_format_.SetAsString(MediaFormat::kMimeType, + mime_type::kUncompressedAudio); + + // Grab the codec context from ffmpeg demuxer. + codec_context_ = ffmpeg_demuxer_stream->av_stream()->codec; + + // Prepare the output buffer. + output_buffer_ = static_cast<uint8*>(av_malloc(kOutputBufferSize)); + if (!output_buffer_) { + host_->Error(PIPELINE_ERROR_OUT_OF_MEMORY); + return false; + } + return true; +} + +void FFmpegAudioDecoder::OnStop() { + if (output_buffer_) + av_free(output_buffer_); } void FFmpegAudioDecoder::OnDecode(Buffer* input) { - NOTIMPLEMENTED(); + const uint8_t* input_buffer = input->GetData(); + size_t input_buffer_size = input->GetDataSize(); + + int output_buffer_size = kOutputBufferSize; + int result = avcodec_decode_audio2(codec_context_, + reinterpret_cast<int16_t*>(output_buffer_), + &output_buffer_size, + input_buffer, + input_buffer_size); + + if (result < 0 || output_buffer_size > kOutputBufferSize) { + host_->Error(PIPELINE_ERROR_DECODE); + } else if (result == 0) { + // TODO(scherkus): does this mark EOS? Do we want to fulfill a read request + // with zero size? + } else { + DataBuffer* result_buffer = new DataBuffer(); + memcpy(result_buffer->GetWritableData(output_buffer_size), + output_buffer_, output_buffer_size); + EnqueueResult(result_buffer); + } } } // namespace diff --git a/media/filters/ffmpeg_audio_decoder.h b/media/filters/ffmpeg_audio_decoder.h index 1f07cd6..045fdf8 100644 --- a/media/filters/ffmpeg_audio_decoder.h +++ b/media/filters/ffmpeg_audio_decoder.h @@ -9,6 +9,8 @@ #include "media/base/factory.h" #include "media/filters/decoder_base.h" +struct AVCodecContext; + namespace media { //------------------------------------------------------------------------------ @@ -23,6 +25,8 @@ class FFmpegAudioDecoder : public DecoderBase<AudioDecoder, Buffer> { virtual bool OnInitialize(DemuxerStream* demuxer_stream); + virtual void OnStop(); + virtual void OnDecode(Buffer* input); private: @@ -30,6 +34,16 @@ class FFmpegAudioDecoder : public DecoderBase<AudioDecoder, Buffer> { FFmpegAudioDecoder(); virtual ~FFmpegAudioDecoder(); + // A FFmpeg defined structure that holds decoder information, this variable + // is initialized in OnInitialize(). + AVCodecContext* codec_context_; + + // Data buffer to carry decoded raw PCM samples. This buffer is created by + // av_malloc and is used throughout the lifetime of this class. + uint8* output_buffer_; + + static const size_t kOutputBufferSize; + DISALLOW_COPY_AND_ASSIGN(FFmpegAudioDecoder); }; diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc index 906c067..5208ed2 100644 --- a/media/filters/ffmpeg_demuxer.cc +++ b/media/filters/ffmpeg_demuxer.cc @@ -63,6 +63,8 @@ FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer, stream->codec->channels); media_format_.SetAsInteger(MediaFormat::kSampleRate, stream->codec->sample_rate); + media_format_.SetAsInteger(MediaFormat::kSampleBits, + stream->codec->bits_per_raw_sample); break; case CODEC_TYPE_VIDEO: media_format_.SetAsString(MediaFormat::kMimeType, |