pulldown.c

来自「linux下的MPEG1」· C语言 代码 · 共 615 行 · 第 1/2 页

C
615
字号
/** * Copyright (C) 2001, 2002, 2003  Billy Biggs <vektor@dumbterm.net>. * * This program 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, or (at your option) * any later version. * * This program 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 this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <stdio.h>#include <limits.h>#include <string.h>#if HAVE_INTTYPES_H#include <inttypes.h>#else#include <stdint.h>#endif#include "pulldown.h"/** * scratch paper: * *  A A  A  B  B  C  C C  D D * [T B  T][B  T][B  T B][T B] * [1 1][2  2][3  3][4 4][5 5] * [C C]      [M  M][C C][C C] *  D A  A  A  B  B  C C  C D * * Top 1 : Drop * Bot 1 : Show * Top 2 : Drop * Bot 2 : Drop * Top 3 : Merge * Bot 3 : Drop * Top 4 : Show  * Bot 4 : Drop * Top 5 : Drop * Bot 5 : Show * *   A A   1 *   A B   2 *   B C   4 *   C C   8 *   D D   16 * *  D D A A A B B C C C D D A A A +------------ * [       ] * [* *  ]                        | 1    top      AA *   [  * *]                      | 0 AA bottom   AA * *     [       ] *     [* *  ]                    | 1    top      AB *       [* *  ]                  | 1 AB bottom   AB * *         [       ] *         [  * *]                | 0    top      BC *           [* *  ]              | 1 BC bottom   BC  * *             [       ] *             [  * *]            | 0    top      CC *               [  * *]          | 0 CC bottom   CC  * *                 [       ] *                 [* *  ]        | 1    top      DD *                   [  * *]      | 0 DD bottom   DD  * * *                     [* *  ]    | 1    top      AA *                       [  * *]  | 0 AA bottom   AA * *//* Offset                               1     2     3      4      5   *//* Field Pattern                       [T B  T][B  T][B   T B]  [T B] *//* Action                              Copy  Save  Merge  Copy  Copy  *//*                                           Bot   Top                */static const int tff_top_pattern[] = { 0,    1,    0,     0,    0     };static const int tff_bot_pattern[] = { 0,    0,    0,     1,    0     };/* Offset                               1     2     3      4      5   *//* Field Pattern                       [B T  B][T  B][T   B T]  [B T] *//* Action                              Copy  Save  Merge  Copy  Copy  *//*                                           Top   Bot                */static const int bff_top_pattern[] = { 0,    0,    0,     1,    0     };static const int bff_bot_pattern[] = { 0,    1,    0,     0,    0     };/* Timestamp mangling                                            *//* From the DVD :         0  +  3003+ 6006 + 9009+ 12012 = 15015 *//* In 24fps time:         0  +      + 3754 + 7508+ 11262 = 15016 *//** * Flag Pattern     Treat as * on DVD           last offset * ============================ * T B T            bff 3 * B T              bff 4 * B T B            tff 3 * T B              tff 4 */int determine_pulldown_offset( int top_repeat, int bot_repeat, int tff,                               int last_offset ){    int predicted_offset;    int pd_patterns = 0;    int offset = -1;    int exact = -1;    int i;    predicted_offset = last_offset << 1;    if( predicted_offset > PULLDOWN_SEQ_DD ) predicted_offset = PULLDOWN_SEQ_AA;    /**     * Detect our pattern.     */    for( i = 0; i < 5; i++ ) {        /**         *  Truth table:         *         *  ref repeat,  frame repeat    valid         *  ===========+==============+=======         *   0           0            ->  1         *   0           1            ->  1         *   1           0            ->  0         *   1           1            ->  1         */        if( tff ) {            if(    ( !tff_top_pattern[ i ] || top_repeat )                && ( !tff_bot_pattern[ i ] || bot_repeat ) ) {                pd_patterns |= ( 1 << i );                offset = i;            }        } else {            if(    ( !bff_top_pattern[ i ] || top_repeat )                && ( !bff_bot_pattern[ i ] || bot_repeat ) ) {                pd_patterns |= ( 1 << i );                offset = i;            }            if( bff_top_pattern[ i ] == top_repeat && bff_bot_pattern[ i ] == bot_repeat ) {                exact = i;            }        }    }    offset = 1 << offset;    /**     * Check if the 3:2 pulldown pattern we previously decided on is     * valid for this set.  If so, we use that.     */    if( pd_patterns & predicted_offset ) offset = predicted_offset;    if( ( top_repeat || bot_repeat ) && exact > 0 ) offset = ( 1 << exact );    return offset;}#define HISTORY_SIZE 5static int tophistory[ 5 ];static int bothistory[ 5 ];static int tophistory_diff[ 5 ];static int bothistory_diff[ 5 ];static int histpos = 0;#if 0  /* FIXME: unused */static void fill_history( int tff ){    if( tff ) {        tophistory[ 0 ] = INT_MAX; bothistory[ 0 ] = INT_MAX;        tophistory[ 1 ] =       0; bothistory[ 1 ] = INT_MAX;        tophistory[ 2 ] = INT_MAX; bothistory[ 2 ] = INT_MAX;        tophistory[ 3 ] = INT_MAX; bothistory[ 3 ] =       0;        tophistory[ 4 ] = INT_MAX; bothistory[ 3 ] = INT_MAX;        tophistory_diff[ 0 ] = 0; bothistory_diff[ 0 ] = 0;        tophistory_diff[ 1 ] = 1; bothistory_diff[ 1 ] = 0;        tophistory_diff[ 2 ] = 0; bothistory_diff[ 2 ] = 0;        tophistory_diff[ 3 ] = 0; bothistory_diff[ 3 ] = 1;        tophistory_diff[ 4 ] = 0; bothistory_diff[ 3 ] = 0;    } else {        tophistory[ 0 ] = INT_MAX; bothistory[ 0 ] = INT_MAX;        tophistory[ 1 ] = INT_MAX; bothistory[ 1 ] =       0;        tophistory[ 2 ] = INT_MAX; bothistory[ 2 ] = INT_MAX;        tophistory[ 3 ] =       0; bothistory[ 3 ] = INT_MAX;        tophistory[ 4 ] = INT_MAX; bothistory[ 3 ] = INT_MAX;        tophistory_diff[ 0 ] = 0; bothistory_diff[ 0 ] = 0;        tophistory_diff[ 1 ] = 0; bothistory_diff[ 1 ] = 1;        tophistory_diff[ 2 ] = 0; bothistory_diff[ 2 ] = 0;        tophistory_diff[ 3 ] = 1; bothistory_diff[ 3 ] = 0;        tophistory_diff[ 4 ] = 0; bothistory_diff[ 3 ] = 0;    }    histpos = 0;}#endifint determine_pulldown_offset_history( int top_repeat, int bot_repeat, int tff, int *realbest ){    int avgbot = 0;    int avgtop = 0;    int best = 0;    int min = -1;    int minpos = 0;    int minbot = 0;    int j;    int ret;    int mintopval = -1;    int mintoppos = -1;    int minbotval = -1;    int minbotpos = -1;    tophistory[ histpos ] = top_repeat;    bothistory[ histpos ] = bot_repeat;    for( j = 0; j < HISTORY_SIZE; j++ ) {        avgtop += tophistory[ j ];        avgbot += bothistory[ j ];    }    avgtop /= 5;    avgbot /= 5;    for( j = 0; j < HISTORY_SIZE; j++ ) {        // int cur = (tophistory[ j ] - avgtop);        int cur = tophistory[ j ];        if( cur < min || min < 0 ) {            min = cur;            minpos = j;        }        if( cur < mintopval || mintopval < 0 ) {            mintopval = cur;            mintoppos = j;        }    }    for( j = 0; j < HISTORY_SIZE; j++ ) {        // int cur = (bothistory[ j ] - avgbot);        int cur = bothistory[ j ];        if( cur < min || min < 0 ) {            min = cur;            minpos = j;            minbot = 1;        }        if( cur < minbotval || minbotval < 0 ) {            minbotval = cur;            minbotpos = j;        }    }    if( minbot ) {        best = tff ? ( minpos + 2 ) : ( minpos + 4 );    } else {        best = tff ? ( minpos + 4 ) : ( minpos + 2 );    }    best = best % HISTORY_SIZE;    *realbest = 1 << ( ( histpos + (2*HISTORY_SIZE) - best ) % HISTORY_SIZE );    best = (minbotpos + 2) % 5;    ret  = 1 << ( ( histpos + (2*HISTORY_SIZE) - best ) % HISTORY_SIZE );    best = (mintoppos + 4) % 5;    ret |= 1 << ( ( histpos + (2*HISTORY_SIZE) - best ) % HISTORY_SIZE );    histpos = (histpos + 1) % HISTORY_SIZE;    return ret;}static int reference = 0;int determine_pulldown_offset_history_new( int top_repeat, int bot_repeat, int tff, int predicted ){    int avgbot = 0;    int avgtop = 0;    int i, j;    int ret;    int mintopval = -1;    int mintoppos = -1;    int min2topval = -1;    int min2toppos = -1;    int minbotval = -1;    int minbotpos = -1;    int min2botval = -1;    int min2botpos = -1;    int predicted_pos = 0;    tophistory[ histpos ] = top_repeat;    bothistory[ histpos ] = bot_repeat;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?