[FFmpeg-devel] [PATCH] libavcodec, libavformat: Added DFPWM1a codec and raw format
Jack Bruienne
jackbruienne at gmail.com
Sat Feb 26 01:42:35 EET 2022
Thanks for looking over the patch. I used git format-patch to make the
email and then sent it with Thunderbird; it appears that the command on
the website doesn't put the patch in an attachment. I'll be adding
--attach for future patches to fix this.
I will be sending split updated patches fixing the issues you mentioned
promptly.
On 2/25/22 03:15, Paul B Mahol wrote:
> On Fri, Feb 25, 2022 at 02:54:35AM -0500, Jack Bruienne wrote:
>> From the wiki page (https://wiki.vexatos.com/dfpwm):
>>> DFPWM (Dynamic Filter Pulse Width Modulation) is an audio codec
>>> created by Ben “GreaseMonkey” Russell in 2012, originally to be used
>>> as a voice codec for asiekierka's pixmess, a C remake of 64pixels.
>>> It is a 1-bit-per-sample codec which uses a dynamic-strength one-pole
>>> low-pass filter as a predictor. Due to the fact that a raw DPFWM decoding
>>> creates a high-pitched whine, it is often followed by some post-processing
>>> filters to make the stream more listenable.
>> It has recently gained popularity through the ComputerCraft mod for
>> Minecraft, which added support for audio through this codec, as well as
>> the Computronics expansion which preceeded the official support. These
>> both implement the slightly adjusted 1a version of the codec, which is
>> the version I have chosen for this patch.
>>
>> This patch adds both a new codec (with encoding and decoding), as well as
>> a raw audio format to be able to read/write the raw files that are most
>> commonly used (as no other container format supports it yet).
>>
>> The codec sources are pretty simple: they use the reference codec with
>> a basic wrapper to connect it to the FFmpeg AVCodec system. There's a
>> bit of extra code to convert from unsigned to signed 8-bit audio, as the
>> codec implementation operates on signed data, which FFmpeg doesn't support.
>>
>> The muxers are mostly copied from the PCM demuxer and the raw muxers, as
>> DFPWM is typically stored as raw data.
>>
>> This patch will be highly useful to ComputerCraft developers who are
>> working with audio, as it is the standard format for audio, and there
>> are few user-friendly encoders out there. It will streamline the process
>> for importing audio, replacing the need to write code or use tools that
>> require very specific input formats.
>>
>> You may use the CraftOS-PC program (https://www.craftos-pc.cc) to test
>> out DFPWM playback. To use it, run the program and type this command:
>> "attach left speaker" Then run "speaker play <file.dfpwm>" for each file.
>> The app runs in a sandbox, so files have to be transferred in first;
>> the easiest way to do this is to simply drag the file on the window.
>> (Or copy files to the folder at https://www.craftos-pc.cc/docs/saves.)
>>
>> Sample DFPWM files can be generated with an online tool at
>> https://music.madefor.cc. This is the current best way to encode DFPWM
>> files. Simply drag an audio file onto the page, and it will encode it,
>> giving a download link on the page.
>>
>> I've made sure to update all of the docs as per Developer§7, and I've
>> tested it as per section 8. Test files encoded to DFPWM play correctly
>> in ComputerCraft, and other files that work in CC are correctly decoded.
>> I have also verified that corrupt files do not crash the decoder - this
>> should theoretically not be an issue as the result size is constant with
>> respect to the input size.
>>
>> One thing I noticed is that this sample file fails to decode to raw:
>> https://samples.ffmpeg.org/ogg/virginradio-three-consecutive-chains.ogg
>> It reports "Application provided invalid, non monotonically increasing
>> dts to muxer in stream 0", which appears to be because the initial
>> timestamp is not 0:00. This affects all raw muxers, including PCM.
>>
>> Signed-off-by: Jack Bruienne <jackbruienne at gmail.com>
>> ---
>> Changelog | 1 +
>> MAINTAINERS | 2 +
>> doc/general_contents.texi | 2 +
>> libavcodec/Makefile | 2 +
>> libavcodec/allcodecs.c | 2 +
>> libavcodec/codec_desc.c | 7 ++
>> libavcodec/codec_id.h | 1 +
>> libavcodec/dfpwmdec.c | 138 +++++++++++++++++++++++++++++++++++++
>> libavcodec/dfpwmenc.c | 140 ++++++++++++++++++++++++++++++++++++++
>> libavcodec/utils.c | 2 +
>> libavcodec/version.h | 2 +-
>> libavformat/Makefile | 2 +
>> libavformat/allformats.c | 2 +
>> libavformat/dfpwmdec.c | 107 +++++++++++++++++++++++++++++
>> libavformat/rawenc.c | 13 ++++
>> libavformat/version.h | 4 +-
>> 16 files changed, 424 insertions(+), 3 deletions(-)
>> create mode 100644 libavcodec/dfpwmdec.c
>> create mode 100644 libavcodec/dfpwmenc.c
>> create mode 100644 libavformat/dfpwmdec.c
>>
>> diff --git a/Changelog b/Changelog
>> index 5ad2cef..ec688da 100644
>> --- a/Changelog
>> +++ b/Changelog
>> @@ -4,6 +4,7 @@ releases are sorted from youngest to oldest.
>> version 5.1:
>> - dialogue enhance audio filter
>> - dropped obsolete XvMC hwaccel
>> +- DFPWM audio encoder/decoder and raw muxer/demuxer
>
> Keep empty line here above and everywhere else you had removed them.
> Is patch corrupted somehow? Just attach file.
> And split demuxer and muxer addition from decoder and encoder.
>
>> version 5.0:
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index f33ccbd..931cf4b 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -161,6 +161,7 @@ Codecs:
>> cscd.c Reimar Doeffinger
>> cuviddec.c Timo Rothenpieler
>> dca* foo86
>> + dfpwm* Jack Bruienne
>> dirac* Rostislav Pehlivanov
>> dnxhd* Baptiste Coudurier
>> dolby_e* foo86
>> @@ -415,6 +416,7 @@ Muxers/Demuxers:
>> dashdec.c Steven Liu
>> dashenc.c Karthick Jeyapal
>> daud.c Reimar Doeffinger
>> + dfpwmdec.c Jack Bruienne
>> dss.c Oleksij Rempel
>> dtsdec.c foo86
>> dtshddec.c Paul B Mahol
>> diff --git a/doc/general_contents.texi b/doc/general_contents.texi
>> index df1692c..fcd9da1 100644
>> --- a/doc/general_contents.texi
>> +++ b/doc/general_contents.texi
>> @@ -578,6 +578,7 @@ library:
>> @item raw aptX @tab X @tab X
>> @item raw aptX HD @tab X @tab X
>> @item raw Chinese AVS video @tab X @tab X
>> + at item raw DFPWM @tab X @tab X
>> @item raw Dirac @tab X @tab X
>> @item raw DNxHD @tab X @tab X
>> @item raw DTS @tab X @tab X
>> @@ -1194,6 +1195,7 @@ following image formats are supported:
>> @item CRI HCA @tab @tab X
>> @item Delphine Software International CIN audio @tab @tab X
>> @tab Codec used in Delphine Software International games.
>> + at item DFPWM @tab X @tab X
>> @item Digital Speech Standard - Standard Play mode (DSS SP) @tab @tab X
>> @item Discworld II BMV Audio @tab @tab X
>> @item COOK @tab @tab X
>> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
>> index 6076b4a..7474220 100644
>> --- a/libavcodec/Makefile
>> +++ b/libavcodec/Makefile
>> @@ -289,6 +289,8 @@ OBJS-$(CONFIG_DERF_DPCM_DECODER) += dpcm.o
>> OBJS-$(CONFIG_DIRAC_DECODER) += diracdec.o dirac.o diracdsp.o
>> diractab.o \
>> dirac_arith.o dirac_dwt.o
>> dirac_vlc.o
>> OBJS-$(CONFIG_DFA_DECODER) += dfa.o
>> +OBJS-$(CONFIG_DFPWM_DECODER) += dfpwmdec.o
>> +OBJS-$(CONFIG_DFPWM_ENCODER) += dfpwmenc.o
>> OBJS-$(CONFIG_DNXHD_DECODER) += dnxhddec.o dnxhddata.o
>> OBJS-$(CONFIG_DNXHD_ENCODER) += dnxhdenc.o dnxhddata.o
>> OBJS-$(CONFIG_DOLBY_E_DECODER) += dolby_e.o dolby_e_parse.o
>> kbdwin.o
>> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
>> index d1e1019..c3a0c26 100644
>> --- a/libavcodec/allcodecs.c
>> +++ b/libavcodec/allcodecs.c
>> @@ -437,6 +437,8 @@ extern const AVCodec ff_bmv_audio_decoder;
>> extern const AVCodec ff_cook_decoder;
>> extern const AVCodec ff_dca_encoder;
>> extern const AVCodec ff_dca_decoder;
>> +extern const AVCodec ff_dfpwm_encoder;
>> +extern const AVCodec ff_dfpwm_decoder;
>> extern const AVCodec ff_dolby_e_decoder;
>> extern const AVCodec ff_dsd_lsbf_decoder;
>> extern const AVCodec ff_dsd_msbf_decoder;
>> diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
>> index 725c687..87ca591 100644
>> --- a/libavcodec/codec_desc.c
>> +++ b/libavcodec/codec_desc.c
>> @@ -3237,6 +3237,13 @@ static const AVCodecDescriptor codec_descriptors[] =
>> {
>> .long_name = NULL_IF_CONFIG_SMALL("MSN Siren"),
>> .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
>> },
>> + {
>> + .id = AV_CODEC_ID_DFPWM,
>> + .type = AVMEDIA_TYPE_AUDIO,
>> + .name = "dfpwm",
>> + .long_name = NULL_IF_CONFIG_SMALL("DFPWM1a audio"),
> You could use full description here instead of just DFPWM1a.
>
>
>> + .props = AV_CODEC_PROP_LOSSY,
>> + },
>> /* subtitle codecs */
>> {
>> diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
>> index ab265ec..3ffb9bd 100644
>> --- a/libavcodec/codec_id.h
>> +++ b/libavcodec/codec_id.h
>> @@ -516,6 +516,7 @@ enum AVCodecID {
>> AV_CODEC_ID_HCA,
>> AV_CODEC_ID_FASTAUDIO,
>> AV_CODEC_ID_MSNSIREN,
>> + AV_CODEC_ID_DFPWM,
> Keep empty line here.
>
>> /* subtitle codecs */
>> AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing
>> at the start of subtitle codecs.
>> diff --git a/libavcodec/dfpwmdec.c b/libavcodec/dfpwmdec.c
>> new file mode 100644
>> index 0000000..9f12841
>> --- /dev/null
>> +++ b/libavcodec/dfpwmdec.c
>> @@ -0,0 +1,138 @@
>> +/*
>> + * DFPWM decoder
>> + * Copyright (c) 2022 Jack Bruienne
>> + * Copyright (c) 2012, 2016 Ben "GreaseMonkey" Russell
>> + *
>> + * 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
>> + * DFPWM1a decoder
>> + */
>> +
>> +#include "libavutil/internal.h"
>> +#include "avcodec.h"
>> +#include "codec_id.h"
>> +#include "internal.h"
>> +
>> +typedef struct {
>> + int fq, q, s, lt;
>> +} DFPWMState;
>> +
>> +// DFPWM codec from https://github.com/ChenThread/dfpwm/blob/master/1a/
>> +// Licensed in the public domain
>> +
>> +#ifndef CONST_PREC
>> +#define CONST_PREC 10
>> +#endif
>> +
>> +static void au_decompress(DFPWMState *state, int fs, int len, int8_t
>> *outbuf, uint8_t *inbuf)
>> +{
>> + int i, j;
>> + uint8_t d;
>> + for (i = 0; i < len; i++) {
>> + // get bits
>> + d = *(inbuf++);
>> + for (j = 0; j < 8; j++) {
>> + int nq, lq, st, ns, ov;
>> + // set target
>> + int t = ((d&1) ? 127 : -128);
>> + d >>= 1;
>> +
>> + // adjust charge
>> + nq = state->q + ((state->s * (t-state->q) +
>> (1<<(CONST_PREC-1)))>>CONST_PREC);
>> + if(nq == state->q && nq != t)
>> + state->q += (t == 127 ? 1 : -1);
>> + lq = state->q;
>> + state->q = nq;
>> +
>> + // adjust strength
>> + st = (t != state->lt ? 0 : (1<<CONST_PREC)-1);
>> + ns = state->s;
>> + if(ns != st)
>> + ns += (st != 0 ? 1 : -1);
>> +#if CONST_PREC > 8
>> + if(ns < 1+(1<<(CONST_PREC-8))) ns = 1+(1<<(CONST_PREC-8));
>> +#endif
>> + state->s = ns;
>> +
>> + // FILTER: perform antijerk
>> + ov = (t != state->lt ? (nq+lq)>>1 : nq);
>> +
>> + // FILTER: perform LPF
>> + state->fq += ((fs*(ov-state->fq) + 0x80)>>8);
>> + ov = state->fq;
>> +
>> + // output sample
>> + *(outbuf++) = ov;
>> +
>> + state->lt = t;
>> + }
>> + }
>> +}
>> +
>> +static av_cold int dfpwm_dec_init(struct AVCodecContext *ctx)
>> +{
>> + DFPWMState *state = ctx->priv_data;
>> +
>> + state->fq = 0;
>> + state->q = 0;
>> + state->s = 0;
>> + state->lt = -128;
>> +
>> + return 0;
>> +}
>> +
>> +static av_cold int dfpwm_dec_end(struct AVCodecContext *ctx)
>> +{
>> + return 0;
>> +}
> Remove if not gonna be used and is empty.
>
>> +
>> +static int dfpwm_dec_frame(struct AVCodecContext *ctx, void *data,
>> + int *got_frame, struct AVPacket *packet)
>> +{
>> + DFPWMState *state = ctx->priv_data;
>> + AVFrame *frame = data;
>> +
>> + frame->format = AV_SAMPLE_FMT_U8;
>> + frame->nb_samples = packet->size * 8;
>> + frame->channel_layout = AV_CH_LAYOUT_MONO;
>> +
>> + av_frame_get_buffer(frame, 0);
> Use ff_get_buffer()
>
> See how libavcodec/pcm.c codecs handles that.
>
>> +
>> + au_decompress(state, 100, packet->size, frame->data[0], packet->data);
>> +
>> + // convert from signed to unsigned 8-bit, as DFPWM outputs S8 but
>> FFmpeg needs U8
>> + for (int i = 0; i < packet->size * 8; i++) frame->data[0][i] =
>> ((int8_t*)frame->data[0])[i] + 128;
> Cant you remove this wrapper, for such trivial code is not helping here.
> Than you can do conversion from S8 to U8 on the fly without need for extra buffer.
>
>> +
>> + if (got_frame) *got_frame = 1;
>> + return packet->size;
>> +}
>> +
>> +const AVCodec ff_dfpwm_decoder = {
>> + .name = "dfpwm",
>> + .long_name = NULL_IF_CONFIG_SMALL("DFPWM1a audio"),
>> + .type = AVMEDIA_TYPE_AUDIO,
>> + .id = AV_CODEC_ID_DFPWM,
>> + .priv_data_size = sizeof(DFPWMState),
>> + .init = dfpwm_dec_init,
>> + .close = dfpwm_dec_end,
>> + .decode = dfpwm_dec_frame,
>> + .capabilities = 0,
> This flags are not correct, or optimal in any way.
>
>> + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
>> +};
>> \ No newline at end of file
>> diff --git a/libavcodec/dfpwmenc.c b/libavcodec/dfpwmenc.c
>> new file mode 100644
>> index 0000000..97fc42e
>> --- /dev/null
>> +++ b/libavcodec/dfpwmenc.c
>> @@ -0,0 +1,140 @@
>> +/*
>> + * DFPWM encoder
>> + * Copyright (c) 2022 Jack Bruienne
>> + * Copyright (c) 2012, 2016 Ben "GreaseMonkey" Russell
>> + *
>> + * 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
>> + * DFPWM1a encoder
>> + */
>> +
>> +#include "libavutil/internal.h"
>> +#include "avcodec.h"
>> +#include "codec_id.h"
>> +#include "internal.h"
>> +
>> +typedef struct {
>> + int fq, q, s, lt;
>> +} DFPWMState;
>> +
>> +// DFPWM codec from https://github.com/ChenThread/dfpwm/blob/master/1a/
>> +// Licensed in the public domain
>> +
>> +#ifndef CONST_PREC
>> +#define CONST_PREC 10
>> +#endif
>> +
>> +// note, len denotes how many compressed bytes there are (uncompressed
>> bytes / 8).
>> +static void au_compress(DFPWMState *state, int len, uint8_t *outbuf, int8_t
>> *inbuf)
>> +{
>> + int i, j;
>> + uint8_t d = 0;
>> + for (i = 0; i < len; i++) {
>> + for (j = 0; j < 8; j++) {
>> + int nq, st, ns;
>> + // get sample
>> + int v = *(inbuf++);
>> + // set bit / target
>> + int t = (v < state->q || v == -128 ? -128 : 127);
>> + d >>= 1;
>> + if(t > 0)
>> + d |= 0x80;
>> +
>> + // adjust charge
>> + nq = state->q + ((state->s * (t-state->q) +
>> (1<<(CONST_PREC-1)))>>CONST_PREC);
>> + if(nq == state->q && nq != t)
>> + nq += (t == 127 ? 1 : -1);
>> + state->q = nq;
>> +
>> + // adjust strength
>> + st = (t != state->lt ? 0 : (1<<CONST_PREC)-1);
>> + ns = state->s;
>> + if(ns != st)
>> + ns += (st != 0 ? 1 : -1);
>> +#if CONST_PREC > 8
>> + if(ns < 1+(1<<(CONST_PREC-8))) ns = 1+(1<<(CONST_PREC-8));
>> +#endif
>> + state->s = ns;
>> +
>> + state->lt = t;
>> +
>> + //fprintf(stderr, "%4i %4i %4i %4i\n", v, *q, *s, t);
>> + //usleep(10000);
>> + }
>> +
>> + // output bits
>> + *(outbuf++) = d;
>> + }
>> +}
>> +
>> +static av_cold int dfpwm_enc_init(struct AVCodecContext *ctx)
>> +{
>> + DFPWMState *state = ctx->priv_data;
>> +
>> + state->fq = 0;
>> + state->q = 0;
>> + state->s = 0;
>> + state->lt = -128;
>> +
>> + return 0;
>> +}
>> +
>> +static av_cold int dfpwm_enc_end(struct AVCodecContext *ctx)
>> +{
>> + return 0;
>> +}
> Please remove functions that do nothing.
>
>> +
>> +static int dfpwm_enc_frame(struct AVCodecContext *ctx, struct AVPacket
>> *packet,
>> + const struct AVFrame *frame, int *got_packet)
>> +{
>> + DFPWMState *state = ctx->priv_data;
>> + int size = frame->nb_samples / 8 + (frame->nb_samples % 8 > 0 ? 1 : 0);
>> + int8_t *data = av_malloc(size * 8);
>> +
>> + if (!data) return AVERROR(ENOMEM);
>> +
>> + if (packet->size < size) av_grow_packet(packet, size - packet->size);
>> + else if (packet->size > size) av_shrink_packet(packet, size);
>> +
>> + // make a temporary S8 buffer as DFPWM needs S8 but FFmpeg uses U8
>> + for (int i = 0; i < frame->nb_samples; i++) data[i] = frame->data[0][i]
>> - 128;
>> + for (int i = frame->nb_samples; i < size * 8; i++) data[i] = 0;
>> +
>> + au_compress(state, size, packet->data, data);
>> + av_free(data);
> Using extra buffer for such trivial code is not optimal solution.
>
>> +
>> + if (got_packet) *got_packet = 1;
>> + return 0;
>> +}
>> +
>> +const AVCodec ff_dfpwm_encoder = {
>> + .name = "dfpwm",
>> + .long_name = NULL_IF_CONFIG_SMALL("DFPWM1a audio"),
>> + .type = AVMEDIA_TYPE_AUDIO,
>> + .id = AV_CODEC_ID_DFPWM,
>> + .priv_data_size = sizeof(DFPWMState),
>> + .init = dfpwm_enc_init,
>> + .close = dfpwm_enc_end,
>> + .encode2 = dfpwm_enc_frame,
>> + .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_U8,
>> AV_SAMPLE_FMT_NONE},
>> + .channel_layouts = (const uint64_t[]){AV_CH_LAYOUT_MONO, 0},
>> + .capabilities = AV_CODEC_CAP_VARIABLE_FRAME_SIZE,
>> + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
>> +};
>> diff --git a/libavcodec/utils.c b/libavcodec/utils.c
>> index 6f9d90a..066da76 100644
>> --- a/libavcodec/utils.c
>> +++ b/libavcodec/utils.c
>> @@ -577,6 +577,8 @@ enum AVCodecID av_get_pcm_codec(enum AVSampleFormat fmt,
>> int be)
>> int av_get_bits_per_sample(enum AVCodecID codec_id)
>> {
>> switch (codec_id) {
>> + case AV_CODEC_ID_DFPWM:
>> + return 1;
>> case AV_CODEC_ID_ADPCM_SBPRO_2:
>> return 2;
>> case AV_CODEC_ID_ADPCM_SBPRO_3:
>> diff --git a/libavcodec/version.h b/libavcodec/version.h
>> index d900503..84f3979 100644
>> --- a/libavcodec/version.h
>> +++ b/libavcodec/version.h
>> @@ -28,7 +28,7 @@
>> #include "libavutil/version.h"
>> #define LIBAVCODEC_VERSION_MAJOR 59
>> -#define LIBAVCODEC_VERSION_MINOR 21
>> +#define LIBAVCODEC_VERSION_MINOR 22
>> #define LIBAVCODEC_VERSION_MICRO 100
>> #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
>> diff --git a/libavformat/Makefile b/libavformat/Makefile
>> index 6566e40..b89073a 100644
>> --- a/libavformat/Makefile
>> +++ b/libavformat/Makefile
>> @@ -165,6 +165,8 @@ OBJS-$(CONFIG_DAUD_MUXER) += daudenc.o
>> OBJS-$(CONFIG_DCSTR_DEMUXER) += dcstr.o
>> OBJS-$(CONFIG_DERF_DEMUXER) += derf.o pcm.o
>> OBJS-$(CONFIG_DFA_DEMUXER) += dfa.o
>> +OBJS-$(CONFIG_DFPWM_DEMUXER) += dfpwmdec.o pcm.o
>> +OBJS-$(CONFIG_DFPWM_MUXER) += rawenc.o
>> OBJS-$(CONFIG_DHAV_DEMUXER) += dhav.o
>> OBJS-$(CONFIG_DIRAC_DEMUXER) += diracdec.o rawdec.o
>> OBJS-$(CONFIG_DIRAC_MUXER) += rawenc.o
>> diff --git a/libavformat/allformats.c b/libavformat/allformats.c
>> index d066a77..587ad59 100644
>> --- a/libavformat/allformats.c
>> +++ b/libavformat/allformats.c
>> @@ -124,6 +124,8 @@ extern const AVOutputFormat ff_daud_muxer;
>> extern const AVInputFormat ff_dcstr_demuxer;
>> extern const AVInputFormat ff_derf_demuxer;
>> extern const AVInputFormat ff_dfa_demuxer;
>> +extern const AVInputFormat ff_dfpwm_demuxer;
>> +extern const AVOutputFormat ff_dfpwm_muxer;
>> extern const AVInputFormat ff_dhav_demuxer;
>> extern const AVInputFormat ff_dirac_demuxer;
>> extern const AVOutputFormat ff_dirac_muxer;
>> diff --git a/libavformat/dfpwmdec.c b/libavformat/dfpwmdec.c
>> new file mode 100644
>> index 0000000..ad5bfa5
>> --- /dev/null
>> +++ b/libavformat/dfpwmdec.c
>> @@ -0,0 +1,107 @@
>> +/*
>> + * RAW PCM demuxers
>> + * Copyright (c) 2002 Fabrice Bellard
>> + * Copyright (c) 2022 Jack Bruienne
>> + *
>> + * 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
>> + */
>> +
>> +#include "libavutil/avstring.h"
>> +#include "avformat.h"
>> +#include "internal.h"
>> +#include "pcm.h"
>> +#include "libavutil/log.h"
>> +#include "libavutil/opt.h"
>> +#include "libavutil/avassert.h"
>> +
>> +typedef struct DFPWMAudioDemuxerContext {
>> + AVClass *class;
>> + int sample_rate;
>> +} DFPWMAudioDemuxerContext;
>> +
>> +static int dfpwm_read_header(AVFormatContext *s)
>> +{
>> + DFPWMAudioDemuxerContext *s1 = s->priv_data;
>> + AVCodecParameters *par;
>> + AVStream *st;
>> + uint8_t *mime_type = NULL;
>> +
>> + st = avformat_new_stream(s, NULL);
>> + if (!st)
>> + return AVERROR(ENOMEM);
>> + par = st->codecpar;
>> +
>> + par->codec_type = AVMEDIA_TYPE_AUDIO;
>> + par->codec_id = s->iformat->raw_codec_id;
>> + par->sample_rate = s1->sample_rate;
>> + par->channels = 1;
>> +
>> + av_opt_get(s->pb, "mime_type", AV_OPT_SEARCH_CHILDREN, &mime_type);
>> + if (mime_type && s->iformat->mime_type) {
>> + int rate = 0;
>> + const char *options;
>> + if (av_stristart(mime_type, s->iformat->mime_type, &options)) { /*
>> audio/L16 */
>> + while (options = strchr(options, ';')) {
>> + options++;
>> + if (!rate)
>> + sscanf(options, " rate=%d", &rate);
>> + }
>> + if (rate <= 0) {
>> + av_log(s, AV_LOG_ERROR,
>> + "Invalid sample_rate found in mime_type \"%s\"\n",
>> + mime_type);
>> + av_freep(&mime_type);
>> + return AVERROR_INVALIDDATA;
>> + }
>> + par->sample_rate = rate;
>> + }
>> + }
>> + av_freep(&mime_type);
>> +
>> + par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id);
>> +
>> + av_assert0(par->bits_per_coded_sample > 0);
>> +
>> + par->block_align = 1;
>> +
>> + avpriv_set_pts_info(st, 64, 1, par->sample_rate);
>> + return 0;
>> +}
>> +
>> +static const AVOption dfpwm_options[] = {
>> + { "sample_rate", "", offsetof(DFPWMAudioDemuxerContext, sample_rate),
>> AV_OPT_TYPE_INT, {.i64 = 44100}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
>> + { NULL },
>> +};
>> +static const AVClass dfpwm_demuxer_class = {
>> + .class_name = "dfpwm demuxer",
>> + .item_name = av_default_item_name,
>> + .option = dfpwm_options,
>> + .version = LIBAVUTIL_VERSION_INT,
>> +};
>> +
>> +const AVInputFormat ff_dfpwm_demuxer = {
>> + .name = "dfpwm",
>> + .long_name = NULL_IF_CONFIG_SMALL("raw DFPWM1a data"),
>> + .priv_data_size = sizeof(DFPWMAudioDemuxerContext),
>> + .read_header = dfpwm_read_header,
>> + .read_packet = ff_pcm_read_packet,
>> + .read_seek = ff_pcm_read_seek,
>> + .flags = AVFMT_GENERIC_INDEX,
>> + .extensions = "dfpwm",
>> + .raw_codec_id = AV_CODEC_ID_DFPWM,
>> + .priv_class = &dfpwm_demuxer_class,
>> +};
>> \ No newline at end of file
>> diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c
>> index 4bbae77..17b627b 100644
>> --- a/libavformat/rawenc.c
>> +++ b/libavformat/rawenc.c
>> @@ -192,6 +192,19 @@ const AVOutputFormat ff_data_muxer = {
>> };
>> #endif
>> +#if CONFIG_DFPWM_MUXER
>> +const AVOutputFormat ff_dfpwm_muxer = {
>> + .name = "dfpwm",
>> + .long_name = NULL_IF_CONFIG_SMALL("raw DFPWM1a audio"),
>> + .extensions = "dfpwm",
>> + .audio_codec = AV_CODEC_ID_DFPWM,
>> + .video_codec = AV_CODEC_ID_NONE,
>> + .init = force_one_stream,
>> + .write_packet = ff_raw_write_packet,
>> + .flags = AVFMT_NOTIMESTAMPS,
>> +};
>> +#endif
>> +
>> #if CONFIG_DIRAC_MUXER
>> const AVOutputFormat ff_dirac_muxer = {
>> .name = "dirac",
>> diff --git a/libavformat/version.h b/libavformat/version.h
>> index 2623457..0f89af4 100644
>> --- a/libavformat/version.h
>> +++ b/libavformat/version.h
>> @@ -32,8 +32,8 @@
>> // 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 59
>> -#define LIBAVFORMAT_VERSION_MINOR 17
>> -#define LIBAVFORMAT_VERSION_MICRO 102
>> +#define LIBAVFORMAT_VERSION_MINOR 18
>> +#define LIBAVFORMAT_VERSION_MICRO 100
>> #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR,
>> \
>>
>> LIBAVFORMAT_VERSION_MINOR, \
>> --
>> 2.35.1
>>
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel at ffmpeg.org
>> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>
>> To unsubscribe, visit link above, or email
>> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".
More information about the ffmpeg-devel
mailing list