[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