Ticket #8693: 0001-avformat-dashenc-reopen-new-http-session-for-http_pe.patch

File 0001-avformat-dashenc-reopen-new-http-session-for-http_pe.patch, 5.8 KB (added by Chris Ribble, 6 years ago)
  • libavformat/dashenc.c

    From 7d6baa57923225af8cc7861955c047d27d6db22e Mon Sep 17 00:00:00 2001
    From: Chris Ribble <chris.ribble@livingasone.com>
    Date: Wed, 27 May 2020 23:04:28 -0500
    Subject: [PATCH] avformat/dashenc: reopen new http session for http_persistent
    
    Based on implementation in hlsenc.c
    
    Signed-off-by: Chris Ribble <chris.ribble@livingasone.com>
    ---
     libavformat/dashenc.c | 67 ++++++++++++++++++++++++++++++++++---------
     1 file changed, 53 insertions(+), 14 deletions(-)
    
    diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
    index 00a37b175d..a45d9bc7d0 100644
    a b typedef struct OutputStream {  
    121121    const char *single_file_name;  /* file names selected for this particular stream */
    122122    const char *init_seg_name;
    123123    const char *media_seg_name;
     124    uint8_t *temp_buffer;
    124125
    125126    char codec_str[100];
    126127    int written_len;
    static int dashenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,  
    239240    return err;
    240241}
    241242
    242 static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) {
     243static int dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) {
    243244    DASHContext *c = s->priv_data;
    244245    int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
    245246
     247    int ret = 0;
    246248    if (!*pb)
    247         return;
     249        return ret;
    248250
    249251    if (!http_base_proto || !c->http_persistent) {
    250252        ff_format_io_close(s, pb);
    static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filenam  
    254256        av_assert0(http_url_context);
    255257        avio_flush(*pb);
    256258        ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE);
     259        ret = ff_http_get_shutdown_status(http_url_context);
    257260#endif
    258261    }
     262    return ret;
    259263}
    260264
    261265static const char *get_format_str(SegmentType segment_type) {
    static void set_codec_str(AVFormatContext *s, AVCodecParameters *par,  
    453457
    454458static int flush_dynbuf(DASHContext *c, OutputStream *os, int *range_length)
    455459{
    456     uint8_t *buffer;
     460    AVFormatContext *ctx = os->ctx;
    457461
    458     if (!os->ctx->pb) {
     462    if (!ctx->pb) {
    459463        return AVERROR(EINVAL);
    460464    }
    461465
    462466    // flush
    463     av_write_frame(os->ctx, NULL);
    464     avio_flush(os->ctx->pb);
     467    av_write_frame(ctx, NULL);
     468    avio_flush(ctx->pb);
    465469
    466470    if (!c->single_file) {
    467471        // write out to file
    468         *range_length = avio_close_dyn_buf(os->ctx->pb, &buffer);
    469         os->ctx->pb = NULL;
     472        *range_length = avio_close_dyn_buf(ctx->pb, &os->temp_buffer);
     473        ctx->pb = NULL;
    470474        if (os->out)
    471             avio_write(os->out, buffer + os->written_len, *range_length - os->written_len);
     475            avio_write(os->out, os->temp_buffer + os->written_len, *range_length - os->written_len);
    472476        os->written_len = 0;
    473         av_free(buffer);
    474477
    475478        // re-open buffer
    476         return avio_open_dyn_buf(&os->ctx->pb);
     479        return avio_open_dyn_buf(&ctx->pb);
    477480    } else {
    478         *range_length = avio_tell(os->ctx->pb) - os->pos;
     481        *range_length = avio_tell(ctx->pb) - os->pos;
    479482        return 0;
    480483    }
    481484}
    482485
     486static void reflush_dynbuf(OutputStream *os, int *range_length)
     487{
     488    // re-open buffer
     489    avio_write(os->out, os->temp_buffer, *range_length);;
     490}
     491
    483492static void set_http_options(AVDictionary **options, DASHContext *c)
    484493{
    485494    if (c->method)
    static int flush_init_segment(AVFormatContext *s, OutputStream *os)  
    596605    int ret, range_length;
    597606
    598607    ret = flush_dynbuf(c, os, &range_length);
     608    av_freep(&os->temp_buffer);
    599609    if (ret < 0)
    600610        return ret;
    601611
    static void dash_free(AVFormatContext *s)  
    642652        av_freep(&os->single_file_name);
    643653        av_freep(&os->init_seg_name);
    644654        av_freep(&os->media_seg_name);
     655        av_freep(&os->temp_buffer);
    645656    }
    646657    av_freep(&c->streams);
    647658
    static int write_manifest(AVFormatContext *s, int final)  
    12411252
    12421253    avio_printf(out, "</MPD>\n");
    12431254    avio_flush(out);
    1244     dashenc_io_close(s, &c->mpd_out, temp_filename);
     1255    ret = dashenc_io_close(s, &c->mpd_out, temp_filename);
     1256    if (ret < 0) {
     1257        av_log(s, AV_LOG_WARNING, "upload manifest failed, will retry with a new http session.\n");
     1258        ff_format_io_close(s, &c->mpd_out);
     1259
     1260        set_http_options(&opts, c);
     1261        dashenc_io_open(s, &c->mpd_out, temp_filename, &opts);
     1262        av_dict_free(&opts);
     1263
     1264        dashenc_io_close(s, &c->mpd_out, temp_filename);
     1265        return ret;
     1266    }
    12451267
    12461268    if (use_rename) {
    12471269        if ((ret = ff_rename(temp_filename, s->url, s)) < 0)
    static int dash_flush(AVFormatContext *s, int final, int stream)  
    19391961        if (c->single_file) {
    19401962            find_index_range(s, os->full_path, os->pos, &index_length);
    19411963        } else {
    1942             dashenc_io_close(s, &os->out, os->temp_path);
     1964            ret = dashenc_io_close(s, &os->out, os->temp_path);
     1965            if (ret < 0) {
     1966                AVDictionary *http_opts = NULL;
     1967
     1968                av_log(s, AV_LOG_WARNING, "upload segment failed, will retry with a new http session.\n");
     1969                ff_format_io_close(s, &os->out);
     1970
     1971                set_http_options(&http_opts, c);
     1972                ret = dashenc_io_open(s, &os->out, os->temp_path, &http_opts);
     1973                av_dict_free(&http_opts);
     1974
     1975                reflush_dynbuf(os, &range_length);
     1976                ret = dashenc_io_close(s, &os->out, os->temp_path);
     1977            }
     1978            av_freep(&os->temp_buffer);
    19431979
    19441980            if (use_rename) {
    19451981                ret = ff_rename(os->temp_path, os->full_path, os->ctx);
    static int dash_flush(AVFormatContext *s, int final, int stream)  
    20102046            c->nr_of_streams_flushed = 0;
    20112047        }
    20122048        ret = write_manifest(s, final);
     2049        if (ret < 0 && c->http_persistent) {
     2050            ret = write_manifest(s, final);
     2051        }
    20132052    }
    20142053    return ret;
    20152054}