Пример #1
0
int mxf_read_next_nonfiller_kl(MXFFile *mxfFile, mxfKey *key, uint8_t *llen, uint64_t *len)
{
    mxfKey tkey;
    uint8_t tllen;
    uint64_t tlen;
    CHK_ORET(mxf_read_kl(mxfFile, &tkey, &tllen, &tlen));
    while (mxf_is_filler(&tkey))
    {
        CHK_ORET(mxf_skip(mxfFile, (int64_t)tlen));
        CHK_ORET(mxf_read_kl(mxfFile, &tkey, &tllen, &tlen));
    }

    *key = tkey;
    *llen = tllen;
    *len = tlen;
    return 1;
}
Пример #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;    
}
Пример #3
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;
}
Пример #4
0
static int ns_read_content_package(MXFReader *reader, int skip, MXFReaderListener *listener)
{
    MXFFile *mxfFile = reader->mxfFile;
    EssenceReader *essenceReader = reader->essenceReader;
    EssenceReaderData *data = essenceReader->data;
    NSFileIndex *nsIndex = &data->nsIndex;
    EssenceTrack *essenceTrack;
    uint8_t *buffer;
    mxfKey key;
    uint8_t llen;
    uint64_t len;
    uint64_t cpCount;
    int trackIndex;

    /* must be positioned at start of a content package */
    CHK_ORET(mxf_equals_key(&nsIndex->nextKey, &nsIndex->startContentPackageKey));

    /* get KL read previously */
    key = nsIndex->nextKey;
    llen = nsIndex->nextLLen;
    len = nsIndex->nextLen;

    cpCount = mxfKey_extlen + llen;

    /* process essence elements in content package */
    while (nsIndex->contentPackageLen == 0 || cpCount <= nsIndex->contentPackageLen)
    {
        if (!skip && mxf_is_gc_essence_element(&key))
        {
            if (get_essence_track_with_tracknumber(essenceReader, mxf_get_track_number(&key), &essenceTrack,
                    &trackIndex))
            {
                /* send data to listener */
                if (accept_frame(listener, trackIndex))
                {
                    if (listener && listener->allocate_buffer(listener, trackIndex, &buffer, len))
                    {
                        CHK_ORET(mxf_file_read(mxfFile, buffer, len) == len);
                        CHK_ORET(send_frame(reader, listener, trackIndex, buffer, len));
                    }
                    else
                    {
                        CHK_ORET(mxf_skip(mxfFile, len));
                    }
                }
                else
                {
                    CHK_ORET(mxf_skip(mxfFile, len));
                }

                cpCount += len;
            }
            else if (element_is_known_system_item(&key))
            {
                CHK_ORET(extract_system_item_info(reader, &key, len,
                    reader->essenceReader->data->nsIndex.currentPosition));
                cpCount += len;
            }
            else
            {
                CHK_ORET(mxf_skip(mxfFile, len));
                cpCount += len;
            }
        }
        else
        {
            CHK_ORET(mxf_skip(mxfFile, len));
            cpCount += len;
        }

        if (!mxf_read_kl(mxfFile, &key, &llen, &len))
        {
            CHK_ORET(mxf_file_eof(mxfFile));
            ns_set_next_kl(nsIndex, &g_Null_Key, 0, 0);
            break;
        }
        ns_set_next_kl(nsIndex, &key, llen, len);
        cpCount += mxfKey_extlen + llen;

        /* if don't know the length of the content package then look out for the first element key
           or the start of a new partition */
        if (nsIndex->contentPackageLen == 0 &&
            (mxf_is_partition_pack(&key) || mxf_equals_key(&key, &nsIndex->startContentPackageKey)))
        {
            break;
        }
    }
    CHK_ORET(nsIndex->contentPackageLen == 0 || cpCount == nsIndex->contentPackageLen + mxfKey_extlen + llen);


    /* set content package length if it was unknown */
    if (nsIndex->contentPackageLen == 0)
    {
        nsIndex->contentPackageLen = cpCount - mxfKey_extlen - llen;
    }

    return 1;
}
Пример #5
0
static int read_content_package(MXFReader *reader, int skip, MXFReaderListener *listener)
{
    MXFFile *mxfFile = reader->mxfFile;
    EssenceReader *essenceReader = reader->essenceReader;
    EssenceReaderData *data = essenceReader->data;
    FileIndex *index = data->index;
    EssenceTrack *essenceTrack;
    uint8_t *buffer;
    uint64_t bufferSize;
    mxfKey key;
    uint8_t llen;
    uint64_t len;
    uint64_t cpLen;
    uint64_t cpCount;
    int trackIndex;

    get_next_kl(index, &key, &llen, &len);
    cpLen = get_cp_len(index);

    cpCount = mxfKey_extlen + llen;

    /* process essence elements in content package */
    while (cpCount <= cpLen)
    {
        if (!skip && mxf_is_gc_essence_element(&key))
        {
            /* send data to listener */
            if (get_essence_track_with_tracknumber(essenceReader, mxf_get_track_number(&key), &essenceTrack,
                    &trackIndex))
            {
                if (accept_frame(listener, trackIndex))
                {
                    CHK_ORET(read_frame(reader, listener, trackIndex, len, &buffer, &bufferSize));
                    CHK_ORET(send_frame(reader, listener, trackIndex, buffer, bufferSize));
                }
                else
                {
                    CHK_ORET(mxf_skip(mxfFile, len));
                }
                cpCount += len;
            }
            else if (element_is_known_system_item(&key))
            {
                CHK_ORET(extract_system_item_info(reader, &key, len,
                    get_current_position(reader->essenceReader->data->index)));
                cpCount += len;
            }
            else
            {
                CHK_ORET(mxf_skip(mxfFile, len));
                cpCount += len;
            }
        }
        else
        {
            CHK_ORET(mxf_skip(mxfFile, len));
            cpCount += len;
        }

        if (!mxf_read_kl(mxfFile, &key, &llen, &len))
        {
            CHK_ORET(mxf_file_eof(mxfFile));
            set_next_kl(index, &g_Null_Key, 0, 0);
            break;
        }
        set_next_kl(index, &key, llen, len);
        cpCount += mxfKey_extlen + llen;
    }
    CHK_ORET(cpCount == cpLen + mxfKey_extlen + llen);

    return 1;
}
Пример #6
0
static int ns_pos_at_next_frame(MXFReader *reader)
{
    MXFFile *mxfFile = reader->mxfFile;
    EssenceReader *essenceReader = reader->essenceReader;
    EssenceReaderData *data = essenceReader->data;
    NSFileIndex *nsIndex = &data->nsIndex;
    MXFPartition *partition = NULL;
    mxfKey key;
    uint8_t llen;
    uint64_t len;
    int atEOF;


    /* move to next partition if at end of current partition */
    if (mxf_is_partition_pack(&nsIndex->nextKey))
    {
        key = nsIndex->nextKey;
        llen = nsIndex->nextLLen;
        len = nsIndex->nextLen;
        atEOF = 0;
        while (!atEOF)
        {
            /* read partition pack and check if it contains essence */
            CHK_OFAIL(mxf_read_partition(mxfFile, &key, &partition));
            if (data->bodySID == partition->bodySID)
            {
                CHK_OFAIL(ns_position_at_first_frame(reader));
                mxf_free_partition(&partition);
                break;
            }
            mxf_free_partition(&partition);

            /* skip this partition */
            while (!atEOF)
            {
                if (!mxf_read_kl(mxfFile, &key, &llen, &len))
                {
                    /* if we fail to read then we must be at eof */
                    CHK_OFAIL(mxf_file_eof(mxfFile));
                    atEOF = 1;
                    ns_set_next_kl(nsIndex, &g_Null_Key, 0, 0);
                    break;
                }
                ns_set_next_kl(nsIndex, &key, llen, len);

                if (mxf_is_partition_pack(&key))
                {
                    break;
                }
                CHK_OFAIL(mxf_skip(mxfFile, len));
            }
        }

        CHK_ORET(atEOF || mxf_equals_key(&key, &nsIndex->startContentPackageKey));
    }

    return 1;

fail:
    mxf_free_partition(&partition);
    return 0;
}
Пример #7
0
static int ns_position_at_first_frame(MXFReader *reader)
{
    MXFFile *mxfFile = reader->mxfFile;
    EssenceReader *essenceReader = reader->essenceReader;
    EssenceReaderData *data = essenceReader->data;
    NSFileIndex *nsIndex = &data->nsIndex;
    MXFPartition *partition = data->headerPartition;
    mxfKey key;
    uint8_t llen;
    uint64_t len;

    /* move to the first partition that contains essence data */
    while (data->bodySID != partition->bodySID)
    {
        if (!mxf_read_kl(mxfFile, &key, &llen, &len))
        {
            CHK_OFAIL(mxf_file_eof(mxfFile));
            ns_set_next_kl(nsIndex, &g_Null_Key, 0, 0);
            return 1;
        }
        while (!mxf_is_partition_pack(&key))
        {
            CHK_OFAIL(mxf_skip(mxfFile, len));
            if (!mxf_read_kl(mxfFile, &key, &llen, &len))
            {
                CHK_OFAIL(mxf_file_eof(mxfFile));
                ns_set_next_kl(nsIndex, &g_Null_Key, 0, 0);
                return 1;
            }
        }
        if (partition != NULL && partition != data->headerPartition)
        {
            mxf_free_partition(&partition);
        }
        CHK_OFAIL(mxf_read_partition(mxfFile, &key, &partition));
    }

    /* move to start of essence data in partition */

    /* if we are in the header partition then the file is positioned after the header metadata,
       otherwise we are positioned after the partition pack that was just read */
    if (partition != data->headerPartition)
    {
        /* skip initial filler which is not included in any header or index byte counts */
        if (!mxf_read_next_nonfiller_kl(mxfFile, &key, &llen, &len))
        {
            CHK_ORET(mxf_file_eof(mxfFile));
            ns_set_next_kl(nsIndex, &g_Null_Key, 0, 0);
            return 1;
        }

        /* skip header metadata */
        if (partition->headerByteCount > 0)
        {
            CHK_ORET(mxf_skip(mxfFile, partition->headerByteCount - mxfKey_extlen - llen));
            if (!mxf_read_kl(mxfFile, &key, &llen, &len))
            {
                CHK_ORET(mxf_file_eof(mxfFile));
                ns_set_next_kl(nsIndex, &g_Null_Key, 0, 0);
                return 1;
            }
        }
        else
        {
            CHK_ORET(!mxf_is_header_metadata(&key));
        }
    }
    else
    {
        if (!mxf_read_kl(mxfFile, &key, &llen, &len))
        {
            CHK_ORET(mxf_file_eof(mxfFile));
            ns_set_next_kl(nsIndex, &g_Null_Key, 0, 0);
            return 1;
        }
    }


    /* skip index table segments. Note: we are not checking for segment key because it
       could be non-standard, eg. MXF V10 indexes */
    if (partition->indexByteCount > 0)
    {
        CHK_ORET(mxf_skip(mxfFile, partition->indexByteCount - mxfKey_extlen - llen));
        if (!mxf_read_kl(mxfFile, &key, &llen, &len))
        {
            CHK_ORET(mxf_file_eof(mxfFile));
            ns_set_next_kl(nsIndex, &g_Null_Key, 0, 0);
            return 1;
        }
    }

    /* check the first essence element KL and position after */
    CHK_ORET(mxf_is_gc_essence_element(&key));
    if (mxf_equals_key(&nsIndex->startContentPackageKey, &g_Null_Key))
    {
        nsIndex->startContentPackageKey = key;
        nsIndex->currentPosition = 0;
    }
    else
    {
        CHK_ORET(mxf_equals_key(&nsIndex->startContentPackageKey, &key));
    }
    ns_set_next_kl(nsIndex, &key, llen, len);

    if (partition != NULL && partition != data->headerPartition)
    {
        mxf_free_partition(&partition);
    }
    return 1;

fail:
    if (partition != NULL && partition != data->headerPartition)
    {
        mxf_free_partition(&partition);
    }
    return 0;
}
Пример #8
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;
}