[FFmpeg-devel] LPCM for mpeg-ts, the second

Jai Menon jmenon86
Sun Aug 2 10:22:09 CEST 2009


On Sun, Aug 2, 2009 at 7:54 AM, Christian P. Schmidt<schmidt at digadd.de> wrote:
> Hi all,
>
> Attached a second attempt at adding the support for LPCM streams in mpeg transport streams.
>
> After some discussions it's made into a separate file which might at some time also host the code for LPCM in DVDs, removing the
> decoding of the header from the mpeg demuxer and putting it in the codec.
>
> It is only tested with the following formats:
> - 2 channels, 16 bits, 48kHz (my original sample)
> - 6 channels, 24 bits, 48kHz (played cropped to stereo on my laptop, thanks to Baptiste for providing the sample)
> - 8 channels, 16 bits, 48kHz (it is recognized, but ffplay can't play back because SDL rejects 8 channels)
>
> The following limitations exist:
> - Also decodes 16bit to 32bit as the codec apparently can't influence the sample format, and the first packet needs to be decoded
> before we know how many bits are stored (at least ffplay didn't make any sense out of anything else)
> - 20 bits is not implemented as I don't have a sample or the specs
> - channel mapping might be wrong - actually I don't know how to tell the core about it
>
> Pointers for any of the above are appreciated.
>
> BTW, I'm pretty sure the 20/24bit code in pcm_dvd isn't working. It seems to me that it tries to read twice the existing number of
> channels.
>
> When I'm back home to my DVD collection in about a month I'll check out if I have any 20/24 bit PCM DVDs in there - in the mean
> time, samples are appreciated.

If you do find any, please upload to samples.mphq

[...]

> +/**
> + * @file libavcodec/pcm-mpeg.c
> + * PCM codecs for encodings found in mpeg streams (dvd/bluray)
> + */
> +
> +#include "avcodec.h"
> +#include "get_bits.h" // for ff_reverse
> +#include "bytestream.h"
> +
> +#define MAX_CHANNELS 64
> +
> +typedef struct PCMDecode {
> + ? ?short table[256];
> +} PCMDecode;
> +
> +static av_cold int pcm_mpeg_decode_init(AVCodecContext * avctx)
> +{
> + ? ?av_log(avctx, AV_LOG_DEBUG, "pcm_mpeg_decode_init\n");
> +
> + ? ?avctx->sample_fmt = SAMPLE_FMT_S32; ///< Will be determined from the header
> + ? ?return 0;
> +}
> +
> +/*
> + * Channel Mapping ?according to http://forum.doom9.org/showthread.php?p=968627#post968627

Is there any spec which could be cited instead? Just asking...

[...]

> +static int pcm_mpeg_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;
> +
> + ? ?int32_t *dst = data;
> +
> + ? ?if (buf_size < 4) {
> + ? ? ? ? ?av_log(avctx, AV_LOG_ERROR, "PCM packet too small\n");
> + ? ? ? ? ?return -1;
> + ? ?}
> +
> + ? ?if (0 == avctx->channels) {
> + ? ? ? ?switch(avctx->codec->id) {
> + ? ? ? ?case CODEC_ID_PCM_BLURAY:
> + ? ? ? ? ? ?if (pcm_bluray_init (avctx, src[2], src[3]))

Since you use src[2], src[3] etc for array lookups, isnt passing these
on directly without sanity checking here or in the init function kinda
fragile..

> + ? ? ? ? ? ? ? ?return -1;
> + ? ? ? ? ? ?break;
> + ? ? ? ?default:
> + ? ? ? ? ?return -1;
> + ? ? ? ?}
> + ? ?}
> +
> + ? ?/* eat header */
> + ? ?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;
> + ? ?num_samples = buf_size / sample_size;
> +
> + ? ?av_log(avctx, AV_LOG_DEBUG, "dec: c: %d sc: %d s: %d in: %d\n",
> + ? ? ? ? ? avctx->channels, num_source_channels, num_samples, buf_size);
> +
> + ? ?if (num_source_channels == avctx->channels) {
> + ? ? ? ?switch (avctx->bits_per_coded_sample) {
> + ? ? ? ?case 16:
> + ? ? ? ? ? ?for (sample = num_samples*avctx->channels; sample; sample--)
> + ? ? ? ? ? ? ? ?*dst++ = bytestream_get_be16(&src) << 16;

bytestream_get_buffer perhaps ?

[...]

-- 
Regards,

Jai



More information about the ffmpeg-devel mailing list