Example #1
0
int mxf_read_partition(MXFFile *mxfFile, const mxfKey *key, uint64_t len, MXFPartition **partition)
{
    MXFPartition *newPartition;
    uint32_t numLabels;
    uint32_t labelLen;
    mxfUL label;
    uint64_t expectedLen;
    uint32_t i;

    CHK_ORET(len >= 88 && len <= INT64_MAX);

    CHK_ORET(mxf_create_partition(&newPartition));
    newPartition->key = *key;

    CHK_OFAIL(mxf_read_uint16(mxfFile, &newPartition->majorVersion));
    CHK_OFAIL(mxf_read_uint16(mxfFile, &newPartition->minorVersion));
    CHK_OFAIL(mxf_read_uint32(mxfFile, &newPartition->kagSize));
    CHK_OFAIL(mxf_read_uint64(mxfFile, &newPartition->thisPartition));
    CHK_OFAIL(mxf_read_uint64(mxfFile, &newPartition->previousPartition));
    CHK_OFAIL(mxf_read_uint64(mxfFile, &newPartition->footerPartition));
    CHK_OFAIL(mxf_read_uint64(mxfFile, &newPartition->headerByteCount));
    CHK_OFAIL(mxf_read_uint64(mxfFile, &newPartition->indexByteCount));
    CHK_OFAIL(mxf_read_uint32(mxfFile, &newPartition->indexSID));
    CHK_OFAIL(mxf_read_uint64(mxfFile, &newPartition->bodyOffset));
    CHK_OFAIL(mxf_read_uint32(mxfFile, &newPartition->bodySID));
    CHK_OFAIL(mxf_read_ul(mxfFile, &newPartition->operationalPattern));

    CHK_OFAIL(mxf_read_batch_header(mxfFile, &numLabels, &labelLen));
    CHK_OFAIL(numLabels == 0 || labelLen == 16);
    expectedLen = 88 + (uint64_t)numLabels * labelLen;
    CHK_OFAIL(len >= expectedLen);
    for (i = 0; i < numLabels; i++)
    {
        CHK_OFAIL(mxf_read_ul(mxfFile, &label));
        CHK_OFAIL(mxf_append_partition_esscont_label(newPartition, &label));
    }

    if (len > expectedLen) {
        mxf_log_warn("Partition pack len %" PRIu64 " is larger than expected len %" PRIu64 "\n",
                     len, expectedLen);
        CHK_OFAIL(mxf_file_seek(mxfFile, (int64_t)(len - expectedLen), SEEK_CUR));
    }

    *partition = newPartition;
    return 1;

fail:
    mxf_free_partition(&newPartition);
    return 0;
}
Example #2
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;    
}
Example #3
0
int mxf_page_file_forward_truncate(MXFPageFile *mxfPageFile)
{
    MXFFileSysData *sysData = mxfPageFile->mxfFile->sysData;
    int page = (int)(sysData->position / sysData->pageSize);
    int i;
    char filename[4096];
#if defined(_WIN32)
    int fileid;
#endif

    if (sysData->mode == READ_MODE)
    {
        mxf_log_error("Cannot forward truncate read-only mxf page file\n");
        return 0;
    }

    /* close and truncate to zero length page files before the current one */
    for (i = 0; i < page; i++)
    {
        if (sysData->pages[i].wasRemoved)
        {
            continue;
        }

        if (sysData->pages[i].fileDescriptor != NULL)
        {
            /* close the file */
            disk_file_close(sysData->pages[i].fileDescriptor);

            /* remove the file descriptor from the list */
            if (sysData->fileDescriptorHead == sysData->pages[i].fileDescriptor)
            {
                sysData->fileDescriptorHead = sysData->fileDescriptorHead->next;
            }
            else
            {
                sysData->pages[i].fileDescriptor->prev->next = sysData->pages[i].fileDescriptor->next;
            }
            if (sysData->fileDescriptorTail == sysData->pages[i].fileDescriptor)
            {
                sysData->fileDescriptorTail = sysData->fileDescriptorTail->prev;
            }
            else
            {
                sysData->pages[i].fileDescriptor->next->prev = sysData->pages[i].fileDescriptor->prev;
            }
            SAFE_FREE(sysData->pages[i].fileDescriptor);
        }

        /* truncate the file to zero length */
        mxf_snprintf(filename, sizeof(filename), sysData->filenameTemplate, sysData->pages[i].index);

#if defined(_WIN32)
        /* WIN32 does not have truncate() so open the file with _O_TRUNC then close it */
        if ((fileid = _open(filename, _O_CREAT | _O_TRUNC, _S_IWRITE)) == -1 ||
            _close(fileid) == -1)
#else
        if (truncate(filename, 0) != 0)
#endif
        {
            mxf_log_warn("Failed to truncate '%s' to zero length: %s\n", filename, strerror(errno));
        }
        sysData->pages[i].wasRemoved = 1;
    }

    return 1;
}
Example #4
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;
}
Example #5
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;
}