]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_setpts.c
asfenc: return error on negative timestamp
[ffmpeg] / libavfilter / vf_setpts.c
index 103f2657821dc089d3b77094eafd0611d05815fb..02fb4bd0c567cf6f76bdf3726b1e137c39bfcced 100644 (file)
 /* #define DEBUG */
 
 #include "libavutil/eval.h"
+#include "libavutil/internal.h"
 #include "libavutil/mathematics.h"
+#include "libavutil/time.h"
 #include "avfilter.h"
+#include "internal.h"
 #include "video.h"
 
 static const char *const var_names[] = {
@@ -37,12 +40,13 @@ static const char *const var_names[] = {
     "N",           ///< frame number (starting at zero)
     "PHI",         ///< golden ratio
     "PI",          ///< greek pi
-    "POS",         ///< original position in the file of the frame
     "PREV_INPTS",  ///< previous  input PTS
     "PREV_OUTPTS", ///< previous output PTS
     "PTS",         ///< original pts in the file of the frame
     "STARTPTS",   ///< PTS at start of movie
     "TB",          ///< timebase
+    "RTCTIME",     ///< wallclock (RTC) time in micro seconds
+    "RTCSTART",    ///< wallclock (RTC) time at the start of the movie in micro seconds
     NULL
 };
 
@@ -52,12 +56,13 @@ enum var_name {
     VAR_N,
     VAR_PHI,
     VAR_PI,
-    VAR_POS,
     VAR_PREV_INPTS,
     VAR_PREV_OUTPTS,
     VAR_PTS,
     VAR_STARTPTS,
     VAR_TB,
+    VAR_RTCTIME,
+    VAR_RTCSTART,
     VAR_VARS_NB
 };
 
@@ -66,7 +71,7 @@ typedef struct {
     double var_values[VAR_VARS_NB];
 } SetPTSContext;
 
-static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
+static av_cold int init(AVFilterContext *ctx, const char *args)
 {
     SetPTSContext *setpts = ctx->priv;
     int ret;
@@ -92,44 +97,45 @@ static int config_input(AVFilterLink *inlink)
     SetPTSContext *setpts = inlink->dst->priv;
 
     setpts->var_values[VAR_TB] = av_q2d(inlink->time_base);
+    setpts->var_values[VAR_RTCSTART] = av_gettime();
 
-    av_log(inlink->src, AV_LOG_INFO, "TB:%f\n", setpts->var_values[VAR_TB]);
+    av_log(inlink->src, AV_LOG_VERBOSE, "TB:%f\n", setpts->var_values[VAR_TB]);
     return 0;
 }
 
 #define D2TS(d)  (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d))
 #define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts))
 
-static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
+static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
 {
     SetPTSContext *setpts = inlink->dst->priv;
+    int64_t in_pts = frame->pts;
     double d;
-    AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);
 
     if (isnan(setpts->var_values[VAR_STARTPTS]))
-        setpts->var_values[VAR_STARTPTS] = TS2D(inpicref->pts);
+        setpts->var_values[VAR_STARTPTS] = TS2D(frame->pts);
 
-    setpts->var_values[VAR_INTERLACED] = inpicref->video->interlaced;
-    setpts->var_values[VAR_PTS       ] = TS2D(inpicref->pts);
-    setpts->var_values[VAR_POS       ] = inpicref->pos == -1 ? NAN : inpicref->pos;
+    setpts->var_values[VAR_INTERLACED] = frame->interlaced_frame;
+    setpts->var_values[VAR_PTS       ] = TS2D(frame->pts);
+    setpts->var_values[VAR_RTCTIME   ] = av_gettime();
 
     d = av_expr_eval(setpts->expr, setpts->var_values, NULL);
-    outpicref->pts = D2TS(d);
+    frame->pts = D2TS(d);
 
 #ifdef DEBUG
     av_log(inlink->dst, AV_LOG_DEBUG,
-           "n:%"PRId64" interlaced:%d pos:%"PRId64" pts:%"PRId64" t:%f -> pts:%"PRId64" t:%f\n",
+           "n:%"PRId64" interlaced:%d pts:%"PRId64" t:%f -> pts:%"PRId64" t:%f\n",
            (int64_t)setpts->var_values[VAR_N],
            (int)setpts->var_values[VAR_INTERLACED],
-           inpicref ->pos,
-           inpicref ->pts, inpicref ->pts * av_q2d(inlink->time_base),
-           outpicref->pts, outpicref->pts * av_q2d(inlink->time_base));
+           in_pts, in_pts * av_q2d(inlink->time_base),
+           frame->pts, frame->pts * av_q2d(inlink->time_base));
 #endif
 
+
     setpts->var_values[VAR_N] += 1.0;
-    setpts->var_values[VAR_PREV_INPTS ] = TS2D(inpicref ->pts);
-    setpts->var_values[VAR_PREV_OUTPTS] = TS2D(outpicref->pts);
-    avfilter_start_frame(inlink->dst->outputs[0], outpicref);
+    setpts->var_values[VAR_PREV_INPTS ] = TS2D(in_pts);
+    setpts->var_values[VAR_PREV_OUTPTS] = TS2D(frame->pts);
+    return ff_filter_frame(inlink->dst->outputs[0], frame);
 }
 
 static av_cold void uninit(AVFilterContext *ctx)
@@ -139,6 +145,25 @@ static av_cold void uninit(AVFilterContext *ctx)
     setpts->expr = NULL;
 }
 
+static const AVFilterPad avfilter_vf_setpts_inputs[] = {
+    {
+        .name             = "default",
+        .type             = AVMEDIA_TYPE_VIDEO,
+        .get_video_buffer = ff_null_get_video_buffer,
+        .config_props     = config_input,
+        .filter_frame     = filter_frame,
+    },
+    { NULL }
+};
+
+static const AVFilterPad avfilter_vf_setpts_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_VIDEO,
+    },
+    { NULL }
+};
+
 AVFilter avfilter_vf_setpts = {
     .name      = "setpts",
     .description = NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."),
@@ -147,13 +172,6 @@ AVFilter avfilter_vf_setpts = {
 
     .priv_size = sizeof(SetPTSContext),
 
-    .inputs    = (AVFilterPad[]) {{ .name             = "default",
-                                    .type             = AVMEDIA_TYPE_VIDEO,
-                                    .get_video_buffer = ff_null_get_video_buffer,
-                                    .config_props     = config_input,
-                                    .start_frame      = start_frame, },
-                                  { .name = NULL }},
-    .outputs   = (AVFilterPad[]) {{ .name             = "default",
-                                    .type             = AVMEDIA_TYPE_VIDEO, },
-                                  { .name = NULL}},
+    .inputs    = avfilter_vf_setpts_inputs,
+    .outputs   = avfilter_vf_setpts_outputs,
 };