コード例 #1
0
ファイル: mxf_list.c プロジェクト: Limecraft/ebu-libmxf
void mxf_free_list(MXFList **list)
{
    if (!(*list))
        return;

    mxf_clear_list(*list);
    SAFE_FREE(*list);
}
コード例 #2
0
ファイル: mxf_partition.c プロジェクト: Limecraft/ebu-libmxf
void mxf_clear_partition(MXFPartition *partition)
{
    if (partition == NULL)
    {
        return;
    }

    mxf_clear_list(&partition->essenceContainers);
}
コード例 #3
0
ファイル: mxf_partition.c プロジェクト: Limecraft/ebu-libmxf
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;
}
コード例 #4
0
void mxf_free_set(MXFMetadataSet** set)
{
    if (*set == NULL)
    {
        return;
    }
    
    mxf_clear_list(&(*set)->items);
    SAFE_FREE(set);
}
コード例 #5
0
ファイル: mxf_list.c プロジェクト: DraFFty/libMXF
void mxf_free_list(MXFList** list)
{
    if (*list == NULL)
    {
        return;
    }
    
    mxf_clear_list(*list);
    SAFE_FREE(list);
}
コード例 #6
0
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);
}
コード例 #7
0
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);
}
コード例 #8
0
ファイル: mxf_partition.c プロジェクト: Limecraft/ebu-libmxf
void mxf_clear_rip(MXFRIP *rip)
{
    mxf_clear_list(&rip->entries);
}
コード例 #9
0
ファイル: mxf_partition.c プロジェクト: Limecraft/ebu-libmxf
void mxf_clear_file_partitions(MXFFilePartitions *partitions)
{
    mxf_clear_list(partitions);
}
コード例 #10
0
ファイル: timecode_index.c プロジェクト: DraFFty/libMXF
void clear_timecode_index(TimecodeIndex* index)
{
    mxf_clear_list(&index->indexArrays);
}
コード例 #11
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;
}
コード例 #12
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;
}
コード例 #13
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;
}