[FFmpeg-devel] [PATCH v3 4/6] avformat: add argo_asf muxer
Andreas Rheinhardt
andreas.rheinhardt at gmail.com
Thu Aug 6 00:09:45 EEST 2020
Zane van Iperen:
> Signed-off-by: Zane van Iperen <zane at zanevaniperen.com>
> ---
> Changelog | 1 +
> libavformat/Makefile | 1 +
> libavformat/allformats.c | 1 +
> libavformat/argo_asf.c | 127 ++++++++++++++++++++++++++++++++++++++-
> libavformat/version.h | 2 +-
> 5 files changed, 130 insertions(+), 2 deletions(-)
>
> diff --git a/Changelog b/Changelog
> index 0f0fbf2abb..0108f8f1a8 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -12,6 +12,7 @@ version <next>:
> - AV1 encoding support SVT-AV1
> - Cineform HD encoder
> - ADPCM Argonaut Games encoder
> +- Argonaut Games ASF muxer
>
>
> version 4.3:
> diff --git a/libavformat/Makefile b/libavformat/Makefile
> index 62d8cbb54e..610d43ca99 100644
> --- a/libavformat/Makefile
> +++ b/libavformat/Makefile
> @@ -103,6 +103,7 @@ OBJS-$(CONFIG_APTX_HD_DEMUXER) += aptxdec.o rawdec.o
> OBJS-$(CONFIG_APTX_HD_MUXER) += rawenc.o
> OBJS-$(CONFIG_AQTITLE_DEMUXER) += aqtitledec.o subtitles.o
> OBJS-$(CONFIG_ARGO_ASF_DEMUXER) += argo_asf.o
> +OBJS-$(CONFIG_ARGO_ASF_MUXER) += argo_asf.o
> OBJS-$(CONFIG_ASF_DEMUXER) += asfdec_f.o asf.o asfcrypt.o \
> avlanguage.o
> OBJS-$(CONFIG_ASF_O_DEMUXER) += asfdec_o.o asf.o asfcrypt.o \
> diff --git a/libavformat/allformats.c b/libavformat/allformats.c
> index fd9e46e233..b7e59ae170 100644
> --- a/libavformat/allformats.c
> +++ b/libavformat/allformats.c
> @@ -64,6 +64,7 @@ extern AVInputFormat ff_aptx_hd_demuxer;
> extern AVOutputFormat ff_aptx_hd_muxer;
> extern AVInputFormat ff_aqtitle_demuxer;
> extern AVInputFormat ff_argo_asf_demuxer;
> +extern AVOutputFormat ff_argo_asf_muxer;
> extern AVInputFormat ff_asf_demuxer;
> extern AVOutputFormat ff_asf_muxer;
> extern AVInputFormat ff_asf_o_demuxer;
> diff --git a/libavformat/argo_asf.c b/libavformat/argo_asf.c
> index 9de64dfab4..8e6b312521 100644
> --- a/libavformat/argo_asf.c
> +++ b/libavformat/argo_asf.c
> @@ -1,5 +1,5 @@
> /*
> - * Argonaut Games ASF demuxer
> + * Argonaut Games ASF (de)muxer
> *
> * Copyright (C) 2020 Zane van Iperen (zane at zanevaniperen.com)
> *
> @@ -63,6 +63,7 @@ typedef struct ArgoASFDemuxContext {
> uint32_t blocks_read;
> } ArgoASFDemuxContext;
>
> +#if CONFIG_ARGO_ASF_DEMUXER
> static void argo_asf_parse_file_header(ArgoASFFileHeader *hdr, const uint8_t *buf)
> {
> hdr->magic = AV_RL32(buf + 0);
> @@ -254,3 +255,127 @@ AVInputFormat ff_argo_asf_demuxer = {
> .read_header = argo_asf_read_header,
> .read_packet = argo_asf_read_packet
> };
> +#endif
> +
> +#if CONFIG_ARGO_ASF_MUXER
> +static int argo_asf_write_init(AVFormatContext *s)
> +{
> + AVCodecParameters *par;
Cosmetic nit: Add const here and in write_header below.
> +
> + if (s->nb_streams != 1) {
> + av_log(s, AV_LOG_ERROR, "ASF files have exactly one stream\n");
> + return AVERROR(EINVAL);
> + }
> +
> + par = s->streams[0]->codecpar;
> +
> + if (par->codec_id != AV_CODEC_ID_ADPCM_ARGO) {
> + av_log(s, AV_LOG_ERROR, "%s codec not supported\n",
> + avcodec_get_name(par->codec_id));
> + return AVERROR(EINVAL);
> + }
> +
> + if (par->channels > 2) {
> + av_log(s, AV_LOG_ERROR, "ASF files only support up to 2 channels\n");
> + return AVERROR(EINVAL);
> + }
> +
> + if (par->sample_rate > UINT16_MAX) {
> + av_log(s, AV_LOG_ERROR, "Sample rate too large\n");
> + return AVERROR(EINVAL);
> + }
> +
> + if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
> + av_log(s, AV_LOG_ERROR, "Stream not seekable, unable to write output file\n");
> + return AVERROR(EINVAL);
> + }
> +
> + return 0;
> +}
> +
> +static void argo_asf_write_file_header(const ArgoASFFileHeader *fhdr, AVIOContext *pb)
> +{
> + avio_wl32( pb, fhdr->magic);
> + avio_wl16( pb, fhdr->version_major);
> + avio_wl16( pb, fhdr->version_minor);
> + avio_wl32( pb, fhdr->num_chunks);
> + avio_wl32( pb, fhdr->chunk_offset);
> + avio_write(pb, fhdr->name, sizeof(fhdr->name));
> +}
> +
> +static void argo_asf_write_chunk_header(const ArgoASFChunkHeader *ckhdr, AVIOContext *pb)
> +{
> + avio_wl32(pb, ckhdr->num_blocks);
> + avio_wl32(pb, ckhdr->num_samples);
> + avio_wl32(pb, ckhdr->unk1);
> + avio_wl16(pb, ckhdr->sample_rate);
> + avio_wl16(pb, ckhdr->unk2);
> + avio_wl32(pb, ckhdr->flags);
> +}
> +
> +static int argo_asf_write_header(AVFormatContext *s)
> +{
> + AVCodecParameters *par = s->streams[0]->codecpar;
> + ArgoASFFileHeader fhdr;
> + ArgoASFChunkHeader chdr;
> +
> + fhdr.magic = ASF_TAG;
> + fhdr.version_major = 2;
> + fhdr.version_minor = 1;
> + fhdr.num_chunks = 1;
> + fhdr.chunk_offset = ASF_FILE_HEADER_SIZE;
> + strncpy(fhdr.name, av_basename(s->url), FF_ARRAY_ELEMS(fhdr.name));
> +
> + chdr.num_blocks = 0;
> + chdr.num_samples = ASF_SAMPLE_COUNT;
> + chdr.unk1 = 0;
> + chdr.sample_rate = par->sample_rate;
> + chdr.unk2 = ~0;
> + chdr.flags = ASF_CF_BITS_PER_SAMPLE | ASF_CF_ALWAYS1;
> +
> + if (par->channels == 2)
> + chdr.flags |= ASF_CF_STEREO;
> +
> + argo_asf_write_file_header(&fhdr, s->pb);
> + argo_asf_write_chunk_header(&chdr, s->pb);
> + return 0;
> +}
> +
> +static int argo_asf_write_packet(AVFormatContext *s, AVPacket *pkt)
> +{
> + if (pkt->size != 17 * s->streams[0]->codecpar->channels)
> + return AVERROR_INVALIDDATA;
> +
> + if (s->streams[0]->nb_frames >= UINT32_MAX)
> + return AVERROR_INVALIDDATA;
> +
> + avio_write(s->pb, pkt->data, pkt->size);
> + return 0;
> +}
> +
> +static int argo_asf_write_trailer(AVFormatContext *s)
> +{
> + int16_t ret;
Using an int16_t here is wrong: It may mask errors and apart from that
it may lead to warnings from static analyzers.
> +
> + if ((ret = avio_seek(s->pb, ASF_FILE_HEADER_SIZE, SEEK_SET) < 0))
> + return ret;
> +
> + avio_wl32(s->pb, (uint32_t)s->streams[0]->nb_frames);
> + return 0;
> +}
> +
> +AVOutputFormat ff_argo_asf_muxer = {
> + .name = "argo_asf",
> + .long_name = NULL_IF_CONFIG_SMALL("Argonaut Games ASF"),
> + /*
> + * NB: Can't do this as it conflicts with the actual ASF format.
> + * .extensions = "asf",
> + */
> + .audio_codec = AV_CODEC_ID_ADPCM_ARGO,
> + .video_codec = AV_CODEC_ID_NONE,
> + .init = argo_asf_write_init,
> + .write_header = argo_asf_write_header,
> + .write_packet = argo_asf_write_packet,
> + .write_trailer = argo_asf_write_trailer
> +};
> +#endif
> \ No newline at end of file
> diff --git a/libavformat/version.h b/libavformat/version.h
> index 33cebed85e..4d31e1ec3e 100644
> --- a/libavformat/version.h
> +++ b/libavformat/version.h
> @@ -32,7 +32,7 @@
> // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
> // Also please add any ticket numbers that you believe might be affected here
> #define LIBAVFORMAT_VERSION_MAJOR 58
> -#define LIBAVFORMAT_VERSION_MINOR 49
> +#define LIBAVFORMAT_VERSION_MINOR 50
> #define LIBAVFORMAT_VERSION_MICRO 100
>
> #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
>
More information about the ffmpeg-devel
mailing list