[FFmpeg-devel,3/3] Adds a new hls_flag avg_bw

Submitted by Amit Kale on Feb. 12, 2018, 8:55 a.m.

Details

Message ID ca537ca8-6e53-44ed-49d0-30ed9b5fa22d@hotstar.com
State New
Headers show

Commit Message

Amit Kale Feb. 12, 2018, 8:55 a.m.
If this flag is set, AVERAGE-BANDWIDTH value will be added to a master 
playlist
entry. This flag implies peak_segment_bw.
---
  doc/muxers.texi           |  4 ++++
  libavformat/dashenc.c     |  2 +-
  libavformat/hlsenc.c      | 20 ++++++++++++++++----
  libavformat/hlsplaylist.c |  6 ++++--
  libavformat/hlsplaylist.h |  4 ++--
  5 files changed, 27 insertions(+), 9 deletions(-)

allowcache,
                                    int target_duration, int64_t sequence,
                                    uint32_t playlist_type);

Patch hide | download patch | download mbox

diff --git a/doc/muxers.texi b/doc/muxers.texi
index e2c9cbfa2f..428d4009b3 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -745,6 +745,10 @@  Possible values:
  If this flag is set, BANDWIDTH value in a master playlist entry will be
  set to the peak segment bandwidth.

+@item avg_bw
+If this flag is set, AVERAGE-BANDWIDTH value will be added to a master
+playlist entry. This flag implies peak_segment_bw.
+
  @item single_file
  If this flag is set, the muxer will store all segments in a single MPEG-TS
  file, and will use byte ranges in the playlist. HLS playlists 
generated with
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 0f6f4f22fa..a918f7e649 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -827,7 +827,7 @@  static int write_manifest(AVFormatContext *s, int final)
                  stream_bitrate += max_audio_bitrate;
              }
              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, 0, 
playlist_file, agroup, NULL, NULL);
          }
          avio_close(out);
          if (use_rename)
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index f40cd0b98f..aa704c94f8 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -99,6 +99,7 @@  typedef enum HLSFlags {
      HLS_PERIODIC_REKEY = (1 << 12),
      HLS_INDEPENDENT_SEGMENTS = (1 << 13),
      HLS_PEAK_SEGMENT_BW = (1 << 14),
+    HLS_AVG_BW = (1 << 15),
  } HLSFlags;

  typedef enum {
@@ -113,6 +114,8 @@  typedef struct VariantStream {
      AVOutputFormat *vtt_oformat;
      AVIOContext *out;
      int packets_written;
+    int64_t bytes_written;
+    double total_duration;
      int init_range_length;

      AVFormatContext *avf;
@@ -1177,7 +1180,7 @@  static int create_master_playlist(AVFormatContext *s,
      AVStream *vid_st, *aud_st;
      AVDictionary *options = NULL;
      unsigned int i, j;
-    int m3u8_name_size, ret, bandwidth;
+    int m3u8_name_size, ret, bandwidth, avgbw;
      char *m3u8_rel_name, *ccgroup;
      ClosedCaptionsStream *ccs;

@@ -1294,7 +1297,9 @@  static int create_master_playlist(AVFormatContext *s,
          }

          bandwidth = 0;
-        if (last && hls->flags & HLS_PEAK_SEGMENT_BW) {
+        avgbw = 0;
+        if (last && (hls->flags & HLS_PEAK_SEGMENT_BW ||
+            hls->flags & HLS_AVG_BW)) {
              HLSSegment *hs = vs->segments;
              while (hs) {
                  int64_t segment_bandwidth = hs->size * 8 / hs->duration;
@@ -1302,6 +1307,8 @@  static int create_master_playlist(AVFormatContext *s,
                      bandwidth = segment_bandwidth;
                  hs = hs->next;
              }
+            if (hls->flags & HLS_AVG_BW)
+                avgbw = vs->bytes_written / vs->total_duration;
          } else {
              if (vid_st)
                  bandwidth += vid_st->codecpar->bit_rate;
@@ -1325,8 +1332,8 @@  static int create_master_playlist(AVFormatContext *s,
                          vs->ccgroup);
          }

-        ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, 
m3u8_rel_name,
-                aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup);
+        ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, avgbw,
+            m3u8_rel_name, aud_st ? vs->agroup : NULL, vs->codec_attr, 
ccgroup);

          av_freep(&m3u8_rel_name);
      }
@@ -2191,6 +2198,8 @@  static int hls_write_packet(AVFormatContext *s, 
AVPacket *pkt)

          new_start_pos = avio_tell(vs->avf->pb);
          vs->size = new_start_pos - vs->start_pos;
+        vs->bytes_written += vs->size;
+        vs->total_duration += vs->duration;

          if (!byterange_mode) {
              if (hls->segment_type == SEGMENT_TYPE_FMP4) {
@@ -2326,6 +2335,8 @@  failed:
      av_write_trailer(oc);
      if (oc->pb) {
          vs->size = avio_tell(vs->avf->pb) - vs->start_pos;
+        vs->bytes_written += vs->size;
+        vs->total_duration += vs->duration;
          if (hls->segment_type != SEGMENT_TYPE_FMP4)
              ff_format_io_close(s, &oc->pb);

@@ -2765,6 +2776,7 @@  static const AVOption options[] = {
      {"fmp4",   "make segment file to fragment mp4 files in m3u8", 0, 
AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_FMP4 }, 0, UINT_MAX, E, 
"segment_type"},
      {"hls_fmp4_init_filename", "set fragment mp4 file init filename", 
OFFSET(fmp4_init_filename),   AV_OPT_TYPE_STRING, {.str = 
"init.mp4"},            0,       0,         E},
      {"hls_flags",     "set flags affecting HLS playlist and media file 
generation", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, 0, UINT_MAX, 
E, "flags"},
+    {"avg_bandwidth",   "sets AVERAGE-BANDWIDTH in master play list, 
implies peak_segment_bw flag", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_AVG_BW 
}, 0, UINT_MAX,   E, "flags"},
      {"peak_segment_bw",   "sets bandwidth in master play list to peak 
segment bandwidth", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PEAK_SEGMENT_BW }, 
0, UINT_MAX,   E, "flags"},
      {"single_file",   "generate a single media file indexed with byte 
ranges", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SINGLE_FILE }, 0, UINT_MAX,   
E, "flags"},
      {"temp_file", "write segment to temporary file and rename when 
complete", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_TEMP_FILE }, 0, UINT_MAX,   
E, "flags"},
diff --git a/libavformat/hlsplaylist.c b/libavformat/hlsplaylist.c
index efcbff0009..11772e4ed9 100644
--- a/libavformat/hlsplaylist.c
+++ b/libavformat/hlsplaylist.c
@@ -46,8 +46,8 @@  void ff_hls_write_audio_rendition(AVIOContext *out, 
char *agroup,
  }

  void ff_hls_write_stream_info(AVStream *st, AVIOContext *out,
-                              int bandwidth, char *filename, char *agroup,
-                              char *codecs, char *ccgroup) {
+                              int bandwidth, int avgbw, char *filename,
+                              char *agroup, char *codecs, char *ccgroup) {

      if (!out || !filename)
          return;
@@ -59,6 +59,8 @@  void ff_hls_write_stream_info(AVStream *st, 
AVIOContext *out,
      }

      avio_printf(out, "#EXT-X-STREAM-INF:BANDWIDTH=%d", bandwidth);
+    if (avgbw != 0)
+        avio_printf(out, ",AVERAGE-BANDWIDTH=%d", avgbw);
      if (st && st->codecpar->width > 0 && st->codecpar->height > 0)
          avio_printf(out, ",RESOLUTION=%dx%d", st->codecpar->width,
                  st->codecpar->height);
diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h
index 5054b01c8f..d981a5e4ee 100644
--- a/libavformat/hlsplaylist.h
+++ b/libavformat/hlsplaylist.h
@@ -40,8 +40,8 @@  void ff_hls_write_playlist_version(AVIOContext *out, 
int version);
  void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup,
                                    char *filename, int name_id, int 
is_default);
  void ff_hls_write_stream_info(AVStream *st, AVIOContext *out,
-                              int bandwidth, char *filename, char *agroup,
-                              char *codecs, char *ccgroup);
+                              int bandwidth, int avgbw, char *filename,
+                              char *agroup, char *codecs, char *ccgroup);
  void ff_hls_write_playlist_header(AVIOContext *out, int version, int