[FFmpeg-devel] [PATCH] resend: add segment_path for save segment movie

Steven Liu lingjiujianke at gmail.com
Sun Oct 27 15:55:57 CET 2013


Create video file in segment_path, and *DO NOT WANT* write the path into the
list file, use "-segment_path path" can do it. If *WANT* write the path into the list, 
*DO NOT USE* "-segment_path path".

for example:
[root at localhost /home/steven/ffmpeg]$ ./ffmpeg -i ../yedian.avi -preset ultrafast -vcodec libx264 -vprofile baseline -vlevel 1.0  -s 640x480 -b:v 800k -r 15  -pix_fmt yuv420p -acodec copy -strict -2 -f segment -segment_format mpegts -segment_time 10 -segment_list /usr/local/nginx/html/a.m3u8 -segment_list_flags live -map 0:0 -map 0:1 -flags -global_header video-%d.ts

Then the file will create at current directory, and the list file will create
at /usr/local/nginx/html/, but the list file context is
[root at localhost /home/steven/ffmpeg]$ cat /usr/local/nginx/html/a.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:NO
#EXT-X-TARGETDURATION:17
#EXTINF:16.680000,
video-0.ts
#EXTINF:16.669333,
video-1.ts
#EXTINF:16.682667,
video-2.ts
#EXTINF:16.672000,
video-3.ts
#EXT-X-ENDLIST
[root at localhost /home/steven/ffmpeg]$ ls /usr/local/nginx/html/
a.m3u8
[root at localhost /home/steven/ffmpeg]$ ls
video-0.ts  video-1.ts  video-2.ts  video-3.ts
[root at localhost /home/steven/ffmpeg]$

And other ways:
[root at localhost /home/steven/ffmpeg]$ ./ffmpeg -i ../yedian.avi -preset ultrafast -vcodec libx264 -vprofile baseline -vlevel 1.0  -s 640x480 -b:v 800k -r 15  -pix_fmt yuv420p -acodec copy -strict -2 -f segment -segment_format mpegts -segment_time 10 -segment_list /usr/local/nginx/html/a.m3u8 -segment_list_flags live -map 0:0 -map 0:1 -flags -global_header /usr/local/nginx/html/video-%d.ts

The list context is
[root at localhost /home/steven/ffmpeg]$ cat /usr/local/nginx/html/a.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:NO
#EXT-X-TARGETDURATION:17
#EXTINF:16.680000,
/usr/local/nginx/html/video-0.ts
#EXTINF:16.669333,
/usr/local/nginx/html/video-1.ts
#EXTINF:16.682667,
/usr/local/nginx/html/video-2.ts
#EXTINF:16.672000,
/usr/local/nginx/html/video-3.ts
#EXTINF:16.685333,
#EXT-X-ENDLIST
[root at localhost /home/steven/ffmpeg]$ ls /usr/local/nginx/html/
a.m3u8  video-0.ts  video-1.ts  video-2.ts  video-3.ts

But the nginx server root is /usr/local/nginx/html, so the list context segment list is *WRONG*

So use this patch can create segment file in the directory at the
/usr/local/nginx/html, and make the list context:
[root at localhost /home/steven/ffmpeg]$ cat /usr/local/nginx/html/a.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:NO
#EXT-X-TARGETDURATION:17
#EXTINF:16.680000,
video-0.ts
#EXTINF:16.669333,
video-1.ts
#EXTINF:16.682667,
video-2.ts
#EXTINF:16.672000,
video-3.ts
#EXT-X-ENDLIST
[root at localhost /home/steven/ffmpeg]$ ls /usr/local/nginx/html/
a.m3u8  video-0.ts  video-1.ts  video-2.ts  video-3.ts

Now the segment list is *RIGHT*


Signed-off-by: Steven Liu <lingjiujianke at gmail.com>

---
libavformat/segment.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/libavformat/segment.c b/libavformat/segment.c
index 05e29d4..c0e3ca5 100644
--- a/libavformat/segment.c
+++ b/libavformat/segment.c
@@ -76,6 +76,8 @@ typedef struct {
    AVIOContext *list_pb;  ///< list file put-byte context
    char *time_str;        ///< segment duration specification string
    int64_t time;          ///< segment duration
+  char *path;            ///< parent path for segment create
+  char *seg_file_path;   ///< segment file create full path

    char *times_str;       ///< segment times specification string
    int64_t *times;        ///< list of segment interval specification
@@ -167,6 +169,14 @@ static int set_segment_filename(AVFormatContext *s)
        return AVERROR(EINVAL);
    }
    av_strlcpy(seg->cur_entry.filename, oc->filename, sizeof(seg->cur_entry.filename));
+
+  /* If no -segment_path option, use the oc->filename */
+  if (!seg->path) {
+      seg->seg_file_path = av_asprintf("%s", oc->filename);
+  } else {
+      seg->seg_file_path = av_asprintf("%s/%s", seg->path, oc->filename);
+  }
+
    return 0;
}

@@ -188,7 +198,7 @@ static int segment_start(AVFormatContext *s, int write_header)
    if ((err = set_segment_filename(s)) < 0)
        return err;

-   if ((err = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
+  if ((err = avio_open2(&oc->pb, seg->seg_file_path, AVIO_FLAG_WRITE,
                          &s->interrupt_callback, NULL)) < 0)
        return err;

@@ -599,7 +609,7 @@ static int seg_write_header(AVFormatContext *s)
        goto fail;

    if (seg->write_header_trailer) {
-        if ((ret = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
+       if ((ret = avio_open2(&oc->pb, seg->seg_file_path, AVIO_FLAG_WRITE,
                              &s->interrupt_callback, NULL)) < 0)
            goto fail;
    } else {
@@ -779,6 +789,7 @@ static const AVOption options[] = {
    { "segment_time_delta","set approximation value used for the segment times", OFFSET(time_delta), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, 0, E },
    { "segment_times",     "set segment split time points",              OFFSET(times_str),AV_OPT_TYPE_STRING,{.str = NULL},  0, 0,       E },
    { "segment_frames",    "set segment split frame numbers",            OFFSET(frames_str),AV_OPT_TYPE_STRING,{.str = NULL},  0, 0,       E },
+  { "segment_path",    "set segment file created path",            OFFSET(path),AV_OPT_TYPE_STRING,{.str = NULL}, 0, 0,       E },
    { "segment_wrap",      "set number after which the index wraps",     OFFSET(segment_idx_wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
    { "segment_start_number", "set the sequence number of the first segment", OFFSET(segment_idx), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },

--
1.7.12.4 (Apple Git-37)


Steven Liu


More information about the ffmpeg-devel mailing list