Beispiel #1
0
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;
}
int mxf_finalize_essence_element_write(MXFFile *mxfFile, MXFEssenceElement *essenceElement)
{
    int64_t filePos;

    assert(essenceElement != NULL);

    CHK_ORET((filePos = mxf_file_tell(mxfFile)) >= 0);

    CHK_ORET(mxf_file_seek(mxfFile, essenceElement->startFilePos + 16, SEEK_SET));
    CHK_ORET(mxf_write_fixed_l(mxfFile, essenceElement->llen, essenceElement->totalLen));

    CHK_ORET(mxf_file_seek(mxfFile, filePos, SEEK_SET));

    return 1;
}
Beispiel #3
0
/* 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;
}
Beispiel #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;
}
Beispiel #5
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;
}
Beispiel #6
0
int test_read(const char* filename)
{
    MXFFile* mxfFile = NULL;
    mxfKey key;
    uint8_t llen;
    uint64_t len;
    mxfLocalTag tag;
    uint8_t indata[256];
    uint8_t valueu8;
    uint16_t valueu16;
    uint32_t valueu32;
    uint64_t valueu64;
    int8_t value8;
    int16_t value16;
    int32_t value32;
    int64_t value64;
    mxfUL ul;
    mxfUID uid;
    mxfUUID uuid;
    uint32_t ablen;
    uint32_t abelen;

    if (!mxf_disk_file_open_read(filename, &mxfFile))
    {
        mxf_log_error("Failed to open '%s'" LOG_LOC_FORMAT, filename, LOG_LOC_PARAMS);
        return 0;
    }

    /* TEST */
    CHK_OFAIL(mxf_file_read(mxfFile, indata, 100) == 100);
    CHK_OFAIL(memcmp(data, indata, 100) == 0);
    CHK_OFAIL(mxf_file_getc(mxfFile) == 0xff);
    CHK_OFAIL(mxf_file_getc(mxfFile) == 0xff);
    CHK_OFAIL(mxf_read_uint8(mxfFile, &valueu8));
    CHK_OFAIL(valueu8 == 0x0f);
    CHK_OFAIL(mxf_read_uint16(mxfFile, &valueu16));
    CHK_OFAIL(valueu16 == 0x0f00);
    CHK_OFAIL(mxf_read_uint32(mxfFile, &valueu32));
    CHK_OFAIL(valueu32 == 0x0f000000);
    CHK_OFAIL(mxf_read_uint64(mxfFile, &valueu64));
    CHK_OFAIL(valueu64 == 0x0f00000000000000LL);
    CHK_OFAIL(mxf_read_int8(mxfFile, &value8));
    CHK_OFAIL(value8 == -0x0f);
    CHK_OFAIL(mxf_read_int16(mxfFile, &value16));
    CHK_OFAIL(value16 == -0x0f00);
    CHK_OFAIL(mxf_read_int32(mxfFile, &value32));
    CHK_OFAIL(value32 == -0x0f000000);
    CHK_OFAIL(mxf_read_int64(mxfFile, &value64));
    CHK_OFAIL(value64 == -0x0f00000000000000LL);
    CHK_OFAIL(mxf_read_local_tag(mxfFile, &tag));
    CHK_OFAIL(tag == 0xffaa);
    CHK_OFAIL(mxf_read_k(mxfFile, &key));
    CHK_OFAIL(mxf_equals_key(&key, &someKey));
    CHK_OFAIL(mxf_read_l(mxfFile, &llen, &len));
    CHK_OFAIL(llen == 1 && len == 0x01);
    CHK_OFAIL(mxf_read_l(mxfFile, &llen, &len));
    CHK_OFAIL(llen == 2 && len == 0x80);
    CHK_OFAIL(mxf_read_l(mxfFile, &llen, &len));
    CHK_OFAIL(llen == 3 && len == 0x8000);
    CHK_OFAIL(mxf_read_l(mxfFile, &llen, &len));
    CHK_OFAIL(llen == 4 && len == 0x800000);
    CHK_OFAIL(mxf_read_l(mxfFile, &llen, &len));
    CHK_OFAIL(llen == 5 && len == 0x80000000);
    CHK_OFAIL(mxf_read_l(mxfFile, &llen, &len));
    CHK_OFAIL(llen == 6 && len == 0x8000000000LL);
    CHK_OFAIL(mxf_read_l(mxfFile, &llen, &len));
    CHK_OFAIL(llen == 7 && len == 0x800000000000LL);
    CHK_OFAIL(mxf_read_l(mxfFile, &llen, &len));
    CHK_OFAIL(llen == 8 && len == 0x80000000000000LL);
    CHK_OFAIL(mxf_read_l(mxfFile, &llen, &len));
    CHK_OFAIL(llen == 9 && len == 0x8000000000000000LL);
    CHK_OFAIL(mxf_read_kl(mxfFile, &key, &llen, &len));
    CHK_OFAIL(mxf_equals_key(&key, &someKey));
    CHK_OFAIL(llen == 3 && len == 0xf100);
    CHK_OFAIL(mxf_read_l(mxfFile, &llen, &len));
    CHK_OFAIL(llen == 8 && len == 0x10);
    CHK_OFAIL(mxf_read_l(mxfFile, &llen, &len));
    CHK_OFAIL(llen == 4 && len == 0x10);
    CHK_OFAIL(mxf_read_kl(mxfFile, &key, &llen, &len));
    CHK_OFAIL(mxf_equals_key(&key, &someKey));
    CHK_OFAIL(llen == 8 && len == 0x1000);
    CHK_OFAIL(mxf_read_ul(mxfFile, &ul));
    CHK_OFAIL(mxf_equals_ul(&ul, &someUL));
    CHK_OFAIL(mxf_read_uid(mxfFile, &uid));
    CHK_OFAIL(mxf_equals_uid(&uid, &someUID));
    CHK_OFAIL(mxf_read_uuid(mxfFile, &uuid));
    CHK_OFAIL(mxf_equals_uuid(&uuid, &someUUID));
    CHK_OFAIL(mxf_read_batch_header(mxfFile, &ablen, &abelen));
    CHK_OFAIL(ablen == 2 && abelen == 16);
    CHK_OFAIL(mxf_read_array_header(mxfFile, &ablen, &abelen));
    CHK_OFAIL(ablen == 4 && abelen == 32);


    mxf_file_close(&mxfFile);

    
    /* test reading from a byte buffer */
    
    const uint8_t data[5] = {1, 2, 3, 4, 5};
    
    if (!mxf_byte_array_wrap_read(data, sizeof(data), &mxfFile))
    {
        mxf_log_error("Failed to open byte array as MXF file" LOG_LOC_FORMAT, LOG_LOC_PARAMS);
        return 0;
    }

    CHK_OFAIL(mxf_file_tell(mxfFile) == 0);
    CHK_OFAIL(mxf_file_getc(mxfFile) == 1);
    CHK_OFAIL(mxf_file_tell(mxfFile) == 1);
    CHK_OFAIL(mxf_file_read(mxfFile, indata, 4));
    CHK_OFAIL(indata[0] == 2 && indata[1] == 3 && indata[2] == 4 && indata[3] == 5);
    CHK_OFAIL(mxf_file_tell(mxfFile) == 5);
    CHK_OFAIL(mxf_file_eof(mxfFile));
    CHK_OFAIL(mxf_file_getc(mxfFile) == EOF);
    CHK_OFAIL(mxf_file_seek(mxfFile, 0, SEEK_SET));
    CHK_OFAIL(mxf_file_tell(mxfFile) == 0);
    CHK_OFAIL(mxf_file_getc(mxfFile) == 1);
    CHK_OFAIL(mxf_file_seek(mxfFile, 2, SEEK_CUR));
    CHK_OFAIL(mxf_file_tell(mxfFile) == 3);
    CHK_OFAIL(mxf_file_getc(mxfFile) == 4);
    CHK_OFAIL(mxf_file_seek(mxfFile, 0, SEEK_END));
    CHK_OFAIL(mxf_file_tell(mxfFile) == 4);
    CHK_OFAIL(mxf_file_getc(mxfFile) == 5);
    CHK_OFAIL(!mxf_file_seek(mxfFile, 5, SEEK_END)); /* should fail */
    CHK_OFAIL(mxf_file_tell(mxfFile) == 5);
    
    
    mxf_file_close(&mxfFile);

    
    return 1;
    
fail:
    mxf_file_close(&mxfFile);
    return 0;
}
Beispiel #7
0
int write_dv50(FILE* dv50File, MXFFile* mxfFile, int test)
{
    MXFFilePartitions partitions;
    MXFPartition* headerPartition;
    MXFPartition* bodyPartition;
    MXFPartition* footerPartition;
    MXFHeaderMetadata* headerMetadata = NULL;
    MXFMetadataSet* metaDictSet = NULL;
    MXFMetadataSet* prefaceSet = NULL;
    MXFMetadataSet* identSet = NULL;
    MXFMetadataSet* contentStorageSet = NULL;
    MXFMetadataSet* sourcePackageSet = NULL;
    MXFMetadataSet* materialPackageSet = NULL;
    MXFMetadataSet* sourcePackageTrackSet = NULL;
    MXFMetadataSet* materialPackageTrackSet = NULL;
    MXFMetadataSet* sequenceSet = NULL;
    MXFMetadataSet* sourceClipSet = NULL;
    MXFMetadataSet* essContainerDataSet = NULL;
    MXFMetadataSet* cdciDescriptorSet = NULL;
    MXFDataModel* dataModel = NULL;
    MXFIndexTableSegment* indexSegment = NULL;
    MXFEssenceElement* essenceElement = NULL;
    MXFMetadataItem* durationItem1 = NULL;
    MXFMetadataItem* durationItem2 = NULL;
    MXFMetadataItem* durationItem3 = NULL;
    MXFMetadataItem* durationItem4 = NULL;
    MXFMetadataItem* durationItem5 = NULL;
    MXFMetadataItem* imageSizeItem = NULL;
    mxfTimestamp now;
    uint32_t bodySID = 1;
    uint32_t indexSID = 2;
    mxfUUID thisGeneration;
    mxfUTF16Char* companyName = L"BBC Research";
    mxfUTF16Char* productName = L"Write Avid DV-50 example";
    mxfUTF16Char* versionString = L"Alpha version";
    mxfUMID sourcePackageUMID;
    mxfUMID materialPackageUMID;
    uint32_t sourceTrackID = 1;
    uint32_t sourceTrackNumber = 0x18010201;
    mxfRational sampleRate = {25, 1};
    mxfRational editRate = sampleRate;
    mxfLength duration = 0;
    mxfRational aspectRatio = {4, 3};
    mxfUUID indexSegmentUUID;
    uint32_t frameSize = 288000;
    int32_t imageSize = 0;
    int32_t resolutionID = 0x8e;
    const uint32_t essenceBufferSize = 4096;
    uint8_t buffer[4096];
    int done = 0;
    uint8_t* arrayElement;
    int64_t headerMetadataPos;
    
    
    mxf_generate_uuid(&thisGeneration);
    mxf_get_timestamp_now(&now);
    /* Older Avids could fail when given files with UMIDs generated using
       other methods. (Note: not 100% sure this is true) */
    mxf_generate_aafsdk_umid(&sourcePackageUMID);
    mxf_generate_aafsdk_umid(&materialPackageUMID);
    mxf_generate_uuid(&indexSegmentUUID);
    
    mxf_initialise_file_partitions(&partitions);

    
    /* set the minimum llen */
    mxf_file_set_min_llen(mxfFile, 4);
    
    
    /* load the data model, plus AVID extensions */
    
    CHK_ORET(mxf_load_data_model(&dataModel));
    CHK_ORET(mxf_avid_load_extensions(dataModel));
    CHK_ORET(mxf_finalise_data_model(dataModel));
    
    
    
    /* write the header partition pack */

    CHK_ORET(mxf_append_new_partition(&partitions, &headerPartition));
    headerPartition->key = MXF_PP_K(ClosedComplete, Header);
    headerPartition->majorVersion = 1;
    headerPartition->minorVersion = 2;
    headerPartition->kagSize = 0x100;
    headerPartition->operationalPattern = MXF_OP_L(atom, NTracks_1SourceClip);
    CHK_ORET(mxf_append_partition_esscont_label(headerPartition, &MXF_EC_L(DVBased_50_625_50_ClipWrapped)));
    
    CHK_ORET(mxf_write_partition(mxfFile, headerPartition));
    CHK_ORET(mxf_fill_to_kag(mxfFile, headerPartition));
    

    
    /* create the header metadata */
    
    CHK_ORET(mxf_create_header_metadata(&headerMetadata, dataModel));
    
    
    /* create the Avid meta-dictionary */
    
    CHK_ORET(mxf_avid_create_default_metadictionary(headerMetadata, &metaDictSet));
    
    
    /* Preface */
    CHK_ORET(mxf_create_set(headerMetadata, &MXF_SET_K(Preface), &prefaceSet));
    CHK_ORET(mxf_set_timestamp_item(prefaceSet, &MXF_ITEM_K(Preface, LastModifiedDate), &now));
    CHK_ORET(mxf_set_version_type_item(prefaceSet, &MXF_ITEM_K(Preface, Version), 0x0102));
    CHK_ORET(mxf_set_ul_item(prefaceSet, &MXF_ITEM_K(Preface, OperationalPattern), &MXF_OP_L(atom, NTracks_1SourceClip)));
    CHK_ORET(mxf_alloc_array_item_elements(prefaceSet, &MXF_ITEM_K(Preface, EssenceContainers), mxfUL_extlen, 1, &arrayElement));
    mxf_set_ul(&MXF_EC_L(DVBased_50_625_50_ClipWrapped), arrayElement);

    
    /* Preface - Identification */
    CHK_ORET(mxf_create_set(headerMetadata, &MXF_SET_K(Identification), &identSet));
    CHK_ORET(mxf_add_array_item_strongref(prefaceSet, &MXF_ITEM_K(Preface, Identifications), identSet));
    CHK_ORET(mxf_set_uuid_item(identSet, &MXF_ITEM_K(Identification, ThisGenerationUID), &thisGeneration));
    CHK_ORET(mxf_set_utf16string_item(identSet, &MXF_ITEM_K(Identification, CompanyName), companyName));
    CHK_ORET(mxf_set_utf16string_item(identSet, &MXF_ITEM_K(Identification, ProductName), productName));
    CHK_ORET(mxf_set_utf16string_item(identSet, &MXF_ITEM_K(Identification, VersionString), versionString));
    CHK_ORET(mxf_set_uuid_item(identSet, &MXF_ITEM_K(Identification, ProductUID), &g_WrapDV50ProductUID_uuid));
    CHK_ORET(mxf_set_timestamp_item(identSet, &MXF_ITEM_K(Identification, ModificationDate), &now));
    CHK_ORET(mxf_set_product_version_item(identSet, &MXF_ITEM_K(Identification, ToolkitVersion), mxf_get_version()));
    if (test)
    {
        /* use the same string on all platforms to make checking diffs easier */
        CHK_ORET(mxf_set_utf16string_item(identSet, &MXF_ITEM_K(Identification, Platform), L"test platform string"));
    }
    else
    {
        CHK_ORET(mxf_set_utf16string_item(identSet, &MXF_ITEM_K(Identification, Platform), mxf_get_platform_wstring()));
    }
    
    
    /* Preface - ContentStorage */
    CHK_ORET(mxf_create_set(headerMetadata, &MXF_SET_K(ContentStorage), &contentStorageSet));
    CHK_ORET(mxf_set_strongref_item(prefaceSet, &MXF_ITEM_K(Preface, ContentStorage), contentStorageSet));
    
    
    /* Preface - ContentStorage - MaterialPackage */
    CHK_ORET(mxf_create_set(headerMetadata, &MXF_SET_K(MaterialPackage), &materialPackageSet));
    CHK_ORET(mxf_add_array_item_strongref(contentStorageSet, &MXF_ITEM_K(ContentStorage, Packages), materialPackageSet));
    CHK_ORET(mxf_set_umid_item(materialPackageSet, &MXF_ITEM_K(GenericPackage, PackageUID), &materialPackageUMID));
    CHK_ORET(mxf_set_timestamp_item(materialPackageSet, &MXF_ITEM_K(GenericPackage, PackageCreationDate), &now));
    CHK_ORET(mxf_set_timestamp_item(materialPackageSet, &MXF_ITEM_K(GenericPackage, PackageModifiedDate), &now));
    CHK_ORET(mxf_set_utf16string_item(materialPackageSet, &MXF_ITEM_K(GenericPackage, Name), L"writedv50 material"));

    /* Preface - ContentStorage - MaterialPackage - Timeline Track */    
    CHK_ORET(mxf_create_set(headerMetadata, &MXF_SET_K(Track), &materialPackageTrackSet));
    CHK_ORET(mxf_add_array_item_strongref(materialPackageSet, &MXF_ITEM_K(GenericPackage, Tracks), materialPackageTrackSet));
    CHK_ORET(mxf_set_uint32_item(materialPackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackID), sourceTrackID));
    CHK_ORET(mxf_set_uint32_item(materialPackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackNumber), sourceTrackNumber));
    CHK_ORET(mxf_set_rational_item(materialPackageTrackSet, &MXF_ITEM_K(Track, EditRate), &editRate));
    CHK_ORET(mxf_set_position_item(materialPackageTrackSet, &MXF_ITEM_K(Track, Origin), 0));

    /* Preface - ContentStorage - MaterialPackage - Timeline Track - Sequence */    
    CHK_ORET(mxf_create_set(headerMetadata, &MXF_SET_K(Sequence), &sequenceSet));
    CHK_ORET(mxf_set_strongref_item(materialPackageTrackSet, &MXF_ITEM_K(GenericTrack, Sequence), sequenceSet));
    CHK_ORET(mxf_set_ul_item(sequenceSet, &MXF_ITEM_K(StructuralComponent, DataDefinition), &MXF_DDEF_L(LegacyPicture)));
    CHK_ORET(mxf_set_length_item(sequenceSet, &MXF_ITEM_K(StructuralComponent, Duration), duration));

    CHK_ORET(mxf_get_item(sequenceSet, &MXF_ITEM_K(StructuralComponent, Duration), &durationItem1));

    /* Preface - ContentStorage - MaterialPackage - Timeline Track - Sequence - SourceClip */    
    CHK_ORET(mxf_create_set(headerMetadata, &MXF_SET_K(SourceClip), &sourceClipSet));
    CHK_ORET(mxf_add_array_item_strongref(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), sourceClipSet));
    CHK_ORET(mxf_set_ul_item(sourceClipSet, &MXF_ITEM_K(StructuralComponent, DataDefinition), &MXF_DDEF_L(LegacyPicture)));
    CHK_ORET(mxf_set_length_item(sourceClipSet, &MXF_ITEM_K(StructuralComponent, Duration), duration));
    CHK_ORET(mxf_set_position_item(sourceClipSet, &MXF_ITEM_K(SourceClip, StartPosition), 0));
    CHK_ORET(mxf_set_umid_item(sourceClipSet, &MXF_ITEM_K(SourceClip, SourcePackageID), &sourcePackageUMID));
    CHK_ORET(mxf_set_uint32_item(sourceClipSet, &MXF_ITEM_K(SourceClip, SourceTrackID), sourceTrackID));

    CHK_ORET(mxf_get_item(sourceClipSet, &MXF_ITEM_K(StructuralComponent, Duration), &durationItem2));
    
    
    /* Preface - ContentStorage - SourcePackage */
    CHK_ORET(mxf_create_set(headerMetadata, &MXF_SET_K(SourcePackage), &sourcePackageSet));
    CHK_ORET(mxf_add_array_item_strongref(contentStorageSet, &MXF_ITEM_K(ContentStorage, Packages), sourcePackageSet));
    CHK_ORET(mxf_set_weakref_item(prefaceSet, &MXF_ITEM_K(Preface, PrimaryPackage), sourcePackageSet));
    CHK_ORET(mxf_set_umid_item(sourcePackageSet, &MXF_ITEM_K(GenericPackage, PackageUID), &sourcePackageUMID));
    CHK_ORET(mxf_set_timestamp_item(sourcePackageSet, &MXF_ITEM_K(GenericPackage, PackageCreationDate), &now));
    CHK_ORET(mxf_set_timestamp_item(sourcePackageSet, &MXF_ITEM_K(GenericPackage, PackageModifiedDate), &now));
    CHK_ORET(mxf_set_utf16string_item(sourcePackageSet, &MXF_ITEM_K(GenericPackage, Name), L"writedv50 source"));

    /* Preface - ContentStorage - SourcePackage - Timeline Track */    
    CHK_ORET(mxf_create_set(headerMetadata, &MXF_SET_K(Track), &sourcePackageTrackSet));
    CHK_ORET(mxf_add_array_item_strongref(sourcePackageSet, &MXF_ITEM_K(GenericPackage, Tracks), sourcePackageTrackSet));
    CHK_ORET(mxf_set_uint32_item(sourcePackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackID), sourceTrackID));
    CHK_ORET(mxf_set_uint32_item(sourcePackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackNumber), sourceTrackNumber));
    CHK_ORET(mxf_set_rational_item(sourcePackageTrackSet, &MXF_ITEM_K(Track, EditRate), &editRate));
    CHK_ORET(mxf_set_position_item(sourcePackageTrackSet, &MXF_ITEM_K(Track, Origin), 0));

    /* Preface - ContentStorage - SourcePackage - Timeline Track - Sequence */    
    CHK_ORET(mxf_create_set(headerMetadata, &MXF_SET_K(Sequence), &sequenceSet));
    CHK_ORET(mxf_set_strongref_item(sourcePackageTrackSet, &MXF_ITEM_K(GenericTrack, Sequence), sequenceSet));
    CHK_ORET(mxf_set_ul_item(sequenceSet, &MXF_ITEM_K(StructuralComponent, DataDefinition), &MXF_DDEF_L(LegacyPicture)));
    CHK_ORET(mxf_set_length_item(sequenceSet, &MXF_ITEM_K(StructuralComponent, Duration), duration));

    CHK_ORET(mxf_get_item(sequenceSet, &MXF_ITEM_K(StructuralComponent, Duration), &durationItem3));

    /* Preface - ContentStorage - SourcePackage - Timeline Track - Sequence - SourceClip */    
    CHK_ORET(mxf_create_set(headerMetadata, &MXF_SET_K(SourceClip), &sourceClipSet));
    CHK_ORET(mxf_add_array_item_strongref(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), sourceClipSet));
    CHK_ORET(mxf_set_ul_item(sourceClipSet, &MXF_ITEM_K(StructuralComponent, DataDefinition), &MXF_DDEF_L(LegacyPicture)));
    CHK_ORET(mxf_set_length_item(sourceClipSet, &MXF_ITEM_K(StructuralComponent, Duration), duration));
    CHK_ORET(mxf_set_position_item(sourceClipSet, &MXF_ITEM_K(SourceClip, StartPosition), 0));
    CHK_ORET(mxf_set_umid_item(sourceClipSet, &MXF_ITEM_K(SourceClip, SourcePackageID), &g_Null_UMID));
    CHK_ORET(mxf_set_uint32_item(sourceClipSet, &MXF_ITEM_K(SourceClip, SourceTrackID), 0));

    CHK_ORET(mxf_get_item(sourceClipSet, &MXF_ITEM_K(StructuralComponent, Duration), &durationItem4));
    
    /* Preface - ContentStorage - SourcePackage - CDCIEssenceDescriptor */    
    CHK_ORET(mxf_create_set(headerMetadata, &MXF_SET_K(CDCIEssenceDescriptor), &cdciDescriptorSet));
    CHK_ORET(mxf_set_strongref_item(sourcePackageSet, &MXF_ITEM_K(SourcePackage, Descriptor), cdciDescriptorSet));
    CHK_ORET(mxf_set_rational_item(cdciDescriptorSet, &MXF_ITEM_K(FileDescriptor, SampleRate), &sampleRate));
    CHK_ORET(mxf_set_length_item(cdciDescriptorSet, &MXF_ITEM_K(FileDescriptor, ContainerDuration), duration));
    CHK_ORET(mxf_set_ul_item(cdciDescriptorSet, &MXF_ITEM_K(FileDescriptor, EssenceContainer), &MXF_EC_L(DVBased_50_625_50_ClipWrapped)));
    CHK_ORET(mxf_set_ul_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, PictureEssenceCoding), &MXF_CMDEF_L(DVBased_50_625_50)));
    CHK_ORET(mxf_set_uint32_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, StoredHeight), 288));
    CHK_ORET(mxf_set_uint32_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, StoredWidth), 720));
    CHK_ORET(mxf_set_uint32_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, SampledHeight), 288));
    CHK_ORET(mxf_set_uint32_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, SampledWidth), 720));
    CHK_ORET(mxf_set_int32_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, SampledXOffset), 0));
    CHK_ORET(mxf_set_int32_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, SampledYOffset), 0));
    CHK_ORET(mxf_set_uint32_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, DisplayHeight), 288));
    CHK_ORET(mxf_set_uint32_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, DisplayWidth), 720));
    CHK_ORET(mxf_set_int32_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, DisplayXOffset), 0));
    CHK_ORET(mxf_set_int32_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, DisplayYOffset), 0));
    CHK_ORET(mxf_set_uint8_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, FrameLayout), 1));
    CHK_ORET(mxf_alloc_array_item_elements(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, VideoLineMap), 4, 2, &arrayElement));
    mxf_set_int32(23, arrayElement);
    mxf_set_int32(335, &arrayElement[4]);
    CHK_ORET(mxf_set_rational_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, AspectRatio), &aspectRatio));
    CHK_ORET(mxf_set_uint32_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, ImageAlignmentOffset), 1));
    CHK_ORET(mxf_set_uint32_item(cdciDescriptorSet, &MXF_ITEM_K(CDCIEssenceDescriptor, ComponentDepth), 8));
    CHK_ORET(mxf_set_uint32_item(cdciDescriptorSet, &MXF_ITEM_K(CDCIEssenceDescriptor, HorizontalSubsampling), 2));
    CHK_ORET(mxf_set_uint32_item(cdciDescriptorSet, &MXF_ITEM_K(CDCIEssenceDescriptor, VerticalSubsampling), 1));
    CHK_ORET(mxf_set_uint8_item(cdciDescriptorSet, &MXF_ITEM_K(CDCIEssenceDescriptor, ColorSiting), 4));
    CHK_ORET(mxf_set_uint32_item(cdciDescriptorSet, &MXF_ITEM_K(CDCIEssenceDescriptor, BlackRefLevel), 16));
    CHK_ORET(mxf_set_uint32_item(cdciDescriptorSet, &MXF_ITEM_K(CDCIEssenceDescriptor, WhiteReflevel), 235));
    CHK_ORET(mxf_set_uint32_item(cdciDescriptorSet, &MXF_ITEM_K(CDCIEssenceDescriptor, ColorRange), 225));

    CHK_ORET(mxf_get_item(cdciDescriptorSet, &MXF_ITEM_K(FileDescriptor, ContainerDuration), &durationItem5));
    
    CHK_ORET(mxf_set_int32_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, ResolutionID), resolutionID));
    CHK_ORET(mxf_set_int32_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, FrameSampleSize), frameSize));
    CHK_ORET(mxf_set_int32_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, ImageSize), 0));

    CHK_ORET(mxf_get_item(cdciDescriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, ImageSize), &imageSizeItem));
    
    
    /* Preface - ContentStorage - EssenceContainerData */    
    CHK_ORET(mxf_create_set(headerMetadata, &MXF_SET_K(EssenceContainerData), &essContainerDataSet));
    CHK_ORET(mxf_add_array_item_strongref(contentStorageSet, &MXF_ITEM_K(ContentStorage, EssenceContainerData), essContainerDataSet));
    CHK_ORET(mxf_set_umid_item(essContainerDataSet, &MXF_ITEM_K(EssenceContainerData, LinkedPackageUID), &sourcePackageUMID));
    CHK_ORET(mxf_set_uint32_item(essContainerDataSet, &MXF_ITEM_K(EssenceContainerData, IndexSID), indexSID));
    CHK_ORET(mxf_set_uint32_item(essContainerDataSet, &MXF_ITEM_K(EssenceContainerData, BodySID), bodySID));


    /* write the header metadata with Avid extensions */    

    CHK_ORET((headerMetadataPos = mxf_file_tell(mxfFile)) >= 0);
    
    CHK_ORET(mxf_mark_header_start(mxfFile, headerPartition));
    CHK_ORET(mxf_avid_write_header_metadata(mxfFile, headerMetadata, headerPartition));
    CHK_ORET(mxf_fill_to_kag(mxfFile, headerPartition));
    CHK_ORET(mxf_mark_header_end(mxfFile, headerPartition));
    


    /* write the body partition pack */

    CHK_ORET(mxf_append_new_from_partition(&partitions, headerPartition, &bodyPartition));
    bodyPartition->key = MXF_PP_K(ClosedComplete, Body);
    bodyPartition->kagSize = 0x200;
    bodyPartition->bodySID = bodySID;

    CHK_ORET(mxf_write_partition(mxfFile, bodyPartition));
    CHK_ORET(mxf_fill_to_kag(mxfFile, bodyPartition));
    
    
    /* write the DV-50 essence element */
    
    CHK_ORET(mxf_open_essence_element_write(mxfFile, &MXF_EE_K(DVClipWrapped), 8, 0, &essenceElement));
    while (!done)
    {
        size_t numRead = fread(buffer, 1, essenceBufferSize, dv50File);
        if (numRead < essenceBufferSize)
        {
            if (!feof(dv50File))
            {
                fprintf(stderr, "Failed to read bytes from dv50 file\n");
                return 0;
            }
            done = 1;
        }
        
        CHK_ORET(mxf_write_essence_element_data(mxfFile, essenceElement, buffer, (uint32_t)numRead));
    }
    duration = essenceElement->totalLen / frameSize;
    imageSize = (int32_t)essenceElement->totalLen;
    CHK_ORET(mxf_finalize_essence_element_write(mxfFile, essenceElement));
    mxf_close_essence_element(&essenceElement);

    CHK_ORET(mxf_fill_to_kag(mxfFile, bodyPartition));


    
    /* write the footer partition pack */

    CHK_ORET(mxf_append_new_from_partition(&partitions, headerPartition, &footerPartition));
    footerPartition->key = MXF_PP_K(ClosedComplete, Footer);
    footerPartition->kagSize = 0x200;
    footerPartition->indexSID = indexSID;

    CHK_ORET(mxf_write_partition(mxfFile, footerPartition));
    CHK_ORET(mxf_fill_to_kag(mxfFile, footerPartition));

    
    /* write the index table segment */
    
    CHK_ORET(mxf_mark_index_start(mxfFile, footerPartition));
    
    CHK_ORET(mxf_create_index_table_segment(&indexSegment)); 
    indexSegment->instanceUID = indexSegmentUUID;
    indexSegment->indexEditRate = editRate;
    indexSegment->indexStartPosition = 0;
    indexSegment->indexDuration = duration;
    indexSegment->editUnitByteCount = frameSize;
    indexSegment->indexSID = indexSID;
    indexSegment->bodySID = bodySID;
    indexSegment->sliceCount = 0;
    indexSegment->posTableCount = 0;
    indexSegment->deltaEntryArray = NULL;
    indexSegment->indexEntryArray = NULL;
    
    CHK_ORET(mxf_write_index_table_segment(mxfFile, indexSegment));
    CHK_ORET(mxf_fill_to_kag(mxfFile, footerPartition));
    
    CHK_ORET(mxf_mark_index_end(mxfFile, footerPartition));
    

    /* write the random index pack */
    
    CHK_ORET(mxf_write_rip(mxfFile, &partitions));

    
    /* update and re-write the header metadata */
    /* Note: the size will not change so it is safe to re-write */
    
    CHK_ORET(mxf_set_length_item(durationItem1->set, &durationItem1->key, duration));
    CHK_ORET(mxf_set_length_item(durationItem2->set, &durationItem2->key, duration));
    CHK_ORET(mxf_set_length_item(durationItem3->set, &durationItem3->key, duration));
    CHK_ORET(mxf_set_length_item(durationItem4->set, &durationItem4->key, duration));
    CHK_ORET(mxf_set_length_item(durationItem5->set, &durationItem5->key, duration));
    CHK_ORET(mxf_set_int32_item(imageSizeItem->set, &imageSizeItem->key, imageSize));

    CHK_ORET(mxf_file_seek(mxfFile, headerMetadataPos, SEEK_SET));
    CHK_ORET(mxf_mark_header_start(mxfFile, headerPartition));
    CHK_ORET(mxf_avid_write_header_metadata(mxfFile, headerMetadata, headerPartition));
    CHK_ORET(mxf_fill_to_kag(mxfFile, headerPartition));
    CHK_ORET(mxf_mark_header_end(mxfFile, headerPartition));
    

    
    
    /* update the partitions */
    
    CHK_ORET(mxf_update_partitions(mxfFile, &partitions));
    
    
       
    /* free memory resources */

    mxf_free_index_table_segment(&indexSegment);
    mxf_clear_file_partitions(&partitions);
    mxf_free_header_metadata(&headerMetadata);
    mxf_free_data_model(&dataModel);
    
    return 1;
}
Beispiel #8
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;
}
Beispiel #9
0
int mxf_find_footer_partition(MXFFile *mxfFile)
{
    const uint32_t maxIterations = 250; /* i.e. search maximum 8MB */
    const uint32_t bufferSize = 32768 + 15;
    unsigned char *buffer;
    uint32_t numRead = 0;
    int64_t offset;
    int lastIteration = 0;
    uint32_t i, j;

    CHK_MALLOC_ARRAY_ORET(buffer, unsigned char, bufferSize);

    if (!mxf_file_seek(mxfFile, 0, SEEK_END))
        goto fail;

    offset = mxf_file_tell(mxfFile);

    for (i = 0; i < maxIterations; i++) {
        if (offset < 17) /* file must start with a header partition pack */
            break;
        numRead = bufferSize - 15;
        if (numRead > offset)
            numRead = (uint32_t)offset;

        /* first 15 bytes from last read are used for comparison in this read */
        if (i > 0)
            memcpy(buffer + numRead, buffer, 15);

        if (!mxf_file_seek(mxfFile, offset - numRead, SEEK_SET) ||
            mxf_file_read(mxfFile, buffer, numRead) != numRead)
        {
            break;
        }

        for (j = 0; j < numRead; j++) {
            if (buffer[j]     == g_PartitionPackPrefix_key.octet0 &&
                buffer[j + 1] == g_PartitionPackPrefix_key.octet1 &&
                memcmp(&buffer[j + 2], &g_PartitionPackPrefix_key.octet2, 11) == 0)
            {
                if (buffer[j + 13] == 0x04) {
                    /* found footer partition pack key - seek to it */
                    if (!mxf_file_seek(mxfFile, offset - numRead + j, SEEK_SET))
                        goto fail;

                    SAFE_FREE(buffer);
                    return 1;
                } else if (buffer[j + 13] == 0x02 || buffer[j + 13] == 0x03) {
                    /* found a header or body partition pack key - continue search in this buffer only */
                    lastIteration = 1;
                }
            }
        }
        if (lastIteration)
            break;

        offset -= numRead;
    }

fail:
    SAFE_FREE(buffer);
    return 0;
}
int main()
{
    MXFPageFile *mxfPageFile;
    MXFFile *mxfFile;
    uint8_t *data;
    int i;

    data = malloc(DATA_SIZE);


    remove_test_files();


    CHECK(mxf_page_file_open_new(g_testFile, PAGE_SIZE, &mxfPageFile));
    mxfFile = mxf_page_file_get_file(mxfPageFile);

    memset(data, 0, DATA_SIZE);

    CHECK(mxf_file_write(mxfFile, data, DATA_SIZE) == DATA_SIZE);

    mxf_file_close(&mxfFile);



    CHECK(mxf_page_file_open_modify(g_testFile, PAGE_SIZE, &mxfPageFile));
    mxfFile = mxf_page_file_get_file(mxfPageFile);

    memset(data, 1, DATA_SIZE);

    CHECK(mxf_file_size(mxfFile) == DATA_SIZE);
    CHECK(mxf_file_read(mxfFile, data, DATA_SIZE) == DATA_SIZE);
    CHECK(mxf_file_eof(mxfFile));
    CHECK(mxf_file_tell(mxfFile) == DATA_SIZE);

    CHECK(mxf_file_write(mxfFile, data, DATA_SIZE) == DATA_SIZE);
    CHECK(mxf_file_eof(mxfFile));
    CHECK(mxf_file_tell(mxfFile) == DATA_SIZE * 2);

    CHECK(mxf_file_seek(mxfFile, 0, SEEK_SET));
    CHECK(mxf_file_tell(mxfFile) == 0);
    CHECK(mxf_file_write(mxfFile, data, DATA_SIZE) == DATA_SIZE);

    mxf_file_close(&mxfFile);



    CHECK(mxf_page_file_open_read(g_testFile, &mxfPageFile));
    mxfFile = mxf_page_file_get_file(mxfPageFile);

    memset(data, 1, DATA_SIZE);

    CHECK(mxf_file_size(mxfFile) == DATA_SIZE * 2);
    CHECK(mxf_file_read(mxfFile, data, DATA_SIZE) == DATA_SIZE);
    CHECK(mxf_file_tell(mxfFile) == DATA_SIZE);
    CHECK(mxf_file_read(mxfFile, data, DATA_SIZE) == DATA_SIZE);
    CHECK(mxf_file_eof(mxfFile));
    CHECK(mxf_file_tell(mxfFile) == DATA_SIZE * 2);
    CHECK(mxf_file_seek(mxfFile, 0, SEEK_SET));
    CHECK(mxf_file_tell(mxfFile) == 0);
    CHECK(mxf_file_read(mxfFile, data, DATA_SIZE) == DATA_SIZE);
    CHECK(mxf_file_tell(mxfFile) == DATA_SIZE);
    CHECK(mxf_file_seek(mxfFile, DATA_SIZE + 1, SEEK_SET));
    CHECK(mxf_file_read(mxfFile, data, DATA_SIZE - 1) == DATA_SIZE - 1);
    CHECK(mxf_file_tell(mxfFile) == DATA_SIZE * 2);
    CHECK(mxf_file_seek(mxfFile, DATA_SIZE - 1, SEEK_SET));
    CHECK(mxf_file_tell(mxfFile) == DATA_SIZE - 1);
    CHECK(mxf_file_seek(mxfFile, DATA_SIZE * 2, SEEK_SET));
    CHECK(mxf_file_tell(mxfFile) == DATA_SIZE * 2);
    CHECK(mxf_file_seek(mxfFile, 0, SEEK_END));
    CHECK(mxf_file_tell(mxfFile) == DATA_SIZE * 2);
    CHECK(mxf_file_seek(mxfFile, -DATA_SIZE * 2, SEEK_END));
    CHECK(mxf_file_tell(mxfFile) == 0);
    CHECK(mxf_file_seek(mxfFile, DATA_SIZE - 5, SEEK_CUR));
    CHECK(mxf_file_tell(mxfFile) == DATA_SIZE - 5);
    CHECK(mxf_file_read(mxfFile, data, DATA_SIZE) == DATA_SIZE);

    mxf_file_close(&mxfFile);



    CHECK(mxf_page_file_open_new("pagetest_out__%d.mxf", PAGE_SIZE, &mxfPageFile));
    mxfFile = mxf_page_file_get_file(mxfPageFile);

    CHECK(mxf_file_write(mxfFile, data, DATA_SIZE) == DATA_SIZE);

    mxf_file_close(&mxfFile);

    CHECK(mxf_page_file_remove("pagetest_out__%d.mxf"));


    /* test forward truncate */

    CHECK(mxf_page_file_open_new(g_testFile, PAGE_SIZE, &mxfPageFile));
    mxfFile = mxf_page_file_get_file(mxfPageFile);

    memset(data, 0, DATA_SIZE);

    for (i = 0; i < 10; i++)
    {
        CHECK(mxf_file_write(mxfFile, data, DATA_SIZE) == DATA_SIZE);
    }

    mxf_file_close(&mxfFile);


    CHECK(mxf_page_file_open_modify(g_testFile, PAGE_SIZE, &mxfPageFile));
    mxfFile = mxf_page_file_get_file(mxfPageFile);

    memset(data, 1, DATA_SIZE);

    CHECK(mxf_page_file_forward_truncate(mxfPageFile));

    for (i = 0; i < 5; i++)
    {
        CHECK(mxf_file_read(mxfFile, data, DATA_SIZE) == DATA_SIZE);
    }
    CHECK(mxf_page_file_forward_truncate(mxfPageFile));

    for (i = 0; i < 4; i++)
    {
        CHECK(mxf_file_read(mxfFile, data, DATA_SIZE) == DATA_SIZE);
    }
    CHECK(mxf_page_file_forward_truncate(mxfPageFile));

    CHECK(mxf_file_read(mxfFile, data, DATA_SIZE) == DATA_SIZE);
    CHECK(mxf_page_file_forward_truncate(mxfPageFile));

    mxf_file_close(&mxfFile);

    CHECK(mxf_page_file_remove(g_testFile));


    free(data);

    return 0;
}
Beispiel #11
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;
}
Beispiel #12
0
int op1a_initialise_reader(MXFReader *reader, MXFPartition **headerPartition)
{
    MXFFile *mxfFile = reader->mxfFile;
    EssenceReader *essenceReader = reader->essenceReader;
    EssenceReaderData *data;
    size_t i;
    size_t numPartitions;
    MXFPartition *partition;
    mxfKey key;
    uint8_t llen;
    uint64_t len;

    essenceReader->data = NULL;


    /* init essence reader */
    CHK_MALLOC_OFAIL(essenceReader->data, EssenceReaderData);
    memset(essenceReader->data, 0, sizeof(EssenceReaderData));
    essenceReader->data->headerPartition = *headerPartition;
    essenceReader->close = op1a_close;
    essenceReader->position_at_frame = op1a_position_at_frame;
    essenceReader->skip_next_frame = op1a_skip_next_frame;
    essenceReader->read_next_frame = op1a_read_next_frame;
    essenceReader->get_next_frame_number = op1a_get_next_frame_number;
    essenceReader->get_last_written_frame_number = op1a_get_last_written_frame_number;
    essenceReader->get_header_metadata = op1a_get_header_metadata;
    essenceReader->have_footer_metadata = op1a_have_footer_metadata;
    essenceReader->set_frame_rate = op1a_set_frame_rate;

    data = essenceReader->data;


    if (mxf_file_is_seekable(mxfFile))
    {
        /* get the file partitions */
        CHK_OFAIL(get_file_partitions(mxfFile, data->headerPartition, &data->partitions));


        /* process the last instance of header metadata */
        numPartitions = mxf_get_list_length(&data->partitions);
        for (i = numPartitions; i > 0; i--)
        {
            partition = (MXFPartition*)mxf_get_list_element(&data->partitions, i - 1);
            if (partition->headerByteCount != 0)
            {
                if (!mxf_partition_is_closed(&partition->key))
                {
                    mxf_log_warn("No closed partition with header metadata found" LOG_LOC_FORMAT, LOG_LOC_PARAMS);
                }
                if (!mxf_partition_is_complete(&partition->key))
                {
                    mxf_log_warn("No complete partition with header metadata found" LOG_LOC_FORMAT, LOG_LOC_PARAMS);
                }

                /* seek to start of partition and skip the partition pack */
                CHK_OFAIL(mxf_file_seek(mxfFile, partition->thisPartition, SEEK_SET));
                CHK_OFAIL(mxf_read_kl(mxfFile, &key, &llen, &len));
                CHK_OFAIL(mxf_skip(mxfFile, len));

                CHK_OFAIL(process_metadata(reader, partition));
                if (mxf_is_footer_partition_pack(&partition->key))
                {
                    data->haveFooterMetadata = 1;
                }
                break;
            }
        }
        if (i == 0)
        {
            mxf_log_error("No partition with header metadata found" LOG_LOC_FORMAT, LOG_LOC_PARAMS);
            goto fail;
        }


        if (!reader->isMetadataOnly)
        {
            /* create file index */
            CHK_OFAIL(create_index(mxfFile, &data->partitions, data->indexSID, data->bodySID, &data->index));


            /* position at start of essence */
            CHK_OFAIL(set_position(mxfFile, data->index, 0));
        }
    }
    else
    {
        essenceReader->data->nsIndex.currentPosition = -1;

        /* process the header metadata */
        if (!mxf_partition_is_closed(&data->headerPartition->key))
        {
            mxf_log_warn("Header partition is not closed" LOG_LOC_FORMAT, LOG_LOC_PARAMS);
        }
        if (!mxf_partition_is_complete(&data->headerPartition->key))
        {
            mxf_log_warn("Header partition is incomplete" LOG_LOC_FORMAT, LOG_LOC_PARAMS);
        }
        CHK_OFAIL(process_metadata(reader, data->headerPartition));


        if (!reader->isMetadataOnly)
        {
            /* position at start of essence */
            CHK_OFAIL(ns_position_at_first_frame(reader));
        }
    }


    *headerPartition = NULL; /* take ownership */
    return 1;

fail:
    reader->essenceReader->data->headerPartition = NULL; /* release ownership */
    /* essenceReader->close() will be called when closing the reader */
    return 0;
}