| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 /* | 
|  | 2  * Copyright (C) 2010 Stefano Sabatini | 
|  | 3  * | 
|  | 4  * This file is part of FFmpeg. | 
|  | 5  * | 
|  | 6  * FFmpeg is free software; you can redistribute it and/or | 
|  | 7  * modify it under the terms of the GNU Lesser General Public | 
|  | 8  * License as published by the Free Software Foundation; either | 
|  | 9  * version 2.1 of the License, or (at your option) any later version. | 
|  | 10  * | 
|  | 11  * FFmpeg is distributed in the hope that it will be useful, | 
|  | 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | 14  * Lesser General Public License for more details. | 
|  | 15  * | 
|  | 16  * You should have received a copy of the GNU Lesser General Public | 
|  | 17  * License along with FFmpeg; if not, write to the Free Software | 
|  | 18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 
|  | 19  */ | 
|  | 20 | 
|  | 21 /** | 
|  | 22  * @file | 
|  | 23  * Set timebase for the output link. | 
|  | 24  */ | 
|  | 25 | 
|  | 26 #include "libavutil/avstring.h" | 
|  | 27 #include "libavutil/eval.h" | 
|  | 28 #include "libavutil/rational.h" | 
|  | 29 #include "avfilter.h" | 
|  | 30 #include "internal.h" | 
|  | 31 | 
|  | 32 static const char *var_names[] = { | 
|  | 33     "E", | 
|  | 34     "PHI", | 
|  | 35     "PI", | 
|  | 36     "AVTB",   /* default timebase 1/AV_TIME_BASE */ | 
|  | 37     "intb",   /* input timebase */ | 
|  | 38     NULL | 
|  | 39 }; | 
|  | 40 | 
|  | 41 enum var_name { | 
|  | 42     VAR_E, | 
|  | 43     VAR_PHI, | 
|  | 44     VAR_PI, | 
|  | 45     VAR_AVTB, | 
|  | 46     VAR_INTB, | 
|  | 47     VAR_VARS_NB | 
|  | 48 }; | 
|  | 49 | 
|  | 50 typedef struct { | 
|  | 51     char tb_expr[256]; | 
|  | 52     double var_values[VAR_VARS_NB]; | 
|  | 53 } SetTBContext; | 
|  | 54 | 
|  | 55 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) | 
|  | 56 { | 
|  | 57     SetTBContext *settb = ctx->priv; | 
|  | 58     av_strlcpy(settb->tb_expr, "intb", sizeof(settb->tb_expr)); | 
|  | 59 | 
|  | 60     if (args) | 
|  | 61         sscanf(args, "%255[^:]", settb->tb_expr); | 
|  | 62 | 
|  | 63     return 0; | 
|  | 64 } | 
|  | 65 | 
|  | 66 static int config_output_props(AVFilterLink *outlink) | 
|  | 67 { | 
|  | 68     AVFilterContext *ctx = outlink->src; | 
|  | 69     SetTBContext *settb = ctx->priv; | 
|  | 70     AVFilterLink *inlink = ctx->inputs[0]; | 
|  | 71     AVRational time_base; | 
|  | 72     int ret; | 
|  | 73     double res; | 
|  | 74 | 
|  | 75     settb->var_values[VAR_E]    = M_E; | 
|  | 76     settb->var_values[VAR_PHI]  = M_PHI; | 
|  | 77     settb->var_values[VAR_PI]   = M_PI; | 
|  | 78     settb->var_values[VAR_AVTB] = av_q2d(AV_TIME_BASE_Q); | 
|  | 79     settb->var_values[VAR_INTB] = av_q2d(inlink->time_base); | 
|  | 80 | 
|  | 81     outlink->w = inlink->w; | 
|  | 82     outlink->h = inlink->h; | 
|  | 83 | 
|  | 84     if ((ret = av_parse_and_eval_expr(&res, settb->tb_expr, var_names, settb->va
     r_values, | 
|  | 85                                       NULL, NULL, NULL, NULL, NULL, 0, NULL)) < 
     0) { | 
|  | 86         av_log(ctx, AV_LOG_ERROR, "Invalid expression '%s' for timebase.\n", set
     tb->tb_expr); | 
|  | 87         return ret; | 
|  | 88     } | 
|  | 89     time_base = av_d2q(res, INT_MAX); | 
|  | 90     if (time_base.num <= 0 || time_base.den <= 0) { | 
|  | 91         av_log(ctx, AV_LOG_ERROR, | 
|  | 92                "Invalid non-positive values for the timebase num:%d or den:%d.\n
     ", | 
|  | 93                time_base.num, time_base.den); | 
|  | 94         return AVERROR(EINVAL); | 
|  | 95     } | 
|  | 96 | 
|  | 97     outlink->time_base = time_base; | 
|  | 98     av_log(outlink->src, AV_LOG_INFO, "tb:%d/%d -> tb:%d/%d\n", | 
|  | 99            inlink ->time_base.num, inlink ->time_base.den, | 
|  | 100            outlink->time_base.num, outlink->time_base.den); | 
|  | 101 | 
|  | 102     return 0; | 
|  | 103 } | 
|  | 104 | 
|  | 105 static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) | 
|  | 106 { | 
|  | 107     AVFilterContext *ctx = inlink->dst; | 
|  | 108     AVFilterLink *outlink = ctx->outputs[0]; | 
|  | 109     AVFilterBufferRef *picref2 = picref; | 
|  | 110 | 
|  | 111     if (av_cmp_q(inlink->time_base, outlink->time_base)) { | 
|  | 112         picref2 = avfilter_ref_buffer(picref, ~0); | 
|  | 113         picref2->pts = av_rescale_q(picref->pts, inlink->time_base, outlink->tim
     e_base); | 
|  | 114         av_log(ctx, AV_LOG_DEBUG, "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId
     64"\n", | 
|  | 115                inlink ->time_base.num, inlink ->time_base.den, picref ->pts, | 
|  | 116                outlink->time_base.num, outlink->time_base.den, picref2->pts); | 
|  | 117         avfilter_unref_buffer(picref); | 
|  | 118     } | 
|  | 119 | 
|  | 120     avfilter_start_frame(outlink, picref2); | 
|  | 121 } | 
|  | 122 | 
|  | 123 AVFilter avfilter_vf_settb = { | 
|  | 124     .name      = "settb", | 
|  | 125     .description = NULL_IF_CONFIG_SMALL("Set timebase for the output link."), | 
|  | 126     .init      = init, | 
|  | 127 | 
|  | 128     .priv_size = sizeof(SetTBContext), | 
|  | 129 | 
|  | 130     .inputs    = (AVFilterPad[]) {{ .name             = "default", | 
|  | 131                                     .type             = AVMEDIA_TYPE_VIDEO, | 
|  | 132                                     .get_video_buffer = avfilter_null_get_video_
     buffer, | 
|  | 133                                     .start_frame      = start_frame, | 
|  | 134                                     .end_frame        = avfilter_null_end_frame 
     }, | 
|  | 135                                   { .name = NULL }}, | 
|  | 136 | 
|  | 137     .outputs   = (AVFilterPad[]) {{ .name            = "default", | 
|  | 138                                     .type            = AVMEDIA_TYPE_VIDEO, | 
|  | 139                                     .config_props    = config_output_props, }, | 
|  | 140                                   { .name = NULL}}, | 
|  | 141 }; | 
| OLD | NEW | 
|---|