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 {
|
| 121 | 121 | const char *single_file_name; /* file names selected for this particular stream */ |
| 122 | 122 | const char *init_seg_name; |
| 123 | 123 | const char *media_seg_name; |
| | 124 | uint8_t *temp_buffer; |
| 124 | 125 | |
| 125 | 126 | char codec_str[100]; |
| 126 | 127 | int written_len; |
| … |
… |
static int dashenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,
|
| 239 | 240 | return err; |
| 240 | 241 | } |
| 241 | 242 | |
| 242 | | static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) { |
| | 243 | static int dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) { |
| 243 | 244 | DASHContext *c = s->priv_data; |
| 244 | 245 | int http_base_proto = filename ? ff_is_http_proto(filename) : 0; |
| 245 | 246 | |
| | 247 | int ret = 0; |
| 246 | 248 | if (!*pb) |
| 247 | | return; |
| | 249 | return ret; |
| 248 | 250 | |
| 249 | 251 | if (!http_base_proto || !c->http_persistent) { |
| 250 | 252 | ff_format_io_close(s, pb); |
| … |
… |
static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filenam
|
| 254 | 256 | av_assert0(http_url_context); |
| 255 | 257 | avio_flush(*pb); |
| 256 | 258 | ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE); |
| | 259 | ret = ff_http_get_shutdown_status(http_url_context); |
| 257 | 260 | #endif |
| 258 | 261 | } |
| | 262 | return ret; |
| 259 | 263 | } |
| 260 | 264 | |
| 261 | 265 | static const char *get_format_str(SegmentType segment_type) { |
| … |
… |
static void set_codec_str(AVFormatContext *s, AVCodecParameters *par,
|
| 453 | 457 | |
| 454 | 458 | static int flush_dynbuf(DASHContext *c, OutputStream *os, int *range_length) |
| 455 | 459 | { |
| 456 | | uint8_t *buffer; |
| | 460 | AVFormatContext *ctx = os->ctx; |
| 457 | 461 | |
| 458 | | if (!os->ctx->pb) { |
| | 462 | if (!ctx->pb) { |
| 459 | 463 | return AVERROR(EINVAL); |
| 460 | 464 | } |
| 461 | 465 | |
| 462 | 466 | // 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); |
| 465 | 469 | |
| 466 | 470 | if (!c->single_file) { |
| 467 | 471 | // 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; |
| 470 | 474 | 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); |
| 472 | 476 | os->written_len = 0; |
| 473 | | av_free(buffer); |
| 474 | 477 | |
| 475 | 478 | // re-open buffer |
| 476 | | return avio_open_dyn_buf(&os->ctx->pb); |
| | 479 | return avio_open_dyn_buf(&ctx->pb); |
| 477 | 480 | } else { |
| 478 | | *range_length = avio_tell(os->ctx->pb) - os->pos; |
| | 481 | *range_length = avio_tell(ctx->pb) - os->pos; |
| 479 | 482 | return 0; |
| 480 | 483 | } |
| 481 | 484 | } |
| 482 | 485 | |
| | 486 | static 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 | |
| 483 | 492 | static void set_http_options(AVDictionary **options, DASHContext *c) |
| 484 | 493 | { |
| 485 | 494 | if (c->method) |
| … |
… |
static int flush_init_segment(AVFormatContext *s, OutputStream *os)
|
| 596 | 605 | int ret, range_length; |
| 597 | 606 | |
| 598 | 607 | ret = flush_dynbuf(c, os, &range_length); |
| | 608 | av_freep(&os->temp_buffer); |
| 599 | 609 | if (ret < 0) |
| 600 | 610 | return ret; |
| 601 | 611 | |
| … |
… |
static void dash_free(AVFormatContext *s)
|
| 642 | 652 | av_freep(&os->single_file_name); |
| 643 | 653 | av_freep(&os->init_seg_name); |
| 644 | 654 | av_freep(&os->media_seg_name); |
| | 655 | av_freep(&os->temp_buffer); |
| 645 | 656 | } |
| 646 | 657 | av_freep(&c->streams); |
| 647 | 658 | |
| … |
… |
static int write_manifest(AVFormatContext *s, int final)
|
| 1241 | 1252 | |
| 1242 | 1253 | avio_printf(out, "</MPD>\n"); |
| 1243 | 1254 | 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 | } |
| 1245 | 1267 | |
| 1246 | 1268 | if (use_rename) { |
| 1247 | 1269 | if ((ret = ff_rename(temp_filename, s->url, s)) < 0) |
| … |
… |
static int dash_flush(AVFormatContext *s, int final, int stream)
|
| 1939 | 1961 | if (c->single_file) { |
| 1940 | 1962 | find_index_range(s, os->full_path, os->pos, &index_length); |
| 1941 | 1963 | } 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); |
| 1943 | 1979 | |
| 1944 | 1980 | if (use_rename) { |
| 1945 | 1981 | ret = ff_rename(os->temp_path, os->full_path, os->ctx); |
| … |
… |
static int dash_flush(AVFormatContext *s, int final, int stream)
|
| 2010 | 2046 | c->nr_of_streams_flushed = 0; |
| 2011 | 2047 | } |
| 2012 | 2048 | ret = write_manifest(s, final); |
| | 2049 | if (ret < 0 && c->http_persistent) { |
| | 2050 | ret = write_manifest(s, final); |
| | 2051 | } |
| 2013 | 2052 | } |
| 2014 | 2053 | return ret; |
| 2015 | 2054 | } |