📄 hint_track.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <gpac/internal/isomedia_dev.h>Bool IsHintTrack(GF_TrackBox *trak){ if (trak->Media->handler->handlerType != GF_ISOM_MEDIA_HINT) return 0; //QT doesn't specify any InfoHeader on HintTracks if (trak->Media->information->InfoHeader && trak->Media->information->InfoHeader->type != GF_ISOM_BOX_TYPE_HMHD) return 0; return 1;}u32 GetHintFormat(GF_TrackBox *trak){ GF_HintMediaHeaderBox *hmhd = (GF_HintMediaHeaderBox *)trak->Media->information->InfoHeader; if (!hmhd->subType) { GF_Box *a = (GF_Box *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, 0); if (a) hmhd->subType = a->type; } return hmhd->subType;}Bool CheckHintFormat(GF_TrackBox *trak, u32 HintType){ if (!IsHintTrack(trak)) return 0; if (GetHintFormat(trak) != HintType) return 0; return 1;}#ifndef GPAC_READ_ONLYGF_Err AdjustHintInfo(GF_HintSampleEntryBox *entry, u32 HintSampleNumber){ u32 offset, count, i, size; GF_HintPacket *pck; GF_Err e; offset = gf_isom_hint_sample_size(entry->hint_sample) - entry->hint_sample->dataLength; count = gf_list_count(entry->hint_sample->packetTable); for (i=0; i<count; i++) { pck = (GF_HintPacket *)gf_list_get(entry->hint_sample->packetTable, i); if (offset && entry->hint_sample->dataLength) { //adjust any offset in this packet e = gf_isom_hint_pck_offset(entry->hint_sample->HintType, pck, offset, HintSampleNumber); if (e) return e; } //adjust the max packet size for this sample entry... size = gf_isom_hint_pck_length(entry->hint_sample->HintType, pck); if (entry->MaxPacketSize < size) entry->MaxPacketSize = size; } return GF_OK;}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_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;}//to use with internally supported protocolsGF_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);}/******************************************************************* RTP WRITING API*******************************************************************///sets the RTP TimeScaleGF_Err gf_isom_rtp_set_timescale(GF_ISOFile *the_file, u32 trackNumber, u32 HintDescriptionIndex, u32 TimeScale){ GF_TrackBox *trak; GF_HintSampleEntryBox *hdesc; u32 i, count; GF_TSHintEntryBox *ent; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !CheckHintFormat(trak, GF_ISOM_HINT_RTP)) return GF_BAD_PARAM; //OK, create a new HintSampleDesc hdesc = (GF_HintSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, HintDescriptionIndex - 1); count = gf_list_count(hdesc->HintDataTable); for (i=0; i< count; i++) { ent = (GF_TSHintEntryBox *)gf_list_get(hdesc->HintDataTable, i); if (ent->type == GF_ISOM_BOX_TYPE_TIMS) { ent->timeScale = TimeScale; return GF_OK; } } //we have to create a new entry... ent = (GF_TSHintEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TIMS); ent->timeScale = TimeScale; return gf_list_add(hdesc->HintDataTable, ent);}//sets the RTP TimeOffset that the server will add to the packets//if not set, the server adds a random offsetGF_Err gf_isom_rtp_set_time_offset(GF_ISOFile *the_file, u32 trackNumber, u32 HintDescriptionIndex, u32 TimeOffset){ GF_TrackBox *trak; GF_HintSampleEntryBox *hdesc; u32 i, count; GF_TimeOffHintEntryBox *ent; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !CheckHintFormat(trak, GF_ISOM_HINT_RTP)) return GF_BAD_PARAM; //OK, create a new HintSampleDesc hdesc = (GF_HintSampleEntryBox *) gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, HintDescriptionIndex - 1); count = gf_list_count(hdesc->HintDataTable); for (i=0; i< count; i++) { ent = (GF_TimeOffHintEntryBox *)gf_list_get(hdesc->HintDataTable, i); if (ent->type == GF_ISOM_BOX_TYPE_TSRO) { ent->TimeOffset = TimeOffset; return GF_OK; } } //we have to create a new entry... ent = (GF_TimeOffHintEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TSRO); ent->TimeOffset = TimeOffset; return gf_list_add(hdesc->HintDataTable, ent);}//sets the RTP SequenceNumber Offset that the server will add to the packets//if not set, the server adds a random offsetGF_Err gf_isom_rtp_set_time_sequence_offset(GF_ISOFile *the_file, u32 trackNumber, u32 HintDescriptionIndex, u32 SequenceNumberOffset){ GF_TrackBox *trak; GF_HintSampleEntryBox *hdesc; u32 i, count; GF_SeqOffHintEntryBox *ent; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !CheckHintFormat(trak, GF_ISOM_HINT_RTP)) return GF_BAD_PARAM; //OK, create a new HintSampleDesc hdesc = (GF_HintSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, HintDescriptionIndex - 1); count = gf_list_count(hdesc->HintDataTable); for (i=0; i< count; i++) { ent = (GF_SeqOffHintEntryBox *)gf_list_get(hdesc->HintDataTable, i); if (ent->type == GF_ISOM_BOX_TYPE_SNRO) { ent->SeqOffset = SequenceNumberOffset; return GF_OK; } } //we have to create a new entry... ent = (GF_SeqOffHintEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_SNRO); ent->SeqOffset = SequenceNumberOffset; return gf_list_add(hdesc->HintDataTable, ent);}//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 trackGF_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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -