[FFmpeg-devel] dash: add descriptor which is useful to the scheme defined by ISO/IEC 23009-1:2014/Amd.2:2015.

Submitted by Leo Zhang on July 12, 2019, 8:31 a.m.

Details

Message ID 1562920274-85570-1-git-send-email-leozhang@qiyi.com
State New
Headers show

Commit Message

Leo Zhang July 12, 2019, 8:31 a.m.
Reference ISO/IEC 23009-1:2014/Amd.2:2015, a spatial relationship descriptor is defined as a spatial part of a content component (e.g. a region of interest, or a tile) 
 and represented by either an Adaptation Set or a Sub-Representation.

Signed-off-by: leozhang <leozhang@qiyi.com>
---
 doc/muxers.texi       |  3 +++
 libavformat/dashenc.c | 36 +++++++++++++++++++++++++++++++++---
 2 files changed, 36 insertions(+), 3 deletions(-)

Comments

UsingtcNower July 14, 2019, 12:33 p.m.
ping?

leozhang <leozhang@qiyi.com> 于2019年7月12日周五 下午4:31写道:
>
>  Reference ISO/IEC 23009-1:2014/Amd.2:2015, a spatial relationship descriptor is defined as a spatial part of a content component (e.g. a region of interest, or a tile)
>  and represented by either an Adaptation Set or a Sub-Representation.
>
> Signed-off-by: leozhang <leozhang@qiyi.com>
> ---
>  doc/muxers.texi       |  3 +++
>  libavformat/dashenc.c | 36 +++++++++++++++++++++++++++++++++---
>  2 files changed, 36 insertions(+), 3 deletions(-)
>
> diff --git a/doc/muxers.texi b/doc/muxers.texi
> index b109297..ac06ad2 100644
> --- a/doc/muxers.texi
> +++ b/doc/muxers.texi
> @@ -275,6 +275,9 @@ of the adaptation sets and a,b,c,d and e are the indices of the mapped streams.
>  To map all video (or audio) streams to an AdaptationSet, "v" (or "a") can be used as stream identifier instead of IDs.
>
>  When no assignment is defined, this defaults to an AdaptationSet for each stream.
> +
> +Optional syntax is "id=x,descriptor=descriptor_str,streams=a,b,c id=y,streams=d,e" and so on, descriptor is useful to the scheme defined by ISO/IEC 23009-1:2014/Amd.2:2015.
> +And descriptor_str must be a properly formatted XML element, which is encoded by base64.
>  @item timeout @var{timeout}
>  Set timeout for socket I/O operations. Applicable only for HTTP output.
>  @item index_correction @var{index_correction}
> diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
> index b25afb4..f7ebb1f 100644
> --- a/libavformat/dashenc.c
> +++ b/libavformat/dashenc.c
> @@ -34,6 +34,7 @@
>  #include "libavutil/rational.h"
>  #include "libavutil/time.h"
>  #include "libavutil/time_internal.h"
> +#include "libavutil/base64.h"
>
>  #include "avc.h"
>  #include "avformat.h"
> @@ -68,6 +69,7 @@ typedef struct Segment {
>
>  typedef struct AdaptationSet {
>      char id[10];
> +    char descriptor[1024];
>      enum AVMediaType media_type;
>      AVDictionary *metadata;
>      AVRational min_frame_rate, max_frame_rate;
> @@ -748,7 +750,8 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind
>      role = av_dict_get(as->metadata, "role", NULL, 0);
>      if (role)
>          avio_printf(out, "\t\t\t<Role schemeIdUri=\"urn:mpeg:dash:role:2011\" value=\"%s\"/>\n", role->value);
> -
> +    if (strlen(as->descriptor))
> +        avio_printf(out, "\t\t\t%s\n", as->descriptor);
>      for (i = 0; i < s->nb_streams; i++) {
>          OutputStream *os = &c->streams[i];
>          char bandwidth_str[64] = {'\0'};
> @@ -820,7 +823,7 @@ static int parse_adaptation_sets(AVFormatContext *s)
>  {
>      DASHContext *c = s->priv_data;
>      const char *p = c->adaptation_sets;
> -    enum { new_set, parse_id, parsing_streams } state;
> +    enum { new_set, parse_id, parsing_streams, parse_descriptor } state;
>      AdaptationSet *as;
>      int i, n, ret;
>
> @@ -837,6 +840,9 @@ static int parse_adaptation_sets(AVFormatContext *s)
>      }
>
>      // syntax id=0,streams=0,1,2 id=1,streams=3,4 and so on
> +    // option id=0,descriptor=descriptor_str,streams=0,1,2 and so on
> +    // descriptor is useful to the scheme defined by ISO/IEC 23009-1:2014/Amd.2:2015
> +    // descriptor_str must be a properly formatted XML element, encoded by base64.
>      state = new_set;
>      while (*p) {
>          if (*p == ' ') {
> @@ -854,7 +860,31 @@ static int parse_adaptation_sets(AVFormatContext *s)
>              if (*p)
>                  p++;
>              state = parse_id;
> -        } else if (state == parse_id && av_strstart(p, "streams=", &p)) {
> +        } else if (state == parse_id && av_strstart(p, "descriptor=", &p)) {
> +            char *encode_str;
> +            uint8_t *decode_str;
> +            int decode_size, ret;
> +
> +            n = strcspn(p, ",");
> +            encode_str = av_strndup(p, n);
> +            decode_size = AV_BASE64_DECODE_SIZE(n);
> +            decode_str = (uint8_t *)av_mallocz(decode_size);
> +            if (decode_str) {
> +                ret = av_base64_decode(decode_str, encode_str, decode_size);
> +                if (ret >= 0)
> +                    snprintf(as->descriptor, sizeof(as->descriptor), "%.*s", decode_size, decode_str);
> +                else
> +                    av_log(s, AV_LOG_WARNING, "descriptor string is invalid base64 encode\n");
> +            } else
> +                av_log(s, AV_LOG_WARNING, "av_mallocz failed, will not parse descriptor\n");
> +
> +            p += n;
> +            if (*p)
> +                p++;
> +            state = parse_descriptor;
> +            av_freep(&encode_str);
> +            av_freep(&decode_str);
> +        } else if ((state == parse_id || state == parse_descriptor) && av_strstart(p, "streams=", &p)) { //descriptor is optional
>              state = parsing_streams;
>          } else if (state == parsing_streams) {
>              AdaptationSet *as = &c->as[c->nb_as - 1];
> --
> 1.8.3.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Carl Eugen Hoyos July 14, 2019, 12:53 p.m.
Am Fr., 12. Juli 2019 um 10:31 Uhr schrieb leozhang <leozhang@qiyi.com>:
>
>  Reference ISO/IEC 23009-1:2014/Amd.2:2015, a spatial relationship descriptor is defined as a spatial part of a content component (e.g. a region of interest, or a tile)
>  and represented by either an Adaptation Set or a Sub-Representation.
>
> Signed-off-by: leozhang <leozhang@qiyi.com>
> ---
>  doc/muxers.texi       |  3 +++
>  libavformat/dashenc.c | 36 +++++++++++++++++++++++++++++++++---
>  2 files changed, 36 insertions(+), 3 deletions(-)
>
> diff --git a/doc/muxers.texi b/doc/muxers.texi
> index b109297..ac06ad2 100644
> --- a/doc/muxers.texi
> +++ b/doc/muxers.texi
> @@ -275,6 +275,9 @@ of the adaptation sets and a,b,c,d and e are the indices of the mapped streams.
>  To map all video (or audio) streams to an AdaptationSet, "v" (or "a") can be used as stream identifier instead of IDs.
>
>  When no assignment is defined, this defaults to an AdaptationSet for each stream.

> +Optional syntax is "id=x,descriptor=descriptor_str,streams=a,b,c id=y,streams=d,e" and so
> on, descriptor is useful to the scheme defined by ISO/IEC 23009-1:2014/Amd.2:2015.
> +And descriptor_str must be a properly formatted XML element, which is encoded by base64.

I wonder how helpful these two sentences are, perhaps somebody who uses
dash can comment?

>  @item timeout @var{timeout}
>  Set timeout for socket I/O operations. Applicable only for HTTP output.
>  @item index_correction @var{index_correction}
> diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
> index b25afb4..f7ebb1f 100644
> --- a/libavformat/dashenc.c
> +++ b/libavformat/dashenc.c
> @@ -34,6 +34,7 @@
>  #include "libavutil/rational.h"
>  #include "libavutil/time.h"
>  #include "libavutil/time_internal.h"
> +#include "libavutil/base64.h"
>
>  #include "avc.h"
>  #include "avformat.h"
> @@ -68,6 +69,7 @@ typedef struct Segment {
>
>  typedef struct AdaptationSet {
>      char id[10];
> +    char descriptor[1024];
>      enum AVMediaType media_type;
>      AVDictionary *metadata;
>      AVRational min_frame_rate, max_frame_rate;
> @@ -748,7 +750,8 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind
>      role = av_dict_get(as->metadata, "role", NULL, 0);
>      if (role)
>          avio_printf(out, "\t\t\t<Role schemeIdUri=\"urn:mpeg:dash:role:2011\" value=\"%s\"/>\n", role->value);
> -
> +    if (strlen(as->descriptor))
> +        avio_printf(out, "\t\t\t%s\n", as->descriptor);
>      for (i = 0; i < s->nb_streams; i++) {
>          OutputStream *os = &c->streams[i];
>          char bandwidth_str[64] = {'\0'};
> @@ -820,7 +823,7 @@ static int parse_adaptation_sets(AVFormatContext *s)
>  {
>      DASHContext *c = s->priv_data;
>      const char *p = c->adaptation_sets;
> -    enum { new_set, parse_id, parsing_streams } state;
> +    enum { new_set, parse_id, parsing_streams, parse_descriptor } state;
>      AdaptationSet *as;
>      int i, n, ret;
>
> @@ -837,6 +840,9 @@ static int parse_adaptation_sets(AVFormatContext *s)
>      }
>
>      // syntax id=0,streams=0,1,2 id=1,streams=3,4 and so on
> +    // option id=0,descriptor=descriptor_str,streams=0,1,2 and so on
> +    // descriptor is useful to the scheme defined by ISO/IEC 23009-1:2014/Amd.2:2015
> +    // descriptor_str must be a properly formatted XML element, encoded by base64.
>      state = new_set;
>      while (*p) {
>          if (*p == ' ') {
> @@ -854,7 +860,31 @@ static int parse_adaptation_sets(AVFormatContext *s)
>              if (*p)
>                  p++;
>              state = parse_id;
> -        } else if (state == parse_id && av_strstart(p, "streams=", &p)) {
> +        } else if (state == parse_id && av_strstart(p, "descriptor=", &p)) {
> +            char *encode_str;
> +            uint8_t *decode_str;
> +            int decode_size, ret;
> +
> +            n = strcspn(p, ",");
> +            encode_str = av_strndup(p, n);
> +            decode_size = AV_BASE64_DECODE_SIZE(n);

> +            decode_str = (uint8_t *)av_mallocz(decode_size);

Why is this (ugly) cast necessary?

> +            if (decode_str) {
> +                ret = av_base64_decode(decode_str, encode_str, decode_size);
> +                if (ret >= 0)
> +                    snprintf(as->descriptor, sizeof(as->descriptor), "%.*s", decode_size, decode_str);
> +                else
> +                    av_log(s, AV_LOG_WARNING, "descriptor string is invalid base64 encode\n");
> +            } else
> +                av_log(s, AV_LOG_WARNING, "av_mallocz failed, will not parse descriptor\n");

Please add some braces.

Carl Eugen

Patch hide | download patch | download mbox

diff --git a/doc/muxers.texi b/doc/muxers.texi
index b109297..ac06ad2 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -275,6 +275,9 @@  of the adaptation sets and a,b,c,d and e are the indices of the mapped streams.
 To map all video (or audio) streams to an AdaptationSet, "v" (or "a") can be used as stream identifier instead of IDs.
 
 When no assignment is defined, this defaults to an AdaptationSet for each stream.
+
+Optional syntax is "id=x,descriptor=descriptor_str,streams=a,b,c id=y,streams=d,e" and so on, descriptor is useful to the scheme defined by ISO/IEC 23009-1:2014/Amd.2:2015.
+And descriptor_str must be a properly formatted XML element, which is encoded by base64.
 @item timeout @var{timeout}
 Set timeout for socket I/O operations. Applicable only for HTTP output.
 @item index_correction @var{index_correction}
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index b25afb4..f7ebb1f 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -34,6 +34,7 @@ 
 #include "libavutil/rational.h"
 #include "libavutil/time.h"
 #include "libavutil/time_internal.h"
+#include "libavutil/base64.h"
 
 #include "avc.h"
 #include "avformat.h"
@@ -68,6 +69,7 @@  typedef struct Segment {
 
 typedef struct AdaptationSet {
     char id[10];
+    char descriptor[1024];
     enum AVMediaType media_type;
     AVDictionary *metadata;
     AVRational min_frame_rate, max_frame_rate;
@@ -748,7 +750,8 @@  static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind
     role = av_dict_get(as->metadata, "role", NULL, 0);
     if (role)
         avio_printf(out, "\t\t\t<Role schemeIdUri=\"urn:mpeg:dash:role:2011\" value=\"%s\"/>\n", role->value);
-
+    if (strlen(as->descriptor))
+        avio_printf(out, "\t\t\t%s\n", as->descriptor);
     for (i = 0; i < s->nb_streams; i++) {
         OutputStream *os = &c->streams[i];
         char bandwidth_str[64] = {'\0'};
@@ -820,7 +823,7 @@  static int parse_adaptation_sets(AVFormatContext *s)
 {
     DASHContext *c = s->priv_data;
     const char *p = c->adaptation_sets;
-    enum { new_set, parse_id, parsing_streams } state;
+    enum { new_set, parse_id, parsing_streams, parse_descriptor } state;
     AdaptationSet *as;
     int i, n, ret;
 
@@ -837,6 +840,9 @@  static int parse_adaptation_sets(AVFormatContext *s)
     }
 
     // syntax id=0,streams=0,1,2 id=1,streams=3,4 and so on
+    // option id=0,descriptor=descriptor_str,streams=0,1,2 and so on
+    // descriptor is useful to the scheme defined by ISO/IEC 23009-1:2014/Amd.2:2015
+    // descriptor_str must be a properly formatted XML element, encoded by base64.
     state = new_set;
     while (*p) {
         if (*p == ' ') {
@@ -854,7 +860,31 @@  static int parse_adaptation_sets(AVFormatContext *s)
             if (*p)
                 p++;
             state = parse_id;
-        } else if (state == parse_id && av_strstart(p, "streams=", &p)) {
+        } else if (state == parse_id && av_strstart(p, "descriptor=", &p)) {
+            char *encode_str;
+            uint8_t *decode_str;
+            int decode_size, ret;
+
+            n = strcspn(p, ",");
+            encode_str = av_strndup(p, n);
+            decode_size = AV_BASE64_DECODE_SIZE(n);
+            decode_str = (uint8_t *)av_mallocz(decode_size);
+            if (decode_str) {
+                ret = av_base64_decode(decode_str, encode_str, decode_size);
+                if (ret >= 0)
+                    snprintf(as->descriptor, sizeof(as->descriptor), "%.*s", decode_size, decode_str);
+                else
+                    av_log(s, AV_LOG_WARNING, "descriptor string is invalid base64 encode\n");
+            } else
+                av_log(s, AV_LOG_WARNING, "av_mallocz failed, will not parse descriptor\n");
+            
+            p += n;
+            if (*p)
+                p++;
+            state = parse_descriptor;
+            av_freep(&encode_str);
+            av_freep(&decode_str);
+        } else if ((state == parse_id || state == parse_descriptor) && av_strstart(p, "streams=", &p)) { //descriptor is optional 
             state = parsing_streams;
         } else if (state == parsing_streams) {
             AdaptationSet *as = &c->as[c->nb_as - 1];