//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 GF_EXPORT GF_Err gf_isom_sdp_add_line(GF_ISOFile *movie, const char *text) { GF_UserDataMap *map; GF_RTPBox *rtp; GF_Err e; GF_HintTrackInfoBox *hnti; char *buf; if (!movie->moov) return GF_BAD_PARAM; //check if we have a udta ... if (!movie->moov->udta) { e = moov_AddBox((GF_Box*)movie->moov, gf_isom_box_new(GF_ISOM_BOX_TYPE_UDTA)); if (e) return e; } //find a hnti in the udta map = udta_getEntry(movie->moov->udta, GF_ISOM_BOX_TYPE_HNTI, NULL); if (!map) { e = udta_AddBox(movie->moov->udta, gf_isom_box_new(GF_ISOM_BOX_TYPE_HNTI)); if (e) return e; map = udta_getEntry(movie->moov->udta, GF_ISOM_BOX_TYPE_HNTI, NULL); } //there should be one and only one hnti if (!gf_list_count(map->other_boxes) ) { e = udta_AddBox(movie->moov->udta, gf_isom_box_new(GF_ISOM_BOX_TYPE_HNTI)); if (e) return e; } else 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) { //we have to create it by hand, as we have a duplication of box type //(GF_RTPSampleEntryBox and GF_RTPBox have the same type...) rtp = (GF_RTPBox *) gf_malloc(sizeof(GF_RTPBox)); rtp->subType = GF_ISOM_BOX_TYPE_SDP; rtp->type = GF_ISOM_BOX_TYPE_RTP; rtp->sdpText = NULL; hnti_AddBox(hnti, (GF_Box *)rtp); } rtp = (GF_RTPBox *) hnti->SDP; if (!rtp->sdpText) { rtp->sdpText = (char*)gf_malloc(sizeof(char) * (strlen(text) + 3)); strcpy(rtp->sdpText, text); strcat(rtp->sdpText, "\r\n"); return GF_OK; } buf = (char*)gf_malloc(sizeof(char) * (strlen(rtp->sdpText) + strlen(text) + 3)); strcpy(buf, rtp->sdpText); strcat(buf, text); strcat(buf, "\r\n"); gf_free(rtp->sdpText); ReorderSDP(buf, GF_TRUE); rtp->sdpText = buf; 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; }
void gf_isom_insert_moov(GF_ISOFile *file) { u64 now; GF_MovieHeaderBox *mvhd; if (file->moov) return; //OK, create our boxes (mvhd, iods, ...) file->moov = (GF_MovieBox *) moov_New(); file->moov->mov = file; //Header SetUp now = gf_isom_get_mp4time(); mvhd = (GF_MovieHeaderBox *) mvhd_New(); mvhd->creationTime = now; mvhd->modificationTime = now; mvhd->nextTrackID = 1; //600 is our default movie TimeScale mvhd->timeScale = 600; file->interleavingTime = mvhd->timeScale; moov_AddBox((GF_Box*)file->moov, (GF_Box *)mvhd); gf_list_add(file->TopBoxes, file->moov); }