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; } }
void* mxf_get_list_element(MXFList* list, long index) { long currentIndex = 0; MXFListElement* element = list->elements; if (index < 0 || index > list->len - 1) { return NULL; } if (index == 0) { return mxf_get_first_list_element(list); } if (index == list->len - 1) { return mxf_get_last_list_element(list); } while (currentIndex != index && element != NULL) { currentIndex++; element = element->next; } if (currentIndex != index || element == NULL) { return NULL; } return element->data; }
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 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; }