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 + -
显示快捷键?