[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