[FFmpeg-devel] [PATCH 1/6] lavf/brstm: add support for BFSTM files

Paul B Mahol onemda at gmail.com
Wed Jun 17 09:18:33 CEST 2015


Dana 17. 6. 2015. 00:28 osoba "Rodger Combs" <rodger.combs at gmail.com>
napisala je:
>
> ---
>  libavcodec/utils.c       |   4 ++
>  libavformat/Makefile     |   1 +
>  libavformat/allformats.c |   1 +
>  libavformat/brstm.c      | 129
+++++++++++++++++++++++++++++++++++++++--------
>  4 files changed, 115 insertions(+), 20 deletions(-)
>
> diff --git a/libavcodec/utils.c b/libavcodec/utils.c
> index 558afeb..a444a5e 100644
> --- a/libavcodec/utils.c
> +++ b/libavcodec/utils.c
> @@ -3430,6 +3430,10 @@ int av_get_audio_frame_duration(AVCodecContext
*avctx, int frame_bytes)
>                  return (frame_bytes - 4) * 2 / ch;
>              case AV_CODEC_ID_ADPCM_IMA_AMV:
>                  return (frame_bytes - 8) * 2 / ch;
> +            case AV_CODEC_ID_ADPCM_THP:
> +                if (avctx->extradata)
> +                    return frame_bytes * 14 / (8 * ch);
> +                break;
>              case AV_CODEC_ID_ADPCM_XA:
>                  return (frame_bytes / 128) * 224 / ch;
>              case AV_CODEC_ID_INTERPLAY_DPCM:
> diff --git a/libavformat/Makefile b/libavformat/Makefile
> index b9169d9..3c2cf9f 100644
> --- a/libavformat/Makefile
> +++ b/libavformat/Makefile
> @@ -106,6 +106,7 @@ OBJS-$(CONFIG_BIT_MUXER)                 += bit.o
>  OBJS-$(CONFIG_BMV_DEMUXER)               += bmv.o
>  OBJS-$(CONFIG_BOA_DEMUXER)               += boadec.o
>  OBJS-$(CONFIG_BRSTM_DEMUXER)             += brstm.o
> +OBJS-$(CONFIG_BFSTM_DEMUXER)             += brstm.o

Not in alphabetical order.

>  OBJS-$(CONFIG_C93_DEMUXER)               += c93.o vocdec.o voc.o
>  OBJS-$(CONFIG_CAF_DEMUXER)               += cafdec.o caf.o mov.o
mov_chan.o \
>                                              isom.o replaygain.o
> diff --git a/libavformat/allformats.c b/libavformat/allformats.c
> index 3a49650..cc77d1c 100644
> --- a/libavformat/allformats.c
> +++ b/libavformat/allformats.c
> @@ -93,6 +93,7 @@ void av_register_all(void)
>      REGISTER_MUXDEMUX(BIT,              bit);
>      REGISTER_DEMUXER (BMV,              bmv);
>      REGISTER_DEMUXER (BRSTM,            brstm);
> +    REGISTER_DEMUXER (BFSTM,           bfstm);

not in alphabetical order

>      REGISTER_DEMUXER (BOA,              boa);
>      REGISTER_DEMUXER (C93,              c93);
>      REGISTER_MUXDEMUX(CAF,              caf);
> diff --git a/libavformat/brstm.c b/libavformat/brstm.c
> index 19a4a2a..1eba943 100644
> --- a/libavformat/brstm.c
> +++ b/libavformat/brstm.c
> @@ -32,6 +32,7 @@ typedef struct BRSTMDemuxContext {
>      uint32_t    last_block_used_bytes;
>      uint8_t     *table;
>      uint8_t     *adpc;
> +    int         bfstm;
>  } BRSTMDemuxContext;
>
>  static int probe(AVProbeData *p)
> @@ -43,6 +44,15 @@ static int probe(AVProbeData *p)
>      return 0;
>  }
>
> +static int probe_bfstm(AVProbeData *p)
> +{
> +    if (AV_RL32(p->buf) == MKTAG('F','S','T','M') &&
> +        (AV_RL16(p->buf + 4) == 0xFFFE ||
> +         AV_RL16(p->buf + 4) == 0xFEFF))
> +        return AVPROBE_SCORE_MAX / 3 * 2;
> +    return 0;
> +}
> +
>  static int read_close(AVFormatContext *s)
>  {
>      BRSTMDemuxContext *b = s->priv_data;
> @@ -57,11 +67,13 @@ static int read_header(AVFormatContext *s)
>  {
>      BRSTMDemuxContext *b = s->priv_data;
>      int bom, major, minor, codec, chunk;
> -    int64_t pos, h1offset, toffset;
> +    int64_t h1offset, pos, toffset, data_offset = 0;
>      uint32_t size, start, asize;
>      AVStream *st;
>      int ret = AVERROR_EOF;
>
> +    b->bfstm = !strcmp("bfstm", s->iformat->name);
> +
>      st = avformat_new_stream(s, NULL);
>      if (!st)
>          return AVERROR(ENOMEM);
> @@ -79,19 +91,65 @@ static int read_header(AVFormatContext *s)
>          return AVERROR_PATCHWELCOME;
>      }
>
> -    major = avio_r8(s->pb);
> -    minor = avio_r8(s->pb);
> -    avio_skip(s->pb, 4); // size of file
> -    size = avio_rb16(s->pb);
> -    if (size < 14)
> -        return AVERROR_INVALIDDATA;
> +    if (!b->bfstm) {
> +        major = avio_r8(s->pb);
> +        minor = avio_r8(s->pb);
> +        avio_skip(s->pb, 4); // size of file
> +        size = avio_rb16(s->pb);
> +        if (size < 14)
> +            return AVERROR_INVALIDDATA;
> +
> +        avio_skip(s->pb, size - 14);
> +        pos = avio_tell(s->pb);
> +        if (avio_rl32(s->pb) != MKTAG('H','E','A','D'))
> +            return AVERROR_INVALIDDATA;
> +    } else {
> +        uint32_t info_offset = 0, info_size;
> +        uint16_t section_count, header_size, i;
> +
> +        header_size = avio_rb16(s->pb); // 6
> +
> +        avio_skip(s->pb, 4); // Unknown constant 0x00030000
> +        avio_skip(s->pb, 4); // size of file
> +        section_count = avio_rb16(s->pb);
> +        avio_skip(s->pb, 2); // padding
> +        for (i = 0; avio_tell(s->pb) < header_size
> +                    && !(data_offset && info_offset)
> +                    && i < section_count; i++) {
> +            uint32_t flag = avio_rb32(s->pb);
> +            switch (flag) {
> +            case 0x40000000:
> +                info_offset = avio_rb32(s->pb);
> +                info_size   = avio_rb32(s->pb);
> +                break;
> +            case 0x40010000:
> +                avio_skip(s->pb, 4); // seek offset
> +                avio_skip(s->pb, 4); // seek size
> +                break;
> +            case 0x40020000:
> +                data_offset = avio_rb32(s->pb);
> +                avio_skip(s->pb, 4); //data_size = avio_rb32(s->pb);
> +                break;
> +            case 0x40030000:
> +                avio_skip(s->pb, 4); // REGN offset
> +                avio_skip(s->pb, 4); // REGN size
> +                break;
> +            }
> +        }
> +
> +        if (!info_offset || !data_offset)
> +            return AVERROR_INVALIDDATA;
> +
> +        start = data_offset + 8;
> +
> +        avio_skip(s->pb, info_offset - avio_tell(s->pb));
> +        pos = avio_tell(s->pb);
> +        if (avio_rl32(s->pb) != MKTAG('I','N','F','O'))
> +            return AVERROR_INVALIDDATA;
> +    }
>
> -    avio_skip(s->pb, size - 14);
> -    pos = avio_tell(s->pb);
> -    if (avio_rl32(s->pb) != MKTAG('H','E','A','D'))
> -        return AVERROR_INVALIDDATA;
>      size = avio_rb32(s->pb);
> -    if (size < 256)
> +    if (size < 192)
>          return AVERROR_INVALIDDATA;
>      avio_skip(s->pb, 4); // unknown
>      h1offset = avio_rb32(s->pb);
> @@ -121,17 +179,22 @@ static int read_header(AVFormatContext *s)
>          return AVERROR_INVALIDDATA;
>
>      avio_skip(s->pb, 1); // padding
> +    if (b->bfstm)
> +        avio_skip(s->pb, 2); // padding
> +
>      st->codec->sample_rate = avio_rb16(s->pb);
>      if (!st->codec->sample_rate)
>          return AVERROR_INVALIDDATA;
>
> -    avio_skip(s->pb, 2); // padding
> +    if (!b->bfstm)
> +        avio_skip(s->pb, 2); // padding
>      avio_skip(s->pb, 4); // loop start sample
>      st->start_time = 0;
>      st->duration = avio_rb32(s->pb);
>      avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
>
> -    start = avio_rb32(s->pb);
> +    if (!b->bfstm)
> +        start = avio_rb32(s->pb);
>      b->current_block = 0;
>      b->block_count = avio_rb32(s->pb);
>      if (b->block_count > UINT16_MAX) {
> @@ -157,7 +220,10 @@ static int read_header(AVFormatContext *s)
>          int ch;
>
>          avio_skip(s->pb, pos + toffset - avio_tell(s->pb));
> -        toffset = avio_rb32(s->pb) + 16LL;
> +        if (!b->bfstm)
> +            toffset = avio_rb32(s->pb) + 16LL;
> +        else
> +            toffset = toffset + avio_rb32(s->pb) + st->codec->channels *
8 - 8;
>          if (toffset > size)
>              return AVERROR_INVALIDDATA;
>
> @@ -171,7 +237,15 @@ static int read_header(AVFormatContext *s)
>                  ret = AVERROR_INVALIDDATA;
>                  goto fail;
>              }
> -            avio_skip(s->pb, 24);
> +            avio_skip(s->pb, b->bfstm ? 14 : 24);
> +        }
> +
> +        if (b->bfstm) {
> +            st->codec->extradata_size = 32 * st->codec->channels;
> +            st->codec->extradata = av_malloc(st->codec->extradata_size);
> +            if (!st->codec->extradata)
> +                return AVERROR(ENOMEM);
> +            memcpy(st->codec->extradata, b->table,
st->codec->extradata_size);
>          }
>      }
>
> @@ -179,7 +253,11 @@ static int read_header(AVFormatContext *s)
>          ret = AVERROR_INVALIDDATA;
>          goto fail;
>      }
> -    avio_skip(s->pb, size - (avio_tell(s->pb) - pos));
> +
> +    if (!b->bfstm)
> +        avio_skip(s->pb, size - (avio_tell(s->pb) - pos));
> +    else
> +        avio_skip(s->pb, data_offset - avio_tell(s->pb));
>
>      while (!avio_feof(s->pb)) {
>          chunk = avio_rl32(s->pb);
> @@ -214,13 +292,13 @@ static int read_header(AVFormatContext *s)
>              break;
>          case MKTAG('D','A','T','A'):
>              if ((start < avio_tell(s->pb)) ||
> -                (!b->adpc && codec == AV_CODEC_ID_ADPCM_THP)) {
> +                (!b->adpc && codec == AV_CODEC_ID_ADPCM_THP &&
!b->bfstm)) {
>                  ret = AVERROR_INVALIDDATA;
>                  goto fail;
>              }
>              avio_skip(s->pb, start - avio_tell(s->pb));
>
> -            if (major != 1 || minor)
> +            if ((major != 1 || minor) && !b->bfstm)
>                  avpriv_request_sample(s, "Version %d.%d", major, minor);
>
>              return 0;
> @@ -257,7 +335,7 @@ static int read_packet(AVFormatContext *s, AVPacket
*pkt)
>          return AVERROR_EOF;
>      }
>
> -    if (codec->codec_id == AV_CODEC_ID_ADPCM_THP) {
> +    if (codec->codec_id == AV_CODEC_ID_ADPCM_THP && !codec->extradata) {
>          uint8_t *dst;
>
>          if (av_new_packet(pkt, 8 + (32 + 4) * codec->channels + size) <
0)
> @@ -295,3 +373,14 @@ AVInputFormat ff_brstm_demuxer = {
>      .read_close     = read_close,
>      .extensions     = "brstm",
>  };
> +
> +AVInputFormat ff_bfstm_demuxer = {
> +    .name           = "bfstm",
> +    .long_name      = NULL_IF_CONFIG_SMALL("BFSTM (Binary Cafe Stream)"),
> +    .priv_data_size = sizeof(BRSTMDemuxContext),
> +    .read_probe     = probe_bfstm,
> +    .read_header    = read_header,
> +    .read_packet    = read_packet,
> +    .read_close     = read_close,
> +    .extensions     = "bfstm",
> +};
> --
> 2.4.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Missing minor bump and changelog entry, rest lgtm.
What about fate test?


More information about the ffmpeg-devel mailing list