1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Copyright (c) 2021 Paul B Mahol 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * This file is part of FFmpeg. 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14cabdff1aSopenharmony_ci * Lesser General Public License for more details. 15cabdff1aSopenharmony_ci * 16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19cabdff1aSopenharmony_ci */ 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci/** 22cabdff1aSopenharmony_ci * @file 23cabdff1aSopenharmony_ci * Change the PTS/DTS timestamps. 24cabdff1aSopenharmony_ci */ 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci#include "libavutil/opt.h" 27cabdff1aSopenharmony_ci#include "libavutil/eval.h" 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci#include "bsf.h" 30cabdff1aSopenharmony_ci#include "bsf_internal.h" 31cabdff1aSopenharmony_ci 32cabdff1aSopenharmony_cistatic const char *const var_names[] = { 33cabdff1aSopenharmony_ci "N", ///< frame number (starting at zero) 34cabdff1aSopenharmony_ci "TS", 35cabdff1aSopenharmony_ci "POS", ///< original position in the file of the frame 36cabdff1aSopenharmony_ci "PREV_INPTS", ///< previous input PTS 37cabdff1aSopenharmony_ci "PREV_INDTS", ///< previous input DTS 38cabdff1aSopenharmony_ci "PREV_INDURATION", ///< previous input duration 39cabdff1aSopenharmony_ci "PREV_OUTPTS", ///< previous output PTS 40cabdff1aSopenharmony_ci "PREV_OUTDTS", ///< previous output DTS 41cabdff1aSopenharmony_ci "PREV_OUTDURATION", ///< previous output duration 42cabdff1aSopenharmony_ci "NEXT_PTS", ///< next input PTS 43cabdff1aSopenharmony_ci "NEXT_DTS", ///< next input DTS 44cabdff1aSopenharmony_ci "NEXT_DURATION", ///< next input duration 45cabdff1aSopenharmony_ci "PTS", ///< original PTS in the file of the frame 46cabdff1aSopenharmony_ci "DTS", ///< original DTS in the file of the frame 47cabdff1aSopenharmony_ci "DURATION", ///< original duration in the file of the frame 48cabdff1aSopenharmony_ci "STARTPTS", ///< PTS at start of movie 49cabdff1aSopenharmony_ci "STARTDTS", ///< DTS at start of movie 50cabdff1aSopenharmony_ci "TB", ///< input timebase of the stream 51cabdff1aSopenharmony_ci "TB_OUT", ///< output timebase of the stream 52cabdff1aSopenharmony_ci "SR", ///< sample rate of the stream 53cabdff1aSopenharmony_ci "NOPTS", ///< The AV_NOPTS_VALUE constant 54cabdff1aSopenharmony_ci NULL 55cabdff1aSopenharmony_ci}; 56cabdff1aSopenharmony_ci 57cabdff1aSopenharmony_cienum var_name { 58cabdff1aSopenharmony_ci VAR_N, 59cabdff1aSopenharmony_ci VAR_TS, 60cabdff1aSopenharmony_ci VAR_POS, 61cabdff1aSopenharmony_ci VAR_PREV_INPTS, 62cabdff1aSopenharmony_ci VAR_PREV_INDTS, 63cabdff1aSopenharmony_ci VAR_PREV_INDUR, 64cabdff1aSopenharmony_ci VAR_PREV_OUTPTS, 65cabdff1aSopenharmony_ci VAR_PREV_OUTDTS, 66cabdff1aSopenharmony_ci VAR_PREV_OUTDUR, 67cabdff1aSopenharmony_ci VAR_NEXT_PTS, 68cabdff1aSopenharmony_ci VAR_NEXT_DTS, 69cabdff1aSopenharmony_ci VAR_NEXT_DUR, 70cabdff1aSopenharmony_ci VAR_PTS, 71cabdff1aSopenharmony_ci VAR_DTS, 72cabdff1aSopenharmony_ci VAR_DURATION, 73cabdff1aSopenharmony_ci VAR_STARTPTS, 74cabdff1aSopenharmony_ci VAR_STARTDTS, 75cabdff1aSopenharmony_ci VAR_TB, 76cabdff1aSopenharmony_ci VAR_TB_OUT, 77cabdff1aSopenharmony_ci VAR_SR, 78cabdff1aSopenharmony_ci VAR_NOPTS, 79cabdff1aSopenharmony_ci VAR_VARS_NB 80cabdff1aSopenharmony_ci}; 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_citypedef struct SetTSContext { 83cabdff1aSopenharmony_ci const AVClass *class; 84cabdff1aSopenharmony_ci 85cabdff1aSopenharmony_ci char *ts_str; 86cabdff1aSopenharmony_ci char *pts_str; 87cabdff1aSopenharmony_ci char *dts_str; 88cabdff1aSopenharmony_ci char *duration_str; 89cabdff1aSopenharmony_ci 90cabdff1aSopenharmony_ci AVRational time_base; 91cabdff1aSopenharmony_ci 92cabdff1aSopenharmony_ci int64_t frame_number; 93cabdff1aSopenharmony_ci 94cabdff1aSopenharmony_ci double var_values[VAR_VARS_NB]; 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_ci AVExpr *ts_expr; 97cabdff1aSopenharmony_ci AVExpr *pts_expr; 98cabdff1aSopenharmony_ci AVExpr *dts_expr; 99cabdff1aSopenharmony_ci AVExpr *duration_expr; 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_ci AVPacket *prev_inpkt; 102cabdff1aSopenharmony_ci AVPacket *prev_outpkt; 103cabdff1aSopenharmony_ci AVPacket *cur_pkt; 104cabdff1aSopenharmony_ci} SetTSContext; 105cabdff1aSopenharmony_ci 106cabdff1aSopenharmony_cistatic int setts_init(AVBSFContext *ctx) 107cabdff1aSopenharmony_ci{ 108cabdff1aSopenharmony_ci SetTSContext *s = ctx->priv_data; 109cabdff1aSopenharmony_ci int ret; 110cabdff1aSopenharmony_ci 111cabdff1aSopenharmony_ci s->prev_inpkt = av_packet_alloc(); 112cabdff1aSopenharmony_ci s->prev_outpkt = av_packet_alloc(); 113cabdff1aSopenharmony_ci s->cur_pkt = av_packet_alloc(); 114cabdff1aSopenharmony_ci if (!s->prev_inpkt || !s->prev_outpkt || !s->cur_pkt) 115cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 116cabdff1aSopenharmony_ci 117cabdff1aSopenharmony_ci if ((ret = av_expr_parse(&s->ts_expr, s->ts_str, 118cabdff1aSopenharmony_ci var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) { 119cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Error while parsing ts expression '%s'\n", s->ts_str); 120cabdff1aSopenharmony_ci return ret; 121cabdff1aSopenharmony_ci } 122cabdff1aSopenharmony_ci 123cabdff1aSopenharmony_ci if ((ret = av_expr_parse(&s->duration_expr, s->duration_str, 124cabdff1aSopenharmony_ci var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) { 125cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Error while parsing duration expression '%s'\n", s->duration_str); 126cabdff1aSopenharmony_ci return ret; 127cabdff1aSopenharmony_ci } 128cabdff1aSopenharmony_ci 129cabdff1aSopenharmony_ci if (s->pts_str) { 130cabdff1aSopenharmony_ci if ((ret = av_expr_parse(&s->pts_expr, s->pts_str, 131cabdff1aSopenharmony_ci var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) { 132cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Error while parsing pts expression '%s'\n", s->pts_str); 133cabdff1aSopenharmony_ci return ret; 134cabdff1aSopenharmony_ci } 135cabdff1aSopenharmony_ci } 136cabdff1aSopenharmony_ci 137cabdff1aSopenharmony_ci if (s->dts_str) { 138cabdff1aSopenharmony_ci if ((ret = av_expr_parse(&s->dts_expr, s->dts_str, 139cabdff1aSopenharmony_ci var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) { 140cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Error while parsing dts expression '%s'\n", s->dts_str); 141cabdff1aSopenharmony_ci return ret; 142cabdff1aSopenharmony_ci } 143cabdff1aSopenharmony_ci } 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_ci if (s->time_base.num > 0 && s->time_base.den > 0) 146cabdff1aSopenharmony_ci ctx->time_base_out = s->time_base; 147cabdff1aSopenharmony_ci 148cabdff1aSopenharmony_ci s->frame_number= 0; 149cabdff1aSopenharmony_ci s->var_values[VAR_STARTPTS] = AV_NOPTS_VALUE; 150cabdff1aSopenharmony_ci s->var_values[VAR_STARTDTS] = AV_NOPTS_VALUE; 151cabdff1aSopenharmony_ci s->var_values[VAR_NOPTS] = AV_NOPTS_VALUE; 152cabdff1aSopenharmony_ci s->var_values[VAR_TB] = ctx->time_base_in.den ? av_q2d(ctx->time_base_in) : 0; 153cabdff1aSopenharmony_ci s->var_values[VAR_TB_OUT]= ctx->time_base_out.den ? av_q2d(ctx->time_base_out) : 0; 154cabdff1aSopenharmony_ci s->var_values[VAR_SR] = ctx->par_in->sample_rate; 155cabdff1aSopenharmony_ci 156cabdff1aSopenharmony_ci return 0; 157cabdff1aSopenharmony_ci} 158cabdff1aSopenharmony_ci 159cabdff1aSopenharmony_cistatic int setts_filter(AVBSFContext *ctx, AVPacket *pkt) 160cabdff1aSopenharmony_ci{ 161cabdff1aSopenharmony_ci SetTSContext *s = ctx->priv_data; 162cabdff1aSopenharmony_ci int64_t new_ts, new_pts, new_dts, new_duration; 163cabdff1aSopenharmony_ci int ret; 164cabdff1aSopenharmony_ci 165cabdff1aSopenharmony_ci ret = ff_bsf_get_packet_ref(ctx, pkt); 166cabdff1aSopenharmony_ci if (ret < 0 && (ret != AVERROR_EOF || !s->cur_pkt->data)) 167cabdff1aSopenharmony_ci return ret; 168cabdff1aSopenharmony_ci 169cabdff1aSopenharmony_ci if (!s->cur_pkt->data) { 170cabdff1aSopenharmony_ci av_packet_move_ref(s->cur_pkt, pkt); 171cabdff1aSopenharmony_ci return AVERROR(EAGAIN); 172cabdff1aSopenharmony_ci } 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci if (s->var_values[VAR_STARTPTS] == AV_NOPTS_VALUE) 175cabdff1aSopenharmony_ci s->var_values[VAR_STARTPTS] = s->cur_pkt->pts; 176cabdff1aSopenharmony_ci 177cabdff1aSopenharmony_ci if (s->var_values[VAR_STARTDTS] == AV_NOPTS_VALUE) 178cabdff1aSopenharmony_ci s->var_values[VAR_STARTDTS] = s->cur_pkt->dts; 179cabdff1aSopenharmony_ci 180cabdff1aSopenharmony_ci s->var_values[VAR_N] = s->frame_number++; 181cabdff1aSopenharmony_ci s->var_values[VAR_TS] = s->cur_pkt->dts; 182cabdff1aSopenharmony_ci s->var_values[VAR_POS] = s->cur_pkt->pos; 183cabdff1aSopenharmony_ci s->var_values[VAR_PTS] = s->cur_pkt->pts; 184cabdff1aSopenharmony_ci s->var_values[VAR_DTS] = s->cur_pkt->dts; 185cabdff1aSopenharmony_ci s->var_values[VAR_DURATION] = s->cur_pkt->duration; 186cabdff1aSopenharmony_ci s->var_values[VAR_PREV_INPTS] = s->prev_inpkt->pts; 187cabdff1aSopenharmony_ci s->var_values[VAR_PREV_INDTS] = s->prev_inpkt->dts; 188cabdff1aSopenharmony_ci s->var_values[VAR_PREV_INDUR] = s->prev_inpkt->duration; 189cabdff1aSopenharmony_ci s->var_values[VAR_PREV_OUTPTS] = s->prev_outpkt->pts; 190cabdff1aSopenharmony_ci s->var_values[VAR_PREV_OUTDTS] = s->prev_outpkt->dts; 191cabdff1aSopenharmony_ci s->var_values[VAR_PREV_OUTDUR] = s->prev_outpkt->duration; 192cabdff1aSopenharmony_ci s->var_values[VAR_NEXT_PTS] = pkt->pts; 193cabdff1aSopenharmony_ci s->var_values[VAR_NEXT_DTS] = pkt->dts; 194cabdff1aSopenharmony_ci s->var_values[VAR_NEXT_DUR] = pkt->duration; 195cabdff1aSopenharmony_ci 196cabdff1aSopenharmony_ci new_ts = llrint(av_expr_eval(s->ts_expr, s->var_values, NULL)); 197cabdff1aSopenharmony_ci new_duration = llrint(av_expr_eval(s->duration_expr, s->var_values, NULL)); 198cabdff1aSopenharmony_ci 199cabdff1aSopenharmony_ci if (s->pts_str) { 200cabdff1aSopenharmony_ci s->var_values[VAR_TS] = s->cur_pkt->pts; 201cabdff1aSopenharmony_ci new_pts = llrint(av_expr_eval(s->pts_expr, s->var_values, NULL)); 202cabdff1aSopenharmony_ci } else { 203cabdff1aSopenharmony_ci new_pts = new_ts; 204cabdff1aSopenharmony_ci } 205cabdff1aSopenharmony_ci 206cabdff1aSopenharmony_ci if (s->dts_str) { 207cabdff1aSopenharmony_ci s->var_values[VAR_TS] = s->cur_pkt->dts; 208cabdff1aSopenharmony_ci new_dts = llrint(av_expr_eval(s->dts_expr, s->var_values, NULL)); 209cabdff1aSopenharmony_ci } else { 210cabdff1aSopenharmony_ci new_dts = new_ts; 211cabdff1aSopenharmony_ci } 212cabdff1aSopenharmony_ci 213cabdff1aSopenharmony_ci av_packet_unref(s->prev_inpkt); 214cabdff1aSopenharmony_ci av_packet_unref(s->prev_outpkt); 215cabdff1aSopenharmony_ci av_packet_move_ref(s->prev_inpkt, s->cur_pkt); 216cabdff1aSopenharmony_ci av_packet_move_ref(s->cur_pkt, pkt); 217cabdff1aSopenharmony_ci 218cabdff1aSopenharmony_ci ret = av_packet_ref(pkt, s->prev_inpkt); 219cabdff1aSopenharmony_ci if (ret < 0) 220cabdff1aSopenharmony_ci return ret; 221cabdff1aSopenharmony_ci 222cabdff1aSopenharmony_ci pkt->pts = new_pts; 223cabdff1aSopenharmony_ci pkt->dts = new_dts; 224cabdff1aSopenharmony_ci pkt->duration = new_duration; 225cabdff1aSopenharmony_ci 226cabdff1aSopenharmony_ci ret = av_packet_ref(s->prev_outpkt, pkt); 227cabdff1aSopenharmony_ci if (ret < 0) 228cabdff1aSopenharmony_ci av_packet_unref(pkt); 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ci return ret; 231cabdff1aSopenharmony_ci} 232cabdff1aSopenharmony_ci 233cabdff1aSopenharmony_cistatic void setts_close(AVBSFContext *bsf) 234cabdff1aSopenharmony_ci{ 235cabdff1aSopenharmony_ci SetTSContext *s = bsf->priv_data; 236cabdff1aSopenharmony_ci 237cabdff1aSopenharmony_ci av_packet_free(&s->prev_inpkt); 238cabdff1aSopenharmony_ci av_packet_free(&s->prev_outpkt); 239cabdff1aSopenharmony_ci av_packet_free(&s->cur_pkt); 240cabdff1aSopenharmony_ci 241cabdff1aSopenharmony_ci av_expr_free(s->ts_expr); 242cabdff1aSopenharmony_ci s->ts_expr = NULL; 243cabdff1aSopenharmony_ci av_expr_free(s->pts_expr); 244cabdff1aSopenharmony_ci s->pts_expr = NULL; 245cabdff1aSopenharmony_ci av_expr_free(s->dts_expr); 246cabdff1aSopenharmony_ci s->dts_expr = NULL; 247cabdff1aSopenharmony_ci av_expr_free(s->duration_expr); 248cabdff1aSopenharmony_ci s->duration_expr = NULL; 249cabdff1aSopenharmony_ci} 250cabdff1aSopenharmony_ci 251cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(SetTSContext, x) 252cabdff1aSopenharmony_ci#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_SUBTITLE_PARAM|AV_OPT_FLAG_BSF_PARAM) 253cabdff1aSopenharmony_ci 254cabdff1aSopenharmony_cistatic const AVOption options[] = { 255cabdff1aSopenharmony_ci { "ts", "set expression for packet PTS and DTS", OFFSET(ts_str), AV_OPT_TYPE_STRING, {.str="TS"}, 0, 0, FLAGS }, 256cabdff1aSopenharmony_ci { "pts", "set expression for packet PTS", OFFSET(pts_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, 257cabdff1aSopenharmony_ci { "dts", "set expression for packet DTS", OFFSET(dts_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, 258cabdff1aSopenharmony_ci { "duration", "set expression for packet duration", OFFSET(duration_str), AV_OPT_TYPE_STRING, {.str="DURATION"}, 0, 0, FLAGS }, 259cabdff1aSopenharmony_ci { "time_base", "set output timebase", OFFSET(time_base), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS }, 260cabdff1aSopenharmony_ci { NULL }, 261cabdff1aSopenharmony_ci}; 262cabdff1aSopenharmony_ci 263cabdff1aSopenharmony_cistatic const AVClass setts_class = { 264cabdff1aSopenharmony_ci .class_name = "setts_bsf", 265cabdff1aSopenharmony_ci .item_name = av_default_item_name, 266cabdff1aSopenharmony_ci .option = options, 267cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 268cabdff1aSopenharmony_ci}; 269cabdff1aSopenharmony_ci 270cabdff1aSopenharmony_ciconst FFBitStreamFilter ff_setts_bsf = { 271cabdff1aSopenharmony_ci .p.name = "setts", 272cabdff1aSopenharmony_ci .p.priv_class = &setts_class, 273cabdff1aSopenharmony_ci .priv_data_size = sizeof(SetTSContext), 274cabdff1aSopenharmony_ci .init = setts_init, 275cabdff1aSopenharmony_ci .close = setts_close, 276cabdff1aSopenharmony_ci .filter = setts_filter, 277cabdff1aSopenharmony_ci}; 278