//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); }
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); }
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); }
GF_Err gf_isom_hint_rtp_read(GF_RTPPacket *ptr, GF_BitStream *bs) { GF_Err e; u8 hasTLV, type; u16 i, count; u32 TLVsize, tempSize; GF_GenericDTE *dte; GF_Box *a; ptr->relativeTransTime = gf_bs_read_u32(bs); //RTP Header //1- reserved fields gf_bs_read_int(bs, 2); ptr->P_bit = gf_bs_read_int(bs, 1); ptr->X_bit = gf_bs_read_int(bs, 1); gf_bs_read_int(bs, 4); ptr->M_bit = gf_bs_read_int(bs, 1); ptr->payloadType = gf_bs_read_int(bs, 7); ptr->SequenceNumber = gf_bs_read_u16(bs); gf_bs_read_int(bs, 13); hasTLV = gf_bs_read_int(bs, 1); ptr->B_bit = gf_bs_read_int(bs, 1); ptr->R_bit = gf_bs_read_int(bs, 1); count = gf_bs_read_u16(bs); //read the TLV if (hasTLV) { tempSize = 4; //TLVsize includes its field length TLVsize = gf_bs_read_u32(bs); while (tempSize < TLVsize) { e = gf_isom_box_parse(&a, bs); if (e) return e; gf_list_add(ptr->TLV, a); tempSize += (u32) a->size; } if (tempSize != TLVsize) return GF_ISOM_INVALID_FILE; } //read the DTEs for (i=0; i<count; i++) { Bool add_it = 0; type = gf_bs_read_u8(bs); dte = NewDTE(type); if (!dte) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso] invalid DTE code %d in hint sample %d of trackID %d\n", type, ptr->sampleNumber, ptr->trackID)); return GF_ISOM_INVALID_FILE; } e = ReadDTE(dte, bs); if (e) return e; /*little opt, remove empty dte*/ switch (type) { case 1: if ( ((GF_ImmediateDTE *)dte)->dataLength) add_it = 1; break; case 2: if ( ((GF_SampleDTE *)dte)->dataLength) add_it = 1; break; case 3: if ( ((GF_StreamDescDTE *)dte)->dataLength) add_it = 1; break; } if (add_it) gf_list_add(ptr->DataTable, dte); else DelDTE(dte); } return GF_OK; }
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); }