Format encode plugin implementations derive from the CMMFFormatEncode
abstract class and several of the MDataSource
and MDataSink
mixin functions.
Derived classes must implement the CMMFFormatEncode
pure virtual functions
and may implement any of the virtual functions.
A derived plugin need only implement the following instantiation method:
static CMMFFormatEncode* NewL(MDataSource* aSource)
;
Note that a client using a format plugin would always instantiate a specific
CMMFFormatEncode
by using one of the four base class NewL()
instantiation functions. It would not instantiate the format encode plugin via the derived class
directly.
The derived NewL()
function will first need to determine whether
or not the sink clip already exists. This is because a CMMFFormatEncode
would typically
be used for a recording or converting operation, where the clip being recorded or converted to may or
may not already exist. The expected behaviour for each of the two alternatives is as follows:
If the sink clip does not already exist, the format encode should set any internal
variables such as frame size and start position to appropriate default values and write any dummy header
information where applicable. Apart from basic initialisation, there is not much more the
NewL()
method can do if the clip does not exist. It is at the discretion of the format
encode plugin writer whether to provide default values for media related parameters such as sample rate,
frame per second, data type etc or whether the user of the format needs to always set these explicitly.
In general, the media-specific type parameter will have to be explicitly set on the format.
There may be exceptions to this, for example an mp3
format will always have a data type
of mp3
.
If the sink clip does already exist, the format
plugin is expected to parse the format by reading the appropriate data from the supplied source in
order to set all its internal settings for the format. Examples of this might be, for a typical
audio format, the sample rate, stereo/ mono, the data type etc. The derived NewL()
function should also determine the data type where possible so that the
CMMFFormatEncode::SinkDataTypeCode()
method can return the correct fourCC code.
The NewL()
function is also responsible for determining if the source is of the
instantiated format. For example, if a derived NewL()
function is called in response to
instantiating a CMMFFormatEncode
using a file with an .mp3
extension, and the file is not a valid mp3
file, then the NewL()
function
should leave with KErrCorrupt
.
The
ECom
TImplementationProxy
table,
which defines the NewL()
for a specific format plugin UID, needs defining in a .
cpp
file.
The CMMFFormatEncode
base class contains a number of audio-specific functions.
Default implementations are provided so there is no need to override these if the format only
supports video:
If the format supports audio then, unlike the CMMFFormatDecode
equivalents, it will usually be necessary to override the CMMFFormatEncode::SetNumChannels()
, CMMFFormatEncode::SetSampleRate()
and CMMFFormatEncode::SetBitRate()
methods. This is because, if the clip does not already exist, the format will need to be supplied with these settings. If
the clip does already exist and can determine the settings for itself then these functions should return KErrAlreadyExists
if the requested setting differs from the actual setting.
Other CMMFFormatEncode
functions that need to be implemented by a format encode plugin are: CMMFFormatEncode::FrameTimeInterval()
, CMMFFormatEncode::Duration()
, CMMFFormatEncode:: CanCreateSinkBuffer()
and CMMFFormatEncode:: CreateSinkBufferL ()
.
In addition: CMMFFormatEncode::GetNumberOfMetaDataEntriesL()
, CMMFFormatEncode::AddMetaDataEntryL()
, CMMFFormatEncode::RemoveMetaDataEntryL()
, CMMFFormatEncode::ReplaceMetaDataEntryL()
and CMMFFormatEncode::MetaDataEntryL()
may optionally be implemented.
CMMFFormatEncode::SetMaximumClipSizeL()
is an optional method used to set the maximum size of the clip. For example, to set a limit on the length of a recording.
If implemented, then the CMMFFormatEncode::EmptyBufferL()
method should check that the value set by this procedure is not about to be exceeded and if so should leave with KErrEof
.
CMMFFormatEncode::CropL()
is an optional method used to remove part of a clip. The clip can be cropped from a specified position (the default behaviour)
where all the clip data from tat position is removed from the clip. Alternatively the format can crop all the data up to a
specified position. There may also be restrictions on what state the format is in as to whether the crop operation is permissible,
for example the format may need to be paused to crop, but this is up to the specific implementation of this function. Writers
of this function must ensure that the clip header, index tables and any other necessary data both on the clip and internally
in the format are correct following the crop operation.
The CMMFFormatEncode::SinkDataTypeCode()
function must be implemented by the derived format encode plugin. It should return the data type via a four CC code of the
sink for the specified media ID. The data type can be determined on instantiation or in the implementation of this function.
The data type for a particular format is usually determined by information in the header, although some formats can only have
one data type e.g. for the mp3
format, the data type is always mp3
. For a WAV
file the data type could be pcm8
, pcm16
, IMA
ADPCM
or GSM610
. If no data type is applicable to the specified media ID, for example if this function was called on an mp3
format plugin with the media ID set to KUidMediaTypeVideo
then the procedure should return the default TFourCC code of 'NULL
'.
Format encode MDataSource
and MDataSink
implementation is described in the following sections:
A CMMFFormatEncode
derived plugin is a sink of data (usually from a datapath).
It therefore derives from the MDataSink
mixin class. The
MDataSink
mixin method concerned with getting data from the format encode plugin
is MDataSink::EmptyBufferL()
.
This method is the means by which data is
written to the data source. The buffer must already contain multimedia data. The format should read the
frame number of the buffer via the buffer's CMMFBufferClass::FrameNumber()
method.
From this, the format encode plugin should be able to determine the actual position of the data on the
data source. The technique here depends on the nature of the format. For a linear audio format, the
position can be obtained by a simple calculation of the frame size, the header size and where appropriate
the datatype. For non linear formats either an index table of frame number and location will need to be
created in the derived NewL()
or some form of approximating algorithm will be required.
Some formats have an index table as part of the format, AVI
for example. If no random access is
required then no index table is required, the format can keep track of the current write position and
increment it on each access, and reset it if the frame number is reset to 0 or 1.
For multimedia formats such as mp4
and AVI
, the format encode is effectively
acting as a multiplexer, and must write the data to the appropriate location on the sink depending on the
media ID. If a maximum clip size has been set via the MDataSink::SetMaximumClipSizeL()
method then the MDataSink::EmptyBufferL()
should ensure that this size is not
exceeded.
MDataSink::BufferEmptiedL()
function is the
MDataSource
call back method of the MDataSink::EmptyBufferL()
called on the sink (the format encode plugin being the source to the data sink) is optional.
The default implementation propagates the callback onto the datapath. If any format specific post
buffer emptied processing is required, such as updating the bytes written, then this function should
be overridden.
The MDataSink
mixin provides a number of state related functions used to
inform a source that the datapath has made a transition to a particular state. These state transition
functions are usually called on the sink from the datapath and so will be called on the
CMMFFormatEncode
plugin. These methods are not pure virtual and so it is not
compulsory to implement them on the format encode plugin (they have no default implementation in the
CMMFFormatEncode
base class).
In many cases it will be necessary to override these functions even if only to propagate the state
change
onto the actual sink as seen by the controller.
In addition, the functions
MDataSink::SinkPlayL()
, MDataSink::SinkPauseL()
,
MDataSink::SinkStopL()
and MDataSink::SinkThreadLogoff()
would not generally have any format encode-specific implementations.
The
CMMFFormatEncode
state methods may be more complex than those of the
CMMFFormatDecode
equivalents. The main reason for this is that the format
encode needs to ensure that the sink clip is valid i.e. has the correct header information.
This should happen every time a MDataSink::SinkPauseL()
(since there is no
guarantee that it will be resumed) and MDataSink::SinkStopL()
is called.
This means that the format encode will need to keep track of any parameters required to write the
header such as clip size, bytes written and so on.
The MDataSink::SetSinkDataTypeCode()
function is not pure virtual in the
base class, and no default implementation is given in the CMMFFormatEncode
base class.
However, unlike a CMMFFormatDecode
, it would normally be necessary to override
this method. This is because the CMMFFormatEncode
is typically used when recording or
converting, such that the clip may or may not already exist prior to the recording or conversion.
If the clip does not already exist then the format needs to know what the expected data type is, and
this is set by the MDataSink::SetSinkDataTypeCode()
method. If the clip does already exist, and so has a data type that is different to the requested data type, then this method
should return KErrAlreadyExists
.
No implementation of the
MDataSink::BufferFilledL()
or MDataSource::FillBufferL()
functions are required in the derived plugin.