Re: [FFmpeg-devel] [PATCH 1/4] avformat/hlsenc: fix first fragment mp4 do not split bug

2017-12-20 Thread 刘歧


> 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

2017-12-18 Thread 刘歧


> 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 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

2017-12-18 Thread Karthick Jeyapal



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

2017-12-18 Thread Steven Liu
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);
+