[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