//adds a chunk of data (max 14 bytes) in the packet that is directly copied //while streaming M4Err M4H_AddDirectData(M4File *the_file, u32 trackNumber, char *data, u32 dataLength, u8 AtBegin) { TrackAtom *trak; HintSampleEntryAtom *entry; u32 count; HintPacket *pck; ImmediateDTE *dte; M4Err e; u32 offset = 0; trak = GetTrackFromFile(the_file, trackNumber); if (!trak || !IsHintTrack(trak) || (dataLength > 14)) 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 = (ImmediateDTE *) NewDTE(1); memcpy(dte->data, data + offset, dataLength); dte->dataLength = dataLength; return AddDTE_HintPacket(entry->w_sample->HintType, pck, (GenericDTE *)dte, AtBegin); }
//adds a chunk of data (max 14 bytes) in the packet that is directly copied //while streaming GF_Err gf_isom_hint_direct_data(GF_ISOFile *the_file, u32 trackNumber, char *data, u32 dataLength, u8 AtBegin) { GF_TrackBox *trak; GF_HintSampleEntryBox *entry; u32 count; GF_HintPacket *pck; GF_ImmediateDTE *dte; GF_Err e; u32 offset = 0; if (!dataLength) return GF_OK; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !IsHintTrack(trak) || (dataLength > 14)) 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_ImmediateDTE *) NewDTE(1); memcpy(dte->data, data + offset, dataLength); dte->dataLength = dataLength; return gf_isom_hint_pck_add_dte(entry->hint_sample->HintType, pck, (GF_GenericDTE *)dte, AtBegin); }
Bool CheckHintFormat(TrackAtom *trak, u32 HintType) { HintMediaHeaderAtom *hmhd; if (!IsHintTrack(trak)) return 0; hmhd = (HintMediaHeaderAtom *)trak->Media->information->InfoHeader; if (hmhd->subType != HintType) return 0; return 1; }
//to use with internally supported protocols GF_Err gf_isom_new_hint_description(GF_ISOFile *the_file, u32 trackNumber, s32 HintTrackVersion, s32 LastCompatibleVersion, u8 Rely, u32 *HintDescriptionIndex) { GF_Err e; u32 drefIndex; GF_TrackBox *trak; GF_HintSampleEntryBox *hdesc; GF_RelyHintBox *relyA; e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(the_file, trackNumber); *HintDescriptionIndex = 0; if (!trak || !IsHintTrack(trak)) return GF_BAD_PARAM; //OK, create a new HintSampleDesc hdesc = (GF_HintSampleEntryBox *) gf_isom_box_new(GetHintFormat(trak)); if (HintTrackVersion > 0) hdesc->HintTrackVersion = HintTrackVersion; if (LastCompatibleVersion > 0) hdesc->LastCompatibleVersion = LastCompatibleVersion; //create a data reference - WE ONLY DEAL WITH SELF-CONTAINED HINT TRACKS e = Media_CreateDataRef(trak->Media->information->dataInformation->dref, NULL, NULL, &drefIndex); if (e) return e; hdesc->dataReferenceIndex = drefIndex; //add the entry to our table... e = stsd_AddBox(trak->Media->information->sampleTable->SampleDescription, (GF_Box *) hdesc); if (e) return e; *HintDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); //RTP needs a default timeScale... use the media one. if (CheckHintFormat(trak, GF_ISOM_HINT_RTP)) { e = gf_isom_rtp_set_timescale(the_file, trackNumber, *HintDescriptionIndex, trak->Media->mediaHeader->timeScale); if (e) return e; } if (!Rely) return GF_OK; //we need a rely box (common to all protocols) relyA = (GF_RelyHintBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_RELY); if (Rely == 1) { relyA->prefered = 1; } else { relyA->required = 1; } return gf_list_add(hdesc->HintDataTable, relyA); }
//stores the hint sample in the file //set IsRandomAccessPoint if you want to indicate that this is a random access point //in the stream M4Err M4H_EndHintSample(M4File *the_file, u32 trackNumber, u8 IsRandomAccessPoint) { TrackAtom *trak; HintSampleEntryAtom *entry; u32 dataRefIndex; M4Err e; BitStream *bs; M4Sample *samp; trak = GetTrackFromFile(the_file, trackNumber); if (!trak || !IsHintTrack(trak)) return M4BadParam; e = Media_GetSampleDesc(trak->Media, trak->Media->information->sampleTable->currentEntryIndex, (SampleEntryAtom **) &entry, &dataRefIndex); if (e) return e; if (!entry->w_sample) return M4BadParam; //first of all, we need to adjust the offset for data referenced IN THIS hint sample //and get some PckSize e = AdjustHintInfo(entry, trak->Media->information->sampleTable->SampleSize->sampleCount + 1); if (e) return e; //ok, let's write the sample bs = NewBitStream(NULL, 0, BS_WRITE); e = Write_HintSample(entry->w_sample, bs); if (e) { DeleteBitStream(bs); return e; } BS_CutBuffer(bs); samp = M4_NewSample(); samp->CTS_Offset = 0; samp->IsRAP = IsRandomAccessPoint; samp->DTS = entry->w_sample->TransmissionTime; //get the sample BS_GetContent(bs, (unsigned char **) &samp->data, &samp->dataLength); DeleteBitStream(bs); //finally add the sample e = M4_AddSample(the_file, trackNumber, trak->Media->information->sampleTable->currentEntryIndex, samp); M4_DeleteSample(&samp); //and delete the sample in our entry ... Del_HintSample(entry->w_sample); entry->w_sample = NULL; return e; }
//to use with internally supported protocols M4Err M4H_NewHintDescription(M4File *the_file, u32 trackNumber, s32 HintTrackVersion, s32 LastCompatibleVersion, u8 Rely, u32 *HintDescriptionIndex) { M4Err e; u32 drefIndex; TrackAtom *trak; HintSampleEntryAtom *hdesc; RelyHintEntry *relyA; M4Err stsd_AddAtom(SampleDescriptionAtom *ptr, Atom *a); trak = GetTrackFromFile(the_file, trackNumber); *HintDescriptionIndex = 0; if (!trak || !IsHintTrack(trak)) return M4BadParam; //OK, create a new HintSampleDesc hdesc = (HintSampleEntryAtom *) CreateAtom(GetHintFormat(trak)); if (HintTrackVersion > 0) hdesc->HintTrackVersion = HintTrackVersion; if (LastCompatibleVersion > 0) hdesc->LastCompatibleVersion = LastCompatibleVersion; //create a data reference - WE ONLY DEAL WITH SELF-CONTAINED HINT TRACKS e = Media_CreateDataRef(trak->Media->information->dataInformation->dref, NULL, NULL, &drefIndex); if (e) return e; hdesc->dataReferenceIndex = drefIndex; //add the entry to our table... e = stsd_AddAtom(trak->Media->information->sampleTable->SampleDescription, (Atom *) hdesc); if (e) return e; *HintDescriptionIndex = ChainGetCount(trak->Media->information->sampleTable->SampleDescription->atomList); //RTP needs a default timeScale... use the media one. if (CheckHintFormat(trak, M4_Hint_RTP)) { e = M4H_RTP_SetTimeScale(the_file, trackNumber, *HintDescriptionIndex, trak->Media->mediaHeader->timeScale); if (e) return e; } if (!Rely) return M4OK; //we need a rely atom (common to all protocols) relyA = (RelyHintEntry *) CreateAtom(relyHintEntryType); if (Rely == 1) { relyA->prefered = 1; } else { relyA->required = 1; } return ChainAddEntry(hdesc->HintDataTable, relyA); }
//stores the hint sample in the file //set IsRandomAccessPoint if you want to indicate that this is a random access point //in the stream GF_Err gf_isom_end_hint_sample(GF_ISOFile *the_file, u32 trackNumber, u8 IsRandomAccessPoint) { GF_TrackBox *trak; GF_HintSampleEntryBox *entry; u32 dataRefIndex; GF_Err e; GF_BitStream *bs; GF_ISOSample *samp; 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, &dataRefIndex); if (e) return e; if (!entry->hint_sample) return GF_BAD_PARAM; //first of all, we need to adjust the offset for data referenced IN THIS hint sample //and get some PckSize e = AdjustHintInfo(entry, trak->Media->information->sampleTable->SampleSize->sampleCount + 1); if (e) return e; //ok, let's write the sample bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); e = gf_isom_hint_sample_write(entry->hint_sample, bs); if (e) { gf_bs_del(bs); return e; } samp = gf_isom_sample_new(); samp->CTS_Offset = 0; samp->IsRAP = IsRandomAccessPoint; samp->DTS = entry->hint_sample->TransmissionTime; //get the sample gf_bs_get_content(bs, &samp->data, &samp->dataLength); gf_bs_del(bs); //finally add the sample e = gf_isom_add_sample(the_file, trackNumber, trak->Media->information->sampleTable->currentEntryIndex, samp); gf_isom_sample_del(&samp); //and delete the sample in our entry ... gf_isom_hint_sample_del(entry->hint_sample); entry->hint_sample = NULL; return e; }
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); }
//adds a blank chunk of data in the sample that is skipped while streaming GF_Err gf_isom_hint_blank_data(GF_ISOFile *the_file, u32 trackNumber, u8 AtBegin) { GF_TrackBox *trak; GF_HintSampleEntryBox *entry; u32 count; GF_HintPacket *pck; GF_EmptyDTE *dte; GF_Err e; 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_EmptyDTE *) NewDTE(0); return gf_isom_hint_pck_add_dte(entry->hint_sample->HintType, pck, (GF_GenericDTE *)dte, AtBegin); }
//adds a blank chunk of data in the sample that is skipped while streaming M4Err M4H_AddBlankData(M4File *the_file, u32 trackNumber, u8 AtBegin) { TrackAtom *trak; HintSampleEntryAtom *entry; u32 count; HintPacket *pck; EmptyDTE *dte; M4Err e; 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 = (EmptyDTE *) NewDTE(0); return AddDTE_HintPacket(entry->w_sample->HintType, pck, (GenericDTE *)dte, AtBegin); }
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); }
//Starts a new sample for the hint track. A sample is just a collection of packets //the transmissionTime is indicated in the media timeScale of the hint track GF_Err gf_isom_begin_hint_sample(GF_ISOFile *the_file, u32 trackNumber, u32 HintDescriptionIndex, u32 TransmissionTime) { GF_TrackBox *trak; u32 descIndex, dataRefIndex; GF_HintSample *samp; GF_HintSampleEntryBox *entry; GF_Err e; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !IsHintTrack(trak)) return GF_BAD_PARAM; //assert we're increasing the timing... if (trak->Media->information->sampleTable->TimeToSample->w_LastDTS > TransmissionTime) return GF_BAD_PARAM; //store the descIndex for this sample descIndex = HintDescriptionIndex; if (!HintDescriptionIndex) { descIndex = trak->Media->information->sampleTable->currentEntryIndex; } e = Media_GetSampleDesc(trak->Media, descIndex, (GF_SampleEntryBox **) &entry, &dataRefIndex); if (e) return e; if (!entry || !dataRefIndex) return GF_BAD_PARAM; //set the current to this one if no packet is used if (entry->hint_sample) return GF_BAD_PARAM; trak->Media->information->sampleTable->currentEntryIndex = descIndex; //create a new sample based on the protocol type of the hint description entry samp = gf_isom_hint_sample_new(entry->type); if (!samp) return GF_NOT_SUPPORTED; //OK, let's store the time of this sample samp->TransmissionTime = TransmissionTime; //OK, set our sample in the entry... entry->hint_sample = samp; return GF_OK; }
//Starts a new sample for the hint track. A sample is just a collection of packets //the transmissionTime is indicated in the media timeScale of the hint track M4Err M4H_BeginHintSample(M4File *the_file, u32 trackNumber, u32 HintDescriptionIndex, u32 TransmissionTime) { TrackAtom *trak; u32 descIndex, dataRefIndex; HintSample *samp; HintSampleEntryAtom *entry; M4Err e; trak = GetTrackFromFile(the_file, trackNumber); if (!trak || !IsHintTrack(trak)) return M4BadParam; //assert we're increasing the timing... if (trak->Media->information->sampleTable->TimeToSample->w_LastDTS > TransmissionTime) return M4BadParam; //store the descIndex for this sample descIndex = HintDescriptionIndex; if (!HintDescriptionIndex) { descIndex = trak->Media->information->sampleTable->currentEntryIndex; } e = Media_GetSampleDesc(trak->Media, descIndex, (SampleEntryAtom **) &entry, &dataRefIndex); if (e) return e; if (!entry || !dataRefIndex) return M4BadParam; //set the current to this one if no packet is used if (entry->w_sample) return M4BadParam; trak->Media->information->sampleTable->currentEntryIndex = descIndex; //create a new sample based on the protocol type of the hint description entry samp = New_HintSample(entry->type); if (!samp) return M4NotSupported; //OK, let's store the time of this sample samp->TransmissionTime = TransmissionTime; //OK, set our sample in the entry... entry->w_sample = samp; return M4OK; }
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); }
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); }
Bool CheckHintFormat(GF_TrackBox *trak, u32 HintType) { if (!IsHintTrack(trak)) return 0; if (GetHintFormat(trak) != HintType) return 0; return 1; }
M4Err M4H_SetupHintTrack(M4File *the_file, u32 trackNumber, u32 HintType) { M4Err e; TrackAtom *trak; TrackReferenceAtom *tref; TrackReferenceTypeAtom *dpnd; HintMediaHeaderAtom *hmhd; //UDTA related ... UserDataAtom *udta; M4Err tref_AddAtom(TrackReferenceAtom *ptr, Atom *a); M4Err trak_AddAtom(TrackAtom *ptr, Atom *a); M4Err moov_AddAtom(MovieAtom *ptr, Atom *a); M4Err udta_AddAtom(UserDataAtom *ptr, Atom *a); //what do we support switch (HintType) { case M4_Hint_RTP: break; default: return M4NotSupported; } trak = GetTrackFromFile(the_file, trackNumber); if (!trak) return M4_GetLastError(the_file); if (((M4Movie *)the_file)->openMode != M4_OPEN_EDIT) return M4InvalidMP4Mode; //check we have a hint ... if ( !IsHintTrack(trak)) { return M4BadParam; } hmhd = (HintMediaHeaderAtom *)trak->Media->information->InfoHeader; //make sure the subtype was not already defined if (hmhd->subType) return M4HintPresent; //store the HintTrack format for later use... hmhd->subType = HintType; //hint tracks always have a tref and everything ... if (!trak->References) { if (!trak->References) { tref = (TrackReferenceAtom *) CreateAtom(TrackReferenceAtomType); e = trak_AddAtom(trak, (Atom *)tref); if (e) return e; } } tref = trak->References; //do we have a hint reference on this trak ??? e = Track_FindRef(trak, HintTrackReferenceAtomType, &dpnd); if (e) return e; //if yes, return false (existing hint track...) if (dpnd) return M4HintPresent; //create our dep dpnd = (TrackReferenceTypeAtom *) CreateAtom(HintTrackReferenceAtomType); e = tref_AddAtom(tref, (Atom *) dpnd); if (e) return e; //for RTP, we need to do some UDTA-related stuff... if (HintType != M4_Hint_RTP) return M4OK; if (!trak->udta) { //create one udta = (UserDataAtom *) CreateAtom(UserDataAtomType); e = trak_AddAtom(trak, (Atom *) udta); if (e) return e; } udta = trak->udta; //end-of-udta marker for Darwin... // if (!udta->voidAtom) { // e = udta_AddAtom(udta, CreateAtom(VoidAtomType)); // if (e) return e; // } //HNTI e = udta_AddAtom(udta, CreateAtom(HintTrackInfoAtomType)); if (e) return e; /* //NAME e = udta_AddAtom(udta, CreateAtom(nameAtomType)); if (e) return e; //HINF return udta_AddAtom(udta, CreateAtom(HintInfoAtomType)); */ return M4OK; }
GF_Err gf_isom_setup_hint_track(GF_ISOFile *movie, u32 trackNumber, u32 HintType) { GF_Err e; GF_TrackBox *trak; GF_TrackReferenceBox *tref; GF_TrackReferenceTypeBox *dpnd; GF_HintMediaHeaderBox *hmhd; //UDTA related ... GF_UserDataBox *udta; //what do we support switch (HintType) { case GF_ISOM_HINT_RTP: break; default: return GF_NOT_SUPPORTED; } e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak) return gf_isom_last_error(movie); //check we have a hint ... if ( !IsHintTrack(trak)) { return GF_BAD_PARAM; } hmhd = (GF_HintMediaHeaderBox *)trak->Media->information->InfoHeader; //make sure the subtype was not already defined if (hmhd->subType) return GF_BAD_PARAM; //store the HintTrack format for later use... hmhd->subType = HintType; //hint tracks always have a tref and everything ... if (!trak->References) { 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; //do we have a hint reference on this trak ??? e = Track_FindRef(trak, GF_ISOM_BOX_TYPE_HINT, &dpnd); if (e) return e; //if yes, return false (existing hint track...) if (dpnd) return GF_BAD_PARAM; //create our dep dpnd = (GF_TrackReferenceTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_REFT); dpnd->reference_type = GF_ISOM_BOX_TYPE_HINT; e = tref_AddBox((GF_Box*)tref, (GF_Box *) dpnd); if (e) return e; //for RTP, we need to do some UDTA-related stuff... if (HintType != GF_ISOM_HINT_RTP) return GF_OK; if (!trak->udta) { //create one udta = (GF_UserDataBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_UDTA); e = trak_AddBox((GF_Box*)trak, (GF_Box *) udta); if (e) return e; } udta = trak->udta; //HNTI e = udta_AddBox(udta, gf_isom_box_new(GF_ISOM_BOX_TYPE_HNTI)); if (e) return e; /* //NAME e = udta_AddBox(udta, gf_isom_box_new(GF_ISOM_BOX_TYPE_NAME)); if (e) return e; //HINF return udta_AddBox(udta, gf_isom_box_new(GF_ISOM_BOX_TYPE_HINF)); */ return GF_OK; }
Bool CheckHintFormat(GF_TrackBox *trak, u32 HintType) { if (!IsHintTrack(trak)) return GF_FALSE; if (GetHintFormat(trak) != HintType) return GF_FALSE; return GF_TRUE; }