[MPlayer-dev-eng] Re: [PATCH] encoding audio with libavcodec
Tobias Diedrich
ranma at gmx.at
Mon Nov 3 01:28:29 CET 2003
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.
--
Tobias PGP: http://9ac7e0bc.2ya.com
This mail is made of 100% recycled bits
np: FFmusic Dj: http://remix.overclocked.org 99 - Final Fantasy 9 Melodies of Techno OC ReMix []
-------------- next part --------------
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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/attachments/20031103/b986909c/attachment.pgp>
More information about the MPlayer-dev-eng
mailing list