1
/***************************************************************************
5
copyright : (C) 2002 by mean
6
email : fixounet@free.fr
7
***************************************************************************/
9
/***************************************************************************
11
* This program is free software; you can redistribute it and/or modify *
12
* it under the terms of the GNU General Public License as published by *
13
* the Free Software Foundation; either version 2 of the License, or *
14
* (at your option) any later version. *
16
***************************************************************************/
23
#include <ADM_assert.h>
33
#include "ADM_toolkit/toolkit.hxx"
34
#include "ADM_editor/ADM_edit.hxx"
35
#include "ADM_video/ADM_genvideo.hxx"
36
#include "ADM_filter/video_filters.h"
37
#include "ADM_userInterfaces/ADM_commonUI/DIA_enter.h"
38
#include "ADM_video/ADM_cache.h"
39
#include "ADM_osSupport/ADM_cpuCap.h"
40
#include "admmangle.h"
42
#include "ADM_userInterfaces/ADM_commonUI/DIA_factory.h"
44
static FILTER_PARAM ResampParam={2,{"newfps","use_linear"}};
45
typedef struct FPS_Param
50
class ADMVideoResampleFPS:public AVDMGenericVideoStream
54
AVDMGenericVideoStream *_in;
55
virtual char *printConf(void);
60
ADMVideoResampleFPS( AVDMGenericVideoStream *in,CONFcouple *setup);
61
ADMVideoResampleFPS( AVDMGenericVideoStream *in,uint32_t target1000);
62
virtual ~ADMVideoResampleFPS();
63
virtual uint8_t configure(AVDMGenericVideoStream *in);
64
virtual uint8_t getFrameNumberNoAlloc(uint32_t frame, uint32_t *len,
65
ADMImage *data,uint32_t *flags);
67
uint8_t getCoupledConf( CONFcouple **couples);
70
SCRIPT_CREATE(resamplefps_script,ADMVideoResampleFPS,ResampParam);
71
BUILD_CREATE(resamplefps_create,ADMVideoResampleFPS);
73
AVDMGenericVideoStream *createResampleFps(AVDMGenericVideoStream *in,uint32_t targetfps1000)
75
return new ADMVideoResampleFPS(in,targetfps1000);
78
uint8_t ADMVideoResampleFPS::configure(AVDMGenericVideoStream *in)
80
float f=_param->newfps;
85
diaElemFloat fps(&f,QT_TR_NOOP("_New frame rate:"),1,200.);
86
diaElemToggle blend(&(_param->use_linear),QT_TR_NOOP("_Blend"));
88
diaElem *elems[2]={&fps,&blend};
90
if( diaFactoryRun(QT_TR_NOOP("Resample fps"),2,elems))
93
_param->newfps=(uint32_t)floor(f+0.4);
94
_info.fps1000=_param->newfps;
99
char *ADMVideoResampleFPS::printConf( void )
103
sprintf((char *)buf," Resample to %2.2f fps (blend:%d)",(double)_param->newfps/1000.,
108
ADMVideoResampleFPS::ADMVideoResampleFPS( AVDMGenericVideoStream *in,uint32_t target)
112
memcpy(&_info,_in->getInfo(),sizeof(_info));
114
_param=new FPS_Param;
116
_param->newfps =target;
117
_param->use_linear=1;
121
newlength=_info.nb_frames;
122
newlength/=_info.fps1000;
123
newlength*=_param->newfps;
124
_info.nb_frames=(uint32_t)floor(newlength);
125
_info.fps1000=_param->newfps;
126
printf("[Resample FPS] %u -> %u\n",_in->getInfo()->nb_frames,_info.nb_frames);
127
vidCache=new VideoCache(3,_in);
131
ADMVideoResampleFPS::ADMVideoResampleFPS( AVDMGenericVideoStream *in,CONFcouple *couples)
135
memcpy(&_info,_in->getInfo(),sizeof(_info));
137
_param=new FPS_Param;
146
_param->newfps =_info.fps1000;
147
_param->use_linear=0;
152
newlength=_info.nb_frames;
153
newlength/=_info.fps1000;
154
newlength*=_param->newfps;
155
_info.nb_frames=(uint32_t)floor(newlength);
156
_info.fps1000=_param->newfps;
157
vidCache=new VideoCache(3,_in);
160
ADMVideoResampleFPS::~ADMVideoResampleFPS()
166
uint8_t ADMVideoResampleFPS::getCoupledConf( CONFcouple **couples)
169
*couples=new CONFcouple(2);
176
#if (defined( ARCH_X86) || defined(ARCH_X86_64))
177
static uint64_t low,high;
178
static void blendMMX(uint8_t *src, uint8_t *src2, uint8_t *dst, uint8_t alpha, uint8_t beta,uint32_t count)
180
uint32_t left=count&3;
181
#define EXPAND(x) (x)+((x)<<16)+((x)<<32) +((x)<<48)
188
__asm__ __volatile__ (
189
"movq "Mangle(high)", %mm0\n"
190
"movq "Mangle(low)", %mm1\n"
194
__asm__ __volatile__ (
195
"movq "Mangle(high)", %%mm0\n"
196
"movq "Mangle(low)", %%mm1\n"
197
"pxor %%mm7 , %%mm7\n"
203
__asm__ __volatile__ (
208
"punpcklbw %%mm7, %%mm2\n"
209
"punpcklbw %%mm7, %%mm3\n"
211
"pmullw %%mm0, %%mm2\n"
212
"pmullw %%mm1, %%mm3\n"
214
"paddw %%mm3, %%mm2\n"
218
"packuswb %%mm2,%%mm2\n"
221
:: "r" (src), "r" (src2), "r" (dst) );
228
__asm__ __volatile__ (
231
for(uint32_t i=0;i<left;i++)
233
dst[i] = ((src[i]*alpha) + (src2[i]*beta))>>8;
239
uint8_t ADMVideoResampleFPS::getFrameNumberNoAlloc(uint32_t frame,
244
ADMImage *mysrc1=NULL;
245
ADMImage *mysrc2=NULL;
247
if(frame>=_info.nb_frames) return 0;
248
// read uncompressed frame
250
// What frame are we seeking ?
252
uint32_t page=_info.width*_info.height;
255
f*=_in->getInfo()->fps1000;
258
if(!_param->use_linear)
262
nw=(uint32_t)floor(f+0.4);
263
if(nw>_in->getInfo()->nb_frames-1)
264
nw=_in->getInfo()->nb_frames-1;
266
mysrc1=vidCache->getImage(nw);
267
if(!mysrc1) return 0;
269
memcpy(YPLANE(data),YPLANE(mysrc1),page);
270
memcpy(UPLANE(data),UPLANE(mysrc1),page>>2);
271
memcpy(VPLANE(data),VPLANE(mysrc1),page>>2);
273
vidCache->unlockAll();
277
/* With linear blending */
284
nw=(uint32_t)floor(f);
286
highweight = (uint8_t)floor(diff*256);
287
lowweight = 256 - highweight;
289
if(nw>=_in->getInfo()->nb_frames-1)
291
printf("[ResampleFps] In %u Out %u\n",frame,nw);
292
nw=_in->getInfo()->nb_frames-1;
295
//printf("New:%lu old:%lu\n",frame,nw);
299
mysrc1=vidCache->getImage(nw);
300
if(!mysrc1) return 0;
302
memcpy(YPLANE(data),YPLANE(mysrc1),page);
303
memcpy(UPLANE(data),UPLANE(mysrc1),page>>2);
304
memcpy(VPLANE(data),VPLANE(mysrc1),page>>2);
306
vidCache->unlockAll();
310
mysrc1=vidCache->getImage(nw);
311
mysrc2=vidCache->getImage(nw+1);
312
if(!mysrc1 || !mysrc2) return 0;
314
uint8_t *out, *in1, *in2;
319
in1 = YPLANE(mysrc1);
320
in2 = YPLANE(mysrc2);
324
#if (defined( ARCH_X86) || defined(ARCH_X86_64))
325
if(CpuCaps::hasMMX())
326
blendMMX(in1,in2,out,lowweight,highweight,(count*3)>>1);
330
for(idx = 0; idx < count; ++idx)
331
out[idx] = ((in1[idx]*lowweight) + (in2[idx]*highweight))>>8;
334
in1 = UPLANE(mysrc1);
335
in2 = UPLANE(mysrc2);
338
for(idx = 0; idx < count; ++idx)
339
out[idx] = ((in1[idx]*lowweight) + (in2[idx]*highweight))>>8;
343
in1 = VPLANE(mysrc1);
344
in2 = VPLANE(mysrc2);
347
for(idx = 0; idx < count; ++idx)
348
out[idx] = ((in1[idx]*lowweight) + (in2[idx]*highweight))>>8;
351
vidCache->unlockAll();