* [FFmpeg-devel] [PATCH v2] avformat/img2dec: Option to play sequence backwards
@ 2022-02-14 8:56 Sergio Acereda
0 siblings, 0 replies; only message in thread
From: Sergio Acereda @ 2022-02-14 8:56 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Sergio Acereda
This patch should allow playing an image sequence in backwards direction, without needing to apply a reverse filter.
ffmpeg -i sequence%05d.png forward.mkv
ffmpeg -reverse 1 -i sequence%05d.png backward.mkv
Signed-off-by: Sergio Acereda <sergio.acereda@gmail.com>
---
libavformat/img2.h | 1 +
libavformat/img2dec.c | 42 +++++++++++++++++++++++++++++++-----------
2 files changed, 32 insertions(+), 11 deletions(-)
diff --git a/libavformat/img2.h b/libavformat/img2.h
index 5fd8ff77fc..3d01c00537 100644
--- a/libavformat/img2.h
+++ b/libavformat/img2.h
@@ -59,6 +59,7 @@ typedef struct VideoDemuxData {
#endif
int start_number;
int start_number_range;
+ int reverse;
int frame_size;
int ts_from_file;
int export_path_metadata; /**< enabled when set to 1. */
diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c
index 8608252d83..37efb3d618 100644
--- a/libavformat/img2dec.c
+++ b/libavformat/img2dec.c
@@ -105,10 +105,12 @@ static int is_glob(const char *path)
* @param plast_index pointer to index updated with the last number in the range
* @param path path which has to be matched by the image files in the range
* @param start_index minimum accepted value for the first index in the range
+ * @param start_index_range range for looking at the first sequence number
+ * @param reverse play backwards
* @return -1 if no image file could be found
*/
static int find_image_range(AVIOContext *pb, int *pfirst_index, int *plast_index,
- const char *path, int start_index, int start_index_range)
+ const char *path, int start_index, int start_index_range, int reverse)
{
char buf[1024];
int range, last_index, range1, first_index;
@@ -152,8 +154,13 @@ static int find_image_range(AVIOContext *pb, int *pfirst_index, int *plast_index
break;
last_index += range;
}
- *pfirst_index = first_index;
- *plast_index = last_index;
+ if (reverse) {
+ *pfirst_index = last_index;
+ *plast_index = first_index;
+ } else {
+ *pfirst_index = first_index;
+ *plast_index = last_index;
+ }
return 0;
fail:
@@ -274,7 +281,7 @@ int ff_img_read_header(AVFormatContext *s1)
}
if ((s->pattern_type == PT_GLOB_SEQUENCE && !s->use_glob) || s->pattern_type == PT_SEQUENCE) {
if (find_image_range(s1->pb, &first_index, &last_index, s->path,
- s->start_number, s->start_number_range) < 0) {
+ s->start_number, s->start_number_range, s->reverse) < 0) {
av_log(s1, AV_LOG_ERROR,
"Could find no file with path '%s' and index in the range %d-%d\n",
s->path, s->start_number, s->start_number + s->start_number_range - 1);
@@ -307,7 +314,7 @@ int ff_img_read_header(AVFormatContext *s1)
/* compute duration */
if (!s->ts_from_file) {
st->start_time = 0;
- st->duration = last_index - first_index + 1;
+ st->duration = FFABS(last_index - first_index) + 1;
}
}
@@ -402,6 +409,13 @@ static int add_filename_as_pkt_side_data(char *filename, AVPacket *pkt) {
return 0;
}
+static int out_bounds(const VideoDemuxData *s)
+{
+ if (s->reverse)
+ return s->img_number < s->img_last;
+ return s->img_number > s->img_last;
+}
+
int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt)
{
VideoDemuxData *s = s1->priv_data;
@@ -414,10 +428,10 @@ int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt)
if (!s->is_pipe) {
/* loop over input */
- if (s->loop && s->img_number > s->img_last) {
+ if (s->loop && out_bounds(s)) {
s->img_number = s->img_first;
}
- if (s->img_number > s->img_last)
+ if (out_bounds(s))
return AVERROR_EOF;
if (s->pattern_type == PT_NONE) {
av_strlcpy(filename_bytes, s->path, sizeof(filename_bytes));
@@ -554,8 +568,9 @@ int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt)
}
goto fail;
} else {
+ int step = s->reverse? -1 : 1;
s->img_count++;
- s->img_number++;
+ s->img_number += step;
s->pts++;
return 0;
}
@@ -585,6 +600,7 @@ static int img_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp
{
VideoDemuxData *s1 = s->priv_data;
AVStream *st = s->streams[0];
+ int span;
if (s1->ts_from_file) {
int index = av_index_search_timestamp(st, timestamp, flags);
@@ -594,10 +610,13 @@ static int img_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp
return 0;
}
- if (timestamp < 0 || !s1->loop && timestamp > s1->img_last - s1->img_first)
+ span = 1 + FFABS(s1->img_last - s1->img_first);
+ if (timestamp < 0 || !s1->loop && timestamp > span)
return -1;
- s1->img_number = timestamp%(s1->img_last - s1->img_first + 1) + s1->img_first;
- s1->pts = timestamp;
+ else {
+ s1->img_number = s1->img_first + timestamp % span;
+ s1->pts = timestamp;
+ }
return 0;
}
@@ -619,6 +638,7 @@ const AVOption ff_img_options[] = {
{ "none", "disable pattern matching", 0, AV_OPT_TYPE_CONST, {.i64=PT_NONE }, INT_MIN, INT_MAX, DEC, "pattern_type" },
{ "start_number", "set first number in the sequence", OFFSET(start_number), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, DEC },
{ "start_number_range", "set range for looking at the first sequence number", OFFSET(start_number_range), AV_OPT_TYPE_INT, {.i64 = 5}, 1, INT_MAX, DEC },
+ { "reverse", "reverse direction", OFFSET(reverse), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, DEC },
{ "ts_from_file", "set frame timestamp from file's one", OFFSET(ts_from_file), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 2, DEC, "ts_type" },
{ "none", "none", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 2, DEC, "ts_type" },
{ "sec", "second precision", 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 2, DEC, "ts_type" },
--
2.33.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-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-02-14 8:56 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-14 8:56 [FFmpeg-devel] [PATCH v2] avformat/img2dec: Option to play sequence backwards Sergio Acereda
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git