Message ID | 20160910033909.93321-1-rodger.combs@gmail.com |
---|---|
State | Superseded |
Headers | show |
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 --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);