Ticket #6391: mythtv-0.21-field-order.4.patch

File mythtv-0.21-field-order.4.patch, 10.2 KB (added by mythtv@…, 11 years ago)

Mark Kendall's improved patch backported to vanilla 2.1 fixes branch

  • filters/fieldorder/fieldorder.pro

    diff -Naur mythtv-0.21-20283-old/filters/fieldorder/fieldorder.pro mythtv-0.21-20283-new/filters/fieldorder/fieldorder.pro
    old new  
     1include ( ../filter-common.pro )
     2include ( ../filter-avcodec.pro )
     3
     4INCLUDEPATH += ../../libs/libmythtv ../../libs/libavcodec ../..
     5
     6# Input
     7SOURCES += filter_fieldorder.c
     8
  • filters/fieldorder/filter_fieldorder.c

    diff -Naur mythtv-0.21-20283-old/filters/fieldorder/filter_fieldorder.c mythtv-0.21-20283-new/filters/fieldorder/filter_fieldorder.c
    old new  
     1/*
     2 * Field-order deinterlacer
     3 *
     4 * Written by Paul Gardiner (mythtv@glidos.net), based on overal
     5 * structure of yadif deinterlacer.
     6 */
     7#include <stdlib.h>
     8#include <stdio.h>
     9
     10#include "config.h"
     11#ifdef HAVE_STDINT_H
     12#include <stdint.h>
     13#endif
     14#include <inttypes.h>
     15
     16#include <string.h>
     17#include <math.h>
     18
     19#include "filter.h"
     20#include "frame.h"
     21
     22#define NREFS 2
     23#define NCHANS 3
     24
     25typedef struct ThisFilter
     26{
     27    VideoFilter vf;
     28
     29    long long last_framenr;
     30
     31    uint8_t *ref[NREFS + 1][NCHANS];
     32    int stride[NCHANS];
     33    int8_t got_frames[NREFS + 1];
     34
     35    int width;
     36    int height;
     37
     38    TF_STRUCT;
     39} ThisFilter;
     40
     41
     42static void AllocFilter(ThisFilter* filter, int width, int height)
     43{
     44    int i, j;
     45    if ((width != filter->width) || height != filter->height)
     46    {
     47        for (i = 0; i < NCHANS * NREFS; i++)
     48        {
     49            uint8_t **p = &filter->ref[i / NCHANS][i % NCHANS];
     50            if (*p) free(*p);
     51            *p = NULL;
     52        }
     53        for (i = 0; i < NCHANS; i++)
     54        {
     55            int is_chroma = !!i;
     56            int w = ((width   + 31) & (~31)) >> is_chroma;
     57            int h = ((height  + 31) & (~31)) >> is_chroma;
     58
     59            filter->stride[i] = w;
     60            for (j = 0; j < NREFS; j++)
     61            {
     62                filter->ref[j][i] =
     63                    (uint8_t*)calloc(w * h * sizeof(uint8_t), 1);
     64            }
     65        }
     66        filter->width  = width;
     67        filter->height = height;
     68        memset(filter->got_frames, 0, sizeof(filter->got_frames));
     69    }
     70}
     71
     72static inline void * memcpy_pic(void * dst, const void * src,
     73                                int bytesPerLine, int height,
     74                                int dstStride, int srcStride)
     75{
     76    int i;
     77    void *retval = dst;
     78
     79    if (dstStride == srcStride)
     80    {
     81        if (srcStride < 0)
     82        {
     83            src = (const uint8_t*)src + (height - 1) * srcStride;
     84            dst = (uint8_t*)dst + (height - 1) * dstStride;
     85            srcStride = -srcStride;
     86        }
     87        memcpy(dst, src, srcStride * height);
     88    }
     89    else
     90    {
     91        for (i = 0; i < height; i++)
     92        {
     93            memcpy(dst, src, bytesPerLine);
     94            src = (const uint8_t*)src + srcStride;
     95            dst = (uint8_t*)dst + dstStride;
     96        }
     97    }
     98    return retval;
     99}
     100
     101static void store_ref(struct ThisFilter *p, uint8_t *src, int src_offsets[3],
     102                      int src_stride[3], int width, int height)
     103{
     104    int i;
     105
     106    memcpy (p->ref[NREFS], p->ref[0], sizeof(uint8_t *) * NCHANS);
     107    memmove(p->ref[0], p->ref[1], sizeof(uint8_t *) * NREFS * NCHANS);
     108    memcpy (&p->got_frames[NREFS], &p->got_frames[0], sizeof(uint8_t));
     109    memmove(&p->got_frames[0], &p->got_frames[1], sizeof(uint8_t) * NREFS);
     110
     111    for (i = 0; i < NCHANS; i++)
     112    {
     113        int is_chroma = !!i;
     114        memcpy_pic(p->ref[NREFS-1][i], src + src_offsets[i],
     115                   width >> is_chroma, height >> is_chroma,
     116                   p->stride[i], src_stride[i]);
     117    }
     118    p->got_frames[NREFS - 1] = 1;
     119}
     120
     121static void filter_func(struct ThisFilter *p, uint8_t *dst,
     122                        int dst_offsets[3], int dst_stride[3], int width,
     123                        int height, int parity, int tff, int dirty)
     124{
     125    int i, y;
     126    uint8_t nr_p, nr_c;
     127    nr_c = NREFS - 1;
     128    nr_p = p->got_frames[NREFS - 2] ? (NREFS - 2) : nr_c;
     129
     130    for (i = 0; i < NCHANS; i++)
     131    {
     132        int is_chroma = !!i;
     133        int w    = width  >> is_chroma;
     134        int h    = height >> is_chroma;
     135        int refs = p->stride[i];
     136
     137        for (y = 0; y < h; y++)
     138        {
     139            int do_copy = dirty;
     140            uint8_t *dst2 = dst + dst_offsets[i] + y * dst_stride[i];
     141            uint8_t *src  = &p->ref[nr_c][i][y * refs];
     142            int     field = parity ^ tff;
     143            if (((y ^ (1 - field)) & 1) && !parity)
     144            {
     145                src = &p->ref[nr_p][i][y * refs], w;
     146                do_copy = 1;
     147            }
     148            if (do_copy)
     149                memcpy(dst2, src, w);
     150        }
     151    }
     152}
     153
     154static int FieldorderDeint (VideoFilter * f, VideoFrame * frame, int field)
     155{
     156    ThisFilter *filter = (ThisFilter *) f;
     157    TF_VARS;
     158
     159    AllocFilter(filter, frame->width, frame->height);
     160
     161    int dirty = 1;
     162    if (filter->last_framenr != frame->frameNumber)
     163    {
     164        if (filter->last_framenr != (frame->frameNumber - 1))
     165        {
     166            memset(filter->got_frames, 0, sizeof(filter->got_frames));
     167        }
     168        store_ref(filter, frame->buf,  frame->offsets,
     169                  frame->pitches, frame->width, frame->height);
     170        dirty = 0;
     171    }
     172
     173    filter_func(
     174        filter, frame->buf, frame->offsets, frame->pitches,
     175        frame->width, frame->height, field, frame->top_field_first,
     176        dirty);
     177
     178    filter->last_framenr = frame->frameNumber;
     179
     180    return 0;
     181}
     182
     183
     184void CleanupFieldorderDeintFilter (VideoFilter * filter)
     185{
     186    int i;
     187    ThisFilter* f = (ThisFilter*)filter;
     188    for (i = 0; i < NCHANS * NREFS; i++)
     189    {
     190        uint8_t **p= &f->ref[i / NCHANS][i % NCHANS];
     191        if (*p) free(*p);
     192        *p= NULL;
     193    }
     194}
     195
     196VideoFilter * FieldorderDeintFilter (VideoFrameType inpixfmt, VideoFrameType outpixfmt,
     197    int *width, int *height, char *options)
     198{
     199    ThisFilter *filter;
     200    (void) height;
     201    (void) options;
     202
     203    filter = (ThisFilter *) malloc (sizeof(ThisFilter));
     204    if (filter == NULL)
     205    {
     206        fprintf (stderr, "FieldorderDeint: failed to allocate memory for filter.\n");
     207        return NULL;
     208    }
     209
     210    filter->width = 0;
     211    filter->height = 0;
     212    memset(filter->ref, 0, sizeof(filter->ref));
     213
     214    AllocFilter(filter, *width, *height);
     215
     216    filter->vf.filter = &FieldorderDeint;
     217    filter->vf.cleanup = &CleanupFieldorderDeintFilter;
     218    return (VideoFilter *) filter;
     219}
     220
     221static FmtConv FmtList[] =
     222{
     223    { FMT_YV12, FMT_YV12 } ,
     224    FMT_NULL
     225};
     226
     227ConstFilterInfo filter_table[] =
     228{
     229    {
     230        symbol:     "FieldorderDeintFilter",
     231        name:       "fieldorderdoubleprocessdeint",
     232        descript:   "avoids synchronisation problems when matching an "
     233                    "interlaced video mode to an interlaced source",
     234        formats:    FmtList,
     235        libname:    NULL
     236    }, FILT_NULL
     237};
     238
     239/* vim: set expandtab tabstop=4 shiftwidth=4: */
  • filters/filters.pro

    diff -Naur mythtv-0.21-20283-old/filters/filters.pro mythtv-0.21-20283-new/filters/filters.pro
    old new  
    22
    33# Directories
    44SUBDIRS += invert linearblend denoise3d quickdnr kerneldeint crop force convert
    5 SUBDIRS += adjust onefield bobdeint ivtc greedyhdeint yadif
     5SUBDIRS += adjust onefield bobdeint ivtc greedyhdeint yadif fieldorder
    66
    77# This filter is currently broken, because the FFmpeg code that
    88# it depends on was moved into a seperate library (libpostproc).
  • libs/libmythtv/videodisplayprofile.cpp

    diff -Naur mythtv-0.21-20283-old/libs/libmythtv/videodisplayprofile.cpp mythtv-0.21-20283-new/libs/libmythtv/videodisplayprofile.cpp
    old new  
    673673        return QObject::tr("Bob (2x)");
    674674    else if ("onefield" == short_name)
    675675        return QObject::tr("One field");
     676    else if ("fieldorderdoubleprocessdeint" == short_name)
     677        return QObject::tr("Interlaced (2x)");
    676678    else if ("opengllinearblend" == short_name)
    677679        return QObject::tr("Linear blend (HW)");
    678680    else if ("openglkerneldeint" == short_name)
     
    12271229        "This deinterlacer uses several fields to reduce motion blur. "
    12281230        "It has increased CPU requirements.");
    12291231
     1232    QString kFieldOrderMsg = QObject::tr(
     1233        "This deinterlacer attempts to syncronise with interlaced displays "
     1234        "whose size and refresh rate exactly match the video source. "
     1235        "It has low CPU requirements.");
     1236
    12301237    if (deint == "none")
    12311238        msg = kNoneMsg;
    12321239    else if (deint == "onefield")
     
    12521259    else if (deint == "opengldoubleratekerneldeint")
    12531260        msg = kKernelMsg + " " + kUsingOpenGLWorkaround;
    12541261    else if (deint == "opengldoubleratefieldorder")
    1255         msg = kNoneMsg  + " " + kUsingOpenGLWorkaround;
     1262        msg = kFieldOrderMsg  + " " + kUsingOpenGLWorkaround;
    12561263    else if (deint == "greedyhdeint")
    12571264        msg = kGreedyHMsg;
    12581265    else if (deint == "greedyhdoubleprocessdeint")
     
    12611268        msg = kYadifMsg;
    12621269    else if (deint == "yadifdoubleprocessdeint")
    12631270        msg = kYadifMsg + " " +  kDoubleRateMsg;
     1271    else if (deint == "fieldorderdoubleprocessdeint")
     1272        msg = kFieldOrderMsg + " " +  kDoubleRateMsg;
    12641273    else
    12651274        msg = QObject::tr("'%1' has not been documented yet.").arg(deint);
    12661275
     
    14311440"greedyhdoubleprocessdeint"
    14321441"yadifdeint"
    14331442"yadifdoubleprocessdeint"
     1443"fieldorderdoubleprocessdeint"
    14341444"opengllinearblend"
    14351445"openglkerneldeint"
    14361446"openglonefield"
     
    14671477        safe_deint[*it] += "greedyhdoubleprocessdeint";
    14681478        safe_deint[*it] += "yadifdeint";
    14691479        safe_deint[*it] += "yadifdoubleprocessdeint";
     1480        safe_deint[*it] += "fieldorderdoubleprocessdeint";
    14701481        safe_deint[*it] += "none";
    14711482        safe_osd[*it]   += "softblend";
    14721483    }