[FFmpeg-devel] [PATCH v2 2/2] avformat/dashenc: Remove muxer overhead from Bandwidth field in DASH manifest

2018-09-04 Thread Karthick J
From: Karthick Jeyapal 

Fixes bug id #7386
Muxer overhead calculations was intented for HLS playlist as Apple's 
mediastreamvalidator tests were failing.
But applying the same fix for DASH manifest proved counterproductive, as 
Bandwidth can be used for segment name templates.
---
 libavformat/dashenc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index c36ab12..2564b9e 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -611,7 +611,7 @@ static int write_adaptation_set(AVFormatContext *s, 
AVIOContext *out, int as_ind
 
 if (os->bit_rate > 0)
 snprintf(bandwidth_str, sizeof(bandwidth_str), " bandwidth=\"%d\"",
- os->bit_rate + os->muxer_overhead);
+ os->bit_rate);
 
 if (as->media_type == AVMEDIA_TYPE_VIDEO) {
 AVStream *st = s->streams[i];
-- 
2.7.4

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 1/2] avformat/dashenc: Add CODECS tag to HLS master playlist

2018-09-04 Thread Karthick J
From: Karthick Jeyapal 

---
 libavformat/dashenc.c | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index ae57fd5..c36ab12 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -864,6 +864,7 @@ static int write_manifest(AVFormatContext *s, int final)
 if (c->hls_playlist && !c->master_playlist_created) {
 char filename_hls[1024];
 const char *audio_group = "A1";
+const char audio_codec_str[128] = "\0";
 int is_default = 1;
 int max_audio_bitrate = 0;
 
@@ -895,21 +896,31 @@ static int write_manifest(AVFormatContext *s, int final)
  playlist_file, i, is_default);
 max_audio_bitrate = FFMAX(st->codecpar->bit_rate +
   os->muxer_overhead, max_audio_bitrate);
+if (!av_strnstr(audio_codec_str, os->codec_str, 
sizeof(audio_codec_str))) {
+if (strlen(audio_codec_str))
+av_strlcat(audio_codec_str, ",", sizeof(audio_codec_str));
+av_strlcat(audio_codec_str, os->codec_str, 
sizeof(audio_codec_str));
+}
 is_default = 0;
 }
 
 for (i = 0; i < s->nb_streams; i++) {
 char playlist_file[64];
+char codec_str[128];
 AVStream *st = s->streams[i];
 OutputStream *os = &c->streams[i];
 char *agroup = NULL;
 int stream_bitrate = st->codecpar->bit_rate + os->muxer_overhead;
+av_strlcpy(codec_str, os->codec_str, sizeof(codec_str));
 if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && 
max_audio_bitrate) {
 agroup = (char *)audio_group;
 stream_bitrate += max_audio_bitrate;
+av_strlcat(codec_str, ",", sizeof(codec_str));
+av_strlcat(codec_str, audio_codec_str, sizeof(codec_str));
 }
 get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, 
i);
-ff_hls_write_stream_info(st, out, stream_bitrate, playlist_file, 
agroup, NULL, NULL);
+ff_hls_write_stream_info(st, out, stream_bitrate, playlist_file, 
agroup,
+ codec_str, NULL);
 }
 avio_close(out);
 if (use_rename)
-- 
2.7.4

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/dashenc: Reduce Muxing overhead for chunked CMAF format

2018-09-14 Thread Karthick J
From: Karthick Jeyapal 

SIDX atom being inserted for every MOOF atom increases the muxing overhead.
This behaviour can be disabled for chunked CMAF format by enabling Global SIDX 
option of mov muxer.
---
 libavformat/dashenc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 87e31e2..9a33321 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -1065,7 +1065,7 @@ static int dash_init(AVFormatContext *s)
 
 if (c->segment_type == SEGMENT_TYPE_MP4) {
 if (c->streaming)
-av_dict_set(&opts, "movflags", 
"frag_every_frame+dash+delay_moov", 0);
+av_dict_set(&opts, "movflags", 
"frag_every_frame+dash+delay_moov+global_sidx", 0);
 else
 av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 
0);
 } else {
-- 
2.7.4

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/dashenc: Format VP9 level as decimal instead of hexadecimal

2018-09-17 Thread Karthick J
From: Karthick Jeyapal 

Commit ID 63c69d51c7532fb6c2460076329b50ec51a0f290 fixed the bug in vpcc, 
get_vp9_level() function, causing this change.
---
 libavformat/dashenc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 9a33321..f429ebc 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -211,7 +211,7 @@ static void set_vp9_codec_str(AVFormatContext *s, 
AVCodecParameters *par,
 VPCC vpcc;
 int ret = ff_isom_get_vpcc_features(s, par, frame_rate, &vpcc);
 if (ret == 0) {
-av_strlcatf(str, size, "vp09.%02x.%02x.%02x",
+av_strlcatf(str, size, "vp09.%02x.%02d.%02x",
 vpcc.profile, vpcc.level, vpcc.bitdepth);
 } else {
 // Default to just vp9 in case of error while finding out profile or 
level
-- 
2.7.4

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 2/2] avformat/dashenc: Format VP9 bitdepth as decimal instead of Hexadecimal

2018-09-17 Thread Karthick J
From: Karthick Jeyapal 

For example bitdepth should be printed as 10 instead of 0A. Thanks to Hendrik 
Leppkes for pointing this out
---
 libavformat/dashenc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index f429ebc..1a201c3 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -211,7 +211,7 @@ static void set_vp9_codec_str(AVFormatContext *s, 
AVCodecParameters *par,
 VPCC vpcc;
 int ret = ff_isom_get_vpcc_features(s, par, frame_rate, &vpcc);
 if (ret == 0) {
-av_strlcatf(str, size, "vp09.%02x.%02d.%02x",
+av_strlcatf(str, size, "vp09.%02x.%02d.%02d",
 vpcc.profile, vpcc.level, vpcc.bitdepth);
 } else {
 // Default to just vp9 in case of error while finding out profile or 
level
-- 
2.7.4

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 1/2] avformat/dashenc: Format VP9 level as decimal instead of hexadecimal

2018-09-17 Thread Karthick J
From: Karthick Jeyapal 

Commit ID 63c69d51c7532fb6c2460076329b50ec51a0f290 fixed the bug in vpcc, 
get_vp9_level() function, causing this change.
---
 libavformat/dashenc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 9a33321..f429ebc 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -211,7 +211,7 @@ static void set_vp9_codec_str(AVFormatContext *s, 
AVCodecParameters *par,
 VPCC vpcc;
 int ret = ff_isom_get_vpcc_features(s, par, frame_rate, &vpcc);
 if (ret == 0) {
-av_strlcatf(str, size, "vp09.%02x.%02x.%02x",
+av_strlcatf(str, size, "vp09.%02x.%02d.%02x",
 vpcc.profile, vpcc.level, vpcc.bitdepth);
 } else {
 // Default to just vp9 in case of error while finding out profile or 
level
-- 
2.7.4

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avdevice/decklink: Add option to align Capture start time

2018-09-24 Thread Karthick J
From: Karthick Jeyapal 

This option is useful for maintaining input synchronization across N
different hardware devices deployed for 'N-way' redundancy.
The system time of different hardware devices should be synchronized
with protocols such as NTP or PTP, before using this option.
---
 doc/indevs.texi | 10 ++
 libavdevice/decklink_common_c.h |  1 +
 libavdevice/decklink_dec.cpp| 20 
 libavdevice/decklink_dec_c.c|  1 +
 4 files changed, 32 insertions(+)

diff --git a/doc/indevs.texi b/doc/indevs.texi
index ed2784b..dfd530a 100644
--- a/doc/indevs.texi
+++ b/doc/indevs.texi
@@ -371,6 +371,16 @@ If set to @option{true}, timestamps are forwarded as they 
are without removing
 the initial offset.
 Defaults to @option{false}.
 
+@item timestamp_align
+Capture start time alignment in seconds. If set to nonzero, input frames are
+dropped till the system timestamp aligns with configured value.
+Alignment difference of upto one frame duration is tolerated.
+This is useful for maintaining input synchronization across N different
+hardware devices deployed for 'N-way' redundancy. The system time of different
+hardware devices should be synchronized with protocols such as NTP or PTP,
+before using this option.
+Defaults to @samp{0}.
+
 @end table
 
 @subsection Examples
diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h
index 32a5d70..c4a8985 100644
--- a/libavdevice/decklink_common_c.h
+++ b/libavdevice/decklink_common_c.h
@@ -56,6 +56,7 @@ struct decklink_cctx {
 int raw_format;
 int64_t queue_size;
 int copyts;
+int timestamp_align;
 };
 
 #endif /* AVDEVICE_DECKLINK_COMMON_C_H */
diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
index 7fabef2..24f5ca9 100644
--- a/libavdevice/decklink_dec.cpp
+++ b/libavdevice/decklink_dec.cpp
@@ -703,6 +703,26 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
 return S_OK;
 }
 
+// Drop the frames till system's timestamp aligns with the configured 
value.
+if (0 == ctx->frameCount && cctx->timestamp_align) {
+int64_t current_time_us = av_gettime();
+int64_t align_factor_us = (cctx->timestamp_align * 100);
+int remainder = current_time_us % align_factor_us;
+if (videoFrame) {
+videoFrame->GetStreamTime(&frameTime, &frameDuration, 100);
+} else if (audioFrame) {
+long sample_count = audioFrame->GetSampleFrameCount();
+frameDuration = (long)(sample_count * 100) / 
bmdAudioSampleRate48kHz;
+} else {
+frameDuration = 0;
+}
+// threshold of one frameDuration
+if(remainder > frameDuration) {
+++ctx->dropped;
+return S_OK;
+}
+}
+
 ctx->frameCount++;
 if (ctx->audio_pts_source == PTS_SRC_WALLCLOCK || ctx->video_pts_source == 
PTS_SRC_WALLCLOCK)
 wallclock = av_gettime_relative();
diff --git a/libavdevice/decklink_dec_c.c b/libavdevice/decklink_dec_c.c
index 6ab3819..bef9c14 100644
--- a/libavdevice/decklink_dec_c.c
+++ b/libavdevice/decklink_dec_c.c
@@ -84,6 +84,7 @@ static const AVOption options[] = {
 { "queue_size","input queue buffer size",   OFFSET(queue_size),   
AV_OPT_TYPE_INT64, { .i64 = (1024 * 1024 * 1024)}, 0, INT64_MAX, DEC },
 { "audio_depth",   "audio bitdepth (16 or 32)", OFFSET(audio_depth),  
AV_OPT_TYPE_INT,   { .i64 = 16}, 16, 32, DEC },
 { "decklink_copyts", "copy timestamps, do not remove the initial offset", 
OFFSET(copyts), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, DEC },
+{ "timestamp_align", "Capture start time alignment (in seconds)", 
OFFSET(timestamp_align), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, DEC },
 { NULL },
 };
 
-- 
2.7.4

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2] avdevice/decklink: Add option to align Capture start time

2018-09-28 Thread Karthick J
From: Karthick Jeyapal 

This option is useful for maintaining input synchronization across N
different hardware devices deployed for 'N-way' redundancy.
The system time of different hardware devices should be synchronized
with protocols such as NTP or PTP, before using this option.
---
 doc/indevs.texi | 13 +
 libavdevice/decklink_common_c.h |  1 +
 libavdevice/decklink_dec.cpp| 11 +++
 libavdevice/decklink_dec_c.c|  1 +
 4 files changed, 26 insertions(+)

diff --git a/doc/indevs.texi b/doc/indevs.texi
index ed2784b..694bac9 100644
--- a/doc/indevs.texi
+++ b/doc/indevs.texi
@@ -371,6 +371,19 @@ If set to @option{true}, timestamps are forwarded as they 
are without removing
 the initial offset.
 Defaults to @option{false}.
 
+@item timestamp_align
+Capture start time alignment in seconds. If set to nonzero, input frames are
+dropped till the system timestamp aligns with configured value.
+Alignment difference of upto one frame duration is tolerated.
+This is useful for maintaining input synchronization across N different
+hardware devices deployed for 'N-way' redundancy. The system time of different
+hardware devices should be synchronized with protocols such as NTP or PTP,
+before using this option.
+Note that this method not foolproof. In some border cases input synchronization
+may not happen due to thread scheduling jitters in the OS. Either sync could go
+wrong by 1 frame or in a rarer case by even @option{timestamp_align} seconds.
+Defaults to @samp{0}.
+
 @end table
 
 @subsection Examples
diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h
index 32a5d70..8e3bbeb 100644
--- a/libavdevice/decklink_common_c.h
+++ b/libavdevice/decklink_common_c.h
@@ -56,6 +56,7 @@ struct decklink_cctx {
 int raw_format;
 int64_t queue_size;
 int copyts;
+int64_t timestamp_align;
 };
 
 #endif /* AVDEVICE_DECKLINK_COMMON_C_H */
diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
index 7fabef2..1f4d68b 100644
--- a/libavdevice/decklink_dec.cpp
+++ b/libavdevice/decklink_dec.cpp
@@ -703,6 +703,17 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
 return S_OK;
 }
 
+// Drop the frames till system's timestamp aligns with the configured 
value.
+if (0 == ctx->frameCount && cctx->timestamp_align) {
+AVRational remainder = av_make_q(av_gettime() % cctx->timestamp_align, 
100);
+AVRational frame_duration = av_make_q(ctx->video_st->r_frame_rate.den,
+  ctx->video_st->r_frame_rate.num);
+if (av_cmp_q(remainder, frame_duration) > 0) {
+++ctx->dropped;
+return S_OK;
+}
+}
+
 ctx->frameCount++;
 if (ctx->audio_pts_source == PTS_SRC_WALLCLOCK || ctx->video_pts_source == 
PTS_SRC_WALLCLOCK)
 wallclock = av_gettime_relative();
diff --git a/libavdevice/decklink_dec_c.c b/libavdevice/decklink_dec_c.c
index 6ab3819..2e6fcb6 100644
--- a/libavdevice/decklink_dec_c.c
+++ b/libavdevice/decklink_dec_c.c
@@ -84,6 +84,7 @@ static const AVOption options[] = {
 { "queue_size","input queue buffer size",   OFFSET(queue_size),   
AV_OPT_TYPE_INT64, { .i64 = (1024 * 1024 * 1024)}, 0, INT64_MAX, DEC },
 { "audio_depth",   "audio bitdepth (16 or 32)", OFFSET(audio_depth),  
AV_OPT_TYPE_INT,   { .i64 = 16}, 16, 32, DEC },
 { "decklink_copyts", "copy timestamps, do not remove the initial offset", 
OFFSET(copyts), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, DEC },
+{ "timestamp_align", "Capture start time alignment (in seconds)", 
OFFSET(timestamp_align), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT_MAX, DEC },
 { NULL },
 };
 
-- 
2.7.4

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/dashenc: Support HTTP Persistent for master.mu8 as well

2018-10-17 Thread Karthick J
---
 libavformat/dashenc.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 3f5f290e25..15b84a0f3b 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -878,14 +878,14 @@ static int write_manifest(AVFormatContext *s, int final)
 snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : 
"%s", filename_hls);
 
 set_http_options(&opts, c);
-ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE, NULL, &opts);
+ret = dashenc_io_open(s, &c->m3u8_out, temp_filename, &opts);
 if (ret < 0) {
 av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", 
temp_filename);
 return ret;
 }
 av_dict_free(&opts);
 
-ff_hls_write_playlist_version(out, 7);
+ff_hls_write_playlist_version(c->m3u8_out, 7);
 
 for (i = 0; i < s->nb_streams; i++) {
 char playlist_file[64];
@@ -894,7 +894,7 @@ static int write_manifest(AVFormatContext *s, int final)
 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
 continue;
 get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, 
i);
-ff_hls_write_audio_rendition(out, (char *)audio_group,
+ff_hls_write_audio_rendition(c->m3u8_out, (char *)audio_group,
  playlist_file, i, is_default);
 max_audio_bitrate = FFMAX(st->codecpar->bit_rate +
   os->muxer_overhead, max_audio_bitrate);
@@ -923,10 +923,11 @@ static int write_manifest(AVFormatContext *s, int final)
 av_strlcat(codec_str, audio_codec_str, sizeof(codec_str));
 }
 get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, 
i);
-ff_hls_write_stream_info(st, out, stream_bitrate, playlist_file, 
agroup,
+ff_hls_write_stream_info(st, c->m3u8_out, stream_bitrate,
+ playlist_file, agroup,
  codec_str, NULL);
 }
-avio_close(out);
+dashenc_io_close(s, &c->m3u8_out, temp_filename);
 if (use_rename)
 if ((ret = avpriv_io_move(temp_filename, filename_hls)) < 0)
 return ret;
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2] avformat/dashenc: Support HTTP Persistent for master.m3u8 as well

2018-10-17 Thread Karthick J
---
 libavformat/dashenc.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 3f5f290e25..15b84a0f3b 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -878,14 +878,14 @@ static int write_manifest(AVFormatContext *s, int final)
 snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : 
"%s", filename_hls);
 
 set_http_options(&opts, c);
-ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE, NULL, &opts);
+ret = dashenc_io_open(s, &c->m3u8_out, temp_filename, &opts);
 if (ret < 0) {
 av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", 
temp_filename);
 return ret;
 }
 av_dict_free(&opts);
 
-ff_hls_write_playlist_version(out, 7);
+ff_hls_write_playlist_version(c->m3u8_out, 7);
 
 for (i = 0; i < s->nb_streams; i++) {
 char playlist_file[64];
@@ -894,7 +894,7 @@ static int write_manifest(AVFormatContext *s, int final)
 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
 continue;
 get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, 
i);
-ff_hls_write_audio_rendition(out, (char *)audio_group,
+ff_hls_write_audio_rendition(c->m3u8_out, (char *)audio_group,
  playlist_file, i, is_default);
 max_audio_bitrate = FFMAX(st->codecpar->bit_rate +
   os->muxer_overhead, max_audio_bitrate);
@@ -923,10 +923,11 @@ static int write_manifest(AVFormatContext *s, int final)
 av_strlcat(codec_str, audio_codec_str, sizeof(codec_str));
 }
 get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, 
i);
-ff_hls_write_stream_info(st, out, stream_bitrate, playlist_file, 
agroup,
+ff_hls_write_stream_info(st, c->m3u8_out, stream_bitrate,
+ playlist_file, agroup,
  codec_str, NULL);
 }
-avio_close(out);
+dashenc_io_close(s, &c->m3u8_out, temp_filename);
 if (use_rename)
 if ((ret = avpriv_io_move(temp_filename, filename_hls)) < 0)
 return ret;
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/dashenc: Support HTTP Persistent for master.mu8 as well

2018-10-17 Thread Karthick J
---
 libavformat/dashenc.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 3f5f290e25..15b84a0f3b 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -878,14 +878,14 @@ static int write_manifest(AVFormatContext *s, int final)
 snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : 
"%s", filename_hls);
 
 set_http_options(&opts, c);
-ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE, NULL, &opts);
+ret = dashenc_io_open(s, &c->m3u8_out, temp_filename, &opts);
 if (ret < 0) {
 av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", 
temp_filename);
 return ret;
 }
 av_dict_free(&opts);
 
-ff_hls_write_playlist_version(out, 7);
+ff_hls_write_playlist_version(c->m3u8_out, 7);
 
 for (i = 0; i < s->nb_streams; i++) {
 char playlist_file[64];
@@ -894,7 +894,7 @@ static int write_manifest(AVFormatContext *s, int final)
 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
 continue;
 get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, 
i);
-ff_hls_write_audio_rendition(out, (char *)audio_group,
+ff_hls_write_audio_rendition(c->m3u8_out, (char *)audio_group,
  playlist_file, i, is_default);
 max_audio_bitrate = FFMAX(st->codecpar->bit_rate +
   os->muxer_overhead, max_audio_bitrate);
@@ -923,10 +923,11 @@ static int write_manifest(AVFormatContext *s, int final)
 av_strlcat(codec_str, audio_codec_str, sizeof(codec_str));
 }
 get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, 
i);
-ff_hls_write_stream_info(st, out, stream_bitrate, playlist_file, 
agroup,
+ff_hls_write_stream_info(st, c->m3u8_out, stream_bitrate,
+ playlist_file, agroup,
  codec_str, NULL);
 }
-avio_close(out);
+dashenc_io_close(s, &c->m3u8_out, temp_filename);
 if (use_rename)
 if ((ret = avpriv_io_move(temp_filename, filename_hls)) < 0)
 return ret;
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/dashenc: URL close unconditionally after DELETE segments

2018-10-18 Thread Karthick J
Fixes bug with HTTP DELETE when HTTP Persistent is ON.
Right now, HTTP Persistent connections is supported only for POSTs and PUTs.
HTTP DELETE will still open a new connection every time.
---
 libavformat/dashenc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 15b84a0f3b..b0a59af3ee 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -1253,7 +1253,7 @@ static void dashenc_delete_file(AVFormatContext *s, char 
*filename) {
 }
 
 av_dict_free(&http_opts);
-dashenc_io_close(s, &out, filename);
+ff_format_io_close(s, &out);
 } else if (unlink(filename) < 0) {
 av_log(s, AV_LOG_ERROR, "failed to delete %s: %s\n", filename, 
strerror(errno));
 }
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/dashenc: Support HTTP persistent for init segments as well

2018-10-20 Thread Karthick J
---
 libavformat/dashenc.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index b0a59af3ee..4e2ea2ebf2 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -355,8 +355,11 @@ static int flush_init_segment(AVFormatContext *s, 
OutputStream *os)
 return ret;
 
 os->pos = os->init_range_length = range_length;
-if (!c->single_file)
-ff_format_io_close(s, &os->out);
+if (!c->single_file) {
+char filename[1024];
+snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
+dashenc_io_close(s, &os->out, filename);
+}
 return 0;
 }
 
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/dashenc: Disable writing CODECS tag for HEVC streams

2018-10-21 Thread Karthick J
For HEVC streams, only the FourCC tag is written without profile, level etc.,
This is breaking playout support in native Safari.
Native Safari playout expects the full info in CODECS tag or None at all.
---
 libavformat/dashenc.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 4e2ea2ebf2..f8b3d106d5 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -915,6 +915,7 @@ static int write_manifest(AVFormatContext *s, int final)
 AVStream *st = s->streams[i];
 OutputStream *os = &c->streams[i];
 char *agroup = NULL;
+char *codec_str_ptr = NULL;
 int stream_bitrate = st->codecpar->bit_rate + os->muxer_overhead;
 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
 continue;
@@ -925,10 +926,13 @@ static int write_manifest(AVFormatContext *s, int final)
 av_strlcat(codec_str, ",", sizeof(codec_str));
 av_strlcat(codec_str, audio_codec_str, sizeof(codec_str));
 }
+if (st->codecpar->codec_id != AV_CODEC_ID_HEVC) {
+codec_str_ptr = codec_str;
+}
 get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, 
i);
 ff_hls_write_stream_info(st, c->m3u8_out, stream_bitrate,
  playlist_file, agroup,
- codec_str, NULL);
+ codec_str_ptr, NULL);
 }
 dashenc_io_close(s, &c->m3u8_out, temp_filename);
 if (use_rename)
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 2/2] avformat/http : Added check for valid URL context before calling shutdown

2018-11-16 Thread Karthick J
---
 libavformat/http.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 3a35bc7eac..240304f6e6 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -1650,7 +1650,7 @@ static int http_close(URLContext *h)
 av_freep(&s->inflate_buffer);
 #endif /* CONFIG_ZLIB */
 
-if (!s->end_chunked_post)
+if (s->hd && !s->end_chunked_post)
 /* Close the write direction by sending the end of chunked encoding. */
 ret = http_shutdown(h, h->flags);
 
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 1/2] avformat/dashenc : Handled error from ff_http_do_new_request() cleanly

2018-11-16 Thread Karthick J
---
 libavformat/dashenc.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index d151921175..2c1cce0c92 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -168,6 +168,8 @@ static int dashenc_io_open(AVFormatContext *s, AVIOContext 
**pb, char *filename,
 URLContext *http_url_context = ffio_geturlcontext(*pb);
 av_assert0(http_url_context);
 err = ff_http_do_new_request(http_url_context, filename);
+if (err < 0)
+ff_format_io_close(s, pb);
 #endif
 }
 return err;
@@ -177,6 +179,9 @@ static void dashenc_io_close(AVFormatContext *s, 
AVIOContext **pb, char *filenam
 DASHContext *c = s->priv_data;
 int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
 
+if (!*pb)
+return;
+
 if (!http_base_proto || !c->http_persistent) {
 ff_format_io_close(s, pb);
 #if CONFIG_HTTP_PROTOCOL
@@ -318,7 +323,8 @@ static int flush_dynbuf(OutputStream *os, int *range_length)
 // write out to file
 *range_length = avio_close_dyn_buf(os->ctx->pb, &buffer);
 os->ctx->pb = NULL;
-avio_write(os->out, buffer + os->written_len, *range_length - 
os->written_len);
+if (os->out)
+avio_write(os->out, buffer + os->written_len, *range_length - 
os->written_len);
 os->written_len = 0;
 av_free(buffer);
 
@@ -1496,9 +1502,9 @@ static int dash_write_packet(AVFormatContext *s, AVPacket 
*pkt)
  use_rename ? "%s.tmp" : "%s", os->full_path);
 set_http_options(&opts, c);
 ret = dashenc_io_open(s, &os->out, os->temp_path, &opts);
+av_dict_free(&opts);
 if (ret < 0)
 return ret;
-av_dict_free(&opts);
 }
 
 //write out the data immediately in streaming mode
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 1/2] avformat/dashenc: Handled the error from dashenc_io_open()

2018-11-26 Thread Karthick J
---
 libavformat/dashenc.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 6ce70e0076..2f403257c0 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -527,8 +527,12 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, AVFormatCont
 snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? 
"%s.tmp" : "%s", filename_hls);
 
 set_http_options(&http_opts, c);
-dashenc_io_open(s, &c->m3u8_out, temp_filename_hls, &http_opts);
+ret = dashenc_io_open(s, &c->m3u8_out, temp_filename_hls, &http_opts);
 av_dict_free(&http_opts);
+if (ret < 0) {
+av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", 
temp_filename_hls);
+return;
+}
 for (i = start_index; i < os->nb_segments; i++) {
 Segment *seg = os->segments[i];
 double duration = (double) seg->duration / timescale;
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 2/2] avformat/dashenc: Added an option to ignore io errors

2018-11-26 Thread Karthick J
When dashenc has to run for long duration(say 24x7 live stream), one can enable 
this option to ignore the io failure of few segment's upload due to an 
intermittent network issues.
When the network connection recovers dashenc will continue with the upload of 
the current segments, leading to the recovery of the stream.
---
 doc/muxers.texi   |  3 +++
 libavformat/dashenc.c | 26 --
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index a02ac01b55..f1cc6f5fee 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -300,6 +300,9 @@ If this flag is set, the dash segment files will be in in 
ISOBMFF format.
 @item webm
 If this flag is set, the dash segment files will be in in WebM format.
 
+@item -ignore_io_errors @var{ignore_io_errors}
+Ignore IO errors during open and write. Useful for long-duration runs with 
network output.
+
 @end table
 
 @anchor{framecrc}
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 2f403257c0..92b09417df 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -138,6 +138,7 @@ typedef struct DASHContext {
 int index_correction;
 char *format_options_str;
 SegmentType segment_type_option;  /* segment type as specified in options 
*/
+int ignore_io_errors;
 } DASHContext;
 
 static struct codec_string {
@@ -846,7 +847,10 @@ static int write_manifest(AVFormatContext *s, int final)
 av_dict_free(&opts);
 if (ret < 0) {
 av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", 
temp_filename);
-return ret;
+if (c->ignore_io_errors)
+return 0;
+else
+return ret;
 }
 out = c->mpd_out;
 avio_printf(out, "\n");
@@ -937,7 +941,10 @@ static int write_manifest(AVFormatContext *s, int final)
 av_dict_free(&opts);
 if (ret < 0) {
 av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", 
temp_filename);
-return ret;
+if (c->ignore_io_errors)
+return 0;
+else
+return ret;
 }
 
 ff_hls_write_playlist_version(c->m3u8_out, 7);
@@ -1565,8 +1572,12 @@ static int dash_write_packet(AVFormatContext *s, 
AVPacket *pkt)
 set_http_options(&opts, c);
 ret = dashenc_io_open(s, &os->out, os->temp_path, &opts);
 av_dict_free(&opts);
-if (ret < 0)
-return ret;
+if (ret < 0) {
+if (c->ignore_io_errors)
+return 0;
+else
+return ret;
+}
 }
 
 //write out the data immediately in streaming mode
@@ -1577,9 +1588,11 @@ static int dash_write_packet(AVFormatContext *s, 
AVPacket *pkt)
 write_styp(os->ctx->pb);
 avio_flush(os->ctx->pb);
 len = avio_get_dyn_buf (os->ctx->pb, &buf);
-avio_write(os->out, buf + os->written_len, len - os->written_len);
+if (os->out) {
+avio_write(os->out, buf + os->written_len, len - os->written_len);
+avio_flush(os->out);
+}
 os->written_len = len;
-avio_flush(os->out);
 }
 
 return ret;
@@ -1670,6 +1683,7 @@ static const AVOption options[] = {
 { "auto", "select segment file format based on codec", 0, 
AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_AUTO }, 0, UINT_MAX,   E, 
"segment_type"},
 { "mp4", "make segment file in ISOBMFF format", 0, AV_OPT_TYPE_CONST, 
{.i64 = SEGMENT_TYPE_MP4 }, 0, UINT_MAX,   E, "segment_type"},
 { "webm", "make segment file in WebM format", 0, AV_OPT_TYPE_CONST, {.i64 
= SEGMENT_TYPE_WEBM }, 0, UINT_MAX,   E, "segment_type"},
+{ "ignore_io_errors", "Ignore IO errors during open and write. Useful for 
long-duration runs with network output", OFFSET(ignore_io_errors), 
AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
 { NULL },
 };
 
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/movenc : Don't write sidx for empty urls

2018-11-28 Thread Karthick J
When movenc is used by other segmenting muxers such as dashenc, url field is 
always empty.
In such cases it is better to not write sidx, instead of throwing errors.
---
 libavformat/movenc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 6dab5193b0..150a505a4a 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -6706,6 +6706,9 @@ static int mov_write_trailer(AVFormatContext *s)
mov->tracks[i].data_offset = 0;
 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) {
 int64_t end;
+// If url is an empty string("") don't write sidx atom.
+if (s->url[0] == '\0')
+return res;
 av_log(s, AV_LOG_INFO, "Starting second pass: inserting sidx 
atoms\n");
 res = shift_data(s);
 if (res < 0)
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2] avformat/movenc : Don't write sidx for empty urls

2018-11-28 Thread Karthick J
When movenc is used by other segmenting muxers such as dashenc, url field is 
always empty.
In such cases it is better to not write sidx, instead of throwing errors.
---
 libavformat/movenc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 6dab5193b0..d47ecc65ca 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -6706,6 +6706,9 @@ static int mov_write_trailer(AVFormatContext *s)
mov->tracks[i].data_offset = 0;
 if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) {
 int64_t end;
+// If url is an empty string("") don't write sidx atom.
+if (s->url[0] == '\0')
+return 0;
 av_log(s, AV_LOG_INFO, "Starting second pass: inserting sidx 
atoms\n");
 res = shift_data(s);
 if (res < 0)
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 1/2] avformat/dashenc: Handled the error from dashenc_io_open()

2018-11-28 Thread Karthick J
---
 libavformat/dashenc.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 6ce70e0076..2f403257c0 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -527,8 +527,12 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, AVFormatCont
 snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? 
"%s.tmp" : "%s", filename_hls);
 
 set_http_options(&http_opts, c);
-dashenc_io_open(s, &c->m3u8_out, temp_filename_hls, &http_opts);
+ret = dashenc_io_open(s, &c->m3u8_out, temp_filename_hls, &http_opts);
 av_dict_free(&http_opts);
+if (ret < 0) {
+av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", 
temp_filename_hls);
+return;
+}
 for (i = start_index; i < os->nb_segments; i++) {
 Segment *seg = os->segments[i];
 double duration = (double) seg->duration / timescale;
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 2/2] avformat/dashenc: Added an option to ignore io errors

2018-11-28 Thread Karthick J
When dashenc has to run for long duration(say 24x7 live stream), one can enable 
this option to ignore the io failure of few segment's upload due to an 
intermittent network issues.
When the network connection recovers dashenc will continue with the upload of 
the current segments, leading to the recovery of the stream.
---
 doc/muxers.texi   |  3 +++
 libavformat/dashenc.c | 17 +++--
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index a02ac01b55..f1cc6f5fee 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -300,6 +300,9 @@ If this flag is set, the dash segment files will be in in 
ISOBMFF format.
 @item webm
 If this flag is set, the dash segment files will be in in WebM format.
 
+@item -ignore_io_errors @var{ignore_io_errors}
+Ignore IO errors during open and write. Useful for long-duration runs with 
network output.
+
 @end table
 
 @anchor{framecrc}
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 2f403257c0..04218af6a6 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -138,6 +138,7 @@ typedef struct DASHContext {
 int index_correction;
 char *format_options_str;
 SegmentType segment_type_option;  /* segment type as specified in options 
*/
+int ignore_io_errors;
 } DASHContext;
 
 static struct codec_string {
@@ -846,7 +847,7 @@ static int write_manifest(AVFormatContext *s, int final)
 av_dict_free(&opts);
 if (ret < 0) {
 av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", 
temp_filename);
-return ret;
+return c->ignore_io_errors ? 0 : ret;
 }
 out = c->mpd_out;
 avio_printf(out, "\n");
@@ -937,7 +938,7 @@ static int write_manifest(AVFormatContext *s, int final)
 av_dict_free(&opts);
 if (ret < 0) {
 av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", 
temp_filename);
-return ret;
+return c->ignore_io_errors ? 0 : ret;
 }
 
 ff_hls_write_playlist_version(c->m3u8_out, 7);
@@ -1565,8 +1566,9 @@ static int dash_write_packet(AVFormatContext *s, AVPacket 
*pkt)
 set_http_options(&opts, c);
 ret = dashenc_io_open(s, &os->out, os->temp_path, &opts);
 av_dict_free(&opts);
-if (ret < 0)
-return ret;
+if (ret < 0) {
+return c->ignore_io_errors ? 0 : ret;
+}
 }
 
 //write out the data immediately in streaming mode
@@ -1577,9 +1579,11 @@ static int dash_write_packet(AVFormatContext *s, 
AVPacket *pkt)
 write_styp(os->ctx->pb);
 avio_flush(os->ctx->pb);
 len = avio_get_dyn_buf (os->ctx->pb, &buf);
-avio_write(os->out, buf + os->written_len, len - os->written_len);
+if (os->out) {
+avio_write(os->out, buf + os->written_len, len - os->written_len);
+avio_flush(os->out);
+}
 os->written_len = len;
-avio_flush(os->out);
 }
 
 return ret;
@@ -1670,6 +1674,7 @@ static const AVOption options[] = {
 { "auto", "select segment file format based on codec", 0, 
AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_AUTO }, 0, UINT_MAX,   E, 
"segment_type"},
 { "mp4", "make segment file in ISOBMFF format", 0, AV_OPT_TYPE_CONST, 
{.i64 = SEGMENT_TYPE_MP4 }, 0, UINT_MAX,   E, "segment_type"},
 { "webm", "make segment file in WebM format", 0, AV_OPT_TYPE_CONST, {.i64 
= SEGMENT_TYPE_WEBM }, 0, UINT_MAX,   E, "segment_type"},
+{ "ignore_io_errors", "Ignore IO errors during open and write. Useful for 
long-duration runs with network output", OFFSET(ignore_io_errors), 
AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
 { NULL },
 };
 
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/dashenc: Added proper logging when io_open fails for write

2018-11-29 Thread Karthick J
---
 libavformat/dashenc.c | 19 +--
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 04218af6a6..09207dcf44 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -209,6 +209,15 @@ static const char *get_format_str(SegmentType 
segment_type) {
 return NULL;
 }
 
+static int handle_io_open_error(AVFormatContext *s, int err, char *url) {
+DASHContext *c = s->priv_data;
+char errbuf[AV_ERROR_MAX_STRING_SIZE];
+av_strerror(err, errbuf, sizeof(errbuf));
+av_log(s, c->ignore_io_errors ? AV_LOG_WARNING : AV_LOG_ERROR,
+   "Unable to open %s for writing: %s\n", url, errbuf);
+return c->ignore_io_errors ? 0 : err;
+}
+
 static inline SegmentType select_segment_type(SegmentType segment_type, enum 
AVCodecID codec_id)
 {
 if (segment_type == SEGMENT_TYPE_AUTO) {
@@ -531,7 +540,7 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, AVFormatCont
 ret = dashenc_io_open(s, &c->m3u8_out, temp_filename_hls, &http_opts);
 av_dict_free(&http_opts);
 if (ret < 0) {
-av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", 
temp_filename_hls);
+handle_io_open_error(s, ret, temp_filename_hls);
 return;
 }
 for (i = start_index; i < os->nb_segments; i++) {
@@ -846,8 +855,7 @@ static int write_manifest(AVFormatContext *s, int final)
 ret = dashenc_io_open(s, &c->mpd_out, temp_filename, &opts);
 av_dict_free(&opts);
 if (ret < 0) {
-av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", 
temp_filename);
-return c->ignore_io_errors ? 0 : ret;
+return handle_io_open_error(s, ret, temp_filename);
 }
 out = c->mpd_out;
 avio_printf(out, "\n");
@@ -937,8 +945,7 @@ static int write_manifest(AVFormatContext *s, int final)
 ret = dashenc_io_open(s, &c->m3u8_out, temp_filename, &opts);
 av_dict_free(&opts);
 if (ret < 0) {
-av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", 
temp_filename);
-return c->ignore_io_errors ? 0 : ret;
+return handle_io_open_error(s, ret, temp_filename);
 }
 
 ff_hls_write_playlist_version(c->m3u8_out, 7);
@@ -1567,7 +1574,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket 
*pkt)
 ret = dashenc_io_open(s, &os->out, os->temp_path, &opts);
 av_dict_free(&opts);
 if (ret < 0) {
-return c->ignore_io_errors ? 0 : ret;
+return handle_io_open_error(s, ret, os->temp_path);
 }
 }
 
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 2/2] avformat/dashenc: Used the movenc option no_sidx instead of global_sidx

2018-12-04 Thread Karthick J
Anyways the intended behaviour was to disable SIDX atom.
---
 libavformat/dashenc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 4d9b564a94..84bc58d6c1 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -1162,7 +1162,7 @@ static int dash_init(AVFormatContext *s)
 
 if (os->segment_type == SEGMENT_TYPE_MP4) {
 if (c->streaming)
-av_dict_set(&opts, "movflags", 
"frag_every_frame+dash+delay_moov+global_sidx", 0);
+av_dict_set(&opts, "movflags", 
"frag_every_frame+dash+delay_moov+no_sidx", 0);
 else
 av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 
0);
 } else {
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 1/2] avformat/movenc: Added an option to disable SIDX atom

2018-12-04 Thread Karthick J
---
 doc/muxers.texi  | 2 ++
 libavformat/movenc.c | 7 +--
 libavformat/movenc.h | 1 +
 3 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index f1cc6f5fee..6ca27b04a3 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -1325,6 +1325,8 @@ more efficient), but with this option set, the muxer 
writes one moof/mdat
 pair for each track, making it easier to separate tracks.
 
 This option is implicitly set when writing ismv (Smooth Streaming) files.
+@item -movflags no_sidx
+Don't write sidx atom.
 @item -movflags faststart
 Run a second pass moving the index (moov atom) to the beginning of the file.
 This operation can take a while, and will not work in various situations such
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 6dab5193b0..83278e8bfd 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -75,6 +75,7 @@ static const AVOption options[] = {
 { "frag_discont", "Signal that the next fragment is discontinuous from 
earlier ones", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_DISCONT}, 
INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
 { "delay_moov", "Delay writing the initial moov until the first fragment 
is cut, or until the first fragment flush", 0, AV_OPT_TYPE_CONST, {.i64 = 
FF_MOV_FLAG_DELAY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 
"movflags" },
 { "global_sidx", "Write a global sidx index at the start of the file", 0, 
AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_GLOBAL_SIDX}, INT_MIN, INT_MAX, 
AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
+{ "no_sidx", "Don't write sidx atom", 0, AV_OPT_TYPE_CONST, {.i64 = 
FF_MOV_FLAG_NO_SIDX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" 
},
 { "write_colr", "Write colr atom (Experimental, may be renamed or changed, 
do not use from scripts)", 0, AV_OPT_TYPE_CONST, {.i64 = 
FF_MOV_FLAG_WRITE_COLR}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 
"movflags" },
 { "write_gama", "Write deprecated gama atom", 0, AV_OPT_TYPE_CONST, {.i64 
= FF_MOV_FLAG_WRITE_GAMA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 
"movflags" },
 { "use_metadata_tags", "Use mdta atom for metadata.", 0, 
AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_USE_MDTA}, INT_MIN, INT_MAX, 
AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
@@ -4603,7 +4604,8 @@ static int mov_write_moof_tag(AVIOContext *pb, 
MOVMuxContext *mov, int tracks,
 mov_write_moof_tag_internal(avio_buf, mov, tracks, 0);
 moof_size = ffio_close_null_buf(avio_buf);
 
-if (mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & 
FF_MOV_FLAG_GLOBAL_SIDX))
+if (mov->flags & FF_MOV_FLAG_DASH &&
+!(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | FF_MOV_FLAG_NO_SIDX)))
 mov_write_sidx_tags(pb, mov, tracks, moof_size + 8 + mdat_size);
 
 if (mov->write_prft > MOV_PRFT_NONE && mov->write_prft < MOV_PRFT_NB)
@@ -5422,7 +5424,8 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
  * the next fragment. This means the cts of the first sample must
  * be the same in all fragments, unless end_pts was updated by
  * the packet causing the fragment to be written. */
-if ((mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & 
FF_MOV_FLAG_GLOBAL_SIDX)) ||
+if ((mov->flags & FF_MOV_FLAG_DASH &&
+!(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | 
FF_MOV_FLAG_NO_SIDX))) ||
 mov->mode == MODE_ISM)
 pkt->pts = pkt->dts + trk->end_pts - 
trk->cluster[trk->entry].dts;
 } else {
diff --git a/libavformat/movenc.h b/libavformat/movenc.h
index fe605d1ad2..ee6749bce2 100644
--- a/libavformat/movenc.h
+++ b/libavformat/movenc.h
@@ -257,6 +257,7 @@ typedef struct MOVMuxContext {
 #define FF_MOV_FLAG_SKIP_TRAILER  (1 << 18)
 #define FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS  (1 << 19)
 #define FF_MOV_FLAG_FRAG_EVERY_FRAME  (1 << 20)
+#define FF_MOV_FLAG_NO_SIDX   (1 << 21)
 
 int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt);
 
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 1/2] avformat/movenc: Added an option to disable SIDX atom

2018-12-04 Thread Karthick J
---
 doc/muxers.texi  |  4 
 libavformat/movenc.c | 12 ++--
 libavformat/movenc.h |  1 +
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index f1cc6f5fee..ca10741900 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -1325,6 +1325,10 @@ more efficient), but with this option set, the muxer 
writes one moof/mdat
 pair for each track, making it easier to separate tracks.
 
 This option is implicitly set when writing ismv (Smooth Streaming) files.
+@item -movflags skip_sidx
+Skip writing of sidx atom. When bitrate overhead due to sidx atom is high,
+this option could be used for cases where sidx atom is not mandatory.
+When global_sidx flag is enabled, this option will be ignored. 
 @item -movflags faststart
 Run a second pass moving the index (moov atom) to the beginning of the file.
 This operation can take a while, and will not work in various situations such
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 6dab5193b0..3781a32895 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -75,6 +75,7 @@ static const AVOption options[] = {
 { "frag_discont", "Signal that the next fragment is discontinuous from 
earlier ones", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_DISCONT}, 
INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
 { "delay_moov", "Delay writing the initial moov until the first fragment 
is cut, or until the first fragment flush", 0, AV_OPT_TYPE_CONST, {.i64 = 
FF_MOV_FLAG_DELAY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 
"movflags" },
 { "global_sidx", "Write a global sidx index at the start of the file", 0, 
AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_GLOBAL_SIDX}, INT_MIN, INT_MAX, 
AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
+{ "skip_sidx", "Skip writing of sidx atom", 0, AV_OPT_TYPE_CONST, {.i64 = 
FF_MOV_FLAG_SKIP_SIDX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 
"movflags" },
 { "write_colr", "Write colr atom (Experimental, may be renamed or changed, 
do not use from scripts)", 0, AV_OPT_TYPE_CONST, {.i64 = 
FF_MOV_FLAG_WRITE_COLR}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 
"movflags" },
 { "write_gama", "Write deprecated gama atom", 0, AV_OPT_TYPE_CONST, {.i64 
= FF_MOV_FLAG_WRITE_GAMA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 
"movflags" },
 { "use_metadata_tags", "Use mdta atom for metadata.", 0, 
AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_USE_MDTA}, INT_MIN, INT_MAX, 
AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
@@ -4603,7 +4604,8 @@ static int mov_write_moof_tag(AVIOContext *pb, 
MOVMuxContext *mov, int tracks,
 mov_write_moof_tag_internal(avio_buf, mov, tracks, 0);
 moof_size = ffio_close_null_buf(avio_buf);
 
-if (mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & 
FF_MOV_FLAG_GLOBAL_SIDX))
+if (mov->flags & FF_MOV_FLAG_DASH &&
+!(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | FF_MOV_FLAG_SKIP_SIDX)))
 mov_write_sidx_tags(pb, mov, tracks, moof_size + 8 + mdat_size);
 
 if (mov->write_prft > MOV_PRFT_NONE && mov->write_prft < MOV_PRFT_NB)
@@ -5422,7 +5424,8 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
  * the next fragment. This means the cts of the first sample must
  * be the same in all fragments, unless end_pts was updated by
  * the packet causing the fragment to be written. */
-if ((mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & 
FF_MOV_FLAG_GLOBAL_SIDX)) ||
+if ((mov->flags & FF_MOV_FLAG_DASH &&
+!(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | 
FF_MOV_FLAG_SKIP_SIDX))) ||
 mov->mode == MODE_ISM)
 pkt->pts = pkt->dts + trk->end_pts - 
trk->cluster[trk->entry].dts;
 } else {
@@ -6067,6 +6070,11 @@ static int mov_init(AVFormatContext *s)
 s->flags &= ~AVFMT_FLAG_AUTO_BSF;
 }
 
+if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX && s->flags & 
FF_MOV_FLAG_SKIP_SIDX) {
+av_log(s, AV_LOG_WARNING, "Global SIDX enabled; Ignoring skip_sidx 
option\n");
+s->flags &= ~FF_MOV_FLAG_SKIP_SIDX;
+}
+
 if (mov->flags & FF_MOV_FLAG_FASTSTART) {
 mov->reserved_moov_size = -1;
 }
diff --git a/libavformat/movenc.h b/libavformat/movenc.h
index fe605d1ad2..68d6f23a5a 100644
--- a/libavformat/movenc.h
+++ b/libavformat/movenc.h
@@ -257,6 +257,7 @@ typedef struct MOVMuxContext {
 #define FF_MOV_FLAG_SKIP_TRAILER  (1 << 18)
 #define FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS  (1 << 19)
 #define FF_MOV_FLAG_FRAG_EVERY_FRAME  (1 << 20)
+#define FF_MOV_FLAG_SKIP_SIDX (1 << 21)
 
 int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt);
 
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 2/2] avformat/dashenc: Used the movenc option skip_sidx instead of global_sidx

2018-12-04 Thread Karthick J
Anyways the intended behaviour was to disable SIDX atom.
---
 libavformat/dashenc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 4d9b564a94..585b34cb97 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -1162,7 +1162,7 @@ static int dash_init(AVFormatContext *s)
 
 if (os->segment_type == SEGMENT_TYPE_MP4) {
 if (c->streaming)
-av_dict_set(&opts, "movflags", 
"frag_every_frame+dash+delay_moov+global_sidx", 0);
+av_dict_set(&opts, "movflags", 
"frag_every_frame+dash+delay_moov+skip_sidx", 0);
 else
 av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 
0);
 } else {
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v3] avformat/movenc: Added an option to disable SIDX atom

2018-12-05 Thread Karthick J
---
 doc/muxers.texi  |  4 
 libavformat/movenc.c | 12 ++--
 libavformat/movenc.h |  1 +
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index f1cc6f5fee..ca10741900 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -1325,6 +1325,10 @@ more efficient), but with this option set, the muxer 
writes one moof/mdat
 pair for each track, making it easier to separate tracks.
 
 This option is implicitly set when writing ismv (Smooth Streaming) files.
+@item -movflags skip_sidx
+Skip writing of sidx atom. When bitrate overhead due to sidx atom is high,
+this option could be used for cases where sidx atom is not mandatory.
+When global_sidx flag is enabled, this option will be ignored. 
 @item -movflags faststart
 Run a second pass moving the index (moov atom) to the beginning of the file.
 This operation can take a while, and will not work in various situations such
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 6dab5193b0..2f7755bf69 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -75,6 +75,7 @@ static const AVOption options[] = {
 { "frag_discont", "Signal that the next fragment is discontinuous from 
earlier ones", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_DISCONT}, 
INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
 { "delay_moov", "Delay writing the initial moov until the first fragment 
is cut, or until the first fragment flush", 0, AV_OPT_TYPE_CONST, {.i64 = 
FF_MOV_FLAG_DELAY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 
"movflags" },
 { "global_sidx", "Write a global sidx index at the start of the file", 0, 
AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_GLOBAL_SIDX}, INT_MIN, INT_MAX, 
AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
+{ "skip_sidx", "Skip writing of sidx atom", 0, AV_OPT_TYPE_CONST, {.i64 = 
FF_MOV_FLAG_SKIP_SIDX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 
"movflags" },
 { "write_colr", "Write colr atom (Experimental, may be renamed or changed, 
do not use from scripts)", 0, AV_OPT_TYPE_CONST, {.i64 = 
FF_MOV_FLAG_WRITE_COLR}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 
"movflags" },
 { "write_gama", "Write deprecated gama atom", 0, AV_OPT_TYPE_CONST, {.i64 
= FF_MOV_FLAG_WRITE_GAMA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 
"movflags" },
 { "use_metadata_tags", "Use mdta atom for metadata.", 0, 
AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_USE_MDTA}, INT_MIN, INT_MAX, 
AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
@@ -4603,7 +4604,8 @@ static int mov_write_moof_tag(AVIOContext *pb, 
MOVMuxContext *mov, int tracks,
 mov_write_moof_tag_internal(avio_buf, mov, tracks, 0);
 moof_size = ffio_close_null_buf(avio_buf);
 
-if (mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & 
FF_MOV_FLAG_GLOBAL_SIDX))
+if (mov->flags & FF_MOV_FLAG_DASH &&
+!(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | FF_MOV_FLAG_SKIP_SIDX)))
 mov_write_sidx_tags(pb, mov, tracks, moof_size + 8 + mdat_size);
 
 if (mov->write_prft > MOV_PRFT_NONE && mov->write_prft < MOV_PRFT_NB)
@@ -5422,7 +5424,8 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
  * the next fragment. This means the cts of the first sample must
  * be the same in all fragments, unless end_pts was updated by
  * the packet causing the fragment to be written. */
-if ((mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & 
FF_MOV_FLAG_GLOBAL_SIDX)) ||
+if ((mov->flags & FF_MOV_FLAG_DASH &&
+!(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | 
FF_MOV_FLAG_SKIP_SIDX))) ||
 mov->mode == MODE_ISM)
 pkt->pts = pkt->dts + trk->end_pts - 
trk->cluster[trk->entry].dts;
 } else {
@@ -6067,6 +6070,11 @@ static int mov_init(AVFormatContext *s)
 s->flags &= ~AVFMT_FLAG_AUTO_BSF;
 }
 
+if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX && s->flags & 
FF_MOV_FLAG_SKIP_SIDX) {
+av_log(s, AV_LOG_WARNING, "Global SIDX enabled; Ignoring skip_sidx 
option\n");
+mov->flags &= ~FF_MOV_FLAG_SKIP_SIDX;
+}
+
 if (mov->flags & FF_MOV_FLAG_FASTSTART) {
 mov->reserved_moov_size = -1;
 }
diff --git a/libavformat/movenc.h b/libavformat/movenc.h
index fe605d1ad2..68d6f23a5a 100644
--- a/libavformat/movenc.h
+++ b/libavformat/movenc.h
@@ -257,6 +257,7 @@ typedef struct MOVMuxContext {
 #define FF_MOV_FLAG_SKIP_TRAILER  (1 << 18)
 #define FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS  (1 << 19)
 #define FF_MOV_FLAG_FRAG_EVERY_FRAME  (1 << 20)
+#define FF_MOV_FLAG_SKIP_SIDX (1 << 21)
 
 int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt);
 
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v4] avformat/movenc: Added an option to disable SIDX atom

2018-12-05 Thread Karthick J
---
 doc/muxers.texi  |  4 
 libavformat/movenc.c | 12 ++--
 libavformat/movenc.h |  1 +
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index f1cc6f5fee..ca10741900 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -1325,6 +1325,10 @@ more efficient), but with this option set, the muxer 
writes one moof/mdat
 pair for each track, making it easier to separate tracks.
 
 This option is implicitly set when writing ismv (Smooth Streaming) files.
+@item -movflags skip_sidx
+Skip writing of sidx atom. When bitrate overhead due to sidx atom is high,
+this option could be used for cases where sidx atom is not mandatory.
+When global_sidx flag is enabled, this option will be ignored. 
 @item -movflags faststart
 Run a second pass moving the index (moov atom) to the beginning of the file.
 This operation can take a while, and will not work in various situations such
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 6dab5193b0..28cf8b719c 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -75,6 +75,7 @@ static const AVOption options[] = {
 { "frag_discont", "Signal that the next fragment is discontinuous from 
earlier ones", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_DISCONT}, 
INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
 { "delay_moov", "Delay writing the initial moov until the first fragment 
is cut, or until the first fragment flush", 0, AV_OPT_TYPE_CONST, {.i64 = 
FF_MOV_FLAG_DELAY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 
"movflags" },
 { "global_sidx", "Write a global sidx index at the start of the file", 0, 
AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_GLOBAL_SIDX}, INT_MIN, INT_MAX, 
AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
+{ "skip_sidx", "Skip writing of sidx atom", 0, AV_OPT_TYPE_CONST, {.i64 = 
FF_MOV_FLAG_SKIP_SIDX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 
"movflags" },
 { "write_colr", "Write colr atom (Experimental, may be renamed or changed, 
do not use from scripts)", 0, AV_OPT_TYPE_CONST, {.i64 = 
FF_MOV_FLAG_WRITE_COLR}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 
"movflags" },
 { "write_gama", "Write deprecated gama atom", 0, AV_OPT_TYPE_CONST, {.i64 
= FF_MOV_FLAG_WRITE_GAMA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 
"movflags" },
 { "use_metadata_tags", "Use mdta atom for metadata.", 0, 
AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_USE_MDTA}, INT_MIN, INT_MAX, 
AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
@@ -4603,7 +4604,8 @@ static int mov_write_moof_tag(AVIOContext *pb, 
MOVMuxContext *mov, int tracks,
 mov_write_moof_tag_internal(avio_buf, mov, tracks, 0);
 moof_size = ffio_close_null_buf(avio_buf);
 
-if (mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & 
FF_MOV_FLAG_GLOBAL_SIDX))
+if (mov->flags & FF_MOV_FLAG_DASH &&
+!(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | FF_MOV_FLAG_SKIP_SIDX)))
 mov_write_sidx_tags(pb, mov, tracks, moof_size + 8 + mdat_size);
 
 if (mov->write_prft > MOV_PRFT_NONE && mov->write_prft < MOV_PRFT_NB)
@@ -5422,7 +5424,8 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
  * the next fragment. This means the cts of the first sample must
  * be the same in all fragments, unless end_pts was updated by
  * the packet causing the fragment to be written. */
-if ((mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & 
FF_MOV_FLAG_GLOBAL_SIDX)) ||
+if ((mov->flags & FF_MOV_FLAG_DASH &&
+!(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | 
FF_MOV_FLAG_SKIP_SIDX))) ||
 mov->mode == MODE_ISM)
 pkt->pts = pkt->dts + trk->end_pts - 
trk->cluster[trk->entry].dts;
 } else {
@@ -6067,6 +6070,11 @@ static int mov_init(AVFormatContext *s)
 s->flags &= ~AVFMT_FLAG_AUTO_BSF;
 }
 
+if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX && mov->flags & 
FF_MOV_FLAG_SKIP_SIDX) {
+av_log(s, AV_LOG_WARNING, "Global SIDX enabled; Ignoring skip_sidx 
option\n");
+mov->flags &= ~FF_MOV_FLAG_SKIP_SIDX;
+}
+
 if (mov->flags & FF_MOV_FLAG_FASTSTART) {
 mov->reserved_moov_size = -1;
 }
diff --git a/libavformat/movenc.h b/libavformat/movenc.h
index fe605d1ad2..68d6f23a5a 100644
--- a/libavformat/movenc.h
+++ b/libavformat/movenc.h
@@ -257,6 +257,7 @@ typedef struct MOVMuxContext {
 #define FF_MOV_FLAG_SKIP_TRAILER  (1 << 18)
 #define FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS  (1 << 19)
 #define FF_MOV_FLAG_FRAG_EVERY_FRAME  (1 << 20)
+#define FF_MOV_FLAG_SKIP_SIDX (1 << 21)
 
 int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt);
 
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 2/2] avformat/hlsenc : Added an option to ignore IO errors

2018-12-06 Thread Karthick J
Useful for long duration runs with network output
---
 doc/muxers.texi  |  3 +++
 libavformat/hlsenc.c | 41 +++--
 2 files changed, 34 insertions(+), 10 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index ca10741900..8eefcf1e82 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -1018,6 +1018,9 @@ Use persistent HTTP connections. Applicable only for HTTP 
output.
 @item timeout
 Set timeout for socket I/O operations. Applicable only for HTTP output.
 
+@item -ignore_io_errors
+Ignore IO errors during open, write and delete. Useful for long-duration runs 
with network output.
+
 @end table
 
 @anchor{ico}
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 42adcfbab1..bdd2a113bd 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -227,6 +227,7 @@ typedef struct HLSContext {
 AVIOContext *m3u8_out;
 AVIOContext *sub_m3u8_out;
 int64_t timeout;
+int ignore_io_errors;
 } HLSContext;
 
 static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,
@@ -496,8 +497,11 @@ static int hls_delete_old_segments(AVFormatContext *s, 
HLSContext *hls,
 proto = avio_find_protocol_name(s->url);
 if (hls->method || (proto && !av_strcasecmp(proto, "http"))) {
 av_dict_set(&options, "method", "DELETE", 0);
-if ((ret = vs->avf->io_open(vs->avf, &out, path, AVIO_FLAG_WRITE, 
&options)) < 0)
+if ((ret = vs->avf->io_open(vs->avf, &out, path, AVIO_FLAG_WRITE, 
&options)) < 0) {
+if (hls->ignore_io_errors)
+ret = 0;
 goto fail;
+}
 ff_format_io_close(vs->avf, &out);
 } else if (unlink(path) < 0) {
 av_log(hls, AV_LOG_ERROR, "failed to delete old segment %s: %s\n",
@@ -525,6 +529,8 @@ static int hls_delete_old_segments(AVFormatContext *s, 
HLSContext *hls,
 if (hls->method || (proto && !av_strcasecmp(proto, "http"))) {
 av_dict_set(&options, "method", "DELETE", 0);
 if ((ret = vs->vtt_avf->io_open(vs->vtt_avf, &out, sub_path, 
AVIO_FLAG_WRITE, &options)) < 0) {
+if (hls->ignore_io_errors)
+ret = 0;
 av_free(sub_path);
 goto fail;
 }
@@ -1380,8 +1386,11 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 
 set_http_options(s, &options, hls);
 snprintf(temp_filename, sizeof(temp_filename), use_temp_file ? "%s.tmp" : 
"%s", vs->m3u8_name);
-if ((ret = hlsenc_io_open(s, &hls->m3u8_out, temp_filename, &options)) < 0)
+if ((ret = hlsenc_io_open(s, &hls->m3u8_out, temp_filename, &options)) < 
0) {
+if (hls->ignore_io_errors)
+ret = 0;
 goto fail;
+}
 
 for (en = vs->segments; en; en = en->next) {
 if (target_duration <= en->duration)
@@ -1428,8 +1437,11 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 ff_hls_write_end_list(hls->m3u8_out);
 
 if( vs->vtt_m3u8_name ) {
-if ((ret = hlsenc_io_open(s, &hls->sub_m3u8_out, vs->vtt_m3u8_name, 
&options)) < 0)
+if ((ret = hlsenc_io_open(s, &hls->sub_m3u8_out, vs->vtt_m3u8_name, 
&options)) < 0) {
+if (hls->ignore_io_errors)
+ret = 0;
 goto fail;
+}
 ff_hls_write_playlist_header(hls->sub_m3u8_out, hls->version, 
hls->allowcache,
  target_duration, sequence, 
PLAYLIST_TYPE_NONE);
 for (en = vs->segments; en; en = en->next) {
@@ -1452,7 +1464,6 @@ fail:
 hlsenc_io_close(s, &hls->sub_m3u8_out, vs->vtt_m3u8_name);
 if (use_temp_file)
 ff_rename(temp_filename, vs->m3u8_name, s);
-
 if (ret >= 0 && hls->master_pl_name)
 if (create_master_playlist(s, vs) < 0)
 av_log(s, AV_LOG_WARNING, "Master playlist creation failed\n");
@@ -1611,13 +1622,19 @@ static int hls_start(AVFormatContext *s, VariantStream 
*vs)
 if (err < 0)
 return err;
 } else if (c->segment_type != SEGMENT_TYPE_FMP4) {
-if ((err = hlsenc_io_open(s, &oc->pb, oc->url, &options)) < 0)
+if ((err = hlsenc_io_open(s, &oc->pb, oc->url, &options)) < 0) {
+if (c->ignore_io_errors)
+err = 0;
 goto fail;
+}
 }
 if (vs->vtt_basename) {
 set_http_options(s, &options, c);
-if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->url, &options)) < 0)
+if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->url, &options)) < 0) 
{
+if (c->ignore_io_errors)
+err = 0;
 goto fail;
+}
 }
 av_dict_free(&options);
 
@@ -2257,9 +2274,9 @@ static int hls_write_packet(AVFormatContext *s, AVPacket 
*pkt)
 set_http_options(s, &options, hls);
 ret = hlsenc_io_open(s, &vs->out, vs->avf->url, &options);
  

[FFmpeg-devel] [PATCH 1/2] avformat/hlsenc: Handled error from ff_http_do_new_request() function

2018-12-06 Thread Karthick J
This patch fixes the segmentation fault issues due to unhandled errors from 
ff_http_do_new_request function.
---
 libavformat/hlsenc.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 31ef0237ae..42adcfbab1 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -241,6 +241,9 @@ static int hlsenc_io_open(AVFormatContext *s, AVIOContext 
**pb, char *filename,
 URLContext *http_url_context = ffio_geturlcontext(*pb);
 av_assert0(http_url_context);
 err = ff_http_do_new_request(http_url_context, filename);
+if (err < 0)
+ff_format_io_close(s, pb);
+
 #endif
 }
 return err;
@@ -249,6 +252,8 @@ static int hlsenc_io_open(AVFormatContext *s, AVIOContext 
**pb, char *filename,
 static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char 
*filename) {
 HLSContext *hls = s->priv_data;
 int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
+if (!*pb)
+return;
 if (!http_base_proto || !hls->http_persistent || hls->key_info_file || 
hls->encrypt) {
 ff_format_io_close(s, pb);
 #if CONFIG_HTTP_PROTOCOL
@@ -2329,7 +2334,8 @@ static int hls_write_packet(AVFormatContext *s, AVPacket 
*pkt)
 }
 
 vs->packets_written++;
-ret = ff_write_chained(oc, stream_index, pkt, s, 0);
+if (oc->pb)
+ret = ff_write_chained(oc, stream_index, pkt, s, 0);
 
 return ret;
 }
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 1/2] avformat/dashenc : Refactored HLS media playlist related code

2018-12-11 Thread Karthick J
Made it as a separate function, so that it could be reused (in future)
---
 libavformat/dashenc.c | 135 +++---
 1 file changed, 75 insertions(+), 60 deletions(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 585b34cb97..f797b7bd1c 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -407,6 +407,78 @@ static void get_hls_playlist_name(char *playlist_name, int 
string_size,
 snprintf(playlist_name, string_size, "media_%d.m3u8", id);
 }
 
+static void get_start_index_number(OutputStream *os, DASHContext *c,
+   int *start_index, int *start_number) {
+*start_index = 0;
+*start_number = 1;
+if (c->window_size) {
+*start_index  = FFMAX(os->nb_segments   - c->window_size, 0);
+*start_number = FFMAX(os->segment_index - c->window_size, 1);
+}
+}
+
+static void write_hls_media_playlist(OutputStream *os, AVFormatContext *s,
+ int representation_id, int final) {
+DASHContext *c = s->priv_data;
+int timescale = os->ctx->streams[0]->time_base.den;
+char temp_filename_hls[1024];
+char filename_hls[1024];
+AVDictionary *http_opts = NULL;
+int target_duration = 0;
+int ret = 0;
+const char *proto = avio_find_protocol_name(c->dirname);
+int use_rename = proto && !strcmp(proto, "file");
+int i, start_index, start_number;
+
+get_start_index_number(os, c, &start_index, &start_number);
+get_hls_playlist_name(filename_hls, sizeof(filename_hls),
+  c->dirname, representation_id);
+
+snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? 
"%s.tmp" : "%s", filename_hls);
+
+set_http_options(&http_opts, c);
+ret = dashenc_io_open(s, &c->m3u8_out, temp_filename_hls, &http_opts);
+av_dict_free(&http_opts);
+if (ret < 0) {
+handle_io_open_error(s, ret, temp_filename_hls);
+return;
+}
+for (i = start_index; i < os->nb_segments; i++) {
+Segment *seg = os->segments[i];
+double duration = (double) seg->duration / timescale;
+if (target_duration <= duration)
+target_duration = lrint(duration);
+}
+
+ff_hls_write_playlist_header(c->m3u8_out, 6, -1, target_duration,
+ start_number, PLAYLIST_TYPE_NONE);
+
+ff_hls_write_init_file(c->m3u8_out, os->initfile, c->single_file,
+   os->init_range_length, os->init_start_pos);
+
+for (i = start_index; i < os->nb_segments; i++) {
+Segment *seg = os->segments[i];
+ret = ff_hls_write_file_entry(c->m3u8_out, 0, c->single_file,
+(double) seg->duration / timescale, 0,
+seg->range_length, seg->start_pos, NULL,
+c->single_file ? os->initfile : seg->file,
+NULL);
+if (ret < 0) {
+av_log(os->ctx, AV_LOG_WARNING, "ff_hls_write_file_entry get 
error\n");
+}
+}
+
+if (final)
+ff_hls_write_end_list(c->m3u8_out);
+
+dashenc_io_close(s, &c->m3u8_out, temp_filename_hls);
+
+if (use_rename)
+if (avpriv_io_move(temp_filename_hls, filename_hls) < 0) {
+av_log(os->ctx, AV_LOG_WARNING, "renaming file %s to %s 
failed\n\n", temp_filename_hls, filename_hls);
+}
+}
+
 static int flush_init_segment(AVFormatContext *s, OutputStream *os)
 {
 DASHContext *c = s->priv_data;
@@ -463,11 +535,8 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, AVFormatCont
 int representation_id, int final)
 {
 DASHContext *c = s->priv_data;
-int i, start_index = 0, start_number = 1;
-if (c->window_size) {
-start_index  = FFMAX(os->nb_segments   - c->window_size, 0);
-start_number = FFMAX(os->segment_index - c->window_size, 1);
-}
+int i, start_index, start_number;
+get_start_index_number(os, c, &start_index, &start_number);
 
 if (c->use_template) {
 int timescale = c->use_timeline ? os->ctx->streams[0]->time_base.den : 
AV_TIME_BASE;
@@ -527,61 +596,7 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, AVFormatCont
 }
 if (c->hls_playlist && start_index < os->nb_segments && os->segment_type 
== SEGMENT_TYPE_MP4)
 {
-int timescale = os->ctx->streams[0]->time_base.den;
-char temp_filename_hls[1024];
-char filename_hls[1024];
-AVDictionary *http_opts = NULL;
-int target_duration = 0;
-int ret = 0;
-const char *proto = avio_find_protocol_name(c->dirname);
-int use_rename = proto && !strcmp(proto, "file");
-
-get_hls_playlist_name(filename_hls, sizeof(filename_hls),
-  c->dirname, representation_id);
-
-snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? 
"%s.tmp" : "

[FFmpeg-devel] [PATCH 2/2] avformat/dashenc: Added support for Low-latency HLS(LHLS)

2018-12-11 Thread Karthick J
Apple doesn't have an official spec for LHLS. Meanwhile hls.js player folks are
trying to standardize a open LHLS spec. The draft spec is available in 
https://github.com/video-dev/hlsjs-rfcs/blob/lhls-spec/proposals/0001-lhls.md
This option will also try to comply with the above open spec, till Apple's spec 
officially supports it.
Applicable only when @var{streaming} and @var{hls_playlist} options are enabled.
---
 doc/muxers.texi   |  7 +++
 libavformat/dashenc.c | 31 +++
 2 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 809f88662e..f09a89db82 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -305,6 +305,13 @@ If this flag is set, the dash segment files will be in in 
WebM format.
 @item -ignore_io_errors @var{ignore_io_errors}
 Ignore IO errors during open and write. Useful for long-duration runs with 
network output.
 
+@item -lhls @var{lhls}
+Enable Low-latency HLS(LHLS). Adds #EXT-X-PREFETCH tag with current segment's 
URI.
+Apple doesn't have an official spec for LHLS. Meanwhile hls.js player folks are
+trying to standardize a open LHLS spec. The draft spec is available in 
https://github.com/video-dev/hlsjs-rfcs/blob/lhls-spec/proposals/0001-lhls.md
+This option will also try to comply with the above open spec, till Apple's 
spec officially supports it.
+Applicable only when @var{streaming} and @var{hls_playlist} options are 
enabled.
+
 @end table
 
 @anchor{framecrc}
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index f797b7bd1c..8685642437 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -139,6 +139,7 @@ typedef struct DASHContext {
 char *format_options_str;
 SegmentType segment_type_option;  /* segment type as specified in options 
*/
 int ignore_io_errors;
+int lhls;
 } DASHContext;
 
 static struct codec_string {
@@ -418,7 +419,8 @@ static void get_start_index_number(OutputStream *os, 
DASHContext *c,
 }
 
 static void write_hls_media_playlist(OutputStream *os, AVFormatContext *s,
- int representation_id, int final) {
+ int representation_id, int final,
+ char *prefetch_url) {
 DASHContext *c = s->priv_data;
 int timescale = os->ctx->streams[0]->time_base.den;
 char temp_filename_hls[1024];
@@ -431,6 +433,11 @@ static void write_hls_media_playlist(OutputStream *os, 
AVFormatContext *s,
 int i, start_index, start_number;
 
 get_start_index_number(os, c, &start_index, &start_number);
+
+if (!c->hls_playlist || start_index >= os->nb_segments ||
+os->segment_type != SEGMENT_TYPE_MP4)
+return;
+
 get_hls_playlist_name(filename_hls, sizeof(filename_hls),
   c->dirname, representation_id);
 
@@ -468,6 +475,9 @@ static void write_hls_media_playlist(OutputStream *os, 
AVFormatContext *s,
 }
 }
 
+if (prefetch_url)
+avio_printf(c->m3u8_out, "#EXT-X-PREFETCH:%s\n", prefetch_url);
+
 if (final)
 ff_hls_write_end_list(c->m3u8_out);
 
@@ -594,9 +604,8 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, AVFormatCont
 }
 avio_printf(out, "\t\t\t\t\n");
 }
-if (c->hls_playlist && start_index < os->nb_segments && os->segment_type 
== SEGMENT_TYPE_MP4)
-{
-write_hls_media_playlist(os, s, representation_id, final);
+if (!c->lhls || final) {
+write_hls_media_playlist(os, s, representation_id, final, NULL);
 }
 
 }
@@ -1054,6 +1063,15 @@ static int dash_init(AVFormatContext *s)
 c->seg_duration = c->min_seg_duration;
 }
 #endif
+if (c->lhls && !c->streaming) {
+av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as streaming is 
not enabled\n");
+c->lhls = 0;
+}
+
+if (c->lhls && !c->hls_playlist) {
+av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as hls_playlist 
is not enabled\n");
+c->lhls = 0;
+}
 
 av_strlcpy(c->dirname, s->url, sizeof(c->dirname));
 ptr = strrchr(c->dirname, '/');
@@ -1635,6 +1653,10 @@ static int dash_write_packet(AVFormatContext *s, 
AVPacket *pkt)
 if (ret < 0) {
 return handle_io_open_error(s, ret, os->temp_path);
 }
+if (c->lhls) {
+char *prefetch_url = use_rename ? NULL : os->filename;
+write_hls_media_playlist(os, s, pkt->stream_index, 0, 
prefetch_url);
+}
 }
 
 //write out the data immediately in streaming mode
@@ -1760,6 +1782,7 @@ static const AVOption options[] = {
 { "mp4", "make segment file in ISOBMFF format", 0, AV_OPT_TYPE_CONST, 
{.i64 = SEGMENT_TYPE_MP4 }, 0, UINT_MAX,   E, "segment_type"},
 { "webm", "make segment file in WebM format", 0, AV_OPT_TYPE_CONST, {.i64 
= SEGMENT_TYPE_WEBM }, 0, UINT_MAX,   E, "segment_type"},
 { "ignore_io_errors", "Ignore IO errors during open and write. Useful

[FFmpeg-devel] [PATCH v2 2/2] avformat/dashenc: Added support for Low-latency HLS(Experimental)

2018-12-12 Thread Karthick J
Apple doesn't have an official spec for LHLS. Meanwhile hls.js player folks are
trying to standardize a open LHLS spec. The draft spec is available in 
https://github.com/video-dev/hlsjs-rfcs/blob/lhls-spec/proposals/0001-lhls.md
This option will also try to comply with the above open spec, till Apple's spec 
officially supports it.
Applicable only when @var{streaming} and @var{hls_playlist} options are enabled.
---
 doc/muxers.texi   |  8 
 libavformat/dashenc.c | 37 +
 2 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 809f88662e..4ed46a2220 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -305,6 +305,14 @@ If this flag is set, the dash segment files will be in in 
WebM format.
 @item -ignore_io_errors @var{ignore_io_errors}
 Ignore IO errors during open and write. Useful for long-duration runs with 
network output.
 
+@item -lhls @var{lhls}
+Enable Low-latency HLS(LHLS). Adds #EXT-X-PREFETCH tag with current segment's 
URI.
+Apple doesn't have an official spec for LHLS. Meanwhile hls.js player folks are
+trying to standardize a open LHLS spec. The draft spec is available in 
https://github.com/video-dev/hlsjs-rfcs/blob/lhls-spec/proposals/0001-lhls.md
+This option will also try to comply with the above open spec, till Apple's 
spec officially supports it.
+Applicable only when @var{streaming} and @var{hls_playlist} options are 
enabled.
+This is an experimental feature.
+
 @end table
 
 @anchor{framecrc}
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index f797b7bd1c..cfd0f601d4 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -139,6 +139,7 @@ typedef struct DASHContext {
 char *format_options_str;
 SegmentType segment_type_option;  /* segment type as specified in options 
*/
 int ignore_io_errors;
+int lhls;
 } DASHContext;
 
 static struct codec_string {
@@ -418,7 +419,8 @@ static void get_start_index_number(OutputStream *os, 
DASHContext *c,
 }
 
 static void write_hls_media_playlist(OutputStream *os, AVFormatContext *s,
- int representation_id, int final) {
+ int representation_id, int final,
+ char *prefetch_url) {
 DASHContext *c = s->priv_data;
 int timescale = os->ctx->streams[0]->time_base.den;
 char temp_filename_hls[1024];
@@ -431,6 +433,11 @@ static void write_hls_media_playlist(OutputStream *os, 
AVFormatContext *s,
 int i, start_index, start_number;
 
 get_start_index_number(os, c, &start_index, &start_number);
+
+if (!c->hls_playlist || start_index >= os->nb_segments ||
+os->segment_type != SEGMENT_TYPE_MP4)
+return;
+
 get_hls_playlist_name(filename_hls, sizeof(filename_hls),
   c->dirname, representation_id);
 
@@ -468,6 +475,9 @@ static void write_hls_media_playlist(OutputStream *os, 
AVFormatContext *s,
 }
 }
 
+if (prefetch_url)
+avio_printf(c->m3u8_out, "#EXT-X-PREFETCH:%s\n", prefetch_url);
+
 if (final)
 ff_hls_write_end_list(c->m3u8_out);
 
@@ -594,9 +604,8 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, AVFormatCont
 }
 avio_printf(out, "\t\t\t\t\n");
 }
-if (c->hls_playlist && start_index < os->nb_segments && os->segment_type 
== SEGMENT_TYPE_MP4)
-{
-write_hls_media_playlist(os, s, representation_id, final);
+if (!c->lhls || final) {
+write_hls_media_playlist(os, s, representation_id, final, NULL);
 }
 
 }
@@ -1054,6 +1063,21 @@ static int dash_init(AVFormatContext *s)
 c->seg_duration = c->min_seg_duration;
 }
 #endif
+if (c->lhls && s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
+av_log(s, AV_LOG_ERROR,
+   "LHLS is experimental, Please set -strict experimental in order 
to enable it.\n");
+return AVERROR_EXPERIMENTAL;
+}
+
+if (c->lhls && !c->streaming) {
+av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as streaming is 
not enabled\n");
+c->lhls = 0;
+}
+
+if (c->lhls && !c->hls_playlist) {
+av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as hls_playlist 
is not enabled\n");
+c->lhls = 0;
+}
 
 av_strlcpy(c->dirname, s->url, sizeof(c->dirname));
 ptr = strrchr(c->dirname, '/');
@@ -1635,6 +1659,10 @@ static int dash_write_packet(AVFormatContext *s, 
AVPacket *pkt)
 if (ret < 0) {
 return handle_io_open_error(s, ret, os->temp_path);
 }
+if (c->lhls) {
+char *prefetch_url = use_rename ? NULL : os->filename;
+write_hls_media_playlist(os, s, pkt->stream_index, 0, 
prefetch_url);
+}
 }
 
 //write out the data immediately in streaming mode
@@ -1760,6 +1788,7 @@ static const AVOption options[] = {
 { "mp4", "make segment file in ISOBMFF format", 

[FFmpeg-devel] [PATCH v2 1/2] avformat/dashenc : Refactored HLS media playlist related code

2018-12-12 Thread Karthick J
Made it as a separate function, so that it could be reused (in future)
---
 libavformat/dashenc.c | 135 +++---
 1 file changed, 75 insertions(+), 60 deletions(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 585b34cb97..f797b7bd1c 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -407,6 +407,78 @@ static void get_hls_playlist_name(char *playlist_name, int 
string_size,
 snprintf(playlist_name, string_size, "media_%d.m3u8", id);
 }
 
+static void get_start_index_number(OutputStream *os, DASHContext *c,
+   int *start_index, int *start_number) {
+*start_index = 0;
+*start_number = 1;
+if (c->window_size) {
+*start_index  = FFMAX(os->nb_segments   - c->window_size, 0);
+*start_number = FFMAX(os->segment_index - c->window_size, 1);
+}
+}
+
+static void write_hls_media_playlist(OutputStream *os, AVFormatContext *s,
+ int representation_id, int final) {
+DASHContext *c = s->priv_data;
+int timescale = os->ctx->streams[0]->time_base.den;
+char temp_filename_hls[1024];
+char filename_hls[1024];
+AVDictionary *http_opts = NULL;
+int target_duration = 0;
+int ret = 0;
+const char *proto = avio_find_protocol_name(c->dirname);
+int use_rename = proto && !strcmp(proto, "file");
+int i, start_index, start_number;
+
+get_start_index_number(os, c, &start_index, &start_number);
+get_hls_playlist_name(filename_hls, sizeof(filename_hls),
+  c->dirname, representation_id);
+
+snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? 
"%s.tmp" : "%s", filename_hls);
+
+set_http_options(&http_opts, c);
+ret = dashenc_io_open(s, &c->m3u8_out, temp_filename_hls, &http_opts);
+av_dict_free(&http_opts);
+if (ret < 0) {
+handle_io_open_error(s, ret, temp_filename_hls);
+return;
+}
+for (i = start_index; i < os->nb_segments; i++) {
+Segment *seg = os->segments[i];
+double duration = (double) seg->duration / timescale;
+if (target_duration <= duration)
+target_duration = lrint(duration);
+}
+
+ff_hls_write_playlist_header(c->m3u8_out, 6, -1, target_duration,
+ start_number, PLAYLIST_TYPE_NONE);
+
+ff_hls_write_init_file(c->m3u8_out, os->initfile, c->single_file,
+   os->init_range_length, os->init_start_pos);
+
+for (i = start_index; i < os->nb_segments; i++) {
+Segment *seg = os->segments[i];
+ret = ff_hls_write_file_entry(c->m3u8_out, 0, c->single_file,
+(double) seg->duration / timescale, 0,
+seg->range_length, seg->start_pos, NULL,
+c->single_file ? os->initfile : seg->file,
+NULL);
+if (ret < 0) {
+av_log(os->ctx, AV_LOG_WARNING, "ff_hls_write_file_entry get 
error\n");
+}
+}
+
+if (final)
+ff_hls_write_end_list(c->m3u8_out);
+
+dashenc_io_close(s, &c->m3u8_out, temp_filename_hls);
+
+if (use_rename)
+if (avpriv_io_move(temp_filename_hls, filename_hls) < 0) {
+av_log(os->ctx, AV_LOG_WARNING, "renaming file %s to %s 
failed\n\n", temp_filename_hls, filename_hls);
+}
+}
+
 static int flush_init_segment(AVFormatContext *s, OutputStream *os)
 {
 DASHContext *c = s->priv_data;
@@ -463,11 +535,8 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, AVFormatCont
 int representation_id, int final)
 {
 DASHContext *c = s->priv_data;
-int i, start_index = 0, start_number = 1;
-if (c->window_size) {
-start_index  = FFMAX(os->nb_segments   - c->window_size, 0);
-start_number = FFMAX(os->segment_index - c->window_size, 1);
-}
+int i, start_index, start_number;
+get_start_index_number(os, c, &start_index, &start_number);
 
 if (c->use_template) {
 int timescale = c->use_timeline ? os->ctx->streams[0]->time_base.den : 
AV_TIME_BASE;
@@ -527,61 +596,7 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, AVFormatCont
 }
 if (c->hls_playlist && start_index < os->nb_segments && os->segment_type 
== SEGMENT_TYPE_MP4)
 {
-int timescale = os->ctx->streams[0]->time_base.den;
-char temp_filename_hls[1024];
-char filename_hls[1024];
-AVDictionary *http_opts = NULL;
-int target_duration = 0;
-int ret = 0;
-const char *proto = avio_find_protocol_name(c->dirname);
-int use_rename = proto && !strcmp(proto, "file");
-
-get_hls_playlist_name(filename_hls, sizeof(filename_hls),
-  c->dirname, representation_id);
-
-snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? 
"%s.tmp" : "

[FFmpeg-devel] [PATCH] avformat/file: Fix file delete for Windows

2018-12-30 Thread Karthick J
From: Karthick Jeyapal 

Fixes bug id : 7638
---
 libavformat/file.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/libavformat/file.c b/libavformat/file.c
index 1d321c4..e613b91 100644
--- a/libavformat/file.c
+++ b/libavformat/file.c
@@ -173,7 +173,11 @@ static int file_delete(URLContext *h)
 av_strstart(filename, "file:", &filename);
 
 ret = rmdir(filename);
-if (ret < 0 && errno == ENOTDIR)
+if (ret < 0 && (errno == ENOTDIR
+#   ifdef _WIN32
+|| errno == EINVAL
+#   endif
+))
 ret = unlink(filename);
 if (ret < 0)
 return AVERROR(errno);
-- 
2.7.4

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/dashenc: Format xs:datetime in millisecond precision

2019-01-17 Thread Karthick J
For low latency streaming even milliseconds matter!
---
 libavformat/dashenc.c | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index cfd0f601d4..912c1cf11d 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -32,6 +32,7 @@
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
 #include "libavutil/rational.h"
+#include "libavutil/time.h"
 #include "libavutil/time_internal.h"
 
 #include "avc.h"
@@ -668,12 +669,18 @@ static void write_time(AVIOContext *out, int64_t time)
 
 static void format_date_now(char *buf, int size)
 {
-time_t t = time(NULL);
 struct tm *ptm, tmbuf;
-ptm = gmtime_r(&t, &tmbuf);
+int64_t time_us = av_gettime();
+int64_t time_ms = time_us / 1000;
+const time_t time_s = time_ms / 1000;
+int millisec = time_ms - (time_s * 1000);
+ptm = gmtime_r(&time_s, &tmbuf);
 if (ptm) {
-if (!strftime(buf, size, "%Y-%m-%dT%H:%M:%SZ", ptm))
+int len;
+if (!strftime(buf, size, "%Y-%m-%dT%H:%M:%S", ptm))
 buf[0] = '\0';
+len = strlen(buf);
+snprintf(buf + len, size - len, ".%03dZ", millisec);
 }
 }
 
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2] avformat/dashenc: Format xs:datetime in millisecond precision

2019-01-17 Thread Karthick J
For low latency streaming even milliseconds matter!
---
 libavformat/dashenc.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index cfd0f601d4..9c90cf17e5 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -32,6 +32,7 @@
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
 #include "libavutil/rational.h"
+#include "libavutil/time.h"
 #include "libavutil/time_internal.h"
 
 #include "avc.h"
@@ -668,12 +669,20 @@ static void write_time(AVIOContext *out, int64_t time)
 
 static void format_date_now(char *buf, int size)
 {
-time_t t = time(NULL);
 struct tm *ptm, tmbuf;
-ptm = gmtime_r(&t, &tmbuf);
+int64_t time_us = av_gettime();
+int64_t time_ms = time_us / 1000;
+const time_t time_s = time_ms / 1000;
+int millisec = time_ms - (time_s * 1000);
+ptm = gmtime_r(&time_s, &tmbuf);
 if (ptm) {
-if (!strftime(buf, size, "%Y-%m-%dT%H:%M:%SZ", ptm))
+int len;
+if (!strftime(buf, size, "%Y-%m-%dT%H:%M:%S", ptm)) {
 buf[0] = '\0';
+return;
+}
+len = strlen(buf);
+snprintf(buf + len, size - len, ".%03dZ", millisec);
 }
 }
 
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/dashenc: Added documentation for $ext$ identifier in filenames

2019-01-17 Thread Karthick J
---
 doc/muxers.texi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 4ed46a2220..d2d985f1ac 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -216,6 +216,8 @@ It creates a MPD manifest file and segment files for each 
stream.
 The segment filename might contain pre-defined identifiers used with 
SegmentTemplate
 as defined in section 5.3.9.4.4 of the standard. Available identifiers are 
"$RepresentationID$",
 "$Number$", "$Bandwidth$" and "$Time$".
+In addition to the standard identifiers, an ffmpeg-specific "$ext$" identifier 
is also supported.
+When specified ffmpeg will replace $ext$ in the file name with muxing format's 
extensions such as mp4, webm etc.,
 
 @example
 ffmpeg -re -i  -map 0 -map 0 -c:a libfdk_aac -c:v libx264
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/dashenc: Skip writing trailer for MP4 output when in streaming mode

2019-01-23 Thread Karthick J
In streaming mode mp4 trailer is not required for playout.
---
 libavformat/dashenc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 9c90cf17e5..6299e179c2 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -1210,7 +1210,7 @@ static int dash_init(AVFormatContext *s)
 
 if (os->segment_type == SEGMENT_TYPE_MP4) {
 if (c->streaming)
-av_dict_set(&opts, "movflags", 
"frag_every_frame+dash+delay_moov+skip_sidx", 0);
+av_dict_set(&opts, "movflags", 
"frag_every_frame+dash+delay_moov+skip_sidx+skip_trailer", 0);
 else
 av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 
0);
 } else {
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/tee : Pass standards compliance value to slave muxers as well

2019-01-30 Thread Karthick J
---
 libavformat/tee.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libavformat/tee.c b/libavformat/tee.c
index ef3b113a47..89a4ceb280 100644
--- a/libavformat/tee.c
+++ b/libavformat/tee.c
@@ -236,6 +236,7 @@ static int open_slave(AVFormatContext *avf, char *slave, 
TeeSlave *tee_slave)
 avf2->io_close = avf->io_close;
 avf2->interrupt_callback = avf->interrupt_callback;
 avf2->flags = avf->flags;
+avf2->strict_std_compliance = avf->strict_std_compliance;
 
 tee_slave->stream_map = av_calloc(avf->nb_streams, 
sizeof(*tee_slave->stream_map));
 if (!tee_slave->stream_map) {
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 2/2] avformat/dashenc: Added comments

2019-02-18 Thread Karthick J
Added comments regarding usage of certain movflags in streaming mode.
---
 libavformat/dashenc.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index a0b44a0ec3..f8782756b4 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -1216,6 +1216,17 @@ static int dash_init(AVFormatContext *s)
 
 if (os->segment_type == SEGMENT_TYPE_MP4) {
 if (c->streaming)
+// Explanation for why certain movflags are used for streaming:
+// frag_every_frame :- Every frame should be moof fragment, so
+// the data from current frame can be streamed without
+// waiting for the completion of the entire segment.
+// skip_sidx :- The SIDX atom for each moof will result in a
+// significant bitrate overhead. Hence disabling it here.
+// skip_trailer :- Writing mp4 trailer means that a list of all
+// fragment's information is stored, which results 
continuous
+// growth in memory usage as more fragments are muxed.
+// Disabling trailer results in deterministic memory usage.
+// Anyways trailer is unnecessary of fmp4 segment.
 av_dict_set(&opts, "movflags", 
"frag_every_frame+dash+delay_moov+skip_sidx+skip_trailer", 0);
 else
 av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 
0);
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 1/2] avformat/dashenc: Added option to repeatedly publish master playlist

2019-02-18 Thread Karthick J
The master playlist can be published at a specified interval with this option
---
 doc/muxers.texi   | 3 +++
 libavformat/dashenc.c | 9 -
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 36010cf2d1..372fab2f92 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -315,6 +315,9 @@ This option will also try to comply with the above open 
spec, till Apple's spec
 Applicable only when @var{streaming} and @var{hls_playlist} options are 
enabled.
 This is an experimental feature.
 
+@item -master_m3u8_publish_rate @var{master_m3u8_publish_rate}
+Publish master playlist repeatedly every after specified number of segment 
intervals.
+
 @end table
 
 @anchor{framecrc}
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 37a7547b12..a0b44a0ec3 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -141,6 +141,7 @@ typedef struct DASHContext {
 SegmentType segment_type_option;  /* segment type as specified in options 
*/
 int ignore_io_errors;
 int lhls;
+int master_publish_rate;
 } DASHContext;
 
 static struct codec_string {
@@ -965,13 +966,18 @@ static int write_manifest(AVFormatContext *s, int final)
 return ret;
 }
 
-if (c->hls_playlist && !c->master_playlist_created) {
+if (c->hls_playlist) {
 char filename_hls[1024];
 const char *audio_group = "A1";
 char audio_codec_str[128] = "\0";
 int is_default = 1;
 int max_audio_bitrate = 0;
 
+// Publish master playlist only the configured rate
+if (c->master_playlist_created && (!c->master_publish_rate ||
+ c->streams[0].segment_index % c->master_publish_rate))
+return 0;
+
 if (*c->dirname)
 snprintf(filename_hls, sizeof(filename_hls), "%smaster.m3u8", 
c->dirname);
 else
@@ -1798,6 +1804,7 @@ static const AVOption options[] = {
 { "webm", "make segment file in WebM format", 0, AV_OPT_TYPE_CONST, {.i64 
= SEGMENT_TYPE_WEBM }, 0, UINT_MAX,   E, "segment_type"},
 { "ignore_io_errors", "Ignore IO errors during open and write. Useful for 
long-duration runs with network output", OFFSET(ignore_io_errors), 
AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
 { "lhls", "Enable Low-latency HLS(Experimental). Adds #EXT-X-PREFETCH tag 
with current segment's URI", OFFSET(lhls), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 
1, E },
+{ "master_m3u8_publish_rate", "Publish master playlist every after this 
many segment intervals", OFFSET(master_publish_rate), AV_OPT_TYPE_INT, {.i64 = 
0}, 0, UINT_MAX, E},
 { NULL },
 };
 
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 2/2] avformat/dashenc: Added comments

2019-02-20 Thread Karthick J
Added comments regarding usage of certain movflags in streaming mode.
---
 libavformat/dashenc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index a0b44a0ec3..c5e882f4ae 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -1216,6 +1216,9 @@ static int dash_init(AVFormatContext *s)
 
 if (os->segment_type == SEGMENT_TYPE_MP4) {
 if (c->streaming)
+// frag_every_frame : Allows lower latency streaming
+// skip_sidx : Reduce bitrate overhead
+// skip_trailer : Avoids growing memory usage with time
 av_dict_set(&opts, "movflags", 
"frag_every_frame+dash+delay_moov+skip_sidx+skip_trailer", 0);
 else
 av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 
0);
-- 
2.17.1 (Apple Git-112)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 1/4] libformat/tcp: Moved all options to a separate structure

2017-11-03 Thread Karthick J
---
 libavformat/tcp.c | 46 +-
 1 file changed, 25 insertions(+), 21 deletions(-)

diff --git a/libavformat/tcp.c b/libavformat/tcp.c
index 07b4ed9..06368ff 100644
--- a/libavformat/tcp.c
+++ b/libavformat/tcp.c
@@ -32,18 +32,22 @@
 #include 
 #endif
 
-typedef struct TCPContext {
-const AVClass *class;
-int fd;
+typedef struct TCPOptions {
 int listen;
-int open_timeout;
 int rw_timeout;
 int listen_timeout;
 int recv_buffer_size;
 int send_buffer_size;
+} TCPOptions;
+
+typedef struct TCPContext {
+const AVClass *class;
+int fd;
+int open_timeout;
+TCPOptions options;
 } TCPContext;
 
-#define OFFSET(x) offsetof(TCPContext, x)
+#define OFFSET(x) (offsetof(TCPContext, options) + offsetof(TCPOptions, x))
 #define D AV_OPT_FLAG_DECODING_PARAM
 #define E AV_OPT_FLAG_ENCODING_PARAM
 static const AVOption options[] = {
@@ -87,26 +91,26 @@ static int tcp_open(URLContext *h, const char *uri, int 
flags)
 if (p) {
 if (av_find_info_tag(buf, sizeof(buf), "listen", p)) {
 char *endptr = NULL;
-s->listen = strtol(buf, &endptr, 10);
+s->options.listen = strtol(buf, &endptr, 10);
 /* assume if no digits were found it is a request to enable it */
 if (buf == endptr)
-s->listen = 1;
+s->options.listen = 1;
 }
 if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) {
-s->rw_timeout = strtol(buf, NULL, 10);
+s->options.rw_timeout = strtol(buf, NULL, 10);
 }
 if (av_find_info_tag(buf, sizeof(buf), "listen_timeout", p)) {
-s->listen_timeout = strtol(buf, NULL, 10);
+s->options.listen_timeout = strtol(buf, NULL, 10);
 }
 }
-if (s->rw_timeout >= 0) {
+if (s->options.rw_timeout >= 0) {
 s->open_timeout =
-h->rw_timeout   = s->rw_timeout;
+h->rw_timeout   = s->options.rw_timeout;
 }
 hints.ai_family = AF_UNSPEC;
 hints.ai_socktype = SOCK_STREAM;
 snprintf(portstr, sizeof(portstr), "%d", port);
-if (s->listen)
+if (s->options.listen)
 hints.ai_flags |= AI_PASSIVE;
 if (!hostname[0])
 ret = getaddrinfo(NULL, portstr, &hints, &ai);
@@ -142,21 +146,21 @@ static int tcp_open(URLContext *h, const char *uri, int 
flags)
 
 /* Set the socket's send or receive buffer sizes, if specified.
If unspecified or setting fails, system default is used. */
-if (s->recv_buffer_size > 0) {
-setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &s->recv_buffer_size, sizeof 
(s->recv_buffer_size));
+if (s->options.recv_buffer_size > 0) {
+setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &s->options.recv_buffer_size, 
sizeof (s->options.recv_buffer_size));
 }
-if (s->send_buffer_size > 0) {
-setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &s->send_buffer_size, sizeof 
(s->send_buffer_size));
+if (s->options.send_buffer_size > 0) {
+setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &s->options.send_buffer_size, 
sizeof (s->options.send_buffer_size));
 }
 
-if (s->listen == 2) {
+if (s->options.listen == 2) {
 // multi-client
 if ((ret = ff_listen(fd, cur_ai->ai_addr, cur_ai->ai_addrlen)) < 0)
 goto fail1;
-} else if (s->listen == 1) {
+} else if (s->options.listen == 1) {
 // single client
 if ((ret = ff_listen_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen,
-  s->listen_timeout, h)) < 0)
+  s->options.listen_timeout, h)) < 0)
 goto fail1;
 // Socket descriptor already closed here. Safe to overwrite to client 
one.
 fd = ret;
@@ -198,11 +202,11 @@ static int tcp_accept(URLContext *s, URLContext **c)
 TCPContext *sc = s->priv_data;
 TCPContext *cc;
 int ret;
-av_assert0(sc->listen);
+av_assert0(sc->options.listen);
 if ((ret = ffurl_alloc(c, s->filename, s->flags, &s->interrupt_callback)) 
< 0)
 return ret;
 cc = (*c)->priv_data;
-ret = ff_accept(sc->fd, sc->listen_timeout, s);
+ret = ff_accept(sc->fd, sc->options.listen_timeout, s);
 if (ret < 0)
 return ret;
 cc->fd = ret;
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 2/4] libavformat/tcp: Added an option to reuse sockets

2017-11-03 Thread Karthick J
---
 doc/protocols.texi  |   4 ++
 libavformat/tcp.c   | 150 
 libavformat/tcp.h   |  27 ++
 libavformat/utils.c |   2 +
 4 files changed, 183 insertions(+)
 create mode 100644 libavformat/tcp.h

diff --git a/doc/protocols.texi b/doc/protocols.texi
index a7968ff..62d317d 100644
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@ -1242,6 +1242,10 @@ Set receive buffer size, expressed bytes.
 
 @item send_buffer_size=@var{bytes}
 Set send buffer size, expressed bytes.
+
+@item reuse_sockets=@var{1|0}
+Reuse sockets instead of opening a new socket each time.
+Default value is 0.
 @end table
 
 The following example shows how to setup a listening TCP connection
diff --git a/libavformat/tcp.c b/libavformat/tcp.c
index 06368ff..8bca628 100644
--- a/libavformat/tcp.c
+++ b/libavformat/tcp.c
@@ -1,6 +1,7 @@
 /*
  * TCP protocol
  * Copyright (c) 2002 Fabrice Bellard
+ * Copyright (c) 2017 Akamai Technologies, Inc
  *
  * This file is part of FFmpeg.
  *
@@ -19,6 +20,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 #include "avformat.h"
+#include "tcp.h"
+#include "libavcodec/internal.h"
 #include "libavutil/avassert.h"
 #include "libavutil/parseutils.h"
 #include "libavutil/opt.h"
@@ -38,6 +41,7 @@ typedef struct TCPOptions {
 int listen_timeout;
 int recv_buffer_size;
 int send_buffer_size;
+int reuse_sockets;
 } TCPOptions;
 
 typedef struct TCPContext {
@@ -47,6 +51,16 @@ typedef struct TCPContext {
 TCPOptions options;
 } TCPContext;
 
+typedef struct TCPSocket {
+char *hostname;
+int  port;
+int in_use;
+int64_t last_close_time;
+int  fd;
+TCPOptions options;
+struct TCPSocket *next;
+} TCPSocket;
+
 #define OFFSET(x) (offsetof(TCPContext, options) + offsetof(TCPOptions, x))
 #define D AV_OPT_FLAG_DECODING_PARAM
 #define E AV_OPT_FLAG_ENCODING_PARAM
@@ -56,6 +70,7 @@ static const AVOption options[] = {
 { "listen_timeout",  "Connection awaiting timeout (in milliseconds)",  
OFFSET(listen_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, 
.flags = D|E },
 { "send_buffer_size", "Socket send buffer size (in bytes)",
OFFSET(send_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, 
.flags = D|E },
 { "recv_buffer_size", "Socket receive buffer size (in bytes)", 
OFFSET(recv_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, 
.flags = D|E },
+{ "reuse_sockets", "Reuse sockets instead of opening a new socket each 
time", OFFSET(reuse_sockets), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, 
.flags = D|E },
 { NULL }
 };
 
@@ -66,6 +81,116 @@ static const AVClass tcp_class = {
 .version= LIBAVUTIL_VERSION_INT,
 };
 
+static TCPSocket *first_socket = NULL;
+
+static TCPSocket* tcp_socket_create (TCPContext *s, char *name, int port)
+{
+TCPSocket *p = NULL;
+
+p = (TCPSocket *) calloc (1, sizeof(TCPSocket));
+if (p == NULL) {
+return NULL;
+}
+
+p->hostname = strdup(name);
+p->port = port;
+p->in_use = 1;
+p->fd = s->fd;
+p->options = s->options;
+p->next = NULL;
+
+return p;
+}
+
+static int tcp_socket_free (TCPSocket *socket)
+{
+if (socket) {
+closesocket(socket->fd);
+free(socket->hostname);
+free(socket);
+}
+return 0;
+}
+
+static void tcp_list_add(TCPContext *s, char *name, int port)
+{
+TCPSocket *socket = tcp_socket_create(s, name, port);
+
+if (!socket)
+return;
+avpriv_lock_avformat();
+socket->next = first_socket;
+first_socket = socket;
+avpriv_unlock_avformat();
+
+}
+
+static void tcp_list_remove_next(TCPSocket *socket)
+{
+TCPSocket *temp;
+if (socket) {
+temp = socket->next;
+socket->next = socket->next->next;
+} else {
+temp = first_socket;
+first_socket = first_socket->next;
+}
+tcp_socket_free(temp);
+
+}
+
+static int tcp_socket_find (TCPContext *s, char *name, int port)
+{
+int lfd = -1;
+TCPSocket *p = first_socket;
+TCPSocket *prev = NULL;
+int64_t current_time = av_gettime();
+avpriv_lock_avformat();
+while(p) {
+const int idle_timeout = 60 * 100;
+// Remove idle connections
+if (!p->in_use && (current_time - p->last_close_time) > idle_timeout) {
+tcp_list_remove_next(prev);
+} else {
+// Reuse the connection if a correct match if found
+if (!p->in_use && lfd == -1 &&
+!strcmp(p->hostname, name) && (p->port == port) &&
+!memcmp(&p->options, &s->options, sizeof(s->options))) {
+p->in_use = 1;
+lfd = p->fd;
+}
+prev = p;
+}
+p = p->next;
+
+}
+avpriv_unlock_avformat();
+return lfd;
+}
+
+static void tcp_socket_release (int search_fd)
+{
+TCPSocket *p = first_sock

[FFmpeg-devel] [PATCH 3/4] libavformat/http: Reuse TCP sockets when 'multiple_requests' is set

2017-11-03 Thread Karthick J
---
 libavformat/http.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libavformat/http.c b/libavformat/http.c
index bd9148f..b7bdcdc 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -227,6 +227,9 @@ static int http_open_cnx_internal(URLContext *h, 
AVDictionary **options)
 ff_url_join(buf, sizeof(buf), lower_proto, NULL, hostname, port, NULL);
 
 if (!s->hd) {
+if (s->multiple_requests && !strcmp(lower_proto, "tcp")) {
+av_dict_set_int(options, "reuse_sockets", 1, 0);
+}
 err = ffurl_open_whitelist(&s->hd, buf, AVIO_FLAG_READ_WRITE,
&h->interrupt_callback, options,
h->protocol_whitelist, 
h->protocol_blacklist, h);
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 4/4] libavformat/hlsenc: Persistent HTTP connections supported as an option

2017-11-03 Thread Karthick J
---
 doc/muxers.texi  | 3 +++
 libavformat/hlsenc.c | 5 -
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 91bbe67..1e1468c 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -794,6 +794,9 @@ files.
 @item http_user_agent
 Override User-Agent field in HTTP header. Applicable only for HTTP output.
 
+@item http_persistent
+Use persistent HTTP connections. Applicable only for HTTP output.
+
 @end table
 
 @anchor{ico}
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 5ea9d21..79db77a 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -175,6 +175,7 @@ typedef struct HLSContext {
 double initial_prog_date_time;
 char current_segment_final_filename_fmt[1024]; // when renaming segments
 char *user_agent;
+int http_persistent;
 } HLSContext;
 
 static int get_int_from_double(double val)
@@ -228,7 +229,8 @@ static void set_http_options(AVFormatContext *s, 
AVDictionary **options, HLSCont
 }
 if (c->user_agent)
 av_dict_set(options, "user_agent", c->user_agent, 0);
-
+if (c->http_persistent)
+av_dict_set_int(options, "multiple_requests", c->http_persistent, 0);
 }
 
 static int replace_int_data_in_filename(char *buf, int buf_size, const char 
*filename, char placeholder, int64_t number)
@@ -1829,6 +1831,7 @@ static const AVOption options[] = {
 {"epoch", "seconds since epoch", 0, AV_OPT_TYPE_CONST, {.i64 = 
HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH }, INT_MIN, INT_MAX, E, 
"start_sequence_source_type" },
 {"datetime", "current datetime as MMDDhhmmss", 0, AV_OPT_TYPE_CONST, 
{.i64 = HLS_START_SEQUENCE_AS_FORMATTED_DATETIME }, INT_MIN, INT_MAX, E, 
"start_sequence_source_type" },
 {"http_user_agent", "override User-Agent field in HTTP header", 
OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,E},
+{"http_persistent", "Use persistent HTTP connections", 
OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
 { NULL },
 };
 
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 1/3] libavformat/avio: Utility function to return URLContext

2017-11-07 Thread Karthick J
---
 libavformat/avio_internal.h | 8 
 libavformat/aviobuf.c   | 8 
 2 files changed, 16 insertions(+)

diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h
index c01835d..04c1ad5 100644
--- a/libavformat/avio_internal.h
+++ b/libavformat/avio_internal.h
@@ -133,6 +133,14 @@ int ffio_open_dyn_packet_buf(AVIOContext **s, int 
max_packet_size);
 int ffio_fdopen(AVIOContext **s, URLContext *h);
 
 /**
+ * Return the URLContext associated with the AVIOContext
+ *
+ * @param s IO context
+ * @return pointer to URLContext or NULL.
+ */
+URLContext *ffio_geturlcontext(AVIOContext *s);
+
+/**
  * Open a write-only fake memory stream. The written data is not stored
  * anywhere - this is only used for measuring the amount of data
  * written.
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index 3b4c843..1353c80 100644
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@ -980,6 +980,14 @@ fail:
 return AVERROR(ENOMEM);
 }
 
+URLContext* ffio_geturlcontext(AVIOContext *s) {
+AVIOInternal *internal = s->opaque;
+if (internal)
+return internal->h;
+else
+return NULL;
+}
+
 int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size)
 {
 uint8_t *buffer;
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 2/3] libavformat/http: Handled multiple_requests option during write

2017-11-07 Thread Karthick J
---
 libavformat/http.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index bd9148f..0854c01 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -1527,7 +1527,7 @@ static int http_write(URLContext *h, const uint8_t *buf, 
int size)
 
 /* silently ignore zero-size data since chunk encoding that would
  * signal EOF */
-if (size > 0) {
+if (size > 0 || s->multiple_requests) {
 /* upload data using chunked encoding */
 snprintf(temp, sizeof(temp), "%x\r\n", size);
 
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 3/3] libavformat/hlsenc: Persistent HTTP connections supported as an option

2017-11-07 Thread Karthick J
---
 doc/muxers.texi  |  3 +++
 libavformat/hlsenc.c | 50 +++---
 2 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 91bbe67..1e1468c 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -794,6 +794,9 @@ files.
 @item http_user_agent
 Override User-Agent field in HTTP header. Applicable only for HTTP output.
 
+@item http_persistent
+Use persistent HTTP connections. Applicable only for HTTP output.
+
 @end table
 
 @anchor{ico}
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 5ea9d21..4a581b4 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -44,6 +44,7 @@
 
 #include "avformat.h"
 #include "avio_internal.h"
+#include "http.h"
 #include "internal.h"
 #include "os_support.h"
 
@@ -175,6 +176,7 @@ typedef struct HLSContext {
 double initial_prog_date_time;
 char current_segment_final_filename_fmt[1024]; // when renaming segments
 char *user_agent;
+int http_persistent;
 } HLSContext;
 
 static int get_int_from_double(double val)
@@ -215,10 +217,40 @@ static int mkdir_p(const char *path) {
 return ret;
 }
 
+static int is_http_proto(char *filename) {
+const char *proto = avio_find_protocol_name(filename);
+return proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, 
"https")) : 0;
+}
+
+static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,
+  AVDictionary **options) {
+HLSContext *hls = s->priv_data;
+int http_base_proto = is_http_proto(filename);
+int err;
+if (*pb == NULL || !http_base_proto || !hls->http_persistent) {
+err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options);
+} else {
+URLContext *http_url_context = ffio_geturlcontext(*pb);
+err = ff_http_do_new_request(http_url_context, filename);
+}
+return err;
+}
+
+static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char 
*filename) {
+HLSContext *hls = s->priv_data;
+int http_base_proto = is_http_proto(filename);
+
+if (!http_base_proto || !hls->http_persistent || hls->key_info_file || 
hls->encrypt) {
+ff_format_io_close(s, pb);
+} else if (*pb) {
+URLContext *http_url_context = ffio_geturlcontext(*pb);
+http_url_context->prot->url_write(http_url_context, NULL, 0);
+}
+}
+
 static void set_http_options(AVFormatContext *s, AVDictionary **options, 
HLSContext *c)
 {
-const char *proto = avio_find_protocol_name(s->filename);
-int http_base_proto = proto ? (!av_strcasecmp(proto, "http") || 
!av_strcasecmp(proto, "https")) : 0;
+int http_base_proto = is_http_proto(s->filename);
 
 if (c->method) {
 av_dict_set(options, "method", c->method, 0);
@@ -228,6 +260,8 @@ static void set_http_options(AVFormatContext *s, 
AVDictionary **options, HLSCont
 }
 if (c->user_agent)
 av_dict_set(options, "user_agent", c->user_agent, 0);
+if (c->http_persistent)
+av_dict_set_int(options, "multiple_requests", 1, 0);
 
 }
 
@@ -1263,17 +1297,17 @@ static int hls_start(AVFormatContext *s)
 err = AVERROR(ENOMEM);
 goto fail;
 }
-err = s->io_open(s, &oc->pb, filename, AVIO_FLAG_WRITE, &options);
+err = hlsenc_io_open(s, &oc->pb, filename, &options);
 av_free(filename);
 av_dict_free(&options);
 if (err < 0)
 return err;
 } else
-if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, 
&options)) < 0)
+if ((err = hlsenc_io_open(s, &oc->pb, oc->filename, &options)) < 0)
 goto fail;
 if (c->vtt_basename) {
 set_http_options(s, &options, c);
-if ((err = s->io_open(s, &vtt_oc->pb, vtt_oc->filename, 
AVIO_FLAG_WRITE, &options)) < 0)
+if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->filename, &options)) 
< 0)
 goto fail;
 }
 av_dict_free(&options);
@@ -1661,9 +1695,10 @@ static int hls_write_packet(AVFormatContext *s, AVPacket 
*pkt)
 hls->size = new_start_pos - hls->start_pos;
 
 if (!byterange_mode) {
-ff_format_io_close(s, &oc->pb);
+hlsenc_io_close(s, &oc->pb,
+hls->fmp4_init_mode ? hls->base_output_dirname : 
oc->filename);
 if (hls->vtt_avf) {
-ff_format_io_close(s, &hls->vtt_avf->pb);
+hlsenc_io_close(s, &hls->vtt_avf->pb, hls->vtt_avf->filename);
 }
 }
 if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) {
@@ -1829,6 +1864,7 @@ static const AVOption options[] = {
 {"epoch", "seconds since epoch", 0, AV_OPT_TYPE_CONST, {.i64 = 
HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH }, INT_MIN, INT_MAX, E, 
"start_sequence_source_type" },
 {"datetime", "current datetime as MMDDhhmmss", 0, AV_OPT_TYPE_CONST, 
{.i64 = HLS_START_SEQUENCE_AS_FORMATTED_DATETIME }, INT_MIN, INT_MAX, E, 
"start_sequ

[FFmpeg-devel] [PATCH 1/1] avformat/dashenc: Added configuration to override HTTP User-Agent

2017-11-08 Thread Karthick J
---
 doc/muxers.texi   |  2 ++
 libavformat/dashenc.c | 22 +++---
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 91bbe67..412fede 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -247,6 +247,8 @@ DASH-templated name to used for the initialization segment. 
Default is "init-str
 DASH-templated name to used for the media segments. Default is 
"chunk-stream$RepresentationID$-$Number%05d$.m4s"
 @item -utc_timing_url @var{utc_url}
 URL of the page that will return the UTC timestamp in ISO format. Example: 
"https://time.akamai.com/?iso";
+@item -http_user_agent @var{user_agent}
+Override User-Agent field in HTTP header. Applicable only for HTTP output.
 @item -adaptation_sets @var{adaptation_sets}
 Assign streams to AdaptationSets. Syntax is "id=x,streams=a,b,c 
id=y,streams=d,e" with x and y being the IDs
 of the adaptation sets and a,b,c,d and e are the indices of the mapped streams.
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 7813f44..a68f7fb 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -100,6 +100,7 @@ typedef struct DASHContext {
 const char *init_seg_name;
 const char *media_seg_name;
 const char *utc_timing_url;
+const char *user_agent;
 } DASHContext;
 
 static struct codec_string {
@@ -210,6 +211,12 @@ static int flush_dynbuf(OutputStream *os, int 
*range_length)
 return avio_open_dyn_buf(&os->ctx->pb);
 }
 
+static void set_http_options(AVDictionary **options, DASHContext *c)
+{
+if (c->user_agent)
+av_dict_set(options, "user_agent", c->user_agent, 0);
+}
+
 static int flush_init_segment(AVFormatContext *s, OutputStream *os)
 {
 DASHContext *c = s->priv_data;
@@ -575,16 +582,19 @@ static int write_manifest(AVFormatContext *s, int final)
 int use_rename = proto && !strcmp(proto, "file");
 static unsigned int warned_non_file = 0;
 AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
+AVDictionary *opts = NULL;
 
 if (!use_rename && !warned_non_file++)
 av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this 
may lead to races and temporary partial files\n");
 
 snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : 
"%s", s->filename);
-ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
+set_http_options(&opts, c);
+ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, &opts);
 if (ret < 0) {
 av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", 
temp_filename);
 return ret;
 }
+av_dict_free(&opts);
 avio_printf(out, "\n");
 avio_printf(out, "http://www.w3.org/2001/XMLSchema-instance\"\n";
 "\txmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n"
@@ -768,9 +778,11 @@ static int dash_init(AVFormatContext *s)
 ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), 
c->init_seg_name, i, 0, os->bit_rate, 0);
 }
 snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
-ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, NULL);
+set_http_options(&opts, c);
+ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, &opts);
 if (ret < 0)
 return ret;
+av_dict_free(&opts);
 os->init_start_pos = 0;
 
 if (!strcmp(os->format_name, "mp4")) {
@@ -974,12 +986,15 @@ static int dash_flush(AVFormatContext *s, int final, int 
stream)
 }
 
 if (!c->single_file) {
+AVDictionary *opts = NULL;
 ff_dash_fill_tmpl_params(filename, sizeof(filename), 
c->media_seg_name, i, os->segment_index, os->bit_rate, os->start_pts);
 snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, 
filename);
 snprintf(temp_path, sizeof(temp_path), use_rename ? "%s.tmp" : 
"%s", full_path);
-ret = s->io_open(s, &os->out, temp_path, AVIO_FLAG_WRITE, NULL);
+set_http_options(&opts, c);
+ret = s->io_open(s, &os->out, temp_path, AVIO_FLAG_WRITE, &opts);
 if (ret < 0)
 break;
+av_dict_free(&opts);
 if (!strcmp(os->format_name, "mp4"))
 write_styp(os->ctx->pb);
 } else {
@@ -1188,6 +1203,7 @@ static const AVOption options[] = {
 { "init_seg_name", "DASH-templated name to used for the initialization 
segment", OFFSET(init_seg_name), AV_OPT_TYPE_STRING, {.str = 
"init-stream$RepresentationID$.m4s"}, 0, 0, E },
 { "media_seg_name", "DASH-templated name to used for the media segments", 
OFFSET(media_seg_name), AV_OPT_TYPE_STRING, {.str = 
"chunk-stream$RepresentationID$-$Number%05d$.m4s"}, 0, 0, E },
 { "utc_timing_url", "URL of the page that will return the UTC timestamp in 
ISO format", OFFSET(utc_timing_url), AV_OPT_TYPE_STRING, { 0 }, 0, 0, E },
+{ "http_user_agent", "override User-Agent field in HTTP header", 
OFFSET(user_agent), A

[FFmpeg-devel] [PATCH v2 1/3] libavformat/avio: Utility function to return URLContext

2017-11-20 Thread Karthick J
---
 libavformat/avio_internal.h |  8 
 libavformat/aviobuf.c   | 13 +
 2 files changed, 21 insertions(+)

diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h
index c01835d..04c1ad5 100644
--- a/libavformat/avio_internal.h
+++ b/libavformat/avio_internal.h
@@ -133,6 +133,14 @@ int ffio_open_dyn_packet_buf(AVIOContext **s, int 
max_packet_size);
 int ffio_fdopen(AVIOContext **s, URLContext *h);
 
 /**
+ * Return the URLContext associated with the AVIOContext
+ *
+ * @param s IO context
+ * @return pointer to URLContext or NULL.
+ */
+URLContext *ffio_geturlcontext(AVIOContext *s);
+
+/**
  * Open a write-only fake memory stream. The written data is not stored
  * anywhere - this is only used for measuring the amount of data
  * written.
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index 3b4c843..86eb657 100644
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@ -980,6 +980,19 @@ fail:
 return AVERROR(ENOMEM);
 }
 
+URLContext* ffio_geturlcontext(AVIOContext *s)
+{
+AVIOInternal *internal;
+if (!s)
+return NULL;
+
+internal = s->opaque;
+if (internal && s->read_packet == io_read_packet)
+return internal->h;
+else
+return NULL;
+}
+
 int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size)
 {
 uint8_t *buffer;
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 2/3] libavformat/http: Handled multiple_requests option during write

2017-11-20 Thread Karthick J
---
 libavformat/http.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/libavformat/http.c b/libavformat/http.c
index 056d5f6..45c0e72 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -171,6 +171,7 @@ static int http_connect(URLContext *h, const char *path, 
const char *local_path,
 const char *hoststr, const char *auth,
 const char *proxyauth, int *new_location);
 static int http_read_header(URLContext *h, int *new_location);
+static int http_shutdown(URLContext *h, int flags);
 
 void ff_http_init_auth_state(URLContext *dest, const URLContext *src)
 {
@@ -306,6 +307,10 @@ int ff_http_do_new_request(URLContext *h, const char *uri)
 AVDictionary *options = NULL;
 int ret;
 
+ret = http_shutdown(h, h->flags);
+if (ret < 0)
+return ret;
+
 s->chunkend  = 0;
 s->off   = 0;
 s->icy_data_read = 0;
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 3/3] libavformat/hlsenc: Persistent HTTP connections supported as an option

2017-11-20 Thread Karthick J
---
 doc/muxers.texi  |  3 +++
 libavformat/hlsenc.c | 48 +---
 2 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 0bb8ad2..c1d753b 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -850,6 +850,9 @@ ffmpeg -re -i in.ts -f hls -master_pl_name master.m3u8 \
 This example creates HLS master playlist with name master.m3u8 and keep
 publishing it repeatedly every after 30 segments i.e. every after 60s.
 
+@item http_persistent
+Use persistent HTTP connections. Applicable only for HTTP output.
+
 @end table
 
 @anchor{ico}
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 3c47ced..32c99a0 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -45,6 +45,7 @@
 
 #include "avformat.h"
 #include "avio_internal.h"
+#include "http.h"
 #include "internal.h"
 #include "os_support.h"
 
@@ -204,6 +205,7 @@ typedef struct HLSContext {
 char *var_stream_map; /* user specified variant stream map string */
 char *master_pl_name;
 unsigned int master_publish_rate;
+int http_persistent;
 } HLSContext;
 
 static int get_int_from_double(double val)
@@ -244,10 +246,38 @@ static int mkdir_p(const char *path) {
 return ret;
 }
 
+static int is_http_proto(char *filename) {
+const char *proto = avio_find_protocol_name(filename);
+return proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, 
"https")) : 0;
+}
+
+static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,
+  AVDictionary **options) {
+HLSContext *hls = s->priv_data;
+int http_base_proto = is_http_proto(filename);
+int err;
+if (*pb == NULL || !http_base_proto || !hls->http_persistent) {
+err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options);
+} else {
+URLContext *http_url_context = ffio_geturlcontext(*pb);
+av_assert0(http_url_context);
+err = ff_http_do_new_request(http_url_context, filename);
+}
+return err;
+}
+
+static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char 
*filename) {
+HLSContext *hls = s->priv_data;
+int http_base_proto = is_http_proto(filename);
+
+if (!http_base_proto || !hls->http_persistent || hls->key_info_file || 
hls->encrypt) {
+ff_format_io_close(s, pb);
+}
+}
+
 static void set_http_options(AVFormatContext *s, AVDictionary **options, 
HLSContext *c)
 {
-const char *proto = avio_find_protocol_name(s->filename);
-int http_base_proto = proto ? (!av_strcasecmp(proto, "http") || 
!av_strcasecmp(proto, "https")) : 0;
+int http_base_proto = is_http_proto(s->filename);
 
 if (c->method) {
 av_dict_set(options, "method", c->method, 0);
@@ -257,6 +287,8 @@ static void set_http_options(AVFormatContext *s, 
AVDictionary **options, HLSCont
 }
 if (c->user_agent)
 av_dict_set(options, "user_agent", c->user_agent, 0);
+if (c->http_persistent)
+av_dict_set_int(options, "multiple_requests", 1, 0);
 
 }
 
@@ -1430,17 +1462,17 @@ static int hls_start(AVFormatContext *s, VariantStream 
*vs)
 err = AVERROR(ENOMEM);
 goto fail;
 }
-err = s->io_open(s, &oc->pb, filename, AVIO_FLAG_WRITE, &options);
+err = hlsenc_io_open(s, &oc->pb, filename, &options);
 av_free(filename);
 av_dict_free(&options);
 if (err < 0)
 return err;
 } else
-if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, 
&options)) < 0)
+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 = s->io_open(s, &vtt_oc->pb, vtt_oc->filename, 
AVIO_FLAG_WRITE, &options)) < 0)
+if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->filename, &options)) 
< 0)
 goto fail;
 }
 av_dict_free(&options);
@@ -2148,11 +2180,12 @@ static int hls_write_packet(AVFormatContext *s, 
AVPacket *pkt)
 avio_open_dyn_buf(&oc->pb);
 vs->packets_written = 0;
 ff_format_io_close(s, &vs->out);
+hlsenc_io_close(s, &vs->out, vs->base_output_dirname);
 } else {
-ff_format_io_close(s, &oc->pb);
+hlsenc_io_close(s, &oc->pb, oc->filename);
 }
 if (vs->vtt_avf) {
-ff_format_io_close(s, &vs->vtt_avf->pb);
+hlsenc_io_close(s, &vs->vtt_avf->pb, vs->vtt_avf->filename);
 }
 }
 if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) {
@@ -2337,6 +2370,7 @@ static const AVOption options[] = {
 {"var_stream_map", "Variant stream map string", OFFSET(var_stream_map), 
AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,E},
 {"master_pl_name", "Create HLS master playlist with this name", 
OFFSET(master_pl_name), AV_OPT_TYPE_STRING, {.str = 

[FFmpeg-devel] Common Media Application Format

2017-11-21 Thread Karthick J
[PATCH 1/2] avformat/hlsenc: Modularized playlist creation to allow
[PATCH 2/2] avformat/dashenc: Option to generate hls playlist as well

One of the biggest applications of MPEG Common Media Application Format, is to 
have common media file/segments, that could be used by both HLS and DASH 
players.
To achieve this possibility in ffmpeg we need to have a muxer plugin that 
generates both DASH manifest and HLS playlist files. 
Two simple options that we have are
1. Modify the dashenc plugin to generate the HLS playlist files
2. Modify the hlsenc plugin to generate DASH manifest files

Both options are equally good. I have chosen option 1, just for the sake 
easiness to implement the same. 

Regards,
Karthick
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 1/2] avformat/hlsenc: Modularized playlist creation to allow reuse

2017-11-21 Thread Karthick J
---
 libavformat/hlsenc.c | 130 +++---
 libavformat/hlsenc.h | 158 +++
 2 files changed, 177 insertions(+), 111 deletions(-)
 create mode 100644 libavformat/hlsenc.h

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 3c47ced..4e017eb 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -45,6 +45,7 @@
 
 #include "avformat.h"
 #include "avio_internal.h"
+#include "hlsenc.h"
 #include "internal.h"
 #include "os_support.h"
 
@@ -73,35 +74,11 @@ typedef struct HLSSegment {
 struct HLSSegment *next;
 } HLSSegment;
 
-typedef enum HLSFlags {
-// Generate a single media file and use byte ranges in the playlist.
-HLS_SINGLE_FILE = (1 << 0),
-HLS_DELETE_SEGMENTS = (1 << 1),
-HLS_ROUND_DURATIONS = (1 << 2),
-HLS_DISCONT_START = (1 << 3),
-HLS_OMIT_ENDLIST = (1 << 4),
-HLS_SPLIT_BY_TIME = (1 << 5),
-HLS_APPEND_LIST = (1 << 6),
-HLS_PROGRAM_DATE_TIME = (1 << 7),
-HLS_SECOND_LEVEL_SEGMENT_INDEX = (1 << 8), // include segment index in 
segment filenames when use_localtime  e.g.: %%03d
-HLS_SECOND_LEVEL_SEGMENT_DURATION = (1 << 9), // include segment duration 
(microsec) in segment filenames when use_localtime  e.g.: %%09t
-HLS_SECOND_LEVEL_SEGMENT_SIZE = (1 << 10), // include segment size (bytes) 
in segment filenames when use_localtime  e.g.: %%014s
-HLS_TEMP_FILE = (1 << 11),
-HLS_PERIODIC_REKEY = (1 << 12),
-} HLSFlags;
-
 typedef enum {
 SEGMENT_TYPE_MPEGTS,
 SEGMENT_TYPE_FMP4,
 } SegmentType;
 
-typedef enum {
-PLAYLIST_TYPE_NONE,
-PLAYLIST_TYPE_EVENT,
-PLAYLIST_TYPE_VOD,
-PLAYLIST_TYPE_NB,
-} PlaylistType;
-
 typedef struct VariantStream {
 unsigned number;
 int64_t sequence;
@@ -1022,19 +999,6 @@ static void hls_free_segments(HLSSegment *p)
 }
 }
 
-static void write_m3u8_head_block(HLSContext *hls, AVIOContext *out, int 
version,
-  int target_duration, int64_t sequence)
-{
-avio_printf(out, "#EXTM3U\n");
-avio_printf(out, "#EXT-X-VERSION:%d\n", version);
-if (hls->allowcache == 0 || hls->allowcache == 1) {
-avio_printf(out, "#EXT-X-ALLOW-CACHE:%s\n", hls->allowcache == 0 ? 
"NO" : "YES");
-}
-avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration);
-avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
-av_log(hls, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
-}
-
 static void hls_rename_temp_file(AVFormatContext *s, AVFormatContext *oc)
 {
 size_t len = strlen(oc->filename);
@@ -1101,8 +1065,7 @@ static int create_master_playlist(AVFormatContext *s,
 goto fail;
 }
 
-avio_printf(master_pb, "#EXTM3U\n");
-avio_printf(master_pb, "#EXT-X-VERSION:%d\n", hls->version);
+hls_write_playlist_version(master_pb, hls->version);
 
 /* For variant streams with video add #EXT-X-STREAM-INF tag with 
attributes*/
 for (i = 0; i < hls->nb_varstreams; i++) {
@@ -1143,18 +1106,7 @@ static int create_master_playlist(AVFormatContext *s,
 bandwidth += aud_st->codecpar->bit_rate;
 bandwidth += bandwidth / 10;
 
-if (!bandwidth) {
-av_log(NULL, AV_LOG_WARNING,
-"Bandwidth info not available, set audio and video 
bitrates\n");
-av_freep(&m3U8_rel_name);
-continue;
-}
-
-avio_printf(master_pb, "#EXT-X-STREAM-INF:BANDWIDTH=%d", bandwidth);
-if (vid_st && vid_st->codecpar->width > 0 && vid_st->codecpar->height 
> 0)
-avio_printf(master_pb, ",RESOLUTION=%dx%d", 
vid_st->codecpar->width,
-vid_st->codecpar->height);
-avio_printf(master_pb, "\n%s\n\n", m3U8_rel_name);
+hls_write_stream_info(vid_st, master_pb, bandwidth, m3U8_rel_name);
 
 av_freep(&m3U8_rel_name);
 }
@@ -1209,12 +1161,8 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 }
 
 vs->discontinuity_set = 0;
-write_m3u8_head_block(hls, out, hls->version, target_duration, sequence);
-if (hls->pl_type == PLAYLIST_TYPE_EVENT) {
-avio_printf(out, "#EXT-X-PLAYLIST-TYPE:EVENT\n");
-} else if (hls->pl_type == PLAYLIST_TYPE_VOD) {
-avio_printf(out, "#EXT-X-PLAYLIST-TYPE:VOD\n");
-}
+hls_write_playlist_header(out, hls->version, hls->allowcache,
+  target_duration, sequence, hls->pl_type);
 
 if((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && 
vs->discontinuity_set==0 ){
 avio_printf(out, "#EXT-X-DISCONTINUITY\n");
@@ -1231,74 +1179,34 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 iv_string = en->iv_string;
 }
 
-if (en->discont) {
-avio_printf(out, "#EXT-X-DISCONTINUITY\n");
-}
-
 if ((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == vs->segments)) {
-avio_printf

[FFmpeg-devel] [PATCH 2/2] avformat/dashenc: Option to generate hls playlist as well

2017-11-21 Thread Karthick J
This is to take full advantage of Common Media Application Format.
Now server can generate one content and serve both HLS and DASH players.
---
 doc/muxers.texi   |   3 ++
 libavformat/dashenc.c | 101 --
 2 files changed, 100 insertions(+), 4 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 0bb8ad2..1cf2481 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -249,6 +249,9 @@ DASH-templated name to used for the media segments. Default 
is "chunk-stream$Rep
 URL of the page that will return the UTC timestamp in ISO format. Example: 
"https://time.akamai.com/?iso";
 @item -http_user_agent @var{user_agent}
 Override User-Agent field in HTTP header. Applicable only for HTTP output.
+@item -hls_playlist @var{hls_playlist}
+Generate HLS playlist files as well. The master playlist is generated with the 
filename master.m3u8.
+One media playlist file is generated for each stream with filenames 
media_0.m3u8, media_1.m3u8, etc.
 @item -adaptation_sets @var{adaptation_sets}
 Assign streams to AdaptationSets. Syntax is "id=x,streams=a,b,c 
id=y,streams=d,e" with x and y being the IDs
 of the adaptation sets and a,b,c,d and e are the indices of the mapped streams.
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 201668a..1fa9d82 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -36,6 +36,7 @@
 #include "avc.h"
 #include "avformat.h"
 #include "avio_internal.h"
+#include "hlsenc.h"
 #include "internal.h"
 #include "isom.h"
 #include "os_support.h"
@@ -101,6 +102,8 @@ typedef struct DASHContext {
 const char *media_seg_name;
 const char *utc_timing_url;
 const char *user_agent;
+int hls_playlist;
+int master_playlist_created;
 } DASHContext;
 
 static struct codec_string {
@@ -217,6 +220,13 @@ static void set_http_options(AVDictionary **options, 
DASHContext *c)
 av_dict_set(options, "user_agent", c->user_agent, 0);
 }
 
+static void get_hls_playlist_name(char *playlist_name, const char *base_url, 
int id) {
+if (base_url)
+sprintf(playlist_name, "%smedia_%d.m3u8", base_url, id);
+else
+sprintf(playlist_name, "media_%d.m3u8", id);
+}
+
 static int flush_init_segment(AVFormatContext *s, OutputStream *os)
 {
 DASHContext *c = s->priv_data;
@@ -262,7 +272,8 @@ static void dash_free(AVFormatContext *s)
 av_freep(&c->streams);
 }
 
-static void output_segment_list(OutputStream *os, AVIOContext *out, 
DASHContext *c)
+static void output_segment_list(OutputStream *os, AVIOContext *out, 
DASHContext *c,
+int representation_id, int final)
 {
 int i, start_index = 0, start_number = 1;
 if (c->window_size) {
@@ -322,6 +333,53 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, DASHContext
 }
 avio_printf(out, "\t\t\t\t\n");
 }
+if (c->hls_playlist && start_index < os->nb_segments)
+{
+int timescale = os->ctx->streams[0]->time_base.den;
+char temp_filename_hls[1024];
+char filename_hls[1024];
+AVIOContext *out_hls = NULL;
+AVDictionary *http_opts = NULL;
+int target_duration = 0;
+const char *proto = avio_find_protocol_name(c->dirname);
+int use_rename = proto && !strcmp(proto, "file");
+
+get_hls_playlist_name(filename_hls, c->dirname, representation_id);
+
+snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? 
"%s.tmp" : "%s", filename_hls);
+
+set_http_options(&http_opts, c);
+avio_open2(&out_hls, temp_filename_hls, AVIO_FLAG_WRITE, NULL, 
&http_opts);
+av_dict_free(&http_opts);
+for (i = start_index; i < os->nb_segments; i++) {
+Segment *seg = os->segments[i];
+if (target_duration < seg->duration)
+target_duration = seg->duration;
+}
+target_duration = lrint((double) target_duration / timescale);
+
+hls_write_playlist_header (out_hls, 6, -1,
+target_duration, start_number, PLAYLIST_TYPE_NONE);
+
+hls_write_init_file(out_hls, os->initfile, c->single_file,
+os->init_range_length, os->init_start_pos);
+
+for (i = start_index; i < os->nb_segments; i++) {
+Segment *seg = os->segments[i];
+hls_write_file_entry(out_hls, 0, c->single_file, 0,
+ (double) seg->duration / timescale,
+ seg->range_length, seg->start_pos, NULL,
+ c->single_file ? os->initfile : seg->file, 
NULL);
+}
+
+if (final)
+hls_write_end_list(out_hls);
+
+avio_close(out_hls);
+if (use_rename)
+avpriv_io_move(temp_filename_hls, filename_hls);
+}
+
 }
 
 static char *xmlescape(const char *str) {
@@ -391,7 +449,8 @@ static void format_date_now(char *buf, int size)
 }
 }
 
-static int write_adaptati

[FFmpeg-devel] [PATCH 1/2] avformat/hlsenc: Minor fix in setting http options for master playlist

2017-11-22 Thread Karthick J
---
 libavformat/hlsenc.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 3c47ced..525605b 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -1089,8 +1089,7 @@ static int create_master_playlist(AVFormatContext *s,
 return 0;
 }
 
-if (hls->user_agent)
-  av_dict_set(&options, "user-agent", hls->user_agent, 0);
+set_http_options(s, &options, hls);
 
 ret = s->io_open(s, &master_pb, hls->master_m3u8_url, AVIO_FLAG_WRITE,\
  &options);
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 2/2] avformat/hlsenc: Refactor an inconsistent variable name

2017-11-22 Thread Karthick J
---
 libavformat/hlsenc.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 525605b..611cc99 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -1074,7 +1074,7 @@ static int create_master_playlist(AVFormatContext *s,
 AVDictionary *options = NULL;
 unsigned int i, j;
 int m3u8_name_size, ret, bandwidth;
-char *m3U8_rel_name;
+char *m3u8_rel_name;
 
 input_vs->m3u8_created = 1;
 if (!hls->master_m3u8_created) {
@@ -1108,14 +1108,14 @@ static int create_master_playlist(AVFormatContext *s,
 vs = &(hls->var_streams[i]);
 
 m3u8_name_size = strlen(vs->m3u8_name) + 1;
-m3U8_rel_name = av_malloc(m3u8_name_size);
-if (!m3U8_rel_name) {
+m3u8_rel_name = av_malloc(m3u8_name_size);
+if (!m3u8_rel_name) {
 ret = AVERROR(ENOMEM);
 goto fail;
 }
-av_strlcpy(m3U8_rel_name, vs->m3u8_name, m3u8_name_size);
+av_strlcpy(m3u8_rel_name, vs->m3u8_name, m3u8_name_size);
 ret = get_relative_url(hls->master_m3u8_url, vs->m3u8_name,
-   m3U8_rel_name, m3u8_name_size);
+   m3u8_rel_name, m3u8_name_size);
 if (ret < 0) {
 av_log(NULL, AV_LOG_ERROR, "Unable to find relative URL\n");
 goto fail;
@@ -1145,7 +1145,7 @@ static int create_master_playlist(AVFormatContext *s,
 if (!bandwidth) {
 av_log(NULL, AV_LOG_WARNING,
 "Bandwidth info not available, set audio and video 
bitrates\n");
-av_freep(&m3U8_rel_name);
+av_freep(&m3u8_rel_name);
 continue;
 }
 
@@ -1153,14 +1153,14 @@ static int create_master_playlist(AVFormatContext *s,
 if (vid_st && vid_st->codecpar->width > 0 && vid_st->codecpar->height 
> 0)
 avio_printf(master_pb, ",RESOLUTION=%dx%d", 
vid_st->codecpar->width,
 vid_st->codecpar->height);
-avio_printf(master_pb, "\n%s\n\n", m3U8_rel_name);
+avio_printf(master_pb, "\n%s\n\n", m3u8_rel_name);
 
-av_freep(&m3U8_rel_name);
+av_freep(&m3u8_rel_name);
 }
 fail:
 if(ret >=0)
 hls->master_m3u8_created = 1;
-av_freep(&m3U8_rel_name);
+av_freep(&m3u8_rel_name);
 ff_format_io_close(s, &master_pb);
 return ret;
 }
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 1/1] avformat/dashenc: Associate mpd extension with dash muxer

2017-11-22 Thread Karthick J
---
 libavformat/dashenc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 201668a..0fee3cd 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -1219,6 +1219,7 @@ static const AVClass dash_class = {
 AVOutputFormat ff_dash_muxer = {
 .name   = "dash",
 .long_name  = NULL_IF_CONFIG_SMALL("DASH Muxer"),
+.extensions = "mpd",
 .priv_data_size = sizeof(DASHContext),
 .audio_codec= AV_CODEC_ID_AAC,
 .video_codec= AV_CODEC_ID_H264,
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 1/2] avformat/hlsenc: Modularized playlist creation to allow reuse

2017-11-22 Thread Karthick J
---
 libavformat/hlsenc.c | 237 +++
 libavformat/hlsenc.h |  67 +++
 2 files changed, 193 insertions(+), 111 deletions(-)
 create mode 100644 libavformat/hlsenc.h

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 3c47ced..d5b1b98 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -45,6 +45,7 @@
 
 #include "avformat.h"
 #include "avio_internal.h"
+#include "hlsenc.h"
 #include "internal.h"
 #include "os_support.h"
 
@@ -73,35 +74,11 @@ typedef struct HLSSegment {
 struct HLSSegment *next;
 } HLSSegment;
 
-typedef enum HLSFlags {
-// Generate a single media file and use byte ranges in the playlist.
-HLS_SINGLE_FILE = (1 << 0),
-HLS_DELETE_SEGMENTS = (1 << 1),
-HLS_ROUND_DURATIONS = (1 << 2),
-HLS_DISCONT_START = (1 << 3),
-HLS_OMIT_ENDLIST = (1 << 4),
-HLS_SPLIT_BY_TIME = (1 << 5),
-HLS_APPEND_LIST = (1 << 6),
-HLS_PROGRAM_DATE_TIME = (1 << 7),
-HLS_SECOND_LEVEL_SEGMENT_INDEX = (1 << 8), // include segment index in 
segment filenames when use_localtime  e.g.: %%03d
-HLS_SECOND_LEVEL_SEGMENT_DURATION = (1 << 9), // include segment duration 
(microsec) in segment filenames when use_localtime  e.g.: %%09t
-HLS_SECOND_LEVEL_SEGMENT_SIZE = (1 << 10), // include segment size (bytes) 
in segment filenames when use_localtime  e.g.: %%014s
-HLS_TEMP_FILE = (1 << 11),
-HLS_PERIODIC_REKEY = (1 << 12),
-} HLSFlags;
-
 typedef enum {
 SEGMENT_TYPE_MPEGTS,
 SEGMENT_TYPE_FMP4,
 } SegmentType;
 
-typedef enum {
-PLAYLIST_TYPE_NONE,
-PLAYLIST_TYPE_EVENT,
-PLAYLIST_TYPE_VOD,
-PLAYLIST_TYPE_NB,
-} PlaylistType;
-
 typedef struct VariantStream {
 unsigned number;
 int64_t sequence;
@@ -206,6 +183,113 @@ typedef struct HLSContext {
 unsigned int master_publish_rate;
 } HLSContext;
 
+void ff_hls_write_playlist_version(AVIOContext *out, int version) {
+if (!out)
+return;
+avio_printf(out, "#EXTM3U\n");
+avio_printf(out, "#EXT-X-VERSION:%d\n", version);
+}
+
+void ff_hls_write_stream_info(AVStream *st, AVIOContext *out,
+  int bandwidth, char *filename) {
+if (!out || !filename)
+return;
+
+if (!bandwidth) {
+av_log(NULL, AV_LOG_WARNING,
+"Bandwidth info not available, set audio and video 
bitrates\n");
+return;
+}
+
+avio_printf(out, "#EXT-X-STREAM-INF:BANDWIDTH=%d", bandwidth);
+if (st && st->codecpar->width > 0 && st->codecpar->height > 0)
+avio_printf(out, ",RESOLUTION=%dx%d", st->codecpar->width,
+st->codecpar->height);
+avio_printf(out, "\n%s\n\n", filename);
+}
+
+void ff_hls_write_playlist_header(AVIOContext *out, int version, int 
allowcache,
+  int target_duration, int64_t sequence,
+  uint32_t playlist_type) {
+if (!out)
+return;
+ff_hls_write_playlist_version(out, version);
+if (allowcache == 0 || allowcache == 1) {
+avio_printf(out, "#EXT-X-ALLOW-CACHE:%s\n", allowcache == 0 ? "NO" : 
"YES");
+}
+avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration);
+avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
+av_log(NULL, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
+
+if (playlist_type == PLAYLIST_TYPE_EVENT) {
+avio_printf(out, "#EXT-X-PLAYLIST-TYPE:EVENT\n");
+} else if (playlist_type == PLAYLIST_TYPE_VOD) {
+avio_printf(out, "#EXT-X-PLAYLIST-TYPE:VOD\n");
+}
+}
+
+void ff_hls_write_init_file(AVIOContext *out, char *filename,
+int byterange_mode, int64_t size, int64_t pos) {
+avio_printf(out, "#EXT-X-MAP:URI=\"%s\"", filename);
+if (byterange_mode) {
+avio_printf(out, ",BYTERANGE=\"%"PRId64"@%"PRId64"\"", size, pos);
+}
+avio_printf(out, "\n");
+}
+
+void ff_hls_write_file_entry(AVIOContext *out, int insert_discont,
+int byterange_mode, uint32_t flags, double 
duration,
+int64_t size, int64_t pos, //Used only if 
HLS_SINGLE_FILE flag is set
+char *baseurl, //Ignored if NULL
+char *filename, double *prog_date_time) {
+if (!out || !filename)
+return;
+
+if (insert_discont) {
+avio_printf(out, "#EXT-X-DISCONTINUITY\n");
+}
+if (flags & HLS_ROUND_DURATIONS)
+avio_printf(out, "#EXTINF:%ld,\n",  lrint(duration));
+else
+avio_printf(out, "#EXTINF:%f,\n", duration);
+if (byterange_mode)
+avio_printf(out, "#EXT-X-BYTERANGE:%"PRId64"@%"PRId64"\n", size, pos);
+
+if ((flags & HLS_PROGRAM_DATE_TIME) && prog_date_time) {
+time_t tt, wrongsecs;
+int milli;
+struct tm *tm, tmpbuf;
+char buf0[128], buf1[128];
+tt = (int64_t)prog_date_time;
+milli = av_clip(lrint(1000*(*prog

[FFmpeg-devel] [PATCH v2 2/2] avformat/dashenc: Option to generate hls playlist as well

2017-11-22 Thread Karthick J
This is to take full advantage of Common Media Application Format.
Now server can generate one content and serve both HLS and DASH players.
---
 doc/muxers.texi   |   3 ++
 libavformat/dashenc.c | 102 --
 2 files changed, 101 insertions(+), 4 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 0bb8ad2..1cf2481 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -249,6 +249,9 @@ DASH-templated name to used for the media segments. Default 
is "chunk-stream$Rep
 URL of the page that will return the UTC timestamp in ISO format. Example: 
"https://time.akamai.com/?iso";
 @item -http_user_agent @var{user_agent}
 Override User-Agent field in HTTP header. Applicable only for HTTP output.
+@item -hls_playlist @var{hls_playlist}
+Generate HLS playlist files as well. The master playlist is generated with the 
filename master.m3u8.
+One media playlist file is generated for each stream with filenames 
media_0.m3u8, media_1.m3u8, etc.
 @item -adaptation_sets @var{adaptation_sets}
 Assign streams to AdaptationSets. Syntax is "id=x,streams=a,b,c 
id=y,streams=d,e" with x and y being the IDs
 of the adaptation sets and a,b,c,d and e are the indices of the mapped streams.
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 201668a..4c3962a 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -36,6 +36,7 @@
 #include "avc.h"
 #include "avformat.h"
 #include "avio_internal.h"
+#include "hlsenc.h"
 #include "internal.h"
 #include "isom.h"
 #include "os_support.h"
@@ -101,6 +102,8 @@ typedef struct DASHContext {
 const char *media_seg_name;
 const char *utc_timing_url;
 const char *user_agent;
+int hls_playlist;
+int master_playlist_created;
 } DASHContext;
 
 static struct codec_string {
@@ -217,6 +220,13 @@ static void set_http_options(AVDictionary **options, 
DASHContext *c)
 av_dict_set(options, "user_agent", c->user_agent, 0);
 }
 
+static void get_hls_playlist_name(char *playlist_name, const char *base_url, 
int id) {
+if (base_url)
+sprintf(playlist_name, "%smedia_%d.m3u8", base_url, id);
+else
+sprintf(playlist_name, "media_%d.m3u8", id);
+}
+
 static int flush_init_segment(AVFormatContext *s, OutputStream *os)
 {
 DASHContext *c = s->priv_data;
@@ -262,7 +272,8 @@ static void dash_free(AVFormatContext *s)
 av_freep(&c->streams);
 }
 
-static void output_segment_list(OutputStream *os, AVIOContext *out, 
DASHContext *c)
+static void output_segment_list(OutputStream *os, AVIOContext *out, 
DASHContext *c,
+int representation_id, int final)
 {
 int i, start_index = 0, start_number = 1;
 if (c->window_size) {
@@ -322,6 +333,54 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, DASHContext
 }
 avio_printf(out, "\t\t\t\t\n");
 }
+if (c->hls_playlist && start_index < os->nb_segments)
+{
+int timescale = os->ctx->streams[0]->time_base.den;
+char temp_filename_hls[1024];
+char filename_hls[1024];
+AVIOContext *out_hls = NULL;
+AVDictionary *http_opts = NULL;
+int target_duration = 0;
+const char *proto = avio_find_protocol_name(c->dirname);
+int use_rename = proto && !strcmp(proto, "file");
+
+get_hls_playlist_name(filename_hls, c->dirname, representation_id);
+
+snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? 
"%s.tmp" : "%s", filename_hls);
+
+set_http_options(&http_opts, c);
+avio_open2(&out_hls, temp_filename_hls, AVIO_FLAG_WRITE, NULL, 
&http_opts);
+av_dict_free(&http_opts);
+for (i = start_index; i < os->nb_segments; i++) {
+Segment *seg = os->segments[i];
+if (target_duration < seg->duration)
+target_duration = seg->duration;
+}
+target_duration = lrint((double) target_duration / timescale);
+
+ff_hls_write_playlist_header(out_hls, 6, -1, target_duration,
+ start_number, PLAYLIST_TYPE_NONE);
+
+ff_hls_write_init_file(out_hls, os->initfile, c->single_file,
+   os->init_range_length, os->init_start_pos);
+
+for (i = start_index; i < os->nb_segments; i++) {
+Segment *seg = os->segments[i];
+ff_hls_write_file_entry(out_hls, 0, c->single_file, 0,
+(double) seg->duration / timescale,
+seg->range_length, seg->start_pos, NULL,
+c->single_file ? os->initfile : seg->file,
+NULL);
+}
+
+if (final)
+ff_hls_write_end_list(out_hls);
+
+avio_close(out_hls);
+if (use_rename)
+avpriv_io_move(temp_filename_hls, filename_hls);
+}
+
 }
 
 static char *xmlescape(const char *str) {
@@ -391,7 +450,8 @@ static 

[FFmpeg-devel] [PATCH v3 2/2] avformat/dashenc: Option to generate hls playlist as well

2017-11-22 Thread Karthick J
This is to take full advantage of Common Media Application Format.
Now server can generate one content and serve both HLS and DASH players.
---
 doc/muxers.texi   |   3 ++
 libavformat/dashenc.c | 103 --
 2 files changed, 102 insertions(+), 4 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 0bb8ad2..1cf2481 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -249,6 +249,9 @@ DASH-templated name to used for the media segments. Default 
is "chunk-stream$Rep
 URL of the page that will return the UTC timestamp in ISO format. Example: 
"https://time.akamai.com/?iso";
 @item -http_user_agent @var{user_agent}
 Override User-Agent field in HTTP header. Applicable only for HTTP output.
+@item -hls_playlist @var{hls_playlist}
+Generate HLS playlist files as well. The master playlist is generated with the 
filename master.m3u8.
+One media playlist file is generated for each stream with filenames 
media_0.m3u8, media_1.m3u8, etc.
 @item -adaptation_sets @var{adaptation_sets}
 Assign streams to AdaptationSets. Syntax is "id=x,streams=a,b,c 
id=y,streams=d,e" with x and y being the IDs
 of the adaptation sets and a,b,c,d and e are the indices of the mapped streams.
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 201668a..3fd1ef3 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -36,6 +36,7 @@
 #include "avc.h"
 #include "avformat.h"
 #include "avio_internal.h"
+#include "hlsenc.h"
 #include "internal.h"
 #include "isom.h"
 #include "os_support.h"
@@ -101,6 +102,8 @@ typedef struct DASHContext {
 const char *media_seg_name;
 const char *utc_timing_url;
 const char *user_agent;
+int hls_playlist;
+int master_playlist_created;
 } DASHContext;
 
 static struct codec_string {
@@ -217,6 +220,14 @@ static void set_http_options(AVDictionary **options, 
DASHContext *c)
 av_dict_set(options, "user_agent", c->user_agent, 0);
 }
 
+static void get_hls_playlist_name(char *playlist_name, int string_size,
+  const char *base_url, int id) {
+if (base_url)
+snprintf(playlist_name, string_size, "%smedia_%d.m3u8", base_url, id);
+else
+snprintf(playlist_name, string_size, "media_%d.m3u8", id);
+}
+
 static int flush_init_segment(AVFormatContext *s, OutputStream *os)
 {
 DASHContext *c = s->priv_data;
@@ -262,7 +273,8 @@ static void dash_free(AVFormatContext *s)
 av_freep(&c->streams);
 }
 
-static void output_segment_list(OutputStream *os, AVIOContext *out, 
DASHContext *c)
+static void output_segment_list(OutputStream *os, AVIOContext *out, 
DASHContext *c,
+int representation_id, int final)
 {
 int i, start_index = 0, start_number = 1;
 if (c->window_size) {
@@ -322,6 +334,55 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, DASHContext
 }
 avio_printf(out, "\t\t\t\t\n");
 }
+if (c->hls_playlist && start_index < os->nb_segments)
+{
+int timescale = os->ctx->streams[0]->time_base.den;
+char temp_filename_hls[1024];
+char filename_hls[1024];
+AVIOContext *out_hls = NULL;
+AVDictionary *http_opts = NULL;
+int target_duration = 0;
+const char *proto = avio_find_protocol_name(c->dirname);
+int use_rename = proto && !strcmp(proto, "file");
+
+get_hls_playlist_name(filename_hls, sizeof(filename_hls),
+  c->dirname, representation_id);
+
+snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? 
"%s.tmp" : "%s", filename_hls);
+
+set_http_options(&http_opts, c);
+avio_open2(&out_hls, temp_filename_hls, AVIO_FLAG_WRITE, NULL, 
&http_opts);
+av_dict_free(&http_opts);
+for (i = start_index; i < os->nb_segments; i++) {
+Segment *seg = os->segments[i];
+if (target_duration < seg->duration)
+target_duration = seg->duration;
+}
+target_duration = lrint((double) target_duration / timescale);
+
+ff_hls_write_playlist_header(out_hls, 6, -1, target_duration,
+ start_number, PLAYLIST_TYPE_NONE);
+
+ff_hls_write_init_file(out_hls, os->initfile, c->single_file,
+   os->init_range_length, os->init_start_pos);
+
+for (i = start_index; i < os->nb_segments; i++) {
+Segment *seg = os->segments[i];
+ff_hls_write_file_entry(out_hls, 0, c->single_file, 0,
+(double) seg->duration / timescale,
+seg->range_length, seg->start_pos, NULL,
+c->single_file ? os->initfile : seg->file,
+NULL);
+}
+
+if (final)
+ff_hls_write_end_list(out_hls);
+
+avio_close(out_hls);
+if (use_rename)
+a

[FFmpeg-devel] [PATCH] avformat/hlsenc: Added option to add EXT-X-INDEPENDENT-SEGMENTS tag

2017-11-22 Thread Karthick J
---
 doc/muxers.texi  |  4 
 libavformat/hlsenc.c | 14 ++
 2 files changed, 18 insertions(+)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 0bb8ad2..9d9ca31 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -737,6 +737,10 @@ The file specified by @code{hls_key_info_file} will be 
checked periodically and
 detect updates to the encryption info. Be sure to replace this file atomically,
 including the file containing the AES encryption key.
 
+@item independent_segments
+Add the @code{#EXT-X-INDEPENDENT-SEGMENTS} to playlists that has video segments
+and when all the segments of that playlist are guaranteed to start with a Key 
frame.
+
 @item split_by_time
 Allow segments to start on frames other than keyframes. This improves
 behavior on some players when the time between keyframes is inconsistent,
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 3c47ced..5fc355a 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -88,6 +88,7 @@ typedef enum HLSFlags {
 HLS_SECOND_LEVEL_SEGMENT_SIZE = (1 << 10), // include segment size (bytes) 
in segment filenames when use_localtime  e.g.: %%014s
 HLS_TEMP_FILE = (1 << 11),
 HLS_PERIODIC_REKEY = (1 << 12),
+HLS_INDEPENDENT_SEGMENTS = (1 << 13),
 } HLSFlags;
 
 typedef enum {
@@ -1191,6 +1192,10 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 sequence = 0;
 }
 
+if (hls->flags & HLS_INDEPENDENT_SEGMENTS) {
+hls->version = 6;
+}
+
 if (hls->segment_type == SEGMENT_TYPE_FMP4) {
 hls->version = 7;
 }
@@ -1220,6 +1225,9 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 avio_printf(out, "#EXT-X-DISCONTINUITY\n");
 vs->discontinuity_set = 1;
 }
+if (vs->has_video && (hls->flags & HLS_INDEPENDENT_SEGMENTS)) {
+avio_printf(out, "#EXT-X-INDEPENDENT-SEGMENTS\n");
+}
 for (en = vs->segments; en; en = en->next) {
 if ((hls->encrypt || hls->key_info_file) && (!key_uri || 
strcmp(en->key_uri, key_uri) ||
 av_strcasecmp(en->iv_string, iv_string))) {
@@ -1732,6 +1740,11 @@ static int hls_write_header(AVFormatContext *s)
 vs->start_pts  = AV_NOPTS_VALUE;
 vs->current_segment_final_filename_fmt[0] = '\0';
 
+if (hls->flags & HLS_SPLIT_BY_TIME) {
+// Independent segments cannot be guaranteed when splitting by time
+hls->flags &= ~HLS_INDEPENDENT_SEGMENTS;
+}
+
 if (hls->flags & HLS_PROGRAM_DATE_TIME) {
 time_t now0;
 time(&now0);
@@ -2323,6 +2336,7 @@ static const AVOption options[] = {
 {"second_level_segment_duration", "include segment duration in segment 
filenames when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 = 
HLS_SECOND_LEVEL_SEGMENT_DURATION }, 0, UINT_MAX,   E, "flags"},
 {"second_level_segment_size", "include segment size in segment filenames 
when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 = 
HLS_SECOND_LEVEL_SEGMENT_SIZE }, 0, UINT_MAX,   E, "flags"},
 {"periodic_rekey", "reload keyinfo file periodically for re-keying", 0, 
AV_OPT_TYPE_CONST, {.i64 = HLS_PERIODIC_REKEY }, 0, UINT_MAX,   E, "flags"},
+{"independent_segments", "add EXT-X-INDEPENDENT-SEGMENTS, whenever 
applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_INDEPENDENT_SEGMENTS }, 0, 
UINT_MAX, E, "flags"},
 {"use_localtime", "set filename expansion with strftime at segment 
creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
 {"use_localtime_mkdir", "create last directory component in 
strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, 
{.i64 = 0 }, 0, 1, E },
 {"hls_playlist_type", "set the HLS playlist type", OFFSET(pl_type), 
AV_OPT_TYPE_INT, {.i64 = PLAYLIST_TYPE_NONE }, 0, PLAYLIST_TYPE_NB-1, E, 
"pl_type" },
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2] avformat/hlsenc: Added option to add EXT-X-INDEPENDENT-SEGMENTS tag

2017-11-23 Thread Karthick J
---
 doc/muxers.texi  |  4 
 libavformat/hlsenc.c | 17 +
 2 files changed, 21 insertions(+)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 0bb8ad2..9d9ca31 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -737,6 +737,10 @@ The file specified by @code{hls_key_info_file} will be 
checked periodically and
 detect updates to the encryption info. Be sure to replace this file atomically,
 including the file containing the AES encryption key.
 
+@item independent_segments
+Add the @code{#EXT-X-INDEPENDENT-SEGMENTS} to playlists that has video segments
+and when all the segments of that playlist are guaranteed to start with a Key 
frame.
+
 @item split_by_time
 Allow segments to start on frames other than keyframes. This improves
 behavior on some players when the time between keyframes is inconsistent,
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 3c47ced..bad5e14 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -88,6 +88,7 @@ typedef enum HLSFlags {
 HLS_SECOND_LEVEL_SEGMENT_SIZE = (1 << 10), // include segment size (bytes) 
in segment filenames when use_localtime  e.g.: %%014s
 HLS_TEMP_FILE = (1 << 11),
 HLS_PERIODIC_REKEY = (1 << 12),
+HLS_INDEPENDENT_SEGMENTS = (1 << 13),
 } HLSFlags;
 
 typedef enum {
@@ -1191,6 +1192,10 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 sequence = 0;
 }
 
+if (hls->flags & HLS_INDEPENDENT_SEGMENTS) {
+hls->version = 6;
+}
+
 if (hls->segment_type == SEGMENT_TYPE_FMP4) {
 hls->version = 7;
 }
@@ -1220,6 +1225,9 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 avio_printf(out, "#EXT-X-DISCONTINUITY\n");
 vs->discontinuity_set = 1;
 }
+if (vs->has_video && (hls->flags & HLS_INDEPENDENT_SEGMENTS)) {
+avio_printf(out, "#EXT-X-INDEPENDENT-SEGMENTS\n");
+}
 for (en = vs->segments; en; en = en->next) {
 if ((hls->encrypt || hls->key_info_file) && (!key_uri || 
strcmp(en->key_uri, key_uri) ||
 av_strcasecmp(en->iv_string, iv_string))) {
@@ -1732,6 +1740,14 @@ static int hls_write_header(AVFormatContext *s)
 vs->start_pts  = AV_NOPTS_VALUE;
 vs->current_segment_final_filename_fmt[0] = '\0';
 
+if (hls->flags & HLS_SPLIT_BY_TIME) {
+// Independent segments cannot be guaranteed when splitting by time
+hls->flags &= ~HLS_INDEPENDENT_SEGMENTS;
+av_log(s, AV_LOG_WARNING,
+   "'split_by_time' and 'independent_segments' cannot be enabled 
together. "
+   "Disabling 'independent_segments' flag\n");
+}
+
 if (hls->flags & HLS_PROGRAM_DATE_TIME) {
 time_t now0;
 time(&now0);
@@ -2323,6 +2339,7 @@ static const AVOption options[] = {
 {"second_level_segment_duration", "include segment duration in segment 
filenames when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 = 
HLS_SECOND_LEVEL_SEGMENT_DURATION }, 0, UINT_MAX,   E, "flags"},
 {"second_level_segment_size", "include segment size in segment filenames 
when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 = 
HLS_SECOND_LEVEL_SEGMENT_SIZE }, 0, UINT_MAX,   E, "flags"},
 {"periodic_rekey", "reload keyinfo file periodically for re-keying", 0, 
AV_OPT_TYPE_CONST, {.i64 = HLS_PERIODIC_REKEY }, 0, UINT_MAX,   E, "flags"},
+{"independent_segments", "add EXT-X-INDEPENDENT-SEGMENTS, whenever 
applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_INDEPENDENT_SEGMENTS }, 0, 
UINT_MAX, E, "flags"},
 {"use_localtime", "set filename expansion with strftime at segment 
creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
 {"use_localtime_mkdir", "create last directory component in 
strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, 
{.i64 = 0 }, 0, 1, E },
 {"hls_playlist_type", "set the HLS playlist type", OFFSET(pl_type), 
AV_OPT_TYPE_INT, {.i64 = PLAYLIST_TYPE_NONE }, 0, PLAYLIST_TYPE_NB-1, E, 
"pl_type" },
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v3] avformat/hlsenc: Added option to add EXT-X-INDEPENDENT-SEGMENTS tag

2017-11-23 Thread Karthick J
---
 doc/muxers.texi  |  4 
 libavformat/hlsenc.c | 17 +
 2 files changed, 21 insertions(+)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 0bb8ad2..9d9ca31 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -737,6 +737,10 @@ The file specified by @code{hls_key_info_file} will be 
checked periodically and
 detect updates to the encryption info. Be sure to replace this file atomically,
 including the file containing the AES encryption key.
 
+@item independent_segments
+Add the @code{#EXT-X-INDEPENDENT-SEGMENTS} to playlists that has video segments
+and when all the segments of that playlist are guaranteed to start with a Key 
frame.
+
 @item split_by_time
 Allow segments to start on frames other than keyframes. This improves
 behavior on some players when the time between keyframes is inconsistent,
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 3c47ced..3010714 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -88,6 +88,7 @@ typedef enum HLSFlags {
 HLS_SECOND_LEVEL_SEGMENT_SIZE = (1 << 10), // include segment size (bytes) 
in segment filenames when use_localtime  e.g.: %%014s
 HLS_TEMP_FILE = (1 << 11),
 HLS_PERIODIC_REKEY = (1 << 12),
+HLS_INDEPENDENT_SEGMENTS = (1 << 13),
 } HLSFlags;
 
 typedef enum {
@@ -1191,6 +1192,10 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 sequence = 0;
 }
 
+if (hls->flags & HLS_INDEPENDENT_SEGMENTS) {
+hls->version = 6;
+}
+
 if (hls->segment_type == SEGMENT_TYPE_FMP4) {
 hls->version = 7;
 }
@@ -1220,6 +1225,9 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 avio_printf(out, "#EXT-X-DISCONTINUITY\n");
 vs->discontinuity_set = 1;
 }
+if (vs->has_video && (hls->flags & HLS_INDEPENDENT_SEGMENTS)) {
+avio_printf(out, "#EXT-X-INDEPENDENT-SEGMENTS\n");
+}
 for (en = vs->segments; en; en = en->next) {
 if ((hls->encrypt || hls->key_info_file) && (!key_uri || 
strcmp(en->key_uri, key_uri) ||
 av_strcasecmp(en->iv_string, iv_string))) {
@@ -1732,6 +1740,14 @@ static int hls_write_header(AVFormatContext *s)
 vs->start_pts  = AV_NOPTS_VALUE;
 vs->current_segment_final_filename_fmt[0] = '\0';
 
+if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & 
HLS_INDEPENDENT_SEGMENTS) {
+// Independent segments cannot be guaranteed when splitting by time
+hls->flags &= ~HLS_INDEPENDENT_SEGMENTS;
+av_log(s, AV_LOG_WARNING,
+   "'split_by_time' and 'independent_segments' cannot be enabled 
together. "
+   "Disabling 'independent_segments' flag\n");
+}
+
 if (hls->flags & HLS_PROGRAM_DATE_TIME) {
 time_t now0;
 time(&now0);
@@ -2323,6 +2339,7 @@ static const AVOption options[] = {
 {"second_level_segment_duration", "include segment duration in segment 
filenames when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 = 
HLS_SECOND_LEVEL_SEGMENT_DURATION }, 0, UINT_MAX,   E, "flags"},
 {"second_level_segment_size", "include segment size in segment filenames 
when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 = 
HLS_SECOND_LEVEL_SEGMENT_SIZE }, 0, UINT_MAX,   E, "flags"},
 {"periodic_rekey", "reload keyinfo file periodically for re-keying", 0, 
AV_OPT_TYPE_CONST, {.i64 = HLS_PERIODIC_REKEY }, 0, UINT_MAX,   E, "flags"},
+{"independent_segments", "add EXT-X-INDEPENDENT-SEGMENTS, whenever 
applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_INDEPENDENT_SEGMENTS }, 0, 
UINT_MAX, E, "flags"},
 {"use_localtime", "set filename expansion with strftime at segment 
creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
 {"use_localtime_mkdir", "create last directory component in 
strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, 
{.i64 = 0 }, 0, 1, E },
 {"hls_playlist_type", "set the HLS playlist type", OFFSET(pl_type), 
AV_OPT_TYPE_INT, {.i64 = PLAYLIST_TYPE_NONE }, 0, PLAYLIST_TYPE_NB-1, E, 
"pl_type" },
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v3 1/2] avformat/hlsenc: Modularized playlist creation to allow reuse

2017-11-23 Thread Karthick J
---
 libavformat/hlsenc.c | 238 +++
 libavformat/hlsenc.h |  68 +++
 2 files changed, 194 insertions(+), 112 deletions(-)
 create mode 100644 libavformat/hlsenc.h

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 30ccf73..5c4f459 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -45,6 +45,7 @@
 
 #include "avformat.h"
 #include "avio_internal.h"
+#include "hlsenc.h"
 #include "internal.h"
 #include "os_support.h"
 
@@ -73,36 +74,11 @@ typedef struct HLSSegment {
 struct HLSSegment *next;
 } HLSSegment;
 
-typedef enum HLSFlags {
-// Generate a single media file and use byte ranges in the playlist.
-HLS_SINGLE_FILE = (1 << 0),
-HLS_DELETE_SEGMENTS = (1 << 1),
-HLS_ROUND_DURATIONS = (1 << 2),
-HLS_DISCONT_START = (1 << 3),
-HLS_OMIT_ENDLIST = (1 << 4),
-HLS_SPLIT_BY_TIME = (1 << 5),
-HLS_APPEND_LIST = (1 << 6),
-HLS_PROGRAM_DATE_TIME = (1 << 7),
-HLS_SECOND_LEVEL_SEGMENT_INDEX = (1 << 8), // include segment index in 
segment filenames when use_localtime  e.g.: %%03d
-HLS_SECOND_LEVEL_SEGMENT_DURATION = (1 << 9), // include segment duration 
(microsec) in segment filenames when use_localtime  e.g.: %%09t
-HLS_SECOND_LEVEL_SEGMENT_SIZE = (1 << 10), // include segment size (bytes) 
in segment filenames when use_localtime  e.g.: %%014s
-HLS_TEMP_FILE = (1 << 11),
-HLS_PERIODIC_REKEY = (1 << 12),
-HLS_INDEPENDENT_SEGMENTS = (1 << 13),
-} HLSFlags;
-
 typedef enum {
 SEGMENT_TYPE_MPEGTS,
 SEGMENT_TYPE_FMP4,
 } SegmentType;
 
-typedef enum {
-PLAYLIST_TYPE_NONE,
-PLAYLIST_TYPE_EVENT,
-PLAYLIST_TYPE_VOD,
-PLAYLIST_TYPE_NB,
-} PlaylistType;
-
 typedef struct VariantStream {
 unsigned number;
 int64_t sequence;
@@ -207,6 +183,113 @@ typedef struct HLSContext {
 unsigned int master_publish_rate;
 } HLSContext;
 
+void ff_hls_write_playlist_version(AVIOContext *out, int version) {
+if (!out)
+return;
+avio_printf(out, "#EXTM3U\n");
+avio_printf(out, "#EXT-X-VERSION:%d\n", version);
+}
+
+void ff_hls_write_stream_info(AVStream *st, AVIOContext *out,
+  int bandwidth, char *filename) {
+if (!out || !filename)
+return;
+
+if (!bandwidth) {
+av_log(NULL, AV_LOG_WARNING,
+"Bandwidth info not available, set audio and video 
bitrates\n");
+return;
+}
+
+avio_printf(out, "#EXT-X-STREAM-INF:BANDWIDTH=%d", bandwidth);
+if (st && st->codecpar->width > 0 && st->codecpar->height > 0)
+avio_printf(out, ",RESOLUTION=%dx%d", st->codecpar->width,
+st->codecpar->height);
+avio_printf(out, "\n%s\n\n", filename);
+}
+
+void ff_hls_write_playlist_header(AVIOContext *out, int version, int 
allowcache,
+  int target_duration, int64_t sequence,
+  uint32_t playlist_type) {
+if (!out)
+return;
+ff_hls_write_playlist_version(out, version);
+if (allowcache == 0 || allowcache == 1) {
+avio_printf(out, "#EXT-X-ALLOW-CACHE:%s\n", allowcache == 0 ? "NO" : 
"YES");
+}
+avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration);
+avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
+av_log(NULL, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
+
+if (playlist_type == PLAYLIST_TYPE_EVENT) {
+avio_printf(out, "#EXT-X-PLAYLIST-TYPE:EVENT\n");
+} else if (playlist_type == PLAYLIST_TYPE_VOD) {
+avio_printf(out, "#EXT-X-PLAYLIST-TYPE:VOD\n");
+}
+}
+
+void ff_hls_write_init_file(AVIOContext *out, char *filename,
+int byterange_mode, int64_t size, int64_t pos) {
+avio_printf(out, "#EXT-X-MAP:URI=\"%s\"", filename);
+if (byterange_mode) {
+avio_printf(out, ",BYTERANGE=\"%"PRId64"@%"PRId64"\"", size, pos);
+}
+avio_printf(out, "\n");
+}
+
+void ff_hls_write_file_entry(AVIOContext *out, int insert_discont,
+int byterange_mode, uint32_t flags, double 
duration,
+int64_t size, int64_t pos, //Used only if 
HLS_SINGLE_FILE flag is set
+char *baseurl, //Ignored if NULL
+char *filename, double *prog_date_time) {
+if (!out || !filename)
+return;
+
+if (insert_discont) {
+avio_printf(out, "#EXT-X-DISCONTINUITY\n");
+}
+if (flags & HLS_ROUND_DURATIONS)
+avio_printf(out, "#EXTINF:%ld,\n",  lrint(duration));
+else
+avio_printf(out, "#EXTINF:%f,\n", duration);
+if (byterange_mode)
+avio_printf(out, "#EXT-X-BYTERANGE:%"PRId64"@%"PRId64"\n", size, pos);
+
+if ((flags & HLS_PROGRAM_DATE_TIME) && prog_date_time) {
+time_t tt, wrongsecs;
+int milli;
+struct tm *tm, tmpbuf;
+char buf0[128], buf1[128];
+tt = (int64_t)prog_date_time;

[FFmpeg-devel] [PATCH v4 2/2] avformat/dashenc: Option to generate hls playlist as well

2017-11-23 Thread Karthick J
This is to take full advantage of Common Media Application Format.
Now server can generate one content and serve both HLS and DASH players.
---
 doc/muxers.texi   |   3 ++
 libavformat/Makefile  |   2 +-
 libavformat/dashenc.c | 103 --
 3 files changed, 103 insertions(+), 5 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 9d9ca31..16b033f 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -249,6 +249,9 @@ DASH-templated name to used for the media segments. Default 
is "chunk-stream$Rep
 URL of the page that will return the UTC timestamp in ISO format. Example: 
"https://time.akamai.com/?iso";
 @item -http_user_agent @var{user_agent}
 Override User-Agent field in HTTP header. Applicable only for HTTP output.
+@item -hls_playlist @var{hls_playlist}
+Generate HLS playlist files as well. The master playlist is generated with the 
filename master.m3u8.
+One media playlist file is generated for each stream with filenames 
media_0.m3u8, media_1.m3u8, etc.
 @item -adaptation_sets @var{adaptation_sets}
 Assign streams to AdaptationSets. Syntax is "id=x,streams=a,b,c 
id=y,streams=d,e" with x and y being the IDs
 of the adaptation sets and a,b,c,d and e are the indices of the mapped streams.
diff --git a/libavformat/Makefile b/libavformat/Makefile
index fd8b9f9..4bffdf2 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -135,7 +135,7 @@ OBJS-$(CONFIG_CONCAT_DEMUXER)+= concatdec.o
 OBJS-$(CONFIG_CRC_MUXER) += crcenc.o
 OBJS-$(CONFIG_DATA_DEMUXER)  += rawdec.o
 OBJS-$(CONFIG_DATA_MUXER)+= rawenc.o
-OBJS-$(CONFIG_DASH_MUXER)+= dash.o dashenc.o
+OBJS-$(CONFIG_DASH_MUXER)+= dash.o dashenc.o hlsplaylist.o
 OBJS-$(CONFIG_DASH_DEMUXER)  += dash.o dashdec.o
 OBJS-$(CONFIG_DAUD_DEMUXER)  += dauddec.o
 OBJS-$(CONFIG_DAUD_MUXER)+= daudenc.o
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 201668a..952a52f 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -36,6 +36,7 @@
 #include "avc.h"
 #include "avformat.h"
 #include "avio_internal.h"
+#include "hlsplaylist.h"
 #include "internal.h"
 #include "isom.h"
 #include "os_support.h"
@@ -101,6 +102,8 @@ typedef struct DASHContext {
 const char *media_seg_name;
 const char *utc_timing_url;
 const char *user_agent;
+int hls_playlist;
+int master_playlist_created;
 } DASHContext;
 
 static struct codec_string {
@@ -217,6 +220,14 @@ static void set_http_options(AVDictionary **options, 
DASHContext *c)
 av_dict_set(options, "user_agent", c->user_agent, 0);
 }
 
+static void get_hls_playlist_name(char *playlist_name, int string_size,
+  const char *base_url, int id) {
+if (base_url)
+snprintf(playlist_name, string_size, "%smedia_%d.m3u8", base_url, id);
+else
+snprintf(playlist_name, string_size, "media_%d.m3u8", id);
+}
+
 static int flush_init_segment(AVFormatContext *s, OutputStream *os)
 {
 DASHContext *c = s->priv_data;
@@ -262,7 +273,8 @@ static void dash_free(AVFormatContext *s)
 av_freep(&c->streams);
 }
 
-static void output_segment_list(OutputStream *os, AVIOContext *out, 
DASHContext *c)
+static void output_segment_list(OutputStream *os, AVIOContext *out, 
DASHContext *c,
+int representation_id, int final)
 {
 int i, start_index = 0, start_number = 1;
 if (c->window_size) {
@@ -322,6 +334,55 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, DASHContext
 }
 avio_printf(out, "\t\t\t\t\n");
 }
+if (c->hls_playlist && start_index < os->nb_segments)
+{
+int timescale = os->ctx->streams[0]->time_base.den;
+char temp_filename_hls[1024];
+char filename_hls[1024];
+AVIOContext *out_hls = NULL;
+AVDictionary *http_opts = NULL;
+int target_duration = 0;
+const char *proto = avio_find_protocol_name(c->dirname);
+int use_rename = proto && !strcmp(proto, "file");
+
+get_hls_playlist_name(filename_hls, sizeof(filename_hls),
+  c->dirname, representation_id);
+
+snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? 
"%s.tmp" : "%s", filename_hls);
+
+set_http_options(&http_opts, c);
+avio_open2(&out_hls, temp_filename_hls, AVIO_FLAG_WRITE, NULL, 
&http_opts);
+av_dict_free(&http_opts);
+for (i = start_index; i < os->nb_segments; i++) {
+Segment *seg = os->segments[i];
+if (target_duration < seg->duration)
+target_duration = seg->duration;
+}
+target_duration = lrint((double) target_duration / timescale);
+
+ff_hls_write_playlist_header(out_hls, 6, -1, target_duration,
+ start_number, PLAYLIST_TYPE_NONE);
+
+ff_hls_wri

[FFmpeg-devel] [PATCH v4 1/2] avformat/hlsenc: Modularized playlist creation to allow reuse

2017-11-23 Thread Karthick J
---
 libavformat/Makefile  |   2 +-
 libavformat/hlsenc.c  | 115 +++
 libavformat/hlsplaylist.c | 136 ++
 libavformat/hlsplaylist.h |  51 +
 4 files changed, 209 insertions(+), 95 deletions(-)
 create mode 100644 libavformat/hlsplaylist.c
 create mode 100644 libavformat/hlsplaylist.h

diff --git a/libavformat/Makefile b/libavformat/Makefile
index b1e7b19..fd8b9f9 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -215,7 +215,7 @@ OBJS-$(CONFIG_HDS_MUXER) += hdsenc.o
 OBJS-$(CONFIG_HEVC_DEMUXER)  += hevcdec.o rawdec.o
 OBJS-$(CONFIG_HEVC_MUXER)+= rawenc.o
 OBJS-$(CONFIG_HLS_DEMUXER)   += hls.o
-OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o
+OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o hlsplaylist.o
 OBJS-$(CONFIG_HNM_DEMUXER)   += hnm.o
 OBJS-$(CONFIG_ICO_DEMUXER)   += icodec.o
 OBJS-$(CONFIG_ICO_MUXER) += icoenc.o
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 30ccf73..7c759a8 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -45,6 +45,7 @@
 
 #include "avformat.h"
 #include "avio_internal.h"
+#include "hlsplaylist.h"
 #include "internal.h"
 #include "os_support.h"
 
@@ -96,13 +97,6 @@ typedef enum {
 SEGMENT_TYPE_FMP4,
 } SegmentType;
 
-typedef enum {
-PLAYLIST_TYPE_NONE,
-PLAYLIST_TYPE_EVENT,
-PLAYLIST_TYPE_VOD,
-PLAYLIST_TYPE_NB,
-} PlaylistType;
-
 typedef struct VariantStream {
 unsigned number;
 int64_t sequence;
@@ -1023,19 +1017,6 @@ static void hls_free_segments(HLSSegment *p)
 }
 }
 
-static void write_m3u8_head_block(HLSContext *hls, AVIOContext *out, int 
version,
-  int target_duration, int64_t sequence)
-{
-avio_printf(out, "#EXTM3U\n");
-avio_printf(out, "#EXT-X-VERSION:%d\n", version);
-if (hls->allowcache == 0 || hls->allowcache == 1) {
-avio_printf(out, "#EXT-X-ALLOW-CACHE:%s\n", hls->allowcache == 0 ? 
"NO" : "YES");
-}
-avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration);
-avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
-av_log(hls, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
-}
-
 static void hls_rename_temp_file(AVFormatContext *s, AVFormatContext *oc)
 {
 size_t len = strlen(oc->filename);
@@ -1101,8 +1082,7 @@ static int create_master_playlist(AVFormatContext *s,
 goto fail;
 }
 
-avio_printf(master_pb, "#EXTM3U\n");
-avio_printf(master_pb, "#EXT-X-VERSION:%d\n", hls->version);
+ff_hls_write_playlist_version(master_pb, hls->version);
 
 /* For variant streams with video add #EXT-X-STREAM-INF tag with 
attributes*/
 for (i = 0; i < hls->nb_varstreams; i++) {
@@ -1143,18 +1123,7 @@ static int create_master_playlist(AVFormatContext *s,
 bandwidth += aud_st->codecpar->bit_rate;
 bandwidth += bandwidth / 10;
 
-if (!bandwidth) {
-av_log(NULL, AV_LOG_WARNING,
-"Bandwidth info not available, set audio and video 
bitrates\n");
-av_freep(&m3u8_rel_name);
-continue;
-}
-
-avio_printf(master_pb, "#EXT-X-STREAM-INF:BANDWIDTH=%d", bandwidth);
-if (vid_st && vid_st->codecpar->width > 0 && vid_st->codecpar->height 
> 0)
-avio_printf(master_pb, ",RESOLUTION=%dx%d", 
vid_st->codecpar->width,
-vid_st->codecpar->height);
-avio_printf(master_pb, "\n%s\n\n", m3u8_rel_name);
+ff_hls_write_stream_info(vid_st, master_pb, bandwidth, m3u8_rel_name);
 
 av_freep(&m3u8_rel_name);
 }
@@ -1183,6 +1152,7 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 char *iv_string = NULL;
 AVDictionary *options = NULL;
 double prog_date_time = vs->initial_prog_date_time;
+double *prog_date_time_p = (hls->flags & HLS_PROGRAM_DATE_TIME) ? 
&prog_date_time : NULL;
 int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size 
> 0);
 
 hls->version = 3;
@@ -1213,12 +1183,8 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 }
 
 vs->discontinuity_set = 0;
-write_m3u8_head_block(hls, out, hls->version, target_duration, sequence);
-if (hls->pl_type == PLAYLIST_TYPE_EVENT) {
-avio_printf(out, "#EXT-X-PLAYLIST-TYPE:EVENT\n");
-} else if (hls->pl_type == PLAYLIST_TYPE_VOD) {
-avio_printf(out, "#EXT-X-PLAYLIST-TYPE:VOD\n");
-}
+ff_hls_write_playlist_header(out, hls->version, hls->allowcache,
+ target_duration, sequence, hls->pl_type);
 
 if((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && 
vs->discontinuity_set==0 ){
 avio_printf(out, "#EXT-X-DISCONTINUITY\n");
@@ -1238,74 +1204,35 @@ static int hls_window(AVFormatContext *s, int last, 
Variant

[FFmpeg-devel] [PATCH v2 1/3] avformat/hlsenc:addition of #EXT-X-MEDIA tag and AUDIO attribute

2017-11-24 Thread Karthick J
From: Vishwanath Dixit 

---
 doc/muxers.texi  | 12 ++
 libavformat/hlsenc.c | 63 ++--
 2 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 9d9ca31..7e6d594 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -831,6 +831,18 @@ be a video only stream with video bitrate 1000k, the 
second variant stream will
 be an audio only stream with bitrate 64k and the third variant stream will be a
 video only stream with bitrate 256k. Here, three media playlist with file names
 out_1.m3u8, out_2.m3u8 and out_3.m3u8 will be created.
+@example
+ffmpeg -re -i in.ts -b:a:0 32k -b:a:1 64k -b:v:0 1000k -b:v:1 3000k  \
+  -map 0:a -map 0:a -map 0:v -map 0:v -f hls \
+  -var_stream_map "a:0,agroup:aud_low a:1,agroup:aud_high v:0,agroup:aud_low 
v:1,agroup:aud_high" \
+  -master_pl_name master.m3u8 \
+  http://example.com/live/out.m3u8
+@end example
+This example creates two audio only and two video only variant streams. In
+addition to the #EXT-X-STREAM-INF tag for each variant stream in the master
+playlist, #EXT-X-MEDIA tag is also added for the two audio only variant streams
+and they are mapped to the two video only variant streams with audio group 
names
+'aud_low' and 'aud_high'.
 
 By default, a single hls variant containing all the encoded streams is created.
 
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 30ccf73..58d7c58 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -147,6 +147,7 @@ typedef struct VariantStream {
 AVStream **streams;
 unsigned int nb_streams;
 int m3u8_created; /* status of media play-list creation */
+char *agroup; /* audio group name */
 char *baseurl;
 } VariantStream;
 
@@ -1069,7 +1070,7 @@ static int create_master_playlist(AVFormatContext *s,
   VariantStream * const input_vs)
 {
 HLSContext *hls = s->priv_data;
-VariantStream *vs;
+VariantStream *vs, *temp_vs;
 AVStream *vid_st, *aud_st;
 AVIOContext *master_pb = 0;
 AVDictionary *options = NULL;
@@ -1104,6 +1105,34 @@ static int create_master_playlist(AVFormatContext *s,
 avio_printf(master_pb, "#EXTM3U\n");
 avio_printf(master_pb, "#EXT-X-VERSION:%d\n", hls->version);
 
+/* For audio only variant streams add #EXT-X-MEDIA tag with attributes*/
+for (i = 0; i < hls->nb_varstreams; i++) {
+vs = &(hls->var_streams[i]);
+
+if (vs->has_video || vs->has_subtitle || !vs->agroup)
+continue;
+
+m3u8_name_size = strlen(vs->m3u8_name) + 1;
+m3u8_rel_name = av_malloc(m3u8_name_size);
+if (!m3u8_rel_name) {
+ret = AVERROR(ENOMEM);
+goto fail;
+}
+av_strlcpy(m3u8_rel_name, vs->m3u8_name, m3u8_name_size);
+ret = get_relative_url(hls->master_m3u8_url, vs->m3u8_name,
+   m3u8_rel_name, m3u8_name_size);
+if (ret < 0) {
+av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n");
+goto fail;
+}
+
+avio_printf(master_pb, "#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"group_%s\"",
+vs->agroup);
+avio_printf(master_pb, ",NAME=\"audio_0\",DEFAULT=YES,URI=\"%s\"\n",
+m3u8_rel_name);
+av_freep(&m3u8_rel_name);
+}
+
 /* For variant streams with video add #EXT-X-STREAM-INF tag with 
attributes*/
 for (i = 0; i < hls->nb_varstreams; i++) {
 vs = &(hls->var_streams[i]);
@@ -1136,6 +1165,25 @@ static int create_master_playlist(AVFormatContext *s,
 continue;
 }
 
+/**
+ * Traverse through the list of audio only rendition streams and find
+ * the rendition which has highest bitrate in the same audio group
+ */
+if (vs->agroup) {
+for (j = 0; j < hls->nb_varstreams; j++) {
+temp_vs = &(hls->var_streams[j]);
+if (!temp_vs->has_video && !temp_vs->has_subtitle &&
+temp_vs->agroup &&
+!strcmp(temp_vs->agroup, vs->agroup)) {
+if (!aud_st)
+aud_st = temp_vs->streams[0];
+if (temp_vs->streams[0]->codecpar->bit_rate >
+aud_st->codecpar->bit_rate)
+aud_st = temp_vs->streams[0];
+}
+}
+}
+
 bandwidth = 0;
 if (vid_st)
 bandwidth += vid_st->codecpar->bit_rate;
@@ -1154,6 +1202,10 @@ static int create_master_playlist(AVFormatContext *s,
 if (vid_st && vid_st->codecpar->width > 0 && vid_st->codecpar->height 
> 0)
 avio_printf(master_pb, ",RESOLUTION=%dx%d", 
vid_st->codecpar->width,
 vid_st->codecpar->height);
+
+if (vs->agroup && aud_st)
+avio_printf(master_pb, ",AUDIO=\"group_%s\"", vs->agroup);
+
 avio_printf(master_pb, "\n%s\n\n", m3u8

[FFmpeg-devel] [PATCH v2 2/3] avcodec/libx264:setting profile and level in avcodec context

2017-11-24 Thread Karthick J
From: Vishwanath Dixit 

---
 libavcodec/libx264.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
index 9c67c91..6b93aa8 100644
--- a/libavcodec/libx264.c
+++ b/libavcodec/libx264.c
@@ -454,6 +454,9 @@ static av_cold int X264_init(AVCodecContext *avctx)
 X264Context *x4 = avctx->priv_data;
 AVCPBProperties *cpb_props;
 int sw,sh;
+x264_nal_t *nal;
+uint8_t *p;
+int nnal, s, i;
 
 if (avctx->global_quality > 0)
 av_log(avctx, AV_LOG_WARNING, "-qscale is ignored, -crf is 
recommended.\n");
@@ -799,12 +802,11 @@ FF_ENABLE_DEPRECATION_WARNINGS
 if (!x4->enc)
 return AVERROR_EXTERNAL;
 
-if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
-x264_nal_t *nal;
-uint8_t *p;
-int nnal, s, i;
+s = x264_encoder_headers(x4->enc, &nal, &nnal);
+avctx->profile = nal->p_payload[5];
+avctx->level = nal->p_payload[7];
 
-s = x264_encoder_headers(x4->enc, &nal, &nnal);
+if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
 avctx->extradata = p = av_mallocz(s + AV_INPUT_BUFFER_PADDING_SIZE);
 if (!p)
 return AVERROR(ENOMEM);
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 3/3] avformat/hlsenc:addition of CODECS attribute in the master playlist

2017-11-24 Thread Karthick J
From: Vishwanath Dixit 

---
 libavformat/hlsenc.c | 65 +++-
 1 file changed, 64 insertions(+), 1 deletion(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 58d7c58..8a634de 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -1066,6 +1066,62 @@ static int get_relative_url(const char *master_url, 
const char *media_url,
 return 0;
 }
 
+static char *get_codec_str(AVStream *vid_st, AVStream *aud_st) {
+size_t codec_str_size = 64;
+char *codec_str = av_malloc(codec_str_size);
+int video_str_len = 0;
+
+if (!codec_str)
+return NULL;
+
+if (!vid_st && !aud_st) {
+goto fail;
+}
+
+if (vid_st) {
+if (vid_st->codecpar->profile != FF_PROFILE_UNKNOWN &&
+vid_st->codecpar->level != FF_LEVEL_UNKNOWN &&
+vid_st->codecpar->codec_id == AV_CODEC_ID_H264) {
+/* TODO : Set constraint_set flags correctly. Hardcoded to 0 here. 
*/
+snprintf(codec_str, codec_str_size, "avc1.%02x00%02x",
+ vid_st->codecpar->profile, vid_st->codecpar->level);
+} else {
+goto fail;
+}
+video_str_len = strlen(codec_str);
+}
+
+if (aud_st) {
+char *audio_str = codec_str;
+if (video_str_len) {
+codec_str[video_str_len] = ',';
+video_str_len += 1;
+audio_str += video_str_len;
+codec_str_size -= video_str_len;
+}
+if (aud_st->codecpar->codec_id == AV_CODEC_ID_MP2) {
+snprintf(audio_str, codec_str_size, "mp4a.40.33");
+} else if (aud_st->codecpar->codec_id == AV_CODEC_ID_MP3) {
+snprintf(audio_str, codec_str_size, "mp4a.40.34");
+} else if (aud_st->codecpar->codec_id == AV_CODEC_ID_AAC) {
+/* TODO : For HE-AAC, HE-AACv2, the last digit needs to be set to 
5 and 29 respectively */
+snprintf(audio_str, codec_str_size, "mp4a.40.2");
+} else if (aud_st->codecpar->codec_id == AV_CODEC_ID_AC3) {
+snprintf(audio_str, codec_str_size, "mp4a.A5");
+} else if (aud_st->codecpar->codec_id == AV_CODEC_ID_EAC3) {
+snprintf(audio_str, codec_str_size, "mp4a.A6");
+} else {
+goto fail;
+}
+}
+
+return codec_str;
+
+fail:
+av_free(codec_str);
+return NULL;
+}
+
 static int create_master_playlist(AVFormatContext *s,
   VariantStream * const input_vs)
 {
@@ -1076,7 +1132,7 @@ static int create_master_playlist(AVFormatContext *s,
 AVDictionary *options = NULL;
 unsigned int i, j;
 int m3u8_name_size, ret, bandwidth;
-char *m3u8_rel_name;
+char *m3u8_rel_name, *codec_str;
 
 input_vs->m3u8_created = 1;
 if (!hls->master_m3u8_created) {
@@ -1203,6 +1259,13 @@ static int create_master_playlist(AVFormatContext *s,
 avio_printf(master_pb, ",RESOLUTION=%dx%d", 
vid_st->codecpar->width,
 vid_st->codecpar->height);
 
+codec_str = get_codec_str(vid_st, aud_st);
+
+if (codec_str) {
+avio_printf(master_pb, ",CODECS=\"%s\"", codec_str);
+av_free(codec_str);
+}
+
 if (vs->agroup && aud_st)
 avio_printf(master_pb, ",AUDIO=\"group_%s\"", vs->agroup);
 
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] avformat/hlsenc: Added context to av_log calls

2017-11-24 Thread Karthick J
---
 libavformat/hlsenc.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 30ccf73..379a4ec 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -1057,7 +1057,6 @@ static int get_relative_url(const char *master_url, const 
char *media_url,
 if (p) {
 base_len = FFABS(p - master_url);
 if (av_strncasecmp(master_url, media_url, base_len)) {
-av_log(NULL, AV_LOG_WARNING, "Unable to find relative url\n");
 return AVERROR(EINVAL);
 }
 }
@@ -1096,7 +1095,7 @@ static int create_master_playlist(AVFormatContext *s,
  &options);
 av_dict_free(&options);
 if (ret < 0) {
-av_log(NULL, AV_LOG_ERROR, "Failed to open master play list file 
'%s'\n",
+av_log(s, AV_LOG_ERROR, "Failed to open master play list file '%s'\n",
 hls->master_m3u8_url);
 goto fail;
 }
@@ -1118,7 +1117,7 @@ static int create_master_playlist(AVFormatContext *s,
 ret = get_relative_url(hls->master_m3u8_url, vs->m3u8_name,
m3u8_rel_name, m3u8_name_size);
 if (ret < 0) {
-av_log(NULL, AV_LOG_ERROR, "Unable to find relative URL\n");
+av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n");
 goto fail;
 }
 
@@ -1132,7 +1131,7 @@ static int create_master_playlist(AVFormatContext *s,
 }
 
 if (!vid_st && !aud_st) {
-av_log(NULL, AV_LOG_WARNING, "Media stream not found\n");
+av_log(s, AV_LOG_WARNING, "Media stream not found\n");
 continue;
 }
 
@@ -1144,7 +1143,7 @@ static int create_master_playlist(AVFormatContext *s,
 bandwidth += bandwidth / 10;
 
 if (!bandwidth) {
-av_log(NULL, AV_LOG_WARNING,
+av_log(s, AV_LOG_WARNING,
 "Bandwidth info not available, set audio and video 
bitrates\n");
 av_freep(&m3u8_rel_name);
 continue;
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2] avformat/hlsenc: Added context to av_log calls

2017-11-24 Thread Karthick J
Also removed a redundant av_log call
---
 libavformat/hlsenc.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 30ccf73..379a4ec 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -1057,7 +1057,6 @@ static int get_relative_url(const char *master_url, const 
char *media_url,
 if (p) {
 base_len = FFABS(p - master_url);
 if (av_strncasecmp(master_url, media_url, base_len)) {
-av_log(NULL, AV_LOG_WARNING, "Unable to find relative url\n");
 return AVERROR(EINVAL);
 }
 }
@@ -1096,7 +1095,7 @@ static int create_master_playlist(AVFormatContext *s,
  &options);
 av_dict_free(&options);
 if (ret < 0) {
-av_log(NULL, AV_LOG_ERROR, "Failed to open master play list file 
'%s'\n",
+av_log(s, AV_LOG_ERROR, "Failed to open master play list file '%s'\n",
 hls->master_m3u8_url);
 goto fail;
 }
@@ -1118,7 +1117,7 @@ static int create_master_playlist(AVFormatContext *s,
 ret = get_relative_url(hls->master_m3u8_url, vs->m3u8_name,
m3u8_rel_name, m3u8_name_size);
 if (ret < 0) {
-av_log(NULL, AV_LOG_ERROR, "Unable to find relative URL\n");
+av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n");
 goto fail;
 }
 
@@ -1132,7 +1131,7 @@ static int create_master_playlist(AVFormatContext *s,
 }
 
 if (!vid_st && !aud_st) {
-av_log(NULL, AV_LOG_WARNING, "Media stream not found\n");
+av_log(s, AV_LOG_WARNING, "Media stream not found\n");
 continue;
 }
 
@@ -1144,7 +1143,7 @@ static int create_master_playlist(AVFormatContext *s,
 bandwidth += bandwidth / 10;
 
 if (!bandwidth) {
-av_log(NULL, AV_LOG_WARNING,
+av_log(s, AV_LOG_WARNING,
 "Bandwidth info not available, set audio and video 
bitrates\n");
 av_freep(&m3u8_rel_name);
 continue;
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v3 2/3] avcodec/libx264:setting profile and level in avcodec context

2017-11-24 Thread Karthick J
From: Vishwanath Dixit 

---
 libavcodec/libx264.c | 17 -
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
index 9c67c91..2f7f53c 100644
--- a/libavcodec/libx264.c
+++ b/libavcodec/libx264.c
@@ -19,6 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "libavutil/avassert.h"
 #include "libavutil/eval.h"
 #include "libavutil/internal.h"
 #include "libavutil/opt.h"
@@ -454,6 +455,9 @@ static av_cold int X264_init(AVCodecContext *avctx)
 X264Context *x4 = avctx->priv_data;
 AVCPBProperties *cpb_props;
 int sw,sh;
+x264_nal_t *nal;
+uint8_t *p;
+int nnal, s, i;
 
 if (avctx->global_quality > 0)
 av_log(avctx, AV_LOG_WARNING, "-qscale is ignored, -crf is 
recommended.\n");
@@ -799,12 +803,15 @@ FF_ENABLE_DEPRECATION_WARNINGS
 if (!x4->enc)
 return AVERROR_EXTERNAL;
 
-if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
-x264_nal_t *nal;
-uint8_t *p;
-int nnal, s, i;
+s = x264_encoder_headers(x4->enc, &nal, &nnal);
+// Assert for NAL start code and SPS unit type
+av_assert0((nal->p_payload[0] | nal->p_payload[1] | nal->p_payload[2]) == 
0 && nal->p_payload[3] == 1);
+av_assert0((nal->p_payload[4] & 0x1F) == 7);
+// bits 0-7 LSB for profile. bits 8-11 for constrained set flags.
+avctx->profile = ((uint32_t)nal->p_payload[5]) | 
(((uint32_t)nal->p_payload[6] >> 4) << 8);
+avctx->level = nal->p_payload[7];
 
-s = x264_encoder_headers(x4->enc, &nal, &nnal);
+if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
 avctx->extradata = p = av_mallocz(s + AV_INPUT_BUFFER_PADDING_SIZE);
 if (!p)
 return AVERROR(ENOMEM);
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v3 3/3] avformat/hlsenc:addition of CODECS attribute in the master playlist

2017-11-24 Thread Karthick J
From: Vishwanath Dixit 

---
 libavformat/hlsenc.c | 66 +++-
 1 file changed, 65 insertions(+), 1 deletion(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 58d7c58..92c90a1 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -1066,6 +1066,63 @@ static int get_relative_url(const char *master_url, 
const char *media_url,
 return 0;
 }
 
+static char *get_codec_str(AVStream *vid_st, AVStream *aud_st) {
+size_t codec_str_size = 64;
+char *codec_str = av_malloc(codec_str_size);
+int video_str_len = 0;
+
+if (!codec_str)
+return NULL;
+
+if (!vid_st && !aud_st) {
+goto fail;
+}
+
+if (vid_st) {
+if (vid_st->codecpar->profile != FF_PROFILE_UNKNOWN &&
+vid_st->codecpar->level != FF_LEVEL_UNKNOWN &&
+vid_st->codecpar->codec_id == AV_CODEC_ID_H264) {
+snprintf(codec_str, codec_str_size, "avc1.%02x%02x%02x",
+ vid_st->codecpar->profile & 0xFF,
+ ((vid_st->codecpar->profile >> 8) << 4) & 0xFF,
+ vid_st->codecpar->level);
+} else {
+goto fail;
+}
+video_str_len = strlen(codec_str);
+}
+
+if (aud_st) {
+char *audio_str = codec_str;
+if (video_str_len) {
+codec_str[video_str_len] = ',';
+video_str_len += 1;
+audio_str += video_str_len;
+codec_str_size -= video_str_len;
+}
+if (aud_st->codecpar->codec_id == AV_CODEC_ID_MP2) {
+snprintf(audio_str, codec_str_size, "mp4a.40.33");
+} else if (aud_st->codecpar->codec_id == AV_CODEC_ID_MP3) {
+snprintf(audio_str, codec_str_size, "mp4a.40.34");
+} else if (aud_st->codecpar->codec_id == AV_CODEC_ID_AAC) {
+/* TODO : For HE-AAC, HE-AACv2, the last digit needs to be set to 
5 and 29 respectively */
+snprintf(audio_str, codec_str_size, "mp4a.40.2");
+} else if (aud_st->codecpar->codec_id == AV_CODEC_ID_AC3) {
+snprintf(audio_str, codec_str_size, "mp4a.A5");
+} else if (aud_st->codecpar->codec_id == AV_CODEC_ID_EAC3) {
+snprintf(audio_str, codec_str_size, "mp4a.A6");
+} else {
+goto fail;
+}
+}
+
+return codec_str;
+
+fail:
+av_free(codec_str);
+return NULL;
+}
+
 static int create_master_playlist(AVFormatContext *s,
   VariantStream * const input_vs)
 {
@@ -1076,7 +1133,7 @@ static int create_master_playlist(AVFormatContext *s,
 AVDictionary *options = NULL;
 unsigned int i, j;
 int m3u8_name_size, ret, bandwidth;
-char *m3u8_rel_name;
+char *m3u8_rel_name, *codec_str;
 
 input_vs->m3u8_created = 1;
 if (!hls->master_m3u8_created) {
@@ -1203,6 +1260,13 @@ static int create_master_playlist(AVFormatContext *s,
 avio_printf(master_pb, ",RESOLUTION=%dx%d", 
vid_st->codecpar->width,
 vid_st->codecpar->height);
 
+codec_str = get_codec_str(vid_st, aud_st);
+
+if (codec_str) {
+avio_printf(master_pb, ",CODECS=\"%s\"", codec_str);
+av_free(codec_str);
+}
+
 if (vs->agroup && aud_st)
 avio_printf(master_pb, ",AUDIO=\"group_%s\"", vs->agroup);
 
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v4 2/3] avcodec/libx264:setting profile and level in avcodec context

2017-11-24 Thread Karthick J
From: Vishwanath Dixit 

---
 libavcodec/libx264.c | 18 +-
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
index 9c67c91..545826c 100644
--- a/libavcodec/libx264.c
+++ b/libavcodec/libx264.c
@@ -19,11 +19,13 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "libavutil/avassert.h"
 #include "libavutil/eval.h"
 #include "libavutil/internal.h"
 #include "libavutil/opt.h"
 #include "libavutil/mem.h"
 #include "libavutil/pixdesc.h"
+#include "libavutil/reverse.h"
 #include "libavutil/stereo3d.h"
 #include "libavutil/intreadwrite.h"
 #include "avcodec.h"
@@ -454,6 +456,9 @@ static av_cold int X264_init(AVCodecContext *avctx)
 X264Context *x4 = avctx->priv_data;
 AVCPBProperties *cpb_props;
 int sw,sh;
+x264_nal_t *nal;
+uint8_t *p;
+int nnal, s, i;
 
 if (avctx->global_quality > 0)
 av_log(avctx, AV_LOG_WARNING, "-qscale is ignored, -crf is 
recommended.\n");
@@ -799,12 +804,15 @@ FF_ENABLE_DEPRECATION_WARNINGS
 if (!x4->enc)
 return AVERROR_EXTERNAL;
 
-if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
-x264_nal_t *nal;
-uint8_t *p;
-int nnal, s, i;
+s = x264_encoder_headers(x4->enc, &nal, &nnal);
+// Assert for NAL start code and SPS unit type
+av_assert0((nal->p_payload[0] | nal->p_payload[1] | nal->p_payload[2]) == 
0 && nal->p_payload[3] == 1);
+av_assert0((nal->p_payload[4] & 0x1F) == 7);
+// bits 0-7 LSB for profile. bits 8-11 for constrained set flags.
+avctx->profile = ((uint32_t)nal->p_payload[5]) | 
((uint32_t)ff_reverse[nal->p_payload[6]] << 8);
+avctx->level = nal->p_payload[7];
 
-s = x264_encoder_headers(x4->enc, &nal, &nnal);
+if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
 avctx->extradata = p = av_mallocz(s + AV_INPUT_BUFFER_PADDING_SIZE);
 if (!p)
 return AVERROR(ENOMEM);
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v4 3/3] avformat/hlsenc:addition of CODECS attribute in the master playlist

2017-11-24 Thread Karthick J
From: Vishwanath Dixit 

---
 libavformat/hlsenc.c | 67 +++-
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 58d7c58..d48963c 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -39,6 +39,7 @@
 #include "libavutil/avstring.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/random_seed.h"
+#include "libavutil/reverse.h"
 #include "libavutil/opt.h"
 #include "libavutil/log.h"
 #include "libavutil/time_internal.h"
@@ -1066,6 +1067,63 @@ static int get_relative_url(const char *master_url, 
const char *media_url,
 return 0;
 }
 
+static char *get_codec_str(AVStream *vid_st, AVStream *aud_st) {
+size_t codec_str_size = 64;
+char *codec_str = av_malloc(codec_str_size);
+int video_str_len = 0;
+
+if (!codec_str)
+return NULL;
+
+if (!vid_st && !aud_st) {
+goto fail;
+}
+
+if (vid_st) {
+if (vid_st->codecpar->profile != FF_PROFILE_UNKNOWN &&
+vid_st->codecpar->level != FF_LEVEL_UNKNOWN &&
+vid_st->codecpar->codec_id == AV_CODEC_ID_H264) {
+snprintf(codec_str, codec_str_size, "avc1.%02x%02x%02x",
+ vid_st->codecpar->profile & 0xFF,
+ ff_reverse[(vid_st->codecpar->profile >> 8) & 0xFF],
+ vid_st->codecpar->level);
+} else {
+goto fail;
+}
+video_str_len = strlen(codec_str);
+}
+
+if (aud_st) {
+char *audio_str = codec_str;
+if (video_str_len) {
+codec_str[video_str_len] = ',';
+video_str_len += 1;
+audio_str += video_str_len;
+codec_str_size -= video_str_len;
+}
+if (aud_st->codecpar->codec_id == AV_CODEC_ID_MP2) {
+snprintf(audio_str, codec_str_size, "mp4a.40.33");
+} else if (aud_st->codecpar->codec_id == AV_CODEC_ID_MP3) {
+snprintf(audio_str, codec_str_size, "mp4a.40.34");
+} else if (aud_st->codecpar->codec_id == AV_CODEC_ID_AAC) {
+/* TODO : For HE-AAC, HE-AACv2, the last digit needs to be set to 
5 and 29 respectively */
+snprintf(audio_str, codec_str_size, "mp4a.40.2");
+} else if (aud_st->codecpar->codec_id == AV_CODEC_ID_AC3) {
+snprintf(audio_str, codec_str_size, "mp4a.A5");
+} else if (aud_st->codecpar->codec_id == AV_CODEC_ID_EAC3) {
+snprintf(audio_str, codec_str_size, "mp4a.A6");
+} else {
+goto fail;
+}
+}
+
+return codec_str;
+
+fail:
+av_free(codec_str);
+return NULL;
+}
+
 static int create_master_playlist(AVFormatContext *s,
   VariantStream * const input_vs)
 {
@@ -1076,7 +1134,7 @@ static int create_master_playlist(AVFormatContext *s,
 AVDictionary *options = NULL;
 unsigned int i, j;
 int m3u8_name_size, ret, bandwidth;
-char *m3u8_rel_name;
+char *m3u8_rel_name, *codec_str;
 
 input_vs->m3u8_created = 1;
 if (!hls->master_m3u8_created) {
@@ -1203,6 +1261,13 @@ static int create_master_playlist(AVFormatContext *s,
 avio_printf(master_pb, ",RESOLUTION=%dx%d", 
vid_st->codecpar->width,
 vid_st->codecpar->height);
 
+codec_str = get_codec_str(vid_st, aud_st);
+
+if (codec_str) {
+avio_printf(master_pb, ",CODECS=\"%s\"", codec_str);
+av_free(codec_str);
+}
+
 if (vs->agroup && aud_st)
 avio_printf(master_pb, ",AUDIO=\"group_%s\"", vs->agroup);
 
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v5 1/2] avformat/hlsenc: Modularized playlist creation to allow reuse

2017-11-24 Thread Karthick J
---
 libavformat/Makefile  |   2 +-
 libavformat/hlsenc.c  | 115 +++---
 libavformat/hlsplaylist.c | 138 ++
 libavformat/hlsplaylist.h |  51 +
 4 files changed, 211 insertions(+), 95 deletions(-)
 create mode 100644 libavformat/hlsplaylist.c
 create mode 100644 libavformat/hlsplaylist.h

diff --git a/libavformat/Makefile b/libavformat/Makefile
index b1e7b19..fd8b9f9 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -215,7 +215,7 @@ OBJS-$(CONFIG_HDS_MUXER) += hdsenc.o
 OBJS-$(CONFIG_HEVC_DEMUXER)  += hevcdec.o rawdec.o
 OBJS-$(CONFIG_HEVC_MUXER)+= rawenc.o
 OBJS-$(CONFIG_HLS_DEMUXER)   += hls.o
-OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o
+OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o hlsplaylist.o
 OBJS-$(CONFIG_HNM_DEMUXER)   += hnm.o
 OBJS-$(CONFIG_ICO_DEMUXER)   += icodec.o
 OBJS-$(CONFIG_ICO_MUXER) += icoenc.o
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 30ccf73..7c759a8 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -45,6 +45,7 @@
 
 #include "avformat.h"
 #include "avio_internal.h"
+#include "hlsplaylist.h"
 #include "internal.h"
 #include "os_support.h"
 
@@ -96,13 +97,6 @@ typedef enum {
 SEGMENT_TYPE_FMP4,
 } SegmentType;
 
-typedef enum {
-PLAYLIST_TYPE_NONE,
-PLAYLIST_TYPE_EVENT,
-PLAYLIST_TYPE_VOD,
-PLAYLIST_TYPE_NB,
-} PlaylistType;
-
 typedef struct VariantStream {
 unsigned number;
 int64_t sequence;
@@ -1023,19 +1017,6 @@ static void hls_free_segments(HLSSegment *p)
 }
 }
 
-static void write_m3u8_head_block(HLSContext *hls, AVIOContext *out, int 
version,
-  int target_duration, int64_t sequence)
-{
-avio_printf(out, "#EXTM3U\n");
-avio_printf(out, "#EXT-X-VERSION:%d\n", version);
-if (hls->allowcache == 0 || hls->allowcache == 1) {
-avio_printf(out, "#EXT-X-ALLOW-CACHE:%s\n", hls->allowcache == 0 ? 
"NO" : "YES");
-}
-avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration);
-avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
-av_log(hls, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
-}
-
 static void hls_rename_temp_file(AVFormatContext *s, AVFormatContext *oc)
 {
 size_t len = strlen(oc->filename);
@@ -1101,8 +1082,7 @@ static int create_master_playlist(AVFormatContext *s,
 goto fail;
 }
 
-avio_printf(master_pb, "#EXTM3U\n");
-avio_printf(master_pb, "#EXT-X-VERSION:%d\n", hls->version);
+ff_hls_write_playlist_version(master_pb, hls->version);
 
 /* For variant streams with video add #EXT-X-STREAM-INF tag with 
attributes*/
 for (i = 0; i < hls->nb_varstreams; i++) {
@@ -1143,18 +1123,7 @@ static int create_master_playlist(AVFormatContext *s,
 bandwidth += aud_st->codecpar->bit_rate;
 bandwidth += bandwidth / 10;
 
-if (!bandwidth) {
-av_log(NULL, AV_LOG_WARNING,
-"Bandwidth info not available, set audio and video 
bitrates\n");
-av_freep(&m3u8_rel_name);
-continue;
-}
-
-avio_printf(master_pb, "#EXT-X-STREAM-INF:BANDWIDTH=%d", bandwidth);
-if (vid_st && vid_st->codecpar->width > 0 && vid_st->codecpar->height 
> 0)
-avio_printf(master_pb, ",RESOLUTION=%dx%d", 
vid_st->codecpar->width,
-vid_st->codecpar->height);
-avio_printf(master_pb, "\n%s\n\n", m3u8_rel_name);
+ff_hls_write_stream_info(vid_st, master_pb, bandwidth, m3u8_rel_name);
 
 av_freep(&m3u8_rel_name);
 }
@@ -1183,6 +1152,7 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 char *iv_string = NULL;
 AVDictionary *options = NULL;
 double prog_date_time = vs->initial_prog_date_time;
+double *prog_date_time_p = (hls->flags & HLS_PROGRAM_DATE_TIME) ? 
&prog_date_time : NULL;
 int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size 
> 0);
 
 hls->version = 3;
@@ -1213,12 +1183,8 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 }
 
 vs->discontinuity_set = 0;
-write_m3u8_head_block(hls, out, hls->version, target_duration, sequence);
-if (hls->pl_type == PLAYLIST_TYPE_EVENT) {
-avio_printf(out, "#EXT-X-PLAYLIST-TYPE:EVENT\n");
-} else if (hls->pl_type == PLAYLIST_TYPE_VOD) {
-avio_printf(out, "#EXT-X-PLAYLIST-TYPE:VOD\n");
-}
+ff_hls_write_playlist_header(out, hls->version, hls->allowcache,
+ target_duration, sequence, hls->pl_type);
 
 if((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && 
vs->discontinuity_set==0 ){
 avio_printf(out, "#EXT-X-DISCONTINUITY\n");
@@ -1238,74 +1204,35 @@ static int hls_window(AVFormatContext *s, int last, 
VariantS

[FFmpeg-devel] [PATCH] avformat/hlsenc: Fixed initial setting for end_pts

2017-11-26 Thread Karthick J
This patch fixes Bug #6868
Sometimes end_pts is getting initialized to audio stream's
first pts, while the duration is calculated based on video stream's pts.
In this patch the end_pts is initialized with the correct stream's first pts.
---
 libavformat/hlsenc.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 30ccf73..6997a5c 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -1737,6 +1737,7 @@ static int hls_write_header(AVFormatContext *s)
 vs->sequence   = hls->start_sequence;
 hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * 
AV_TIME_BASE;
 vs->start_pts  = AV_NOPTS_VALUE;
+vs->end_pts  = AV_NOPTS_VALUE;
 vs->current_segment_final_filename_fmt[0] = '\0';
 
 if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & 
HLS_INDEPENDENT_SEGMENTS) {
@@ -2111,7 +2112,6 @@ static int hls_write_packet(AVFormatContext *s, AVPacket 
*pkt)
 
 if (vs->start_pts == AV_NOPTS_VALUE) {
 vs->start_pts = pkt->pts;
-vs->end_pts   = pkt->pts;
 }
 
 if (vs->has_video) {
@@ -2123,6 +2123,8 @@ static int hls_write_packet(AVFormatContext *s, AVPacket 
*pkt)
 is_ref_pkt = can_split = 0;
 
 if (is_ref_pkt) {
+if (vs->end_pts == AV_NOPTS_VALUE)
+vs->end_pts = pkt->pts;
 if (vs->new_start) {
 vs->new_start = 0;
 vs->duration = (double)(pkt->pts - vs->end_pts)
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v3 1/3] libavformat/avio: Utility function to return URLContext

2017-11-28 Thread Karthick J
---
 libavformat/avio_internal.h |  8 
 libavformat/aviobuf.c   | 13 +
 2 files changed, 21 insertions(+)

diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h
index c01835d..04c1ad5 100644
--- a/libavformat/avio_internal.h
+++ b/libavformat/avio_internal.h
@@ -133,6 +133,14 @@ int ffio_open_dyn_packet_buf(AVIOContext **s, int 
max_packet_size);
 int ffio_fdopen(AVIOContext **s, URLContext *h);
 
 /**
+ * Return the URLContext associated with the AVIOContext
+ *
+ * @param s IO context
+ * @return pointer to URLContext or NULL.
+ */
+URLContext *ffio_geturlcontext(AVIOContext *s);
+
+/**
  * Open a write-only fake memory stream. The written data is not stored
  * anywhere - this is only used for measuring the amount of data
  * written.
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index 3b4c843..86eb657 100644
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@ -980,6 +980,19 @@ fail:
 return AVERROR(ENOMEM);
 }
 
+URLContext* ffio_geturlcontext(AVIOContext *s)
+{
+AVIOInternal *internal;
+if (!s)
+return NULL;
+
+internal = s->opaque;
+if (internal && s->read_packet == io_read_packet)
+return internal->h;
+else
+return NULL;
+}
+
 int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size)
 {
 uint8_t *buffer;
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v3 2/3] libavformat/http: Handled multiple_requests option during write

2017-11-28 Thread Karthick J
---
 libavformat/http.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/libavformat/http.c b/libavformat/http.c
index 056d5f6..cf86adc 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -171,6 +171,7 @@ static int http_connect(URLContext *h, const char *path, 
const char *local_path,
 const char *hoststr, const char *auth,
 const char *proxyauth, int *new_location);
 static int http_read_header(URLContext *h, int *new_location);
+static int http_shutdown(URLContext *h, int flags);
 
 void ff_http_init_auth_state(URLContext *dest, const URLContext *src)
 {
@@ -306,6 +307,11 @@ int ff_http_do_new_request(URLContext *h, const char *uri)
 AVDictionary *options = NULL;
 int ret;
 
+ret = http_shutdown(h, h->flags);
+if (ret < 0)
+return ret;
+
+s->end_chunked_post = 0;
 s->chunkend  = 0;
 s->off   = 0;
 s->icy_data_read = 0;
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v3 3/3] libavformat/hlsenc: Persistent HTTP connections supported as an option

2017-11-28 Thread Karthick J
---
 doc/muxers.texi  |  3 +++
 libavformat/hlsenc.c | 48 +---
 2 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 9d9ca31..8ec48c2 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -854,6 +854,9 @@ ffmpeg -re -i in.ts -f hls -master_pl_name master.m3u8 \
 This example creates HLS master playlist with name master.m3u8 and keep
 publishing it repeatedly every after 30 segments i.e. every after 60s.
 
+@item http_persistent
+Use persistent HTTP connections. Applicable only for HTTP output.
+
 @end table
 
 @anchor{ico}
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 6997a5c..d5c732f 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -45,6 +45,7 @@
 
 #include "avformat.h"
 #include "avio_internal.h"
+#include "http.h"
 #include "internal.h"
 #include "os_support.h"
 
@@ -205,6 +206,7 @@ typedef struct HLSContext {
 char *var_stream_map; /* user specified variant stream map string */
 char *master_pl_name;
 unsigned int master_publish_rate;
+int http_persistent;
 } HLSContext;
 
 static int get_int_from_double(double val)
@@ -245,10 +247,38 @@ static int mkdir_p(const char *path) {
 return ret;
 }
 
+static int is_http_proto(char *filename) {
+const char *proto = avio_find_protocol_name(filename);
+return proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, 
"https")) : 0;
+}
+
+static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,
+  AVDictionary **options) {
+HLSContext *hls = s->priv_data;
+int http_base_proto = is_http_proto(filename);
+int err;
+if (!*pb || !http_base_proto || !hls->http_persistent) {
+err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options);
+} else {
+URLContext *http_url_context = ffio_geturlcontext(*pb);
+av_assert0(http_url_context);
+err = ff_http_do_new_request(http_url_context, filename);
+}
+return err;
+}
+
+static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char 
*filename) {
+HLSContext *hls = s->priv_data;
+int http_base_proto = is_http_proto(filename);
+
+if (!http_base_proto || !hls->http_persistent || hls->key_info_file || 
hls->encrypt) {
+ff_format_io_close(s, pb);
+}
+}
+
 static void set_http_options(AVFormatContext *s, AVDictionary **options, 
HLSContext *c)
 {
-const char *proto = avio_find_protocol_name(s->filename);
-int http_base_proto = proto ? (!av_strcasecmp(proto, "http") || 
!av_strcasecmp(proto, "https")) : 0;
+int http_base_proto = is_http_proto(s->filename);
 
 if (c->method) {
 av_dict_set(options, "method", c->method, 0);
@@ -258,6 +288,8 @@ static void set_http_options(AVFormatContext *s, 
AVDictionary **options, HLSCont
 }
 if (c->user_agent)
 av_dict_set(options, "user_agent", c->user_agent, 0);
+if (c->http_persistent)
+av_dict_set_int(options, "multiple_requests", 1, 0);
 
 }
 
@@ -1437,17 +1469,17 @@ static int hls_start(AVFormatContext *s, VariantStream 
*vs)
 err = AVERROR(ENOMEM);
 goto fail;
 }
-err = s->io_open(s, &oc->pb, filename, AVIO_FLAG_WRITE, &options);
+err = hlsenc_io_open(s, &oc->pb, filename, &options);
 av_free(filename);
 av_dict_free(&options);
 if (err < 0)
 return err;
 } else
-if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, 
&options)) < 0)
+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 = s->io_open(s, &vtt_oc->pb, vtt_oc->filename, 
AVIO_FLAG_WRITE, &options)) < 0)
+if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->filename, &options)) 
< 0)
 goto fail;
 }
 av_dict_free(&options);
@@ -2165,11 +2197,12 @@ static int hls_write_packet(AVFormatContext *s, 
AVPacket *pkt)
 avio_open_dyn_buf(&oc->pb);
 vs->packets_written = 0;
 ff_format_io_close(s, &vs->out);
+hlsenc_io_close(s, &vs->out, vs->base_output_dirname);
 } else {
-ff_format_io_close(s, &oc->pb);
+hlsenc_io_close(s, &oc->pb, oc->filename);
 }
 if (vs->vtt_avf) {
-ff_format_io_close(s, &vs->vtt_avf->pb);
+hlsenc_io_close(s, &vs->vtt_avf->pb, vs->vtt_avf->filename);
 }
 }
 if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) {
@@ -2355,6 +2388,7 @@ static const AVOption options[] = {
 {"var_stream_map", "Variant stream map string", OFFSET(var_stream_map), 
AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,E},
 {"master_pl_name", "Create HLS master playlist with this name", 
OFFSET(master_pl_name), AV_OPT_TYPE_STRING, {.str = NULL}, 

[FFmpeg-devel] [PATCH v6 1/2] avformat/hlsenc: Modularized playlist creation to allow reuse

2017-11-29 Thread Karthick J
---
 libavformat/Makefile  |   2 +-
 libavformat/hlsenc.c  | 115 +++---
 libavformat/hlsplaylist.c | 138 ++
 libavformat/hlsplaylist.h |  51 +
 4 files changed, 211 insertions(+), 95 deletions(-)
 create mode 100644 libavformat/hlsplaylist.c
 create mode 100644 libavformat/hlsplaylist.h

diff --git a/libavformat/Makefile b/libavformat/Makefile
index b1e7b19..fd8b9f9 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -215,7 +215,7 @@ OBJS-$(CONFIG_HDS_MUXER) += hdsenc.o
 OBJS-$(CONFIG_HEVC_DEMUXER)  += hevcdec.o rawdec.o
 OBJS-$(CONFIG_HEVC_MUXER)+= rawenc.o
 OBJS-$(CONFIG_HLS_DEMUXER)   += hls.o
-OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o
+OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o hlsplaylist.o
 OBJS-$(CONFIG_HNM_DEMUXER)   += hnm.o
 OBJS-$(CONFIG_ICO_DEMUXER)   += icodec.o
 OBJS-$(CONFIG_ICO_MUXER) += icoenc.o
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index d5c732f..f63b08d 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -46,6 +46,7 @@
 #include "avformat.h"
 #include "avio_internal.h"
 #include "http.h"
+#include "hlsplaylist.h"
 #include "internal.h"
 #include "os_support.h"
 
@@ -97,13 +98,6 @@ typedef enum {
 SEGMENT_TYPE_FMP4,
 } SegmentType;
 
-typedef enum {
-PLAYLIST_TYPE_NONE,
-PLAYLIST_TYPE_EVENT,
-PLAYLIST_TYPE_VOD,
-PLAYLIST_TYPE_NB,
-} PlaylistType;
-
 typedef struct VariantStream {
 unsigned number;
 int64_t sequence;
@@ -1055,19 +1049,6 @@ static void hls_free_segments(HLSSegment *p)
 }
 }
 
-static void write_m3u8_head_block(HLSContext *hls, AVIOContext *out, int 
version,
-  int target_duration, int64_t sequence)
-{
-avio_printf(out, "#EXTM3U\n");
-avio_printf(out, "#EXT-X-VERSION:%d\n", version);
-if (hls->allowcache == 0 || hls->allowcache == 1) {
-avio_printf(out, "#EXT-X-ALLOW-CACHE:%s\n", hls->allowcache == 0 ? 
"NO" : "YES");
-}
-avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration);
-avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
-av_log(hls, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
-}
-
 static void hls_rename_temp_file(AVFormatContext *s, AVFormatContext *oc)
 {
 size_t len = strlen(oc->filename);
@@ -1133,8 +1114,7 @@ static int create_master_playlist(AVFormatContext *s,
 goto fail;
 }
 
-avio_printf(master_pb, "#EXTM3U\n");
-avio_printf(master_pb, "#EXT-X-VERSION:%d\n", hls->version);
+ff_hls_write_playlist_version(master_pb, hls->version);
 
 /* For variant streams with video add #EXT-X-STREAM-INF tag with 
attributes*/
 for (i = 0; i < hls->nb_varstreams; i++) {
@@ -1175,18 +1155,7 @@ static int create_master_playlist(AVFormatContext *s,
 bandwidth += aud_st->codecpar->bit_rate;
 bandwidth += bandwidth / 10;
 
-if (!bandwidth) {
-av_log(NULL, AV_LOG_WARNING,
-"Bandwidth info not available, set audio and video 
bitrates\n");
-av_freep(&m3u8_rel_name);
-continue;
-}
-
-avio_printf(master_pb, "#EXT-X-STREAM-INF:BANDWIDTH=%d", bandwidth);
-if (vid_st && vid_st->codecpar->width > 0 && vid_st->codecpar->height 
> 0)
-avio_printf(master_pb, ",RESOLUTION=%dx%d", 
vid_st->codecpar->width,
-vid_st->codecpar->height);
-avio_printf(master_pb, "\n%s\n\n", m3u8_rel_name);
+ff_hls_write_stream_info(vid_st, master_pb, bandwidth, m3u8_rel_name);
 
 av_freep(&m3u8_rel_name);
 }
@@ -1215,6 +1184,7 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 char *iv_string = NULL;
 AVDictionary *options = NULL;
 double prog_date_time = vs->initial_prog_date_time;
+double *prog_date_time_p = (hls->flags & HLS_PROGRAM_DATE_TIME) ? 
&prog_date_time : NULL;
 int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size 
> 0);
 
 hls->version = 3;
@@ -1245,12 +1215,8 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 }
 
 vs->discontinuity_set = 0;
-write_m3u8_head_block(hls, out, hls->version, target_duration, sequence);
-if (hls->pl_type == PLAYLIST_TYPE_EVENT) {
-avio_printf(out, "#EXT-X-PLAYLIST-TYPE:EVENT\n");
-} else if (hls->pl_type == PLAYLIST_TYPE_VOD) {
-avio_printf(out, "#EXT-X-PLAYLIST-TYPE:VOD\n");
-}
+ff_hls_write_playlist_header(out, hls->version, hls->allowcache,
+ target_duration, sequence, hls->pl_type);
 
 if((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && 
vs->discontinuity_set==0 ){
 avio_printf(out, "#EXT-X-DISCONTINUITY\n");
@@ -1270,74 +1236,35 @@ static int hls_window(AVFormatContext *s, in

[FFmpeg-devel] [PATCH v6 2/2] avformat/dashenc: Option to generate hls playlist as well

2017-11-29 Thread Karthick J
This is to take full advantage of Common Media Application Format.
Now server can generate one content and serve both HLS and DASH players.
---
 doc/muxers.texi   |   3 ++
 libavformat/Makefile  |   2 +-
 libavformat/dashenc.c | 103 --
 3 files changed, 103 insertions(+), 5 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 8ec48c2..3d0c7bf 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -249,6 +249,9 @@ DASH-templated name to used for the media segments. Default 
is "chunk-stream$Rep
 URL of the page that will return the UTC timestamp in ISO format. Example: 
"https://time.akamai.com/?iso";
 @item -http_user_agent @var{user_agent}
 Override User-Agent field in HTTP header. Applicable only for HTTP output.
+@item -hls_playlist @var{hls_playlist}
+Generate HLS playlist files as well. The master playlist is generated with the 
filename master.m3u8.
+One media playlist file is generated for each stream with filenames 
media_0.m3u8, media_1.m3u8, etc.
 @item -adaptation_sets @var{adaptation_sets}
 Assign streams to AdaptationSets. Syntax is "id=x,streams=a,b,c 
id=y,streams=d,e" with x and y being the IDs
 of the adaptation sets and a,b,c,d and e are the indices of the mapped streams.
diff --git a/libavformat/Makefile b/libavformat/Makefile
index fd8b9f9..4bffdf2 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -135,7 +135,7 @@ OBJS-$(CONFIG_CONCAT_DEMUXER)+= concatdec.o
 OBJS-$(CONFIG_CRC_MUXER) += crcenc.o
 OBJS-$(CONFIG_DATA_DEMUXER)  += rawdec.o
 OBJS-$(CONFIG_DATA_MUXER)+= rawenc.o
-OBJS-$(CONFIG_DASH_MUXER)+= dash.o dashenc.o
+OBJS-$(CONFIG_DASH_MUXER)+= dash.o dashenc.o hlsplaylist.o
 OBJS-$(CONFIG_DASH_DEMUXER)  += dash.o dashdec.o
 OBJS-$(CONFIG_DAUD_DEMUXER)  += dauddec.o
 OBJS-$(CONFIG_DAUD_MUXER)+= daudenc.o
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 0fee3cd..ee9dc85 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -36,6 +36,7 @@
 #include "avc.h"
 #include "avformat.h"
 #include "avio_internal.h"
+#include "hlsplaylist.h"
 #include "internal.h"
 #include "isom.h"
 #include "os_support.h"
@@ -101,6 +102,8 @@ typedef struct DASHContext {
 const char *media_seg_name;
 const char *utc_timing_url;
 const char *user_agent;
+int hls_playlist;
+int master_playlist_created;
 } DASHContext;
 
 static struct codec_string {
@@ -217,6 +220,14 @@ static void set_http_options(AVDictionary **options, 
DASHContext *c)
 av_dict_set(options, "user_agent", c->user_agent, 0);
 }
 
+static void get_hls_playlist_name(char *playlist_name, int string_size,
+  const char *base_url, int id) {
+if (base_url)
+snprintf(playlist_name, string_size, "%smedia_%d.m3u8", base_url, id);
+else
+snprintf(playlist_name, string_size, "media_%d.m3u8", id);
+}
+
 static int flush_init_segment(AVFormatContext *s, OutputStream *os)
 {
 DASHContext *c = s->priv_data;
@@ -262,7 +273,8 @@ static void dash_free(AVFormatContext *s)
 av_freep(&c->streams);
 }
 
-static void output_segment_list(OutputStream *os, AVIOContext *out, 
DASHContext *c)
+static void output_segment_list(OutputStream *os, AVIOContext *out, 
DASHContext *c,
+int representation_id, int final)
 {
 int i, start_index = 0, start_number = 1;
 if (c->window_size) {
@@ -322,6 +334,55 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, DASHContext
 }
 avio_printf(out, "\t\t\t\t\n");
 }
+if (c->hls_playlist && start_index < os->nb_segments)
+{
+int timescale = os->ctx->streams[0]->time_base.den;
+char temp_filename_hls[1024];
+char filename_hls[1024];
+AVIOContext *out_hls = NULL;
+AVDictionary *http_opts = NULL;
+int target_duration = 0;
+const char *proto = avio_find_protocol_name(c->dirname);
+int use_rename = proto && !strcmp(proto, "file");
+
+get_hls_playlist_name(filename_hls, sizeof(filename_hls),
+  c->dirname, representation_id);
+
+snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? 
"%s.tmp" : "%s", filename_hls);
+
+set_http_options(&http_opts, c);
+avio_open2(&out_hls, temp_filename_hls, AVIO_FLAG_WRITE, NULL, 
&http_opts);
+av_dict_free(&http_opts);
+for (i = start_index; i < os->nb_segments; i++) {
+Segment *seg = os->segments[i];
+if (target_duration < seg->duration)
+target_duration = seg->duration;
+}
+target_duration = lrint((double) target_duration / timescale);
+
+ff_hls_write_playlist_header(out_hls, 6, -1, target_duration,
+ start_number, PLAYLIST_TYPE_NONE);
+
+ff_hls_wri

[FFmpeg-devel] [PATCH 2/2] avformat/dashenc: Option to generate hls playlist as well

2017-11-29 Thread Karthick J
This is to take full advantage of Common Media Application Format.
Now server can generate one content and serve both HLS and DASH players.
---
 doc/muxers.texi   |   3 ++
 libavformat/Makefile  |   2 +-
 libavformat/dashenc.c | 103 --
 3 files changed, 103 insertions(+), 5 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 8ec48c2..3d0c7bf 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -249,6 +249,9 @@ DASH-templated name to used for the media segments. Default 
is "chunk-stream$Rep
 URL of the page that will return the UTC timestamp in ISO format. Example: 
"https://time.akamai.com/?iso";
 @item -http_user_agent @var{user_agent}
 Override User-Agent field in HTTP header. Applicable only for HTTP output.
+@item -hls_playlist @var{hls_playlist}
+Generate HLS playlist files as well. The master playlist is generated with the 
filename master.m3u8.
+One media playlist file is generated for each stream with filenames 
media_0.m3u8, media_1.m3u8, etc.
 @item -adaptation_sets @var{adaptation_sets}
 Assign streams to AdaptationSets. Syntax is "id=x,streams=a,b,c 
id=y,streams=d,e" with x and y being the IDs
 of the adaptation sets and a,b,c,d and e are the indices of the mapped streams.
diff --git a/libavformat/Makefile b/libavformat/Makefile
index fd8b9f9..4bffdf2 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -135,7 +135,7 @@ OBJS-$(CONFIG_CONCAT_DEMUXER)+= concatdec.o
 OBJS-$(CONFIG_CRC_MUXER) += crcenc.o
 OBJS-$(CONFIG_DATA_DEMUXER)  += rawdec.o
 OBJS-$(CONFIG_DATA_MUXER)+= rawenc.o
-OBJS-$(CONFIG_DASH_MUXER)+= dash.o dashenc.o
+OBJS-$(CONFIG_DASH_MUXER)+= dash.o dashenc.o hlsplaylist.o
 OBJS-$(CONFIG_DASH_DEMUXER)  += dash.o dashdec.o
 OBJS-$(CONFIG_DAUD_DEMUXER)  += dauddec.o
 OBJS-$(CONFIG_DAUD_MUXER)+= daudenc.o
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 0fee3cd..efc2012 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -36,6 +36,7 @@
 #include "avc.h"
 #include "avformat.h"
 #include "avio_internal.h"
+#include "hlsplaylist.h"
 #include "internal.h"
 #include "isom.h"
 #include "os_support.h"
@@ -101,6 +102,8 @@ typedef struct DASHContext {
 const char *media_seg_name;
 const char *utc_timing_url;
 const char *user_agent;
+int hls_playlist;
+int master_playlist_created;
 } DASHContext;
 
 static struct codec_string {
@@ -217,6 +220,14 @@ static void set_http_options(AVDictionary **options, 
DASHContext *c)
 av_dict_set(options, "user_agent", c->user_agent, 0);
 }
 
+static void get_hls_playlist_name(char *playlist_name, int string_size,
+  const char *base_url, int id) {
+if (base_url)
+snprintf(playlist_name, string_size, "%smedia_%d.m3u8", base_url, id);
+else
+snprintf(playlist_name, string_size, "media_%d.m3u8", id);
+}
+
 static int flush_init_segment(AVFormatContext *s, OutputStream *os)
 {
 DASHContext *c = s->priv_data;
@@ -262,7 +273,8 @@ static void dash_free(AVFormatContext *s)
 av_freep(&c->streams);
 }
 
-static void output_segment_list(OutputStream *os, AVIOContext *out, 
DASHContext *c)
+static void output_segment_list(OutputStream *os, AVIOContext *out, 
DASHContext *c,
+int representation_id, int final)
 {
 int i, start_index = 0, start_number = 1;
 if (c->window_size) {
@@ -322,6 +334,55 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, DASHContext
 }
 avio_printf(out, "\t\t\t\t\n");
 }
+if (c->hls_playlist && start_index < os->nb_segments)
+{
+int timescale = os->ctx->streams[0]->time_base.den;
+char temp_filename_hls[1024];
+char filename_hls[1024];
+AVIOContext *out_hls = NULL;
+AVDictionary *http_opts = NULL;
+int target_duration = 0;
+const char *proto = avio_find_protocol_name(c->dirname);
+int use_rename = proto && !strcmp(proto, "file");
+
+get_hls_playlist_name(filename_hls, sizeof(filename_hls),
+  c->dirname, representation_id);
+
+snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? 
"%s.tmp" : "%s", filename_hls);
+
+set_http_options(&http_opts, c);
+avio_open2(&out_hls, temp_filename_hls, AVIO_FLAG_WRITE, NULL, 
&http_opts);
+av_dict_free(&http_opts);
+for (i = start_index; i < os->nb_segments; i++) {
+Segment *seg = os->segments[i];
+double duration = (double) seg->duration / timescale;
+if (target_duration <= duration)
+target_duration = hls_get_int_from_double(duration);
+}
+
+ff_hls_write_playlist_header(out_hls, 6, -1, target_duration,
+ start_number, PLAYLIST_TYPE_NONE);
+
+   

[FFmpeg-devel] [PATCH 1/2] avformat/hlsenc: Refactored 'get_int_from_double' function to allow reuse

2017-11-29 Thread Karthick J
From: Karthick Jeyapal 

---
 libavformat/hlsenc.c  | 7 +--
 libavformat/hlsplaylist.h | 5 +
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index f63b08d..cdfbf45 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -203,11 +203,6 @@ typedef struct HLSContext {
 int http_persistent;
 } HLSContext;
 
-static int get_int_from_double(double val)
-{
-return (int)((val - (int)val) >= 0.001) ? (int)(val + 1) : (int)val;
-}
-
 static int mkdir_p(const char *path) {
 int ret = 0;
 char *temp = av_strdup(path);
@@ -1211,7 +1206,7 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 
 for (en = vs->segments; en; en = en->next) {
 if (target_duration <= en->duration)
-target_duration = get_int_from_double(en->duration);
+target_duration = hls_get_int_from_double(en->duration);
 }
 
 vs->discontinuity_set = 0;
diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h
index fd36c7e..68ef8d4 100644
--- a/libavformat/hlsplaylist.h
+++ b/libavformat/hlsplaylist.h
@@ -32,6 +32,11 @@ typedef enum {
 PLAYLIST_TYPE_NB,
 } PlaylistType;
 
+static inline int hls_get_int_from_double(double val)
+{
+return (int)((val - (int)val) >= 0.001) ? (int)(val + 1) : (int)val;
+}
+
 void ff_hls_write_playlist_version(AVIOContext *out, int version);
 void ff_hls_write_stream_info(AVStream *st, AVIOContext *out,
   int bandwidth, char *filename);
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 1/2] avformat/hlsenc: Refactored 'get_int_from_double' function to allow reuse

2017-11-29 Thread Karthick J
From: Karthick Jeyapal 

---
 libavformat/hlsenc.c  | 7 +--
 libavformat/hlsplaylist.h | 5 +
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index f63b08d..cdfbf45 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -203,11 +203,6 @@ typedef struct HLSContext {
 int http_persistent;
 } HLSContext;
 
-static int get_int_from_double(double val)
-{
-return (int)((val - (int)val) >= 0.001) ? (int)(val + 1) : (int)val;
-}
-
 static int mkdir_p(const char *path) {
 int ret = 0;
 char *temp = av_strdup(path);
@@ -1211,7 +1206,7 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 
 for (en = vs->segments; en; en = en->next) {
 if (target_duration <= en->duration)
-target_duration = get_int_from_double(en->duration);
+target_duration = hls_get_int_from_double(en->duration);
 }
 
 vs->discontinuity_set = 0;
diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h
index fd36c7e..68ef8d4 100644
--- a/libavformat/hlsplaylist.h
+++ b/libavformat/hlsplaylist.h
@@ -32,6 +32,11 @@ typedef enum {
 PLAYLIST_TYPE_NB,
 } PlaylistType;
 
+static inline int hls_get_int_from_double(double val)
+{
+return (int)((val - (int)val) >= 0.001) ? (int)(val + 1) : (int)val;
+}
+
 void ff_hls_write_playlist_version(AVIOContext *out, int version);
 void ff_hls_write_stream_info(AVStream *st, AVIOContext *out,
   int bandwidth, char *filename);
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 2/2] avformat/dashenc: Option to generate hls playlist as well

2017-11-29 Thread Karthick J
This is to take full advantage of Common Media Application Format.
Now server can generate one content and serve both HLS and DASH players.
---
 doc/muxers.texi   |   3 ++
 libavformat/Makefile  |   2 +-
 libavformat/dashenc.c | 110 +++---
 3 files changed, 108 insertions(+), 7 deletions(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 8ec48c2..3d0c7bf 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -249,6 +249,9 @@ DASH-templated name to used for the media segments. Default 
is "chunk-stream$Rep
 URL of the page that will return the UTC timestamp in ISO format. Example: 
"https://time.akamai.com/?iso";
 @item -http_user_agent @var{user_agent}
 Override User-Agent field in HTTP header. Applicable only for HTTP output.
+@item -hls_playlist @var{hls_playlist}
+Generate HLS playlist files as well. The master playlist is generated with the 
filename master.m3u8.
+One media playlist file is generated for each stream with filenames 
media_0.m3u8, media_1.m3u8, etc.
 @item -adaptation_sets @var{adaptation_sets}
 Assign streams to AdaptationSets. Syntax is "id=x,streams=a,b,c 
id=y,streams=d,e" with x and y being the IDs
 of the adaptation sets and a,b,c,d and e are the indices of the mapped streams.
diff --git a/libavformat/Makefile b/libavformat/Makefile
index fd8b9f9..4bffdf2 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -135,7 +135,7 @@ OBJS-$(CONFIG_CONCAT_DEMUXER)+= concatdec.o
 OBJS-$(CONFIG_CRC_MUXER) += crcenc.o
 OBJS-$(CONFIG_DATA_DEMUXER)  += rawdec.o
 OBJS-$(CONFIG_DATA_MUXER)+= rawenc.o
-OBJS-$(CONFIG_DASH_MUXER)+= dash.o dashenc.o
+OBJS-$(CONFIG_DASH_MUXER)+= dash.o dashenc.o hlsplaylist.o
 OBJS-$(CONFIG_DASH_DEMUXER)  += dash.o dashdec.o
 OBJS-$(CONFIG_DAUD_DEMUXER)  += dauddec.o
 OBJS-$(CONFIG_DAUD_MUXER)+= daudenc.o
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 0fee3cd..1783675 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -36,6 +36,7 @@
 #include "avc.h"
 #include "avformat.h"
 #include "avio_internal.h"
+#include "hlsplaylist.h"
 #include "internal.h"
 #include "isom.h"
 #include "os_support.h"
@@ -101,6 +102,8 @@ typedef struct DASHContext {
 const char *media_seg_name;
 const char *utc_timing_url;
 const char *user_agent;
+int hls_playlist;
+int master_playlist_created;
 } DASHContext;
 
 static struct codec_string {
@@ -217,6 +220,14 @@ static void set_http_options(AVDictionary **options, 
DASHContext *c)
 av_dict_set(options, "user_agent", c->user_agent, 0);
 }
 
+static void get_hls_playlist_name(char *playlist_name, int string_size,
+  const char *base_url, int id) {
+if (base_url)
+snprintf(playlist_name, string_size, "%smedia_%d.m3u8", base_url, id);
+else
+snprintf(playlist_name, string_size, "media_%d.m3u8", id);
+}
+
 static int flush_init_segment(AVFormatContext *s, OutputStream *os)
 {
 DASHContext *c = s->priv_data;
@@ -262,7 +273,8 @@ static void dash_free(AVFormatContext *s)
 av_freep(&c->streams);
 }
 
-static void output_segment_list(OutputStream *os, AVIOContext *out, 
DASHContext *c)
+static void output_segment_list(OutputStream *os, AVIOContext *out, 
DASHContext *c,
+int representation_id, int final)
 {
 int i, start_index = 0, start_number = 1;
 if (c->window_size) {
@@ -322,6 +334,55 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, DASHContext
 }
 avio_printf(out, "\t\t\t\t\n");
 }
+if (c->hls_playlist && start_index < os->nb_segments)
+{
+int timescale = os->ctx->streams[0]->time_base.den;
+char temp_filename_hls[1024];
+char filename_hls[1024];
+AVIOContext *out_hls = NULL;
+AVDictionary *http_opts = NULL;
+int target_duration = 0;
+const char *proto = avio_find_protocol_name(c->dirname);
+int use_rename = proto && !strcmp(proto, "file");
+
+get_hls_playlist_name(filename_hls, sizeof(filename_hls),
+  c->dirname, representation_id);
+
+snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? 
"%s.tmp" : "%s", filename_hls);
+
+set_http_options(&http_opts, c);
+avio_open2(&out_hls, temp_filename_hls, AVIO_FLAG_WRITE, NULL, 
&http_opts);
+av_dict_free(&http_opts);
+for (i = start_index; i < os->nb_segments; i++) {
+Segment *seg = os->segments[i];
+double duration = (double) seg->duration / timescale;
+if (target_duration <= duration)
+target_duration = hls_get_int_from_double(duration);
+}
+
+ff_hls_write_playlist_header(out_hls, 6, -1, target_duration,
+ start_number, PLAYLIST_TYPE_NONE);
+
+   

[FFmpeg-devel] [PATCH 2/3] avformat/hlsenc: Handle NULL input in IO open and close utility functions

2017-11-30 Thread Karthick J
From: Karthick Jeyapal 

---
 libavformat/hlsenc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 9048cb2..ff982c5 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -244,7 +244,7 @@ static int is_http_proto(char *filename) {
 static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,
   AVDictionary **options) {
 HLSContext *hls = s->priv_data;
-int http_base_proto = is_http_proto(filename);
+int http_base_proto = filename ? is_http_proto(filename) : 0;
 int err;
 if (!*pb || !http_base_proto || !hls->http_persistent) {
 err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options);
@@ -258,7 +258,7 @@ static int hlsenc_io_open(AVFormatContext *s, AVIOContext 
**pb, char *filename,
 
 static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char 
*filename) {
 HLSContext *hls = s->priv_data;
-int http_base_proto = is_http_proto(filename);
+int http_base_proto = filename ? is_http_proto(filename) : 0;
 
 if (!http_base_proto || !hls->http_persistent || hls->key_info_file || 
hls->encrypt) {
 ff_format_io_close(s, pb);
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 1/3] avformat/hlsenc: Call avio_flush during persistent http connections

2017-11-30 Thread Karthick J
From: Karthick Jeyapal 

Since close is not called, during http persistent connection,
flush needs to be called so that output is written on time.
---
 libavformat/hlsenc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index cdfbf45..9048cb2 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -262,6 +262,8 @@ static void hlsenc_io_close(AVFormatContext *s, AVIOContext 
**pb, char *filename
 
 if (!http_base_proto || !hls->http_persistent || hls->key_info_file || 
hls->encrypt) {
 ff_format_io_close(s, pb);
+} else {
+avio_flush(*pb);
 }
 }
 
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 3/3] avformat/hlsenc: Extend persistent http connections to playlists

2017-11-30 Thread Karthick J
From: Karthick Jeyapal 

Before this patch persistent http connections would work only for media 
segments.
The playlists were still opening a new connection everytime.
This patch extends persistent http connections to playlists as well.
---
 libavformat/hlsenc.c | 46 ++
 1 file changed, 22 insertions(+), 24 deletions(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index ff982c5..350836d 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -201,6 +201,8 @@ typedef struct HLSContext {
 char *master_pl_name;
 unsigned int master_publish_rate;
 int http_persistent;
+AVIOContext *m3u8_out;
+AVIOContext *sub_m3u8_out;
 } HLSContext;
 
 static int mkdir_p(const char *path) {
@@ -1081,7 +1083,6 @@ static int create_master_playlist(AVFormatContext *s,
 HLSContext *hls = s->priv_data;
 VariantStream *vs;
 AVStream *vid_st, *aud_st;
-AVIOContext *master_pb = 0;
 AVDictionary *options = NULL;
 unsigned int i, j;
 int m3u8_name_size, ret, bandwidth;
@@ -1102,8 +1103,7 @@ static int create_master_playlist(AVFormatContext *s,
 
 set_http_options(s, &options, hls);
 
-ret = s->io_open(s, &master_pb, hls->master_m3u8_url, AVIO_FLAG_WRITE,\
- &options);
+ret = hlsenc_io_open(s, &hls->m3u8_out, hls->master_m3u8_url, &options);
 av_dict_free(&options);
 if (ret < 0) {
 av_log(NULL, AV_LOG_ERROR, "Failed to open master play list file 
'%s'\n",
@@ -,7 +,7 @@ static int create_master_playlist(AVFormatContext *s,
 goto fail;
 }
 
-ff_hls_write_playlist_version(master_pb, hls->version);
+ff_hls_write_playlist_version(hls->m3u8_out, hls->version);
 
 /* For variant streams with video add #EXT-X-STREAM-INF tag with 
attributes*/
 for (i = 0; i < hls->nb_varstreams; i++) {
@@ -1152,7 +1152,7 @@ static int create_master_playlist(AVFormatContext *s,
 bandwidth += aud_st->codecpar->bit_rate;
 bandwidth += bandwidth / 10;
 
-ff_hls_write_stream_info(vid_st, master_pb, bandwidth, m3u8_rel_name);
+ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, 
m3u8_rel_name);
 
 av_freep(&m3u8_rel_name);
 }
@@ -1160,7 +1160,7 @@ fail:
 if(ret >=0)
 hls->master_m3u8_created = 1;
 av_freep(&m3u8_rel_name);
-ff_format_io_close(s, &master_pb);
+hlsenc_io_close(s, &hls->m3u8_out, hls->master_m3u8_url);
 return ret;
 }
 
@@ -1170,8 +1170,6 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 HLSSegment *en;
 int target_duration = 0;
 int ret = 0;
-AVIOContext *out = NULL;
-AVIOContext *sub_out = NULL;
 char temp_filename[1024];
 int64_t sequence = FFMAX(hls->start_sequence, vs->sequence - 
vs->nb_entries);
 const char *proto = avio_find_protocol_name(s->filename);
@@ -1203,7 +1201,7 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 
 set_http_options(s, &options, hls);
 snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : 
"%s", vs->m3u8_name);
-if ((ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, &options)) 
< 0)
+if ((ret = hlsenc_io_open(s, &hls->m3u8_out, temp_filename, &options)) < 0)
 goto fail;
 
 for (en = vs->segments; en; en = en->next) {
@@ -1212,33 +1210,33 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 }
 
 vs->discontinuity_set = 0;
-ff_hls_write_playlist_header(out, hls->version, hls->allowcache,
+ff_hls_write_playlist_header(hls->m3u8_out, hls->version, hls->allowcache,
  target_duration, sequence, hls->pl_type);
 
 if((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && 
vs->discontinuity_set==0 ){
-avio_printf(out, "#EXT-X-DISCONTINUITY\n");
+avio_printf(hls->m3u8_out, "#EXT-X-DISCONTINUITY\n");
 vs->discontinuity_set = 1;
 }
 if (vs->has_video && (hls->flags & HLS_INDEPENDENT_SEGMENTS)) {
-avio_printf(out, "#EXT-X-INDEPENDENT-SEGMENTS\n");
+avio_printf(hls->m3u8_out, "#EXT-X-INDEPENDENT-SEGMENTS\n");
 }
 for (en = vs->segments; en; en = en->next) {
 if ((hls->encrypt || hls->key_info_file) && (!key_uri || 
strcmp(en->key_uri, key_uri) ||
 av_strcasecmp(en->iv_string, iv_string))) {
-avio_printf(out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", 
en->key_uri);
+avio_printf(hls->m3u8_out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", 
en->key_uri);
 if (*en->iv_string)
-avio_printf(out, ",IV=0x%s", en->iv_string);
-avio_printf(out, "\n");
+avio_printf(hls->m3u8_out, ",IV=0x%s", en->iv_string);
+avio_printf(hls->m3u8_out, "\n");
 key_uri = en->key_uri;
 iv_string = en->iv_string;
 }
 
 if ((hls->segment_type == SEGME

[FFmpeg-devel] [PATCH v2 1/3] avformat/hlsenc: Call avio_flush during persistent http connections

2017-12-14 Thread Karthick J
From: Karthick Jeyapal 

Since close is not called, during http persistent connection,
flush needs to be called so that output is written on time.
---
 libavformat/hlsenc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index fdf614b..30d0285 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -266,6 +266,8 @@ static void hlsenc_io_close(AVFormatContext *s, AVIOContext 
**pb, char *filename
 
 if (!http_base_proto || !hls->http_persistent || hls->key_info_file || 
hls->encrypt) {
 ff_format_io_close(s, pb);
+} else {
+avio_flush(*pb);
 }
 }
 
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 2/3] avformat/hlsenc: Handle NULL input in IO open and close utility functions

2017-12-14 Thread Karthick J
From: Karthick Jeyapal 

---
 libavformat/hlsenc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 30d0285..af9d949 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -246,7 +246,7 @@ static int is_http_proto(char *filename) {
 static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,
   AVDictionary **options) {
 HLSContext *hls = s->priv_data;
-int http_base_proto = is_http_proto(filename);
+int http_base_proto = filename ? is_http_proto(filename) : 0;
 int err = AVERROR_MUXER_NOT_FOUND;
 if (!*pb || !http_base_proto || !hls->http_persistent) {
 err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options);
@@ -262,7 +262,7 @@ static int hlsenc_io_open(AVFormatContext *s, AVIOContext 
**pb, char *filename,
 
 static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char 
*filename) {
 HLSContext *hls = s->priv_data;
-int http_base_proto = is_http_proto(filename);
+int http_base_proto = filename ? is_http_proto(filename) : 0;
 
 if (!http_base_proto || !hls->http_persistent || hls->key_info_file || 
hls->encrypt) {
 ff_format_io_close(s, pb);
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 3/3] avformat/hlsenc: Extend persistent http connections to playlists

2017-12-14 Thread Karthick J
From: Karthick Jeyapal 

Before this patch persistent http connections would work only for media 
segments.
The playlists were still opening a new connection everytime.
This patch extends persistent http connections to playlists as well.
---
 libavformat/hlsenc.c | 56 +---
 1 file changed, 27 insertions(+), 29 deletions(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index af9d949..e3442c3 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -203,6 +203,8 @@ typedef struct HLSContext {
 char *master_pl_name;
 unsigned int master_publish_rate;
 int http_persistent;
+AVIOContext *m3u8_out;
+AVIOContext *sub_m3u8_out;
 } HLSContext;
 
 static int mkdir_p(const char *path) {
@@ -1085,7 +1087,6 @@ static int create_master_playlist(AVFormatContext *s,
 HLSContext *hls = s->priv_data;
 VariantStream *vs;
 AVStream *vid_st, *aud_st;
-AVIOContext *master_pb = 0;
 AVDictionary *options = NULL;
 unsigned int i, j;
 int m3u8_name_size, ret, bandwidth;
@@ -1106,8 +1107,7 @@ static int create_master_playlist(AVFormatContext *s,
 
 set_http_options(s, &options, hls);
 
-ret = s->io_open(s, &master_pb, hls->master_m3u8_url, AVIO_FLAG_WRITE,\
- &options);
+ret = hlsenc_io_open(s, &hls->m3u8_out, hls->master_m3u8_url, &options);
 av_dict_free(&options);
 if (ret < 0) {
 av_log(NULL, AV_LOG_ERROR, "Failed to open master play list file 
'%s'\n",
@@ -1115,7 +1115,7 @@ static int create_master_playlist(AVFormatContext *s,
 goto fail;
 }
 
-ff_hls_write_playlist_version(master_pb, hls->version);
+ff_hls_write_playlist_version(hls->m3u8_out, hls->version);
 
 /* For variant streams with video add #EXT-X-STREAM-INF tag with 
attributes*/
 for (i = 0; i < hls->nb_varstreams; i++) {
@@ -1156,7 +1156,7 @@ static int create_master_playlist(AVFormatContext *s,
 bandwidth += aud_st->codecpar->bit_rate;
 bandwidth += bandwidth / 10;
 
-ff_hls_write_stream_info(vid_st, master_pb, bandwidth, m3u8_rel_name);
+ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, 
m3u8_rel_name);
 
 av_freep(&m3u8_rel_name);
 }
@@ -1164,7 +1164,7 @@ fail:
 if(ret >=0)
 hls->master_m3u8_created = 1;
 av_freep(&m3u8_rel_name);
-ff_format_io_close(s, &master_pb);
+hlsenc_io_close(s, &hls->m3u8_out, hls->master_m3u8_url);
 return ret;
 }
 
@@ -1174,8 +1174,6 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 HLSSegment *en;
 int target_duration = 0;
 int ret = 0;
-AVIOContext *out = NULL;
-AVIOContext *sub_out = NULL;
 char temp_filename[1024];
 int64_t sequence = FFMAX(hls->start_sequence, vs->sequence - 
vs->nb_entries);
 const char *proto = avio_find_protocol_name(s->filename);
@@ -1207,7 +1205,7 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 
 set_http_options(s, &options, hls);
 snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : 
"%s", vs->m3u8_name);
-if ((ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, &options)) 
< 0)
+if ((ret = hlsenc_io_open(s, &hls->m3u8_out, temp_filename, &options)) < 0)
 goto fail;
 
 for (en = vs->segments; en; en = en->next) {
@@ -1216,67 +1214,67 @@ static int hls_window(AVFormatContext *s, int last, 
VariantStream *vs)
 }
 
 vs->discontinuity_set = 0;
-ff_hls_write_playlist_header(out, hls->version, hls->allowcache,
+ff_hls_write_playlist_header(hls->m3u8_out, hls->version, hls->allowcache,
  target_duration, sequence, hls->pl_type);
 
 if((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && 
vs->discontinuity_set==0 ){
-avio_printf(out, "#EXT-X-DISCONTINUITY\n");
+avio_printf(hls->m3u8_out, "#EXT-X-DISCONTINUITY\n");
 vs->discontinuity_set = 1;
 }
 if (vs->has_video && (hls->flags & HLS_INDEPENDENT_SEGMENTS)) {
-avio_printf(out, "#EXT-X-INDEPENDENT-SEGMENTS\n");
+avio_printf(hls->m3u8_out, "#EXT-X-INDEPENDENT-SEGMENTS\n");
 }
 for (en = vs->segments; en; en = en->next) {
 if ((hls->encrypt || hls->key_info_file) && (!key_uri || 
strcmp(en->key_uri, key_uri) ||
 av_strcasecmp(en->iv_string, iv_string))) {
-avio_printf(out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", 
en->key_uri);
+avio_printf(hls->m3u8_out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", 
en->key_uri);
 if (*en->iv_string)
-avio_printf(out, ",IV=0x%s", en->iv_string);
-avio_printf(out, "\n");
+avio_printf(hls->m3u8_out, ",IV=0x%s", en->iv_string);
+avio_printf(hls->m3u8_out, "\n");
 key_uri = en->key_uri;
 iv_string = en->iv_string;
 }
 
 if ((hls->segment_type ==

[FFmpeg-devel] [PATCH] avformat/hlsenc: Minor fix for persistent http connection of init fmp4

2017-12-15 Thread Karthick J
From: Karthick Jeyapal 

---
 libavformat/hlsenc.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index fdf614b..0e2f412 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -1787,7 +1787,6 @@ static int hls_write_packet(AVFormatContext *s, AVPacket 
*pkt)
 vs->init_range_length = range_length;
 avio_open_dyn_buf(&oc->pb);
 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);
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 1/2] avformat/hlsenc, utils: Moved is_http_proto from hlsenc to utils for re-use

2017-12-15 Thread Karthick J
From: Karthick Jeyapal 

---
 libavformat/hlsenc.c   | 12 +++-
 libavformat/internal.h |  8 
 libavformat/utils.c|  5 +
 3 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index e3442c3..03d54c7 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -240,15 +240,10 @@ static int mkdir_p(const char *path) {
 return ret;
 }
 
-static int is_http_proto(char *filename) {
-const char *proto = avio_find_protocol_name(filename);
-return proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, 
"https")) : 0;
-}
-
 static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,
   AVDictionary **options) {
 HLSContext *hls = s->priv_data;
-int http_base_proto = filename ? is_http_proto(filename) : 0;
+int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
 int err = AVERROR_MUXER_NOT_FOUND;
 if (!*pb || !http_base_proto || !hls->http_persistent) {
 err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options);
@@ -264,8 +259,7 @@ static int hlsenc_io_open(AVFormatContext *s, AVIOContext 
**pb, char *filename,
 
 static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char 
*filename) {
 HLSContext *hls = s->priv_data;
-int http_base_proto = filename ? is_http_proto(filename) : 0;
-
+int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
 if (!http_base_proto || !hls->http_persistent || hls->key_info_file || 
hls->encrypt) {
 ff_format_io_close(s, pb);
 } else {
@@ -275,7 +269,7 @@ static void hlsenc_io_close(AVFormatContext *s, AVIOContext 
**pb, char *filename
 
 static void set_http_options(AVFormatContext *s, AVDictionary **options, 
HLSContext *c)
 {
-int http_base_proto = is_http_proto(s->filename);
+int http_base_proto = ff_is_http_proto(s->filename);
 
 if (c->method) {
 av_dict_set(options, "method", c->method, 0);
diff --git a/libavformat/internal.h b/libavformat/internal.h
index 36a5721..8f168c9 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -619,6 +619,14 @@ int ff_format_output_open(AVFormatContext *s, const char 
*url, AVDictionary **op
 void ff_format_io_close(AVFormatContext *s, AVIOContext **pb);
 
 /**
+ * Utility function to check if the file uses http or https protocol
+ *
+ * @param s AVFormatContext
+ * @param filename URL or file name to open for writing
+ */
+int ff_is_http_proto(char *filename);
+
+/**
  * Parse creation_time in AVFormatContext metadata if exists and warn if the
  * parsing fails.
  *
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 84e4920..f18a7c8 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -5459,6 +5459,11 @@ void ff_format_io_close(AVFormatContext *s, AVIOContext 
**pb)
 *pb = NULL;
 }
 
+int ff_is_http_proto(char *filename) {
+const char *proto = avio_find_protocol_name(filename);
+return proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, 
"https")) : 0;
+}
+
 int ff_parse_creation_time_metadata(AVFormatContext *s, int64_t *timestamp, 
int return_seconds)
 {
 AVDictionaryEntry *entry;
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 2/2] avformat/dashenc: Persistent HTTP connections supported as an option

2017-12-15 Thread Karthick J
From: Karthick Jeyapal 

---
 libavformat/dashenc.c | 67 +--
 1 file changed, 54 insertions(+), 13 deletions(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 5687530..e7d1a0d 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -37,6 +37,9 @@
 #include "avformat.h"
 #include "avio_internal.h"
 #include "hlsplaylist.h"
+#if CONFIG_HTTP_PROTOCOL
+#include "http.h"
+#endif
 #include "internal.h"
 #include "isom.h"
 #include "os_support.h"
@@ -103,7 +106,10 @@ typedef struct DASHContext {
 const char *utc_timing_url;
 const char *user_agent;
 int hls_playlist;
+int http_persistent;
 int master_playlist_created;
+AVIOContext *mpd_out;
+AVIOContext *m3u8_out;
 } DASHContext;
 
 static struct codec_string {
@@ -117,6 +123,36 @@ static struct codec_string {
 { 0, NULL }
 };
 
+static int dashenc_io_open(AVFormatContext *s, AVIOContext **pb, char 
*filename,
+   AVDictionary **options) {
+DASHContext *c = s->priv_data;
+int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
+int err = AVERROR_MUXER_NOT_FOUND;
+if (!*pb || !http_base_proto || !c->http_persistent) {
+err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options);
+#if CONFIG_HTTP_PROTOCOL
+} else {
+URLContext *http_url_context = ffio_geturlcontext(*pb);
+av_assert0(http_url_context);
+err = ff_http_do_new_request(http_url_context, filename);
+#endif
+}
+return err;
+}
+
+static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char 
*filename) {
+DASHContext *c = s->priv_data;
+int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
+
+if (!http_base_proto || !c->http_persistent) {
+ff_format_io_close(s, pb);
+#if CONFIG_HTTP_PROTOCOL
+} else {
+avio_flush(*pb);
+#endif
+}
+}
+
 static void set_codec_str(AVFormatContext *s, AVCodecParameters *par,
   char *str, int size)
 {
@@ -218,6 +254,8 @@ static void set_http_options(AVDictionary **options, 
DASHContext *c)
 {
 if (c->user_agent)
 av_dict_set(options, "user_agent", c->user_agent, 0);
+if (c->http_persistent)
+av_dict_set_int(options, "multiple_requests", 1, 0);
 }
 
 static void get_hls_playlist_name(char *playlist_name, int string_size,
@@ -273,9 +311,10 @@ static void dash_free(AVFormatContext *s)
 av_freep(&c->streams);
 }
 
-static void output_segment_list(OutputStream *os, AVIOContext *out, 
DASHContext *c,
+static void output_segment_list(OutputStream *os, AVIOContext *out, 
AVFormatContext *s,
 int representation_id, int final)
 {
+DASHContext *c = s->priv_data;
 int i, start_index = 0, start_number = 1;
 if (c->window_size) {
 start_index  = FFMAX(os->nb_segments   - c->window_size, 0);
@@ -339,7 +378,6 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, DASHContext
 int timescale = os->ctx->streams[0]->time_base.den;
 char temp_filename_hls[1024];
 char filename_hls[1024];
-AVIOContext *out_hls = NULL;
 AVDictionary *http_opts = NULL;
 int target_duration = 0;
 int ret = 0;
@@ -352,7 +390,7 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, DASHContext
 snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? 
"%s.tmp" : "%s", filename_hls);
 
 set_http_options(&http_opts, c);
-avio_open2(&out_hls, temp_filename_hls, AVIO_FLAG_WRITE, NULL, 
&http_opts);
+dashenc_io_open(s, &c->m3u8_out, temp_filename_hls, &http_opts);
 av_dict_free(&http_opts);
 for (i = start_index; i < os->nb_segments; i++) {
 Segment *seg = os->segments[i];
@@ -361,15 +399,15 @@ static void output_segment_list(OutputStream *os, 
AVIOContext *out, DASHContext
 target_duration = hls_get_int_from_double(duration);
 }
 
-ff_hls_write_playlist_header(out_hls, 6, -1, target_duration,
+ff_hls_write_playlist_header(c->m3u8_out, 6, -1, target_duration,
  start_number, PLAYLIST_TYPE_NONE);
 
-ff_hls_write_init_file(out_hls, os->initfile, c->single_file,
+ff_hls_write_init_file(c->m3u8_out, os->initfile, c->single_file,
os->init_range_length, os->init_start_pos);
 
 for (i = start_index; i < os->nb_segments; i++) {
 Segment *seg = os->segments[i];
-ret = ff_hls_write_file_entry(out_hls, 0, c->single_file,
+ret = ff_hls_write_file_entry(c->m3u8_out, 0, c->single_file,
 (double) seg->duration / timescale, 0,
 seg->range_length, seg->start_pos, NULL,
 c->single_file ? os->initfile : seg->file,
@@ -380,9 +418,10 @@ static void output_segme

[FFmpeg-devel] [PATCH v2 1/2] avformat/hlsenc, utils: Moved is_http_proto from hlsenc to utils for re-use

2017-12-16 Thread Karthick J
From: Karthick Jeyapal 

---
 libavformat/hlsenc.c   | 12 +++-
 libavformat/internal.h |  8 
 libavformat/utils.c|  5 +
 3 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index e3442c3..03d54c7 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -240,15 +240,10 @@ static int mkdir_p(const char *path) {
 return ret;
 }
 
-static int is_http_proto(char *filename) {
-const char *proto = avio_find_protocol_name(filename);
-return proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, 
"https")) : 0;
-}
-
 static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,
   AVDictionary **options) {
 HLSContext *hls = s->priv_data;
-int http_base_proto = filename ? is_http_proto(filename) : 0;
+int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
 int err = AVERROR_MUXER_NOT_FOUND;
 if (!*pb || !http_base_proto || !hls->http_persistent) {
 err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options);
@@ -264,8 +259,7 @@ static int hlsenc_io_open(AVFormatContext *s, AVIOContext 
**pb, char *filename,
 
 static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char 
*filename) {
 HLSContext *hls = s->priv_data;
-int http_base_proto = filename ? is_http_proto(filename) : 0;
-
+int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
 if (!http_base_proto || !hls->http_persistent || hls->key_info_file || 
hls->encrypt) {
 ff_format_io_close(s, pb);
 } else {
@@ -275,7 +269,7 @@ static void hlsenc_io_close(AVFormatContext *s, AVIOContext 
**pb, char *filename
 
 static void set_http_options(AVFormatContext *s, AVDictionary **options, 
HLSContext *c)
 {
-int http_base_proto = is_http_proto(s->filename);
+int http_base_proto = ff_is_http_proto(s->filename);
 
 if (c->method) {
 av_dict_set(options, "method", c->method, 0);
diff --git a/libavformat/internal.h b/libavformat/internal.h
index 36a5721..8f168c9 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -619,6 +619,14 @@ int ff_format_output_open(AVFormatContext *s, const char 
*url, AVDictionary **op
 void ff_format_io_close(AVFormatContext *s, AVIOContext **pb);
 
 /**
+ * Utility function to check if the file uses http or https protocol
+ *
+ * @param s AVFormatContext
+ * @param filename URL or file name to open for writing
+ */
+int ff_is_http_proto(char *filename);
+
+/**
  * Parse creation_time in AVFormatContext metadata if exists and warn if the
  * parsing fails.
  *
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 84e4920..f18a7c8 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -5459,6 +5459,11 @@ void ff_format_io_close(AVFormatContext *s, AVIOContext 
**pb)
 *pb = NULL;
 }
 
+int ff_is_http_proto(char *filename) {
+const char *proto = avio_find_protocol_name(filename);
+return proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, 
"https")) : 0;
+}
+
 int ff_parse_creation_time_metadata(AVFormatContext *s, int64_t *timestamp, 
int return_seconds)
 {
 AVDictionaryEntry *entry;
-- 
1.9.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


  1   2   >