X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmxf.c;h=17a5a20a071c7b71ed062f7d988ef1a0dca4e64a;hb=6f3e0b21748b53fd7b0471196bbda1d7e561f4fe;hp=c5ab58e64ad9f9c4955f93c6eaffbef2216f07fe;hpb=088e827a96888523dffcb06bd9940cf707eb7b03;p=ffmpeg diff --git a/libavformat/mxf.c b/libavformat/mxf.c index c5ab58e64ad..17a5a20a071 100644 --- a/libavformat/mxf.c +++ b/libavformat/mxf.c @@ -60,18 +60,17 @@ enum MXFMetadataSetType { MultipleDescriptor, Descriptor, Track, - EssenceContainerData, CryptoContext, }; -typedef struct MXFCryptoContext { +typedef struct { UID uid; enum MXFMetadataSetType type; UID context_uid; UID source_container_ul; } MXFCryptoContext; -typedef struct MXFStructuralComponent { +typedef struct { UID uid; enum MXFMetadataSetType type; UID source_package_uid; @@ -81,7 +80,7 @@ typedef struct MXFStructuralComponent { int source_track_id; } MXFStructuralComponent; -typedef struct MXFSequence { +typedef struct { UID uid; enum MXFMetadataSetType type; UID data_definition_ul; @@ -90,7 +89,7 @@ typedef struct MXFSequence { int64_t duration; } MXFSequence; -typedef struct MXFTrack { +typedef struct { UID uid; enum MXFMetadataSetType type; MXFSequence *sequence; /* mandatory, and only one */ @@ -100,7 +99,7 @@ typedef struct MXFTrack { AVRational edit_rate; } MXFTrack; -typedef struct MXFDescriptor { +typedef struct { UID uid; enum MXFMetadataSetType type; UID essence_container_ul; @@ -118,7 +117,7 @@ typedef struct MXFDescriptor { int extradata_size; } MXFDescriptor; -typedef struct MXFPackage { +typedef struct { UID uid; enum MXFMetadataSetType type; UID package_uid; @@ -128,28 +127,21 @@ typedef struct MXFPackage { UID descriptor_ref; } MXFPackage; -typedef struct MXFEssenceContainerData { - UID uid; - enum MXFMetadataSetType type; - UID linked_package_uid; -} MXFEssenceContainerData; - typedef struct { UID uid; enum MXFMetadataSetType type; } MXFMetadataSet; -typedef struct MXFContext { +typedef struct { UID *packages_refs; int packages_count; MXFMetadataSet **metadata_sets; int metadata_sets_count; - const uint8_t *sync_key; AVFormatContext *fc; struct AVAES *aesc; } MXFContext; -typedef struct KLVPacket { +typedef struct { UID key; offset_t offset; uint64_t length; @@ -160,18 +152,18 @@ enum MXFWrappingScheme { Clip, }; -typedef struct MXFCodecUL { +typedef struct { UID uid; enum CodecID id; enum MXFWrappingScheme wrapping; } MXFCodecUL; -typedef struct MXFDataDefinitionUL { +typedef struct { UID uid; enum CodecType type; } MXFDataDefinitionUL; -typedef struct MXFMetadataReadTableEntry { +typedef struct { const UID key; int (*read)(); int ctx_size; @@ -181,6 +173,7 @@ typedef struct MXFMetadataReadTableEntry { /* partial keys to match */ static const uint8_t mxf_header_partition_pack_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02 }; static const uint8_t mxf_essence_element_key[] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01 }; +static const uint8_t mxf_klv_key[] = { 0x06,0x0e,0x2b,0x34 }; /* complete keys to match */ static const uint8_t mxf_encrypted_triplet_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x04,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x7e,0x01,0x00 }; static const uint8_t mxf_encrypted_essence_container[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0b,0x01,0x00 }; @@ -205,10 +198,26 @@ static int64_t klv_decode_ber_length(ByteIOContext *pb) return size; } +static int mxf_read_sync(ByteIOContext *pb, const uint8_t *key, unsigned size) +{ + int i, b; + for (i = 0; i < size && !url_feof(pb); i++) { + b = get_byte(pb); + if (b == key[0]) + i = 0; + else if (b != key[i]) + i = -1; + } + return i == size; +} + static int klv_read_packet(KLVPacket *klv, ByteIOContext *pb) { - klv->offset = url_ftell(pb); - get_buffer(pb, klv->key, 16); + if (!mxf_read_sync(pb, mxf_klv_key, 4)) + return -1; + klv->offset = url_ftell(pb) - 4; + memcpy(klv->key, mxf_klv_key, 4); + get_buffer(pb, klv->key + 4, 12); klv->length = klv_decode_ber_length(pb); return klv->length == -1 ? -1 : 0; } @@ -281,16 +290,20 @@ static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv // source klv key klv_decode_ber_length(pb); get_buffer(pb, klv->key, 16); - if (!IS_KLV_KEY(klv, mxf_essence_element_key)) goto err_out; + if (!IS_KLV_KEY(klv, mxf_essence_element_key)) + return -1; index = mxf_get_stream_index(s, klv); - if (index < 0) goto err_out; + if (index < 0) + return -1; // source size klv_decode_ber_length(pb); orig_size = get_be64(pb); - if (orig_size < plaintext_size) goto err_out; + if (orig_size < plaintext_size) + return -1; // enc. code size = klv_decode_ber_length(pb); - if (size < 32 || size - 32 < orig_size) goto err_out; + if (size < 32 || size - 32 < orig_size) + return -1; get_buffer(pb, ivec, 16); get_buffer(pb, tmpbuf, 16); if (mxf->aesc) @@ -307,28 +320,20 @@ static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv pkt->stream_index = index; url_fskip(pb, end - url_ftell(pb)); return 0; - -err_out: - url_fskip(pb, end - url_ftell(pb)); - return -1; } static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) { - MXFContext *mxf = s->priv_data; KLVPacket klv; while (!url_feof(&s->pb)) { - if (klv_read_packet(&klv, &s->pb) < 0) { - av_log(s, AV_LOG_ERROR, "error reading KLV packet\n"); + if (klv_read_packet(&klv, &s->pb) < 0) return -1; - } #ifdef DEBUG PRINT_KEY(s, "read packet", klv.key); #endif if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key)) { int res = mxf_decrypt_triplet(s, pkt, &klv); - mxf->sync_key = mxf_encrypted_triplet_key; if (res < 0) { av_log(s, AV_LOG_ERROR, "invalid encoded triplet\n"); return -1; @@ -351,11 +356,12 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) } else av_get_packet(&s->pb, pkt, klv.length); pkt->stream_index = index; + pkt->pos = klv.offset; return 0; } else url_fskip(&s->pb, klv.length); } - return AVERROR_IO; + return AVERROR(EIO); } static int mxf_add_metadata_set(MXFContext *mxf, void *metadata_set) @@ -582,27 +588,34 @@ static const MXFDataDefinitionUL mxf_data_definition_uls[] = { static const MXFCodecUL mxf_codec_uls[] = { /* PictureEssenceCoding */ - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x02,0x02,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@ML I-Frame */ - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x02,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@HL I-Frame */ - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x03,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@HL Long GoP */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x11,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* MP@ML Long GoP */ + + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x05 }, CODEC_ID_MPEG2VIDEO, Frame }, /* D-10 30Mbps PAL */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x03 }, CODEC_ID_MPEG2VIDEO, Frame }, /* D-10 40Mbps PAL */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x01 }, CODEC_ID_MPEG2VIDEO, Frame }, /* D-10 50Mbps PAL */ + + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x02,0x02,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@ML I-Frame */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x02,0x03,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@ML Long GoP */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x03,0x03,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* MP@HL Long GoP */ + + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x02,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@HL I-Frame */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x03,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@HL Long GoP */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x20,0x02,0x03 }, CODEC_ID_MPEG4, Frame }, /* XDCAM proxy_pal030926.mxf */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x20,0x02,0x04 }, CODEC_ID_MPEG4, Frame }, /* XDCAM Proxy C0023S01.mxf */ - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x05 }, CODEC_ID_MPEG2VIDEO, Frame }, /* D-10 30Mbps PAL */ - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x03 }, CODEC_ID_MPEG2VIDEO, Frame }, /* D-10 40Mbps PAL */ - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x01 }, CODEC_ID_MPEG2VIDEO, Frame }, /* D-10 50Mbps PAL */ - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x04,0x00 }, CODEC_ID_DVVIDEO, Frame }, /* DVCPRO50 PAL */ - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x02,0x00 }, CODEC_ID_DVVIDEO, Frame }, /* DVCPRO25 PAL */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x01,0x02,0x00 }, CODEC_ID_DVVIDEO, Frame }, /* DV25 IEC PAL */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x02,0x00 }, CODEC_ID_DVVIDEO, Frame }, /* DVCPRO25 PAL */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x04,0x00 }, CODEC_ID_DVVIDEO, Frame }, /* DVCPRO50 PAL */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, CODEC_ID_JPEG2000, Frame }, /* JPEG2000 Codestream */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x01,0x7F,0x00,0x00,0x00 }, CODEC_ID_RAWVIDEO, Frame }, /* Uncompressed */ /* SoundEssenceCompression */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, CODEC_ID_PCM_S16LE, Frame }, /* Uncompressed */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x7F,0x00,0x00,0x00 }, CODEC_ID_PCM_S16LE, Frame }, { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x02,0x02,0x01,0x7E,0x00,0x00,0x00 }, CODEC_ID_PCM_S16BE, Frame }, /* From Omneon MXF file */ - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x01,0x01,0x00 }, CODEC_ID_PCM_ALAW, Frame }, { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x04,0x04,0x02,0x02,0x02,0x03,0x01,0x01,0x00 }, CODEC_ID_PCM_ALAW, Frame }, /* XDCAM Proxy C0023S01.mxf */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x01,0x00 }, CODEC_ID_AC3, Frame }, { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x05,0x00 }, CODEC_ID_MP2, Frame }, /* MP2 or MP3 */ @@ -624,14 +637,29 @@ static const MXFCodecUL mxf_sound_essence_container_uls[] = { { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0xc0,0x01 }, CODEC_ID_MP2, Frame }, /* MPEG-ES Frame wrapped, 0xc0 MPA stream id */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0xc0,0x02 }, CODEC_ID_MP2, Clip }, /* MPEG-ES Clip wrapped, 0xc0 MPA stream id */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x05,0x01 }, CODEC_ID_PCM_S16BE, Frame }, /* D-10 Mapping 30Mbps PAL Extended Template */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x03,0x01 }, CODEC_ID_PCM_S16BE, Frame }, /* D-10 Mapping 40Mbps PAL Extended Template */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }, CODEC_ID_PCM_S16BE, Frame }, /* D-10 Mapping 50Mbps PAL Extended Template */ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, CODEC_ID_NONE, Frame }, }; +/* + * Match an uid independently of the version byte and up to len common bytes + * Returns: boolean + */ +static int mxf_match_uid(const UID key, const UID uid, int len) +{ + int i; + for (i = 0; i < len; i++) { + if (i != 7 && key[i] != uid[i]) + return 0; + } + return 1; +} + static const MXFCodecUL *mxf_get_codec_ul(const MXFCodecUL *uls, UID *uid) { while (uls->id != CODEC_ID_NONE) { - if(!memcmp(uls->uid, *uid, 16)) + if(mxf_match_uid(uls->uid, *uid, 16)) break; uls++; } @@ -641,7 +669,7 @@ static const MXFCodecUL *mxf_get_codec_ul(const MXFCodecUL *uls, UID *uid) static enum CodecType mxf_get_codec_type(const MXFDataDefinitionUL *uls, UID *uid) { while (uls->type != CODEC_TYPE_DATA) { - if(!memcmp(uls->uid, *uid, 16)) + if(mxf_match_uid(uls->uid, *uid, 16)) break; uls++; } @@ -811,7 +839,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) st->codec->width = descriptor->width; st->codec->height = descriptor->height; st->codec->bits_per_sample = descriptor->bits_per_sample; /* Uncompressed */ - st->need_parsing = 2; /* only parse headers */ + st->need_parsing = AVSTREAM_PARSE_HEADERS; } else if (st->codec->codec_type == CODEC_TYPE_AUDIO) { container_ul = mxf_get_codec_ul(mxf_sound_essence_container_uls, essence_container_ul); if (st->codec->codec_id == CODEC_ID_NONE) @@ -833,12 +861,12 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) if (descriptor->essence_container_ul[13] == 0x01) /* D-10 Mapping */ st->codec->channels = 8; /* force channels to 8 */ } else if (st->codec->codec_id == CODEC_ID_MP2) { - st->need_parsing = 1; + st->need_parsing = AVSTREAM_PARSE_FULL; } } if (container_ul && container_ul->wrapping == Clip) { dprintf(mxf->fc, "stream %d: clip wrapped essence\n", st->index); - st->need_parsing = 1; + st->need_parsing = AVSTREAM_PARSE_FULL; } } return 0; @@ -863,19 +891,6 @@ static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = { { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, NULL, 0, AnyType }, }; -static int mxf_read_sync(ByteIOContext *pb, const uint8_t *key, unsigned size) -{ - int i, b; - for (i = 0; i < size && !url_feof(pb); i++) { - b = get_byte(pb); - if (b == key[0]) - i = 0; - else if (b != key[i]) - i = -1; - } - return i == size; -} - static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, int (*read_child)(), int ctx_size, enum MXFMetadataSetType type) { ByteIOContext *pb = &mxf->fc->pb; @@ -907,7 +922,6 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) MXFContext *mxf = s->priv_data; KLVPacket klv; - mxf->sync_key = mxf_essence_element_key; if (!mxf_read_sync(&s->pb, mxf_header_partition_pack_key, 14)) { av_log(s, AV_LOG_ERROR, "could not find header partition pack key\n"); return -1; @@ -917,10 +931,8 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) while (!url_feof(&s->pb)) { const MXFMetadataReadTableEntry *metadata; - if (klv_read_packet(&klv, &s->pb) < 0) { - av_log(s, AV_LOG_ERROR, "error reading KLV packet\n"); + if (klv_read_packet(&klv, &s->pb) < 0) return -1; - } #ifdef DEBUG PRINT_KEY(s, "read header", klv.key); #endif @@ -990,11 +1002,10 @@ static int mxf_probe(AVProbeData *p) { return 0; } -/* rudimentary binary seek */ +/* rudimentary byte seek */ /* XXX: use MXF Index */ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags) { - MXFContext *mxf = s->priv_data; AVStream *st = s->streams[stream_index]; int64_t seconds; @@ -1004,11 +1015,6 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti sample_time = 0; seconds = av_rescale(sample_time, st->time_base.num, st->time_base.den); url_fseek(&s->pb, (s->bit_rate * seconds) >> 3, SEEK_SET); - if (!mxf_read_sync(&s->pb, mxf->sync_key, 12)) - return -1; - - /* found KLV key */ - url_fseek(&s->pb, -12, SEEK_CUR); av_update_cur_dts(s, st, sample_time); return 0; }