int test_modify(const char* filename) { MXFFile* mxfFile = NULL; if (!mxf_disk_file_open_modify(filename, &mxfFile)) { mxf_log_error("Failed to open modify '%s'" LOG_LOC_FORMAT, filename, LOG_LOC_PARAMS); return 0; } /* TEST */ CHK_OFAIL(do_write(mxfFile)); mxf_file_close(&mxfFile); CHK_OFAIL(test_read(filename)); return 1; fail: mxf_file_close(&mxfFile); 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 hac_create_http_access(MediaPlayer* player, int port, HTTPAccess** access) { HTTPAccess* newAccess; CALLOC_ORET(newAccess, HTTPAccess, 1); CHK_OFAIL(har_create_resources(&newAccess->resources)); newAccess->control = ply_get_media_control(player); if (newAccess->control == NULL) { fprintf(stderr, "Media player has no control\n"); goto fail; } newAccess->playerListener.data = newAccess; newAccess->playerListener.frame_displayed_event = hac_frame_displayed_event; newAccess->playerListener.frame_dropped_event = hac_frame_dropped_event; newAccess->playerListener.state_change_event = hac_state_change_event; newAccess->playerListener.end_of_source_event = hac_end_of_source_event; newAccess->playerListener.start_of_source_event = hac_start_of_source_event; newAccess->playerListener.player_closed = hac_player_closed; if (!ply_register_player_listener(player, &newAccess->playerListener)) { fprintf(stderr, "Failed to register http access as player listener\n"); goto fail; } CHK_OFAIL((newAccess->ctx = shttpd_init(NULL, "document_root", "/dev/null", NULL)) != NULL); shttpd_register_uri(newAccess->ctx, "/", &http_player_page, newAccess); shttpd_register_uri(newAccess->ctx, "/player.html", &http_player_page, newAccess); shttpd_register_uri(newAccess->ctx, "/index.html", &http_player_page, newAccess); shttpd_register_uri(newAccess->ctx, "/resources/*", &http_static_content, newAccess); shttpd_register_uri(newAccess->ctx, "/player/state.xml", &http_player_state_xml, newAccess); shttpd_register_uri(newAccess->ctx, "/player/state.txt", &http_player_state_txt, newAccess); shttpd_register_uri(newAccess->ctx, "/player/control/*", &http_player_control, newAccess); CHK_OFAIL(shttpd_listen(newAccess->ctx, port, 0)); CHK_OFAIL(init_mutex(&newAccess->playerStateMutex)); CHK_OFAIL(create_joinable_thread(&newAccess->httpThreadId, http_thread, newAccess)); *access = newAccess; return 1; fail: hac_free_http_access(&newAccess); return 0; }
int bks_create(const StreamInfo* videoStreamInfo, int64_t length, MediaSource** source) { BlankSource* newSource = NULL; if (videoStreamInfo->type != PICTURE_STREAM_TYPE) { ml_log_error("Blank source only does video\n"); return 0; } CALLOC_ORET(newSource, BlankSource, 1); newSource->length = length; newSource->mediaSource.data = newSource; newSource->mediaSource.finalise_blank_source = bks_finalise_blank_source; newSource->mediaSource.get_num_streams = bks_get_num_streams; newSource->mediaSource.get_stream_info = bks_get_stream_info; newSource->mediaSource.set_frame_rate_or_disable = bks_set_frame_rate_or_disable; newSource->mediaSource.disable_stream = bks_disable_stream; newSource->mediaSource.disable_video = bks_disable_video; newSource->mediaSource.stream_is_disabled = bks_stream_is_disabled; newSource->mediaSource.read_frame = bks_read_frame; newSource->mediaSource.is_seekable = bks_is_seekable; newSource->mediaSource.seek = bks_seek; newSource->mediaSource.get_length = bks_get_length; newSource->mediaSource.get_position = bks_get_position; newSource->mediaSource.get_available_length = bks_get_available_length; newSource->mediaSource.eof = bks_eof; newSource->mediaSource.set_source_name = bks_set_source_name; newSource->mediaSource.set_clip_id = bks_set_clip_id; newSource->mediaSource.close = bks_close; newSource->streamInfo = *videoStreamInfo; newSource->streamInfo.sourceId = msc_create_id(); CHK_OFAIL(add_known_source_info(&newSource->streamInfo, SRC_INFO_TITLE, "Blank Source")); CHK_OFAIL(add_known_source_info(&newSource->streamInfo, SRC_INFO_ORIGINAL_STREAM_FORMAT, get_stream_format_string(newSource->streamInfo.format))); *source = &newSource->mediaSource; return 1; fail: bks_close(newSource); return 0; }
static int append_name_to_string_array(MXFMetadataSet* set, const mxfKey* itemKey, const mxfUTF16Char* name) { uint8_t* nameArray = NULL; uint16_t existingNameArraySize = 0; uint16_t nameArraySize = 0; MXFMetadataItem* namesItem = NULL; if (mxf_have_item(set, itemKey)) { CHK_ORET(mxf_get_item(set, itemKey, &namesItem)); existingNameArraySize = namesItem->length; } nameArraySize = existingNameArraySize + (uint16_t)(mxfUTF16Char_extlen * (wcslen(name) + 1)); CHK_MALLOC_ARRAY_ORET(nameArray, uint8_t, nameArraySize); if (existingNameArraySize > 0) { memcpy(nameArray, namesItem->value, existingNameArraySize); } mxf_set_utf16string(name, &nameArray[existingNameArraySize]); CHK_OFAIL(mxf_set_item(set, itemKey, nameArray, nameArraySize)); SAFE_FREE(&nameArray); return 1; fail: SAFE_FREE(&nameArray); return 0; }
static int init_display(X11DisplaySink* sink, const StreamInfo* streamInfo) { if (!sink->displayInitialised) { CHK_OFAIL(x11c_prepare_display(&sink->x11Common)); } sink->inputWidth = streamInfo->width; sink->inputHeight = streamInfo->height; sink->width = sink->inputWidth / sink->swScale; sink->height = sink->inputHeight / sink->swScale; sink->aspectRatio.num = 4; sink->aspectRatio.den = 3; sink->displayWidth = sink->width; sink->displayHeight = sink->height; if (streamInfo->format == UYVY_FORMAT || streamInfo->format == UYVY_10BIT_FORMAT) { sink->yuvFormat = UYVY; } else if (streamInfo->format == YUV422_FORMAT) { sink->yuvFormat = YV16; } else /* streamInfo->format == YUV420_FORMAT */ { sink->yuvFormat = I420; } /* check if we can use shared memory */ sink->useSharedMemory = x11c_shared_memory_available(&sink->x11Common); CHK_OFAIL(x11c_init_window(&sink->x11Common, sink->displayWidth, sink->displayHeight, sink->width, sink->height)); sink->displayInitialised = 1; sink->displayInitFailed = 0; return 1; fail: sink->displayInitialised = 0; sink->displayInitFailed = 1; return 0; }
int is_archive_mxf(MXFHeaderMetadata* headerMetadata) { MXFMetadataSet* prefaceSet; MXFArrayItemIterator arrayIter; uint8_t* arrayElement; uint32_t arrayElementLen; int haveBBCScheme = 0; mxfUL ul; CHK_OFAIL(mxf_find_singular_set_by_key(headerMetadata, &MXF_SET_K(Preface), &prefaceSet)); /* check is OP-1A */ CHK_OFAIL(mxf_get_ul_item(prefaceSet, &MXF_ITEM_K(Preface, OperationalPattern), &ul)); if (!is_op_1a(&ul)) { return 0; } /* check BBC descriptive metadata scheme */ if (mxf_have_item(prefaceSet, &MXF_ITEM_K(Preface, DMSchemes))) { CHK_OFAIL(mxf_initialise_array_item_iterator(prefaceSet, &MXF_ITEM_K(Preface, DMSchemes), &arrayIter)); while (mxf_next_array_item_element(&arrayIter, &arrayElement, &arrayElementLen)) { mxf_get_ul(arrayElement, &ul); if (mxf_equals_ul(&ul, &MXF_DM_L(APP_PreservationDescriptiveScheme))) { haveBBCScheme = 1; break; } } } if (!haveBBCScheme) { return 0; } return 1; fail: return 0; }
int mxf_open_essence_element_write(MXFFile *mxfFile, const mxfKey *key, uint8_t llen, uint64_t len, MXFEssenceElement **essenceElement) { MXFEssenceElement *newEssenceElement = NULL; int64_t filePos; CHK_ORET(create_essence_element(key, llen, &newEssenceElement)); CHK_OFAIL((filePos = mxf_file_tell(mxfFile)) >= 0); newEssenceElement->startFilePos = filePos; newEssenceElement->currentFilePos = newEssenceElement->startFilePos; CHK_OFAIL(mxf_write_k(mxfFile, key)); CHK_OFAIL(mxf_write_fixed_l(mxfFile, llen, len)); *essenceElement = newEssenceElement; return 1; fail: SAFE_FREE(newEssenceElement); return 0; }
int mxf_create_set(MXFHeaderMetadata* headerMetadata, const mxfKey* key, MXFMetadataSet** set) { MXFMetadataSet* newSet; mxfUUID uuid; CHK_ORET(create_empty_set(key, &newSet)); mxf_generate_uuid(&uuid); newSet->instanceUID = uuid; CHK_OFAIL(mxf_add_set(headerMetadata, newSet)); CHK_OFAIL(mxf_set_uuid_item(newSet, &MXF_ITEM_K(InterchangeObject, InstanceUID), &uuid)); *set = newSet; return 1; fail: mxf_free_set(&newSet); return 0; }
int mxf_append_partition_esscont_label(MXFPartition *partition, const mxfUL *label) { mxfUL *newLabel; CHK_MALLOC_ORET(newLabel, mxfUL); *newLabel = *label; CHK_OFAIL(mxf_append_list_element(&partition->essenceContainers, newLabel)); return 1; fail: SAFE_FREE(newLabel); return 0; }
int mxf_append_new_partition(MXFFilePartitions *partitions, MXFPartition **partition) { MXFPartition *newPartition; CHK_ORET(mxf_create_partition(&newPartition)); CHK_OFAIL(mxf_append_partition(partitions, newPartition)); *partition = newPartition; return 1; fail: mxf_free_partition(&newPartition); return 0; }
int mxf_create_header_metadata(MXFHeaderMetadata** headerMetadata, MXFDataModel* dataModel) { MXFHeaderMetadata* newHeaderMetadata; CHK_MALLOC_ORET(newHeaderMetadata, MXFHeaderMetadata); memset(newHeaderMetadata, 0, sizeof(MXFHeaderMetadata)); newHeaderMetadata->dataModel = dataModel; mxf_initialise_list(&newHeaderMetadata->sets, free_metadata_set_in_list); CHK_OFAIL(mxf_create_primer_pack(&newHeaderMetadata->primerPack)); *headerMetadata = newHeaderMetadata; return 1; fail: mxf_free_header_metadata(&newHeaderMetadata); return 0; }
static int add_metadef_to_list(MXFList* list, const mxfUL* identification, const mxfUUID* instanceUID) { MetaDefData* data = NULL; CHK_MALLOC_ORET(data, MetaDefData); data->identification = *identification; data->instanceUID = *instanceUID; CHK_OFAIL(mxf_append_list_element(list, (void*)data)); data = NULL; return 1; fail: SAFE_FREE(&data); 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; }
static int add_weakref_to_list(MXFList* list, MXFMetadataItem* item, int arrayIndex, const mxfUL* targetIdentification) { WeakRefData* data = NULL; CHK_MALLOC_ORET(data, WeakRefData); data->item = item; data->arrayIndex = arrayIndex; data->targetIdentification = *targetIdentification; CHK_OFAIL(mxf_append_list_element(list, (void*)data)); data = NULL; return 1; fail: SAFE_FREE(&data); return 0; }
int mxf_create_item(MXFMetadataSet* set, const mxfKey* key, mxfLocalTag tag, MXFMetadataItem** item) { MXFMetadataItem* newItem; CHK_MALLOC_ORET(newItem, MXFMetadataItem); memset(newItem, 0, sizeof(MXFMetadataItem)); newItem->tag = tag; newItem->isPersistent = 0; newItem->key = *key; CHK_OFAIL(add_item(set, newItem)); *item = newItem; return 1; fail: mxf_free_item(&newItem); return 0; }
int sts_create(int64_t startTimecode, const Rational* startTimecodeFrameRate, MediaSource** source) { SystemTimecodeSource* newSource = NULL; CALLOC_ORET(newSource, SystemTimecodeSource, 1); newSource->startTimecode = startTimecode; newSource->length = 0x7fffffffffffffffLL; newSource->mediaSource.data = newSource; newSource->mediaSource.get_num_streams = sts_get_num_streams; newSource->mediaSource.get_stream_info = sts_get_stream_info; newSource->mediaSource.set_frame_rate_or_disable = sts_set_frame_rate_or_disable; newSource->mediaSource.disable_stream = sts_disable_stream; newSource->mediaSource.stream_is_disabled = sts_stream_is_disabled; newSource->mediaSource.read_frame = sts_read_frame; newSource->mediaSource.is_seekable = sts_is_seekable; newSource->mediaSource.seek = sts_seek; newSource->mediaSource.get_length = sts_get_length; newSource->mediaSource.get_position = sts_get_position; newSource->mediaSource.get_available_length = sts_get_available_length; newSource->mediaSource.eof = sts_eof; newSource->mediaSource.set_source_name = sts_set_source_name; newSource->mediaSource.set_clip_id = sts_set_clip_id; newSource->mediaSource.close = sts_close; CHK_OFAIL(initialise_stream_info(&newSource->streamInfo)); newSource->streamInfo.type = TIMECODE_STREAM_TYPE; newSource->streamInfo.format = TIMECODE_FORMAT; newSource->streamInfo.frameRate = *startTimecodeFrameRate; newSource->streamInfo.isHardFrameRate = 0; newSource->streamInfo.format = TIMECODE_FORMAT; newSource->streamInfo.sourceId = msc_create_id(); newSource->streamInfo.timecodeType = SYSTEM_TIMECODE_TYPE; newSource->streamInfo.timecodeSubType = NO_TIMECODE_SUBTYPE; *source = &newSource->mediaSource; return 1; fail: sts_close(newSource); 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 xml_writer_open(const char* filename, XMLWriter** writer) { XMLWriter* newWriter; CHK_MALLOC_ORET(newWriter, XMLWriter); memset(newWriter, 0, sizeof(XMLWriter)); newWriter->previousWrite = ELEMENT_END; if ((newWriter->file = fopen(filename, "wb")) == NULL) { mxf_log_error("Failed to open xml file '%s'" LOG_LOC_FORMAT, filename, LOG_LOC_PARAMS); goto fail; } CHK_OFAIL(fprintf(newWriter->file, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>") > 0); *writer = newWriter; return 1; fail: SAFE_FREE(&newWriter); return 0; }
int mxf_find_set_by_key(MXFHeaderMetadata* headerMetadata, const mxfKey* key, MXFList** setList) { MXFListIterator iter; MXFList* newList = NULL; CHK_ORET(mxf_create_list(&newList, NULL)); /* free func == NULL because newList doesn't own the data */ mxf_initialise_list_iter(&iter, &headerMetadata->sets); while (mxf_next_list_iter_element(&iter)) { MXFMetadataSet* set = (MXFMetadataSet*)mxf_get_iter_element(&iter); if (mxf_equals_key(key, &set->key)) { CHK_OFAIL(mxf_append_list_element(newList, (void*)set)); } } *setList = newList; return 1; fail: mxf_free_list(&newList); return 0; }
static int archive_mxf_get_package_pse_failures(MXFHeaderMetadata* headerMetadata, MXFMetadataSet* packageSet, PSEFailure** failures, long* numFailures) { MXFArrayItemIterator arrayIter; MXFArrayItemIterator arrayIter2; uint8_t* arrayElement; uint32_t arrayElementLen; mxfUL dataDef; uint32_t count; MXFMetadataSet* packageTrackSet; MXFMetadataSet* sequenceSet; MXFMetadataSet* dmSet; MXFMetadataSet* dmFrameworkSet; MXFListIterator setsIter; PSEFailure* newFailures = NULL; long countedPSEFailures = 0; PSEFailure* tmp; int32_t i; CHK_OFAIL(mxf_uu_get_package_tracks(packageSet, &arrayIter)); while (mxf_uu_next_track(headerMetadata, &arrayIter, &packageTrackSet)) { CHK_OFAIL(mxf_uu_get_track_datadef(packageTrackSet, &dataDef)); if (mxf_is_descriptive_metadata(&dataDef)) { /* get to the sequence */ CHK_OFAIL(mxf_get_strongref_item(packageTrackSet, &MXF_ITEM_K(GenericTrack, Sequence), &sequenceSet)); if (mxf_is_subclass_of(headerMetadata->dataModel, &sequenceSet->key, &MXF_SET_K(Sequence))) { CHK_OFAIL(mxf_get_array_item_count(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), &count)); if (count == 0) { continue; } CHK_OFAIL(mxf_get_array_item_element(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), 0, &arrayElement)); CHK_OFAIL(mxf_get_strongref(headerMetadata, arrayElement, &dmSet)); } else { dmSet = sequenceSet; } /* if it is a DMSegment with a DMFramework reference then we have the DMS track */ if (mxf_is_subclass_of(headerMetadata->dataModel, &dmSet->key, &MXF_SET_K(DMSegment))) { if (mxf_have_item(dmSet, &MXF_ITEM_K(DMSegment, DMFramework))) { CHK_OFAIL(mxf_get_strongref_item(dmSet, &MXF_ITEM_K(DMSegment, DMFramework), &dmFrameworkSet)); /* check whether the DMFrameworkSet is a APP_PSEAnalysisFramework */ if (mxf_is_subclass_of(headerMetadata->dataModel, &dmFrameworkSet->key, &MXF_SET_K(APP_PSEAnalysisFramework))) { /* go back to the sequence and extract the PSE failures */ CHK_OFAIL(mxf_get_array_item_count(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), &count)); countedPSEFailures += count; if (newFailures == NULL) { CHK_OFAIL((tmp = malloc(sizeof(PSEFailure) * countedPSEFailures)) != NULL); } else { /* multiple tracks with PSE failures - reallocate the array */ CHK_OFAIL((tmp = realloc(newFailures, sizeof(PSEFailure) * countedPSEFailures)) != NULL); } newFailures = tmp; /* extract the PSE failures */ initialise_sets_iter(headerMetadata, &setsIter); i = 0; mxf_initialise_array_item_iterator(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), &arrayIter2); while (mxf_next_array_item_element(&arrayIter2, &arrayElement, &arrayElementLen)) { PSEFailure* pseFailure = &newFailures[i]; CHK_OFAIL(mxf_get_strongref_s(headerMetadata, &setsIter, arrayElement, &dmSet)); CHK_OFAIL(mxf_get_position_item(dmSet, &MXF_ITEM_K(DMSegment, EventStartPosition), &pseFailure->position)); CHK_OFAIL(mxf_get_strongref_item_s(&setsIter, dmSet, &MXF_ITEM_K(DMSegment, DMFramework), &dmFrameworkSet)); CHK_OFAIL(mxf_get_int16_item(dmFrameworkSet, &MXF_ITEM_K(APP_PSEAnalysisFramework, APP_RedFlash), &pseFailure->redFlash)); CHK_OFAIL(mxf_get_int16_item(dmFrameworkSet, &MXF_ITEM_K(APP_PSEAnalysisFramework, APP_SpatialPattern), &pseFailure->spatialPattern)); CHK_OFAIL(mxf_get_int16_item(dmFrameworkSet, &MXF_ITEM_K(APP_PSEAnalysisFramework, APP_LuminanceFlash), &pseFailure->luminanceFlash)); CHK_OFAIL(mxf_get_boolean_item(dmFrameworkSet, &MXF_ITEM_K(APP_PSEAnalysisFramework, APP_ExtendedFailure), &pseFailure->extendedFailure)); i++; } break; } } } } } *failures = newFailures; *numFailures = countedPSEFailures; return 1; fail: SAFE_FREE(&newFailures); return 0; }
/* Read primer pack followed by sets. The inputs pkey, pllen, plen must correspond to that for the primer pack */ int mxf_read_filtered_header_metadata(MXFFile* mxfFile, MXFReadFilter* filter, MXFHeaderMetadata* headerMetadata, uint64_t headerByteCount, const mxfKey* pkey, uint8_t pllen, uint64_t plen) { mxfKey key; uint8_t llen; uint64_t len; int skip = 0; MXFMetadataSet* newSet = NULL; uint64_t count = 0; int result; CHK_ORET(headerByteCount != 0); /* check that input pkey is as expected, and assume pllen and plen are also ok */ CHK_ORET(mxf_is_primer_pack(pkey)); count += mxfKey_extlen + pllen; if (headerMetadata->primerPack != NULL) { mxf_free_primer_pack(&headerMetadata->primerPack); } CHK_ORET(mxf_read_primer_pack(mxfFile, &headerMetadata->primerPack)); count += plen; while (count < headerByteCount) { CHK_ORET(mxf_read_kl(mxfFile, &key, &llen, &len)); count += mxfKey_extlen + llen; if (mxf_is_filler(&key)) { CHK_ORET(mxf_skip(mxfFile, len)); } else { if (filter != NULL) { /* signal before read */ skip = 0; if (filter->before_set_read != NULL) { CHK_ORET(filter->before_set_read(filter->privateData, headerMetadata, &key, llen, len, &skip)); } if (!skip) { CHK_ORET((result = mxf_read_and_return_set(mxfFile, &key, len, headerMetadata, 0, &newSet)) > 0); if (result == 1) /* set was read and returned in "set" parameter */ { /* signal after read */ skip = 0; if (filter->after_set_read != NULL) { CHK_OFAIL(filter->after_set_read(filter->privateData, headerMetadata, newSet, &skip)); } if (!skip) { CHK_OFAIL(mxf_add_set(headerMetadata, newSet)); } else { mxf_free_set(&newSet); } } } else { CHK_ORET(mxf_skip(mxfFile, len)); } } else { CHK_ORET(mxf_read_set(mxfFile, &key, len, headerMetadata, 1) > 0); } } count += len; } CHK_ORET(count == headerByteCount); return 1; fail: mxf_free_set(&newSet); 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; }
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_create_and_write(const char *filename) { MXFFile *mxfFile = NULL; uint8_t runin[RUNIN_LEN]; MXFFilePartitions partitions; MXFPartition *headerPartition = NULL; MXFPartition *bodyPartition1 = NULL; MXFPartition *bodyPartition2 = NULL; MXFPartition *footerPartition = NULL; if (!mxf_disk_file_open_new(filename, &mxfFile)) { mxf_log_error("Failed to create '%s'" LOG_LOC_FORMAT, filename, LOG_LOC_PARAMS); return 0; } mxf_initialise_file_partitions(&partitions); /* TEST */ /* write 8 bytes of runin */ memset(runin, 0, RUNIN_LEN); CHK_OFAIL(mxf_file_write(mxfFile, runin, RUNIN_LEN) == RUNIN_LEN); /* write the header pp */ CHK_OFAIL(mxf_append_new_partition(&partitions, &headerPartition)); headerPartition->key = MXF_PP_K(ClosedComplete, Header); headerPartition->indexSID = 1; CHK_OFAIL(mxf_append_partition_esscont_label(headerPartition, &MXF_EC_L(SD_Unc_625_50i_422_135_FrameWrapped))); CHK_OFAIL(mxf_append_partition_esscont_label(headerPartition, &MXF_EC_L(BWFFrameWrapped))); CHK_OFAIL(mxf_write_partition(mxfFile, headerPartition)); /* write empty header metadata */ CHK_OFAIL(mxf_mark_header_start(mxfFile, headerPartition)); CHK_OFAIL(mxf_allocate_space(mxfFile, 1024)); CHK_OFAIL(mxf_mark_header_end(mxfFile, headerPartition)); /* write the body pp 1 */ CHK_OFAIL(mxf_append_new_from_partition(&partitions, headerPartition, &bodyPartition1)); bodyPartition1->key = MXF_PP_K(ClosedComplete, Body); bodyPartition1->bodySID = 2; CHK_OFAIL(mxf_write_partition(mxfFile, bodyPartition1)); /* write the body pp 2, with KAG 256 */ CHK_OFAIL(mxf_append_new_from_partition(&partitions, headerPartition, &bodyPartition2)); bodyPartition2->key = MXF_PP_K(ClosedComplete, Body); bodyPartition2->bodySID = 3; bodyPartition2->kagSize = 256; CHK_OFAIL(mxf_write_partition(mxfFile, bodyPartition2)); CHK_OFAIL(mxf_fill_to_kag(mxfFile, bodyPartition2)); /* write the footer pp */ CHK_OFAIL(mxf_append_new_from_partition(&partitions, headerPartition, &footerPartition)); footerPartition->key = MXF_PP_K(ClosedComplete, Footer); footerPartition->indexSID = 1; CHK_OFAIL(mxf_write_partition(mxfFile, footerPartition)); /* write RIP */ CHK_OFAIL(mxf_write_rip(mxfFile, &partitions)); /* update the partitions */ CHK_OFAIL(mxf_update_partitions(mxfFile, &partitions)); mxf_file_close(&mxfFile); mxf_clear_file_partitions(&partitions); return 1; fail: 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 archive_mxf_get_info(MXFHeaderMetadata* headerMetadata, ArchiveMXFInfo* info) { MXFList* list = NULL; MXFListIterator iter; MXFArrayItemIterator arrayIter; uint8_t* arrayElement; uint32_t arrayElementLen; mxfUL dataDef; uint32_t count; mxfUTF16Char* tempWString = NULL; int haveSourceInfaxData = 0; MXFList* nameList = NULL; MXFList* valueList = NULL; MXFMetadataSet* identSet; MXFMetadataSet* fileSourcePackageSet; MXFMetadataSet* sourcePackageSet; MXFMetadataSet* sourcePackageTrackSet; MXFMetadataSet* sequenceSet; MXFMetadataSet* dmSet; MXFMetadataSet* dmFrameworkSet; MXFMetadataSet* descriptorSet; MXFMetadataSet* locatorSet; MXFMetadataSet* materialPackageSet; /* if metadata only then only try reading infax user comments */ if (is_metadata_only_file(headerMetadata, &materialPackageSet)) { if (mxf_avid_read_string_user_comments(materialPackageSet, &nameList, &valueList)) { haveSourceInfaxData = parse_infax_user_comments(nameList, valueList, &info->sourceInfaxData); mxf_free_list(&nameList); mxf_free_list(&valueList); } return 1; } /* Creation timestamp identification info */ CHK_OFAIL(mxf_find_set_by_key(headerMetadata, &MXF_SET_K(Identification), &list)); mxf_initialise_list_iter(&iter, list); if (mxf_next_list_iter_element(&iter)) { identSet = (MXFMetadataSet*)mxf_get_iter_element(&iter); CHK_OFAIL(mxf_get_timestamp_item(identSet, &MXF_ITEM_K(Identification, ModificationDate), &info->creationDate)); } mxf_free_list(&list); /* LTO Infax data */ CHK_OFAIL(mxf_uu_get_top_file_package(headerMetadata, &fileSourcePackageSet)); CHK_OFAIL(mxf_uu_get_package_tracks(fileSourcePackageSet, &arrayIter)); while (mxf_uu_next_track(headerMetadata, &arrayIter, &sourcePackageTrackSet)) { CHK_OFAIL(mxf_uu_get_track_datadef(sourcePackageTrackSet, &dataDef)); if (mxf_is_descriptive_metadata(&dataDef)) { /* get to the single DMSegment */ CHK_OFAIL(mxf_get_strongref_item(sourcePackageTrackSet, &MXF_ITEM_K(GenericTrack, Sequence), &sequenceSet)); if (mxf_is_subclass_of(headerMetadata->dataModel, &sequenceSet->key, &MXF_SET_K(Sequence))) { CHK_OFAIL(mxf_get_array_item_count(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), &count)); if (count != 1) { /* Sequence of length 1 is expected for the DMS track */ continue; } CHK_OFAIL(mxf_get_array_item_element(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), 0, &arrayElement)); CHK_OFAIL(mxf_get_strongref(headerMetadata, arrayElement, &dmSet)); } else { dmSet = sequenceSet; } /* if it is a DMSegment with a DMFramework reference then we have the DMS track */ if (mxf_is_subclass_of(headerMetadata->dataModel, &dmSet->key, &MXF_SET_K(DMSegment))) { if (mxf_have_item(dmSet, &MXF_ITEM_K(DMSegment, DMFramework))) { CHK_OFAIL(mxf_get_strongref_item(dmSet, &MXF_ITEM_K(DMSegment, DMFramework), &dmFrameworkSet)); /* if it is a APP_InfaxFramework then it is the Infax data */ if (mxf_is_subclass_of(headerMetadata->dataModel, &dmFrameworkSet->key, &MXF_SET_K(APP_InfaxFramework))) { CHK_OFAIL(get_infax_data(dmFrameworkSet, &info->ltoInfaxData)); break; } } } } } /* original filename */ CHK_OFAIL(mxf_get_strongref_item(fileSourcePackageSet, &MXF_ITEM_K(SourcePackage, Descriptor), &descriptorSet)); if (mxf_have_item(descriptorSet, &MXF_ITEM_K(GenericDescriptor, Locators))) { CHK_OFAIL(mxf_initialise_array_item_iterator(descriptorSet, &MXF_ITEM_K(GenericDescriptor, Locators), &arrayIter)); while (mxf_next_array_item_element(&arrayIter, &arrayElement, &arrayElementLen)) { CHK_OFAIL(mxf_get_strongref(headerMetadata, arrayElement, &locatorSet)); if (mxf_is_subclass_of(headerMetadata->dataModel, &locatorSet->key, &MXF_SET_K(NetworkLocator))) { CHK_OFAIL(mxf_uu_get_utf16string_item(locatorSet, &MXF_ITEM_K(NetworkLocator, URLString), &tempWString)); CHK_OFAIL(wcstombs(info->filename, tempWString, sizeof(info->filename)) != (size_t)(-1)); info->filename[sizeof(info->filename) - 1] = '\0'; SAFE_FREE(&tempWString); break; } } } /* source Infax data */ CHK_OFAIL(mxf_find_set_by_key(headerMetadata, &MXF_SET_K(SourcePackage), &list)); mxf_initialise_list_iter(&iter, list); while (mxf_next_list_iter_element(&iter)) { sourcePackageSet = (MXFMetadataSet*)(mxf_get_iter_element(&iter)); /* it is the tape SourcePackage if it has a TapeDescriptor */ CHK_OFAIL(mxf_get_strongref_item(sourcePackageSet, &MXF_ITEM_K(SourcePackage, Descriptor), &descriptorSet)); if (mxf_is_subclass_of(headerMetadata->dataModel, &descriptorSet->key, &MXF_SET_K(TapeDescriptor))) { /* go through the tracks and find the DMS track */ CHK_OFAIL(mxf_uu_get_package_tracks(sourcePackageSet, &arrayIter)); while (mxf_uu_next_track(headerMetadata, &arrayIter, &sourcePackageTrackSet)) { CHK_OFAIL(mxf_uu_get_track_datadef(sourcePackageTrackSet, &dataDef)); if (mxf_is_descriptive_metadata(&dataDef)) { /* get to the single DMSegment */ CHK_OFAIL(mxf_get_strongref_item(sourcePackageTrackSet, &MXF_ITEM_K(GenericTrack, Sequence), &sequenceSet)); if (mxf_is_subclass_of(headerMetadata->dataModel, &sequenceSet->key, &MXF_SET_K(Sequence))) { CHK_OFAIL(mxf_get_array_item_count(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), &count)); if (count != 1) { /* Sequence of length 1 is expected for the DMS track */ continue; } CHK_OFAIL(mxf_get_array_item_element(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), 0, &arrayElement)); CHK_OFAIL(mxf_get_strongref(headerMetadata, arrayElement, &dmSet)); } else { dmSet = sequenceSet; } /* if it is a DMSegment with a DMFramework reference then we have the DMS track */ if (mxf_is_subclass_of(headerMetadata->dataModel, &dmSet->key, &MXF_SET_K(DMSegment))) { if (mxf_have_item(dmSet, &MXF_ITEM_K(DMSegment, DMFramework))) { CHK_OFAIL(mxf_get_strongref_item(dmSet, &MXF_ITEM_K(DMSegment, DMFramework), &dmFrameworkSet)); /* if it is a APP_InfaxFramework then it is the Infax data */ if (mxf_is_subclass_of(headerMetadata->dataModel, &dmFrameworkSet->key, &MXF_SET_K(APP_InfaxFramework))) { CHK_OFAIL(get_infax_data(dmFrameworkSet, &info->sourceInfaxData)); haveSourceInfaxData = 1; break; } } } } } break; } } mxf_free_list(&list); /* try reading Infax data from UserComments attached to the MaterialPackage if no data was found elsewhere */ if (!haveSourceInfaxData) { CHK_OFAIL(mxf_find_singular_set_by_key(headerMetadata, &MXF_SET_K(MaterialPackage), &materialPackageSet)); if (mxf_avid_read_string_user_comments(materialPackageSet, &nameList, &valueList)) { haveSourceInfaxData = parse_infax_user_comments(nameList, valueList, &info->sourceInfaxData); mxf_free_list(&nameList); mxf_free_list(&valueList); } } return haveSourceInfaxData; fail: SAFE_FREE(&tempWString); mxf_free_list(&list); mxf_free_list(&nameList); mxf_free_list(&valueList); return 0; }
int create_dv_connect(MediaSink* sink, int sinkStreamId, int sourceStreamId, const StreamInfo* streamInfo, int numFFMPEGThreads, int useWorkerThread, StreamConnect** connect) { DVDecodeStreamConnect* newConnect; StreamInfo decodedStreamInfo; int result; /* register stream with sink */ if (streamInfo->format == DV25_YUV420_FORMAT) { decodedStreamInfo = *streamInfo; decodedStreamInfo.format = YUV420_FORMAT; result = msk_accept_stream(sink, &decodedStreamInfo); } else if (streamInfo->format == DV25_YUV411_FORMAT) { decodedStreamInfo = *streamInfo; decodedStreamInfo.format = YUV411_FORMAT; result = msk_accept_stream(sink, &decodedStreamInfo); } else /* streamInfo->format == DV50_FORMAT || streamInfo->format == DV100_FORMAT */ { decodedStreamInfo = *streamInfo; decodedStreamInfo.format = YUV422_FORMAT; result = msk_accept_stream(sink, &decodedStreamInfo); } /* try UYVY if default format is not accepted */ if (!result) { decodedStreamInfo = *streamInfo; decodedStreamInfo.format = UYVY_FORMAT; result = msk_accept_stream(sink, &decodedStreamInfo); } if (!result) { /* shouldn't be here because a call to dv_connect_accept() should've returned false already */ ml_log_error("Failed to create DV connector because format is not accepted\n"); return 0; } if (!msk_register_stream(sink, sinkStreamId, &decodedStreamInfo)) { /* could have failed if max streams exceeded for example */ return 0; } CALLOC_ORET(newConnect, DVDecodeStreamConnect, 1); newConnect->useWorkerThread = useWorkerThread; newConnect->decodedFormat = decodedStreamInfo.format; if (streamInfo->format == DV25_YUV420_FORMAT || streamInfo->format == DV25_YUV411_FORMAT) { newConnect->dvDataSize = (stream_is_pal_frame_rate(streamInfo) ? 144000 : 120000); } else if (streamInfo->format == DV50_FORMAT) { newConnect->dvDataSize = (stream_is_pal_frame_rate(streamInfo) ? 288000 : 240000); } else /* streamInfo->format == DV100_FORMAT */ { newConnect->dvDataSize = 576000; } if ((newConnect->dvData = (unsigned char*)calloc( newConnect->dvDataSize + FF_INPUT_BUFFER_PADDING_SIZE /* FFMPEG for some reason needs the extra space */, sizeof(unsigned char))) == NULL) { ml_log_error("Failed to allocate memory\n"); goto fail; } newConnect->sink = sink; newConnect->sourceStreamId = sourceStreamId; newConnect->sinkStreamId = sinkStreamId; newConnect->streamInfo = *streamInfo; if (decodedStreamInfo.format == UYVY_FORMAT) { newConnect->sinkBufferSize = streamInfo->width * streamInfo->height * 2; } else if (decodedStreamInfo.format == YUV422_FORMAT) { newConnect->sinkBufferSize = streamInfo->width * streamInfo->height * 2; } else /* YUV420 / YUV411 */ { newConnect->sinkBufferSize = streamInfo->width * streamInfo->height * 3 / 2; } newConnect->streamConnect.data = newConnect; newConnect->streamConnect.get_source_listener = ddc_get_source_listener; newConnect->streamConnect.sync = ddc_sync; newConnect->streamConnect.close = ddc_close; newConnect->sourceListener.data = newConnect; newConnect->sourceListener.accept_frame = ddc_accept_frame; newConnect->sourceListener.allocate_buffer = ddc_allocate_buffer; newConnect->sourceListener.deallocate_buffer = ddc_deallocate_buffer; newConnect->sourceListener.receive_frame = ddc_receive_frame; newConnect->sourceListener.receive_frame_const = ddc_receive_frame_const; /* create DV decoder */ CHK_OFAIL(init_dv_decoder_resources()); CHK_OFAIL(create_dv_decoder(streamInfo->format, streamInfo->width, streamInfo->height, numFFMPEGThreads, &newConnect->decoder)); /* create worker thread */ if (useWorkerThread) { CHK_OFAIL(init_mutex(&newConnect->workerMutex)); CHK_OFAIL(init_cond_var(&newConnect->frameIsReadyCond)); CHK_OFAIL(init_cond_var(&newConnect->workerIsBusyCond)); CHK_OFAIL(create_joinable_thread(&newConnect->workerThreadId, worker_thread, newConnect)); } *connect = &newConnect->streamConnect; return 1; fail: ddc_close(newConnect); return 0; }
int mxf_read_and_return_set(MXFFile* mxfFile, const mxfKey* key, uint64_t len, MXFHeaderMetadata* headerMetadata, int addToHeaderMetadata, MXFMetadataSet** set) { MXFMetadataSet* newSet = NULL; MXFSetDef* setDef = NULL; uint64_t totalLen = 0; mxfLocalTag itemTag; uint16_t itemLen; int haveInstanceUID = 0; mxfKey itemKey; MXFItemDef* itemDef = NULL; MXFMetadataItem* newItem; assert(headerMetadata->primerPack != NULL); /* only read sets with known definitions */ if (mxf_find_set_def(headerMetadata->dataModel, key, &setDef)) { CHK_ORET(create_empty_set(key, &newSet)); /* read each item in the set*/ haveInstanceUID = 0; do { CHK_OFAIL(mxf_read_item_tl(mxfFile, &itemTag, &itemLen)); /* check the item tag is registered in the primer */ if (mxf_get_item_key(headerMetadata->primerPack, itemTag, &itemKey)) { /* only read items with known definition */ if (mxf_find_item_def_in_set_def(&itemKey, setDef, &itemDef)) { CHK_OFAIL(mxf_create_item(newSet, &itemKey, itemTag, &newItem)); newItem->isPersistent = 1; CHK_OFAIL(mxf_read_item(mxfFile, newItem, itemLen)); if (mxf_equals_key(&MXF_ITEM_K(InterchangeObject, InstanceUID), &itemKey)) { mxf_get_uuid(newItem->value, &newSet->instanceUID); haveInstanceUID = 1; } } /* skip items with unknown definition */ else { CHK_OFAIL(mxf_skip(mxfFile, (int64_t)itemLen)); } } /* skip items not registered in the primer. Log warning because the file is invalid */ else { mxf_log_warn("Encountered item with tag %d not registered in the primer" LOG_LOC_FORMAT, itemTag, LOG_LOC_PARAMS); CHK_OFAIL(mxf_skip(mxfFile, (int64_t)itemLen)); } totalLen += 4 + itemLen; } while (totalLen < len); if (totalLen != len) { mxf_log_error("Incorrect metadata set length encountered" LOG_LOC_FORMAT, LOG_LOC_PARAMS); goto fail; } if (!haveInstanceUID) { mxf_log_error("Metadata set does not have InstanceUID item" LOG_LOC_FORMAT, LOG_LOC_PARAMS); goto fail; } /* ok to add set */ if (addToHeaderMetadata) { CHK_OFAIL(mxf_add_set(headerMetadata, newSet)); } *set = newSet; return 1; } /* skip the set if the def is unknown */ CHK_ORET(mxf_skip(mxfFile, (int64_t)len)); *set = NULL; return 2; fail: mxf_free_set(&newSet); return 0; }
static int archive_mxf_get_package_timecode_breaks(MXFHeaderMetadata* headerMetadata, MXFMetadataSet* packageSet, TimecodeBreak** timecodeBreaks, long* numTimecodeBreaks) { MXFArrayItemIterator arrayIter; MXFArrayItemIterator arrayIter2; uint8_t* arrayElement; uint32_t arrayElementLen; mxfUL dataDef; uint32_t count; MXFMetadataSet* packageTrackSet; MXFMetadataSet* sequenceSet; MXFMetadataSet* dmSet; MXFMetadataSet* dmFrameworkSet; MXFListIterator setsIter; TimecodeBreak* newTimecodeBreaks = NULL; long totalBreaks = 0; TimecodeBreak* tmp; CHK_OFAIL(mxf_uu_get_package_tracks(packageSet, &arrayIter)); while (mxf_uu_next_track(headerMetadata, &arrayIter, &packageTrackSet)) { CHK_OFAIL(mxf_uu_get_track_datadef(packageTrackSet, &dataDef)); if (mxf_is_descriptive_metadata(&dataDef)) { /* get to the sequence */ CHK_OFAIL(mxf_get_strongref_item(packageTrackSet, &MXF_ITEM_K(GenericTrack, Sequence), &sequenceSet)); if (mxf_is_subclass_of(headerMetadata->dataModel, &sequenceSet->key, &MXF_SET_K(Sequence))) { CHK_OFAIL(mxf_get_array_item_count(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), &count)); if (count == 0) { continue; } CHK_OFAIL(mxf_get_array_item_element(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), 0, &arrayElement)); CHK_OFAIL(mxf_get_strongref(headerMetadata, arrayElement, &dmSet)); } else { dmSet = sequenceSet; } /* if it is a DMSegment with a DMFramework reference then we have the DMS track */ if (mxf_is_subclass_of(headerMetadata->dataModel, &dmSet->key, &MXF_SET_K(DMSegment))) { if (mxf_have_item(dmSet, &MXF_ITEM_K(DMSegment, DMFramework))) { CHK_OFAIL(mxf_get_strongref_item(dmSet, &MXF_ITEM_K(DMSegment, DMFramework), &dmFrameworkSet)); /* check whether the DMFrameworkSet is a APP_TimecodeBreakFramework */ if (mxf_is_subclass_of(headerMetadata->dataModel, &dmFrameworkSet->key, &MXF_SET_K(APP_TimecodeBreakFramework))) { /* go back to the sequence and extract the timecode breaks */ CHK_OFAIL(mxf_get_array_item_count(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), &count)); if (newTimecodeBreaks == NULL) { CHK_OFAIL((tmp = malloc(sizeof(TimecodeBreak) * (totalBreaks + count))) != NULL); } else { /* multiple tracks with timecode breaks - reallocate the array */ CHK_OFAIL((tmp = realloc(newTimecodeBreaks, sizeof(TimecodeBreak) * (totalBreaks + count))) != NULL); } newTimecodeBreaks = tmp; /* extract the digibeta dropouts */ initialise_sets_iter(headerMetadata, &setsIter); mxf_initialise_array_item_iterator(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), &arrayIter2); while (mxf_next_array_item_element(&arrayIter2, &arrayElement, &arrayElementLen)) { TimecodeBreak* timecodeBreak = &newTimecodeBreaks[totalBreaks]; CHK_OFAIL(mxf_get_strongref_s(headerMetadata, &setsIter, arrayElement, &dmSet)); CHK_OFAIL(mxf_get_position_item(dmSet, &MXF_ITEM_K(DMSegment, EventStartPosition), &timecodeBreak->position)); CHK_OFAIL(mxf_get_strongref_item_s(&setsIter, dmSet, &MXF_ITEM_K(DMSegment, DMFramework), &dmFrameworkSet)); CHK_OFAIL(mxf_get_uint16_item(dmFrameworkSet, &MXF_ITEM_K(APP_TimecodeBreakFramework, APP_TimecodeType), &timecodeBreak->timecodeType)); totalBreaks++; } } } } } } *timecodeBreaks = newTimecodeBreaks; *numTimecodeBreaks = totalBreaks; return 1; fail: SAFE_FREE(&newTimecodeBreaks); return 0; }