void mxf_update_partitions_in_memory(MXFFilePartitions *partitions) { MXFPartition *previousPartition; MXFPartition *lastPartition; MXFListIterator iter; int haveFooter; /* check if anything there to update */ if (mxf_get_list_length(partitions) == 0) { return; } /* update partition packs with previousPartition and footerPartition (if present) offsets */ lastPartition = (MXFPartition*)mxf_get_last_list_element(partitions); haveFooter = mxf_is_footer_partition_pack(&lastPartition->key); previousPartition = NULL; mxf_initialise_list_iter(&iter, partitions); while (mxf_next_list_iter_element(&iter)) { MXFPartition *partition = (MXFPartition*)mxf_get_iter_element(&iter); if (previousPartition != NULL) { partition->previousPartition = previousPartition->thisPartition; } if (haveFooter) { partition->footerPartition = lastPartition->thisPartition; } previousPartition = partition; } }
int mxf_write_rip(MXFFile *mxfFile, MXFFilePartitions *partitions) { uint32_t numPartitions; uint64_t len; uint8_t llen; MXFListIterator iter; numPartitions = (uint32_t)mxf_get_list_length(partitions); len = (4 + 8) * numPartitions + 4; CHK_ORET(mxf_write_k(mxfFile, &g_RandomIndexPack_key)); CHK_ORET((llen = mxf_write_l(mxfFile, len)) != 0); mxf_initialise_list_iter(&iter, partitions); while (mxf_next_list_iter_element(&iter)) { MXFPartition *partition = (MXFPartition*)mxf_get_iter_element(&iter); CHK_ORET(mxf_write_uint32(mxfFile, partition->bodySID)); CHK_ORET(mxf_write_uint64(mxfFile, partition->thisPartition)); } CHK_ORET(mxf_write_uint32(mxfFile, (uint32_t)(16 + llen + len))); return 1; }
int is_null_timecode_index(TimecodeIndex* index) { TimecodeIndexArray* indexArray; long listLen; /* index is null if the index is empty or has a duration > 1 with timecode frozen at 00:00:00:00 */ listLen = mxf_get_list_length(&index->indexArrays); if (listLen == 0) { return 1; } else if (listLen == 1) { indexArray = (TimecodeIndexArray*)mxf_get_first_list_element(&index->indexArrays); if (indexArray->numElements == 0 || (indexArray->numElements == 1 && indexArray->elements[0].frozen && indexArray->elements[0].timecodePos == 0 && indexArray->elements[0].duration > 1)) { return 1; } } return 0; }
int mxf_find_singular_set_by_key(MXFHeaderMetadata* headerMetadata, const mxfKey* key, MXFMetadataSet** set) { MXFList* setList = NULL; if (!mxf_find_set_by_key(headerMetadata, key, &setList)) { return 0; } CHK_OFAIL(mxf_get_list_length(setList) == 1); *set = (MXFMetadataSet*)mxf_get_first_list_element(setList); mxf_free_list(&setList); return 1; fail: mxf_free_list(&setList); return 0; }
int archive_mxf_is_metadata_only(const char* filename) { MXFPageFile* mxfPageFile = NULL; MXFFile* mxfFile = NULL; mxfKey key; uint8_t llen; uint64_t len; MXFPartition* headerPartition = NULL; int result; /* open MXF file */ if (strstr(filename, "%d") != NULL) { CHK_OFAIL_NOMSG(mxf_page_file_open_read(filename, &mxfPageFile)); mxfFile = mxf_page_file_get_file(mxfPageFile); } else { CHK_OFAIL_NOMSG(mxf_disk_file_open_read(filename, &mxfFile)); } /* read header partition pack */ if (!mxf_read_header_pp_kl_with_runin(mxfFile, &key, &llen, &len) || !mxf_read_partition(mxfFile, &key, &headerPartition)) { return 0; } /* check whether there is an essence container label */ result = (mxf_get_list_length(&headerPartition->essenceContainers) == 0); mxf_free_partition(&headerPartition); mxf_file_close(&mxfFile); return result; fail: mxf_free_partition(&headerPartition); mxf_file_close(&mxfFile); return 0; }
int mxf_write_partition(MXFFile *mxfFile, MXFPartition *partition) { uint32_t essenceContainerLen = (uint32_t)mxf_get_list_length(&partition->essenceContainers); uint64_t packLen = 88 + mxfUL_extlen * essenceContainerLen; int64_t filePos; MXFListIterator iter; CHK_ORET((filePos = mxf_file_tell(mxfFile)) >= 0); partition->thisPartition = filePos - mxf_get_runin_len(mxfFile); if (mxf_is_footer_partition_pack(&partition->key)) { partition->footerPartition = partition->thisPartition; } CHK_ORET(mxf_write_kl(mxfFile, &partition->key, packLen)); CHK_ORET(mxf_write_uint16(mxfFile, partition->majorVersion)); CHK_ORET(mxf_write_uint16(mxfFile, partition->minorVersion)); CHK_ORET(mxf_write_uint32(mxfFile, partition->kagSize)); CHK_ORET(mxf_write_uint64(mxfFile, partition->thisPartition)); CHK_ORET(mxf_write_uint64(mxfFile, partition->previousPartition)); CHK_ORET(mxf_write_uint64(mxfFile, partition->footerPartition)); CHK_ORET(mxf_write_uint64(mxfFile, partition->headerByteCount)); CHK_ORET(mxf_write_uint64(mxfFile, partition->indexByteCount)); CHK_ORET(mxf_write_uint32(mxfFile, partition->indexSID)); CHK_ORET(mxf_write_uint64(mxfFile, partition->bodyOffset)); CHK_ORET(mxf_write_uint32(mxfFile, partition->bodySID)); CHK_ORET(mxf_write_ul(mxfFile, &partition->operationalPattern)); CHK_ORET(mxf_write_batch_header(mxfFile, essenceContainerLen, mxfUL_extlen)); mxf_initialise_list_iter(&iter, &partition->essenceContainers); while (mxf_next_list_iter_element(&iter)) { CHK_ORET(mxf_write_ul(mxfFile, (mxfUL*)mxf_get_iter_element(&iter))); } return 1; }
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 add_timecode_to_index(TimecodeIndex* index, ArchiveTimecode* timecode) { TimecodeIndexArray* newArray = NULL; TimecodeIndexArray* lastArray; int64_t timecodePos = timecode_to_position(timecode); if (mxf_get_list_length(&index->indexArrays) == 0) { CHK_MALLOC_OFAIL(newArray, TimecodeIndexArray); CHK_MALLOC_ARRAY_OFAIL(newArray->elements, TimecodeIndexElement, index->arraySize); newArray->numElements = 0; CHK_OFAIL(mxf_append_list_element(&index->indexArrays, newArray)); newArray = NULL; /* list has ownership */ } lastArray = (TimecodeIndexArray*)mxf_get_last_list_element(&index->indexArrays); if (lastArray->numElements != 0) { if (lastArray->elements[lastArray->numElements - 1].timecodePos + lastArray->elements[lastArray->numElements - 1].duration == timecodePos) { /* timecode is previous + 1 */ lastArray->elements[lastArray->numElements - 1].duration++; } else if (lastArray->elements[lastArray->numElements - 1].timecodePos == timecodePos && (lastArray->elements[lastArray->numElements - 1].frozen || lastArray->elements[lastArray->numElements - 1].duration == 1)) { /* timecode is frozen with the previous timecode value */ lastArray->elements[lastArray->numElements - 1].frozen = 1; lastArray->elements[lastArray->numElements - 1].duration++; } else { /* timecode is not frozen or previous + 1 */ if (lastArray->numElements == index->arraySize) { CHK_MALLOC_OFAIL(newArray, TimecodeIndexArray); CHK_MALLOC_ARRAY_OFAIL(newArray->elements, TimecodeIndexElement, index->arraySize); newArray->numElements = 0; CHK_OFAIL(mxf_append_list_element(&index->indexArrays, newArray)); newArray = NULL; /* list has ownership */ lastArray = (TimecodeIndexArray*)mxf_get_last_list_element(&index->indexArrays); } lastArray->numElements++; lastArray->elements[lastArray->numElements - 1].frozen = 0; lastArray->elements[lastArray->numElements - 1].timecodePos = timecodePos; lastArray->elements[lastArray->numElements - 1].duration = 1; } } else { lastArray->numElements++; lastArray->elements[lastArray->numElements - 1].frozen = 0; lastArray->elements[lastArray->numElements - 1].timecodePos = timecodePos; lastArray->elements[lastArray->numElements - 1].duration = 1; } return 1; fail: free_index_array(&newArray); return 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; }
int op1a_is_supported(MXFPartition *headerPartition) { MXFListIterator iter; mxfUL *label; int supportCount = 0; if (!mxf_is_op_1a(&headerPartition->operationalPattern)) { return 0; } if (mxf_get_list_length(&headerPartition->essenceContainers) == 0) { /* metadata only */ return 1; } if (mxf_get_list_length(&headerPartition->essenceContainers) == 1) { label = (mxfUL*)mxf_get_list_element(&headerPartition->essenceContainers, 0); if (is_d10_essence(label)) { return 1; } } mxf_initialise_list_iter(&iter, &headerPartition->essenceContainers); while (mxf_next_list_iter_element(&iter)) { label = (mxfUL*)mxf_get_iter_element(&iter); if (mxf_equals_ul(label, &MXF_EC_L(MultipleWrappings))) { supportCount++; } else if (is_d10_picture_essence(label)) { supportCount++; } else if (mxf_equals_ul(label, &MXF_EC_L(IECDV_25_525_60_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(IECDV_25_625_50_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(DVBased_25_525_60_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(DVBased_25_625_50_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(DVBased_50_525_60_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(DVBased_50_625_50_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(DVBased_100_1080_50_I_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(DVBased_100_1080_60_I_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(DVBased_100_720_50_P_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(DVBased_100_720_60_P_FrameWrapped))) { supportCount++; } else if (mxf_equals_ul(label, &MXF_EC_L(SD_Unc_625_50i_422_135_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(SD_Unc_525_5994i_422_135_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_50i_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_5994i_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_25p_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_50p_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_2997p_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_5994p_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_720_25p_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_720_2997p_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_720_50p_422_FrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(HD_Unc_720_5994p_422_FrameWrapped))) { supportCount++; } else if (mxf_equals_ul(label, &MXF_EC_L(BWFFrameWrapped)) || mxf_equals_ul(label, &MXF_EC_L(AES3FrameWrapped))) { supportCount++; } else if (mxf_is_avc_ec(label, 1)) { supportCount++; } } return supportCount > 0; }