On 04/19/2010 12:17 PM, Stefano Sabatini wrote:
On date Monday 2010-04-19 00:42:37 -0700, S.N. Hemanth Meenakshisundaram
encoded:
On 04/18/2010 07:44 PM, S.N. Hemanth Meenakshisundaram wrote:
+#include "avfilter.h"
+#include<stdio.h>
+#include<stdlib.h>
+#include<string.h>
+#include<inttypes.h>
+#include<math.h>
+#include "config.h"
many of these are not required if you include "avfilter.h", also
"config.h" should be removed.
+typedef struct {
+ int mode;
+ int parity;
+ int buffered_tff;
+ double buffered_pts;
+ AVFilterPicRef *buffered_pic;
+ int stride[3];
+ uint8_t *ref[4][3];
+} YadifContext;
Please document all these fields.
+static inline void * memcpy_pic(void * dst, const void * src,
+ int bytesPerLine, int height,
+ int dstStride, int srcStride)
nits: use K&R style, plain_style variables.
+static void store_ref(YadifContext *p, uint8_t *src[3], int src_stride[3], int
width, int height) {
p is not a good name, yadif or something like that is better.
+static void filter_line_c(YadifContext *p, uint8_t *dst, uint8_t *prev,
uint8_t *cur, uint8_t *next, int w, int refs, int parity){
Split this overly long line, also p is not a good name.
+ av_log(p, AV_LOG_ERROR, "Params are : '%d'\n", refs);
AV_LOG_DEBUG, also this will crash as YadifContext is not a proper log
context.
+#if HAVE_MMX&& defined(NAMED_ASM_ARGS)
+ if(gCpuCaps.hasMMX2) __asm__ volatile("emms \n\t" : : : "memory");
+#endif
skip this, FFmpeg has no gCpuCaps.
+ av_log(NULL, AV_LOG_ERROR, "Alloc dims are : '%d, %d, %d, %ld'\n", w,
h, i, yadif);
use link->dst as the log context, replace AV_LOG_ERROR -> AV_LOG_INFO
and use a notation such as: w:%d h:%d
+ yadif->stride[i]= w;
+ for(j=0; j<3; j++)
+ yadif->ref[j][i]= (uint8_t *)(av_malloc(w*h*sizeof(uint8_t)))+3*w;
+ }
+ return 0;
+}
+
+static void continue_buffered_image(AVFilterContext *ctx);
Maybe you can avoid this forward declaration re-ordering a little the
code.
+extern int correct_pts;
Well this shouldn't be an extern int, maybe this should be a parameter
of the yadif context.
+
+static void start_frame(AVFilterLink *link, AVFilterPicRef *picref)
+{
+ AVFilterLink *out = link->dst->outputs[0];
+
+ out->outpic = avfilter_get_video_buffer(out, AV_PERM_WRITE, picref->w,
picref->h);
+ out->outpic->pts = picref->pts;
+ // out->outpic->fields = picref->fields;
Try to provide also a patch for this, it basically requires to add a
pixel format field flags to AVFilterPicRef, check
libmpcodecs/mp_image.h for ideas, that may be something like:
#define AV_PIX_FMT_FIELD_ORDERED 0x01
#define AV_PIX_FMT_FIELD_TOP_FIRST 0x02
#define AV_PIX_FMT_FIELD_REPEAT_FIRST 0x04
...
Regards.
_______________________________________________
FFmpeg-soc mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc
Hi,
I made changes as per the comments above. Deinterlacing now works,
however there are still some issues I need help on. One of them is also
seen in the original mplayer yadif :
1. We initially wait for first two frames before calling the 'filter'
function for the first time. This is so that we have a 'cur' frame and a
'next' frame. However, we do not have a 'prev' frame at this point.
'prev' frames are available only for subsequent frames. The problem is
that the filter_line_c function does a branch depending on the 'prev'
values even when 'prev' data is unavailable and thus the memory of
'prev' is uninitialized. This has no visible effect on output video but
shows up on running valgrind. The issue is not seen in mplayer initially
because the yadif there uses the assembly version of filter_line by
default. But on forcing mplayer yadif filter to use filter_line_c, the
same error is seen in valgrind for mplayer too.
I fixed it here by initializing the memory to zero (av_mallocz instead
of av_malloc for the ref array in yadif context). Is this a correct fix?
2. The second issue is a leak. I call unref_pic on both input and output
PicRefs after passing data to the next filter. Yet, memory leaks in
multiples of PicRef/Pic structure size for modes 1 and 3. For modes 0
and 2, there is a single PicRef size block leaked at the beginning.
valgrind shows the memory allocated on calling get_video_buffer is the
one that is leaked. Why is the leak still seen after calling unref pic?
I do ensure that for modes 1 and 3, I call unref pic twice for the two
output frames.
3. We need to wait for two frames initially before being able to do
deinterlacing but the filter chain does not supply a second input frame
until the first is processed and passed on. So am sending an initial
blank (all green) frame at the start of the video alone. Is this ok?
The diff is attached.
Regards,
Index: vf_yadif.c
===================================================================
--- vf_yadif.c (revision 0)
+++ vf_yadif.c (revision 0)
@@ -0,0 +1,526 @@
+/*
+ * Copyright (C) 2006 Michael Niedermayer <[email protected]>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * @file libavfilter/vf_yadif.c
+ * Yet Another Deinterlacing Filter
+ *
+ */
+
+#include "avfilter.h"
+
+typedef struct {
+ int mode; ///< deinterlace mode, modes 1 & 3 double
frame rate.
+ int parity; ///< field dominance.
+ int buffered_tff; ///< top field first - 0 (false) or 1 (true)
+ int start_deinterlace; ///< to ensure we wait for 2 input frames
before output starts.
+ double buffered_pts; ///< presentation timestamp of latest
incoming frame.
+ AVFilterPicRef *buffered_pic; ///< latest incoming frame.
+ int stride[3]; ///< stride length of incoming frames.
+ uint8_t *ref[4][3]; ///< buffer for current, next and previous
frame.
+} YadifContext;
+
+static void (*filter_line)(YadifContext *yadif, uint8_t *dst, uint8_t *prev,
+ uint8_t *cur, uint8_t *next, int w, int refs, int
parity);
+
+static inline void * memcpy_pic(void * dst, const void * src,
+ int bytes_per_line, int height,
+ int dst_stride, int src_stride)
+{
+ int i;
+ void *retval=dst;
+
+ if(dst_stride == src_stride)
+ {
+ if (src_stride < 0) {
+ src = (const uint8_t*)src + (height-1)*src_stride;
+ dst = (uint8_t*)dst + (height-1)*dst_stride;
+ src_stride = -src_stride;
+ }
+ memcpy(dst, src, src_stride*height);
+ }
+ else
+ {
+ for(i=0; i<height; i++)
+ {
+ memcpy(dst, src, bytes_per_line);
+ src = (const uint8_t*)src + src_stride;
+ dst = (uint8_t*)dst + dst_stride;
+ }
+ }
+ return retval;
+}
+
+static void store_ref(YadifContext *yadif, uint8_t *src[3], int src_stride[3],
int width, int height) {
+ int i;
+
+ memcpy(yadif->ref[3], yadif->ref[0], sizeof(uint8_t *)*3);
+ memmove(yadif->ref[0], yadif->ref[1], sizeof(uint8_t *)*3*3);
+
+ for(i=0; i<3; i++){
+ int is_chroma= !!i;
+ memcpy_pic(yadif->ref[2][i], src[i], width>>is_chroma,
height>>is_chroma, yadif->stride[i], src_stride[i]);
+ }
+}
+
+#if HAVE_MMX && defined(NAMED_ASM_ARGS)
+
+#define LOAD4(mem,dst) \
+ "movd "mem", "#dst" \n\t"\
+ "punpcklbw %%mm7, "#dst" \n\t"
+
+#define PABS(tmp,dst) \
+ "pxor "#tmp", "#tmp" \n\t"\
+ "psubw "#dst", "#tmp" \n\t"\
+ "pmaxsw "#tmp", "#dst" \n\t"
+
+#define CHECK(pj,mj) \
+ "movq "#pj"(%[cur],%[mrefs]), %%mm2 \n\t" /* cur[x-refs-1+j] */\
+ "movq "#mj"(%[cur],%[prefs]), %%mm3 \n\t" /* cur[x+refs-1-j] */\
+ "movq %%mm2, %%mm4 \n\t"\
+ "movq %%mm2, %%mm5 \n\t"\
+ "pxor %%mm3, %%mm4 \n\t"\
+ "pavgb %%mm3, %%mm5 \n\t"\
+ "pand %[pb1], %%mm4 \n\t"\
+ "psubusb %%mm4, %%mm5 \n\t"\
+ "psrlq $8, %%mm5 \n\t"\
+ "punpcklbw %%mm7, %%mm5 \n\t" /* (cur[x-refs+j] +
cur[x+refs-j])>>1 */\
+ "movq %%mm2, %%mm4 \n\t"\
+ "psubusb %%mm3, %%mm2 \n\t"\
+ "psubusb %%mm4, %%mm3 \n\t"\
+ "pmaxub %%mm3, %%mm2 \n\t"\
+ "movq %%mm2, %%mm3 \n\t"\
+ "movq %%mm2, %%mm4 \n\t" /* ABS(cur[x-refs-1+j] -
cur[x+refs-1-j]) */\
+ "psrlq $8, %%mm3 \n\t" /* ABS(cur[x-refs +j] - cur[x+refs
-j]) */\
+ "psrlq $16, %%mm4 \n\t" /* ABS(cur[x-refs+1+j] -
cur[x+refs+1-j]) */\
+ "punpcklbw %%mm7, %%mm2 \n\t"\
+ "punpcklbw %%mm7, %%mm3 \n\t"\
+ "punpcklbw %%mm7, %%mm4 \n\t"\
+ "paddw %%mm3, %%mm2 \n\t"\
+ "paddw %%mm4, %%mm2 \n\t" /* score */
+
+#define CHECK1 \
+ "movq %%mm0, %%mm3 \n\t"\
+ "pcmpgtw %%mm2, %%mm3 \n\t" /* if(score < spatial_score) */\
+ "pminsw %%mm2, %%mm0 \n\t" /* spatial_score= score; */\
+ "movq %%mm3, %%mm6 \n\t"\
+ "pand %%mm3, %%mm5 \n\t"\
+ "pandn %%mm1, %%mm3 \n\t"\
+ "por %%mm5, %%mm3 \n\t"\
+ "movq %%mm3, %%mm1 \n\t" /* spatial_pred= (cur[x-refs+j] +
cur[x+refs-j])>>1; */
+
+#define CHECK2 /* pretend not to have checked dir=2 if dir=1 was bad.\
+ hurts both quality and speed, but matches the C version. */\
+ "paddw %[pw1], %%mm6 \n\t"\
+ "psllw $14, %%mm6 \n\t"\
+ "paddsw %%mm6, %%mm2 \n\t"\
+ "movq %%mm0, %%mm3 \n\t"\
+ "pcmpgtw %%mm2, %%mm3 \n\t"\
+ "pminsw %%mm2, %%mm0 \n\t"\
+ "pand %%mm3, %%mm5 \n\t"\
+ "pandn %%mm1, %%mm3 \n\t"\
+ "por %%mm5, %%mm3 \n\t"\
+ "movq %%mm3, %%mm1 \n\t"
+
+static void filter_line_mmx2(YadifContext *yadif, uint8_t *dst, uint8_t *prev,
+ uint8_t *cur, uint8_t *next, int w, int refs, int
parity) {
+ static const uint64_t pw_1 = 0x0001000100010001ULL;
+ static const uint64_t pb_1 = 0x0101010101010101ULL;
+ const int mode = yadif->mode;
+ uint64_t tmp0, tmp1, tmp2, tmp3;
+ int x;
+
+#define FILTER\
+ for(x=0; x<w; x+=4){\
+ __asm__ volatile(\
+ "pxor %%mm7, %%mm7 \n\t"\
+ LOAD4("(%[cur],%[mrefs])", %%mm0) /* c = cur[x-refs] */\
+ LOAD4("(%[cur],%[prefs])", %%mm1) /* e = cur[x+refs] */\
+ LOAD4("(%["prev2"])", %%mm2) /* prev2[x] */\
+ LOAD4("(%["next2"])", %%mm3) /* next2[x] */\
+ "movq %%mm3, %%mm4 \n\t"\
+ "paddw %%mm2, %%mm3 \n\t"\
+ "psraw $1, %%mm3 \n\t" /* d = (prev2[x] + next2[x])>>1 */\
+ "movq %%mm0, %[tmp0] \n\t" /* c */\
+ "movq %%mm3, %[tmp1] \n\t" /* d */\
+ "movq %%mm1, %[tmp2] \n\t" /* e */\
+ "psubw %%mm4, %%mm2 \n\t"\
+ PABS( %%mm4, %%mm2) /* temporal_diff0 */\
+ LOAD4("(%[prev],%[mrefs])", %%mm3) /* prev[x-refs] */\
+ LOAD4("(%[prev],%[prefs])", %%mm4) /* prev[x+refs] */\
+ "psubw %%mm0, %%mm3 \n\t"\
+ "psubw %%mm1, %%mm4 \n\t"\
+ PABS( %%mm5, %%mm3)\
+ PABS( %%mm5, %%mm4)\
+ "paddw %%mm4, %%mm3 \n\t" /* temporal_diff1 */\
+ "psrlw $1, %%mm2 \n\t"\
+ "psrlw $1, %%mm3 \n\t"\
+ "pmaxsw %%mm3, %%mm2 \n\t"\
+ LOAD4("(%[next],%[mrefs])", %%mm3) /* next[x-refs] */\
+ LOAD4("(%[next],%[prefs])", %%mm4) /* next[x+refs] */\
+ "psubw %%mm0, %%mm3 \n\t"\
+ "psubw %%mm1, %%mm4 \n\t"\
+ PABS( %%mm5, %%mm3)\
+ PABS( %%mm5, %%mm4)\
+ "paddw %%mm4, %%mm3 \n\t" /* temporal_diff2 */\
+ "psrlw $1, %%mm3 \n\t"\
+ "pmaxsw %%mm3, %%mm2 \n\t"\
+ "movq %%mm2, %[tmp3] \n\t" /* diff */\
+\
+ "paddw %%mm0, %%mm1 \n\t"\
+ "paddw %%mm0, %%mm0 \n\t"\
+ "psubw %%mm1, %%mm0 \n\t"\
+ "psrlw $1, %%mm1 \n\t" /* spatial_pred */\
+ PABS( %%mm2, %%mm0) /* ABS(c-e) */\
+\
+ "movq -1(%[cur],%[mrefs]), %%mm2 \n\t" /* cur[x-refs-1] */\
+ "movq -1(%[cur],%[prefs]), %%mm3 \n\t" /* cur[x+refs-1] */\
+ "movq %%mm2, %%mm4 \n\t"\
+ "psubusb %%mm3, %%mm2 \n\t"\
+ "psubusb %%mm4, %%mm3 \n\t"\
+ "pmaxub %%mm3, %%mm2 \n\t"\
+ "pshufw $9,%%mm2, %%mm3 \n\t"\
+ "punpcklbw %%mm7, %%mm2 \n\t" /* ABS(cur[x-refs-1] -
cur[x+refs-1]) */\
+ "punpcklbw %%mm7, %%mm3 \n\t" /* ABS(cur[x-refs+1] -
cur[x+refs+1]) */\
+ "paddw %%mm2, %%mm0 \n\t"\
+ "paddw %%mm3, %%mm0 \n\t"\
+ "psubw %[pw1], %%mm0 \n\t" /* spatial_score */\
+\
+ CHECK(-2,0)\
+ CHECK1\
+ CHECK(-3,1)\
+ CHECK2\
+ CHECK(0,-2)\
+ CHECK1\
+ CHECK(1,-3)\
+ CHECK2\
+\
+ /* if(yadif->mode<2) ... */\
+ "movq %[tmp3], %%mm6 \n\t" /* diff */\
+ "cmp $2, %[mode] \n\t"\
+ "jge 1f \n\t"\
+ LOAD4("(%["prev2"],%[mrefs],2)", %%mm2) /* prev2[x-2*refs] */\
+ LOAD4("(%["next2"],%[mrefs],2)", %%mm4) /* next2[x-2*refs] */\
+ LOAD4("(%["prev2"],%[prefs],2)", %%mm3) /* prev2[x+2*refs] */\
+ LOAD4("(%["next2"],%[prefs],2)", %%mm5) /* next2[x+2*refs] */\
+ "paddw %%mm4, %%mm2 \n\t"\
+ "paddw %%mm5, %%mm3 \n\t"\
+ "psrlw $1, %%mm2 \n\t" /* b */\
+ "psrlw $1, %%mm3 \n\t" /* f */\
+ "movq %[tmp0], %%mm4 \n\t" /* c */\
+ "movq %[tmp1], %%mm5 \n\t" /* d */\
+ "movq %[tmp2], %%mm7 \n\t" /* e */\
+ "psubw %%mm4, %%mm2 \n\t" /* b-c */\
+ "psubw %%mm7, %%mm3 \n\t" /* f-e */\
+ "movq %%mm5, %%mm0 \n\t"\
+ "psubw %%mm4, %%mm5 \n\t" /* d-c */\
+ "psubw %%mm7, %%mm0 \n\t" /* d-e */\
+ "movq %%mm2, %%mm4 \n\t"\
+ "pminsw %%mm3, %%mm2 \n\t"\
+ "pmaxsw %%mm4, %%mm3 \n\t"\
+ "pmaxsw %%mm5, %%mm2 \n\t"\
+ "pminsw %%mm5, %%mm3 \n\t"\
+ "pmaxsw %%mm0, %%mm2 \n\t" /* max */\
+ "pminsw %%mm0, %%mm3 \n\t" /* min */\
+ "pxor %%mm4, %%mm4 \n\t"\
+ "pmaxsw %%mm3, %%mm6 \n\t"\
+ "psubw %%mm2, %%mm4 \n\t" /* -max */\
+ "pmaxsw %%mm4, %%mm6 \n\t" /* diff= MAX3(diff, min, -max); */\
+ "1: \n\t"\
+\
+ "movq %[tmp1], %%mm2 \n\t" /* d */\
+ "movq %%mm2, %%mm3 \n\t"\
+ "psubw %%mm6, %%mm2 \n\t" /* d-diff */\
+ "paddw %%mm6, %%mm3 \n\t" /* d+diff */\
+ "pmaxsw %%mm2, %%mm1 \n\t"\
+ "pminsw %%mm3, %%mm1 \n\t" /* d = clip(spatial_pred, d-diff,
d+diff); */\
+ "packuswb %%mm1, %%mm1 \n\t"\
+\
+ :[tmp0]"=m"(tmp0),\
+ [tmp1]"=m"(tmp1),\
+ [tmp2]"=m"(tmp2),\
+ [tmp3]"=m"(tmp3)\
+ :[prev] "r"(prev),\
+ [cur] "r"(cur),\
+ [next] "r"(next),\
+ [prefs]"r"((x86_reg)refs),\
+ [mrefs]"r"((x86_reg)-refs),\
+ [pw1] "m"(pw_1),\
+ [pb1] "m"(pb_1),\
+ [mode] "g"(mode)\
+ );\
+ __asm__ volatile("movd %%mm1, %0" :"=m"(*dst));\
+ dst += 4;\
+ prev+= 4;\
+ cur += 4;\
+ next+= 4;\
+ }
+
+ if(parity){
+#define prev2 "prev"
+#define next2 "cur"
+ FILTER
+#undef prev2
+#undef next2
+ }else{
+#define prev2 "cur"
+#define next2 "next"
+ FILTER
+#undef prev2
+#undef next2
+ }
+}
+#undef LOAD4
+#undef PABS
+#undef CHECK
+#undef CHECK1
+#undef CHECK2
+#undef FILTER
+
+#endif /* HAVE_MMX && defined(NAMED_ASM_ARGS) */
+
+static void filter_line_c(YadifContext *yadif, uint8_t *dst, uint8_t *prev,
+ uint8_t *cur, uint8_t *next, int w, int refs, int
parity) {
+ int x;
+ uint8_t *prev2= parity ? prev : cur ;
+ uint8_t *next2= parity ? cur : next;
+ for(x=0; x<w; x++) {
+ int c= cur[-refs];
+ int d= (prev2[0] + next2[0])>>1;
+ int e= cur[+refs];
+ int temporal_diff0= FFABS(prev2[0] - next2[0]);
+ int temporal_diff1=( FFABS(prev[-refs] - c) + FFABS(prev[+refs] - e)
)>>1;
+ int temporal_diff2=( FFABS(next[-refs] - c) + FFABS(next[+refs] - e)
)>>1;
+ int diff= FFMAX3(temporal_diff0>>1, temporal_diff1, temporal_diff2);
+ int spatial_pred= (c+e)>>1;
+ int spatial_score= FFABS(cur[-refs-1] - cur[+refs-1]) + FFABS(c-e)
+ + FFABS(cur[-refs+1] - cur[+refs+1]) - 1;
+
+#define CHECK(j)\
+ { int score= FFABS(cur[-refs-1+j] - cur[+refs-1-j])\
+ + FFABS(cur[-refs +j] - cur[+refs -j])\
+ + FFABS(cur[-refs+1+j] - cur[+refs+1-j]);\
+ if(score < spatial_score) {\
+ spatial_score= score;\
+ spatial_pred= (cur[-refs +j] + cur[+refs -j])>>1;\
+
+ CHECK(-1) CHECK(-2) }} }}
+ CHECK( 1) CHECK( 2) }} }}
+
+ if(yadif->mode<2) {
+ int b= (prev2[-2*refs] + next2[-2*refs])>>1;
+ int f= (prev2[+2*refs] + next2[+2*refs])>>1;
+#if 0
+ int a= cur[-3*refs];
+ int g= cur[+3*refs];
+ int max= FFMAX3(d-e, d-c,
FFMIN3(FFMAX(b-c,f-e),FFMAX(b-c,b-a),FFMAX(f-g,f-e)) );
+ int min= FFMIN3(d-e, d-c,
FFMAX3(FFMIN(b-c,f-e),FFMIN(b-c,b-a),FFMIN(f-g,f-e)) );
+#else
+ int max= FFMAX3(d-e, d-c, FFMIN(b-c, f-e));
+ int min= FFMIN3(d-e, d-c, FFMAX(b-c, f-e));
+#endif
+
+ diff= FFMAX3(diff, min, -max);
+ }
+
+ if(spatial_pred > d + diff)
+ spatial_pred = d + diff;
+ else if(spatial_pred < d - diff)
+ spatial_pred = d - diff;
+
+ dst[0] = spatial_pred;
+
+ dst++;
+ cur++;
+ prev++;
+ next++;
+ prev2++;
+ next2++;
+ }
+}
+
+static void filter(YadifContext *yadif, uint8_t *dst[3], int dst_stride[3],
+ int width, int height, int parity, int tff) {
+ int y, i;
+
+ for(i=0; i<3; i++) {
+ int is_chroma= !!i;
+ int w= width >>is_chroma;
+ int h= height>>is_chroma;
+ int refs= yadif->stride[i];
+
+ for(y=0; y<h; y++) {
+ if((y ^ parity) & 1) {
+ uint8_t *prev= &yadif->ref[0][i][y*refs];
+ uint8_t *cur = &yadif->ref[1][i][y*refs];
+ uint8_t *next= &yadif->ref[2][i][y*refs];
+ uint8_t *dst2= &dst[i][y*dst_stride[i]];
+ filter_line(yadif, dst2, prev, cur, next, w, refs, parity ^
tff);
+ } else {
+ memcpy(&dst[i][y*dst_stride[i]], &yadif->ref[1][i][y*refs], w);
+ }
+ }
+ }
+}
+
+static int config_props_input(AVFilterLink *link)
+{
+ YadifContext *yadif = link->dst->priv;
+ int i, j;
+
+ for(i=0; i<3; i++) {
+ int is_chroma= !!i;
+ int w= ((link->w + 31) & (~31))>>is_chroma;
+ int h= ((link->h + 6 + 31) & (~31))>>is_chroma;
+
+ yadif->stride[i]= w;
+ for(j=0; j<3; j++)
+ yadif->ref[j][i]= (uint8_t *)(av_mallocz(w*h*sizeof(uint8_t)))+3*w;
+ }
+ return 0;
+}
+
+static void continue_buffered_image(AVFilterContext *ctx)
+{
+ YadifContext *yadif = ctx->priv;
+ AVFilterPicRef *picref = yadif->buffered_pic;
+ AVFilterPicRef *dpicref = ctx->outputs[0]->outpic;
+ AVFilterLink *out = ctx->outputs[0];
+ int tff = yadif->buffered_tff;
+ int i;
+
+ dpicref = avfilter_get_video_buffer(out, AV_PERM_WRITE, picref->w,
picref->h);
+ if(yadif->start_deinterlace == 0) {
+ yadif->start_deinterlace = 1;
+ dpicref->pts = picref->pts;
+ dpicref->pos = picref->pos;
+ dpicref->fields = picref->fields;
+ avfilter_start_frame(out, avfilter_ref_pic(dpicref, ~0));
+ avfilter_unref_pic(picref);
+ avfilter_draw_slice(out, 0, dpicref->h, 1);
+ avfilter_end_frame(out);
+ avfilter_unref_pic(dpicref);
+ return;
+ }
+
+ for(i = 0; i<=(yadif->mode & 1); i++) {
+ dpicref->pts = picref->pts + i*0.02; // FIXME : Assuming 2*25fps here
+ dpicref->fields = picref->fields;
+ dpicref->pos = picref->pos;
+ filter(yadif, dpicref->data, dpicref->linesize, picref->w, picref->h,
i ^ tff ^ 1, tff);
+ avfilter_start_frame(out, avfilter_ref_pic(dpicref, ~0));
+ avfilter_draw_slice(out, 0, dpicref->h, 1);
+ avfilter_end_frame(out);
+ avfilter_unref_pic(dpicref);
+ if(i < (yadif->mode & 1))
+ dpicref = avfilter_get_video_buffer(out, AV_PERM_WRITE, picref->w,
picref->h);
+ }
+ avfilter_unref_pic(picref);
+ return;
+}
+
+static void start_frame(AVFilterLink *link, AVFilterPicRef *picref)
+{
+ return;
+}
+
+static void end_frame(AVFilterLink *link)
+{
+ YadifContext *yadif = link->dst->priv;
+ AVFilterPicRef *picref = link->cur_pic;
+ int tff;
+
+ if(yadif->parity < 0) {
+ if (picref->fields & MP_IMGFIELD_ORDERED)
+ tff = !!(picref->fields & MP_IMGFIELD_TOP_FIRST);
+ else
+ tff = 1;
+ } else
+ tff = (yadif->parity&1)^1;
+
+ store_ref(yadif, picref->data, picref->linesize, picref->w, picref->h);
+
+ yadif->buffered_pic = picref;
+ yadif->buffered_tff = tff;
+ yadif->buffered_pts = picref->pts;
+
+ continue_buffered_image(link->dst);
+ return;
+}
+
+static void uninit(AVFilterContext *ctx){
+ int i;
+ YadifContext *yadif = ctx->priv;
+ if(!yadif) return;
+
+ for(i=0; i<3*3; i++) {
+ uint8_t **p= &yadif->ref[i%3][i/3];
+ if(*p) av_free(*p - 3*yadif->stride[i/3]);
+ *p= NULL;
+ }
+}
+
+static int query_formats(AVFilterContext *ctx)
+{
+ enum PixelFormat pix_fmts[] = {
+ PIX_FMT_YUV420P, PIX_FMT_GRAY8, PIX_FMT_NONE
+ };
+
+ avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
+ return 0;
+}
+
+static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
+{
+ YadifContext *yadif = ctx->priv;
+ yadif->mode = 0;
+ yadif->parity = -1;
+ yadif->start_deinterlace = 0;
+
+ if (args)
+ sscanf(args, "%d:%d", &yadif->mode, &yadif->parity);
+
+ filter_line = filter_line_c;
+
+ return 0;
+}
+
+AVFilter avfilter_vf_yadif =
+{
+ .name = "yadif",
+ .description = "Yet Another DeInterlacing Filter",
+ .priv_size = sizeof(YadifContext),
+ .init = init,
+ .uninit = uninit,
+
+ .query_formats = query_formats,
+
+ .inputs = (AVFilterPad[]) {{ .name = "default",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .start_frame = start_frame,
+ .end_frame = end_frame,
+ .config_props = config_props_input,
+ .min_perms = AV_PERM_READ, },
+ { .name = NULL}},
+ .outputs = (AVFilterPad[]) {{ .name = "default",
+ .type = AVMEDIA_TYPE_VIDEO, },
+ { .name = NULL}},
+};
+
Index: avfilter.h
===================================================================
--- avfilter.h (revision 22749)
+++ avfilter.h (working copy)
@@ -62,6 +62,14 @@
/* TODO: look for other flags which may be useful in this structure (interlace
* flags, etc)
*/
+
+#define MP_IMGFIELD_ORDERED 0x01
+#define MP_IMGFIELD_TOP_FIRST 0x02
+#define MP_IMGFIELD_REPEAT_FIRST 0x04
+#define MP_IMGFIELD_TOP 0x08
+#define MP_IMGFIELD_BOTTOM 0x10
+#define MP_IMGFIELD_INTERLACED 0x20
+
/**
* A reference-counted picture data type used by the filter system. Filters
* should not store pointers to this structure directly, but instead use the
@@ -86,6 +94,7 @@
void (*free)(struct AVFilterPic *pic);
int w, h; ///< width and height of the allocated buffer
+ int fields; ///< field ordering
} AVFilterPic;
/**
@@ -103,6 +112,7 @@
int linesize[4]; ///< number of bytes per line
int w; ///< image width
int h; ///< image height
+ int fields; ///< field ordering
int64_t pts; ///< presentation timestamp in units of
1/AV_TIME_BASE
int64_t pos; ///< byte position in stream, -1 if unknown
_______________________________________________
FFmpeg-soc mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc