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; }
/* 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; }
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; }
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; }
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; }
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; }
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; }
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; }
static int get_file_partitions(MXFFile *mxfFile, MXFPartition *headerPartition, MXFList *partitions) { mxfKey key; uint8_t llen; uint64_t len; MXFPartition *partition = NULL; MXFPartition *partitionRef; uint64_t thisPartition; MXFRIP rip; MXFRIPEntry *ripEntry; MXFListIterator iter; mxf_initialise_list(partitions, free_partition_in_list); memset(&rip, 0, sizeof(MXFRIP)); /* use the RIP if there is one */ if (mxf_read_rip(mxfFile, &rip)) { mxf_initialise_list_iter(&iter, &rip.entries); while (mxf_next_list_iter_element(&iter)) { ripEntry = (MXFRIPEntry*)mxf_get_iter_element(&iter); /* seek to partition and read and add to list */ CHK_OFAIL(mxf_file_seek(mxfFile, mxf_get_runin_len(mxfFile) + ripEntry->thisPartition, SEEK_SET)); CHK_OFAIL(mxf_read_kl(mxfFile, &key, &llen, &len)); CHK_OFAIL(mxf_is_partition_pack(&key)); CHK_OFAIL(mxf_read_partition(mxfFile, &key, &partition)); CHK_OFAIL(mxf_append_list_element(partitions, partition)); partition = NULL; /* owned by list */ } } /* start from footer partition and index back to the header partition */ else { if (headerPartition->footerPartition == 0) { /* no footer partition or at unknown position, so we only index the header partition */ goto fail; } thisPartition = headerPartition->footerPartition; do { /* seek to partition and read and add to list */ CHK_OFAIL(mxf_file_seek(mxfFile, mxf_get_runin_len(mxfFile) + thisPartition, SEEK_SET)); CHK_OFAIL(mxf_read_kl(mxfFile, &key, &llen, &len)); CHK_OFAIL(mxf_is_partition_pack(&key)); CHK_OFAIL(mxf_read_partition(mxfFile, &key, &partition)); CHK_OFAIL(mxf_prepend_list_element(partitions, partition)); partitionRef = partition; partition = NULL; /* owned by list */ thisPartition = partitionRef->previousPartition; } while (partitionRef->thisPartition != partitionRef->previousPartition); } mxf_clear_rip(&rip); return 1; fail: /* if something failed then just add the header partition Note: some Omneon files had references to a footer partition which was not actually present in the file */ mxf_clear_list(partitions); mxf_free_partition(&partition); mxf_clear_rip(&rip); /* create copy of header partition pack */ CHK_ORET(mxf_create_from_partition(headerPartition, &partition)); partition->key = headerPartition->key; partition->majorVersion = headerPartition->majorVersion; partition->minorVersion = headerPartition->minorVersion; partition->kagSize = headerPartition->kagSize; partition->thisPartition = headerPartition->thisPartition; partition->previousPartition = headerPartition->previousPartition; partition->footerPartition = headerPartition->footerPartition; partition->headerByteCount = headerPartition->headerByteCount; partition->indexByteCount = headerPartition->indexByteCount; partition->indexSID = headerPartition->indexSID; partition->bodyOffset = headerPartition->bodyOffset; partition->bodySID = headerPartition->bodySID; /* add partition to list */ if (!mxf_append_list_element(partitions, partition)) { mxf_free_partition(&partition); mxf_log_error("Failed to append header partition to list" LOG_LOC_FORMAT, LOG_LOC_PARAMS); return 0; } return 1; }
int 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; }