[FFmpeg-devel] [PATCH] LPCM in MPEG-TS, next iteration

Benjamin Larsson banan
Fri Aug 14 15:48:53 CEST 2009


Christian P. Schmidt wrote:
> Hello everyone,
>
> Attached is thenext iteration for the LPCM in MPEG-TS patch. The channel
> mapping is correct now, thanks to merbanan and superdump on IRC for
> explaining me how it works internally.
>
> The actual remapping code might not be optimal in every environment, but
> it's a working starting point.
>
> Regards,
> Christian
>   
> ------------------------------------------------------------------------
> [...]
>      /* various ADPCM codecs */
>      CODEC_ID_ADPCM_IMA_QT= 0x11000,
> @@ -394,6 +395,7 @@
>  #define CH_LAYOUT_5POINT1           (CH_LAYOUT_5POINT0|CH_LOW_FREQUENCY)
>  #define CH_LAYOUT_5POINT0_BACK      (CH_LAYOUT_SURROUND|CH_BACK_LEFT|CH_BACK_RIGHT)
>  #define CH_LAYOUT_5POINT1_BACK      (CH_LAYOUT_5POINT0_BACK|CH_LOW_FREQUENCY)
> +#define CH_LAYOUT_7POINT0           (CH_LAYOUT_5POINT0|CH_BACK_LEFT|CH_BACK_RIGHT)
>  #define CH_LAYOUT_7POINT1           (CH_LAYOUT_5POINT1|CH_BACK_LEFT|CH_BACK_RIGHT)
>  #define CH_LAYOUT_7POINT1_WIDE      (CH_LAYOUT_5POINT1_BACK|\
>                                            CH_FRONT_LEFT_OF_CENTER|CH_FRONT_RIGHT_OF_CENTER)
>   

This hunk could be committed right away.
[...]
> +static int pcm_bluray_decode_frame(AVCodecContext *avctx,
> +                                   void *data, int *data_size,
> +                                   AVPacket *avpkt)
> +{
> +    const uint8_t *src = avpkt->data;
> +    int buf_size = avpkt->size;
> +    int num_source_channels, channel, retval;
> +    int sample_size, num_samples, sample;
> +    int16_t *dst16 = data;
> +    int32_t *dst32 = data;
> +
> +    if(buf_size < 4) {
> +        av_log(avctx, AV_LOG_ERROR, "PCM packet too small\n");
> +        return -1;
> +    }
> +
> +    if(pcm_bluray_parse_header (avctx, src))
> +        return -1;
> +    src += 4;
> +    buf_size -= 4;
> +
> +    /* There's always an even number of channels in the source */
> +    num_source_channels = (avctx->channels & 1) ? avctx->channels + 1 :
> +                                                  avctx->channels;
> +
> +    /* Order of calculation matters: early division by 8 kills the fraction for 20bit samples */
> +    sample_size = (num_source_channels * avctx->bits_per_coded_sample) / 8;
>   

use shift instead

> +    num_samples = buf_size / sample_size;
> +
> +    dprintf(avctx, "pcm_bluray_decode_frame: c: %d sc: %d s: %d in: %d ds: %d\n",
> +            avctx->channels, num_source_channels, num_samples, buf_size,
> +            *data_size);
> +
> +    switch(avctx->channel_layout) {
> +    case CH_LAYOUT_STEREO:  ///< same number of source and coded channels
> +    case CH_LAYOUT_4POINT0:
> +    case CH_LAYOUT_2_2:
> +        if(16 == avctx->bits_per_coded_sample) {
>   

I'd prefer if(avctx->bits_per_coded_sample == 16) but that's just me
> +#if HAVE_BIGENDIAN
> +            memcpy(dst16, src, 2*num_samples*num_source_channels);
> +#else
> +            for(sample = num_samples*avctx->channels; sample; sample--)
> +                *dst16++ = bytestream_get_be16(&src);
> +#endif
> +        } else {
> +            for(sample = num_samples*avctx->channels; sample; sample--)
> +                *dst32++ = bytestream_get_be24(&src) << 8;
> +        }
> +        break;
> +    case CH_LAYOUT_MONO:    ///< number of source channels = coded channels +1
> +    case CH_LAYOUT_SURROUND:
> +    case CH_LAYOUT_2_1:
> +    case CH_LAYOUT_5POINT0:
> +        if(16 == avctx->bits_per_coded_sample) {
>   

same and there are more

> +            sample_size = avctx->channels * 2;
> +            for (sample = num_samples; sample; sample--) {
> +#if HAVE_BIGENDIAN
> +                memcpy(dst16, src, sample_size);
> +                dst16 += avctx->channels;
> +#else
> +                for(channel = avctx->channels; channel; channel--)
> +                    *dst16++ = bytestream_get_be16(&src);
> +#endif
> +                src += 2;
> +            }
> +        } else {
> +            for(sample = num_samples*avctx->channels; sample; sample--) {
> +                for(channel = avctx->channels; channel; channel--)
> +                    *dst32++ = bytestream_get_be24(&src) << 8;
> +                src += 3;
> +            }
> +        }
> +        break;
> +    case CH_LAYOUT_5POINT1: ///< remapping: L, R, C, LBack, RBack, LF
> +        if(16 == avctx->bits_per_coded_sample) {
> +            for(sample = num_samples; sample; sample--) {
> +                dst16[0] = bytestream_get_be16(&src);
> +                dst16[1] = bytestream_get_be16(&src);
> +                dst16[2] = bytestream_get_be16(&src);
> +                dst16[4] = bytestream_get_be16(&src);
> +                dst16[5] = bytestream_get_be16(&src);
> +                dst16[3] = bytestream_get_be16(&src);
> +                dst16 += 6;
> +            }
> +        } else {
> +            for(sample = num_samples; sample; sample--) {
> +                dst32[0] = bytestream_get_be24(&src) << 8;
> +                dst32[1] = bytestream_get_be24(&src) << 8;
> +                dst32[2] = bytestream_get_be24(&src) << 8;
> +                dst32[4] = bytestream_get_be24(&src) << 8;
> +                dst32[5] = bytestream_get_be24(&src) << 8;
> +                dst32[3] = bytestream_get_be24(&src) << 8;
> +                dst32 += 6;
> +            }
> +        }
> +        break;
> +    case CH_LAYOUT_7POINT0: ///< remapping: L, R, C, LSide, LBack, RBack, RSide, <unused>
> +        if(16 == avctx->bits_per_coded_sample) {
> +            for(sample = num_samples; sample; sample--) {
> +                dst16[0] = bytestream_get_be16(&src);
> +                dst16[1] = bytestream_get_be16(&src);
> +                dst16[2] = bytestream_get_be16(&src);
> +                dst16[5] = bytestream_get_be16(&src);
> +                dst16[3] = bytestream_get_be16(&src);
> +                dst16[4] = bytestream_get_be16(&src);
> +                dst16[6] = bytestream_get_be16(&src);
> +                dst16 += 7;
> +                src += 2;
> +            }
> +        } else {
> +            for(sample = num_samples; sample; sample--) {
> +                dst32[0] = bytestream_get_be24(&src) << 8;
> +                dst32[1] = bytestream_get_be24(&src) << 8;
> +                dst32[2] = bytestream_get_be24(&src) << 8;
> +                dst32[5] = bytestream_get_be24(&src) << 8;
> +                dst32[3] = bytestream_get_be24(&src) << 8;
> +                dst32[4] = bytestream_get_be24(&src) << 8;
> +                dst32[6] = bytestream_get_be24(&src) << 8;
> +                dst32 += 7;
> +                src += 3;
> +            }
> +        }
> +        break;
> +    case CH_LAYOUT_7POINT1: ///< remapping: L, R, C, LSide, LBack, RBack, RSide, LF
> +        if(16 == avctx->bits_per_coded_sample) {
> +            for(sample = num_samples; sample; sample--) {
> +                dst16[0] = bytestream_get_be16(&src);
> +                dst16[1] = bytestream_get_be16(&src);
> +                dst16[2] = bytestream_get_be16(&src);
> +                dst16[6] = bytestream_get_be16(&src);
> +                dst16[4] = bytestream_get_be16(&src);
> +                dst16[5] = bytestream_get_be16(&src);
> +                dst16[7] = bytestream_get_be16(&src);
> +                dst16[3] = bytestream_get_be16(&src);
> +                dst16 += 8;
> +            }
> +        } else {
> +            for(sample = num_samples; sample; sample--) {
> +                dst32[0] = bytestream_get_be24(&src) << 8;
> +                dst32[1] = bytestream_get_be24(&src) << 8;
> +                dst32[2] = bytestream_get_be24(&src) << 8;
> +                dst32[6] = bytestream_get_be24(&src) << 8;
> +                dst32[4] = bytestream_get_be24(&src) << 8;
> +                dst32[5] = bytestream_get_be24(&src) << 8;
> +                dst32[7] = bytestream_get_be24(&src) << 8;
> +                dst32[3] = bytestream_get_be24(&src) << 8;
> +                dst32 += 8;
> +            }
> +        }
> +        break;
> +    }
> +
> +    if(16 == avctx->bits_per_coded_sample)
> +        *data_size = 2*num_samples*avctx->channels;
> +    else
> +        *data_size = 4*num_samples*avctx->channels;
>   

IIRC the 2 and 4 shouldn't be constants. sizeof(int16||int32) or 
something else.


> +    retval = src - avpkt->data;
> +    dprintf(avctx, "pcm_bluray_decode_frame: decoded %d -> %d bytes\n",
> +            retval, *data_size);
> +    return retval;
> +}
> +
> +AVCodec pcm_bluray_decoder = {
> +    "pcm_bluray",
> +    CODEC_TYPE_AUDIO,
> +    CODEC_ID_PCM_BLURAY,
> +    0,
> +    pcm_bluray_decode_init,
> +    NULL,
> +    NULL,
> +    pcm_bluray_decode_frame,
> +    .sample_fmts = (enum SampleFormat[]){SAMPLE_FMT_S16, SAMPLE_FMT_S32,
> +                                         SAMPLE_FMT_NONE},
> +    .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian"),
>   

Should be a "bluray" somewhere in the long name.

> +};
> diff -urN ffmpeg.old/trunk/libavformat/mpegts.c ffmpeg/trunk/libavformat/mpegts.c
> --- ffmpeg.old/trunk/libavformat/mpegts.c	2009-08-02 19:43:32.691876261 +0300
> +++ ffmpeg/trunk/libavformat/mpegts.c	2009-08-14 15:26:27.371908511 +0300
> @@ -504,6 +504,7 @@
>  };
>  
>  static const StreamType HDMV_types[] = {
> +    { 0x80, CODEC_TYPE_AUDIO, CODEC_ID_PCM_BLURAY },
>      { 0x81, CODEC_TYPE_AUDIO, CODEC_ID_AC3 },
>      { 0x82, CODEC_TYPE_AUDIO, CODEC_ID_DTS },
>      { 0 },
>   

MvH
Benjamin Larsson





More information about the ffmpeg-devel mailing list