//remove all SDP info at the track level GF_Err gf_isom_sdp_clean_track(GF_ISOFile *the_file, u32 trackNumber) { GF_TrackBox *trak; GF_UserDataMap *map; GF_HintTrackInfoBox *hnti; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return GF_BAD_PARAM; //currently, only RTP hinting supports SDP if (!CheckHintFormat(trak, GF_ISOM_HINT_RTP)) return GF_BAD_PARAM; map = udta_getEntry(trak->udta, GF_ISOM_BOX_TYPE_HNTI, NULL); if (!map) return GF_ISOM_INVALID_FILE; //we should have only one HNTI in the UDTA if (gf_list_count(map->other_boxes) != 1) return GF_ISOM_INVALID_FILE; hnti = (GF_HintTrackInfoBox *)gf_list_get(map->other_boxes, 0); if (!hnti->SDP) return GF_OK; //and free the SDP gf_free(((GF_SDPBox *)hnti->SDP)->sdpText); ((GF_SDPBox *)hnti->SDP)->sdpText = NULL; return GF_OK; }
M4Err M4H_SDP_GetSDP(M4File *the_file, const char **sdp, u32 *length) { M4Movie *mov; UserDataMap *map; HintTrackInfoAtom *hnti; RTPAtom *rtp; mov = (M4Movie *)the_file; *length = 0; *sdp = NULL; //check if we have a udta ... if (!mov->moov->udta) return M4OK; //find a hnti in the udta map = udta_getEntry(mov->moov->udta, HintTrackInfoAtomType); if (!map) return M4OK; //there should be one and only one hnti if (ChainGetCount(map->atomList) != 1) return M4InvalidMP4File; hnti = ChainGetEntry(map->atomList, 0); if (!hnti->SDP) return M4OK; rtp = (RTPAtom *) hnti->SDP; *length = strlen(rtp->sdpText); *sdp = rtp->sdpText; return M4OK; }
M4Err M4H_SDP_GetTrackSDP(M4File *the_file, u32 trackNumber, const char **sdp, u32 *length) { TrackAtom *trak; UserDataMap *map; HintTrackInfoAtom *hnti; SDPAtom *sdpa; *sdp = NULL; *length = 0; trak = GetTrackFromFile(the_file, trackNumber); if (!trak) return M4BadParam; if (!trak->udta) return M4OK; map = udta_getEntry(trak->udta, HintTrackInfoAtomType); if (!map) return M4InvalidMP4File; //we should have only one HNTI in the UDTA if (ChainGetCount(map->atomList) != 1) return M4InvalidMP4File; hnti = ChainGetEntry(map->atomList, 0); if (!hnti->SDP) return M4OK; sdpa = (SDPAtom *) hnti->SDP; *length = strlen(sdpa->sdpText); *sdp = sdpa->sdpText; return M4OK; }
//remove all SDP info at the track level M4Err M4H_SDP_CleanTrack(M4File *the_file, u32 trackNumber) { TrackAtom *trak; UserDataMap *map; HintTrackInfoAtom *hnti; trak = GetTrackFromFile(the_file, trackNumber); if (!trak) return M4BadParam; //currently, only RTP hinting supports SDP if (!CheckHintFormat(trak, M4_Hint_RTP)) return M4BadParam; map = udta_getEntry(trak->udta, HintTrackInfoAtomType); if (!map) return M4InvalidMP4File; //we should have only one HNTI in the UDTA if (ChainGetCount(map->atomList) != 1) return M4InvalidMP4File; hnti = ChainGetEntry(map->atomList, 0); if (!hnti->SDP) return M4OK; //and free the SDP free(((SDPAtom *)hnti->SDP)->sdpText); ((SDPAtom *)hnti->SDP)->sdpText = NULL; return M4OK; }
GF_EXPORT const char *gf_isom_get_payt_info(GF_ISOFile *the_file, u32 trackNumber, u32 index, u32 *payID) { u32 i, count; GF_TrackBox *trak; GF_UserDataMap *map; GF_HintInfoBox *hinf; GF_PAYTBox *payt; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !index) return NULL; if (!CheckHintFormat(trak, GF_4CC('r', 't', 'p', ' '))) return NULL; map = udta_getEntry(trak->udta, GF_ISOM_BOX_TYPE_HINF, NULL); if (!map) return NULL; if (gf_list_count(map->boxList) != 1) return NULL; hinf = (GF_HintInfoBox *)gf_list_get(map->boxList, 0); count = 0; i = 0; while ((payt = gf_list_enum(hinf->boxList, &i))) { if (payt->type == GF_ISOM_BOX_TYPE_PAYT) { count++; if (count == index) { if (payID) *payID=payt->payloadCode; return payt->payloadString; } } } return NULL; }
GF_EXPORT u32 gf_isom_get_payt_count(GF_ISOFile *the_file, u32 trackNumber) { u32 i, count; GF_TrackBox *trak; GF_UserDataMap *map; GF_HintInfoBox *hinf; GF_PAYTBox *payt; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return 0; if (!CheckHintFormat(trak, GF_4CC('r', 't', 'p', ' '))) return 0; map = udta_getEntry(trak->udta, GF_ISOM_BOX_TYPE_HINF, NULL); if (!map) return 0; if (gf_list_count(map->boxList) != 1) return 0; hinf = (GF_HintInfoBox *)gf_list_get(map->boxList, 0); count = 0; i = 0; while ((payt = gf_list_enum(hinf->boxList, &i))) { if (payt->type == GF_ISOM_BOX_TYPE_PAYT) count++; } return count; }
GF_EXPORT GF_Err gf_isom_sdp_track_get(GF_ISOFile *the_file, u32 trackNumber, const char **sdp, u32 *length) { GF_TrackBox *trak; GF_UserDataMap *map; GF_HintTrackInfoBox *hnti; GF_SDPBox *sdpa; *sdp = NULL; *length = 0; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return GF_BAD_PARAM; if (!trak->udta) return GF_OK; map = udta_getEntry(trak->udta, GF_ISOM_BOX_TYPE_HNTI, NULL); if (!map) return GF_ISOM_INVALID_FILE; //we should have only one HNTI in the UDTA if (gf_list_count(map->boxList) != 1) return GF_ISOM_INVALID_FILE; hnti = (GF_HintTrackInfoBox *)gf_list_get(map->boxList, 0); if (!hnti->SDP) return GF_OK; sdpa = (GF_SDPBox *) hnti->SDP; *length = strlen(sdpa->sdpText); *sdp = sdpa->sdpText; return GF_OK; }
GF_EXPORT GF_Err gf_isom_sdp_get(GF_ISOFile *movie, const char **sdp, u32 *length) { GF_UserDataMap *map; GF_HintTrackInfoBox *hnti; GF_RTPBox *rtp; *length = 0; *sdp = NULL; if (!movie || !movie->moov) return GF_BAD_PARAM; //check if we have a udta ... if (!movie->moov->udta) return GF_OK; //find a hnti in the udta map = udta_getEntry(movie->moov->udta, GF_ISOM_BOX_TYPE_HNTI, NULL); if (!map) return GF_OK; //there should be one and only one hnti if (gf_list_count(map->boxList) != 1) return GF_ISOM_INVALID_FILE; hnti = (GF_HintTrackInfoBox *)gf_list_get(map->boxList, 0); if (!hnti->SDP) return GF_OK; rtp = (GF_RTPBox *) hnti->SDP; *length = strlen(rtp->sdpText); *sdp = rtp->sdpText; return GF_OK; }
//add an SDP line to the SDP container at the track level (media-specific SDP info) GF_EXPORT GF_Err gf_isom_sdp_add_track_line(GF_ISOFile *the_file, u32 trackNumber, const char *text) { GF_TrackBox *trak; GF_UserDataMap *map; GF_HintTrackInfoBox *hnti; GF_SDPBox *sdp; GF_Err e; char *buf; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return GF_BAD_PARAM; //currently, only RTP hinting supports SDP if (!CheckHintFormat(trak, GF_ISOM_HINT_RTP)) return GF_BAD_PARAM; map = udta_getEntry(trak->udta, GF_ISOM_BOX_TYPE_HNTI, NULL); if (!map) return GF_ISOM_INVALID_FILE; //we should have only one HNTI in the UDTA if (gf_list_count(map->other_boxes) != 1) return GF_ISOM_INVALID_FILE; hnti = (GF_HintTrackInfoBox *)gf_list_get(map->other_boxes, 0); if (!hnti->SDP) { e = hnti_AddBox(hnti, gf_isom_box_new(GF_ISOM_BOX_TYPE_SDP)); if (e) return e; } sdp = (GF_SDPBox *) hnti->SDP; if (!sdp->sdpText) { sdp->sdpText = (char *)gf_malloc(sizeof(char) * (strlen(text) + 3)); strcpy(sdp->sdpText, text); strcat(sdp->sdpText, "\r\n"); return GF_OK; } buf = (char *)gf_malloc(sizeof(char) * (strlen(sdp->sdpText) + strlen(text) + 3)); strcpy(buf, sdp->sdpText); strcat(buf, text); strcat(buf, "\r\n"); gf_free(sdp->sdpText); ReorderSDP(buf, GF_FALSE); sdp->sdpText = buf; return GF_OK; }
//add an SDP line to the SDP container at the track level (media-specific SDP info) M4Err M4H_SDP_TrackAddLine(M4File *the_file, u32 trackNumber, const char *text) { TrackAtom *trak; UserDataMap *map; HintTrackInfoAtom *hnti; SDPAtom *sdp; M4Err e; char *buf; M4Err hnti_AddAtom(HintTrackInfoAtom *hnti, Atom *a); trak = GetTrackFromFile(the_file, trackNumber); if (!trak) return M4BadParam; //currently, only RTP hinting supports SDP if (!CheckHintFormat(trak, M4_Hint_RTP)) return M4BadParam; map = udta_getEntry(trak->udta, HintTrackInfoAtomType); if (!map) return M4InvalidMP4File; //we should have only one HNTI in the UDTA if (ChainGetCount(map->atomList) != 1) return M4InvalidMP4File; hnti = ChainGetEntry(map->atomList, 0); if (!hnti->SDP) { e = hnti_AddAtom(hnti, CreateAtom(SDPAtomType)); if (e) return e; } sdp = (SDPAtom *) hnti->SDP; if (!sdp->sdpText) { sdp->sdpText = malloc(sizeof(char) * (strlen(text) + 3)); strcpy(sdp->sdpText, text); strcat(sdp->sdpText, "\r\n"); return M4OK; } buf = malloc(sizeof(char) * (strlen(sdp->sdpText) + strlen(text) + 3)); strcpy(buf, sdp->sdpText); strcat(buf, text); strcat(buf, "\r\n"); free(sdp->sdpText); sdp->sdpText = buf; return M4OK; }
GF_MetaBox *gf_isom_apple_get_meta_extensions(GF_ISOFile *mov) { u32 i; GF_MetaBox *meta; GF_UserDataMap *map; if (!mov || !mov->moov) return NULL; if (!mov->moov->udta) return NULL; map = udta_getEntry(mov->moov->udta, GF_ISOM_BOX_TYPE_META, NULL); if (!map) return NULL; for(i = 0; i < gf_list_count(map->other_boxes); i++) { meta = (GF_MetaBox*)gf_list_get(map->other_boxes, i); if(meta != NULL && meta->handler != NULL && meta->handler->handlerType == GF_ISOM_HANDLER_TYPE_MDIR) return meta; } return NULL; }
//remove all SDP info at the movie level GF_Err gf_isom_sdp_clean(GF_ISOFile *movie) { GF_UserDataMap *map; GF_HintTrackInfoBox *hnti; //check if we have a udta ... if (!movie->moov || !movie->moov->udta) return GF_OK; //find a hnti in the udta map = udta_getEntry(movie->moov->udta, GF_ISOM_BOX_TYPE_HNTI, NULL); if (!map) return GF_OK; //there should be one and only one hnti if (gf_list_count(map->boxList) != 1) return GF_ISOM_INVALID_FILE; hnti = (GF_HintTrackInfoBox *)gf_list_get(map->boxList, 0); //remove and destroy the entry gf_list_rem(map->boxList, 0); gf_isom_box_del((GF_Box *)hnti); return GF_OK; }
GF_MetaBox *gf_isom_apple_create_meta_extensions(GF_ISOFile *mov) { GF_Err e; u32 i; GF_MetaBox *meta; GF_UserDataMap *map; if (!mov || !mov->moov) return NULL; if (!mov->moov->udta) { e = moov_AddBox((GF_Box*)mov->moov, gf_isom_box_new(GF_ISOM_BOX_TYPE_UDTA)); if (e) return NULL; } map = udta_getEntry(mov->moov->udta, GF_ISOM_BOX_TYPE_META, NULL); if (map) { for(i = 0; i < gf_list_count(map->other_boxes); i++) { meta = (GF_MetaBox*)gf_list_get(map->other_boxes, i); if(meta != NULL && meta->handler != NULL && meta->handler->handlerType == GF_ISOM_HANDLER_TYPE_MDIR) return meta; } } meta = (GF_MetaBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_META); if(meta != NULL) { meta->handler = (GF_HandlerBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_HDLR); if(meta->handler == NULL) { gf_isom_box_del((GF_Box *)meta); return NULL; } meta->handler->handlerType = GF_ISOM_HANDLER_TYPE_MDIR; if (!meta->other_boxes) meta->other_boxes = gf_list_new(); gf_list_add(meta->other_boxes, gf_isom_box_new(GF_ISOM_BOX_TYPE_ILST)); udta_AddBox(mov->moov->udta, (GF_Box *)meta); } return meta; }
//remove all SDP info at the movie level M4Err M4H_SDP_CleanMovie(M4File *the_file) { M4Movie *mov; UserDataMap *map; HintTrackInfoAtom *hnti; mov = (M4Movie *)the_file; //check if we have a udta ... if (!mov->moov->udta) return M4OK; //find a hnti in the udta map = udta_getEntry(mov->moov->udta, HintTrackInfoAtomType); if (!map) return M4OK; //there should be one and only one hnti if (ChainGetCount(map->atomList) != 1) return M4InvalidMP4File; hnti = ChainGetEntry(map->atomList, 0); //remove and destroy the entry ChainDeleteEntry(map->atomList, 0); DelAtom((Atom *)hnti); return M4OK; }
//add an SDP line to the SDP container at the movie level (presentation SDP info) //NOTE: the \r\n end of line for SDP is automatically inserted M4Err M4H_SDP_MovieAddLine(M4File *the_file, const char *text) { M4Movie *mov; UserDataMap *map; RTPAtom *rtp; M4Err e; HintTrackInfoAtom *hnti; char *buf; M4Err udta_AddAtom(UserDataAtom *ptr, Atom *a); M4Err hnti_AddAtom(HintTrackInfoAtom *hnti, Atom *a); M4Err moov_AddAtom(MovieAtom *moov, Atom *a); mov = (M4Movie *)the_file; //check if we have a udta ... if (!mov->moov->udta) { e = moov_AddAtom(mov->moov, CreateAtom(UserDataAtomType)); if (e) return e; } //find a hnti in the udta map = udta_getEntry(mov->moov->udta, HintTrackInfoAtomType); if (!map) { e = udta_AddAtom(mov->moov->udta, CreateAtom(HintTrackInfoAtomType)); if (e) return e; map = udta_getEntry(mov->moov->udta, HintTrackInfoAtomType); } //there should be one and only one hnti if (!ChainGetCount(map->atomList) ) { e = udta_AddAtom(mov->moov->udta, CreateAtom(HintTrackInfoAtomType)); if (e) return e; } else if (ChainGetCount(map->atomList) < 1) return M4InvalidMP4File; hnti = ChainGetEntry(map->atomList, 0); if (!hnti->SDP) { //we have to create it by hand, as we have a duplication of atom type //(RTPSampleEntryAtom and RTPAtom have the same type...) rtp = malloc(sizeof(RTPAtom)); rtp->subType = SDPAtomType; rtp->type = RTPAtomType; rtp->sdpText = NULL; hnti_AddAtom(hnti, (Atom *)rtp); } rtp = (RTPAtom *) hnti->SDP; if (!rtp->sdpText) { rtp->sdpText = malloc(sizeof(char) * (strlen(text) + 3)); strcpy(rtp->sdpText, text); strcat(rtp->sdpText, "\r\n"); return M4OK; } buf = malloc(sizeof(char) * (strlen(rtp->sdpText) + strlen(text) + 3)); strcpy(buf, rtp->sdpText); strcat(buf, text); strcat(buf, "\r\n"); free(rtp->sdpText); rtp->sdpText = buf; return M4OK; }