Ejemplo n.º 1
0
M4Err M4H_AddStreamDescriptionData(M4File *the_file, u32 trackNumber, u32 SourceTrackID, u32 StreamDescriptionIndex, u16 DataLength, u32 offsetInDescription, u8 AtBegin)
{
	TrackAtom *trak;
	HintSampleEntryAtom *entry;
	u32 count;
	u16 refIndex;
	HintPacket *pck;
	StreamDescDTE *dte;
	M4Err e;
	TrackReferenceTypeAtom *hint;

	M4Err reftype_AddRefTrack(TrackReferenceTypeAtom *ref, u32 trackID, u16 *outRefIndex);

	trak = GetTrackFromFile(the_file, trackNumber);
	if (!trak || !IsHintTrack(trak)) return M4BadParam;

	e = Media_GetSampleDesc(trak->Media, trak->Media->information->sampleTable->currentEntryIndex, (SampleEntryAtom **) &entry, &count);
	if (e) return e;
	if (!entry->w_sample) return M4BadParam;
	count = ChainGetCount(entry->w_sample->packetTable);
	if (!count) return M4BadParam;
	pck = ChainGetEntry(entry->w_sample->packetTable, count - 1);

	dte = (StreamDescDTE *) NewDTE(3);
	dte->byteOffset = offsetInDescription;
	dte->dataLength = DataLength;
	dte->streamDescIndex = StreamDescriptionIndex;
	if (SourceTrackID == trak->Header->trackID) {
		dte->trackRefIndex = -1;
	} else {
		//get (or set) the track reference index 
		e = Track_FindRef(trak, M4_HintTrack_Ref, &hint);
		if (e) return e;
		e = reftype_AddRefTrack(hint, SourceTrackID, &refIndex);
		if (e) return e;
		//WARNING: IN QT, MUST BE 0-based !!!
		dte->trackRefIndex = (u8) (refIndex - 1);
	}
	return AddDTE_HintPacket(entry->w_sample->HintType, pck, (GenericDTE *)dte, AtBegin);
}
Ejemplo n.º 2
0
GF_Err gf_isom_hint_sample_description_data(GF_ISOFile *the_file, u32 trackNumber, u32 SourceTrackID, u32 StreamDescriptionIndex, u16 DataLength, u32 offsetInDescription, u8 AtBegin)
{
	GF_TrackBox *trak;
	GF_HintSampleEntryBox *entry;
	u32 count;
	u16 refIndex;
	GF_HintPacket *pck;
	GF_StreamDescDTE *dte;
	GF_Err e;
	GF_TrackReferenceTypeBox *hint;

	trak = gf_isom_get_track_from_file(the_file, trackNumber);
	if (!trak || !IsHintTrack(trak)) return GF_BAD_PARAM;

	e = Media_GetSampleDesc(trak->Media, trak->Media->information->sampleTable->currentEntryIndex, (GF_SampleEntryBox **) &entry, &count);
	if (e) return e;
	if (!entry->hint_sample) return GF_BAD_PARAM;
	count = gf_list_count(entry->hint_sample->packetTable);
	if (!count) return GF_BAD_PARAM;
	pck = (GF_HintPacket *)gf_list_get(entry->hint_sample->packetTable, count - 1);

	dte = (GF_StreamDescDTE *) NewDTE(3);
	dte->byteOffset = offsetInDescription;
	dte->dataLength = DataLength;
	dte->streamDescIndex = StreamDescriptionIndex;
	if (SourceTrackID == trak->Header->trackID) {
		dte->trackRefIndex = (s8) -1;
	} else {
		//get (or set) the track reference index 
		e = Track_FindRef(trak, GF_ISOM_REF_HINT, &hint);
		if (e) return e;
		e = reftype_AddRefTrack(hint, SourceTrackID, &refIndex);
		if (e) return e;
		//WARNING: IN QT, MUST BE 0-based !!!
		dte->trackRefIndex = (u8) (refIndex - 1);
	}
	return gf_isom_hint_pck_add_dte(entry->hint_sample->HintType, pck, (GF_GenericDTE *)dte, AtBegin);
}
Ejemplo n.º 3
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;
    }
Ejemplo n.º 4
0
GF_Err gf_isom_hint_sample_data(GF_ISOFile *the_file, u32 trackNumber, u32 SourceTrackID, u32 SampleNumber, u16 DataLength, u32 offsetInSample, char *extra_data, u8 AtBegin)
{
	GF_TrackBox *trak;
	GF_HintSampleEntryBox *entry;
	u32 count;
	u16 refIndex;
	GF_HintPacket *pck;
	GF_SampleDTE *dte;
	GF_Err e;
	GF_TrackReferenceTypeBox *hint;

	trak = gf_isom_get_track_from_file(the_file, trackNumber);
	if (!trak || !IsHintTrack(trak)) return GF_BAD_PARAM;


	e = Media_GetSampleDesc(trak->Media, trak->Media->information->sampleTable->currentEntryIndex, (GF_SampleEntryBox **) &entry, &count);
	if (e) return e;
	if (!entry->hint_sample) return GF_BAD_PARAM;
	count = gf_list_count(entry->hint_sample->packetTable);
	if (!count) return GF_BAD_PARAM;
	pck = (GF_HintPacket *)gf_list_get(entry->hint_sample->packetTable, count - 1);

	dte = (GF_SampleDTE *) NewDTE(2);

	dte->dataLength = DataLength;
	dte->sampleNumber = SampleNumber;
	dte->byteOffset = offsetInSample;

	//we're getting data from another track
	if (SourceTrackID != trak->Header->trackID) {
		//get (or set) the track reference index 
		e = Track_FindRef(trak, GF_ISOM_REF_HINT, &hint);
		if (e) return e;
		e = reftype_AddRefTrack(hint, SourceTrackID, &refIndex);
		if (e) return e;
		//WARNING: IN QT, MUST BE 0-based !!!
		dte->trackRefIndex = (u8) (refIndex - 1);
	} else {
		//we're in the hint track
		dte->trackRefIndex = (s8) -1;
		//basic check...
		if (SampleNumber > trak->Media->information->sampleTable->SampleSize->sampleCount + 1) {
			DelDTE((GF_GenericDTE *)dte);
			return GF_BAD_PARAM;
		}

		//are we in the current sample ??
		if (!SampleNumber || (SampleNumber == trak->Media->information->sampleTable->SampleSize->sampleCount + 1)) {
			//we adding some stuff in the current sample ...
			dte->byteOffset += entry->hint_sample->dataLength;
			entry->hint_sample->AdditionalData = (char*)gf_realloc(entry->hint_sample->AdditionalData, sizeof(char) * (entry->hint_sample->dataLength + DataLength));
			if (AtBegin) {
				if (entry->hint_sample->dataLength)
					memmove(entry->hint_sample->AdditionalData + DataLength, entry->hint_sample->AdditionalData, entry->hint_sample->dataLength);
				memcpy(entry->hint_sample->AdditionalData, extra_data, DataLength);
				/*offset existing DTE*/
				gf_isom_hint_pck_offset(entry->hint_sample->HintType, pck, DataLength, SampleNumber);
			} else {
				memcpy(entry->hint_sample->AdditionalData + entry->hint_sample->dataLength, extra_data, DataLength);
			}
			entry->hint_sample->dataLength += DataLength;
			//and set the sample number ...
			dte->sampleNumber = trak->Media->information->sampleTable->SampleSize->sampleCount + 1;
		}
	}
	//OK, add the entry
	return gf_isom_hint_pck_add_dte(entry->hint_sample->HintType, pck, (GF_GenericDTE *)dte, AtBegin);
}
Ejemplo n.º 5
0
// Update the dependancies when an OD AU is inserted in the file
GF_Err Media_ParseODFrame(GF_MediaBox *mdia, GF_ISOSample *sample, GF_ISOSample **od_samp)
{
	GF_TrackReferenceBox *tref;
	GF_TrackReferenceTypeBox *mpod;
	GF_Err e;
	GF_ODCom *com;
	GF_ODCodec *ODencode;
	GF_ODCodec *ODdecode;
	u32 i, j;
	//the commands we proceed
	GF_ESDUpdate *esdU, *esdU2;
	GF_ESDRemove *esdR, *esdR2;
	GF_ODUpdate *odU, *odU2;

	//the desc they contain
	GF_ObjectDescriptor *od;
	GF_IsomObjectDescriptor *isom_od;
	GF_ESD *esd;
	GF_ES_ID_Ref *ref;
	GF_Descriptor *desc;

	*od_samp = NULL;
	if (!mdia || !sample || !sample->data || !sample->dataLength) return GF_BAD_PARAM;

	//First find the references, and create them if none
	tref = mdia->mediaTrack->References;
	if (!tref) {
		tref = (GF_TrackReferenceBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TREF);
		e = trak_AddBox((GF_Box*)mdia->mediaTrack, (GF_Box *) tref);
		if (e) return e;
	}
	//then find the OD reference, and create it if none
	e = Track_FindRef(mdia->mediaTrack, GF_ISOM_BOX_TYPE_MPOD, &mpod);
	if (e) return e;
	if (!mpod) {
		mpod = (GF_TrackReferenceTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_REFT);
		mpod->reference_type = GF_ISOM_BOX_TYPE_MPOD;
		e = tref_AddBox((GF_Box*)tref, (GF_Box *)mpod);
		if (e) return e;
	}

	//OK, create our codecs
	ODencode = gf_odf_codec_new();
	if (!ODencode) return GF_OUT_OF_MEM;
	ODdecode = gf_odf_codec_new();
	if (!ODdecode) return GF_OUT_OF_MEM;

	e = gf_odf_codec_set_au(ODdecode, sample->data, sample->dataLength);
	if (e) goto err_exit;
	e = gf_odf_codec_decode(ODdecode);
	if (e) goto err_exit;

	while (1) {
		com = gf_odf_codec_get_com(ODdecode);
		if (!com) break;

		//check our commands
		switch (com->tag) {
		//Rewrite OD Update
		case GF_ODF_OD_UPDATE_TAG:
			//duplicate our command
			odU = (GF_ODUpdate *) com;
			odU2 = (GF_ODUpdate *) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG);

			i=0;
			while ((desc = (GF_Descriptor*)gf_list_enum(odU->objectDescriptors, &i))) {
				//both OD and IODs are accepted
				switch (desc->tag) {
				case GF_ODF_OD_TAG:
				case GF_ODF_IOD_TAG:
					break;
				default:
					e = GF_ODF_INVALID_DESCRIPTOR;
					goto err_exit;
				}
				//get the esd
				e = gf_odf_desc_copy(desc, (GF_Descriptor **)&od);
				if (e) goto err_exit;
				if (desc->tag == GF_ODF_OD_TAG) {
					isom_od = (GF_IsomObjectDescriptor *) gf_malloc(sizeof(GF_IsomObjectDescriptor));
					isom_od->tag = GF_ODF_ISOM_OD_TAG;
				} else {
					isom_od = (GF_IsomObjectDescriptor *) gf_malloc(sizeof(GF_IsomInitialObjectDescriptor));
					isom_od->tag = GF_ODF_ISOM_IOD_TAG;
					//copy PL
					((GF_IsomInitialObjectDescriptor *)isom_od)->inlineProfileFlag = ((GF_InitialObjectDescriptor *)od)->inlineProfileFlag;
					((GF_IsomInitialObjectDescriptor *)isom_od)->graphics_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->graphics_profileAndLevel;
					((GF_IsomInitialObjectDescriptor *)isom_od)->audio_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->audio_profileAndLevel;
					((GF_IsomInitialObjectDescriptor *)isom_od)->OD_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->OD_profileAndLevel;
					((GF_IsomInitialObjectDescriptor *)isom_od)->scene_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->scene_profileAndLevel;
					((GF_IsomInitialObjectDescriptor *)isom_od)->visual_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->visual_profileAndLevel;
					((GF_IsomInitialObjectDescriptor *)isom_od)->IPMPToolList = ((GF_InitialObjectDescriptor *)od)->IPMPToolList;
					((GF_InitialObjectDescriptor *)od)->IPMPToolList = NULL;
				}
				//in OD stream only ref desc are accepted
				isom_od->ES_ID_RefDescriptors = gf_list_new();
				isom_od->ES_ID_IncDescriptors = NULL;
	
				//TO DO: check that a given sampleDescription exists
				isom_od->extensionDescriptors = od->extensionDescriptors;
				od->extensionDescriptors = NULL;
				isom_od->IPMP_Descriptors = od->IPMP_Descriptors;
				od->IPMP_Descriptors = NULL;
				isom_od->OCIDescriptors = od->OCIDescriptors;
				od->OCIDescriptors = NULL;
				isom_od->URLString = od->URLString;
				od->URLString = NULL;
				isom_od->objectDescriptorID = od->objectDescriptorID;

				j=0;
				while ((esd = (GF_ESD*)gf_list_enum(od->ESDescriptors, &j))) {
					ref = (GF_ES_ID_Ref *) gf_odf_desc_new(GF_ODF_ESD_REF_TAG);
					//1 to 1 mapping trackID and ESID. Add this track to MPOD
					//if track does not exist, this will be remove while reading the OD stream
					e = reftype_AddRefTrack(mpod, esd->ESID, &ref->trackRef);
					e = gf_odf_desc_add_desc((GF_Descriptor *)isom_od, (GF_Descriptor *)ref);
					if (e) goto err_exit;
				}
				//delete our desc
				gf_odf_desc_del((GF_Descriptor *)od);
				//and add the new one to our command
				gf_list_add(odU2->objectDescriptors, isom_od);
			}
			//delete the command
			gf_odf_com_del((GF_ODCom **)&odU);
			//and add the new one to the codec
			gf_odf_codec_add_com(ODencode, (GF_ODCom *)odU2);
			break;

		//Rewrite ESD Update
		case GF_ODF_ESD_UPDATE_TAG:
			esdU = (GF_ESDUpdate *) com;
			esdU2 = (GF_ESDUpdate *) gf_odf_com_new(GF_ODF_ESD_UPDATE_TAG);
			esdU2->ODID = esdU->ODID;
			i=0;
			while ((esd = (GF_ESD*)gf_list_enum(esdU->ESDescriptors, &i))) {
				ref = (GF_ES_ID_Ref *) gf_odf_desc_new(GF_ODF_ESD_REF_TAG);
				//1 to 1 mapping trackID and ESID
				e = reftype_AddRefTrack(mpod, esd->ESID, &ref->trackRef);
				e = gf_list_add(esdU2->ESDescriptors, ref);
				if (e) goto err_exit;
			}
			gf_odf_com_del((GF_ODCom **)&esdU);
			gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdU2);
			break;

		//Brand new case: the ESRemove has to be rewritten too according to the specs...
		case GF_ODF_ESD_REMOVE_TAG:
			esdR = (GF_ESDRemove *) com;
			esdR2 = (GF_ESDRemove *) gf_odf_com_new(GF_ODF_ESD_REMOVE_TAG);
			//change the tag for the file format
			esdR2->tag = GF_ODF_ESD_REMOVE_REF_TAG;
			esdR2->ODID = esdR->ODID;
			esdR2->NbESDs = esdR->NbESDs;
			if (esdR->NbESDs) {
				//alloc our stuff
				esdR2->ES_ID = (unsigned short*)gf_malloc(sizeof(u32) * esdR->NbESDs);
				if (!esdR2->ES_ID) {
					e = GF_OUT_OF_MEM;
					goto err_exit;
				}
				for (i = 0; i < esdR->NbESDs; i++) {
					//1 to 1 mapping trackID and ESID
					e = reftype_AddRefTrack(mpod, esdR->ES_ID[i], &esdR2->ES_ID[i]);
					if (e) goto err_exit;
				}
			}
			gf_odf_com_del(&com);
			gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdR2);
			break;

		//Add the command as is
		default:
			e = gf_odf_codec_add_com(ODencode, com);
			if (e) goto err_exit;
		}
	}

	//encode our new AU
	e = gf_odf_codec_encode(ODencode, 1);
	if (e) goto err_exit;

	//and set the buffer in the sample
	*od_samp = gf_isom_sample_new();
	(*od_samp)->CTS_Offset = sample->CTS_Offset;
	(*od_samp)->DTS = sample->DTS;
	(*od_samp)->IsRAP = sample->IsRAP;
	e = gf_odf_codec_get_au(ODencode, & (*od_samp)->data, & (*od_samp)->dataLength);
	if (e) {
		gf_isom_sample_del(od_samp);
		*od_samp = NULL;
	}

err_exit:

	gf_odf_codec_del(ODencode);
	gf_odf_codec_del(ODdecode);
	return e;
}
Ejemplo n.º 6
0
// Update the dependancies when an OD AU is inserted in the file
M4Err Media_ParseODFrame(MediaAtom *mdia, M4Sample *sample)
{
	TrackReferenceAtom *tref;
	TrackReferenceTypeAtom *mpod;
	M4Err e;
	ODCommand *com;
	LPODCODEC ODencode;
	LPODCODEC ODdecode;
	u32 i, j;

	//the commands we proceed
	ESDescriptorUpdate *esdU, *esdU2;
	ESDescriptorRemove *esdR, *esdR2;
	ObjectDescriptorUpdate *odU, *odU2;

	//the desc they contain
	ObjectDescriptor *od;
	M4F_ObjectDescriptor *m4_od;
	ESDescriptor *esd;
	ES_ID_Ref *ref;
	Descriptor *desc;
	M4Err reftype_AddRefTrack(TrackReferenceTypeAtom *ref, u32 trackID, u16 *outRefIndex);
	M4Err trak_AddAtom(TrackAtom *ptr, Atom *a);
	M4Err tref_AddAtom(TrackReferenceAtom *ptr, Atom *a);

	if (!mdia || !sample || !sample->data || !sample->dataLength) return M4BadParam;

	//First find the references, and create them if none
	tref = mdia->mediaTrack->References;
	if (!tref) {
		tref = (TrackReferenceAtom *) CreateAtom(TrackReferenceAtomType);
		e = trak_AddAtom(mdia->mediaTrack, (Atom *) tref);
		if (e) return e;
	}
	//then find the OD reference, and create it if none
	e = Track_FindRef(mdia->mediaTrack, ODTrackReferenceAtomType, &mpod);
	if (e) return e;
	if (!mpod) {
		mpod = (TrackReferenceTypeAtom *) CreateAtom(ODTrackReferenceAtomType);
		e = tref_AddAtom(tref, (Atom *)mpod);
		if (e) return e;
	}

	//OK, create our codecs
	ODencode = OD_NewCodec(OD_WRITE);
	if (!ODencode) return M4OutOfMem;
	ODdecode = OD_NewCodec(OD_READ);
	if (!ODdecode) return M4OutOfMem;

	e = OD_SetBuffer(ODdecode, sample->data, sample->dataLength);
	if (e) goto err_exit;
	e = OD_DecodeAU(ODdecode);
	if (e) goto err_exit;

	while (1) {
		com = OD_GetCommand(ODdecode);
		if (!com) break;

		//check our commands
		switch (com->tag) {
		//Rewrite OD Update
		case ODUpdate_Tag:
			//duplicate our command
			odU = (ObjectDescriptorUpdate *) com;
			odU2 = (ObjectDescriptorUpdate *) OD_NewCommand(ODUpdate_Tag);

			for (i = 0; i < ChainGetCount(odU->objectDescriptors); i++) {
				desc = (Descriptor*)ChainGetEntry(odU->objectDescriptors, i);
				//both OD and IODs are accepted
				switch (desc->tag) {
				case ObjectDescriptor_Tag:
				case InitialObjectDescriptor_Tag:
					break;
				default:
					e = M4InvalidDescriptor;
					goto err_exit;
				}
				//get the esd
				e = OD_DuplicateDescriptor(desc, (Descriptor **)&od);
				if (e) goto err_exit;
				if (desc->tag == ObjectDescriptor_Tag) {
					m4_od = (M4F_ObjectDescriptor *) malloc(sizeof(M4F_ObjectDescriptor));
					m4_od->tag = MP4_OD_Tag;
				} else {
					m4_od = (M4F_ObjectDescriptor *) malloc(sizeof(M4F_InitialObjectDescriptor));
					m4_od->tag = MP4_IOD_Tag;
					//copy PL
					((M4F_InitialObjectDescriptor *)m4_od)->inlineProfileFlag = ((InitialObjectDescriptor *)od)->inlineProfileFlag;
					((M4F_InitialObjectDescriptor *)m4_od)->graphics_profileAndLevel = ((InitialObjectDescriptor *)od)->graphics_profileAndLevel;
					((M4F_InitialObjectDescriptor *)m4_od)->audio_profileAndLevel = ((InitialObjectDescriptor *)od)->audio_profileAndLevel;
					((M4F_InitialObjectDescriptor *)m4_od)->OD_profileAndLevel = ((InitialObjectDescriptor *)od)->OD_profileAndLevel;
					((M4F_InitialObjectDescriptor *)m4_od)->scene_profileAndLevel = ((InitialObjectDescriptor *)od)->scene_profileAndLevel;
					((M4F_InitialObjectDescriptor *)m4_od)->visual_profileAndLevel = ((InitialObjectDescriptor *)od)->visual_profileAndLevel;
				}
				//in OD stream only ref desc are accepted
				m4_od->ES_ID_RefDescriptors = NewChain();
				m4_od->ES_ID_IncDescriptors = NULL;
	
				//TO DO: check that a given sampleDescription exists
				m4_od->extensionDescriptors = od->extensionDescriptors;
				od->extensionDescriptors = NULL;
				m4_od->IPMPDescriptorPointers = od->IPMPDescriptorPointers;
				od->IPMPDescriptorPointers = NULL;
				m4_od->OCIDescriptors = od->OCIDescriptors;
				od->OCIDescriptors = NULL;
				m4_od->URLString = od->URLString;
				od->URLString = NULL;
				m4_od->objectDescriptorID = od->objectDescriptorID;

				for (j = 0; j < ChainGetCount(od->ESDescriptors); j++) {
					esd =(ESDescriptor*)ChainGetEntry(od->ESDescriptors, j);
					ref = (ES_ID_Ref *) OD_NewDescriptor(ES_ID_RefTag);
					//1 to 1 mapping trackID and ESID. Add this track to MPOD
					//if track does not exist, this will be remove while reading the OD stream
					e = reftype_AddRefTrack(mpod, esd->ESID, &ref->trackRef);
					e = OD_AddDescToDesc((Descriptor *)m4_od, (Descriptor *)ref);
					if (e) goto err_exit;
				}
				//delete our desc
				OD_DeleteDescriptor((Descriptor **)&od);
				//and add the new one to our command
				ChainAddEntry(odU2->objectDescriptors, m4_od);
			}
			//delete the command
			OD_DeleteCommand((ODCommand **)&odU);
			//and add the new one to the codec
			OD_AddCommand(ODencode, (ODCommand *)odU2);
			break;

		//Rewrite ESD Update
		case ESDUpdate_Tag:
			esdU = (ESDescriptorUpdate *) com;
			esdU2 = (ESDescriptorUpdate *) OD_NewCommand(ESDUpdate_Tag);
			esdU2->ODID = esdU->ODID;
			for (i = 0; i< ChainGetCount(esdU->ESDescriptors); i++) {
				esd = (ESDescriptor*)ChainGetEntry(esdU->ESDescriptors, i);
				ref = (ES_ID_Ref *) OD_NewDescriptor(ES_ID_RefTag);
				//1 to 1 mapping trackID and ESID
				e = reftype_AddRefTrack(mpod, esd->ESID, &ref->trackRef);
				e = ChainAddEntry(esdU2->ESDescriptors, ref);
				if (e) goto err_exit;
			}
			OD_DeleteCommand((ODCommand **)&esdU);
			OD_AddCommand(ODencode, (ODCommand *)esdU2);
			break;

		//Brand new case: the ESRemove has to be rewritten too according to the specs...
		case ESDRemove_Tag:
			esdR = (ESDescriptorRemove *) com;
			esdR2 = (ESDescriptorRemove *) OD_NewCommand(ESDRemove_Tag);
			//change the tag for the file format
			esdR2->tag = ESDRemove_Ref_Tag;
			esdR2->ODID = esdR->ODID;
			esdR2->NbESDs = esdR->NbESDs;
			//alloc our stuff
			esdR2->ES_ID = (unsigned short*)malloc(sizeof(u32) * esdR->NbESDs);
			if (!esdR2->ES_ID) {
				e = M4OutOfMem;
				goto err_exit;
			}
			for (i = 0; i < esdR->NbESDs; i++) {
				//1 to 1 mapping trackID and ESID
				e = reftype_AddRefTrack(mpod, esdR->ES_ID[i], &esdR2->ES_ID[i]);
				if (e) goto err_exit;
			}
			OD_DeleteCommand(&com);
			OD_AddCommand(ODencode, (ODCommand *)esdR2);
			break;

		//Add the command as is
		default:
			e = OD_AddCommand(ODencode, com);
			if (e) goto err_exit;
		}
	}

	//encode our new AU
	e = OD_EncodeAU(ODencode);
	if (e) goto err_exit;

	//and set the buffer in the sample
	free(sample->data);
	sample->data = NULL;
	sample->dataLength = 0;
	e = OD_GetEncodedAU(ODencode, &sample->data, &sample->dataLength);

err_exit:

	OD_DeleteCodec(ODencode);
	OD_DeleteCodec(ODdecode);
	return e;
}
Ejemplo n.º 7
0
M4Err M4H_AddSampleData(M4File *the_file, u32 trackNumber, u32 SourceTrackID, u32 SampleNumber, u16 DataLength, u32 offsetInSample, char *extra_data, u8 AtBegin)
{
	TrackAtom *trak;
	HintSampleEntryAtom *entry;
	u32 count;
	u16 refIndex;
	HintPacket *pck;
	SampleDTE *dte;
	M4Err e;
	TrackReferenceTypeAtom *hint;

	M4Err reftype_AddRefTrack(TrackReferenceTypeAtom *ref, u32 trackID, u16 *outRefIndex);

	trak = GetTrackFromFile(the_file, trackNumber);
	if (!trak || !IsHintTrack(trak)) return M4BadParam;


	e = Media_GetSampleDesc(trak->Media, trak->Media->information->sampleTable->currentEntryIndex, (SampleEntryAtom **) &entry, &count);
	if (e) return e;
	if (!entry->w_sample) return M4BadParam;
	count = ChainGetCount(entry->w_sample->packetTable);
	if (!count) return M4BadParam;
	pck = ChainGetEntry(entry->w_sample->packetTable, count - 1);

	dte = (SampleDTE *) NewDTE(2);

	dte->dataLength = DataLength;
	dte->sampleNumber = SampleNumber;
	dte->byteOffset = offsetInSample;

	//we're getting data from another track
	if (SourceTrackID != trak->Header->trackID) {
		//get (or set) the track reference index 
		e = Track_FindRef(trak, M4_HintTrack_Ref, &hint);
		if (e) return e;
		e = reftype_AddRefTrack(hint, SourceTrackID, &refIndex);
		if (e) return e;
		//WARNING: IN QT, MUST BE 0-based !!!
		dte->trackRefIndex = (u8) (refIndex - 1);
	} else {
		//we're in the hint track
		dte->trackRefIndex = -1;
		//basic check...
		if (SampleNumber > trak->Media->information->sampleTable->SampleSize->sampleCount + 1) {
			DelDTE((GenericDTE *)dte);
			return M4BadParam;
		}

		//are we in the current sample ??
		if (!SampleNumber || (SampleNumber == trak->Media->information->sampleTable->SampleSize->sampleCount + 1)) {
			//we adding some stuff in the current sample ...
			dte->byteOffset += entry->w_sample->dataLength;
			if (entry->w_sample->AdditionalData) {
				entry->w_sample->AdditionalData = realloc(entry->w_sample->AdditionalData, sizeof(char) * (entry->w_sample->dataLength + DataLength));
				memcpy(entry->w_sample->AdditionalData + entry->w_sample->dataLength, extra_data, DataLength);
				entry->w_sample->dataLength += DataLength;
			} else {
				entry->w_sample->AdditionalData = malloc(sizeof(char) * DataLength);
				memcpy(entry->w_sample->AdditionalData, extra_data, DataLength);
				entry->w_sample->dataLength = DataLength;
			}
			//and set the sample number ...
			dte->sampleNumber = trak->Media->information->sampleTable->SampleSize->sampleCount + 1;
		}
	}
	//OK, add the entry
	return AddDTE_HintPacket(entry->w_sample->HintType, pck, (GenericDTE *)dte, AtBegin);
}
Ejemplo n.º 8
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;
}