From patchwork Fri Aug 23 07:05:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Liu X-Patchwork-Id: 14675 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id EF8D3447B9C for ; Fri, 23 Aug 2019 10:06:06 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id CC69F68A988; Fri, 23 Aug 2019 10:06:06 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from smtpbgeu2.qq.com (smtpbgeu2.qq.com [18.194.254.142]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id EEF586800C3 for ; Fri, 23 Aug 2019 10:05:59 +0300 (EEST) X-QQ-mid: bizesmtp12t1566543937t6pfwo9e Received: from localhost (unknown [47.90.47.25]) by esmtp6.qq.com (ESMTP) with id ; Fri, 23 Aug 2019 15:05:36 +0800 (CST) X-QQ-SSF: 01100000002000K0ZQF1B00A0000000 X-QQ-FEAT: LeopHTht9Rn6iJmBFJQF/wHpQ8O5nAdGOHIesqGse+qyDZPLIG5ZM2pzHXDM+ FZ+DMkgqLADbax2zDP0qtvYwRztmrO+bFXPQB3eNcKOtqsGd6PaUElnyc0i0+gLLHVOvF9O XwTDyv1/yo13BqbqNQsq2UwVHjb9EpETN2fGYzVXoWhRNs9ll892jCeb8a2mcaGsG2no9Zt zuyeRMZ33dves0GkzTAIZZWp2zyzxA/VIIx3fMjxjQ1b0o51a5x5u1bpZflJmahJmT+Jmys otPjROHCtzW9OtRW3CPq9bjihr86QC1Zsm4ohJHjwaQPI+ X-QQ-GoodBg: 0 From: Steven Liu To: ffmpeg-devel@ffmpeg.org Date: Fri, 23 Aug 2019 15:05:35 +0800 Message-Id: <20190823070535.32277-1-lq@chinaffmpeg.org> X-Mailer: git-send-email 2.10.1.382.ga23ca1b.dirty X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:chinaffmpeg.org:qybgforeign:qybgforeign4 X-QQ-Bgrelay: 1 Subject: [FFmpeg-devel] [PATCH] avformat/hlsenc: reopen new http session for http_persistent when upload file failed X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Steven Liu MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" fix ticket: 7975 Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 67 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 18173cdce1..26e0f3819b 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -118,6 +118,7 @@ typedef struct VariantStream { AVIOContext *out; int packets_written; int init_range_length; + uint8_t *temp_buffer; AVFormatContext *avf; AVFormatContext *vtt_avf; @@ -262,11 +263,12 @@ static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename, return err; } -static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) { +static int hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) { HLSContext *hls = s->priv_data; int http_base_proto = filename ? ff_is_http_proto(filename) : 0; + int ret = 0; if (!*pb) - return; + return ret; if (!http_base_proto || !hls->http_persistent || hls->key_info_file || hls->encrypt) { ff_format_io_close(s, pb); #if CONFIG_HTTP_PROTOCOL @@ -274,9 +276,10 @@ static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename URLContext *http_url_context = ffio_geturlcontext(*pb); av_assert0(http_url_context); avio_flush(*pb); - ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE); + ret = ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE); #endif } + return ret; } static void set_http_options(AVFormatContext *s, AVDictionary **options, HLSContext *c) @@ -447,7 +450,6 @@ static void write_styp(AVIOContext *pb) static int flush_dynbuf(VariantStream *vs, int *range_length) { AVFormatContext *ctx = vs->avf; - uint8_t *buffer; if (!ctx->pb) { return AVERROR(EINVAL); @@ -458,15 +460,20 @@ static int flush_dynbuf(VariantStream *vs, int *range_length) avio_flush(ctx->pb); // write out to file - *range_length = avio_close_dyn_buf(ctx->pb, &buffer); + *range_length = avio_close_dyn_buf(ctx->pb, &vs->temp_buffer); ctx->pb = NULL; - avio_write(vs->out, buffer, *range_length); - av_free(buffer); + avio_write(vs->out, vs->temp_buffer, *range_length); // re-open buffer return avio_open_dyn_buf(&ctx->pb); } +static void reflush_dynbuf(VariantStream *vs, int *range_length) +{ + // re-open buffer + avio_write(vs->out, vs->temp_buffer, *range_length);; +} + static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls, VariantStream *vs) { @@ -1544,7 +1551,10 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) fail: av_dict_free(&options); - hlsenc_io_close(s, (byterange_mode || hls->segment_type == SEGMENT_TYPE_FMP4) ? &hls->m3u8_out : &vs->out, temp_filename); + ret = hlsenc_io_close(s, (byterange_mode || hls->segment_type == SEGMENT_TYPE_FMP4) ? &hls->m3u8_out : &vs->out, temp_filename); + if (ret < 0) { + return ret; + } hlsenc_io_close(s, &hls->sub_m3u8_out, vs->vtt_m3u8_name); if (use_temp_file) { ff_rename(temp_filename, vs->m3u8_name, s); @@ -2399,7 +2409,16 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) if (ret < 0) { return ret; } - hlsenc_io_close(s, &vs->out, filename); + ret = hlsenc_io_close(s, &vs->out, filename); + if (ret < 0) { + av_log(s, AV_LOG_WARNING, "upload segment failed," + "and will retry upload by a new http session.\n"); + ff_format_io_close(s, &vs->out); + ret = hlsenc_io_open(s, &vs->out, filename, &options); + reflush_dynbuf(vs, &range_length); + ret = hlsenc_io_close(s, &vs->out, filename); + } + av_free(vs->temp_buffer); av_free(filename); } } @@ -2426,8 +2445,13 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) // 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) { if ((ret = hls_window(s, 0, vs)) < 0) { - av_free(old_filename); - return ret; + av_log(s, AV_LOG_WARNING, "update playlist failed, will retry once time\n"); + ff_format_io_close(s, &vs->out); + vs->out = NULL; + if ((ret = hls_window(s, 0, vs)) < 0) { + av_free(old_filename); + return ret; + } } } @@ -2577,7 +2601,19 @@ static int hls_write_trailer(struct AVFormatContext *s) goto failed; vs->size = range_length; - hlsenc_io_close(s, &vs->out, filename); + ret = hlsenc_io_close(s, &vs->out, filename); + if (ret < 0) { + av_log(s, AV_LOG_WARNING, "write segment failed, will close old handle and retry once time\n"); + ff_format_io_close(s, &vs->out); + ret = hlsenc_io_open(s, &vs->out, filename, &options); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", vs->avf->url); + goto failed; + } + reflush_dynbuf(vs, &range_length); + ret = hlsenc_io_close(s, &vs->out, filename); + } + av_free(vs->temp_buffer); av_free(filename); failed: @@ -2610,7 +2646,12 @@ failed: ff_format_io_close(s, &vtt_oc->pb); avformat_free_context(vtt_oc); } - hls_window(s, 1, vs); + ret = hls_window(s, 1, vs); + if (ret < 0) { + av_log(s, AV_LOG_WARNING, "update playlist failed, will retry once time\n"); + ff_format_io_close(s, &vs->out); + hls_window(s, 1, vs); + } avformat_free_context(oc); vs->avf = NULL;