void RP_SetupObjects(RTPClient *rtp) { GF_ObjectDescriptor *od; RTPStream *ch; u32 i; /*add everything*/ i=0; while ((ch = (RTPStream *)gf_list_enum(rtp->channels, &i))) { if (ch->control && !strnicmp(ch->control, "data:", 5)) continue; if (ch->prev_stream) continue; if (!rtp->media_type) { od = RP_GetChannelOD(ch, i); if (!od) continue; gf_term_add_media(rtp->service, (GF_Descriptor*)od, 1); } else if (rtp->media_type==ch->depacketizer->sl_map.StreamType) { od = RP_GetChannelOD(ch, i); if (!od) continue; gf_term_add_media(rtp->service, (GF_Descriptor*)od, 1); rtp->media_type = 0; break; } } gf_term_add_media(rtp->service, NULL, 0); }
static void MP2TS_DeclareStream(M2TSIn *m2ts, GF_M2TS_PES *stream, char *dsi, u32 dsi_size) { GF_ObjectDescriptor *od = MP2TS_GetOD(m2ts, stream, dsi, dsi_size, NULL); if (!od) return; /*declare but don't regenerate scene*/ gf_term_add_media(m2ts->service, (GF_Descriptor*)od, 1); }
static void tti_setup_object(TTIn *tti) { GF_ObjectDescriptor *od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); GF_ESD *esd = tti_get_esd(tti); od->objectDescriptorID = esd->ESID; gf_list_add(od->ESDescriptors, esd); gf_term_add_media(tti->service, (GF_Descriptor *)od, 0); }
static void AC3_SetupObject(AC3Reader *read) { GF_ESD *esd; GF_ObjectDescriptor *od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); od->objectDescriptorID = 1; esd = AC3_GetESD(read); esd->OCRESID = 0; gf_list_add(od->ESDescriptors, esd); gf_term_add_media(read->service, (GF_Descriptor*)od, 0); }
static u32 ext_media_load_th(void *par) { GF_HYBMEDIA *self = (GF_HYBMEDIA*) par; /*declare object to terminal*/ GF_ObjectDescriptor *od = (GF_ObjectDescriptor*)gf_odf_desc_new(GF_ODF_OD_TAG); od->URLString = gf_strdup("http://gpac.sourceforge.net/screenshots/lion.jpg"); od->objectDescriptorID = 0; gf_sleep(2000); //TODO: remove the sleep gf_term_add_media(self->owner, (GF_Descriptor*)od, 0); return 0; }
static void mp3_setup_object(MP3Reader *read) { if (read->is_inline) { GF_ESD *esd; GF_ObjectDescriptor *od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); od->objectDescriptorID = 1; esd = MP3_GetESD(read); gf_list_add(od->ESDescriptors, esd); gf_term_add_media(read->service, (GF_Descriptor*)od, 0); } }
static void FFD_SetupObjects(FFDemux *ffd) { GF_ESD *esd; GF_ObjectDescriptor *od; u32 audio_esid = 0; if ((ffd->audio_st>=0) && (ffd->service_type != 1)) { od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); esd = FFD_GetESDescriptor(ffd, 1); od->objectDescriptorID = esd->ESID; audio_esid = esd->ESID; gf_list_add(od->ESDescriptors, esd); gf_term_add_media(ffd->service, (GF_Descriptor*)od, (ffd->video_st>=0) ? 1 : 0); } if ((ffd->video_st>=0) && (ffd->service_type != 2)) { od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); esd = FFD_GetESDescriptor(ffd, 0); od->objectDescriptorID = esd->ESID; esd->OCRESID = audio_esid; gf_list_add(od->ESDescriptors, esd); gf_term_add_media(ffd->service, (GF_Descriptor*)od, 0); } }
static GF_Err HYB_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url) { u32 i; GF_Err e = GF_OK; const size_t nb_masters = sizeof(hyb_masters) / sizeof(GF_HYBMEDIA*); GF_HYB_In *hyb_in = (GF_HYB_In*)plug->priv; GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[HYB_IN] Received Connection request from service %p for %s\n", serv, url)); if (!hyb_in || !serv || !url) return GF_BAD_PARAM; hyb_in->service = serv; /*choose the master service*/ for (i=0; i<nb_masters; i++) { if (hyb_masters[i]->CanHandleURL(url)) { hyb_in->master = hyb_masters[i]; break; } } assert(hyb_in->master); /*sanity check about the master*/ e = hybmedia_sanity_check(hyb_in->master); if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[HYB_IN] Error - object \"%s\" failed the sanity checks\n", hyb_in->master->name)); gf_term_on_connect(hyb_in->service, NULL, e); return e; } GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[HYB_IN] Selected master object \"%s\" for URL: %s\n", hyb_in->master->name, url)); /*connect the master*/ e = hyb_in->master->Connect(hyb_in->master, hyb_in->service, url); if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[HYB_IN] Error - cannot connect service, wrong URL %s\n", url)); gf_term_on_connect(hyb_in->service, NULL, GF_BAD_PARAM); return e; } gf_term_on_connect(hyb_in->service, NULL, GF_OK); gf_term_add_media(hyb_in->service, (GF_Descriptor*)hyb_in->master->GetOD(), 0); return GF_OK; }
static void MP2TS_SetupProgram(M2TSIn *m2ts, GF_M2TS_Program *prog, Bool regenerate_scene, Bool no_declare) { u32 i, count; count = gf_list_count(prog->streams); #ifdef GPAC_HAS_LINUX_DVB if (m2ts->ts->tuner) { Bool found = 0; for (i=0; i<count; i++) { GF_M2TS_PES *pes = gf_list_get(prog->streams, i); if (pes->pid==m2ts->ts->tuner->vpid) found = 1; else if (pes->pid==m2ts->ts->tuner->apid) found = 1; } if (!found) return; } #endif /*TS is a file, start regulation regardless of how the TS is access (with or without fragment URI)*/ if (m2ts->ts->file || m2ts->ts->dnload || m2ts->owner->query_proxy) m2ts->ts->file_regulate = 1; for (i=0; i<count; i++) { GF_M2TS_ES *es = gf_list_get(prog->streams, i); if (es->pid==prog->pmt_pid) continue; if ((es->flags & GF_M2TS_ES_IS_PES) && ((GF_M2TS_PES *)es)->depends_on_pid ) continue; /*move to skip mode for all ES until asked for playback*/ if (!es->user) gf_m2ts_set_pes_framing((GF_M2TS_PES *)es, GF_M2TS_PES_FRAMING_SKIP); if (!prog->pmt_iod && !no_declare) { MP2TS_DeclareStream(m2ts, (GF_M2TS_PES *)es, NULL, 0); } /*if IOD, streams not declared through OD framework are refered to by pid:// scheme, and will be declared upon request by the terminal through GetServiceDesc*/ } /*force scene regeneration*/ if (!prog->pmt_iod && regenerate_scene) gf_term_add_media(m2ts->service, NULL, 0); }
void isor_declare_objects(ISOMReader *read) { GF_ObjectDescriptor *od; GF_ESD *esd; const char *tag; u32 i, count, ocr_es_id, tlen, base_track, j, track_id; Bool highest_stream; char *opt; Bool add_ps_lower = GF_TRUE; ocr_es_id = 0; opt = (char*) gf_modules_get_option((GF_BaseInterface *)read->input, "ISOReader", "DeclareScalableXPS"); if (!opt) { gf_modules_set_option((GF_BaseInterface *)read->input, "ISOReader", "DeclareScalableXPS", "yes"); } else if (!strcmp(opt, "no")) { add_ps_lower = GF_FALSE; } /*TODO check for alternate tracks*/ count = gf_isom_get_track_count(read->mov); for (i=0; i<count; i++) { if (!gf_isom_is_track_enabled(read->mov, i+1)) continue; switch (gf_isom_get_media_type(read->mov, i+1)) { case GF_ISOM_MEDIA_AUDIO: case GF_ISOM_MEDIA_VISUAL: case GF_ISOM_MEDIA_TEXT: case GF_ISOM_MEDIA_SUBT: case GF_ISOM_MEDIA_SCENE: case GF_ISOM_MEDIA_SUBPIC: break; default: continue; } /*we declare only the highest video track (i.e the track we play)*/ highest_stream = GF_TRUE; track_id = gf_isom_get_track_id(read->mov, i+1); for (j = 0; j < count; j++) { if (gf_isom_has_track_reference(read->mov, j+1, GF_ISOM_REF_SCAL, track_id) > 0) { highest_stream = GF_FALSE; break; } } if ((gf_isom_get_media_type(read->mov, i+1) == GF_ISOM_MEDIA_VISUAL) && !highest_stream) continue; esd = gf_media_map_esd(read->mov, i+1); if (esd) { gf_isom_get_reference(read->mov, i+1, GF_ISOM_REF_BASE, 1, &base_track); esd->has_ref_base = base_track ? GF_TRUE : GF_FALSE; /*FIXME: if we declare only SPS/PPS of the highest layer, we have a problem in decoding even though we have all SPS/PPS inband (OpenSVC bug ?)*/ /*so we add by default the SPS/PPS of the lower layers to this esd*/ if (esd->has_ref_base && add_ps_lower) { u32 count, refIndex, ref_track, num_sps, num_pps, t; GF_AVCConfig *cfg = gf_odf_avc_cfg_read(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength); GF_AVCConfig *avccfg, *svccfg; count = gf_isom_get_reference_count(read->mov, i+1, GF_ISOM_REF_SCAL); for (refIndex = count; refIndex != 0; refIndex--) { gf_isom_get_reference(read->mov, i+1, GF_ISOM_REF_SCAL, refIndex, &ref_track); avccfg = gf_isom_avc_config_get(read->mov, ref_track, 1); svccfg = gf_isom_svc_config_get(read->mov, ref_track, 1); if (avccfg) { num_sps = gf_list_count(avccfg->sequenceParameterSets); for (t = 0; t < num_sps; t++) { GF_AVCConfigSlot *slc = gf_list_get(avccfg->sequenceParameterSets, t); GF_AVCConfigSlot *sl = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot)); sl->id = slc->id; sl->size = slc->size; sl->data = (char*)gf_malloc(sizeof(char)*sl->size); memcpy(sl->data, slc->data, sizeof(char)*sl->size); gf_list_insert(cfg->sequenceParameterSets, sl, 0); } num_pps = gf_list_count(avccfg->pictureParameterSets); for (t = 0; t < num_sps; t++) { GF_AVCConfigSlot *slc = gf_list_get(avccfg->pictureParameterSets, t); GF_AVCConfigSlot *sl = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot)); sl->id = slc->id; sl->size = slc->size; sl->data = (char*)gf_malloc(sizeof(char)*sl->size); memcpy(sl->data, slc->data, sizeof(char)*sl->size); gf_list_insert(cfg->pictureParameterSets, sl, 0); } gf_odf_avc_cfg_del(avccfg); } if (svccfg) { num_sps = gf_list_count(svccfg->sequenceParameterSets); for (t = 0; t < num_sps; t++) { GF_AVCConfigSlot *slc = gf_list_get(svccfg->sequenceParameterSets, t); GF_AVCConfigSlot *sl = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot)); sl->id = slc->id; sl->size = slc->size; sl->data = (char*)gf_malloc(sizeof(char)*sl->size); memcpy(sl->data, slc->data, sizeof(char)*sl->size); gf_list_insert(cfg->sequenceParameterSets, sl, 0); } num_pps = gf_list_count(svccfg->pictureParameterSets); for (t = 0; t < num_pps; t++) { GF_AVCConfigSlot *slc = gf_list_get(svccfg->pictureParameterSets, t); GF_AVCConfigSlot *sl = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot)); sl->id = slc->id; sl->size = slc->size; sl->data = (char*)gf_malloc(sizeof(char)*sl->size); memcpy(sl->data, slc->data, sizeof(char)*sl->size); gf_list_insert(cfg->pictureParameterSets, sl, 0); } gf_odf_avc_cfg_del(svccfg); } } if (esd->decoderConfig->decoderSpecificInfo->data) gf_free(esd->decoderConfig->decoderSpecificInfo->data); gf_odf_avc_cfg_write(cfg, &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength); gf_odf_avc_cfg_del(cfg); } od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); od->service_ifce = read->input; od->objectDescriptorID = 0; if (!ocr_es_id) ocr_es_id = esd->ESID; esd->OCRESID = ocr_es_id; gf_list_add(od->ESDescriptors, esd); if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) { send_proxy_command(read, GF_FALSE, GF_TRUE, GF_OK, (GF_Descriptor*)od, NULL); } else { gf_term_add_media(read->service, (GF_Descriptor*)od, GF_TRUE); } } } /*if cover art, extract it in cache*/ if (gf_isom_apple_get_tag(read->mov, GF_ISOM_ITUNE_COVER_ART, &tag, &tlen)==GF_OK) { const char *cdir = gf_modules_get_option((GF_BaseInterface *)gf_term_get_service_interface(read->service), "General", "CacheDirectory"); if (cdir) { char szName[GF_MAX_PATH]; const char *sep; FILE *t; sep = strrchr(gf_isom_get_filename(read->mov), '\\'); if (!sep) sep = strrchr(gf_isom_get_filename(read->mov), '/'); if (!sep) sep = gf_isom_get_filename(read->mov); if ((cdir[strlen(cdir)-1] != '\\') && (cdir[strlen(cdir)-1] != '/')) { sprintf(szName, "%s/%s_cover.%s", cdir, sep, (tlen & 0x80000000) ? "png" : "jpg"); } else { sprintf(szName, "%s%s_cover.%s", cdir, sep, (tlen & 0x80000000) ? "png" : "jpg"); } t = gf_f64_open(szName, "wb"); if (t) { Bool isom_contains_video = GF_FALSE; /*write cover data*/ assert(!(tlen & 0x80000000)); gf_fwrite(tag, tlen & 0x7FFFFFFF, 1, t); fclose(t); /*don't display cover art when video is present*/ for (i=0; i<gf_isom_get_track_count(read->mov); i++) { if (!gf_isom_is_track_enabled(read->mov, i+1)) continue; if (gf_isom_get_media_type(read->mov, i+1) == GF_ISOM_MEDIA_VISUAL) { isom_contains_video = GF_TRUE; break; } } if (!isom_contains_video) { od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); od->service_ifce = read->input; od->objectDescriptorID = GF_MEDIA_EXTERNAL_ID; od->URLString = gf_strdup(szName); if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) { send_proxy_command(read, GF_FALSE, GF_TRUE, GF_OK, (GF_Descriptor*)od, NULL); } else { gf_term_add_media(read->service, (GF_Descriptor*)od, GF_TRUE); } } } } } if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) { send_proxy_command(read, GF_FALSE, GF_TRUE, GF_OK, NULL, NULL); } else { gf_term_add_media(read->service, NULL, GF_FALSE); } }
static void M2TS_OnEvent(GF_M2TS_Demuxer *ts, u32 evt_type, void *param) { GF_Event evt; M2TSIn *m2ts = (M2TSIn *) ts->user; switch (evt_type) { case GF_M2TS_EVT_PAT_UPDATE: /* example code showing how to forward an event from MPEG-2 TS input service to GPAC user*/ #if 0 { GF_Event evt; evt.type = GF_EVENT_FORWARDED; evt.forwarded_event.forward_type = GF_EVT_FORWARDED_MPEG2; evt.forwarded_event.forward_type = GF_EVT_FORWARDED_MPEG2; evt.forwarded_event.service_event_type = evt_type; evt.forwarded_event.param = param; gf_term_on_service_event(m2ts->service, &evt); } #endif break; case GF_M2TS_EVT_AIT_FOUND: evt.type = GF_EVENT_FORWARDED; evt.forwarded_event.forward_type = GF_EVT_FORWARDED_MPEG2; evt.forwarded_event.service_event_type = evt_type; evt.forwarded_event.param = param; gf_term_on_service_event(m2ts->service, &evt); break; case GF_M2TS_EVT_PAT_FOUND: /* In case the TS has one program, wait for the PMT to send connect, in case of IOD in PMT */ if (gf_list_count(m2ts->ts->programs) != 1) { gf_term_on_connect(m2ts->service, NULL, GF_OK); m2ts->is_connected = 1; } /* Send the TS to the a user if needed. Useful to check the number of received programs*/ evt.type = GF_EVENT_FORWARDED; evt.forwarded_event.forward_type = GF_M2TS_EVT_PAT_FOUND; evt.forwarded_event.service_event_type = evt_type; evt.forwarded_event.param = ts; gf_term_on_service_event(m2ts->service, &evt); break; case GF_M2TS_EVT_PMT_FOUND: if (gf_list_count(m2ts->ts->programs) == 1) { gf_term_on_connect(m2ts->service, NULL, GF_OK); m2ts->is_connected = 1; } /*do not declare if single program was requested for playback*/ MP2TS_SetupProgram(m2ts, param, m2ts->request_all_pids, m2ts->request_all_pids ? 0 : 1); M2TS_FlushRequested(m2ts); break; case GF_M2TS_EVT_PMT_REPEAT: // case GF_M2TS_EVT_PMT_UPDATE: M2TS_FlushRequested(m2ts); break; case GF_M2TS_EVT_SDT_REPEAT: case GF_M2TS_EVT_SDT_UPDATE: case GF_M2TS_EVT_SDT_FOUND: M2TS_FlushRequested(m2ts); break; case GF_M2TS_EVT_DVB_GENERAL: if (m2ts->eit_channel) { GF_M2TS_SL_PCK *pck = (GF_M2TS_SL_PCK *)param; gf_term_on_sl_packet(m2ts->service, m2ts->eit_channel, pck->data, pck->data_len, NULL, GF_OK); } break; case GF_M2TS_EVT_PES_PCK: MP2TS_SendPacket(m2ts, param); break; case GF_M2TS_EVT_SL_PCK: MP2TS_SendSLPacket(m2ts, param); break; case GF_M2TS_EVT_AAC_CFG: { GF_M2TS_PES_PCK *pck = (GF_M2TS_PES_PCK*)param; if (!pck->stream->first_dts) { gf_m2ts_set_pes_framing(pck->stream, GF_M2TS_PES_FRAMING_SKIP_NO_RESET); MP2TS_DeclareStream(m2ts, pck->stream, pck->data, pck->data_len); if (ts->file || ts->dnload) ts->file_regulate = 1; pck->stream->first_dts=1; /*force scene regeneration*/ gf_term_add_media(m2ts->service, NULL, 0); } } break; case GF_M2TS_EVT_PES_PCR: /*send pcr*/ if (((GF_M2TS_PES_PCK *) param)->stream && ((GF_M2TS_PES_PCK *) param)->stream->user) { GF_SLHeader slh; memset(&slh, 0, sizeof(GF_SLHeader) ); slh.OCRflag = 1; slh.m2ts_pcr = ( ((GF_M2TS_PES_PCK *) param)->flags & GF_M2TS_PES_PCK_DISCONTINUITY) ? 2 : 1; slh.objectClockReference = ((GF_M2TS_PES_PCK *) param)->PTS; gf_term_on_sl_packet(m2ts->service, ((GF_M2TS_PES_PCK *) param)->stream->user, NULL, 0, &slh, GF_OK); } ((GF_M2TS_PES_PCK *) param)->stream->program->first_dts = 1; if ( ((GF_M2TS_PES_PCK *) param)->flags & GF_M2TS_PES_PCK_DISCONTINUITY) { #if 0 if (ts->pcr_last) { ts->pcr_last = ((GF_M2TS_PES_PCK *) param)->PTS; ts->stb_at_last_pcr = gf_sys_clock(); } #endif GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[M2TS In] PCR discontinuity - switching from old STB "LLD" to new one "LLD"\n", ts->pcr_last, ((GF_M2TS_PES_PCK *) param)->PTS)); /*FIXME - we need to find a way to treat PCR discontinuities correctly while ignoring broken PCR discontinuities seen in many HLS solutions*/ return; } if (ts->file_regulate) { u64 pcr = ((GF_M2TS_PES_PCK *) param)->PTS; u32 stb = gf_sys_clock(); if (m2ts->regulation_pcr_pid==0) { /*we pick the first PCR PID for file regulation - we don't need to make sure this is the PCR of a program being plyaed as we only check buffer levels, not DTS/PTS of the streams in the regulation step*/ m2ts->regulation_pcr_pid = ((GF_M2TS_PES_PCK *) param)->stream->pid; } else if (m2ts->regulation_pcr_pid != ((GF_M2TS_PES_PCK *) param)->stream->pid) { return; } if (ts->pcr_last) { s32 diff; if (pcr < ts->pcr_last) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[M2TS In] PCR "LLU" less than previous PCR "LLU"\n", ((GF_M2TS_PES_PCK *) param)->PTS, ts->pcr_last)); ts->pcr_last = pcr; ts->stb_at_last_pcr = gf_sys_clock(); diff = 0; } else { u64 pcr_diff = (pcr - ts->pcr_last); pcr_diff /= 27000; if (pcr_diff>1000) { GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[M2TS In] PCR diff too big: "LLU" ms - PCR "LLU" - previous PCR "LLU" - error in TS ?\n", pcr_diff, ((GF_M2TS_PES_PCK *) param)->PTS, ts->pcr_last)); diff = 100; } else { diff = (u32) pcr_diff - (stb - ts->stb_at_last_pcr); } } if (diff<0) { GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[M2TS In] Demux not going fast enough according to PCR (drift %d, pcr: "LLU", last pcr: "LLU")\n", diff, pcr, ts->pcr_last)); } else if (diff>0) { u32 sleep_for=1; #ifndef GPAC_DISABLE_LOG u32 nb_sleep=0; #endif /*query buffer level, don't sleep if too low*/ GF_NetworkCommand com; com.command_type = GF_NET_BUFFER_QUERY; while (ts->run_state) { gf_term_on_command(m2ts->service, &com, GF_OK); if (com.buffer.occupancy < M2TS_BUFFER_MAX) { GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[M2TS In] Demux not going to sleep: buffer occupancy %d ms\n", com.buffer.occupancy)); break; } /*We don't sleep for the entire buffer occupancy, because we would take the risk of starving the audio chains. We try to keep buffers half full*/ #ifndef GPAC_DISABLE_LOG if (!nb_sleep) { GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[M2TS In] Demux going to sleep (buffer occupancy %d ms)\n", com.buffer.occupancy)); } nb_sleep++; #endif gf_sleep(sleep_for); } #ifndef GPAC_DISABLE_LOG if (nb_sleep) { GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[M2TS In] Demux resume after %d ms - current buffer occupancy %d ms\n", sleep_for*nb_sleep, com.buffer.occupancy)); } #endif ts->nb_pck = 0; ts->pcr_last = pcr; ts->stb_at_last_pcr = gf_sys_clock(); } else { GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[M2TS In] Demux drift according to PCR (drift %d, pcr: "LLD", last pcr: "LLD")\n", diff, pcr, ts->pcr_last)); } } else { ts->pcr_last = pcr; ts->stb_at_last_pcr = gf_sys_clock(); } } break; case GF_M2TS_EVT_TDT: if (m2ts->hybrid_on) { u32 i, count; GF_M2TS_TDT_TOT *tdt = (GF_M2TS_TDT_TOT *)param; GF_NetworkCommand com; memset(&com, 0, sizeof(com)); com.command_type = GF_NET_CHAN_MAP_TIME; com.map_time.media_time = tdt->hour*3600+tdt->minute*60+tdt->second; com.map_time.reset_buffers = 0; count = gf_list_count(ts->programs); for (i=0; i<count; i++) { GF_M2TS_Program *prog = gf_list_get(ts->programs, i); u32 j, count2; if (prog->tdt_found || !prog->last_pcr_value) /*map TDT one time, after we received a PCR*/ continue; prog->tdt_found = 1; count2 = gf_list_count(prog->streams); com.map_time.timestamp = prog->last_pcr_value/300; for (j=0; j<count2; j++) { GF_M2TS_ES * stream = gf_list_get(prog->streams, j); if (stream->user) { com.base.on_channel = stream->user; gf_term_on_command(m2ts->service, &com, GF_OK); } } GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[M2TS In] Mapping TDT Time %04d/%02d/%02d %02d:%02d:%02d and PCR time "LLD" on program %d\n", tdt->year, tdt->month, tdt->day, tdt->hour, tdt->minute, tdt->second, com.map_time.timestamp, prog->number)); } } break; case GF_M2TS_EVT_TOT: break; } }
static void M2TS_FlushRequested(M2TSIn *m2ts) { u32 i, j, req_prog_count, count, prog_id, found; gf_mx_p(m2ts->mx); found = 0; count = gf_list_count(m2ts->ts->requested_pids); for (i=0; i<count; i++) { M2TSIn_Prog *req_pid = gf_list_get(m2ts->ts->requested_pids, i); GF_M2TS_ES *es = m2ts->ts->ess[req_pid->pid]; if (es==NULL) continue; /*move to skip mode for all PES until asked for playback*/ if (!(es->flags & GF_M2TS_ES_IS_SECTION) && !es->user) gf_m2ts_set_pes_framing((GF_M2TS_PES *)es, GF_M2TS_PES_FRAMING_SKIP); MP2TS_DeclareStream(m2ts, (GF_M2TS_PES *)es, NULL, 0); gf_list_rem(m2ts->ts->requested_pids, i); gf_free(req_pid); i--; count--; found++; } req_prog_count = gf_list_count(m2ts->ts->requested_progs); for (i = 0; i < req_prog_count; i++) { M2TSIn_Prog *req_prog = gf_list_get(m2ts->ts->requested_progs, i); prog_id = atoi(req_prog->fragment); count = gf_list_count(m2ts->ts->SDTs); for (j=0; j<count; j++) { GF_M2TS_SDT *sdt = gf_list_get(m2ts->ts->SDTs, j); if (!stricmp(sdt->service, req_prog->fragment)) req_prog->id = sdt->service_id; else if (sdt->service_id==prog_id) req_prog->id = sdt->service_id; } if (req_prog->id) { GF_M2TS_Program *ts_prog; count = gf_list_count(m2ts->ts->programs); for (j=0; j<count; j++) { ts_prog = gf_list_get(m2ts->ts->programs, j); if (ts_prog->number==req_prog->id) { MP2TS_SetupProgram(m2ts, ts_prog, 0, 0); found++; gf_free(req_prog->fragment); gf_free(req_prog); gf_list_rem(m2ts->ts->requested_progs, i); req_prog_count--; i--; break; } } } } if (m2ts->epg_requested) { if (!m2ts->has_eit) { GF_ObjectDescriptor *od = M2TS_GenerateEPG_OD(m2ts); /*declare but don't regenerate scene*/ gf_term_add_media(m2ts->service, (GF_Descriptor*)od, 0); m2ts->has_eit = 1; } } else { /*force scene regeneration only when EPG is not requested*/ if (found) gf_term_add_media(m2ts->service, NULL, 0); } gf_mx_v(m2ts->mx); }
GF_Err LIBPLAYER_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url) { LibPlayerIn *read = (LibPlayerIn *) plug->priv; #ifndef TEST_LIBPLAYER unsigned long prop; mrl_t *mrl = NULL; #endif printf("[LibPlayerIN]connecting\n"); if (!read || !serv || !url) return GF_BAD_PARAM; if (!strnicmp(url, "libplayer://", 12)) url+=12; if (!read->init) { read->init=1; /* libplayer init */ read->url = url; read->player_id = libplayer_id; #ifndef TEST_LIBPLAYER read->player = player_init(PLAYER_TYPE_DUMMY, PLAYER_AO_AUTO, PLAYER_VO_AUTO, PLAYER_MSG_INFO, read->player_id, on_libplayer_event); //~ read->width = 0; //~ read->height = 0; if (!read->player) { GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[LibPlayerIN]�Failed to instanciate libplayer instance %d\n", read->player_id)); gf_term_on_connect(serv, NULL, GF_REMOTE_SERVICE_ERROR); return GF_OK; } #endif libplayer_id++; GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] Opening URL %s for Player instance %d\n", url, read->player_id)); //~ player_local_location_set(read->player, url); } #ifndef TEST_LIBPLAYER mrl = NULL; if (!strnicmp(url, "dvb://", 6)) { } else if (!strnicmp(url, "file://", 7) || !strstr(url, "://")) { mrl_resource_local_args_t *mrl_args; mrl_args = calloc(1, sizeof(mrl_resource_local_args_t)); if (!strnicmp(url, "file://", 7)) { mrl_args->location = strdup(url + 7); } else { mrl_args->location = strdup(url); } mrl = mrl_new (read->player, MRL_RESOURCE_FILE, mrl_args); } else { } if (!mrl) { GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[LibPlayerIN]�Failed to create MRL for url %s\n", url)); gf_term_on_connect(serv, NULL, GF_URL_ERROR); return GF_OK; } player_mrl_set(read->player, mrl); #endif read->state = 0; read->service = serv; /*ACK connection is OK*/ gf_term_on_connect(serv, NULL, GF_OK); /*setup LIBPLAYER object descriptor*/ { GF_ESD *esd; GF_ObjectDescriptor *od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); od->objectDescriptorID = 1+read->player_id; esd = gf_odf_desc_esd_new(0); esd->ESID = 1+read->player_id; esd->slConfig->timestampResolution = 1000; esd->decoderConfig->streamType = GF_STREAM_PRIVATE_MEDIA; esd->decoderConfig->objectTypeIndication = GPAC_OTI_PRIVATE_MEDIA_LIBPLAYER; #ifndef TEST_LIBPLAYER esd->decoderConfig->decoderSpecificInfo->data = read; #endif gf_list_add(od->ESDescriptors, esd); gf_term_add_media(read->service, (GF_Descriptor*)od, 0); } return GF_OK; }
static void SAF_NetIO(void *cbk, GF_NETIO_Parameter *param) { GF_Err e; Bool is_rap, go; SAFChannel *ch; u32 cts, au_sn, au_size, type, i, stream_id; u64 bs_pos; GF_BitStream *bs; GF_SLHeader sl_hdr; SAFIn *read = (SAFIn *) cbk; e = param->error; /*done*/ if (param->msg_type==GF_NETIO_DATA_TRANSFERED) { if (read->stream && (read->saf_type==SAF_FILE_REMOTE)) read->saf_type = SAF_FILE_LOCAL; return; } else { /*handle service message*/ gf_term_download_update_stats(read->dnload); if (param->msg_type!=GF_NETIO_DATA_EXCHANGE) { if (e<0) { if (read->needs_connection) { read->needs_connection = 0; gf_term_on_connect(read->service, NULL, e); } return; } if (read->needs_connection) { u32 total_size; gf_dm_sess_get_stats(read->dnload, NULL, NULL, &total_size, NULL, NULL, NULL); if (!total_size) read->saf_type = SAF_LIVE_STREAM; } return; } } if (!param->size) return; if (!read->run_state) return; if (read->alloc_size < read->saf_size + param->size) { read->saf_data = (char*)gf_realloc(read->saf_data, sizeof(char)*(read->saf_size + param->size) ); read->alloc_size = read->saf_size + param->size; } memcpy(read->saf_data + read->saf_size, param->data, sizeof(char)*param->size); read->saf_size += param->size; /*first AU not complete yet*/ if (read->saf_size<10) return; bs = gf_bs_new(read->saf_data, read->saf_size, GF_BITSTREAM_READ); bs_pos = 0; go = 1; while (go) { u64 avail = gf_bs_available(bs); bs_pos = gf_bs_get_position(bs); if (avail<10) break; is_rap = gf_bs_read_int(bs, 1); au_sn = gf_bs_read_int(bs, 15); gf_bs_read_int(bs, 2); cts = gf_bs_read_int(bs, 30); au_size = gf_bs_read_int(bs, 16); avail-=8; if (au_size > avail) break; assert(au_size>=2); is_rap = 1; type = gf_bs_read_int(bs, 4); stream_id = gf_bs_read_int(bs, 12); au_size -= 2; ch = saf_get_channel(read, stream_id, NULL); switch (type) { case 1: case 2: case 7: if (ch) { gf_bs_skip_bytes(bs, au_size); } else { SAFChannel *first = (SAFChannel *)gf_list_get(read->channels, 0); GF_SAFEALLOC(ch, SAFChannel); ch->stream_id = stream_id; ch->esd = gf_odf_desc_esd_new(0); ch->esd->ESID = stream_id; ch->esd->OCRESID = first ? first->stream_id : stream_id; ch->esd->slConfig->useRandomAccessPointFlag = 1; ch->esd->slConfig->AUSeqNumLength = 0; ch->esd->decoderConfig->objectTypeIndication = gf_bs_read_u8(bs); ch->esd->decoderConfig->streamType = gf_bs_read_u8(bs); ch->ts_res = ch->esd->slConfig->timestampResolution = gf_bs_read_u24(bs); ch->esd->decoderConfig->bufferSizeDB = gf_bs_read_u16(bs); au_size -= 7; if ((ch->esd->decoderConfig->objectTypeIndication == 0xFF) && (ch->esd->decoderConfig->streamType == 0xFF) ) { u16 mimeLen = gf_bs_read_u16(bs); gf_bs_skip_bytes(bs, mimeLen); au_size -= mimeLen+2; } if (type==7) { u16 urlLen = gf_bs_read_u16(bs); ch->esd->URLString = (char*)gf_malloc(sizeof(char)*(urlLen+1)); gf_bs_read_data(bs, ch->esd->URLString, urlLen); ch->esd->URLString[urlLen] = 0; au_size -= urlLen+2; } if (au_size) { ch->esd->decoderConfig->decoderSpecificInfo->dataLength = au_size; ch->esd->decoderConfig->decoderSpecificInfo->data = (char*)gf_malloc(sizeof(char)*au_size); gf_bs_read_data(bs, ch->esd->decoderConfig->decoderSpecificInfo->data, au_size); } if (ch->esd->decoderConfig->streamType==4) ch->buffer_min=100; else if (ch->esd->decoderConfig->streamType==5) ch->buffer_min=400; else ch->buffer_min=0; if (read->needs_connection && (ch->esd->decoderConfig->streamType==GF_STREAM_SCENE)) { gf_list_add(read->channels, ch); read->needs_connection = 0; gf_term_on_connect(read->service, NULL, GF_OK); } else if (read->needs_connection) { gf_odf_desc_del((GF_Descriptor *) ch->esd); gf_free(ch); ch = NULL; } else { GF_ObjectDescriptor *od; gf_list_add(read->channels, ch); od = (GF_ObjectDescriptor*)gf_odf_desc_new(GF_ODF_OD_TAG); gf_list_add(od->ESDescriptors, ch->esd); ch->esd = NULL; od->objectDescriptorID = ch->stream_id; gf_term_add_media(read->service, (GF_Descriptor*)od, 0); } } break; case 4: if (ch) { bs_pos = gf_bs_get_position(bs); memset(&sl_hdr, 0, sizeof(GF_SLHeader)); sl_hdr.accessUnitLength = au_size; sl_hdr.AU_sequenceNumber = au_sn; sl_hdr.compositionTimeStampFlag = 1; sl_hdr.compositionTimeStamp = cts; sl_hdr.randomAccessPointFlag = is_rap; if (read->start_range && (read->start_range*ch->ts_res>cts*1000)) { sl_hdr.compositionTimeStamp = read->start_range*ch->ts_res/1000; } gf_term_on_sl_packet(read->service, ch->ch, read->saf_data+bs_pos, au_size, &sl_hdr, GF_OK); } gf_bs_skip_bytes(bs, au_size); break; case 3: if (ch) gf_term_on_sl_packet(read->service, ch->ch, NULL, 0, NULL, GF_EOS); break; case 5: go = 0; read->run_state = 0; i=0; while ((ch = (SAFChannel *)gf_list_enum(read->channels, &i))) { gf_term_on_sl_packet(read->service, ch->ch, NULL, 0, NULL, GF_EOS); } break; } } gf_bs_del(bs); if (bs_pos) { u32 remain = (u32) (read->saf_size - bs_pos); if (remain) memmove(read->saf_data, read->saf_data+bs_pos, sizeof(char)*remain); read->saf_size = remain; } SAF_Regulate(read); }