[FFmpeg-devel] [PATCH 1/2] img2: added support for %t output pattern

Yuval Adam yuv.adm at gmail.com
Wed Jan 4 13:47:44 CET 2012


From: Yuval Adam <yuv.adm at 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 at 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 at 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


More information about the ffmpeg-devel mailing list