summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/renderer/webmediaplayer_delegate_impl.cc2
-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
4 files changed, 92 insertions, 7 deletions
diff --git a/chrome/renderer/webmediaplayer_delegate_impl.cc b/chrome/renderer/webmediaplayer_delegate_impl.cc
index b7d087d..a39fa59 100644
--- a/chrome/renderer/webmediaplayer_delegate_impl.cc
+++ b/chrome/renderer/webmediaplayer_delegate_impl.cc
@@ -10,6 +10,7 @@
#include "googleurl/src/gurl.h"
#if defined(OS_WIN)
// FFmpeg is not ready for Linux and Mac yet.
+#include "media/filters/ffmpeg_audio_decoder.h"
#include "media/filters/ffmpeg_demuxer.h"
#endif
@@ -59,6 +60,7 @@ WebMediaPlayerDelegateImpl::WebMediaPlayerDelegateImpl(RenderView* view)
#if defined(OS_WIN)
// FFmpeg is not ready for Linux and Mac yet.
filter_factory_->AddFactory(media::FFmpegDemuxer::CreateFilterFactory());
+ filter_factory_->AddFactory(media::FFmpegAudioDecoder::CreateFactory());
#endif
filter_factory_->AddFactory(AudioRendererImpl::CreateFactory(this));
filter_factory_->AddFactory(VideoRendererImpl::CreateFactory(this));
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,