> 在 2018年8月15日,下午6:37,Ronak Patel <ronak2...@yahoo.com> 写道:
> 
>> 
>> On Aug 14, 2018, at 10:57 PM, Liu Steven <l...@chinaffmpeg.org> wrote:
>> 
>> 
>> 
>>> 在 2018年8月15日,上午9:31,Ronak <ronak2121-at-yahoo....@ffmpeg.org> 写道:
>>> 
>>> From: "Ronak Patel" <ronak2121@ <mailto:ronak2...@yahoo.com>yahoo.com>
>>> 
>>> This fixes the creation of the hls manifest in hlsenc.c by writing the 
>>> entire manifest at the end for VOD playlists. Live & Event Playlists are 
>>> unaffected.
>>> This also fixes the behavior with HLS_TEMP_FILE to work correctly when 
>>> -hlsflags temp_file is specified, instead of always relying on use_rename, 
>>> which caused these problems.
>>> 
>>> Files that would previously take over a week to fragment now take 1 minute 
>>> on the same hardware. This was a 153 hour audio file (2.2GB of audio).
>>> 
>>> Signed-off-by: Ronak Patel <ronak2...@yahoo.com 
>>> <mailto:ronak2...@yahoo.com>>
>>> ---
>>> libavformat/hlsenc.c | 51 
>>> ++++++++++++++++++++++++++++++++++++---------------
>>> 1 file changed, 36 insertions(+), 15 deletions(-)
>>> 
>>> diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
>>> index b5644f0..7933b79 100644
>>> --- a/libavformat/hlsenc.c
>>> +++ b/libavformat/hlsenc.c
>>> @@ -1168,7 +1168,6 @@ static int hls_rename_temp_file(AVFormatContext *s, 
>>> AVFormatContext *oc)
>>>       return AVERROR(ENOMEM);
>>>   final_filename[len-4] = '\0';
>>>   ret = ff_rename(oc->url, final_filename, s);
>>> -    oc->url[len-4] = '\0';
>>>   av_freep(&final_filename);
>>>   return ret;
>>> }
>>> @@ -1374,7 +1373,7 @@ static int hls_window(AVFormatContext *s, int last, 
>>> VariantStream *vs)
>>>   char temp_filename[1024];
>>>   int64_t sequence = FFMAX(hls->start_sequence, vs->sequence - 
>>> vs->nb_entries);
>>>   const char *proto = avio_find_protocol_name(s->url);
>>> -    int use_rename = proto && !strcmp(proto, "file");
>>> +    int use_temp_file = proto && !strcmp(proto, "file") && (s->flags & 
>>> HLS_TEMP_FILE);
>>>   static unsigned warned_non_file;
>>>   char *key_uri = NULL;
>>>   char *iv_string = NULL;
>>> @@ -1397,11 +1396,11 @@ static int hls_window(AVFormatContext *s, int last, 
>>> VariantStream *vs)
>>>       hls->version = 7;
>>>   }
>>> -    if (!use_rename && !warned_non_file++)
>>> +    if (!use_temp_file && !warned_non_file++)
>>>       av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this 
>>> may lead to races and temporary partial files\n");
>>>   set_http_options(s, &options, hls);
>>> -    snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : 
>>> "%s", vs->m3u8_name);
>>> +    snprintf(temp_filename, sizeof(temp_filename), use_temp_file ? 
>>> "%s.tmp" : "%s", vs->m3u8_name);
>>>   if ((ret = hlsenc_io_open(s, &hls->m3u8_out, temp_filename, &options)) < 
>>> 0)
>>>       goto fail;
>>> @@ -1472,8 +1471,8 @@ fail:
>>>   av_dict_free(&options);
>>>   hlsenc_io_close(s, &hls->m3u8_out, temp_filename);
>>>   hlsenc_io_close(s, &hls->sub_m3u8_out, vs->vtt_m3u8_name);
>>> -    if (ret >= 0 && use_rename)
>>> -        ff_rename(temp_filename, vs->m3u8_name, s);
>>> +    if (use_temp_file)
>>> +        ff_rename(temp_filename, vs->m3u8_name, s);
>>>   if (ret >= 0 && hls->master_pl_name)
>>>       if (create_master_playlist(s, vs) < 0)
>>> @@ -1488,6 +1487,8 @@ static int hls_start(AVFormatContext *s, 
>>> VariantStream *vs)
>>>   AVFormatContext *oc = vs->avf;
>>>   AVFormatContext *vtt_oc = vs->vtt_avf;
>>>   AVDictionary *options = NULL;
>>> +    const char *proto = avio_find_protocol_name(s->url);
>>> +    int use_temp_file = proto && !strcmp(proto, "file") && (s->flags & 
>>> HLS_TEMP_FILE);
>>>   char *filename, iv_string[KEYSIZE*2 + 1];
>>>   int err = 0;
>>> @@ -1583,7 +1584,7 @@ static int hls_start(AVFormatContext *s, 
>>> VariantStream *vs)
>>>   set_http_options(s, &options, c);
>>> -    if (c->flags & HLS_TEMP_FILE) {
>>> +    if (use_temp_file) {
>>>       char *new_name = av_asprintf("%s.tmp", oc->url);
>>>       if (!new_name)
>>>           return AVERROR(ENOMEM);
>>> @@ -2145,6 +2146,8 @@ static int hls_write_packet(AVFormatContext *s, 
>>> AVPacket *pkt)
>>>   int ret = 0, can_split = 1, i, j;
>>>   int stream_index = 0;
>>>   int range_length = 0;
>>> +    const char *proto = avio_find_protocol_name(s->url);
>>> +    int use_temp_file = proto && !strcmp(proto, "file") && (s->flags & 
>>> HLS_TEMP_FILE);
>>>   uint8_t *buffer = NULL;
>>>   VariantStream *vs = NULL;
>>>   AVDictionary *options = NULL;
>>> @@ -2214,10 +2217,10 @@ static int hls_write_packet(AVFormatContext *s, 
>>> AVPacket *pkt)
>>>   }
>>> +    char *old_filename = NULL;
>>>   if (vs->packets_written && can_split && av_compare_ts(pkt->pts - 
>>> vs->start_pts, st->time_base,
>>>                                                         end_pts, 
>>> AV_TIME_BASE_Q) >= 0) {
>>>       int64_t new_start_pos;
>>> -        char *old_filename = NULL;
>>>       int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || 
>>> (hls->max_seg_size > 0);
>>>       av_write_frame(vs->avf, NULL); /* Flush any buffered data */
>>> @@ -2253,11 +2256,13 @@ static int hls_write_packet(AVFormatContext *s, 
>>> AVPacket *pkt)
>>>               hlsenc_io_close(s, &vs->vtt_avf->pb, vs->vtt_avf->url);
>>>           }
>>>       }
>>> -        if ((hls->flags & HLS_TEMP_FILE) && oc->url[0]) {
>>> +
>>> +        // look to rename the asset name
>>> +        if (use_temp_file && oc->url[0]) {
>>>           if (!(hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size <= 0))
>>> -                if ((vs->avf->oformat->priv_class && vs->avf->priv_data) 
>>> && hls->segment_type != SEGMENT_TYPE_FMP4)
>>> -                    av_opt_set(vs->avf->priv_data, "mpegts_flags", 
>>> "resend_headers", 0);
>>> -            hls_rename_temp_file(s, oc);
>>> +                if ((vs->avf->oformat->priv_class && vs->avf->priv_data) 
>>> && hls->segment_type != SEGMENT_TYPE_FMP4) {
>>> +                    av_opt_set(vs->avf->priv_data, "mpegts_flags", 
>>> "resend_headers", 0);
>>> +                }
>>>       }
>>>       if (vs->fmp4_init_mode) {
>>> @@ -2286,6 +2291,17 @@ static int hls_write_packet(AVFormatContext *s, 
>>> AVPacket *pkt)
>>>                   return ret;
>>>               }
>>>               ff_format_io_close(s, &vs->out);
>>> +
>>> +                // rename that segment from .tmp to the real one
>>> +                if (use_temp_file && oc->url[0]) {
>>> +                    hls_rename_temp_file(s, oc);
>>> +                    av_free(old_filename);
>>> +                    old_filename = av_strdup(vs->avf->url);
>>> +
>>> +                    if (!old_filename) {
>>> +                        return AVERROR(ENOMEM);
>>> +                    }
>>> +                }
>>>           }
>>>       }
>>> @@ -2334,10 +2350,12 @@ static int hls_write_packet(AVFormatContext *s, 
>>> AVPacket *pkt)
>>>           return ret;
>>>       }
>>> -        if (!vs->fmp4_init_mode || byterange_mode)
>> why do you remove this line?
> 
> Because the above code sets fmp4_init_mode to 0 and this is always true. I 
> tested mpegts and fmp4 in single file and multiple file modes and this is 
> always true.
There have a logic:

 771     if (hls->segment_type == SEGMENT_TYPE_FMP4) {
 772         if (hls->max_seg_size > 0) {
 773             av_log(s, AV_LOG_WARNING, "Multi-file byterange mode is 
currently unsupported in the HLS muxer.\n");
 774             return AVERROR_PATCHWELCOME;
 775         }
 776
 777         vs->packets_written = 0;
 778         vs->init_range_length = 0;
 779         vs->fmp4_init_mode = !byterange_mode;

> 
>>> +        // if we're building a VOD playlist, skip writing the manifest 
>>> multiple times, and just wait until the end
>>> +        if (hls->pl_type != PLAYLIST_TYPE_VOD) {
>> maybe your mean is just write one time when PLAYLIST_TYPE_VOD, that is 
>> happen at the end of the full list, is that right?
> 
> Yes. Like I mentioned before there is no need to refresh the whole file every 
> single time.
> 
> This is not the best fix in my opinion either but it is the simplest. The 
> best way would be to split the code based on the playlist type so it was 
> easier to follow. This is altogether confusing code.
> 
>>>           if ((ret = hls_window(s, 0, vs)) < 0) {
>>>               return ret;
>>>           }
>>> +        }
>>>   }
>>>   vs->packets_written++;
>>> @@ -2352,6 +2370,8 @@ static int hls_write_trailer(struct AVFormatContext 
>>> *s)
>>>   AVFormatContext *oc = NULL;
>>>   AVFormatContext *vtt_oc = NULL;
>>>   char *old_filename = NULL;
>>> +    const char *proto = avio_find_protocol_name(s->url);
>>> +    int use_temp_file = proto && !strcmp(proto, "file") && (s->flags & 
>>> HLS_TEMP_FILE);
>>>   int i;
>>>   int ret = 0;
>>>   VariantStream *vs = NULL;
>>> @@ -2394,8 +2414,9 @@ failed:
>>>           if (hls->segment_type != SEGMENT_TYPE_FMP4)
>>>               ff_format_io_close(s, &oc->pb);
>>> -            if ((hls->flags & HLS_TEMP_FILE) && oc->url[0]) {
>>> -                hls_rename_temp_file(s, oc);
>>> +            // rename that segment from .tmp to the real one
>>> +            if (use_temp_file && oc->url[0] && !(hls->flags & 
>>> HLS_SINGLE_FILE)) {
>>> +                hls_rename_temp_file(s, oc);
>>>               av_free(old_filename);
>>>               old_filename = av_strdup(vs->avf->url);
>>> -- 
>>> 2.6.3
>>> _______________________________________________
>>> ffmpeg-devel mailing list
>>> ffmpeg-devel@ffmpeg.org
>>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> 
>> 
>> 
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel



_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to