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

File mythtv-0.21-field-order.8.patch, 10.2 KB (added by Tom Dexter <digitalaudiorock@…>, 3 years ago)

Mark Kendall's improved patch backported to vanilla 2.1 fixes branch, with non-interlaced fix

  • filters/fieldorder/fieldorder.pro

    diff -Naur mythtv-0.21-20306-old/filters/fieldorder/fieldorder.pro mythtv-0.21-20306-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-20306-old/filters/fieldorder/filter_fieldorder.c mythtv-0.21-20306-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) 
     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, dirty | !frame->interlaced_frame, 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 
     227FilterInfo 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-20306-old/filters/filters.pro mythtv-0.21-20306-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-20306-old/libs/libmythtv/videodisplayprofile.cpp mythtv-0.21-20306-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    }