コード例 #1
0
ファイル: mxf_partition.c プロジェクト: Limecraft/ebu-libmxf
void mxf_update_partitions_in_memory(MXFFilePartitions *partitions)
{
    MXFPartition *previousPartition;
    MXFPartition *lastPartition;
    MXFListIterator iter;
    int haveFooter;

    /* check if anything there to update */
    if (mxf_get_list_length(partitions) == 0)
    {
        return;
    }

    /* update partition packs with previousPartition and footerPartition (if present) offsets */
    lastPartition = (MXFPartition*)mxf_get_last_list_element(partitions);
    haveFooter = mxf_is_footer_partition_pack(&lastPartition->key);
    previousPartition = NULL;
    mxf_initialise_list_iter(&iter, partitions);
    while (mxf_next_list_iter_element(&iter))
    {
        MXFPartition *partition = (MXFPartition*)mxf_get_iter_element(&iter);

        if (previousPartition != NULL)
        {
            partition->previousPartition = previousPartition->thisPartition;
        }
        if (haveFooter)
        {
            partition->footerPartition = lastPartition->thisPartition;
        }

        previousPartition = partition;
    }
}
コード例 #2
0
ファイル: mxf_partition.c プロジェクト: Limecraft/ebu-libmxf
int mxf_write_rip(MXFFile *mxfFile, MXFFilePartitions *partitions)
{
    uint32_t numPartitions;
    uint64_t len;
    uint8_t llen;
    MXFListIterator iter;

    numPartitions = (uint32_t)mxf_get_list_length(partitions);
    len = (4 + 8) * numPartitions + 4;

    CHK_ORET(mxf_write_k(mxfFile, &g_RandomIndexPack_key));
    CHK_ORET((llen = mxf_write_l(mxfFile, len)) != 0);

    mxf_initialise_list_iter(&iter, partitions);
    while (mxf_next_list_iter_element(&iter))
    {
        MXFPartition *partition = (MXFPartition*)mxf_get_iter_element(&iter);

        CHK_ORET(mxf_write_uint32(mxfFile, partition->bodySID));
        CHK_ORET(mxf_write_uint64(mxfFile, partition->thisPartition));
    }
    CHK_ORET(mxf_write_uint32(mxfFile, (uint32_t)(16 + llen + len)));

    return 1;
}
コード例 #3
0
ファイル: timecode_index.c プロジェクト: DraFFty/libMXF
int is_null_timecode_index(TimecodeIndex* index)
{
    TimecodeIndexArray* indexArray;
    long listLen;
    
    /* index is null if the index is empty or has a duration > 1 with timecode frozen at 00:00:00:00 */
    
    listLen = mxf_get_list_length(&index->indexArrays);
    if (listLen == 0)
    {
        return 1;
    }
    else if (listLen == 1)
    {
        indexArray = (TimecodeIndexArray*)mxf_get_first_list_element(&index->indexArrays);
        if (indexArray->numElements == 0 ||
            (indexArray->numElements == 1 && indexArray->elements[0].frozen &&
                indexArray->elements[0].timecodePos == 0 && indexArray->elements[0].duration > 1))
        {
            return 1;
        }
    }
    
    return 0;
}
コード例 #4
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;
}
コード例 #5
0
ファイル: archive_mxf_info_lib.c プロジェクト: DraFFty/libMXF
int archive_mxf_is_metadata_only(const char* filename)
{
    MXFPageFile* mxfPageFile = NULL;
    MXFFile* mxfFile = NULL;
    mxfKey key;
    uint8_t llen;
    uint64_t len;
    MXFPartition* headerPartition = NULL;
    int result;
    
    /* open MXF file */
    if (strstr(filename, "%d") != NULL)
    {
        CHK_OFAIL_NOMSG(mxf_page_file_open_read(filename, &mxfPageFile));
        mxfFile = mxf_page_file_get_file(mxfPageFile);
    }
    else
    {
        CHK_OFAIL_NOMSG(mxf_disk_file_open_read(filename, &mxfFile));
    }
    
    /* read header partition pack */
    if (!mxf_read_header_pp_kl_with_runin(mxfFile, &key, &llen, &len) ||
        !mxf_read_partition(mxfFile, &key, &headerPartition))
    {
        return 0;
    }
    
    /* check whether there is an essence container label */
    result = (mxf_get_list_length(&headerPartition->essenceContainers) == 0);

    mxf_free_partition(&headerPartition);
    mxf_file_close(&mxfFile);
    return result;

fail:
    mxf_free_partition(&headerPartition);
    mxf_file_close(&mxfFile);
    return 0;
}
コード例 #6
0
ファイル: mxf_partition.c プロジェクト: Limecraft/ebu-libmxf
int mxf_write_partition(MXFFile *mxfFile, MXFPartition *partition)
{
    uint32_t essenceContainerLen = (uint32_t)mxf_get_list_length(&partition->essenceContainers);
    uint64_t packLen = 88 + mxfUL_extlen * essenceContainerLen;
    int64_t filePos;
    MXFListIterator iter;

    CHK_ORET((filePos = mxf_file_tell(mxfFile)) >= 0);
    partition->thisPartition = filePos - mxf_get_runin_len(mxfFile);
    if (mxf_is_footer_partition_pack(&partition->key))
    {
        partition->footerPartition = partition->thisPartition;
    }

    CHK_ORET(mxf_write_kl(mxfFile, &partition->key, packLen));

    CHK_ORET(mxf_write_uint16(mxfFile, partition->majorVersion));
    CHK_ORET(mxf_write_uint16(mxfFile, partition->minorVersion));
    CHK_ORET(mxf_write_uint32(mxfFile, partition->kagSize));
    CHK_ORET(mxf_write_uint64(mxfFile, partition->thisPartition));
    CHK_ORET(mxf_write_uint64(mxfFile, partition->previousPartition));
    CHK_ORET(mxf_write_uint64(mxfFile, partition->footerPartition));
    CHK_ORET(mxf_write_uint64(mxfFile, partition->headerByteCount));
    CHK_ORET(mxf_write_uint64(mxfFile, partition->indexByteCount));
    CHK_ORET(mxf_write_uint32(mxfFile, partition->indexSID));
    CHK_ORET(mxf_write_uint64(mxfFile, partition->bodyOffset));
    CHK_ORET(mxf_write_uint32(mxfFile, partition->bodySID));
    CHK_ORET(mxf_write_ul(mxfFile, &partition->operationalPattern));
    CHK_ORET(mxf_write_batch_header(mxfFile, essenceContainerLen, mxfUL_extlen));

    mxf_initialise_list_iter(&iter, &partition->essenceContainers);
    while (mxf_next_list_iter_element(&iter))
    {
        CHK_ORET(mxf_write_ul(mxfFile, (mxfUL*)mxf_get_iter_element(&iter)));
    }

    return 1;
}
コード例 #7
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;
}
コード例 #8
0
ファイル: timecode_index.c プロジェクト: DraFFty/libMXF
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;
}
コード例 #9
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;
}
コード例 #10
0
int op1a_is_supported(MXFPartition *headerPartition)
{
    MXFListIterator iter;
    mxfUL *label;
    int supportCount = 0;

    if (!mxf_is_op_1a(&headerPartition->operationalPattern))
    {
        return 0;
    }

    if (mxf_get_list_length(&headerPartition->essenceContainers) == 0)
    {
        /* metadata only */
        return 1;
    }

    if (mxf_get_list_length(&headerPartition->essenceContainers) == 1)
    {
        label = (mxfUL*)mxf_get_list_element(&headerPartition->essenceContainers, 0);

        if (is_d10_essence(label))
        {
            return 1;
        }
    }

    mxf_initialise_list_iter(&iter, &headerPartition->essenceContainers);
    while (mxf_next_list_iter_element(&iter))
    {
        label = (mxfUL*)mxf_get_iter_element(&iter);

        if (mxf_equals_ul(label, &MXF_EC_L(MultipleWrappings)))
        {
            supportCount++;
        }
        else if (is_d10_picture_essence(label))
        {
            supportCount++;
        }
        else if (mxf_equals_ul(label, &MXF_EC_L(IECDV_25_525_60_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(IECDV_25_625_50_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(DVBased_25_525_60_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(DVBased_25_625_50_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(DVBased_50_525_60_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(DVBased_50_625_50_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(DVBased_100_1080_50_I_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(DVBased_100_1080_60_I_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(DVBased_100_720_50_P_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(DVBased_100_720_60_P_FrameWrapped)))
        {
            supportCount++;
        }
        else if (mxf_equals_ul(label, &MXF_EC_L(SD_Unc_625_50i_422_135_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(SD_Unc_525_5994i_422_135_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_50i_422_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_5994i_422_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_25p_422_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_50p_422_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_2997p_422_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(HD_Unc_1080_5994p_422_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(HD_Unc_720_25p_422_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(HD_Unc_720_2997p_422_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(HD_Unc_720_50p_422_FrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(HD_Unc_720_5994p_422_FrameWrapped)))
        {
            supportCount++;
        }
        else if (mxf_equals_ul(label, &MXF_EC_L(BWFFrameWrapped)) ||
                 mxf_equals_ul(label, &MXF_EC_L(AES3FrameWrapped)))
        {
            supportCount++;
        }
        else if (mxf_is_avc_ec(label, 1))
        {
            supportCount++;
        }
    }

    return supportCount > 0;
}