Bug 1022501 - Add MP3 support to MP4 demuxer. r=edwin

--HG--
rename : content/media/fmp4/eme/EMEAACDecoder.cpp => content/media/fmp4/eme/EMEAudioDecoder.cpp
rename : content/media/fmp4/eme/EMEAACDecoder.h => content/media/fmp4/eme/EMEAudioDecoder.h
rename : content/media/fmp4/ffmpeg/FFmpegAACDecoder.cpp => content/media/fmp4/ffmpeg/FFmpegAudioDecoder.cpp
rename : content/media/fmp4/ffmpeg/FFmpegAACDecoder.h => content/media/fmp4/ffmpeg/FFmpegAudioDecoder.h
extra : rebase_source : 964077ffa7abd11a5da586bfcdee2ee98d4bc210
This commit is contained in:
Jean-Yves Avenard 2014-08-15 16:25:06 +10:00
Родитель 59cfd2da54
Коммит 399b759f3e
29 изменённых файлов: 234 добавлений и 145 удалений

Просмотреть файл

@ -229,9 +229,9 @@ public:
// Decode thread.
virtual already_AddRefed<MediaDataDecoder>
CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE {
CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE {
BlankAudioDataCreator* creator = new BlankAudioDataCreator(
aConfig.channel_count, aConfig.samples_per_second);
@ -241,6 +241,13 @@ public:
aCallback);
return decoder.forget();
}
virtual bool
SupportsAudioMimeType(const char* aMimeType) MOZ_OVERRIDE
{
return true;
}
};
PlatformDecoderModule* CreateBlankDecoderModule()

Просмотреть файл

@ -288,6 +288,14 @@ MP4Reader::ExtractCryptoInitData(nsTArray<uint8_t>& aInitData)
}
}
bool
MP4Reader::IsSupportedAudioMimeType(const char* aMimeType)
{
return (!strcmp(aMimeType, "audio/mpeg") ||
!strcmp(aMimeType, "audio/mp4a-latm")) &&
mPlatform->SupportsAudioMimeType(aMimeType);
}
nsresult
MP4Reader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags)
@ -296,13 +304,6 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo,
bool ok = mDemuxer->Init();
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
mInfo.mAudio.mHasAudio = mAudio.mActive = mDemuxer->HasValidAudio();
const AudioDecoderConfig& audio = mDemuxer->AudioConfig();
// If we have audio, we *only* allow AAC to be decoded.
if (mInfo.mAudio.mHasAudio && strcmp(audio.mime_type, "audio/mp4a-latm")) {
return NS_ERROR_FAILURE;
}
mInfo.mVideo.mHasVideo = mVideo.mActive = mDemuxer->HasValidVideo();
const VideoDecoderConfig& video = mDemuxer->VideoConfig();
// If we have video, we *only* allow H.264 to be decoded.
@ -370,14 +371,18 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo,
NS_ENSURE_TRUE(mPlatform, NS_ERROR_FAILURE);
}
if (HasAudio()) {
if (mDemuxer->HasValidAudio()) {
const AudioDecoderConfig& audio = mDemuxer->AudioConfig();
mInfo.mAudio.mHasAudio = mAudio.mActive = true;
if (mInfo.mAudio.mHasAudio && !IsSupportedAudioMimeType(audio.mime_type)) {
return NS_ERROR_FAILURE;
}
mInfo.mAudio.mRate = audio.samples_per_second;
mInfo.mAudio.mChannels = audio.channel_count;
mAudio.mCallback = new DecoderCallback(this, kAudio);
mAudio.mDecoder = mPlatform->CreateAACDecoder(audio,
mAudio.mTaskQueue,
mAudio.mCallback);
mAudio.mDecoder = mPlatform->CreateAudioDecoder(audio,
mAudio.mTaskQueue,
mAudio.mCallback);
NS_ENSURE_TRUE(mAudio.mDecoder != nullptr, NS_ERROR_FAILURE);
nsresult rv = mAudio.mDecoder->Init();
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -87,6 +87,7 @@ private:
void Flush(mp4_demuxer::TrackType aTrack);
void DrainComplete(mp4_demuxer::TrackType aTrack);
void UpdateIndex();
bool IsSupportedAudioMimeType(const char* aMimeType);
void NotifyResourcesStatusChanged();
bool IsWaitingOnCodecResource();
bool IsWaitingOnCDMResource();

Просмотреть файл

@ -153,4 +153,10 @@ PlatformDecoderModule::Create()
return nullptr;
}
bool
PlatformDecoderModule::SupportsAudioMimeType(const char* aMimeType)
{
return !strcmp(aMimeType, "audio/mp4a-latm");
}
} // namespace mozilla

Просмотреть файл

@ -35,8 +35,8 @@ class CDMProxy;
typedef int64_t Microseconds;
// The PlatformDecoderModule interface is used by the MP4Reader to abstract
// access to the H264 and AAC decoders provided by various platforms. It
// may be extended to support other codecs in future. Each platform (Windows,
// access to the H264 and Audio (AAC/MP3) decoders provided by various platforms.
// It may be extended to support other codecs in future. Each platform (Windows,
// MacOSX, Linux, B2G etc) must implement a PlatformDecoderModule to provide
// access to its decoders in order to get decompressed H.264/AAC from the
// MP4Reader.
@ -103,7 +103,7 @@ public:
MediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback) = 0;
// Creates an AAC decoder with the specified properties.
// Creates an Audio decoder with the specified properties.
// Asynchronous decoding of audio should be done in runnables dispatched to
// aAudioTaskQueue. If the task queue isn't needed, the decoder should
// not hold a reference to it.
@ -114,9 +114,14 @@ public:
// It is safe to store a reference to aConfig.
// This is called on the decode task queue.
virtual already_AddRefed<MediaDataDecoder>
CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) = 0;
CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) = 0;
// An audio decoder module must support AAC by default.
// If more audio codec is to be supported, SupportsAudioMimeType will have
// to be extended
virtual bool SupportsAudioMimeType(const char* aMimeType);
virtual ~PlatformDecoderModule() {}

Просмотреть файл

@ -37,13 +37,20 @@ AppleATDecoder::AppleATDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
, mHaveOutput(false)
{
MOZ_COUNT_CTOR(AppleATDecoder);
LOG("Creating Apple AudioToolbox AAC decoder");
LOG("Creating Apple AudioToolbox Audio decoder");
LOG("Audio Decoder configuration: %s %d Hz %d channels %d bits per channel",
mConfig.mime_type,
mConfig.samples_per_second,
mConfig.channel_count,
mConfig.bits_per_sample);
// TODO: Verify aConfig.mime_type.
if (!strcmp(aConfig.mime_type, "audio/mpeg")) {
mFileType = kAudioFileMP3Type;
} else if (!strcmp(aConfig.mime_type, "audio/mp4a-latm")) {
mFileType = kAudioFileAAC_ADTSType;
} else {
mFileType = 0;
}
}
AppleATDecoder::~AppleATDecoder()
@ -80,12 +87,15 @@ _SampleCallback(void* aDecoder,
nsresult
AppleATDecoder::Init()
{
LOG("Initializing Apple AudioToolbox AAC decoder");
AudioFileTypeID fileType = kAudioFileAAC_ADTSType;
if (!mFileType) {
NS_ERROR("Non recognised format");
return NS_ERROR_FAILURE;
}
LOG("Initializing Apple AudioToolbox Audio decoder");
OSStatus rv = AudioFileStreamOpen(this,
_MetadataCallback,
_SampleCallback,
fileType,
mFileType,
&mStream);
if (rv) {
NS_ERROR("Couldn't open AudioFileStream");

Просмотреть файл

@ -53,6 +53,7 @@ private:
int64_t mSamplePosition;
bool mHaveOutput;
AudioStreamBasicDescription mOutputFormat;
AudioFileTypeID mFileType;
void SetupDecoder();
void SubmitSample(nsAutoPtr<mp4_demuxer::MP4Sample> aSample);

Просмотреть файл

@ -87,13 +87,19 @@ AppleDecoderModule::CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aCo
}
already_AddRefed<MediaDataDecoder>
AppleDecoderModule::CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback)
AppleDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback)
{
nsRefPtr<MediaDataDecoder> decoder =
new AppleATDecoder(aConfig, aAudioTaskQueue, aCallback);
return decoder.forget();
}
bool
AppleDecoderModule::SupportsAudioMimeType(const char* aMimeType)
{
return !strcmp(aMimeType, "audio/mp4a-latm") || !strcmp(aMimeType, "audio/mpeg");
}
} // namespace mozilla

Просмотреть файл

@ -34,9 +34,11 @@ public:
// Decode thread.
virtual already_AddRefed<MediaDataDecoder>
CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
virtual bool SupportsAudioMimeType(const char* aMimeType) MOZ_OVERRIDE;
static void Init();
private:

Просмотреть файл

@ -4,7 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "EMEAACDecoder.h"
#include "EMEAudioDecoder.h"
#include "mp4_demuxer/DecoderData.h"
#include "mozilla/EMELog.h"
#include "gmp-audio-host.h"
@ -18,10 +18,10 @@
namespace mozilla {
EMEAACDecoder::EMEAACDecoder(CDMProxy* aProxy,
const AudioDecoderConfig& aConfig,
MediaTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback)
EMEAudioDecoder::EMEAudioDecoder(CDMProxy* aProxy,
const AudioDecoderConfig& aConfig,
MediaTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback)
: mAudioRate(0)
, mAudioBytesPerSample(0)
, mAudioChannels(0)
@ -34,17 +34,17 @@ EMEAACDecoder::EMEAACDecoder(CDMProxy* aProxy,
, mConfig(aConfig)
, mTaskQueue(aTaskQueue)
, mCallback(aCallback)
, mMonitor("EMEAACDecoder")
, mMonitor("EMEAudioDecoder")
, mFlushComplete(false)
{
}
EMEAACDecoder::~EMEAACDecoder()
EMEAudioDecoder::~EMEAudioDecoder()
{
}
nsresult
EMEAACDecoder::Init()
EMEAudioDecoder::Init()
{
// Note: this runs on the decode task queue.
@ -65,7 +65,7 @@ EMEAACDecoder::Init()
}
nsresult
EMEAACDecoder::Input(MP4Sample* aSample)
EMEAudioDecoder::Input(MP4Sample* aSample)
{
MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
@ -77,7 +77,7 @@ EMEAACDecoder::Input(MP4Sample* aSample)
}
nsresult
EMEAACDecoder::Flush()
EMEAudioDecoder::Flush()
{
MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
@ -87,7 +87,7 @@ EMEAACDecoder::Flush()
}
nsRefPtr<nsIRunnable> task;
task = NS_NewRunnableMethod(this, &EMEAACDecoder::GmpFlush);
task = NS_NewRunnableMethod(this, &EMEAudioDecoder::GmpFlush);
nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
@ -102,34 +102,34 @@ EMEAACDecoder::Flush()
}
nsresult
EMEAACDecoder::Drain()
EMEAudioDecoder::Drain()
{
MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
nsRefPtr<nsIRunnable> task;
task = NS_NewRunnableMethod(this, &EMEAACDecoder::GmpDrain);
task = NS_NewRunnableMethod(this, &EMEAudioDecoder::GmpDrain);
nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult
EMEAACDecoder::Shutdown()
EMEAudioDecoder::Shutdown()
{
MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
nsRefPtr<nsIRunnable> task;
task = NS_NewRunnableMethod(this, &EMEAACDecoder::GmpShutdown);
task = NS_NewRunnableMethod(this, &EMEAudioDecoder::GmpShutdown);
nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_SYNC);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
void
EMEAACDecoder::Decoded(const nsTArray<int16_t>& aPCM,
uint64_t aTimeStamp,
uint32_t aChannels,
uint32_t aRate)
EMEAudioDecoder::Decoded(const nsTArray<int16_t>& aPCM,
uint64_t aTimeStamp,
uint32_t aChannels,
uint32_t aRate)
{
MOZ_ASSERT(IsOnGMPThread());
@ -192,21 +192,21 @@ EMEAACDecoder::Decoded(const nsTArray<int16_t>& aPCM,
}
void
EMEAACDecoder::InputDataExhausted()
EMEAudioDecoder::InputDataExhausted()
{
MOZ_ASSERT(IsOnGMPThread());
mCallback->InputExhausted();
}
void
EMEAACDecoder::DrainComplete()
EMEAudioDecoder::DrainComplete()
{
MOZ_ASSERT(IsOnGMPThread());
mCallback->DrainComplete();
}
void
EMEAACDecoder::ResetComplete()
EMEAudioDecoder::ResetComplete()
{
MOZ_ASSERT(IsOnGMPThread());
mMustRecaptureAudioPosition = true;
@ -218,23 +218,23 @@ EMEAACDecoder::ResetComplete()
}
void
EMEAACDecoder::Error(GMPErr aErr)
EMEAudioDecoder::Error(GMPErr aErr)
{
MOZ_ASSERT(IsOnGMPThread());
EME_LOG("EMEAACDecoder::Error");
EME_LOG("EMEAudioDecoder::Error");
mCallback->Error();
GmpShutdown();
}
void
EMEAACDecoder::Terminated()
EMEAudioDecoder::Terminated()
{
MOZ_ASSERT(IsOnGMPThread());
GmpShutdown();
}
nsresult
EMEAACDecoder::GmpInit()
EMEAudioDecoder::GmpInit()
{
MOZ_ASSERT(IsOnGMPThread());
@ -266,7 +266,7 @@ EMEAACDecoder::GmpInit()
}
nsresult
EMEAACDecoder::GmpInput(MP4Sample* aSample)
EMEAudioDecoder::GmpInput(MP4Sample* aSample)
{
MOZ_ASSERT(IsOnGMPThread());
nsAutoPtr<MP4Sample> sample(aSample);
@ -296,7 +296,7 @@ EMEAACDecoder::GmpInput(MP4Sample* aSample)
}
void
EMEAACDecoder::GmpFlush()
EMEAudioDecoder::GmpFlush()
{
MOZ_ASSERT(IsOnGMPThread());
if (!mGMP || NS_FAILED(mGMP->Reset())) {
@ -308,7 +308,7 @@ EMEAACDecoder::GmpFlush()
}
void
EMEAACDecoder::GmpDrain()
EMEAudioDecoder::GmpDrain()
{
MOZ_ASSERT(IsOnGMPThread());
if (!mGMP || NS_FAILED(mGMP->Drain())) {
@ -317,7 +317,7 @@ EMEAACDecoder::GmpDrain()
}
void
EMEAACDecoder::GmpShutdown()
EMEAudioDecoder::GmpShutdown()
{
MOZ_ASSERT(IsOnGMPThread());
if (!mGMP) {

Просмотреть файл

@ -16,18 +16,18 @@
namespace mozilla {
class EMEAACDecoder : public MediaDataDecoder
, public GMPAudioDecoderProxyCallback
class EMEAudioDecoder : public MediaDataDecoder
, public GMPAudioDecoderProxyCallback
{
typedef mp4_demuxer::MP4Sample MP4Sample;
typedef mp4_demuxer::AudioDecoderConfig AudioDecoderConfig;
public:
EMEAACDecoder(CDMProxy* aProxy,
const AudioDecoderConfig& aConfig,
MediaTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback);
EMEAudioDecoder(CDMProxy* aProxy,
const AudioDecoderConfig& aConfig,
MediaTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback);
~EMEAACDecoder();
~EMEAudioDecoder();
// MediaDataDecoder implementation.
virtual nsresult Init() MOZ_OVERRIDE;
@ -51,7 +51,7 @@ private:
class DeliverSample : public nsRunnable {
public:
DeliverSample(EMEAACDecoder* aDecoder,
DeliverSample(EMEAudioDecoder* aDecoder,
mp4_demuxer::MP4Sample* aSample)
: mDecoder(aDecoder)
, mSample(aSample)
@ -62,13 +62,13 @@ private:
return NS_OK;
}
private:
nsRefPtr<EMEAACDecoder> mDecoder;
nsRefPtr<EMEAudioDecoder> mDecoder;
nsAutoPtr<mp4_demuxer::MP4Sample> mSample;
};
class InitTask : public nsRunnable {
public:
InitTask(EMEAACDecoder* aDecoder)
InitTask(EMEAudioDecoder* aDecoder)
: mDecoder(aDecoder)
{}
NS_IMETHOD Run() {
@ -76,7 +76,7 @@ private:
return NS_OK;
}
nsresult mResult;
EMEAACDecoder* mDecoder;
EMEAudioDecoder* mDecoder;
};
nsresult GmpInit();
@ -114,4 +114,4 @@ private:
} // namespace mozilla
#endif
#endif

Просмотреть файл

@ -19,7 +19,7 @@
#include "SharedThreadPool.h"
#include "mozilla/EMELog.h"
#include "EMEH264Decoder.h"
#include "EMEAACDecoder.h"
#include "EMEAudioDecoder.h"
#include <string>
namespace mozilla {
@ -227,21 +227,21 @@ EMEDecoderModule::CreateH264Decoder(const VideoDecoderConfig& aConfig,
}
already_AddRefed<MediaDataDecoder>
EMEDecoderModule::CreateAACDecoder(const AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback)
EMEDecoderModule::CreateAudioDecoder(const AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback)
{
if (mCDMDecodesAudio) {
nsRefPtr<MediaDataDecoder> decoder(new EMEAACDecoder(mProxy,
aConfig,
aAudioTaskQueue,
aCallback));
nsRefPtr<MediaDataDecoder> decoder(new EMEAudioDecoder(mProxy,
aConfig,
aAudioTaskQueue,
aCallback));
return decoder.forget();
}
nsRefPtr<MediaDataDecoder> decoder(mPDM->CreateAACDecoder(aConfig,
aAudioTaskQueue,
aCallback));
nsRefPtr<MediaDataDecoder> decoder(mPDM->CreateAudioDecoder(aConfig,
aAudioTaskQueue,
aCallback));
if (!decoder) {
return nullptr;
}

Просмотреть файл

@ -42,9 +42,9 @@ public:
// Decode thread.
virtual already_AddRefed<MediaDataDecoder>
CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
private:
nsRefPtr<CDMProxy> mProxy;

Просмотреть файл

@ -5,13 +5,13 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS += [
'EMEAACDecoder.h',
'EMEAudioDecoder.h',
'EMEDecoderModule.h',
'EMEH264Decoder.h',
]
UNIFIED_SOURCES += [
'EMEAACDecoder.cpp',
'EMEAudioDecoder.cpp',
'EMEDecoderModule.cpp',
'EMEH264Decoder.cpp',
]

Просмотреть файл

@ -7,7 +7,7 @@
#include "MediaTaskQueue.h"
#include "FFmpegRuntimeLinker.h"
#include "FFmpegAACDecoder.h"
#include "FFmpegAudioDecoder.h"
#define MAX_CHANNELS 16
@ -16,16 +16,17 @@ typedef mp4_demuxer::MP4Sample MP4Sample;
namespace mozilla
{
FFmpegAACDecoder<LIBAV_VER>::FFmpegAACDecoder(
FFmpegAudioDecoder<LIBAV_VER>::FFmpegAudioDecoder(
MediaTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback,
const mp4_demuxer::AudioDecoderConfig& aConfig)
: FFmpegDataDecoder(aTaskQueue, AV_CODEC_ID_AAC), mCallback(aCallback)
: FFmpegDataDecoder(aTaskQueue, GetCodecId(aConfig.mime_type))
, mCallback(aCallback)
{
MOZ_COUNT_CTOR(FFmpegAACDecoder);
MOZ_COUNT_CTOR(FFmpegAudioDecoder);
}
nsresult
FFmpegAACDecoder<LIBAV_VER>::Init()
FFmpegAudioDecoder<LIBAV_VER>::Init()
{
nsresult rv = FFmpegDataDecoder::Init();
NS_ENSURE_SUCCESS(rv, rv);
@ -34,24 +35,44 @@ FFmpegAACDecoder<LIBAV_VER>::Init()
}
static AudioDataValue*
CopyAndPackAudio(AVFrame* aFrame, uint32_t aNumChannels, uint32_t aNumSamples)
CopyAndPackAudio(AVFrame* aFrame, uint32_t aNumChannels, uint32_t aNumAFrames)
{
MOZ_ASSERT(aNumChannels <= MAX_CHANNELS);
nsAutoArrayPtr<AudioDataValue> audio(
new AudioDataValue[aNumChannels * aNumSamples]);
AudioDataValue** data = reinterpret_cast<AudioDataValue**>(aFrame->data);
new AudioDataValue[aNumChannels * aNumAFrames]);
if (aFrame->format == AV_SAMPLE_FMT_FLT) {
// Audio data already packed. No need to do anything other than copy it
// into a buffer we own.
memcpy(audio, data[0], aNumChannels * aNumSamples * sizeof(AudioDataValue));
memcpy(audio, aFrame->data[0],
aNumChannels * aNumAFrames * sizeof(AudioDataValue));
} else if (aFrame->format == AV_SAMPLE_FMT_FLTP) {
// Planar audio data. Pack it into something we can understand.
for (uint32_t channel = 0; channel < aNumChannels; channel++) {
for (uint32_t sample = 0; sample < aNumSamples; sample++) {
audio[sample * aNumChannels + channel] = data[channel][sample];
AudioDataValue* tmp = audio;
AudioDataValue** data = reinterpret_cast<AudioDataValue**>(aFrame->data);
for (uint32_t frame = 0; frame < aNumAFrames; frame++) {
for (uint32_t channel = 0; channel < aNumChannels; channel++) {
*tmp++ = data[channel][frame];
}
}
} else if (aFrame->format == AV_SAMPLE_FMT_S16) {
// Audio data already packed. Need to convert from S16 to 32 bits Float
AudioDataValue* tmp = audio;
int16_t* data = reinterpret_cast<int16_t**>(aFrame->data)[0];
for (uint32_t frame = 0; frame < aNumAFrames; frame++) {
for (uint32_t channel = 0; channel < aNumChannels; channel++) {
*tmp++ = AudioSampleToFloat(*data++);
}
}
} else if (aFrame->format == AV_SAMPLE_FMT_S16P) {
// Planar audio data. Convert it from S16 to 32 bits float
// and pack it into something we can understand.
AudioDataValue* tmp = audio;
int16_t** data = reinterpret_cast<int16_t**>(aFrame->data);
for (uint32_t frame = 0; frame < aNumAFrames; frame++) {
for (uint32_t channel = 0; channel < aNumChannels; channel++) {
*tmp++ = AudioSampleToFloat(data[channel][frame]);
}
}
}
@ -60,7 +81,7 @@ CopyAndPackAudio(AVFrame* aFrame, uint32_t aNumChannels, uint32_t aNumSamples)
}
void
FFmpegAACDecoder<LIBAV_VER>::DecodePacket(MP4Sample* aSample)
FFmpegAudioDecoder<LIBAV_VER>::DecodePacket(MP4Sample* aSample)
{
AVPacket packet;
av_init_packet(&packet);
@ -107,24 +128,38 @@ FFmpegAACDecoder<LIBAV_VER>::DecodePacket(MP4Sample* aSample)
}
nsresult
FFmpegAACDecoder<LIBAV_VER>::Input(MP4Sample* aSample)
FFmpegAudioDecoder<LIBAV_VER>::Input(MP4Sample* aSample)
{
mTaskQueue->Dispatch(NS_NewRunnableMethodWithArg<nsAutoPtr<MP4Sample> >(
this, &FFmpegAACDecoder::DecodePacket, nsAutoPtr<MP4Sample>(aSample)));
this, &FFmpegAudioDecoder::DecodePacket, nsAutoPtr<MP4Sample>(aSample)));
return NS_OK;
}
nsresult
FFmpegAACDecoder<LIBAV_VER>::Drain()
FFmpegAudioDecoder<LIBAV_VER>::Drain()
{
mCallback->DrainComplete();
return NS_OK;
}
FFmpegAACDecoder<LIBAV_VER>::~FFmpegAACDecoder()
AVCodecID
FFmpegAudioDecoder<LIBAV_VER>::GetCodecId(const char* aMimeType)
{
MOZ_COUNT_DTOR(FFmpegAACDecoder);
if (!strcmp(aMimeType, "audio/mpeg")) {
return AV_CODEC_ID_MP3;
}
if (!strcmp(aMimeType, "audio/mp4a-latm")) {
return AV_CODEC_ID_AAC;
}
return AV_CODEC_ID_NONE;
}
FFmpegAudioDecoder<LIBAV_VER>::~FFmpegAudioDecoder()
{
MOZ_COUNT_DTOR(FFmpegAudioDecoder);
}
} // namespace mozilla

Просмотреть файл

@ -13,22 +13,23 @@
namespace mozilla
{
template <int V> class FFmpegAACDecoder
template <int V> class FFmpegAudioDecoder
{
};
template <>
class FFmpegAACDecoder<LIBAV_VER> : public FFmpegDataDecoder<LIBAV_VER>
class FFmpegAudioDecoder<LIBAV_VER> : public FFmpegDataDecoder<LIBAV_VER>
{
public:
FFmpegAACDecoder(MediaTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback,
const mp4_demuxer::AudioDecoderConfig& aConfig);
virtual ~FFmpegAACDecoder();
FFmpegAudioDecoder(MediaTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback,
const mp4_demuxer::AudioDecoderConfig& aConfig);
virtual ~FFmpegAudioDecoder();
virtual nsresult Init() MOZ_OVERRIDE;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
virtual nsresult Drain() MOZ_OVERRIDE;
static AVCodecID GetCodecId(const char* aMimeType);
private:
void DecodePacket(mp4_demuxer::MP4Sample* aSample);

Просмотреть файл

@ -108,8 +108,10 @@ FFmpegDataDecoder<LIBAV_VER>::Init()
if (mCodecContext->codec_type == AVMEDIA_TYPE_AUDIO &&
mCodecContext->sample_fmt != AV_SAMPLE_FMT_FLT &&
mCodecContext->sample_fmt != AV_SAMPLE_FMT_FLTP) {
NS_WARNING("FFmpeg AAC decoder outputs unsupported audio format.");
mCodecContext->sample_fmt != AV_SAMPLE_FMT_FLTP &&
mCodecContext->sample_fmt != AV_SAMPLE_FMT_S16 &&
mCodecContext->sample_fmt != AV_SAMPLE_FMT_S16P) {
NS_WARNING("FFmpeg audio decoder outputs unsupported audio format.");
return NS_ERROR_FAILURE;
}

Просмотреть файл

@ -8,7 +8,7 @@
#define __FFmpegDecoderModule_h__
#include "PlatformDecoderModule.h"
#include "FFmpegAACDecoder.h"
#include "FFmpegAudioDecoder.h"
#include "FFmpegH264Decoder.h"
namespace mozilla
@ -39,14 +39,19 @@ public:
}
virtual already_AddRefed<MediaDataDecoder>
CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE
CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE
{
nsRefPtr<MediaDataDecoder> decoder =
new FFmpegAACDecoder<V>(aAudioTaskQueue, aCallback, aConfig);
new FFmpegAudioDecoder<V>(aAudioTaskQueue, aCallback, aConfig);
return decoder.forget();
}
virtual bool SupportsAudioMimeType(const char* aMimeType) MOZ_OVERRIDE
{
return FFmpegAudioDecoder<V>::GetCodecId(aMimeType) != AV_CODEC_ID_NONE;
}
};
} // namespace mozilla

Просмотреть файл

@ -18,6 +18,8 @@ extern "C" {
#if LIBAVCODEC_VERSION_MAJOR < 55
#define AV_CODEC_ID_H264 CODEC_ID_H264
#define AV_CODEC_ID_AAC CODEC_ID_AAC
#define AV_CODEC_ID_MP3 CODEC_ID_MP3
#define AV_CODEC_ID_NONE CODEC_ID_NONE
typedef CodecID AVCodecID;
#endif

Просмотреть файл

@ -5,7 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
'../FFmpegAACDecoder.cpp',
'../FFmpegAudioDecoder.cpp',
'../FFmpegDataDecoder.cpp',
'../FFmpegDecoderModule.cpp',
'../FFmpegH264Decoder.cpp',

Просмотреть файл

@ -5,7 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
'../FFmpegAACDecoder.cpp',
'../FFmpegAudioDecoder.cpp',
'../FFmpegDataDecoder.cpp',
'../FFmpegDecoderModule.cpp',
'../FFmpegH264Decoder.cpp',

Просмотреть файл

@ -5,7 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
'../FFmpegAACDecoder.cpp',
'../FFmpegAudioDecoder.cpp',
'../FFmpegDataDecoder.cpp',
'../FFmpegDecoderModule.cpp',
'../FFmpegH264Decoder.cpp',

Просмотреть файл

@ -48,9 +48,9 @@ GonkDecoderModule::CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aCon
}
already_AddRefed<MediaDataDecoder>
GonkDecoderModule::CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback)
GonkDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback)
{
nsRefPtr<MediaDataDecoder> decoder =
new GonkMediaDataDecoder(new GonkAudioDecoderManager(aConfig), aAudioTaskQueue,

Просмотреть файл

@ -29,9 +29,9 @@ public:
// Decode thread.
virtual already_AddRefed<MediaDataDecoder>
CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
static void Init();
};

Просмотреть файл

@ -81,9 +81,9 @@ WMFDecoderModule::CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConf
}
already_AddRefed<MediaDataDecoder>
WMFDecoderModule::CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback)
WMFDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback)
{
nsRefPtr<MediaDataDecoder> decoder =
new WMFMediaDataDecoder(new WMFAudioMFTManager(aConfig),

Просмотреть файл

@ -30,9 +30,9 @@ public:
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
virtual already_AddRefed<MediaDataDecoder>
CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
// Called on main thread.
static void Init();

Просмотреть файл

@ -8,6 +8,7 @@
#include "mp4_demuxer/DecoderData.h"
#include "media/stagefright/MetaData.h"
#include "media/stagefright/MediaBuffer.h"
#include "media/stagefright/MediaDefs.h"
#include "media/stagefright/Utils.h"
#include "mozilla/ArrayUtils.h"
#include "include/ESDS.h"
@ -159,7 +160,7 @@ bool
AudioDecoderConfig::IsValid()
{
return channel_count > 0 && samples_per_second > 0 && frequency_index > 0 &&
aac_profile > 0;
(mime_type != MEDIA_MIMETYPE_AUDIO_AAC || aac_profile > 0);
}
void

Просмотреть файл

@ -4,6 +4,7 @@
#include "include/MPEG4Extractor.h"
#include "media/stagefright/DataSource.h"
#include "media/stagefright/MediaDefs.h"
#include "media/stagefright/MediaSource.h"
#include "media/stagefright/MetaData.h"
#include "mp4_demuxer/Adts.h"
@ -168,10 +169,12 @@ MP4Demuxer::DemuxAudioSample()
}
sample->Update();
if (!Adts::ConvertEsdsToAdts(mAudioConfig.channel_count,
mAudioConfig.frequency_index,
mAudioConfig.aac_profile, sample)) {
return nullptr;
if (!strcmp(mAudioConfig.mime_type, MEDIA_MIMETYPE_AUDIO_AAC)) {
if (!Adts::ConvertEsdsToAdts(mAudioConfig.channel_count,
mAudioConfig.frequency_index,
mAudioConfig.aac_profile, sample)) {
return nullptr;
}
}
return sample.forget();

Просмотреть файл

@ -2302,10 +2302,7 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
if (objectTypeIndication == 0x6b) {
// The media subtype is MP3 audio
// Our software MP3 audio decoder may not be able to handle
// packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
ALOGE("MP3 track in MP4/3GPP file is not supported");
return ERROR_UNSUPPORTED;
mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
}
const uint8_t *csd;