[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