Libav 0.7.1
|
00001 /* 00002 * Copyright (c) 2010 Stefano Sabatini 00003 * Copyright (c) 2008 Victor Paesa 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00027 /* #define DEBUG */ 00028 00029 #include "libavutil/eval.h" 00030 #include "avfilter.h" 00031 00032 static const char *var_names[] = { 00033 "E", 00034 "INTERLACED", 00035 "N", 00036 "PHI", 00037 "PI", 00038 "POS", 00039 "PREV_INPTS", 00040 "PREV_OUTPTS", 00041 "PTS", 00042 "STARTPTS", 00043 "TB", 00044 NULL 00045 }; 00046 00047 enum var_name { 00048 VAR_E, 00049 VAR_INTERLACED, 00050 VAR_N, 00051 VAR_PHI, 00052 VAR_PI, 00053 VAR_POS, 00054 VAR_PREV_INPTS, 00055 VAR_PREV_OUTPTS, 00056 VAR_PTS, 00057 VAR_STARTPTS, 00058 VAR_TB, 00059 VAR_VARS_NB 00060 }; 00061 00062 typedef struct { 00063 AVExpr *expr; 00064 double var_values[VAR_VARS_NB]; 00065 } SetPTSContext; 00066 00067 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) 00068 { 00069 SetPTSContext *setpts = ctx->priv; 00070 int ret; 00071 00072 if ((ret = av_expr_parse(&setpts->expr, args ? args : "PTS", 00073 var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) { 00074 av_log(ctx, AV_LOG_ERROR, "Error while parsing expression '%s'\n", args); 00075 return ret; 00076 } 00077 00078 setpts->var_values[VAR_E ] = M_E; 00079 setpts->var_values[VAR_N ] = 0.0; 00080 setpts->var_values[VAR_PHI ] = M_PHI; 00081 setpts->var_values[VAR_PI ] = M_PI; 00082 setpts->var_values[VAR_PREV_INPTS ] = NAN; 00083 setpts->var_values[VAR_PREV_OUTPTS] = NAN; 00084 setpts->var_values[VAR_STARTPTS ] = NAN; 00085 return 0; 00086 } 00087 00088 static int config_input(AVFilterLink *inlink) 00089 { 00090 SetPTSContext *setpts = inlink->dst->priv; 00091 00092 setpts->var_values[VAR_TB] = av_q2d(inlink->time_base); 00093 00094 av_log(inlink->src, AV_LOG_INFO, "TB:%f\n", setpts->var_values[VAR_TB]); 00095 return 0; 00096 } 00097 00098 #define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d)) 00099 #define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)) 00100 00101 static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) 00102 { 00103 SetPTSContext *setpts = inlink->dst->priv; 00104 double d; 00105 AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0); 00106 00107 if (isnan(setpts->var_values[VAR_STARTPTS])) 00108 setpts->var_values[VAR_STARTPTS] = TS2D(inpicref->pts); 00109 00110 setpts->var_values[VAR_INTERLACED] = inpicref->video->interlaced; 00111 setpts->var_values[VAR_PTS ] = TS2D(inpicref->pts); 00112 setpts->var_values[VAR_POS ] = inpicref->pos == -1 ? NAN : inpicref->pos; 00113 00114 d = av_expr_eval(setpts->expr, setpts->var_values, NULL); 00115 outpicref->pts = D2TS(d); 00116 00117 #ifdef DEBUG 00118 av_log(inlink->dst, AV_LOG_DEBUG, 00119 "n:%"PRId64" interlaced:%d pos:%"PRId64" pts:%"PRId64" t:%f -> pts:%"PRId64" t:%f\n", 00120 (int64_t)setpts->var_values[VAR_N], 00121 (int)setpts->var_values[VAR_INTERLACED], 00122 inpicref ->pos, 00123 inpicref ->pts, inpicref ->pts * av_q2d(inlink->time_base), 00124 outpicref->pts, outpicref->pts * av_q2d(inlink->time_base)); 00125 #endif 00126 00127 setpts->var_values[VAR_N] += 1.0; 00128 setpts->var_values[VAR_PREV_INPTS ] = TS2D(inpicref ->pts); 00129 setpts->var_values[VAR_PREV_OUTPTS] = TS2D(outpicref->pts); 00130 avfilter_start_frame(inlink->dst->outputs[0], outpicref); 00131 } 00132 00133 static av_cold void uninit(AVFilterContext *ctx) 00134 { 00135 SetPTSContext *setpts = ctx->priv; 00136 av_expr_free(setpts->expr); 00137 setpts->expr = NULL; 00138 } 00139 00140 AVFilter avfilter_vf_setpts = { 00141 .name = "setpts", 00142 .description = NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."), 00143 .init = init, 00144 .uninit = uninit, 00145 00146 .priv_size = sizeof(SetPTSContext), 00147 00148 .inputs = (AVFilterPad[]) {{ .name = "default", 00149 .type = AVMEDIA_TYPE_VIDEO, 00150 .get_video_buffer = avfilter_null_get_video_buffer, 00151 .config_props = config_input, 00152 .start_frame = start_frame, }, 00153 { .name = NULL }}, 00154 .outputs = (AVFilterPad[]) {{ .name = "default", 00155 .type = AVMEDIA_TYPE_VIDEO, }, 00156 { .name = NULL}}, 00157 };