void RP_SDPFromData(RTPClient *rtp, char *s_url, RTPStream *stream) { char *url; char buf[2000]; u32 size; url = strstr(s_url, ","); if (!url) { gf_service_connect_ack(rtp->service, NULL, GF_URL_ERROR); return; } url += 1; if (strstr(url, ";base64")) { //decode size = gf_base64_decode(url, (u32) strlen(url), buf, 2000); buf[size] = 0; url = buf; } RP_LoadSDP(rtp, url, (u32) strlen(url), stream); }
static GF_Err RP_ChannelGetSLP(GF_InputService *plug, LPNETCHANNEL channel, char **out_data_ptr, u32 *out_data_size, GF_SLHeader *out_sl_hdr, Bool *sl_compressed, GF_Err *out_reception_status, Bool *is_new_data) { char *data; RTPStream *ch; RTPClient *priv = (RTPClient *)plug->priv; ch = RP_FindChannel(priv, channel, 0, NULL, 0); if (!ch) return GF_STREAM_NOT_FOUND; if (ch->rtp_ch || ch->rtsp || !ch->control) return GF_SERVICE_ERROR; if (ch->status != RTP_Running) return GF_SERVICE_ERROR; data = strstr(ch->control, ";base64"); if (!data) return GF_SERVICE_ERROR; if (ch->current_start>=0) { *sl_compressed = 0; memset(out_sl_hdr, 0, sizeof(GF_SLHeader)); out_sl_hdr->accessUnitEndFlag = 1; out_sl_hdr->accessUnitStartFlag = 1; out_sl_hdr->compositionTimeStamp = (u64) (ch->current_start * ch->ts_res); out_sl_hdr->compositionTimeStampFlag = 1; out_sl_hdr->randomAccessPointFlag = 1; *out_reception_status = GF_OK; *is_new_data = (ch->flags & GF_RTP_NEW_AU) ? 1 : 0; /*decode data*/ data = strstr(data, ","); data += 1; *out_data_size = gf_base64_decode(data, strlen(data), ch->buffer, RTP_BUFFER_SIZE); /*FIXME - currently only support for empty SL header*/ *out_data_ptr = ch->buffer; ch->flags &= ~GF_RTP_NEW_AU; } else { *out_data_ptr = NULL; *out_data_size = 0; *out_reception_status = GF_EOS; ch->flags |= RTP_EOS; } return GF_OK; }
/*load iod from data:application/mpeg4-iod;base64*/ GF_Err RP_SDPLoadIOD(RTPClient *rtp, char *iod_str) { char buf[2000]; u32 size; if (rtp->session_desc) return GF_SERVICE_ERROR; /*the only IOD format we support*/ iod_str += 1; if (!strnicmp(iod_str, "data:application/mpeg4-iod;base64", strlen("data:application/mpeg4-iod;base64"))) { char *buf64; u32 size64; buf64 = strstr(iod_str, ","); if (!buf64) return GF_URL_ERROR; buf64 += 1; size64 = (u32) strlen(buf64) - 1; size = gf_base64_decode(buf64, size64, buf, 2000); if (!size) return GF_SERVICE_ERROR; } else if (!strnicmp(iod_str, "data:application/mpeg4-iod;base16", strlen("data:application/mpeg4-iod;base16"))) { char *buf16; u32 size16; buf16 = strstr(iod_str, ","); if (!buf16) return GF_URL_ERROR; buf16 += 1; size16 = (u32) strlen(buf16) - 1; size = gf_base16_decode(buf16, size16, buf, 2000); if (!size) return GF_SERVICE_ERROR; } else { return GF_NOT_SUPPORTED; } gf_odf_desc_read(buf, size, &rtp->session_desc); return GF_OK; }
void gf_sm_update_bitwrapper_buffer(GF_Node *node, const char *fileName) { u32 data_size = 0; char *data = NULL; char *buffer; M_BitWrapper *bw = (M_BitWrapper *)node; if (!bw->buffer.buffer) return; buffer = bw->buffer.buffer; if (!strnicmp(buffer, "file://", 7)) { char *url = gf_url_concatenate(fileName, buffer+7); if (url) { FILE *f = fopen(url, "rb"); if (f) { fseek(f, 0, SEEK_END); data_size = ftell(f); fseek(f, 0, SEEK_SET); data = gf_malloc(sizeof(char)*data_size); if (data) { size_t s = fread(data, 1, data_size, f); assert(s == data_size); } fclose(f); } gf_free(url); } } else { Bool base_64 = 0; if (!strnicmp(buffer, "data:application/octet-string", 29)) { char *sep = strchr(bw->buffer.buffer, ','); base_64 = strstr(bw->buffer.buffer, ";base64") ? 1 : 0; if (sep) buffer = sep+1; } if (base_64) { data_size = 2 * (u32) strlen(buffer); data = (char*)gf_malloc(sizeof(char)*data_size); if (data) data_size = gf_base64_decode(buffer, (u32) strlen(buffer), data, data_size); } else { u32 i, c; char s[3]; data_size = (u32) strlen(buffer) / 3; data = (char*)gf_malloc(sizeof(char) * data_size); if (data) { s[2] = 0; for (i=0; i<data_size; i++) { s[0] = buffer[3*i+1]; s[1] = buffer[3*i+2]; sscanf(s, "%02X", &c); data[i] = (unsigned char) c; } } } } gf_free(bw->buffer.buffer); bw->buffer.buffer = NULL; bw->buffer_len = 0; if (data) { bw->buffer.buffer = data; bw->buffer_len = data_size; } }
GF_EXPORT GF_Err gf_node_store_embedded_data(XMLRI *iri, const char *cache_dir, const char *base_filename) { char szFile[GF_MAX_PATH], buf[20], *sep, *data, *ext; u32 data_size, idx; Bool existing; FILE *f; if (!cache_dir || !base_filename || !iri || !iri->string || strncmp(iri->string, "data:", 5)) return GF_OK; /*handle "data:" scheme when cache is specified*/ strcpy(szFile, cache_dir); data_size = (u32) strlen(szFile); if (szFile[data_size-1] != GF_PATH_SEPARATOR) { szFile[data_size] = GF_PATH_SEPARATOR; szFile[data_size+1] = 0; } if (base_filename) { sep = strrchr(base_filename, GF_PATH_SEPARATOR); #ifdef WIN32 if (!sep) sep = strrchr(base_filename, '/'); #endif if (!sep) sep = (char *) base_filename; else sep += 1; strcat(szFile, sep); } sep = strrchr(szFile, '.'); if (sep) sep[0] = 0; strcat(szFile, "_img_"); /*get mime type*/ sep = (char *)iri->string + 5; if (!strncmp(sep, "image/jpg", 9) || !strncmp(sep, "image/jpeg", 10)) ext = ".jpg"; else if (!strncmp(sep, "image/png", 9)) ext = ".png"; else if (!strncmp(sep, "image/svg+xml", 13)) ext = ".svg"; else return GF_BAD_PARAM; data = NULL; sep = strchr(iri->string, ';'); if (!strncmp(sep, ";base64,", 8)) { sep += 8; data_size = 2 * (u32) strlen(sep); data = (char*)gf_malloc(sizeof(char)*data_size); if (!data) return GF_OUT_OF_MEM; data_size = gf_base64_decode(sep, (u32) strlen(sep), data, data_size); } else if (!strncmp(sep, ";base16,", 8)) { data_size = 2 * (u32) strlen(sep); data = (char*)gf_malloc(sizeof(char)*data_size); if (!data) return GF_OUT_OF_MEM; sep += 8; data_size = gf_base16_decode(sep, (u32) strlen(sep), data, data_size); } if (!data_size) return GF_OK; iri->type = XMLRI_STRING; existing = 0; idx = 0; while (1) { u32 res = check_existing_file(szFile, ext, data, data_size, idx); if (!res) break; if (res==2) { existing = 1; break; } idx++; } sprintf(buf, "%04X", idx); strcat(szFile, buf); strcat(szFile, ext); if (!existing) { f = gf_f64_open(szFile, "wb"); if (!f) { gf_free(data); gf_free(iri->string); iri->string = NULL; return GF_IO_ERR; } gf_fwrite(data, data_size, 1, f); fclose(f); } gf_free(data); gf_free(iri->string); iri->string = gf_strdup(szFile); return GF_OK; }
static GF_Err ISMA_Setup(ISMAEAPriv *priv, GF_IPMPEvent *evt) { GF_Err e; GF_ISMACrypConfig *cfg = (GF_ISMACrypConfig*)evt->config_data; priv->state = ISMAEA_STATE_ERROR; if (cfg->scheme_type != GF_4CC('i','A','E','C')) return GF_NOT_SUPPORTED; if (cfg->scheme_version != 1) return GF_NOT_SUPPORTED; if (!cfg->kms_uri) return GF_NON_COMPLIANT_BITSTREAM; /*try to fetch the keys*/ /*base64 inband encoding*/ if (!strnicmp(cfg->kms_uri, "(key)", 5)) { char data[100]; gf_base64_decode((char*)cfg->kms_uri+5, (u32)strlen(cfg->kms_uri)-5, data, 100); memcpy(priv->key, data, sizeof(char)*16); memcpy(priv->salt, data+16, sizeof(char)*8); } /*hexadecimal inband encoding*/ else if (!strnicmp(cfg->kms_uri, "(key-hexa)", 10)) { u32 v; char szT[3], *k; u32 i; szT[2] = 0; if (strlen(cfg->kms_uri) < 10+32+16) return GF_NON_COMPLIANT_BITSTREAM; k = (char *)cfg->kms_uri + 10; for (i=0; i<16; i++) { szT[0] = k[2*i]; szT[1] = k[2*i + 1]; sscanf(szT, "%X", &v); priv->key[i] = v; } k = (char *)cfg->kms_uri + 10 + 32; for (i=0; i<8; i++) { szT[0] = k[2*i]; szT[1] = k[2*i + 1]; sscanf(szT, "%X", &v); priv->salt[i] = v; } } /*MPEG4-IP KMS*/ else if (!stricmp(cfg->kms_uri, "AudioKey") || !stricmp(cfg->kms_uri, "VideoKey")) { if (!gf_ismacryp_mpeg4ip_get_info((char *) cfg->kms_uri, priv->key, priv->salt)) { return GF_BAD_PARAM; } } /*gpac default scheme is used, fetch file from KMS and load keys*/ else if (cfg->scheme_uri && !stricmp(cfg->scheme_uri, "urn:gpac:isma:encryption_scheme")) { e = ISMA_GetGPAC_KMS(priv, evt->channel, cfg->kms_uri); if (e) return e; } /*hardcoded keys*/ else { static u8 mysalt[] = { 8,7,6,5,4,3,2,1, 0,0,0,0,0,0,0,0 }; static u8 mykey[][16] = { { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 } }; memcpy(priv->salt, mysalt, sizeof(char)*8); memcpy(priv->key, mykey, sizeof(char)*16); } priv->state = ISMAEA_STATE_SETUP; //priv->nb_allow_play = 1; return GF_OK; }
RTPStream *RP_NewStream(RTPClient *rtp, GF_SDPMedia *media, GF_SDPInfo *sdp, RTPStream *input_stream) { GF_RTSPRange *range; RTPStream *tmp; GF_RTPMap *map; u32 i, ESID, ODID, ssrc, rtp_seq, rtp_time; Bool force_bcast = 0; Double Start, End; Float CurrentTime; u16 rvc_predef = 0; char *rvc_config_att = NULL; u32 s_port_first, s_port_last; GF_X_Attribute *att; Bool is_migration = 0; char *ctrl; GF_SDPConnection *conn; GF_RTSPTransport trans; u32 mid, prev_stream, base_stream; //extract all relevant info from the GF_SDPMedia Start = 0.0; End = -1.0; CurrentTime = 0.0f; ODID = 0; ESID = 0; ctrl = NULL; range = NULL; s_port_first = s_port_last = 0; ssrc = rtp_seq = rtp_time = 0; mid = prev_stream = base_stream = 0; i=0; while ((att = (GF_X_Attribute*)gf_list_enum(media->Attributes, &i))) { if (!stricmp(att->Name, "control")) ctrl = att->Value; else if (!stricmp(att->Name, "gpac-broadcast")) force_bcast = 1; else if (!stricmp(att->Name, "mpeg4-esid") && att->Value) ESID = atoi(att->Value); else if (!stricmp(att->Name, "mpeg4-odid") && att->Value) ODID = atoi(att->Value); else if (!stricmp(att->Name, "range") && !range) range = gf_rtsp_range_parse(att->Value); else if (!stricmp(att->Name, "x-stream-state") ) { sscanf(att->Value, "server-port=%u-%u;ssrc=%X;npt=%g;seq=%u;rtptime=%u", &s_port_first, &s_port_last, &ssrc, &CurrentTime, &rtp_seq, &rtp_time); is_migration = 1; } else if (!stricmp(att->Name, "x-server-port") ) { sscanf(att->Value, "%u-%u", &s_port_first, &s_port_last); } else if (!stricmp(att->Name, "rvc-config-predef")) { rvc_predef = atoi(att->Value); } else if (!stricmp(att->Name, "rvc-config")) { rvc_config_att = att->Value; } else if (!stricmp(att->Name, "mid")) { sscanf(att->Value, "L%d", &mid); } else if (!stricmp(att->Name, "depend")) { char buf[3000]; memset(buf, 0, 3000); sscanf(att->Value, "%*d lay L%d %*s %s", &base_stream, buf); if (!strlen(buf)) sscanf(att->Value, "%*d lay %s", buf); sscanf(buf, "L%d", &prev_stream); } } if (range) { Start = range->start; End = range->end; gf_rtsp_range_del(range); } /*check connection*/ conn = sdp->c_connection; if (conn && (!conn->host || !strcmp(conn->host, "0.0.0.0"))) conn = NULL; if (!conn) conn = (GF_SDPConnection*)gf_list_get(media->Connections, 0); if (conn && (!conn->host || !strcmp(conn->host, "0.0.0.0"))) conn = NULL; if (!conn) { /*RTSP RFC recommends an empty "c= " line but some server don't send it. Use session info (o=)*/ if (!sdp->o_net_type || !sdp->o_add_type || strcmp(sdp->o_net_type, "IN")) return NULL; if (strcmp(sdp->o_add_type, "IP4") && strcmp(sdp->o_add_type, "IP6")) return NULL; } else { if (strcmp(conn->net_type, "IN")) return NULL; if (strcmp(conn->add_type, "IP4") && strcmp(conn->add_type, "IP6")) return NULL; } /*do we support transport*/ if (strcmp(media->Profile, "RTP/AVP") && strcmp(media->Profile, "RTP/AVP/TCP") && strcmp(media->Profile, "RTP/SAVP") && strcmp(media->Profile, "RTP/SAVP/TCP") ) return NULL; /*check RTP map. For now we only support 1 RTPMap*/ if (media->fmt_list || (gf_list_count(media->RTPMaps) > 1)) return NULL; /*check payload type*/ map = (GF_RTPMap*)gf_list_get(media->RTPMaps, 0); /*this is an ESD-URL setup, we likely have namespace conflicts so overwrite given ES_ID by the app one (client side), but keep control (server side) if provided*/ if (input_stream) { ESID = input_stream->ES_ID; if (!ctrl) ctrl = input_stream->control; tmp = input_stream; } else { tmp = RP_FindChannel(rtp, NULL, ESID, NULL, 0); if (tmp) return NULL; GF_SAFEALLOC(tmp, RTPStream); tmp->owner = rtp; } /*create an RTP channel*/ tmp->rtp_ch = gf_rtp_new(); if (ctrl) tmp->control = gf_strdup(ctrl); tmp->ES_ID = ESID; tmp->OD_ID = ODID; tmp->mid = mid; tmp->prev_stream = prev_stream; tmp->base_stream = base_stream; memset(&trans, 0, sizeof(GF_RTSPTransport)); trans.Profile = media->Profile; trans.source = conn ? conn->host : sdp->o_address; trans.IsUnicast = gf_sk_is_multicast_address(trans.source) ? 0 : 1; if (!trans.IsUnicast) { trans.port_first = media->PortNumber; trans.port_last = media->PortNumber + 1; trans.TTL = conn ? conn->TTL : 0; } else { trans.client_port_first = media->PortNumber; trans.client_port_last = media->PortNumber + 1; trans.port_first = s_port_first ? s_port_first : trans.client_port_first; trans.port_last = s_port_last ? s_port_last : trans.client_port_last; } if (gf_rtp_setup_transport(tmp->rtp_ch, &trans, NULL) != GF_OK) { RP_DeleteStream(tmp); return NULL; } /*setup depacketizer*/ tmp->depacketizer = gf_rtp_depacketizer_new(media, rtp_sl_packet_cbk, tmp); if (!tmp->depacketizer) { RP_DeleteStream(tmp); return NULL; } /*setup channel*/ gf_rtp_setup_payload(tmp->rtp_ch, map); // tmp->status = NM_Disconnected; ctrl = (char *) gf_modules_get_option((GF_BaseInterface *) gf_term_get_service_interface(rtp->service), "Streaming", "DisableRTCP"); if (!ctrl || stricmp(ctrl, "yes")) tmp->flags |= RTP_ENABLE_RTCP; /*setup NAT keep-alive*/ ctrl = (char *) gf_modules_get_option((GF_BaseInterface *) gf_term_get_service_interface(rtp->service), "Streaming", "NATKeepAlive"); if (ctrl) gf_rtp_enable_nat_keepalive(tmp->rtp_ch, atoi(ctrl)); tmp->range_start = Start; tmp->range_end = End; if (End != -1.0) tmp->flags |= RTP_HAS_RANGE; if (force_bcast) tmp->flags |= RTP_FORCE_BROADCAST; if (is_migration) { tmp->current_start = (Double) CurrentTime; tmp->check_rtp_time = RTP_SET_TIME_RTP; gf_rtp_set_info_rtp(tmp->rtp_ch, rtp_seq, rtp_time, ssrc); tmp->status = RTP_SessionResume; } if (rvc_predef) { tmp->depacketizer->sl_map.rvc_predef = rvc_predef ; } else if (rvc_config_att) { char *rvc_data=NULL; u32 rvc_size; Bool is_gz = 0; if (!strncmp(rvc_config_att, "data:application/rvc-config+xml", 32) && strstr(rvc_config_att, "base64") ) { char *data = strchr(rvc_config_att, ','); if (data) { rvc_size = (u32) strlen(data) * 3 / 4 + 1; rvc_data = gf_malloc(sizeof(char) * rvc_size); rvc_size = gf_base64_decode(data, (u32) strlen(data), rvc_data, rvc_size); rvc_data[rvc_size] = 0; } if (!strncmp(rvc_config_att, "data:application/rvc-config+xml+gz", 35)) is_gz = 1; } else if (!strnicmp(rvc_config_att, "http://", 7) || !strnicmp(rvc_config_att, "https://", 8) ) { char *mime; if (gf_dm_get_file_memory(rvc_config_att, &rvc_data, &rvc_size, &mime) == GF_OK) { if (mime && strstr(mime, "+gz")) is_gz = 1; if (mime) gf_free(mime); } } if (rvc_data) { if (is_gz) { #ifdef GPAC_DISABLE_ZLIB fprintf(stderr, "Error: no zlib support - RVC not supported in RTP\n"); return NULL; #endif gf_gz_decompress_payload(rvc_data, rvc_size, &tmp->depacketizer->sl_map.rvc_config, &tmp->depacketizer->sl_map.rvc_config_size); gf_free(rvc_data); } else { tmp->depacketizer->sl_map.rvc_config = rvc_data; tmp->depacketizer->sl_map.rvc_config_size = rvc_size; } } } return tmp; }
int main(int argc, char **argv) { /********************/ /* declarations */ /********************/ char *input, *output, tmpstr[GF_MAX_PATH]; GF_ISOFile *isom_file_in; GF_MediaImporter import; AdobeHDSCtx ctx; GF_Err e; u32 i; /*****************/ /* gpac init */ /*****************/ gf_sys_init(GF_MemTrackerNone); gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_WARNING); /***********************/ /* initialisations */ /***********************/ input = NULL; output = NULL; isom_file_in = NULL; memset(&import, 0, sizeof(GF_MediaImporter)); e = GF_OK; memset(&ctx, 0, sizeof(ctx)); ctx.curr_time = 0; ctx.segnum = 1; /*********************************************/ /* parse arguments and build HDS context */ /*********************************************/ if (GF_OK != parse_args(argc, argv, &input, &output, &ctx.curr_time, &ctx.segnum)) { usage(argv[0]); goto exit; } ctx.multirate_manifest = adobe_alloc_multirate_manifest(output); #if 0 /*'moov' conversion tests*/ { char metamoov64[GF_MAX_PATH]; u32 metamoov64_len; unsigned char metamoov[GF_MAX_PATH]; u32 metamoov_len=GF_MAX_PATH; FILE *f = gf_fopen("metamoov64"/*input*/, "rt"); gf_fseek(f, 0, SEEK_END); metamoov64_len = (u32)gf_ftell(f); gf_fseek(f, 0, SEEK_SET); fread(metamoov64, metamoov64_len, 1, f); metamoov_len = gf_base64_decode(metamoov64, metamoov64_len, metamoov, metamoov_len); gf_fclose(f); f = gf_fopen("metamoov", "wb"); fwrite(metamoov, metamoov_len, 1, f); gf_fclose(f); return 0; } #endif #if 0 /*'abst'conversion tests*/ { char bootstrap64[GF_MAX_PATH]; u32 bootstrap64_len; unsigned char bootstrap[GF_MAX_PATH]; u32 bootstrap_len=GF_MAX_PATH; GF_AdobeBootstrapInfoBox *abst = (GF_AdobeBootstrapInfoBox *)abst_New(); GF_BitStream *bs; #if 1 //64 FILE *f = gf_fopen("bootstrap64"/*input*/, "rt"); gf_fseek(f, 0, SEEK_END); bootstrap64_len = (u32)gf_ftell(f); gf_fseek(f, 0, SEEK_SET); fread(bootstrap64, bootstrap64_len, 1, f); bootstrap_len = gf_base64_decode(bootstrap64, bootstrap64_len, bootstrap, bootstrap_len); #else //binary bootstrap FILE *f = gf_fopen("bootstrap.bin"/*input*/, "rb"); gf_fseek(f, 0, SEEK_END); bootstrap_len = (u32)gf_ftell(f); gf_fseek(f, 0, SEEK_SET); fread(bootstrap, bootstrap_len, 1, f); #endif bs = gf_bs_new(bootstrap+8, bootstrap_len-8, GF_BITSTREAM_READ); abst->size = bootstrap[2]*256+bootstrap[3]; assert(abst->size<GF_MAX_PATH); abst_Read((GF_Box*)abst, bs); gf_bs_del(bs); //then rewrite with just one 'afrt' memset(bootstrap, 0, bootstrap_len); bs = gf_bs_new(bootstrap, bootstrap_len, GF_BITSTREAM_WRITE); abst_Write((GF_Box*)abst, bs); bootstrap_len = (u32)gf_bs_get_position(bs); gf_bs_del(bs); gf_fclose(f); f = gf_fopen("bootstrap", "wt"); bootstrap64_len = gf_base64_encode(bootstrap, bootstrap_len, bootstrap64, GF_MAX_PATH); fwrite(bootstrap64, bootstrap64_len, 1, f); fprintf(f, "\n\n"); abst_dump((GF_Box*)abst, f); gf_fclose(f); abst_del((GF_Box*)abst); return 0; } #endif /*****************/ /* main loop */ /*****************/ import.trackID = 0; import.in_name = input; import.flags = GF_IMPORT_PROBE_ONLY; //create output or open when recovering from a saved state sprintf(tmpstr, "%s_import.mp4", input); isom_file_in = gf_isom_open(tmpstr, GF_ISOM_WRITE_EDIT, NULL); if (!isom_file_in) { fprintf(stderr, "Error opening output file %s: %s\n", tmpstr, gf_error_to_string(e)); assert(0); goto exit; } import.dest = isom_file_in; //probe input e = gf_media_import(&import); if (e) { fprintf(stderr, "Error while importing input file %s: %s\n", input, gf_error_to_string(e)); assert(0); goto exit; } //import input data import.flags = 0; for (i=0; i<import.nb_tracks; i++) { import.trackID = import.tk_info[i].track_num; e = gf_media_import(&import); if (e) { fprintf(stderr, "Error while importing track number %u, input file %s: %s\n", import.trackID, input, gf_error_to_string(e)); assert(0); goto exit; } } //Adobe specific stuff e = adobize_segment(isom_file_in, &ctx); if (e) { fprintf(stderr, "Couldn't turn the ISOM fragmented file into an Adobe f4v segment: %s\n", gf_error_to_string(e)); assert(0); goto exit; } //interleave data and remove imported file //FIXME: set multiple fragments: sprintf(tmpstr, "%s_HD_100_Seg%u-Frag1", output, ctx.segnum); //FIXME: "HD", "100" and fragnum: pass as arg //e = gf_media_fragment_file(isom_file_in, tmpstr, 1.0); e = gf_media_fragment_file(isom_file_in, tmpstr, 1.0+gf_isom_get_duration(isom_file_in)/gf_isom_get_timescale(isom_file_in)); if (e) { fprintf(stderr, "Error while fragmenting file to output %s: %s\n", output, gf_error_to_string(e)); assert(0); goto exit; } gf_isom_delete(isom_file_in); isom_file_in = NULL; e = adobe_gen_multirate_manifest(ctx.multirate_manifest, ctx.bootstrap, ctx.bootstrap_size); if (e) { fprintf(stderr, "Couldn't generate Adobe f4m manifest: %s\n", gf_error_to_string(e)); assert(0); goto exit; } exit: //delete intermediate mp4 file if (isom_file_in) gf_isom_delete(isom_file_in); if (ctx.multirate_manifest) adobe_free_multirate_manifest(ctx.multirate_manifest); if (ctx.bootstrap) { gf_free(ctx.bootstrap); //ctx.bootstrap = NULL; //ctx.bootstrap_size = 0; } gf_sys_close(); return !e ? 0 : 1; }