diff options
Diffstat (limited to 'libavfilter')
140 files changed, 27972 insertions, 598 deletions
diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 1a6fd9b68f..e29fe5eabd 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -1,9 +1,12 @@ +include $(SUBDIR)../config.mak + NAME = avfilter FFLIBS = avutil FFLIBS-$(CONFIG_MOVIE_FILTER) += avformat avcodec FFLIBS-$(CONFIG_SCALE_FILTER) += swscale +FFLIBS-$(CONFIG_MP_FILTER) += avcodec -HEADERS = avfilter.h avfiltergraph.h +HEADERS = avcodec.h avfilter.h avfiltergraph.h vsink_buffer.h vsrc_buffer.h OBJS = allfilters.o \ avfilter.o \ @@ -13,6 +16,8 @@ OBJS = allfilters.o \ formats.o \ graphparser.o \ +OBJS-$(CONFIG_AVCODEC) += avcodec.o + OBJS-$(CONFIG_ANULL_FILTER) += af_anull.o OBJS-$(CONFIG_ANULLSRC_FILTER) += asrc_anullsrc.o @@ -20,6 +25,7 @@ OBJS-$(CONFIG_ANULLSRC_FILTER) += asrc_anullsrc.o OBJS-$(CONFIG_ANULLSINK_FILTER) += asink_anullsink.o OBJS-$(CONFIG_BLACKFRAME_FILTER) += vf_blackframe.o +OBJS-$(CONFIG_BOXBLUR_FILTER) += vf_boxblur.o OBJS-$(CONFIG_COPY_FILTER) += vf_copy.o OBJS-$(CONFIG_CROP_FILTER) += vf_crop.o OBJS-$(CONFIG_CROPDETECT_FILTER) += vf_cropdetect.o @@ -33,6 +39,11 @@ OBJS-$(CONFIG_FREI0R_FILTER) += vf_frei0r.o OBJS-$(CONFIG_GRADFUN_FILTER) += vf_gradfun.o OBJS-$(CONFIG_HFLIP_FILTER) += vf_hflip.o OBJS-$(CONFIG_HQDN3D_FILTER) += vf_hqdn3d.o +OBJS-$(CONFIG_LUT_FILTER) += vf_lut.o +OBJS-$(CONFIG_LUTRGB_FILTER) += vf_lut.o +OBJS-$(CONFIG_LUTYUV_FILTER) += vf_lut.o +OBJS-$(CONFIG_MP_FILTER) += vf_mp.o +OBJS-$(CONFIG_NEGATE_FILTER) += vf_lut.o OBJS-$(CONFIG_NOFORMAT_FILTER) += vf_format.o OBJS-$(CONFIG_NULL_FILTER) += vf_null.o OBJS-$(CONFIG_OCV_FILTER) += vf_libopencv.o @@ -40,11 +51,14 @@ OBJS-$(CONFIG_OVERLAY_FILTER) += vf_overlay.o OBJS-$(CONFIG_PAD_FILTER) += vf_pad.o OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o OBJS-$(CONFIG_SCALE_FILTER) += vf_scale.o +OBJS-$(CONFIG_SELECT_FILTER) += vf_select.o OBJS-$(CONFIG_SETDAR_FILTER) += vf_aspect.o OBJS-$(CONFIG_SETPTS_FILTER) += vf_setpts.o OBJS-$(CONFIG_SETSAR_FILTER) += vf_aspect.o OBJS-$(CONFIG_SETTB_FILTER) += vf_settb.o +OBJS-$(CONFIG_SHOWINFO_FILTER) += vf_showinfo.o OBJS-$(CONFIG_SLICIFY_FILTER) += vf_slicify.o +OBJS-$(CONFIG_SPLIT_FILTER) += vf_split.o OBJS-$(CONFIG_TRANSPOSE_FILTER) += vf_transpose.o OBJS-$(CONFIG_UNSHARP_FILTER) += vf_unsharp.o OBJS-$(CONFIG_VFLIP_FILTER) += vf_vflip.o @@ -55,12 +69,78 @@ OBJS-$(CONFIG_COLOR_FILTER) += vsrc_color.o OBJS-$(CONFIG_FREI0R_SRC_FILTER) += vf_frei0r.o OBJS-$(CONFIG_MOVIE_FILTER) += vsrc_movie.o OBJS-$(CONFIG_NULLSRC_FILTER) += vsrc_nullsrc.o +OBJS-$(CONFIG_TESTSRC_FILTER) += vsrc_testsrc.o +OBJS-$(CONFIG_BUFFERSINK_FILTER) += vsink_buffer.o OBJS-$(CONFIG_NULLSINK_FILTER) += vsink_nullsink.o + +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/mp_image.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/img_format.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_2xsai.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_blackframe.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_boxblur.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_cropdetect.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_decimate.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_delogo.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_denoise3d.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_detc.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_dint.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_divtc.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_down3dright.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_dsize.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_eq2.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_eq.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_field.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_fil.o +#OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_filmdint.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_fixpts.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_framestep.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_fspp.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_geq.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_gradfun.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_harddup.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_hqdn3d.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_hue.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_il.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_ilpack.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_ivtc.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_kerndeint.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_mcdeint.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_mirror.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_noise.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_ow.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_palette.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_perspective.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_phase.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_pp7.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_pullup.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_qp.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_rectangle.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_remove_logo.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_rgbtest.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_rotate.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_sab.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_screenshot.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_smartblur.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_softpulldown.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_softskip.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_spp.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_swapuv.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_telecine.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_test.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_tile.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_tinterlace.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_unsharp.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_uspp.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_yuvcsp.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_yvu9.o +OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/pullup.o + + -include $(SRC_PATH)/$(SUBDIR)$(ARCH)/Makefile -DIRS = x86 +DIRS = x86 libmpcodecs TOOLS = graph2dot lavfi-showfiltfmts diff --git a/libavfilter/af_anull.c b/libavfilter/af_anull.c index e2bed36f0a..94e7e17b48 100644 --- a/libavfilter/af_anull.c +++ b/libavfilter/af_anull.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index e29b4f97bd..8d80957cff 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -2,20 +2,20 @@ * filter registration * Copyright (c) 2008 Vitor Sessak * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -41,6 +41,7 @@ void avfilter_register_all(void) REGISTER_FILTER (ANULLSINK, anullsink, asink); REGISTER_FILTER (BLACKFRAME, blackframe, vf); + REGISTER_FILTER (BOXBLUR, boxblur, vf); REGISTER_FILTER (COPY, copy, vf); REGISTER_FILTER (CROP, crop, vf); REGISTER_FILTER (CROPDETECT, cropdetect, vf); @@ -54,6 +55,11 @@ void avfilter_register_all(void) REGISTER_FILTER (GRADFUN, gradfun, vf); REGISTER_FILTER (HFLIP, hflip, vf); REGISTER_FILTER (HQDN3D, hqdn3d, vf); + REGISTER_FILTER (LUT, lut, vf); + REGISTER_FILTER (LUTRGB, lutrgb, vf); + REGISTER_FILTER (LUTYUV, lutyuv, vf); + REGISTER_FILTER (MP, mp, vf); + REGISTER_FILTER (NEGATE, negate, vf); REGISTER_FILTER (NOFORMAT, noformat, vf); REGISTER_FILTER (NULL, null, vf); REGISTER_FILTER (OCV, ocv, vf); @@ -61,11 +67,14 @@ void avfilter_register_all(void) REGISTER_FILTER (PAD, pad, vf); REGISTER_FILTER (PIXDESCTEST, pixdesctest, vf); REGISTER_FILTER (SCALE, scale, vf); + REGISTER_FILTER (SELECT, select, vf); REGISTER_FILTER (SETDAR, setdar, vf); REGISTER_FILTER (SETPTS, setpts, vf); REGISTER_FILTER (SETSAR, setsar, vf); REGISTER_FILTER (SETTB, settb, vf); + REGISTER_FILTER (SHOWINFO, showinfo, vf); REGISTER_FILTER (SLICIFY, slicify, vf); + REGISTER_FILTER (SPLIT, split, vf); REGISTER_FILTER (TRANSPOSE, transpose, vf); REGISTER_FILTER (UNSHARP, unsharp, vf); REGISTER_FILTER (VFLIP, vflip, vf); @@ -76,6 +85,8 @@ void avfilter_register_all(void) REGISTER_FILTER (FREI0R, frei0r_src, vsrc); REGISTER_FILTER (MOVIE, movie, vsrc); REGISTER_FILTER (NULLSRC, nullsrc, vsrc); + REGISTER_FILTER (TESTSRC, testsrc, vsrc); + REGISTER_FILTER (BUFFER, buffersink, vsink); REGISTER_FILTER (NULLSINK, nullsink, vsink); } diff --git a/libavfilter/asink_anullsink.c b/libavfilter/asink_anullsink.c index 3a505e79f2..5a89c2792e 100644 --- a/libavfilter/asink_anullsink.c +++ b/libavfilter/asink_anullsink.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavfilter/asrc_anullsrc.c b/libavfilter/asrc_anullsrc.c index dd671c5d53..4f49c3f186 100644 --- a/libavfilter/asrc_anullsrc.c +++ b/libavfilter/asrc_anullsrc.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavfilter/avcodec.c b/libavfilter/avcodec.c new file mode 100644 index 0000000000..2010040d14 --- /dev/null +++ b/libavfilter/avcodec.c @@ -0,0 +1,73 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * libavcodec/libavfilter gluing utilities + */ + +#include "avcodec.h" + +void avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src) +{ + dst->pts = src->pts; + dst->pos = src->pkt_pos; + dst->format = src->format; + + switch (dst->type) { + case AVMEDIA_TYPE_VIDEO: + dst->video->w = src->width; + dst->video->h = src->height; + dst->video->sample_aspect_ratio = src->sample_aspect_ratio; + dst->video->interlaced = src->interlaced_frame; + dst->video->top_field_first = src->top_field_first; + dst->video->key_frame = src->key_frame; + dst->video->pict_type = src->pict_type; + } +} + +AVFilterBufferRef *avfilter_get_video_buffer_ref_from_frame(const AVFrame *frame, + int perms) +{ + AVFilterBufferRef *picref = + avfilter_get_video_buffer_ref_from_arrays(frame->data, frame->linesize, perms, + frame->width, frame->height, + frame->format); + if (!picref) + return NULL; + avfilter_copy_frame_props(picref, frame); + return picref; +} + +int avfilter_fill_frame_from_video_buffer_ref(AVFrame *frame, + const AVFilterBufferRef *picref) +{ + if (!picref || !picref->video || !frame) + return AVERROR(EINVAL); + + memcpy(frame->data, picref->data, sizeof(frame->data)); + memcpy(frame->linesize, picref->linesize, sizeof(frame->linesize)); + frame->pkt_pos = picref->pos; + frame->interlaced_frame = picref->video->interlaced; + frame->top_field_first = picref->video->top_field_first; + frame->key_frame = picref->video->key_frame; + frame->pict_type = picref->video->pict_type; + frame->sample_aspect_ratio = picref->video->sample_aspect_ratio; + + return 0; +} diff --git a/libavfilter/avcodec.h b/libavfilter/avcodec.h new file mode 100644 index 0000000000..dec5ae4a7c --- /dev/null +++ b/libavfilter/avcodec.h @@ -0,0 +1,71 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_AVCODEC_H +#define AVFILTER_AVCODEC_H + +/** + * @file + * libavcodec/libavfilter gluing utilities + * + * This should be included in an application ONLY if the installed + * libavfilter has been compiled with libavcodec support, otherwise + * symbols defined below will not be available. + */ + +#include "libavcodec/avcodec.h" // AVFrame +#include "avfilter.h" +#include "vsrc_buffer.h" + +/** + * Copy the frame properties of src to dst, without copying the actual + * image data. + */ +void avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src); + +/** + * Create and return a picref reference from the data and properties + * contained in frame. + * + * @param perms permissions to assign to the new buffer reference + */ +AVFilterBufferRef *avfilter_get_video_buffer_ref_from_frame(const AVFrame *frame, int perms); + +/** + * Fill an AVFrame with the information stored in picref. + * + * @param frame an already allocated AVFrame + * @param picref a video buffer reference + * @return 0 in case of success, a negative AVERROR code in case of + * failure + */ +int avfilter_fill_frame_from_video_buffer_ref(AVFrame *frame, + const AVFilterBufferRef *picref); + +/** + * Add frame data to buffer_src. + * + * @param buffer_src pointer to a buffer source context + * @param flags a combination of AV_VSRC_BUF_FLAG_* flags + * @return >= 0 in case of success, a negative AVERROR code in case of + * failure + */ +int av_vsrc_buffer_add_frame(AVFilterContext *buffer_src, + const AVFrame *frame, int flags); + +#endif /* AVFILTER_AVCODEC_H */ diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index abeae14f79..a57677c0e4 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -2,20 +2,20 @@ * filter layer * Copyright (c) 2007 Bobby Bingham * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -25,6 +25,7 @@ #include "libavutil/rational.h" #include "libavutil/audioconvert.h" #include "libavutil/imgutils.h" +#include "libavutil/avassert.h" #include "avfilter.h" #include "internal.h" @@ -34,13 +35,13 @@ unsigned avfilter_version(void) { const char *avfilter_configuration(void) { - return LIBAV_CONFIGURATION; + return FFMPEG_CONFIGURATION; } const char *avfilter_license(void) { #define LICENSE_PREFIX "libavfilter license: " - return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1; + return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; } AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask) @@ -69,14 +70,47 @@ AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask) return ret; } +static void store_in_pool(AVFilterBufferRef *ref) +{ + int i; + AVFilterPool *pool= ref->buf->priv; + + av_assert0(ref->buf->data[0]); + + if (pool->count == POOL_SIZE) { + AVFilterBufferRef *ref1 = pool->pic[0]; + av_freep(&ref1->video); + av_freep(&ref1->audio); + av_freep(&ref1->buf->data[0]); + av_freep(&ref1->buf); + av_free(ref1); + memmove(&pool->pic[0], &pool->pic[1], sizeof(void*)*(POOL_SIZE-1)); + pool->count--; + pool->pic[POOL_SIZE-1] = NULL; + } + + for (i = 0; i < POOL_SIZE; i++) { + if (!pool->pic[i]) { + pool->pic[i] = ref; + pool->count++; + break; + } + } +} + void avfilter_unref_buffer(AVFilterBufferRef *ref) { if (!ref) return; - if (!(--ref->buf->refcount)) + if (!(--ref->buf->refcount)) { + if (!ref->buf->free) { + store_in_pool(ref); + return; + } ref->buf->free(ref->buf); - av_free(ref->video); - av_free(ref->audio); + } + av_freep(&ref->video); + av_freep(&ref->audio); av_free(ref); } @@ -131,6 +165,32 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad, return 0; } +void avfilter_link_free(AVFilterLink **link) +{ + if (!*link) + return; + + if ((*link)->pool) { + int i; + for (i = 0; i < POOL_SIZE; i++) { + if ((*link)->pool->pic[i]) { + AVFilterBufferRef *picref = (*link)->pool->pic[i]; + /* free buffer: picrefs stored in the pool are not + * supposed to contain a free callback */ + av_freep(&picref->buf->data[0]); + av_freep(&picref->buf); + + av_freep(&picref->audio); + av_freep(&picref->video); + av_freep(&(*link)->pool->pic[i]); + } + } + (*link)->pool->count = 0; +// av_freep(&(*link)->pool); + } + av_freep(link); +} + int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, unsigned filt_srcpad_idx, unsigned filt_dstpad_idx) { @@ -158,6 +218,9 @@ int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, if (link->out_formats) avfilter_formats_changeref(&link->out_formats, &filt->outputs[filt_dstpad_idx]->out_formats); + if (link->out_chlayouts) + avfilter_formats_changeref(&link->out_chlayouts, + &filt->outputs[filt_dstpad_idx]->out_chlayouts); return 0; } @@ -215,7 +278,6 @@ int avfilter_config_links(AVFilterContext *filter) return 0; } -#ifdef DEBUG static char *ff_get_ref_perms_string(char *buf, size_t buf_size, int perms) { snprintf(buf, buf_size, "%s%s%s%s%s%s", @@ -227,7 +289,6 @@ static char *ff_get_ref_perms_string(char *buf, size_t buf_size, int perms) perms & AV_PERM_NEG_LINESIZES ? "n" : ""); return buf; } -#endif static void ff_dlog_ref(void *ctx, AVFilterBufferRef *ref, int end) { @@ -240,7 +301,7 @@ static void ff_dlog_ref(void *ctx, AVFilterBufferRef *ref, int end) if (ref->video) { av_dlog(ctx, " a:%d/%d s:%dx%d i:%c iskey:%d type:%c", - ref->video->pixel_aspect.num, ref->video->pixel_aspect.den, + ref->video->sample_aspect_ratio.num, ref->video->sample_aspect_ratio.den, ref->video->w, ref->video->h, !ref->video->interlaced ? 'P' : /* Progressive */ ref->video->top_field_first ? 'T' : 'B', /* Top / Bottom */ @@ -248,10 +309,9 @@ static void ff_dlog_ref(void *ctx, AVFilterBufferRef *ref, int end) av_get_picture_type_char(ref->video->pict_type)); } if (ref->audio) { - av_dlog(ctx, " cl:%"PRId64"d sn:%d s:%d sr:%d p:%d", + av_dlog(ctx, " cl:%"PRId64"d n:%d r:%d p:%d", ref->audio->channel_layout, ref->audio->nb_samples, - ref->audio->size, ref->audio->sample_rate, ref->audio->planar); } @@ -308,7 +368,7 @@ AVFilterBufferRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int } AVFilterBufferRef * -avfilter_get_video_buffer_ref_from_arrays(uint8_t *data[4], int linesize[4], int perms, +avfilter_get_video_buffer_ref_from_arrays(uint8_t * const data[4], const int linesize[4], int perms, int w, int h, enum PixelFormat format) { AVFilterBuffer *pic = av_mallocz(sizeof(AVFilterBuffer)); @@ -348,16 +408,16 @@ fail: } AVFilterBufferRef *avfilter_get_audio_buffer(AVFilterLink *link, int perms, - enum AVSampleFormat sample_fmt, int size, + enum AVSampleFormat sample_fmt, int nb_samples, int64_t channel_layout, int planar) { AVFilterBufferRef *ret = NULL; if (link->dstpad->get_audio_buffer) - ret = link->dstpad->get_audio_buffer(link, perms, sample_fmt, size, channel_layout, planar); + ret = link->dstpad->get_audio_buffer(link, perms, sample_fmt, nb_samples, channel_layout, planar); if (!ret) - ret = avfilter_default_get_audio_buffer(link, perms, sample_fmt, size, channel_layout, planar); + ret = avfilter_default_get_audio_buffer(link, perms, sample_fmt, nb_samples, channel_layout, planar); if (ret) ret->type = AVMEDIA_TYPE_AUDIO; @@ -365,6 +425,48 @@ AVFilterBufferRef *avfilter_get_audio_buffer(AVFilterLink *link, int perms, return ret; } +AVFilterBufferRef * +avfilter_get_audio_buffer_ref_from_arrays(uint8_t *data[8], int linesize[8], int perms, + int nb_samples, enum AVSampleFormat sample_fmt, + int64_t channel_layout, int planar) +{ + AVFilterBuffer *samples = av_mallocz(sizeof(AVFilterBuffer)); + AVFilterBufferRef *samplesref = av_mallocz(sizeof(AVFilterBufferRef)); + + if (!samples || !samplesref) + goto fail; + + samplesref->buf = samples; + samplesref->buf->free = ff_avfilter_default_free_buffer; + if (!(samplesref->audio = av_mallocz(sizeof(AVFilterBufferRefAudioProps)))) + goto fail; + + samplesref->audio->nb_samples = nb_samples; + samplesref->audio->channel_layout = channel_layout; + samplesref->audio->planar = planar; + + /* make sure the buffer gets read permission or it's useless for output */ + samplesref->perms = perms | AV_PERM_READ; + + samples->refcount = 1; + samplesref->type = AVMEDIA_TYPE_AUDIO; + samplesref->format = sample_fmt; + + memcpy(samples->data, data, sizeof(samples->data)); + memcpy(samples->linesize, linesize, sizeof(samples->linesize)); + memcpy(samplesref->data, data, sizeof(samplesref->data)); + memcpy(samplesref->linesize, linesize, sizeof(samplesref->linesize)); + + return samplesref; + +fail: + if (samplesref && samplesref->audio) + av_freep(&samplesref->audio); + av_freep(&samplesref); + av_freep(&samples); + return NULL; +} + int avfilter_request_frame(AVFilterLink *link) { FF_DPRINTF_START(NULL, request_frame); ff_dlog_link(NULL, link, 1); @@ -488,6 +590,7 @@ void avfilter_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) { void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *); AVFilterPad *dst = link->dstpad; + int i; FF_DPRINTF_START(NULL, filter_samples); ff_dlog_link(NULL, link, 1); @@ -504,14 +607,15 @@ void avfilter_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) link->cur_buf = avfilter_default_get_audio_buffer(link, dst->min_perms, samplesref->format, - samplesref->audio->size, + samplesref->audio->nb_samples, samplesref->audio->channel_layout, samplesref->audio->planar); link->cur_buf->pts = samplesref->pts; link->cur_buf->audio->sample_rate = samplesref->audio->sample_rate; /* Copy actual data into new samples buffer */ - memcpy(link->cur_buf->data[0], samplesref->data[0], samplesref->audio->size); + for (i = 0; samplesref->data[i]; i++) + memcpy(link->cur_buf->data[i], samplesref->data[i], samplesref->linesize[0]); avfilter_unref_buffer(samplesref); } else @@ -651,7 +755,7 @@ void avfilter_free(AVFilterContext *filter) avfilter_formats_unref(&link->in_formats); avfilter_formats_unref(&link->out_formats); } - av_freep(&link); + avfilter_link_free(&link); } for (i = 0; i < filter->output_count; i++) { if ((link = filter->outputs[i])) { @@ -660,7 +764,7 @@ void avfilter_free(AVFilterContext *filter) avfilter_formats_unref(&link->in_formats); avfilter_formats_unref(&link->out_formats); } - av_freep(&link); + avfilter_link_free(&link); } av_freep(&filter->name); diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index f8295e77c5..3e1acea542 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -2,20 +2,20 @@ * filter layer * Copyright (c) 2007 Bobby Bingham * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -29,7 +29,7 @@ #include "libavutil/rational.h" #define LIBAVFILTER_VERSION_MAJOR 2 -#define LIBAVFILTER_VERSION_MINOR 4 +#define LIBAVFILTER_VERSION_MINOR 25 #define LIBAVFILTER_VERSION_MICRO 0 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ @@ -101,8 +101,7 @@ typedef struct AVFilterBuffer { */ typedef struct AVFilterBufferRefAudioProps { int64_t channel_layout; ///< channel layout of audio buffer - int nb_samples; ///< number of audio samples - int size; ///< audio buffer size + int nb_samples; ///< number of audio samples per channel uint32_t sample_rate; ///< audio buffer sample rate int planar; ///< audio buffer - planar or packed } AVFilterBufferRefAudioProps; @@ -115,7 +114,7 @@ typedef struct AVFilterBufferRefAudioProps { typedef struct AVFilterBufferRefVideoProps { int w; ///< image width int h; ///< image height - AVRational pixel_aspect; ///< pixel aspect ratio + AVRational sample_aspect_ratio; ///< sample aspect ratio int interlaced; ///< is frame interlaced int top_field_first; ///< field order enum AVPictureType pict_type; ///< picture type of the frame @@ -163,6 +162,7 @@ static inline void avfilter_copy_buffer_ref_props(AVFilterBufferRef *dst, AVFilt switch (src->type) { case AVMEDIA_TYPE_VIDEO: *dst->video = *src->video; break; case AVMEDIA_TYPE_AUDIO: *dst->audio = *src->audio; break; + default: break; } } @@ -227,7 +227,7 @@ void avfilter_unref_buffer(AVFilterBufferRef *ref); */ typedef struct AVFilterFormats { unsigned format_count; ///< number of formats - int *formats; ///< list of media formats + int64_t *formats; ///< list of media formats unsigned refcount; ///< number of references to this list struct AVFilterFormats ***refs; ///< references to this list @@ -237,10 +237,12 @@ typedef struct AVFilterFormats { * Create a list of supported formats. This is intended for use in * AVFilter->query_formats(). * - * @param fmts list of media formats, terminated by -1 + * @param fmts list of media formats, terminated by -1. If NULL an + * empty list is created. * @return the format list, with no existing references */ AVFilterFormats *avfilter_make_format_list(const int *fmts); +AVFilterFormats *avfilter_make_format64_list(const int64_t *fmts); /** * Add fmt to the list of media formats contained in *avff. @@ -250,14 +252,19 @@ AVFilterFormats *avfilter_make_format_list(const int *fmts); * @return a non negative value in case of success, or a negative * value corresponding to an AVERROR code in case of error */ -int avfilter_add_format(AVFilterFormats **avff, int fmt); +int avfilter_add_format(AVFilterFormats **avff, int64_t fmt); /** - * Return a list of all formats supported by Libav for the given media type. + * Return a list of all formats supported by FFmpeg for the given media type. */ AVFilterFormats *avfilter_all_formats(enum AVMediaType type); /** + * Return a list of all channel layouts supported by FFmpeg. + */ +AVFilterFormats *avfilter_all_channel_layouts(void); + +/** * Return a format list which contains the intersection of the formats of * a and b. Also, all the references of a, all the references of b, and * a and b themselves will be deallocated. @@ -375,7 +382,7 @@ struct AVFilterPad { * Input audio pads only. */ AVFilterBufferRef *(*get_audio_buffer)(AVFilterLink *link, int perms, - enum AVSampleFormat sample_fmt, int size, + enum AVSampleFormat sample_fmt, int nb_samples, int64_t channel_layout, int planar); /** @@ -464,15 +471,17 @@ AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, /** default handler for get_audio_buffer() for audio inputs */ AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link, int perms, - enum AVSampleFormat sample_fmt, int size, + enum AVSampleFormat sample_fmt, int nb_samples, int64_t channel_layout, int planar); /** - * A helper for query_formats() which sets all links to the same list of - * formats. If there are no links hooked to this filter, the list of formats is - * freed. + * Helpers for query_formats() which set all links to the same list of + * formats/layouts. If there are no links hooked to this filter, the list + * of formats is freed. */ -void avfilter_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats); +void avfilter_set_common_pixel_formats(AVFilterContext *ctx, AVFilterFormats *formats); +void avfilter_set_common_sample_formats(AVFilterContext *ctx, AVFilterFormats *formats); +void avfilter_set_common_channel_layouts(AVFilterContext *ctx, AVFilterFormats *formats); /** Default handler for query_formats() */ int avfilter_default_query_formats(AVFilterContext *ctx); @@ -523,9 +532,9 @@ typedef struct AVFilter { void (*uninit)(AVFilterContext *ctx); /** - * Queries formats supported by the filter and its pads, and sets the - * in_formats for links connected to its output pads, and out_formats - * for links connected to its input pads. + * Queries formats/layouts supported by the filter and its pads, and sets + * the in_formats/in_chlayouts for links connected to its output pads, + * and out_formats/out_chlayouts for links connected to its input pads. * * @return zero on success, a negative value corresponding to an * AVERROR code otherwise @@ -595,13 +604,18 @@ struct AVFilterLink { int format; ///< agreed upon media format /** - * Lists of formats supported by the input and output filters respectively. - * These lists are used for negotiating the format to actually be used, - * which will be loaded into the format member, above, when chosen. + * Lists of formats and channel layouts supported by the input and output + * filters respectively. These lists are used for negotiating the format + * to actually be used, which will be loaded into the format and + * channel_layout members, above, when chosen. + * */ AVFilterFormats *in_formats; AVFilterFormats *out_formats; + AVFilterFormats *in_chlayouts; + AVFilterFormats *out_chlayouts; + /** * The buffer reference currently being sent across the link by the source * filter. This is used internally by the filter system to allow @@ -622,6 +636,8 @@ struct AVFilterLink { * input link is assumed to be an unchangeable property. */ AVRational time_base; + + struct AVFilterPool *pool; }; /** @@ -637,6 +653,11 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad, AVFilterContext *dst, unsigned dstpad); /** + * Free the link in *link, and set its pointer to NULL. + */ +void avfilter_link_free(AVFilterLink **link); + +/** * Negotiate the media format, dimensions, etc of all inputs to a filter. * * @param filter the filter to negotiate the properties for its inputs @@ -670,7 +691,7 @@ AVFilterBufferRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, * @param format the pixel format of the image specified by the data and linesize arrays */ AVFilterBufferRef * -avfilter_get_video_buffer_ref_from_arrays(uint8_t *data[4], int linesize[4], int perms, +avfilter_get_video_buffer_ref_from_arrays(uint8_t * const data[4], const int linesize[4], int perms, int w, int h, enum PixelFormat format); /** @@ -680,17 +701,34 @@ avfilter_get_video_buffer_ref_from_arrays(uint8_t *data[4], int linesize[4], int * be requested * @param perms the required access permissions * @param sample_fmt the format of each sample in the buffer to allocate - * @param size the buffer size in bytes + * @param nb_samples the number of samples per channel * @param channel_layout the number and type of channels per sample in the buffer to allocate * @param planar audio data layout - planar or packed * @return A reference to the samples. This must be unreferenced with * avfilter_unref_buffer when you are finished with it. */ AVFilterBufferRef *avfilter_get_audio_buffer(AVFilterLink *link, int perms, - enum AVSampleFormat sample_fmt, int size, + enum AVSampleFormat sample_fmt, int nb_samples, int64_t channel_layout, int planar); /** + * Create an audio buffer reference wrapped around an already + * allocated samples buffer. + * + * @param data pointers to the samples plane buffers + * @param linesize linesize for the samples plane buffers + * @param perms the required access permissions + * @param nb_samples number of samples per channel + * @param sample_fmt the format of each sample in the buffer to allocate + * @param channel_layout the channel layout of the buffer + * @param planar audio data layout - planar or packed + */ +AVFilterBufferRef * +avfilter_get_audio_buffer_ref_from_arrays(uint8_t *data[8], int linesize[8], int perms, + int nb_samples, enum AVSampleFormat sample_fmt, + int64_t channel_layout, int planar); + +/** * Request an input frame from the filter at the other end of the link. * * @param link the input link diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index b503c366f8..04768617de 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -3,20 +3,20 @@ * Copyright (c) 2008 Vitor Sessak * Copyright (c) 2007 Bobby Bingham * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -90,7 +90,7 @@ int ff_avfilter_graph_check_validity(AVFilterGraph *graph, AVClass *log_ctx) av_log(log_ctx, AV_LOG_ERROR, "Input pad \"%s\" for the filter \"%s\" of type \"%s\" not connected to any source\n", filt->input_pads[j].name, filt->name, filt->filter->name); - return -1; + return AVERROR(EINVAL); } } @@ -99,7 +99,7 @@ int ff_avfilter_graph_check_validity(AVFilterGraph *graph, AVClass *log_ctx) av_log(log_ctx, AV_LOG_ERROR, "Output pad \"%s\" for the filter \"%s\" of type \"%s\" not connected to any destination\n", filt->output_pads[j].name, filt->name, filt->filter->name); - return -1; + return AVERROR(EINVAL); } } } @@ -178,7 +178,7 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) av_log(log_ctx, AV_LOG_ERROR, "Impossible to convert between the formats supported by the filter " "'%s' and the filter '%s'\n", link->src->name, link->dst->name); - return -1; + return AVERROR(EINVAL); } } } @@ -195,9 +195,16 @@ static void pick_format(AVFilterLink *link) link->in_formats->format_count = 1; link->format = link->in_formats->formats[0]; - avfilter_formats_unref(&link->in_formats); avfilter_formats_unref(&link->out_formats); + + if (link->type == AVMEDIA_TYPE_AUDIO) { + link->in_chlayouts->format_count = 1; + link->channel_layout = link->in_chlayouts->formats[0]; + avfilter_formats_unref(&link->in_chlayouts); + avfilter_formats_unref(&link->out_chlayouts); + } + } static void pick_formats(AVFilterGraph *graph) @@ -216,9 +223,11 @@ static void pick_formats(AVFilterGraph *graph) int ff_avfilter_graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx) { + int ret; + /* find supported formats from sub-filters, and merge along links */ - if (query_formats(graph, log_ctx)) - return -1; + if ((ret = query_formats(graph, log_ctx)) < 0) + return ret; /* Once everything is merged, it's possible that we'll still have * multiple valid media format choices. We pick the first one. */ @@ -227,7 +236,7 @@ int ff_avfilter_graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx) return 0; } -int avfilter_graph_config(AVFilterGraph *graphctx, AVClass *log_ctx) +int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx) { int ret; diff --git a/libavfilter/avfiltergraph.h b/libavfilter/avfiltergraph.h index a0f6b2e01f..f4c88bc796 100644 --- a/libavfilter/avfiltergraph.h +++ b/libavfilter/avfiltergraph.h @@ -2,20 +2,20 @@ * Filter graphs * copyright (c) 2007 Bobby Bingham * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -76,7 +76,7 @@ int avfilter_graph_create_filter(AVFilterContext **filt_ctx, AVFilter *filt, * @param log_ctx context used for logging * @return 0 in case of success, a negative AVERROR code otherwise */ -int avfilter_graph_config(AVFilterGraph *graphctx, AVClass *log_ctx); +int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx); /** * Free a graph, destroy its links, and set *graph to NULL. @@ -108,16 +108,32 @@ typedef struct AVFilterInOut { } AVFilterInOut; /** + * Create an AVFilterInOut. + * Must be free with avfilter_inout_free(). + */ +AVFilterInOut *avfilter_inout_alloc(void); + +/** + * Free the AVFilterInOut in *inout, and set its pointer to NULL. + * If *inout is NULL, do nothing. + */ +void avfilter_inout_free(AVFilterInOut **inout); + +/** * Add a graph described by a string to a graph. * * @param graph the filter graph where to link the parsed graph context * @param filters string to be parsed - * @param inputs linked list to the inputs of the graph - * @param outputs linked list to the outputs of the graph + * @param inputs pointer to a linked list to the inputs of the graph, may be NULL. + * If non-NULL, *inputs is updated to contain the list of open inputs + * after the parsing, should be freed with avfilter_inout_free(). + * @param outputs pointer to a linked list to the outputs of the graph, may be NULL. + * If non-NULL, *outputs is updated to contain the list of open outputs + * after the parsing, should be freed with avfilter_inout_free(). * @return zero on success, a negative AVERROR code on error */ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, - AVFilterInOut *inputs, AVFilterInOut *outputs, - AVClass *log_ctx); + AVFilterInOut **inputs, AVFilterInOut **outputs, + void *log_ctx); #endif /* AVFILTER_AVFILTERGRAPH_H */ diff --git a/libavfilter/defaults.c b/libavfilter/defaults.c index b891ab1f22..b03816dd24 100644 --- a/libavfilter/defaults.c +++ b/libavfilter/defaults.c @@ -2,20 +2,20 @@ * Filter layer - default implementations * Copyright (c) 2007 Bobby Bingham * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -25,7 +25,6 @@ #include "avfilter.h" #include "internal.h" -/* TODO: buffer pool. see comment for avfilter_default_get_video_buffer() */ void ff_avfilter_default_free_buffer(AVFilterBuffer *ptr) { av_free(ptr->data[0]); @@ -39,10 +38,32 @@ AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int per { int linesize[4]; uint8_t *data[4]; + int i; AVFilterBufferRef *picref = NULL; + AVFilterPool *pool = link->pool; + + if (pool) { + for (i = 0; i < POOL_SIZE; i++) { + picref = pool->pic[i]; + if (picref && picref->buf->format == link->format && picref->buf->w == w && picref->buf->h == h) { + AVFilterBuffer *pic = picref->buf; + pool->pic[i] = NULL; + pool->count--; + picref->video->w = w; + picref->video->h = h; + picref->perms = perms | AV_PERM_READ; + picref->format = link->format; + pic->refcount = 1; + memcpy(picref->data, pic->data, sizeof(picref->data)); + memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize)); + return picref; + } + } + } else + pool = link->pool = av_mallocz(sizeof(AVFilterPool)); - // +2 is needed for swscaler, +16 to be SIMD-friendly - if (av_image_alloc(data, linesize, w, h, link->format, 16) < 0) + // align: +2 is needed for swscaler, +16 to be SIMD-friendly + if ((i = av_image_alloc(data, linesize, w, h, link->format, 16)) < 0) return NULL; picref = avfilter_get_video_buffer_ref_from_arrays(data, linesize, @@ -51,86 +72,39 @@ AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int per av_free(data[0]); return NULL; } + memset(data[0], 128, i); + + picref->buf->priv = pool; + picref->buf->free = NULL; return picref; } AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link, int perms, - enum AVSampleFormat sample_fmt, int size, + enum AVSampleFormat sample_fmt, int nb_samples, int64_t channel_layout, int planar) { - AVFilterBuffer *samples = av_mallocz(sizeof(AVFilterBuffer)); - AVFilterBufferRef *ref = NULL; - int i, sample_size, chans_nb, bufsize, per_channel_size, step_size = 0; - char *buf; - - if (!samples || !(ref = av_mallocz(sizeof(AVFilterBufferRef)))) - goto fail; - - ref->buf = samples; - ref->format = sample_fmt; - - ref->audio = av_mallocz(sizeof(AVFilterBufferRefAudioProps)); - if (!ref->audio) - goto fail; - - ref->audio->channel_layout = channel_layout; - ref->audio->size = size; - ref->audio->planar = planar; - - /* make sure the buffer gets read permission or it's useless for output */ - ref->perms = perms | AV_PERM_READ; - - samples->refcount = 1; - samples->free = ff_avfilter_default_free_buffer; - - sample_size = av_get_bytes_per_sample(sample_fmt); - chans_nb = av_get_channel_layout_nb_channels(channel_layout); - - per_channel_size = size/chans_nb; - ref->audio->nb_samples = per_channel_size/sample_size; - - /* Set the number of bytes to traverse to reach next sample of a particular channel: - * For planar, this is simply the sample size. - * For packed, this is the number of samples * sample_size. - */ - for (i = 0; i < chans_nb; i++) - samples->linesize[i] = planar > 0 ? per_channel_size : sample_size; - memset(&samples->linesize[chans_nb], 0, (8-chans_nb) * sizeof(samples->linesize[0])); + AVFilterBufferRef *samplesref = NULL; + int linesize[8]; + uint8_t *data[8]; + int nb_channels = av_get_channel_layout_nb_channels(channel_layout); /* Calculate total buffer size, round to multiple of 16 to be SIMD friendly */ - bufsize = (size + 15)&~15; - buf = av_malloc(bufsize); - if (!buf) - goto fail; - - /* For planar, set the start point of each channel's data within the buffer - * For packed, set the start point of the entire buffer only - */ - samples->data[0] = buf; - if (buf && planar) { - for (i = 1; i < chans_nb; i++) { - step_size += per_channel_size; - samples->data[i] = buf + step_size; - } - } else { - for (i = 1; i < chans_nb; i++) - samples->data[i] = buf; - } - - memset(&samples->data[chans_nb], 0, (8-chans_nb) * sizeof(samples->data[0])); - - memcpy(ref->data, samples->data, sizeof(ref->data)); - memcpy(ref->linesize, samples->linesize, sizeof(ref->linesize)); + if (av_samples_alloc(data, linesize, + nb_channels, nb_samples, sample_fmt, + planar, 16) < 0) + return NULL; - return ref; + samplesref = + avfilter_get_audio_buffer_ref_from_arrays(data, linesize, perms, + nb_samples, sample_fmt, + channel_layout, planar); + if (!samplesref) { + av_free(data[0]); + return NULL; + } -fail: - if (ref) - av_free(ref->audio); - av_free(ref); - av_free(samples); - return NULL; + return samplesref; } void avfilter_default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) @@ -187,7 +161,7 @@ void avfilter_default_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *sa if (outlink) { outlink->out_buf = avfilter_default_get_audio_buffer(inlink, AV_PERM_WRITE, samplesref->format, - samplesref->audio->size, + samplesref->audio->nb_samples, samplesref->audio->channel_layout, samplesref->audio->planar); outlink->out_buf->pts = samplesref->pts; @@ -223,45 +197,54 @@ int avfilter_default_config_output_link(AVFilterLink *link) return 0; } -/** - * A helper for query_formats() which sets all links to the same list of - * formats. If there are no links hooked to this filter, the list of formats is - * freed. - * - * FIXME: this will need changed for filters with a mix of pad types - * (video + audio, etc) - */ -void avfilter_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats) +static void set_common_formats(AVFilterContext *ctx, AVFilterFormats *fmts, + enum AVMediaType type, int offin, int offout) { - int count = 0, i; - - for (i = 0; i < ctx->input_count; i++) { - if (ctx->inputs[i]) { - avfilter_formats_ref(formats, &ctx->inputs[i]->out_formats); - count++; - } - } - for (i = 0; i < ctx->output_count; i++) { - if (ctx->outputs[i]) { - avfilter_formats_ref(formats, &ctx->outputs[i]->in_formats); - count++; - } + int i; + for (i = 0; i < ctx->input_count; i++) + if (ctx->inputs[i] && ctx->inputs[i]->type == type) + avfilter_formats_ref(fmts, + (AVFilterFormats**)((void*)ctx->inputs[i]+offout)); + + for (i = 0; i < ctx->output_count; i++) + if (ctx->outputs[i] && ctx->outputs[i]->type == type) + avfilter_formats_ref(fmts, + (AVFilterFormats**)((void*)ctx->outputs[i]+offin)); + + if (!fmts->refcount) { + av_free(fmts->formats); + av_free(fmts->refs); + av_free(fmts); } +} - if (!count) { - av_free(formats->formats); - av_free(formats->refs); - av_free(formats); - } +void avfilter_set_common_pixel_formats(AVFilterContext *ctx, AVFilterFormats *formats) +{ + set_common_formats(ctx, formats, AVMEDIA_TYPE_VIDEO, + offsetof(AVFilterLink, in_formats), + offsetof(AVFilterLink, out_formats)); +} + +void avfilter_set_common_sample_formats(AVFilterContext *ctx, AVFilterFormats *formats) +{ + set_common_formats(ctx, formats, AVMEDIA_TYPE_AUDIO, + offsetof(AVFilterLink, in_formats), + offsetof(AVFilterLink, out_formats)); +} + +void avfilter_set_common_channel_layouts(AVFilterContext *ctx, AVFilterFormats *formats) +{ + set_common_formats(ctx, formats, AVMEDIA_TYPE_AUDIO, + offsetof(AVFilterLink, in_chlayouts), + offsetof(AVFilterLink, out_chlayouts)); } int avfilter_default_query_formats(AVFilterContext *ctx) { - enum AVMediaType type = ctx->inputs && ctx->inputs [0] ? ctx->inputs [0]->type : - ctx->outputs && ctx->outputs[0] ? ctx->outputs[0]->type : - AVMEDIA_TYPE_VIDEO; + avfilter_set_common_pixel_formats(ctx, avfilter_all_formats(AVMEDIA_TYPE_VIDEO)); + avfilter_set_common_sample_formats(ctx, avfilter_all_formats(AVMEDIA_TYPE_AUDIO)); + avfilter_set_common_channel_layouts(ctx, avfilter_all_channel_layouts()); - avfilter_set_common_formats(ctx, avfilter_all_formats(type)); return 0; } diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c index 6aaf5c5866..dd9ceff117 100644 --- a/libavfilter/drawutils.c +++ b/libavfilter/drawutils.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavfilter/drawutils.h b/libavfilter/drawutils.h index 7b11c06694..e838660579 100644 --- a/libavfilter/drawutils.h +++ b/libavfilter/drawutils.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavfilter/formats.c b/libavfilter/formats.c index bb7b921552..b6e30e7ab4 100644 --- a/libavfilter/formats.c +++ b/libavfilter/formats.c @@ -2,25 +2,27 @@ * Filter layer - format negotiation * Copyright (c) 2007 Bobby Bingham * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libavutil/pixdesc.h" +#include "libavutil/audioconvert.h" #include "avfilter.h" +#include "internal.h" /** * Add all refs from a to ret and destroy a. @@ -29,7 +31,7 @@ static void merge_ref(AVFilterFormats *ret, AVFilterFormats *a) { int i; - for(i = 0; i < a->refcount; i ++) { + for (i = 0; i < a->refcount; i++) { ret->refs[ret->refcount] = a->refs[i]; *ret->refs[ret->refcount++] = ret; } @@ -44,19 +46,21 @@ AVFilterFormats *avfilter_merge_formats(AVFilterFormats *a, AVFilterFormats *b) AVFilterFormats *ret; unsigned i, j, k = 0; + if (a == b) return a; + ret = av_mallocz(sizeof(AVFilterFormats)); /* merge list of formats */ ret->formats = av_malloc(sizeof(*ret->formats) * FFMIN(a->format_count, b->format_count)); - for(i = 0; i < a->format_count; i ++) - for(j = 0; j < b->format_count; j ++) - if(a->formats[i] == b->formats[j]) + for (i = 0; i < a->format_count; i++) + for (j = 0; j < b->format_count; j++) + if (a->formats[i] == b->formats[j]) ret->formats[k++] = a->formats[i]; ret->format_count = k; /* check that there was at least one common format */ - if(!ret->format_count) { + if (!ret->format_count) { av_free(ret->formats); av_free(ret); return NULL; @@ -70,31 +74,61 @@ AVFilterFormats *avfilter_merge_formats(AVFilterFormats *a, AVFilterFormats *b) return ret; } +int ff_fmt_is_in(int fmt, const int *fmts) +{ + const int *p; + + for (p = fmts; *p != -1; p++) { + if (fmt == *p) + return 1; + } + return 0; +} + +#define MAKE_FORMAT_LIST() \ + AVFilterFormats *formats; \ + int count = 0; \ + if (fmts) \ + for (count = 0; fmts[count] != -1; count++) \ + ; \ + formats = av_mallocz(sizeof(AVFilterFormats)); \ + if (!formats) return NULL; \ + formats->format_count = count; \ + if (count) { \ + formats->formats = av_malloc(sizeof(*formats->formats)*count); \ + if (!formats->formats) { \ + av_free(formats); \ + return NULL; \ + } \ + } + AVFilterFormats *avfilter_make_format_list(const int *fmts) { - AVFilterFormats *formats; - int count; + MAKE_FORMAT_LIST(); + while (count--) + formats->formats[count] = fmts[count]; - for (count = 0; fmts[count] != -1; count++) - ; + return formats; +} - formats = av_mallocz(sizeof(AVFilterFormats)); - formats->formats = av_malloc(sizeof(*formats->formats) * count); - formats->format_count = count; - memcpy(formats->formats, fmts, sizeof(*formats->formats) * count); +AVFilterFormats *avfilter_make_format64_list(const int64_t *fmts) +{ + MAKE_FORMAT_LIST(); + if (count) + memcpy(formats->formats, fmts, sizeof(*formats->formats) * count); return formats; } -int avfilter_add_format(AVFilterFormats **avff, int fmt) +int avfilter_add_format(AVFilterFormats **avff, int64_t fmt) { - int *fmts; + int64_t *fmts; if (!(*avff) && !(*avff = av_mallocz(sizeof(AVFilterFormats)))) return AVERROR(ENOMEM); fmts = av_realloc((*avff)->formats, - sizeof((*avff)->formats) * ((*avff)->format_count+1)); + sizeof(*(*avff)->formats) * ((*avff)->format_count+1)); if (!fmts) return AVERROR(ENOMEM); @@ -118,6 +152,27 @@ AVFilterFormats *avfilter_all_formats(enum AVMediaType type) return ret; } +AVFilterFormats *avfilter_all_channel_layouts(void) +{ + static int64_t chlayouts[] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_QUAD, + AV_CH_LAYOUT_5POINT0, + AV_CH_LAYOUT_5POINT0_BACK, + AV_CH_LAYOUT_5POINT1, + AV_CH_LAYOUT_5POINT1_BACK, + AV_CH_LAYOUT_5POINT1|AV_CH_LAYOUT_STEREO_DOWNMIX, + AV_CH_LAYOUT_7POINT1, + AV_CH_LAYOUT_7POINT1_WIDE, + AV_CH_LAYOUT_7POINT1|AV_CH_LAYOUT_STEREO_DOWNMIX, + -1, + }; + + return avfilter_make_format64_list(chlayouts); +} + void avfilter_formats_ref(AVFilterFormats *f, AVFilterFormats **ref) { *ref = f; @@ -128,8 +183,8 @@ void avfilter_formats_ref(AVFilterFormats *f, AVFilterFormats **ref) static int find_ref_index(AVFilterFormats **ref) { int i; - for(i = 0; i < (*ref)->refcount; i ++) - if((*ref)->refs[i] == ref) + for (i = 0; i < (*ref)->refcount; i++) + if ((*ref)->refs[i] == ref) return i; return -1; } @@ -143,11 +198,11 @@ void avfilter_formats_unref(AVFilterFormats **ref) idx = find_ref_index(ref); - if(idx >= 0) + if (idx >= 0) memmove((*ref)->refs + idx, (*ref)->refs + idx+1, sizeof(AVFilterFormats**) * ((*ref)->refcount-idx-1)); - if(!--(*ref)->refcount) { + if (!--(*ref)->refcount) { av_free((*ref)->formats); av_free((*ref)->refs); av_free(*ref); @@ -160,7 +215,7 @@ void avfilter_formats_changeref(AVFilterFormats **oldref, { int idx = find_ref_index(oldref); - if(idx >= 0) { + if (idx >= 0) { (*oldref)->refs[idx] = newref; *newref = *oldref; *oldref = NULL; diff --git a/libavfilter/gradfun.h b/libavfilter/gradfun.h index 6b192a3113..3c01085b83 100644 --- a/libavfilter/gradfun.h +++ b/libavfilter/gradfun.h @@ -2,20 +2,20 @@ * Copyright (c) 2010 Nolan Lum <nol888@gmail.com> * Copyright (c) 2009 Loren Merritt <lorenm@u.washignton.edu> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -33,16 +33,16 @@ typedef struct { int chroma_r; ///< blur radius for the chroma planes uint16_t *buf; ///< holds image data for blur algorithm passed into filter. /// DSP functions. - 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 src_linesize, int width); + void (*filter_line) (uint8_t *dst, const uint8_t *src, const uint16_t *dc, int width, int thresh, const uint16_t *dithers); + void (*blur_line) (uint16_t *dc, uint16_t *buf, const uint16_t *buf1, const uint8_t *src, int src_linesize, int width); } GradFunContext; -void ff_gradfun_filter_line_c(uint8_t *dst, uint8_t *src, uint16_t *dc, int width, int thresh, const uint16_t *dithers); -void ff_gradfun_blur_line_c(uint16_t *dc, uint16_t *buf, uint16_t *buf1, uint8_t *src, int src_linesize, int width); +void ff_gradfun_filter_line_c(uint8_t *dst, const uint8_t *src, const uint16_t *dc, int width, int thresh, const uint16_t *dithers); +void ff_gradfun_blur_line_c(uint16_t *dc, uint16_t *buf, const uint16_t *buf1, const uint8_t *src, int src_linesize, int width); -void ff_gradfun_filter_line_mmx2(uint8_t *dst, uint8_t *src, uint16_t *dc, int width, int thresh, const uint16_t *dithers); -void ff_gradfun_filter_line_ssse3(uint8_t *dst, uint8_t *src, uint16_t *dc, int width, int thresh, const uint16_t *dithers); +void ff_gradfun_filter_line_mmx2(uint8_t *dst, const uint8_t *src, const uint16_t *dc, int width, int thresh, const uint16_t *dithers); +void ff_gradfun_filter_line_ssse3(uint8_t *dst, const uint8_t *src, const uint16_t *dc, int width, int thresh, const uint16_t *dithers); -void ff_gradfun_blur_line_sse2(uint16_t *dc, uint16_t *buf, uint16_t *buf1, uint8_t *src, int src_linesize, int width); +void ff_gradfun_blur_line_sse2(uint16_t *dc, uint16_t *buf, const uint16_t *buf1, const uint8_t *src, int src_linesize, int width); #endif /* AVFILTER_GRADFUN_H */ diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c index f5e68edfa4..f38c6cfcae 100644 --- a/libavfilter/graphparser.c +++ b/libavfilter/graphparser.c @@ -3,20 +3,20 @@ * Copyright (c) 2008 Vitor Sessak * Copyright (c) 2007 Bobby Bingham * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -36,7 +36,7 @@ */ static int link_filter(AVFilterContext *src, int srcpad, AVFilterContext *dst, int dstpad, - AVClass *log_ctx) + void *log_ctx) { int ret; if ((ret = avfilter_link(src, srcpad, dst, dstpad))) { @@ -55,7 +55,7 @@ static int link_filter(AVFilterContext *src, int srcpad, * @return a pointer (that need to be freed after use) to the name * between parenthesis */ -static char *parse_link_name(const char **buf, AVClass *log_ctx) +static char *parse_link_name(const char **buf, void *log_ctx) { const char *start = *buf; char *name; @@ -92,7 +92,7 @@ static char *parse_link_name(const char **buf, AVClass *log_ctx) * @return 0 in case of success, a negative AVERROR code otherwise */ static int create_filter(AVFilterContext **filt_ctx, AVFilterGraph *ctx, int index, - const char *filt_name, const char *args, AVClass *log_ctx) + const char *filt_name, const char *args, void *log_ctx) { AVFilter *filt; char inst_name[30]; @@ -153,7 +153,7 @@ static int create_filter(AVFilterContext **filt_ctx, AVFilterGraph *ctx, int ind * @return 0 in case of success, a negative AVERROR code otherwise */ static int parse_filter(AVFilterContext **filt_ctx, const char **buf, AVFilterGraph *graph, - int index, AVClass *log_ctx) + int index, void *log_ctx) { char *opts = NULL; char *name = av_get_token(buf, "=,;[\n"); @@ -170,13 +170,18 @@ static int parse_filter(AVFilterContext **filt_ctx, const char **buf, AVFilterGr return ret; } -static void free_inout(AVFilterInOut *head) +AVFilterInOut *avfilter_inout_alloc(void) { - while (head) { - AVFilterInOut *next = head->next; - av_free(head->name); - av_free(head); - head = next; + return av_mallocz(sizeof(AVFilterInOut)); +} + +void avfilter_inout_free(AVFilterInOut **inout) +{ + while (*inout) { + AVFilterInOut *next = (*inout)->next; + av_freep(&(*inout)->name); + av_freep(inout); + *inout = next; } } @@ -203,7 +208,7 @@ static void insert_inout(AVFilterInOut **inouts, AVFilterInOut *element) static int link_filter_inouts(AVFilterContext *filt_ctx, AVFilterInOut **curr_inputs, - AVFilterInOut **open_inputs, AVClass *log_ctx) + AVFilterInOut **open_inputs, void *log_ctx) { int pad = filt_ctx->input_count, ret; @@ -251,7 +256,7 @@ static int link_filter_inouts(AVFilterContext *filt_ctx, } static int parse_inputs(const char **buf, AVFilterInOut **curr_inputs, - AVFilterInOut **open_outputs, AVClass *log_ctx) + AVFilterInOut **open_outputs, void *log_ctx) { int pad = 0; @@ -286,7 +291,7 @@ static int parse_inputs(const char **buf, AVFilterInOut **curr_inputs, static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs, AVFilterInOut **open_inputs, - AVFilterInOut **open_outputs, AVClass *log_ctx) + AVFilterInOut **open_outputs, void *log_ctx) { int ret, pad = 0; @@ -330,13 +335,15 @@ static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs, } int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, - AVFilterInOut *open_inputs, - AVFilterInOut *open_outputs, AVClass *log_ctx) + AVFilterInOut **open_inputs_ptr, AVFilterInOut **open_outputs_ptr, + void *log_ctx) { - int index = 0, ret; + int index = 0, ret = 0; char chr = 0; AVFilterInOut *curr_inputs = NULL; + AVFilterInOut *open_inputs = open_inputs_ptr ? *open_inputs_ptr : NULL; + AVFilterInOut *open_outputs = open_outputs_ptr ? *open_outputs_ptr : NULL; do { AVFilterContext *filter; @@ -344,24 +351,24 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, filters += strspn(filters, WHITESPACES); if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx)) < 0) - goto fail; + goto end; if ((ret = parse_filter(&filter, &filters, graph, index, log_ctx)) < 0) - goto fail; + goto end; if (filter->input_count == 1 && !curr_inputs && !index) { - /* First input can be omitted if it is "[in]" */ + /* First input pad, assume it is "[in]" if not specified */ const char *tmp = "[in]"; if ((ret = parse_inputs(&tmp, &curr_inputs, &open_outputs, log_ctx)) < 0) - goto fail; + goto end; } if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx)) < 0) - goto fail; + goto end; if ((ret = parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs, log_ctx)) < 0) - goto fail; + goto end; filters += strspn(filters, WHITESPACES); chr = *filters++; @@ -371,7 +378,7 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, "Invalid filterchain containing an unlabelled output pad: \"%s\"\n", filterchain); ret = AVERROR(EINVAL); - goto fail; + goto end; } index++; } while (chr == ',' || chr == ';'); @@ -381,25 +388,29 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, "Unable to parse graph description substring: \"%s\"\n", filters - 1); ret = AVERROR(EINVAL); - goto fail; + goto end; } - if (open_inputs && !strcmp(open_inputs->name, "out") && curr_inputs) { - /* Last output can be omitted if it is "[out]" */ + if (curr_inputs) { + /* Last output pad, assume it is "[out]" if not specified */ const char *tmp = "[out]"; if ((ret = parse_outputs(&tmp, &curr_inputs, &open_inputs, &open_outputs, log_ctx)) < 0) - goto fail; + goto end; } - return 0; - - fail: - for (; graph->filter_count > 0; graph->filter_count--) - avfilter_free(graph->filters[graph->filter_count - 1]); - av_freep(&graph->filters); - free_inout(open_inputs); - free_inout(open_outputs); - free_inout(curr_inputs); +end: + /* clear open_in/outputs only if not passed as parameters */ + if (open_inputs_ptr) *open_inputs_ptr = open_inputs; + else avfilter_inout_free(&open_inputs); + if (open_outputs_ptr) *open_outputs_ptr = open_outputs; + else avfilter_inout_free(&open_outputs); + avfilter_inout_free(&curr_inputs); + + if (ret < 0) { + for (; graph->filter_count > 0; graph->filter_count--) + avfilter_free(graph->filters[graph->filter_count - 1]); + av_freep(&graph->filters); + } return ret; } diff --git a/libavfilter/internal.h b/libavfilter/internal.h index 64b3f3b865..7537565768 100644 --- a/libavfilter/internal.h +++ b/libavfilter/internal.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -27,6 +27,12 @@ #include "avfilter.h" #include "avfiltergraph.h" +#define POOL_SIZE 32 +typedef struct AVFilterPool { + AVFilterBufferRef *pic[POOL_SIZE]; + int count; +} AVFilterPool; + /** * Check for the validity of graph. * @@ -52,4 +58,7 @@ int ff_avfilter_graph_config_formats(AVFilterGraph *graphctx, AVClass *log_ctx); /** default handler for freeing audio/video buffer when there are no references left */ void ff_avfilter_default_free_buffer(AVFilterBuffer *buf); +/** Tell is a format is contained in the provided list terminated by -1. */ +int ff_fmt_is_in(int fmt, const int *fmts); + #endif /* AVFILTER_INTERNAL_H */ diff --git a/libavfilter/libmpcodecs/cpudetect.h b/libavfilter/libmpcodecs/cpudetect.h new file mode 100644 index 0000000000..0f433e707c --- /dev/null +++ b/libavfilter/libmpcodecs/cpudetect.h @@ -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 */ diff --git a/libavfilter/libmpcodecs/help_mp.h b/libavfilter/libmpcodecs/help_mp.h new file mode 100644 index 0000000000..87b828d933 --- /dev/null +++ b/libavfilter/libmpcodecs/help_mp.h @@ -0,0 +1,2136 @@ +/* WARNING! This is a generated file, do NOT edit. + * See the help/ subdirectory for the editable files. */ + +#ifndef MPLAYER_HELP_MP_H +#define MPLAYER_HELP_MP_H + +// $Revision: 32397 $ +// MASTER FILE. Use this file as base for translations. +// Translated files should be sent to the mplayer-DOCS mailing list or +// to the help messages maintainer, see DOCS/tech/MAINTAINERS. +// The header of the translated file should contain credits and contact +// information. Before major releases we will notify all translators to update +// their files. Please do not simply translate and forget this, outdated +// translations quickly become worthless. To help us spot outdated files put a +// note like "sync'ed with help_mp-en.h XXX" in the header of the translation. +// Do NOT translate the above lines, just follow the instructions. + + +// ========================= MPlayer help =========================== + +static const char help_text[]= +"Usage: mplayer [options] [url|path/]filename\n" +"\n" +"Basic options: (complete list in the man page)\n" +" -vo <drv> select video output driver ('-vo help' for a list)\n" +" -ao <drv> select audio output driver ('-ao help' for a list)\n" +#ifdef CONFIG_VCD +" vcd://<trackno> play (S)VCD (Super Video CD) track (raw device, no mount)\n" +#endif +#ifdef CONFIG_DVDREAD +" dvd://<titleno> play DVD title from device instead of plain file\n" +#endif +" -alang/-slang select DVD audio/subtitle language (by 2-char country code)\n" +" -ss <position> seek to given (seconds or hh:mm:ss) position\n" +" -nosound do not play sound\n" +" -fs fullscreen playback (or -vm, -zoom, details in the man page)\n" +" -x <x> -y <y> set display resolution (for use with -vm or -zoom)\n" +" -sub <file> specify subtitle file to use (also see -subfps, -subdelay)\n" +" -playlist <file> specify playlist file\n" +" -vid x -aid y select video (x) and audio (y) stream to play\n" +" -fps x -srate y change video (x fps) and audio (y Hz) rate\n" +" -pp <quality> enable postprocessing filter (details in the man page)\n" +" -framedrop enable frame dropping (for slow machines)\n" +"\n" +"Basic keys: (complete list in the man page, also check input.conf)\n" +" <- or -> seek backward/forward 10 seconds\n" +" down or up seek backward/forward 1 minute\n" +" pgdown or pgup seek backward/forward 10 minutes\n" +" < or > step backward/forward in playlist\n" +" p or SPACE pause movie (press any key to continue)\n" +" q or ESC stop playing and quit program\n" +" + or - adjust audio delay by +/- 0.1 second\n" +" o cycle OSD mode: none / seekbar / seekbar + timer\n" +" * or / increase or decrease PCM volume\n" +" x or z adjust subtitle delay by +/- 0.1 second\n" +" r or t adjust subtitle position up/down, also see -vf expand\n" +"\n" +" * * * SEE THE MAN PAGE FOR DETAILS, FURTHER (ADVANCED) OPTIONS AND KEYS * * *\n" +"\n"; + +// ========================= MPlayer messages =========================== + +// mplayer.c +#define MSGTR_Exiting "\nExiting...\n" +#define MSGTR_ExitingHow "\nExiting... (%s)\n" +#define MSGTR_Exit_quit "Quit" +#define MSGTR_Exit_eof "End of file" +#define MSGTR_Exit_error "Fatal error" +#define MSGTR_IntBySignal "\nMPlayer interrupted by signal %d in module: %s\n" +#define MSGTR_NoHomeDir "Cannot find HOME directory.\n" +#define MSGTR_GetpathProblem "get_path(\"config\") problem\n" +#define MSGTR_CreatingCfgFile "Creating config file: %s\n" +#define MSGTR_BuiltinCodecsConf "Using built-in default codecs.conf.\n" +#define MSGTR_CantLoadFont "Cannot load bitmap font: %s\n" +#define MSGTR_CantLoadSub "Cannot load subtitles: %s\n" +#define MSGTR_DumpSelectedStreamMissing "dump: FATAL: Selected stream missing!\n" +#define MSGTR_CantOpenDumpfile "Cannot open dump file.\n" +#define MSGTR_CoreDumped "Core dumped ;)\n" +#define MSGTR_FPSnotspecified "FPS not specified in the header or invalid, use the -fps option.\n" +#define MSGTR_TryForceAudioFmtStr "Trying to force audio codec driver family %s...\n" +#define MSGTR_CantFindAudioCodec "Cannot find codec for audio format 0x%X.\n" +#define MSGTR_TryForceVideoFmtStr "Trying to force video codec driver family %s...\n" +#define MSGTR_CantFindVideoCodec "Cannot find codec matching selected -vo and video format 0x%X.\n" +#define MSGTR_CannotInitVO "FATAL: Cannot initialize video driver.\n" +#define MSGTR_CannotInitAO "Could not open/initialize audio device -> no sound.\n" +#define MSGTR_StartPlaying "Starting playback...\n" + +#define MSGTR_SystemTooSlow "\n\n"\ +" ************************************************\n"\ +" **** Your system is too SLOW to play this! ****\n"\ +" ************************************************\n\n"\ +"Possible reasons, problems, workarounds:\n"\ +"- Most common: broken/buggy _audio_ driver\n"\ +" - Try -ao sdl or use the OSS emulation of ALSA.\n"\ +" - Experiment with different values for -autosync, 30 is a good start.\n"\ +"- Slow video output\n"\ +" - Try a different -vo driver (-vo help for a list) or try -framedrop!\n"\ +"- Slow CPU\n"\ +" - Don't try to play a big DVD/DivX on a slow CPU! Try some of the lavdopts,\n"\ +" e.g. -vfm ffmpeg -lavdopts lowres=1:fast:skiploopfilter=all.\n"\ +"- Broken file\n"\ +" - Try various combinations of -nobps -ni -forceidx -mc 0.\n"\ +"- Slow media (NFS/SMB mounts, DVD, VCD etc)\n"\ +" - Try -cache 8192.\n"\ +"- Are you using -cache to play a non-interleaved AVI file?\n"\ +" - Try -nocache.\n"\ +"Read DOCS/HTML/en/video.html for tuning/speedup tips.\n"\ +"If none of this helps you, read DOCS/HTML/en/bugreports.html.\n\n" + +#define MSGTR_NoGui "MPlayer was compiled WITHOUT GUI support.\n" +#define MSGTR_GuiNeedsX "MPlayer GUI requires X11.\n" +#define MSGTR_Playing "\nPlaying %s.\n" +#define MSGTR_NoSound "Audio: no sound\n" +#define MSGTR_FPSforced "FPS forced to be %5.3f (ftime: %5.3f).\n" +#define MSGTR_CompiledWithRuntimeDetection "Compiled with runtime CPU detection.\n" +#define MSGTR_CompiledWithCPUExtensions "Compiled for x86 CPU with extensions:" +#define MSGTR_AvailableVideoOutputDrivers "Available video output drivers:\n" +#define MSGTR_AvailableAudioOutputDrivers "Available audio output drivers:\n" +#define MSGTR_AvailableAudioCodecs "Available audio codecs:\n" +#define MSGTR_AvailableVideoCodecs "Available video codecs:\n" +#define MSGTR_AvailableAudioFm "Available (compiled-in) audio codec families/drivers:\n" +#define MSGTR_AvailableVideoFm "Available (compiled-in) video codec families/drivers:\n" +#define MSGTR_AvailableFsType "Available fullscreen layer change modes:\n" +#define MSGTR_UsingRTCTiming "Using Linux hardware RTC timing (%ldHz).\n" +#define MSGTR_CannotReadVideoProperties "Video: Cannot read properties.\n" +#define MSGTR_NoStreamFound "No stream found.\n" +#define MSGTR_ErrorInitializingVODevice "Error opening/initializing the selected video_out (-vo) device.\n" +#define MSGTR_ForcedVideoCodec "Forced video codec: %s\n" +#define MSGTR_ForcedAudioCodec "Forced audio codec: %s\n" +#define MSGTR_Video_NoVideo "Video: no video\n" +#define MSGTR_NotInitializeVOPorVO "\nFATAL: Could not initialize video filters (-vf) or video output (-vo).\n" +#define MSGTR_Paused "\n ===== PAUSE =====\r" // no more than 23 characters (status line for audio files) +#define MSGTR_PlaylistLoadUnable "\nUnable to load playlist %s.\n" +#define MSGTR_Exit_SIGILL_RTCpuSel \ +"- MPlayer crashed by an 'Illegal Instruction'.\n"\ +" It may be a bug in our new runtime CPU-detection code...\n"\ +" Please read DOCS/HTML/en/bugreports.html.\n" +#define MSGTR_Exit_SIGILL \ +"- MPlayer crashed by an 'Illegal Instruction'.\n"\ +" It usually happens when you run it on a CPU different than the one it was\n"\ +" compiled/optimized for.\n"\ +" Verify this!\n" +#define MSGTR_Exit_SIGSEGV_SIGFPE \ +"- MPlayer crashed by bad usage of CPU/FPU/RAM.\n"\ +" Recompile MPlayer with --enable-debug and make a 'gdb' backtrace and\n"\ +" disassembly. Details in DOCS/HTML/en/bugreports_what.html#bugreports_crash.\n" +#define MSGTR_Exit_SIGCRASH \ +"- MPlayer crashed. This shouldn't happen.\n"\ +" It can be a bug in the MPlayer code _or_ in your drivers _or_ in your\n"\ +" gcc version. If you think it's MPlayer's fault, please read\n"\ +" DOCS/HTML/en/bugreports.html and follow the instructions there. We can't and\n"\ +" won't help unless you provide this information when reporting a possible bug.\n" +#define MSGTR_LoadingConfig "Loading config '%s'\n" +#define MSGTR_LoadingProtocolProfile "Loading protocol-related profile '%s'\n" +#define MSGTR_LoadingExtensionProfile "Loading extension-related profile '%s'\n" +#define MSGTR_AddedSubtitleFile "SUB: Added subtitle file (%d): %s\n" +#define MSGTR_RemovedSubtitleFile "SUB: Removed subtitle file (%d): %s\n" +#define MSGTR_ErrorOpeningOutputFile "Error opening file [%s] for writing!\n" +#define MSGTR_CommandLine "CommandLine:" +#define MSGTR_RTCDeviceNotOpenable "Failed to open %s: %s (it should be readable by the user.)\n" +#define MSGTR_LinuxRTCInitErrorIrqpSet "Linux RTC init error in ioctl (rtc_irqp_set %lu): %s\n" +#define MSGTR_IncreaseRTCMaxUserFreq "Try adding \"echo %lu > /proc/sys/dev/rtc/max-user-freq\" to your system startup scripts.\n" +#define MSGTR_LinuxRTCInitErrorPieOn "Linux RTC init error in ioctl (rtc_pie_on): %s\n" +#define MSGTR_UsingTimingType "Using %s timing.\n" +#define MSGTR_NoIdleAndGui "The -idle option cannot be used with GMPlayer.\n" +#define MSGTR_MenuInitialized "Menu initialized: %s\n" +#define MSGTR_MenuInitFailed "Menu init failed.\n" +#define MSGTR_Getch2InitializedTwice "WARNING: getch2_init called twice!\n" +#define MSGTR_DumpstreamFdUnavailable "Cannot dump this stream - no file descriptor available.\n" +#define MSGTR_CantOpenLibmenuFilterWithThisRootMenu "Can't open libmenu video filter with root menu %s.\n" +#define MSGTR_AudioFilterChainPreinitError "Error at audio filter chain pre-init!\n" +#define MSGTR_LinuxRTCReadError "Linux RTC read error: %s\n" +#define MSGTR_SoftsleepUnderflow "Warning! Softsleep underflow!\n" +#define MSGTR_DvdnavNullEvent "DVDNAV Event NULL?!\n" +#define MSGTR_DvdnavHighlightEventBroken "DVDNAV Event: Highlight event broken\n" +#define MSGTR_DvdnavEvent "DVDNAV Event: %s\n" +#define MSGTR_DvdnavHighlightHide "DVDNAV Event: Highlight Hide\n" +#define MSGTR_DvdnavStillFrame "######################################## DVDNAV Event: Still Frame: %d sec(s)\n" +#define MSGTR_DvdnavNavStop "DVDNAV Event: Nav Stop\n" +#define MSGTR_DvdnavNavNOP "DVDNAV Event: Nav NOP\n" +#define MSGTR_DvdnavNavSpuStreamChangeVerbose "DVDNAV Event: Nav SPU Stream Change: phys: %d/%d/%d logical: %d\n" +#define MSGTR_DvdnavNavSpuStreamChange "DVDNAV Event: Nav SPU Stream Change: phys: %d logical: %d\n" +#define MSGTR_DvdnavNavAudioStreamChange "DVDNAV Event: Nav Audio Stream Change: phys: %d logical: %d\n" +#define MSGTR_DvdnavNavVTSChange "DVDNAV Event: Nav VTS Change\n" +#define MSGTR_DvdnavNavCellChange "DVDNAV Event: Nav Cell Change\n" +#define MSGTR_DvdnavNavSpuClutChange "DVDNAV Event: Nav SPU CLUT Change\n" +#define MSGTR_DvdnavNavSeekDone "DVDNAV Event: Nav Seek Done\n" +#define MSGTR_MenuCall "Menu call\n" +#define MSGTR_MasterQuit "Option -udp-slave: exiting because master exited\n" +#define MSGTR_InvalidIP "Option -udp-ip: invalid IP address\n" + +// --- edit decision lists +#define MSGTR_EdlOutOfMem "Can't allocate enough memory to hold EDL data.\n" +#define MSGTR_EdlOutOfMemFile "Can't allocate enough memory to hold EDL file name [%s].\n" +#define MSGTR_EdlRecordsNo "Read %d EDL actions.\n" +#define MSGTR_EdlQueueEmpty "There are no EDL actions to take care of.\n" +#define MSGTR_EdlCantOpenForWrite "Can't open EDL file [%s] for writing.\n" +#define MSGTR_EdlCantOpenForRead "Can't open EDL file [%s] for reading.\n" +#define MSGTR_EdlNOsh_video "Cannot use EDL without video, disabling.\n" +#define MSGTR_EdlNOValidLine "Invalid EDL line: %s\n" +#define MSGTR_EdlBadlyFormattedLine "Badly formatted EDL line [%d], discarding.\n" +#define MSGTR_EdlBadLineOverlap "Last stop position was [%f]; next start is [%f].\n"\ +"Entries must be in chronological order, cannot overlap. Discarding.\n" +#define MSGTR_EdlBadLineBadStop "Stop time has to be after start time.\n" +#define MSGTR_EdloutBadStop "EDL skip canceled, last start > stop\n" +#define MSGTR_EdloutStartSkip "EDL skip start, press 'i' again to end block.\n" +#define MSGTR_EdloutEndSkip "EDL skip end, line written.\n" +#define MSGTR_MPEndposNoSizeBased "Option -endpos in MPlayer does not yet support size units.\n" + +// mplayer.c OSD +#define MSGTR_OSDenabled "enabled" +#define MSGTR_OSDdisabled "disabled" +#define MSGTR_OSDAudio "Audio: %s" +#define MSGTR_OSDVideo "Video: %s" +#define MSGTR_OSDChannel "Channel: %s" +#define MSGTR_OSDSubDelay "Sub delay: %d ms" +#define MSGTR_OSDSpeed "Speed: x %6.2f" +#define MSGTR_OSDosd "OSD: %s" +#define MSGTR_OSDChapter "Chapter: (%d) %s" +#define MSGTR_OSDAngle "Angle: %d/%d" +#define MSGTR_OSDDeinterlace "Deinterlace: %s" + +// property values +#define MSGTR_Enabled "enabled" +#define MSGTR_EnabledEdl "enabled (EDL)" +#define MSGTR_Disabled "disabled" +#define MSGTR_HardFrameDrop "hard" +#define MSGTR_Unknown "unknown" +#define MSGTR_Bottom "bottom" +#define MSGTR_Center "center" +#define MSGTR_Top "top" +#define MSGTR_SubSourceFile "file" +#define MSGTR_SubSourceVobsub "vobsub" +#define MSGTR_SubSourceDemux "embedded" + +// OSD bar names +#define MSGTR_Volume "Volume" +#define MSGTR_Panscan "Panscan" +#define MSGTR_Gamma "Gamma" +#define MSGTR_Brightness "Brightness" +#define MSGTR_Contrast "Contrast" +#define MSGTR_Saturation "Saturation" +#define MSGTR_Hue "Hue" +#define MSGTR_Balance "Balance" + +// property state +#define MSGTR_LoopStatus "Loop: %s" +#define MSGTR_MuteStatus "Mute: %s" +#define MSGTR_AVDelayStatus "A-V delay: %s" +#define MSGTR_OnTopStatus "Stay on top: %s" +#define MSGTR_RootwinStatus "Rootwin: %s" +#define MSGTR_BorderStatus "Border: %s" +#define MSGTR_FramedroppingStatus "Framedropping: %s" +#define MSGTR_VSyncStatus "VSync: %s" +#define MSGTR_SubSelectStatus "Subtitles: %s" +#define MSGTR_SubSourceStatus "Sub source: %s" +#define MSGTR_SubPosStatus "Sub position: %s/100" +#define MSGTR_SubAlignStatus "Sub alignment: %s" +#define MSGTR_SubDelayStatus "Sub delay: %s" +#define MSGTR_SubScale "Sub Scale: %s" +#define MSGTR_SubVisibleStatus "Subtitles: %s" +#define MSGTR_SubForcedOnlyStatus "Forced sub only: %s" + +// mencoder.c +#define MSGTR_UsingPass3ControlFile "Using pass3 control file: %s\n" +#define MSGTR_MissingFilename "\nFilename missing.\n\n" +#define MSGTR_CannotOpenFile_Device "Cannot open file/device.\n" +#define MSGTR_CannotOpenDemuxer "Cannot open demuxer.\n" +#define MSGTR_NoAudioEncoderSelected "\nNo audio encoder (-oac) selected. Select one (see -oac help) or use -nosound.\n" +#define MSGTR_NoVideoEncoderSelected "\nNo video encoder (-ovc) selected. Select one (see -ovc help).\n" +#define MSGTR_CannotOpenOutputFile "Cannot open output file '%s'.\n" +#define MSGTR_EncoderOpenFailed "Failed to open the encoder.\n" +#define MSGTR_MencoderWrongFormatAVI "\nWARNING: OUTPUT FILE FORMAT IS _AVI_. See -of help.\n" +#define MSGTR_MencoderWrongFormatMPG "\nWARNING: OUTPUT FILE FORMAT IS _MPEG_. See -of help.\n" +#define MSGTR_MissingOutputFilename "No output file specified, please see the -o option." +#define MSGTR_ForcingOutputFourcc "Forcing output FourCC to %x [%.4s].\n" +#define MSGTR_ForcingOutputAudiofmtTag "Forcing output audio format tag to 0x%x.\n" +#define MSGTR_DuplicateFrames "\n%d duplicate frame(s)!\n" +#define MSGTR_SkipFrame "\nSkipping frame!\n" +#define MSGTR_ResolutionDoesntMatch "\nNew video file has different resolution or colorspace than the previous one.\n" +#define MSGTR_FrameCopyFileMismatch "\nAll video files must have identical fps, resolution, and codec for -ovc copy.\n" +#define MSGTR_AudioCopyFileMismatch "\nAll files must have identical audio codec and format for -oac copy.\n" +#define MSGTR_NoAudioFileMismatch "\nCannot mix video-only files with audio and video files. Try -nosound.\n" +#define MSGTR_NoSpeedWithFrameCopy "WARNING: -speed is not guaranteed to work correctly with -oac copy!\n"\ +"Your encode might be broken!\n" +#define MSGTR_ErrorWritingFile "%s: Error writing file.\n" +#define MSGTR_FlushingVideoFrames "\nFlushing video frames.\n" +#define MSGTR_FiltersHaveNotBeenConfiguredEmptyFile "Filters have not been configured! Empty file?\n" +#define MSGTR_RecommendedVideoBitrate "Recommended video bitrate for %s CD: %d\n" +#define MSGTR_VideoStreamResult "\nVideo stream: %8.3f kbit/s (%d B/s) size: %"PRIu64" bytes %5.3f secs %d frames\n" +#define MSGTR_AudioStreamResult "\nAudio stream: %8.3f kbit/s (%d B/s) size: %"PRIu64" bytes %5.3f secs\n" +#define MSGTR_EdlSkipStartEndCurrent "EDL SKIP: Start: %.2f End: %.2f Current: V: %.2f A: %.2f \r" +#define MSGTR_OpenedStream "success: format: %d data: 0x%X - 0x%x\n" +#define MSGTR_VCodecFramecopy "videocodec: framecopy (%dx%d %dbpp fourcc=%x)\n" +#define MSGTR_ACodecFramecopy "audiocodec: framecopy (format=%x chans=%d rate=%d bits=%d B/s=%d sample-%d)\n" +#define MSGTR_CBRPCMAudioSelected "CBR PCM audio selected.\n" +#define MSGTR_MP3AudioSelected "MP3 audio selected.\n" +#define MSGTR_CannotAllocateBytes "Couldn't allocate %d bytes.\n" +#define MSGTR_SettingAudioDelay "Setting audio delay to %5.3fs.\n" +#define MSGTR_SettingVideoDelay "Setting video delay to %5.3fs.\n" +#define MSGTR_SettingAudioInputGain "Setting audio input gain to %f.\n" +#define MSGTR_LamePresetEquals "\npreset=%s\n\n" +#define MSGTR_LimitingAudioPreload "Limiting audio preload to 0.4s.\n" +#define MSGTR_IncreasingAudioDensity "Increasing audio density to 4.\n" +#define MSGTR_ZeroingAudioPreloadAndMaxPtsCorrection "Forcing audio preload to 0, max pts correction to 0.\n" +#define MSGTR_CBRAudioByterate "\n\nCBR audio: %d bytes/sec, %d bytes/block\n" +#define MSGTR_LameVersion "LAME version %s (%s)\n\n" +#define MSGTR_InvalidBitrateForLamePreset "Error: The bitrate specified is out of the valid range for this preset.\n"\ +"\n"\ +"When using this mode you must enter a value between \"8\" and \"320\".\n"\ +"\n"\ +"For further information try: \"-lameopts preset=help\"\n" +#define MSGTR_InvalidLamePresetOptions "Error: You did not enter a valid profile and/or options with preset.\n"\ +"\n"\ +"Available profiles are:\n"\ +"\n"\ +" <fast> standard\n"\ +" <fast> extreme\n"\ +" insane\n"\ +" <cbr> (ABR Mode) - The ABR Mode is implied. To use it,\n"\ +" simply specify a bitrate. For example:\n"\ +" \"preset=185\" activates this\n"\ +" preset and uses 185 as an average kbps.\n"\ +"\n"\ +" Some examples:\n"\ +"\n"\ +" \"-lameopts fast:preset=standard \"\n"\ +" or \"-lameopts cbr:preset=192 \"\n"\ +" or \"-lameopts preset=172 \"\n"\ +" or \"-lameopts preset=extreme \"\n"\ +"\n"\ +"For further information try: \"-lameopts preset=help\"\n" +#define MSGTR_LamePresetsLongInfo "\n"\ +"The preset switches are designed to provide the highest possible quality.\n"\ +"\n"\ +"They have for the most part been subjected to and tuned via rigorous double\n"\ +"blind listening tests to verify and achieve this objective.\n"\ +"\n"\ +"These are continually updated to coincide with the latest developments that\n"\ +"occur and as a result should provide you with nearly the best quality\n"\ +"currently possible from LAME.\n"\ +"\n"\ +"To activate these presets:\n"\ +"\n"\ +" For VBR modes (generally highest quality):\n"\ +"\n"\ +" \"preset=standard\" This preset should generally be transparent\n"\ +" to most people on most music and is already\n"\ +" quite high in quality.\n"\ +"\n"\ +" \"preset=extreme\" If you have extremely good hearing and similar\n"\ +" equipment, this preset will generally provide\n"\ +" slightly higher quality than the \"standard\"\n"\ +" mode.\n"\ +"\n"\ +" For CBR 320kbps (highest quality possible from the preset switches):\n"\ +"\n"\ +" \"preset=insane\" This preset will usually be overkill for most\n"\ +" people and most situations, but if you must\n"\ +" have the absolute highest quality with no\n"\ +" regard to filesize, this is the way to go.\n"\ +"\n"\ +" For ABR modes (high quality per given bitrate but not as high as VBR):\n"\ +"\n"\ +" \"preset=<kbps>\" Using this preset will usually give you good\n"\ +" quality at a specified bitrate. Depending on the\n"\ +" bitrate entered, this preset will determine the\n"\ +" optimal settings for that particular situation.\n"\ +" While this approach works, it is not nearly as\n"\ +" flexible as VBR, and usually will not attain the\n"\ +" same level of quality as VBR at higher bitrates.\n"\ +"\n"\ +"The following options are also available for the corresponding profiles:\n"\ +"\n"\ +" <fast> standard\n"\ +" <fast> extreme\n"\ +" insane\n"\ +" <cbr> (ABR Mode) - The ABR Mode is implied. To use it,\n"\ +" simply specify a bitrate. For example:\n"\ +" \"preset=185\" activates this\n"\ +" preset and uses 185 as an average kbps.\n"\ +"\n"\ +" \"fast\" - Enables the new fast VBR for a particular profile. The\n"\ +" disadvantage to the speed switch is that often times the\n"\ +" bitrate will be slightly higher than with the normal mode\n"\ +" and quality may be slightly lower also.\n"\ +" Warning: with the current version fast presets might result in too\n"\ +" high bitrate compared to regular presets.\n"\ +"\n"\ +" \"cbr\" - If you use the ABR mode (read above) with a significant\n"\ +" bitrate such as 80, 96, 112, 128, 160, 192, 224, 256, 320,\n"\ +" you can use the \"cbr\" option to force CBR mode encoding\n"\ +" instead of the standard abr mode. ABR does provide higher\n"\ +" quality but CBR may be useful in situations such as when\n"\ +" streaming an MP3 over the internet may be important.\n"\ +"\n"\ +" For example:\n"\ +"\n"\ +" \"-lameopts fast:preset=standard \"\n"\ +" or \"-lameopts cbr:preset=192 \"\n"\ +" or \"-lameopts preset=172 \"\n"\ +" or \"-lameopts preset=extreme \"\n"\ +"\n"\ +"\n"\ +"A few aliases are available for ABR mode:\n"\ +"phone => 16kbps/mono phon+/lw/mw-eu/sw => 24kbps/mono\n"\ +"mw-us => 40kbps/mono voice => 56kbps/mono\n"\ +"fm/radio/tape => 112kbps hifi => 160kbps\n"\ +"cd => 192kbps studio => 256kbps" +#define MSGTR_LameCantInit \ +"Cannot set LAME options, check bitrate/samplerate, some very low bitrates\n"\ +"(<32) need lower samplerates (i.e. -srate 8000).\n"\ +"If everything else fails, try a preset." +#define MSGTR_ConfigFileError "config file error" +#define MSGTR_ErrorParsingCommandLine "error parsing command line" +#define MSGTR_VideoStreamRequired "Video stream is mandatory!\n" +#define MSGTR_ForcingInputFPS "Input fps will be interpreted as %5.3f instead.\n" +#define MSGTR_RawvideoDoesNotSupportAudio "Output file format RAWVIDEO does not support audio - disabling audio.\n" +#define MSGTR_DemuxerDoesntSupportNosound "This demuxer doesn't support -nosound yet.\n" +#define MSGTR_MemAllocFailed "Memory allocation failed.\n" +#define MSGTR_NoMatchingFilter "Couldn't find matching filter/ao format!\n" +#define MSGTR_MP3WaveFormatSizeNot30 "sizeof(MPEGLAYER3WAVEFORMAT)==%d!=30, maybe broken C compiler?\n" +#define MSGTR_NoLavcAudioCodecName "Audio LAVC, Missing codec name!\n" +#define MSGTR_LavcAudioCodecNotFound "Audio LAVC, couldn't find encoder for codec %s.\n" +#define MSGTR_CouldntAllocateLavcContext "Audio LAVC, couldn't allocate context!\n" +#define MSGTR_CouldntOpenCodec "Couldn't open codec %s, br=%d.\n" +#define MSGTR_CantCopyAudioFormat "Audio format 0x%x is incompatible with '-oac copy', please try '-oac pcm' instead or use '-fafmttag' to override it.\n" + +// cfg-mencoder.h +#define MSGTR_MEncoderMP3LameHelp "\n\n"\ +" vbr=<0-4> variable bitrate method\n"\ +" 0: cbr (constant bitrate)\n"\ +" 1: mt (Mark Taylor VBR algorithm)\n"\ +" 2: rh (Robert Hegemann VBR algorithm - default)\n"\ +" 3: abr (average bitrate)\n"\ +" 4: mtrh (Mark Taylor Robert Hegemann VBR algorithm)\n"\ +"\n"\ +" abr average bitrate\n"\ +"\n"\ +" cbr constant bitrate\n"\ +" Also forces CBR mode encoding on subsequent ABR presets modes.\n"\ +"\n"\ +" br=<0-1024> specify bitrate in kBit (CBR and ABR only)\n"\ +"\n"\ +" q=<0-9> quality (0-highest, 9-lowest) (only for VBR)\n"\ +"\n"\ +" aq=<0-9> algorithmic quality (0-best/slowest, 9-worst/fastest)\n"\ +"\n"\ +" ratio=<1-100> compression ratio\n"\ +"\n"\ +" vol=<0-10> set audio input gain\n"\ +"\n"\ +" mode=<0-3> (default: auto)\n"\ +" 0: stereo\n"\ +" 1: joint-stereo\n"\ +" 2: dualchannel\n"\ +" 3: mono\n"\ +"\n"\ +" padding=<0-2>\n"\ +" 0: no\n"\ +" 1: all\n"\ +" 2: adjust\n"\ +"\n"\ +" fast Switch on faster encoding on subsequent VBR presets modes,\n"\ +" slightly lower quality and higher bitrates.\n"\ +"\n"\ +" preset=<value> Provide the highest possible quality settings.\n"\ +" medium: VBR encoding, good quality\n"\ +" (150-180 kbps bitrate range)\n"\ +" standard: VBR encoding, high quality\n"\ +" (170-210 kbps bitrate range)\n"\ +" extreme: VBR encoding, very high quality\n"\ +" (200-240 kbps bitrate range)\n"\ +" insane: CBR encoding, highest preset quality\n"\ +" (320 kbps bitrate)\n"\ +" <8-320>: ABR encoding at average given kbps bitrate.\n\n" + +// codec-cfg.c +#define MSGTR_DuplicateFourcc "duplicated FourCC" +#define MSGTR_TooManyFourccs "too many FourCCs/formats..." +#define MSGTR_ParseError "parse error" +#define MSGTR_ParseErrorFIDNotNumber "parse error (format ID not a number?)" +#define MSGTR_ParseErrorFIDAliasNotNumber "parse error (format ID alias not a number?)" +#define MSGTR_DuplicateFID "duplicated format ID" +#define MSGTR_TooManyOut "too many out..." +#define MSGTR_InvalidCodecName "\ncodec(%s) name is not valid!\n" +#define MSGTR_CodecLacksFourcc "\ncodec(%s) does not have FourCC/format!\n" +#define MSGTR_CodecLacksDriver "\ncodec(%s) does not have a driver!\n" +#define MSGTR_CodecNeedsDLL "\ncodec(%s) needs a 'dll'!\n" +#define MSGTR_CodecNeedsOutfmt "\ncodec(%s) needs an 'outfmt'!\n" +#define MSGTR_CantAllocateComment "Can't allocate memory for comment. " +#define MSGTR_GetTokenMaxNotLessThanMAX_NR_TOKEN "get_token(): max >= MAX_MR_TOKEN!" +#define MSGTR_ReadingFile "Reading %s: " +#define MSGTR_CantOpenFileError "Can't open '%s': %s\n" +#define MSGTR_CantGetMemoryForLine "Can't get memory for 'line': %s\n" +#define MSGTR_CantReallocCodecsp "Can't realloc '*codecsp': %s\n" +#define MSGTR_CodecNameNotUnique "Codec name '%s' isn't unique." +#define MSGTR_CantStrdupName "Can't strdup -> 'name': %s\n" +#define MSGTR_CantStrdupInfo "Can't strdup -> 'info': %s\n" +#define MSGTR_CantStrdupDriver "Can't strdup -> 'driver': %s\n" +#define MSGTR_CantStrdupDLL "Can't strdup -> 'dll': %s" +#define MSGTR_AudioVideoCodecTotals "%d audio & %d video codecs\n" +#define MSGTR_CodecDefinitionIncorrect "Codec is not defined correctly." +#define MSGTR_OutdatedCodecsConf "This codecs.conf is too old and incompatible with this MPlayer release!" + +// fifo.c +#define MSGTR_CannotMakePipe "Cannot make PIPE!\n" + +// parser-mecmd.c, parser-mpcmd.c +#define MSGTR_NoFileGivenOnCommandLine "'--' indicates no more options, but no filename was given on the command line.\n" +#define MSGTR_TheLoopOptionMustBeAnInteger "The loop option must be an integer: %s\n" +#define MSGTR_UnknownOptionOnCommandLine "Unknown option on the command line: -%s\n" +#define MSGTR_ErrorParsingOptionOnCommandLine "Error parsing option on the command line: -%s\n" +#define MSGTR_InvalidPlayEntry "Invalid play entry %s\n" +#define MSGTR_NotAnMEncoderOption "-%s is not an MEncoder option\n" +#define MSGTR_NoFileGiven "No file given\n" + +// m_config.c +#define MSGTR_SaveSlotTooOld "Save slot found from lvl %d is too old: %d !!!\n" +#define MSGTR_InvalidCfgfileOption "The %s option can't be used in a config file.\n" +#define MSGTR_InvalidCmdlineOption "The %s option can't be used on the command line.\n" +#define MSGTR_InvalidSuboption "Error: option '%s' has no suboption '%s'.\n" +#define MSGTR_MissingSuboptionParameter "Error: suboption '%s' of '%s' must have a parameter!\n" +#define MSGTR_MissingOptionParameter "Error: option '%s' must have a parameter!\n" +#define MSGTR_OptionListHeader "\n Name Type Min Max Global CL Cfg\n\n" +#define MSGTR_TotalOptions "\nTotal: %d options\n" +#define MSGTR_ProfileInclusionTooDeep "WARNING: Profile inclusion too deep.\n" +#define MSGTR_NoProfileDefined "No profiles have been defined.\n" +#define MSGTR_AvailableProfiles "Available profiles:\n" +#define MSGTR_UnknownProfile "Unknown profile '%s'.\n" +#define MSGTR_Profile "Profile %s: %s\n" + +// m_property.c +#define MSGTR_PropertyListHeader "\n Name Type Min Max\n\n" +#define MSGTR_TotalProperties "\nTotal: %d properties\n" + +// loader/ldt_keeper.c +#define MSGTR_LOADER_DYLD_Warning "WARNING: Attempting to use DLL codecs but environment variable\n DYLD_BIND_AT_LAUNCH not set. This will likely crash.\n" + + +// ====================== GUI messages/buttons ======================== + +// --- labels --- +#define MSGTR_About "About" +#define MSGTR_FileSelect "Select file..." +#define MSGTR_SubtitleSelect "Select subtitle..." +#define MSGTR_OtherSelect "Select..." +#define MSGTR_AudioFileSelect "Select external audio channel..." +#define MSGTR_FontSelect "Select font..." +// Note: If you change MSGTR_PlayList please see if it still fits MSGTR_MENU_PlayList +#define MSGTR_PlayList "Playlist" +#define MSGTR_Equalizer "Equalizer" +#define MSGTR_ConfigureEqualizer "Configure Equalizer" +#define MSGTR_SkinBrowser "Skin Browser" +#define MSGTR_Network "Network streaming..." +// Note: If you change MSGTR_Preferences please see if it still fits MSGTR_MENU_Preferences +#define MSGTR_Preferences "Preferences" +#define MSGTR_AudioPreferences "Audio driver configuration" +#define MSGTR_NoMediaOpened "No media opened." +#define MSGTR_VCDTrack "VCD track %d" +#define MSGTR_NoChapter "No chapter" +#define MSGTR_Chapter "Chapter %d" +#define MSGTR_NoFileLoaded "No file loaded." + +// --- buttons --- +#define MSGTR_Ok "OK" +#define MSGTR_Cancel "Cancel" +#define MSGTR_Add "Add" +#define MSGTR_Remove "Remove" +#define MSGTR_Clear "Clear" +#define MSGTR_Config "Config" +#define MSGTR_ConfigDriver "Configure driver" +#define MSGTR_Browse "Browse" + +// --- error messages --- +#define MSGTR_NEMDB "Sorry, not enough memory to draw buffer." +#define MSGTR_NEMFMR "Sorry, not enough memory for menu rendering." +#define MSGTR_IDFGCVD "Sorry, I did not find a GUI-compatible video output driver." +#define MSGTR_NEEDLAVC "Sorry, you cannot play non-MPEG files with your DXR3/H+ device without reencoding.\nPlease enable lavc in the DXR3/H+ configuration box." +#define MSGTR_UNKNOWNWINDOWTYPE "Unknown window type found ..." + +// --- skin loader error messages +#define MSGTR_SKIN_ERRORMESSAGE "[skin] error in skin config file on line %d: %s" +#define MSGTR_SKIN_WARNING1 "[skin] warning: in config file line %d:\nwidget (%s) found but no \"section\" found before" +#define MSGTR_SKIN_WARNING2 "[skin] warning: in config file line %d:\nwidget (%s) found but no \"subsection\" found before" +#define MSGTR_SKIN_WARNING3 "[skin] warning: in config file line %d:\nthis subsection is not supported by widget (%s)" +#define MSGTR_SKIN_SkinFileNotFound "[skin] file ( %s ) not found.\n" +#define MSGTR_SKIN_SkinFileNotReadable "[skin] file ( %s ) not readable.\n" +#define MSGTR_SKIN_BITMAP_16bit "Bitmaps of 16 bits or less depth not supported (%s).\n" +#define MSGTR_SKIN_BITMAP_FileNotFound "File not found (%s)\n" +#define MSGTR_SKIN_BITMAP_BMPReadError "BMP read error (%s)\n" +#define MSGTR_SKIN_BITMAP_TGAReadError "TGA read error (%s)\n" +#define MSGTR_SKIN_BITMAP_PNGReadError "PNG read error (%s)\n" +#define MSGTR_SKIN_BITMAP_RLENotSupported "RLE packed TGA not supported (%s)\n" +#define MSGTR_SKIN_BITMAP_UnknownFileType "unknown file type (%s)\n" +#define MSGTR_SKIN_BITMAP_ConversionError "24 bit to 32 bit conversion error (%s)\n" +#define MSGTR_SKIN_BITMAP_UnknownMessage "unknown message: %s\n" +#define MSGTR_SKIN_FONT_NotEnoughtMemory "not enough memory\n" +#define MSGTR_SKIN_FONT_TooManyFontsDeclared "Too many fonts declared.\n" +#define MSGTR_SKIN_FONT_FontFileNotFound "Font file not found.\n" +#define MSGTR_SKIN_FONT_FontImageNotFound "Font image file not found.\n" +#define MSGTR_SKIN_FONT_NonExistentFontID "non-existent font identifier (%s)\n" +#define MSGTR_SKIN_UnknownParameter "unknown parameter (%s)\n" +#define MSGTR_SKIN_SKINCFG_SkinNotFound "Skin not found (%s).\n" +#define MSGTR_SKIN_SKINCFG_SelectedSkinNotFound "Selected skin ( %s ) not found, trying 'default'...\n" +#define MSGTR_SKIN_SKINCFG_SkinCfgReadError "skin config file read error (%s)\n" +#define MSGTR_SKIN_LABEL "Skins:" + +// --- GTK menus +#define MSGTR_MENU_AboutMPlayer "About MPlayer" +#define MSGTR_MENU_Open "Open..." +#define MSGTR_MENU_PlayFile "Play file..." +#define MSGTR_MENU_PlayVCD "Play VCD..." +#define MSGTR_MENU_PlayDVD "Play DVD..." +#define MSGTR_MENU_PlayURL "Play URL..." +#define MSGTR_MENU_LoadSubtitle "Load subtitle..." +#define MSGTR_MENU_DropSubtitle "Drop subtitle..." +#define MSGTR_MENU_LoadExternAudioFile "Load external audio file..." +#define MSGTR_MENU_Playing "Playing" +#define MSGTR_MENU_Play "Play" +#define MSGTR_MENU_Pause "Pause" +#define MSGTR_MENU_Stop "Stop" +#define MSGTR_MENU_NextStream "Next stream" +#define MSGTR_MENU_PrevStream "Prev stream" +#define MSGTR_MENU_Size "Size" +#define MSGTR_MENU_HalfSize "Half size" +#define MSGTR_MENU_NormalSize "Normal size" +#define MSGTR_MENU_DoubleSize "Double size" +#define MSGTR_MENU_FullScreen "Fullscreen" +#define MSGTR_MENU_DVD "DVD" +#define MSGTR_MENU_VCD "VCD" +#define MSGTR_MENU_PlayDisc "Open disc..." +#define MSGTR_MENU_ShowDVDMenu "Show DVD menu" +#define MSGTR_MENU_Titles "Titles" +#define MSGTR_MENU_Title "Title %2d" +#define MSGTR_MENU_None "(none)" +#define MSGTR_MENU_Chapters "Chapters" +#define MSGTR_MENU_Chapter "Chapter %2d" +#define MSGTR_MENU_AudioLanguages "Audio languages" +#define MSGTR_MENU_SubtitleLanguages "Subtitle languages" +#define MSGTR_MENU_PlayList MSGTR_PlayList +#define MSGTR_MENU_SkinBrowser "Skin browser" +#define MSGTR_MENU_Preferences MSGTR_Preferences +#define MSGTR_MENU_Exit "Exit..." +#define MSGTR_MENU_Mute "Mute" +#define MSGTR_MENU_Original "Original" +#define MSGTR_MENU_AspectRatio "Aspect ratio" +#define MSGTR_MENU_AudioTrack "Audio track" +#define MSGTR_MENU_Track "Track %d" +#define MSGTR_MENU_VideoTrack "Video track" +#define MSGTR_MENU_Subtitles "Subtitles" + +// --- equalizer +// Note: If you change MSGTR_EQU_Audio please see if it still fits MSGTR_PREFERENCES_Audio +#define MSGTR_EQU_Audio "Audio" +// Note: If you change MSGTR_EQU_Video please see if it still fits MSGTR_PREFERENCES_Video +#define MSGTR_EQU_Video "Video" +#define MSGTR_EQU_Contrast "Contrast: " +#define MSGTR_EQU_Brightness "Brightness: " +#define MSGTR_EQU_Hue "Hue: " +#define MSGTR_EQU_Saturation "Saturation: " +#define MSGTR_EQU_Front_Left "Front Left" +#define MSGTR_EQU_Front_Right "Front Right" +#define MSGTR_EQU_Back_Left "Rear Left" +#define MSGTR_EQU_Back_Right "Rear Right" +#define MSGTR_EQU_Center "Center" +#define MSGTR_EQU_Bass "Bass" +#define MSGTR_EQU_All "All" +#define MSGTR_EQU_Channel1 "Channel 1:" +#define MSGTR_EQU_Channel2 "Channel 2:" +#define MSGTR_EQU_Channel3 "Channel 3:" +#define MSGTR_EQU_Channel4 "Channel 4:" +#define MSGTR_EQU_Channel5 "Channel 5:" +#define MSGTR_EQU_Channel6 "Channel 6:" + +// --- playlist +#define MSGTR_PLAYLIST_Path "Path" +#define MSGTR_PLAYLIST_Selected "Selected files" +#define MSGTR_PLAYLIST_Files "Files" +#define MSGTR_PLAYLIST_DirectoryTree "Directory tree" + +// --- preferences +#define MSGTR_PREFERENCES_Audio MSGTR_EQU_Audio +#define MSGTR_PREFERENCES_Video MSGTR_EQU_Video +#define MSGTR_PREFERENCES_SubtitleOSD "Subtitles & OSD" +#define MSGTR_PREFERENCES_Codecs "Codecs & demuxer" +// Note: If you change MSGTR_PREFERENCES_Misc see if it still fits MSGTR_PREFERENCES_FRAME_Misc +#define MSGTR_PREFERENCES_Misc "Misc" +#define MSGTR_PREFERENCES_None "None" +#define MSGTR_PREFERENCES_DriverDefault "driver default" +#define MSGTR_PREFERENCES_AvailableDrivers "Available drivers:" +#define MSGTR_PREFERENCES_DoNotPlaySound "Do not play sound" +#define MSGTR_PREFERENCES_NormalizeSound "Normalize sound" +#define MSGTR_PREFERENCES_EnableEqualizer "Enable equalizer" +#define MSGTR_PREFERENCES_SoftwareMixer "Enable Software Mixer" +#define MSGTR_PREFERENCES_ExtraStereo "Enable extra stereo" +#define MSGTR_PREFERENCES_Coefficient "Coefficient:" +#define MSGTR_PREFERENCES_AudioDelay "Audio delay" +#define MSGTR_PREFERENCES_DoubleBuffer "Enable double buffering" +#define MSGTR_PREFERENCES_DirectRender "Enable direct rendering" +#define MSGTR_PREFERENCES_FrameDrop "Enable frame dropping" +#define MSGTR_PREFERENCES_HFrameDrop "Enable HARD frame dropping (dangerous)" +#define MSGTR_PREFERENCES_Flip "Flip image upside down" +#define MSGTR_PREFERENCES_Panscan "Panscan: " +#define MSGTR_PREFERENCES_OSDTimer "Timer and indicators" +#define MSGTR_PREFERENCES_OSDProgress "Progressbars only" +#define MSGTR_PREFERENCES_OSDTimerPercentageTotalTime "Timer, percentage and total time" +#define MSGTR_PREFERENCES_Subtitle "Subtitle:" +#define MSGTR_PREFERENCES_SUB_Delay "Delay: " +#define MSGTR_PREFERENCES_SUB_FPS "FPS:" +#define MSGTR_PREFERENCES_SUB_POS "Position: " +#define MSGTR_PREFERENCES_SUB_AutoLoad "Disable subtitle autoloading" +#define MSGTR_PREFERENCES_SUB_Unicode "Unicode subtitle" +#define MSGTR_PREFERENCES_SUB_MPSUB "Convert the given subtitle to MPlayer's subtitle format" +#define MSGTR_PREFERENCES_SUB_SRT "Convert the given subtitle to the time based SubViewer (SRT) format" +#define MSGTR_PREFERENCES_SUB_Overlap "Toggle subtitle overlapping" +#define MSGTR_PREFERENCES_SUB_USE_ASS "SSA/ASS subtitle rendering" +#define MSGTR_PREFERENCES_SUB_ASS_USE_MARGINS "Use margins" +#define MSGTR_PREFERENCES_SUB_ASS_TOP_MARGIN "Top: " +#define MSGTR_PREFERENCES_SUB_ASS_BOTTOM_MARGIN "Bottom: " +#define MSGTR_PREFERENCES_Font "Font:" +#define MSGTR_PREFERENCES_FontFactor "Font factor:" +#define MSGTR_PREFERENCES_PostProcess "Enable postprocessing" +#define MSGTR_PREFERENCES_AutoQuality "Auto quality: " +#define MSGTR_PREFERENCES_NI "Use non-interleaved AVI parser" +#define MSGTR_PREFERENCES_IDX "Rebuild index table, if needed" +#define MSGTR_PREFERENCES_VideoCodecFamily "Video codec family:" +#define MSGTR_PREFERENCES_AudioCodecFamily "Audio codec family:" +#define MSGTR_PREFERENCES_FRAME_OSD_Level "OSD level" +#define MSGTR_PREFERENCES_FRAME_Subtitle "Subtitle" +#define MSGTR_PREFERENCES_FRAME_Font "Font" +#define MSGTR_PREFERENCES_FRAME_PostProcess "Postprocessing" +#define MSGTR_PREFERENCES_FRAME_CodecDemuxer "Codec & demuxer" +#define MSGTR_PREFERENCES_FRAME_Cache "Cache" +#define MSGTR_PREFERENCES_FRAME_Misc MSGTR_PREFERENCES_Misc +#define MSGTR_PREFERENCES_Audio_Device "Device:" +#define MSGTR_PREFERENCES_Audio_Mixer "Mixer:" +#define MSGTR_PREFERENCES_Audio_MixerChannel "Mixer channel:" +#define MSGTR_PREFERENCES_Message "Please remember that you need to restart playback for some options to take effect!" +#define MSGTR_PREFERENCES_DXR3_VENC "Video encoder:" +#define MSGTR_PREFERENCES_DXR3_LAVC "Use LAVC (FFmpeg)" +#define MSGTR_PREFERENCES_FontEncoding1 "Unicode" +#define MSGTR_PREFERENCES_FontEncoding2 "Western European Languages (ISO-8859-1)" +#define MSGTR_PREFERENCES_FontEncoding3 "Western European Languages with Euro (ISO-8859-15)" +#define MSGTR_PREFERENCES_FontEncoding4 "Slavic/Central European Languages (ISO-8859-2)" +#define MSGTR_PREFERENCES_FontEncoding5 "Esperanto, Galician, Maltese, Turkish (ISO-8859-3)" +#define MSGTR_PREFERENCES_FontEncoding6 "Old Baltic charset (ISO-8859-4)" +#define MSGTR_PREFERENCES_FontEncoding7 "Cyrillic (ISO-8859-5)" +#define MSGTR_PREFERENCES_FontEncoding8 "Arabic (ISO-8859-6)" +#define MSGTR_PREFERENCES_FontEncoding9 "Modern Greek (ISO-8859-7)" +#define MSGTR_PREFERENCES_FontEncoding10 "Turkish (ISO-8859-9)" +#define MSGTR_PREFERENCES_FontEncoding11 "Baltic (ISO-8859-13)" +#define MSGTR_PREFERENCES_FontEncoding12 "Celtic (ISO-8859-14)" +#define MSGTR_PREFERENCES_FontEncoding13 "Hebrew charsets (ISO-8859-8)" +#define MSGTR_PREFERENCES_FontEncoding14 "Russian (KOI8-R)" +#define MSGTR_PREFERENCES_FontEncoding15 "Ukrainian, Belarusian (KOI8-U/RU)" +#define MSGTR_PREFERENCES_FontEncoding16 "Simplified Chinese charset (CP936)" +#define MSGTR_PREFERENCES_FontEncoding17 "Traditional Chinese charset (BIG5)" +#define MSGTR_PREFERENCES_FontEncoding18 "Japanese charsets (SHIFT-JIS)" +#define MSGTR_PREFERENCES_FontEncoding19 "Korean charset (CP949)" +#define MSGTR_PREFERENCES_FontEncoding20 "Thai charset (CP874)" +#define MSGTR_PREFERENCES_FontEncoding21 "Cyrillic Windows (CP1251)" +#define MSGTR_PREFERENCES_FontEncoding22 "Slavic/Central European Windows (CP1250)" +#define MSGTR_PREFERENCES_FontEncoding23 "Arabic Windows (CP1256)" +#define MSGTR_PREFERENCES_FontNoAutoScale "No autoscale" +#define MSGTR_PREFERENCES_FontPropWidth "Proportional to movie width" +#define MSGTR_PREFERENCES_FontPropHeight "Proportional to movie height" +#define MSGTR_PREFERENCES_FontPropDiagonal "Proportional to movie diagonal" +#define MSGTR_PREFERENCES_FontEncoding "Encoding:" +#define MSGTR_PREFERENCES_FontBlur "Blur:" +#define MSGTR_PREFERENCES_FontOutLine "Outline:" +#define MSGTR_PREFERENCES_FontTextScale "Text scale:" +#define MSGTR_PREFERENCES_FontOSDScale "OSD scale:" +#define MSGTR_PREFERENCES_Cache "Cache on/off" +#define MSGTR_PREFERENCES_CacheSize "Cache size: " +#define MSGTR_PREFERENCES_LoadFullscreen "Start in fullscreen" +#define MSGTR_PREFERENCES_SaveWinPos "Save window position" +#define MSGTR_PREFERENCES_XSCREENSAVER "Stop XScreenSaver" +#define MSGTR_PREFERENCES_PlayBar "Enable playbar" +#define MSGTR_PREFERENCES_AutoSync "AutoSync on/off" +#define MSGTR_PREFERENCES_AutoSyncValue "Autosync: " +#define MSGTR_PREFERENCES_CDROMDevice "CD-ROM device:" +#define MSGTR_PREFERENCES_DVDDevice "DVD device:" +#define MSGTR_PREFERENCES_FPS "Movie FPS:" +#define MSGTR_PREFERENCES_ShowVideoWindow "Show video window when inactive" +#define MSGTR_PREFERENCES_ArtsBroken "Newer aRts versions are incompatible "\ + "with GTK 1.x and will crash GMPlayer!" + +// -- aboutbox +#define MSGTR_ABOUT_UHU "GUI development sponsored by UHU Linux\n" +#define MSGTR_ABOUT_Contributors "Code and documentation contributors\n" +#define MSGTR_ABOUT_Codecs_libs_contributions "Codecs and third party libraries\n" +#define MSGTR_ABOUT_Translations "Translations\n" +#define MSGTR_ABOUT_Skins "Skins\n" + +// --- messagebox +#define MSGTR_MSGBOX_LABEL_FatalError "Fatal error!" +#define MSGTR_MSGBOX_LABEL_Error "Error!" +#define MSGTR_MSGBOX_LABEL_Warning "Warning!" + +// bitmap.c +#define MSGTR_NotEnoughMemoryC32To1 "[c32to1] not enough memory for image\n" +#define MSGTR_NotEnoughMemoryC1To32 "[c1to32] not enough memory for image\n" + +// cfg.c +#define MSGTR_ConfigFileReadError "[cfg] config file read error ...\n" +#define MSGTR_UnableToSaveOption "[cfg] Unable to save the '%s' option.\n" + +// interface.c +#define MSGTR_DeletingSubtitles "[GUI] Deleting subtitles.\n" +#define MSGTR_LoadingSubtitles "[GUI] Loading subtitles: %s\n" +#define MSGTR_AddingVideoFilter "[GUI] Adding video filter: %s\n" +#define MSGTR_RemovingVideoFilter "[GUI] Removing video filter: %s\n" + +// mw.c +#define MSGTR_NotAFile "This does not seem to be a file: %s !\n" + +// ws.c +#define MSGTR_WS_CouldNotOpenDisplay "[ws] Could not open the display.\n" +#define MSGTR_WS_RemoteDisplay "[ws] Remote display, disabling XMITSHM.\n" +#define MSGTR_WS_NoXshm "[ws] Sorry, your system does not support the X shared memory extension.\n" +#define MSGTR_WS_NoXshape "[ws] Sorry, your system does not support the XShape extension.\n" +#define MSGTR_WS_ColorDepthTooLow "[ws] Sorry, the color depth is too low.\n" +#define MSGTR_WS_TooManyOpenWindows "[ws] There are too many open windows.\n" +#define MSGTR_WS_ShmError "[ws] shared memory extension error\n" +#define MSGTR_WS_NotEnoughMemoryDrawBuffer "[ws] Sorry, not enough memory to draw buffer.\n" +#define MSGTR_WS_DpmsUnavailable "DPMS not available?\n" +#define MSGTR_WS_DpmsNotEnabled "Could not enable DPMS.\n" + +// wsxdnd.c +#define MSGTR_WS_NotAFile "This does not seem to be a file...\n" +#define MSGTR_WS_DDNothing "D&D: Nothing returned!\n" + +// ======================= video output drivers ======================== + +#define MSGTR_VOincompCodec "The selected video_out device is incompatible with this codec.\n"\ + "Try appending the scale filter to your filter list,\n"\ + "e.g. -vf spp,scale instead of -vf spp.\n" +#define MSGTR_VO_GenericError "This error has occurred" +#define MSGTR_VO_UnableToAccess "Unable to access" +#define MSGTR_VO_ExistsButNoDirectory "already exists, but is not a directory." +#define MSGTR_VO_DirExistsButNotWritable "Output directory already exists, but is not writable." +#define MSGTR_VO_DirExistsAndIsWritable "Output directory already exists and is writable." +#define MSGTR_VO_CantCreateDirectory "Unable to create output directory." +#define MSGTR_VO_CantCreateFile "Unable to create output file." +#define MSGTR_VO_DirectoryCreateSuccess "Output directory successfully created." +#define MSGTR_VO_ValueOutOfRange "value out of range" +#define MSGTR_VO_NoValueSpecified "No value specified." +#define MSGTR_VO_UnknownSuboptions "unknown suboption(s)" + +// aspect.c +#define MSGTR_LIBVO_ASPECT_NoSuitableNewResFound "[ASPECT] Warning: No suitable new res found!\n" +#define MSGTR_LIBVO_ASPECT_NoNewSizeFoundThatFitsIntoRes "[ASPECT] Error: No new size found that fits into res!\n" + +// font_load_ft.c +#define MSGTR_LIBVO_FONT_LOAD_FT_NewFaceFailed "New_Face failed. Maybe the font path is wrong.\nPlease supply the text font file (~/.mplayer/subfont.ttf).\n" +#define MSGTR_LIBVO_FONT_LOAD_FT_NewMemoryFaceFailed "New_Memory_Face failed..\n" +#define MSGTR_LIBVO_FONT_LOAD_FT_SubFaceFailed "subtitle font: load_sub_face failed.\n" +#define MSGTR_LIBVO_FONT_LOAD_FT_SubFontCharsetFailed "subtitle font: prepare_charset failed.\n" +#define MSGTR_LIBVO_FONT_LOAD_FT_CannotPrepareSubtitleFont "Cannot prepare subtitle font.\n" +#define MSGTR_LIBVO_FONT_LOAD_FT_CannotPrepareOSDFont "Cannot prepare OSD font.\n" +#define MSGTR_LIBVO_FONT_LOAD_FT_CannotGenerateTables "Cannot generate tables.\n" +#define MSGTR_LIBVO_FONT_LOAD_FT_DoneFreeTypeFailed "FT_Done_FreeType failed.\n" +#define MSGTR_LIBVO_FONT_LOAD_FT_FontconfigNoMatch "Fontconfig failed to select a font. Trying without fontconfig...\n" + +// sub.c +#define MSGTR_VO_SUB_Seekbar "Seekbar" +#define MSGTR_VO_SUB_Play "Play" +#define MSGTR_VO_SUB_Pause "Pause" +#define MSGTR_VO_SUB_Stop "Stop" +#define MSGTR_VO_SUB_Rewind "Rewind" +#define MSGTR_VO_SUB_Forward "Forward" +#define MSGTR_VO_SUB_Clock "Clock" +#define MSGTR_VO_SUB_Contrast "Contrast" +#define MSGTR_VO_SUB_Saturation "Saturation" +#define MSGTR_VO_SUB_Volume "Volume" +#define MSGTR_VO_SUB_Brightness "Brightness" +#define MSGTR_VO_SUB_Hue "Hue" +#define MSGTR_VO_SUB_Balance "Balance" + +// vo_3dfx.c +#define MSGTR_LIBVO_3DFX_Only16BppSupported "[VO_3DFX] Only 16bpp supported!" +#define MSGTR_LIBVO_3DFX_VisualIdIs "[VO_3DFX] Visual ID is %lx.\n" +#define MSGTR_LIBVO_3DFX_UnableToOpenDevice "[VO_3DFX] Unable to open /dev/3dfx.\n" +#define MSGTR_LIBVO_3DFX_Error "[VO_3DFX] Error: %d.\n" +#define MSGTR_LIBVO_3DFX_CouldntMapMemoryArea "[VO_3DFX] Couldn't map 3dfx memory areas: %p,%p,%d.\n" +#define MSGTR_LIBVO_3DFX_DisplayInitialized "[VO_3DFX] Initialized: %p.\n" +#define MSGTR_LIBVO_3DFX_UnknownSubdevice "[VO_3DFX] Unknown subdevice: %s.\n" + +// vo_aa.c +#define MSGTR_VO_AA_HelpHeader "\n\nHere are the aalib vo_aa suboptions:\n" +#define MSGTR_VO_AA_AdditionalOptions "Additional options vo_aa provides:\n" \ +" help print this help message\n" \ +" osdcolor set OSD color\n subcolor set subtitle color\n" \ +" the color parameters are:\n 0 : normal\n" \ +" 1 : dim\n 2 : bold\n 3 : boldfont\n" \ +" 4 : reverse\n 5 : special\n\n\n" + +// vo_dxr3.c +#define MSGTR_LIBVO_DXR3_UnableToLoadNewSPUPalette "[VO_DXR3] Unable to load new SPU palette!\n" +#define MSGTR_LIBVO_DXR3_UnableToSetPlaymode "[VO_DXR3] Unable to set playmode!\n" +#define MSGTR_LIBVO_DXR3_UnableToSetSubpictureMode "[VO_DXR3] Unable to set subpicture mode!\n" +#define MSGTR_LIBVO_DXR3_UnableToGetTVNorm "[VO_DXR3] Unable to get TV norm!\n" +#define MSGTR_LIBVO_DXR3_AutoSelectedTVNormByFrameRate "[VO_DXR3] Auto-selected TV norm by framerate: " +#define MSGTR_LIBVO_DXR3_UnableToSetTVNorm "[VO_DXR3] Unable to set TV norm!\n" +#define MSGTR_LIBVO_DXR3_SettingUpForNTSC "[VO_DXR3] Setting up for NTSC.\n" +#define MSGTR_LIBVO_DXR3_SettingUpForPALSECAM "[VO_DXR3] Setting up for PAL/SECAM.\n" +#define MSGTR_LIBVO_DXR3_SettingAspectRatioTo43 "[VO_DXR3] Setting aspect ratio to 4:3.\n" +#define MSGTR_LIBVO_DXR3_SettingAspectRatioTo169 "[VO_DXR3] Setting aspect ratio to 16:9.\n" +#define MSGTR_LIBVO_DXR3_OutOfMemory "[VO_DXR3] out of memory\n" +#define MSGTR_LIBVO_DXR3_UnableToAllocateKeycolor "[VO_DXR3] Unable to allocate keycolor!\n" +#define MSGTR_LIBVO_DXR3_UnableToAllocateExactKeycolor "[VO_DXR3] Unable to allocate exact keycolor, using closest match (0x%lx).\n" +#define MSGTR_LIBVO_DXR3_Uninitializing "[VO_DXR3] Uninitializing.\n" +#define MSGTR_LIBVO_DXR3_FailedRestoringTVNorm "[VO_DXR3] Failed restoring TV norm!\n" +#define MSGTR_LIBVO_DXR3_EnablingPrebuffering "[VO_DXR3] Enabling prebuffering.\n" +#define MSGTR_LIBVO_DXR3_UsingNewSyncEngine "[VO_DXR3] Using new sync engine.\n" +#define MSGTR_LIBVO_DXR3_UsingOverlay "[VO_DXR3] Using overlay.\n" +#define MSGTR_LIBVO_DXR3_ErrorYouNeedToCompileMplayerWithX11 "[VO_DXR3] Error: Overlay requires compiling with X11 libs/headers installed.\n" +#define MSGTR_LIBVO_DXR3_WillSetTVNormTo "[VO_DXR3] Will set TV norm to: " +#define MSGTR_LIBVO_DXR3_AutoAdjustToMovieFrameRatePALPAL60 "auto-adjust to movie framerate (PAL/PAL-60)" +#define MSGTR_LIBVO_DXR3_AutoAdjustToMovieFrameRatePALNTSC "auto-adjust to movie framerate (PAL/NTSC)" +#define MSGTR_LIBVO_DXR3_UseCurrentNorm "Use current norm." +#define MSGTR_LIBVO_DXR3_UseUnknownNormSuppliedCurrentNorm "Unknown norm supplied. Use current norm." +#define MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTrying "[VO_DXR3] Error opening %s for writing, trying /dev/em8300 instead.\n" +#define MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTryingMV "[VO_DXR3] Error opening %s for writing, trying /dev/em8300_mv instead.\n" +#define MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWell "[VO_DXR3] Error opening /dev/em8300 for writing as well!\nBailing out.\n" +#define MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWellMV "[VO_DXR3] Error opening /dev/em8300_mv for writing as well!\nBailing out.\n" +#define MSGTR_LIBVO_DXR3_Opened "[VO_DXR3] Opened: %s.\n" +#define MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTryingSP "[VO_DXR3] Error opening %s for writing, trying /dev/em8300_sp instead.\n" +#define MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWellSP "[VO_DXR3] Error opening /dev/em8300_sp for writing as well!\nBailing out.\n" +#define MSGTR_LIBVO_DXR3_UnableToOpenDisplayDuringHackSetup "[VO_DXR3] Unable to open display during overlay hack setup!\n" +#define MSGTR_LIBVO_DXR3_UnableToInitX11 "[VO_DXR3] Unable to init X11!\n" +#define MSGTR_LIBVO_DXR3_FailedSettingOverlayAttribute "[VO_DXR3] Failed setting overlay attribute.\n" +#define MSGTR_LIBVO_DXR3_FailedSettingOverlayScreen "[VO_DXR3] Failed setting overlay screen!\nExiting.\n" +#define MSGTR_LIBVO_DXR3_FailedEnablingOverlay "[VO_DXR3] Failed enabling overlay!\nExiting.\n" +#define MSGTR_LIBVO_DXR3_FailedResizingOverlayWindow "[VO_DXR3] Failed resizing overlay window!\n" +#define MSGTR_LIBVO_DXR3_FailedSettingOverlayBcs "[VO_DXR3] Failed setting overlay bcs!\n" +#define MSGTR_LIBVO_DXR3_FailedGettingOverlayYOffsetValues "[VO_DXR3] Failed getting overlay Y-offset values!\nExiting.\n" +#define MSGTR_LIBVO_DXR3_FailedGettingOverlayXOffsetValues "[VO_DXR3] Failed getting overlay X-offset values!\nExiting.\n" +#define MSGTR_LIBVO_DXR3_FailedGettingOverlayXScaleCorrection "[VO_DXR3] Failed getting overlay X scale correction!\nExiting.\n" +#define MSGTR_LIBVO_DXR3_YOffset "[VO_DXR3] Yoffset: %d.\n" +#define MSGTR_LIBVO_DXR3_XOffset "[VO_DXR3] Xoffset: %d.\n" +#define MSGTR_LIBVO_DXR3_XCorrection "[VO_DXR3] Xcorrection: %d.\n" +#define MSGTR_LIBVO_DXR3_FailedSetSignalMix "[VO_DXR3] Failed to set signal mix!\n" + +// vo_jpeg.c +#define MSGTR_VO_JPEG_ProgressiveJPEG "Progressive JPEG enabled." +#define MSGTR_VO_JPEG_NoProgressiveJPEG "Progressive JPEG disabled." +#define MSGTR_VO_JPEG_BaselineJPEG "Baseline JPEG enabled." +#define MSGTR_VO_JPEG_NoBaselineJPEG "Baseline JPEG disabled." + +// vo_mga.c +#define MSGTR_LIBVO_MGA_AspectResized "[VO_MGA] aspect(): resized to %dx%d.\n" +#define MSGTR_LIBVO_MGA_Uninit "[VO] uninit!\n" + +// mga_template.c +#define MSGTR_LIBVO_MGA_ErrorInConfigIoctl "[MGA] error in mga_vid_config ioctl (wrong mga_vid.o version?)" +#define MSGTR_LIBVO_MGA_CouldNotGetLumaValuesFromTheKernelModule "[MGA] Could not get luma values from the kernel module!\n" +#define MSGTR_LIBVO_MGA_CouldNotSetLumaValuesFromTheKernelModule "[MGA] Could not set luma values from the kernel module!\n" +#define MSGTR_LIBVO_MGA_ScreenWidthHeightUnknown "[MGA] Screen width/height unknown!\n" +#define MSGTR_LIBVO_MGA_InvalidOutputFormat "[MGA] invalid output format %0X\n" +#define MSGTR_LIBVO_MGA_IncompatibleDriverVersion "[MGA] Your mga_vid driver version is incompatible with this MPlayer version!\n" +#define MSGTR_LIBVO_MGA_CouldntOpen "[MGA] Couldn't open: %s\n" +#define MSGTR_LIBVO_MGA_ResolutionTooHigh "[MGA] Source resolution exceeds 1023x1023 in at least one dimension.\n[MGA] Rescale in software or use -lavdopts lowres=1.\n" +#define MSGTR_LIBVO_MGA_mgavidVersionMismatch "[MGA] mismatch between kernel (%u) and MPlayer (%u) mga_vid driver versions\n" + +// vo_null.c +#define MSGTR_LIBVO_NULL_UnknownSubdevice "[VO_NULL] Unknown subdevice: %s.\n" + +// vo_png.c +#define MSGTR_LIBVO_PNG_Warning1 "[VO_PNG] Warning: compression level set to 0, compression disabled!\n" +#define MSGTR_LIBVO_PNG_Warning2 "[VO_PNG] Info: Use -vo png:z=<n> to set compression level from 0 to 9.\n" +#define MSGTR_LIBVO_PNG_Warning3 "[VO_PNG] Info: (0 = no compression, 1 = fastest, lowest - 9 best, slowest compression)\n" +#define MSGTR_LIBVO_PNG_ErrorOpeningForWriting "\n[VO_PNG] Error opening '%s' for writing!\n" +#define MSGTR_LIBVO_PNG_ErrorInCreatePng "[VO_PNG] Error in create_png.\n" + +// vo_pnm.c +#define MSGTR_VO_PNM_ASCIIMode "ASCII mode enabled." +#define MSGTR_VO_PNM_RawMode "Raw mode enabled." +#define MSGTR_VO_PNM_PPMType "Will write PPM files." +#define MSGTR_VO_PNM_PGMType "Will write PGM files." +#define MSGTR_VO_PNM_PGMYUVType "Will write PGMYUV files." + +// vo_sdl.c +#define MSGTR_LIBVO_SDL_CouldntGetAnyAcceptableSDLModeForOutput "[VO_SDL] Couldn't get any acceptable SDL Mode for output.\n" +#define MSGTR_LIBVO_SDL_SetVideoModeFailed "[VO_SDL] set_video_mode: SDL_SetVideoMode failed: %s.\n" +#define MSGTR_LIBVO_SDL_SetVideoModeFailedFull "[VO_SDL] Set_fullmode: SDL_SetVideoMode failed: %s.\n" +#define MSGTR_LIBVO_SDL_MappingI420ToIYUV "[VO_SDL] Mapping I420 to IYUV.\n" +#define MSGTR_LIBVO_SDL_UnsupportedImageFormat "[VO_SDL] Unsupported image format (0x%X).\n" +#define MSGTR_LIBVO_SDL_InfoPleaseUseVmOrZoom "[VO_SDL] Info - please use -vm or -zoom to switch to the best resolution.\n" +#define MSGTR_LIBVO_SDL_FailedToSetVideoMode "[VO_SDL] Failed to set video mode: %s.\n" +#define MSGTR_LIBVO_SDL_CouldntCreateAYUVOverlay "[VO_SDL] Couldn't create a YUV overlay: %s.\n" +#define MSGTR_LIBVO_SDL_CouldntCreateARGBSurface "[VO_SDL] Couldn't create an RGB surface: %s.\n" +#define MSGTR_LIBVO_SDL_UsingDepthColorspaceConversion "[VO_SDL] Using depth/colorspace conversion, this will slow things down (%ibpp -> %ibpp).\n" +#define MSGTR_LIBVO_SDL_UnsupportedImageFormatInDrawslice "[VO_SDL] Unsupported image format in draw_slice, contact MPlayer developers!\n" +#define MSGTR_LIBVO_SDL_BlitFailed "[VO_SDL] Blit failed: %s.\n" +#define MSGTR_LIBVO_SDL_InitializationFailed "[VO_SDL] SDL initialization failed: %s.\n" +#define MSGTR_LIBVO_SDL_UsingDriver "[VO_SDL] Using driver: %s.\n" + +// vo_svga.c +#define MSGTR_LIBVO_SVGA_ForcedVidmodeNotAvailable "[VO_SVGA] Forced vid_mode %d (%s) not available.\n" +#define MSGTR_LIBVO_SVGA_ForcedVidmodeTooSmall "[VO_SVGA] Forced vid_mode %d (%s) too small.\n" +#define MSGTR_LIBVO_SVGA_Vidmode "[VO_SVGA] Vid_mode: %d, %dx%d %dbpp.\n" +#define MSGTR_LIBVO_SVGA_VgasetmodeFailed "[VO_SVGA] Vga_setmode(%d) failed.\n" +#define MSGTR_LIBVO_SVGA_VideoModeIsLinearAndMemcpyCouldBeUsed "[VO_SVGA] Video mode is linear and memcpy could be used for image transfer.\n" +#define MSGTR_LIBVO_SVGA_VideoModeHasHardwareAcceleration "[VO_SVGA] Video mode has hardware acceleration and put_image could be used.\n" +#define MSGTR_LIBVO_SVGA_IfItWorksForYouIWouldLikeToKnow "[VO_SVGA] If it works for you I would like to know.\n[VO_SVGA] (send log with `mplayer test.avi -v -v -v -v &> svga.log`). Thx!\n" +#define MSGTR_LIBVO_SVGA_VideoModeHas "[VO_SVGA] Video mode has %d page(s).\n" +#define MSGTR_LIBVO_SVGA_CenteringImageStartAt "[VO_SVGA] Centering image. Starting at (%d,%d)\n" +#define MSGTR_LIBVO_SVGA_UsingVidix "[VO_SVGA] Using VIDIX. w=%i h=%i mw=%i mh=%i\n" + +// vo_tdfx_vid.c +#define MSGTR_LIBVO_TDFXVID_Move "[VO_TDXVID] Move %d(%d) x %d => %d.\n" +#define MSGTR_LIBVO_TDFXVID_AGPMoveFailedToClearTheScreen "[VO_TDFXVID] AGP move failed to clear the screen.\n" +#define MSGTR_LIBVO_TDFXVID_BlitFailed "[VO_TDFXVID] Blit failed.\n" +#define MSGTR_LIBVO_TDFXVID_NonNativeOverlayFormatNeedConversion "[VO_TDFXVID] Non-native overlay format needs conversion.\n" +#define MSGTR_LIBVO_TDFXVID_UnsupportedInputFormat "[VO_TDFXVID] Unsupported input format 0x%x.\n" +#define MSGTR_LIBVO_TDFXVID_OverlaySetupFailed "[VO_TDFXVID] Overlay setup failed.\n" +#define MSGTR_LIBVO_TDFXVID_OverlayOnFailed "[VO_TDFXVID] Overlay on failed.\n" +#define MSGTR_LIBVO_TDFXVID_OverlayReady "[VO_TDFXVID] Overlay ready: %d(%d) x %d @ %d => %d(%d) x %d @ %d.\n" +#define MSGTR_LIBVO_TDFXVID_TextureBlitReady "[VO_TDFXVID] Texture blit ready: %d(%d) x %d @ %d => %d(%d) x %d @ %d.\n" +#define MSGTR_LIBVO_TDFXVID_OverlayOffFailed "[VO_TDFXVID] Overlay off failed\n" +#define MSGTR_LIBVO_TDFXVID_CantOpen "[VO_TDFXVID] Can't open %s: %s.\n" +#define MSGTR_LIBVO_TDFXVID_CantGetCurrentCfg "[VO_TDFXVID] Can't get current configuration: %s.\n" +#define MSGTR_LIBVO_TDFXVID_MemmapFailed "[VO_TDFXVID] Memmap failed !!!!!\n" +#define MSGTR_LIBVO_TDFXVID_GetImageTodo "Get image todo.\n" +#define MSGTR_LIBVO_TDFXVID_AgpMoveFailed "[VO_TDFXVID] AGP move failed.\n" +#define MSGTR_LIBVO_TDFXVID_SetYuvFailed "[VO_TDFXVID] Set YUV failed.\n" +#define MSGTR_LIBVO_TDFXVID_AgpMoveFailedOnYPlane "[VO_TDFXVID] AGP move failed on Y plane.\n" +#define MSGTR_LIBVO_TDFXVID_AgpMoveFailedOnUPlane "[VO_TDFXVID] AGP move failed on U plane.\n" +#define MSGTR_LIBVO_TDFXVID_AgpMoveFailedOnVPlane "[VO_TDFXVID] AGP move failed on V plane.\n" +#define MSGTR_LIBVO_TDFXVID_UnknownFormat "[VO_TDFXVID] unknown format: 0x%x.\n" + +// vo_tdfxfb.c +#define MSGTR_LIBVO_TDFXFB_CantOpen "[VO_TDFXFB] Can't open %s: %s.\n" +#define MSGTR_LIBVO_TDFXFB_ProblemWithFbitgetFscreenInfo "[VO_TDFXFB] Problem with FBITGET_FSCREENINFO ioctl: %s.\n" +#define MSGTR_LIBVO_TDFXFB_ProblemWithFbitgetVscreenInfo "[VO_TDFXFB] Problem with FBITGET_VSCREENINFO ioctl: %s.\n" +#define MSGTR_LIBVO_TDFXFB_ThisDriverOnlySupports "[VO_TDFXFB] This driver only supports the 3Dfx Banshee, Voodoo3 and Voodoo 5.\n" +#define MSGTR_LIBVO_TDFXFB_OutputIsNotSupported "[VO_TDFXFB] %d bpp output is not supported.\n" +#define MSGTR_LIBVO_TDFXFB_CouldntMapMemoryAreas "[VO_TDFXFB] Couldn't map memory areas: %s.\n" +#define MSGTR_LIBVO_TDFXFB_BppOutputIsNotSupported "[VO_TDFXFB] %d bpp output is not supported (This should never have happened).\n" +#define MSGTR_LIBVO_TDFXFB_SomethingIsWrongWithControl "[VO_TDFXFB] Eik! Something's wrong with control().\n" +#define MSGTR_LIBVO_TDFXFB_NotEnoughVideoMemoryToPlay "[VO_TDFXFB] Not enough video memory to play this movie. Try at a lower resolution.\n" +#define MSGTR_LIBVO_TDFXFB_ScreenIs "[VO_TDFXFB] Screen is %dx%d at %d bpp, in is %dx%d at %d bpp, norm is %dx%d.\n" + +// vo_tga.c +#define MSGTR_LIBVO_TGA_UnknownSubdevice "[VO_TGA] Unknown subdevice: %s.\n" + +// vo_vesa.c +#define MSGTR_LIBVO_VESA_FatalErrorOccurred "[VO_VESA] Fatal error occurred! Can't continue.\n" +#define MSGTR_LIBVO_VESA_UnknownSubdevice "[VO_VESA] unknown subdevice: '%s'.\n" +#define MSGTR_LIBVO_VESA_YouHaveTooLittleVideoMemory "[VO_VESA] You have too little video memory for this mode:\n[VO_VESA] Required: %08lX present: %08lX.\n" +#define MSGTR_LIBVO_VESA_YouHaveToSpecifyTheCapabilitiesOfTheMonitor "[VO_VESA] You have to specify the capabilities of the monitor. Not changing refresh rate.\n" +#define MSGTR_LIBVO_VESA_UnableToFitTheMode "[VO_VESA] The mode does not fit the monitor limits. Not changing refresh rate.\n" +#define MSGTR_LIBVO_VESA_DetectedInternalFatalError "[VO_VESA] Detected internal fatal error: init is called before preinit.\n" +#define MSGTR_LIBVO_VESA_SwitchFlipIsNotSupported "[VO_VESA] The -flip option is not supported.\n" +#define MSGTR_LIBVO_VESA_PossibleReasonNoVbe2BiosFound "[VO_VESA] Possible reason: No VBE2 BIOS found.\n" +#define MSGTR_LIBVO_VESA_FoundVesaVbeBiosVersion "[VO_VESA] Found VESA VBE BIOS Version %x.%x Revision: %x.\n" +#define MSGTR_LIBVO_VESA_VideoMemory "[VO_VESA] Video memory: %u Kb.\n" +#define MSGTR_LIBVO_VESA_Capabilites "[VO_VESA] VESA Capabilities: %s %s %s %s %s.\n" +#define MSGTR_LIBVO_VESA_BelowWillBePrintedOemInfo "[VO_VESA] !!! OEM info will be printed below !!!\n" +#define MSGTR_LIBVO_VESA_YouShouldSee5OemRelatedLines "[VO_VESA] You should see 5 OEM related lines below; If not, you've broken vm86.\n" +#define MSGTR_LIBVO_VESA_OemInfo "[VO_VESA] OEM info: %s.\n" +#define MSGTR_LIBVO_VESA_OemRevision "[VO_VESA] OEM Revision: %x.\n" +#define MSGTR_LIBVO_VESA_OemVendor "[VO_VESA] OEM vendor: %s.\n" +#define MSGTR_LIBVO_VESA_OemProductName "[VO_VESA] OEM Product Name: %s.\n" +#define MSGTR_LIBVO_VESA_OemProductRev "[VO_VESA] OEM Product Rev: %s.\n" +#define MSGTR_LIBVO_VESA_Hint "[VO_VESA] Hint: For working TV-Out you should have plugged in the TV connector\n"\ +"[VO_VESA] before booting since VESA BIOS initializes itself only during POST.\n" +#define MSGTR_LIBVO_VESA_UsingVesaMode "[VO_VESA] Using VESA mode (%u) = %x [%ux%u@%u]\n" +#define MSGTR_LIBVO_VESA_CantInitializeSwscaler "[VO_VESA] Can't initialize software scaler.\n" +#define MSGTR_LIBVO_VESA_CantUseDga "[VO_VESA] Can't use DGA. Force bank switching mode. :(\n" +#define MSGTR_LIBVO_VESA_UsingDga "[VO_VESA] Using DGA (physical resources: %08lXh, %08lXh)" +#define MSGTR_LIBVO_VESA_CantUseDoubleBuffering "[VO_VESA] Can't use double buffering: not enough video memory.\n" +#define MSGTR_LIBVO_VESA_CantFindNeitherDga "[VO_VESA] Can find neither DGA nor relocatable window frame.\n" +#define MSGTR_LIBVO_VESA_YouveForcedDga "[VO_VESA] You've forced DGA. Exiting\n" +#define MSGTR_LIBVO_VESA_CantFindValidWindowAddress "[VO_VESA] Can't find valid window address.\n" +#define MSGTR_LIBVO_VESA_UsingBankSwitchingMode "[VO_VESA] Using bank switching mode (physical resources: %08lXh, %08lXh).\n" +#define MSGTR_LIBVO_VESA_CantAllocateTemporaryBuffer "[VO_VESA] Can't allocate temporary buffer.\n" +#define MSGTR_LIBVO_VESA_SorryUnsupportedMode "[VO_VESA] Sorry, unsupported mode -- try -x 640 -zoom.\n" +#define MSGTR_LIBVO_VESA_OhYouReallyHavePictureOnTv "[VO_VESA] Oh you really have a picture on the TV!\n" +#define MSGTR_LIBVO_VESA_CantInitialozeLinuxVideoOverlay "[VO_VESA] Can't initialize Linux Video Overlay.\n" +#define MSGTR_LIBVO_VESA_UsingVideoOverlay "[VO_VESA] Using video overlay: %s.\n" +#define MSGTR_LIBVO_VESA_CantInitializeVidixDriver "[VO_VESA] Can't initialize VIDIX driver.\n" +#define MSGTR_LIBVO_VESA_UsingVidix "[VO_VESA] Using VIDIX.\n" +#define MSGTR_LIBVO_VESA_CantFindModeFor "[VO_VESA] Can't find mode for: %ux%u@%u.\n" +#define MSGTR_LIBVO_VESA_InitializationComplete "[VO_VESA] VESA initialization complete.\n" + +// vesa_lvo.c +#define MSGTR_LIBVO_VESA_ThisBranchIsNoLongerSupported "[VESA_LVO] This branch is no longer supported.\n[VESA_LVO] Please use -vo vesa:vidix instead.\n" +#define MSGTR_LIBVO_VESA_CouldntOpen "[VESA_LVO] Couldn't open: '%s'\n" +#define MSGTR_LIBVO_VESA_InvalidOutputFormat "[VESA_LVI] Invalid output format: %s(%0X)\n" +#define MSGTR_LIBVO_VESA_IncompatibleDriverVersion "[VESA_LVO] Your fb_vid driver version is incompatible with this MPlayer version!\n" + +// vo_x11.c +#define MSGTR_LIBVO_X11_DrawFrameCalled "[VO_X11] draw_frame() called!!!!!!\n" + +// vo_xv.c +#define MSGTR_LIBVO_XV_DrawFrameCalled "[VO_XV] draw_frame() called!!!!!!\n" +#define MSGTR_LIBVO_XV_SharedMemoryNotSupported "[VO_XV] Shared memory not supported\nReverting to normal Xv.\n" +#define MSGTR_LIBVO_XV_XvNotSupportedByX11 "[VO_XV] Sorry, Xv not supported by this X11 version/driver\n[VO_XV] ******** Try with -vo x11 or -vo sdl *********\n" +#define MSGTR_LIBVO_XV_XvQueryAdaptorsFailed "[VO_XV] XvQueryAdaptors failed.\n" +#define MSGTR_LIBVO_XV_InvalidPortParameter "[VO_XV] Invalid port parameter, overriding with port 0.\n" +#define MSGTR_LIBVO_XV_CouldNotGrabPort "[VO_XV] Could not grab port %i.\n" +#define MSGTR_LIBVO_XV_CouldNotFindFreePort "[VO_XV] Could not find free Xvideo port - maybe another process is already\n"\ +"[VO_XV] using it. Close all video applications, and try again. If that does\n"\ +"[VO_XV] not help, see 'mplayer -vo help' for other (non-xv) video out drivers.\n" +#define MSGTR_LIBVO_XV_NoXvideoSupport "[VO_XV] It seems there is no Xvideo support for your video card available.\n"\ +"[VO_XV] Run 'xvinfo' to verify its Xv support and read\n"\ +"[VO_XV] DOCS/HTML/en/video.html#xv!\n"\ +"[VO_XV] See 'mplayer -vo help' for other (non-xv) video out drivers.\n"\ +"[VO_XV] Try -vo x11.\n" +#define MSGTR_VO_XV_ImagedimTooHigh "Source image dimensions are too high: %ux%u (maximum is %ux%u)\n" + +// vo_yuv4mpeg.c +#define MSGTR_VO_YUV4MPEG_InterlacedHeightDivisibleBy4 "Interlaced mode requires image height to be divisible by 4." +#define MSGTR_VO_YUV4MPEG_InterlacedLineBufAllocFail "Unable to allocate line buffer for interlaced mode." +#define MSGTR_VO_YUV4MPEG_WidthDivisibleBy2 "Image width must be divisible by 2." +#define MSGTR_VO_YUV4MPEG_OutFileOpenError "Can't get memory or file handle to write \"%s\"!" +#define MSGTR_VO_YUV4MPEG_OutFileWriteError "Error writing image to output!" +#define MSGTR_VO_YUV4MPEG_UnknownSubDev "Unknown subdevice: %s" +#define MSGTR_VO_YUV4MPEG_InterlacedTFFMode "Using interlaced output mode, top-field first." +#define MSGTR_VO_YUV4MPEG_InterlacedBFFMode "Using interlaced output mode, bottom-field first." +#define MSGTR_VO_YUV4MPEG_ProgressiveMode "Using (default) progressive frame mode." + +// vosub_vidix.c +#define MSGTR_LIBVO_SUB_VIDIX_CantStartPlayback "[VO_SUB_VIDIX] Can't start playback: %s\n" +#define MSGTR_LIBVO_SUB_VIDIX_CantStopPlayback "[VO_SUB_VIDIX] Can't stop playback: %s\n" +#define MSGTR_LIBVO_SUB_VIDIX_InterleavedUvForYuv410pNotSupported "[VO_SUB_VIDIX] Interleaved UV for YUV410P not supported.\n" +#define MSGTR_LIBVO_SUB_VIDIX_DummyVidixdrawsliceWasCalled "[VO_SUB_VIDIX] Dummy vidix_draw_slice() was called.\n" +#define MSGTR_LIBVO_SUB_VIDIX_DummyVidixdrawframeWasCalled "[VO_SUB_VIDIX] Dummy vidix_draw_frame() was called.\n" +#define MSGTR_LIBVO_SUB_VIDIX_UnsupportedFourccForThisVidixDriver "[VO_SUB_VIDIX] Unsupported FourCC for this VIDIX driver: %x (%s).\n" +#define MSGTR_LIBVO_SUB_VIDIX_VideoServerHasUnsupportedResolution "[VO_SUB_VIDIX] Video server has unsupported resolution (%dx%d), supported: %dx%d-%dx%d.\n" +#define MSGTR_LIBVO_SUB_VIDIX_VideoServerHasUnsupportedColorDepth "[VO_SUB_VIDIX] Video server has unsupported color depth by vidix (%d).\n" +#define MSGTR_LIBVO_SUB_VIDIX_DriverCantUpscaleImage "[VO_SUB_VIDIX] VIDIX driver can't upscale image (%d%d -> %d%d).\n" +#define MSGTR_LIBVO_SUB_VIDIX_DriverCantDownscaleImage "[VO_SUB_VIDIX] VIDIX driver can't downscale image (%d%d -> %d%d).\n" +#define MSGTR_LIBVO_SUB_VIDIX_CantConfigurePlayback "[VO_SUB_VIDIX] Can't configure playback: %s.\n" +#define MSGTR_LIBVO_SUB_VIDIX_YouHaveWrongVersionOfVidixLibrary "[VO_SUB_VIDIX] You have the wrong version of the VIDIX library.\n" +#define MSGTR_LIBVO_SUB_VIDIX_CouldntFindWorkingVidixDriver "[VO_SUB_VIDIX] Couldn't find working VIDIX driver.\n" +#define MSGTR_LIBVO_SUB_VIDIX_CouldntGetCapability "[VO_SUB_VIDIX] Couldn't get capability: %s.\n" + +// x11_common.c +#define MSGTR_EwmhFullscreenStateFailed "\nX11: Couldn't send EWMH fullscreen event!\n" +#define MSGTR_CouldNotFindXScreenSaver "xscreensaver_disable: Could not find XScreenSaver window.\n" +#define MSGTR_SelectedVideoMode "XF86VM: Selected video mode %dx%d for image size %dx%d.\n" + +#define MSGTR_InsertingAfVolume "[Mixer] No hardware mixing, inserting volume filter.\n" +#define MSGTR_NoVolume "[Mixer] No volume control available.\n" +#define MSGTR_NoBalance "[Mixer] No balance control available.\n" + +// old vo drivers that have been replaced +#define MSGTR_VO_PGM_HasBeenReplaced "The pgm video output driver has been replaced by -vo pnm:pgmyuv.\n" +#define MSGTR_VO_MD5_HasBeenReplaced "The md5 video output driver has been replaced by -vo md5sum.\n" + + +// ======================= audio output drivers ======================== + +// audio_out.c +#define MSGTR_AO_ALSA9_1x_Removed "audio_out: alsa9 and alsa1x modules were removed, use -ao alsa instead.\n" +#define MSGTR_AO_TryingPreferredAudioDriver "Trying preferred audio driver '%.*s', options '%s'\n" +#define MSGTR_AO_NoSuchDriver "No such audio driver '%.*s'\n" +#define MSGTR_AO_FailedInit "Failed to initialize audio driver '%s'\n" +#define MSGTR_AO_TryingEveryKnown "Trying every known audio driver...\n" + +// ao_oss.c +#define MSGTR_AO_OSS_CantOpenMixer "[AO OSS] audio_setup: Can't open mixer device %s: %s\n" +#define MSGTR_AO_OSS_ChanNotFound "[AO OSS] audio_setup: Audio card mixer does not have channel '%s', using default.\n" +#define MSGTR_AO_OSS_CantOpenDev "[AO OSS] audio_setup: Can't open audio device %s: %s\n" +#define MSGTR_AO_OSS_CantMakeFd "[AO OSS] audio_setup: Can't make file descriptor blocking: %s\n" +#define MSGTR_AO_OSS_CantSet "[AO OSS] Can't set audio device %s to %s output, trying %s...\n" +#define MSGTR_AO_OSS_CantSetChans "[AO OSS] audio_setup: Failed to set audio device to %d channels.\n" +#define MSGTR_AO_OSS_CantUseGetospace "[AO OSS] audio_setup: driver doesn't support SNDCTL_DSP_GETOSPACE :-(\n" +#define MSGTR_AO_OSS_CantUseSelect "[AO OSS]\n *** Your audio driver DOES NOT support select() ***\n Recompile MPlayer with #undef HAVE_AUDIO_SELECT in config.h !\n\n" +#define MSGTR_AO_OSS_CantReopen "[AO OSS]\nFatal error: *** CANNOT RE-OPEN / RESET AUDIO DEVICE *** %s\n" +#define MSGTR_AO_OSS_UnknownUnsupportedFormat "[AO OSS] Unknown/Unsupported OSS format: %x.\n" + +// ao_arts.c +#define MSGTR_AO_ARTS_CantInit "[AO ARTS] %s\n" +#define MSGTR_AO_ARTS_ServerConnect "[AO ARTS] Connected to sound server.\n" +#define MSGTR_AO_ARTS_CantOpenStream "[AO ARTS] Unable to open a stream.\n" +#define MSGTR_AO_ARTS_StreamOpen "[AO ARTS] Stream opened.\n" +#define MSGTR_AO_ARTS_BufferSize "[AO ARTS] buffer size: %d\n" + +// ao_dxr2.c +#define MSGTR_AO_DXR2_SetVolFailed "[AO DXR2] Setting volume to %d failed.\n" +#define MSGTR_AO_DXR2_UnsupSamplerate "[AO DXR2] %d Hz not supported, try to resample.\n" + +// ao_esd.c +#define MSGTR_AO_ESD_CantOpenSound "[AO ESD] esd_open_sound failed: %s\n" +#define MSGTR_AO_ESD_LatencyInfo "[AO ESD] latency: [server: %0.2fs, net: %0.2fs] (adjust %0.2fs)\n" +#define MSGTR_AO_ESD_CantOpenPBStream "[AO ESD] failed to open ESD playback stream: %s\n" + +// ao_mpegpes.c +#define MSGTR_AO_MPEGPES_CantSetMixer "[AO MPEGPES] DVB audio set mixer failed: %s.\n" +#define MSGTR_AO_MPEGPES_UnsupSamplerate "[AO MPEGPES] %d Hz not supported, try to resample.\n" + +// ao_pcm.c +#define MSGTR_AO_PCM_FileInfo "[AO PCM] File: %s (%s)\nPCM: Samplerate: %iHz Channels: %s Format %s\n" +#define MSGTR_AO_PCM_HintInfo "[AO PCM] Info: Faster dumping is achieved with -vc null -vo null -ao pcm:fast\n[AO PCM] Info: To write WAVE files use -ao pcm:waveheader (default).\n" +#define MSGTR_AO_PCM_CantOpenOutputFile "[AO PCM] Failed to open %s for writing!\n" + +// ao_sdl.c +#define MSGTR_AO_SDL_INFO "[AO SDL] Samplerate: %iHz Channels: %s Format %s\n" +#define MSGTR_AO_SDL_DriverInfo "[AO SDL] using %s audio driver.\n" +#define MSGTR_AO_SDL_UnsupportedAudioFmt "[AO SDL] Unsupported audio format: 0x%x.\n" +#define MSGTR_AO_SDL_CantInit "[AO SDL] SDL Audio initialization failed: %s\n" +#define MSGTR_AO_SDL_CantOpenAudio "[AO SDL] Unable to open audio: %s\n" + +// ao_sgi.c +#define MSGTR_AO_SGI_INFO "[AO SGI] control.\n" +#define MSGTR_AO_SGI_InitInfo "[AO SGI] init: Samplerate: %iHz Channels: %s Format %s\n" +#define MSGTR_AO_SGI_InvalidDevice "[AO SGI] play: invalid device.\n" +#define MSGTR_AO_SGI_CantSetParms_Samplerate "[AO SGI] init: setparams failed: %s\nCould not set desired samplerate.\n" +#define MSGTR_AO_SGI_CantSetAlRate "[AO SGI] init: AL_RATE was not accepted on the given resource.\n" +#define MSGTR_AO_SGI_CantGetParms "[AO SGI] init: getparams failed: %s\n" +#define MSGTR_AO_SGI_SampleRateInfo "[AO SGI] init: samplerate is now %lf (desired rate is %lf)\n" +#define MSGTR_AO_SGI_InitConfigError "[AO SGI] init: %s\n" +#define MSGTR_AO_SGI_InitOpenAudioFailed "[AO SGI] init: Unable to open audio channel: %s\n" +#define MSGTR_AO_SGI_Uninit "[AO SGI] uninit: ...\n" +#define MSGTR_AO_SGI_Reset "[AO SGI] reset: ...\n" +#define MSGTR_AO_SGI_PauseInfo "[AO SGI] audio_pause: ...\n" +#define MSGTR_AO_SGI_ResumeInfo "[AO SGI] audio_resume: ...\n" + +// ao_sun.c +#define MSGTR_AO_SUN_RtscSetinfoFailed "[AO SUN] rtsc: SETINFO failed.\n" +#define MSGTR_AO_SUN_RtscWriteFailed "[AO SUN] rtsc: write failed.\n" +#define MSGTR_AO_SUN_CantOpenAudioDev "[AO SUN] Can't open audio device %s, %s -> nosound.\n" +#define MSGTR_AO_SUN_UnsupSampleRate "[AO SUN] audio_setup: your card doesn't support %d channel, %s, %d Hz samplerate.\n" +#define MSGTR_AO_SUN_CantUseSelect "[AO SUN]\n *** Your audio driver DOES NOT support select() ***\nRecompile MPlayer with #undef HAVE_AUDIO_SELECT in config.h !\n\n" +#define MSGTR_AO_SUN_CantReopenReset "[AO SUN]\nFatal error: *** CANNOT REOPEN / RESET AUDIO DEVICE (%s) ***\n" + +// ao_alsa5.c +#define MSGTR_AO_ALSA5_InitInfo "[AO ALSA5] alsa-init: requested format: %d Hz, %d channels, %s\n" +#define MSGTR_AO_ALSA5_SoundCardNotFound "[AO ALSA5] alsa-init: no soundcards found.\n" +#define MSGTR_AO_ALSA5_InvalidFormatReq "[AO ALSA5] alsa-init: invalid format (%s) requested - output disabled.\n" +#define MSGTR_AO_ALSA5_PlayBackError "[AO ALSA5] alsa-init: playback open error: %s\n" +#define MSGTR_AO_ALSA5_PcmInfoError "[AO ALSA5] alsa-init: PCM info error: %s\n" +#define MSGTR_AO_ALSA5_SoundcardsFound "[AO ALSA5] alsa-init: %d soundcard(s) found, using: %s\n" +#define MSGTR_AO_ALSA5_PcmChanInfoError "[AO ALSA5] alsa-init: PCM channel info error: %s\n" +#define MSGTR_AO_ALSA5_CantSetParms "[AO ALSA5] alsa-init: error setting parameters: %s\n" +#define MSGTR_AO_ALSA5_CantSetChan "[AO ALSA5] alsa-init: error setting up channel: %s\n" +#define MSGTR_AO_ALSA5_ChanPrepareError "[AO ALSA5] alsa-init: channel prepare error: %s\n" +#define MSGTR_AO_ALSA5_DrainError "[AO ALSA5] alsa-uninit: playback drain error: %s\n" +#define MSGTR_AO_ALSA5_FlushError "[AO ALSA5] alsa-uninit: playback flush error: %s\n" +#define MSGTR_AO_ALSA5_PcmCloseError "[AO ALSA5] alsa-uninit: PCM close error: %s\n" +#define MSGTR_AO_ALSA5_ResetDrainError "[AO ALSA5] alsa-reset: playback drain error: %s\n" +#define MSGTR_AO_ALSA5_ResetFlushError "[AO ALSA5] alsa-reset: playback flush error: %s\n" +#define MSGTR_AO_ALSA5_ResetChanPrepareError "[AO ALSA5] alsa-reset: channel prepare error: %s\n" +#define MSGTR_AO_ALSA5_PauseDrainError "[AO ALSA5] alsa-pause: playback drain error: %s\n" +#define MSGTR_AO_ALSA5_PauseFlushError "[AO ALSA5] alsa-pause: playback flush error: %s\n" +#define MSGTR_AO_ALSA5_ResumePrepareError "[AO ALSA5] alsa-resume: channel prepare error: %s\n" +#define MSGTR_AO_ALSA5_Underrun "[AO ALSA5] alsa-play: alsa underrun, resetting stream.\n" +#define MSGTR_AO_ALSA5_PlaybackPrepareError "[AO ALSA5] alsa-play: playback prepare error: %s\n" +#define MSGTR_AO_ALSA5_WriteErrorAfterReset "[AO ALSA5] alsa-play: write error after reset: %s - giving up.\n" +#define MSGTR_AO_ALSA5_OutPutError "[AO ALSA5] alsa-play: output error: %s\n" + +// ao_alsa.c +#define MSGTR_AO_ALSA_InvalidMixerIndexDefaultingToZero "[AO_ALSA] Invalid mixer index. Defaulting to 0.\n" +#define MSGTR_AO_ALSA_MixerOpenError "[AO_ALSA] Mixer open error: %s\n" +#define MSGTR_AO_ALSA_MixerAttachError "[AO_ALSA] Mixer attach %s error: %s\n" +#define MSGTR_AO_ALSA_MixerRegisterError "[AO_ALSA] Mixer register error: %s\n" +#define MSGTR_AO_ALSA_MixerLoadError "[AO_ALSA] Mixer load error: %s\n" +#define MSGTR_AO_ALSA_UnableToFindSimpleControl "[AO_ALSA] Unable to find simple control '%s',%i.\n" +#define MSGTR_AO_ALSA_ErrorSettingLeftChannel "[AO_ALSA] Error setting left channel, %s\n" +#define MSGTR_AO_ALSA_ErrorSettingRightChannel "[AO_ALSA] Error setting right channel, %s\n" +#define MSGTR_AO_ALSA_CommandlineHelp "\n[AO_ALSA] -ao alsa commandline help:\n"\ +"[AO_ALSA] Example: mplayer -ao alsa:device=hw=0.3\n"\ +"[AO_ALSA] Sets first card fourth hardware device.\n\n"\ +"[AO_ALSA] Options:\n"\ +"[AO_ALSA] noblock\n"\ +"[AO_ALSA] Opens device in non-blocking mode.\n"\ +"[AO_ALSA] device=<device-name>\n"\ +"[AO_ALSA] Sets device (change , to . and : to =)\n" +#define MSGTR_AO_ALSA_ChannelsNotSupported "[AO_ALSA] %d channels are not supported.\n" +#define MSGTR_AO_ALSA_OpenInNonblockModeFailed "[AO_ALSA] Open in nonblock-mode failed, trying to open in block-mode.\n" +#define MSGTR_AO_ALSA_PlaybackOpenError "[AO_ALSA] Playback open error: %s\n" +#define MSGTR_AO_ALSA_ErrorSetBlockMode "[AL_ALSA] Error setting block-mode %s.\n" +#define MSGTR_AO_ALSA_UnableToGetInitialParameters "[AO_ALSA] Unable to get initial parameters: %s\n" +#define MSGTR_AO_ALSA_UnableToSetAccessType "[AO_ALSA] Unable to set access type: %s\n" +#define MSGTR_AO_ALSA_FormatNotSupportedByHardware "[AO_ALSA] Format %s is not supported by hardware, trying default.\n" +#define MSGTR_AO_ALSA_UnableToSetFormat "[AO_ALSA] Unable to set format: %s\n" +#define MSGTR_AO_ALSA_UnableToSetChannels "[AO_ALSA] Unable to set channels: %s\n" +#define MSGTR_AO_ALSA_UnableToDisableResampling "[AO_ALSA] Unable to disable resampling: %s\n" +#define MSGTR_AO_ALSA_UnableToSetSamplerate2 "[AO_ALSA] Unable to set samplerate-2: %s\n" +#define MSGTR_AO_ALSA_UnableToSetBufferTimeNear "[AO_ALSA] Unable to set buffer time near: %s\n" +#define MSGTR_AO_ALSA_UnableToGetPeriodSize "[AO ALSA] Unable to get period size: %s\n" +#define MSGTR_AO_ALSA_UnableToSetPeriods "[AO_ALSA] Unable to set periods: %s\n" +#define MSGTR_AO_ALSA_UnableToSetHwParameters "[AO_ALSA] Unable to set hw-parameters: %s\n" +#define MSGTR_AO_ALSA_UnableToGetBufferSize "[AO_ALSA] Unable to get buffersize: %s\n" +#define MSGTR_AO_ALSA_UnableToGetSwParameters "[AO_ALSA] Unable to get sw-parameters: %s\n" +#define MSGTR_AO_ALSA_UnableToSetSwParameters "[AO_ALSA] Unable to set sw-parameters: %s\n" +#define MSGTR_AO_ALSA_UnableToGetBoundary "[AO_ALSA] Unable to get boundary: %s\n" +#define MSGTR_AO_ALSA_UnableToSetStartThreshold "[AO_ALSA] Unable to set start threshold: %s\n" +#define MSGTR_AO_ALSA_UnableToSetStopThreshold "[AO_ALSA] Unable to set stop threshold: %s\n" +#define MSGTR_AO_ALSA_UnableToSetSilenceSize "[AO_ALSA] Unable to set silence size: %s\n" +#define MSGTR_AO_ALSA_PcmCloseError "[AO_ALSA] pcm close error: %s\n" +#define MSGTR_AO_ALSA_NoHandlerDefined "[AO_ALSA] No handler defined!\n" +#define MSGTR_AO_ALSA_PcmPrepareError "[AO_ALSA] pcm prepare error: %s\n" +#define MSGTR_AO_ALSA_PcmPauseError "[AO_ALSA] pcm pause error: %s\n" +#define MSGTR_AO_ALSA_PcmDropError "[AO_ALSA] pcm drop error: %s\n" +#define MSGTR_AO_ALSA_PcmResumeError "[AO_ALSA] pcm resume error: %s\n" +#define MSGTR_AO_ALSA_DeviceConfigurationError "[AO_ALSA] Device configuration error." +#define MSGTR_AO_ALSA_PcmInSuspendModeTryingResume "[AO_ALSA] Pcm in suspend mode, trying to resume.\n" +#define MSGTR_AO_ALSA_WriteError "[AO_ALSA] Write error: %s\n" +#define MSGTR_AO_ALSA_TryingToResetSoundcard "[AO_ALSA] Trying to reset soundcard.\n" +#define MSGTR_AO_ALSA_CannotGetPcmStatus "[AO_ALSA] Cannot get pcm status: %s\n" + +// ao_plugin.c +#define MSGTR_AO_PLUGIN_InvalidPlugin "[AO PLUGIN] invalid plugin: %s\n" + + +// ======================= audio filters ================================ + +// af_scaletempo.c +#define MSGTR_AF_ValueOutOfRange MSGTR_VO_ValueOutOfRange + +// af_ladspa.c +#define MSGTR_AF_LADSPA_AvailableLabels "available labels in" +#define MSGTR_AF_LADSPA_WarnNoInputs "WARNING! This LADSPA plugin has no audio inputs.\n The incoming audio signal will be lost." +#define MSGTR_AF_LADSPA_ErrMultiChannel "Multi-channel (>2) plugins are not supported (yet).\n Use only mono and stereo plugins." +#define MSGTR_AF_LADSPA_ErrNoOutputs "This LADSPA plugin has no audio outputs." +#define MSGTR_AF_LADSPA_ErrInOutDiff "The number of audio inputs and audio outputs of the LADSPA plugin differ." +#define MSGTR_AF_LADSPA_ErrFailedToLoad "failed to load" +#define MSGTR_AF_LADSPA_ErrNoDescriptor "Couldn't find ladspa_descriptor() function in the specified library file." +#define MSGTR_AF_LADSPA_ErrLabelNotFound "Couldn't find label in plugin library." +#define MSGTR_AF_LADSPA_ErrNoSuboptions "No suboptions specified." +#define MSGTR_AF_LADSPA_ErrNoLibFile "No library file specified." +#define MSGTR_AF_LADSPA_ErrNoLabel "No filter label specified." +#define MSGTR_AF_LADSPA_ErrNotEnoughControls "Not enough controls specified on the command line." +#define MSGTR_AF_LADSPA_ErrControlBelow "%s: Input control #%d is below lower boundary of %0.4f.\n" +#define MSGTR_AF_LADSPA_ErrControlAbove "%s: Input control #%d is above upper boundary of %0.4f.\n" + +// format.c +#define MSGTR_AF_FORMAT_UnknownFormat "unknown format " + + +// ========================== INPUT ========================================= + +// joystick.c +#define MSGTR_INPUT_JOYSTICK_Opening "Opening joystick device %s\n" +#define MSGTR_INPUT_JOYSTICK_CantOpen "Can't open joystick device %s: %s\n" +#define MSGTR_INPUT_JOYSTICK_ErrReading "Error while reading joystick device: %s\n" +#define MSGTR_INPUT_JOYSTICK_LoosingBytes "Joystick: We lose %d bytes of data\n" +#define MSGTR_INPUT_JOYSTICK_WarnLostSync "Joystick: warning init event, we have lost sync with driver.\n" +#define MSGTR_INPUT_JOYSTICK_WarnUnknownEvent "Joystick warning unknown event type %d\n" + +// appleir.c +#define MSGTR_INPUT_APPLE_IR_Init "Initializing Apple IR on %s\n" +#define MSGTR_INPUT_APPLE_IR_Detect "Detected Apple IR on %s\n" +#define MSGTR_INPUT_APPLE_IR_CantOpen "Can't open Apple IR device: %s\n" + +// input.c +#define MSGTR_INPUT_INPUT_ErrCantRegister2ManyCmdFds "Too many command file descriptors, cannot register file descriptor %d.\n" +#define MSGTR_INPUT_INPUT_ErrCantRegister2ManyKeyFds "Too many key file descriptors, cannot register file descriptor %d.\n" +#define MSGTR_INPUT_INPUT_ErrArgMustBeInt "Command %s: argument %d isn't an integer.\n" +#define MSGTR_INPUT_INPUT_ErrArgMustBeFloat "Command %s: argument %d isn't a float.\n" +#define MSGTR_INPUT_INPUT_ErrUnterminatedArg "Command %s: argument %d is unterminated.\n" +#define MSGTR_INPUT_INPUT_ErrUnknownArg "Unknown argument %d\n" +#define MSGTR_INPUT_INPUT_Err2FewArgs "Command %s requires at least %d arguments, we found only %d so far.\n" +#define MSGTR_INPUT_INPUT_ErrReadingCmdFd "Error while reading command file descriptor %d: %s\n" +#define MSGTR_INPUT_INPUT_ErrCmdBufferFullDroppingContent "Command buffer of file descriptor %d is full: dropping content.\n" +#define MSGTR_INPUT_INPUT_ErrInvalidCommandForKey "Invalid command for bound key %s" +#define MSGTR_INPUT_INPUT_ErrSelect "Select error: %s\n" +#define MSGTR_INPUT_INPUT_ErrOnKeyInFd "Error on key input file descriptor %d\n" +#define MSGTR_INPUT_INPUT_ErrDeadKeyOnFd "Dead key input on file descriptor %d\n" +#define MSGTR_INPUT_INPUT_Err2ManyKeyDowns "Too many key down events at the same time\n" +#define MSGTR_INPUT_INPUT_ErrOnCmdFd "Error on command file descriptor %d\n" +#define MSGTR_INPUT_INPUT_ErrReadingInputConfig "Error while reading input config file %s: %s\n" +#define MSGTR_INPUT_INPUT_ErrUnknownKey "Unknown key '%s'\n" +#define MSGTR_INPUT_INPUT_ErrUnfinishedBinding "Unfinished binding %s\n" +#define MSGTR_INPUT_INPUT_ErrBuffer2SmallForKeyName "Buffer is too small for this key name: %s\n" +#define MSGTR_INPUT_INPUT_ErrNoCmdForKey "No command found for key %s" +#define MSGTR_INPUT_INPUT_ErrBuffer2SmallForCmd "Buffer is too small for command %s\n" +#define MSGTR_INPUT_INPUT_ErrWhyHere "What are we doing here?\n" +#define MSGTR_INPUT_INPUT_ErrCantInitJoystick "Can't init input joystick\n" +#define MSGTR_INPUT_INPUT_ErrCantStatFile "Can't stat %s: %s\n" +#define MSGTR_INPUT_INPUT_ErrCantOpenFile "Can't open %s: %s\n" +#define MSGTR_INPUT_INPUT_ErrCantInitAppleRemote "Can't init Apple Remote.\n" + +// lirc.c +#define MSGTR_SettingUpLIRC "Setting up LIRC support...\n" +#define MSGTR_LIRCopenfailed "Failed to open LIRC support. You will not be able to use your remote control.\n" +#define MSGTR_LIRCcfgerr "Failed to read LIRC config file %s.\n" + + +// ========================== LIBMPDEMUX =================================== + +// muxer.c, muxer_*.c +#define MSGTR_TooManyStreams "Too many streams!" +#define MSGTR_RawMuxerOnlyOneStream "Rawaudio muxer supports only one audio stream!\n" +#define MSGTR_IgnoringVideoStream "Ignoring video stream!\n" +#define MSGTR_UnknownStreamType "Warning, unknown stream type: %d\n" +#define MSGTR_WarningLenIsntDivisible "Warning, len isn't divisible by samplesize!\n" +#define MSGTR_MuxbufMallocErr "Muxer frame buffer cannot allocate memory!\n" +#define MSGTR_MuxbufReallocErr "Muxer frame buffer cannot reallocate memory!\n" +#define MSGTR_MuxbufSending "Muxer frame buffer sending %d frame(s) to the muxer.\n" +#define MSGTR_WritingHeader "Writing header...\n" +#define MSGTR_WritingTrailer "Writing index...\n" + +// demuxer.c, demux_*.c +#define MSGTR_AudioStreamRedefined "WARNING: Audio stream header %d redefined.\n" +#define MSGTR_VideoStreamRedefined "WARNING: Video stream header %d redefined.\n" +#define MSGTR_TooManyAudioInBuffer "\nToo many audio packets in the buffer: (%d in %d bytes).\n" +#define MSGTR_TooManyVideoInBuffer "\nToo many video packets in the buffer: (%d in %d bytes).\n" +#define MSGTR_MaybeNI "Maybe you are playing a non-interleaved stream/file or the codec failed?\n" \ + "For AVI files, try to force non-interleaved mode with the -ni option.\n" +#define MSGTR_WorkAroundBlockAlignHeaderBug "AVI: Working around CBR-MP3 nBlockAlign header bug!\n" +#define MSGTR_SwitchToNi "\nBadly interleaved AVI file detected - switching to -ni mode...\n" +#define MSGTR_InvalidAudioStreamNosound "AVI: invalid audio stream ID: %d - ignoring (nosound)\n" +#define MSGTR_InvalidAudioStreamUsingDefault "AVI: invalid video stream ID: %d - ignoring (using default)\n" +#define MSGTR_ON2AviFormat "ON2 AVI format" +#define MSGTR_Detected_XXX_FileFormat "%s file format detected.\n" +#define MSGTR_DetectedAudiofile "Audio file detected.\n" +#define MSGTR_NotSystemStream "Not MPEG System Stream format... (maybe Transport Stream?)\n" +#define MSGTR_InvalidMPEGES "Invalid MPEG-ES stream??? Contact the author, it may be a bug :(\n" +#define MSGTR_FormatNotRecognized "============ Sorry, this file format is not recognized/supported =============\n"\ + "=== If this file is an AVI, ASF or MPEG stream, please contact the author! ===\n" +#define MSGTR_SettingProcessPriority "Setting process priority: %s\n" +#define MSGTR_FilefmtFourccSizeFpsFtime "[V] filefmt:%d fourcc:0x%X size:%dx%d fps:%5.3f ftime:=%6.4f\n" +#define MSGTR_CannotInitializeMuxer "Cannot initialize muxer." +#define MSGTR_MissingVideoStream "No video stream found.\n" +#define MSGTR_MissingAudioStream "No audio stream found -> no sound.\n" +#define MSGTR_MissingVideoStreamBug "Missing video stream!? Contact the author, it may be a bug :(\n" + +#define MSGTR_DoesntContainSelectedStream "demux: File doesn't contain the selected audio or video stream.\n" + +#define MSGTR_NI_Forced "Forced" +#define MSGTR_NI_Detected "Detected" +#define MSGTR_NI_Message "%s NON-INTERLEAVED AVI file format.\n" + +#define MSGTR_UsingNINI "Using NON-INTERLEAVED broken AVI file format.\n" +#define MSGTR_CouldntDetFNo "Could not determine number of frames (for absolute seek).\n" +#define MSGTR_CantSeekRawAVI "Cannot seek in raw AVI streams. (Index required, try with the -idx switch.)\n" +#define MSGTR_CantSeekFile "Cannot seek in this file.\n" + +#define MSGTR_MOVcomprhdr "MOV: Compressed headers support requires ZLIB!\n" +#define MSGTR_MOVvariableFourCC "MOV: WARNING: Variable FourCC detected!?\n" +#define MSGTR_MOVtooManyTrk "MOV: WARNING: too many tracks" +#define MSGTR_FoundAudioStream "==> Found audio stream: %d\n" +#define MSGTR_FoundVideoStream "==> Found video stream: %d\n" +#define MSGTR_DetectedTV "TV detected! ;-)\n" +#define MSGTR_ErrorOpeningOGGDemuxer "Unable to open the Ogg demuxer.\n" +#define MSGTR_ASFSearchingForAudioStream "ASF: Searching for audio stream (id:%d).\n" +#define MSGTR_CannotOpenAudioStream "Cannot open audio stream: %s\n" +#define MSGTR_CannotOpenSubtitlesStream "Cannot open subtitle stream: %s\n" +#define MSGTR_OpeningAudioDemuxerFailed "Failed to open audio demuxer: %s\n" +#define MSGTR_OpeningSubtitlesDemuxerFailed "Failed to open subtitle demuxer: %s\n" +#define MSGTR_TVInputNotSeekable "TV input is not seekable! (Seeking will probably be for changing channels ;)\n" +#define MSGTR_DemuxerInfoChanged "Demuxer info %s changed to %s\n" +#define MSGTR_ClipInfo "Clip info:\n" + +#define MSGTR_LeaveTelecineMode "\ndemux_mpg: 30000/1001fps NTSC content detected, switching framerate.\n" +#define MSGTR_EnterTelecineMode "\ndemux_mpg: 24000/1001fps progressive NTSC content detected, switching framerate.\n" + +#define MSGTR_CacheFill "\rCache fill: %5.2f%% (%"PRId64" bytes) " +#define MSGTR_NoBindFound "No bind found for key '%s'." +#define MSGTR_FailedToOpen "Failed to open %s.\n" + +#define MSGTR_VideoID "[%s] Video stream found, -vid %d\n" +#define MSGTR_AudioID "[%s] Audio stream found, -aid %d\n" +#define MSGTR_SubtitleID "[%s] Subtitle stream found, -sid %d\n" + +// asfheader.c +#define MSGTR_MPDEMUX_ASFHDR_HeaderSizeOver1MB "FATAL: header size bigger than 1 MB (%d)!\nPlease contact MPlayer authors, and upload/send this file.\n" +#define MSGTR_MPDEMUX_ASFHDR_HeaderMallocFailed "Could not allocate %d bytes for header.\n" +#define MSGTR_MPDEMUX_ASFHDR_EOFWhileReadingHeader "EOF while reading ASF header, broken/incomplete file?\n" +#define MSGTR_MPDEMUX_ASFHDR_DVRWantsLibavformat "DVR will probably only work with libavformat, try -demuxer 35 if you have problems\n" +#define MSGTR_MPDEMUX_ASFHDR_NoDataChunkAfterHeader "No data chunk following header!\n" +#define MSGTR_MPDEMUX_ASFHDR_AudioVideoHeaderNotFound "ASF: no audio or video headers found - broken file?\n" +#define MSGTR_MPDEMUX_ASFHDR_InvalidLengthInASFHeader "Invalid length in ASF header!\n" +#define MSGTR_MPDEMUX_ASFHDR_DRMLicenseURL "DRM License URL: %s\n" +#define MSGTR_MPDEMUX_ASFHDR_DRMProtected "This file has been encumbered with DRM encryption, it will not play in MPlayer!\n" + +// aviheader.c +#define MSGTR_MPDEMUX_AVIHDR_EmptyList "** empty list?!\n" +#define MSGTR_MPDEMUX_AVIHDR_FoundMovieAt "Found movie at 0x%X - 0x%X\n" +#define MSGTR_MPDEMUX_AVIHDR_FoundBitmapInfoHeader "Found 'bih', %u bytes of %d\n" +#define MSGTR_MPDEMUX_AVIHDR_RegeneratingKeyfTableForMPG4V1 "Regenerating keyframe table for M$ mpg4v1 video.\n" +#define MSGTR_MPDEMUX_AVIHDR_RegeneratingKeyfTableForDIVX3 "Regenerating keyframe table for DIVX3 video.\n" +#define MSGTR_MPDEMUX_AVIHDR_RegeneratingKeyfTableForMPEG4 "Regenerating keyframe table for MPEG-4 video.\n" +#define MSGTR_MPDEMUX_AVIHDR_FoundWaveFmt "Found 'wf', %d bytes of %d\n" +#define MSGTR_MPDEMUX_AVIHDR_FoundAVIV2Header "AVI: dmlh found (size=%d) (total_frames=%d)\n" +#define MSGTR_MPDEMUX_AVIHDR_ReadingIndexBlockChunksForFrames "Reading INDEX block, %d chunks for %d frames (fpos=%"PRId64").\n" +#define MSGTR_MPDEMUX_AVIHDR_AdditionalRIFFHdr "Additional RIFF header...\n" +#define MSGTR_MPDEMUX_AVIHDR_WarnNotExtendedAVIHdr "** Warning: this is no extended AVI header..\n" +#define MSGTR_MPDEMUX_AVIHDR_BrokenChunk "Broken chunk? chunksize=%d (id=%.4s)\n" +#define MSGTR_MPDEMUX_AVIHDR_BuildingODMLidx "AVI: ODML: Building ODML index (%d superindexchunks).\n" +#define MSGTR_MPDEMUX_AVIHDR_BrokenODMLfile "AVI: ODML: Broken (incomplete?) file detected. Will use traditional index.\n" +#define MSGTR_MPDEMUX_AVIHDR_CantReadIdxFile "Can't read index file %s: %s\n" +#define MSGTR_MPDEMUX_AVIHDR_NotValidMPidxFile "%s is not a valid MPlayer index file.\n" +#define MSGTR_MPDEMUX_AVIHDR_FailedMallocForIdxFile "Could not allocate memory for index data from %s.\n" +#define MSGTR_MPDEMUX_AVIHDR_PrematureEOF "premature end of index file %s\n" +#define MSGTR_MPDEMUX_AVIHDR_IdxFileLoaded "Loaded index file: %s\n" +#define MSGTR_MPDEMUX_AVIHDR_GeneratingIdx "Generating Index: %3lu %s \r" +#define MSGTR_MPDEMUX_AVIHDR_IdxGeneratedForHowManyChunks "AVI: Generated index table for %d chunks!\n" +#define MSGTR_MPDEMUX_AVIHDR_Failed2WriteIdxFile "Couldn't write index file %s: %s\n" +#define MSGTR_MPDEMUX_AVIHDR_IdxFileSaved "Saved index file: %s\n" + +// demux_audio.c +#define MSGTR_MPDEMUX_AUDIO_UnknownFormat "Audio demuxer: unknown format %d.\n" + +// demux_demuxers.c +#define MSGTR_MPDEMUX_DEMUXERS_FillBufferError "fill_buffer error: bad demuxer: not vd, ad or sd.\n" + +// demux_mkv.c +#define MSGTR_MPDEMUX_MKV_ZlibInitializationFailed "[mkv] zlib initialization failed.\n" +#define MSGTR_MPDEMUX_MKV_ZlibDecompressionFailed "[mkv] zlib decompression failed.\n" +#define MSGTR_MPDEMUX_MKV_LzoInitializationFailed "[mkv] lzo initialization failed.\n" +#define MSGTR_MPDEMUX_MKV_LzoDecompressionFailed "[mkv] lzo decompression failed.\n" +#define MSGTR_MPDEMUX_MKV_TrackEncrypted "[mkv] Track number %u has been encrypted and decryption has not yet been\n[mkv] implemented. Skipping track.\n" +#define MSGTR_MPDEMUX_MKV_UnknownContentEncoding "[mkv] Unknown content encoding type for track %u. Skipping track.\n" +#define MSGTR_MPDEMUX_MKV_UnknownCompression "[mkv] Track %u has been compressed with an unknown/unsupported compression\n[mkv] algorithm (%u). Skipping track.\n" +#define MSGTR_MPDEMUX_MKV_ZlibCompressionUnsupported "[mkv] Track %u was compressed with zlib but mplayer has not been compiled\n[mkv] with support for zlib compression. Skipping track.\n" +#define MSGTR_MPDEMUX_MKV_TrackIDName "[mkv] Track ID %u: %s (%s) \"%s\", %s\n" +#define MSGTR_MPDEMUX_MKV_TrackID "[mkv] Track ID %u: %s (%s), %s\n" +#define MSGTR_MPDEMUX_MKV_UnknownCodecID "[mkv] Unknown/unsupported CodecID (%s) or missing/bad CodecPrivate\n[mkv] data (track %u).\n" +#define MSGTR_MPDEMUX_MKV_FlacTrackDoesNotContainValidHeaders "[mkv] FLAC track does not contain valid headers.\n" +#define MSGTR_MPDEMUX_MKV_UnknownAudioCodec "[mkv] Unknown/unsupported audio codec ID '%s' for track %u or missing/faulty\n[mkv] private codec data.\n" +#define MSGTR_MPDEMUX_MKV_SubtitleTypeNotSupported "[mkv] Subtitle type '%s' is not supported.\n" +#define MSGTR_MPDEMUX_MKV_WillPlayVideoTrack "[mkv] Will play video track %u.\n" +#define MSGTR_MPDEMUX_MKV_NoVideoTrackFound "[mkv] No video track found/wanted.\n" +#define MSGTR_MPDEMUX_MKV_NoAudioTrackFound "[mkv] No audio track found/wanted.\n" +#define MSGTR_MPDEMUX_MKV_WillDisplaySubtitleTrack "[mkv] Will display subtitle track %u.\n" +#define MSGTR_MPDEMUX_MKV_NoBlockDurationForSubtitleTrackFound "[mkv] Warning: No BlockDuration for subtitle track found.\n" +#define MSGTR_MPDEMUX_MKV_TooManySublines "[mkv] Warning: too many sublines to render, skipping.\n" +#define MSGTR_MPDEMUX_MKV_TooManySublinesSkippingAfterFirst "\n[mkv] Warning: too many sublines to render, skipping after first %i.\n" + +// demux_nuv.c +#define MSGTR_MPDEMUX_NUV_NoVideoBlocksInFile "No video blocks in file.\n" + +// demux_xmms.c +#define MSGTR_MPDEMUX_XMMS_FoundPlugin "Found plugin: %s (%s).\n" +#define MSGTR_MPDEMUX_XMMS_ClosingPlugin "Closing plugin: %s.\n" +#define MSGTR_MPDEMUX_XMMS_WaitForStart "Waiting for the XMMS plugin to start playback of '%s'...\n" + + +// ========================== LIBMENU =================================== + +// common +#define MSGTR_LIBMENU_NoEntryFoundInTheMenuDefinition "[MENU] No entry found in the menu definition.\n" + +// libmenu/menu.c +#define MSGTR_LIBMENU_SyntaxErrorAtLine "[MENU] syntax error at line: %d\n" +#define MSGTR_LIBMENU_MenuDefinitionsNeedANameAttrib "[MENU] Menu definitions need a name attribute (line %d).\n" +#define MSGTR_LIBMENU_BadAttrib "[MENU] bad attribute %s=%s in menu '%s' at line %d\n" +#define MSGTR_LIBMENU_UnknownMenuType "[MENU] unknown menu type '%s' at line %d\n" +#define MSGTR_LIBMENU_CantOpenConfigFile "[MENU] Can't open menu config file: %s\n" +#define MSGTR_LIBMENU_ConfigFileIsTooBig "[MENU] Config file is too big (> %d KB)\n" +#define MSGTR_LIBMENU_ConfigFileIsEmpty "[MENU] Config file is empty.\n" +#define MSGTR_LIBMENU_MenuNotFound "[MENU] Menu %s not found.\n" +#define MSGTR_LIBMENU_MenuInitFailed "[MENU] Menu '%s': Init failed.\n" +#define MSGTR_LIBMENU_UnsupportedOutformat "[MENU] Unsupported output format!!!!\n" + +// libmenu/menu_cmdlist.c +#define MSGTR_LIBMENU_ListMenuEntryDefinitionsNeedAName "[MENU] List menu entry definitions need a name (line %d).\n" +#define MSGTR_LIBMENU_ListMenuNeedsAnArgument "[MENU] List menu needs an argument.\n" + +// libmenu/menu_console.c +#define MSGTR_LIBMENU_WaitPidError "[MENU] Waitpid error: %s.\n" +#define MSGTR_LIBMENU_SelectError "[MENU] Select error.\n" +#define MSGTR_LIBMENU_ReadErrorOnChildFD "[MENU] Read error on child's file descriptor: %s.\n" +#define MSGTR_LIBMENU_ConsoleRun "[MENU] Console run: %s ...\n" +#define MSGTR_LIBMENU_AChildIsAlreadyRunning "[MENU] A child is already running.\n" +#define MSGTR_LIBMENU_ForkFailed "[MENU] Fork failed !!!\n" +#define MSGTR_LIBMENU_WriteError "[MENU] write error\n" + +// libmenu/menu_filesel.c +#define MSGTR_LIBMENU_OpendirError "[MENU] opendir error: %s\n" +#define MSGTR_LIBMENU_ReallocError "[MENU] realloc error: %s\n" +#define MSGTR_LIBMENU_MallocError "[MENU] memory allocation error: %s\n" +#define MSGTR_LIBMENU_ReaddirError "[MENU] readdir error: %s\n" +#define MSGTR_LIBMENU_CantOpenDirectory "[MENU] Can't open directory %s.\n" + +// libmenu/menu_param.c +#define MSGTR_LIBMENU_SubmenuDefinitionNeedAMenuAttribut "[MENU] Submenu definition needs a 'menu' attribute.\n" +#define MSGTR_LIBMENU_InvalidProperty "[MENU] Invalid property '%s' in pref menu entry. (line %d).\n" +#define MSGTR_LIBMENU_PrefMenuEntryDefinitionsNeed "[MENU] Pref menu entry definitions need a valid 'property' or 'txt' attribute (line %d).\n" +#define MSGTR_LIBMENU_PrefMenuNeedsAnArgument "[MENU] Pref menu needs an argument.\n" + +// libmenu/menu_pt.c +#define MSGTR_LIBMENU_CantfindTheTargetItem "[MENU] Can't find the target item ????\n" +#define MSGTR_LIBMENU_FailedToBuildCommand "[MENU] Failed to build command: %s.\n" + +// libmenu/menu_txt.c +#define MSGTR_LIBMENU_MenuTxtNeedATxtFileName "[MENU] Text menu needs a textfile name (parameter file).\n" +#define MSGTR_LIBMENU_MenuTxtCantOpen "[MENU] Can't open %s.\n" +#define MSGTR_LIBMENU_WarningTooLongLineSplitting "[MENU] Warning, line too long. Splitting it.\n" +#define MSGTR_LIBMENU_ParsedLines "[MENU] Parsed %d lines.\n" + +// libmenu/vf_menu.c +#define MSGTR_LIBMENU_UnknownMenuCommand "[MENU] Unknown command: '%s'.\n" +#define MSGTR_LIBMENU_FailedToOpenMenu "[MENU] Failed to open menu: '%s'.\n" + + +// ========================== LIBMPCODECS =================================== + +// dec_video.c & dec_audio.c: +#define MSGTR_CantOpenCodec "Could not open codec.\n" +#define MSGTR_CantCloseCodec "Could not close codec.\n" + +#define MSGTR_MissingDLLcodec "ERROR: Could not open required DirectShow codec %s.\n" +#define MSGTR_ACMiniterror "Could not load/initialize Win32/ACM audio codec (missing DLL file?).\n" +#define MSGTR_MissingLAVCcodec "Cannot find codec '%s' in libavcodec...\n" + +#define MSGTR_MpegNoSequHdr "MPEG: FATAL: EOF while searching for sequence header.\n" +#define MSGTR_CannotReadMpegSequHdr "FATAL: Cannot read sequence header.\n" +#define MSGTR_CannotReadMpegSequHdrEx "FATAL: Cannot read sequence header extension.\n" +#define MSGTR_BadMpegSequHdr "MPEG: bad sequence header\n" +#define MSGTR_BadMpegSequHdrEx "MPEG: bad sequence header extension\n" + +#define MSGTR_ShMemAllocFail "Cannot allocate shared memory.\n" +#define MSGTR_CantAllocAudioBuf "Cannot allocate audio out buffer.\n" + +#define MSGTR_UnknownAudio "Unknown/missing audio format -> no sound\n" + +#define MSGTR_UsingExternalPP "[PP] Using external postprocessing filter, max q = %d.\n" +#define MSGTR_UsingCodecPP "[PP] Using codec's postprocessing, max q = %d.\n" +#define MSGTR_VideoAttributeNotSupportedByVO_VD "Video attribute '%s' is not supported by selected vo & vd.\n" +#define MSGTR_VideoCodecFamilyNotAvailableStr "Requested video codec family [%s] (vfm=%s) not available.\nEnable it at compilation.\n" +#define MSGTR_AudioCodecFamilyNotAvailableStr "Requested audio codec family [%s] (afm=%s) not available.\nEnable it at compilation.\n" +#define MSGTR_OpeningVideoDecoder "Opening video decoder: [%s] %s\n" +#define MSGTR_SelectedVideoCodec "Selected video codec: [%s] vfm: %s (%s)\n" +#define MSGTR_OpeningAudioDecoder "Opening audio decoder: [%s] %s\n" +#define MSGTR_SelectedAudioCodec "Selected audio codec: [%s] afm: %s (%s)\n" +#define MSGTR_BuildingAudioFilterChain "Building audio filter chain for %dHz/%dch/%s -> %dHz/%dch/%s...\n" +#define MSGTR_UninitVideoStr "Uninit video: %s\n" +#define MSGTR_UninitAudioStr "Uninit audio: %s\n" +#define MSGTR_VDecoderInitFailed "VDecoder init failed :(\n" +#define MSGTR_ADecoderInitFailed "ADecoder init failed :(\n" +#define MSGTR_ADecoderPreinitFailed "ADecoder preinit failed :(\n" +#define MSGTR_AllocatingBytesForInputBuffer "dec_audio: Allocating %d bytes for input buffer.\n" +#define MSGTR_AllocatingBytesForOutputBuffer "dec_audio: Allocating %d + %d = %d bytes for output buffer.\n" + +// ad_dvdpcm.c: +#define MSGTR_SamplesWanted "Samples of this format are needed to improve support. Please contact the developers.\n" + +// libmpcodecs/ad_libdv.c +#define MSGTR_MPCODECS_AudioFramesizeDiffers "[AD_LIBDV] Warning! Audio framesize differs! read=%d hdr=%d.\n" + +// vd.c +#define MSGTR_CodecDidNotSet "VDec: Codec did not set sh->disp_w and sh->disp_h, trying workaround.\n" +#define MSGTR_CouldNotFindColorspace "Could not find matching colorspace - retrying with -vf scale...\n" +#define MSGTR_MovieAspectIsSet "Movie-Aspect is %.2f:1 - prescaling to correct movie aspect.\n" +#define MSGTR_MovieAspectUndefined "Movie-Aspect is undefined - no prescaling applied.\n" + +// vd_dshow.c, vd_dmo.c +#define MSGTR_DownloadCodecPackage "You need to upgrade/install the binary codecs package.\nGo to http://www.mplayerhq.hu/dload.html\n" +#define MSGTR_DShowInitOK "INFO: Win32/DShow video codec init OK.\n" +#define MSGTR_DMOInitOK "INFO: Win32/DMO video codec init OK.\n" + +// libmpcodecs/vd_dmo.c vd_dshow.c vd_vfw.c +#define MSGTR_MPCODECS_CouldntAllocateImageForCinepakCodec "[VD_DMO] Couldn't allocate image for cinepak codec.\n" + +// libmpcodecs/vd_ffmpeg.c +#define MSGTR_MPCODECS_XVMCAcceleratedCodec "[VD_FFMPEG] XVMC accelerated codec.\n" +#define MSGTR_MPCODECS_ArithmeticMeanOfQP "[VD_FFMPEG] Arithmetic mean of QP: %2.4f, Harmonic mean of QP: %2.4f\n" +#define MSGTR_MPCODECS_DRIFailure "[VD_FFMPEG] DRI failure.\n" +#define MSGTR_MPCODECS_CouldntAllocateImageForCodec "[VD_FFMPEG] Couldn't allocate image for codec.\n" +#define MSGTR_MPCODECS_XVMCAcceleratedMPEG2 "[VD_FFMPEG] XVMC-accelerated MPEG-2.\n" +#define MSGTR_MPCODECS_TryingPixfmt "[VD_FFMPEG] Trying pixfmt=%d.\n" +#define MSGTR_MPCODECS_McGetBufferShouldWorkOnlyWithXVMC "[VD_FFMPEG] The mc_get_buffer should work only with XVMC acceleration!!" +#define MSGTR_MPCODECS_UnexpectedInitVoError "[VD_FFMPEG] Unexpected init_vo error.\n" +#define MSGTR_MPCODECS_UnrecoverableErrorRenderBuffersNotTaken "[VD_FFMPEG] Unrecoverable error, render buffers not taken.\n" +#define MSGTR_MPCODECS_OnlyBuffersAllocatedByVoXvmcAllowed "[VD_FFMPEG] Only buffers allocated by vo_xvmc allowed.\n" + +// libmpcodecs/ve_lavc.c +#define MSGTR_MPCODECS_HighQualityEncodingSelected "[VE_LAVC] High quality encoding selected (non-realtime)!\n" +#define MSGTR_MPCODECS_UsingConstantQscale "[VE_LAVC] Using constant qscale = %f (VBR).\n" + +// libmpcodecs/ve_raw.c +#define MSGTR_MPCODECS_OutputWithFourccNotSupported "[VE_RAW] Raw output with FourCC [%x] not supported!\n" +#define MSGTR_MPCODECS_NoVfwCodecSpecified "[VE_RAW] Required VfW codec not specified!!\n" + +// vf.c +#define MSGTR_CouldNotFindVideoFilter "Couldn't find video filter '%s'.\n" +#define MSGTR_CouldNotOpenVideoFilter "Couldn't open video filter '%s'.\n" +#define MSGTR_OpeningVideoFilter "Opening video filter: " +#define MSGTR_CannotFindColorspace "Cannot find matching colorspace, even by inserting 'scale' :(\n" + +// libmpcodecs/vf_crop.c +#define MSGTR_MPCODECS_CropBadPositionWidthHeight "[CROP] Bad position/width/height - cropped area outside of the original!\n" + +// libmpcodecs/vf_cropdetect.c +#define MSGTR_MPCODECS_CropArea "[CROP] Crop area: X: %d..%d Y: %d..%d (-vf crop=%d:%d:%d:%d).\n" + +// libmpcodecs/vf_format.c, vf_palette.c, vf_noformat.c +#define MSGTR_MPCODECS_UnknownFormatName "[VF_FORMAT] Unknown format name: '%s'.\n" + +// libmpcodecs/vf_framestep.c vf_noformat.c vf_palette.c vf_tile.c +#define MSGTR_MPCODECS_ErrorParsingArgument "[VF_FRAMESTEP] Error parsing argument.\n" + +// libmpcodecs/ve_vfw.c +#define MSGTR_MPCODECS_CompressorType "Compressor type: %.4lx\n" +#define MSGTR_MPCODECS_CompressorSubtype "Compressor subtype: %.4lx\n" +#define MSGTR_MPCODECS_CompressorFlags "Compressor flags: %lu, version %lu, ICM version: %lu\n" +#define MSGTR_MPCODECS_Flags "Flags:" +#define MSGTR_MPCODECS_Quality " quality" + +// libmpcodecs/vf_expand.c +#define MSGTR_MPCODECS_FullDRNotPossible "Full DR not possible, trying SLICES instead!\n" +#define MSGTR_MPCODECS_WarnNextFilterDoesntSupportSlices "WARNING! Next filter doesn't support SLICES, get ready for sig11...\n" +#define MSGTR_MPCODECS_FunWhydowegetNULL "Why do we get NULL??\n" + +// libmpcodecs/vf_test.c, vf_yuy2.c, vf_yvu9.c +#define MSGTR_MPCODECS_WarnNextFilterDoesntSupport "%s not supported by next filter/vo :(\n" + + +// ================================== LIBASS ==================================== + +// ass_bitmap.c +#define MSGTR_LIBASS_FT_Glyph_To_BitmapError "[ass] FT_Glyph_To_Bitmap error %d \n" +#define MSGTR_LIBASS_UnsupportedPixelMode "[ass] Unsupported pixel mode: %d\n" +#define MSGTR_LIBASS_GlyphBBoxTooLarge "[ass] Glyph bounding box too large: %dx%dpx\n" + +// ass.c +#define MSGTR_LIBASS_NoStyleNamedXFoundUsingY "[ass] [%p] Warning: no style named '%s' found, using '%s'\n" +#define MSGTR_LIBASS_BadTimestamp "[ass] bad timestamp\n" +#define MSGTR_LIBASS_BadEncodedDataSize "[ass] bad encoded data size\n" +#define MSGTR_LIBASS_FontLineTooLong "[ass] Font line too long: %d, %s\n" +#define MSGTR_LIBASS_EventFormatHeaderMissing "[ass] Event format header missing\n" +#define MSGTR_LIBASS_ErrorOpeningIconvDescriptor "[ass] error opening iconv descriptor.\n" +#define MSGTR_LIBASS_ErrorRecodingFile "[ass] error recoding file.\n" +#define MSGTR_LIBASS_FopenFailed "[ass] ass_read_file(%s): fopen failed\n" +#define MSGTR_LIBASS_FseekFailed "[ass] ass_read_file(%s): fseek failed\n" +#define MSGTR_LIBASS_RefusingToLoadSubtitlesLargerThan100M "[ass] ass_read_file(%s): Refusing to load subtitles larger than 100M\n" +#define MSGTR_LIBASS_ReadFailed "Read failed, %d: %s\n" +#define MSGTR_LIBASS_AddedSubtitleFileMemory "[ass] Added subtitle file: <memory> (%d styles, %d events)\n" +#define MSGTR_LIBASS_AddedSubtitleFileFname "[ass] Added subtitle file: %s (%d styles, %d events)\n" +#define MSGTR_LIBASS_FailedToCreateDirectory "[ass] Failed to create directory %s\n" +#define MSGTR_LIBASS_NotADirectory "[ass] Not a directory: %s\n" + +// ass_cache.c +#define MSGTR_LIBASS_TooManyFonts "[ass] Too many fonts\n" +#define MSGTR_LIBASS_ErrorOpeningFont "[ass] Error opening font: %s, %d\n" + +// ass_fontconfig.c +#define MSGTR_LIBASS_SelectedFontFamilyIsNotTheRequestedOne "[ass] fontconfig: Selected font is not the requested one: '%s' != '%s'\n" +#define MSGTR_LIBASS_UsingDefaultFontFamily "[ass] fontconfig_select: Using default font family: (%s, %d, %d) -> %s, %d\n" +#define MSGTR_LIBASS_UsingDefaultFont "[ass] fontconfig_select: Using default font: (%s, %d, %d) -> %s, %d\n" +#define MSGTR_LIBASS_UsingArialFontFamily "[ass] fontconfig_select: Using 'Arial' font family: (%s, %d, %d) -> %s, %d\n" +#define MSGTR_LIBASS_FcInitLoadConfigAndFontsFailed "[ass] FcInitLoadConfigAndFonts failed.\n" +#define MSGTR_LIBASS_UpdatingFontCache "[ass] Updating font cache.\n" +#define MSGTR_LIBASS_BetaVersionsOfFontconfigAreNotSupported "[ass] Beta versions of fontconfig are not supported.\n[ass] Update before reporting any bugs.\n" +#define MSGTR_LIBASS_FcStrSetAddFailed "[ass] FcStrSetAdd failed.\n" +#define MSGTR_LIBASS_FcDirScanFailed "[ass] FcDirScan failed.\n" +#define MSGTR_LIBASS_FcDirSave "[ass] FcDirSave failed.\n" +#define MSGTR_LIBASS_FcConfigAppFontAddDirFailed "[ass] FcConfigAppFontAddDir failed\n" +#define MSGTR_LIBASS_FontconfigDisabledDefaultFontWillBeUsed "[ass] Fontconfig disabled, only default font will be used.\n" +#define MSGTR_LIBASS_FunctionCallFailed "[ass] %s failed\n" + +// ass_render.c +#define MSGTR_LIBASS_NeitherPlayResXNorPlayResYDefined "[ass] Neither PlayResX nor PlayResY defined. Assuming 384x288.\n" +#define MSGTR_LIBASS_PlayResYUndefinedSettingY "[ass] PlayResY undefined, setting %d.\n" +#define MSGTR_LIBASS_PlayResXUndefinedSettingX "[ass] PlayResX undefined, setting %d.\n" +#define MSGTR_LIBASS_FT_Init_FreeTypeFailed "[ass] FT_Init_FreeType failed.\n" +#define MSGTR_LIBASS_Init "[ass] Init\n" +#define MSGTR_LIBASS_InitFailed "[ass] Init failed.\n" +#define MSGTR_LIBASS_BadCommand "[ass] Bad command: %c%c\n" +#define MSGTR_LIBASS_ErrorLoadingGlyph "[ass] Error loading glyph.\n" +#define MSGTR_LIBASS_FT_Glyph_Stroke_Error "[ass] FT_Glyph_Stroke error %d \n" +#define MSGTR_LIBASS_UnknownEffectType_InternalError "[ass] Unknown effect type (internal error)\n" +#define MSGTR_LIBASS_NoStyleFound "[ass] No style found!\n" +#define MSGTR_LIBASS_EmptyEvent "[ass] Empty event!\n" +#define MSGTR_LIBASS_MAX_GLYPHS_Reached "[ass] MAX_GLYPHS reached: event %d, start = %llu, duration = %llu\n Text = %s\n" +#define MSGTR_LIBASS_EventHeightHasChanged "[ass] Warning! Event height has changed! \n" + +// ass_font.c +#define MSGTR_LIBASS_GlyphNotFoundReselectingFont "[ass] Glyph 0x%X not found, selecting one more font for (%s, %d, %d)\n" +#define MSGTR_LIBASS_GlyphNotFound "[ass] Glyph 0x%X not found in font for (%s, %d, %d)\n" +#define MSGTR_LIBASS_ErrorOpeningMemoryFont "[ass] Error opening memory font: %s\n" +#define MSGTR_LIBASS_NoCharmaps "[ass] font face with no charmaps\n" +#define MSGTR_LIBASS_NoCharmapAutodetected "[ass] no charmap autodetected, trying the first one\n" + + +// ================================== stream ==================================== + +// ai_alsa1x.c +#define MSGTR_MPDEMUX_AIALSA1X_CannotSetSamplerate "Cannot set samplerate.\n" +#define MSGTR_MPDEMUX_AIALSA1X_CannotSetBufferTime "Cannot set buffer time.\n" +#define MSGTR_MPDEMUX_AIALSA1X_CannotSetPeriodTime "Cannot set period time.\n" + +// ai_alsa1x.c / ai_alsa.c +#define MSGTR_MPDEMUX_AIALSA_PcmBrokenConfig "Broken configuration for this PCM: no configurations available.\n" +#define MSGTR_MPDEMUX_AIALSA_UnavailableAccessType "Access type not available.\n" +#define MSGTR_MPDEMUX_AIALSA_UnavailableSampleFmt "Sample format not available.\n" +#define MSGTR_MPDEMUX_AIALSA_UnavailableChanCount "Channel count not available - reverting to default: %d\n" +#define MSGTR_MPDEMUX_AIALSA_CannotInstallHWParams "Unable to install hardware parameters: %s" +#define MSGTR_MPDEMUX_AIALSA_PeriodEqualsBufferSize "Can't use period equal to buffer size (%u == %lu)\n" +#define MSGTR_MPDEMUX_AIALSA_CannotInstallSWParams "Unable to install software parameters:\n" +#define MSGTR_MPDEMUX_AIALSA_ErrorOpeningAudio "Error opening audio: %s\n" +#define MSGTR_MPDEMUX_AIALSA_AlsaStatusError "ALSA status error: %s" +#define MSGTR_MPDEMUX_AIALSA_AlsaXRUN "ALSA xrun!!! (at least %.3f ms long)\n" +#define MSGTR_MPDEMUX_AIALSA_AlsaStatus "ALSA Status:\n" +#define MSGTR_MPDEMUX_AIALSA_AlsaXRUNPrepareError "ALSA xrun: prepare error: %s" +#define MSGTR_MPDEMUX_AIALSA_AlsaReadWriteError "ALSA read/write error" + +// ai_oss.c +#define MSGTR_MPDEMUX_AIOSS_Unable2SetChanCount "Unable to set channel count: %d\n" +#define MSGTR_MPDEMUX_AIOSS_Unable2SetStereo "Unable to set stereo: %d\n" +#define MSGTR_MPDEMUX_AIOSS_Unable2Open "Unable to open '%s': %s\n" +#define MSGTR_MPDEMUX_AIOSS_UnsupportedFmt "unsupported format\n" +#define MSGTR_MPDEMUX_AIOSS_Unable2SetAudioFmt "Unable to set audio format." +#define MSGTR_MPDEMUX_AIOSS_Unable2SetSamplerate "Unable to set samplerate: %d\n" +#define MSGTR_MPDEMUX_AIOSS_Unable2SetTrigger "Unable to set trigger: %d\n" +#define MSGTR_MPDEMUX_AIOSS_Unable2GetBlockSize "Unable to get block size!\n" +#define MSGTR_MPDEMUX_AIOSS_AudioBlockSizeZero "Audio block size is zero, setting to %d!\n" +#define MSGTR_MPDEMUX_AIOSS_AudioBlockSize2Low "Audio block size too low, setting to %d!\n" + +// asf_mmst_streaming.c +#define MSGTR_MPDEMUX_MMST_WriteError "write error\n" +#define MSGTR_MPDEMUX_MMST_EOFAlert "\nAlert! EOF\n" +#define MSGTR_MPDEMUX_MMST_PreHeaderReadFailed "pre-header read failed\n" +#define MSGTR_MPDEMUX_MMST_InvalidHeaderSize "Invalid header size, giving up.\n" +#define MSGTR_MPDEMUX_MMST_HeaderDataReadFailed "Header data read failed.\n" +#define MSGTR_MPDEMUX_MMST_packet_lenReadFailed "packet_len read failed.\n" +#define MSGTR_MPDEMUX_MMST_InvalidRTSPPacketSize "Invalid RTSP packet size, giving up.\n" +#define MSGTR_MPDEMUX_MMST_CmdDataReadFailed "Command data read failed.\n" +#define MSGTR_MPDEMUX_MMST_HeaderObject "header object\n" +#define MSGTR_MPDEMUX_MMST_DataObject "data object\n" +#define MSGTR_MPDEMUX_MMST_FileObjectPacketLen "file object, packet length = %d (%d)\n" +#define MSGTR_MPDEMUX_MMST_StreamObjectStreamID "stream object, stream ID: %d\n" +#define MSGTR_MPDEMUX_MMST_2ManyStreamID "Too many IDs, stream skipped." +#define MSGTR_MPDEMUX_MMST_UnknownObject "unknown object\n" +#define MSGTR_MPDEMUX_MMST_MediaDataReadFailed "Media data read failed.\n" +#define MSGTR_MPDEMUX_MMST_MissingSignature "missing signature\n" +#define MSGTR_MPDEMUX_MMST_PatentedTechnologyJoke "Everything done. Thank you for downloading a media file containing proprietary and patented technology.\n" +#define MSGTR_MPDEMUX_MMST_UnknownCmd "unknown command %02x\n" +#define MSGTR_MPDEMUX_MMST_GetMediaPacketErr "get_media_packet error : %s\n" +#define MSGTR_MPDEMUX_MMST_Connected "Connected\n" + +// asf_streaming.c +#define MSGTR_MPDEMUX_ASF_StreamChunkSize2Small "Ahhhh, stream_chunck size is too small: %d\n" +#define MSGTR_MPDEMUX_ASF_SizeConfirmMismatch "size_confirm mismatch!: %d %d\n" +#define MSGTR_MPDEMUX_ASF_WarnDropHeader "Warning: drop header ????\n" +#define MSGTR_MPDEMUX_ASF_ErrorParsingChunkHeader "Error while parsing chunk header\n" +#define MSGTR_MPDEMUX_ASF_NoHeaderAtFirstChunk "Didn't get a header as first chunk !!!!\n" +#define MSGTR_MPDEMUX_ASF_BufferMallocFailed "Error: Can't allocate %d bytes buffer.\n" +#define MSGTR_MPDEMUX_ASF_ErrReadingNetworkStream "Error while reading network stream.\n" +#define MSGTR_MPDEMUX_ASF_ErrChunk2Small "Error: Chunk is too small.\n" +#define MSGTR_MPDEMUX_ASF_ErrSubChunkNumberInvalid "Error: Subchunk number is invalid.\n" +#define MSGTR_MPDEMUX_ASF_Bandwidth2SmallCannotPlay "Bandwidth too small, file cannot be played!\n" +#define MSGTR_MPDEMUX_ASF_Bandwidth2SmallDeselectedAudio "Bandwidth too small, deselected audio stream.\n" +#define MSGTR_MPDEMUX_ASF_Bandwidth2SmallDeselectedVideo "Bandwidth too small, deselected video stream.\n" +#define MSGTR_MPDEMUX_ASF_InvalidLenInHeader "Invalid length in ASF header!\n" +#define MSGTR_MPDEMUX_ASF_ErrReadingChunkHeader "Error while reading chunk header.\n" +#define MSGTR_MPDEMUX_ASF_ErrChunkBiggerThanPacket "Error: chunk_size > packet_size\n" +#define MSGTR_MPDEMUX_ASF_ErrReadingChunk "Error while reading chunk.\n" +#define MSGTR_MPDEMUX_ASF_ASFRedirector "=====> ASF Redirector\n" +#define MSGTR_MPDEMUX_ASF_InvalidProxyURL "invalid proxy URL\n" +#define MSGTR_MPDEMUX_ASF_UnknownASFStreamType "unknown ASF stream type\n" +#define MSGTR_MPDEMUX_ASF_Failed2ParseHTTPResponse "Failed to parse HTTP response.\n" +#define MSGTR_MPDEMUX_ASF_ServerReturn "Server returned %d:%s\n" +#define MSGTR_MPDEMUX_ASF_ASFHTTPParseWarnCuttedPragma "ASF HTTP PARSE WARNING : Pragma %s cut from %zd bytes to %d\n" +#define MSGTR_MPDEMUX_ASF_SocketWriteError "socket write error: %s\n" +#define MSGTR_MPDEMUX_ASF_HeaderParseFailed "Failed to parse header.\n" +#define MSGTR_MPDEMUX_ASF_NoStreamFound "No stream found.\n" +#define MSGTR_MPDEMUX_ASF_UnknownASFStreamingType "unknown ASF streaming type\n" +#define MSGTR_MPDEMUX_ASF_InfoStreamASFURL "STREAM_ASF, URL: %s\n" +#define MSGTR_MPDEMUX_ASF_StreamingFailed "Failed, exiting.\n" + +// audio_in.c +#define MSGTR_MPDEMUX_AUDIOIN_ErrReadingAudio "\nError reading audio: %s\n" +#define MSGTR_MPDEMUX_AUDIOIN_XRUNSomeFramesMayBeLeftOut "Recovered from cross-run, some frames may be left out!\n" +#define MSGTR_MPDEMUX_AUDIOIN_ErrFatalCannotRecover "Fatal error, cannot recover!\n" +#define MSGTR_MPDEMUX_AUDIOIN_NotEnoughSamples "\nNot enough audio samples!\n" + +// cache2.c +#define MSGTR_MPDEMUX_CACHE2_NonCacheableStream "\rThis stream is non-cacheable.\n" +#define MSGTR_MPDEMUX_CACHE2_ReadFileposDiffers "!!! read_filepos differs!!! Report this bug...\n" + +// network.c +#define MSGTR_MPDEMUX_NW_UnknownAF "Unknown address family %d\n" +#define MSGTR_MPDEMUX_NW_ResolvingHostForAF "Resolving %s for %s...\n" +#define MSGTR_MPDEMUX_NW_CantResolv "Couldn't resolve name for %s: %s\n" +#define MSGTR_MPDEMUX_NW_ConnectingToServer "Connecting to server %s[%s]: %d...\n" +#define MSGTR_MPDEMUX_NW_CantConnect2Server "Failed to connect to server with %s\n" +#define MSGTR_MPDEMUX_NW_SelectFailed "Select failed.\n" +#define MSGTR_MPDEMUX_NW_ConnTimeout "connection timeout\n" +#define MSGTR_MPDEMUX_NW_GetSockOptFailed "getsockopt failed: %s\n" +#define MSGTR_MPDEMUX_NW_ConnectError "connect error: %s\n" +#define MSGTR_MPDEMUX_NW_InvalidProxySettingTryingWithout "Invalid proxy setting... Trying without proxy.\n" +#define MSGTR_MPDEMUX_NW_CantResolvTryingWithoutProxy "Could not resolve remote hostname for AF_INET. Trying without proxy.\n" +#define MSGTR_MPDEMUX_NW_ErrSendingHTTPRequest "Error while sending HTTP request: Didn't send all the request.\n" +#define MSGTR_MPDEMUX_NW_ReadFailed "Read failed.\n" +#define MSGTR_MPDEMUX_NW_Read0CouldBeEOF "http_read_response read 0 (i.e. EOF).\n" +#define MSGTR_MPDEMUX_NW_AuthFailed "Authentication failed. Please use the -user and -passwd options to provide your\n"\ +"username/password for a list of URLs, or form an URL like:\n"\ +"http://username:password@hostname/file\n" +#define MSGTR_MPDEMUX_NW_AuthRequiredFor "Authentication required for %s\n" +#define MSGTR_MPDEMUX_NW_AuthRequired "Authentication required.\n" +#define MSGTR_MPDEMUX_NW_NoPasswdProvidedTryingBlank "No password provided, trying blank password.\n" +#define MSGTR_MPDEMUX_NW_ErrServerReturned "Server returns %d: %s\n" +#define MSGTR_MPDEMUX_NW_CacheSizeSetTo "Cache size set to %d KBytes\n" + +// open.c, stream.c: +#define MSGTR_CdDevNotfound "CD-ROM Device '%s' not found.\n" +#define MSGTR_ErrTrackSelect "Error selecting VCD track." +#define MSGTR_ReadSTDIN "Reading from stdin...\n" +#define MSGTR_UnableOpenURL "Unable to open URL: %s\n" +#define MSGTR_ConnToServer "Connected to server: %s\n" +#define MSGTR_FileNotFound "File not found: '%s'\n" + +#define MSGTR_SMBInitError "Cannot init the libsmbclient library: %d\n" +#define MSGTR_SMBFileNotFound "Could not open from LAN: '%s'\n" +#define MSGTR_SMBNotCompiled "MPlayer was not compiled with SMB reading support.\n" + +#define MSGTR_CantOpenBluray "Couldn't open Blu-ray device: %s\n" +#define MSGTR_CantOpenDVD "Couldn't open DVD device: %s (%s)\n" + +// stream_cdda.c +#define MSGTR_MPDEMUX_CDDA_CantOpenCDDADevice "Can't open CDDA device.\n" +#define MSGTR_MPDEMUX_CDDA_CantOpenDisc "Can't open disc.\n" +#define MSGTR_MPDEMUX_CDDA_AudioCDFoundWithNTracks "Found audio CD with %d tracks.\n" + +// stream_cddb.c +#define MSGTR_MPDEMUX_CDDB_FailedToReadTOC "Failed to read TOC.\n" +#define MSGTR_MPDEMUX_CDDB_FailedToOpenDevice "Failed to open %s device.\n" +#define MSGTR_MPDEMUX_CDDB_NotAValidURL "not a valid URL\n" +#define MSGTR_MPDEMUX_CDDB_FailedToSendHTTPRequest "Failed to send the HTTP request.\n" +#define MSGTR_MPDEMUX_CDDB_FailedToReadHTTPResponse "Failed to read the HTTP response.\n" +#define MSGTR_MPDEMUX_CDDB_HTTPErrorNOTFOUND "Not Found.\n" +#define MSGTR_MPDEMUX_CDDB_HTTPErrorUnknown "unknown error code\n" +#define MSGTR_MPDEMUX_CDDB_NoCacheFound "No cache found.\n" +#define MSGTR_MPDEMUX_CDDB_NotAllXMCDFileHasBeenRead "Not all the xmcd file has been read.\n" +#define MSGTR_MPDEMUX_CDDB_FailedToCreateDirectory "Failed to create directory %s.\n" +#define MSGTR_MPDEMUX_CDDB_NotAllXMCDFileHasBeenWritten "Not all of the xmcd file has been written.\n" +#define MSGTR_MPDEMUX_CDDB_InvalidXMCDDatabaseReturned "Invalid xmcd database file returned.\n" +#define MSGTR_MPDEMUX_CDDB_UnexpectedFIXME "unexpected FIXME\n" +#define MSGTR_MPDEMUX_CDDB_UnhandledCode "unhandled code\n" +#define MSGTR_MPDEMUX_CDDB_UnableToFindEOL "Unable to find end of line.\n" +#define MSGTR_MPDEMUX_CDDB_ParseOKFoundAlbumTitle "Parse OK, found: %s\n" +#define MSGTR_MPDEMUX_CDDB_AlbumNotFound "Album not found.\n" +#define MSGTR_MPDEMUX_CDDB_ServerReturnsCommandSyntaxErr "Server returns: Command syntax error\n" +#define MSGTR_MPDEMUX_CDDB_NoSitesInfoAvailable "No sites information available.\n" +#define MSGTR_MPDEMUX_CDDB_FailedToGetProtocolLevel "Failed to get the protocol level.\n" +#define MSGTR_MPDEMUX_CDDB_NoCDInDrive "No CD in the drive.\n" + +// stream_cue.c +#define MSGTR_MPDEMUX_CUEREAD_UnexpectedCuefileLine "[bincue] Unexpected cuefile line: %s\n" +#define MSGTR_MPDEMUX_CUEREAD_BinFilenameTested "[bincue] bin filename tested: %s\n" +#define MSGTR_MPDEMUX_CUEREAD_CannotFindBinFile "[bincue] Couldn't find the bin file - giving up.\n" +#define MSGTR_MPDEMUX_CUEREAD_UsingBinFile "[bincue] Using bin file %s.\n" +#define MSGTR_MPDEMUX_CUEREAD_UnknownModeForBinfile "[bincue] unknown mode for binfile. Should not happen. Aborting.\n" +#define MSGTR_MPDEMUX_CUEREAD_CannotOpenCueFile "[bincue] Cannot open %s.\n" +#define MSGTR_MPDEMUX_CUEREAD_ErrReadingFromCueFile "[bincue] Error reading from %s\n" +#define MSGTR_MPDEMUX_CUEREAD_ErrGettingBinFileSize "[bincue] Error getting size of bin file.\n" +#define MSGTR_MPDEMUX_CUEREAD_InfoTrackFormat "track %02d: format=%d %02d:%02d:%02d\n" +#define MSGTR_MPDEMUX_CUEREAD_UnexpectedBinFileEOF "[bincue] unexpected end of bin file\n" +#define MSGTR_MPDEMUX_CUEREAD_CannotReadNBytesOfPayload "[bincue] Couldn't read %d bytes of payload.\n" +#define MSGTR_MPDEMUX_CUEREAD_CueStreamInfo_FilenameTrackTracksavail "CUE stream_open, filename=%s, track=%d, available tracks: %d -> %d\n" + +// stream_dvd.c +#define MSGTR_DVDspeedCantOpen "Couldn't open DVD device for writing, changing DVD speed needs write access.\n" +#define MSGTR_DVDrestoreSpeed "Restoring DVD speed... " +#define MSGTR_DVDlimitSpeed "Limiting DVD speed to %dKB/s... " +#define MSGTR_DVDlimitFail "failed\n" +#define MSGTR_DVDlimitOk "successful\n" +#define MSGTR_NoDVDSupport "MPlayer was compiled without DVD support, exiting.\n" +#define MSGTR_DVDnumTitles "There are %d titles on this DVD.\n" +#define MSGTR_DVDinvalidTitle "Invalid DVD title number: %d\n" +#define MSGTR_DVDnumChapters "There are %d chapters in this DVD title.\n" +#define MSGTR_DVDinvalidChapter "Invalid DVD chapter number: %d\n" +#define MSGTR_DVDinvalidChapterRange "Invalid chapter range specification %s\n" +#define MSGTR_DVDinvalidLastChapter "Invalid DVD last chapter number: %d\n" +#define MSGTR_DVDnumAngles "There are %d angles in this DVD title.\n" +#define MSGTR_DVDinvalidAngle "Invalid DVD angle number: %d\n" +#define MSGTR_DVDnoIFO "Cannot open the IFO file for DVD title %d.\n" +#define MSGTR_DVDnoVMG "Can't open VMG info!\n" +#define MSGTR_DVDnoVOBs "Cannot open title VOBS (VTS_%02d_1.VOB).\n" +#define MSGTR_DVDnoMatchingAudio "No matching DVD audio language found!\n" +#define MSGTR_DVDaudioChannel "Selected DVD audio channel: %d language: %c%c\n" +#define MSGTR_DVDaudioStreamInfo "audio stream: %d format: %s (%s) language: %s aid: %d.\n" +#define MSGTR_DVDnumAudioChannels "number of audio channels on disk: %d.\n" +#define MSGTR_DVDnoMatchingSubtitle "No matching DVD subtitle language found!\n" +#define MSGTR_DVDsubtitleChannel "Selected DVD subtitle channel: %d language: %c%c\n" +#define MSGTR_DVDsubtitleLanguage "subtitle ( sid ): %d language: %s\n" +#define MSGTR_DVDnumSubtitles "number of subtitles on disk: %d\n" + +// stream_bluray.c +#define MSGTR_BlurayNoDevice "No Blu-ray device/location was specified ...\n" +#define MSGTR_BlurayNoTitles "Can't find any Blu-ray-compatible title here.\n" +#define MSGTR_BlurayOK "Blu-ray successfully opened.\n" + +// stream_radio.c +#define MSGTR_RADIO_ChannelNamesDetected "[radio] Radio channel names detected.\n" +#define MSGTR_RADIO_FreqRange "[radio] Allowed frequency range is %.2f-%.2f MHz.\n" +#define MSGTR_RADIO_WrongFreqForChannel "[radio] Wrong frequency for channel %s\n" +#define MSGTR_RADIO_WrongChannelNumberFloat "[radio] Wrong channel number: %.2f\n" +#define MSGTR_RADIO_WrongChannelNumberInt "[radio] Wrong channel number: %d\n" +#define MSGTR_RADIO_WrongChannelName "[radio] Wrong channel name: %s\n" +#define MSGTR_RADIO_FreqParameterDetected "[radio] Radio frequency parameter detected.\n" +#define MSGTR_RADIO_DoneParsingChannels "[radio] Done parsing channels.\n" +#define MSGTR_RADIO_GetTunerFailed "[radio] Warning: ioctl get tuner failed: %s. Setting frac to %d.\n" +#define MSGTR_RADIO_NotRadioDevice "[radio] %s is no radio device!\n" +#define MSGTR_RADIO_TunerCapLowYes "[radio] tuner is low:yes frac=%d\n" +#define MSGTR_RADIO_TunerCapLowNo "[radio] tuner is low:no frac=%d\n" +#define MSGTR_RADIO_SetFreqFailed "[radio] ioctl set frequency 0x%x (%.2f) failed: %s\n" +#define MSGTR_RADIO_GetFreqFailed "[radio] ioctl get frequency failed: %s\n" +#define MSGTR_RADIO_SetMuteFailed "[radio] ioctl set mute failed: %s\n" +#define MSGTR_RADIO_QueryControlFailed "[radio] ioctl query control failed: %s\n" +#define MSGTR_RADIO_GetVolumeFailed "[radio] ioctl get volume failed: %s\n" +#define MSGTR_RADIO_SetVolumeFailed "[radio] ioctl set volume failed: %s\n" +#define MSGTR_RADIO_DroppingFrame "\n[radio] too bad - dropping audio frame (%d bytes)!\n" +#define MSGTR_RADIO_BufferEmpty "[radio] grab_audio_frame: buffer empty, waiting for %d data bytes.\n" +#define MSGTR_RADIO_AudioInitFailed "[radio] audio_in_init failed: %s\n" +#define MSGTR_RADIO_AudioBuffer "[radio] Audio capture - buffer=%d bytes (block=%d bytes).\n" +#define MSGTR_RADIO_AllocateBufferFailed "[radio] cannot allocate audio buffer (block=%d,buf=%d): %s\n" +#define MSGTR_RADIO_CurrentFreq "[radio] Current frequency: %.2f\n" +#define MSGTR_RADIO_SelectedChannel "[radio] Selected channel: %d - %s (freq: %.2f)\n" +#define MSGTR_RADIO_ChangeChannelNoChannelList "[radio] Can not change channel: no channel list given.\n" +#define MSGTR_RADIO_UnableOpenDevice "[radio] Unable to open '%s': %s\n" +#define MSGTR_RADIO_RadioDevice "[radio] Radio fd: %d, %s\n" +#define MSGTR_RADIO_InitFracFailed "[radio] init_frac failed.\n" +#define MSGTR_RADIO_WrongFreq "[radio] Wrong frequency: %.2f\n" +#define MSGTR_RADIO_UsingFreq "[radio] Using frequency: %.2f.\n" +#define MSGTR_RADIO_AudioInInitFailed "[radio] audio_in_init failed.\n" +#define MSGTR_RADIO_BufferString "[radio] %s: in buffer=%d dropped=%d\n" +#define MSGTR_RADIO_AudioInSetupFailed "[radio] audio_in_setup call failed: %s\n" +#define MSGTR_RADIO_CaptureStarting "[radio] Starting capture stuff.\n" +#define MSGTR_RADIO_ClearBufferFailed "[radio] Clearing buffer failed: %s\n" +#define MSGTR_RADIO_StreamEnableCacheFailed "[radio] Call to stream_enable_cache failed: %s\n" +#define MSGTR_RADIO_DriverUnknownStr "[radio] Unknown driver name: %s\n" +#define MSGTR_RADIO_DriverV4L2 "[radio] Using V4Lv2 radio interface.\n" +#define MSGTR_RADIO_DriverV4L "[radio] Using V4Lv1 radio interface.\n" +#define MSGTR_RADIO_DriverBSDBT848 "[radio] Using *BSD BT848 radio interface.\n" +#define MSGTR_RADIO_AvailableDrivers "[radio] Available drivers: " + +//tv.c +#define MSGTR_TV_BogusNormParameter "tv.c: norm_from_string(%s): Bogus norm parameter, setting %s.\n" +#define MSGTR_TV_NoVideoInputPresent "Error: No video input present!\n" +#define MSGTR_TV_UnknownImageFormat ""\ +"==================================================================\n"\ +" WARNING: UNTESTED OR UNKNOWN OUTPUT IMAGE FORMAT REQUESTED (0x%x)\n"\ +" This may cause buggy playback or program crash! Bug reports will\n"\ +" be ignored! You should try again with YV12 (which is the default\n"\ +" colorspace) and read the documentation!\n"\ +"==================================================================\n" +#define MSGTR_TV_SelectedNormId "Selected norm id: %d\n" +#define MSGTR_TV_SelectedNorm "Selected norm : %s\n" +#define MSGTR_TV_CannotSetNorm "Error: Cannot set norm!\n" +#define MSGTR_TV_MJP_WidthHeight " MJP: width %d height %d\n" +#define MSGTR_TV_UnableToSetWidth "Unable to set requested width: %d\n" +#define MSGTR_TV_UnableToSetHeight "Unable to set requested height: %d\n" +#define MSGTR_TV_NoTuner "Selected input hasn't got a tuner!\n" +#define MSGTR_TV_UnableFindChanlist "Unable to find selected channel list! (%s)\n" +#define MSGTR_TV_SelectedChanlist "Selected channel list: %s (including %d channels)\n" +#define MSGTR_TV_ChannelFreqParamConflict "You can't set frequency and channel simultaneously!\n" +#define MSGTR_TV_ChannelNamesDetected "TV channel names detected.\n" +#define MSGTR_TV_NoFreqForChannel "Couldn't find frequency for channel %s (%s)\n" +#define MSGTR_TV_SelectedChannel3 "Selected channel: %s - %s (freq: %.3f)\n" +#define MSGTR_TV_SelectedChannel2 "Selected channel: %s (freq: %.3f)\n" +#define MSGTR_TV_SelectedFrequency "Selected frequency: %lu (%.3f)\n" +#define MSGTR_TV_RequestedChannel "Requested channel: %s\n" +#define MSGTR_TV_UnsupportedAudioType "Audio type '%s (%x)' unsupported!\n" +#define MSGTR_TV_AudioFormat " TV audio: %d channels, %d bits, %d Hz\n" +#define MSGTR_TV_AvailableDrivers "Available drivers:\n" +#define MSGTR_TV_DriverInfo "Selected driver: %s\n name: %s\n author: %s\n comment: %s\n" +#define MSGTR_TV_NoSuchDriver "No such driver: %s\n" +#define MSGTR_TV_DriverAutoDetectionFailed "TV driver autodetection failed.\n" +#define MSGTR_TV_UnknownColorOption "Unknown color option (%d) specified!\n" +#define MSGTR_TV_CurrentFrequency "Current frequency: %lu (%.3f)\n" +#define MSGTR_TV_NoTeletext "No teletext" +#define MSGTR_TV_Bt848IoctlFailed "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n" +#define MSGTR_TV_Bt848InvalidAudioRate "tvi_bsdbt848: Invalid audio rate. Error: %s\n" +#define MSGTR_TV_Bt848ErrorOpeningBktrDev "tvi_bsdbt848: Unable to open bktr device. Error: %s\n" +#define MSGTR_TV_Bt848ErrorOpeningTunerDev "tvi_bsdbt848: Unable to open tuner device. Error: %s\n" +#define MSGTR_TV_Bt848ErrorOpeningDspDev "tvi_bsdbt848: Unable to open dsp device. Error: %s\n" +#define MSGTR_TV_Bt848ErrorConfiguringDsp "tvi_bsdbt848: Configuration of dsp failed. Error: %s\n" +#define MSGTR_TV_Bt848ErrorReadingAudio "tvi_bsdbt848: Error reading audio data. Error: %s\n" +#define MSGTR_TV_Bt848MmapFailed "tvi_bsdbt848: mmap failed. Error: %s\n" +#define MSGTR_TV_Bt848FrameBufAllocFailed "tvi_bsdbt848: Frame buffer allocation failed. Error: %s\n" +#define MSGTR_TV_Bt848ErrorSettingWidth "tvi_bsdbt848: Error setting picture width. Error: %s\n" +#define MSGTR_TV_Bt848ErrorSettingHeight "tvi_bsdbt848: Error setting picture height. Error: %s\n" +#define MSGTR_TV_Bt848UnableToStopCapture "tvi_bsdbt848: Unable to stop capture. Error: %s\n" +#define MSGTR_TV_TTSupportedLanguages "Supported Teletext languages:\n" +#define MSGTR_TV_TTSelectedLanguage "Selected default teletext language: %s\n" +#define MSGTR_TV_ScannerNotAvailableWithoutTuner "Channel scanner is not available without tuner\n" + +//tvi_dshow.c +#define MSGTR_TVI_DS_UnableConnectInputVideoDecoder "Unable to connect given input to video decoder. Error:0x%x\n" +#define MSGTR_TVI_DS_UnableConnectInputAudioDecoder "Unable to connect given input to audio decoder. Error:0x%x\n" +#define MSGTR_TVI_DS_UnableSelectVideoFormat "tvi_dshow: Unable to select video format. Error:0x%x\n" +#define MSGTR_TVI_DS_UnableSelectAudioFormat "tvi_dshow: Unable to select audio format. Error:0x%x\n" +#define MSGTR_TVI_DS_UnableGetMediaControlInterface "tvi_dshow: Unable to get IMediaControl interface. Error:0x%x\n" +#define MSGTR_TVI_DS_UnableStartGraph "tvi_dshow: Unable to start graph! Error:0x%x\n" +#define MSGTR_TVI_DS_DeviceNotFound "tvi_dshow: Device #%d not found\n" +#define MSGTR_TVI_DS_UnableGetDeviceName "tvi_dshow: Unable to get name for device #%d\n" +#define MSGTR_TVI_DS_UsingDevice "tvi_dshow: Using device #%d: %s\n" +#define MSGTR_TVI_DS_DeviceName "tvi_dshow: Device #%d: %s\n" +#define MSGTR_TVI_DS_DirectGetFreqFailed "tvi_dshow: Unable to get frequency directly. OS built-in channels table will be used.\n" +#define MSGTR_TVI_DS_DirectSetFreqFailed "tvi_dshow: Unable to set frequency directly. OS built-in channels table will be used.\n" +#define MSGTR_TVI_DS_SupportedNorms "tvi_dshow: supported norms:" +#define MSGTR_TVI_DS_AvailableVideoInputs "tvi_dshow: available video inputs:" +#define MSGTR_TVI_DS_AvailableAudioInputs "tvi_dshow: available audio inputs:" +//following phrase will be printed near the selected audio/video input +#define MSGTR_TVI_DS_InputSelected "(selected)" +#define MSGTR_TVI_DS_UnableExtractFreqTable "tvi_dshow: Unable to load frequency table from kstvtune.ax\n" +#define MSGTR_TVI_DS_WrongDeviceParam "tvi_dshow: Wrong device parameter: %s\n" +#define MSGTR_TVI_DS_WrongDeviceIndex "tvi_dshow: Wrong device index: %d\n" +#define MSGTR_TVI_DS_WrongADeviceParam "tvi_dshow: Wrong adevice parameter: %s\n" +#define MSGTR_TVI_DS_WrongADeviceIndex "tvi_dshow: Wrong adevice index: %d\n" + +#define MSGTR_TVI_DS_SamplerateNotsupported "tvi_dshow: Samplerate %d is not supported by device. Failing back to first available.\n" +#define MSGTR_TVI_DS_VideoAdjustigNotSupported "tvi_dshow: Adjusting of brightness/hue/saturation/contrast is not supported by device\n" + +#define MSGTR_TVI_DS_ChangingWidthHeightNotSupported "tvi_dshow: Changing video width/height is not supported by device.\n" +#define MSGTR_TVI_DS_SelectingInputNotSupported "tvi_dshow: Selection of capture source is not supported by device\n" +#define MSGTR_TVI_DS_FreqTableLoaded "tvi_dshow: loaded system (%s) frequency table for country id=%d (channels:%d).\n" +#define MSGTR_TVI_DS_ErrorParsingAudioFormatStruct "tvi_dshow: Unable to parse audio format structure.\n" +#define MSGTR_TVI_DS_ErrorParsingVideoFormatStruct "tvi_dshow: Unable to parse video format structure.\n" +#define MSGTR_TVI_DS_UnableSetAudioMode "tvi_dshow: Unable to set audio mode %d. Error:0x%x\n" +#define MSGTR_TVI_DS_UnsupportedMediaType "tvi_dshow: Unsupported media type passed to %s\n" +#define MSGTR_TVI_DS_UnableGetsupportedVideoFormats "tvi_dshow: Unable to get supported media formats from video pin. Error:0x%x\n" +#define MSGTR_TVI_DS_UnableGetsupportedAudioFormats "tvi_dshow: Unable to get supported media formats from audio pin. Error:0x%x Disabling audio.\n" +#define MSGTR_TVI_DS_UnableFindNearestChannel "tvi_dshow: Unable to find nearest channel in system frequency table\n" +#define MSGTR_TVI_DS_UnableToSetChannel "tvi_dshow: Unable to switch to nearest channel from system frequency table. Error:0x%x\n" +#define MSGTR_TVI_DS_UnableTerminateVPPin "tvi_dshow: Unable to terminate VideoPort pin with any filter in graph. Error:0x%x\n" +#define MSGTR_TVI_DS_UnableBuildVideoSubGraph "tvi_dshow: Unable to build video chain of capture graph. Error:0x%x\n" +#define MSGTR_TVI_DS_UnableBuildAudioSubGraph "tvi_dshow: Unable to build audio chain of capture graph. Error:0x%x\n" +#define MSGTR_TVI_DS_UnableBuildVBISubGraph "tvi_dshow: Unable to build VBI chain of capture graph. Error:0x%x\n" +#define MSGTR_TVI_DS_GraphInitFailure "tvi_dshow: Directshow graph initialization failure.\n" +#define MSGTR_TVI_DS_NoVideoCaptureDevice "tvi_dshow: Unable to find video capture device\n" +#define MSGTR_TVI_DS_NoAudioCaptureDevice "tvi_dshow: Unable to find audio capture device\n" +#define MSGTR_TVI_DS_GetActualMediatypeFailed "tvi_dshow: Unable to get actual mediatype (Error:0x%x). Assuming equal to requested.\n" + +// url.c +#define MSGTR_MPDEMUX_URL_StringAlreadyEscaped "String appears to be already escaped in url_escape %c%c1%c2\n" + +// subtitles +#define MSGTR_SUBTITLES_SubRip_UnknownFontColor "SubRip: unknown font color in subtitle: %s\n" + + +/* untranslated messages from the English master file */ + + +#endif /* MPLAYER_HELP_MP_H */ diff --git a/libavfilter/libmpcodecs/img_format.c b/libavfilter/libmpcodecs/img_format.c new file mode 100644 index 0000000000..ba870421d3 --- /dev/null +++ b/libavfilter/libmpcodecs/img_format.c @@ -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; +} diff --git a/libavfilter/libmpcodecs/img_format.h b/libavfilter/libmpcodecs/img_format.h new file mode 100644 index 0000000000..c95ed4df3c --- /dev/null +++ b/libavfilter/libmpcodecs/img_format.h @@ -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 */ diff --git a/libavfilter/libmpcodecs/libvo/fastmemcpy.h b/libavfilter/libmpcodecs/libvo/fastmemcpy.h new file mode 100644 index 0000000000..5a17d0192a --- /dev/null +++ b/libavfilter/libmpcodecs/libvo/fastmemcpy.h @@ -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 = (const 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 = (const 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 = (const 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 = (const uint8_t*)src + srcStride; + dst = (uint8_t*)dst + dstStride; + } + } + + return retval; +} + +#endif /* MPLAYER_FASTMEMCPY_H */ diff --git a/libavfilter/libmpcodecs/libvo/video_out.h b/libavfilter/libmpcodecs/libvo/video_out.h new file mode 100644 index 0000000000..77b0229991 --- /dev/null +++ b/libavfilter/libmpcodecs/libvo/video_out.h @@ -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 "../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 */ diff --git a/libavfilter/libmpcodecs/mp_image.c b/libavfilter/libmpcodecs/mp_image.c new file mode 100644 index 0000000000..bd6d33fe0a --- /dev/null +++ b/libavfilter/libmpcodecs/mp_image.c @@ -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 "img_format.h" +#include "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); +} + diff --git a/libavfilter/libmpcodecs/mp_image.h b/libavfilter/libmpcodecs/mp_image.h new file mode 100644 index 0000000000..50d3fa19a6 --- /dev/null +++ b/libavfilter/libmpcodecs/mp_image.h @@ -0,0 +1,150 @@ +/* + * 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> +#undef printf //FIXME +#undef fprintf //FIXME +#include "mp_msg.h" +#include "libavutil/avutil.h" +#include "libavutil/avassert.h" +#undef realloc +#undef malloc +#undef free +#undef rand +#undef srand +#undef printf +#undef strncpy +#define ASMALIGN(ZEROBITS) ".p2align " #ZEROBITS "\n\t" + + +//--------- 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 */ diff --git a/libavfilter/libmpcodecs/mp_msg.h b/libavfilter/libmpcodecs/mp_msg.h new file mode 100644 index 0000000000..7b6405b883 --- /dev/null +++ b/libavfilter/libmpcodecs/mp_msg.h @@ -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 */ diff --git a/libavfilter/libmpcodecs/mpbswap.h b/libavfilter/libmpcodecs/mpbswap.h new file mode 100644 index 0000000000..28f7337841 --- /dev/null +++ b/libavfilter/libmpcodecs/mpbswap.h @@ -0,0 +1,34 @@ +/* + * 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) + +#endif /* MPLAYER_MPBSWAP_H */ diff --git a/libavfilter/libmpcodecs/mpc_info.h b/libavfilter/libmpcodecs/mpc_info.h new file mode 100644 index 0000000000..8554699120 --- /dev/null +++ b/libavfilter/libmpcodecs/mpc_info.h @@ -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 */ diff --git a/libavfilter/libmpcodecs/pullup.c b/libavfilter/libmpcodecs/pullup.c new file mode 100644 index 0000000000..c1c4e0f5ca --- /dev/null +++ b/libavfilter/libmpcodecs/pullup.c @@ -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); +} diff --git a/libavfilter/libmpcodecs/pullup.h b/libavfilter/libmpcodecs/pullup.h new file mode 100644 index 0000000000..9c74fb5944 --- /dev/null +++ b/libavfilter/libmpcodecs/pullup.h @@ -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 */ diff --git a/libavfilter/libmpcodecs/vd_ffmpeg.h b/libavfilter/libmpcodecs/vd_ffmpeg.h new file mode 100644 index 0000000000..004d477330 --- /dev/null +++ b/libavfilter/libmpcodecs/vd_ffmpeg.h @@ -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 */ diff --git a/libavfilter/libmpcodecs/vf.h b/libavfilter/libmpcodecs/vf.h new file mode 100644 index 0000000000..9119b6209d --- /dev/null +++ b/libavfilter/libmpcodecs/vf.h @@ -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 */ diff --git a/libavfilter/libmpcodecs/vf_2xsai.c b/libavfilter/libmpcodecs/vf_2xsai.c new file mode 100644 index 0000000000..a19420ff98 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_2xsai.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_blackframe.c b/libavfilter/libmpcodecs/vf_blackframe.c new file mode 100644 index 0000000000..c72552c99e --- /dev/null +++ b/libavfilter/libmpcodecs/vf_blackframe.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_boxblur.c b/libavfilter/libmpcodecs/vf_boxblur.c new file mode 100644 index 0000000000..bc1ec80284 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_boxblur.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_cropdetect.c b/libavfilter/libmpcodecs/vf_cropdetect.c new file mode 100644 index 0000000000..c3de24793b --- /dev/null +++ b/libavfilter/libmpcodecs/vf_cropdetect.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_decimate.c b/libavfilter/libmpcodecs/vf_decimate.c new file mode 100644 index 0000000000..1fd7bce3d3 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_decimate.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_delogo.c b/libavfilter/libmpcodecs/vf_delogo.c new file mode 100644 index 0000000000..7a69e57863 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_delogo.c @@ -0,0 +1,252 @@ +/* + * 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" + +//===========================================================================// + +struct vf_priv_s { + unsigned int outfmt; + int xoff, yoff, lw, lh, band, show; +}; + +#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){ + int res=0; + 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) res = sscanf(args, "%d:%d:%d:%d:%d", + &vf->priv->xoff, &vf->priv->yoff, + &vf->priv->lw, &vf->priv->lh, + &vf->priv->band); + + if (res != 5) { + mp_msg(MSGT_VFILTER, MSGL_ERR, "deLogo: syntax is \"delogo=xoff:yoff:width:height:band\"\n"); + uninit(vf); + return 0; + } + + 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; +} + +const vf_info_t vf_info_delogo = { + "simple logo remover", + "delogo", + "Jindrich Makovicka, Alex Beregszaszi", + "", + vf_open, +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_denoise3d.c b/libavfilter/libmpcodecs/vf_denoise3d.c new file mode 100644 index 0000000000..a952a22287 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_denoise3d.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_detc.c b/libavfilter/libmpcodecs/vf_detc.c new file mode 100644 index 0000000000..28d20e09b7 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_detc.c @@ -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 { + const 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=av_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 +}; diff --git a/libavfilter/libmpcodecs/vf_dint.c b/libavfilter/libmpcodecs/vf_dint.c new file mode 100644 index 0000000000..ac5bf54a54 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_dint.c @@ -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; + int 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, + 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) +{ + int8_t rrow0[MAXROWSIZE]; + int8_t rrow1[MAXROWSIZE]; + int8_t rrow2[MAXROWSIZE]; + int8_t *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 +}; diff --git a/libavfilter/libmpcodecs/vf_divtc.c b/libavfilter/libmpcodecs/vf_divtc.c new file mode 100644 index 0000000000..4c171d1728 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_divtc.c @@ -0,0 +1,721 @@ +/* + * 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; + int8_t *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; + int8_t *pbuf; + int8_t 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; + const char *filename="framediff.log"; + char *ap, *q, *a; + + if(args && !(args=av_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 + }; diff --git a/libavfilter/libmpcodecs/vf_down3dright.c b/libavfilter/libmpcodecs/vf_down3dright.c new file mode 100644 index 0000000000..4dba19a2f0 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_down3dright.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_dsize.c b/libavfilter/libmpcodecs/vf_dsize.c new file mode 100644 index 0000000000..7772b3732d --- /dev/null +++ b/libavfilter/libmpcodecs/vf_dsize.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_eq.c b/libavfilter/libmpcodecs/vf_eq.c new file mode 100644 index 0000000000..df4e851363 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_eq.c @@ -0,0 +1,240 @@ +/* + * 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" + +static struct vf_priv_s { + unsigned char *buf; + int brightness; + int contrast; +}; + +#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; + + 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->brightness, &vf->priv->contrast); + + process = process_C; +#if HAVE_MMX + if(gCpuCaps.hasMMX) process = process_MMX; +#endif + + return 1; +} + +const vf_info_t vf_info_eq = { + "soft video equalizer", + "eq", + "Richard Felker", + "", + vf_open, +}; diff --git a/libavfilter/libmpcodecs/vf_eq2.c b/libavfilter/libmpcodecs/vf_eq2.c new file mode 100644 index 0000000000..fe4a89fb13 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_eq2.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_field.c b/libavfilter/libmpcodecs/vf_field.c new file mode 100644 index 0000000000..fcf24be0bc --- /dev/null +++ b/libavfilter/libmpcodecs/vf_field.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_fil.c b/libavfilter/libmpcodecs/vf_fil.c new file mode 100644 index 0000000000..7df7eb0af7 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_fil.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_filmdint.c b/libavfilter/libmpcodecs/vf_filmdint.c new file mode 100644 index 0000000000..70db246e1d --- /dev/null +++ b/libavfilter/libmpcodecs/vf_filmdint.c @@ -0,0 +1,1461 @@ +/* + * 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 <sys/time.h> + +#include "config.h" +#include "mp_msg.h" +#include "cpudetect.h" + +#include "img_format.h" +#include "mp_image.h" +#include "vd.h" +#include "vf.h" +#include "cmmx.h" + +#include "libvo/fastmemcpy.h" + +#define NUM_STORED 4 + +enum pu_field_type_t { + PU_1ST_OF_3, + PU_2ND_OF_3, + PU_3RD_OF_3, + PU_1ST_OF_2, + PU_2ND_OF_2, + PU_INTERLACED +}; + +struct metrics { + /* This struct maps to a packed word 64-bit MMX register */ + unsigned short int even; + unsigned short int odd; + unsigned short int noise; + unsigned short int temp; +} __attribute__ ((aligned (8))); + +struct frame_stats { + struct metrics tiny, low, high, bigger, twox, max; + struct { unsigned int even, odd, noise, temp; } sad; + unsigned short interlaced_high; + unsigned short interlaced_low; + unsigned short num_blocks; +}; + +struct vf_priv_s { + unsigned long inframes; + unsigned long outframes; + enum pu_field_type_t prev_type; + unsigned swapped, chroma_swapped; + unsigned luma_only; + unsigned verbose; + unsigned fast; + unsigned long w, h, cw, ch, stride, chroma_stride, nplanes; + unsigned long sad_thres; + unsigned long dint_thres; + unsigned char *memory_allocated; + unsigned char *planes[2*NUM_STORED][4]; + unsigned char **old_planes; + unsigned long static_idx; + unsigned long temp_idx; + unsigned long crop_x, crop_y, crop_cx, crop_cy; + unsigned long export_count, merge_count; + unsigned long num_breaks; + unsigned long num_copies; + long in_inc, out_dec, iosync; + long num_fields; + long prev_fields; + long notout; + long mmx2; + unsigned small_bytes[2]; + unsigned mmx_temp[2]; + struct frame_stats stats[2]; + struct metrics thres; + char chflag; + double diff_time, merge_time, decode_time, vo_time, filter_time; +}; + +#define PPZ { 2000, 2000, 0, 2000 } +#define PPR { 2000, 2000, 0, 2000 } +static const struct frame_stats ppzs = {PPZ,PPZ,PPZ,PPZ,PPZ,PPZ,PPZ,0,0,9999}; +static const struct frame_stats pprs = {PPR,PPR,PPR,PPR,PPR,PPR,PPR,0,0,9999}; + +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif +#ifndef MAX +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +#define PDIFFUB(X,Y,T) "movq " #X "," #T "\n\t" \ + "psubusb " #Y "," #T "\n\t" \ + "psubusb " #X "," #Y "\n\t" \ + "paddusb " #Y "," #T "\n\t" + +#define PDIFFUBT(X,Y,T) "movq " #X "," #T "\n\t" \ + "psubusb " #Y "," #T "\n\t" \ + "psubusb " #X "," #Y "\n\t" \ + "paddusb " #T "," #Y "\n\t" + +#define PSUMBW(X,T,Z) "movq " #X "," #T "\n\t" \ + "punpcklbw " #Z "," #X "\n\t" \ + "punpckhbw " #Z "," #T "\n\t" \ + "paddw " #T "," #X "\n\t" \ + "movq " #X "," #T "\n\t" \ + "psllq $32, " #T "\n\t" \ + "paddw " #T "," #X "\n\t" \ + "movq " #X "," #T "\n\t" \ + "psllq $16, " #T "\n\t" \ + "paddw " #T "," #X "\n\t" \ + "psrlq $48, " #X "\n\t" + +#define PSADBW(X,Y,T,Z) PDIFFUBT(X,Y,T) PSUMBW(Y,T,Z) + +#define PMAXUB(X,Y) "psubusb " #X "," #Y "\n\tpaddusb " #X "," #Y "\n\t" +#define PMAXUW(X,Y) "psubusw " #X "," #Y "\n\tpaddusw " #X "," #Y "\n\t" +#define PMINUBT(X,Y,T) "movq " #Y "," #T "\n\t" \ + "psubusb " #X "," #T "\n\t" \ + "psubusb " #T "," #Y "\n\t" +#define PAVGB(X,Y) "pavgusb " #X "," #Y "\n\t" + +static inline void +get_metrics_c(unsigned char *a, unsigned char *b, int as, int bs, int lines, + struct metrics *m) +{ + a -= as; + b -= bs; + do { + cmmx_t old_po = *(cmmx_t*)(a ); + cmmx_t po = *(cmmx_t*)(b ); + cmmx_t e = *(cmmx_t*)(b + bs); + cmmx_t old_o = *(cmmx_t*)(a + 2*as); + cmmx_t o = *(cmmx_t*)(b + 2*bs); + cmmx_t ne = *(cmmx_t*)(b + 3*bs); + cmmx_t old_no = *(cmmx_t*)(a + 4*as); + cmmx_t no = *(cmmx_t*)(b + 4*bs); + + cmmx_t qup_old_odd = p31avgb(old_o, old_po); + cmmx_t qup_odd = p31avgb( o, po); + cmmx_t qdown_old_odd = p31avgb(old_o, old_no); + cmmx_t qdown_odd = p31avgb( o, no); + + cmmx_t qup_even = p31avgb(ne, e); + cmmx_t qdown_even = p31avgb(e, ne); + + cmmx_t temp_up_diff = pdiffub(qdown_even, qup_old_odd); + cmmx_t noise_up_diff = pdiffub(qdown_even, qup_odd); + cmmx_t temp_down_diff = pdiffub(qup_even, qdown_old_odd); + cmmx_t noise_down_diff = pdiffub(qup_even, qdown_odd); + + cmmx_t odd_diff = pdiffub(o, old_o); + m->odd += psumbw(odd_diff); + m->even += psadbw(e, *(cmmx_t*)(a+as)); + + temp_up_diff = pminub(temp_up_diff, temp_down_diff); + temp_up_diff = pminub(temp_up_diff, odd_diff); + m->temp += psumbw(temp_up_diff); + noise_up_diff = pminub(noise_up_diff, odd_diff); + noise_up_diff = pminub(noise_up_diff, noise_down_diff); + + m->noise += psumbw(noise_up_diff); + a += 2*as; + b += 2*bs; + } while (--lines); +} + +static inline void +get_metrics_fast_c(unsigned char *a, unsigned char *b, int as, int bs, + int lines, struct metrics *m) +{ + a -= as; + b -= bs; + do { + cmmx_t old_po = (*(cmmx_t*)(a ) >> 1) & ~SIGN_BITS; + cmmx_t po = (*(cmmx_t*)(b ) >> 1) & ~SIGN_BITS; + cmmx_t old_e = (*(cmmx_t*)(a + as) >> 1) & ~SIGN_BITS; + cmmx_t e = (*(cmmx_t*)(b + bs) >> 1) & ~SIGN_BITS; + cmmx_t old_o = (*(cmmx_t*)(a + 2*as) >> 1) & ~SIGN_BITS; + cmmx_t o = (*(cmmx_t*)(b + 2*bs) >> 1) & ~SIGN_BITS; + cmmx_t ne = (*(cmmx_t*)(b + 3*bs) >> 1) & ~SIGN_BITS; + cmmx_t old_no = (*(cmmx_t*)(a + 4*as) >> 1) & ~SIGN_BITS; + cmmx_t no = (*(cmmx_t*)(b + 4*bs) >> 1) & ~SIGN_BITS; + + cmmx_t qup_old_odd = p31avgb_s(old_o, old_po); + cmmx_t qup_odd = p31avgb_s( o, po); + cmmx_t qdown_old_odd = p31avgb_s(old_o, old_no); + cmmx_t qdown_odd = p31avgb_s( o, no); + + cmmx_t qup_even = p31avgb_s(ne, e); + cmmx_t qdown_even = p31avgb_s(e, ne); + + cmmx_t temp_up_diff = pdiffub_s(qdown_even, qup_old_odd); + cmmx_t noise_up_diff = pdiffub_s(qdown_even, qup_odd); + cmmx_t temp_down_diff = pdiffub_s(qup_even, qdown_old_odd); + cmmx_t noise_down_diff = pdiffub_s(qup_even, qdown_odd); + + cmmx_t odd_diff = pdiffub_s(o, old_o); + m->odd += psumbw_s(odd_diff) << 1; + m->even += psadbw_s(e, old_e) << 1; + + temp_up_diff = pminub_s(temp_up_diff, temp_down_diff); + temp_up_diff = pminub_s(temp_up_diff, odd_diff); + m->temp += psumbw_s(temp_up_diff) << 1; + noise_up_diff = pminub_s(noise_up_diff, odd_diff); + noise_up_diff = pminub_s(noise_up_diff, noise_down_diff); + + m->noise += psumbw_s(noise_up_diff) << 1; + a += 2*as; + b += 2*bs; + } while (--lines); +} + +static inline void +get_metrics_faster_c(unsigned char *a, unsigned char *b, int as, int bs, + int lines, struct metrics *m) +{ + a -= as; + b -= bs; + do { + cmmx_t old_po = (*(cmmx_t*)(a )>>1) & ~SIGN_BITS; + cmmx_t po = (*(cmmx_t*)(b )>>1) & ~SIGN_BITS; + cmmx_t old_e = (*(cmmx_t*)(a + as)>>1) & ~SIGN_BITS; + cmmx_t e = (*(cmmx_t*)(b + bs)>>1) & ~SIGN_BITS; + cmmx_t old_o = (*(cmmx_t*)(a + 2*as)>>1) & ~SIGN_BITS; + cmmx_t o = (*(cmmx_t*)(b + 2*bs)>>1) & ~SIGN_BITS; + cmmx_t ne = (*(cmmx_t*)(b + 3*bs)>>1) & ~SIGN_BITS; + + cmmx_t down_even = p31avgb_s(e, ne); + cmmx_t up_odd = p31avgb_s(o, po); + cmmx_t up_old_odd = p31avgb_s(old_o, old_po); + + cmmx_t odd_diff = pdiffub_s(o, old_o); + cmmx_t temp_diff = pdiffub_s(down_even, up_old_odd); + cmmx_t noise_diff = pdiffub_s(down_even, up_odd); + + m->even += psadbw_s(e, old_e) << 1; + m->odd += psumbw_s(odd_diff) << 1; + + temp_diff = pminub_s(temp_diff, odd_diff); + noise_diff = pminub_s(noise_diff, odd_diff); + + m->noise += psumbw_s(noise_diff) << 1; + m->temp += psumbw_s(temp_diff) << 1; + a += 2*as; + b += 2*bs; + } while (--lines); + +} + +static inline void +get_block_stats(struct metrics *m, struct vf_priv_s *p, struct frame_stats *s) +{ + unsigned two_e = m->even + MAX(m->even , p->thres.even ); + unsigned two_o = m->odd + MAX(m->odd , p->thres.odd ); + unsigned two_n = m->noise + MAX(m->noise, p->thres.noise); + unsigned two_t = m->temp + MAX(m->temp , p->thres.temp ); + + unsigned e_big = m->even >= (m->odd + two_o + 1)/2; + unsigned o_big = m->odd >= (m->even + two_e + 1)/2; + unsigned n_big = m->noise >= (m->temp + two_t + 1)/2; + unsigned t_big = m->temp >= (m->noise + two_n + 1)/2; + + unsigned e2x = m->even >= two_o; + unsigned o2x = m->odd >= two_e; + unsigned n2x = m->noise >= two_t; + unsigned t2x = m->temp >= two_n; + + unsigned ntiny_e = m->even > p->thres.even ; + unsigned ntiny_o = m->odd > p->thres.odd ; + unsigned ntiny_n = m->noise > p->thres.noise; + unsigned ntiny_t = m->temp > p->thres.temp ; + + unsigned nlow_e = m->even > 2*p->thres.even ; + unsigned nlow_o = m->odd > 2*p->thres.odd ; + unsigned nlow_n = m->noise > 2*p->thres.noise; + unsigned nlow_t = m->temp > 2*p->thres.temp ; + + unsigned high_e = m->even > 4*p->thres.even ; + unsigned high_o = m->odd > 4*p->thres.odd ; + unsigned high_n = m->noise > 4*p->thres.noise; + unsigned high_t = m->temp > 4*p->thres.temp ; + + unsigned low_il = !n_big && !t_big && ntiny_n && ntiny_t; + unsigned high_il = !n_big && !t_big && nlow_n && nlow_t; + + if (low_il | high_il) { + s->interlaced_low += low_il; + s->interlaced_high += high_il; + } else { + s->tiny.even += ntiny_e; + s->tiny.odd += ntiny_o; + s->tiny.noise += ntiny_n; + s->tiny.temp += ntiny_t; + + s->low .even += nlow_e ; + s->low .odd += nlow_o ; + s->low .noise += nlow_n ; + s->low .temp += nlow_t ; + + s->high.even += high_e ; + s->high.odd += high_o ; + s->high.noise += high_n ; + s->high.temp += high_t ; + + if (m->even >= p->sad_thres) s->sad.even += m->even ; + if (m->odd >= p->sad_thres) s->sad.odd += m->odd ; + if (m->noise >= p->sad_thres) s->sad.noise += m->noise; + if (m->temp >= p->sad_thres) s->sad.temp += m->temp ; + } + s->num_blocks++; + s->max.even = MAX(s->max.even , m->even ); + s->max.odd = MAX(s->max.odd , m->odd ); + s->max.noise = MAX(s->max.noise, m->noise); + s->max.temp = MAX(s->max.temp , m->temp ); + + s->bigger.even += e_big ; + s->bigger.odd += o_big ; + s->bigger.noise += n_big ; + s->bigger.temp += t_big ; + + s->twox.even += e2x ; + s->twox.odd += o2x ; + s->twox.noise += n2x ; + s->twox.temp += t2x ; + +} + +static inline struct metrics +block_metrics_c(unsigned char *a, unsigned char *b, int as, int bs, + int lines, struct vf_priv_s *p, struct frame_stats *s) +{ + struct metrics tm; + tm.even = tm.odd = tm.noise = tm.temp = 0; + get_metrics_c(a, b, as, bs, lines, &tm); + if (sizeof(cmmx_t) < 8) + get_metrics_c(a+4, b+4, as, bs, lines, &tm); + get_block_stats(&tm, p, s); + return tm; +} + +static inline struct metrics +block_metrics_fast_c(unsigned char *a, unsigned char *b, int as, int bs, + int lines, struct vf_priv_s *p, struct frame_stats *s) +{ + struct metrics tm; + tm.even = tm.odd = tm.noise = tm.temp = 0; + get_metrics_fast_c(a, b, as, bs, lines, &tm); + if (sizeof(cmmx_t) < 8) + get_metrics_fast_c(a+4, b+4, as, bs, lines, &tm); + get_block_stats(&tm, p, s); + return tm; +} + +static inline struct metrics +block_metrics_faster_c(unsigned char *a, unsigned char *b, int as, int bs, + int lines, struct vf_priv_s *p, struct frame_stats *s) +{ + struct metrics tm; + tm.even = tm.odd = tm.noise = tm.temp = 0; + get_metrics_faster_c(a, b, as, bs, lines, &tm); + if (sizeof(cmmx_t) < 8) + get_metrics_faster_c(a+4, b+4, as, bs, lines, &tm); + get_block_stats(&tm, p, s); + return tm; +} + +#define MEQ(X,Y) ((X).even == (Y).even && (X).odd == (Y).odd && (X).temp == (Y).temp && (X).noise == (Y).noise) + +#define BLOCK_METRICS_TEMPLATE() \ + __asm__ volatile("pxor %mm7, %mm7\n\t" /* The result is colleted in mm7 */ \ + "pxor %mm6, %mm6\n\t" /* Temp to stay at 0 */ \ + ); \ + a -= as; \ + b -= bs; \ + do { \ + __asm__ volatile( \ + "movq (%0,%2), %%mm0\n\t" \ + "movq (%1,%3), %%mm1\n\t" /* mm1 = even */ \ + PSADBW(%%mm1, %%mm0, %%mm4, %%mm6) \ + "paddusw %%mm0, %%mm7\n\t" /* even diff */ \ + "movq (%0,%2,2), %%mm0\n\t" /* mm0 = old odd */ \ + "movq (%1,%3,2), %%mm2\n\t" /* mm2 = odd */ \ + "movq (%0), %%mm3\n\t" \ + "psubusb %4, %%mm3\n\t" \ + PAVGB(%%mm0, %%mm3) \ + PAVGB(%%mm0, %%mm3) /* mm3 = qup old odd */ \ + "movq %%mm0, %%mm5\n\t" \ + PSADBW(%%mm2, %%mm0, %%mm4, %%mm6) \ + "psllq $16, %%mm0\n\t" \ + "paddusw %%mm0, %%mm7\n\t" \ + "movq (%1), %%mm4\n\t" \ + "lea (%0,%2,2), %0\n\t" \ + "lea (%1,%3,2), %1\n\t" \ + "psubusb %4, %%mm4\n\t" \ + PAVGB(%%mm2, %%mm4) \ + PAVGB(%%mm2, %%mm4) /* mm4 = qup odd */ \ + PDIFFUBT(%%mm5, %%mm2, %%mm0) /* mm2 =abs(oldodd-odd) */ \ + "movq (%1,%3), %%mm5\n\t" \ + "psubusb %4, %%mm5\n\t" \ + PAVGB(%%mm1, %%mm5) \ + PAVGB(%%mm5, %%mm1) /* mm1 = qdown even */ \ + PAVGB((%1,%3), %%mm5) /* mm5 = qup next even */ \ + PDIFFUBT(%%mm1, %%mm3, %%mm0) /* mm3 = abs(qupoldo-qde) */ \ + PDIFFUBT(%%mm1, %%mm4, %%mm0) /* mm4 = abs(qupodd-qde) */ \ + PMINUBT(%%mm2, %%mm3, %%mm0) /* limit temp to odd diff */ \ + PMINUBT(%%mm2, %%mm4, %%mm0) /* limit noise to odd diff */ \ + "movq (%1,%3,2), %%mm2\n\t" \ + "psubusb %4, %%mm2\n\t" \ + PAVGB((%1), %%mm2) \ + PAVGB((%1), %%mm2) /* mm2 = qdown odd */ \ + "movq (%0,%2,2), %%mm1\n\t" \ + "psubusb %4, %%mm1\n\t" \ + PAVGB((%0), %%mm1) \ + PAVGB((%0), %%mm1) /* mm1 = qdown old odd */ \ + PDIFFUBT(%%mm5, %%mm2, %%mm0) /* mm2 = abs(qdo-qune) */ \ + PDIFFUBT(%%mm5, %%mm1, %%mm0) /* mm1 = abs(qdoo-qune) */ \ + PMINUBT(%%mm4, %%mm2, %%mm0) /* current */ \ + PMINUBT(%%mm3, %%mm1, %%mm0) /* old */ \ + PSUMBW(%%mm2, %%mm0, %%mm6) \ + PSUMBW(%%mm1, %%mm0, %%mm6) \ + "psllq $32, %%mm2\n\t" \ + "psllq $48, %%mm1\n\t" \ + "paddusw %%mm2, %%mm7\n\t" \ + "paddusw %%mm1, %%mm7\n\t" \ + : "=r" (a), "=r" (b) \ + : "r"((x86_reg)as), "r"((x86_reg)bs), "m" (ones), "0"(a), "1"(b), "X"(*a), "X"(*b) \ + ); \ + } while (--lines); + +static inline struct metrics +block_metrics_3dnow(unsigned char *a, unsigned char *b, int as, int bs, + int lines, struct vf_priv_s *p, struct frame_stats *s) +{ + struct metrics tm; +#if !HAVE_AMD3DNOW + mp_msg(MSGT_VFILTER, MSGL_FATAL, "block_metrics_3dnow: internal error\n"); +#else + static const unsigned long long ones = 0x0101010101010101ull; + + BLOCK_METRICS_TEMPLATE(); + __asm__ volatile("movq %%mm7, %0\n\temms" : "=m" (tm)); + get_block_stats(&tm, p, s); +#endif + return tm; +} + +#undef PSUMBW +#undef PSADBW +#undef PMAXUB +#undef PMINUBT +#undef PAVGB + +#define PSUMBW(X,T,Z) "psadbw " #Z "," #X "\n\t" +#define PSADBW(X,Y,T,Z) "psadbw " #X "," #Y "\n\t" +#define PMAXUB(X,Y) "pmaxub " #X "," #Y "\n\t" +#define PMINUBT(X,Y,T) "pminub " #X "," #Y "\n\t" +#define PAVGB(X,Y) "pavgb " #X "," #Y "\n\t" + +static inline struct metrics +block_metrics_mmx2(unsigned char *a, unsigned char *b, int as, int bs, + int lines, struct vf_priv_s *p, struct frame_stats *s) +{ + struct metrics tm; +#if !HAVE_MMX + mp_msg(MSGT_VFILTER, MSGL_FATAL, "block_metrics_mmx2: internal error\n"); +#else + static const unsigned long long ones = 0x0101010101010101ull; + x86_reg interlaced; + x86_reg prefetch_line = (((long)a>>3) & 7) + 10; +#ifdef DEBUG + struct frame_stats ts = *s; +#endif + __asm__ volatile("prefetcht0 (%0,%2)\n\t" + "prefetcht0 (%1,%3)\n\t" : + : "r" (a), "r" (b), + "r" (prefetch_line * as), "r" (prefetch_line * bs)); + + BLOCK_METRICS_TEMPLATE(); + + s->num_blocks++; + __asm__ volatile( + "movq %3, %%mm0\n\t" + "movq %%mm7, %%mm1\n\t" + "psubusw %%mm0, %%mm1\n\t" + "movq %%mm1, %%mm2\n\t" + "paddusw %%mm0, %%mm2\n\t" + "paddusw %%mm7, %%mm2\n\t" + "pshufw $0xb1, %%mm2, %%mm3\n\t" + "pavgw %%mm7, %%mm2\n\t" + "pshufw $0xb1, %%mm2, %%mm2\n\t" + "psubusw %%mm7, %%mm2\n\t" + "pcmpeqw %%mm6, %%mm2\n\t" /* 1 if >= 1.5x */ + "psubusw %%mm7, %%mm3\n\t" + "pcmpeqw %%mm6, %%mm3\n\t" /* 1 if >= 2x */ + "movq %1, %%mm4\n\t" + "movq %2, %%mm5\n\t" + "psubw %%mm2, %%mm4\n\t" + "psubw %%mm3, %%mm5\n\t" + "movq %%mm4, %1\n\t" + "movq %%mm5, %2\n\t" + "pxor %%mm4, %%mm4\n\t" + "pcmpeqw %%mm1, %%mm4\n\t" /* 1 if <= t */ + "psubusw %%mm0, %%mm1\n\t" + "pxor %%mm5, %%mm5\n\t" + "pcmpeqw %%mm1, %%mm5\n\t" /* 1 if <= 2t */ + "psubusw %%mm0, %%mm1\n\t" + "psubusw %%mm0, %%mm1\n\t" + "pcmpeqw %%mm6, %%mm1\n\t" /* 1 if <= 4t */ + "pshufw $0xb1, %%mm2, %%mm0\n\t" + "por %%mm2, %%mm0\n\t" /* 1 if not close */ + "punpckhdq %%mm0, %%mm0\n\t" + "movq %%mm4, %%mm2\n\t" /* tttt */ + "punpckhdq %%mm5, %%mm2\n\t" /* ttll */ + "por %%mm2, %%mm0\n\t" + "pcmpeqd %%mm6, %%mm0\n\t" /* close && big */ + "psrlq $16, %%mm0\n\t" + "psrlw $15, %%mm0\n\t" + "movd %%mm0, %0\n\t" + : "=r" (interlaced), "=m" (s->bigger), "=m" (s->twox) + : "m" (p->thres) + ); + + if (interlaced) { + s->interlaced_high += interlaced >> 16; + s->interlaced_low += interlaced; + } else { + __asm__ volatile( + "pcmpeqw %%mm0, %%mm0\n\t" /* -1 */ + "psubw %%mm0, %%mm4\n\t" + "psubw %%mm0, %%mm5\n\t" + "psubw %%mm0, %%mm1\n\t" + "paddw %0, %%mm4\n\t" + "paddw %1, %%mm5\n\t" + "paddw %2, %%mm1\n\t" + "movq %%mm4, %0\n\t" + "movq %%mm5, %1\n\t" + "movq %%mm1, %2\n\t" + : "=m" (s->tiny), "=m" (s->low), "=m" (s->high) + ); + + __asm__ volatile( + "pshufw $0, %2, %%mm0\n\t" + "psubusw %%mm7, %%mm0\n\t" + "pcmpeqw %%mm6, %%mm0\n\t" /* 0 if below sad_thres */ + "pand %%mm7, %%mm0\n\t" + "movq %%mm0, %%mm1\n\t" + "punpcklwd %%mm6, %%mm0\n\t" /* sad even, odd */ + "punpckhwd %%mm6, %%mm1\n\t" /* sad noise, temp */ + "paddd %0, %%mm0\n\t" + "paddd %1, %%mm1\n\t" + "movq %%mm0, %0\n\t" + "movq %%mm1, %1\n\t" + : "=m" (s->sad.even), "=m" (s->sad.noise) + : "m" (p->sad_thres) + ); + } + + __asm__ volatile( + "movq %%mm7, (%1)\n\t" + PMAXUW((%0), %%mm7) + "movq %%mm7, (%0)\n\t" + "emms" + : : "r" (&s->max), "r" (&tm), "X" (s->max) + : "memory" + ); +#ifdef DEBUG + if (1) { + struct metrics cm; + a -= 7*as; + b -= 7*bs; + cm = block_metrics_c(a, b, as, bs, 4, p, &ts); + if (!MEQ(tm, cm)) + mp_msg(MSGT_VFILTER, MSGL_WARN, "Bad metrics\n"); + if (s) { +# define CHECK(X) if (!MEQ(s->X, ts.X)) \ + mp_msg(MSGT_VFILTER, MSGL_WARN, "Bad " #X "\n"); + CHECK(tiny); + CHECK(low); + CHECK(high); + CHECK(sad); + CHECK(max); + } + } +#endif +#endif + return tm; +} + +static inline int +dint_copy_line_mmx2(unsigned char *dst, unsigned char *a, long bos, + long cos, int ds, int ss, int w, int t) +{ +#if !HAVE_MMX + mp_msg(MSGT_VFILTER, MSGL_FATAL, "dint_copy_line_mmx2: internal error\n"); + return 0; +#else + unsigned long len = (w+7) >> 3; + int ret; + __asm__ volatile ( + "pxor %%mm6, %%mm6 \n\t" /* deinterlaced pixel counter */ + "movd %0, %%mm7 \n\t" + "punpcklbw %%mm7, %%mm7 \n\t" + "punpcklwd %%mm7, %%mm7 \n\t" + "punpckldq %%mm7, %%mm7 \n\t" /* mm7 = threshold */ + : /* no output */ + : "rm" (t) + ); + do { + __asm__ volatile ( + "movq (%0), %%mm0\n\t" + "movq (%0,%3,2), %%mm1\n\t" + "movq %%mm0, (%2)\n\t" + "pmaxub %%mm1, %%mm0\n\t" + "pavgb (%0), %%mm1\n\t" + "psubusb %%mm1, %%mm0\n\t" + "paddusb %%mm7, %%mm0\n\t" /* mm0 = max-avg+thr */ + "movq (%0,%1), %%mm2\n\t" + "movq (%0,%5), %%mm3\n\t" + "movq %%mm2, %%mm4\n\t" + PDIFFUBT(%%mm1, %%mm2, %%mm5) + PDIFFUBT(%%mm1, %%mm3, %%mm5) + "pminub %%mm2, %%mm3\n\t" + "pcmpeqb %%mm3, %%mm2\n\t" /* b = min */ + "pand %%mm2, %%mm4\n\t" + "pandn (%0,%5), %%mm2\n\t" + "por %%mm4, %%mm2\n\t" + "pminub %%mm0, %%mm3\n\t" + "pcmpeqb %%mm0, %%mm3\n\t" /* set to 1s if >= threshold */ + "psubb %%mm3, %%mm6\n\t" /* count pixels above thr. */ + "pand %%mm3, %%mm1 \n\t" + "pandn %%mm2, %%mm3 \n\t" + "por %%mm3, %%mm1 \n\t" /* avg if >= threshold */ + "movq %%mm1, (%2,%4) \n\t" + : /* no output */ + : "r" (a), "r" ((x86_reg)bos), "r" ((x86_reg)dst), "r" ((x86_reg)ss), "r" ((x86_reg)ds), "r" ((x86_reg)cos) + ); + a += 8; + dst += 8; + } while (--len); + + __asm__ volatile ("pxor %%mm7, %%mm7 \n\t" + "psadbw %%mm6, %%mm7 \n\t" + "movd %%mm7, %0 \n\t" + "emms \n\t" + : "=r" (ret) + ); + return ret; +#endif +} + +static inline int +dint_copy_line(unsigned char *dst, unsigned char *a, long bos, + long cos, int ds, int ss, int w, int t) +{ + unsigned long len = ((unsigned long)w+sizeof(cmmx_t)-1) / sizeof(cmmx_t); + cmmx_t dint_count = 0; + cmmx_t thr; + t |= t << 8; + thr = t | (t << 16); + if (sizeof(cmmx_t) > 4) + thr |= thr << (sizeof(cmmx_t)*4); + do { + cmmx_t e = *(cmmx_t*)a; + cmmx_t ne = *(cmmx_t*)(a+2*ss); + cmmx_t o = *(cmmx_t*)(a+bos); + cmmx_t oo = *(cmmx_t*)(a+cos); + cmmx_t maxe = pmaxub(e, ne); + cmmx_t avge = pavgb(e, ne); + cmmx_t max_diff = maxe - avge + thr; /* 0<=max-avg<128, thr<128 */ + cmmx_t diffo = pdiffub(avge, o); + cmmx_t diffoo = pdiffub(avge, oo); + cmmx_t diffcmp = pcmpgtub(diffo, diffoo); + cmmx_t bo = ((oo ^ o) & diffcmp) ^ o; + cmmx_t diffbo = ((diffoo ^ diffo) & diffcmp) ^ diffo; + cmmx_t above_thr = ~pcmpgtub(max_diff, diffbo); + cmmx_t bo_or_avg = ((avge ^ bo) & above_thr) ^ bo; + dint_count += above_thr & ONE_BYTES; + *(cmmx_t*)(dst) = e; + *(cmmx_t*)(dst+ds) = bo_or_avg; + a += sizeof(cmmx_t); + dst += sizeof(cmmx_t); + } while (--len); + return psumbw(dint_count); +} + +static int +dint_copy_plane(unsigned char *d, unsigned char *a, unsigned char *b, + unsigned char *c, unsigned long w, unsigned long h, + unsigned long ds, unsigned long ss, unsigned long threshold, + long field, long mmx2) +{ + unsigned long ret = 0; + long bos = b - a; + long cos = c - a; + if (field) { + fast_memcpy(d, b, w); + h--; + d += ds; + a += ss; + } + bos += ss; + cos += ss; + while (h > 2) { + if (threshold >= 128) { + fast_memcpy(d, a, w); + fast_memcpy(d+ds, a+bos, w); + } else if (mmx2 == 1) { + ret += dint_copy_line_mmx2(d, a, bos, cos, ds, ss, w, threshold); + } else + ret += dint_copy_line(d, a, bos, cos, ds, ss, w, threshold); + h -= 2; + d += 2*ds; + a += 2*ss; + } + fast_memcpy(d, a, w); + if (h == 2) + fast_memcpy(d+ds, a+bos, w); + return ret; +} + +static void +copy_merge_fields(struct vf_priv_s *p, mp_image_t *dmpi, + unsigned char **old, unsigned char **new, unsigned long show) +{ + unsigned long threshold = 256; + unsigned long field = p->swapped; + unsigned long dint_pixels = 0; + unsigned char **other = old; + if (show >= 12 || !(show & 3)) + show >>= 2, other = new, new = old; + if (show <= 2) { /* Single field: de-interlace */ + threshold = p->dint_thres; + field ^= show & 1; + old = new; + } else if (show == 3) + old = new; + else + field ^= 1; + dint_pixels +=dint_copy_plane(dmpi->planes[0], old[0], new[0], + other[0], p->w, p->h, dmpi->stride[0], + p->stride, threshold, field, p->mmx2); + if (dmpi->flags & MP_IMGFLAG_PLANAR) { + if (p->luma_only) + old = new, other = new; + else + threshold = threshold/2 + 1; + field ^= p->chroma_swapped; + dint_copy_plane(dmpi->planes[1], old[1], new[1], + other[1], p->cw, p->ch, dmpi->stride[1], + p->chroma_stride, threshold, field, p->mmx2); + dint_copy_plane(dmpi->planes[2], old[2], new[2], + other[2], p->cw, p->ch, dmpi->stride[2], + p->chroma_stride, threshold, field, p->mmx2); + } + if (dint_pixels > 0 && p->verbose) + mp_msg(MSGT_VFILTER,MSGL_INFO,"Deinterlaced %lu pixels\n",dint_pixels); +} + +static void diff_planes(struct vf_priv_s *p, struct frame_stats *s, + unsigned char *of, unsigned char *nf, + int w, int h, int os, int ns, int swapped) +{ + int i, y; + int align = -(long)nf & 7; + of += align; + nf += align; + w -= align; + if (swapped) + of -= os, nf -= ns; + i = (h*3 >> 7) & ~1; + of += i*os + 8; + nf += i*ns + 8; + h -= i; + w -= 16; + + memset(s, 0, sizeof(*s)); + + for (y = (h-8) >> 3; y; y--) { + if (p->mmx2 == 1) { + for (i = 0; i < w; i += 8) + block_metrics_mmx2(of+i, nf+i, os, ns, 4, p, s); + } else if (p->mmx2 == 2) { + for (i = 0; i < w; i += 8) + block_metrics_3dnow(of+i, nf+i, os, ns, 4, p, s); + } else if (p->fast > 3) { + for (i = 0; i < w; i += 8) + block_metrics_faster_c(of+i, nf+i, os, ns, 4, p, s); + } else if (p->fast > 1) { + for (i = 0; i < w; i += 8) + block_metrics_fast_c(of+i, nf+i, os, ns, 4, p, s); + } else { + for (i = 0; i < w; i += 8) + block_metrics_c(of+i, nf+i, os, ns, 4, p, s); + } + of += 8*os; + nf += 8*ns; + } +} + +#define METRICS(X) (X).even, (X).odd, (X).noise, (X).temp + +static void diff_fields(struct vf_priv_s *p, struct frame_stats *s, + unsigned char **old, unsigned char **new) +{ + diff_planes(p, s, old[0], new[0], p->w, p->h, + p->stride, p->stride, p->swapped); + s->sad.even = (s->sad.even * 16ul) / s->num_blocks; + s->sad.odd = (s->sad.odd * 16ul) / s->num_blocks; + s->sad.noise = (s->sad.noise * 16ul) / s->num_blocks; + s->sad.temp = (s->sad.temp * 16ul) / s->num_blocks; + if (p->verbose) + mp_msg(MSGT_VFILTER, MSGL_INFO, "%lu%c M:%d/%d/%d/%d - %d, " + "t:%d/%d/%d/%d, l:%d/%d/%d/%d, h:%d/%d/%d/%d, bg:%d/%d/%d/%d, " + "2x:%d/%d/%d/%d, sad:%d/%d/%d/%d, lil:%d, hil:%d, ios:%.1f\n", + p->inframes, p->chflag, METRICS(s->max), s->num_blocks, + METRICS(s->tiny), METRICS(s->low), METRICS(s->high), + METRICS(s->bigger), METRICS(s->twox), METRICS(s->sad), + s->interlaced_low, s->interlaced_high, + p->iosync / (double) p->in_inc); +} + +static const char *parse_args(struct vf_priv_s *p, const char *args) +{ + args--; + while (args && *++args && + (sscanf(args, "io=%lu:%lu", &p->out_dec, &p->in_inc) == 2 || + sscanf(args, "diff_thres=%hu", &p->thres.even ) == 1 || + sscanf(args, "comb_thres=%hu", &p->thres.noise) == 1 || + sscanf(args, "sad_thres=%lu", &p->sad_thres ) == 1 || + sscanf(args, "dint_thres=%lu", &p->dint_thres ) == 1 || + sscanf(args, "fast=%u", &p->fast ) == 1 || + sscanf(args, "mmx2=%lu", &p->mmx2 ) == 1 || + sscanf(args, "luma_only=%u", &p->luma_only ) == 1 || + sscanf(args, "verbose=%u", &p->verbose ) == 1 || + sscanf(args, "crop=%lu:%lu:%lu:%lu", &p->w, + &p->h, &p->crop_x, &p->crop_y) == 4)) + args = strchr(args, '/'); + return args; +} + +static unsigned long gcd(unsigned long x, unsigned long y) +{ + unsigned long t; + if (x > y) + t = x, x = y, y = t; + + while (x) { + t = y % x; + y = x; + x = t; + } + return y; +} + +static void init(struct vf_priv_s *p, mp_image_t *mpi) +{ + unsigned long i; + unsigned long plane_size, chroma_plane_size; + unsigned char *plane; + unsigned long cos, los; + p->crop_cx = p->crop_x >> mpi->chroma_x_shift; + p->crop_cy = p->crop_y >> mpi->chroma_y_shift; + if (mpi->flags & MP_IMGFLAG_ACCEPT_STRIDE) { + p->stride = (mpi->w + 15) & ~15; + p->chroma_stride = p->stride >> mpi->chroma_x_shift; + } else { + p->stride = mpi->width; + p->chroma_stride = mpi->chroma_width; + } + p->cw = p->w >> mpi->chroma_x_shift; + p->ch = p->h >> mpi->chroma_y_shift; + p->nplanes = 1; + p->static_idx = 0; + p->temp_idx = 0; + p->old_planes = p->planes[0]; + plane_size = mpi->h * p->stride; + chroma_plane_size = mpi->flags & MP_IMGFLAG_PLANAR ? + mpi->chroma_height * p->chroma_stride : 0; + p->memory_allocated = + malloc(NUM_STORED * (plane_size+2*chroma_plane_size) + + 8*p->chroma_stride + 4096); + /* align to page boundary */ + plane = p->memory_allocated + (-(long)p->memory_allocated & 4095); + memset(plane, 0, NUM_STORED * plane_size); + los = p->crop_x + p->crop_y * p->stride; + cos = p->crop_cx + p->crop_cy * p->chroma_stride; + for (i = 0; i != NUM_STORED; i++, plane += plane_size) { + p->planes[i][0] = plane; + p->planes[NUM_STORED + i][0] = plane + los; + } + if (mpi->flags & MP_IMGFLAG_PLANAR) { + p->nplanes = 3; + memset(plane, 0x80, NUM_STORED * 2 * chroma_plane_size); + for (i = 0; i != NUM_STORED; i++) { + p->planes[i][1] = plane; + p->planes[NUM_STORED + i][1] = plane + cos; + plane += chroma_plane_size; + p->planes[i][2] = plane; + p->planes[NUM_STORED + i][2] = plane + cos; + plane += chroma_plane_size; + } + } + p->out_dec <<= 2; + i = gcd(p->in_inc, p->out_dec); + p->in_inc /= i; + p->out_dec /= i; + p->iosync = 0; + p->num_fields = 3; +} + +static inline double get_time(void) +{ + struct timeval tv; + gettimeofday(&tv, 0); + return tv.tv_sec + tv.tv_usec * 1e-6; +} + +static void get_image(struct vf_instance *vf, mp_image_t *mpi) +{ + struct vf_priv_s *p = vf->priv; + static unsigned char **planes, planes_idx; + + if (mpi->type == MP_IMGTYPE_STATIC) return; + + if (!p->planes[0][0]) init(p, mpi); + + if (mpi->type == MP_IMGTYPE_TEMP || + (mpi->type == MP_IMGTYPE_IPB && !(mpi->flags & MP_IMGFLAG_READABLE))) + planes_idx = NUM_STORED/2 + (++p->temp_idx % (NUM_STORED/2)); + else + planes_idx = ++p->static_idx % (NUM_STORED/2); + planes = p->planes[planes_idx]; + mpi->priv = p->planes[NUM_STORED + planes_idx]; + if (mpi->priv == p->old_planes) { + unsigned char **old_planes = + p->planes[NUM_STORED + 2 + (++p->temp_idx & 1)]; + my_memcpy_pic(old_planes[0], p->old_planes[0], + p->w, p->h, p->stride, p->stride); + if (mpi->flags & MP_IMGFLAG_PLANAR) { + my_memcpy_pic(old_planes[1], p->old_planes[1], + p->cw, p->ch, p->chroma_stride, p->chroma_stride); + my_memcpy_pic(old_planes[2], p->old_planes[2], + p->cw, p->ch, p->chroma_stride, p->chroma_stride); + } + p->old_planes = old_planes; + p->num_copies++; + } + mpi->planes[0] = planes[0]; + mpi->stride[0] = p->stride; + if (mpi->flags & MP_IMGFLAG_PLANAR) { + mpi->planes[1] = planes[1]; + mpi->planes[2] = planes[2]; + mpi->stride[1] = mpi->stride[2] = p->chroma_stride; + } + mpi->width = p->stride; + + mpi->flags |= MP_IMGFLAG_DIRECT; + mpi->flags &= ~MP_IMGFLAG_DRAW_CALLBACK; +} + +static inline long +cmpe(unsigned long x, unsigned long y, unsigned long err, unsigned long e) +{ + long diff = x-y; + long unit = ((x+y+err) >> e); + long ret = (diff > unit) - (diff < -unit); + unit >>= 1; + return ret + (diff > unit) - (diff < -unit); +} + +static unsigned long +find_breaks(struct vf_priv_s *p, struct frame_stats *s) +{ + struct frame_stats *ps = &p->stats[(p->inframes-1) & 1]; + long notfilm = 5*p->in_inc - p->out_dec; + unsigned long n = s->num_blocks >> 8; + unsigned long sad_comb_cmp = cmpe(s->sad.temp, s->sad.noise, 512, 1); + unsigned long ret = 8; + + if (cmpe(s->sad.temp, s->sad.even, 512, 1) > 0) + mp_msg(MSGT_VFILTER, MSGL_WARN, + "@@@@@@@@ Bottom-first field??? @@@@@@@@\n"); + if (s->sad.temp > 1000 && s->sad.noise > 1000) + return 3; + if (s->interlaced_high >= 2*n && s->sad.temp > 256 && s->sad.noise > 256) + return 3; + if (s->high.noise > s->num_blocks/4 && s->sad.noise > 10000 && + s->sad.noise > 2*s->sad.even && s->sad.noise > 2*ps->sad.odd) { + // Mid-frame scene change + if (s->tiny.temp + s->interlaced_low < n || + s->low.temp + s->interlaced_high < n/4 || + s->high.temp + s->interlaced_high < n/8 || + s->sad.temp < 160) + return 1; + return 3; + } + if (s->high.temp > s->num_blocks/4 && s->sad.temp > 10000 && + s->sad.temp > 2*ps->sad.odd && s->sad.temp > 2*ps->sad.even) { + // Start frame scene change + if (s->tiny.noise + s->interlaced_low < n || + s->low.noise + s->interlaced_high < n/4 || + s->high.noise + s->interlaced_high < n/8 || + s->sad.noise < 160) + return 2; + return 3; + } + if (sad_comb_cmp == 2) + return 2; + if (sad_comb_cmp == -2) + return 1; + + if (s->tiny.odd > 3*MAX(n,s->tiny.even) + s->interlaced_low) + return 1; + if (s->tiny.even > 3*MAX(n,s->tiny.odd)+s->interlaced_low && + (!sad_comb_cmp || (s->low.noise <= n/4 && s->low.temp <= n/4))) + return 4; + + if (s->sad.noise < 64 && s->sad.temp < 64 && + s->low.noise <= n/2 && s->high.noise <= n/4 && + s->low.temp <= n/2 && s->high.temp <= n/4) + goto still; + + if (s->tiny.temp > 3*MAX(n,s->tiny.noise) + s->interlaced_low) + return 2; + if (s->tiny.noise > 3*MAX(n,s->tiny.temp) + s->interlaced_low) + return 1; + + if (s->low.odd > 3*MAX(n/4,s->low.even) + s->interlaced_high) + return 1; + if (s->low.even > 3*MAX(n/4,s->low.odd)+s->interlaced_high && + s->sad.even > 2*s->sad.odd && + (!sad_comb_cmp || (s->low.noise <= n/4 && s->low.temp <= n/4))) + return 4; + + if (s->low.temp > 3*MAX(n/4,s->low.noise) + s->interlaced_high) + return 2; + if (s->low.noise > 3*MAX(n/4,s->low.temp) + s->interlaced_high) + return 1; + + if (sad_comb_cmp == 1 && s->sad.noise < 64) + return 2; + if (sad_comb_cmp == -1 && s->sad.temp < 64) + return 1; + + if (s->tiny.odd <= n || (s->tiny.noise <= n/2 && s->tiny.temp <= n/2)) { + if (s->interlaced_low <= n) { + if (p->num_fields == 1) + goto still; + if (s->tiny.even <= n || ps->tiny.noise <= n/2) + /* Still frame */ + goto still; + if (s->bigger.even >= 2*MAX(n,s->bigger.odd) + s->interlaced_low) + return 4; + if (s->low.even >= 2*n + s->interlaced_low) + return 4; + goto still; + } + } + if (s->low.odd <= n/4) { + if (s->interlaced_high <= n/4) { + if (p->num_fields == 1) + goto still; + if (s->low.even <= n/4) + /* Still frame */ + goto still; + if (s->bigger.even >= 2*MAX(n/4,s->bigger.odd)+s->interlaced_high) + return 4; + if (s->low.even >= n/2 + s->interlaced_high) + return 4; + goto still; + } + } + if (s->bigger.temp > 2*MAX(n,s->bigger.noise) + s->interlaced_low) + return 2; + if (s->bigger.noise > 2*MAX(n,s->bigger.temp) + s->interlaced_low) + return 1; + if (s->bigger.temp > 2*MAX(n,s->bigger.noise) + s->interlaced_high) + return 2; + if (s->bigger.noise > 2*MAX(n,s->bigger.temp) + s->interlaced_high) + return 1; + if (s->twox.temp > 2*MAX(n,s->twox.noise) + s->interlaced_high) + return 2; + if (s->twox.noise > 2*MAX(n,s->twox.temp) + s->interlaced_high) + return 1; + if (s->bigger.even > 2*MAX(n,s->bigger.odd) + s->interlaced_low && + s->bigger.temp < n && s->bigger.noise < n) + return 4; + if (s->interlaced_low > MIN(2*n, s->tiny.odd)) + return 3; + ret = 8 + (1 << (s->sad.temp > s->sad.noise)); + still: + if (p->num_fields == 1 && p->prev_fields == 3 && notfilm >= 0 && + (s->tiny.temp <= s->tiny.noise || s->sad.temp < s->sad.noise+16)) + return 1; + if (p->notout < p->num_fields && p->iosync > 2*p->in_inc && notfilm < 0) + notfilm = 0; + if (p->num_fields < 2 || + (p->num_fields == 2 && p->prev_fields == 2 && notfilm < 0)) + return ret; + if (!notfilm && (p->prev_fields&~1) == 2) { + if (p->prev_fields + p->num_fields == 5) { + if (s->tiny.noise <= s->tiny.temp || + s->low.noise == 0 || s->low.noise < s->low.temp || + s->sad.noise < s->sad.temp+16) + return 2; + } + if (p->prev_fields + p->num_fields == 4) { + if (s->tiny.temp <= s->tiny.noise || + s->low.temp == 0 || s->low.temp < s->low.noise || + s->sad.temp < s->sad.noise+16) + return 1; + } + } + if (p->num_fields > 2 && + ps->sad.noise > s->sad.noise && ps->sad.noise > s->sad.temp) + return 4; + return 2 >> (s->sad.noise > s->sad.temp); +} + +#define ITOC(X) (!(X) ? ' ' : (X) + ((X)>9 ? 'a'-10 : '0')) + +static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) +{ + mp_image_t *dmpi; + struct vf_priv_s *p = vf->priv; + unsigned char **planes, **old_planes; + struct frame_stats *s = &p->stats[p->inframes & 1]; + struct frame_stats *ps = &p->stats[(p->inframes-1) & 1]; + int swapped = 0; + const int flags = mpi->fields; + int breaks, prev; + int show_fields = 0; + int dropped_fields = 0; + double start_time, diff_time; + char prev_chflag = p->chflag; + int keep_rate; + + if (!p->planes[0][0]) init(p, mpi); + + old_planes = p->old_planes; + + if ((mpi->flags & MP_IMGFLAG_DIRECT) && mpi->priv) { + planes = mpi->priv; + mpi->priv = 0; + } else { + planes = p->planes[2 + (++p->temp_idx & 1)]; + my_memcpy_pic(planes[0], + mpi->planes[0] + p->crop_x + p->crop_y * mpi->stride[0], + p->w, p->h, p->stride, mpi->stride[0]); + if (mpi->flags & MP_IMGFLAG_PLANAR) { + my_memcpy_pic(planes[1], + mpi->planes[1] + p->crop_cx + p->crop_cy * mpi->stride[1], + p->cw, p->ch, p->chroma_stride, mpi->stride[1]); + my_memcpy_pic(planes[2], + mpi->planes[2] + p->crop_cx + p->crop_cy * mpi->stride[2], + p->cw, p->ch, p->chroma_stride, mpi->stride[2]); + p->num_copies++; + } + } + + p->old_planes = planes; + p->chflag = ';'; + if (flags & MP_IMGFIELD_ORDERED) { + swapped = !(flags & MP_IMGFIELD_TOP_FIRST); + p->chflag = (flags & MP_IMGFIELD_REPEAT_FIRST ? '|' : + flags & MP_IMGFIELD_TOP_FIRST ? ':' : '.'); + } + p->swapped = swapped; + + start_time = get_time(); + if (p->chflag == '|') { + *s = ppzs; + p->iosync += p->in_inc; + } else if ((p->fast & 1) && prev_chflag == '|') + *s = pprs; + else + diff_fields(p, s, old_planes, planes); + diff_time = get_time(); + p->diff_time += diff_time - start_time; + breaks = p->inframes ? find_breaks(p, s) : 2; + p->inframes++; + keep_rate = 4*p->in_inc == p->out_dec; + + switch (breaks) { + case 0: + case 8: + case 9: + case 10: + if (!keep_rate && p->notout < p->num_fields && p->iosync < 2*p->in_inc) + break; + if (p->notout < p->num_fields) + dropped_fields = -2; + case 4: + if (keep_rate || p->iosync >= -2*p->in_inc) + show_fields = (4<<p->num_fields)-1; + break; + case 3: + if (keep_rate) + show_fields = 2; + else if (p->iosync > 0) { + if (p->notout >= p->num_fields && p->iosync > 2*p->in_inc) { + show_fields = 4; /* prev odd only */ + if (p->num_fields > 1) + show_fields |= 8; /* + prev even */ + } else { + show_fields = 2; /* even only */ + if (p->notout >= p->num_fields) + dropped_fields += p->num_fields; + } + } + break; + case 2: + if (p->iosync <= -3*p->in_inc) { + if (p->notout >= p->num_fields) + dropped_fields = p->num_fields; + break; + } + if (p->num_fields == 1) { + int prevbreak = ps->sad.noise >= 128; + if (p->iosync < 4*p->in_inc) { + show_fields = 3; + dropped_fields = prevbreak; + } else { + show_fields = 4 | (!prevbreak << 3); + if (p->notout < 1 + p->prev_fields) + dropped_fields = -!prevbreak; + } + break; + } + default: + if (keep_rate) + show_fields = 3 << (breaks & 1); + else if (p->notout >= p->num_fields && + p->iosync >= (breaks == 1 ? -p->in_inc : + p->in_inc << (p->num_fields == 1))) { + show_fields = (1 << (2 + p->num_fields)) - (1<<breaks); + } else { + if (p->notout >= p->num_fields) + dropped_fields += p->num_fields + 2 - breaks; + if (breaks == 1) { + if (p->iosync >= 4*p->in_inc) + show_fields = 6; + } else if (p->iosync > -3*p->in_inc) + show_fields = 3; /* odd+even */ + } + break; + } + + show_fields &= 15; + prev = p->prev_fields; + if (breaks < 8) { + if (p->num_fields == 1) + breaks &= ~4; + if (breaks) + p->num_breaks++; + if (breaks == 3) + p->prev_fields = p->num_fields = 1; + else if (breaks) { + p->prev_fields = p->num_fields + (breaks==1) - (breaks==4); + p->num_fields = breaks - (breaks == 4) + (p->chflag == '|'); + } else + p->num_fields += 2; + } else + p->num_fields += 2; + + p->iosync += 4 * p->in_inc; + if (p->chflag == '|') + p->iosync += p->in_inc; + + if (show_fields) { + p->iosync -= p->out_dec; + p->notout = !(show_fields & 1) + !(show_fields & 3); + if (((show_fields & 3) == 3 && + (s->low.noise + s->interlaced_low < (s->num_blocks>>8) || + s->sad.noise < 160)) || + ((show_fields & 12) == 12 && + (ps->low.noise + ps->interlaced_low < (s->num_blocks>>8) || + ps->sad.noise < 160))) { + p->export_count++; + dmpi = vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_EXPORT, + MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE, + p->w, p->h); + if ((show_fields & 3) != 3) planes = old_planes; + dmpi->planes[0] = planes[0]; + dmpi->stride[0] = p->stride; + dmpi->width = mpi->width; + if (mpi->flags & MP_IMGFLAG_PLANAR) { + dmpi->planes[1] = planes[1]; + dmpi->planes[2] = planes[2]; + dmpi->stride[1] = p->chroma_stride; + dmpi->stride[2] = p->chroma_stride; + } + } else { + p->merge_count++; + dmpi = vf_get_image(vf->next, mpi->imgfmt, + MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, + p->w, p->h); + copy_merge_fields(p, dmpi, old_planes, planes, show_fields); + } + p->outframes++; + } else + p->notout += 2; + + if (p->verbose) + mp_msg(MSGT_VFILTER, MSGL_INFO, "%lu %lu: %x %c %c %lu%s%s%c%s\n", + p->inframes, p->outframes, + breaks, breaks<8 && breaks>0 ? (int) p->prev_fields+'0' : ' ', + ITOC(show_fields), + p->num_breaks, 5*p->in_inc == p->out_dec && breaks<8 && + breaks>0 && ((prev&~1)!=2 || prev+p->prev_fields!=5) ? + " ######## bad telecine ########" : "", + dropped_fields ? " ======== dropped ":"", ITOC(dropped_fields), + !show_fields || (show_fields & (show_fields-1)) ? + "" : " @@@@@@@@@@@@@@@@@"); + + p->merge_time += get_time() - diff_time; + return show_fields ? vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE) : 0; +} + +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: + case IMGFMT_411P: + case IMGFMT_422P: + case IMGFMT_444P: + 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) +{ + unsigned long cxm = 0; + unsigned long cym = 0; + struct vf_priv_s *p = vf->priv; + // rounding: + if(!IMGFMT_IS_RGB(outfmt) && !IMGFMT_IS_BGR(outfmt)){ + switch(outfmt){ + case IMGFMT_444P: + case IMGFMT_Y800: + case IMGFMT_Y8: + break; + case IMGFMT_YVU9: + case IMGFMT_IF09: + cym = 3; + case IMGFMT_411P: + cxm = 3; + break; + case IMGFMT_YV12: + case IMGFMT_I420: + case IMGFMT_IYUV: + cym = 1; + default: + cxm = 1; + } + } + p->chroma_swapped = !!(p->crop_y & (cym+1)); + if (p->w) p->w += p->crop_x & cxm; + if (p->h) p->h += p->crop_y & cym; + p->crop_x &= ~cxm; + p->crop_y &= ~cym; + if (!p->w || p->w > width ) p->w = width; + if (!p->h || p->h > height) p->h = height; + if (p->crop_x + p->w > width ) p->crop_x = 0; + if (p->crop_y + p->h > height) p->crop_y = 0; + + if(!opt_screen_size_x && !opt_screen_size_y){ + d_width = d_width * p->w/width; + d_height = d_height * p->h/height; + } + return vf_next_config(vf, p->w, p->h, d_width, d_height, flags, outfmt); +} + +static void uninit(struct vf_instance *vf) +{ + struct vf_priv_s *p = vf->priv; + mp_msg(MSGT_VFILTER, MSGL_INFO, "diff_time: %.3f, merge_time: %.3f, " + "export: %lu, merge: %lu, copy: %lu\n", p->diff_time, p->merge_time, + p->export_count, p->merge_count, p->num_copies); + free(p->memory_allocated); + free(p); +} + +static int vf_open(vf_instance_t *vf, char *args) +{ + struct vf_priv_s *p; + 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->out_dec = 5; + p->in_inc = 4; + p->thres.noise = 128; + p->thres.even = 128; + p->sad_thres = 64; + p->dint_thres = 4; + p->luma_only = 0; + p->fast = 3; + p->mmx2 = gCpuCaps.hasMMX2 ? 1 : gCpuCaps.has3DNow ? 2 : 0; + if (args) { + const char *args_remain = parse_args(p, args); + if (args_remain) { + mp_msg(MSGT_VFILTER, MSGL_FATAL, + "filmdint: unknown suboption: %s\n", args_remain); + return 0; + } + if (p->out_dec < p->in_inc) { + mp_msg(MSGT_VFILTER, MSGL_FATAL, + "filmdint: increasing the frame rate is not supported\n"); + return 0; + } + } + if (p->mmx2 > 2) + p->mmx2 = 0; +#if !HAVE_MMX + p->mmx2 = 0; +#endif +#if !HAVE_AMD3DNOW + p->mmx2 &= 1; +#endif + p->thres.odd = p->thres.even; + p->thres.temp = p->thres.noise; + p->diff_time = 0; + p->merge_time = 0; + return 1; +} + +const vf_info_t vf_info_filmdint = { + "Advanced inverse telecine filer", + "filmdint", + "Zoltan Hidvegi", + "", + vf_open, + NULL +}; diff --git a/libavfilter/libmpcodecs/vf_fixpts.c b/libavfilter/libmpcodecs/vf_fixpts.c new file mode 100644 index 0000000000..ae32b40d83 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_fixpts.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_framestep.c b/libavfilter/libmpcodecs/vf_framestep.c new file mode 100644 index 0000000000..cdf5386670 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_framestep.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_fspp.c b/libavfilter/libmpcodecs/vf_fspp.c new file mode 100644 index 0000000000..a98c70b26c --- /dev/null +++ b/libavfilter/libmpcodecs/vf_fspp.c @@ -0,0 +1,2117 @@ +/* + * Copyright (C) 2003 Michael Niedermayer <michaelni@gmx.at> + * Copyright (C) 2005 Nikolaj Poroshin <porosh3@psu.ru> + * + * 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) + * Futher, with splitting (i)dct into hor/ver passes, one of them can be + * performed once per block, not pixel. This allows for much better speed. + */ + +/* + Heavily optimized version of SPP filter by Nikolaj + */ + +#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 "vd_ffmpeg.h" +#include "libvo/fastmemcpy.h" + +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/dsputil.h" + +#undef free +#undef malloc + +//===========================================================================// +#define BLOCKSZ 12 + +static const short custom_threshold[64]= +// values (296) can't be too high +// -it causes too big quant dependence +// or maybe overflow(check), which results in some flashing +{ 71, 296, 295, 237, 71, 40, 38, 19, + 245, 193, 185, 121, 102, 73, 53, 27, + 158, 129, 141, 107, 97, 73, 50, 26, + 102, 116, 109, 98, 82, 66, 45, 23, + 71, 94, 95, 81, 70, 56, 38, 20, + 56, 77, 74, 66, 56, 44, 30, 15, + 38, 53, 50, 45, 38, 30, 21, 11, + 20, 27, 26, 23, 20, 15, 11, 5 +}; + +static const uint8_t __attribute__((aligned(32))) 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 { //align 16 ! + uint64_t threshold_mtx_noq[8*2]; + uint64_t threshold_mtx[8*2];//used in both C & MMX (& later SSE2) versions + + int log2_count; + int temp_stride; + int qp; + int mpeg2; + int prev_q; + uint8_t *src; + int16_t *temp; + int bframes; + char *non_b_qp; +}; + + +#if !HAVE_MMX + +//This func reads from 1 slice, 1 and clears 0 & 1 +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 + pos] + (d[pos]>>log2_scale))>>(6-log2_scale); \ + src[x + pos]=src[x + pos - 8*src_stride]=0; \ + if(temp & 0x100) temp= ~(temp>>31); \ + dst[x + 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); + } + src+=src_stride; + dst+=dst_stride; + } +} + +//This func reads from 2 slices, 0 & 2 and clears 2-nd +static void store_slice2_c(uint8_t *dst, int16_t *src, int dst_stride, int src_stride, int width, int height, int log2_scale) +{int y, x; +#define STORE2(pos) \ + temp= (src[x + pos] + src[x + pos + 16*src_stride] + (d[pos]>>log2_scale))>>(6-log2_scale); \ + src[x + pos + 16*src_stride]=0; \ + if(temp & 0x100) temp= ~(temp>>31); \ + dst[x + pos]= temp; + + for(y=0; y<height; y++){ + const uint8_t *d= dither[y]; + for(x=0; x<width; x+=8){ + int temp; + STORE2(0); + STORE2(1); + STORE2(2); + STORE2(3); + STORE2(4); + STORE2(5); + STORE2(6); + STORE2(7); + } + src+=src_stride; + dst+=dst_stride; + } +} + +static void mul_thrmat_c(struct vf_priv_s *p,int q) +{ + int a; + for(a=0;a<64;a++) + ((short*)p->threshold_mtx)[a]=q * ((short*)p->threshold_mtx_noq)[a];//ints faster in C +} + +static void column_fidct_c(int16_t* thr_adr, DCTELEM *data, DCTELEM *output, int cnt); +static void row_idct_c(DCTELEM* workspace, + int16_t* output_adr, int output_stride, int cnt); +static void row_fdct_c(DCTELEM *data, const uint8_t *pixels, int line_size, int cnt); + +//this is rather ugly, but there is no need for function pointers +#define store_slice_s store_slice_c +#define store_slice2_s store_slice2_c +#define mul_thrmat_s mul_thrmat_c +#define column_fidct_s column_fidct_c +#define row_idct_s row_idct_c +#define row_fdct_s row_fdct_c + +#else /* HAVE_MMX */ + +//This func reads from 1 slice, 1 and clears 0 & 1 +static void store_slice_mmx(uint8_t *dst, int16_t *src, long dst_stride, long src_stride, long width, long height, long log2_scale) +{ + const uint8_t *od=&dither[0][0]; + const uint8_t *end=&dither[height][0]; + width = (width+7)&~7; + dst_stride-=width; + //src_stride=(src_stride-width)*2; + __asm__ volatile( + "mov %5, %%"REG_d" \n\t" + "mov %6, %%"REG_S" \n\t" + "mov %7, %%"REG_D" \n\t" + "mov %1, %%"REG_a" \n\t" + "movd %%"REG_d", %%mm5 \n\t" + "xor $-1, %%"REG_d" \n\t" + "mov %%"REG_a", %%"REG_c" \n\t" + "add $7, %%"REG_d" \n\t" + "neg %%"REG_a" \n\t" + "sub %0, %%"REG_c" \n\t" + "add %%"REG_c", %%"REG_c" \n\t" + "movd %%"REG_d", %%mm2 \n\t" + "mov %%"REG_c", %1 \n\t" + "mov %2, %%"REG_d" \n\t" + "shl $4, %%"REG_a" \n\t" + + "2: \n\t" + "movq (%%"REG_d"), %%mm3 \n\t" + "movq %%mm3, %%mm4 \n\t" + "pxor %%mm7, %%mm7 \n\t" + "punpcklbw %%mm7, %%mm3 \n\t" + "punpckhbw %%mm7, %%mm4 \n\t" + "mov %0, %%"REG_c" \n\t" + "psraw %%mm5, %%mm3 \n\t" + "psraw %%mm5, %%mm4 \n\t" + "1: \n\t" + "movq %%mm7, (%%"REG_S",%%"REG_a",) \n\t" + "movq (%%"REG_S"), %%mm0 \n\t" + "movq 8(%%"REG_S"), %%mm1 \n\t" + + "movq %%mm7, 8(%%"REG_S",%%"REG_a",) \n\t" + "paddw %%mm3, %%mm0 \n\t" + "paddw %%mm4, %%mm1 \n\t" + + "movq %%mm7, (%%"REG_S") \n\t" + "psraw %%mm2, %%mm0 \n\t" + "psraw %%mm2, %%mm1 \n\t" + + "movq %%mm7, 8(%%"REG_S") \n\t" + "packuswb %%mm1, %%mm0 \n\t" + "add $16, %%"REG_S" \n\t" + + "movq %%mm0, (%%"REG_D") \n\t" + "add $8, %%"REG_D" \n\t" + "sub $8, %%"REG_c" \n\t" + "jg 1b \n\t" + "add %1, %%"REG_S" \n\t" + "add $8, %%"REG_d" \n\t" + "add %3, %%"REG_D" \n\t" + "cmp %4, %%"REG_d" \n\t" + "jl 2b \n\t" + + : + : "m" (width), "m" (src_stride), "erm" (od), "m" (dst_stride), "erm" (end), + "m" (log2_scale), "m" (src), "m" (dst) //input + : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S, "%"REG_D + ); +} + +//This func reads from 2 slices, 0 & 2 and clears 2-nd +static void store_slice2_mmx(uint8_t *dst, int16_t *src, long dst_stride, long src_stride, long width, long height, long log2_scale) +{ + const uint8_t *od=&dither[0][0]; + const uint8_t *end=&dither[height][0]; + width = (width+7)&~7; + dst_stride-=width; + //src_stride=(src_stride-width)*2; + __asm__ volatile( + "mov %5, %%"REG_d" \n\t" + "mov %6, %%"REG_S" \n\t" + "mov %7, %%"REG_D" \n\t" + "mov %1, %%"REG_a" \n\t" + "movd %%"REG_d", %%mm5 \n\t" + "xor $-1, %%"REG_d" \n\t" + "mov %%"REG_a", %%"REG_c" \n\t" + "add $7, %%"REG_d" \n\t" + "sub %0, %%"REG_c" \n\t" + "add %%"REG_c", %%"REG_c" \n\t" + "movd %%"REG_d", %%mm2 \n\t" + "mov %%"REG_c", %1 \n\t" + "mov %2, %%"REG_d" \n\t" + "shl $5, %%"REG_a" \n\t" + + "2: \n\t" + "movq (%%"REG_d"), %%mm3 \n\t" + "movq %%mm3, %%mm4 \n\t" + "pxor %%mm7, %%mm7 \n\t" + "punpcklbw %%mm7, %%mm3 \n\t" + "punpckhbw %%mm7, %%mm4 \n\t" + "mov %0, %%"REG_c" \n\t" + "psraw %%mm5, %%mm3 \n\t" + "psraw %%mm5, %%mm4 \n\t" + "1: \n\t" + "movq (%%"REG_S"), %%mm0 \n\t" + "movq 8(%%"REG_S"), %%mm1 \n\t" + "paddw %%mm3, %%mm0 \n\t" + + "paddw (%%"REG_S",%%"REG_a",), %%mm0 \n\t" + "paddw %%mm4, %%mm1 \n\t" + "movq 8(%%"REG_S",%%"REG_a",), %%mm6 \n\t" + + "movq %%mm7, (%%"REG_S",%%"REG_a",) \n\t" + "psraw %%mm2, %%mm0 \n\t" + "paddw %%mm6, %%mm1 \n\t" + + "movq %%mm7, 8(%%"REG_S",%%"REG_a",) \n\t" + "psraw %%mm2, %%mm1 \n\t" + "packuswb %%mm1, %%mm0 \n\t" + + "movq %%mm0, (%%"REG_D") \n\t" + "add $16, %%"REG_S" \n\t" + "add $8, %%"REG_D" \n\t" + "sub $8, %%"REG_c" \n\t" + "jg 1b \n\t" + "add %1, %%"REG_S" \n\t" + "add $8, %%"REG_d" \n\t" + "add %3, %%"REG_D" \n\t" + "cmp %4, %%"REG_d" \n\t" + "jl 2b \n\t" + + : + : "m" (width), "m" (src_stride), "erm" (od), "m" (dst_stride), "erm" (end), + "m" (log2_scale), "m" (src), "m" (dst) //input + : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_D, "%"REG_S + ); +} + +static void mul_thrmat_mmx(struct vf_priv_s *p, int q) +{ + uint64_t *adr=&p->threshold_mtx_noq[0]; + __asm__ volatile( + "movd %0, %%mm7 \n\t" + "add $8*8*2, %%"REG_D" \n\t" + "movq 0*8(%%"REG_S"), %%mm0 \n\t" + "punpcklwd %%mm7, %%mm7 \n\t" + "movq 1*8(%%"REG_S"), %%mm1 \n\t" + "punpckldq %%mm7, %%mm7 \n\t" + "pmullw %%mm7, %%mm0 \n\t" + + "movq 2*8(%%"REG_S"), %%mm2 \n\t" + "pmullw %%mm7, %%mm1 \n\t" + + "movq 3*8(%%"REG_S"), %%mm3 \n\t" + "pmullw %%mm7, %%mm2 \n\t" + + "movq %%mm0, 0*8(%%"REG_D") \n\t" + "movq 4*8(%%"REG_S"), %%mm4 \n\t" + "pmullw %%mm7, %%mm3 \n\t" + + "movq %%mm1, 1*8(%%"REG_D") \n\t" + "movq 5*8(%%"REG_S"), %%mm5 \n\t" + "pmullw %%mm7, %%mm4 \n\t" + + "movq %%mm2, 2*8(%%"REG_D") \n\t" + "movq 6*8(%%"REG_S"), %%mm6 \n\t" + "pmullw %%mm7, %%mm5 \n\t" + + "movq %%mm3, 3*8(%%"REG_D") \n\t" + "movq 7*8+0*8(%%"REG_S"), %%mm0 \n\t" + "pmullw %%mm7, %%mm6 \n\t" + + "movq %%mm4, 4*8(%%"REG_D") \n\t" + "movq 7*8+1*8(%%"REG_S"), %%mm1 \n\t" + "pmullw %%mm7, %%mm0 \n\t" + + "movq %%mm5, 5*8(%%"REG_D") \n\t" + "movq 7*8+2*8(%%"REG_S"), %%mm2 \n\t" + "pmullw %%mm7, %%mm1 \n\t" + + "movq %%mm6, 6*8(%%"REG_D") \n\t" + "movq 7*8+3*8(%%"REG_S"), %%mm3 \n\t" + "pmullw %%mm7, %%mm2 \n\t" + + "movq %%mm0, 7*8+0*8(%%"REG_D") \n\t" + "movq 7*8+4*8(%%"REG_S"), %%mm4 \n\t" + "pmullw %%mm7, %%mm3 \n\t" + + "movq %%mm1, 7*8+1*8(%%"REG_D") \n\t" + "movq 7*8+5*8(%%"REG_S"), %%mm5 \n\t" + "pmullw %%mm7, %%mm4 \n\t" + + "movq %%mm2, 7*8+2*8(%%"REG_D") \n\t" + "movq 7*8+6*8(%%"REG_S"), %%mm6 \n\t" + "pmullw %%mm7, %%mm5 \n\t" + + "movq %%mm3, 7*8+3*8(%%"REG_D") \n\t" + "movq 14*8+0*8(%%"REG_S"), %%mm0 \n\t" + "pmullw %%mm7, %%mm6 \n\t" + + "movq %%mm4, 7*8+4*8(%%"REG_D") \n\t" + "movq 14*8+1*8(%%"REG_S"), %%mm1 \n\t" + "pmullw %%mm7, %%mm0 \n\t" + + "movq %%mm5, 7*8+5*8(%%"REG_D") \n\t" + "pmullw %%mm7, %%mm1 \n\t" + + "movq %%mm6, 7*8+6*8(%%"REG_D") \n\t" + "movq %%mm0, 14*8+0*8(%%"REG_D") \n\t" + "movq %%mm1, 14*8+1*8(%%"REG_D") \n\t" + + : "+g" (q), "+S" (adr), "+D" (adr) + : + ); +} + +static void column_fidct_mmx(int16_t* thr_adr, DCTELEM *data, DCTELEM *output, int cnt); +static void row_idct_mmx(DCTELEM* workspace, + int16_t* output_adr, int output_stride, int cnt); +static void row_fdct_mmx(DCTELEM *data, const uint8_t *pixels, int line_size, int cnt); + +#define store_slice_s store_slice_mmx +#define store_slice2_s store_slice2_mmx +#define mul_thrmat_s mul_thrmat_mmx +#define column_fidct_s column_fidct_mmx +#define row_idct_s row_idct_mmx +#define row_fdct_s row_fdct_mmx +#endif // HAVE_MMX + +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, x0, y, es, qy, t; + const int stride= is_luma ? p->temp_stride : (width+16);//((width+16+15)&(~15)) + const int step=6-p->log2_count; + const int qps= 3 + is_luma; + int32_t __attribute__((aligned(32))) block_align[4*8*BLOCKSZ+ 4*8*BLOCKSZ]; + DCTELEM *block= (DCTELEM *)block_align; + DCTELEM *block3=(DCTELEM *)(block_align+4*8*BLOCKSZ); + + memset(block3, 0, 4*8*BLOCKSZ); + + //p->src=src-src_stride*8-8;//! + 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);//this line can be avoided by using DR & user fr.buffers + 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=8; y<24; y++) + memset(p->temp+ 8 +y*stride, 0,width*sizeof(int16_t)); + + for(y=step; y<height+8; y+=step){ //step= 1,2 + qy=y-4; + if (qy>height-1) qy=height-1; + if (qy<0) qy=0; + qy=(qy>>qps)*qp_stride; + row_fdct_s(block, p->src + y*stride +2-(y&1), stride, 2); + for(x0=0; x0<width+8-8*(BLOCKSZ-1); x0+=8*(BLOCKSZ-1)){ + row_fdct_s(block+8*8, p->src + y*stride+8+x0 +2-(y&1), stride, 2*(BLOCKSZ-1)); + if(p->qp) + column_fidct_s((int16_t*)(&p->threshold_mtx[0]), block+0*8, block3+0*8, 8*(BLOCKSZ-1)); //yes, this is a HOTSPOT + else + for (x=0; x<8*(BLOCKSZ-1); x+=8) { + t=x+x0-2; //correct t=x+x0-2-(y&1), but its the same + if (t<0) t=0;//t always < width-2 + t=qp_store[qy+(t>>qps)]; + t=norm_qscale(t, p->mpeg2); + if (t!=p->prev_q) p->prev_q=t, mul_thrmat_s(p, t); + column_fidct_s((int16_t*)(&p->threshold_mtx[0]), block+x*8, block3+x*8, 8); //yes, this is a HOTSPOT + } + row_idct_s(block3+0*8, p->temp + (y&15)*stride+x0+2-(y&1), stride, 2*(BLOCKSZ-1)); + memmove(block, block+(BLOCKSZ-1)*64, 8*8*sizeof(DCTELEM)); //cycling + memmove(block3, block3+(BLOCKSZ-1)*64, 6*8*sizeof(DCTELEM)); + } + // + es=width+8-x0; // 8, ... + if (es>8) + row_fdct_s(block+8*8, p->src + y*stride+8+x0 +2-(y&1), stride, (es-4)>>2); + column_fidct_s((int16_t*)(&p->threshold_mtx[0]), block, block3, es&(~1)); + row_idct_s(block3+0*8, p->temp + (y&15)*stride+x0+2-(y&1), stride, es>>2); + {const int y1=y-8+step;//l5-7 l4-6 + if (!(y1&7) && y1) { + if (y1&8) store_slice_s(dst + (y1-8)*dst_stride, p->temp+ 8 +8*stride, + dst_stride, stride, width, 8, 5-p->log2_count); + else store_slice2_s(dst + (y1-8)*dst_stride, p->temp+ 8 +0*stride, + dst_stride, stride, width, 8, 5-p->log2_count); + } } + } + + if (y&7) { // == height & 7 + if (y&8) store_slice_s(dst + ((y-8)&~7)*dst_stride, p->temp+ 8 +8*stride, + dst_stride, stride, width, y&7, 5-p->log2_count); + else store_slice2_s(dst + ((y-8)&~7)*dst_stride, p->temp+ 8 +0*stride, + dst_stride, stride, width, y&7, 5-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 h= (height+16+15)&(~15); + + vf->priv->temp_stride= (width+16+15)&(~15); + vf->priv->temp= (int16_t*)av_mallocz(vf->priv->temp_stride*3*8*sizeof(int16_t)); + //this can also be avoided, see above + vf->priv->src = (uint8_t*)av_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, 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->bframes || !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; + + av_free(vf->priv->temp); + vf->priv->temp= NULL; + av_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; + + av_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 5; + case VFCTRL_SET_PP_LEVEL: + vf->priv->log2_count= *((unsigned int*)data); + if (vf->priv->log2_count < 4) vf->priv->log2_count=4; + return CONTROL_TRUE; + } + return vf_next_control(vf,request,data); +} + +static int vf_open(vf_instance_t *vf, char *args) +{ + int i=0, bias; + int custom_threshold_m[64]; + 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=av_mallocz(sizeof(struct vf_priv_s));//assumes align 16 ! + + init_avcodec(); + + //vf->priv->avctx= avcodec_alloc_context(); + //dsputil_init(&vf->priv->dsp, vf->priv->avctx); + + vf->priv->log2_count= 4; + vf->priv->bframes = 0; + + if (args) sscanf(args, "%d:%d:%d:%d", &log2c, &vf->priv->qp, &i, &vf->priv->bframes); + + if( log2c >=4 && log2c <=5 ) + vf->priv->log2_count = log2c; + else if( log2c >= 6 ) + vf->priv->log2_count = 5; + + if(vf->priv->qp < 0) + vf->priv->qp = 0; + + if (i < -15) i = -15; + if (i > 32) i = 32; + + bias= (1<<4)+i; //regulable + vf->priv->prev_q=0; + // + for(i=0;i<64;i++) //FIXME: tune custom_threshold[] and remove this ! + custom_threshold_m[i]=(int)(custom_threshold[i]*(bias/71.)+ 0.5); + for(i=0;i<8;i++){ + vf->priv->threshold_mtx_noq[2*i]=(uint64_t)custom_threshold_m[i*8+2] + |(((uint64_t)custom_threshold_m[i*8+6])<<16) + |(((uint64_t)custom_threshold_m[i*8+0])<<32) + |(((uint64_t)custom_threshold_m[i*8+4])<<48); + vf->priv->threshold_mtx_noq[2*i+1]=(uint64_t)custom_threshold_m[i*8+5] + |(((uint64_t)custom_threshold_m[i*8+3])<<16) + |(((uint64_t)custom_threshold_m[i*8+1])<<32) + |(((uint64_t)custom_threshold_m[i*8+7])<<48); + } + + if (vf->priv->qp) vf->priv->prev_q=vf->priv->qp, mul_thrmat_s(vf->priv, vf->priv->qp); + + return 1; +} + +const vf_info_t vf_info_fspp = { + "fast simple postprocess", + "fspp", + "Michael Niedermayer, Nikolaj Poroshin", + "", + vf_open, + NULL +}; + +//==================================================================== +//Specific spp's dct, idct and threshold functions +//I'd prefer to have them in the separate file. + +//#define MANGLE(a) #a + +//typedef int16_t DCTELEM; //! only int16_t + +#define DCTSIZE 8 +#define DCTSIZE_S "8" + +#define FIX(x,s) ((int) ((x) * (1<<s) + 0.5)&0xffff) +#define C64(x) ((uint64_t)((x)|(x)<<16))<<32 | (uint64_t)(x) | (uint64_t)(x)<<16 +#define FIX64(x,s) C64(FIX(x,s)) + +#define MULTIPLY16H(x,k) (((x)*(k))>>16) +#define THRESHOLD(r,x,t) if(((unsigned)((x)+t))>t*2) r=(x);else r=0; +#define DESCALE(x,n) (((x) + (1 << ((n)-1))) >> n) + +#if HAVE_MMX + +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_382683433)=FIX64(0.382683433, 14); +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_541196100)=FIX64(0.541196100, 14); +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_707106781)=FIX64(0.707106781, 14); +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_1_306562965)=FIX64(1.306562965, 14); + +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_1_414213562_A)=FIX64(1.414213562, 14); + +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_1_847759065)=FIX64(1.847759065, 13); +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_2_613125930)=FIX64(-2.613125930, 13); //- +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_1_414213562)=FIX64(1.414213562, 13); +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_1_082392200)=FIX64(1.082392200, 13); +//for t3,t5,t7 == 0 shortcut +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_847759065)=FIX64(0.847759065, 14); +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_566454497)=FIX64(0.566454497, 14); +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_198912367)=FIX64(0.198912367, 14); + +DECLARE_ASM_CONST(8, uint64_t, MM_DESCALE_RND)=C64(4); +DECLARE_ASM_CONST(8, uint64_t, MM_2)=C64(2); + +#else /* !HAVE_MMX */ + +typedef int32_t int_simd16_t; +static const int16_t FIX_0_382683433=FIX(0.382683433, 14); +static const int16_t FIX_0_541196100=FIX(0.541196100, 14); +static const int16_t FIX_0_707106781=FIX(0.707106781, 14); +static const int16_t FIX_1_306562965=FIX(1.306562965, 14); +static const int16_t FIX_1_414213562_A=FIX(1.414213562, 14); +static const int16_t FIX_1_847759065=FIX(1.847759065, 13); +static const int16_t FIX_2_613125930=FIX(-2.613125930, 13); //- +static const int16_t FIX_1_414213562=FIX(1.414213562, 13); +static const int16_t FIX_1_082392200=FIX(1.082392200, 13); + +#endif + +#if !HAVE_MMX + +static void column_fidct_c(int16_t* thr_adr, DCTELEM *data, DCTELEM *output, int cnt) +{ + int_simd16_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + int_simd16_t tmp10, tmp11, tmp12, tmp13; + int_simd16_t z1,z2,z3,z4,z5, z10, z11, z12, z13; + int_simd16_t d0, d1, d2, d3, d4, d5, d6, d7; + + DCTELEM* dataptr; + DCTELEM* wsptr; + int16_t *threshold; + int ctr; + + dataptr = data; + wsptr = output; + + for (; cnt > 0; cnt-=2) { //start positions + threshold=(int16_t*)thr_adr;//threshold_mtx + for (ctr = DCTSIZE; ctr > 0; ctr--) { + // Process columns from input, add to output. + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + // Even part of FDCT + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + d0 = tmp10 + tmp11; + d4 = tmp10 - tmp11; + + z1 = MULTIPLY16H((tmp12 + tmp13) <<2, FIX_0_707106781); + d2 = tmp13 + z1; + d6 = tmp13 - z1; + + // Even part of IDCT + + THRESHOLD(tmp0, d0, threshold[0*8]); + THRESHOLD(tmp1, d2, threshold[2*8]); + THRESHOLD(tmp2, d4, threshold[4*8]); + THRESHOLD(tmp3, d6, threshold[6*8]); + tmp0+=2; + tmp10 = (tmp0 + tmp2)>>2; + tmp11 = (tmp0 - tmp2)>>2; + + tmp13 = (tmp1 + tmp3)>>2; //+2 ! (psnr decides) + tmp12 = MULTIPLY16H((tmp1 - tmp3), FIX_1_414213562_A) - tmp13; //<<2 + + tmp0 = tmp10 + tmp13; //->temps + tmp3 = tmp10 - tmp13; //->temps + tmp1 = tmp11 + tmp12; //->temps + tmp2 = tmp11 - tmp12; //->temps + + // Odd part of FDCT + + tmp10 = tmp4 + tmp5; + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + z5 = MULTIPLY16H((tmp10 - tmp12)<<2, FIX_0_382683433); + z2 = MULTIPLY16H(tmp10 <<2, FIX_0_541196100) + z5; + z4 = MULTIPLY16H(tmp12 <<2, FIX_1_306562965) + z5; + z3 = MULTIPLY16H(tmp11 <<2, FIX_0_707106781); + + z11 = tmp7 + z3; + z13 = tmp7 - z3; + + d5 = z13 + z2; + d3 = z13 - z2; + d1 = z11 + z4; + d7 = z11 - z4; + + // Odd part of IDCT + + THRESHOLD(tmp4, d1, threshold[1*8]); + THRESHOLD(tmp5, d3, threshold[3*8]); + THRESHOLD(tmp6, d5, threshold[5*8]); + THRESHOLD(tmp7, d7, threshold[7*8]); + + //Simd version uses here a shortcut for the tmp5,tmp6,tmp7 == 0 + z13 = tmp6 + tmp5; + z10 = (tmp6 - tmp5)<<1; + z11 = tmp4 + tmp7; + z12 = (tmp4 - tmp7)<<1; + + tmp7 = (z11 + z13)>>2; //+2 ! + tmp11 = MULTIPLY16H((z11 - z13)<<1, FIX_1_414213562); + z5 = MULTIPLY16H(z10 + z12, FIX_1_847759065); + tmp10 = MULTIPLY16H(z12, FIX_1_082392200) - z5; + tmp12 = MULTIPLY16H(z10, FIX_2_613125930) + z5; // - !! + + tmp6 = tmp12 - tmp7; + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0]+= (tmp0 + tmp7); + wsptr[DCTSIZE*1]+= (tmp1 + tmp6); + wsptr[DCTSIZE*2]+= (tmp2 + tmp5); + wsptr[DCTSIZE*3]+= (tmp3 - tmp4); + wsptr[DCTSIZE*4]+= (tmp3 + tmp4); + wsptr[DCTSIZE*5]+= (tmp2 - tmp5); + wsptr[DCTSIZE*6]= (tmp1 - tmp6); + wsptr[DCTSIZE*7]= (tmp0 - tmp7); + // + dataptr++; //next column + wsptr++; + threshold++; + } + dataptr+=8; //skip each second start pos + wsptr +=8; + } +} + +#else /* HAVE_MMX */ + +static void column_fidct_mmx(int16_t* thr_adr, DCTELEM *data, DCTELEM *output, int cnt) +{ + uint64_t __attribute__((aligned(8))) temps[4]; + __asm__ volatile( + ASMALIGN(4) + "1: \n\t" + "movq "DCTSIZE_S"*0*2(%%"REG_S"), %%mm1 \n\t" + // + "movq "DCTSIZE_S"*3*2(%%"REG_S"), %%mm7 \n\t" + "movq %%mm1, %%mm0 \n\t" + + "paddw "DCTSIZE_S"*7*2(%%"REG_S"), %%mm1 \n\t" //t0 + "movq %%mm7, %%mm3 \n\t" + + "paddw "DCTSIZE_S"*4*2(%%"REG_S"), %%mm7 \n\t" //t3 + "movq %%mm1, %%mm5 \n\t" + + "movq "DCTSIZE_S"*1*2(%%"REG_S"), %%mm6 \n\t" + "psubw %%mm7, %%mm1 \n\t" //t13 + + "movq "DCTSIZE_S"*2*2(%%"REG_S"), %%mm2 \n\t" + "movq %%mm6, %%mm4 \n\t" + + "paddw "DCTSIZE_S"*6*2(%%"REG_S"), %%mm6 \n\t" //t1 + "paddw %%mm7, %%mm5 \n\t" //t10 + + "paddw "DCTSIZE_S"*5*2(%%"REG_S"), %%mm2 \n\t" //t2 + "movq %%mm6, %%mm7 \n\t" + + "paddw %%mm2, %%mm6 \n\t" //t11 + "psubw %%mm2, %%mm7 \n\t" //t12 + + "movq %%mm5, %%mm2 \n\t" + "paddw %%mm6, %%mm5 \n\t" //d0 + // i0 t13 t12 i3 i1 d0 - d4 + "psubw %%mm6, %%mm2 \n\t" //d4 + "paddw %%mm1, %%mm7 \n\t" + + "movq 4*16(%%"REG_d"), %%mm6 \n\t" + "psllw $2, %%mm7 \n\t" + + "psubw 0*16(%%"REG_d"), %%mm5 \n\t" + "psubw %%mm6, %%mm2 \n\t" + + "paddusw 0*16(%%"REG_d"), %%mm5 \n\t" + "paddusw %%mm6, %%mm2 \n\t" + + "pmulhw "MANGLE(MM_FIX_0_707106781)", %%mm7 \n\t" + // + "paddw 0*16(%%"REG_d"), %%mm5 \n\t" + "paddw %%mm6, %%mm2 \n\t" + + "psubusw 0*16(%%"REG_d"), %%mm5 \n\t" + "psubusw %%mm6, %%mm2 \n\t" + +//This func is totally compute-bound, operates at huge speed. So, DC shortcut +// at this place isn't worthwhile due to BTB miss penalty (checked on Pent. 3). +//However, typical numbers: nondc - 29%%, dc - 46%%, zero - 25%%. All <> 0 case is very rare. + "paddw "MANGLE(MM_2)", %%mm5 \n\t" + "movq %%mm2, %%mm6 \n\t" + + "paddw %%mm5, %%mm2 \n\t" + "psubw %%mm6, %%mm5 \n\t" + + "movq %%mm1, %%mm6 \n\t" + "paddw %%mm7, %%mm1 \n\t" //d2 + + "psubw 2*16(%%"REG_d"), %%mm1 \n\t" + "psubw %%mm7, %%mm6 \n\t" //d6 + + "movq 6*16(%%"REG_d"), %%mm7 \n\t" + "psraw $2, %%mm5 \n\t" + + "paddusw 2*16(%%"REG_d"), %%mm1 \n\t" + "psubw %%mm7, %%mm6 \n\t" + // t7 d2 /t11 t4 t6 - d6 /t10 + + "paddw 2*16(%%"REG_d"), %%mm1 \n\t" + "paddusw %%mm7, %%mm6 \n\t" + + "psubusw 2*16(%%"REG_d"), %%mm1 \n\t" + "paddw %%mm7, %%mm6 \n\t" + + "psubw "DCTSIZE_S"*4*2(%%"REG_S"), %%mm3 \n\t" + "psubusw %%mm7, %%mm6 \n\t" + + //movq [edi+"DCTSIZE_S"*2*2], mm1 + //movq [edi+"DCTSIZE_S"*6*2], mm6 + "movq %%mm1, %%mm7 \n\t" + "psraw $2, %%mm2 \n\t" + + "psubw "DCTSIZE_S"*6*2(%%"REG_S"), %%mm4 \n\t" + "psubw %%mm6, %%mm1 \n\t" + + "psubw "DCTSIZE_S"*7*2(%%"REG_S"), %%mm0 \n\t" + "paddw %%mm7, %%mm6 \n\t" //'t13 + + "psraw $2, %%mm6 \n\t" //paddw mm6, MM_2 !! --- + "movq %%mm2, %%mm7 \n\t" + + "pmulhw "MANGLE(MM_FIX_1_414213562_A)", %%mm1 \n\t" + "paddw %%mm6, %%mm2 \n\t" //'t0 + + "movq %%mm2, 0*8+%3 \n\t" //! + "psubw %%mm6, %%mm7 \n\t" //'t3 + + "movq "DCTSIZE_S"*2*2(%%"REG_S"), %%mm2 \n\t" + "psubw %%mm6, %%mm1 \n\t" //'t12 + + "psubw "DCTSIZE_S"*5*2(%%"REG_S"), %%mm2 \n\t" //t5 + "movq %%mm5, %%mm6 \n\t" + + "movq %%mm7, 3*8+%3 \n\t" + "paddw %%mm2, %%mm3 \n\t" //t10 + + "paddw %%mm4, %%mm2 \n\t" //t11 + "paddw %%mm0, %%mm4 \n\t" //t12 + + "movq %%mm3, %%mm7 \n\t" + "psubw %%mm4, %%mm3 \n\t" + + "psllw $2, %%mm3 \n\t" + "psllw $2, %%mm7 \n\t" //opt for P6 + + "pmulhw "MANGLE(MM_FIX_0_382683433)", %%mm3 \n\t" + "psllw $2, %%mm4 \n\t" + + "pmulhw "MANGLE(MM_FIX_0_541196100)", %%mm7 \n\t" + "psllw $2, %%mm2 \n\t" + + "pmulhw "MANGLE(MM_FIX_1_306562965)", %%mm4 \n\t" + "paddw %%mm1, %%mm5 \n\t" //'t1 + + "pmulhw "MANGLE(MM_FIX_0_707106781)", %%mm2 \n\t" + "psubw %%mm1, %%mm6 \n\t" //'t2 + // t7 't12 't11 t4 t6 - 't13 't10 --- + + "paddw %%mm3, %%mm7 \n\t" //z2 + + "movq %%mm5, 1*8+%3 \n\t" + "paddw %%mm3, %%mm4 \n\t" //z4 + + "movq 3*16(%%"REG_d"), %%mm3 \n\t" + "movq %%mm0, %%mm1 \n\t" + + "movq %%mm6, 2*8+%3 \n\t" + "psubw %%mm2, %%mm1 \n\t" //z13 + +//=== + "paddw %%mm2, %%mm0 \n\t" //z11 + "movq %%mm1, %%mm5 \n\t" + + "movq 5*16(%%"REG_d"), %%mm2 \n\t" + "psubw %%mm7, %%mm1 \n\t" //d3 + + "paddw %%mm7, %%mm5 \n\t" //d5 + "psubw %%mm3, %%mm1 \n\t" + + "movq 1*16(%%"REG_d"), %%mm7 \n\t" + "psubw %%mm2, %%mm5 \n\t" + + "movq %%mm0, %%mm6 \n\t" + "paddw %%mm4, %%mm0 \n\t" //d1 + + "paddusw %%mm3, %%mm1 \n\t" + "psubw %%mm4, %%mm6 \n\t" //d7 + + // d1 d3 - - - d5 d7 - + "movq 7*16(%%"REG_d"), %%mm4 \n\t" + "psubw %%mm7, %%mm0 \n\t" + + "psubw %%mm4, %%mm6 \n\t" + "paddusw %%mm2, %%mm5 \n\t" + + "paddusw %%mm4, %%mm6 \n\t" + "paddw %%mm3, %%mm1 \n\t" + + "paddw %%mm2, %%mm5 \n\t" + "paddw %%mm4, %%mm6 \n\t" + + "psubusw %%mm3, %%mm1 \n\t" + "psubusw %%mm2, %%mm5 \n\t" + + "psubusw %%mm4, %%mm6 \n\t" + "movq %%mm1, %%mm4 \n\t" + + "por %%mm5, %%mm4 \n\t" + "paddusw %%mm7, %%mm0 \n\t" + + "por %%mm6, %%mm4 \n\t" + "paddw %%mm7, %%mm0 \n\t" + + "packssdw %%mm4, %%mm4 \n\t" + "psubusw %%mm7, %%mm0 \n\t" + + "movd %%mm4, %%"REG_a" \n\t" + "or %%"REG_a", %%"REG_a" \n\t" + "jnz 2f \n\t" + //movq [edi+"DCTSIZE_S"*3*2], mm1 + //movq [edi+"DCTSIZE_S"*5*2], mm5 + //movq [edi+"DCTSIZE_S"*1*2], mm0 + //movq [edi+"DCTSIZE_S"*7*2], mm6 + // t4 t5 - - - t6 t7 - + //--- t4 (mm0) may be <>0; mm1, mm5, mm6 == 0 +//Typical numbers: nondc - 19%%, dc - 26%%, zero - 55%%. zero case alone isn't worthwhile + "movq 0*8+%3, %%mm4 \n\t" + "movq %%mm0, %%mm1 \n\t" + + "pmulhw "MANGLE(MM_FIX_0_847759065)", %%mm0 \n\t" //tmp6 + "movq %%mm1, %%mm2 \n\t" + + "movq "DCTSIZE_S"*0*2(%%"REG_D"), %%mm5 \n\t" + "movq %%mm2, %%mm3 \n\t" + + "pmulhw "MANGLE(MM_FIX_0_566454497)", %%mm1 \n\t" //tmp5 + "paddw %%mm4, %%mm5 \n\t" + + "movq 1*8+%3, %%mm6 \n\t" + //paddw mm3, MM_2 + "psraw $2, %%mm3 \n\t" //tmp7 + + "pmulhw "MANGLE(MM_FIX_0_198912367)", %%mm2 \n\t" //-tmp4 + "psubw %%mm3, %%mm4 \n\t" + + "movq "DCTSIZE_S"*1*2(%%"REG_D"), %%mm7 \n\t" + "paddw %%mm3, %%mm5 \n\t" + + "movq %%mm4, "DCTSIZE_S"*7*2(%%"REG_D") \n\t" + "paddw %%mm6, %%mm7 \n\t" + + "movq 2*8+%3, %%mm3 \n\t" + "psubw %%mm0, %%mm6 \n\t" + + "movq "DCTSIZE_S"*2*2(%%"REG_D"), %%mm4 \n\t" + "paddw %%mm0, %%mm7 \n\t" + + "movq %%mm5, "DCTSIZE_S"*0*2(%%"REG_D") \n\t" + "paddw %%mm3, %%mm4 \n\t" + + "movq %%mm6, "DCTSIZE_S"*6*2(%%"REG_D") \n\t" + "psubw %%mm1, %%mm3 \n\t" + + "movq "DCTSIZE_S"*5*2(%%"REG_D"), %%mm5 \n\t" + "paddw %%mm1, %%mm4 \n\t" + + "movq "DCTSIZE_S"*3*2(%%"REG_D"), %%mm6 \n\t" + "paddw %%mm3, %%mm5 \n\t" + + "movq 3*8+%3, %%mm0 \n\t" + "add $8, %%"REG_S" \n\t" + + "movq %%mm7, "DCTSIZE_S"*1*2(%%"REG_D") \n\t" + "paddw %%mm0, %%mm6 \n\t" + + "movq %%mm4, "DCTSIZE_S"*2*2(%%"REG_D") \n\t" + "psubw %%mm2, %%mm0 \n\t" + + "movq "DCTSIZE_S"*4*2(%%"REG_D"), %%mm7 \n\t" + "paddw %%mm2, %%mm6 \n\t" + + "movq %%mm5, "DCTSIZE_S"*5*2(%%"REG_D") \n\t" + "paddw %%mm0, %%mm7 \n\t" + + "movq %%mm6, "DCTSIZE_S"*3*2(%%"REG_D") \n\t" + + "movq %%mm7, "DCTSIZE_S"*4*2(%%"REG_D") \n\t" + "add $8, %%"REG_D" \n\t" + "jmp 4f \n\t" + + "2: \n\t" + //--- non DC2 + //psraw mm1, 2 w/o it -> offset. thr1, thr1, thr1 (actually thr1, thr1, thr1-1) + //psraw mm5, 2 + //psraw mm0, 2 + //psraw mm6, 2 + "movq %%mm5, %%mm3 \n\t" + "psubw %%mm1, %%mm5 \n\t" + + "psllw $1, %%mm5 \n\t" //'z10 + "paddw %%mm1, %%mm3 \n\t" //'z13 + + "movq %%mm0, %%mm2 \n\t" + "psubw %%mm6, %%mm0 \n\t" + + "movq %%mm5, %%mm1 \n\t" + "psllw $1, %%mm0 \n\t" //'z12 + + "pmulhw "MANGLE(MM_FIX_2_613125930)", %%mm1 \n\t" //- + "paddw %%mm0, %%mm5 \n\t" + + "pmulhw "MANGLE(MM_FIX_1_847759065)", %%mm5 \n\t" //'z5 + "paddw %%mm6, %%mm2 \n\t" //'z11 + + "pmulhw "MANGLE(MM_FIX_1_082392200)", %%mm0 \n\t" + "movq %%mm2, %%mm7 \n\t" + + //--- + "movq 0*8+%3, %%mm4 \n\t" + "psubw %%mm3, %%mm2 \n\t" + + "psllw $1, %%mm2 \n\t" + "paddw %%mm3, %%mm7 \n\t" //'t7 + + "pmulhw "MANGLE(MM_FIX_1_414213562)", %%mm2 \n\t" //'t11 + "movq %%mm4, %%mm6 \n\t" + //paddw mm7, MM_2 + "psraw $2, %%mm7 \n\t" + + "paddw "DCTSIZE_S"*0*2(%%"REG_D"), %%mm4 \n\t" + "psubw %%mm7, %%mm6 \n\t" + + "movq 1*8+%3, %%mm3 \n\t" + "paddw %%mm7, %%mm4 \n\t" + + "movq %%mm6, "DCTSIZE_S"*7*2(%%"REG_D") \n\t" + "paddw %%mm5, %%mm1 \n\t" //'t12 + + "movq %%mm4, "DCTSIZE_S"*0*2(%%"REG_D") \n\t" + "psubw %%mm7, %%mm1 \n\t" //'t6 + + "movq 2*8+%3, %%mm7 \n\t" + "psubw %%mm5, %%mm0 \n\t" //'t10 + + "movq 3*8+%3, %%mm6 \n\t" + "movq %%mm3, %%mm5 \n\t" + + "paddw "DCTSIZE_S"*1*2(%%"REG_D"), %%mm3 \n\t" + "psubw %%mm1, %%mm5 \n\t" + + "psubw %%mm1, %%mm2 \n\t" //'t5 + "paddw %%mm1, %%mm3 \n\t" + + "movq %%mm5, "DCTSIZE_S"*6*2(%%"REG_D") \n\t" + "movq %%mm7, %%mm4 \n\t" + + "paddw "DCTSIZE_S"*2*2(%%"REG_D"), %%mm7 \n\t" + "psubw %%mm2, %%mm4 \n\t" + + "paddw "DCTSIZE_S"*5*2(%%"REG_D"), %%mm4 \n\t" + "paddw %%mm2, %%mm7 \n\t" + + "movq %%mm3, "DCTSIZE_S"*1*2(%%"REG_D") \n\t" + "paddw %%mm2, %%mm0 \n\t" //'t4 + + // 't4 't6 't5 - - - - 't7 + "movq %%mm7, "DCTSIZE_S"*2*2(%%"REG_D") \n\t" + "movq %%mm6, %%mm1 \n\t" + + "paddw "DCTSIZE_S"*4*2(%%"REG_D"), %%mm6 \n\t" + "psubw %%mm0, %%mm1 \n\t" + + "paddw "DCTSIZE_S"*3*2(%%"REG_D"), %%mm1 \n\t" + "paddw %%mm0, %%mm6 \n\t" + + "movq %%mm4, "DCTSIZE_S"*5*2(%%"REG_D") \n\t" + "add $8, %%"REG_S" \n\t" + + "movq %%mm6, "DCTSIZE_S"*4*2(%%"REG_D") \n\t" + + "movq %%mm1, "DCTSIZE_S"*3*2(%%"REG_D") \n\t" + "add $8, %%"REG_D" \n\t" + + "4: \n\t" +//=part 2 (the same)=========================================================== + "movq "DCTSIZE_S"*0*2(%%"REG_S"), %%mm1 \n\t" + // + "movq "DCTSIZE_S"*3*2(%%"REG_S"), %%mm7 \n\t" + "movq %%mm1, %%mm0 \n\t" + + "paddw "DCTSIZE_S"*7*2(%%"REG_S"), %%mm1 \n\t" //t0 + "movq %%mm7, %%mm3 \n\t" + + "paddw "DCTSIZE_S"*4*2(%%"REG_S"), %%mm7 \n\t" //t3 + "movq %%mm1, %%mm5 \n\t" + + "movq "DCTSIZE_S"*1*2(%%"REG_S"), %%mm6 \n\t" + "psubw %%mm7, %%mm1 \n\t" //t13 + + "movq "DCTSIZE_S"*2*2(%%"REG_S"), %%mm2 \n\t" + "movq %%mm6, %%mm4 \n\t" + + "paddw "DCTSIZE_S"*6*2(%%"REG_S"), %%mm6 \n\t" //t1 + "paddw %%mm7, %%mm5 \n\t" //t10 + + "paddw "DCTSIZE_S"*5*2(%%"REG_S"), %%mm2 \n\t" //t2 + "movq %%mm6, %%mm7 \n\t" + + "paddw %%mm2, %%mm6 \n\t" //t11 + "psubw %%mm2, %%mm7 \n\t" //t12 + + "movq %%mm5, %%mm2 \n\t" + "paddw %%mm6, %%mm5 \n\t" //d0 + // i0 t13 t12 i3 i1 d0 - d4 + "psubw %%mm6, %%mm2 \n\t" //d4 + "paddw %%mm1, %%mm7 \n\t" + + "movq 1*8+4*16(%%"REG_d"), %%mm6 \n\t" + "psllw $2, %%mm7 \n\t" + + "psubw 1*8+0*16(%%"REG_d"), %%mm5 \n\t" + "psubw %%mm6, %%mm2 \n\t" + + "paddusw 1*8+0*16(%%"REG_d"), %%mm5 \n\t" + "paddusw %%mm6, %%mm2 \n\t" + + "pmulhw "MANGLE(MM_FIX_0_707106781)", %%mm7 \n\t" + // + "paddw 1*8+0*16(%%"REG_d"), %%mm5 \n\t" + "paddw %%mm6, %%mm2 \n\t" + + "psubusw 1*8+0*16(%%"REG_d"), %%mm5 \n\t" + "psubusw %%mm6, %%mm2 \n\t" + +//This func is totally compute-bound, operates at huge speed. So, DC shortcut +// at this place isn't worthwhile due to BTB miss penalty (checked on Pent. 3). +//However, typical numbers: nondc - 29%%, dc - 46%%, zero - 25%%. All <> 0 case is very rare. + "paddw "MANGLE(MM_2)", %%mm5 \n\t" + "movq %%mm2, %%mm6 \n\t" + + "paddw %%mm5, %%mm2 \n\t" + "psubw %%mm6, %%mm5 \n\t" + + "movq %%mm1, %%mm6 \n\t" + "paddw %%mm7, %%mm1 \n\t" //d2 + + "psubw 1*8+2*16(%%"REG_d"), %%mm1 \n\t" + "psubw %%mm7, %%mm6 \n\t" //d6 + + "movq 1*8+6*16(%%"REG_d"), %%mm7 \n\t" + "psraw $2, %%mm5 \n\t" + + "paddusw 1*8+2*16(%%"REG_d"), %%mm1 \n\t" + "psubw %%mm7, %%mm6 \n\t" + // t7 d2 /t11 t4 t6 - d6 /t10 + + "paddw 1*8+2*16(%%"REG_d"), %%mm1 \n\t" + "paddusw %%mm7, %%mm6 \n\t" + + "psubusw 1*8+2*16(%%"REG_d"), %%mm1 \n\t" + "paddw %%mm7, %%mm6 \n\t" + + "psubw "DCTSIZE_S"*4*2(%%"REG_S"), %%mm3 \n\t" + "psubusw %%mm7, %%mm6 \n\t" + + //movq [edi+"DCTSIZE_S"*2*2], mm1 + //movq [edi+"DCTSIZE_S"*6*2], mm6 + "movq %%mm1, %%mm7 \n\t" + "psraw $2, %%mm2 \n\t" + + "psubw "DCTSIZE_S"*6*2(%%"REG_S"), %%mm4 \n\t" + "psubw %%mm6, %%mm1 \n\t" + + "psubw "DCTSIZE_S"*7*2(%%"REG_S"), %%mm0 \n\t" + "paddw %%mm7, %%mm6 \n\t" //'t13 + + "psraw $2, %%mm6 \n\t" //paddw mm6, MM_2 !! --- + "movq %%mm2, %%mm7 \n\t" + + "pmulhw "MANGLE(MM_FIX_1_414213562_A)", %%mm1 \n\t" + "paddw %%mm6, %%mm2 \n\t" //'t0 + + "movq %%mm2, 0*8+%3 \n\t" //! + "psubw %%mm6, %%mm7 \n\t" //'t3 + + "movq "DCTSIZE_S"*2*2(%%"REG_S"), %%mm2 \n\t" + "psubw %%mm6, %%mm1 \n\t" //'t12 + + "psubw "DCTSIZE_S"*5*2(%%"REG_S"), %%mm2 \n\t" //t5 + "movq %%mm5, %%mm6 \n\t" + + "movq %%mm7, 3*8+%3 \n\t" + "paddw %%mm2, %%mm3 \n\t" //t10 + + "paddw %%mm4, %%mm2 \n\t" //t11 + "paddw %%mm0, %%mm4 \n\t" //t12 + + "movq %%mm3, %%mm7 \n\t" + "psubw %%mm4, %%mm3 \n\t" + + "psllw $2, %%mm3 \n\t" + "psllw $2, %%mm7 \n\t" //opt for P6 + + "pmulhw "MANGLE(MM_FIX_0_382683433)", %%mm3 \n\t" + "psllw $2, %%mm4 \n\t" + + "pmulhw "MANGLE(MM_FIX_0_541196100)", %%mm7 \n\t" + "psllw $2, %%mm2 \n\t" + + "pmulhw "MANGLE(MM_FIX_1_306562965)", %%mm4 \n\t" + "paddw %%mm1, %%mm5 \n\t" //'t1 + + "pmulhw "MANGLE(MM_FIX_0_707106781)", %%mm2 \n\t" + "psubw %%mm1, %%mm6 \n\t" //'t2 + // t7 't12 't11 t4 t6 - 't13 't10 --- + + "paddw %%mm3, %%mm7 \n\t" //z2 + + "movq %%mm5, 1*8+%3 \n\t" + "paddw %%mm3, %%mm4 \n\t" //z4 + + "movq 1*8+3*16(%%"REG_d"), %%mm3 \n\t" + "movq %%mm0, %%mm1 \n\t" + + "movq %%mm6, 2*8+%3 \n\t" + "psubw %%mm2, %%mm1 \n\t" //z13 + +//=== + "paddw %%mm2, %%mm0 \n\t" //z11 + "movq %%mm1, %%mm5 \n\t" + + "movq 1*8+5*16(%%"REG_d"), %%mm2 \n\t" + "psubw %%mm7, %%mm1 \n\t" //d3 + + "paddw %%mm7, %%mm5 \n\t" //d5 + "psubw %%mm3, %%mm1 \n\t" + + "movq 1*8+1*16(%%"REG_d"), %%mm7 \n\t" + "psubw %%mm2, %%mm5 \n\t" + + "movq %%mm0, %%mm6 \n\t" + "paddw %%mm4, %%mm0 \n\t" //d1 + + "paddusw %%mm3, %%mm1 \n\t" + "psubw %%mm4, %%mm6 \n\t" //d7 + + // d1 d3 - - - d5 d7 - + "movq 1*8+7*16(%%"REG_d"), %%mm4 \n\t" + "psubw %%mm7, %%mm0 \n\t" + + "psubw %%mm4, %%mm6 \n\t" + "paddusw %%mm2, %%mm5 \n\t" + + "paddusw %%mm4, %%mm6 \n\t" + "paddw %%mm3, %%mm1 \n\t" + + "paddw %%mm2, %%mm5 \n\t" + "paddw %%mm4, %%mm6 \n\t" + + "psubusw %%mm3, %%mm1 \n\t" + "psubusw %%mm2, %%mm5 \n\t" + + "psubusw %%mm4, %%mm6 \n\t" + "movq %%mm1, %%mm4 \n\t" + + "por %%mm5, %%mm4 \n\t" + "paddusw %%mm7, %%mm0 \n\t" + + "por %%mm6, %%mm4 \n\t" + "paddw %%mm7, %%mm0 \n\t" + + "packssdw %%mm4, %%mm4 \n\t" + "psubusw %%mm7, %%mm0 \n\t" + + "movd %%mm4, %%"REG_a" \n\t" + "or %%"REG_a", %%"REG_a" \n\t" + "jnz 3f \n\t" + //movq [edi+"DCTSIZE_S"*3*2], mm1 + //movq [edi+"DCTSIZE_S"*5*2], mm5 + //movq [edi+"DCTSIZE_S"*1*2], mm0 + //movq [edi+"DCTSIZE_S"*7*2], mm6 + // t4 t5 - - - t6 t7 - + //--- t4 (mm0) may be <>0; mm1, mm5, mm6 == 0 +//Typical numbers: nondc - 19%%, dc - 26%%, zero - 55%%. zero case alone isn't worthwhile + "movq 0*8+%3, %%mm4 \n\t" + "movq %%mm0, %%mm1 \n\t" + + "pmulhw "MANGLE(MM_FIX_0_847759065)", %%mm0 \n\t" //tmp6 + "movq %%mm1, %%mm2 \n\t" + + "movq "DCTSIZE_S"*0*2(%%"REG_D"), %%mm5 \n\t" + "movq %%mm2, %%mm3 \n\t" + + "pmulhw "MANGLE(MM_FIX_0_566454497)", %%mm1 \n\t" //tmp5 + "paddw %%mm4, %%mm5 \n\t" + + "movq 1*8+%3, %%mm6 \n\t" + //paddw mm3, MM_2 + "psraw $2, %%mm3 \n\t" //tmp7 + + "pmulhw "MANGLE(MM_FIX_0_198912367)", %%mm2 \n\t" //-tmp4 + "psubw %%mm3, %%mm4 \n\t" + + "movq "DCTSIZE_S"*1*2(%%"REG_D"), %%mm7 \n\t" + "paddw %%mm3, %%mm5 \n\t" + + "movq %%mm4, "DCTSIZE_S"*7*2(%%"REG_D") \n\t" + "paddw %%mm6, %%mm7 \n\t" + + "movq 2*8+%3, %%mm3 \n\t" + "psubw %%mm0, %%mm6 \n\t" + + "movq "DCTSIZE_S"*2*2(%%"REG_D"), %%mm4 \n\t" + "paddw %%mm0, %%mm7 \n\t" + + "movq %%mm5, "DCTSIZE_S"*0*2(%%"REG_D") \n\t" + "paddw %%mm3, %%mm4 \n\t" + + "movq %%mm6, "DCTSIZE_S"*6*2(%%"REG_D") \n\t" + "psubw %%mm1, %%mm3 \n\t" + + "movq "DCTSIZE_S"*5*2(%%"REG_D"), %%mm5 \n\t" + "paddw %%mm1, %%mm4 \n\t" + + "movq "DCTSIZE_S"*3*2(%%"REG_D"), %%mm6 \n\t" + "paddw %%mm3, %%mm5 \n\t" + + "movq 3*8+%3, %%mm0 \n\t" + "add $24, %%"REG_S" \n\t" + + "movq %%mm7, "DCTSIZE_S"*1*2(%%"REG_D") \n\t" + "paddw %%mm0, %%mm6 \n\t" + + "movq %%mm4, "DCTSIZE_S"*2*2(%%"REG_D") \n\t" + "psubw %%mm2, %%mm0 \n\t" + + "movq "DCTSIZE_S"*4*2(%%"REG_D"), %%mm7 \n\t" + "paddw %%mm2, %%mm6 \n\t" + + "movq %%mm5, "DCTSIZE_S"*5*2(%%"REG_D") \n\t" + "paddw %%mm0, %%mm7 \n\t" + + "movq %%mm6, "DCTSIZE_S"*3*2(%%"REG_D") \n\t" + + "movq %%mm7, "DCTSIZE_S"*4*2(%%"REG_D") \n\t" + "add $24, %%"REG_D" \n\t" + "sub $2, %%"REG_c" \n\t" + "jnz 1b \n\t" + "jmp 5f \n\t" + + "3: \n\t" + //--- non DC2 + //psraw mm1, 2 w/o it -> offset. thr1, thr1, thr1 (actually thr1, thr1, thr1-1) + //psraw mm5, 2 + //psraw mm0, 2 + //psraw mm6, 2 + "movq %%mm5, %%mm3 \n\t" + "psubw %%mm1, %%mm5 \n\t" + + "psllw $1, %%mm5 \n\t" //'z10 + "paddw %%mm1, %%mm3 \n\t" //'z13 + + "movq %%mm0, %%mm2 \n\t" + "psubw %%mm6, %%mm0 \n\t" + + "movq %%mm5, %%mm1 \n\t" + "psllw $1, %%mm0 \n\t" //'z12 + + "pmulhw "MANGLE(MM_FIX_2_613125930)", %%mm1 \n\t" //- + "paddw %%mm0, %%mm5 \n\t" + + "pmulhw "MANGLE(MM_FIX_1_847759065)", %%mm5 \n\t" //'z5 + "paddw %%mm6, %%mm2 \n\t" //'z11 + + "pmulhw "MANGLE(MM_FIX_1_082392200)", %%mm0 \n\t" + "movq %%mm2, %%mm7 \n\t" + + //--- + "movq 0*8+%3, %%mm4 \n\t" + "psubw %%mm3, %%mm2 \n\t" + + "psllw $1, %%mm2 \n\t" + "paddw %%mm3, %%mm7 \n\t" //'t7 + + "pmulhw "MANGLE(MM_FIX_1_414213562)", %%mm2 \n\t" //'t11 + "movq %%mm4, %%mm6 \n\t" + //paddw mm7, MM_2 + "psraw $2, %%mm7 \n\t" + + "paddw "DCTSIZE_S"*0*2(%%"REG_D"), %%mm4 \n\t" + "psubw %%mm7, %%mm6 \n\t" + + "movq 1*8+%3, %%mm3 \n\t" + "paddw %%mm7, %%mm4 \n\t" + + "movq %%mm6, "DCTSIZE_S"*7*2(%%"REG_D") \n\t" + "paddw %%mm5, %%mm1 \n\t" //'t12 + + "movq %%mm4, "DCTSIZE_S"*0*2(%%"REG_D") \n\t" + "psubw %%mm7, %%mm1 \n\t" //'t6 + + "movq 2*8+%3, %%mm7 \n\t" + "psubw %%mm5, %%mm0 \n\t" //'t10 + + "movq 3*8+%3, %%mm6 \n\t" + "movq %%mm3, %%mm5 \n\t" + + "paddw "DCTSIZE_S"*1*2(%%"REG_D"), %%mm3 \n\t" + "psubw %%mm1, %%mm5 \n\t" + + "psubw %%mm1, %%mm2 \n\t" //'t5 + "paddw %%mm1, %%mm3 \n\t" + + "movq %%mm5, "DCTSIZE_S"*6*2(%%"REG_D") \n\t" + "movq %%mm7, %%mm4 \n\t" + + "paddw "DCTSIZE_S"*2*2(%%"REG_D"), %%mm7 \n\t" + "psubw %%mm2, %%mm4 \n\t" + + "paddw "DCTSIZE_S"*5*2(%%"REG_D"), %%mm4 \n\t" + "paddw %%mm2, %%mm7 \n\t" + + "movq %%mm3, "DCTSIZE_S"*1*2(%%"REG_D") \n\t" + "paddw %%mm2, %%mm0 \n\t" //'t4 + + // 't4 't6 't5 - - - - 't7 + "movq %%mm7, "DCTSIZE_S"*2*2(%%"REG_D") \n\t" + "movq %%mm6, %%mm1 \n\t" + + "paddw "DCTSIZE_S"*4*2(%%"REG_D"), %%mm6 \n\t" + "psubw %%mm0, %%mm1 \n\t" + + "paddw "DCTSIZE_S"*3*2(%%"REG_D"), %%mm1 \n\t" + "paddw %%mm0, %%mm6 \n\t" + + "movq %%mm4, "DCTSIZE_S"*5*2(%%"REG_D") \n\t" + "add $24, %%"REG_S" \n\t" + + "movq %%mm6, "DCTSIZE_S"*4*2(%%"REG_D") \n\t" + + "movq %%mm1, "DCTSIZE_S"*3*2(%%"REG_D") \n\t" + "add $24, %%"REG_D" \n\t" + "sub $2, %%"REG_c" \n\t" + "jnz 1b \n\t" + "5: \n\t" + + : "+S"(data), "+D"(output), "+c"(cnt), "=o"(temps) + : "d"(thr_adr) + : "%"REG_a + ); +} + +#endif // HAVE_MMX + +#if !HAVE_MMX + +static void row_idct_c(DCTELEM* workspace, + int16_t* output_adr, int output_stride, int cnt) +{ + int_simd16_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + int_simd16_t tmp10, tmp11, tmp12, tmp13; + int_simd16_t z5, z10, z11, z12, z13; + int16_t* outptr; + DCTELEM* wsptr; + + cnt*=4; + wsptr = workspace; + outptr = output_adr; + for (; cnt > 0; cnt--) { + // Even part + //Simd version reads 4x4 block and transposes it + tmp10 = ( wsptr[2] + wsptr[3]); + tmp11 = ( wsptr[2] - wsptr[3]); + + tmp13 = ( wsptr[0] + wsptr[1]); + tmp12 = (MULTIPLY16H( wsptr[0] - wsptr[1], FIX_1_414213562_A)<<2) - tmp13;//this shift order to avoid overflow + + tmp0 = tmp10 + tmp13; //->temps + tmp3 = tmp10 - tmp13; //->temps + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + // Odd part + //Also transpose, with previous: + // ---- ---- |||| + // ---- ---- idct |||| + // ---- ---- ---> |||| + // ---- ---- |||| + z13 = wsptr[4] + wsptr[5]; + z10 = wsptr[4] - wsptr[5]; + z11 = wsptr[6] + wsptr[7]; + z12 = wsptr[6] - wsptr[7]; + + tmp7 = z11 + z13; + tmp11 = MULTIPLY16H(z11 - z13, FIX_1_414213562); + + z5 = MULTIPLY16H(z10 + z12, FIX_1_847759065); + tmp10 = MULTIPLY16H(z12, FIX_1_082392200) - z5; + tmp12 = MULTIPLY16H(z10, FIX_2_613125930) + z5; // - FIX_ + + tmp6 = (tmp12<<3) - tmp7; + tmp5 = (tmp11<<3) - tmp6; + tmp4 = (tmp10<<3) + tmp5; + + // Final output stage: descale and write column + outptr[0*output_stride]+= DESCALE(tmp0 + tmp7, 3); + outptr[1*output_stride]+= DESCALE(tmp1 + tmp6, 3); + outptr[2*output_stride]+= DESCALE(tmp2 + tmp5, 3); + outptr[3*output_stride]+= DESCALE(tmp3 - tmp4, 3); + outptr[4*output_stride]+= DESCALE(tmp3 + tmp4, 3); + outptr[5*output_stride]+= DESCALE(tmp2 - tmp5, 3); + outptr[6*output_stride]+= DESCALE(tmp1 - tmp6, 3); //no += ? + outptr[7*output_stride]+= DESCALE(tmp0 - tmp7, 3); //no += ? + outptr++; + + wsptr += DCTSIZE; // advance pointer to next row + } +} + +#else /* HAVE_MMX */ + +static void row_idct_mmx (DCTELEM* workspace, + int16_t* output_adr, int output_stride, int cnt) +{ + uint64_t __attribute__((aligned(8))) temps[4]; + __asm__ volatile( + "lea (%%"REG_a",%%"REG_a",2), %%"REG_d" \n\t" + "1: \n\t" + "movq "DCTSIZE_S"*0*2(%%"REG_S"), %%mm0 \n\t" + // + + "movq "DCTSIZE_S"*1*2(%%"REG_S"), %%mm1 \n\t" + "movq %%mm0, %%mm4 \n\t" + + "movq "DCTSIZE_S"*2*2(%%"REG_S"), %%mm2 \n\t" + "punpcklwd %%mm1, %%mm0 \n\t" + + "movq "DCTSIZE_S"*3*2(%%"REG_S"), %%mm3 \n\t" + "punpckhwd %%mm1, %%mm4 \n\t" + + //transpose 4x4 + "movq %%mm2, %%mm7 \n\t" + "punpcklwd %%mm3, %%mm2 \n\t" + + "movq %%mm0, %%mm6 \n\t" + "punpckldq %%mm2, %%mm0 \n\t" //0 + + "punpckhdq %%mm2, %%mm6 \n\t" //1 + "movq %%mm0, %%mm5 \n\t" + + "punpckhwd %%mm3, %%mm7 \n\t" + "psubw %%mm6, %%mm0 \n\t" + + "pmulhw "MANGLE(MM_FIX_1_414213562_A)", %%mm0 \n\t" + "movq %%mm4, %%mm2 \n\t" + + "punpckldq %%mm7, %%mm4 \n\t" //2 + "paddw %%mm6, %%mm5 \n\t" + + "punpckhdq %%mm7, %%mm2 \n\t" //3 + "movq %%mm4, %%mm1 \n\t" + + "psllw $2, %%mm0 \n\t" + "paddw %%mm2, %%mm4 \n\t" //t10 + + "movq "DCTSIZE_S"*0*2+"DCTSIZE_S"(%%"REG_S"), %%mm3 \n\t" + "psubw %%mm2, %%mm1 \n\t" //t11 + + "movq "DCTSIZE_S"*1*2+"DCTSIZE_S"(%%"REG_S"), %%mm2 \n\t" + "psubw %%mm5, %%mm0 \n\t" + + "movq %%mm4, %%mm6 \n\t" + "paddw %%mm5, %%mm4 \n\t" //t0 + + "psubw %%mm5, %%mm6 \n\t" //t3 + "movq %%mm1, %%mm7 \n\t" + + "movq "DCTSIZE_S"*2*2+"DCTSIZE_S"(%%"REG_S"), %%mm5 \n\t" + "paddw %%mm0, %%mm1 \n\t" //t1 + + "movq %%mm4, 0*8+%3 \n\t" //t0 + "movq %%mm3, %%mm4 \n\t" + + "movq %%mm6, 1*8+%3 \n\t" //t3 + "punpcklwd %%mm2, %%mm3 \n\t" + + //transpose 4x4 + "movq "DCTSIZE_S"*3*2+"DCTSIZE_S"(%%"REG_S"), %%mm6 \n\t" + "punpckhwd %%mm2, %%mm4 \n\t" + + "movq %%mm5, %%mm2 \n\t" + "punpcklwd %%mm6, %%mm5 \n\t" + + "psubw %%mm0, %%mm7 \n\t" //t2 + "punpckhwd %%mm6, %%mm2 \n\t" + + "movq %%mm3, %%mm0 \n\t" + "punpckldq %%mm5, %%mm3 \n\t" //4 + + "punpckhdq %%mm5, %%mm0 \n\t" //5 + "movq %%mm4, %%mm5 \n\t" + + // + "movq %%mm3, %%mm6 \n\t" + "punpckldq %%mm2, %%mm4 \n\t" //6 + + "psubw %%mm0, %%mm3 \n\t" //z10 + "punpckhdq %%mm2, %%mm5 \n\t" //7 + + "paddw %%mm0, %%mm6 \n\t" //z13 + "movq %%mm4, %%mm2 \n\t" + + "movq %%mm3, %%mm0 \n\t" + "psubw %%mm5, %%mm4 \n\t" //z12 + + "pmulhw "MANGLE(MM_FIX_2_613125930)", %%mm0 \n\t" //- + "paddw %%mm4, %%mm3 \n\t" + + "pmulhw "MANGLE(MM_FIX_1_847759065)", %%mm3 \n\t" //z5 + "paddw %%mm5, %%mm2 \n\t" //z11 > + + "pmulhw "MANGLE(MM_FIX_1_082392200)", %%mm4 \n\t" + "movq %%mm2, %%mm5 \n\t" + + "psubw %%mm6, %%mm2 \n\t" + "paddw %%mm6, %%mm5 \n\t" //t7 + + "pmulhw "MANGLE(MM_FIX_1_414213562)", %%mm2 \n\t" //t11 + "paddw %%mm3, %%mm0 \n\t" //t12 + + "psllw $3, %%mm0 \n\t" + "psubw %%mm3, %%mm4 \n\t" //t10 + + "movq 0*8+%3, %%mm6 \n\t" + "movq %%mm1, %%mm3 \n\t" + + "psllw $3, %%mm4 \n\t" + "psubw %%mm5, %%mm0 \n\t" //t6 + + "psllw $3, %%mm2 \n\t" + "paddw %%mm0, %%mm1 \n\t" //d1 + + "psubw %%mm0, %%mm2 \n\t" //t5 + "psubw %%mm0, %%mm3 \n\t" //d6 + + "paddw %%mm2, %%mm4 \n\t" //t4 + "movq %%mm7, %%mm0 \n\t" + + "paddw %%mm2, %%mm7 \n\t" //d2 + "psubw %%mm2, %%mm0 \n\t" //d5 + + "movq "MANGLE(MM_DESCALE_RND)", %%mm2 \n\t" //4 + "psubw %%mm5, %%mm6 \n\t" //d7 + + "paddw 0*8+%3, %%mm5 \n\t" //d0 + "paddw %%mm2, %%mm1 \n\t" + + "paddw %%mm2, %%mm5 \n\t" + "psraw $3, %%mm1 \n\t" + + "paddw %%mm2, %%mm7 \n\t" + "psraw $3, %%mm5 \n\t" + + "paddw (%%"REG_D"), %%mm5 \n\t" + "psraw $3, %%mm7 \n\t" + + "paddw (%%"REG_D",%%"REG_a",), %%mm1 \n\t" + "paddw %%mm2, %%mm0 \n\t" + + "paddw (%%"REG_D",%%"REG_a",2), %%mm7 \n\t" + "paddw %%mm2, %%mm3 \n\t" + + "movq %%mm5, (%%"REG_D") \n\t" + "paddw %%mm2, %%mm6 \n\t" + + "movq %%mm1, (%%"REG_D",%%"REG_a",) \n\t" + "psraw $3, %%mm0 \n\t" + + "movq %%mm7, (%%"REG_D",%%"REG_a",2) \n\t" + "add %%"REG_d", %%"REG_D" \n\t" //3*ls + + "movq 1*8+%3, %%mm5 \n\t" //t3 + "psraw $3, %%mm3 \n\t" + + "paddw (%%"REG_D",%%"REG_a",2), %%mm0 \n\t" + "psubw %%mm4, %%mm5 \n\t" //d3 + + "paddw (%%"REG_D",%%"REG_d",), %%mm3 \n\t" + "psraw $3, %%mm6 \n\t" + + "paddw 1*8+%3, %%mm4 \n\t" //d4 + "paddw %%mm2, %%mm5 \n\t" + + "paddw (%%"REG_D",%%"REG_a",4), %%mm6 \n\t" + "paddw %%mm2, %%mm4 \n\t" + + "movq %%mm0, (%%"REG_D",%%"REG_a",2) \n\t" + "psraw $3, %%mm5 \n\t" + + "paddw (%%"REG_D"), %%mm5 \n\t" + "psraw $3, %%mm4 \n\t" + + "paddw (%%"REG_D",%%"REG_a",), %%mm4 \n\t" + "add $"DCTSIZE_S"*2*4, %%"REG_S" \n\t" //4 rows + + "movq %%mm3, (%%"REG_D",%%"REG_d",) \n\t" + "movq %%mm6, (%%"REG_D",%%"REG_a",4) \n\t" + "movq %%mm5, (%%"REG_D") \n\t" + "movq %%mm4, (%%"REG_D",%%"REG_a",) \n\t" + + "sub %%"REG_d", %%"REG_D" \n\t" + "add $8, %%"REG_D" \n\t" + "dec %%"REG_c" \n\t" + "jnz 1b \n\t" + + : "+S"(workspace), "+D"(output_adr), "+c"(cnt), "=o"(temps) + : "a"(output_stride*sizeof(short)) + : "%"REG_d + ); +} + +#endif // HAVE_MMX + +#if !HAVE_MMX + +static void row_fdct_c(DCTELEM *data, const uint8_t *pixels, int line_size, int cnt) +{ + int_simd16_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + int_simd16_t tmp10, tmp11, tmp12, tmp13; + int_simd16_t z1, z2, z3, z4, z5, z11, z13; + DCTELEM *dataptr; + + cnt*=4; + // Pass 1: process rows. + + dataptr = data; + for (; cnt > 0; cnt--) { + tmp0 = pixels[line_size*0] + pixels[line_size*7]; + tmp7 = pixels[line_size*0] - pixels[line_size*7]; + tmp1 = pixels[line_size*1] + pixels[line_size*6]; + tmp6 = pixels[line_size*1] - pixels[line_size*6]; + tmp2 = pixels[line_size*2] + pixels[line_size*5]; + tmp5 = pixels[line_size*2] - pixels[line_size*5]; + tmp3 = pixels[line_size*3] + pixels[line_size*4]; + tmp4 = pixels[line_size*3] - pixels[line_size*4]; + + // Even part + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + //Even columns are written first, this leads to different order of columns + //in column_fidct(), but they are processed independently, so all ok. + //Later in the row_idct() columns readed at the same order. + dataptr[2] = tmp10 + tmp11; + dataptr[3] = tmp10 - tmp11; + + z1 = MULTIPLY16H((tmp12 + tmp13)<<2, FIX_0_707106781); + dataptr[0] = tmp13 + z1; + dataptr[1] = tmp13 - z1; + + // Odd part + + tmp10 = (tmp4 + tmp5) <<2; + tmp11 = (tmp5 + tmp6) <<2; + tmp12 = (tmp6 + tmp7) <<2; + + z5 = MULTIPLY16H(tmp10 - tmp12, FIX_0_382683433); + z2 = MULTIPLY16H(tmp10, FIX_0_541196100) + z5; + z4 = MULTIPLY16H(tmp12, FIX_1_306562965) + z5; + z3 = MULTIPLY16H(tmp11, FIX_0_707106781); + + z11 = tmp7 + z3; + z13 = tmp7 - z3; + + dataptr[4] = z13 + z2; + dataptr[5] = z13 - z2; + dataptr[6] = z11 + z4; + dataptr[7] = z11 - z4; + + pixels++; // advance pointer to next column + dataptr += DCTSIZE; + } +} + +#else /* HAVE_MMX */ + +static void row_fdct_mmx(DCTELEM *data, const uint8_t *pixels, int line_size, int cnt) +{ + uint64_t __attribute__((aligned(8))) temps[4]; + __asm__ volatile( + "lea (%%"REG_a",%%"REG_a",2), %%"REG_d" \n\t" + "6: \n\t" + "movd (%%"REG_S"), %%mm0 \n\t" + "pxor %%mm7, %%mm7 \n\t" + + "movd (%%"REG_S",%%"REG_a",), %%mm1 \n\t" + "punpcklbw %%mm7, %%mm0 \n\t" + + "movd (%%"REG_S",%%"REG_a",2), %%mm2 \n\t" + "punpcklbw %%mm7, %%mm1 \n\t" + + "punpcklbw %%mm7, %%mm2 \n\t" + "add %%"REG_d", %%"REG_S" \n\t" + + "movq %%mm0, %%mm5 \n\t" + // + + "movd (%%"REG_S",%%"REG_a",4), %%mm3 \n\t" //7 ;prefetch! + "movq %%mm1, %%mm6 \n\t" + + "movd (%%"REG_S",%%"REG_d",), %%mm4 \n\t" //6 + "punpcklbw %%mm7, %%mm3 \n\t" + + "psubw %%mm3, %%mm5 \n\t" + "punpcklbw %%mm7, %%mm4 \n\t" + + "paddw %%mm3, %%mm0 \n\t" + "psubw %%mm4, %%mm6 \n\t" + + "movd (%%"REG_S",%%"REG_a",2), %%mm3 \n\t" //5 + "paddw %%mm4, %%mm1 \n\t" + + "movq %%mm5, 0*8+%3 \n\t" //t7 + "punpcklbw %%mm7, %%mm3 \n\t" + + "movq %%mm6, 1*8+%3 \n\t" //t6 + "movq %%mm2, %%mm4 \n\t" + + "movd (%%"REG_S"), %%mm5 \n\t" //3 + "paddw %%mm3, %%mm2 \n\t" + + "movd (%%"REG_S",%%"REG_a",), %%mm6 \n\t" //4 + "punpcklbw %%mm7, %%mm5 \n\t" + + "psubw %%mm3, %%mm4 \n\t" + "punpcklbw %%mm7, %%mm6 \n\t" + + "movq %%mm5, %%mm3 \n\t" + "paddw %%mm6, %%mm5 \n\t" //t3 + + "psubw %%mm6, %%mm3 \n\t" //t4 ; t0 t1 t2 t4 t5 t3 - - + "movq %%mm0, %%mm6 \n\t" + + "movq %%mm1, %%mm7 \n\t" + "psubw %%mm5, %%mm0 \n\t" //t13 + + "psubw %%mm2, %%mm1 \n\t" + "paddw %%mm2, %%mm7 \n\t" //t11 + + "paddw %%mm0, %%mm1 \n\t" + "movq %%mm7, %%mm2 \n\t" + + "psllw $2, %%mm1 \n\t" + "paddw %%mm5, %%mm6 \n\t" //t10 + + "pmulhw "MANGLE(MM_FIX_0_707106781)", %%mm1 \n\t" + "paddw %%mm6, %%mm7 \n\t" //d2 + + "psubw %%mm2, %%mm6 \n\t" //d3 + "movq %%mm0, %%mm5 \n\t" + + //transpose 4x4 + "movq %%mm7, %%mm2 \n\t" + "punpcklwd %%mm6, %%mm7 \n\t" + + "paddw %%mm1, %%mm0 \n\t" //d0 + "punpckhwd %%mm6, %%mm2 \n\t" + + "psubw %%mm1, %%mm5 \n\t" //d1 + "movq %%mm0, %%mm6 \n\t" + + "movq 1*8+%3, %%mm1 \n\t" + "punpcklwd %%mm5, %%mm0 \n\t" + + "punpckhwd %%mm5, %%mm6 \n\t" + "movq %%mm0, %%mm5 \n\t" + + "punpckldq %%mm7, %%mm0 \n\t" //0 + "paddw %%mm4, %%mm3 \n\t" + + "punpckhdq %%mm7, %%mm5 \n\t" //1 + "movq %%mm6, %%mm7 \n\t" + + "movq %%mm0, "DCTSIZE_S"*0*2(%%"REG_D") \n\t" + "punpckldq %%mm2, %%mm6 \n\t" //2 + + "movq %%mm5, "DCTSIZE_S"*1*2(%%"REG_D") \n\t" + "punpckhdq %%mm2, %%mm7 \n\t" //3 + + "movq %%mm6, "DCTSIZE_S"*2*2(%%"REG_D") \n\t" + "paddw %%mm1, %%mm4 \n\t" + + "movq %%mm7, "DCTSIZE_S"*3*2(%%"REG_D") \n\t" + "psllw $2, %%mm3 \n\t" //t10 + + "movq 0*8+%3, %%mm2 \n\t" + "psllw $2, %%mm4 \n\t" //t11 + + "pmulhw "MANGLE(MM_FIX_0_707106781)", %%mm4 \n\t" //z3 + "paddw %%mm2, %%mm1 \n\t" + + "psllw $2, %%mm1 \n\t" //t12 + "movq %%mm3, %%mm0 \n\t" + + "pmulhw "MANGLE(MM_FIX_0_541196100)", %%mm0 \n\t" + "psubw %%mm1, %%mm3 \n\t" + + "pmulhw "MANGLE(MM_FIX_0_382683433)", %%mm3 \n\t" //z5 + "movq %%mm2, %%mm5 \n\t" + + "pmulhw "MANGLE(MM_FIX_1_306562965)", %%mm1 \n\t" + "psubw %%mm4, %%mm2 \n\t" //z13 + + "paddw %%mm4, %%mm5 \n\t" //z11 + "movq %%mm2, %%mm6 \n\t" + + "paddw %%mm3, %%mm0 \n\t" //z2 + "movq %%mm5, %%mm7 \n\t" + + "paddw %%mm0, %%mm2 \n\t" //d4 + "psubw %%mm0, %%mm6 \n\t" //d5 + + "movq %%mm2, %%mm4 \n\t" + "paddw %%mm3, %%mm1 \n\t" //z4 + + //transpose 4x4 + "punpcklwd %%mm6, %%mm2 \n\t" + "paddw %%mm1, %%mm5 \n\t" //d6 + + "punpckhwd %%mm6, %%mm4 \n\t" + "psubw %%mm1, %%mm7 \n\t" //d7 + + "movq %%mm5, %%mm6 \n\t" + "punpcklwd %%mm7, %%mm5 \n\t" + + "punpckhwd %%mm7, %%mm6 \n\t" + "movq %%mm2, %%mm7 \n\t" + + "punpckldq %%mm5, %%mm2 \n\t" //4 + "sub %%"REG_d", %%"REG_S" \n\t" + + "punpckhdq %%mm5, %%mm7 \n\t" //5 + "movq %%mm4, %%mm5 \n\t" + + "movq %%mm2, "DCTSIZE_S"*0*2+"DCTSIZE_S"(%%"REG_D") \n\t" + "punpckldq %%mm6, %%mm4 \n\t" //6 + + "movq %%mm7, "DCTSIZE_S"*1*2+"DCTSIZE_S"(%%"REG_D") \n\t" + "punpckhdq %%mm6, %%mm5 \n\t" //7 + + "movq %%mm4, "DCTSIZE_S"*2*2+"DCTSIZE_S"(%%"REG_D") \n\t" + "add $4, %%"REG_S" \n\t" + + "movq %%mm5, "DCTSIZE_S"*3*2+"DCTSIZE_S"(%%"REG_D") \n\t" + "add $"DCTSIZE_S"*2*4, %%"REG_D" \n\t" //4 rows + "dec %%"REG_c" \n\t" + "jnz 6b \n\t" + + : "+S"(pixels), "+D"(data), "+c"(cnt), "=o"(temps) + : "a"(line_size) + : "%"REG_d); +} + +#endif // HAVE_MMX diff --git a/libavfilter/libmpcodecs/vf_geq.c b/libavfilter/libmpcodecs/vf_geq.c new file mode 100644 index 0000000000..2102c87f55 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_geq.c @@ -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_expr_eval(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_expr_parse(&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 +}; diff --git a/libavfilter/libmpcodecs/vf_gradfun.c b/libavfilter/libmpcodecs/vf_gradfun.c new file mode 100644 index 0000000000..fd4236cc37 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_gradfun.c @@ -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_SSE && 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_SSE + +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_SSE && 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 +}; diff --git a/libavfilter/libmpcodecs/vf_harddup.c b/libavfilter/libmpcodecs/vf_harddup.c new file mode 100644 index 0000000000..5b6c2ff010 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_harddup.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_hqdn3d.c b/libavfilter/libmpcodecs/vf_hqdn3d.c new file mode 100644 index 0000000000..eba3439d88 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_hqdn3d.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_hue.c b/libavfilter/libmpcodecs/vf_hue.c new file mode 100644 index 0000000000..9a8fc8b61b --- /dev/null +++ b/libavfilter/libmpcodecs/vf_hue.c @@ -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 <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" + +struct vf_priv_s { + uint8_t *buf[2]; + float hue; + float saturation; +}; + +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 = malloc(sizeof(struct vf_priv_s)); + memset(vf->priv, 0, sizeof(struct vf_priv_s)); + sscanf(args, "%f:%f", &vf->priv->hue, &vf->priv->saturation); + vf->priv->hue *= M_PI / 180.0; + + process = process_C; + return 1; +} + +const vf_info_t vf_info_hue = { + "hue changer", + "hue", + "Michael Niedermayer", + "", + vf_open, +}; diff --git a/libavfilter/libmpcodecs/vf_il.c b/libavfilter/libmpcodecs/vf_il.c new file mode 100644 index 0000000000..210e30d3f6 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_il.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_ilpack.c b/libavfilter/libmpcodecs/vf_ilpack.c new file mode 100644 index 0000000000..db4a849e1f --- /dev/null +++ b/libavfilter/libmpcodecs/vf_ilpack.c @@ -0,0 +1,456 @@ +/* + * 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 "libavutil/attributes.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 av_unused us, int av_unused vs) +{ + 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, + int av_unused us, int av_unused vs) +{ + __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), 0, 0); +} + +#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_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_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 +}; diff --git a/libavfilter/libmpcodecs/vf_ivtc.c b/libavfilter/libmpcodecs/vf_ivtc.c new file mode 100644 index 0000000000..b10e50561a --- /dev/null +++ b/libavfilter/libmpcodecs/vf_ivtc.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_kerndeint.c b/libavfilter/libmpcodecs/vf_kerndeint.c new file mode 100644 index 0000000000..c5197fc542 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_kerndeint.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_mcdeint.c b/libavfilter/libmpcodecs/vf_mcdeint.c new file mode 100644 index 0000000000..aad2afdfad --- /dev/null +++ b/libavfilter/libmpcodecs/vf_mcdeint.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_mirror.c b/libavfilter/libmpcodecs/vf_mirror.c new file mode 100644 index 0000000000..5ac05e9145 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_mirror.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_noise.c b/libavfilter/libmpcodecs/vf_noise.c new file mode 100644 index 0000000000..9521619aed --- /dev/null +++ b/libavfilter/libmpcodecs/vf_noise.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_ow.c b/libavfilter/libmpcodecs/vf_ow.c new file mode 100644 index 0000000000..f7fb02db72 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_ow.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_palette.c b/libavfilter/libmpcodecs/vf_palette.c new file mode 100644 index 0000000000..3a7f0869bf --- /dev/null +++ b/libavfilter/libmpcodecs/vf_palette.c @@ -0,0 +1,236 @@ +/* + * 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. + */ + +#define _BSD_SOURCE //strcasecmp +#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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_perspective.c b/libavfilter/libmpcodecs/vf_perspective.c new file mode 100644 index 0000000000..f6c6dd60d7 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_perspective.c @@ -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= av_malloc(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; + + av_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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_phase.c b/libavfilter/libmpcodecs/vf_phase.c new file mode 100644 index 0000000000..7dd642ebc0 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_phase.c @@ -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 + }; diff --git a/libavfilter/libmpcodecs/vf_pp7.c b/libavfilter/libmpcodecs/vf_pp7.c new file mode 100644 index 0000000000..c075d6619c --- /dev/null +++ b/libavfilter/libmpcodecs/vf_pp7.c @@ -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= (DCTELEM *)p->src; + DCTELEM *temp= (DCTELEM *)(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 = av_malloc(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; + + av_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 +}; diff --git a/libavfilter/libmpcodecs/vf_pullup.c b/libavfilter/libmpcodecs/vf_pullup.c new file mode 100644 index 0000000000..02a2031591 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_pullup.c @@ -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 = 1; + 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 +}; diff --git a/libavfilter/libmpcodecs/vf_qp.c b/libavfilter/libmpcodecs/vf_qp.c new file mode 100644 index 0000000000..d74f138662 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_qp.c @@ -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_expr_parse_and_eval(&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 +}; diff --git a/libavfilter/libmpcodecs/vf_rectangle.c b/libavfilter/libmpcodecs/vf_rectangle.c new file mode 100644 index 0000000000..21bc209de4 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_rectangle.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_remove_logo.c b/libavfilter/libmpcodecs/vf_remove_logo.c new file mode 100644 index 0000000000..5f1265eab3 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_remove_logo.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_rgbtest.c b/libavfilter/libmpcodecs/vf_rgbtest.c new file mode 100644 index 0000000000..cbed6ed367 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_rgbtest.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_rotate.c b/libavfilter/libmpcodecs/vf_rotate.c new file mode 100644 index 0000000000..08d73bec28 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_rotate.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_sab.c b/libavfilter/libmpcodecs/vf_sab.c new file mode 100644 index 0000000000..51e9d78158 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_sab.c @@ -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= av_malloc(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, 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= av_malloc(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; + + av_free(f->preFilterBuf); + f->preFilterBuf=NULL; + + av_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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_scale.h b/libavfilter/libmpcodecs/vf_scale.h new file mode 100644 index 0000000000..4de3b48ec3 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_scale.h @@ -0,0 +1,34 @@ +/* + * 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; + +struct SwsContext *sws_getContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat); + +#endif /* MPLAYER_VF_SCALE_H */ diff --git a/libavfilter/libmpcodecs/vf_screenshot.c b/libavfilter/libmpcodecs/vf_screenshot.c new file mode 100644 index 0000000000..82b345b446 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_screenshot.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_smartblur.c b/libavfilter/libmpcodecs/vf_smartblur.c new file mode 100644 index 0000000000..5bfcb2806e --- /dev/null +++ b/libavfilter/libmpcodecs/vf_smartblur.c @@ -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, &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; + int threshold = vf->priv->luma.threshold || vf->priv->chroma.threshold; + + mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt, + MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE| + (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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_softpulldown.c b/libavfilter/libmpcodecs/vf_softpulldown.c new file mode 100644 index 0000000000..04d1eae3d4 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_softpulldown.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_softskip.c b/libavfilter/libmpcodecs/vf_softskip.c new file mode 100644 index 0000000000..150c3e7b72 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_softskip.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_spp.c b/libavfilter/libmpcodecs/vf_spp.c new file mode 100644 index 0000000000..0b4b2306f4 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_spp.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_swapuv.c b/libavfilter/libmpcodecs/vf_swapuv.c new file mode 100644 index 0000000000..4d0e8fcb16 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_swapuv.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_telecine.c b/libavfilter/libmpcodecs/vf_telecine.c new file mode 100644 index 0000000000..3b92518c84 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_telecine.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_test.c b/libavfilter/libmpcodecs/vf_test.c new file mode 100644 index 0000000000..bef06120e1 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_test.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_tile.c b/libavfilter/libmpcodecs/vf_tile.c new file mode 100644 index 0000000000..9ec037ef4c --- /dev/null +++ b/libavfilter/libmpcodecs/vf_tile.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_tinterlace.c b/libavfilter/libmpcodecs/vf_tinterlace.c new file mode 100644 index 0000000000..6dbcbc9481 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_tinterlace.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_unsharp.c b/libavfilter/libmpcodecs/vf_unsharp.c new file mode 100644 index 0000000000..db22f78e9d --- /dev/null +++ b/libavfilter/libmpcodecs/vf_unsharp.c @@ -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; + const 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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_uspp.c b/libavfilter/libmpcodecs/vf_uspp.c new file mode 100644 index 0000000000..7f5a86522a --- /dev/null +++ b/libavfilter/libmpcodecs/vf_uspp.c @@ -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 +}; diff --git a/libavfilter/libmpcodecs/vf_yuvcsp.c b/libavfilter/libmpcodecs/vf_yuvcsp.c new file mode 100644 index 0000000000..102ce14538 --- /dev/null +++ b/libavfilter/libmpcodecs/vf_yuvcsp.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vf_yvu9.c b/libavfilter/libmpcodecs/vf_yvu9.c new file mode 100644 index 0000000000..1f74261ccf --- /dev/null +++ b/libavfilter/libmpcodecs/vf_yvu9.c @@ -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 +}; + +//===========================================================================// diff --git a/libavfilter/libmpcodecs/vfcap.h b/libavfilter/libmpcodecs/vfcap.h new file mode 100644 index 0000000000..611d642869 --- /dev/null +++ b/libavfilter/libmpcodecs/vfcap.h @@ -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 */ diff --git a/libavfilter/vf_aspect.c b/libavfilter/vf_aspect.c index b43aa86bea..5234adb4f5 100644 --- a/libavfilter/vf_aspect.c +++ b/libavfilter/vf_aspect.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2010 Bobby Bingham - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -66,7 +66,7 @@ static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref) { AspectContext *aspect = link->dst->priv; - picref->video->pixel_aspect = aspect->aspect; + picref->video->sample_aspect_ratio = aspect->aspect; avfilter_start_frame(link->dst->outputs[0], picref); } diff --git a/libavfilter/vf_blackframe.c b/libavfilter/vf_blackframe.c index 770eec94e0..41b4a92ce5 100644 --- a/libavfilter/vf_blackframe.c +++ b/libavfilter/vf_blackframe.c @@ -4,20 +4,20 @@ * Copyright (c) 2006 Julian Hall * Copyright (c) 2002-2003 Brian J. Murrell * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or modify + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software Foundation, Inc., + * with FFmpeg; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -44,7 +44,7 @@ static int query_formats(AVFilterContext *ctx) PIX_FMT_NONE }; - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); return 0; } diff --git a/libavfilter/vf_boxblur.c b/libavfilter/vf_boxblur.c new file mode 100644 index 0000000000..7fb1ec5ba2 --- /dev/null +++ b/libavfilter/vf_boxblur.c @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at> + * Copyright (c) 2011 Stefano Sabatini + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * @file + * Apply a boxblur filter to the input video. + * Ported from MPlayer libmpcodecs/vf_boxblur.c. + */ + +#include "libavutil/avstring.h" +#include "libavutil/eval.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" + +static const char *var_names[] = { + "w", + "h", + "cw", + "ch", + "hsub", + "vsub", + NULL +}; + +enum var_name { + VAR_W, + VAR_H, + VAR_CW, + VAR_CH, + VAR_HSUB, + VAR_VSUB, + VARS_NB +}; + +typedef struct { + int radius; + int power; +} FilterParam; + +typedef struct { + FilterParam luma_param; + FilterParam chroma_param; + FilterParam alpha_param; + char luma_radius_expr [256]; + char chroma_radius_expr[256]; + char alpha_radius_expr [256]; + + int hsub, vsub; + int radius[4]; + int power[4]; + uint8_t *temp[2]; ///< temporary buffer used in blur_power() +} BoxBlurContext; + +#define Y 0 +#define U 1 +#define V 2 +#define A 3 + +static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) +{ + BoxBlurContext *boxblur = ctx->priv; + int e; + + if (!args) { + av_log(ctx, AV_LOG_ERROR, + "Filter expects 2 or 4 arguments, none provided\n"); + return AVERROR(EINVAL); + } + + e = sscanf(args, "%255[^:]:%d:%255[^:]:%d:%255[^:]:%d", + boxblur->luma_radius_expr, &boxblur->luma_param .power, + boxblur->chroma_radius_expr, &boxblur->chroma_param.power, + boxblur->alpha_radius_expr, &boxblur->alpha_param .power); + + if (e != 2 && e != 4 && e != 6) { + av_log(ctx, AV_LOG_ERROR, + "Filter expects 2 or 4 or 6 params, provided %d\n", e); + return AVERROR(EINVAL); + } + + if (e < 4) { + boxblur->chroma_param.power = boxblur->luma_param.power; + av_strlcpy(boxblur->chroma_radius_expr, boxblur->luma_radius_expr, + sizeof(boxblur->chroma_radius_expr)); + } + if (e < 6) { + boxblur->alpha_param.power = boxblur->luma_param.power; + av_strlcpy(boxblur->alpha_radius_expr, boxblur->luma_radius_expr, + sizeof(boxblur->alpha_radius_expr)); + } + + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + BoxBlurContext *boxblur = ctx->priv; + + av_freep(&boxblur->temp[0]); + av_freep(&boxblur->temp[1]); +} + +static int query_formats(AVFilterContext *ctx) +{ + enum PixelFormat pix_fmts[] = { + PIX_FMT_YUV444P, PIX_FMT_YUV422P, PIX_FMT_YUV420P, + PIX_FMT_YUV411P, PIX_FMT_YUV410P, PIX_FMT_YUVA420P, + PIX_FMT_YUV440P, PIX_FMT_GRAY8, + PIX_FMT_YUVJ444P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ420P, + PIX_FMT_YUVJ440P, + PIX_FMT_NONE + }; + + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); + return 0; +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + BoxBlurContext *boxblur = ctx->priv; + const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[inlink->format]; + int w = inlink->w, h = inlink->h; + int cw, ch; + double var_values[VARS_NB], res; + char *expr; + int ret; + + if (!(boxblur->temp[0] = av_malloc(w)) || + !(boxblur->temp[1] = av_malloc(w))) + return AVERROR(ENOMEM); + + boxblur->hsub = desc->log2_chroma_w; + boxblur->vsub = desc->log2_chroma_h; + + var_values[VAR_W] = inlink->w; + var_values[VAR_H] = inlink->h; + var_values[VAR_CW] = cw = w>>boxblur->hsub; + var_values[VAR_CH] = ch = h>>boxblur->vsub; + var_values[VAR_HSUB] = 1<<boxblur->hsub; + var_values[VAR_VSUB] = 1<<boxblur->vsub; + +#define EVAL_RADIUS_EXPR(comp) \ + expr = boxblur->comp##_radius_expr; \ + ret = av_expr_parse_and_eval(&res, expr, var_names, var_values, \ + NULL, NULL, NULL, NULL, NULL, 0, ctx); \ + boxblur->comp##_param.radius = res; \ + if (ret < 0) { \ + av_log(NULL, AV_LOG_ERROR, \ + "Error when evaluating " #comp " radius expression '%s'\n", expr); \ + return ret; \ + } + EVAL_RADIUS_EXPR(luma); + EVAL_RADIUS_EXPR(chroma); + EVAL_RADIUS_EXPR(alpha); + + av_log(ctx, AV_LOG_INFO, + "luma_radius:%d luma_power:%d " + "chroma_radius:%d chroma_power:%d " + "alpha_radius:%d alpha_power:%d " + "w:%d chroma_w:%d h:%d chroma_h:%d\n", + boxblur->luma_param .radius, boxblur->luma_param .power, + boxblur->chroma_param.radius, boxblur->chroma_param.power, + boxblur->alpha_param .radius, boxblur->alpha_param .power, + w, cw, h, ch); + +#define CHECK_RADIUS_VAL(w_, h_, comp) \ + if (boxblur->comp##_param.radius < 0 || \ + 2*boxblur->comp##_param.radius > FFMIN(w_, h_)) { \ + av_log(ctx, AV_LOG_ERROR, \ + "Invalid " #comp " radius value %d, must be >= 0 and <= %d\n", \ + boxblur->comp##_param.radius, FFMIN(w_, h_)/2); \ + return AVERROR(EINVAL); \ + } + CHECK_RADIUS_VAL(w, h, luma); + CHECK_RADIUS_VAL(cw, ch, chroma); + CHECK_RADIUS_VAL(w, h, alpha); + + boxblur->radius[Y] = boxblur->luma_param.radius; + boxblur->radius[U] = boxblur->radius[V] = boxblur->chroma_param.radius; + boxblur->radius[A] = boxblur->alpha_param.radius; + + boxblur->power[Y] = boxblur->luma_param.power; + boxblur->power[U] = boxblur->power[V] = boxblur->chroma_param.power; + boxblur->power[A] = boxblur->alpha_param.power; + + return 0; +} + +static inline void blur(uint8_t *dst, int dst_step, const uint8_t *src, int src_step, + int w, int radius) +{ + /* Naive boxblur would sum source pixels from x-radius .. x+radius + * for destination pixel x. That would be O(radius*width). + * If you now look at what source pixels represent 2 consecutive + * output pixels, then you see they are almost identical and only + * differ by 2 pixels, like: + * src0 111111111 + * dst0 1 + * src1 111111111 + * dst1 1 + * src0-src1 1 -1 + * so when you know one output pixel you can find the next by just adding + * and subtracting 1 input pixel. + * The following code adopts this faster variant. + */ + int x, sum = 0; + const int length = radius*2 + 1; + const int inv = ((1<<16) + length/2)/length; + + for (x = 0; x < radius; x++) + sum += src[x*src_step]<<1; + sum += src[radius*src_step]; + + for (x = 0; x <= radius; x++) { + sum += src[(radius+x)*src_step] - src[(radius-x)*src_step]; + dst[x*dst_step] = (sum*inv + (1<<15))>>16; + } + + for (; x < w-radius; x++) { + sum += src[(radius+x)*src_step] - src[(x-radius-1)*src_step]; + dst[x*dst_step] = (sum*inv + (1<<15))>>16; + } + + for (; x < w; x++) { + sum += src[(2*w-radius-x-1)*src_step] - src[(x-radius-1)*src_step]; + dst[x*dst_step] = (sum*inv + (1<<15))>>16; + } +} + +static inline void blur_power(uint8_t *dst, int dst_step, const uint8_t *src, int src_step, + int w, int radius, int power, uint8_t *temp[2]) +{ + uint8_t *a = temp[0], *b = temp[1]; + + if (radius && power) { + blur(a, 1, src, src_step, w, radius); + for (; power > 2; power--) { + uint8_t *c; + blur(b, 1, a, 1, w, radius); + c = a; a = b; b = c; + } + if (power > 1) { + blur(dst, dst_step, a, 1, w, radius); + } else { + int i; + for (i = 0; i < w; i++) + dst[i*dst_step] = a[i]; + } + } else { + int i; + for (i = 0; i < w; i++) + dst[i*dst_step] = src[i*src_step]; + } +} + +static void hblur(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, + int w, int h, int radius, int power, uint8_t *temp[2]) +{ + int y; + + if (radius == 0 && dst == src) + return; + + for (y = 0; y < h; y++) + blur_power(dst + y*dst_linesize, 1, src + y*src_linesize, 1, + w, radius, power, temp); +} + +static void vblur(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, + int w, int h, int radius, int power, uint8_t *temp[2]) +{ + int x; + + if (radius == 0 && dst == src) + return; + + for (x = 0; x < w; x++) + blur_power(dst + x, dst_linesize, src + x, src_linesize, + h, radius, power, temp); +} + +static void draw_slice(AVFilterLink *inlink, int y0, int h0, int slice_dir) +{ + AVFilterContext *ctx = inlink->dst; + BoxBlurContext *boxblur = ctx->priv; + AVFilterLink *outlink = inlink->dst->outputs[0]; + AVFilterBufferRef *inpicref = inlink ->cur_buf; + AVFilterBufferRef *outpicref = outlink->out_buf; + int plane; + int cw = inlink->w >> boxblur->hsub, ch = h0 >> boxblur->vsub; + int w[4] = { inlink->w, cw, cw, inlink->w }; + int h[4] = { h0, ch, ch, h0 }; + uint8_t *dst[4], *src[4]; + + for (plane = 0; inpicref->data[plane] && plane < 4; plane++) { + int y = plane == 1 || plane == 2 ? y0 >> boxblur->vsub : y0; + src[plane] = inpicref ->data[plane] + inpicref ->linesize[plane] * y; + dst[plane] = outpicref->data[plane] + outpicref->linesize[plane] * y; + } + + for (plane = 0; inpicref->data[plane] && plane < 4; plane++) + hblur(outpicref->data[plane], outpicref->linesize[plane], + inpicref ->data[plane], inpicref ->linesize[plane], + w[plane], h[plane], boxblur->radius[plane], boxblur->power[plane], + boxblur->temp); + + for (plane = 0; inpicref->data[plane] && plane < 4; plane++) + vblur(outpicref->data[plane], outpicref->linesize[plane], + outpicref->data[plane], outpicref->linesize[plane], + w[plane], h[plane], boxblur->radius[plane], boxblur->power[plane], + boxblur->temp); +} + +AVFilter avfilter_vf_boxblur = { + .name = "boxblur", + .description = NULL_IF_CONFIG_SMALL("Blur the input."), + .priv_size = sizeof(BoxBlurContext), + .init = init, + .uninit = uninit, + .query_formats = query_formats, + + .inputs = (AVFilterPad[]) {{ .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + .draw_slice = draw_slice, + .min_perms = AV_PERM_READ }, + { .name = NULL}}, + .outputs = (AVFilterPad[]) {{ .name = "default", + .type = AVMEDIA_TYPE_VIDEO, }, + { .name = NULL}}, +}; diff --git a/libavfilter/vf_copy.c b/libavfilter/vf_copy.c index 705ad1e2e6..480ebcc034 100644 --- a/libavfilter/vf_copy.c +++ b/libavfilter/vf_copy.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavfilter/vf_crop.c b/libavfilter/vf_crop.c index 0880d4e5f9..b9c60cb65b 100644 --- a/libavfilter/vf_crop.c +++ b/libavfilter/vf_crop.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2007 Bobby Bingham * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -105,7 +105,7 @@ static int query_formats(AVFilterContext *ctx) PIX_FMT_NONE }; - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); return 0; } diff --git a/libavfilter/vf_cropdetect.c b/libavfilter/vf_cropdetect.c index 34b5dc9a2a..a997cbede8 100644 --- a/libavfilter/vf_cropdetect.c +++ b/libavfilter/vf_cropdetect.c @@ -1,19 +1,19 @@ /* * Copyright (c) 2002 A'rpi - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or modify + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software Foundation, Inc., + * with FFmpeg; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -46,7 +46,7 @@ static int query_formats(AVFilterContext *ctx) PIX_FMT_NONE }; - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); return 0; } diff --git a/libavfilter/vf_drawbox.c b/libavfilter/vf_drawbox.c index 37c48c5c89..1ad8e94de2 100644 --- a/libavfilter/vf_drawbox.c +++ b/libavfilter/vf_drawbox.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2008 Affine Systems, Inc (Michael Sullivan, Bobby Impollonia) * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -70,7 +70,7 @@ static int query_formats(AVFilterContext *ctx) PIX_FMT_NONE }; - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); return 0; } diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index ed4b1003d8..7d8372b886 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -3,20 +3,20 @@ * Copyright (c) 2010 S.N. Hemanth Meenakshisundaram * Copyright (c) 2003 Gustavo Sverzut Barbieri <gsbarbieri@yahoo.com.br> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -102,21 +102,21 @@ static const AVOption drawtext_options[]= { /* FT_LOAD_* flags */ {"ft_load_flags", "set font loading flags for libfreetype", OFFSET(ft_load_flags), FF_OPT_TYPE_FLAGS, {.dbl=FT_LOAD_DEFAULT|FT_LOAD_RENDER}, 0, INT_MAX, 0, "ft_load_flags" }, -{"default", "set default", 0, FF_OPT_TYPE_CONST, {FT_LOAD_DEFAULT}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, -{"no_scale", "set no_scale", 0, FF_OPT_TYPE_CONST, {FT_LOAD_NO_SCALE}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, -{"no_hinting", "set no_hinting", 0, FF_OPT_TYPE_CONST, {FT_LOAD_NO_HINTING}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, -{"render", "set render", 0, FF_OPT_TYPE_CONST, {FT_LOAD_RENDER}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, -{"no_bitmap", "set no_bitmap", 0, FF_OPT_TYPE_CONST, {FT_LOAD_NO_BITMAP}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, -{"vertical_layout", "set vertical_layout", 0, FF_OPT_TYPE_CONST, {FT_LOAD_VERTICAL_LAYOUT}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, -{"force_autohint", "set force_autohint", 0, FF_OPT_TYPE_CONST, {FT_LOAD_FORCE_AUTOHINT}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, -{"crop_bitmap", "set crop_bitmap", 0, FF_OPT_TYPE_CONST, {FT_LOAD_CROP_BITMAP}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, -{"pedantic", "set pedantic", 0, FF_OPT_TYPE_CONST, {FT_LOAD_PEDANTIC}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, -{"ignore_global_advance_width", "set ignore_global_advance_width", 0, FF_OPT_TYPE_CONST, {FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, -{"no_recurse", "set no_recurse", 0, FF_OPT_TYPE_CONST, {FT_LOAD_NO_RECURSE}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, -{"ignore_transform", "set ignore_transform", 0, FF_OPT_TYPE_CONST, {FT_LOAD_IGNORE_TRANSFORM}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, -{"monochrome", "set monochrome", 0, FF_OPT_TYPE_CONST, {FT_LOAD_MONOCHROME}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, -{"linear_design", "set linear_design", 0, FF_OPT_TYPE_CONST, {FT_LOAD_LINEAR_DESIGN}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, -{"no_autohint", "set no_autohint", 0, FF_OPT_TYPE_CONST, {FT_LOAD_NO_AUTOHINT}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, +{"default", "set default", 0, FF_OPT_TYPE_CONST, {.dbl=FT_LOAD_DEFAULT}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, +{"no_scale", "set no_scale", 0, FF_OPT_TYPE_CONST, {.dbl=FT_LOAD_NO_SCALE}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, +{"no_hinting", "set no_hinting", 0, FF_OPT_TYPE_CONST, {.dbl=FT_LOAD_NO_HINTING}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, +{"render", "set render", 0, FF_OPT_TYPE_CONST, {.dbl=FT_LOAD_RENDER}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, +{"no_bitmap", "set no_bitmap", 0, FF_OPT_TYPE_CONST, {.dbl=FT_LOAD_NO_BITMAP}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, +{"vertical_layout", "set vertical_layout", 0, FF_OPT_TYPE_CONST, {.dbl=FT_LOAD_VERTICAL_LAYOUT}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, +{"force_autohint", "set force_autohint", 0, FF_OPT_TYPE_CONST, {.dbl=FT_LOAD_FORCE_AUTOHINT}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, +{"crop_bitmap", "set crop_bitmap", 0, FF_OPT_TYPE_CONST, {.dbl=FT_LOAD_CROP_BITMAP}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, +{"pedantic", "set pedantic", 0, FF_OPT_TYPE_CONST, {.dbl=FT_LOAD_PEDANTIC}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, +{"ignore_global_advance_width", "set ignore_global_advance_width", 0, FF_OPT_TYPE_CONST, {.dbl=FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, +{"no_recurse", "set no_recurse", 0, FF_OPT_TYPE_CONST, {.dbl=FT_LOAD_NO_RECURSE}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, +{"ignore_transform", "set ignore_transform", 0, FF_OPT_TYPE_CONST, {.dbl=FT_LOAD_IGNORE_TRANSFORM}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, +{"monochrome", "set monochrome", 0, FF_OPT_TYPE_CONST, {.dbl=FT_LOAD_MONOCHROME}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, +{"linear_design", "set linear_design", 0, FF_OPT_TYPE_CONST, {.dbl=FT_LOAD_LINEAR_DESIGN}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, +{"no_autohint", "set no_autohint", 0, FF_OPT_TYPE_CONST, {.dbl=FT_LOAD_NO_AUTOHINT}, INT_MIN, INT_MAX, 0, "ft_load_flags" }, {NULL}, }; @@ -334,7 +334,7 @@ static int query_formats(AVFilterContext *ctx) PIX_FMT_NONE }; - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); return 0; } diff --git a/libavfilter/vf_fade.c b/libavfilter/vf_fade.c index 0c8668ce90..6c2a23dac3 100644 --- a/libavfilter/vf_fade.c +++ b/libavfilter/vf_fade.c @@ -2,20 +2,20 @@ * Copyright (c) 2010 Brandon Mintern * Copyright (c) 2007 Bobby Bingham * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -78,7 +78,7 @@ static int query_formats(AVFilterContext *ctx) PIX_FMT_NONE }; - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); return 0; } diff --git a/libavfilter/vf_fieldorder.c b/libavfilter/vf_fieldorder.c index 444dffb52c..0913b6950e 100644 --- a/libavfilter/vf_fieldorder.c +++ b/libavfilter/vf_fieldorder.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2011 Mark Himsley * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavfilter/vf_fifo.c b/libavfilter/vf_fifo.c index 836cce28b5..32199eddc8 100644 --- a/libavfilter/vf_fifo.c +++ b/libavfilter/vf_fifo.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2007 Bobby Bingham * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavfilter/vf_format.c b/libavfilter/vf_format.c index 0b0d094169..9ecb0269ce 100644 --- a/libavfilter/vf_format.c +++ b/libavfilter/vf_format.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2007 Bobby Bingham * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -88,7 +88,7 @@ static AVFilterFormats *make_format_list(FormatContext *format, int flag) #if CONFIG_FORMAT_FILTER static int query_formats_format(AVFilterContext *ctx) { - avfilter_set_common_formats(ctx, make_format_list(ctx->priv, 1)); + avfilter_set_common_pixel_formats(ctx, make_format_list(ctx->priv, 1)); return 0; } @@ -118,7 +118,7 @@ AVFilter avfilter_vf_format = { #if CONFIG_NOFORMAT_FILTER static int query_formats_noformat(AVFilterContext *ctx) { - avfilter_set_common_formats(ctx, make_format_list(ctx->priv, 0)); + avfilter_set_common_pixel_formats(ctx, make_format_list(ctx->priv, 0)); return 0; } diff --git a/libavfilter/vf_frei0r.c b/libavfilter/vf_frei0r.c index 455e24a7f1..f5b7abb543 100644 --- a/libavfilter/vf_frei0r.c +++ b/libavfilter/vf_frei0r.c @@ -1,19 +1,19 @@ /* * Copyright (c) 2010 Stefano Sabatini - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -333,7 +333,7 @@ static int query_formats(AVFilterContext *ctx) if (!formats) return AVERROR(ENOMEM); - avfilter_set_common_formats(ctx, formats); + avfilter_set_common_pixel_formats(ctx, formats); return 0; } @@ -431,7 +431,7 @@ static int source_request_frame(AVFilterLink *outlink) { Frei0rContext *frei0r = outlink->src->priv; AVFilterBufferRef *picref = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); - picref->video->pixel_aspect = (AVRational) {1, 1}; + picref->video->sample_aspect_ratio = (AVRational) {1, 1}; picref->pts = frei0r->pts++; picref->pos = -1; diff --git a/libavfilter/vf_gradfun.c b/libavfilter/vf_gradfun.c index c6663c4102..084dcc5c3c 100644 --- a/libavfilter/vf_gradfun.c +++ b/libavfilter/vf_gradfun.c @@ -2,20 +2,20 @@ * Copyright (c) 2010 Nolan Lum <nol888@gmail.com> * Copyright (c) 2009 Loren Merritt <lorenm@u.washignton.edu> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -49,7 +49,7 @@ DECLARE_ALIGNED(16, static const uint16_t, dither)[8][8] = { {0x54,0x34,0x4C,0x2C,0x52,0x32,0x4A,0x2A}, }; -void ff_gradfun_filter_line_c(uint8_t *dst, uint8_t *src, uint16_t *dc, int width, int thresh, const uint16_t *dithers) +void ff_gradfun_filter_line_c(uint8_t *dst, const uint8_t *src, const uint16_t *dc, int width, int thresh, const uint16_t *dithers) { int x; for (x = 0; x < width; x++, dc += x & 1) { @@ -63,7 +63,7 @@ void ff_gradfun_filter_line_c(uint8_t *dst, uint8_t *src, uint16_t *dc, int widt } } -void ff_gradfun_blur_line_c(uint16_t *dc, uint16_t *buf, uint16_t *buf1, uint8_t *src, int src_linesize, int width) +void ff_gradfun_blur_line_c(uint16_t *dc, uint16_t *buf, const uint16_t *buf1, const uint8_t *src, int src_linesize, int width) { int x, v, old; for (x = 0; x < width; x++) { @@ -74,7 +74,7 @@ void ff_gradfun_blur_line_c(uint16_t *dc, uint16_t *buf, uint16_t *buf1, uint8_t } } -static void filter(GradFunContext *ctx, uint8_t *dst, uint8_t *src, int width, int height, int dst_linesize, int src_linesize, int r) +static void filter(GradFunContext *ctx, uint8_t *dst, const uint8_t *src, int width, int height, int dst_linesize, int src_linesize, int r) { int bstride = FFALIGN(width, 16) / 2; int y; @@ -160,7 +160,7 @@ static int query_formats(AVFilterContext *ctx) PIX_FMT_NONE }; - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); return 0; } diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c index fb8911f851..9b995a9894 100644 --- a/libavfilter/vf_hflip.c +++ b/libavfilter/vf_hflip.c @@ -2,20 +2,20 @@ * Copyright (c) 2007 Benoit Fouet * Copyright (c) 2010 Stefano Sabatini * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -62,7 +62,7 @@ static int query_formats(AVFilterContext *ctx) PIX_FMT_NONE }; - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); return 0; } diff --git a/libavfilter/vf_hqdn3d.c b/libavfilter/vf_hqdn3d.c index 2e9a89510b..993ce7623d 100644 --- a/libavfilter/vf_hqdn3d.c +++ b/libavfilter/vf_hqdn3d.c @@ -2,20 +2,20 @@ * Copyright (c) 2003 Daniel Moreno <comac AT comac DOT darktech DOT org> * Copyright (c) 2010 Baptiste Coudurier * - * This file is part of Libav, ported from MPlayer. + * This file is part of FFmpeg, ported from MPlayer. * - * Libav is free software; you can redistribute it and/or modify + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software Foundation, Inc., + * with FFmpeg; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -268,7 +268,7 @@ static int query_formats(AVFilterContext *ctx) PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_YUV411P, PIX_FMT_NONE }; - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); return 0; } diff --git a/libavfilter/vf_libopencv.c b/libavfilter/vf_libopencv.c index 5a52f246ba..e1b51c52c2 100644 --- a/libavfilter/vf_libopencv.c +++ b/libavfilter/vf_libopencv.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2010 Stefano Sabatini * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -26,7 +26,7 @@ /* #define DEBUG */ #include <opencv/cv.h> -#include <opencv/cxtypes.h> +#include <opencv/cxcore.h> #include "libavutil/avstring.h" #include "libavutil/file.h" #include "avfilter.h" @@ -61,7 +61,7 @@ static int query_formats(AVFilterContext *ctx) PIX_FMT_BGR24, PIX_FMT_BGRA, PIX_FMT_GRAY8, PIX_FMT_NONE }; - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); return 0; } diff --git a/libavfilter/vf_lut.c b/libavfilter/vf_lut.c new file mode 100644 index 0000000000..a1f93ffc91 --- /dev/null +++ b/libavfilter/vf_lut.c @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2011 Stefano Sabatini + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Compute a look-up table for binding the input value to the output + * value, and apply it to input video. + */ + +#include "libavutil/eval.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" +#include "internal.h" + +static const char *var_names[] = { + "E", + "PHI", + "PI", + "w", ///< width of the input video + "h", ///< height of the input video + "val", ///< input value for the pixel + "maxval", ///< max value for the pixel + "minval", ///< min value for the pixel + "negval", ///< negated value + "clipval", + NULL +}; + +enum var_name { + VAR_E, + VAR_PHI, + VAR_PI, + VAR_W, + VAR_H, + VAR_VAL, + VAR_MAXVAL, + VAR_MINVAL, + VAR_NEGVAL, + VAR_CLIPVAL, + VAR_VARS_NB +}; + +typedef struct { + const AVClass *class; + uint8_t lut[4][256]; ///< lookup table for each component + char *comp_expr_str[4]; + AVExpr *comp_expr[4]; + int hsub, vsub; + double var_values[VAR_VARS_NB]; + int is_rgb, is_yuv; + int rgba_map[4]; + int step; + int negate_alpha; /* only used by negate */ +} LutContext; + +#define Y 0 +#define U 1 +#define V 2 +#define R 0 +#define G 1 +#define B 2 +#define A 3 + +#define OFFSET(x) offsetof(LutContext, x) + +static const AVOption lut_options[] = { + {"c0", "set component #0 expression", OFFSET(comp_expr_str[0]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX}, + {"c1", "set component #1 expression", OFFSET(comp_expr_str[1]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX}, + {"c2", "set component #2 expression", OFFSET(comp_expr_str[2]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX}, + {"c3", "set component #3 expression", OFFSET(comp_expr_str[3]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX}, + {"y", "set Y expression", OFFSET(comp_expr_str[Y]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX}, + {"u", "set U expression", OFFSET(comp_expr_str[U]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX}, + {"v", "set V expression", OFFSET(comp_expr_str[V]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX}, + {"r", "set R expression", OFFSET(comp_expr_str[R]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX}, + {"g", "set G expression", OFFSET(comp_expr_str[G]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX}, + {"b", "set B expression", OFFSET(comp_expr_str[B]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX}, + {"a", "set A expression", OFFSET(comp_expr_str[A]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX}, + {NULL}, +}; + +static const char *lut_get_name(void *ctx) +{ + return "lut"; +} + +static const AVClass lut_class = { + "LutContext", + lut_get_name, + lut_options +}; + +static int init(AVFilterContext *ctx, const char *args, void *opaque) +{ + LutContext *lut = ctx->priv; + int ret; + + lut->class = &lut_class; + av_opt_set_defaults2(lut, 0, 0); + + lut->var_values[VAR_PHI] = M_PHI; + lut->var_values[VAR_PI] = M_PI; + lut->var_values[VAR_E ] = M_E; + + lut->is_rgb = !strcmp(ctx->filter->name, "lutrgb"); + lut->is_yuv = !strcmp(ctx->filter->name, "lutyuv"); + if (args && (ret = av_set_options_string(lut, args, "=", ":")) < 0) + return ret; + + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + LutContext *lut = ctx->priv; + int i; + + for (i = 0; i < 4; i++) { + av_expr_free(lut->comp_expr[i]); + lut->comp_expr[i] = NULL; + av_freep(&lut->comp_expr_str[i]); + } +} + +#define YUV_FORMATS \ + PIX_FMT_YUV444P, PIX_FMT_YUV422P, PIX_FMT_YUV420P, \ + PIX_FMT_YUV411P, PIX_FMT_YUV410P, PIX_FMT_YUV440P, \ + PIX_FMT_YUVA420P, \ + PIX_FMT_YUVJ444P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ420P, \ + PIX_FMT_YUVJ440P + +#define RGB_FORMATS \ + PIX_FMT_ARGB, PIX_FMT_RGBA, \ + PIX_FMT_ABGR, PIX_FMT_BGRA, \ + PIX_FMT_RGB24, PIX_FMT_BGR24 + +static enum PixelFormat yuv_pix_fmts[] = { YUV_FORMATS, PIX_FMT_NONE }; +static enum PixelFormat rgb_pix_fmts[] = { RGB_FORMATS, PIX_FMT_NONE }; +static enum PixelFormat all_pix_fmts[] = { RGB_FORMATS, YUV_FORMATS, PIX_FMT_NONE }; + +static int query_formats(AVFilterContext *ctx) +{ + LutContext *lut = ctx->priv; + + enum PixelFormat *pix_fmts = lut->is_rgb ? rgb_pix_fmts : + lut->is_yuv ? yuv_pix_fmts : all_pix_fmts; + + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); + return 0; +} + +/** + * Clip value val in the minval - maxval range. + */ +static double clip(void *opaque, double val) +{ + LutContext *lut = opaque; + double minval = lut->var_values[VAR_MINVAL]; + double maxval = lut->var_values[VAR_MAXVAL]; + + return av_clip(val, minval, maxval); +} + +/** + * Compute gamma correction for value val, assuming the minval-maxval + * range, val is clipped to a value contained in the same interval. + */ +static double compute_gammaval(void *opaque, double gamma) +{ + LutContext *lut = opaque; + double val = lut->var_values[VAR_CLIPVAL]; + double minval = lut->var_values[VAR_MINVAL]; + double maxval = lut->var_values[VAR_MAXVAL]; + + return pow((val-minval)/(maxval-minval), gamma) * (maxval-minval)+minval; +} + +static double (* const funcs1[])(void *, double) = { + (void *)clip, + (void *)compute_gammaval, + NULL +}; + +static const char * const funcs1_names[] = { + "clip", + "gammaval", + NULL +}; + +static int config_props(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + LutContext *lut = ctx->priv; + const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[inlink->format]; + int min[4], max[4]; + int val, comp, ret; + + lut->hsub = desc->log2_chroma_w; + lut->vsub = desc->log2_chroma_h; + + lut->var_values[VAR_W] = inlink->w; + lut->var_values[VAR_H] = inlink->h; + + switch (inlink->format) { + case PIX_FMT_YUV410P: + case PIX_FMT_YUV411P: + case PIX_FMT_YUV420P: + case PIX_FMT_YUV422P: + case PIX_FMT_YUV440P: + case PIX_FMT_YUV444P: + case PIX_FMT_YUVA420P: + min[Y] = min[U] = min[V] = 16; + max[Y] = 235; + max[U] = max[V] = 240; + min[A] = 0; max[A] = 255; + break; + default: + min[0] = min[1] = min[2] = min[3] = 0; + max[0] = max[1] = max[2] = max[3] = 255; + } + + lut->is_yuv = lut->is_rgb = 0; + if (ff_fmt_is_in(inlink->format, yuv_pix_fmts)) lut->is_yuv = 1; + else if (ff_fmt_is_in(inlink->format, rgb_pix_fmts)) lut->is_rgb = 1; + + if (lut->is_rgb) { + switch (inlink->format) { + case PIX_FMT_ARGB: lut->rgba_map[A] = 0; lut->rgba_map[R] = 1; lut->rgba_map[G] = 2; lut->rgba_map[B] = 3; break; + case PIX_FMT_ABGR: lut->rgba_map[A] = 0; lut->rgba_map[B] = 1; lut->rgba_map[G] = 2; lut->rgba_map[R] = 3; break; + case PIX_FMT_RGBA: + case PIX_FMT_RGB24: lut->rgba_map[R] = 0; lut->rgba_map[G] = 1; lut->rgba_map[B] = 2; lut->rgba_map[A] = 3; break; + case PIX_FMT_BGRA: + case PIX_FMT_BGR24: lut->rgba_map[B] = 0; lut->rgba_map[G] = 1; lut->rgba_map[R] = 2; lut->rgba_map[A] = 3; break; + } + lut->step = av_get_bits_per_pixel(desc) >> 3; + } + + for (comp = 0; comp < desc->nb_components; comp++) { + double res; + + /* create the parsed expression */ + ret = av_expr_parse(&lut->comp_expr[comp], lut->comp_expr_str[comp], + var_names, funcs1_names, funcs1, NULL, NULL, 0, ctx); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, + "Error when parsing the expression '%s' for the component %d.\n", + lut->comp_expr_str[comp], comp); + return AVERROR(EINVAL); + } + + /* compute the lut */ + lut->var_values[VAR_MAXVAL] = max[comp]; + lut->var_values[VAR_MINVAL] = min[comp]; + + for (val = 0; val < 256; val++) { + lut->var_values[VAR_VAL] = val; + lut->var_values[VAR_CLIPVAL] = av_clip(val, min[comp], max[comp]); + lut->var_values[VAR_NEGVAL] = + av_clip(min[comp] + max[comp] - lut->var_values[VAR_VAL], + min[comp], max[comp]); + + res = av_expr_eval(lut->comp_expr[comp], lut->var_values, lut); + if (isnan(res)) { + av_log(ctx, AV_LOG_ERROR, + "Error when evaluating the expression '%s' for the value %d for the component #%d.\n", + lut->comp_expr_str[comp], val, comp); + return AVERROR(EINVAL); + } + lut->lut[comp][val] = av_clip((int)res, min[comp], max[comp]); + av_log(ctx, AV_LOG_DEBUG, "val[%d][%d] = %d\n", comp, val, lut->lut[comp][val]); + } + } + + return 0; +} + +static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) +{ + AVFilterContext *ctx = inlink->dst; + LutContext *lut = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFilterBufferRef *inpic = inlink ->cur_buf; + AVFilterBufferRef *outpic = outlink->out_buf; + uint8_t *inrow, *outrow, *inrow0, *outrow0; + int i, j, k, plane; + + if (lut->is_rgb) { + /* packed */ + inrow0 = inpic ->data[0] + y * inpic ->linesize[0]; + outrow0 = outpic->data[0] + y * outpic->linesize[0]; + + for (i = 0; i < h; i ++) { + inrow = inrow0; + outrow = outrow0; + for (j = 0; j < inlink->w; j++) { + for (k = 0; k < lut->step; k++) + outrow[k] = lut->lut[lut->rgba_map[k]][inrow[k]]; + outrow += lut->step; + inrow += lut->step; + } + inrow0 += inpic ->linesize[0]; + outrow0 += outpic->linesize[0]; + } + } else { + /* planar */ + for (plane = 0; plane < 4 && inpic->data[plane]; plane++) { + int vsub = plane == 1 || plane == 2 ? lut->vsub : 0; + int hsub = plane == 1 || plane == 2 ? lut->hsub : 0; + + inrow = inpic ->data[plane] + (y>>vsub) * inpic ->linesize[plane]; + outrow = outpic->data[plane] + (y>>vsub) * outpic->linesize[plane]; + + for (i = 0; i < h>>vsub; i ++) { + for (j = 0; j < inlink->w>>hsub; j++) + outrow[j] = lut->lut[plane][inrow[j]]; + inrow += inpic ->linesize[plane]; + outrow += outpic->linesize[plane]; + } + } + } + + avfilter_draw_slice(outlink, y, h, slice_dir); +} + +#define DEFINE_LUT_FILTER(name_, description_, init_) \ + AVFilter avfilter_vf_##name_ = { \ + .name = NULL_IF_CONFIG_SMALL(#name_), \ + .description = description_, \ + .priv_size = sizeof(LutContext), \ + \ + .init = init_, \ + .uninit = uninit, \ + .query_formats = query_formats, \ + \ + .inputs = (AVFilterPad[]) {{ .name = "default", \ + .type = AVMEDIA_TYPE_VIDEO, \ + .draw_slice = draw_slice, \ + .config_props = config_props, \ + .min_perms = AV_PERM_READ, }, \ + { .name = NULL}}, \ + .outputs = (AVFilterPad[]) {{ .name = "default", \ + .type = AVMEDIA_TYPE_VIDEO, }, \ + { .name = NULL}}, \ + } + +DEFINE_LUT_FILTER(lut, "Compute and apply a lookup table to the RGB/YUV input video.", init); +DEFINE_LUT_FILTER(lutyuv, "Compute and apply a lookup table to the YUV input video.", init); +DEFINE_LUT_FILTER(lutrgb, "Compute and apply a lookup table to the RGB input video.", init); + +#if CONFIG_NEGATE_FILTER + +static int negate_init(AVFilterContext *ctx, const char *args, void *opaque) +{ + LutContext *lut = ctx->priv; + char lut_params[1024]; + + if (args) + sscanf(args, "%d", &lut->negate_alpha); + + av_log(ctx, AV_LOG_INFO, "negate_alpha:%d\n", lut->negate_alpha); + + snprintf(lut_params, sizeof(lut_params), "c0=negval:c1=negval:c2=negval:a=%s", + lut->negate_alpha ? "negval" : "val"); + + return init(ctx, lut_params, opaque); +} + +DEFINE_LUT_FILTER(negate, "Negate input video.", negate_init); + +#endif diff --git a/libavfilter/vf_mp.c b/libavfilter/vf_mp.c new file mode 100644 index 0000000000..9e413b4776 --- /dev/null +++ b/libavfilter/vf_mp.c @@ -0,0 +1,913 @@ +/* + * Copyright (c) 2011 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Parts of this file have been stolen from mplayer + */ + +/** + * @file + */ + +#include "avfilter.h" +#include "libavutil/avassert.h" +#include "libavutil/pixdesc.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" + +#include "libmpcodecs/vf.h" +#include "libmpcodecs/img_format.h" +#include "libmpcodecs/cpudetect.h" +#include "libmpcodecs/vd_ffmpeg.h" +#include "libmpcodecs/vf_scale.h" +#include "libmpcodecs/libvo/fastmemcpy.h" + +#include "libswscale/swscale.h" + + +//FIXME maybe link the orig in +//XXX: identical pix_fmt must be following with each others +static const struct { + int fmt; + enum PixelFormat pix_fmt; +} conversion_map[] = { + {IMGFMT_ARGB, PIX_FMT_ARGB}, + {IMGFMT_BGRA, PIX_FMT_BGRA}, + {IMGFMT_BGR24, PIX_FMT_BGR24}, + {IMGFMT_BGR16BE, PIX_FMT_RGB565BE}, + {IMGFMT_BGR16LE, PIX_FMT_RGB565LE}, + {IMGFMT_BGR15BE, PIX_FMT_RGB555BE}, + {IMGFMT_BGR15LE, PIX_FMT_RGB555LE}, + {IMGFMT_BGR12BE, PIX_FMT_RGB444BE}, + {IMGFMT_BGR12LE, PIX_FMT_RGB444LE}, + {IMGFMT_BGR8, PIX_FMT_RGB8}, + {IMGFMT_BGR4, PIX_FMT_RGB4}, + {IMGFMT_BGR1, PIX_FMT_MONOBLACK}, + {IMGFMT_RGB1, PIX_FMT_MONOBLACK}, + {IMGFMT_RG4B, PIX_FMT_BGR4_BYTE}, + {IMGFMT_BG4B, PIX_FMT_RGB4_BYTE}, + {IMGFMT_RGB48LE, PIX_FMT_RGB48LE}, + {IMGFMT_RGB48BE, PIX_FMT_RGB48BE}, + {IMGFMT_ABGR, PIX_FMT_ABGR}, + {IMGFMT_RGBA, PIX_FMT_RGBA}, + {IMGFMT_RGB24, PIX_FMT_RGB24}, + {IMGFMT_RGB16BE, PIX_FMT_BGR565BE}, + {IMGFMT_RGB16LE, PIX_FMT_BGR565LE}, + {IMGFMT_RGB15BE, PIX_FMT_BGR555BE}, + {IMGFMT_RGB15LE, PIX_FMT_BGR555LE}, + {IMGFMT_RGB12BE, PIX_FMT_BGR444BE}, + {IMGFMT_RGB12LE, PIX_FMT_BGR444LE}, + {IMGFMT_RGB8, PIX_FMT_BGR8}, + {IMGFMT_RGB4, PIX_FMT_BGR4}, + {IMGFMT_BGR8, PIX_FMT_PAL8}, + {IMGFMT_YUY2, PIX_FMT_YUYV422}, + {IMGFMT_UYVY, PIX_FMT_UYVY422}, + {IMGFMT_NV12, PIX_FMT_NV12}, + {IMGFMT_NV21, PIX_FMT_NV21}, + {IMGFMT_Y800, PIX_FMT_GRAY8}, + {IMGFMT_Y8, PIX_FMT_GRAY8}, + {IMGFMT_YVU9, PIX_FMT_YUV410P}, + {IMGFMT_IF09, PIX_FMT_YUV410P}, + {IMGFMT_YV12, PIX_FMT_YUV420P}, + {IMGFMT_I420, PIX_FMT_YUV420P}, + {IMGFMT_IYUV, PIX_FMT_YUV420P}, + {IMGFMT_411P, PIX_FMT_YUV411P}, + {IMGFMT_422P, PIX_FMT_YUV422P}, + {IMGFMT_444P, PIX_FMT_YUV444P}, + {IMGFMT_440P, PIX_FMT_YUV440P}, + + {IMGFMT_420A, PIX_FMT_YUVA420P}, + + {IMGFMT_420P16_LE, PIX_FMT_YUV420P16LE}, + {IMGFMT_420P16_BE, PIX_FMT_YUV420P16BE}, + {IMGFMT_422P16_LE, PIX_FMT_YUV422P16LE}, + {IMGFMT_422P16_BE, PIX_FMT_YUV422P16BE}, + {IMGFMT_444P16_LE, PIX_FMT_YUV444P16LE}, + {IMGFMT_444P16_BE, PIX_FMT_YUV444P16BE}, + + // YUVJ are YUV formats that use the full Y range and not just + // 16 - 235 (see colorspaces.txt). + // Currently they are all treated the same way. + {IMGFMT_YV12, PIX_FMT_YUVJ420P}, + {IMGFMT_422P, PIX_FMT_YUVJ422P}, + {IMGFMT_444P, PIX_FMT_YUVJ444P}, + {IMGFMT_440P, PIX_FMT_YUVJ440P}, + + {IMGFMT_XVMC_MOCO_MPEG2, PIX_FMT_XVMC_MPEG2_MC}, + {IMGFMT_XVMC_IDCT_MPEG2, PIX_FMT_XVMC_MPEG2_IDCT}, + {IMGFMT_VDPAU_MPEG1, PIX_FMT_VDPAU_MPEG1}, + {IMGFMT_VDPAU_MPEG2, PIX_FMT_VDPAU_MPEG2}, + {IMGFMT_VDPAU_H264, PIX_FMT_VDPAU_H264}, + {IMGFMT_VDPAU_WMV3, PIX_FMT_VDPAU_WMV3}, + {IMGFMT_VDPAU_VC1, PIX_FMT_VDPAU_VC1}, + {IMGFMT_VDPAU_MPEG4, PIX_FMT_VDPAU_MPEG4}, + {0, PIX_FMT_NONE} +}; + +//copied from vf.c +extern const vf_info_t vf_info_vo; +extern const vf_info_t vf_info_rectangle; +extern const vf_info_t vf_info_bmovl; +extern const vf_info_t vf_info_crop; +extern const vf_info_t vf_info_expand; +extern const vf_info_t vf_info_pp; +extern const vf_info_t vf_info_scale; +extern const vf_info_t vf_info_format; +extern const vf_info_t vf_info_noformat; +extern const vf_info_t vf_info_flip; +extern const vf_info_t vf_info_rotate; +extern const vf_info_t vf_info_mirror; +extern const vf_info_t vf_info_palette; +extern const vf_info_t vf_info_lavc; +extern const vf_info_t vf_info_zrmjpeg; +extern const vf_info_t vf_info_dvbscale; +extern const vf_info_t vf_info_cropdetect; +extern const vf_info_t vf_info_test; +extern const vf_info_t vf_info_noise; +extern const vf_info_t vf_info_yvu9; +extern const vf_info_t vf_info_lavcdeint; +extern const vf_info_t vf_info_eq; +extern const vf_info_t vf_info_eq2; +extern const vf_info_t vf_info_gradfun; +extern const vf_info_t vf_info_halfpack; +extern const vf_info_t vf_info_dint; +extern const vf_info_t vf_info_1bpp; +extern const vf_info_t vf_info_2xsai; +extern const vf_info_t vf_info_unsharp; +extern const vf_info_t vf_info_swapuv; +extern const vf_info_t vf_info_il; +extern const vf_info_t vf_info_fil; +extern const vf_info_t vf_info_boxblur; +extern const vf_info_t vf_info_sab; +extern const vf_info_t vf_info_smartblur; +extern const vf_info_t vf_info_perspective; +extern const vf_info_t vf_info_down3dright; +extern const vf_info_t vf_info_field; +extern const vf_info_t vf_info_denoise3d; +extern const vf_info_t vf_info_hqdn3d; +extern const vf_info_t vf_info_detc; +extern const vf_info_t vf_info_telecine; +extern const vf_info_t vf_info_tinterlace; +extern const vf_info_t vf_info_tfields; +extern const vf_info_t vf_info_ivtc; +extern const vf_info_t vf_info_ilpack; +extern const vf_info_t vf_info_dsize; +extern const vf_info_t vf_info_decimate; +extern const vf_info_t vf_info_softpulldown; +extern const vf_info_t vf_info_pullup; +extern const vf_info_t vf_info_filmdint; +extern const vf_info_t vf_info_framestep; +extern const vf_info_t vf_info_tile; +extern const vf_info_t vf_info_delogo; +extern const vf_info_t vf_info_remove_logo; +extern const vf_info_t vf_info_hue; +extern const vf_info_t vf_info_spp; +extern const vf_info_t vf_info_uspp; +extern const vf_info_t vf_info_fspp; +extern const vf_info_t vf_info_pp7; +extern const vf_info_t vf_info_yuvcsp; +extern const vf_info_t vf_info_kerndeint; +extern const vf_info_t vf_info_rgbtest; +extern const vf_info_t vf_info_qp; +extern const vf_info_t vf_info_phase; +extern const vf_info_t vf_info_divtc; +extern const vf_info_t vf_info_harddup; +extern const vf_info_t vf_info_softskip; +extern const vf_info_t vf_info_screenshot; +extern const vf_info_t vf_info_ass; +extern const vf_info_t vf_info_mcdeint; +extern const vf_info_t vf_info_yadif; +extern const vf_info_t vf_info_blackframe; +extern const vf_info_t vf_info_geq; +extern const vf_info_t vf_info_ow; +extern const vf_info_t vf_info_fixpts; +extern const vf_info_t vf_info_stereo3d; + + +static const vf_info_t* const filters[]={ + &vf_info_2xsai, + &vf_info_blackframe, + &vf_info_boxblur, + &vf_info_cropdetect, + &vf_info_decimate, + &vf_info_delogo, + &vf_info_denoise3d, + &vf_info_detc, + &vf_info_dint, + &vf_info_divtc, + &vf_info_down3dright, + &vf_info_dsize, + &vf_info_eq2, + &vf_info_eq, + &vf_info_field, + &vf_info_fil, +// &vf_info_filmdint, cmmx.h vd.h ‘opt_screen_size_x’ + &vf_info_fixpts, + &vf_info_framestep, + &vf_info_fspp, + &vf_info_geq, + &vf_info_gradfun, + &vf_info_harddup, + &vf_info_hqdn3d, + &vf_info_hue, + &vf_info_il, + &vf_info_ilpack, + &vf_info_ivtc, + &vf_info_kerndeint, + &vf_info_mcdeint, + &vf_info_mirror, + &vf_info_noise, + &vf_info_ow, + &vf_info_palette, + &vf_info_perspective, + &vf_info_phase, + &vf_info_pp7, + &vf_info_pullup, + &vf_info_qp, + &vf_info_rectangle, + &vf_info_remove_logo, + &vf_info_rgbtest, + &vf_info_rotate, + &vf_info_sab, + &vf_info_screenshot, + &vf_info_smartblur, + &vf_info_softpulldown, + &vf_info_softskip, + &vf_info_spp, + &vf_info_swapuv, + &vf_info_telecine, + &vf_info_test, + &vf_info_tile, + &vf_info_tinterlace, + &vf_info_unsharp, + &vf_info_uspp, + &vf_info_yuvcsp, + &vf_info_yvu9, + + NULL +}; + +/* +Unsupported filters +1bpp +ass +bmovl +crop +dvbscale +flip +expand +format +halfpack +lavc +lavcdeint +noformat +pp +scale +stereo3d +tfields +vo +yadif +zrmjpeg +*/ + +CpuCaps gCpuCaps; //FIXME initialize this so optims work + + +static void sws_getFlagsAndFilterFromCmdLine(int *flags, SwsFilter **srcFilterParam, SwsFilter **dstFilterParam) +{ + static int firstTime=1; + *flags=0; + +#if ARCH_X86 + if(gCpuCaps.hasMMX) + __asm__ volatile("emms\n\t"::: "memory"); //FIXME this should not be required but it IS (even for non-MMX versions) +#endif + if(firstTime) + { + firstTime=0; + *flags= SWS_PRINT_INFO; + } + else if( mp_msg_test(MSGT_VFILTER,MSGL_DBG2) ) *flags= SWS_PRINT_INFO; + + switch(SWS_BILINEAR) + { + 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= NULL; + *dstFilterParam= NULL; +} + +//exact copy from vf_scale.c +// will use sws_flags & src_filter (from cmd line) +struct SwsContext *sws_getContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat) +{ + int flags, i; + SwsFilter *dstFilterParam, *srcFilterParam; + enum PixelFormat dfmt, sfmt; + + for(i=0; conversion_map[i].fmt && dstFormat != conversion_map[i].fmt; i++); + dfmt= conversion_map[i].pix_fmt; + for(i=0; conversion_map[i].fmt && srcFormat != conversion_map[i].fmt; i++); + sfmt= conversion_map[i].pix_fmt; + + 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 , srcFilterParam, dstFilterParam, NULL); +} + +typedef struct { + vf_instance_t vf; + vf_instance_t next_vf; + AVFilterContext *avfctx; + int frame_returned; +} MPContext; + +void mp_msg(int mod, int lev, const char *format, ... ){ + va_list va; + va_start(va, format); + //FIXME convert lev/mod + av_vlog(NULL, AV_LOG_DEBUG, format, va); + va_end(va); +} + +int mp_msg_test(int mod, int lev){ + return 123; +} + +void init_avcodec(void) +{ + //we maybe should init but its kinda 1. unneeded 2. a bit inpolite from here +} + +//Exact copy of vf.c +void vf_clone_mpi_attributes(mp_image_t* dst, mp_image_t* src){ + dst->pict_type= src->pict_type; + dst->fields = src->fields; + dst->qscale_type= src->qscale_type; + if(dst->width == src->width && dst->height == src->height){ + dst->qstride= src->qstride; + dst->qscale= src->qscale; + } +} + +//Exact copy of vf.c +void vf_next_draw_slice(struct vf_instance *vf,unsigned char** src, int * stride,int w, int h, int x, int y){ + if (vf->next->draw_slice) { + vf->next->draw_slice(vf->next,src,stride,w,h,x,y); + return; + } + if (!vf->dmpi) { + mp_msg(MSGT_VFILTER,MSGL_ERR,"draw_slice: dmpi not stored by vf_%s\n", vf->info->name); + return; + } + if (!(vf->dmpi->flags & MP_IMGFLAG_PLANAR)) { + memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+vf->dmpi->bpp/8*x, + src[0], vf->dmpi->bpp/8*w, h, vf->dmpi->stride[0], stride[0]); + return; + } + memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+x, src[0], + w, h, vf->dmpi->stride[0], stride[0]); + memcpy_pic(vf->dmpi->planes[1]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[1]+(x>>vf->dmpi->chroma_x_shift), + src[1], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[1], stride[1]); + memcpy_pic(vf->dmpi->planes[2]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[2]+(x>>vf->dmpi->chroma_x_shift), + src[2], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[2], stride[2]); +} + +//Exact copy of vf.c +void vf_mpi_clear(mp_image_t* mpi,int x0,int y0,int w,int h){ + int y; + if(mpi->flags&MP_IMGFLAG_PLANAR){ + y0&=~1;h+=h&1; + if(x0==0 && w==mpi->width){ + // full width clear: + memset(mpi->planes[0]+mpi->stride[0]*y0,0,mpi->stride[0]*h); + memset(mpi->planes[1]+mpi->stride[1]*(y0>>mpi->chroma_y_shift),128,mpi->stride[1]*(h>>mpi->chroma_y_shift)); + memset(mpi->planes[2]+mpi->stride[2]*(y0>>mpi->chroma_y_shift),128,mpi->stride[2]*(h>>mpi->chroma_y_shift)); + } else + for(y=y0;y<y0+h;y+=2){ + memset(mpi->planes[0]+x0+mpi->stride[0]*y,0,w); + memset(mpi->planes[0]+x0+mpi->stride[0]*(y+1),0,w); + memset(mpi->planes[1]+(x0>>mpi->chroma_x_shift)+mpi->stride[1]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift)); + memset(mpi->planes[2]+(x0>>mpi->chroma_x_shift)+mpi->stride[2]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift)); + } + return; + } + // packed: + for(y=y0;y<y0+h;y++){ + unsigned char* dst=mpi->planes[0]+mpi->stride[0]*y+(mpi->bpp>>3)*x0; + if(mpi->flags&MP_IMGFLAG_YUV){ + unsigned int* p=(unsigned int*) dst; + int size=(mpi->bpp>>3)*w/4; + int i; +#if HAVE_BIGENDIAN +#define CLEAR_PACKEDYUV_PATTERN 0x00800080 +#define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x80008000 +#else +#define CLEAR_PACKEDYUV_PATTERN 0x80008000 +#define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x00800080 +#endif + if(mpi->flags&MP_IMGFLAG_SWAPPED){ + for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN_SWAPPED; + for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN_SWAPPED; + } else { + for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN; + for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN; + } + } else + memset(dst,0,(mpi->bpp>>3)*w); + } +} + +int vf_next_query_format(struct vf_instance *vf, unsigned int fmt){ + return 1; +} + +//used by delogo +unsigned int vf_match_csp(vf_instance_t** vfp,const unsigned int* list,unsigned int preferred){ + return preferred; +} + +mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, int mp_imgflag, int w, int h){ + MPContext *m= ((uint8_t*)vf) - offsetof(MPContext, next_vf); + mp_image_t* mpi=NULL; + int w2; + int number = mp_imgtype >> 16; + + av_assert0(vf->next == NULL); // all existing filters call this just on next + + //vf_dint needs these as it calls vf_get_image() before configuring the output + if(vf->w==0 && w>0) vf->w=w; + if(vf->h==0 && h>0) vf->h=h; + + av_assert0(w == -1 || w >= vf->w); + av_assert0(h == -1 || h >= vf->h); + av_assert0(vf->w > 0); + av_assert0(vf->h > 0); + + av_log(m->avfctx, AV_LOG_DEBUG, "get_image: %d:%d, vf: %d:%d\n", w,h,vf->w,vf->h); + + if (w == -1) w = vf->w; + if (h == -1) h = vf->h; + + w2=(mp_imgflag&MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE)?((w+15)&(~15)):w; + + // Note: we should call libvo first to check if it supports direct rendering + // and if not, then fallback to software buffers: + switch(mp_imgtype & 0xff){ + case MP_IMGTYPE_EXPORT: + if(!vf->imgctx.export_images[0]) vf->imgctx.export_images[0]=new_mp_image(w2,h); + mpi=vf->imgctx.export_images[0]; + break; + case MP_IMGTYPE_STATIC: + if(!vf->imgctx.static_images[0]) vf->imgctx.static_images[0]=new_mp_image(w2,h); + mpi=vf->imgctx.static_images[0]; + break; + case MP_IMGTYPE_TEMP: + if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h); + mpi=vf->imgctx.temp_images[0]; + break; + case MP_IMGTYPE_IPB: + if(!(mp_imgflag&MP_IMGFLAG_READABLE)){ // B frame: + if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h); + mpi=vf->imgctx.temp_images[0]; + break; + } + case MP_IMGTYPE_IP: + if(!vf->imgctx.static_images[vf->imgctx.static_idx]) vf->imgctx.static_images[vf->imgctx.static_idx]=new_mp_image(w2,h); + mpi=vf->imgctx.static_images[vf->imgctx.static_idx]; + vf->imgctx.static_idx^=1; + break; + case MP_IMGTYPE_NUMBERED: + if (number == -1) { + int i; + for (i = 0; i < NUM_NUMBERED_MPI; i++) + if (!vf->imgctx.numbered_images[i] || !vf->imgctx.numbered_images[i]->usage_count) + break; + number = i; + } + if (number < 0 || number >= NUM_NUMBERED_MPI) return NULL; + if (!vf->imgctx.numbered_images[number]) vf->imgctx.numbered_images[number] = new_mp_image(w2,h); + mpi = vf->imgctx.numbered_images[number]; + mpi->number = number; + break; + } + if(mpi){ + mpi->type=mp_imgtype; + mpi->w=vf->w; mpi->h=vf->h; + // keep buffer allocation status & color flags only: +// mpi->flags&=~(MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE|MP_IMGFLAG_DIRECT); + mpi->flags&=MP_IMGFLAG_ALLOCATED|MP_IMGFLAG_TYPE_DISPLAYED|MP_IMGFLAGMASK_COLORS; + // accept restrictions, draw_slice and palette flags only: + mpi->flags|=mp_imgflag&(MP_IMGFLAGMASK_RESTRICTIONS|MP_IMGFLAG_DRAW_CALLBACK|MP_IMGFLAG_RGB_PALETTE); + if(!vf->draw_slice) mpi->flags&=~MP_IMGFLAG_DRAW_CALLBACK; + if(mpi->width!=w2 || mpi->height!=h){ +// printf("vf.c: MPI parameters changed! %dx%d -> %dx%d \n", mpi->width,mpi->height,w2,h); + if(mpi->flags&MP_IMGFLAG_ALLOCATED){ + if(mpi->width<w2 || mpi->height<h){ + // need to re-allocate buffer memory: + av_free(mpi->planes[0]); + mpi->flags&=~MP_IMGFLAG_ALLOCATED; + mp_msg(MSGT_VFILTER,MSGL_V,"vf.c: have to REALLOCATE buffer memory :(\n"); + } +// } else { + } { + mpi->width=w2; mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift; + mpi->height=h; mpi->chroma_height=(h + (1<<mpi->chroma_y_shift) - 1)>>mpi->chroma_y_shift; + } + } + if(!mpi->bpp) mp_image_setfmt(mpi,outfmt); + if(!(mpi->flags&MP_IMGFLAG_ALLOCATED) && mpi->type>MP_IMGTYPE_EXPORT){ + + av_assert0(!vf->get_image); + // check libvo first! + if(vf->get_image) vf->get_image(vf,mpi); + + if(!(mpi->flags&MP_IMGFLAG_DIRECT)){ + // non-direct and not yet allocated image. allocate it! + if (!mpi->bpp) { // no way we can allocate this + mp_msg(MSGT_DECVIDEO, MSGL_FATAL, + "vf_get_image: Tried to allocate a format that can not be allocated!\n"); + return NULL; + } + + // check if codec prefer aligned stride: + if(mp_imgflag&MP_IMGFLAG_PREFER_ALIGNED_STRIDE){ + int align=(mpi->flags&MP_IMGFLAG_PLANAR && + mpi->flags&MP_IMGFLAG_YUV) ? + (8<<mpi->chroma_x_shift)-1 : 15; // -- maybe FIXME + w2=((w+align)&(~align)); + if(mpi->width!=w2){ +#if 0 + // we have to change width... check if we CAN co it: + int flags=vf->query_format(vf,outfmt); // should not fail + if(!(flags&3)) mp_msg(MSGT_DECVIDEO,MSGL_WARN,"??? vf_get_image{vf->query_format(outfmt)} failed!\n"); +// printf("query -> 0x%X \n",flags); + if(flags&VFCAP_ACCEPT_STRIDE){ +#endif + mpi->width=w2; + mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift; +// } + } + } + + mp_image_alloc_planes(mpi); +// printf("clearing img!\n"); + vf_mpi_clear(mpi,0,0,mpi->width,mpi->height); + } + } + av_assert0(!vf->start_slice); + if(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK) + if(vf->start_slice) vf->start_slice(vf,mpi); + if(!(mpi->flags&MP_IMGFLAG_TYPE_DISPLAYED)){ + mp_msg(MSGT_DECVIDEO,MSGL_V,"*** [%s] %s%s mp_image_t, %dx%dx%dbpp %s %s, %d bytes\n", + "NULL"/*vf->info->name*/, + (mpi->type==MP_IMGTYPE_EXPORT)?"Exporting": + ((mpi->flags&MP_IMGFLAG_DIRECT)?"Direct Rendering":"Allocating"), + (mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)?" (slices)":"", + mpi->width,mpi->height,mpi->bpp, + (mpi->flags&MP_IMGFLAG_YUV)?"YUV":((mpi->flags&MP_IMGFLAG_SWAPPED)?"BGR":"RGB"), + (mpi->flags&MP_IMGFLAG_PLANAR)?"planar":"packed", + mpi->bpp*mpi->width*mpi->height/8); + mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"(imgfmt: %x, planes: %p,%p,%p strides: %d,%d,%d, chroma: %dx%d, shift: h:%d,v:%d)\n", + mpi->imgfmt, mpi->planes[0], mpi->planes[1], mpi->planes[2], + mpi->stride[0], mpi->stride[1], mpi->stride[2], + mpi->chroma_width, mpi->chroma_height, mpi->chroma_x_shift, mpi->chroma_y_shift); + mpi->flags|=MP_IMGFLAG_TYPE_DISPLAYED; + } + + mpi->qscale = NULL; + } + mpi->usage_count++; +// printf("\rVF_MPI: %p %p %p %d %d %d \n", +// mpi->planes[0],mpi->planes[1],mpi->planes[2], +// mpi->stride[0],mpi->stride[1],mpi->stride[2]); + return mpi; +} + + +int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts){ + MPContext *m= (void*)vf; + AVFilterLink *outlink = m->avfctx->outputs[0]; + AVFilterBuffer *pic = av_mallocz(sizeof(AVFilterBuffer)); + AVFilterBufferRef *picref = av_mallocz(sizeof(AVFilterBufferRef)); + int i; + + av_assert0(vf->next); + + av_log(m->avfctx, AV_LOG_DEBUG, "vf_next_put_image\n"); + + if (!pic || !picref) + goto fail; + + picref->buf = pic; + picref->buf->please_use_av_free= av_free; + if (!(picref->video = av_mallocz(sizeof(AVFilterBufferRefVideoProps)))) + goto fail; + + pic->w = picref->video->w = mpi->w; + pic->h = picref->video->h = mpi->h; + + /* make sure the buffer gets read permission or it's useless for output */ + picref->perms = AV_PERM_READ | AV_PERM_REUSE2; +// av_assert0(mpi->flags&MP_IMGFLAG_READABLE); + if(!(mpi->flags&MP_IMGFLAG_PRESERVE)) + picref->perms |= AV_PERM_WRITE; + + pic->refcount = 1; + picref->type = AVMEDIA_TYPE_VIDEO; + + for(i=0; conversion_map[i].fmt && mpi->imgfmt != conversion_map[i].fmt; i++); + pic->format = picref->format = conversion_map[i].pix_fmt; + + memcpy(pic->data, mpi->planes, FFMIN(sizeof(pic->data) , sizeof(mpi->planes))); + memcpy(pic->linesize, mpi->stride, FFMIN(sizeof(pic->linesize), sizeof(mpi->stride))); + memcpy(picref->data, pic->data, sizeof(picref->data)); + memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize)); + + if(pts != MP_NOPTS_VALUE) + picref->pts= pts * av_q2d(outlink->time_base); + + avfilter_start_frame(outlink, avfilter_ref_buffer(picref, ~0)); + avfilter_draw_slice(outlink, 0, picref->video->h, 1); + avfilter_end_frame(outlink); + avfilter_unref_buffer(picref); + m->frame_returned++; + + return 1; +fail: + if (picref && picref->video) + av_free(picref->video); + av_free(picref); + av_free(pic); + return 0; +} + +int vf_next_config(struct vf_instance *vf, + int width, int height, int d_width, int d_height, + unsigned int voflags, unsigned int outfmt){ + + av_assert0(width>0 && height>0); + vf->next->w = width; vf->next->h = height; + + return 1; +#if 0 + int flags=vf->next->query_format(vf->next,outfmt); + if(!flags){ + // hmm. colorspace mismatch!!! + //this is fatal for us ATM + return 0; + } + mp_msg(MSGT_VFILTER,MSGL_V,"REQ: flags=0x%X req=0x%X \n",flags,vf->default_reqs); + miss=vf->default_reqs - (flags&vf->default_reqs); + if(miss&VFCAP_ACCEPT_STRIDE){ + // vf requires stride support but vf->next doesn't support it! + // let's insert the 'expand' filter, it does the job for us: + vf_instance_t* vf2=vf_open_filter(vf->next,"expand",NULL); + if(!vf2) return 0; // shouldn't happen! + vf->next=vf2; + } + vf->next->w = width; vf->next->h = height; +#endif + return 1; +} + +int vf_next_control(struct vf_instance *vf, int request, void* data){ + MPContext *m= (void*)vf; + av_log(m->avfctx, AV_LOG_DEBUG, "Received control %d\n", request); + return 0; +} + +static int vf_default_query_format(struct vf_instance *vf, unsigned int fmt){ + MPContext *m= (void*)vf; + int i; + av_log(m->avfctx, AV_LOG_DEBUG, "query %X\n", fmt); + + for(i=0; conversion_map[i].fmt; i++){ + if(fmt==conversion_map[i].fmt) + return 1; //we suport all + } + return 0; +} + + +static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) +{ + MPContext *m = ctx->priv; + char name[256]; + int i; + + av_log(ctx, AV_LOG_WARNING, +"This is a unholy filter, it will be purified by the ffmpeg exorcist team\n" +"which will change its syntax from dark -vf mp to light -vf.\n" +"Thou shalst not make spells or scripts that depend on it\n"); + + m->avfctx= ctx; + + if(!args || 1!=sscanf(args, "%255[^:=]", name)){ + av_log(ctx, AV_LOG_ERROR, "Invalid parameter.\n"); + return AVERROR(EINVAL); + } + args+= strlen(name)+1; + + for(i=0; ;i++){ + if(!filters[i] || !strcmp(name, filters[i]->name)) + break; + } + + if(!filters[i]){ + av_log(ctx, AV_LOG_ERROR, "Unknown filter %s\n", name); + return AVERROR(EINVAL); + } + + memset(&m->vf,0,sizeof(m->vf)); + m->vf.info= filters[i]; + + m->vf.next = &m->next_vf; + m->vf.put_image = vf_next_put_image; + m->vf.config = vf_next_config; + m->vf.query_format= vf_default_query_format; + m->vf.control = vf_next_control; + m->vf.default_caps=VFCAP_ACCEPT_STRIDE; + m->vf.default_reqs=0; + if(m->vf.info->opts) + av_log(ctx, AV_LOG_ERROR, "opts / m_struct_set is unsupported\n"); +#if 0 + if(vf->info->opts) { // vf_vo get some special argument + const m_struct_t* st = vf->info->opts; + void* vf_priv = m_struct_alloc(st); + int n; + for(n = 0 ; args && args[2*n] ; n++) + m_struct_set(st,vf_priv,args[2*n],args[2*n+1]); + vf->priv = vf_priv; + args = NULL; + } else // Otherwise we should have the '_oldargs_' + if(args && !strcmp(args[0],"_oldargs_")) + args = (char**)args[1]; + else + args = NULL; +#endif + if(m->vf.info->vf_open(&m->vf, args)<=0){ + av_log(ctx, AV_LOG_ERROR, "vf_open() of %s with arg=%s failed\n", name, args); + return -1; + } + + return 0; +} + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *avfmts=NULL; + MPContext *m = ctx->priv; + enum PixelFormat lastpixfmt = PIX_FMT_NONE; + int i; + + for(i=0; conversion_map[i].fmt; i++){ + av_log(ctx, AV_LOG_DEBUG, "query: %X\n", conversion_map[i].fmt); + if(m->vf.query_format(&m->vf, conversion_map[i].fmt)){ + av_log(ctx, AV_LOG_DEBUG, "supported,adding\n"); + if (conversion_map[i].pix_fmt != lastpixfmt) { + avfilter_add_format(&avfmts, conversion_map[i].pix_fmt); + lastpixfmt = conversion_map[i].pix_fmt; + } + } + } + + //We assume all allowed input formats are also allowed output formats + avfilter_set_common_pixel_formats(ctx, avfmts); + return 0; +} + +static int config_inprops(AVFilterLink *inlink) +{ + MPContext *m = inlink->dst->priv; + int i; + for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++); + + av_assert0(conversion_map[i].fmt && inlink->w && inlink->h); + + m->vf.fmt.have_configured = 1; + m->vf.fmt.orig_height = inlink->h; + m->vf.fmt.orig_width = inlink->w; + m->vf.fmt.orig_fmt = conversion_map[i].fmt; + + if(m->vf.config(&m->vf, inlink->w, inlink->h, inlink->w, inlink->h, 0, conversion_map[i].fmt)<=0) + return -1; + + return 0; +} + +static int config_outprops(AVFilterLink *outlink) +{ + MPContext *m = outlink->src->priv; + + outlink->w = m->next_vf.w; + outlink->h = m->next_vf.h; + + return 0; +} + +static int request_frame(AVFilterLink *outlink) +{ + MPContext *m = outlink->src->priv; + int ret; + + av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame\n"); + + for(m->frame_returned=0; !m->frame_returned;){ + ret=avfilter_request_frame(outlink->src->inputs[0]); + if(ret<0) + break; + } + + av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame ret=%d\n", ret); + return ret; +} + +static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) +{ +} + +static void null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) +{ +} + +static void end_frame(AVFilterLink *inlink) +{ + MPContext *m = inlink->dst->priv; + AVFilterBufferRef *inpic = inlink->cur_buf; + int i; + double pts= MP_NOPTS_VALUE; + mp_image_t* mpi = new_mp_image(inpic->video->w, inpic->video->h); + + if(inpic->pts != AV_NOPTS_VALUE) + pts= inpic->pts / av_q2d(inlink->time_base); + + for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++); + mp_image_setfmt(mpi,conversion_map[i].fmt); + + memcpy(mpi->planes, inpic->data, FFMIN(sizeof(inpic->data) , sizeof(mpi->planes))); + memcpy(mpi->stride, inpic->linesize, FFMIN(sizeof(inpic->linesize), sizeof(mpi->stride))); + + //FIXME pass interleced & tff flags around + + // mpi->flags|=MP_IMGFLAG_ALLOCATED; ? + mpi->flags |= MP_IMGFLAG_READABLE; + if(!(inpic->perms & AV_PERM_WRITE)) + mpi->flags |= MP_IMGFLAG_PRESERVE; + if(m->vf.put_image(&m->vf, mpi, pts) == 0){ + av_log(m->avfctx, AV_LOG_DEBUG, "put_image() says skip\n"); + } + free_mp_image(mpi); + + avfilter_unref_buffer(inpic); +} + +AVFilter avfilter_vf_mp = { + .name = "mp", + .description = NULL_IF_CONFIG_SMALL("libmpcodecs wrapper."), + .init = init, + .priv_size = sizeof(MPContext), + .query_formats = query_formats, + + .inputs = (AVFilterPad[]) {{ .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .start_frame = start_frame, + .draw_slice = null_draw_slice, + .end_frame = end_frame, + .config_props = config_inprops, + .min_perms = AV_PERM_READ, }, + { .name = NULL}}, + .outputs = (AVFilterPad[]) {{ .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .request_frame = request_frame, + .config_props = config_outprops, }, + { .name = NULL}}, +}; diff --git a/libavfilter/vf_null.c b/libavfilter/vf_null.c index 8414c5f4fa..989cd86fc1 100644 --- a/libavfilter/vf_null.c +++ b/libavfilter/vf_null.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c index 39b2375235..d473c1b62b 100644 --- a/libavfilter/vf_overlay.c +++ b/libavfilter/vf_overlay.c @@ -3,20 +3,20 @@ * Copyright (c) 2010 Baptiste Coudurier * Copyright (c) 2007 Bobby Bingham * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavfilter/vf_pad.c b/libavfilter/vf_pad.c index 851172c058..e01a750d94 100644 --- a/libavfilter/vf_pad.c +++ b/libavfilter/vf_pad.c @@ -2,26 +2,26 @@ * Copyright (c) 2008 vmrsss * Copyright (c) 2009 Stefano Sabatini * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * @file - * video padding filter and color source + * video padding filter */ #include "avfilter.h" @@ -45,7 +45,8 @@ static const char *var_names[] = { "out_h", "oh", "x", "y", - "a", + "a", "dar", + "sar", "hsub", "vsub", NULL @@ -61,7 +62,8 @@ enum var_name { VAR_OUT_H, VAR_OH, VAR_X, VAR_Y, - VAR_A, + VAR_A, VAR_DAR, + VAR_SAR, VAR_HSUB, VAR_VSUB, VARS_NB @@ -84,7 +86,7 @@ static int query_formats(AVFilterContext *ctx) PIX_FMT_NONE }; - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); return 0; } @@ -156,9 +158,11 @@ static int config_input(AVFilterLink *inlink) var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h; var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN; var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN; - var_values[VAR_A] = (float) inlink->w / inlink->h; + var_values[VAR_DAR] = var_values[VAR_A] = (float) inlink->w / inlink->h; + var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? + (float) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1; var_values[VAR_HSUB] = 1<<pad->hsub; - var_values[VAR_VSUB] = 2<<pad->vsub; + var_values[VAR_VSUB] = 1<<pad->vsub; /* evaluate width and height */ av_expr_parse_and_eval(&res, (expr = pad->w_expr), diff --git a/libavfilter/vf_pixdesctest.c b/libavfilter/vf_pixdesctest.c index 344f6648f1..1fb577e7fc 100644 --- a/libavfilter/vf_pixdesctest.c +++ b/libavfilter/vf_pixdesctest.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2009 Stefano Sabatini * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index 9ec686f8f9..3be5d99e96 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2007 Bobby Bingham * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -28,6 +28,7 @@ #include "libavutil/eval.h" #include "libavutil/mathematics.h" #include "libavutil/pixdesc.h" +#include "libavutil/avassert.h" #include "libswscale/swscale.h" static const char *var_names[] = { @@ -38,7 +39,8 @@ static const char *var_names[] = { "in_h", "ih", "out_w", "ow", "out_h", "oh", - "a", + "a", "dar", + "sar", "hsub", "vsub", NULL @@ -52,7 +54,8 @@ enum var_name { VAR_IN_H, VAR_IH, VAR_OUT_W, VAR_OW, VAR_OUT_H, VAR_OH, - VAR_A, + VAR_A, VAR_DAR, + VAR_SAR, VAR_HSUB, VAR_VSUB, VARS_NB @@ -60,6 +63,7 @@ enum var_name { typedef struct { struct SwsContext *sws; ///< software scaler context + struct SwsContext *isws[2]; ///< software scaler context for interlaced material /** * New dimensions. Special values are: @@ -72,6 +76,7 @@ typedef struct { int hsub, vsub; ///< chroma subsampling int slice_y; ///< top of current output slice int input_is_pal; ///< set to 1 if the input format is paletted + int interlaced; char w_expr[256]; ///< width expression string char h_expr[256]; ///< height expression string @@ -90,6 +95,10 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) sscanf(args, "%255[^:]:%255[^:]", scale->w_expr, scale->h_expr); p = strstr(args,"flags="); if (p) scale->flags = strtoul(p+6, NULL, 0); + if(strstr(args,"interl=1")){ + scale->interlaced=1; + }else if(strstr(args,"interl=-1")) + scale->interlaced=-1; } return 0; @@ -99,6 +108,8 @@ static av_cold void uninit(AVFilterContext *ctx) { ScaleContext *scale = ctx->priv; sws_freeContext(scale->sws); + sws_freeContext(scale->isws[0]); + sws_freeContext(scale->isws[1]); scale->sws = NULL; } @@ -149,7 +160,9 @@ static int config_props(AVFilterLink *outlink) var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h; var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN; var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN; - var_values[VAR_A] = (float) inlink->w / inlink->h; + var_values[VAR_DAR] = var_values[VAR_A] = (float) inlink->w / inlink->h; + var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? + (float) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1; var_values[VAR_HSUB] = 1<<av_pix_fmt_descriptors[inlink->format].log2_chroma_w; var_values[VAR_VSUB] = 1<<av_pix_fmt_descriptors[inlink->format].log2_chroma_h; @@ -206,9 +219,21 @@ static int config_props(AVFilterLink *outlink) scale->input_is_pal = av_pix_fmt_descriptors[inlink->format].flags & PIX_FMT_PAL; + if (scale->sws) + sws_freeContext(scale->sws); scale->sws = sws_getContext(inlink ->w, inlink ->h, inlink ->format, outlink->w, outlink->h, outlink->format, scale->flags, NULL, NULL, NULL); + if (scale->isws[0]) + sws_freeContext(scale->isws[0]); + scale->isws[0] = sws_getContext(inlink ->w, inlink ->h/2, inlink ->format, + outlink->w, outlink->h/2, outlink->format, + scale->flags, NULL, NULL, NULL); + if (scale->isws[1]) + sws_freeContext(scale->isws[1]); + scale->isws[1] = sws_getContext(inlink ->w, inlink ->h/2, inlink ->format, + outlink->w, outlink->h/2, outlink->format, + scale->flags, NULL, NULL, NULL); if (!scale->sws) return AVERROR(EINVAL); @@ -236,35 +261,56 @@ static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref) outlink->out_buf = outpicref; - av_reduce(&outpicref->video->pixel_aspect.num, &outpicref->video->pixel_aspect.den, - (int64_t)picref->video->pixel_aspect.num * outlink->h * link->w, - (int64_t)picref->video->pixel_aspect.den * outlink->w * link->h, + av_reduce(&outpicref->video->sample_aspect_ratio.num, &outpicref->video->sample_aspect_ratio.den, + (int64_t)picref->video->sample_aspect_ratio.num * outlink->h * link->w, + (int64_t)picref->video->sample_aspect_ratio.den * outlink->w * link->h, INT_MAX); scale->slice_y = 0; avfilter_start_frame(outlink, avfilter_ref_buffer(outpicref, ~0)); } +static int scale_slice(AVFilterLink *link, struct SwsContext *sws, int y, int h, int mul, int field) +{ + ScaleContext *scale = link->dst->priv; + AVFilterBufferRef *cur_pic = link->cur_buf; + AVFilterBufferRef *out_buf = link->dst->outputs[0]->out_buf; + const uint8_t *in[4]; + uint8_t *out[4]; + int in_stride[4],out_stride[4]; + int i; + + for(i=0; i<4; i++){ + int vsub= ((i+1)&2) ? scale->vsub : 0; + in_stride[i] = cur_pic->linesize[i] * mul; + out_stride[i] = out_buf->linesize[i] * mul; + in[i] = cur_pic->data[i] + ((y>>vsub)+field) * cur_pic->linesize[i]; + out[i] = out_buf->data[i] + field * out_buf->linesize[i]; + } + if(scale->input_is_pal){ + in[1] = cur_pic->data[1]; + out[1] = out_buf->data[1]; + } + + return sws_scale(sws, in, in_stride, y/mul, h, + out,out_stride); +} + static void draw_slice(AVFilterLink *link, int y, int h, int slice_dir) { ScaleContext *scale = link->dst->priv; int out_h; - AVFilterBufferRef *cur_pic = link->cur_buf; - const uint8_t *data[4]; if (scale->slice_y == 0 && slice_dir == -1) scale->slice_y = link->dst->outputs[0]->h; - data[0] = cur_pic->data[0] + y * cur_pic->linesize[0]; - data[1] = scale->input_is_pal ? - cur_pic->data[1] : - cur_pic->data[1] + (y>>scale->vsub) * cur_pic->linesize[1]; - data[2] = cur_pic->data[2] + (y>>scale->vsub) * cur_pic->linesize[2]; - data[3] = cur_pic->data[3] + y * cur_pic->linesize[3]; - - out_h = sws_scale(scale->sws, data, cur_pic->linesize, y, h, - link->dst->outputs[0]->out_buf->data, - link->dst->outputs[0]->out_buf->linesize); + if(scale->interlaced>0 || (scale->interlaced<0 && link->cur_buf->video->interlaced)){ + av_assert0(y%4 == 0); + out_h = scale_slice(link, scale->isws[0], y, (h+1)/2, 2, 0); + out_h+= scale_slice(link, scale->isws[1], y, h /2, 2, 1); + }else{ + out_h = scale_slice(link, scale->sws, y, h, 1, 0); + } if (slice_dir == -1) scale->slice_y -= out_h; diff --git a/libavfilter/vf_select.c b/libavfilter/vf_select.c new file mode 100644 index 0000000000..3d05167d13 --- /dev/null +++ b/libavfilter/vf_select.c @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2011 Stefano Sabatini + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * filter for selecting which frame passes in the filterchain + */ + +#include "libavutil/eval.h" +#include "libavutil/fifo.h" +#include "avfilter.h" + +static const char *var_names[] = { + "E", ///< Euler number + "PHI", ///< golden ratio + "PI", ///< greek pi + + "TB", ///< timebase + + "pts", ///< original pts in the file of the frame + "start_pts", ///< first PTS in the stream, expressed in TB units + "prev_pts", ///< previous frame PTS + "prev_selected_pts", ///< previous selected frame PTS + + "t", ///< first PTS in seconds + "start_t", ///< first PTS in the stream, expressed in seconds + "prev_t", ///< previous frame time + "prev_selected_t", ///< previously selected time + + "pict_type", ///< the type of picture in the movie + "PICT_TYPE_I", + "PICT_TYPE_P", + "PICT_TYPE_B", + "PICT_TYPE_S", + "PICT_TYPE_SI", + "PICT_TYPE_SP", + "PICT_TYPE_BI", + + "interlace_type", ///< the frame interlace type + "INTERLACE_TYPE_P", + "INTERLACE_TYPE_T", + "INTERLACE_TYPE_B", + + "n", ///< frame number (starting from zero) + "selected_n", ///< selected frame number (starting from zero) + "prev_selected_n", ///< number of the last selected frame + + "key", ///< tell if the frame is a key frame + "pos", ///< original position in the file of the frame + + NULL +}; + +enum var_name { + VAR_E, + VAR_PHI, + VAR_PI, + + VAR_TB, + + VAR_PTS, + VAR_START_PTS, + VAR_PREV_PTS, + VAR_PREV_SELECTED_PTS, + + VAR_T, + VAR_START_T, + VAR_PREV_T, + VAR_PREV_SELECTED_T, + + VAR_PICT_TYPE, + VAR_PICT_TYPE_I, + VAR_PICT_TYPE_P, + VAR_PICT_TYPE_B, + VAR_PICT_TYPE_S, + VAR_PICT_TYPE_SI, + VAR_PICT_TYPE_SP, + VAR_PICT_TYPE_BI, + + VAR_INTERLACE_TYPE, + VAR_INTERLACE_TYPE_P, + VAR_INTERLACE_TYPE_T, + VAR_INTERLACE_TYPE_B, + + VAR_N, + VAR_SELECTED_N, + VAR_PREV_SELECTED_N, + + VAR_KEY, + VAR_POS, + + VAR_VARS_NB +}; + +#define FIFO_SIZE 8 + +typedef struct { + AVExpr *expr; + double var_values[VAR_VARS_NB]; + double select; + int cache_frames; + AVFifoBuffer *pending_frames; ///< FIFO buffer of video frames +} SelectContext; + +static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) +{ + SelectContext *select = ctx->priv; + int ret; + + if ((ret = av_expr_parse(&select->expr, args ? args : "1", + var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) { + av_log(ctx, AV_LOG_ERROR, "Error while parsing expression '%s'\n", args); + return ret; + } + + select->pending_frames = av_fifo_alloc(FIFO_SIZE*sizeof(AVFilterBufferRef*)); + if (!select->pending_frames) { + av_log(ctx, AV_LOG_ERROR, "Failed to allocate pending frames buffer.\n"); + return AVERROR(ENOMEM); + } + return 0; +} + +#define INTERLACE_TYPE_P 0 +#define INTERLACE_TYPE_T 1 +#define INTERLACE_TYPE_B 2 + +static int config_input(AVFilterLink *inlink) +{ + SelectContext *select = inlink->dst->priv; + + select->var_values[VAR_E] = M_E; + select->var_values[VAR_PHI] = M_PHI; + select->var_values[VAR_PI] = M_PI; + + select->var_values[VAR_N] = 0.0; + select->var_values[VAR_SELECTED_N] = 0.0; + + select->var_values[VAR_TB] = av_q2d(inlink->time_base); + + select->var_values[VAR_PREV_PTS] = NAN; + select->var_values[VAR_PREV_SELECTED_PTS] = NAN; + select->var_values[VAR_PREV_SELECTED_T] = NAN; + select->var_values[VAR_START_PTS] = NAN; + select->var_values[VAR_START_T] = NAN; + + select->var_values[VAR_PICT_TYPE_I] = AV_PICTURE_TYPE_I; + select->var_values[VAR_PICT_TYPE_P] = AV_PICTURE_TYPE_P; + select->var_values[VAR_PICT_TYPE_B] = AV_PICTURE_TYPE_B; + select->var_values[VAR_PICT_TYPE_SI] = AV_PICTURE_TYPE_SI; + select->var_values[VAR_PICT_TYPE_SP] = AV_PICTURE_TYPE_SP; + + select->var_values[VAR_INTERLACE_TYPE_P] = INTERLACE_TYPE_P; + select->var_values[VAR_INTERLACE_TYPE_T] = INTERLACE_TYPE_T; + select->var_values[VAR_INTERLACE_TYPE_B] = INTERLACE_TYPE_B;; + + return 0; +} + +#define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d)) +#define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)) + +static int select_frame(AVFilterContext *ctx, AVFilterBufferRef *picref) +{ + SelectContext *select = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + double res; + + if (isnan(select->var_values[VAR_START_PTS])) + select->var_values[VAR_START_PTS] = TS2D(picref->pts); + + select->var_values[VAR_PTS] = TS2D(picref->pts); + select->var_values[VAR_T ] = picref->pts * av_q2d(inlink->time_base); + select->var_values[VAR_POS] = picref->pos == -1 ? NAN : picref->pos; + select->var_values[VAR_PREV_PTS] = TS2D(picref ->pts); + + select->var_values[VAR_INTERLACE_TYPE] = + !picref->video->interlaced ? INTERLACE_TYPE_P : + picref->video->top_field_first ? INTERLACE_TYPE_T : INTERLACE_TYPE_B; + select->var_values[VAR_PICT_TYPE] = picref->video->pict_type; + + res = av_expr_eval(select->expr, select->var_values, NULL); + av_log(inlink->dst, AV_LOG_DEBUG, + "n:%d pts:%d t:%f pos:%d interlace_type:%c key:%d pict_type:%c " + "-> select:%f\n", + (int)select->var_values[VAR_N], + (int)select->var_values[VAR_PTS], + select->var_values[VAR_T], + (int)select->var_values[VAR_POS], + select->var_values[VAR_INTERLACE_TYPE] == INTERLACE_TYPE_P ? 'P' : + select->var_values[VAR_INTERLACE_TYPE] == INTERLACE_TYPE_T ? 'T' : + select->var_values[VAR_INTERLACE_TYPE] == INTERLACE_TYPE_B ? 'B' : '?', + (int)select->var_values[VAR_KEY], + av_get_picture_type_char(select->var_values[VAR_PICT_TYPE]), + res); + + select->var_values[VAR_N] += 1.0; + + if (res) { + select->var_values[VAR_PREV_SELECTED_N] = select->var_values[VAR_N]; + select->var_values[VAR_PREV_SELECTED_PTS] = select->var_values[VAR_PTS]; + select->var_values[VAR_PREV_SELECTED_T] = select->var_values[VAR_T]; + select->var_values[VAR_SELECTED_N] += 1.0; + } + return res; +} + +static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) +{ + SelectContext *select = inlink->dst->priv; + + select->select = select_frame(inlink->dst, picref); + if (select->select) { + /* frame was requested through poll_frame */ + if (select->cache_frames) { + if (!av_fifo_space(select->pending_frames)) + av_log(inlink->dst, AV_LOG_ERROR, + "Buffering limit reached, cannot cache more frames\n"); + else + av_fifo_generic_write(select->pending_frames, &picref, + sizeof(picref), NULL); + return; + } + avfilter_start_frame(inlink->dst->outputs[0], avfilter_ref_buffer(picref, ~0)); + } +} + +static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) +{ + SelectContext *select = inlink->dst->priv; + + if (select->select && !select->cache_frames) + avfilter_draw_slice(inlink->dst->outputs[0], y, h, slice_dir); +} + +static void end_frame(AVFilterLink *inlink) +{ + SelectContext *select = inlink->dst->priv; + AVFilterBufferRef *picref = inlink->cur_buf; + + if (select->select) { + if (select->cache_frames) + return; + avfilter_end_frame(inlink->dst->outputs[0]); + } + avfilter_unref_buffer(picref); +} + +static int request_frame(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + SelectContext *select = ctx->priv; + AVFilterLink *inlink = outlink->src->inputs[0]; + select->select = 0; + + if (av_fifo_size(select->pending_frames)) { + AVFilterBufferRef *picref; + av_fifo_generic_read(select->pending_frames, &picref, sizeof(picref), NULL); + avfilter_start_frame(outlink, avfilter_ref_buffer(picref, ~0)); + avfilter_draw_slice(outlink, 0, outlink->h, 1); + avfilter_end_frame(outlink); + avfilter_unref_buffer(picref); + return 0; + } + + while (!select->select) { + int ret = avfilter_request_frame(inlink); + if (ret < 0) + return ret; + } + + return 0; +} + +static int poll_frame(AVFilterLink *outlink) +{ + SelectContext *select = outlink->src->priv; + AVFilterLink *inlink = outlink->src->inputs[0]; + int count, ret; + + if (!av_fifo_size(select->pending_frames)) { + if ((count = avfilter_poll_frame(inlink)) <= 0) + return count; + /* request frame from input, and apply select condition to it */ + select->cache_frames = 1; + while (count-- && av_fifo_space(select->pending_frames)) { + ret = avfilter_request_frame(inlink); + if (ret < 0) + break; + } + select->cache_frames = 0; + } + + return av_fifo_size(select->pending_frames)/sizeof(AVFilterBufferRef *); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + SelectContext *select = ctx->priv; + AVFilterBufferRef *picref; + int i; + + av_expr_free(select->expr); + select->expr = NULL; + + for (i = 0; i < av_fifo_size(select->pending_frames)/sizeof(picref); i++) { + av_fifo_generic_read(select->pending_frames, &picref, sizeof(picref), NULL); + avfilter_unref_buffer(picref); + } + av_fifo_free(select->pending_frames); +} + +AVFilter avfilter_vf_select = { + .name = "select", + .description = NULL_IF_CONFIG_SMALL("Select frames to pass in output."), + .init = init, + .uninit = uninit, + + .priv_size = sizeof(SelectContext), + + .inputs = (AVFilterPad[]) {{ .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .get_video_buffer = avfilter_null_get_video_buffer, + .config_props = config_input, + .start_frame = start_frame, + .draw_slice = draw_slice, + .end_frame = end_frame }, + { .name = NULL }}, + .outputs = (AVFilterPad[]) {{ .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .poll_frame = poll_frame, + .request_frame = request_frame, }, + { .name = NULL}}, +}; diff --git a/libavfilter/vf_setpts.c b/libavfilter/vf_setpts.c index f2650923d0..ace2595346 100644 --- a/libavfilter/vf_setpts.c +++ b/libavfilter/vf_setpts.c @@ -2,20 +2,20 @@ * Copyright (c) 2010 Stefano Sabatini * Copyright (c) 2008 Victor Paesa * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavfilter/vf_settb.c b/libavfilter/vf_settb.c index eeb4353915..d0ac35c8f2 100644 --- a/libavfilter/vf_settb.c +++ b/libavfilter/vf_settb.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2010 Stefano Sabatini * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c new file mode 100644 index 0000000000..82aa3b9901 --- /dev/null +++ b/libavfilter/vf_showinfo.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2011 Stefano Sabatini + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * filter fow showing textual video frame information + */ + +#include "libavutil/adler32.h" +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" + +typedef struct { + unsigned int frame; +} ShowInfoContext; + +static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) +{ + ShowInfoContext *showinfo = ctx->priv; + showinfo->frame = 0; + return 0; +} + +static void end_frame(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + ShowInfoContext *showinfo = ctx->priv; + AVFilterBufferRef *picref = inlink->cur_buf; + uint32_t plane_checksum[4] = {0}, checksum = 0; + int i, plane, vsub = av_pix_fmt_descriptors[inlink->format].log2_chroma_h; + + for (plane = 0; picref->data[plane] && plane < 4; plane++) { + size_t linesize = av_image_get_linesize(picref->format, picref->video->w, plane); + uint8_t *data = picref->data[plane]; + int h = plane == 1 || plane == 2 ? inlink->h >> vsub : inlink->h; + + for (i = 0; i < h; i++) { + plane_checksum[plane] = av_adler32_update(plane_checksum[plane], data, linesize); + checksum = av_adler32_update(checksum, data, linesize); + data += picref->linesize[plane]; + } + } + + av_log(ctx, AV_LOG_INFO, + "n:%d pts:%"PRId64" pts_time:%f pos:%"PRId64" " + "fmt:%s sar:%d/%d s:%dx%d i:%c iskey:%d type:%c " + "checksum:%u plane_checksum:[%u %u %u %u]\n", + showinfo->frame, + picref->pts, picref ->pts * av_q2d(inlink->time_base), picref->pos, + av_pix_fmt_descriptors[picref->format].name, + picref->video->sample_aspect_ratio.num, picref->video->sample_aspect_ratio.den, + picref->video->w, picref->video->h, + !picref->video->interlaced ? 'P' : /* Progressive */ + picref->video->top_field_first ? 'T' : 'B', /* Top / Bottom */ + picref->video->key_frame, + av_get_picture_type_char(picref->video->pict_type), + checksum, plane_checksum[0], plane_checksum[1], plane_checksum[2], plane_checksum[3]); + + showinfo->frame++; + avfilter_end_frame(inlink->dst->outputs[0]); +} + +AVFilter avfilter_vf_showinfo = { + .name = "showinfo", + .description = NULL_IF_CONFIG_SMALL("Show textual information for each video frame."), + + .priv_size = sizeof(ShowInfoContext), + .init = init, + + .inputs = (AVFilterPad[]) {{ .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .get_video_buffer = avfilter_null_get_video_buffer, + .start_frame = avfilter_null_start_frame, + .end_frame = end_frame, + .min_perms = AV_PERM_READ, }, + { .name = NULL}}, + + .outputs = (AVFilterPad[]) {{ .name = "default", + .type = AVMEDIA_TYPE_VIDEO }, + { .name = NULL}}, +}; diff --git a/libavfilter/vf_slicify.c b/libavfilter/vf_slicify.c index cc56fe857c..177ac1f2b9 100644 --- a/libavfilter/vf_slicify.c +++ b/libavfilter/vf_slicify.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2007 Bobby Bingham * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavfilter/vf_split.c b/libavfilter/vf_split.c new file mode 100644 index 0000000000..cbebf264fa --- /dev/null +++ b/libavfilter/vf_split.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2007 Bobby Bingham + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Video splitter + */ + +#include "avfilter.h" + +static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) +{ + avfilter_start_frame(inlink->dst->outputs[0], + avfilter_ref_buffer(picref, ~AV_PERM_WRITE)); + avfilter_start_frame(inlink->dst->outputs[1], + avfilter_ref_buffer(picref, ~AV_PERM_WRITE)); +} + +static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) +{ + avfilter_draw_slice(inlink->dst->outputs[0], y, h, slice_dir); + avfilter_draw_slice(inlink->dst->outputs[1], y, h, slice_dir); +} + +static void end_frame(AVFilterLink *inlink) +{ + avfilter_end_frame(inlink->dst->outputs[0]); + avfilter_end_frame(inlink->dst->outputs[1]); + + avfilter_unref_buffer(inlink->cur_buf); +} + +AVFilter avfilter_vf_split = { + .name = "split", + .description = NULL_IF_CONFIG_SMALL("Pass on the input to two outputs."), + + .inputs = (AVFilterPad[]) {{ .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .get_video_buffer= avfilter_null_get_video_buffer, + .start_frame = start_frame, + .draw_slice = draw_slice, + .end_frame = end_frame, }, + { .name = NULL}}, + .outputs = (AVFilterPad[]) {{ .name = "output1", + .type = AVMEDIA_TYPE_VIDEO, }, + { .name = "output2", + .type = AVMEDIA_TYPE_VIDEO, }, + { .name = NULL}}, +}; diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c index a0ec67c426..8b11ae8d53 100644 --- a/libavfilter/vf_transpose.c +++ b/libavfilter/vf_transpose.c @@ -2,20 +2,20 @@ * Copyright (c) 2010 Stefano Sabatini * Copyright (c) 2008 Vitor Sessak * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -83,7 +83,7 @@ static int query_formats(AVFilterContext *ctx) PIX_FMT_NONE }; - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); return 0; } @@ -122,11 +122,11 @@ static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) outlink->w, outlink->h); outlink->out_buf->pts = picref->pts; - if (picref->video->pixel_aspect.num == 0) { - outlink->out_buf->video->pixel_aspect = picref->video->pixel_aspect; + if (picref->video->sample_aspect_ratio.num == 0) { + outlink->out_buf->video->sample_aspect_ratio = picref->video->sample_aspect_ratio; } else { - outlink->out_buf->video->pixel_aspect.num = picref->video->pixel_aspect.den; - outlink->out_buf->video->pixel_aspect.den = picref->video->pixel_aspect.num; + outlink->out_buf->video->sample_aspect_ratio.num = picref->video->sample_aspect_ratio.den; + outlink->out_buf->video->sample_aspect_ratio.den = picref->video->sample_aspect_ratio.num; } avfilter_start_frame(outlink, avfilter_ref_buffer(outlink->out_buf, ~0)); diff --git a/libavfilter/vf_unsharp.c b/libavfilter/vf_unsharp.c index 274b13c296..3542ca3eac 100644 --- a/libavfilter/vf_unsharp.c +++ b/libavfilter/vf_unsharp.c @@ -3,26 +3,26 @@ * Port copyright (c) 2010 Daniel G. Taylor <dan@programmer-art.org> * Relicensed to the LGPL with permission from Remi Guyomarch. * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * @file - * blur / sharpen filter, ported to Libav from MPlayer + * blur / sharpen filter, ported to FFmpeg from MPlayer * libmpcodecs/unsharp.c. * * This code is based on: @@ -63,7 +63,7 @@ typedef struct { FilterParam chroma; ///< chroma parameters (width, height, amount) } UnsharpContext; -static void unsharpen(uint8_t *dst, uint8_t *src, int dst_stride, int src_stride, int width, int height, FilterParam *fp) +static void unsharpen(uint8_t *dst, const uint8_t *src, int dst_stride, int src_stride, int width, int height, FilterParam *fp) { uint32_t **sc = fp->sc; uint32_t sr[(MAX_SIZE * MAX_SIZE) - 1], tmp1, tmp2; @@ -96,7 +96,7 @@ static void unsharpen(uint8_t *dst, uint8_t *src, int dst_stride, int src_stride tmp1 = sc[z + 1][x + fp->steps_x] + tmp2; sc[z + 1][x + fp->steps_x] = tmp2; } if (x >= fp->steps_x && y >= fp->steps_y) { - uint8_t* srx = src - fp->steps_y * src_stride + x - fp->steps_x; + const uint8_t* srx = src - fp->steps_y * src_stride + x - fp->steps_x; uint8_t* dsx = dst - fp->steps_y * dst_stride + x - fp->steps_x; res = (int32_t)*srx + ((((int32_t) * srx - (int32_t)((tmp1 + fp->halfscale) >> fp->scalebits)) * fp->amount) >> 16); @@ -155,7 +155,7 @@ static int query_formats(AVFilterContext *ctx) PIX_FMT_YUVJ444P, PIX_FMT_YUVJ440P, PIX_FMT_NONE }; - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); return 0; } diff --git a/libavfilter/vf_vflip.c b/libavfilter/vf_vflip.c index 09ba303bb9..e5cede81b5 100644 --- a/libavfilter/vf_vflip.c +++ b/libavfilter/vf_vflip.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2007 Bobby Bingham * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c index 42a7219d26..56e4489986 100644 --- a/libavfilter/vf_yadif.c +++ b/libavfilter/vf_yadif.c @@ -2,20 +2,18 @@ * Copyright (C) 2006-2010 Michael Niedermayer <michaelni@gmx.at> * 2010 James Darnley <james.darnley@gmail.com> * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or modify + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software Foundation, Inc., + * with FFmpeg; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -46,6 +44,12 @@ typedef struct { int frame_pending; + /** + * 0: deinterlace all frames + * 1: only deinterlace frames marked as interlaced + */ + int auto_enable; + AVFilterBufferRef *cur; AVFilterBufferRef *next; AVFilterBufferRef *prev; @@ -242,6 +246,14 @@ static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref) if (!yadif->cur) return; + if (yadif->auto_enable && !yadif->cur->video->interlaced) { + yadif->out = avfilter_ref_buffer(yadif->cur, AV_PERM_READ); + avfilter_unref_buffer(yadif->prev); + yadif->prev = NULL; + avfilter_start_frame(ctx->outputs[0], yadif->out); + return; + } + if (!yadif->prev) yadif->prev = avfilter_ref_buffer(yadif->cur, AV_PERM_READ); @@ -261,6 +273,12 @@ static void end_frame(AVFilterLink *link) if (!yadif->out) return; + if (yadif->auto_enable && !yadif->cur->video->interlaced) { + avfilter_draw_slice(ctx->outputs[0], 0, link->h, 1); + avfilter_end_frame(ctx->outputs[0]); + return; + } + return_frame(ctx, 0); } @@ -301,6 +319,9 @@ static int poll_frame(AVFilterLink *link) } assert(yadif->next || !val); + if (yadif->auto_enable && yadif->next && !yadif->next->video->interlaced) + return val; + return val * ((yadif->mode&1)+1); } @@ -334,7 +355,7 @@ static int query_formats(AVFilterContext *ctx) PIX_FMT_NONE }; - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); return 0; } @@ -346,9 +367,10 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) yadif->mode = 0; yadif->parity = -1; + yadif->auto_enable = 0; yadif->csp = NULL; - if (args) sscanf(args, "%d:%d", &yadif->mode, &yadif->parity); + if (args) sscanf(args, "%d:%d:%d", &yadif->mode, &yadif->parity, &yadif->auto_enable); yadif->filter_line = filter_line_c; if (HAVE_SSSE3 && cpu_flags & AV_CPU_FLAG_SSSE3) @@ -358,7 +380,7 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) else if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) yadif->filter_line = ff_yadif_filter_line_mmx; - av_log(ctx, AV_LOG_INFO, "mode:%d parity:%d\n", yadif->mode, yadif->parity); + av_log(ctx, AV_LOG_INFO, "mode:%d parity:%d auto_enable:%d\n", yadif->mode, yadif->parity, yadif->auto_enable); return 0; } diff --git a/libavfilter/vsink_buffer.c b/libavfilter/vsink_buffer.c new file mode 100644 index 0000000000..f8140b5e5a --- /dev/null +++ b/libavfilter/vsink_buffer.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2011 Stefano Sabatini + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * buffer video sink + */ + +#include "avfilter.h" +#include "vsink_buffer.h" + +typedef struct { + AVFilterBufferRef *picref; ///< cached picref + enum PixelFormat *pix_fmts; ///< accepted pixel formats, must be terminated with -1 +} BufferSinkContext; + +static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) +{ + BufferSinkContext *buf = ctx->priv; + + if (!opaque) { + av_log(ctx, AV_LOG_ERROR, "No opaque field provided, which is required.\n"); + return AVERROR(EINVAL); + } + + buf->pix_fmts = opaque; + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + BufferSinkContext *buf = ctx->priv; + + if (buf->picref) + avfilter_unref_buffer(buf->picref); + buf->picref = NULL; +} + +static void end_frame(AVFilterLink *inlink) +{ + BufferSinkContext *buf = inlink->dst->priv; + + if (buf->picref) /* drop the last cached frame */ + avfilter_unref_buffer(buf->picref); + buf->picref = inlink->cur_buf; +} + +static int query_formats(AVFilterContext *ctx) +{ + BufferSinkContext *buf = ctx->priv; + + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(buf->pix_fmts)); + return 0; +} + +int av_vsink_buffer_get_video_buffer_ref(AVFilterContext *ctx, + AVFilterBufferRef **picref, int flags) +{ + BufferSinkContext *buf = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + int ret; + *picref = NULL; + + /* no picref available, fetch it from the filterchain */ + if (!buf->picref) { + if ((ret = avfilter_request_frame(inlink)) < 0) + return ret; + } + + if (!buf->picref) + return AVERROR(EINVAL); + + *picref = buf->picref; + if (!(flags & AV_VSINK_BUF_FLAG_PEEK)) + buf->picref = NULL; + + return 0; +} + +AVFilter avfilter_vsink_buffersink = { + .name = "buffersink", + .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."), + .priv_size = sizeof(BufferSinkContext), + .init = init, + .uninit = uninit, + + .query_formats = query_formats, + + .inputs = (AVFilterPad[]) {{ .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .end_frame = end_frame, + .min_perms = AV_PERM_READ, }, + { .name = NULL }}, + .outputs = (AVFilterPad[]) {{ .name = NULL }}, +}; diff --git a/libavfilter/vsink_buffer.h b/libavfilter/vsink_buffer.h new file mode 100644 index 0000000000..88b4c1d258 --- /dev/null +++ b/libavfilter/vsink_buffer.h @@ -0,0 +1,47 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_VSINK_BUFFER_H +#define AVFILTER_VSINK_BUFFER_H + +/** + * @file + * memory buffer sink API for video + */ + +#include "avfilter.h" + +/** + * Tell av_vsink_buffer_get_video_buffer_ref() to read the picref, but not + * remove it from the buffer. This is useful if you need only to read + * the picref, without to fetch it. + */ +#define AV_VSINK_BUF_FLAG_PEEK 1 + +/** + * Get a video buffer data from buffer_sink and put it in picref. + * + * @param buffer_sink pointer to a buffer sink context + * @param flags a combination of AV_VSINK_BUF_FLAG_* flags + * @return >= 0 in case of success, a negative AVERROR code in case of + * failure + */ +int av_vsink_buffer_get_video_buffer_ref(AVFilterContext *buffer_sink, + AVFilterBufferRef **picref, int flags); + +#endif /* AVFILTER_VSINK_BUFFER_H */ diff --git a/libavfilter/vsink_nullsink.c b/libavfilter/vsink_nullsink.c index bdfcb8a2e4..0998bd0f89 100644 --- a/libavfilter/vsink_nullsink.c +++ b/libavfilter/vsink_nullsink.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavfilter/vsrc_buffer.c b/libavfilter/vsrc_buffer.c index 1f0233e3e3..54867f7766 100644 --- a/libavfilter/vsrc_buffer.c +++ b/libavfilter/vsrc_buffer.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2008 Vitor Sessak * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -24,58 +24,127 @@ */ #include "avfilter.h" +#include "avcodec.h" #include "vsrc_buffer.h" #include "libavutil/imgutils.h" typedef struct { - int64_t pts; - AVFrame frame; - int has_frame; + AVFilterBufferRef *picref; int h, w; enum PixelFormat pix_fmt; AVRational time_base; ///< time_base to set in the output link - AVRational pixel_aspect; + AVRational sample_aspect_ratio; + char sws_param[256]; } BufferSourceContext; -int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, - int64_t pts, AVRational pixel_aspect) +int av_vsrc_buffer_add_video_buffer_ref(AVFilterContext *buffer_filter, + AVFilterBufferRef *picref, int flags) { BufferSourceContext *c = buffer_filter->priv; + AVFilterLink *outlink = buffer_filter->outputs[0]; + int ret; + + if (c->picref) { + if (flags & AV_VSRC_BUF_FLAG_OVERWRITE) { + avfilter_unref_buffer(c->picref); + c->picref = NULL; + } else { + av_log(buffer_filter, AV_LOG_ERROR, + "Buffering several frames is not supported. " + "Please consume all available frames before adding a new one.\n"); + return AVERROR(EINVAL); + } + } - if (c->has_frame) { - av_log(buffer_filter, AV_LOG_ERROR, - "Buffering several frames is not supported. " - "Please consume all available frames before adding a new one.\n" - ); - //return -1; + if (picref->video->w != c->w || picref->video->h != c->h || picref->format != c->pix_fmt) { + AVFilterContext *scale = buffer_filter->outputs[0]->dst; + AVFilterLink *link; + char scale_param[1024]; + + av_log(buffer_filter, AV_LOG_INFO, + "Buffer video input changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", + c->w, c->h, av_pix_fmt_descriptors[c->pix_fmt].name, + picref->video->w, picref->video->h, av_pix_fmt_descriptors[picref->format].name); + + if (!scale || strcmp(scale->filter->name, "scale")) { + AVFilter *f = avfilter_get_by_name("scale"); + + av_log(buffer_filter, AV_LOG_INFO, "Inserting scaler filter\n"); + if ((ret = avfilter_open(&scale, f, "Input equalizer")) < 0) + return ret; + + snprintf(scale_param, sizeof(scale_param)-1, "%d:%d:%s", c->w, c->h, c->sws_param); + if ((ret = avfilter_init_filter(scale, scale_param, NULL)) < 0) { + avfilter_free(scale); + return ret; + } + + if ((ret = avfilter_insert_filter(buffer_filter->outputs[0], scale, 0, 0)) < 0) { + avfilter_free(scale); + return ret; + } + scale->outputs[0]->time_base = scale->inputs[0]->time_base; + + scale->outputs[0]->format= c->pix_fmt; + } else if (!strcmp(scale->filter->name, "scale")) { + snprintf(scale_param, sizeof(scale_param)-1, "%d:%d:%s", + scale->outputs[0]->w, scale->outputs[0]->h, c->sws_param); + scale->filter->init(scale, scale_param, NULL); + } + + c->pix_fmt = scale->inputs[0]->format = picref->format; + c->w = scale->inputs[0]->w = picref->video->w; + c->h = scale->inputs[0]->h = picref->video->h; + + link = scale->outputs[0]; + if ((ret = link->srcpad->config_props(link)) < 0) + return ret; } - memcpy(c->frame.data , frame->data , sizeof(frame->data)); - memcpy(c->frame.linesize, frame->linesize, sizeof(frame->linesize)); - c->frame.interlaced_frame= frame->interlaced_frame; - c->frame.top_field_first = frame->top_field_first; - c->frame.key_frame = frame->key_frame; - c->frame.pict_type = frame->pict_type; - c->pts = pts; - c->pixel_aspect = pixel_aspect; - c->has_frame = 1; + c->picref = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, + picref->video->w, picref->video->h); + av_image_copy(c->picref->data, c->picref->linesize, + picref->data, picref->linesize, + picref->format, picref->video->w, picref->video->h); + avfilter_copy_buffer_ref_props(c->picref, picref); return 0; } +#if CONFIG_AVCODEC +#include "avcodec.h" + +int av_vsrc_buffer_add_frame(AVFilterContext *buffer_src, + const AVFrame *frame, int flags) +{ + int ret; + AVFilterBufferRef *picref = + avfilter_get_video_buffer_ref_from_frame(frame, AV_PERM_WRITE); + if (!picref) + return AVERROR(ENOMEM); + ret = av_vsrc_buffer_add_video_buffer_ref(buffer_src, picref, flags); + picref->buf->data[0] = NULL; + avfilter_unref_buffer(picref); + + return ret; +} +#endif + static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) { BufferSourceContext *c = ctx->priv; char pix_fmt_str[128]; int n = 0; + *c->sws_param = 0; if (!args || - (n = sscanf(args, "%d:%d:%127[^:]:%d:%d:%d:%d", &c->w, &c->h, pix_fmt_str, + (n = sscanf(args, "%d:%d:%127[^:]:%d:%d:%d:%d:%255c", &c->w, &c->h, pix_fmt_str, &c->time_base.num, &c->time_base.den, - &c->pixel_aspect.num, &c->pixel_aspect.den)) != 7) { - av_log(ctx, AV_LOG_ERROR, "Expected 7 arguments, but %d found in '%s'\n", n, args); + &c->sample_aspect_ratio.num, &c->sample_aspect_ratio.den, c->sws_param)) < 7) { + av_log(ctx, AV_LOG_ERROR, "Expected at least 7 arguments, but only %d found in '%s'\n", n, args); return AVERROR(EINVAL); } + if ((c->pix_fmt = av_get_pix_fmt(pix_fmt_str)) == PIX_FMT_NONE) { char *tail; c->pix_fmt = strtol(pix_fmt_str, &tail, 10); @@ -85,7 +154,10 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) } } - av_log(ctx, AV_LOG_INFO, "w:%d h:%d pixfmt:%s\n", c->w, c->h, av_pix_fmt_descriptors[c->pix_fmt].name); + av_log(ctx, AV_LOG_INFO, "w:%d h:%d pixfmt:%s tb:%d/%d sar:%d/%d sws_param:%s\n", + c->w, c->h, av_pix_fmt_descriptors[c->pix_fmt].name, + c->time_base.num, c->time_base.den, + c->sample_aspect_ratio.num, c->sample_aspect_ratio.den, c->sws_param); return 0; } @@ -94,7 +166,7 @@ static int query_formats(AVFilterContext *ctx) BufferSourceContext *c = ctx->priv; enum PixelFormat pix_fmts[] = { c->pix_fmt, PIX_FMT_NONE }; - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); return 0; } @@ -104,7 +176,7 @@ static int config_props(AVFilterLink *link) link->w = c->w; link->h = c->h; - link->sample_aspect_ratio = c->pixel_aspect; + link->sample_aspect_ratio = c->sample_aspect_ratio; link->time_base = c->time_base; return 0; @@ -113,36 +185,18 @@ static int config_props(AVFilterLink *link) static int request_frame(AVFilterLink *link) { BufferSourceContext *c = link->src->priv; - AVFilterBufferRef *picref; - if (!c->has_frame) { - av_log(link->src, AV_LOG_ERROR, + if (!c->picref) { + av_log(link->src, AV_LOG_WARNING, "request_frame() called with no available frame!\n"); - //return -1; + return AVERROR(EINVAL); } - /* This picture will be needed unmodified later for decoding the next - * frame */ - picref = avfilter_get_video_buffer(link, AV_PERM_WRITE | AV_PERM_PRESERVE | - AV_PERM_REUSE2, - link->w, link->h); - - av_image_copy(picref->data, picref->linesize, - c->frame.data, c->frame.linesize, - picref->format, link->w, link->h); - - picref->pts = c->pts; - picref->video->pixel_aspect = c->pixel_aspect; - picref->video->interlaced = c->frame.interlaced_frame; - picref->video->top_field_first = c->frame.top_field_first; - picref->video->key_frame = c->frame.key_frame; - picref->video->pict_type = c->frame.pict_type; - avfilter_start_frame(link, avfilter_ref_buffer(picref, ~0)); + avfilter_start_frame(link, avfilter_ref_buffer(c->picref, ~0)); avfilter_draw_slice(link, 0, link->h, 1); avfilter_end_frame(link); - avfilter_unref_buffer(picref); - - c->has_frame = 0; + avfilter_unref_buffer(c->picref); + c->picref = NULL; return 0; } @@ -150,7 +204,7 @@ static int request_frame(AVFilterLink *link) static int poll_frame(AVFilterLink *link) { BufferSourceContext *c = link->src->priv; - return !!(c->has_frame); + return !!(c->picref); } AVFilter avfilter_vsrc_buffer = { diff --git a/libavfilter/vsrc_buffer.h b/libavfilter/vsrc_buffer.h index cfaf7919ac..b661d414ea 100644 --- a/libavfilter/vsrc_buffer.h +++ b/libavfilter/vsrc_buffer.h @@ -1,21 +1,20 @@ /* - * Memory buffer source filter * Copyright (c) 2008 Vitor Sessak * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -27,10 +26,24 @@ * memory buffer source API for video */ -#include "libavcodec/avcodec.h" /* AVFrame */ #include "avfilter.h" -int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, - int64_t pts, AVRational pixel_aspect); +/** + * Tell av_vsrc_buffer_add_video_buffer_ref() to overwrite the already + * cached video buffer with the new added one, otherwise the function + * will complain and exit. + */ +#define AV_VSRC_BUF_FLAG_OVERWRITE 1 + +/** + * Add video buffer data in picref to buffer_src. + * + * @param buffer_src pointer to a buffer source context + * @param flags a combination of AV_VSRC_BUF_FLAG_* flags + * @return >= 0 in case of success, a negative AVERROR code in case of + * failure + */ +int av_vsrc_buffer_add_video_buffer_ref(AVFilterContext *buffer_src, + AVFilterBufferRef *picref, int flags); #endif /* AVFILTER_VSRC_BUFFER_H */ diff --git a/libavfilter/vsrc_color.c b/libavfilter/vsrc_color.c index 0fb08d7dc6..b854ff2e4c 100644 --- a/libavfilter/vsrc_color.c +++ b/libavfilter/vsrc_color.c @@ -1,23 +1,28 @@ /* * Copyright (c) 2010 Stefano Sabatini * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +/** + * @file + * color source + */ + #include "avfilter.h" #include "libavutil/pixdesc.h" #include "libavutil/colorspace.h" @@ -95,7 +100,7 @@ static int query_formats(AVFilterContext *ctx) PIX_FMT_NONE }; - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); return 0; } @@ -125,6 +130,7 @@ static int color_config_props(AVFilterLink *inlink) is_packed_rgba ? "rgba" : "yuva"); inlink->w = color->w; inlink->h = color->h; + inlink->time_base = color->time_base; return 0; } @@ -133,9 +139,9 @@ static int color_request_frame(AVFilterLink *link) { ColorContext *color = link->src->priv; AVFilterBufferRef *picref = avfilter_get_video_buffer(link, AV_PERM_WRITE, color->w, color->h); - picref->video->pixel_aspect = (AVRational) {1, 1}; - picref->pts = av_rescale_q(color->pts++, color->time_base, AV_TIME_BASE_Q); - picref->pos = 0; + picref->video->sample_aspect_ratio = (AVRational) {1, 1}; + picref->pts = color->pts++; + picref->pos = -1; avfilter_start_frame(link, avfilter_ref_buffer(picref, ~0)); ff_draw_rectangle(picref->data, picref->linesize, diff --git a/libavfilter/vsrc_movie.c b/libavfilter/vsrc_movie.c index b018ba7418..f9818d1694 100644 --- a/libavfilter/vsrc_movie.c +++ b/libavfilter/vsrc_movie.c @@ -2,20 +2,20 @@ * Copyright (c) 2010 Stefano Sabatini * Copyright (c) 2008 Victor Paesa * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -35,6 +35,7 @@ #include "libavutil/opt.h" #include "libavutil/imgutils.h" #include "libavformat/avformat.h" +#include "avcodec.h" #include "avfilter.h" typedef struct { @@ -202,7 +203,7 @@ static int query_formats(AVFilterContext *ctx) MovieContext *movie = ctx->priv; enum PixelFormat pix_fmts[] = { movie->codec_ctx->pix_fmt, PIX_FMT_NONE }; - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); return 0; } @@ -230,7 +231,6 @@ static int movie_get_frame(AVFilterLink *outlink) while ((ret = av_read_frame(movie->format_ctx, &pkt)) >= 0) { // Is this a packet from the video stream? if (pkt.stream_index == movie->stream_index) { - movie->codec_ctx->reordered_opaque = pkt.pos; avcodec_decode_video2(movie->codec_ctx, movie->frame, &frame_decoded, &pkt); if (frame_decoded) { @@ -240,26 +240,22 @@ static int movie_get_frame(AVFilterLink *outlink) av_image_copy(movie->picref->data, movie->picref->linesize, movie->frame->data, movie->frame->linesize, movie->picref->format, outlink->w, outlink->h); + avfilter_copy_frame_props(movie->picref, movie->frame); /* FIXME: use a PTS correction mechanism as that in * ffplay.c when some API will be available for that */ /* use pkt_dts if pkt_pts is not available */ movie->picref->pts = movie->frame->pkt_pts == AV_NOPTS_VALUE ? movie->frame->pkt_dts : movie->frame->pkt_pts; - - movie->picref->pos = movie->frame->reordered_opaque; - movie->picref->video->pixel_aspect = st->sample_aspect_ratio.num ? - st->sample_aspect_ratio : movie->codec_ctx->sample_aspect_ratio; - movie->picref->video->interlaced = movie->frame->interlaced_frame; - movie->picref->video->top_field_first = movie->frame->top_field_first; - movie->picref->video->key_frame = movie->frame->key_frame; - movie->picref->video->pict_type = movie->frame->pict_type; + if (!movie->frame->sample_aspect_ratio.num) + movie->picref->video->sample_aspect_ratio = st->sample_aspect_ratio; av_dlog(outlink->src, "movie_get_frame(): file:'%s' pts:%"PRId64" time:%lf pos:%"PRId64" aspect:%d/%d\n", movie->file_name, movie->picref->pts, (double)movie->picref->pts * av_q2d(st->time_base), movie->picref->pos, - movie->picref->video->pixel_aspect.num, movie->picref->video->pixel_aspect.den); + movie->picref->video->sample_aspect_ratio.num, + movie->picref->video->sample_aspect_ratio.den); // We got it. Free the packet since we are returning av_free_packet(&pkt); diff --git a/libavfilter/vsrc_nullsrc.c b/libavfilter/vsrc_nullsrc.c index dfd56fa495..c513be800d 100644 --- a/libavfilter/vsrc_nullsrc.c +++ b/libavfilter/vsrc_nullsrc.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c new file mode 100644 index 0000000000..6f2c3cf166 --- /dev/null +++ b/libavfilter/vsrc_testsrc.c @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2007 Nicolas George <nicolas.george@normalesup.org> + * Copyright (c) 2011 Stefano Sabatini + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Based on the test pattern generator demuxer by Nicolas George: + * http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2007-October/037845.html + */ + +#include <float.h> + +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" +#include "avfilter.h" + +typedef struct { + const AVClass *class; + int h, w; + unsigned int nb_frame; + AVRational time_base; + int64_t pts, max_pts; + char *size; ///< video frame size + char *rate; ///< video frame rate + char *duration; ///< total duration of the generated video +} TestSourceContext; + +#define OFFSET(x) offsetof(TestSourceContext, x) + +static const AVOption testsrc_options[]= { + { "size", "set video size", OFFSET(size), FF_OPT_TYPE_STRING, {.str = "320x240"}, 0, 0 }, + { "s", "set video size", OFFSET(size), FF_OPT_TYPE_STRING, {.str = "320x240"}, 0, 0 }, + { "rate", "set video rate", OFFSET(rate), FF_OPT_TYPE_STRING, {.str = "25"}, 0, 0 }, + { "r", "set video rate", OFFSET(rate), FF_OPT_TYPE_STRING, {.str = "25"}, 0, 0 }, + { "duration", "set video duration", OFFSET(duration), FF_OPT_TYPE_STRING, {.str = NULL}, 0, 0 }, + { NULL }, +}; + +static const char *testsrc_get_name(void *ctx) +{ + return "testsrc"; +} + +static const AVClass testsrc_class = { + "TestSourceContext", + testsrc_get_name, + testsrc_options +}; + +static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) +{ + TestSourceContext *test = ctx->priv; + AVRational frame_rate_q; + int64_t duration = -1; + int ret = 0; + + test->class = &testsrc_class; + av_opt_set_defaults2(test, 0, 0); + + if ((ret = (av_set_options_string(test, args, "=", ":"))) < 0) { + av_log(ctx, AV_LOG_ERROR, "Error parsing options string: '%s'\n", args); + return ret; + } + + if ((ret = av_parse_video_size(&test->w, &test->h, test->size)) < 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid frame size: '%s'\n", test->size); + return ret; + } + + if ((ret = av_parse_video_rate(&frame_rate_q, test->rate)) < 0 || + frame_rate_q.den <= 0 || frame_rate_q.num <= 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid frame rate: '%s'\n", test->rate); + return ret; + } + + if ((test->duration) && (ret = av_parse_time(&duration, test->duration, 1)) < 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid duration: '%s'\n", test->duration); + return ret; + } + + test->time_base.num = frame_rate_q.den; + test->time_base.den = frame_rate_q.num; + test->max_pts = duration >= 0 ? + av_rescale_q(duration, AV_TIME_BASE_Q, test->time_base) : -1; + test->nb_frame = 0; + test->pts = 0; + + av_log(ctx, AV_LOG_INFO, "size:%dx%d rate:%d/%d duration:%f\n", + test->w, test->h, frame_rate_q.num, frame_rate_q.den, + duration < 0 ? -1 : test->max_pts * av_q2d(test->time_base)); + return 0; +} + +static int config_props(AVFilterLink *outlink) +{ + TestSourceContext *test = outlink->src->priv; + + outlink->w = test->w; + outlink->h = test->h; + outlink->time_base = test->time_base; + + return 0; +} + +/** + * Fill a rectangle with value val. + * + * @param val the RGB value to set + * @param dst pointer to the destination buffer to fill + * @param dst_linesize linesize of destination + * @param segment_width width of the segment + * @param x horizontal coordinate where to draw the rectangle in the destination buffer + * @param y horizontal coordinate where to draw the rectangle in the destination buffer + * @param w width of the rectangle to draw, expressed as a number of segment_width units + * @param h height of the rectangle to draw, expressed as a number of segment_width units + */ +static void draw_rectangle(unsigned val, uint8_t *dst, int dst_linesize, unsigned segment_width, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + int i; + int step = 3; + + dst += segment_width * (step * x + y * dst_linesize); + w *= segment_width * step; + h *= segment_width; + for (i = 0; i < h; i++) { + memset(dst, val, w); + dst += dst_linesize; + } +} + +static void draw_digit(int digit, uint8_t *dst, unsigned dst_linesize, + unsigned segment_width) +{ +#define TOP_HBAR 1 +#define MID_HBAR 2 +#define BOT_HBAR 4 +#define LEFT_TOP_VBAR 8 +#define LEFT_BOT_VBAR 16 +#define RIGHT_TOP_VBAR 32 +#define RIGHT_BOT_VBAR 64 + struct { + int x, y, w, h; + } segments[] = { + { 1, 0, 5, 1 }, /* TOP_HBAR */ + { 1, 6, 5, 1 }, /* MID_HBAR */ + { 1, 12, 5, 1 }, /* BOT_HBAR */ + { 0, 1, 1, 5 }, /* LEFT_TOP_VBAR */ + { 0, 7, 1, 5 }, /* LEFT_BOT_VBAR */ + { 6, 1, 1, 5 }, /* RIGHT_TOP_VBAR */ + { 6, 7, 1, 5 } /* RIGHT_BOT_VBAR */ + }; + static const unsigned char masks[10] = { + /* 0 */ TOP_HBAR |BOT_HBAR|LEFT_TOP_VBAR|LEFT_BOT_VBAR|RIGHT_TOP_VBAR|RIGHT_BOT_VBAR, + /* 1 */ RIGHT_TOP_VBAR|RIGHT_BOT_VBAR, + /* 2 */ TOP_HBAR|MID_HBAR|BOT_HBAR|LEFT_BOT_VBAR |RIGHT_TOP_VBAR, + /* 3 */ TOP_HBAR|MID_HBAR|BOT_HBAR |RIGHT_TOP_VBAR|RIGHT_BOT_VBAR, + /* 4 */ MID_HBAR |LEFT_TOP_VBAR |RIGHT_TOP_VBAR|RIGHT_BOT_VBAR, + /* 5 */ TOP_HBAR|BOT_HBAR|MID_HBAR|LEFT_TOP_VBAR |RIGHT_BOT_VBAR, + /* 6 */ TOP_HBAR|BOT_HBAR|MID_HBAR|LEFT_TOP_VBAR|LEFT_BOT_VBAR |RIGHT_BOT_VBAR, + /* 7 */ TOP_HBAR |RIGHT_TOP_VBAR|RIGHT_BOT_VBAR, + /* 8 */ TOP_HBAR|BOT_HBAR|MID_HBAR|LEFT_TOP_VBAR|LEFT_BOT_VBAR|RIGHT_TOP_VBAR|RIGHT_BOT_VBAR, + /* 9 */ TOP_HBAR|BOT_HBAR|MID_HBAR|LEFT_TOP_VBAR |RIGHT_TOP_VBAR|RIGHT_BOT_VBAR, + }; + unsigned mask = masks[digit]; + int i; + + draw_rectangle(0, dst, dst_linesize, segment_width, 0, 0, 8, 13); + for (i = 0; i < FF_ARRAY_ELEMS(segments); i++) + if (mask & (1<<i)) + draw_rectangle(255, dst, dst_linesize, segment_width, + segments[i].x, segments[i].y, segments[i].w, segments[i].h); +} + +#define GRADIENT_SIZE (6 * 256) + +static void fill_picture(TestSourceContext *test, AVFilterBufferRef *picref) +{ + uint8_t *p, *p0; + int x, y; + int color, color_rest; + int icolor; + int radius; + int quad0, quad; + int dquad_x, dquad_y; + int grad, dgrad, rgrad, drgrad; + int seg_size; + int second; + int i; + uint8_t *data = picref->data[0]; + int width = picref->video->w; + int height = picref->video->h; + + /* draw colored bars and circle */ + radius = (width + height) / 4; + quad0 = width * width / 4 + height * height / 4 - radius * radius; + dquad_y = 1 - height; + p0 = data; + for (y = 0; y < height; y++) { + p = p0; + color = 0; + color_rest = 0; + quad = quad0; + dquad_x = 1 - width; + for (x = 0; x < width; x++) { + icolor = color; + if (quad < 0) + icolor ^= 7; + quad += dquad_x; + dquad_x += 2; + *(p++) = icolor & 1 ? 255 : 0; + *(p++) = icolor & 2 ? 255 : 0; + *(p++) = icolor & 4 ? 255 : 0; + color_rest += 8; + if (color_rest >= width) { + color_rest -= width; + color++; + } + } + quad0 += dquad_y; + dquad_y += 2; + p0 += picref->linesize[0]; + } + + /* draw sliding color line */ + p = data + picref->linesize[0] * height * 3/4; + grad = (256 * test->nb_frame * test->time_base.num / test->time_base.den) % + GRADIENT_SIZE; + rgrad = 0; + dgrad = GRADIENT_SIZE / width; + drgrad = GRADIENT_SIZE % width; + for (x = 0; x < width; x++) { + *(p++) = + grad < 256 || grad >= 5 * 256 ? 255 : + grad >= 2 * 256 && grad < 4 * 256 ? 0 : + grad < 2 * 256 ? 2 * 256 - 1 - grad : grad - 4 * 256; + *(p++) = + grad >= 4 * 256 ? 0 : + grad >= 1 * 256 && grad < 3 * 256 ? 255 : + grad < 1 * 256 ? grad : 4 * 256 - 1 - grad; + *(p++) = + grad < 2 * 256 ? 0 : + grad >= 3 * 256 && grad < 5 * 256 ? 255 : + grad < 3 * 256 ? grad - 2 * 256 : 6 * 256 - 1 - grad; + grad += dgrad; + rgrad += drgrad; + if (rgrad >= GRADIENT_SIZE) { + grad++; + rgrad -= GRADIENT_SIZE; + } + if (grad >= GRADIENT_SIZE) + grad -= GRADIENT_SIZE; + } + for (y = height / 8; y > 0; y--) { + memcpy(p, p - picref->linesize[0], 3 * width); + p += picref->linesize[0]; + } + + /* draw digits */ + seg_size = width / 80; + if (seg_size >= 1 && height >= 13 * seg_size) { + second = test->nb_frame * test->time_base.num / test->time_base.den; + x = width - (width - seg_size * 64) / 2; + y = (height - seg_size * 13) / 2; + p = data + (x*3 + y * picref->linesize[0]); + for (i = 0; i < 8; i++) { + p -= 3 * 8 * seg_size; + draw_digit(second % 10, p, picref->linesize[0], seg_size); + second /= 10; + if (second == 0) + break; + } + } +} + +static int request_frame(AVFilterLink *outlink) +{ + TestSourceContext *test = outlink->src->priv; + AVFilterBufferRef *picref; + + if (test->max_pts >= 0 && test->pts > test->max_pts) + return AVERROR_EOF; + picref = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, + test->w, test->h); + picref->pts = test->pts++; + test->nb_frame++; + fill_picture(test, picref); + + avfilter_start_frame(outlink, avfilter_ref_buffer(picref, ~0)); + avfilter_draw_slice(outlink, 0, picref->video->h, 1); + avfilter_end_frame(outlink); + avfilter_unref_buffer(picref); + + return 0; +} + +static int query_formats(AVFilterContext *ctx) +{ + static const enum PixelFormat pix_fmts[] = { + PIX_FMT_RGB24, PIX_FMT_NONE + }; + avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); + return 0; +} + +AVFilter avfilter_vsrc_testsrc = { + .name = "testsrc", + .description = NULL_IF_CONFIG_SMALL("Generate test pattern."), + .priv_size = sizeof(TestSourceContext), + .init = init, + + .query_formats = query_formats, + + .inputs = (AVFilterPad[]) {{ .name = NULL}}, + + .outputs = (AVFilterPad[]) {{ .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .request_frame = request_frame, + .config_props = config_props, }, + { .name = NULL }}, +}; diff --git a/libavfilter/x86/gradfun.c b/libavfilter/x86/gradfun.c index ff3b19d38d..e892117d67 100644 --- a/libavfilter/x86/gradfun.c +++ b/libavfilter/x86/gradfun.c @@ -1,20 +1,20 @@ /* * Copyright (C) 2009 Loren Merritt <lorenm@u.washignton.edu> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -25,7 +25,7 @@ DECLARE_ALIGNED(16, static const uint16_t, pw_7f)[8] = {0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F}; DECLARE_ALIGNED(16, static const uint16_t, pw_ff)[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; -void ff_gradfun_filter_line_mmx2(uint8_t *dst, uint8_t *src, uint16_t *dc, int width, int thresh, const uint16_t *dithers) +void ff_gradfun_filter_line_mmx2(uint8_t *dst, const uint8_t *src, const uint16_t *dc, int width, int thresh, const uint16_t *dithers) { #if HAVE_MMX intptr_t x; @@ -73,7 +73,7 @@ void ff_gradfun_filter_line_mmx2(uint8_t *dst, uint8_t *src, uint16_t *dc, int w #endif } -void ff_gradfun_filter_line_ssse3(uint8_t *dst, uint8_t *src, uint16_t *dc, int width, int thresh, const uint16_t *dithers) +void ff_gradfun_filter_line_ssse3(uint8_t *dst, const uint8_t *src, const uint16_t *dc, int width, int thresh, const uint16_t *dithers) { #if HAVE_SSSE3 intptr_t x; @@ -120,7 +120,7 @@ void ff_gradfun_filter_line_ssse3(uint8_t *dst, uint8_t *src, uint16_t *dc, int #endif // HAVE_SSSE3 } -void ff_gradfun_blur_line_sse2(uint16_t *dc, uint16_t *buf, uint16_t *buf1, uint8_t *src, int src_linesize, int width) +void ff_gradfun_blur_line_sse2(uint16_t *dc, uint16_t *buf, const uint16_t *buf1, const uint8_t *src, int src_linesize, int width) { #if HAVE_SSE #define BLURV(load)\ diff --git a/libavfilter/x86/yadif.c b/libavfilter/x86/yadif.c index 7cd7e19258..2b55c00763 100644 --- a/libavfilter/x86/yadif.c +++ b/libavfilter/x86/yadif.c @@ -1,20 +1,20 @@ /* * Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or modify + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software Foundation, Inc., + * with FFmpeg; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ diff --git a/libavfilter/x86/yadif_template.c b/libavfilter/x86/yadif_template.c index 962a7c777d..0b60526007 100644 --- a/libavfilter/x86/yadif_template.c +++ b/libavfilter/x86/yadif_template.c @@ -1,20 +1,20 @@ /* * Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or modify + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software Foundation, Inc., + * with FFmpeg; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -107,10 +107,8 @@ void RENAME(ff_yadif_filter_line)(uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int prefs, int mrefs, int parity, int mode) { - DECLARE_ALIGNED(16, uint8_t, tmp0[16]); - DECLARE_ALIGNED(16, uint8_t, tmp1[16]); - DECLARE_ALIGNED(16, uint8_t, tmp2[16]); - DECLARE_ALIGNED(16, uint8_t, tmp3[16]); + uint8_t tmp[5*16]; + uint8_t *tmpA= (uint8_t*)(((uint64_t)(tmp+15)) & ~15); int x; #define FILTER\ @@ -124,9 +122,9 @@ void RENAME(ff_yadif_filter_line)(uint8_t *dst, MOVQ" "MM"3, "MM"4 \n\t"\ "paddw "MM"2, "MM"3 \n\t"\ "psraw $1, "MM"3 \n\t" /* d = (prev2[x] + next2[x])>>1 */\ - MOVQ" "MM"0, %[tmp0] \n\t" /* c */\ - MOVQ" "MM"3, %[tmp1] \n\t" /* d */\ - MOVQ" "MM"1, %[tmp2] \n\t" /* e */\ + MOVQ" "MM"0, (%[tmpA]) \n\t" /* c */\ + MOVQ" "MM"3, 16(%[tmpA]) \n\t" /* d */\ + MOVQ" "MM"1, 32(%[tmpA]) \n\t" /* e */\ "psubw "MM"4, "MM"2 \n\t"\ PABS( MM"4", MM"2") /* temporal_diff0 */\ LOAD("(%[prev],%[mrefs])", MM"3") /* prev[x-refs] */\ @@ -148,7 +146,7 @@ void RENAME(ff_yadif_filter_line)(uint8_t *dst, "paddw "MM"4, "MM"3 \n\t" /* temporal_diff2 */\ "psrlw $1, "MM"3 \n\t"\ "pmaxsw "MM"3, "MM"2 \n\t"\ - MOVQ" "MM"2, %[tmp3] \n\t" /* diff */\ + MOVQ" "MM"2, 48(%[tmpA]) \n\t" /* diff */\ \ "paddw "MM"0, "MM"1 \n\t"\ "paddw "MM"0, "MM"0 \n\t"\ @@ -179,7 +177,7 @@ void RENAME(ff_yadif_filter_line)(uint8_t *dst, CHECK2\ \ /* if(p->mode<2) ... */\ - MOVQ" %[tmp3], "MM"6 \n\t" /* diff */\ + MOVQ" 48(%[tmpA]), "MM"6 \n\t" /* diff */\ "cmpl $2, %[mode] \n\t"\ "jge 1f \n\t"\ LOAD("(%["prev2"],%[mrefs],2)", MM"2") /* prev2[x-2*refs] */\ @@ -190,9 +188,9 @@ void RENAME(ff_yadif_filter_line)(uint8_t *dst, "paddw "MM"5, "MM"3 \n\t"\ "psrlw $1, "MM"2 \n\t" /* b */\ "psrlw $1, "MM"3 \n\t" /* f */\ - MOVQ" %[tmp0], "MM"4 \n\t" /* c */\ - MOVQ" %[tmp1], "MM"5 \n\t" /* d */\ - MOVQ" %[tmp2], "MM"7 \n\t" /* e */\ + MOVQ" (%[tmpA]), "MM"4 \n\t" /* c */\ + MOVQ" 16(%[tmpA]), "MM"5 \n\t" /* d */\ + MOVQ" 32(%[tmpA]), "MM"7 \n\t" /* e */\ "psubw "MM"4, "MM"2 \n\t" /* b-c */\ "psubw "MM"7, "MM"3 \n\t" /* f-e */\ MOVQ" "MM"5, "MM"0 \n\t"\ @@ -211,7 +209,7 @@ void RENAME(ff_yadif_filter_line)(uint8_t *dst, "pmaxsw "MM"4, "MM"6 \n\t" /* diff= MAX3(diff, min, -max); */\ "1: \n\t"\ \ - MOVQ" %[tmp1], "MM"2 \n\t" /* d */\ + MOVQ" 16(%[tmpA]), "MM"2 \n\t" /* d */\ MOVQ" "MM"2, "MM"3 \n\t"\ "psubw "MM"6, "MM"2 \n\t" /* d-diff */\ "paddw "MM"6, "MM"3 \n\t" /* d+diff */\ @@ -219,11 +217,9 @@ void RENAME(ff_yadif_filter_line)(uint8_t *dst, "pminsw "MM"3, "MM"1 \n\t" /* d = clip(spatial_pred, d-diff, d+diff); */\ "packuswb "MM"1, "MM"1 \n\t"\ \ - :[tmp0]"=m"(tmp0),\ - [tmp1]"=m"(tmp1),\ - [tmp2]"=m"(tmp2),\ - [tmp3]"=m"(tmp3)\ - :[prev] "r"(prev),\ + :\ + :[tmpA] "r"(tmpA),\ + [prev] "r"(prev),\ [cur] "r"(cur),\ [next] "r"(next),\ [prefs]"r"((x86_reg)prefs),\ diff --git a/libavfilter/yadif.h b/libavfilter/yadif.h index d658b683d7..ff574daf49 100644 --- a/libavfilter/yadif.h +++ b/libavfilter/yadif.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or modify + * FFmpeg 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. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 Libav; if not, write to the Free Software Foundation, Inc., + * with FFmpeg; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ |