From 8a964239cdbe666e012774c0cd30859579319cf1 Mon Sep 17 00:00:00 2001 From: Michael Roitzsch Date: Sun, 25 May 2003 18:34:54 +0000 Subject: compiling libavcodec's encoding part as an MPEG encoder suitable for the DXR3 * libavcodec/mpegvideo.c has been modified to work without the need to compile libavcodec/motion_est.c to save compilation time (we don't need motion estimation when encoding I-frames only anyway) * the patch to libavcodec/i386/mpegvideo_mmx_template.c has been reverted, because the encoder crashes with it CVS patchset: 4930 CVS date: 2003/05/25 18:34:54 --- src/libffmpeg/Makefile.am | 8 +- src/libffmpeg/diff_to_ffmpeg_cvs.txt | 238 ++++---------- src/libffmpeg/libavcodec/Makefile.am | 9 +- .../libavcodec/i386/mpegvideo_mmx_template.c | 76 ++--- src/libffmpeg/libavcodec/mpegvideo.c | 10 + src/libffmpeg/xine_encoder.c | 359 +++++++++++++++++++++ 6 files changed, 478 insertions(+), 222 deletions(-) create mode 100644 src/libffmpeg/xine_encoder.c diff --git a/src/libffmpeg/Makefile.am b/src/libffmpeg/Makefile.am index 44297a054..45e97dcaa 100644 --- a/src/libffmpeg/Makefile.am +++ b/src/libffmpeg/Makefile.am @@ -12,8 +12,12 @@ libdir = $(XINE_PLUGINDIR) lib_LTLIBRARIES = xineplug_decode_ff.la -xineplug_decode_ff_la_SOURCES = xine_decoder.c -xineplug_decode_ff_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ +xineplug_decode_ff_la_SOURCES = xine_decoder.c xine_encoder.c +# The dxr3 uses ffmpegs MPEG encoder by dlopen()ing the ffmpeg plugin and +# dlsym()ing the necessary function. Therefore we must allow more exported +# symbols and cannot use @XINE_PLUGIN_MIN_SYMS@ +#xineplug_decode_ff_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ +xineplug_decode_ff_la_LDFLAGS = -avoid-version -module xineplug_decode_ff_la_LIBADD = $(XINE_LIB) \ $(top_builddir)/src/libffmpeg/libavcodec/libavcodec.la \ $(top_builddir)/src/libffmpeg/libavcodec/libpostproc/libpostprocess.la diff --git a/src/libffmpeg/diff_to_ffmpeg_cvs.txt b/src/libffmpeg/diff_to_ffmpeg_cvs.txt index c0de1f128..7420eef4c 100644 --- a/src/libffmpeg/diff_to_ffmpeg_cvs.txt +++ b/src/libffmpeg/diff_to_ffmpeg_cvs.txt @@ -80,23 +80,6 @@ diff -u -r1.60 dsputil.h #define emms_c() \ -Index: libavcodec/mpegvideo.c -=================================================================== -RCS file: /cvsroot/ffmpeg/ffmpeg/libavcodec/mpegvideo.c,v -retrieving revision 1.231 -diff -u -r1.231 mpegvideo.c ---- libavcodec/mpegvideo.c 22 Mar 2003 12:09:01 -0000 1.231 -+++ libavcodec/mpegvideo.c 26 Mar 2003 13:49:19 -0000 -@@ -34,8 +34,7 @@ - #include "fastmemcpy.h" - #endif - --//#undef NDEBUG --//#include -+#define CONFIG_RISKY - - #ifdef CONFIG_ENCODERS - static void encode_picture(MpegEncContext *s, int picture_number); Index: libavcodec/i386/cputest.c =================================================================== RCS file: /cvsroot/ffmpeg/ffmpeg/libavcodec/i386/cputest.c,v @@ -482,160 +465,6 @@ diff -u -r1.3 mmx.h - -#endif /* AVCODEC_I386MMX_H */ +#include "xineutils.h" -Index: libavcodec/i386/mpegvideo_mmx_template.c -=================================================================== -RCS file: /cvsroot/ffmpeg/ffmpeg/libavcodec/i386/mpegvideo_mmx_template.c,v -retrieving revision 1.15 -diff -u -r1.15 mpegvideo_mmx_template.c ---- libavcodec/i386/mpegvideo_mmx_template.c 3 Mar 2003 14:53:53 -0000 1.15 -+++ libavcodec/i386/mpegvideo_mmx_template.c 26 Mar 2003 13:49:20 -0000 -@@ -83,16 +83,25 @@ - } - - if(s->out_format == FMT_H263 && s->mpeg_quant==0){ -- -+ -+ /* the following code is patched using avifile's modifications -+ to enable -fpic compilation. this patch has not been accepted on -+ main ffmpeg cvs. */ -+ - asm volatile( - "movd %%eax, %%mm3 \n\t" // last_non_zero_p1 - SPREADW(%%mm3) - "pxor %%mm7, %%mm7 \n\t" // 0 - "pxor %%mm4, %%mm4 \n\t" // 0 -- "movq (%2), %%mm5 \n\t" // qmat[0] -+ "movq (%1), %%mm5 \n\t" // qmat[0] - "pxor %%mm6, %%mm6 \n\t" -- "psubw (%3), %%mm6 \n\t" // -bias[0] -+ "psubw (%2), %%mm6 \n\t" // -bias[0] - "movl $-128, %%eax \n\t" -+ : "+a" (last_non_zero_p1) -+ : "r" (qmat), "r" (bias) -+ ); -+ /* CORE */ -+ asm volatile( - ".balign 16 \n\t" - "1: \n\t" - "pxor %%mm1, %%mm1 \n\t" // 0 -@@ -105,7 +114,7 @@ - "por %%mm0, %%mm4 \n\t" - "pxor %%mm1, %%mm0 \n\t" - "psubw %%mm1, %%mm0 \n\t" // out=((ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16)*sign(block[i]) -- "movq %%mm0, (%5, %%eax) \n\t" -+ "movq %%mm0, (%3, %%eax) \n\t" - "pcmpeqw %%mm7, %%mm0 \n\t" // out==0 ? 0xFF : 0x00 - "movq (%4, %%eax), %%mm1 \n\t" - "movq %%mm7, (%1, %%eax) \n\t" // 0 -@@ -113,6 +122,11 @@ - PMAXW(%%mm0, %%mm3) - "addl $8, %%eax \n\t" - " js 1b \n\t" -+ : "+a" (last_non_zero_p1) -+ : "r" (block+64), "r" (inv_zigzag_direct16+64), "r" (temp_block+64) -+ ); -+ /* EPILOGUE */ -+ asm volatile( - "movq %%mm3, %%mm0 \n\t" - "psrlq $32, %%mm3 \n\t" - PMAXW(%%mm0, %%mm3) -@@ -121,48 +135,46 @@ - PMAXW(%%mm0, %%mm3) - "movd %%mm3, %%eax \n\t" - "movzbl %%al, %%eax \n\t" // last_non_zero_p1 -- : "+a" (last_non_zero_p1) -- : "r" (block+64), "r" (qmat), "r" (bias), -- "r" (inv_zigzag_direct16+64), "r" (temp_block+64) -- ); -- // note the asm is split cuz gcc doesnt like that many operands ... -- asm volatile( -- "movd %1, %%mm1 \n\t" // max_qcoeff -+ "movd %2, %%mm1 \n\t" // max_qcoeff - SPREADW(%%mm1) - "psubusw %%mm1, %%mm4 \n\t" - "packuswb %%mm4, %%mm4 \n\t" -- "movd %%mm4, %0 \n\t" // *overflow -- : "=g" (*overflow) -- : "g" (s->max_qcoeff) -- ); -+ "movd %%mm4, %1 \n\t" // *overflow -+ : "+a" (last_non_zero_p1), "=r" (*overflow) -+ : "r" (s->max_qcoeff) -+ ); - }else{ // FMT_H263 - asm volatile( -- "movd %%eax, %%mm3 \n\t" // last_non_zero_p1 -+ "pushl %%ebp \n\t" -+ "pushl %%ebx \n\t" -+ "movl %0, %%ebp \n\t" -+ "movl (%%ebp), %%ebx \n\t" -+ "movd %%ebx, %%mm3 \n\t" // last_non_zero_p1 - SPREADW(%%mm3) - "pxor %%mm7, %%mm7 \n\t" // 0 - "pxor %%mm4, %%mm4 \n\t" // 0 -- "movl $-128, %%eax \n\t" -+ "movl $-128, %%ebx \n\t" - ".balign 16 \n\t" - "1: \n\t" - "pxor %%mm1, %%mm1 \n\t" // 0 -- "movq (%1, %%eax), %%mm0 \n\t" // block[i] -+ "movq (%1, %%ebx), %%mm0 \n\t" // block[i] - "pcmpgtw %%mm0, %%mm1 \n\t" // block[i] <= 0 ? 0xFF : 0x00 - "pxor %%mm1, %%mm0 \n\t" - "psubw %%mm1, %%mm0 \n\t" // ABS(block[i]) -- "movq (%3, %%eax), %%mm6 \n\t" // bias[0] -+ "movq (%3, %%ebx), %%mm6 \n\t" // bias[0] - "paddusw %%mm6, %%mm0 \n\t" // ABS(block[i]) + bias[0] -- "movq (%2, %%eax), %%mm5 \n\t" // qmat[i] -+ "movq (%2, %%ebx), %%mm5 \n\t" // qmat[i] - "pmulhw %%mm5, %%mm0 \n\t" // (ABS(block[i])*qmat[0] + bias[0]*qmat[0])>>16 - "por %%mm0, %%mm4 \n\t" - "pxor %%mm1, %%mm0 \n\t" - "psubw %%mm1, %%mm0 \n\t" // out=((ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16)*sign(block[i]) -- "movq %%mm0, (%5, %%eax) \n\t" -+ "movq %%mm0, (%5, %%ebx) \n\t" - "pcmpeqw %%mm7, %%mm0 \n\t" // out==0 ? 0xFF : 0x00 -- "movq (%4, %%eax), %%mm1 \n\t" -- "movq %%mm7, (%1, %%eax) \n\t" // 0 -+ "movq (%4, %%ebx), %%mm1 \n\t" -+ "movq %%mm7, (%1, %%ebx) \n\t" // 0 - "pandn %%mm1, %%mm0 \n\t" - PMAXW(%%mm0, %%mm3) -- "addl $8, %%eax \n\t" -+ "addl $8, %%ebx \n\t" - " js 1b \n\t" - "movq %%mm3, %%mm0 \n\t" - "psrlq $32, %%mm3 \n\t" -@@ -170,10 +182,14 @@ - "movq %%mm3, %%mm0 \n\t" - "psrlq $16, %%mm3 \n\t" - PMAXW(%%mm0, %%mm3) -- "movd %%mm3, %%eax \n\t" -- "movzbl %%al, %%eax \n\t" // last_non_zero_p1 -- : "+a" (last_non_zero_p1) -- : "r" (block+64), "r" (qmat+64), "r" (bias+64), -+ "movd %%mm3, %%ebx \n\t" -+ "movzbl %%bl, %%ebx \n\t" // last_non_zero_p1 -+ "movl %%ebx, (%%ebp) \n\t" -+ "popl %%ebx \n\t" -+ "popl %%ebp \n\t" -+ : -+ : "m" (last_non_zero_p1), -+ "r" (block+64), "r" (qmat+64), "r" (bias+64), - "r" (inv_zigzag_direct16+64), "r" (temp_block+64) - ); - // note the asm is split cuz gcc doesnt like that many operands ... -@@ -183,8 +199,8 @@ - "psubusw %%mm1, %%mm4 \n\t" - "packuswb %%mm4, %%mm4 \n\t" - "movd %%mm4, %0 \n\t" // *overflow -- : "=g" (*overflow) -- : "g" (s->max_qcoeff) -+ : "=r" (*overflow) -+ : "r" (s->max_qcoeff) - ); - } - Index: libavcodec/libpostproc/postprocess.c =================================================================== RCS file: /cvsroot/ffmpeg/ffmpeg/libavcodec/libpostproc/postprocess.c,v @@ -722,3 +551,70 @@ diff -u -r1.61 mjpeg.c // if (s->first_picture) // printf("mjpeg: workarounding buggy AVID\n"); s->interlace_polarity = get_bits(&s->gb, 8); +Index: libavcodec/mpegvideo.c +=================================================================== +RCS file: /cvsroot/xine/xine-lib/src/libffmpeg/libavcodec/mpegvideo.c,v +retrieving revision 1.31 +diff -u -r1.31 mpegvideo.c +--- libavcodec/mpegvideo.c 9 May 2003 23:54:05 -0000 1.31 ++++ libavcodec/mpegvideo.c 25 May 2003 18:29:52 -0000 +@@ -761,7 +761,9 @@ + if (MPV_common_init(s) < 0) + return -1; + ++#ifdef CONFIG_ENCODERS_FULL + ff_init_me(s); ++#endif + + #ifdef CONFIG_ENCODERS + #ifdef CONFIG_RISKY +@@ -1438,7 +1440,9 @@ + mjpeg_picture_trailer(s); + + if(s->flags&CODEC_FLAG_PASS1) ++#ifdef CONFIG_ENCODERS_FULL + ff_write_pass1_stats(s); ++#endif + + for(i=0; i<4; i++){ + avctx->error[i] += s->current_picture_ptr->error[i]; +@@ -3014,6 +3018,7 @@ + /* Estimate motion for every MB */ + s->mb_intra=0; //for the rate distoration & bit compare functions + if(s->pict_type != I_TYPE){ ++#ifdef CONFIG_ENCODERS_FULL + if(s->pict_type != B_TYPE){ + if((s->avctx->pre_me && s->last_non_b_pict_type==I_TYPE) || s->avctx->pre_me==2){ + s->me.pre_pass=1; +@@ -3051,6 +3056,7 @@ + ff_estimate_p_frame_motion(s, mb_x, mb_y); + } + } ++#endif + }else /* if(s->pict_type == I_TYPE) */{ + /* I-Frame */ + //FIXME do we need to zero them? +@@ -3087,12 +3093,15 @@ + + if(!s->umvplus){ + if(s->pict_type==P_TYPE || s->pict_type==S_TYPE) { ++#ifdef CONFIG_ENCODERS_FULL + s->f_code= ff_get_best_fcode(s, s->p_mv_table, MB_TYPE_INTER); + + ff_fix_long_p_mvs(s); ++#endif + } + + if(s->pict_type==B_TYPE){ ++#ifdef CONFIG_ENCODERS_FULL + int a, b; + + a = ff_get_best_fcode(s, s->b_forw_mv_table, MB_TYPE_FORWARD); +@@ -3107,6 +3116,7 @@ + ff_fix_long_b_mvs(s, s->b_back_mv_table, s->b_code, MB_TYPE_BACKWARD); + ff_fix_long_b_mvs(s, s->b_bidir_forw_mv_table, s->f_code, MB_TYPE_BIDIR); + ff_fix_long_b_mvs(s, s->b_bidir_back_mv_table, s->b_code, MB_TYPE_BIDIR); ++#endif + } + } + diff --git a/src/libffmpeg/libavcodec/Makefile.am b/src/libffmpeg/libavcodec/Makefile.am index a27478a5a..14140396a 100644 --- a/src/libffmpeg/libavcodec/Makefile.am +++ b/src/libffmpeg/libavcodec/Makefile.am @@ -3,12 +3,12 @@ include $(top_srcdir)/misc/Makefile.common SUBDIRS = armv4l i386 mlib alpha libpostproc ## we include ppc/* files since auto* doesn't dive into. -EXTRA_DIST = fdctref.c imgresample.c motion_est_template.c svq3.c wmv2.c \ +EXTRA_DIST = fdctref.c motion_est_template.c svq3.c wmv2.c \ ppc/dsputil_ppc.c ppc/libavcodec_ppc_dummy.c ppc/mpegvideo_altivec.c \ ppc/dsputil_altivec.c ppc/fft_altivec.c ppc/Makefile.am ppc/mpegvideo_ppc.c \ ppc/dsputil_altivec.h ppc/idct_altivec.c -AM_CFLAGS = $(LIBFFMPEG_CFLAGS) -DCONFIG_RISKY +AM_CFLAGS = $(LIBFFMPEG_CFLAGS) -DCONFIG_RISKY -DCONFIG_ENCODERS ASFLAGS = noinst_LTLIBRARIES = libavcodec.la @@ -40,12 +40,15 @@ libavcodec_la_SOURCES = \ mpegvideo.c \ msmpeg4.c \ opts.c \ + ratecontrol.c \ rv10.c \ simple_idct.c \ svq1.c \ utils.c \ wmadec.c -#imgresample.c + +# these are currently unneeded +EXTRA_DIST += imgresample.c motion_est.c libavcodec_la_LDFLAGS = \ $(top_builddir)/src/libffmpeg/libavcodec/armv4l/libavcodec_armv4l.la \ diff --git a/src/libffmpeg/libavcodec/i386/mpegvideo_mmx_template.c b/src/libffmpeg/libavcodec/i386/mpegvideo_mmx_template.c index 8cd91024b..fa1ab579d 100644 --- a/src/libffmpeg/libavcodec/i386/mpegvideo_mmx_template.c +++ b/src/libffmpeg/libavcodec/i386/mpegvideo_mmx_template.c @@ -83,25 +83,16 @@ static int RENAME(dct_quantize)(MpegEncContext *s, } if(s->out_format == FMT_H263 && s->mpeg_quant==0){ - - /* the following code is patched using avifile's modifications - to enable -fpic compilation. this patch has not been accepted on - main ffmpeg cvs. */ - + asm volatile( "movd %%eax, %%mm3 \n\t" // last_non_zero_p1 SPREADW(%%mm3) "pxor %%mm7, %%mm7 \n\t" // 0 "pxor %%mm4, %%mm4 \n\t" // 0 - "movq (%1), %%mm5 \n\t" // qmat[0] + "movq (%2), %%mm5 \n\t" // qmat[0] "pxor %%mm6, %%mm6 \n\t" - "psubw (%2), %%mm6 \n\t" // -bias[0] + "psubw (%3), %%mm6 \n\t" // -bias[0] "movl $-128, %%eax \n\t" - : "+a" (last_non_zero_p1) - : "r" (qmat), "r" (bias) - ); - /* CORE */ - asm volatile( ".balign 16 \n\t" "1: \n\t" "pxor %%mm1, %%mm1 \n\t" // 0 @@ -114,7 +105,7 @@ static int RENAME(dct_quantize)(MpegEncContext *s, "por %%mm0, %%mm4 \n\t" "pxor %%mm1, %%mm0 \n\t" "psubw %%mm1, %%mm0 \n\t" // out=((ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16)*sign(block[i]) - "movq %%mm0, (%3, %%eax) \n\t" + "movq %%mm0, (%5, %%eax) \n\t" "pcmpeqw %%mm7, %%mm0 \n\t" // out==0 ? 0xFF : 0x00 "movq (%4, %%eax), %%mm1 \n\t" "movq %%mm7, (%1, %%eax) \n\t" // 0 @@ -122,11 +113,6 @@ static int RENAME(dct_quantize)(MpegEncContext *s, PMAXW(%%mm0, %%mm3) "addl $8, %%eax \n\t" " js 1b \n\t" - : "+a" (last_non_zero_p1) - : "r" (block+64), "r" (inv_zigzag_direct16+64), "r" (temp_block+64) - ); - /* EPILOGUE */ - asm volatile( "movq %%mm3, %%mm0 \n\t" "psrlq $32, %%mm3 \n\t" PMAXW(%%mm0, %%mm3) @@ -135,46 +121,48 @@ static int RENAME(dct_quantize)(MpegEncContext *s, PMAXW(%%mm0, %%mm3) "movd %%mm3, %%eax \n\t" "movzbl %%al, %%eax \n\t" // last_non_zero_p1 - "movd %2, %%mm1 \n\t" // max_qcoeff + : "+a" (last_non_zero_p1) + : "r" (block+64), "r" (qmat), "r" (bias), + "r" (inv_zigzag_direct16+64), "r" (temp_block+64) + ); + // note the asm is split cuz gcc doesnt like that many operands ... + asm volatile( + "movd %1, %%mm1 \n\t" // max_qcoeff SPREADW(%%mm1) "psubusw %%mm1, %%mm4 \n\t" "packuswb %%mm4, %%mm4 \n\t" - "movd %%mm4, %1 \n\t" // *overflow - : "+a" (last_non_zero_p1), "=r" (*overflow) - : "r" (s->max_qcoeff) - ); + "movd %%mm4, %0 \n\t" // *overflow + : "=g" (*overflow) + : "g" (s->max_qcoeff) + ); }else{ // FMT_H263 asm volatile( - "pushl %%ebp \n\t" - "pushl %%ebx \n\t" - "movl %0, %%ebp \n\t" - "movl (%%ebp), %%ebx \n\t" - "movd %%ebx, %%mm3 \n\t" // last_non_zero_p1 + "movd %%eax, %%mm3 \n\t" // last_non_zero_p1 SPREADW(%%mm3) "pxor %%mm7, %%mm7 \n\t" // 0 "pxor %%mm4, %%mm4 \n\t" // 0 - "movl $-128, %%ebx \n\t" + "movl $-128, %%eax \n\t" ".balign 16 \n\t" "1: \n\t" "pxor %%mm1, %%mm1 \n\t" // 0 - "movq (%1, %%ebx), %%mm0 \n\t" // block[i] + "movq (%1, %%eax), %%mm0 \n\t" // block[i] "pcmpgtw %%mm0, %%mm1 \n\t" // block[i] <= 0 ? 0xFF : 0x00 "pxor %%mm1, %%mm0 \n\t" "psubw %%mm1, %%mm0 \n\t" // ABS(block[i]) - "movq (%3, %%ebx), %%mm6 \n\t" // bias[0] + "movq (%3, %%eax), %%mm6 \n\t" // bias[0] "paddusw %%mm6, %%mm0 \n\t" // ABS(block[i]) + bias[0] - "movq (%2, %%ebx), %%mm5 \n\t" // qmat[i] + "movq (%2, %%eax), %%mm5 \n\t" // qmat[i] "pmulhw %%mm5, %%mm0 \n\t" // (ABS(block[i])*qmat[0] + bias[0]*qmat[0])>>16 "por %%mm0, %%mm4 \n\t" "pxor %%mm1, %%mm0 \n\t" "psubw %%mm1, %%mm0 \n\t" // out=((ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16)*sign(block[i]) - "movq %%mm0, (%5, %%ebx) \n\t" + "movq %%mm0, (%5, %%eax) \n\t" "pcmpeqw %%mm7, %%mm0 \n\t" // out==0 ? 0xFF : 0x00 - "movq (%4, %%ebx), %%mm1 \n\t" - "movq %%mm7, (%1, %%ebx) \n\t" // 0 + "movq (%4, %%eax), %%mm1 \n\t" + "movq %%mm7, (%1, %%eax) \n\t" // 0 "pandn %%mm1, %%mm0 \n\t" PMAXW(%%mm0, %%mm3) - "addl $8, %%ebx \n\t" + "addl $8, %%eax \n\t" " js 1b \n\t" "movq %%mm3, %%mm0 \n\t" "psrlq $32, %%mm3 \n\t" @@ -182,14 +170,10 @@ static int RENAME(dct_quantize)(MpegEncContext *s, "movq %%mm3, %%mm0 \n\t" "psrlq $16, %%mm3 \n\t" PMAXW(%%mm0, %%mm3) - "movd %%mm3, %%ebx \n\t" - "movzbl %%bl, %%ebx \n\t" // last_non_zero_p1 - "movl %%ebx, (%%ebp) \n\t" - "popl %%ebx \n\t" - "popl %%ebp \n\t" - : - : "m" (last_non_zero_p1), - "r" (block+64), "r" (qmat+64), "r" (bias+64), + "movd %%mm3, %%eax \n\t" + "movzbl %%al, %%eax \n\t" // last_non_zero_p1 + : "+a" (last_non_zero_p1) + : "r" (block+64), "r" (qmat+64), "r" (bias+64), "r" (inv_zigzag_direct16+64), "r" (temp_block+64) ); // note the asm is split cuz gcc doesnt like that many operands ... @@ -199,8 +183,8 @@ static int RENAME(dct_quantize)(MpegEncContext *s, "psubusw %%mm1, %%mm4 \n\t" "packuswb %%mm4, %%mm4 \n\t" "movd %%mm4, %0 \n\t" // *overflow - : "=r" (*overflow) - : "r" (s->max_qcoeff) + : "=g" (*overflow) + : "g" (s->max_qcoeff) ); } diff --git a/src/libffmpeg/libavcodec/mpegvideo.c b/src/libffmpeg/libavcodec/mpegvideo.c index c0dd96bbe..d2f3c8e90 100644 --- a/src/libffmpeg/libavcodec/mpegvideo.c +++ b/src/libffmpeg/libavcodec/mpegvideo.c @@ -761,7 +761,9 @@ int MPV_encode_init(AVCodecContext *avctx) if (MPV_common_init(s) < 0) return -1; +#ifdef CONFIG_ENCODERS_FULL ff_init_me(s); +#endif #ifdef CONFIG_ENCODERS #ifdef CONFIG_RISKY @@ -1438,7 +1440,9 @@ int MPV_encode_picture(AVCodecContext *avctx, mjpeg_picture_trailer(s); if(s->flags&CODEC_FLAG_PASS1) +#ifdef CONFIG_ENCODERS_FULL ff_write_pass1_stats(s); +#endif for(i=0; i<4; i++){ avctx->error[i] += s->current_picture_ptr->error[i]; @@ -3014,6 +3018,7 @@ static void encode_picture(MpegEncContext *s, int picture_number) /* Estimate motion for every MB */ s->mb_intra=0; //for the rate distoration & bit compare functions if(s->pict_type != I_TYPE){ +#ifdef CONFIG_ENCODERS_FULL if(s->pict_type != B_TYPE){ if((s->avctx->pre_me && s->last_non_b_pict_type==I_TYPE) || s->avctx->pre_me==2){ s->me.pre_pass=1; @@ -3051,6 +3056,7 @@ static void encode_picture(MpegEncContext *s, int picture_number) ff_estimate_p_frame_motion(s, mb_x, mb_y); } } +#endif }else /* if(s->pict_type == I_TYPE) */{ /* I-Frame */ //FIXME do we need to zero them? @@ -3087,12 +3093,15 @@ static void encode_picture(MpegEncContext *s, int picture_number) if(!s->umvplus){ if(s->pict_type==P_TYPE || s->pict_type==S_TYPE) { +#ifdef CONFIG_ENCODERS_FULL s->f_code= ff_get_best_fcode(s, s->p_mv_table, MB_TYPE_INTER); ff_fix_long_p_mvs(s); +#endif } if(s->pict_type==B_TYPE){ +#ifdef CONFIG_ENCODERS_FULL int a, b; a = ff_get_best_fcode(s, s->b_forw_mv_table, MB_TYPE_FORWARD); @@ -3107,6 +3116,7 @@ static void encode_picture(MpegEncContext *s, int picture_number) ff_fix_long_b_mvs(s, s->b_back_mv_table, s->b_code, MB_TYPE_BACKWARD); ff_fix_long_b_mvs(s, s->b_bidir_forw_mv_table, s->f_code, MB_TYPE_BIDIR); ff_fix_long_b_mvs(s, s->b_bidir_back_mv_table, s->b_code, MB_TYPE_BIDIR); +#endif } } diff --git a/src/libffmpeg/xine_encoder.c b/src/libffmpeg/xine_encoder.c new file mode 100644 index 000000000..4502fb372 --- /dev/null +++ b/src/libffmpeg/xine_encoder.c @@ -0,0 +1,359 @@ +/* + * Copyright (C) 2000-2003 the xine project + * + * This file is part of xine, a unix video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: xine_encoder.c,v 1.1 2003/05/25 18:34:54 mroi Exp $ + */ + +/* mpeg encoders for the dxr3 video out plugin. */ + +#include +#include +#include +#include +#include +#include + +#include "../dxr3/video_out_dxr3.h" +#include "libavcodec/avcodec.h" + +#define LOG_ENC 0 + +/* buffer size for encoded mpeg1 stream; will hold one intra frame + * at 640x480 typical sizes are <50 kB. 512 kB should be plenty */ +#define DEFAULT_BUFFER_SIZE 512*1024 + + +/*initialisation function*/ +int dxr3_encoder_init(dxr3_driver_t *drv); + +/* functions required by encoder api */ +static int lavc_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame); +static int lavc_on_display_frame(dxr3_driver_t *drv, dxr3_frame_t *frame); +static int lavc_on_unneeded(dxr3_driver_t *drv); + +/*encoder structure*/ +typedef struct lavc_data_s { + encoder_data_t encoder_data; + AVCodecContext *context; /* handle for encoding */ + int width, height; /* width and height of the video frame */ + uint8_t *ffmpeg_buffer; /* lavc buffer */ + AVFrame *picture; /* picture to be encoded */ + uint8_t *out[3]; /* aligned buffer for YV12 data */ + uint8_t *buf; /* unaligned YV12 buffer */ +} lavc_data_t; + + +int dxr3_encoder_init(dxr3_driver_t *drv) +{ + lavc_data_t* this; + avcodec_init(); + + register_avcodec(&mpeg1video_encoder); +#if LOG_ENC + printf("dxr3_mpeg_encoder: lavc init , version %x\n", avcodec_version()); +#endif + this = malloc(sizeof(lavc_data_t)); + if (!this) return 0; + memset(this, 0, sizeof(lavc_data_t)); + + this->encoder_data.type = ENC_LAVC; + this->encoder_data.on_update_format = lavc_on_update_format; + this->encoder_data.on_frame_copy = NULL; + this->encoder_data.on_display_frame = lavc_on_display_frame; + this->encoder_data.on_unneeded = lavc_on_unneeded; + this->context = 0; + + drv->enc = &this->encoder_data; + return 1; +} + +/* helper function */ +static int lavc_prepare_frame(lavc_data_t *this, dxr3_driver_t *drv, dxr3_frame_t *frame); + +static int lavc_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) +{ + lavc_data_t *this = (lavc_data_t *)drv->enc; + AVCodec *codec; + double fps; + unsigned char use_quantizer; + + if (this->context) { + avcodec_close(this->context); + free(this->context); + free(this->picture); + this->context = NULL; + this->picture = NULL; + } + + /* if YUY2 and dimensions changed, we need to re-allocate the + * internal YV12 buffer */ + if (frame->vo_frame.format == XINE_IMGFMT_YUY2) { + int image_size = frame->vo_frame.width * frame->oheight; + + this->out[0] = xine_xmalloc_aligned(16, image_size * 3/2, + (void *)&this->buf); + this->out[1] = this->out[0] + image_size; + this->out[2] = this->out[1] + image_size/4; + + /* fill with black (yuv 16,128,128) */ + memset(this->out[0], 16, image_size); + memset(this->out[1], 128, image_size/4); + memset(this->out[2], 128, image_size/4); +#if LOG_ENC + printf("dxr3_mpeg_encoder: Using YUY2->YV12 conversion\n"); +#endif + } + + + /* resolution must be a multiple of two */ + if ((frame->vo_frame.pitches[0] % 2 != 0) || (frame->oheight % 2 != 0)) { + printf("dxr3_mpeg_encoder: lavc only handles video dimensions which are multiples of 2\n"); + return 0; + } + + /* get mpeg codec handle */ + codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO); + if (!codec) { + printf("dxr3_mpeg_encoder: lavc MPEG1 codec not found\n"); + return 0; + } +#if LOG_ENC + printf("dxr3_mpeg_encoder: lavc MPEG1 encoder found.\n"); +#endif + this->width = frame->vo_frame.pitches[0]; + this->height = frame->oheight; + + this->context = avcodec_alloc_context(); + if (!this->context) { + printf("dxr3_mpeg_encoder: Couldn't start the ffmpeg library\n"); + return 0; + } + this->picture = avcodec_alloc_frame(); + if (!this->picture) { + printf("dxr3_mpeg_encoder: Couldn't allocate ffmpeg frame\n"); + return 0; + } + + /* put sample parameters */ + this->context->bit_rate = drv->class->xine->config->register_range(drv->class->xine->config, + "dxr3.lavc_bitrate", 10000, 1000, 20000, + _("Dxr3enc: libavcodec mpeg output bitrate (kbit/s)"), + _("The bitrate the libavcodec mpeg encoder should use for dxr3's encoding mode"), 10, + NULL, NULL); + this->context->bit_rate *= 1000; /* config in kbit/s, libavcodec wants bit/s */ + + use_quantizer = drv->class->xine->config->register_range(drv->class->xine->config, + "dxr3.lavc_quantizer", 1, 0, 1, + _("Dxr3enc: Use quantizer instead of bitrate"),NULL, 0, NULL, NULL); + + if (use_quantizer) { + this->context->qmin = drv->class->xine->config->register_range(drv->class->xine->config, + "dxr3.lavc_qmin", 1, 1, 10, + _("Dxr3enc: Minimum quantizer"),NULL , 10, NULL, NULL); + + this->context->qmax = drv->class->xine->config->register_range(drv->class->xine->config, + "dxr3.lavc_qmax", 2, 1, 20, + _("Dxr3enc: Maximum quantizer"),NULL, 10, NULL, NULL); + } + +#if LOG_ENC + printf("dxr3_mpeg_encoder: lavc -> bitrate %d \n", this->context->bit_rate); +#endif + + this->context->width = frame->vo_frame.width; + this->context->height = frame->oheight; + + this->context->gop_size = 0; /*intra frames only */ + this->context->me_method = ME_ZERO; /*motion estimation type*/ + + /* start guessing the framerate */ + fps = 90000.0 / frame->vo_frame.duration; +#if LOG_ENC + printf("dxr3_mpeg_encoder: fps = %f\n", fps); +#endif + + + if (fabs(fps - 25) < 0.01) { /* PAL */ +#if LOG_ENC + printf("dxr3_mpeg_encoder: setting mpeg output framerate to PAL (25 Hz)\n"); +#endif + this->context->frame_rate = 25; + this->context->frame_rate_base= 1; + } + else if (fabs(fps - 24) < 0.01) { /* FILM */ +#if LOG_ENC + printf("dxr3_mpeg_encoder: setting mpeg output framerate to FILM (24 Hz)\n"); +#endif + this->context->frame_rate = 24; + this->context->frame_rate_base= 1; + } + else if (fabs(fps - 23.976) < 0.01) { /* NTSC-FILM */ +#if LOG_ENC + printf("dxr3_mpeg_encoder: setting mpeg output framerate to NTSC-FILM (23.976 Hz)\n"); +#endif + this->context->frame_rate = 24000; + this->context->frame_rate_base= 1001; + } + else if (fabs(fps - 29.97) < 0.01) { /* NTSC */ +#if LOG_ENC + printf("dxr3_mpeg_encoder: setting mpeg output framerate to NTSC (29.97 Hz)\n"); +#endif + this->context->frame_rate = 30000; + this->context->frame_rate_base= 1001; + } else { /* will go to PAL */ + this->context->frame_rate = 25; + this->context->frame_rate_base= 1; +#if LOG_ENC + printf("dxr3_mpeg_encoder: trying to set mpeg output framerate to 25 Hz\n"); +#endif + } + + /* open avcodec */ + if (avcodec_open(this->context, codec) < 0) { + printf("dxr3_mpeg_encoder: could not open codec\n"); + return 0; + } +#if LOG_ENC + printf("dxr3_mpeg_encoder: lavc MPEG1 codec opened.\n"); +#endif + + if (!this->ffmpeg_buffer) + this->ffmpeg_buffer = (unsigned char *)malloc(DEFAULT_BUFFER_SIZE); /* why allocate more than needed ?! */ + if (!this->ffmpeg_buffer) { + printf("dxr3_mpeg_encoder: Couldn't allocate temp buffer for mpeg data\n"); + return 0; + } + + /* set the dxr3 playmode */ + if (drv->enhanced_mode) { + em8300_register_t regs; + regs.microcode_register = 1; + regs.reg = 0; + regs.val = MVCOMMAND_SYNC; + ioctl(drv->fd_control, EM8300_IOCTL_WRITEREG, ®s); + } + + return 1; +} + +static int lavc_on_display_frame(dxr3_driver_t *drv, dxr3_frame_t *frame) +{ + int size; + lavc_data_t* this = (lavc_data_t *)drv->enc; + char tmpstr[128]; + ssize_t written; + + if (frame->vo_frame.bad_frame) return 1; + /* ignore old frames */ + if ((frame->vo_frame.width != this->context->width) || (frame->oheight != this->context->height)) { + frame->vo_frame.displayed(&frame->vo_frame); + printf("LAVC ignoring frame !!!\n"); + return 1; + } + + /* prepare frame for conversion, handles YUY2 -> YV12 conversion when necessary */ + lavc_prepare_frame(this, drv, frame); + + /* do the encoding */ + size = avcodec_encode_video(this->context, this->ffmpeg_buffer, DEFAULT_BUFFER_SIZE, this->picture); + + frame->vo_frame.displayed(&frame->vo_frame); + + if (drv->fd_video == CLOSED_FOR_ENCODER) { + snprintf (tmpstr, sizeof(tmpstr), "%s_mv%s", drv->class->devname, drv->class->devnum); + drv->fd_video = open(tmpstr, O_WRONLY | O_NONBLOCK); + } + if (drv->fd_video < 0) return 0; + written = write(drv->fd_video, this->ffmpeg_buffer, size); + if (written < 0) { + printf("dxr3_mpeg_encoder: video device write failed (%s)\n", + strerror(errno)); + return 0; + } + if (written != size) + printf("dxr3_mpeg_encoder: Could only write %d of %d mpeg bytes.\n", + written, size); + return 1; +} + +static int lavc_on_unneeded(dxr3_driver_t *drv) +{ + lavc_data_t *this = (lavc_data_t *)drv->enc; +#if LOG_ENC + printf("dxr3_mpeg_encoder: flushing buffers\n"); +#endif + if (this->context) { + avcodec_close(this->context); + free(this->context); + free(this->picture); + this->context = NULL; + this->picture = NULL; + } + return 1; +} +static int lavc_prepare_frame(lavc_data_t *this, dxr3_driver_t *drv, dxr3_frame_t *frame) +{ + int i, j, w2; + uint8_t *yuy2; + + if (frame->vo_frame.bad_frame) return 1; + + if (frame->vo_frame.format == XINE_IMGFMT_YUY2) { + /* need YUY2->YV12 conversion */ + if (!(this->out[0] && this->out[1] && this->out[2]) ) { + printf("dxr3_mpeg_encoder: Internal YV12 buffer not created.\n"); + return 0; + } + this->picture->data[0] = this->out[0] + frame->vo_frame.width * drv->top_bar; /* y */ + this->picture->data[1] = this->out[1] + (frame->vo_frame.width / 2) * (drv->top_bar / 2); /* u */ + this->picture->data[2] = this->out[2] + (frame->vo_frame.width / 2) * (drv->top_bar / 2); /* v */ + yuy2 = frame->vo_frame.base[0]; + w2 = frame->vo_frame.width / 2; + for (i = 0; i < frame->vo_frame.height; i += 2) { + for (j = 0; j < w2; j++) { + /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */ + *(this->picture->data[0]++) = *(yuy2++); + *(this->picture->data[1]++) = *(yuy2++); + *(this->picture->data[0]++) = *(yuy2++); + *(this->picture->data[2]++) = *(yuy2++); + } + /* down sampling */ + for (j = 0; j < w2; j++) { + /* skip every second line for U and V */ + *(this->picture->data[0]++) = *(yuy2++); + yuy2++; + *(this->picture->data[0]++) = *(yuy2++); + yuy2++; + } + } + /* reset for encoder */ + this->picture->data[0] = this->out[0]; + this->picture->data[1] = this->out[1]; + this->picture->data[2] = this->out[2]; + } + else { /* YV12 **/ + this->picture->data[0] = frame->real_base[0]; + this->picture->data[1] = frame->real_base[1]; + this->picture->data[2] = frame->real_base[2]; + } + this->picture->linesize[0] = this->context->width; + this->picture->linesize[1] = this->context->width / 2; + this->picture->linesize[2] = this->context->width / 2; + return 1; +} -- cgit v1.2.3