u32 RP_Thread(void *param) { u32 i; GF_NetworkCommand com; RTSPSession *sess; RTPStream *ch; RTPClient *rtp = (RTPClient *)param; rtp->th_state = 1; com.command_type = GF_NET_CHAN_BUFFER_QUERY; while (rtp->th_state) { gf_mx_p(rtp->mx); /*fecth data on udp*/ i=0; while ((ch = (RTPStream *)gf_list_enum(rtp->channels, &i))) { if ((ch->flags & RTP_EOS) || (ch->status!=RTP_Running) ) continue; /*for interleaved channels don't read too fast, query the buffer occupancy*/ if (ch->flags & RTP_INTERLEAVED) { com.base.on_channel = ch->channel; gf_term_on_command(rtp->service, &com, GF_OK); /*if no buffering, use a default value (3 sec of data should do it)*/ if (!com.buffer.max) com.buffer.max = 3000; if (com.buffer.occupancy <= com.buffer.max) ch->rtsp->flags |= RTSP_TCP_FLUSH; } else { RP_ReadStream(ch); } } /*and process commands / flush TCP*/ i=0; while ((sess = (RTSPSession *)gf_list_enum(rtp->sessions, &i))) { RP_ProcessCommands(sess); if (sess->connect_error) { gf_term_on_connect(sess->owner->service, NULL, sess->connect_error); sess->connect_error = 0; } } gf_mx_v(rtp->mx); gf_sleep(1); } if (rtp->dnload) gf_term_download_del(rtp->dnload); rtp->dnload = NULL; rtp->th_state = 2; return 0; }
static GF_Err AC3_CloseService(GF_InputService *plug) { AC3Reader *read = plug->priv; if (read->stream) fclose(read->stream); read->stream = NULL; if (read->dnload) gf_term_download_del(read->dnload); read->dnload = NULL; if (read->data) gf_free(read->data); read->data = NULL; gf_term_on_disconnect(read->service, NULL, GF_OK); return GF_OK; }
static GF_Err M2TS_CloseService(GF_InputService *plug) { M2TSIn *m2ts = plug->priv; GF_M2TS_Demuxer* ts = m2ts->ts; TSDemux_CloseDemux(ts); if (ts->dnload) gf_term_download_del(ts->dnload); ts->dnload = NULL; gf_term_on_disconnect(m2ts->service, NULL, GF_OK); return GF_OK; }
static GF_Err SAF_CloseService(GF_InputService *plug) { SAFIn *read = (SAFIn *)plug->priv; if (read->th) { if (read->run_state == 1) { read->run_state=0; while (read->run_state!=2) gf_sleep(2); } gf_th_del(read->th); read->th = NULL; } if (read->stream) fclose(read->stream); read->stream = NULL; if (read->dnload) gf_term_download_del(read->dnload); read->dnload = NULL; gf_term_on_disconnect(read->service, NULL, GF_OK); return GF_OK; }
static GF_Err TTIn_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url) { GF_Err e; TTIn *tti = (TTIn *)plug->priv; if (!plug || !url) return GF_BAD_PARAM; tti->service = serv; if (tti->dnload) gf_term_download_del(tti->dnload); tti->dnload = NULL; /*remote fetch*/ if (!TTIn_is_local(url)) { TTIn_download_file(plug, url); return GF_OK; } e = TTIn_LoadFile(plug, url, 0); gf_term_on_connect(serv, NULL, e); if (!e && !tti->od_done) tti_setup_object(tti); return GF_OK; }
GF_Err ISOR_CloseService(GF_InputService *plug) { GF_Err reply; ISOMReader *read; if (!plug || !plug->priv) return GF_SERVICE_ERROR; read = (ISOMReader *) plug->priv; reply = GF_OK; if (read->mov) gf_isom_close(read->mov); read->mov = NULL; while (gf_list_count(read->channels)) { ISOMChannel *ch = (ISOMChannel *)gf_list_get(read->channels, 0); gf_list_rem(read->channels, 0); isor_delete_channel(read, ch); } if (read->dnload) gf_term_download_del(read->dnload); read->dnload = NULL; gf_term_on_disconnect(read->service, NULL, reply); return GF_OK; }
static GF_Err VTT_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url) { GF_Err e; VTTIn *vttin = (VTTIn *)plug->priv; if (!plug || !url) return GF_BAD_PARAM; vttin->service = serv; if (vttin->dnload) gf_term_download_del(vttin->dnload); vttin->dnload = NULL; /*remote fetch*/ if (!VTT_is_local(url)) { VTT_download_file(plug, url); return GF_OK; } else { e = GF_OK; //e = TTIn_LoadFile(plug, url, 0); gf_term_on_connect(serv, NULL, e); //if (!e && !vttin->od_done) tti_setup_object(vttin); } return GF_OK; }
static GF_Err MP3_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url) { char szURL[2048]; u32 minSizeToRead = 0; char *ext; GF_Err reply; MP3Reader *read = plug->priv; read->service = serv; if (read->dnload) gf_term_download_del(read->dnload); read->dnload = NULL; strcpy(szURL, url); ext = strrchr(szURL, '#'); if (ext) ext[0] = 0; /*remote fetch*/ read->is_remote = !mp3_is_local(szURL); if (read->is_remote) { mp3_download_file(plug, (char *) szURL); return GF_OK; } reply = GF_OK; read->stream = gf_f64_open(szURL, "rb"); if (!read->stream) { reply = GF_URL_ERROR; } else if (!MP3_ConfigureFromFile(read, &minSizeToRead)) { fclose(read->stream); read->stream = NULL; reply = GF_NOT_SUPPORTED; } gf_term_on_connect(serv, NULL, reply); if (!reply) mp3_setup_object(read); return GF_OK; }
static GF_Err SAF_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url) { char szURL[2048]; char *ext; SAFIn *read = (SAFIn *)plug->priv; read->service = serv; if (read->dnload) gf_term_download_del(read->dnload); read->dnload = NULL; strcpy(szURL, url); ext = strrchr(szURL, '#'); if (ext) ext[0] = 0; read->needs_connection = 1; read->duration = 0; read->saf_type = SAF_FILE_LOCAL; /*remote fetch*/ if (strnicmp(url, "file://", 7) && strstr(url, "://")) { read->saf_type = SAF_FILE_REMOTE; SAF_DownloadFile(plug, (char *) szURL); return GF_OK; } read->stream = gf_f64_open(szURL, "rb"); if (!read->stream) { gf_term_on_connect(serv, NULL, GF_URL_ERROR); return GF_OK; } SAF_CheckFile(read); read->th = gf_th_new("SAFDemux"); /*start playing for tune-in*/ gf_th_run(read->th, SAF_Run, read); return GF_OK; }
void mpdin_dash_io_del(GF_DASHFileIO *dashio, GF_DASHFileIOSession session) { gf_term_download_del((GF_DownloadSession *)session); }
GF_Err RP_ConnectServiceEx(GF_InputService *plug, GF_ClientService *serv, const char *url, Bool skip_migration) { char *session_cache; RTSPSession *sess; RTPClient *priv = (RTPClient *)plug->priv; /*store user address*/ priv->service = serv; if (priv->dnload) gf_term_download_del(priv->dnload); priv->dnload = NULL; GF_LOG(GF_LOG_INFO, GF_LOG_RTP, ("[RTP] Opening service %s\n", url)); /*load preferences*/ RT_LoadPrefs(plug, priv); /*start thread*/ gf_th_run(priv->th, RP_Thread, priv); if (!skip_migration) { session_cache = (char *) gf_modules_get_option((GF_BaseInterface *) plug, "Streaming", "SessionMigrationFile"); if (session_cache && session_cache[0]) { FILE *f = gf_f64_open(session_cache, "rb"); if (f) { fclose(f); GF_LOG(GF_LOG_INFO, GF_LOG_RTP, ("[RTP] Restarting RTSP session from %s\n", session_cache)); RP_FetchSDP(priv, (char *) session_cache, NULL, (char *) url); return GF_OK; } if (!strncmp(session_cache, "http://", 7)) { GF_LOG(GF_LOG_INFO, GF_LOG_RTP, ("[RTP] Restarting RTSP session from %s\n", session_cache)); RP_FetchSDP(priv, (char *) session_cache, NULL, (char *) url); return GF_OK; } } } /*local or remote SDP*/ if (strstr(url, "data:application/sdp") || (strnicmp(url, "rtsp", 4) && strstr(url, ".sdp")) ) { RP_FetchSDP(priv, (char *) url, NULL, NULL); return GF_OK; } /*rtsp and rtsp over udp*/ if (!strnicmp(url, "rtsp://", 7) || !strnicmp(url, "rtspu://", 8)) { char *the_url = gf_strdup(url); char *the_ext = strrchr(the_url, '#'); if (the_ext) { if (!stricmp(the_ext, "#audio")) priv->media_type = GF_MEDIA_OBJECT_AUDIO; else if (!stricmp(the_ext, "#video")) priv->media_type = GF_MEDIA_OBJECT_VIDEO; the_ext[0] = 0; } sess = RP_NewSession(priv, (char *) the_url); gf_free(the_url); if (!sess) { gf_term_on_connect(serv, NULL, GF_NOT_SUPPORTED); } else { RP_Describe(sess, 0, NULL); } return GF_OK; } /*direct RTP (no control) or embedded data - this means the service is attached to a single channel (no IOD) reply right away*/ gf_term_on_connect(serv, NULL, GF_OK); RP_SetupObjects(priv); return GF_OK; }
void RP_SaveSessionState(RTPClient *rtp) { GF_Err e; char *sdp_buf; const char *opt; GF_X_Attribute*att; u32 i, j; GF_SDPInfo *sdp; RTSPSession *sess = NULL; if (!rtp->session_state_data) return; sdp_buf = rtp->session_state_data + strlen("data:application/sdp,"); sdp = gf_sdp_info_new(); e = gf_sdp_info_parse(sdp, sdp_buf, (u32) strlen(sdp_buf) ); for (i=0; i<gf_list_count(rtp->channels); i++) { GF_SDPMedia *media = NULL; RTPStream *ch = gf_list_get(rtp->channels, i); if (!ch->control) continue; for (j=0; j<gf_list_count(sdp->media_desc); j++) { u32 k; GF_SDPMedia *med = (GF_SDPMedia*)gf_list_get(sdp->media_desc, j); for (k=0; k<gf_list_count(med->Attributes); k++) { att = (GF_X_Attribute*)gf_list_get(med->Attributes, k); if (!stricmp(att->Name, "control") && (strstr(att->Value, ch->control)!=NULL) ) { media = med; break; } } if (media) break; } if (!media) continue; if (ch->rtp_ch->net_info.IsUnicast) { char szPorts[4096]; u16 porta, portb; media->PortNumber = ch->rtp_ch->net_info.client_port_first; /*remove x-server-port extension*/ for (j=0; j<gf_list_count(media->Attributes); j++) { att = (GF_X_Attribute*)gf_list_get(media->Attributes, j); if (!stricmp(att->Name, "x-stream-state") ) { gf_free(att->Name); gf_free(att->Value); gf_free(att); gf_list_rem(media->Attributes, j); } } ch->current_start += gf_rtp_get_current_time(ch->rtp_ch); GF_SAFEALLOC(att, GF_X_Attribute); att->Name = gf_strdup("x-stream-state"); porta = ch->rtp_ch->net_info.port_first ? ch->rtp_ch->net_info.port_first : ch->rtp_ch->net_info.client_port_first; portb = ch->rtp_ch->net_info.port_last ? ch->rtp_ch->net_info.port_last : ch->rtp_ch->net_info.client_port_last; sprintf(szPorts, "server-port=%d-%d;ssrc=%X;npt=%g;seq=%d;rtptime=%d", porta, portb, ch->rtp_ch->SenderSSRC, ch->current_start, ch->rtp_ch->rtp_first_SN, ch->rtp_ch->rtp_time ); att->Value = gf_strdup(szPorts); gf_list_add(media->Attributes, att); if (ch->rtsp) sess = ch->rtsp; } else { media->PortNumber = ch->rtp_ch->net_info.port_first; } } /*remove x-server-port/x-session-id extension*/ for (j=0; j<gf_list_count(sdp->Attributes); j++) { att = (GF_X_Attribute*)gf_list_get(sdp->Attributes, j); if (!stricmp(att->Name, "x-session-id") || !stricmp(att->Name, "x-session-name") ) { gf_free(att->Name); gf_free(att->Value); gf_free(att); gf_list_rem(sdp->Attributes, j); } } if (sess) { char szURL[4096]; if (sess->session_id) { GF_SAFEALLOC(att, GF_X_Attribute); att->Name = gf_strdup("x-session-id"); att->Value = gf_strdup(sess->session_id); gf_list_add(sdp->Attributes, att); } GF_SAFEALLOC(att, GF_X_Attribute); att->Name = gf_strdup("x-session-name"); sprintf(szURL, "rtsp://%s:%d/%s", sess->session->Server, sess->session->Port, sess->session->Service); att->Value = gf_strdup(szURL); gf_list_add(sdp->Attributes, att); } gf_free(rtp->session_state_data); sdp_buf = NULL; gf_sdp_info_write(sdp, &sdp_buf); if (sdp_buf) { rtp->session_state_data = gf_malloc(sizeof(char) * (strlen("data:application/sdp,") + strlen(sdp_buf) + 1) ); strcpy(rtp->session_state_data, "data:application/sdp,"); strcat(rtp->session_state_data, sdp_buf); gf_free(sdp_buf); } gf_sdp_info_del(sdp); opt = (char *) gf_modules_get_option((GF_BaseInterface *) gf_term_get_service_interface(rtp->service), "Streaming", "SessionMigrationServer"); if (opt) { if (rtp->dnload) gf_term_download_del(rtp->dnload); rtp->dnload = NULL; if (strnicmp(opt, "http://", 7)) { rtp->dnload = gf_term_download_new(rtp->service, opt, GF_NETIO_SESSION_NOT_THREADED, MigrateSDP_NetIO, rtp); while (1) { char buffer[100]; u32 read; e = gf_dm_sess_fetch_data(rtp->dnload, buffer, 100, &read); if (e && (e!=GF_IP_NETWORK_EMPTY)) break; } gf_term_download_del(rtp->dnload); rtp->dnload = NULL; } else { FILE *f = gf_f64_open(opt, "wt"); if (f) { sdp_buf = rtp->session_state_data + strlen("data:application/sdp,"); gf_fwrite(sdp_buf, 1, strlen(sdp_buf), f); fclose(f); } else { e = GF_IO_ERR; } } if (e<0) { gf_term_on_message(sess->owner->service, e, "Error saving session state"); } } }
GF_Err DC_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url) { DCReader *read = (DCReader *) plug->priv; FILE *test; char *tmp, *ext; if (!read || !serv || !url) return GF_BAD_PARAM; if (read->dnload) gf_term_download_del(read->dnload); read->dnload = NULL; read->url = gf_strdup(url); ext = strchr(read->url, '#'); if (ext) { char *anext; ext[0] = 0; anext = strrchr(read->url, '.'); ext[0] = '#'; ext = anext; } else { ext = strrchr(read->url, '.'); } if (ext && !stricmp(ext, ".gz")) { char *anext; ext[0] = 0; anext = strrchr(read->url, '.'); ext[0] = '.'; ext = anext; } read->service = serv; if (ext) { char *cgi_par = NULL; ext += 1; if (ext) { tmp = strchr(ext, '#'); if (tmp) tmp[0] = 0; /* Warning the '?' sign should not be present in local files but it is convenient to have it to test web content locally */ cgi_par = strchr(ext, '?'); if (cgi_par) cgi_par[0] = 0; } if (!stricmp(ext, "bt") || !stricmp(ext, "btz") || !stricmp(ext, "bt.gz") || !stricmp(ext, "xmta") || !stricmp(ext, "xmt") || !stricmp(ext, "xmt.gz") || !stricmp(ext, "xmtz") || !stricmp(ext, "wrl") || !stricmp(ext, "wrl.gz") || !stricmp(ext, "x3d") || !stricmp(ext, "x3d.gz") || !stricmp(ext, "x3dz") || !stricmp(ext, "x3dv") || !stricmp(ext, "x3dv.gz") || !stricmp(ext, "x3dvz") || !stricmp(ext, "swf") ) read->oti = GPAC_OTI_PRIVATE_SCENE_GENERIC; else if (!stricmp(ext, "svg") || !stricmp(ext, "svgz") || !stricmp(ext, "svg.gz")) { read->oti = GPAC_OTI_PRIVATE_SCENE_SVG; } /*XML LASeR*/ else if (!stricmp(ext, "xsr")) read->oti = GPAC_OTI_PRIVATE_SCENE_LASER; else if (!stricmp(ext, "xbl")) read->oti = GPAC_OTI_PRIVATE_SCENE_XBL; else if (!stricmp(ext, "wgt") || !stricmp(ext, "mgt")) read->oti = GPAC_OTI_PRIVATE_SCENE_WGT; if (cgi_par) cgi_par[0] = '?'; } if (!read->oti && (!strnicmp(url, "file://", 7) || !strstr(url, "://"))) { char *rtype = gf_xml_get_root_type(url, NULL); if (rtype) { if (!strcmp(rtype, "SAFSession")) read->oti = GPAC_OTI_PRIVATE_SCENE_LASER; else if (!strcmp(rtype, "svg")) read->oti = GPAC_OTI_PRIVATE_SCENE_SVG; else if (!strcmp(rtype, "XMT-A")) read->oti = GPAC_OTI_PRIVATE_SCENE_GENERIC; else if (!strcmp(rtype, "X3D")) read->oti = GPAC_OTI_PRIVATE_SCENE_GENERIC; else if (!strcmp(rtype, "bindings")) read->oti = GPAC_OTI_PRIVATE_SCENE_XBL; else if (!strcmp(rtype, "widget")) read->oti = GPAC_OTI_PRIVATE_SCENE_WGT; gf_free(rtype); } } /*remote fetch*/ if (!strnicmp(url, "file://", 7)) { url += 7; } else if (strstr(url, "://")) { DC_DownloadFile(plug, read->url); return GF_OK; } test = gf_f64_open(read->url, "rt"); if (!test) { gf_term_on_connect(serv, NULL, GF_URL_ERROR); return GF_OK; } fclose(test); if (!read->is_service_connected) { gf_term_on_connect(serv, NULL, GF_OK); read->is_service_connected = 1; } return GF_OK; }
void m2ts_net_io(void *cbk, GF_NETIO_Parameter *param) { GF_Err e; M2TSIn *m2ts = (M2TSIn *) cbk; assert( m2ts ); /*handle service message*/ gf_term_download_update_stats(m2ts->ts->dnload); if (param->msg_type==GF_NETIO_DATA_TRANSFERED) { e = GF_EOS; } else if (param->msg_type==GF_NETIO_DATA_EXCHANGE) { e = GF_OK; assert( m2ts->ts); if (param->size > 0){ /*process chunk*/ assert(param->data); if (m2ts->network_buffer_size < param->size){ m2ts->network_buffer = gf_realloc(m2ts->network_buffer, sizeof(char) * param->size); m2ts->network_buffer_size = param->size; } assert( m2ts->network_buffer ); memcpy(m2ts->network_buffer, param->data, param->size); gf_m2ts_process_data(m2ts->ts, m2ts->network_buffer, param->size); } /*if asked to regulate, wait until we get a play request*/ if (m2ts->ts->run_state && !m2ts->ts->nb_playing && (m2ts->ts->file_regulate==1)) { while (m2ts->ts->run_state && !m2ts->ts->nb_playing && (m2ts->ts->file_regulate==1) ) { gf_sleep(50); continue; } } else { gf_sleep(1); } #if 1 //see commit 3642: crashes when reload quickly with http if (!m2ts->ts->run_state) { if (m2ts->ts->dnload) gf_term_download_del( m2ts->ts->dnload ); m2ts->ts->dnload = NULL; } #endif } else { e = param->error; } switch (e){ case GF_EOS: if (!m2ts->is_connected) { gf_term_on_connect(m2ts->service, NULL, GF_OK); } return; case GF_OK: return; default: if (!m2ts->ts_setup) { m2ts->ts_setup = 1; } GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER,("[MPEGTSIn] : Error while getting data : %s\n", gf_error_to_string(e))); gf_term_on_connect(m2ts->service, NULL, e); } }