/* This function creates a magic cookie basec on the codec parameter and formatID * Return value: a pointer to a magic cookie which has to be av_free()'d * in cookieSize, the size of the magic cookie is returned to the caller */ uint8_t *create_cookie(AVCodecContext *codec, size_t *cookieSize, UInt32 formatID, int vbr) { uint8_t *waveAtom = NULL; PutByteContext p; int waveSize; if (formatID == kAudioFormatMPEG4AAC) { return CreateEsdsFromSetupData(codec->extradata, codec->extradata_size, cookieSize, 1, true, false); } /* Do we need an endia atom, too? */ /* initialize the user Atom * 8 bytes for the atom size & atom type * 18 bytes for the already extracted part, see wav.c in the ffmpeg project * extradata_size for the data still stored in the AVCodecContext structure */ waveSize = 18 + codec->extradata_size + 8; waveAtom = av_malloc(waveSize); if (!waveAtom) goto bail; bytestream2_init_writer(&p, waveAtom, waveSize); /* now construct the wave atom */ /* QT Atoms are big endian, I think but the WAVE data should be little endian */ bytestream2_put_be32(&p, waveSize); bytestream2_put_be32(&p, formatID); bytestream2_put_le32(&p, codec->codec_tag); bytestream2_put_le32(&p, codec->channels); bytestream2_put_le32(&p, codec->sample_rate); bytestream2_put_le32(&p, vbr ? 0 : codec->bit_rate / 8); bytestream2_put_le16(&p, codec->block_align); bytestream2_put_le16(&p, codec->bits_per_coded_sample); bytestream2_put_le16(&p, codec->extradata_size); /* now the remaining stuff */ bytestream2_put_buffer(&p, codec->extradata, codec->extradata_size); bail: *cookieSize = waveSize; return waveAtom; } /* create_cookie() */
static uint8_t* ffat_get_magic_cookie(AVCodecContext *avctx, UInt32 *cookie_size) { ATDecodeContext *at = avctx->priv_data; if (avctx->codec_id == AV_CODEC_ID_AAC) { char *extradata; PutByteContext pb; *cookie_size = 5 + 3 + 5+13 + 5+at->extradata_size; if (!(extradata = av_malloc(*cookie_size))) return NULL; bytestream2_init_writer(&pb, extradata, *cookie_size); // ES descriptor put_descr(&pb, 0x03, 3 + 5+13 + 5+at->extradata_size); bytestream2_put_be16(&pb, 0); bytestream2_put_byte(&pb, 0x00); // flags (= no flags) // DecoderConfig descriptor put_descr(&pb, 0x04, 13 + 5+at->extradata_size); // Object type indication bytestream2_put_byte(&pb, 0x40); bytestream2_put_byte(&pb, 0x15); // flags (= Audiostream) bytestream2_put_be24(&pb, 0); // Buffersize DB bytestream2_put_be32(&pb, 0); // maxbitrate bytestream2_put_be32(&pb, 0); // avgbitrate // DecoderSpecific info descriptor put_descr(&pb, 0x05, at->extradata_size); bytestream2_put_buffer(&pb, at->extradata, at->extradata_size); return extradata; } else { *cookie_size = at->extradata_size; return at->extradata; } }
/* This function creates an image description extension that some codecs need to be able * to decode properly, a copy of the strf (BITMAPINFOHEADER) chunk in the avi. * Return value: a handle to an image description extension which has to be DisposeHandle()'d * in cookieSize, the size of the image description extension is returned to the caller */ Handle create_strf_ext(AVCodecContext *codec) { Handle result = NULL; PutByteContext p; int size; /* initialize the extension * 40 bytes for the BITMAPINFOHEADER stucture, see avienc.c in the ffmpeg project * extradata_size for the data still stored in the AVCodecContext structure */ size = 40 + codec->extradata_size; result = NewHandle(size); if (result == NULL) goto bail; bytestream2_init_writer(&p, (uint8_t*)*result, size); /* construct the BITMAPINFOHEADER structure */ /* QT Atoms are big endian, but the STRF atom should be little endian */ bytestream2_put_be32(&p, size); bytestream2_put_le32(&p, codec->width); bytestream2_put_le32(&p, codec->width); bytestream2_put_le16(&p, 1); // planes bytestream2_put_le16(&p, codec->bits_per_coded_sample ?: 24); /* compression type */ bytestream2_put_le32(&p, codec->codec_tag); bytestream2_put_le32(&p, codec->width * codec->height * 3); bytestream2_put_le32(&p, 0); bytestream2_put_le32(&p, 0); bytestream2_put_le32(&p, 0); bytestream2_put_le32(&p, 0); /* now the remaining stuff */ bytestream2_put_buffer(&p, codec->extradata, codec->extradata_size); if (codec->extradata_size & 1) { bytestream2_put_byte(&p, 0); } bail: return result; } /* create_extension() */