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 {
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;
118  s->start_pts = AV_NOPTS_VALUE;
119  s->start_dts = AV_NOPTS_VALUE;
120  s->prev_inpts = AV_NOPTS_VALUE;
121  s->prev_indts = AV_NOPTS_VALUE;
122  s->prev_outpts = AV_NOPTS_VALUE;
123  s->prev_outdts = AV_NOPTS_VALUE;
124 
125  return 0;
126 }
127 
129 {
131  int64_t new_ts, new_pts, new_dts;
132  int ret;
133 
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;
149  s->var_values[VAR_PREV_INPTS] = s->prev_inpts;
150  s->var_values[VAR_PREV_INDTS] = s->prev_indts;
151  s->var_values[VAR_PREV_OUTPTS] = s->prev_outpts;
152  s->var_values[VAR_PREV_OUTDTS] = s->prev_outdts;
153  s->var_values[VAR_STARTPTS] = s->start_pts;
154  s->var_values[VAR_STARTDTS] = s->start_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;
191  av_expr_free(s->pts_expr);
192  s->pts_expr = NULL;
193  av_expr_free(s->dts_expr);
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 };
SetTSContext::start_pts
int64_t start_pts
Definition: setts_bsf.c:76
setts_class
static const AVClass setts_class
Definition: setts_bsf.c:207
init
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:31
VAR_TB
@ VAR_TB
Definition: setts_bsf.c:62
bsf_internal.h
opt.h
VAR_STARTDTS
@ VAR_STARTDTS
Definition: setts_bsf.c:61
ff_setts_bsf
const AVBitStreamFilter ff_setts_bsf
Definition: setts_bsf.c:214
AVBitStreamFilter::name
const char * name
Definition: bsf.h:99
FLAGS
#define FLAGS
Definition: setts_bsf.c:198
AVOption
AVOption.
Definition: opt.h:248
SetTSContext::var_values
double var_values[VAR_VARS_NB]
Definition: setts_bsf.c:83
VAR_N
@ VAR_N
Definition: setts_bsf.c:51
VAR_POS
@ VAR_POS
Definition: setts_bsf.c:53
filter
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
Definition: filter_design.txt:228
ts_str
static void ts_str(char buffer[60], int64_t ts, AVRational base)
Definition: seek.c:47
VAR_VARS_NB
@ VAR_VARS_NB
Definition: setts_bsf.c:64
AVBSFContext
The bitstream filter state.
Definition: bsf.h:49
SetTSContext::prev_indts
int64_t prev_indts
Definition: setts_bsf.c:79
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:685
bsf.h
VAR_SR
@ VAR_SR
Definition: setts_bsf.c:63
options
static const AVOption options[]
Definition: setts_bsf.c:200
VAR_DTS
@ VAR_DTS
Definition: setts_bsf.c:59
SetTSContext::ts_expr
AVExpr * ts_expr
Definition: setts_bsf.c:85
av_expr_free
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition: eval.c:336
pkt
AVPacket * pkt
Definition: movenc.c:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
var_name
var_name
Definition: setts_bsf.c:50
VAR_TS
@ VAR_TS
Definition: setts_bsf.c:52
SetTSContext::prev_outdts
int64_t prev_outdts
Definition: setts_bsf.c:81
s
#define s(width, name)
Definition: cbs_vp9.c:257
VAR_PREV_INDTS
@ VAR_PREV_INDTS
Definition: setts_bsf.c:55
av_q2d
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition: rational.h:104
VAR_PREV_OUTDTS
@ VAR_PREV_OUTDTS
Definition: setts_bsf.c:57
OFFSET
#define OFFSET(x)
Definition: setts_bsf.c:197
ctx
AVFormatContext * ctx
Definition: movenc.c:48
av_expr_eval
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition: eval.c:766
AVExpr
Definition: eval.c:157
setts_init
static int setts_init(AVBSFContext *ctx)
Definition: setts_bsf.c:90
SetTSContext::start_dts
int64_t start_dts
Definition: setts_bsf.c:77
VAR_PREV_INPTS
@ VAR_PREV_INPTS
Definition: setts_bsf.c:54
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:67
SetTSContext
Definition: setts_bsf.c:67
NULL
#define NULL
Definition: coverity.c:32
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
SetTSContext::frame_number
int64_t frame_number
Definition: setts_bsf.c:74
SetTSContext::pts_expr
AVExpr * pts_expr
Definition: setts_bsf.c:86
eval.h
VAR_PREV_OUTPTS
@ VAR_PREV_OUTPTS
Definition: setts_bsf.c:56
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:368
VAR_STARTPTS
@ VAR_STARTPTS
Definition: setts_bsf.c:60
SetTSContext::dts_expr
AVExpr * dts_expr
Definition: setts_bsf.c:87
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:362
var_names
static const char *const var_names[]
Definition: setts_bsf.c:33
avcodec.h
AVBSFContext::priv_data
void * priv_data
Opaque filter-specific private data.
Definition: bsf.h:70
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:72
setts_close
static void setts_close(AVBSFContext *bsf)
Definition: setts_bsf.c:185
SetTSContext::prev_outpts
int64_t prev_outpts
Definition: setts_bsf.c:80
setts_filter
static int setts_filter(AVBSFContext *ctx, AVPacket *pkt)
Definition: setts_bsf.c:128
AVBitStreamFilter
Definition: bsf.h:98
SetTSContext::ts_str
char * ts_str
Definition: setts_bsf.c:70
SetTSContext::pts_str
char * pts_str
Definition: setts_bsf.c:71
SetTSContext::dts_str
char * dts_str
Definition: setts_bsf.c:72
VAR_PTS
@ VAR_PTS
Definition: setts_bsf.c:58
llrint
#define llrint(x)
Definition: libm.h:394
SetTSContext::prev_inpts
int64_t prev_inpts
Definition: setts_bsf.c:78
AVPacket
This structure stores compressed data.
Definition: packet.h:346
AVPacket::pos
int64_t pos
byte position in stream, -1 if unknown
Definition: packet.h:389
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
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:253
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
AVFormatContext::priv_data
void * priv_data
Format private data.
Definition: avformat.h:1260