93 #include "libavutil/ffversion.h"
104 return FFMPEG_CONFIGURATION;
109 #define LICENSE_PREFIX "libpostproc license: "
117 #define GET_MODE_BUFFER_SIZE 500
118 #define OPTIONS_ARRAY_SIZE 10
120 #define TEMP_STRIDE 8
123 #if ARCH_X86 && HAVE_INLINE_ASM
147 {
"dr",
"dering", 1, 5, 6,
DERING},
148 {
"al",
"autolevels", 0, 1, 2,
LEVEL_FIX},
157 {
"be",
"bitexact", 1, 0, 0,
BITEXACT},
164 "default",
"hb:a,vb:a,dr:a",
165 "de",
"hb:a,vb:a,dr:a",
166 "fast",
"h1:a,v1:a,dr:a",
167 "fa",
"h1:a,v1:a,dr:a",
168 "ac",
"ha:a:128:7,va:a,dr:a",
183 const int dcThreshold= dcOffset*2 + 1;
186 numEq += ((unsigned)(src[0] - src[1] + dcOffset)) < dcThreshold;
187 numEq += ((unsigned)(src[1] - src[2] + dcOffset)) < dcThreshold;
188 numEq += ((unsigned)(src[2] - src[3] + dcOffset)) < dcThreshold;
189 numEq += ((unsigned)(src[3] - src[4] + dcOffset)) < dcThreshold;
190 numEq += ((unsigned)(src[4] - src[5] + dcOffset)) < dcThreshold;
191 numEq += ((unsigned)(src[5] - src[6] + dcOffset)) < dcThreshold;
192 numEq += ((unsigned)(src[6] - src[7] + dcOffset)) < dcThreshold;
206 const int dcThreshold= dcOffset*2 + 1;
210 numEq += ((unsigned)(src[0] - src[0+stride] + dcOffset)) < dcThreshold;
211 numEq += ((unsigned)(src[1] - src[1+stride] + dcOffset)) < dcThreshold;
212 numEq += ((unsigned)(src[2] - src[2+stride] + dcOffset)) < dcThreshold;
213 numEq += ((unsigned)(src[3] - src[3+stride] + dcOffset)) < dcThreshold;
214 numEq += ((unsigned)(src[4] - src[4+stride] + dcOffset)) < dcThreshold;
215 numEq += ((unsigned)(src[5] - src[5+stride] + dcOffset)) < dcThreshold;
216 numEq += ((unsigned)(src[6] - src[6+stride] + dcOffset)) < dcThreshold;
217 numEq += ((unsigned)(src[7] - src[7+stride] + dcOffset)) < dcThreshold;
227 if((
unsigned)(src[0] - src[5] + 2*QP) > 4*QP)
return 0;
229 if((
unsigned)(src[2] - src[7] + 2*QP) > 4*QP)
return 0;
231 if((
unsigned)(src[4] - src[1] + 2*QP) > 4*QP)
return 0;
233 if((
unsigned)(src[6] - src[3] + 2*QP) > 4*QP)
return 0;
244 if((
unsigned)(src[ x + 0*stride] - src[ x + 5*stride] + 2*QP) > 4*QP)
return 0;
245 if((
unsigned)(src[1+x + 2*stride] - src[1+x + 7*stride] + 2*QP) > 4*QP)
return 0;
246 if((
unsigned)(src[2+x + 4*stride] - src[2+x + 1*stride] + 2*QP) > 4*QP)
return 0;
247 if((
unsigned)(src[3+x + 6*stride] - src[3+x + 3*stride] + 2*QP) > 4*QP)
return 0;
274 const int middleEnergy= 5*(dst[4] - dst[3]) + 2*(dst[2] - dst[5]);
276 if(
FFABS(middleEnergy) < 8*c->
QP){
277 const int q=(dst[3] - dst[4])/2;
278 const int leftEnergy= 5*(dst[2] - dst[1]) + 2*(dst[0] - dst[3]);
279 const int rightEnergy= 5*(dst[6] - dst[5]) + 2*(dst[4] - dst[7]);
285 d*=
FFSIGN(-middleEnergy);
313 const int first=
FFABS(dst[-1] - dst[0]) < c->
QP ? dst[-1] : dst[0];
314 const int last=
FFABS(dst[8] - dst[7]) < c->
QP ? dst[8] : dst[7];
317 sums[0] = 4*first + dst[0] + dst[1] + dst[2] + 4;
318 sums[1] = sums[0] - first + dst[3];
319 sums[2] = sums[1] - first + dst[4];
320 sums[3] = sums[2] - first + dst[5];
321 sums[4] = sums[3] - first + dst[6];
322 sums[5] = sums[4] - dst[0] + dst[7];
323 sums[6] = sums[5] - dst[1] + last;
324 sums[7] = sums[6] - dst[2] + last;
325 sums[8] = sums[7] - dst[3] + last;
326 sums[9] = sums[8] - dst[4] + last;
328 dst[0]= (sums[0] + sums[2] + 2*dst[0])>>4;
329 dst[1]= (sums[1] + sums[3] + 2*dst[1])>>4;
330 dst[2]= (sums[2] + sums[4] + 2*dst[2])>>4;
331 dst[3]= (sums[3] + sums[5] + 2*dst[3])>>4;
332 dst[4]= (sums[4] + sums[6] + 2*dst[4])>>4;
333 dst[5]= (sums[5] + sums[7] + 2*dst[5])>>4;
334 dst[6]= (sums[6] + sums[8] + 2*dst[6])>>4;
335 dst[7]= (sums[7] + sums[9] + 2*dst[7])>>4;
352 static uint64_t lut[256];
358 int v= i < 128 ? 2*i : 2*(i-256);
367 uint64_t
a= (v/16) & 0xFF;
368 uint64_t
b= (v*3/16) & 0xFF;
369 uint64_t
c= (v*5/16) & 0xFF;
370 uint64_t d= (7*v/16) & 0xFF;
371 uint64_t
A= (0x100 -
a)&0xFF;
372 uint64_t
B= (0x100 -
b)&0xFF;
373 uint64_t
C= (0x100 -
c)&0xFF;
374 uint64_t
D= (0x100 -
c)&0xFF;
376 lut[i] = (a<<56) | (b<<48) | (c<<40) | (d<<32) |
377 (D<<24) | (C<<16) | (B<<8) | (A);
383 int a= src[1] - src[2];
384 int b= src[3] - src[4];
385 int c= src[5] - src[6];
412 const int dcThreshold= dcOffset*2 + 1;
418 numEq += ((unsigned)(src[-1*step] - src[0*step] + dcOffset)) < dcThreshold;
419 numEq += ((unsigned)(src[ 0*step] - src[1*step] + dcOffset)) < dcThreshold;
420 numEq += ((unsigned)(src[ 1*step] - src[2*step] + dcOffset)) < dcThreshold;
421 numEq += ((unsigned)(src[ 2*step] - src[3*step] + dcOffset)) < dcThreshold;
422 numEq += ((unsigned)(src[ 3*step] - src[4*step] + dcOffset)) < dcThreshold;
423 numEq += ((unsigned)(src[ 4*step] - src[5*step] + dcOffset)) < dcThreshold;
424 numEq += ((unsigned)(src[ 5*step] - src[6*step] + dcOffset)) < dcThreshold;
425 numEq += ((unsigned)(src[ 6*step] - src[7*step] + dcOffset)) < dcThreshold;
426 numEq += ((unsigned)(src[ 7*step] - src[8*step] + dcOffset)) < dcThreshold;
430 if(src[0] > src[step]){
438 if(src[x*step] > src[(x+1)*step]){
439 if(src[x *step] > max) max= src[ x *step];
440 if(src[(x+1)*step] <
min) min= src[(x+1)*step];
442 if(src[(x+1)*step] > max) max= src[(x+1)*step];
443 if(src[ x *step] < min) min= src[ x *step];
447 const int first=
FFABS(src[-1*step] - src[0]) < QP ? src[-1*step] : src[0];
448 const int last=
FFABS(src[8*step] - src[7*step]) < QP ? src[8*step] : src[7*step];
451 sums[0] = 4*first + src[0*step] + src[1*step] + src[2*step] + 4;
452 sums[1] = sums[0] - first + src[3*step];
453 sums[2] = sums[1] - first + src[4*step];
454 sums[3] = sums[2] - first + src[5*step];
455 sums[4] = sums[3] - first + src[6*step];
456 sums[5] = sums[4] - src[0*step] + src[7*step];
457 sums[6] = sums[5] - src[1*step] + last;
458 sums[7] = sums[6] - src[2*step] + last;
459 sums[8] = sums[7] - src[3*step] + last;
460 sums[9] = sums[8] - src[4*step] + last;
472 src[0*step]= (sums[0] + sums[2] + 2*src[0*step])>>4;
473 src[1*step]= (sums[1] + sums[3] + 2*src[1*step])>>4;
474 src[2*step]= (sums[2] + sums[4] + 2*src[2*step])>>4;
475 src[3*step]= (sums[3] + sums[5] + 2*src[3*step])>>4;
476 src[4*step]= (sums[4] + sums[6] + 2*src[4*step])>>4;
477 src[5*step]= (sums[5] + sums[7] + 2*src[5*step])>>4;
478 src[6*step]= (sums[6] + sums[8] + 2*src[6*step])>>4;
479 src[7*step]= (sums[7] + sums[9] + 2*src[7*step])>>4;
482 const int middleEnergy= 5*(src[4*step] - src[3*step]) + 2*(src[2*step] - src[5*step]);
484 if(
FFABS(middleEnergy) < 8*
QP){
485 const int q=(src[3*step] - src[4*step])/2;
486 const int leftEnergy= 5*(src[2*step] - src[1*step]) + 2*(src[0*step] - src[3*step]);
487 const int rightEnergy= 5*(src[6*step] - src[5*step]) + 2*(src[4*step] - src[7*step]);
493 d*=
FFSIGN(-middleEnergy);
504 d= (d < 0) ? 32 : -32;
505 src[3*step]= av_clip_uint8(src[3*step] - d);
506 src[4*step]= av_clip_uint8(src[4*step] + d);
527 #define TEMPLATE_PP_C 1
531 # define TEMPLATE_PP_ALTIVEC 1
536 #if ARCH_X86 && HAVE_INLINE_ASM
537 # if CONFIG_RUNTIME_CPUDETECT
538 # define TEMPLATE_PP_MMX 1
540 # define TEMPLATE_PP_MMXEXT 1
542 # define TEMPLATE_PP_3DNOW 1
544 # define TEMPLATE_PP_SSE2 1
547 # if HAVE_SSE2_INLINE
548 # define TEMPLATE_PP_SSE2 1
550 # elif HAVE_MMXEXT_INLINE
551 # define TEMPLATE_PP_MMXEXT 1
553 # elif HAVE_AMD3DNOW_INLINE
554 # define TEMPLATE_PP_3DNOW 1
556 # elif HAVE_MMX_INLINE
557 # define TEMPLATE_PP_MMX 1
564 const QP_STORE_T QPs[],
int QPStride,
int isColor,
PPContext *
c2);
569 pp_fn pp = postProcess_C;
575 #if CONFIG_RUNTIME_CPUDETECT
576 #if ARCH_X86 && HAVE_INLINE_ASM
587 pp = postProcess_SSE2;
588 #elif HAVE_MMXEXT_INLINE
589 pp = postProcess_MMX2;
590 #elif HAVE_AMD3DNOW_INLINE
591 pp = postProcess_3DNow;
592 #elif HAVE_MMX_INLINE
593 pp = postProcess_MMX;
595 pp = postProcess_altivec;
600 pp(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
606 "Available postprocessing filters:\n"
608 "short long name short long option Description\n"
609 "* * a autoq CPU power dependent enabler\n"
610 " c chrom chrominance filtering enabled\n"
611 " y nochrom chrominance filtering disabled\n"
612 " n noluma luma filtering disabled\n"
613 "hb hdeblock (2 threshold) horizontal deblocking filter\n"
614 " 1. difference factor: default=32, higher -> more deblocking\n"
615 " 2. flatness threshold: default=39, lower -> more deblocking\n"
616 " the h & v deblocking filters share these\n"
617 " so you can't set different thresholds for h / v\n"
618 "vb vdeblock (2 threshold) vertical deblocking filter\n"
619 "ha hadeblock (2 threshold) horizontal deblocking filter\n"
620 "va vadeblock (2 threshold) vertical deblocking filter\n"
621 "h1 x1hdeblock experimental h deblock filter 1\n"
622 "v1 x1vdeblock experimental v deblock filter 1\n"
623 "dr dering deringing filter\n"
624 "al autolevels automatic brightness / contrast\n"
625 " f fullyrange stretch luminance to (0..255)\n"
626 "lb linblenddeint linear blend deinterlacer\n"
627 "li linipoldeint linear interpolating deinterlace\n"
628 "ci cubicipoldeint cubic interpolating deinterlacer\n"
629 "md mediandeint median deinterlacer\n"
630 "fd ffmpegdeint ffmpeg deinterlacer\n"
631 "l5 lowpass5 FIR lowpass deinterlacer\n"
632 "de default hb:a,vb:a,dr:a\n"
633 "fa fast h1:a,v1:a,dr:a\n"
634 "ac ha:a:128:7,va:a,dr:a\n"
635 "tn tmpnoise (3 threshold) temporal noise reducer\n"
636 " 1. <= 2. <= 3. larger -> stronger filtering\n"
637 "fq forceQuant <quantizer> force quantizer\n"
639 "<filterName>[:<option>[:<option>...]][[,|/][-]<filterName>[:<option>...]]...\n"
640 "long form example:\n"
641 "vdeblock:autoq/hdeblock:autoq/linblenddeint default,-vdeblock\n"
642 "short form example:\n"
643 "vb:a/hb:a/lb de,-vb\n"
653 static const char filterDelimiters[] =
",/";
654 static const char optionDelimiters[] =
":|";
663 if (!strcmp(name,
"help")) {
665 for (p =
pp_help; strchr(p,
'\n'); p = strchr(p,
'\n') + 1) {
694 const char *filterName;
702 int numOfUnknownOptions=0;
706 filterToken=
av_strtok(p, filterDelimiters, &tokstate);
707 if(!filterToken)
break;
708 p+= strlen(filterToken) + 1;
709 filterName=
av_strtok(filterToken, optionDelimiters, &tokstate);
716 if(*filterName ==
'-'){
726 if(!strcmp(
"autoq", option) || !strcmp(
"a", option)) q= quality;
727 else if(!strcmp(
"nochrom", option) || !strcmp(
"y", option)) chrom=0;
728 else if(!strcmp(
"chrom", option) || !strcmp(
"c", option)) chrom=1;
729 else if(!strcmp(
"noluma", option) || !strcmp(
"n", option)) luma=0;
731 options[numOfUnknownOptions] =
option;
732 numOfUnknownOptions++;
736 options[numOfUnknownOptions] =
NULL;
748 spaceLeft= p - temp + plen;
753 memmove(p + newlen, p, plen+1);
760 if( !strcmp(filters[i].longName, filterName)
761 || !strcmp(filters[i].shortName, filterName)){
768 if(q >= filters[i].minLumQuality && luma)
770 if(chrom==1 || (chrom==-1 && filters[i].chromDefault))
771 if(q >= filters[i].minChromQuality)
778 for(o=0; options[o]; o++){
779 if( !strcmp(options[o],
"fullyrange")
780 ||!strcmp(options[o],
"f")){
783 numOfUnknownOptions--;
792 for(o=0; options[o]; o++){
795 strtol(options[o], &tail, 0);
796 if(tail!=options[o]){
798 numOfUnknownOptions--;
799 if(numOfNoises >= 3)
break;
807 for(o=0; options[o] && o<2; o++){
809 int val= strtol(options[o], &tail, 0);
810 if(tail==options[o])
break;
812 numOfUnknownOptions--;
821 for(o=0; options[o] && o<1; o++){
823 int val= strtol(options[o], &tail, 0);
824 if(tail==options[o])
break;
826 numOfUnknownOptions--;
832 if(!filterNameOk) ppMode->
error++;
833 ppMode->
error += numOfUnknownOptions;
855 int mbWidth = (width+15)>>4;
856 int mbHeight= (height+15)>>4;
890 int qpStride= (width+15)/16 + 2;
944 uint8_t * dst[3],
const int dstStride[3],
946 const QP_STORE_T *QP_store,
int QPStride,
947 pp_mode *vm,
void *vc,
int pict_type)
949 int mbWidth = (width+15)>>4;
950 int mbHeight= (height+15)>>4;
954 int absQPStride =
FFABS(QPStride);
965 absQPStride = QPStride = 0;
974 const int count=
FFMAX(mbHeight * absQPStride, mbWidth);
975 for(i=0; i<(count>>2); i++){
978 for(i<<=2; i<
count; i++){
982 QPStride= absQPStride;
987 for(y=0; y<mbHeight; y++){
988 for(x=0; x<mbWidth; x++){
996 if((pict_type&7)!=3){
999 const int count=
FFMAX(mbHeight * QPStride, mbWidth);
1000 for(i=0; i<(count>>2); i++){
1003 for(i<<=2; i<
count; i++){
1008 for(i=0; i<mbHeight; i++) {
1009 for(j=0; j<absQPStride; j++) {
1010 c->
nonBQPTable[i*absQPStride+j] = QP_store[i*QPStride+j] & 0x3F;
1019 postProcess(src[0], srcStride[0], dst[0], dstStride[0],
1020 width, height, QP_store, QPStride, 0, mode, c);
1022 if (!(src[1] && src[2] && dst[1] && dst[2]))
1029 postProcess(src[1], srcStride[1], dst[1], dstStride[1],
1030 width, height, QP_store, QPStride, 1, mode, c);
1031 postProcess(src[2], srcStride[2], dst[2], dstStride[2],
1032 width, height, QP_store, QPStride, 2, mode, c);
1034 else if(srcStride[1] == dstStride[1] && srcStride[2] == dstStride[2]){
1035 linecpy(dst[1], src[1], height, srcStride[1]);
1036 linecpy(dst[2], src[2], height, srcStride[2]);
1040 memcpy(&(dst[1][y*dstStride[1]]), &(src[1][y*srcStride[1]]), width);
1041 memcpy(&(dst[2][y*dstStride[2]]), &(src[2][y*srcStride[2]]), width);
static av_always_inline void do_a_deblock_C(uint8_t *src, int step, int stride, const PPContext *c, int mode)
accurate deblock filter
#define AV_CPU_FLAG_ALTIVEC
standard
const char const char void * val
static const char *const replaceTable[]
int maxTmpNoise[3]
for Temporal Noise Reducing filter (Maximal sum of abs differences)
const AVClass * av_class
info on struct for av_log
int chromMode
activates filters for chrominance
uint8_t * tempDst
Temporary buffers for handling the last row(s)
av_cold void pp_free_context(void *vc)
static void doHorizDefFilter_C(uint8_t dst[], int stride, const PPContext *c)
void pp_postprocess(const uint8_t *src[3], const int srcStride[3], uint8_t *dst[3], const int dstStride[3], int width, int height, const QP_STORE_T *QP_store, int QPStride, pp_mode *vm, void *vc, int pict_type)
pp_mode * pp_get_mode_by_name_and_quality(const char *name, int quality)
Return a pp_mode or NULL if an error occurred.
Convenience header that includes libavutil's core.
void(* pp_fn)(const uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height, const QP_STORE_T QPs[], int QPStride, int isColor, PPContext *c2)
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
av_cold pp_context * pp_get_context(int width, int height, int cpuCaps)
#define LINEAR_BLEND_DEINT_FILTER
mmx/mmx2/3dnow postprocess code.
QP_STORE_T * stdQPTable
used to fix MPEG2 style qscale
#define av_assert0(cond)
assert() equivalent, that is always enabled.
unsigned postproc_version(void)
Return the LIBPOSTPROC_VERSION_INT constant.
static int isVertMinMaxOk_C(const uint8_t src[], int stride, int QP)
int minAllowedY
for brightness correction
int qpStride
size of qp buffers (needed to realloc them if needed)
uint64_t * yHistogram
luma histogram.
#define AV_CPU_FLAG_MMXEXT
SSE integer functions or AMD MMX ext.
static int horizClassify_C(const uint8_t src[], int stride, const PPContext *c)
static int isHorizDC_C(const uint8_t src[], int stride, const PPContext *c)
Check if the given 8x8 Block is mostly "flat".
static int vertClassify_C(const uint8_t src[], int stride, const PPContext *c)
#define LOWPASS5_DEINT_FILTER
static void horizX1Filter(uint8_t *src, int stride, int QP)
Experimental Filter 1 (Horizontal) will not damage linear gradients Flat blocks should look like they...
const OptionDef options[]
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
static const uint16_t mask[17]
const char * postproc_license(void)
Return the libpostproc license.
const char pp_help[]
a simple help text
int error
non zero on error
static void linecpy(void *dest, const void *src, int lines, int stride)
#define MEDIAN_DEINT_FILTER
#define CUBIC_IPOL_DEINT_FILTER
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
simple assert() macros that are a bit more flexible than ISO C assert().
uint8_t * tempBlurred[3]
Temporal noise reducing buffers.
int forcedQuant
quantizer if FORCE_QUANT is used
#define PP_CPU_CAPS_ALTIVEC
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
static int isVertDC_C(const uint8_t src[], int stride, const PPContext *c)
Check if the middle 8x8 Block in the given 8x16 block is flat.
#define PP_PICT_TYPE_QP2
MPEG2 style QScale.
#define LINEAR_IPOL_DEINT_FILTER
int maxAllowedY
for brightness correction
static void reallocAlign(void **p, int size)
typedef void(APIENTRY *FF_PFNGLACTIVETEXTUREPROC)(GLenum texture)
const char postproc_ffversion[]
void pp_free_mode(pp_mode *mode)
#define FFMPEG_DEINT_FILTER
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
static const AVClass av_codec_context_class
#define FF_ARRAY_ELEMS(a)
int lumMode
activates filters for luminance
static void reallocBuffers(PPContext *c, int width, int height, int stride, int qpStride)
#define AV_CPU_FLAG_3DNOW
AMD 3DNOW.
#define AV_LOG_INFO
Standard information.
#define AV_CPU_FLAG_MMX
standard MMX
uint8_t * tempBlocks
used for the horizontal code
Describe the class of an AVClass context structure.
Rational number (pair of numerator and denominator).
int av_get_cpu_flags(void)
Return the flags which specify extensions supported by the CPU.
AVRational maxClippedThreshold
amount of "black" you are willing to lose to get a brightness-corrected picture
QP_STORE_T * forcedQPTable
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok()...
int32_t * tempBlurredPast[3]
GLint GLenum GLboolean GLsizei stride
const char * postproc_configuration(void)
Return the libpostproc build-time configuration.
static int isHorizMinMaxOk_C(const uint8_t src[], int stride, int QP)
#define LIBPOSTPROC_VERSION_INT
#define TEMP_NOISE_FILTER
DECLARE_ASM_CONST(8, int, deringThreshold)
int mask
Bitmask to turn this filter on.
static const struct PPFilter filters[]
static const char * context_to_name(void *ptr)
#define AV_CPU_FLAG_SSE2
PIV SSE2 functions.
static void doHorizLowPass_C(uint8_t dst[], int stride, const PPContext *c)
Do a horizontal low pass filter on the 10x8 block (dst points to middle 8x8 Block) using the 9-Tap Fi...
#define OPTIONS_ARRAY_SIZE
#define LEVEL_FIX
Brightness & Contrast.
mode
Use these values in ebur128_init (or'ed).
#define LIBPOSTPROC_VERSION_MICRO
int stride
size of some buffers (needed to realloc them if needed)
static void postProcess(const uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height, const QP_STORE_T QPs[], int QPStride, int isColor, pp_mode *vm, pp_context *vc)
#define PP_CPU_CAPS_3DNOW
#define GET_MODE_BUFFER_SIZE