⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isom_store.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 3 页
字号:
			}			//no sample found, we're done with this group			if (!curWriter) {				//we're done with the group				curTrackPriority = 0;				writeGroup = 0;				continue;			}			//To Check: are empty sample tables allowed ???			if (curWriter->sampleNumber > curWriter->mdia->information->sampleTable->SampleSize->sampleCount) {				curWriter->isDone = 1;				tracksDone ++;				continue;			}			e = stbl_GetSampleInfos(curWriter->mdia->information->sampleTable, curWriter->sampleNumber, &sampOffset, &chunkNumber, &descIndex, &isEdited);			if (e) return e;			e = stbl_GetSampleSize(curWriter->mdia->information->sampleTable->SampleSize, curWriter->sampleNumber, &sampSize);			if (e) return e;						//do we actually write, or do we emulate ?			if (Emulation) {				//are we in the same track ??? If not, force a new chunk when adding this sample				if (curWriter != prevWriter) {					forceNewChunk = 1;				} else {					forceNewChunk = 0;				}				//update our offsets...				if (Media_IsSelfContained(curWriter->mdia, descIndex) ) {					e = stbl_SetChunkAndOffset(curWriter->mdia->information->sampleTable, curWriter->sampleNumber, descIndex, curWriter->stsc, &curWriter->stco, offset, forceNewChunk);					if (e) return e;					offset += sampSize;					totSize += sampSize;				} else {					if (curWriter->prev_offset != sampOffset) forceNewChunk = 1;					curWriter->prev_offset = sampOffset + sampSize;					//we have a DataRef, so use the offset idicated in sampleToChunk 					//and ChunkOffset tables...					e = stbl_SetChunkAndOffset(curWriter->mdia->information->sampleTable, curWriter->sampleNumber, descIndex, curWriter->stsc, &curWriter->stco, sampOffset, 0);					if (e) return e;				}			} else {				//this is no game, we're writing ....				if (Media_IsSelfContained(curWriter->mdia, descIndex) ) {					e = WriteSample(mw, sampSize, sampOffset, isEdited, bs);					if (e) return e;				}			}			//ok, the sample is done			if (curWriter->sampleNumber == curWriter->mdia->information->sampleTable->SampleSize->sampleCount) {				curWriter->isDone = 1;				//one more track done...				tracksDone ++;			} else {				curWriter->sampleNumber ++;			}			prevWriter = curWriter;		}		//if all our track are done, break		if (tracksDone == gf_list_count(writers)) break;		//go to next group		curGroupID ++;	}	movie->mdat->dataSize = totSize;	return GF_OK;}/*uncomment the following to easily test large file generation. This will prepend 4096*1MByte of 0 before the media data*///#define TEST_LARGE_FILESGF_Err DoInterleave(MovieWriter *mw, GF_List *writers, GF_BitStream *bs, u8 Emulation, u32 StartOffset, Bool drift_inter){	u32 i, tracksDone;	TrackWriter *tmp, *curWriter;	GF_Err e;	u32 descIndex, sampSize, chunkNumber;	u64 DTS;	u16 curGroupID;	u8 forceNewChunk, writeGroup, isEdited;	//this is used to emulate the write ...	u64 offset, sampOffset, size, mdatSize;	u32 count;	GF_ISOFile *movie = mw->movie;	mdatSize = 0;#ifdef TEST_LARGE_FILES	if (!Emulation) {		char *blank;		u32 count, i;		i = count = 0;		blank = malloc(sizeof(char)*1024*1024);		memset(blank, 0, sizeof(char)*1024*1024);		count = 4096;		memset(blank, 0, sizeof(char)*1024*1024);		while (i<count) {			u32 res = gf_bs_write_data(bs, blank, 1024*1024);			if (res != 1024*1024) fprintf(stdout, "error writing to disk: only %d bytes written\n", res);			i++;			fprintf(stdout, "writing blank block: %.02f done - %d/%d \r", (100.0*i)/count , i, count);		}		free(blank);	}	mdatSize = 4096*1024;	mdatSize *= 1024;#endif	/*write meta content first - WE DON'T support fragmentation of resources in ISOM atm*/	if (movie->meta) {		e = DoWriteMeta(movie, movie->meta, bs, Emulation, StartOffset, &size);		if (e) return e;		mdatSize += size;		StartOffset += (u32) size;	}	if (movie->moov && movie->moov->meta) {		e = DoWriteMeta(movie, movie->moov->meta, bs, Emulation, StartOffset, &size);		if (e) return e;		mdatSize += size;		StartOffset += (u32) size;	}	i=0;	while ((tmp = (TrackWriter*)gf_list_enum(writers, &i))) {		if (tmp->mdia->mediaTrack->meta) {			e = DoWriteMeta(movie, tmp->mdia->mediaTrack->meta, bs, Emulation, StartOffset, &size);			if (e) return e;			mdatSize += size;			StartOffset += (u32) size;		}	}	if (movie->storageMode == GF_ISOM_STORE_TIGHT) 		return DoFullInterleave(mw, writers, bs, Emulation, StartOffset);	e = GF_OK;	curGroupID = 1;	//we emulate a write from this offset...	offset = StartOffset;	writeGroup = 1;	tracksDone = 0;#ifdef TEST_LARGE_FILES	offset += mdatSize;#endif	count = gf_list_count(writers);	//browse each groups	while (1) {		writeGroup = 1;		//proceed a group		while (writeGroup) {			/*the DTS for the end of this chunk*/			u64 chunkMaxDTS = 0;			/*the timescale DTS for the end of this chunk*/			u32 chunkMaxScale = 0;			curWriter = NULL;			for (i=0 ; i < count; i++) {				tmp = (TrackWriter*)gf_list_get(writers, i);								//is it done writing ?				if (tmp->isDone) continue;				//is it in our group ??				if (tmp->mdia->information->sampleTable->groupID != curGroupID) continue;				//write till this chunk is full on this track...				while (1) {					//To Check: are empty sample tables allowed ???					if (tmp->sampleNumber > tmp->mdia->information->sampleTable->SampleSize->sampleCount) {						tmp->isDone = 1;						tracksDone ++;						break;					}					//OK, get the current sample in this track					stbl_GetSampleDTS(tmp->mdia->information->sampleTable->TimeToSample, tmp->sampleNumber, &DTS);					//can this sample fit in our chunk ?					if ( ( (DTS - tmp->DTSprev) + tmp->chunkDur) *  movie->moov->mvhd->timeScale > movie->interleavingTime * tmp->timeScale						/*try to keep chunk synchronized within the group*/						|| (drift_inter && chunkMaxDTS && ( ((u64)tmp->DTSprev*chunkMaxScale) > ((u64)chunkMaxDTS*tmp->timeScale)) ) 						) {						//in case the sample is longer than InterleaveTime						if (!tmp->chunkDur) {							forceNewChunk = 1;						} else {							//this one is full. go to next one (exit the loop)							tmp->chunkDur = 0;							break;						}					} else {						forceNewChunk = tmp->chunkDur ? 0 : 1;					}					//OK, we can write this track					curWriter = tmp;										//small check for first 2 samples (DTS = 0 :)					if (tmp->sampleNumber == 2 && !tmp->chunkDur) forceNewChunk = 0;					tmp->chunkDur += (u32) (DTS - tmp->DTSprev);					tmp->DTSprev = DTS;					e = stbl_GetSampleInfos(curWriter->mdia->information->sampleTable, curWriter->sampleNumber, &sampOffset, &chunkNumber, &descIndex, &isEdited);					if (e) return e;					e = stbl_GetSampleSize(curWriter->mdia->information->sampleTable->SampleSize, curWriter->sampleNumber, &sampSize);					if (e) return e;										//do we actually write, or do we emulate ?					if (Emulation) {						//update our offsets...						if (Media_IsSelfContained(curWriter->mdia, descIndex) ) {							e = stbl_SetChunkAndOffset(curWriter->mdia->information->sampleTable, curWriter->sampleNumber, descIndex, curWriter->stsc, &curWriter->stco, offset, forceNewChunk);							if (e) return e;							offset += sampSize;							mdatSize += sampSize;						} else {							if (curWriter->prev_offset != sampOffset) forceNewChunk = 1;							curWriter->prev_offset = sampOffset + sampSize;							//we have a DataRef, so use the offset idicated in sampleToChunk 							//and ChunkOffset tables...							e = stbl_SetChunkAndOffset(curWriter->mdia->information->sampleTable, curWriter->sampleNumber, descIndex, curWriter->stsc, &curWriter->stco, sampOffset, forceNewChunk);							if (e) return e;						}					} else {						//this is no game, we're writing ....						if (Media_IsSelfContained(curWriter->mdia, descIndex) ) {							e = WriteSample(mw, sampSize, sampOffset, isEdited, bs);							if (e) return e;						}					}					//ok, the sample is done					if (curWriter->sampleNumber == curWriter->mdia->information->sampleTable->SampleSize->sampleCount) {						curWriter->isDone = 1;						//one more track done...						tracksDone ++;						break;					} else {						curWriter->sampleNumber ++;					}				}				/*record chunk end-time & track timescale for drift-controled interleaving*/				if (drift_inter && !chunkMaxDTS && curWriter) {					chunkMaxDTS = curWriter->DTSprev;					chunkMaxScale = curWriter->timeScale;				}			}			//no sample found, we're done with this group			if (!curWriter) {				writeGroup = 0;				continue;			}		}		//if all our track are done, break		if (tracksDone == gf_list_count(writers)) break;		//go to next group		curGroupID ++;	}	if (movie->mdat) movie->mdat->dataSize = mdatSize;	return GF_OK;}static GF_Err WriteInterleaved(MovieWriter *mw, GF_BitStream *bs, Bool drift_inter){	GF_Err e;	u32 i;	GF_Box *a;	u64 firstSize, finalSize, offset, finalOffset;	GF_List *writers = gf_list_new();	GF_ISOFile *movie = mw->movie;	//first setup the writers	e = SetupWriters(mw, writers, 1);	if (e) goto exit;	if (movie->is_jp2) {		gf_bs_write_u32(bs, 12);		gf_bs_write_u32(bs, GF_4CC('j','P',' ',' '));		gf_bs_write_u32(bs, 0x0D0A870A);	}	if (movie->brand) {		e = gf_isom_box_size((GF_Box *)movie->brand);		if (e) goto exit;		e = gf_isom_box_write((GF_Box *)movie->brand, bs);		if (e) goto exit;	}	if (movie->pdin) {		e = gf_isom_box_size((GF_Box *)movie->pdin);		if (e) goto exit;		e = gf_isom_box_write((GF_Box *)movie->pdin, bs);		if (e) goto exit;	}	e = DoInterleave(mw, writers, bs, 1, (u32) gf_bs_get_position(bs), drift_inter);	if (e) goto exit;	firstSize = GetMoovAndMetaSize(movie, writers);	offset = firstSize;	if (movie->mdat && movie->mdat->dataSize) offset += 8 + (movie->mdat->dataSize > 0xFFFFFFFF ? 8 : 0);	e = ShiftOffset(movie, writers, offset);	if (e) goto exit;	//get the size and see if it has changed (eg, we moved to 64 bit offsets)	finalSize = GetMoovAndMetaSize(movie, writers);	if (firstSize != finalSize) {		//we need to remove our offsets		ResetWriters(writers);		finalOffset = finalSize;		if (movie->mdat->dataSize) finalOffset += 8 + (movie->mdat->dataSize > 0xFFFFFFFF ? 8 : 0);		//OK, now we're sure about the final size -> shift the offsets		//we don't need to re-emulate, as the only thing that changed is the offset		//so just shift the offset		e = ShiftOffset(movie, writers, finalOffset - offset);		if (e) goto exit;	}	//now write our stuff	e = WriteMoovAndMeta(movie, writers, bs);	if (e) goto exit;	/*we have 8 extra bytes for large size (not computed in gf_isom_box_size) */	if (movie->mdat && movie->mdat->dataSize) {		if (movie->mdat->dataSize > 0xFFFFFFFF) movie->mdat->dataSize += 8;		e = gf_isom_box_size((GF_Box *)movie->mdat);		if (e) goto exit;		e = gf_isom_box_write((GF_Box *)movie->mdat, bs);		if (e) goto exit;	}	//we don't need the offset as we are writing...	ResetWriters(writers);	e = DoInterleave(mw, writers, bs, 0, 0, drift_inter);	if (e) goto exit;	//then the rest	i=0;	while ((a = (GF_Box*)gf_list_enum(movie->TopBoxes, &i))) {		switch (a->type) {		case GF_ISOM_BOX_TYPE_MOOV:		case GF_ISOM_BOX_TYPE_META:		case GF_ISOM_BOX_TYPE_FTYP:		case GF_ISOM_BOX_TYPE_PDIN:		case GF_ISOM_BOX_TYPE_MDAT:			break;		default:			e = gf_isom_box_size(a);			if (e) goto exit;			e = gf_isom_box_write(a, bs);			if (e) goto exit;		}	}exit:	CleanWriters(writers);	gf_list_del(writers);	return e;}GF_Err WriteToFile(GF_ISOFile *movie){	FILE *stream;	GF_BitStream *bs;	MovieWriter mw;	GF_Err e = GF_OK;	if (!movie) return GF_BAD_PARAM;	if (movie->openMode == GF_ISOM_OPEN_READ) return GF_BAD_PARAM;	e = gf_isom_insert_copyright(movie);	if (e) return e;	memset(&mw, 0, sizeof(mw));	mw.movie = movie;	//capture mode: we don't need a new bitstream	if (movie->openMode == GF_ISOM_OPEN_WRITE) {		e = WriteFlat(&mw, 0, movie->editFileMap->bs);	} else {		//OK, we need a new bitstream		stream = gf_f64_open(movie->finalName, "w+b");		if (!stream) return GF_IO_ERR;		bs = gf_bs_from_file(stream, GF_BITSTREAM_WRITE);		if (!bs) {			fclose(stream);			return GF_OUT_OF_MEM;		}		switch (movie->storageMode) {		case GF_ISOM_STORE_TIGHT:		case GF_ISOM_STORE_INTERLEAVED:			e = WriteInterleaved(&mw, bs, 0);			break;		case GF_ISOM_STORE_DRIFT_INTERLEAVED:			e = WriteInterleaved(&mw, bs, 1);			break;		case GF_ISOM_STORE_STREAMABLE:			e = WriteFlat(&mw, 1, bs);			break;		default:			e = WriteFlat(&mw, 0, bs);			break;		}				gf_bs_del(bs);		fclose(stream);	}	if (mw.buffer) free(mw.buffer);	if (mw.nb_done<mw.total_samples) {		gf_set_progress("ISO File Writing", mw.total_samples, mw.total_samples);	}	return e;}#endif	//GPAC_READ_ONLY

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -