On 2/5/2022, "Paul B Mahol" <one...@gmail.com> wrote:
>Only patches for master are accepted.
>
>No more wrappers.
>
>Thanks.

Hi Paul,

Please find attached the libmad MP3 decoding patch against the master
(ffmpeg-master-b67572c).

I'm not sure what "No more wrappers" means?

Best regards, David.
diff -Nur ./ffmpeg-master-b67572c/configure ./ffmpeg-master-b67572c-libmad/configure
--- ./ffmpeg-master-b67572c/configure	2022-05-02 16:10:22.000000000 +0100
+++ ./ffmpeg-master-b67572c-libmad/configure	2022-05-02 17:56:30.772026904 +0100
@@ -245,6 +245,7 @@
   --enable-libklvanc       enable Kernel Labs VANC processing [no]
   --enable-libkvazaar      enable HEVC encoding via libkvazaar [no]
   --enable-liblensfun      enable lensfun lens correction [no]
+  --enable-libmad          enable MP3 decoding via libmad [no]
   --enable-libmodplug      enable ModPlug via libmodplug [no]
   --enable-libmp3lame      enable MP3 encoding via libmp3lame [no]
   --enable-libopencore-amrnb enable AMR-NB de/encoding via libopencore-amrnb [no]
@@ -1775,6 +1776,7 @@
     frei0r
     libcdio
     libdavs2
+    libmad
     librubberband
     libvidstab
     libx264
@@ -3339,6 +3341,7 @@
 libjxl_encoder_deps="libjxl libjxl_threads"
 libkvazaar_encoder_deps="libkvazaar"
 libmodplug_demuxer_deps="libmodplug"
+libmad_decoder_deps="libmad"
 libmp3lame_encoder_deps="libmp3lame"
 libmp3lame_encoder_select="audio_frame_queue mpegaudioheader"
 libopencore_amrnb_decoder_deps="libopencore_amrnb"
@@ -6572,6 +6575,7 @@
 fi
 
 enabled libmodplug        && require_pkg_config libmodplug libmodplug libmodplug/modplug.h ModPlug_Load
+enabled libmad            && require libmad "mad.h" mad_decoder_init -lmad
 enabled libmp3lame        && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame $libm_extralibs
 enabled libmysofa         && { check_pkg_config libmysofa libmysofa mysofa.h mysofa_neighborhood_init_withstepdefine ||
                                require libmysofa mysofa.h mysofa_neighborhood_init_withstepdefine -lmysofa $zlib_extralibs; }
diff -Nur ./ffmpeg-master-b67572c/libavcodec/Makefile ./ffmpeg-master-b67572c-libmad/libavcodec/Makefile
--- ./ffmpeg-master-b67572c/libavcodec/Makefile	2022-05-02 16:10:22.000000000 +0100
+++ ./ffmpeg-master-b67572c-libmad/libavcodec/Makefile	2022-05-02 17:56:30.772026904 +0100
@@ -1065,6 +1065,7 @@
 OBJS-$(CONFIG_LIBJXL_DECODER)             += libjxldec.o libjxl.o
 OBJS-$(CONFIG_LIBJXL_ENCODER)             += libjxlenc.o libjxl.o
 OBJS-$(CONFIG_LIBKVAZAAR_ENCODER)         += libkvazaar.o
+OBJS-$(CONFIG_LIBMAD_DECODER)             += libmaddec.o
 OBJS-$(CONFIG_LIBMP3LAME_ENCODER)         += libmp3lame.o
 OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER)  += libopencore-amr.o
 OBJS-$(CONFIG_LIBOPENCORE_AMRNB_ENCODER)  += libopencore-amr.o
diff -Nur ./ffmpeg-master-b67572c/libavcodec/allcodecs.c ./ffmpeg-master-b67572c-libmad/libavcodec/allcodecs.c
--- ./ffmpeg-master-b67572c/libavcodec/allcodecs.c	2022-05-02 16:10:22.000000000 +0100
+++ ./ffmpeg-master-b67572c-libmad/libavcodec/allcodecs.c	2022-05-02 17:56:30.773026904 +0100
@@ -744,6 +744,7 @@
 extern const FFCodec ff_libdav1d_decoder;
 extern const FFCodec ff_libdavs2_decoder;
 extern const FFCodec ff_libfdk_aac_encoder;
+extern const AVCodec ff_libmad_decoder;
 extern const FFCodec ff_libfdk_aac_decoder;
 extern const FFCodec ff_libgsm_encoder;
 extern const FFCodec ff_libgsm_decoder;
diff -Nur ./ffmpeg-master-b67572c/libavcodec/codec_id.h ./ffmpeg-master-b67572c-libmad/libavcodec/codec_id.h
--- ./ffmpeg-master-b67572c/libavcodec/codec_id.h	2022-05-02 16:10:22.000000000 +0100
+++ ./ffmpeg-master-b67572c-libmad/libavcodec/codec_id.h	2022-05-02 18:01:05.995035711 +0100
@@ -519,6 +519,7 @@
     AV_CODEC_ID_FASTAUDIO,
     AV_CODEC_ID_MSNSIREN,
     AV_CODEC_ID_DFPWM,
+    AV_CODEC_ID_LIBMAD,
 
     /* subtitle codecs */
     AV_CODEC_ID_FIRST_SUBTITLE = 0x17000,          ///< A dummy ID pointing at the start of subtitle codecs.
diff -Nur ./ffmpeg-master-b67572c/libavcodec/libmaddec.c ./ffmpeg-master-b67572c-libmad/libavcodec/libmaddec.c
--- ./ffmpeg-master-b67572c/libavcodec/libmaddec.c	1970-01-01 01:00:00.000000000 +0100
+++ ./ffmpeg-master-b67572c-libmad/libavcodec/libmaddec.c	2022-05-02 18:11:33.062055778 +0100
@@ -0,0 +1,181 @@
+/*
+ * MP3 decoder using libmad
+ * Copyright (c) 2022 David Fletcher
+ *
+ * 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 <mad.h>
+
+#include "libavutil/channel_layout.h"
+#include "libavutil/common.h"
+#include "avcodec.h"
+#include "internal.h"
+#include "decode.h"
+
+#define MAD_BUFSIZE (32 * 1024)
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+typedef struct libmad_context {
+    uint8_t input_buffer[MAD_BUFSIZE+MAD_BUFFER_GUARD];
+    struct mad_synth  synth; 
+    struct mad_stream stream;
+    struct mad_frame  frame;
+    struct mad_header header;
+    int got_header;
+}libmad_context;		
+
+/* utility to scale and round samples to 16 bits */
+static inline signed int mad_scale(mad_fixed_t sample)
+{
+     /* round */
+     sample += (1L << (MAD_F_FRACBITS - 16));
+ 
+     /* clip */
+     if (sample >= MAD_F_ONE)
+         sample = MAD_F_ONE - 1;
+     else if (sample < -MAD_F_ONE)
+         sample = -MAD_F_ONE;
+    
+     /* quantize */
+     return sample >> (MAD_F_FRACBITS + 1 - 16);
+}
+
+static av_cold int libmad_decode_init(AVCodecContext *avc)
+{
+     libmad_context *mad = avc->priv_data;
+
+     mad_synth_init  (&mad->synth);
+     mad_stream_init (&mad->stream);
+     mad_frame_init  (&mad->frame);
+     mad->got_header = 0;
+
+     return 0;
+}
+
+static av_cold int libmad_decode_close(AVCodecContext *avc)
+{
+     libmad_context *mad = avc->priv_data;
+
+     mad_synth_finish(&mad->synth);
+     mad_frame_finish(&mad->frame);
+     mad_stream_finish(&mad->stream);
+
+     mad = NULL;
+    
+     return 0;
+}
+
+static int libmad_decode_frame(AVCodecContext *avc, void *data,
+                          int *got_frame_ptr, AVPacket *pkt)
+{
+     AVFrame *frame = data;
+     libmad_context *mad = avc->priv_data;
+     struct mad_pcm *pcm;
+     mad_fixed_t const *left_ch;
+     mad_fixed_t const *right_ch;
+     int16_t *output;
+     int nsamples;
+     int nchannels;
+     size_t bytes_read = 0;
+     size_t remaining = 0;
+     
+     if (!avc)
+	 return 0;
+     
+     if (!mad)
+	 return 0;
+     
+     remaining = mad->stream.bufend - mad->stream.next_frame;
+     memmove(mad->input_buffer, mad->stream.next_frame, remaining);
+     bytes_read = MIN(pkt->size, MAD_BUFSIZE - remaining);
+     memcpy(mad->input_buffer+remaining, pkt->data, bytes_read);
+     
+     if (bytes_read == 0){
+	 *got_frame_ptr = 0;
+	 return 0;
+     }
+     
+     mad_stream_buffer(&mad->stream, mad->input_buffer, remaining + bytes_read);
+     mad->stream.error = 0;
+     
+     if(!mad->got_header){
+	 mad_header_decode(&mad->header, &mad->stream);
+	 mad->got_header = 1;
+	 avc->frame_size = 32 * (mad->header.layer == MAD_LAYER_I ? 12 : \
+				 ((mad->header.layer == MAD_LAYER_III && \
+				   (mad->header.flags & MAD_FLAG_LSF_EXT)) ? 18 : 36));
+	 avc->sample_fmt = AV_SAMPLE_FMT_S16;
+	 if(mad->header.mode == MAD_MODE_SINGLE_CHANNEL){
+	     avc->channel_layout = AV_CH_LAYOUT_MONO;
+	     avc->channels = 1;
+	 }else{
+	     avc->channel_layout = AV_CH_LAYOUT_STEREO;
+	     avc->channels = 2;
+	 }
+     }
+     
+     frame->channel_layout = avc->channel_layout;
+     frame->format = avc->sample_fmt;
+     frame->channels = avc->channels;
+     frame->nb_samples = avc->frame_size; 
+     
+     if ((ff_get_buffer(avc, frame, 0)) < 0)
+	 return 0;
+     
+     if (mad_frame_decode(&mad->frame, &mad->stream) == -1) {
+	 *got_frame_ptr = 0;
+	 return mad->stream.bufend - mad->stream.next_frame;
+     }
+     
+     mad_synth_frame (&mad->synth, &mad->frame);
+     
+     pcm = &mad->synth.pcm;
+     output = (int16_t *)frame->data[0];
+     nsamples = pcm->length;
+     nchannels = pcm->channels;
+     left_ch = pcm->samples[0];
+     right_ch = pcm->samples[1];
+     while (nsamples--) {
+	 *output++ = mad_scale(*(left_ch++));
+	 if (nchannels == 2) {
+	     *output++ = mad_scale(*(right_ch++));
+	 }
+	 //Players should recognise mono and play through both channels
+	 //Writing the same thing to both left and right channels here causes
+	 //memory issues as it creates double the number of samples allocated.
+     }
+     
+     *got_frame_ptr = 1;
+     
+     return mad->stream.bufend - mad->stream.next_frame;
+}
+
+AVCodec ff_libmad_decoder = {
+    .name           = "libmad",
+    .long_name      = NULL_IF_CONFIG_SMALL("libmad MP3 decoder"),
+    .wrapper_name   = "libmad",
+    .type           = AVMEDIA_TYPE_AUDIO,
+    .id             = AV_CODEC_ID_MP3,
+    .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE },
+    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
+    .priv_data_size = sizeof(libmad_context),
+    .init           = libmad_decode_init,
+    .close          = libmad_decode_close,
+    .decode         = libmad_decode_frame
+};
+
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to