94 #include "libavutil/ffversion.h"
105 return FFMPEG_CONFIGURATION;
110 #define LICENSE_PREFIX "libpostproc license: "
114 #define GET_MODE_BUFFER_SIZE 500
115 #define OPTIONS_ARRAY_SIZE 10
117 #define TEMP_STRIDE 8
120 #if ARCH_X86 && HAVE_INLINE_ASM
144 {
"dr",
"dering", 1, 5, 6,
DERING},
145 {
"al",
"autolevels", 0, 1, 2,
LEVEL_FIX},
154 {
"be",
"bitexact", 1, 0, 0,
BITEXACT},
161 "default",
"hb:a,vb:a,dr:a",
162 "de",
"hb:a,vb:a,dr:a",
163 "fast",
"h1:a,v1:a,dr:a",
164 "fa",
"h1:a,v1:a,dr:a",
165 "ac",
"ha:a:128:7,va:a,dr:a",
179 const int dcOffset= ((
c->nonBQP*
c->ppMode.baseDcDiff)>>8) + 1;
180 const int dcThreshold= dcOffset*2 + 1;
183 numEq += ((unsigned)(
src[0] -
src[1] + dcOffset)) < dcThreshold;
184 numEq += ((unsigned)(
src[1] -
src[2] + dcOffset)) < dcThreshold;
185 numEq += ((unsigned)(
src[2] -
src[3] + dcOffset)) < dcThreshold;
186 numEq += ((unsigned)(
src[3] -
src[4] + dcOffset)) < dcThreshold;
187 numEq += ((unsigned)(
src[4] -
src[5] + dcOffset)) < dcThreshold;
188 numEq += ((unsigned)(
src[5] -
src[6] + dcOffset)) < dcThreshold;
189 numEq += ((unsigned)(
src[6] -
src[7] + dcOffset)) < dcThreshold;
192 return numEq >
c->ppMode.flatnessThreshold;
202 const int dcOffset= ((
c->nonBQP*
c->ppMode.baseDcDiff)>>8) + 1;
203 const int dcThreshold= dcOffset*2 + 1;
207 numEq += ((unsigned)(
src[0] -
src[0+
stride] + dcOffset)) < dcThreshold;
208 numEq += ((unsigned)(
src[1] -
src[1+
stride] + dcOffset)) < dcThreshold;
209 numEq += ((unsigned)(
src[2] -
src[2+
stride] + dcOffset)) < dcThreshold;
210 numEq += ((unsigned)(
src[3] -
src[3+
stride] + dcOffset)) < dcThreshold;
211 numEq += ((unsigned)(
src[4] -
src[4+
stride] + dcOffset)) < dcThreshold;
212 numEq += ((unsigned)(
src[5] -
src[5+
stride] + dcOffset)) < dcThreshold;
213 numEq += ((unsigned)(
src[6] -
src[6+
stride] + dcOffset)) < dcThreshold;
214 numEq += ((unsigned)(
src[7] -
src[7+
stride] + dcOffset)) < dcThreshold;
217 return numEq >
c->ppMode.flatnessThreshold;
224 if((
unsigned)(
src[0] -
src[5] + 2*
QP) > 4*
QP)
return 0;
226 if((
unsigned)(
src[2] -
src[7] + 2*
QP) > 4*
QP)
return 0;
228 if((
unsigned)(
src[4] -
src[1] + 2*
QP) > 4*
QP)
return 0;
230 if((
unsigned)(
src[6] -
src[3] + 2*
QP) > 4*
QP)
return 0;
271 const int middleEnergy= 5*(dst[4] - dst[3]) + 2*(dst[2] - dst[5]);
273 if(
FFABS(middleEnergy) < 8*
c->QP){
274 const int q=(dst[3] - dst[4])/2;
275 const int leftEnergy= 5*(dst[2] - dst[1]) + 2*(dst[0] - dst[3]);
276 const int rightEnergy= 5*(dst[6] - dst[5]) + 2*(dst[4] - dst[7]);
282 d*=
FFSIGN(-middleEnergy);
310 const int first=
FFABS(dst[-1] - dst[0]) <
c->QP ? dst[-1] : dst[0];
311 const int last=
FFABS(dst[8] - dst[7]) <
c->QP ? dst[8] : dst[7];
314 sums[0] = 4*
first + dst[0] + dst[1] + dst[2] + 4;
315 sums[1] = sums[0] -
first + dst[3];
316 sums[2] = sums[1] -
first + dst[4];
317 sums[3] = sums[2] -
first + dst[5];
318 sums[4] = sums[3] -
first + dst[6];
319 sums[5] = sums[4] - dst[0] + dst[7];
320 sums[6] = sums[5] - dst[1] + last;
321 sums[7] = sums[6] - dst[2] + last;
322 sums[8] = sums[7] - dst[3] + last;
323 sums[9] = sums[8] - dst[4] + last;
325 dst[0]= (sums[0] + sums[2] + 2*dst[0])>>4;
326 dst[1]= (sums[1] + sums[3] + 2*dst[1])>>4;
327 dst[2]= (sums[2] + sums[4] + 2*dst[2])>>4;
328 dst[3]= (sums[3] + sums[5] + 2*dst[3])>>4;
329 dst[4]= (sums[4] + sums[6] + 2*dst[4])>>4;
330 dst[5]= (sums[5] + sums[7] + 2*dst[5])>>4;
331 dst[6]= (sums[6] + sums[8] + 2*dst[6])>>4;
332 dst[7]= (sums[7] + sums[9] + 2*dst[7])>>4;
349 static uint64_t lut[256];
355 int v=
i < 128 ? 2*
i : 2*(
i-256);
364 uint64_t
a= (v/16) & 0xFF;
365 uint64_t
b= (v*3/16) & 0xFF;
366 uint64_t
c= (v*5/16) & 0xFF;
367 uint64_t d= (7*v/16) & 0xFF;
368 uint64_t
A= (0x100 -
a)&0xFF;
369 uint64_t
B= (0x100 -
b)&0xFF;
370 uint64_t
C= (0x100 -
c)&0xFF;
371 uint64_t
D= (0x100 -
c)&0xFF;
373 lut[
i] = (
a<<56) | (
b<<48) | (
c<<40) | (d<<32) |
374 (
D<<24) | (
C<<16) | (
B<<8) | (
A);
408 const int dcOffset= ((
c->nonBQP*
c->ppMode.baseDcDiff)>>8) + 1;
409 const int dcThreshold= dcOffset*2 + 1;
415 numEq += ((unsigned)(
src[-1*
step] -
src[0*
step] + dcOffset)) < dcThreshold;
416 numEq += ((unsigned)(
src[ 0*
step] -
src[1*
step] + dcOffset)) < dcThreshold;
417 numEq += ((unsigned)(
src[ 1*
step] -
src[2*
step] + dcOffset)) < dcThreshold;
418 numEq += ((unsigned)(
src[ 2*
step] -
src[3*
step] + dcOffset)) < dcThreshold;
419 numEq += ((unsigned)(
src[ 3*
step] -
src[4*
step] + dcOffset)) < dcThreshold;
420 numEq += ((unsigned)(
src[ 4*
step] -
src[5*
step] + dcOffset)) < dcThreshold;
421 numEq += ((unsigned)(
src[ 5*
step] -
src[6*
step] + dcOffset)) < dcThreshold;
422 numEq += ((unsigned)(
src[ 6*
step] -
src[7*
step] + dcOffset)) < dcThreshold;
423 numEq += ((unsigned)(
src[ 7*
step] -
src[8*
step] + dcOffset)) < dcThreshold;
424 if(numEq >
c->ppMode.flatnessThreshold){
454 sums[6] = sums[5] -
src[1*
step] + last;
455 sums[7] = sums[6] -
src[2*
step] + last;
456 sums[8] = sums[7] -
src[3*
step] + last;
457 sums[9] = sums[8] -
src[4*
step] + last;
481 if(
FFABS(middleEnergy) < 8*
QP){
490 d*=
FFSIGN(-middleEnergy);
501 d= (d < 0) ? 32 : -32;
524 #define TEMPLATE_PP_C 1
528 # define TEMPLATE_PP_ALTIVEC 1
533 #if ARCH_X86 && HAVE_INLINE_ASM
534 # if CONFIG_RUNTIME_CPUDETECT
535 # define TEMPLATE_PP_MMX 1
537 # define TEMPLATE_PP_MMXEXT 1
539 # define TEMPLATE_PP_3DNOW 1
541 # define TEMPLATE_PP_SSE2 1
544 # if HAVE_SSE2_INLINE
545 # define TEMPLATE_PP_SSE2 1
547 # elif HAVE_MMXEXT_INLINE
548 # define TEMPLATE_PP_MMXEXT 1
550 # elif HAVE_AMD3DNOW_INLINE
551 # define TEMPLATE_PP_3DNOW 1
553 # elif HAVE_MMX_INLINE
554 # define TEMPLATE_PP_MMX 1
561 const int8_t QPs[],
int QPStride,
int isColor,
PPContext *
c2);
566 pp_fn pp = postProcess_C;
572 #if CONFIG_RUNTIME_CPUDETECT
573 #if ARCH_X86 && HAVE_INLINE_ASM
584 pp = postProcess_SSE2;
585 #elif HAVE_MMXEXT_INLINE
586 pp = postProcess_MMX2;
587 #elif HAVE_AMD3DNOW_INLINE
588 pp = postProcess_3DNow;
589 #elif HAVE_MMX_INLINE
590 pp = postProcess_MMX;
592 pp = postProcess_altivec;
597 pp(
src, srcStride, dst, dstStride,
width,
height, QPs, QPStride, isColor,
c);
603 "Available postprocessing filters:\n"
605 "short long name short long option Description\n"
606 "* * a autoq CPU power dependent enabler\n"
607 " c chrom chrominance filtering enabled\n"
608 " y nochrom chrominance filtering disabled\n"
609 " n noluma luma filtering disabled\n"
610 "hb hdeblock (2 threshold) horizontal deblocking filter\n"
611 " 1. difference factor: default=32, higher -> more deblocking\n"
612 " 2. flatness threshold: default=39, lower -> more deblocking\n"
613 " the h & v deblocking filters share these\n"
614 " so you can't set different thresholds for h / v\n"
615 "vb vdeblock (2 threshold) vertical deblocking filter\n"
616 "ha hadeblock (2 threshold) horizontal deblocking filter\n"
617 "va vadeblock (2 threshold) vertical deblocking filter\n"
618 "h1 x1hdeblock experimental h deblock filter 1\n"
619 "v1 x1vdeblock experimental v deblock filter 1\n"
620 "dr dering deringing filter\n"
621 "al autolevels automatic brightness / contrast\n"
622 " f fullyrange stretch luminance to (0..255)\n"
623 "lb linblenddeint linear blend deinterlacer\n"
624 "li linipoldeint linear interpolating deinterlace\n"
625 "ci cubicipoldeint cubic interpolating deinterlacer\n"
626 "md mediandeint median deinterlacer\n"
627 "fd ffmpegdeint ffmpeg deinterlacer\n"
628 "l5 lowpass5 FIR lowpass deinterlacer\n"
629 "de default hb:a,vb:a,dr:a\n"
630 "fa fast h1:a,v1:a,dr:a\n"
631 "ac ha:a:128:7,va:a,dr:a\n"
632 "tn tmpnoise (3 threshold) temporal noise reducer\n"
633 " 1. <= 2. <= 3. larger -> stronger filtering\n"
634 "fq forceQuant <quantizer> force quantizer\n"
636 "<filterName>[:<option>[:<option>...]][[,|/][-]<filterName>[:<option>...]]...\n"
637 "long form example:\n"
638 "vdeblock:autoq/hdeblock:autoq/linblenddeint default,-vdeblock\n"
639 "short form example:\n"
640 "vb:a/hb:a/lb de,-vb\n"
650 static const char filterDelimiters[] =
",/";
651 static const char optionDelimiters[] =
":|";
660 if (!strcmp(
name,
"help")) {
662 for (p =
pp_help; strchr(p,
'\n'); p = strchr(p,
'\n') + 1) {
691 const char *filterName;
699 int numOfUnknownOptions=0;
703 filterToken=
av_strtok(p, filterDelimiters, &tokstate);
704 if(!filterToken)
break;
705 p+= strlen(filterToken) + 1;
706 filterName=
av_strtok(filterToken, optionDelimiters, &tokstate);
713 if(*filterName ==
'-'){
724 else if(!strcmp(
"nochrom",
option) || !strcmp(
"y",
option)) chrom=0;
725 else if(!strcmp(
"chrom",
option) || !strcmp(
"c",
option)) chrom=1;
726 else if(!strcmp(
"noluma",
option) || !strcmp(
"n",
option)) luma=0;
729 numOfUnknownOptions++;
745 spaceLeft= p -
temp + plen;
750 memmove(p + newlen, p, plen+1);
757 if( !strcmp(
filters[
i].longName, filterName)
758 || !strcmp(
filters[
i].shortName, filterName)){
765 if(q >=
filters[
i].minLumQuality && luma)
767 if(chrom==1 || (chrom==-1 &&
filters[
i].chromDefault))
776 if( !strcmp(
options[o],
"fullyrange")
780 numOfUnknownOptions--;
795 numOfUnknownOptions--;
796 if(numOfNoises >= 3)
break;
804 for(o=0;
options[o] && o<2; o++){
809 numOfUnknownOptions--;
818 for(o=0;
options[o] && o<1; o++){
823 numOfUnknownOptions--;
829 if(!filterNameOk) ppMode->
error++;
830 ppMode->
error += numOfUnknownOptions;
852 int mbWidth = (
width+15)>>4;
853 int mbHeight= (
height+15)>>4;
857 c->qpStride= qpStride;
873 reallocAlign((
void **)&
c->nonBQPTable, qpStride*mbHeight*
sizeof(int8_t));
874 reallocAlign((
void **)&
c->stdQPTable, qpStride*mbHeight*
sizeof(int8_t));
875 reallocAlign((
void **)&
c->forcedQPTable, mbWidth*
sizeof(int8_t));
887 int qpStride= (
width+15)/16 + 2;
894 c->hChromaSubSample= cpuCaps&0x3;
895 c->vChromaSubSample= (cpuCaps>>4)&0x3;
897 c->hChromaSubSample= 1;
898 c->vChromaSubSample= 1;
941 uint8_t * dst[3],
const int dstStride[3],
943 const int8_t *QP_store,
int QPStride,
944 pp_mode *vm,
void *vc,
int pict_type)
946 int mbWidth = (
width+15)>>4;
947 int mbHeight= (
height+15)>>4;
951 int absQPStride =
FFABS(QPStride);
954 if(
c->stride < minStride ||
c->qpStride < absQPStride)
956 FFMAX(minStride,
c->stride),
957 FFMAX(
c->qpStride, absQPStride));
961 QP_store=
c->forcedQPTable;
962 absQPStride = QPStride = 0;
964 for(
i=0;
i<mbWidth;
i++)
c->forcedQPTable[
i]=
mode->forcedQuant;
966 for(
i=0;
i<mbWidth;
i++)
c->forcedQPTable[
i]= 1;
971 const int count=
FFMAX(mbHeight * absQPStride, mbWidth);
976 c->stdQPTable[
i] = QP_store[
i]>>1;
978 QP_store=
c->stdQPTable;
979 QPStride= absQPStride;
984 for(y=0; y<mbHeight; y++){
985 for(x=0; x<mbWidth; x++){
993 if((pict_type&7)!=3){
996 const int count=
FFMAX(mbHeight * QPStride, mbWidth);
1001 c->nonBQPTable[
i] = QP_store[
i] & 0x3F;
1005 for(
i=0;
i<mbHeight;
i++) {
1006 for(j=0; j<absQPStride; j++) {
1007 c->nonBQPTable[
i*absQPStride+j] = QP_store[
i*QPStride+j] & 0x3F;
1019 if (!(
src[1] &&
src[2] && dst[1] && dst[2]))
1025 if(
mode->chromMode){
1031 else if(srcStride[1] == dstStride[1] && srcStride[2] == dstStride[2]){
1037 memcpy(&(dst[1][y*dstStride[1]]), &(
src[1][y*srcStride[1]]),
width);
1038 memcpy(&(dst[2][y*dstStride[2]]), &(
src[2][y*srcStride[2]]),
width);