Re: [FFmpeg-devel] [PATCH v3 1/1] avformat/hlsenc: closed caption tags in the master playlist
> 在 2018年1月23日,下午1:21,vdi...@akamai.com 写道: > > From: Vishwanath Dixit> > --- > doc/muxers.texi | 37 +++ > libavformat/dashenc.c | 2 +- > libavformat/hlsenc.c | 155 +- > libavformat/hlsplaylist.c | 5 +- > libavformat/hlsplaylist.h | 2 +- > 5 files changed, 196 insertions(+), 5 deletions(-) > > diff --git a/doc/muxers.texi b/doc/muxers.texi > index b060c4f..d9a5cc0 100644 > --- a/doc/muxers.texi > +++ b/doc/muxers.texi > @@ -901,6 +901,43 @@ and they are mapped to the two video only variant > streams with audio group names > > By default, a single hls variant containing all the encoded streams is > created. > > +@item cc_stream_map > +Map string which specifies different closed captions groups and their > +attributes. The closed captions stream groups are separated by space. > +Expected string format is like this > +"ccgroup:,instreamid:,language: > ". > +'ccgroup' and 'instreamid' are mandatory attributes. 'language' is an > optional > +attribute. > +The closed captions groups configured using this option are mapped to > different > +variant streams by providing the same 'ccgroup' name in the > +@code{var_stream_map} string. If @code{var_stream_map} is not set, then the > +first available ccgroup in @code{cc_stream_map} is mapped to the output > variant > +stream. The examples for these two use cases are given below. > + > +@example > +ffmpeg -re -i in.ts -b:v 1000k -b:a 64k -a53cc 1 -f hls \ > + -cc_stream_map "ccgroup:cc,instreamid:CC1,language:en" \ > + -master_pl_name master.m3u8 \ > + http://example.com/live/out.m3u8 > +@end example > +This example adds @code{#EXT-X-MEDIA} tag with @code{TYPE=CLOSED-CAPTIONS} in > +the master playlist with group name 'cc', langauge 'en' (english) and > +INSTREAM-ID 'CC1'. Also, it adds @code{CLOSED-CAPTIONS} attribute with group > +name 'cc' for the output variant stream. > +@example > +ffmpeg -re -i in.ts -b:v:0 1000k -b:v:1 256k -b:a:0 64k -b:a:1 32k \ > + -a53cc:0 1 -a53cc:1 1\ > + -map 0:v -map 0:a -map 0:v -map 0:a -f hls \ > + -cc_stream_map "ccgroup:cc,instreamid:CC1,language:en > ccgroup:cc,instreamid:CC2,language:sp" \ > + -var_stream_map "v:0,a:0,ccgroup:cc v:1,a:1,ccgroup:cc" \ > + -master_pl_name master.m3u8 \ > + http://example.com/live/out_%v.m3u8 > +@end example > +This example adds two @code{#EXT-X-MEDIA} tags with > @code{TYPE=CLOSED-CAPTIONS} in > +the master playlist for the INSTREAM-IDs 'CC1' and 'CC2'. Also, it adds > +@code{CLOSED-CAPTIONS} attribute with group name 'cc' for the two output > variant > +streams. > + > @item master_pl_name > Create HLS master playlist with the given name. > > diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c > index 39d0afe..5ece100 100644 > --- a/libavformat/dashenc.c > +++ b/libavformat/dashenc.c > @@ -820,7 +820,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); > +ff_hls_write_stream_info(st, out, stream_bitrate, playlist_file, > agroup, NULL, NULL); > } > avio_close(out); > if (use_rename) > diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c > index 42e437f..aab21f2 100644 > --- a/libavformat/hlsenc.c > +++ b/libavformat/hlsenc.c > @@ -152,9 +152,16 @@ typedef struct VariantStream { > unsigned int nb_streams; > int m3u8_created; /* status of media play-list creation */ > char *agroup; /* audio group name */ > +char *ccgroup; /* closed caption group name */ > char *baseurl; > } VariantStream; > > +typedef struct ClosedCaptionsStream { > +char *ccgroup; /* closed caption group name */ > +char *instreamid; /* closed captions INSTREAM-ID */ > +char *language; /* closed captions langauge */ > +} ClosedCaptionsStream; > + > typedef struct HLSContext { > const AVClass *class; // Class for private options. > int64_t start_sequence; > @@ -203,11 +210,14 @@ typedef struct HLSContext { > > VariantStream *var_streams; > unsigned int nb_varstreams; > +ClosedCaptionsStream *cc_streams; > +unsigned int nb_ccstreams; > > int master_m3u8_created; /* status of master play-list creation */ > char *master_m3u8_url; /* URL of the master m3u8 file */ > int version; /* HLS version */ > char *var_stream_map; /* user specified variant stream map string */ > +char *cc_stream_map; /* user specified closed caption streams map string > */ > char *master_pl_name; > unsigned int master_publish_rate; > int http_persistent; > @@ -1167,7 +1177,8 @@ static int create_master_playlist(AVFormatContext *s, > AVDictionary *options = NULL; > unsigned int i, j; > int m3u8_name_size, ret, bandwidth; > -
[FFmpeg-devel] [PATCH v3 1/1] avformat/hlsenc: closed caption tags in the master playlist
From: Vishwanath Dixit--- doc/muxers.texi | 37 +++ libavformat/dashenc.c | 2 +- libavformat/hlsenc.c | 155 +- libavformat/hlsplaylist.c | 5 +- libavformat/hlsplaylist.h | 2 +- 5 files changed, 196 insertions(+), 5 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index b060c4f..d9a5cc0 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -901,6 +901,43 @@ and they are mapped to the two video only variant streams with audio group names By default, a single hls variant containing all the encoded streams is created. +@item cc_stream_map +Map string which specifies different closed captions groups and their +attributes. The closed captions stream groups are separated by space. +Expected string format is like this +"ccgroup:,instreamid:,language: ". +'ccgroup' and 'instreamid' are mandatory attributes. 'language' is an optional +attribute. +The closed captions groups configured using this option are mapped to different +variant streams by providing the same 'ccgroup' name in the +@code{var_stream_map} string. If @code{var_stream_map} is not set, then the +first available ccgroup in @code{cc_stream_map} is mapped to the output variant +stream. The examples for these two use cases are given below. + +@example +ffmpeg -re -i in.ts -b:v 1000k -b:a 64k -a53cc 1 -f hls \ + -cc_stream_map "ccgroup:cc,instreamid:CC1,language:en" \ + -master_pl_name master.m3u8 \ + http://example.com/live/out.m3u8 +@end example +This example adds @code{#EXT-X-MEDIA} tag with @code{TYPE=CLOSED-CAPTIONS} in +the master playlist with group name 'cc', langauge 'en' (english) and +INSTREAM-ID 'CC1'. Also, it adds @code{CLOSED-CAPTIONS} attribute with group +name 'cc' for the output variant stream. +@example +ffmpeg -re -i in.ts -b:v:0 1000k -b:v:1 256k -b:a:0 64k -b:a:1 32k \ + -a53cc:0 1 -a53cc:1 1\ + -map 0:v -map 0:a -map 0:v -map 0:a -f hls \ + -cc_stream_map "ccgroup:cc,instreamid:CC1,language:en ccgroup:cc,instreamid:CC2,language:sp" \ + -var_stream_map "v:0,a:0,ccgroup:cc v:1,a:1,ccgroup:cc" \ + -master_pl_name master.m3u8 \ + http://example.com/live/out_%v.m3u8 +@end example +This example adds two @code{#EXT-X-MEDIA} tags with @code{TYPE=CLOSED-CAPTIONS} in +the master playlist for the INSTREAM-IDs 'CC1' and 'CC2'. Also, it adds +@code{CLOSED-CAPTIONS} attribute with group name 'cc' for the two output variant +streams. + @item master_pl_name Create HLS master playlist with the given name. diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 39d0afe..5ece100 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -820,7 +820,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); +ff_hls_write_stream_info(st, out, stream_bitrate, playlist_file, agroup, NULL, NULL); } avio_close(out); if (use_rename) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 42e437f..aab21f2 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -152,9 +152,16 @@ typedef struct VariantStream { unsigned int nb_streams; int m3u8_created; /* status of media play-list creation */ char *agroup; /* audio group name */ +char *ccgroup; /* closed caption group name */ char *baseurl; } VariantStream; +typedef struct ClosedCaptionsStream { +char *ccgroup; /* closed caption group name */ +char *instreamid; /* closed captions INSTREAM-ID */ +char *language; /* closed captions langauge */ +} ClosedCaptionsStream; + typedef struct HLSContext { const AVClass *class; // Class for private options. int64_t start_sequence; @@ -203,11 +210,14 @@ typedef struct HLSContext { VariantStream *var_streams; unsigned int nb_varstreams; +ClosedCaptionsStream *cc_streams; +unsigned int nb_ccstreams; int master_m3u8_created; /* status of master play-list creation */ char *master_m3u8_url; /* URL of the master m3u8 file */ int version; /* HLS version */ char *var_stream_map; /* user specified variant stream map string */ +char *cc_stream_map; /* user specified closed caption streams map string */ char *master_pl_name; unsigned int master_publish_rate; int http_persistent; @@ -1167,7 +1177,8 @@ static int create_master_playlist(AVFormatContext *s, AVDictionary *options = NULL; unsigned int i, j; int m3u8_name_size, ret, bandwidth; -char *m3u8_rel_name; +char *m3u8_rel_name, *ccgroup; +ClosedCaptionsStream *ccs; input_vs->m3u8_created = 1; if (!hls->master_m3u8_created) { @@ -1194,6 +1205,16 @@ static int create_master_playlist(AVFormatContext *s,