Browse Source

avformat/dashenc: chunk streaming support for low latency use cases

tags/n4.0
Vishwanath Dixit Karthick Jeyapal 7 years ago
parent
commit
28924f4b48
2 changed files with 26 additions and 3 deletions
  1. +3
    -0
      doc/muxers.texi
  2. +23
    -3
      libavformat/dashenc.c

+ 3
- 0
doc/muxers.texi View File

@@ -254,6 +254,9 @@ Use persistent HTTP connections. Applicable only for HTTP output.
@item -hls_playlist @var{hls_playlist} @item -hls_playlist @var{hls_playlist}
Generate HLS playlist files as well. The master playlist is generated with the filename master.m3u8. 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. One media playlist file is generated for each stream with filenames media_0.m3u8, media_1.m3u8, etc.
@item -streaming @var{streaming}
Enable (1) or disable (0) chunk streaming mode of output. In chunk streaming
mode, each frame will be a moof fragment which forms a chunk.
@item -adaptation_sets @var{adaptation_sets} @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 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. of the adaptation sets and a,b,c,d and e are the indices of the mapped streams.


+ 23
- 3
libavformat/dashenc.c View File

@@ -81,6 +81,7 @@ typedef struct OutputStream {
char bandwidth_str[64]; char bandwidth_str[64];


char codec_str[100]; char codec_str[100];
int written_len;
char filename[1024]; char filename[1024];
char full_path[1024]; char full_path[1024];
char temp_path[1024]; char temp_path[1024];
@@ -114,6 +115,7 @@ typedef struct DASHContext {
int master_playlist_created; int master_playlist_created;
AVIOContext *mpd_out; AVIOContext *mpd_out;
AVIOContext *m3u8_out; AVIOContext *m3u8_out;
int streaming;
} DASHContext; } DASHContext;


static struct codec_string { static struct codec_string {
@@ -250,7 +252,8 @@ static int flush_dynbuf(OutputStream *os, int *range_length)
// write out to file // write out to file
*range_length = avio_close_dyn_buf(os->ctx->pb, &buffer); *range_length = avio_close_dyn_buf(os->ctx->pb, &buffer);
os->ctx->pb = NULL; os->ctx->pb = NULL;
avio_write(os->out, buffer, *range_length);
avio_write(os->out, buffer + os->written_len, *range_length - os->written_len);
os->written_len = 0;
av_free(buffer); av_free(buffer);


// re-open buffer // re-open buffer
@@ -960,7 +963,10 @@ static int dash_init(AVFormatContext *s)
os->init_start_pos = 0; os->init_start_pos = 0;


if (!strcmp(os->format_name, "mp4")) { if (!strcmp(os->format_name, "mp4")) {
av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
if (c->streaming)
av_dict_set(&opts, "movflags", "frag_every_frame+dash+delay_moov", 0);
else
av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
} else { } else {
av_dict_set_int(&opts, "cluster_time_limit", c->min_seg_duration / 1000, 0); av_dict_set_int(&opts, "cluster_time_limit", c->min_seg_duration / 1000, 0);
av_dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit av_dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit
@@ -1155,7 +1161,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream)
} }


if (!c->single_file) { if (!c->single_file) {
if (!strcmp(os->format_name, "mp4"))
if (!strcmp(os->format_name, "mp4") && !os->written_len)
write_styp(os->ctx->pb); write_styp(os->ctx->pb);
} else { } else {
snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname, os->initfile); snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname, os->initfile);
@@ -1318,6 +1324,19 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
av_dict_free(&opts); av_dict_free(&opts);
} }


//write out the data immediately in streaming mode
if (c->streaming && !strcmp(os->format_name, "mp4")) {
int len = 0;
uint8_t *buf = NULL;
if (!os->written_len)
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);
os->written_len = len;
avio_flush(os->out);
}

return ret; return ret;
} }


@@ -1394,6 +1413,7 @@ static const AVOption options[] = {
{ "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, { "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 }, { "http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
{ "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
{ "streaming", "Enable/Disable streaming mode of output. Each frame will be moof fragment", OFFSET(streaming), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
{ NULL }, { NULL },
}; };




Loading…
Cancel
Save