95 #include "libavutil/ffversion.h"
106 return FFMPEG_CONFIGURATION;
111 #define LICENSE_PREFIX "libpostproc license: "
115 #define GET_MODE_BUFFER_SIZE 500
116 #define OPTIONS_ARRAY_SIZE 10
118 #define TEMP_STRIDE 8
121 #if ARCH_X86 && HAVE_INLINE_ASM
145 {
"dr",
"dering", 1, 5, 6,
DERING},
146 {
"al",
"autolevels", 0, 1, 2,
LEVEL_FIX},
155 {
"be",
"bitexact", 1, 0, 0,
BITEXACT},
162 "default",
"hb:a,vb:a,dr:a",
163 "de",
"hb:a,vb:a,dr:a",
164 "fast",
"h1:a,v1:a,dr:a",
165 "fa",
"h1:a,v1:a,dr:a",
166 "ac",
"ha:a:128:7,va:a,dr:a",
180 const int dcOffset= ((
c->nonBQP*
c->ppMode.baseDcDiff)>>8) + 1;
181 const int dcThreshold= dcOffset*2 + 1;
184 numEq += ((unsigned)(
src[0] -
src[1] + dcOffset)) < dcThreshold;
185 numEq += ((unsigned)(
src[1] -
src[2] + dcOffset)) < dcThreshold;
186 numEq += ((unsigned)(
src[2] -
src[3] + dcOffset)) < dcThreshold;
187 numEq += ((unsigned)(
src[3] -
src[4] + dcOffset)) < dcThreshold;
188 numEq += ((unsigned)(
src[4] -
src[5] + dcOffset)) < dcThreshold;
189 numEq += ((unsigned)(
src[5] -
src[6] + dcOffset)) < dcThreshold;
190 numEq += ((unsigned)(
src[6] -
src[7] + dcOffset)) < dcThreshold;
193 return numEq >
c->ppMode.flatnessThreshold;
203 const int dcOffset= ((
c->nonBQP*
c->ppMode.baseDcDiff)>>8) + 1;
204 const int dcThreshold= dcOffset*2 + 1;
208 numEq += ((unsigned)(
src[0] -
src[0+
stride] + dcOffset)) < dcThreshold;
209 numEq += ((unsigned)(
src[1] -
src[1+
stride] + dcOffset)) < dcThreshold;
210 numEq += ((unsigned)(
src[2] -
src[2+
stride] + dcOffset)) < dcThreshold;
211 numEq += ((unsigned)(
src[3] -
src[3+
stride] + dcOffset)) < dcThreshold;
212 numEq += ((unsigned)(
src[4] -
src[4+
stride] + dcOffset)) < dcThreshold;
213 numEq += ((unsigned)(
src[5] -
src[5+
stride] + dcOffset)) < dcThreshold;
214 numEq += ((unsigned)(
src[6] -
src[6+
stride] + dcOffset)) < dcThreshold;
215 numEq += ((unsigned)(
src[7] -
src[7+
stride] + dcOffset)) < dcThreshold;
218 return numEq >
c->ppMode.flatnessThreshold;
225 if((
unsigned)(
src[0] -
src[5] + 2*
QP) > 4*
QP)
return 0;
227 if((
unsigned)(
src[2] -
src[7] + 2*
QP) > 4*
QP)
return 0;
229 if((
unsigned)(
src[4] -
src[1] + 2*
QP) > 4*
QP)
return 0;
231 if((
unsigned)(
src[6] -
src[3] + 2*
QP) > 4*
QP)
return 0;
272 const int middleEnergy= 5*(dst[4] - dst[3]) + 2*(dst[2] - dst[5]);
274 if(
FFABS(middleEnergy) < 8*
c->QP){
275 const int q=(dst[3] - dst[4])/2;
276 const int leftEnergy= 5*(dst[2] - dst[1]) + 2*(dst[0] - dst[3]);
277 const int rightEnergy= 5*(dst[6] - dst[5]) + 2*(dst[4] - dst[7]);
311 const int first=
FFABS(dst[-1] - dst[0]) <
c->QP ? dst[-1] : dst[0];
312 const int last=
FFABS(dst[8] - dst[7]) <
c->QP ? dst[8] : dst[7];
315 sums[0] = 4*
first + dst[0] + dst[1] + dst[2] + 4;
316 sums[1] = sums[0] -
first + dst[3];
317 sums[2] = sums[1] -
first + dst[4];
318 sums[3] = sums[2] -
first + dst[5];
319 sums[4] = sums[3] -
first + dst[6];
320 sums[5] = sums[4] - dst[0] + dst[7];
321 sums[6] = sums[5] - dst[1] + last;
322 sums[7] = sums[6] - dst[2] + last;
323 sums[8] = sums[7] - dst[3] + last;
324 sums[9] = sums[8] - dst[4] + last;
326 dst[0]= (sums[0] + sums[2] + 2*dst[0])>>4;
327 dst[1]= (sums[1] + sums[3] + 2*dst[1])>>4;
328 dst[2]= (sums[2] + sums[4] + 2*dst[2])>>4;
329 dst[3]= (sums[3] + sums[5] + 2*dst[3])>>4;
330 dst[4]= (sums[4] + sums[6] + 2*dst[4])>>4;
331 dst[5]= (sums[5] + sums[7] + 2*dst[5])>>4;
332 dst[6]= (sums[6] + sums[8] + 2*dst[6])>>4;
333 dst[7]= (sums[7] + sums[9] + 2*dst[7])>>4;
350 static uint64_t lut[256];
356 int v=
i < 128 ? 2*
i : 2*(
i-256);
365 uint64_t
a= (v/16) & 0xFF;
366 uint64_t
b= (v*3/16) & 0xFF;
367 uint64_t
c= (v*5/16) & 0xFF;
368 uint64_t
d= (7*v/16) & 0xFF;
369 uint64_t
A= (0x100 -
a)&0xFF;
370 uint64_t
B= (0x100 -
b)&0xFF;
371 uint64_t
C= (0x100 -
c)&0xFF;
372 uint64_t
D= (0x100 -
c)&0xFF;
374 lut[
i] = (
a<<56) | (
b<<48) | (
c<<40) | (
d<<32) |
375 (
D<<24) | (
C<<16) | (
B<<8) | (
A);
409 const int dcOffset= ((
c->nonBQP*
c->ppMode.baseDcDiff)>>8) + 1;
410 const int dcThreshold= dcOffset*2 + 1;
416 numEq += ((unsigned)(
src[-1*
step] -
src[0*
step] + dcOffset)) < dcThreshold;
417 numEq += ((unsigned)(
src[ 0*
step] -
src[1*
step] + dcOffset)) < dcThreshold;
418 numEq += ((unsigned)(
src[ 1*
step] -
src[2*
step] + dcOffset)) < dcThreshold;
419 numEq += ((unsigned)(
src[ 2*
step] -
src[3*
step] + dcOffset)) < dcThreshold;
420 numEq += ((unsigned)(
src[ 3*
step] -
src[4*
step] + dcOffset)) < dcThreshold;
421 numEq += ((unsigned)(
src[ 4*
step] -
src[5*
step] + dcOffset)) < dcThreshold;
422 numEq += ((unsigned)(
src[ 5*
step] -
src[6*
step] + dcOffset)) < dcThreshold;
423 numEq += ((unsigned)(
src[ 6*
step] -
src[7*
step] + dcOffset)) < dcThreshold;
424 numEq += ((unsigned)(
src[ 7*
step] -
src[8*
step] + dcOffset)) < dcThreshold;
425 if(numEq >
c->ppMode.flatnessThreshold){
455 sums[6] = sums[5] -
src[1*
step] + last;
456 sums[7] = sums[6] -
src[2*
step] + last;
457 sums[8] = sums[7] -
src[3*
step] + last;
458 sums[9] = sums[8] -
src[4*
step] + last;
482 if(
FFABS(middleEnergy) < 8*
QP){
502 d= (
d < 0) ? 32 : -32;
520 #define TEMPLATE_PP_C 1
524 # define TEMPLATE_PP_ALTIVEC 1
529 #if ARCH_X86 && HAVE_INLINE_ASM
530 # if CONFIG_RUNTIME_CPUDETECT
531 # define TEMPLATE_PP_MMX 1
533 # define TEMPLATE_PP_MMXEXT 1
535 # define TEMPLATE_PP_3DNOW 1
537 # define TEMPLATE_PP_SSE2 1
540 # if HAVE_SSE2_INLINE
541 # define TEMPLATE_PP_SSE2 1
543 # elif HAVE_MMXEXT_INLINE
544 # define TEMPLATE_PP_MMXEXT 1
546 # elif HAVE_AMD3DNOW_INLINE
547 # define TEMPLATE_PP_3DNOW 1
549 # elif HAVE_MMX_INLINE
550 # define TEMPLATE_PP_MMX 1
556 typedef void (*
pp_fn)(
const uint8_t
src[],
int srcStride, uint8_t dst[],
int dstStride,
int width,
int height,
557 const int8_t QPs[],
int QPStride,
int isColor,
PPContext *
c2);
562 pp_fn pp = postProcess_C;
568 #if CONFIG_RUNTIME_CPUDETECT
569 #if ARCH_X86 && HAVE_INLINE_ASM
580 pp = postProcess_SSE2;
581 #elif HAVE_MMXEXT_INLINE
582 pp = postProcess_MMX2;
583 #elif HAVE_AMD3DNOW_INLINE
584 pp = postProcess_3DNow;
585 #elif HAVE_MMX_INLINE
586 pp = postProcess_MMX;
588 pp = postProcess_altivec;
593 pp(
src, srcStride, dst, dstStride,
width,
height, QPs, QPStride, isColor,
c);
599 "Available postprocessing filters:\n"
601 "short long name short long option Description\n"
602 "* * a autoq CPU power dependent enabler\n"
603 " c chrom chrominance filtering enabled\n"
604 " y nochrom chrominance filtering disabled\n"
605 " n noluma luma filtering disabled\n"
606 "hb hdeblock (2 threshold) horizontal deblocking filter\n"
607 " 1. difference factor: default=32, higher -> more deblocking\n"
608 " 2. flatness threshold: default=39, lower -> more deblocking\n"
609 " the h & v deblocking filters share these\n"
610 " so you can't set different thresholds for h / v\n"
611 "vb vdeblock (2 threshold) vertical deblocking filter\n"
612 "ha hadeblock (2 threshold) horizontal deblocking filter\n"
613 "va vadeblock (2 threshold) vertical deblocking filter\n"
614 "h1 x1hdeblock experimental h deblock filter 1\n"
615 "v1 x1vdeblock experimental v deblock filter 1\n"
616 "dr dering deringing filter\n"
617 "al autolevels automatic brightness / contrast\n"
618 " f fullyrange stretch luminance to (0..255)\n"
619 "lb linblenddeint linear blend deinterlacer\n"
620 "li linipoldeint linear interpolating deinterlace\n"
621 "ci cubicipoldeint cubic interpolating deinterlacer\n"
622 "md mediandeint median deinterlacer\n"
623 "fd ffmpegdeint ffmpeg deinterlacer\n"
624 "l5 lowpass5 FIR lowpass deinterlacer\n"
625 "de default hb:a,vb:a,dr:a\n"
626 "fa fast h1:a,v1:a,dr:a\n"
627 "ac ha:a:128:7,va:a,dr:a\n"
628 "tn tmpnoise (3 threshold) temporal noise reducer\n"
629 " 1. <= 2. <= 3. larger -> stronger filtering\n"
630 "fq forceQuant <quantizer> force quantizer\n"
632 "<filterName>[:<option>[:<option>...]][[,|/][-]<filterName>[:<option>...]]...\n"
633 "long form example:\n"
634 "vdeblock:autoq/hdeblock:autoq/linblenddeint default,-vdeblock\n"
635 "short form example:\n"
636 "vb:a/hb:a/lb de,-vb\n"
646 static const char filterDelimiters[] =
",/";
647 static const char optionDelimiters[] =
":|";
656 if (!strcmp(
name,
"help")) {
658 for (p =
pp_help; strchr(p,
'\n'); p = strchr(p,
'\n') + 1) {
687 const char *filterName;
695 int numOfUnknownOptions=0;
699 filterToken=
av_strtok(p, filterDelimiters, &tokstate);
700 if(!filterToken)
break;
701 p+= strlen(filterToken) + 1;
702 filterName=
av_strtok(filterToken, optionDelimiters, &tokstate);
709 if(*filterName ==
'-'){
720 else if(!strcmp(
"nochrom",
option) || !strcmp(
"y",
option)) chrom=0;
721 else if(!strcmp(
"chrom",
option) || !strcmp(
"c",
option)) chrom=1;
722 else if(!strcmp(
"noluma",
option) || !strcmp(
"n",
option)) luma=0;
725 numOfUnknownOptions++;
741 spaceLeft= p -
temp + plen;
746 memmove(p + newlen, p, plen+1);
753 if( !strcmp(
filters[
i].longName, filterName)
754 || !strcmp(
filters[
i].shortName, filterName)){
761 if(q >=
filters[
i].minLumQuality && luma)
763 if(chrom==1 || (chrom==-1 &&
filters[
i].chromDefault))
772 if( !strcmp(
options[o],
"fullyrange")
776 numOfUnknownOptions--;
791 numOfUnknownOptions--;
792 if(numOfNoises >= 3)
break;
800 for(o=0;
options[o] && o<2; o++){
805 numOfUnknownOptions--;
814 for(o=0;
options[o] && o<1; o++){
819 numOfUnknownOptions--;
825 if(!filterNameOk) ppMode->
error++;
826 ppMode->
error += numOfUnknownOptions;
848 int mbWidth = (
width+15)>>4;
849 int mbHeight= (
height+15)>>4;
853 c->qpStride= qpStride;
869 reallocAlign((
void **)&
c->nonBQPTable, qpStride*mbHeight*
sizeof(int8_t));
870 reallocAlign((
void **)&
c->stdQPTable, qpStride*mbHeight*
sizeof(int8_t));
871 reallocAlign((
void **)&
c->forcedQPTable, mbWidth*
sizeof(int8_t));
883 int qpStride= (
width+15)/16 + 2;
890 c->hChromaSubSample= cpuCaps&0x3;
891 c->vChromaSubSample= (cpuCaps>>4)&0x3;
893 c->hChromaSubSample= 1;
894 c->vChromaSubSample= 1;
937 uint8_t * dst[3],
const int dstStride[3],
939 const int8_t *QP_store,
int QPStride,
940 pp_mode *vm,
void *vc,
int pict_type)
942 int mbWidth = (
width+15)>>4;
943 int mbHeight= (
height+15)>>4;
947 int absQPStride =
FFABS(QPStride);
950 if(
c->stride < minStride ||
c->qpStride < absQPStride)
952 FFMAX(minStride,
c->stride),
953 FFMAX(
c->qpStride, absQPStride));
957 QP_store=
c->forcedQPTable;
958 absQPStride = QPStride = 0;
960 for(
i=0;
i<mbWidth;
i++)
c->forcedQPTable[
i]=
mode->forcedQuant;
962 for(
i=0;
i<mbWidth;
i++)
c->forcedQPTable[
i]= 1;
967 const int count=
FFMAX(mbHeight * absQPStride, mbWidth);
968 for(
i=0;
i<(count>>2);
i++){
971 for(
i<<=2;
i<count;
i++){
972 c->stdQPTable[
i] = QP_store[
i]>>1;
974 QP_store=
c->stdQPTable;
975 QPStride= absQPStride;
980 for(y=0; y<mbHeight; y++){
981 for(x=0; x<mbWidth; x++){
989 if((pict_type&7)!=3){
992 const int count=
FFMAX(mbHeight * QPStride, mbWidth);
993 for(
i=0;
i<(count>>2);
i++){
996 for(
i<<=2;
i<count;
i++){
997 c->nonBQPTable[
i] = QP_store[
i] & 0x3F;
1001 for(
i=0;
i<mbHeight;
i++) {
1002 for(j=0; j<absQPStride; j++) {
1003 c->nonBQPTable[
i*absQPStride+j] = QP_store[
i*QPStride+j] & 0x3F;
1015 if (!(
src[1] &&
src[2] && dst[1] && dst[2]))
1021 if(
mode->chromMode){
1027 else if(srcStride[1] == dstStride[1] && srcStride[2] == dstStride[2]){
1033 memcpy(&(dst[1][y*dstStride[1]]), &(
src[1][y*srcStride[1]]),
width);
1034 memcpy(&(dst[2][y*dstStride[2]]), &(
src[2][y*srcStride[2]]),
width);