diff options
-rw-r--r-- | chrome/renderer/webmediaplayer_delegate_impl.cc | 2 | ||||
-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 |
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, |