int mxf_mem_file_open_read(const unsigned char *data, int64_t size, int64_t virtualStartPos, MXFMemoryFile **mxfMemFile) { MXFFile *newMXFFile = NULL; CHK_MALLOC_ORET(newMXFFile, MXFFile); memset(newMXFFile, 0, sizeof(*newMXFFile)); newMXFFile->close = mem_file_close; newMXFFile->read = mem_file_read; newMXFFile->write = mem_file_write; newMXFFile->get_char = mem_file_getchar; newMXFFile->put_char = mem_file_putchar; newMXFFile->eof = mem_file_eof; newMXFFile->seek = mem_file_seek; newMXFFile->tell = mem_file_tell; newMXFFile->is_seekable = mem_file_is_seekable; newMXFFile->size = mem_file_size; newMXFFile->free_sys_data = free_mem_file; CHK_MALLOC_OFAIL(newMXFFile->sysData, MXFFileSysData); memset(newMXFFile->sysData, 0, sizeof(*newMXFFile->sysData)); newMXFFile->sysData->virtualStartPos = virtualStartPos; newMXFFile->sysData->readOnly = 1; newMXFFile->sysData->mxfMemFile.mxfFile = newMXFFile; CHK_MALLOC_OFAIL(newMXFFile->sysData->chunks, Chunk); newMXFFile->sysData->chunks->data = (unsigned char*)data; newMXFFile->sysData->chunks->allocSize = size; newMXFFile->sysData->chunks->size = size; newMXFFile->sysData->numChunks++; *mxfMemFile = &newMXFFile->sysData->mxfMemFile; return 1; fail: if (newMXFFile) mxf_file_close(&newMXFFile); return 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_page_file_open_new(const char *filenameTemplate, int64_t pageSize, MXFPageFile **mxfPageFile) { MXFFile *newMXFFile = NULL; if (strstr(filenameTemplate, "%d") == NULL) { mxf_log_error("Filename template '%s' doesn't contain %%d\n", filenameTemplate); return 0; } CHK_MALLOC_ORET(newMXFFile, MXFFile); memset(newMXFFile, 0, sizeof(*newMXFFile)); newMXFFile->close = page_file_close; newMXFFile->read = page_file_read; newMXFFile->write = page_file_write; newMXFFile->get_char = page_file_getchar; newMXFFile->put_char = page_file_putchar; newMXFFile->eof = page_file_eof; newMXFFile->seek = page_file_seek; newMXFFile->tell = page_file_tell; newMXFFile->is_seekable = page_file_is_seekable; newMXFFile->size = page_file_size; newMXFFile->free_sys_data = free_page_file; CHK_MALLOC_OFAIL(newMXFFile->sysData, MXFFileSysData); memset(newMXFFile->sysData, 0, sizeof(*newMXFFile->sysData)); CHK_OFAIL((newMXFFile->sysData->filenameTemplate = strdup(filenameTemplate)) != NULL); newMXFFile->sysData->pageSize = pageSize; newMXFFile->sysData->mode = WRITE_MODE; newMXFFile->sysData->mxfPageFile.mxfFile = newMXFFile; *mxfPageFile = &newMXFFile->sysData->mxfPageFile; return 1; fail: if (newMXFFile != NULL) { mxf_file_close(&newMXFFile); } return 0; }
int mxf_mem_file_open_new(uint32_t chunkSize, int64_t virtualStartPos, MXFMemoryFile **mxfMemFile) { MXFFile *newMXFFile = NULL; CHK_MALLOC_ORET(newMXFFile, MXFFile); memset(newMXFFile, 0, sizeof(*newMXFFile)); newMXFFile->close = mem_file_close; newMXFFile->read = mem_file_read; newMXFFile->write = mem_file_write; newMXFFile->get_char = mem_file_getchar; newMXFFile->put_char = mem_file_putchar; newMXFFile->eof = mem_file_eof; newMXFFile->seek = mem_file_seek; newMXFFile->tell = mem_file_tell; newMXFFile->is_seekable = mem_file_is_seekable; newMXFFile->size = mem_file_size; newMXFFile->free_sys_data = free_mem_file; CHK_MALLOC_OFAIL(newMXFFile->sysData, MXFFileSysData); memset(newMXFFile->sysData, 0, sizeof(*newMXFFile->sysData)); newMXFFile->sysData->chunkSize = (chunkSize == 0 ? DEFAULT_CHUNK_SIZE : chunkSize); newMXFFile->sysData->virtualStartPos = virtualStartPos; newMXFFile->sysData->mxfMemFile.mxfFile = newMXFFile; *mxfMemFile = &newMXFFile->sysData->mxfMemFile; return 1; fail: if (newMXFFile) mxf_file_close(&newMXFFile); return 0; }
int mxf_page_file_open_modify(const char *filenameTemplate, int64_t pageSize, MXFPageFile **mxfPageFile) { MXFFile *newMXFFile = NULL; int pageCount; int allocatedPages; char filename[4096]; FILE *file; int64_t fileSize; if (strstr(filenameTemplate, "%d") == NULL) { mxf_log_error("Filename template '%s' doesn't contain %%d\n", filenameTemplate); return 0; } /* count number of page files */ pageCount = 0; for(;;) { mxf_snprintf(filename, sizeof(filename), filenameTemplate, pageCount); if ((file = fopen(filename, "rb")) == NULL) { break; } fclose(file); pageCount++; } if (pageCount == 0) { /* file not found */ return 0; } /* check the size of the first file equals the pageSize */ if (pageCount > 1) { mxf_snprintf(filename, sizeof(filename), filenameTemplate, 0); fileSize = disk_file_size(filename); if (fileSize < 0) { mxf_log_error("Failed to stat file '%s': %s\n", filename, strerror(errno)); return 0; } if (pageSize != fileSize) { mxf_log_error("Size of first file '%s' (%"PRId64" does not equal page size %"PRId64"\n", filename, fileSize, pageSize); return 0; } } CHK_MALLOC_ORET(newMXFFile, MXFFile); memset(newMXFFile, 0, sizeof(*newMXFFile)); newMXFFile->close = page_file_close; newMXFFile->read = page_file_read; newMXFFile->write = page_file_write; newMXFFile->get_char = page_file_getchar; newMXFFile->put_char = page_file_putchar; newMXFFile->eof = page_file_eof; newMXFFile->seek = page_file_seek; newMXFFile->tell = page_file_tell; newMXFFile->is_seekable = page_file_is_seekable; newMXFFile->size = page_file_size; newMXFFile->free_sys_data = free_page_file; CHK_MALLOC_OFAIL(newMXFFile->sysData, MXFFileSysData); memset(newMXFFile->sysData, 0, sizeof(*newMXFFile->sysData)); CHK_OFAIL((newMXFFile->sysData->filenameTemplate = strdup(filenameTemplate)) != NULL); newMXFFile->sysData->pageSize = pageSize; newMXFFile->sysData->mode = MODIFY_MODE; newMXFFile->sysData->mxfPageFile.mxfFile = newMXFFile; /* allocate pages */ allocatedPages = (pageCount < PAGE_ALLOC_INCR) ? PAGE_ALLOC_INCR : pageCount; CHK_MALLOC_ARRAY_ORET(newMXFFile->sysData->pages, Page, allocatedPages); memset(newMXFFile->sysData->pages, 0, allocatedPages * sizeof(Page)); newMXFFile->sysData->numPages = pageCount; newMXFFile->sysData->numPagesAllocated = allocatedPages; for (pageCount = 0; pageCount < newMXFFile->sysData->numPages; pageCount++) { newMXFFile->sysData->pages[pageCount].index = pageCount; newMXFFile->sysData->pages[pageCount].size = pageSize; } /* set the files size of the last file, which could have size < pageSize */ mxf_snprintf(filename, sizeof(filename), filenameTemplate, newMXFFile->sysData->numPages - 1); fileSize = disk_file_size(filename); if (fileSize < 0) { mxf_log_error("Failed to stat file '%s': %s\n", filename, strerror(errno)); goto fail; } newMXFFile->sysData->pages[newMXFFile->sysData->numPages - 1].size = fileSize; *mxfPageFile = &newMXFFile->sysData->mxfPageFile; return 1; fail: if (newMXFFile != NULL) { mxf_file_close(&newMXFFile); } return 0; }
static int open_file(MXFFileSysData *sysData, Page *page) { FILE *newFile = NULL; char filename[4096]; FileDescriptor *newFileDescriptor = NULL; if (page->wasRemoved) { mxf_log_warn("Failed to open mxf page file which was removed after truncation\n"); return 0; } /* move file descriptor to tail if already open, and return */ if (page->fileDescriptor != NULL) { if (page->fileDescriptor == sysData->fileDescriptorTail) { return 1; } /* extract file descriptor */ if (page->fileDescriptor->next != NULL) { page->fileDescriptor->next->prev = page->fileDescriptor->prev; } if (page->fileDescriptor->prev != NULL) { page->fileDescriptor->prev->next = page->fileDescriptor->next; } if (sysData->fileDescriptorHead == page->fileDescriptor) { sysData->fileDescriptorHead = page->fileDescriptor->next; } /* put file descriptor at tail */ page->fileDescriptor->next = NULL; page->fileDescriptor->prev = sysData->fileDescriptorTail; if (sysData->fileDescriptorTail != NULL) { sysData->fileDescriptorTail->next = page->fileDescriptor; } sysData->fileDescriptorTail = page->fileDescriptor; return 1; } /* close the least used file descriptor (the head) if too many file descriptors are open */ if (sysData->numFileDescriptors >= MAX_FILE_DESCRIPTORS) { if (sysData->fileDescriptorTail == sysData->fileDescriptorHead) { /* single file descriptor */ sysData->fileDescriptorHead->page->fileDescriptor = NULL; disk_file_close(sysData->fileDescriptorHead); SAFE_FREE(sysData->fileDescriptorHead); sysData->fileDescriptorHead = NULL; sysData->fileDescriptorTail = NULL; sysData->numFileDescriptors--; } else { /* multiple file descriptors */ FileDescriptor *newHead = sysData->fileDescriptorHead->next; sysData->fileDescriptorHead->page->fileDescriptor = NULL; disk_file_close(sysData->fileDescriptorHead); SAFE_FREE(sysData->fileDescriptorHead); sysData->fileDescriptorHead = newHead; newHead->prev = NULL; sysData->numFileDescriptors--; } } /* open the file */ mxf_snprintf(filename, sizeof(filename), sysData->filenameTemplate, page->index); switch (sysData->mode) { case READ_MODE: newFile = fopen(filename, "rb"); break; case WRITE_MODE: if (!page->wasOpenedBefore) { newFile = fopen(filename, "w+b"); } else { newFile = fopen(filename, "r+b"); } break; case MODIFY_MODE: newFile = fopen(filename, "r+b"); if (newFile == NULL) { newFile = fopen(filename, "w+b"); } break; } if (newFile == NULL) { mxf_log_error("Failed to open paged mxf file '%s': %s\n", filename, strerror(errno)); return 0; } /* create the new file descriptor */ CHK_MALLOC_OFAIL(newFileDescriptor, FileDescriptor); memset(newFileDescriptor, 0, sizeof(*newFileDescriptor)); newFileDescriptor->file = newFile; newFile = NULL; newFileDescriptor->page = page; page->fileDescriptor = newFileDescriptor; page->wasOpenedBefore = 1; page->offset = 0; if (sysData->fileDescriptorTail != NULL) { sysData->fileDescriptorTail->next = newFileDescriptor; } newFileDescriptor->prev = sysData->fileDescriptorTail; sysData->fileDescriptorTail = newFileDescriptor; if (sysData->fileDescriptorHead == NULL) { sysData->fileDescriptorHead = newFileDescriptor; } sysData->numFileDescriptors++; return 1; fail: if (newFile != NULL) { fclose(newFile); } 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; }
static int mxf_win32_file_open(const char *in_filename, int flags, OpenMode mode, MXFFile **mxfFile) { MXFFile *newMXFFile = NULL; MXFFileSysData *newDiskFile = NULL; int attrs_and_flags = FILE_ATTRIBUTE_NORMAL; #if !defined (_UNICODE) const char *filename = in_filename; #else wchar_t *filename = NULL; size_t size; CHK_OFAIL((size = mbstowcs(NULL, in_filename, 0)) != (size_t)(-1)); size += 1; CHK_MALLOC_ARRAY_OFAIL(filename, wchar_t, size); mbstowcs(filename, in_filename, size); #endif CHK_MALLOC_OFAIL(newMXFFile, MXFFile); memset(newMXFFile, 0, sizeof(MXFFile)); CHK_MALLOC_OFAIL(newDiskFile, MXFFileSysData); memset(newDiskFile, 0, sizeof(MXFFileSysData)); newDiskFile->file = INVALID_HANDLE_VALUE; if (flags & MXF_WIN32_FLAG_RANDOM_ACCESS) attrs_and_flags |= FILE_FLAG_RANDOM_ACCESS; else if (flags & MXF_WIN32_FLAG_SEQUENTIAL_SCAN) attrs_and_flags |= FILE_FLAG_SEQUENTIAL_SCAN; switch (mode) { case NEW_MODE: newDiskFile->file = CreateFile(filename, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, attrs_and_flags, NULL); break; case READ_MODE: newDiskFile->file = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, attrs_and_flags, NULL); break; case MODIFY_MODE: newDiskFile->file = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, attrs_and_flags, NULL); break; } if (newDiskFile->file == INVALID_HANDLE_VALUE) goto fail; #if defined (_UNICODE) SAFE_FREE(filename); #endif newMXFFile->close = win32_file_close; newMXFFile->read = win32_file_read; newMXFFile->write = win32_file_write; newMXFFile->get_char = win32_file_getchar; newMXFFile->put_char = win32_file_putchar; newMXFFile->eof = win32_file_eof; newMXFFile->seek = win32_file_seek; newMXFFile->tell = win32_file_tell; newMXFFile->is_seekable = win32_file_is_seekable; newMXFFile->size = win32_file_size; newMXFFile->free_sys_data = free_win32_file; newMXFFile->sysData = newDiskFile; *mxfFile = newMXFFile; return 1; fail: SAFE_FREE(newMXFFile); SAFE_FREE(newDiskFile); #if defined (_UNICODE) SAFE_FREE(filename); #endif return 0; }
static int process_metadata(MXFReader *reader, MXFPartition *partition) { MXFFile *mxfFile = reader->mxfFile; EssenceReader *essenceReader = reader->essenceReader; EssenceReaderData *data = essenceReader->data; mxfKey key; uint8_t llen; uint64_t len; MXFMetadataSet *essContainerDataSet; MXFMetadataSet *sourcePackageSet; MXFMetadataSet *sourcePackageTrackSet; MXFMetadataSet *materialPackageSet; MXFMetadataSet *materialPackageTrackSet; MXFMetadataSet *descriptorSet; MXFArrayItemIterator arrayIter; mxfUL dataDefUL; MXFTrack *track; EssenceTrack *essenceTrack; MXFList wrappedTracks; MXFList sortedWrappedTracks; WrappedTrack *newWrappedTrack = NULL; WrappedTrack *wrappedTrack; WrappedTrack *sortedWrappedTrack; WrappedTrack *prevSortedWrappedTrack; WrappedTrack *firstSortedWrappedTrack; MXFListIterator listIter; MXFListIterator sortedListIter; int wasInserted; int haveZeroTrackNumber; uint32_t trackID; mxf_initialise_list(&wrappedTracks, free); mxf_initialise_list(&sortedWrappedTracks, NULL); /* create and read the header metadata */ CHK_OFAIL(mxf_read_next_nonfiller_kl(mxfFile, &key, &llen, &len)); CHK_OFAIL(mxf_is_header_metadata(&key)); CHK_OFAIL(mxf_create_header_metadata(&data->headerMetadata, reader->dataModel)); CHK_OFAIL(mxf_read_header_metadata(mxfFile, data->headerMetadata, partition->headerByteCount, &key, llen, len)); /* check for metadata only files */ if (!mxf_find_singular_set_by_key(data->headerMetadata, &MXF_SET_K(EssenceContainerData), &essContainerDataSet)) { reader->isMetadataOnly = 1; return 1; } /* get the body and index SID from the (single essence container; external essence not supported) */ CHK_OFAIL(mxf_get_uint32_item(essContainerDataSet, &MXF_ITEM_K(EssenceContainerData, BodySID), &data->bodySID)); if (mxf_have_item(essContainerDataSet, &MXF_ITEM_K(EssenceContainerData, IndexSID))) { CHK_OFAIL(mxf_get_uint32_item(essContainerDataSet, &MXF_ITEM_K(EssenceContainerData, IndexSID), &data->indexSID)); } else { data->indexSID = 0; } /* get the clip duration */ CHK_OFAIL(get_clip_duration(data->headerMetadata, &reader->clip, 0)); /* get the tracks from the (single) material package */ haveZeroTrackNumber = 0; CHK_OFAIL(mxf_find_singular_set_by_key(data->headerMetadata, &MXF_SET_K(MaterialPackage), &materialPackageSet)); CHK_OFAIL(mxf_uu_get_package_tracks(materialPackageSet, &arrayIter)); while (mxf_uu_next_track(data->headerMetadata, &arrayIter, &materialPackageTrackSet)) { /* CHK_OFAIL(mxf_uu_get_track_datadef(materialPackageTrackSet, &dataDefUL)); */ /* NOTE: not failing because files from Omneon were found to have a missing DataDefinition item in the Sequence and DMSourceClip referenced by a static DM Track */ if (!mxf_uu_get_track_datadef(materialPackageTrackSet, &dataDefUL)) { continue; } if (mxf_is_picture(&dataDefUL) || mxf_is_sound(&dataDefUL)) { CHK_MALLOC_OFAIL(newWrappedTrack, WrappedTrack); memset(newWrappedTrack, 0, sizeof(WrappedTrack)); CHK_OFAIL(mxf_append_list_element(&wrappedTracks, newWrappedTrack)); wrappedTrack = newWrappedTrack; newWrappedTrack = NULL; /* assigned to list so set to NULL so not free'ed in fail */ CHK_OFAIL(add_track(reader, &track)); wrappedTrack->track = track; if (mxf_have_item(materialPackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackNumber))) { CHK_OFAIL(mxf_get_uint32_item(materialPackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackNumber), &wrappedTrack->trackNumber)); } else { wrappedTrack->trackNumber = 0; } CHK_OFAIL(mxf_get_uint32_item(materialPackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackID), &wrappedTrack->trackID)); CHK_OFAIL(mxf_get_rational_item(materialPackageTrackSet, &MXF_ITEM_K(Track, EditRate), &wrappedTrack->editRate)); CHK_OFAIL(mxf_uu_get_track_duration(materialPackageTrackSet, &wrappedTrack->duration)); CHK_OFAIL(mxf_uu_get_track_reference(materialPackageTrackSet, &wrappedTrack->sourcePackageUID, &wrappedTrack->sourceTrackID)); wrappedTrack->isVideo = mxf_is_picture(&dataDefUL); track->isVideo = wrappedTrack->isVideo; track->materialTrackID = wrappedTrack->trackID; track->materialTrackNumber = wrappedTrack->trackNumber; if (wrappedTrack->isVideo) { track->video.frameRate = wrappedTrack->editRate; } if (wrappedTrack->trackNumber == 0) { haveZeroTrackNumber = 1; } } } /* sort the tracks; use trackNumber if != 0 else use the trackID; video track is always first */ mxf_initialise_list_iter(&listIter, &wrappedTracks); while (mxf_next_list_iter_element(&listIter)) { wrappedTrack = (WrappedTrack*)mxf_get_iter_element(&listIter); wasInserted = 0; mxf_initialise_list_iter(&sortedListIter, &sortedWrappedTracks); while (mxf_next_list_iter_element(&sortedListIter)) { sortedWrappedTrack = (WrappedTrack*)mxf_get_iter_element(&sortedListIter); if ((wrappedTrack->track->isVideo && !sortedWrappedTrack->track->isVideo) || (wrappedTrack->track->isVideo == sortedWrappedTrack->track->isVideo && ((!haveZeroTrackNumber && wrappedTrack->trackNumber < sortedWrappedTrack->trackNumber) || (haveZeroTrackNumber && wrappedTrack->trackID < sortedWrappedTrack->trackID)))) { CHK_OFAIL(mxf_insert_list_element(&sortedWrappedTracks, mxf_get_list_iter_index(&sortedListIter), 1, wrappedTrack)); wasInserted = 1; break; } } if (!wasInserted) { CHK_OFAIL(mxf_append_list_element(&sortedWrappedTracks, wrappedTrack)); } } /* set the MXFTracks to the same order */ prevSortedWrappedTrack = NULL; firstSortedWrappedTrack = NULL; mxf_initialise_list_iter(&sortedListIter, &sortedWrappedTracks); while (mxf_next_list_iter_element(&sortedListIter)) { sortedWrappedTrack = (WrappedTrack*)mxf_get_iter_element(&sortedListIter); if (firstSortedWrappedTrack == NULL) { firstSortedWrappedTrack = sortedWrappedTrack; } if (prevSortedWrappedTrack != NULL) { prevSortedWrappedTrack->track->next = sortedWrappedTrack->track; } prevSortedWrappedTrack = sortedWrappedTrack; } if (prevSortedWrappedTrack != NULL) { prevSortedWrappedTrack->track->next = NULL; } if (firstSortedWrappedTrack != NULL) { reader->clip.tracks = firstSortedWrappedTrack->track; } /* process source package tracks and linked descriptors */ mxf_initialise_list_iter(&sortedListIter, &sortedWrappedTracks); while (mxf_next_list_iter_element(&sortedListIter)) { sortedWrappedTrack = (WrappedTrack*)mxf_get_iter_element(&sortedListIter); CHK_OFAIL(mxf_uu_get_referenced_track(data->headerMetadata, &sortedWrappedTrack->sourcePackageUID, sortedWrappedTrack->sourceTrackID, &sourcePackageTrackSet)); CHK_OFAIL(add_essence_track(essenceReader, &essenceTrack)); essenceTrack->isVideo = sortedWrappedTrack->isVideo; if (mxf_have_item(sourcePackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackNumber))) { CHK_OFAIL(mxf_get_uint32_item(sourcePackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackNumber), &essenceTrack->trackNumber)); } else { essenceTrack->trackNumber = 0; } CHK_OFAIL(mxf_get_uint32_item(sourcePackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackID), &trackID)); essenceTrack->frameRate = reader->clip.frameRate; essenceTrack->playoutDuration = reader->clip.duration; essenceTrack->indexSID = data->indexSID; essenceTrack->bodySID = data->bodySID; /* process the descriptor */ CHK_OFAIL(mxf_uu_get_referenced_package(data->headerMetadata, &sortedWrappedTrack->sourcePackageUID, &sourcePackageSet)); CHK_OFAIL(mxf_uu_get_track_descriptor(sourcePackageSet, trackID, &descriptorSet)); if (mxf_is_subclass_of(data->headerMetadata->dataModel, &descriptorSet->key, &MXF_SET_K(CDCIEssenceDescriptor))) { CHK_OFAIL(process_cdci_descriptor(descriptorSet, sortedWrappedTrack->track, essenceTrack)); } else if (mxf_is_subclass_of(data->headerMetadata->dataModel, &descriptorSet->key, &MXF_SET_K(WaveAudioDescriptor))) { CHK_OFAIL(process_wav_descriptor(descriptorSet, sortedWrappedTrack->track, essenceTrack)); } else if (mxf_is_subclass_of(data->headerMetadata->dataModel, &descriptorSet->key, &MXF_SET_K(GenericSoundEssenceDescriptor))) { CHK_OFAIL(process_sound_descriptor(descriptorSet, track, essenceTrack)); } else { mxf_log_error("Unsupported file descriptor" LOG_LOC_FORMAT, LOG_LOC_PARAMS); return 0; } } /* initialise the playout timecode */ if (!initialise_playout_timecode(reader, materialPackageSet)) { CHK_ORET(initialise_default_playout_timecode(reader)); } /* initialise the source timecodes */ initialise_source_timecodes(reader, sourcePackageSet); mxf_clear_list(&wrappedTracks); mxf_clear_list(&sortedWrappedTracks); return 1; fail: SAFE_FREE(newWrappedTrack); mxf_clear_list(&wrappedTracks); mxf_clear_list(&sortedWrappedTracks); 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; }