diff options
Diffstat (limited to 'video/sws_utils.c')
-rw-r--r-- | video/sws_utils.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/video/sws_utils.c b/video/sws_utils.c new file mode 100644 index 0000000000..4fc5639e55 --- /dev/null +++ b/video/sws_utils.c @@ -0,0 +1,199 @@ +/* + * 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 <assert.h> + +#include <libavutil/opt.h> + +#include "libmpcodecs/sws_utils.h" + +#include "libmpcodecs/mp_image.h" +#include "libmpcodecs/img_format.h" +#include "fmt-conversion.h" +#include "libvo/csputils.h" +#include "mp_msg.h" + +//global sws_flags from the command line +int sws_flags = 2; + +float sws_lum_gblur = 0.0; +float sws_chr_gblur = 0.0; +int sws_chr_vshift = 0; +int sws_chr_hshift = 0; +float sws_chr_sharpen = 0.0; +float sws_lum_sharpen = 0.0; + +//global srcFilter +static SwsFilter *src_filter = NULL; + +void sws_getFlagsAndFilterFromCmdLine(int *flags, SwsFilter **srcFilterParam, + SwsFilter **dstFilterParam) +{ + static int firstTime = 1; + *flags = 0; + + if (firstTime) { + firstTime = 0; + *flags = SWS_PRINT_INFO; + } else if (mp_msg_test(MSGT_VFILTER, MSGL_DBG2)) + *flags = SWS_PRINT_INFO; + + if (src_filter) + sws_freeFilter(src_filter); + + src_filter = sws_getDefaultFilter( + sws_lum_gblur, sws_chr_gblur, + sws_lum_sharpen, sws_chr_sharpen, + sws_chr_hshift, sws_chr_vshift, verbose > 1); + + switch (sws_flags) { + case 0: *flags |= SWS_FAST_BILINEAR; + break; + case 1: *flags |= SWS_BILINEAR; + break; + case 2: *flags |= SWS_BICUBIC; + break; + case 3: *flags |= SWS_X; + break; + case 4: *flags |= SWS_POINT; + break; + case 5: *flags |= SWS_AREA; + break; + case 6: *flags |= SWS_BICUBLIN; + break; + case 7: *flags |= SWS_GAUSS; + break; + case 8: *flags |= SWS_SINC; + break; + case 9: *flags |= SWS_LANCZOS; + break; + case 10: *flags |= SWS_SPLINE; + break; + default: *flags |= SWS_BILINEAR; + break; + } + + *srcFilterParam = src_filter; + *dstFilterParam = NULL; +} + +// will use sws_flags & src_filter (from cmd line) +static struct SwsContext *sws_getContextFromCmdLine2(int srcW, int srcH, + int srcFormat, int dstW, + int dstH, int dstFormat, + int extraflags) +{ + int flags; + SwsFilter *dstFilterParam, *srcFilterParam; + enum PixelFormat dfmt, sfmt; + + dfmt = imgfmt2pixfmt(dstFormat); + sfmt = imgfmt2pixfmt(srcFormat); + if (srcFormat == IMGFMT_RGB8 || srcFormat == IMGFMT_BGR8) + sfmt = PIX_FMT_PAL8; + sws_getFlagsAndFilterFromCmdLine(&flags, &srcFilterParam, &dstFilterParam); + + return sws_getContext(srcW, srcH, sfmt, dstW, dstH, dfmt, flags | + extraflags, srcFilterParam, dstFilterParam, + NULL); +} + +struct SwsContext *sws_getContextFromCmdLine(int srcW, int srcH, int srcFormat, + int dstW, int dstH, + int dstFormat) +{ + return sws_getContextFromCmdLine2(srcW, srcH, srcFormat, dstW, dstH, + dstFormat, + 0); +} + +struct SwsContext *sws_getContextFromCmdLine_hq(int srcW, int srcH, + int srcFormat, int dstW, + int dstH, + int dstFormat) +{ + return sws_getContextFromCmdLine2( + srcW, srcH, srcFormat, dstW, dstH, dstFormat, + SWS_FULL_CHR_H_INT | SWS_FULL_CHR_H_INP | + SWS_ACCURATE_RND | SWS_BITEXACT); +} + +bool mp_sws_supported_format(int imgfmt) +{ + enum PixelFormat av_format = imgfmt2pixfmt(imgfmt); + + return av_format != PIX_FMT_NONE && sws_isSupportedInput(av_format) + && sws_isSupportedOutput(av_format); +} + +static int mp_csp_to_sws_colorspace(enum mp_csp csp) +{ + switch (csp) { + case MP_CSP_BT_601: return SWS_CS_ITU601; + case MP_CSP_BT_709: return SWS_CS_ITU709; + case MP_CSP_SMPTE_240M: return SWS_CS_SMPTE240M; + default: return SWS_CS_DEFAULT; + } +} + +void mp_image_swscale(struct mp_image *dst, struct mp_image *src, + int my_sws_flags) +{ + enum PixelFormat s_fmt = imgfmt2pixfmt(src->imgfmt); + if (src->imgfmt == IMGFMT_RGB8 || src->imgfmt == IMGFMT_BGR8) + s_fmt = PIX_FMT_PAL8; + int s_csp = mp_csp_to_sws_colorspace(mp_image_csp(src)); + int s_range = mp_image_levels(src) == MP_CSP_LEVELS_PC; + + enum PixelFormat d_fmt = imgfmt2pixfmt(dst->imgfmt); + int d_csp = mp_csp_to_sws_colorspace(mp_image_csp(dst)); + int d_range = mp_image_levels(dst) == MP_CSP_LEVELS_PC; + + // Work around libswscale bug #1852 (fixed in ffmpeg commit 8edf9b1fa): + // setting range flags for RGB gives random bogus results. + // Newer libswscale always ignores range flags for RGB. + bool s_yuv = src->flags & MP_IMGFLAG_YUV; + bool d_yuv = dst->flags & MP_IMGFLAG_YUV; + s_range = s_range && s_yuv; + d_range = d_range && d_yuv; + + struct SwsContext *sws = sws_alloc_context(); + + av_opt_set_int(sws, "sws_flags", my_sws_flags, 0); + + av_opt_set_int(sws, "srcw", src->w, 0); + av_opt_set_int(sws, "srch", src->h, 0); + av_opt_set_int(sws, "src_format", s_fmt, 0); + + av_opt_set_int(sws, "dstw", dst->w, 0); + av_opt_set_int(sws, "dsth", dst->h, 0); + av_opt_set_int(sws, "dst_format", d_fmt, 0); + + sws_setColorspaceDetails(sws, sws_getCoefficients(s_csp), s_range, + sws_getCoefficients(d_csp), d_range, + 0, 1 << 16, 1 << 16); + + int res = sws_init_context(sws, NULL, NULL); + assert(res >= 0); + + sws_scale(sws, (const uint8_t *const *) src->planes, src->stride, + 0, src->h, dst->planes, dst->stride); + sws_freeContext(sws); +} + +// vim: ts=4 sw=4 et tw=80 |