Commit 28924f4b authored by Vishwanath Dixit's avatar Vishwanath Dixit Committed by Karthick Jeyapal

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

parent ffe7cc89
...@@ -254,6 +254,9 @@ Use persistent HTTP connections. Applicable only for HTTP output. ...@@ -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.
......
...@@ -81,6 +81,7 @@ typedef struct OutputStream { ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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[] = { ...@@ -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 },
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment