From: Paul B Mahol <onemda@gmail.com> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org> Subject: Re: [FFmpeg-devel] [PATCH] libavcodec, libavformat: Added DFPWM1a codec and raw format Date: Fri, 25 Feb 2022 09:15:42 +0100 Message-ID: <YhiQLhFObneHW+cK@archlinux> (raw) In-Reply-To: <43daccc7-c618-993e-912d-54e633e8c7f2@gmail.com> 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@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 > +@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. > +@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@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2022-02-25 8:14 UTC|newest] Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top 2022-02-25 7:54 Jack Bruienne 2022-02-25 8:15 ` Paul B Mahol [this message] 2022-02-25 23:42 ` Jack Bruienne
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=YhiQLhFObneHW+cK@archlinux \ --to=onemda@gmail.com \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git