int mxf_register_set_items(MXFHeaderMetadata* headerMetadata, const mxfKey* key) { MXFSetDef* setDef; MXFItemDef* itemDef; MXFListIterator iter; mxfLocalTag tag; CHK_ORET(mxf_find_set_def(headerMetadata->dataModel, key, &setDef)); /* go though the set def and parents and register the items */ while (setDef != NULL) { mxf_initialise_list_iter(&iter, &setDef->itemDefs); while (mxf_next_list_iter_element(&iter)) { itemDef = (MXFItemDef*)mxf_get_iter_element(&iter); CHK_ORET(mxf_register_primer_entry(headerMetadata->primerPack, (const mxfUID*)&itemDef->key, itemDef->localTag, &tag)); } setDef = setDef->parentSetDef; } return 1; }
int mxf_write_rip(MXFFile *mxfFile, MXFFilePartitions *partitions) { uint32_t numPartitions; uint64_t len; uint8_t llen; MXFListIterator iter; numPartitions = (uint32_t)mxf_get_list_length(partitions); len = (4 + 8) * numPartitions + 4; CHK_ORET(mxf_write_k(mxfFile, &g_RandomIndexPack_key)); CHK_ORET((llen = mxf_write_l(mxfFile, len)) != 0); mxf_initialise_list_iter(&iter, partitions); while (mxf_next_list_iter_element(&iter)) { MXFPartition *partition = (MXFPartition*)mxf_get_iter_element(&iter); CHK_ORET(mxf_write_uint32(mxfFile, partition->bodySID)); CHK_ORET(mxf_write_uint64(mxfFile, partition->thisPartition)); } CHK_ORET(mxf_write_uint32(mxfFile, (uint32_t)(16 + llen + len))); return 1; }
/* note: keep in sync with mxf_write_set */ uint64_t mxf_get_set_size(MXFFile* mxfFile, MXFMetadataSet* set) { MXFListIterator iter; uint64_t len; uint8_t llen; if (set->fixedSpaceAllocation > 0) { return set->fixedSpaceAllocation; } len = 0; mxf_initialise_list_iter(&iter, &set->items); while (mxf_next_list_iter_element(&iter)) { len += ((MXFMetadataItem*)mxf_get_iter_element(&iter))->length + 4; } llen = mxf_get_llen(mxfFile, len); if (llen < 4) { /* spec says preferred 4-byte BER encoded len for sets */ llen = 4; } return mxfKey_extlen + len + llen; }
void mxf_update_partitions_in_memory(MXFFilePartitions *partitions) { MXFPartition *previousPartition; MXFPartition *lastPartition; MXFListIterator iter; int haveFooter; /* check if anything there to update */ if (mxf_get_list_length(partitions) == 0) { return; } /* update partition packs with previousPartition and footerPartition (if present) offsets */ lastPartition = (MXFPartition*)mxf_get_last_list_element(partitions); haveFooter = mxf_is_footer_partition_pack(&lastPartition->key); previousPartition = NULL; mxf_initialise_list_iter(&iter, partitions); while (mxf_next_list_iter_element(&iter)) { MXFPartition *partition = (MXFPartition*)mxf_get_iter_element(&iter); if (previousPartition != NULL) { partition->previousPartition = previousPartition->thisPartition; } if (haveFooter) { partition->footerPartition = lastPartition->thisPartition; } previousPartition = partition; } }
/* note: keep in sync with mxf_get_set_len */ int mxf_write_set(MXFFile* mxfFile, MXFMetadataSet* set) { MXFListIterator iter; uint64_t setLen = 0; uint64_t setSize = 0; mxf_initialise_list_iter(&iter, &set->items); while (mxf_next_list_iter_element(&iter)) { setLen += ((MXFMetadataItem*)mxf_get_iter_element(&iter))->length + 4; } if (mxf_get_llen(mxfFile, setLen) <= 4) { /* spec says preferred 4-byte BER encoded len for sets */ CHK_ORET(mxf_write_fixed_kl(mxfFile, &set->key, 4, setLen)); setSize = mxfKey_extlen + 4 + setLen; } else { CHK_ORET(mxf_write_kl(mxfFile, &set->key, setLen)); setSize = mxfKey_extlen + mxf_get_llen(mxfFile, setLen) + setLen; } mxf_initialise_list_iter(&iter, &set->items); while (mxf_next_list_iter_element(&iter)) { CHK_ORET(mxf_write_item(mxfFile, (MXFMetadataItem*)mxf_get_iter_element(&iter))); } if (set->fixedSpaceAllocation > 0) { /* check that we can achieve the fixed size, possibly using a filler */ CHK_ORET(setSize == set->fixedSpaceAllocation || (setSize < set->fixedSpaceAllocation && setSize + mxf_get_min_llen(mxfFile) + mxfKey_extlen <= set->fixedSpaceAllocation)); if (setSize < set->fixedSpaceAllocation) { /* add filler */ CHK_ORET(mxf_write_fill(mxfFile, (uint32_t)(set->fixedSpaceAllocation - setSize))); } } return 1; }
/* this will be faster is we de-reference multiple sets in the same order as they were written */ int mxf_dereference_s(MXFHeaderMetadata* headerMetadata, MXFListIterator* setsIter, const mxfUUID* uuid, MXFMetadataSet** set) { MXFMetadataSet* setInList; long startIndex = mxf_get_list_iter_index(setsIter); /* try find it at the previous position in the list */ if (startIndex >= 0) { setInList = (MXFMetadataSet*)mxf_get_iter_element(setsIter); if (mxf_equals_uuid(uuid, &setInList->instanceUID)) { *set = setInList; return 1; } } /* try find it starting from the previous position in the list */ while (mxf_next_list_iter_element(setsIter)) { setInList = (MXFMetadataSet*)mxf_get_iter_element(setsIter); if (mxf_equals_uuid(uuid, &setInList->instanceUID)) { *set = setInList; return 1; } } /* go back to beginning and try find it before the previous position in the list */ initialise_sets_iter(headerMetadata, setsIter); while (mxf_next_list_iter_element(setsIter) && mxf_get_list_iter_index(setsIter) < startIndex) { setInList = (MXFMetadataSet*)mxf_get_iter_element(setsIter); if (mxf_equals_uuid(uuid, &setInList->instanceUID)) { *set = setInList; return 1; } } return 0; }
void initialise_timecode_index_searcher(TimecodeIndex* index, TimecodeIndexSearcher* searcher) { mxf_initialise_list_iter(&searcher->indexArrayIter, &index->indexArrays); searcher->elementNum = 0; searcher->elementOffset = 0; searcher->position = 0; searcher->index = index; searcher->atEnd = !mxf_next_list_iter_element(&searcher->indexArrayIter); searcher->beforeStart = 1; }
void mxf_get_header_metadata_size(MXFFile* mxfFile, MXFHeaderMetadata* headerMetadata, uint64_t* size) { MXFListIterator iter; uint64_t primerSize; mxf_get_primer_pack_size(mxfFile, headerMetadata->primerPack, &primerSize); *size = primerSize; mxf_initialise_list_iter(&iter, &headerMetadata->sets); while (mxf_next_list_iter_element(&iter)) { *size += mxf_get_set_size(mxfFile, (MXFMetadataSet*)mxf_get_iter_element(&iter)); } }
/* Note: positions file pointer at end of file */ int mxf_rewrite_partitions(MXFFile *mxfFile, MXFFilePartitions *partitions) { MXFListIterator iter; mxf_initialise_list_iter(&iter, partitions); while (mxf_next_list_iter_element(&iter)) { MXFPartition *partition = (MXFPartition*)mxf_get_iter_element(&iter); CHK_ORET(mxf_file_seek(mxfFile, (int64_t)partition->thisPartition + mxf_get_runin_len(mxfFile), SEEK_SET)); CHK_ORET(mxf_write_partition(mxfFile, partition)); } CHK_ORET(mxf_file_seek(mxfFile, 0, SEEK_END)); return 1; }
static int find_weakref_target_instance_uid(MXFList* mapList, const mxfUL* targetIdentification, mxfUUID* instanceUID) { MXFListIterator iter; mxf_initialise_list_iter(&iter, mapList); while (mxf_next_list_iter_element(&iter)) { MetaDefData* data = (MetaDefData*)mxf_get_iter_element(&iter); if (mxf_equals_ul(&data->identification, targetIdentification)) { *instanceUID = data->instanceUID; return 1; } } return 0; }
static int move_timecode_index_searcher_to_next_element(TimecodeIndexSearcher* searcher) { TimecodeIndexArray* indexArray; TimecodeIndexElement* arrayElement; TimecodeIndexSearcher searcherCopy = *searcher; if (searcher->atEnd) { return 0; } indexArray = (TimecodeIndexArray*)mxf_get_iter_element(&searcher->indexArrayIter); arrayElement = &indexArray->elements[searcher->elementNum]; if (searcher->elementNum + 1 < indexArray->numElements) { /* move to next element in array */ searcher->position += arrayElement->duration - searcher->elementOffset; searcher->elementOffset = 0; searcher->elementNum++; return 1; } else if (indexArray->numElements == searcher->index->arraySize) { /* move to next array in list */ searcher->position += arrayElement->duration - searcher->elementOffset; searcher->elementOffset = 0; searcher->elementNum = 0; searcher->atEnd = !mxf_next_list_iter_element(&searcher->indexArrayIter); if (!searcher->atEnd) { return 1; } /* else at end of index */ } /* else at end of index */ *searcher = searcherCopy; return 0; }
int mxf_initialise_with_partition(const MXFPartition *sourcePartition, MXFPartition *partition) { MXFListIterator iter; mxf_initialise_partition(partition); partition->key = g_Null_Key; partition->majorVersion = sourcePartition->majorVersion; partition->minorVersion = sourcePartition->minorVersion; partition->kagSize = sourcePartition->kagSize; partition->operationalPattern = sourcePartition->operationalPattern; mxf_initialise_list_iter(&iter, &sourcePartition->essenceContainers); while (mxf_next_list_iter_element(&iter)) { CHK_ORET(mxf_append_partition_esscont_label(partition, (mxfUL*)mxf_get_iter_element(&iter))); } return 1; }
int mxf_write_header_sets(MXFFile* mxfFile, MXFHeaderMetadata* headerMetadata) { MXFListIterator iter; MXFMetadataSet* prefaceSet; /* must write the Preface set first (and there must be a Preface set) */ CHK_ORET(mxf_find_singular_set_by_key(headerMetadata, &MXF_SET_K(Preface), &prefaceSet)); CHK_ORET(mxf_write_set(mxfFile, prefaceSet)); mxf_initialise_list_iter(&iter, &headerMetadata->sets); while (mxf_next_list_iter_element(&iter)) { MXFMetadataSet* set = (MXFMetadataSet*)mxf_get_iter_element(&iter); if (!mxf_equals_key(&set->key, &MXF_SET_K(Preface))) { CHK_ORET(mxf_write_set(mxfFile, set)); } } return 1; }
int mxf_write_partition(MXFFile *mxfFile, MXFPartition *partition) { uint32_t essenceContainerLen = (uint32_t)mxf_get_list_length(&partition->essenceContainers); uint64_t packLen = 88 + mxfUL_extlen * essenceContainerLen; int64_t filePos; MXFListIterator iter; CHK_ORET((filePos = mxf_file_tell(mxfFile)) >= 0); partition->thisPartition = filePos - mxf_get_runin_len(mxfFile); if (mxf_is_footer_partition_pack(&partition->key)) { partition->footerPartition = partition->thisPartition; } CHK_ORET(mxf_write_kl(mxfFile, &partition->key, packLen)); CHK_ORET(mxf_write_uint16(mxfFile, partition->majorVersion)); CHK_ORET(mxf_write_uint16(mxfFile, partition->minorVersion)); CHK_ORET(mxf_write_uint32(mxfFile, partition->kagSize)); CHK_ORET(mxf_write_uint64(mxfFile, partition->thisPartition)); CHK_ORET(mxf_write_uint64(mxfFile, partition->previousPartition)); CHK_ORET(mxf_write_uint64(mxfFile, partition->footerPartition)); CHK_ORET(mxf_write_uint64(mxfFile, partition->headerByteCount)); CHK_ORET(mxf_write_uint64(mxfFile, partition->indexByteCount)); CHK_ORET(mxf_write_uint32(mxfFile, partition->indexSID)); CHK_ORET(mxf_write_uint64(mxfFile, partition->bodyOffset)); CHK_ORET(mxf_write_uint32(mxfFile, partition->bodySID)); CHK_ORET(mxf_write_ul(mxfFile, &partition->operationalPattern)); CHK_ORET(mxf_write_batch_header(mxfFile, essenceContainerLen, mxfUL_extlen)); mxf_initialise_list_iter(&iter, &partition->essenceContainers); while (mxf_next_list_iter_element(&iter)) { CHK_ORET(mxf_write_ul(mxfFile, (mxfUL*)mxf_get_iter_element(&iter))); } return 1; }
int mxf_find_set_by_key(MXFHeaderMetadata* headerMetadata, const mxfKey* key, MXFList** setList) { MXFListIterator iter; MXFList* newList = NULL; CHK_ORET(mxf_create_list(&newList, NULL)); /* free func == NULL because newList doesn't own the data */ mxf_initialise_list_iter(&iter, &headerMetadata->sets); while (mxf_next_list_iter_element(&iter)) { MXFMetadataSet* set = (MXFMetadataSet*)mxf_get_iter_element(&iter); if (mxf_equals_key(key, &set->key)) { CHK_OFAIL(mxf_append_list_element(newList, (void*)set)); } } *setList = newList; return 1; fail: mxf_free_list(&newList); return 0; }
int mxf_app_get_info(MXFHeaderMetadata *headerMetadata, ArchiveMXFInfo *info) { MXFList *list = NULL; MXFListIterator iter; MXFArrayItemIterator arrayIter; uint8_t *arrayElement; uint32_t arrayElementLen; mxfUTF16Char *tempWString = NULL; MXFList *nameList = NULL; MXFList *valueList = NULL; MXFMetadataSet *identSet; MXFMetadataSet *fileSourcePackageSet; MXFMetadataSet *sourcePackageSet; MXFMetadataSet *descriptorSet; MXFMetadataSet *locatorSet; MXFMetadataSet *materialPackageSet; MXFMetadataSet *prefaceSet; memset(info, 0, sizeof(*info)); /* read event counts in Preface */ CHK_ORET(mxf_find_singular_set_by_key(headerMetadata, &MXF_SET_K(Preface), &prefaceSet)); #define GET_EVENT_COUNT(name, var) \ if (mxf_have_item(prefaceSet, &MXF_ITEM_K(Preface, name))) \ CHK_ORET(mxf_get_uint32_item(prefaceSet, &MXF_ITEM_K(Preface, name), &var)); GET_EVENT_COUNT(APP_VTRErrorCount, info->vtrErrorCount) GET_EVENT_COUNT(APP_PSEFailureCount, info->pseFailureCount) GET_EVENT_COUNT(APP_DigiBetaDropoutCount, info->digibetaDropoutCount) GET_EVENT_COUNT(APP_TimecodeBreakCount, info->timecodeBreakCount) /* if metadata only then only try reading infax user comments */ if (is_metadata_only_file(headerMetadata, &materialPackageSet)) { if (mxf_avid_read_string_user_comments(materialPackageSet, &nameList, &valueList)) { info->haveSourceInfaxData = parse_infax_user_comments(nameList, valueList, &info->sourceInfaxData); mxf_free_list(&nameList); mxf_free_list(&valueList); } return 1; } /* Creation timestamp identification info */ CHK_OFAIL(mxf_find_set_by_key(headerMetadata, &MXF_SET_K(Identification), &list)); mxf_initialise_list_iter(&iter, list); if (mxf_next_list_iter_element(&iter)) { identSet = (MXFMetadataSet*)mxf_get_iter_element(&iter); CHK_OFAIL(mxf_get_timestamp_item(identSet, &MXF_ITEM_K(Identification, ModificationDate), &info->creationDate)); } mxf_free_list(&list); /* LTO Infax data */ CHK_OFAIL(mxf_uu_get_top_file_package(headerMetadata, &fileSourcePackageSet)); info->haveLTOInfaxData = archive_mxf_get_package_infax_data(headerMetadata, fileSourcePackageSet, &info->ltoInfaxData); /* original filename */ CHK_OFAIL(mxf_get_strongref_item(fileSourcePackageSet, &MXF_ITEM_K(SourcePackage, Descriptor), &descriptorSet)); if (mxf_have_item(descriptorSet, &MXF_ITEM_K(GenericDescriptor, Locators))) { CHK_OFAIL(mxf_initialise_array_item_iterator(descriptorSet, &MXF_ITEM_K(GenericDescriptor, Locators), &arrayIter)); while (mxf_next_array_item_element(&arrayIter, &arrayElement, &arrayElementLen)) { CHK_OFAIL(mxf_get_strongref(headerMetadata, arrayElement, &locatorSet)); if (mxf_is_subclass_of(headerMetadata->dataModel, &locatorSet->key, &MXF_SET_K(NetworkLocator))) { CHK_OFAIL(mxf_uu_get_utf16string_item(locatorSet, &MXF_ITEM_K(NetworkLocator, URLString), &tempWString)); CHK_OFAIL(mxf_utf16_to_utf8(info->filename, tempWString, sizeof(info->filename)) != (size_t)(-1)); info->filename[sizeof(info->filename) - 1] = '\0'; SAFE_FREE(tempWString); break; } } } /* source Infax data */ CHK_OFAIL(mxf_find_set_by_key(headerMetadata, &MXF_SET_K(SourcePackage), &list)); mxf_initialise_list_iter(&iter, list); while (mxf_next_list_iter_element(&iter)) { sourcePackageSet = (MXFMetadataSet*)(mxf_get_iter_element(&iter)); /* it is the tape SourcePackage if it has a TapeDescriptor */ CHK_OFAIL(mxf_get_strongref_item(sourcePackageSet, &MXF_ITEM_K(SourcePackage, Descriptor), &descriptorSet)); if (mxf_is_subclass_of(headerMetadata->dataModel, &descriptorSet->key, &MXF_SET_K(TapeDescriptor))) { info->haveSourceInfaxData = archive_mxf_get_package_infax_data(headerMetadata, sourcePackageSet, &info->sourceInfaxData); break; } } mxf_free_list(&list); /* try alternative locations for source Infax data */ if (!info->haveSourceInfaxData) { /* framework in the material package */ CHK_OFAIL(mxf_find_singular_set_by_key(headerMetadata, &MXF_SET_K(MaterialPackage), &materialPackageSet)); info->haveSourceInfaxData = archive_mxf_get_package_infax_data(headerMetadata, materialPackageSet, &info->sourceInfaxData); /* UserComments in the MaterialPackage */ if (!info->haveSourceInfaxData) { if (mxf_avid_read_string_user_comments(materialPackageSet, &nameList, &valueList)) { info->haveSourceInfaxData = parse_infax_user_comments(nameList, valueList, &info->sourceInfaxData); mxf_free_list(&nameList); mxf_free_list(&valueList); } } } return info->haveSourceInfaxData; fail: SAFE_FREE(tempWString); mxf_free_list(&list); mxf_free_list(&nameList); mxf_free_list(&valueList); return 0; }
int mxf_avid_create_default_metadictionary(MXFHeaderMetadata* headerMetadata, MXFMetadataSet** metaDictSet) { MXFMetadataSet* newMetaDictSet = NULL; MXFMetadataSet* classDefSet; MXFMetadataSet* set; mxfUL label1; mxfUL label2; mxfUL label3; MXFList classMetaDefList; MXFList typeMetaDefList; MXFList classWeakRefList; MXFList typeWeakRefList; MXFMetadataItem* item; MXFListIterator iter; mxfUUID targetInstanceUID; int arrayIndex; mxf_initialise_list(&classMetaDefList, free); mxf_initialise_list(&typeMetaDefList, free); mxf_initialise_list(&classWeakRefList, free); mxf_initialise_list(&typeWeakRefList, free); CHK_OFAIL(mxf_avid_create_metadictionary(headerMetadata, &newMetaDictSet)); /* register meta-definitions */ /* set temporary weak reference values which will be replaced later */ #define LABEL(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15) \ bounce_label(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, &label1) #define LABEL_2(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15) \ bounce_label(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, &label2) #define WEAKREF(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15) \ bounce_label(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, &label3) #define CLASS_DEF(id, name, description, parentId, isConcrete) \ CHK_OFAIL(mxf_avid_create_classdef(newMetaDictSet, id, name, description, parentId, isConcrete, &classDefSet)); \ CHK_OFAIL(mxf_get_item(classDefSet, &MXF_ITEM_K(ClassDefinition, ParentClass), &item)); \ CHK_OFAIL(add_weakref_to_list(&classWeakRefList, item, -1, parentId)); \ CHK_OFAIL(add_metadef_to_list(&classMetaDefList, id, &classDefSet->instanceUID)); #define PROPERTY_DEF(id, name, description, typeId, isOptional, localId, isUniqueId) \ CHK_OFAIL(mxf_avid_create_propertydef(classDefSet->headerMetadata->primerPack, classDefSet, \ id, name, description, typeId, isOptional, localId, isUniqueId, &set)); #define CHARACTER_DEF(id, name, description) \ CHK_OFAIL(mxf_avid_create_typedef_char(newMetaDictSet, id, name, description, &set)); \ CHK_OFAIL(add_metadef_to_list(&typeMetaDefList, id, &set->instanceUID)); #define ENUM_DEF(id, name, description, typeId) \ CHK_OFAIL(mxf_avid_create_typedef_enum(newMetaDictSet, id, name, description, typeId, &set)); \ CHK_OFAIL(mxf_get_item(set, &MXF_ITEM_K(TypeDefinitionEnumeration, Type), &item)); \ CHK_OFAIL(add_weakref_to_list(&typeWeakRefList, item, -1, typeId)); \ CHK_OFAIL(add_metadef_to_list(&typeMetaDefList, id, &set->instanceUID)); #define ENUM_ELEMENT(name, value) \ CHK_OFAIL(mxf_avid_add_typedef_enum_element(set, name, value)); #define EXTENUM_DEF(id, name, description) \ CHK_OFAIL(mxf_avid_create_typedef_extenum(newMetaDictSet, id, name, description, &set)); \ CHK_OFAIL(add_metadef_to_list(&typeMetaDefList, id, &set->instanceUID)); #define EXTENUM_ELEMENT(name, value) \ CHK_OFAIL(mxf_avid_add_typedef_extenum_element(set, name, value)); #define FIXEDARRAY_DEF(id, name, description, typeId, count) \ CHK_OFAIL(mxf_avid_create_typedef_fixedarray(newMetaDictSet, id, name, description, typeId, count, &set)); \ CHK_OFAIL(mxf_get_item(set, &MXF_ITEM_K(TypeDefinitionFixedArray, ElementType), &item)); \ CHK_OFAIL(add_weakref_to_list(&typeWeakRefList, item, -1, typeId)); \ CHK_OFAIL(add_metadef_to_list(&typeMetaDefList, id, &set->instanceUID)); #define INDIRECT_DEF(id, name, description) \ CHK_OFAIL(mxf_avid_create_typedef_indirect(newMetaDictSet, id, name, description, &set)); \ CHK_OFAIL(add_metadef_to_list(&typeMetaDefList, id, &set->instanceUID)); #define INTEGER_DEF(id, name, description, size, isSigned) \ CHK_OFAIL(mxf_avid_create_typedef_integer(newMetaDictSet, id, name, description, size, isSigned, &set)); \ CHK_OFAIL(add_metadef_to_list(&typeMetaDefList, id, &set->instanceUID)); #define OPAQUE_DEF(id, name, description) \ CHK_OFAIL(mxf_avid_create_typedef_opaque(newMetaDictSet, id, name, description, &set)); \ CHK_OFAIL(add_metadef_to_list(&typeMetaDefList, id, &set->instanceUID)); #define RENAME_DEF(id, name, description, typeId) \ CHK_OFAIL(mxf_avid_create_typedef_rename(newMetaDictSet, id, name, description, typeId, &set)); \ CHK_OFAIL(mxf_get_item(set, &MXF_ITEM_K(TypeDefinitionRename, RenamedType), &item)); \ CHK_OFAIL(add_weakref_to_list(&typeWeakRefList, item, -1, typeId)); \ CHK_OFAIL(add_metadef_to_list(&typeMetaDefList, id, &set->instanceUID)); #define RECORD_DEF(id, name, description) \ CHK_OFAIL(mxf_avid_create_typedef_record(newMetaDictSet, id, name, description, &set)); \ CHK_OFAIL(add_metadef_to_list(&typeMetaDefList, id, &set->instanceUID)); \ arrayIndex = 0; #define RECORD_MEMBER(name, type) \ CHK_OFAIL(mxf_avid_add_typedef_record_member(set, name, type)); \ CHK_OFAIL(mxf_get_item(set, &MXF_ITEM_K(TypeDefinitionRecord, MemberTypes), &item)); \ CHK_OFAIL(add_weakref_to_list(&typeWeakRefList, item, arrayIndex, type)); \ arrayIndex++; #define SET_DEF(id, name, description, typeId) \ CHK_OFAIL(mxf_avid_create_typedef_set(newMetaDictSet, id, name, description, typeId, &set)); \ CHK_OFAIL(mxf_get_item(set, &MXF_ITEM_K(TypeDefinitionSet, ElementType), &item)); \ CHK_OFAIL(add_weakref_to_list(&typeWeakRefList, item, -1, typeId)); \ CHK_OFAIL(add_metadef_to_list(&typeMetaDefList, id, &set->instanceUID)); #define STREAM_DEF(id, name, description) \ CHK_OFAIL(mxf_avid_create_typedef_stream(newMetaDictSet, id, name, description, &set)); \ CHK_OFAIL(add_metadef_to_list(&typeMetaDefList, id, &set->instanceUID)); #define STRING_DEF(id, name, description, typeId) \ CHK_OFAIL(mxf_avid_create_typedef_string(newMetaDictSet, id, name, description, typeId, &set)); \ CHK_OFAIL(mxf_get_item(set, &MXF_ITEM_K(TypeDefinitionString, ElementType), &item)); \ CHK_OFAIL(add_weakref_to_list(&typeWeakRefList, item, -1, typeId)); \ CHK_OFAIL(add_metadef_to_list(&typeMetaDefList, id, &set->instanceUID)); #define STRONGOBJREF_DEF(id, name, description, refTypeId) \ CHK_OFAIL(mxf_avid_create_typedef_strongref(newMetaDictSet, id, name, description, refTypeId, &set)); \ CHK_OFAIL(mxf_get_item(set, &MXF_ITEM_K(TypeDefinitionStrongObjectReference, ReferencedType), &item)); \ CHK_OFAIL(add_weakref_to_list(&classWeakRefList, item, -1, refTypeId)); \ CHK_OFAIL(add_metadef_to_list(&typeMetaDefList, id, &set->instanceUID)); #define WEAKOBJREF_DEF(id, name, description, refTypeId) \ CHK_OFAIL(mxf_avid_create_typedef_weakref(newMetaDictSet, id, name, description, refTypeId, &set)); \ CHK_OFAIL(mxf_get_item(set, &MXF_ITEM_K(TypeDefinitionWeakObjectReference, ReferencedType), &item)); \ CHK_OFAIL(add_weakref_to_list(&classWeakRefList, item, -1, refTypeId)); \ CHK_OFAIL(add_metadef_to_list(&typeMetaDefList, id, &set->instanceUID)); #define WEAKOBJREF_TARGET_ELEMENT(id) \ CHK_OFAIL(mxf_avid_add_typedef_weakref_target(set, id)); #define VARARRAY_DEF(id, name, description, typeId) \ CHK_OFAIL(mxf_avid_create_typedef_vararray(newMetaDictSet, id, name, description, typeId, &set)); \ CHK_OFAIL(mxf_get_item(set, &MXF_ITEM_K(TypeDefinitionVariableArray, ElementType), &item)); \ CHK_OFAIL(add_weakref_to_list(&typeWeakRefList, item, -1, typeId)); \ CHK_OFAIL(add_metadef_to_list(&typeMetaDefList, id, &set->instanceUID)); #include "mxf_avid_metadictionary_data.h" /* de-reference class and type weak references and replace weak reference value with instanceUID of target set */ mxf_initialise_list_iter(&iter, &classWeakRefList); while (mxf_next_list_iter_element(&iter)) { WeakRefData* data = (WeakRefData*)mxf_get_iter_element(&iter); CHK_OFAIL(find_weakref_target_instance_uid(&classMetaDefList, &data->targetIdentification, &targetInstanceUID)); if (data->arrayIndex >= 0) { mxf_set_uuid(&targetInstanceUID, get_array_element(data->item, data->arrayIndex)); } else { mxf_set_uuid(&targetInstanceUID, data->item->value); } } mxf_initialise_list_iter(&iter, &typeWeakRefList); while (mxf_next_list_iter_element(&iter)) { WeakRefData* data = (WeakRefData*)mxf_get_iter_element(&iter); CHK_OFAIL(find_weakref_target_instance_uid(&typeMetaDefList, &data->targetIdentification, &targetInstanceUID)); if (data->arrayIndex >= 0) { mxf_set_uuid(&targetInstanceUID, get_array_element(data->item, data->arrayIndex)); } else { mxf_set_uuid(&targetInstanceUID, data->item->value); } } mxf_clear_list(&classMetaDefList); mxf_clear_list(&typeMetaDefList); mxf_clear_list(&classWeakRefList); mxf_clear_list(&typeWeakRefList); *metaDictSet = newMetaDictSet; return 1; fail: if (newMetaDictSet != NULL) { mxf_remove_set(headerMetadata, newMetaDictSet); mxf_free_set(&newMetaDictSet); } mxf_clear_list(&classMetaDefList); mxf_clear_list(&typeMetaDefList); mxf_clear_list(&classWeakRefList); mxf_clear_list(&typeWeakRefList); return 0; }
int test_read(const char *filename) { MXFFile *mxfFile = NULL; MXFFilePartitions partitions; MXFPartition *headerPartition = NULL; MXFPartition *bodyPartition1 = NULL; MXFPartition *bodyPartition2 = NULL; MXFPartition *footerPartition = NULL; MXFListIterator iter; mxfKey key; uint8_t llen; uint64_t len; int i; MXFRIP rip; if (!mxf_disk_file_open_read(filename, &mxfFile)) { mxf_log_error("Failed to open '%s'" LOG_LOC_FORMAT, filename, LOG_LOC_PARAMS); return 0; } mxf_initialise_file_partitions(&partitions); /* TEST */ /* read RIP */ CHK_OFAIL(mxf_read_rip(mxfFile, &rip)); CHK_OFAIL(mxf_get_list_length(&rip.entries) == 4); CHK_OFAIL(mxf_file_seek(mxfFile, 0, SEEK_SET)); mxf_initialise_list_iter(&iter, &rip.entries); i = 0; while (mxf_next_list_iter_element(&iter)) { MXFRIPEntry *entry = (MXFRIPEntry*)mxf_get_iter_element(&iter); if (i == 0) { CHK_OFAIL(entry->bodySID == 0); CHK_OFAIL(entry->thisPartition == RUNIN_LEN); } else if (i == 1) { CHK_OFAIL(entry->bodySID == 2); CHK_OFAIL(entry->thisPartition == RUNIN_LEN + 1161); } else if (i == 2) { CHK_OFAIL(entry->bodySID == 3); CHK_OFAIL(entry->thisPartition == RUNIN_LEN + 1298); } else { CHK_OFAIL(entry->bodySID == 0); CHK_OFAIL(entry->thisPartition == RUNIN_LEN + 1554); } i++; } /* read header pp, allowing for runin */ CHK_OFAIL(mxf_read_header_pp_kl_with_runin(mxfFile, &key, &llen, &len)); CHK_OFAIL(mxf_read_partition(mxfFile, &key, &headerPartition)); CHK_OFAIL(mxf_append_partition(&partitions, headerPartition)); CHK_OFAIL(headerPartition->indexSID == 1); CHK_OFAIL(headerPartition->bodySID == 0); CHK_OFAIL(mxf_get_list_length(&headerPartition->essenceContainers) == 2); mxf_initialise_list_iter(&iter, &headerPartition->essenceContainers); i = 0; while (mxf_next_list_iter_element(&iter)) { mxfUL *label = (mxfUL*)mxf_get_iter_element(&iter); if (i == 0) { CHK_OFAIL(mxf_equals_ul(label, &MXF_EC_L(SD_Unc_625_50i_422_135_FrameWrapped))); } else { CHK_OFAIL(mxf_equals_ul(label, &MXF_EC_L(BWFFrameWrapped))); } i++; } /* skip filler and read body pp 1 */ CHK_OFAIL(mxf_read_next_nonfiller_kl(mxfFile, &key, &llen, &len)); CHK_OFAIL(mxf_is_partition_pack(&key)); CHK_OFAIL(mxf_read_partition(mxfFile, &key, &bodyPartition1)); CHK_OFAIL(bodyPartition1->indexSID == 0); CHK_OFAIL(bodyPartition1->bodySID == 2); CHK_OFAIL(mxf_append_partition(&partitions, bodyPartition1)); /* skip filler and read body pp 2 */ CHK_OFAIL(mxf_read_next_nonfiller_kl(mxfFile, &key, &llen, &len)); CHK_OFAIL(mxf_is_partition_pack(&key)); CHK_OFAIL(mxf_read_partition(mxfFile, &key, &bodyPartition2)); CHK_OFAIL(bodyPartition2->indexSID == 0); CHK_OFAIL(bodyPartition2->bodySID == 3); CHK_OFAIL(mxf_append_partition(&partitions, bodyPartition2)); /* skip filler and read footer pp */ CHK_OFAIL(mxf_read_next_nonfiller_kl(mxfFile, &key, &llen, &len)); CHK_OFAIL(mxf_is_partition_pack(&key)); CHK_OFAIL(mxf_read_partition(mxfFile, &key, &footerPartition)); CHK_OFAIL(footerPartition->bodySID == 0); CHK_OFAIL(footerPartition->indexSID == 1); CHK_OFAIL(mxf_append_partition(&partitions, footerPartition)); mxf_initialise_list_iter(&iter, &footerPartition->essenceContainers); i = 0; while (mxf_next_list_iter_element(&iter)) { mxfUL *label = (mxfUL*)mxf_get_iter_element(&iter); if (i == 0) { CHK_OFAIL(mxf_equals_ul(label, &MXF_EC_L(SD_Unc_625_50i_422_135_FrameWrapped))); } else { CHK_OFAIL(mxf_equals_ul(label, &MXF_EC_L(BWFFrameWrapped))); } i++; } mxf_clear_rip(&rip); mxf_file_close(&mxfFile); mxf_clear_file_partitions(&partitions); return 1; fail: mxf_clear_rip(&rip); mxf_file_close(&mxfFile); mxf_clear_file_partitions(&partitions); return 0; }
static int process_metadata(MXFReader *reader, MXFPartition *partition) { MXFFile *mxfFile = reader->mxfFile; EssenceReader *essenceReader = reader->essenceReader; EssenceReaderData *data = essenceReader->data; mxfKey key; uint8_t llen; uint64_t len; MXFMetadataSet *essContainerDataSet; MXFMetadataSet *sourcePackageSet; MXFMetadataSet *sourcePackageTrackSet; MXFMetadataSet *materialPackageSet; MXFMetadataSet *materialPackageTrackSet; MXFMetadataSet *descriptorSet; MXFArrayItemIterator arrayIter; mxfUL dataDefUL; MXFTrack *track; EssenceTrack *essenceTrack; MXFList wrappedTracks; MXFList sortedWrappedTracks; WrappedTrack *newWrappedTrack = NULL; WrappedTrack *wrappedTrack; WrappedTrack *sortedWrappedTrack; WrappedTrack *prevSortedWrappedTrack; WrappedTrack *firstSortedWrappedTrack; MXFListIterator listIter; MXFListIterator sortedListIter; int wasInserted; int haveZeroTrackNumber; uint32_t trackID; mxf_initialise_list(&wrappedTracks, free); mxf_initialise_list(&sortedWrappedTracks, NULL); /* create and read the header metadata */ CHK_OFAIL(mxf_read_next_nonfiller_kl(mxfFile, &key, &llen, &len)); CHK_OFAIL(mxf_is_header_metadata(&key)); CHK_OFAIL(mxf_create_header_metadata(&data->headerMetadata, reader->dataModel)); CHK_OFAIL(mxf_read_header_metadata(mxfFile, data->headerMetadata, partition->headerByteCount, &key, llen, len)); /* check for metadata only files */ if (!mxf_find_singular_set_by_key(data->headerMetadata, &MXF_SET_K(EssenceContainerData), &essContainerDataSet)) { reader->isMetadataOnly = 1; return 1; } /* get the body and index SID from the (single essence container; external essence not supported) */ CHK_OFAIL(mxf_get_uint32_item(essContainerDataSet, &MXF_ITEM_K(EssenceContainerData, BodySID), &data->bodySID)); if (mxf_have_item(essContainerDataSet, &MXF_ITEM_K(EssenceContainerData, IndexSID))) { CHK_OFAIL(mxf_get_uint32_item(essContainerDataSet, &MXF_ITEM_K(EssenceContainerData, IndexSID), &data->indexSID)); } else { data->indexSID = 0; } /* get the clip duration */ CHK_OFAIL(get_clip_duration(data->headerMetadata, &reader->clip, 0)); /* get the tracks from the (single) material package */ haveZeroTrackNumber = 0; CHK_OFAIL(mxf_find_singular_set_by_key(data->headerMetadata, &MXF_SET_K(MaterialPackage), &materialPackageSet)); CHK_OFAIL(mxf_uu_get_package_tracks(materialPackageSet, &arrayIter)); while (mxf_uu_next_track(data->headerMetadata, &arrayIter, &materialPackageTrackSet)) { /* CHK_OFAIL(mxf_uu_get_track_datadef(materialPackageTrackSet, &dataDefUL)); */ /* NOTE: not failing because files from Omneon were found to have a missing DataDefinition item in the Sequence and DMSourceClip referenced by a static DM Track */ if (!mxf_uu_get_track_datadef(materialPackageTrackSet, &dataDefUL)) { continue; } if (mxf_is_picture(&dataDefUL) || mxf_is_sound(&dataDefUL)) { CHK_MALLOC_OFAIL(newWrappedTrack, WrappedTrack); memset(newWrappedTrack, 0, sizeof(WrappedTrack)); CHK_OFAIL(mxf_append_list_element(&wrappedTracks, newWrappedTrack)); wrappedTrack = newWrappedTrack; newWrappedTrack = NULL; /* assigned to list so set to NULL so not free'ed in fail */ CHK_OFAIL(add_track(reader, &track)); wrappedTrack->track = track; if (mxf_have_item(materialPackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackNumber))) { CHK_OFAIL(mxf_get_uint32_item(materialPackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackNumber), &wrappedTrack->trackNumber)); } else { wrappedTrack->trackNumber = 0; } CHK_OFAIL(mxf_get_uint32_item(materialPackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackID), &wrappedTrack->trackID)); CHK_OFAIL(mxf_get_rational_item(materialPackageTrackSet, &MXF_ITEM_K(Track, EditRate), &wrappedTrack->editRate)); CHK_OFAIL(mxf_uu_get_track_duration(materialPackageTrackSet, &wrappedTrack->duration)); CHK_OFAIL(mxf_uu_get_track_reference(materialPackageTrackSet, &wrappedTrack->sourcePackageUID, &wrappedTrack->sourceTrackID)); wrappedTrack->isVideo = mxf_is_picture(&dataDefUL); track->isVideo = wrappedTrack->isVideo; track->materialTrackID = wrappedTrack->trackID; track->materialTrackNumber = wrappedTrack->trackNumber; if (wrappedTrack->isVideo) { track->video.frameRate = wrappedTrack->editRate; } if (wrappedTrack->trackNumber == 0) { haveZeroTrackNumber = 1; } } } /* sort the tracks; use trackNumber if != 0 else use the trackID; video track is always first */ mxf_initialise_list_iter(&listIter, &wrappedTracks); while (mxf_next_list_iter_element(&listIter)) { wrappedTrack = (WrappedTrack*)mxf_get_iter_element(&listIter); wasInserted = 0; mxf_initialise_list_iter(&sortedListIter, &sortedWrappedTracks); while (mxf_next_list_iter_element(&sortedListIter)) { sortedWrappedTrack = (WrappedTrack*)mxf_get_iter_element(&sortedListIter); if ((wrappedTrack->track->isVideo && !sortedWrappedTrack->track->isVideo) || (wrappedTrack->track->isVideo == sortedWrappedTrack->track->isVideo && ((!haveZeroTrackNumber && wrappedTrack->trackNumber < sortedWrappedTrack->trackNumber) || (haveZeroTrackNumber && wrappedTrack->trackID < sortedWrappedTrack->trackID)))) { CHK_OFAIL(mxf_insert_list_element(&sortedWrappedTracks, mxf_get_list_iter_index(&sortedListIter), 1, wrappedTrack)); wasInserted = 1; break; } } if (!wasInserted) { CHK_OFAIL(mxf_append_list_element(&sortedWrappedTracks, wrappedTrack)); } } /* set the MXFTracks to the same order */ prevSortedWrappedTrack = NULL; firstSortedWrappedTrack = NULL; mxf_initialise_list_iter(&sortedListIter, &sortedWrappedTracks); while (mxf_next_list_iter_element(&sortedListIter)) { sortedWrappedTrack = (WrappedTrack*)mxf_get_iter_element(&sortedListIter); if (firstSortedWrappedTrack == NULL) { firstSortedWrappedTrack = sortedWrappedTrack; } if (prevSortedWrappedTrack != NULL) { prevSortedWrappedTrack->track->next = sortedWrappedTrack->track; } prevSortedWrappedTrack = sortedWrappedTrack; } if (prevSortedWrappedTrack != NULL) { prevSortedWrappedTrack->track->next = NULL; } if (firstSortedWrappedTrack != NULL) { reader->clip.tracks = firstSortedWrappedTrack->track; } /* process source package tracks and linked descriptors */ mxf_initialise_list_iter(&sortedListIter, &sortedWrappedTracks); while (mxf_next_list_iter_element(&sortedListIter)) { sortedWrappedTrack = (WrappedTrack*)mxf_get_iter_element(&sortedListIter); CHK_OFAIL(mxf_uu_get_referenced_track(data->headerMetadata, &sortedWrappedTrack->sourcePackageUID, sortedWrappedTrack->sourceTrackID, &sourcePackageTrackSet)); CHK_OFAIL(add_essence_track(essenceReader, &essenceTrack)); essenceTrack->isVideo = sortedWrappedTrack->isVideo; if (mxf_have_item(sourcePackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackNumber))) { CHK_OFAIL(mxf_get_uint32_item(sourcePackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackNumber), &essenceTrack->trackNumber)); } else { essenceTrack->trackNumber = 0; } CHK_OFAIL(mxf_get_uint32_item(sourcePackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackID), &trackID)); essenceTrack->frameRate = reader->clip.frameRate; essenceTrack->playoutDuration = reader->clip.duration; essenceTrack->indexSID = data->indexSID; essenceTrack->bodySID = data->bodySID; /* process the descriptor */ CHK_OFAIL(mxf_uu_get_referenced_package(data->headerMetadata, &sortedWrappedTrack->sourcePackageUID, &sourcePackageSet)); CHK_OFAIL(mxf_uu_get_track_descriptor(sourcePackageSet, trackID, &descriptorSet)); if (mxf_is_subclass_of(data->headerMetadata->dataModel, &descriptorSet->key, &MXF_SET_K(CDCIEssenceDescriptor))) { CHK_OFAIL(process_cdci_descriptor(descriptorSet, sortedWrappedTrack->track, essenceTrack)); } else if (mxf_is_subclass_of(data->headerMetadata->dataModel, &descriptorSet->key, &MXF_SET_K(WaveAudioDescriptor))) { CHK_OFAIL(process_wav_descriptor(descriptorSet, sortedWrappedTrack->track, essenceTrack)); } else if (mxf_is_subclass_of(data->headerMetadata->dataModel, &descriptorSet->key, &MXF_SET_K(GenericSoundEssenceDescriptor))) { CHK_OFAIL(process_sound_descriptor(descriptorSet, track, essenceTrack)); } else { mxf_log_error("Unsupported file descriptor" LOG_LOC_FORMAT, LOG_LOC_PARAMS); return 0; } } /* initialise the playout timecode */ if (!initialise_playout_timecode(reader, materialPackageSet)) { CHK_ORET(initialise_default_playout_timecode(reader)); } /* initialise the source timecodes */ initialise_source_timecodes(reader, sourcePackageSet); mxf_clear_list(&wrappedTracks); mxf_clear_list(&sortedWrappedTracks); return 1; fail: SAFE_FREE(newWrappedTrack); mxf_clear_list(&wrappedTracks); mxf_clear_list(&sortedWrappedTracks); return 0; }
int find_position(TimecodeIndexSearcher* searcher, const ArchiveTimecode* timecode, int64_t* position) { TimecodeIndexArray* indexArray; TimecodeIndexElement* arrayElement; int64_t timecodePos = timecode_to_position(timecode); int doneFirst = 0; TimecodeIndexSearcher searcherCopy = *searcher; if (timecode->hour == INVALID_TIMECODE_HOUR) { return 0; } if (searcher->atEnd) { return 0; } indexArray = (TimecodeIndexArray*)mxf_get_iter_element(&searcher->indexArrayIter); while (1) { arrayElement = &indexArray->elements[searcher->elementNum]; if ((doneFirst || searcher->beforeStart || timecodePos > arrayElement->timecodePos + searcher->elementOffset) && timecodePos >= arrayElement->timecodePos + searcher->elementOffset && timecodePos < arrayElement->timecodePos + arrayElement->duration) { /* found it in incrementing timecode element */ searcher->position += timecodePos - (arrayElement->timecodePos + searcher->elementOffset); searcher->elementOffset = timecodePos - arrayElement->timecodePos; *position = searcher->position; searcher->beforeStart = 0; return 1; } else if (arrayElement->frozen && timecodePos == arrayElement->timecodePos) { /* found it in frozen timecode element - position is the searcher position */ *position = searcher->position; searcher->beforeStart = 0; return 1; } else if (searcher->elementNum + 1 < indexArray->numElements) { /* move to next element in array */ searcher->position += arrayElement->duration - searcher->elementOffset; searcher->elementOffset = 0; searcher->elementNum++; } else if (searcher->elementNum + 1 >= indexArray->numElements && indexArray->numElements == searcher->index->arraySize) { /* move to next array in list */ searcher->position += arrayElement->duration - searcher->elementOffset; searcher->elementOffset = 0; searcher->elementNum = 0; searcher->atEnd = !mxf_next_list_iter_element(&searcher->indexArrayIter); if (searcher->atEnd) { /* end of index */ break; } indexArray = (TimecodeIndexArray*)mxf_get_iter_element(&searcher->indexArrayIter); } else { /* end of index */ break; } doneFirst = 1; } *searcher = searcherCopy; return 0; }
static int get_file_partitions(MXFFile *mxfFile, MXFPartition *headerPartition, MXFList *partitions) { mxfKey key; uint8_t llen; uint64_t len; MXFPartition *partition = NULL; MXFPartition *partitionRef; uint64_t thisPartition; MXFRIP rip; MXFRIPEntry *ripEntry; MXFListIterator iter; mxf_initialise_list(partitions, free_partition_in_list); memset(&rip, 0, sizeof(MXFRIP)); /* use the RIP if there is one */ if (mxf_read_rip(mxfFile, &rip)) { mxf_initialise_list_iter(&iter, &rip.entries); while (mxf_next_list_iter_element(&iter)) { ripEntry = (MXFRIPEntry*)mxf_get_iter_element(&iter); /* seek to partition and read and add to list */ CHK_OFAIL(mxf_file_seek(mxfFile, mxf_get_runin_len(mxfFile) + ripEntry->thisPartition, SEEK_SET)); CHK_OFAIL(mxf_read_kl(mxfFile, &key, &llen, &len)); CHK_OFAIL(mxf_is_partition_pack(&key)); CHK_OFAIL(mxf_read_partition(mxfFile, &key, &partition)); CHK_OFAIL(mxf_append_list_element(partitions, partition)); partition = NULL; /* owned by list */ } } /* start from footer partition and index back to the header partition */ else { if (headerPartition->footerPartition == 0) { /* no footer partition or at unknown position, so we only index the header partition */ goto fail; } thisPartition = headerPartition->footerPartition; do { /* seek to partition and read and add to list */ CHK_OFAIL(mxf_file_seek(mxfFile, mxf_get_runin_len(mxfFile) + thisPartition, SEEK_SET)); CHK_OFAIL(mxf_read_kl(mxfFile, &key, &llen, &len)); CHK_OFAIL(mxf_is_partition_pack(&key)); CHK_OFAIL(mxf_read_partition(mxfFile, &key, &partition)); CHK_OFAIL(mxf_prepend_list_element(partitions, partition)); partitionRef = partition; partition = NULL; /* owned by list */ thisPartition = partitionRef->previousPartition; } while (partitionRef->thisPartition != partitionRef->previousPartition); } mxf_clear_rip(&rip); return 1; fail: /* if something failed then just add the header partition Note: some Omneon files had references to a footer partition which was not actually present in the file */ mxf_clear_list(partitions); mxf_free_partition(&partition); mxf_clear_rip(&rip); /* create copy of header partition pack */ CHK_ORET(mxf_create_from_partition(headerPartition, &partition)); partition->key = headerPartition->key; partition->majorVersion = headerPartition->majorVersion; partition->minorVersion = headerPartition->minorVersion; partition->kagSize = headerPartition->kagSize; partition->thisPartition = headerPartition->thisPartition; partition->previousPartition = headerPartition->previousPartition; partition->footerPartition = headerPartition->footerPartition; partition->headerByteCount = headerPartition->headerByteCount; partition->indexByteCount = headerPartition->indexByteCount; partition->indexSID = headerPartition->indexSID; partition->bodyOffset = headerPartition->bodyOffset; partition->bodySID = headerPartition->bodySID; /* add partition to list */ if (!mxf_append_list_element(partitions, partition)) { mxf_free_partition(&partition); mxf_log_error("Failed to append header partition to list" LOG_LOC_FORMAT, LOG_LOC_PARAMS); return 0; } return 1; }
int archive_mxf_get_info(MXFHeaderMetadata* headerMetadata, ArchiveMXFInfo* info) { MXFList* list = NULL; MXFListIterator iter; MXFArrayItemIterator arrayIter; uint8_t* arrayElement; uint32_t arrayElementLen; mxfUL dataDef; uint32_t count; mxfUTF16Char* tempWString = NULL; int haveSourceInfaxData = 0; MXFList* nameList = NULL; MXFList* valueList = NULL; MXFMetadataSet* identSet; MXFMetadataSet* fileSourcePackageSet; MXFMetadataSet* sourcePackageSet; MXFMetadataSet* sourcePackageTrackSet; MXFMetadataSet* sequenceSet; MXFMetadataSet* dmSet; MXFMetadataSet* dmFrameworkSet; MXFMetadataSet* descriptorSet; MXFMetadataSet* locatorSet; MXFMetadataSet* materialPackageSet; /* if metadata only then only try reading infax user comments */ if (is_metadata_only_file(headerMetadata, &materialPackageSet)) { if (mxf_avid_read_string_user_comments(materialPackageSet, &nameList, &valueList)) { haveSourceInfaxData = parse_infax_user_comments(nameList, valueList, &info->sourceInfaxData); mxf_free_list(&nameList); mxf_free_list(&valueList); } return 1; } /* Creation timestamp identification info */ CHK_OFAIL(mxf_find_set_by_key(headerMetadata, &MXF_SET_K(Identification), &list)); mxf_initialise_list_iter(&iter, list); if (mxf_next_list_iter_element(&iter)) { identSet = (MXFMetadataSet*)mxf_get_iter_element(&iter); CHK_OFAIL(mxf_get_timestamp_item(identSet, &MXF_ITEM_K(Identification, ModificationDate), &info->creationDate)); } mxf_free_list(&list); /* LTO Infax data */ CHK_OFAIL(mxf_uu_get_top_file_package(headerMetadata, &fileSourcePackageSet)); CHK_OFAIL(mxf_uu_get_package_tracks(fileSourcePackageSet, &arrayIter)); while (mxf_uu_next_track(headerMetadata, &arrayIter, &sourcePackageTrackSet)) { CHK_OFAIL(mxf_uu_get_track_datadef(sourcePackageTrackSet, &dataDef)); if (mxf_is_descriptive_metadata(&dataDef)) { /* get to the single DMSegment */ CHK_OFAIL(mxf_get_strongref_item(sourcePackageTrackSet, &MXF_ITEM_K(GenericTrack, Sequence), &sequenceSet)); if (mxf_is_subclass_of(headerMetadata->dataModel, &sequenceSet->key, &MXF_SET_K(Sequence))) { CHK_OFAIL(mxf_get_array_item_count(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), &count)); if (count != 1) { /* Sequence of length 1 is expected for the DMS track */ continue; } CHK_OFAIL(mxf_get_array_item_element(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), 0, &arrayElement)); CHK_OFAIL(mxf_get_strongref(headerMetadata, arrayElement, &dmSet)); } else { dmSet = sequenceSet; } /* if it is a DMSegment with a DMFramework reference then we have the DMS track */ if (mxf_is_subclass_of(headerMetadata->dataModel, &dmSet->key, &MXF_SET_K(DMSegment))) { if (mxf_have_item(dmSet, &MXF_ITEM_K(DMSegment, DMFramework))) { CHK_OFAIL(mxf_get_strongref_item(dmSet, &MXF_ITEM_K(DMSegment, DMFramework), &dmFrameworkSet)); /* if it is a APP_InfaxFramework then it is the Infax data */ if (mxf_is_subclass_of(headerMetadata->dataModel, &dmFrameworkSet->key, &MXF_SET_K(APP_InfaxFramework))) { CHK_OFAIL(get_infax_data(dmFrameworkSet, &info->ltoInfaxData)); break; } } } } } /* original filename */ CHK_OFAIL(mxf_get_strongref_item(fileSourcePackageSet, &MXF_ITEM_K(SourcePackage, Descriptor), &descriptorSet)); if (mxf_have_item(descriptorSet, &MXF_ITEM_K(GenericDescriptor, Locators))) { CHK_OFAIL(mxf_initialise_array_item_iterator(descriptorSet, &MXF_ITEM_K(GenericDescriptor, Locators), &arrayIter)); while (mxf_next_array_item_element(&arrayIter, &arrayElement, &arrayElementLen)) { CHK_OFAIL(mxf_get_strongref(headerMetadata, arrayElement, &locatorSet)); if (mxf_is_subclass_of(headerMetadata->dataModel, &locatorSet->key, &MXF_SET_K(NetworkLocator))) { CHK_OFAIL(mxf_uu_get_utf16string_item(locatorSet, &MXF_ITEM_K(NetworkLocator, URLString), &tempWString)); CHK_OFAIL(wcstombs(info->filename, tempWString, sizeof(info->filename)) != (size_t)(-1)); info->filename[sizeof(info->filename) - 1] = '\0'; SAFE_FREE(&tempWString); break; } } } /* source Infax data */ CHK_OFAIL(mxf_find_set_by_key(headerMetadata, &MXF_SET_K(SourcePackage), &list)); mxf_initialise_list_iter(&iter, list); while (mxf_next_list_iter_element(&iter)) { sourcePackageSet = (MXFMetadataSet*)(mxf_get_iter_element(&iter)); /* it is the tape SourcePackage if it has a TapeDescriptor */ CHK_OFAIL(mxf_get_strongref_item(sourcePackageSet, &MXF_ITEM_K(SourcePackage, Descriptor), &descriptorSet)); if (mxf_is_subclass_of(headerMetadata->dataModel, &descriptorSet->key, &MXF_SET_K(TapeDescriptor))) { /* go through the tracks and find the DMS track */ CHK_OFAIL(mxf_uu_get_package_tracks(sourcePackageSet, &arrayIter)); while (mxf_uu_next_track(headerMetadata, &arrayIter, &sourcePackageTrackSet)) { CHK_OFAIL(mxf_uu_get_track_datadef(sourcePackageTrackSet, &dataDef)); if (mxf_is_descriptive_metadata(&dataDef)) { /* get to the single DMSegment */ CHK_OFAIL(mxf_get_strongref_item(sourcePackageTrackSet, &MXF_ITEM_K(GenericTrack, Sequence), &sequenceSet)); if (mxf_is_subclass_of(headerMetadata->dataModel, &sequenceSet->key, &MXF_SET_K(Sequence))) { CHK_OFAIL(mxf_get_array_item_count(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), &count)); if (count != 1) { /* Sequence of length 1 is expected for the DMS track */ continue; } CHK_OFAIL(mxf_get_array_item_element(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), 0, &arrayElement)); CHK_OFAIL(mxf_get_strongref(headerMetadata, arrayElement, &dmSet)); } else { dmSet = sequenceSet; } /* if it is a DMSegment with a DMFramework reference then we have the DMS track */ if (mxf_is_subclass_of(headerMetadata->dataModel, &dmSet->key, &MXF_SET_K(DMSegment))) { if (mxf_have_item(dmSet, &MXF_ITEM_K(DMSegment, DMFramework))) { CHK_OFAIL(mxf_get_strongref_item(dmSet, &MXF_ITEM_K(DMSegment, DMFramework), &dmFrameworkSet)); /* if it is a APP_InfaxFramework then it is the Infax data */ if (mxf_is_subclass_of(headerMetadata->dataModel, &dmFrameworkSet->key, &MXF_SET_K(APP_InfaxFramework))) { CHK_OFAIL(get_infax_data(dmFrameworkSet, &info->sourceInfaxData)); haveSourceInfaxData = 1; break; } } } } } break; } } mxf_free_list(&list); /* try reading Infax data from UserComments attached to the MaterialPackage if no data was found elsewhere */ if (!haveSourceInfaxData) { CHK_OFAIL(mxf_find_singular_set_by_key(headerMetadata, &MXF_SET_K(MaterialPackage), &materialPackageSet)); if (mxf_avid_read_string_user_comments(materialPackageSet, &nameList, &valueList)) { haveSourceInfaxData = parse_infax_user_comments(nameList, valueList, &info->sourceInfaxData); mxf_free_list(&nameList); mxf_free_list(&valueList); } } return haveSourceInfaxData; fail: SAFE_FREE(&tempWString); mxf_free_list(&list); mxf_free_list(&nameList); mxf_free_list(&valueList); return 0; }
int op1a_is_supported(MXFPartition *headerPartition) { MXFListIterator iter; mxfUL *label; int supportCount = 0; if (!mxf_is_op_1a(&headerPartition->operationalPattern)) { return 0; } if (mxf_get_list_length(&headerPartition->essenceContainers) == 0) { /* metadata only */ return 1; } if (mxf_get_list_length(&headerPartition->essenceContainers) == 1) { label = (mxfUL*)mxf_get_list_element(&headerPartition->essenceContainers, 0); if (is_d10_essence(label)) { return 1; } } mxf_initialise_list_iter(&iter, &headerPartition->essenceContainers); while (mxf_next_list_iter_element(&iter)) { label = (mxfUL*)mxf_get_iter_element(&iter); if (mxf_equals_ul(label, &MXF_EC_L(MultipleWrappings))) { supportCount++; } else if (is_d10_picture_essence(label)) { supportCount++; } else if (mxf_equals_ul(label, &MXF_EC_L(IECDV_25_525_60_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(IECDV_25_625_50_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(DVBased_25_525_60_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(DVBased_25_625_50_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(DVBased_50_525_60_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(DVBased_50_625_50_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(DVBased_100_1080_50_I_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(DVBased_100_1080_60_I_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(DVBased_100_720_50_P_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(DVBased_100_720_60_P_FrameWrapped))) { supportCount++; } else if (mxf_equals_ul(label, &MXF_EC_L(SD_Unc_625_50i_422_135_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(SD_Unc_525_5994i_422_135_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_50i_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_5994i_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_25p_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_50p_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_2997p_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_5994p_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_720_25p_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_720_2997p_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_720_50p_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_720_5994p_422_FrameWrapped))) { supportCount++; } else if (mxf_equals_ul(label, &MXF_EC_L(BWFFrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(AES3FrameWrapped))) { supportCount++; } else if (mxf_is_avc_ec(label, 1)) { supportCount++; } } return supportCount > 0; }
static int move_timecode_index_searcher(TimecodeIndexSearcher* searcher, int64_t position) { TimecodeIndexArray* indexArray; TimecodeIndexElement* arrayElement; TimecodeIndexSearcher searcherCopy = *searcher; if (position == searcher->position) { return 1; } if (searcher->atEnd || position < searcher->position) { return 0; } indexArray = (TimecodeIndexArray*)mxf_get_iter_element(&searcher->indexArrayIter); while (1) { arrayElement = &indexArray->elements[searcher->elementNum]; if (position < searcher->position + (arrayElement->duration - searcher->elementOffset)) { /* found it the right element */ searcher->elementOffset += position - searcher->position; searcher->position = position; searcher->beforeStart = 0; return 1; } else if (searcher->elementNum + 1 < indexArray->numElements) { /* move to next element in array */ searcher->position += arrayElement->duration - searcher->elementOffset; searcher->elementOffset = 0; searcher->elementNum++; } else if (searcher->elementNum + 1 >= indexArray->numElements && indexArray->numElements == searcher->index->arraySize) { /* move to next array in list */ searcher->position += arrayElement->duration - searcher->elementOffset; searcher->elementOffset = 0; searcher->elementNum = 0; searcher->atEnd = !mxf_next_list_iter_element(&searcher->indexArrayIter); if (searcher->atEnd) { /* end of index */ break; } indexArray = (TimecodeIndexArray*)mxf_get_iter_element(&searcher->indexArrayIter); } else { /* end of index */ break; } } *searcher = searcherCopy; return 0; }