1 /***************************************************************************
2                        Pulldown : Duplicate frame fields to convert
3 		       	24 fps to 30 fps movie
4 
5 			1 2 3 4       1  2  3  4  4
6 			1 2 3 4 --> 1  2  2  3  4
7 
8 
9     begin                : Thu Mar 21 2002
10     copyright            : (C) 2002 by mean
11     email                : fixounet@free.fr
12  ***************************************************************************/
13 
14 /***************************************************************************
15  *                                                                         *
16  *   This program is free software; you can redistribute it and/or modify  *
17  *   it under the terms of the GNU General Public License as published by  *
18  *   the Free Software Foundation; either version 2 of the License, or     *
19  *   (at your option) any later version.                                   *
20  *                                                                         *
21  ***************************************************************************/
22 
23 #include "ADM_default.h"
24 
25 #include "ADM_videoFilterDynamic.h"
26 #include "ADM_vidFieldUtil.h"
27 #include "ADM_interlaced.h"
28 #include "ADM_vidPulldown.h"
29 
30 #define aprintf(...) {}
31 
32 
33 static FILTER_PARAM swapParam={0,{""}};
34 //********** Register chunk ************
35 
36 VF_DEFINE_FILTER(ADMVideoPullDown,swapParam,
37                 pulldown,
38                 QT_TR_NOOP("Pulldown"),
39                 1,
40                 VF_INTERLACING,
41                 QT_TR_NOOP("Convert 24 fps to 30 fps by repeating fields."));
42 //********** Register chunk ************
43 
printConf(void)44 char *ADMVideoPullDown::printConf( void )
45 {
46  	ADM_FILTER_DECLARE_CONF(" Pulldown");
47 
48 }
49 //_______________________________________________________________
ADMVideoPullDown(AVDMGenericVideoStream * in,CONFcouple * setup)50 ADMVideoPullDown::ADMVideoPullDown(
51 									AVDMGenericVideoStream *in,CONFcouple *setup)
52 {
53 UNUSED_ARG(setup);
54   	_in=in;
55    	memcpy(&_info,_in->getInfo(),sizeof(_info));
56 	_info.fps1000=(_info.fps1000*5)/4;
57 	_info.nb_frames=(_info.nb_frames*5)/4;
58 	for(uint32_t i=0;i<5;i++)
59 	{
60 		_uncompressed[i]=new ADMImage(_info.width,_info.height);
61 	}
62 	_cacheStart=0xfffffff;
63 }
64 // ___ destructor_____________
~ADMVideoPullDown()65 ADMVideoPullDown::~ADMVideoPullDown()
66 {
67 	for(uint32_t i=0;i<5;i++)
68 	{
69  		delete  _uncompressed[i];
70 	}
71 }
72 
73 
getFrameNumberNoAlloc(uint32_t frame,uint32_t * len,ADMImage * data,uint32_t * flags)74 uint8_t ADMVideoPullDown::getFrameNumberNoAlloc(uint32_t frame,
75 				uint32_t *len,
76    				ADMImage *data,
77 				uint32_t *flags)
78 {
79 //static Image in,out;
80 			if(frame>=_info.nb_frames)
81 			{
82 				printf("out of bound frame (%lu / %lu)\n",frame,_info.nb_frames);
83 				return 0;
84 			}
85 
86 		uint32_t w=_info.width;
87 		uint32_t h=_info.height;
88 		uint32_t page=w*h;
89 		uint32_t i;
90 
91 		uint32_t target;
92 		uint32_t loop=0;
93 
94 		*len=(page*3)>>1;
95 
96 cont:
97 
98 		target=frame-((frame)%5);
99 		// got it ?
100 		if(_cacheStart==target)
101 		{
102 			uint32_t index;
103 
104 			aprintf("Filter: It is in cache...(cachestart=%lu)\n",_cacheStart);
105 			index=frame%5;
106 			aprintf("getting %lu)\n",index);
107 			memcpy(YPLANE(data),YPLANE(_uncompressed[index]),page);
108 			memcpy(UPLANE(data),UPLANE(_uncompressed[index]),page>>2);
109 			memcpy(VPLANE(data),VPLANE(_uncompressed[index]),page>>2);
110 			*flags=0;
111 			return 1;
112 		}
113 		else
114 		{
115 			aprintf("Not in cache...\n");
116 		}
117 		// Else ask the 5 corresponding frame
118 		_cacheStart=target;
119 		target=(target*4)/5;
120 
121 		uint32_t dflags,dlen;
122 #define GET_FRAME(x,y) if(!_in->getFrameNumberNoAlloc(x, &dlen,_uncompressed[y],&dflags)) \
123  {\
124 				 	 	printf("Cannot get frame %lu\n",x);\
125 					 	return 0;     \
126 				 }
127 
128 		GET_FRAME(target+0,0);
129 		GET_FRAME(target+1,1);
130 		GET_FRAME(target+2,3);
131 		GET_FRAME(target+3,4);
132 		// copy chroma 1->2
133 		memcpy(UPLANE(_uncompressed[2]),UPLANE(_uncompressed[1]),page>>2);
134 		memcpy(VPLANE(_uncompressed[2]),VPLANE(_uncompressed[1]),page>>2);
135 #define COPY_FIELD \
136 		for(uint32_t y=0;y<_info.height>>1;y++) \
137 		{ \
138 			memcpy(out,in,_info.width); \
139 			in+=_info.width<<1; \
140 			out+=_info.width<<1; \
141 		}
142 
143 		// now we merge 1 & 3 into 2
144 
145 		uint8_t *in,*out;
146 		in=YPLANE(_uncompressed[1]);
147 		out=YPLANE(_uncompressed[2]);
148 		COPY_FIELD;
149 
150 
151 		// merge 3->2
152 		//
153 		//	0 1 x 2 3
154 		//      0 1 x 2 3
155 		//
156 		//  0 1 1 2 3
157 		//  0 1 X 2 3
158 		in=YPLANE(_uncompressed[3])+w;
159 		out=YPLANE(_uncompressed[2])+w;
160 		COPY_FIELD;
161 		//  0 1 1 2 3
162 		//  0 1 2 2 3
163 		in=YPLANE(_uncompressed[4])+w;
164 		out=YPLANE(_uncompressed[3])+w;
165 		//  0 1 1 2 3
166 		//  0 1 2 3 3
167 		COPY_FIELD;
168 		goto cont;
169 		return 1;
170 }
171 
172 
173 
174