Esempio n. 1
0
static void free_partition_in_list(void *data)
{
    MXFPartition *tmpPartition;

    if (data == NULL)
    {
        return;
    }

    tmpPartition = (MXFPartition*)data;
    mxf_free_partition(&tmpPartition);
}
Esempio n. 2
0
int archive_mxf_is_metadata_only(const char* filename)
{
    MXFPageFile* mxfPageFile = NULL;
    MXFFile* mxfFile = NULL;
    mxfKey key;
    uint8_t llen;
    uint64_t len;
    MXFPartition* headerPartition = NULL;
    int result;
    
    /* open MXF file */
    if (strstr(filename, "%d") != NULL)
    {
        CHK_OFAIL_NOMSG(mxf_page_file_open_read(filename, &mxfPageFile));
        mxfFile = mxf_page_file_get_file(mxfPageFile);
    }
    else
    {
        CHK_OFAIL_NOMSG(mxf_disk_file_open_read(filename, &mxfFile));
    }
    
    /* read header partition pack */
    if (!mxf_read_header_pp_kl_with_runin(mxfFile, &key, &llen, &len) ||
        !mxf_read_partition(mxfFile, &key, &headerPartition))
    {
        return 0;
    }
    
    /* check whether there is an essence container label */
    result = (mxf_get_list_length(&headerPartition->essenceContainers) == 0);

    mxf_free_partition(&headerPartition);
    mxf_file_close(&mxfFile);
    return result;

fail:
    mxf_free_partition(&headerPartition);
    mxf_file_close(&mxfFile);
    return 0;
}
Esempio n. 3
0
int mxf_append_new_partition(MXFFilePartitions *partitions, MXFPartition **partition)
{
    MXFPartition *newPartition;

    CHK_ORET(mxf_create_partition(&newPartition));
    CHK_OFAIL(mxf_append_partition(partitions, newPartition));

    *partition = newPartition;
    return 1;

fail:
    mxf_free_partition(&newPartition);
    return 0;
}
Esempio n. 4
0
int mxf_read_partition(MXFFile *mxfFile, const mxfKey *key, uint64_t len, MXFPartition **partition)
{
    MXFPartition *newPartition;
    uint32_t numLabels;
    uint32_t labelLen;
    mxfUL label;
    uint64_t expectedLen;
    uint32_t i;

    CHK_ORET(len >= 88 && len <= INT64_MAX);

    CHK_ORET(mxf_create_partition(&newPartition));
    newPartition->key = *key;

    CHK_OFAIL(mxf_read_uint16(mxfFile, &newPartition->majorVersion));
    CHK_OFAIL(mxf_read_uint16(mxfFile, &newPartition->minorVersion));
    CHK_OFAIL(mxf_read_uint32(mxfFile, &newPartition->kagSize));
    CHK_OFAIL(mxf_read_uint64(mxfFile, &newPartition->thisPartition));
    CHK_OFAIL(mxf_read_uint64(mxfFile, &newPartition->previousPartition));
    CHK_OFAIL(mxf_read_uint64(mxfFile, &newPartition->footerPartition));
    CHK_OFAIL(mxf_read_uint64(mxfFile, &newPartition->headerByteCount));
    CHK_OFAIL(mxf_read_uint64(mxfFile, &newPartition->indexByteCount));
    CHK_OFAIL(mxf_read_uint32(mxfFile, &newPartition->indexSID));
    CHK_OFAIL(mxf_read_uint64(mxfFile, &newPartition->bodyOffset));
    CHK_OFAIL(mxf_read_uint32(mxfFile, &newPartition->bodySID));
    CHK_OFAIL(mxf_read_ul(mxfFile, &newPartition->operationalPattern));

    CHK_OFAIL(mxf_read_batch_header(mxfFile, &numLabels, &labelLen));
    CHK_OFAIL(numLabels == 0 || labelLen == 16);
    expectedLen = 88 + (uint64_t)numLabels * labelLen;
    CHK_OFAIL(len >= expectedLen);
    for (i = 0; i < numLabels; i++)
    {
        CHK_OFAIL(mxf_read_ul(mxfFile, &label));
        CHK_OFAIL(mxf_append_partition_esscont_label(newPartition, &label));
    }

    if (len > expectedLen) {
        mxf_log_warn("Partition pack len %" PRIu64 " is larger than expected len %" PRIu64 "\n",
                     len, expectedLen);
        CHK_OFAIL(mxf_file_seek(mxfFile, (int64_t)(len - expectedLen), SEEK_CUR));
    }

    *partition = newPartition;
    return 1;

fail:
    mxf_free_partition(&newPartition);
    return 0;
}
Esempio n. 5
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);
}
Esempio n. 6
0
int mxf_create_from_partition(const MXFPartition *sourcePartition, MXFPartition **partition)
{
    MXFPartition *newPartition;

    CHK_MALLOC_ORET(newPartition, MXFPartition);
    if (!mxf_initialise_with_partition(sourcePartition, newPartition))
    {
        goto fail;
    }

    *partition = newPartition;
    return 1;

fail:
    mxf_free_partition(&newPartition);
    return 0;
}
Esempio n. 7
0
int archive_mxf_read_footer_metadata(const char* filename, MXFDataModel* dataModel, MXFHeaderMetadata** headerMetadata)
{
    MXFPageFile* mxfPageFile = NULL;
    MXFFile* mxfFile = NULL;
    MXFRIP rip;
    MXFRIPEntry* lastRIPEntry = NULL;
    mxfKey key;
    uint8_t llen;
    uint64_t len;
    MXFPartition* footerPartition = NULL;
    int result = 0;
    MXFHeaderMetadata* newHeaderMetadata = NULL;
    
    memset(&rip, 0, sizeof(rip));
 
    
    /* open MXF file */    
    if (strstr(filename, "%d") != NULL)
    {
        CHK_OFAIL_NOMSG(mxf_page_file_open_read(filename, &mxfPageFile));
        mxfFile = mxf_page_file_get_file(mxfPageFile);
    }
    else
    {
        CHK_OFAIL_NOMSG(mxf_disk_file_open_read(filename, &mxfFile));
    }
    
    /* read the RIP */
    CHK_OFAIL_NOMSG(mxf_read_rip(mxfFile, &rip));
    
    /* read footer partition pack */
    CHK_OFAIL_NOMSG((lastRIPEntry = (MXFRIPEntry*)mxf_get_last_list_element(&rip.entries)) != NULL);
    CHK_OFAIL_NOMSG(mxf_file_seek(mxfFile, mxf_get_runin_len(mxfFile) + lastRIPEntry->thisPartition, SEEK_SET));
    CHK_OFAIL_NOMSG(mxf_read_kl(mxfFile, &key, &llen, &len));
    CHK_OFAIL_NOMSG(mxf_is_partition_pack(&key));
    result = 2; /* the file is complete and the presence, or not, of the header metadata will not change */
    *headerMetadata = NULL;
    
    CHK_OFAIL_NOMSG(mxf_is_footer_partition_pack(&key));
    CHK_OFAIL_NOMSG(mxf_read_partition(mxfFile, &key, &footerPartition));
    
    /* read the header metadata */
    CHK_OFAIL_NOMSG(mxf_read_next_nonfiller_kl(mxfFile, &key, &llen, &len));
    CHK_OFAIL_NOMSG(mxf_is_header_metadata(&key));
    CHK_OFAIL_NOMSG(mxf_create_header_metadata(&newHeaderMetadata, dataModel));
    CHK_OFAIL_NOMSG(mxf_read_header_metadata(mxfFile, newHeaderMetadata, 
        footerPartition->headerByteCount, &key, llen, len));

    mxf_free_partition(&footerPartition);
    mxf_clear_rip(&rip);
    mxf_file_close(&mxfFile);
    
    *headerMetadata = newHeaderMetadata;
    newHeaderMetadata = NULL;
    return 1;
 
    
fail:
    mxf_free_header_metadata(&newHeaderMetadata);
    mxf_free_partition(&footerPartition);
    mxf_clear_rip(&rip);
    mxf_file_close(&mxfFile);
    return result;
}
Esempio n. 8
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;
}
Esempio n. 9
0
static int ns_pos_at_next_frame(MXFReader *reader)
{
    MXFFile *mxfFile = reader->mxfFile;
    EssenceReader *essenceReader = reader->essenceReader;
    EssenceReaderData *data = essenceReader->data;
    NSFileIndex *nsIndex = &data->nsIndex;
    MXFPartition *partition = NULL;
    mxfKey key;
    uint8_t llen;
    uint64_t len;
    int atEOF;


    /* move to next partition if at end of current partition */
    if (mxf_is_partition_pack(&nsIndex->nextKey))
    {
        key = nsIndex->nextKey;
        llen = nsIndex->nextLLen;
        len = nsIndex->nextLen;
        atEOF = 0;
        while (!atEOF)
        {
            /* read partition pack and check if it contains essence */
            CHK_OFAIL(mxf_read_partition(mxfFile, &key, &partition));
            if (data->bodySID == partition->bodySID)
            {
                CHK_OFAIL(ns_position_at_first_frame(reader));
                mxf_free_partition(&partition);
                break;
            }
            mxf_free_partition(&partition);

            /* skip this partition */
            while (!atEOF)
            {
                if (!mxf_read_kl(mxfFile, &key, &llen, &len))
                {
                    /* if we fail to read then we must be at eof */
                    CHK_OFAIL(mxf_file_eof(mxfFile));
                    atEOF = 1;
                    ns_set_next_kl(nsIndex, &g_Null_Key, 0, 0);
                    break;
                }
                ns_set_next_kl(nsIndex, &key, llen, len);

                if (mxf_is_partition_pack(&key))
                {
                    break;
                }
                CHK_OFAIL(mxf_skip(mxfFile, len));
            }
        }

        CHK_ORET(atEOF || mxf_equals_key(&key, &nsIndex->startContentPackageKey));
    }

    return 1;

fail:
    mxf_free_partition(&partition);
    return 0;
}
Esempio n. 10
0
static int ns_position_at_first_frame(MXFReader *reader)
{
    MXFFile *mxfFile = reader->mxfFile;
    EssenceReader *essenceReader = reader->essenceReader;
    EssenceReaderData *data = essenceReader->data;
    NSFileIndex *nsIndex = &data->nsIndex;
    MXFPartition *partition = data->headerPartition;
    mxfKey key;
    uint8_t llen;
    uint64_t len;

    /* move to the first partition that contains essence data */
    while (data->bodySID != partition->bodySID)
    {
        if (!mxf_read_kl(mxfFile, &key, &llen, &len))
        {
            CHK_OFAIL(mxf_file_eof(mxfFile));
            ns_set_next_kl(nsIndex, &g_Null_Key, 0, 0);
            return 1;
        }
        while (!mxf_is_partition_pack(&key))
        {
            CHK_OFAIL(mxf_skip(mxfFile, len));
            if (!mxf_read_kl(mxfFile, &key, &llen, &len))
            {
                CHK_OFAIL(mxf_file_eof(mxfFile));
                ns_set_next_kl(nsIndex, &g_Null_Key, 0, 0);
                return 1;
            }
        }
        if (partition != NULL && partition != data->headerPartition)
        {
            mxf_free_partition(&partition);
        }
        CHK_OFAIL(mxf_read_partition(mxfFile, &key, &partition));
    }

    /* move to start of essence data in partition */

    /* if we are in the header partition then the file is positioned after the header metadata,
       otherwise we are positioned after the partition pack that was just read */
    if (partition != data->headerPartition)
    {
        /* skip initial filler which is not included in any header or index byte counts */
        if (!mxf_read_next_nonfiller_kl(mxfFile, &key, &llen, &len))
        {
            CHK_ORET(mxf_file_eof(mxfFile));
            ns_set_next_kl(nsIndex, &g_Null_Key, 0, 0);
            return 1;
        }

        /* skip header metadata */
        if (partition->headerByteCount > 0)
        {
            CHK_ORET(mxf_skip(mxfFile, partition->headerByteCount - mxfKey_extlen - llen));
            if (!mxf_read_kl(mxfFile, &key, &llen, &len))
            {
                CHK_ORET(mxf_file_eof(mxfFile));
                ns_set_next_kl(nsIndex, &g_Null_Key, 0, 0);
                return 1;
            }
        }
        else
        {
            CHK_ORET(!mxf_is_header_metadata(&key));
        }
    }
    else
    {
        if (!mxf_read_kl(mxfFile, &key, &llen, &len))
        {
            CHK_ORET(mxf_file_eof(mxfFile));
            ns_set_next_kl(nsIndex, &g_Null_Key, 0, 0);
            return 1;
        }
    }


    /* skip index table segments. Note: we are not checking for segment key because it
       could be non-standard, eg. MXF V10 indexes */
    if (partition->indexByteCount > 0)
    {
        CHK_ORET(mxf_skip(mxfFile, partition->indexByteCount - mxfKey_extlen - llen));
        if (!mxf_read_kl(mxfFile, &key, &llen, &len))
        {
            CHK_ORET(mxf_file_eof(mxfFile));
            ns_set_next_kl(nsIndex, &g_Null_Key, 0, 0);
            return 1;
        }
    }

    /* check the first essence element KL and position after */
    CHK_ORET(mxf_is_gc_essence_element(&key));
    if (mxf_equals_key(&nsIndex->startContentPackageKey, &g_Null_Key))
    {
        nsIndex->startContentPackageKey = key;
        nsIndex->currentPosition = 0;
    }
    else
    {
        CHK_ORET(mxf_equals_key(&nsIndex->startContentPackageKey, &key));
    }
    ns_set_next_kl(nsIndex, &key, llen, len);

    if (partition != NULL && partition != data->headerPartition)
    {
        mxf_free_partition(&partition);
    }
    return 1;

fail:
    if (partition != NULL && partition != data->headerPartition)
    {
        mxf_free_partition(&partition);
    }
    return 0;
}