Re: [FFmpeg-devel] [PATCH v3 1/1] avformat/hlsenc: closed caption tags in the master playlist

2018-01-22 Thread Liu Steven

> 在 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

2018-01-22 Thread vdixit
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,