Beispiel #1
0
static void gf_m2ts_switch_quality(GF_M2TS_Program *prog, GF_M2TS_Demuxer *ts, Bool switch_up)
{
	GF_M2TS_ES *es;
	u32 i, count;
	GF_NetworkCommand com;

	if (!prog->is_scalable)
		return;

	if (switch_up) {
		for (i = 0; i < GF_M2TS_MAX_STREAMS; i++) {
			es = ts->ess[i];
			if (es && (es->flags & GF_M2TS_ES_IS_PES) && (((GF_M2TS_PES *)es)->depends_on_pid == prog->pid_playing)) {
				GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("Turn on ES%d\n", es->pid));
				gf_m2ts_set_pes_framing((GF_M2TS_PES *)ts->ess[es->pid], GF_M2TS_PES_FRAMING_DEFAULT);
				prog->pid_playing = es->pid;
				return;
			}
		}
	}
	else {
		count = gf_list_count(prog->streams);
		for (i = 0; i < count; i++) {
			es = (GF_M2TS_ES *)gf_list_get(prog->streams, i);
			if (es && (es->pid == prog->pid_playing) && ((GF_M2TS_PES *)es)->depends_on_pid) {
				GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("Turn off ES%d - playing ES%d\n", es->pid, ((GF_M2TS_PES *)es)->depends_on_pid));
				gf_m2ts_set_pes_framing((GF_M2TS_PES *)ts->ess[es->pid], GF_M2TS_PES_FRAMING_SKIP);
				memset(&com, 0, sizeof(com));
				com.command_type = GF_NET_CHAN_RESET;
				com.base.on_channel = ((GF_M2TS_PES *)es)->user;
				gf_term_on_command(((M2TSIn *)ts->user)->service, &com, GF_OK);
				prog->pid_playing = ((GF_M2TS_PES *)es)->depends_on_pid;
				return;
			}
		}
	}
}
Beispiel #2
0
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);
}
Beispiel #3
0
static GF_Err M2TS_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
{
    GF_M2TS_PES *pes;
    M2TSIn *m2ts = plug->priv;
    GF_M2TS_Demuxer *ts = m2ts->ts;

    if (com->command_type==GF_NET_SERVICE_HAS_AUDIO) {
        char *frag = strchr(com->audio.base_url, '#');
        if (frag && !strnicmp(frag, "#pid=", 5)) return GF_NOT_SUPPORTED;
        return GF_OK;
    }
    if (!com->base.on_channel) return GF_NOT_SUPPORTED;
    switch (com->command_type) {
    /*we cannot pull complete AUs from the stream*/
    case GF_NET_CHAN_SET_PULL:
        return GF_NOT_SUPPORTED;
    /*we cannot seek stream by stream*/
    case GF_NET_CHAN_INTERACTIVE:
        return GF_NOT_SUPPORTED;
    case GF_NET_CHAN_BUFFER:
        com->buffer.max = M2TS_BUFFER_MAX;
        com->buffer.min = 0;
        return GF_OK;
    case GF_NET_CHAN_DURATION:
        com->duration.duration = ts->duration;
        return GF_OK;
    case GF_NET_CHAN_PLAY:
        pes = M2TS_GetChannel(m2ts, com->base.on_channel);
        if (!pes) {
            if (com->base.on_channel == m2ts->eit_channel) {
                return GF_OK;
            }
            return GF_STREAM_NOT_FOUND;
        }
        /*mark pcr as not initialized*/
        if (pes->program->pcr_pid==pes->pid) pes->program->first_dts=0;
        gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_DEFAULT);
        GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[M2TSIn] Setting default reframing for PID %d\n", pes->pid));
        /*this is a multplex, only trigger the play command for the first stream activated*/
        if (!ts->nb_playing) {
            ts->start_range = (u32) (com->play.start_range*1000);
            ts->end_range = (com->play.end_range>0) ? (u32) (com->play.end_range*1000) : 0;
            /*start demuxer*/
            if (ts->run_state!=1) {
                return TSDemux_DemuxPlay(ts);
            }
        }
        ts->nb_playing++;
        return GF_OK;
    case GF_NET_CHAN_STOP:
        pes = M2TS_GetChannel(m2ts, com->base.on_channel);
        if (!pes) {
            if (com->base.on_channel == m2ts->eit_channel) {
                return GF_OK;
            }
            return GF_STREAM_NOT_FOUND;
        }

        gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_SKIP);
        /* In case of EOS, we may receive a stop command after no one is playing */
        if (ts->nb_playing)
            ts->nb_playing--;
        /*stop demuxer*/
        if (!ts->nb_playing && (ts->run_state==1)) {
            ts->run_state=0;
            while (ts->run_state!=2) gf_sleep(2);
            if (gf_list_count(m2ts->ts->requested_progs)) {
                ts->file_regulate = 0;
                return TSDemux_DemuxPlay(ts);
            }
        }
        return GF_OK;
    case GF_NET_CHAN_CONFIG:
        pes = M2TS_GetChannel(m2ts, com->base.on_channel);
        /*filter all sections carrying SL data for the app to signal the version number of the section*/
        if (pes && pes->flags & GF_M2TS_ES_IS_SECTION) {
            if (pes->slcfg) gf_free(pes->slcfg);
            pes->slcfg = gf_malloc(sizeof(GF_SLConfig));
            memcpy(pes->slcfg, &com->cfg.sl_config, sizeof(GF_SLConfig));
            com->cfg.use_m2ts_sections = 1;
            pes->flags |= GF_M2TS_ES_SEND_REPEATED_SECTIONS;
        }
        return GF_OK;
    default:
        return GF_OK;
    }
}
Beispiel #4
0
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;
    }
}
Beispiel #5
0
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);
}
Beispiel #6
0
static GF_ObjectDescriptor *MP2TS_GetOD(M2TSIn *m2ts, GF_M2TS_PES *stream, char *dsi, u32 dsi_size, u32 *streamType)
{
    GF_ObjectDescriptor *od;
    GF_ESD *esd;

    /*create a stream description for this channel*/
    esd = gf_odf_desc_esd_new(0);
    esd->ESID = stream->mpeg4_es_id ? stream->mpeg4_es_id : stream->pid;

    switch (stream->stream_type) {
    case GF_M2TS_VIDEO_MPEG1:
        esd->decoderConfig->streamType = GF_STREAM_VISUAL;
        esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_MPEG1;
        break;
    case GF_M2TS_VIDEO_MPEG2:
        esd->decoderConfig->streamType = GF_STREAM_VISUAL;
        esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_MPEG2_422;
        break;
    case GF_M2TS_VIDEO_MPEG4:
        esd->decoderConfig->streamType = GF_STREAM_VISUAL;
        esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_MPEG4_PART2;
        break;
    case GF_M2TS_VIDEO_H264:
        esd->decoderConfig->streamType = GF_STREAM_VISUAL;
        esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_AVC;
        break;
    case GF_M2TS_VIDEO_VC1:
        esd->decoderConfig->streamType = GF_STREAM_VISUAL;
        esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_SMPTE_VC1;
        break;
    case GF_M2TS_AUDIO_MPEG1:
        esd->decoderConfig->streamType = GF_STREAM_AUDIO;
        esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_MPEG1;
        break;
    case GF_M2TS_AUDIO_MPEG2:
        esd->decoderConfig->streamType = GF_STREAM_AUDIO;
        esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_MPEG2_PART3;
        break;
    case GF_M2TS_AUDIO_LATM_AAC:
    case GF_M2TS_AUDIO_AAC:
        if (!dsi) {
            /*discard regulate until we fetch the AAC config*/
            m2ts->ts->file_regulate = 0;
            /*turn on parsing*/
            gf_m2ts_set_pes_framing(stream, GF_M2TS_PES_FRAMING_DEFAULT);
            gf_odf_desc_del((GF_Descriptor *)esd);
            return NULL;
        }
        esd->decoderConfig->streamType = GF_STREAM_AUDIO;
        esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_AAC_MPEG4;
        break;
    case GF_M2TS_SYSTEMS_MPEG4_SECTIONS:
    default:
        gf_odf_desc_del((GF_Descriptor *)esd);
        return NULL;
    }
    esd->decoderConfig->bufferSizeDB = 0;

    /*we only use AUstart indicator*/
    esd->slConfig->useAccessUnitStartFlag = 1;
    esd->slConfig->useAccessUnitEndFlag = 0;
    esd->slConfig->useRandomAccessPointFlag = 1;
    esd->slConfig->AUSeqNumLength = 0;
    esd->slConfig->timestampResolution = 90000;

    /*ASSIGN PCR here*/
    esd->OCRESID = stream->program->pcr_pid;
    if (stream->pid == stream->program->pcr_pid) {
        esd->slConfig->OCRResolution = 27000000;
    }

    /*decoder config*/
    if (dsi) {
        esd->decoderConfig->decoderSpecificInfo->data = gf_malloc(sizeof(char)*dsi_size);
        memcpy(esd->decoderConfig->decoderSpecificInfo->data, dsi, sizeof(char)*dsi_size);
        esd->decoderConfig->decoderSpecificInfo->dataLength = dsi_size;
    }

    /*declare object to terminal*/
    od = (GF_ObjectDescriptor*)gf_odf_desc_new(GF_ODF_OD_TAG);
    gf_list_add(od->ESDescriptors, esd);
    od->objectDescriptorID = 0;
    if (streamType) *streamType = esd->decoderConfig->streamType;
    /*remember program number for service/program selection*/
    od->ServiceID = stream->program->number;
    od->service_ifce = m2ts->owner;
    return od;
}
Beispiel #7
0
static GF_ESD *MP2TS_GetESD(M2TSIn *m2ts, GF_M2TS_PES *stream, char *dsi, u32 dsi_size)
{
	GF_ESD *esd;

	esd = gf_odf_desc_esd_new(0);
	esd->ESID = stream->mpeg4_es_id ? stream->mpeg4_es_id : stream->pid;

	switch (stream->stream_type) {
	case GF_M2TS_VIDEO_MPEG1:
		esd->decoderConfig->streamType = GF_STREAM_VISUAL;
		esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_MPEG1;
		break;
	case GF_M2TS_VIDEO_MPEG2:
	case GF_M2TS_VIDEO_DCII:
		esd->decoderConfig->streamType = GF_STREAM_VISUAL;
		esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_MPEG2_422;
		break;
	case GF_M2TS_VIDEO_MPEG4:
		esd->decoderConfig->streamType = GF_STREAM_VISUAL;
		esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_MPEG4_PART2;
		break;
	case GF_M2TS_VIDEO_H264:
		esd->decoderConfig->streamType = GF_STREAM_VISUAL;
		esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_AVC;
		break;
	case GF_M2TS_VIDEO_SVC:
		esd->decoderConfig->streamType = GF_STREAM_VISUAL;
		esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_SVC;
		break;
	case GF_M2TS_VIDEO_HEVC:
		esd->decoderConfig->streamType = GF_STREAM_VISUAL;
		esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_HEVC;
		break;
	case GF_M2TS_VIDEO_VC1:
		esd->decoderConfig->streamType = GF_STREAM_VISUAL;
		esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_SMPTE_VC1;
		break;
	case GF_M2TS_AUDIO_MPEG1:
		esd->decoderConfig->streamType = GF_STREAM_AUDIO;
		esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_MPEG1;
		break;
	case GF_M2TS_AUDIO_MPEG2:
		esd->decoderConfig->streamType = GF_STREAM_AUDIO;
		esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_MPEG2_PART3;
		break;
	case GF_M2TS_AUDIO_LATM_AAC:
	case GF_M2TS_AUDIO_AAC:
	case GPAC_OTI_AUDIO_AAC_MPEG2_MP:
	case GPAC_OTI_AUDIO_AAC_MPEG2_LCP:
	case GPAC_OTI_AUDIO_AAC_MPEG2_SSRP:
		if (!dsi) {
			/*turn on parsing to get AAC config
				NB: we removed "no file regulation" since we may get broken files where PMT declares an AAC stream but no AAC PID is in the MUX
				(filtered out). In this case, "no regulation" will make the entire TS to be read as fast as possible
			*/
			if (m2ts->ts->file)
				m2ts->ts->file_regulate = 2;

			gf_m2ts_set_pes_framing(stream, GF_M2TS_PES_FRAMING_DEFAULT);
			gf_odf_desc_del((GF_Descriptor *)esd);
			return NULL;
		}
		esd->decoderConfig->streamType = GF_STREAM_AUDIO;
		esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_AAC_MPEG4;
		break;
	case GF_M2TS_SYSTEMS_MPEG4_SECTIONS:
	default:
		gf_odf_desc_del((GF_Descriptor *)esd);
		return NULL;
	}
	esd->decoderConfig->bufferSizeDB = 0;

	/*we only use AUstart indicator*/
	esd->slConfig->useAccessUnitStartFlag = 1;
	esd->slConfig->useAccessUnitEndFlag = 0;
	esd->slConfig->useRandomAccessPointFlag = 1;
	esd->slConfig->AUSeqNumLength = 0;
	esd->slConfig->timestampResolution = 90000;

	/*ASSIGN PCR here*/
	esd->OCRESID = stream->program->pcr_pid;
	if (stream->pid == stream->program->pcr_pid) {
		esd->slConfig->OCRResolution = 27000000;
	}

	/*decoder config*/
	if (dsi) {
		esd->decoderConfig->decoderSpecificInfo->data = gf_malloc(sizeof(char)*dsi_size);
		memcpy(esd->decoderConfig->decoderSpecificInfo->data, dsi, sizeof(char)*dsi_size);
		esd->decoderConfig->decoderSpecificInfo->dataLength = dsi_size;
	}
	return esd;
}