void mxf_free_list(MXFList **list) { if (!(*list)) return; mxf_clear_list(*list); SAFE_FREE(*list); }
void mxf_clear_partition(MXFPartition *partition) { if (partition == NULL) { return; } mxf_clear_list(&partition->essenceContainers); }
int mxf_read_rip_and_size(MXFFile *mxfFile, MXFRIP *rip, uint32_t* size) { uint32_t rip_size; mxfKey key; uint8_t llen; uint64_t len; uint32_t numEntries; MXFRIPEntry *newEntry = NULL; MXFRIPEntry *entry; uint32_t i; mxf_initialise_list(&rip->entries, free); /* read RIP size (min is 16 + 1 + (4 + 8) * 1 + 4) at end of file */ if (!mxf_file_seek(mxfFile, -4, SEEK_END) || !mxf_read_uint32(mxfFile, &rip_size) || rip_size < 33) { return 0; } /* seek, read and check RIP key */ if (!mxf_file_seek(mxfFile, (int64_t)0 - rip_size, SEEK_CUR) || !mxf_read_k(mxfFile, &key) || !mxf_equals_key(&key, &g_RandomIndexPack_key) || !mxf_read_l(mxfFile, &llen, &len)) { return 0; } /* read RIP */ numEntries = ((uint32_t)len - 4) / 12; CHK_ORET(((uint32_t)len - 4) % 12 == 0); for (i = 0; i < numEntries; i++) { CHK_MALLOC_OFAIL(newEntry, MXFRIPEntry); CHK_OFAIL(mxf_append_list_element(&rip->entries, newEntry)); entry = newEntry; newEntry = NULL; /* entry assigned to list so set to NULL so not free'ed in fail */ CHK_OFAIL(mxf_read_uint32(mxfFile, &entry->bodySID)); CHK_OFAIL(mxf_read_uint64(mxfFile, &entry->thisPartition)); } *size = rip_size; return 1; fail: if (newEntry != NULL) { free(newEntry); } mxf_clear_list(&rip->entries); return 0; }
void mxf_free_set(MXFMetadataSet** set) { if (*set == NULL) { return; } mxf_clear_list(&(*set)->items); SAFE_FREE(set); }
void mxf_free_list(MXFList** list) { if (*list == NULL) { return; } mxf_clear_list(*list); SAFE_FREE(list); }
void mxf_free_header_metadata(MXFHeaderMetadata** headerMetadata) { if (*headerMetadata == NULL) { return; } mxf_clear_list(&(*headerMetadata)->sets); mxf_free_primer_pack(&(*headerMetadata)->primerPack); SAFE_FREE(headerMetadata); }
static void op1a_close(MXFReader *reader) { if (reader->essenceReader == NULL || reader->essenceReader->data == NULL) { return; } mxf_free_header_metadata(&reader->essenceReader->data->headerMetadata); mxf_free_partition(&reader->essenceReader->data->headerPartition); free_index(&reader->essenceReader->data->index); mxf_clear_list(&reader->essenceReader->data->partitions); SAFE_FREE(reader->essenceReader->data); }
void mxf_clear_rip(MXFRIP *rip) { mxf_clear_list(&rip->entries); }
void mxf_clear_file_partitions(MXFFilePartitions *partitions) { mxf_clear_list(partitions); }
void clear_timecode_index(TimecodeIndex* index) { mxf_clear_list(&index->indexArrays); }
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; }
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; }
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; }