[PATCH 1/2] img2: added support for %t output pattern
From: Yuval Adam <yuv.adm@gmail.com> The image2 muxer now supports timestamps in output filenames. When used in an output patterm '%t' will be replaced with the frames timestamp in hours, minutes and seconds (hh:mm:ss). Signed-off-by: Yuval Adam <yuv.adm@gmail.com> --- doc/muxers.texi | 5 +++++ libavformat/avformat.h | 6 ++++-- libavformat/img2.c | 13 ++++++++----- libavformat/utils.c | 32 +++++++++++++++++++++++++------- 4 files changed, 42 insertions(+), 14 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 60a72d6..72212fe 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -109,6 +109,11 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential. +The pattern may also contain "%t", this string specifies the timestamp +of the frame in hours, minutes and seconds. Note that if two frames are written at the +same second, they will be overwritten, yielding a maximum output of 1 fps. +The "%t" and "%d" patterns may not be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write. diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 2ed6b56..a9ab0cc 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2067,7 +2067,8 @@ attribute_deprecated int find_info_tag(char *arg, int arg_size, const char *tag1 #endif /** - * Return in 'buf' the path with '%d' replaced by a number. + * Return in 'buf' the path with '%d' replaced by the frame number, + * and '%t' replaced by the frame timestamp. * * Also handles the '%0nd' format where 'n' is the total number * of digits and '%%'. @@ -2076,10 +2077,11 @@ attribute_deprecated int find_info_tag(char *arg, int arg_size, const char *tag1 * @param buf_size destination buffer size * @param path numbered sequence string * @param number frame number + * @param ts frame timestamp in seconds * @return 0 if OK, -1 on format error */ int av_get_frame_filename(char *buf, int buf_size, - const char *path, int number); + const char *path, int number, int ts); /** * Check whether filename actually is a numbered sequence generator. diff --git a/libavformat/img2.c b/libavformat/img2.c index bc35591..8012e5b 100644 --- a/libavformat/img2.c +++ b/libavformat/img2.c @@ -142,7 +142,7 @@ static int find_image_range(int *pfirst_index, int *plast_index, /* find the first image */ for(first_index = 0; first_index < 5; first_index++) { - if (av_get_frame_filename(buf, sizeof(buf), path, first_index) < 0){ + if (av_get_frame_filename(buf, sizeof(buf), path, first_index, 0) < 0){ *pfirst_index = *plast_index = 1; if (avio_check(buf, AVIO_FLAG_READ) > 0) @@ -165,7 +165,7 @@ static int find_image_range(int *pfirst_index, int *plast_index, else range1 = 2 * range; if (av_get_frame_filename(buf, sizeof(buf), path, - last_index + range1) < 0) + last_index + range1, 0) < 0) goto fail; if (avio_check(buf, AVIO_FLAG_READ) <= 0) break; @@ -310,7 +310,7 @@ static int read_packet(AVFormatContext *s1, AVPacket *pkt) if (s->img_number > s->img_last) return AVERROR_EOF; if (av_get_frame_filename(filename, sizeof(filename), - s->path, s->img_number)<0 && s->img_number > 1) + s->path, s->img_number, 0)<0 && s->img_number > 1) return AVERROR(EIO); for(i=0; i<3; i++){ if (avio_open2(&f[i], filename, AVIO_FLAG_READ, @@ -389,12 +389,15 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) VideoData *img = s->priv_data; AVIOContext *pb[3]; char filename[1024]; - AVCodecContext *codec= s->streams[ pkt->stream_index ]->codec; + AVStream *stream = s->streams[ pkt->stream_index ]; + AVCodecContext *codec = stream->codec; int i; + int ts = av_rescale_q(pkt->pts, stream->time_base, AV_TIME_BASE_Q) / AV_TIME_BASE; + if (!img->is_pipe) { if (av_get_frame_filename(filename, sizeof(filename), - img->path, img->img_number) < 0 && img->img_number>1 && !img->updatefirst) { + img->path, img->img_number, ts) < 0 && img->img_number>1 && !img->updatefirst) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s'\n", img->img_number, img->path); diff --git a/libavformat/utils.c b/libavformat/utils.c index f0df759..6db2db0 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -319,7 +319,7 @@ int av_append_packet(AVIOContext *s, AVPacket *pkt, int size) int av_filename_number_test(const char *filename) { char buf[1024]; - return filename && (av_get_frame_filename(buf, sizeof(buf), filename, 1)>=0); + return filename && (av_get_frame_filename(buf, sizeof(buf), filename, 1, 0)>=0); } AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score_ret) @@ -3774,15 +3774,16 @@ int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info) #endif int av_get_frame_filename(char *buf, int buf_size, - const char *path, int number) + const char *path, int number, int ts) { const char *p; char *q, buf1[20], c; - int nd, len, percentd_found; + int nd, len, percent_found; + int hours, mins, secs; q = buf; p = path; - percentd_found = 0; + percent_found = 0; for(;;) { c = *p++; if (c == '\0') @@ -3800,9 +3801,9 @@ int av_get_frame_filename(char *buf, int buf_size, case '%': goto addchar; case 'd': - if (percentd_found) + if (percent_found) goto fail; - percentd_found = 1; + percent_found = 1; snprintf(buf1, sizeof(buf1), "%0*d", nd, number); len = strlen(buf1); if ((q - buf + len) > buf_size - 1) @@ -3810,6 +3811,23 @@ int av_get_frame_filename(char *buf, int buf_size, memcpy(q, buf1, len); q += len; break; + case 't': + if (percent_found) + goto fail; + percent_found = 1; + secs = ts % 60; + ts /= 60; + mins = ts % 60; + ts /= 60; + hours = ts; + snprintf(buf1, sizeof(buf1), + "%02d:%02d:%02d", hours, mins, secs); + len = strlen(buf1); + if ((q - buf + len) > buf_size - 1) + goto fail; + memcpy(q, buf1, len); + q += len; + break; default: goto fail; } @@ -3819,7 +3837,7 @@ int av_get_frame_filename(char *buf, int buf_size, *q++ = c; } } - if (!percentd_found) + if (!percent_found) goto fail; *q = '\0'; return 0; -- 1.7.2.2
On 1/4/12, Yuval Adam <yuv.adm@gmail.com> wrote:
From: Yuval Adam <yuv.adm@gmail.com>
The image2 muxer now supports timestamps in output filenames. When used in an output patterm '%t' will be replaced with the frames timestamp in hours, minutes and seconds (hh:mm:ss).
A somewhat updated (but not yet cleaned up) revision: https://gist.github.com/rdp/e518616f2a702367ae5a922b56e09e04 see also https://trac.ffmpeg.org/ticket/1452
On 9/22/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 1/4/12, Yuval Adam <yuv.adm@gmail.com> wrote:
From: Yuval Adam <yuv.adm@gmail.com>
The image2 muxer now supports timestamps in output filenames. When used in an output patterm '%t' will be replaced with the frames timestamp in hours, minutes and seconds (hh:mm:ss).
A somewhat updated (but not yet cleaned up) revision:
https://gist.github.com/rdp/e518616f2a702367ae5a922b56e09e04
see also https://trac.ffmpeg.org/ticket/1452
OK attached is the "cleaned up" patch, ready for review/commit. how to test: (apply then) run this: ./ffmpeg -i input -copyts -vsync vfr temp/abc-%d-%t.jpeg and compare filenames with the timestamps from video packets of ffprobe -show_packets. Probably a better way would have been to mix it into av_bprint_strftime however I wasn't sure how to use that within libavformat/utils.c av_get_frame_filename2 Adam's initial patch (https://github.com/yuvadm/FFmpeg/commit/0eb002821a2076cb3593c823399aeef9fdd2...) also deprecated av_get_frame_filename but I wasn't sure if we wanted that here or not so didn't include it. Thank you for your consideration. -roger-
On 10/10/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 9/22/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 1/4/12, Yuval Adam <yuv.adm@gmail.com> wrote:
From: Yuval Adam <yuv.adm@gmail.com>
The image2 muxer now supports timestamps in output filenames. When used in an output patterm '%t' will be replaced with the frames timestamp in hours, minutes and seconds (hh:mm:ss).
A somewhat updated (but not yet cleaned up) revision:
https://gist.github.com/rdp/e518616f2a702367ae5a922b56e09e04
see also https://trac.ffmpeg.org/ticket/1452
OK attached is the "cleaned up" patch, ready for review/commit.
how to test: (apply then) run this:
./ffmpeg -i input -copyts -vsync vfr temp/abc-%d-%t.jpeg and compare filenames with the timestamps from video packets of ffprobe -show_packets.
Probably a better way would have been to mix it into av_bprint_strftime however I wasn't sure how to use that within libavformat/utils.c av_get_frame_filename2
Adam's initial patch (https://github.com/yuvadm/FFmpeg/commit/0eb002821a2076cb3593c823399aeef9fdd2...) also deprecated av_get_frame_filename
but I wasn't sure if we wanted that here or not so didn't include it. Thank you for your consideration.
bump (this last one is cleaned up enough to be considered for merge please...). -roger-
On Mon, Oct 10, 2016 at 02:56:24PM -0600, Roger Pack wrote:
On 9/22/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 1/4/12, Yuval Adam <yuv.adm@gmail.com> wrote:
From: Yuval Adam <yuv.adm@gmail.com>
The image2 muxer now supports timestamps in output filenames. When used in an output patterm '%t' will be replaced with the frames timestamp in hours, minutes and seconds (hh:mm:ss).
A somewhat updated (but not yet cleaned up) revision:
https://gist.github.com/rdp/e518616f2a702367ae5a922b56e09e04
see also https://trac.ffmpeg.org/ticket/1452
OK attached is the "cleaned up" patch, ready for review/commit.
how to test: (apply then) run this:
./ffmpeg -i input -copyts -vsync vfr temp/abc-%d-%t.jpeg and compare filenames with the timestamps from video packets of ffprobe -show_packets.
Probably a better way would have been to mix it into av_bprint_strftime however I wasn't sure how to use that within libavformat/utils.c av_get_frame_filename2
Adam's initial patch (https://github.com/yuvadm/FFmpeg/commit/0eb002821a2076cb3593c823399aeef9fdd2...) also deprecated av_get_frame_filename
but I wasn't sure if we wanted that here or not so didn't include it. Thank you for your consideration. -roger-
doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 7 +++++-- libavformat/utils.c | 36 ++++++++++++++++++++++++++++++++---- 5 files changed, 58 insertions(+), 13 deletions(-) 06950fc8ba5a9163ffb838a2bff9933e69255b41 0001-img2-encoder-allow-t-in-filename-based-on-patch-from.patch From 11deddfacc595c43a4f542fffe5e90b142e39c85 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Mon, 10 Oct 2016 14:50:20 -0600 Subject: [PATCH] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 7 +++++-- libavformat/utils.c | 36 ++++++++++++++++++++++++++++++++---- 5 files changed, 58 insertions(+), 13 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index 9ec2e31..6fff966 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -635,7 +641,7 @@ The following example shows how to use @command{ffmpeg} for creating a sequence of files @file{img-001.jpeg}, @file{img-002.jpeg}, ..., taking one image every second from the input video: @example -ffmpeg -i in.avi -vsync 1 -r 1 -f image2 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 -f image2 'img-%03d.jpeg' @end example
Note that with @command{ffmpeg}, if the format is not specified with the @@ -643,12 +649,12 @@ Note that with @command{ffmpeg}, if the format is not specified with the format, the image2 muxer is automatically selected, so the previous command can be written as: @example -ffmpeg -i in.avi -vsync 1 -r 1 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 'img-%03d.jpeg' @end example
Note also that the pattern must not necessarily contain "%d" or "%0@var{N}d", for example to create a single image file -@file{img.jpeg} from the input video you can employ the command: +@file{img.jpeg} from the start of the input video you can employ the command: @example ffmpeg -i in.avi -f image2 -frames:v 1 img.jpeg @end example @@ -664,6 +670,13 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example
+The following example uses the timestamp parameter to generate one +image file per video frame from the input, and name it including its original +timestamp. +@example +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg +@end example + @subsection Options
@table @option diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 057f8c5..4eeb6f4 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2744,10 +2744,11 @@ void av_dump_format(AVFormatContext *ic, * @param path numbered sequence string * @param number frame number * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. * @return 0 if OK, -1 on format error */ int av_get_frame_filename2(char *buf, int buf_size, - const char *path, int number, int flags); + const char *path, int number, int flags, int64_t ts);
int av_get_frame_filename(char *buf, int buf_size, const char *path, int number); diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 9ca2df7..02d8d44 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -654,7 +654,7 @@ static int hls_start(AVFormatContext *s) } else if (c->max_seg_size > 0) { if (av_get_frame_filename2(oc->filename, sizeof(oc->filename), c->basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -use_localtime 1 with it\n", c->basename); return AVERROR(EINVAL); } @@ -685,14 +685,14 @@ static int hls_start(AVFormatContext *s) } } else if (av_get_frame_filename2(oc->filename, sizeof(oc->filename), c->basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -use_localtime 1 with it\n", c->basename); return AVERROR(EINVAL); } if( c->vtt_basename) { if (av_get_frame_filename2(vtt_oc->filename, sizeof(vtt_oc->filename), c->vtt_basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", c->vtt_basename); return AVERROR(EINVAL); } diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 1297b1a..e5db290 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -80,10 +80,13 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) VideoMuxData *img = s->priv_data; AVIOContext *pb[4]; char filename[1024]; - AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + AVStream *stream = s->streams[ pkt->stream_index ]; + AVCodecParameters *par = stream->codecpar;
+ AVCodecContext *codec = stream->codec;
unused
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format); int i; int nb_renames = 0; + int64_t ts = av_rescale_q(pkt->pts, stream->time_base, AV_TIME_BASE_Q);
if (!img->is_pipe) { if (img->update) { @@ -99,7 +102,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) } } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, img->img_number, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && + AV_FRAME_FILENAME_FLAGS_MULTIPLE, ts) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s' (either set updatefirst or use a pattern like %%03d within the filename pattern)\n", diff --git a/libavformat/utils.c b/libavformat/utils.c index 8a51aea..a8b0e8c 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -4377,15 +4377,17 @@ uint64_t ff_ntp_time(void) return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US; }
-int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags) +int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags, int64_t ts) { const char *p; char *q, buf1[20], c; - int nd, len, percentd_found; + int nd, len, percentd_found, percentt_found; + int hours, mins, secs, ms;
q = buf; p = path; percentd_found = 0; + percentt_found = 0; for (;;) { c = *p++; if (c == '\0')
@@ -4414,6 +4416,32 @@ int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number memcpy(q, buf1, len); q += len; break; + case 't': + if (!(flags & AV_FRAME_FILENAME_FLAGS_MULTIPLE) && percentt_found) { + av_log(NULL, AV_LOG_ERROR, "double %%t not allowed"); + goto fail; + } + if (ts == 0) { + av_log(NULL, AV_LOG_DEBUG, "%%t but no ts, using 0"); // necessary for first frame on some streams + } + percentt_found = 1; + ms = ts % AV_TIME_BASE; + ts /= AV_TIME_BASE; + secs = ts % 60; + ts /= 60; + mins = ts % 60; + ts /= 60; + hours = ts;
does this support negative ts ? i think nothig stops negative ts from reaching this [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB Dictatorship naturally arises out of democracy, and the most aggravated form of tyranny and slavery out of the most extreme liberty. -- Plato
On 10/16/16, Michael Niedermayer <michael@niedermayer.cc> wrote:
On Mon, Oct 10, 2016 at 02:56:24PM -0600, Roger Pack wrote:
On 9/22/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 1/4/12, Yuval Adam <yuv.adm@gmail.com> wrote:
From: Yuval Adam <yuv.adm@gmail.com>
The image2 muxer now supports timestamps in output filenames. When used in an output patterm '%t' will be replaced with the frames timestamp in hours, minutes and seconds (hh:mm:ss).
A somewhat updated (but not yet cleaned up) revision:
https://gist.github.com/rdp/e518616f2a702367ae5a922b56e09e04
see also https://trac.ffmpeg.org/ticket/1452
OK attached is the "cleaned up" patch, ready for review/commit.
how to test: (apply then) run this:
./ffmpeg -i input -copyts -vsync vfr temp/abc-%d-%t.jpeg and compare filenames with the timestamps from video packets of ffprobe -show_packets.
Probably a better way would have been to mix it into av_bprint_strftime however I wasn't sure how to use that within libavformat/utils.c av_get_frame_filename2
Adam's initial patch (https://github.com/yuvadm/FFmpeg/commit/0eb002821a2076cb3593c823399aeef9fdd2...) also deprecated av_get_frame_filename
but I wasn't sure if we wanted that here or not so didn't include it. Thank you for your consideration. -roger-
doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 7 +++++-- libavformat/utils.c | 36 ++++++++++++++++++++++++++++++++---- 5 files changed, 58 insertions(+), 13 deletions(-) 06950fc8ba5a9163ffb838a2bff9933e69255b41 0001-img2-encoder-allow-t-in-filename-based-on-patch-from.patch From 11deddfacc595c43a4f542fffe5e90b142e39c85 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Mon, 10 Oct 2016 14:50:20 -0600 Subject: [PATCH] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 7 +++++-- libavformat/utils.c | 36 ++++++++++++++++++++++++++++++++---- 5 files changed, 58 insertions(+), 13 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index 9ec2e31..6fff966 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -635,7 +641,7 @@ The following example shows how to use @command{ffmpeg} for creating a sequence of files @file{img-001.jpeg}, @file{img-002.jpeg}, ..., taking one image every second from the input video: @example -ffmpeg -i in.avi -vsync 1 -r 1 -f image2 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 -f image2 'img-%03d.jpeg' @end example
Note that with @command{ffmpeg}, if the format is not specified with the @@ -643,12 +649,12 @@ Note that with @command{ffmpeg}, if the format is not specified with the format, the image2 muxer is automatically selected, so the previous command can be written as: @example -ffmpeg -i in.avi -vsync 1 -r 1 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 'img-%03d.jpeg' @end example
Note also that the pattern must not necessarily contain "%d" or "%0@var{N}d", for example to create a single image file -@file{img.jpeg} from the input video you can employ the command: +@file{img.jpeg} from the start of the input video you can employ the command: @example ffmpeg -i in.avi -f image2 -frames:v 1 img.jpeg @end example @@ -664,6 +670,13 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example
+The following example uses the timestamp parameter to generate one +image file per video frame from the input, and name it including its original +timestamp. +@example +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg +@end example + @subsection Options
@table @option diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 057f8c5..4eeb6f4 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2744,10 +2744,11 @@ void av_dump_format(AVFormatContext *ic, * @param path numbered sequence string * @param number frame number * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. * @return 0 if OK, -1 on format error */ int av_get_frame_filename2(char *buf, int buf_size, - const char *path, int number, int flags); + const char *path, int number, int flags, int64_t ts);
int av_get_frame_filename(char *buf, int buf_size, const char *path, int number); diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 9ca2df7..02d8d44 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -654,7 +654,7 @@ static int hls_start(AVFormatContext *s) } else if (c->max_seg_size > 0) { if (av_get_frame_filename2(oc->filename, sizeof(oc->filename), c->basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -use_localtime 1 with it\n", c->basename); return AVERROR(EINVAL); } @@ -685,14 +685,14 @@ static int hls_start(AVFormatContext *s) } } else if (av_get_frame_filename2(oc->filename, sizeof(oc->filename), c->basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -use_localtime 1 with it\n", c->basename); return AVERROR(EINVAL); } if( c->vtt_basename) { if (av_get_frame_filename2(vtt_oc->filename, sizeof(vtt_oc->filename), c->vtt_basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", c->vtt_basename); return AVERROR(EINVAL); } diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 1297b1a..e5db290 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -80,10 +80,13 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) VideoMuxData *img = s->priv_data; AVIOContext *pb[4]; char filename[1024]; - AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + AVStream *stream = s->streams[ pkt->stream_index ]; + AVCodecParameters *par = stream->codecpar;
+ AVCodecContext *codec = stream->codec;
unused
Oops, removed it now.
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format); int i; int nb_renames = 0; + int64_t ts = av_rescale_q(pkt->pts, stream->time_base, AV_TIME_BASE_Q);
if (!img->is_pipe) { if (img->update) { @@ -99,7 +102,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) } } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, img->img_number, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && + AV_FRAME_FILENAME_FLAGS_MULTIPLE, ts) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s' (either set updatefirst or use a pattern like %%03d within the filename pattern)\n", diff --git a/libavformat/utils.c b/libavformat/utils.c index 8a51aea..a8b0e8c 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -4377,15 +4377,17 @@ uint64_t ff_ntp_time(void) return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US; }
-int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags) +int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags, int64_t ts) { const char *p; char *q, buf1[20], c; - int nd, len, percentd_found; + int nd, len, percentd_found, percentt_found; + int hours, mins, secs, ms;
q = buf; p = path; percentd_found = 0; + percentt_found = 0; for (;;) { c = *p++; if (c == '\0')
@@ -4414,6 +4416,32 @@ int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number memcpy(q, buf1, len); q += len; break; + case 't': + if (!(flags & AV_FRAME_FILENAME_FLAGS_MULTIPLE) && percentt_found) { + av_log(NULL, AV_LOG_ERROR, "double %%t not allowed"); + goto fail; + } + if (ts == 0) { + av_log(NULL, AV_LOG_DEBUG, "%%t but no ts, using 0"); // necessary for first frame on some streams + } + percentt_found = 1; + ms = ts % AV_TIME_BASE; + ts /= AV_TIME_BASE; + secs = ts % 60; + ts /= 60; + mins = ts % 60; + ts /= 60; + hours = ts;
does this support negative ts ? i think nothig stops negative ts from reaching this
turns out it did not. Please see the attached patch which does. Thank you. -roger-
On Mon, Oct 24, 2016 at 03:20:14PM -0600, Roger Pack wrote:
On 10/16/16, Michael Niedermayer <michael@niedermayer.cc> wrote:
On Mon, Oct 10, 2016 at 02:56:24PM -0600, Roger Pack wrote:
On 9/22/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 1/4/12, Yuval Adam <yuv.adm@gmail.com> wrote:
From: Yuval Adam <yuv.adm@gmail.com>
The image2 muxer now supports timestamps in output filenames. When used in an output patterm '%t' will be replaced with the frames timestamp in hours, minutes and seconds (hh:mm:ss).
A somewhat updated (but not yet cleaned up) revision:
https://gist.github.com/rdp/e518616f2a702367ae5a922b56e09e04
see also https://trac.ffmpeg.org/ticket/1452
OK attached is the "cleaned up" patch, ready for review/commit.
how to test: (apply then) run this:
./ffmpeg -i input -copyts -vsync vfr temp/abc-%d-%t.jpeg and compare filenames with the timestamps from video packets of ffprobe -show_packets.
Probably a better way would have been to mix it into av_bprint_strftime however I wasn't sure how to use that within libavformat/utils.c av_get_frame_filename2
Adam's initial patch (https://github.com/yuvadm/FFmpeg/commit/0eb002821a2076cb3593c823399aeef9fdd2...) also deprecated av_get_frame_filename
but I wasn't sure if we wanted that here or not so didn't include it. Thank you for your consideration. -roger-
doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 7 +++++-- libavformat/utils.c | 36 ++++++++++++++++++++++++++++++++---- 5 files changed, 58 insertions(+), 13 deletions(-) 06950fc8ba5a9163ffb838a2bff9933e69255b41 0001-img2-encoder-allow-t-in-filename-based-on-patch-from.patch From 11deddfacc595c43a4f542fffe5e90b142e39c85 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Mon, 10 Oct 2016 14:50:20 -0600 Subject: [PATCH] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 7 +++++-- libavformat/utils.c | 36 ++++++++++++++++++++++++++++++++---- 5 files changed, 58 insertions(+), 13 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index 9ec2e31..6fff966 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -635,7 +641,7 @@ The following example shows how to use @command{ffmpeg} for creating a sequence of files @file{img-001.jpeg}, @file{img-002.jpeg}, ..., taking one image every second from the input video: @example -ffmpeg -i in.avi -vsync 1 -r 1 -f image2 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 -f image2 'img-%03d.jpeg' @end example
Note that with @command{ffmpeg}, if the format is not specified with the @@ -643,12 +649,12 @@ Note that with @command{ffmpeg}, if the format is not specified with the format, the image2 muxer is automatically selected, so the previous command can be written as: @example -ffmpeg -i in.avi -vsync 1 -r 1 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 'img-%03d.jpeg' @end example
Note also that the pattern must not necessarily contain "%d" or "%0@var{N}d", for example to create a single image file -@file{img.jpeg} from the input video you can employ the command: +@file{img.jpeg} from the start of the input video you can employ the command: @example ffmpeg -i in.avi -f image2 -frames:v 1 img.jpeg @end example @@ -664,6 +670,13 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example
+The following example uses the timestamp parameter to generate one +image file per video frame from the input, and name it including its original +timestamp. +@example +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg +@end example + @subsection Options
@table @option diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 057f8c5..4eeb6f4 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2744,10 +2744,11 @@ void av_dump_format(AVFormatContext *ic, * @param path numbered sequence string * @param number frame number * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. * @return 0 if OK, -1 on format error */ int av_get_frame_filename2(char *buf, int buf_size, - const char *path, int number, int flags); + const char *path, int number, int flags, int64_t ts);
int av_get_frame_filename(char *buf, int buf_size, const char *path, int number); diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 9ca2df7..02d8d44 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -654,7 +654,7 @@ static int hls_start(AVFormatContext *s) } else if (c->max_seg_size > 0) { if (av_get_frame_filename2(oc->filename, sizeof(oc->filename), c->basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -use_localtime 1 with it\n", c->basename); return AVERROR(EINVAL); } @@ -685,14 +685,14 @@ static int hls_start(AVFormatContext *s) } } else if (av_get_frame_filename2(oc->filename, sizeof(oc->filename), c->basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -use_localtime 1 with it\n", c->basename); return AVERROR(EINVAL); } if( c->vtt_basename) { if (av_get_frame_filename2(vtt_oc->filename, sizeof(vtt_oc->filename), c->vtt_basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", c->vtt_basename); return AVERROR(EINVAL); } diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 1297b1a..e5db290 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -80,10 +80,13 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) VideoMuxData *img = s->priv_data; AVIOContext *pb[4]; char filename[1024]; - AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + AVStream *stream = s->streams[ pkt->stream_index ]; + AVCodecParameters *par = stream->codecpar;
+ AVCodecContext *codec = stream->codec;
unused
Oops, removed it now.
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format); int i; int nb_renames = 0; + int64_t ts = av_rescale_q(pkt->pts, stream->time_base, AV_TIME_BASE_Q);
if (!img->is_pipe) { if (img->update) { @@ -99,7 +102,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) } } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, img->img_number, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && + AV_FRAME_FILENAME_FLAGS_MULTIPLE, ts) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s' (either set updatefirst or use a pattern like %%03d within the filename pattern)\n", diff --git a/libavformat/utils.c b/libavformat/utils.c index 8a51aea..a8b0e8c 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -4377,15 +4377,17 @@ uint64_t ff_ntp_time(void) return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US; }
-int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags) +int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags, int64_t ts) { const char *p; char *q, buf1[20], c; - int nd, len, percentd_found; + int nd, len, percentd_found, percentt_found; + int hours, mins, secs, ms;
q = buf; p = path; percentd_found = 0; + percentt_found = 0; for (;;) { c = *p++; if (c == '\0')
@@ -4414,6 +4416,32 @@ int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number memcpy(q, buf1, len); q += len; break; + case 't': + if (!(flags & AV_FRAME_FILENAME_FLAGS_MULTIPLE) && percentt_found) { + av_log(NULL, AV_LOG_ERROR, "double %%t not allowed"); + goto fail; + } + if (ts == 0) { + av_log(NULL, AV_LOG_DEBUG, "%%t but no ts, using 0"); // necessary for first frame on some streams + } + percentt_found = 1; + ms = ts % AV_TIME_BASE; + ts /= AV_TIME_BASE; + secs = ts % 60; + ts /= 60; + mins = ts % 60; + ts /= 60; + hours = ts;
does this support negative ts ? i think nothig stops negative ts from reaching this
turns out it did not. Please see the attached patch which does. Thank you. -roger-
doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 63 insertions(+), 13 deletions(-) 18b06c4f7d811fe5f716d4e0917dc71d58ffbe12 0001-img2-encoder-allow-t-in-filename-based-on-patch-from.patch From 0f98c18233954d8198ab8a9382a6e58a57d88a12 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Mon, 24 Oct 2016 15:18:28 -0600 Subject: [PATCH] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 63 insertions(+), 13 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index 0d856db..ef2116a 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -635,7 +641,7 @@ The following example shows how to use @command{ffmpeg} for creating a sequence of files @file{img-001.jpeg}, @file{img-002.jpeg}, ..., taking one image every second from the input video: @example -ffmpeg -i in.avi -vsync 1 -r 1 -f image2 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 -f image2 'img-%03d.jpeg' @end example
Note that with @command{ffmpeg}, if the format is not specified with the
This looks unrelated
@@ -643,12 +649,12 @@ Note that with @command{ffmpeg}, if the format is not specified with the format, the image2 muxer is automatically selected, so the previous command can be written as: @example -ffmpeg -i in.avi -vsync 1 -r 1 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 'img-%03d.jpeg' @end example
same otherwise i didnt immdeatly see an issue but didt review this deeply [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB When you are offended at any man's fault, turn to yourself and study your own failings. Then you will forget your anger. -- Epictetus
On 10/25/16, Michael Niedermayer <michael@niedermayer.cc> wrote:
On Mon, Oct 24, 2016 at 03:20:14PM -0600, Roger Pack wrote:
On 10/16/16, Michael Niedermayer <michael@niedermayer.cc> wrote:
On Mon, Oct 10, 2016 at 02:56:24PM -0600, Roger Pack wrote:
On 9/22/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 1/4/12, Yuval Adam <yuv.adm@gmail.com> wrote:
From: Yuval Adam <yuv.adm@gmail.com>
The image2 muxer now supports timestamps in output filenames. When used in an output patterm '%t' will be replaced with the frames timestamp in hours, minutes and seconds (hh:mm:ss).
A somewhat updated (but not yet cleaned up) revision:
https://gist.github.com/rdp/e518616f2a702367ae5a922b56e09e04
see also https://trac.ffmpeg.org/ticket/1452
OK attached is the "cleaned up" patch, ready for review/commit.
how to test: (apply then) run this:
./ffmpeg -i input -copyts -vsync vfr temp/abc-%d-%t.jpeg and compare filenames with the timestamps from video packets of ffprobe -show_packets.
Probably a better way would have been to mix it into av_bprint_strftime however I wasn't sure how to use that within libavformat/utils.c av_get_frame_filename2
Adam's initial patch (https://github.com/yuvadm/FFmpeg/commit/0eb002821a2076cb3593c823399aeef9fdd2...) also deprecated av_get_frame_filename
but I wasn't sure if we wanted that here or not so didn't include it. Thank you for your consideration. -roger-
doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 7 +++++-- libavformat/utils.c | 36 ++++++++++++++++++++++++++++++++---- 5 files changed, 58 insertions(+), 13 deletions(-) 06950fc8ba5a9163ffb838a2bff9933e69255b41 0001-img2-encoder-allow-t-in-filename-based-on-patch-from.patch From 11deddfacc595c43a4f542fffe5e90b142e39c85 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Mon, 10 Oct 2016 14:50:20 -0600 Subject: [PATCH] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 7 +++++-- libavformat/utils.c | 36 ++++++++++++++++++++++++++++++++---- 5 files changed, 58 insertions(+), 13 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index 9ec2e31..6fff966 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -635,7 +641,7 @@ The following example shows how to use @command{ffmpeg} for creating a sequence of files @file{img-001.jpeg}, @file{img-002.jpeg}, ..., taking one image every second from the input video: @example -ffmpeg -i in.avi -vsync 1 -r 1 -f image2 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 -f image2 'img-%03d.jpeg' @end example
Note that with @command{ffmpeg}, if the format is not specified with the @@ -643,12 +649,12 @@ Note that with @command{ffmpeg}, if the format is not specified with the format, the image2 muxer is automatically selected, so the previous command can be written as: @example -ffmpeg -i in.avi -vsync 1 -r 1 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 'img-%03d.jpeg' @end example
Note also that the pattern must not necessarily contain "%d" or "%0@var{N}d", for example to create a single image file -@file{img.jpeg} from the input video you can employ the command: +@file{img.jpeg} from the start of the input video you can employ the command: @example ffmpeg -i in.avi -f image2 -frames:v 1 img.jpeg @end example @@ -664,6 +670,13 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example
+The following example uses the timestamp parameter to generate one +image file per video frame from the input, and name it including its original +timestamp. +@example +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg +@end example + @subsection Options
@table @option diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 057f8c5..4eeb6f4 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2744,10 +2744,11 @@ void av_dump_format(AVFormatContext *ic, * @param path numbered sequence string * @param number frame number * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. * @return 0 if OK, -1 on format error */ int av_get_frame_filename2(char *buf, int buf_size, - const char *path, int number, int flags); + const char *path, int number, int flags, int64_t ts);
int av_get_frame_filename(char *buf, int buf_size, const char *path, int number); diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 9ca2df7..02d8d44 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -654,7 +654,7 @@ static int hls_start(AVFormatContext *s) } else if (c->max_seg_size > 0) { if (av_get_frame_filename2(oc->filename, sizeof(oc->filename), c->basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -use_localtime 1 with it\n", c->basename); return AVERROR(EINVAL); } @@ -685,14 +685,14 @@ static int hls_start(AVFormatContext *s) } } else if (av_get_frame_filename2(oc->filename, sizeof(oc->filename), c->basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -use_localtime 1 with it\n", c->basename); return AVERROR(EINVAL); } if( c->vtt_basename) { if (av_get_frame_filename2(vtt_oc->filename, sizeof(vtt_oc->filename), c->vtt_basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", c->vtt_basename); return AVERROR(EINVAL); } diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 1297b1a..e5db290 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -80,10 +80,13 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) VideoMuxData *img = s->priv_data; AVIOContext *pb[4]; char filename[1024]; - AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + AVStream *stream = s->streams[ pkt->stream_index ]; + AVCodecParameters *par = stream->codecpar;
+ AVCodecContext *codec = stream->codec;
unused
Oops, removed it now.
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format); int i; int nb_renames = 0; + int64_t ts = av_rescale_q(pkt->pts, stream->time_base, AV_TIME_BASE_Q);
if (!img->is_pipe) { if (img->update) { @@ -99,7 +102,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) } } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, img->img_number, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && + AV_FRAME_FILENAME_FLAGS_MULTIPLE, ts) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s' (either set updatefirst or use a pattern like %%03d within the filename pattern)\n", diff --git a/libavformat/utils.c b/libavformat/utils.c index 8a51aea..a8b0e8c 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -4377,15 +4377,17 @@ uint64_t ff_ntp_time(void) return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US; }
-int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags) +int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags, int64_t ts) { const char *p; char *q, buf1[20], c; - int nd, len, percentd_found; + int nd, len, percentd_found, percentt_found; + int hours, mins, secs, ms;
q = buf; p = path; percentd_found = 0; + percentt_found = 0; for (;;) { c = *p++; if (c == '\0')
@@ -4414,6 +4416,32 @@ int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number memcpy(q, buf1, len); q += len; break; + case 't': + if (!(flags & AV_FRAME_FILENAME_FLAGS_MULTIPLE) && percentt_found) { + av_log(NULL, AV_LOG_ERROR, "double %%t not allowed"); + goto fail; + } + if (ts == 0) { + av_log(NULL, AV_LOG_DEBUG, "%%t but no ts, using 0"); // necessary for first frame on some streams + } + percentt_found = 1; + ms = ts % AV_TIME_BASE; + ts /= AV_TIME_BASE; + secs = ts % 60; + ts /= 60; + mins = ts % 60; + ts /= 60; + hours = ts;
does this support negative ts ? i think nothig stops negative ts from reaching this
turns out it did not. Please see the attached patch which does. Thank you. -roger-
doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 63 insertions(+), 13 deletions(-) 18b06c4f7d811fe5f716d4e0917dc71d58ffbe12 0001-img2-encoder-allow-t-in-filename-based-on-patch-from.patch From 0f98c18233954d8198ab8a9382a6e58a57d88a12 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Mon, 24 Oct 2016 15:18:28 -0600 Subject: [PATCH] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 63 insertions(+), 13 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index 0d856db..ef2116a 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -635,7 +641,7 @@ The following example shows how to use @command{ffmpeg} for creating a sequence of files @file{img-001.jpeg}, @file{img-002.jpeg}, ..., taking one image every second from the input video: @example -ffmpeg -i in.avi -vsync 1 -r 1 -f image2 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 -f image2 'img-%03d.jpeg' @end example
Note that with @command{ffmpeg}, if the format is not specified with the
This looks unrelated
OK split it into two commits. See attached. Thanks!
On Tue, Oct 25, 2016 at 06:38:12PM -0600, Roger Pack wrote:
On 10/25/16, Michael Niedermayer <michael@niedermayer.cc> wrote:
On Mon, Oct 24, 2016 at 03:20:14PM -0600, Roger Pack wrote:
On 10/16/16, Michael Niedermayer <michael@niedermayer.cc> wrote:
On Mon, Oct 10, 2016 at 02:56:24PM -0600, Roger Pack wrote:
On 9/22/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 1/4/12, Yuval Adam <yuv.adm@gmail.com> wrote: > From: Yuval Adam <yuv.adm@gmail.com> > > The image2 muxer now supports timestamps in output filenames. > When used in an output patterm '%t' will be replaced with the > frames > timestamp in hours, minutes and seconds (hh:mm:ss).
A somewhat updated (but not yet cleaned up) revision:
https://gist.github.com/rdp/e518616f2a702367ae5a922b56e09e04
see also https://trac.ffmpeg.org/ticket/1452
OK attached is the "cleaned up" patch, ready for review/commit.
how to test: (apply then) run this:
./ffmpeg -i input -copyts -vsync vfr temp/abc-%d-%t.jpeg and compare filenames with the timestamps from video packets of ffprobe -show_packets.
Probably a better way would have been to mix it into av_bprint_strftime however I wasn't sure how to use that within libavformat/utils.c av_get_frame_filename2
Adam's initial patch (https://github.com/yuvadm/FFmpeg/commit/0eb002821a2076cb3593c823399aeef9fdd2...) also deprecated av_get_frame_filename
but I wasn't sure if we wanted that here or not so didn't include it. Thank you for your consideration. -roger-
doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 7 +++++-- libavformat/utils.c | 36 ++++++++++++++++++++++++++++++++---- 5 files changed, 58 insertions(+), 13 deletions(-) 06950fc8ba5a9163ffb838a2bff9933e69255b41 0001-img2-encoder-allow-t-in-filename-based-on-patch-from.patch From 11deddfacc595c43a4f542fffe5e90b142e39c85 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Mon, 10 Oct 2016 14:50:20 -0600 Subject: [PATCH] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 7 +++++-- libavformat/utils.c | 36 ++++++++++++++++++++++++++++++++---- 5 files changed, 58 insertions(+), 13 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index 9ec2e31..6fff966 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -635,7 +641,7 @@ The following example shows how to use @command{ffmpeg} for creating a sequence of files @file{img-001.jpeg}, @file{img-002.jpeg}, ..., taking one image every second from the input video: @example -ffmpeg -i in.avi -vsync 1 -r 1 -f image2 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 -f image2 'img-%03d.jpeg' @end example
Note that with @command{ffmpeg}, if the format is not specified with the @@ -643,12 +649,12 @@ Note that with @command{ffmpeg}, if the format is not specified with the format, the image2 muxer is automatically selected, so the previous command can be written as: @example -ffmpeg -i in.avi -vsync 1 -r 1 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 'img-%03d.jpeg' @end example
Note also that the pattern must not necessarily contain "%d" or "%0@var{N}d", for example to create a single image file -@file{img.jpeg} from the input video you can employ the command: +@file{img.jpeg} from the start of the input video you can employ the command: @example ffmpeg -i in.avi -f image2 -frames:v 1 img.jpeg @end example @@ -664,6 +670,13 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example
+The following example uses the timestamp parameter to generate one +image file per video frame from the input, and name it including its original +timestamp. +@example +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg +@end example + @subsection Options
@table @option diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 057f8c5..4eeb6f4 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2744,10 +2744,11 @@ void av_dump_format(AVFormatContext *ic, * @param path numbered sequence string * @param number frame number * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. * @return 0 if OK, -1 on format error */ int av_get_frame_filename2(char *buf, int buf_size, - const char *path, int number, int flags); + const char *path, int number, int flags, int64_t ts);
int av_get_frame_filename(char *buf, int buf_size, const char *path, int number); diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 9ca2df7..02d8d44 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -654,7 +654,7 @@ static int hls_start(AVFormatContext *s) } else if (c->max_seg_size > 0) { if (av_get_frame_filename2(oc->filename, sizeof(oc->filename), c->basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -use_localtime 1 with it\n", c->basename); return AVERROR(EINVAL); } @@ -685,14 +685,14 @@ static int hls_start(AVFormatContext *s) } } else if (av_get_frame_filename2(oc->filename, sizeof(oc->filename), c->basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -use_localtime 1 with it\n", c->basename); return AVERROR(EINVAL); } if( c->vtt_basename) { if (av_get_frame_filename2(vtt_oc->filename, sizeof(vtt_oc->filename), c->vtt_basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", c->vtt_basename); return AVERROR(EINVAL); } diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 1297b1a..e5db290 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -80,10 +80,13 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) VideoMuxData *img = s->priv_data; AVIOContext *pb[4]; char filename[1024]; - AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + AVStream *stream = s->streams[ pkt->stream_index ]; + AVCodecParameters *par = stream->codecpar;
+ AVCodecContext *codec = stream->codec;
unused
Oops, removed it now.
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format); int i; int nb_renames = 0; + int64_t ts = av_rescale_q(pkt->pts, stream->time_base, AV_TIME_BASE_Q);
if (!img->is_pipe) { if (img->update) { @@ -99,7 +102,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) } } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, img->img_number, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && + AV_FRAME_FILENAME_FLAGS_MULTIPLE, ts) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s' (either set updatefirst or use a pattern like %%03d within the filename pattern)\n", diff --git a/libavformat/utils.c b/libavformat/utils.c index 8a51aea..a8b0e8c 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -4377,15 +4377,17 @@ uint64_t ff_ntp_time(void) return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US; }
-int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags) +int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags, int64_t ts) { const char *p; char *q, buf1[20], c; - int nd, len, percentd_found; + int nd, len, percentd_found, percentt_found; + int hours, mins, secs, ms;
q = buf; p = path; percentd_found = 0; + percentt_found = 0; for (;;) { c = *p++; if (c == '\0')
@@ -4414,6 +4416,32 @@ int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number memcpy(q, buf1, len); q += len; break; + case 't': + if (!(flags & AV_FRAME_FILENAME_FLAGS_MULTIPLE) && percentt_found) { + av_log(NULL, AV_LOG_ERROR, "double %%t not allowed"); + goto fail; + } + if (ts == 0) { + av_log(NULL, AV_LOG_DEBUG, "%%t but no ts, using 0"); // necessary for first frame on some streams + } + percentt_found = 1; + ms = ts % AV_TIME_BASE; + ts /= AV_TIME_BASE; + secs = ts % 60; + ts /= 60; + mins = ts % 60; + ts /= 60; + hours = ts;
does this support negative ts ? i think nothig stops negative ts from reaching this
turns out it did not. Please see the attached patch which does. Thank you. -roger-
doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 63 insertions(+), 13 deletions(-) 18b06c4f7d811fe5f716d4e0917dc71d58ffbe12 0001-img2-encoder-allow-t-in-filename-based-on-patch-from.patch From 0f98c18233954d8198ab8a9382a6e58a57d88a12 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Mon, 24 Oct 2016 15:18:28 -0600 Subject: [PATCH] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 63 insertions(+), 13 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index 0d856db..ef2116a 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -635,7 +641,7 @@ The following example shows how to use @command{ffmpeg} for creating a sequence of files @file{img-001.jpeg}, @file{img-002.jpeg}, ..., taking one image every second from the input video: @example -ffmpeg -i in.avi -vsync 1 -r 1 -f image2 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 -f image2 'img-%03d.jpeg' @end example
Note that with @command{ffmpeg}, if the format is not specified with the
This looks unrelated
OK split it into two commits.
See attached. Thanks!
doc/muxers.texi | 13 +++++++++++++ libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 60 insertions(+), 10 deletions(-) 9503d1b6ebc586b796ce6f51011eb705fcf23f5b 0001-img2-encoder-allow-t-in-filename-based-on-patch-from.patch From e8cac5c7de18766ce0f8f286f7dc140b82129df2 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Tue, 25 Oct 2016 18:33:12 -0600 Subject: [PATCH 1/2] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Acked-by: Michael [...]
muxers.texi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 331cfe5f69530b091202d09e78cd68848079c2ec 0002-img2-encoder-use-more-descriptive-vsync-names.patch From d83554983bde469adb09674c174258b189e242aa Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Tue, 25 Oct 2016 18:33:30 -0600 Subject: [PATCH 2/2] img2 encoder: use more descriptive vsync names
LGTM [...] thx -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB In fact, the RIAA has been known to suggest that students drop out of college or go to community college in order to be able to afford settlements. -- The RIAA
On 10/26/16, Michael Niedermayer <michael@niedermayer.cc> wrote:
On Tue, Oct 25, 2016 at 06:38:12PM -0600, Roger Pack wrote:
On 10/25/16, Michael Niedermayer <michael@niedermayer.cc> wrote:
On Mon, Oct 24, 2016 at 03:20:14PM -0600, Roger Pack wrote:
On 10/16/16, Michael Niedermayer <michael@niedermayer.cc> wrote:
On Mon, Oct 10, 2016 at 02:56:24PM -0600, Roger Pack wrote:
On 9/22/16, Roger Pack <rogerdpack2@gmail.com> wrote: > On 1/4/12, Yuval Adam <yuv.adm@gmail.com> wrote: >> From: Yuval Adam <yuv.adm@gmail.com> >> >> The image2 muxer now supports timestamps in output filenames. >> When used in an output patterm '%t' will be replaced with the >> frames >> timestamp in hours, minutes and seconds (hh:mm:ss). > > A somewhat updated (but not yet cleaned up) revision: > > https://gist.github.com/rdp/e518616f2a702367ae5a922b56e09e04 > > see also https://trac.ffmpeg.org/ticket/1452
OK attached is the "cleaned up" patch, ready for review/commit.
how to test: (apply then) run this:
./ffmpeg -i input -copyts -vsync vfr temp/abc-%d-%t.jpeg and compare filenames with the timestamps from video packets of ffprobe -show_packets.
Probably a better way would have been to mix it into av_bprint_strftime however I wasn't sure how to use that within libavformat/utils.c av_get_frame_filename2
Adam's initial patch (https://github.com/yuvadm/FFmpeg/commit/0eb002821a2076cb3593c823399aeef9fdd2...) also deprecated av_get_frame_filename
but I wasn't sure if we wanted that here or not so didn't include it. Thank you for your consideration. -roger-
doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 7 +++++-- libavformat/utils.c | 36 ++++++++++++++++++++++++++++++++---- 5 files changed, 58 insertions(+), 13 deletions(-) 06950fc8ba5a9163ffb838a2bff9933e69255b41 0001-img2-encoder-allow-t-in-filename-based-on-patch-from.patch From 11deddfacc595c43a4f542fffe5e90b142e39c85 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Mon, 10 Oct 2016 14:50:20 -0600 Subject: [PATCH] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 7 +++++-- libavformat/utils.c | 36 ++++++++++++++++++++++++++++++++---- 5 files changed, 58 insertions(+), 13 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index 9ec2e31..6fff966 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -635,7 +641,7 @@ The following example shows how to use @command{ffmpeg} for creating a sequence of files @file{img-001.jpeg}, @file{img-002.jpeg}, ..., taking one image every second from the input video: @example -ffmpeg -i in.avi -vsync 1 -r 1 -f image2 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 -f image2 'img-%03d.jpeg' @end example
Note that with @command{ffmpeg}, if the format is not specified with the @@ -643,12 +649,12 @@ Note that with @command{ffmpeg}, if the format is not specified with the format, the image2 muxer is automatically selected, so the previous command can be written as: @example -ffmpeg -i in.avi -vsync 1 -r 1 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 'img-%03d.jpeg' @end example
Note also that the pattern must not necessarily contain "%d" or "%0@var{N}d", for example to create a single image file -@file{img.jpeg} from the input video you can employ the command: +@file{img.jpeg} from the start of the input video you can employ the command: @example ffmpeg -i in.avi -f image2 -frames:v 1 img.jpeg @end example @@ -664,6 +670,13 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example
+The following example uses the timestamp parameter to generate one +image file per video frame from the input, and name it including its original +timestamp. +@example +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg +@end example + @subsection Options
@table @option diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 057f8c5..4eeb6f4 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2744,10 +2744,11 @@ void av_dump_format(AVFormatContext *ic, * @param path numbered sequence string * @param number frame number * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. * @return 0 if OK, -1 on format error */ int av_get_frame_filename2(char *buf, int buf_size, - const char *path, int number, int flags); + const char *path, int number, int flags, int64_t ts);
int av_get_frame_filename(char *buf, int buf_size, const char *path, int number); diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 9ca2df7..02d8d44 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -654,7 +654,7 @@ static int hls_start(AVFormatContext *s) } else if (c->max_seg_size > 0) { if (av_get_frame_filename2(oc->filename, sizeof(oc->filename), c->basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -use_localtime 1 with it\n", c->basename); return AVERROR(EINVAL); } @@ -685,14 +685,14 @@ static int hls_start(AVFormatContext *s) } } else if (av_get_frame_filename2(oc->filename, sizeof(oc->filename), c->basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -use_localtime 1 with it\n", c->basename); return AVERROR(EINVAL); } if( c->vtt_basename) { if (av_get_frame_filename2(vtt_oc->filename, sizeof(vtt_oc->filename), c->vtt_basename, c->wrap ? c->sequence % c->wrap : c->sequence, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", c->vtt_basename); return AVERROR(EINVAL); } diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 1297b1a..e5db290 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -80,10 +80,13 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) VideoMuxData *img = s->priv_data; AVIOContext *pb[4]; char filename[1024]; - AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + AVStream *stream = s->streams[ pkt->stream_index ]; + AVCodecParameters *par = stream->codecpar;
+ AVCodecContext *codec = stream->codec;
unused
Oops, removed it now.
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format); int i; int nb_renames = 0; + int64_t ts = av_rescale_q(pkt->pts, stream->time_base, AV_TIME_BASE_Q);
if (!img->is_pipe) { if (img->update) { @@ -99,7 +102,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) } } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, img->img_number, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && + AV_FRAME_FILENAME_FLAGS_MULTIPLE, ts) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s' (either set updatefirst or use a pattern like %%03d within the filename pattern)\n", diff --git a/libavformat/utils.c b/libavformat/utils.c index 8a51aea..a8b0e8c 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -4377,15 +4377,17 @@ uint64_t ff_ntp_time(void) return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US; }
-int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags) +int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags, int64_t ts) { const char *p; char *q, buf1[20], c; - int nd, len, percentd_found; + int nd, len, percentd_found, percentt_found; + int hours, mins, secs, ms;
q = buf; p = path; percentd_found = 0; + percentt_found = 0; for (;;) { c = *p++; if (c == '\0')
@@ -4414,6 +4416,32 @@ int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number memcpy(q, buf1, len); q += len; break; + case 't': + if (!(flags & AV_FRAME_FILENAME_FLAGS_MULTIPLE) && percentt_found) { + av_log(NULL, AV_LOG_ERROR, "double %%t not allowed"); + goto fail; + } + if (ts == 0) { + av_log(NULL, AV_LOG_DEBUG, "%%t but no ts, using 0"); // necessary for first frame on some streams + } + percentt_found = 1; + ms = ts % AV_TIME_BASE; + ts /= AV_TIME_BASE; + secs = ts % 60; + ts /= 60; + mins = ts % 60; + ts /= 60; + hours = ts;
does this support negative ts ? i think nothig stops negative ts from reaching this
turns out it did not. Please see the attached patch which does. Thank you. -roger-
doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 63 insertions(+), 13 deletions(-) 18b06c4f7d811fe5f716d4e0917dc71d58ffbe12 0001-img2-encoder-allow-t-in-filename-based-on-patch-from.patch From 0f98c18233954d8198ab8a9382a6e58a57d88a12 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Mon, 24 Oct 2016 15:18:28 -0600 Subject: [PATCH] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 63 insertions(+), 13 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index 0d856db..ef2116a 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -635,7 +641,7 @@ The following example shows how to use @command{ffmpeg} for creating a sequence of files @file{img-001.jpeg}, @file{img-002.jpeg}, ..., taking one image every second from the input video: @example -ffmpeg -i in.avi -vsync 1 -r 1 -f image2 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 -f image2 'img-%03d.jpeg' @end example
Note that with @command{ffmpeg}, if the format is not specified with the
This looks unrelated
OK split it into two commits.
See attached. Thanks!
doc/muxers.texi | 13 +++++++++++++ libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 60 insertions(+), 10 deletions(-) 9503d1b6ebc586b796ce6f51011eb705fcf23f5b 0001-img2-encoder-allow-t-in-filename-based-on-patch-from.patch From e8cac5c7de18766ce0f8f286f7dc140b82129df2 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Tue, 25 Oct 2016 18:33:12 -0600 Subject: [PATCH 1/2] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Acked-by: Michael
[...]
muxers.texi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 331cfe5f69530b091202d09e78cd68848079c2ec 0002-img2-encoder-use-more-descriptive-vsync-names.patch From d83554983bde469adb09674c174258b189e242aa Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Tue, 25 Oct 2016 18:33:30 -0600 Subject: [PATCH 2/2] img2 encoder: use more descriptive vsync names
LGTM
Anybody able to commit this for me? Thanks all. -roger-
On Tue, Nov 01, 2016 at 11:23:47AM -0600, Roger Pack wrote:
On 10/26/16, Michael Niedermayer <michael@niedermayer.cc> wrote:
On Tue, Oct 25, 2016 at 06:38:12PM -0600, Roger Pack wrote:
On 10/25/16, Michael Niedermayer <michael@niedermayer.cc> wrote:
On Mon, Oct 24, 2016 at 03:20:14PM -0600, Roger Pack wrote:
On 10/16/16, Michael Niedermayer <michael@niedermayer.cc> wrote:
On Mon, Oct 10, 2016 at 02:56:24PM -0600, Roger Pack wrote: > On 9/22/16, Roger Pack <rogerdpack2@gmail.com> wrote: > > On 1/4/12, Yuval Adam <yuv.adm@gmail.com> wrote: > >> From: Yuval Adam <yuv.adm@gmail.com> > >> > >> The image2 muxer now supports timestamps in output filenames. > >> When used in an output patterm '%t' will be replaced with the > >> frames > >> timestamp in hours, minutes and seconds (hh:mm:ss). > > > > A somewhat updated (but not yet cleaned up) revision: > > > > https://gist.github.com/rdp/e518616f2a702367ae5a922b56e09e04 > > > > see also https://trac.ffmpeg.org/ticket/1452 > > OK attached is the "cleaned up" patch, ready for review/commit. > > how to test: > (apply then) run this: > > ./ffmpeg -i input -copyts -vsync vfr temp/abc-%d-%t.jpeg > and compare filenames with the timestamps from video packets of > ffprobe -show_packets. > > Probably a better way would have been to mix it into > av_bprint_strftime however I wasn't sure how to use that within > libavformat/utils.c av_get_frame_filename2 > > Adam's initial patch > (https://github.com/yuvadm/FFmpeg/commit/0eb002821a2076cb3593c823399aeef9fdd2...) > also deprecated av_get_frame_filename > > but I wasn't sure if we wanted that here or not so didn't include > it. > Thank you for your consideration. > -roger-
> doc/muxers.texi | 19 ++++++++++++++++--- > libavformat/avformat.h | 3 ++- > libavformat/hlsenc.c | 6 +++--- > libavformat/img2enc.c | 7 +++++-- > libavformat/utils.c | 36 ++++++++++++++++++++++++++++++++---- > 5 files changed, 58 insertions(+), 13 deletions(-) > 06950fc8ba5a9163ffb838a2bff9933e69255b41 > 0001-img2-encoder-allow-t-in-filename-based-on-patch-from.patch > From 11deddfacc595c43a4f542fffe5e90b142e39c85 Mon Sep 17 00:00:00 > 2001 > From: rogerdpack <rogerpack2005@gmail.com> > Date: Mon, 10 Oct 2016 14:50:20 -0600 > Subject: [PATCH] img2 encoder: allow %t in filename, based on patch > from > Yuval > Adam > > Signed-off-by: rogerdpack <rogerpack2005@gmail.com> > --- > doc/muxers.texi | 19 ++++++++++++++++--- > libavformat/avformat.h | 3 ++- > libavformat/hlsenc.c | 6 +++--- > libavformat/img2enc.c | 7 +++++-- > libavformat/utils.c | 36 ++++++++++++++++++++++++++++++++---- > 5 files changed, 58 insertions(+), 13 deletions(-) > > diff --git a/doc/muxers.texi b/doc/muxers.texi > index 9ec2e31..6fff966 100644 > --- a/doc/muxers.texi > +++ b/doc/muxers.texi > @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", > the > first filename of > the file list specified will contain the number 1, all the > following > numbers will be sequential. > > +If the pattern contains "%t", the frame's timestamps will be > inserted > +in the filename like "00.00.00.000" for hours, minutes, seconds, > +and milliseconds. > + > +The "%t" and "%d" patterns may be used simultaneously. > + > The pattern may contain a suffix which is used to automatically > determine the format of the image files to write. > > @@ -635,7 +641,7 @@ The following example shows how to use > @command{ffmpeg} for creating a > sequence of files @file{img-001.jpeg}, @file{img-002.jpeg}, ..., > taking one image every second from the input video: > @example > -ffmpeg -i in.avi -vsync 1 -r 1 -f image2 'img-%03d.jpeg' > +ffmpeg -i in.avi -vsync cfr -r 1 -f image2 'img-%03d.jpeg' > @end example > > Note that with @command{ffmpeg}, if the format is not specified > with > the > @@ -643,12 +649,12 @@ Note that with @command{ffmpeg}, if the > format > is > not specified with the > format, the image2 muxer is automatically selected, so the > previous > command can be written as: > @example > -ffmpeg -i in.avi -vsync 1 -r 1 'img-%03d.jpeg' > +ffmpeg -i in.avi -vsync cfr -r 1 'img-%03d.jpeg' > @end example > > Note also that the pattern must not necessarily contain "%d" or > "%0@var{N}d", for example to create a single image file > -@file{img.jpeg} from the input video you can employ the command: > +@file{img.jpeg} from the start of the input video you can employ > the > command: > @example > ffmpeg -i in.avi -f image2 -frames:v 1 img.jpeg > @end example > @@ -664,6 +670,13 @@ can be used: > ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 > "%Y-%m-%d_%H-%M-%S.jpg" > @end example > > +The following example uses the timestamp parameter to generate one > +image file per video frame from the input, and name it including > its > original > +timestamp. > +@example > +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg > +@end example > + > @subsection Options > > @table @option > diff --git a/libavformat/avformat.h b/libavformat/avformat.h > index 057f8c5..4eeb6f4 100644 > --- a/libavformat/avformat.h > +++ b/libavformat/avformat.h > @@ -2744,10 +2744,11 @@ void av_dump_format(AVFormatContext *ic, > * @param path numbered sequence string > * @param number frame number > * @param flags AV_FRAME_FILENAME_FLAGS_* > + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. > * @return 0 if OK, -1 on format error > */ > int av_get_frame_filename2(char *buf, int buf_size, > - const char *path, int number, int > flags); > + const char *path, int number, int flags, > int64_t ts); > > int av_get_frame_filename(char *buf, int buf_size, > const char *path, int number); > diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c > index 9ca2df7..02d8d44 100644 > --- a/libavformat/hlsenc.c > +++ b/libavformat/hlsenc.c > @@ -654,7 +654,7 @@ static int hls_start(AVFormatContext *s) > } else if (c->max_seg_size > 0) { > if (av_get_frame_filename2(oc->filename, > sizeof(oc->filename), > c->basename, c->wrap ? c->sequence % c->wrap : > c->sequence, > - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { > + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { > av_log(oc, AV_LOG_ERROR, "Invalid segment filename > template '%s', you can try to use -use_localtime 1 with it\n", > c->basename); > return AVERROR(EINVAL); > } > @@ -685,14 +685,14 @@ static int hls_start(AVFormatContext *s) > } > } else if (av_get_frame_filename2(oc->filename, > sizeof(oc->filename), > c->basename, c->wrap ? > c->sequence > % > c->wrap : c->sequence, > - AV_FRAME_FILENAME_FLAGS_MULTIPLE) > < > 0) > { > + AV_FRAME_FILENAME_FLAGS_MULTIPLE, > 0) > < > 0) { > av_log(oc, AV_LOG_ERROR, "Invalid segment filename > template > '%s' you can try to use -use_localtime 1 with it\n", c->basename); > return AVERROR(EINVAL); > } > if( c->vtt_basename) { > if (av_get_frame_filename2(vtt_oc->filename, > sizeof(vtt_oc->filename), > c->vtt_basename, c->wrap ? > c->sequence > % > c->wrap : c->sequence, > - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < > 0) > { > + AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) > < > 0) > { > av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment > filename > template '%s'\n", c->vtt_basename); > return AVERROR(EINVAL); > } > diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c > index 1297b1a..e5db290 100644 > --- a/libavformat/img2enc.c > +++ b/libavformat/img2enc.c > @@ -80,10 +80,13 @@ static int write_packet(AVFormatContext *s, > AVPacket > *pkt) > VideoMuxData *img = s->priv_data; > AVIOContext *pb[4]; > char filename[1024]; > - AVCodecParameters *par = > s->streams[pkt->stream_index]->codecpar; > + AVStream *stream = s->streams[ pkt->stream_index ]; > + AVCodecParameters *par = stream->codecpar;
> + AVCodecContext *codec = stream->codec;
unused
Oops, removed it now.
> const AVPixFmtDescriptor *desc = > av_pix_fmt_desc_get(par->format); > int i; > int nb_renames = 0; > + int64_t ts = av_rescale_q(pkt->pts, stream->time_base, > AV_TIME_BASE_Q); > > if (!img->is_pipe) { > if (img->update) { > @@ -99,7 +102,7 @@ static int write_packet(AVFormatContext *s, > AVPacket > *pkt) > } > } else if (av_get_frame_filename2(filename, > sizeof(filename), > img->path, > img->img_number, > - > AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && > + > AV_FRAME_FILENAME_FLAGS_MULTIPLE, ts) < 0 && > img->img_number > 1) { > av_log(s, AV_LOG_ERROR, > "Could not get frame filename number %d from > pattern > '%s' (either set updatefirst or use a pattern like %%03d within the > filename pattern)\n", > diff --git a/libavformat/utils.c b/libavformat/utils.c > index 8a51aea..a8b0e8c 100644 > --- a/libavformat/utils.c > +++ b/libavformat/utils.c > @@ -4377,15 +4377,17 @@ uint64_t ff_ntp_time(void) > return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US; > } > > -int av_get_frame_filename2(char *buf, int buf_size, const char > *path, > int > number, int flags) > +int av_get_frame_filename2(char *buf, int buf_size, const char > *path, > int > number, int flags, int64_t ts) > { > const char *p; > char *q, buf1[20], c; > - int nd, len, percentd_found; > + int nd, len, percentd_found, percentt_found; > + int hours, mins, secs, ms; > > q = buf; > p = path; > percentd_found = 0; > + percentt_found = 0; > for (;;) { > c = *p++; > if (c == '\0')
> @@ -4414,6 +4416,32 @@ int av_get_frame_filename2(char *buf, int > buf_size, > const char *path, int number > memcpy(q, buf1, len); > q += len; > break; > + case 't': > + if (!(flags & AV_FRAME_FILENAME_FLAGS_MULTIPLE) && > percentt_found) { > + av_log(NULL, AV_LOG_ERROR, "double %%t not > allowed"); > + goto fail; > + } > + if (ts == 0) { > + av_log(NULL, AV_LOG_DEBUG, "%%t but no ts, > using > 0"); > // necessary for first frame on some streams > + } > + percentt_found = 1; > + ms = ts % AV_TIME_BASE; > + ts /= AV_TIME_BASE; > + secs = ts % 60; > + ts /= 60; > + mins = ts % 60; > + ts /= 60; > + hours = ts;
does this support negative ts ? i think nothig stops negative ts from reaching this
turns out it did not. Please see the attached patch which does. Thank you. -roger-
doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 63 insertions(+), 13 deletions(-) 18b06c4f7d811fe5f716d4e0917dc71d58ffbe12 0001-img2-encoder-allow-t-in-filename-based-on-patch-from.patch From 0f98c18233954d8198ab8a9382a6e58a57d88a12 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Mon, 24 Oct 2016 15:18:28 -0600 Subject: [PATCH] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 19 ++++++++++++++++--- libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 63 insertions(+), 13 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index 0d856db..ef2116a 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -635,7 +641,7 @@ The following example shows how to use @command{ffmpeg} for creating a sequence of files @file{img-001.jpeg}, @file{img-002.jpeg}, ..., taking one image every second from the input video: @example -ffmpeg -i in.avi -vsync 1 -r 1 -f image2 'img-%03d.jpeg' +ffmpeg -i in.avi -vsync cfr -r 1 -f image2 'img-%03d.jpeg' @end example
Note that with @command{ffmpeg}, if the format is not specified with the
This looks unrelated
OK split it into two commits.
See attached. Thanks!
doc/muxers.texi | 13 +++++++++++++ libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 60 insertions(+), 10 deletions(-) 9503d1b6ebc586b796ce6f51011eb705fcf23f5b 0001-img2-encoder-allow-t-in-filename-based-on-patch-from.patch From e8cac5c7de18766ce0f8f286f7dc140b82129df2 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Tue, 25 Oct 2016 18:33:12 -0600 Subject: [PATCH 1/2] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Acked-by: Michael
[...]
muxers.texi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 331cfe5f69530b091202d09e78cd68848079c2ec 0002-img2-encoder-use-more-descriptive-vsync-names.patch From d83554983bde469adb09674c174258b189e242aa Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Tue, 25 Oct 2016 18:33:30 -0600 Subject: [PATCH 2/2] img2 encoder: use more descriptive vsync names
LGTM
Anybody able to commit this for me?
applied thx [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB While the State exists there can be no freedom; when there is freedom there will be no State. -- Vladimir Lenin
On 10/25/2016 9:38 PM, Roger Pack wrote:
From e8cac5c7de18766ce0f8f286f7dc140b82129df2 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Tue, 25 Oct 2016 18:33:12 -0600 Subject: [PATCH 1/2] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 13 +++++++++++++ libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 60 insertions(+), 10 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index 0d856db..0c3a198 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -664,6 +670,13 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example
+The following example uses the timestamp parameter to generate one +image file per video frame from the input, and name it including its original +timestamp. +@example +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg +@end example + @subsection Options
@table @option diff --git a/libavformat/avformat.h b/libavformat/avformat.h index f9f4d72..7f39698 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2780,10 +2780,11 @@ void av_dump_format(AVFormatContext *ic, * @param path numbered sequence string * @param number frame number * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. * @return 0 if OK, -1 on format error */ int av_get_frame_filename2(char *buf, int buf_size, - const char *path, int number, int flags); + const char *path, int number, int flags, int64_t ts);
Uhh, what? did you just break API modifying a public function?
int av_get_frame_filename(char *buf, int buf_size, const char *path, int number);
On 11/1/2016 6:43 PM, James Almer wrote:
On 10/25/2016 9:38 PM, Roger Pack wrote:
From e8cac5c7de18766ce0f8f286f7dc140b82129df2 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Tue, 25 Oct 2016 18:33:12 -0600 Subject: [PATCH 1/2] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 13 +++++++++++++ libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 60 insertions(+), 10 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index 0d856db..0c3a198 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -664,6 +670,13 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example
+The following example uses the timestamp parameter to generate one +image file per video frame from the input, and name it including its original +timestamp. +@example +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg +@end example + @subsection Options
@table @option diff --git a/libavformat/avformat.h b/libavformat/avformat.h index f9f4d72..7f39698 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2780,10 +2780,11 @@ void av_dump_format(AVFormatContext *ic, * @param path numbered sequence string * @param number frame number * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. * @return 0 if OK, -1 on format error */ int av_get_frame_filename2(char *buf, int buf_size, - const char *path, int number, int flags); + const char *path, int number, int flags, int64_t ts);
Uhh, what? did you just break API modifying a public function?
For the record, this was reverted. Shouldn't be hard to solve, i think. Just add a new ff_get_frame_filename() function to internal.h with this new signature, at least for now and for this feature, to avoid adding a third public function doing the same thing unless absolutely necessary.
int av_get_frame_filename(char *buf, int buf_size, const char *path, int number);
On 11/1/16, James Almer <jamrial@gmail.com> wrote:
On 11/1/2016 6:43 PM, James Almer wrote:
On 10/25/2016 9:38 PM, Roger Pack wrote:
From e8cac5c7de18766ce0f8f286f7dc140b82129df2 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Tue, 25 Oct 2016 18:33:12 -0600 Subject: [PATCH 1/2] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 13 +++++++++++++ libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 60 insertions(+), 10 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index 0d856db..0c3a198 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -664,6 +670,13 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example
+The following example uses the timestamp parameter to generate one +image file per video frame from the input, and name it including its original +timestamp. +@example +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg +@end example + @subsection Options
@table @option diff --git a/libavformat/avformat.h b/libavformat/avformat.h index f9f4d72..7f39698 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2780,10 +2780,11 @@ void av_dump_format(AVFormatContext *ic, * @param path numbered sequence string * @param number frame number * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. * @return 0 if OK, -1 on format error */ int av_get_frame_filename2(char *buf, int buf_size, - const char *path, int number, int flags); + const char *path, int number, int flags, int64_t ts);
Uhh, what? did you just break API modifying a public function?
For the record, this was reverted.
Shouldn't be hard to solve, i think. Just add a new ff_get_frame_filename() function to internal.h with this new signature, at least for now and for this feature, to avoid adding a third public function doing the same thing unless absolutely necessary.
OK see attached. Wasn't sure if I should duplicate docs or not, feel free to modify. Cheers! -roger-
On 11/10/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 11/1/16, James Almer <jamrial@gmail.com> wrote:
On 11/1/2016 6:43 PM, James Almer wrote:
On 10/25/2016 9:38 PM, Roger Pack wrote:
From e8cac5c7de18766ce0f8f286f7dc140b82129df2 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Tue, 25 Oct 2016 18:33:12 -0600 Subject: [PATCH 1/2] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 13 +++++++++++++ libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 60 insertions(+), 10 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index 0d856db..0c3a198 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -664,6 +670,13 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example
+The following example uses the timestamp parameter to generate one +image file per video frame from the input, and name it including its original +timestamp. +@example +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg +@end example + @subsection Options
@table @option diff --git a/libavformat/avformat.h b/libavformat/avformat.h index f9f4d72..7f39698 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2780,10 +2780,11 @@ void av_dump_format(AVFormatContext *ic, * @param path numbered sequence string * @param number frame number * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. * @return 0 if OK, -1 on format error */ int av_get_frame_filename2(char *buf, int buf_size, - const char *path, int number, int flags); + const char *path, int number, int flags, int64_t ts);
Uhh, what? did you just break API modifying a public function?
For the record, this was reverted.
Shouldn't be hard to solve, i think. Just add a new ff_get_frame_filename() function to internal.h with this new signature, at least for now and for this feature, to avoid adding a third public function doing the same thing unless absolutely necessary.
OK see attached. Wasn't sure if I should duplicate docs or not, feel free to modify.
Ping...if no response in another few days I'll go ahead and get write access and commit it myself. Thanks. -roger-
On 11/10/2016 4:26 PM, Roger Pack wrote:
On 11/1/16, James Almer <jamrial@gmail.com> wrote:
On 11/1/2016 6:43 PM, James Almer wrote:
On 10/25/2016 9:38 PM, Roger Pack wrote:
> From e8cac5c7de18766ce0f8f286f7dc140b82129df2 Mon Sep 17 00:00:00 2001 > From: rogerdpack <rogerpack2005@gmail.com> > Date: Tue, 25 Oct 2016 18:33:12 -0600 > Subject: [PATCH 1/2] img2 encoder: allow %t in filename, based on patch > from > Yuval Adam > > Signed-off-by: rogerdpack <rogerpack2005@gmail.com> > --- > doc/muxers.texi | 13 +++++++++++++ > libavformat/avformat.h | 3 ++- > libavformat/hlsenc.c | 6 +++--- > libavformat/img2enc.c | 6 ++++-- > libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- > 5 files changed, 60 insertions(+), 10 deletions(-) > > diff --git a/doc/muxers.texi b/doc/muxers.texi > index 0d856db..0c3a198 100644 > --- a/doc/muxers.texi > +++ b/doc/muxers.texi > @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", the > first filename of > the file list specified will contain the number 1, all the following > numbers will be sequential. > > +If the pattern contains "%t", the frame's timestamps will be inserted > +in the filename like "00.00.00.000" for hours, minutes, seconds, > +and milliseconds. > + > +The "%t" and "%d" patterns may be used simultaneously. > + > The pattern may contain a suffix which is used to automatically > determine the format of the image files to write. > > @@ -664,6 +670,13 @@ can be used: > ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 > "%Y-%m-%d_%H-%M-%S.jpg" > @end example > > +The following example uses the timestamp parameter to generate one > +image file per video frame from the input, and name it including its > original > +timestamp. > +@example > +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg > +@end example > + > @subsection Options > > @table @option > diff --git a/libavformat/avformat.h b/libavformat/avformat.h > index f9f4d72..7f39698 100644 > --- a/libavformat/avformat.h > +++ b/libavformat/avformat.h > @@ -2780,10 +2780,11 @@ void av_dump_format(AVFormatContext *ic, > * @param path numbered sequence string > * @param number frame number > * @param flags AV_FRAME_FILENAME_FLAGS_* > + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. > * @return 0 if OK, -1 on format error > */ > int av_get_frame_filename2(char *buf, int buf_size, > - const char *path, int number, int flags); > + const char *path, int number, int flags, > int64_t ts);
Uhh, what? did you just break API modifying a public function?
For the record, this was reverted.
Shouldn't be hard to solve, i think. Just add a new ff_get_frame_filename() function to internal.h with this new signature, at least for now and for this feature, to avoid adding a third public function doing the same thing unless absolutely necessary. OK see attached. Wasn't sure if I should duplicate docs or not, feel free to modify. Cheers! -roger-
0001-img2-encoder-allow-t-in-filepattern-based-on-patch-f.patch
From 8287f1ca543f764e9e88659ee5a07873860d607d Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Thu, 10 Nov 2016 12:24:49 -0700 Subject: [PATCH] img2 encoder: allow %t in filepattern, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 13 +++++++++++++ libavformat/img2enc.c | 8 +++++--- libavformat/internal.h | 18 ++++++++++++++++++ libavformat/utils.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 78 insertions(+), 6 deletions(-)
No hlsenc.c?
diff --git a/doc/muxers.texi b/doc/muxers.texi index 806182a..670fcca 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -622,6 +622,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -667,6 +673,13 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example
+The following example uses the timestamp parameter to generate one +image file per video frame from the input, and name it including its original +timestamp. +@example +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg +@end example + @subsection Options
@table @option diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 1297b1a..651739e 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -80,10 +80,12 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) VideoMuxData *img = s->priv_data; AVIOContext *pb[4]; char filename[1024]; - AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + AVStream *stream = s->streams[ pkt->stream_index ]; + AVCodecParameters *par = stream->codecpar; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format); int i; int nb_renames = 0; + int64_t ts = av_rescale_q(pkt->pts, stream->time_base, AV_TIME_BASE_Q);
if (!img->is_pipe) { if (img->update) { @@ -97,9 +99,9 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_ERROR, "Could not get frame filename with strftime\n"); return AVERROR(EINVAL); } - } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, + } else if (av_get_frame_filename3(filename, sizeof(filename), img->path, img->img_number, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && + AV_FRAME_FILENAME_FLAGS_MULTIPLE, ts) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s' (either set updatefirst or use a pattern like %%03d within the filename pattern)\n", diff --git a/libavformat/internal.h b/libavformat/internal.h index da64c64..d7174c5 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -356,6 +356,24 @@ void ff_reduce_index(AVFormatContext *s, int stream_index); enum AVCodecID ff_guess_image2_codec(const char *filename);
/** + * Return in 'buf' the path with '%d' replaced by a number. + * + * Also handles the '%0nd' format where 'n' is the total number + * of digits and '%%'. + * Also handles the '%t' format where 't' is the timestamp. + * + * @param buf destination buffer + * @param buf_size destination buffer size + * @param path numbered sequence string + * @param number frame number + * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. + * @return 0 if OK, -1 on format error + */ +int av_get_frame_filename3(char *buf, int buf_size,
Since it's internal it needs to have an ff_ prefix, not av_. No comments about the code itself. If it's the same as the already reviewed version then it should be good.
+ const char *path, int number, int flags, int64_t ts); + +/** * Perform a binary search using av_index_search_timestamp() and * AVInputFormat.read_timestamp(). * diff --git a/libavformat/utils.c b/libavformat/utils.c index 5664646..ba8707e 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -4391,15 +4391,18 @@ uint64_t ff_ntp_time(void) return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US; }
-int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags) +int av_get_frame_filename3(char *buf, int buf_size, const char *path, int number, int flags, int64_t ts) { const char *p; char *q, buf1[20], c; - int nd, len, percentd_found; + int nd, len, percentd_found, percentt_found; + int hours, mins, secs, ms; + int64_t abs_ts;
q = buf; p = path; percentd_found = 0; + percentt_found = 0; for (;;) { c = *p++; if (c == '\0') @@ -4428,6 +4431,37 @@ int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number memcpy(q, buf1, len); q += len; break; + case 't': + if (!(flags & AV_FRAME_FILENAME_FLAGS_MULTIPLE) && percentt_found) { + av_log(NULL, AV_LOG_ERROR, "double %%t not allowed"); + goto fail; + } + if (ts == 0) { + av_log(NULL, AV_LOG_DEBUG, "%%t but no ts, using 0"); // necessary for first frame on some streams + } + percentt_found = 1; + abs_ts = llabs(ts); + ms = abs_ts % AV_TIME_BASE; + abs_ts /= AV_TIME_BASE; + secs = abs_ts % 60; + abs_ts /= 60; + mins = abs_ts % 60; + abs_ts /= 60; + hours = abs_ts; + if (ts < 0) + snprintf(buf1, sizeof(buf1), + "-%02d.%02d.%02d.%03d", hours, mins, secs, ms); + else + snprintf(buf1, sizeof(buf1), + "%02d.%02d.%02d.%03d", hours, mins, secs, ms); + len = strlen(buf1); + if ((q - buf + len) > buf_size - 1) { + av_log(NULL, AV_LOG_ERROR, "%%t size overflow"); + goto fail; + } + memcpy(q, buf1, len); + q += len; + break; default: goto fail; } @@ -4437,7 +4471,7 @@ addchar: *q++ = c; } } - if (!percentd_found) + if (!percentd_found && !percentt_found) goto fail; *q = '\0'; return 0; @@ -4451,6 +4485,11 @@ int av_get_frame_filename(char *buf, int buf_size, const char *path, int number) return av_get_frame_filename2(buf, buf_size, path, number, 0); }
+int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags) +{ + return av_get_frame_filename3(buf, buf_size, path, number, flags, 0); +} + void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, -- 2.9.3 (Apple Git-75)
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
On 11/15/16, James Almer <jamrial@gmail.com> wrote:
On 11/10/2016 4:26 PM, Roger Pack wrote:
On 11/1/16, James Almer <jamrial@gmail.com> wrote:
On 11/1/2016 6:43 PM, James Almer wrote:
On 10/25/2016 9:38 PM, Roger Pack wrote: >> From e8cac5c7de18766ce0f8f286f7dc140b82129df2 Mon Sep 17 00:00:00 >> 2001 >> From: rogerdpack <rogerpack2005@gmail.com> >> Date: Tue, 25 Oct 2016 18:33:12 -0600 >> Subject: [PATCH 1/2] img2 encoder: allow %t in filename, based on >> patch >> from >> Yuval Adam >> >> Signed-off-by: rogerdpack <rogerpack2005@gmail.com> >> --- >> doc/muxers.texi | 13 +++++++++++++ >> libavformat/avformat.h | 3 ++- >> libavformat/hlsenc.c | 6 +++--- >> libavformat/img2enc.c | 6 ++++-- >> libavformat/utils.c | 42 >> ++++++++++++++++++++++++++++++++++++++---- >> 5 files changed, 60 insertions(+), 10 deletions(-) >> >> diff --git a/doc/muxers.texi b/doc/muxers.texi >> index 0d856db..0c3a198 100644 >> --- a/doc/muxers.texi >> +++ b/doc/muxers.texi >> @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", >> the >> first filename of >> the file list specified will contain the number 1, all the >> following >> numbers will be sequential. >> >> +If the pattern contains "%t", the frame's timestamps will be >> inserted >> +in the filename like "00.00.00.000" for hours, minutes, seconds, >> +and milliseconds. >> + >> +The "%t" and "%d" patterns may be used simultaneously. >> + >> The pattern may contain a suffix which is used to automatically >> determine the format of the image files to write. >> >> @@ -664,6 +670,13 @@ can be used: >> ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 >> "%Y-%m-%d_%H-%M-%S.jpg" >> @end example >> >> +The following example uses the timestamp parameter to generate one >> +image file per video frame from the input, and name it including >> its >> original >> +timestamp. >> +@example >> +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg >> +@end example >> + >> @subsection Options >> >> @table @option >> diff --git a/libavformat/avformat.h b/libavformat/avformat.h >> index f9f4d72..7f39698 100644 >> --- a/libavformat/avformat.h >> +++ b/libavformat/avformat.h >> @@ -2780,10 +2780,11 @@ void av_dump_format(AVFormatContext *ic, >> * @param path numbered sequence string >> * @param number frame number >> * @param flags AV_FRAME_FILENAME_FLAGS_* >> + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. >> * @return 0 if OK, -1 on format error >> */ >> int av_get_frame_filename2(char *buf, int buf_size, >> - const char *path, int number, int >> flags); >> + const char *path, int number, int flags, >> int64_t ts);
Uhh, what? did you just break API modifying a public function?
For the record, this was reverted.
Shouldn't be hard to solve, i think. Just add a new ff_get_frame_filename() function to internal.h with this new signature, at least for now and for this feature, to avoid adding a third public function doing the same thing unless absolutely necessary. OK see attached. Wasn't sure if I should duplicate docs or not, feel free to modify. Cheers! -roger-
0001-img2-encoder-allow-t-in-filepattern-based-on-patch-f.patch
From 8287f1ca543f764e9e88659ee5a07873860d607d Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Thu, 10 Nov 2016 12:24:49 -0700 Subject: [PATCH] img2 encoder: allow %t in filepattern, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 13 +++++++++++++ libavformat/img2enc.c | 8 +++++--- libavformat/internal.h | 18 ++++++++++++++++++ libavformat/utils.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 78 insertions(+), 6 deletions(-)
No hlsenc.c?
Yeah, good idea, moved them all to use the ff_get_frame_filename3 now just so people would realize the extra parameter is available.
diff --git a/doc/muxers.texi b/doc/muxers.texi index 806182a..670fcca 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -622,6 +622,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -667,6 +673,13 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example
+The following example uses the timestamp parameter to generate one +image file per video frame from the input, and name it including its original +timestamp. +@example +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg +@end example + @subsection Options
@table @option diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 1297b1a..651739e 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -80,10 +80,12 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) VideoMuxData *img = s->priv_data; AVIOContext *pb[4]; char filename[1024]; - AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + AVStream *stream = s->streams[ pkt->stream_index ]; + AVCodecParameters *par = stream->codecpar; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format); int i; int nb_renames = 0; + int64_t ts = av_rescale_q(pkt->pts, stream->time_base, AV_TIME_BASE_Q);
if (!img->is_pipe) { if (img->update) { @@ -97,9 +99,9 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_ERROR, "Could not get frame filename with strftime\n"); return AVERROR(EINVAL); } - } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, + } else if (av_get_frame_filename3(filename, sizeof(filename), img->path, img->img_number, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && + AV_FRAME_FILENAME_FLAGS_MULTIPLE, ts) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s' (either set updatefirst or use a pattern like %%03d within the filename pattern)\n", diff --git a/libavformat/internal.h b/libavformat/internal.h index da64c64..d7174c5 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -356,6 +356,24 @@ void ff_reduce_index(AVFormatContext *s, int stream_index); enum AVCodecID ff_guess_image2_codec(const char *filename);
/** + * Return in 'buf' the path with '%d' replaced by a number. + * + * Also handles the '%0nd' format where 'n' is the total number + * of digits and '%%'. + * Also handles the '%t' format where 't' is the timestamp. + * + * @param buf destination buffer + * @param buf_size destination buffer size + * @param path numbered sequence string + * @param number frame number + * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. + * @return 0 if OK, -1 on format error + */ +int av_get_frame_filename3(char *buf, int buf_size,
Since it's internal it needs to have an ff_ prefix, not av_.
OK hopefully fixed with the attached, thanks. -roger-
On 11/18/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 11/15/16, James Almer <jamrial@gmail.com> wrote:
On 11/10/2016 4:26 PM, Roger Pack wrote:
On 11/1/16, James Almer <jamrial@gmail.com> wrote:
On 11/1/2016 6:43 PM, James Almer wrote:
> On 10/25/2016 9:38 PM, Roger Pack wrote: >>> From e8cac5c7de18766ce0f8f286f7dc140b82129df2 Mon Sep 17 00:00:00 >>> 2001 >>> From: rogerdpack <rogerpack2005@gmail.com> >>> Date: Tue, 25 Oct 2016 18:33:12 -0600 >>> Subject: [PATCH 1/2] img2 encoder: allow %t in filename, based on >>> patch >>> from >>> Yuval Adam >>> >>> Signed-off-by: rogerdpack <rogerpack2005@gmail.com> >>> --- >>> doc/muxers.texi | 13 +++++++++++++ >>> libavformat/avformat.h | 3 ++- >>> libavformat/hlsenc.c | 6 +++--- >>> libavformat/img2enc.c | 6 ++++-- >>> libavformat/utils.c | 42 >>> ++++++++++++++++++++++++++++++++++++++---- >>> 5 files changed, 60 insertions(+), 10 deletions(-) >>> >>> diff --git a/doc/muxers.texi b/doc/muxers.texi >>> index 0d856db..0c3a198 100644 >>> --- a/doc/muxers.texi >>> +++ b/doc/muxers.texi >>> @@ -619,6 +619,12 @@ If the pattern contains "%d" or >>> "%0@var{N}d", >>> the >>> first filename of >>> the file list specified will contain the number 1, all the >>> following >>> numbers will be sequential. >>> >>> +If the pattern contains "%t", the frame's timestamps will be >>> inserted >>> +in the filename like "00.00.00.000" for hours, minutes, seconds, >>> +and milliseconds. >>> + >>> +The "%t" and "%d" patterns may be used simultaneously. >>> + >>> The pattern may contain a suffix which is used to automatically >>> determine the format of the image files to write. >>> >>> @@ -664,6 +670,13 @@ can be used: >>> ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 >>> "%Y-%m-%d_%H-%M-%S.jpg" >>> @end example >>> >>> +The following example uses the timestamp parameter to generate >>> one >>> +image file per video frame from the input, and name it including >>> its >>> original >>> +timestamp. >>> +@example >>> +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg >>> +@end example >>> + >>> @subsection Options >>> >>> @table @option >>> diff --git a/libavformat/avformat.h b/libavformat/avformat.h >>> index f9f4d72..7f39698 100644 >>> --- a/libavformat/avformat.h >>> +++ b/libavformat/avformat.h >>> @@ -2780,10 +2780,11 @@ void av_dump_format(AVFormatContext *ic, >>> * @param path numbered sequence string >>> * @param number frame number >>> * @param flags AV_FRAME_FILENAME_FLAGS_* >>> + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. >>> * @return 0 if OK, -1 on format error >>> */ >>> int av_get_frame_filename2(char *buf, int buf_size, >>> - const char *path, int number, int >>> flags); >>> + const char *path, int number, int >>> flags, >>> int64_t ts); > > Uhh, what? did you just break API modifying a public function? >
For the record, this was reverted.
Shouldn't be hard to solve, i think. Just add a new ff_get_frame_filename() function to internal.h with this new signature, at least for now and for this feature, to avoid adding a third public function doing the same thing unless absolutely necessary. OK see attached. Wasn't sure if I should duplicate docs or not, feel free to modify. Cheers! -roger-
0001-img2-encoder-allow-t-in-filepattern-based-on-patch-f.patch
From 8287f1ca543f764e9e88659ee5a07873860d607d Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Thu, 10 Nov 2016 12:24:49 -0700 Subject: [PATCH] img2 encoder: allow %t in filepattern, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 13 +++++++++++++ libavformat/img2enc.c | 8 +++++--- libavformat/internal.h | 18 ++++++++++++++++++ libavformat/utils.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 78 insertions(+), 6 deletions(-)
No hlsenc.c?
Yeah, good idea, moved them all to use the ff_get_frame_filename3 now just so people would realize the extra parameter is available.
diff --git a/doc/muxers.texi b/doc/muxers.texi index 806182a..670fcca 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -622,6 +622,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -667,6 +673,13 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example
+The following example uses the timestamp parameter to generate one +image file per video frame from the input, and name it including its original +timestamp. +@example +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg +@end example + @subsection Options
@table @option diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 1297b1a..651739e 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -80,10 +80,12 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) VideoMuxData *img = s->priv_data; AVIOContext *pb[4]; char filename[1024]; - AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + AVStream *stream = s->streams[ pkt->stream_index ]; + AVCodecParameters *par = stream->codecpar; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format); int i; int nb_renames = 0; + int64_t ts = av_rescale_q(pkt->pts, stream->time_base, AV_TIME_BASE_Q);
if (!img->is_pipe) { if (img->update) { @@ -97,9 +99,9 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_ERROR, "Could not get frame filename with strftime\n"); return AVERROR(EINVAL); } - } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, + } else if (av_get_frame_filename3(filename, sizeof(filename), img->path, img->img_number, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && + AV_FRAME_FILENAME_FLAGS_MULTIPLE, ts) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s' (either set updatefirst or use a pattern like %%03d within the filename pattern)\n", diff --git a/libavformat/internal.h b/libavformat/internal.h index da64c64..d7174c5 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -356,6 +356,24 @@ void ff_reduce_index(AVFormatContext *s, int stream_index); enum AVCodecID ff_guess_image2_codec(const char *filename);
/** + * Return in 'buf' the path with '%d' replaced by a number. + * + * Also handles the '%0nd' format where 'n' is the total number + * of digits and '%%'. + * Also handles the '%t' format where 't' is the timestamp. + * + * @param buf destination buffer + * @param buf_size destination buffer size + * @param path numbered sequence string + * @param number frame number + * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. + * @return 0 if OK, -1 on format error + */ +int av_get_frame_filename3(char *buf, int buf_size,
Since it's internal it needs to have an ff_ prefix, not av_.
OK hopefully fixed with the attached, thanks.
Ping... Happy holidays! -roger-
On 11/25/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 11/18/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 11/15/16, James Almer <jamrial@gmail.com> wrote:
On 11/10/2016 4:26 PM, Roger Pack wrote:
On 11/1/16, James Almer <jamrial@gmail.com> wrote:
On 11/1/2016 6:43 PM, James Almer wrote: >> On 10/25/2016 9:38 PM, Roger Pack wrote: > >>> From e8cac5c7de18766ce0f8f286f7dc140b82129df2 Mon Sep 17 > >>> 00:00:00 > >>> 2001 > >>> From: rogerdpack <rogerpack2005@gmail.com> > >>> Date: Tue, 25 Oct 2016 18:33:12 -0600 > >>> Subject: [PATCH 1/2] img2 encoder: allow %t in filename, based > >>> on > >>> patch > >>> from > >>> Yuval Adam > >>> > >>> Signed-off-by: rogerdpack <rogerpack2005@gmail.com> > >>> --- > >>> doc/muxers.texi | 13 +++++++++++++ > >>> libavformat/avformat.h | 3 ++- > >>> libavformat/hlsenc.c | 6 +++--- > >>> libavformat/img2enc.c | 6 ++++-- > >>> libavformat/utils.c | 42 > >>> ++++++++++++++++++++++++++++++++++++++---- > >>> 5 files changed, 60 insertions(+), 10 deletions(-) > >>> > >>> diff --git a/doc/muxers.texi b/doc/muxers.texi > >>> index 0d856db..0c3a198 100644 > >>> --- a/doc/muxers.texi > >>> +++ b/doc/muxers.texi > >>> @@ -619,6 +619,12 @@ If the pattern contains "%d" or > >>> "%0@var{N}d", > >>> the > >>> first filename of > >>> the file list specified will contain the number 1, all the > >>> following > >>> numbers will be sequential. > >>> > >>> +If the pattern contains "%t", the frame's timestamps will be > >>> inserted > >>> +in the filename like "00.00.00.000" for hours, minutes, > >>> seconds, > >>> +and milliseconds. > >>> + > >>> +The "%t" and "%d" patterns may be used simultaneously. > >>> + > >>> The pattern may contain a suffix which is used to automatically > >>> determine the format of the image files to write. > >>> > >>> @@ -664,6 +670,13 @@ can be used: > >>> ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 > >>> "%Y-%m-%d_%H-%M-%S.jpg" > >>> @end example > >>> > >>> +The following example uses the timestamp parameter to generate > >>> one > >>> +image file per video frame from the input, and name it > >>> including > >>> its > >>> original > >>> +timestamp. > >>> +@example > >>> +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg > >>> +@end example > >>> + > >>> @subsection Options > >>> > >>> @table @option > >>> diff --git a/libavformat/avformat.h b/libavformat/avformat.h > >>> index f9f4d72..7f39698 100644 > >>> --- a/libavformat/avformat.h > >>> +++ b/libavformat/avformat.h > >>> @@ -2780,10 +2780,11 @@ void av_dump_format(AVFormatContext *ic, > >>> * @param path numbered sequence string > >>> * @param number frame number > >>> * @param flags AV_FRAME_FILENAME_FLAGS_* > >>> + * @param ts frame timestamp in AV_TIME_BASE fractional > >>> seconds. > >>> * @return 0 if OK, -1 on format error > >>> */ > >>> int av_get_frame_filename2(char *buf, int buf_size, > >>> - const char *path, int number, int > >>> flags); > >>> + const char *path, int number, int > >>> flags, > >>> int64_t ts); >> >> Uhh, what? did you just break API modifying a public function? >>
For the record, this was reverted.
Shouldn't be hard to solve, i think. Just add a new ff_get_frame_filename() function to internal.h with this new signature, at least for now and for this feature, to avoid adding a third public function doing the same thing unless absolutely necessary. OK see attached. Wasn't sure if I should duplicate docs or not, feel free to modify. Cheers! -roger-
0001-img2-encoder-allow-t-in-filepattern-based-on-patch-f.patch
From 8287f1ca543f764e9e88659ee5a07873860d607d Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Thu, 10 Nov 2016 12:24:49 -0700 Subject: [PATCH] img2 encoder: allow %t in filepattern, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 13 +++++++++++++ libavformat/img2enc.c | 8 +++++--- libavformat/internal.h | 18 ++++++++++++++++++ libavformat/utils.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 78 insertions(+), 6 deletions(-)
No hlsenc.c?
Yeah, good idea, moved them all to use the ff_get_frame_filename3 now just so people would realize the extra parameter is available.
diff --git a/doc/muxers.texi b/doc/muxers.texi index 806182a..670fcca 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -622,6 +622,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -667,6 +673,13 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example
+The following example uses the timestamp parameter to generate one +image file per video frame from the input, and name it including its original +timestamp. +@example +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg +@end example + @subsection Options
@table @option diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 1297b1a..651739e 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -80,10 +80,12 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) VideoMuxData *img = s->priv_data; AVIOContext *pb[4]; char filename[1024]; - AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + AVStream *stream = s->streams[ pkt->stream_index ]; + AVCodecParameters *par = stream->codecpar; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format); int i; int nb_renames = 0; + int64_t ts = av_rescale_q(pkt->pts, stream->time_base, AV_TIME_BASE_Q);
if (!img->is_pipe) { if (img->update) { @@ -97,9 +99,9 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_ERROR, "Could not get frame filename with strftime\n"); return AVERROR(EINVAL); } - } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, + } else if (av_get_frame_filename3(filename, sizeof(filename), img->path, img->img_number, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && + AV_FRAME_FILENAME_FLAGS_MULTIPLE, ts) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s' (either set updatefirst or use a pattern like %%03d within the filename pattern)\n", diff --git a/libavformat/internal.h b/libavformat/internal.h index da64c64..d7174c5 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -356,6 +356,24 @@ void ff_reduce_index(AVFormatContext *s, int stream_index); enum AVCodecID ff_guess_image2_codec(const char *filename);
/** + * Return in 'buf' the path with '%d' replaced by a number. + * + * Also handles the '%0nd' format where 'n' is the total number + * of digits and '%%'. + * Also handles the '%t' format where 't' is the timestamp. + * + * @param buf destination buffer + * @param buf_size destination buffer size + * @param path numbered sequence string + * @param number frame number + * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. + * @return 0 if OK, -1 on format error + */ +int av_get_frame_filename3(char *buf, int buf_size,
Since it's internal it needs to have an ff_ prefix, not av_.
OK hopefully fixed with the attached, thanks.
Ping...
ping2...
On 12/2/2016 10:06 PM, Roger Pack wrote:
On 11/25/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 11/18/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 11/15/16, James Almer <jamrial@gmail.com> wrote:
On 11/10/2016 4:26 PM, Roger Pack wrote:
On 11/1/16, James Almer <jamrial@gmail.com> wrote:
> On 11/1/2016 6:43 PM, James Almer wrote: >>> On 10/25/2016 9:38 PM, Roger Pack wrote: >>>>> From e8cac5c7de18766ce0f8f286f7dc140b82129df2 Mon Sep 17 >>>>> 00:00:00 >>>>> 2001 >>>>> From: rogerdpack <rogerpack2005@gmail.com> >>>>> Date: Tue, 25 Oct 2016 18:33:12 -0600 >>>>> Subject: [PATCH 1/2] img2 encoder: allow %t in filename, based >>>>> on >>>>> patch >>>>> from >>>>> Yuval Adam >>>>> >>>>> Signed-off-by: rogerdpack <rogerpack2005@gmail.com> >>>>> --- >>>>> doc/muxers.texi | 13 +++++++++++++ >>>>> libavformat/avformat.h | 3 ++- >>>>> libavformat/hlsenc.c | 6 +++--- >>>>> libavformat/img2enc.c | 6 ++++-- >>>>> libavformat/utils.c | 42 >>>>> ++++++++++++++++++++++++++++++++++++++---- >>>>> 5 files changed, 60 insertions(+), 10 deletions(-) >>>>> >>>>> diff --git a/doc/muxers.texi b/doc/muxers.texi >>>>> index 0d856db..0c3a198 100644 >>>>> --- a/doc/muxers.texi >>>>> +++ b/doc/muxers.texi >>>>> @@ -619,6 +619,12 @@ If the pattern contains "%d" or >>>>> "%0@var{N}d", >>>>> the >>>>> first filename of >>>>> the file list specified will contain the number 1, all the >>>>> following >>>>> numbers will be sequential. >>>>> >>>>> +If the pattern contains "%t", the frame's timestamps will be >>>>> inserted >>>>> +in the filename like "00.00.00.000" for hours, minutes, >>>>> seconds, >>>>> +and milliseconds. >>>>> + >>>>> +The "%t" and "%d" patterns may be used simultaneously. >>>>> + >>>>> The pattern may contain a suffix which is used to automatically >>>>> determine the format of the image files to write. >>>>> >>>>> @@ -664,6 +670,13 @@ can be used: >>>>> ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 >>>>> "%Y-%m-%d_%H-%M-%S.jpg" >>>>> @end example >>>>> >>>>> +The following example uses the timestamp parameter to generate >>>>> one >>>>> +image file per video frame from the input, and name it >>>>> including >>>>> its >>>>> original >>>>> +timestamp. >>>>> +@example >>>>> +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg >>>>> +@end example >>>>> + >>>>> @subsection Options >>>>> >>>>> @table @option >>>>> diff --git a/libavformat/avformat.h b/libavformat/avformat.h >>>>> index f9f4d72..7f39698 100644 >>>>> --- a/libavformat/avformat.h >>>>> +++ b/libavformat/avformat.h >>>>> @@ -2780,10 +2780,11 @@ void av_dump_format(AVFormatContext *ic, >>>>> * @param path numbered sequence string >>>>> * @param number frame number >>>>> * @param flags AV_FRAME_FILENAME_FLAGS_* >>>>> + * @param ts frame timestamp in AV_TIME_BASE fractional >>>>> seconds. >>>>> * @return 0 if OK, -1 on format error >>>>> */ >>>>> int av_get_frame_filename2(char *buf, int buf_size, >>>>> - const char *path, int number, int >>>>> flags); >>>>> + const char *path, int number, int >>>>> flags, >>>>> int64_t ts); >>> >>> Uhh, what? did you just break API modifying a public function? >>> > > For the record, this was reverted. > > Shouldn't be hard to solve, i think. Just add a new > ff_get_frame_filename() > function to internal.h with this new signature, at least for now and > for > this > feature, to avoid adding a third public function doing the same > thing > unless > absolutely necessary. OK see attached. Wasn't sure if I should duplicate docs or not, feel free to modify. Cheers! -roger-
0001-img2-encoder-allow-t-in-filepattern-based-on-patch-f.patch
From 8287f1ca543f764e9e88659ee5a07873860d607d Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Thu, 10 Nov 2016 12:24:49 -0700 Subject: [PATCH] img2 encoder: allow %t in filepattern, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 13 +++++++++++++ libavformat/img2enc.c | 8 +++++--- libavformat/internal.h | 18 ++++++++++++++++++ libavformat/utils.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 78 insertions(+), 6 deletions(-)
No hlsenc.c?
Yeah, good idea, moved them all to use the ff_get_frame_filename3 now just so people would realize the extra parameter is available.
diff --git a/doc/muxers.texi b/doc/muxers.texi index 806182a..670fcca 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -622,6 +622,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -667,6 +673,13 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example
+The following example uses the timestamp parameter to generate one +image file per video frame from the input, and name it including its original +timestamp. +@example +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg +@end example + @subsection Options
@table @option diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 1297b1a..651739e 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -80,10 +80,12 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) VideoMuxData *img = s->priv_data; AVIOContext *pb[4]; char filename[1024]; - AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + AVStream *stream = s->streams[ pkt->stream_index ]; + AVCodecParameters *par = stream->codecpar; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format); int i; int nb_renames = 0; + int64_t ts = av_rescale_q(pkt->pts, stream->time_base, AV_TIME_BASE_Q);
if (!img->is_pipe) { if (img->update) { @@ -97,9 +99,9 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_ERROR, "Could not get frame filename with strftime\n"); return AVERROR(EINVAL); } - } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, + } else if (av_get_frame_filename3(filename, sizeof(filename), img->path, img->img_number, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && + AV_FRAME_FILENAME_FLAGS_MULTIPLE, ts) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s' (either set updatefirst or use a pattern like %%03d within the filename pattern)\n", diff --git a/libavformat/internal.h b/libavformat/internal.h index da64c64..d7174c5 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -356,6 +356,24 @@ void ff_reduce_index(AVFormatContext *s, int stream_index); enum AVCodecID ff_guess_image2_codec(const char *filename);
/** + * Return in 'buf' the path with '%d' replaced by a number. + * + * Also handles the '%0nd' format where 'n' is the total number + * of digits and '%%'. + * Also handles the '%t' format where 't' is the timestamp. + * + * @param buf destination buffer + * @param buf_size destination buffer size + * @param path numbered sequence string + * @param number frame number + * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. + * @return 0 if OK, -1 on format error + */ +int av_get_frame_filename3(char *buf, int buf_size,
Since it's internal it needs to have an ff_ prefix, not av_.
OK hopefully fixed with the attached, thanks.
Ping...
ping2...
I said that if it's technically the same as the previously committed code then it should be good to go since it's already reviewed. Do you have write access, or should i push this?
On 12/2/16, James Almer <jamrial@gmail.com> wrote:
On 12/2/2016 10:06 PM, Roger Pack wrote:
On 11/25/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 11/18/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 11/15/16, James Almer <jamrial@gmail.com> wrote:
On 11/10/2016 4:26 PM, Roger Pack wrote:
On 11/1/16, James Almer <jamrial@gmail.com> wrote: >> On 11/1/2016 6:43 PM, James Almer wrote: >>>> On 10/25/2016 9:38 PM, Roger Pack wrote: >>>>>> From e8cac5c7de18766ce0f8f286f7dc140b82129df2 Mon Sep 17 >>>>>> 00:00:00 >>>>>> 2001 >>>>>> From: rogerdpack <rogerpack2005@gmail.com> >>>>>> Date: Tue, 25 Oct 2016 18:33:12 -0600 >>>>>> Subject: [PATCH 1/2] img2 encoder: allow %t in filename, based >>>>>> on >>>>>> patch >>>>>> from >>>>>> Yuval Adam >>>>>> >>>>>> Signed-off-by: rogerdpack <rogerpack2005@gmail.com> >>>>>> --- >>>>>> doc/muxers.texi | 13 +++++++++++++ >>>>>> libavformat/avformat.h | 3 ++- >>>>>> libavformat/hlsenc.c | 6 +++--- >>>>>> libavformat/img2enc.c | 6 ++++-- >>>>>> libavformat/utils.c | 42 >>>>>> ++++++++++++++++++++++++++++++++++++++---- >>>>>> 5 files changed, 60 insertions(+), 10 deletions(-) >>>>>> >>>>>> diff --git a/doc/muxers.texi b/doc/muxers.texi >>>>>> index 0d856db..0c3a198 100644 >>>>>> --- a/doc/muxers.texi >>>>>> +++ b/doc/muxers.texi >>>>>> @@ -619,6 +619,12 @@ If the pattern contains "%d" or >>>>>> "%0@var{N}d", >>>>>> the >>>>>> first filename of >>>>>> the file list specified will contain the number 1, all the >>>>>> following >>>>>> numbers will be sequential. >>>>>> >>>>>> +If the pattern contains "%t", the frame's timestamps will be >>>>>> inserted >>>>>> +in the filename like "00.00.00.000" for hours, minutes, >>>>>> seconds, >>>>>> +and milliseconds. >>>>>> + >>>>>> +The "%t" and "%d" patterns may be used simultaneously. >>>>>> + >>>>>> The pattern may contain a suffix which is used to automatically >>>>>> determine the format of the image files to write. >>>>>> >>>>>> @@ -664,6 +670,13 @@ can be used: >>>>>> ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 >>>>>> "%Y-%m-%d_%H-%M-%S.jpg" >>>>>> @end example >>>>>> >>>>>> +The following example uses the timestamp parameter to generate >>>>>> one >>>>>> +image file per video frame from the input, and name it >>>>>> including >>>>>> its >>>>>> original >>>>>> +timestamp. >>>>>> +@example >>>>>> +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg >>>>>> +@end example >>>>>> + >>>>>> @subsection Options >>>>>> >>>>>> @table @option >>>>>> diff --git a/libavformat/avformat.h b/libavformat/avformat.h >>>>>> index f9f4d72..7f39698 100644 >>>>>> --- a/libavformat/avformat.h >>>>>> +++ b/libavformat/avformat.h >>>>>> @@ -2780,10 +2780,11 @@ void av_dump_format(AVFormatContext *ic, >>>>>> * @param path numbered sequence string >>>>>> * @param number frame number >>>>>> * @param flags AV_FRAME_FILENAME_FLAGS_* >>>>>> + * @param ts frame timestamp in AV_TIME_BASE fractional >>>>>> seconds. >>>>>> * @return 0 if OK, -1 on format error >>>>>> */ >>>>>> int av_get_frame_filename2(char *buf, int buf_size, >>>>>> - const char *path, int number, int >>>>>> flags); >>>>>> + const char *path, int number, int >>>>>> flags, >>>>>> int64_t ts); >>>> >>>> Uhh, what? did you just break API modifying a public function? >>>> >> >> For the record, this was reverted. >> >> Shouldn't be hard to solve, i think. Just add a new >> ff_get_frame_filename() >> function to internal.h with this new signature, at least for now and >> for >> this >> feature, to avoid adding a third public function doing the same >> thing >> unless >> absolutely necessary. OK see attached. Wasn't sure if I should duplicate docs or not, feel free to modify. Cheers! -roger-
0001-img2-encoder-allow-t-in-filepattern-based-on-patch-f.patch
From 8287f1ca543f764e9e88659ee5a07873860d607d Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Thu, 10 Nov 2016 12:24:49 -0700 Subject: [PATCH] img2 encoder: allow %t in filepattern, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 13 +++++++++++++ libavformat/img2enc.c | 8 +++++--- libavformat/internal.h | 18 ++++++++++++++++++ libavformat/utils.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 78 insertions(+), 6 deletions(-)
No hlsenc.c?
Yeah, good idea, moved them all to use the ff_get_frame_filename3 now just so people would realize the extra parameter is available.
diff --git a/doc/muxers.texi b/doc/muxers.texi index 806182a..670fcca 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -622,6 +622,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -667,6 +673,13 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example
+The following example uses the timestamp parameter to generate one +image file per video frame from the input, and name it including its original +timestamp. +@example +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg +@end example + @subsection Options
@table @option diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 1297b1a..651739e 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -80,10 +80,12 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) VideoMuxData *img = s->priv_data; AVIOContext *pb[4]; char filename[1024]; - AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + AVStream *stream = s->streams[ pkt->stream_index ]; + AVCodecParameters *par = stream->codecpar; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format); int i; int nb_renames = 0; + int64_t ts = av_rescale_q(pkt->pts, stream->time_base, AV_TIME_BASE_Q);
if (!img->is_pipe) { if (img->update) { @@ -97,9 +99,9 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_ERROR, "Could not get frame filename with strftime\n"); return AVERROR(EINVAL); } - } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, + } else if (av_get_frame_filename3(filename, sizeof(filename), img->path, img->img_number, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && + AV_FRAME_FILENAME_FLAGS_MULTIPLE, ts) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s' (either set updatefirst or use a pattern like %%03d within the filename pattern)\n", diff --git a/libavformat/internal.h b/libavformat/internal.h index da64c64..d7174c5 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -356,6 +356,24 @@ void ff_reduce_index(AVFormatContext *s, int stream_index); enum AVCodecID ff_guess_image2_codec(const char *filename);
/** + * Return in 'buf' the path with '%d' replaced by a number. + * + * Also handles the '%0nd' format where 'n' is the total number + * of digits and '%%'. + * Also handles the '%t' format where 't' is the timestamp. + * + * @param buf destination buffer + * @param buf_size destination buffer size + * @param path numbered sequence string + * @param number frame number + * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. + * @return 0 if OK, -1 on format error + */ +int av_get_frame_filename3(char *buf, int buf_size,
Since it's internal it needs to have an ff_ prefix, not av_.
OK hopefully fixed with the attached, thanks.
Ping...
ping2...
I said that if it's technically the same as the previously committed code then it should be good to go since it's already reviewed.
Do you have write access, or should i push this?
I don't so please push it. Thanks! -roger-
On Mon, Dec 05, 2016 at 07:06:35AM -0700, Roger Pack wrote:
On 12/2/16, James Almer <jamrial@gmail.com> wrote:
On 12/2/2016 10:06 PM, Roger Pack wrote:
On 11/25/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 11/18/16, Roger Pack <rogerdpack2@gmail.com> wrote:
On 11/15/16, James Almer <jamrial@gmail.com> wrote:
On 11/10/2016 4:26 PM, Roger Pack wrote: > On 11/1/16, James Almer <jamrial@gmail.com> wrote: >>> On 11/1/2016 6:43 PM, James Almer wrote: >>>>> On 10/25/2016 9:38 PM, Roger Pack wrote: >>>>>>> From e8cac5c7de18766ce0f8f286f7dc140b82129df2 Mon Sep 17 >>>>>>> 00:00:00 >>>>>>> 2001 >>>>>>> From: rogerdpack <rogerpack2005@gmail.com> >>>>>>> Date: Tue, 25 Oct 2016 18:33:12 -0600 >>>>>>> Subject: [PATCH 1/2] img2 encoder: allow %t in filename, based >>>>>>> on >>>>>>> patch >>>>>>> from >>>>>>> Yuval Adam >>>>>>> >>>>>>> Signed-off-by: rogerdpack <rogerpack2005@gmail.com> >>>>>>> --- >>>>>>> doc/muxers.texi | 13 +++++++++++++ >>>>>>> libavformat/avformat.h | 3 ++- >>>>>>> libavformat/hlsenc.c | 6 +++--- >>>>>>> libavformat/img2enc.c | 6 ++++-- >>>>>>> libavformat/utils.c | 42 >>>>>>> ++++++++++++++++++++++++++++++++++++++---- >>>>>>> 5 files changed, 60 insertions(+), 10 deletions(-) >>>>>>> >>>>>>> diff --git a/doc/muxers.texi b/doc/muxers.texi >>>>>>> index 0d856db..0c3a198 100644 >>>>>>> --- a/doc/muxers.texi >>>>>>> +++ b/doc/muxers.texi >>>>>>> @@ -619,6 +619,12 @@ If the pattern contains "%d" or >>>>>>> "%0@var{N}d", >>>>>>> the >>>>>>> first filename of >>>>>>> the file list specified will contain the number 1, all the >>>>>>> following >>>>>>> numbers will be sequential. >>>>>>> >>>>>>> +If the pattern contains "%t", the frame's timestamps will be >>>>>>> inserted >>>>>>> +in the filename like "00.00.00.000" for hours, minutes, >>>>>>> seconds, >>>>>>> +and milliseconds. >>>>>>> + >>>>>>> +The "%t" and "%d" patterns may be used simultaneously. >>>>>>> + >>>>>>> The pattern may contain a suffix which is used to automatically >>>>>>> determine the format of the image files to write. >>>>>>> >>>>>>> @@ -664,6 +670,13 @@ can be used: >>>>>>> ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 >>>>>>> "%Y-%m-%d_%H-%M-%S.jpg" >>>>>>> @end example >>>>>>> >>>>>>> +The following example uses the timestamp parameter to generate >>>>>>> one >>>>>>> +image file per video frame from the input, and name it >>>>>>> including >>>>>>> its >>>>>>> original >>>>>>> +timestamp. >>>>>>> +@example >>>>>>> +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg >>>>>>> +@end example >>>>>>> + >>>>>>> @subsection Options >>>>>>> >>>>>>> @table @option >>>>>>> diff --git a/libavformat/avformat.h b/libavformat/avformat.h >>>>>>> index f9f4d72..7f39698 100644 >>>>>>> --- a/libavformat/avformat.h >>>>>>> +++ b/libavformat/avformat.h >>>>>>> @@ -2780,10 +2780,11 @@ void av_dump_format(AVFormatContext *ic, >>>>>>> * @param path numbered sequence string >>>>>>> * @param number frame number >>>>>>> * @param flags AV_FRAME_FILENAME_FLAGS_* >>>>>>> + * @param ts frame timestamp in AV_TIME_BASE fractional >>>>>>> seconds. >>>>>>> * @return 0 if OK, -1 on format error >>>>>>> */ >>>>>>> int av_get_frame_filename2(char *buf, int buf_size, >>>>>>> - const char *path, int number, int >>>>>>> flags); >>>>>>> + const char *path, int number, int >>>>>>> flags, >>>>>>> int64_t ts); >>>>> >>>>> Uhh, what? did you just break API modifying a public function? >>>>> >>> >>> For the record, this was reverted. >>> >>> Shouldn't be hard to solve, i think. Just add a new >>> ff_get_frame_filename() >>> function to internal.h with this new signature, at least for now and >>> for >>> this >>> feature, to avoid adding a third public function doing the same >>> thing >>> unless >>> absolutely necessary. > OK see attached. Wasn't sure if I should duplicate docs or not, feel > free to modify. > Cheers! > -roger- > > > 0001-img2-encoder-allow-t-in-filepattern-based-on-patch-f.patch > > > From 8287f1ca543f764e9e88659ee5a07873860d607d Mon Sep 17 00:00:00 2001 > From: rogerdpack <rogerpack2005@gmail.com> > Date: Thu, 10 Nov 2016 12:24:49 -0700 > Subject: [PATCH] img2 encoder: allow %t in filepattern, based on patch > from > Yuval Adam > > Signed-off-by: rogerdpack <rogerpack2005@gmail.com> > --- > doc/muxers.texi | 13 +++++++++++++ > libavformat/img2enc.c | 8 +++++--- > libavformat/internal.h | 18 ++++++++++++++++++ > libavformat/utils.c | 45 > ++++++++++++++++++++++++++++++++++++++++++--- > 4 files changed, 78 insertions(+), 6 deletions(-)
No hlsenc.c?
Yeah, good idea, moved them all to use the ff_get_frame_filename3 now just so people would realize the extra parameter is available.
> > diff --git a/doc/muxers.texi b/doc/muxers.texi > index 806182a..670fcca 100644 > --- a/doc/muxers.texi > +++ b/doc/muxers.texi > @@ -622,6 +622,12 @@ If the pattern contains "%d" or "%0@var{N}d", the > first filename of > the file list specified will contain the number 1, all the following > numbers will be sequential. > > +If the pattern contains "%t", the frame's timestamps will be inserted > +in the filename like "00.00.00.000" for hours, minutes, seconds, > +and milliseconds. > + > +The "%t" and "%d" patterns may be used simultaneously. > + > The pattern may contain a suffix which is used to automatically > determine the format of the image files to write. > > @@ -667,6 +673,13 @@ can be used: > ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 > "%Y-%m-%d_%H-%M-%S.jpg" > @end example > > +The following example uses the timestamp parameter to generate one > +image file per video frame from the input, and name it including its > original > +timestamp. > +@example > +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg > +@end example > + > @subsection Options > > @table @option > diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c > index 1297b1a..651739e 100644 > --- a/libavformat/img2enc.c > +++ b/libavformat/img2enc.c > @@ -80,10 +80,12 @@ static int write_packet(AVFormatContext *s, > AVPacket > *pkt) > VideoMuxData *img = s->priv_data; > AVIOContext *pb[4]; > char filename[1024]; > - AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; > + AVStream *stream = s->streams[ pkt->stream_index ]; > + AVCodecParameters *par = stream->codecpar; > const AVPixFmtDescriptor *desc = > av_pix_fmt_desc_get(par->format); > int i; > int nb_renames = 0; > + int64_t ts = av_rescale_q(pkt->pts, stream->time_base, > AV_TIME_BASE_Q); > > if (!img->is_pipe) { > if (img->update) { > @@ -97,9 +99,9 @@ static int write_packet(AVFormatContext *s, AVPacket > *pkt) > av_log(s, AV_LOG_ERROR, "Could not get frame filename > with strftime\n"); > return AVERROR(EINVAL); > } > - } else if (av_get_frame_filename2(filename, sizeof(filename), > img->path, > + } else if (av_get_frame_filename3(filename, sizeof(filename), > img->path, > img->img_number, > - > AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && > + > AV_FRAME_FILENAME_FLAGS_MULTIPLE, ts) < 0 && > img->img_number > 1) { > av_log(s, AV_LOG_ERROR, > "Could not get frame filename number %d from > pattern > '%s' (either set updatefirst or use a pattern like %%03d within the > filename pattern)\n", > diff --git a/libavformat/internal.h b/libavformat/internal.h > index da64c64..d7174c5 100644 > --- a/libavformat/internal.h > +++ b/libavformat/internal.h > @@ -356,6 +356,24 @@ void ff_reduce_index(AVFormatContext *s, int > stream_index); > enum AVCodecID ff_guess_image2_codec(const char *filename); > > /** > + * Return in 'buf' the path with '%d' replaced by a number. > + * > + * Also handles the '%0nd' format where 'n' is the total number > + * of digits and '%%'. > + * Also handles the '%t' format where 't' is the timestamp. > + * > + * @param buf destination buffer > + * @param buf_size destination buffer size > + * @param path numbered sequence string > + * @param number frame number > + * @param flags AV_FRAME_FILENAME_FLAGS_* > + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. > + * @return 0 if OK, -1 on format error > + */ > +int av_get_frame_filename3(char *buf, int buf_size,
Since it's internal it needs to have an ff_ prefix, not av_.
OK hopefully fixed with the attached, thanks.
Ping...
ping2...
I said that if it's technically the same as the previously committed code then it should be good to go since it's already reviewed.
Do you have write access, or should i push this?
I don't so please push it.
if you want write access, send me your public ssh key, you are in MAINTAINERs [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB No snowflake in an avalanche ever feels responsible. -- Voltaire
On 11/1/16, James Almer <jamrial@gmail.com> wrote:
On 10/25/2016 9:38 PM, Roger Pack wrote:
From e8cac5c7de18766ce0f8f286f7dc140b82129df2 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Tue, 25 Oct 2016 18:33:12 -0600 Subject: [PATCH 1/2] img2 encoder: allow %t in filename, based on patch from Yuval Adam
Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- doc/muxers.texi | 13 +++++++++++++ libavformat/avformat.h | 3 ++- libavformat/hlsenc.c | 6 +++--- libavformat/img2enc.c | 6 ++++-- libavformat/utils.c | 42 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 60 insertions(+), 10 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index 0d856db..0c3a198 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -619,6 +619,12 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential.
+If the pattern contains "%t", the frame's timestamps will be inserted +in the filename like "00.00.00.000" for hours, minutes, seconds, +and milliseconds. + +The "%t" and "%d" patterns may be used simultaneously. + The pattern may contain a suffix which is used to automatically determine the format of the image files to write.
@@ -664,6 +670,13 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example
+The following example uses the timestamp parameter to generate one +image file per video frame from the input, and name it including its original +timestamp. +@example +ffmpeg -i in.avi -vsync vfr -copyts img-%t.jpg +@end example + @subsection Options
@table @option diff --git a/libavformat/avformat.h b/libavformat/avformat.h index f9f4d72..7f39698 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2780,10 +2780,11 @@ void av_dump_format(AVFormatContext *ic, * @param path numbered sequence string * @param number frame number * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in AV_TIME_BASE fractional seconds. * @return 0 if OK, -1 on format error */ int av_get_frame_filename2(char *buf, int buf_size, - const char *path, int number, int flags); + const char *path, int number, int flags, int64_t ts);
Uhh, what? did you just break API modifying a public function?
Yes, it was a recently added method so I hoped to get it "included" before a version was released (but it took so long it maybe missed a deadline...?) Cheers! -roger-
participants (4)
-
James Almer -
Michael Niedermayer -
Roger Pack -
Yuval Adam