FFmpeg
Loading...
Searching...
No Matches
setts.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 Paul B Mahol
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 * Change the PTS/DTS timestamps.
24 */
25
26#include "libavutil/opt.h"
27#include "libavutil/eval.h"
28
29#include "libavcodec/bsf.h"
31
32static const char *const var_names[] = {
33 "N", ///< frame number (starting at zero)
34 "TS",
35 "POS", ///< original position in the file of the frame
36 "PREV_INPTS", ///< previous input PTS
37 "PREV_INDTS", ///< previous input DTS
38 "PREV_INDURATION", ///< previous input duration
39 "PREV_OUTPTS", ///< previous output PTS
40 "PREV_OUTDTS", ///< previous output DTS
41 "PREV_OUTDURATION", ///< previous output duration
42 "NEXT_PTS", ///< next input PTS
43 "NEXT_DTS", ///< next input DTS
44 "NEXT_DURATION", ///< next input duration
45 "PTS", ///< original PTS in the file of the frame
46 "DTS", ///< original DTS in the file of the frame
47 "DURATION", ///< original duration in the file of the frame
48 "STARTPTS", ///< PTS at start of movie
49 "STARTDTS", ///< DTS at start of movie
50 "TB", ///< input timebase of the stream
51 "TB_OUT", ///< output timebase of the stream
52 "SR", ///< sample rate of the stream
53 "NOPTS", ///< The AV_NOPTS_VALUE constant
54 NULL
55};
56
81
107
109{
110 SetTSContext *s = ctx->priv_data;
111 int ret;
112
113 s->prev_inpkt = av_packet_alloc();
114 s->prev_outpkt = av_packet_alloc();
115 s->cur_pkt = av_packet_alloc();
116 if (!s->prev_inpkt || !s->prev_outpkt || !s->cur_pkt)
117 return AVERROR(ENOMEM);
118
119 if ((ret = av_expr_parse(&s->ts_expr, s->ts_str,
120 var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
121 av_log(ctx, AV_LOG_ERROR, "Error while parsing ts expression '%s'\n", s->ts_str);
122 return ret;
123 }
124
125 if ((ret = av_expr_parse(&s->duration_expr, s->duration_str,
126 var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
127 av_log(ctx, AV_LOG_ERROR, "Error while parsing duration expression '%s'\n", s->duration_str);
128 return ret;
129 }
130
131 if (s->pts_str) {
132 if ((ret = av_expr_parse(&s->pts_expr, s->pts_str,
133 var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
134 av_log(ctx, AV_LOG_ERROR, "Error while parsing pts expression '%s'\n", s->pts_str);
135 return ret;
136 }
137 }
138
139 if (s->dts_str) {
140 if ((ret = av_expr_parse(&s->dts_expr, s->dts_str,
141 var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
142 av_log(ctx, AV_LOG_ERROR, "Error while parsing dts expression '%s'\n", s->dts_str);
143 return ret;
144 }
145 }
146
147 if (s->time_base.num > 0 && s->time_base.den > 0) {
148 ctx->time_base_out = s->time_base;
149 s->user_outtb = 1;
150 } else if (s->time_base.num || !s->time_base.den) {
151 av_log(ctx, AV_LOG_ERROR, "Invalid value %d/%d specified for output timebase\n", s->time_base.num, s->time_base.den);
152 return AVERROR_INVALIDDATA;
153 } else
154 s->prescale = 0;
155
156 s->frame_number= 0;
157 s->var_values[VAR_STARTPTS] = AV_NOPTS_VALUE;
158 s->var_values[VAR_STARTDTS] = AV_NOPTS_VALUE;
159 s->var_values[VAR_NOPTS] = AV_NOPTS_VALUE;
160 s->var_values[VAR_TB_OUT]= ctx->time_base_out.den ? av_q2d(ctx->time_base_out) : 0;
161 s->var_values[VAR_SR] = ctx->par_in->sample_rate;
162
163 if (s->user_outtb && s->prescale)
164 s->var_values[VAR_TB] = av_q2d(ctx->time_base_out);
165 else
166 s->var_values[VAR_TB] = ctx->time_base_in.den ? av_q2d(ctx->time_base_in) : 0;
167
168 return 0;
169}
170
171#define PRESCALED(x) ( s->prescale ? av_rescale_q(x, ctx->time_base_in, ctx->time_base_out) : x )
172
174{
175 SetTSContext *s = ctx->priv_data;
176 int64_t new_ts, new_pts, new_dts, new_duration;
177 int ret;
178
180 if (ret < 0 && (ret != AVERROR_EOF || !s->cur_pkt->data))
181 return ret;
182
183 if (!s->cur_pkt->data) {
184 av_packet_move_ref(s->cur_pkt, pkt);
185 return AVERROR(EAGAIN);
186 }
187
188 if (s->var_values[VAR_STARTPTS] == AV_NOPTS_VALUE)
189 s->var_values[VAR_STARTPTS] = PRESCALED(s->cur_pkt->pts);
190
191 if (s->var_values[VAR_STARTDTS] == AV_NOPTS_VALUE)
192 s->var_values[VAR_STARTDTS] = PRESCALED(s->cur_pkt->dts);
193
194 s->var_values[VAR_N] = s->frame_number++;
195 s->var_values[VAR_TS] = PRESCALED(s->cur_pkt->dts);
196 s->var_values[VAR_POS] = s->cur_pkt->pos;
197 s->var_values[VAR_PTS] = PRESCALED(s->cur_pkt->pts);
198 s->var_values[VAR_DTS] = PRESCALED(s->cur_pkt->dts);
199 s->var_values[VAR_DURATION] = PRESCALED(s->cur_pkt->duration);
200 s->var_values[VAR_PREV_INPTS] = PRESCALED(s->prev_inpkt->pts);
201 s->var_values[VAR_PREV_INDTS] = PRESCALED(s->prev_inpkt->dts);
202 s->var_values[VAR_PREV_INDUR] = PRESCALED(s->prev_inpkt->duration);
203 s->var_values[VAR_PREV_OUTPTS] = s->prev_outpkt->pts;
204 s->var_values[VAR_PREV_OUTDTS] = s->prev_outpkt->dts;
205 s->var_values[VAR_PREV_OUTDUR] = s->prev_outpkt->duration;
206 s->var_values[VAR_NEXT_PTS] = PRESCALED(pkt->pts);
207 s->var_values[VAR_NEXT_DTS] = PRESCALED(pkt->dts);
208 s->var_values[VAR_NEXT_DUR] = PRESCALED(pkt->duration);
209
210 new_ts = llrint(av_expr_eval(s->ts_expr, s->var_values, NULL));
211 new_duration = llrint(av_expr_eval(s->duration_expr, s->var_values, NULL));
212
213 if (s->pts_str) {
214 s->var_values[VAR_TS] = PRESCALED(s->cur_pkt->pts);
215 new_pts = llrint(av_expr_eval(s->pts_expr, s->var_values, NULL));
216 } else {
217 new_pts = new_ts;
218 }
219
220 if (s->dts_str) {
221 s->var_values[VAR_TS] = PRESCALED(s->cur_pkt->dts);
222 new_dts = llrint(av_expr_eval(s->dts_expr, s->var_values, NULL));
223 } else {
224 new_dts = new_ts;
225 }
226
227 av_packet_unref(s->prev_inpkt);
228 av_packet_unref(s->prev_outpkt);
229 av_packet_move_ref(s->prev_inpkt, s->cur_pkt);
230 av_packet_move_ref(s->cur_pkt, pkt);
231
232 ret = av_packet_ref(pkt, s->prev_inpkt);
233 if (ret < 0)
234 return ret;
235
236 if (s->user_outtb && !s->prescale) {
237 new_pts = av_rescale_q(new_pts, ctx->time_base_in, ctx->time_base_out);
238 new_dts = av_rescale_q(new_dts, ctx->time_base_in, ctx->time_base_out);
239 new_duration = av_rescale_q(new_duration, ctx->time_base_in, ctx->time_base_out);
240 }
241
242 pkt->pts = new_pts;
243 pkt->dts = new_dts;
244 pkt->duration = new_duration;
245
246 ret = av_packet_ref(s->prev_outpkt, pkt);
247 if (ret < 0)
249
250 return ret;
251}
252
253static void setts_close(AVBSFContext *bsf)
254{
255 SetTSContext *s = bsf->priv_data;
256
257 av_packet_free(&s->prev_inpkt);
258 av_packet_free(&s->prev_outpkt);
259 av_packet_free(&s->cur_pkt);
260
261 av_expr_free(s->ts_expr);
262 s->ts_expr = NULL;
263 av_expr_free(s->pts_expr);
264 s->pts_expr = NULL;
265 av_expr_free(s->dts_expr);
266 s->dts_expr = NULL;
267 av_expr_free(s->duration_expr);
268 s->duration_expr = NULL;
269}
270
271#define OFFSET(x) offsetof(SetTSContext, x)
272#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_SUBTITLE_PARAM|AV_OPT_FLAG_BSF_PARAM)
273
274static const AVOption options[] = {
275 { "ts", "set expression for packet PTS and DTS", OFFSET(ts_str), AV_OPT_TYPE_STRING, {.str="TS"}, 0, 0, FLAGS },
276 { "pts", "set expression for packet PTS", OFFSET(pts_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
277 { "dts", "set expression for packet DTS", OFFSET(dts_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
278 { "duration", "set expression for packet duration", OFFSET(duration_str), AV_OPT_TYPE_STRING, {.str="DURATION"}, 0, 0, FLAGS },
279 { "time_base", "set output timebase", OFFSET(time_base), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS },
280 { "prescale", "convert to output timebase before evaluation", OFFSET(prescale), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
281 { NULL },
282};
283
284static const AVClass setts_class = {
285 .class_name = "setts_bsf",
286 .item_name = av_default_item_name,
287 .option = options,
288 .version = LIBAVUTIL_VERSION_INT,
289};
290
292 .p.name = "setts",
293 .p.priv_class = &setts_class,
294 .priv_data_size = sizeof(SetTSContext),
295 .init = setts_init,
298};
static AVFormatContext * ctx
static av_cold void close(AVCodecParserContext *s)
Definition apv_parser.c:197
const FFBitStreamFilter ff_setts_bsf
Definition setts.c:291
int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt)
Called by bitstream filters to get packet for filtering.
Definition bsf.c:254
#define s(width, name)
Definition cbs_vp9.c:198
#define FLAGS
Definition cmdutils.c:598
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static AVPacket * pkt
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition eval.c:368
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition eval.c:824
int av_expr_parse(AVExpr **expr, const char *s, const char *const *const_names, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), int log_offset, void *log_ctx)
Parse an expression.
Definition eval.c:735
simple arithmetic expression evaluator
static const FLOAT prescale[64]
Definition faanidct.c:40
@ AV_OPT_TYPE_RATIONAL
Underlying C type is AVRational.
Definition opt.h:279
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition opt.h:326
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition packet.c:74
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition packet.c:434
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition packet.c:491
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition packet.c:63
int av_packet_ref(AVPacket *dst, const AVPacket *src)
Setup a new reference to the data described by a given packet.
Definition packet.c:442
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR_EOF
End of file.
Definition error.h:57
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition rational.h:104
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition avutil.h:247
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
#define llrint(x)
Definition libm.h:396
var_name
Definition noise.c:46
@ VAR_STARTPTS
Definition noise.c:52
@ VAR_PTS
Definition noise.c:49
@ VAR_POS
Definition noise.c:55
@ VAR_TB
Definition noise.c:48
@ VAR_NOPTS
Definition noise.c:51
@ VAR_DTS
Definition noise.c:50
@ VAR_N
Definition noise.c:47
@ VAR_VARS_NB
Definition noise.c:59
@ VAR_DURATION
Definition noise.c:54
@ VAR_STARTDTS
Definition noise.c:53
static const char *const var_names[]
Definition noise.c:30
AVOptions.
@ VAR_TS
Definition setts.c:59
@ VAR_PREV_OUTDTS
Definition setts.c:65
@ VAR_PREV_INDTS
Definition setts.c:62
@ VAR_PREV_OUTDUR
Definition setts.c:66
@ VAR_NEXT_DUR
Definition setts.c:69
@ VAR_PREV_OUTPTS
Definition setts.c:64
@ VAR_VARS_NB
Definition setts.c:79
@ VAR_NEXT_DTS
Definition setts.c:68
@ VAR_SR
Definition setts.c:77
@ VAR_NEXT_PTS
Definition setts.c:67
@ VAR_TB_OUT
Definition setts.c:76
@ VAR_PREV_INPTS
Definition setts.c:61
@ VAR_PREV_INDUR
Definition setts.c:63
static int setts_init(AVBSFContext *ctx)
Definition setts.c:108
static const AVClass setts_class
Definition setts.c:284
static int setts_filter(AVBSFContext *ctx, AVPacket *pkt)
Definition setts.c:173
static void setts_close(AVBSFContext *bsf)
Definition setts.c:253
#define OFFSET(x)
Definition setts.c:271
#define PRESCALED(x)
Definition setts.c:171
The bitstream filter state.
Definition bsf.h:68
void * priv_data
Opaque filter-specific private data.
Definition bsf.h:83
Describe the class of an AVClass context structure.
Definition log.h:76
Definition eval.c:171
AVOption.
Definition opt.h:428
This structure stores compressed data.
Definition packet.h:580
Rational number (pair of numerator and denominator).
Definition rational.h:58
AVPacket * prev_inpkt
Definition setts.c:103
AVPacket * prev_outpkt
Definition setts.c:104
AVExpr * dts_expr
Definition setts.c:100
double var_values[VAR_VARS_NB]
Definition setts.c:96
AVPacket * cur_pkt
Definition setts.c:105
char * dts_str
Definition setts.c:87
int prescale
Definition setts.c:92
int64_t frame_number
Definition setts.c:94
AVExpr * pts_expr
Definition setts.c:99
char * duration_str
Definition setts.c:88
int user_outtb
Definition setts.c:91
char * pts_str
Definition setts.c:86
AVExpr * duration_expr
Definition setts.c:101
AVRational time_base
Definition setts.c:90
AVExpr * ts_expr
Definition setts.c:98
char * ts_str
Definition setts.c:85
#define av_log(a,...)
void(* filter)(uint8_t *src, ptrdiff_t stride, int qscale)
Definition h263dsp.c:29
static void ts_str(char buffer[60], int64_t ts, AVRational base)
Definition seek.c:47