Message ID | 20171218084705.13885-1-lq@chinaffmpeg.org |
---|---|
State | Accepted |
Commit | 8318f60845bbbc4d33a39eee45e4daff0e5dacfb |
Headers | show |
On 12/18/17 2:17 PM, Steven Liu wrote: > fix ticket id: 6888 > > Signed-off-by: Steven Liu <lq@chinaffmpeg.org> > --- > libavformat/hlsenc.c | 72 ++++++++++++++++++++++++++++++++++++++++++++-------- > 1 file 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); Will it be better if you call "set_http_options()" here itself, instead of a separate patch 4/4? In that way this patch would be self contained. > + 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); Again is it better to call hlsenc_io_close() here itself instead of patch 3/4. Again just from self-containment perspective. > + } > 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); > + } Will it make sense it make this code as a separate function in order to avoid code repetition? > > 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: Thanks, Karthick
> On 19 Dec 2017, at 11:42, Karthick Jeyapal <kjeyapal@akamai.com> wrote: > > > > On 12/18/17 2:17 PM, Steven Liu wrote: >> fix ticket id: 6888 >> >> Signed-off-by: Steven Liu <lq@chinaffmpeg.org> >> --- >> libavformat/hlsenc.c | 72 ++++++++++++++++++++++++++++++++++++++++++++-------- >> 1 file 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); > Will it be better if you call "set_http_options()" here itself, instead of a separate patch 4/4? In that way this patch would be self contained. set_http_options is add option to http operation, so separate two patches. And this patch just fix ticket >> + 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); > Again is it better to call hlsenc_io_close() here itself instead of patch 3/4. Again just from self-containment perspective. Replace API to hlsenc_io_close is a new operation, so separate two patch And this patch just fix ticket >> + } >> 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); >> + } > Will it make sense it make this code as a separate function in order to avoid code repetition? That is optimize operation, this patch just fix ticket, so i will send a new patch to merge two workflow to on function. Thanks Steven >> 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: > Thanks, > Karthick > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> On 19 Dec 2017, at 11:51, 刘歧 <lq@chinaffmpeg.org> wrote: > > > >> On 19 Dec 2017, at 11:42, Karthick Jeyapal <kjeyapal@akamai.com> wrote: >> >> >> >> On 12/18/17 2:17 PM, Steven Liu wrote: >>> fix ticket id: 6888 >>> >>> Signed-off-by: Steven Liu <lq@chinaffmpeg.org> >>> --- >>> libavformat/hlsenc.c | 72 ++++++++++++++++++++++++++++++++++++++++++++-------- >>> 1 file 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); >> Will it be better if you call "set_http_options()" here itself, instead of a separate patch 4/4? In that way this patch would be self contained. > set_http_options is add option to http operation, so separate two patches. > And this patch just fix ticket >>> + 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); >> Again is it better to call hlsenc_io_close() here itself instead of patch 3/4. Again just from self-containment perspective. > Replace API to hlsenc_io_close is a new operation, so separate two patch > And this patch just fix ticket >>> + } >>> 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); >>> + } >> Will it make sense it make this code as a separate function in order to avoid code repetition? > That is optimize operation, this patch just fix ticket, so i will send a new patch to merge two workflow to on function. > > Thanks > > Steven >>> 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: >> Thanks, >> Karthick >> _______________________________________________ >> ffmpeg-devel mailing list >> ffmpeg-devel@ffmpeg.org >> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel pushed Thanks
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:
fix ticket id: 6888 Signed-off-by: Steven Liu <lq@chinaffmpeg.org> --- libavformat/hlsenc.c | 72 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 10 deletions(-)