changeset 12334:eeddcef4fb08

"hard" frame duplication for mencoder. this finally makes it possible to generate valid mpeg output from avi's that have duplicate frames in them, or when using inverse telecine filters. to use it, put the "harddup" filter at the end of your filter chain.
author rfelker
date Wed, 28 Apr 2004 04:02:46 +0000
parents 80036bf4a9f5
children 189cd9abb0a1
files libmpcodecs/Makefile libmpcodecs/vf.c libmpcodecs/vf_harddup.c mencoder.c
diffstat 4 files changed, 98 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/libmpcodecs/Makefile	Wed Apr 28 03:19:35 2004 +0000
+++ b/libmpcodecs/Makefile	Wed Apr 28 04:02:46 2004 +0000
@@ -14,7 +14,7 @@
 VIDEO_SRCS_OPT=vd_realvid.c vd_ffmpeg.c vd_dshow.c vd_dmo.c vd_vfw.c vd_vfwex.c vd_odivx.c vd_divx4.c vd_zrmjpeg.c vd_xanim.c vd_xvid.c vd_xvid4.c vd_libdv.c vd_qtvideo.c vd_theora.c
 VIDEO_SRCS=dec_video.c vd.c $(VIDEO_SRCS_NAT) $(VIDEO_SRCS_LIB) $(VIDEO_SRCS_OPT)
 
-VFILTER_SRCS=vf.c vf_vo.c vf_crop.c vf_expand.c vf_scale.c vf_format.c vf_noformat.c vf_yuy2.c vf_flip.c vf_rgb2bgr.c vf_rotate.c vf_mirror.c vf_palette.c vf_lavc.c vf_dvbscale.c vf_cropdetect.c vf_test.c vf_noise.c vf_yvu9.c vf_rectangle.c vf_lavcdeint.c vf_eq.c vf_eq2.c vf_halfpack.c vf_dint.c vf_1bpp.c vf_bmovl.c vf_2xsai.c vf_unsharp.c vf_swapuv.c vf_il.c vf_boxblur.c vf_sab.c vf_smartblur.c vf_perspective.c vf_down3dright.c vf_field.c vf_denoise3d.c vf_hqdn3d.c vf_detc.c vf_telecine.c vf_tfields.c vf_ivtc.c vf_ilpack.c vf_dsize.c vf_decimate.c vf_softpulldown.c vf_tinterlace.c vf_pullup.c pullup.c vf_framestep.c vf_tile.c vf_delogo.c vf_fil.c vf_hue.c vf_spp.c vf_yuvcsp.c vf_filmdint.c vf_kerndeint.c vf_rgbtest.c vf_qp.c vf_phase.c vf_divtc.c
+VFILTER_SRCS=vf.c vf_vo.c vf_crop.c vf_expand.c vf_scale.c vf_format.c vf_noformat.c vf_yuy2.c vf_flip.c vf_rgb2bgr.c vf_rotate.c vf_mirror.c vf_palette.c vf_lavc.c vf_dvbscale.c vf_cropdetect.c vf_test.c vf_noise.c vf_yvu9.c vf_rectangle.c vf_lavcdeint.c vf_eq.c vf_eq2.c vf_halfpack.c vf_dint.c vf_1bpp.c vf_bmovl.c vf_2xsai.c vf_unsharp.c vf_swapuv.c vf_il.c vf_boxblur.c vf_sab.c vf_smartblur.c vf_perspective.c vf_down3dright.c vf_field.c vf_denoise3d.c vf_hqdn3d.c vf_detc.c vf_telecine.c vf_tfields.c vf_ivtc.c vf_ilpack.c vf_dsize.c vf_decimate.c vf_softpulldown.c vf_tinterlace.c vf_pullup.c pullup.c vf_framestep.c vf_tile.c vf_delogo.c vf_fil.c vf_hue.c vf_spp.c vf_yuvcsp.c vf_filmdint.c vf_kerndeint.c vf_rgbtest.c vf_qp.c vf_phase.c vf_divtc.c vf_harddup.c
 ifeq ($(HAVE_FFPOSTPROCESS),yes)
 VFILTER_SRCS += vf_pp.c
 endif
--- a/libmpcodecs/vf.c	Wed Apr 28 03:19:35 2004 +0000
+++ b/libmpcodecs/vf.c	Wed Apr 28 04:02:46 2004 +0000
@@ -89,6 +89,7 @@
 extern vf_info_t vf_info_qp;
 extern vf_info_t vf_info_phase;
 extern vf_info_t vf_info_divtc;
+extern vf_info_t vf_info_harddup;
 
 // list of available filters:
 static vf_info_t* filter_list[]={
@@ -171,6 +172,7 @@
 #endif
     &vf_info_phase,
     &vf_info_divtc,
+    &vf_info_harddup,
     NULL
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmpcodecs/vf_harddup.c	Wed Apr 28 04:02:46 2004 +0000
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../config.h"
+#include "../mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#include "../libvo/fastmemcpy.h"
+
+struct vf_priv_s {
+	mp_image_t *last_mpi;
+};
+
+static int put_image(struct vf_instance_s* vf, mp_image_t *mpi)
+{
+	mp_image_t *dmpi;
+	int ret;
+
+	vf->priv->last_mpi = mpi;
+	
+	dmpi = vf_get_image(vf->next, mpi->imgfmt,
+		MP_IMGTYPE_EXPORT, 0, mpi->width, mpi->height);
+
+	dmpi->planes[0] = mpi->planes[0];
+	dmpi->stride[0] = mpi->stride[0];
+	if (dmpi->flags&MP_IMGFLAG_PLANAR) {
+		dmpi->planes[1] = mpi->planes[1];
+		dmpi->stride[1] = mpi->stride[1];
+		dmpi->planes[2] = mpi->planes[2];
+		dmpi->stride[2] = mpi->stride[2];
+	}
+	
+	return vf_next_put_image(vf, dmpi);
+}
+
+static int control(struct vf_instance_s* vf, int request, void* data)
+{
+	switch (request) {
+	case VFCTRL_DUPLICATE_FRAME:
+		if (!vf->priv->last_mpi) break;
+		// This is a huge hack. We assume nothing
+		// has been called earlier in the filter chain
+		// since the last put_image. This is reasonable
+		// because we're handling a duplicate frame!
+		puts("hard dup!");
+		if (put_image(vf, vf->priv->last_mpi))
+			return CONTROL_TRUE;
+		break;
+	}
+	return vf_next_control(vf, request, data);
+}
+
+static int query_format(struct vf_instance_s* vf, unsigned int fmt)
+{
+	/* FIXME - figure out which other formats work */
+	switch (fmt) {
+	case IMGFMT_YV12:
+	case IMGFMT_IYUV:
+	case IMGFMT_I420:
+		return vf_next_query_format(vf, fmt);
+	}
+	return 0;
+}
+
+static void uninit(struct vf_instance_s* vf)
+{
+	free(vf->priv);
+}
+
+static int open(vf_instance_t *vf, char* args)
+{
+	vf->put_image = put_image;
+	vf->control = control;
+	vf->uninit = uninit;
+	vf->priv = calloc(1, sizeof(struct vf_priv_s));
+	return 1;
+}
+
+vf_info_t vf_info_harddup = {
+    "resubmit duplicate frames for encoding",
+    "harddup",
+    "Rich Felker",
+    "",
+    open,
+    NULL
+};
+
+
--- a/mencoder.c	Wed Apr 28 03:19:35 2004 +0000
+++ b/mencoder.c	Wed Apr 28 04:02:46 2004 +0000
@@ -189,6 +189,7 @@
 #endif
 
 int auto_expand=1;
+int encode_duplicates=1;
 
 // infos are empty by default
 char *info_name=NULL;
@@ -1312,7 +1313,8 @@
 	if(file_format != DEMUXER_TYPE_TV && !verbose) printf(MSGTR_DuplicateFrames,-skip_flag);
     while(skip_flag<0){
 	duplicatedframes++;
-	muxer_write_chunk(mux_v,0,0);
+	if (!encode_duplicates || vf_next_control(sh_video->vfilter, VFCTRL_DUPLICATE_FRAME, 0) != CONTROL_TRUE)
+	    muxer_write_chunk(mux_v,0,0);
 	++skip_flag;
     }
 } else