This source file includes following definitions.
- gf_isom_set_output_buffering
 
- gf_isom_datamap_del
 
- gf_isom_datamap_close
 
- IsLargeFile
 
- gf_isom_datamap_new
 
- gf_isom_datamap_open
 
- gf_isom_datamap_get_data
 
- gf_isom_datamap_flush
 
- gf_isom_datamap_get_offset
 
- gf_isom_datamap_add_data
 
- gf_isom_fdm_new_temp
 
- gf_isom_fdm_new
 
- gf_isom_fdm_del
 
- gf_isom_fdm_get_data
 
- FDM_GetTotalOffset
 
- FDM_AddData
 
- gf_isom_fmo_new
 
- gf_isom_fmo_del
 
- gf_isom_fmo_get_data
 
- gf_isom_fmo_new
 
- gf_isom_fmo_del
 
- gf_isom_fmo_get_data
 
#include <gpac/internal/isomedia_dev.h>
#include <gpac/network.h>
#ifndef GPAC_DISABLE_ISOM
static u32 default_write_buffering_size = 0;
GF_EXPORT
GF_Err gf_isom_set_output_buffering(GF_ISOFile *movie, u32 size)
{
#ifndef GPAC_DISABLE_ISOM_WRITE
        if (!movie) {
                default_write_buffering_size = size;
                return GF_OK;
        }
        if (!movie->editFileMap) return GF_BAD_PARAM;
        return gf_bs_set_output_buffering(movie->editFileMap->bs, size);
#else
        return GF_NOT_SUPPORTED;
#endif
}
void gf_isom_datamap_del(GF_DataMap *ptr)
{
        if (!ptr) return;
        if (ptr->szName) gf_free(ptr->szName);
        
        switch (ptr->type) {
        
        case GF_ISOM_DATA_FILE:
                gf_isom_fdm_del((GF_FileDataMap *)ptr);
                break;
        case GF_ISOM_DATA_FILE_MAPPING:
                gf_isom_fmo_del((GF_FileMappingDataMap *)ptr);
                break;
        
        default:
                break;
        }
}
void gf_isom_datamap_close(GF_MediaInformationBox *minf)
{
        GF_DataEntryBox *ent;
        if (!minf || !minf->dataHandler) return;
        ent = (GF_DataEntryBox*)gf_list_get(minf->dataInformation->dref->other_boxes, minf->dataEntryIndex - 1);
        
        if (ent == NULL) return;
        
        switch (ent->type) {
        case GF_ISOM_BOX_TYPE_URL:
        case GF_ISOM_BOX_TYPE_URN:
                if (ent->flags == 1) return;
                break;
        default:
                return;
        }
        
        gf_isom_datamap_del(minf->dataHandler);
        minf->dataHandler = NULL;
}
#if 0
static Bool IsLargeFile(char *path)
{
#ifndef _WIN32_WCE
        FILE *stream;
        s64 size;
        stream = gf_fopen(path, "rb");
        if (!stream) return 0;
        gf_fseek(stream, 0, SEEK_END);
        size = gf_ftell(stream);
        gf_fclose(stream);
        if (size == -1L) return 0;
        if (size > 0xFFFFFFFF) return 1;
#endif
        return 0;
}
#endif
GF_Err gf_isom_datamap_new(const char *location, const char *parentPath, u8 mode, GF_DataMap **outDataMap)
{
        Bool extern_file;
        char *sPath;
        *outDataMap = NULL;
        
        if (!location) {
                
                return GF_NOT_SUPPORTED;
        }
        
        if (!strcmp(location, "mp4_tmp_edit")) {
#ifndef GPAC_DISABLE_ISOM_WRITE
                *outDataMap = gf_isom_fdm_new_temp(parentPath);
                if (! (*outDataMap)) {
                        return GF_IO_ERR;
                }
                return GF_OK;
#else
                return GF_NOT_SUPPORTED;
#endif
        } else if (!strncmp(location, "gmem://", 7)) {
                *outDataMap = gf_isom_fdm_new(location, GF_ISOM_DATA_MAP_READ);
                if (! (*outDataMap)) {
                        return GF_IO_ERR;
                }
                return GF_OK;
        }
        extern_file = !gf_url_is_local(location);
        if (mode == GF_ISOM_DATA_MAP_EDIT) {
                
                if (extern_file) return GF_ISOM_INVALID_MODE;
                
                mode = GF_ISOM_DATA_MAP_READ;
        }
        
        if (extern_file) {
                return GF_NOT_SUPPORTED;
        }
        sPath = gf_url_get_absolute_path(location, parentPath);
        if (sPath == NULL) {
                return GF_URL_ERROR;
        }
        if (mode == GF_ISOM_DATA_MAP_READ_ONLY) {
                mode = GF_ISOM_DATA_MAP_READ;
                
#if 0
                if (IsLargeFile(sPath)) {
                        *outDataMap = gf_isom_fdm_new(sPath, mode);
                } else {
                        *outDataMap = gf_isom_fmo_new(sPath, mode);
                }
#else
                *outDataMap = gf_isom_fdm_new(sPath, mode);
#endif
        } else {
                *outDataMap = gf_isom_fdm_new(sPath, mode);
                if (*outDataMap) {
                        (*outDataMap)->szName = sPath;
                        sPath = NULL;
                }
        }
        if (sPath) {
                gf_free(sPath);
        }
        if (! (*outDataMap)) {
                return GF_URL_ERROR;
        }
        return GF_OK;
}
GF_Err gf_isom_datamap_open(GF_MediaBox *mdia, u32 dataRefIndex, u8 Edit)
{
        GF_DataEntryBox *ent;
        GF_MediaInformationBox *minf;
        u32 SelfCont, count;
        GF_Err e = GF_OK;
        if ((mdia == NULL) || (! mdia->information) || !dataRefIndex)
                return GF_ISOM_INVALID_MEDIA;
        minf = mdia->information;
        count = gf_list_count(minf->dataInformation->dref->other_boxes);
        if (!count) {
                SelfCont = 1;
                ent = NULL;
        } else {
                if (dataRefIndex > gf_list_count(minf->dataInformation->dref->other_boxes))
                        return GF_BAD_PARAM;
                ent = (GF_DataEntryBox*)gf_list_get(minf->dataInformation->dref->other_boxes, dataRefIndex - 1);
                if (ent == NULL) return GF_ISOM_INVALID_MEDIA;
                
                if ((minf->dataEntryIndex == dataRefIndex) && (ent->flags != 1)) {
                        return GF_OK;
                }
                SelfCont = 0;
                switch (ent->type) {
                case GF_ISOM_BOX_TYPE_URL:
                case GF_ISOM_BOX_TYPE_URN:
                        if (ent->flags == 1) SelfCont = 1;
                        break;
                default:
                        SelfCont = 1;
                        break;
                }
        }
        
        
        if (minf->dataHandler) gf_isom_datamap_close(minf);
        
        if (SelfCont) {
                
                if (!Edit) {
                        if (mdia->mediaTrack->moov->mov->movieFileMap == NULL) return GF_ISOM_INVALID_FILE;
                        minf->dataHandler = mdia->mediaTrack->moov->mov->movieFileMap;
                } else {
#ifndef GPAC_DISABLE_ISOM_WRITE
                        if (mdia->mediaTrack->moov->mov->editFileMap == NULL) return GF_ISOM_INVALID_FILE;
                        minf->dataHandler = mdia->mediaTrack->moov->mov->editFileMap;
#else
                        
                        return GF_BAD_PARAM;
#endif
                }
                
        } else {
                e = gf_isom_datamap_new(ent->location, mdia->mediaTrack->moov->mov->fileName, GF_ISOM_DATA_MAP_READ, & mdia->information->dataHandler);
                if (e) return (e==GF_URL_ERROR) ? GF_ISOM_UNKNOWN_DATA_REF : e;
        }
        
        minf->dataEntryIndex = dataRefIndex;
        return GF_OK;
}
u32 gf_isom_datamap_get_data(GF_DataMap *map, char *buffer, u32 bufferLength, u64 Offset)
{
        if (!map || !buffer) return 0;
        switch (map->type) {
        case GF_ISOM_DATA_FILE:
                return gf_isom_fdm_get_data((GF_FileDataMap *)map, buffer, bufferLength, Offset);
        case GF_ISOM_DATA_FILE_MAPPING:
                return gf_isom_fmo_get_data((GF_FileMappingDataMap *)map, buffer, bufferLength, Offset);
        default:
                return 0;
        }
}
void gf_isom_datamap_flush(GF_DataMap *map)
{
        if (!map) return;
        if (map->type==GF_ISOM_DATA_FILE) {
                GF_FileDataMap *fdm = (GF_FileDataMap *)map;
                gf_bs_flush(fdm->bs);
        }
}
#ifndef GPAC_DISABLE_ISOM_WRITE
u64 FDM_GetTotalOffset(GF_FileDataMap *ptr);
GF_Err FDM_AddData(GF_FileDataMap *ptr, char *data, u32 dataSize);
u64 gf_isom_datamap_get_offset(GF_DataMap *map)
{
        if (!map) return 0;
        switch (map->type) {
        case GF_ISOM_DATA_FILE:
                return FDM_GetTotalOffset((GF_FileDataMap *)map);
        default:
                return 0;
        }
}
GF_Err gf_isom_datamap_add_data(GF_DataMap *ptr, char *data, u32 dataSize)
{
        if (!ptr || !data|| !dataSize) return GF_BAD_PARAM;
        switch (ptr->type) {
        case GF_ISOM_DATA_FILE:
                return FDM_AddData((GF_FileDataMap *)ptr, data, dataSize);
        default:
                return GF_NOT_SUPPORTED;
        }
}
GF_DataMap *gf_isom_fdm_new_temp(const char *sPath)
{
        GF_FileDataMap *tmp;
        GF_SAFEALLOC(tmp, GF_FileDataMap);
        if (!tmp) return NULL;
        tmp->type = GF_ISOM_DATA_FILE;
        tmp->mode = GF_ISOM_DATA_MAP_WRITE;
        if (!sPath) {
                tmp->stream = gf_temp_file_new(&tmp->temp_file);
        } else {
                char szPath[GF_MAX_PATH];
                if ((sPath[strlen(sPath)-1] != '\\') && (sPath[strlen(sPath)-1] != '/')) {
                        sprintf(szPath, "%s%c%p_isotmp", sPath, GF_PATH_SEPARATOR, (void*) tmp);
                } else {
                        sprintf(szPath, "%s%p_isotmp", sPath, (void*) tmp);
                }
                tmp->stream = gf_fopen(szPath, "w+b");
                tmp->temp_file = gf_strdup(szPath);
        }
        if (!tmp->stream) {
                if (tmp->temp_file) gf_free(tmp->temp_file);
                gf_free(tmp);
                return NULL;
        }
        tmp->bs = gf_bs_from_file(tmp->stream, GF_BITSTREAM_WRITE);
        if (!tmp->bs) {
                gf_fclose(tmp->stream);
                gf_free(tmp);
                return NULL;
        }
        if (default_write_buffering_size) {
                gf_bs_set_output_buffering(tmp->bs, default_write_buffering_size);
        }
        return (GF_DataMap *)tmp;
}
#endif 
#include <errno.h>
#include <string.h>
GF_DataMap *gf_isom_fdm_new(const char *sPath, u8 mode)
{
        u8 bs_mode;
        GF_FileDataMap *tmp;
        GF_SAFEALLOC(tmp, GF_FileDataMap);
        if (!tmp) return NULL;
        tmp->type = GF_ISOM_DATA_FILE;
        tmp->mode = mode;
#ifndef GPAC_DISABLE_ISOM_WRITE
        
        if (!strcmp(sPath, "mp4_tmp_edit")) {
                
                tmp->stream = gf_temp_file_new(&tmp->temp_file);
        }
#endif
        if (!strncmp(sPath, "gmem://", 7)) {
                u32 size;
                void *mem_address;
                if (sscanf(sPath, "gmem://%d@%p", &size, &mem_address) != 2)
                        return NULL;
                tmp->bs = gf_bs_new((const char *)mem_address, size, GF_BITSTREAM_READ);
                if (!tmp->bs) {
                        gf_free(tmp);
                        return NULL;
                }
                return (GF_DataMap *)tmp;
        }
        switch (mode) {
        case GF_ISOM_DATA_MAP_READ:
                if (!tmp->stream) tmp->stream = gf_fopen(sPath, "rb");
                bs_mode = GF_BITSTREAM_READ;
                break;
        
        case GF_ISOM_DATA_MAP_WRITE:
                if (!strcmp(sPath, "std")) {
                        tmp->stream = stdout;
                        tmp->is_stdout = 1;
                }
                if (!tmp->stream) tmp->stream = gf_fopen(sPath, "w+b");
                if (!tmp->stream) tmp->stream = gf_fopen(sPath, "wb");
                bs_mode = GF_BITSTREAM_WRITE;
                break;
        
        case GF_ISOM_DATA_MAP_CAT:
                if (!strcmp(sPath, "std")) {
                        tmp->stream = stdout;
                        tmp->is_stdout = 1;
                }
                if (!tmp->stream) tmp->stream = gf_fopen(sPath, "a+b");
                if (tmp->stream) gf_fseek(tmp->stream, 0, SEEK_END);
                bs_mode = GF_BITSTREAM_WRITE;
                break;
        default:
                gf_free(tmp);
                return NULL;
        }
        if (!tmp->stream) {
                gf_free(tmp);
                return NULL;
        }
        tmp->bs = gf_bs_from_file(tmp->stream, bs_mode);
        if (!tmp->bs) {
                gf_fclose(tmp->stream);
                gf_free(tmp);
                return NULL;
        }
        if (default_write_buffering_size) {
                gf_bs_set_output_buffering(tmp->bs, default_write_buffering_size);
        }
        return (GF_DataMap *)tmp;
}
void gf_isom_fdm_del(GF_FileDataMap *ptr)
{
        if (!ptr || (ptr->type != GF_ISOM_DATA_FILE)) return;
        if (ptr->bs) gf_bs_del(ptr->bs);
        if (ptr->stream && !ptr->is_stdout)
                gf_fclose(ptr->stream);
#ifndef GPAC_DISABLE_ISOM_WRITE
        if (ptr->temp_file) {
                gf_delete_file(ptr->temp_file);
                gf_free(ptr->temp_file);
        }
#endif
        gf_free(ptr);
}
u32 gf_isom_fdm_get_data(GF_FileDataMap *ptr, char *buffer, u32 bufferLength, u64 fileOffset)
{
        u32 bytesRead;
        
        if (fileOffset > gf_bs_get_size(ptr->bs)) return 0;
        if (gf_bs_get_position(ptr->bs) != fileOffset) {
                
                if (gf_bs_seek(ptr->bs, fileOffset) != GF_OK) return 0;
        }
        ptr->curPos = fileOffset;
        
        bytesRead = gf_bs_read_data(ptr->bs, buffer, bufferLength);
        
        if (bytesRead == bufferLength) {
                ptr->curPos += bytesRead;
        } else {
                gf_bs_get_refreshed_size(ptr->bs);
                gf_bs_seek(ptr->bs, fileOffset);
                bytesRead = gf_bs_read_data(ptr->bs, buffer, bufferLength);
                
                if (bytesRead == bufferLength) {
                        ptr->curPos += bytesRead;
                } else {
                        gf_bs_seek(ptr->bs, ptr->curPos);
                        bytesRead = 0;
                }
        }
        ptr->last_acces_was_read = 1;
        return bytesRead;
}
#ifndef GPAC_DISABLE_ISOM_WRITE
u64 FDM_GetTotalOffset(GF_FileDataMap *ptr)
{
        if (!ptr) return 0;
        
        
        
        return gf_bs_get_size(ptr->bs);
}
GF_Err FDM_AddData(GF_FileDataMap *ptr, char *data, u32 dataSize)
{
        u32 ret;
        u64 orig;
        if (ptr->mode == GF_ISOM_DATA_MAP_READ) return GF_BAD_PARAM;
        orig = gf_bs_get_size(ptr->bs);
        
        if (ptr->last_acces_was_read) {
                gf_bs_seek(ptr->bs, orig);
                ptr->last_acces_was_read = 0;
        }
        
        
        ret = gf_bs_write_data(ptr->bs, data, dataSize);
        if (ret != dataSize) {
                ptr->curPos = orig;
                gf_bs_seek(ptr->bs, orig);
                return GF_IO_ERR;
        }
        ptr->curPos = gf_bs_get_position(ptr->bs);
        
        if (ptr->stream) fflush(ptr->stream);
        return GF_OK;
}
#endif  
#ifdef WIN32
#include <windows.h>
#include <winerror.h>
GF_DataMap *gf_isom_fmo_new(const char *sPath, u8 mode)
{
        GF_FileMappingDataMap *tmp;
        HANDLE fileH, fileMapH;
#ifdef _WIN32_WCE
        unsigned short sWPath[MAX_PATH];
#endif
        
        if (mode != GF_ISOM_DATA_MAP_READ) return NULL;
        GF_SAFEALLOC(tmp, GF_FileMappingDataMap);
        if (!tmp) return NULL;
        tmp->type = GF_ISOM_DATA_FILE_MAPPING;
        tmp->mode = mode;
        tmp->name = gf_strdup(sPath);
        
        
        
#ifdef _WIN32_WCE
        
        CE_CharToWide((char *)sPath, sWPath);
        fileH = CreateFileForMapping(sWPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
                                     (FILE_ATTRIBUTE_READONLY | FILE_FLAG_RANDOM_ACCESS), NULL );
#else
        fileH = CreateFile(sPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
                           (FILE_ATTRIBUTE_READONLY | FILE_FLAG_RANDOM_ACCESS), NULL );
#endif
        if (fileH == INVALID_HANDLE_VALUE) {
                gf_free(tmp->name);
                gf_free(tmp);
                return NULL;
        }
        tmp->file_size = GetFileSize(fileH, NULL);
        if (tmp->file_size == 0xFFFFFFFF) {
                CloseHandle(fileH);
                gf_free(tmp->name);
                gf_free(tmp);
                return NULL;
        }
        
        
        
        fileMapH = CreateFileMapping(fileH, NULL, PAGE_READONLY, 0, 0, NULL);
        if (fileMapH == NULL) {
                CloseHandle(fileH);
                gf_free(tmp->name);
                gf_free(tmp);
                return NULL;
        }
        tmp->byte_map = MapViewOfFile(fileMapH, FILE_MAP_READ, 0, 0, 0);
        if (tmp->byte_map == NULL) {
                CloseHandle(fileMapH);
                CloseHandle(fileH);
                gf_free(tmp->name);
                gf_free(tmp);
                return NULL;
        }
        CloseHandle(fileH);
        CloseHandle(fileMapH);
        
        tmp->bs = gf_bs_new(tmp->byte_map, tmp->file_size, GF_BITSTREAM_READ);
        return (GF_DataMap *)tmp;
}
void gf_isom_fmo_del(GF_FileMappingDataMap *ptr)
{
        if (!ptr || (ptr->type != GF_ISOM_DATA_FILE_MAPPING)) return;
        if (ptr->bs) gf_bs_del(ptr->bs);
        if (ptr->byte_map) UnmapViewOfFile(ptr->byte_map);
        gf_free(ptr->name);
        gf_free(ptr);
}
u32 gf_isom_fmo_get_data(GF_FileMappingDataMap *ptr, char *buffer, u32 bufferLength, u64 fileOffset)
{
        
        if (fileOffset > ptr->file_size) return 0;
        
        memcpy(buffer, ptr->byte_map + fileOffset, bufferLength);
        return bufferLength;
}
#else
GF_DataMap *gf_isom_fmo_new(const char *sPath, u8 mode) {
        return gf_isom_fdm_new(sPath, mode);
}
void gf_isom_fmo_del(GF_FileMappingDataMap *ptr) {
        gf_isom_fdm_del((GF_FileDataMap *)ptr);
}
u32 gf_isom_fmo_get_data(GF_FileMappingDataMap *ptr, char *buffer, u32 bufferLength, u64 fileOffset)
{
        return gf_isom_fdm_get_data((GF_FileDataMap *)ptr, buffer, bufferLength, fileOffset);
}
#endif
#endif