[FFmpeg-devel] [PATCH] MLP/TrueHD decoder
Michael Niedermayer
michaelni
Sat Oct 13 04:03:21 CEST 2007
Hi
On Fri, Oct 12, 2007 at 01:29:46PM +0100, Ian Caulfield wrote:
> Hi all,
>
> I've been working for a while on reverse engineering the MLP audio
> stream format, and writing my own decoder. I've finally got to a point
> where I have something ready for review. I'm going to try to get the
> documentation I've produced on the format up on the multimediawiki as
> well.
>
> I've attached the code as two patches - the first adds a parser, the
> second the actual decoder.
>
> Current caveats:
>
> - The decoder is limited by a #define to a maximum of six channels. I
> imagine that 7.1 streams will be more-or-less a case of changing the
> #defines, but I'd like to see a sample stream first to check.
> - Surround files are output with the channels in codec order (L, R,
> C, LFE, Ls, Rs for 5.1). There was some discussion on the list earlier
> on adding this kind of code to libavcodec instead of individual
> codecs, so I've left out reordering code for now.
> - Funky MLP stuff, like having some channels at 96KHz and some at
> 48KHz isn't supported
> - Blu-Ray TrueHD streams aren't supported. Apparently these consist
> of an AC3 base layer, plus a TrueHD layer with residual data or
> somesuch in. Anyone have any samples?
>
> Extracting a two-channel downmix from a 5.1 stream is supported using
> avctx->request_channels
>
> Comments welcome :)
[...]
> +static inline int mlp_samplerate(int in)
> +{
> + int rate;
> +
> + if (in == 0xF)
> + return 0;
> +
> + if (in & 8)
> + rate = 44100;
> + else
> + rate = 48000;
> +
> + rate <<= in & 7;
> +
> + return rate;
> +}
this doesnt look speed critical, so why is it inline?
[...]
> + if (buf_size < 28) {
> + av_log(log, AV_LOG_ERROR, "Packet too short, unable to read major sync\n");
> + return -1;
> + }
> +
> + if (!crc_init)
> + {
> + av_crc_init(crc_2D, 0, 16, 0x002D, sizeof(crc_2D));
> + crc_init = 1;
> + }
the {} are placed inconsistant
> +
> + crc = av_crc(crc_2D, 0, buf, 24) ^ AV_RL16(buf+24);
> + if (crc != AV_RL16(buf+26))
> + {
> + av_log(log, AV_LOG_ERROR, "Major sync info header CRC error\n");
> + return -1;
> + }
i would rather write
crc = av_crc(crc_2D, 0, buf, 24);
if (crc != (AV_RL16(buf+26) ^ AV_RL16(buf+24)))
> +
> + if (get_bits_long(gbp, 24) != 0xf8726f) /* Sync words */
> + return -1;
> +
> + mh->stream_type = get_bits(gbp, 8);
> + if (mh->stream_type != 0xba && mh->stream_type != 0xbb)
> + return -1;
> +
> + if (mh->stream_type == 0xbb) {
> + mh->group1_bits = mlp_quants[get_bits(gbp, 4)];
> + mh->group2_bits = mlp_quants[get_bits(gbp, 4)];
> +
> + ratebits = get_bits(gbp, 4);
> + mh->group1_samplerate = mlp_samplerate(ratebits);
> + mh->group2_samplerate = mlp_samplerate(get_bits(gbp, 4));
> +
> + skip_bits(gbp, 11);
> +
> + mh->channels_mlp = get_bits(gbp, 5);
> + } else {
> + mh->group1_bits = 24; // TODO: Is this information actually conveyed anywhere?
> + mh->group2_bits = 0;
> +
> + ratebits = get_bits(gbp, 4);
> + mh->group1_samplerate = mlp_samplerate(ratebits);
> + mh->group2_samplerate = 0;
> +
> + skip_bits(gbp, 8);
> +
> + mh->channels_thd_stream1 = get_bits(gbp, 5);
> +
> + skip_bits(gbp, 2);
> +
> + mh->channels_thd_stream2 = get_bits(gbp, 13);
> + }
if bb
else if ba
else return -1
[...]
> +static int mlp_parse(AVCodecParserContext *s,
> + AVCodecContext *avctx,
> + const uint8_t **poutbuf, int *poutbuf_size,
> + const uint8_t *buf, int buf_size)
> +{
> + GetBitContext bits;
> + MLPParseContext *pc = s->priv_data;
> + int bytes_read;
> + int sync_present;
> + uint8_t parity_bits;
> + int i, p, offset = 0;
> +
> + *poutbuf_size = 0;
> +
> +presync:
> + if (!pc->in_sync)
> + {
> + for (i = 0; i < buf_size; i++) {
> + pc->state = (pc->state << 8) | buf[i];
> + if (pc->state == 0xf8726fba || pc->state == 0xf8726fbb)
> + {
> + if (i < 7)
> + {
> + memmove(pc->buf, pc->buf + pc->buf_size - (7 - i), (7 - i));
> + pc->buf_size = 7 - i;
> + } else {
> + pc->buf_size = 0;
> + }
> + memcpy(pc->buf + pc->buf_size, buf + i - 7, 8 - pc->buf_size);
in the i<7 case buf + i - 7 will point outside of the array
also the parser looks messy, maybe using ff_combine_frame() would help?
ill review the decoder patch later
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
There will always be a question for which you do not know the correct awnser.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20071013/d4afea8d/attachment.pgp>
More information about the ffmpeg-devel
mailing list