[FFmpeg-devel] [RFC]Support G.726 in Sun AU
Paul B Mahol
onemda at gmail.com
Sat Nov 24 10:18:55 CET 2012
On 11/24/12, Carl Eugen Hoyos <cehoyos at ag.or.at> wrote:
>
> diff --git a/libavformat/au.c b/libavformat/au.c
> index 788e261..58628a1 100644
> --- a/libavformat/au.c
> +++ b/libavformat/au.c
> @@ -36,6 +36,10 @@
> /* if we don't know the size in advance */
> #define AU_UNKNOWN_SIZE ((uint32_t)(~0))
>
> +typedef struct {
> + int bps;
You could use bits_per_coded_sample?
> +} AUContext;
> +
> /* The libavcodec codecs we support, and the IDs they have in the file */
> static const AVCodecTag codec_au_tags[] = {
> { AV_CODEC_ID_PCM_MULAW, 1 },
> @@ -45,6 +49,9 @@ static const AVCodecTag codec_au_tags[] = {
> { AV_CODEC_ID_PCM_S32BE, 5 },
> { AV_CODEC_ID_PCM_F32BE, 6 },
> { AV_CODEC_ID_PCM_F64BE, 7 },
> + { AV_CODEC_ID_ADPCM_G726, 23 },
> + { AV_CODEC_ID_ADPCM_G726, 25 },
> + { AV_CODEC_ID_ADPCM_G726, 26 },
> { AV_CODEC_ID_PCM_ALAW, 27 },
> { AV_CODEC_ID_NONE, 0 },
> };
> @@ -55,6 +62,15 @@ static int put_au_header(AVIOContext *pb, AVCodecContext *enc)
> {
> if(!enc->codec_tag)
> return -1;
> + if (enc->codec_id == AV_CODEC_ID_ADPCM_G726) {
> + if (enc->bits_per_coded_sample < 3 || enc->bits_per_coded_sample > 5) {
> + av_log(pb, AV_LOG_ERROR,
> + "bits_per_coded_sample '%d' not supported for G.726 in Sun AU\n",
> + enc->bits_per_coded_sample);
> + return AVERROR_INVALIDDATA;
> + }
> + enc->codec_tag = (uint8_t []){23, 26, 0, 25}[enc->bits_per_coded_sample & 3];
> + }
> ffio_wfourcc(pb, ".snd"); /* magic number */
> avio_wb32(pb, 24); /* header size */
> avio_wb32(pb, AU_UNKNOWN_SIZE); /* data size */
> @@ -120,7 +136,8 @@ static int au_probe(AVProbeData *p)
> /* au input */
> static int au_read_header(AVFormatContext *s)
> {
> - int size, bps, data_size = 0;
> + AUContext *au = s->priv_data;
> + int size, data_size = 0;
> unsigned int tag;
> AVIOContext *pb = s->pb;
> unsigned int id, channels, rate;
> @@ -145,7 +162,9 @@ static int au_read_header(AVFormatContext *s)
>
> codec = ff_codec_get_id(codec_au_tags, id);
>
> - if (!(bps = av_get_bits_per_sample(codec))) {
> + if (codec == AV_CODEC_ID_ADPCM_G726) {
> + au->bps = (uint8_t []){4, 0, 3, 5}[id - 23];
bps could become 0 in future causing division by 0 in later code.
> + } else if (!(au->bps = av_get_bits_per_sample(codec))) {
> av_log_ask_for_sample(s, "could not determine bits per sample\n");
> return AVERROR_INVALIDDATA;
> }
> @@ -169,8 +188,9 @@ static int au_read_header(AVFormatContext *s)
> st->codec->codec_id = codec;
> st->codec->channels = channels;
> st->codec->sample_rate = rate;
> + st->codec->bits_per_coded_sample = au->bps;
> if (data_size != AU_UNKNOWN_SIZE)
> - st->duration = (((int64_t)data_size)<<3) / (st->codec->channels * (int64_t)bps);
> + st->duration = (((int64_t)data_size)<<3) / (st->codec->channels * (int64_t)au->bps);
> avpriv_set_pts_info(st, 64, 1, rate);
> return 0;
> }
> @@ -180,14 +200,14 @@ static int au_read_header(AVFormatContext *s)
> static int au_read_packet(AVFormatContext *s,
> AVPacket *pkt)
> {
> + AUContext *au = s->priv_data;
> int ret;
> - int bpcs = av_get_bits_per_sample(s->streams[0]->codec->codec_id);
>
> - if (!bpcs)
> + if (!au->bps)
> return AVERROR(EINVAL);
> ret= av_get_packet(s->pb, pkt, BLOCK_SIZE *
> s->streams[0]->codec->channels *
> - bpcs >> 3);
> + au->bps >> 3);
> if (ret < 0)
> return ret;
> pkt->flags &= ~AV_PKT_FLAG_CORRUPT;
> @@ -199,6 +219,7 @@ static int au_read_packet(AVFormatContext *s,
> AVInputFormat ff_au_demuxer = {
> .name = "au",
> .long_name = NULL_IF_CONFIG_SMALL("Sun AU"),
> + .priv_data_size = sizeof(AUContext),
> .read_probe = au_probe,
> .read_header = au_read_header,
> .read_packet = au_read_packet,
More information about the ffmpeg-devel
mailing list