1 /*
2 * Copyright (C) 2001-2003 Michael Niedermayer (michaelni@gmx.at)
3 *
4 * AltiVec optimizations (C) 2004 Romain Dolbeau <romain@dolbeau.org>
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 /**
24 * @file
25 * postprocessing.
26 */
27
28 /*
29 C MMX MMX2 3DNow AltiVec
30 isVertDC Ec Ec Ec
31 isVertMinMaxOk Ec Ec Ec
32 doVertLowPass E e e Ec
33 doVertDefFilter Ec Ec e e Ec
34 isHorizDC Ec Ec Ec
35 isHorizMinMaxOk a E Ec
36 doHorizLowPass E e e Ec
37 doHorizDefFilter Ec Ec e e Ec
38 do_a_deblock Ec E Ec E
39 deRing E e e* Ecp
40 Vertical RKAlgo1 E a a
41 Horizontal RKAlgo1 a a
42 Vertical X1# a E E
43 Horizontal X1# a E E
44 LinIpolDeinterlace e E E*
45 CubicIpolDeinterlace a e e*
46 LinBlendDeinterlace e E E*
47 MedianDeinterlace# E Ec Ec
48 TempDeNoiser# E e e Ec
49
50 * I do not have a 3DNow! CPU -> it is untested, but no one said it does not work so it seems to work
51 # more or less selfinvented filters so the exactness is not too meaningful
52 E = Exact implementation
53 e = almost exact implementation (slightly different rounding,...)
54 a = alternative / approximate impl
55 c = checked against the other implementations (-vo md5)
56 p = partially optimized, still some work to do
57 */
58
59 /*
60 TODO:
61 reduce the time wasted on the mem transfer
62 unroll stuff if instructions depend too much on the prior one
63 move YScale thing to the end instead of fixing QP
64 write a faster and higher quality deblocking filter :)
65 make the mainloop more flexible (variable number of blocks at once
66 (the if/else stuff per block is slowing things down)
67 compare the quality & speed of all filters
68 split this huge file
69 optimize c versions
70 try to unroll inner for(x=0 ... loop to avoid these damn if(x ... checks
71 ...
72 */
73
74 //Changelog: use git log
75
80 #include <inttypes.h>
81 #include <stdio.h>
82 #include <stdlib.h>
83 #include <string.h>
84 //#undef HAVE_MMXEXT_INLINE
85 //#define HAVE_AMD3DNOW_INLINE
86 //#undef HAVE_MMX_INLINE
87 //#undef ARCH_X86
88 //#define DEBUG_BRIGHTNESS
92
93 #include "libavutil/ffversion.h"
95
97 {
100 }
101
103 {
104 return FFMPEG_CONFIGURATION;
105 }
106
108 {
109 #define LICENSE_PREFIX "libpostproc license: "
111 }
112
113 #if HAVE_ALTIVEC_H
114 #include <altivec.h>
115 #endif
116
117 #define GET_MODE_BUFFER_SIZE 500
118 #define OPTIONS_ARRAY_SIZE 10
120 #define TEMP_STRIDE 8
121 //#define NUM_BLOCKS_AT_ONCE 16 //not used yet
122
123 #if ARCH_X86 && HAVE_INLINE_ASM
132 #endif
133
135
136
138 {
141 /* {"hr", "rkhdeblock", 1, 1, 3, H_RK1_FILTER},
142 {"vr", "rkvdeblock", 1, 2, 4, V_RK1_FILTER},*/
147 {
"dr",
"dering", 1, 5, 6,
DERING},
148 {
"al",
"autolevels", 0, 1, 2,
LEVEL_FIX},
157 {
"be",
"bitexact", 1, 0, 0,
BITEXACT},
160 };
161
163 {
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",
170 };
171
172 /* The horizontal functions exist only in C because the MMX
173 * code is faster with vertical filters and transposing. */
174
175 /**
176 * Check if the given 8x8 Block is mostly "flat"
177 */
179 {
180 int numEq= 0;
181 int y;
183 const int dcThreshold= dcOffset*2 + 1;
184
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;
194 }
196 }
197
198 /**
199 * Check if the middle 8x8 Block in the given 8x16 block is flat
200 */
202 {
203 int numEq= 0;
204 int y;
206 const int dcThreshold= dcOffset*2 + 1;
207
208 src+= stride*4; // src points to begin of the 8x8 Block
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;
219 }
221 }
222
224 {
225 int i;
226 for(i=0; i<2; i++){
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;
235 }
236 return 1;
237 }
238
240 {
241 int x;
242 src+= stride*4;
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;
248 }
249 return 1;
250 }
251
253 {
256 }else{
257 return 2;
258 }
259 }
260
262 {
265 }else{
266 return 2;
267 }
268 }
269
271 {
272 int y;
274 const int middleEnergy= 5*(dst[4] - dst[3]) + 2*(dst[2] - dst[5]);
275
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]);
280
283
284 d= (5*d + 32) >> 6;
285 d*=
FFSIGN(-middleEnergy);
286
287 if(q>0)
288 {
291 }
292 else
293 {
296 }
297
298 dst[3]-= d;
299 dst[4]+= d;
300 }
302 }
303 }
304
305 /**
306 * Do a horizontal low pass filter on the 10x8 block (dst points to middle 8x8 Block)
307 * using the 9-Tap Filter (1,1,2,2,4,2,2,1,1)/16 (C version)
308 */
310 {
311 int y;
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];
315
316 int sums[10];
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;
327
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;
336
338 }
339 }
340
341 /**
342 * Experimental Filter 1 (Horizontal)
343 * will not damage linear gradients
344 * Flat blocks should look like they were passed through the (1,1,2,2,4,2,2,1,1) 9-Tap filter
345 * can only smooth blocks at the expected locations (it cannot smooth them if they did move)
346 * MMX2 version does correct clipping C version does not
347 * not identical with the vertical one
348 */
350 {
351 int y;
352 static uint64_t lut[256];
353 if(!lut[255])
354 {
355 int i;
356 for(i=0; i<256; i++)
357 {
358 int v= i < 128 ? 2*i : 2*(i-256);
359 /*
360 //Simulate 112242211 9-Tap filter
361 uint64_t a= (v/16) & 0xFF;
362 uint64_t b= (v/8) & 0xFF;
363 uint64_t c= (v/4) & 0xFF;
364 uint64_t d= (3*v/8) & 0xFF;
365 */
366 //Simulate piecewise linear interpolation
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;
375
376 lut[i] = (a<<56) | (b<<48) | (c<<40) | (d<<32) |
377 (D<<24) | (C<<16) | (B<<8) | (A);
378 //lut[i] = (v<<32) | (v<<24);
379 }
380 }
381
383 int a= src[1] - src[2];
384 int b= src[3] - src[4];
385 int c= src[5] - src[6];
386
388
389 if(d < QP){
391
392 src[1] +=v/8;
393 src[2] +=v/4;
394 src[3] +=3*v/8;
395 src[4] -=3*v/8;
396 src[5] -=v/4;
397 src[6] -=v/8;
398 }
400 }
401 }
402
403 /**
404 * accurate deblock filter
405 */
408 {
409 int y;
412 const int dcThreshold= dcOffset*2 + 1;
413 //START_TIMER
414 src+= step*4; // src points to begin of the 8x8 Block
415 for(y=0; y<8; y++){
416 int numEq= 0;
417
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;
429
430 if(src[0] > src[step]){
431 max= src[0];
432 min= src[step];
433 }else{
434 max= src[step];
435 min= src[0];
436 }
437 for(x=2; x<8; x+=2){
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];
441 }else{
442 if(src[(x+1)*step] > max) max= src[(x+1)*step];
443 if(src[ x *step] < min) min= src[ x *step];
444 }
445 }
446 if(max-min < 2*QP){
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];
449
450 int sums[10];
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;
461
463 src[0*step] =
464 src[1*step] =
465 src[2*step] =
466 src[3*step] =
467 src[4*step] =
468 src[5*step] =
469 src[6*step] =
470 src[7*step] = 128;
471 }
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;
480 }
481 }else{
482 const int middleEnergy= 5*(src[4*step] - src[3*step]) + 2*(src[2*step] - src[5*step]);
483
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]);
488
491
492 d= (5*d + 32) >> 6;
493 d*=
FFSIGN(-middleEnergy);
494
495 if(q>0){
498 }else{
501 }
502
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);
507 d = 0;
508 }
509
510 src[3*step]-= d;
511 src[4*step]+= d;
512 }
513 }
514
516 }
517 /*if(step==16){
518 STOP_TIMER("step16")
519 }else{
520 STOP_TIMER("stepX")
521 }*/
522 }
523
524 //Note: we have C, MMX, MMX2, 3DNOW version there is no 3DNOW+MMX2 one
525 //Plain C versions
526 //we always compile C for testing which needs bitexactness
527 #define TEMPLATE_PP_C 1
529
530 #if HAVE_ALTIVEC
531 # define TEMPLATE_PP_ALTIVEC 1
534 #endif
535
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
546 # else
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
559 # endif
560 # endif
561 #endif
562
564 const QP_STORE_T QPs[],
int QPStride,
int isColor,
PPContext *
c2);
565
568 {
569 pp_fn pp = postProcess_C;
572 c->
ppMode= *ppMode;
//FIXME
573
575 #if CONFIG_RUNTIME_CPUDETECT
576 #if ARCH_X86 && HAVE_INLINE_ASM
577 // ordered per speed fastest first
582 #elif HAVE_ALTIVEC
584 #endif
585 #else /* CONFIG_RUNTIME_CPUDETECT */
586 #if HAVE_SSE2_INLINE
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;
594 #elif HAVE_ALTIVEC
595 pp = postProcess_altivec;
596 #endif
597 #endif /* !CONFIG_RUNTIME_CPUDETECT */
598 }
599
600 pp(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
601 }
602
603 /* -pp Command line Help
604 */
606 "Available postprocessing filters:\n"
607 "Filters Options\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"
638 "Usage:\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"
644 "more examples:\n"
645 "tn:64:128:256\n"
646 "\n"
647 ;
648
650 {
653 static const char filterDelimiters[] = ",/";
654 static const char optionDelimiters[] = ":|";
656 char *filterToken;
657
658 if (!name) {
661 }
662
663 if (!strcmp(name, "help")) {
664 const char *p;
665 for (p =
pp_help; strchr(p,
'\n'); p = strchr(p,
'\n') + 1) {
668 }
670 }
671
673 if (!ppMode)
675
687
690
692
693 for(;;){
694 const char *filterName;
695 int q= 1000000; //PP_QUALITY_MAX;
696 int chrom=-1;
697 int luma=-1;
700 int i;
701 int filterNameOk=0;
702 int numOfUnknownOptions=0;
703 int enable=1; //does the user want us to enabled or disabled the filter
704 char *tokstate;
705
706 filterToken=
av_strtok(p, filterDelimiters, &tokstate);
707 if(!filterToken) break;
708 p+= strlen(filterToken) + 1; // p points to next filterToken
709 filterName=
av_strtok(filterToken, optionDelimiters, &tokstate);
710 if (!filterName) {
712 break;
713 }
715
716 if(*filterName == '-'){
717 enable=0;
718 filterName++;
719 }
720
721 for(;;){ //for all options
723 if(!option) break;
724
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;
730 else{
731 options[numOfUnknownOptions] =
option;
732 numOfUnknownOptions++;
733 }
735 }
736 options[numOfUnknownOptions] =
NULL;
737
738 /* replace stuff from the replace Table */
742 int plen;
743 int spaceLeft;
744
745 p--, *p=',';
746
747 plen= strlen(p);
748 spaceLeft= p - temp + plen;
751 break;
752 }
753 memmove(p + newlen, p, plen+1);
755 filterNameOk=1;
756 }
757 }
758
760 if( !strcmp(filters[i].longName, filterName)
761 || !strcmp(filters[i].shortName, filterName)){
764
765 filterNameOk=1;
766 if(!enable) break; // user wants to disable it
767
768 if(q >= filters[i].minLumQuality && luma)
770 if(chrom==1 || (chrom==-1 && filters[i].chromDefault))
771 if(q >= filters[i].minChromQuality)
773
775 int o;
778 for(o=0; options[o]; o++){
779 if( !strcmp(options[o],"fullyrange")
780 ||!strcmp(options[o],"f")){
783 numOfUnknownOptions--;
784 }
785 }
786 }
788 {
789 int o;
790 int numOfNoises=0;
791
792 for(o=0; options[o]; o++){
793 char *tail;
795 strtol(options[o], &tail, 0);
796 if(tail!=options[o]){
797 numOfNoises++;
798 numOfUnknownOptions--;
799 if(numOfNoises >= 3) break;
800 }
801 }
802 }
805 int o;
806
807 for(o=0; options[o] && o<2; o++){
808 char *tail;
809 int val= strtol(options[o], &tail, 0);
810 if(tail==options[o]) break;
811
812 numOfUnknownOptions--;
815 }
816 }
818 int o;
820
821 for(o=0; options[o] && o<1; o++){
822 char *tail;
823 int val= strtol(options[o], &tail, 0);
824 if(tail==options[o]) break;
825
826 numOfUnknownOptions--;
828 }
829 }
830 }
831 }
832 if(!filterNameOk) ppMode->
error++;
833 ppMode->
error += numOfUnknownOptions;
834 }
835
841 }
842 return ppMode;
843 }
844
847 }
848
852 }
853
855 int mbWidth = (width+15)>>4;
856 int mbHeight= (height+15)>>4;
857 int i;
858
861
866 for(i=0; i<256; i++)
868
869 for(i=0; i<3; i++){
870 //Note: The +17*1024 is just there so I do not have to worry about r/w over the end.
873 }
874
879 }
880
882 return "postproc";
883 }
884
886
889 int stride=
FFALIGN(width, 16);
//assumed / will realloc if needed
890 int qpStride= (width+15)/16 + 2; //assumed / will realloc if needed
891
892 if (!c)
894
899 }else{
902 }
905 } else {
911 }
912
914
916
918 }
919
922 int i;
923
928
937
939
941 }
942
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)
948 {
949 int mbWidth = (width+15)>>4;
950 int mbHeight= (height+15)>>4;
954 int absQPStride =
FFABS(QPStride);
955
956 // c->stride and c->QPStride are always positive
961
963 int i;
965 absQPStride = QPStride = 0;
968 else
970 }
971
973 int i;
974 const int count=
FFMAX(mbHeight * absQPStride, mbWidth);
975 for(i=0; i<(count>>2); i++){
976 ((uint32_t*)c->
stdQPTable)[i] = (((
const uint32_t*)QP_store)[i]>>1) & 0x7F7F7F7F;
977 }
978 for(i<<=2; i<
count; i++){
980 }
982 QPStride= absQPStride;
983 }
984
985 if(0){
986 int x,y;
987 for(y=0; y<mbHeight; y++){
988 for(x=0; x<mbWidth; x++){
990 }
992 }
994 }
995
996 if((pict_type&7)!=3){
997 if (QPStride >= 0){
998 int i;
999 const int count=
FFMAX(mbHeight * QPStride, mbWidth);
1000 for(i=0; i<(count>>2); i++){
1002 }
1003 for(i<<=2; i<
count; i++){
1005 }
1006 } else {
1007 int i,j;
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;
1011 }
1012 }
1013 }
1014 }
1015
1018
1019 postProcess(src[0], srcStride[0], dst[0], dstStride[0],
1020 width, height, QP_store, QPStride, 0, mode, c);
1021
1022 if (!(src[1] && src[2] && dst[1] && dst[2]))
1023 return;
1024
1027
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);
1033 }
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]);
1037 }else{
1038 int y;
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);
1042 }
1043 }
1044 }
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.
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)
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
BYTE int const BYTE int int int height
Describe the class of an AVClass context structure.
rational number numerator/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.
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
#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