[FFmpeg-devel] [PATCH] avfilter/vf_subtitles: add shift option

2020-07-04 Thread Manolis Stamatogiannakis
Allows shifting of subtitle display times to align them with the video.
This avoids having to rewrite the subtitle file in order to display
subtitles correctly when input is seeked (-ss).
Also handy for minor subtitle timing corrections without rewriting the
subtitles file.

Signed-off-by: Manolis Stamatogiannakis 
---
 doc/filters.texi   |  8 
 libavfilter/vf_subtitles.c | 23 +--
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index ad2448acb2..c962ac55b0 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -17935,6 +17935,9 @@ The filter accepts the following options:
 @item filename, f
 Set the filename of the subtitle file to read. It must be specified.
 
+@item shift
+Shift subtitles timings by the specified amount.
+
 @item original_size
 Specify the size of the original video, the video for which the ASS file
 was composed. For the syntax of this option, check the
@@ -17991,6 +17994,11 @@ To make the subtitles stream from @file{sub.srt} 
appear in 80% transparent blue
 subtitles=sub.srt:force_style='Fontname=DejaVu Serif,PrimaryColour='
 @end example
 
+To re-sync subtitles after seeking the input e.g. with @code{-ss 20:20}, use:
+@example
+subtitles=filename=sub.srt:shift='-20\:20'
+@end example
+
 @section super2xsai
 
 Scale the input by 2x and smooth using the Super2xSaI (Scale and
diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c
index 1bd42391e0..125fbd9ac7 100644
--- a/libavfilter/vf_subtitles.c
+++ b/libavfilter/vf_subtitles.c
@@ -52,6 +52,7 @@ typedef struct AssContext {
 char *filename;
 char *fontsdir;
 char *charenc;
+int64_t shift;
 char *force_style;
 int stream_index;
 int alpha;
@@ -103,6 +104,11 @@ static av_cold int init(AVFilterContext *ctx)
 return AVERROR(EINVAL);
 }
 
+if (ass->shift != 0) {
+ass->shift = av_rescale_q(ass->shift, AV_TIME_BASE_Q, av_make_q(1, 
1000));
+av_log(ctx, AV_LOG_DEBUG, "Shifting subtitles by %0.3fsec.\n", 
ass->shift/1000.0);
+}
+
 ass->library = ass_library_init();
 if (!ass->library) {
 av_log(ctx, AV_LOG_ERROR, "Could not initialize libass.\n");
@@ -267,6 +273,7 @@ static const AVOption subtitles_options[] = {
 {"stream_index", "set stream index", OFFSET(stream_index), 
AV_OPT_TYPE_INT,{ .i64 = -1 }, -1,   INT_MAX,  FLAGS},
 {"si",   "set stream index", OFFSET(stream_index), 
AV_OPT_TYPE_INT,{ .i64 = -1 }, -1,   INT_MAX,  FLAGS},
 {"force_style",  "force subtitle style", OFFSET(force_style),  
AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS},
+{"shift","shift subtitles timing",   OFFSET(shift),
AV_OPT_TYPE_DURATION, {.i64 = 0},  INT64_MIN, INT64_MAX, FLAGS },
 {NULL},
 };
 
@@ -297,7 +304,7 @@ AVFILTER_DEFINE_CLASS(subtitles);
 
 static av_cold int init_subtitles(AVFilterContext *ctx)
 {
-int j, ret, sid;
+int j, ret, sid, nskip;
 int k = 0;
 AVDictionary *codec_opts = NULL;
 AVFormatContext *fmt = NULL;
@@ -448,6 +455,7 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
 av_init_packet();
 pkt.data = NULL;
 pkt.size = 0;
+nskip = 0;
 while (av_read_frame(fmt, ) >= 0) {
 int i, got_subtitle;
 AVSubtitle sub = {0};
@@ -458,8 +466,17 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
 av_log(ctx, AV_LOG_WARNING, "Error decoding: %s (ignored)\n",
av_err2str(ret));
 } else if (got_subtitle) {
-const int64_t start_time = av_rescale_q(sub.pts, 
AV_TIME_BASE_Q, av_make_q(1, 1000));
+const int64_t start_time = av_rescale_q(sub.pts, 
AV_TIME_BASE_Q, av_make_q(1, 1000)) + ass->shift;
 const int64_t duration   = sub.end_display_time;
+
+if (start_time + duration < 0) {
+nskip++;
+goto pkt_end;
+} else if (nskip > 0) {
+av_log(ctx, AV_LOG_INFO, "Skipped %d subtitles out of time 
range.\n", nskip);
+nskip = 0;
+}
+
 for (i = 0; i < sub.num_rects; i++) {
 char *ass_line = sub.rects[i]->ass;
 if (!ass_line)
@@ -472,6 +489,8 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
 }
 }
 }
+
+pkt_end:
 av_packet_unref();
 avsubtitle_free();
 }
-- 
2.17.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Re: [FFmpeg-devel] [PATCH] avfilter/vf_subtitles: add shift option

2020-05-18 Thread lance . lmwang
On Mon, May 18, 2020 at 11:34:03AM +0200, Manolis Stamatogiannakis wrote:
> Bumping this up after 10 days without a comment.
> 
> On Fri, 8 May 2020 at 13:14, Manolis Stamatogiannakis 
> wrote:
> 
> > Allows shifting of subtitle display times to align them with the video.
> > This avoids having to rewrite the subtitle file in order to display
> > subtitles correctly when input is seeked (-ss).
> > Also handy for minor subtitle timing corrections without rewriting the
> > subtitles file.
> >
> > Signed-off-by: Manolis Stamatogiannakis 
> > ---
> >  doc/filters.texi   |  8 
> >  libavfilter/vf_subtitles.c | 29 +++--
> >  2 files changed, 35 insertions(+), 2 deletions(-)
> >
> > diff --git a/doc/filters.texi b/doc/filters.texi
> > index d19fd346ae..94323495f0 100644
> > --- a/doc/filters.texi
> > +++ b/doc/filters.texi
> > @@ -17851,6 +17851,9 @@ The filter accepts the following options:
> >  @item filename, f
> >  Set the filename of the subtitle file to read. It must be specified.
> >
> > +@item shift
> > +Shift subtitles timings by the specified amount.
> > +
> >  @item original_size
> >  Specify the size of the original video, the video for which the ASS file
> >  was composed. For the syntax of this option, check the
> > @@ -17907,6 +17910,11 @@ To make the subtitles stream from @file{sub.srt}
> > appear in 80% transparent blue
> >  subtitles=sub.srt:force_style='FontName=DejaVu
> > Serif,PrimaryColour='
> >  @end example
> >
> > +To re-sync subtitles after seeking the input e.g. with @code{-ss 20:20},
> > use:
> > +@example
> > +subtitles=filename=sub.srt:shift=-20\:20
> > +@end example
> > +
> >  @section super2xsai
> >
> >  Scale the input by 2x and smooth using the Super2xSaI (Scale and
> > diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c
> > index a3b4029af4..47a38b55b1 100644
> > --- a/libavfilter/vf_subtitles.c
> > +++ b/libavfilter/vf_subtitles.c
> > @@ -52,6 +52,8 @@ typedef struct AssContext {
> >  char *filename;
> >  char *fontsdir;
> >  char *charenc;
> > +int64_t shift;
> > +char *shift_opt;
> >  char *force_style;
> >  int stream_index;
> >  int alpha;
> > @@ -68,6 +70,7 @@ typedef struct AssContext {
> >  #define COMMON_OPTIONS \
> >  {"filename",   "set the filename of file to read",
> >  OFFSET(filename),   AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,
> > FLAGS }, \
> >  {"f",  "set the filename of file to read",
> >  OFFSET(filename),   AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,
> > FLAGS }, \
> > +{"shift",  "shift the timing of the subtitles",
> >   OFFSET(shift_opt),  AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,
> > FLAGS }, \

I can't give comments for the function, but here It's better to use 
AV_OPT_TYPE_DURATION type
for the timing shift, then you can use shift directly and shift_opt isn't 
necessary anymore.


> >  {"original_size",  "set the size of the original video (used to scale
> > fonts)", OFFSET(original_w), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL},  0, 0,
> > FLAGS }, \
> >  {"fontsdir",   "set the directory containing the fonts to read",
> >  OFFSET(fontsdir),   AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,
> > FLAGS }, \
> >  {"alpha",  "enable processing of alpha channel",
> >  OFFSET(alpha),  AV_OPT_TYPE_BOOL,   {.i64 = 0   },
> >  0,1, FLAGS }, \
> > @@ -103,6 +106,16 @@ static av_cold int init(AVFilterContext *ctx)
> >  return AVERROR(EINVAL);
> >  }
> >
> > +if (ass->shift_opt) {
> > +if (av_parse_time(>shift, ass->shift_opt, 1) < 0) {
> > +av_log(ctx, AV_LOG_ERROR, "Invalid subtitles shift: %s\n",
> > +   ass->shift_opt);
> > +return AVERROR(EINVAL);
> > +}
> > +ass->shift = av_rescale_q(ass->shift, AV_TIME_BASE_Q,
> > av_make_q(1, 1000));
> > +av_log(ctx, AV_LOG_DEBUG, "Shifting subtitles by %0.3fsec.\n",
> > ass->shift/1000.0);
> > +}
> > +
> >  ass->library = ass_library_init();
> >  if (!ass->library) {
> >  av_log(ctx, AV_LOG_ERROR, "Could not initialize libass.\n");
> > @@ -297,7 +310,7 @@ AVFILTER_DEFINE_CLASS(subtitles);
> >
> >  static av_cold int init_subtitles(AVFilterContext *ctx)
> >  {
> > -int j, ret, sid;
> > +int j, ret, sid, nskip;
> >  int k = 0;
> >  AVDictionary *codec_opts = NULL;
> >  AVFormatContext *fmt = NULL;
> > @@ -448,6 +461,7 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
> >  av_init_packet();
> >  pkt.data = NULL;
> >  pkt.size = 0;
> > +nskip = 0;
> >  while (av_read_frame(fmt, ) >= 0) {
> >  int i, got_subtitle;
> >  AVSubtitle sub = {0};
> > @@ -458,8 +472,17 @@ static av_cold int init_subtitles(AVFilterContext
> > *ctx)
> >  av_log(ctx, AV_LOG_WARNING, "Error decoding: %s
> > (ignored)\n",
> > 

Re: [FFmpeg-devel] [PATCH] avfilter/vf_subtitles: add shift option

2020-05-18 Thread Manolis Stamatogiannakis
Bumping this up after 10 days without a comment.

On Fri, 8 May 2020 at 13:14, Manolis Stamatogiannakis 
wrote:

> Allows shifting of subtitle display times to align them with the video.
> This avoids having to rewrite the subtitle file in order to display
> subtitles correctly when input is seeked (-ss).
> Also handy for minor subtitle timing corrections without rewriting the
> subtitles file.
>
> Signed-off-by: Manolis Stamatogiannakis 
> ---
>  doc/filters.texi   |  8 
>  libavfilter/vf_subtitles.c | 29 +++--
>  2 files changed, 35 insertions(+), 2 deletions(-)
>
> diff --git a/doc/filters.texi b/doc/filters.texi
> index d19fd346ae..94323495f0 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -17851,6 +17851,9 @@ The filter accepts the following options:
>  @item filename, f
>  Set the filename of the subtitle file to read. It must be specified.
>
> +@item shift
> +Shift subtitles timings by the specified amount.
> +
>  @item original_size
>  Specify the size of the original video, the video for which the ASS file
>  was composed. For the syntax of this option, check the
> @@ -17907,6 +17910,11 @@ To make the subtitles stream from @file{sub.srt}
> appear in 80% transparent blue
>  subtitles=sub.srt:force_style='FontName=DejaVu
> Serif,PrimaryColour='
>  @end example
>
> +To re-sync subtitles after seeking the input e.g. with @code{-ss 20:20},
> use:
> +@example
> +subtitles=filename=sub.srt:shift=-20\:20
> +@end example
> +
>  @section super2xsai
>
>  Scale the input by 2x and smooth using the Super2xSaI (Scale and
> diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c
> index a3b4029af4..47a38b55b1 100644
> --- a/libavfilter/vf_subtitles.c
> +++ b/libavfilter/vf_subtitles.c
> @@ -52,6 +52,8 @@ typedef struct AssContext {
>  char *filename;
>  char *fontsdir;
>  char *charenc;
> +int64_t shift;
> +char *shift_opt;
>  char *force_style;
>  int stream_index;
>  int alpha;
> @@ -68,6 +70,7 @@ typedef struct AssContext {
>  #define COMMON_OPTIONS \
>  {"filename",   "set the filename of file to read",
>  OFFSET(filename),   AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,
> FLAGS }, \
>  {"f",  "set the filename of file to read",
>  OFFSET(filename),   AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,
> FLAGS }, \
> +{"shift",  "shift the timing of the subtitles",
>   OFFSET(shift_opt),  AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,
> FLAGS }, \
>  {"original_size",  "set the size of the original video (used to scale
> fonts)", OFFSET(original_w), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL},  0, 0,
> FLAGS }, \
>  {"fontsdir",   "set the directory containing the fonts to read",
>  OFFSET(fontsdir),   AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,
> FLAGS }, \
>  {"alpha",  "enable processing of alpha channel",
>  OFFSET(alpha),  AV_OPT_TYPE_BOOL,   {.i64 = 0   },
>  0,1, FLAGS }, \
> @@ -103,6 +106,16 @@ static av_cold int init(AVFilterContext *ctx)
>  return AVERROR(EINVAL);
>  }
>
> +if (ass->shift_opt) {
> +if (av_parse_time(>shift, ass->shift_opt, 1) < 0) {
> +av_log(ctx, AV_LOG_ERROR, "Invalid subtitles shift: %s\n",
> +   ass->shift_opt);
> +return AVERROR(EINVAL);
> +}
> +ass->shift = av_rescale_q(ass->shift, AV_TIME_BASE_Q,
> av_make_q(1, 1000));
> +av_log(ctx, AV_LOG_DEBUG, "Shifting subtitles by %0.3fsec.\n",
> ass->shift/1000.0);
> +}
> +
>  ass->library = ass_library_init();
>  if (!ass->library) {
>  av_log(ctx, AV_LOG_ERROR, "Could not initialize libass.\n");
> @@ -297,7 +310,7 @@ AVFILTER_DEFINE_CLASS(subtitles);
>
>  static av_cold int init_subtitles(AVFilterContext *ctx)
>  {
> -int j, ret, sid;
> +int j, ret, sid, nskip;
>  int k = 0;
>  AVDictionary *codec_opts = NULL;
>  AVFormatContext *fmt = NULL;
> @@ -448,6 +461,7 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
>  av_init_packet();
>  pkt.data = NULL;
>  pkt.size = 0;
> +nskip = 0;
>  while (av_read_frame(fmt, ) >= 0) {
>  int i, got_subtitle;
>  AVSubtitle sub = {0};
> @@ -458,8 +472,17 @@ static av_cold int init_subtitles(AVFilterContext
> *ctx)
>  av_log(ctx, AV_LOG_WARNING, "Error decoding: %s
> (ignored)\n",
> av_err2str(ret));
>  } else if (got_subtitle) {
> -const int64_t start_time = av_rescale_q(sub.pts,
> AV_TIME_BASE_Q, av_make_q(1, 1000));
> +const int64_t start_time = av_rescale_q(sub.pts,
> AV_TIME_BASE_Q, av_make_q(1, 1000)) + ass->shift;
>  const int64_t duration   = sub.end_display_time;
> +
> +if (start_time + duration < 0) {
> +nskip++;
> +goto pkt_end;
> +} else if (nskip > 

[FFmpeg-devel] [PATCH] avfilter/vf_subtitles: add shift option

2020-05-08 Thread Manolis Stamatogiannakis
Allows shifting of subtitle display times to align them with the video.
This avoids having to rewrite the subtitle file in order to display
subtitles correctly when input is seeked (-ss).
Also handy for minor subtitle timing corrections without rewriting the
subtitles file.

Signed-off-by: Manolis Stamatogiannakis 
---
 doc/filters.texi   |  8 
 libavfilter/vf_subtitles.c | 29 +++--
 2 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index d19fd346ae..94323495f0 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -17851,6 +17851,9 @@ The filter accepts the following options:
 @item filename, f
 Set the filename of the subtitle file to read. It must be specified.
 
+@item shift
+Shift subtitles timings by the specified amount.
+
 @item original_size
 Specify the size of the original video, the video for which the ASS file
 was composed. For the syntax of this option, check the
@@ -17907,6 +17910,11 @@ To make the subtitles stream from @file{sub.srt} 
appear in 80% transparent blue
 subtitles=sub.srt:force_style='FontName=DejaVu Serif,PrimaryColour='
 @end example
 
+To re-sync subtitles after seeking the input e.g. with @code{-ss 20:20}, use:
+@example
+subtitles=filename=sub.srt:shift=-20\:20
+@end example
+
 @section super2xsai
 
 Scale the input by 2x and smooth using the Super2xSaI (Scale and
diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c
index a3b4029af4..47a38b55b1 100644
--- a/libavfilter/vf_subtitles.c
+++ b/libavfilter/vf_subtitles.c
@@ -52,6 +52,8 @@ typedef struct AssContext {
 char *filename;
 char *fontsdir;
 char *charenc;
+int64_t shift;
+char *shift_opt;
 char *force_style;
 int stream_index;
 int alpha;
@@ -68,6 +70,7 @@ typedef struct AssContext {
 #define COMMON_OPTIONS \
 {"filename",   "set the filename of file to read", 
OFFSET(filename),   AV_OPT_TYPE_STRING, {.str = NULL},  0, 0, FLAGS }, \
 {"f",  "set the filename of file to read", 
OFFSET(filename),   AV_OPT_TYPE_STRING, {.str = NULL},  0, 0, FLAGS }, \
+{"shift",  "shift the timing of the subtitles",
OFFSET(shift_opt),  AV_OPT_TYPE_STRING, {.str = NULL},  0, 0, FLAGS }, \
 {"original_size",  "set the size of the original video (used to scale 
fonts)", OFFSET(original_w), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL},  0, 0, 
FLAGS }, \
 {"fontsdir",   "set the directory containing the fonts to read",   
OFFSET(fontsdir),   AV_OPT_TYPE_STRING, {.str = NULL},  0, 0, FLAGS }, \
 {"alpha",  "enable processing of alpha channel",   
OFFSET(alpha),  AV_OPT_TYPE_BOOL,   {.i64 = 0   }, 0,   
 1, FLAGS }, \
@@ -103,6 +106,16 @@ static av_cold int init(AVFilterContext *ctx)
 return AVERROR(EINVAL);
 }
 
+if (ass->shift_opt) {
+if (av_parse_time(>shift, ass->shift_opt, 1) < 0) {
+av_log(ctx, AV_LOG_ERROR, "Invalid subtitles shift: %s\n",
+   ass->shift_opt);
+return AVERROR(EINVAL);
+}
+ass->shift = av_rescale_q(ass->shift, AV_TIME_BASE_Q, av_make_q(1, 
1000));
+av_log(ctx, AV_LOG_DEBUG, "Shifting subtitles by %0.3fsec.\n", 
ass->shift/1000.0);
+}
+
 ass->library = ass_library_init();
 if (!ass->library) {
 av_log(ctx, AV_LOG_ERROR, "Could not initialize libass.\n");
@@ -297,7 +310,7 @@ AVFILTER_DEFINE_CLASS(subtitles);
 
 static av_cold int init_subtitles(AVFilterContext *ctx)
 {
-int j, ret, sid;
+int j, ret, sid, nskip;
 int k = 0;
 AVDictionary *codec_opts = NULL;
 AVFormatContext *fmt = NULL;
@@ -448,6 +461,7 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
 av_init_packet();
 pkt.data = NULL;
 pkt.size = 0;
+nskip = 0;
 while (av_read_frame(fmt, ) >= 0) {
 int i, got_subtitle;
 AVSubtitle sub = {0};
@@ -458,8 +472,17 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
 av_log(ctx, AV_LOG_WARNING, "Error decoding: %s (ignored)\n",
av_err2str(ret));
 } else if (got_subtitle) {
-const int64_t start_time = av_rescale_q(sub.pts, 
AV_TIME_BASE_Q, av_make_q(1, 1000));
+const int64_t start_time = av_rescale_q(sub.pts, 
AV_TIME_BASE_Q, av_make_q(1, 1000)) + ass->shift;
 const int64_t duration   = sub.end_display_time;
+
+if (start_time + duration < 0) {
+nskip++;
+goto pkt_end;
+} else if (nskip > 0) {
+av_log(ctx, AV_LOG_INFO, "Skipped %d subtitles out of time 
range.\n", nskip);
+nskip = 0;
+}
+
 for (i = 0; i < sub.num_rects; i++) {
 char *ass_line = sub.rects[i]->ass;