Mercurial > libavformat.hg
comparison mxf.c @ 2945:670945e9899d libavformat
support dynamically allocated local tags, used by encrypted files
author | bcoudurier |
---|---|
date | Sat, 19 Jan 2008 16:17:39 +0000 |
parents | 74bcc1d2eabb |
children | f90a2a21d5f6 |
comparison
equal
deleted
inserted
replaced
2944:74bcc1d2eabb | 2945:670945e9899d |
---|---|
138 int packages_count; | 138 int packages_count; |
139 MXFMetadataSet **metadata_sets; | 139 MXFMetadataSet **metadata_sets; |
140 int metadata_sets_count; | 140 int metadata_sets_count; |
141 AVFormatContext *fc; | 141 AVFormatContext *fc; |
142 struct AVAES *aesc; | 142 struct AVAES *aesc; |
143 uint8_t *local_tags; | |
144 int local_tags_count; | |
143 } MXFContext; | 145 } MXFContext; |
144 | 146 |
145 typedef struct { | 147 typedef struct { |
146 UID key; | 148 UID key; |
147 offset_t offset; | 149 offset_t offset; |
175 /* partial keys to match */ | 177 /* partial keys to match */ |
176 static const uint8_t mxf_header_partition_pack_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02 }; | 178 static const uint8_t mxf_header_partition_pack_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02 }; |
177 static const uint8_t mxf_essence_element_key[] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01 }; | 179 static const uint8_t mxf_essence_element_key[] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01 }; |
178 static const uint8_t mxf_klv_key[] = { 0x06,0x0e,0x2b,0x34 }; | 180 static const uint8_t mxf_klv_key[] = { 0x06,0x0e,0x2b,0x34 }; |
179 /* complete keys to match */ | 181 /* complete keys to match */ |
182 static const uint8_t mxf_crypto_context_uid[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x09,0x01,0x01,0x15,0x11,0x00,0x00,0x00,0x00 }; | |
183 static const uint8_t mxf_crypto_source_container_ul[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x02,0x02,0x00,0x00,0x00 }; | |
180 static const uint8_t mxf_encrypted_triplet_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x04,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x7e,0x01,0x00 }; | 184 static const uint8_t mxf_encrypted_triplet_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x04,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x7e,0x01,0x00 }; |
181 static const uint8_t mxf_encrypted_essence_container[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0b,0x01,0x00 }; | 185 static const uint8_t mxf_encrypted_essence_container[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0b,0x01,0x00 }; |
182 | 186 |
183 #define IS_KLV_KEY(x, y) (!memcmp(x, y, sizeof(y))) | 187 #define IS_KLV_KEY(x, y) (!memcmp(x, y, sizeof(y))) |
184 | 188 |
365 url_fskip(s->pb, klv.length); | 369 url_fskip(s->pb, klv.length); |
366 } | 370 } |
367 return AVERROR(EIO); | 371 return AVERROR(EIO); |
368 } | 372 } |
369 | 373 |
374 static int mxf_read_primer_pack(MXFContext *mxf) | |
375 { | |
376 ByteIOContext *pb = mxf->fc->pb; | |
377 int item_num = get_be32(pb); | |
378 int item_len = get_be32(pb); | |
379 | |
380 if (item_len != 18) { | |
381 av_log(mxf->fc, AV_LOG_ERROR, "unsupported primer pack item length\n"); | |
382 return -1; | |
383 } | |
384 if (item_num > UINT_MAX / item_len) | |
385 return -1; | |
386 mxf->local_tags_count = item_num; | |
387 mxf->local_tags = av_malloc(item_num*item_len); | |
388 if (!mxf->local_tags) | |
389 return -1; | |
390 get_buffer(pb, mxf->local_tags, item_num*item_len); | |
391 return 0; | |
392 } | |
393 | |
370 static int mxf_add_metadata_set(MXFContext *mxf, void *metadata_set) | 394 static int mxf_add_metadata_set(MXFContext *mxf, void *metadata_set) |
371 { | 395 { |
372 mxf->metadata_sets = av_realloc(mxf->metadata_sets, (mxf->metadata_sets_count + 1) * sizeof(*mxf->metadata_sets)); | 396 mxf->metadata_sets = av_realloc(mxf->metadata_sets, (mxf->metadata_sets_count + 1) * sizeof(*mxf->metadata_sets)); |
373 if (!mxf->metadata_sets) | 397 if (!mxf->metadata_sets) |
374 return -1; | 398 return -1; |
375 mxf->metadata_sets[mxf->metadata_sets_count] = metadata_set; | 399 mxf->metadata_sets[mxf->metadata_sets_count] = metadata_set; |
376 mxf->metadata_sets_count++; | 400 mxf->metadata_sets_count++; |
377 return 0; | 401 return 0; |
378 } | 402 } |
379 | 403 |
380 static int mxf_read_metadata_cryptographic_context(MXFCryptoContext *cryptocontext, ByteIOContext *pb, int tag) | 404 static int mxf_read_metadata_cryptographic_context(MXFCryptoContext *cryptocontext, ByteIOContext *pb, int tag, int size, UID uid) |
381 { | 405 { |
382 switch(tag) { | 406 if (size != 16) |
383 case 0xFFFE: | 407 return -1; |
408 if (IS_KLV_KEY(uid, mxf_crypto_context_uid)) | |
384 get_buffer(pb, cryptocontext->context_uid, 16); | 409 get_buffer(pb, cryptocontext->context_uid, 16); |
385 break; | 410 else if (IS_KLV_KEY(uid, mxf_crypto_source_container_ul)) |
386 case 0xFFFD: | |
387 get_buffer(pb, cryptocontext->source_container_ul, 16); | 411 get_buffer(pb, cryptocontext->source_container_ul, 16); |
388 break; | |
389 } | |
390 return 0; | 412 return 0; |
391 } | 413 } |
392 | 414 |
393 static int mxf_read_metadata_content_storage(MXFContext *mxf, ByteIOContext *pb, int tag) | 415 static int mxf_read_metadata_content_storage(MXFContext *mxf, ByteIOContext *pb, int tag) |
394 { | 416 { |
874 } | 896 } |
875 return 0; | 897 return 0; |
876 } | 898 } |
877 | 899 |
878 static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = { | 900 static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = { |
901 { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x05,0x01,0x00 }, mxf_read_primer_pack }, | |
879 { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x18,0x00 }, mxf_read_metadata_content_storage, 0, AnyType }, | 902 { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x18,0x00 }, mxf_read_metadata_content_storage, 0, AnyType }, |
880 { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x37,0x00 }, mxf_read_metadata_source_package, sizeof(MXFPackage), SourcePackage }, | 903 { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x37,0x00 }, mxf_read_metadata_source_package, sizeof(MXFPackage), SourcePackage }, |
881 { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x36,0x00 }, mxf_read_metadata_material_package, sizeof(MXFPackage), MaterialPackage }, | 904 { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x36,0x00 }, mxf_read_metadata_material_package, sizeof(MXFPackage), MaterialPackage }, |
882 { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0F,0x00 }, mxf_read_metadata_sequence, sizeof(MXFSequence), Sequence }, | 905 { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0F,0x00 }, mxf_read_metadata_sequence, sizeof(MXFSequence), Sequence }, |
883 { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x11,0x00 }, mxf_read_metadata_source_clip, sizeof(MXFStructuralComponent), SourceClip }, | 906 { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x11,0x00 }, mxf_read_metadata_source_clip, sizeof(MXFStructuralComponent), SourceClip }, |
904 return -1; | 927 return -1; |
905 while (url_ftell(pb) + 4 < klv_end) { | 928 while (url_ftell(pb) + 4 < klv_end) { |
906 int tag = get_be16(pb); | 929 int tag = get_be16(pb); |
907 int size = get_be16(pb); /* KLV specified by 0x53 */ | 930 int size = get_be16(pb); /* KLV specified by 0x53 */ |
908 uint64_t next= url_ftell(pb) + size; | 931 uint64_t next= url_ftell(pb) + size; |
932 UID uid; | |
909 | 933 |
910 if (!size) { /* ignore empty tag, needed for some files with empty UMID tag */ | 934 if (!size) { /* ignore empty tag, needed for some files with empty UMID tag */ |
911 av_log(mxf->fc, AV_LOG_ERROR, "local tag 0x%04X with 0 size\n", tag); | 935 av_log(mxf->fc, AV_LOG_ERROR, "local tag 0x%04X with 0 size\n", tag); |
912 continue; | 936 continue; |
913 } | 937 } |
938 if (tag > 0x7FFF) { /* dynamic tag */ | |
939 int i; | |
940 for (i = 0; i < mxf->local_tags_count; i++) { | |
941 int local_tag = AV_RB16(mxf->local_tags+i*18); | |
942 if (local_tag == tag) { | |
943 memcpy(uid, mxf->local_tags+i*18+2, 16); | |
944 dprintf(mxf->fc, "local tag 0x%04X\n", local_tag); | |
945 #ifdef DEBUG | |
946 PRINT_KEY(mxf->fc, "uid", uid); | |
947 #endif | |
948 } | |
949 } | |
950 } | |
914 if(ctx_size && tag == 0x3C0A) | 951 if(ctx_size && tag == 0x3C0A) |
915 get_buffer(pb, ctx->uid, 16); | 952 get_buffer(pb, ctx->uid, 16); |
916 else | 953 else |
917 read_child(ctx, pb, tag, size); | 954 read_child(ctx, pb, tag, size, uid); |
918 | 955 |
919 url_fseek(pb, next, SEEK_SET); | 956 url_fseek(pb, next, SEEK_SET); |
920 } | 957 } |
921 if (ctx_size) ctx->type = type; | 958 if (ctx_size) ctx->type = type; |
922 return ctx_size ? mxf_add_metadata_set(mxf, ctx) : 0; | 959 return ctx_size ? mxf_add_metadata_set(mxf, ctx) : 0; |
948 break; | 985 break; |
949 } | 986 } |
950 | 987 |
951 for (metadata = mxf_metadata_read_table; metadata->read; metadata++) { | 988 for (metadata = mxf_metadata_read_table; metadata->read; metadata++) { |
952 if (IS_KLV_KEY(klv.key, metadata->key)) { | 989 if (IS_KLV_KEY(klv.key, metadata->key)) { |
953 if (mxf_read_local_tags(mxf, &klv, metadata->read, metadata->ctx_size, metadata->type) < 0) { | 990 int (*read)() = klv.key[5] == 0x53 ? mxf_read_local_tags : metadata->read; |
991 if (read(mxf, &klv, metadata->read, metadata->ctx_size, metadata->type) < 0) { | |
954 av_log(s, AV_LOG_ERROR, "error reading header metadata\n"); | 992 av_log(s, AV_LOG_ERROR, "error reading header metadata\n"); |
955 return -1; | 993 return -1; |
956 } | 994 } |
957 break; | 995 break; |
958 } | 996 } |
986 } | 1024 } |
987 av_freep(&mxf->metadata_sets[i]); | 1025 av_freep(&mxf->metadata_sets[i]); |
988 } | 1026 } |
989 av_freep(&mxf->metadata_sets); | 1027 av_freep(&mxf->metadata_sets); |
990 av_freep(&mxf->aesc); | 1028 av_freep(&mxf->aesc); |
1029 av_freep(&mxf->local_tags); | |
991 return 0; | 1030 return 0; |
992 } | 1031 } |
993 | 1032 |
994 static int mxf_probe(AVProbeData *p) { | 1033 static int mxf_probe(AVProbeData *p) { |
995 uint8_t *bufp = p->buf; | 1034 uint8_t *bufp = p->buf; |