Based on an idea by Andrey Utkin <andrey.krieger.utkin@gmail.com>.
Stefano Sabatini authored on 2012/08/08 20:44:11... | ... |
@@ -3032,9 +3032,11 @@ Mark the frame as top-field-first. |
3032 | 3032 |
Mark the frame as progressive. |
3033 | 3033 |
@end table |
3034 | 3034 |
|
3035 |
-@section setpts |
|
3035 |
+@section asetpts, setpts |
|
3036 | 3036 |
|
3037 |
-Change the PTS (presentation timestamp) of the input video frames. |
|
3037 |
+Change the PTS (presentation timestamp) of the input frames. |
|
3038 |
+ |
|
3039 |
+@code{asetpts} works on audio frames, @code{setpts} on video frames. |
|
3038 | 3040 |
|
3039 | 3041 |
Accept in input an expression evaluated through the eval API, which |
3040 | 3042 |
can contain the following constants: |
... | ... |
@@ -3046,6 +3048,16 @@ the presentation timestamp in input |
3046 | 3046 |
@item N |
3047 | 3047 |
the count of the input frame, starting from 0. |
3048 | 3048 |
|
3049 |
+@item NB_CONSUMED_SAMPLES |
|
3050 |
+the number of consumed samples, not including the current frame (only |
|
3051 |
+audio) |
|
3052 |
+ |
|
3053 |
+@item NB_SAMPLES |
|
3054 |
+the number of samples in the current frame (only audio) |
|
3055 |
+ |
|
3056 |
+@item SAMPLE_RATE |
|
3057 |
+audio sample rate |
|
3058 |
+ |
|
3049 | 3059 |
@item STARTPTS |
3050 | 3060 |
the PTS of the first video frame |
3051 | 3061 |
|
... | ... |
@@ -3084,6 +3096,9 @@ setpts=N/(25*TB) |
3084 | 3084 |
|
3085 | 3085 |
# fixed rate 25 fps with some jitter |
3086 | 3086 |
setpts='1/(25*TB) * (N + 0.05 * sin(N*2*PI/25))' |
3087 |
+ |
|
3088 |
+# apply an offset of 10 seconds to the input PTS |
|
3089 |
+setpts=PTS+10/TB |
|
3087 | 3090 |
@end example |
3088 | 3091 |
|
3089 | 3092 |
@section settb, asettb |
... | ... |
@@ -52,6 +52,7 @@ OBJS-$(CONFIG_AMIX_FILTER) += af_amix.o |
52 | 52 |
OBJS-$(CONFIG_ANULL_FILTER) += af_anull.o |
53 | 53 |
OBJS-$(CONFIG_ARESAMPLE_FILTER) += af_aresample.o |
54 | 54 |
OBJS-$(CONFIG_ASETNSAMPLES_FILTER) += af_asetnsamples.o |
55 |
+OBJS-$(CONFIG_ASETPTS_FILTER) += vf_setpts.o |
|
55 | 56 |
OBJS-$(CONFIG_ASETTB_FILTER) += f_settb.o |
56 | 57 |
OBJS-$(CONFIG_ASHOWINFO_FILTER) += af_ashowinfo.o |
57 | 58 |
OBJS-$(CONFIG_ASPLIT_FILTER) += split.o |
... | ... |
@@ -42,6 +42,7 @@ void avfilter_register_all(void) |
42 | 42 |
REGISTER_FILTER (ANULL, anull, af); |
43 | 43 |
REGISTER_FILTER (ARESAMPLE, aresample, af); |
44 | 44 |
REGISTER_FILTER (ASETNSAMPLES, asetnsamples, af); |
45 |
+ REGISTER_FILTER (ASETPTS, asetpts, af); |
|
45 | 46 |
REGISTER_FILTER (ASETTB, asettb, af); |
46 | 47 |
REGISTER_FILTER (ASHOWINFO, ashowinfo, af); |
47 | 48 |
REGISTER_FILTER (ASPLIT, asplit, af); |
... | ... |
@@ -29,7 +29,7 @@ |
29 | 29 |
#include "libavutil/avutil.h" |
30 | 30 |
|
31 | 31 |
#define LIBAVFILTER_VERSION_MAJOR 3 |
32 |
-#define LIBAVFILTER_VERSION_MINOR 6 |
|
32 |
+#define LIBAVFILTER_VERSION_MINOR 7 |
|
33 | 33 |
#define LIBAVFILTER_VERSION_MICRO 100 |
34 | 34 |
|
35 | 35 |
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ |
... | ... |
@@ -30,16 +30,20 @@ |
30 | 30 |
#include "libavutil/mathematics.h" |
31 | 31 |
#include "avfilter.h" |
32 | 32 |
#include "internal.h" |
33 |
+#include "audio.h" |
|
33 | 34 |
#include "video.h" |
34 | 35 |
|
35 | 36 |
static const char *const var_names[] = { |
36 | 37 |
"INTERLACED", ///< tell if the current frame is interlaced |
37 | 38 |
"N", ///< frame number (starting at zero) |
39 |
+ "NB_CONSUMED_SAMPLES", ///< number of samples consumed by the filter (only audio) |
|
40 |
+ "NB_SAMPLES", ///< number of samples in the current frame (only audio) |
|
38 | 41 |
"POS", ///< original position in the file of the frame |
39 | 42 |
"PREV_INPTS", ///< previous input PTS |
40 | 43 |
"PREV_OUTPTS", ///< previous output PTS |
41 | 44 |
"PTS", ///< original pts in the file of the frame |
42 |
- "STARTPTS", ///< PTS at start of movie |
|
45 |
+ "SAMPLE_RATE", ///< sample rate (only audio) |
|
46 |
+ "STARTPTS", ///< PTS at start of movie |
|
43 | 47 |
"TB", ///< timebase |
44 | 48 |
NULL |
45 | 49 |
}; |
... | ... |
@@ -47,10 +51,13 @@ static const char *const var_names[] = { |
47 | 47 |
enum var_name { |
48 | 48 |
VAR_INTERLACED, |
49 | 49 |
VAR_N, |
50 |
+ VAR_NB_CONSUMED_SAMPLES, |
|
51 |
+ VAR_NB_SAMPLES, |
|
50 | 52 |
VAR_POS, |
51 | 53 |
VAR_PREV_INPTS, |
52 | 54 |
VAR_PREV_OUTPTS, |
53 | 55 |
VAR_PTS, |
56 |
+ VAR_SAMPLE_RATE, |
|
54 | 57 |
VAR_STARTPTS, |
55 | 58 |
VAR_TB, |
56 | 59 |
VAR_VARS_NB |
... | ... |
@@ -59,6 +66,7 @@ enum var_name { |
59 | 59 |
typedef struct { |
60 | 60 |
AVExpr *expr; |
61 | 61 |
double var_values[VAR_VARS_NB]; |
62 |
+ enum AVMediaType type; |
|
62 | 63 |
} SetPTSContext; |
63 | 64 |
|
64 | 65 |
static av_cold int init(AVFilterContext *ctx, const char *args) |
... | ... |
@@ -81,18 +89,24 @@ static av_cold int init(AVFilterContext *ctx, const char *args) |
81 | 81 |
|
82 | 82 |
static int config_input(AVFilterLink *inlink) |
83 | 83 |
{ |
84 |
- SetPTSContext *setpts = inlink->dst->priv; |
|
84 |
+ AVFilterContext *ctx = inlink->dst; |
|
85 |
+ SetPTSContext *setpts = ctx->priv; |
|
85 | 86 |
|
87 |
+ setpts->type = inlink->type; |
|
86 | 88 |
setpts->var_values[VAR_TB] = av_q2d(inlink->time_base); |
87 | 89 |
|
88 |
- av_log(inlink->src, AV_LOG_VERBOSE, "TB:%f\n", setpts->var_values[VAR_TB]); |
|
90 |
+ if (setpts->type == AVMEDIA_TYPE_AUDIO) |
|
91 |
+ setpts->var_values[VAR_SAMPLE_RATE] = inlink->sample_rate; |
|
92 |
+ |
|
93 |
+ av_log(inlink->src, AV_LOG_VERBOSE, "TB:%f SAMPLE_RATE:%f\n", |
|
94 |
+ setpts->var_values[VAR_TB], setpts->var_values[VAR_SAMPLE_RATE]); |
|
89 | 95 |
return 0; |
90 | 96 |
} |
91 | 97 |
|
92 | 98 |
#define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d)) |
93 | 99 |
#define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)) |
94 | 100 |
|
95 |
-static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) |
|
101 |
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) |
|
96 | 102 |
{ |
97 | 103 |
SetPTSContext *setpts = inlink->dst->priv; |
98 | 104 |
double d; |
... | ... |
@@ -103,28 +117,45 @@ static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) |
103 | 103 |
|
104 | 104 |
if (isnan(setpts->var_values[VAR_STARTPTS])) |
105 | 105 |
setpts->var_values[VAR_STARTPTS] = TS2D(inpicref->pts); |
106 |
- |
|
107 |
- setpts->var_values[VAR_INTERLACED] = inpicref->video->interlaced; |
|
108 | 106 |
setpts->var_values[VAR_PTS ] = TS2D(inpicref->pts); |
109 | 107 |
setpts->var_values[VAR_POS ] = inpicref->pos == -1 ? NAN : inpicref->pos; |
110 | 108 |
|
109 |
+ switch (inlink->type) { |
|
110 |
+ case AVMEDIA_TYPE_VIDEO: |
|
111 |
+ setpts->var_values[VAR_INTERLACED] = inpicref->video->interlaced; |
|
112 |
+ break; |
|
113 |
+ |
|
114 |
+ case AVMEDIA_TYPE_AUDIO: |
|
115 |
+ setpts->var_values[VAR_NB_SAMPLES] = inpicref->audio->nb_samples; |
|
116 |
+ break; |
|
117 |
+ } |
|
118 |
+ |
|
111 | 119 |
d = av_expr_eval(setpts->expr, setpts->var_values, NULL); |
112 | 120 |
outpicref->pts = D2TS(d); |
113 | 121 |
|
114 | 122 |
#ifdef DEBUG |
115 | 123 |
av_log(inlink->dst, AV_LOG_DEBUG, |
116 |
- "n:%"PRId64" interlaced:%d pos:%"PRId64" pts:%"PRId64" t:%f -> pts:%"PRId64" t:%f\n", |
|
124 |
+ "n:%"PRId64" interlaced:%d nb_samples:%d nb_consumed_samples:%d " |
|
125 |
+ "pos:%"PRId64" pts:%"PRId64" t:%f -> pts:%"PRId64" t:%f\n", |
|
117 | 126 |
(int64_t)setpts->var_values[VAR_N], |
118 | 127 |
(int)setpts->var_values[VAR_INTERLACED], |
128 |
+ (int)setpts->var_values[VAR_NB_SAMPLES], |
|
129 |
+ (int)setpts->var_values[VAR_NB_CONSUMED_SAMPLES], |
|
119 | 130 |
inpicref ->pos, |
120 | 131 |
inpicref ->pts, inpicref ->pts * av_q2d(inlink->time_base), |
121 | 132 |
outpicref->pts, outpicref->pts * av_q2d(inlink->time_base)); |
133 |
+ |
|
122 | 134 |
#endif |
123 | 135 |
|
124 | 136 |
setpts->var_values[VAR_N] += 1.0; |
125 | 137 |
setpts->var_values[VAR_PREV_INPTS ] = TS2D(inpicref ->pts); |
126 | 138 |
setpts->var_values[VAR_PREV_OUTPTS] = TS2D(outpicref->pts); |
127 |
- return ff_start_frame(inlink->dst->outputs[0], outpicref); |
|
139 |
+ |
|
140 |
+ if (setpts->type == AVMEDIA_TYPE_AUDIO) { |
|
141 |
+ setpts->var_values[VAR_NB_CONSUMED_SAMPLES] += inpicref->audio->nb_samples; |
|
142 |
+ return ff_filter_samples(inlink->dst->outputs[0], outpicref); |
|
143 |
+ } else |
|
144 |
+ return ff_start_frame (inlink->dst->outputs[0], outpicref); |
|
128 | 145 |
} |
129 | 146 |
|
130 | 147 |
static av_cold void uninit(AVFilterContext *ctx) |
... | ... |
@@ -134,6 +165,36 @@ static av_cold void uninit(AVFilterContext *ctx) |
134 | 134 |
setpts->expr = NULL; |
135 | 135 |
} |
136 | 136 |
|
137 |
+#if CONFIG_ASETPTS_FILTER |
|
138 |
+AVFilter avfilter_af_asetpts = { |
|
139 |
+ .name = "asetpts", |
|
140 |
+ .description = NULL_IF_CONFIG_SMALL("Set PTS for the output audio frame."), |
|
141 |
+ .init = init, |
|
142 |
+ .uninit = uninit, |
|
143 |
+ |
|
144 |
+ .priv_size = sizeof(SetPTSContext), |
|
145 |
+ |
|
146 |
+ .inputs = (const AVFilterPad[]) { |
|
147 |
+ { |
|
148 |
+ .name = "default", |
|
149 |
+ .type = AVMEDIA_TYPE_AUDIO, |
|
150 |
+ .get_audio_buffer = ff_null_get_audio_buffer, |
|
151 |
+ .config_props = config_input, |
|
152 |
+ .filter_samples = filter_frame, |
|
153 |
+ }, |
|
154 |
+ { .name = NULL } |
|
155 |
+ }, |
|
156 |
+ .outputs = (const AVFilterPad[]) { |
|
157 |
+ { |
|
158 |
+ .name = "default", |
|
159 |
+ .type = AVMEDIA_TYPE_AUDIO, |
|
160 |
+ }, |
|
161 |
+ { .name = NULL } |
|
162 |
+ }, |
|
163 |
+}; |
|
164 |
+#endif /* CONFIG_ASETPTS_FILTER */ |
|
165 |
+ |
|
166 |
+#if CONFIG_SETPTS_FILTER |
|
137 | 167 |
AVFilter avfilter_vf_setpts = { |
138 | 168 |
.name = "setpts", |
139 | 169 |
.description = NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."), |
... | ... |
@@ -146,9 +207,10 @@ AVFilter avfilter_vf_setpts = { |
146 | 146 |
.type = AVMEDIA_TYPE_VIDEO, |
147 | 147 |
.get_video_buffer = ff_null_get_video_buffer, |
148 | 148 |
.config_props = config_input, |
149 |
- .start_frame = start_frame, }, |
|
149 |
+ .start_frame = filter_frame, }, |
|
150 | 150 |
{ .name = NULL }}, |
151 | 151 |
.outputs = (const AVFilterPad[]) {{ .name = "default", |
152 | 152 |
.type = AVMEDIA_TYPE_VIDEO, }, |
153 | 153 |
{ .name = NULL}}, |
154 | 154 |
}; |
155 |
+#endif /* CONFIG_SETPTS_FILTER */ |