1
/***************************************************************************
2
ADM_vidDenoise.cpp - description
4
begin : Mon Nov 25 2002
5
copyright : (C) 2002 by mean
6
email : fixounet@free.fr
8
Denoiser inspired from DNR in transcode
9
Ported to YV12 and simplified
11
Original code Copyright (C) Gerhard Monzel - November 2001
14
***************************************************************************/
16
/***************************************************************************
18
* This program is free software; you can redistribute it and/or modify *
19
* it under the terms of the GNU General Public License as published by *
20
* the Free Software Foundation; either version 2 of the License, or *
21
* (at your option) any later version. *
23
***************************************************************************/
27
#include <ADM_assert.h>
37
#include "ADM_toolkit/toolkit.hxx"
38
#include "ADM_editor/ADM_edit.hxx"
39
#include "ADM_video/ADM_genvideo.hxx"
40
#include "ADM_video/ADM_vidDenoise.h"
41
#include "ADM_filter/video_filters.h"
44
static FILTER_PARAM denoiseParam={5,{"lumaLock","lumaThreshold","chromaLock","chromaThreshold",
48
SCRIPT_CREATE(denoise_script,ADMVideoDenoise,denoiseParam);
50
uint8_t distMatrix[256][256];
53
//static uint8_t matrixReady=0;
54
//static uint8_t doOnePix(uint8_t *in,uint8_t *out,uint8_t *lock,uint8_t *nb);
56
BUILD_CREATE(denoise_create,ADMVideoDenoise);
57
char *ADMVideoDenoise::printConf( void )
62
sprintf((char *)buf," Denoise : Lum :%02ld/:%02ld / Chm :%02ld/%02ld",
64
_param->lumaThreshold,
66
_param->chromaThreshold);
69
void buildDistMatrix( void );
70
void buildDistMatrix( void )
73
for(uint32_t y=255;y>0;y--)
74
for(uint32_t x=255;x>0;x--)
89
//_______________________________________________________________
91
ADMVideoDenoise::ADMVideoDenoise(
92
AVDMGenericVideoStream *in,CONFcouple *couples)
97
memcpy(&_info,_in->getInfo(),sizeof(_info));
102
page= _in->getInfo()->width*_in->getInfo()->height;
104
// _uncompressed=new uint8_t [page];
105
_uncompressed=new ADMImage(_in->getInfo()->width,_in->getInfo()->height);
106
ADM_assert(_uncompressed);
108
// _locked=new uint8_t [page];
109
_locked=new ADMImage(_in->getInfo()->width,_in->getInfo()->height);
112
// _lockcount=new uint8_t [page];
116
_lockcount=new ADMImage(_in->getInfo()->width,_in->getInfo()->height);
117
memset(YPLANE(_lockcount),0,page);
118
memset(UPLANE(_lockcount),0,page>>2);
119
memset(VPLANE(_lockcount),0,page>>2);
125
_param=NEW(NOISE_PARAM);
129
GET(chromaThreshold);
135
_param=NEW(NOISE_PARAM);
136
_param->lumaLock= 4*XXX;
137
_param->lumaThreshold= 10*XXX;
138
_param->chromaLock= 8*XXX;
139
_param->chromaThreshold= 16*XXX;
140
_param->sceneChange= 30*XXX;
142
_lastFrame=0xfffffff0;
146
uint8_t ADMVideoDenoise::getCoupledConf( CONFcouple **couples)
150
*couples=new CONFcouple(5);
152
#define CSET(x) (*couples)->setCouple((char *)#x,(_param->x))
156
CSET(chromaThreshold);
162
ADMVideoDenoise::~ADMVideoDenoise()
165
delete _uncompressed;
170
_uncompressed=_locked=_lockcount=NULL;
174
// Remove y and v just keep U and expand it
176
uint8_t ADMVideoDenoise::getFrameNumberNoAlloc(uint32_t frame,
184
ADM_assert(frame<_info.nb_frames);
187
if(!_in->getFrameNumberNoAlloc(frame, len,_uncompressed,flags)) return 0;
190
page=_info.width*_info.height;
193
if((_lastFrame+1)!=frame) // async jump
196
memcpy(YPLANE(data),YPLANE(_uncompressed),page);
197
memcpy(UPLANE(data),UPLANE(_uncompressed),page>>2);
198
memcpy(VPLANE(data),VPLANE(_uncompressed),page>>2);
200
memcpy(YPLANE(_locked),YPLANE(_uncompressed),page);
201
memcpy(UPLANE(_locked),UPLANE(_uncompressed),page>>2);
202
memcpy(VPLANE(_locked),VPLANE(_uncompressed),page>>2);
209
// copy chroma for now
215
//uint32_t cell=page*4; // size of luma
216
uint8_t *in,*out,*lock,*nb;
217
uint8_t *uin,*uout,*ulock,*unb;
218
uint8_t *vin,*vout,*vlock,*vnb;
225
nb=YPLANE(_lockcount);
226
lock=YPLANE(_locked);
227
in=YPLANE(_uncompressed);
230
unb=UPLANE(_lockcount);
231
ulock=UPLANE(_locked);
232
uin=UPLANE(_uncompressed);
235
vnb=VPLANE(_lockcount);
236
vlock=VPLANE(_locked);
237
vin=VPLANE(_uncompressed);
241
uint32_t xx,yy/*,dl*/,du,dv;
243
for(yy=_info.height>>1;yy>0;yy--)
245
for(xx=_info.width>>1;xx>0;xx--)
247
du=distMatrix[*uin][*ulock];
248
dv=distMatrix[*vin][*vlock];
250
// if chroma is locked , we try to lock luma
251
if( (du<_param->chromaLock)
252
&& (dv<_param->chromaLock))
257
#define PIX(z) doOnePix(in+z,out+z,lock+z,nb+z)
258
locked+=PIX(0)+ PIX(1)+ PIX(_info.width)+PIX(_info.width+1);
261
// if chroma is blended, we blend luma
263
#define PIX(z) doBlend(in+z,out+z,lock+z,nb+z)
264
if( (du<_param->chromaThreshold)
265
&& (dv<_param->chromaThreshold))
271
*uout=*ulock=(*uin+*uin)>>1;
272
*vout=*vlock=(*vin+*vin)>>1;
278
#define PIX(z) *(out+z)=*(lock+z)=*(in+z);*(nb+z)=0
291
uin++;uout++;ulock++;unb++;
292
vin++;vout++;vlock++;vnb++;
293
in++;out++;lock++;nb++;
294
in++;out++;lock++;nb++;
304
if(locked>((page*3)>>2)) // if more than 75% pixel not locked -> scene change
306
memcpy(YPLANE(data),YPLANE(_uncompressed),page);
307
memcpy(UPLANE(data),UPLANE(_uncompressed),page>>2);
308
memcpy(VPLANE(data),VPLANE(_uncompressed),page>>2);
310
memcpy(YPLANE(_locked),YPLANE(_uncompressed),page);
311
memcpy(UPLANE(_locked),UPLANE(_uncompressed),page>>2);
312
memcpy(VPLANE(_locked),VPLANE(_uncompressed),page>>2);
314
data->copyInfo(_uncompressed);
323
uint8_t ADMVideoDenoise::doOnePix(uint8_t *in,uint8_t *out,uint8_t *lock,uint8_t *nb)
326
d=distMatrix[*(in)][*(lock)];
327
if(d<_param->lumaLock)
329
if(*(nb)>30) // out of scope -> copy new
330
{ // too much copy ->
332
*(out)=(*(in)+*(lock))>>1;
339
*nb += 1; // *(nb)++;
343
else if(d< _param->lumaThreshold)
346
*(out)=(*(in)+*(lock))>>1;
349
else // too big delta
361
uint8_t ADMVideoDenoise::doBlend(uint8_t *in,uint8_t *out,uint8_t *lock,uint8_t *nb)
364
d=distMatrix[*(in)][*(lock)];
367
if(d<_param->lumaThreshold)
369
*(out)=(*(in)+*(lock))>>1;