mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 1205927 - Part 1: [MediaEncoder] Support *.3g2 with EVRC audio format. r=ayang
This commit is contained in:
parent
bff6406254
commit
42b02d58cd
@ -599,6 +599,12 @@ private:
|
||||
mRecorder->GetVideoBitrate(),
|
||||
mRecorder->GetBitrate(),
|
||||
aTrackTypes);
|
||||
} else if (mRecorder->mMimeType.EqualsLiteral(AUDIO_3GPP2)) {
|
||||
mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(AUDIO_3GPP2),
|
||||
mRecorder->GetAudioBitrate(),
|
||||
mRecorder->GetVideoBitrate(),
|
||||
mRecorder->GetBitrate(),
|
||||
aTrackTypes);
|
||||
} else {
|
||||
mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(""),
|
||||
mRecorder->GetAudioBitrate(),
|
||||
|
@ -60,6 +60,8 @@ public:
|
||||
AAC_CSD, // AAC codec specific data
|
||||
AMR_AUDIO_CSD,
|
||||
AMR_AUDIO_FRAME,
|
||||
EVRC_AUDIO_CSD,
|
||||
EVRC_AUDIO_FRAME,
|
||||
UNKNOWN // FrameType not set
|
||||
};
|
||||
void SwapInFrameData(nsTArray<uint8_t>& aData)
|
||||
|
@ -130,6 +130,14 @@ MediaEncoder::CreateEncoder(const nsAString& aMIMEType, uint32_t aAudioBitrate,
|
||||
writer = new ISOMediaWriter(aTrackTypes, ISOMediaWriter::TYPE_FRAG_3GP);
|
||||
NS_ENSURE_TRUE(writer, nullptr);
|
||||
mimeType = NS_LITERAL_STRING(AUDIO_3GPP);
|
||||
} else if (MediaEncoder::IsOMXEncoderEnabled() &&
|
||||
(aMIMEType.EqualsLiteral(AUDIO_3GPP2))) {
|
||||
audioEncoder = new OmxEVRCAudioTrackEncoder();
|
||||
NS_ENSURE_TRUE(audioEncoder, nullptr);
|
||||
|
||||
writer = new ISOMediaWriter(aTrackTypes, ISOMediaWriter::TYPE_FRAG_3G2);
|
||||
NS_ENSURE_TRUE(writer, nullptr);
|
||||
mimeType = NS_LITERAL_STRING(AUDIO_3GPP2) ;
|
||||
}
|
||||
#endif // MOZ_OMX_ENCODER
|
||||
else if (MediaDecoder::IsOggEnabled() && MediaDecoder::IsOpusEnabled() &&
|
||||
|
@ -184,7 +184,7 @@ OmxAudioTrackEncoder::AppendEncodedFrames(EncodedFrameContainer& aContainer)
|
||||
3000); // wait up to 3ms
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!frameData.IsEmpty()) {
|
||||
if (!frameData.IsEmpty() || outFlags & OMXCodecWrapper::BUFFER_EOS) { // Some hw codec may send out EOS with an empty frame
|
||||
bool isCSD = false;
|
||||
if (outFlags & OMXCodecWrapper::BUFFER_CODEC_CONFIG) { // codec specific data
|
||||
isCSD = true;
|
||||
@ -199,6 +199,9 @@ OmxAudioTrackEncoder::AppendEncodedFrames(EncodedFrameContainer& aContainer)
|
||||
} else if (mEncoder->GetCodecType() == OMXCodecWrapper::AMR_NB_ENC){
|
||||
audiodata->SetFrameType(isCSD ?
|
||||
EncodedFrame::AMR_AUDIO_CSD : EncodedFrame::AMR_AUDIO_FRAME);
|
||||
} else if (mEncoder->GetCodecType() == OMXCodecWrapper::EVRC_ENC){
|
||||
audiodata->SetFrameType(isCSD ?
|
||||
EncodedFrame::EVRC_AUDIO_CSD : EncodedFrame::EVRC_AUDIO_FRAME);
|
||||
} else {
|
||||
MOZ_ASSERT(false, "audio codec not supported");
|
||||
}
|
||||
@ -343,4 +346,44 @@ OmxAMRAudioTrackEncoder::GetMetadata()
|
||||
return meta.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
OmxEVRCAudioTrackEncoder::Init(int aChannels, int aSamplingRate)
|
||||
{
|
||||
mChannels = aChannels;
|
||||
mSamplingRate = aSamplingRate;
|
||||
|
||||
mEncoder = OMXCodecWrapper::CreateEVRCEncoder();
|
||||
NS_ENSURE_TRUE(mEncoder, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv = mEncoder->Configure(mChannels, mSamplingRate, EVRC_SAMPLERATE);
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
mInitialized = (rv == NS_OK);
|
||||
|
||||
mReentrantMonitor.NotifyAll();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<TrackMetadataBase>
|
||||
OmxEVRCAudioTrackEncoder::GetMetadata()
|
||||
{
|
||||
PROFILER_LABEL("OmxEVRCAudioTrackEncoder", "GetMetadata",
|
||||
js::ProfileEntry::Category::OTHER);
|
||||
{
|
||||
// Wait if mEncoder is not initialized nor is being canceled.
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
while (!mCanceled && !mInitialized) {
|
||||
mReentrantMonitor.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
if (mCanceled || mEncodingComplete) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<EVRCTrackMetadata> meta = new EVRCTrackMetadata();
|
||||
meta->mChannels = mChannels;
|
||||
return meta.forget();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -90,5 +90,21 @@ protected:
|
||||
nsresult Init(int aChannels, int aSamplingRate) override;
|
||||
};
|
||||
|
||||
class OmxEVRCAudioTrackEncoder final : public OmxAudioTrackEncoder
|
||||
{
|
||||
public:
|
||||
OmxEVRCAudioTrackEncoder()
|
||||
: OmxAudioTrackEncoder()
|
||||
{}
|
||||
|
||||
enum {
|
||||
EVRC_SAMPLERATE = 8000,
|
||||
};
|
||||
already_AddRefed<TrackMetadataBase> GetMetadata() override;
|
||||
|
||||
protected:
|
||||
nsresult Init(int aChannels, int aSamplingRate) override;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -22,6 +22,7 @@ public:
|
||||
METADATA_AVC,
|
||||
METADATA_AAC,
|
||||
METADATA_AMR,
|
||||
METADATA_EVRC,
|
||||
METADATA_UNKNOWN // Metadata Kind not set
|
||||
};
|
||||
// Return the specific metadata kind
|
||||
|
84
dom/media/encoder/fmp4_muxer/EVRCBox.cpp
Normal file
84
dom/media/encoder/fmp4_muxer/EVRCBox.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 "ISOControl.h"
|
||||
#include "ISOMediaBoxes.h"
|
||||
#include "EVRCBox.h"
|
||||
#include "ISOTrackMetadata.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
nsresult
|
||||
EVRCSampleEntry::Generate(uint32_t* aBoxSize)
|
||||
{
|
||||
uint32_t box_size;
|
||||
nsresult rv = evrc_special_box->Generate(&box_size);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
size += box_size;
|
||||
|
||||
*aBoxSize = size;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
EVRCSampleEntry::Write()
|
||||
{
|
||||
BoxSizeChecker checker(mControl, size);
|
||||
nsresult rv;
|
||||
rv = AudioSampleEntry::Write();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = evrc_special_box->Write();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
EVRCSampleEntry::EVRCSampleEntry(ISOControl* aControl)
|
||||
: AudioSampleEntry(NS_LITERAL_CSTRING("sevc"), aControl)
|
||||
{
|
||||
evrc_special_box = new EVRCSpecificBox(aControl);
|
||||
MOZ_COUNT_CTOR(EVRCSampleEntry);
|
||||
}
|
||||
|
||||
EVRCSampleEntry::~EVRCSampleEntry()
|
||||
{
|
||||
MOZ_COUNT_DTOR(EVRCSampleEntry);
|
||||
}
|
||||
|
||||
nsresult
|
||||
EVRCSpecificBox::Generate(uint32_t* aBoxSize)
|
||||
{
|
||||
nsresult rv;
|
||||
FragmentBuffer* frag = mControl->GetFragment(Audio_Track);
|
||||
rv = frag->GetCSD(evrcDecSpecInfo);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
size += evrcDecSpecInfo.Length();
|
||||
*aBoxSize = size;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
EVRCSpecificBox::Write()
|
||||
{
|
||||
BoxSizeChecker checker(mControl, size);
|
||||
Box::Write();
|
||||
mControl->Write(evrcDecSpecInfo.Elements(), evrcDecSpecInfo.Length());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
EVRCSpecificBox::EVRCSpecificBox(ISOControl* aControl)
|
||||
: Box(NS_LITERAL_CSTRING("devc"), aControl)
|
||||
{
|
||||
MOZ_COUNT_CTOR(EVRCSpecificBox);
|
||||
}
|
||||
|
||||
EVRCSpecificBox::~EVRCSpecificBox()
|
||||
{
|
||||
MOZ_COUNT_DTOR(EVRCSpecificBox);
|
||||
}
|
||||
|
||||
}
|
50
dom/media/encoder/fmp4_muxer/EVRCBox.h
Normal file
50
dom/media/encoder/fmp4_muxer/EVRCBox.h
Normal file
@ -0,0 +1,50 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#ifndef EVRCBOX_h_
|
||||
#define EVRCBOX_h_
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "MuxerOperation.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ISOControl;
|
||||
|
||||
// 3GPP TS 26.244 6.7 'EVRCSpecificBox field for EVRCSampleEntry box'
|
||||
// Box type: 'devc'
|
||||
class EVRCSpecificBox : public Box {
|
||||
public:
|
||||
// 3GPP members
|
||||
nsTArray<uint8_t> evrcDecSpecInfo;
|
||||
|
||||
// MuxerOperation methods
|
||||
nsresult Generate(uint32_t* aBoxSize) override;
|
||||
nsresult Write() override;
|
||||
|
||||
// EVRCSpecificBox methods
|
||||
EVRCSpecificBox(ISOControl* aControl);
|
||||
~EVRCSpecificBox();
|
||||
};
|
||||
|
||||
// 3GPP TS 26.244 6.5 'EVRCSampleEntry box'
|
||||
// Box type: 'sevc'
|
||||
class EVRCSampleEntry : public AudioSampleEntry {
|
||||
public:
|
||||
// 3GPP members
|
||||
RefPtr<EVRCSpecificBox> evrc_special_box;
|
||||
|
||||
// MuxerOperation methods
|
||||
nsresult Generate(uint32_t* aBoxSize) override;
|
||||
nsresult Write() override;
|
||||
|
||||
// EVRCSampleEntry methods
|
||||
EVRCSampleEntry(ISOControl* aControl);
|
||||
~EVRCSampleEntry();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // EVRCBOX_h_
|
@ -62,7 +62,7 @@ FragmentBuffer::AddFrame(EncodedFrame* aFrame)
|
||||
|
||||
EncodedFrame::FrameType type = aFrame->GetFrameType();
|
||||
if (type == EncodedFrame::AAC_CSD || type == EncodedFrame::AVC_CSD ||
|
||||
type == EncodedFrame::AMR_AUDIO_CSD) {
|
||||
type == EncodedFrame::AMR_AUDIO_CSD || type == EncodedFrame::EVRC_AUDIO_CSD) {
|
||||
mCSDFrame = aFrame;
|
||||
// Use CSD's timestamp as the start time. Encoder should send CSD frame first
|
||||
// and then data frames.
|
||||
@ -168,7 +168,8 @@ ISOControl::SetMetadata(TrackMetadataBase* aTrackMeta)
|
||||
{
|
||||
if (aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AAC ||
|
||||
aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AMR ||
|
||||
aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AVC) {
|
||||
aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AVC ||
|
||||
aTrackMeta->GetKind() == TrackMetadataBase::METADATA_EVRC) {
|
||||
mMetaArray.AppendElement(aTrackMeta);
|
||||
return NS_OK;
|
||||
}
|
||||
@ -180,7 +181,8 @@ ISOControl::GetAudioMetadata(RefPtr<AudioTrackMetadata>& aAudMeta)
|
||||
{
|
||||
for (uint32_t i = 0; i < mMetaArray.Length() ; i++) {
|
||||
if (mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AAC ||
|
||||
mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AMR) {
|
||||
mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AMR ||
|
||||
mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_EVRC) {
|
||||
aAudMeta = static_cast<AudioTrackMetadata*>(mMetaArray[i].get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "MP4ESDS.h"
|
||||
#include "AMRBox.h"
|
||||
#include "AVCBox.h"
|
||||
#include "EVRCBox.h"
|
||||
#include "VideoUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -666,6 +667,8 @@ SampleDescriptionBox::CreateAudioSampleEntry(RefPtr<SampleEntryBox>& aSampleEntr
|
||||
aSampleEntry = new AMRSampleEntry(mControl);
|
||||
} else if (mAudioMeta->GetKind() == TrackMetadataBase::METADATA_AAC) {
|
||||
aSampleEntry = new MP4AudioSampleEntry(mControl);
|
||||
} else if (mAudioMeta->GetKind() == TrackMetadataBase::METADATA_EVRC) {
|
||||
aSampleEntry = new EVRCSampleEntry(mControl);
|
||||
} else {
|
||||
MOZ_ASSERT(0);
|
||||
}
|
||||
@ -1250,6 +1253,17 @@ FileTypeBox::Generate(uint32_t* aBoxSize)
|
||||
compatible_brands.AppendElement("3gp7");
|
||||
compatible_brands.AppendElement("3gp6");
|
||||
compatible_brands.AppendElement("isom");
|
||||
} else if (mControl->GetMuxingType() == ISOMediaWriter::TYPE_FRAG_3G2) {
|
||||
major_brand = "3g2a";
|
||||
// 3GPP2 Release 0 and A and 3GPP Release 6 allow movie fragmentation
|
||||
compatible_brands.AppendElement("3gp9");
|
||||
compatible_brands.AppendElement("3gp8");
|
||||
compatible_brands.AppendElement("3gp7");
|
||||
compatible_brands.AppendElement("3gp6");
|
||||
compatible_brands.AppendElement("isom");
|
||||
compatible_brands.AppendElement("3g2c");
|
||||
compatible_brands.AppendElement("3g2b");
|
||||
compatible_brands.AppendElement("3g2a");
|
||||
} else {
|
||||
MOZ_ASSERT(0);
|
||||
}
|
||||
|
@ -104,7 +104,9 @@ ISOMediaWriter::WriteEncodedTrack(const EncodedFrameContainer& aData,
|
||||
if (type == EncodedFrame::AAC_AUDIO_FRAME ||
|
||||
type == EncodedFrame::AAC_CSD ||
|
||||
type == EncodedFrame::AMR_AUDIO_FRAME ||
|
||||
type == EncodedFrame::AMR_AUDIO_CSD) {
|
||||
type == EncodedFrame::AMR_AUDIO_CSD ||
|
||||
type == EncodedFrame::EVRC_AUDIO_FRAME ||
|
||||
type == EncodedFrame::EVRC_AUDIO_CSD) {
|
||||
frag = mAudioFragmentBuffer;
|
||||
} else if (type == EncodedFrame::AVC_I_FRAME ||
|
||||
type == EncodedFrame::AVC_P_FRAME ||
|
||||
@ -212,7 +214,8 @@ ISOMediaWriter::SetMetadata(TrackMetadataBase* aMetadata)
|
||||
PROFILER_LABEL("ISOMediaWriter", "SetMetadata",
|
||||
js::ProfileEntry::Category::OTHER);
|
||||
if (aMetadata->GetKind() == TrackMetadataBase::METADATA_AAC ||
|
||||
aMetadata->GetKind() == TrackMetadataBase::METADATA_AMR) {
|
||||
aMetadata->GetKind() == TrackMetadataBase::METADATA_AMR ||
|
||||
aMetadata->GetKind() == TrackMetadataBase::METADATA_EVRC) {
|
||||
mControl->SetMetadata(aMetadata);
|
||||
mAudioFragmentBuffer = new FragmentBuffer(Audio_Track, FRAG_DURATION);
|
||||
mControl->SetFragment(mAudioFragmentBuffer);
|
||||
|
@ -26,6 +26,10 @@ public:
|
||||
// Brand names in 'ftyp' box are '3gp9' and 'isom'.
|
||||
const static uint32_t TYPE_FRAG_3GP = 1 << 1;
|
||||
|
||||
// Generate an fragmented 3G2 stream, 3GPP2 C.S0050-B
|
||||
// Brand names in 'ftyp' box are '3g2c' and 'isom'
|
||||
const static uint32_t TYPE_FRAG_3G2 = 1 << 2;
|
||||
|
||||
// aType is the combination of CREATE_AUDIO_TRACK and CREATE_VIDEO_TRACK.
|
||||
// It is a hint to muxer that the output streaming contains audio, video
|
||||
// or both.
|
||||
|
@ -99,6 +99,33 @@ public:
|
||||
~AMRTrackMetadata() { MOZ_COUNT_DTOR(AMRTrackMetadata); }
|
||||
};
|
||||
|
||||
// EVRC sample rate is 8000 samples/s.
|
||||
#define EVRC_SAMPLE_RATE 8000
|
||||
|
||||
class EVRCTrackMetadata : public AudioTrackMetadata {
|
||||
public:
|
||||
// AudioTrackMetadata members
|
||||
//
|
||||
// The number of sample sets generates by encoder is variant. So the
|
||||
// frame duration and frame size are both 0.
|
||||
uint32_t GetAudioFrameDuration() override { return 0; }
|
||||
uint32_t GetAudioFrameSize() override { return 0; }
|
||||
uint32_t GetAudioSampleRate() override { return EVRC_SAMPLE_RATE; }
|
||||
uint32_t GetAudioChannels() override { return mChannels; }
|
||||
|
||||
// TrackMetadataBase member
|
||||
MetadataKind GetKind() const override { return METADATA_EVRC; }
|
||||
|
||||
// EVRCTrackMetadata members
|
||||
EVRCTrackMetadata()
|
||||
: mChannels(0) {
|
||||
MOZ_COUNT_CTOR(EVRCTrackMetadata);
|
||||
}
|
||||
~EVRCTrackMetadata() { MOZ_COUNT_DTOR(EVRCTrackMetadata); }
|
||||
|
||||
uint32_t mChannels; // Channel number, it should be 1 or 2.
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // ISOTrackMetadata_h_
|
||||
|
@ -12,6 +12,7 @@ EXPORTS += [
|
||||
UNIFIED_SOURCES += [
|
||||
'AMRBox.cpp',
|
||||
'AVCBox.cpp',
|
||||
'EVRCBox.cpp',
|
||||
'ISOControl.cpp',
|
||||
'ISOMediaBoxes.cpp',
|
||||
'ISOMediaWriter.cpp',
|
||||
|
@ -30,6 +30,7 @@ using namespace mozilla::layers;
|
||||
#define INPUT_BUFFER_TIMEOUT_US (5 * 1000ll)
|
||||
// AMR NB kbps
|
||||
#define AMRNB_BITRATE 12200
|
||||
#define EVRC_BITRATE 8755
|
||||
|
||||
#define CODEC_ERROR(args...) \
|
||||
do { \
|
||||
@ -38,6 +39,8 @@ using namespace mozilla::layers;
|
||||
|
||||
namespace android {
|
||||
|
||||
const char *MEDIA_MIMETYPE_AUDIO_EVRC = "audio/evrc";
|
||||
|
||||
enum BufferState
|
||||
{
|
||||
BUFFER_OK,
|
||||
@ -85,6 +88,16 @@ OMXCodecWrapper::CreateAMRNBEncoder()
|
||||
return amr.forget();
|
||||
}
|
||||
|
||||
OMXAudioEncoder*
|
||||
OMXCodecWrapper::CreateEVRCEncoder()
|
||||
{
|
||||
nsAutoPtr<OMXAudioEncoder> evrc(new OMXAudioEncoder(CodecType::EVRC_ENC));
|
||||
// Return the object only when media codec is valid.
|
||||
NS_ENSURE_TRUE(evrc->IsValid(), nullptr);
|
||||
|
||||
return evrc.forget();
|
||||
}
|
||||
|
||||
OMXVideoEncoder*
|
||||
OMXCodecWrapper::CreateAVCEncoder()
|
||||
{
|
||||
@ -99,6 +112,7 @@ OMXCodecWrapper::OMXCodecWrapper(CodecType aCodecType)
|
||||
: mCodecType(aCodecType)
|
||||
, mStarted(false)
|
||||
, mAMRCSDProvided(false)
|
||||
, mEVRCCSDProvided(false)
|
||||
{
|
||||
ProcessState::self()->startThreadPool();
|
||||
|
||||
@ -111,6 +125,8 @@ OMXCodecWrapper::OMXCodecWrapper(CodecType aCodecType)
|
||||
mCodec = MediaCodec::CreateByType(mLooper, MEDIA_MIMETYPE_AUDIO_AMR_NB, true);
|
||||
} else if (aCodecType == CodecType::AAC_ENC) {
|
||||
mCodec = MediaCodec::CreateByType(mLooper, MEDIA_MIMETYPE_AUDIO_AAC, true);
|
||||
} else if (aCodecType == CodecType::EVRC_ENC) {
|
||||
mCodec = MediaCodec::CreateByType(mLooper, MEDIA_MIMETYPE_AUDIO_EVRC, true);
|
||||
} else {
|
||||
NS_ERROR("Unknown codec type.");
|
||||
}
|
||||
@ -633,6 +649,10 @@ OMXAudioEncoder::Configure(int aChannels, int aInputSampleRate,
|
||||
format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
|
||||
format->setInt32("bitrate", AMRNB_BITRATE);
|
||||
format->setInt32("sample-rate", aEncodedSampleRate);
|
||||
} else if (mCodecType == EVRC_ENC) {
|
||||
format->setString("mime", MEDIA_MIMETYPE_AUDIO_EVRC);
|
||||
format->setInt32("bitrate", EVRC_BITRATE);
|
||||
format->setInt32("sample-rate", aEncodedSampleRate);
|
||||
} else {
|
||||
MOZ_ASSERT(false, "Can't support this codec type!!");
|
||||
}
|
||||
@ -1070,6 +1090,18 @@ OMXCodecWrapper::GetNextEncodedFrame(nsTArray<uint8_t>* aOutputBuf,
|
||||
aOutputBuf->AppendElements(decConfig, sizeof(decConfig));
|
||||
outFlags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
|
||||
mAMRCSDProvided = true;
|
||||
} else if ((mCodecType == EVRC_ENC) && !mEVRCCSDProvided){
|
||||
// OMX EVRC codec won't provide csd data, need to generate a fake one.
|
||||
RefPtr<EncodedFrame> audiodata = new EncodedFrame();
|
||||
// Decoder config descriptor
|
||||
const uint8_t decConfig[] = {
|
||||
0x0, 0x0, 0x0, 0x0, // vendor: 4 bytes
|
||||
0x0, // decoder version
|
||||
0x01, // frames per sample
|
||||
};
|
||||
aOutputBuf->AppendElements(decConfig, sizeof(decConfig));
|
||||
outFlags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
|
||||
mEVRCCSDProvided = true;
|
||||
} else {
|
||||
AppendFrame(aOutputBuf, omxBuf->data(), omxBuf->size());
|
||||
}
|
||||
|
@ -88,6 +88,7 @@ public:
|
||||
AAC_ENC, // AAC encoder.
|
||||
AMR_NB_ENC, // AMR_NB encoder.
|
||||
AVC_ENC, // AVC/H.264 encoder.
|
||||
EVRC_ENC, // EVRC encoder
|
||||
TYPE_COUNT
|
||||
};
|
||||
|
||||
@ -120,6 +121,9 @@ public:
|
||||
/** Create a AMR audio encoder. Returns nullptr when failed. */
|
||||
static OMXAudioEncoder* CreateAMRNBEncoder();
|
||||
|
||||
/** Create a EVRC audio encoder. Returns nullptr when failed. */
|
||||
static OMXAudioEncoder* CreateEVRCEncoder();
|
||||
|
||||
/** Create a AVC/H.264 video encoder. Returns nullptr when failed. */
|
||||
static OMXVideoEncoder* CreateAVCEncoder();
|
||||
|
||||
@ -204,6 +208,7 @@ private:
|
||||
int mCodecType;
|
||||
bool mStarted; // Has MediaCodec been started?
|
||||
bool mAMRCSDProvided;
|
||||
bool mEVRCCSDProvided;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define AUDIO_AMR "audio/amr"
|
||||
#define AUDIO_FLAC "audio/flac"
|
||||
#define AUDIO_3GPP "audio/3gpp"
|
||||
#define AUDIO_3GPP2 "audio/3gpp2"
|
||||
#define AUDIO_MIDI "audio/x-midi"
|
||||
#define AUDIO_MATROSKA "audio/x-matroska"
|
||||
|
||||
|
@ -618,6 +618,7 @@ static nsExtraMimeTypeEntry extraMimeEntries [] =
|
||||
// app on Firefox OS depends on the "3gp" extension mapping to the
|
||||
// "video/3gpp" MIME type.
|
||||
{ AUDIO_3GPP, "3gpp,3gp", "3GPP Audio" },
|
||||
{ AUDIO_3GPP2, "3g2", "3GPP2 Audio" },
|
||||
#endif
|
||||
{ AUDIO_MIDI, "mid", "Standard MIDI Audio" }
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user