From: Marcus Johansson <mar...@compuccino.com> Added the option to extract images with timecode as token The '%t' parameter is now supported for for images sequences just like the '%d' param When using '%t', images will have HH.MM.SS.XXX appended. Minor changes were made to the code by Marcus Johansson.
See https://trac.ffmpeg.org/ticket/1452 for more details Signed-off-by: Alex Mi <magixx2...@gmail.com> --- doc/muxers.texi | 3 +++ libavformat/avformat.h | 3 ++- libavformat/img2enc.c | 8 +++++--- libavformat/utils.c | 31 +++++++++++++++++++++++++++---- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index e77055e7ef..91997bd4fa 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -1384,6 +1384,9 @@ 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 can also contain "%t" which writes out the timestamp of the +frame in the format "HH.mm.ss.fff" + 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 cd7b0d941c..513de9e477 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2602,10 +2602,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 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/img2enc.c b/libavformat/img2enc.c index 7b5133d300..55dca272ea 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -131,9 +131,11 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) AVIOContext *pb[4] = {0}; char filename[1024]; AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + AVStream *stream = s->streams[ pkt->stream_index ]; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format); int ret, i; int nb_renames = 0; + int64_t ts = av_rescale_q(pkt->pts, stream->time_base, AV_TIME_BASE_Q); AVDictionary *options = NULL; if (img->update) { @@ -148,13 +150,13 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(EINVAL); } } else if (img->frame_pts) { - if (av_get_frame_filename2(filename, sizeof(filename), img->path, pkt->pts, AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + if (av_get_frame_filename2(filename, sizeof(filename), img->path, pkt->pts, AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(s, AV_LOG_ERROR, "Cannot write filename by pts of the frames."); return AVERROR(EINVAL); } } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, - img->img_number, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && + img->img_number, 0, + ts) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s'. " diff --git a/libavformat/utils.c b/libavformat/utils.c index 0df14682a4..d2e7cb7d34 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -4589,15 +4589,17 @@ uint64_t ff_parse_ntp_time(uint64_t ntp_ts) return (sec * 1000000) + usec; } -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') @@ -4629,6 +4631,27 @@ 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 (percentd_found) + goto fail; + if (ts < 0) + goto fail; + percentt_found = 1; + ms = (ts/1000)%1000; + ts /= AV_TIME_BASE; + secs = ts % 60; + ts /= 60; + mins = ts % 60; + ts /= 60; + hours = ts; + snprintf(buf1, sizeof(buf1), + "%02d.%02d.%02d.%03d", hours, mins, secs, ms); + len = strlen(buf1); + if ((q - buf + len) > buf_size - 1) + goto fail; + memcpy(q, buf1, len); + q += len; + break; default: goto fail; } @@ -4638,7 +4661,7 @@ addchar: *q++ = c; } } - if (!percentd_found) + if (!(percentd_found || percentt_found)) goto fail; *q = '\0'; return 0; @@ -4649,7 +4672,7 @@ fail: 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); + return av_get_frame_filename2(buf, buf_size, path, number, 0, 0); } void av_url_split(char *proto, int proto_size, -- 2.32.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".