summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-30 20:10:07 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-30 20:10:07 +0000
commit4c616fa594f093134d0124bc782d702d003c4566 (patch)
treeff6f6d390fd46424e9306e6a2ea92d606f41638a /media
parent23b357b59e5eb192d6c747c9ff19c3d91e1556e1 (diff)
downloadchromium_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.cc81
-rw-r--r--media/filters/ffmpeg_audio_decoder.h14
-rw-r--r--media/filters/ffmpeg_demuxer.cc2
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,