From patchwork Tue Mar 8 03:29:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jack Bruienne X-Patchwork-Id: 34639 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6838:4285:0:0:0:0 with SMTP id wq5csp160162nkb; Mon, 7 Mar 2022 19:30:05 -0800 (PST) X-Google-Smtp-Source: ABdhPJxdi6kQ3kDRXqegP7VV5oFmWegM8D3D3A/5UuDO482hs+D7Dwm/O0SJbI4JRc6++ncXtzRb X-Received: by 2002:a17:907:60cf:b0:6da:95de:3920 with SMTP id hv15-20020a17090760cf00b006da95de3920mr11781692ejc.95.1646710205233; Mon, 07 Mar 2022 19:30:05 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1646710205; cv=none; d=google.com; s=arc-20160816; b=ikcV+0c6Xo5Cg032pHOV15YIwwttOYtMvgHJMBtNwvMVAmSk55BKBGrLR1V+poUspy IrMJzlruCBPqKRJh3inG6Eggks2vUFp6u5tweZVD0tCK5v+fJQKNENzJrcutj9wJdkEK mpSi2iM/5/p+1CHO07417+fXSILbM0OWt4v/QRuemMvoGNeJA1vwOycCy7LmH/QzxxwP cR8BhVKTQjNsPwhZay2SpdZJRc7l/GaWI36csiJ5yR/XYCnmMclIXRGFhPYKG32xFKB1 SyOB366qSPYEite0UKJfnkhxOaghK++QI/7G9TMvMqtyaJIe7kbxUhKiZ6YMD4mfiCFG Pj6A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject :content-language:to:from:user-agent:mime-version:date:message-id :dkim-signature:delivered-to; bh=btVcv05gdYLALzQW4aZuxe94N3Dg8XL/eaw2rBbZSmo=; b=admrDArsGP3c4LHhVAO1lfqVqiLf3DF/9Gbgj8B4MIBaUMiW6GJ28d6Ev8+ZyE+JdK ur0AvqKOGtLIequXyfOLw5pTAD+iDB1nccBGS0T9RbB5bLVGsQ/7kIw/vtyYFwOhzMcn MmHISM22iBKho0R42wEtXeClvxmgRSoVyBEj4u5TvVRV1nxjuighh8twtvM3/UXUSvPH 8u99APlWcISK5XiPFB3WgA2fKYWSrxHgef44Aoz/9dbNk5BbUCwc1nC6M1y/dmV++ve2 rvzTyVk4LSp/gIGzre9wDpvTe56dWKgNrWmfslB65u3e+C9jCylmlJ8aRqTdseC9sT+q Strw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=KB7TpgAT; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id ga25-20020a1709070c1900b006dab560c04asi7979794ejc.338.2022.03.07.19.30.04; Mon, 07 Mar 2022 19:30:05 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=KB7TpgAT; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9056D68B1D1; Tue, 8 Mar 2022 05:30:00 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-io1-f46.google.com (mail-io1-f46.google.com [209.85.166.46]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 41C2568B0A4 for ; Tue, 8 Mar 2022 05:29:54 +0200 (EET) Received: by mail-io1-f46.google.com with SMTP id x4so4592197iop.7 for ; Mon, 07 Mar 2022 19:29:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:date:mime-version:user-agent:from:subject:to :content-language; bh=VSKQtzwz3G7cccFnE7r+/d8AzLU85N9InY98cHh3q98=; b=KB7TpgAT4n13mEsGXQwSipAKL8L13uLIuwPsvGw5Bff5jfdpcXpymaxqRTCxlJaG4x iRZR3XFfV1dqlUp3MLT5DOTJCWSh7wXm6VLTI1tNQAgSEXd7JWse233ldu2ywh/FLy9R Lf6yAW7GpXNRdnf+s7dNZPxHdl2vuEaywl1PMj0+IzzaeTcVQpfRF8QzgNnT4nNmErhw d2U7P+vZ+vNqUhxq4f6D5Mn7rSsI7nhbAy6bNFV1OEwS4D1tOZ7CfyCK0Ib3/87dAVUn sjrvF8SY97uj8J7PsfpH8Ylw7CyYUXfSUXmkT0a9lZEFlTr/jHriYMc6DcKb4PLRLxES KosQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:date:mime-version:user-agent:from :subject:to:content-language; bh=VSKQtzwz3G7cccFnE7r+/d8AzLU85N9InY98cHh3q98=; b=pl90+qczF1FVosXLu/N2AoEcAENpCbJAhmlVhAdIzWeCAJfHQM2JNWmqoh9EOY+w+E wBnrsRhYmfzopALXOiEsgUpWkuK743eD8uGCLd/wtt9ycz3ztJmDfmnd8yvbVMfaPAjn z9FYgCfiYdrUq/UxmXcSNYMNQg6C8uCfzkFsXVGIObhciD/U+DqDQc5KnBeeysOdEEno pi5gC2VCZHU5ZnyEJJZ9AvqIck5+3ZSci6Zd/mwT5M6RXAKjarZZw6sCVWwc+Ja+eqZa 22xZBLuOKPONgFaoyR1TcJtGbTOQNVisyKppciaUaDX4Kn7GbsJ+rlnCbO6P8VNRJISd kdtw== X-Gm-Message-State: AOAM531KNnnzKmvkBg0WpcEQJjVR3BFDPB8rmoNqoC+BKAmlH/q2ogiw mqVxnJJtiEzMxt0ytFIH2qyMNr3VehUiHg== X-Received: by 2002:a05:6602:15d2:b0:645:61c9:dc92 with SMTP id f18-20020a05660215d200b0064561c9dc92mr12873727iow.94.1646710191894; Mon, 07 Mar 2022 19:29:51 -0800 (PST) Received: from [192.168.7.86] (c-68-40-205-18.hsd1.mi.comcast.net. [68.40.205.18]) by smtp.gmail.com with ESMTPSA id u9-20020a5d8189000000b006415781ebe5sm9980213ion.5.2022.03.07.19.29.50 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 07 Mar 2022 19:29:51 -0800 (PST) Message-ID: <595a810c-d14e-413f-8208-264154b3d9c9@gmail.com> Date: Mon, 7 Mar 2022 22:29:49 -0500 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.6.1 From: Jack Bruienne To: ffmpeg-devel@ffmpeg.org Content-Language: en-US Subject: [FFmpeg-devel] [PATCH v7 1/3] libavcodec: Added DFPWM1a codec X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: sv8Y/JyOa+qx 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 a new codec (with encoding and decoding) for DFPWM1a. The codec sources are pretty simple: they use the reference codec with a basic wrapper to connect it to the FFmpeg AVCodec system. To clarify, the codec does not have a specific sample rate - it is provided by the container (or user), which is typically 48000, but has also been known to be 32768. The codec does not specify channel info either, and it's pretty much always used with one mono channel. However, since it appears that libavcodec expects both sample rate and channel count to be handled by either the codec or container, I have made the decision to allow multiple channels interleaved, which as far as I know has never been used, but it works fine here nevertheless. The accompanying raw format has a channels option to set this. (I expect most users of this will not use multiple channels, but it remains an option just in case.) 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, and even fewer decoders. It will streamline the process for importing and listening to 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 " 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. Changes since v5: Moved channel check to init, and added sample size check in decoder. Changes since v4: Fixed missing channel check in decoder. Changes since v3: Added support for multiple interleaved channels, and cleaned up the code a bunch. Changes since v2: I've found that the reference encoder has a few errors, and sounds worse than the Java-based implementation that is used most often. I got in contact with someone who knows DFPWM much better than I do, and I worked with them to make a few adjustments that should improve the audio quality. I also made sure that the output matches the Java codec exactly, so it should have the exact same quality as other codecs. Signed-off-by: Jack Bruienne --- Changelog | 1 + MAINTAINERS | 1 + doc/general_contents.texi | 1 + libavcodec/Makefile | 2 + libavcodec/allcodecs.c | 2 + libavcodec/codec_desc.c | 7 ++ libavcodec/codec_id.h | 1 + libavcodec/dfpwmdec.c | 134 ++++++++++++++++++++++++++++++++++++++ libavcodec/dfpwmenc.c | 121 ++++++++++++++++++++++++++++++++++ libavcodec/utils.c | 2 + 10 files changed, 272 insertions(+) create mode 100644 libavcodec/dfpwmdec.c create mode 100644 libavcodec/dfpwmenc.c diff --git a/Changelog b/Changelog index 3af8aa0..f3249fe 100644 --- a/Changelog +++ b/Changelog @@ -5,6 +5,7 @@ version 5.1: - dialogue enhance audio filter - dropped obsolete XvMC hwaccel - pcm-bluray encoder +- DFPWM audio encoder/decoder version 5.0: diff --git a/MAINTAINERS b/MAINTAINERS index f33ccbd..57b6f33 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 diff --git a/doc/general_contents.texi b/doc/general_contents.texi index df1692c..14aeaed 100644 --- a/doc/general_contents.texi +++ b/doc/general_contents.texi @@ -1194,6 +1194,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 bfc31ba..cd929da 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 1be67e3..628d27f 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..81f3b3c 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("DFPWM (Dynamic Filter Pulse Width Modulation)"), + .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, /* 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..05f7944 --- /dev/null +++ b/libavcodec/dfpwmdec.c @@ -0,0 +1,134 @@ +/* + * 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 + +static void au_decompress(DFPWMState *state, int fs, int len, uint8_t *outbuf, uint8_t *inbuf) +{ + unsigned d; + for (int i = 0; i < len; i++) { + // get bits + d = *(inbuf++); + for (int 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) + 512)>>10); + if(nq == state->q && nq != t) + nq += (t == 127 ? 1 : -1); + lq = state->q; + state->q = nq; + + // adjust strength + st = (t != state->lt ? 0 : 1023); + ns = state->s; + if(ns != st) + ns += (st != 0 ? 1 : -1); + if(ns < 8) ns = 8; + state->s = ns; + + // FILTER: perform antijerk + ov = (t != state->lt ? (nq+lq+1)>>1 : nq); + + // FILTER: perform LPF + state->fq += ((fs*(ov-state->fq) + 0x80)>>8); + ov = state->fq; + + // output sample + *(outbuf++) = ov + 128; + + state->lt = t; + } + } +} + +static av_cold int dfpwm_dec_init(struct AVCodecContext *ctx) +{ + DFPWMState *state = ctx->priv_data; + + if (ctx->channels <= 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid number of channels\n"); + return AVERROR(EINVAL); + } + + state->fq = 0; + state->q = 0; + state->s = 0; + state->lt = -128; + + ctx->sample_fmt = AV_SAMPLE_FMT_U8; + ctx->bits_per_raw_sample = 8; + + return 0; +} + +static int dfpwm_dec_frame(struct AVCodecContext *ctx, void *data, + int *got_frame, struct AVPacket *packet) +{ + DFPWMState *state = ctx->priv_data; + AVFrame *frame = data; + int ret; + + frame->nb_samples = packet->size * 8 / ctx->channels; + if (frame->nb_samples <= 0) { + av_log(ctx, AV_LOG_ERROR, "invalid number of samples in packet\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(ctx, frame, 0)) < 0) + return ret; + + au_decompress(state, 140, packet->size, frame->data[0], packet->data); + + *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, + .decode = dfpwm_dec_frame, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, +}; diff --git a/libavcodec/dfpwmenc.c b/libavcodec/dfpwmenc.c new file mode 100644 index 0000000..02f2e64 --- /dev/null +++ b/libavcodec/dfpwmenc.c @@ -0,0 +1,121 @@ +/* + * 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 "encode.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 + +// note, len denotes how many compressed bytes there are (uncompressed bytes / 8). +static void au_compress(DFPWMState *state, int len, uint8_t *outbuf, uint8_t *inbuf) +{ + unsigned d = 0; + for (int i = 0; i < len; i++) { + for (int j = 0; j < 8; j++) { + int nq, st, ns; + // get sample + int v = *(inbuf++) - 128; + // set bit / target + int t = (v > state->q || (v == state->q && v == 127) ? 127 : -128); + d >>= 1; + if(t > 0) + d |= 0x80; + + // adjust charge + nq = state->q + ((state->s * (t-state->q) + 512)>>10); + if(nq == state->q && nq != t) + nq += (t == 127 ? 1 : -1); + state->q = nq; + + // adjust strength + st = (t != state->lt ? 0 : 1023); + ns = state->s; + if(ns != st) + ns += (st != 0 ? 1 : -1); + if(ns < 8) ns = 8; + state->s = ns; + + state->lt = t; + } + + // 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; + + ctx->bits_per_coded_sample = 1; + + return 0; +} + +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 * frame->channels / 8 + (frame->nb_samples % 8 > 0 ? 1 : 0); + int ret = ff_get_encode_buffer(ctx, packet, size, 0); + + if (ret) { + *got_packet = 0; + return ret; + } + + au_compress(state, size, packet->data, frame->data[0]); + + *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, + .encode2 = dfpwm_enc_frame, + .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NONE}, + .capabilities = AV_CODEC_CAP_DR1 | 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: From patchwork Tue Mar 8 03:29:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jack Bruienne X-Patchwork-Id: 34640 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6838:4285:0:0:0:0 with SMTP id wq5csp160233nkb; Mon, 7 Mar 2022 19:30:16 -0800 (PST) X-Google-Smtp-Source: ABdhPJz8W7p6qmrxJYsjD1FHLRix/JRK+yeacSswck/v5eRMA5x9QMspFnN58YjyUvkLFqZOFzxr X-Received: by 2002:a17:907:608f:b0:6da:8eec:ab87 with SMTP id ht15-20020a170907608f00b006da8eecab87mr11082422ejc.485.1646710215772; Mon, 07 Mar 2022 19:30:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1646710215; cv=none; d=google.com; s=arc-20160816; b=xbkEXNyxRu9GwKRnpgj3aaEgVqTU4LfxBehQUCemPc6qfWXnbiiH9SFYzK1O9x+Qw/ z590Kup1pZwMwXQNsjcmhwX21XEQlvkSanoXny1wHlUnw/LZBn5323dEx23c87LoFb6b T9ugVw8K2HH9uQCKqxDZ5udsbLvD8zogiZV0vtAwrRJ8ggCuJqLgXmGL+CwNdyiakomU 7MSxACiYeHBSHfwf5rrOIPeGNfDfAPE8pqb09MKnRexi2zPmXfLP2KQuF7e4DQrv4MrD QcFYGU1nhuG6+8OOSXp6mjU3R2HK1GzhbfW5+JycBEW/c5XZF7wdU0FSPoIfmVT0nakc 72iA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject :content-language:to:from:user-agent:mime-version:date:message-id :dkim-signature:delivered-to; bh=vNvxvhHHI9Tt1r6gyBR/pj26kS/WhARQE5+A+j+3ejY=; b=yYlayV3ewLEUB+u/eAx4/9lItb/s0L5repeSJaEY+aYEPyrzMA7lKVu+dfr4NIa5tz qXOyVcPuR/VSualgUM+FdD6920AQDee+Hr7tnm4YvVMwqjwfqQRgeN8EThhZ7ZYp6z3F e9M+6QsOFri9qRsT/J/1dLjH6AtXHtjqQUhdYed0XkAM3PfpARyhNsCaogPiuGoVVRAR 6mm1Xw5ZbCNI15T1enAwA+BhshsW3Ejgu0zbwWo8mGDyPaRbYvPf33MtAfBZ5UdVcI+z xSmMtDxt3D6T6W5SI8gnlBwLUaMnDiy8ouLoL0R3ON+rFI3mTe/u1+ppwEqjhClitJ8Q Bdlw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=epcxiSpc; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id f2-20020a1709067f8200b006d0edf83954si8687711ejr.666.2022.03.07.19.30.15; Mon, 07 Mar 2022 19:30:15 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=epcxiSpc; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 90A5668B1E6; Tue, 8 Mar 2022 05:30:06 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-io1-f53.google.com (mail-io1-f53.google.com [209.85.166.53]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id D11C668A958 for ; Tue, 8 Mar 2022 05:30:00 +0200 (EET) Received: by mail-io1-f53.google.com with SMTP id b16so5183987ioz.3 for ; Mon, 07 Mar 2022 19:30:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:date:mime-version:user-agent:from:subject:to :content-language; bh=hNWchkwgfMGBNrQfJ7bPpcJx3W/oCYmsOwP09LmPMKQ=; b=epcxiSpc6X9mU9rm//wnNYQi9z6tHVgD2GJKMpOvwR2EX/JYM9a8sq4+2Hx5Fq3lPr gE68M7tva/i9WoTCubeChVPriYPH9p77Dw6rWQgkBT+yKDc5/NPVe0DBWMmLaD5yj94n +OXKKj0jdVBJeZMnIYprR5DjYGC5CykQvan4Toxzq9XCAlKK9rxusXo45Gy9VVVQ3edI hFLbIsDhuQiT9Gm63Z+eJ/VsBmbCFEJbbqHNbyjcWJpJxDrCA0vgirFHvVgHwMlhy6A1 f8x+US0IU3I2aKlByIet9He9ZF6DYGeRjYn5q/CSU2TgrX6a0h3uKjryijifHxdL6cN8 JsDA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:date:mime-version:user-agent:from :subject:to:content-language; bh=hNWchkwgfMGBNrQfJ7bPpcJx3W/oCYmsOwP09LmPMKQ=; b=3PKFAxs6IxtjjJCf+TB5peVXxizxFn2lCGoZ1nhCrfTHQ+ZGfB0RT/fCbnBp7U6/qr fvXON0rzMBote3Tr4SZXWFJ5DSPL+VpRv48Db5xR/YOzHerOu8vaJnFZIICf1DlpZwGg Hy8ueD6sjebVp/+CM6UGna5AsZbobVTqmkkOE16kBBdE6WJhVTd7+2pSVE2BGlGKfzI2 v8t9qloyo87OiYryTe+nNzSVaigXl6Vw+UpRmWffSzIe+upQ/G6FGtq9j4zFHu6QSH/T pHkKmJggjpVtU90Qa04Y7qY+kcm9eP4a+6d5fIB8z3P3nmoO2BrP0fqY00pLnUMgAGcT Mp0w== X-Gm-Message-State: AOAM531t8kNCe8b1cid8qkCs0C+2NPdNkNsC9BIgZSpGUBgEeod5TEPS 1djJye2jNbzwiOOBPV5FCc7Efxbg//NEBA== X-Received: by 2002:a05:6638:22c3:b0:30a:2226:e601 with SMTP id j3-20020a05663822c300b0030a2226e601mr13679984jat.237.1646710199171; Mon, 07 Mar 2022 19:29:59 -0800 (PST) Received: from [192.168.7.86] (c-68-40-205-18.hsd1.mi.comcast.net. [68.40.205.18]) by smtp.gmail.com with ESMTPSA id s13-20020a6bdc0d000000b006408888551dsm9584585ioc.8.2022.03.07.19.29.58 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 07 Mar 2022 19:29:58 -0800 (PST) Message-ID: <08b63a0d-bb01-cabf-62d4-ddb561b5c1ce@gmail.com> Date: Mon, 7 Mar 2022 22:29:57 -0500 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.6.1 From: Jack Bruienne To: ffmpeg-devel@ffmpeg.org Content-Language: en-US Subject: [FFmpeg-devel] [PATCH v7 2/3] libavformat: Add DFPWM raw format X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 2mKgriY6pwlE This patch builds on my previous DFPWM codec patch, adding 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 muxers are mostly copied from the PCM demuxer and the raw muxers, as DFPWM is typically stored as raw data. Please see the previous patch for more information on DFPWM. Changes since v4: Fixed descriptions of formats. Changes since v2/v3: Removed unused MIME parsing code, and added channels option. Signed-off-by: Jack Bruienne --- Changelog | 2 +- MAINTAINERS | 1 + doc/general_contents.texi | 1 + libavformat/Makefile | 2 + libavformat/allformats.c | 2 + libavformat/dfpwmdec.c | 82 +++++++++++++++++++++++++++++++++++++++ libavformat/rawenc.c | 13 +++++++ libavformat/version.h | 4 +- 8 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 libavformat/dfpwmdec.c diff --git a/Changelog b/Changelog index f3249fe..ac614f8 100644 --- a/Changelog +++ b/Changelog @@ -5,7 +5,7 @@ version 5.1: - dialogue enhance audio filter - dropped obsolete XvMC hwaccel - pcm-bluray encoder -- DFPWM audio encoder/decoder +- DFPWM audio encoder/decoder and raw muxer/demuxer version 5.0: diff --git a/MAINTAINERS b/MAINTAINERS index 57b6f33..931cf4b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -416,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 14aeaed..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 diff --git a/libavformat/Makefile b/libavformat/Makefile index 16d019d..322c8e7 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -166,6 +166,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..85d9b61 --- /dev/null +++ b/libavformat/dfpwmdec.c @@ -0,0 +1,82 @@ +/* + * 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; + int channels; +} DFPWMAudioDemuxerContext; + +static int dfpwm_read_header(AVFormatContext *s) +{ + DFPWMAudioDemuxerContext *s1 = s->priv_data; + AVCodecParameters *par; + AVStream *st; + + 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 = s1->channels; + par->bits_per_coded_sample = 1; + 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 = 48000}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { "channels", "", offsetof(DFPWMAudioDemuxerContext, channels), AV_OPT_TYPE_INT, {.i64 = 1}, 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"), + .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..f8c267c 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"), + .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 05688e3..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 103 +#define LIBAVFORMAT_VERSION_MINOR 18 +#define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From patchwork Tue Mar 8 03:30:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jack Bruienne X-Patchwork-Id: 34641 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6838:4285:0:0:0:0 with SMTP id wq5csp160463nkb; Mon, 7 Mar 2022 19:30:38 -0800 (PST) X-Google-Smtp-Source: ABdhPJwZeiLTeCTSbtdLI0viuU/pFYav5nhHMYABKR5wXjdfMQv55CrGQYJiTfZg0bWzSs1K2TWU X-Received: by 2002:a17:906:610:b0:6d6:e68b:136 with SMTP id s16-20020a170906061000b006d6e68b0136mr11930095ejb.332.1646710237697; Mon, 07 Mar 2022 19:30:37 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1646710237; cv=none; d=google.com; s=arc-20160816; b=lTsJwZeeXmfq/rWec/XJr7buUrltnd7ZHdOeJp4tZPEaE7onAwCqoYUQxlF1ZW4bHm J8m5U31G0T5MH2cl5uNSlWT4iLfmH9I0ogs+R3jxrtevtv8vbltYDF2drjx+Z65aRv7S acpcdFwv4W4Rlkxe3/rNOckeOZWPHLjPvJNFaNVh5R9KbkT2JDCF6yToglzC5ijKlTjM vWZAbj+AwQ2Lw6HV2Mvb497IkL9YFHUUJ6T6FS6sdM1urTFWzVNqxAC/oV1bgxVwRYR1 ezVog9bjbWcdRhTL1J2ZCNv9HsmrJ+ktjqtIIu8KM8J2zaicpXc30CjfoXxvUwXdqncV MRzQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject :content-language:to:from:user-agent:mime-version:date:message-id :dkim-signature:delivered-to; bh=C5fQPzmucSiayxLRPY0zd8+4tNT0D8cKKC22KbF35o4=; b=cv00lPf1uj2H5IUZ+DcLE96NJTt6qxxl7u9unCtiQu5ppUifZy9zeZiFxUMYJ+ihRk VpCATAo0oD0UW/BwPRtHwOUaHAy77oiHGEJ7jhuNO1ylBejrFN5s9ptKSafw/LsMN2q8 xUc03hNVCh2Dw0s7DAfEHkzFzGCRZkWB8nSon0ORtwdSk9ifYHdSBs9VosBx2pFhvQKE CwQ9zHa6caNvfntrDOFWwePIdPLhWUzwbRmXphBlRjTYhb/nRYUeM1xXPcjqW4z93cAo 4rufDN8dmkAOgIU9ij1QLewsZVWOF/dgBWBGf3oRHHC/x6a6jzAhspo6SuP5GA/y3GtA iUUQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=K7WHb6qE; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id g15-20020a056402424f00b004139bbefb4fsi10858870edb.317.2022.03.07.19.30.37; Mon, 07 Mar 2022 19:30:37 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=K7WHb6qE; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 7500368B204; Tue, 8 Mar 2022 05:30:34 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-io1-f42.google.com (mail-io1-f42.google.com [209.85.166.42]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2BEBC68AF0A for ; Tue, 8 Mar 2022 05:30:27 +0200 (EET) Received: by mail-io1-f42.google.com with SMTP id k25so3667499iok.8 for ; Mon, 07 Mar 2022 19:30:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:date:mime-version:user-agent:from:subject:to :content-language; bh=E3xtX42oPm7x8AOpjSwS8p2AqT02xymL5otvnR/ZWpU=; b=K7WHb6qEV26Z9kY663hCveqHCDIeSwU36m8G2EstwN9nn51i1bx2cKIPk4zevL0A8e UVWs2nzDE4/3JnDPXxsqAyhS2BzixN7VsMsf+mEceaRFTluBl7pj88iTcBQbCTq06x4E qYaB+8k89/pQMZNBv2mIM/lG6voDX8BBoZV+j68QUjRmsAjCxpXGXCZJVSc5uqqnRva5 qMcDIaxLhhuBfBNG78SxKQvYEwA2uKOBB1zg7svfXA1IiycAtMxf6PvMlcBVnjlZiplW 28AmuYSGTHNWHtgMW+lBDpIjVK/32UIDSDZUjvpHOSnZRivIQ6+SOCAGqqcYLkYcYhgk AgKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:date:mime-version:user-agent:from :subject:to:content-language; bh=E3xtX42oPm7x8AOpjSwS8p2AqT02xymL5otvnR/ZWpU=; b=OBViIj6mO2iKrSHWSkgM0TLIkp93Z3O6gKAmGbsbTugHyGfpEHRk4VEtAREGSg5asm lV5i2fcAVeEsRsuOQ05/lPVJmI/x/jlyBOyOZh6Lej7rwuNNFYgFwlCdcSRpKPNwImn+ da4vk2aijvTkv/Zg3t2mygsSwqSVL73PW0/GjwS6VqKLUhCwex0K6aL0lNOfbpJM61fU D6DjRSkEhQpUdXhFMy+9wTtPRnczqlIur3QYzgw8KujFF6QNwJr0hivxMhojUfQiKr4k 0cpaaRylB4Cp08jnwHnxOAq11bUxKBfLGhD3DsMXzXZnZfBKfWjghY4Vp30oyuRADWLq EkxA== X-Gm-Message-State: AOAM533MvyKOsDmlXnB1Uhzu914alqJ2hQ9+w+3FoYc7THH1gtyn8FFX unTx4Qbd7UDnjBJgrvIQC3axy4ezpLNKqg== X-Received: by 2002:a6b:c842:0:b0:645:c339:38c7 with SMTP id y63-20020a6bc842000000b00645c33938c7mr7216828iof.26.1646710225569; Mon, 07 Mar 2022 19:30:25 -0800 (PST) Received: from [192.168.7.86] (c-68-40-205-18.hsd1.mi.comcast.net. [68.40.205.18]) by smtp.gmail.com with ESMTPSA id i3-20020a056602134300b0064620a85b6dsm612785iov.12.2022.03.07.19.30.24 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 07 Mar 2022 19:30:24 -0800 (PST) Message-ID: <193e12fa-5bea-5fab-6def-a5ebd3a4be63@gmail.com> Date: Mon, 7 Mar 2022 22:30:24 -0500 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.6.1 From: Jack Bruienne To: ffmpeg-devel@ffmpeg.org Content-Language: en-US Subject: [FFmpeg-devel] [PATCH v7 3/3] libavformat: Added DFPWM WAV container support X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: nPCLuD5d6541 This commit adds support for storing DFPWM audio in a WAV container. It uses the WAVEFORMATEXTENSIBLE structure, following these conventions: https://gist.github.com/MCJack123/90c24b64c8e626c7f130b57e9800962c The implementation is very simple: it just adds the GUID to the list of WAV GUIDs, and modifies the WAV muxer to always use WAVEFORMATEXTENSIBLE format with that GUID. This creates a standard container format for DFPWM besides raw data. It will allow users to transfer DFPWM audio in a standard container format, with the sample rate and channel count contained in the file as opposed to being an external parameter as in the raw format. This format is already supported in my AUKit library, which is the CC analog to libav (albeit much smaller). Support in other applications is TBD. Signed-off-by: Jack Bruienne --- libavformat/riff.c | 3 +++ libavformat/riffenc.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libavformat/riff.c b/libavformat/riff.c index 0c19d3f..f098c1d 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -587,6 +587,8 @@ const AVCodecTag ff_codec_wav_tags[] = { { AV_CODEC_ID_AAC, 0xA106 }, { AV_CODEC_ID_SPEEX, 0xA109 }, { AV_CODEC_ID_FLAC, 0xF1AC }, + /* DFPWM does not have an assigned format tag; it uses a GUID in WAVEFORMATEX instead */ + { AV_CODEC_ID_DFPWM, 0xFFFE }, { AV_CODEC_ID_ADPCM_SWF, ('S' << 8) + 'F' }, /* HACK/FIXME: Does Vorbis in WAV/AVI have an (in)official ID? */ { AV_CODEC_ID_VORBIS, ('V' << 8) + 'o' }, @@ -637,5 +639,6 @@ const AVCodecGuid ff_codec_wav_guids[] = { { AV_CODEC_ID_EAC3, { 0xAF, 0x87, 0xFB, 0xA7, 0x02, 0x2D, 0xFB, 0x42, 0xA4, 0xD4, 0x05, 0xCD, 0x93, 0x84, 0x3B, 0xDD } }, { AV_CODEC_ID_MP2, { 0x2B, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA } }, { AV_CODEC_ID_ADPCM_AGM,{ 0x82, 0xEC, 0x1F, 0x6A, 0xCA, 0xDB, 0x19, 0x45, 0xBD, 0xE7, 0x56, 0xD3, 0xB3, 0xEF, 0x98, 0x1D } }, + { AV_CODEC_ID_DFPWM, { 0x3A, 0xC1, 0xFA, 0x38, 0x81, 0x1D, 0x43, 0x61, 0xA4, 0x0D, 0xCE, 0x53, 0xCA, 0x60, 0x7C, 0xD1 } }, { AV_CODEC_ID_NONE } }; diff --git a/libavformat/riffenc.c b/libavformat/riffenc.c index ffccfa3..96750e7 100644 --- a/libavformat/riffenc.c +++ b/libavformat/riffenc.c @@ -81,7 +81,7 @@ int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb, par->channels == 1 && par->channel_layout && par->channel_layout != AV_CH_LAYOUT_MONO || par->channels == 2 && par->channel_layout && par->channel_layout != AV_CH_LAYOUT_STEREO || par->sample_rate > 48000 || - par->codec_id == AV_CODEC_ID_EAC3 || + par->codec_id == AV_CODEC_ID_EAC3 || par->codec_id == AV_CODEC_ID_DFPWM || av_get_bits_per_sample(par->codec_id) > 16; if (waveformatextensible) @@ -188,7 +188,7 @@ int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb, /* dwChannelMask */ avio_wl32(pb, write_channel_mask ? par->channel_layout : 0); /* GUID + next 3 */ - if (par->codec_id == AV_CODEC_ID_EAC3) { + if (par->codec_id == AV_CODEC_ID_EAC3 || par->codec_id == AV_CODEC_ID_DFPWM) { ff_put_guid(pb, ff_get_codec_guid(par->codec_id, ff_codec_wav_guids)); } else { avio_wl32(pb, par->codec_tag);