diff options
author | Rodger Combs <rodger.combs@gmail.com> | 2015-06-17 03:09:52 -0500 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2015-06-17 13:24:11 +0200 |
commit | bb42a7d4d4011101ddbd817c3a5f6d0d86ee26bd (patch) | |
tree | 66694ca9f6310854cb7443c260b941ae833e6115 /libavformat | |
parent | dc87758775e2ce8be84e4fe598e12416e83d2845 (diff) | |
download | ffmpeg-streaming-bb42a7d4d4011101ddbd817c3a5f6d0d86ee26bd.zip ffmpeg-streaming-bb42a7d4d4011101ddbd817c3a5f6d0d86ee26bd.tar.gz |
lavf/brstm: add support for BFSTM files
Previous version reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/Makefile | 1 | ||||
-rw-r--r-- | libavformat/allformats.c | 1 | ||||
-rw-r--r-- | libavformat/brstm.c | 129 | ||||
-rw-r--r-- | libavformat/version.h | 2 |
4 files changed, 112 insertions, 21 deletions
diff --git a/libavformat/Makefile b/libavformat/Makefile index b9169d9..993ec09 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -105,6 +105,7 @@ OBJS-$(CONFIG_BIT_DEMUXER) += bit.o OBJS-$(CONFIG_BIT_MUXER) += bit.o OBJS-$(CONFIG_BMV_DEMUXER) += bmv.o OBJS-$(CONFIG_BOA_DEMUXER) += boadec.o +OBJS-$(CONFIG_BFSTM_DEMUXER) += brstm.o OBJS-$(CONFIG_BRSTM_DEMUXER) += brstm.o OBJS-$(CONFIG_C93_DEMUXER) += c93.o vocdec.o voc.o OBJS-$(CONFIG_CAF_DEMUXER) += cafdec.o caf.o mov.o mov_chan.o \ diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 3a49650..306e0c9 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -92,6 +92,7 @@ void av_register_all(void) REGISTER_DEMUXER (BINK, bink); REGISTER_MUXDEMUX(BIT, bit); REGISTER_DEMUXER (BMV, bmv); + REGISTER_DEMUXER (BFSTM, bfstm); REGISTER_DEMUXER (BRSTM, brstm); REGISTER_DEMUXER (BOA, boa); REGISTER_DEMUXER (C93, c93); 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", +}; diff --git a/libavformat/version.h b/libavformat/version.h index c0920d5..99b7190 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFORMAT_VERSION_MAJOR 56 -#define LIBAVFORMAT_VERSION_MINOR 36 +#define LIBAVFORMAT_VERSION_MINOR 37 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ |