2017-12-29 19:58 GMT+08:00 Dixit, Vishwanath <vdi...@akamai.com>: > > > On 12/29/17 5:11 PM, Steven Liu wrote: >> 2017-12-29 18:44 GMT+08:00 <vdi...@akamai.com>: >>> From: Vishwanath Dixit <vdi...@akamai.com> >>> >>> --- >>> doc/muxers.texi | 4 ++++ >>> libavformat/dashenc.c | 2 +- >>> libavformat/hlsenc.c | 14 +++++++++++++- >>> libavformat/hlsplaylist.c | 5 ++++- >>> libavformat/hlsplaylist.h | 3 ++- >>> 5 files changed, 24 insertions(+), 4 deletions(-) >>> >>> diff --git a/doc/muxers.texi b/doc/muxers.texi >>> index 93db549..8229202 100644 >>> --- a/doc/muxers.texi >>> +++ b/doc/muxers.texi >>> @@ -872,6 +872,10 @@ publishing it repeatedly every after 30 segments i.e. >>> every after 60s. >>> @item http_persistent >>> Use persistent HTTP connections. Applicable only for HTTP output. >>> >>> +@item cc_instream_id >>> +Add @code{#EXT-X-MEDIA} tag in the master playlist with the specified >>> instream ID. It >>> +accepts the values in the range 1-4. >>> + >>> @end table >>> >>> @anchor{ico} >>> diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c >>> index 478a384..8797959 100644 >>> --- a/libavformat/dashenc.c >>> +++ b/libavformat/dashenc.c >>> @@ -760,7 +760,7 @@ static int write_manifest(AVFormatContext *s, int final) >>> AVStream *st = s->streams[i]; >>> get_hls_playlist_name(playlist_file, sizeof(playlist_file), >>> NULL, i); >>> ff_hls_write_stream_info(st, out, st->codecpar->bit_rate, >>> - playlist_file, NULL); >>> + playlist_file, NULL, NULL); >>> } >>> avio_close(out); >>> if (use_rename) >>> diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c >>> index 74f66ce..e5176a8 100644 >>> --- a/libavformat/hlsenc.c >>> +++ b/libavformat/hlsenc.c >>> @@ -206,6 +206,7 @@ typedef struct HLSContext { >>> int http_persistent; >>> AVIOContext *m3u8_out; >>> AVIOContext *sub_m3u8_out; >>> + int cc_instream_id; /* closed captions INSTREAM-ID */ >>> } HLSContext; >>> >>> static int mkdir_p(const char *path) { >>> @@ -1122,6 +1123,7 @@ static int create_master_playlist(AVFormatContext *s, >>> unsigned int i, j; >>> int m3u8_name_size, ret, bandwidth; >>> char *m3u8_rel_name; >>> + char cc_group[16] = {0}; >>> >>> input_vs->m3u8_created = 1; >>> if (!hls->master_m3u8_created) { >>> @@ -1148,6 +1150,14 @@ static int create_master_playlist(AVFormatContext *s, >>> >>> ff_hls_write_playlist_version(hls->m3u8_out, hls->version); >>> >>> + if (hls->cc_instream_id) { >>> + av_strlcpy(cc_group, "group_cc", sizeof(cc_group)); >> >> Why do you write "group_cc" ? maybe this can make an option be set by >> user, and set a default string, if it can be set by user, need >> attention with the printf, about that security. >> > Unlike audio rendition streams, in common usage scenarios, there will be only > one cc rendition stream and all the video rendition streams refer to the same > cc rendition stream. The following example shows a common use case where both > video rendition streams (media_0.m3u8 and media_2.m3u8) are referring to the > same closed caption rendition with group id “group_cc”. > #EXTM3U > #EXT-X-VERSION:3 > > #EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS,GROUP-ID="group_cc",NAME="captions",INSTREAM-ID="CC1" > > #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="group_aud1",NAME="audio_0",DEFAULT=YES,URI="media_1.m3u8" > > #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="group_aud2",NAME="audio_0",DEFAULT=YES,URI="media_3.m3u8" > > #EXT-X-STREAM-INF:BANDWIDTH=140800,RESOLUTION=1280x720,AUDIO="group_aud1",CLOSED-CAPTIONS="group_cc" > media_0.m3u8 > > #EXT-X-STREAM-INF:BANDWIDTH=140800,AUDIO="group_aud1" > media_1.m3u8 > > > #EXT-X-STREAM-INF:BANDWIDTH=140800,RESOLUTION=1280x720,AUDIO="group_aud2",CLOSED-CAPTIONS="group_cc" > media_2.m3u8 > > #EXT-X-STREAM-INF:BANDWIDTH=140800,AUDIO="group_aud2" > media_3.m3u8 > > So, currently the group id name is fixed to “group_cc”. However, this > functionality can be further extended in the future for different CC groups > when there are different closed caption sources are present in the input. > Please let me know your further thoughts/suggestions on this.
I think "group_cc" should be a variable, it can be set by the user, not write to a constant by hlsenc. for example: #EXTM3U #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="low",NAME="Main", \ DEFAULT=YES,URI="low/main/audio-video.m3u8" #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="low",NAME="Centerfield", \ DEFAULT=NO,URI="low/centerfield/audio-video.m3u8" #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="low",NAME="Dugout", \ DEFAULT=NO,URI="low/dugout/audio-video.m3u8" #EXT-X-STREAM-INF:BANDWIDTH=1280000,CODECS="...",VIDEO="low" low/main/audio-video.m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="mid",NAME="Main", \ DEFAULT=YES,URI="mid/main/audio-video.m3u8" #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="mid",NAME="Centerfield", \ DEFAULT=NO,URI="mid/centerfield/audio-video.m3u8" #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="mid",NAME="Dugout", \ DEFAULT=NO,URI="mid/dugout/audio-video.m3u8" #EXT-X-STREAM-INF:BANDWIDTH=2560000,CODECS="...",VIDEO="mid" mid/main/audio-video.m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="hi",NAME="Main", \ DEFAULT=YES,URI="hi/main/audio-video.m3u8" #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="hi",NAME="Centerfield", \ DEFAULT=NO,URI="hi/centerfield/audio-video.m3u8" #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="hi",NAME="Dugout", \ DEFAULT=NO,URI="hi/dugout/audio-video.m3u8" #EXT-X-STREAM-INF:BANDWIDTH=7680000,CODECS="...",VIDEO="hi" hi/main/audio-video.m3u8 What do you think about it?? > > >>> + avio_printf(hls->m3u8_out, >>> "#EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS,GROUP-ID=\"%s\"", >>> + cc_group); >>> + avio_printf(hls->m3u8_out, >>> ",NAME=\"captions\",INSTREAM-ID=\"CC%d\"\n", >>> + hls->cc_instream_id); >>> + } >>> + >>> /* 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]); >>> @@ -1235,7 +1245,8 @@ static int create_master_playlist(AVFormatContext *s, >>> bandwidth += bandwidth / 10; >>> >>> ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, >>> m3u8_rel_name, >>> - aud_st ? vs->agroup : NULL); >>> + aud_st ? vs->agroup : NULL, >>> + vid_st ? cc_group : NULL); >>> >>> av_freep(&m3u8_rel_name); >>> } >>> @@ -2444,6 +2455,7 @@ static const AVOption options[] = { >>> {"master_pl_name", "Create HLS master playlist with this name", >>> OFFSET(master_pl_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, >>> {"master_pl_publish_rate", "Publish master play list every after this >>> many segment intervals", OFFSET(master_publish_rate), AV_OPT_TYPE_INT, >>> {.i64 = 0}, 0, UINT_MAX, E}, >>> {"http_persistent", "Use persistent HTTP connections", >>> OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, >>> + {"cc_instream_id", "Closed captions INSTREAM-ID", >>> OFFSET(cc_instream_id), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 4, E}, >>> { NULL }, >>> }; >>> >>> diff --git a/libavformat/hlsplaylist.c b/libavformat/hlsplaylist.c >>> index 42f059a..8619436 100644 >>> --- a/libavformat/hlsplaylist.c >>> +++ b/libavformat/hlsplaylist.c >>> @@ -36,7 +36,8 @@ void ff_hls_write_playlist_version(AVIOContext *out, int >>> version) { >>> } >>> >>> void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, >>> - int bandwidth, char *filename, char *agroup) >>> { >>> + int bandwidth, char *filename, char *agroup, >>> + char *cc_group) { >>> if (!out || !filename) >>> return; >>> >>> @@ -52,6 +53,8 @@ void ff_hls_write_stream_info(AVStream *st, AVIOContext >>> *out, >>> st->codecpar->height); >>> if (agroup && strlen(agroup) > 0) >>> avio_printf(out, ",AUDIO=\"group_%s\"", agroup); >>> + if (cc_group && strlen(cc_group) > 0) >>> + avio_printf(out, ",CLOSED-CAPTIONS=\"%s\"", cc_group); >>> avio_printf(out, "\n%s\n\n", filename); >>> } >>> >>> diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h >>> index ac03550..71ccee7 100644 >>> --- a/libavformat/hlsplaylist.h >>> +++ b/libavformat/hlsplaylist.h >>> @@ -38,7 +38,8 @@ typedef enum { >>> >>> void ff_hls_write_playlist_version(AVIOContext *out, int version); >>> void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, >>> - int bandwidth, char *filename, char *agroup); >>> + int bandwidth, char *filename, char *agroup, >>> + char *cc_group); >>> void ff_hls_write_playlist_header(AVIOContext *out, int version, int >>> allowcache, >>> int target_duration, int64_t sequence, >>> uint32_t playlist_type); >>> -- >>> 1.9.1 >>> _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel