示例#1
0
//Get the total media duration based on the TimeToSample table
M4Err Media_SetDuration(TrackAtom *trak)
{
	ESDescriptor *esd;
	u32 DTS, DTSprev;
	u32 nbSamp = trak->Media->information->sampleTable->SampleSize->sampleCount;

	//we need to check how many samples we have. 
	// == 1 -> last sample duration == default duration
	// > 1 -> last sample duration == prev sample duration
	switch (nbSamp) {
	case 0:
		trak->Media->mediaHeader->duration = 0;
		//we have an URL stream, set duration to its max
		if (!Track_IsMPEG4Stream(trak->Media->handler->handlerType)) {
			Media_GetESD(trak->Media, 1, &esd, 1);
			if (esd && esd->URLString) trak->Media->mediaHeader->duration = -1;
		}
		return M4OK;

	case 1:
		trak->Media->mediaHeader->duration = trak->Media->mediaHeader->timeScale;
		return M4OK;

	default:
		//we assume a constant frame rate for the media and assume the last sample
		//will be hold the same time as the prev one
		stbl_GetSampleDTS(trak->Media->information->sampleTable->TimeToSample, nbSamp, &DTS);
		stbl_GetSampleDTS(trak->Media->information->sampleTable->TimeToSample, nbSamp-1, &DTSprev);
		trak->Media->mediaHeader->duration = DTS + (DTS - DTSprev);
		return M4OK;
	}
}
示例#2
0
GF_Err Track_SetStreamDescriptor(GF_TrackBox *trak, u32 StreamDescriptionIndex, u32 DataReferenceIndex, GF_ESD *esd, u32 *outStreamIndex)
{
    GF_Err e;
    GF_MPEGSampleEntryBox *entry;
    GF_MPEGVisualSampleEntryBox *entry_v;
    GF_MPEGAudioSampleEntryBox *entry_a;
    GF_TrackReferenceBox *tref;
    GF_TrackReferenceTypeBox *dpnd;
    u16 tmpRef;

    entry = NULL;
    tref = NULL;

    if (!trak || !esd || (!outStreamIndex && !DataReferenceIndex) ) return GF_BAD_PARAM;
    if (!Track_IsMPEG4Stream(trak->Media->handler->handlerType)) return GF_ISOM_INVALID_MEDIA;


    esd->ESID = 0;
    //set SL to predefined if no url
    if (esd->URLString == NULL) {
        if (!esd->slConfig) esd->slConfig = (GF_SLConfig*) gf_odf_desc_new(GF_ODF_SLC_TAG);
        esd->slConfig->predefined = SLPredef_MP4;
        esd->slConfig->durationFlag = 0;
        esd->slConfig->useTimestampsFlag = 1;
    }

    //get the REF box if needed
    if (esd->dependsOnESID  || esd->OCRESID ) {
        if (!trak->References) {
            tref = (GF_TrackReferenceBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TREF);
            e = trak_AddBox((GF_Box*)trak, (GF_Box *)tref);
            if (e) return e;
        }
        tref = trak->References;
    }

    //Update Stream dependancies
    e = Track_FindRef(trak, GF_ISOM_REF_DECODE, &dpnd);
    if (e) return e;
    if (!dpnd && esd->dependsOnESID) {
        dpnd = (GF_TrackReferenceTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_REFT);
        dpnd->reference_type = GF_ISOM_BOX_TYPE_DPND;
        e = tref_AddBox((GF_Box*)tref, (GF_Box *) dpnd);
        if (e) return e;
        e = reftype_AddRefTrack(dpnd, esd->dependsOnESID, NULL);
        if (e) return e;
    } else if (dpnd && !esd->dependsOnESID) {
        Track_RemoveRef(trak, GF_ISOM_BOX_TYPE_DPND);
    }
    esd->dependsOnESID = 0;

    //Update GF_Clock dependancies
    e = Track_FindRef(trak, GF_ISOM_REF_OCR, &dpnd);
    if (e) return e;
    if (!dpnd && esd->OCRESID) {
        dpnd = (GF_TrackReferenceTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_REFT);
        dpnd->reference_type = GF_ISOM_BOX_TYPE_SYNC;
        e = tref_AddBox((GF_Box*)tref, (GF_Box *) dpnd);
        if (e) return e;
        e = reftype_AddRefTrack(dpnd, esd->OCRESID, NULL);
        if (e) return e;
    } else if (dpnd && !esd->OCRESID) {
        Track_RemoveRef(trak, GF_ISOM_BOX_TYPE_SYNC);
    } else if (dpnd && esd->OCRESID) {
        if (dpnd->trackIDCount != 1) return GF_ISOM_INVALID_MEDIA;
        dpnd->trackIDs[0] = esd->OCRESID;
    }
    esd->OCRESID = 0;

    //brand new case: we have to change the IPI desc
    if (esd->ipiPtr) {
        e = Track_FindRef(trak, GF_ISOM_REF_IPI, &dpnd);
        if (e) return e;
        if (!dpnd) {
            tmpRef = 0;
            dpnd = (GF_TrackReferenceTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_REFT);
            dpnd->reference_type = GF_ISOM_BOX_TYPE_IPIR;
            e = tref_AddBox((GF_Box*)tref, (GF_Box *) dpnd);
            if (e) return e;
            e = reftype_AddRefTrack(dpnd, esd->ipiPtr->IPI_ES_Id, &tmpRef);
            if (e) return e;
            //and replace the tag and value...
            esd->ipiPtr->IPI_ES_Id = tmpRef;
            esd->ipiPtr->tag = GF_ODF_ISOM_IPI_PTR_TAG;
        } else {
            //Watch out! ONLY ONE IPI dependancy is allowed per stream
            if (dpnd->trackIDCount != 1) return GF_ISOM_INVALID_MEDIA;
            //if an existing one is there, what shall we do ???
            //donno, erase it
            dpnd->trackIDs[0] = esd->ipiPtr->IPI_ES_Id;
            //and replace the tag and value...
            esd->ipiPtr->IPI_ES_Id = 1;
            esd->ipiPtr->tag = GF_ODF_ISOM_IPI_PTR_TAG;
        }
    }

    /*don't store the lang desc in ESD, use the media header language info*/
    if (esd->langDesc) {
        trak->Media->mediaHeader->packedLanguage[0] = (esd->langDesc->langCode>>16)&0xFF;
        trak->Media->mediaHeader->packedLanguage[1] = (esd->langDesc->langCode>>8)&0xFF;
        trak->Media->mediaHeader->packedLanguage[2] = (esd->langDesc->langCode)&0xFF;
        gf_odf_desc_del((GF_Descriptor *)esd->langDesc);
        esd->langDesc = NULL;
    }
示例#3
0
//Get the total media duration based on the TimeToSample table
GF_Err Media_SetDuration(GF_TrackBox *trak)
{
	GF_ESD *esd;
	u64 DTS;
	GF_SttsEntry *ent;
	u32 nbSamp = trak->Media->information->sampleTable->SampleSize->sampleCount;

	//we need to check how many samples we have. 
	// == 1 -> last sample duration == default duration
	// > 1 -> last sample duration == prev sample duration
	switch (nbSamp) {
	case 0:
		trak->Media->mediaHeader->duration = 0;
		if (Track_IsMPEG4Stream(trak->Media->handler->handlerType)) {
			Media_GetESD(trak->Media, 1, &esd, 1);
			if (esd && esd->URLString) trak->Media->mediaHeader->duration = (u64) -1;
		}
		return GF_OK;

//	case 1:
//		trak->Media->mediaHeader->duration = trak->Media->mediaHeader->timeScale;
//		return GF_OK;

	default:
		//we assume a constant frame rate for the media and assume the last sample
		//will be hold the same time as the prev one
		stbl_GetSampleDTS(trak->Media->information->sampleTable->TimeToSample, nbSamp, &DTS);
		ent = &trak->Media->information->sampleTable->TimeToSample->entries[trak->Media->information->sampleTable->TimeToSample->nb_entries-1];
		trak->Media->mediaHeader->duration = DTS;

#if 1
		trak->Media->mediaHeader->duration += ent->sampleDelta;
#else
		if (!ent) {
			u64 DTSprev;
			stbl_GetSampleDTS(trak->Media->information->sampleTable->TimeToSample, nbSamp-1, &DTSprev);
			trak->Media->mediaHeader->duration += (DTS - DTSprev);
		} else {
#ifndef GPAC_DISABLE_ISOM_WRITE
			if (trak->moov->mov->editFileMap && trak->Media->information->sampleTable->CompositionOffset) {
				u32 count, i;
				u64 max_ts;
				GF_DttsEntry *cts_ent;
				GF_CompositionOffsetBox *ctts = trak->Media->information->sampleTable->CompositionOffset;
				if (ctts->w_LastSampleNumber==nbSamp) {
					count = gf_list_count(ctts->entryList);
					max_ts = trak->Media->mediaHeader->duration;
					while (count) {
						count -= 1;
						cts_ent = gf_list_get(ctts->entryList, count);
						if (nbSamp<cts_ent->sampleCount) break;

						for (i=0; i<cts_ent->sampleCount; i++) {
							stbl_GetSampleDTS(trak->Media->information->sampleTable->TimeToSample, nbSamp-i, &DTS);
							if ((s32) cts_ent->decodingOffset < 0) max_ts = DTS;
							else max_ts = DTS + cts_ent->decodingOffset;
							if (max_ts>=trak->Media->mediaHeader->duration) {
								trak->Media->mediaHeader->duration = max_ts;
							} else {
								break;
							}
						}
						if (max_ts<trak->Media->mediaHeader->duration) {
							break;
						}
						nbSamp-=cts_ent->sampleCount;
					}
				}
			}
#endif /*GPAC_DISABLE_ISOM_WRITE*/
			trak->Media->mediaHeader->duration += ent->sampleDelta;
		}
#endif
		return GF_OK;
	}
}
示例#4
0
M4Err Track_SetStreamDescriptor(TrackAtom *trak, u32 StreamDescriptionIndex, u32 DataReferenceIndex, ESDescriptor *esd, u32 *outStreamIndex)
{
	M4Err e;
	MPEGSampleEntryAtom *entry;
	MPEGVisualSampleEntryAtom *entry_v;
	MPEGAudioSampleEntryAtom *entry_a;
	TrackReferenceAtom *tref;
	TrackReferenceTypeAtom *dpnd;
	u16 tmpRef;

	M4Err reftype_AddRefTrack(TrackReferenceTypeAtom *ref, u32 trackID, u16 *outRefIndex);
	M4Err tref_AddAtom(TrackReferenceAtom *ptr, Atom *a);
	M4Err stsd_AddAtom(SampleDescriptionAtom *ptr, Atom *a);
	M4Err trak_AddAtom(TrackAtom *ptr, Atom *a);

	entry = NULL;
	tref = NULL;

	if (!trak || !esd || (!outStreamIndex && !DataReferenceIndex) ) return M4BadParam;
	if (!Track_IsMPEG4Stream(trak->Media->handler->handlerType)) return M4InvalidMP4Media;

	
	esd->ESID = 0;
	//set SL to predefined if no url
	if (esd->URLString == NULL) {
		esd->slConfig->predefined = SLPredef_MP4;
		esd->slConfig->durationFlag = 0;
		esd->slConfig->useTimestampsFlag = 1;
	}

	//get the REF atom if needed
	if (esd->dependsOnESID  || esd->OCRESID ) {
		if (!trak->References) {
			tref = (TrackReferenceAtom *) CreateAtom(TrackReferenceAtomType);
			e = trak_AddAtom(trak, (Atom *)tref);
			if (e) return e;
		}
		tref = trak->References;
	}

	//Update Stream dependancies
	e = Track_FindRef(trak, M4_StreamDependence_Ref, &dpnd);
	if (e) return e;
	if (!dpnd && esd->dependsOnESID) {
		dpnd = (TrackReferenceTypeAtom *) CreateAtom(StreamDependenceAtomType);
		e = tref_AddAtom(tref, (Atom *) dpnd);
		if (e) return e;
		e = reftype_AddRefTrack(dpnd, esd->dependsOnESID, NULL);
		if (e) return e;
	} else if (dpnd && !esd->dependsOnESID) {
		Track_RemoveRef(trak, StreamDependenceAtomType);
	}
	esd->dependsOnESID = 0;

	//Update Clock dependancies
	e = Track_FindRef(trak, M4_OCR_Ref, &dpnd);
	if (e) return e;
	if (!dpnd && esd->OCRESID) {
		dpnd = (TrackReferenceTypeAtom *) CreateAtom(OCRReferenceAtomType);
		e = tref_AddAtom(tref, (Atom *) dpnd);
		if (e) return e;
		e = reftype_AddRefTrack(dpnd, esd->OCRESID, NULL);
		if (e) return e;
	} else if (dpnd && !esd->OCRESID) {
		Track_RemoveRef(trak, OCRReferenceAtomType);
	} else if (dpnd && esd->OCRESID) {
		if (dpnd->trackIDCount != 1) return M4InvalidMP4Media;
		dpnd->trackIDs[0] = esd->OCRESID;
	}
	esd->OCRESID = 0;

	//brand new case: we have to change the IPI desc
	if (esd->ipiPtr) {
		e = Track_FindRef(trak, M4_IPI_Ref, &dpnd);
		if (e) return e;
		if (!dpnd) {
			tmpRef = 0;
			dpnd = (TrackReferenceTypeAtom *) CreateAtom(IPIReferenceAtomType);
			e = tref_AddAtom(tref, (Atom *) dpnd);
			if (e) return e;
			e = reftype_AddRefTrack(dpnd, esd->ipiPtr->IPI_ES_Id, &tmpRef);
			if (e) return e;
			//and replace the tag and value...
			esd->ipiPtr->IPI_ES_Id = tmpRef;
			esd->ipiPtr->tag = IPI_DescPtr_Tag;
		} else {
			//Watch out! ONLY ONE IPI dependancy is allowed per stream
			if (dpnd->trackIDCount != 1) return M4InvalidMP4Media;
			//if an existing one is there, what shall we do ???
			//donno, erase it
			dpnd->trackIDs[0] = esd->ipiPtr->IPI_ES_Id;
			//and replace the tag and value...
			esd->ipiPtr->IPI_ES_Id = 1;
			esd->ipiPtr->tag = IPI_DescPtr_Tag;
		}
	}

	//we have a streamDescritpionIndex, use it
	if (StreamDescriptionIndex) {
		entry = (MPEGSampleEntryAtom*)ChainGetEntry(trak->Media->information->sampleTable->SampleDescription->atomList, StreamDescriptionIndex - 1);
		if (!entry) return M4InvalidMP4File;

		switch (entry->type) {
		case MPEGSampleEntryAtomType:
			//OK, delete the previous ESD
			e = OD_DeleteDescriptor((Descriptor **) &entry->esd->desc);
			if (e) return e;
			entry->esd->desc = esd;
			break;
		case MPEGVisualSampleEntryAtomType:
			entry_v = (MPEGVisualSampleEntryAtom*) entry;
			//OK, delete the previous ESD
			e = OD_DeleteDescriptor((Descriptor **) &entry_v->esd->desc);
			if (e) return e;
			entry_v->esd->desc = esd;
			break;
		case MPEGAudioSampleEntryAtomType:
			entry_a = (MPEGAudioSampleEntryAtom*) entry;
			//OK, delete the previous ESD
			e = OD_DeleteDescriptor((Descriptor **) &entry_a->esd->desc);
			if (e) return e;
			entry_a->esd->desc = esd;
			break;
		}
	} else {
		//need to check we're not in URL mode where only ONE description is allowed...
		StreamDescriptionIndex = ChainGetCount(trak->Media->information->sampleTable->SampleDescription->atomList);
		if (StreamDescriptionIndex) {
			entry = (MPEGSampleEntryAtom*)ChainGetEntry(trak->Media->information->sampleTable->SampleDescription->atomList, StreamDescriptionIndex - 1);
			if (!entry) return M4InvalidMP4File;
			if (entry->esd->desc->URLString) return M4BadParam;
		}

		//OK, check the handler and create the entry
		switch (trak->Media->handler->handlerType) {
		case M4_VisualMediaType:
			entry_v = (MPEGVisualSampleEntryAtom *) CreateAtom(MPEGVisualSampleEntryAtomType);
			if (!entry_v) return M4OutOfMem;
			//create an esdAtom
			entry_v->esd = (ESDAtom *) CreateAtom(ESDAtomType);
			entry_v->esd->desc = esd;

			//type cast possible now
			entry = (MPEGSampleEntryAtom*) entry_v;
			break;
		case M4_AudioMediaType:
			entry_a = (MPEGAudioSampleEntryAtom *) CreateAtom(MPEGAudioSampleEntryAtomType);
			entry_a->samplerate_hi = trak->Media->mediaHeader->timeScale;
			if (!entry_a) return M4OutOfMem;
			//create an esdAtom
			entry_a->esd = (ESDAtom *) CreateAtom(ESDAtomType);
			entry_a->esd->desc = esd;
			//type cast possible now
			entry = (MPEGSampleEntryAtom*) entry_a;
			break;
		case M4_ODMediaType:
		case M4_OCRMediaType:
		case M4_BIFSMediaType:
		case M4_MPEG7MediaType:
		case M4_OCIMediaType:
		case M4_IPMPMediaType:
		case M4_MPEGJMediaType:
			entry = (MPEGSampleEntryAtom *) CreateAtom(MPEGSampleEntryAtomType);
			//create an esdAtom
			entry->esd = (ESDAtom *) CreateAtom(ESDAtomType);
			entry->esd->desc = esd;
			break;
		}
		entry->dataReferenceIndex = DataReferenceIndex;

		//and add the entry to our table...
		e = stsd_AddAtom(trak->Media->information->sampleTable->SampleDescription, (Atom *) entry);
		if (e) return e;
		if(outStreamIndex) *outStreamIndex = ChainGetCount(trak->Media->information->sampleTable->SampleDescription->atomList);
	}
	return M4OK;
}