[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