Encoding and Decoding using MMF based Codec( CMMFCodec )
The MultiMediaFramework(MMF) provides support for software codecs to be used for encoding the audio data to some other codec type and also decoding the encoded audio data. CMMFCodec is the ECom plugin class which provides these services.
The CMMFCodec class processes the source data in a certain coding type( say fourCC code ) and converts it to a destination buffer of another fourCC coding type. The CMMFCodec class can be instantiated by using any one of the following methods:
1. NewL(const TFourCC& aSrcDatatype, const TFourCC& aDstDataType). This instantiate a codec that can convert the aSrcDatatype to a aDstDataType.
2. NewL(const TFourCC& aSrcDatatype, const TFourCC& aDstDataType, const TDesC& aPreferredSupplier). This is similar to the above but is used where there may be multiple codecs that perform the same conversion - the idea is that a 3rd party deveoper may develop there own controller and codecs and can ensure the controller uses their codecs by setting the preferredSupplier to themselves.
3. NewL(TUid aUid). This is used to explicitly instantiated a codec where the uid is known. This might be used by controlers that only support one codec type.
The ConfigureL() API of CMMFCodec may or may not be used based upon the requirement. For example, if we need our AMR encoder to encode the PCM data to AMR mode 7( ie. 32 byte frames ) where as the default AMR mode is 1( which is 14 byte frames ), then ConfigureL() can be used to set the AMR encoding mode by passing the appropriate parameters.( however this applies only for 2nd edition devices ). How to do this for AAC codecs: Configuring AAC codec.
ProcessL() is the API, which does the process of converting the source audio buffer to destination audio buffer according to the codec initialization. As ProcessL() API accepts buffers of any size, the source data may or may not be processed fully at the very first call. So it is our duty to ensure whether the processing is done properly by using the TCodecProcessResult returned by the ProcessL().
Following are the most common TCodecProcessResult return values encountered while using ProcessL() API:
If the return value is EProcessComplete, the source AMR data has been entirely decoded and filled the destination buffer.
If the return value is EProcessIncomplete, the destination buffer is full, but there is still data in the source buffer - call ProcessL() again with the same source buffer, but with a new destination buffer.
If the return value is EDstNotFilled, this indicates that the source buffer has been emptied as much as possible but the destination buffer was not filled. In the case of AMR, the codec will return this if we have submitted half a 20ms frame to be decoded. There will still be data in the source buffer...append new source data onto the end and do another ProcessL() with the same destination buffer.
If the return value is EProcessError, there is probably an error due to corrupted data.
Here is the code snippet for using CMMFCodec for encoding and decoding AMR frames.
// Uid of PCM16toAMR codec is 0x101FAF68
CMMFCodec* encoder = CMMFCodec::NewL(TUid::Uid(0x101FAF68));
// Source buffer to be passed to CMMFCodec
CMMFDescriptorBuffer* srcbuf = CMMFDescriptorBuffer::NewL(320);
// Copy your PCM frame data into srcbuf, like
// The Destination buffer must be filled after codec processing.
// Note that for proper processing, the size of this buffer should be altered
// according to the AMR mode( frame size ) used in the device.
CMMFDescriptorBuffer* dstbuf = CMMFDescriptorBuffer::NewL(32);
// actual codec processing is done here
TCodecProcessResult result = encoder->ProcessL(*srcbuf, *dstbuf):
// now the dstbuf will contain the encoded AMR frame data from the srcbuf.
If we need to convert AMR frame data to PCM16, the UID to be used for CMMFCodec instantiation should be changed to 0x101FAF67 and the source bufer should contain AMR data where as the decoded PCM data will be obtained from destination buffer passed to ProcessL().