diff options
author | Steven Liu <lq@chinaffmpeg.org> | 2017-12-21 11:14:32 +0800 |
---|---|---|
committer | Steven Liu <lq@chinaffmpeg.org> | 2017-12-21 11:14:32 +0800 |
commit | 8318f60845bbbc4d33a39eee45e4daff0e5dacfb (patch) | |
tree | 9f39306615821db020b702308cb808db341de4a7 /libavformat/hlsenc.c | |
parent | 58a25aeb8e69532aae6ed1762fe7e0b260990010 (diff) | |
download | ffmpeg-8318f60845bbbc4d33a39eee45e4daff0e5dacfb.tar.gz |
avformat/hlsenc: fix first fragment mp4 do not split bug
fix ticket id: 6888
Tested-by: beloko <beloko@gmail.com>
Signed-off-by: Steven Liu <lq@chinaffmpeg.org>
Diffstat (limited to 'libavformat/hlsenc.c')
-rw-r--r-- | libavformat/hlsenc.c | 72 |
1 files changed, 62 insertions, 10 deletions
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index e3442c368f..f51fec1030 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -352,6 +352,29 @@ static void write_styp(AVIOContext *pb) ffio_wfourcc(pb, "msix"); } +static int flush_dynbuf(VariantStream *vs, int *range_length) +{ + AVFormatContext *ctx = vs->avf; + uint8_t *buffer; + + if (!ctx->pb) { + return AVERROR(EINVAL); + } + + // flush + av_write_frame(ctx, NULL); + avio_flush(ctx->pb); + + // write out to file + *range_length = avio_close_dyn_buf(ctx->pb, &buffer); + ctx->pb = NULL; + avio_write(vs->out, buffer, *range_length); + av_free(buffer); + + // re-open buffer + return avio_open_dyn_buf(&ctx->pb); +} + static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls, VariantStream *vs) { @@ -677,7 +700,9 @@ static int hls_mux_init(AVFormatContext *s, VariantStream *vs) if ((ret = avio_open_dyn_buf(&oc->pb)) < 0) return ret; - if ((ret = s->io_open(s, &vs->out, vs->base_output_dirname, AVIO_FLAG_WRITE, &options)) < 0) { + ret = hlsenc_io_open(s, &vs->out, vs->base_output_dirname, &options); + av_dict_free(&options); + if (ret < 0) { av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", vs->fmp4_init_filename); return ret; } @@ -1404,9 +1429,10 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) av_dict_free(&options); if (err < 0) return err; - } else + } else if (c->segment_type != SEGMENT_TYPE_FMP4) { if ((err = hlsenc_io_open(s, &oc->pb, oc->filename, &options)) < 0) goto fail; + } if (vs->vtt_basename) { set_http_options(s, &options, c); if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->filename, &options)) < 0) @@ -1414,9 +1440,7 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) } av_dict_free(&options); - if (c->segment_type == SEGMENT_TYPE_FMP4 && !(c->flags & HLS_SINGLE_FILE)) { - write_styp(oc->pb); - } else { + if (c->segment_type != SEGMENT_TYPE_FMP4) { /* We only require one PAT/PMT per segment. */ if (oc->oformat->priv_class && oc->priv_data) { char period[21]; @@ -1780,7 +1804,8 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) vs->size = new_start_pos - vs->start_pos; if (!byterange_mode) { - if (hls->segment_type == SEGMENT_TYPE_FMP4 && !vs->init_range_length) { + if (hls->segment_type == SEGMENT_TYPE_FMP4) { + if (!vs->init_range_length) { avio_flush(oc->pb); range_length = avio_close_dyn_buf(oc->pb, &buffer); avio_write(vs->out, buffer, range_length); @@ -1789,6 +1814,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) vs->packets_written = 0; ff_format_io_close(s, &vs->out); hlsenc_io_close(s, &vs->out, vs->base_output_dirname); + } } else { hlsenc_io_close(s, &oc->pb, oc->filename); } @@ -1807,7 +1833,20 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) vs->number--; } - if (!vs->fmp4_init_mode || byterange_mode) + if (hls->segment_type == SEGMENT_TYPE_FMP4) { + ret = hlsenc_io_open(s, &vs->out, vs->avf->filename, NULL); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Failed to open file '%s'\n", + vs->avf->filename); + return ret; + } + write_styp(vs->out); + ret = flush_dynbuf(vs, &range_length); + if (ret < 0) { + return ret; + } + ff_format_io_close(s, &vs->out); + } ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size); vs->start_pos = new_start_pos; if (ret < 0) { @@ -1861,6 +1900,7 @@ static int hls_write_trailer(struct AVFormatContext *s) AVFormatContext *vtt_oc = NULL; char *old_filename = NULL; int i; + int ret = 0; VariantStream *vs = NULL; for (i = 0; i < hls->nb_varstreams; i++) { @@ -1873,11 +1913,25 @@ static int hls_write_trailer(struct AVFormatContext *s) if (!old_filename) { return AVERROR(ENOMEM); } - + if ( hls->segment_type == SEGMENT_TYPE_FMP4) { + int range_length = 0; + ret = hlsenc_io_open(s, &vs->out, vs->avf->filename, NULL); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Failed to open file '%s'\n", vs->avf->filename); + return AVERROR(ENOENT); + } + write_styp(vs->out); + ret = flush_dynbuf(vs, &range_length); + if (ret < 0) { + return ret; + } + ff_format_io_close(s, &vs->out); + } av_write_trailer(oc); if (oc->pb) { vs->size = avio_tell(vs->avf->pb) - vs->start_pos; + if (hls->segment_type != SEGMENT_TYPE_FMP4) ff_format_io_close(s, &oc->pb); if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) { @@ -2238,10 +2292,8 @@ static int hls_init(AVFormatContext *s) } } - if (hls->segment_type != SEGMENT_TYPE_FMP4 || hls->flags & HLS_SINGLE_FILE) { if ((ret = hls_start(s, vs)) < 0) goto fail; - } } fail: |