[MPlayer-dev-eng] Re: [PATCH] encoding audio with libavcodec

Nico nsabbi at libero.it
Mon Nov 3 08:42:01 CET 2003


Hi,

IMO audio encoding parameters should be totally indipendent from video 
lavc ones, so
I wouldn't keep a unified lavc structure as you did.

Thanks for your patch !!  I'll test it as soon as I can


Tobias Diedrich wrote:

>I wrote:
>  
>
>>[imaadpcm] sound is distorted a bit.
>>    
>>
>
>This seems to be a bug in the libavcodec encoder...
>Except for that it's working fine for me now.
>
>Arpi, can you comment on the muxer_avi change?
>This basically reverts the r1.4->r1.5 change (log message "fixed AVI header
>creation - now should be compatible with NaNdub"), the offending line is
>
>|#define WFSIZE(wf) (sizeof(WAVEFORMATEX)+(((wf)->cbSize)?((wf)->cbSize-2):0))
>
>which unconditionally subtracts 2 from cbSize.  For MP3 audio Virtualdub
>complains the header is too short (30 vs. 28 bytes) and for adpcm the 2
>additional bytes are not written at all.
>
>I think
>#define WFSIZE(wf) (sizeof(WAVEFORMATEX)+(wf)->cbSize)
>should be correct.
>
>  
>
>------------------------------------------------------------------------
>
>Index: mencoder.c
>===================================================================
>RCS file: /cvsroot/mplayer/main/mencoder.c,v
>retrieving revision 1.219
>diff -u -r1.219 mencoder.c
>--- mencoder.c	22 Oct 2003 17:04:15 -0000	1.219
>+++ mencoder.c	3 Nov 2003 00:06:31 -0000
>@@ -14,6 +14,7 @@
> #define ACODEC_PCM 1
> #define ACODEC_VBRMP3 2
> #define ACODEC_NULL 3
>+#define ACODEC_LAVC 4
> 
> #include <stdio.h>
> #include <stdlib.h>
>@@ -71,6 +72,21 @@
> 
> #include "osdep/timer.h"
> 
>+#ifdef USE_LIBAVCODEC
>+// for lavc audio encoding
>+#include "libavcodec/avcodec.h"
>+static AVCodec        *lavc_acodec;
>+static AVCodecContext *lavc_actx = NULL;
>+extern char    *lavc_param_acodec;
>+extern int      lavc_param_abitrate;
>+extern int      lavc_param_atag;
>+// tmp buffer for lavc audio encoding (to free!!!!!)
>+static void    *lavc_abuf = NULL;
>+extern int      avcodec_inited;
>+
>+static uint32_t lavc_find_atag(char *codec);
>+#endif
>+
> int vo_doublebuffering=0;
> int vo_directrendering=0;
> int vo_config_count=0;
>@@ -792,6 +808,151 @@
>     }
>     break;
> #endif
>+#ifdef USE_LIBAVCODEC
>+case ACODEC_LAVC:
>+    if(! lavc_param_acodec)
>+    {
>+       mp_msg(MSGT_MENCODER, MSGL_FATAL, "Audio LAVC, Missing codec name!\n");
>+       exit(1);
>+    }
>+
>+    if (!avcodec_inited){
>+       avcodec_init();
>+       avcodec_register_all();
>+       avcodec_inited=1;
>+    }
>+
>+    lavc_acodec = avcodec_find_encoder_by_name(lavc_param_acodec);
>+    if (!lavc_acodec)
>+    {
>+       mp_msg(MSGT_MENCODER, MSGL_FATAL, "Audio LAVC, couldn't find encoder for codec %s\n", lavc_param_acodec);
>+       exit(1);
>+    }
>+
>+    lavc_actx = avcodec_alloc_context();
>+    if(lavc_actx == NULL)
>+    {
>+       mp_msg(MSGT_MENCODER, MSGL_FATAL, "Audio LAVC, couldn't allocate context!\n");
>+       exit(1);
>+    }
>+
>+    if(lavc_param_atag == 0)
>+        lavc_param_atag = lavc_find_atag(lavc_param_acodec);
>+
>+    // put sample parameters
>+    lavc_actx->channels = audio_output_channels ? audio_output_channels : sh_audio->channels;
>+    lavc_actx->sample_rate = force_srate ? force_srate : sh_audio->samplerate;
>+    lavc_actx->bit_rate = lavc_param_abitrate * 1000;
>+
>+    /*
>+     * Special case for imaadpcm.
>+     * The bitrate is only dependant on samplerate.
>+     * We have to known frame_size and block_align in advance,
>+     * so I just copied the code from libavcodec/adpcm.c
>+     *
>+     * However, ms imaadpcm uses a block_align of 2048,
>+     * lavc defaults to 1024
>+     */
>+    if(lavc_param_atag == 0x11) {
>+        int blkalign = 2048;
>+        int framesize = (blkalign - 4 * lavc_actx->channels) * 8 / (4 * lavc_actx->channels) + 1;
>+        lavc_actx->bit_rate = lavc_actx->sample_rate*8*blkalign/framesize;
>+    }
>+
>+    if(avcodec_open(lavc_actx, lavc_acodec) < 0)
>+    {
>+       mp_msg(MSGT_MENCODER, MSGL_FATAL, "Couldn't open codec %s, br=%d\n", lavc_param_acodec, lavc_param_abitrate);
>+       exit(1);
>+    }
>+
>+    if(lavc_param_atag == 0x11) {
>+        lavc_actx->block_align = 2048;
>+	lavc_actx->frame_size = (lavc_actx->block_align - 4 * lavc_actx->channels) * 8 / (4 * lavc_actx->channels) + 1;
>+    }
>+
>+    lavc_abuf = malloc(lavc_actx->frame_size * 2 * lavc_actx->channels);
>+    if(lavc_abuf == NULL)
>+    {
>+       fprintf(stderr, "Couldn't allocate %d bytes\n", lavc_actx->frame_size * 2 * lavc_actx->channels);
>+       exit(1);
>+    }
>+
>+    if (sizeof(MPEGLAYER3WAVEFORMAT) != 30)
>+       mp_msg(MSGT_MENCODER, MSGL_WARN,
>+              "sizeof(MPEGLAYER3WAVEFORMAT)==%d!=30, maybe broken C compiler?\n",
>+              sizeof(MPEGLAYER3WAVEFORMAT));
>+
>+    mux_a->wf = malloc(sizeof(MPEGLAYER3WAVEFORMAT));  // should be 30
>+    mux_a->wf->wFormatTag = lavc_param_atag;
>+    mux_a->wf->nChannels = lavc_actx->channels;
>+    mux_a->wf->nSamplesPerSec = lavc_actx->sample_rate;
>+    mux_a->wf->nAvgBytesPerSec = (lavc_actx->bit_rate / 8);
>+    mux_a->h.dwRate = mux_a->wf->nAvgBytesPerSec;
>+    if (lavc_actx->block_align) {
>+	mux_a->h.dwSampleSize = mux_a->h.dwScale = lavc_actx->block_align;
>+    } else {
>+	mux_a->h.dwScale = (mux_a->wf->nAvgBytesPerSec * lavc_actx->frame_size)/ mux_a->wf->nSamplesPerSec; /* for cbr */
>+
>+	if ((mux_a->wf->nAvgBytesPerSec *
>+	    lavc_actx->frame_size) % mux_a->wf->nSamplesPerSec) {
>+	    mux_a->h.dwScale = lavc_actx->frame_size;
>+	    mux_a->h.dwRate = lavc_actx->sample_rate;
>+	    mux_a->h.dwSampleSize = 0; // Blocksize not constant
>+	} else {
>+	    mux_a->h.dwSampleSize = mux_a->h.dwScale;
>+	}
>+    }
>+    mux_a->wf->nBlockAlign = mux_a->h.dwScale;
>+    mux_a->h.dwSuggestedBufferSize = mux_a->wf->nBlockAlign*(mux_a->wf->nAvgBytesPerSec/(2*mux_a->wf->nBlockAlign)); /* suggest BufferSize 0.5 seconds */
>+
>+    switch (lavc_param_atag) {
>+    case 0x11: /* imaadpcm */
>+        mux_a->wf->wBitsPerSample = 4;
>+        mux_a->wf->cbSize = 2;
>+        /*
>+         * Magic imaadpcm values, currently probably only valid
>+         * for 48KHz Stereo
>+         */
>+        ((unsigned char*)mux_a->wf)[sizeof(WAVEFORMATEX)] = 0xf9;
>+        ((unsigned char*)mux_a->wf)[sizeof(WAVEFORMATEX)+1] = 0x07;
>+        break;
>+    case 0x55: /* mp3 */
>+    case 0x50: /* mp2 */
>+        mux_a->wf->cbSize = 12;
>+        mux_a->wf->wBitsPerSample = 0; /* does not apply */
>+        ((MPEGLAYER3WAVEFORMAT *) (mux_a->wf))->wID = 1;
>+        ((MPEGLAYER3WAVEFORMAT *) (mux_a->wf))->fdwFlags = 2;
>+        ((MPEGLAYER3WAVEFORMAT *) (mux_a->wf))->nBlockSize = mux_a->wf->nBlockAlign;
>+        ((MPEGLAYER3WAVEFORMAT *) (mux_a->wf))->nFramesPerBlock = 1;
>+        ((MPEGLAYER3WAVEFORMAT *) (mux_a->wf))->nCodecDelay = 0;
>+        break;
>+    default:
>+        mux_a->wf->cbSize = 0;
>+        mux_a->wf->wBitsPerSample = 0; /* Unknown */
>+        break;
>+    }
>+
>+    // setup filter:
>+    if (!init_audio_filters(
>+       sh_audio,
>+       sh_audio->samplerate, sh_audio->channels,
>+       sh_audio->sample_format, sh_audio->samplesize,
>+       mux_a->wf->nSamplesPerSec, mux_a->wf->nChannels,
>+#ifdef WORDS_BIGENDIAN
>+       AFMT_S16_BE, 2,
>+#else
>+       AFMT_S16_LE, 2,
>+#endif
>+       mux_a->h.dwSuggestedBufferSize,
>+       mux_a->h.dwSuggestedBufferSize*2)) {
>+        mp_msg(MSGT_CPLAYER, MSGL_ERR, "Couldn't find matching filter / ao format!\n");
>+        exit(1);
>+    }
>+
>+    mp_msg(MSGT_MENCODER, MSGL_V, "FRAME_SIZE: %d, BUFFER_SIZE: %d, TAG: 0x%x\n", lavc_actx->frame_size, lavc_actx->frame_size * 2 * lavc_actx->channels, mux_a->wf->wFormatTag);
>+
>+    break;
>+#endif
> }
> 
> if (verbose>1) print_wave_header(mux_a->wf);
>@@ -919,6 +1080,23 @@
> 
> 	ptimer_start = GetTimerMS();
> 
>+#ifdef USE_LIBAVCODEC
>+	if(mux_a->codec == ACODEC_LAVC){
>+	    int  size, rd_len;
>+
>+	    size = lavc_actx->frame_size * 2 * mux_a->wf->nChannels;
>+
>+	    rd_len = dec_audio(sh_audio, lavc_abuf, size);
>+	    if(rd_len != size)
>+		break;
>+
>+	    // Encode one frame
>+/*	    mux_a->buffer_len += avcodec_encode_audio(lavc_actx, mux_a->buffer + mux_a->buffer_len, size, lavc_abuf);
>+	    if (mux_a->buffer_len >= mux_a->wf->nBlockAlign)
>+		len = mux_a->wf->nBlockAlign;*/
>+	    len = avcodec_encode_audio(lavc_actx, mux_a->buffer + mux_a->buffer_len, size, lavc_abuf);
>+	}
>+#endif
> 	if(mux_a->h.dwSampleSize){
> 	    // CBR - copy 0.5 sec of audio
> 	    switch(mux_a->codec){
>@@ -1294,6 +1472,11 @@
> if(demuxer) free_demuxer(demuxer);
> if(stream) free_stream(stream); // kill cache thread
> 
>+#ifdef USE_LIBAVCODEC
>+if(lavc_abuf != NULL)
>+    free(lavc_abuf);
>+#endif
>+
> return interrupted;
> }
> 
>@@ -1600,3 +1783,26 @@
> 	mencoder_exit(0, NULL);
> }
> #endif
>+
>+#ifdef USE_LIBAVCODEC
>+static uint32_t lavc_find_atag(char *codec)
>+{
>+    if(codec == NULL)
>+       return 0;
>+
>+    if(! strcasecmp(codec, "mp2"))
>+       return 0x50;
>+
>+    if(! strcasecmp(codec, "mp3"))
>+       return 0x55;
>+
>+    if(! strcasecmp(codec, "ac3"))
>+       return 0x2000;
>+
>+    if(! strcasecmp(codec, "adpcm_ima_wav"))
>+       return 0x11;
>+
>+    return 0;
>+}
>+#endif
>+
>Index: cfg-mencoder.h
>===================================================================
>RCS file: /cvsroot/mplayer/main/cfg-mencoder.h,v
>retrieving revision 1.71
>diff -u -r1.71 cfg-mencoder.h
>--- cfg-mencoder.h	25 Oct 2003 18:44:41 -0000	1.71
>+++ cfg-mencoder.h	3 Nov 2003 00:06:33 -0000
>@@ -108,11 +108,19 @@
> #else
> 	{"mp3lame", "MPlayer was compiled without libmp3lame support!\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
> #endif
>+#ifdef USE_LIBAVCODEC
>+	{"lavc", &out_audio_codec, CONF_TYPE_FLAG, 0, 0, ACODEC_LAVC, NULL},
>+#else
>+	{"lavc", "MPlayer was compiled without libavcodec! See README or DOCS!\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
>+#endif
> 	{"help", "\nAvailable codecs:\n"
> 	"   copy     - frame copy, without re-encoding (useful for AC3)\n"
> 	"   pcm      - uncompressed PCM audio\n"
> #ifdef HAVE_MP3LAME
> 	"   mp3lame  - cbr/abr/vbr MP3 using libmp3lame\n"
>+#endif
>+#ifdef USE_LIBAVCODEC
>+	"   lavc     - ffmpeg audio encoder (mp2, ac3, ...)\n"
> #endif
> 	"\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
> 	{NULL, NULL, 0, 0, 0, 0, NULL}
>Index: configure
>===================================================================
>RCS file: /cvsroot/mplayer/main/configure,v
>retrieving revision 1.801
>diff -u -r1.801 configure
>--- configure	2 Nov 2003 13:45:24 -0000	1.801
>+++ configure	3 Nov 2003 00:06:51 -0000
>@@ -5725,6 +5725,7 @@
> SHARED_PP = $_shared_pp
> CONFIG_PP = yes
> CONFIG_RISKY = yes
>+CONFIG_MP3LAME = $_mp3lame
> LIBMENU = $_menu
> I18NLIBS = $_i18n_libs
> MATROSKA = $_matroska
>@@ -5802,7 +5803,7 @@
> ARCH_LIB =  $_ld_arch $_ld_iconv
> XVID = $_xvid
> XVID_LIB = $_ld_xvid
>-DECORE_LIB = $_ld_decore
>+DECORE_LIB = $_ld_decore $_ld_mp3lame
> MENCODER = $_mencoder
> ENCORE_LIB =  $_ld_encore $_ld_mp3lame
> DIRECTFB_INC = $_inc_directfb
>@@ -5944,6 +5945,7 @@
> /* Indicates if libmp3lame is available
>    Note: for mencoder */
> $_def_mp3lame
>+#define CONFIG_MP3LAME HAVE_MP3LAME
> 
> /* Define libmp1e for realtime mpeg encoding (for DXR3 and DVB cards) */
> $_def_mp1e
>Index: libmpdemux/muxer_avi.c
>===================================================================
>RCS file: /cvsroot/mplayer/main/libmpdemux/muxer_avi.c,v
>retrieving revision 1.15
>diff -u -r1.15 muxer_avi.c
>--- libmpdemux/muxer_avi.c	19 Jan 2003 00:33:11 -0000	1.15
>+++ libmpdemux/muxer_avi.c	3 Nov 2003 00:06:52 -0000
>@@ -111,7 +111,7 @@
>     if(s->h.dwSampleSize){
> 	// CBR
> 	s->h.dwLength+=len/s->h.dwSampleSize;
>-	if(len%s->h.dwSampleSize) printf("Warning! len isn't divisable by samplesize!\n");
>+	if(len%s->h.dwSampleSize) printf("Warning! len(%d) isn't divisable by samplesize(%d)!\n", len, s->h.dwSampleSize);
>     } else {
> 	// VBR
> 	s->h.dwLength++;
>@@ -136,7 +136,8 @@
> }
> 
> // muxer->streams[i]->wf->cbSize
>-#define WFSIZE(wf) (sizeof(WAVEFORMATEX)+(((wf)->cbSize)?((wf)->cbSize-2):0))
>+// #define WFSIZE(wf) (sizeof(WAVEFORMATEX)+(((wf)->cbSize)?((wf)->cbSize-2):0))
>+#define WFSIZE(wf) (sizeof(WAVEFORMATEX)+(wf)->cbSize)
> 
> static void avifile_write_header(muxer_t *muxer){
>   uint32_t riff[3];
>Index: libmpcodecs/ve_lavc.c
>===================================================================
>RCS file: /cvsroot/mplayer/main/libmpcodecs/ve_lavc.c,v
>retrieving revision 1.81
>diff -u -r1.81 ve_lavc.c
>--- libmpcodecs/ve_lavc.c	23 Oct 2003 12:05:33 -0000	1.81
>+++ libmpcodecs/ve_lavc.c	3 Nov 2003 00:06:55 -0000
>@@ -134,10 +134,17 @@
> static int lavc_param_cbp= 0;
> static int lavc_param_mv0= 0;
> 
>+char *lavc_param_acodec = "mp2";
>+int lavc_param_atag = 0;
>+int lavc_param_abitrate = 224;
>+
> #include "m_option.h"
> 
> #ifdef USE_LIBAVCODEC
> m_option_t lavcopts_conf[]={
>+	{"acodec", &lavc_param_acodec, CONF_TYPE_STRING, 0, 0, 0, NULL},
>+	{"abitrate", &lavc_param_abitrate, CONF_TYPE_INT, CONF_RANGE, 1, 1000, NULL},
>+	{"atag", &lavc_param_atag, CONF_TYPE_INT, CONF_RANGE, 0, 0xffff, NULL},
> 	{"vcodec", &lavc_param_vcodec, CONF_TYPE_STRING, 0, 0, 0, NULL},
> 	{"vbitrate", &lavc_param_vbitrate, CONF_TYPE_INT, CONF_RANGE, 4, 24000000, NULL},
> 	{"vratetol", &lavc_param_vrate_tolerance, CONF_TYPE_INT, CONF_RANGE, 4, 24000000, NULL},
>Index: DOCS/man/en/mplayer.1
>===================================================================
>RCS file: /cvsroot/mplayer/main/DOCS/man/en/mplayer.1,v
>retrieving revision 1.476
>diff -u -r1.476 mplayer.1
>--- DOCS/man/en/mplayer.1	30 Oct 2003 16:52:05 -0000	1.476
>+++ DOCS/man/en/mplayer.1	3 Nov 2003 00:07:13 -0000
>@@ -3242,6 +3242,8 @@
> encode to uncompressed PCM
> .IPs "\-oac mp3lame"
> encode to MP3 (using Lame)
>+.IPs "\-oac lavc"
>+encode with a libavcodec codecs
> .RE
> .PD 1
> .
>@@ -3521,8 +3523,29 @@
> .PD 1
> 
> .TP
>+.B acodec=<value>
>+Audio codec (default: mp2):
>+.PD 0
>+.RSs
>+.IPs mp2
>+MPEG Layer 2
>+.IPs mp3
>+MPEG Layer 3
>+.IPs ac3
>+AC3
>+.IPs adpcm_ima_wav
>+IMA Adaptive PCM (4bits per sample, 4:1 compression)
>+.RE
>+.PD 1
>+.TP
>+.B abitrate=<value>
>+Audio bitrate in kBit (default 224).
>+.TP
>+.B atag=<value>
>+Use the specified windows audio format tag (e.g. atag=0x55).
>+.TP
> .B vcodec=<value>
>-use the specified codec (there is no default, you must specify it):
>+use the specified codec (default: mpeg4):
> .PD 0
> .RSs
> .IPs mjpeg
>  
>
>------------------------------------------------------------------------
>
>_______________________________________________
>MPlayer-dev-eng mailing list
>MPlayer-dev-eng at mplayerhq.hu
>http://mplayerhq.hu/mailman/listinfo/mplayer-dev-eng
>  
>




More information about the MPlayer-dev-eng mailing list