blob: 11f0a707ef07e02b5c001e42ae85df501567feb8 [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
; INCLUDES
----------------------------------------------------------------------------*/
#include "amr_enc.h"
OmxAmrEncoder::OmxAmrEncoder()
{
// Codec and encoder setting structure
ipGsmEncoder = NULL;
ipEncProps = NULL;
iNextStartTime = 0;
iOutputFormat = PVMF_MIME_AMR_IETF;
ipSizeArrayForOutputFrames = NULL;
iNextStartTime = 0;
iMaxNumOutputFramesPerBuffer = MAX_NUM_OUTPUT_FRAMES_PER_BUFFER;
iOneInputFrameLength = 320;
iMaxInputSize = 0;
iAmrInitFlag = 0;
}
/* Decoder Initialization function */
OMX_BOOL OmxAmrEncoder::AmrEncInit(OMX_AUDIO_PARAM_PCMMODETYPE aPcmMode,
OMX_AUDIO_PARAM_AMRTYPE aAmrParam,
OMX_U32* aInputFrameLength,
OMX_U32* aMaxNumberOutputFrames)
{
OMX_U32 MaxOutputBufferSize;
iAmrInitFlag = 0;
ipGsmEncoder = OSCL_NEW(CPvGsmAmrEncoder, ());
if (!ipGsmEncoder)
{
return OMX_FALSE;
}
// for encoder properties
ipEncProps = OSCL_NEW(TEncodeProperties, ());
if (!ipEncProps)
{
return OMX_FALSE;
}
//Extracting the output format information
if (OMX_AUDIO_AMRFrameFormatFSF == aAmrParam.eAMRFrameFormat)
{
iOutputFormat = PVMF_MIME_AMR_IETF;
}
else if (OMX_AUDIO_AMRFrameFormatIF2 == aAmrParam.eAMRFrameFormat)
{
iOutputFormat = PVMF_MIME_AMR_IF2;
}
else
{
//unsupported format
return OMX_FALSE;
}
if (OMX_AUDIO_AMRBandModeNB0 == aAmrParam.eAMRBandMode)
{
ipEncProps->iMode = ipGsmEncoder->GSM_AMR_4_75;
}
else if (OMX_AUDIO_AMRBandModeNB1 == aAmrParam.eAMRBandMode)
{
ipEncProps->iMode = ipGsmEncoder->GSM_AMR_5_15;
}
else if (OMX_AUDIO_AMRBandModeNB2 == aAmrParam.eAMRBandMode)
{
ipEncProps->iMode = ipGsmEncoder->GSM_AMR_5_90;
}
else if (OMX_AUDIO_AMRBandModeNB3 == aAmrParam.eAMRBandMode)
{
ipEncProps->iMode = ipGsmEncoder->GSM_AMR_6_70;
}
else if (OMX_AUDIO_AMRBandModeNB4 == aAmrParam.eAMRBandMode)
{
ipEncProps->iMode = ipGsmEncoder->GSM_AMR_7_40;
}
else if (OMX_AUDIO_AMRBandModeNB5 == aAmrParam.eAMRBandMode)
{
ipEncProps->iMode = ipGsmEncoder->GSM_AMR_7_95;
}
else if (OMX_AUDIO_AMRBandModeNB6 == aAmrParam.eAMRBandMode)
{
ipEncProps->iMode = ipGsmEncoder->GSM_AMR_10_2;
}
else if (OMX_AUDIO_AMRBandModeNB7 == aAmrParam.eAMRBandMode)
{
ipEncProps->iMode = ipGsmEncoder->GSM_AMR_12_2;
}
else
{
//unsupported mode
return OMX_FALSE;
}
//Adding all the param verification here before allocating them into ipEncProps
if ((16 != aPcmMode.nBitPerSample) ||
(8000 != aPcmMode.nSamplingRate) ||
(1 != aPcmMode.nChannels))
{
return OMX_FALSE;
}
ipEncProps->iInBitsPerSample = aPcmMode.nBitPerSample;
ipEncProps->iInSamplingRate = aPcmMode.nSamplingRate;
ipEncProps->iInClockRate = 1000;
ipEncProps->iInNumChannels = (uint8)aPcmMode.nChannels;
ipEncProps->iInInterleaveMode = TEncodeProperties::EINTERLEAVE_LR;
ipEncProps->iBitStreamFormat = (iOutputFormat == PVMF_MIME_AMR_IF2);
ipEncProps->iAudioObjectType = 0; // only for AAC encoder
ipEncProps->iOutSamplingRate = aPcmMode.nSamplingRate;
ipEncProps->iOutNumChannels = (uint8)aPcmMode.nChannels;
ipEncProps->iOutClockRate = ipEncProps->iInClockRate;
// initialize the amr encoder
MaxOutputBufferSize = iMaxNumOutputFramesPerBuffer * MAX_AMR_FRAME_SIZE;
if (ipGsmEncoder->InitializeEncoder(MaxOutputBufferSize, ipEncProps) < 0)
{
return OMX_FALSE;
}
ipSizeArrayForOutputFrames = (int32*) oscl_malloc(iMaxNumOutputFramesPerBuffer * sizeof(int32));
oscl_memset(ipSizeArrayForOutputFrames, 0, iMaxNumOutputFramesPerBuffer * sizeof(int32));
iOneInputFrameLength = AMR_FRAME_LENGTH_IN_TIMESTAMP * ipEncProps->iInSamplingRate * ipEncProps->iInBitsPerSample / 8000000;
iMaxInputSize = iMaxNumOutputFramesPerBuffer * iOneInputFrameLength;
*aInputFrameLength = iOneInputFrameLength;
*aMaxNumberOutputFrames = iMaxNumOutputFramesPerBuffer;
return OMX_TRUE;
}
/* Decoder De-Initialization function */
void OmxAmrEncoder::AmrEncDeinit()
{
if (ipGsmEncoder)
{
ipGsmEncoder->CleanupEncoder();
OSCL_DELETE(ipGsmEncoder);
ipGsmEncoder = NULL;
}
if (ipEncProps)
{
OSCL_DELETE(ipEncProps);
ipEncProps = NULL;
}
if (ipSizeArrayForOutputFrames)
{
oscl_free(ipSizeArrayForOutputFrames);
ipSizeArrayForOutputFrames = NULL;
}
}
/* Decode function for all the input formats */
OMX_BOOL OmxAmrEncoder::AmrEncodeFrame(OMX_U8* aOutputBuffer,
OMX_U32* aOutputLength,
OMX_U8* aInBuffer,
OMX_U32 aInBufSize,
OMX_TICKS aInTimeStamp,
OMX_TICKS* aOutTimeStamp)
{
TInputAudioStream StreamInput;
TOutputAudioStream StreamOutput;
int32 InputFrameNum;
StreamOutput.iBitStreamBuffer = (uint8*) aOutputBuffer;
StreamOutput.iNumSampleFrames = 0;
StreamOutput.iSampleFrameSize = ipSizeArrayForOutputFrames;
//Calculate the number of input frames to be encoded
InputFrameNum = aInBufSize / iOneInputFrameLength;
StreamInput.iSampleBuffer = (uint8*) aInBuffer;
StreamInput.iSampleLength = (int32) aInBufSize;
StreamInput.iMode = ipEncProps->iMode;
StreamInput.iStartTime = (iNextStartTime >= aInTimeStamp ? iNextStartTime : aInTimeStamp);
StreamInput.iStopTime = StreamInput.iStartTime + AMR_FRAME_LENGTH_IN_TIMESTAMP * InputFrameNum;
iNextStartTime = StreamInput.iStopTime; // for the next encoding
// Do encoding at one time for multiple frame input
if (ipGsmEncoder->Encode(StreamInput, StreamOutput) < 0 || StreamOutput.iNumSampleFrames != InputFrameNum)
{
return OMX_FALSE;
}
// For IETF, make a conversion from WMF
uint8* TmpBuffer = StreamOutput.iBitStreamBuffer;
uint32 ii;
for (ii = 0; ii < (uint32)StreamOutput.iNumSampleFrames; ii++)
{
// for IETF format, we need to make change
if (!ipEncProps->iBitStreamFormat)
{
// non-IF2 => IETF format, not WMF format
TmpBuffer[0] = (uint8)(((TmpBuffer[0] << 3) | 0x4) & 0x7C); // IETF frame header: P(1) + FT(4) + Q(1) + P(2) , Q=1 for good frame, P=padding bit, 0
TmpBuffer += StreamOutput.iSampleFrameSize[ii];
}
// Set fragment length
*aOutputLength += StreamOutput.iSampleFrameSize[ii];
}
*aOutTimeStamp = StreamInput.iStartTime;
return OMX_TRUE;
}