FFmpeg
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 "bsf.h"
30 #include "bsf_internal.h"
31 
32 static 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 
57 enum var_name {
80 };
81 
82 typedef struct SetTSContext {
83  const AVClass *class;
84 
85  char *ts_str;
86  char *pts_str;
87  char *dts_str;
88  char *duration_str;
89 
91 
93 
95 
100 
104 } SetTSContext;
105 
107 {
109  int ret;
110 
111  s->prev_inpkt = av_packet_alloc();
112  s->prev_outpkt = av_packet_alloc();
113  s->cur_pkt = av_packet_alloc();
114  if (!s->prev_inpkt || !s->prev_outpkt || !s->cur_pkt)
115  return AVERROR(ENOMEM);
116 
117  if ((ret = av_expr_parse(&s->ts_expr, s->ts_str,
118  var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
119  av_log(ctx, AV_LOG_ERROR, "Error while parsing ts expression '%s'\n", s->ts_str);
120  return ret;
121  }
122 
123  if ((ret = av_expr_parse(&s->duration_expr, s->duration_str,
124  var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
125  av_log(ctx, AV_LOG_ERROR, "Error while parsing duration expression '%s'\n", s->duration_str);
126  return ret;
127  }
128 
129  if (s->pts_str) {
130  if ((ret = av_expr_parse(&s->pts_expr, s->pts_str,
131  var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
132  av_log(ctx, AV_LOG_ERROR, "Error while parsing pts expression '%s'\n", s->pts_str);
133  return ret;
134  }
135  }
136 
137  if (s->dts_str) {
138  if ((ret = av_expr_parse(&s->dts_expr, s->dts_str,
139  var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
140  av_log(ctx, AV_LOG_ERROR, "Error while parsing dts expression '%s'\n", s->dts_str);
141  return ret;
142  }
143  }
144 
145  if (s->time_base.num > 0 && s->time_base.den > 0)
146  ctx->time_base_out = s->time_base;
147 
148  s->frame_number= 0;
149  s->var_values[VAR_STARTPTS] = AV_NOPTS_VALUE;
150  s->var_values[VAR_STARTDTS] = AV_NOPTS_VALUE;
151  s->var_values[VAR_NOPTS] = AV_NOPTS_VALUE;
152  s->var_values[VAR_TB] = ctx->time_base_in.den ? av_q2d(ctx->time_base_in) : 0;
153  s->var_values[VAR_TB_OUT]= ctx->time_base_out.den ? av_q2d(ctx->time_base_out) : 0;
154  s->var_values[VAR_SR] = ctx->par_in->sample_rate;
155 
156  return 0;
157 }
158 
160 {
162  int64_t new_ts, new_pts, new_dts, new_duration;
163  int ret;
164 
166  if (ret < 0 && (ret != AVERROR_EOF || !s->cur_pkt->data))
167  return ret;
168 
169  if (!s->cur_pkt->data) {
170  av_packet_move_ref(s->cur_pkt, pkt);
171  return AVERROR(EAGAIN);
172  }
173 
174  if (s->var_values[VAR_STARTPTS] == AV_NOPTS_VALUE)
175  s->var_values[VAR_STARTPTS] = s->cur_pkt->pts;
176 
177  if (s->var_values[VAR_STARTDTS] == AV_NOPTS_VALUE)
178  s->var_values[VAR_STARTDTS] = s->cur_pkt->dts;
179 
180  s->var_values[VAR_N] = s->frame_number++;
181  s->var_values[VAR_TS] = s->cur_pkt->dts;
182  s->var_values[VAR_POS] = s->cur_pkt->pos;
183  s->var_values[VAR_PTS] = s->cur_pkt->pts;
184  s->var_values[VAR_DTS] = s->cur_pkt->dts;
185  s->var_values[VAR_DURATION] = s->cur_pkt->duration;
186  s->var_values[VAR_PREV_INPTS] = s->prev_inpkt->pts;
187  s->var_values[VAR_PREV_INDTS] = s->prev_inpkt->dts;
188  s->var_values[VAR_PREV_INDUR] = s->prev_inpkt->duration;
189  s->var_values[VAR_PREV_OUTPTS] = s->prev_outpkt->pts;
190  s->var_values[VAR_PREV_OUTDTS] = s->prev_outpkt->dts;
191  s->var_values[VAR_PREV_OUTDUR] = s->prev_outpkt->duration;
192  s->var_values[VAR_NEXT_PTS] = pkt->pts;
193  s->var_values[VAR_NEXT_DTS] = pkt->dts;
194  s->var_values[VAR_NEXT_DUR] = pkt->duration;
195 
196  new_ts = llrint(av_expr_eval(s->ts_expr, s->var_values, NULL));
197  new_duration = llrint(av_expr_eval(s->duration_expr, s->var_values, NULL));
198 
199  if (s->pts_str) {
200  s->var_values[VAR_TS] = s->cur_pkt->pts;
201  new_pts = llrint(av_expr_eval(s->pts_expr, s->var_values, NULL));
202  } else {
203  new_pts = new_ts;
204  }
205 
206  if (s->dts_str) {
207  s->var_values[VAR_TS] = s->cur_pkt->dts;
208  new_dts = llrint(av_expr_eval(s->dts_expr, s->var_values, NULL));
209  } else {
210  new_dts = new_ts;
211  }
212 
213  av_packet_unref(s->prev_inpkt);
214  av_packet_unref(s->prev_outpkt);
215  av_packet_move_ref(s->prev_inpkt, s->cur_pkt);
216  av_packet_move_ref(s->cur_pkt, pkt);
217 
218  ret = av_packet_ref(pkt, s->prev_inpkt);
219  if (ret < 0)
220  return ret;
221 
222  pkt->pts = new_pts;
223  pkt->dts = new_dts;
224  pkt->duration = new_duration;
225 
226  ret = av_packet_ref(s->prev_outpkt, pkt);
227  if (ret < 0)
229 
230  return ret;
231 }
232 
233 static void setts_close(AVBSFContext *bsf)
234 {
235  SetTSContext *s = bsf->priv_data;
236 
237  av_packet_free(&s->prev_inpkt);
238  av_packet_free(&s->prev_outpkt);
239  av_packet_free(&s->cur_pkt);
240 
241  av_expr_free(s->ts_expr);
242  s->ts_expr = NULL;
243  av_expr_free(s->pts_expr);
244  s->pts_expr = NULL;
245  av_expr_free(s->dts_expr);
246  s->dts_expr = NULL;
247  av_expr_free(s->duration_expr);
248  s->duration_expr = NULL;
249 }
250 
251 #define OFFSET(x) offsetof(SetTSContext, x)
252 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_SUBTITLE_PARAM|AV_OPT_FLAG_BSF_PARAM)
253 
254 static const AVOption options[] = {
255  { "ts", "set expression for packet PTS and DTS", OFFSET(ts_str), AV_OPT_TYPE_STRING, {.str="TS"}, 0, 0, FLAGS },
256  { "pts", "set expression for packet PTS", OFFSET(pts_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
257  { "dts", "set expression for packet DTS", OFFSET(dts_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
258  { "duration", "set expression for packet duration", OFFSET(duration_str), AV_OPT_TYPE_STRING, {.str="DURATION"}, 0, 0, FLAGS },
259  { "time_base", "set output timebase", OFFSET(time_base), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS },
260  { NULL },
261 };
262 
263 static const AVClass setts_class = {
264  .class_name = "setts_bsf",
265  .item_name = av_default_item_name,
266  .option = options,
267  .version = LIBAVUTIL_VERSION_INT,
268 };
269 
271  .p.name = "setts",
272  .p.priv_class = &setts_class,
273  .priv_data_size = sizeof(SetTSContext),
274  .init = setts_init,
275  .close = setts_close,
276  .filter = setts_filter,
277 };
SetTSContext::cur_pkt
AVPacket * cur_pkt
Definition: setts.c:103
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: packet.c:429
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
VAR_TB_OUT
@ VAR_TB_OUT
Definition: setts.c:76
bsf_internal.h
opt.h
var_name
var_name
Definition: noise.c:47
VAR_PREV_OUTPTS
@ VAR_PREV_OUTPTS
Definition: setts.c:64
VAR_NEXT_DUR
@ VAR_NEXT_DUR
Definition: setts.c:69
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
AVBitStreamFilter::name
const char * name
Definition: bsf.h:112
int64_t
long long int64_t
Definition: coverity.c:34
setts_init
static int setts_init(AVBSFContext *ctx)
Definition: setts.c:106
SetTSContext::duration_expr
AVExpr * duration_expr
Definition: setts.c:99
AVOption
AVOption.
Definition: opt.h:429
SetTSContext::var_values
double var_values[VAR_VARS_NB]
Definition: setts.c:94
options
static const AVOption options[]
Definition: setts.c:254
VAR_DURATION
@ VAR_DURATION
Definition: setts.c:72
filter
void(* filter)(uint8_t *src, int stride, int qscale)
Definition: h263dsp.c:29
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:557
AV_OPT_TYPE_RATIONAL
@ AV_OPT_TYPE_RATIONAL
Underlying C type is AVRational.
Definition: opt.h:280
av_packet_free
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: packet.c:74
AVBSFContext
The bitstream filter state.
Definition: bsf.h:68
av_expr_parse
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:710
var_names
static const char *const var_names[]
Definition: setts.c:32
VAR_PREV_OUTDTS
@ VAR_PREV_OUTDTS
Definition: setts.c:65
bsf.h
SetTSContext::duration_str
char * duration_str
Definition: setts.c:88
VAR_DTS
@ VAR_DTS
Definition: setts.c:71
VAR_NEXT_DTS
@ VAR_NEXT_DTS
Definition: setts.c:68
VAR_POS
@ VAR_POS
Definition: setts.c:60
SetTSContext::ts_expr
AVExpr * ts_expr
Definition: setts.c:96
VAR_NEXT_PTS
@ VAR_NEXT_PTS
Definition: setts.c:67
VAR_STARTDTS
@ VAR_STARTDTS
Definition: setts.c:74
av_expr_free
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition: eval.c:358
SetTSContext::time_base
AVRational time_base
Definition: setts.c:90
VAR_STARTPTS
@ VAR_STARTPTS
Definition: setts.c:73
pkt
AVPacket * pkt
Definition: movenc.c:60
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
setts_class
static const AVClass setts_class
Definition: setts.c:263
s
#define s(width, name)
Definition: cbs_vp9.c:198
av_q2d
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition: rational.h:104
ctx
AVFormatContext * ctx
Definition: movenc.c:49
av_expr_eval
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition: eval.c:792
VAR_TS
@ VAR_TS
Definition: setts.c:59
VAR_TB
@ VAR_TB
Definition: setts.c:75
AVExpr
Definition: eval.c:158
setts_filter
static int setts_filter(AVBSFContext *ctx, AVPacket *pkt)
Definition: setts.c:159
VAR_PREV_INDUR
@ VAR_PREV_INDUR
Definition: setts.c:63
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
SetTSContext
Definition: setts.c:82
NULL
#define NULL
Definition: coverity.c:32
setts_close
static void setts_close(AVBSFContext *bsf)
Definition: setts.c:233
ts_str
static void ts_str(char buffer[60], int64_t ts, AVRational base)
Definition: seek.c:47
FFBitStreamFilter
Definition: bsf_internal.h:27
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
SetTSContext::frame_number
int64_t frame_number
Definition: setts.c:92
av_packet_ref
int av_packet_ref(AVPacket *dst, const AVPacket *src)
Setup a new reference to the data described by a given packet.
Definition: packet.c:437
av_packet_move_ref
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition: packet.c:486
SetTSContext::pts_expr
AVExpr * pts_expr
Definition: setts.c:97
FFBitStreamFilter::p
AVBitStreamFilter p
The public AVBitStreamFilter.
Definition: bsf_internal.h:31
eval.h
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:368
ff_setts_bsf
const FFBitStreamFilter ff_setts_bsf
Definition: setts.c:270
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
SetTSContext::prev_outpkt
AVPacket * prev_outpkt
Definition: setts.c:102
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:538
SetTSContext::prev_inpkt
AVPacket * prev_inpkt
Definition: setts.c:101
av_packet_alloc
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition: packet.c:63
VAR_N
@ VAR_N
Definition: setts.c:58
SetTSContext::dts_expr
AVExpr * dts_expr
Definition: setts.c:98
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:532
VAR_PREV_INDTS
@ VAR_PREV_INDTS
Definition: setts.c:62
VAR_PREV_OUTDUR
@ VAR_PREV_OUTDUR
Definition: setts.c:66
AVBSFContext::priv_data
void * priv_data
Opaque filter-specific private data.
Definition: bsf.h:83
ret
ret
Definition: filter_design.txt:187
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:80
VAR_PTS
@ VAR_PTS
Definition: setts.c:70
VAR_NOPTS
@ VAR_NOPTS
Definition: setts.c:78
SetTSContext::ts_str
char * ts_str
Definition: setts.c:85
SetTSContext::pts_str
char * pts_str
Definition: setts.c:86
VAR_VARS_NB
@ VAR_VARS_NB
Definition: setts.c:79
SetTSContext::dts_str
char * dts_str
Definition: setts.c:87
llrint
#define llrint(x)
Definition: libm.h:394
AVPacket
This structure stores compressed data.
Definition: packet.h:516
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
ff_bsf_get_packet_ref
int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt)
Called by bitstream filters to get packet for filtering.
Definition: bsf.c:256
AV_OPT_TYPE_STRING
@ 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:276
OFFSET
#define OFFSET(x)
Definition: setts.c:251
AVFormatContext::priv_data
void * priv_data
Format private data.
Definition: avformat.h:1328
VAR_PREV_INPTS
@ VAR_PREV_INPTS
Definition: setts.c:61
FLAGS
#define FLAGS
Definition: setts.c:252
VAR_SR
@ VAR_SR
Definition: setts.c:77