📄 isom_read.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <gpac/internal/isomedia_dev.h>//the only static var. Used to store any error happening while opening a moviestatic GF_Err MP4_API_IO_Err;void gf_isom_set_last_error(GF_ISOFile *movie, GF_Err error){ if (!movie) { MP4_API_IO_Err = error; } else { movie->LastError = error; }}GF_EXPORTGF_Err gf_isom_last_error(GF_ISOFile *the_file){ if (!the_file) return MP4_API_IO_Err; return the_file->LastError;}GF_EXPORTu8 gf_isom_get_mode(GF_ISOFile *the_file){ if (!the_file) return 0; return the_file->openMode;}/************************************************************** Sample Manip**************************************************************///creates a new empty sampleGF_EXPORTGF_ISOSample *gf_isom_sample_new(){ GF_ISOSample *tmp; GF_SAFEALLOC(tmp, GF_ISOSample); return tmp;}//delete a sampleGF_EXPORTvoid gf_isom_sample_del(GF_ISOSample **samp){ if (! *samp) return; if ((*samp)->data && (*samp)->dataLength) free((*samp)->data); free(*samp); *samp = NULL;}GF_EXPORTBool gf_isom_probe_file(const char *fileName){ unsigned char data[4]; u32 type; FILE *f = fopen(fileName, "rb"); if (!f) return 0; type = 0; if (fread(data, 1, 4, f) == 4) { if (fread(data, 1, 4, f) == 4) { type = GF_4CC(data[0], data[1], data[2], data[3]); } } fclose(f); switch (type) { case GF_ISOM_BOX_TYPE_MOOV: case GF_ISOM_BOX_TYPE_MDAT: case GF_ISOM_BOX_TYPE_FTYP: case GF_ISOM_BOX_TYPE_FREE: case GF_ISOM_BOX_TYPE_SKIP: case GF_ISOM_BOX_TYPE_UDTA: case GF_ISOM_BOX_TYPE_META: case GF_ISOM_BOX_TYPE_VOID: case GF_4CC('j','P',' ',' '): case GF_4CC('w','i','d','e'): return 1; default: return 0; }}/************************************************************** File Opening in streaming mode the file map is regular (through FILE handles)**************************************************************/GF_EXPORTGF_Err gf_isom_open_progressive(const char *fileName, GF_ISOFile **the_file, u64 *BytesMissing){ GF_Err e; GF_ISOFile *movie; *BytesMissing = 0; *the_file = NULL; movie = gf_isom_new_movie(); if (!movie) return GF_OUT_OF_MEM; movie->fileName = strdup(fileName); movie->openMode = GF_ISOM_OPEN_READ; //do NOT use FileMapping on incomplete files e = gf_isom_datamap_new(fileName, NULL, GF_ISOM_DATA_MAP_READ, &movie->movieFileMap); if (e) { gf_isom_delete_movie(movie); return e; }#ifndef GPAC_READ_ONLY movie->editFileMap = NULL; movie->finalName = NULL;#endif //GPAC_READ_ONLY e = gf_isom_parse_movie_boxes(movie, BytesMissing); if (e == GF_ISOM_INCOMPLETE_FILE) { //if we have a moov, we're fine if (movie->moov) { *the_file = (GF_ISOFile *)movie; return GF_OK; } //if not, delete the movie gf_isom_delete_movie(movie); return e; } else if (e) { //if not, delete the movie gf_isom_delete_movie(movie); return e; } //OK, let's return *the_file = (GF_ISOFile *)movie; return GF_OK;}/************************************************************** File Reading**************************************************************/GF_EXPORTGF_ISOFile *gf_isom_open(const char *fileName, u32 OpenMode, const char *tmp_dir){ GF_ISOFile *movie; MP4_API_IO_Err = GF_OK; switch (OpenMode & 0xFF) { case GF_ISOM_OPEN_READ_DUMP: case GF_ISOM_OPEN_READ: movie = gf_isom_open_file(fileName, OpenMode, NULL); break;#ifndef GPAC_READ_ONLY case GF_ISOM_OPEN_WRITE: movie = gf_isom_create_movie(fileName, OpenMode, tmp_dir); break; case GF_ISOM_OPEN_EDIT: movie = gf_isom_open_file(fileName, OpenMode, tmp_dir); break; case GF_ISOM_WRITE_EDIT: movie = gf_isom_create_movie(fileName, OpenMode, tmp_dir); break;#endif //GPAC_READ_ONLY default: return NULL; } return (GF_ISOFile *) movie;}GF_EXPORTGF_Err gf_isom_close(GF_ISOFile *movie){ GF_Err e; if (movie == NULL) return GF_ISOM_INVALID_FILE; e = GF_OK;#ifndef GPAC_READ_ONLY //write our movie to the file if (movie->openMode != GF_ISOM_OPEN_READ) { gf_isom_get_duration(movie);#ifndef GF_ISOM_NO_FRAGMENTS //movie fragment mode, just store the fragment if ( (movie->openMode == GF_ISOM_OPEN_WRITE) && (movie->FragmentsFlags & GF_ISOM_FRAG_WRITE_READY) ) { e = StoreFragment(movie); } else #endif e = WriteToFile(movie); } #endif //GPAC_READ_ONLY //free and return; gf_isom_delete_movie(movie); return e;}GF_EXPORTBool gf_isom_has_root_od(GF_ISOFile *movie){ if (!movie || !movie->moov || !movie->moov->iods || !movie->moov->iods->descriptor) return 0; return 1;}//this funct is used for exchange files, where the iods contains an ODGF_EXPORTGF_Descriptor *gf_isom_get_root_od(GF_ISOFile *movie){ GF_Descriptor *desc; GF_ObjectDescriptor *od; GF_InitialObjectDescriptor *iod; GF_IsomObjectDescriptor *isom_od; GF_IsomInitialObjectDescriptor *isom_iod; GF_ESD *esd; GF_ES_ID_Inc *inc; u32 i; u8 useIOD; if (!movie || !movie->moov) return NULL; if (!movie->moov->iods) return NULL; od = NULL; iod = NULL; switch (movie->moov->iods->descriptor->tag) { case GF_ODF_ISOM_OD_TAG: od = (GF_ObjectDescriptor*)malloc(sizeof(GF_ObjectDescriptor)); memset(od, 0, sizeof(GF_ObjectDescriptor)); od->ESDescriptors = gf_list_new(); useIOD = 0; break; case GF_ODF_ISOM_IOD_TAG: iod = (GF_InitialObjectDescriptor*)malloc(sizeof(GF_InitialObjectDescriptor)); memset(iod, 0, sizeof(GF_InitialObjectDescriptor)); iod->ESDescriptors = gf_list_new(); useIOD = 1; break; default: return NULL; } //duplicate our descriptor movie->LastError = gf_odf_desc_copy((GF_Descriptor *) movie->moov->iods->descriptor, &desc); if (movie->LastError) return NULL; if (!useIOD) { isom_od = (GF_IsomObjectDescriptor *)desc; od->objectDescriptorID = isom_od->objectDescriptorID; od->extensionDescriptors = isom_od->extensionDescriptors; isom_od->extensionDescriptors = NULL; od->IPMP_Descriptors = isom_od->IPMP_Descriptors; isom_od->IPMP_Descriptors = NULL; od->OCIDescriptors = isom_od->OCIDescriptors; isom_od->OCIDescriptors = NULL; od->URLString = isom_od->URLString; isom_od->URLString = NULL; od->tag = GF_ODF_OD_TAG; //then recreate the desc in Inc i=0; while ((inc = (GF_ES_ID_Inc*)gf_list_enum(isom_od->ES_ID_IncDescriptors, &i))) { movie->LastError = GetESDForTime(movie->moov, inc->trackID, 0, &esd); if (!movie->LastError) movie->LastError = gf_list_add(od->ESDescriptors, esd); if (movie->LastError) { gf_odf_desc_del(desc); gf_odf_desc_del((GF_Descriptor *) od); return NULL; } } gf_odf_desc_del(desc); return (GF_Descriptor *)od; } else { isom_iod = (GF_IsomInitialObjectDescriptor *)desc; iod->objectDescriptorID = isom_iod->objectDescriptorID; iod->extensionDescriptors = isom_iod->extensionDescriptors; isom_iod->extensionDescriptors = NULL; iod->IPMP_Descriptors = isom_iod->IPMP_Descriptors; isom_iod->IPMP_Descriptors = NULL; iod->OCIDescriptors = isom_iod->OCIDescriptors; isom_iod->OCIDescriptors = NULL; iod->URLString = isom_iod->URLString; isom_iod->URLString = NULL; iod->tag = GF_ODF_IOD_TAG; iod->audio_profileAndLevel = isom_iod->audio_profileAndLevel; iod->graphics_profileAndLevel = isom_iod->graphics_profileAndLevel; iod->inlineProfileFlag = isom_iod->inlineProfileFlag; iod->OD_profileAndLevel = isom_iod->OD_profileAndLevel; iod->scene_profileAndLevel = isom_iod->scene_profileAndLevel; iod->visual_profileAndLevel = isom_iod->visual_profileAndLevel; iod->IPMPToolList = isom_iod->IPMPToolList; isom_iod->IPMPToolList = NULL; //then recreate the desc in Inc i=0; while ((inc = (GF_ES_ID_Inc*)gf_list_enum(isom_iod->ES_ID_IncDescriptors, &i))) { movie->LastError = GetESDForTime(movie->moov, inc->trackID, 0, &esd); if (!movie->LastError) movie->LastError = gf_list_add(iod->ESDescriptors, esd); if (movie->LastError) { gf_odf_desc_del(desc); gf_odf_desc_del((GF_Descriptor *) &iod); return NULL; } } gf_odf_desc_del(desc); return (GF_Descriptor *)iod; }}GF_EXPORTu32 gf_isom_get_track_count(GF_ISOFile *movie){ if (!movie || !movie->moov) return 0; if (! movie->moov->trackList) { movie->LastError = GF_ISOM_INVALID_FILE; return 0; } return gf_list_count(movie->moov->trackList);}GF_EXPORTu32 gf_isom_get_track_id(GF_ISOFile *movie, u32 trackNumber){ GF_TrackBox *trak; if (!movie) return 0; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak) return 0; return trak->Header->trackID;}GF_EXPORTu32 gf_isom_get_track_by_id(GF_ISOFile *the_file, u32 trackID){ GF_TrackBox *trak; u32 count; u32 i; if (the_file == NULL) return 0; count = gf_isom_get_track_count(the_file); if (!count) return 0; for (i = 0; i < count; i++) { trak = gf_isom_get_track_from_file(the_file, i+1); if (!trak) return 0; if (trak->Header->trackID == trackID) return i+1; } return 0;}//return the timescale of the movie, 0 if errorGF_EXPORTBool gf_isom_has_movie(GF_ISOFile *file){ if (file && file->moov) return 1; return 0;}//return the timescale of the movie, 0 if errorGF_EXPORTu32 gf_isom_get_timescale(GF_ISOFile *movie){ if (!movie || !movie->moov) return 0; return movie->moov->mvhd->timeScale;}//return the duration of the movie, 0 if errorGF_EXPORTu64 gf_isom_get_duration(GF_ISOFile *movie){#ifndef GPAC_READ_ONLY u32 i; u64 maxDur; GF_TrackBox *trak;#endif if (!movie || !movie->moov) return 0; //if file was open in Write or Edit mode, recompute the duration //the duration of a movie is the MaxDuration of all the tracks...#ifndef GPAC_READ_ONLY if (movie->openMode != GF_ISOM_OPEN_READ) { maxDur = 0; i=0; while ((trak = (GF_TrackBox *)gf_list_enum(movie->moov->trackList, &i))) { if( (movie->LastError = SetTrackDuration(trak)) ) return 0; if (trak->Header->duration > maxDur) maxDur = trak->Header->duration; } movie->moov->mvhd->duration = maxDur; }#endif //GPAC_READ_ONLY return movie->moov->mvhd->duration;}//return the creation info of the movieGF_EXPORTGF_Err gf_isom_get_creation_time(GF_ISOFile *movie, u64 *creationTime, u64 *modificationTime){ if (!movie || !movie->moov) return GF_BAD_PARAM; if (creationTime) *creationTime = movie->moov->mvhd->creationTime; if (creationTime) *modificationTime = movie->moov->mvhd->modificationTime; return GF_OK;}//check the presence of a track in IOD. 0: NO, 1: YES, 2: ERROR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -