Exemplo n.º 1
0
int mxf_mem_file_open_read(const unsigned char *data, int64_t size, int64_t virtualStartPos, MXFMemoryFile **mxfMemFile)
{
    MXFFile *newMXFFile = NULL;

    CHK_MALLOC_ORET(newMXFFile, MXFFile);
    memset(newMXFFile, 0, sizeof(*newMXFFile));

    newMXFFile->close           = mem_file_close;
    newMXFFile->read            = mem_file_read;
    newMXFFile->write           = mem_file_write;
    newMXFFile->get_char        = mem_file_getchar;
    newMXFFile->put_char        = mem_file_putchar;
    newMXFFile->eof             = mem_file_eof;
    newMXFFile->seek            = mem_file_seek;
    newMXFFile->tell            = mem_file_tell;
    newMXFFile->is_seekable     = mem_file_is_seekable;
    newMXFFile->size            = mem_file_size;
    newMXFFile->free_sys_data   = free_mem_file;


    CHK_MALLOC_OFAIL(newMXFFile->sysData, MXFFileSysData);
    memset(newMXFFile->sysData, 0, sizeof(*newMXFFile->sysData));

    newMXFFile->sysData->virtualStartPos    = virtualStartPos;
    newMXFFile->sysData->readOnly           = 1;
    newMXFFile->sysData->mxfMemFile.mxfFile = newMXFFile;


    CHK_MALLOC_OFAIL(newMXFFile->sysData->chunks, Chunk);

    newMXFFile->sysData->chunks->data      = (unsigned char*)data;
    newMXFFile->sysData->chunks->allocSize = size;
    newMXFFile->sysData->chunks->size      = size;
    newMXFFile->sysData->numChunks++;


    *mxfMemFile = &newMXFFile->sysData->mxfMemFile;
    return 1;

fail:
    if (newMXFFile)
        mxf_file_close(&newMXFFile);
    return 0;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
int mxf_mem_file_open_new(uint32_t chunkSize, int64_t virtualStartPos, MXFMemoryFile **mxfMemFile)
{
    MXFFile *newMXFFile = NULL;

    CHK_MALLOC_ORET(newMXFFile, MXFFile);
    memset(newMXFFile, 0, sizeof(*newMXFFile));

    newMXFFile->close           = mem_file_close;
    newMXFFile->read            = mem_file_read;
    newMXFFile->write           = mem_file_write;
    newMXFFile->get_char        = mem_file_getchar;
    newMXFFile->put_char        = mem_file_putchar;
    newMXFFile->eof             = mem_file_eof;
    newMXFFile->seek            = mem_file_seek;
    newMXFFile->tell            = mem_file_tell;
    newMXFFile->is_seekable     = mem_file_is_seekable;
    newMXFFile->size            = mem_file_size;
    newMXFFile->free_sys_data   = free_mem_file;


    CHK_MALLOC_OFAIL(newMXFFile->sysData, MXFFileSysData);
    memset(newMXFFile->sysData, 0, sizeof(*newMXFFile->sysData));

    newMXFFile->sysData->chunkSize          = (chunkSize == 0 ? DEFAULT_CHUNK_SIZE : chunkSize);
    newMXFFile->sysData->virtualStartPos    = virtualStartPos;
    newMXFFile->sysData->mxfMemFile.mxfFile = newMXFFile;


    *mxfMemFile = &newMXFFile->sysData->mxfMemFile;
    return 1;

fail:
    if (newMXFFile)
        mxf_file_close(&newMXFFile);
    return 0;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
0
int add_timecode_to_index(TimecodeIndex* index, ArchiveTimecode* timecode)
{
    TimecodeIndexArray* newArray = NULL;
    TimecodeIndexArray* lastArray;
    int64_t timecodePos = timecode_to_position(timecode);
    
    
    if (mxf_get_list_length(&index->indexArrays) == 0)
    {
        CHK_MALLOC_OFAIL(newArray, TimecodeIndexArray);
        CHK_MALLOC_ARRAY_OFAIL(newArray->elements, TimecodeIndexElement, index->arraySize);
        newArray->numElements = 0;
        CHK_OFAIL(mxf_append_list_element(&index->indexArrays, newArray));
        newArray = NULL; /* list has ownership */
    }
    
    lastArray = (TimecodeIndexArray*)mxf_get_last_list_element(&index->indexArrays);
    
    if (lastArray->numElements != 0)
    {
        if (lastArray->elements[lastArray->numElements - 1].timecodePos + 
                lastArray->elements[lastArray->numElements - 1].duration == timecodePos)
        {
            /* timecode is previous + 1 */
            lastArray->elements[lastArray->numElements - 1].duration++;
        }
        else if (lastArray->elements[lastArray->numElements - 1].timecodePos == timecodePos &&
            (lastArray->elements[lastArray->numElements - 1].frozen ||
                lastArray->elements[lastArray->numElements - 1].duration == 1))
        {
            /* timecode is frozen with the previous timecode value */
            lastArray->elements[lastArray->numElements - 1].frozen = 1;
            lastArray->elements[lastArray->numElements - 1].duration++;
        }
        else
        {
            /* timecode is not frozen or previous + 1 */
            
            if (lastArray->numElements == index->arraySize)
            {
                CHK_MALLOC_OFAIL(newArray, TimecodeIndexArray);
                CHK_MALLOC_ARRAY_OFAIL(newArray->elements, TimecodeIndexElement, index->arraySize);
                newArray->numElements = 0;
                CHK_OFAIL(mxf_append_list_element(&index->indexArrays, newArray));
                newArray = NULL; /* list has ownership */

                lastArray = (TimecodeIndexArray*)mxf_get_last_list_element(&index->indexArrays);
            }
            
            lastArray->numElements++;
            lastArray->elements[lastArray->numElements - 1].frozen = 0;
            lastArray->elements[lastArray->numElements - 1].timecodePos = timecodePos;
            lastArray->elements[lastArray->numElements - 1].duration = 1;
        }
    }
    else
    {
        lastArray->numElements++;
        lastArray->elements[lastArray->numElements - 1].frozen = 0;
        lastArray->elements[lastArray->numElements - 1].timecodePos = timecodePos;
        lastArray->elements[lastArray->numElements - 1].duration = 1;
    }
    
    
    return 1;
    
fail:
    free_index_array(&newArray);
    return 0;
}
Exemplo n.º 8
0
static int mxf_win32_file_open(const char *in_filename, int flags, OpenMode mode, MXFFile **mxfFile)
{
    MXFFile *newMXFFile = NULL;
    MXFFileSysData *newDiskFile = NULL;
    int attrs_and_flags = FILE_ATTRIBUTE_NORMAL;
#if !defined (_UNICODE)
    const char *filename = in_filename;
#else
    wchar_t *filename = NULL;
    size_t size;

    CHK_OFAIL((size = mbstowcs(NULL, in_filename, 0)) != (size_t)(-1));
    size += 1;
    CHK_MALLOC_ARRAY_OFAIL(filename, wchar_t, size);
    mbstowcs(filename, in_filename, size);
#endif

    CHK_MALLOC_OFAIL(newMXFFile, MXFFile);
    memset(newMXFFile, 0, sizeof(MXFFile));
    CHK_MALLOC_OFAIL(newDiskFile, MXFFileSysData);
    memset(newDiskFile, 0, sizeof(MXFFileSysData));
    newDiskFile->file = INVALID_HANDLE_VALUE;

    if (flags & MXF_WIN32_FLAG_RANDOM_ACCESS)
        attrs_and_flags |= FILE_FLAG_RANDOM_ACCESS;
    else if (flags & MXF_WIN32_FLAG_SEQUENTIAL_SCAN)
        attrs_and_flags |= FILE_FLAG_SEQUENTIAL_SCAN;

    switch (mode)
    {
        case NEW_MODE:
            newDiskFile->file = CreateFile(filename, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
                                           NULL, CREATE_ALWAYS, attrs_and_flags, NULL);
            break;
        case READ_MODE:
            newDiskFile->file = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
                                           NULL, OPEN_EXISTING, attrs_and_flags, NULL);
            break;
        case MODIFY_MODE:
            newDiskFile->file = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
                                           NULL, OPEN_EXISTING, attrs_and_flags, NULL);
            break;
    }
    if (newDiskFile->file == INVALID_HANDLE_VALUE)
        goto fail;

#if defined (_UNICODE)
    SAFE_FREE(filename);
#endif

    newMXFFile->close         = win32_file_close;
    newMXFFile->read          = win32_file_read;
    newMXFFile->write         = win32_file_write;
    newMXFFile->get_char      = win32_file_getchar;
    newMXFFile->put_char      = win32_file_putchar;
    newMXFFile->eof           = win32_file_eof;
    newMXFFile->seek          = win32_file_seek;
    newMXFFile->tell          = win32_file_tell;
    newMXFFile->is_seekable   = win32_file_is_seekable;
    newMXFFile->size          = win32_file_size;

    newMXFFile->free_sys_data = free_win32_file;
    newMXFFile->sysData       = newDiskFile;


    *mxfFile = newMXFFile;
    return 1;

fail:
    SAFE_FREE(newMXFFile);
    SAFE_FREE(newDiskFile);
#if defined (_UNICODE)
    SAFE_FREE(filename);
#endif
    return 0;
}
Exemplo n.º 9
0
static int process_metadata(MXFReader *reader, MXFPartition *partition)
{
    MXFFile *mxfFile = reader->mxfFile;
    EssenceReader *essenceReader = reader->essenceReader;
    EssenceReaderData *data = essenceReader->data;
    mxfKey key;
    uint8_t llen;
    uint64_t len;
    MXFMetadataSet *essContainerDataSet;
    MXFMetadataSet *sourcePackageSet;
    MXFMetadataSet *sourcePackageTrackSet;
    MXFMetadataSet *materialPackageSet;
    MXFMetadataSet *materialPackageTrackSet;
    MXFMetadataSet *descriptorSet;
    MXFArrayItemIterator arrayIter;
    mxfUL dataDefUL;
    MXFTrack *track;
    EssenceTrack *essenceTrack;
    MXFList wrappedTracks;
    MXFList sortedWrappedTracks;
    WrappedTrack *newWrappedTrack = NULL;
    WrappedTrack *wrappedTrack;
    WrappedTrack *sortedWrappedTrack;
    WrappedTrack *prevSortedWrappedTrack;
    WrappedTrack *firstSortedWrappedTrack;
    MXFListIterator listIter;
    MXFListIterator sortedListIter;
    int wasInserted;
    int haveZeroTrackNumber;
    uint32_t trackID;


    mxf_initialise_list(&wrappedTracks, free);
    mxf_initialise_list(&sortedWrappedTracks, NULL);


    /* create and read the header metadata */

    CHK_OFAIL(mxf_read_next_nonfiller_kl(mxfFile, &key, &llen, &len));
    CHK_OFAIL(mxf_is_header_metadata(&key));
    CHK_OFAIL(mxf_create_header_metadata(&data->headerMetadata, reader->dataModel));
    CHK_OFAIL(mxf_read_header_metadata(mxfFile, data->headerMetadata,
        partition->headerByteCount, &key, llen, len));


    /* check for metadata only files */

    if (!mxf_find_singular_set_by_key(data->headerMetadata, &MXF_SET_K(EssenceContainerData), &essContainerDataSet))
    {
        reader->isMetadataOnly = 1;
        return 1;
    }


    /* get the body and index SID from the (single essence container; external essence not supported) */

    CHK_OFAIL(mxf_get_uint32_item(essContainerDataSet, &MXF_ITEM_K(EssenceContainerData, BodySID), &data->bodySID));
    if (mxf_have_item(essContainerDataSet, &MXF_ITEM_K(EssenceContainerData, IndexSID)))
    {
        CHK_OFAIL(mxf_get_uint32_item(essContainerDataSet, &MXF_ITEM_K(EssenceContainerData, IndexSID), &data->indexSID));
    }
    else
    {
        data->indexSID = 0;
    }


    /* get the clip duration */

    CHK_OFAIL(get_clip_duration(data->headerMetadata, &reader->clip, 0));


    /* get the tracks from the (single) material package */

    haveZeroTrackNumber = 0;
    CHK_OFAIL(mxf_find_singular_set_by_key(data->headerMetadata, &MXF_SET_K(MaterialPackage), &materialPackageSet));
    CHK_OFAIL(mxf_uu_get_package_tracks(materialPackageSet, &arrayIter));
    while (mxf_uu_next_track(data->headerMetadata, &arrayIter, &materialPackageTrackSet))
    {
        /* CHK_OFAIL(mxf_uu_get_track_datadef(materialPackageTrackSet, &dataDefUL)); */
        /* NOTE: not failing because files from Omneon were found to have a missing DataDefinition item
           in the Sequence and DMSourceClip referenced by a static DM Track */
        if (!mxf_uu_get_track_datadef(materialPackageTrackSet, &dataDefUL))
        {
            continue;
        }

        if (mxf_is_picture(&dataDefUL) || mxf_is_sound(&dataDefUL))
        {
            CHK_MALLOC_OFAIL(newWrappedTrack, WrappedTrack);
            memset(newWrappedTrack, 0, sizeof(WrappedTrack));
            CHK_OFAIL(mxf_append_list_element(&wrappedTracks, newWrappedTrack));
            wrappedTrack = newWrappedTrack;
            newWrappedTrack = NULL;  /* assigned to list so set to NULL so not free'ed in fail */

            CHK_OFAIL(add_track(reader, &track));
            wrappedTrack->track = track;

            if (mxf_have_item(materialPackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackNumber)))
            {
                CHK_OFAIL(mxf_get_uint32_item(materialPackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackNumber), &wrappedTrack->trackNumber));
            }
            else
            {
                wrappedTrack->trackNumber = 0;
            }
            CHK_OFAIL(mxf_get_uint32_item(materialPackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackID), &wrappedTrack->trackID));
            CHK_OFAIL(mxf_get_rational_item(materialPackageTrackSet, &MXF_ITEM_K(Track, EditRate), &wrappedTrack->editRate));
            CHK_OFAIL(mxf_uu_get_track_duration(materialPackageTrackSet, &wrappedTrack->duration));
            CHK_OFAIL(mxf_uu_get_track_reference(materialPackageTrackSet, &wrappedTrack->sourcePackageUID, &wrappedTrack->sourceTrackID));
            wrappedTrack->isVideo = mxf_is_picture(&dataDefUL);
            track->isVideo = wrappedTrack->isVideo;
            track->materialTrackID = wrappedTrack->trackID;
            track->materialTrackNumber = wrappedTrack->trackNumber;

            if (wrappedTrack->isVideo)
            {
                track->video.frameRate = wrappedTrack->editRate;
            }

            if (wrappedTrack->trackNumber == 0)
            {
                haveZeroTrackNumber = 1;
            }
        }
    }


    /* sort the tracks; use trackNumber if != 0 else use the trackID; video track is always first */

    mxf_initialise_list_iter(&listIter, &wrappedTracks);
    while (mxf_next_list_iter_element(&listIter))
    {
        wrappedTrack = (WrappedTrack*)mxf_get_iter_element(&listIter);

        wasInserted = 0;
        mxf_initialise_list_iter(&sortedListIter, &sortedWrappedTracks);
        while (mxf_next_list_iter_element(&sortedListIter))
        {
            sortedWrappedTrack = (WrappedTrack*)mxf_get_iter_element(&sortedListIter);
            if ((wrappedTrack->track->isVideo && !sortedWrappedTrack->track->isVideo) ||
                (wrappedTrack->track->isVideo == sortedWrappedTrack->track->isVideo &&
                    ((!haveZeroTrackNumber && wrappedTrack->trackNumber < sortedWrappedTrack->trackNumber) ||
                        (haveZeroTrackNumber && wrappedTrack->trackID < sortedWrappedTrack->trackID))))
            {
                CHK_OFAIL(mxf_insert_list_element(&sortedWrappedTracks, mxf_get_list_iter_index(&sortedListIter),
                    1, wrappedTrack));
                wasInserted = 1;
                break;
            }
        }

        if (!wasInserted)
        {
            CHK_OFAIL(mxf_append_list_element(&sortedWrappedTracks, wrappedTrack));
        }
    }
    /* set the MXFTracks to the same order */
    prevSortedWrappedTrack = NULL;
    firstSortedWrappedTrack = NULL;
    mxf_initialise_list_iter(&sortedListIter, &sortedWrappedTracks);
    while (mxf_next_list_iter_element(&sortedListIter))
    {
        sortedWrappedTrack = (WrappedTrack*)mxf_get_iter_element(&sortedListIter);
        if (firstSortedWrappedTrack == NULL)
        {
            firstSortedWrappedTrack = sortedWrappedTrack;
        }
        if (prevSortedWrappedTrack != NULL)
        {
            prevSortedWrappedTrack->track->next = sortedWrappedTrack->track;
        }
        prevSortedWrappedTrack = sortedWrappedTrack;
    }
    if (prevSortedWrappedTrack != NULL)
    {
        prevSortedWrappedTrack->track->next = NULL;
    }
    if (firstSortedWrappedTrack != NULL)
    {
        reader->clip.tracks = firstSortedWrappedTrack->track;
    }


    /* process source package tracks and linked descriptors */

    mxf_initialise_list_iter(&sortedListIter, &sortedWrappedTracks);
    while (mxf_next_list_iter_element(&sortedListIter))
    {
        sortedWrappedTrack = (WrappedTrack*)mxf_get_iter_element(&sortedListIter);

        CHK_OFAIL(mxf_uu_get_referenced_track(data->headerMetadata, &sortedWrappedTrack->sourcePackageUID,
            sortedWrappedTrack->sourceTrackID, &sourcePackageTrackSet));

        CHK_OFAIL(add_essence_track(essenceReader, &essenceTrack));

        essenceTrack->isVideo = sortedWrappedTrack->isVideo;

        if (mxf_have_item(sourcePackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackNumber)))
        {
            CHK_OFAIL(mxf_get_uint32_item(sourcePackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackNumber), &essenceTrack->trackNumber));
        }
        else
        {
            essenceTrack->trackNumber = 0;
        }
        CHK_OFAIL(mxf_get_uint32_item(sourcePackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackID), &trackID));

        essenceTrack->frameRate = reader->clip.frameRate;
        essenceTrack->playoutDuration = reader->clip.duration;

        essenceTrack->indexSID = data->indexSID;
        essenceTrack->bodySID = data->bodySID;

        /* process the descriptor */

        CHK_OFAIL(mxf_uu_get_referenced_package(data->headerMetadata, &sortedWrappedTrack->sourcePackageUID,
            &sourcePackageSet));
        CHK_OFAIL(mxf_uu_get_track_descriptor(sourcePackageSet, trackID, &descriptorSet));

        if (mxf_is_subclass_of(data->headerMetadata->dataModel, &descriptorSet->key, &MXF_SET_K(CDCIEssenceDescriptor)))
        {
            CHK_OFAIL(process_cdci_descriptor(descriptorSet, sortedWrappedTrack->track, essenceTrack));
        }
        else if (mxf_is_subclass_of(data->headerMetadata->dataModel, &descriptorSet->key, &MXF_SET_K(WaveAudioDescriptor)))
        {
            CHK_OFAIL(process_wav_descriptor(descriptorSet, sortedWrappedTrack->track, essenceTrack));
        }
        else if (mxf_is_subclass_of(data->headerMetadata->dataModel, &descriptorSet->key, &MXF_SET_K(GenericSoundEssenceDescriptor)))
        {
            CHK_OFAIL(process_sound_descriptor(descriptorSet, track, essenceTrack));
        }
        else
        {
            mxf_log_error("Unsupported file descriptor" LOG_LOC_FORMAT, LOG_LOC_PARAMS);
            return 0;
        }
    }


    /* initialise the playout timecode */

    if (!initialise_playout_timecode(reader, materialPackageSet))
    {
        CHK_ORET(initialise_default_playout_timecode(reader));
    }


    /* initialise the source timecodes */

    initialise_source_timecodes(reader, sourcePackageSet);



    mxf_clear_list(&wrappedTracks);
    mxf_clear_list(&sortedWrappedTracks);
    return 1;

fail:
    SAFE_FREE(newWrappedTrack);
    mxf_clear_list(&wrappedTracks);
    mxf_clear_list(&sortedWrappedTracks);
    return 0;
}
Exemplo n.º 10
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;
}