FFmpeg
setts_bsf.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 "avcodec.h"
30 #include "bsf.h"
31 #include "bsf_internal.h"
32 
33 static const char *const var_names[] = {
34  "N", ///< frame number (starting at zero)
35  "TS",
36  "POS", ///< original position in the file of the frame
37  "PREV_INPTS", ///< previous input PTS
38  "PREV_INDTS", ///< previous input DTS
39  "PREV_OUTPTS", ///< previous output PTS
40  "PREV_OUTDTS", ///< previous output DTS
41  "PTS", ///< original PTS in the file of the frame
42  "DTS", ///< original DTS in the file of the frame
43  "STARTPTS", ///< PTS at start of movie
44  "STARTDTS", ///< DTS at start of movie
45  "TB", ///< timebase of the stream
46  "SR", ///< sample rate of the stream
47  NULL
48 };
49 
50 enum var_name {
65 };
66 
67 typedef struct SetTSContext {
68  const AVClass *class;
69 
70  char *ts_str;
71  char *pts_str;
72  char *dts_str;
73 
74  int64_t frame_number;
75 
76  int64_t start_pts;
77  int64_t start_dts;
78  int64_t prev_inpts;
79  int64_t prev_indts;
80  int64_t prev_outpts;
81  int64_t prev_outdts;
82 
84 
88 } SetTSContext;
89 
91 {
92  SetTSContext *s = ctx->priv_data;
93  int ret;
94 
95  if ((ret = av_expr_parse(&s->ts_expr, s->ts_str,
96  var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
97  av_log(ctx, AV_LOG_ERROR, "Error while parsing ts expression '%s'\n", s->ts_str);
98  return ret;
99  }
100 
101  if (s->pts_str) {
102  if ((ret = av_expr_parse(&s->pts_expr, s->pts_str,
103  var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
104  av_log(ctx, AV_LOG_ERROR, "Error while parsing pts expression '%s'\n", s->pts_str);
105  return ret;
106  }
107  }
108 
109  if (s->dts_str) {
110  if ((ret = av_expr_parse(&s->dts_expr, s->dts_str,
111  var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
112  av_log(ctx, AV_LOG_ERROR, "Error while parsing dts expression '%s'\n", s->dts_str);
113  return ret;
114  }
115  }
116 
117  s->frame_number= 0;
124 
125  return 0;
126 }
127 
129 {
130  SetTSContext *s = ctx->priv_data;
131  int64_t new_ts, new_pts, new_dts;
132  int ret;
133 
134  ret = ff_bsf_get_packet_ref(ctx, pkt);
135  if (ret < 0)
136  return ret;
137 
138  if (s->start_pts == AV_NOPTS_VALUE)
139  s->start_pts = pkt->pts;
140 
141  if (s->start_dts == AV_NOPTS_VALUE)
142  s->start_dts = pkt->dts;
143 
144  s->var_values[VAR_N] = s->frame_number++;
145  s->var_values[VAR_TS] = pkt->dts;
146  s->var_values[VAR_POS] = pkt->pos;
147  s->var_values[VAR_PTS] = pkt->pts;
148  s->var_values[VAR_DTS] = pkt->dts;
155  s->var_values[VAR_TB] = ctx->time_base_out.den ? av_q2d(ctx->time_base_out) : 0;
156  s->var_values[VAR_SR] = ctx->par_in->sample_rate;
157 
158  new_ts = llrint(av_expr_eval(s->ts_expr, s->var_values, NULL));
159 
160  if (s->pts_str) {
161  s->var_values[VAR_TS] = pkt->pts;
162  new_pts = llrint(av_expr_eval(s->pts_expr, s->var_values, NULL));
163  } else {
164  new_pts = new_ts;
165  }
166 
167  if (s->dts_str) {
168  s->var_values[VAR_TS] = pkt->dts;
169  new_dts = llrint(av_expr_eval(s->dts_expr, s->var_values, NULL));
170  } else {
171  new_dts = new_ts;
172  }
173 
174  s->var_values[VAR_PREV_INPTS] = pkt->pts;
175  s->var_values[VAR_PREV_INDTS] = pkt->dts;
176  s->var_values[VAR_PREV_OUTPTS] = new_pts;
177  s->var_values[VAR_PREV_OUTDTS] = new_dts;
178 
179  pkt->pts = new_pts;
180  pkt->dts = new_dts;
181 
182  return ret;
183 }
184 
185 static void setts_close(AVBSFContext *bsf)
186 {
187  SetTSContext *s = bsf->priv_data;
188 
189  av_expr_free(s->ts_expr);
190  s->ts_expr = NULL;
192  s->pts_expr = NULL;
194  s->dts_expr = NULL;
195 }
196 
197 #define OFFSET(x) offsetof(SetTSContext, x)
198 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_SUBTITLE_PARAM|AV_OPT_FLAG_BSF_PARAM)
199 
200 static const AVOption options[] = {
201  { "ts", "set expression for packet PTS and DTS", OFFSET(ts_str), AV_OPT_TYPE_STRING, {.str="TS"}, 0, 0, FLAGS },
202  { "pts", "set expression for packet PTS", OFFSET(pts_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
203  { "dts", "set expression for packet DTS", OFFSET(dts_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
204  { NULL },
205 };
206 
207 static const AVClass setts_class = {
208  .class_name = "setts_bsf",
209  .item_name = av_default_item_name,
210  .option = options,
211  .version = LIBAVUTIL_VERSION_INT,
212 };
213 
215  .name = "setts",
216  .priv_data_size = sizeof(SetTSContext),
217  .priv_class = &setts_class,
218  .init = setts_init,
219  .close = setts_close,
220  .filter = setts_filter,
221 };
int64_t prev_outdts
Definition: setts_bsf.c:81
#define NULL
Definition: coverity.c:32
#define OFFSET(x)
Definition: setts_bsf.c:197
AVOption.
Definition: opt.h:248
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
int64_t pos
byte position in stream, -1 if unknown
Definition: packet.h:389
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:31
The bitstream filter state.
Definition: bsf.h:49
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
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:685
AVPacket * pkt
Definition: movenc.c:59
void * priv_data
Opaque filter-specific private data.
Definition: bsf.h:70
char * ts_str
Definition: setts_bsf.c:70
AVExpr * dts_expr
Definition: setts_bsf.c:87
int64_t prev_inpts
Definition: setts_bsf.c:78
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:72
const AVBitStreamFilter ff_setts_bsf
Definition: setts_bsf.c:214
AVOptions.
#define FLAGS
Definition: setts_bsf.c:198
Definition: eval.c:157
const char * name
Definition: bsf.h:99
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition: rational.h:104
int64_t start_pts
Definition: setts_bsf.c:76
#define av_log(a,...)
static void setts_close(AVBSFContext *bsf)
Definition: setts_bsf.c:185
char * dts_str
Definition: setts_bsf.c:72
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce then the filter should push the output frames on the output link immediately As an exception to the previous rule if the input frame is enough to produce several output frames then the filter needs output only at least one per link The additional frames can be left buffered in the filter
AVRational time_base_out
The timebase used for the timestamps of the output packets.
Definition: bsf.h:95
AVFormatContext * ctx
Definition: movenc.c:48
#define s(width, name)
Definition: cbs_vp9.c:257
int64_t start_dts
Definition: setts_bsf.c:77
static int setts_filter(AVBSFContext *ctx, AVPacket *pkt)
Definition: setts_bsf.c:128
AVExpr * ts_expr
Definition: setts_bsf.c:85
Libavcodec external API header.
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition: eval.c:336
AVExpr * pts_expr
Definition: setts_bsf.c:86
#define llrint(x)
Definition: libm.h:394
Describe the class of an AVClass context structure.
Definition: log.h:67
static int setts_init(AVBSFContext *ctx)
Definition: setts_bsf.c:90
char * pts_str
Definition: setts_bsf.c:71
static const AVOption options[]
Definition: setts_bsf.c:200
static const char *const var_names[]
Definition: setts_bsf.c:33
int sample_rate
Audio only.
Definition: codec_par.h:170
double var_values[VAR_VARS_NB]
Definition: setts_bsf.c:83
int64_t frame_number
Definition: setts_bsf.c:74
int den
Denominator.
Definition: rational.h:60
int64_t prev_indts
Definition: setts_bsf.c:79
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition: eval.c:766
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
Definition: packet.h:368
int64_t prev_outpts
Definition: setts_bsf.c:80
This structure stores compressed data.
Definition: packet.h:346
static const AVClass setts_class
Definition: setts_bsf.c:207
AVCodecParameters * par_in
Parameters of the input stream.
Definition: bsf.h:77
int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt)
Called by bitstream filters to get packet for filtering.
Definition: bsf.c:253
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:362
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
var_name
Definition: setts_bsf.c:50
simple arithmetic expression evaluator