You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

222 lines
6.4KB

  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. * @file
  22. * Change the PTS/DTS timestamps.
  23. */
  24. #include "libavutil/opt.h"
  25. #include "libavutil/eval.h"
  26. #include "avcodec.h"
  27. #include "bsf.h"
  28. #include "bsf_internal.h"
  29. static const char *const var_names[] = {
  30. "N", ///< frame number (starting at zero)
  31. "TS",
  32. "POS", ///< original position in the file of the frame
  33. "PREV_INPTS", ///< previous input PTS
  34. "PREV_INDTS", ///< previous input DTS
  35. "PREV_OUTPTS", ///< previous output PTS
  36. "PREV_OUTDTS", ///< previous output DTS
  37. "PTS", ///< original PTS in the file of the frame
  38. "DTS", ///< original DTS in the file of the frame
  39. "STARTPTS", ///< PTS at start of movie
  40. "STARTDTS", ///< DTS at start of movie
  41. "TB", ///< timebase of the stream
  42. "SR", ///< sample rate of the stream
  43. NULL
  44. };
  45. enum var_name {
  46. VAR_N,
  47. VAR_TS,
  48. VAR_POS,
  49. VAR_PREV_INPTS,
  50. VAR_PREV_INDTS,
  51. VAR_PREV_OUTPTS,
  52. VAR_PREV_OUTDTS,
  53. VAR_PTS,
  54. VAR_DTS,
  55. VAR_STARTPTS,
  56. VAR_STARTDTS,
  57. VAR_TB,
  58. VAR_SR,
  59. VAR_VARS_NB
  60. };
  61. typedef struct SetTSContext {
  62. const AVClass *class;
  63. char *ts_str;
  64. char *pts_str;
  65. char *dts_str;
  66. int64_t frame_number;
  67. int64_t start_pts;
  68. int64_t start_dts;
  69. int64_t prev_inpts;
  70. int64_t prev_indts;
  71. int64_t prev_outpts;
  72. int64_t prev_outdts;
  73. double var_values[VAR_VARS_NB];
  74. AVExpr *ts_expr;
  75. AVExpr *pts_expr;
  76. AVExpr *dts_expr;
  77. } SetTSContext;
  78. static int setts_init(AVBSFContext *ctx)
  79. {
  80. SetTSContext *s = ctx->priv_data;
  81. int ret;
  82. if ((ret = av_expr_parse(&s->ts_expr, s->ts_str,
  83. var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
  84. av_log(ctx, AV_LOG_ERROR, "Error while parsing ts expression '%s'\n", s->ts_str);
  85. return ret;
  86. }
  87. if (s->pts_str) {
  88. if ((ret = av_expr_parse(&s->pts_expr, s->pts_str,
  89. var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
  90. av_log(ctx, AV_LOG_ERROR, "Error while parsing pts expression '%s'\n", s->pts_str);
  91. return ret;
  92. }
  93. }
  94. if (s->dts_str) {
  95. if ((ret = av_expr_parse(&s->dts_expr, s->dts_str,
  96. var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
  97. av_log(ctx, AV_LOG_ERROR, "Error while parsing dts expression '%s'\n", s->dts_str);
  98. return ret;
  99. }
  100. }
  101. s->frame_number= 0;
  102. s->start_pts = AV_NOPTS_VALUE;
  103. s->start_dts = AV_NOPTS_VALUE;
  104. s->prev_inpts = AV_NOPTS_VALUE;
  105. s->prev_indts = AV_NOPTS_VALUE;
  106. s->prev_outpts = AV_NOPTS_VALUE;
  107. s->prev_outdts = AV_NOPTS_VALUE;
  108. return 0;
  109. }
  110. static int setts_filter(AVBSFContext *ctx, AVPacket *pkt)
  111. {
  112. SetTSContext *s = ctx->priv_data;
  113. int64_t new_ts, new_pts, new_dts;
  114. int ret;
  115. ret = ff_bsf_get_packet_ref(ctx, pkt);
  116. if (ret < 0)
  117. return ret;
  118. if (s->start_pts == AV_NOPTS_VALUE)
  119. s->start_pts = pkt->pts;
  120. if (s->start_dts == AV_NOPTS_VALUE)
  121. s->start_dts = pkt->dts;
  122. s->var_values[VAR_N] = s->frame_number++;
  123. s->var_values[VAR_TS] = pkt->dts;
  124. s->var_values[VAR_POS] = pkt->pos;
  125. s->var_values[VAR_PTS] = pkt->pts;
  126. s->var_values[VAR_DTS] = pkt->dts;
  127. s->var_values[VAR_PREV_INPTS] = s->prev_inpts;
  128. s->var_values[VAR_PREV_INDTS] = s->prev_indts;
  129. s->var_values[VAR_PREV_OUTPTS] = s->prev_outpts;
  130. s->var_values[VAR_PREV_OUTDTS] = s->prev_outdts;
  131. s->var_values[VAR_STARTPTS] = s->start_pts;
  132. s->var_values[VAR_STARTDTS] = s->start_dts;
  133. s->var_values[VAR_TB] = ctx->time_base_out.den ? av_q2d(ctx->time_base_out) : 0;
  134. s->var_values[VAR_SR] = ctx->par_in->sample_rate;
  135. new_ts = llrint(av_expr_eval(s->ts_expr, s->var_values, NULL));
  136. if (s->pts_str) {
  137. s->var_values[VAR_TS] = pkt->pts;
  138. new_pts = llrint(av_expr_eval(s->pts_expr, s->var_values, NULL));
  139. } else {
  140. new_pts = new_ts;
  141. }
  142. if (s->dts_str) {
  143. s->var_values[VAR_TS] = pkt->dts;
  144. new_dts = llrint(av_expr_eval(s->dts_expr, s->var_values, NULL));
  145. } else {
  146. new_dts = new_ts;
  147. }
  148. s->var_values[VAR_PREV_INPTS] = pkt->pts;
  149. s->var_values[VAR_PREV_INDTS] = pkt->dts;
  150. s->var_values[VAR_PREV_OUTPTS] = new_pts;
  151. s->var_values[VAR_PREV_OUTDTS] = new_dts;
  152. pkt->pts = new_pts;
  153. pkt->dts = new_dts;
  154. return ret;
  155. }
  156. static void setts_close(AVBSFContext *bsf)
  157. {
  158. SetTSContext *s = bsf->priv_data;
  159. av_expr_free(s->ts_expr);
  160. s->ts_expr = NULL;
  161. av_expr_free(s->pts_expr);
  162. s->pts_expr = NULL;
  163. av_expr_free(s->dts_expr);
  164. s->dts_expr = NULL;
  165. }
  166. #define OFFSET(x) offsetof(SetTSContext, x)
  167. #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_SUBTITLE_PARAM|AV_OPT_FLAG_BSF_PARAM)
  168. static const AVOption options[] = {
  169. { "ts", "set expression for packet PTS and DTS", OFFSET(ts_str), AV_OPT_TYPE_STRING, {.str="TS"}, 0, 0, FLAGS },
  170. { "pts", "set expression for packet PTS", OFFSET(pts_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
  171. { "dts", "set expression for packet DTS", OFFSET(dts_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
  172. { NULL },
  173. };
  174. static const AVClass setts_class = {
  175. .class_name = "setts_bsf",
  176. .item_name = av_default_item_name,
  177. .option = options,
  178. .version = LIBAVUTIL_VERSION_INT,
  179. };
  180. const AVBitStreamFilter ff_setts_bsf = {
  181. .name = "setts",
  182. .priv_data_size = sizeof(SetTSContext),
  183. .priv_class = &setts_class,
  184. .init = setts_init,
  185. .close = setts_close,
  186. .filter = setts_filter,
  187. };