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 "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_OUTPTS", ///< previous output PTS
39  "PREV_OUTDTS", ///< previous output DTS
40  "PTS", ///< original PTS in the file of the frame
41  "DTS", ///< original DTS in the file of the frame
42  "STARTPTS", ///< PTS at start of movie
43  "STARTDTS", ///< DTS at start of movie
44  "TB", ///< timebase of the stream
45  "SR", ///< sample rate of the stream
46  "NOPTS", ///< The AV_NOPTS_VALUE constant
47  NULL
48 };
49 
50 enum var_name {
66 };
67 
68 typedef struct SetTSContext {
69  const AVClass *class;
70 
71  char *ts_str;
72  char *pts_str;
73  char *dts_str;
74 
75  int64_t frame_number;
76 
77  int64_t start_pts;
78  int64_t start_dts;
79  int64_t prev_inpts;
80  int64_t prev_indts;
81  int64_t prev_outpts;
82  int64_t prev_outdts;
83 
85 
89 } SetTSContext;
90 
92 {
94  int ret;
95 
96  if ((ret = av_expr_parse(&s->ts_expr, s->ts_str,
97  var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
98  av_log(ctx, AV_LOG_ERROR, "Error while parsing ts expression '%s'\n", s->ts_str);
99  return ret;
100  }
101 
102  if (s->pts_str) {
103  if ((ret = av_expr_parse(&s->pts_expr, s->pts_str,
104  var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
105  av_log(ctx, AV_LOG_ERROR, "Error while parsing pts expression '%s'\n", s->pts_str);
106  return ret;
107  }
108  }
109 
110  if (s->dts_str) {
111  if ((ret = av_expr_parse(&s->dts_expr, s->dts_str,
112  var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
113  av_log(ctx, AV_LOG_ERROR, "Error while parsing dts expression '%s'\n", s->dts_str);
114  return ret;
115  }
116  }
117 
118  s->frame_number= 0;
119  s->start_pts = AV_NOPTS_VALUE;
120  s->start_dts = AV_NOPTS_VALUE;
121  s->prev_inpts = AV_NOPTS_VALUE;
122  s->prev_indts = AV_NOPTS_VALUE;
123  s->prev_outpts = AV_NOPTS_VALUE;
124  s->prev_outdts = AV_NOPTS_VALUE;
125  s->var_values[VAR_NOPTS] = AV_NOPTS_VALUE;
126 
127  return 0;
128 }
129 
131 {
133  int64_t new_ts, new_pts, new_dts;
134  int ret;
135 
137  if (ret < 0)
138  return ret;
139 
140  if (s->start_pts == AV_NOPTS_VALUE)
141  s->start_pts = pkt->pts;
142 
143  if (s->start_dts == AV_NOPTS_VALUE)
144  s->start_dts = pkt->dts;
145 
146  s->var_values[VAR_N] = s->frame_number++;
147  s->var_values[VAR_TS] = pkt->dts;
148  s->var_values[VAR_POS] = pkt->pos;
149  s->var_values[VAR_PTS] = pkt->pts;
150  s->var_values[VAR_DTS] = pkt->dts;
151  s->var_values[VAR_PREV_INPTS] = s->prev_inpts;
152  s->var_values[VAR_PREV_INDTS] = s->prev_indts;
153  s->var_values[VAR_PREV_OUTPTS] = s->prev_outpts;
154  s->var_values[VAR_PREV_OUTDTS] = s->prev_outdts;
155  s->var_values[VAR_STARTPTS] = s->start_pts;
156  s->var_values[VAR_STARTDTS] = s->start_dts;
157  s->var_values[VAR_TB] = ctx->time_base_out.den ? av_q2d(ctx->time_base_out) : 0;
158  s->var_values[VAR_SR] = ctx->par_in->sample_rate;
159 
160  new_ts = llrint(av_expr_eval(s->ts_expr, s->var_values, NULL));
161 
162  if (s->pts_str) {
163  s->var_values[VAR_TS] = pkt->pts;
164  new_pts = llrint(av_expr_eval(s->pts_expr, s->var_values, NULL));
165  } else {
166  new_pts = new_ts;
167  }
168 
169  if (s->dts_str) {
170  s->var_values[VAR_TS] = pkt->dts;
171  new_dts = llrint(av_expr_eval(s->dts_expr, s->var_values, NULL));
172  } else {
173  new_dts = new_ts;
174  }
175 
176  s->prev_inpts = pkt->pts;
177  s->prev_indts = pkt->dts;
178  s->prev_outpts = new_pts;
179  s->prev_outdts = new_dts;
180 
181  pkt->pts = new_pts;
182  pkt->dts = new_dts;
183 
184  return ret;
185 }
186 
187 static void setts_close(AVBSFContext *bsf)
188 {
189  SetTSContext *s = bsf->priv_data;
190 
191  av_expr_free(s->ts_expr);
192  s->ts_expr = NULL;
193  av_expr_free(s->pts_expr);
194  s->pts_expr = NULL;
195  av_expr_free(s->dts_expr);
196  s->dts_expr = NULL;
197 }
198 
199 #define OFFSET(x) offsetof(SetTSContext, x)
200 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_SUBTITLE_PARAM|AV_OPT_FLAG_BSF_PARAM)
201 
202 static const AVOption options[] = {
203  { "ts", "set expression for packet PTS and DTS", OFFSET(ts_str), AV_OPT_TYPE_STRING, {.str="TS"}, 0, 0, FLAGS },
204  { "pts", "set expression for packet PTS", OFFSET(pts_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
205  { "dts", "set expression for packet DTS", OFFSET(dts_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
206  { NULL },
207 };
208 
209 static const AVClass setts_class = {
210  .class_name = "setts_bsf",
211  .item_name = av_default_item_name,
212  .option = options,
213  .version = LIBAVUTIL_VERSION_INT,
214 };
215 
217  .name = "setts",
218  .priv_data_size = sizeof(SetTSContext),
219  .priv_class = &setts_class,
220  .init = setts_init,
221  .close = setts_close,
222  .filter = setts_filter,
223 };
SetTSContext::start_pts
int64_t start_pts
Definition: setts_bsf.c:77
setts_class
static const AVClass setts_class
Definition: setts_bsf.c:209
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:216
AVBitStreamFilter::name
const char * name
Definition: bsf.h:91
FLAGS
#define FLAGS
Definition: setts_bsf.c:200
VAR_NOPTS
@ VAR_NOPTS
Definition: setts_bsf.c:64
AVOption
AVOption.
Definition: opt.h:247
SetTSContext::var_values
double var_values[VAR_VARS_NB]
Definition: setts_bsf.c:84
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
VAR_VARS_NB
@ VAR_VARS_NB
Definition: setts_bsf.c:65
AVBSFContext
The bitstream filter state.
Definition: bsf.h:47
SetTSContext::prev_indts
int64_t prev_indts
Definition: setts_bsf.c:80
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:202
VAR_DTS
@ VAR_DTS
Definition: setts_bsf.c:59
SetTSContext::ts_expr
AVExpr * ts_expr
Definition: setts_bsf.c:86
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:180
VAR_TS
@ VAR_TS
Definition: setts_bsf.c:52
SetTSContext::prev_outdts
int64_t prev_outdts
Definition: setts_bsf.c:82
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:199
var_name
var_name
Definition: noise_bsf.c:47
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:91
SetTSContext::start_dts
int64_t start_dts
Definition: setts_bsf.c:78
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:66
SetTSContext
Definition: setts_bsf.c:68
NULL
#define NULL
Definition: coverity.c:32
ts_str
static void ts_str(char buffer[60], int64_t ts, AVRational base)
Definition: seek.c:47
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:75
SetTSContext::pts_expr
AVExpr * pts_expr
Definition: setts_bsf.c:87
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:372
VAR_STARTPTS
@ VAR_STARTPTS
Definition: setts_bsf.c:60
SetTSContext::dts_expr
AVExpr * dts_expr
Definition: setts_bsf.c:88
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:366
var_names
static const char *const var_names[]
Definition: setts_bsf.c:32
AVBSFContext::priv_data
void * priv_data
Opaque filter-specific private data.
Definition: bsf.h:62
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:71
setts_close
static void setts_close(AVBSFContext *bsf)
Definition: setts_bsf.c:187
SetTSContext::prev_outpts
int64_t prev_outpts
Definition: setts_bsf.c:81
setts_filter
static int setts_filter(AVBSFContext *ctx, AVPacket *pkt)
Definition: setts_bsf.c:130
AVBitStreamFilter
Definition: bsf.h:90
SetTSContext::ts_str
char * ts_str
Definition: setts_bsf.c:71
SetTSContext::pts_str
char * pts_str
Definition: setts_bsf.c:72
SetTSContext::dts_str
char * dts_str
Definition: setts_bsf.c:73
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:79
AVPacket
This structure stores compressed data.
Definition: packet.h:350
AVPacket::pos
int64_t pos
byte position in stream, -1 if unknown
Definition: packet.h:393
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:252
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:228
AVFormatContext::priv_data
void * priv_data
Format private data.
Definition: avformat.h:1221