diff mbox

[FFmpeg-devel] lavf/matroska: expose stream encoding as global side-data

Message ID 20160910033909.93321-1-rodger.combs@gmail.com
State Superseded
Headers show

Commit Message

Rodger Combs Sept. 10, 2016, 3:39 a.m. UTC
Some demuxers can't handle Matroska compression, so this lets API users
check if a file uses it and determine whether those players will fail.
---
 libavcodec/avcodec.h      | 35 ++++++++++++++++++++++++++++++++++-
 libavcodec/avpacket.c     |  1 +
 libavcodec/version.h      |  4 ++--
 libavformat/matroskadec.c | 23 +++++++++++++++++------
 4 files changed, 54 insertions(+), 9 deletions(-)

Comments

James Almer Sept. 10, 2016, 4:19 a.m. UTC | #1
On 9/10/2016 12:39 AM, Rodger Combs wrote:
> Some demuxers can't handle Matroska compression, so this lets API users
> check if a file uses it and determine whether those players will fail.
> ---
>  libavcodec/avcodec.h      | 35 ++++++++++++++++++++++++++++++++++-
>  libavcodec/avpacket.c     |  1 +
>  libavcodec/version.h      |  4 ++--
>  libavformat/matroskadec.c | 23 +++++++++++++++++------
>  4 files changed, 54 insertions(+), 9 deletions(-)
> 
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index 01f9b29..0ecc6b4 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -1330,6 +1330,34 @@ typedef struct AVCPBProperties {
>      uint64_t vbv_delay;
>  } AVCPBProperties;
>  
> +/**
> + * This structure describes the Matroska encoding (compression or encryption) applied to
> + * a stream. It can be useful when determining whether or not other demuxers can handle
> + * a file, since some players don't support header compression.
> + */
> +typedef struct AVMatroskaEncoding {
> +    /**
> +     * Type of content encoding. 0 for compression; 1 for encryption.
> +     */
> +    uint64_t type;

If it's a boolean value then just use int/unsigned.

> +    /**
> +     * Algorithm used for the compression or encryption.
> +     * For compression:
> +     * 0 - zlib,
> +     * 1 - bzlib,
> +     * 2 - lzo1x
> +     * 3 - Header Stripping
> +     * For encryption:
> +     * 0 - Signing only
> +     * 1 - DES
> +     * 2 - 3DES
> +     * 3 - Twofish
> +     * 4 - Blowfish
> +     * 5 - AES
> +     */
> +    uint64_t algorithm;

Enum? Otherwise int/unsigned and ideally #defines.

> +} AVMatroskaEncoding;
> +
>  #if FF_API_QSCALE_TYPE
>  #define FF_QSCALE_TYPE_MPEG1 0
>  #define FF_QSCALE_TYPE_MPEG2 1
> @@ -1525,7 +1553,12 @@ enum AVPacketSideDataType {
>       * should be associated with a video stream and containts data in the form
>       * of the AVMasteringDisplayMetadata struct.
>       */
> -    AV_PKT_DATA_MASTERING_DISPLAY_METADATA
> +    AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
> +
> +    /**
> +     * Corresponds to the AVMatroskaEncoding struct.
> +     */
> +    AV_PKT_DATA_MATROSKA_ENCODING,
>  };
>  
>  #define AV_PKT_DATA_QUALITY_FACTOR AV_PKT_DATA_QUALITY_STATS //DEPRECATED
> diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
> index fa2844d..220e305 100644
> --- a/libavcodec/avpacket.c
> +++ b/libavcodec/avpacket.c
> @@ -367,6 +367,7 @@ const char *av_packet_side_data_name(enum AVPacketSideDataType type)
>      case AV_PKT_DATA_METADATA_UPDATE:            return "Metadata Update";
>      case AV_PKT_DATA_MPEGTS_STREAM_ID:           return "MPEGTS Stream ID";
>      case AV_PKT_DATA_MASTERING_DISPLAY_METADATA: return "Mastering display metadata";
> +    case AV_PKT_DATA_MATROSKA_ENCODING:          return "Matroska Encoding";
>      }
>      return NULL;
>  }
> diff --git a/libavcodec/version.h b/libavcodec/version.h
> index f5dd118..ecd48c5 100644
> --- a/libavcodec/version.h
> +++ b/libavcodec/version.h
> @@ -28,8 +28,8 @@
>  #include "libavutil/version.h"
>  
>  #define LIBAVCODEC_VERSION_MAJOR  57
> -#define LIBAVCODEC_VERSION_MINOR  55
> -#define LIBAVCODEC_VERSION_MICRO 101
> +#define LIBAVCODEC_VERSION_MINOR  56
> +#define LIBAVCODEC_VERSION_MICRO 100
>  
>  #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
>                                                 LIBAVCODEC_VERSION_MINOR, \
> diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
> index 77b8a5d..9bae9c8 100644
> --- a/libavformat/matroskadec.c
> +++ b/libavformat/matroskadec.c
> @@ -1919,6 +1919,10 @@ static int matroska_parse_tracks(AVFormatContext *s)
>          if (!track->codec_id)
>              continue;
>  
> +        st = track->stream = avformat_new_stream(s, NULL);
> +        if (!st)
> +            return AVERROR(ENOMEM);
> +
>          if (track->audio.samplerate < 0 || track->audio.samplerate > INT_MAX ||
>              isnan(track->audio.samplerate)) {
>              av_log(matroska->ctx, AV_LOG_WARNING,
> @@ -1944,7 +1948,16 @@ static int matroska_parse_tracks(AVFormatContext *s)
>              av_log(matroska->ctx, AV_LOG_ERROR,
>                     "Multiple combined encodings not supported");
>          } else if (encodings_list->nb_elem == 1) {
> +            AVMatroskaEncoding *side_data = (void*)av_stream_new_side_data(st,
> +                                                     AV_PKT_DATA_MATROSKA_ENCODING,
> +                                                     sizeof(AVMatroskaEncoding));
> +            if (!side_data)
> +                return AVERROR(ENOMEM);
> +
> +            side_data->type = encodings[0].type;
> +
>              if (encodings[0].type) {
> +                side_data->algorithm = encodings[0].encryption.algo;
>                  if (encodings[0].encryption.key_id.size > 0) {
>                      /* Save the encryption key id to be stored later as a
>                         metadata tag. */
> @@ -1972,10 +1985,12 @@ static int matroska_parse_tracks(AVFormatContext *s)
>                   encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_LZO   &&
>  #endif
>                   encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP) {
> +                side_data->algorithm = encodings[0].compression.algo;
>                  encodings[0].scope = 0;
>                  av_log(matroska->ctx, AV_LOG_ERROR,
>                         "Unsupported encoding type");
>              } else if (track->codec_priv.size && encodings[0].scope & 2) {
> +                side_data->algorithm = encodings[0].compression.algo;
>                  uint8_t *codec_priv = track->codec_priv.data;
>                  int ret = matroska_decode_buffer(&track->codec_priv.data,
>                                                   &track->codec_priv.size,
> @@ -1989,6 +2004,8 @@ static int matroska_parse_tracks(AVFormatContext *s)
>  
>                  if (codec_priv != track->codec_priv.data)
>                      av_free(codec_priv);
> +            } else {
> +                side_data->algorithm = encodings[0].compression.algo;
>              }
>          }
>  
> @@ -2000,12 +2017,6 @@ static int matroska_parse_tracks(AVFormatContext *s)
>              }
>          }
>  
> -        st = track->stream = avformat_new_stream(s, NULL);
> -        if (!st) {
> -            av_free(key_id_base64);
> -            return AVERROR(ENOMEM);
> -        }
> -
>          if (key_id_base64) {
>              /* export encryption key id as base64 metadata tag */
>              av_dict_set(&st->metadata, "enc_key_id", key_id_base64, 0);
> 

No comments on the actual implementation.
diff mbox

Patch

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 01f9b29..0ecc6b4 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1330,6 +1330,34 @@  typedef struct AVCPBProperties {
     uint64_t vbv_delay;
 } AVCPBProperties;
 
+/**
+ * This structure describes the Matroska encoding (compression or encryption) applied to
+ * a stream. It can be useful when determining whether or not other demuxers can handle
+ * a file, since some players don't support header compression.
+ */
+typedef struct AVMatroskaEncoding {
+    /**
+     * Type of content encoding. 0 for compression; 1 for encryption.
+     */
+    uint64_t type;
+    /**
+     * Algorithm used for the compression or encryption.
+     * For compression:
+     * 0 - zlib,
+     * 1 - bzlib,
+     * 2 - lzo1x
+     * 3 - Header Stripping
+     * For encryption:
+     * 0 - Signing only
+     * 1 - DES
+     * 2 - 3DES
+     * 3 - Twofish
+     * 4 - Blowfish
+     * 5 - AES
+     */
+    uint64_t algorithm;
+} AVMatroskaEncoding;
+
 #if FF_API_QSCALE_TYPE
 #define FF_QSCALE_TYPE_MPEG1 0
 #define FF_QSCALE_TYPE_MPEG2 1
@@ -1525,7 +1553,12 @@  enum AVPacketSideDataType {
      * should be associated with a video stream and containts data in the form
      * of the AVMasteringDisplayMetadata struct.
      */
-    AV_PKT_DATA_MASTERING_DISPLAY_METADATA
+    AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
+
+    /**
+     * Corresponds to the AVMatroskaEncoding struct.
+     */
+    AV_PKT_DATA_MATROSKA_ENCODING,
 };
 
 #define AV_PKT_DATA_QUALITY_FACTOR AV_PKT_DATA_QUALITY_STATS //DEPRECATED
diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
index fa2844d..220e305 100644
--- a/libavcodec/avpacket.c
+++ b/libavcodec/avpacket.c
@@ -367,6 +367,7 @@  const char *av_packet_side_data_name(enum AVPacketSideDataType type)
     case AV_PKT_DATA_METADATA_UPDATE:            return "Metadata Update";
     case AV_PKT_DATA_MPEGTS_STREAM_ID:           return "MPEGTS Stream ID";
     case AV_PKT_DATA_MASTERING_DISPLAY_METADATA: return "Mastering display metadata";
+    case AV_PKT_DATA_MATROSKA_ENCODING:          return "Matroska Encoding";
     }
     return NULL;
 }
diff --git a/libavcodec/version.h b/libavcodec/version.h
index f5dd118..ecd48c5 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -28,8 +28,8 @@ 
 #include "libavutil/version.h"
 
 #define LIBAVCODEC_VERSION_MAJOR  57
-#define LIBAVCODEC_VERSION_MINOR  55
-#define LIBAVCODEC_VERSION_MICRO 101
+#define LIBAVCODEC_VERSION_MINOR  56
+#define LIBAVCODEC_VERSION_MICRO 100
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                LIBAVCODEC_VERSION_MINOR, \
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 77b8a5d..9bae9c8 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -1919,6 +1919,10 @@  static int matroska_parse_tracks(AVFormatContext *s)
         if (!track->codec_id)
             continue;
 
+        st = track->stream = avformat_new_stream(s, NULL);
+        if (!st)
+            return AVERROR(ENOMEM);
+
         if (track->audio.samplerate < 0 || track->audio.samplerate > INT_MAX ||
             isnan(track->audio.samplerate)) {
             av_log(matroska->ctx, AV_LOG_WARNING,
@@ -1944,7 +1948,16 @@  static int matroska_parse_tracks(AVFormatContext *s)
             av_log(matroska->ctx, AV_LOG_ERROR,
                    "Multiple combined encodings not supported");
         } else if (encodings_list->nb_elem == 1) {
+            AVMatroskaEncoding *side_data = (void*)av_stream_new_side_data(st,
+                                                     AV_PKT_DATA_MATROSKA_ENCODING,
+                                                     sizeof(AVMatroskaEncoding));
+            if (!side_data)
+                return AVERROR(ENOMEM);
+
+            side_data->type = encodings[0].type;
+
             if (encodings[0].type) {
+                side_data->algorithm = encodings[0].encryption.algo;
                 if (encodings[0].encryption.key_id.size > 0) {
                     /* Save the encryption key id to be stored later as a
                        metadata tag. */
@@ -1972,10 +1985,12 @@  static int matroska_parse_tracks(AVFormatContext *s)
                  encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_LZO   &&
 #endif
                  encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP) {
+                side_data->algorithm = encodings[0].compression.algo;
                 encodings[0].scope = 0;
                 av_log(matroska->ctx, AV_LOG_ERROR,
                        "Unsupported encoding type");
             } else if (track->codec_priv.size && encodings[0].scope & 2) {
+                side_data->algorithm = encodings[0].compression.algo;
                 uint8_t *codec_priv = track->codec_priv.data;
                 int ret = matroska_decode_buffer(&track->codec_priv.data,
                                                  &track->codec_priv.size,
@@ -1989,6 +2004,8 @@  static int matroska_parse_tracks(AVFormatContext *s)
 
                 if (codec_priv != track->codec_priv.data)
                     av_free(codec_priv);
+            } else {
+                side_data->algorithm = encodings[0].compression.algo;
             }
         }
 
@@ -2000,12 +2017,6 @@  static int matroska_parse_tracks(AVFormatContext *s)
             }
         }
 
-        st = track->stream = avformat_new_stream(s, NULL);
-        if (!st) {
-            av_free(key_id_base64);
-            return AVERROR(ENOMEM);
-        }
-
         if (key_id_base64) {
             /* export encryption key id as base64 metadata tag */
             av_dict_set(&st->metadata, "enc_key_id", key_id_base64, 0);