Hi all,
I'm writing a core audio decoders wrapper plugin for GStreamer. This
involves allowing to use the existing QT decoders within a GStreamer
pipeline.
I currently have it working with mp3 and somewhat with QDM2, but
it's failing miserably with AAC.
The first time I call AudioConverterFillComplexBuffer() it returns
'!pkd' (kAudioConverterErr_RequiresPacketDescriptionsError). The
problem is that I am giving that function a table of
AudioStreamPacketDescription, so I can't figure out what's wrong here.
I have been looking for documentation on what that error really means
(apart from the obvious "you haven't given a packet description) but
couldn't find any documentation whatsoever.
Below follows the relevant part of my plugin so you can see how I'm
using AudioConverter.
Since this is a GStreamer plugin, we get the data (in this case AAC
packets) without having any knowledge of where it comes from, so
there's no way to use the QuickTime API that requires giving a file.
This reduces drastically the number of examples I can base myself on
(well ... basically no examples).
I would appreciate any hints as to why ACFCB would return that error
code, or any hints on what would be wrong in that code.
Thanks in advance
static void
clear_AudioStreamBasicDescription (AudioStreamBasicDescription * desc)
{
desc->mSampleRate = 0;
desc->mFormatID = 0;
desc->mFormatFlags = 0;
desc->mBytesPerPacket = 0;
desc->mFramesPerPacket = 0;
desc->mBytesPerFrame = 0;
desc->mChannelsPerFrame = 0;
desc->mBitsPerChannel = 0;
}
static void
fill_indesc_aac (MacOSXAudioDecoder * macosx, guint32 fourcc, gint
rate,
gint channels)
{
clear_AudioStreamBasicDescription (&macosx->indesc);
/* aac always has 1024 bytes per packet */
macosx->indesc.mFormatID = kAudioFormatMPEG4AAC;
macosx->indesc.mBytesPerPacket = 1024;
}
static gboolean
open_decoder (MacOSXAudioDecoder * macosx, GstCaps * caps, GstCaps
** othercaps)
{
switch (oclass->componentSubType) {
case QT_MAKE_FOURCC_LE ('.', 'm', 'p', '3'):
fill_indesc_mp3 (macosx, oclass->componentSubType, rate,
channels);
break;
case QT_MAKE_FOURCC_LE ('m', 'p', '4', 'a'):
fill_indesc_aac (macosx, oclass->componentSubType, rate,
channels);
break;
default:
fill_indesc_generic (macosx, oclass->componentSubType, rate,
channels);
break;
}
macosx->samplerate = rate;
/* Setup the output format description */
macosx->outdesc.mSampleRate = rate;
macosx->outdesc.mFormatID = kAudioFormatLinearPCM;
macosx->outdesc.mFormatFlags = kAudioFormatFlagIsFloat;
#if G_BYTE_ORDER == G_BIG_ENDIAN
macosx->outdesc.mFormatFlags |= kAudioFormatFlagIsBigEndian;
#endif
macosx->outdesc.mBytesPerPacket = channels * 4;
macosx->outdesc.mFramesPerPacket = 1;
macosx->outdesc.mBytesPerFrame = channels * 4; /* channels *
bytes-per-samples */
macosx->outdesc.mChannelsPerFrame = channels;
macosx->outdesc.mBitsPerChannel = 32;
/* Create an AudioConverter */
status = AudioConverterNew (&macosx->indesc,
&macosx->outdesc, &macosx->aconv);
if (status != noErr) {
GST_WARNING_OBJECT (macosx,
"Error when calling AudioConverterNew() : %" GST_FOURCC_FORMAT,
QT_FOURCC_ARGS (status));
goto beach;
}
/* if we have codec_data, give it to the converter ! */
if (codec_data) {
oserr = AudioConverterSetProperty (macosx->aconv,
kAudioConverterDecompressionMagicCookie,
GST_BUFFER_SIZE (codec_data), GST_BUFFER_DATA (codec_data));
if (oserr != noErr) {
GST_WARNING_OBJECT (macosx, "Error setting extra codec data !");
goto beach;
}
}
/* Create output bufferlist */
macosx->bufferlist =
(AudioBufferList *) calloc (1,
sizeof (AudioBufferList) + channels * sizeof (AudioBuffer));
macosx->bufferlist->mNumberBuffers = 1;
macosx->bufferlist->mBuffers[0].mNumberChannels = channels;
for (i = channels; i; i--) {
/* 50 ms */
macosx->bufferlist->mBuffers[i-1].mDataByteSize = rate *
channels * 4 / 20;
macosx->bufferlist->mBuffers[i-1].mData =
g_malloc0 (rate * channels * 4 / 20);
}
}
static OSStatus
process_buffer_cb (AudioConverterRef inAudioConverter,
UInt32 * ioNumberDataPackets,
AudioBufferList * ioData,
AudioStreamPacketDescription ** outDataPacketDescription,
MacOSXAudioDecoder * macosx)
{
gint len;
GST_LOG_OBJECT (macosx,
"ioNumberDataPackets:%lu, iodata:%p, *outDataPacketDescription:
%p",
*ioNumberDataPackets, ioData, *outDataPacketDescription);
ioData->mBuffers[0].mData = NULL;
ioData->mBuffers[0].mDataByteSize = 0;
if (macosx->prevdata)
g_free (macosx->prevdata);
len = gst_adapter_available (macosx->adapter);
if (len) {
ioData->mBuffers[0].mData = gst_adapter_take (macosx->adapter,
len);
macosx->prevdata = ioData->mBuffers[0].mData;
} else {
macosx->prevdata = NULL;
}
ioData->mBuffers[0].mDataByteSize = len;
*outDataPacketDescription = NULL;
GST_LOG_OBJECT (macosx, "returning %d bytes at %p",
len, ioData->mBuffers[0].mData);
if (!len)
return 42;
return noErr;
}
chain() {
while (gst_adapter_available (macosx->adapter) > 128) {
GstBuffer *outbuf;
OSErr oserr;
OSStatus status;
guint32 outsamples = macosx->bufferlist->mBuffers
[0].mDataByteSize / 8;
guint32 savedbytes = macosx->bufferlist->mBuffers[0].mDataByteSize;
guint32 realbytes;
AudioStreamPacketDescription *aspd;
GST_LOG_OBJECT (macosx, "Calling FillBuffer(outsamples:%d ,
outdata:%p)",
outsamples, macosx->bufferlist->mBuffers[0].mData);
aspd = g_new0 (AudioStreamPacketDescription, outsamples);
/* Ask AudioConverter to give us data ! */
status = AudioConverterFillComplexBuffer (macosx->aconv,
(AudioConverterComplexInputDataProc) process_buffer_cb,
macosx, &outsamples, macosx->bufferlist, aspd);
g_free (aspd);
if ((status != noErr) && (status != 42)) {
if (status < 0)
GST_WARNING_OBJECT (macosx,
"Error in AudioConverterFillComplexBuffer() : %d", status);
else
GST_WARNING_OBJECT (macosx,
"Error in AudioConverterFillComplexBuffer() : %"
GST_FOURCC_FORMAT,
QT_FOURCC_ARGS (status));
ret = GST_FLOW_ERROR;
goto beach;
}
realbytes = macosx->bufferlist->mBuffers[0].mDataByteSize;
GST_LOG_OBJECT (macosx, "We now have %d samples [%d bytes]",
outsamples, realbytes);
macosx->bufferlist->mBuffers[0].mDataByteSize = savedbytes;
if (!outsamples)
break;
/* 4. Create buffer and copy data in it */
ret = gst_pad_alloc_buffer (macosx->srcpad, macosx->cur_offset,
realbytes, GST_PAD_CAPS (macosx->srcpad), &outbuf);
if (ret != GST_FLOW_OK)
goto beach;
/* copy data from bufferlist to output buffer */
g_memmove (GST_BUFFER_DATA (outbuf),
macosx->bufferlist->mBuffers[0].mData, realbytes);
}
--
Edward Hervey
Multimedia editing developer / Fluendo S.A.
http://www.pitivi.org/
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden