diff mbox

[FFmpeg-devel] avformat/hlsenc: implement program_date_time

Message ID 20160907193444.27361-1-michael@niedermayer.cc
State Accepted
Headers show

Commit Message

Michael Niedermayer Sept. 7, 2016, 7:34 p.m. UTC
TODO: docs, version bump

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
 libavformat/hlsenc.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

Comments

Steven Liu Sept. 7, 2016, 10:38 p.m. UTC | #1
2016-09-08 3:34 GMT+08:00 Michael Niedermayer <michael@niedermayer.cc>:

> TODO: docs, version bump
>
> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
> ---
>  libavformat/hlsenc.c | 23 +++++++++++++++++++++++
>  1 file changed, 23 insertions(+)
>
> diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
> index c0b5ef2..a376312 100644
> --- a/libavformat/hlsenc.c
> +++ b/libavformat/hlsenc.c
> @@ -64,6 +64,7 @@ typedef enum HLSFlags {
>      HLS_OMIT_ENDLIST = (1 << 4),
>      HLS_SPLIT_BY_TIME = (1 << 5),
>      HLS_APPEND_LIST = (1 << 6),
> +    HLS_PROGRAM_DATE_TIME = (1 << 7),
>  } HLSFlags;
>
>  typedef enum {
> @@ -128,6 +129,7 @@ typedef struct HLSContext {
>
>      char *method;
>
> +    double initial_prog_date_time;
>  } HLSContext;
>
>  static int hls_delete_old_segments(HLSContext *hls) {
> @@ -481,6 +483,7 @@ static int hls_window(AVFormatContext *s, int last)
>      char *key_uri = NULL;
>      char *iv_string = NULL;
>      AVDictionary *options = NULL;
> +    double prog_date_time = hls->initial_prog_date_time;
>
>      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 temporarly partial files\n");
> @@ -533,6 +536,19 @@ static int hls_window(AVFormatContext *s, int last)
>          if (hls->flags & HLS_SINGLE_FILE)
>               avio_printf(out, "#EXT-X-BYTERANGE:%"PRIi64"@%"PRIi64"\n",
>                           en->size, en->pos);
> +        if (hls->flags & HLS_PROGRAM_DATE_TIME) {
> +            time_t tt;
> +            int milli;
> +            struct tm *tm, tmpbuf;
> +            char buf0[128], buf1[128];
> +            tt = (int64_t)prog_date_time;
> +            milli = av_clip(lrint(1000*(prog_date_time - tt)), 0, 999);
> +            tm = localtime_r(&tt, &tmpbuf);
> +            strftime(buf0, sizeof(buf0), "%FT%T", tm);
> +            strftime(buf1, sizeof(buf1), "%z", tm);
> +            avio_printf(out, "#EXT-X-PROGRAM-DATE-TIME:%s.%03d%s\n",
> buf0, milli, buf1);
> +            prog_date_time += en->duration;
> +        }
>          if (hls->baseurl)
>              avio_printf(out, "%s", hls->baseurl);
>          avio_printf(out, "%s\n", en->filename);
> @@ -710,6 +726,12 @@ static int hls_write_header(AVFormatContext *s)
>      hls->recording_time = (hls->init_time ? hls->init_time : hls->time) *
> AV_TIME_BASE;
>      hls->start_pts      = AV_NOPTS_VALUE;
>
> +    if (hls->flags & HLS_PROGRAM_DATE_TIME) {
> +        time_t now0;
> +        time(&now0);
> +        hls->initial_prog_date_time = now0;
> +    }
> +
>      if (hls->format_options_str) {
>          ret = av_dict_parse_string(&hls->format_options,
> hls->format_options_str, "=", ":", 0);
>          if (ret < 0) {
> @@ -1005,6 +1027,7 @@ static const AVOption options[] = {
>      {"omit_endlist", "Do not append an endlist when ending stream", 0,
> AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX,   E, "flags"},
>      {"split_by_time", "split the hls segment by time which user set by
> hls_time", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SPLIT_BY_TIME }, 0, UINT_MAX,
>  E, "flags"},
>      {"append_list", "append the new segments into old hls segment list",
> 0, AV_OPT_TYPE_CONST, {.i64 = HLS_APPEND_LIST }, 0, UINT_MAX,   E, "flags"},
> +    {"program_date_time", "add EXT-X-PROGRAM-DATE-TIME", 0,
> AV_OPT_TYPE_CONST, {.i64 = HLS_PROGRAM_DATE_TIME }, 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" },
> --
> 2.9.3
>
LGTM

Thanks
Michael Niedermayer Sept. 8, 2016, 12:24 a.m. UTC | #2
On Thu, Sep 08, 2016 at 06:38:03AM +0800, Steven Liu wrote:
> 2016-09-08 3:34 GMT+08:00 Michael Niedermayer <michael@niedermayer.cc>:
> 
> > TODO: docs, version bump
> >
> > Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
> > ---
> >  libavformat/hlsenc.c | 23 +++++++++++++++++++++++
> >  1 file changed, 23 insertions(+)
> >
> > diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
> > index c0b5ef2..a376312 100644
> > --- a/libavformat/hlsenc.c
> > +++ b/libavformat/hlsenc.c
> > @@ -64,6 +64,7 @@ typedef enum HLSFlags {
> >      HLS_OMIT_ENDLIST = (1 << 4),
> >      HLS_SPLIT_BY_TIME = (1 << 5),
> >      HLS_APPEND_LIST = (1 << 6),
> > +    HLS_PROGRAM_DATE_TIME = (1 << 7),
> >  } HLSFlags;
> >
> >  typedef enum {
> > @@ -128,6 +129,7 @@ typedef struct HLSContext {
> >
> >      char *method;
> >
> > +    double initial_prog_date_time;
> >  } HLSContext;
> >
> >  static int hls_delete_old_segments(HLSContext *hls) {
> > @@ -481,6 +483,7 @@ static int hls_window(AVFormatContext *s, int last)
> >      char *key_uri = NULL;
> >      char *iv_string = NULL;
> >      AVDictionary *options = NULL;
> > +    double prog_date_time = hls->initial_prog_date_time;
> >
> >      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 temporarly partial files\n");
> > @@ -533,6 +536,19 @@ static int hls_window(AVFormatContext *s, int last)
> >          if (hls->flags & HLS_SINGLE_FILE)
> >               avio_printf(out, "#EXT-X-BYTERANGE:%"PRIi64"@%"PRIi64"\n",
> >                           en->size, en->pos);
> > +        if (hls->flags & HLS_PROGRAM_DATE_TIME) {
> > +            time_t tt;
> > +            int milli;
> > +            struct tm *tm, tmpbuf;
> > +            char buf0[128], buf1[128];
> > +            tt = (int64_t)prog_date_time;
> > +            milli = av_clip(lrint(1000*(prog_date_time - tt)), 0, 999);
> > +            tm = localtime_r(&tt, &tmpbuf);
> > +            strftime(buf0, sizeof(buf0), "%FT%T", tm);
> > +            strftime(buf1, sizeof(buf1), "%z", tm);
> > +            avio_printf(out, "#EXT-X-PROGRAM-DATE-TIME:%s.%03d%s\n",
> > buf0, milli, buf1);
> > +            prog_date_time += en->duration;
> > +        }
> >          if (hls->baseurl)
> >              avio_printf(out, "%s", hls->baseurl);
> >          avio_printf(out, "%s\n", en->filename);
> > @@ -710,6 +726,12 @@ static int hls_write_header(AVFormatContext *s)
> >      hls->recording_time = (hls->init_time ? hls->init_time : hls->time) *
> > AV_TIME_BASE;
> >      hls->start_pts      = AV_NOPTS_VALUE;
> >
> > +    if (hls->flags & HLS_PROGRAM_DATE_TIME) {
> > +        time_t now0;
> > +        time(&now0);
> > +        hls->initial_prog_date_time = now0;
> > +    }
> > +
> >      if (hls->format_options_str) {
> >          ret = av_dict_parse_string(&hls->format_options,
> > hls->format_options_str, "=", ":", 0);
> >          if (ret < 0) {
> > @@ -1005,6 +1027,7 @@ static const AVOption options[] = {
> >      {"omit_endlist", "Do not append an endlist when ending stream", 0,
> > AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX,   E, "flags"},
> >      {"split_by_time", "split the hls segment by time which user set by
> > hls_time", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SPLIT_BY_TIME }, 0, UINT_MAX,
> >  E, "flags"},
> >      {"append_list", "append the new segments into old hls segment list",
> > 0, AV_OPT_TYPE_CONST, {.i64 = HLS_APPEND_LIST }, 0, UINT_MAX,   E, "flags"},
> > +    {"program_date_time", "add EXT-X-PROGRAM-DATE-TIME", 0,
> > AV_OPT_TYPE_CONST, {.i64 = HLS_PROGRAM_DATE_TIME }, 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" },
> > --
> > 2.9.3
> >
> LGTM

applied

thanks

[...]
diff mbox

Patch

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index c0b5ef2..a376312 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -64,6 +64,7 @@  typedef enum HLSFlags {
     HLS_OMIT_ENDLIST = (1 << 4),
     HLS_SPLIT_BY_TIME = (1 << 5),
     HLS_APPEND_LIST = (1 << 6),
+    HLS_PROGRAM_DATE_TIME = (1 << 7),
 } HLSFlags;
 
 typedef enum {
@@ -128,6 +129,7 @@  typedef struct HLSContext {
 
     char *method;
 
+    double initial_prog_date_time;
 } HLSContext;
 
 static int hls_delete_old_segments(HLSContext *hls) {
@@ -481,6 +483,7 @@  static int hls_window(AVFormatContext *s, int last)
     char *key_uri = NULL;
     char *iv_string = NULL;
     AVDictionary *options = NULL;
+    double prog_date_time = hls->initial_prog_date_time;
 
     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 temporarly partial files\n");
@@ -533,6 +536,19 @@  static int hls_window(AVFormatContext *s, int last)
         if (hls->flags & HLS_SINGLE_FILE)
              avio_printf(out, "#EXT-X-BYTERANGE:%"PRIi64"@%"PRIi64"\n",
                          en->size, en->pos);
+        if (hls->flags & HLS_PROGRAM_DATE_TIME) {
+            time_t tt;
+            int milli;
+            struct tm *tm, tmpbuf;
+            char buf0[128], buf1[128];
+            tt = (int64_t)prog_date_time;
+            milli = av_clip(lrint(1000*(prog_date_time - tt)), 0, 999);
+            tm = localtime_r(&tt, &tmpbuf);
+            strftime(buf0, sizeof(buf0), "%FT%T", tm);
+            strftime(buf1, sizeof(buf1), "%z", tm);
+            avio_printf(out, "#EXT-X-PROGRAM-DATE-TIME:%s.%03d%s\n", buf0, milli, buf1);
+            prog_date_time += en->duration;
+        }
         if (hls->baseurl)
             avio_printf(out, "%s", hls->baseurl);
         avio_printf(out, "%s\n", en->filename);
@@ -710,6 +726,12 @@  static int hls_write_header(AVFormatContext *s)
     hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * AV_TIME_BASE;
     hls->start_pts      = AV_NOPTS_VALUE;
 
+    if (hls->flags & HLS_PROGRAM_DATE_TIME) {
+        time_t now0;
+        time(&now0);
+        hls->initial_prog_date_time = now0;
+    }
+
     if (hls->format_options_str) {
         ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0);
         if (ret < 0) {
@@ -1005,6 +1027,7 @@  static const AVOption options[] = {
     {"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX,   E, "flags"},
     {"split_by_time", "split the hls segment by time which user set by hls_time", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SPLIT_BY_TIME }, 0, UINT_MAX,   E, "flags"},
     {"append_list", "append the new segments into old hls segment list", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_APPEND_LIST }, 0, UINT_MAX,   E, "flags"},
+    {"program_date_time", "add EXT-X-PROGRAM-DATE-TIME", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PROGRAM_DATE_TIME }, 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" },