Add MPlayers libmpcodecs, this will be needed for our libavfilter wraper for it.
This commit is contained in:
parent
fe67841355
commit
e4852fb38d
59
libavfilter/libmpcodecs/cpudetect.h
Normal file
59
libavfilter/libmpcodecs/cpudetect.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_CPUDETECT_H
|
||||
#define MPLAYER_CPUDETECT_H
|
||||
|
||||
//#include "config.h"
|
||||
|
||||
#define CPUTYPE_I386 3
|
||||
#define CPUTYPE_I486 4
|
||||
#define CPUTYPE_I586 5
|
||||
#define CPUTYPE_I686 6
|
||||
|
||||
#include "libavutil/x86_cpu.h"
|
||||
|
||||
typedef struct cpucaps_s {
|
||||
int cpuType;
|
||||
int cpuModel;
|
||||
int cpuStepping;
|
||||
int hasMMX;
|
||||
int hasMMX2;
|
||||
int has3DNow;
|
||||
int has3DNowExt;
|
||||
int hasSSE;
|
||||
int hasSSE2;
|
||||
int hasSSE3;
|
||||
int hasSSSE3;
|
||||
int hasSSE4a;
|
||||
int isX86;
|
||||
unsigned cl_size; /* size of cache line */
|
||||
int hasAltiVec;
|
||||
int hasTSC;
|
||||
} CpuCaps;
|
||||
|
||||
extern CpuCaps gCpuCaps;
|
||||
|
||||
void do_cpuid(unsigned int ax, unsigned int *p);
|
||||
|
||||
void GetCpuCaps(CpuCaps *caps);
|
||||
|
||||
/* returned value is malloc()'ed so free() it after use */
|
||||
char *GetCpuFriendlyName(unsigned int regs[], unsigned int regs2[]);
|
||||
|
||||
#endif /* MPLAYER_CPUDETECT_H */
|
||||
2136
libavfilter/libmpcodecs/help_mp.h
Normal file
2136
libavfilter/libmpcodecs/help_mp.h
Normal file
File diff suppressed because it is too large
Load Diff
170
libavfilter/libmpcodecs/img_format.c
Normal file
170
libavfilter/libmpcodecs/img_format.c
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "img_format.h"
|
||||
#include "stdio.h"
|
||||
|
||||
const char *vo_format_name(int format)
|
||||
{
|
||||
static char unknown_format[20];
|
||||
switch(format)
|
||||
{
|
||||
case IMGFMT_RGB1: return "RGB 1-bit";
|
||||
case IMGFMT_RGB4: return "RGB 4-bit";
|
||||
case IMGFMT_RG4B: return "RGB 4-bit per byte";
|
||||
case IMGFMT_RGB8: return "RGB 8-bit";
|
||||
case IMGFMT_RGB12: return "RGB 12-bit";
|
||||
case IMGFMT_RGB15: return "RGB 15-bit";
|
||||
case IMGFMT_RGB16: return "RGB 16-bit";
|
||||
case IMGFMT_RGB24: return "RGB 24-bit";
|
||||
// case IMGFMT_RGB32: return "RGB 32-bit";
|
||||
case IMGFMT_RGB48LE: return "RGB 48-bit LE";
|
||||
case IMGFMT_RGB48BE: return "RGB 48-bit BE";
|
||||
case IMGFMT_BGR1: return "BGR 1-bit";
|
||||
case IMGFMT_BGR4: return "BGR 4-bit";
|
||||
case IMGFMT_BG4B: return "BGR 4-bit per byte";
|
||||
case IMGFMT_BGR8: return "BGR 8-bit";
|
||||
case IMGFMT_BGR12: return "BGR 12-bit";
|
||||
case IMGFMT_BGR15: return "BGR 15-bit";
|
||||
case IMGFMT_BGR16: return "BGR 16-bit";
|
||||
case IMGFMT_BGR24: return "BGR 24-bit";
|
||||
// case IMGFMT_BGR32: return "BGR 32-bit";
|
||||
case IMGFMT_ABGR: return "ABGR";
|
||||
case IMGFMT_BGRA: return "BGRA";
|
||||
case IMGFMT_ARGB: return "ARGB";
|
||||
case IMGFMT_RGBA: return "RGBA";
|
||||
case IMGFMT_YVU9: return "Planar YVU9";
|
||||
case IMGFMT_IF09: return "Planar IF09";
|
||||
case IMGFMT_YV12: return "Planar YV12";
|
||||
case IMGFMT_I420: return "Planar I420";
|
||||
case IMGFMT_IYUV: return "Planar IYUV";
|
||||
case IMGFMT_CLPL: return "Planar CLPL";
|
||||
case IMGFMT_Y800: return "Planar Y800";
|
||||
case IMGFMT_Y8: return "Planar Y8";
|
||||
case IMGFMT_420P16_LE: return "Planar 420P 16-bit little-endian";
|
||||
case IMGFMT_420P16_BE: return "Planar 420P 16-bit big-endian";
|
||||
case IMGFMT_422P16_LE: return "Planar 422P 16-bit little-endian";
|
||||
case IMGFMT_422P16_BE: return "Planar 422P 16-bit big-endian";
|
||||
case IMGFMT_444P16_LE: return "Planar 444P 16-bit little-endian";
|
||||
case IMGFMT_444P16_BE: return "Planar 444P 16-bit big-endian";
|
||||
case IMGFMT_420A: return "Planar 420P with alpha";
|
||||
case IMGFMT_444P: return "Planar 444P";
|
||||
case IMGFMT_422P: return "Planar 422P";
|
||||
case IMGFMT_411P: return "Planar 411P";
|
||||
case IMGFMT_NV12: return "Planar NV12";
|
||||
case IMGFMT_NV21: return "Planar NV21";
|
||||
case IMGFMT_HM12: return "Planar NV12 Macroblock";
|
||||
case IMGFMT_IUYV: return "Packed IUYV";
|
||||
case IMGFMT_IY41: return "Packed IY41";
|
||||
case IMGFMT_IYU1: return "Packed IYU1";
|
||||
case IMGFMT_IYU2: return "Packed IYU2";
|
||||
case IMGFMT_UYVY: return "Packed UYVY";
|
||||
case IMGFMT_UYNV: return "Packed UYNV";
|
||||
case IMGFMT_cyuv: return "Packed CYUV";
|
||||
case IMGFMT_Y422: return "Packed Y422";
|
||||
case IMGFMT_YUY2: return "Packed YUY2";
|
||||
case IMGFMT_YUNV: return "Packed YUNV";
|
||||
case IMGFMT_YVYU: return "Packed YVYU";
|
||||
case IMGFMT_Y41P: return "Packed Y41P";
|
||||
case IMGFMT_Y211: return "Packed Y211";
|
||||
case IMGFMT_Y41T: return "Packed Y41T";
|
||||
case IMGFMT_Y42T: return "Packed Y42T";
|
||||
case IMGFMT_V422: return "Packed V422";
|
||||
case IMGFMT_V655: return "Packed V655";
|
||||
case IMGFMT_CLJR: return "Packed CLJR";
|
||||
case IMGFMT_YUVP: return "Packed YUVP";
|
||||
case IMGFMT_UYVP: return "Packed UYVP";
|
||||
case IMGFMT_MPEGPES: return "Mpeg PES";
|
||||
case IMGFMT_ZRMJPEGNI: return "Zoran MJPEG non-interlaced";
|
||||
case IMGFMT_ZRMJPEGIT: return "Zoran MJPEG top field first";
|
||||
case IMGFMT_ZRMJPEGIB: return "Zoran MJPEG bottom field first";
|
||||
case IMGFMT_XVMC_MOCO_MPEG2: return "MPEG1/2 Motion Compensation";
|
||||
case IMGFMT_XVMC_IDCT_MPEG2: return "MPEG1/2 Motion Compensation and IDCT";
|
||||
case IMGFMT_VDPAU_MPEG1: return "MPEG1 VDPAU acceleration";
|
||||
case IMGFMT_VDPAU_MPEG2: return "MPEG2 VDPAU acceleration";
|
||||
case IMGFMT_VDPAU_H264: return "H.264 VDPAU acceleration";
|
||||
case IMGFMT_VDPAU_MPEG4: return "MPEG-4 Part 2 VDPAU acceleration";
|
||||
case IMGFMT_VDPAU_WMV3: return "WMV3 VDPAU acceleration";
|
||||
case IMGFMT_VDPAU_VC1: return "VC1 VDPAU acceleration";
|
||||
}
|
||||
snprintf(unknown_format,20,"Unknown 0x%04x",format);
|
||||
return unknown_format;
|
||||
}
|
||||
|
||||
int mp_get_chroma_shift(int format, int *x_shift, int *y_shift)
|
||||
{
|
||||
int xs = 0, ys = 0;
|
||||
int bpp;
|
||||
int bpp_factor = 1;
|
||||
int err = 0;
|
||||
switch (format) {
|
||||
case IMGFMT_420P16_LE:
|
||||
case IMGFMT_420P16_BE:
|
||||
bpp_factor = 2;
|
||||
case IMGFMT_420A:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_YV12:
|
||||
xs = 1;
|
||||
ys = 1;
|
||||
break;
|
||||
case IMGFMT_IF09:
|
||||
case IMGFMT_YVU9:
|
||||
xs = 2;
|
||||
ys = 2;
|
||||
break;
|
||||
case IMGFMT_444P16_LE:
|
||||
case IMGFMT_444P16_BE:
|
||||
bpp_factor = 2;
|
||||
case IMGFMT_444P:
|
||||
xs = 0;
|
||||
ys = 0;
|
||||
break;
|
||||
case IMGFMT_422P16_LE:
|
||||
case IMGFMT_422P16_BE:
|
||||
bpp_factor = 2;
|
||||
case IMGFMT_422P:
|
||||
xs = 1;
|
||||
ys = 0;
|
||||
break;
|
||||
case IMGFMT_411P:
|
||||
xs = 2;
|
||||
ys = 0;
|
||||
break;
|
||||
case IMGFMT_440P:
|
||||
xs = 0;
|
||||
ys = 1;
|
||||
break;
|
||||
case IMGFMT_Y8:
|
||||
case IMGFMT_Y800:
|
||||
xs = 31;
|
||||
ys = 31;
|
||||
break;
|
||||
default:
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
if (x_shift) *x_shift = xs;
|
||||
if (y_shift) *y_shift = ys;
|
||||
bpp = 8 + ((16 >> xs) >> ys);
|
||||
if (format == IMGFMT_420A)
|
||||
bpp += 8;
|
||||
bpp *= bpp_factor;
|
||||
return err ? 0 : bpp;
|
||||
}
|
||||
214
libavfilter/libmpcodecs/img_format.h
Normal file
214
libavfilter/libmpcodecs/img_format.h
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_IMG_FORMAT_H
|
||||
#define MPLAYER_IMG_FORMAT_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* RGB/BGR Formats */
|
||||
|
||||
#define IMGFMT_RGB_MASK 0xFFFFFF00
|
||||
#define IMGFMT_RGB (('R'<<24)|('G'<<16)|('B'<<8))
|
||||
#define IMGFMT_RGB1 (IMGFMT_RGB|1)
|
||||
#define IMGFMT_RGB4 (IMGFMT_RGB|4)
|
||||
#define IMGFMT_RGB4_CHAR (IMGFMT_RGB|4|128) // RGB4 with 1 pixel per byte
|
||||
#define IMGFMT_RGB8 (IMGFMT_RGB|8)
|
||||
#define IMGFMT_RGB12 (IMGFMT_RGB|12)
|
||||
#define IMGFMT_RGB15 (IMGFMT_RGB|15)
|
||||
#define IMGFMT_RGB16 (IMGFMT_RGB|16)
|
||||
#define IMGFMT_RGB24 (IMGFMT_RGB|24)
|
||||
#define IMGFMT_RGB32 (IMGFMT_RGB|32)
|
||||
#define IMGFMT_RGB48LE (IMGFMT_RGB|48)
|
||||
#define IMGFMT_RGB48BE (IMGFMT_RGB|48|128)
|
||||
|
||||
#define IMGFMT_BGR_MASK 0xFFFFFF00
|
||||
#define IMGFMT_BGR (('B'<<24)|('G'<<16)|('R'<<8))
|
||||
#define IMGFMT_BGR1 (IMGFMT_BGR|1)
|
||||
#define IMGFMT_BGR4 (IMGFMT_BGR|4)
|
||||
#define IMGFMT_BGR4_CHAR (IMGFMT_BGR|4|128) // BGR4 with 1 pixel per byte
|
||||
#define IMGFMT_BGR8 (IMGFMT_BGR|8)
|
||||
#define IMGFMT_BGR12 (IMGFMT_BGR|12)
|
||||
#define IMGFMT_BGR15 (IMGFMT_BGR|15)
|
||||
#define IMGFMT_BGR16 (IMGFMT_BGR|16)
|
||||
#define IMGFMT_BGR24 (IMGFMT_BGR|24)
|
||||
#define IMGFMT_BGR32 (IMGFMT_BGR|32)
|
||||
|
||||
#if HAVE_BIGENDIAN
|
||||
#define IMGFMT_ABGR IMGFMT_RGB32
|
||||
#define IMGFMT_BGRA (IMGFMT_RGB32|64)
|
||||
#define IMGFMT_ARGB IMGFMT_BGR32
|
||||
#define IMGFMT_RGBA (IMGFMT_BGR32|64)
|
||||
#define IMGFMT_RGB48NE IMGFMT_RGB48BE
|
||||
#define IMGFMT_RGB12BE IMGFMT_RGB12
|
||||
#define IMGFMT_RGB12LE (IMGFMT_RGB12|64)
|
||||
#define IMGFMT_RGB15BE IMGFMT_RGB15
|
||||
#define IMGFMT_RGB15LE (IMGFMT_RGB15|64)
|
||||
#define IMGFMT_RGB16BE IMGFMT_RGB16
|
||||
#define IMGFMT_RGB16LE (IMGFMT_RGB16|64)
|
||||
#define IMGFMT_BGR12BE IMGFMT_BGR12
|
||||
#define IMGFMT_BGR12LE (IMGFMT_BGR12|64)
|
||||
#define IMGFMT_BGR15BE IMGFMT_BGR15
|
||||
#define IMGFMT_BGR15LE (IMGFMT_BGR15|64)
|
||||
#define IMGFMT_BGR16BE IMGFMT_BGR16
|
||||
#define IMGFMT_BGR16LE (IMGFMT_BGR16|64)
|
||||
#else
|
||||
#define IMGFMT_ABGR (IMGFMT_BGR32|64)
|
||||
#define IMGFMT_BGRA IMGFMT_BGR32
|
||||
#define IMGFMT_ARGB (IMGFMT_RGB32|64)
|
||||
#define IMGFMT_RGBA IMGFMT_RGB32
|
||||
#define IMGFMT_RGB48NE IMGFMT_RGB48LE
|
||||
#define IMGFMT_RGB12BE (IMGFMT_RGB12|64)
|
||||
#define IMGFMT_RGB12LE IMGFMT_RGB12
|
||||
#define IMGFMT_RGB15BE (IMGFMT_RGB15|64)
|
||||
#define IMGFMT_RGB15LE IMGFMT_RGB15
|
||||
#define IMGFMT_RGB16BE (IMGFMT_RGB16|64)
|
||||
#define IMGFMT_RGB16LE IMGFMT_RGB16
|
||||
#define IMGFMT_BGR12BE (IMGFMT_BGR12|64)
|
||||
#define IMGFMT_BGR12LE IMGFMT_BGR12
|
||||
#define IMGFMT_BGR15BE (IMGFMT_BGR15|64)
|
||||
#define IMGFMT_BGR15LE IMGFMT_BGR15
|
||||
#define IMGFMT_BGR16BE (IMGFMT_BGR16|64)
|
||||
#define IMGFMT_BGR16LE IMGFMT_BGR16
|
||||
#endif
|
||||
|
||||
/* old names for compatibility */
|
||||
#define IMGFMT_RG4B IMGFMT_RGB4_CHAR
|
||||
#define IMGFMT_BG4B IMGFMT_BGR4_CHAR
|
||||
|
||||
#define IMGFMT_IS_RGB(fmt) (((fmt)&IMGFMT_RGB_MASK)==IMGFMT_RGB)
|
||||
#define IMGFMT_IS_BGR(fmt) (((fmt)&IMGFMT_BGR_MASK)==IMGFMT_BGR)
|
||||
|
||||
#define IMGFMT_RGB_DEPTH(fmt) ((fmt)&0x3F)
|
||||
#define IMGFMT_BGR_DEPTH(fmt) ((fmt)&0x3F)
|
||||
|
||||
|
||||
/* Planar YUV Formats */
|
||||
|
||||
#define IMGFMT_YVU9 0x39555659
|
||||
#define IMGFMT_IF09 0x39304649
|
||||
#define IMGFMT_YV12 0x32315659
|
||||
#define IMGFMT_I420 0x30323449
|
||||
#define IMGFMT_IYUV 0x56555949
|
||||
#define IMGFMT_CLPL 0x4C504C43
|
||||
#define IMGFMT_Y800 0x30303859
|
||||
#define IMGFMT_Y8 0x20203859
|
||||
#define IMGFMT_NV12 0x3231564E
|
||||
#define IMGFMT_NV21 0x3132564E
|
||||
|
||||
/* unofficial Planar Formats, FIXME if official 4CC exists */
|
||||
#define IMGFMT_444P 0x50343434
|
||||
#define IMGFMT_422P 0x50323234
|
||||
#define IMGFMT_411P 0x50313134
|
||||
#define IMGFMT_440P 0x50303434
|
||||
#define IMGFMT_HM12 0x32314D48
|
||||
|
||||
// 4:2:0 planar with alpha
|
||||
#define IMGFMT_420A 0x41303234
|
||||
|
||||
#define IMGFMT_444P16_LE 0x51343434
|
||||
#define IMGFMT_444P16_BE 0x34343451
|
||||
#define IMGFMT_422P16_LE 0x51323234
|
||||
#define IMGFMT_422P16_BE 0x34323251
|
||||
#define IMGFMT_420P16_LE 0x51303234
|
||||
#define IMGFMT_420P16_BE 0x34323051
|
||||
#if HAVE_BIGENDIAN
|
||||
#define IMGFMT_444P16 IMGFMT_444P16_BE
|
||||
#define IMGFMT_422P16 IMGFMT_422P16_BE
|
||||
#define IMGFMT_420P16 IMGFMT_420P16_BE
|
||||
#else
|
||||
#define IMGFMT_444P16 IMGFMT_444P16_LE
|
||||
#define IMGFMT_422P16 IMGFMT_422P16_LE
|
||||
#define IMGFMT_420P16 IMGFMT_420P16_LE
|
||||
#endif
|
||||
|
||||
#define IMGFMT_IS_YUVP16_LE(fmt) (((fmt ^ IMGFMT_420P16_LE) & 0xff0000ff) == 0)
|
||||
#define IMGFMT_IS_YUVP16_BE(fmt) (((fmt ^ IMGFMT_420P16_BE) & 0xff0000ff) == 0)
|
||||
#define IMGFMT_IS_YUVP16_NE(fmt) (((fmt ^ IMGFMT_420P16 ) & 0xff0000ff) == 0)
|
||||
#define IMGFMT_IS_YUVP16(fmt) (IMGFMT_IS_YUVP16_LE(fmt) || IMGFMT_IS_YUVP16_BE(fmt))
|
||||
|
||||
/* Packed YUV Formats */
|
||||
|
||||
#define IMGFMT_IUYV 0x56595549
|
||||
#define IMGFMT_IY41 0x31435949
|
||||
#define IMGFMT_IYU1 0x31555949
|
||||
#define IMGFMT_IYU2 0x32555949
|
||||
#define IMGFMT_UYVY 0x59565955
|
||||
#define IMGFMT_UYNV 0x564E5955
|
||||
#define IMGFMT_cyuv 0x76757963
|
||||
#define IMGFMT_Y422 0x32323459
|
||||
#define IMGFMT_YUY2 0x32595559
|
||||
#define IMGFMT_YUNV 0x564E5559
|
||||
#define IMGFMT_YVYU 0x55595659
|
||||
#define IMGFMT_Y41P 0x50313459
|
||||
#define IMGFMT_Y211 0x31313259
|
||||
#define IMGFMT_Y41T 0x54313459
|
||||
#define IMGFMT_Y42T 0x54323459
|
||||
#define IMGFMT_V422 0x32323456
|
||||
#define IMGFMT_V655 0x35353656
|
||||
#define IMGFMT_CLJR 0x524A4C43
|
||||
#define IMGFMT_YUVP 0x50565559
|
||||
#define IMGFMT_UYVP 0x50565955
|
||||
|
||||
/* Compressed Formats */
|
||||
#define IMGFMT_MPEGPES (('M'<<24)|('P'<<16)|('E'<<8)|('S'))
|
||||
#define IMGFMT_MJPEG (('M')|('J'<<8)|('P'<<16)|('G'<<24))
|
||||
/* Formats that are understood by zoran chips, we include
|
||||
* non-interlaced, interlaced top-first, interlaced bottom-first */
|
||||
#define IMGFMT_ZRMJPEGNI (('Z'<<24)|('R'<<16)|('N'<<8)|('I'))
|
||||
#define IMGFMT_ZRMJPEGIT (('Z'<<24)|('R'<<16)|('I'<<8)|('T'))
|
||||
#define IMGFMT_ZRMJPEGIB (('Z'<<24)|('R'<<16)|('I'<<8)|('B'))
|
||||
|
||||
// I think that this code could not be used by any other codec/format
|
||||
#define IMGFMT_XVMC 0x1DC70000
|
||||
#define IMGFMT_XVMC_MASK 0xFFFF0000
|
||||
#define IMGFMT_IS_XVMC(fmt) (((fmt)&IMGFMT_XVMC_MASK)==IMGFMT_XVMC)
|
||||
//these are chroma420
|
||||
#define IMGFMT_XVMC_MOCO_MPEG2 (IMGFMT_XVMC|0x02)
|
||||
#define IMGFMT_XVMC_IDCT_MPEG2 (IMGFMT_XVMC|0x82)
|
||||
|
||||
// VDPAU specific format.
|
||||
#define IMGFMT_VDPAU 0x1DC80000
|
||||
#define IMGFMT_VDPAU_MASK 0xFFFF0000
|
||||
#define IMGFMT_IS_VDPAU(fmt) (((fmt)&IMGFMT_VDPAU_MASK)==IMGFMT_VDPAU)
|
||||
#define IMGFMT_VDPAU_MPEG1 (IMGFMT_VDPAU|0x01)
|
||||
#define IMGFMT_VDPAU_MPEG2 (IMGFMT_VDPAU|0x02)
|
||||
#define IMGFMT_VDPAU_H264 (IMGFMT_VDPAU|0x03)
|
||||
#define IMGFMT_VDPAU_WMV3 (IMGFMT_VDPAU|0x04)
|
||||
#define IMGFMT_VDPAU_VC1 (IMGFMT_VDPAU|0x05)
|
||||
#define IMGFMT_VDPAU_MPEG4 (IMGFMT_VDPAU|0x06)
|
||||
|
||||
#define IMGFMT_IS_HWACCEL(fmt) (IMGFMT_IS_VDPAU(fmt) || IMGFMT_IS_XVMC(fmt))
|
||||
|
||||
typedef struct {
|
||||
void* data;
|
||||
int size;
|
||||
int id; // stream id. usually 0x1E0
|
||||
int timestamp; // pts, 90000 Hz counter based
|
||||
} vo_mpegpes_t;
|
||||
|
||||
const char *vo_format_name(int format);
|
||||
|
||||
/**
|
||||
* Calculates the scale shifts for the chroma planes for planar YUV
|
||||
*
|
||||
* \return bits-per-pixel for format if successful (i.e. format is 3 or 4-planes planar YUV), 0 otherwise
|
||||
*/
|
||||
int mp_get_chroma_shift(int format, int *x_shift, int *y_shift);
|
||||
|
||||
#endif /* MPLAYER_IMG_FORMAT_H */
|
||||
99
libavfilter/libmpcodecs/libvo/fastmemcpy.h
Normal file
99
libavfilter/libmpcodecs/libvo/fastmemcpy.h
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with MPlayer; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_FASTMEMCPY_H
|
||||
#define MPLAYER_FASTMEMCPY_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void * fast_memcpy(void * to, const void * from, size_t len);
|
||||
void * mem2agpcpy(void * to, const void * from, size_t len);
|
||||
|
||||
#if ! defined(CONFIG_FASTMEMCPY) || ! (HAVE_MMX || HAVE_MMX2 || HAVE_AMD3DNOW /* || HAVE_SSE || HAVE_SSE2 */)
|
||||
#define mem2agpcpy(a,b,c) memcpy(a,b,c)
|
||||
#define fast_memcpy(a,b,c) memcpy(a,b,c)
|
||||
#endif
|
||||
|
||||
static inline void * mem2agpcpy_pic(void * dst, const void * src, int bytesPerLine, int height, int dstStride, int srcStride)
|
||||
{
|
||||
int i;
|
||||
void *retval=dst;
|
||||
|
||||
if(dstStride == srcStride)
|
||||
{
|
||||
if (srcStride < 0) {
|
||||
src = (uint8_t*)src + (height-1)*srcStride;
|
||||
dst = (uint8_t*)dst + (height-1)*dstStride;
|
||||
srcStride = -srcStride;
|
||||
}
|
||||
|
||||
mem2agpcpy(dst, src, srcStride*height);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0; i<height; i++)
|
||||
{
|
||||
mem2agpcpy(dst, src, bytesPerLine);
|
||||
src = (uint8_t*)src + srcStride;
|
||||
dst = (uint8_t*)dst + dstStride;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#define memcpy_pic(d, s, b, h, ds, ss) memcpy_pic2(d, s, b, h, ds, ss, 0)
|
||||
#define my_memcpy_pic(d, s, b, h, ds, ss) memcpy_pic2(d, s, b, h, ds, ss, 1)
|
||||
|
||||
/**
|
||||
* \param limit2width always skip data between end of line and start of next
|
||||
* instead of copying the full block when strides are the same
|
||||
*/
|
||||
static inline void * memcpy_pic2(void * dst, const void * src,
|
||||
int bytesPerLine, int height,
|
||||
int dstStride, int srcStride, int limit2width)
|
||||
{
|
||||
int i;
|
||||
void *retval=dst;
|
||||
|
||||
if(!limit2width && dstStride == srcStride)
|
||||
{
|
||||
if (srcStride < 0) {
|
||||
src = (uint8_t*)src + (height-1)*srcStride;
|
||||
dst = (uint8_t*)dst + (height-1)*dstStride;
|
||||
srcStride = -srcStride;
|
||||
}
|
||||
|
||||
fast_memcpy(dst, src, srcStride*height);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0; i<height; i++)
|
||||
{
|
||||
fast_memcpy(dst, src, bytesPerLine);
|
||||
src = (uint8_t*)src + srcStride;
|
||||
dst = (uint8_t*)dst + dstStride;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif /* MPLAYER_FASTMEMCPY_H */
|
||||
287
libavfilter/libmpcodecs/libvo/video_out.h
Normal file
287
libavfilter/libmpcodecs/libvo/video_out.h
Normal file
@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright (C) Aaron Holtzman - Aug 1999
|
||||
* Strongly modified, most parts rewritten: A'rpi/ESP-team - 2000-2001
|
||||
* (C) MPlayer developers
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_VIDEO_OUT_H
|
||||
#define MPLAYER_VIDEO_OUT_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
//#include "sub/font_load.h"
|
||||
#include "libmpcodecs/img_format.h"
|
||||
//#include "vidix/vidix.h"
|
||||
|
||||
#define VO_EVENT_EXPOSE 1
|
||||
#define VO_EVENT_RESIZE 2
|
||||
#define VO_EVENT_KEYPRESS 4
|
||||
#define VO_EVENT_REINIT 8
|
||||
#define VO_EVENT_MOVE 16
|
||||
|
||||
/* Obsolete: VOCTRL_QUERY_VAA 1 */
|
||||
/* does the device support the required format */
|
||||
#define VOCTRL_QUERY_FORMAT 2
|
||||
/* signal a device reset seek */
|
||||
#define VOCTRL_RESET 3
|
||||
/* true if vo driver can use GUI created windows */
|
||||
#define VOCTRL_GUISUPPORT 4
|
||||
#define VOCTRL_GUI_NOWINDOW 19
|
||||
/* used to switch to fullscreen */
|
||||
#define VOCTRL_FULLSCREEN 5
|
||||
/* signal a device pause */
|
||||
#define VOCTRL_PAUSE 7
|
||||
/* start/resume playback */
|
||||
#define VOCTRL_RESUME 8
|
||||
/* libmpcodecs direct rendering: */
|
||||
#define VOCTRL_GET_IMAGE 9
|
||||
#define VOCTRL_DRAW_IMAGE 13
|
||||
#define VOCTRL_SET_SPU_PALETTE 14
|
||||
/* decoding ahead: */
|
||||
#define VOCTRL_GET_NUM_FRAMES 10
|
||||
#define VOCTRL_GET_FRAME_NUM 11
|
||||
#define VOCTRL_SET_FRAME_NUM 12
|
||||
#define VOCTRL_GET_PANSCAN 15
|
||||
#define VOCTRL_SET_PANSCAN 16
|
||||
/* equalizer controls */
|
||||
#define VOCTRL_SET_EQUALIZER 17
|
||||
#define VOCTRL_GET_EQUALIZER 18
|
||||
//#define VOCTRL_GUI_NOWINDOW 19
|
||||
/* Frame duplication */
|
||||
#define VOCTRL_DUPLICATE_FRAME 20
|
||||
// ... 21
|
||||
#define VOCTRL_START_SLICE 21
|
||||
|
||||
#define VOCTRL_ONTOP 25
|
||||
#define VOCTRL_ROOTWIN 26
|
||||
#define VOCTRL_BORDER 27
|
||||
#define VOCTRL_DRAW_EOSD 28
|
||||
#define VOCTRL_GET_EOSD_RES 29
|
||||
|
||||
#define VOCTRL_SET_DEINTERLACE 30
|
||||
#define VOCTRL_GET_DEINTERLACE 31
|
||||
|
||||
#define VOCTRL_UPDATE_SCREENINFO 32
|
||||
|
||||
// Vo can be used by xover
|
||||
#define VOCTRL_XOVERLAY_SUPPORT 22
|
||||
|
||||
#define VOCTRL_XOVERLAY_SET_COLORKEY 24
|
||||
typedef struct {
|
||||
uint32_t x11; // The raw x11 color
|
||||
uint16_t r,g,b;
|
||||
} mp_colorkey_t;
|
||||
|
||||
#define VOCTRL_XOVERLAY_SET_WIN 23
|
||||
typedef struct {
|
||||
int x,y;
|
||||
int w,h;
|
||||
} mp_win_t;
|
||||
|
||||
#define VO_TRUE 1
|
||||
#define VO_FALSE 0
|
||||
#define VO_ERROR -1
|
||||
#define VO_NOTAVAIL -2
|
||||
#define VO_NOTIMPL -3
|
||||
|
||||
#define VOFLAG_FULLSCREEN 0x01
|
||||
#define VOFLAG_MODESWITCHING 0x02
|
||||
#define VOFLAG_SWSCALE 0x04
|
||||
#define VOFLAG_FLIPPING 0x08
|
||||
#define VOFLAG_HIDDEN 0x10 //< Use to create a hidden window
|
||||
#define VOFLAG_STEREO 0x20 //< Use to create a stereo-capable window
|
||||
#define VOFLAG_XOVERLAY_SUB_VO 0x10000
|
||||
|
||||
typedef struct vo_info_s
|
||||
{
|
||||
/* driver name ("Matrox Millennium G200/G400" */
|
||||
const char *name;
|
||||
/* short name (for config strings) ("mga") */
|
||||
const char *short_name;
|
||||
/* author ("Aaron Holtzman <aholtzma@ess.engr.uvic.ca>") */
|
||||
const char *author;
|
||||
/* any additional comments */
|
||||
const char *comment;
|
||||
} vo_info_t;
|
||||
|
||||
typedef struct vo_functions_s
|
||||
{
|
||||
const vo_info_t *info;
|
||||
/*
|
||||
* Preinitializes driver (real INITIALIZATION)
|
||||
* arg - currently it's vo_subdevice
|
||||
* returns: zero on successful initialization, non-zero on error.
|
||||
*/
|
||||
int (*preinit)(const char *arg);
|
||||
/*
|
||||
* Initialize (means CONFIGURE) the display driver.
|
||||
* params:
|
||||
* width,height: image source size
|
||||
* d_width,d_height: size of the requested window size, just a hint
|
||||
* fullscreen: flag, 0=windowd 1=fullscreen, just a hint
|
||||
* title: window title, if available
|
||||
* format: fourcc of pixel format
|
||||
* returns : zero on successful initialization, non-zero on error.
|
||||
*/
|
||||
int (*config)(uint32_t width, uint32_t height, uint32_t d_width,
|
||||
uint32_t d_height, uint32_t fullscreen, char *title,
|
||||
uint32_t format);
|
||||
|
||||
/*
|
||||
* Control interface
|
||||
*/
|
||||
int (*control)(uint32_t request, void *data, ...);
|
||||
|
||||
/*
|
||||
* Display a new RGB/BGR frame of the video to the screen.
|
||||
* params:
|
||||
* src[0] - pointer to the image
|
||||
*/
|
||||
int (*draw_frame)(uint8_t *src[]);
|
||||
|
||||
/*
|
||||
* Draw a planar YUV slice to the buffer:
|
||||
* params:
|
||||
* src[3] = source image planes (Y,U,V)
|
||||
* stride[3] = source image planes line widths (in bytes)
|
||||
* w,h = width*height of area to be copied (in Y pixels)
|
||||
* x,y = position at the destination image (in Y pixels)
|
||||
*/
|
||||
int (*draw_slice)(uint8_t *src[], int stride[], int w,int h, int x,int y);
|
||||
|
||||
/*
|
||||
* Draws OSD to the screen buffer
|
||||
*/
|
||||
void (*draw_osd)(void);
|
||||
|
||||
/*
|
||||
* Blit/Flip buffer to the screen. Must be called after each frame!
|
||||
*/
|
||||
void (*flip_page)(void);
|
||||
|
||||
/*
|
||||
* This func is called after every frames to handle keyboard and
|
||||
* other events. It's called in PAUSE mode too!
|
||||
*/
|
||||
void (*check_events)(void);
|
||||
|
||||
/*
|
||||
* Closes driver. Should restore the original state of the system.
|
||||
*/
|
||||
void (*uninit)(void);
|
||||
} vo_functions_t;
|
||||
|
||||
const vo_functions_t* init_best_video_out(char** vo_list);
|
||||
int config_video_out(const vo_functions_t *vo, uint32_t width, uint32_t height,
|
||||
uint32_t d_width, uint32_t d_height, uint32_t flags,
|
||||
char *title, uint32_t format);
|
||||
void list_video_out(void);
|
||||
|
||||
// NULL terminated array of all drivers
|
||||
extern const vo_functions_t* const video_out_drivers[];
|
||||
|
||||
extern int vo_flags;
|
||||
|
||||
extern int vo_config_count;
|
||||
|
||||
extern int xinerama_screen;
|
||||
extern int xinerama_x;
|
||||
extern int xinerama_y;
|
||||
|
||||
// correct resolution/bpp on screen: (should be autodetected by vo_init())
|
||||
extern int vo_depthonscreen;
|
||||
extern int vo_screenwidth;
|
||||
extern int vo_screenheight;
|
||||
|
||||
// requested resolution/bpp: (-x -y -bpp options)
|
||||
extern int vo_dx;
|
||||
extern int vo_dy;
|
||||
extern int vo_dwidth;
|
||||
extern int vo_dheight;
|
||||
extern int vo_dbpp;
|
||||
|
||||
extern int vo_grabpointer;
|
||||
extern int vo_doublebuffering;
|
||||
extern int vo_directrendering;
|
||||
extern int vo_vsync;
|
||||
extern int vo_fs;
|
||||
extern int vo_fsmode;
|
||||
extern float vo_panscan;
|
||||
extern int vo_adapter_num;
|
||||
extern int vo_refresh_rate;
|
||||
extern int vo_keepaspect;
|
||||
extern int vo_rootwin;
|
||||
extern int vo_ontop;
|
||||
extern int vo_border;
|
||||
|
||||
extern int vo_gamma_gamma;
|
||||
extern int vo_gamma_brightness;
|
||||
extern int vo_gamma_saturation;
|
||||
extern int vo_gamma_contrast;
|
||||
extern int vo_gamma_hue;
|
||||
extern int vo_gamma_red_intensity;
|
||||
extern int vo_gamma_green_intensity;
|
||||
extern int vo_gamma_blue_intensity;
|
||||
|
||||
extern int vo_nomouse_input;
|
||||
extern int enable_mouse_movements;
|
||||
|
||||
extern int vo_pts;
|
||||
extern float vo_fps;
|
||||
|
||||
extern char *vo_subdevice;
|
||||
|
||||
extern int vo_colorkey;
|
||||
|
||||
extern char *vo_winname;
|
||||
extern char *vo_wintitle;
|
||||
|
||||
extern int64_t WinID;
|
||||
|
||||
typedef struct {
|
||||
float min;
|
||||
float max;
|
||||
} range_t;
|
||||
|
||||
float range_max(range_t *r);
|
||||
int in_range(range_t *r, float f);
|
||||
range_t *str2range(char *s);
|
||||
extern char *monitor_hfreq_str;
|
||||
extern char *monitor_vfreq_str;
|
||||
extern char *monitor_dotclock_str;
|
||||
|
||||
struct mp_keymap {
|
||||
int from;
|
||||
int to;
|
||||
};
|
||||
int lookup_keymap_table(const struct mp_keymap *map, int key);
|
||||
struct vo_rect {
|
||||
int left, right, top, bottom, width, height;
|
||||
};
|
||||
void calc_src_dst_rects(int src_width, int src_height, struct vo_rect *src, struct vo_rect *dst,
|
||||
struct vo_rect *borders, const struct vo_rect *crop);
|
||||
void vo_mouse_movement(int posx, int posy);
|
||||
|
||||
static inline int aspect_scaling(void)
|
||||
{
|
||||
return vo_fs;
|
||||
}
|
||||
|
||||
#endif /* MPLAYER_VIDEO_OUT_H */
|
||||
200
libavfilter/libmpcodecs/mp_image.c
Normal file
200
libavfilter/libmpcodecs/mp_image.c
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include "libmpcodecs/img_format.h"
|
||||
#include "libmpcodecs/mp_image.h"
|
||||
|
||||
#include "libvo/fastmemcpy.h"
|
||||
#include "libavutil/mem.h"
|
||||
|
||||
void mp_image_alloc_planes(mp_image_t *mpi) {
|
||||
// IF09 - allocate space for 4. plane delta info - unused
|
||||
if (mpi->imgfmt == IMGFMT_IF09) {
|
||||
mpi->planes[0]=av_malloc(mpi->bpp*mpi->width*(mpi->height+2)/8+
|
||||
mpi->chroma_width*mpi->chroma_height);
|
||||
} else
|
||||
mpi->planes[0]=av_malloc(mpi->bpp*mpi->width*(mpi->height+2)/8);
|
||||
if (mpi->flags&MP_IMGFLAG_PLANAR) {
|
||||
int bpp = IMGFMT_IS_YUVP16(mpi->imgfmt)? 2 : 1;
|
||||
// YV12/I420/YVU9/IF09. feel free to add other planar formats here...
|
||||
mpi->stride[0]=mpi->stride[3]=bpp*mpi->width;
|
||||
if(mpi->num_planes > 2){
|
||||
mpi->stride[1]=mpi->stride[2]=bpp*mpi->chroma_width;
|
||||
if(mpi->flags&MP_IMGFLAG_SWAPPED){
|
||||
// I420/IYUV (Y,U,V)
|
||||
mpi->planes[1]=mpi->planes[0]+mpi->stride[0]*mpi->height;
|
||||
mpi->planes[2]=mpi->planes[1]+mpi->stride[1]*mpi->chroma_height;
|
||||
if (mpi->num_planes > 3)
|
||||
mpi->planes[3]=mpi->planes[2]+mpi->stride[2]*mpi->chroma_height;
|
||||
} else {
|
||||
// YV12,YVU9,IF09 (Y,V,U)
|
||||
mpi->planes[2]=mpi->planes[0]+mpi->stride[0]*mpi->height;
|
||||
mpi->planes[1]=mpi->planes[2]+mpi->stride[1]*mpi->chroma_height;
|
||||
if (mpi->num_planes > 3)
|
||||
mpi->planes[3]=mpi->planes[1]+mpi->stride[1]*mpi->chroma_height;
|
||||
}
|
||||
} else {
|
||||
// NV12/NV21
|
||||
mpi->stride[1]=mpi->chroma_width;
|
||||
mpi->planes[1]=mpi->planes[0]+mpi->stride[0]*mpi->height;
|
||||
}
|
||||
} else {
|
||||
mpi->stride[0]=mpi->width*mpi->bpp/8;
|
||||
if (mpi->flags & MP_IMGFLAG_RGB_PALETTE)
|
||||
mpi->planes[1] = av_malloc(1024);
|
||||
}
|
||||
mpi->flags|=MP_IMGFLAG_ALLOCATED;
|
||||
}
|
||||
|
||||
mp_image_t* alloc_mpi(int w, int h, unsigned long int fmt) {
|
||||
mp_image_t* mpi = new_mp_image(w,h);
|
||||
|
||||
mp_image_setfmt(mpi,fmt);
|
||||
mp_image_alloc_planes(mpi);
|
||||
|
||||
return mpi;
|
||||
}
|
||||
|
||||
void copy_mpi(mp_image_t *dmpi, mp_image_t *mpi) {
|
||||
if(mpi->flags&MP_IMGFLAG_PLANAR){
|
||||
memcpy_pic(dmpi->planes[0],mpi->planes[0], mpi->w, mpi->h,
|
||||
dmpi->stride[0],mpi->stride[0]);
|
||||
memcpy_pic(dmpi->planes[1],mpi->planes[1], mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[1],mpi->stride[1]);
|
||||
memcpy_pic(dmpi->planes[2], mpi->planes[2], mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[2],mpi->stride[2]);
|
||||
} else {
|
||||
memcpy_pic(dmpi->planes[0],mpi->planes[0],
|
||||
mpi->w*(dmpi->bpp/8), mpi->h,
|
||||
dmpi->stride[0],mpi->stride[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_image_setfmt(mp_image_t* mpi,unsigned int out_fmt){
|
||||
mpi->flags&=~(MP_IMGFLAG_PLANAR|MP_IMGFLAG_YUV|MP_IMGFLAG_SWAPPED);
|
||||
mpi->imgfmt=out_fmt;
|
||||
// compressed formats
|
||||
if(out_fmt == IMGFMT_MPEGPES ||
|
||||
out_fmt == IMGFMT_ZRMJPEGNI || out_fmt == IMGFMT_ZRMJPEGIT || out_fmt == IMGFMT_ZRMJPEGIB ||
|
||||
IMGFMT_IS_HWACCEL(out_fmt)){
|
||||
mpi->bpp=0;
|
||||
return;
|
||||
}
|
||||
mpi->num_planes=1;
|
||||
if (IMGFMT_IS_RGB(out_fmt)) {
|
||||
if (IMGFMT_RGB_DEPTH(out_fmt) < 8 && !(out_fmt&128))
|
||||
mpi->bpp = IMGFMT_RGB_DEPTH(out_fmt);
|
||||
else
|
||||
mpi->bpp=(IMGFMT_RGB_DEPTH(out_fmt)+7)&(~7);
|
||||
return;
|
||||
}
|
||||
if (IMGFMT_IS_BGR(out_fmt)) {
|
||||
if (IMGFMT_BGR_DEPTH(out_fmt) < 8 && !(out_fmt&128))
|
||||
mpi->bpp = IMGFMT_BGR_DEPTH(out_fmt);
|
||||
else
|
||||
mpi->bpp=(IMGFMT_BGR_DEPTH(out_fmt)+7)&(~7);
|
||||
mpi->flags|=MP_IMGFLAG_SWAPPED;
|
||||
return;
|
||||
}
|
||||
mpi->flags|=MP_IMGFLAG_YUV;
|
||||
mpi->num_planes=3;
|
||||
if (mp_get_chroma_shift(out_fmt, NULL, NULL)) {
|
||||
mpi->flags|=MP_IMGFLAG_PLANAR;
|
||||
mpi->bpp = mp_get_chroma_shift(out_fmt, &mpi->chroma_x_shift, &mpi->chroma_y_shift);
|
||||
mpi->chroma_width = mpi->width >> mpi->chroma_x_shift;
|
||||
mpi->chroma_height = mpi->height >> mpi->chroma_y_shift;
|
||||
}
|
||||
switch(out_fmt){
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
mpi->flags|=MP_IMGFLAG_SWAPPED;
|
||||
case IMGFMT_YV12:
|
||||
return;
|
||||
case IMGFMT_420A:
|
||||
case IMGFMT_IF09:
|
||||
mpi->num_planes=4;
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
case IMGFMT_440P:
|
||||
case IMGFMT_444P16_LE:
|
||||
case IMGFMT_444P16_BE:
|
||||
case IMGFMT_422P16_LE:
|
||||
case IMGFMT_422P16_BE:
|
||||
case IMGFMT_420P16_LE:
|
||||
case IMGFMT_420P16_BE:
|
||||
return;
|
||||
case IMGFMT_Y800:
|
||||
case IMGFMT_Y8:
|
||||
/* they're planar ones, but for easier handling use them as packed */
|
||||
mpi->flags&=~MP_IMGFLAG_PLANAR;
|
||||
mpi->num_planes=1;
|
||||
return;
|
||||
case IMGFMT_UYVY:
|
||||
mpi->flags|=MP_IMGFLAG_SWAPPED;
|
||||
case IMGFMT_YUY2:
|
||||
mpi->bpp=16;
|
||||
mpi->num_planes=1;
|
||||
return;
|
||||
case IMGFMT_NV12:
|
||||
mpi->flags|=MP_IMGFLAG_SWAPPED;
|
||||
case IMGFMT_NV21:
|
||||
mpi->flags|=MP_IMGFLAG_PLANAR;
|
||||
mpi->bpp=12;
|
||||
mpi->num_planes=2;
|
||||
mpi->chroma_width=(mpi->width>>0);
|
||||
mpi->chroma_height=(mpi->height>>1);
|
||||
mpi->chroma_x_shift=0;
|
||||
mpi->chroma_y_shift=1;
|
||||
return;
|
||||
}
|
||||
mp_msg(MSGT_DECVIDEO,MSGL_WARN,"mp_image: unknown out_fmt: 0x%X\n",out_fmt);
|
||||
mpi->bpp=0;
|
||||
}
|
||||
|
||||
mp_image_t* new_mp_image(int w,int h){
|
||||
mp_image_t* mpi = malloc(sizeof(mp_image_t));
|
||||
if(!mpi) return NULL; // error!
|
||||
memset(mpi,0,sizeof(mp_image_t));
|
||||
mpi->width=mpi->w=w;
|
||||
mpi->height=mpi->h=h;
|
||||
return mpi;
|
||||
}
|
||||
|
||||
void free_mp_image(mp_image_t* mpi){
|
||||
if(!mpi) return;
|
||||
if(mpi->flags&MP_IMGFLAG_ALLOCATED){
|
||||
/* becouse we allocate the whole image in once */
|
||||
av_free(mpi->planes[0]);
|
||||
if (mpi->flags & MP_IMGFLAG_RGB_PALETTE)
|
||||
av_free(mpi->planes[1]);
|
||||
}
|
||||
free(mpi);
|
||||
}
|
||||
|
||||
137
libavfilter/libmpcodecs/mp_image.h
Normal file
137
libavfilter/libmpcodecs/mp_image.h
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_MP_IMAGE_H
|
||||
#define MPLAYER_MP_IMAGE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "mp_msg.h"
|
||||
|
||||
//--------- codec's requirements (filled by the codec/vf) ---------
|
||||
|
||||
//--- buffer content restrictions:
|
||||
// set if buffer content shouldn't be modified:
|
||||
#define MP_IMGFLAG_PRESERVE 0x01
|
||||
// set if buffer content will be READ for next frame's MC: (I/P mpeg frames)
|
||||
#define MP_IMGFLAG_READABLE 0x02
|
||||
|
||||
//--- buffer width/stride/plane restrictions: (used for direct rendering)
|
||||
// stride _have_to_ be aligned to MB boundary: [for DR restrictions]
|
||||
#define MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE 0x4
|
||||
// stride should be aligned to MB boundary: [for buffer allocation]
|
||||
#define MP_IMGFLAG_PREFER_ALIGNED_STRIDE 0x8
|
||||
// codec accept any stride (>=width):
|
||||
#define MP_IMGFLAG_ACCEPT_STRIDE 0x10
|
||||
// codec accept any width (width*bpp=stride -> stride%bpp==0) (>=width):
|
||||
#define MP_IMGFLAG_ACCEPT_WIDTH 0x20
|
||||
//--- for planar formats only:
|
||||
// uses only stride[0], and stride[1]=stride[2]=stride[0]>>mpi->chroma_x_shift
|
||||
#define MP_IMGFLAG_COMMON_STRIDE 0x40
|
||||
// uses only planes[0], and calculates planes[1,2] from width,height,imgfmt
|
||||
#define MP_IMGFLAG_COMMON_PLANE 0x80
|
||||
|
||||
#define MP_IMGFLAGMASK_RESTRICTIONS 0xFF
|
||||
|
||||
//--------- color info (filled by mp_image_setfmt() ) -----------
|
||||
// set if number of planes > 1
|
||||
#define MP_IMGFLAG_PLANAR 0x100
|
||||
// set if it's YUV colorspace
|
||||
#define MP_IMGFLAG_YUV 0x200
|
||||
// set if it's swapped (BGR or YVU) plane/byteorder
|
||||
#define MP_IMGFLAG_SWAPPED 0x400
|
||||
// set if you want memory for palette allocated and managed by vf_get_image etc.
|
||||
#define MP_IMGFLAG_RGB_PALETTE 0x800
|
||||
|
||||
#define MP_IMGFLAGMASK_COLORS 0xF00
|
||||
|
||||
// codec uses drawing/rendering callbacks (draw_slice()-like thing, DR method 2)
|
||||
// [the codec will set this flag if it supports callbacks, and the vo _may_
|
||||
// clear it in get_image() if draw_slice() not implemented]
|
||||
#define MP_IMGFLAG_DRAW_CALLBACK 0x1000
|
||||
// set if it's in video buffer/memory: [set by vo/vf's get_image() !!!]
|
||||
#define MP_IMGFLAG_DIRECT 0x2000
|
||||
// set if buffer is allocated (used in destination images):
|
||||
#define MP_IMGFLAG_ALLOCATED 0x4000
|
||||
|
||||
// buffer type was printed (do NOT set this flag - it's for INTERNAL USE!!!)
|
||||
#define MP_IMGFLAG_TYPE_DISPLAYED 0x8000
|
||||
|
||||
// codec doesn't support any form of direct rendering - it has own buffer
|
||||
// allocation. so we just export its buffer pointers:
|
||||
#define MP_IMGTYPE_EXPORT 0
|
||||
// codec requires a static WO buffer, but it does only partial updates later:
|
||||
#define MP_IMGTYPE_STATIC 1
|
||||
// codec just needs some WO memory, where it writes/copies the whole frame to:
|
||||
#define MP_IMGTYPE_TEMP 2
|
||||
// I+P type, requires 2+ independent static R/W buffers
|
||||
#define MP_IMGTYPE_IP 3
|
||||
// I+P+B type, requires 2+ independent static R/W and 1+ temp WO buffers
|
||||
#define MP_IMGTYPE_IPB 4
|
||||
// Upper 16 bits give desired buffer number, -1 means get next available
|
||||
#define MP_IMGTYPE_NUMBERED 5
|
||||
// Doesn't need any buffer, incomplete image (probably a first field only)
|
||||
// we need this type to be able to differentiate between half frames and
|
||||
// all other cases
|
||||
#define MP_IMGTYPE_INCOMPLETE 6
|
||||
|
||||
#define MP_MAX_PLANES 4
|
||||
|
||||
#define MP_IMGFIELD_ORDERED 0x01
|
||||
#define MP_IMGFIELD_TOP_FIRST 0x02
|
||||
#define MP_IMGFIELD_REPEAT_FIRST 0x04
|
||||
#define MP_IMGFIELD_TOP 0x08
|
||||
#define MP_IMGFIELD_BOTTOM 0x10
|
||||
#define MP_IMGFIELD_INTERLACED 0x20
|
||||
|
||||
typedef struct mp_image {
|
||||
unsigned int flags;
|
||||
unsigned char type;
|
||||
int number;
|
||||
unsigned char bpp; // bits/pixel. NOT depth! for RGB it will be n*8
|
||||
unsigned int imgfmt;
|
||||
int width,height; // stored dimensions
|
||||
int x,y,w,h; // visible dimensions
|
||||
unsigned char* planes[MP_MAX_PLANES];
|
||||
int stride[MP_MAX_PLANES];
|
||||
char * qscale;
|
||||
int qstride;
|
||||
int pict_type; // 0->unknown, 1->I, 2->P, 3->B
|
||||
int fields;
|
||||
int qscale_type; // 0->mpeg1/4/h263, 1->mpeg2
|
||||
int num_planes;
|
||||
/* these are only used by planar formats Y,U(Cb),V(Cr) */
|
||||
int chroma_width;
|
||||
int chroma_height;
|
||||
int chroma_x_shift; // horizontal
|
||||
int chroma_y_shift; // vertical
|
||||
int usage_count;
|
||||
/* for private use by filter or vo driver (to store buffer id or dmpi) */
|
||||
void* priv;
|
||||
} mp_image_t;
|
||||
|
||||
void mp_image_setfmt(mp_image_t* mpi,unsigned int out_fmt);
|
||||
mp_image_t* new_mp_image(int w,int h);
|
||||
void free_mp_image(mp_image_t* mpi);
|
||||
|
||||
mp_image_t* alloc_mpi(int w, int h, unsigned long int fmt);
|
||||
void mp_image_alloc_planes(mp_image_t *mpi);
|
||||
void copy_mpi(mp_image_t *dmpi, mp_image_t *mpi);
|
||||
|
||||
#endif /* MPLAYER_MP_IMAGE_H */
|
||||
164
libavfilter/libmpcodecs/mp_msg.h
Normal file
164
libavfilter/libmpcodecs/mp_msg.h
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_MP_MSG_H
|
||||
#define MPLAYER_MP_MSG_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
// defined in mplayer.c and mencoder.c
|
||||
extern int verbose;
|
||||
|
||||
// verbosity elevel:
|
||||
|
||||
/* Only messages level MSGL_FATAL-MSGL_STATUS should be translated,
|
||||
* messages level MSGL_V and above should not be translated. */
|
||||
|
||||
#define MSGL_FATAL 0 // will exit/abort
|
||||
#define MSGL_ERR 1 // continues
|
||||
#define MSGL_WARN 2 // only warning
|
||||
#define MSGL_HINT 3 // short help message
|
||||
#define MSGL_INFO 4 // -quiet
|
||||
#define MSGL_STATUS 5 // v=0
|
||||
#define MSGL_V 6 // v=1
|
||||
#define MSGL_DBG2 7 // v=2
|
||||
#define MSGL_DBG3 8 // v=3
|
||||
#define MSGL_DBG4 9 // v=4
|
||||
#define MSGL_DBG5 10 // v=5
|
||||
|
||||
#define MSGL_FIXME 1 // for conversions from printf where the appropriate MSGL is not known; set equal to ERR for obtrusiveness
|
||||
#define MSGT_FIXME 0 // for conversions from printf where the appropriate MSGT is not known; set equal to GLOBAL for obtrusiveness
|
||||
|
||||
// code/module:
|
||||
|
||||
#define MSGT_GLOBAL 0 // common player stuff errors
|
||||
#define MSGT_CPLAYER 1 // console player (mplayer.c)
|
||||
#define MSGT_GPLAYER 2 // gui player
|
||||
|
||||
#define MSGT_VO 3 // libvo
|
||||
#define MSGT_AO 4 // libao
|
||||
|
||||
#define MSGT_DEMUXER 5 // demuxer.c (general stuff)
|
||||
#define MSGT_DS 6 // demux stream (add/read packet etc)
|
||||
#define MSGT_DEMUX 7 // fileformat-specific stuff (demux_*.c)
|
||||
#define MSGT_HEADER 8 // fileformat-specific header (*header.c)
|
||||
|
||||
#define MSGT_AVSYNC 9 // mplayer.c timer stuff
|
||||
#define MSGT_AUTOQ 10 // mplayer.c auto-quality stuff
|
||||
|
||||
#define MSGT_CFGPARSER 11 // cfgparser.c
|
||||
|
||||
#define MSGT_DECAUDIO 12 // av decoder
|
||||
#define MSGT_DECVIDEO 13
|
||||
|
||||
#define MSGT_SEEK 14 // seeking code
|
||||
#define MSGT_WIN32 15 // win32 dll stuff
|
||||
#define MSGT_OPEN 16 // open.c (stream opening)
|
||||
#define MSGT_DVD 17 // open.c (DVD init/read/seek)
|
||||
|
||||
#define MSGT_PARSEES 18 // parse_es.c (mpeg stream parser)
|
||||
#define MSGT_LIRC 19 // lirc_mp.c and input lirc driver
|
||||
|
||||
#define MSGT_STREAM 20 // stream.c
|
||||
#define MSGT_CACHE 21 // cache2.c
|
||||
|
||||
#define MSGT_MENCODER 22
|
||||
|
||||
#define MSGT_XACODEC 23 // XAnim codecs
|
||||
|
||||
#define MSGT_TV 24 // TV input subsystem
|
||||
|
||||
#define MSGT_OSDEP 25 // OS-dependent parts
|
||||
|
||||
#define MSGT_SPUDEC 26 // spudec.c
|
||||
|
||||
#define MSGT_PLAYTREE 27 // Playtree handeling (playtree.c, playtreeparser.c)
|
||||
|
||||
#define MSGT_INPUT 28
|
||||
|
||||
#define MSGT_VFILTER 29
|
||||
|
||||
#define MSGT_OSD 30
|
||||
|
||||
#define MSGT_NETWORK 31
|
||||
|
||||
#define MSGT_CPUDETECT 32
|
||||
|
||||
#define MSGT_CODECCFG 33
|
||||
|
||||
#define MSGT_SWS 34
|
||||
|
||||
#define MSGT_VOBSUB 35
|
||||
#define MSGT_SUBREADER 36
|
||||
|
||||
#define MSGT_AFILTER 37 // Audio filter messages
|
||||
|
||||
#define MSGT_NETST 38 // Netstream
|
||||
|
||||
#define MSGT_MUXER 39 // muxer layer
|
||||
|
||||
#define MSGT_OSD_MENU 40
|
||||
|
||||
#define MSGT_IDENTIFY 41 // -identify output
|
||||
|
||||
#define MSGT_RADIO 42
|
||||
|
||||
#define MSGT_ASS 43 // libass messages
|
||||
|
||||
#define MSGT_LOADER 44 // dll loader messages
|
||||
|
||||
#define MSGT_STATUSLINE 45 // playback/encoding status line
|
||||
|
||||
#define MSGT_TELETEXT 46 // Teletext decoder
|
||||
|
||||
#define MSGT_MAX 64
|
||||
|
||||
|
||||
extern char *mp_msg_charset;
|
||||
extern int mp_msg_color;
|
||||
extern int mp_msg_module;
|
||||
|
||||
extern int mp_msg_levels[MSGT_MAX];
|
||||
extern int mp_msg_level_all;
|
||||
|
||||
|
||||
void mp_msg_init(void);
|
||||
int mp_msg_test(int mod, int lev);
|
||||
|
||||
#include "config.h"
|
||||
|
||||
void mp_msg_va(int mod, int lev, const char *format, va_list va);
|
||||
#ifdef __GNUC__
|
||||
void mp_msg(int mod, int lev, const char *format, ... ) __attribute__ ((format (printf, 3, 4)));
|
||||
# ifdef MP_DEBUG
|
||||
# define mp_dbg(mod,lev, args... ) mp_msg(mod, lev, ## args )
|
||||
# else
|
||||
# define mp_dbg(mod,lev, args... ) /* only useful for developers */
|
||||
# endif
|
||||
#else // not GNU C
|
||||
void mp_msg(int mod, int lev, const char *format, ... );
|
||||
# ifdef MP_DEBUG
|
||||
# define mp_dbg(mod,lev, ... ) mp_msg(mod, lev, __VA_ARGS__)
|
||||
# else
|
||||
# define mp_dbg(mod,lev, ... ) /* only useful for developers */
|
||||
# endif
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
const char* filename_recode(const char* filename);
|
||||
|
||||
#endif /* MPLAYER_MP_MSG_H */
|
||||
38
libavfilter/libmpcodecs/mpbswap.h
Normal file
38
libavfilter/libmpcodecs/mpbswap.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_MPBSWAP_H
|
||||
#define MPLAYER_MPBSWAP_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "config.h"
|
||||
#include "libavutil/bswap.h"
|
||||
|
||||
#define bswap_16(v) av_bswap16(v)
|
||||
#define bswap_32(v) av_bswap32(v)
|
||||
#define le2me_16(v) av_le2ne16(v)
|
||||
#define le2me_32(v) av_le2ne32(v)
|
||||
#define le2me_64(v) av_le2ne64(v)
|
||||
#define be2me_16(v) av_be2ne16(v)
|
||||
#define be2me_32(v) av_be2ne32(v)
|
||||
|
||||
#ifndef HAVE_SWAB
|
||||
void swab(const void *from, void *to, ssize_t n);
|
||||
#endif
|
||||
|
||||
#endif /* MPLAYER_MPBSWAP_H */
|
||||
43
libavfilter/libmpcodecs/mpc_info.h
Normal file
43
libavfilter/libmpcodecs/mpc_info.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_MPC_INFO_H
|
||||
#define MPLAYER_MPC_INFO_H
|
||||
|
||||
typedef struct mp_codec_info_s
|
||||
{
|
||||
/* codec long name ("Autodesk FLI/FLC Animation decoder" */
|
||||
const char *name;
|
||||
/* short name (same as driver name in codecs.conf) ("dshow") */
|
||||
const char *short_name;
|
||||
/* interface author/maintainer */
|
||||
const char *maintainer;
|
||||
/* codec author ("Aaron Holtzman <aholtzma@ess.engr.uvic.ca>") */
|
||||
const char *author;
|
||||
/* any additional comments */
|
||||
const char *comment;
|
||||
} mp_codec_info_t;
|
||||
|
||||
#define CONTROL_OK 1
|
||||
#define CONTROL_TRUE 1
|
||||
#define CONTROL_FALSE 0
|
||||
#define CONTROL_UNKNOWN -1
|
||||
#define CONTROL_ERROR -2
|
||||
#define CONTROL_NA -3
|
||||
|
||||
#endif /* MPLAYER_MPC_INFO_H */
|
||||
822
libavfilter/libmpcodecs/pullup.c
Normal file
822
libavfilter/libmpcodecs/pullup.c
Normal file
@ -0,0 +1,822 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "config.h"
|
||||
#include "pullup.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
|
||||
|
||||
#if ARCH_X86
|
||||
#if HAVE_MMX
|
||||
static int diff_y_mmx(unsigned char *a, unsigned char *b, int s)
|
||||
{
|
||||
int ret;
|
||||
__asm__ volatile (
|
||||
"movl $4, %%ecx \n\t"
|
||||
"pxor %%mm4, %%mm4 \n\t"
|
||||
"pxor %%mm7, %%mm7 \n\t"
|
||||
|
||||
"1: \n\t"
|
||||
|
||||
"movq (%%"REG_S"), %%mm0 \n\t"
|
||||
"movq (%%"REG_S"), %%mm2 \n\t"
|
||||
"add %%"REG_a", %%"REG_S" \n\t"
|
||||
"movq (%%"REG_D"), %%mm1 \n\t"
|
||||
"add %%"REG_a", %%"REG_D" \n\t"
|
||||
"psubusb %%mm1, %%mm2 \n\t"
|
||||
"psubusb %%mm0, %%mm1 \n\t"
|
||||
"movq %%mm2, %%mm0 \n\t"
|
||||
"movq %%mm1, %%mm3 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpcklbw %%mm7, %%mm1 \n\t"
|
||||
"punpckhbw %%mm7, %%mm2 \n\t"
|
||||
"punpckhbw %%mm7, %%mm3 \n\t"
|
||||
"paddw %%mm0, %%mm4 \n\t"
|
||||
"paddw %%mm1, %%mm4 \n\t"
|
||||
"paddw %%mm2, %%mm4 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
|
||||
"decl %%ecx \n\t"
|
||||
"jnz 1b \n\t"
|
||||
|
||||
"movq %%mm4, %%mm3 \n\t"
|
||||
"punpcklwd %%mm7, %%mm4 \n\t"
|
||||
"punpckhwd %%mm7, %%mm3 \n\t"
|
||||
"paddd %%mm4, %%mm3 \n\t"
|
||||
"movd %%mm3, %%eax \n\t"
|
||||
"psrlq $32, %%mm3 \n\t"
|
||||
"movd %%mm3, %%edx \n\t"
|
||||
"addl %%edx, %%eax \n\t"
|
||||
"emms \n\t"
|
||||
: "=a" (ret)
|
||||
: "S" (a), "D" (b), "a" (s)
|
||||
: "%ecx", "%edx"
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int licomb_y_mmx(unsigned char *a, unsigned char *b, int s)
|
||||
{
|
||||
int ret;
|
||||
__asm__ volatile (
|
||||
"movl $4, %%ecx \n\t"
|
||||
"pxor %%mm6, %%mm6 \n\t"
|
||||
"pxor %%mm7, %%mm7 \n\t"
|
||||
"sub %%"REG_a", %%"REG_D" \n\t"
|
||||
|
||||
"2: \n\t"
|
||||
|
||||
"movq (%%"REG_D"), %%mm0 \n\t"
|
||||
"movq (%%"REG_D"), %%mm1 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"movq (%%"REG_D",%%"REG_a"), %%mm2 \n\t"
|
||||
"punpcklbw %%mm7, %%mm1 \n\t"
|
||||
"punpcklbw %%mm7, %%mm2 \n\t"
|
||||
"paddw %%mm0, %%mm0 \n\t"
|
||||
"paddw %%mm2, %%mm1 \n\t"
|
||||
"movq %%mm0, %%mm2 \n\t"
|
||||
"psubusw %%mm1, %%mm0 \n\t"
|
||||
"psubusw %%mm2, %%mm1 \n\t"
|
||||
"paddw %%mm0, %%mm6 \n\t"
|
||||
"paddw %%mm1, %%mm6 \n\t"
|
||||
|
||||
"movq (%%"REG_S"), %%mm0 \n\t"
|
||||
"movq (%%"REG_D"), %%mm1 \n\t"
|
||||
"punpckhbw %%mm7, %%mm0 \n\t"
|
||||
"movq (%%"REG_D",%%"REG_a"), %%mm2 \n\t"
|
||||
"punpckhbw %%mm7, %%mm1 \n\t"
|
||||
"punpckhbw %%mm7, %%mm2 \n\t"
|
||||
"paddw %%mm0, %%mm0 \n\t"
|
||||
"paddw %%mm2, %%mm1 \n\t"
|
||||
"movq %%mm0, %%mm2 \n\t"
|
||||
"psubusw %%mm1, %%mm0 \n\t"
|
||||
"psubusw %%mm2, %%mm1 \n\t"
|
||||
"paddw %%mm0, %%mm6 \n\t"
|
||||
"paddw %%mm1, %%mm6 \n\t"
|
||||
|
||||
"movq (%%"REG_D",%%"REG_a"), %%mm0 \n\t"
|
||||
"movq (%%"REG_S"), %%mm1 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"movq (%%"REG_S",%%"REG_a"), %%mm2 \n\t"
|
||||
"punpcklbw %%mm7, %%mm1 \n\t"
|
||||
"punpcklbw %%mm7, %%mm2 \n\t"
|
||||
"paddw %%mm0, %%mm0 \n\t"
|
||||
"paddw %%mm2, %%mm1 \n\t"
|
||||
"movq %%mm0, %%mm2 \n\t"
|
||||
"psubusw %%mm1, %%mm0 \n\t"
|
||||
"psubusw %%mm2, %%mm1 \n\t"
|
||||
"paddw %%mm0, %%mm6 \n\t"
|
||||
"paddw %%mm1, %%mm6 \n\t"
|
||||
|
||||
"movq (%%"REG_D",%%"REG_a"), %%mm0 \n\t"
|
||||
"movq (%%"REG_S"), %%mm1 \n\t"
|
||||
"punpckhbw %%mm7, %%mm0 \n\t"
|
||||
"movq (%%"REG_S",%%"REG_a"), %%mm2 \n\t"
|
||||
"punpckhbw %%mm7, %%mm1 \n\t"
|
||||
"punpckhbw %%mm7, %%mm2 \n\t"
|
||||
"paddw %%mm0, %%mm0 \n\t"
|
||||
"paddw %%mm2, %%mm1 \n\t"
|
||||
"movq %%mm0, %%mm2 \n\t"
|
||||
"psubusw %%mm1, %%mm0 \n\t"
|
||||
"psubusw %%mm2, %%mm1 \n\t"
|
||||
"paddw %%mm0, %%mm6 \n\t"
|
||||
"paddw %%mm1, %%mm6 \n\t"
|
||||
|
||||
"add %%"REG_a", %%"REG_S" \n\t"
|
||||
"add %%"REG_a", %%"REG_D" \n\t"
|
||||
"decl %%ecx \n\t"
|
||||
"jnz 2b \n\t"
|
||||
|
||||
"movq %%mm6, %%mm5 \n\t"
|
||||
"punpcklwd %%mm7, %%mm6 \n\t"
|
||||
"punpckhwd %%mm7, %%mm5 \n\t"
|
||||
"paddd %%mm6, %%mm5 \n\t"
|
||||
"movd %%mm5, %%eax \n\t"
|
||||
"psrlq $32, %%mm5 \n\t"
|
||||
"movd %%mm5, %%edx \n\t"
|
||||
"addl %%edx, %%eax \n\t"
|
||||
|
||||
"emms \n\t"
|
||||
: "=a" (ret)
|
||||
: "S" (a), "D" (b), "a" (s)
|
||||
: "%ecx", "%edx"
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int var_y_mmx(unsigned char *a, unsigned char *b, int s)
|
||||
{
|
||||
int ret;
|
||||
__asm__ volatile (
|
||||
"movl $3, %%ecx \n\t"
|
||||
"pxor %%mm4, %%mm4 \n\t"
|
||||
"pxor %%mm7, %%mm7 \n\t"
|
||||
|
||||
"1: \n\t"
|
||||
|
||||
"movq (%%"REG_S"), %%mm0 \n\t"
|
||||
"movq (%%"REG_S"), %%mm2 \n\t"
|
||||
"movq (%%"REG_S",%%"REG_a"), %%mm1 \n\t"
|
||||
"add %%"REG_a", %%"REG_S" \n\t"
|
||||
"psubusb %%mm1, %%mm2 \n\t"
|
||||
"psubusb %%mm0, %%mm1 \n\t"
|
||||
"movq %%mm2, %%mm0 \n\t"
|
||||
"movq %%mm1, %%mm3 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpcklbw %%mm7, %%mm1 \n\t"
|
||||
"punpckhbw %%mm7, %%mm2 \n\t"
|
||||
"punpckhbw %%mm7, %%mm3 \n\t"
|
||||
"paddw %%mm0, %%mm4 \n\t"
|
||||
"paddw %%mm1, %%mm4 \n\t"
|
||||
"paddw %%mm2, %%mm4 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
|
||||
"decl %%ecx \n\t"
|
||||
"jnz 1b \n\t"
|
||||
|
||||
"movq %%mm4, %%mm3 \n\t"
|
||||
"punpcklwd %%mm7, %%mm4 \n\t"
|
||||
"punpckhwd %%mm7, %%mm3 \n\t"
|
||||
"paddd %%mm4, %%mm3 \n\t"
|
||||
"movd %%mm3, %%eax \n\t"
|
||||
"psrlq $32, %%mm3 \n\t"
|
||||
"movd %%mm3, %%edx \n\t"
|
||||
"addl %%edx, %%eax \n\t"
|
||||
"emms \n\t"
|
||||
: "=a" (ret)
|
||||
: "S" (a), "a" (s)
|
||||
: "%ecx", "%edx"
|
||||
);
|
||||
return 4*ret;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define ABS(a) (((a)^((a)>>31))-((a)>>31))
|
||||
|
||||
static int diff_y(unsigned char *a, unsigned char *b, int s)
|
||||
{
|
||||
int i, j, diff=0;
|
||||
for (i=4; i; i--) {
|
||||
for (j=0; j<8; j++) diff += ABS(a[j]-b[j]);
|
||||
a+=s; b+=s;
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
static int licomb_y(unsigned char *a, unsigned char *b, int s)
|
||||
{
|
||||
int i, j, diff=0;
|
||||
for (i=4; i; i--) {
|
||||
for (j=0; j<8; j++)
|
||||
diff += ABS((a[j]<<1) - b[j-s] - b[j])
|
||||
+ ABS((b[j]<<1) - a[j] - a[j+s]);
|
||||
a+=s; b+=s;
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int qpcomb_y(unsigned char *a, unsigned char *b, int s)
|
||||
{
|
||||
int i, j, diff=0;
|
||||
for (i=4; i; i--) {
|
||||
for (j=0; j<8; j++)
|
||||
diff += ABS(a[j] - 3*b[j-s] + 3*a[j+s] - b[j]);
|
||||
a+=s; b+=s;
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
static int licomb_y_test(unsigned char *a, unsigned char *b, int s)
|
||||
{
|
||||
int c = licomb_y(a,b,s);
|
||||
int m = licomb_y_mmx(a,b,s);
|
||||
if (c != m) printf("%d != %d\n", c, m);
|
||||
return m;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int var_y(unsigned char *a, unsigned char *b, int s)
|
||||
{
|
||||
int i, j, var=0;
|
||||
for (i=3; i; i--) {
|
||||
for (j=0; j<8; j++) {
|
||||
var += ABS(a[j]-a[j+s]);
|
||||
}
|
||||
a+=s; b+=s;
|
||||
}
|
||||
return 4*var; /* match comb scaling */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void alloc_buffer(struct pullup_context *c, struct pullup_buffer *b)
|
||||
{
|
||||
int i;
|
||||
if (b->planes) return;
|
||||
b->planes = calloc(c->nplanes, sizeof(unsigned char *));
|
||||
for (i = 0; i < c->nplanes; i++) {
|
||||
b->planes[i] = malloc(c->h[i]*c->stride[i]);
|
||||
/* Deal with idiotic 128=0 for chroma: */
|
||||
memset(b->planes[i], c->background[i], c->h[i]*c->stride[i]);
|
||||
}
|
||||
}
|
||||
|
||||
struct pullup_buffer *pullup_lock_buffer(struct pullup_buffer *b, int parity)
|
||||
{
|
||||
if (!b) return 0;
|
||||
if ((parity+1) & 1) b->lock[0]++;
|
||||
if ((parity+1) & 2) b->lock[1]++;
|
||||
return b;
|
||||
}
|
||||
|
||||
void pullup_release_buffer(struct pullup_buffer *b, int parity)
|
||||
{
|
||||
if (!b) return;
|
||||
if ((parity+1) & 1) b->lock[0]--;
|
||||
if ((parity+1) & 2) b->lock[1]--;
|
||||
}
|
||||
|
||||
struct pullup_buffer *pullup_get_buffer(struct pullup_context *c, int parity)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Try first to get the sister buffer for the previous field */
|
||||
if (parity < 2 && c->last && parity != c->last->parity
|
||||
&& !c->last->buffer->lock[parity]) {
|
||||
alloc_buffer(c, c->last->buffer);
|
||||
return pullup_lock_buffer(c->last->buffer, parity);
|
||||
}
|
||||
|
||||
/* Prefer a buffer with both fields open */
|
||||
for (i = 0; i < c->nbuffers; i++) {
|
||||
if (c->buffers[i].lock[0]) continue;
|
||||
if (c->buffers[i].lock[1]) continue;
|
||||
alloc_buffer(c, &c->buffers[i]);
|
||||
return pullup_lock_buffer(&c->buffers[i], parity);
|
||||
}
|
||||
|
||||
if (parity == 2) return 0;
|
||||
|
||||
/* Search for any half-free buffer */
|
||||
for (i = 0; i < c->nbuffers; i++) {
|
||||
if (((parity+1) & 1) && c->buffers[i].lock[0]) continue;
|
||||
if (((parity+1) & 2) && c->buffers[i].lock[1]) continue;
|
||||
alloc_buffer(c, &c->buffers[i]);
|
||||
return pullup_lock_buffer(&c->buffers[i], parity);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void compute_metric(struct pullup_context *c,
|
||||
struct pullup_field *fa, int pa,
|
||||
struct pullup_field *fb, int pb,
|
||||
int (*func)(unsigned char *, unsigned char *, int), int *dest)
|
||||
{
|
||||
unsigned char *a, *b;
|
||||
int x, y;
|
||||
int mp = c->metric_plane;
|
||||
int xstep = c->bpp[mp];
|
||||
int ystep = c->stride[mp]<<3;
|
||||
int s = c->stride[mp]<<1; /* field stride */
|
||||
int w = c->metric_w*xstep;
|
||||
|
||||
if (!fa->buffer || !fb->buffer) return;
|
||||
|
||||
/* Shortcut for duplicate fields (e.g. from RFF flag) */
|
||||
if (fa->buffer == fb->buffer && pa == pb) {
|
||||
memset(dest, 0, c->metric_len * sizeof(int));
|
||||
return;
|
||||
}
|
||||
|
||||
a = fa->buffer->planes[mp] + pa * c->stride[mp] + c->metric_offset;
|
||||
b = fb->buffer->planes[mp] + pb * c->stride[mp] + c->metric_offset;
|
||||
|
||||
for (y = c->metric_h; y; y--) {
|
||||
for (x = 0; x < w; x += xstep) {
|
||||
*dest++ = func(a + x, b + x, s);
|
||||
}
|
||||
a += ystep; b += ystep;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void alloc_metrics(struct pullup_context *c, struct pullup_field *f)
|
||||
{
|
||||
f->diffs = calloc(c->metric_len, sizeof(int));
|
||||
f->comb = calloc(c->metric_len, sizeof(int));
|
||||
f->var = calloc(c->metric_len, sizeof(int));
|
||||
/* add more metrics here as needed */
|
||||
}
|
||||
|
||||
static struct pullup_field *make_field_queue(struct pullup_context *c, int len)
|
||||
{
|
||||
struct pullup_field *head, *f;
|
||||
f = head = calloc(1, sizeof(struct pullup_field));
|
||||
alloc_metrics(c, f);
|
||||
for (; len > 0; len--) {
|
||||
f->next = calloc(1, sizeof(struct pullup_field));
|
||||
f->next->prev = f;
|
||||
f = f->next;
|
||||
alloc_metrics(c, f);
|
||||
}
|
||||
f->next = head;
|
||||
head->prev = f;
|
||||
return head;
|
||||
}
|
||||
|
||||
static void check_field_queue(struct pullup_context *c)
|
||||
{
|
||||
if (c->head->next == c->first) {
|
||||
struct pullup_field *f = calloc(1, sizeof(struct pullup_field));
|
||||
alloc_metrics(c, f);
|
||||
f->prev = c->head;
|
||||
f->next = c->first;
|
||||
c->head->next = f;
|
||||
c->first->prev = f;
|
||||
}
|
||||
}
|
||||
|
||||
void pullup_submit_field(struct pullup_context *c, struct pullup_buffer *b, int parity)
|
||||
{
|
||||
struct pullup_field *f;
|
||||
|
||||
/* Grow the circular list if needed */
|
||||
check_field_queue(c);
|
||||
|
||||
/* Cannot have two fields of same parity in a row; drop the new one */
|
||||
if (c->last && c->last->parity == parity) return;
|
||||
|
||||
f = c->head;
|
||||
f->parity = parity;
|
||||
f->buffer = pullup_lock_buffer(b, parity);
|
||||
f->flags = 0;
|
||||
f->breaks = 0;
|
||||
f->affinity = 0;
|
||||
|
||||
compute_metric(c, f, parity, f->prev->prev, parity, c->diff, f->diffs);
|
||||
compute_metric(c, parity?f->prev:f, 0, parity?f:f->prev, 1, c->comb, f->comb);
|
||||
compute_metric(c, f, parity, f, -1, c->var, f->var);
|
||||
|
||||
/* Advance the circular list */
|
||||
if (!c->first) c->first = c->head;
|
||||
c->last = c->head;
|
||||
c->head = c->head->next;
|
||||
}
|
||||
|
||||
void pullup_flush_fields(struct pullup_context *c)
|
||||
{
|
||||
struct pullup_field *f;
|
||||
|
||||
for (f = c->first; f && f != c->head; f = f->next) {
|
||||
pullup_release_buffer(f->buffer, f->parity);
|
||||
f->buffer = 0;
|
||||
}
|
||||
c->first = c->last = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define F_HAVE_BREAKS 1
|
||||
#define F_HAVE_AFFINITY 2
|
||||
|
||||
|
||||
#define BREAK_LEFT 1
|
||||
#define BREAK_RIGHT 2
|
||||
|
||||
|
||||
|
||||
|
||||
static int queue_length(struct pullup_field *begin, struct pullup_field *end)
|
||||
{
|
||||
int count = 1;
|
||||
struct pullup_field *f;
|
||||
|
||||
if (!begin || !end) return 0;
|
||||
for (f = begin; f != end; f = f->next) count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
static int find_first_break(struct pullup_field *f, int max)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < max; i++) {
|
||||
if (f->breaks & BREAK_RIGHT || f->next->breaks & BREAK_LEFT)
|
||||
return i+1;
|
||||
f = f->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void compute_breaks(struct pullup_context *c, struct pullup_field *f0)
|
||||
{
|
||||
int i;
|
||||
struct pullup_field *f1 = f0->next;
|
||||
struct pullup_field *f2 = f1->next;
|
||||
struct pullup_field *f3 = f2->next;
|
||||
int l, max_l=0, max_r=0;
|
||||
//struct pullup_field *ff;
|
||||
//for (i=0, ff=c->first; ff != f0; i++, ff=ff->next);
|
||||
|
||||
if (f0->flags & F_HAVE_BREAKS) return;
|
||||
//printf("\n%d: ", i);
|
||||
f0->flags |= F_HAVE_BREAKS;
|
||||
|
||||
/* Special case when fields are 100% identical */
|
||||
if (f0->buffer == f2->buffer && f1->buffer != f3->buffer) {
|
||||
f2->breaks |= BREAK_RIGHT;
|
||||
return;
|
||||
}
|
||||
if (f0->buffer != f2->buffer && f1->buffer == f3->buffer) {
|
||||
f1->breaks |= BREAK_LEFT;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < c->metric_len; i++) {
|
||||
l = f2->diffs[i] - f3->diffs[i];
|
||||
if (l > max_l) max_l = l;
|
||||
if (-l > max_r) max_r = -l;
|
||||
}
|
||||
/* Don't get tripped up when differences are mostly quant error */
|
||||
//printf("%d %d\n", max_l, max_r);
|
||||
if (max_l + max_r < 128) return;
|
||||
if (max_l > 4*max_r) f1->breaks |= BREAK_LEFT;
|
||||
if (max_r > 4*max_l) f2->breaks |= BREAK_RIGHT;
|
||||
}
|
||||
|
||||
static void compute_affinity(struct pullup_context *c, struct pullup_field *f)
|
||||
{
|
||||
int i;
|
||||
int max_l=0, max_r=0, l;
|
||||
if (f->flags & F_HAVE_AFFINITY) return;
|
||||
f->flags |= F_HAVE_AFFINITY;
|
||||
if (f->buffer == f->next->next->buffer) {
|
||||
f->affinity = 1;
|
||||
f->next->affinity = 0;
|
||||
f->next->next->affinity = -1;
|
||||
f->next->flags |= F_HAVE_AFFINITY;
|
||||
f->next->next->flags |= F_HAVE_AFFINITY;
|
||||
return;
|
||||
}
|
||||
if (1) {
|
||||
for (i = 0; i < c->metric_len; i++) {
|
||||
int lv = f->prev->var[i];
|
||||
int rv = f->next->var[i];
|
||||
int v = f->var[i];
|
||||
int lc = f->comb[i] - (v+lv) + ABS(v-lv);
|
||||
int rc = f->next->comb[i] - (v+rv) + ABS(v-rv);
|
||||
lc = lc>0 ? lc : 0;
|
||||
rc = rc>0 ? rc : 0;
|
||||
l = lc - rc;
|
||||
if (l > max_l) max_l = l;
|
||||
if (-l > max_r) max_r = -l;
|
||||
}
|
||||
if (max_l + max_r < 64) return;
|
||||
if (max_r > 6*max_l) f->affinity = -1;
|
||||
else if (max_l > 6*max_r) f->affinity = 1;
|
||||
} else {
|
||||
for (i = 0; i < c->metric_len; i++) {
|
||||
l = f->comb[i] - f->next->comb[i];
|
||||
if (l > max_l) max_l = l;
|
||||
if (-l > max_r) max_r = -l;
|
||||
}
|
||||
if (max_l + max_r < 64) return;
|
||||
if (max_r > 2*max_l) f->affinity = -1;
|
||||
else if (max_l > 2*max_r) f->affinity = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void foo(struct pullup_context *c)
|
||||
{
|
||||
struct pullup_field *f = c->first;
|
||||
int i, n = queue_length(f, c->last);
|
||||
for (i = 0; i < n-1; i++) {
|
||||
if (i < n-3) compute_breaks(c, f);
|
||||
compute_affinity(c, f);
|
||||
f = f->next;
|
||||
}
|
||||
}
|
||||
|
||||
static int decide_frame_length(struct pullup_context *c)
|
||||
{
|
||||
struct pullup_field *f0 = c->first;
|
||||
struct pullup_field *f1 = f0->next;
|
||||
struct pullup_field *f2 = f1->next;
|
||||
int l;
|
||||
|
||||
if (queue_length(c->first, c->last) < 4) return 0;
|
||||
foo(c);
|
||||
|
||||
if (f0->affinity == -1) return 1;
|
||||
|
||||
l = find_first_break(f0, 3);
|
||||
if (l == 1 && c->strict_breaks < 0) l = 0;
|
||||
|
||||
switch (l) {
|
||||
case 1:
|
||||
if (c->strict_breaks < 1 && f0->affinity == 1 && f1->affinity == -1)
|
||||
return 2;
|
||||
else return 1;
|
||||
case 2:
|
||||
/* FIXME: strictly speaking, f0->prev is no longer valid... :) */
|
||||
if (c->strict_pairs
|
||||
&& (f0->prev->breaks & BREAK_RIGHT) && (f2->breaks & BREAK_LEFT)
|
||||
&& (f0->affinity != 1 || f1->affinity != -1) )
|
||||
return 1;
|
||||
if (f1->affinity == 1) return 1;
|
||||
else return 2;
|
||||
case 3:
|
||||
if (f2->affinity == 1) return 2;
|
||||
else return 3;
|
||||
default:
|
||||
/* 9 possibilities covered before switch */
|
||||
if (f1->affinity == 1) return 1; /* covers 6 */
|
||||
else if (f1->affinity == -1) return 2; /* covers 6 */
|
||||
else if (f2->affinity == -1) { /* covers 2 */
|
||||
if (f0->affinity == 1) return 3;
|
||||
else return 1;
|
||||
}
|
||||
else return 2; /* the remaining 6 */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void print_aff_and_breaks(struct pullup_context *c, struct pullup_field *f)
|
||||
{
|
||||
int i;
|
||||
struct pullup_field *f0 = f;
|
||||
const char aff_l[] = "+..", aff_r[] = "..+";
|
||||
printf("\naffinity: ");
|
||||
for (i = 0; i < 4; i++) {
|
||||
printf("%c%d%c", aff_l[1+f->affinity], i, aff_r[1+f->affinity]);
|
||||
f = f->next;
|
||||
}
|
||||
f = f0;
|
||||
printf("\nbreaks: ");
|
||||
for (i=0; i<4; i++) {
|
||||
printf("%c%d%c", f->breaks & BREAK_LEFT ? '|' : '.', i, f->breaks & BREAK_RIGHT ? '|' : '.');
|
||||
f = f->next;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct pullup_frame *pullup_get_frame(struct pullup_context *c)
|
||||
{
|
||||
int i;
|
||||
struct pullup_frame *fr = c->frame;
|
||||
int n = decide_frame_length(c);
|
||||
int aff = c->first->next->affinity;
|
||||
|
||||
if (!n) return 0;
|
||||
if (fr->lock) return 0;
|
||||
|
||||
if (c->verbose) {
|
||||
print_aff_and_breaks(c, c->first);
|
||||
printf("duration: %d \n", n);
|
||||
}
|
||||
|
||||
fr->lock++;
|
||||
fr->length = n;
|
||||
fr->parity = c->first->parity;
|
||||
fr->buffer = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
/* We cheat and steal the buffer without release+relock */
|
||||
fr->ifields[i] = c->first->buffer;
|
||||
c->first->buffer = 0;
|
||||
c->first = c->first->next;
|
||||
}
|
||||
|
||||
if (n == 1) {
|
||||
fr->ofields[fr->parity] = fr->ifields[0];
|
||||
fr->ofields[fr->parity^1] = 0;
|
||||
} else if (n == 2) {
|
||||
fr->ofields[fr->parity] = fr->ifields[0];
|
||||
fr->ofields[fr->parity^1] = fr->ifields[1];
|
||||
} else if (n == 3) {
|
||||
if (aff == 0)
|
||||
aff = (fr->ifields[0] == fr->ifields[1]) ? -1 : 1;
|
||||
/* else if (c->verbose) printf("forced aff: %d \n", aff); */
|
||||
fr->ofields[fr->parity] = fr->ifields[1+aff];
|
||||
fr->ofields[fr->parity^1] = fr->ifields[1];
|
||||
}
|
||||
pullup_lock_buffer(fr->ofields[0], 0);
|
||||
pullup_lock_buffer(fr->ofields[1], 1);
|
||||
|
||||
if (fr->ofields[0] == fr->ofields[1]) {
|
||||
fr->buffer = fr->ofields[0];
|
||||
pullup_lock_buffer(fr->buffer, 2);
|
||||
return fr;
|
||||
}
|
||||
return fr;
|
||||
}
|
||||
|
||||
static void copy_field(struct pullup_context *c, struct pullup_buffer *dest,
|
||||
struct pullup_buffer *src, int parity)
|
||||
{
|
||||
int i, j;
|
||||
unsigned char *d, *s;
|
||||
for (i = 0; i < c->nplanes; i++) {
|
||||
s = src->planes[i] + parity*c->stride[i];
|
||||
d = dest->planes[i] + parity*c->stride[i];
|
||||
for (j = c->h[i]>>1; j; j--) {
|
||||
memcpy(d, s, c->stride[i]);
|
||||
s += c->stride[i]<<1;
|
||||
d += c->stride[i]<<1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pullup_pack_frame(struct pullup_context *c, struct pullup_frame *fr)
|
||||
{
|
||||
int i;
|
||||
if (fr->buffer) return;
|
||||
if (fr->length < 2) return; /* FIXME: deal with this */
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (fr->ofields[i]->lock[i^1]) continue;
|
||||
fr->buffer = fr->ofields[i];
|
||||
pullup_lock_buffer(fr->buffer, 2);
|
||||
copy_field(c, fr->buffer, fr->ofields[i^1], i^1);
|
||||
return;
|
||||
}
|
||||
fr->buffer = pullup_get_buffer(c, 2);
|
||||
copy_field(c, fr->buffer, fr->ofields[0], 0);
|
||||
copy_field(c, fr->buffer, fr->ofields[1], 1);
|
||||
}
|
||||
|
||||
void pullup_release_frame(struct pullup_frame *fr)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < fr->length; i++)
|
||||
pullup_release_buffer(fr->ifields[i], fr->parity ^ (i&1));
|
||||
pullup_release_buffer(fr->ofields[0], 0);
|
||||
pullup_release_buffer(fr->ofields[1], 1);
|
||||
if (fr->buffer) pullup_release_buffer(fr->buffer, 2);
|
||||
fr->lock--;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct pullup_context *pullup_alloc_context(void)
|
||||
{
|
||||
struct pullup_context *c;
|
||||
|
||||
c = calloc(1, sizeof(struct pullup_context));
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void pullup_preinit_context(struct pullup_context *c)
|
||||
{
|
||||
c->bpp = calloc(c->nplanes, sizeof(int));
|
||||
c->w = calloc(c->nplanes, sizeof(int));
|
||||
c->h = calloc(c->nplanes, sizeof(int));
|
||||
c->stride = calloc(c->nplanes, sizeof(int));
|
||||
c->background = calloc(c->nplanes, sizeof(int));
|
||||
}
|
||||
|
||||
void pullup_init_context(struct pullup_context *c)
|
||||
{
|
||||
int mp = c->metric_plane;
|
||||
if (c->nbuffers < 10) c->nbuffers = 10;
|
||||
c->buffers = calloc(c->nbuffers, sizeof (struct pullup_buffer));
|
||||
|
||||
c->metric_w = (c->w[mp] - ((c->junk_left + c->junk_right) << 3)) >> 3;
|
||||
c->metric_h = (c->h[mp] - ((c->junk_top + c->junk_bottom) << 1)) >> 3;
|
||||
c->metric_offset = c->junk_left*c->bpp[mp] + (c->junk_top<<1)*c->stride[mp];
|
||||
c->metric_len = c->metric_w * c->metric_h;
|
||||
|
||||
c->head = make_field_queue(c, 8);
|
||||
|
||||
c->frame = calloc(1, sizeof (struct pullup_frame));
|
||||
c->frame->ifields = calloc(3, sizeof (struct pullup_buffer *));
|
||||
|
||||
switch(c->format) {
|
||||
case PULLUP_FMT_Y:
|
||||
c->diff = diff_y;
|
||||
c->comb = licomb_y;
|
||||
c->var = var_y;
|
||||
#if ARCH_X86
|
||||
#if HAVE_MMX
|
||||
if (c->cpu & PULLUP_CPU_MMX) {
|
||||
c->diff = diff_y_mmx;
|
||||
c->comb = licomb_y_mmx;
|
||||
c->var = var_y_mmx;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
/* c->comb = qpcomb_y; */
|
||||
break;
|
||||
#if 0
|
||||
case PULLUP_FMT_YUY2:
|
||||
c->diff = diff_yuy2;
|
||||
break;
|
||||
case PULLUP_FMT_RGB32:
|
||||
c->diff = diff_rgb32;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void pullup_free_context(struct pullup_context *c)
|
||||
{
|
||||
struct pullup_field *f;
|
||||
free(c->buffers);
|
||||
f = c->head;
|
||||
do {
|
||||
if (!f) break;
|
||||
free(f->diffs);
|
||||
free(f->comb);
|
||||
f = f->next;
|
||||
free(f->prev);
|
||||
} while (f != c->head);
|
||||
free(c->frame);
|
||||
free(c);
|
||||
}
|
||||
102
libavfilter/libmpcodecs/pullup.h
Normal file
102
libavfilter/libmpcodecs/pullup.h
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_PULLUP_H
|
||||
#define MPLAYER_PULLUP_H
|
||||
|
||||
#define PULLUP_CPU_MMX 1
|
||||
#define PULLUP_CPU_MMX2 2
|
||||
#define PULLUP_CPU_3DNOW 4
|
||||
#define PULLUP_CPU_3DNOWEXT 8
|
||||
#define PULLUP_CPU_SSE 16
|
||||
#define PULLUP_CPU_SSE2 32
|
||||
|
||||
#define PULLUP_FMT_Y 1
|
||||
#define PULLUP_FMT_YUY2 2
|
||||
#define PULLUP_FMT_UYVY 3
|
||||
#define PULLUP_FMT_RGB32 4
|
||||
|
||||
struct pullup_buffer
|
||||
{
|
||||
int lock[2];
|
||||
unsigned char **planes;
|
||||
};
|
||||
|
||||
struct pullup_field
|
||||
{
|
||||
int parity;
|
||||
struct pullup_buffer *buffer;
|
||||
unsigned int flags;
|
||||
int breaks;
|
||||
int affinity;
|
||||
int *diffs;
|
||||
int *comb;
|
||||
int *var;
|
||||
struct pullup_field *prev, *next;
|
||||
};
|
||||
|
||||
struct pullup_frame
|
||||
{
|
||||
int lock;
|
||||
int length;
|
||||
int parity;
|
||||
struct pullup_buffer **ifields, *ofields[2];
|
||||
struct pullup_buffer *buffer;
|
||||
};
|
||||
|
||||
struct pullup_context
|
||||
{
|
||||
/* Public interface */
|
||||
int format;
|
||||
int nplanes;
|
||||
int *bpp, *w, *h, *stride, *background;
|
||||
unsigned int cpu;
|
||||
int junk_left, junk_right, junk_top, junk_bottom;
|
||||
int verbose;
|
||||
int metric_plane;
|
||||
int strict_breaks;
|
||||
int strict_pairs;
|
||||
/* Internal data */
|
||||
struct pullup_field *first, *last, *head;
|
||||
struct pullup_buffer *buffers;
|
||||
int nbuffers;
|
||||
int (*diff)(unsigned char *, unsigned char *, int);
|
||||
int (*comb)(unsigned char *, unsigned char *, int);
|
||||
int (*var)(unsigned char *, unsigned char *, int);
|
||||
int metric_w, metric_h, metric_len, metric_offset;
|
||||
struct pullup_frame *frame;
|
||||
};
|
||||
|
||||
|
||||
struct pullup_buffer *pullup_lock_buffer(struct pullup_buffer *b, int parity);
|
||||
void pullup_release_buffer(struct pullup_buffer *b, int parity);
|
||||
struct pullup_buffer *pullup_get_buffer(struct pullup_context *c, int parity);
|
||||
|
||||
void pullup_submit_field(struct pullup_context *c, struct pullup_buffer *b, int parity);
|
||||
void pullup_flush_fields(struct pullup_context *c);
|
||||
|
||||
struct pullup_frame *pullup_get_frame(struct pullup_context *c);
|
||||
void pullup_pack_frame(struct pullup_context *c, struct pullup_frame *fr);
|
||||
void pullup_release_frame(struct pullup_frame *fr);
|
||||
|
||||
struct pullup_context *pullup_alloc_context(void);
|
||||
void pullup_preinit_context(struct pullup_context *c);
|
||||
void pullup_init_context(struct pullup_context *c);
|
||||
void pullup_free_context(struct pullup_context *c);
|
||||
|
||||
#endif /* MPLAYER_PULLUP_H */
|
||||
24
libavfilter/libmpcodecs/vd_ffmpeg.h
Normal file
24
libavfilter/libmpcodecs/vd_ffmpeg.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_VD_FFMPEG_H
|
||||
#define MPLAYER_VD_FFMPEG_H
|
||||
|
||||
void init_avcodec(void);
|
||||
|
||||
#endif /* MPLAYER_VD_FFMPEG_H */
|
||||
169
libavfilter/libmpcodecs/vf.h
Normal file
169
libavfilter/libmpcodecs/vf.h
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_VF_H
|
||||
#define MPLAYER_VF_H
|
||||
|
||||
#include "m_option.h"
|
||||
#include "mp_image.h"
|
||||
|
||||
extern m_obj_settings_t* vf_settings;
|
||||
extern const m_obj_list_t vf_obj_list;
|
||||
|
||||
struct vf_instance;
|
||||
struct vf_priv_s;
|
||||
|
||||
typedef struct vf_info_s {
|
||||
const char *info;
|
||||
const char *name;
|
||||
const char *author;
|
||||
const char *comment;
|
||||
int (*vf_open)(struct vf_instance *vf,char* args);
|
||||
// Ptr to a struct dscribing the options
|
||||
const void* opts;
|
||||
} vf_info_t;
|
||||
|
||||
#define NUM_NUMBERED_MPI 50
|
||||
|
||||
typedef struct vf_image_context_s {
|
||||
mp_image_t* static_images[2];
|
||||
mp_image_t* temp_images[1];
|
||||
mp_image_t* export_images[1];
|
||||
mp_image_t* numbered_images[NUM_NUMBERED_MPI];
|
||||
int static_idx;
|
||||
} vf_image_context_t;
|
||||
|
||||
typedef struct vf_format_context_t {
|
||||
int have_configured;
|
||||
int orig_width, orig_height, orig_fmt;
|
||||
} vf_format_context_t;
|
||||
|
||||
typedef struct vf_instance {
|
||||
const vf_info_t* info;
|
||||
// funcs:
|
||||
int (*config)(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt);
|
||||
int (*control)(struct vf_instance *vf,
|
||||
int request, void* data);
|
||||
int (*query_format)(struct vf_instance *vf,
|
||||
unsigned int fmt);
|
||||
void (*get_image)(struct vf_instance *vf,
|
||||
mp_image_t *mpi);
|
||||
int (*put_image)(struct vf_instance *vf,
|
||||
mp_image_t *mpi, double pts);
|
||||
void (*start_slice)(struct vf_instance *vf,
|
||||
mp_image_t *mpi);
|
||||
void (*draw_slice)(struct vf_instance *vf,
|
||||
unsigned char** src, int* stride, int w,int h, int x, int y);
|
||||
void (*uninit)(struct vf_instance *vf);
|
||||
|
||||
int (*continue_buffered_image)(struct vf_instance *vf);
|
||||
// caps:
|
||||
unsigned int default_caps; // used by default query_format()
|
||||
unsigned int default_reqs; // used by default config()
|
||||
// data:
|
||||
int w, h;
|
||||
vf_image_context_t imgctx;
|
||||
vf_format_context_t fmt;
|
||||
struct vf_instance *next;
|
||||
mp_image_t *dmpi;
|
||||
struct vf_priv_s* priv;
|
||||
} vf_instance_t;
|
||||
|
||||
// control codes:
|
||||
#include "mpc_info.h"
|
||||
|
||||
typedef struct vf_seteq_s
|
||||
{
|
||||
const char *item;
|
||||
int value;
|
||||
} vf_equalizer_t;
|
||||
|
||||
#define VFCTRL_QUERY_MAX_PP_LEVEL 4 /* test for postprocessing support (max level) */
|
||||
#define VFCTRL_SET_PP_LEVEL 5 /* set postprocessing level */
|
||||
#define VFCTRL_SET_EQUALIZER 6 /* set color options (brightness,contrast etc) */
|
||||
#define VFCTRL_GET_EQUALIZER 8 /* gset color options (brightness,contrast etc) */
|
||||
#define VFCTRL_DRAW_OSD 7
|
||||
#define VFCTRL_CHANGE_RECTANGLE 9 /* Change the rectangle boundaries */
|
||||
#define VFCTRL_FLIP_PAGE 10 /* Tell the vo to flip pages */
|
||||
#define VFCTRL_DUPLICATE_FRAME 11 /* For encoding - encode zero-change frame */
|
||||
#define VFCTRL_SKIP_NEXT_FRAME 12 /* For encoding - drop the next frame that passes thru */
|
||||
#define VFCTRL_FLUSH_FRAMES 13 /* For encoding - flush delayed frames */
|
||||
#define VFCTRL_SCREENSHOT 14 /* Make a screenshot */
|
||||
#define VFCTRL_INIT_EOSD 15 /* Select EOSD renderer */
|
||||
#define VFCTRL_DRAW_EOSD 16 /* Render EOSD */
|
||||
#define VFCTRL_GET_PTS 17 /* Return last pts value that reached vf_vo*/
|
||||
#define VFCTRL_SET_DEINTERLACE 18 /* Set deinterlacing status */
|
||||
#define VFCTRL_GET_DEINTERLACE 19 /* Get deinterlacing status */
|
||||
|
||||
#include "vfcap.h"
|
||||
|
||||
//FIXME this should be in a common header, but i dunno which
|
||||
#define MP_NOPTS_VALUE (-1LL<<63) //both int64_t and double should be able to represent this exactly
|
||||
|
||||
|
||||
// functions:
|
||||
void vf_mpi_clear(mp_image_t* mpi,int x0,int y0,int w,int h);
|
||||
mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, int mp_imgflag, int w, int h);
|
||||
|
||||
vf_instance_t* vf_open_plugin(const vf_info_t* const* filter_list, vf_instance_t* next, const char *name, char **args);
|
||||
vf_instance_t* vf_open_filter(vf_instance_t* next, const char *name, char **args);
|
||||
vf_instance_t* vf_add_before_vo(vf_instance_t **vf, char *name, char **args);
|
||||
vf_instance_t* vf_open_encoder(vf_instance_t* next, const char *name, char *args);
|
||||
|
||||
unsigned int vf_match_csp(vf_instance_t** vfp,const unsigned int* list,unsigned int preferred);
|
||||
void vf_clone_mpi_attributes(mp_image_t* dst, mp_image_t* src);
|
||||
void vf_queue_frame(vf_instance_t *vf, int (*)(vf_instance_t *));
|
||||
int vf_output_queued_frame(vf_instance_t *vf);
|
||||
|
||||
// default wrappers:
|
||||
int vf_next_config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt);
|
||||
int vf_next_control(struct vf_instance *vf, int request, void* data);
|
||||
void vf_extra_flip(struct vf_instance *vf);
|
||||
int vf_next_query_format(struct vf_instance *vf, unsigned int fmt);
|
||||
int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts);
|
||||
void vf_next_draw_slice (struct vf_instance *vf, unsigned char** src, int* stride, int w,int h, int x, int y);
|
||||
|
||||
vf_instance_t* append_filters(vf_instance_t* last);
|
||||
|
||||
void vf_uninit_filter(vf_instance_t* vf);
|
||||
void vf_uninit_filter_chain(vf_instance_t* vf);
|
||||
|
||||
int vf_config_wrapper(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt);
|
||||
|
||||
static inline int norm_qscale(int qscale, int type)
|
||||
{
|
||||
switch (type) {
|
||||
case 0: // MPEG-1
|
||||
return qscale;
|
||||
case 1: // MPEG-2
|
||||
return qscale >> 1;
|
||||
case 2: // H264
|
||||
return qscale >> 2;
|
||||
case 3: // VP56
|
||||
return (63 - qscale + 2) >> 2;
|
||||
}
|
||||
return qscale;
|
||||
}
|
||||
|
||||
#endif /* MPLAYER_VF_H */
|
||||
336
libavfilter/libmpcodecs/vf_2xsai.c
Normal file
336
libavfilter/libmpcodecs/vf_2xsai.c
Normal file
@ -0,0 +1,336 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
/* FIXME: these all belong in the context, not as globals! */
|
||||
|
||||
static uint32_t colorMask = 0xF7DEF7DE;
|
||||
static uint32_t lowPixelMask = 0x08210821;
|
||||
static uint32_t qcolorMask = 0xE79CE79C;
|
||||
static uint32_t qlowpixelMask = 0x18631863;
|
||||
static uint32_t redblueMask = 0xF81F;
|
||||
static uint32_t greenMask = 0x7E0;
|
||||
static int PixelsPerMask = 2;
|
||||
|
||||
#define makecol(r,g,b) (r+(g<<8)+(b<<16))
|
||||
#define makecol_depth(d,r,g,b) (r+(g<<8)+(b<<16))
|
||||
|
||||
static int Init_2xSaI(int d)
|
||||
{
|
||||
|
||||
int minr = 0, ming = 0, minb = 0;
|
||||
int i;
|
||||
|
||||
// if (d != 15 && d != 16 && d != 24 && d != 32)
|
||||
// return -1;
|
||||
|
||||
/* Get lowest color bit */
|
||||
for (i = 0; i < 255; i++) {
|
||||
if (!minr)
|
||||
minr = makecol(i, 0, 0);
|
||||
if (!ming)
|
||||
ming = makecol(0, i, 0);
|
||||
if (!minb)
|
||||
minb = makecol(0, 0, i);
|
||||
}
|
||||
|
||||
colorMask = (makecol_depth(d, 255, 0, 0) - minr) | (makecol_depth(d, 0, 255, 0) - ming) | (makecol_depth(d, 0, 0, 255) - minb);
|
||||
lowPixelMask = minr | ming | minb;
|
||||
qcolorMask = (makecol_depth(d, 255, 0, 0) - 3 * minr) | (makecol_depth(d, 0, 255, 0) - 3 * ming) | (makecol_depth(d, 0, 0, 255) - 3 * minb);
|
||||
qlowpixelMask = (minr * 3) | (ming * 3) | (minb * 3);
|
||||
redblueMask = makecol_depth(d, 255, 0, 255);
|
||||
greenMask = makecol_depth(d, 0, 255, 0);
|
||||
|
||||
PixelsPerMask = (d <= 16) ? 2 : 1;
|
||||
|
||||
if (PixelsPerMask == 2) {
|
||||
colorMask |= (colorMask << 16);
|
||||
qcolorMask |= (qcolorMask << 16);
|
||||
lowPixelMask |= (lowPixelMask << 16);
|
||||
qlowpixelMask |= (qlowpixelMask << 16);
|
||||
}
|
||||
|
||||
// TRACE("Color Mask: 0x%lX\n", colorMask);
|
||||
// TRACE("Low Pixel Mask: 0x%lX\n", lowPixelMask);
|
||||
// TRACE("QColor Mask: 0x%lX\n", qcolorMask);
|
||||
// TRACE("QLow Pixel Mask: 0x%lX\n", qlowpixelMask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D))
|
||||
|
||||
#define INTERPOLATE(A, B) (((A & colorMask) >> 1) + ((B & colorMask) >> 1) + (A & B & lowPixelMask))
|
||||
|
||||
#define Q_INTERPOLATE(A, B, C, D) ((A & qcolorMask) >> 2) + ((B & qcolorMask) >> 2) + ((C & qcolorMask) >> 2) + ((D & qcolorMask) >> 2) \
|
||||
+ ((((A & qlowpixelMask) + (B & qlowpixelMask) + (C & qlowpixelMask) + (D & qlowpixelMask)) >> 2) & qlowpixelMask)
|
||||
|
||||
|
||||
static void Super2xSaI_ex(uint8_t *src, uint32_t src_pitch,
|
||||
uint8_t *dst, uint32_t dst_pitch,
|
||||
uint32_t width, uint32_t height, int sbpp)
|
||||
{
|
||||
|
||||
unsigned int x, y;
|
||||
uint32_t color[16];
|
||||
unsigned char *src_line[4];
|
||||
|
||||
/* Point to the first 3 lines. */
|
||||
src_line[0] = src;
|
||||
src_line[1] = src;
|
||||
src_line[2] = src + src_pitch;
|
||||
src_line[3] = src + src_pitch * 2;
|
||||
|
||||
x = 0, y = 0;
|
||||
|
||||
if (PixelsPerMask == 2) {
|
||||
unsigned short *sbp;
|
||||
sbp = (unsigned short*)src_line[0];
|
||||
color[0] = *sbp; color[1] = color[0]; color[2] = color[0]; color[3] = color[0];
|
||||
color[4] = color[0]; color[5] = color[0]; color[6] = *(sbp + 1); color[7] = *(sbp + 2);
|
||||
sbp = (unsigned short*)src_line[2];
|
||||
color[8] = *sbp; color[9] = color[8]; color[10] = *(sbp + 1); color[11] = *(sbp + 2);
|
||||
sbp = (unsigned short*)src_line[3];
|
||||
color[12] = *sbp; color[13] = color[12]; color[14] = *(sbp + 1); color[15] = *(sbp + 2);
|
||||
}
|
||||
else {
|
||||
uint32_t *lbp;
|
||||
lbp = (uint32_t*)src_line[0];
|
||||
color[0] = *lbp; color[1] = color[0]; color[2] = color[0]; color[3] = color[0];
|
||||
color[4] = color[0]; color[5] = color[0]; color[6] = *(lbp + 1); color[7] = *(lbp + 2);
|
||||
lbp = (uint32_t*)src_line[2];
|
||||
color[8] = *lbp; color[9] = color[8]; color[10] = *(lbp + 1); color[11] = *(lbp + 2);
|
||||
lbp = (uint32_t*)src_line[3];
|
||||
color[12] = *lbp; color[13] = color[12]; color[14] = *(lbp + 1); color[15] = *(lbp + 2);
|
||||
}
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
unsigned char *dst_line[2];
|
||||
|
||||
dst_line[0] = dst + dst_pitch*2*y;
|
||||
dst_line[1] = dst + dst_pitch*(2*y+1);
|
||||
|
||||
/* Todo: x = width - 2, x = width - 1 */
|
||||
|
||||
for (x = 0; x < width; x++) {
|
||||
uint32_t product1a, product1b, product2a, product2b;
|
||||
|
||||
//--------------------------------------- B0 B1 B2 B3 0 1 2 3
|
||||
// 4 5* 6 S2 -> 4 5* 6 7
|
||||
// 1 2 3 S1 8 9 10 11
|
||||
// A0 A1 A2 A3 12 13 14 15
|
||||
//--------------------------------------
|
||||
if (color[9] == color[6] && color[5] != color[10]) {
|
||||
product2b = color[9];
|
||||
product1b = product2b;
|
||||
}
|
||||
else if (color[5] == color[10] && color[9] != color[6]) {
|
||||
product2b = color[5];
|
||||
product1b = product2b;
|
||||
}
|
||||
else if (color[5] == color[10] && color[9] == color[6]) {
|
||||
int r = 0;
|
||||
|
||||
r += GET_RESULT(color[6], color[5], color[8], color[13]);
|
||||
r += GET_RESULT(color[6], color[5], color[4], color[1]);
|
||||
r += GET_RESULT(color[6], color[5], color[14], color[11]);
|
||||
r += GET_RESULT(color[6], color[5], color[2], color[7]);
|
||||
|
||||
if (r > 0)
|
||||
product1b = color[6];
|
||||
else if (r < 0)
|
||||
product1b = color[5];
|
||||
else
|
||||
product1b = INTERPOLATE(color[5], color[6]);
|
||||
|
||||
product2b = product1b;
|
||||
|
||||
}
|
||||
else {
|
||||
if (color[6] == color[10] && color[10] == color[13] && color[9] != color[14] && color[10] != color[12])
|
||||
product2b = Q_INTERPOLATE(color[10], color[10], color[10], color[9]);
|
||||
else if (color[5] == color[9] && color[9] == color[14] && color[13] != color[10] && color[9] != color[15])
|
||||
product2b = Q_INTERPOLATE(color[9], color[9], color[9], color[10]);
|
||||
else
|
||||
product2b = INTERPOLATE(color[9], color[10]);
|
||||
|
||||
if (color[6] == color[10] && color[6] == color[1] && color[5] != color[2] && color[6] != color[0])
|
||||
product1b = Q_INTERPOLATE(color[6], color[6], color[6], color[5]);
|
||||
else if (color[5] == color[9] && color[5] == color[2] && color[1] != color[6] && color[5] != color[3])
|
||||
product1b = Q_INTERPOLATE(color[6], color[5], color[5], color[5]);
|
||||
else
|
||||
product1b = INTERPOLATE(color[5], color[6]);
|
||||
}
|
||||
|
||||
if (color[5] == color[10] && color[9] != color[6] && color[4] == color[5] && color[5] != color[14])
|
||||
product2a = INTERPOLATE(color[9], color[5]);
|
||||
else if (color[5] == color[8] && color[6] == color[5] && color[4] != color[9] && color[5] != color[12])
|
||||
product2a = INTERPOLATE(color[9], color[5]);
|
||||
else
|
||||
product2a = color[9];
|
||||
|
||||
if (color[9] == color[6] && color[5] != color[10] && color[8] == color[9] && color[9] != color[2])
|
||||
product1a = INTERPOLATE(color[9], color[5]);
|
||||
else if (color[4] == color[9] && color[10] == color[9] && color[8] != color[5] && color[9] != color[0])
|
||||
product1a = INTERPOLATE(color[9], color[5]);
|
||||
else
|
||||
product1a = color[5];
|
||||
|
||||
if (PixelsPerMask == 2) {
|
||||
*((uint32_t *) (&dst_line[0][x * 4])) = product1a | (product1b << 16);
|
||||
*((uint32_t *) (&dst_line[1][x * 4])) = product2a | (product2b << 16);
|
||||
}
|
||||
else {
|
||||
*((uint32_t *) (&dst_line[0][x * 8])) = product1a;
|
||||
*((uint32_t *) (&dst_line[0][x * 8 + 4])) = product1b;
|
||||
*((uint32_t *) (&dst_line[1][x * 8])) = product2a;
|
||||
*((uint32_t *) (&dst_line[1][x * 8 + 4])) = product2b;
|
||||
}
|
||||
|
||||
/* Move color matrix forward */
|
||||
color[0] = color[1]; color[4] = color[5]; color[8] = color[9]; color[12] = color[13];
|
||||
color[1] = color[2]; color[5] = color[6]; color[9] = color[10]; color[13] = color[14];
|
||||
color[2] = color[3]; color[6] = color[7]; color[10] = color[11]; color[14] = color[15];
|
||||
|
||||
if (x < width - 3) {
|
||||
x += 3;
|
||||
if (PixelsPerMask == 2) {
|
||||
color[3] = *(((unsigned short*)src_line[0]) + x);
|
||||
color[7] = *(((unsigned short*)src_line[1]) + x);
|
||||
color[11] = *(((unsigned short*)src_line[2]) + x);
|
||||
color[15] = *(((unsigned short*)src_line[3]) + x);
|
||||
}
|
||||
else {
|
||||
color[3] = *(((uint32_t*)src_line[0]) + x);
|
||||
color[7] = *(((uint32_t*)src_line[1]) + x);
|
||||
color[11] = *(((uint32_t*)src_line[2]) + x);
|
||||
color[15] = *(((uint32_t*)src_line[3]) + x);
|
||||
}
|
||||
x -= 3;
|
||||
}
|
||||
}
|
||||
|
||||
/* We're done with one line, so we shift the source lines up */
|
||||
src_line[0] = src_line[1];
|
||||
src_line[1] = src_line[2];
|
||||
src_line[2] = src_line[3];
|
||||
|
||||
/* Read next line */
|
||||
if (y + 3 >= height)
|
||||
src_line[3] = src_line[2];
|
||||
else
|
||||
src_line[3] = src_line[2] + src_pitch;
|
||||
|
||||
/* Then shift the color matrix up */
|
||||
if (PixelsPerMask == 2) {
|
||||
unsigned short *sbp;
|
||||
sbp = (unsigned short*)src_line[0];
|
||||
color[0] = *sbp; color[1] = color[0]; color[2] = *(sbp + 1); color[3] = *(sbp + 2);
|
||||
sbp = (unsigned short*)src_line[1];
|
||||
color[4] = *sbp; color[5] = color[4]; color[6] = *(sbp + 1); color[7] = *(sbp + 2);
|
||||
sbp = (unsigned short*)src_line[2];
|
||||
color[8] = *sbp; color[9] = color[9]; color[10] = *(sbp + 1); color[11] = *(sbp + 2);
|
||||
sbp = (unsigned short*)src_line[3];
|
||||
color[12] = *sbp; color[13] = color[12]; color[14] = *(sbp + 1); color[15] = *(sbp + 2);
|
||||
}
|
||||
else {
|
||||
uint32_t *lbp;
|
||||
lbp = (uint32_t*)src_line[0];
|
||||
color[0] = *lbp; color[1] = color[0]; color[2] = *(lbp + 1); color[3] = *(lbp + 2);
|
||||
lbp = (uint32_t*)src_line[1];
|
||||
color[4] = *lbp; color[5] = color[4]; color[6] = *(lbp + 1); color[7] = *(lbp + 2);
|
||||
lbp = (uint32_t*)src_line[2];
|
||||
color[8] = *lbp; color[9] = color[9]; color[10] = *(lbp + 1); color[11] = *(lbp + 2);
|
||||
lbp = (uint32_t*)src_line[3];
|
||||
color[12] = *lbp; color[13] = color[12]; color[14] = *(lbp + 1); color[15] = *(lbp + 2);
|
||||
}
|
||||
|
||||
} // y loop
|
||||
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
|
||||
Init_2xSaI(outfmt&255);
|
||||
|
||||
return vf_next_config(vf,2*width,2*height,2*d_width,2*d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
|
||||
// hope we'll get DR buffer:
|
||||
dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
2*mpi->w, 2*mpi->h);
|
||||
|
||||
Super2xSaI_ex(mpi->planes[0], mpi->stride[0],
|
||||
dmpi->planes[0], dmpi->stride[0],
|
||||
mpi->w, mpi->h, mpi->bpp/8);
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
switch(fmt){
|
||||
// case IMGFMT_BGR15:
|
||||
// case IMGFMT_BGR16:
|
||||
case IMGFMT_BGR32:
|
||||
return vf_next_query_format(vf,fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->query_format=query_format;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_2xsai = {
|
||||
"2xSai BGR bitmap 2x scaler",
|
||||
"2xsai",
|
||||
"A'rpi",
|
||||
"http://elektron.its.tudelft.nl/~dalikifa/",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
148
libavfilter/libmpcodecs/vf_blackframe.c
Normal file
148
libavfilter/libmpcodecs/vf_blackframe.c
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* detect frames that are (almost) black
|
||||
* search for black frames to detect scene transitions
|
||||
* (c) 2006 Julian Hall
|
||||
*
|
||||
* based on code designed for skipping commercials
|
||||
* (c) 2002-2003 Brian J. Murrell
|
||||
*
|
||||
* cleanup, simplify, speedup (c) 2006 by Ivo van Poorten
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
unsigned int bamount, bthresh, frame, lastkeyframe;
|
||||
};
|
||||
|
||||
static int config(struct vf_instance *vf, int width, int height, int d_width,
|
||||
int d_height, unsigned int flags, unsigned int outfmt) {
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned fmt) {
|
||||
switch(fmt) {
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_IF09:
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_CLPL:
|
||||
case IMGFMT_Y800:
|
||||
case IMGFMT_Y8:
|
||||
case IMGFMT_NV12:
|
||||
case IMGFMT_NV21:
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
case IMGFMT_HM12:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
int x, y;
|
||||
int nblack=0, pblack=0;
|
||||
unsigned char *yplane = mpi->planes[0];
|
||||
unsigned int ystride = mpi->stride[0];
|
||||
int pict_type = mpi->pict_type;
|
||||
int w = mpi->w, h = mpi->h;
|
||||
int bthresh = vf->priv->bthresh;
|
||||
int bamount = vf->priv->bamount;
|
||||
static const char *const picttypes[4] = { "unknown", "I", "P", "B" };
|
||||
|
||||
for (y=1; y<=h; y++) {
|
||||
for (x=0; x<w; x++)
|
||||
nblack += yplane[x] < bthresh;
|
||||
pblack = nblack*100/(w*y);
|
||||
if (pblack < bamount) break;
|
||||
yplane += ystride;
|
||||
}
|
||||
|
||||
if (pict_type > 3 || pict_type < 0) pict_type = 0;
|
||||
if (pict_type == 1) vf->priv->lastkeyframe = vf->priv->frame;
|
||||
|
||||
if (pblack >= bamount)
|
||||
mp_msg(MSGT_VFILTER, MSGL_INFO,"vf_blackframe: %u, %i%%, %s (I:%u)\n",
|
||||
vf->priv->frame, pblack, picttypes[pict_type],
|
||||
vf->priv->lastkeyframe);
|
||||
|
||||
vf->priv->frame++;
|
||||
|
||||
dmpi = vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_EXPORT, 0,
|
||||
mpi->width, mpi->height);
|
||||
dmpi->planes[0] = mpi->planes[0];
|
||||
dmpi->stride[0] = mpi->stride[0];
|
||||
dmpi->planes[1] = mpi->planes[1];
|
||||
dmpi->stride[1] = mpi->stride[1];
|
||||
dmpi->planes[2] = mpi->planes[2];
|
||||
dmpi->stride[2] = mpi->stride[2];
|
||||
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
|
||||
return vf_next_put_image(vf, dmpi, pts);
|
||||
}
|
||||
|
||||
static int control(struct vf_instance *vf, int request, void* data){
|
||||
return vf_next_control(vf,request,data);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf) {
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
vf->priv = malloc(sizeof(struct vf_priv_s));
|
||||
if (!vf->priv) return 0;
|
||||
|
||||
vf->config = config;
|
||||
vf->put_image = put_image;
|
||||
vf->control = control;
|
||||
vf->uninit = uninit;
|
||||
vf->query_format = query_format;
|
||||
|
||||
vf->priv->bamount = 98;
|
||||
vf->priv->bthresh = 0x20;
|
||||
vf->priv->frame = 0;
|
||||
vf->priv->lastkeyframe = 0;
|
||||
|
||||
if (args)
|
||||
sscanf(args, "%u:%u", &vf->priv->bamount, &vf->priv->bthresh);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_blackframe = {
|
||||
"detects black frames",
|
||||
"blackframe",
|
||||
"Brian J. Murrell, Julian Hall, Ivo van Poorten",
|
||||
"Useful for detecting scene transitions",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
214
libavfilter/libmpcodecs/vf_boxblur.c
Normal file
214
libavfilter/libmpcodecs/vf_boxblur.c
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mp_msg.h"
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
typedef struct FilterParam{
|
||||
int radius;
|
||||
int power;
|
||||
}FilterParam;
|
||||
|
||||
struct vf_priv_s {
|
||||
FilterParam lumaParam;
|
||||
FilterParam chromaParam;
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static inline void blur(uint8_t *dst, uint8_t *src, int w, int radius, int dstStep, int srcStep){
|
||||
int x;
|
||||
const int length= radius*2 + 1;
|
||||
const int inv= ((1<<16) + length/2)/length;
|
||||
|
||||
int sum= 0;
|
||||
|
||||
for(x=0; x<radius; x++){
|
||||
sum+= src[x*srcStep]<<1;
|
||||
}
|
||||
sum+= src[radius*srcStep];
|
||||
|
||||
for(x=0; x<=radius; x++){
|
||||
sum+= src[(radius+x)*srcStep] - src[(radius-x)*srcStep];
|
||||
dst[x*dstStep]= (sum*inv + (1<<15))>>16;
|
||||
}
|
||||
|
||||
for(; x<w-radius; x++){
|
||||
sum+= src[(radius+x)*srcStep] - src[(x-radius-1)*srcStep];
|
||||
dst[x*dstStep]= (sum*inv + (1<<15))>>16;
|
||||
}
|
||||
|
||||
for(; x<w; x++){
|
||||
sum+= src[(2*w-radius-x-1)*srcStep] - src[(x-radius-1)*srcStep];
|
||||
dst[x*dstStep]= (sum*inv + (1<<15))>>16;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void blur2(uint8_t *dst, uint8_t *src, int w, int radius, int power, int dstStep, int srcStep){
|
||||
uint8_t temp[2][4096];
|
||||
uint8_t *a= temp[0], *b=temp[1];
|
||||
|
||||
if(radius){
|
||||
blur(a, src, w, radius, 1, srcStep);
|
||||
for(; power>2; power--){
|
||||
uint8_t *c;
|
||||
blur(b, a, w, radius, 1, 1);
|
||||
c=a; a=b; b=c;
|
||||
}
|
||||
if(power>1)
|
||||
blur(dst, a, w, radius, dstStep, 1);
|
||||
else{
|
||||
int i;
|
||||
for(i=0; i<w; i++)
|
||||
dst[i*dstStep]= a[i];
|
||||
}
|
||||
}else{
|
||||
int i;
|
||||
for(i=0; i<w; i++)
|
||||
dst[i*dstStep]= src[i*srcStep];
|
||||
}
|
||||
}
|
||||
|
||||
static void hBlur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, int radius, int power){
|
||||
int y;
|
||||
|
||||
if(radius==0 && dst==src) return;
|
||||
|
||||
for(y=0; y<h; y++){
|
||||
blur2(dst + y*dstStride, src + y*srcStride, w, radius, power, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME optimize (x before y !!!)
|
||||
static void vBlur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, int radius, int power){
|
||||
int x;
|
||||
|
||||
if(radius==0 && dst==src) return;
|
||||
|
||||
for(x=0; x<w; x++){
|
||||
blur2(dst + x, src + x, h, radius, power, dstStride, srcStride);
|
||||
}
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
int cw= mpi->w >> mpi->chroma_x_shift;
|
||||
int ch= mpi->h >> mpi->chroma_y_shift;
|
||||
|
||||
mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_READABLE,
|
||||
mpi->w,mpi->h);
|
||||
|
||||
assert(mpi->flags&MP_IMGFLAG_PLANAR);
|
||||
|
||||
hBlur(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h,
|
||||
dmpi->stride[0], mpi->stride[0], vf->priv->lumaParam.radius, vf->priv->lumaParam.power);
|
||||
hBlur(dmpi->planes[1], mpi->planes[1], cw,ch,
|
||||
dmpi->stride[1], mpi->stride[1], vf->priv->chromaParam.radius, vf->priv->chromaParam.power);
|
||||
hBlur(dmpi->planes[2], mpi->planes[2], cw,ch,
|
||||
dmpi->stride[2], mpi->stride[2], vf->priv->chromaParam.radius, vf->priv->chromaParam.power);
|
||||
|
||||
vBlur(dmpi->planes[0], dmpi->planes[0], mpi->w,mpi->h,
|
||||
dmpi->stride[0], dmpi->stride[0], vf->priv->lumaParam.radius, vf->priv->lumaParam.power);
|
||||
vBlur(dmpi->planes[1], dmpi->planes[1], cw,ch,
|
||||
dmpi->stride[1], dmpi->stride[1], vf->priv->chromaParam.radius, vf->priv->chromaParam.power);
|
||||
vBlur(dmpi->planes[2], dmpi->planes[2], cw,ch,
|
||||
dmpi->stride[2], dmpi->stride[2], vf->priv->chromaParam.radius, vf->priv->chromaParam.power);
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
switch(fmt)
|
||||
{
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
int e;
|
||||
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
// vf->get_image=get_image;
|
||||
vf->query_format=query_format;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
|
||||
if(args==NULL) return 0;
|
||||
|
||||
e=sscanf(args, "%d:%d:%d:%d",
|
||||
&vf->priv->lumaParam.radius,
|
||||
&vf->priv->lumaParam.power,
|
||||
&vf->priv->chromaParam.radius,
|
||||
&vf->priv->chromaParam.power
|
||||
);
|
||||
|
||||
if(e==2){
|
||||
vf->priv->chromaParam.radius= vf->priv->lumaParam.radius;
|
||||
vf->priv->chromaParam.power = vf->priv->lumaParam.power;
|
||||
}else if(e!=4)
|
||||
return 0;
|
||||
|
||||
if(vf->priv->lumaParam.radius < 0) return 0;
|
||||
if(vf->priv->chromaParam.radius < 0) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_boxblur = {
|
||||
"box blur",
|
||||
"boxblur",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
201
libavfilter/libmpcodecs/vf_cropdetect.c
Normal file
201
libavfilter/libmpcodecs/vf_cropdetect.c
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "help_mp.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
int x1,y1,x2,y2;
|
||||
int limit;
|
||||
int round;
|
||||
int reset_count;
|
||||
int fno;
|
||||
};
|
||||
|
||||
static int checkline(unsigned char* src,int stride,int len,int bpp){
|
||||
int total=0;
|
||||
int div=len;
|
||||
switch(bpp){
|
||||
case 1:
|
||||
while(--len>=0){
|
||||
total+=src[0]; src+=stride;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
while(--len>=0){
|
||||
total+=src[0]+src[1]+src[2]; src+=stride;
|
||||
}
|
||||
div*=3;
|
||||
break;
|
||||
}
|
||||
total/=div;
|
||||
// printf("total=%d\n",total);
|
||||
return total;
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
vf->priv->x1=width - 1;
|
||||
vf->priv->y1=height - 1;
|
||||
vf->priv->x2=0;
|
||||
vf->priv->y2=0;
|
||||
vf->priv->fno=-2;
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
int bpp=mpi->bpp/8;
|
||||
int w,h,x,y,shrink_by;
|
||||
|
||||
// hope we'll get DR buffer:
|
||||
dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_EXPORT, 0,
|
||||
mpi->w, mpi->h);
|
||||
|
||||
dmpi->planes[0]=mpi->planes[0];
|
||||
dmpi->planes[1]=mpi->planes[1];
|
||||
dmpi->planes[2]=mpi->planes[2];
|
||||
dmpi->stride[0]=mpi->stride[0];
|
||||
dmpi->stride[1]=mpi->stride[1];
|
||||
dmpi->stride[2]=mpi->stride[2];
|
||||
dmpi->width=mpi->width;
|
||||
dmpi->height=mpi->height;
|
||||
|
||||
if(++vf->priv->fno>0){ // ignore first 2 frames - they may be empty
|
||||
|
||||
// Reset the crop area every reset_count frames, if reset_count is > 0
|
||||
if(vf->priv->reset_count > 0 && vf->priv->fno > vf->priv->reset_count){
|
||||
vf->priv->x1=mpi->w-1;
|
||||
vf->priv->y1=mpi->h-1;
|
||||
vf->priv->x2=0;
|
||||
vf->priv->y2=0;
|
||||
vf->priv->fno=1;
|
||||
}
|
||||
|
||||
for(y=0;y<vf->priv->y1;y++){
|
||||
if(checkline(mpi->planes[0]+mpi->stride[0]*y,bpp,mpi->w,bpp)>vf->priv->limit){
|
||||
vf->priv->y1=y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(y=mpi->h-1;y>vf->priv->y2;y--){
|
||||
if(checkline(mpi->planes[0]+mpi->stride[0]*y,bpp,mpi->w,bpp)>vf->priv->limit){
|
||||
vf->priv->y2=y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(y=0;y<vf->priv->x1;y++){
|
||||
if(checkline(mpi->planes[0]+bpp*y,mpi->stride[0],mpi->h,bpp)>vf->priv->limit){
|
||||
vf->priv->x1=y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(y=mpi->w-1;y>vf->priv->x2;y--){
|
||||
if(checkline(mpi->planes[0]+bpp*y,mpi->stride[0],mpi->h,bpp)>vf->priv->limit){
|
||||
vf->priv->x2=y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// round x and y (up), important for yuv colorspaces
|
||||
// make sure they stay rounded!
|
||||
x=(vf->priv->x1+1)&(~1);
|
||||
y=(vf->priv->y1+1)&(~1);
|
||||
|
||||
w = vf->priv->x2 - x + 1;
|
||||
h = vf->priv->y2 - y + 1;
|
||||
|
||||
// w and h must be divisible by 2 as well because of yuv
|
||||
// colorspace problems.
|
||||
if (vf->priv->round <= 1)
|
||||
vf->priv->round = 16;
|
||||
if (vf->priv->round % 2)
|
||||
vf->priv->round *= 2;
|
||||
|
||||
shrink_by = w % vf->priv->round;
|
||||
w -= shrink_by;
|
||||
x += (shrink_by / 2 + 1) & ~1;
|
||||
|
||||
shrink_by = h % vf->priv->round;
|
||||
h -= shrink_by;
|
||||
y += (shrink_by / 2 + 1) & ~1;
|
||||
|
||||
mp_msg(MSGT_VFILTER, MSGL_INFO, MSGTR_MPCODECS_CropArea,
|
||||
vf->priv->x1,vf->priv->x2,
|
||||
vf->priv->y1,vf->priv->y2,
|
||||
w,h,x,y);
|
||||
|
||||
|
||||
}
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt) {
|
||||
switch(fmt) {
|
||||
// the default limit value works only right with YV12 right now.
|
||||
case IMGFMT_YV12:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//===========================================================================//
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->query_format=query_format;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
vf->priv->limit=24; // should be option
|
||||
vf->priv->round = 0;
|
||||
vf->priv->reset_count = 0;
|
||||
if(args) sscanf(args, "%d:%d:%d",
|
||||
&vf->priv->limit,
|
||||
&vf->priv->round,
|
||||
&vf->priv->reset_count);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_cropdetect = {
|
||||
"autodetect crop size",
|
||||
"cropdetect",
|
||||
"A'rpi",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
198
libavfilter/libmpcodecs/vf_decimate.c
Normal file
198
libavfilter/libmpcodecs/vf_decimate.c
Normal file
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
|
||||
struct vf_priv_s {
|
||||
int hi, lo;
|
||||
float frac;
|
||||
int max, last, cnt;
|
||||
};
|
||||
|
||||
#if HAVE_MMX && HAVE_EBX_AVAILABLE
|
||||
static int diff_MMX(unsigned char *old, unsigned char *new, int os, int ns)
|
||||
{
|
||||
volatile short out[4];
|
||||
__asm__ (
|
||||
"movl $8, %%ecx \n\t"
|
||||
"pxor %%mm4, %%mm4 \n\t"
|
||||
"pxor %%mm7, %%mm7 \n\t"
|
||||
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
|
||||
"movq (%%"REG_S"), %%mm0 \n\t"
|
||||
"movq (%%"REG_S"), %%mm2 \n\t"
|
||||
"add %%"REG_a", %%"REG_S" \n\t"
|
||||
"movq (%%"REG_D"), %%mm1 \n\t"
|
||||
"add %%"REG_b", %%"REG_D" \n\t"
|
||||
"psubusb %%mm1, %%mm2 \n\t"
|
||||
"psubusb %%mm0, %%mm1 \n\t"
|
||||
"movq %%mm2, %%mm0 \n\t"
|
||||
"movq %%mm1, %%mm3 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpcklbw %%mm7, %%mm1 \n\t"
|
||||
"punpckhbw %%mm7, %%mm2 \n\t"
|
||||
"punpckhbw %%mm7, %%mm3 \n\t"
|
||||
"paddw %%mm0, %%mm4 \n\t"
|
||||
"paddw %%mm1, %%mm4 \n\t"
|
||||
"paddw %%mm2, %%mm4 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
|
||||
"decl %%ecx \n\t"
|
||||
"jnz 1b \n\t"
|
||||
"movq %%mm4, (%%"REG_d") \n\t"
|
||||
"emms \n\t"
|
||||
:
|
||||
: "S" (old), "D" (new), "a" ((long)os), "b" ((long)ns), "d" (out)
|
||||
: "%ecx", "memory"
|
||||
);
|
||||
return out[0]+out[1]+out[2]+out[3];
|
||||
}
|
||||
#endif
|
||||
|
||||
static int diff_C(unsigned char *old, unsigned char *new, int os, int ns)
|
||||
{
|
||||
int x, y, d=0;
|
||||
for (y = 8; y; y--) {
|
||||
for (x = 8; x; x--) {
|
||||
d += abs(new[x] - old[x]);
|
||||
}
|
||||
new += ns;
|
||||
old += os;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
static int (*diff)(unsigned char *, unsigned char *, int, int);
|
||||
|
||||
static int diff_to_drop_plane(int hi, int lo, float frac, unsigned char *old, unsigned char *new, int w, int h, int os, int ns)
|
||||
{
|
||||
int x, y;
|
||||
int d, c=0;
|
||||
int t = (w/16)*(h/16)*frac;
|
||||
for (y = 0; y < h-7; y += 4) {
|
||||
for (x = 8; x < w-7; x += 4) {
|
||||
d = diff(old+x+y*os, new+x+y*ns, os, ns);
|
||||
if (d > hi) return 0;
|
||||
if (d > lo) {
|
||||
c++;
|
||||
if (c > t) return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int diff_to_drop(int hi, int lo, float frac, mp_image_t *old, mp_image_t *new)
|
||||
{
|
||||
if (new->flags & MP_IMGFLAG_PLANAR) {
|
||||
return diff_to_drop_plane(hi,lo,frac, old->planes[0], new->planes[0],
|
||||
new->w, new->h, old->stride[0], new->stride[0])
|
||||
&& diff_to_drop_plane(hi,lo,frac, old->planes[1], new->planes[1],
|
||||
new->chroma_width, new->chroma_height,
|
||||
old->stride[1], new->stride[1])
|
||||
&& diff_to_drop_plane(hi,lo,frac, old->planes[2], new->planes[2],
|
||||
new->chroma_width, new->chroma_height,
|
||||
old->stride[2], new->stride[2]);
|
||||
}
|
||||
return diff_to_drop_plane(hi,lo,frac, old->planes[0], new->planes[0],
|
||||
new->w*(new->bpp/8), new->h, old->stride[0], new->stride[0]);
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
mp_image_t *dmpi;
|
||||
|
||||
dmpi = vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
|
||||
MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE,
|
||||
mpi->width, mpi->height);
|
||||
dmpi->qscale = mpi->qscale;
|
||||
dmpi->qstride = mpi->qstride;
|
||||
dmpi->qscale_type = mpi->qscale_type;
|
||||
|
||||
if (diff_to_drop(vf->priv->hi, vf->priv->lo, vf->priv->frac, dmpi, mpi)) {
|
||||
if (vf->priv->max == 0)
|
||||
return 0;
|
||||
else if ((vf->priv->max > 0) && (vf->priv->cnt++ < vf->priv->max))
|
||||
return 0;
|
||||
else if ((vf->priv->max < 0) && (vf->priv->last+1 >= -vf->priv->max))
|
||||
return vf->priv->last=0;
|
||||
}
|
||||
vf->priv->last++;
|
||||
vf->priv->cnt=0;
|
||||
|
||||
memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
|
||||
dmpi->stride[0], mpi->stride[0]);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
memcpy_pic(dmpi->planes[1], mpi->planes[1],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[1], mpi->stride[1]);
|
||||
memcpy_pic(dmpi->planes[2], mpi->planes[2],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[2], mpi->stride[2]);
|
||||
}
|
||||
return vf_next_put_image(vf, dmpi, pts);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
struct vf_priv_s *p;
|
||||
vf->put_image = put_image;
|
||||
vf->uninit = uninit;
|
||||
vf->default_reqs = VFCAP_ACCEPT_STRIDE;
|
||||
vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
|
||||
p->max = 0;
|
||||
p->hi = 64*12;
|
||||
p->lo = 64*5;
|
||||
p->frac = 0.33;
|
||||
if (args) sscanf(args, "%d:%d:%d:%f", &p->max, &p->hi, &p->lo, &p->frac);
|
||||
diff = diff_C;
|
||||
#if HAVE_MMX && HAVE_EBX_AVAILABLE
|
||||
if(gCpuCaps.hasMMX) diff = diff_MMX;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_decimate = {
|
||||
"near-duplicate frame remover",
|
||||
"decimate",
|
||||
"Rich Felker",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
262
libavfilter/libmpcodecs/vf_delogo.c
Normal file
262
libavfilter/libmpcodecs/vf_delogo.c
Normal file
@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Jindrich Makovicka <makovick@gmail.com>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/* A very simple tv station logo remover */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
#include "m_option.h"
|
||||
#include "m_struct.h"
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static struct vf_priv_s {
|
||||
unsigned int outfmt;
|
||||
int xoff, yoff, lw, lh, band, show;
|
||||
} const vf_priv_dflt = {
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
static void delogo(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int width, int height,
|
||||
int logo_x, int logo_y, int logo_w, int logo_h, int band, int show, int direct) {
|
||||
int y, x;
|
||||
int interp, dist;
|
||||
uint8_t *xdst, *xsrc;
|
||||
|
||||
uint8_t *topleft, *botleft, *topright;
|
||||
int xclipl, xclipr, yclipt, yclipb;
|
||||
int logo_x1, logo_x2, logo_y1, logo_y2;
|
||||
|
||||
xclipl = MAX(-logo_x, 0);
|
||||
xclipr = MAX(logo_x+logo_w-width, 0);
|
||||
yclipt = MAX(-logo_y, 0);
|
||||
yclipb = MAX(logo_y+logo_h-height, 0);
|
||||
|
||||
logo_x1 = logo_x + xclipl;
|
||||
logo_x2 = logo_x + logo_w - xclipr;
|
||||
logo_y1 = logo_y + yclipt;
|
||||
logo_y2 = logo_y + logo_h - yclipb;
|
||||
|
||||
topleft = src+logo_y1*srcStride+logo_x1;
|
||||
topright = src+logo_y1*srcStride+logo_x2-1;
|
||||
botleft = src+(logo_y2-1)*srcStride+logo_x1;
|
||||
|
||||
if (!direct) memcpy_pic(dst, src, width, height, dstStride, srcStride);
|
||||
|
||||
dst += (logo_y1+1)*dstStride;
|
||||
src += (logo_y1+1)*srcStride;
|
||||
|
||||
for(y = logo_y1+1; y < logo_y2-1; y++)
|
||||
{
|
||||
for (x = logo_x1+1, xdst = dst+logo_x1+1, xsrc = src+logo_x1+1; x < logo_x2-1; x++, xdst++, xsrc++) {
|
||||
interp = ((topleft[srcStride*(y-logo_y-yclipt)]
|
||||
+ topleft[srcStride*(y-logo_y-1-yclipt)]
|
||||
+ topleft[srcStride*(y-logo_y+1-yclipt)])*(logo_w-(x-logo_x))/logo_w
|
||||
+ (topright[srcStride*(y-logo_y-yclipt)]
|
||||
+ topright[srcStride*(y-logo_y-1-yclipt)]
|
||||
+ topright[srcStride*(y-logo_y+1-yclipt)])*(x-logo_x)/logo_w
|
||||
+ (topleft[x-logo_x-xclipl]
|
||||
+ topleft[x-logo_x-1-xclipl]
|
||||
+ topleft[x-logo_x+1-xclipl])*(logo_h-(y-logo_y))/logo_h
|
||||
+ (botleft[x-logo_x-xclipl]
|
||||
+ botleft[x-logo_x-1-xclipl]
|
||||
+ botleft[x-logo_x+1-xclipl])*(y-logo_y)/logo_h
|
||||
)/6;
|
||||
/* interp = (topleft[srcStride*(y-logo_y)]*(logo_w-(x-logo_x))/logo_w
|
||||
+ topright[srcStride*(y-logo_y)]*(x-logo_x)/logo_w
|
||||
+ topleft[x-logo_x]*(logo_h-(y-logo_y))/logo_h
|
||||
+ botleft[x-logo_x]*(y-logo_y)/logo_h
|
||||
)/2;*/
|
||||
if (y >= logo_y+band && y < logo_y+logo_h-band && x >= logo_x+band && x < logo_x+logo_w-band) {
|
||||
*xdst = interp;
|
||||
} else {
|
||||
dist = 0;
|
||||
if (x < logo_x+band) dist = MAX(dist, logo_x-x+band);
|
||||
else if (x >= logo_x+logo_w-band) dist = MAX(dist, x-(logo_x+logo_w-1-band));
|
||||
if (y < logo_y+band) dist = MAX(dist, logo_y-y+band);
|
||||
else if (y >= logo_y+logo_h-band) dist = MAX(dist, y-(logo_y+logo_h-1-band));
|
||||
*xdst = (*xsrc*dist + interp*(band-dist))/band;
|
||||
if (show && (dist == band-1)) *xdst = 0;
|
||||
}
|
||||
}
|
||||
|
||||
dst+= dstStride;
|
||||
src+= srcStride;
|
||||
}
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
|
||||
static void get_image(struct vf_instance *vf, mp_image_t *mpi){
|
||||
if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
|
||||
if(mpi->imgfmt!=vf->priv->outfmt) return; // colorspace differ
|
||||
// ok, we can do pp in-place (or pp disabled):
|
||||
vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
mpi->type, mpi->flags, mpi->w, mpi->h);
|
||||
mpi->planes[0]=vf->dmpi->planes[0];
|
||||
mpi->stride[0]=vf->dmpi->stride[0];
|
||||
mpi->width=vf->dmpi->width;
|
||||
if(mpi->flags&MP_IMGFLAG_PLANAR){
|
||||
mpi->planes[1]=vf->dmpi->planes[1];
|
||||
mpi->planes[2]=vf->dmpi->planes[2];
|
||||
mpi->stride[1]=vf->dmpi->stride[1];
|
||||
mpi->stride[2]=vf->dmpi->stride[2];
|
||||
}
|
||||
mpi->flags|=MP_IMGFLAG_DIRECT;
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
|
||||
if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
|
||||
// no DR, so get a new image! hope we'll get DR buffer:
|
||||
vf->dmpi=vf_get_image(vf->next,vf->priv->outfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->w,mpi->h);
|
||||
}
|
||||
dmpi= vf->dmpi;
|
||||
|
||||
delogo(dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h,
|
||||
vf->priv->xoff, vf->priv->yoff, vf->priv->lw, vf->priv->lh, vf->priv->band, vf->priv->show,
|
||||
mpi->flags&MP_IMGFLAG_DIRECT);
|
||||
delogo(dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w/2, mpi->h/2,
|
||||
vf->priv->xoff/2, vf->priv->yoff/2, vf->priv->lw/2, vf->priv->lh/2, vf->priv->band/2, vf->priv->show,
|
||||
mpi->flags&MP_IMGFLAG_DIRECT);
|
||||
delogo(dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w/2, mpi->h/2,
|
||||
vf->priv->xoff/2, vf->priv->yoff/2, vf->priv->lw/2, vf->priv->lh/2, vf->priv->band/2, vf->priv->show,
|
||||
mpi->flags&MP_IMGFLAG_DIRECT);
|
||||
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf){
|
||||
if(!vf->priv) return;
|
||||
|
||||
free(vf->priv);
|
||||
vf->priv=NULL;
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
switch(fmt)
|
||||
{
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
return vf_next_query_format(vf,vf->priv->outfmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const unsigned int fmt_list[]={
|
||||
IMGFMT_YV12,
|
||||
IMGFMT_I420,
|
||||
IMGFMT_IYUV,
|
||||
0
|
||||
};
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->get_image=get_image;
|
||||
vf->query_format=query_format;
|
||||
vf->uninit=uninit;
|
||||
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, "delogo: %d x %d, %d x %d, band = %d\n",
|
||||
vf->priv->xoff, vf->priv->yoff,
|
||||
vf->priv->lw, vf->priv->lh,
|
||||
vf->priv->band);
|
||||
|
||||
vf->priv->show = 0;
|
||||
|
||||
if (vf->priv->band < 0) {
|
||||
vf->priv->band = 4;
|
||||
vf->priv->show = 1;
|
||||
}
|
||||
|
||||
|
||||
vf->priv->lw += vf->priv->band*2;
|
||||
vf->priv->lh += vf->priv->band*2;
|
||||
vf->priv->xoff -= vf->priv->band;
|
||||
vf->priv->yoff -= vf->priv->band;
|
||||
|
||||
// check csp:
|
||||
vf->priv->outfmt=vf_match_csp(&vf->next,fmt_list,IMGFMT_YV12);
|
||||
if(!vf->priv->outfmt)
|
||||
{
|
||||
uninit(vf);
|
||||
return 0; // no csp match :(
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define ST_OFF(f) M_ST_OFF(struct vf_priv_s,f)
|
||||
static const m_option_t vf_opts_fields[] = {
|
||||
{ "x", ST_OFF(xoff), CONF_TYPE_INT, 0, 0, 0, NULL },
|
||||
{ "y", ST_OFF(yoff), CONF_TYPE_INT, 0, 0, 0, NULL },
|
||||
{ "w", ST_OFF(lw), CONF_TYPE_INT, 0, 0, 0, NULL },
|
||||
{ "h", ST_OFF(lh), CONF_TYPE_INT, 0, 0, 0, NULL },
|
||||
{ "t", ST_OFF(band), CONF_TYPE_INT, 0, 0, 0, NULL },
|
||||
{ "band", ST_OFF(band), CONF_TYPE_INT, 0, 0, 0, NULL }, // alias
|
||||
{ NULL, NULL, 0, 0, 0, 0, NULL }
|
||||
};
|
||||
|
||||
static const m_struct_t vf_opts = {
|
||||
"delogo",
|
||||
sizeof(struct vf_priv_s),
|
||||
&vf_priv_dflt,
|
||||
vf_opts_fields
|
||||
};
|
||||
|
||||
const vf_info_t vf_info_delogo = {
|
||||
"simple logo remover",
|
||||
"delogo",
|
||||
"Jindrich Makovicka, Alex Beregszaszi",
|
||||
"",
|
||||
vf_open,
|
||||
&vf_opts
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
268
libavfilter/libmpcodecs/vf_denoise3d.c
Normal file
268
libavfilter/libmpcodecs/vf_denoise3d.c
Normal file
@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Copyright (C) 2003 Daniel Moreno <comac@comac.darktech.org>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "mp_msg.h"
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#define PARAM1_DEFAULT 4.0
|
||||
#define PARAM2_DEFAULT 3.0
|
||||
#define PARAM3_DEFAULT 6.0
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
struct vf_priv_s {
|
||||
int Coefs[4][512];
|
||||
unsigned char *Line;
|
||||
mp_image_t *pmpi;
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
|
||||
free(vf->priv->Line);
|
||||
vf->priv->Line = malloc(width);
|
||||
vf->priv->pmpi=NULL;
|
||||
// vf->default_caps &= !VFCAP_ACCEPT_STRIDE;
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
free(vf->priv->Line);
|
||||
}
|
||||
|
||||
#define LowPass(Prev, Curr, Coef) (Curr + Coef[Prev - Curr])
|
||||
|
||||
static void deNoise(unsigned char *Frame, // mpi->planes[x]
|
||||
unsigned char *FramePrev, // pmpi->planes[x]
|
||||
unsigned char *FrameDest, // dmpi->planes[x]
|
||||
unsigned char *LineAnt, // vf->priv->Line (width bytes)
|
||||
int W, int H, int sStride, int pStride, int dStride,
|
||||
int *Horizontal, int *Vertical, int *Temporal)
|
||||
{
|
||||
int X, Y;
|
||||
int sLineOffs = 0, pLineOffs = 0, dLineOffs = 0;
|
||||
unsigned char PixelAnt;
|
||||
|
||||
/* First pixel has no left nor top neighbor. Only previous frame */
|
||||
LineAnt[0] = PixelAnt = Frame[0];
|
||||
FrameDest[0] = LowPass(FramePrev[0], LineAnt[0], Temporal);
|
||||
|
||||
/* Fist line has no top neighbor. Only left one for each pixel and
|
||||
* last frame */
|
||||
for (X = 1; X < W; X++)
|
||||
{
|
||||
PixelAnt = LowPass(PixelAnt, Frame[X], Horizontal);
|
||||
LineAnt[X] = PixelAnt;
|
||||
FrameDest[X] = LowPass(FramePrev[X], LineAnt[X], Temporal);
|
||||
}
|
||||
|
||||
for (Y = 1; Y < H; Y++)
|
||||
{
|
||||
sLineOffs += sStride, pLineOffs += pStride, dLineOffs += dStride;
|
||||
/* First pixel on each line doesn't have previous pixel */
|
||||
PixelAnt = Frame[sLineOffs];
|
||||
LineAnt[0] = LowPass(LineAnt[0], PixelAnt, Vertical);
|
||||
FrameDest[dLineOffs] = LowPass(FramePrev[pLineOffs], LineAnt[0], Temporal);
|
||||
|
||||
for (X = 1; X < W; X++)
|
||||
{
|
||||
/* The rest are normal */
|
||||
PixelAnt = LowPass(PixelAnt, Frame[sLineOffs+X], Horizontal);
|
||||
LineAnt[X] = LowPass(LineAnt[X], PixelAnt, Vertical);
|
||||
FrameDest[dLineOffs+X] = LowPass(FramePrev[pLineOffs+X], LineAnt[X], Temporal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
int cw= mpi->w >> mpi->chroma_x_shift;
|
||||
int ch= mpi->h >> mpi->chroma_y_shift;
|
||||
int W = mpi->w, H = mpi->h;
|
||||
|
||||
mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_IP, MP_IMGFLAG_ACCEPT_STRIDE |
|
||||
MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE,
|
||||
mpi->w,mpi->h);
|
||||
|
||||
if(!dmpi) return 0;
|
||||
if (!vf->priv->pmpi) vf->priv->pmpi=mpi;
|
||||
|
||||
deNoise(mpi->planes[0], vf->priv->pmpi->planes[0], dmpi->planes[0],
|
||||
vf->priv->Line, W, H,
|
||||
mpi->stride[0], vf->priv->pmpi->stride[0], dmpi->stride[0],
|
||||
vf->priv->Coefs[0] + 256,
|
||||
vf->priv->Coefs[0] + 256,
|
||||
vf->priv->Coefs[1] + 256);
|
||||
deNoise(mpi->planes[1], vf->priv->pmpi->planes[1], dmpi->planes[1],
|
||||
vf->priv->Line, cw, ch,
|
||||
mpi->stride[1], vf->priv->pmpi->stride[1], dmpi->stride[1],
|
||||
vf->priv->Coefs[2] + 256,
|
||||
vf->priv->Coefs[2] + 256,
|
||||
vf->priv->Coefs[3] + 256);
|
||||
deNoise(mpi->planes[2], vf->priv->pmpi->planes[2], dmpi->planes[2],
|
||||
vf->priv->Line, cw, ch,
|
||||
mpi->stride[2], vf->priv->pmpi->stride[2], dmpi->stride[2],
|
||||
vf->priv->Coefs[2] + 256,
|
||||
vf->priv->Coefs[2] + 256,
|
||||
vf->priv->Coefs[3] + 256);
|
||||
|
||||
vf->priv->pmpi=dmpi; // save reference image
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
switch(fmt)
|
||||
{
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define ABS(A) ( (A) > 0 ? (A) : -(A) )
|
||||
|
||||
static void PrecalcCoefs(int *Ct, double Dist25)
|
||||
{
|
||||
int i;
|
||||
double Gamma, Simil, C;
|
||||
|
||||
Gamma = log(0.25) / log(1.0 - Dist25/255.0);
|
||||
|
||||
for (i = -256; i <= 255; i++)
|
||||
{
|
||||
Simil = 1.0 - ABS(i) / 255.0;
|
||||
// Ct[256+i] = lround(pow(Simil, Gamma) * (double)i);
|
||||
C = pow(Simil, Gamma) * (double)i;
|
||||
Ct[256+i] = (C<0) ? (C-0.5) : (C+0.5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
double LumSpac, LumTmp, ChromSpac, ChromTmp;
|
||||
double Param1, Param2, Param3;
|
||||
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->query_format=query_format;
|
||||
vf->uninit=uninit;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
|
||||
if (args)
|
||||
{
|
||||
switch(sscanf(args, "%lf:%lf:%lf",
|
||||
&Param1, &Param2, &Param3
|
||||
))
|
||||
{
|
||||
case 0:
|
||||
LumSpac = PARAM1_DEFAULT;
|
||||
LumTmp = PARAM3_DEFAULT;
|
||||
|
||||
ChromSpac = PARAM2_DEFAULT;
|
||||
ChromTmp = LumTmp * ChromSpac / LumSpac;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
LumSpac = Param1;
|
||||
LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
|
||||
|
||||
ChromSpac = PARAM2_DEFAULT * Param1 / PARAM1_DEFAULT;
|
||||
ChromTmp = LumTmp * ChromSpac / LumSpac;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
LumSpac = Param1;
|
||||
LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
|
||||
|
||||
ChromSpac = Param2;
|
||||
ChromTmp = LumTmp * ChromSpac / LumSpac;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
LumSpac = Param1;
|
||||
LumTmp = Param3;
|
||||
|
||||
ChromSpac = Param2;
|
||||
ChromTmp = LumTmp * ChromSpac / LumSpac;
|
||||
break;
|
||||
|
||||
default:
|
||||
LumSpac = PARAM1_DEFAULT;
|
||||
LumTmp = PARAM3_DEFAULT;
|
||||
|
||||
ChromSpac = PARAM2_DEFAULT;
|
||||
ChromTmp = LumTmp * ChromSpac / LumSpac;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LumSpac = PARAM1_DEFAULT;
|
||||
LumTmp = PARAM3_DEFAULT;
|
||||
|
||||
ChromSpac = PARAM2_DEFAULT;
|
||||
ChromTmp = LumTmp * ChromSpac / LumSpac;
|
||||
}
|
||||
|
||||
PrecalcCoefs(vf->priv->Coefs[0], LumSpac);
|
||||
PrecalcCoefs(vf->priv->Coefs[1], LumTmp);
|
||||
PrecalcCoefs(vf->priv->Coefs[2], ChromSpac);
|
||||
PrecalcCoefs(vf->priv->Coefs[3], ChromTmp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_denoise3d = {
|
||||
"3D Denoiser (variable lowpass filter)",
|
||||
"denoise3d",
|
||||
"Daniel Moreno",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
453
libavfilter/libmpcodecs/vf_detc.c
Normal file
453
libavfilter/libmpcodecs/vf_detc.c
Normal file
@ -0,0 +1,453 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
struct metrics {
|
||||
int even;
|
||||
int odd;
|
||||
int noise;
|
||||
int temp;
|
||||
};
|
||||
|
||||
struct vf_priv_s {
|
||||
int frame;
|
||||
int drop, lastdrop;
|
||||
struct metrics pm;
|
||||
int thres[5];
|
||||
int inframes, outframes;
|
||||
int mode;
|
||||
int (*analyze)(struct vf_priv_s *, mp_image_t *, mp_image_t *);
|
||||
int needread;
|
||||
};
|
||||
|
||||
#define COMPE(a,b,e) (abs((a)-(b)) < (((a)+(b))>>(e)))
|
||||
#define COMPARABLE(a,b) COMPE((a),(b),2)
|
||||
#define VERYCLOSE(a,b) COMPE((a),(b),3)
|
||||
|
||||
#define OUTER_TC_NBHD(s) ( \
|
||||
COMPARABLE((s)[-1].m.even,(s)[-1].m.odd) && \
|
||||
COMPARABLE((s)[1].m.even,(s)[0].m.odd) && \
|
||||
COMPARABLE((s)[2].m.even,(s)[1].m.odd) && \
|
||||
COMPARABLE((s)[-1].m.noise,(s)[0].m.temp) && \
|
||||
COMPARABLE((s)[2].m.noise,(s)[2].m.temp) )
|
||||
|
||||
#define INNER_TC_NBHD(s,l,h) ( \
|
||||
COMPARABLE((s)[0].m.even,(l)) && \
|
||||
COMPARABLE((s)[2].m.odd,(l)) && ( \
|
||||
COMPARABLE((s)[0].m.noise,(h)) || \
|
||||
COMPARABLE((s)[1].m.noise,(h)) ) )
|
||||
|
||||
enum {
|
||||
TC_DROP,
|
||||
TC_PROG,
|
||||
TC_IL1,
|
||||
TC_IL2
|
||||
};
|
||||
|
||||
static void block_diffs(struct metrics *m, unsigned char *old, unsigned char *new, int os, int ns)
|
||||
{
|
||||
int x, y, even=0, odd=0, noise, temp;
|
||||
unsigned char *oldp, *newp;
|
||||
m->noise = m->temp = 0;
|
||||
for (x = 8; x; x--) {
|
||||
oldp = old++;
|
||||
newp = new++;
|
||||
noise = temp = 0;
|
||||
for (y = 4; y; y--) {
|
||||
even += abs(newp[0]-oldp[0]);
|
||||
odd += abs(newp[ns]-oldp[os]);
|
||||
noise += newp[ns]-newp[0];
|
||||
temp += oldp[os]-newp[0];
|
||||
oldp += os<<1;
|
||||
newp += ns<<1;
|
||||
}
|
||||
m->noise += abs(noise);
|
||||
m->temp += abs(temp);
|
||||
}
|
||||
m->even = even;
|
||||
m->odd = odd;
|
||||
}
|
||||
|
||||
static void diff_planes(struct metrics *m, unsigned char *old, unsigned char *new, int w, int h, int os, int ns)
|
||||
{
|
||||
int x, y, me=0, mo=0, mn=0, mt=0;
|
||||
struct metrics l;
|
||||
for (y = 0; y < h-7; y += 8) {
|
||||
for (x = 0; x < w-7; x += 8) {
|
||||
block_diffs(&l, old+x+y*os, new+x+y*ns, os, ns);
|
||||
if (l.even > me) me = l.even;
|
||||
if (l.odd > mo) mo = l.odd;
|
||||
if (l.noise > mn) mn = l.noise;
|
||||
if (l.temp > mt) mt = l.temp;
|
||||
}
|
||||
}
|
||||
m->even = me;
|
||||
m->odd = mo;
|
||||
m->noise = mn;
|
||||
m->temp = mt;
|
||||
}
|
||||
|
||||
static void diff_fields(struct metrics *metr, mp_image_t *old, mp_image_t *new)
|
||||
{
|
||||
struct metrics m, mu, mv;
|
||||
diff_planes(&m, old->planes[0], new->planes[0],
|
||||
new->w, new->h, old->stride[0], new->stride[0]);
|
||||
if (new->flags & MP_IMGFLAG_PLANAR) {
|
||||
diff_planes(&mu, old->planes[1], new->planes[1],
|
||||
new->chroma_width, new->chroma_height,
|
||||
old->stride[1], new->stride[1]);
|
||||
diff_planes(&mv, old->planes[2], new->planes[2],
|
||||
new->chroma_width, new->chroma_height,
|
||||
old->stride[2], new->stride[2]);
|
||||
if (mu.even > m.even) m.even = mu.even;
|
||||
if (mu.odd > m.odd) m.odd = mu.odd;
|
||||
if (mu.noise > m.noise) m.noise = mu.noise;
|
||||
if (mu.temp > m.temp) m.temp = mu.temp;
|
||||
if (mv.even > m.even) m.even = mv.even;
|
||||
if (mv.odd > m.odd) m.odd = mv.odd;
|
||||
if (mv.noise > m.noise) m.noise = mv.noise;
|
||||
if (mv.temp > m.temp) m.temp = mv.temp;
|
||||
}
|
||||
*metr = m;
|
||||
}
|
||||
|
||||
static void status(int f, struct metrics *m)
|
||||
{
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, "frame %d: e=%d o=%d n=%d t=%d\n",
|
||||
f, m->even, m->odd, m->noise, m->temp);
|
||||
}
|
||||
|
||||
static int analyze_fixed_pattern(struct vf_priv_s *p, mp_image_t *new, mp_image_t *old)
|
||||
{
|
||||
if (p->frame >= 0) p->frame = (p->frame+1)%5;
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, "frame %d\n", p->frame);
|
||||
switch (p->frame) {
|
||||
case -1: case 0: case 1: case 2:
|
||||
return TC_PROG;
|
||||
case 3:
|
||||
return TC_IL1;
|
||||
case 4:
|
||||
return TC_IL2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int analyze_aggressive(struct vf_priv_s *p, mp_image_t *new, mp_image_t *old)
|
||||
{
|
||||
struct metrics m, pm;
|
||||
|
||||
if (p->frame >= 0) p->frame = (p->frame+1)%5;
|
||||
|
||||
diff_fields(&m, old, new);
|
||||
|
||||
status(p->frame, &m);
|
||||
|
||||
pm = p->pm;
|
||||
p->pm = m;
|
||||
|
||||
if (p->frame == 4) {
|
||||
/* We need to break at scene changes, but is this a valid test? */
|
||||
if ((m.even > p->thres[2]) && (m.odd > p->thres[2]) && (m.temp > p->thres[3])
|
||||
&& (m.temp > 5*pm.temp) && (m.temp*2 > m.noise)) {
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, "scene change breaking telecine!\n");
|
||||
p->frame = -1;
|
||||
return TC_DROP;
|
||||
}
|
||||
/* Thres. is to compensate for quantization errors when noise is low */
|
||||
if (m.noise - m.temp > -p->thres[4]) {
|
||||
if (COMPARABLE(m.even, pm.odd)) {
|
||||
//mp_msg(MSGT_VFILTER, MSGL_V, "confirmed field match!\n");
|
||||
return TC_IL2;
|
||||
} else if ((m.even < p->thres[0]) && (m.odd < p->thres[0]) && VERYCLOSE(m.even, m.odd)
|
||||
&& VERYCLOSE(m.noise,m.temp) && VERYCLOSE(m.noise,pm.noise)) {
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, "interlaced frame appears in duplicate!!!\n");
|
||||
p->pm = pm; /* hack :) */
|
||||
p->frame = 3;
|
||||
return TC_IL1;
|
||||
}
|
||||
} else {
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, "mismatched telecine fields!\n");
|
||||
p->frame = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (2*m.even*m.temp < m.odd*m.noise) {
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, "caught telecine sync!\n");
|
||||
p->frame = 3;
|
||||
return TC_IL1;
|
||||
}
|
||||
|
||||
if (p->frame < 3) {
|
||||
if (m.noise > p->thres[3]) {
|
||||
if (m.noise > 2*m.temp) {
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, "merging fields out of sequence!\n");
|
||||
return TC_IL2;
|
||||
}
|
||||
if ((m.noise > 2*pm.noise) && (m.even > p->thres[2]) && (m.odd > p->thres[2])) {
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, "dropping horrible interlaced frame!\n");
|
||||
return TC_DROP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (p->frame) {
|
||||
case -1:
|
||||
if (4*m.noise > 5*m.temp) {
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, "merging fields out of sequence!\n");
|
||||
return TC_IL2;
|
||||
}
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
return TC_PROG;
|
||||
case 3:
|
||||
if ((m.even > p->thres[1]) && (m.even > m.odd) && (m.temp > m.noise)) {
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, "lost telecine tracking!\n");
|
||||
p->frame = -1;
|
||||
return TC_PROG;
|
||||
}
|
||||
return TC_IL1;
|
||||
case 4:
|
||||
return TC_IL2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void copy_image(mp_image_t *dmpi, mp_image_t *mpi, int field)
|
||||
{
|
||||
switch (field) {
|
||||
case 0:
|
||||
my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2,
|
||||
dmpi->stride[0]*2, mpi->stride[0]*2);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
my_memcpy_pic(dmpi->planes[1], mpi->planes[1],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[1]*2, mpi->stride[1]*2);
|
||||
my_memcpy_pic(dmpi->planes[2], mpi->planes[2],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[2]*2, mpi->stride[2]*2);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
|
||||
mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2,
|
||||
dmpi->stride[0]*2, mpi->stride[0]*2);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
|
||||
mpi->planes[1]+mpi->stride[1],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[1]*2, mpi->stride[1]*2);
|
||||
my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
|
||||
mpi->planes[2]+mpi->stride[2],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[2]*2, mpi->stride[2]*2);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
|
||||
dmpi->stride[0], mpi->stride[0]);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
memcpy_pic(dmpi->planes[1], mpi->planes[1],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[1], mpi->stride[1]);
|
||||
memcpy_pic(dmpi->planes[2], mpi->planes[2],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[2], mpi->stride[2]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int do_put_image(struct vf_instance *vf, mp_image_t *dmpi)
|
||||
{
|
||||
struct vf_priv_s *p = vf->priv;
|
||||
int dropflag;
|
||||
|
||||
switch (p->drop) {
|
||||
default:
|
||||
dropflag = 0;
|
||||
break;
|
||||
case 1:
|
||||
dropflag = (++p->lastdrop >= 5);
|
||||
break;
|
||||
case 2:
|
||||
dropflag = (++p->lastdrop >= 5) && (4*p->inframes <= 5*p->outframes);
|
||||
break;
|
||||
}
|
||||
|
||||
if (dropflag) {
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, "drop! [%d/%d=%g]\n",
|
||||
p->outframes, p->inframes, (float)p->outframes/p->inframes);
|
||||
p->lastdrop = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
p->outframes++;
|
||||
return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
int ret=0;
|
||||
mp_image_t *dmpi;
|
||||
struct vf_priv_s *p = vf->priv;
|
||||
|
||||
p->inframes++;
|
||||
|
||||
if (p->needread) dmpi = vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
|
||||
MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE,
|
||||
mpi->width, mpi->height);
|
||||
/* FIXME: is there a good way to get rid of static type? */
|
||||
else dmpi = vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
|
||||
MP_IMGFLAG_PRESERVE, mpi->width, mpi->height);
|
||||
|
||||
switch (p->analyze(p, mpi, dmpi)) {
|
||||
case TC_DROP:
|
||||
/* Don't copy anything unless we'll need to read it. */
|
||||
if (p->needread) copy_image(dmpi, mpi, 2);
|
||||
p->lastdrop = 0;
|
||||
break;
|
||||
case TC_PROG:
|
||||
/* Copy and display the whole frame. */
|
||||
copy_image(dmpi, mpi, 2);
|
||||
ret = do_put_image(vf, dmpi);
|
||||
break;
|
||||
case TC_IL1:
|
||||
/* Only copy bottom field unless we need to read. */
|
||||
if (p->needread) copy_image(dmpi, mpi, 2);
|
||||
else copy_image(dmpi, mpi, 1);
|
||||
p->lastdrop = 0;
|
||||
break;
|
||||
case TC_IL2:
|
||||
/* Copy top field and show frame, then copy bottom if needed. */
|
||||
copy_image(dmpi, mpi, 0);
|
||||
ret = do_put_image(vf, dmpi);
|
||||
if (p->needread) copy_image(dmpi, mpi, 1);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt)
|
||||
{
|
||||
/* FIXME - figure out which other formats work */
|
||||
switch (fmt) {
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_I420:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt)
|
||||
{
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
int (*func)(struct vf_priv_s *p, mp_image_t *new, mp_image_t *old);
|
||||
int needread;
|
||||
} anal_funcs[] = {
|
||||
{ "fixed", analyze_fixed_pattern, 0 },
|
||||
{ "aggressive", analyze_aggressive, 1 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
#define STARTVARS if (0)
|
||||
#define GETVAR(str, name, out, func) \
|
||||
else if (!strncmp((str), name "=", sizeof(name))) \
|
||||
(out) = (func)((str) + sizeof(name))
|
||||
|
||||
static void parse_var(struct vf_priv_s *p, char *var)
|
||||
{
|
||||
STARTVARS;
|
||||
GETVAR(var, "dr", p->drop, atoi);
|
||||
GETVAR(var, "t0", p->thres[0], atoi);
|
||||
GETVAR(var, "t1", p->thres[1], atoi);
|
||||
GETVAR(var, "t2", p->thres[2], atoi);
|
||||
GETVAR(var, "t3", p->thres[3], atoi);
|
||||
GETVAR(var, "t4", p->thres[4], atoi);
|
||||
GETVAR(var, "fr", p->frame, atoi);
|
||||
GETVAR(var, "am", p->mode, atoi);
|
||||
}
|
||||
|
||||
static void parse_args(struct vf_priv_s *p, char *args)
|
||||
{
|
||||
char *next, *orig;
|
||||
for (args=orig=strdup(args); args; args=next) {
|
||||
next = strchr(args, ':');
|
||||
if (next) *next++ = 0;
|
||||
parse_var(p, args);
|
||||
}
|
||||
free(orig);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
struct vf_priv_s *p;
|
||||
vf->config = config;
|
||||
vf->put_image = put_image;
|
||||
vf->query_format = query_format;
|
||||
vf->uninit = uninit;
|
||||
vf->default_reqs = VFCAP_ACCEPT_STRIDE;
|
||||
vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
|
||||
p->frame = -1;
|
||||
p->thres[0] = 440;
|
||||
p->thres[1] = 720;
|
||||
p->thres[2] = 2500;
|
||||
p->thres[3] = 2500;
|
||||
p->thres[4] = 800;
|
||||
p->drop = 0;
|
||||
p->mode = 1;
|
||||
if (args) parse_args(p, args);
|
||||
p->analyze = anal_funcs[p->mode].func;
|
||||
p->needread = anal_funcs[p->mode].needread;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_detc = {
|
||||
"de-telecine filter",
|
||||
"detc",
|
||||
"Rich Felker",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
214
libavfilter/libmpcodecs/vf_dint.c
Normal file
214
libavfilter/libmpcodecs/vf_dint.c
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "mp_image.h"
|
||||
#include "img_format.h"
|
||||
#include "vf.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
float sense; // first parameter
|
||||
float level; // second parameter
|
||||
unsigned int imgfmt;
|
||||
char diff;
|
||||
uint32_t max;
|
||||
// int dfr;
|
||||
// int rdfr;
|
||||
int was_dint;
|
||||
mp_image_t *pmpi; // previous mpi
|
||||
};
|
||||
|
||||
#define MAXROWSIZE 1200
|
||||
|
||||
static int config (struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt)
|
||||
{
|
||||
int rowsize;
|
||||
|
||||
vf->priv->pmpi = vf_get_image (vf->next, outfmt, MP_IMGTYPE_TEMP,
|
||||
0, width, height);
|
||||
if (!(vf->priv->pmpi->flags & MP_IMGFLAG_PLANAR) &&
|
||||
outfmt != IMGFMT_RGB32 && outfmt != IMGFMT_BGR32 &&
|
||||
outfmt != IMGFMT_RGB24 && outfmt != IMGFMT_BGR24 &&
|
||||
outfmt != IMGFMT_RGB16 && outfmt != IMGFMT_BGR16)
|
||||
{
|
||||
mp_msg (MSGT_VFILTER, MSGL_WARN, "Drop-interlaced filter doesn't support this outfmt :(\n");
|
||||
return 0;
|
||||
}
|
||||
vf->priv->imgfmt = outfmt;
|
||||
// recalculate internal values
|
||||
rowsize = vf->priv->pmpi->width;
|
||||
if (rowsize > MAXROWSIZE) rowsize = MAXROWSIZE;
|
||||
vf->priv->max = vf->priv->level * vf->priv->pmpi->height * rowsize / 2;
|
||||
if (vf->priv->pmpi->flags & MP_IMGFLAG_PLANAR) // planar YUV
|
||||
vf->priv->diff = vf->priv->sense * 256;
|
||||
else
|
||||
vf->priv->diff = vf->priv->sense * (1 << (vf->priv->pmpi->bpp/3));
|
||||
if (vf->priv->diff < 0) vf->priv->diff = 0;
|
||||
if (!(vf->priv->pmpi->flags & MP_IMGFLAG_PLANAR) &&
|
||||
vf->priv->pmpi->bpp < 24 && vf->priv->diff > 31)
|
||||
vf->priv->diff = 31;
|
||||
mp_msg (MSGT_VFILTER, MSGL_INFO, "Drop-interlaced: %dx%d diff %d / level %u\n",
|
||||
vf->priv->pmpi->width, vf->priv->pmpi->height,
|
||||
(int)vf->priv->diff, (unsigned int)vf->priv->max);
|
||||
// vf->priv->rdfr = vf->priv->dfr = 0;
|
||||
vf->priv->was_dint = 0;
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static int put_image (struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
char rrow0[MAXROWSIZE];
|
||||
char rrow1[MAXROWSIZE];
|
||||
char rrow2[MAXROWSIZE];
|
||||
char *row0 = rrow0, *row1 = rrow1, *row2 = rrow2/*, *row3 = rrow3*/;
|
||||
int rowsize = mpi->width;
|
||||
uint32_t nok = 0, max = vf->priv->max;
|
||||
int diff = vf->priv->diff;
|
||||
int i, j;
|
||||
register int n1, n2;
|
||||
unsigned char *cur0, *prv0;
|
||||
register unsigned char *cur, *prv;
|
||||
|
||||
if (rowsize > MAXROWSIZE) rowsize = MAXROWSIZE;
|
||||
// check if nothing to do
|
||||
if (mpi->imgfmt == vf->priv->imgfmt)
|
||||
{
|
||||
cur0 = mpi->planes[0] + mpi->stride[0];
|
||||
prv0 = mpi->planes[0];
|
||||
for (j = 1; j < mpi->height && nok <= max; j++)
|
||||
{
|
||||
cur = cur0;
|
||||
prv = prv0;
|
||||
// analyse row (row0)
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) // planar YUV - check luminance
|
||||
for (i = 0; i < rowsize; i++)
|
||||
{
|
||||
if (cur[0] - prv[0] > diff)
|
||||
row0[i] = 1;
|
||||
else if (cur[0] - prv[0] < -diff)
|
||||
row0[i] = -1;
|
||||
else
|
||||
row0[i] = 0;
|
||||
cur++;
|
||||
prv++;
|
||||
// check if row0 is 1 but row1 is 0, and row2 is 1 or row2 is 0
|
||||
// but row3 is 1 so it's interlaced ptr (nok++)
|
||||
if (j > 2 && row0[i] > 0 && (row1[i] < 0 || (!row1[i] && row2[i] < 0)) &&
|
||||
(++nok) > max)
|
||||
break;
|
||||
}
|
||||
else if (mpi->bpp < 24) // RGB/BGR 16 - check all colors
|
||||
for (i = 0; i < rowsize; i++)
|
||||
{
|
||||
n1 = cur[0] + (cur[1]<<8);
|
||||
n2 = prv[0] + (prv[1]<<8);
|
||||
if ((n1&0x1f) - (n2&0x1f) > diff ||
|
||||
((n1>>5)&0x3f) - ((n2>>5)&0x3f) > diff ||
|
||||
((n1>>11)&0x1f) - ((n2>>11)&0x1f) > diff)
|
||||
row0[i] = 1;
|
||||
else if ((n1&0x1f) - (n2&0x1f) < -diff ||
|
||||
((n1>>5)&0x3f) - ((n2>>5)&0x3f) < -diff ||
|
||||
((n1>>11)&0x1f) - ((n2>>11)&0x1f) < -diff)
|
||||
row0[i] = -1;
|
||||
else
|
||||
row0[i] = 0;
|
||||
cur += 2;
|
||||
prv += 2;
|
||||
// check if row0 is 1 but row1 is 0, and row2 is 1 or row2 is 0
|
||||
// but row3 is 1 so it's interlaced ptr (nok++)
|
||||
if (j > 2 && row0[i] > 0 && (row1[i] < 0 || (!row1[i] && row2[i] < 0)) &&
|
||||
(++nok) > max)
|
||||
break;
|
||||
}
|
||||
else // RGB/BGR 24/32
|
||||
for (i = 0; i < rowsize; i++)
|
||||
{
|
||||
if (cur[0] - prv[0] > diff ||
|
||||
cur[1] - prv[1] > diff ||
|
||||
cur[2] - prv[2] > diff)
|
||||
row0[i] = 1;
|
||||
else if (prv[0] - cur[0] > diff ||
|
||||
prv[1] - cur[1] > diff ||
|
||||
prv[2] - cur[2] > diff)
|
||||
row0[i] = -1;
|
||||
else
|
||||
row0[i] = 0;
|
||||
cur += mpi->bpp/8;
|
||||
prv += mpi->bpp/8;
|
||||
// check if row0 is 1 but row1 is 0, and row2 is 1 or row2 is 0
|
||||
// but row3 is 1 so it's interlaced ptr (nok++)
|
||||
if (j > 2 && row0[i] > 0 && (row1[i] < 0 || (!row1[i] && row2[i] < 0)) &&
|
||||
(++nok) > max)
|
||||
break;
|
||||
}
|
||||
cur0 += mpi->stride[0];
|
||||
prv0 += mpi->stride[0];
|
||||
// rotate rows
|
||||
cur = row2;
|
||||
row2 = row1;
|
||||
row1 = row0;
|
||||
row0 = cur;
|
||||
}
|
||||
}
|
||||
// check if number of interlaced is above of max
|
||||
if (nok > max)
|
||||
{
|
||||
// vf->priv->dfr++;
|
||||
if (vf->priv->was_dint < 1) // can skip at most one frame!
|
||||
{
|
||||
vf->priv->was_dint++;
|
||||
// vf->priv->rdfr++;
|
||||
// mp_msg (MSGT_VFILTER, MSGL_INFO, "DI:%d/%d ", vf->priv->rdfr, vf->priv->dfr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
vf->priv->was_dint = 0;
|
||||
// mp_msg (MSGT_VFILTER, MSGL_INFO, "DI:%d/%d ", vf->priv->rdfr, vf->priv->dfr);
|
||||
return vf_next_put_image (vf, mpi, pts);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
vf->config = config;
|
||||
vf->put_image = put_image;
|
||||
// vf->default_reqs=VFCAP_ACCEPT_STRIDE;
|
||||
vf->priv = malloc (sizeof(struct vf_priv_s));
|
||||
vf->priv->sense = 0.1;
|
||||
vf->priv->level = 0.15;
|
||||
vf->priv->pmpi = NULL;
|
||||
if (args)
|
||||
sscanf (args, "%f:%f", &vf->priv->sense, &vf->priv->level);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_dint = {
|
||||
"drop interlaced frames",
|
||||
"dint",
|
||||
"A.G.",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
720
libavfilter/libmpcodecs/vf_divtc.c
Normal file
720
libavfilter/libmpcodecs/vf_divtc.c
Normal file
@ -0,0 +1,720 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
#include "libavutil/common.h"
|
||||
#include "mpbswap.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
const vf_info_t vf_info_divtc;
|
||||
|
||||
struct vf_priv_s
|
||||
{
|
||||
int deghost, pass, phase, window, fcount, bcount, frameno, misscount,
|
||||
ocount, sum[5];
|
||||
double threshold;
|
||||
FILE *file;
|
||||
char *bdata;
|
||||
unsigned int *csdata;
|
||||
int *history;
|
||||
};
|
||||
|
||||
/*
|
||||
* diff_MMX and diff_C stolen from vf_decimate.c
|
||||
*/
|
||||
|
||||
#if HAVE_MMX && HAVE_EBX_AVAILABLE
|
||||
static int diff_MMX(unsigned char *old, unsigned char *new, int os, int ns)
|
||||
{
|
||||
volatile short out[4];
|
||||
__asm__ (
|
||||
"movl $8, %%ecx \n\t"
|
||||
"pxor %%mm4, %%mm4 \n\t"
|
||||
"pxor %%mm7, %%mm7 \n\t"
|
||||
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
|
||||
"movq (%%"REG_S"), %%mm0 \n\t"
|
||||
"movq (%%"REG_S"), %%mm2 \n\t"
|
||||
"add %%"REG_a", %%"REG_S" \n\t"
|
||||
"movq (%%"REG_D"), %%mm1 \n\t"
|
||||
"add %%"REG_b", %%"REG_D" \n\t"
|
||||
"psubusb %%mm1, %%mm2 \n\t"
|
||||
"psubusb %%mm0, %%mm1 \n\t"
|
||||
"movq %%mm2, %%mm0 \n\t"
|
||||
"movq %%mm1, %%mm3 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpcklbw %%mm7, %%mm1 \n\t"
|
||||
"punpckhbw %%mm7, %%mm2 \n\t"
|
||||
"punpckhbw %%mm7, %%mm3 \n\t"
|
||||
"paddw %%mm0, %%mm4 \n\t"
|
||||
"paddw %%mm1, %%mm4 \n\t"
|
||||
"paddw %%mm2, %%mm4 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
|
||||
"decl %%ecx \n\t"
|
||||
"jnz 1b \n\t"
|
||||
"movq %%mm4, (%%"REG_d") \n\t"
|
||||
"emms \n\t"
|
||||
:
|
||||
: "S" (old), "D" (new), "a" ((long)os), "b" ((long)ns), "d" (out)
|
||||
: "%ecx", "memory"
|
||||
);
|
||||
return out[0]+out[1]+out[2]+out[3];
|
||||
}
|
||||
#endif
|
||||
|
||||
static int diff_C(unsigned char *old, unsigned char *new, int os, int ns)
|
||||
{
|
||||
int x, y, d=0;
|
||||
|
||||
for(y=8; y; y--, new+=ns, old+=os)
|
||||
for(x=8; x; x--)
|
||||
d+=abs(new[x]-old[x]);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
static int (*diff)(unsigned char *, unsigned char *, int, int);
|
||||
|
||||
static int diff_plane(unsigned char *old, unsigned char *new,
|
||||
int w, int h, int os, int ns, int arg)
|
||||
{
|
||||
int x, y, d, max=0, sum=0, n=0;
|
||||
|
||||
for(y=0; y<h-7; y+=8)
|
||||
{
|
||||
for(x=0; x<w-7; x+=8)
|
||||
{
|
||||
d=diff(old+x+y*os, new+x+y*ns, os, ns);
|
||||
if(d>max) max=d;
|
||||
sum+=d;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
return (sum+n*max)/2;
|
||||
}
|
||||
|
||||
/*
|
||||
static unsigned int checksum_plane(unsigned char *p, unsigned char *z,
|
||||
int w, int h, int s, int zs, int arg)
|
||||
{
|
||||
unsigned int shift, sum;
|
||||
unsigned char *e;
|
||||
|
||||
for(sum=0; h; h--, p+=s-w)
|
||||
for(e=p+w, shift=32; p<e;)
|
||||
sum^=(*p++)<<(shift=(shift-8)&31);
|
||||
|
||||
return sum;
|
||||
}
|
||||
*/
|
||||
|
||||
static unsigned int checksum_plane(unsigned char *p, unsigned char *z,
|
||||
int w, int h, int s, int zs, int arg)
|
||||
{
|
||||
unsigned int shift;
|
||||
uint32_t sum, t;
|
||||
unsigned char *e, *e2;
|
||||
#if HAVE_FAST_64BIT
|
||||
typedef uint64_t wsum_t;
|
||||
#else
|
||||
typedef uint32_t wsum_t;
|
||||
#endif
|
||||
wsum_t wsum;
|
||||
|
||||
for(sum=0; h; h--, p+=s-w)
|
||||
{
|
||||
for(shift=0, e=p+w; (int)p&(sizeof(wsum_t)-1) && p<e;)
|
||||
sum^=*p++<<(shift=(shift-8)&31);
|
||||
|
||||
for(wsum=0, e2=e-sizeof(wsum_t)+1; p<e2; p+=sizeof(wsum_t))
|
||||
wsum^=*(wsum_t *)p;
|
||||
|
||||
#if HAVE_FAST_64BIT
|
||||
t=be2me_32((uint32_t)(wsum>>32^wsum));
|
||||
#else
|
||||
t=be2me_32(wsum);
|
||||
#endif
|
||||
|
||||
for(sum^=(t<<shift|t>>(32-shift)); p<e;)
|
||||
sum^=*p++<<(shift=(shift-8)&31);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
static int deghost_plane(unsigned char *d, unsigned char *s,
|
||||
int w, int h, int ds, int ss, int threshold)
|
||||
{
|
||||
int t;
|
||||
unsigned char *e;
|
||||
|
||||
for(; h; h--, s+=ss-w, d+=ds-w)
|
||||
for(e=d+w; d<e; d++, s++)
|
||||
if(abs(*d-*s)>=threshold)
|
||||
*d=(t=(*d<<1)-*s)<0?0:t>255?255:t;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int copyop(unsigned char *d, unsigned char *s, int bpl, int h, int dstride, int sstride, int dummy) {
|
||||
memcpy_pic(d, s, bpl, h, dstride, sstride);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imgop(int(*planeop)(unsigned char *, unsigned char *,
|
||||
int, int, int, int, int),
|
||||
mp_image_t *dst, mp_image_t *src, int arg)
|
||||
{
|
||||
if(dst->flags&MP_IMGFLAG_PLANAR)
|
||||
return planeop(dst->planes[0], src?src->planes[0]:0,
|
||||
dst->w, dst->h,
|
||||
dst->stride[0], src?src->stride[0]:0, arg)+
|
||||
planeop(dst->planes[1], src?src->planes[1]:0,
|
||||
dst->chroma_width, dst->chroma_height,
|
||||
dst->stride[1], src?src->stride[1]:0, arg)+
|
||||
planeop(dst->planes[2], src?src->planes[2]:0,
|
||||
dst->chroma_width, dst->chroma_height,
|
||||
dst->stride[2], src?src->stride[2]:0, arg);
|
||||
|
||||
return planeop(dst->planes[0], src?src->planes[0]:0,
|
||||
dst->w*(dst->bpp/8), dst->h,
|
||||
dst->stride[0], src?src->stride[0]:0, arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the phase in which the telecine pattern fits best to the
|
||||
* given 5 frame slice of frame difference measurements.
|
||||
*
|
||||
* If phase1 and phase2 are not negative, only the two specified
|
||||
* phases are tested.
|
||||
*/
|
||||
|
||||
static int match(struct vf_priv_s *p, int *diffs,
|
||||
int phase1, int phase2, double *strength)
|
||||
{
|
||||
static const int pattern1[]={ -4, 1, 1, 1, 1 },
|
||||
pattern2[]={ -2, -3, 4, 4, -3 }, *pattern;
|
||||
int f, m, n, t[5];
|
||||
|
||||
pattern=p->deghost>0?pattern2:pattern1;
|
||||
|
||||
for(f=0; f<5; f++)
|
||||
{
|
||||
if(phase1<0 || phase2<0 || f==phase1 || f==phase2)
|
||||
{
|
||||
for(n=t[f]=0; n<5; n++)
|
||||
t[f]+=diffs[n]*pattern[(n-f+5)%5];
|
||||
}
|
||||
else
|
||||
t[f]=INT_MIN;
|
||||
}
|
||||
|
||||
/* find the best match */
|
||||
for(m=0, n=1; n<5; n++)
|
||||
if(t[n]>t[m]) m=n;
|
||||
|
||||
if(strength)
|
||||
{
|
||||
/* the second best match */
|
||||
for(f=m?0:1, n=f+1; n<5; n++)
|
||||
if(n!=m && t[n]>t[f]) f=n;
|
||||
|
||||
*strength=(t[m]>0?(double)(t[m]-t[f])/t[m]:0.0);
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
mp_image_t *dmpi, *tmpi=0;
|
||||
int n, m, f, newphase;
|
||||
struct vf_priv_s *p=vf->priv;
|
||||
unsigned int checksum;
|
||||
double d;
|
||||
|
||||
dmpi=vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
|
||||
MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE,
|
||||
mpi->width, mpi->height);
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
|
||||
newphase=p->phase;
|
||||
|
||||
switch(p->pass)
|
||||
{
|
||||
case 1:
|
||||
fprintf(p->file, "%08x %d\n",
|
||||
(unsigned int)imgop((void *)checksum_plane, mpi, 0, 0),
|
||||
p->frameno?imgop(diff_plane, dmpi, mpi, 0):0);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if(p->frameno/5>p->bcount)
|
||||
{
|
||||
mp_msg(MSGT_VFILTER, MSGL_ERR,
|
||||
"\n%s: Log file ends prematurely! "
|
||||
"Switching to one pass mode.\n", vf->info->name);
|
||||
p->pass=0;
|
||||
break;
|
||||
}
|
||||
|
||||
checksum=(unsigned int)imgop((void *)checksum_plane, mpi, 0, 0);
|
||||
|
||||
if(checksum!=p->csdata[p->frameno])
|
||||
{
|
||||
for(f=0; f<100; f++)
|
||||
if(p->frameno+f<p->fcount && p->csdata[p->frameno+f]==checksum)
|
||||
break;
|
||||
else if(p->frameno-f>=0 && p->csdata[p->frameno-f]==checksum)
|
||||
{
|
||||
f=-f;
|
||||
break;
|
||||
}
|
||||
|
||||
if(f<100)
|
||||
{
|
||||
mp_msg(MSGT_VFILTER, MSGL_INFO,
|
||||
"\n%s: Mismatch with pass-1: %+d frame(s).\n",
|
||||
vf->info->name, f);
|
||||
|
||||
p->frameno+=f;
|
||||
p->misscount=0;
|
||||
}
|
||||
else if(p->misscount++>=30)
|
||||
{
|
||||
mp_msg(MSGT_VFILTER, MSGL_ERR,
|
||||
"\n%s: Sync with pass-1 lost! "
|
||||
"Switching to one pass mode.\n", vf->info->name);
|
||||
p->pass=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
n=(p->frameno)/5;
|
||||
if(n>=p->bcount) n=p->bcount-1;
|
||||
|
||||
newphase=p->bdata[n];
|
||||
break;
|
||||
|
||||
default:
|
||||
if(p->frameno)
|
||||
{
|
||||
int *sump=p->sum+p->frameno%5,
|
||||
*histp=p->history+p->frameno%p->window;
|
||||
|
||||
*sump-=*histp;
|
||||
*sump+=(*histp=imgop(diff_plane, dmpi, mpi, 0));
|
||||
}
|
||||
|
||||
m=match(p, p->sum, -1, -1, &d);
|
||||
|
||||
if(d>=p->threshold)
|
||||
newphase=m;
|
||||
}
|
||||
|
||||
n=p->ocount++%5;
|
||||
|
||||
if(newphase!=p->phase && ((p->phase+4)%5<n)==((newphase+4)%5<n))
|
||||
{
|
||||
p->phase=newphase;
|
||||
mp_msg(MSGT_VFILTER, MSGL_STATUS,
|
||||
"\n%s: Telecine phase %d.\n", vf->info->name, p->phase);
|
||||
}
|
||||
|
||||
switch((p->frameno++-p->phase+10)%5)
|
||||
{
|
||||
case 0:
|
||||
imgop(copyop, dmpi, mpi, 0);
|
||||
return 0;
|
||||
|
||||
case 4:
|
||||
if(p->deghost>0)
|
||||
{
|
||||
tmpi=vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE |
|
||||
MP_IMGFLAG_READABLE,
|
||||
mpi->width, mpi->height);
|
||||
vf_clone_mpi_attributes(tmpi, mpi);
|
||||
|
||||
imgop(copyop, tmpi, mpi, 0);
|
||||
imgop(deghost_plane, tmpi, dmpi, p->deghost);
|
||||
imgop(copyop, dmpi, mpi, 0);
|
||||
return vf_next_put_image(vf, tmpi, MP_NOPTS_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
imgop(copyop, dmpi, mpi, 0);
|
||||
return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
|
||||
}
|
||||
|
||||
static int analyze(struct vf_priv_s *p)
|
||||
{
|
||||
int *buf=0, *bp, bufsize=0, n, b, f, i, j, m, s;
|
||||
unsigned int *cbuf=0, *cp;
|
||||
char *pbuf;
|
||||
char lbuf[256];
|
||||
int sum[5];
|
||||
double d;
|
||||
|
||||
/* read the file */
|
||||
|
||||
n=15;
|
||||
while(fgets(lbuf, 256, p->file))
|
||||
{
|
||||
if(n>=bufsize-19)
|
||||
{
|
||||
bufsize=bufsize?bufsize*2:30000;
|
||||
if((bp=realloc(buf, bufsize*sizeof *buf))) buf=bp;
|
||||
if((cp=realloc(cbuf, bufsize*sizeof *cbuf))) cbuf=cp;
|
||||
|
||||
if(!bp || !cp)
|
||||
{
|
||||
mp_msg(MSGT_VFILTER, MSGL_FATAL, "%s: Not enough memory.\n",
|
||||
vf_info_divtc.name);
|
||||
free(buf);
|
||||
free(cbuf);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
sscanf(lbuf, "%x %d", cbuf+n, buf+n);
|
||||
n++;
|
||||
}
|
||||
|
||||
if(!n)
|
||||
{
|
||||
mp_msg(MSGT_VFILTER, MSGL_FATAL, "%s: Empty 2-pass log file.\n",
|
||||
vf_info_divtc.name);
|
||||
free(buf);
|
||||
free(cbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* generate some dummy data past the beginning and end of the array */
|
||||
|
||||
buf+=15, cbuf+=15;
|
||||
n-=15;
|
||||
|
||||
memcpy(buf-15, buf, 15*sizeof *buf);
|
||||
memset(cbuf-15, 0, 15*sizeof *cbuf);
|
||||
|
||||
while(n%5)
|
||||
buf[n]=buf[n-5], cbuf[n]=0, n++;
|
||||
|
||||
memcpy(buf+n, buf+n-15, 15*sizeof *buf);
|
||||
memset(cbuf+n, 0, 15*sizeof *cbuf);
|
||||
|
||||
p->csdata=cbuf;
|
||||
p->fcount=n;
|
||||
|
||||
/* array with one slot for each slice of 5 frames */
|
||||
|
||||
p->bdata=pbuf=malloc(p->bcount=b=(n/5));
|
||||
memset(pbuf, 255, b);
|
||||
|
||||
/* resolve the automatic mode */
|
||||
|
||||
if(p->deghost<0)
|
||||
{
|
||||
int deghost=-p->deghost;
|
||||
double s0=0.0, s1=0.0;
|
||||
|
||||
for(f=0; f<n; f+=5)
|
||||
{
|
||||
p->deghost=0; match(p, buf+f, -1, -1, &d); s0+=d;
|
||||
p->deghost=1; match(p, buf+f, -1, -1, &d); s1+=d;
|
||||
}
|
||||
|
||||
p->deghost=s1>s0?deghost:0;
|
||||
|
||||
mp_msg(MSGT_VFILTER, MSGL_INFO,
|
||||
"%s: Deghosting %-3s (relative pattern strength %+.2fdB).\n",
|
||||
vf_info_divtc.name,
|
||||
p->deghost?"ON":"OFF",
|
||||
10.0*log10(s1/s0));
|
||||
}
|
||||
|
||||
/* analyze the data */
|
||||
|
||||
for(f=0; f<5; f++)
|
||||
for(sum[f]=0, n=-15; n<20; n+=5)
|
||||
sum[f]+=buf[n+f];
|
||||
|
||||
for(f=0; f<b; f++)
|
||||
{
|
||||
m=match(p, sum, -1, -1, &d);
|
||||
|
||||
if(d>=p->threshold)
|
||||
pbuf[f]=m;
|
||||
|
||||
if(f<b-1)
|
||||
for(n=0; n<5; n++)
|
||||
sum[n]=sum[n]-buf[5*(f-3)+n]+buf[5*(f+4)+n];
|
||||
}
|
||||
|
||||
/* fill in the gaps */
|
||||
|
||||
/* the beginning */
|
||||
for(f=0; f<b && pbuf[f]==-1; f++);
|
||||
|
||||
if(f==b)
|
||||
{
|
||||
free(buf-15);
|
||||
mp_msg(MSGT_VFILTER, MSGL_FATAL, "%s: No telecine pattern found!\n",
|
||||
vf_info_divtc.name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(n=0; n<f; pbuf[n++]=pbuf[f]);
|
||||
|
||||
/* the end */
|
||||
for(f=b-1; pbuf[f]==-1; f--);
|
||||
for(n=f+1; n<b; pbuf[n++]=pbuf[f]);
|
||||
|
||||
/* the rest */
|
||||
for(f=0;;)
|
||||
{
|
||||
while(f<b && pbuf[f]!=-1) f++;
|
||||
if(f==b) break;
|
||||
for(n=f; pbuf[n]==-1; n++);
|
||||
|
||||
if(pbuf[f-1]==pbuf[n])
|
||||
{
|
||||
/* just a gap */
|
||||
while(f<n) pbuf[f++]=pbuf[n];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* phase change, reanalyze the original data in the gap with zero
|
||||
threshold for only the two phases that appear at the ends */
|
||||
|
||||
for(i=0; i<5; i++)
|
||||
for(sum[i]=0, j=5*f-15; j<5*f; j+=5)
|
||||
sum[i]+=buf[i+j];
|
||||
|
||||
for(i=f; i<n; i++)
|
||||
{
|
||||
pbuf[i]=match(p, sum, pbuf[f-1], pbuf[n], 0);
|
||||
|
||||
for(j=0; j<5; j++)
|
||||
sum[j]=sum[j]-buf[5*(i-3)+j]+buf[5*(i+4)+j];
|
||||
}
|
||||
|
||||
/* estimate the transition point by dividing the gap
|
||||
in the same proportion as the number of matches of each kind */
|
||||
|
||||
for(i=f, m=f; i<n; i++)
|
||||
if(pbuf[i]==pbuf[f-1]) m++;
|
||||
|
||||
/* find the transition of the right direction nearest to the
|
||||
estimated point */
|
||||
|
||||
if(m>f && m<n)
|
||||
{
|
||||
for(j=m; j>f; j--)
|
||||
if(pbuf[j-1]==pbuf[f-1] && pbuf[j]==pbuf[n]) break;
|
||||
for(s=m; s<n; s++)
|
||||
if(pbuf[s-1]==pbuf[f-1] && pbuf[s]==pbuf[n]) break;
|
||||
|
||||
m=(s-m<m-j)?s:j;
|
||||
}
|
||||
|
||||
/* and rewrite the data to allow only this one transition */
|
||||
|
||||
for(i=f; i<m; i++)
|
||||
pbuf[i]=pbuf[f-1];
|
||||
|
||||
for(; i<n; i++)
|
||||
pbuf[i]=pbuf[n];
|
||||
|
||||
f=n;
|
||||
}
|
||||
}
|
||||
|
||||
free(buf-15);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt)
|
||||
{
|
||||
switch(fmt)
|
||||
{
|
||||
case IMGFMT_444P: case IMGFMT_IYUV: case IMGFMT_RGB24:
|
||||
case IMGFMT_422P: case IMGFMT_UYVY: case IMGFMT_BGR24:
|
||||
case IMGFMT_411P: case IMGFMT_YUY2: case IMGFMT_IF09:
|
||||
case IMGFMT_YV12: case IMGFMT_I420: case IMGFMT_YVU9:
|
||||
case IMGFMT_IUYV: case IMGFMT_Y800: case IMGFMT_Y8:
|
||||
return vf_next_query_format(vf,fmt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
if(vf->priv)
|
||||
{
|
||||
if(vf->priv->file) fclose(vf->priv->file);
|
||||
if(vf->priv->csdata) free(vf->priv->csdata-15);
|
||||
free(vf->priv->bdata);
|
||||
free(vf->priv->history);
|
||||
free(vf->priv);
|
||||
}
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
struct vf_priv_s *p;
|
||||
char *filename="framediff.log", *ap, *q, *a;
|
||||
|
||||
if(args && !(args=strdup(args)))
|
||||
{
|
||||
nomem:
|
||||
mp_msg(MSGT_VFILTER, MSGL_FATAL,
|
||||
"%s: Not enough memory.\n", vf->info->name);
|
||||
fail:
|
||||
uninit(vf);
|
||||
free(args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vf->put_image=put_image;
|
||||
vf->uninit=uninit;
|
||||
vf->query_format=query_format;
|
||||
vf->default_reqs=VFCAP_ACCEPT_STRIDE;
|
||||
if(!(vf->priv=p=calloc(1, sizeof(struct vf_priv_s))))
|
||||
goto nomem;
|
||||
|
||||
p->phase=5;
|
||||
p->threshold=0.5;
|
||||
p->window=30;
|
||||
|
||||
if((ap=args))
|
||||
while(*ap)
|
||||
{
|
||||
q=ap;
|
||||
if((ap=strchr(q, ':'))) *ap++=0; else ap=q+strlen(q);
|
||||
if((a=strchr(q, '='))) *a++=0; else a=q+strlen(q);
|
||||
|
||||
switch(*q)
|
||||
{
|
||||
case 0: break;
|
||||
case 'f': filename=a; break;
|
||||
case 't': p->threshold=atof(a); break;
|
||||
case 'w': p->window=5*(atoi(a)+4)/5; break;
|
||||
case 'd': p->deghost=atoi(a); break;
|
||||
case 'p':
|
||||
if(q[1]=='h') p->phase=atoi(a);
|
||||
else p->pass=atoi(a);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
mp_msg(MSGT_VFILTER, MSGL_INFO,
|
||||
"\n%s options:\n\n"
|
||||
"pass=1|2 - Use 2-pass mode.\n"
|
||||
"file=filename - Set the 2-pass log file name "
|
||||
"(default %s).\n"
|
||||
"threshold=value - Set the pattern recognition "
|
||||
"sensitivity (default %g).\n"
|
||||
"deghost=value - Select deghosting threshold "
|
||||
"(default %d).\n"
|
||||
"window=numframes - Set the statistics window "
|
||||
"for 1-pass mode (default %d).\n"
|
||||
"phase=0|1|2|3|4 - Set the initial phase "
|
||||
"for 1-pass mode (default %d).\n\n"
|
||||
"The option names can be abbreviated to the shortest "
|
||||
"unique prefix.\n\n",
|
||||
vf->info->name, filename, p->threshold, p->deghost,
|
||||
p->window, p->phase%5);
|
||||
break;
|
||||
|
||||
default:
|
||||
mp_msg(MSGT_VFILTER, MSGL_FATAL,
|
||||
"%s: Unknown argument %s.\n", vf->info->name, q);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
switch(p->pass)
|
||||
{
|
||||
case 1:
|
||||
if(!(p->file=fopen(filename, "w")))
|
||||
{
|
||||
mp_msg(MSGT_VFILTER, MSGL_FATAL,
|
||||
"%s: Can't create file %s.\n", vf->info->name, filename);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if(!(p->file=fopen(filename, "r")))
|
||||
{
|
||||
mp_msg(MSGT_VFILTER, MSGL_FATAL,
|
||||
"%s: Can't open file %s.\n", vf->info->name, filename);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(!analyze(p))
|
||||
goto fail;
|
||||
|
||||
fclose(p->file);
|
||||
p->file=0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(p->window<5) p->window=5;
|
||||
if(!(p->history=calloc(sizeof *p->history, p->window)))
|
||||
goto nomem;
|
||||
|
||||
diff = diff_C;
|
||||
#if HAVE_MMX && HAVE_EBX_AVAILABLE
|
||||
if(gCpuCaps.hasMMX) diff = diff_MMX;
|
||||
#endif
|
||||
|
||||
free(args);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_divtc =
|
||||
{
|
||||
"inverse telecine for deinterlaced video",
|
||||
"divtc",
|
||||
"Ville Saari",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
166
libavfilter/libmpcodecs/vf_down3dright.c
Normal file
166
libavfilter/libmpcodecs/vf_down3dright.c
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
int skipline;
|
||||
int scalew;
|
||||
int scaleh;
|
||||
};
|
||||
|
||||
static void toright(unsigned char *dst[3], unsigned char *src[3],
|
||||
int dststride[3], int srcstride[3],
|
||||
int w, int h, struct vf_priv_s* p)
|
||||
{
|
||||
int k;
|
||||
|
||||
for (k = 0; k < 3; k++) {
|
||||
unsigned char* fromL = src[k];
|
||||
unsigned char* fromR = src[k];
|
||||
unsigned char* to = dst[k];
|
||||
int src = srcstride[k];
|
||||
int dst = dststride[k];
|
||||
int ss;
|
||||
unsigned int dd;
|
||||
int i;
|
||||
|
||||
if (k > 0) {
|
||||
i = h / 4 - p->skipline / 2;
|
||||
ss = src * (h / 4 + p->skipline / 2);
|
||||
dd = w / 4;
|
||||
} else {
|
||||
i = h / 2 - p->skipline;
|
||||
ss = src * (h / 2 + p->skipline);
|
||||
dd = w / 2;
|
||||
}
|
||||
fromR += ss;
|
||||
for ( ; i > 0; i--) {
|
||||
int j;
|
||||
unsigned char* t = to;
|
||||
unsigned char* sL = fromL;
|
||||
unsigned char* sR = fromR;
|
||||
|
||||
if (p->scalew == 1) {
|
||||
for (j = dd; j > 0; j--) {
|
||||
*t++ = (sL[0] + sL[1]) / 2;
|
||||
sL+=2;
|
||||
}
|
||||
for (j = dd ; j > 0; j--) {
|
||||
*t++ = (sR[0] + sR[1]) / 2;
|
||||
sR+=2;
|
||||
}
|
||||
} else {
|
||||
for (j = dd * 2 ; j > 0; j--)
|
||||
*t++ = *sL++;
|
||||
for (j = dd * 2 ; j > 0; j--)
|
||||
*t++ = *sR++;
|
||||
}
|
||||
if (p->scaleh == 1) {
|
||||
fast_memcpy(to + dst, to, dst);
|
||||
to += dst;
|
||||
}
|
||||
to += dst;
|
||||
fromL += src;
|
||||
fromR += src;
|
||||
}
|
||||
//printf("K %d %d %d %d %d \n", k, w, h, src, dst);
|
||||
}
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
mp_image_t *dmpi;
|
||||
|
||||
// hope we'll get DR buffer:
|
||||
dmpi=vf_get_image(vf->next, IMGFMT_YV12,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE |
|
||||
(vf->priv->scaleh == 1) ? MP_IMGFLAG_READABLE : 0,
|
||||
mpi->w * vf->priv->scalew,
|
||||
mpi->h / vf->priv->scaleh - vf->priv->skipline);
|
||||
|
||||
toright(dmpi->planes, mpi->planes, dmpi->stride,
|
||||
mpi->stride, mpi->w, mpi->h, vf->priv);
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt)
|
||||
{
|
||||
/* FIXME - also support UYVY output? */
|
||||
return vf_next_config(vf, width * vf->priv->scalew,
|
||||
height / vf->priv->scaleh - vf->priv->skipline, d_width, d_height, flags, IMGFMT_YV12);
|
||||
}
|
||||
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt)
|
||||
{
|
||||
/* FIXME - really any YUV 4:2:0 input format should work */
|
||||
switch (fmt) {
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_I420:
|
||||
return vf_next_query_format(vf, IMGFMT_YV12);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
vf->config=config;
|
||||
vf->query_format=query_format;
|
||||
vf->put_image=put_image;
|
||||
vf->uninit=uninit;
|
||||
|
||||
vf->priv = calloc(1, sizeof (struct vf_priv_s));
|
||||
vf->priv->skipline = 0;
|
||||
vf->priv->scalew = 1;
|
||||
vf->priv->scaleh = 2;
|
||||
if (args) sscanf(args, "%d:%d:%d", &vf->priv->skipline, &vf->priv->scalew, &vf->priv->scaleh);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_down3dright = {
|
||||
"convert stereo movie from top-bottom to left-right field",
|
||||
"down3dright",
|
||||
"Zdenek Kabelac",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
123
libavfilter/libmpcodecs/vf_dsize.c
Normal file
123
libavfilter/libmpcodecs/vf_dsize.c
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
int w, h;
|
||||
int method; // aspect method, 0 -> downscale, 1-> upscale. +2 -> original aspect.
|
||||
int round;
|
||||
float aspect;
|
||||
};
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt)
|
||||
{
|
||||
if (vf->priv->aspect < 0.001) { // did the user input aspect or w,h params
|
||||
if (vf->priv->w == 0) vf->priv->w = d_width;
|
||||
if (vf->priv->h == 0) vf->priv->h = d_height;
|
||||
if (vf->priv->w == -1) vf->priv->w = width;
|
||||
if (vf->priv->h == -1) vf->priv->h = height;
|
||||
if (vf->priv->w == -2) vf->priv->w = vf->priv->h * (double)d_width / d_height;
|
||||
if (vf->priv->w == -3) vf->priv->w = vf->priv->h * (double)width / height;
|
||||
if (vf->priv->h == -2) vf->priv->h = vf->priv->w * (double)d_height / d_width;
|
||||
if (vf->priv->h == -3) vf->priv->h = vf->priv->w * (double)height / width;
|
||||
if (vf->priv->method > -1) {
|
||||
double aspect = (vf->priv->method & 2) ? ((double)height / width) : ((double)d_height / d_width);
|
||||
if ((vf->priv->h > vf->priv->w * aspect) ^ (vf->priv->method & 1)) {
|
||||
vf->priv->h = vf->priv->w * aspect;
|
||||
} else {
|
||||
vf->priv->w = vf->priv->h / aspect;
|
||||
}
|
||||
}
|
||||
if (vf->priv->round > 1) { // round up
|
||||
vf->priv->w += (vf->priv->round - 1 - (vf->priv->w - 1) % vf->priv->round);
|
||||
vf->priv->h += (vf->priv->round - 1 - (vf->priv->h - 1) % vf->priv->round);
|
||||
}
|
||||
d_width = vf->priv->w;
|
||||
d_height = vf->priv->h;
|
||||
} else {
|
||||
if (vf->priv->aspect * height > width) {
|
||||
d_width = height * vf->priv->aspect + .5;
|
||||
d_height = height;
|
||||
} else {
|
||||
d_height = width / vf->priv->aspect + .5;
|
||||
d_width = width;
|
||||
}
|
||||
}
|
||||
return vf_next_config(vf, width, height, d_width, d_height, flags, outfmt);
|
||||
}
|
||||
|
||||
static void uninit(vf_instance_t *vf) {
|
||||
free(vf->priv);
|
||||
vf->priv = NULL;
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
vf->config = config;
|
||||
vf->draw_slice = vf_next_draw_slice;
|
||||
vf->uninit = uninit;
|
||||
//vf->default_caps = 0;
|
||||
vf->priv = calloc(sizeof(struct vf_priv_s), 1);
|
||||
vf->priv->aspect = 0.;
|
||||
vf->priv->w = -1;
|
||||
vf->priv->h = -1;
|
||||
vf->priv->method = -1;
|
||||
vf->priv->round = 1;
|
||||
if (args) {
|
||||
if (strchr(args, '/')) {
|
||||
int w, h;
|
||||
sscanf(args, "%d/%d", &w, &h);
|
||||
vf->priv->aspect = (float)w/h;
|
||||
} else if (strchr(args, '.')) {
|
||||
sscanf(args, "%f", &vf->priv->aspect);
|
||||
} else {
|
||||
sscanf(args, "%d:%d:%d:%d", &vf->priv->w, &vf->priv->h, &vf->priv->method, &vf->priv->round);
|
||||
}
|
||||
}
|
||||
if ((vf->priv->aspect < 0.) || (vf->priv->w < -3) || (vf->priv->h < -3) ||
|
||||
((vf->priv->w < -1) && (vf->priv->h < -1)) ||
|
||||
(vf->priv->method < -1) || (vf->priv->method > 3) ||
|
||||
(vf->priv->round < 0)) {
|
||||
mp_msg(MSGT_VFILTER, MSGL_ERR, "[dsize] Illegal value(s): aspect: %f w: %d h: %d aspect_method: %d round: %d\n", vf->priv->aspect, vf->priv->w, vf->priv->h, vf->priv->method, vf->priv->round);
|
||||
free(vf->priv); vf->priv = NULL;
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_dsize = {
|
||||
"reset displaysize/aspect",
|
||||
"dsize",
|
||||
"Rich Felker",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
258
libavfilter/libmpcodecs/vf_eq.c
Normal file
258
libavfilter/libmpcodecs/vf_eq.c
Normal file
@ -0,0 +1,258 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#include "libvo/video_out.h"
|
||||
|
||||
#include "m_option.h"
|
||||
#include "m_struct.h"
|
||||
|
||||
static struct vf_priv_s {
|
||||
unsigned char *buf;
|
||||
int brightness;
|
||||
int contrast;
|
||||
} const vf_priv_dflt = {
|
||||
NULL,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
#if HAVE_MMX
|
||||
static void process_MMX(unsigned char *dest, int dstride, unsigned char *src, int sstride,
|
||||
int w, int h, int brightness, int contrast)
|
||||
{
|
||||
int i;
|
||||
int pel;
|
||||
int dstep = dstride-w;
|
||||
int sstep = sstride-w;
|
||||
short brvec[4];
|
||||
short contvec[4];
|
||||
|
||||
contrast = ((contrast+100)*256*16)/100;
|
||||
brightness = ((brightness+100)*511)/200-128 - contrast/32;
|
||||
|
||||
brvec[0] = brvec[1] = brvec[2] = brvec[3] = brightness;
|
||||
contvec[0] = contvec[1] = contvec[2] = contvec[3] = contrast;
|
||||
|
||||
while (h--) {
|
||||
__asm__ volatile (
|
||||
"movq (%5), %%mm3 \n\t"
|
||||
"movq (%6), %%mm4 \n\t"
|
||||
"pxor %%mm0, %%mm0 \n\t"
|
||||
"movl %4, %%eax\n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%0), %%mm1 \n\t"
|
||||
"movq (%0), %%mm2 \n\t"
|
||||
"punpcklbw %%mm0, %%mm1 \n\t"
|
||||
"punpckhbw %%mm0, %%mm2 \n\t"
|
||||
"psllw $4, %%mm1 \n\t"
|
||||
"psllw $4, %%mm2 \n\t"
|
||||
"pmulhw %%mm4, %%mm1 \n\t"
|
||||
"pmulhw %%mm4, %%mm2 \n\t"
|
||||
"paddw %%mm3, %%mm1 \n\t"
|
||||
"paddw %%mm3, %%mm2 \n\t"
|
||||
"packuswb %%mm2, %%mm1 \n\t"
|
||||
"add $8, %0 \n\t"
|
||||
"movq %%mm1, (%1) \n\t"
|
||||
"add $8, %1 \n\t"
|
||||
"decl %%eax \n\t"
|
||||
"jnz 1b \n\t"
|
||||
: "=r" (src), "=r" (dest)
|
||||
: "0" (src), "1" (dest), "r" (w>>3), "r" (brvec), "r" (contvec)
|
||||
: "%eax"
|
||||
);
|
||||
|
||||
for (i = w&7; i; i--)
|
||||
{
|
||||
pel = ((*src++* contrast)>>12) + brightness;
|
||||
if(pel&768) pel = (-pel)>>31;
|
||||
*dest++ = pel;
|
||||
}
|
||||
|
||||
src += sstep;
|
||||
dest += dstep;
|
||||
}
|
||||
__asm__ volatile ( "emms \n\t" ::: "memory" );
|
||||
}
|
||||
#endif
|
||||
|
||||
static void process_C(unsigned char *dest, int dstride, unsigned char *src, int sstride,
|
||||
int w, int h, int brightness, int contrast)
|
||||
{
|
||||
int i;
|
||||
int pel;
|
||||
int dstep = dstride-w;
|
||||
int sstep = sstride-w;
|
||||
|
||||
contrast = ((contrast+100)*256*256)/100;
|
||||
brightness = ((brightness+100)*511)/200-128 - contrast/512;
|
||||
|
||||
while (h--) {
|
||||
for (i = w; i; i--)
|
||||
{
|
||||
pel = ((*src++* contrast)>>16) + brightness;
|
||||
if(pel&768) pel = (-pel)>>31;
|
||||
*dest++ = pel;
|
||||
}
|
||||
src += sstep;
|
||||
dest += dstep;
|
||||
}
|
||||
}
|
||||
|
||||
static void (*process)(unsigned char *dest, int dstride, unsigned char *src, int sstride,
|
||||
int w, int h, int brightness, int contrast);
|
||||
|
||||
/* FIXME: add packed yuv version of process */
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
mp_image_t *dmpi;
|
||||
|
||||
dmpi=vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_EXPORT, 0,
|
||||
mpi->w, mpi->h);
|
||||
|
||||
dmpi->stride[0] = mpi->stride[0];
|
||||
dmpi->planes[1] = mpi->planes[1];
|
||||
dmpi->planes[2] = mpi->planes[2];
|
||||
dmpi->stride[1] = mpi->stride[1];
|
||||
dmpi->stride[2] = mpi->stride[2];
|
||||
|
||||
if (!vf->priv->buf) vf->priv->buf = malloc(mpi->stride[0]*mpi->h);
|
||||
|
||||
if ((vf->priv->brightness == 0) && (vf->priv->contrast == 0))
|
||||
dmpi->planes[0] = mpi->planes[0];
|
||||
else {
|
||||
dmpi->planes[0] = vf->priv->buf;
|
||||
process(dmpi->planes[0], dmpi->stride[0],
|
||||
mpi->planes[0], mpi->stride[0],
|
||||
mpi->w, mpi->h, vf->priv->brightness,
|
||||
vf->priv->contrast);
|
||||
}
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
static int control(struct vf_instance *vf, int request, void* data)
|
||||
{
|
||||
vf_equalizer_t *eq;
|
||||
|
||||
switch (request) {
|
||||
case VFCTRL_SET_EQUALIZER:
|
||||
eq = data;
|
||||
if (!strcmp(eq->item,"brightness")) {
|
||||
vf->priv->brightness = eq->value;
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
else if (!strcmp(eq->item,"contrast")) {
|
||||
vf->priv->contrast = eq->value;
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
break;
|
||||
case VFCTRL_GET_EQUALIZER:
|
||||
eq = data;
|
||||
if (!strcmp(eq->item,"brightness")) {
|
||||
eq->value = vf->priv->brightness;
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
else if (!strcmp(eq->item,"contrast")) {
|
||||
eq->value = vf->priv->contrast;
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return vf_next_control(vf, request, data);
|
||||
}
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt)
|
||||
{
|
||||
switch (fmt) {
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_IF09:
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_CLPL:
|
||||
case IMGFMT_Y800:
|
||||
case IMGFMT_Y8:
|
||||
case IMGFMT_NV12:
|
||||
case IMGFMT_NV21:
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
free(vf->priv->buf);
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
vf->control=control;
|
||||
vf->query_format=query_format;
|
||||
vf->put_image=put_image;
|
||||
vf->uninit=uninit;
|
||||
|
||||
process = process_C;
|
||||
#if HAVE_MMX
|
||||
if(gCpuCaps.hasMMX) process = process_MMX;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define ST_OFF(f) M_ST_OFF(struct vf_priv_s,f)
|
||||
static const m_option_t vf_opts_fields[] = {
|
||||
{"brightness", ST_OFF(brightness), CONF_TYPE_INT, M_OPT_RANGE,-100 ,100, NULL},
|
||||
{"contrast", ST_OFF(contrast), CONF_TYPE_INT, M_OPT_RANGE,-100 ,100, NULL},
|
||||
{ NULL, NULL, 0, 0, 0, 0, NULL }
|
||||
};
|
||||
|
||||
static const m_struct_t vf_opts = {
|
||||
"eq",
|
||||
sizeof(struct vf_priv_s),
|
||||
&vf_priv_dflt,
|
||||
vf_opts_fields
|
||||
};
|
||||
|
||||
const vf_info_t vf_info_eq = {
|
||||
"soft video equalizer",
|
||||
"eq",
|
||||
"Richard Felker",
|
||||
"",
|
||||
vf_open,
|
||||
&vf_opts
|
||||
};
|
||||
519
libavfilter/libmpcodecs/vf_eq2.c
Normal file
519
libavfilter/libmpcodecs/vf_eq2.c
Normal file
@ -0,0 +1,519 @@
|
||||
/*
|
||||
* Software equalizer (brightness, contrast, gamma, saturation)
|
||||
*
|
||||
* Hampa Hug <hampa@hampa.ch> (original LUT gamma/contrast/brightness filter)
|
||||
* Daniel Moreno <comac@comac.darktech.org> (saturation, R/G/B gamma support)
|
||||
* Richard Felker (original MMX contrast/brightness code (vf_eq.c))
|
||||
* Michael Niedermayer <michalni@gmx.at> (LUT16)
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#define LUT16
|
||||
|
||||
/* Per channel parameters */
|
||||
typedef struct eq2_param_t {
|
||||
unsigned char lut[256];
|
||||
#ifdef LUT16
|
||||
uint16_t lut16[256*256];
|
||||
#endif
|
||||
int lut_clean;
|
||||
|
||||
void (*adjust) (struct eq2_param_t *par, unsigned char *dst, unsigned char *src,
|
||||
unsigned w, unsigned h, unsigned dstride, unsigned sstride);
|
||||
|
||||
double c;
|
||||
double b;
|
||||
double g;
|
||||
double w;
|
||||
} eq2_param_t;
|
||||
|
||||
typedef struct vf_priv_s {
|
||||
eq2_param_t param[3];
|
||||
|
||||
double contrast;
|
||||
double brightness;
|
||||
double saturation;
|
||||
|
||||
double gamma;
|
||||
double gamma_weight;
|
||||
double rgamma;
|
||||
double ggamma;
|
||||
double bgamma;
|
||||
|
||||
unsigned buf_w[3];
|
||||
unsigned buf_h[3];
|
||||
unsigned char *buf[3];
|
||||
} vf_eq2_t;
|
||||
|
||||
|
||||
static
|
||||
void create_lut (eq2_param_t *par)
|
||||
{
|
||||
unsigned i;
|
||||
double g, v;
|
||||
double lw, gw;
|
||||
|
||||
g = par->g;
|
||||
gw = par->w;
|
||||
lw = 1.0 - gw;
|
||||
|
||||
if ((g < 0.001) || (g > 1000.0)) {
|
||||
g = 1.0;
|
||||
}
|
||||
|
||||
g = 1.0 / g;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
v = (double) i / 255.0;
|
||||
v = par->c * (v - 0.5) + 0.5 + par->b;
|
||||
|
||||
if (v <= 0.0) {
|
||||
par->lut[i] = 0;
|
||||
}
|
||||
else {
|
||||
v = v*lw + pow(v, g)*gw;
|
||||
|
||||
if (v >= 1.0) {
|
||||
par->lut[i] = 255;
|
||||
}
|
||||
else {
|
||||
par->lut[i] = (unsigned char) (256.0 * v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LUT16
|
||||
for(i=0; i<256*256; i++){
|
||||
par->lut16[i]= par->lut[i&0xFF] + (par->lut[i>>8]<<8);
|
||||
}
|
||||
#endif
|
||||
|
||||
par->lut_clean = 1;
|
||||
}
|
||||
|
||||
#if HAVE_MMX
|
||||
static
|
||||
void affine_1d_MMX (eq2_param_t *par, unsigned char *dst, unsigned char *src,
|
||||
unsigned w, unsigned h, unsigned dstride, unsigned sstride)
|
||||
{
|
||||
unsigned i;
|
||||
int contrast, brightness;
|
||||
unsigned dstep, sstep;
|
||||
int pel;
|
||||
short brvec[4];
|
||||
short contvec[4];
|
||||
|
||||
// printf("\nmmx: src=%p dst=%p w=%d h=%d ds=%d ss=%d\n",src,dst,w,h,dstride,sstride);
|
||||
|
||||
contrast = (int) (par->c * 256 * 16);
|
||||
brightness = ((int) (100.0 * par->b + 100.0) * 511) / 200 - 128 - contrast / 32;
|
||||
|
||||
brvec[0] = brvec[1] = brvec[2] = brvec[3] = brightness;
|
||||
contvec[0] = contvec[1] = contvec[2] = contvec[3] = contrast;
|
||||
|
||||
sstep = sstride - w;
|
||||
dstep = dstride - w;
|
||||
|
||||
while (h-- > 0) {
|
||||
__asm__ volatile (
|
||||
"movq (%5), %%mm3 \n\t"
|
||||
"movq (%6), %%mm4 \n\t"
|
||||
"pxor %%mm0, %%mm0 \n\t"
|
||||
"movl %4, %%eax\n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%0), %%mm1 \n\t"
|
||||
"movq (%0), %%mm2 \n\t"
|
||||
"punpcklbw %%mm0, %%mm1 \n\t"
|
||||
"punpckhbw %%mm0, %%mm2 \n\t"
|
||||
"psllw $4, %%mm1 \n\t"
|
||||
"psllw $4, %%mm2 \n\t"
|
||||
"pmulhw %%mm4, %%mm1 \n\t"
|
||||
"pmulhw %%mm4, %%mm2 \n\t"
|
||||
"paddw %%mm3, %%mm1 \n\t"
|
||||
"paddw %%mm3, %%mm2 \n\t"
|
||||
"packuswb %%mm2, %%mm1 \n\t"
|
||||
"add $8, %0 \n\t"
|
||||
"movq %%mm1, (%1) \n\t"
|
||||
"add $8, %1 \n\t"
|
||||
"decl %%eax \n\t"
|
||||
"jnz 1b \n\t"
|
||||
: "=r" (src), "=r" (dst)
|
||||
: "0" (src), "1" (dst), "r" (w >> 3), "r" (brvec), "r" (contvec)
|
||||
: "%eax"
|
||||
);
|
||||
|
||||
for (i = w & 7; i > 0; i--) {
|
||||
pel = ((*src++ * contrast) >> 12) + brightness;
|
||||
if (pel & 768) {
|
||||
pel = (-pel) >> 31;
|
||||
}
|
||||
*dst++ = pel;
|
||||
}
|
||||
|
||||
src += sstep;
|
||||
dst += dstep;
|
||||
}
|
||||
|
||||
__asm__ volatile ( "emms \n\t" ::: "memory" );
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
void apply_lut (eq2_param_t *par, unsigned char *dst, unsigned char *src,
|
||||
unsigned w, unsigned h, unsigned dstride, unsigned sstride)
|
||||
{
|
||||
unsigned i, j, w2;
|
||||
unsigned char *lut;
|
||||
uint16_t *lut16;
|
||||
|
||||
if (!par->lut_clean) {
|
||||
create_lut (par);
|
||||
}
|
||||
|
||||
lut = par->lut;
|
||||
#ifdef LUT16
|
||||
lut16 = par->lut16;
|
||||
w2= (w>>3)<<2;
|
||||
for (j = 0; j < h; j++) {
|
||||
uint16_t *src16= (uint16_t*)src;
|
||||
uint16_t *dst16= (uint16_t*)dst;
|
||||
for (i = 0; i < w2; i+=4) {
|
||||
dst16[i+0] = lut16[src16[i+0]];
|
||||
dst16[i+1] = lut16[src16[i+1]];
|
||||
dst16[i+2] = lut16[src16[i+2]];
|
||||
dst16[i+3] = lut16[src16[i+3]];
|
||||
}
|
||||
i <<= 1;
|
||||
#else
|
||||
w2= (w>>3)<<3;
|
||||
for (j = 0; j < h; j++) {
|
||||
for (i = 0; i < w2; i+=8) {
|
||||
dst[i+0] = lut[src[i+0]];
|
||||
dst[i+1] = lut[src[i+1]];
|
||||
dst[i+2] = lut[src[i+2]];
|
||||
dst[i+3] = lut[src[i+3]];
|
||||
dst[i+4] = lut[src[i+4]];
|
||||
dst[i+5] = lut[src[i+5]];
|
||||
dst[i+6] = lut[src[i+6]];
|
||||
dst[i+7] = lut[src[i+7]];
|
||||
}
|
||||
#endif
|
||||
for (; i < w; i++) {
|
||||
dst[i] = lut[src[i]];
|
||||
}
|
||||
|
||||
src += sstride;
|
||||
dst += dstride;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int put_image (vf_instance_t *vf, mp_image_t *src, double pts)
|
||||
{
|
||||
unsigned i;
|
||||
vf_eq2_t *eq2;
|
||||
mp_image_t *dst;
|
||||
unsigned long img_n,img_c;
|
||||
|
||||
eq2 = vf->priv;
|
||||
|
||||
if ((eq2->buf_w[0] != src->w) || (eq2->buf_h[0] != src->h)) {
|
||||
eq2->buf_w[0] = src->w;
|
||||
eq2->buf_h[0] = src->h;
|
||||
eq2->buf_w[1] = eq2->buf_w[2] = src->w >> src->chroma_x_shift;
|
||||
eq2->buf_h[1] = eq2->buf_h[2] = src->h >> src->chroma_y_shift;
|
||||
img_n = eq2->buf_w[0]*eq2->buf_h[0];
|
||||
if(src->num_planes>1){
|
||||
img_c = eq2->buf_w[1]*eq2->buf_h[1];
|
||||
eq2->buf[0] = realloc (eq2->buf[0], img_n + 2*img_c);
|
||||
eq2->buf[1] = eq2->buf[0] + img_n;
|
||||
eq2->buf[2] = eq2->buf[1] + img_c;
|
||||
} else
|
||||
eq2->buf[0] = realloc (eq2->buf[0], img_n);
|
||||
}
|
||||
|
||||
dst = vf_get_image (vf->next, src->imgfmt, MP_IMGTYPE_EXPORT, 0, src->w, src->h);
|
||||
|
||||
for (i = 0; i < ((src->num_planes>1)?3:1); i++) {
|
||||
if (eq2->param[i].adjust != NULL) {
|
||||
dst->planes[i] = eq2->buf[i];
|
||||
dst->stride[i] = eq2->buf_w[i];
|
||||
|
||||
eq2->param[i].adjust (&eq2->param[i], dst->planes[i], src->planes[i],
|
||||
eq2->buf_w[i], eq2->buf_h[i], dst->stride[i], src->stride[i]);
|
||||
}
|
||||
else {
|
||||
dst->planes[i] = src->planes[i];
|
||||
dst->stride[i] = src->stride[i];
|
||||
}
|
||||
}
|
||||
|
||||
return vf_next_put_image (vf, dst, pts);
|
||||
}
|
||||
|
||||
static
|
||||
void check_values (eq2_param_t *par)
|
||||
{
|
||||
/* yuck! floating point comparisons... */
|
||||
|
||||
if ((par->c == 1.0) && (par->b == 0.0) && (par->g == 1.0)) {
|
||||
par->adjust = NULL;
|
||||
}
|
||||
#if HAVE_MMX
|
||||
else if (par->g == 1.0 && gCpuCaps.hasMMX) {
|
||||
par->adjust = &affine_1d_MMX;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
par->adjust = &apply_lut;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void print_values (vf_eq2_t *eq2)
|
||||
{
|
||||
mp_msg (MSGT_VFILTER, MSGL_V, "vf_eq2: c=%.2f b=%.2f g=%.4f s=%.2f \n",
|
||||
eq2->contrast, eq2->brightness, eq2->gamma, eq2->saturation
|
||||
);
|
||||
}
|
||||
|
||||
static
|
||||
void set_contrast (vf_eq2_t *eq2, double c)
|
||||
{
|
||||
eq2->contrast = c;
|
||||
eq2->param[0].c = c;
|
||||
eq2->param[0].lut_clean = 0;
|
||||
check_values (&eq2->param[0]);
|
||||
print_values (eq2);
|
||||
}
|
||||
|
||||
static
|
||||
void set_brightness (vf_eq2_t *eq2, double b)
|
||||
{
|
||||
eq2->brightness = b;
|
||||
eq2->param[0].b = b;
|
||||
eq2->param[0].lut_clean = 0;
|
||||
check_values (&eq2->param[0]);
|
||||
print_values (eq2);
|
||||
}
|
||||
|
||||
static
|
||||
void set_gamma (vf_eq2_t *eq2, double g)
|
||||
{
|
||||
eq2->gamma = g;
|
||||
|
||||
eq2->param[0].g = eq2->gamma * eq2->ggamma;
|
||||
eq2->param[1].g = sqrt (eq2->bgamma / eq2->ggamma);
|
||||
eq2->param[2].g = sqrt (eq2->rgamma / eq2->ggamma);
|
||||
eq2->param[0].w = eq2->param[1].w = eq2->param[2].w = eq2->gamma_weight;
|
||||
|
||||
eq2->param[0].lut_clean = 0;
|
||||
eq2->param[1].lut_clean = 0;
|
||||
eq2->param[2].lut_clean = 0;
|
||||
|
||||
check_values (&eq2->param[0]);
|
||||
check_values (&eq2->param[1]);
|
||||
check_values (&eq2->param[2]);
|
||||
|
||||
print_values (eq2);
|
||||
}
|
||||
|
||||
static
|
||||
void set_saturation (vf_eq2_t *eq2, double s)
|
||||
{
|
||||
eq2->saturation = s;
|
||||
|
||||
eq2->param[1].c = s;
|
||||
eq2->param[2].c = s;
|
||||
|
||||
eq2->param[1].lut_clean = 0;
|
||||
eq2->param[2].lut_clean = 0;
|
||||
|
||||
check_values (&eq2->param[1]);
|
||||
check_values (&eq2->param[2]);
|
||||
|
||||
print_values (eq2);
|
||||
}
|
||||
|
||||
static
|
||||
int control (vf_instance_t *vf, int request, void *data)
|
||||
{
|
||||
vf_equalizer_t *eq;
|
||||
|
||||
switch (request) {
|
||||
case VFCTRL_SET_EQUALIZER:
|
||||
eq = (vf_equalizer_t *) data;
|
||||
|
||||
if (strcmp (eq->item, "gamma") == 0) {
|
||||
set_gamma (vf->priv, exp (log (8.0) * eq->value / 100.0));
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
else if (strcmp (eq->item, "contrast") == 0) {
|
||||
set_contrast (vf->priv, (1.0 / 100.0) * (eq->value + 100));
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
else if (strcmp (eq->item, "brightness") == 0) {
|
||||
set_brightness (vf->priv, (1.0 / 100.0) * eq->value);
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
else if (strcmp (eq->item, "saturation") == 0) {
|
||||
set_saturation (vf->priv, (double) (eq->value + 100) / 100.0);
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case VFCTRL_GET_EQUALIZER:
|
||||
eq = (vf_equalizer_t *) data;
|
||||
if (strcmp (eq->item, "gamma") == 0) {
|
||||
eq->value = (int) (100.0 * log (vf->priv->gamma) / log (8.0));
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
else if (strcmp (eq->item, "contrast") == 0) {
|
||||
eq->value = (int) (100.0 * vf->priv->contrast) - 100;
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
else if (strcmp (eq->item, "brightness") == 0) {
|
||||
eq->value = (int) (100.0 * vf->priv->brightness);
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
else if (strcmp (eq->item, "saturation") == 0) {
|
||||
eq->value = (int) (100.0 * vf->priv->saturation) - 100;
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return vf_next_control (vf, request, data);
|
||||
}
|
||||
|
||||
static
|
||||
int query_format (vf_instance_t *vf, unsigned fmt)
|
||||
{
|
||||
switch (fmt) {
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_IF09:
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_Y800:
|
||||
case IMGFMT_Y8:
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
return vf_next_query_format (vf, fmt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
void uninit (vf_instance_t *vf)
|
||||
{
|
||||
if (vf->priv != NULL) {
|
||||
free (vf->priv->buf[0]);
|
||||
free (vf->priv);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
unsigned i;
|
||||
vf_eq2_t *eq2;
|
||||
double par[8];
|
||||
|
||||
vf->control = control;
|
||||
vf->query_format = query_format;
|
||||
vf->put_image = put_image;
|
||||
vf->uninit = uninit;
|
||||
|
||||
vf->priv = malloc (sizeof (vf_eq2_t));
|
||||
eq2 = vf->priv;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
eq2->buf[i] = NULL;
|
||||
eq2->buf_w[i] = 0;
|
||||
eq2->buf_h[i] = 0;
|
||||
|
||||
eq2->param[i].adjust = NULL;
|
||||
eq2->param[i].c = 1.0;
|
||||
eq2->param[i].b = 0.0;
|
||||
eq2->param[i].g = 1.0;
|
||||
eq2->param[i].lut_clean = 0;
|
||||
}
|
||||
|
||||
eq2->contrast = 1.0;
|
||||
eq2->brightness = 0.0;
|
||||
eq2->saturation = 1.0;
|
||||
|
||||
eq2->gamma = 1.0;
|
||||
eq2->gamma_weight = 1.0;
|
||||
eq2->rgamma = 1.0;
|
||||
eq2->ggamma = 1.0;
|
||||
eq2->bgamma = 1.0;
|
||||
|
||||
if (args != NULL) {
|
||||
par[0] = 1.0;
|
||||
par[1] = 1.0;
|
||||
par[2] = 0.0;
|
||||
par[3] = 1.0;
|
||||
par[4] = 1.0;
|
||||
par[5] = 1.0;
|
||||
par[6] = 1.0;
|
||||
par[7] = 1.0;
|
||||
sscanf (args, "%lf:%lf:%lf:%lf:%lf:%lf:%lf:%lf",
|
||||
par, par + 1, par + 2, par + 3, par + 4, par + 5, par + 6, par + 7
|
||||
);
|
||||
|
||||
eq2->rgamma = par[4];
|
||||
eq2->ggamma = par[5];
|
||||
eq2->bgamma = par[6];
|
||||
eq2->gamma_weight = par[7];
|
||||
|
||||
set_gamma (eq2, par[0]);
|
||||
set_contrast (eq2, par[1]);
|
||||
set_brightness (eq2, par[2]);
|
||||
set_saturation (eq2, par[3]);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_eq2 = {
|
||||
"Software equalizer",
|
||||
"eq2",
|
||||
"Hampa Hug, Daniel Moreno, Richard Felker",
|
||||
"",
|
||||
&vf_open,
|
||||
NULL
|
||||
};
|
||||
89
libavfilter/libmpcodecs/vf_field.c
Normal file
89
libavfilter/libmpcodecs/vf_field.c
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
int field;
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
return vf_next_config(vf,width,height/2,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->width, mpi->height/2);
|
||||
|
||||
// set up mpi as a double-stride image of dmpi:
|
||||
vf->dmpi->planes[0]=mpi->planes[0]+mpi->stride[0]*vf->priv->field;
|
||||
vf->dmpi->stride[0]=2*mpi->stride[0];
|
||||
if(vf->dmpi->flags&MP_IMGFLAG_PLANAR){
|
||||
vf->dmpi->planes[1]=mpi->planes[1]+
|
||||
mpi->stride[1]*vf->priv->field;
|
||||
vf->dmpi->stride[1]=2*mpi->stride[1];
|
||||
vf->dmpi->planes[2]=mpi->planes[2]+
|
||||
mpi->stride[2]*vf->priv->field;
|
||||
vf->dmpi->stride[2]=2*mpi->stride[2];
|
||||
} else
|
||||
vf->dmpi->planes[1]=mpi->planes[1]; // passthru bgr8 palette!!!
|
||||
|
||||
return vf_next_put_image(vf,vf->dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->uninit=uninit;
|
||||
vf->default_reqs=VFCAP_ACCEPT_STRIDE;
|
||||
vf->priv=calloc(1, sizeof(struct vf_priv_s));
|
||||
if (args) sscanf(args, "%d", &vf->priv->field);
|
||||
vf->priv->field &= 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_field = {
|
||||
"extract single field",
|
||||
"field",
|
||||
"Rich Felker",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
116
libavfilter/libmpcodecs/vf_fil.c
Normal file
116
libavfilter/libmpcodecs/vf_fil.c
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
int interleave;
|
||||
int height;
|
||||
int width;
|
||||
int stridefactor;
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
int pixel_stride= (width+15)&~15; //FIXME this is ust a guess ... especially for non planar its somewhat bad one
|
||||
|
||||
#if 0
|
||||
if(mpi->flags&MP_IMGFLAG_PLANAR)
|
||||
pixel_stride= mpi->stride[0];
|
||||
else
|
||||
pixel_stride= 8*mpi->stride[0] / mpi->bpp;
|
||||
|
||||
#endif
|
||||
|
||||
if(vf->priv->interleave){
|
||||
vf->priv->height= 2*height;
|
||||
vf->priv->width= width - (pixel_stride/2);
|
||||
vf->priv->stridefactor=1;
|
||||
}else{
|
||||
vf->priv->height= height/2;
|
||||
vf->priv->width= width + pixel_stride;
|
||||
vf->priv->stridefactor=4;
|
||||
}
|
||||
//printf("hX %d %d %d\n", vf->priv->width,vf->priv->height,vf->priv->stridefactor);
|
||||
|
||||
return vf_next_config(vf, vf->priv->width, vf->priv->height,
|
||||
(d_width*vf->priv->stridefactor)>>1, 2*d_height/vf->priv->stridefactor, flags, outfmt);
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
if(mpi->flags&MP_IMGFLAG_DIRECT){
|
||||
// we've used DR, so we're ready...
|
||||
return vf_next_put_image(vf,(mp_image_t*)mpi->priv, pts);
|
||||
}
|
||||
|
||||
vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
vf->priv->width, vf->priv->height);
|
||||
|
||||
// set up mpi as a double-stride image of dmpi:
|
||||
vf->dmpi->planes[0]=mpi->planes[0];
|
||||
vf->dmpi->stride[0]=(mpi->stride[0]*vf->priv->stridefactor)>>1;
|
||||
if(vf->dmpi->flags&MP_IMGFLAG_PLANAR){
|
||||
vf->dmpi->planes[1]=mpi->planes[1];
|
||||
vf->dmpi->stride[1]=(mpi->stride[1]*vf->priv->stridefactor)>>1;
|
||||
vf->dmpi->planes[2]=mpi->planes[2];
|
||||
vf->dmpi->stride[2]=(mpi->stride[2]*vf->priv->stridefactor)>>1;
|
||||
} else
|
||||
vf->dmpi->planes[1]=mpi->planes[1]; // passthru bgr8 palette!!!
|
||||
|
||||
return vf_next_put_image(vf,vf->dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->uninit=uninit;
|
||||
vf->default_reqs=VFCAP_ACCEPT_STRIDE;
|
||||
vf->priv=calloc(1, sizeof(struct vf_priv_s));
|
||||
vf->priv->interleave= args && (*args == 'i');
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_fil = {
|
||||
"fast (de)interleaver",
|
||||
"fil",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
1461
libavfilter/libmpcodecs/vf_filmdint.c
Normal file
1461
libavfilter/libmpcodecs/vf_filmdint.c
Normal file
File diff suppressed because it is too large
Load Diff
137
libavfilter/libmpcodecs/vf_fixpts.c
Normal file
137
libavfilter/libmpcodecs/vf_fixpts.c
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "help_mp.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
double current;
|
||||
double step;
|
||||
int autostart;
|
||||
int autostep;
|
||||
unsigned have_step:1;
|
||||
unsigned print:1;
|
||||
};
|
||||
|
||||
static int put_image(vf_instance_t *vf, mp_image_t *src, double pts)
|
||||
{
|
||||
struct vf_priv_s *p = vf->priv;
|
||||
|
||||
if (p->print) {
|
||||
if (pts == MP_NOPTS_VALUE)
|
||||
mp_msg(MSGT_VFILTER, MSGL_INFO, "PTS: undef\n");
|
||||
else
|
||||
mp_msg(MSGT_VFILTER, MSGL_INFO, "PTS: %f\n", pts);
|
||||
}
|
||||
if (pts != MP_NOPTS_VALUE && p->autostart != 0) {
|
||||
p->current = pts;
|
||||
if (p->autostart > 0)
|
||||
p->autostart--;
|
||||
} else if (pts != MP_NOPTS_VALUE && p->autostep > 0) {
|
||||
p->step = pts - p->current;
|
||||
p->current = pts;
|
||||
p->autostep--;
|
||||
p->have_step = 1;
|
||||
} else if (p->have_step) {
|
||||
p->current += p->step;
|
||||
pts = p->current;
|
||||
} else {
|
||||
pts = MP_NOPTS_VALUE;
|
||||
}
|
||||
return vf_next_put_image(vf, src, pts);
|
||||
}
|
||||
|
||||
static void uninit(vf_instance_t *vf)
|
||||
{
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int parse_args(struct vf_priv_s *p, const char *args)
|
||||
{
|
||||
int pos;
|
||||
double num, denom = 1;
|
||||
int iarg;
|
||||
|
||||
while (*args != 0) {
|
||||
pos = 0;
|
||||
if (sscanf(args, "print%n", &pos) == 0 && pos > 0) {
|
||||
p->print = 1;
|
||||
} else if (sscanf(args, "fps=%lf%n/%lf%n", &num, &pos, &denom, &pos) >=
|
||||
1 && pos > 0) {
|
||||
p->step = denom / num;
|
||||
p->have_step = 1;
|
||||
} else if (sscanf(args, "start=%lf%n", &num, &pos) >= 1 && pos > 0) {
|
||||
p->current = num;
|
||||
} else if (sscanf(args, "autostart=%d%n", &iarg, &pos) == 1 && pos > 0) {
|
||||
p->autostart = iarg;
|
||||
} else if (sscanf(args, "autofps=%d%n", &iarg, &pos) == 1 && pos > 0) {
|
||||
p->autostep = iarg;
|
||||
} else {
|
||||
mp_msg(MSGT_VFILTER, MSGL_FATAL,
|
||||
"fixpts: unknown suboption: %s\n", args);
|
||||
return 0;
|
||||
}
|
||||
args += pos;
|
||||
if (*args == ':')
|
||||
args++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
struct vf_priv_s *p;
|
||||
struct vf_priv_s ptmp = {
|
||||
.current = 0,
|
||||
.step = 0,
|
||||
.autostart = 0,
|
||||
.autostep = 0,
|
||||
.have_step = 0,
|
||||
.print = 0,
|
||||
};
|
||||
|
||||
if (!parse_args(&ptmp, args == NULL ? "" : args))
|
||||
return 0;
|
||||
|
||||
vf->put_image = put_image;
|
||||
vf->uninit = uninit;
|
||||
vf->priv = p = malloc(sizeof(struct vf_priv_s));
|
||||
*p = ptmp;
|
||||
p->current = -p->step;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_fixpts = {
|
||||
"Fix presentation timestamps",
|
||||
"fixpts",
|
||||
"Nicolas George",
|
||||
"",
|
||||
&open,
|
||||
NULL
|
||||
};
|
||||
205
libavfilter/libmpcodecs/vf_framestep.c
Normal file
205
libavfilter/libmpcodecs/vf_framestep.c
Normal file
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* filter to ouput only 1 every n frame, or only the I (key)frame
|
||||
*
|
||||
* The parameters are:
|
||||
*
|
||||
* [I] | [i]num
|
||||
*
|
||||
* if you call the filter with I (uppercase) as the parameter
|
||||
* ... -vf framestep=I ...
|
||||
* then ONLY the keyframes are outputted.
|
||||
* For DVD it means, generally, one every 15 frames (IBBPBBPBBPBBPBB), for avi it means
|
||||
* every scene change or every keyint value (see -lavcopts).
|
||||
*
|
||||
* if you call the filter with the i (lowercase)
|
||||
* ... -vf framestep=i ...
|
||||
* then a I! followed by a cr is printed when a key frame (eg Intra frame) is
|
||||
* found, leaving the current line of mplayer/mencoder, where you got the
|
||||
* time, in seconds, and frame of the key. Use this information to split the
|
||||
* AVI.
|
||||
*
|
||||
* After the i or alone you can put a positive number and only one frame every
|
||||
* x (the number you set) is passed on the filter chain, limiting the output
|
||||
* of the frame.
|
||||
*
|
||||
* Example
|
||||
* ... -vf framestep=i20 ...
|
||||
* Dump one every 20 frames, printing on the console when a I-Frame is encounter.
|
||||
*
|
||||
* ... -vf framestep=25
|
||||
* Dump one every 25 frames.
|
||||
*
|
||||
* If you call the filter without parameter it does nothing (except using memory
|
||||
* and resource of your system,. of course).
|
||||
*
|
||||
* This filter doesn' t work like the option -sstep seconds.
|
||||
*
|
||||
* The -sstep seek to the new position, without decoding all frames but,
|
||||
* expecially on avi file coded whith mpeg4 (lavc or xvid or divx), the
|
||||
* seek is not always too much precise.
|
||||
*
|
||||
* This filter simply discard the unwanted frames, so you are very precise in
|
||||
* counting the frame but sometime you use a lot of CPU for nothing.
|
||||
*
|
||||
* As usual it depends on what you're doing.
|
||||
*
|
||||
* copyright (c) 2003 Daniele Forghieri ( guru@digitalfantasy.it )
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "help_mp.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
/* Uncomment if you want to print some info on the format */
|
||||
// #define DUMP_FORMAT_DATA
|
||||
|
||||
/* Private data */
|
||||
struct vf_priv_s {
|
||||
/* Current frame */
|
||||
int frame_cur;
|
||||
/* Frame output step, 0 = all */
|
||||
int frame_step;
|
||||
/* Only I-Frame (2), print on I-Frame (1) */
|
||||
int dump_iframe;
|
||||
};
|
||||
|
||||
/* Filter handler */
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
mp_image_t *dmpi;
|
||||
struct vf_priv_s *priv;
|
||||
int skip;
|
||||
|
||||
priv = vf->priv;
|
||||
|
||||
/* Print the 'I' if is a intra frame. The \n advance the current line so you got the
|
||||
* current file time (in second) and the frame number on the console ;-)
|
||||
*/
|
||||
if (priv->dump_iframe) {
|
||||
if (mpi->pict_type == 1) {
|
||||
mp_msg(MSGT_VFILTER, MSGL_INFO, "I!\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* decide if frame must be shown */
|
||||
if (priv->dump_iframe == 2) {
|
||||
/* Only key frame */
|
||||
skip = mpi->pict_type == 1 ? 0 : 1;
|
||||
}
|
||||
else {
|
||||
/* Only 1 every frame_step */
|
||||
skip = 0;
|
||||
if ((priv->frame_step != 0) && ((priv->frame_cur % priv->frame_step) != 0)) {
|
||||
skip = 1;
|
||||
}
|
||||
}
|
||||
/* Increment current frame */
|
||||
++priv->frame_cur;
|
||||
|
||||
if (skip == 0) {
|
||||
/* Get image, export type (we don't modify tghe image) */
|
||||
dmpi=vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_EXPORT, 0,
|
||||
mpi->w, mpi->h);
|
||||
/* Copy only the pointer ( MP_IMGTYPE_EXPORT ! ) */
|
||||
dmpi->planes[0] = mpi->planes[0];
|
||||
dmpi->planes[1] = mpi->planes[1];
|
||||
dmpi->planes[2] = mpi->planes[2];
|
||||
|
||||
dmpi->stride[0] = mpi->stride[0];
|
||||
dmpi->stride[1] = mpi->stride[1];
|
||||
dmpi->stride[2] = mpi->stride[2];
|
||||
|
||||
dmpi->width = mpi->width;
|
||||
dmpi->height = mpi->height;
|
||||
|
||||
/* Chain to next filter / output ... */
|
||||
return vf_next_put_image(vf, dmpi, pts);
|
||||
}
|
||||
|
||||
/* Skip the frame */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
/* Free private data */
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
/* Main entry funct for the filter */
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
struct vf_priv_s *p;
|
||||
|
||||
vf->put_image = put_image;
|
||||
vf->uninit = uninit;
|
||||
vf->default_reqs = VFCAP_ACCEPT_STRIDE;
|
||||
vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
|
||||
if (p == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (args != NULL) {
|
||||
#ifdef DUMP_FORMAT_DATA
|
||||
if (*args == 'd') {
|
||||
p->dump_iframe = 3;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (*args == 'I') {
|
||||
/* Dump only KEY (ie INTRA) frame */
|
||||
p->dump_iframe = 2;
|
||||
}
|
||||
else {
|
||||
if (*args == 'i') {
|
||||
/* Print a 'I!' when a i-frame is encounter */
|
||||
p->dump_iframe = 1;
|
||||
++args;
|
||||
}
|
||||
|
||||
if (*args != '\0') {
|
||||
p->frame_step = atoi(args);
|
||||
if (p->frame_step <= 0) {
|
||||
mp_msg(MSGT_VFILTER, MSGL_WARN, MSGTR_MPCODECS_ErrorParsingArgument);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_framestep = {
|
||||
"Dump one every n / key frames",
|
||||
"framestep",
|
||||
"Daniele Forghieri",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
2117
libavfilter/libmpcodecs/vf_fspp.c
Normal file
2117
libavfilter/libmpcodecs/vf_fspp.c
Normal file
File diff suppressed because it is too large
Load Diff
197
libavfilter/libmpcodecs/vf_geq.c
Normal file
197
libavfilter/libmpcodecs/vf_geq.c
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavutil/eval.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
AVExpr * e[3];
|
||||
int framenum;
|
||||
mp_image_t *mpi;
|
||||
};
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static inline double getpix(struct vf_instance *vf, double x, double y, int plane){
|
||||
int xi, yi;
|
||||
mp_image_t *mpi= vf->priv->mpi;
|
||||
int stride= mpi->stride[plane];
|
||||
uint8_t *src= mpi->planes[plane];
|
||||
xi=x= FFMIN(FFMAX(x, 0), (mpi->w >> (plane ? mpi->chroma_x_shift : 0))-1);
|
||||
yi=y= FFMIN(FFMAX(y, 0), (mpi->h >> (plane ? mpi->chroma_y_shift : 0))-1);
|
||||
|
||||
x-=xi;
|
||||
y-=yi;
|
||||
|
||||
return
|
||||
(1-y)*((1-x)*src[xi + yi * stride] + x*src[xi + 1 + yi * stride])
|
||||
+ y *((1-x)*src[xi + (yi+1) * stride] + x*src[xi + 1 + (yi+1) * stride]);
|
||||
}
|
||||
|
||||
//FIXME cubic interpolate
|
||||
//FIXME keep the last few frames
|
||||
static double lum(void *vf, double x, double y){
|
||||
return getpix(vf, x, y, 0);
|
||||
}
|
||||
|
||||
static double cb(void *vf, double x, double y){
|
||||
return getpix(vf, x, y, 1);
|
||||
}
|
||||
|
||||
static double cr(void *vf, double x, double y){
|
||||
return getpix(vf, x, y, 2);
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
int x,y, plane;
|
||||
|
||||
if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
|
||||
// no DR, so get a new image! hope we'll get DR buffer:
|
||||
vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, MP_IMGTYPE_TEMP,
|
||||
MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
|
||||
mpi->w,mpi->h);
|
||||
}
|
||||
|
||||
dmpi= vf->dmpi;
|
||||
vf->priv->mpi= mpi;
|
||||
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
|
||||
for(plane=0; plane<3; plane++){
|
||||
int w= mpi->w >> (plane ? mpi->chroma_x_shift : 0);
|
||||
int h= mpi->h >> (plane ? mpi->chroma_y_shift : 0);
|
||||
uint8_t *dst = dmpi->planes[plane];
|
||||
int dst_stride= dmpi->stride[plane];
|
||||
double const_values[]={
|
||||
M_PI,
|
||||
M_E,
|
||||
0,
|
||||
0,
|
||||
w,
|
||||
h,
|
||||
vf->priv->framenum,
|
||||
w/(double)mpi->w,
|
||||
h/(double)mpi->h,
|
||||
0
|
||||
};
|
||||
if (!vf->priv->e[plane]) continue;
|
||||
for(y=0; y<h; y++){
|
||||
const_values[3]=y;
|
||||
for(x=0; x<w; x++){
|
||||
const_values[2]=x;
|
||||
dst[x + y * dst_stride] = av_eval_expr(vf->priv->e[plane],
|
||||
const_values, vf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vf->priv->framenum++;
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf){
|
||||
av_free(vf->priv);
|
||||
vf->priv=NULL;
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
char eq[3][2000] = { { 0 }, { 0 }, { 0 } };
|
||||
int plane, res;
|
||||
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
// vf->get_image=get_image;
|
||||
vf->uninit=uninit;
|
||||
vf->priv=av_malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
|
||||
if (args) sscanf(args, "%1999[^:]:%1999[^:]:%1999[^:]", eq[0], eq[1], eq[2]);
|
||||
|
||||
if (!eq[1][0]) strncpy(eq[1], eq[0], sizeof(eq[0])-1);
|
||||
if (!eq[2][0]) strncpy(eq[2], eq[1], sizeof(eq[0])-1);
|
||||
|
||||
for(plane=0; plane<3; plane++){
|
||||
static const char *const_names[]={
|
||||
"PI",
|
||||
"E",
|
||||
"X",
|
||||
"Y",
|
||||
"W",
|
||||
"H",
|
||||
"N",
|
||||
"SW",
|
||||
"SH",
|
||||
NULL
|
||||
};
|
||||
static const char *func2_names[]={
|
||||
"lum",
|
||||
"cb",
|
||||
"cr",
|
||||
"p",
|
||||
NULL
|
||||
};
|
||||
double (*func2[])(void *, double, double)={
|
||||
lum,
|
||||
cb,
|
||||
cr,
|
||||
plane==0 ? lum : (plane==1 ? cb : cr),
|
||||
NULL
|
||||
};
|
||||
res = av_parse_expr(&vf->priv->e[plane], eq[plane], const_names, NULL, NULL, func2_names, func2, 0, NULL);
|
||||
|
||||
if (res < 0) {
|
||||
mp_msg(MSGT_VFILTER, MSGL_ERR, "geq: error loading equation `%s'\n", eq[plane]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_geq = {
|
||||
"generic equation filter",
|
||||
"geq",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
411
libavfilter/libmpcodecs/vf_gradfun.c
Normal file
411
libavfilter/libmpcodecs/vf_gradfun.c
Normal file
@ -0,0 +1,411 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Loren Merritt <lorenm@u.washignton.edu>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Debanding algorithm (from gradfun2db by prunedtree):
|
||||
* Boxblur.
|
||||
* Foreach pixel, if it's within threshold of the blurred value, make it closer.
|
||||
* So now we have a smoothed and higher bitdepth version of all the shallow
|
||||
* gradients, while leaving detailed areas untouched.
|
||||
* Dither it back to 8bit.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "cpudetect.h"
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
#include "libvo/fastmemcpy.h"
|
||||
#include "libavutil/avutil.h"
|
||||
#include "libavutil/x86_cpu.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
int thresh;
|
||||
int radius;
|
||||
uint16_t *buf;
|
||||
void (*filter_line)(uint8_t *dst, uint8_t *src, uint16_t *dc,
|
||||
int width, int thresh, const uint16_t *dithers);
|
||||
void (*blur_line)(uint16_t *dc, uint16_t *buf, uint16_t *buf1,
|
||||
uint8_t *src, int sstride, int width);
|
||||
};
|
||||
|
||||
static const uint16_t __attribute__((aligned(16))) pw_7f[8] = {127,127,127,127,127,127,127,127};
|
||||
static const uint16_t __attribute__((aligned(16))) pw_ff[8] = {255,255,255,255,255,255,255,255};
|
||||
static const uint16_t __attribute__((aligned(16))) dither[8][8] = {
|
||||
{ 0, 96, 24,120, 6,102, 30,126 },
|
||||
{ 64, 32, 88, 56, 70, 38, 94, 62 },
|
||||
{ 16,112, 8,104, 22,118, 14,110 },
|
||||
{ 80, 48, 72, 40, 86, 54, 78, 46 },
|
||||
{ 4,100, 28,124, 2, 98, 26,122 },
|
||||
{ 68, 36, 92, 60, 66, 34, 90, 58 },
|
||||
{ 20,116, 12,108, 18,114, 10,106 },
|
||||
{ 84, 52, 76, 44, 82, 50, 74, 42 },
|
||||
};
|
||||
|
||||
static void filter_line_c(uint8_t *dst, uint8_t *src, uint16_t *dc,
|
||||
int width, int thresh, const uint16_t *dithers)
|
||||
{
|
||||
int x;
|
||||
for (x=0; x<width; x++, dc+=x&1) {
|
||||
int pix = src[x]<<7;
|
||||
int delta = dc[0] - pix;
|
||||
int m = abs(delta) * thresh >> 16;
|
||||
m = FFMAX(0, 127-m);
|
||||
m = m*m*delta >> 14;
|
||||
pix += m + dithers[x&7];
|
||||
dst[x] = av_clip_uint8(pix>>7);
|
||||
}
|
||||
}
|
||||
|
||||
static void blur_line_c(uint16_t *dc, uint16_t *buf, uint16_t *buf1,
|
||||
uint8_t *src, int sstride, int width)
|
||||
{
|
||||
int x, v, old;
|
||||
for (x=0; x<width; x++) {
|
||||
v = buf1[x] + src[2*x] + src[2*x+1] + src[2*x+sstride] + src[2*x+1+sstride];
|
||||
old = buf[x];
|
||||
buf[x] = v;
|
||||
dc[x] = v - old;
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_MMX2
|
||||
static void filter_line_mmx2(uint8_t *dst, uint8_t *src, uint16_t *dc,
|
||||
int width, int thresh, const uint16_t *dithers)
|
||||
{
|
||||
intptr_t x;
|
||||
if (width&3) {
|
||||
x = width&~3;
|
||||
filter_line_c(dst+x, src+x, dc+x/2, width-x, thresh, dithers);
|
||||
width = x;
|
||||
}
|
||||
x = -width;
|
||||
__asm__ volatile(
|
||||
"movd %4, %%mm5 \n"
|
||||
"pxor %%mm7, %%mm7 \n"
|
||||
"pshufw $0, %%mm5, %%mm5 \n"
|
||||
"movq %6, %%mm6 \n"
|
||||
"movq %5, %%mm4 \n"
|
||||
"1: \n"
|
||||
"movd (%2,%0), %%mm0 \n"
|
||||
"movd (%3,%0), %%mm1 \n"
|
||||
"punpcklbw %%mm7, %%mm0 \n"
|
||||
"punpcklwd %%mm1, %%mm1 \n"
|
||||
"psllw $7, %%mm0 \n"
|
||||
"pxor %%mm2, %%mm2 \n"
|
||||
"psubw %%mm0, %%mm1 \n" // delta = dc - pix
|
||||
"psubw %%mm1, %%mm2 \n"
|
||||
"pmaxsw %%mm1, %%mm2 \n"
|
||||
"pmulhuw %%mm5, %%mm2 \n" // m = abs(delta) * thresh >> 16
|
||||
"psubw %%mm6, %%mm2 \n"
|
||||
"pminsw %%mm7, %%mm2 \n" // m = -max(0, 127-m)
|
||||
"pmullw %%mm2, %%mm2 \n"
|
||||
"paddw %%mm4, %%mm0 \n" // pix += dither
|
||||
"pmulhw %%mm2, %%mm1 \n"
|
||||
"psllw $2, %%mm1 \n" // m = m*m*delta >> 14
|
||||
"paddw %%mm1, %%mm0 \n" // pix += m
|
||||
"psraw $7, %%mm0 \n"
|
||||
"packuswb %%mm0, %%mm0 \n"
|
||||
"movd %%mm0, (%1,%0) \n" // dst = clip(pix>>7)
|
||||
"add $4, %0 \n"
|
||||
"jl 1b \n"
|
||||
"emms \n"
|
||||
:"+r"(x)
|
||||
:"r"(dst+width), "r"(src+width), "r"(dc+width/2),
|
||||
"rm"(thresh), "m"(*dithers), "m"(*pw_7f)
|
||||
:"memory"
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_SSSE3
|
||||
static void filter_line_ssse3(uint8_t *dst, uint8_t *src, uint16_t *dc,
|
||||
int width, int thresh, const uint16_t *dithers)
|
||||
{
|
||||
intptr_t x;
|
||||
if (width&7) {
|
||||
// could be 10% faster if I somehow eliminated this
|
||||
x = width&~7;
|
||||
filter_line_c(dst+x, src+x, dc+x/2, width-x, thresh, dithers);
|
||||
width = x;
|
||||
}
|
||||
x = -width;
|
||||
__asm__ volatile(
|
||||
"movd %4, %%xmm5 \n"
|
||||
"pxor %%xmm7, %%xmm7 \n"
|
||||
"pshuflw $0,%%xmm5, %%xmm5 \n"
|
||||
"movdqa %6, %%xmm6 \n"
|
||||
"punpcklqdq %%xmm5, %%xmm5 \n"
|
||||
"movdqa %5, %%xmm4 \n"
|
||||
"1: \n"
|
||||
"movq (%2,%0), %%xmm0 \n"
|
||||
"movq (%3,%0), %%xmm1 \n"
|
||||
"punpcklbw %%xmm7, %%xmm0 \n"
|
||||
"punpcklwd %%xmm1, %%xmm1 \n"
|
||||
"psllw $7, %%xmm0 \n"
|
||||
"psubw %%xmm0, %%xmm1 \n" // delta = dc - pix
|
||||
"pabsw %%xmm1, %%xmm2 \n"
|
||||
"pmulhuw %%xmm5, %%xmm2 \n" // m = abs(delta) * thresh >> 16
|
||||
"psubw %%xmm6, %%xmm2 \n"
|
||||
"pminsw %%xmm7, %%xmm2 \n" // m = -max(0, 127-m)
|
||||
"pmullw %%xmm2, %%xmm2 \n"
|
||||
"psllw $1, %%xmm2 \n"
|
||||
"paddw %%xmm4, %%xmm0 \n" // pix += dither
|
||||
"pmulhrsw %%xmm2, %%xmm1 \n" // m = m*m*delta >> 14
|
||||
"paddw %%xmm1, %%xmm0 \n" // pix += m
|
||||
"psraw $7, %%xmm0 \n"
|
||||
"packuswb %%xmm0, %%xmm0 \n"
|
||||
"movq %%xmm0, (%1,%0) \n" // dst = clip(pix>>7)
|
||||
"add $8, %0 \n"
|
||||
"jl 1b \n"
|
||||
:"+&r"(x)
|
||||
:"r"(dst+width), "r"(src+width), "r"(dc+width/2),
|
||||
"rm"(thresh), "m"(*dithers), "m"(*pw_7f)
|
||||
:"memory"
|
||||
);
|
||||
}
|
||||
#endif // HAVE_SSSE3
|
||||
|
||||
#if HAVE_SSE2 && HAVE_6REGS
|
||||
#define BLURV(load)\
|
||||
intptr_t x = -2*width;\
|
||||
__asm__ volatile(\
|
||||
"movdqa %6, %%xmm7 \n"\
|
||||
"1: \n"\
|
||||
load" (%4,%0), %%xmm0 \n"\
|
||||
load" (%5,%0), %%xmm1 \n"\
|
||||
"movdqa %%xmm0, %%xmm2 \n"\
|
||||
"movdqa %%xmm1, %%xmm3 \n"\
|
||||
"psrlw $8, %%xmm0 \n"\
|
||||
"psrlw $8, %%xmm1 \n"\
|
||||
"pand %%xmm7, %%xmm2 \n"\
|
||||
"pand %%xmm7, %%xmm3 \n"\
|
||||
"paddw %%xmm1, %%xmm0 \n"\
|
||||
"paddw %%xmm3, %%xmm2 \n"\
|
||||
"paddw %%xmm2, %%xmm0 \n"\
|
||||
"paddw (%2,%0), %%xmm0 \n"\
|
||||
"movdqa (%1,%0), %%xmm1 \n"\
|
||||
"movdqa %%xmm0, (%1,%0) \n"\
|
||||
"psubw %%xmm1, %%xmm0 \n"\
|
||||
"movdqa %%xmm0, (%3,%0) \n"\
|
||||
"add $16, %0 \n"\
|
||||
"jl 1b \n"\
|
||||
:"+&r"(x)\
|
||||
:"r"(buf+width),\
|
||||
"r"(buf1+width),\
|
||||
"r"(dc+width),\
|
||||
"r"(src+width*2),\
|
||||
"r"(src+width*2+sstride),\
|
||||
"m"(*pw_ff)\
|
||||
:"memory"\
|
||||
);
|
||||
|
||||
static void blur_line_sse2(uint16_t *dc, uint16_t *buf, uint16_t *buf1,
|
||||
uint8_t *src, int sstride, int width)
|
||||
{
|
||||
if (((intptr_t)src|sstride)&15) {
|
||||
BLURV("movdqu");
|
||||
} else {
|
||||
BLURV("movdqa");
|
||||
}
|
||||
}
|
||||
#endif // HAVE_6REGS && HAVE_SSE2
|
||||
|
||||
static void filter(struct vf_priv_s *ctx, uint8_t *dst, uint8_t *src,
|
||||
int width, int height, int dstride, int sstride, int r)
|
||||
{
|
||||
int bstride = ((width+15)&~15)/2;
|
||||
int y;
|
||||
uint32_t dc_factor = (1<<21)/(r*r);
|
||||
uint16_t *dc = ctx->buf+16;
|
||||
uint16_t *buf = ctx->buf+bstride+32;
|
||||
int thresh = ctx->thresh;
|
||||
|
||||
memset(dc, 0, (bstride+16)*sizeof(*buf));
|
||||
for (y=0; y<r; y++)
|
||||
ctx->blur_line(dc, buf+y*bstride, buf+(y-1)*bstride, src+2*y*sstride, sstride, width/2);
|
||||
for (;;) {
|
||||
if (y < height-r) {
|
||||
int mod = ((y+r)/2)%r;
|
||||
uint16_t *buf0 = buf+mod*bstride;
|
||||
uint16_t *buf1 = buf+(mod?mod-1:r-1)*bstride;
|
||||
int x, v;
|
||||
ctx->blur_line(dc, buf0, buf1, src+(y+r)*sstride, sstride, width/2);
|
||||
for (x=v=0; x<r; x++)
|
||||
v += dc[x];
|
||||
for (; x<width/2; x++) {
|
||||
v += dc[x] - dc[x-r];
|
||||
dc[x-r] = v * dc_factor >> 16;
|
||||
}
|
||||
for (; x<(width+r+1)/2; x++)
|
||||
dc[x-r] = v * dc_factor >> 16;
|
||||
for (x=-r/2; x<0; x++)
|
||||
dc[x] = dc[0];
|
||||
}
|
||||
if (y == r) {
|
||||
for (y=0; y<r; y++)
|
||||
ctx->filter_line(dst+y*dstride, src+y*sstride, dc-r/2, width, thresh, dither[y&7]);
|
||||
}
|
||||
ctx->filter_line(dst+y*dstride, src+y*sstride, dc-r/2, width, thresh, dither[y&7]);
|
||||
if (++y >= height) break;
|
||||
ctx->filter_line(dst+y*dstride, src+y*sstride, dc-r/2, width, thresh, dither[y&7]);
|
||||
if (++y >= height) break;
|
||||
}
|
||||
}
|
||||
|
||||
static void get_image(struct vf_instance *vf, mp_image_t *mpi)
|
||||
{
|
||||
if (mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
|
||||
// ok, we can do pp in-place:
|
||||
vf->dmpi = vf_get_image(vf->next, mpi->imgfmt,
|
||||
mpi->type, mpi->flags, mpi->width, mpi->height);
|
||||
mpi->planes[0] = vf->dmpi->planes[0];
|
||||
mpi->stride[0] = vf->dmpi->stride[0];
|
||||
mpi->width = vf->dmpi->width;
|
||||
if (mpi->flags&MP_IMGFLAG_PLANAR){
|
||||
mpi->planes[1] = vf->dmpi->planes[1];
|
||||
mpi->planes[2] = vf->dmpi->planes[2];
|
||||
mpi->stride[1] = vf->dmpi->stride[1];
|
||||
mpi->stride[2] = vf->dmpi->stride[2];
|
||||
}
|
||||
mpi->flags |= MP_IMGFLAG_DIRECT;
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
mp_image_t *dmpi = vf->dmpi;
|
||||
int p;
|
||||
|
||||
if (!(mpi->flags&MP_IMGFLAG_DIRECT)) {
|
||||
// no DR, so get a new image. hope we'll get DR buffer:
|
||||
dmpi = vf_get_image(vf->next,mpi->imgfmt, MP_IMGTYPE_TEMP,
|
||||
MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
|
||||
mpi->w, mpi->h);
|
||||
}
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
|
||||
for (p=0; p<mpi->num_planes; p++) {
|
||||
int w = mpi->w;
|
||||
int h = mpi->h;
|
||||
int r = vf->priv->radius;
|
||||
if (p) {
|
||||
w >>= mpi->chroma_x_shift;
|
||||
h >>= mpi->chroma_y_shift;
|
||||
r = ((r>>mpi->chroma_x_shift) + (r>>mpi->chroma_y_shift)) / 2;
|
||||
r = av_clip((r+1)&~1,4,32);
|
||||
}
|
||||
if (FFMIN(w,h) > 2*r)
|
||||
filter(vf->priv, dmpi->planes[p], mpi->planes[p], w, h,
|
||||
dmpi->stride[p], mpi->stride[p], r);
|
||||
else if (dmpi->planes[p] != mpi->planes[p])
|
||||
memcpy_pic(dmpi->planes[p], mpi->planes[p], w, h,
|
||||
dmpi->stride[p], mpi->stride[p]);
|
||||
}
|
||||
|
||||
return vf_next_put_image(vf, dmpi, pts);
|
||||
}
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt)
|
||||
{
|
||||
switch (fmt){
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_IF09:
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_CLPL:
|
||||
case IMGFMT_Y800:
|
||||
case IMGFMT_Y8:
|
||||
case IMGFMT_NV12:
|
||||
case IMGFMT_NV21:
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
case IMGFMT_HM12:
|
||||
return vf_next_query_format(vf,fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt)
|
||||
{
|
||||
free(vf->priv->buf);
|
||||
vf->priv->buf = av_mallocz((((width+15)&~15)*(vf->priv->radius+1)/2+32)*sizeof(uint16_t));
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
if (!vf->priv) return;
|
||||
av_free(vf->priv->buf);
|
||||
free(vf->priv);
|
||||
vf->priv = NULL;
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
float thresh = 1.2;
|
||||
int radius = 16;
|
||||
|
||||
vf->get_image=get_image;
|
||||
vf->put_image=put_image;
|
||||
vf->query_format=query_format;
|
||||
vf->config=config;
|
||||
vf->uninit=uninit;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
|
||||
if (args) sscanf(args, "%f:%d", &thresh, &radius);
|
||||
vf->priv->thresh = (1<<15)/av_clipf(thresh,0.51,255);
|
||||
vf->priv->radius = av_clip((radius+1)&~1,4,32);
|
||||
|
||||
vf->priv->blur_line = blur_line_c;
|
||||
vf->priv->filter_line = filter_line_c;
|
||||
#if HAVE_SSE2 && HAVE_6REGS
|
||||
if (gCpuCaps.hasSSE2)
|
||||
vf->priv->blur_line = blur_line_sse2;
|
||||
#endif
|
||||
#if HAVE_MMX2
|
||||
if (gCpuCaps.hasMMX2)
|
||||
vf->priv->filter_line = filter_line_mmx2;
|
||||
#endif
|
||||
#if HAVE_SSSE3
|
||||
if (gCpuCaps.hasSSSE3)
|
||||
vf->priv->filter_line = filter_line_ssse3;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_gradfun = {
|
||||
"gradient deband",
|
||||
"gradfun",
|
||||
"Loren Merritt",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
92
libavfilter/libmpcodecs/vf_harddup.c
Normal file
92
libavfilter/libmpcodecs/vf_harddup.c
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
mp_image_t *last_mpi;
|
||||
};
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
mp_image_t *dmpi;
|
||||
|
||||
vf->priv->last_mpi = mpi;
|
||||
|
||||
dmpi = vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_EXPORT, 0, mpi->width, mpi->height);
|
||||
|
||||
dmpi->planes[0] = mpi->planes[0];
|
||||
dmpi->stride[0] = mpi->stride[0];
|
||||
if (dmpi->flags&MP_IMGFLAG_PLANAR) {
|
||||
dmpi->planes[1] = mpi->planes[1];
|
||||
dmpi->stride[1] = mpi->stride[1];
|
||||
dmpi->planes[2] = mpi->planes[2];
|
||||
dmpi->stride[2] = mpi->stride[2];
|
||||
}
|
||||
|
||||
return vf_next_put_image(vf, dmpi, pts);
|
||||
}
|
||||
|
||||
static int control(struct vf_instance *vf, int request, void* data)
|
||||
{
|
||||
switch (request) {
|
||||
case VFCTRL_DUPLICATE_FRAME:
|
||||
if (!vf->priv->last_mpi) break;
|
||||
// This is a huge hack. We assume nothing
|
||||
// has been called earlier in the filter chain
|
||||
// since the last put_image. This is reasonable
|
||||
// because we're handling a duplicate frame!
|
||||
if (put_image(vf, vf->priv->last_mpi, MP_NOPTS_VALUE))
|
||||
return CONTROL_TRUE;
|
||||
break;
|
||||
}
|
||||
return vf_next_control(vf, request, data);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
vf->put_image = put_image;
|
||||
vf->control = control;
|
||||
vf->uninit = uninit;
|
||||
vf->priv = calloc(1, sizeof(struct vf_priv_s));
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_harddup = {
|
||||
"resubmit duplicate frames for encoding",
|
||||
"harddup",
|
||||
"Rich Felker",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
373
libavfilter/libmpcodecs/vf_hqdn3d.c
Normal file
373
libavfilter/libmpcodecs/vf_hqdn3d.c
Normal file
@ -0,0 +1,373 @@
|
||||
/*
|
||||
* Copyright (C) 2003 Daniel Moreno <comac@comac.darktech.org>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "mp_msg.h"
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#define PARAM1_DEFAULT 4.0
|
||||
#define PARAM2_DEFAULT 3.0
|
||||
#define PARAM3_DEFAULT 6.0
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
struct vf_priv_s {
|
||||
int Coefs[4][512*16];
|
||||
unsigned int *Line;
|
||||
unsigned short *Frame[3];
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
free(vf->priv->Line);
|
||||
free(vf->priv->Frame[0]);
|
||||
free(vf->priv->Frame[1]);
|
||||
free(vf->priv->Frame[2]);
|
||||
|
||||
vf->priv->Line = NULL;
|
||||
vf->priv->Frame[0] = NULL;
|
||||
vf->priv->Frame[1] = NULL;
|
||||
vf->priv->Frame[2] = NULL;
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
|
||||
uninit(vf);
|
||||
vf->priv->Line = malloc(width*sizeof(int));
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static inline unsigned int LowPassMul(unsigned int PrevMul, unsigned int CurrMul, int* Coef){
|
||||
// int dMul= (PrevMul&0xFFFFFF)-(CurrMul&0xFFFFFF);
|
||||
int dMul= PrevMul-CurrMul;
|
||||
unsigned int d=((dMul+0x10007FF)>>12);
|
||||
return CurrMul + Coef[d];
|
||||
}
|
||||
|
||||
static void deNoiseTemporal(
|
||||
unsigned char *Frame, // mpi->planes[x]
|
||||
unsigned char *FrameDest, // dmpi->planes[x]
|
||||
unsigned short *FrameAnt,
|
||||
int W, int H, int sStride, int dStride,
|
||||
int *Temporal)
|
||||
{
|
||||
long X, Y;
|
||||
unsigned int PixelDst;
|
||||
|
||||
for (Y = 0; Y < H; Y++){
|
||||
for (X = 0; X < W; X++){
|
||||
PixelDst = LowPassMul(FrameAnt[X]<<8, Frame[X]<<16, Temporal);
|
||||
FrameAnt[X] = ((PixelDst+0x1000007F)>>8);
|
||||
FrameDest[X]= ((PixelDst+0x10007FFF)>>16);
|
||||
}
|
||||
Frame += sStride;
|
||||
FrameDest += dStride;
|
||||
FrameAnt += W;
|
||||
}
|
||||
}
|
||||
|
||||
static void deNoiseSpacial(
|
||||
unsigned char *Frame, // mpi->planes[x]
|
||||
unsigned char *FrameDest, // dmpi->planes[x]
|
||||
unsigned int *LineAnt, // vf->priv->Line (width bytes)
|
||||
int W, int H, int sStride, int dStride,
|
||||
int *Horizontal, int *Vertical)
|
||||
{
|
||||
long X, Y;
|
||||
long sLineOffs = 0, dLineOffs = 0;
|
||||
unsigned int PixelAnt;
|
||||
unsigned int PixelDst;
|
||||
|
||||
/* First pixel has no left nor top neighbor. */
|
||||
PixelDst = LineAnt[0] = PixelAnt = Frame[0]<<16;
|
||||
FrameDest[0]= ((PixelDst+0x10007FFF)>>16);
|
||||
|
||||
/* First line has no top neighbor, only left. */
|
||||
for (X = 1; X < W; X++){
|
||||
PixelDst = LineAnt[X] = LowPassMul(PixelAnt, Frame[X]<<16, Horizontal);
|
||||
FrameDest[X]= ((PixelDst+0x10007FFF)>>16);
|
||||
}
|
||||
|
||||
for (Y = 1; Y < H; Y++){
|
||||
unsigned int PixelAnt;
|
||||
sLineOffs += sStride, dLineOffs += dStride;
|
||||
/* First pixel on each line doesn't have previous pixel */
|
||||
PixelAnt = Frame[sLineOffs]<<16;
|
||||
PixelDst = LineAnt[0] = LowPassMul(LineAnt[0], PixelAnt, Vertical);
|
||||
FrameDest[dLineOffs]= ((PixelDst+0x10007FFF)>>16);
|
||||
|
||||
for (X = 1; X < W; X++){
|
||||
unsigned int PixelDst;
|
||||
/* The rest are normal */
|
||||
PixelAnt = LowPassMul(PixelAnt, Frame[sLineOffs+X]<<16, Horizontal);
|
||||
PixelDst = LineAnt[X] = LowPassMul(LineAnt[X], PixelAnt, Vertical);
|
||||
FrameDest[dLineOffs+X]= ((PixelDst+0x10007FFF)>>16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void deNoise(unsigned char *Frame, // mpi->planes[x]
|
||||
unsigned char *FrameDest, // dmpi->planes[x]
|
||||
unsigned int *LineAnt, // vf->priv->Line (width bytes)
|
||||
unsigned short **FrameAntPtr,
|
||||
int W, int H, int sStride, int dStride,
|
||||
int *Horizontal, int *Vertical, int *Temporal)
|
||||
{
|
||||
long X, Y;
|
||||
long sLineOffs = 0, dLineOffs = 0;
|
||||
unsigned int PixelAnt;
|
||||
unsigned int PixelDst;
|
||||
unsigned short* FrameAnt=(*FrameAntPtr);
|
||||
|
||||
if(!FrameAnt){
|
||||
(*FrameAntPtr)=FrameAnt=malloc(W*H*sizeof(unsigned short));
|
||||
for (Y = 0; Y < H; Y++){
|
||||
unsigned short* dst=&FrameAnt[Y*W];
|
||||
unsigned char* src=Frame+Y*sStride;
|
||||
for (X = 0; X < W; X++) dst[X]=src[X]<<8;
|
||||
}
|
||||
}
|
||||
|
||||
if(!Horizontal[0] && !Vertical[0]){
|
||||
deNoiseTemporal(Frame, FrameDest, FrameAnt,
|
||||
W, H, sStride, dStride, Temporal);
|
||||
return;
|
||||
}
|
||||
if(!Temporal[0]){
|
||||
deNoiseSpacial(Frame, FrameDest, LineAnt,
|
||||
W, H, sStride, dStride, Horizontal, Vertical);
|
||||
return;
|
||||
}
|
||||
|
||||
/* First pixel has no left nor top neighbor. Only previous frame */
|
||||
LineAnt[0] = PixelAnt = Frame[0]<<16;
|
||||
PixelDst = LowPassMul(FrameAnt[0]<<8, PixelAnt, Temporal);
|
||||
FrameAnt[0] = ((PixelDst+0x1000007F)>>8);
|
||||
FrameDest[0]= ((PixelDst+0x10007FFF)>>16);
|
||||
|
||||
/* First line has no top neighbor. Only left one for each pixel and
|
||||
* last frame */
|
||||
for (X = 1; X < W; X++){
|
||||
LineAnt[X] = PixelAnt = LowPassMul(PixelAnt, Frame[X]<<16, Horizontal);
|
||||
PixelDst = LowPassMul(FrameAnt[X]<<8, PixelAnt, Temporal);
|
||||
FrameAnt[X] = ((PixelDst+0x1000007F)>>8);
|
||||
FrameDest[X]= ((PixelDst+0x10007FFF)>>16);
|
||||
}
|
||||
|
||||
for (Y = 1; Y < H; Y++){
|
||||
unsigned int PixelAnt;
|
||||
unsigned short* LinePrev=&FrameAnt[Y*W];
|
||||
sLineOffs += sStride, dLineOffs += dStride;
|
||||
/* First pixel on each line doesn't have previous pixel */
|
||||
PixelAnt = Frame[sLineOffs]<<16;
|
||||
LineAnt[0] = LowPassMul(LineAnt[0], PixelAnt, Vertical);
|
||||
PixelDst = LowPassMul(LinePrev[0]<<8, LineAnt[0], Temporal);
|
||||
LinePrev[0] = ((PixelDst+0x1000007F)>>8);
|
||||
FrameDest[dLineOffs]= ((PixelDst+0x10007FFF)>>16);
|
||||
|
||||
for (X = 1; X < W; X++){
|
||||
unsigned int PixelDst;
|
||||
/* The rest are normal */
|
||||
PixelAnt = LowPassMul(PixelAnt, Frame[sLineOffs+X]<<16, Horizontal);
|
||||
LineAnt[X] = LowPassMul(LineAnt[X], PixelAnt, Vertical);
|
||||
PixelDst = LowPassMul(LinePrev[X]<<8, LineAnt[X], Temporal);
|
||||
LinePrev[X] = ((PixelDst+0x1000007F)>>8);
|
||||
FrameDest[dLineOffs+X]= ((PixelDst+0x10007FFF)>>16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
int cw= mpi->w >> mpi->chroma_x_shift;
|
||||
int ch= mpi->h >> mpi->chroma_y_shift;
|
||||
int W = mpi->w, H = mpi->h;
|
||||
|
||||
mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->w,mpi->h);
|
||||
|
||||
if(!dmpi) return 0;
|
||||
|
||||
deNoise(mpi->planes[0], dmpi->planes[0],
|
||||
vf->priv->Line, &vf->priv->Frame[0], W, H,
|
||||
mpi->stride[0], dmpi->stride[0],
|
||||
vf->priv->Coefs[0],
|
||||
vf->priv->Coefs[0],
|
||||
vf->priv->Coefs[1]);
|
||||
deNoise(mpi->planes[1], dmpi->planes[1],
|
||||
vf->priv->Line, &vf->priv->Frame[1], cw, ch,
|
||||
mpi->stride[1], dmpi->stride[1],
|
||||
vf->priv->Coefs[2],
|
||||
vf->priv->Coefs[2],
|
||||
vf->priv->Coefs[3]);
|
||||
deNoise(mpi->planes[2], dmpi->planes[2],
|
||||
vf->priv->Line, &vf->priv->Frame[2], cw, ch,
|
||||
mpi->stride[2], dmpi->stride[2],
|
||||
vf->priv->Coefs[2],
|
||||
vf->priv->Coefs[2],
|
||||
vf->priv->Coefs[3]);
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
switch(fmt)
|
||||
{
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define ABS(A) ( (A) > 0 ? (A) : -(A) )
|
||||
|
||||
static void PrecalcCoefs(int *Ct, double Dist25)
|
||||
{
|
||||
int i;
|
||||
double Gamma, Simil, C;
|
||||
|
||||
Gamma = log(0.25) / log(1.0 - Dist25/255.0 - 0.00001);
|
||||
|
||||
for (i = -255*16; i <= 255*16; i++)
|
||||
{
|
||||
Simil = 1.0 - ABS(i) / (16*255.0);
|
||||
C = pow(Simil, Gamma) * 65536.0 * (double)i / 16.0;
|
||||
Ct[16*256+i] = (C<0) ? (C-0.5) : (C+0.5);
|
||||
}
|
||||
|
||||
Ct[0] = (Dist25 != 0);
|
||||
}
|
||||
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
double LumSpac, LumTmp, ChromSpac, ChromTmp;
|
||||
double Param1, Param2, Param3, Param4;
|
||||
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->query_format=query_format;
|
||||
vf->uninit=uninit;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
|
||||
if (args)
|
||||
{
|
||||
switch(sscanf(args, "%lf:%lf:%lf:%lf",
|
||||
&Param1, &Param2, &Param3, &Param4
|
||||
))
|
||||
{
|
||||
case 0:
|
||||
LumSpac = PARAM1_DEFAULT;
|
||||
LumTmp = PARAM3_DEFAULT;
|
||||
|
||||
ChromSpac = PARAM2_DEFAULT;
|
||||
ChromTmp = LumTmp * ChromSpac / LumSpac;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
LumSpac = Param1;
|
||||
LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
|
||||
|
||||
ChromSpac = PARAM2_DEFAULT * Param1 / PARAM1_DEFAULT;
|
||||
ChromTmp = LumTmp * ChromSpac / LumSpac;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
LumSpac = Param1;
|
||||
LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
|
||||
|
||||
ChromSpac = Param2;
|
||||
ChromTmp = LumTmp * ChromSpac / LumSpac;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
LumSpac = Param1;
|
||||
LumTmp = Param3;
|
||||
|
||||
ChromSpac = Param2;
|
||||
ChromTmp = LumTmp * ChromSpac / LumSpac;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
LumSpac = Param1;
|
||||
LumTmp = Param3;
|
||||
|
||||
ChromSpac = Param2;
|
||||
ChromTmp = Param4;
|
||||
break;
|
||||
|
||||
default:
|
||||
LumSpac = PARAM1_DEFAULT;
|
||||
LumTmp = PARAM3_DEFAULT;
|
||||
|
||||
ChromSpac = PARAM2_DEFAULT;
|
||||
ChromTmp = LumTmp * ChromSpac / LumSpac;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LumSpac = PARAM1_DEFAULT;
|
||||
LumTmp = PARAM3_DEFAULT;
|
||||
|
||||
ChromSpac = PARAM2_DEFAULT;
|
||||
ChromTmp = LumTmp * ChromSpac / LumSpac;
|
||||
}
|
||||
|
||||
PrecalcCoefs(vf->priv->Coefs[0], LumSpac);
|
||||
PrecalcCoefs(vf->priv->Coefs[1], LumTmp);
|
||||
PrecalcCoefs(vf->priv->Coefs[2], ChromSpac);
|
||||
PrecalcCoefs(vf->priv->Coefs[3], ChromTmp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_hqdn3d = {
|
||||
"High Quality 3D Denoiser",
|
||||
"hqdn3d",
|
||||
"Daniel Moreno & A'rpi",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
200
libavfilter/libmpcodecs/vf_hue.c
Normal file
200
libavfilter/libmpcodecs/vf_hue.c
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#include "libvo/video_out.h"
|
||||
|
||||
#include "m_option.h"
|
||||
#include "m_struct.h"
|
||||
|
||||
static struct vf_priv_s {
|
||||
uint8_t *buf[2];
|
||||
float hue;
|
||||
float saturation;
|
||||
} const vf_priv_dflt = {
|
||||
{NULL, NULL},
|
||||
0.0,
|
||||
1.0,
|
||||
};
|
||||
|
||||
static void process_C(uint8_t *udst, uint8_t *vdst, uint8_t *usrc, uint8_t *vsrc, int dststride, int srcstride,
|
||||
int w, int h, float hue, float sat)
|
||||
{
|
||||
int i;
|
||||
const int s= rint(sin(hue) * (1<<16) * sat);
|
||||
const int c= rint(cos(hue) * (1<<16) * sat);
|
||||
|
||||
while (h--) {
|
||||
for (i = 0; i<w; i++)
|
||||
{
|
||||
const int u= usrc[i] - 128;
|
||||
const int v= vsrc[i] - 128;
|
||||
int new_u= (c*u - s*v + (1<<15) + (128<<16))>>16;
|
||||
int new_v= (s*u + c*v + (1<<15) + (128<<16))>>16;
|
||||
if(new_u & 768) new_u= (-new_u)>>31;
|
||||
if(new_v & 768) new_v= (-new_v)>>31;
|
||||
udst[i]= new_u;
|
||||
vdst[i]= new_v;
|
||||
}
|
||||
usrc += srcstride;
|
||||
vsrc += srcstride;
|
||||
udst += dststride;
|
||||
vdst += dststride;
|
||||
}
|
||||
}
|
||||
|
||||
static void (*process)(uint8_t *udst, uint8_t *vdst, uint8_t *usrc, uint8_t *vsrc, int dststride, int srcstride,
|
||||
int w, int h, float hue, float sat);
|
||||
|
||||
/* FIXME: add packed yuv version of process */
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
mp_image_t *dmpi;
|
||||
|
||||
dmpi=vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_EXPORT, 0,
|
||||
mpi->w, mpi->h);
|
||||
|
||||
dmpi->planes[0] = mpi->planes[0];
|
||||
dmpi->stride[0] = mpi->stride[0];
|
||||
dmpi->stride[1] = mpi->stride[1];
|
||||
dmpi->stride[2] = mpi->stride[2];
|
||||
|
||||
if (!vf->priv->buf[0]){
|
||||
vf->priv->buf[0] = malloc(mpi->stride[1]*mpi->h >> mpi->chroma_y_shift);
|
||||
vf->priv->buf[1] = malloc(mpi->stride[2]*mpi->h >> mpi->chroma_y_shift);
|
||||
}
|
||||
|
||||
if (vf->priv->hue == 0 && vf->priv->saturation == 1){
|
||||
dmpi->planes[1] = mpi->planes[1];
|
||||
dmpi->planes[2] = mpi->planes[2];
|
||||
}else {
|
||||
dmpi->planes[1] = vf->priv->buf[0];
|
||||
dmpi->planes[2] = vf->priv->buf[1];
|
||||
process(dmpi->planes[1], dmpi->planes[2],
|
||||
mpi->planes[1], mpi->planes[2],
|
||||
dmpi->stride[1],mpi->stride[1],
|
||||
mpi->w>> mpi->chroma_x_shift, mpi->h>> mpi->chroma_y_shift,
|
||||
vf->priv->hue, vf->priv->saturation);
|
||||
}
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
static int control(struct vf_instance *vf, int request, void* data)
|
||||
{
|
||||
vf_equalizer_t *eq;
|
||||
|
||||
switch (request) {
|
||||
case VFCTRL_SET_EQUALIZER:
|
||||
eq = data;
|
||||
if (!strcmp(eq->item,"hue")) {
|
||||
vf->priv->hue = eq->value * M_PI / 100;
|
||||
return CONTROL_TRUE;
|
||||
} else if (!strcmp(eq->item,"saturation")) {
|
||||
vf->priv->saturation = (eq->value + 100)/100.0;
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
break;
|
||||
case VFCTRL_GET_EQUALIZER:
|
||||
eq = data;
|
||||
if (!strcmp(eq->item,"hue")) {
|
||||
eq->value = rint(vf->priv->hue *100 / M_PI);
|
||||
return CONTROL_TRUE;
|
||||
}else if (!strcmp(eq->item,"saturation")) {
|
||||
eq->value = rint(vf->priv->saturation*100 - 100);
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return vf_next_control(vf, request, data);
|
||||
}
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt)
|
||||
{
|
||||
switch (fmt) {
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_IF09:
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_CLPL:
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
free(vf->priv->buf[0]);
|
||||
free(vf->priv->buf[1]);
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
vf->control=control;
|
||||
vf->query_format=query_format;
|
||||
vf->put_image=put_image;
|
||||
vf->uninit=uninit;
|
||||
|
||||
vf->priv->hue *= M_PI / 180.0;
|
||||
|
||||
process = process_C;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define ST_OFF(f) M_ST_OFF(struct vf_priv_s,f)
|
||||
static const m_option_t vf_opts_fields[] = {
|
||||
{"hue", ST_OFF(hue), CONF_TYPE_FLOAT, M_OPT_RANGE,-180.0 ,180.0, NULL},
|
||||
{"saturation", ST_OFF(saturation), CONF_TYPE_FLOAT, M_OPT_RANGE,-10.0 ,10.0, NULL},
|
||||
{ NULL, NULL, 0, 0, 0, 0, NULL }
|
||||
};
|
||||
|
||||
static const m_struct_t vf_opts = {
|
||||
"hue",
|
||||
sizeof(struct vf_priv_s),
|
||||
&vf_priv_dflt,
|
||||
vf_opts_fields
|
||||
};
|
||||
|
||||
const vf_info_t vf_info_hue = {
|
||||
"hue changer",
|
||||
"hue",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
&vf_opts
|
||||
};
|
||||
148
libavfilter/libmpcodecs/vf_il.c
Normal file
148
libavfilter/libmpcodecs/vf_il.c
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mp_msg.h"
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
typedef struct FilterParam{
|
||||
int interleave;
|
||||
int swap;
|
||||
}FilterParam;
|
||||
|
||||
struct vf_priv_s {
|
||||
FilterParam lumaParam;
|
||||
FilterParam chromaParam;
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static void interleave(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, int interleave, int swap){
|
||||
const int a= swap;
|
||||
const int b= 1-a;
|
||||
const int m= h>>1;
|
||||
int y;
|
||||
|
||||
switch(interleave){
|
||||
case -1:
|
||||
for(y=0; y < m; y++){
|
||||
fast_memcpy(dst + dstStride* y , src + srcStride*(y*2 + a), w);
|
||||
fast_memcpy(dst + dstStride*(y + m), src + srcStride*(y*2 + b), w);
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
for(y=0; y < m; y++){
|
||||
fast_memcpy(dst + dstStride* y*2 , src + srcStride*(y*2 + a), w);
|
||||
fast_memcpy(dst + dstStride*(y*2+1), src + srcStride*(y*2 + b), w);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
for(y=0; y < m; y++){
|
||||
fast_memcpy(dst + dstStride*(y*2+a), src + srcStride* y , w);
|
||||
fast_memcpy(dst + dstStride*(y*2+b), src + srcStride*(y + m), w);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
int w;
|
||||
FilterParam *luma = &vf->priv->lumaParam;
|
||||
FilterParam *chroma= &vf->priv->chromaParam;
|
||||
|
||||
mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->w,mpi->h);
|
||||
|
||||
if(mpi->flags&MP_IMGFLAG_PLANAR)
|
||||
w= mpi->w;
|
||||
else
|
||||
w= mpi->w * mpi->bpp/8;
|
||||
|
||||
interleave(dmpi->planes[0], mpi->planes[0],
|
||||
w, mpi->h, dmpi->stride[0], mpi->stride[0], luma->interleave, luma->swap);
|
||||
|
||||
if(mpi->flags&MP_IMGFLAG_PLANAR){
|
||||
int cw= mpi->w >> mpi->chroma_x_shift;
|
||||
int ch= mpi->h >> mpi->chroma_y_shift;
|
||||
|
||||
interleave(dmpi->planes[1], mpi->planes[1], cw,ch,
|
||||
dmpi->stride[1], mpi->stride[1], chroma->interleave, luma->swap);
|
||||
interleave(dmpi->planes[2], mpi->planes[2], cw,ch,
|
||||
dmpi->stride[2], mpi->stride[2], chroma->interleave, luma->swap);
|
||||
}
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static void parse(FilterParam *fp, char* args){
|
||||
char *pos;
|
||||
char *max= strchr(args, ':');
|
||||
|
||||
if(!max) max= args + strlen(args);
|
||||
|
||||
pos= strchr(args, 's');
|
||||
if(pos && pos<max) fp->swap=1;
|
||||
pos= strchr(args, 'i');
|
||||
if(pos && pos<max) fp->interleave=1;
|
||||
pos= strchr(args, 'd');
|
||||
if(pos && pos<max) fp->interleave=-1;
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
|
||||
vf->put_image=put_image;
|
||||
// vf->get_image=get_image;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
|
||||
if(args)
|
||||
{
|
||||
char *arg2= strchr(args,':');
|
||||
if(arg2) parse(&vf->priv->chromaParam, arg2+1);
|
||||
parse(&vf->priv->lumaParam, args);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_il = {
|
||||
"(de)interleave",
|
||||
"il",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
453
libavfilter/libmpcodecs/vf_ilpack.c
Normal file
453
libavfilter/libmpcodecs/vf_ilpack.c
Normal file
@ -0,0 +1,453 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
typedef void (pack_func_t)(unsigned char *dst, unsigned char *y,
|
||||
unsigned char *u, unsigned char *v, int w, int us, int vs);
|
||||
|
||||
struct vf_priv_s {
|
||||
int mode;
|
||||
pack_func_t *pack[2];
|
||||
};
|
||||
|
||||
static void pack_nn_C(unsigned char *dst, unsigned char *y,
|
||||
unsigned char *u, unsigned char *v, int w)
|
||||
{
|
||||
int j;
|
||||
for (j = w/2; j; j--) {
|
||||
*dst++ = *y++;
|
||||
*dst++ = *u++;
|
||||
*dst++ = *y++;
|
||||
*dst++ = *v++;
|
||||
}
|
||||
}
|
||||
|
||||
static void pack_li_0_C(unsigned char *dst, unsigned char *y,
|
||||
unsigned char *u, unsigned char *v, int w, int us, int vs)
|
||||
{
|
||||
int j;
|
||||
for (j = w/2; j; j--) {
|
||||
*dst++ = *y++;
|
||||
*dst++ = (u[us+us] + 7*u[0])>>3;
|
||||
*dst++ = *y++;
|
||||
*dst++ = (v[vs+vs] + 7*v[0])>>3;
|
||||
u++; v++;
|
||||
}
|
||||
}
|
||||
|
||||
static void pack_li_1_C(unsigned char *dst, unsigned char *y,
|
||||
unsigned char *u, unsigned char *v, int w, int us, int vs)
|
||||
{
|
||||
int j;
|
||||
for (j = w/2; j; j--) {
|
||||
*dst++ = *y++;
|
||||
*dst++ = (3*u[us+us] + 5*u[0])>>3;
|
||||
*dst++ = *y++;
|
||||
*dst++ = (3*v[vs+vs] + 5*v[0])>>3;
|
||||
u++; v++;
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_MMX
|
||||
static void pack_nn_MMX(unsigned char *dst, unsigned char *y,
|
||||
unsigned char *u, unsigned char *v, int w)
|
||||
{
|
||||
__asm__ volatile (""
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%0), %%mm1 \n\t"
|
||||
"movq (%0), %%mm2 \n\t"
|
||||
"movq (%1), %%mm4 \n\t"
|
||||
"movq (%2), %%mm6 \n\t"
|
||||
"punpcklbw %%mm6, %%mm4 \n\t"
|
||||
"punpcklbw %%mm4, %%mm1 \n\t"
|
||||
"punpckhbw %%mm4, %%mm2 \n\t"
|
||||
|
||||
"add $8, %0 \n\t"
|
||||
"add $4, %1 \n\t"
|
||||
"add $4, %2 \n\t"
|
||||
"movq %%mm1, (%3) \n\t"
|
||||
"movq %%mm2, 8(%3) \n\t"
|
||||
"add $16, %3 \n\t"
|
||||
"decl %4 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
"emms \n\t"
|
||||
:
|
||||
: "r" (y), "r" (u), "r" (v), "r" (dst), "r" (w/8)
|
||||
: "memory"
|
||||
);
|
||||
pack_nn_C(dst, y, u, v, (w&7));
|
||||
}
|
||||
|
||||
#if HAVE_EBX_AVAILABLE
|
||||
static void pack_li_0_MMX(unsigned char *dst, unsigned char *y,
|
||||
unsigned char *u, unsigned char *v, int w, int us, int vs)
|
||||
{
|
||||
__asm__ volatile (""
|
||||
"push %%"REG_BP" \n\t"
|
||||
#if ARCH_X86_64
|
||||
"mov %6, %%"REG_BP" \n\t"
|
||||
#else
|
||||
"movl 4(%%"REG_d"), %%"REG_BP" \n\t"
|
||||
"movl (%%"REG_d"), %%"REG_d" \n\t"
|
||||
#endif
|
||||
"pxor %%mm0, %%mm0 \n\t"
|
||||
|
||||
ASMALIGN(4)
|
||||
".Lli0: \n\t"
|
||||
"movq (%%"REG_S"), %%mm1 \n\t"
|
||||
"movq (%%"REG_S"), %%mm2 \n\t"
|
||||
|
||||
"movq (%%"REG_a",%%"REG_d",2), %%mm4 \n\t"
|
||||
"movq (%%"REG_b",%%"REG_BP",2), %%mm6 \n\t"
|
||||
"punpcklbw %%mm0, %%mm4 \n\t"
|
||||
"punpcklbw %%mm0, %%mm6 \n\t"
|
||||
"movq (%%"REG_a"), %%mm3 \n\t"
|
||||
"movq (%%"REG_b"), %%mm5 \n\t"
|
||||
"punpcklbw %%mm0, %%mm3 \n\t"
|
||||
"punpcklbw %%mm0, %%mm5 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"psrlw $3, %%mm4 \n\t"
|
||||
"psrlw $3, %%mm6 \n\t"
|
||||
"packuswb %%mm4, %%mm4 \n\t"
|
||||
"packuswb %%mm6, %%mm6 \n\t"
|
||||
"punpcklbw %%mm6, %%mm4 \n\t"
|
||||
"punpcklbw %%mm4, %%mm1 \n\t"
|
||||
"punpckhbw %%mm4, %%mm2 \n\t"
|
||||
|
||||
"movq %%mm1, (%%"REG_D") \n\t"
|
||||
"movq %%mm2, 8(%%"REG_D") \n\t"
|
||||
|
||||
"movq 8(%%"REG_S"), %%mm1 \n\t"
|
||||
"movq 8(%%"REG_S"), %%mm2 \n\t"
|
||||
|
||||
"movq (%%"REG_a",%%"REG_d",2), %%mm4 \n\t"
|
||||
"movq (%%"REG_b",%%"REG_BP",2), %%mm6 \n\t"
|
||||
"punpckhbw %%mm0, %%mm4 \n\t"
|
||||
"punpckhbw %%mm0, %%mm6 \n\t"
|
||||
"movq (%%"REG_a"), %%mm3 \n\t"
|
||||
"movq (%%"REG_b"), %%mm5 \n\t"
|
||||
"punpckhbw %%mm0, %%mm3 \n\t"
|
||||
"punpckhbw %%mm0, %%mm5 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"psrlw $3, %%mm4 \n\t"
|
||||
"psrlw $3, %%mm6 \n\t"
|
||||
"packuswb %%mm4, %%mm4 \n\t"
|
||||
"packuswb %%mm6, %%mm6 \n\t"
|
||||
"punpcklbw %%mm6, %%mm4 \n\t"
|
||||
"punpcklbw %%mm4, %%mm1 \n\t"
|
||||
"punpckhbw %%mm4, %%mm2 \n\t"
|
||||
|
||||
"add $16, %%"REG_S" \n\t"
|
||||
"add $8, %%"REG_a" \n\t"
|
||||
"add $8, %%"REG_b" \n\t"
|
||||
|
||||
"movq %%mm1, 16(%%"REG_D") \n\t"
|
||||
"movq %%mm2, 24(%%"REG_D") \n\t"
|
||||
"add $32, %%"REG_D" \n\t"
|
||||
|
||||
"decl %%ecx \n\t"
|
||||
"jnz .Lli0 \n\t"
|
||||
"emms \n\t"
|
||||
"pop %%"REG_BP" \n\t"
|
||||
:
|
||||
: "S" (y), "D" (dst), "a" (u), "b" (v), "c" (w/16),
|
||||
#if ARCH_X86_64
|
||||
"d" ((x86_reg)us), "r" ((x86_reg)vs)
|
||||
#else
|
||||
"d" (&us)
|
||||
#endif
|
||||
: "memory"
|
||||
);
|
||||
pack_li_0_C(dst, y, u, v, (w&15), us, vs);
|
||||
}
|
||||
|
||||
static void pack_li_1_MMX(unsigned char *dst, unsigned char *y,
|
||||
unsigned char *u, unsigned char *v, int w, int us, int vs)
|
||||
{
|
||||
__asm__ volatile (""
|
||||
"push %%"REG_BP" \n\t"
|
||||
#if ARCH_X86_64
|
||||
"mov %6, %%"REG_BP" \n\t"
|
||||
#else
|
||||
"movl 4(%%"REG_d"), %%"REG_BP" \n\t"
|
||||
"movl (%%"REG_d"), %%"REG_d" \n\t"
|
||||
#endif
|
||||
"pxor %%mm0, %%mm0 \n\t"
|
||||
|
||||
ASMALIGN(4)
|
||||
".Lli1: \n\t"
|
||||
"movq (%%"REG_S"), %%mm1 \n\t"
|
||||
"movq (%%"REG_S"), %%mm2 \n\t"
|
||||
|
||||
"movq (%%"REG_a",%%"REG_d",2), %%mm4 \n\t"
|
||||
"movq (%%"REG_b",%%"REG_BP",2), %%mm6 \n\t"
|
||||
"punpcklbw %%mm0, %%mm4 \n\t"
|
||||
"punpcklbw %%mm0, %%mm6 \n\t"
|
||||
"movq (%%"REG_a"), %%mm3 \n\t"
|
||||
"movq (%%"REG_b"), %%mm5 \n\t"
|
||||
"punpcklbw %%mm0, %%mm3 \n\t"
|
||||
"punpcklbw %%mm0, %%mm5 \n\t"
|
||||
"movq %%mm4, %%mm7 \n\t"
|
||||
"paddw %%mm4, %%mm4 \n\t"
|
||||
"paddw %%mm7, %%mm4 \n\t"
|
||||
"movq %%mm6, %%mm7 \n\t"
|
||||
"paddw %%mm6, %%mm6 \n\t"
|
||||
"paddw %%mm7, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"psrlw $3, %%mm4 \n\t"
|
||||
"psrlw $3, %%mm6 \n\t"
|
||||
"packuswb %%mm4, %%mm4 \n\t"
|
||||
"packuswb %%mm6, %%mm6 \n\t"
|
||||
"punpcklbw %%mm6, %%mm4 \n\t"
|
||||
"punpcklbw %%mm4, %%mm1 \n\t"
|
||||
"punpckhbw %%mm4, %%mm2 \n\t"
|
||||
|
||||
"movq %%mm1, (%%"REG_D") \n\t"
|
||||
"movq %%mm2, 8(%%"REG_D") \n\t"
|
||||
|
||||
"movq 8(%%"REG_S"), %%mm1 \n\t"
|
||||
"movq 8(%%"REG_S"), %%mm2 \n\t"
|
||||
|
||||
"movq (%%"REG_a",%%"REG_d",2), %%mm4 \n\t"
|
||||
"movq (%%"REG_b",%%"REG_BP",2), %%mm6 \n\t"
|
||||
"punpckhbw %%mm0, %%mm4 \n\t"
|
||||
"punpckhbw %%mm0, %%mm6 \n\t"
|
||||
"movq (%%"REG_a"), %%mm3 \n\t"
|
||||
"movq (%%"REG_b"), %%mm5 \n\t"
|
||||
"punpckhbw %%mm0, %%mm3 \n\t"
|
||||
"punpckhbw %%mm0, %%mm5 \n\t"
|
||||
"movq %%mm4, %%mm7 \n\t"
|
||||
"paddw %%mm4, %%mm4 \n\t"
|
||||
"paddw %%mm7, %%mm4 \n\t"
|
||||
"movq %%mm6, %%mm7 \n\t"
|
||||
"paddw %%mm6, %%mm6 \n\t"
|
||||
"paddw %%mm7, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
"paddw %%mm5, %%mm6 \n\t"
|
||||
"psrlw $3, %%mm4 \n\t"
|
||||
"psrlw $3, %%mm6 \n\t"
|
||||
"packuswb %%mm4, %%mm4 \n\t"
|
||||
"packuswb %%mm6, %%mm6 \n\t"
|
||||
"punpcklbw %%mm6, %%mm4 \n\t"
|
||||
"punpcklbw %%mm4, %%mm1 \n\t"
|
||||
"punpckhbw %%mm4, %%mm2 \n\t"
|
||||
|
||||
"add $16, %%"REG_S" \n\t"
|
||||
"add $8, %%"REG_a" \n\t"
|
||||
"add $8, %%"REG_b" \n\t"
|
||||
|
||||
"movq %%mm1, 16(%%"REG_D") \n\t"
|
||||
"movq %%mm2, 24(%%"REG_D") \n\t"
|
||||
"add $32, %%"REG_D" \n\t"
|
||||
|
||||
"decl %%ecx \n\t"
|
||||
"jnz .Lli1 \n\t"
|
||||
"emms \n\t"
|
||||
"pop %%"REG_BP" \n\t"
|
||||
:
|
||||
: "S" (y), "D" (dst), "a" (u), "b" (v), "c" (w/16),
|
||||
#if ARCH_X86_64
|
||||
"d" ((x86_reg)us), "r" ((x86_reg)vs)
|
||||
#else
|
||||
"d" (&us)
|
||||
#endif
|
||||
: "memory"
|
||||
);
|
||||
pack_li_1_C(dst, y, u, v, (w&15), us, vs);
|
||||
}
|
||||
#endif /* HAVE_EBX_AVAILABLE */
|
||||
#endif
|
||||
|
||||
static pack_func_t *pack_nn;
|
||||
static pack_func_t *pack_li_0;
|
||||
static pack_func_t *pack_li_1;
|
||||
|
||||
static void ilpack(unsigned char *dst, unsigned char *src[3],
|
||||
int dststride, int srcstride[3], int w, int h, pack_func_t *pack[2])
|
||||
{
|
||||
int i;
|
||||
unsigned char *y, *u, *v;
|
||||
int ys = srcstride[0], us = srcstride[1], vs = srcstride[2];
|
||||
int a, b;
|
||||
|
||||
y = src[0];
|
||||
u = src[1];
|
||||
v = src[2];
|
||||
|
||||
pack_nn(dst, y, u, v, w, 0, 0);
|
||||
y += ys; dst += dststride;
|
||||
pack_nn(dst, y, u+us, v+vs, w, 0, 0);
|
||||
y += ys; dst += dststride;
|
||||
for (i=2; i<h-2; i++) {
|
||||
a = (i&2) ? 1 : -1;
|
||||
b = (i&1) ^ ((i&2)>>1);
|
||||
pack[b](dst, y, u, v, w, us*a, vs*a);
|
||||
y += ys;
|
||||
if ((i&3) == 1) {
|
||||
u -= us;
|
||||
v -= vs;
|
||||
} else {
|
||||
u += us;
|
||||
v += vs;
|
||||
}
|
||||
dst += dststride;
|
||||
}
|
||||
pack_nn(dst, y, u, v, w, 0, 0);
|
||||
y += ys; dst += dststride; u += us; v += vs;
|
||||
pack_nn(dst, y, u, v, w, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
mp_image_t *dmpi;
|
||||
|
||||
// hope we'll get DR buffer:
|
||||
dmpi=vf_get_image(vf->next, IMGFMT_YUY2,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->w, mpi->h);
|
||||
|
||||
ilpack(dmpi->planes[0], mpi->planes, dmpi->stride[0], mpi->stride, mpi->w, mpi->h, vf->priv->pack);
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt)
|
||||
{
|
||||
/* FIXME - also support UYVY output? */
|
||||
return vf_next_config(vf, width, height, d_width, d_height, flags, IMGFMT_YUY2);
|
||||
}
|
||||
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt)
|
||||
{
|
||||
/* FIXME - really any YUV 4:2:0 input format should work */
|
||||
switch (fmt) {
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_I420:
|
||||
return vf_next_query_format(vf,IMGFMT_YUY2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
vf->config=config;
|
||||
vf->query_format=query_format;
|
||||
vf->put_image=put_image;
|
||||
vf->priv = calloc(1, sizeof(struct vf_priv_s));
|
||||
vf->priv->mode = 1;
|
||||
if (args) sscanf(args, "%d", &vf->priv->mode);
|
||||
|
||||
pack_nn = (pack_func_t *)pack_nn_C;
|
||||
pack_li_0 = pack_li_0_C;
|
||||
pack_li_1 = pack_li_1_C;
|
||||
#if HAVE_MMX
|
||||
if(gCpuCaps.hasMMX) {
|
||||
pack_nn = (pack_func_t *)pack_nn_MMX;
|
||||
#if HAVE_EBX_AVAILABLE
|
||||
pack_li_0 = pack_li_0_MMX;
|
||||
pack_li_1 = pack_li_1_MMX;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
switch(vf->priv->mode) {
|
||||
case 0:
|
||||
vf->priv->pack[0] = vf->priv->pack[1] = pack_nn;
|
||||
break;
|
||||
default:
|
||||
mp_msg(MSGT_VFILTER, MSGL_WARN,
|
||||
"ilpack: unknown mode %d (fallback to linear)\n",
|
||||
vf->priv->mode);
|
||||
case 1:
|
||||
vf->priv->pack[0] = pack_li_0;
|
||||
vf->priv->pack[1] = pack_li_1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_ilpack = {
|
||||
"4:2:0 planar -> 4:2:2 packed reinterlacer",
|
||||
"ilpack",
|
||||
"Richard Felker",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
550
libavfilter/libmpcodecs/vf_ivtc.c
Normal file
550
libavfilter/libmpcodecs/vf_ivtc.c
Normal file
@ -0,0 +1,550 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
|
||||
struct metrics {
|
||||
/* difference: total, even lines, odd lines */
|
||||
int d, e, o;
|
||||
/* noise: temporal, spacial (current), spacial (past) */
|
||||
int t, s, p;
|
||||
};
|
||||
|
||||
struct frameinfo {
|
||||
/* peak, relative, mean */
|
||||
struct metrics p, r, m;
|
||||
};
|
||||
|
||||
struct vf_priv_s {
|
||||
struct frameinfo fi[2];
|
||||
mp_image_t *dmpi;
|
||||
int first;
|
||||
int drop, lastdrop, dropnext;
|
||||
int inframes, outframes;
|
||||
};
|
||||
|
||||
enum {
|
||||
F_DROP,
|
||||
F_MERGE,
|
||||
F_NEXT,
|
||||
F_SHOW
|
||||
};
|
||||
|
||||
#if HAVE_MMX && HAVE_EBX_AVAILABLE
|
||||
static void block_diffs_MMX(struct metrics *m, unsigned char *old, unsigned char *new, int os, int ns)
|
||||
{
|
||||
int i;
|
||||
short out[24]; // output buffer for the partial metrics from the mmx code
|
||||
|
||||
__asm__ (
|
||||
"movl $4, %%ecx \n\t"
|
||||
"pxor %%mm4, %%mm4 \n\t" // 4 even difference sums
|
||||
"pxor %%mm5, %%mm5 \n\t" // 4 odd difference sums
|
||||
"pxor %%mm7, %%mm7 \n\t" // all zeros
|
||||
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
|
||||
// Even difference
|
||||
"movq (%%"REG_S"), %%mm0 \n\t"
|
||||
"movq (%%"REG_S"), %%mm2 \n\t"
|
||||
"add %%"REG_a", %%"REG_S" \n\t"
|
||||
"movq (%%"REG_D"), %%mm1 \n\t"
|
||||
"add %%"REG_b", %%"REG_D" \n\t"
|
||||
"psubusb %%mm1, %%mm2 \n\t"
|
||||
"psubusb %%mm0, %%mm1 \n\t"
|
||||
"movq %%mm2, %%mm0 \n\t"
|
||||
"movq %%mm1, %%mm3 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpcklbw %%mm7, %%mm1 \n\t"
|
||||
"punpckhbw %%mm7, %%mm2 \n\t"
|
||||
"punpckhbw %%mm7, %%mm3 \n\t"
|
||||
"paddw %%mm0, %%mm4 \n\t"
|
||||
"paddw %%mm1, %%mm4 \n\t"
|
||||
"paddw %%mm2, %%mm4 \n\t"
|
||||
"paddw %%mm3, %%mm4 \n\t"
|
||||
|
||||
// Odd difference
|
||||
"movq (%%"REG_S"), %%mm0 \n\t"
|
||||
"movq (%%"REG_S"), %%mm2 \n\t"
|
||||
"add %%"REG_a", %%"REG_S" \n\t"
|
||||
"movq (%%"REG_D"), %%mm1 \n\t"
|
||||
"add %%"REG_b", %%"REG_D" \n\t"
|
||||
"psubusb %%mm1, %%mm2 \n\t"
|
||||
"psubusb %%mm0, %%mm1 \n\t"
|
||||
"movq %%mm2, %%mm0 \n\t"
|
||||
"movq %%mm1, %%mm3 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpcklbw %%mm7, %%mm1 \n\t"
|
||||
"punpckhbw %%mm7, %%mm2 \n\t"
|
||||
"punpckhbw %%mm7, %%mm3 \n\t"
|
||||
"paddw %%mm0, %%mm5 \n\t"
|
||||
"paddw %%mm1, %%mm5 \n\t"
|
||||
"paddw %%mm2, %%mm5 \n\t"
|
||||
"paddw %%mm3, %%mm5 \n\t"
|
||||
|
||||
"decl %%ecx \n\t"
|
||||
"jnz 1b \n\t"
|
||||
"movq %%mm4, (%%"REG_d") \n\t"
|
||||
"movq %%mm5, 8(%%"REG_d") \n\t"
|
||||
:
|
||||
: "S" (old), "D" (new), "a" (os), "b" (ns), "d" (out)
|
||||
: "memory"
|
||||
);
|
||||
m->e = out[0]+out[1]+out[2]+out[3];
|
||||
m->o = out[4]+out[5]+out[6]+out[7];
|
||||
m->d = m->e + m->o;
|
||||
|
||||
__asm__ (
|
||||
// First loop to measure first four columns
|
||||
"movl $4, %%ecx \n\t"
|
||||
"pxor %%mm4, %%mm4 \n\t" // Past spacial noise
|
||||
"pxor %%mm5, %%mm5 \n\t" // Temporal noise
|
||||
"pxor %%mm6, %%mm6 \n\t" // Current spacial noise
|
||||
|
||||
ASMALIGN(4)
|
||||
"2: \n\t"
|
||||
|
||||
"movq (%%"REG_S"), %%mm0 \n\t"
|
||||
"movq (%%"REG_S",%%"REG_a"), %%mm1 \n\t"
|
||||
"add %%"REG_a", %%"REG_S" \n\t"
|
||||
"add %%"REG_a", %%"REG_S" \n\t"
|
||||
"movq (%%"REG_D"), %%mm2 \n\t"
|
||||
"movq (%%"REG_D",%%"REG_b"), %%mm3 \n\t"
|
||||
"add %%"REG_b", %%"REG_D" \n\t"
|
||||
"add %%"REG_b", %%"REG_D" \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpcklbw %%mm7, %%mm1 \n\t"
|
||||
"punpcklbw %%mm7, %%mm2 \n\t"
|
||||
"punpcklbw %%mm7, %%mm3 \n\t"
|
||||
"paddw %%mm1, %%mm4 \n\t"
|
||||
"paddw %%mm1, %%mm5 \n\t"
|
||||
"paddw %%mm3, %%mm6 \n\t"
|
||||
"psubw %%mm0, %%mm4 \n\t"
|
||||
"psubw %%mm2, %%mm5 \n\t"
|
||||
"psubw %%mm2, %%mm6 \n\t"
|
||||
|
||||
"decl %%ecx \n\t"
|
||||
"jnz 2b \n\t"
|
||||
|
||||
"movq %%mm0, %%mm1 \n\t"
|
||||
"movq %%mm0, %%mm2 \n\t"
|
||||
"movq %%mm0, %%mm3 \n\t"
|
||||
"pcmpgtw %%mm4, %%mm1 \n\t"
|
||||
"pcmpgtw %%mm5, %%mm2 \n\t"
|
||||
"pcmpgtw %%mm6, %%mm3 \n\t"
|
||||
"pxor %%mm1, %%mm4 \n\t"
|
||||
"pxor %%mm2, %%mm5 \n\t"
|
||||
"pxor %%mm3, %%mm6 \n\t"
|
||||
"psubw %%mm1, %%mm4 \n\t"
|
||||
"psubw %%mm2, %%mm5 \n\t"
|
||||
"psubw %%mm3, %%mm6 \n\t"
|
||||
"movq %%mm4, (%%"REG_d") \n\t"
|
||||
"movq %%mm5, 16(%%"REG_d") \n\t"
|
||||
"movq %%mm6, 32(%%"REG_d") \n\t"
|
||||
|
||||
"mov %%"REG_a", %%"REG_c" \n\t"
|
||||
"shl $3, %%"REG_c" \n\t"
|
||||
"sub %%"REG_c", %%"REG_S" \n\t"
|
||||
"mov %%"REG_b", %%"REG_c" \n\t"
|
||||
"shl $3, %%"REG_c" \n\t"
|
||||
"sub %%"REG_c", %%"REG_D" \n\t"
|
||||
|
||||
// Second loop for the last four columns
|
||||
"movl $4, %%ecx \n\t"
|
||||
"pxor %%mm4, %%mm4 \n\t"
|
||||
"pxor %%mm5, %%mm5 \n\t"
|
||||
"pxor %%mm6, %%mm6 \n\t"
|
||||
|
||||
ASMALIGN(4)
|
||||
"3: \n\t"
|
||||
|
||||
"movq (%%"REG_S"), %%mm0 \n\t"
|
||||
"movq (%%"REG_S",%%"REG_a"), %%mm1 \n\t"
|
||||
"add %%"REG_a", %%"REG_S" \n\t"
|
||||
"add %%"REG_a", %%"REG_S" \n\t"
|
||||
"movq (%%"REG_D"), %%mm2 \n\t"
|
||||
"movq (%%"REG_D",%%"REG_b"), %%mm3 \n\t"
|
||||
"add %%"REG_b", %%"REG_D" \n\t"
|
||||
"add %%"REG_b", %%"REG_D" \n\t"
|
||||
"punpckhbw %%mm7, %%mm0 \n\t"
|
||||
"punpckhbw %%mm7, %%mm1 \n\t"
|
||||
"punpckhbw %%mm7, %%mm2 \n\t"
|
||||
"punpckhbw %%mm7, %%mm3 \n\t"
|
||||
"paddw %%mm1, %%mm4 \n\t"
|
||||
"paddw %%mm1, %%mm5 \n\t"
|
||||
"paddw %%mm3, %%mm6 \n\t"
|
||||
"psubw %%mm0, %%mm4 \n\t"
|
||||
"psubw %%mm2, %%mm5 \n\t"
|
||||
"psubw %%mm2, %%mm6 \n\t"
|
||||
|
||||
"decl %%ecx \n\t"
|
||||
"jnz 3b \n\t"
|
||||
|
||||
"movq %%mm0, %%mm1 \n\t"
|
||||
"movq %%mm0, %%mm2 \n\t"
|
||||
"movq %%mm0, %%mm3 \n\t"
|
||||
"pcmpgtw %%mm4, %%mm1 \n\t"
|
||||
"pcmpgtw %%mm5, %%mm2 \n\t"
|
||||
"pcmpgtw %%mm6, %%mm3 \n\t"
|
||||
"pxor %%mm1, %%mm4 \n\t"
|
||||
"pxor %%mm2, %%mm5 \n\t"
|
||||
"pxor %%mm3, %%mm6 \n\t"
|
||||
"psubw %%mm1, %%mm4 \n\t"
|
||||
"psubw %%mm2, %%mm5 \n\t"
|
||||
"psubw %%mm3, %%mm6 \n\t"
|
||||
"movq %%mm4, 8(%%"REG_d") \n\t"
|
||||
"movq %%mm5, 24(%%"REG_d") \n\t"
|
||||
"movq %%mm6, 40(%%"REG_d") \n\t"
|
||||
|
||||
"emms \n\t"
|
||||
:
|
||||
: "S" (old), "D" (new), "a" ((long)os), "b" ((long)ns), "d" (out)
|
||||
: "memory"
|
||||
);
|
||||
m->p = m->t = m->s = 0;
|
||||
for (i=0; i<8; i++) {
|
||||
m->p += out[i];
|
||||
m->t += out[8+i];
|
||||
m->s += out[16+i];
|
||||
}
|
||||
//printf("e=%d o=%d d=%d p=%d t=%d s=%d\n", m->e, m->o, m->d, m->p, m->t, m->s);
|
||||
}
|
||||
#endif
|
||||
|
||||
//#define MAG(a) ((a)*(a))
|
||||
//#define MAG(a) (abs(a))
|
||||
#define MAG(a) (((a)^((a)>>31))-((a)>>31))
|
||||
|
||||
//#define LOWPASS(s) (((s)[-2] + 4*(s)[-1] + 6*(s)[0] + 4*(s)[1] + (s)[2])>>4)
|
||||
//#define LOWPASS(s) (((s)[-1] + 2*(s)[0] + (s)[1])>>2)
|
||||
#define LOWPASS(s) ((s)[0])
|
||||
|
||||
|
||||
static void block_diffs_C(struct metrics *m, unsigned char *old, unsigned char *new, int os, int ns)
|
||||
{
|
||||
int x, y, e=0, o=0, s=0, p=0, t=0;
|
||||
unsigned char *oldp, *newp;
|
||||
m->s = m->p = m->t = 0;
|
||||
for (x = 8; x; x--) {
|
||||
oldp = old++;
|
||||
newp = new++;
|
||||
s = p = t = 0;
|
||||
for (y = 4; y; y--) {
|
||||
e += MAG(newp[0]-oldp[0]);
|
||||
o += MAG(newp[ns]-oldp[os]);
|
||||
s += newp[ns]-newp[0];
|
||||
p += oldp[os]-oldp[0];
|
||||
t += oldp[os]-newp[0];
|
||||
oldp += os<<1;
|
||||
newp += ns<<1;
|
||||
}
|
||||
m->s += MAG(s);
|
||||
m->p += MAG(p);
|
||||
m->t += MAG(t);
|
||||
}
|
||||
m->e = e;
|
||||
m->o = o;
|
||||
m->d = e+o;
|
||||
}
|
||||
|
||||
static void (*block_diffs)(struct metrics *, unsigned char *, unsigned char *, int, int);
|
||||
|
||||
#define MAXUP(a,b) ((a) = ((a)>(b)) ? (a) : (b))
|
||||
|
||||
static void diff_planes(struct frameinfo *fi,
|
||||
unsigned char *old, unsigned char *new, int w, int h, int os, int ns)
|
||||
{
|
||||
int x, y;
|
||||
struct metrics l;
|
||||
struct metrics *peak=&fi->p, *rel=&fi->r, *mean=&fi->m;
|
||||
memset(peak, 0, sizeof(struct metrics));
|
||||
memset(rel, 0, sizeof(struct metrics));
|
||||
memset(mean, 0, sizeof(struct metrics));
|
||||
for (y = 0; y < h-7; y += 8) {
|
||||
for (x = 8; x < w-8-7; x += 8) {
|
||||
block_diffs(&l, old+x+y*os, new+x+y*ns, os, ns);
|
||||
mean->d += l.d;
|
||||
mean->e += l.e;
|
||||
mean->o += l.o;
|
||||
mean->s += l.s;
|
||||
mean->p += l.p;
|
||||
mean->t += l.t;
|
||||
MAXUP(peak->d, l.d);
|
||||
MAXUP(peak->e, l.e);
|
||||
MAXUP(peak->o, l.o);
|
||||
MAXUP(peak->s, l.s);
|
||||
MAXUP(peak->p, l.p);
|
||||
MAXUP(peak->t, l.t);
|
||||
MAXUP(rel->e, l.e-l.o);
|
||||
MAXUP(rel->o, l.o-l.e);
|
||||
MAXUP(rel->s, l.s-l.t);
|
||||
MAXUP(rel->p, l.p-l.t);
|
||||
MAXUP(rel->t, l.t-l.p);
|
||||
MAXUP(rel->d, l.t-l.s); /* hack */
|
||||
}
|
||||
}
|
||||
x = (w/8-2)*(h/8);
|
||||
mean->d /= x;
|
||||
mean->e /= x;
|
||||
mean->o /= x;
|
||||
mean->s /= x;
|
||||
mean->p /= x;
|
||||
mean->t /= x;
|
||||
}
|
||||
|
||||
static void diff_fields(struct frameinfo *fi, mp_image_t *old, mp_image_t *new)
|
||||
{
|
||||
diff_planes(fi, old->planes[0], new->planes[0],
|
||||
new->w, new->h, old->stride[0], new->stride[0]);
|
||||
}
|
||||
|
||||
static void stats(struct frameinfo *f)
|
||||
{
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, " pd=%d re=%d ro=%d rp=%d rt=%d rs=%d rd=%d pp=%d pt=%d ps=%d\r",
|
||||
f->p.d, f->r.e, f->r.o, f->r.p, f->r.t, f->r.s, f->r.d, f->p.p, f->p.t, f->p.s);
|
||||
}
|
||||
|
||||
static int foo(struct vf_priv_s *p, mp_image_t *new, mp_image_t *cur)
|
||||
{
|
||||
struct frameinfo *f = p->fi;
|
||||
|
||||
f[0] = f[1];
|
||||
diff_fields(&f[1], cur, new);
|
||||
stats(&f[1]);
|
||||
|
||||
// Immediately drop this frame if it's already been used.
|
||||
if (p->dropnext) {
|
||||
p->dropnext = 0;
|
||||
return F_DROP;
|
||||
}
|
||||
|
||||
// Sometimes a pulldown frame comes all by itself, so both
|
||||
// its top and bottom field are duplicates from the adjacent
|
||||
// two frames. We can just drop such a frame, but we
|
||||
// immediately show the next frame instead to keep the frame
|
||||
// drops evenly spaced during normal 3:2 pulldown sequences.
|
||||
if ((3*f[1].r.o < f[1].r.e) && (f[1].r.s < f[1].r.d)) {
|
||||
p->dropnext = 1;
|
||||
return F_NEXT;
|
||||
}
|
||||
|
||||
// If none of these conditions hold, we will consider the frame
|
||||
// progressive and just show it as-is.
|
||||
if (!( (3*f[0].r.e < f[0].r.o) ||
|
||||
((2*f[0].r.d < f[0].r.s) && (f[0].r.s > 1200)) ||
|
||||
((2*f[1].r.t < f[1].r.p) && (f[1].r.p > 1200)) ))
|
||||
return F_SHOW;
|
||||
|
||||
// Otherwise, we have to decide whether to merge or drop.
|
||||
// If the noise metric only increases minimally, we're off
|
||||
// to a good start...
|
||||
if (((2*f[1].r.t < 3*f[1].r.p) && (f[1].r.t < 3600)) ||
|
||||
(f[1].r.t < 900) || (f[1].r.d < 900)) {
|
||||
// ...and if noise decreases or the duplicate even field
|
||||
// is detected, we go ahead with the merge.
|
||||
if ((3*f[0].r.e < f[0].r.o) || (2*f[1].r.t < f[1].r.p)) {
|
||||
p->dropnext = 1;
|
||||
return F_MERGE;
|
||||
}
|
||||
}
|
||||
return F_DROP;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void copy_image(mp_image_t *dmpi, mp_image_t *mpi, int field)
|
||||
{
|
||||
switch (field) {
|
||||
case 0:
|
||||
my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2,
|
||||
dmpi->stride[0]*2, mpi->stride[0]*2);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
my_memcpy_pic(dmpi->planes[1], mpi->planes[1],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[1]*2, mpi->stride[1]*2);
|
||||
my_memcpy_pic(dmpi->planes[2], mpi->planes[2],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[2]*2, mpi->stride[2]*2);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
|
||||
mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2,
|
||||
dmpi->stride[0]*2, mpi->stride[0]*2);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
|
||||
mpi->planes[1]+mpi->stride[1],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[1]*2, mpi->stride[1]*2);
|
||||
my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
|
||||
mpi->planes[2]+mpi->stride[2],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[2]*2, mpi->stride[2]*2);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
|
||||
dmpi->stride[0], mpi->stride[0]);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
memcpy_pic(dmpi->planes[1], mpi->planes[1],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[1], mpi->stride[1]);
|
||||
memcpy_pic(dmpi->planes[2], mpi->planes[2],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[2], mpi->stride[2]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int do_put_image(struct vf_instance *vf, mp_image_t *dmpi)
|
||||
{
|
||||
struct vf_priv_s *p = vf->priv;
|
||||
int dropflag=0;
|
||||
|
||||
if (!p->dropnext) switch (p->drop) {
|
||||
case 0:
|
||||
dropflag = 0;
|
||||
break;
|
||||
case 1:
|
||||
dropflag = (++p->lastdrop >= 5);
|
||||
break;
|
||||
case 2:
|
||||
dropflag = (++p->lastdrop >= 5) && (4*p->inframes <= 5*p->outframes);
|
||||
break;
|
||||
}
|
||||
|
||||
if (dropflag) {
|
||||
//mp_msg(MSGT_VFILTER, MSGL_V, "drop! [%d/%d=%g]\n",
|
||||
// p->outframes, p->inframes, (float)p->outframes/p->inframes);
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, "!");
|
||||
p->lastdrop = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
p->outframes++;
|
||||
return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
int ret=0;
|
||||
struct vf_priv_s *p = vf->priv;
|
||||
|
||||
p->inframes++;
|
||||
|
||||
if (p->first) { /* hack */
|
||||
p->first = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!p->dmpi) p->dmpi = vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
|
||||
MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE,
|
||||
mpi->width, mpi->height);
|
||||
/* FIXME -- not correct, off by one frame! */
|
||||
p->dmpi->qscale = mpi->qscale;
|
||||
p->dmpi->qstride = mpi->qstride;
|
||||
p->dmpi->qscale_type = mpi->qscale_type;
|
||||
|
||||
switch (foo(p, mpi, p->dmpi)) {
|
||||
case F_DROP:
|
||||
copy_image(p->dmpi, mpi, 2);
|
||||
ret = 0;
|
||||
p->lastdrop = 0;
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, "DROP\n");
|
||||
break;
|
||||
case F_MERGE:
|
||||
copy_image(p->dmpi, mpi, 0);
|
||||
ret = do_put_image(vf, p->dmpi);
|
||||
copy_image(p->dmpi, mpi, 1);
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, "MERGE\n");
|
||||
p->dmpi = NULL;
|
||||
break;
|
||||
case F_NEXT:
|
||||
copy_image(p->dmpi, mpi, 2);
|
||||
ret = do_put_image(vf, p->dmpi);
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, "NEXT\n");
|
||||
p->dmpi = NULL;
|
||||
break;
|
||||
case F_SHOW:
|
||||
ret = do_put_image(vf, p->dmpi);
|
||||
copy_image(p->dmpi, mpi, 2);
|
||||
mp_msg(MSGT_VFILTER, MSGL_V, "OK\n");
|
||||
p->dmpi = NULL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt)
|
||||
{
|
||||
switch (fmt) {
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_I420:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
struct vf_priv_s *p;
|
||||
vf->put_image = put_image;
|
||||
vf->query_format = query_format;
|
||||
vf->uninit = uninit;
|
||||
vf->default_reqs = VFCAP_ACCEPT_STRIDE;
|
||||
vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
|
||||
p->drop = 0;
|
||||
p->first = 1;
|
||||
if (args) sscanf(args, "%d", &p->drop);
|
||||
block_diffs = block_diffs_C;
|
||||
#if HAVE_MMX && HAVE_EBX_AVAILABLE
|
||||
if(gCpuCaps.hasMMX) block_diffs = block_diffs_MMX;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_ivtc = {
|
||||
"inverse telecine, take 2",
|
||||
"ivtc",
|
||||
"Rich Felker",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
345
libavfilter/libmpcodecs/vf_kerndeint.c
Normal file
345
libavfilter/libmpcodecs/vf_kerndeint.c
Normal file
@ -0,0 +1,345 @@
|
||||
/*
|
||||
* Original AVISynth Filter Copyright (C) 2003 Donald A. Graft
|
||||
* Adapted to MPlayer by Tobias Diedrich
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "mp_msg.h"
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
struct vf_priv_s {
|
||||
int frame;
|
||||
int map;
|
||||
int order;
|
||||
int thresh;
|
||||
int sharp;
|
||||
int twoway;
|
||||
int do_deinterlace;
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static inline int IsRGB(mp_image_t *mpi)
|
||||
{
|
||||
return mpi->imgfmt == IMGFMT_RGB;
|
||||
}
|
||||
|
||||
static inline int IsYUY2(mp_image_t *mpi)
|
||||
{
|
||||
return mpi->imgfmt == IMGFMT_YUY2;
|
||||
}
|
||||
|
||||
#define PLANAR_Y 0
|
||||
#define PLANAR_U 1
|
||||
#define PLANAR_V 2
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
int cw= mpi->w >> mpi->chroma_x_shift;
|
||||
int ch= mpi->h >> mpi->chroma_y_shift;
|
||||
int W = mpi->w, H = mpi->h;
|
||||
const unsigned char *prvp, *prvpp, *prvpn, *prvpnn, *prvppp, *prvp4p, *prvp4n;
|
||||
const unsigned char *srcp_saved;
|
||||
const unsigned char *srcp, *srcpp, *srcpn, *srcpnn, *srcppp, *srcp3p, *srcp3n, *srcp4p, *srcp4n;
|
||||
unsigned char *dstp, *dstp_saved;
|
||||
int src_pitch;
|
||||
int psrc_pitch;
|
||||
int dst_pitch;
|
||||
int x, y, z;
|
||||
int n = vf->priv->frame++;
|
||||
int val, hi, lo, w, h;
|
||||
double valf;
|
||||
int plane;
|
||||
int threshold = vf->priv->thresh;
|
||||
int order = vf->priv->order;
|
||||
int map = vf->priv->map;
|
||||
int sharp = vf->priv->sharp;
|
||||
int twoway = vf->priv->twoway;
|
||||
mp_image_t *dmpi, *pmpi;
|
||||
|
||||
if(!vf->priv->do_deinterlace)
|
||||
return vf_next_put_image(vf, mpi, pts);
|
||||
|
||||
dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_IP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->w,mpi->h);
|
||||
pmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->w,mpi->h);
|
||||
if(!dmpi) return 0;
|
||||
|
||||
for (z=0; z<mpi->num_planes; z++) {
|
||||
if (z == 0) plane = PLANAR_Y;
|
||||
else if (z == 1) plane = PLANAR_U;
|
||||
else plane = PLANAR_V;
|
||||
|
||||
h = plane == PLANAR_Y ? H : ch;
|
||||
w = plane == PLANAR_Y ? W : cw;
|
||||
|
||||
srcp = srcp_saved = mpi->planes[z];
|
||||
src_pitch = mpi->stride[z];
|
||||
psrc_pitch = pmpi->stride[z];
|
||||
dstp = dstp_saved = dmpi->planes[z];
|
||||
dst_pitch = dmpi->stride[z];
|
||||
srcp = srcp_saved + (1-order) * src_pitch;
|
||||
dstp = dstp_saved + (1-order) * dst_pitch;
|
||||
|
||||
for (y=0; y<h; y+=2) {
|
||||
fast_memcpy(dstp, srcp, w);
|
||||
srcp += 2*src_pitch;
|
||||
dstp += 2*dst_pitch;
|
||||
}
|
||||
|
||||
// Copy through the lines that will be missed below.
|
||||
fast_memcpy(dstp_saved + order*dst_pitch, srcp_saved + (1-order)*src_pitch, w);
|
||||
fast_memcpy(dstp_saved + (2+order)*dst_pitch, srcp_saved + (3-order)*src_pitch, w);
|
||||
fast_memcpy(dstp_saved + (h-2+order)*dst_pitch, srcp_saved + (h-1-order)*src_pitch, w);
|
||||
fast_memcpy(dstp_saved + (h-4+order)*dst_pitch, srcp_saved + (h-3-order)*src_pitch, w);
|
||||
/* For the other field choose adaptively between using the previous field
|
||||
or the interpolant from the current field. */
|
||||
|
||||
prvp = pmpi->planes[z] + 5*psrc_pitch - (1-order)*psrc_pitch;
|
||||
prvpp = prvp - psrc_pitch;
|
||||
prvppp = prvp - 2*psrc_pitch;
|
||||
prvp4p = prvp - 4*psrc_pitch;
|
||||
prvpn = prvp + psrc_pitch;
|
||||
prvpnn = prvp + 2*psrc_pitch;
|
||||
prvp4n = prvp + 4*psrc_pitch;
|
||||
srcp = srcp_saved + 5*src_pitch - (1-order)*src_pitch;
|
||||
srcpp = srcp - src_pitch;
|
||||
srcppp = srcp - 2*src_pitch;
|
||||
srcp3p = srcp - 3*src_pitch;
|
||||
srcp4p = srcp - 4*src_pitch;
|
||||
srcpn = srcp + src_pitch;
|
||||
srcpnn = srcp + 2*src_pitch;
|
||||
srcp3n = srcp + 3*src_pitch;
|
||||
srcp4n = srcp + 4*src_pitch;
|
||||
dstp = dstp_saved + 5*dst_pitch - (1-order)*dst_pitch;
|
||||
for (y = 5 - (1-order); y <= h - 5 - (1-order); y+=2)
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
if ((threshold == 0) || (n == 0) ||
|
||||
(abs((int)prvp[x] - (int)srcp[x]) > threshold) ||
|
||||
(abs((int)prvpp[x] - (int)srcpp[x]) > threshold) ||
|
||||
(abs((int)prvpn[x] - (int)srcpn[x]) > threshold))
|
||||
{
|
||||
if (map == 1)
|
||||
{
|
||||
int g = x & ~3;
|
||||
if (IsRGB(mpi) == 1)
|
||||
{
|
||||
dstp[g++] = 255;
|
||||
dstp[g++] = 255;
|
||||
dstp[g++] = 255;
|
||||
dstp[g] = 255;
|
||||
x = g;
|
||||
}
|
||||
else if (IsYUY2(mpi) == 1)
|
||||
{
|
||||
dstp[g++] = 235;
|
||||
dstp[g++] = 128;
|
||||
dstp[g++] = 235;
|
||||
dstp[g] = 128;
|
||||
x = g;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (plane == PLANAR_Y) dstp[x] = 235;
|
||||
else dstp[x] = 128;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsRGB(mpi))
|
||||
{
|
||||
hi = 255;
|
||||
lo = 0;
|
||||
}
|
||||
else if (IsYUY2(mpi))
|
||||
{
|
||||
hi = (x & 1) ? 240 : 235;
|
||||
lo = 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
hi = (plane == PLANAR_Y) ? 235 : 240;
|
||||
lo = 16;
|
||||
}
|
||||
|
||||
if (sharp == 1)
|
||||
{
|
||||
if (twoway == 1)
|
||||
valf = + 0.526*((int)srcpp[x] + (int)srcpn[x])
|
||||
+ 0.170*((int)srcp[x] + (int)prvp[x])
|
||||
- 0.116*((int)srcppp[x] + (int)srcpnn[x] + (int)prvppp[x] + (int)prvpnn[x])
|
||||
- 0.026*((int)srcp3p[x] + (int)srcp3n[x])
|
||||
+ 0.031*((int)srcp4p[x] + (int)srcp4n[x] + (int)prvp4p[x] + (int)prvp4n[x]);
|
||||
else
|
||||
valf = + 0.526*((int)srcpp[x] + (int)srcpn[x])
|
||||
+ 0.170*((int)prvp[x])
|
||||
- 0.116*((int)prvppp[x] + (int)prvpnn[x])
|
||||
- 0.026*((int)srcp3p[x] + (int)srcp3n[x])
|
||||
+ 0.031*((int)prvp4p[x] + (int)prvp4p[x]);
|
||||
if (valf > hi) valf = hi;
|
||||
else if (valf < lo) valf = lo;
|
||||
dstp[x] = (int) valf;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (twoway == 1)
|
||||
val = (8*((int)srcpp[x] + (int)srcpn[x]) + 2*((int)srcp[x] + (int)prvp[x]) -
|
||||
(int)(srcppp[x]) - (int)(srcpnn[x]) -
|
||||
(int)(prvppp[x]) - (int)(prvpnn[x])) >> 4;
|
||||
else
|
||||
val = (8*((int)srcpp[x] + (int)srcpn[x]) + 2*((int)prvp[x]) -
|
||||
(int)(prvppp[x]) - (int)(prvpnn[x])) >> 4;
|
||||
if (val > hi) val = hi;
|
||||
else if (val < lo) val = lo;
|
||||
dstp[x] = (int) val;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dstp[x] = srcp[x];
|
||||
}
|
||||
}
|
||||
prvp += 2*psrc_pitch;
|
||||
prvpp += 2*psrc_pitch;
|
||||
prvppp += 2*psrc_pitch;
|
||||
prvpn += 2*psrc_pitch;
|
||||
prvpnn += 2*psrc_pitch;
|
||||
prvp4p += 2*psrc_pitch;
|
||||
prvp4n += 2*psrc_pitch;
|
||||
srcp += 2*src_pitch;
|
||||
srcpp += 2*src_pitch;
|
||||
srcppp += 2*src_pitch;
|
||||
srcp3p += 2*src_pitch;
|
||||
srcp4p += 2*src_pitch;
|
||||
srcpn += 2*src_pitch;
|
||||
srcpnn += 2*src_pitch;
|
||||
srcp3n += 2*src_pitch;
|
||||
srcp4n += 2*src_pitch;
|
||||
dstp += 2*dst_pitch;
|
||||
}
|
||||
|
||||
srcp = mpi->planes[z];
|
||||
dstp = pmpi->planes[z];
|
||||
for (y=0; y<h; y++) {
|
||||
fast_memcpy(dstp, srcp, w);
|
||||
srcp += src_pitch;
|
||||
dstp += psrc_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
switch(fmt)
|
||||
{
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_RGB:
|
||||
case IMGFMT_YUY2:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int control(struct vf_instance *vf, int request, void* data){
|
||||
switch (request)
|
||||
{
|
||||
case VFCTRL_GET_DEINTERLACE:
|
||||
*(int*)data = vf->priv->do_deinterlace;
|
||||
return CONTROL_OK;
|
||||
case VFCTRL_SET_DEINTERLACE:
|
||||
vf->priv->do_deinterlace = *(int*)data;
|
||||
return CONTROL_OK;
|
||||
}
|
||||
return vf_next_control (vf, request, data);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
|
||||
vf->control=control;
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->query_format=query_format;
|
||||
vf->uninit=uninit;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
|
||||
vf->priv->frame = 0;
|
||||
|
||||
vf->priv->map = 0;
|
||||
vf->priv->order = 0;
|
||||
vf->priv->thresh = 10;
|
||||
vf->priv->sharp = 0;
|
||||
vf->priv->twoway = 0;
|
||||
vf->priv->do_deinterlace=1;
|
||||
|
||||
if (args)
|
||||
{
|
||||
sscanf(args, "%d:%d:%d:%d:%d",
|
||||
&vf->priv->thresh, &vf->priv->map,
|
||||
&vf->priv->order, &vf->priv->sharp,
|
||||
&vf->priv->twoway);
|
||||
}
|
||||
if (vf->priv->order > 1) vf->priv->order = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_kerndeint = {
|
||||
"Kernel Deinterlacer",
|
||||
"kerndeint",
|
||||
"Donald Graft",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
338
libavfilter/libmpcodecs/vf_mcdeint.c
Normal file
338
libavfilter/libmpcodecs/vf_mcdeint.c
Normal file
@ -0,0 +1,338 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Known Issues:
|
||||
* The motion estimation is somewhat at the mercy of the input, if the input
|
||||
frames are created purely based on spatial interpolation then for example
|
||||
a thin black line or another random and not interpolateable pattern
|
||||
will cause problems
|
||||
Note: completly ignoring the "unavailable" lines during motion estimation
|
||||
didnt look any better, so the most obvious solution would be to improve
|
||||
tfields or penalize problematic motion vectors ...
|
||||
|
||||
* If non iterative ME is used then snow currently ignores the OBMC window
|
||||
and as a result sometimes creates artifacts
|
||||
|
||||
* only past frames are used, we should ideally use future frames too, something
|
||||
like filtering the whole movie in forward and then backward direction seems
|
||||
like a interresting idea but the current filter framework is FAR from
|
||||
supporting such things
|
||||
|
||||
* combining the motion compensated image with the input image also isnt
|
||||
as trivial as it seems, simple blindly taking even lines from one and
|
||||
odd ones from the other doesnt work at all as ME/MC sometimes simple
|
||||
has nothing in the previous frames which matches the current, the current
|
||||
algo has been found by trial and error and almost certainly can be
|
||||
improved ...
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
#include "libavutil/internal.h"
|
||||
#include "libavutil/intreadwrite.h"
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavcodec/dsputil.h"
|
||||
|
||||
#undef fprintf
|
||||
#undef free
|
||||
#undef malloc
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
#include "vd_ffmpeg.h"
|
||||
|
||||
#define MIN(a,b) ((a) > (b) ? (b) : (a))
|
||||
#define MAX(a,b) ((a) < (b) ? (b) : (a))
|
||||
#define ABS(a) ((a) > 0 ? (a) : (-(a)))
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
struct vf_priv_s {
|
||||
int mode;
|
||||
int qp;
|
||||
int parity;
|
||||
#if 0
|
||||
int temp_stride[3];
|
||||
uint8_t *src[3];
|
||||
int16_t *temp[3];
|
||||
#endif
|
||||
int outbuf_size;
|
||||
uint8_t *outbuf;
|
||||
AVCodecContext *avctx_enc;
|
||||
AVFrame *frame;
|
||||
AVFrame *frame_dec;
|
||||
};
|
||||
|
||||
static void filter(struct vf_priv_s *p, uint8_t *dst[3], uint8_t *src[3], int dst_stride[3], int src_stride[3], int width, int height){
|
||||
int x, y, i;
|
||||
int out_size;
|
||||
|
||||
for(i=0; i<3; i++){
|
||||
p->frame->data[i]= src[i];
|
||||
p->frame->linesize[i]= src_stride[i];
|
||||
}
|
||||
|
||||
p->avctx_enc->me_cmp=
|
||||
p->avctx_enc->me_sub_cmp= FF_CMP_SAD /*| (p->parity ? FF_CMP_ODD : FF_CMP_EVEN)*/;
|
||||
p->frame->quality= p->qp*FF_QP2LAMBDA;
|
||||
out_size = avcodec_encode_video(p->avctx_enc, p->outbuf, p->outbuf_size, p->frame);
|
||||
p->frame_dec = p->avctx_enc->coded_frame;
|
||||
|
||||
for(i=0; i<3; i++){
|
||||
int is_chroma= !!i;
|
||||
int w= width >>is_chroma;
|
||||
int h= height>>is_chroma;
|
||||
int fils= p->frame_dec->linesize[i];
|
||||
int srcs= src_stride[i];
|
||||
|
||||
for(y=0; y<h; y++){
|
||||
if((y ^ p->parity) & 1){
|
||||
for(x=0; x<w; x++){
|
||||
if((x-2)+(y-1)*w>=0 && (x+2)+(y+1)*w<w*h){ //FIXME either alloc larger images or optimize this
|
||||
uint8_t *filp= &p->frame_dec->data[i][x + y*fils];
|
||||
uint8_t *srcp= &src[i][x + y*srcs];
|
||||
int diff0= filp[-fils] - srcp[-srcs];
|
||||
int diff1= filp[+fils] - srcp[+srcs];
|
||||
int spatial_score= ABS(srcp[-srcs-1] - srcp[+srcs-1])
|
||||
+ABS(srcp[-srcs ] - srcp[+srcs ])
|
||||
+ABS(srcp[-srcs+1] - srcp[+srcs+1]) - 1;
|
||||
int temp= filp[0];
|
||||
|
||||
#define CHECK(j)\
|
||||
{ int score= ABS(srcp[-srcs-1+j] - srcp[+srcs-1-j])\
|
||||
+ ABS(srcp[-srcs +j] - srcp[+srcs -j])\
|
||||
+ ABS(srcp[-srcs+1+j] - srcp[+srcs+1-j]);\
|
||||
if(score < spatial_score){\
|
||||
spatial_score= score;\
|
||||
diff0= filp[-fils+j] - srcp[-srcs+j];\
|
||||
diff1= filp[+fils-j] - srcp[+srcs-j];
|
||||
|
||||
CHECK(-1) CHECK(-2) }} }}
|
||||
CHECK( 1) CHECK( 2) }} }}
|
||||
#if 0
|
||||
if((diff0 ^ diff1) > 0){
|
||||
int mindiff= ABS(diff0) > ABS(diff1) ? diff1 : diff0;
|
||||
temp-= mindiff;
|
||||
}
|
||||
#elif 1
|
||||
if(diff0 + diff1 > 0)
|
||||
temp-= (diff0 + diff1 - ABS( ABS(diff0) - ABS(diff1) )/2)/2;
|
||||
else
|
||||
temp-= (diff0 + diff1 + ABS( ABS(diff0) - ABS(diff1) )/2)/2;
|
||||
#else
|
||||
temp-= (diff0 + diff1)/2;
|
||||
#endif
|
||||
#if 1
|
||||
filp[0]=
|
||||
dst[i][x + y*dst_stride[i]]= temp > 255U ? ~(temp>>31) : temp;
|
||||
#else
|
||||
dst[i][x + y*dst_stride[i]]= filp[0];
|
||||
filp[0]= temp > 255U ? ~(temp>>31) : temp;
|
||||
#endif
|
||||
}else
|
||||
dst[i][x + y*dst_stride[i]]= p->frame_dec->data[i][x + y*fils];
|
||||
}
|
||||
}
|
||||
}
|
||||
for(y=0; y<h; y++){
|
||||
if(!((y ^ p->parity) & 1)){
|
||||
for(x=0; x<w; x++){
|
||||
#if 1
|
||||
p->frame_dec->data[i][x + y*fils]=
|
||||
dst[i][x + y*dst_stride[i]]= src[i][x + y*srcs];
|
||||
#else
|
||||
dst[i][x + y*dst_stride[i]]= p->frame_dec->data[i][x + y*fils];
|
||||
p->frame_dec->data[i][x + y*fils]= src[i][x + y*srcs];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p->parity ^= 1;
|
||||
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
int i;
|
||||
AVCodec *enc= avcodec_find_encoder(CODEC_ID_SNOW);
|
||||
|
||||
for(i=0; i<3; i++){
|
||||
AVCodecContext *avctx_enc;
|
||||
#if 0
|
||||
int is_chroma= !!i;
|
||||
int w= ((width + 31) & (~31))>>is_chroma;
|
||||
int h= ((height + 31) & (~31))>>is_chroma;
|
||||
|
||||
vf->priv->temp_stride[i]= w;
|
||||
vf->priv->temp[i]= malloc(vf->priv->temp_stride[i]*h*sizeof(int16_t));
|
||||
vf->priv->src [i]= malloc(vf->priv->temp_stride[i]*h*sizeof(uint8_t));
|
||||
#endif
|
||||
avctx_enc=
|
||||
vf->priv->avctx_enc= avcodec_alloc_context();
|
||||
avctx_enc->width = width;
|
||||
avctx_enc->height = height;
|
||||
avctx_enc->time_base= (AVRational){1,25}; // meaningless
|
||||
avctx_enc->gop_size = 300;
|
||||
avctx_enc->max_b_frames= 0;
|
||||
avctx_enc->pix_fmt = PIX_FMT_YUV420P;
|
||||
avctx_enc->flags = CODEC_FLAG_QSCALE | CODEC_FLAG_LOW_DELAY;
|
||||
avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
|
||||
avctx_enc->global_quality= 1;
|
||||
avctx_enc->flags2= CODEC_FLAG2_MEMC_ONLY;
|
||||
avctx_enc->me_cmp=
|
||||
avctx_enc->me_sub_cmp= FF_CMP_SAD; //SSE;
|
||||
avctx_enc->mb_cmp= FF_CMP_SSE;
|
||||
|
||||
switch(vf->priv->mode){
|
||||
case 3:
|
||||
avctx_enc->refs= 3;
|
||||
case 2:
|
||||
avctx_enc->me_method= ME_ITER;
|
||||
case 1:
|
||||
avctx_enc->flags |= CODEC_FLAG_4MV;
|
||||
avctx_enc->dia_size=2;
|
||||
// avctx_enc->mb_decision = MB_DECISION_RD;
|
||||
case 0:
|
||||
avctx_enc->flags |= CODEC_FLAG_QPEL;
|
||||
}
|
||||
|
||||
avcodec_open(avctx_enc, enc);
|
||||
|
||||
}
|
||||
vf->priv->frame= avcodec_alloc_frame();
|
||||
|
||||
vf->priv->outbuf_size= width*height*10;
|
||||
vf->priv->outbuf= malloc(vf->priv->outbuf_size);
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static void get_image(struct vf_instance *vf, mp_image_t *mpi){
|
||||
if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
|
||||
return; //caused problems, dunno why
|
||||
// ok, we can do pp in-place (or pp disabled):
|
||||
vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height);
|
||||
mpi->planes[0]=vf->dmpi->planes[0];
|
||||
mpi->stride[0]=vf->dmpi->stride[0];
|
||||
mpi->width=vf->dmpi->width;
|
||||
if(mpi->flags&MP_IMGFLAG_PLANAR){
|
||||
mpi->planes[1]=vf->dmpi->planes[1];
|
||||
mpi->planes[2]=vf->dmpi->planes[2];
|
||||
mpi->stride[1]=vf->dmpi->stride[1];
|
||||
mpi->stride[2]=vf->dmpi->stride[2];
|
||||
}
|
||||
mpi->flags|=MP_IMGFLAG_DIRECT;
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
|
||||
if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
|
||||
// no DR, so get a new image! hope we'll get DR buffer:
|
||||
dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP,
|
||||
MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
|
||||
mpi->width,mpi->height);
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
}else{
|
||||
dmpi=vf->dmpi;
|
||||
}
|
||||
|
||||
filter(vf->priv, dmpi->planes, mpi->planes, dmpi->stride, mpi->stride, mpi->w, mpi->h);
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf){
|
||||
if(!vf->priv) return;
|
||||
|
||||
#if 0
|
||||
for(i=0; i<3; i++){
|
||||
free(vf->priv->temp[i]);
|
||||
vf->priv->temp[i]= NULL;
|
||||
free(vf->priv->src[i]);
|
||||
vf->priv->src[i]= NULL;
|
||||
}
|
||||
#endif
|
||||
if (vf->priv->avctx_enc) {
|
||||
avcodec_close(vf->priv->avctx_enc);
|
||||
av_freep(&vf->priv->avctx_enc);
|
||||
}
|
||||
|
||||
free(vf->priv->outbuf);
|
||||
free(vf->priv);
|
||||
vf->priv=NULL;
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
switch(fmt){
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_Y800:
|
||||
case IMGFMT_Y8:
|
||||
return vf_next_query_format(vf,fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->get_image=get_image;
|
||||
vf->query_format=query_format;
|
||||
vf->uninit=uninit;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
|
||||
init_avcodec();
|
||||
|
||||
vf->priv->mode=0;
|
||||
vf->priv->parity= -1;
|
||||
vf->priv->qp=1;
|
||||
|
||||
if (args) sscanf(args, "%d:%d:%d", &vf->priv->mode, &vf->priv->parity, &vf->priv->qp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_mcdeint = {
|
||||
"motion compensating deinterlacer",
|
||||
"mcdeint",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
131
libavfilter/libmpcodecs/vf_mirror.c
Normal file
131
libavfilter/libmpcodecs/vf_mirror.c
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
|
||||
static void mirror(unsigned char* dst,unsigned char* src,int dststride,int srcstride,int w,int h,int bpp,unsigned int fmt){
|
||||
int y;
|
||||
for(y=0;y<h;y++){
|
||||
int x;
|
||||
switch(bpp){
|
||||
case 1:
|
||||
for(x=0;x<w;x++) dst[x]=src[w-x-1];
|
||||
break;
|
||||
case 2:
|
||||
switch(fmt){
|
||||
case IMGFMT_UYVY: {
|
||||
// packed YUV is tricky. U,V are 32bpp while Y is 16bpp:
|
||||
int w2=w>>1;
|
||||
for(x=0;x<w2;x++){
|
||||
// TODO: optimize this...
|
||||
dst[x*4+0]=src[0+(w2-x-1)*4];
|
||||
dst[x*4+1]=src[3+(w2-x-1)*4];
|
||||
dst[x*4+2]=src[2+(w2-x-1)*4];
|
||||
dst[x*4+3]=src[1+(w2-x-1)*4];
|
||||
}
|
||||
break; }
|
||||
case IMGFMT_YUY2:
|
||||
case IMGFMT_YVYU: {
|
||||
// packed YUV is tricky. U,V are 32bpp while Y is 16bpp:
|
||||
int w2=w>>1;
|
||||
for(x=0;x<w2;x++){
|
||||
// TODO: optimize this...
|
||||
dst[x*4+0]=src[2+(w2-x-1)*4];
|
||||
dst[x*4+1]=src[1+(w2-x-1)*4];
|
||||
dst[x*4+2]=src[0+(w2-x-1)*4];
|
||||
dst[x*4+3]=src[3+(w2-x-1)*4];
|
||||
}
|
||||
break; }
|
||||
default:
|
||||
for(x=0;x<w;x++) *((short*)(dst+x*2))=*((short*)(src+(w-x-1)*2));
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
for(x=0;x<w;x++){
|
||||
dst[x*3+0]=src[0+(w-x-1)*3];
|
||||
dst[x*3+1]=src[1+(w-x-1)*3];
|
||||
dst[x*3+2]=src[2+(w-x-1)*3];
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for(x=0;x<w;x++) *((int*)(dst+x*4))=*((int*)(src+(w-x-1)*4));
|
||||
}
|
||||
src+=srcstride;
|
||||
dst+=dststride;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
|
||||
// hope we'll get DR buffer:
|
||||
dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->w, mpi->h);
|
||||
|
||||
if(mpi->flags&MP_IMGFLAG_PLANAR){
|
||||
mirror(dmpi->planes[0],mpi->planes[0],
|
||||
dmpi->stride[0],mpi->stride[0],
|
||||
dmpi->w,dmpi->h,1,mpi->imgfmt);
|
||||
mirror(dmpi->planes[1],mpi->planes[1],
|
||||
dmpi->stride[1],mpi->stride[1],
|
||||
dmpi->w>>mpi->chroma_x_shift,dmpi->h>>mpi->chroma_y_shift,1,mpi->imgfmt);
|
||||
mirror(dmpi->planes[2],mpi->planes[2],
|
||||
dmpi->stride[2],mpi->stride[2],
|
||||
dmpi->w>>mpi->chroma_x_shift,dmpi->h>>mpi->chroma_y_shift,1,mpi->imgfmt);
|
||||
} else {
|
||||
mirror(dmpi->planes[0],mpi->planes[0],
|
||||
dmpi->stride[0],mpi->stride[0],
|
||||
dmpi->w,dmpi->h,dmpi->bpp>>3,mpi->imgfmt);
|
||||
dmpi->planes[1]=mpi->planes[1]; // passthrough rgb8 palette
|
||||
}
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
//vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_mirror = {
|
||||
"horizontal mirror",
|
||||
"mirror",
|
||||
"Eyck",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
474
libavfilter/libmpcodecs/vf_noise.c
Normal file
474
libavfilter/libmpcodecs/vf_noise.c
Normal file
@ -0,0 +1,474 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
#if HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
#include "libvo/fastmemcpy.h"
|
||||
#include "libavutil/mem.h"
|
||||
|
||||
#define MAX_NOISE 4096
|
||||
#define MAX_SHIFT 1024
|
||||
#define MAX_RES (MAX_NOISE-MAX_SHIFT)
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static inline void lineNoise_C(uint8_t *dst, uint8_t *src, int8_t *noise, int len, int shift);
|
||||
static inline void lineNoiseAvg_C(uint8_t *dst, uint8_t *src, int len, int8_t **shift);
|
||||
|
||||
static void (*lineNoise)(uint8_t *dst, uint8_t *src, int8_t *noise, int len, int shift)= lineNoise_C;
|
||||
static void (*lineNoiseAvg)(uint8_t *dst, uint8_t *src, int len, int8_t **shift)= lineNoiseAvg_C;
|
||||
|
||||
typedef struct FilterParam{
|
||||
int strength;
|
||||
int uniform;
|
||||
int temporal;
|
||||
int quality;
|
||||
int averaged;
|
||||
int pattern;
|
||||
int shiftptr;
|
||||
int8_t *noise;
|
||||
int8_t *prev_shift[MAX_RES][3];
|
||||
}FilterParam;
|
||||
|
||||
struct vf_priv_s {
|
||||
FilterParam lumaParam;
|
||||
FilterParam chromaParam;
|
||||
unsigned int outfmt;
|
||||
};
|
||||
|
||||
static int nonTempRandShift_init;
|
||||
static int nonTempRandShift[MAX_RES];
|
||||
|
||||
static int patt[4] = {
|
||||
-1,0,1,0
|
||||
};
|
||||
|
||||
#define RAND_N(range) ((int) ((double)range*rand()/(RAND_MAX+1.0)))
|
||||
static int8_t *initNoise(FilterParam *fp){
|
||||
int strength= fp->strength;
|
||||
int uniform= fp->uniform;
|
||||
int averaged= fp->averaged;
|
||||
int pattern= fp->pattern;
|
||||
int8_t *noise= av_malloc(MAX_NOISE*sizeof(int8_t));
|
||||
int i, j;
|
||||
|
||||
srand(123457);
|
||||
|
||||
for(i=0,j=0; i<MAX_NOISE; i++,j++)
|
||||
{
|
||||
if(uniform) {
|
||||
if (averaged) {
|
||||
if (pattern) {
|
||||
noise[i]= (RAND_N(strength) - strength/2)/6
|
||||
+patt[j%4]*strength*0.25/3;
|
||||
} else {
|
||||
noise[i]= (RAND_N(strength) - strength/2)/3;
|
||||
}
|
||||
} else {
|
||||
if (pattern) {
|
||||
noise[i]= (RAND_N(strength) - strength/2)/2
|
||||
+ patt[j%4]*strength*0.25;
|
||||
} else {
|
||||
noise[i]= RAND_N(strength) - strength/2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
double x1, x2, w, y1;
|
||||
do {
|
||||
x1 = 2.0 * rand()/(float)RAND_MAX - 1.0;
|
||||
x2 = 2.0 * rand()/(float)RAND_MAX - 1.0;
|
||||
w = x1 * x1 + x2 * x2;
|
||||
} while ( w >= 1.0 );
|
||||
|
||||
w = sqrt( (-2.0 * log( w ) ) / w );
|
||||
y1= x1 * w;
|
||||
y1*= strength / sqrt(3.0);
|
||||
if (pattern) {
|
||||
y1 /= 2;
|
||||
y1 += patt[j%4]*strength*0.35;
|
||||
}
|
||||
if (y1<-128) y1=-128;
|
||||
else if(y1> 127) y1= 127;
|
||||
if (averaged) y1 /= 3.0;
|
||||
noise[i]= (int)y1;
|
||||
}
|
||||
if (RAND_N(6) == 0) j--;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < MAX_RES; i++)
|
||||
for (j = 0; j < 3; j++)
|
||||
fp->prev_shift[i][j] = noise + (rand()&(MAX_SHIFT-1));
|
||||
|
||||
if(!nonTempRandShift_init){
|
||||
for(i=0; i<MAX_RES; i++){
|
||||
nonTempRandShift[i]= rand()&(MAX_SHIFT-1);
|
||||
}
|
||||
nonTempRandShift_init = 1;
|
||||
}
|
||||
|
||||
fp->noise= noise;
|
||||
fp->shiftptr= 0;
|
||||
return noise;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#if HAVE_MMX
|
||||
static inline void lineNoise_MMX(uint8_t *dst, uint8_t *src, int8_t *noise, int len, int shift){
|
||||
x86_reg mmx_len= len&(~7);
|
||||
noise+=shift;
|
||||
|
||||
__asm__ volatile(
|
||||
"mov %3, %%"REG_a" \n\t"
|
||||
"pcmpeqb %%mm7, %%mm7 \n\t"
|
||||
"psllw $15, %%mm7 \n\t"
|
||||
"packsswb %%mm7, %%mm7 \n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%0, %%"REG_a"), %%mm0 \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm1 \n\t"
|
||||
"pxor %%mm7, %%mm0 \n\t"
|
||||
"paddsb %%mm1, %%mm0 \n\t"
|
||||
"pxor %%mm7, %%mm0 \n\t"
|
||||
"movq %%mm0, (%2, %%"REG_a") \n\t"
|
||||
"add $8, %%"REG_a" \n\t"
|
||||
" js 1b \n\t"
|
||||
:: "r" (src+mmx_len), "r" (noise+mmx_len), "r" (dst+mmx_len), "g" (-mmx_len)
|
||||
: "%"REG_a
|
||||
);
|
||||
if(mmx_len!=len)
|
||||
lineNoise_C(dst+mmx_len, src+mmx_len, noise+mmx_len, len-mmx_len, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
//duplicate of previous except movntq
|
||||
#if HAVE_MMX2
|
||||
static inline void lineNoise_MMX2(uint8_t *dst, uint8_t *src, int8_t *noise, int len, int shift){
|
||||
x86_reg mmx_len= len&(~7);
|
||||
noise+=shift;
|
||||
|
||||
__asm__ volatile(
|
||||
"mov %3, %%"REG_a" \n\t"
|
||||
"pcmpeqb %%mm7, %%mm7 \n\t"
|
||||
"psllw $15, %%mm7 \n\t"
|
||||
"packsswb %%mm7, %%mm7 \n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%0, %%"REG_a"), %%mm0 \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm1 \n\t"
|
||||
"pxor %%mm7, %%mm0 \n\t"
|
||||
"paddsb %%mm1, %%mm0 \n\t"
|
||||
"pxor %%mm7, %%mm0 \n\t"
|
||||
"movntq %%mm0, (%2, %%"REG_a") \n\t"
|
||||
"add $8, %%"REG_a" \n\t"
|
||||
" js 1b \n\t"
|
||||
:: "r" (src+mmx_len), "r" (noise+mmx_len), "r" (dst+mmx_len), "g" (-mmx_len)
|
||||
: "%"REG_a
|
||||
);
|
||||
if(mmx_len!=len)
|
||||
lineNoise_C(dst+mmx_len, src+mmx_len, noise+mmx_len, len-mmx_len, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void lineNoise_C(uint8_t *dst, uint8_t *src, int8_t *noise, int len, int shift){
|
||||
int i;
|
||||
noise+= shift;
|
||||
for(i=0; i<len; i++)
|
||||
{
|
||||
int v= src[i]+ noise[i];
|
||||
if(v>255) dst[i]=255; //FIXME optimize
|
||||
else if(v<0) dst[i]=0;
|
||||
else dst[i]=v;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#if HAVE_MMX
|
||||
static inline void lineNoiseAvg_MMX(uint8_t *dst, uint8_t *src, int len, int8_t **shift){
|
||||
x86_reg mmx_len= len&(~7);
|
||||
|
||||
__asm__ volatile(
|
||||
"mov %5, %%"REG_a" \n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm1 \n\t"
|
||||
"movq (%0, %%"REG_a"), %%mm0 \n\t"
|
||||
"paddb (%2, %%"REG_a"), %%mm1 \n\t"
|
||||
"paddb (%3, %%"REG_a"), %%mm1 \n\t"
|
||||
"movq %%mm0, %%mm2 \n\t"
|
||||
"movq %%mm1, %%mm3 \n\t"
|
||||
"punpcklbw %%mm0, %%mm0 \n\t"
|
||||
"punpckhbw %%mm2, %%mm2 \n\t"
|
||||
"punpcklbw %%mm1, %%mm1 \n\t"
|
||||
"punpckhbw %%mm3, %%mm3 \n\t"
|
||||
"pmulhw %%mm0, %%mm1 \n\t"
|
||||
"pmulhw %%mm2, %%mm3 \n\t"
|
||||
"paddw %%mm1, %%mm1 \n\t"
|
||||
"paddw %%mm3, %%mm3 \n\t"
|
||||
"paddw %%mm0, %%mm1 \n\t"
|
||||
"paddw %%mm2, %%mm3 \n\t"
|
||||
"psrlw $8, %%mm1 \n\t"
|
||||
"psrlw $8, %%mm3 \n\t"
|
||||
"packuswb %%mm3, %%mm1 \n\t"
|
||||
"movq %%mm1, (%4, %%"REG_a") \n\t"
|
||||
"add $8, %%"REG_a" \n\t"
|
||||
" js 1b \n\t"
|
||||
:: "r" (src+mmx_len), "r" (shift[0]+mmx_len), "r" (shift[1]+mmx_len), "r" (shift[2]+mmx_len),
|
||||
"r" (dst+mmx_len), "g" (-mmx_len)
|
||||
: "%"REG_a
|
||||
);
|
||||
|
||||
if(mmx_len!=len){
|
||||
int8_t *shift2[3]={shift[0]+mmx_len, shift[1]+mmx_len, shift[2]+mmx_len};
|
||||
lineNoiseAvg_C(dst+mmx_len, src+mmx_len, len-mmx_len, shift2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void lineNoiseAvg_C(uint8_t *dst, uint8_t *src, int len, int8_t **shift){
|
||||
int i;
|
||||
int8_t *src2= (int8_t*)src;
|
||||
|
||||
for(i=0; i<len; i++)
|
||||
{
|
||||
const int n= shift[0][i] + shift[1][i] + shift[2][i];
|
||||
dst[i]= src2[i]+((n*src2[i])>>7);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static void noise(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int width, int height, FilterParam *fp){
|
||||
int8_t *noise= fp->noise;
|
||||
int y;
|
||||
int shift=0;
|
||||
|
||||
if(!noise)
|
||||
{
|
||||
if(src==dst) return;
|
||||
|
||||
if(dstStride==srcStride) fast_memcpy(dst, src, srcStride*height);
|
||||
else
|
||||
{
|
||||
for(y=0; y<height; y++)
|
||||
{
|
||||
fast_memcpy(dst, src, width);
|
||||
dst+= dstStride;
|
||||
src+= srcStride;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for(y=0; y<height; y++)
|
||||
{
|
||||
if(fp->temporal) shift= rand()&(MAX_SHIFT -1);
|
||||
else shift= nonTempRandShift[y];
|
||||
|
||||
if(fp->quality==0) shift&= ~7;
|
||||
if (fp->averaged) {
|
||||
lineNoiseAvg(dst, src, width, fp->prev_shift[y]);
|
||||
fp->prev_shift[y][fp->shiftptr] = noise + shift;
|
||||
} else {
|
||||
lineNoise(dst, src, noise, width, shift);
|
||||
}
|
||||
dst+= dstStride;
|
||||
src+= srcStride;
|
||||
}
|
||||
fp->shiftptr++;
|
||||
if (fp->shiftptr == 3) fp->shiftptr = 0;
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static void get_image(struct vf_instance *vf, mp_image_t *mpi){
|
||||
if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
|
||||
if(mpi->imgfmt!=vf->priv->outfmt) return; // colorspace differ
|
||||
// ok, we can do pp in-place (or pp disabled):
|
||||
vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
mpi->type, mpi->flags, mpi->w, mpi->h);
|
||||
mpi->planes[0]=vf->dmpi->planes[0];
|
||||
mpi->stride[0]=vf->dmpi->stride[0];
|
||||
mpi->width=vf->dmpi->width;
|
||||
if(mpi->flags&MP_IMGFLAG_PLANAR){
|
||||
mpi->planes[1]=vf->dmpi->planes[1];
|
||||
mpi->planes[2]=vf->dmpi->planes[2];
|
||||
mpi->stride[1]=vf->dmpi->stride[1];
|
||||
mpi->stride[2]=vf->dmpi->stride[2];
|
||||
}
|
||||
mpi->flags|=MP_IMGFLAG_DIRECT;
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
|
||||
if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
|
||||
// no DR, so get a new image! hope we'll get DR buffer:
|
||||
vf->dmpi=vf_get_image(vf->next,vf->priv->outfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->w,mpi->h);
|
||||
//printf("nodr\n");
|
||||
}
|
||||
//else printf("dr\n");
|
||||
dmpi= vf->dmpi;
|
||||
|
||||
noise(dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, &vf->priv->lumaParam);
|
||||
noise(dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w/2, mpi->h/2, &vf->priv->chromaParam);
|
||||
noise(dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w/2, mpi->h/2, &vf->priv->chromaParam);
|
||||
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
|
||||
#if HAVE_MMX
|
||||
if(gCpuCaps.hasMMX) __asm__ volatile ("emms\n\t");
|
||||
#endif
|
||||
#if HAVE_MMX2
|
||||
if(gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
|
||||
#endif
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf){
|
||||
if(!vf->priv) return;
|
||||
|
||||
av_free(vf->priv->chromaParam.noise);
|
||||
vf->priv->chromaParam.noise= NULL;
|
||||
|
||||
av_free(vf->priv->lumaParam.noise);
|
||||
vf->priv->lumaParam.noise= NULL;
|
||||
|
||||
free(vf->priv);
|
||||
vf->priv=NULL;
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
switch(fmt)
|
||||
{
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
return vf_next_query_format(vf,vf->priv->outfmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void parse(FilterParam *fp, char* args){
|
||||
char *pos;
|
||||
char *max= strchr(args, ':');
|
||||
|
||||
if(!max) max= args + strlen(args);
|
||||
|
||||
fp->strength= atoi(args);
|
||||
pos= strchr(args, 'u');
|
||||
if(pos && pos<max) fp->uniform=1;
|
||||
pos= strchr(args, 't');
|
||||
if(pos && pos<max) fp->temporal=1;
|
||||
pos= strchr(args, 'h');
|
||||
if(pos && pos<max) fp->quality=1;
|
||||
pos= strchr(args, 'p');
|
||||
if(pos && pos<max) fp->pattern=1;
|
||||
pos= strchr(args, 'a');
|
||||
if(pos && pos<max) {
|
||||
fp->temporal=1;
|
||||
fp->averaged=1;
|
||||
}
|
||||
|
||||
if(fp->strength) initNoise(fp);
|
||||
}
|
||||
|
||||
static const unsigned int fmt_list[]={
|
||||
IMGFMT_YV12,
|
||||
IMGFMT_I420,
|
||||
IMGFMT_IYUV,
|
||||
0
|
||||
};
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->get_image=get_image;
|
||||
vf->query_format=query_format;
|
||||
vf->uninit=uninit;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
if(args)
|
||||
{
|
||||
char *arg2= strchr(args,':');
|
||||
if(arg2) parse(&vf->priv->chromaParam, arg2+1);
|
||||
parse(&vf->priv->lumaParam, args);
|
||||
}
|
||||
|
||||
// check csp:
|
||||
vf->priv->outfmt=vf_match_csp(&vf->next,fmt_list,IMGFMT_YV12);
|
||||
if(!vf->priv->outfmt)
|
||||
{
|
||||
uninit(vf);
|
||||
return 0; // no csp match :(
|
||||
}
|
||||
|
||||
|
||||
#if HAVE_MMX
|
||||
if(gCpuCaps.hasMMX){
|
||||
lineNoise= lineNoise_MMX;
|
||||
lineNoiseAvg= lineNoiseAvg_MMX;
|
||||
}
|
||||
#endif
|
||||
#if HAVE_MMX2
|
||||
if(gCpuCaps.hasMMX2) lineNoise= lineNoise_MMX2;
|
||||
// if(gCpuCaps.hasMMX) lineNoiseAvg= lineNoiseAvg_MMX2;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_noise = {
|
||||
"noise generator",
|
||||
"noise",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
322
libavfilter/libmpcodecs/vf_ow.c
Normal file
322
libavfilter/libmpcodecs/vf_ow.c
Normal file
@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @todo try to change to int
|
||||
* @todo try lifting based implementation
|
||||
* @todo optimize optimize optimize
|
||||
* @todo hard tresholding
|
||||
* @todo use QP to decide filter strength
|
||||
* @todo wavelet normalization / least squares optimal signal vs. noise thresholds
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "mp_msg.h"
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
//===========================================================================//
|
||||
static const uint8_t __attribute__((aligned(8))) dither[8][8]={
|
||||
{ 0, 48, 12, 60, 3, 51, 15, 63, },
|
||||
{ 32, 16, 44, 28, 35, 19, 47, 31, },
|
||||
{ 8, 56, 4, 52, 11, 59, 7, 55, },
|
||||
{ 40, 24, 36, 20, 43, 27, 39, 23, },
|
||||
{ 2, 50, 14, 62, 1, 49, 13, 61, },
|
||||
{ 34, 18, 46, 30, 33, 17, 45, 29, },
|
||||
{ 10, 58, 6, 54, 9, 57, 5, 53, },
|
||||
{ 42, 26, 38, 22, 41, 25, 37, 21, },
|
||||
};
|
||||
//FIXME the above is duplicated in many filters
|
||||
|
||||
struct vf_priv_s {
|
||||
float strength[2];
|
||||
float delta;
|
||||
int mode;
|
||||
int depth;
|
||||
float *plane[16][4];
|
||||
int stride;
|
||||
};
|
||||
|
||||
#define S 1.41421356237 //sqrt(2)
|
||||
|
||||
static const double coeff[2][5]={
|
||||
{
|
||||
0.6029490182363579 *S,
|
||||
0.2668641184428723 *S,
|
||||
-0.07822326652898785 *S,
|
||||
-0.01686411844287495 *S,
|
||||
0.02674875741080976 *S
|
||||
},{
|
||||
1.115087052456994 /S,
|
||||
-0.5912717631142470 /S,
|
||||
-0.05754352622849957 /S,
|
||||
0.09127176311424948 /S
|
||||
}
|
||||
};
|
||||
|
||||
static const double icoeff[2][5]={
|
||||
{
|
||||
1.115087052456994 /S,
|
||||
0.5912717631142470 /S,
|
||||
-0.05754352622849957 /S,
|
||||
-0.09127176311424948 /S
|
||||
},{
|
||||
0.6029490182363579 *S,
|
||||
-0.2668641184428723 *S,
|
||||
-0.07822326652898785 *S,
|
||||
0.01686411844287495 *S,
|
||||
0.02674875741080976 *S
|
||||
}
|
||||
};
|
||||
#undef S
|
||||
|
||||
static inline int mirror(int x, int w){
|
||||
while((unsigned)x > (unsigned)w){
|
||||
x=-x;
|
||||
if(x<0) x+= 2*w;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void decompose(float *dstL, float *dstH, float *src, int stride, int w){
|
||||
int x, i;
|
||||
for(x=0; x<w; x++){
|
||||
double sumL= src[x*stride] * coeff[0][0];
|
||||
double sumH= src[x*stride] * coeff[1][0];
|
||||
for(i=1; i<=4; i++){
|
||||
double s= (src[mirror(x-i, w-1)*stride] + src[mirror(x+i, w-1)*stride]);
|
||||
|
||||
sumL+= coeff[0][i]*s;
|
||||
sumH+= coeff[1][i]*s;
|
||||
}
|
||||
dstL[x*stride]= sumL;
|
||||
dstH[x*stride]= sumH;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void compose(float *dst, float *srcL, float *srcH, int stride, int w){
|
||||
int x, i;
|
||||
for(x=0; x<w; x++){
|
||||
double sumL= srcL[x*stride] * icoeff[0][0];
|
||||
double sumH= srcH[x*stride] * icoeff[1][0];
|
||||
for(i=1; i<=4; i++){
|
||||
int x0= mirror(x-i, w-1)*stride;
|
||||
int x1= mirror(x+i, w-1)*stride;
|
||||
|
||||
sumL+= icoeff[0][i]*(srcL[x0] + srcL[x1]);
|
||||
sumH+= icoeff[1][i]*(srcH[x0] + srcH[x1]);
|
||||
}
|
||||
dst[x*stride]= (sumL + sumH)*0.5;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void decompose2D(float *dstL, float *dstH, float *src, int xstride, int ystride, int step, int w, int h){
|
||||
int y, x;
|
||||
for(y=0; y<h; y++)
|
||||
for(x=0; x<step; x++)
|
||||
decompose(dstL + ystride*y + xstride*x, dstH + ystride*y + xstride*x, src + ystride*y + xstride*x, step*xstride, (w-x+step-1)/step);
|
||||
}
|
||||
|
||||
static inline void compose2D(float *dst, float *srcL, float *srcH, int xstride, int ystride, int step, int w, int h){
|
||||
int y, x;
|
||||
for(y=0; y<h; y++)
|
||||
for(x=0; x<step; x++)
|
||||
compose(dst + ystride*y + xstride*x, srcL + ystride*y + xstride*x, srcH + ystride*y + xstride*x, step*xstride, (w-x+step-1)/step);
|
||||
}
|
||||
|
||||
static void decompose2D2(float *dst[4], float *src, float *temp[2], int stride, int step, int w, int h){
|
||||
decompose2D(temp[0], temp[1], src , 1, stride, step , w, h);
|
||||
decompose2D( dst[0], dst[1], temp[0], stride, 1, step , h, w);
|
||||
decompose2D( dst[2], dst[3], temp[1], stride, 1, step , h, w);
|
||||
}
|
||||
|
||||
static void compose2D2(float *dst, float *src[4], float *temp[2], int stride, int step, int w, int h){
|
||||
compose2D(temp[0], src[0], src[1], stride, 1, step , h, w);
|
||||
compose2D(temp[1], src[2], src[3], stride, 1, step , h, w);
|
||||
compose2D(dst , temp[0], temp[1], 1, stride, step , w, h);
|
||||
}
|
||||
|
||||
static void filter(struct vf_priv_s *p, uint8_t *dst, uint8_t *src, int dst_stride, int src_stride, int width, int height, int is_luma){
|
||||
int x,y, i, j;
|
||||
// double sum=0;
|
||||
double s= p->strength[!is_luma];
|
||||
int depth= p->depth;
|
||||
|
||||
while(1<<depth > width || 1<<depth > height)
|
||||
depth--;
|
||||
|
||||
for(y=0; y<height; y++)
|
||||
for(x=0; x<width; x++)
|
||||
p->plane[0][0][x + y*p->stride]= src[x + y*src_stride];
|
||||
|
||||
for(i=0; i<depth; i++){
|
||||
decompose2D2(p->plane[i+1], p->plane[i][0], p->plane[0]+1,p->stride, 1<<i, width, height);
|
||||
}
|
||||
for(i=0; i<depth; i++){
|
||||
for(j=1; j<4; j++){
|
||||
for(y=0; y<height; y++){
|
||||
for(x=0; x<width; x++){
|
||||
double v= p->plane[i+1][j][x + y*p->stride];
|
||||
if (v> s) v-=s;
|
||||
else if(v<-s) v+=s;
|
||||
else v =0;
|
||||
p->plane[i+1][j][x + y*p->stride]= v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i=depth-1; i>=0; i--){
|
||||
compose2D2(p->plane[i][0], p->plane[i+1], p->plane[0]+1, p->stride, 1<<i, width, height);
|
||||
}
|
||||
|
||||
for(y=0; y<height; y++)
|
||||
for(x=0; x<width; x++){
|
||||
i= p->plane[0][0][x + y*p->stride] + dither[x&7][y&7]*(1.0/64) + 1.0/128; //yes the rounding is insane but optimal :)
|
||||
// double e= i - src[x + y*src_stride];
|
||||
// sum += e*e;
|
||||
if((unsigned)i > 255U) i= ~(i>>31);
|
||||
dst[x + y*dst_stride]= i;
|
||||
}
|
||||
|
||||
// printf("%f\n", sum/height/width);
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt){
|
||||
int h= (height+15)&(~15);
|
||||
int i,j;
|
||||
|
||||
vf->priv->stride= (width+15)&(~15);
|
||||
for(j=0; j<4; j++){
|
||||
for(i=0; i<=vf->priv->depth; i++)
|
||||
vf->priv->plane[i][j]= malloc(vf->priv->stride*h*sizeof(vf->priv->plane[0][0][0]));
|
||||
}
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static void get_image(struct vf_instance *vf, mp_image_t *mpi){
|
||||
if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
|
||||
// ok, we can do pp in-place (or pp disabled):
|
||||
vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height);
|
||||
mpi->planes[0]=vf->dmpi->planes[0];
|
||||
mpi->stride[0]=vf->dmpi->stride[0];
|
||||
mpi->width=vf->dmpi->width;
|
||||
if(mpi->flags&MP_IMGFLAG_PLANAR){
|
||||
mpi->planes[1]=vf->dmpi->planes[1];
|
||||
mpi->planes[2]=vf->dmpi->planes[2];
|
||||
mpi->stride[1]=vf->dmpi->stride[1];
|
||||
mpi->stride[2]=vf->dmpi->stride[2];
|
||||
}
|
||||
mpi->flags|=MP_IMGFLAG_DIRECT;
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
|
||||
if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
|
||||
// no DR, so get a new image! hope we'll get DR buffer:
|
||||
dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP,
|
||||
MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
|
||||
mpi->width,mpi->height);
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
}else{
|
||||
dmpi=vf->dmpi;
|
||||
}
|
||||
|
||||
filter(vf->priv, dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, 1);
|
||||
filter(vf->priv, dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, 0);
|
||||
filter(vf->priv, dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, 0);
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf){
|
||||
int i,j;
|
||||
if(!vf->priv) return;
|
||||
|
||||
for(j=0; j<4; j++){
|
||||
for(i=0; i<16; i++){
|
||||
free(vf->priv->plane[i][j]);
|
||||
vf->priv->plane[i][j]= NULL;
|
||||
}
|
||||
}
|
||||
|
||||
free(vf->priv);
|
||||
vf->priv=NULL;
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
switch(fmt){
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_IF09:
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_CLPL:
|
||||
case IMGFMT_Y800:
|
||||
case IMGFMT_Y8:
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
return vf_next_query_format(vf,fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->get_image=get_image;
|
||||
vf->query_format=query_format;
|
||||
vf->uninit=uninit;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
|
||||
vf->priv->depth= 8;
|
||||
vf->priv->strength[0]= 1.0;
|
||||
vf->priv->strength[1]= 1.0;
|
||||
vf->priv->delta= 1.0;
|
||||
|
||||
if (args) sscanf(args, "%d:%f:%f:%d:%f", &vf->priv->depth,
|
||||
&vf->priv->strength[0],
|
||||
&vf->priv->strength[1],
|
||||
&vf->priv->mode,
|
||||
&vf->priv->delta);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_ow = {
|
||||
"overcomplete wavelet denoiser",
|
||||
"ow",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
235
libavfilter/libmpcodecs/vf_palette.c
Normal file
235
libavfilter/libmpcodecs/vf_palette.c
Normal file
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "help_mp.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
#include "mpbswap.h"
|
||||
|
||||
#include "libswscale/swscale.h"
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
// commented out 16 and 15 bit output support, because the conversion
|
||||
// routines are incorrrect. they assume the palette to be of the same
|
||||
// depth as the output, which is incorrect. --Joey
|
||||
|
||||
static const unsigned int bgr_list[]={
|
||||
IMGFMT_BGR32,
|
||||
IMGFMT_BGR24,
|
||||
// IMGFMT_BGR16,
|
||||
// IMGFMT_BGR15,
|
||||
0
|
||||
};
|
||||
static const unsigned int rgb_list[]={
|
||||
IMGFMT_RGB32,
|
||||
IMGFMT_RGB24,
|
||||
// IMGFMT_RGB16,
|
||||
// IMGFMT_RGB15,
|
||||
0
|
||||
};
|
||||
|
||||
/**
|
||||
* Palette is assumed to contain BGR16, see rgb32to16 to convert the palette.
|
||||
*/
|
||||
static void palette8torgb16(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette)
|
||||
{
|
||||
long i;
|
||||
for (i=0; i<num_pixels; i++)
|
||||
((uint16_t *)dst)[i] = ((const uint16_t *)palette)[src[i]];
|
||||
}
|
||||
|
||||
static void palette8tobgr16(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette)
|
||||
{
|
||||
long i;
|
||||
for (i=0; i<num_pixels; i++)
|
||||
((uint16_t *)dst)[i] = bswap_16(((const uint16_t *)palette)[src[i]]);
|
||||
}
|
||||
|
||||
static unsigned int gray_pal[256];
|
||||
|
||||
static unsigned int find_best(struct vf_instance *vf, unsigned int fmt){
|
||||
unsigned int best=0;
|
||||
int ret;
|
||||
const unsigned int* p;
|
||||
if(fmt==IMGFMT_BGR8) p=bgr_list;
|
||||
else if(fmt==IMGFMT_RGB8) p=rgb_list;
|
||||
else return 0;
|
||||
while(*p){
|
||||
ret=vf->next->query_format(vf->next,*p);
|
||||
mp_msg(MSGT_VFILTER,MSGL_DBG2,"[%s] query(%s) -> %d\n",vf->info->name,vo_format_name(*p),ret&3);
|
||||
if(ret&VFCAP_CSP_SUPPORTED_BY_HW){ best=*p; break;} // no conversion -> bingo!
|
||||
if(ret&VFCAP_CSP_SUPPORTED && !best) best=*p; // best with conversion
|
||||
++p;
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
struct vf_priv_s {
|
||||
unsigned int fmt;
|
||||
int pal_msg;
|
||||
};
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
if (!vf->priv->fmt)
|
||||
vf->priv->fmt=find_best(vf,outfmt);
|
||||
if(!vf->priv->fmt){
|
||||
// no matching fmt, so force one...
|
||||
if(outfmt==IMGFMT_RGB8) vf->priv->fmt=IMGFMT_RGB32;
|
||||
else if(outfmt==IMGFMT_BGR8) vf->priv->fmt=IMGFMT_BGR32;
|
||||
else return 0;
|
||||
}
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,vf->priv->fmt);
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
uint8_t *old_palette = mpi->planes[1];
|
||||
|
||||
// hope we'll get DR buffer:
|
||||
dmpi=vf_get_image(vf->next,vf->priv->fmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->w, mpi->h);
|
||||
|
||||
if (!mpi->planes[1])
|
||||
{
|
||||
if(!vf->priv->pal_msg){
|
||||
mp_msg(MSGT_VFILTER,MSGL_V,"[%s] no palette given, assuming builtin grayscale one\n",vf->info->name);
|
||||
vf->priv->pal_msg=1;
|
||||
}
|
||||
mpi->planes[1] = (unsigned char*)gray_pal;
|
||||
}
|
||||
|
||||
if(mpi->w==mpi->stride[0] && dmpi->w*(dmpi->bpp>>3)==dmpi->stride[0]){
|
||||
// no stride conversion needed
|
||||
switch(IMGFMT_RGB_DEPTH(dmpi->imgfmt)){
|
||||
case 15:
|
||||
case 16:
|
||||
if (IMGFMT_IS_BGR(dmpi->imgfmt))
|
||||
palette8tobgr16(mpi->planes[0],dmpi->planes[0],mpi->h*mpi->w,mpi->planes[1]);
|
||||
else
|
||||
palette8torgb16(mpi->planes[0],dmpi->planes[0],mpi->h*mpi->w,mpi->planes[1]);
|
||||
break;
|
||||
case 24:
|
||||
if (IMGFMT_IS_BGR(dmpi->imgfmt))
|
||||
sws_convertPalette8ToPacked24(mpi->planes[0],dmpi->planes[0],mpi->h*mpi->w,mpi->planes[1]);
|
||||
else
|
||||
sws_convertPalette8ToPacked24(mpi->planes[0],dmpi->planes[0],mpi->h*mpi->w,mpi->planes[1]);
|
||||
break;
|
||||
case 32:
|
||||
if (IMGFMT_IS_BGR(dmpi->imgfmt))
|
||||
sws_convertPalette8ToPacked32(mpi->planes[0],dmpi->planes[0],mpi->h*mpi->w,mpi->planes[1]);
|
||||
else
|
||||
sws_convertPalette8ToPacked32(mpi->planes[0],dmpi->planes[0],mpi->h*mpi->w,mpi->planes[1]);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
int y;
|
||||
for(y=0;y<mpi->h;y++){
|
||||
unsigned char* src=mpi->planes[0]+y*mpi->stride[0];
|
||||
unsigned char* dst=dmpi->planes[0]+y*dmpi->stride[0];
|
||||
switch(IMGFMT_RGB_DEPTH(dmpi->imgfmt)){
|
||||
case 15:
|
||||
case 16:
|
||||
if (IMGFMT_IS_BGR(dmpi->imgfmt))
|
||||
palette8tobgr16(src,dst,mpi->w,mpi->planes[1]);
|
||||
else
|
||||
palette8torgb16(src,dst,mpi->w,mpi->planes[1]);
|
||||
break;
|
||||
case 24:
|
||||
if (IMGFMT_IS_BGR(dmpi->imgfmt))
|
||||
sws_convertPalette8ToPacked24(src,dst,mpi->w,mpi->planes[1]);
|
||||
else
|
||||
sws_convertPalette8ToPacked24(src,dst,mpi->w,mpi->planes[1]);
|
||||
break;
|
||||
case 32:
|
||||
if (IMGFMT_IS_BGR(dmpi->imgfmt))
|
||||
sws_convertPalette8ToPacked32(src,dst,mpi->w,mpi->planes[1]);
|
||||
else
|
||||
sws_convertPalette8ToPacked32(src,dst,mpi->w,mpi->planes[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
mpi->planes[1] = old_palette;
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
int best=find_best(vf,fmt);
|
||||
if(!best) return 0; // no match
|
||||
return vf->next->query_format(vf->next,best);
|
||||
}
|
||||
|
||||
static void uninit(vf_instance_t *vf) {
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
unsigned int i;
|
||||
vf->config=config;
|
||||
vf->uninit=uninit;
|
||||
vf->put_image=put_image;
|
||||
vf->query_format=query_format;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
for(i=0;i<256;i++) gray_pal[i]=0x01010101*i;
|
||||
if (args)
|
||||
{
|
||||
if (!strcasecmp(args,"rgb15")) vf->priv->fmt=IMGFMT_RGB15; else
|
||||
if (!strcasecmp(args,"rgb16")) vf->priv->fmt=IMGFMT_RGB16; else
|
||||
if (!strcasecmp(args,"rgb24")) vf->priv->fmt=IMGFMT_RGB24; else
|
||||
if (!strcasecmp(args,"rgb32")) vf->priv->fmt=IMGFMT_RGB32; else
|
||||
if (!strcasecmp(args,"bgr15")) vf->priv->fmt=IMGFMT_BGR15; else
|
||||
if (!strcasecmp(args,"bgr16")) vf->priv->fmt=IMGFMT_BGR16; else
|
||||
if (!strcasecmp(args,"bgr24")) vf->priv->fmt=IMGFMT_BGR24; else
|
||||
if (!strcasecmp(args,"bgr32")) vf->priv->fmt=IMGFMT_BGR32; else
|
||||
{
|
||||
mp_msg(MSGT_VFILTER, MSGL_WARN, MSGTR_MPCODECS_UnknownFormatName, args);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_palette = {
|
||||
"8bpp indexed (using palette) -> BGR 15/16/24/32 conversion",
|
||||
"palette",
|
||||
"A'rpi & Alex",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
343
libavfilter/libmpcodecs/vf_perspective.c
Normal file
343
libavfilter/libmpcodecs/vf_perspective.c
Normal file
@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#if HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#define SUB_PIXEL_BITS 8
|
||||
#define SUB_PIXELS (1<<SUB_PIXEL_BITS)
|
||||
#define COEFF_BITS 11
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
struct vf_priv_s {
|
||||
double ref[4][2];
|
||||
int32_t coeff[1<<SUB_PIXEL_BITS][4];
|
||||
int32_t (*pv)[2];
|
||||
int pvStride;
|
||||
int cubic;
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static void initPv(struct vf_priv_s *priv, int W, int H){
|
||||
double a,b,c,d,e,f,g,h,D;
|
||||
double (*ref)[2]= priv->ref;
|
||||
int x,y;
|
||||
|
||||
g= ( (ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0])*(ref[2][1] - ref[3][1])
|
||||
- (ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1])*(ref[2][0] - ref[3][0]))*H;
|
||||
h= ( (ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1])*(ref[1][0] - ref[3][0])
|
||||
- (ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0])*(ref[1][1] - ref[3][1]))*W;
|
||||
D= (ref[1][0] - ref[3][0])*(ref[2][1] - ref[3][1])
|
||||
- (ref[2][0] - ref[3][0])*(ref[1][1] - ref[3][1]);
|
||||
|
||||
a= D*(ref[1][0] - ref[0][0])*H + g*ref[1][0];
|
||||
b= D*(ref[2][0] - ref[0][0])*W + h*ref[2][0];
|
||||
c= D*ref[0][0]*W*H;
|
||||
d= D*(ref[1][1] - ref[0][1])*H + g*ref[1][1];
|
||||
e= D*(ref[2][1] - ref[0][1])*W + h*ref[2][1];
|
||||
f= D*ref[0][1]*W*H;
|
||||
|
||||
for(y=0; y<H; y++){
|
||||
for(x=0; x<W; x++){
|
||||
int u, v;
|
||||
|
||||
u= (int)floor( SUB_PIXELS*(a*x + b*y + c)/(g*x + h*y + D*W*H) + 0.5);
|
||||
v= (int)floor( SUB_PIXELS*(d*x + e*y + f)/(g*x + h*y + D*W*H) + 0.5);
|
||||
|
||||
priv->pv[x + y*W][0]= u;
|
||||
priv->pv[x + y*W][1]= v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static double getCoeff(double d){
|
||||
double A= -0.60;
|
||||
double coeff;
|
||||
|
||||
d= fabs(d);
|
||||
|
||||
// Equation is from VirtualDub
|
||||
if(d<1.0)
|
||||
coeff = (1.0 - (A+3.0)*d*d + (A+2.0)*d*d*d);
|
||||
else if(d<2.0)
|
||||
coeff = (-4.0*A + 8.0*A*d - 5.0*A*d*d + A*d*d*d);
|
||||
else
|
||||
coeff=0.0;
|
||||
|
||||
return coeff;
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
int i, j;
|
||||
|
||||
vf->priv->pvStride= width;
|
||||
vf->priv->pv= (void*)memalign(8, width*height*2*sizeof(int32_t));
|
||||
initPv(vf->priv, width, height);
|
||||
|
||||
for(i=0; i<SUB_PIXELS; i++){
|
||||
double d= i/(double)SUB_PIXELS;
|
||||
double temp[4];
|
||||
double sum=0;
|
||||
|
||||
for(j=0; j<4; j++)
|
||||
temp[j]= getCoeff(j - d - 1);
|
||||
|
||||
for(j=0; j<4; j++)
|
||||
sum+= temp[j];
|
||||
|
||||
for(j=0; j<4; j++)
|
||||
vf->priv->coeff[i][j]= (int)floor((1<<COEFF_BITS)*temp[j]/sum + 0.5);
|
||||
}
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf){
|
||||
if(!vf->priv) return;
|
||||
|
||||
free(vf->priv->pv);
|
||||
vf->priv->pv= NULL;
|
||||
|
||||
free(vf->priv);
|
||||
vf->priv=NULL;
|
||||
}
|
||||
|
||||
static inline void resampleCubic(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, struct vf_priv_s *privParam, int xShift, int yShift){
|
||||
int x, y;
|
||||
struct vf_priv_s priv= *privParam;
|
||||
|
||||
for(y=0; y<h; y++){
|
||||
for(x=0; x<w; x++){
|
||||
int u, v, subU, subV, sum, sx, sy;
|
||||
|
||||
sx= x << xShift;
|
||||
sy= y << yShift;
|
||||
u= priv.pv[sx + sy*priv.pvStride][0]>>xShift;
|
||||
v= priv.pv[sx + sy*priv.pvStride][1]>>yShift;
|
||||
subU= u & (SUB_PIXELS-1);
|
||||
subV= v & (SUB_PIXELS-1);
|
||||
u >>= SUB_PIXEL_BITS;
|
||||
v >>= SUB_PIXEL_BITS;
|
||||
|
||||
if(u>0 && v>0 && u<w-2 && v<h-2){
|
||||
const int index= u + v*srcStride;
|
||||
const int a= priv.coeff[subU][0];
|
||||
const int b= priv.coeff[subU][1];
|
||||
const int c= priv.coeff[subU][2];
|
||||
const int d= priv.coeff[subU][3];
|
||||
|
||||
sum=
|
||||
priv.coeff[subV][0]*( a*src[index - 1 - srcStride] + b*src[index - 0 - srcStride]
|
||||
+ c*src[index + 1 - srcStride] + d*src[index + 2 - srcStride])
|
||||
+priv.coeff[subV][1]*( a*src[index - 1 ] + b*src[index - 0 ]
|
||||
+ c*src[index + 1 ] + d*src[index + 2 ])
|
||||
+priv.coeff[subV][2]*( a*src[index - 1 + srcStride] + b*src[index - 0 + srcStride]
|
||||
+ c*src[index + 1 + srcStride] + d*src[index + 2 + srcStride])
|
||||
+priv.coeff[subV][3]*( a*src[index - 1+2*srcStride] + b*src[index - 0+2*srcStride]
|
||||
+ c*src[index + 1+2*srcStride] + d*src[index + 2+2*srcStride]);
|
||||
}else{
|
||||
int dx, dy;
|
||||
sum=0;
|
||||
|
||||
for(dy=0; dy<4; dy++){
|
||||
int iy= v + dy - 1;
|
||||
if (iy< 0) iy=0;
|
||||
else if(iy>=h) iy=h-1;
|
||||
for(dx=0; dx<4; dx++){
|
||||
int ix= u + dx - 1;
|
||||
if (ix< 0) ix=0;
|
||||
else if(ix>=w) ix=w-1;
|
||||
|
||||
sum+= priv.coeff[subU][dx]*priv.coeff[subV][dy]
|
||||
*src[ ix + iy*srcStride];
|
||||
}
|
||||
}
|
||||
}
|
||||
sum= (sum + (1<<(COEFF_BITS*2-1)) ) >> (COEFF_BITS*2);
|
||||
if(sum&~255){
|
||||
if(sum<0) sum=0;
|
||||
else sum=255;
|
||||
}
|
||||
dst[ x + y*dstStride]= sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void resampleLinear(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride,
|
||||
struct vf_priv_s *privParam, int xShift, int yShift){
|
||||
int x, y;
|
||||
struct vf_priv_s priv= *privParam;
|
||||
|
||||
for(y=0; y<h; y++){
|
||||
for(x=0; x<w; x++){
|
||||
int u, v, subU, subV, sum, sx, sy, index, subUI, subVI;
|
||||
|
||||
sx= x << xShift;
|
||||
sy= y << yShift;
|
||||
u= priv.pv[sx + sy*priv.pvStride][0]>>xShift;
|
||||
v= priv.pv[sx + sy*priv.pvStride][1]>>yShift;
|
||||
subU= u & (SUB_PIXELS-1);
|
||||
subV= v & (SUB_PIXELS-1);
|
||||
u >>= SUB_PIXEL_BITS;
|
||||
v >>= SUB_PIXEL_BITS;
|
||||
index= u + v*srcStride;
|
||||
subUI= SUB_PIXELS - subU;
|
||||
subVI= SUB_PIXELS - subV;
|
||||
|
||||
if((unsigned)u < (unsigned)(w - 1)){
|
||||
if((unsigned)v < (unsigned)(h - 1)){
|
||||
sum= subVI*(subUI*src[index ] + subU*src[index +1])
|
||||
+subV *(subUI*src[index+srcStride] + subU*src[index+srcStride+1]);
|
||||
sum= (sum + (1<<(SUB_PIXEL_BITS*2-1)) ) >> (SUB_PIXEL_BITS*2);
|
||||
}else{
|
||||
if(v<0) v= 0;
|
||||
else v= h-1;
|
||||
index= u + v*srcStride;
|
||||
sum= subUI*src[index] + subU*src[index+1];
|
||||
sum= (sum + (1<<(SUB_PIXEL_BITS-1)) ) >> SUB_PIXEL_BITS;
|
||||
}
|
||||
}else{
|
||||
if((unsigned)v < (unsigned)(h - 1)){
|
||||
if(u<0) u= 0;
|
||||
else u= w-1;
|
||||
index= u + v*srcStride;
|
||||
sum= subVI*src[index] + subV*src[index+srcStride];
|
||||
sum= (sum + (1<<(SUB_PIXEL_BITS-1)) ) >> SUB_PIXEL_BITS;
|
||||
}else{
|
||||
if(u<0) u= 0;
|
||||
else u= w-1;
|
||||
if(v<0) v= 0;
|
||||
else v= h-1;
|
||||
index= u + v*srcStride;
|
||||
sum= src[index];
|
||||
}
|
||||
}
|
||||
if(sum&~255){
|
||||
if(sum<0) sum=0;
|
||||
else sum=255;
|
||||
}
|
||||
dst[ x + y*dstStride]= sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
int cw= mpi->w >> mpi->chroma_x_shift;
|
||||
int ch= mpi->h >> mpi->chroma_y_shift;
|
||||
|
||||
mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->w,mpi->h);
|
||||
|
||||
assert(mpi->flags&MP_IMGFLAG_PLANAR);
|
||||
|
||||
if(vf->priv->cubic){
|
||||
resampleCubic(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0],
|
||||
vf->priv, 0, 0);
|
||||
resampleCubic(dmpi->planes[1], mpi->planes[1], cw , ch , dmpi->stride[1], mpi->stride[1],
|
||||
vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift);
|
||||
resampleCubic(dmpi->planes[2], mpi->planes[2], cw , ch , dmpi->stride[2], mpi->stride[2],
|
||||
vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift);
|
||||
}else{
|
||||
resampleLinear(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0],
|
||||
vf->priv, 0, 0);
|
||||
resampleLinear(dmpi->planes[1], mpi->planes[1], cw , ch , dmpi->stride[1], mpi->stride[1],
|
||||
vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift);
|
||||
resampleLinear(dmpi->planes[2], mpi->planes[2], cw , ch , dmpi->stride[2], mpi->stride[2],
|
||||
vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift);
|
||||
}
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
switch(fmt)
|
||||
{
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
int e;
|
||||
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
// vf->get_image=get_image;
|
||||
vf->query_format=query_format;
|
||||
vf->uninit=uninit;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
|
||||
if(args==NULL) return 0;
|
||||
|
||||
e=sscanf(args, "%lf:%lf:%lf:%lf:%lf:%lf:%lf:%lf:%d",
|
||||
&vf->priv->ref[0][0], &vf->priv->ref[0][1],
|
||||
&vf->priv->ref[1][0], &vf->priv->ref[1][1],
|
||||
&vf->priv->ref[2][0], &vf->priv->ref[2][1],
|
||||
&vf->priv->ref[3][0], &vf->priv->ref[3][1],
|
||||
&vf->priv->cubic
|
||||
);
|
||||
|
||||
if(e!=9)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_perspective = {
|
||||
"perspective correcture",
|
||||
"perspective",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
301
libavfilter/libmpcodecs/vf_phase.c
Normal file
301
libavfilter/libmpcodecs/vf_phase.c
Normal file
@ -0,0 +1,301 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
enum mode { PROGRESSIVE, TOP_FIRST, BOTTOM_FIRST,
|
||||
TOP_FIRST_ANALYZE, BOTTOM_FIRST_ANALYZE,
|
||||
ANALYZE, FULL_ANALYZE, AUTO, AUTO_ANALYZE };
|
||||
|
||||
#define fixed_mode(p) ((p)<=BOTTOM_FIRST)
|
||||
|
||||
struct vf_priv_s
|
||||
{
|
||||
enum mode mode;
|
||||
int verbose;
|
||||
unsigned char *buf[3];
|
||||
};
|
||||
|
||||
/*
|
||||
* Copy fields from either current or buffered previous frame to the
|
||||
* output and store the current frame unmodified to the buffer.
|
||||
*/
|
||||
|
||||
static void do_plane(unsigned char *to, unsigned char *from,
|
||||
int w, int h, int ts, int fs,
|
||||
unsigned char **bufp, enum mode mode)
|
||||
{
|
||||
unsigned char *buf, *end;
|
||||
int top;
|
||||
|
||||
if(!*bufp)
|
||||
{
|
||||
mode=PROGRESSIVE;
|
||||
if(!(*bufp=malloc(h*w))) return;
|
||||
}
|
||||
|
||||
for(end=to+h*ts, buf=*bufp, top=1; to<end; from+=fs, to+=ts, buf+=w, top^=1)
|
||||
{
|
||||
fast_memcpy(to, mode==(top?BOTTOM_FIRST:TOP_FIRST)?buf:from, w);
|
||||
fast_memcpy(buf, from, w);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This macro interpolates the value of both fields at a point halfway
|
||||
* between lines and takes the squared difference. In field resolution
|
||||
* the point is a quarter pixel below a line in one field and a quarter
|
||||
* pixel above a line in other.
|
||||
*
|
||||
* (the result is actually multiplied by 25)
|
||||
*/
|
||||
|
||||
#define diff(a, as, b, bs) (t=((*a-b[bs])<<2)+a[as<<1]-b[-bs], t*t)
|
||||
|
||||
/*
|
||||
* Find which field combination has the smallest average squared difference
|
||||
* between the fields.
|
||||
*/
|
||||
|
||||
static enum mode analyze_plane(unsigned char *old, unsigned char *new,
|
||||
int w, int h, int os, int ns, enum mode mode,
|
||||
int verbose, int fields)
|
||||
{
|
||||
double bdiff, pdiff, tdiff, scale;
|
||||
int bdif, tdif, pdif;
|
||||
int top, t;
|
||||
unsigned char *end, *rend;
|
||||
|
||||
if(mode==AUTO)
|
||||
mode=fields&MP_IMGFIELD_ORDERED?fields&MP_IMGFIELD_TOP_FIRST?
|
||||
TOP_FIRST:BOTTOM_FIRST:PROGRESSIVE;
|
||||
else if(mode==AUTO_ANALYZE)
|
||||
mode=fields&MP_IMGFIELD_ORDERED?fields&MP_IMGFIELD_TOP_FIRST?
|
||||
TOP_FIRST_ANALYZE:BOTTOM_FIRST_ANALYZE:FULL_ANALYZE;
|
||||
|
||||
if(fixed_mode(mode))
|
||||
bdiff=pdiff=tdiff=65536.0;
|
||||
else
|
||||
{
|
||||
bdiff=pdiff=tdiff=0.0;
|
||||
|
||||
for(end=new+(h-2)*ns, new+=ns, old+=os, top=0;
|
||||
new<end; new+=ns-w, old+=os-w, top^=1)
|
||||
{
|
||||
pdif=tdif=bdif=0;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case TOP_FIRST_ANALYZE:
|
||||
if(top)
|
||||
for(rend=new+w; new<rend; new++, old++)
|
||||
pdif+=diff(new, ns, new, ns),
|
||||
tdif+=diff(new, ns, old, os);
|
||||
else
|
||||
for(rend=new+w; new<rend; new++, old++)
|
||||
pdif+=diff(new, ns, new, ns),
|
||||
tdif+=diff(old, os, new, ns);
|
||||
break;
|
||||
|
||||
case BOTTOM_FIRST_ANALYZE:
|
||||
if(top)
|
||||
for(rend=new+w; new<rend; new++, old++)
|
||||
pdif+=diff(new, ns, new, ns),
|
||||
bdif+=diff(old, os, new, ns);
|
||||
else
|
||||
for(rend=new+w; new<rend; new++, old++)
|
||||
pdif+=diff(new, ns, new, ns),
|
||||
bdif+=diff(new, ns, old, os);
|
||||
break;
|
||||
|
||||
case ANALYZE:
|
||||
if(top)
|
||||
for(rend=new+w; new<rend; new++, old++)
|
||||
tdif+=diff(new, ns, old, os),
|
||||
bdif+=diff(old, os, new, ns);
|
||||
else
|
||||
for(rend=new+w; new<rend; new++, old++)
|
||||
bdif+=diff(new, ns, old, os),
|
||||
tdif+=diff(old, os, new, ns);
|
||||
break;
|
||||
|
||||
default: /* FULL_ANALYZE */
|
||||
if(top)
|
||||
for(rend=new+w; new<rend; new++, old++)
|
||||
pdif+=diff(new, ns, new, ns),
|
||||
tdif+=diff(new, ns, old, os),
|
||||
bdif+=diff(old, os, new, ns);
|
||||
else
|
||||
for(rend=new+w; new<rend; new++, old++)
|
||||
pdif+=diff(new, ns, new, ns),
|
||||
bdif+=diff(new, ns, old, os),
|
||||
tdif+=diff(old, os, new, ns);
|
||||
}
|
||||
|
||||
pdiff+=(double)pdif;
|
||||
tdiff+=(double)tdif;
|
||||
bdiff+=(double)bdif;
|
||||
}
|
||||
|
||||
scale=1.0/(w*(h-3))/25.0;
|
||||
pdiff*=scale;
|
||||
tdiff*=scale;
|
||||
bdiff*=scale;
|
||||
|
||||
if(mode==TOP_FIRST_ANALYZE)
|
||||
bdiff=65536.0;
|
||||
else if(mode==BOTTOM_FIRST_ANALYZE)
|
||||
tdiff=65536.0;
|
||||
else if(mode==ANALYZE)
|
||||
pdiff=65536.0;
|
||||
|
||||
if(bdiff<pdiff && bdiff<tdiff)
|
||||
mode=BOTTOM_FIRST;
|
||||
else if(tdiff<pdiff && tdiff<bdiff)
|
||||
mode=TOP_FIRST;
|
||||
else
|
||||
mode=PROGRESSIVE;
|
||||
}
|
||||
|
||||
if( mp_msg_test(MSGT_VFILTER,MSGL_V) )
|
||||
{
|
||||
mp_msg(MSGT_VFILTER, MSGL_INFO, "%c", mode==BOTTOM_FIRST?'b':mode==TOP_FIRST?'t':'p');
|
||||
if(tdiff==65536.0) mp_msg(MSGT_VFILTER, MSGL_INFO," N/A "); else mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", tdiff);
|
||||
if(bdiff==65536.0) mp_msg(MSGT_VFILTER, MSGL_INFO," N/A "); else mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", bdiff);
|
||||
if(pdiff==65536.0) mp_msg(MSGT_VFILTER, MSGL_INFO," N/A "); else mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", pdiff);
|
||||
mp_msg(MSGT_VFILTER, MSGL_INFO," \n");
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
mp_image_t *dmpi;
|
||||
int w;
|
||||
enum mode mode;
|
||||
|
||||
if(!(dmpi=vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->w, mpi->h)))
|
||||
return 0;
|
||||
|
||||
w=dmpi->w;
|
||||
if(!(dmpi->flags&MP_IMGFLAG_PLANAR))
|
||||
w*=dmpi->bpp/8;
|
||||
|
||||
mode=vf->priv->mode;
|
||||
|
||||
if(!vf->priv->buf[0])
|
||||
mode=PROGRESSIVE;
|
||||
else
|
||||
mode=analyze_plane(vf->priv->buf[0], mpi->planes[0],
|
||||
w, dmpi->h, w, mpi->stride[0], mode,
|
||||
vf->priv->verbose, mpi->fields);
|
||||
|
||||
do_plane(dmpi->planes[0], mpi->planes[0],
|
||||
w, dmpi->h,
|
||||
dmpi->stride[0], mpi->stride[0],
|
||||
&vf->priv->buf[0], mode);
|
||||
|
||||
if(dmpi->flags&MP_IMGFLAG_PLANAR)
|
||||
{
|
||||
do_plane(dmpi->planes[1], mpi->planes[1],
|
||||
dmpi->chroma_width, dmpi->chroma_height,
|
||||
dmpi->stride[1], mpi->stride[1],
|
||||
&vf->priv->buf[1], mode);
|
||||
do_plane(dmpi->planes[2], mpi->planes[2],
|
||||
dmpi->chroma_width, dmpi->chroma_height,
|
||||
dmpi->stride[2], mpi->stride[2],
|
||||
&vf->priv->buf[2], mode);
|
||||
}
|
||||
|
||||
return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
free(vf->priv->buf[0]);
|
||||
free(vf->priv->buf[1]);
|
||||
free(vf->priv->buf[2]);
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
vf->put_image = put_image;
|
||||
vf->uninit = uninit;
|
||||
vf->default_reqs = VFCAP_ACCEPT_STRIDE;
|
||||
|
||||
if(!(vf->priv = calloc(1, sizeof(struct vf_priv_s))))
|
||||
{
|
||||
uninit(vf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vf->priv->mode=AUTO_ANALYZE;
|
||||
vf->priv->verbose=0;
|
||||
|
||||
while(args && *args)
|
||||
{
|
||||
switch(*args)
|
||||
{
|
||||
case 't': vf->priv->mode=TOP_FIRST; break;
|
||||
case 'a': vf->priv->mode=AUTO; break;
|
||||
case 'b': vf->priv->mode=BOTTOM_FIRST; break;
|
||||
case 'u': vf->priv->mode=ANALYZE; break;
|
||||
case 'T': vf->priv->mode=TOP_FIRST_ANALYZE; break;
|
||||
case 'A': vf->priv->mode=AUTO_ANALYZE; break;
|
||||
case 'B': vf->priv->mode=BOTTOM_FIRST_ANALYZE; break;
|
||||
case 'U': vf->priv->mode=FULL_ANALYZE; break;
|
||||
case 'p': vf->priv->mode=PROGRESSIVE; break;
|
||||
case 'v': vf->priv->verbose=1; break;
|
||||
case ':': break;
|
||||
|
||||
default:
|
||||
uninit(vf);
|
||||
return 0; /* bad args */
|
||||
}
|
||||
|
||||
if( (args=strchr(args, ':')) ) args++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_phase =
|
||||
{
|
||||
"phase shift fields",
|
||||
"phase",
|
||||
"Ville Saari",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
491
libavfilter/libmpcodecs/vf_pp7.c
Normal file
491
libavfilter/libmpcodecs/vf_pp7.c
Normal file
@ -0,0 +1,491 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
#if HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
#define XMIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define XMAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
typedef short DCTELEM;
|
||||
|
||||
//===========================================================================//
|
||||
static const uint8_t __attribute__((aligned(8))) dither[8][8]={
|
||||
{ 0, 48, 12, 60, 3, 51, 15, 63, },
|
||||
{ 32, 16, 44, 28, 35, 19, 47, 31, },
|
||||
{ 8, 56, 4, 52, 11, 59, 7, 55, },
|
||||
{ 40, 24, 36, 20, 43, 27, 39, 23, },
|
||||
{ 2, 50, 14, 62, 1, 49, 13, 61, },
|
||||
{ 34, 18, 46, 30, 33, 17, 45, 29, },
|
||||
{ 10, 58, 6, 54, 9, 57, 5, 53, },
|
||||
{ 42, 26, 38, 22, 41, 25, 37, 21, },
|
||||
};
|
||||
|
||||
struct vf_priv_s {
|
||||
int qp;
|
||||
int mode;
|
||||
int mpeg2;
|
||||
int temp_stride;
|
||||
uint8_t *src;
|
||||
};
|
||||
#if 0
|
||||
static inline void dct7_c(DCTELEM *dst, int s0, int s1, int s2, int s3, int step){
|
||||
int s, d;
|
||||
int dst2[64];
|
||||
//#define S0 (1024/0.37796447300922719759)
|
||||
#define C0 ((int)(1024*0.37796447300922719759+0.5)) //sqrt(1/7)
|
||||
#define C1 ((int)(1024*0.53452248382484879308/6+0.5)) //sqrt(2/7)/6
|
||||
|
||||
#define C2 ((int)(1024*0.45221175985034745004/2+0.5))
|
||||
#define C3 ((int)(1024*0.36264567479870879474/2+0.5))
|
||||
|
||||
//0.1962505182412941918 0.0149276808419397944-0.2111781990832339584
|
||||
#define C4 ((int)(1024*0.1962505182412941918+0.5))
|
||||
#define C5 ((int)(1024*0.0149276808419397944+0.5))
|
||||
//#define C6 ((int)(1024*0.2111781990832339584+0.5))
|
||||
#if 0
|
||||
s= s0 + s1 + s2;
|
||||
dst[0*step] = ((s + s3)*C0 + 512) >> 10;
|
||||
s= (s - 6*s3)*C1 + 512;
|
||||
d= (s0-s2)*C4 + (s1-s2)*C5;
|
||||
dst[1*step] = (s + 2*d)>>10;
|
||||
s -= d;
|
||||
d= (s1-s0)*C2 + (s1-s2)*C3;
|
||||
dst[2*step] = (s + d)>>10;
|
||||
dst[3*step] = (s - d)>>10;
|
||||
#elif 1
|
||||
s = s3+s3;
|
||||
s3= s-s0;
|
||||
s0= s+s0;
|
||||
s = s2+s1;
|
||||
s2= s2-s1;
|
||||
dst[0*step]= s0 + s;
|
||||
dst[2*step]= s0 - s;
|
||||
dst[1*step]= 2*s3 + s2;
|
||||
dst[3*step]= s3 - 2*s2;
|
||||
#else
|
||||
int i,j,n=7;
|
||||
for(i=0; i<7; i+=2){
|
||||
dst2[i*step/2]= 0;
|
||||
for(j=0; j<4; j++)
|
||||
dst2[i*step/2] += src[j*step] * cos(i*M_PI/n*(j+0.5)) * sqrt((i?2.0:1.0)/n);
|
||||
if(fabs(dst2[i*step/2] - dst[i*step/2]) > 20)
|
||||
printf("%d %d %d (%d %d %d %d) -> (%d %d %d %d)\n", i,dst2[i*step/2], dst[i*step/2],src[0*step], src[1*step], src[2*step], src[3*step], dst[0*step], dst[1*step],dst[2*step],dst[3*step]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void dctA_c(DCTELEM *dst, uint8_t *src, int stride){
|
||||
int i;
|
||||
|
||||
for(i=0; i<4; i++){
|
||||
int s0= src[0*stride] + src[6*stride];
|
||||
int s1= src[1*stride] + src[5*stride];
|
||||
int s2= src[2*stride] + src[4*stride];
|
||||
int s3= src[3*stride];
|
||||
int s= s3+s3;
|
||||
s3= s-s0;
|
||||
s0= s+s0;
|
||||
s = s2+s1;
|
||||
s2= s2-s1;
|
||||
dst[0]= s0 + s;
|
||||
dst[2]= s0 - s;
|
||||
dst[1]= 2*s3 + s2;
|
||||
dst[3]= s3 - 2*s2;
|
||||
src++;
|
||||
dst+=4;
|
||||
}
|
||||
}
|
||||
|
||||
static void dctB_c(DCTELEM *dst, DCTELEM *src){
|
||||
int i;
|
||||
|
||||
for(i=0; i<4; i++){
|
||||
int s0= src[0*4] + src[6*4];
|
||||
int s1= src[1*4] + src[5*4];
|
||||
int s2= src[2*4] + src[4*4];
|
||||
int s3= src[3*4];
|
||||
int s= s3+s3;
|
||||
s3= s-s0;
|
||||
s0= s+s0;
|
||||
s = s2+s1;
|
||||
s2= s2-s1;
|
||||
dst[0*4]= s0 + s;
|
||||
dst[2*4]= s0 - s;
|
||||
dst[1*4]= 2*s3 + s2;
|
||||
dst[3*4]= s3 - 2*s2;
|
||||
src++;
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_MMX
|
||||
static void dctB_mmx(DCTELEM *dst, DCTELEM *src){
|
||||
__asm__ volatile (
|
||||
"movq (%0), %%mm0 \n\t"
|
||||
"movq 1*4*2(%0), %%mm1 \n\t"
|
||||
"paddw 6*4*2(%0), %%mm0 \n\t"
|
||||
"paddw 5*4*2(%0), %%mm1 \n\t"
|
||||
"movq 2*4*2(%0), %%mm2 \n\t"
|
||||
"movq 3*4*2(%0), %%mm3 \n\t"
|
||||
"paddw 4*4*2(%0), %%mm2 \n\t"
|
||||
"paddw %%mm3, %%mm3 \n\t" //s
|
||||
"movq %%mm3, %%mm4 \n\t" //s
|
||||
"psubw %%mm0, %%mm3 \n\t" //s-s0
|
||||
"paddw %%mm0, %%mm4 \n\t" //s+s0
|
||||
"movq %%mm2, %%mm0 \n\t" //s2
|
||||
"psubw %%mm1, %%mm2 \n\t" //s2-s1
|
||||
"paddw %%mm1, %%mm0 \n\t" //s2+s1
|
||||
"movq %%mm4, %%mm1 \n\t" //s0'
|
||||
"psubw %%mm0, %%mm4 \n\t" //s0'-s'
|
||||
"paddw %%mm0, %%mm1 \n\t" //s0'+s'
|
||||
"movq %%mm3, %%mm0 \n\t" //s3'
|
||||
"psubw %%mm2, %%mm3 \n\t"
|
||||
"psubw %%mm2, %%mm3 \n\t"
|
||||
"paddw %%mm0, %%mm2 \n\t"
|
||||
"paddw %%mm0, %%mm2 \n\t"
|
||||
"movq %%mm1, (%1) \n\t"
|
||||
"movq %%mm4, 2*4*2(%1) \n\t"
|
||||
"movq %%mm2, 1*4*2(%1) \n\t"
|
||||
"movq %%mm3, 3*4*2(%1) \n\t"
|
||||
:: "r" (src), "r"(dst)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void (*dctB)(DCTELEM *dst, DCTELEM *src)= dctB_c;
|
||||
|
||||
#define N0 4
|
||||
#define N1 5
|
||||
#define N2 10
|
||||
#define SN0 2
|
||||
#define SN1 2.2360679775
|
||||
#define SN2 3.16227766017
|
||||
#define N (1<<16)
|
||||
|
||||
static const int factor[16]={
|
||||
N/(N0*N0), N/(N0*N1), N/(N0*N0),N/(N0*N2),
|
||||
N/(N1*N0), N/(N1*N1), N/(N1*N0),N/(N1*N2),
|
||||
N/(N0*N0), N/(N0*N1), N/(N0*N0),N/(N0*N2),
|
||||
N/(N2*N0), N/(N2*N1), N/(N2*N0),N/(N2*N2),
|
||||
};
|
||||
|
||||
static const int thres[16]={
|
||||
N/(SN0*SN0), N/(SN0*SN2), N/(SN0*SN0),N/(SN0*SN2),
|
||||
N/(SN2*SN0), N/(SN2*SN2), N/(SN2*SN0),N/(SN2*SN2),
|
||||
N/(SN0*SN0), N/(SN0*SN2), N/(SN0*SN0),N/(SN0*SN2),
|
||||
N/(SN2*SN0), N/(SN2*SN2), N/(SN2*SN0),N/(SN2*SN2),
|
||||
};
|
||||
|
||||
static int thres2[99][16];
|
||||
|
||||
static void init_thres2(void){
|
||||
int qp, i;
|
||||
int bias= 0; //FIXME
|
||||
|
||||
for(qp=0; qp<99; qp++){
|
||||
for(i=0; i<16; i++){
|
||||
thres2[qp][i]= ((i&1)?SN2:SN0) * ((i&4)?SN2:SN0) * XMAX(1,qp) * (1<<2) - 1 - bias;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int hardthresh_c(DCTELEM *src, int qp){
|
||||
int i;
|
||||
int a;
|
||||
|
||||
a= src[0] * factor[0];
|
||||
for(i=1; i<16; i++){
|
||||
unsigned int threshold1= thres2[qp][i];
|
||||
unsigned int threshold2= (threshold1<<1);
|
||||
int level= src[i];
|
||||
if(((unsigned)(level+threshold1))>threshold2){
|
||||
a += level * factor[i];
|
||||
}
|
||||
}
|
||||
return (a + (1<<11))>>12;
|
||||
}
|
||||
|
||||
static int mediumthresh_c(DCTELEM *src, int qp){
|
||||
int i;
|
||||
int a;
|
||||
|
||||
a= src[0] * factor[0];
|
||||
for(i=1; i<16; i++){
|
||||
unsigned int threshold1= thres2[qp][i];
|
||||
unsigned int threshold2= (threshold1<<1);
|
||||
int level= src[i];
|
||||
if(((unsigned)(level+threshold1))>threshold2){
|
||||
if(((unsigned)(level+2*threshold1))>2*threshold2){
|
||||
a += level * factor[i];
|
||||
}else{
|
||||
if(level>0) a+= 2*(level - (int)threshold1)*factor[i];
|
||||
else a+= 2*(level + (int)threshold1)*factor[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return (a + (1<<11))>>12;
|
||||
}
|
||||
|
||||
static int softthresh_c(DCTELEM *src, int qp){
|
||||
int i;
|
||||
int a;
|
||||
|
||||
a= src[0] * factor[0];
|
||||
for(i=1; i<16; i++){
|
||||
unsigned int threshold1= thres2[qp][i];
|
||||
unsigned int threshold2= (threshold1<<1);
|
||||
int level= src[i];
|
||||
if(((unsigned)(level+threshold1))>threshold2){
|
||||
if(level>0) a+= (level - (int)threshold1)*factor[i];
|
||||
else a+= (level + (int)threshold1)*factor[i];
|
||||
}
|
||||
}
|
||||
return (a + (1<<11))>>12;
|
||||
}
|
||||
|
||||
static int (*requantize)(DCTELEM *src, int qp)= hardthresh_c;
|
||||
|
||||
static void filter(struct vf_priv_s *p, uint8_t *dst, uint8_t *src, int dst_stride, int src_stride, int width, int height, uint8_t *qp_store, int qp_stride, int is_luma){
|
||||
int x, y;
|
||||
const int stride= is_luma ? p->temp_stride : ((width+16+15)&(~15));
|
||||
uint8_t *p_src= p->src + 8*stride;
|
||||
DCTELEM *block= p->src;
|
||||
DCTELEM *temp= p->src + 32;
|
||||
|
||||
if (!src || !dst) return; // HACK avoid crash for Y8 colourspace
|
||||
for(y=0; y<height; y++){
|
||||
int index= 8 + 8*stride + y*stride;
|
||||
fast_memcpy(p_src + index, src + y*src_stride, width);
|
||||
for(x=0; x<8; x++){
|
||||
p_src[index - x - 1]= p_src[index + x ];
|
||||
p_src[index + width + x ]= p_src[index + width - x - 1];
|
||||
}
|
||||
}
|
||||
for(y=0; y<8; y++){
|
||||
fast_memcpy(p_src + ( 7-y)*stride, p_src + ( y+8)*stride, stride);
|
||||
fast_memcpy(p_src + (height+8+y)*stride, p_src + (height-y+7)*stride, stride);
|
||||
}
|
||||
//FIXME (try edge emu)
|
||||
|
||||
for(y=0; y<height; y++){
|
||||
for(x=-8; x<0; x+=4){
|
||||
const int index= x + y*stride + (8-3)*(1+stride) + 8; //FIXME silly offset
|
||||
uint8_t *src = p_src + index;
|
||||
DCTELEM *tp= temp+4*x;
|
||||
|
||||
dctA_c(tp+4*8, src, stride);
|
||||
}
|
||||
for(x=0; x<width; ){
|
||||
const int qps= 3 + is_luma;
|
||||
int qp;
|
||||
int end= XMIN(x+8, width);
|
||||
|
||||
if(p->qp)
|
||||
qp= p->qp;
|
||||
else{
|
||||
qp= qp_store[ (XMIN(x, width-1)>>qps) + (XMIN(y, height-1)>>qps) * qp_stride];
|
||||
qp=norm_qscale(qp, p->mpeg2);
|
||||
}
|
||||
for(; x<end; x++){
|
||||
const int index= x + y*stride + (8-3)*(1+stride) + 8; //FIXME silly offset
|
||||
uint8_t *src = p_src + index;
|
||||
DCTELEM *tp= temp+4*x;
|
||||
int v;
|
||||
|
||||
if((x&3)==0)
|
||||
dctA_c(tp+4*8, src, stride);
|
||||
|
||||
dctB(block, tp);
|
||||
|
||||
v= requantize(block, qp);
|
||||
v= (v + dither[y&7][x&7])>>6;
|
||||
if((unsigned)v > 255)
|
||||
v= (-v)>>31;
|
||||
dst[x + y*dst_stride]= v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
int h= (height+16+15)&(~15);
|
||||
|
||||
vf->priv->temp_stride= (width+16+15)&(~15);
|
||||
vf->priv->src = memalign(8, vf->priv->temp_stride*(h+8)*sizeof(uint8_t));
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static void get_image(struct vf_instance *vf, mp_image_t *mpi){
|
||||
if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
|
||||
// ok, we can do pp in-place (or pp disabled):
|
||||
vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height);
|
||||
mpi->planes[0]=vf->dmpi->planes[0];
|
||||
mpi->stride[0]=vf->dmpi->stride[0];
|
||||
mpi->width=vf->dmpi->width;
|
||||
if(mpi->flags&MP_IMGFLAG_PLANAR){
|
||||
mpi->planes[1]=vf->dmpi->planes[1];
|
||||
mpi->planes[2]=vf->dmpi->planes[2];
|
||||
mpi->stride[1]=vf->dmpi->stride[1];
|
||||
mpi->stride[2]=vf->dmpi->stride[2];
|
||||
}
|
||||
mpi->flags|=MP_IMGFLAG_DIRECT;
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
|
||||
if(mpi->flags&MP_IMGFLAG_DIRECT){
|
||||
dmpi=vf->dmpi;
|
||||
}else{
|
||||
// no DR, so get a new image! hope we'll get DR buffer:
|
||||
dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP,
|
||||
MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
|
||||
mpi->width,mpi->height);
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
}
|
||||
|
||||
vf->priv->mpeg2= mpi->qscale_type;
|
||||
if(mpi->qscale || vf->priv->qp){
|
||||
filter(vf->priv, dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, mpi->qscale, mpi->qstride, 1);
|
||||
filter(vf->priv, dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, mpi->qscale, mpi->qstride, 0);
|
||||
filter(vf->priv, dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, mpi->qscale, mpi->qstride, 0);
|
||||
}else{
|
||||
memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h, dmpi->stride[0], mpi->stride[0]);
|
||||
memcpy_pic(dmpi->planes[1], mpi->planes[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[1], mpi->stride[1]);
|
||||
memcpy_pic(dmpi->planes[2], mpi->planes[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[2], mpi->stride[2]);
|
||||
}
|
||||
|
||||
#if HAVE_MMX
|
||||
if(gCpuCaps.hasMMX) __asm__ volatile ("emms\n\t");
|
||||
#endif
|
||||
#if HAVE_MMX2
|
||||
if(gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
|
||||
#endif
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf){
|
||||
if(!vf->priv) return;
|
||||
|
||||
free(vf->priv->src);
|
||||
vf->priv->src= NULL;
|
||||
|
||||
free(vf->priv);
|
||||
vf->priv=NULL;
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
switch(fmt){
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_IF09:
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_CLPL:
|
||||
case IMGFMT_Y800:
|
||||
case IMGFMT_Y8:
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
return vf_next_query_format(vf,fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int control(struct vf_instance *vf, int request, void* data){
|
||||
return vf_next_control(vf,request,data);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->get_image=get_image;
|
||||
vf->query_format=query_format;
|
||||
vf->uninit=uninit;
|
||||
vf->control= control;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
|
||||
if (args) sscanf(args, "%d:%d", &vf->priv->qp, &vf->priv->mode);
|
||||
|
||||
if(vf->priv->qp < 0)
|
||||
vf->priv->qp = 0;
|
||||
|
||||
init_thres2();
|
||||
|
||||
switch(vf->priv->mode){
|
||||
case 0: requantize= hardthresh_c; break;
|
||||
case 1: requantize= softthresh_c; break;
|
||||
default:
|
||||
case 2: requantize= mediumthresh_c; break;
|
||||
}
|
||||
|
||||
#if HAVE_MMX
|
||||
if(gCpuCaps.hasMMX){
|
||||
dctB= dctB_mmx;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
if(gCpuCaps.hasMMX){
|
||||
switch(vf->priv->mode){
|
||||
case 0: requantize= hardthresh_mmx; break;
|
||||
case 1: requantize= softthresh_mmx; break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_pp7 = {
|
||||
"postprocess 7",
|
||||
"pp7",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
314
libavfilter/libmpcodecs/vf_pullup.c
Normal file
314
libavfilter/libmpcodecs/vf_pullup.c
Normal file
@ -0,0 +1,314 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
#include "pullup.h"
|
||||
|
||||
#undef MAX
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
|
||||
struct vf_priv_s {
|
||||
struct pullup_context *ctx;
|
||||
int init;
|
||||
int fakecount;
|
||||
char *qbuf;
|
||||
};
|
||||
|
||||
static void init_pullup(struct vf_instance *vf, mp_image_t *mpi)
|
||||
{
|
||||
struct pullup_context *c = vf->priv->ctx;
|
||||
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
c->format = PULLUP_FMT_Y;
|
||||
c->nplanes = 4;
|
||||
pullup_preinit_context(c);
|
||||
c->bpp[0] = c->bpp[1] = c->bpp[2] = 8;
|
||||
c->w[0] = mpi->w;
|
||||
c->h[0] = mpi->h;
|
||||
c->w[1] = c->w[2] = mpi->chroma_width;
|
||||
c->h[1] = c->h[2] = mpi->chroma_height;
|
||||
c->w[3] = ((mpi->w+15)/16) * ((mpi->h+15)/16);
|
||||
c->h[3] = 2;
|
||||
c->stride[0] = mpi->width;
|
||||
c->stride[1] = c->stride[2] = mpi->chroma_width;
|
||||
c->stride[3] = c->w[3];
|
||||
c->background[1] = c->background[2] = 128;
|
||||
}
|
||||
|
||||
if (gCpuCaps.hasMMX) c->cpu |= PULLUP_CPU_MMX;
|
||||
if (gCpuCaps.hasMMX2) c->cpu |= PULLUP_CPU_MMX2;
|
||||
if (gCpuCaps.has3DNow) c->cpu |= PULLUP_CPU_3DNOW;
|
||||
if (gCpuCaps.has3DNowExt) c->cpu |= PULLUP_CPU_3DNOWEXT;
|
||||
if (gCpuCaps.hasSSE) c->cpu |= PULLUP_CPU_SSE;
|
||||
if (gCpuCaps.hasSSE2) c->cpu |= PULLUP_CPU_SSE2;
|
||||
|
||||
pullup_init_context(c);
|
||||
|
||||
vf->priv->init = 1;
|
||||
vf->priv->qbuf = malloc(c->w[3]);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static void get_image(struct vf_instance *vf, mp_image_t *mpi)
|
||||
{
|
||||
struct pullup_context *c = vf->priv->ctx;
|
||||
struct pullup_buffer *b;
|
||||
|
||||
if (mpi->type == MP_IMGTYPE_STATIC) return;
|
||||
|
||||
if (!vf->priv->init) init_pullup(vf, mpi);
|
||||
|
||||
b = pullup_get_buffer(c, 2);
|
||||
if (!b) return; /* shouldn't happen... */
|
||||
|
||||
mpi->priv = b;
|
||||
|
||||
mpi->planes[0] = b->planes[0];
|
||||
mpi->planes[1] = b->planes[1];
|
||||
mpi->planes[2] = b->planes[2];
|
||||
mpi->stride[0] = c->stride[0];
|
||||
mpi->stride[1] = c->stride[1];
|
||||
mpi->stride[2] = c->stride[2];
|
||||
|
||||
mpi->flags |= MP_IMGFLAG_DIRECT;
|
||||
mpi->flags &= ~MP_IMGFLAG_DRAW_CALLBACK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
struct pullup_context *c = vf->priv->ctx;
|
||||
struct pullup_buffer *b;
|
||||
struct pullup_frame *f;
|
||||
mp_image_t *dmpi;
|
||||
int ret;
|
||||
int p;
|
||||
int i;
|
||||
|
||||
if (!vf->priv->init) init_pullup(vf, mpi);
|
||||
|
||||
if (mpi->flags & MP_IMGFLAG_DIRECT) {
|
||||
b = mpi->priv;
|
||||
mpi->priv = 0;
|
||||
} else {
|
||||
b = pullup_get_buffer(c, 2);
|
||||
if (!b) {
|
||||
mp_msg(MSGT_VFILTER,MSGL_ERR,"Could not get buffer from pullup!\n");
|
||||
f = pullup_get_frame(c);
|
||||
pullup_release_frame(f);
|
||||
return 0;
|
||||
}
|
||||
memcpy_pic(b->planes[0], mpi->planes[0], mpi->w, mpi->h,
|
||||
c->stride[0], mpi->stride[0]);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
memcpy_pic(b->planes[1], mpi->planes[1],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
c->stride[1], mpi->stride[1]);
|
||||
memcpy_pic(b->planes[2], mpi->planes[2],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
c->stride[2], mpi->stride[2]);
|
||||
}
|
||||
}
|
||||
if (mpi->qscale) {
|
||||
fast_memcpy(b->planes[3], mpi->qscale, c->w[3]);
|
||||
fast_memcpy(b->planes[3]+c->w[3], mpi->qscale, c->w[3]);
|
||||
}
|
||||
|
||||
p = mpi->fields & MP_IMGFIELD_TOP_FIRST ? 0 :
|
||||
(mpi->fields & MP_IMGFIELD_ORDERED ? 1 : 0);
|
||||
pullup_submit_field(c, b, p);
|
||||
pullup_submit_field(c, b, p^1);
|
||||
if (mpi->fields & MP_IMGFIELD_REPEAT_FIRST)
|
||||
pullup_submit_field(c, b, p);
|
||||
|
||||
pullup_release_buffer(b, 2);
|
||||
|
||||
f = pullup_get_frame(c);
|
||||
|
||||
/* Fake yes for first few frames (buffer depth) to keep from
|
||||
* breaking A/V sync with G1's bad architecture... */
|
||||
if (!f) return vf->priv->fakecount ? (--vf->priv->fakecount,1) : 0;
|
||||
|
||||
if (f->length < 2) {
|
||||
pullup_release_frame(f);
|
||||
f = pullup_get_frame(c);
|
||||
if (!f) return 0;
|
||||
if (f->length < 2) {
|
||||
pullup_release_frame(f);
|
||||
if (!(mpi->fields & MP_IMGFIELD_REPEAT_FIRST))
|
||||
return 0;
|
||||
f = pullup_get_frame(c);
|
||||
if (!f) return 0;
|
||||
if (f->length < 2) {
|
||||
pullup_release_frame(f);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Average qscale tables from both frames. */
|
||||
if (mpi->qscale) {
|
||||
for (i=0; i<c->w[3]; i++) {
|
||||
vf->priv->qbuf[i] = (f->ofields[0]->planes[3][i]
|
||||
+ f->ofields[1]->planes[3][i+c->w[3]])>>1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* Take worst of qscale tables from both frames. */
|
||||
if (mpi->qscale) {
|
||||
for (i=0; i<c->w[3]; i++) {
|
||||
vf->priv->qbuf[i] = MAX(f->ofields[0]->planes[3][i], f->ofields[1]->planes[3][i+c->w[3]]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If the frame isn't already exportable... */
|
||||
while (!f->buffer) {
|
||||
dmpi = vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->width, mpi->height);
|
||||
/* FIXME: Is it ok to discard dmpi if it's not direct? */
|
||||
if (!(dmpi->flags & MP_IMGFLAG_DIRECT)) {
|
||||
pullup_pack_frame(c, f);
|
||||
break;
|
||||
}
|
||||
/* Direct render fields into output buffer */
|
||||
my_memcpy_pic(dmpi->planes[0], f->ofields[0]->planes[0],
|
||||
mpi->w, mpi->h/2, dmpi->stride[0]*2, c->stride[0]*2);
|
||||
my_memcpy_pic(dmpi->planes[0] + dmpi->stride[0],
|
||||
f->ofields[1]->planes[0] + c->stride[0],
|
||||
mpi->w, mpi->h/2, dmpi->stride[0]*2, c->stride[0]*2);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
my_memcpy_pic(dmpi->planes[1], f->ofields[0]->planes[1],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[1]*2, c->stride[1]*2);
|
||||
my_memcpy_pic(dmpi->planes[1] + dmpi->stride[1],
|
||||
f->ofields[1]->planes[1] + c->stride[1],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[1]*2, c->stride[1]*2);
|
||||
my_memcpy_pic(dmpi->planes[2], f->ofields[0]->planes[2],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[2]*2, c->stride[2]*2);
|
||||
my_memcpy_pic(dmpi->planes[2] + dmpi->stride[2],
|
||||
f->ofields[1]->planes[2] + c->stride[2],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[2]*2, c->stride[2]*2);
|
||||
}
|
||||
pullup_release_frame(f);
|
||||
if (mpi->qscale) {
|
||||
dmpi->qscale = vf->priv->qbuf;
|
||||
dmpi->qstride = mpi->qstride;
|
||||
dmpi->qscale_type = mpi->qscale_type;
|
||||
}
|
||||
return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
|
||||
}
|
||||
dmpi = vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->width, mpi->height);
|
||||
|
||||
dmpi->planes[0] = f->buffer->planes[0];
|
||||
dmpi->planes[1] = f->buffer->planes[1];
|
||||
dmpi->planes[2] = f->buffer->planes[2];
|
||||
|
||||
dmpi->stride[0] = c->stride[0];
|
||||
dmpi->stride[1] = c->stride[1];
|
||||
dmpi->stride[2] = c->stride[2];
|
||||
|
||||
if (mpi->qscale) {
|
||||
dmpi->qscale = vf->priv->qbuf;
|
||||
dmpi->qstride = mpi->qstride;
|
||||
dmpi->qscale_type = mpi->qscale_type;
|
||||
}
|
||||
ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
|
||||
pullup_release_frame(f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt)
|
||||
{
|
||||
/* FIXME - support more formats */
|
||||
switch (fmt) {
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_I420:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt)
|
||||
{
|
||||
if (height&3) return 0;
|
||||
return vf_next_config(vf, width, height, d_width, d_height, flags, outfmt);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
pullup_free_context(vf->priv->ctx);
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
struct vf_priv_s *p;
|
||||
struct pullup_context *c;
|
||||
//vf->get_image = get_image;
|
||||
vf->put_image = put_image;
|
||||
vf->config = config;
|
||||
vf->query_format = query_format;
|
||||
vf->uninit = uninit;
|
||||
vf->default_reqs = VFCAP_ACCEPT_STRIDE;
|
||||
vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
|
||||
p->ctx = c = pullup_alloc_context();
|
||||
p->fakecount = 1;
|
||||
c->verbose = verbose>0;
|
||||
c->junk_left = c->junk_right = 1;
|
||||
c->junk_top = c->junk_bottom = 4;
|
||||
c->strict_breaks = 0;
|
||||
c->metric_plane = 0;
|
||||
if (args) {
|
||||
sscanf(args, "%d:%d:%d:%d:%d:%d", &c->junk_left, &c->junk_right, &c->junk_top, &c->junk_bottom, &c->strict_breaks, &c->metric_plane);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_pullup = {
|
||||
"pullup (from field sequence to frames)",
|
||||
"pullup",
|
||||
"Rich Felker",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
177
libavfilter/libmpcodecs/vf_qp.c
Normal file
177
libavfilter/libmpcodecs/vf_qp.c
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavutil/eval.h"
|
||||
|
||||
|
||||
struct vf_priv_s {
|
||||
char eq[200];
|
||||
int8_t *qp;
|
||||
int8_t lut[257];
|
||||
int qp_stride;
|
||||
};
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
int h= (height+15)>>4;
|
||||
int i;
|
||||
|
||||
vf->priv->qp_stride= (width+15)>>4;
|
||||
vf->priv->qp= av_malloc(vf->priv->qp_stride*h*sizeof(int8_t));
|
||||
|
||||
for(i=-129; i<128; i++){
|
||||
double const_values[]={
|
||||
M_PI,
|
||||
M_E,
|
||||
i != -129,
|
||||
i,
|
||||
0
|
||||
};
|
||||
static const char *const_names[]={
|
||||
"PI",
|
||||
"E",
|
||||
"known",
|
||||
"qp",
|
||||
NULL
|
||||
};
|
||||
double temp_val;
|
||||
int res;
|
||||
|
||||
res= av_parse_and_eval_expr(&temp_val, vf->priv->eq, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL);
|
||||
|
||||
if (res < 0){
|
||||
mp_msg(MSGT_VFILTER, MSGL_ERR, "qp: Error evaluating \"%s\" \n", vf->priv->eq);
|
||||
return 0;
|
||||
}
|
||||
vf->priv->lut[i+129]= lrintf(temp_val);
|
||||
}
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static void get_image(struct vf_instance *vf, mp_image_t *mpi){
|
||||
if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
|
||||
// ok, we can do pp in-place (or pp disabled):
|
||||
vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
mpi->type, mpi->flags, mpi->w, mpi->h);
|
||||
mpi->planes[0]=vf->dmpi->planes[0];
|
||||
mpi->stride[0]=vf->dmpi->stride[0];
|
||||
mpi->width=vf->dmpi->width;
|
||||
if(mpi->flags&MP_IMGFLAG_PLANAR){
|
||||
mpi->planes[1]=vf->dmpi->planes[1];
|
||||
mpi->planes[2]=vf->dmpi->planes[2];
|
||||
mpi->stride[1]=vf->dmpi->stride[1];
|
||||
mpi->stride[2]=vf->dmpi->stride[2];
|
||||
}
|
||||
mpi->flags|=MP_IMGFLAG_DIRECT;
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
int x,y;
|
||||
|
||||
if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
|
||||
// no DR, so get a new image! hope we'll get DR buffer:
|
||||
vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
|
||||
mpi->w,mpi->h);
|
||||
}
|
||||
|
||||
dmpi= vf->dmpi;
|
||||
|
||||
if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
|
||||
memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h, dmpi->stride[0], mpi->stride[0]);
|
||||
if(mpi->flags&MP_IMGFLAG_PLANAR){
|
||||
memcpy_pic(dmpi->planes[1], mpi->planes[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[1], mpi->stride[1]);
|
||||
memcpy_pic(dmpi->planes[2], mpi->planes[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[2], mpi->stride[2]);
|
||||
}
|
||||
}
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
|
||||
dmpi->qscale = vf->priv->qp;
|
||||
dmpi->qstride= vf->priv->qp_stride;
|
||||
if(mpi->qscale){
|
||||
for(y=0; y<((dmpi->h+15)>>4); y++){
|
||||
for(x=0; x<vf->priv->qp_stride; x++){
|
||||
dmpi->qscale[x + dmpi->qstride*y]=
|
||||
vf->priv->lut[ 129 + ((int8_t)mpi->qscale[x + mpi->qstride*y]) ];
|
||||
}
|
||||
}
|
||||
}else{
|
||||
int qp= vf->priv->lut[0];
|
||||
for(y=0; y<((dmpi->h+15)>>4); y++){
|
||||
for(x=0; x<vf->priv->qp_stride; x++){
|
||||
dmpi->qscale[x + dmpi->qstride*y]= qp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf){
|
||||
if(!vf->priv) return;
|
||||
|
||||
av_free(vf->priv->qp);
|
||||
vf->priv->qp= NULL;
|
||||
|
||||
av_free(vf->priv);
|
||||
vf->priv=NULL;
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->get_image=get_image;
|
||||
vf->uninit=uninit;
|
||||
vf->priv=av_malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
|
||||
// avcodec_init();
|
||||
|
||||
if (args) strncpy(vf->priv->eq, args, 199);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_qp = {
|
||||
"QP changer",
|
||||
"qp",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
181
libavfilter/libmpcodecs/vf_rectangle.c
Normal file
181
libavfilter/libmpcodecs/vf_rectangle.c
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "mp_image.h"
|
||||
#include "mp_msg.h"
|
||||
#include "vf.h"
|
||||
|
||||
#include "libvo/fastmemcpy.h"
|
||||
#include "libavutil/common.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
int x, y, w, h;
|
||||
};
|
||||
|
||||
static int
|
||||
config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt)
|
||||
{
|
||||
if (vf->priv->w < 0 || width < vf->priv->w)
|
||||
vf->priv->w = width;
|
||||
if (vf->priv->h < 0 || height < vf->priv->h)
|
||||
vf->priv->h = height;
|
||||
if (vf->priv->x < 0)
|
||||
vf->priv->x = (width - vf->priv->w) / 2;
|
||||
if (vf->priv->y < 0)
|
||||
vf->priv->y = (height - vf->priv->h) / 2;
|
||||
if (vf->priv->w + vf->priv->x > width
|
||||
|| vf->priv->h + vf->priv->y > height) {
|
||||
mp_msg(MSGT_VFILTER,MSGL_WARN,"rectangle: bad position/width/height - rectangle area is out of the original!\n");
|
||||
return 0;
|
||||
}
|
||||
return vf_next_config(vf, width, height, d_width, d_height, flags, outfmt);
|
||||
}
|
||||
|
||||
static int
|
||||
control(struct vf_instance *vf, int request, void *data)
|
||||
{
|
||||
const int *const tmp = data;
|
||||
switch(request){
|
||||
case VFCTRL_CHANGE_RECTANGLE:
|
||||
switch (tmp[0]){
|
||||
case 0:
|
||||
vf->priv->w += tmp[1];
|
||||
return 1;
|
||||
break;
|
||||
case 1:
|
||||
vf->priv->h += tmp[1];
|
||||
return 1;
|
||||
break;
|
||||
case 2:
|
||||
vf->priv->x += tmp[1];
|
||||
return 1;
|
||||
break;
|
||||
case 3:
|
||||
vf->priv->y += tmp[1];
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
mp_msg(MSGT_VFILTER,MSGL_FATAL,"Unknown param %d \n", tmp[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return vf_next_control(vf, request, data);
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
put_image(struct vf_instance *vf, mp_image_t* mpi, double pts){
|
||||
mp_image_t* dmpi;
|
||||
unsigned int bpp = mpi->bpp / 8;
|
||||
int x, y, w, h;
|
||||
dmpi = vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_TEMP,
|
||||
MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
|
||||
mpi->w, mpi->h);
|
||||
|
||||
memcpy_pic(dmpi->planes[0],mpi->planes[0],mpi->w*bpp, mpi->h,
|
||||
dmpi->stride[0],mpi->stride[0]);
|
||||
if(mpi->flags&MP_IMGFLAG_PLANAR && mpi->flags&MP_IMGFLAG_YUV){
|
||||
memcpy_pic(dmpi->planes[1],mpi->planes[1],
|
||||
mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift,
|
||||
dmpi->stride[1],mpi->stride[1]);
|
||||
memcpy_pic(dmpi->planes[2],mpi->planes[2],
|
||||
mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift,
|
||||
dmpi->stride[2],mpi->stride[2]);
|
||||
}
|
||||
|
||||
/* Draw the rectangle */
|
||||
|
||||
mp_msg(MSGT_VFILTER,MSGL_INFO, "rectangle: -vf rectangle=%d:%d:%d:%d \n", vf->priv->w, vf->priv->h, vf->priv->x, vf->priv->y);
|
||||
|
||||
x = FFMIN(vf->priv->x, dmpi->width);
|
||||
x = FFMAX(x, 0);
|
||||
|
||||
w = vf->priv->x + vf->priv->w - 1 - x;
|
||||
w = FFMIN(w, dmpi->width - x);
|
||||
w = FFMAX(w, 0);
|
||||
|
||||
y = FFMIN(vf->priv->y, dmpi->height);
|
||||
y = FFMAX(y, 0);
|
||||
|
||||
h = vf->priv->y + vf->priv->h - 1 - y;
|
||||
h = FFMIN(h, dmpi->height - y);
|
||||
h = FFMAX(h, 0);
|
||||
|
||||
if (0 <= vf->priv->y && vf->priv->y <= dmpi->height) {
|
||||
unsigned char *p = dmpi->planes[0] + y * dmpi->stride[0] + x * bpp;
|
||||
unsigned int count = w * bpp;
|
||||
while (count--)
|
||||
p[count] = 0xff - p[count];
|
||||
}
|
||||
if (h != 1 && vf->priv->y + vf->priv->h - 1 <= mpi->height) {
|
||||
unsigned char *p = dmpi->planes[0] + (vf->priv->y + vf->priv->h - 1) * dmpi->stride[0] + x * bpp;
|
||||
unsigned int count = w * bpp;
|
||||
while (count--)
|
||||
p[count] = 0xff - p[count];
|
||||
}
|
||||
if (0 <= vf->priv->x && vf->priv->x <= dmpi->width) {
|
||||
unsigned char *p = dmpi->planes[0] + y * dmpi->stride[0] + x * bpp;
|
||||
unsigned int count = h;
|
||||
while (count--) {
|
||||
unsigned int i = bpp;
|
||||
while (i--)
|
||||
p[i] = 0xff - p[i];
|
||||
p += dmpi->stride[0];
|
||||
}
|
||||
}
|
||||
if (w != 1 && vf->priv->x + vf->priv->w - 1 <= mpi->width) {
|
||||
unsigned char *p = dmpi->planes[0] + y * dmpi->stride[0] + (vf->priv->x + vf->priv->w - 1) * bpp;
|
||||
unsigned int count = h;
|
||||
while (count--) {
|
||||
unsigned int i = bpp;
|
||||
while (i--)
|
||||
p[i] = 0xff - p[i];
|
||||
p += dmpi->stride[0];
|
||||
}
|
||||
}
|
||||
return vf_next_put_image(vf, dmpi, pts);
|
||||
}
|
||||
|
||||
static int
|
||||
vf_open(vf_instance_t *vf, char *args) {
|
||||
vf->config = config;
|
||||
vf->control = control;
|
||||
vf->put_image = put_image;
|
||||
vf->priv = malloc(sizeof(struct vf_priv_s));
|
||||
vf->priv->x = -1;
|
||||
vf->priv->y = -1;
|
||||
vf->priv->w = -1;
|
||||
vf->priv->h = -1;
|
||||
if (args)
|
||||
sscanf(args, "%d:%d:%d:%d",
|
||||
&vf->priv->w, &vf->priv->h, &vf->priv->x, &vf->priv->y);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_rectangle = {
|
||||
"draw rectangle",
|
||||
"rectangle",
|
||||
"Kim Minh Kaplan",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
906
libavfilter/libmpcodecs/vf_remove_logo.c
Normal file
906
libavfilter/libmpcodecs/vf_remove_logo.c
Normal file
@ -0,0 +1,906 @@
|
||||
/*
|
||||
* This filter loads a .pgm mask file showing where a logo is and uses
|
||||
* a blur transform to remove the logo.
|
||||
*
|
||||
* Copyright (C) 2005 Robert Edele <yartrebo@earthlink.net>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file vf_remove_logo.c
|
||||
*
|
||||
* \brief Advanced blur-based logo removing filter.
|
||||
|
||||
* Hello and welcome. This code implements a filter to remove annoying TV
|
||||
* logos and other annoying images placed onto a video stream. It works by filling
|
||||
* in the pixels that comprise the logo with neighboring pixels. The transform is
|
||||
* very loosely based on a gaussian blur, but it is different enough to merit its
|
||||
* own paragraph later on. It is a major improvement on the old delogo filter as
|
||||
* it both uses a better blurring algorithm and uses a bitmap to use an arbitrary
|
||||
* and generally much tighter fitting shape than a rectangle.
|
||||
*
|
||||
* The filter requires 1 argument and has no optional arguments. It requires
|
||||
* a filter bitmap, which must be in PGM or PPM format. A sample invocation would
|
||||
* be -vf remove_logo=/home/username/logo_bitmaps/xyz.pgm. Pixels with a value of
|
||||
* zero are not part of the logo, and non-zero pixels are part of the logo. If you
|
||||
* use white (255) for the logo and black (0) for the rest, you will be safe. For
|
||||
* making the filter bitmap, I recommend taking a screen capture of a black frame
|
||||
* with the logo visible, and then using The GIMP's threshold filter followed by
|
||||
* the erode filter once or twice. If needed, little splotches can be fixed
|
||||
* manually. Remember that if logo pixels are not covered, the filter quality will
|
||||
* be much reduced. Marking too many pixels as part of the logo doesn't hurt as
|
||||
* much, but it will increase the amount of blurring needed to cover over the
|
||||
* image and will destroy more information than necessary. Additionally, this blur
|
||||
* algorithm is O(n) = n^4, where n is the width and height of a hypothetical
|
||||
* square logo, so extra pixels will slow things down on a large lo
|
||||
*
|
||||
* The logo removal algorithm has two key points. The first is that it
|
||||
* distinguishes between pixels in the logo and those not in the logo by using the
|
||||
* passed-in bitmap. Pixels not in the logo are copied over directly without being
|
||||
* modified and they also serve as source pixels for the logo fill-in. Pixels
|
||||
* inside the logo have the mask applied.
|
||||
*
|
||||
* At init-time the bitmap is reprocessed internally, and the distance to the
|
||||
* nearest edge of the logo (Manhattan distance), along with a little extra to
|
||||
* remove rough edges, is stored in each pixel. This is done using an in-place
|
||||
* erosion algorithm, and incrementing each pixel that survives any given erosion.
|
||||
* Once every pixel is eroded, the maximum value is recorded, and a set of masks
|
||||
* from size 0 to this size are generaged. The masks are circular binary masks,
|
||||
* where each pixel within a radius N (where N is the size of the mask) is a 1,
|
||||
* and all other pixels are a 0. Although a gaussian mask would be more
|
||||
* mathematically accurate, a binary mask works better in practice because we
|
||||
* generally do not use the central pixels in the mask (because they are in the
|
||||
* logo region), and thus a gaussian mask will cause too little blur and thus a
|
||||
* very unstable image.
|
||||
*
|
||||
* The mask is applied in a special way. Namely, only pixels in the mask that
|
||||
* line up to pixels outside the logo are used. The dynamic mask size means that
|
||||
* the mask is just big enough so that the edges touch pixels outside the logo, so
|
||||
* the blurring is kept to a minimum and at least the first boundary condition is
|
||||
* met (that the image function itself is continuous), even if the second boundary
|
||||
* condition (that the derivative of the image function is continuous) is not met.
|
||||
* A masking algorithm that does preserve the second boundary coundition
|
||||
* (perhaps something based on a highly-modified bi-cubic algorithm) should offer
|
||||
* even better results on paper, but the noise in a typical TV signal should make
|
||||
* anything based on derivatives hopelessly noisy.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
/** \brief Returns the larger of the two arguments. **/
|
||||
#define max(x,y) ((x)>(y)?(x):(y))
|
||||
/** \brief Returns the smaller of the two arguments. **/
|
||||
#define min(x,y) ((x)>(y)?(y):(x))
|
||||
|
||||
/**
|
||||
* \brief Test if a pixel is part of the logo.
|
||||
*/
|
||||
#define test_filter(image, x, y) ((unsigned char) (image->pixel[((y) * image->width) + (x)]))
|
||||
|
||||
/**
|
||||
* \brief Chooses a slightly larger mask size to improve performance.
|
||||
*
|
||||
* This function maps the absolute minimum mask size needed to the mask size we'll
|
||||
* actually use. f(x) = x (the smallest that will work) will produce the sharpest
|
||||
* results, but will be quite jittery. f(x) = 1.25x (what I'm using) is a good
|
||||
* tradeoff in my opinion. This will calculate only at init-time, so you can put a
|
||||
* long expression here without effecting performance.
|
||||
*/
|
||||
#define apply_mask_fudge_factor(x) (((x) >> 2) + x)
|
||||
|
||||
/**
|
||||
* \brief Simple implementation of the PGM image format.
|
||||
*
|
||||
* This struct holds a bare-bones image loaded from a PGM or PPM file. Once
|
||||
* loaded and pre-processed, each pixel in this struct will contain how far from
|
||||
* the edge of the logo each pixel is, using the manhattan distance (|dx| + |dy|).
|
||||
*
|
||||
* pixels in char * pixel can be addressed using (y * width) + height.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
|
||||
unsigned char * pixel;
|
||||
|
||||
} pgm_structure;
|
||||
|
||||
/**
|
||||
* \brief Stores persistant variables.
|
||||
*
|
||||
* Variables stored here are kept from frame to frame, and separate instances of
|
||||
* the filter will get their own separate copies.
|
||||
*/
|
||||
struct vf_priv_s
|
||||
{
|
||||
unsigned int fmt; /* Not exactly sure of the use for this. It came with the example filter I used as a basis for this, and it looks like a lot of stuff will break if I remove it. */
|
||||
int max_mask_size; /* The largest possible mask size that will be needed with the given filter and corresponding half_size_filter. The half_size_filter can have a larger requirment in some rare (but not degenerate) cases. */
|
||||
int * * * mask; /* Stores our collection of masks. The first * is for an array of masks, the second for the y axis, and the third for the x axis. */
|
||||
pgm_structure * filter; /* Stores the full-size filter image. This is used to tell what pixels are in the logo or not in the luma plane. */
|
||||
pgm_structure * half_size_filter; /* Stores a 50% width and 50% height filter image. This is used to tell what pixels are in the logo or not in the chroma planes. */
|
||||
/* These 8 variables store the bounding rectangles that the logo resides in. */
|
||||
int bounding_rectangle_posx1;
|
||||
int bounding_rectangle_posy1;
|
||||
int bounding_rectangle_posx2;
|
||||
int bounding_rectangle_posy2;
|
||||
int bounding_rectangle_half_size_posx1;
|
||||
int bounding_rectangle_half_size_posy1;
|
||||
int bounding_rectangle_half_size_posx2;
|
||||
int bounding_rectangle_half_size_posy2;
|
||||
} vf_priv_s;
|
||||
|
||||
/**
|
||||
* \brief Mallocs memory and checks to make sure it succeeded.
|
||||
*
|
||||
* \param size How many bytes to allocate.
|
||||
*
|
||||
* \return A pointer to the freshly allocated memory block, or NULL on failutre.
|
||||
*
|
||||
* Mallocs memory, and checks to make sure it was successfully allocated. Because
|
||||
* of how MPlayer works, it cannot safely halt execution, but at least the user
|
||||
* will get an error message before the segfault happens.
|
||||
*/
|
||||
static void * safe_malloc(int size)
|
||||
{
|
||||
void * answer = malloc(size);
|
||||
if (answer == NULL)
|
||||
mp_msg(MSGT_VFILTER, MSGL_ERR, "Unable to allocate memory in vf_remove_logo.c\n");
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Calculates the smallest rectangle that will encompass the logo region.
|
||||
*
|
||||
* \param filter This image contains the logo around which the rectangle will
|
||||
* will be fitted.
|
||||
*
|
||||
* The bounding rectangle is calculated by testing successive lines (from the four
|
||||
* sides of the rectangle) until no more can be removed without removing logo
|
||||
* pixels. The results are returned by reference to posx1, posy1, posx2, and
|
||||
* posy2.
|
||||
*/
|
||||
static void calculate_bounding_rectangle(int * posx1, int * posy1, int * posx2, int * posy2, pgm_structure * filter)
|
||||
{
|
||||
int x; /* Temporary variables to run */
|
||||
int y; /* through each row or column. */
|
||||
int start_x;
|
||||
int start_y;
|
||||
int end_x = filter->width - 1;
|
||||
int end_y = filter->height - 1;
|
||||
int did_we_find_a_logo_pixel = 0;
|
||||
|
||||
/* Let's find the top bound first. */
|
||||
for (start_x = 0; start_x < filter->width && !did_we_find_a_logo_pixel; start_x++)
|
||||
{
|
||||
for (y = 0; y < filter->height; y++)
|
||||
{
|
||||
did_we_find_a_logo_pixel |= test_filter(filter, start_x, y);
|
||||
}
|
||||
}
|
||||
start_x--;
|
||||
|
||||
/* Now the bottom bound. */
|
||||
did_we_find_a_logo_pixel = 0;
|
||||
for (end_x = filter->width - 1; end_x > start_x && !did_we_find_a_logo_pixel; end_x--)
|
||||
{
|
||||
for (y = 0; y < filter->height; y++)
|
||||
{
|
||||
did_we_find_a_logo_pixel |= test_filter(filter, end_x, y);
|
||||
}
|
||||
}
|
||||
end_x++;
|
||||
|
||||
/* Left bound. */
|
||||
did_we_find_a_logo_pixel = 0;
|
||||
for (start_y = 0; start_y < filter->height && !did_we_find_a_logo_pixel; start_y++)
|
||||
{
|
||||
for (x = 0; x < filter->width; x++)
|
||||
{
|
||||
did_we_find_a_logo_pixel |= test_filter(filter, x, start_y);
|
||||
}
|
||||
}
|
||||
start_y--;
|
||||
|
||||
/* Right bound. */
|
||||
did_we_find_a_logo_pixel = 0;
|
||||
for (end_y = filter->height - 1; end_y > start_y && !did_we_find_a_logo_pixel; end_y--)
|
||||
{
|
||||
for (x = 0; x < filter->width; x++)
|
||||
{
|
||||
did_we_find_a_logo_pixel |= test_filter(filter, x, end_y);
|
||||
}
|
||||
}
|
||||
end_y++;
|
||||
|
||||
*posx1 = start_x;
|
||||
*posy1 = start_y;
|
||||
*posx2 = end_x;
|
||||
*posy2 = end_y;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Free mask memory.
|
||||
*
|
||||
* \param vf Data structure which stores our persistant data, and is to be freed.
|
||||
*
|
||||
* We call this function when our filter is done. It will free the memory
|
||||
* allocated to the masks and leave the variables in a safe state.
|
||||
*/
|
||||
static void destroy_masks(vf_instance_t * vf)
|
||||
{
|
||||
int a, b;
|
||||
|
||||
/* Load values from the vf->priv struct for faster dereferencing. */
|
||||
int * * * mask = vf->priv->mask;
|
||||
int max_mask_size = vf->priv->max_mask_size;
|
||||
|
||||
if (mask == NULL)
|
||||
return; /* Nothing allocated, so return before we segfault. */
|
||||
|
||||
/* Free all allocated memory. */
|
||||
for (a = 0; a <= max_mask_size; a++) /* Loop through each mask. */
|
||||
{
|
||||
for (b = -a; b <= a; b++) /* Loop through each scanline in a mask. */
|
||||
{
|
||||
free(mask[a][b + a]); /* Free a scanline. */
|
||||
}
|
||||
free(mask[a]); /* Free a mask. */
|
||||
}
|
||||
free(mask); /* Free the array of pointers pointing to the masks. */
|
||||
|
||||
/* Set the pointer to NULL, so that any duplicate calls to this function will not cause a crash. */
|
||||
vf->priv->mask = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set up our array of masks.
|
||||
*
|
||||
* \param vf Where our filter stores persistance data, like these masks.
|
||||
*
|
||||
* This creates an array of progressively larger masks and calculates their
|
||||
* values. The values will not change during program execution once this function
|
||||
* is done.
|
||||
*/
|
||||
static void initialize_masks(vf_instance_t * vf)
|
||||
{
|
||||
int a, b, c;
|
||||
|
||||
/* Load values from the vf->priv struct for faster dereferencing. */
|
||||
int * * * mask = vf->priv->mask;
|
||||
int max_mask_size = vf->priv->max_mask_size; /* This tells us how many masks we'll need to generate. */
|
||||
|
||||
/* Create a circular mask for each size up to max_mask_size. When the filter is applied, the mask size is
|
||||
determined on a pixel by pixel basis, with pixels nearer the edge of the logo getting smaller mask sizes. */
|
||||
mask = (int * * *) safe_malloc(sizeof(int * *) * (max_mask_size + 1));
|
||||
for (a = 0; a <= max_mask_size; a++)
|
||||
{
|
||||
mask[a] = (int * *) safe_malloc(sizeof(int *) * ((a * 2) + 1));
|
||||
for (b = -a; b <= a; b++)
|
||||
{
|
||||
mask[a][b + a] = (int *) safe_malloc(sizeof(int) * ((a * 2) + 1));
|
||||
for (c = -a; c <= a; c++)
|
||||
{
|
||||
if ((b * b) + (c * c) <= (a * a)) /* Circular 0/1 mask. */
|
||||
mask[a][b + a][c + a] = 1;
|
||||
else
|
||||
mask[a][b + a][c + a] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Store values back to vf->priv so they aren't lost after the function returns. */
|
||||
vf->priv->mask = mask;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Pre-processes an image to give distance information.
|
||||
*
|
||||
* \param vf Data structure that holds persistant information. All it is used for
|
||||
in this function is to store the calculated max_mask_size variable.
|
||||
* \param mask This image will be converted from a greyscale image into a
|
||||
* distance image.
|
||||
*
|
||||
* This function takes a greyscale image (pgm_structure * mask) and converts it
|
||||
* in place into a distance image. A distance image is zero for pixels ourside of
|
||||
* the logo and is the manhattan distance (|dx| + |dy|) for pixels inside of the
|
||||
* logo. This will overestimate the distance, but that is safe, and is far easier
|
||||
* to implement than a proper pythagorean distance since I'm using a modified
|
||||
* erosion algorithm to compute the distances.
|
||||
*/
|
||||
static void convert_mask_to_strength_mask(vf_instance_t * vf, pgm_structure * mask)
|
||||
{
|
||||
int x, y; /* Used by our for loops to go through every single pixel in the picture one at a time. */
|
||||
int has_anything_changed = 1; /* Used by the main while() loop to know if anything changed on the last erosion. */
|
||||
int current_pass = 0; /* How many times we've gone through the loop. Used in the in-place erosion algorithm
|
||||
and to get us max_mask_size later on. */
|
||||
int max_mask_size; /* This will record how large a mask the pixel that is the furthest from the edge of the logo
|
||||
(and thus the neediest) is. */
|
||||
char * current_pixel = mask->pixel; /* This stores the actual pixel data. */
|
||||
|
||||
/* First pass, set all non-zero values to 1. After this loop finishes, the data should be considered numeric
|
||||
data for the filter, not color data. */
|
||||
for (x = 0; x < mask->height * mask->width; x++, current_pixel++)
|
||||
if(*current_pixel) *current_pixel = 1;
|
||||
|
||||
/* Second pass and future passes. For each pass, if a pixel is itself the same value as the current pass,
|
||||
and its four neighbors are too, then it is incremented. If no pixels are incremented by the end of the pass,
|
||||
then we go again. Edge pixels are counted as always excluded (this should be true anyway for any sane mask,
|
||||
but if it isn't this will ensure that we eventually exit). */
|
||||
while (has_anything_changed)
|
||||
{
|
||||
current_pass++;
|
||||
current_pixel = mask->pixel;
|
||||
|
||||
has_anything_changed = 0; /* If this doesn't get set by the end of this pass, then we're done. */
|
||||
|
||||
for (y = 1; y < mask->height - 1; y++)
|
||||
{
|
||||
for (x = 1; x < mask->width - 1; x++)
|
||||
{
|
||||
/* Apply the in-place erosion transform. It is based on the following two premises: 1 - Any pixel that fails 1 erosion
|
||||
will fail all future erosions. 2 - Only pixels having survived all erosions up to the present will be >= to
|
||||
current_pass. It doesn't matter if it survived the current pass, failed it, or hasn't been tested yet. */
|
||||
if (*current_pixel >= current_pass && /* By using >= instead of ==, we allow the algorithm to work in place. */
|
||||
*(current_pixel + 1) >= current_pass &&
|
||||
*(current_pixel - 1) >= current_pass &&
|
||||
*(current_pixel + mask->width) >= current_pass &&
|
||||
*(current_pixel - mask->width) >= current_pass)
|
||||
{
|
||||
(*current_pixel)++; /* Increment the value since it still has not been eroded, as evidenced by the if statement
|
||||
that just evaluated to true. */
|
||||
has_anything_changed = 1;
|
||||
}
|
||||
current_pixel++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply the fudge factor, which will increase the size of the mask a little to reduce jitter at the cost of more blur. */
|
||||
for (y = 1; y < mask->height - 1; y++)
|
||||
{
|
||||
for (x = 1; x < mask->width - 1; x++)
|
||||
{
|
||||
mask->pixel[(y * mask->width) + x] = apply_mask_fudge_factor(mask->pixel[(y * mask->width) + x]);
|
||||
}
|
||||
}
|
||||
|
||||
max_mask_size = current_pass + 1; /* As a side-effect, we now know the maximum mask size, which we'll use to generate our masks. */
|
||||
max_mask_size = apply_mask_fudge_factor(max_mask_size); /* Apply the fudge factor to this number too, since we must
|
||||
ensure that enough masks are generated. */
|
||||
vf->priv->max_mask_size = max_mask_size; /* Commit the newly calculated max_mask_size to the vf->priv struct. */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Our blurring function.
|
||||
*
|
||||
* \param vf Stores persistant data. In this function we are interested in the
|
||||
* array of masks.
|
||||
* \param value_out The properly blurred and delogoed pixel is outputted here.
|
||||
* \param logo_mask Tells us which pixels are in the logo and which aren't.
|
||||
* \param image The image that is having its logo removed.
|
||||
* \param x x-coordinate of the pixel to blur.
|
||||
* \param y y-coordinate of the pixel to blur.
|
||||
* \param plane 0 = luma, 1 = blue chroma, 2 = red chroma (YUV).
|
||||
*
|
||||
* This function is the core of the filter. It takes a pixel that is inside the
|
||||
* logo and blurs it. It does so by finding the average of all the pixels within
|
||||
* the mask and outside of the logo.
|
||||
*/
|
||||
static void get_blur(const vf_instance_t * const vf, unsigned int * const value_out, const pgm_structure * const logo_mask,
|
||||
const mp_image_t * const image, const int x, const int y, const int plane)
|
||||
{
|
||||
int mask_size; /* Mask size tells how large a circle to use. The radius is about (slightly larger than) mask size. */
|
||||
/* Get values from vf->priv for faster dereferencing. */
|
||||
int * * * mask = vf->priv->mask;
|
||||
|
||||
int start_posx, start_posy, end_posx, end_posy;
|
||||
int i, j;
|
||||
unsigned int accumulator = 0, divisor = 0;
|
||||
const unsigned char * mask_read_position; /* What pixel we are reading out of the circular blur mask. */
|
||||
const unsigned char * logo_mask_read_position; /* What pixel we are reading out of the filter image. */
|
||||
|
||||
/* Prepare our bounding rectangle and clip it if need be. */
|
||||
mask_size = test_filter(logo_mask, x, y);
|
||||
start_posx = max(0, x - mask_size);
|
||||
start_posy = max(0, y - mask_size);
|
||||
end_posx = min(image->width - 1, x + mask_size);
|
||||
end_posy = min(image->height - 1, y + mask_size);
|
||||
|
||||
mask_read_position = image->planes[plane] + (image->stride[plane] * start_posy) + start_posx;
|
||||
logo_mask_read_position = logo_mask->pixel + (start_posy * logo_mask->width) + start_posx;
|
||||
|
||||
for (j = start_posy; j <= end_posy; j++)
|
||||
{
|
||||
for (i = start_posx; i <= end_posx; i++)
|
||||
{
|
||||
if (!(*logo_mask_read_position) && mask[mask_size][i - start_posx][j - start_posy])
|
||||
{ /* Check to see if this pixel is in the logo or not. Only use the pixel if it is not. */
|
||||
accumulator += *mask_read_position;
|
||||
divisor++;
|
||||
}
|
||||
|
||||
mask_read_position++;
|
||||
logo_mask_read_position++;
|
||||
}
|
||||
|
||||
mask_read_position += (image->stride[plane] - ((end_posx + 1) - start_posx));
|
||||
logo_mask_read_position += (logo_mask->width - ((end_posx + 1) - start_posx));
|
||||
}
|
||||
|
||||
if (divisor == 0) /* This means that not a single pixel is outside of the logo, so we have no data. */
|
||||
{ /* We should put some eye catching value here, to indicate the flaw to the user. */
|
||||
*value_out = 255;
|
||||
}
|
||||
else /* Else we need to normalise the data using the divisor. */
|
||||
{
|
||||
*value_out = (accumulator + (divisor / 2)) / divisor; /* Divide, taking into account average rounding error. */
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Free a pgm_structure. Undoes load_pgm(...).
|
||||
*/
|
||||
static void destroy_pgm(pgm_structure * to_be_destroyed)
|
||||
{
|
||||
if (to_be_destroyed == NULL)
|
||||
return; /* Don't do anything if a NULL pointer was passed it. */
|
||||
|
||||
/* Internally allocated memory. */
|
||||
if (to_be_destroyed->pixel != NULL)
|
||||
{
|
||||
free(to_be_destroyed->pixel);
|
||||
to_be_destroyed->pixel = NULL;
|
||||
}
|
||||
|
||||
/* Free the actual struct instance. This is done here and not by the calling function. */
|
||||
free(to_be_destroyed);
|
||||
}
|
||||
|
||||
/** \brief Helper function for load_pgm(...) to skip whitespace. */
|
||||
static void load_pgm_skip(FILE *f) {
|
||||
int c, comment = 0;
|
||||
do {
|
||||
c = fgetc(f);
|
||||
if (c == '#')
|
||||
comment = 1;
|
||||
if (c == '\n')
|
||||
comment = 0;
|
||||
} while (c != EOF && (isspace(c) || comment));
|
||||
ungetc(c, f);
|
||||
}
|
||||
|
||||
#define REMOVE_LOGO_LOAD_PGM_ERROR_MESSAGE(message) {mp_msg(MSGT_VFILTER, MSGL_ERR, message); return NULL;}
|
||||
|
||||
/**
|
||||
* \brief Loads a raw pgm or ppm file into a newly created pgm_structure object.
|
||||
*
|
||||
* \param file_name The name of the file to be loaded. So long as the file is a
|
||||
* valid pgm or ppm file, it will load correctly, even if the
|
||||
* extension is missing or invalid.
|
||||
*
|
||||
* \return A pointer to the newly created pgm_structure object. Don't forget to
|
||||
* call destroy_pgm(...) when you're done with this. If an error occurs,
|
||||
* NULL is returned.
|
||||
*
|
||||
* Can load either raw pgm (P5) or raw ppm (P6) image files as a binary image.
|
||||
* While a pgm file will be loaded normally (greyscale), the only thing that is
|
||||
* guaranteed with ppm is that all zero (R = 0, G = 0, B = 0) pixels will remain
|
||||
* zero, and non-zero pixels will remain non-zero.
|
||||
*/
|
||||
static pgm_structure * load_pgm(const char * file_name)
|
||||
{
|
||||
int maximum_greyscale_value;
|
||||
FILE * input;
|
||||
int pnm_number;
|
||||
pgm_structure * new_pgm = (pgm_structure *) safe_malloc (sizeof(pgm_structure));
|
||||
char * write_position;
|
||||
char * end_position;
|
||||
int image_size; /* width * height */
|
||||
|
||||
if((input = fopen(file_name, "rb")) == NULL) REMOVE_LOGO_LOAD_PGM_ERROR_MESSAGE("[vf]remove-logo: Unable to open file. File not found or insufficient permissions.\n");
|
||||
|
||||
/* Parse the PGM header. */
|
||||
if (fgetc(input) != 'P') REMOVE_LOGO_LOAD_PGM_ERROR_MESSAGE("[vf]remove-logo: File is not a valid PGM or PPM file.\n");
|
||||
pnm_number = fgetc(input) - '0';
|
||||
if (pnm_number != 5 && pnm_number != 6) REMOVE_LOGO_LOAD_PGM_ERROR_MESSAGE("[vf]remove-logo: Invalid PNM file. Only raw PGM (Portable Gray Map) and raw PPM (Portable Pixel Map) subtypes are allowed.\n");
|
||||
load_pgm_skip(input);
|
||||
if (fscanf(input, "%i", &(new_pgm->width)) != 1) REMOVE_LOGO_LOAD_PGM_ERROR_MESSAGE("[vf]remove-logo: Invalid PGM/PPM header.\n");
|
||||
load_pgm_skip(input);
|
||||
if (fscanf(input, "%i", &(new_pgm->height)) != 1) REMOVE_LOGO_LOAD_PGM_ERROR_MESSAGE("[vf]remove-logo: Invalid PGM/PPM header.\n");
|
||||
load_pgm_skip(input);
|
||||
if (fscanf(input, "%i", &maximum_greyscale_value) != 1) REMOVE_LOGO_LOAD_PGM_ERROR_MESSAGE("[vf]remove-logo: Invalid PGM/PPM header.\n");
|
||||
if (maximum_greyscale_value >= 256) REMOVE_LOGO_LOAD_PGM_ERROR_MESSAGE("[vf]remove_logo: Only 1 byte per pixel (pgm) or 1 byte per color value (ppm) are supported.\n");
|
||||
load_pgm_skip(input);
|
||||
|
||||
new_pgm->pixel = (unsigned char *) safe_malloc (sizeof(unsigned char) * new_pgm->width * new_pgm->height);
|
||||
|
||||
/* Load the pixels. */
|
||||
/* Note: I am aware that fgetc(input) isn't the fastest way of doing things, but it is quite compact and the code only runs once when the filter is initialized.*/
|
||||
image_size = new_pgm->width * new_pgm->height;
|
||||
end_position = new_pgm->pixel + image_size;
|
||||
for (write_position = new_pgm->pixel; write_position < end_position; write_position++)
|
||||
{
|
||||
*write_position = fgetc(input);
|
||||
if (pnm_number == 6) /* This tests to see if the file is a PPM file. */
|
||||
{ /* If it is, then consider the pixel set if any of the three color channels are set. Since we just care about == 0 or != 0, a bitwise or will do the trick. */
|
||||
*write_position |= fgetc(input);
|
||||
*write_position |= fgetc(input);
|
||||
}
|
||||
}
|
||||
|
||||
return new_pgm;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Generates a scaled down image with half width, height, and intensity.
|
||||
*
|
||||
* \param vf Our struct for persistant data. In this case, it is used to update
|
||||
* mask_max_size with the larger of the old or new value.
|
||||
* \param input_image The image from which the new half-sized one will be based.
|
||||
*
|
||||
* \return The newly allocated and shrunken image.
|
||||
*
|
||||
* This function not only scales down an image, but halves the value in each pixel
|
||||
* too. The purpose of this is to produce a chroma filter image out of a luma
|
||||
* filter image. The pixel values store the distance to the edge of the logo and
|
||||
* halving the dimensions halves the distance. This function rounds up, because
|
||||
* a downwards rounding error could cause the filter to fail, but an upwards
|
||||
* rounding error will only cause a minor amount of excess blur in the chroma
|
||||
* planes.
|
||||
*/
|
||||
static pgm_structure * generate_half_size_image(vf_instance_t * vf, pgm_structure * input_image)
|
||||
{
|
||||
int x, y;
|
||||
pgm_structure * new_pgm = (pgm_structure *) safe_malloc (sizeof(pgm_structure));
|
||||
int has_anything_changed = 1;
|
||||
int current_pass;
|
||||
int max_mask_size;
|
||||
char * current_pixel;
|
||||
|
||||
new_pgm->width = input_image->width / 2;
|
||||
new_pgm->height = input_image->height / 2;
|
||||
new_pgm->pixel = (unsigned char *) safe_malloc (sizeof(unsigned char) * new_pgm->width * new_pgm->height);
|
||||
|
||||
/* Copy over the image data, using the average of 4 pixels for to calculate each downsampled pixel. */
|
||||
for (y = 0; y < new_pgm->height; y++)
|
||||
for (x = 0; x < new_pgm->width; x++)
|
||||
{
|
||||
/* Set the pixel if there exists a non-zero value in the source pixels, else clear it. */
|
||||
new_pgm->pixel[(y * new_pgm->width) + x] = input_image->pixel[((y << 1) * input_image->width) + (x << 1)] ||
|
||||
input_image->pixel[((y << 1) * input_image->width) + (x << 1) + 1] ||
|
||||
input_image->pixel[(((y << 1) + 1) * input_image->width) + (x << 1)] ||
|
||||
input_image->pixel[(((y << 1) + 1) * input_image->width) + (x << 1) + 1];
|
||||
new_pgm->pixel[(y * new_pgm->width) + x] = min(1, new_pgm->pixel[(y * new_pgm->width) + x]);
|
||||
}
|
||||
|
||||
/* Now we need to recalculate the numbers for the smaller size. Just using the old_value / 2 can cause subtle
|
||||
and fairly rare, but very nasty, bugs. */
|
||||
|
||||
current_pixel = new_pgm->pixel;
|
||||
/* First pass, set all non-zero values to 1. */
|
||||
for (x = 0; x < new_pgm->height * new_pgm->width; x++, current_pixel++)
|
||||
if(*current_pixel) *current_pixel = 1;
|
||||
|
||||
/* Second pass and future passes. For each pass, if a pixel is itself the same value as the current pass,
|
||||
and its four neighbors are too, then it is incremented. If no pixels are incremented by the end of the pass,
|
||||
then we go again. Edge pixels are counted as always excluded (this should be true anyway for any sane mask,
|
||||
but if it isn't this will ensure that we eventually exit). */
|
||||
current_pass = 0;
|
||||
while (has_anything_changed)
|
||||
{
|
||||
current_pass++;
|
||||
|
||||
has_anything_changed = 0; /* If this doesn't get set by the end of this pass, then we're done. */
|
||||
|
||||
for (y = 1; y < new_pgm->height - 1; y++)
|
||||
{
|
||||
for (x = 1; x < new_pgm->width - 1; x++)
|
||||
{
|
||||
if (new_pgm->pixel[(y * new_pgm->width) + x] >= current_pass && /* By using >= instead of ==, we allow the algorithm to work in place. */
|
||||
new_pgm->pixel[(y * new_pgm->width) + (x + 1)] >= current_pass &&
|
||||
new_pgm->pixel[(y * new_pgm->width) + (x - 1)] >= current_pass &&
|
||||
new_pgm->pixel[((y + 1) * new_pgm->width) + x] >= current_pass &&
|
||||
new_pgm->pixel[((y - 1) * new_pgm->width) + x] >= current_pass)
|
||||
{
|
||||
new_pgm->pixel[(y * new_pgm->width) + x]++; /* Increment the value since it still has not been eroded,
|
||||
as evidenced by the if statement that just evaluated to true. */
|
||||
has_anything_changed = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (y = 1; y < new_pgm->height - 1; y++)
|
||||
{
|
||||
for (x = 1; x < new_pgm->width - 1; x++)
|
||||
{
|
||||
new_pgm->pixel[(y * new_pgm->width) + x] = apply_mask_fudge_factor(new_pgm->pixel[(y * new_pgm->width) + x]);
|
||||
}
|
||||
}
|
||||
|
||||
max_mask_size = current_pass + 1; /* As a side-effect, we now know the maximum mask size, which we'll use to generate our masks. */
|
||||
max_mask_size = apply_mask_fudge_factor(max_mask_size);
|
||||
/* Commit the newly calculated max_mask_size to the vf->priv struct. */
|
||||
vf->priv->max_mask_size = max(max_mask_size, vf->priv->max_mask_size);
|
||||
|
||||
return new_pgm;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Checks if YV12 is supported by the next filter.
|
||||
*/
|
||||
static unsigned int find_best(struct vf_instance *vf){
|
||||
int is_format_okay = vf->next->query_format(vf->next, IMGFMT_YV12);
|
||||
if ((is_format_okay & VFCAP_CSP_SUPPORTED_BY_HW) || (is_format_okay & VFCAP_CSP_SUPPORTED))
|
||||
return IMGFMT_YV12;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
/**
|
||||
* \brief Configure the filter and call the next filter's config function.
|
||||
*/
|
||||
static int config(struct vf_instance *vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt)
|
||||
{
|
||||
if(!(vf->priv->fmt=find_best(vf)))
|
||||
return 0;
|
||||
else
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,vf->priv->fmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Removes the logo from a plane (either luma or chroma).
|
||||
*
|
||||
* \param vf Not needed by this function, but needed by the blur function.
|
||||
* \param source The image to have it's logo removed.
|
||||
* \param destination Where the output image will be stored.
|
||||
* \param source_stride How far apart (in memory) two consecutive lines are.
|
||||
* \param destination Same as source_stride, but for the destination image.
|
||||
* \param width Width of the image. This is the same for source and destination.
|
||||
* \param height Height of the image. This is the same for source and destination.
|
||||
* \param is_image_direct If the image is direct, then source and destination are
|
||||
* the same and we can save a lot of time by not copying pixels that
|
||||
* haven't changed.
|
||||
* \param filter The image that stores the distance to the edge of the logo for
|
||||
* each pixel.
|
||||
* \param logo_start_x Smallest x-coordinate that contains at least 1 logo pixel.
|
||||
* \param logo_start_y Smallest y-coordinate that contains at least 1 logo pixel.
|
||||
* \param logo_end_x Largest x-coordinate that contains at least 1 logo pixel.
|
||||
* \param logo_end_y Largest y-coordinate that contains at least 1 logo pixel.
|
||||
*
|
||||
* This function processes an entire plane. Pixels outside of the logo are copied
|
||||
* to the output without change, and pixels inside the logo have the de-blurring
|
||||
* function applied.
|
||||
*/
|
||||
static void convert_yv12(const vf_instance_t * const vf, const char * const source, const int source_stride,
|
||||
const mp_image_t * const source_image, const int width, const int height,
|
||||
char * const destination, const int destination_stride, int is_image_direct, pgm_structure * filter,
|
||||
const int plane, const int logo_start_x, const int logo_start_y, const int logo_end_x, const int logo_end_y)
|
||||
{
|
||||
int y;
|
||||
int x;
|
||||
|
||||
/* These pointers point to where we are getting our pixel data (inside mpi) and where we are storing it (inside dmpi). */
|
||||
const unsigned char * source_line;
|
||||
unsigned char * destination_line;
|
||||
|
||||
if (!is_image_direct)
|
||||
memcpy_pic(destination, source, width, height, destination_stride, source_stride);
|
||||
|
||||
for (y = logo_start_y; y <= logo_end_y; y++)
|
||||
{
|
||||
source_line = (const unsigned char *) source + (source_stride * y);
|
||||
destination_line = (unsigned char *) destination + (destination_stride * y);
|
||||
|
||||
for (x = logo_start_x; x <= logo_end_x; x++)
|
||||
{
|
||||
unsigned int output;
|
||||
|
||||
if (filter->pixel[(y * filter->width) + x]) /* Only process if we are in the logo. */
|
||||
{
|
||||
get_blur(vf, &output, filter, source_image, x, y, plane);
|
||||
destination_line[x] = output;
|
||||
}
|
||||
else /* Else just copy the data. */
|
||||
if (!is_image_direct)
|
||||
destination_line[x] = source_line[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Process a frame.
|
||||
*
|
||||
* \param mpi The image sent to use by the previous filter.
|
||||
* \param dmpi Where we will store the processed output image.
|
||||
* \param vf This is how the filter gets access to it's persistant data.
|
||||
*
|
||||
* \return The return code of the next filter, or 0 on failure/error.
|
||||
*
|
||||
* This function processes an entire frame. The frame is sent by the previous
|
||||
* filter, has the logo removed by the filter, and is then sent to the next
|
||||
* filter.
|
||||
*/
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
|
||||
dmpi=vf_get_image(vf->next,vf->priv->fmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->w, mpi->h);
|
||||
|
||||
/* Check to make sure that the filter image and the video stream are the same size. */
|
||||
if (vf->priv->filter->width != mpi->w || vf->priv->filter->height != mpi->h)
|
||||
{
|
||||
mp_msg(MSGT_VFILTER,MSGL_ERR, "Filter image and video stream are not of the same size. (Filter: %d x %d, Stream: %d x %d)\n",
|
||||
vf->priv->filter->width, vf->priv->filter->height, mpi->w, mpi->h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(dmpi->imgfmt){
|
||||
case IMGFMT_YV12:
|
||||
convert_yv12(vf, mpi->planes[0], mpi->stride[0], mpi, mpi->w, mpi->h,
|
||||
dmpi->planes[0], dmpi->stride[0],
|
||||
mpi->flags & MP_IMGFLAG_DIRECT, vf->priv->filter, 0,
|
||||
vf->priv->bounding_rectangle_posx1, vf->priv->bounding_rectangle_posy1,
|
||||
vf->priv->bounding_rectangle_posx2, vf->priv->bounding_rectangle_posy2);
|
||||
convert_yv12(vf, mpi->planes[1], mpi->stride[1], mpi, mpi->w / 2, mpi->h / 2,
|
||||
dmpi->planes[1], dmpi->stride[1],
|
||||
mpi->flags & MP_IMGFLAG_DIRECT, vf->priv->half_size_filter, 1,
|
||||
vf->priv->bounding_rectangle_half_size_posx1, vf->priv->bounding_rectangle_half_size_posy1,
|
||||
vf->priv->bounding_rectangle_half_size_posx2, vf->priv->bounding_rectangle_half_size_posy2);
|
||||
convert_yv12(vf, mpi->planes[2], mpi->stride[2], mpi, mpi->w / 2, mpi->h / 2,
|
||||
dmpi->planes[2], dmpi->stride[2],
|
||||
mpi->flags & MP_IMGFLAG_DIRECT, vf->priv->half_size_filter, 2,
|
||||
vf->priv->bounding_rectangle_half_size_posx1, vf->priv->bounding_rectangle_half_size_posy1,
|
||||
vf->priv->bounding_rectangle_half_size_posx2, vf->priv->bounding_rectangle_half_size_posy2);
|
||||
break;
|
||||
|
||||
default:
|
||||
mp_msg(MSGT_VFILTER,MSGL_ERR,"Unhandled format: 0x%X\n",dmpi->imgfmt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
/**
|
||||
* \brief Checks to see if the next filter accepts YV12 images.
|
||||
*/
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt)
|
||||
{
|
||||
if (fmt == IMGFMT_YV12)
|
||||
return vf->next->query_format(vf->next, IMGFMT_YV12);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Frees memory that our filter allocated.
|
||||
*
|
||||
* This is called at exit-time.
|
||||
*/
|
||||
static void uninit(vf_instance_t *vf)
|
||||
{
|
||||
/* Destroy our masks and images. */
|
||||
destroy_pgm(vf->priv->filter);
|
||||
destroy_pgm(vf->priv->half_size_filter);
|
||||
destroy_masks(vf);
|
||||
|
||||
/* Destroy our private structure that had been used to store those masks and images. */
|
||||
free(vf->priv);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initializes our filter.
|
||||
*
|
||||
* \param args The arguments passed in from the command line go here. This
|
||||
* filter expects only a single argument telling it where the PGM
|
||||
* or PPM file that describes the logo region is.
|
||||
*
|
||||
* This sets up our instance variables and parses the arguments to the filter.
|
||||
*/
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
vf->priv = safe_malloc(sizeof(vf_priv_s));
|
||||
vf->uninit = uninit;
|
||||
|
||||
/* Load our filter image. */
|
||||
if (args)
|
||||
vf->priv->filter = load_pgm(args);
|
||||
else
|
||||
{
|
||||
mp_msg(MSGT_VFILTER, MSGL_ERR, "[vf]remove_logo usage: remove_logo=/path/to/filter_image_file.pgm\n");
|
||||
free(vf->priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vf->priv->filter == NULL)
|
||||
{
|
||||
/* Error message was displayed by load_pgm(). */
|
||||
free(vf->priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create the scaled down filter image for the chroma planes. */
|
||||
convert_mask_to_strength_mask(vf, vf->priv->filter);
|
||||
vf->priv->half_size_filter = generate_half_size_image(vf, vf->priv->filter);
|
||||
|
||||
/* Now that we know how many masks we need (the info is in vf), we can generate the masks. */
|
||||
initialize_masks(vf);
|
||||
|
||||
/* Calculate our bounding rectangles, which determine in what region the logo resides for faster processing. */
|
||||
calculate_bounding_rectangle(&vf->priv->bounding_rectangle_posx1, &vf->priv->bounding_rectangle_posy1,
|
||||
&vf->priv->bounding_rectangle_posx2, &vf->priv->bounding_rectangle_posy2,
|
||||
vf->priv->filter);
|
||||
calculate_bounding_rectangle(&vf->priv->bounding_rectangle_half_size_posx1,
|
||||
&vf->priv->bounding_rectangle_half_size_posy1,
|
||||
&vf->priv->bounding_rectangle_half_size_posx2,
|
||||
&vf->priv->bounding_rectangle_half_size_posy2,
|
||||
vf->priv->half_size_filter);
|
||||
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->query_format=query_format;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Meta data about our filter.
|
||||
*/
|
||||
const vf_info_t vf_info_remove_logo = {
|
||||
"Removes a tv logo based on a mask image.",
|
||||
"remove-logo",
|
||||
"Robert Edele",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
171
libavfilter/libmpcodecs/vf_rgbtest.c
Normal file
171
libavfilter/libmpcodecs/vf_rgbtest.c
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
struct vf_priv_s {
|
||||
unsigned int fmt;
|
||||
int w, h;
|
||||
};
|
||||
|
||||
static unsigned int getfmt(unsigned int outfmt){
|
||||
switch(outfmt){
|
||||
case IMGFMT_RGB12:
|
||||
case IMGFMT_RGB15:
|
||||
case IMGFMT_RGB16:
|
||||
case IMGFMT_RGB24:
|
||||
case IMGFMT_RGBA:
|
||||
case IMGFMT_ARGB:
|
||||
case IMGFMT_BGR12:
|
||||
case IMGFMT_BGR15:
|
||||
case IMGFMT_BGR16:
|
||||
case IMGFMT_BGR24:
|
||||
case IMGFMT_BGRA:
|
||||
case IMGFMT_ABGR:
|
||||
return outfmt;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void put_pixel(uint8_t *buf, int x, int y, int stride, int r, int g, int b, int fmt){
|
||||
switch(fmt){
|
||||
case IMGFMT_BGR12: ((uint16_t*)(buf + y*stride))[x]=
|
||||
((r >> 4) << 8) | ((g >> 4) << 4) | (b >> 4);
|
||||
break;
|
||||
case IMGFMT_RGB12: ((uint16_t*)(buf + y*stride))[x]=
|
||||
((b >> 4) << 8) | ((g >> 4) << 4) | (r >> 4);
|
||||
break;
|
||||
case IMGFMT_BGR15: ((uint16_t*)(buf + y*stride))[x]= ((r>>3)<<10) | ((g>>3)<<5) | (b>>3);
|
||||
break;
|
||||
case IMGFMT_RGB15: ((uint16_t*)(buf + y*stride))[x]= ((b>>3)<<10) | ((g>>3)<<5) | (r>>3);
|
||||
break;
|
||||
case IMGFMT_BGR16: ((uint16_t*)(buf + y*stride))[x]= ((r>>3)<<11) | ((g>>2)<<5) | (b>>3);
|
||||
break;
|
||||
case IMGFMT_RGB16: ((uint16_t*)(buf + y*stride))[x]= ((b>>3)<<11) | ((g>>2)<<5) | (r>>3);
|
||||
break;
|
||||
case IMGFMT_RGB24:
|
||||
buf[3*x + y*stride + 0]= r;
|
||||
buf[3*x + y*stride + 1]= g;
|
||||
buf[3*x + y*stride + 2]= b;
|
||||
break;
|
||||
case IMGFMT_BGR24:
|
||||
buf[3*x + y*stride + 0]= b;
|
||||
buf[3*x + y*stride + 1]= g;
|
||||
buf[3*x + y*stride + 2]= r;
|
||||
break;
|
||||
case IMGFMT_RGBA:
|
||||
buf[4*x + y*stride + 0]= r;
|
||||
buf[4*x + y*stride + 1]= g;
|
||||
buf[4*x + y*stride + 2]= b;
|
||||
break;
|
||||
case IMGFMT_BGRA:
|
||||
buf[4*x + y*stride + 0]= b;
|
||||
buf[4*x + y*stride + 1]= g;
|
||||
buf[4*x + y*stride + 2]= r;
|
||||
break;
|
||||
case IMGFMT_ARGB:
|
||||
buf[4*x + y*stride + 1]= r;
|
||||
buf[4*x + y*stride + 2]= g;
|
||||
buf[4*x + y*stride + 3]= b;
|
||||
break;
|
||||
case IMGFMT_ABGR:
|
||||
buf[4*x + y*stride + 1]= b;
|
||||
buf[4*x + y*stride + 2]= g;
|
||||
buf[4*x + y*stride + 3]= r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
if (vf->priv->w > 0) { d_width = width = vf->priv->w; }
|
||||
if (vf->priv->h > 0) { d_height = height = vf->priv->h; }
|
||||
vf->priv->fmt=getfmt(outfmt);
|
||||
mp_msg(MSGT_VFILTER,MSGL_V,"rgb test format:%s\n", vo_format_name(outfmt));
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,vf->priv->fmt);
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
int x, y;
|
||||
int w = vf->priv->w > 0 ? vf->priv->w : mpi->w;
|
||||
int h = vf->priv->h > 0 ? vf->priv->h : mpi->h;
|
||||
|
||||
// hope we'll get DR buffer:
|
||||
dmpi=vf_get_image(vf->next,vf->priv->fmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
w, h);
|
||||
|
||||
for(y=0; y<h; y++){
|
||||
for(x=0; x<w; x++){
|
||||
int c= 256*x/w;
|
||||
int r=0,g=0,b=0;
|
||||
|
||||
if(3*y<h) r=c;
|
||||
else if(3*y<2*h) g=c;
|
||||
else b=c;
|
||||
|
||||
put_pixel(dmpi->planes[0], x, y, dmpi->stride[0], r, g, b, vf->priv->fmt);
|
||||
}
|
||||
}
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int outfmt){
|
||||
unsigned int fmt=getfmt(outfmt);
|
||||
if(!fmt) return 0;
|
||||
return vf_next_query_format(vf,fmt) & (~VFCAP_CSP_SUPPORTED_BY_HW);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->query_format=query_format;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
vf->priv->w = vf->priv->h = 0;
|
||||
if (args)
|
||||
sscanf(args, "%d:%d", &vf->priv->w, &vf->priv->h);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_rgbtest = {
|
||||
"rgbtest",
|
||||
"rgbtest",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
152
libavfilter/libmpcodecs/vf_rotate.c
Normal file
152
libavfilter/libmpcodecs/vf_rotate.c
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
int direction;
|
||||
};
|
||||
|
||||
static void rotate(unsigned char* dst,unsigned char* src,int dststride,int srcstride,int w,int h,int bpp,int dir){
|
||||
int y;
|
||||
if(dir&1){
|
||||
src+=srcstride*(w-1);
|
||||
srcstride*=-1;
|
||||
}
|
||||
if(dir&2){
|
||||
dst+=dststride*(h-1);
|
||||
dststride*=-1;
|
||||
}
|
||||
|
||||
for(y=0;y<h;y++){
|
||||
int x;
|
||||
switch(bpp){
|
||||
case 1:
|
||||
for(x=0;x<w;x++) dst[x]=src[y+x*srcstride];
|
||||
break;
|
||||
case 2:
|
||||
for(x=0;x<w;x++) *((short*)(dst+x*2))=*((short*)(src+y*2+x*srcstride));
|
||||
break;
|
||||
case 3:
|
||||
for(x=0;x<w;x++){
|
||||
dst[x*3+0]=src[0+y*3+x*srcstride];
|
||||
dst[x*3+1]=src[1+y*3+x*srcstride];
|
||||
dst[x*3+2]=src[2+y*3+x*srcstride];
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for(x=0;x<w;x++) *((int*)(dst+x*4))=*((int*)(src+y*4+x*srcstride));
|
||||
}
|
||||
dst+=dststride;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
if (vf->priv->direction & 4) {
|
||||
if (width<height) vf->priv->direction&=3;
|
||||
}
|
||||
if (vf->priv->direction & 4){
|
||||
vf->put_image=vf_next_put_image; // passthru mode!
|
||||
if (vf->next->draw_slice) vf->draw_slice=vf_next_draw_slice;
|
||||
/* FIXME: this should be in an other procedure in vf.c; that should always check
|
||||
whether the filter after the passthrough one still (not)supports slices */
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
return vf_next_config(vf,height,width,d_height,d_width,flags,outfmt);
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
|
||||
// hope we'll get DR buffer:
|
||||
dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->h, mpi->w);
|
||||
|
||||
if(mpi->flags&MP_IMGFLAG_PLANAR){
|
||||
rotate(dmpi->planes[0],mpi->planes[0],
|
||||
dmpi->stride[0],mpi->stride[0],
|
||||
dmpi->w,dmpi->h,1,vf->priv->direction);
|
||||
rotate(dmpi->planes[1],mpi->planes[1],
|
||||
dmpi->stride[1],mpi->stride[1],
|
||||
dmpi->w>>mpi->chroma_x_shift,dmpi->h>>mpi->chroma_y_shift,1,vf->priv->direction);
|
||||
rotate(dmpi->planes[2],mpi->planes[2],
|
||||
dmpi->stride[2],mpi->stride[2],
|
||||
dmpi->w>>mpi->chroma_x_shift,dmpi->h>>mpi->chroma_y_shift,1,vf->priv->direction);
|
||||
} else {
|
||||
rotate(dmpi->planes[0],mpi->planes[0],
|
||||
dmpi->stride[0],mpi->stride[0],
|
||||
dmpi->w,dmpi->h,dmpi->bpp>>3,vf->priv->direction);
|
||||
dmpi->planes[1] = mpi->planes[1]; // passthrough rgb8 palette
|
||||
}
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
if(IMGFMT_IS_RGB(fmt) || IMGFMT_IS_BGR(fmt)) return vf_next_query_format(vf, fmt);
|
||||
// we can support only symmetric (chroma_x_shift==chroma_y_shift) YUV formats:
|
||||
switch(fmt) {
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_YVU9:
|
||||
// case IMGFMT_IF09:
|
||||
case IMGFMT_Y8:
|
||||
case IMGFMT_Y800:
|
||||
case IMGFMT_444P:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->query_format=query_format;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
vf->priv->direction=args?atoi(args):0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_rotate = {
|
||||
"rotate",
|
||||
"rotate",
|
||||
"A'rpi",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
321
libavfilter/libmpcodecs/vf_sab.c
Normal file
321
libavfilter/libmpcodecs/vf_sab.c
Normal file
@ -0,0 +1,321 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#if HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include "libavutil/avutil.h"
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
#include "libswscale/swscale.h"
|
||||
#include "vf_scale.h"
|
||||
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
typedef struct FilterParam{
|
||||
float radius;
|
||||
float preFilterRadius;
|
||||
float strength;
|
||||
float quality;
|
||||
struct SwsContext *preFilterContext;
|
||||
uint8_t *preFilterBuf;
|
||||
int preFilterStride;
|
||||
int distWidth;
|
||||
int distStride;
|
||||
int *distCoeff;
|
||||
int colorDiffCoeff[512];
|
||||
}FilterParam;
|
||||
|
||||
struct vf_priv_s {
|
||||
FilterParam luma;
|
||||
FilterParam chroma;
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
//FIXME stupid code duplication
|
||||
static void getSubSampleFactors(int *h, int *v, int format){
|
||||
switch(format){
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
*h=1;
|
||||
*v=1;
|
||||
break;
|
||||
case IMGFMT_YVU9:
|
||||
*h=2;
|
||||
*v=2;
|
||||
break;
|
||||
case IMGFMT_444P:
|
||||
*h=0;
|
||||
*v=0;
|
||||
break;
|
||||
case IMGFMT_422P:
|
||||
*h=1;
|
||||
*v=0;
|
||||
break;
|
||||
case IMGFMT_411P:
|
||||
*h=2;
|
||||
*v=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int allocStuff(FilterParam *f, int width, int height){
|
||||
int stride= (width+7)&~7;
|
||||
SwsVector *vec;
|
||||
SwsFilter swsF;
|
||||
int i,x,y;
|
||||
f->preFilterBuf= (uint8_t*)memalign(8, stride*height);
|
||||
f->preFilterStride= stride;
|
||||
|
||||
vec = sws_getGaussianVec(f->preFilterRadius, f->quality);
|
||||
swsF.lumH= swsF.lumV= vec;
|
||||
swsF.chrH= swsF.chrV= NULL;
|
||||
f->preFilterContext= sws_getContext(
|
||||
width, height, PIX_FMT_GRAY8, width, height, PIX_FMT_GRAY8, get_sws_cpuflags()|SWS_POINT, &swsF, NULL, NULL);
|
||||
|
||||
sws_freeVec(vec);
|
||||
vec = sws_getGaussianVec(f->strength, 5.0);
|
||||
for(i=0; i<512; i++){
|
||||
double d;
|
||||
int index= i-256 + vec->length/2;
|
||||
|
||||
if(index<0 || index>=vec->length) d= 0.0;
|
||||
else d= vec->coeff[index];
|
||||
|
||||
f->colorDiffCoeff[i]= (int)(d/vec->coeff[vec->length/2]*(1<<12) + 0.5);
|
||||
}
|
||||
sws_freeVec(vec);
|
||||
vec = sws_getGaussianVec(f->radius, f->quality);
|
||||
f->distWidth= vec->length;
|
||||
f->distStride= (vec->length+7)&~7;
|
||||
f->distCoeff= (int32_t*)memalign(8, f->distWidth*f->distStride*sizeof(int32_t));
|
||||
|
||||
for(y=0; y<vec->length; y++){
|
||||
for(x=0; x<vec->length; x++){
|
||||
double d= vec->coeff[x] * vec->coeff[y];
|
||||
|
||||
f->distCoeff[x + y*f->distStride]= (int)(d*(1<<10) + 0.5);
|
||||
// if(y==vec->length/2)
|
||||
// printf("%6d ", f->distCoeff[x + y*f->distStride]);
|
||||
}
|
||||
}
|
||||
sws_freeVec(vec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
|
||||
int sw, sh;
|
||||
//__asm__ volatile("emms\n\t");
|
||||
allocStuff(&vf->priv->luma, width, height);
|
||||
|
||||
getSubSampleFactors(&sw, &sh, outfmt);
|
||||
allocStuff(&vf->priv->chroma, width>>sw, height>>sh);
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static void freeBuffers(FilterParam *f){
|
||||
if(f->preFilterContext) sws_freeContext(f->preFilterContext);
|
||||
f->preFilterContext=NULL;
|
||||
|
||||
free(f->preFilterBuf);
|
||||
f->preFilterBuf=NULL;
|
||||
|
||||
free(f->distCoeff);
|
||||
f->distCoeff=NULL;
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf){
|
||||
if(!vf->priv) return;
|
||||
|
||||
freeBuffers(&vf->priv->luma);
|
||||
freeBuffers(&vf->priv->chroma);
|
||||
|
||||
free(vf->priv);
|
||||
vf->priv=NULL;
|
||||
}
|
||||
|
||||
static inline void blur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, FilterParam *fp){
|
||||
int x, y;
|
||||
FilterParam f= *fp;
|
||||
const int radius= f.distWidth/2;
|
||||
const uint8_t* const srcArray[MP_MAX_PLANES] = {src};
|
||||
uint8_t *dstArray[MP_MAX_PLANES]= {f.preFilterBuf};
|
||||
int srcStrideArray[MP_MAX_PLANES]= {srcStride};
|
||||
int dstStrideArray[MP_MAX_PLANES]= {f.preFilterStride};
|
||||
|
||||
// f.preFilterContext->swScale(f.preFilterContext, srcArray, srcStrideArray, 0, h, dstArray, dstStrideArray);
|
||||
sws_scale(f.preFilterContext, srcArray, srcStrideArray, 0, h, dstArray, dstStrideArray);
|
||||
|
||||
for(y=0; y<h; y++){
|
||||
for(x=0; x<w; x++){
|
||||
int sum=0;
|
||||
int div=0;
|
||||
int dy;
|
||||
const int preVal= f.preFilterBuf[x + y*f.preFilterStride];
|
||||
#if 0
|
||||
const int srcVal= src[x + y*srcStride];
|
||||
if((x/32)&1){
|
||||
dst[x + y*dstStride]= srcVal;
|
||||
if(y%32==0) dst[x + y*dstStride]= 0;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if(x >= radius && x < w - radius){
|
||||
for(dy=0; dy<radius*2+1; dy++){
|
||||
int dx;
|
||||
int iy= y+dy - radius;
|
||||
if (iy<0) iy= -iy;
|
||||
else if(iy>=h) iy= h+h-iy-1;
|
||||
|
||||
for(dx=0; dx<radius*2+1; dx++){
|
||||
const int ix= x+dx - radius;
|
||||
int factor;
|
||||
|
||||
factor= f.colorDiffCoeff[256+preVal - f.preFilterBuf[ix + iy*f.preFilterStride] ]
|
||||
*f.distCoeff[dx + dy*f.distStride];
|
||||
sum+= src[ix + iy*srcStride] *factor;
|
||||
div+= factor;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
for(dy=0; dy<radius*2+1; dy++){
|
||||
int dx;
|
||||
int iy= y+dy - radius;
|
||||
if (iy<0) iy= -iy;
|
||||
else if(iy>=h) iy= h+h-iy-1;
|
||||
|
||||
for(dx=0; dx<radius*2+1; dx++){
|
||||
int ix= x+dx - radius;
|
||||
int factor;
|
||||
if (ix<0) ix= -ix;
|
||||
else if(ix>=w) ix= w+w-ix-1;
|
||||
|
||||
factor= f.colorDiffCoeff[256+preVal - f.preFilterBuf[ix + iy*f.preFilterStride] ]
|
||||
*f.distCoeff[dx + dy*f.distStride];
|
||||
sum+= src[ix + iy*srcStride] *factor;
|
||||
div+= factor;
|
||||
}
|
||||
}
|
||||
}
|
||||
dst[x + y*dstStride]= (sum + div/2)/div;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
int cw= mpi->w >> mpi->chroma_x_shift;
|
||||
int ch= mpi->h >> mpi->chroma_y_shift;
|
||||
|
||||
mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->w,mpi->h);
|
||||
|
||||
assert(mpi->flags&MP_IMGFLAG_PLANAR);
|
||||
|
||||
blur(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0], &vf->priv->luma);
|
||||
blur(dmpi->planes[1], mpi->planes[1], cw , ch , dmpi->stride[1], mpi->stride[1], &vf->priv->chroma);
|
||||
blur(dmpi->planes[2], mpi->planes[2], cw , ch , dmpi->stride[2], mpi->stride[2], &vf->priv->chroma);
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
switch(fmt)
|
||||
{
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
int e;
|
||||
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
// vf->get_image=get_image;
|
||||
vf->query_format=query_format;
|
||||
vf->uninit=uninit;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
|
||||
if(args==NULL) return 0;
|
||||
|
||||
e=sscanf(args, "%f:%f:%f:%f:%f:%f",
|
||||
&vf->priv->luma.radius,
|
||||
&vf->priv->luma.preFilterRadius,
|
||||
&vf->priv->luma.strength,
|
||||
&vf->priv->chroma.radius,
|
||||
&vf->priv->chroma.preFilterRadius,
|
||||
&vf->priv->chroma.strength
|
||||
);
|
||||
|
||||
vf->priv->luma.quality = vf->priv->chroma.quality= 3.0;
|
||||
|
||||
if(e==3){
|
||||
vf->priv->chroma.radius= vf->priv->luma.radius;
|
||||
vf->priv->chroma.preFilterRadius = vf->priv->luma.preFilterRadius;
|
||||
vf->priv->chroma.strength= vf->priv->luma.strength;
|
||||
}else if(e!=6)
|
||||
return 0;
|
||||
|
||||
// if(vf->priv->luma.radius < 0) return 0;
|
||||
// if(vf->priv->chroma.radius < 0) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_sab = {
|
||||
"shape adaptive blur",
|
||||
"sab",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
35
libavfilter/libmpcodecs/vf_scale.h
Normal file
35
libavfilter/libmpcodecs/vf_scale.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_VF_SCALE_H
|
||||
#define MPLAYER_VF_SCALE_H
|
||||
|
||||
extern int sws_chr_vshift;
|
||||
extern int sws_chr_hshift;
|
||||
|
||||
extern float sws_chr_gblur;
|
||||
extern float sws_lum_gblur;
|
||||
extern float sws_chr_sharpen;
|
||||
extern float sws_lum_sharpen;
|
||||
|
||||
extern int sws_flags;
|
||||
|
||||
int get_sws_cpuflags(void);
|
||||
struct SwsContext *sws_getContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat);
|
||||
|
||||
#endif /* MPLAYER_VF_SCALE_H */
|
||||
322
libavfilter/libmpcodecs/vf_screenshot.c
Normal file
322
libavfilter/libmpcodecs/vf_screenshot.c
Normal file
@ -0,0 +1,322 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#if HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
#include "vf_scale.h"
|
||||
|
||||
#include "libswscale/swscale.h"
|
||||
#include "libavcodec/avcodec.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
int frameno;
|
||||
char fname[102];
|
||||
/// shot stores current screenshot mode:
|
||||
/// 0: don't take screenshots
|
||||
/// 1: take single screenshot, reset to 0 afterwards
|
||||
/// 2: take screenshots of each frame
|
||||
int shot, store_slices;
|
||||
int dw, dh, stride;
|
||||
uint8_t *buffer;
|
||||
struct SwsContext *ctx;
|
||||
AVCodecContext *avctx;
|
||||
uint8_t *outbuffer;
|
||||
int outbuffer_size;
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt)
|
||||
{
|
||||
vf->priv->ctx=sws_getContextFromCmdLine(width, height, outfmt,
|
||||
d_width, d_height, IMGFMT_RGB24);
|
||||
|
||||
vf->priv->outbuffer_size = d_width * d_height * 3 * 2;
|
||||
vf->priv->outbuffer = realloc(vf->priv->outbuffer, vf->priv->outbuffer_size);
|
||||
vf->priv->avctx->width = d_width;
|
||||
vf->priv->avctx->height = d_height;
|
||||
vf->priv->avctx->pix_fmt = PIX_FMT_RGB24;
|
||||
vf->priv->avctx->compression_level = 0;
|
||||
vf->priv->dw = d_width;
|
||||
vf->priv->dh = d_height;
|
||||
vf->priv->stride = (3*vf->priv->dw+15)&~15;
|
||||
|
||||
free(vf->priv->buffer); // probably reconfigured
|
||||
vf->priv->buffer = NULL;
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static void write_png(struct vf_priv_s *priv)
|
||||
{
|
||||
char *fname = priv->fname;
|
||||
FILE * fp;
|
||||
AVFrame pic;
|
||||
int size;
|
||||
|
||||
fp = fopen (fname, "wb");
|
||||
if (fp == NULL) {
|
||||
mp_msg(MSGT_VFILTER,MSGL_ERR,"\nPNG Error opening %s for writing!\n", fname);
|
||||
return;
|
||||
}
|
||||
|
||||
pic.data[0] = priv->buffer;
|
||||
pic.linesize[0] = priv->stride;
|
||||
size = avcodec_encode_video(priv->avctx, priv->outbuffer, priv->outbuffer_size, &pic);
|
||||
if (size > 0)
|
||||
fwrite(priv->outbuffer, size, 1, fp);
|
||||
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
static int fexists(char *fname)
|
||||
{
|
||||
struct stat dummy;
|
||||
if (stat(fname, &dummy) == 0) return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
static void gen_fname(struct vf_priv_s* priv)
|
||||
{
|
||||
do {
|
||||
snprintf (priv->fname, 100, "shot%04d.png", ++priv->frameno);
|
||||
} while (fexists(priv->fname) && priv->frameno < 100000);
|
||||
if (fexists(priv->fname)) {
|
||||
priv->fname[0] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
mp_msg(MSGT_VFILTER,MSGL_INFO,"*** screenshot '%s' ***\n",priv->fname);
|
||||
|
||||
}
|
||||
|
||||
static void scale_image(struct vf_priv_s* priv, mp_image_t *mpi)
|
||||
{
|
||||
uint8_t *dst[MP_MAX_PLANES] = {NULL};
|
||||
int dst_stride[MP_MAX_PLANES] = {0};
|
||||
|
||||
dst_stride[0] = priv->stride;
|
||||
if (!priv->buffer)
|
||||
priv->buffer = av_malloc(dst_stride[0]*priv->dh);
|
||||
|
||||
dst[0] = priv->buffer;
|
||||
sws_scale(priv->ctx, mpi->planes, mpi->stride, 0, priv->dh, dst, dst_stride);
|
||||
}
|
||||
|
||||
static void start_slice(struct vf_instance *vf, mp_image_t *mpi)
|
||||
{
|
||||
vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
mpi->type, mpi->flags, mpi->width, mpi->height);
|
||||
if (vf->priv->shot) {
|
||||
vf->priv->store_slices = 1;
|
||||
if (!vf->priv->buffer)
|
||||
vf->priv->buffer = av_malloc(vf->priv->stride*vf->priv->dh);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void draw_slice(struct vf_instance *vf, unsigned char** src,
|
||||
int* stride, int w,int h, int x, int y)
|
||||
{
|
||||
if (vf->priv->store_slices) {
|
||||
uint8_t *dst[MP_MAX_PLANES] = {NULL};
|
||||
int dst_stride[MP_MAX_PLANES] = {0};
|
||||
dst_stride[0] = vf->priv->stride;
|
||||
dst[0] = vf->priv->buffer;
|
||||
sws_scale(vf->priv->ctx, src, stride, y, h, dst, dst_stride);
|
||||
}
|
||||
vf_next_draw_slice(vf,src,stride,w,h,x,y);
|
||||
}
|
||||
|
||||
static void get_image(struct vf_instance *vf, mp_image_t *mpi)
|
||||
{
|
||||
// FIXME: should vf.c really call get_image when using slices??
|
||||
if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
|
||||
return;
|
||||
vf->dmpi= vf_get_image(vf->next, mpi->imgfmt,
|
||||
mpi->type, mpi->flags/* | MP_IMGFLAG_READABLE*/, mpi->width, mpi->height);
|
||||
|
||||
mpi->planes[0]=vf->dmpi->planes[0];
|
||||
mpi->stride[0]=vf->dmpi->stride[0];
|
||||
if(mpi->flags&MP_IMGFLAG_PLANAR){
|
||||
mpi->planes[1]=vf->dmpi->planes[1];
|
||||
mpi->planes[2]=vf->dmpi->planes[2];
|
||||
mpi->stride[1]=vf->dmpi->stride[1];
|
||||
mpi->stride[2]=vf->dmpi->stride[2];
|
||||
}
|
||||
mpi->width=vf->dmpi->width;
|
||||
|
||||
mpi->flags|=MP_IMGFLAG_DIRECT;
|
||||
|
||||
mpi->priv=(void*)vf->dmpi;
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
mp_image_t *dmpi = (mp_image_t *)mpi->priv;
|
||||
|
||||
if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
|
||||
dmpi = vf->dmpi;
|
||||
else
|
||||
if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
|
||||
dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_EXPORT, 0,
|
||||
mpi->width, mpi->height);
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
dmpi->planes[0]=mpi->planes[0];
|
||||
dmpi->planes[1]=mpi->planes[1];
|
||||
dmpi->planes[2]=mpi->planes[2];
|
||||
dmpi->stride[0]=mpi->stride[0];
|
||||
dmpi->stride[1]=mpi->stride[1];
|
||||
dmpi->stride[2]=mpi->stride[2];
|
||||
dmpi->width=mpi->width;
|
||||
dmpi->height=mpi->height;
|
||||
}
|
||||
|
||||
if(vf->priv->shot) {
|
||||
if (vf->priv->shot==1)
|
||||
vf->priv->shot=0;
|
||||
gen_fname(vf->priv);
|
||||
if (vf->priv->fname[0]) {
|
||||
if (!vf->priv->store_slices)
|
||||
scale_image(vf->priv, dmpi);
|
||||
write_png(vf->priv);
|
||||
}
|
||||
vf->priv->store_slices = 0;
|
||||
}
|
||||
|
||||
return vf_next_put_image(vf, dmpi, pts);
|
||||
}
|
||||
|
||||
static int control (vf_instance_t *vf, int request, void *data)
|
||||
{
|
||||
/** data contains an integer argument
|
||||
* 0: take screenshot with the next frame
|
||||
* 1: take screenshots with each frame until the same command is given once again
|
||||
**/
|
||||
if(request==VFCTRL_SCREENSHOT) {
|
||||
if (data && *(int*)data) { // repeated screenshot mode
|
||||
if (vf->priv->shot==2)
|
||||
vf->priv->shot=0;
|
||||
else
|
||||
vf->priv->shot=2;
|
||||
} else { // single screenshot
|
||||
if (!vf->priv->shot)
|
||||
vf->priv->shot=1;
|
||||
}
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
return vf_next_control (vf, request, data);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt)
|
||||
{
|
||||
switch(fmt){
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_UYVY:
|
||||
case IMGFMT_YUY2:
|
||||
case IMGFMT_BGR32:
|
||||
case IMGFMT_BGR24:
|
||||
case IMGFMT_BGR16:
|
||||
case IMGFMT_BGR15:
|
||||
case IMGFMT_BGR12:
|
||||
case IMGFMT_RGB32:
|
||||
case IMGFMT_RGB24:
|
||||
case IMGFMT_Y800:
|
||||
case IMGFMT_Y8:
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_IF09:
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uninit(vf_instance_t *vf)
|
||||
{
|
||||
avcodec_close(vf->priv->avctx);
|
||||
av_freep(&vf->priv->avctx);
|
||||
if(vf->priv->ctx) sws_freeContext(vf->priv->ctx);
|
||||
av_free(vf->priv->buffer);
|
||||
free(vf->priv->outbuffer);
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
vf->config=config;
|
||||
vf->control=control;
|
||||
vf->put_image=put_image;
|
||||
vf->query_format=query_format;
|
||||
vf->start_slice=start_slice;
|
||||
vf->draw_slice=draw_slice;
|
||||
vf->get_image=get_image;
|
||||
vf->uninit=uninit;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
vf->priv->frameno=0;
|
||||
vf->priv->shot=0;
|
||||
vf->priv->store_slices=0;
|
||||
vf->priv->buffer=0;
|
||||
vf->priv->outbuffer=0;
|
||||
vf->priv->ctx=0;
|
||||
vf->priv->avctx = avcodec_alloc_context();
|
||||
avcodec_register_all();
|
||||
if (avcodec_open(vf->priv->avctx, avcodec_find_encoder(CODEC_ID_PNG))) {
|
||||
mp_msg(MSGT_VFILTER, MSGL_FATAL, "Could not open libavcodec PNG encoder\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
const vf_info_t vf_info_screenshot = {
|
||||
"screenshot to file",
|
||||
"screenshot",
|
||||
"A'rpi, Jindrich Makovicka",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
262
libavfilter/libmpcodecs/vf_smartblur.c
Normal file
262
libavfilter/libmpcodecs/vf_smartblur.c
Normal file
@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mp_msg.h"
|
||||
#include "libavutil/avutil.h"
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
#include "libswscale/swscale.h"
|
||||
#include "vf_scale.h"
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
typedef struct FilterParam{
|
||||
float radius;
|
||||
float strength;
|
||||
int threshold;
|
||||
float quality;
|
||||
struct SwsContext *filterContext;
|
||||
}FilterParam;
|
||||
|
||||
struct vf_priv_s {
|
||||
FilterParam luma;
|
||||
FilterParam chroma;
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
//FIXME stupid code duplication
|
||||
static void getSubSampleFactors(int *h, int *v, int format){
|
||||
switch(format){
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
*h=1;
|
||||
*v=1;
|
||||
break;
|
||||
case IMGFMT_YVU9:
|
||||
*h=2;
|
||||
*v=2;
|
||||
break;
|
||||
case IMGFMT_444P:
|
||||
*h=0;
|
||||
*v=0;
|
||||
break;
|
||||
case IMGFMT_422P:
|
||||
*h=1;
|
||||
*v=0;
|
||||
break;
|
||||
case IMGFMT_411P:
|
||||
*h=2;
|
||||
*v=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int allocStuff(FilterParam *f, int width, int height){
|
||||
SwsVector *vec;
|
||||
SwsFilter swsF;
|
||||
|
||||
vec = sws_getGaussianVec(f->radius, f->quality);
|
||||
sws_scaleVec(vec, f->strength);
|
||||
vec->coeff[vec->length/2]+= 1.0 - f->strength;
|
||||
swsF.lumH= swsF.lumV= vec;
|
||||
swsF.chrH= swsF.chrV= NULL;
|
||||
f->filterContext= sws_getContext(
|
||||
width, height, PIX_FMT_GRAY8, width, height, PIX_FMT_GRAY8, SWS_BICUBIC | get_sws_cpuflags(), &swsF, NULL, NULL);
|
||||
|
||||
sws_freeVec(vec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
|
||||
int sw, sh;
|
||||
|
||||
allocStuff(&vf->priv->luma, width, height);
|
||||
|
||||
getSubSampleFactors(&sw, &sh, outfmt);
|
||||
allocStuff(&vf->priv->chroma, width>>sw, height>>sh);
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static void freeBuffers(FilterParam *f){
|
||||
if(f->filterContext) sws_freeContext(f->filterContext);
|
||||
f->filterContext=NULL;
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf){
|
||||
if(!vf->priv) return;
|
||||
|
||||
freeBuffers(&vf->priv->luma);
|
||||
freeBuffers(&vf->priv->chroma);
|
||||
|
||||
free(vf->priv);
|
||||
vf->priv=NULL;
|
||||
}
|
||||
|
||||
static inline void blur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, FilterParam *fp){
|
||||
int x, y;
|
||||
FilterParam f= *fp;
|
||||
const uint8_t* const srcArray[MP_MAX_PLANES] = {src};
|
||||
uint8_t *dstArray[MP_MAX_PLANES]= {dst};
|
||||
int srcStrideArray[MP_MAX_PLANES]= {srcStride};
|
||||
int dstStrideArray[MP_MAX_PLANES]= {dstStride};
|
||||
|
||||
sws_scale(f.filterContext, srcArray, srcStrideArray, 0, h, dstArray, dstStrideArray);
|
||||
|
||||
if(f.threshold > 0){
|
||||
for(y=0; y<h; y++){
|
||||
for(x=0; x<w; x++){
|
||||
const int orig= src[x + y*srcStride];
|
||||
const int filtered= dst[x + y*dstStride];
|
||||
const int diff= orig - filtered;
|
||||
|
||||
if(diff > 0){
|
||||
if(diff > 2*f.threshold){
|
||||
dst[x + y*dstStride]= orig;
|
||||
}else if(diff > f.threshold){
|
||||
dst[x + y*dstStride]= filtered + diff - f.threshold;
|
||||
}
|
||||
}else{
|
||||
if(-diff > 2*f.threshold){
|
||||
dst[x + y*dstStride]= orig;
|
||||
}else if(-diff > f.threshold){
|
||||
dst[x + y*dstStride]= filtered + diff + f.threshold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if(f.threshold < 0){
|
||||
for(y=0; y<h; y++){
|
||||
for(x=0; x<w; x++){
|
||||
const int orig= src[x + y*srcStride];
|
||||
const int filtered= dst[x + y*dstStride];
|
||||
const int diff= orig - filtered;
|
||||
|
||||
if(diff > 0){
|
||||
if(diff > -2*f.threshold){
|
||||
}else if(diff > -f.threshold){
|
||||
dst[x + y*dstStride]= orig - diff - f.threshold;
|
||||
}else
|
||||
dst[x + y*dstStride]= orig;
|
||||
}else{
|
||||
if(diff < 2*f.threshold){
|
||||
}else if(diff < f.threshold){
|
||||
dst[x + y*dstStride]= orig - diff + f.threshold;
|
||||
}else
|
||||
dst[x + y*dstStride]= orig;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
int cw= mpi->w >> mpi->chroma_x_shift;
|
||||
int ch= mpi->h >> mpi->chroma_y_shift;
|
||||
FilterParam *f= &vf->priv;
|
||||
|
||||
mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE|
|
||||
(f->threshold) ? MP_IMGFLAG_READABLE : 0,
|
||||
mpi->w,mpi->h);
|
||||
|
||||
assert(mpi->flags&MP_IMGFLAG_PLANAR);
|
||||
|
||||
blur(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0], &vf->priv->luma);
|
||||
blur(dmpi->planes[1], mpi->planes[1], cw , ch , dmpi->stride[1], mpi->stride[1], &vf->priv->chroma);
|
||||
blur(dmpi->planes[2], mpi->planes[2], cw , ch , dmpi->stride[2], mpi->stride[2], &vf->priv->chroma);
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
switch(fmt)
|
||||
{
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
int e;
|
||||
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
// vf->get_image=get_image;
|
||||
vf->query_format=query_format;
|
||||
vf->uninit=uninit;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
|
||||
if(args==NULL) return 0;
|
||||
|
||||
e=sscanf(args, "%f:%f:%d:%f:%f:%d",
|
||||
&vf->priv->luma.radius,
|
||||
&vf->priv->luma.strength,
|
||||
&vf->priv->luma.threshold,
|
||||
&vf->priv->chroma.radius,
|
||||
&vf->priv->chroma.strength,
|
||||
&vf->priv->chroma.threshold
|
||||
);
|
||||
|
||||
vf->priv->luma.quality = vf->priv->chroma.quality= 3.0;
|
||||
|
||||
if(e==3){
|
||||
vf->priv->chroma.radius= vf->priv->luma.radius;
|
||||
vf->priv->chroma.strength= vf->priv->luma.strength;
|
||||
vf->priv->chroma.threshold = vf->priv->luma.threshold;
|
||||
}else if(e!=6)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_smartblur = {
|
||||
"smart blur",
|
||||
"smartblur",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
164
libavfilter/libmpcodecs/vf_softpulldown.c
Normal file
164
libavfilter/libmpcodecs/vf_softpulldown.c
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
int state;
|
||||
long long in;
|
||||
long long out;
|
||||
};
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
mp_image_t *dmpi;
|
||||
int ret = 0;
|
||||
int flags = mpi->fields;
|
||||
int state = vf->priv->state;
|
||||
|
||||
dmpi = vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
|
||||
MP_IMGFLAG_PRESERVE, mpi->width, mpi->height);
|
||||
|
||||
vf->priv->in++;
|
||||
|
||||
if ((state == 0 &&
|
||||
!(flags & MP_IMGFIELD_TOP_FIRST)) ||
|
||||
(state == 1 &&
|
||||
flags & MP_IMGFIELD_TOP_FIRST)) {
|
||||
mp_msg(MSGT_VFILTER, MSGL_WARN,
|
||||
"softpulldown: Unexpected field flags: state=%d top_field_first=%d repeat_first_field=%d\n",
|
||||
state,
|
||||
(flags & MP_IMGFIELD_TOP_FIRST) != 0,
|
||||
(flags & MP_IMGFIELD_REPEAT_FIRST) != 0);
|
||||
state ^= 1;
|
||||
}
|
||||
|
||||
if (state == 0) {
|
||||
ret = vf_next_put_image(vf, mpi, MP_NOPTS_VALUE);
|
||||
vf->priv->out++;
|
||||
if (flags & MP_IMGFIELD_REPEAT_FIRST) {
|
||||
my_memcpy_pic(dmpi->planes[0],
|
||||
mpi->planes[0], mpi->w, mpi->h/2,
|
||||
dmpi->stride[0]*2, mpi->stride[0]*2);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
my_memcpy_pic(dmpi->planes[1],
|
||||
mpi->planes[1],
|
||||
mpi->chroma_width,
|
||||
mpi->chroma_height/2,
|
||||
dmpi->stride[1]*2,
|
||||
mpi->stride[1]*2);
|
||||
my_memcpy_pic(dmpi->planes[2],
|
||||
mpi->planes[2],
|
||||
mpi->chroma_width,
|
||||
mpi->chroma_height/2,
|
||||
dmpi->stride[2]*2,
|
||||
mpi->stride[2]*2);
|
||||
}
|
||||
state=1;
|
||||
}
|
||||
} else {
|
||||
my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
|
||||
mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2,
|
||||
dmpi->stride[0]*2, mpi->stride[0]*2);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
|
||||
mpi->planes[1]+mpi->stride[1],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[1]*2, mpi->stride[1]*2);
|
||||
my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
|
||||
mpi->planes[2]+mpi->stride[2],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[2]*2, mpi->stride[2]*2);
|
||||
}
|
||||
ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
|
||||
vf->priv->out++;
|
||||
if (flags & MP_IMGFIELD_REPEAT_FIRST) {
|
||||
ret |= vf_next_put_image(vf, mpi, MP_NOPTS_VALUE);
|
||||
vf->priv->out++;
|
||||
state=0;
|
||||
} else {
|
||||
my_memcpy_pic(dmpi->planes[0],
|
||||
mpi->planes[0], mpi->w, mpi->h/2,
|
||||
dmpi->stride[0]*2, mpi->stride[0]*2);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
my_memcpy_pic(dmpi->planes[1],
|
||||
mpi->planes[1],
|
||||
mpi->chroma_width,
|
||||
mpi->chroma_height/2,
|
||||
dmpi->stride[1]*2,
|
||||
mpi->stride[1]*2);
|
||||
my_memcpy_pic(dmpi->planes[2],
|
||||
mpi->planes[2],
|
||||
mpi->chroma_width,
|
||||
mpi->chroma_height/2,
|
||||
dmpi->stride[2]*2,
|
||||
mpi->stride[2]*2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vf->priv->state = state;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt)
|
||||
{
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
mp_msg(MSGT_VFILTER, MSGL_INFO, "softpulldown: %lld frames in, %lld frames out\n", vf->priv->in, vf->priv->out);
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
struct vf_priv_s *p;
|
||||
vf->config = config;
|
||||
vf->put_image = put_image;
|
||||
vf->uninit = uninit;
|
||||
vf->default_reqs = VFCAP_ACCEPT_STRIDE;
|
||||
vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
|
||||
vf->priv->state = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_softpulldown = {
|
||||
"mpeg2 soft 3:2 pulldown",
|
||||
"softpulldown",
|
||||
"Tobias Diedrich <ranma+mplayer@tdiedrich.de>",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
102
libavfilter/libmpcodecs/vf_softskip.c
Normal file
102
libavfilter/libmpcodecs/vf_softskip.c
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
int skipflag;
|
||||
};
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
mp_image_t *dmpi;
|
||||
|
||||
if (vf->priv->skipflag)
|
||||
return vf->priv->skipflag = 0;
|
||||
|
||||
dmpi = vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_EXPORT, 0, mpi->width, mpi->height);
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
|
||||
dmpi->planes[0] = mpi->planes[0];
|
||||
dmpi->stride[0] = mpi->stride[0];
|
||||
if (dmpi->flags&MP_IMGFLAG_PLANAR) {
|
||||
dmpi->planes[1] = mpi->planes[1];
|
||||
dmpi->stride[1] = mpi->stride[1];
|
||||
dmpi->planes[2] = mpi->planes[2];
|
||||
dmpi->stride[2] = mpi->stride[2];
|
||||
}
|
||||
|
||||
return vf_next_put_image(vf, dmpi, pts);
|
||||
}
|
||||
|
||||
static int control(struct vf_instance *vf, int request, void* data)
|
||||
{
|
||||
switch (request) {
|
||||
case VFCTRL_SKIP_NEXT_FRAME:
|
||||
vf->priv->skipflag = 1;
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
return vf_next_control(vf, request, data);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt)
|
||||
{
|
||||
/* FIXME - figure out which other formats work */
|
||||
switch (fmt) {
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_I420:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
vf->put_image = put_image;
|
||||
vf->control = control;
|
||||
vf->uninit = uninit;
|
||||
vf->priv = calloc(1, sizeof(struct vf_priv_s));
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_softskip = {
|
||||
"soft (post-filter) frame skipping for encoding",
|
||||
"softskip",
|
||||
"Rich Felker",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
620
libavfilter/libmpcodecs/vf_spp.c
Normal file
620
libavfilter/libmpcodecs/vf_spp.c
Normal file
@ -0,0 +1,620 @@
|
||||
/*
|
||||
* Copyright (C) 2003 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This implementation is based on an algorithm described in
|
||||
* "Aria Nosratinia Embedded Post-Processing for
|
||||
* Enhancement of Compressed Images (1999)"
|
||||
* (http://citeseer.nj.nec.com/nosratinia99embedded.html)
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
#include "libavutil/internal.h"
|
||||
#include "libavutil/intreadwrite.h"
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavcodec/dsputil.h"
|
||||
|
||||
#undef fprintf
|
||||
#undef free
|
||||
#undef malloc
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
#include "vd_ffmpeg.h"
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
#define XMIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
//===========================================================================//
|
||||
static const uint8_t __attribute__((aligned(8))) dither[8][8]={
|
||||
{ 0, 48, 12, 60, 3, 51, 15, 63, },
|
||||
{ 32, 16, 44, 28, 35, 19, 47, 31, },
|
||||
{ 8, 56, 4, 52, 11, 59, 7, 55, },
|
||||
{ 40, 24, 36, 20, 43, 27, 39, 23, },
|
||||
{ 2, 50, 14, 62, 1, 49, 13, 61, },
|
||||
{ 34, 18, 46, 30, 33, 17, 45, 29, },
|
||||
{ 10, 58, 6, 54, 9, 57, 5, 53, },
|
||||
{ 42, 26, 38, 22, 41, 25, 37, 21, },
|
||||
};
|
||||
|
||||
static const uint8_t offset[127][2]= {
|
||||
{0,0},
|
||||
{0,0}, {4,4},
|
||||
{0,0}, {2,2}, {6,4}, {4,6},
|
||||
{0,0}, {5,1}, {2,2}, {7,3}, {4,4}, {1,5}, {6,6}, {3,7},
|
||||
|
||||
{0,0}, {4,0}, {1,1}, {5,1}, {3,2}, {7,2}, {2,3}, {6,3},
|
||||
{0,4}, {4,4}, {1,5}, {5,5}, {3,6}, {7,6}, {2,7}, {6,7},
|
||||
|
||||
{0,0}, {0,2}, {0,4}, {0,6}, {1,1}, {1,3}, {1,5}, {1,7},
|
||||
{2,0}, {2,2}, {2,4}, {2,6}, {3,1}, {3,3}, {3,5}, {3,7},
|
||||
{4,0}, {4,2}, {4,4}, {4,6}, {5,1}, {5,3}, {5,5}, {5,7},
|
||||
{6,0}, {6,2}, {6,4}, {6,6}, {7,1}, {7,3}, {7,5}, {7,7},
|
||||
|
||||
{0,0}, {4,4}, {0,4}, {4,0}, {2,2}, {6,6}, {2,6}, {6,2},
|
||||
{0,2}, {4,6}, {0,6}, {4,2}, {2,0}, {6,4}, {2,4}, {6,0},
|
||||
{1,1}, {5,5}, {1,5}, {5,1}, {3,3}, {7,7}, {3,7}, {7,3},
|
||||
{1,3}, {5,7}, {1,7}, {5,3}, {3,1}, {7,5}, {3,5}, {7,1},
|
||||
{0,1}, {4,5}, {0,5}, {4,1}, {2,3}, {6,7}, {2,7}, {6,3},
|
||||
{0,3}, {4,7}, {0,7}, {4,3}, {2,1}, {6,5}, {2,5}, {6,1},
|
||||
{1,0}, {5,4}, {1,4}, {5,0}, {3,2}, {7,6}, {3,6}, {7,2},
|
||||
{1,2}, {5,6}, {1,6}, {5,2}, {3,0}, {7,4}, {3,4}, {7,0},
|
||||
};
|
||||
|
||||
struct vf_priv_s {
|
||||
int log2_count;
|
||||
int qp;
|
||||
int mode;
|
||||
int mpeg2;
|
||||
int temp_stride;
|
||||
uint8_t *src;
|
||||
int16_t *temp;
|
||||
AVCodecContext *avctx;
|
||||
DSPContext dsp;
|
||||
char *non_b_qp;
|
||||
};
|
||||
|
||||
#define SHIFT 22
|
||||
|
||||
static void hardthresh_c(DCTELEM dst[64], DCTELEM src[64], int qp, uint8_t *permutation){
|
||||
int i;
|
||||
int bias= 0; //FIXME
|
||||
unsigned int threshold1, threshold2;
|
||||
|
||||
threshold1= qp*((1<<4) - bias) - 1;
|
||||
threshold2= (threshold1<<1);
|
||||
|
||||
memset(dst, 0, 64*sizeof(DCTELEM));
|
||||
dst[0]= (src[0] + 4)>>3;
|
||||
|
||||
for(i=1; i<64; i++){
|
||||
int level= src[i];
|
||||
if(((unsigned)(level+threshold1))>threshold2){
|
||||
const int j= permutation[i];
|
||||
dst[j]= (level + 4)>>3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void softthresh_c(DCTELEM dst[64], DCTELEM src[64], int qp, uint8_t *permutation){
|
||||
int i;
|
||||
int bias= 0; //FIXME
|
||||
unsigned int threshold1, threshold2;
|
||||
|
||||
threshold1= qp*((1<<4) - bias) - 1;
|
||||
threshold2= (threshold1<<1);
|
||||
|
||||
memset(dst, 0, 64*sizeof(DCTELEM));
|
||||
dst[0]= (src[0] + 4)>>3;
|
||||
|
||||
for(i=1; i<64; i++){
|
||||
int level= src[i];
|
||||
if(((unsigned)(level+threshold1))>threshold2){
|
||||
const int j= permutation[i];
|
||||
if(level>0)
|
||||
dst[j]= (level - threshold1 + 4)>>3;
|
||||
else
|
||||
dst[j]= (level + threshold1 + 4)>>3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_MMX
|
||||
static void hardthresh_mmx(DCTELEM dst[64], DCTELEM src[64], int qp, uint8_t *permutation){
|
||||
int bias= 0; //FIXME
|
||||
unsigned int threshold1;
|
||||
|
||||
threshold1= qp*((1<<4) - bias) - 1;
|
||||
|
||||
__asm__ volatile(
|
||||
#define REQUANT_CORE(dst0, dst1, dst2, dst3, src0, src1, src2, src3) \
|
||||
"movq " #src0 ", %%mm0 \n\t"\
|
||||
"movq " #src1 ", %%mm1 \n\t"\
|
||||
"movq " #src2 ", %%mm2 \n\t"\
|
||||
"movq " #src3 ", %%mm3 \n\t"\
|
||||
"psubw %%mm4, %%mm0 \n\t"\
|
||||
"psubw %%mm4, %%mm1 \n\t"\
|
||||
"psubw %%mm4, %%mm2 \n\t"\
|
||||
"psubw %%mm4, %%mm3 \n\t"\
|
||||
"paddusw %%mm5, %%mm0 \n\t"\
|
||||
"paddusw %%mm5, %%mm1 \n\t"\
|
||||
"paddusw %%mm5, %%mm2 \n\t"\
|
||||
"paddusw %%mm5, %%mm3 \n\t"\
|
||||
"paddw %%mm6, %%mm0 \n\t"\
|
||||
"paddw %%mm6, %%mm1 \n\t"\
|
||||
"paddw %%mm6, %%mm2 \n\t"\
|
||||
"paddw %%mm6, %%mm3 \n\t"\
|
||||
"psubusw %%mm6, %%mm0 \n\t"\
|
||||
"psubusw %%mm6, %%mm1 \n\t"\
|
||||
"psubusw %%mm6, %%mm2 \n\t"\
|
||||
"psubusw %%mm6, %%mm3 \n\t"\
|
||||
"psraw $3, %%mm0 \n\t"\
|
||||
"psraw $3, %%mm1 \n\t"\
|
||||
"psraw $3, %%mm2 \n\t"\
|
||||
"psraw $3, %%mm3 \n\t"\
|
||||
\
|
||||
"movq %%mm0, %%mm7 \n\t"\
|
||||
"punpcklwd %%mm2, %%mm0 \n\t" /*A*/\
|
||||
"punpckhwd %%mm2, %%mm7 \n\t" /*C*/\
|
||||
"movq %%mm1, %%mm2 \n\t"\
|
||||
"punpcklwd %%mm3, %%mm1 \n\t" /*B*/\
|
||||
"punpckhwd %%mm3, %%mm2 \n\t" /*D*/\
|
||||
"movq %%mm0, %%mm3 \n\t"\
|
||||
"punpcklwd %%mm1, %%mm0 \n\t" /*A*/\
|
||||
"punpckhwd %%mm7, %%mm3 \n\t" /*C*/\
|
||||
"punpcklwd %%mm2, %%mm7 \n\t" /*B*/\
|
||||
"punpckhwd %%mm2, %%mm1 \n\t" /*D*/\
|
||||
\
|
||||
"movq %%mm0, " #dst0 " \n\t"\
|
||||
"movq %%mm7, " #dst1 " \n\t"\
|
||||
"movq %%mm3, " #dst2 " \n\t"\
|
||||
"movq %%mm1, " #dst3 " \n\t"
|
||||
|
||||
"movd %2, %%mm4 \n\t"
|
||||
"movd %3, %%mm5 \n\t"
|
||||
"movd %4, %%mm6 \n\t"
|
||||
"packssdw %%mm4, %%mm4 \n\t"
|
||||
"packssdw %%mm5, %%mm5 \n\t"
|
||||
"packssdw %%mm6, %%mm6 \n\t"
|
||||
"packssdw %%mm4, %%mm4 \n\t"
|
||||
"packssdw %%mm5, %%mm5 \n\t"
|
||||
"packssdw %%mm6, %%mm6 \n\t"
|
||||
REQUANT_CORE( (%1), 8(%1), 16(%1), 24(%1), (%0), 8(%0), 64(%0), 72(%0))
|
||||
REQUANT_CORE(32(%1), 40(%1), 48(%1), 56(%1),16(%0),24(%0), 48(%0), 56(%0))
|
||||
REQUANT_CORE(64(%1), 72(%1), 80(%1), 88(%1),32(%0),40(%0), 96(%0),104(%0))
|
||||
REQUANT_CORE(96(%1),104(%1),112(%1),120(%1),80(%0),88(%0),112(%0),120(%0))
|
||||
: : "r" (src), "r" (dst), "g" (threshold1+1), "g" (threshold1+5), "g" (threshold1-4) //FIXME maybe more accurate then needed?
|
||||
);
|
||||
dst[0]= (src[0] + 4)>>3;
|
||||
}
|
||||
|
||||
static void softthresh_mmx(DCTELEM dst[64], DCTELEM src[64], int qp, uint8_t *permutation){
|
||||
int bias= 0; //FIXME
|
||||
unsigned int threshold1;
|
||||
|
||||
threshold1= qp*((1<<4) - bias) - 1;
|
||||
|
||||
__asm__ volatile(
|
||||
#undef REQUANT_CORE
|
||||
#define REQUANT_CORE(dst0, dst1, dst2, dst3, src0, src1, src2, src3) \
|
||||
"movq " #src0 ", %%mm0 \n\t"\
|
||||
"movq " #src1 ", %%mm1 \n\t"\
|
||||
"pxor %%mm6, %%mm6 \n\t"\
|
||||
"pxor %%mm7, %%mm7 \n\t"\
|
||||
"pcmpgtw %%mm0, %%mm6 \n\t"\
|
||||
"pcmpgtw %%mm1, %%mm7 \n\t"\
|
||||
"pxor %%mm6, %%mm0 \n\t"\
|
||||
"pxor %%mm7, %%mm1 \n\t"\
|
||||
"psubusw %%mm4, %%mm0 \n\t"\
|
||||
"psubusw %%mm4, %%mm1 \n\t"\
|
||||
"pxor %%mm6, %%mm0 \n\t"\
|
||||
"pxor %%mm7, %%mm1 \n\t"\
|
||||
"movq " #src2 ", %%mm2 \n\t"\
|
||||
"movq " #src3 ", %%mm3 \n\t"\
|
||||
"pxor %%mm6, %%mm6 \n\t"\
|
||||
"pxor %%mm7, %%mm7 \n\t"\
|
||||
"pcmpgtw %%mm2, %%mm6 \n\t"\
|
||||
"pcmpgtw %%mm3, %%mm7 \n\t"\
|
||||
"pxor %%mm6, %%mm2 \n\t"\
|
||||
"pxor %%mm7, %%mm3 \n\t"\
|
||||
"psubusw %%mm4, %%mm2 \n\t"\
|
||||
"psubusw %%mm4, %%mm3 \n\t"\
|
||||
"pxor %%mm6, %%mm2 \n\t"\
|
||||
"pxor %%mm7, %%mm3 \n\t"\
|
||||
\
|
||||
"paddsw %%mm5, %%mm0 \n\t"\
|
||||
"paddsw %%mm5, %%mm1 \n\t"\
|
||||
"paddsw %%mm5, %%mm2 \n\t"\
|
||||
"paddsw %%mm5, %%mm3 \n\t"\
|
||||
"psraw $3, %%mm0 \n\t"\
|
||||
"psraw $3, %%mm1 \n\t"\
|
||||
"psraw $3, %%mm2 \n\t"\
|
||||
"psraw $3, %%mm3 \n\t"\
|
||||
\
|
||||
"movq %%mm0, %%mm7 \n\t"\
|
||||
"punpcklwd %%mm2, %%mm0 \n\t" /*A*/\
|
||||
"punpckhwd %%mm2, %%mm7 \n\t" /*C*/\
|
||||
"movq %%mm1, %%mm2 \n\t"\
|
||||
"punpcklwd %%mm3, %%mm1 \n\t" /*B*/\
|
||||
"punpckhwd %%mm3, %%mm2 \n\t" /*D*/\
|
||||
"movq %%mm0, %%mm3 \n\t"\
|
||||
"punpcklwd %%mm1, %%mm0 \n\t" /*A*/\
|
||||
"punpckhwd %%mm7, %%mm3 \n\t" /*C*/\
|
||||
"punpcklwd %%mm2, %%mm7 \n\t" /*B*/\
|
||||
"punpckhwd %%mm2, %%mm1 \n\t" /*D*/\
|
||||
\
|
||||
"movq %%mm0, " #dst0 " \n\t"\
|
||||
"movq %%mm7, " #dst1 " \n\t"\
|
||||
"movq %%mm3, " #dst2 " \n\t"\
|
||||
"movq %%mm1, " #dst3 " \n\t"
|
||||
|
||||
"movd %2, %%mm4 \n\t"
|
||||
"movd %3, %%mm5 \n\t"
|
||||
"packssdw %%mm4, %%mm4 \n\t"
|
||||
"packssdw %%mm5, %%mm5 \n\t"
|
||||
"packssdw %%mm4, %%mm4 \n\t"
|
||||
"packssdw %%mm5, %%mm5 \n\t"
|
||||
REQUANT_CORE( (%1), 8(%1), 16(%1), 24(%1), (%0), 8(%0), 64(%0), 72(%0))
|
||||
REQUANT_CORE(32(%1), 40(%1), 48(%1), 56(%1),16(%0),24(%0), 48(%0), 56(%0))
|
||||
REQUANT_CORE(64(%1), 72(%1), 80(%1), 88(%1),32(%0),40(%0), 96(%0),104(%0))
|
||||
REQUANT_CORE(96(%1),104(%1),112(%1),120(%1),80(%0),88(%0),112(%0),120(%0))
|
||||
: : "r" (src), "r" (dst), "g" (threshold1), "rm" (4) //FIXME maybe more accurate then needed?
|
||||
);
|
||||
|
||||
dst[0]= (src[0] + 4)>>3;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void add_block(int16_t *dst, int stride, DCTELEM block[64]){
|
||||
int y;
|
||||
|
||||
for(y=0; y<8; y++){
|
||||
*(uint32_t*)&dst[0 + y*stride]+= *(uint32_t*)&block[0 + y*8];
|
||||
*(uint32_t*)&dst[2 + y*stride]+= *(uint32_t*)&block[2 + y*8];
|
||||
*(uint32_t*)&dst[4 + y*stride]+= *(uint32_t*)&block[4 + y*8];
|
||||
*(uint32_t*)&dst[6 + y*stride]+= *(uint32_t*)&block[6 + y*8];
|
||||
}
|
||||
}
|
||||
|
||||
static void store_slice_c(uint8_t *dst, int16_t *src, int dst_stride, int src_stride, int width, int height, int log2_scale){
|
||||
int y, x;
|
||||
|
||||
#define STORE(pos) \
|
||||
temp= ((src[x + y*src_stride + pos]<<log2_scale) + d[pos])>>6;\
|
||||
if(temp & 0x100) temp= ~(temp>>31);\
|
||||
dst[x + y*dst_stride + pos]= temp;
|
||||
|
||||
for(y=0; y<height; y++){
|
||||
const uint8_t *d= dither[y];
|
||||
for(x=0; x<width; x+=8){
|
||||
int temp;
|
||||
STORE(0);
|
||||
STORE(1);
|
||||
STORE(2);
|
||||
STORE(3);
|
||||
STORE(4);
|
||||
STORE(5);
|
||||
STORE(6);
|
||||
STORE(7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_MMX
|
||||
static void store_slice_mmx(uint8_t *dst, int16_t *src, int dst_stride, int src_stride, int width, int height, int log2_scale){
|
||||
int y;
|
||||
|
||||
for(y=0; y<height; y++){
|
||||
uint8_t *dst1= dst;
|
||||
int16_t *src1= src;
|
||||
__asm__ volatile(
|
||||
"movq (%3), %%mm3 \n\t"
|
||||
"movq (%3), %%mm4 \n\t"
|
||||
"movd %4, %%mm2 \n\t"
|
||||
"pxor %%mm0, %%mm0 \n\t"
|
||||
"punpcklbw %%mm0, %%mm3 \n\t"
|
||||
"punpckhbw %%mm0, %%mm4 \n\t"
|
||||
"psraw %%mm2, %%mm3 \n\t"
|
||||
"psraw %%mm2, %%mm4 \n\t"
|
||||
"movd %5, %%mm2 \n\t"
|
||||
"1: \n\t"
|
||||
"movq (%0), %%mm0 \n\t"
|
||||
"movq 8(%0), %%mm1 \n\t"
|
||||
"paddw %%mm3, %%mm0 \n\t"
|
||||
"paddw %%mm4, %%mm1 \n\t"
|
||||
"psraw %%mm2, %%mm0 \n\t"
|
||||
"psraw %%mm2, %%mm1 \n\t"
|
||||
"packuswb %%mm1, %%mm0 \n\t"
|
||||
"movq %%mm0, (%1) \n\t"
|
||||
"add $16, %0 \n\t"
|
||||
"add $8, %1 \n\t"
|
||||
"cmp %2, %1 \n\t"
|
||||
" jb 1b \n\t"
|
||||
: "+r" (src1), "+r"(dst1)
|
||||
: "r"(dst + width), "r"(dither[y]), "g"(log2_scale), "g"(6-log2_scale)
|
||||
);
|
||||
src += src_stride;
|
||||
dst += dst_stride;
|
||||
}
|
||||
// if(width != mmxw)
|
||||
// store_slice_c(dst + mmxw, src + mmxw, dst_stride, src_stride, width - mmxw, log2_scale);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void (*store_slice)(uint8_t *dst, int16_t *src, int dst_stride, int src_stride, int width, int height, int log2_scale)= store_slice_c;
|
||||
|
||||
static void (*requantize)(DCTELEM dst[64], DCTELEM src[64], int qp, uint8_t *permutation)= hardthresh_c;
|
||||
|
||||
static void filter(struct vf_priv_s *p, uint8_t *dst, uint8_t *src, int dst_stride, int src_stride, int width, int height, uint8_t *qp_store, int qp_stride, int is_luma){
|
||||
int x, y, i;
|
||||
const int count= 1<<p->log2_count;
|
||||
const int stride= is_luma ? p->temp_stride : ((width+16+15)&(~15));
|
||||
uint64_t __attribute__((aligned(16))) block_align[32];
|
||||
DCTELEM *block = (DCTELEM *)block_align;
|
||||
DCTELEM *block2= (DCTELEM *)(block_align+16);
|
||||
|
||||
if (!src || !dst) return; // HACK avoid crash for Y8 colourspace
|
||||
for(y=0; y<height; y++){
|
||||
int index= 8 + 8*stride + y*stride;
|
||||
fast_memcpy(p->src + index, src + y*src_stride, width);
|
||||
for(x=0; x<8; x++){
|
||||
p->src[index - x - 1]= p->src[index + x ];
|
||||
p->src[index + width + x ]= p->src[index + width - x - 1];
|
||||
}
|
||||
}
|
||||
for(y=0; y<8; y++){
|
||||
fast_memcpy(p->src + ( 7-y)*stride, p->src + ( y+8)*stride, stride);
|
||||
fast_memcpy(p->src + (height+8+y)*stride, p->src + (height-y+7)*stride, stride);
|
||||
}
|
||||
//FIXME (try edge emu)
|
||||
|
||||
for(y=0; y<height+8; y+=8){
|
||||
memset(p->temp + (8+y)*stride, 0, 8*stride*sizeof(int16_t));
|
||||
for(x=0; x<width+8; x+=8){
|
||||
const int qps= 3 + is_luma;
|
||||
int qp;
|
||||
|
||||
if(p->qp)
|
||||
qp= p->qp;
|
||||
else{
|
||||
qp= qp_store[ (XMIN(x, width-1)>>qps) + (XMIN(y, height-1)>>qps) * qp_stride];
|
||||
qp = FFMAX(1, norm_qscale(qp, p->mpeg2));
|
||||
}
|
||||
for(i=0; i<count; i++){
|
||||
const int x1= x + offset[i+count-1][0];
|
||||
const int y1= y + offset[i+count-1][1];
|
||||
const int index= x1 + y1*stride;
|
||||
p->dsp.get_pixels(block, p->src + index, stride);
|
||||
p->dsp.fdct(block);
|
||||
requantize(block2, block, qp, p->dsp.idct_permutation);
|
||||
p->dsp.idct(block2);
|
||||
add_block(p->temp + index, stride, block2);
|
||||
}
|
||||
}
|
||||
if(y)
|
||||
store_slice(dst + (y-8)*dst_stride, p->temp + 8 + y*stride, dst_stride, stride, width, XMIN(8, height+8-y), 6-p->log2_count);
|
||||
}
|
||||
#if 0
|
||||
for(y=0; y<height; y++){
|
||||
for(x=0; x<width; x++){
|
||||
if((((x>>6) ^ (y>>6)) & 1) == 0)
|
||||
dst[x + y*dst_stride]= p->src[8 + 8*stride + x + y*stride];
|
||||
if((x&63) == 0 || (y&63)==0)
|
||||
dst[x + y*dst_stride] += 128;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//FIXME reorder for better caching
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
int h= (height+16+15)&(~15);
|
||||
|
||||
vf->priv->temp_stride= (width+16+15)&(~15);
|
||||
vf->priv->temp= malloc(vf->priv->temp_stride*h*sizeof(int16_t));
|
||||
vf->priv->src = malloc(vf->priv->temp_stride*h*sizeof(uint8_t));
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static void get_image(struct vf_instance *vf, mp_image_t *mpi){
|
||||
if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
|
||||
// ok, we can do pp in-place (or pp disabled):
|
||||
vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height);
|
||||
mpi->planes[0]=vf->dmpi->planes[0];
|
||||
mpi->stride[0]=vf->dmpi->stride[0];
|
||||
mpi->width=vf->dmpi->width;
|
||||
if(mpi->flags&MP_IMGFLAG_PLANAR){
|
||||
mpi->planes[1]=vf->dmpi->planes[1];
|
||||
mpi->planes[2]=vf->dmpi->planes[2];
|
||||
mpi->stride[1]=vf->dmpi->stride[1];
|
||||
mpi->stride[2]=vf->dmpi->stride[2];
|
||||
}
|
||||
mpi->flags|=MP_IMGFLAG_DIRECT;
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
|
||||
if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
|
||||
// no DR, so get a new image! hope we'll get DR buffer:
|
||||
dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP,
|
||||
MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
|
||||
mpi->width,mpi->height);
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
}else{
|
||||
dmpi=vf->dmpi;
|
||||
}
|
||||
|
||||
vf->priv->mpeg2= mpi->qscale_type;
|
||||
if(mpi->pict_type != 3 && mpi->qscale && !vf->priv->qp){
|
||||
int w = mpi->qstride;
|
||||
int h = (mpi->h + 15) >> 4;
|
||||
if (!w) {
|
||||
w = (mpi->w + 15) >> 4;
|
||||
h = 1;
|
||||
}
|
||||
if(!vf->priv->non_b_qp)
|
||||
vf->priv->non_b_qp= malloc(w*h);
|
||||
fast_memcpy(vf->priv->non_b_qp, mpi->qscale, w*h);
|
||||
}
|
||||
if(vf->priv->log2_count || !(mpi->flags&MP_IMGFLAG_DIRECT)){
|
||||
char *qp_tab= vf->priv->non_b_qp;
|
||||
if((vf->priv->mode&4) || !qp_tab)
|
||||
qp_tab= mpi->qscale;
|
||||
|
||||
if(qp_tab || vf->priv->qp){
|
||||
filter(vf->priv, dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, qp_tab, mpi->qstride, 1);
|
||||
filter(vf->priv, dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, qp_tab, mpi->qstride, 0);
|
||||
filter(vf->priv, dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, qp_tab, mpi->qstride, 0);
|
||||
}else{
|
||||
memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h, dmpi->stride[0], mpi->stride[0]);
|
||||
memcpy_pic(dmpi->planes[1], mpi->planes[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[1], mpi->stride[1]);
|
||||
memcpy_pic(dmpi->planes[2], mpi->planes[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[2], mpi->stride[2]);
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_MMX
|
||||
if(gCpuCaps.hasMMX) __asm__ volatile ("emms\n\t");
|
||||
#endif
|
||||
#if HAVE_MMX2
|
||||
if(gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
|
||||
#endif
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf){
|
||||
if(!vf->priv) return;
|
||||
|
||||
free(vf->priv->temp);
|
||||
vf->priv->temp= NULL;
|
||||
free(vf->priv->src);
|
||||
vf->priv->src= NULL;
|
||||
free(vf->priv->avctx);
|
||||
vf->priv->avctx= NULL;
|
||||
free(vf->priv->non_b_qp);
|
||||
vf->priv->non_b_qp= NULL;
|
||||
|
||||
free(vf->priv);
|
||||
vf->priv=NULL;
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
switch(fmt){
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_IF09:
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_CLPL:
|
||||
case IMGFMT_Y800:
|
||||
case IMGFMT_Y8:
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
return vf_next_query_format(vf,fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int control(struct vf_instance *vf, int request, void* data){
|
||||
switch(request){
|
||||
case VFCTRL_QUERY_MAX_PP_LEVEL:
|
||||
return 6;
|
||||
case VFCTRL_SET_PP_LEVEL:
|
||||
vf->priv->log2_count= *((unsigned int*)data);
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
return vf_next_control(vf,request,data);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
|
||||
int log2c=-1;
|
||||
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->get_image=get_image;
|
||||
vf->query_format=query_format;
|
||||
vf->uninit=uninit;
|
||||
vf->control= control;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
|
||||
init_avcodec();
|
||||
|
||||
vf->priv->avctx= avcodec_alloc_context();
|
||||
dsputil_init(&vf->priv->dsp, vf->priv->avctx);
|
||||
|
||||
vf->priv->log2_count= 3;
|
||||
|
||||
if (args) sscanf(args, "%d:%d:%d", &log2c, &vf->priv->qp, &vf->priv->mode);
|
||||
|
||||
if( log2c >=0 && log2c <=6 )
|
||||
vf->priv->log2_count = log2c;
|
||||
|
||||
if(vf->priv->qp < 0)
|
||||
vf->priv->qp = 0;
|
||||
|
||||
switch(vf->priv->mode&3){
|
||||
default:
|
||||
case 0: requantize= hardthresh_c; break;
|
||||
case 1: requantize= softthresh_c; break;
|
||||
}
|
||||
|
||||
#if HAVE_MMX
|
||||
if(gCpuCaps.hasMMX){
|
||||
store_slice= store_slice_mmx;
|
||||
switch(vf->priv->mode&3){
|
||||
case 0: requantize= hardthresh_mmx; break;
|
||||
case 1: requantize= softthresh_mmx; break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_spp = {
|
||||
"simple postprocess",
|
||||
"spp",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
106
libavfilter/libmpcodecs/vf_swapuv.c
Normal file
106
libavfilter/libmpcodecs/vf_swapuv.c
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mp_msg.h"
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static void get_image(struct vf_instance *vf, mp_image_t *mpi){
|
||||
mp_image_t *dmpi= vf_get_image(vf->next, mpi->imgfmt,
|
||||
mpi->type, mpi->flags, mpi->w, mpi->h);
|
||||
|
||||
mpi->planes[0]=dmpi->planes[0];
|
||||
mpi->planes[1]=dmpi->planes[2];
|
||||
mpi->planes[2]=dmpi->planes[1];
|
||||
mpi->stride[0]=dmpi->stride[0];
|
||||
mpi->stride[1]=dmpi->stride[2];
|
||||
mpi->stride[2]=dmpi->stride[1];
|
||||
mpi->width=dmpi->width;
|
||||
|
||||
mpi->flags|=MP_IMGFLAG_DIRECT;
|
||||
mpi->priv=(void*)dmpi;
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
|
||||
if(mpi->flags&MP_IMGFLAG_DIRECT){
|
||||
dmpi=(mp_image_t*)mpi->priv;
|
||||
} else {
|
||||
dmpi=vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_EXPORT, 0, mpi->w, mpi->h);
|
||||
assert(mpi->flags&MP_IMGFLAG_PLANAR);
|
||||
dmpi->planes[0]=mpi->planes[0];
|
||||
dmpi->planes[1]=mpi->planes[2];
|
||||
dmpi->planes[2]=mpi->planes[1];
|
||||
dmpi->stride[0]=mpi->stride[0];
|
||||
dmpi->stride[1]=mpi->stride[2];
|
||||
dmpi->stride[2]=mpi->stride[1];
|
||||
dmpi->width=mpi->width;
|
||||
}
|
||||
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
switch(fmt)
|
||||
{
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
vf->put_image=put_image;
|
||||
vf->get_image=get_image;
|
||||
vf->query_format=query_format;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_swapuv = {
|
||||
"UV swapper",
|
||||
"swapuv",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
155
libavfilter/libmpcodecs/vf_telecine.c
Normal file
155
libavfilter/libmpcodecs/vf_telecine.c
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
int frame;
|
||||
};
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
mp_image_t *dmpi;
|
||||
int ret;
|
||||
|
||||
vf->priv->frame = (vf->priv->frame+1)%4;
|
||||
|
||||
dmpi = vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
|
||||
MP_IMGFLAG_PRESERVE, mpi->width, mpi->height);
|
||||
|
||||
ret = 0;
|
||||
// 0/0 1/1 2/2 2/3 3/0
|
||||
switch (vf->priv->frame) {
|
||||
case 0:
|
||||
my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
|
||||
mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2,
|
||||
dmpi->stride[0]*2, mpi->stride[0]*2);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
|
||||
mpi->planes[1]+mpi->stride[1],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[1]*2, mpi->stride[1]*2);
|
||||
my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
|
||||
mpi->planes[2]+mpi->stride[2],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[2]*2, mpi->stride[2]*2);
|
||||
}
|
||||
ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
|
||||
case 1:
|
||||
case 2:
|
||||
memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
|
||||
dmpi->stride[0], mpi->stride[0]);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
memcpy_pic(dmpi->planes[1], mpi->planes[1],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[1], mpi->stride[1]);
|
||||
memcpy_pic(dmpi->planes[2], mpi->planes[2],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[2], mpi->stride[2]);
|
||||
}
|
||||
return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE) || ret;
|
||||
case 3:
|
||||
my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
|
||||
mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2,
|
||||
dmpi->stride[0]*2, mpi->stride[0]*2);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
|
||||
mpi->planes[1]+mpi->stride[1],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[1]*2, mpi->stride[1]*2);
|
||||
my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
|
||||
mpi->planes[2]+mpi->stride[2],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[2]*2, mpi->stride[2]*2);
|
||||
}
|
||||
ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
|
||||
my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2,
|
||||
dmpi->stride[0]*2, mpi->stride[0]*2);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
my_memcpy_pic(dmpi->planes[1], mpi->planes[1],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[1]*2, mpi->stride[1]*2);
|
||||
my_memcpy_pic(dmpi->planes[2], mpi->planes[2],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[2]*2, mpi->stride[2]*2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt)
|
||||
{
|
||||
/* FIXME - figure out which other formats work */
|
||||
switch (fmt) {
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_I420:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt)
|
||||
{
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
//vf->config = config;
|
||||
vf->put_image = put_image;
|
||||
//vf->query_format = query_format;
|
||||
vf->uninit = uninit;
|
||||
vf->default_reqs = VFCAP_ACCEPT_STRIDE;
|
||||
vf->priv = calloc(1, sizeof(struct vf_priv_s));
|
||||
vf->priv->frame = 1;
|
||||
if (args) sscanf(args, "%d", &vf->priv->frame);
|
||||
vf->priv->frame--;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_telecine = {
|
||||
"telecine filter",
|
||||
"telecine",
|
||||
"Rich Felker",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
333
libavfilter/libmpcodecs/vf_test.c
Normal file
333
libavfilter/libmpcodecs/vf_test.c
Normal file
@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "help_mp.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define ABS(a,b) ((a) > 0 ? (a) : -(a))
|
||||
|
||||
#define WIDTH 512
|
||||
#define HEIGHT 512
|
||||
|
||||
struct vf_priv_s {
|
||||
int frame_num;
|
||||
};
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
|
||||
if(vf_next_query_format(vf,IMGFMT_YV12)<=0){
|
||||
mp_msg(MSGT_VFILTER, MSGL_WARN, MSGTR_MPCODECS_WarnNextFilterDoesntSupport, "YV12");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//hmm whats the meaning of these ... ;)
|
||||
d_width= width= WIDTH;
|
||||
d_height= height= HEIGHT;
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,IMGFMT_YV12);
|
||||
}
|
||||
|
||||
static double c[64];
|
||||
|
||||
static void initIdct(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
double s= i==0 ? sqrt(0.125) : 0.5;
|
||||
int j;
|
||||
|
||||
for(j=0; j<8; j++)
|
||||
c[i*8+j]= s*cos((3.141592654/8.0)*i*(j+0.5));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void idct(uint8_t *dst, int dstStride, int src[64])
|
||||
{
|
||||
int i, j, k;
|
||||
double tmp[64];
|
||||
|
||||
for(i=0; i<8; i++)
|
||||
{
|
||||
for(j=0; j<8; j++)
|
||||
{
|
||||
double sum= 0.0;
|
||||
|
||||
for(k=0; k<8; k++)
|
||||
sum+= c[k*8+j]*src[8*i+k];
|
||||
|
||||
tmp[8*i+j]= sum;
|
||||
}
|
||||
}
|
||||
|
||||
for(j=0; j<8; j++)
|
||||
{
|
||||
for(i=0; i<8; i++)
|
||||
{
|
||||
int v;
|
||||
double sum= 0.0;
|
||||
|
||||
for(k=0; k<8; k++)
|
||||
sum+= c[k*8+i]*tmp[8*k+j];
|
||||
|
||||
v= (int)floor(sum+0.5);
|
||||
if(v<0) v=0;
|
||||
else if(v>255) v=255;
|
||||
|
||||
dst[dstStride*i + j] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void drawDc(uint8_t *dst, int stride, int color, int w, int h)
|
||||
{
|
||||
int y;
|
||||
for(y=0; y<h; y++)
|
||||
{
|
||||
int x;
|
||||
for(x=0; x<w; x++)
|
||||
{
|
||||
dst[x + y*stride]= color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void drawBasis(uint8_t *dst, int stride, int amp, int freq, int dc)
|
||||
{
|
||||
int src[64];
|
||||
|
||||
memset(src, 0, 64*sizeof(int));
|
||||
src[0]= dc;
|
||||
if(amp) src[freq]= amp;
|
||||
idct(dst, stride, src);
|
||||
}
|
||||
|
||||
static void drawCbp(uint8_t *dst[3], int stride[3], int cbp, int amp, int dc)
|
||||
{
|
||||
if(cbp&1) drawBasis(dst[0] , stride[0], amp, 1, dc);
|
||||
if(cbp&2) drawBasis(dst[0]+8 , stride[0], amp, 1, dc);
|
||||
if(cbp&4) drawBasis(dst[0]+ 8*stride[0], stride[0], amp, 1, dc);
|
||||
if(cbp&8) drawBasis(dst[0]+8+8*stride[0], stride[0], amp, 1, dc);
|
||||
if(cbp&16)drawBasis(dst[1] , stride[1], amp, 1, dc);
|
||||
if(cbp&32)drawBasis(dst[2] , stride[2], amp, 1, dc);
|
||||
}
|
||||
|
||||
static void dc1Test(uint8_t *dst, int stride, int w, int h, int off)
|
||||
{
|
||||
const int step= MAX(256/(w*h/256), 1);
|
||||
int y;
|
||||
int color=off;
|
||||
for(y=0; y<h; y+=16)
|
||||
{
|
||||
int x;
|
||||
for(x=0; x<w; x+=16)
|
||||
{
|
||||
drawDc(dst + x + y*stride, stride, color, 8, 8);
|
||||
color+=step;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void freq1Test(uint8_t *dst, int stride, int off)
|
||||
{
|
||||
int y;
|
||||
int freq=0;
|
||||
for(y=0; y<8*16; y+=16)
|
||||
{
|
||||
int x;
|
||||
for(x=0; x<8*16; x+=16)
|
||||
{
|
||||
drawBasis(dst + x + y*stride, stride, 4*(96+off), freq, 128*8);
|
||||
freq++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void amp1Test(uint8_t *dst, int stride, int off)
|
||||
{
|
||||
int y;
|
||||
int amp=off;
|
||||
for(y=0; y<16*16; y+=16)
|
||||
{
|
||||
int x;
|
||||
for(x=0; x<16*16; x+=16)
|
||||
{
|
||||
drawBasis(dst + x + y*stride, stride, 4*(amp), 1, 128*8);
|
||||
amp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cbp1Test(uint8_t *dst[3], int stride[3], int off)
|
||||
{
|
||||
int y;
|
||||
int cbp=0;
|
||||
for(y=0; y<16*8; y+=16)
|
||||
{
|
||||
int x;
|
||||
for(x=0; x<16*8; x+=16)
|
||||
{
|
||||
uint8_t *dst1[3];
|
||||
dst1[0]= dst[0] + x*2 + y*2*stride[0];
|
||||
dst1[1]= dst[1] + x + y*stride[1];
|
||||
dst1[2]= dst[2] + x + y*stride[2];
|
||||
|
||||
drawCbp(dst1, stride, cbp, (64+off)*4, 128*8);
|
||||
cbp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mv1Test(uint8_t *dst, int stride, int off)
|
||||
{
|
||||
int y;
|
||||
for(y=0; y<16*16; y++)
|
||||
{
|
||||
int x;
|
||||
if(y&16) continue;
|
||||
for(x=0; x<16*16; x++)
|
||||
{
|
||||
dst[x + y*stride]= x + off*8/(y/32+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ring1Test(uint8_t *dst, int stride, int off)
|
||||
{
|
||||
int y;
|
||||
int color=0;
|
||||
for(y=off; y<16*16; y+=16)
|
||||
{
|
||||
int x;
|
||||
for(x=off; x<16*16; x+=16)
|
||||
{
|
||||
drawDc(dst + x + y*stride, stride, ((x+y)&16) ? color : -color, 16, 16);
|
||||
// dst[x + y*stride]= 255 + (off&1);
|
||||
color++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ring2Test(uint8_t *dst, int stride, int off)
|
||||
{
|
||||
int y;
|
||||
for(y=0; y<16*16; y++)
|
||||
{
|
||||
int x;
|
||||
for(x=0; x<16*16; x++)
|
||||
{
|
||||
double d= sqrt((x-8*16)*(x-8*16) + (y-8*16)*(y-8*16));
|
||||
double r= d/20 - (int)(d/20);
|
||||
if(r<off/30.0)
|
||||
{
|
||||
dst[x + y*stride]= 255;
|
||||
dst[x + y*stride+256]= 0;
|
||||
}
|
||||
else{
|
||||
dst[x + y*stride]= x;
|
||||
dst[x + y*stride+256]= x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
int frame= vf->priv->frame_num;
|
||||
|
||||
// hope we'll get DR buffer:
|
||||
dmpi=vf_get_image(vf->next,IMGFMT_YV12,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
WIDTH, HEIGHT);
|
||||
|
||||
// clean
|
||||
memset(dmpi->planes[0], 0, dmpi->stride[0]*dmpi->h);
|
||||
memset(dmpi->planes[1], 128, dmpi->stride[1]*dmpi->h>>dmpi->chroma_y_shift);
|
||||
memset(dmpi->planes[2], 128, dmpi->stride[2]*dmpi->h>>dmpi->chroma_y_shift);
|
||||
|
||||
if(frame%30)
|
||||
{
|
||||
switch(frame/30)
|
||||
{
|
||||
case 0: dc1Test(dmpi->planes[0], dmpi->stride[0], 256, 256, frame%30); break;
|
||||
case 1: dc1Test(dmpi->planes[1], dmpi->stride[1], 256, 256, frame%30); break;
|
||||
case 2: freq1Test(dmpi->planes[0], dmpi->stride[0], frame%30); break;
|
||||
case 3: freq1Test(dmpi->planes[1], dmpi->stride[1], frame%30); break;
|
||||
case 4: amp1Test(dmpi->planes[0], dmpi->stride[0], frame%30); break;
|
||||
case 5: amp1Test(dmpi->planes[1], dmpi->stride[1], frame%30); break;
|
||||
case 6: cbp1Test(dmpi->planes , dmpi->stride , frame%30); break;
|
||||
case 7: mv1Test(dmpi->planes[0], dmpi->stride[0], frame%30); break;
|
||||
case 8: ring1Test(dmpi->planes[0], dmpi->stride[0], frame%30); break;
|
||||
case 9: ring2Test(dmpi->planes[0], dmpi->stride[0], frame%30); break;
|
||||
}
|
||||
}
|
||||
|
||||
frame++;
|
||||
vf->priv->frame_num= frame;
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
return vf_next_query_format(vf,IMGFMT_YV12) & (~VFCAP_CSP_SUPPORTED_BY_HW);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->query_format=query_format;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
vf->priv->frame_num= args ? atoi(args) : 0;
|
||||
initIdct();
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_test = {
|
||||
"test pattern generator",
|
||||
"test",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
330
libavfilter/libmpcodecs/vf_tile.c
Normal file
330
libavfilter/libmpcodecs/vf_tile.c
Normal file
@ -0,0 +1,330 @@
|
||||
/*
|
||||
* filter to tile a serie of image in a single, bigger, image
|
||||
*
|
||||
* The parameters are:
|
||||
*
|
||||
* xtile: number of tile on the x axis (5)
|
||||
* ytile: number of tile on the y axis (5)
|
||||
* xytile: when write the image, it can be different then xtile * ytile
|
||||
* (for example you can write 8 * 7 tile, writing the file every
|
||||
* 50 frame, to have one image every 2 seconds @ 25 fps ).
|
||||
* start: pixel at the start (x/y), default 2
|
||||
* delta: pixel between 2 tile, (x/y), default 4
|
||||
*
|
||||
* For example a valid command line is:
|
||||
* ... -vf tile=10:5:-1:4:8 ...
|
||||
* that make images of 10 * 5 tiles, with 4 pixel at the beginning and
|
||||
* 8 pixel between tiles.
|
||||
*
|
||||
* The default command is:
|
||||
* ... -vf tile=5:5:25:2:4
|
||||
*
|
||||
* If you omit a parameter or put a value less then 0, the default is used.
|
||||
* ... -vf tile=10:5::-1:10
|
||||
*
|
||||
* You can also stop when you're ok
|
||||
* ... -vf tile=10:5
|
||||
* (and this is probably the option you will use more often ...)
|
||||
*
|
||||
* Probably is good to put the scale filter before the tile :-)
|
||||
*
|
||||
* copyright (c) 2003 Daniele Forghieri ( guru@digitalfantasy.it )
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
// strtoi memcpy_pic
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "help_mp.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
/* private data */
|
||||
struct vf_priv_s {
|
||||
/* configuration data */
|
||||
/* Number on hor/ver tiles */
|
||||
int xtile;
|
||||
int ytile;
|
||||
/* When write the whole frame (default = xtile * ytile) */
|
||||
int xytile;
|
||||
/* pixel at start / end (default = 4) */
|
||||
int start;
|
||||
/* pixel between image (default = 2) */
|
||||
int delta;
|
||||
// /* Background color, in destination format */
|
||||
// int bkgSet;
|
||||
|
||||
/* Work data */
|
||||
int frame_cur;
|
||||
};
|
||||
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
|
||||
struct vf_priv_s *priv;
|
||||
int xw;
|
||||
int yh;
|
||||
|
||||
/* Calculate new destination size */
|
||||
priv = vf->priv;
|
||||
xw = priv->start * 2 +
|
||||
priv->xtile * width +
|
||||
(priv->xtile - 1) * priv->delta;
|
||||
yh = priv->start * 2 +
|
||||
priv->ytile * height +
|
||||
(priv->ytile - 1) * priv->delta;
|
||||
|
||||
mp_msg(MSGT_VFILTER,MSGL_V,"vf_tile:config size set to %d * %d\n", xw, yh);
|
||||
|
||||
return vf_next_config(vf, xw, yh, xw, yh, flags, outfmt);
|
||||
}
|
||||
|
||||
/* Filter handler */
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
mp_image_t *dmpi;
|
||||
struct vf_priv_s *priv;
|
||||
int t;
|
||||
int xw;
|
||||
int yh;
|
||||
int xi;
|
||||
int yi;
|
||||
int by;
|
||||
int dw;
|
||||
|
||||
/* Calculate new size */
|
||||
priv = vf->priv;
|
||||
xw = priv->start * 2 +
|
||||
priv->xtile * mpi->w +
|
||||
(priv->xtile - 1) * priv->delta;
|
||||
yh = priv->start * 2 +
|
||||
priv->ytile * mpi->h+
|
||||
(priv->ytile - 1) * priv->delta;
|
||||
|
||||
/* Get the big image! */
|
||||
dmpi=vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
xw, yh);
|
||||
|
||||
/* bytes x pixel & bytes x line */
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
by = 1;
|
||||
dw = mpi->w;
|
||||
}
|
||||
else {
|
||||
by = (mpi->bpp + 7) / 8;
|
||||
dw = mpi->w * by;
|
||||
}
|
||||
/* Index position */
|
||||
t = priv->frame_cur % priv->xytile;
|
||||
// if ((t == 0) && (bkg != 0)) {
|
||||
// /* First frame, delete the background */
|
||||
//
|
||||
// }
|
||||
|
||||
/* Position of image */
|
||||
xi = priv->start + (mpi->w + priv->delta) * (t % priv->xtile);
|
||||
yi = priv->start + (mpi->h + priv->delta) * (t / priv->xtile);
|
||||
|
||||
/* Copy first (or only) plane */
|
||||
memcpy_pic( dmpi->planes[0] + xi * by + yi * dmpi->stride[0],
|
||||
mpi->planes[0],
|
||||
dw,
|
||||
mpi->h,
|
||||
dmpi->stride[0],
|
||||
mpi->stride[0]);
|
||||
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
/* Copy the other 2 planes */
|
||||
memcpy_pic( dmpi->planes[1] + (xi >> mpi->chroma_x_shift) + (yi >> mpi->chroma_y_shift) * dmpi->stride[1],
|
||||
mpi->planes[1],
|
||||
mpi->chroma_width,
|
||||
mpi->chroma_height,
|
||||
dmpi->stride[1],
|
||||
mpi->stride[1]);
|
||||
memcpy_pic( dmpi->planes[2] + (xi >> mpi->chroma_x_shift) + (yi >> mpi->chroma_y_shift) * dmpi->stride[2],
|
||||
mpi->planes[2],
|
||||
mpi->chroma_width,
|
||||
mpi->chroma_height,
|
||||
dmpi->stride[2],
|
||||
mpi->stride[2]);
|
||||
}
|
||||
|
||||
/* Increment current frame */
|
||||
++priv->frame_cur;
|
||||
|
||||
if (t == priv->xytile - 1) {
|
||||
/* Display the composition */
|
||||
dmpi->width = xw;
|
||||
dmpi->height = yh;
|
||||
return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
|
||||
}
|
||||
else {
|
||||
/* Skip the frame */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
/* free local data */
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
/* rgb/bgr 12...32 supported & some Yxxx */
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt)
|
||||
{
|
||||
switch (fmt) {
|
||||
/* rgb 12...32 bit */
|
||||
case IMGFMT_RGB12:
|
||||
case IMGFMT_RGB15:
|
||||
case IMGFMT_RGB16:
|
||||
case IMGFMT_RGB24:
|
||||
case IMGFMT_RGB32:
|
||||
/* bgr 12...32 bit */
|
||||
case IMGFMT_BGR12:
|
||||
case IMGFMT_BGR15:
|
||||
case IMGFMT_BGR16:
|
||||
case IMGFMT_BGR24:
|
||||
case IMGFMT_BGR32:
|
||||
/* Various Yxxx Formats */
|
||||
case IMGFMT_444P:
|
||||
case IMGFMT_422P:
|
||||
case IMGFMT_411P:
|
||||
case IMGFMT_YUY2:
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_YVU9:
|
||||
case IMGFMT_IF09:
|
||||
case IMGFMT_IYUV:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get an integer from the string pointed by s, adjusting s.
|
||||
* If the value is less then 0 def_val is used.
|
||||
* Return 0 for ok
|
||||
*
|
||||
* Look below ( in vf_open(...) ) for a use ...
|
||||
*/
|
||||
static int parse_int(char **s, int *rt, int def_val)
|
||||
{
|
||||
|
||||
int t = 0;
|
||||
|
||||
if (**s) {
|
||||
/* Get value (dec, hex or octal) */
|
||||
t = strtol( *s, s, 0 );
|
||||
|
||||
/* Use default */
|
||||
if (t < 0) {
|
||||
t = def_val;
|
||||
}
|
||||
|
||||
if (**s == ':') {
|
||||
/* Point to next character (problably a digit) */
|
||||
++(*s);
|
||||
}
|
||||
else if (**s != '\0') {
|
||||
/* Error, we got some wrong char */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
t = def_val;
|
||||
}
|
||||
|
||||
*rt = t;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* Main entry funct for the filter */
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
struct vf_priv_s *p;
|
||||
int er;
|
||||
|
||||
vf->put_image = put_image;
|
||||
vf->query_format = query_format;
|
||||
vf->config = config;
|
||||
vf->uninit = uninit;
|
||||
vf->default_reqs = VFCAP_ACCEPT_STRIDE;
|
||||
/* Private data */
|
||||
vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
|
||||
if (p == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (args == NULL) {
|
||||
/* Use the default */
|
||||
args = "";
|
||||
}
|
||||
/* Parse all the arguments */
|
||||
er = parse_int( &args, &p->xtile, 5 );
|
||||
er |= parse_int( &args, &p->ytile, 5 );
|
||||
er |= parse_int( &args, &p->xytile, 0 );
|
||||
er |= parse_int( &args, &p->start, 2 );
|
||||
er |= parse_int( &args, &p->delta, 4 );
|
||||
// er |= parse_int( &args, &p->bkgSet, 0 );
|
||||
|
||||
if (er) {
|
||||
mp_msg(MSGT_VFILTER, MSGL_ERR, MSGTR_MPCODECS_ErrorParsingArgument);
|
||||
return 0;
|
||||
}
|
||||
/* Load some default */
|
||||
if ((p->xytile <= 0) || (p->xytile > p->xtile * p->ytile)) {
|
||||
p->xytile = p->xtile * p->ytile;
|
||||
}
|
||||
|
||||
/* Say what happen: use mp_msg(...)? */
|
||||
if ( mp_msg_test(MSGT_VFILTER,MSGL_V) ) {
|
||||
printf("vf_tile: tiling %d * %d, output every %d frames\n",
|
||||
p->xtile,
|
||||
p->ytile,
|
||||
p->xytile);
|
||||
printf("vf_tile: start pixel %d, delta pixel %d\n",
|
||||
p->start,
|
||||
p->delta);
|
||||
// printf("vf_tile: background 0x%x\n",
|
||||
// p->bkgSet);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_tile = {
|
||||
"Make a single image tiling x/y images",
|
||||
"tile",
|
||||
"Daniele Forghieri",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
235
libavfilter/libmpcodecs/vf_tinterlace.c
Normal file
235
libavfilter/libmpcodecs/vf_tinterlace.c
Normal file
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (C) 2003 Michael Zucchi <notzed@ximian.com>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
int mode;
|
||||
int frame;
|
||||
mp_image_t *dmpi;
|
||||
};
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
int ret = 0;
|
||||
mp_image_t *dmpi;
|
||||
|
||||
switch (vf->priv->mode) {
|
||||
case 0:
|
||||
dmpi = vf->priv->dmpi;
|
||||
if (dmpi == NULL) {
|
||||
dmpi = vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
|
||||
MP_IMGFLAG_PRESERVE,
|
||||
mpi->width, mpi->height*2);
|
||||
|
||||
vf->priv->dmpi = dmpi;
|
||||
|
||||
memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
|
||||
dmpi->stride[0]*2, mpi->stride[0]);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
memcpy_pic(dmpi->planes[1], mpi->planes[1],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[1]*2, mpi->stride[1]);
|
||||
memcpy_pic(dmpi->planes[2], mpi->planes[2],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[2]*2, mpi->stride[2]);
|
||||
}
|
||||
} else {
|
||||
vf->priv->dmpi = NULL;
|
||||
|
||||
memcpy_pic(dmpi->planes[0]+dmpi->stride[0], mpi->planes[0], mpi->w, mpi->h,
|
||||
dmpi->stride[0]*2, mpi->stride[0]);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
memcpy_pic(dmpi->planes[1]+dmpi->stride[1], mpi->planes[1],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[1]*2, mpi->stride[1]);
|
||||
memcpy_pic(dmpi->planes[2]+dmpi->stride[2], mpi->planes[2],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[2]*2, mpi->stride[2]);
|
||||
}
|
||||
ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (vf->priv->frame & 1)
|
||||
ret = vf_next_put_image(vf, mpi, MP_NOPTS_VALUE);
|
||||
break;
|
||||
case 2:
|
||||
if ((vf->priv->frame & 1) == 0)
|
||||
ret = vf_next_put_image(vf, mpi, MP_NOPTS_VALUE);
|
||||
break;
|
||||
case 3:
|
||||
dmpi = vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->width, mpi->height*2);
|
||||
/* fixme, just clear alternate lines */
|
||||
vf_mpi_clear(dmpi, 0, 0, dmpi->w, dmpi->h);
|
||||
if ((vf->priv->frame & 1) == 0) {
|
||||
memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
|
||||
dmpi->stride[0]*2, mpi->stride[0]);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
memcpy_pic(dmpi->planes[1], mpi->planes[1],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[1]*2, mpi->stride[1]);
|
||||
memcpy_pic(dmpi->planes[2], mpi->planes[2],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[2]*2, mpi->stride[2]);
|
||||
}
|
||||
} else {
|
||||
memcpy_pic(dmpi->planes[0]+dmpi->stride[0], mpi->planes[0], mpi->w, mpi->h,
|
||||
dmpi->stride[0]*2, mpi->stride[0]);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
memcpy_pic(dmpi->planes[1]+dmpi->stride[1], mpi->planes[1],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[1]*2, mpi->stride[1]);
|
||||
memcpy_pic(dmpi->planes[2]+dmpi->stride[2], mpi->planes[2],
|
||||
mpi->chroma_width, mpi->chroma_height,
|
||||
dmpi->stride[2]*2, mpi->stride[2]);
|
||||
}
|
||||
}
|
||||
ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
|
||||
break;
|
||||
case 4:
|
||||
// Interleave even lines (only) from Frame 'i' with odd
|
||||
// lines (only) from Frame 'i+1', halving the Frame
|
||||
// rate and preserving image height.
|
||||
|
||||
dmpi = vf->priv->dmpi;
|
||||
|
||||
// @@ Need help: Should I set dmpi->fields to indicate
|
||||
// that the (new) frame will be interlaced!? E.g. ...
|
||||
// dmpi->fields |= MP_IMGFIELD_INTERLACED;
|
||||
// dmpi->fields |= MP_IMGFIELD_TOP_FIRST;
|
||||
// etc.
|
||||
|
||||
if (dmpi == NULL) {
|
||||
dmpi = vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
|
||||
MP_IMGFLAG_PRESERVE,
|
||||
mpi->width, mpi->height);
|
||||
|
||||
vf->priv->dmpi = dmpi;
|
||||
|
||||
my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2,
|
||||
dmpi->stride[0]*2, mpi->stride[0]*2);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
my_memcpy_pic(dmpi->planes[1], mpi->planes[1],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[1]*2, mpi->stride[1]*2);
|
||||
my_memcpy_pic(dmpi->planes[2], mpi->planes[2],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[2]*2, mpi->stride[2]*2);
|
||||
}
|
||||
} else {
|
||||
vf->priv->dmpi = NULL;
|
||||
|
||||
my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
|
||||
mpi->planes[0]+mpi->stride[0],
|
||||
mpi->w, mpi->h/2,
|
||||
dmpi->stride[0]*2, mpi->stride[0]*2);
|
||||
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
||||
my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
|
||||
mpi->planes[1]+mpi->stride[1],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[1]*2, mpi->stride[1]*2);
|
||||
my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
|
||||
mpi->planes[2]+mpi->stride[2],
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[2]*2, mpi->stride[2]*2);
|
||||
}
|
||||
ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
vf->priv->frame++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt)
|
||||
{
|
||||
/* FIXME - figure out which other formats work */
|
||||
switch (fmt) {
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_I420:
|
||||
return vf_next_query_format(vf, fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt)
|
||||
{
|
||||
switch (vf->priv->mode) {
|
||||
case 0:
|
||||
case 3:
|
||||
return vf_next_config(vf,width,height*2,d_width,d_height*2,flags,outfmt);
|
||||
case 1: /* odd frames */
|
||||
case 2: /* even frames */
|
||||
case 4: /* alternate frame (height-preserving) interlacing */
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf)
|
||||
{
|
||||
free(vf->priv);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args)
|
||||
{
|
||||
struct vf_priv_s *p;
|
||||
vf->config = config;
|
||||
vf->put_image = put_image;
|
||||
vf->query_format = query_format;
|
||||
vf->uninit = uninit;
|
||||
vf->default_reqs = VFCAP_ACCEPT_STRIDE;
|
||||
vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
|
||||
vf->priv->mode = 0;
|
||||
if (args)
|
||||
sscanf(args, "%d", &vf->priv->mode);
|
||||
vf->priv->frame = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_tinterlace = {
|
||||
"temporal field interlacing",
|
||||
"tinterlace",
|
||||
"Michael Zucchi",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
324
libavfilter/libmpcodecs/vf_unsharp.c
Normal file
324
libavfilter/libmpcodecs/vf_unsharp.c
Normal file
@ -0,0 +1,324 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Remi Guyomarch <rguyom@pobox.com>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
#if HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
#include "libvo/fastmemcpy.h"
|
||||
#include "libavutil/common.h"
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
#define MIN_MATRIX_SIZE 3
|
||||
#define MAX_MATRIX_SIZE 63
|
||||
|
||||
typedef struct FilterParam {
|
||||
int msizeX, msizeY;
|
||||
double amount;
|
||||
uint32_t *SC[MAX_MATRIX_SIZE-1];
|
||||
} FilterParam;
|
||||
|
||||
struct vf_priv_s {
|
||||
FilterParam lumaParam;
|
||||
FilterParam chromaParam;
|
||||
unsigned int outfmt;
|
||||
};
|
||||
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
/* This code is based on :
|
||||
|
||||
An Efficient algorithm for Gaussian blur using finite-state machines
|
||||
Frederick M. Waltz and John W. V. Miller
|
||||
|
||||
SPIE Conf. on Machine Vision Systems for Inspection and Metrology VII
|
||||
Originally published Boston, Nov 98
|
||||
|
||||
*/
|
||||
|
||||
static void unsharp( uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int width, int height, FilterParam *fp ) {
|
||||
|
||||
uint32_t **SC = fp->SC;
|
||||
uint32_t SR[MAX_MATRIX_SIZE-1], Tmp1, Tmp2;
|
||||
uint8_t* src2 = src; // avoid gcc warning
|
||||
|
||||
int32_t res;
|
||||
int x, y, z;
|
||||
int amount = fp->amount * 65536.0;
|
||||
int stepsX = fp->msizeX/2;
|
||||
int stepsY = fp->msizeY/2;
|
||||
int scalebits = (stepsX+stepsY)*2;
|
||||
int32_t halfscale = 1 << ((stepsX+stepsY)*2-1);
|
||||
|
||||
if( !fp->amount ) {
|
||||
if( src == dst )
|
||||
return;
|
||||
if( dstStride == srcStride )
|
||||
fast_memcpy( dst, src, srcStride*height );
|
||||
else
|
||||
for( y=0; y<height; y++, dst+=dstStride, src+=srcStride )
|
||||
fast_memcpy( dst, src, width );
|
||||
return;
|
||||
}
|
||||
|
||||
for( y=0; y<2*stepsY; y++ )
|
||||
memset( SC[y], 0, sizeof(SC[y][0]) * (width+2*stepsX) );
|
||||
|
||||
for( y=-stepsY; y<height+stepsY; y++ ) {
|
||||
if( y < height ) src2 = src;
|
||||
memset( SR, 0, sizeof(SR[0]) * (2*stepsX-1) );
|
||||
for( x=-stepsX; x<width+stepsX; x++ ) {
|
||||
Tmp1 = x<=0 ? src2[0] : x>=width ? src2[width-1] : src2[x];
|
||||
for( z=0; z<stepsX*2; z+=2 ) {
|
||||
Tmp2 = SR[z+0] + Tmp1; SR[z+0] = Tmp1;
|
||||
Tmp1 = SR[z+1] + Tmp2; SR[z+1] = Tmp2;
|
||||
}
|
||||
for( z=0; z<stepsY*2; z+=2 ) {
|
||||
Tmp2 = SC[z+0][x+stepsX] + Tmp1; SC[z+0][x+stepsX] = Tmp1;
|
||||
Tmp1 = SC[z+1][x+stepsX] + Tmp2; SC[z+1][x+stepsX] = Tmp2;
|
||||
}
|
||||
if( x>=stepsX && y>=stepsY ) {
|
||||
uint8_t* srx = src - stepsY*srcStride + x - stepsX;
|
||||
uint8_t* dsx = dst - stepsY*dstStride + x - stepsX;
|
||||
|
||||
res = (int32_t)*srx + ( ( ( (int32_t)*srx - (int32_t)((Tmp1+halfscale) >> scalebits) ) * amount ) >> 16 );
|
||||
*dsx = res>255 ? 255 : res<0 ? 0 : (uint8_t)res;
|
||||
}
|
||||
}
|
||||
if( y >= 0 ) {
|
||||
dst += dstStride;
|
||||
src += srcStride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int config( struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt ) {
|
||||
|
||||
int z, stepsX, stepsY;
|
||||
FilterParam *fp;
|
||||
char *effect;
|
||||
|
||||
// allocate buffers
|
||||
|
||||
fp = &vf->priv->lumaParam;
|
||||
effect = fp->amount == 0 ? "don't touch" : fp->amount < 0 ? "blur" : "sharpen";
|
||||
mp_msg( MSGT_VFILTER, MSGL_INFO, "unsharp: %dx%d:%0.2f (%s luma) \n", fp->msizeX, fp->msizeY, fp->amount, effect );
|
||||
memset( fp->SC, 0, sizeof( fp->SC ) );
|
||||
stepsX = fp->msizeX/2;
|
||||
stepsY = fp->msizeY/2;
|
||||
for( z=0; z<2*stepsY; z++ )
|
||||
fp->SC[z] = av_malloc(sizeof(*(fp->SC[z])) * (width+2*stepsX));
|
||||
|
||||
fp = &vf->priv->chromaParam;
|
||||
effect = fp->amount == 0 ? "don't touch" : fp->amount < 0 ? "blur" : "sharpen";
|
||||
mp_msg( MSGT_VFILTER, MSGL_INFO, "unsharp: %dx%d:%0.2f (%s chroma)\n", fp->msizeX, fp->msizeY, fp->amount, effect );
|
||||
memset( fp->SC, 0, sizeof( fp->SC ) );
|
||||
stepsX = fp->msizeX/2;
|
||||
stepsY = fp->msizeY/2;
|
||||
for( z=0; z<2*stepsY; z++ )
|
||||
fp->SC[z] = av_malloc(sizeof(*(fp->SC[z])) * (width+2*stepsX));
|
||||
|
||||
return vf_next_config( vf, width, height, d_width, d_height, flags, outfmt );
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static void get_image( struct vf_instance *vf, mp_image_t *mpi ) {
|
||||
if( mpi->flags & MP_IMGFLAG_PRESERVE )
|
||||
return; // don't change
|
||||
if( mpi->imgfmt!=vf->priv->outfmt )
|
||||
return; // colorspace differ
|
||||
|
||||
vf->dmpi = vf_get_image( vf->next, mpi->imgfmt, mpi->type, mpi->flags, mpi->w, mpi->h );
|
||||
mpi->planes[0] = vf->dmpi->planes[0];
|
||||
mpi->stride[0] = vf->dmpi->stride[0];
|
||||
mpi->width = vf->dmpi->width;
|
||||
if( mpi->flags & MP_IMGFLAG_PLANAR ) {
|
||||
mpi->planes[1] = vf->dmpi->planes[1];
|
||||
mpi->planes[2] = vf->dmpi->planes[2];
|
||||
mpi->stride[1] = vf->dmpi->stride[1];
|
||||
mpi->stride[2] = vf->dmpi->stride[2];
|
||||
}
|
||||
mpi->flags |= MP_IMGFLAG_DIRECT;
|
||||
}
|
||||
|
||||
static int put_image( struct vf_instance *vf, mp_image_t *mpi, double pts) {
|
||||
mp_image_t *dmpi;
|
||||
|
||||
if( !(mpi->flags & MP_IMGFLAG_DIRECT) )
|
||||
// no DR, so get a new image! hope we'll get DR buffer:
|
||||
vf->dmpi = vf_get_image( vf->next,vf->priv->outfmt, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, mpi->w, mpi->h);
|
||||
dmpi= vf->dmpi;
|
||||
|
||||
unsharp( dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, &vf->priv->lumaParam );
|
||||
unsharp( dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w/2, mpi->h/2, &vf->priv->chromaParam );
|
||||
unsharp( dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w/2, mpi->h/2, &vf->priv->chromaParam );
|
||||
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
|
||||
#if HAVE_MMX
|
||||
if(gCpuCaps.hasMMX)
|
||||
__asm__ volatile ("emms\n\t");
|
||||
#endif
|
||||
#if HAVE_MMX2
|
||||
if(gCpuCaps.hasMMX2)
|
||||
__asm__ volatile ("sfence\n\t");
|
||||
#endif
|
||||
|
||||
return vf_next_put_image( vf, dmpi, pts);
|
||||
}
|
||||
|
||||
static void uninit( struct vf_instance *vf ) {
|
||||
unsigned int z;
|
||||
FilterParam *fp;
|
||||
|
||||
if( !vf->priv ) return;
|
||||
|
||||
fp = &vf->priv->lumaParam;
|
||||
for( z=0; z<sizeof(fp->SC)/sizeof(fp->SC[0]); z++ ) {
|
||||
av_free( fp->SC[z] );
|
||||
fp->SC[z] = NULL;
|
||||
}
|
||||
fp = &vf->priv->chromaParam;
|
||||
for( z=0; z<sizeof(fp->SC)/sizeof(fp->SC[0]); z++ ) {
|
||||
av_free( fp->SC[z] );
|
||||
fp->SC[z] = NULL;
|
||||
}
|
||||
|
||||
free( vf->priv );
|
||||
vf->priv = NULL;
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format( struct vf_instance *vf, unsigned int fmt ) {
|
||||
switch(fmt) {
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
return vf_next_query_format( vf, vf->priv->outfmt );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static void parse( FilterParam *fp, char* args ) {
|
||||
|
||||
// l7x5:0.8:c3x3:-0.2
|
||||
|
||||
char *z;
|
||||
char *pos = args;
|
||||
char *max = args + strlen(args);
|
||||
|
||||
// parse matrix sizes
|
||||
fp->msizeX = ( pos && pos+1<max ) ? atoi( pos+1 ) : 0;
|
||||
z = strchr( pos+1, 'x' );
|
||||
fp->msizeY = ( z && z+1<max ) ? atoi( pos=z+1 ) : fp->msizeX;
|
||||
|
||||
// min/max & odd
|
||||
fp->msizeX = 1 | av_clip(fp->msizeX, MIN_MATRIX_SIZE, MAX_MATRIX_SIZE);
|
||||
fp->msizeY = 1 | av_clip(fp->msizeY, MIN_MATRIX_SIZE, MAX_MATRIX_SIZE);
|
||||
|
||||
// parse amount
|
||||
pos = strchr( pos+1, ':' );
|
||||
fp->amount = ( pos && pos+1<max ) ? atof( pos+1 ) : 0;
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static const unsigned int fmt_list[] = {
|
||||
IMGFMT_YV12,
|
||||
IMGFMT_I420,
|
||||
IMGFMT_IYUV,
|
||||
0
|
||||
};
|
||||
|
||||
static int vf_open( vf_instance_t *vf, char *args ) {
|
||||
vf->config = config;
|
||||
vf->put_image = put_image;
|
||||
vf->get_image = get_image;
|
||||
vf->query_format = query_format;
|
||||
vf->uninit = uninit;
|
||||
vf->priv = malloc( sizeof(struct vf_priv_s) );
|
||||
memset( vf->priv, 0, sizeof(struct vf_priv_s) );
|
||||
|
||||
if( args ) {
|
||||
char *args2 = strchr( args, 'l' );
|
||||
if( args2 )
|
||||
parse( &vf->priv->lumaParam, args2 );
|
||||
else {
|
||||
vf->priv->lumaParam.amount =
|
||||
vf->priv->lumaParam.msizeX =
|
||||
vf->priv->lumaParam.msizeY = 0;
|
||||
}
|
||||
|
||||
args2 = strchr( args, 'c' );
|
||||
if( args2 )
|
||||
parse( &vf->priv->chromaParam, args2 );
|
||||
else {
|
||||
vf->priv->chromaParam.amount =
|
||||
vf->priv->chromaParam.msizeX =
|
||||
vf->priv->chromaParam.msizeY = 0;
|
||||
}
|
||||
|
||||
if( !vf->priv->lumaParam.msizeX && !vf->priv->chromaParam.msizeX )
|
||||
return 0; // nothing to do
|
||||
}
|
||||
|
||||
// check csp:
|
||||
vf->priv->outfmt = vf_match_csp( &vf->next, fmt_list, IMGFMT_YV12 );
|
||||
if( !vf->priv->outfmt ) {
|
||||
uninit( vf );
|
||||
return 0; // no csp match :(
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_unsharp = {
|
||||
"unsharp mask & gaussian blur",
|
||||
"unsharp",
|
||||
"Remi Guyomarch",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
385
libavfilter/libmpcodecs/vf_uspp.c
Normal file
385
libavfilter/libmpcodecs/vf_uspp.c
Normal file
@ -0,0 +1,385 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "mp_msg.h"
|
||||
#include "cpudetect.h"
|
||||
|
||||
#include "libavcodec/avcodec.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
#include "vd_ffmpeg.h"
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
#define XMIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#define BLOCK 16
|
||||
|
||||
//===========================================================================//
|
||||
static const uint8_t __attribute__((aligned(8))) dither[8][8]={
|
||||
{ 0*4, 48*4, 12*4, 60*4, 3*4, 51*4, 15*4, 63*4, },
|
||||
{ 32*4, 16*4, 44*4, 28*4, 35*4, 19*4, 47*4, 31*4, },
|
||||
{ 8*4, 56*4, 4*4, 52*4, 11*4, 59*4, 7*4, 55*4, },
|
||||
{ 40*4, 24*4, 36*4, 20*4, 43*4, 27*4, 39*4, 23*4, },
|
||||
{ 2*4, 50*4, 14*4, 62*4, 1*4, 49*4, 13*4, 61*4, },
|
||||
{ 34*4, 18*4, 46*4, 30*4, 33*4, 17*4, 45*4, 29*4, },
|
||||
{ 10*4, 58*4, 6*4, 54*4, 9*4, 57*4, 5*4, 53*4, },
|
||||
{ 42*4, 26*4, 38*4, 22*4, 41*4, 25*4, 37*4, 21*4, },
|
||||
};
|
||||
|
||||
static const uint8_t offset[511][2]= {
|
||||
{ 0, 0},
|
||||
{ 0, 0}, { 8, 8},
|
||||
{ 0, 0}, { 4, 4}, {12, 8}, { 8,12},
|
||||
{ 0, 0}, {10, 2}, { 4, 4}, {14, 6}, { 8, 8}, { 2,10}, {12,12}, { 6,14},
|
||||
|
||||
{ 0, 0}, {10, 2}, { 4, 4}, {14, 6}, { 8, 8}, { 2,10}, {12,12}, { 6,14},
|
||||
{ 5, 1}, {15, 3}, { 9, 5}, { 3, 7}, {13, 9}, { 7,11}, { 1,13}, {11,15},
|
||||
|
||||
{ 0, 0}, { 8, 0}, { 0, 8}, { 8, 8}, { 5, 1}, {13, 1}, { 5, 9}, {13, 9},
|
||||
{ 2, 2}, {10, 2}, { 2,10}, {10,10}, { 7, 3}, {15, 3}, { 7,11}, {15,11},
|
||||
{ 4, 4}, {12, 4}, { 4,12}, {12,12}, { 1, 5}, { 9, 5}, { 1,13}, { 9,13},
|
||||
{ 6, 6}, {14, 6}, { 6,14}, {14,14}, { 3, 7}, {11, 7}, { 3,15}, {11,15},
|
||||
|
||||
{ 0, 0}, { 8, 0}, { 0, 8}, { 8, 8}, { 4, 0}, {12, 0}, { 4, 8}, {12, 8},
|
||||
{ 1, 1}, { 9, 1}, { 1, 9}, { 9, 9}, { 5, 1}, {13, 1}, { 5, 9}, {13, 9},
|
||||
{ 3, 2}, {11, 2}, { 3,10}, {11,10}, { 7, 2}, {15, 2}, { 7,10}, {15,10},
|
||||
{ 2, 3}, {10, 3}, { 2,11}, {10,11}, { 6, 3}, {14, 3}, { 6,11}, {14,11},
|
||||
{ 0, 4}, { 8, 4}, { 0,12}, { 8,12}, { 4, 4}, {12, 4}, { 4,12}, {12,12},
|
||||
{ 1, 5}, { 9, 5}, { 1,13}, { 9,13}, { 5, 5}, {13, 5}, { 5,13}, {13,13},
|
||||
{ 3, 6}, {11, 6}, { 3,14}, {11,14}, { 7, 6}, {15, 6}, { 7,14}, {15,14},
|
||||
{ 2, 7}, {10, 7}, { 2,15}, {10,15}, { 6, 7}, {14, 7}, { 6,15}, {14,15},
|
||||
|
||||
{ 0, 0}, { 8, 0}, { 0, 8}, { 8, 8}, { 0, 2}, { 8, 2}, { 0,10}, { 8,10},
|
||||
{ 0, 4}, { 8, 4}, { 0,12}, { 8,12}, { 0, 6}, { 8, 6}, { 0,14}, { 8,14},
|
||||
{ 1, 1}, { 9, 1}, { 1, 9}, { 9, 9}, { 1, 3}, { 9, 3}, { 1,11}, { 9,11},
|
||||
{ 1, 5}, { 9, 5}, { 1,13}, { 9,13}, { 1, 7}, { 9, 7}, { 1,15}, { 9,15},
|
||||
{ 2, 0}, {10, 0}, { 2, 8}, {10, 8}, { 2, 2}, {10, 2}, { 2,10}, {10,10},
|
||||
{ 2, 4}, {10, 4}, { 2,12}, {10,12}, { 2, 6}, {10, 6}, { 2,14}, {10,14},
|
||||
{ 3, 1}, {11, 1}, { 3, 9}, {11, 9}, { 3, 3}, {11, 3}, { 3,11}, {11,11},
|
||||
{ 3, 5}, {11, 5}, { 3,13}, {11,13}, { 3, 7}, {11, 7}, { 3,15}, {11,15},
|
||||
{ 4, 0}, {12, 0}, { 4, 8}, {12, 8}, { 4, 2}, {12, 2}, { 4,10}, {12,10},
|
||||
{ 4, 4}, {12, 4}, { 4,12}, {12,12}, { 4, 6}, {12, 6}, { 4,14}, {12,14},
|
||||
{ 5, 1}, {13, 1}, { 5, 9}, {13, 9}, { 5, 3}, {13, 3}, { 5,11}, {13,11},
|
||||
{ 5, 5}, {13, 5}, { 5,13}, {13,13}, { 5, 7}, {13, 7}, { 5,15}, {13,15},
|
||||
{ 6, 0}, {14, 0}, { 6, 8}, {14, 8}, { 6, 2}, {14, 2}, { 6,10}, {14,10},
|
||||
{ 6, 4}, {14, 4}, { 6,12}, {14,12}, { 6, 6}, {14, 6}, { 6,14}, {14,14},
|
||||
{ 7, 1}, {15, 1}, { 7, 9}, {15, 9}, { 7, 3}, {15, 3}, { 7,11}, {15,11},
|
||||
{ 7, 5}, {15, 5}, { 7,13}, {15,13}, { 7, 7}, {15, 7}, { 7,15}, {15,15},
|
||||
|
||||
{ 0, 0}, { 8, 0}, { 0, 8}, { 8, 8}, { 4, 4}, {12, 4}, { 4,12}, {12,12}, { 0, 4}, { 8, 4}, { 0,12}, { 8,12}, { 4, 0}, {12, 0}, { 4, 8}, {12, 8}, { 2, 2}, {10, 2}, { 2,10}, {10,10}, { 6, 6}, {14, 6}, { 6,14}, {14,14}, { 2, 6}, {10, 6}, { 2,14}, {10,14}, { 6, 2}, {14, 2}, { 6,10}, {14,10}, { 0, 2}, { 8, 2}, { 0,10}, { 8,10}, { 4, 6}, {12, 6}, { 4,14}, {12,14}, { 0, 6}, { 8, 6}, { 0,14}, { 8,14}, { 4, 2}, {12, 2}, { 4,10}, {12,10}, { 2, 0}, {10, 0}, { 2, 8}, {10, 8}, { 6, 4}, {14, 4}, { 6,12}, {14,12}, { 2, 4}, {10, 4}, { 2,12}, {10,12}, { 6, 0}, {14, 0}, { 6, 8}, {14, 8}, { 1, 1}, { 9, 1}, { 1, 9}, { 9, 9}, { 5, 5}, {13, 5}, { 5,13}, {13,13}, { 1, 5}, { 9, 5}, { 1,13}, { 9,13}, { 5, 1}, {13, 1}, { 5, 9}, {13, 9}, { 3, 3}, {11, 3}, { 3,11}, {11,11}, { 7, 7}, {15, 7}, { 7,15}, {15,15}, { 3, 7}, {11, 7}, { 3,15}, {11,15}, { 7, 3}, {15, 3}, { 7,11}, {15,11}, { 1, 3}, { 9, 3}, { 1,11}, { 9,11}, { 5, 7}, {13, 7}, { 5,15}, {13,15}, { 1, 7}, { 9, 7}, { 1,15}, { 9,15}, { 5, 3}, {13, 3}, { 5,11}, {13,11}, { 3, 1}, {11, 1}, { 3, 9}, {11, 9}, { 7, 5}, {15, 5}, { 7,13}, {15,13}, { 3, 5}, {11, 5}, { 3,13}, {11,13}, { 7, 1}, {15, 1}, { 7, 9}, {15, 9}, { 0, 1}, { 8, 1}, { 0, 9}, { 8, 9}, { 4, 5}, {12, 5}, { 4,13}, {12,13}, { 0, 5}, { 8, 5}, { 0,13}, { 8,13}, { 4, 1}, {12, 1}, { 4, 9}, {12, 9}, { 2, 3}, {10, 3}, { 2,11}, {10,11}, { 6, 7}, {14, 7}, { 6,15}, {14,15}, { 2, 7}, {10, 7}, { 2,15}, {10,15}, { 6, 3}, {14, 3}, { 6,11}, {14,11}, { 0, 3}, { 8, 3}, { 0,11}, { 8,11}, { 4, 7}, {12, 7}, { 4,15}, {12,15}, { 0, 7}, { 8, 7}, { 0,15}, { 8,15}, { 4, 3}, {12, 3}, { 4,11}, {12,11}, { 2, 1}, {10, 1}, { 2, 9}, {10, 9}, { 6, 5}, {14, 5}, { 6,13}, {14,13}, { 2, 5}, {10, 5}, { 2,13}, {10,13}, { 6, 1}, {14, 1}, { 6, 9}, {14, 9}, { 1, 0}, { 9, 0}, { 1, 8}, { 9, 8}, { 5, 4}, {13, 4}, { 5,12}, {13,12}, { 1, 4}, { 9, 4}, { 1,12}, { 9,12}, { 5, 0}, {13, 0}, { 5, 8}, {13, 8}, { 3, 2}, {11, 2}, { 3,10}, {11,10}, { 7, 6}, {15, 6}, { 7,14}, {15,14}, { 3, 6}, {11, 6}, { 3,14}, {11,14}, { 7, 2}, {15, 2}, { 7,10}, {15,10}, { 1, 2}, { 9, 2}, { 1,10}, { 9,10}, { 5, 6}, {13, 6}, { 5,14}, {13,14}, { 1, 6}, { 9, 6}, { 1,14}, { 9,14}, { 5, 2}, {13, 2}, { 5,10}, {13,10}, { 3, 0}, {11, 0}, { 3, 8}, {11, 8}, { 7, 4}, {15, 4}, { 7,12}, {15,12}, { 3, 4}, {11, 4}, { 3,12}, {11,12}, { 7, 0}, {15, 0}, { 7, 8}, {15, 8},
|
||||
};
|
||||
|
||||
struct vf_priv_s {
|
||||
int log2_count;
|
||||
int qp;
|
||||
int mode;
|
||||
int mpeg2;
|
||||
int temp_stride[3];
|
||||
uint8_t *src[3];
|
||||
int16_t *temp[3];
|
||||
int outbuf_size;
|
||||
uint8_t *outbuf;
|
||||
AVCodecContext *avctx_enc[BLOCK*BLOCK];
|
||||
AVFrame *frame;
|
||||
AVFrame *frame_dec;
|
||||
};
|
||||
|
||||
static void store_slice_c(uint8_t *dst, int16_t *src, int dst_stride, int src_stride, int width, int height, int log2_scale){
|
||||
int y, x;
|
||||
|
||||
#define STORE(pos) \
|
||||
temp= ((src[x + y*src_stride + pos]<<log2_scale) + d[pos])>>8;\
|
||||
if(temp & 0x100) temp= ~(temp>>31);\
|
||||
dst[x + y*dst_stride + pos]= temp;
|
||||
|
||||
for(y=0; y<height; y++){
|
||||
const uint8_t *d= dither[y&7];
|
||||
for(x=0; x<width; x+=8){
|
||||
int temp;
|
||||
STORE(0);
|
||||
STORE(1);
|
||||
STORE(2);
|
||||
STORE(3);
|
||||
STORE(4);
|
||||
STORE(5);
|
||||
STORE(6);
|
||||
STORE(7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void filter(struct vf_priv_s *p, uint8_t *dst[3], uint8_t *src[3], int dst_stride[3], int src_stride[3], int width, int height, uint8_t *qp_store, int qp_stride){
|
||||
int x, y, i, j;
|
||||
const int count= 1<<p->log2_count;
|
||||
|
||||
for(i=0; i<3; i++){
|
||||
int is_chroma= !!i;
|
||||
int w= width >>is_chroma;
|
||||
int h= height>>is_chroma;
|
||||
int stride= p->temp_stride[i];
|
||||
int block= BLOCK>>is_chroma;
|
||||
|
||||
if (!src[i] || !dst[i])
|
||||
continue; // HACK avoid crash for Y8 colourspace
|
||||
for(y=0; y<h; y++){
|
||||
int index= block + block*stride + y*stride;
|
||||
fast_memcpy(p->src[i] + index, src[i] + y*src_stride[i], w);
|
||||
for(x=0; x<block; x++){
|
||||
p->src[i][index - x - 1]= p->src[i][index + x ];
|
||||
p->src[i][index + w + x ]= p->src[i][index + w - x - 1];
|
||||
}
|
||||
}
|
||||
for(y=0; y<block; y++){
|
||||
fast_memcpy(p->src[i] + ( block-1-y)*stride, p->src[i] + ( y+block )*stride, stride);
|
||||
fast_memcpy(p->src[i] + (h+block +y)*stride, p->src[i] + (h-y+block-1)*stride, stride);
|
||||
}
|
||||
|
||||
p->frame->linesize[i]= stride;
|
||||
memset(p->temp[i], 0, (h+2*block)*stride*sizeof(int16_t));
|
||||
}
|
||||
|
||||
if(p->qp)
|
||||
p->frame->quality= p->qp * FF_QP2LAMBDA;
|
||||
else
|
||||
p->frame->quality= norm_qscale(qp_store[0], p->mpeg2) * FF_QP2LAMBDA;
|
||||
// init per MB qscale stuff FIXME
|
||||
|
||||
for(i=0; i<count; i++){
|
||||
const int x1= offset[i+count-1][0];
|
||||
const int y1= offset[i+count-1][1];
|
||||
int offset, out_size;
|
||||
p->frame->data[0]= p->src[0] + x1 + y1 * p->frame->linesize[0];
|
||||
p->frame->data[1]= p->src[1] + x1/2 + y1/2 * p->frame->linesize[1];
|
||||
p->frame->data[2]= p->src[2] + x1/2 + y1/2 * p->frame->linesize[2];
|
||||
|
||||
out_size = avcodec_encode_video(p->avctx_enc[i], p->outbuf, p->outbuf_size, p->frame);
|
||||
p->frame_dec = p->avctx_enc[i]->coded_frame;
|
||||
|
||||
offset= (BLOCK-x1) + (BLOCK-y1)*p->frame_dec->linesize[0];
|
||||
//FIXME optimize
|
||||
for(y=0; y<height; y++){
|
||||
for(x=0; x<width; x++){
|
||||
p->temp[0][ x + y*p->temp_stride[0] ] += p->frame_dec->data[0][ x + y*p->frame_dec->linesize[0] + offset ];
|
||||
}
|
||||
}
|
||||
offset= (BLOCK/2-x1/2) + (BLOCK/2-y1/2)*p->frame_dec->linesize[1];
|
||||
for(y=0; y<height/2; y++){
|
||||
for(x=0; x<width/2; x++){
|
||||
p->temp[1][ x + y*p->temp_stride[1] ] += p->frame_dec->data[1][ x + y*p->frame_dec->linesize[1] + offset ];
|
||||
p->temp[2][ x + y*p->temp_stride[2] ] += p->frame_dec->data[2][ x + y*p->frame_dec->linesize[2] + offset ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(j=0; j<3; j++){
|
||||
int is_chroma= !!j;
|
||||
store_slice_c(dst[j], p->temp[j], dst_stride[j], p->temp_stride[j], width>>is_chroma, height>>is_chroma, 8-p->log2_count);
|
||||
}
|
||||
}
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
int i;
|
||||
AVCodec *enc= avcodec_find_encoder(CODEC_ID_SNOW);
|
||||
|
||||
for(i=0; i<3; i++){
|
||||
int is_chroma= !!i;
|
||||
int w= ((width + 4*BLOCK-1) & (~(2*BLOCK-1)))>>is_chroma;
|
||||
int h= ((height + 4*BLOCK-1) & (~(2*BLOCK-1)))>>is_chroma;
|
||||
|
||||
vf->priv->temp_stride[i]= w;
|
||||
vf->priv->temp[i]= malloc(vf->priv->temp_stride[i]*h*sizeof(int16_t));
|
||||
vf->priv->src [i]= malloc(vf->priv->temp_stride[i]*h*sizeof(uint8_t));
|
||||
}
|
||||
for(i=0; i< (1<<vf->priv->log2_count); i++){
|
||||
AVCodecContext *avctx_enc;
|
||||
|
||||
avctx_enc=
|
||||
vf->priv->avctx_enc[i]= avcodec_alloc_context();
|
||||
avctx_enc->width = width + BLOCK;
|
||||
avctx_enc->height = height + BLOCK;
|
||||
avctx_enc->time_base= (AVRational){1,25}; // meaningless
|
||||
avctx_enc->gop_size = 300;
|
||||
avctx_enc->max_b_frames= 0;
|
||||
avctx_enc->pix_fmt = PIX_FMT_YUV420P;
|
||||
avctx_enc->flags = CODEC_FLAG_QSCALE | CODEC_FLAG_LOW_DELAY;
|
||||
avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
|
||||
avctx_enc->global_quality= 123;
|
||||
avcodec_open(avctx_enc, enc);
|
||||
assert(avctx_enc->codec);
|
||||
}
|
||||
vf->priv->frame= avcodec_alloc_frame();
|
||||
vf->priv->frame_dec= avcodec_alloc_frame();
|
||||
|
||||
vf->priv->outbuf_size= (width + BLOCK)*(height + BLOCK)*10;
|
||||
vf->priv->outbuf= malloc(vf->priv->outbuf_size);
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static void get_image(struct vf_instance *vf, mp_image_t *mpi){
|
||||
if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
|
||||
// ok, we can do pp in-place (or pp disabled):
|
||||
vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height);
|
||||
mpi->planes[0]=vf->dmpi->planes[0];
|
||||
mpi->stride[0]=vf->dmpi->stride[0];
|
||||
mpi->width=vf->dmpi->width;
|
||||
if(mpi->flags&MP_IMGFLAG_PLANAR){
|
||||
mpi->planes[1]=vf->dmpi->planes[1];
|
||||
mpi->planes[2]=vf->dmpi->planes[2];
|
||||
mpi->stride[1]=vf->dmpi->stride[1];
|
||||
mpi->stride[2]=vf->dmpi->stride[2];
|
||||
}
|
||||
mpi->flags|=MP_IMGFLAG_DIRECT;
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
|
||||
if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
|
||||
// no DR, so get a new image! hope we'll get DR buffer:
|
||||
dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP,
|
||||
MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
|
||||
mpi->width,mpi->height);
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
}else{
|
||||
dmpi=vf->dmpi;
|
||||
}
|
||||
|
||||
vf->priv->mpeg2= mpi->qscale_type;
|
||||
if(vf->priv->log2_count || !(mpi->flags&MP_IMGFLAG_DIRECT)){
|
||||
if(mpi->qscale || vf->priv->qp){
|
||||
filter(vf->priv, dmpi->planes, mpi->planes, dmpi->stride, mpi->stride, mpi->w, mpi->h, mpi->qscale, mpi->qstride);
|
||||
}else{
|
||||
memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h, dmpi->stride[0], mpi->stride[0]);
|
||||
memcpy_pic(dmpi->planes[1], mpi->planes[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[1], mpi->stride[1]);
|
||||
memcpy_pic(dmpi->planes[2], mpi->planes[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[2], mpi->stride[2]);
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_MMX
|
||||
if(gCpuCaps.hasMMX) __asm__ volatile ("emms\n\t");
|
||||
#endif
|
||||
#if HAVE_MMX2
|
||||
if(gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
|
||||
#endif
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
static void uninit(struct vf_instance *vf){
|
||||
int i;
|
||||
if(!vf->priv) return;
|
||||
|
||||
for(i=0; i<3; i++){
|
||||
free(vf->priv->temp[i]);
|
||||
vf->priv->temp[i]= NULL;
|
||||
free(vf->priv->src[i]);
|
||||
vf->priv->src[i]= NULL;
|
||||
}
|
||||
for(i=0; i<BLOCK*BLOCK; i++){
|
||||
av_freep(&vf->priv->avctx_enc[i]);
|
||||
}
|
||||
|
||||
free(vf->priv);
|
||||
vf->priv=NULL;
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
switch(fmt){
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
case IMGFMT_Y800:
|
||||
case IMGFMT_Y8:
|
||||
return vf_next_query_format(vf,fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int control(struct vf_instance *vf, int request, void* data){
|
||||
switch(request){
|
||||
case VFCTRL_QUERY_MAX_PP_LEVEL:
|
||||
return 8;
|
||||
case VFCTRL_SET_PP_LEVEL:
|
||||
vf->priv->log2_count= *((unsigned int*)data);
|
||||
//FIXME we have to realloc a few things here
|
||||
return CONTROL_TRUE;
|
||||
}
|
||||
return vf_next_control(vf,request,data);
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
|
||||
int log2c=-1;
|
||||
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->get_image=get_image;
|
||||
vf->query_format=query_format;
|
||||
vf->uninit=uninit;
|
||||
vf->control= control;
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
memset(vf->priv, 0, sizeof(struct vf_priv_s));
|
||||
|
||||
init_avcodec();
|
||||
|
||||
vf->priv->log2_count= 4;
|
||||
|
||||
if (args) sscanf(args, "%d:%d:%d", &log2c, &vf->priv->qp, &vf->priv->mode);
|
||||
|
||||
if( log2c >=0 && log2c <=8 )
|
||||
vf->priv->log2_count = log2c;
|
||||
|
||||
if(vf->priv->qp < 0)
|
||||
vf->priv->qp = 0;
|
||||
|
||||
// #if HAVE_MMX
|
||||
// if(gCpuCaps.hasMMX){
|
||||
// store_slice= store_slice_mmx;
|
||||
// }
|
||||
// #endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_uspp = {
|
||||
"ultra simple/slow postprocess",
|
||||
"uspp",
|
||||
"Michael Niedermayer",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
120
libavfilter/libmpcodecs/vf_yuvcsp.c
Normal file
120
libavfilter/libmpcodecs/vf_yuvcsp.c
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
struct vf_priv_s {
|
||||
int csp;
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
return vf_next_config(vf, width, height, d_width, d_height, flags, outfmt);
|
||||
}
|
||||
|
||||
static inline int clamp_y(int x){
|
||||
return (x > 235) ? 235 : (x < 16) ? 16 : x;
|
||||
}
|
||||
|
||||
static inline int clamp_c(int x){
|
||||
return (x > 240) ? 240 : (x < 16) ? 16 : x;
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
int i,j;
|
||||
uint8_t *y_in, *cb_in, *cr_in;
|
||||
uint8_t *y_out, *cb_out, *cr_out;
|
||||
|
||||
vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->width, mpi->height);
|
||||
|
||||
y_in = mpi->planes[0];
|
||||
cb_in = mpi->planes[1];
|
||||
cr_in = mpi->planes[2];
|
||||
|
||||
y_out = vf->dmpi->planes[0];
|
||||
cb_out = vf->dmpi->planes[1];
|
||||
cr_out = vf->dmpi->planes[2];
|
||||
|
||||
for (i = 0; i < mpi->height; i++)
|
||||
for (j = 0; j < mpi->width; j++)
|
||||
y_out[i*vf->dmpi->stride[0]+j] = clamp_y(y_in[i*mpi->stride[0]+j]);
|
||||
|
||||
for (i = 0; i < mpi->chroma_height; i++)
|
||||
for (j = 0; j < mpi->chroma_width; j++)
|
||||
{
|
||||
cb_out[i*vf->dmpi->stride[1]+j] = clamp_c(cb_in[i*mpi->stride[1]+j]);
|
||||
cr_out[i*vf->dmpi->stride[2]+j] = clamp_c(cr_in[i*mpi->stride[2]+j]);
|
||||
}
|
||||
|
||||
return vf_next_put_image(vf,vf->dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
/*
|
||||
static void uninit(struct vf_instance *vf){
|
||||
free(vf->priv);
|
||||
}
|
||||
*/
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
switch(fmt){
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
case IMGFMT_IYUV:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
// vf->uninit=uninit;
|
||||
vf->query_format=query_format;
|
||||
// vf->priv=calloc(1, sizeof(struct vf_priv_s));
|
||||
// if (args)
|
||||
// vf->priv->csp = atoi(args);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_yuvcsp = {
|
||||
"yuv colorspace converter",
|
||||
"yuvcsp",
|
||||
"Alex Beregszaszi",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
105
libavfilter/libmpcodecs/vf_yvu9.c
Normal file
105
libavfilter/libmpcodecs/vf_yvu9.c
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mp_msg.h"
|
||||
#include "help_mp.h"
|
||||
|
||||
#include "img_format.h"
|
||||
#include "mp_image.h"
|
||||
#include "vf.h"
|
||||
|
||||
#include "libvo/fastmemcpy.h"
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int config(struct vf_instance *vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
|
||||
if(vf_next_query_format(vf,IMGFMT_YV12)<=0){
|
||||
mp_msg(MSGT_VFILTER, MSGL_WARN, MSGTR_MPCODECS_WarnNextFilterDoesntSupport, "YVU9");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,IMGFMT_YV12);
|
||||
}
|
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
int y,w,h;
|
||||
|
||||
// hope we'll get DR buffer:
|
||||
dmpi=vf_get_image(vf->next,IMGFMT_YV12,
|
||||
MP_IMGTYPE_TEMP, 0/*MP_IMGFLAG_ACCEPT_STRIDE*/,
|
||||
mpi->w, mpi->h);
|
||||
|
||||
for(y=0;y<mpi->h;y++)
|
||||
fast_memcpy(dmpi->planes[0]+dmpi->stride[0]*y,
|
||||
mpi->planes[0]+mpi->stride[0]*y,
|
||||
mpi->w);
|
||||
|
||||
w=mpi->w/4; h=mpi->h/2;
|
||||
for(y=0;y<h;y++){
|
||||
unsigned char* s=mpi->planes[1]+mpi->stride[1]*(y>>1);
|
||||
unsigned char* d=dmpi->planes[1]+dmpi->stride[1]*y;
|
||||
int x;
|
||||
for(x=0;x<w;x++) d[2*x]=d[2*x+1]=s[x];
|
||||
}
|
||||
for(y=0;y<h;y++){
|
||||
unsigned char* s=mpi->planes[2]+mpi->stride[2]*(y>>1);
|
||||
unsigned char* d=dmpi->planes[2]+dmpi->stride[2]*y;
|
||||
int x;
|
||||
for(x=0;x<w;x++) d[2*x]=d[2*x+1]=s[x];
|
||||
}
|
||||
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
|
||||
return vf_next_put_image(vf,dmpi, pts);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
static int query_format(struct vf_instance *vf, unsigned int fmt){
|
||||
if (fmt == IMGFMT_YVU9 || fmt == IMGFMT_IF09)
|
||||
return vf_next_query_format(vf,IMGFMT_YV12) & (~VFCAP_CSP_SUPPORTED_BY_HW);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args){
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
vf->query_format=query_format;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const vf_info_t vf_info_yvu9 = {
|
||||
"fast YVU9->YV12 conversion",
|
||||
"yvu9",
|
||||
"alex",
|
||||
"",
|
||||
vf_open,
|
||||
NULL
|
||||
};
|
||||
|
||||
//===========================================================================//
|
||||
56
libavfilter/libmpcodecs/vfcap.h
Normal file
56
libavfilter/libmpcodecs/vfcap.h
Normal file
@ -0,0 +1,56 @@
|
||||
/* VFCAP_* values: they are flags, returned by query_format():
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_VFCAP_H
|
||||
#define MPLAYER_VFCAP_H
|
||||
|
||||
// set, if the given colorspace is supported (with or without conversion)
|
||||
#define VFCAP_CSP_SUPPORTED 0x1
|
||||
// set, if the given colorspace is supported _without_ conversion
|
||||
#define VFCAP_CSP_SUPPORTED_BY_HW 0x2
|
||||
// set if the driver/filter can draw OSD
|
||||
#define VFCAP_OSD 0x4
|
||||
// set if the driver/filter can handle compressed SPU stream
|
||||
#define VFCAP_SPU 0x8
|
||||
// scaling up/down by hardware, or software:
|
||||
#define VFCAP_HWSCALE_UP 0x10
|
||||
#define VFCAP_HWSCALE_DOWN 0x20
|
||||
#define VFCAP_SWSCALE 0x40
|
||||
// driver/filter can do vertical flip (upside-down)
|
||||
#define VFCAP_FLIP 0x80
|
||||
|
||||
// driver/hardware handles timing (blocking)
|
||||
#define VFCAP_TIMER 0x100
|
||||
// driver _always_ flip image upside-down (for ve_vfw)
|
||||
#define VFCAP_FLIPPED 0x200
|
||||
// vf filter: accepts stride (put_image)
|
||||
// vo driver: has draw_slice() support for the given csp
|
||||
#define VFCAP_ACCEPT_STRIDE 0x400
|
||||
// filter does postprocessing (so you shouldn't scale/filter image before it)
|
||||
#define VFCAP_POSTPROC 0x800
|
||||
// filter cannot be reconfigured to different size & format
|
||||
#define VFCAP_CONSTANT 0x1000
|
||||
// filter can draw EOSD
|
||||
#define VFCAP_EOSD 0x2000
|
||||
// filter will draw EOSD at screen resolution (without scaling)
|
||||
#define VFCAP_EOSD_UNSCALED 0x4000
|
||||
// used by libvo and vf_vo, indicates the VO does not support draw_slice for this format
|
||||
#define VOCAP_NOSLICES 0x8000
|
||||
|
||||
#endif /* MPLAYER_VFCAP_H */
|
||||
Loading…
x
Reference in New Issue
Block a user