Message ID | AM9PR09MB5170B6BBC2B6CE106EB83C85C5459@AM9PR09MB5170.eurprd09.prod.outlook.com |
---|---|
State | Accepted |
Headers | show |
Series | [FFmpeg-devel,v2,1/2] avcodec/adpcmenc: Adds encoder for Westwood ADPCM. | expand |
Context | Check | Description |
---|---|---|
andriy/x86_make | success | Make finished |
andriy/x86_make_fate | success | Make fate finished |
andriy/PPC64_make | success | Make finished |
andriy/PPC64_make_fate | success | Make fate finished |
On 24/4/21 8:35 am, Aidan Richmond wrote: > + > + if (st->codecpar->codec_id != AV_CODEC_ID_ADPCM_IMA_WS) { > + av_log(st, AV_LOG_ERROR, "%s codec not supported for Westwood AUD.\n", > + avcodec_get_name(st->codecpar->codec_id)); > + return -1; AVERROR(EINVAL) > + } > + > + if (ctx->nb_streams != 1) { > + av_log(st, AV_LOG_ERROR, "AUD files have exactly one stream\n"); > + return AVERROR(EINVAL); > + } > + Move both these checks into an init function. > +static int wsaud_write_trailer(AVFormatContext *ctx) > +{ > + AVIOContext *pb = ctx->pb; > + AUDMuxContext *a = ctx->priv_data; > + > + if(!pb->seekable) { > + av_log(ctx->streams[0], AV_LOG_ERROR, "Cannot seek to write file size to header."); > + return -1; > + } > + Same with this one. No point writing the file at all if it's not seekable. > + avio_seek(pb, 2, SEEK_SET); > + avio_wl32(pb, a->size); > + avio_wl32(pb, a->uncomp_size); > + > + return 0; > +} > + > +AVOutputFormat ff_wsaud_muxer = { > + .name = "wsaud", > + .long_name = NULL_IF_CONFIG_SMALL("Westwood Studios audio"), > + .extensions = "aud", > + .priv_data_size = sizeof(AUDMuxContext), > + .audio_codec = AV_CODEC_ID_ADPCM_IMA_WS, > + .video_codec = AV_CODEC_ID_NONE, > + .write_header = wsaud_write_header, > + .write_packet = wsaud_write_packet, > + .write_trailer = wsaud_write_trailer, > +}; >
On 24/4/21 8:35 am, Aidan Richmond wrote: > + > +static int wsaud_write_trailer(AVFormatContext *ctx) > +{ > + AVIOContext *pb = ctx->pb; > + AUDMuxContext *a = ctx->priv_data; > + > + if(!pb->seekable) { Also missing a space.
On 24/4/21 8:35 am, Aidan Richmond wrote: > Format is still used by modders of these old games. > --- > libavformat/Makefile | 1 + > libavformat/allformats.c | 1 + > libavformat/westwood_audenc.c | 129 ++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 131 insertions(+) > create mode 100644 libavformat/westwood_audenc.c > > diff --git a/libavformat/Makefile b/libavformat/Makefile > index bc1ddfa81c..85b5d8e7eb 100644 > --- a/libavformat/Makefile > +++ b/libavformat/Makefile > @@ -581,6 +581,7 @@ OBJS-$(CONFIG_WEBP_MUXER) += webpenc.o > OBJS-$(CONFIG_WEBVTT_DEMUXER) += webvttdec.o subtitles.o > OBJS-$(CONFIG_WEBVTT_MUXER) += webvttenc.o > OBJS-$(CONFIG_WSAUD_DEMUXER) += westwood_aud.o > +OBJS-$(CONFIG_WSAUD_MUXER) += westwood_audenc.o > OBJS-$(CONFIG_WSD_DEMUXER) += wsddec.o rawdec.o > OBJS-$(CONFIG_WSVQA_DEMUXER) += westwood_vqa.o > OBJS-$(CONFIG_WTV_DEMUXER) += wtvdec.o wtv_common.o \ > diff --git a/libavformat/allformats.c b/libavformat/allformats.c > index fa093c7ac2..fe70a1e9a2 100644 > --- a/libavformat/allformats.c > +++ b/libavformat/allformats.c > @@ -478,6 +478,7 @@ extern AVOutputFormat ff_webp_muxer; > extern AVInputFormat ff_webvtt_demuxer; > extern AVOutputFormat ff_webvtt_muxer; > extern AVInputFormat ff_wsaud_demuxer; > +extern AVOutputFormat ff_wsaud_muxer; > extern AVInputFormat ff_wsd_demuxer; > extern AVInputFormat ff_wsvqa_demuxer; > extern AVInputFormat ff_wtv_demuxer; > diff --git a/libavformat/westwood_audenc.c b/libavformat/westwood_audenc.c > new file mode 100644 > index 0000000000..e381aa9a1a > --- /dev/null > +++ b/libavformat/westwood_audenc.c > @@ -0,0 +1,129 @@ > +/* > + * Copyright (c) 2021 Aidan Richmond > + * > + * This file is part of FFmpeg. > + * > + * FFmpeg is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * FFmpeg is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with FFmpeg; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA > + */ > + > +/** > + * @file > + * Westwood Studios AUD file muxer > + * by Aidan Richmond (aidan.is@hotmail.co.uk) > + * > + * This muxer supports IMA ADPCM packed in westwoods format. > + * > + * @see http://xhp.xwis.net/documents/aud3.txt > + */ > + > +#include "libavutil/avassert.h" > + > +#include "avformat.h" > +#include "avio_internal.h" > +#include "internal.h" > +#include <stdint.h> > + > +#define AUD_CHUNK_SIGNATURE 0x0000DEAF > + > +typedef struct AUDMuxContext { > + int uncomp_size; > + int size; > +} AUDMuxContext; > + > +static int wsaud_write_header(AVFormatContext *ctx) > +{ > + AVStream *st = ctx->streams[0]; > + AVIOContext *pb = ctx->pb; > + AUDMuxContext *a = ctx->priv_data; > + unsigned char flags = 0; > + > + if (st->codecpar->codec_id != AV_CODEC_ID_ADPCM_IMA_WS) { > + av_log(st, AV_LOG_ERROR, "%s codec not supported for Westwood AUD.\n", > + avcodec_get_name(st->codecpar->codec_id)); > + return -1; > + } > + > + if (ctx->nb_streams != 1) { > + av_log(st, AV_LOG_ERROR, "AUD files have exactly one stream\n"); > + return AVERROR(EINVAL); > + } > + > + a->uncomp_size = 0; > + a->size = 0; > + > + /* Flag if we have stereo data. */ > + if (st->codecpar->channels == 2) > + flags |= 1; > + > + /* This flags that the file contains 16 bit samples rather than 8 bit > + since the encoder only encodes 16 bit samples this should be set. */ > + if (av_get_bits_per_sample(st->codecpar->codec_id) == 4) > + flags |= 2; > + > + avio_wl16(pb, st->codecpar->sample_rate); > + /* We don't know the file size yet, so just zero 8 bytes */ > + ffio_fill(pb, 0, 8); > + avio_w8(pb, flags); > + /* 99 indicates the ADPCM format. Other formats not supported. */ > + avio_w8(pb, 99); > + > + return 0; > +} > + > +static int wsaud_write_packet(AVFormatContext *ctx, AVPacket *pkt) > +{ > + AVIOContext *pb = ctx->pb; > + AUDMuxContext *a = ctx->priv_data; > + > + av_assert1(pkt->size < UINT16_MAX && (pkt->size * 4) < UINT16_MAX); > + /* Assumes ADPCM since this muxer doesn't support SND1 or PCM format. */ > + avio_wl16(pb, pkt->size); > + avio_wl16(pb, pkt->size * 4); > + avio_wl32(pb, AUD_CHUNK_SIGNATURE); > + avio_write(pb, pkt->data, pkt->size); > + a->size += pkt->size + 8; > + a->uncomp_size += pkt->size * 4; > + > + return 0; > +} > + > +static int wsaud_write_trailer(AVFormatContext *ctx) > +{ > + AVIOContext *pb = ctx->pb; > + AUDMuxContext *a = ctx->priv_data; > + > + if(!pb->seekable) { And should be !(s->pb->seekable & AVIO_SEEKABLE_NORMAL)
diff --git a/libavformat/Makefile b/libavformat/Makefile index bc1ddfa81c..85b5d8e7eb 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -581,6 +581,7 @@ OBJS-$(CONFIG_WEBP_MUXER) += webpenc.o OBJS-$(CONFIG_WEBVTT_DEMUXER) += webvttdec.o subtitles.o OBJS-$(CONFIG_WEBVTT_MUXER) += webvttenc.o OBJS-$(CONFIG_WSAUD_DEMUXER) += westwood_aud.o +OBJS-$(CONFIG_WSAUD_MUXER) += westwood_audenc.o OBJS-$(CONFIG_WSD_DEMUXER) += wsddec.o rawdec.o OBJS-$(CONFIG_WSVQA_DEMUXER) += westwood_vqa.o OBJS-$(CONFIG_WTV_DEMUXER) += wtvdec.o wtv_common.o \ diff --git a/libavformat/allformats.c b/libavformat/allformats.c index fa093c7ac2..fe70a1e9a2 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -478,6 +478,7 @@ extern AVOutputFormat ff_webp_muxer; extern AVInputFormat ff_webvtt_demuxer; extern AVOutputFormat ff_webvtt_muxer; extern AVInputFormat ff_wsaud_demuxer; +extern AVOutputFormat ff_wsaud_muxer; extern AVInputFormat ff_wsd_demuxer; extern AVInputFormat ff_wsvqa_demuxer; extern AVInputFormat ff_wtv_demuxer; diff --git a/libavformat/westwood_audenc.c b/libavformat/westwood_audenc.c new file mode 100644 index 0000000000..e381aa9a1a --- /dev/null +++ b/libavformat/westwood_audenc.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2021 Aidan Richmond + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Westwood Studios AUD file muxer + * by Aidan Richmond (aidan.is@hotmail.co.uk) + * + * This muxer supports IMA ADPCM packed in westwoods format. + * + * @see http://xhp.xwis.net/documents/aud3.txt + */ + +#include "libavutil/avassert.h" + +#include "avformat.h" +#include "avio_internal.h" +#include "internal.h" +#include <stdint.h> + +#define AUD_CHUNK_SIGNATURE 0x0000DEAF + +typedef struct AUDMuxContext { + int uncomp_size; + int size; +} AUDMuxContext; + +static int wsaud_write_header(AVFormatContext *ctx) +{ + AVStream *st = ctx->streams[0]; + AVIOContext *pb = ctx->pb; + AUDMuxContext *a = ctx->priv_data; + unsigned char flags = 0; + + if (st->codecpar->codec_id != AV_CODEC_ID_ADPCM_IMA_WS) { + av_log(st, AV_LOG_ERROR, "%s codec not supported for Westwood AUD.\n", + avcodec_get_name(st->codecpar->codec_id)); + return -1; + } + + if (ctx->nb_streams != 1) { + av_log(st, AV_LOG_ERROR, "AUD files have exactly one stream\n"); + return AVERROR(EINVAL); + } + + a->uncomp_size = 0; + a->size = 0; + + /* Flag if we have stereo data. */ + if (st->codecpar->channels == 2) + flags |= 1; + + /* This flags that the file contains 16 bit samples rather than 8 bit + since the encoder only encodes 16 bit samples this should be set. */ + if (av_get_bits_per_sample(st->codecpar->codec_id) == 4) + flags |= 2; + + avio_wl16(pb, st->codecpar->sample_rate); + /* We don't know the file size yet, so just zero 8 bytes */ + ffio_fill(pb, 0, 8); + avio_w8(pb, flags); + /* 99 indicates the ADPCM format. Other formats not supported. */ + avio_w8(pb, 99); + + return 0; +} + +static int wsaud_write_packet(AVFormatContext *ctx, AVPacket *pkt) +{ + AVIOContext *pb = ctx->pb; + AUDMuxContext *a = ctx->priv_data; + + av_assert1(pkt->size < UINT16_MAX && (pkt->size * 4) < UINT16_MAX); + /* Assumes ADPCM since this muxer doesn't support SND1 or PCM format. */ + avio_wl16(pb, pkt->size); + avio_wl16(pb, pkt->size * 4); + avio_wl32(pb, AUD_CHUNK_SIGNATURE); + avio_write(pb, pkt->data, pkt->size); + a->size += pkt->size + 8; + a->uncomp_size += pkt->size * 4; + + return 0; +} + +static int wsaud_write_trailer(AVFormatContext *ctx) +{ + AVIOContext *pb = ctx->pb; + AUDMuxContext *a = ctx->priv_data; + + if(!pb->seekable) { + av_log(ctx->streams[0], AV_LOG_ERROR, "Cannot seek to write file size to header."); + return -1; + } + + avio_seek(pb, 2, SEEK_SET); + avio_wl32(pb, a->size); + avio_wl32(pb, a->uncomp_size); + + return 0; +} + +AVOutputFormat ff_wsaud_muxer = { + .name = "wsaud", + .long_name = NULL_IF_CONFIG_SMALL("Westwood Studios audio"), + .extensions = "aud", + .priv_data_size = sizeof(AUDMuxContext), + .audio_codec = AV_CODEC_ID_ADPCM_IMA_WS, + .video_codec = AV_CODEC_ID_NONE, + .write_header = wsaud_write_header, + .write_packet = wsaud_write_packet, + .write_trailer = wsaud_write_trailer, +};