avformat/hlsenc: fix hls_flags temp_file bug
authorSteven Liu <lq@chinaffmpeg.org>
Sat, 25 Feb 2017 02:59:05 +0000 (10:59 +0800)
committerSteven Liu <lq@chinaffmpeg.org>
Sat, 25 Feb 2017 02:59:05 +0000 (10:59 +0800)
refer to ticket id: #6170

rename file from temp to origin name after complete current segment

Reviewed-by: Aman Gupta <ffmpeg@tmm1.net>
Signed-off-by: Steven Liu <lq@chinaffmpeg.org>
libavformat/hlsenc.c

index 86a3b05..0238705 100644 (file)
@@ -691,6 +691,17 @@ static void write_m3u8_head_block(HLSContext *hls, AVIOContext *out, int version
     av_log(hls, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
 }
 
+static void hls_rename_temp_file(AVFormatContext *s, AVFormatContext *oc)
+{
+    size_t len = strlen(oc->filename);
+    char final_filename[sizeof(oc->filename)];
+
+    av_strlcpy(final_filename, oc->filename, len);
+    final_filename[len-4] = '\0';
+    ff_rename(oc->filename, final_filename, s);
+    oc->filename[len-4] = '\0';
+}
+
 static int hls_window(AVFormatContext *s, int last)
 {
     HLSContext *hls = s->priv_data;
@@ -833,15 +844,6 @@ static int hls_start(AVFormatContext *s)
     char *filename, iv_string[KEYSIZE*2 + 1];
     int err = 0;
 
-    if ((c->flags & HLS_TEMP_FILE) && oc->filename[0] != 0) {
-        size_t len = strlen(oc->filename);
-        char final_filename[sizeof(oc->filename)];
-        av_strlcpy(final_filename, oc->filename, len);
-        final_filename[len-4] = '\0';
-        ff_rename(oc->filename, final_filename, s);
-        oc->filename[len-4] = '\0';
-    }
-
     if (c->flags & HLS_SINGLE_FILE) {
         av_strlcpy(oc->filename, c->basename,
                    sizeof(oc->filename));
@@ -1325,6 +1327,17 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
 
         new_start_pos = avio_tell(hls->avf->pb);
         hls->size = new_start_pos - hls->start_pos;
+
+        if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) {
+            if (!(hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size <= 0))
+                if (hls->avf->oformat->priv_class && hls->avf->priv_data)
+                    av_opt_set(hls->avf->priv_data, "mpegts_flags", "resend_headers", 0);
+            ff_format_io_close(s, &oc->pb);
+            if (hls->vtt_avf)
+                ff_format_io_close(s, &hls->vtt_avf->pb);
+            hls_rename_temp_file(s, oc);
+        }
+
         ret = hls_append_segment(s, hls, hls->duration, hls->start_pos, hls->size);
         hls->start_pos = new_start_pos;
         if (ret < 0) {
@@ -1336,21 +1349,14 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
         hls->duration = 0;
 
         if (hls->flags & HLS_SINGLE_FILE) {
-            if (hls->avf->oformat->priv_class && hls->avf->priv_data)
-                av_opt_set(hls->avf->priv_data, "mpegts_flags", "resend_headers", 0);
             hls->number++;
         } else if (hls->max_seg_size > 0) {
-            if (hls->avf->oformat->priv_class && hls->avf->priv_data)
-                av_opt_set(hls->avf->priv_data, "mpegts_flags", "resend_headers", 0);
             if (hls->start_pos >= hls->max_seg_size) {
                 hls->sequence++;
-                ff_format_io_close(s, &oc->pb);
                 if ((hls->flags & (HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION)) &&
                      strlen(hls->current_segment_final_filename_fmt)) {
                     ff_rename(old_filename, hls->avf->filename, hls);
                 }
-                if (hls->vtt_avf)
-                    ff_format_io_close(s, &hls->vtt_avf->pb);
                 ret = hls_start(s);
                 hls->start_pos = 0;
                 /* When split segment by byte, the duration is short than hls_time,
@@ -1359,13 +1365,10 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
             }
             hls->number++;
         } else {
-            ff_format_io_close(s, &oc->pb);
             if ((hls->flags & (HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION)) &&
                 strlen(hls->current_segment_final_filename_fmt)) {
                 ff_rename(old_filename, hls->avf->filename, hls);
             }
-            if (hls->vtt_avf)
-                ff_format_io_close(s, &hls->vtt_avf->pb);
 
             ret = hls_start(s);
         }
@@ -1402,6 +1405,11 @@ static int hls_write_trailer(struct AVFormatContext *s)
     if (oc->pb) {
         hls->size = avio_tell(hls->avf->pb) - hls->start_pos;
         ff_format_io_close(s, &oc->pb);
+
+        if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) {
+            hls_rename_temp_file(s, oc);
+        }
+
         /* after av_write_trailer, then duration + 1 duration per packet */
         hls_append_segment(s, hls, hls->duration + hls->dpp, hls->start_pos, hls->size);
     }
@@ -1411,15 +1419,6 @@ static int hls_write_trailer(struct AVFormatContext *s)
          ff_rename(old_filename, hls->avf->filename, hls);
     }
 
-    if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0] != 0) {
-        size_t len = strlen(oc->filename);
-        char final_filename[sizeof(oc->filename)];
-        av_strlcpy(final_filename, oc->filename, len);
-        final_filename[len-4] = '\0';
-        ff_rename(oc->filename, final_filename, s);
-        oc->filename[len-4] = '\0';
-    }
-
     if (vtt_oc) {
         if (vtt_oc->pb)
             av_write_trailer(vtt_oc);