Re: [FFmpeg-devel] [PATCH 1/4] avformat/hlsenc: fix first fragment mp4 do not split bug
> On 19 Dec 2017, at 11:51, 刘歧wrote: > > > >> On 19 Dec 2017, at 11:42, Karthick Jeyapal wrote: >> >> >> >> On 12/18/17 2:17 PM, Steven Liu wrote: >>> fix ticket id: 6888 >>> >>> Signed-off-by: Steven Liu >>> --- >>> 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, ); >>> +ctx->pb = NULL; >>> +avio_write(vs->out, buffer, *range_length); >>> +av_free(buffer); >>> + >>> +// re-open buffer >>> +return avio_open_dyn_buf(>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(>pb)) < 0) >>> return ret; >>> -if ((ret = s->io_open(s, >out, vs->base_output_dirname, >>> AVIO_FLAG_WRITE, )) < 0) { >>> +ret = hlsenc_io_open(s, >out, vs->base_output_dirname, >>> ); >>> +av_dict_free(); >>> +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(); >>> if (err < 0) >>> return err; >>> -} else >>> +} else if (c->segment_type != SEGMENT_TYPE_FMP4) { >>> if ((err = hlsenc_io_open(s, >pb, oc->filename, )) < 0) >>> goto fail; >>> +} >>> if (vs->vtt_basename) { >>> set_http_options(s, , c); >>> if ((err = hlsenc_io_open(s, _oc->pb, vtt_oc->filename, >>> )) < 0) >>> @@ -1414,9 +1440,7 @@ static int hls_start(AVFormatContext *s, >>> VariantStream *vs) >>> } >>> av_dict_free(); >>> -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, ); >>> 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, >out); >>> hlsenc_io_close(s, >out, vs->base_output_dirname); >>> +} >>> } else { >>> hlsenc_io_close(s, >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, >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, _length); >>> +if (ret < 0) { >>> +return ret; >>> +} >>> +ff_format_io_close(s, >out); >> Again is it better to call hlsenc_io_close() here itself instead of
Re: [FFmpeg-devel] [PATCH 1/4] avformat/hlsenc: fix first fragment mp4 do not split bug
> On 19 Dec 2017, at 11:42, Karthick Jeyapalwrote: > > > > On 12/18/17 2:17 PM, Steven Liu wrote: >> fix ticket id: 6888 >> >> Signed-off-by: Steven Liu >> --- >> 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, ); >> +ctx->pb = NULL; >> +avio_write(vs->out, buffer, *range_length); >> +av_free(buffer); >> + >> +// re-open buffer >> +return avio_open_dyn_buf(>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(>pb)) < 0) >> return ret; >> -if ((ret = s->io_open(s, >out, vs->base_output_dirname, >> AVIO_FLAG_WRITE, )) < 0) { >> +ret = hlsenc_io_open(s, >out, vs->base_output_dirname, >> ); >> +av_dict_free(); >> +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(); >> if (err < 0) >> return err; >> -} else >> +} else if (c->segment_type != SEGMENT_TYPE_FMP4) { >> if ((err = hlsenc_io_open(s, >pb, oc->filename, )) < 0) >> goto fail; >> +} >> if (vs->vtt_basename) { >> set_http_options(s, , c); >> if ((err = hlsenc_io_open(s, _oc->pb, vtt_oc->filename, >> )) < 0) >> @@ -1414,9 +1440,7 @@ static int hls_start(AVFormatContext *s, VariantStream >> *vs) >> } >> av_dict_free(); >> -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, ); >> 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, >out); >> hlsenc_io_close(s, >out, vs->base_output_dirname); >> +} >> } else { >> hlsenc_io_close(s, >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, >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, _length); >> +if (ret < 0) { >> +return ret; >> +} >> +ff_format_io_close(s, >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
Re: [FFmpeg-devel] [PATCH 1/4] avformat/hlsenc: fix first fragment mp4 do not split bug
On 12/18/17 2:17 PM, Steven Liu wrote: fix ticket id: 6888 Signed-off-by: Steven Liu--- 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, ); +ctx->pb = NULL; +avio_write(vs->out, buffer, *range_length); +av_free(buffer); + +// re-open buffer +return avio_open_dyn_buf(>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(>pb)) < 0) return ret; -if ((ret = s->io_open(s, >out, vs->base_output_dirname, AVIO_FLAG_WRITE, )) < 0) { +ret = hlsenc_io_open(s, >out, vs->base_output_dirname, ); +av_dict_free(); +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(); if (err < 0) return err; -} else +} else if (c->segment_type != SEGMENT_TYPE_FMP4) { if ((err = hlsenc_io_open(s, >pb, oc->filename, )) < 0) goto fail; +} if (vs->vtt_basename) { set_http_options(s, , c); if ((err = hlsenc_io_open(s, _oc->pb, vtt_oc->filename, )) < 0) @@ -1414,9 +1440,7 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) } av_dict_free(); -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, ); 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, >out); hlsenc_io_close(s, >out, vs->base_output_dirname); +} } else { hlsenc_io_close(s, >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, >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, _length); +if (ret < 0) { +return ret; +} +ff_format_io_close(s, >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 (
[FFmpeg-devel] [PATCH 1/4] avformat/hlsenc: fix first fragment mp4 do not split bug
fix ticket id: 6888 Signed-off-by: Steven Liu--- 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, ); +ctx->pb = NULL; +avio_write(vs->out, buffer, *range_length); +av_free(buffer); + +// re-open buffer +return avio_open_dyn_buf(>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(>pb)) < 0) return ret; -if ((ret = s->io_open(s, >out, vs->base_output_dirname, AVIO_FLAG_WRITE, )) < 0) { +ret = hlsenc_io_open(s, >out, vs->base_output_dirname, ); +av_dict_free(); +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(); if (err < 0) return err; -} else +} else if (c->segment_type != SEGMENT_TYPE_FMP4) { if ((err = hlsenc_io_open(s, >pb, oc->filename, )) < 0) goto fail; +} if (vs->vtt_basename) { set_http_options(s, , c); if ((err = hlsenc_io_open(s, _oc->pb, vtt_oc->filename, )) < 0) @@ -1414,9 +1440,7 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) } av_dict_free(); -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, ); 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, >out); hlsenc_io_close(s, >out, vs->base_output_dirname); +} } else { hlsenc_io_close(s, >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, >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, _length); +if (ret < 0) { +return ret; +} +ff_format_io_close(s, >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, >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, _length); +