Esempio n. 1
0
void HEVC_RewriteESDescriptor(GF_MPEGVisualSampleEntryBox *hevc)
{
	if (hevc->emul_esd) gf_odf_desc_del((GF_Descriptor *)hevc->emul_esd);
	hevc->emul_esd = gf_odf_desc_esd_new(2);
	hevc->emul_esd->decoderConfig->streamType = GF_STREAM_VISUAL;
	hevc->emul_esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_HEVC;
	if (hevc->bitrate) {
		hevc->emul_esd->decoderConfig->bufferSizeDB = hevc->bitrate->bufferSizeDB;
		hevc->emul_esd->decoderConfig->avgBitrate = hevc->bitrate->avgBitrate;
		hevc->emul_esd->decoderConfig->maxBitrate = hevc->bitrate->maxBitrate;
	}
	if (hevc->descr) {
		u32 i=0;
		GF_Descriptor *desc,*clone;
		i=0;
		while ((desc = (GF_Descriptor *)gf_list_enum(hevc->descr->descriptors, &i))) {
			clone = NULL;
			gf_odf_desc_copy(desc, &clone);
			if (gf_odf_desc_add_desc((GF_Descriptor *)hevc->emul_esd, clone) != GF_OK)
				gf_odf_desc_del(clone);
		}
	}
	if (hevc->hevc_config && hevc->hevc_config->config) {
		gf_odf_hevc_cfg_write(hevc->hevc_config->config, &hevc->emul_esd->decoderConfig->decoderSpecificInfo->data, &hevc->emul_esd->decoderConfig->decoderSpecificInfo->dataLength);
	}
}
Esempio n. 2
0
void AVC_RewriteESDescriptor(GF_MPEGVisualSampleEntryBox *avc)
{
	if (avc->emul_esd) gf_odf_desc_del((GF_Descriptor *)avc->emul_esd);
	avc->emul_esd = gf_odf_desc_esd_new(2);
	avc->emul_esd->decoderConfig->streamType = GF_STREAM_VISUAL;
	/*AVC OTI is 0x21, AVC parameter set stream OTI (not supported in gpac) is 0x22*/
	avc->emul_esd->decoderConfig->objectTypeIndication = 0x21;
	if (avc->bitrate) {
		avc->emul_esd->decoderConfig->bufferSizeDB = avc->bitrate->bufferSizeDB;
		avc->emul_esd->decoderConfig->avgBitrate = avc->bitrate->avgBitrate;
		avc->emul_esd->decoderConfig->maxBitrate = avc->bitrate->maxBitrate;
	}
	if (avc->descr) {
		u32 i=0; 
		GF_Descriptor *desc,*clone;
		i=0;
		while ((desc = (GF_Descriptor *)gf_list_enum(avc->descr->descriptors, &i))) {
			clone = NULL;
			gf_odf_desc_copy(desc, &clone);
			if (gf_odf_desc_add_desc((GF_Descriptor *)avc->emul_esd, clone) != GF_OK) 
				gf_odf_desc_del(clone);
		}
	}
	if (avc->avc_config && avc->avc_config->config) {
		gf_odf_avc_cfg_write(avc->avc_config->config, &avc->emul_esd->decoderConfig->decoderSpecificInfo->data, &avc->emul_esd->decoderConfig->decoderSpecificInfo->dataLength);
	}
}
Esempio n. 3
0
void AVC_RewriteESDescriptor(GF_MPEGVisualSampleEntryBox *avc)
{
	GF_AVCConfig *avcc, *svcc;
	if (avc->emul_esd) gf_odf_desc_del((GF_Descriptor *)avc->emul_esd);
	avc->emul_esd = gf_odf_desc_esd_new(2);
	avc->emul_esd->decoderConfig->streamType = GF_STREAM_VISUAL;
	/*AVC OTI is 0x21, AVC parameter set stream OTI (not supported in gpac) is 0x22*/
	avc->emul_esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_AVC;
	if (avc->bitrate) {
		avc->emul_esd->decoderConfig->bufferSizeDB = avc->bitrate->bufferSizeDB;
		avc->emul_esd->decoderConfig->avgBitrate = avc->bitrate->avgBitrate;
		avc->emul_esd->decoderConfig->maxBitrate = avc->bitrate->maxBitrate;
	}
	if (avc->descr) {
		u32 i=0;
		GF_Descriptor *desc,*clone;
		i=0;
		while ((desc = (GF_Descriptor *)gf_list_enum(avc->descr->descriptors, &i))) {
			clone = NULL;
			gf_odf_desc_copy(desc, &clone);
			if (gf_odf_desc_add_desc((GF_Descriptor *)avc->emul_esd, clone) != GF_OK)
				gf_odf_desc_del(clone);
		}
	}
	if (avc->avc_config) {
		avcc = avc->avc_config->config ? AVC_DuplicateConfig(avc->avc_config->config) : NULL;
		/*merge SVC config*/
		if (avc->svc_config) {
			svcc = AVC_DuplicateConfig(avc->svc_config->config);
			while (gf_list_count(svcc->sequenceParameterSets)) {
				GF_AVCConfigSlot *p = (GF_AVCConfigSlot*)gf_list_get(svcc->sequenceParameterSets, 0);
				gf_list_rem(svcc->sequenceParameterSets, 0);
				gf_list_add(avcc->sequenceParameterSets, p);
			}
			while (gf_list_count(svcc->pictureParameterSets)) {
				GF_AVCConfigSlot *p = (GF_AVCConfigSlot*)gf_list_get(svcc->pictureParameterSets, 0);
				gf_list_rem(svcc->pictureParameterSets, 0);
				gf_list_add(avcc->pictureParameterSets, p);
			}
			gf_odf_avc_cfg_del(svcc);
		}
		if (avcc) {
			gf_odf_avc_cfg_write(avcc, &avc->emul_esd->decoderConfig->decoderSpecificInfo->data, &avc->emul_esd->decoderConfig->decoderSpecificInfo->dataLength);
			gf_odf_avc_cfg_del(avcc);
		}
	} else if (avc->svc_config) {
		svcc = AVC_DuplicateConfig(avc->svc_config->config);
		gf_odf_avc_cfg_write(svcc, &avc->emul_esd->decoderConfig->decoderSpecificInfo->data, &avc->emul_esd->decoderConfig->decoderSpecificInfo->dataLength);
		gf_odf_avc_cfg_del(svcc);
	}
}
Esempio n. 4
0
void gf_mse_source_buffer_del(GF_HTML_SourceBuffer *sb)
{
	GF_HTML_TrackList tlist;
	gf_html_timeranges_del(sb->buffered);
	gf_mse_reset_input_buffer(sb->input_buffer);
	gf_list_del(sb->input_buffer);

	if (sb->prev_buffer) gf_arraybuffer_del((GF_HTML_ArrayBuffer *)sb->prev_buffer, GF_FALSE);

	tlist.tracks = sb->tracks;
	gf_html_tracklist_del(&tlist);
	{
		u32 i, count;
		count = gf_list_count(sb->threads);
		for(i = 0; i < count; i++) {
			GF_Thread *t = (GF_Thread *)gf_list_get(sb->threads, i);
			gf_th_del(t);
		}
		gf_list_del(sb->threads);
	}
	gf_th_del(sb->parser_thread);
	gf_th_del(sb->remove_thread);

	if (sb->service_desc) gf_odf_desc_del((GF_Descriptor *)sb->service_desc);
	gf_free(sb);

}
Esempio n. 5
0
void gf_isom_ipmpx_remove_tool_list(GF_ISOFile *the_file)
{
	/*remove IPMPToolList if any*/
	if (the_file && the_file->moov && the_file->moov->iods && (the_file ->moov->iods->descriptor->tag == GF_ODF_ISOM_IOD_TAG) ) {
		GF_IsomInitialObjectDescriptor *iod = (GF_IsomInitialObjectDescriptor *)the_file ->moov->iods->descriptor;
		if (iod->IPMPToolList) gf_odf_desc_del((GF_Descriptor*) iod->IPMPToolList);
		iod->IPMPToolList = NULL;
	}
}
Esempio n. 6
0
GF_EXPORT
void gf_sm_reset(GF_SceneManager *ctx)
{
    GF_StreamContext *sc;
    u32 i=0;
    while ( (sc = gf_list_enum(ctx->streams, &i)) ) {
        gf_sm_reset_stream(sc);
    }
    if (ctx->root_od) gf_odf_desc_del((GF_Descriptor *) ctx->root_od);
    ctx->root_od = NULL;
}
Esempio n. 7
0
GF_Err AVC_UpdateESD(GF_MPEGVisualSampleEntryBox *avc, GF_ESD *esd)
{
	if (!avc->bitrate) avc->bitrate = (GF_MPEG4BitRateBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_BTRT);
	if (avc->descr) gf_isom_box_del((GF_Box *) avc->descr);
	avc->descr = NULL;
	avc->bitrate->avgBitrate = esd->decoderConfig->avgBitrate;
	avc->bitrate->maxBitrate = esd->decoderConfig->maxBitrate;
	avc->bitrate->bufferSizeDB = esd->decoderConfig->bufferSizeDB;

	if (gf_list_count(esd->IPIDataSet)
		|| gf_list_count(esd->IPMPDescriptorPointers)
		|| esd->langDesc
		|| gf_list_count(esd->extensionDescriptors)
		|| esd->ipiPtr || esd->qos || esd->RegDescriptor) {

		avc->descr = (GF_MPEG4ExtensionDescriptorsBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_M4DS);
		if (esd->RegDescriptor) { gf_list_add(avc->descr->descriptors, esd->RegDescriptor); esd->RegDescriptor = NULL; }
		if (esd->qos) { gf_list_add(avc->descr->descriptors, esd->qos); esd->qos = NULL; }
		if (esd->ipiPtr) { gf_list_add(avc->descr->descriptors, esd->ipiPtr); esd->ipiPtr= NULL; }

		while (gf_list_count(esd->IPIDataSet)) {
			GF_Descriptor *desc = (GF_Descriptor *)gf_list_get(esd->IPIDataSet, 0);
			gf_list_rem(esd->IPIDataSet, 0);
			gf_list_add(avc->descr->descriptors, desc);
		}
		while (gf_list_count(esd->IPMPDescriptorPointers)) {
			GF_Descriptor *desc = (GF_Descriptor *)gf_list_get(esd->IPMPDescriptorPointers, 0);
			gf_list_rem(esd->IPMPDescriptorPointers, 0);
			gf_list_add(avc->descr->descriptors, desc);
		}
		if (esd->langDesc) {
			gf_list_add(avc->descr->descriptors, esd->langDesc);
			esd->langDesc = NULL;
		}
		while (gf_list_count(esd->extensionDescriptors)) {
			GF_Descriptor *desc = (GF_Descriptor *)gf_list_get(esd->extensionDescriptors, 0);
			gf_list_rem(esd->extensionDescriptors, 0);
			gf_list_add(avc->descr->descriptors, desc);
		}
	}

	/*update GF_AVCConfig*/
	if (!avc->svc_config) {
		if (!avc->avc_config) avc->avc_config = (GF_AVCConfigurationBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_AVCC);
		if (esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) {
			if (avc->avc_config->config) gf_odf_avc_cfg_del(avc->avc_config->config);
			avc->avc_config->config = gf_odf_avc_cfg_read(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength);
		}
		gf_odf_desc_del((GF_Descriptor *)esd);
	}
	AVC_RewriteESDescriptor(avc);
	return GF_OK;
}
Esempio n. 8
0
static void recompute_bitrate_mp4( GF_ISOFile *p_file, int i_track )
{
    u32 count, di, timescale, time_wnd, rate;
    u64 offset;
    Double br;
    GF_ESD *esd;

    esd = gf_isom_get_esd( p_file, i_track, 1 );
    if( !esd )
        return;

    esd->decoderConfig->avgBitrate = 0;
    esd->decoderConfig->maxBitrate = 0;
    rate = time_wnd = 0;

    timescale = gf_isom_get_media_timescale( p_file, i_track );
    count = gf_isom_get_sample_count( p_file, i_track );
    for( u32 i = 0; i < count; i++ )
    {
        GF_ISOSample *samp = gf_isom_get_sample_info( p_file, i_track, i+1, &di, &offset );
        if( !samp )
        {
            x264_cli_log( "mp4", X264_LOG_ERROR, "failure reading back frame %u\n", i );
            break;
        }

        if( esd->decoderConfig->bufferSizeDB < samp->dataLength )
            esd->decoderConfig->bufferSizeDB = samp->dataLength;

        esd->decoderConfig->avgBitrate += samp->dataLength;
        rate += samp->dataLength;
        if( samp->DTS > time_wnd + timescale )
        {
            if( rate > esd->decoderConfig->maxBitrate )
                esd->decoderConfig->maxBitrate = rate;
            time_wnd = samp->DTS;
            rate = 0;
        }

        gf_isom_sample_del( &samp );
    }

    br = (Double)(s64)gf_isom_get_media_duration( p_file, i_track );
    br /= timescale;
    esd->decoderConfig->avgBitrate = (u32)(esd->decoderConfig->avgBitrate / br);
    /*move to bps*/
    esd->decoderConfig->avgBitrate *= 8;
    esd->decoderConfig->maxBitrate *= 8;

    gf_isom_change_mpeg4_description( p_file, i_track, 1, esd );
    gf_odf_desc_del( (GF_Descriptor*)esd );
}
Esempio n. 9
0
GF_EXPORT
void gf_sm_del(GF_SceneManager *ctx)
{
    u32 count;
    while ( (count = gf_list_count(ctx->streams)) ) {
        GF_StreamContext *sc = (GF_StreamContext *)gf_list_get(ctx->streams, count-1);
        gf_list_rem(ctx->streams, count-1);
        gf_sm_delete_stream(sc);
    }
    gf_list_del(ctx->streams);
    if (ctx->root_od) gf_odf_desc_del((GF_Descriptor *) ctx->root_od);
    gf_free(ctx);
}
Esempio n. 10
0
GF_Err LSR_UpdateESD(GF_LASeRSampleEntryBox *lsr, GF_ESD *esd)
{
	if (!lsr->bitrate) lsr->bitrate = (GF_MPEG4BitRateBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_BTRT);
	if (lsr->descr) gf_isom_box_del((GF_Box *) lsr->descr);
	lsr->descr = NULL;
	lsr->bitrate->avgBitrate = esd->decoderConfig->avgBitrate;
	lsr->bitrate->maxBitrate = esd->decoderConfig->maxBitrate;
	lsr->bitrate->bufferSizeDB = esd->decoderConfig->bufferSizeDB;

	if (gf_list_count(esd->IPIDataSet)
		|| gf_list_count(esd->IPMPDescriptorPointers)
		|| esd->langDesc
		|| gf_list_count(esd->extensionDescriptors)
		|| esd->ipiPtr || esd->qos || esd->RegDescriptor) {

		lsr->descr = (GF_MPEG4ExtensionDescriptorsBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_M4DS);
		if (esd->RegDescriptor) { gf_list_add(lsr->descr->descriptors, esd->RegDescriptor); esd->RegDescriptor = NULL; }
		if (esd->qos) { gf_list_add(lsr->descr->descriptors, esd->qos); esd->qos = NULL; }
		if (esd->ipiPtr) { gf_list_add(lsr->descr->descriptors, esd->ipiPtr); esd->ipiPtr= NULL; }

		while (gf_list_count(esd->IPIDataSet)) {
			GF_Descriptor *desc = (GF_Descriptor *)gf_list_get(esd->IPIDataSet, 0);
			gf_list_rem(esd->IPIDataSet, 0);
			gf_list_add(lsr->descr->descriptors, desc);
		}
		while (gf_list_count(esd->IPMPDescriptorPointers)) {
			GF_Descriptor *desc = (GF_Descriptor *)gf_list_get(esd->IPMPDescriptorPointers, 0);
			gf_list_rem(esd->IPMPDescriptorPointers, 0);
			gf_list_add(lsr->descr->descriptors, desc);
		}
		if (esd->langDesc) {
			gf_list_add(lsr->descr->descriptors, esd->langDesc);
			esd->langDesc = NULL;
		}
		while (gf_list_count(esd->extensionDescriptors)) {
			GF_Descriptor *desc = (GF_Descriptor *)gf_list_get(esd->extensionDescriptors, 0);
			gf_list_rem(esd->extensionDescriptors, 0);
			gf_list_add(lsr->descr->descriptors, desc);
		}
	}

	/*update GF_AVCConfig*/
	if (!lsr->lsr_config) lsr->lsr_config = (GF_LASERConfigurationBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_LSRC);
	if (esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) {
		lsr->lsr_config->hdr = gf_realloc(lsr->lsr_config->hdr, sizeof(char) * esd->decoderConfig->decoderSpecificInfo->dataLength);
		lsr->lsr_config->hdr_size = esd->decoderConfig->decoderSpecificInfo->dataLength;
		memcpy(lsr->lsr_config->hdr, esd->decoderConfig->decoderSpecificInfo->data, sizeof(char)*esd->decoderConfig->decoderSpecificInfo->dataLength);
	}
	gf_odf_desc_del((GF_Descriptor *)esd);
	return GF_OK;
}
Esempio n. 11
0
File: saf_in.c Progetto: Bevara/GPAC
static GF_Err SAF_DisconnectChannel(GF_InputService *plug, LPNETCHANNEL channel)
{
	SAFChannel *ch;
	SAFIn *read = (SAFIn *)plug->priv;

	GF_Err e = GF_STREAM_NOT_FOUND;
	ch = saf_get_channel(read, 0, channel);
	if (ch) {
		gf_list_del_item(read->channels, ch);
		if (ch->esd) gf_odf_desc_del((GF_Descriptor*)ch->esd);
		gf_free(ch);
		e = GF_OK;
	}
	gf_service_disconnect_ack(read->service, channel, e);
	return GF_OK;
}
Esempio n. 12
0
static GF_Descriptor *RP_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url)
{
	GF_Descriptor *desc;
	RTPClient *priv = (RTPClient *)plug->priv;

	GF_LOG(GF_LOG_DEBUG, GF_LOG_RTP, ("[RTP] Fetching service descriptor\n"));
	if ((expect_type!=GF_MEDIA_OBJECT_UNDEF) && (expect_type!=GF_MEDIA_OBJECT_SCENE) && (expect_type!=GF_MEDIA_OBJECT_UPDATES)) {
		/*ignore the SDP IOD and regenerate one*/
		if (priv->session_desc) gf_odf_desc_del(priv->session_desc);
		priv->session_desc = NULL;
		priv->media_type = expect_type;
		return RP_EmulateIOD(priv, sub_url);
	}

	desc = priv->session_desc;
	priv->session_desc = NULL;
	return desc;
}
Esempio n. 13
0
static GF_Err TTD_DetachStream(GF_BaseDecoder *plug, u16 ES_ID)
{
	TTDPriv *priv = (TTDPriv *)plug->privateStack;
	if (!priv->nb_streams) return GF_BAD_PARAM;

	gf_scene_register_extra_graph(priv->inlineScene, priv->sg, 1);

	gf_node_unregister((GF_Node *) priv->ts_blink, NULL);
	gf_node_unregister((GF_Node *) priv->process_blink, NULL);
	gf_node_unregister((GF_Node *) priv->ts_scroll, NULL);
	gf_node_unregister((GF_Node *) priv->process_scroll, NULL);

	gf_sg_del(priv->sg);
	priv->sg = NULL;
	if (priv->cfg) gf_odf_desc_del((GF_Descriptor *) priv->cfg);
	priv->cfg = NULL;
	priv->nb_streams = 0;
	gf_list_del(priv->blink_nodes);
	return GF_OK;
}
Esempio n. 14
0
File: saf_in.c Progetto: Bevara/GPAC
void DeleteSAFReader(void *ifce)
{
	GF_InputService *plug = (GF_InputService *) ifce;
	SAFIn *read = (SAFIn *)plug->priv;
	if (!ifce)
		return;
	while (gf_list_count(read->channels)) {
		SAFChannel *ch = (SAFChannel *)gf_list_last(read->channels);
		gf_list_rem_last(read->channels);
		if (ch->esd) gf_odf_desc_del((GF_Descriptor *) ch->esd);
		gf_free(ch);
	}
	gf_list_del(read->channels);
	if (read->saf_data)
		gf_free(read->saf_data);
	read->saf_data = NULL;
	gf_free(read);
	plug->priv = NULL;
	gf_free(plug);
}
Esempio n. 15
0
static GF_Descriptor *MPD_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url)
{
	u32 i;
	GF_MPD_In *mpdin = (GF_MPD_In*) plug->priv;
	GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] Received Service Description request from terminal for %s\n", sub_url));
	for (i=0; i<gf_dash_get_group_count(mpdin->dash); i++) {
		GF_Descriptor *desc;
		GF_MPDGroup *mudta;
#if 0
		if (!gf_dash_is_group_selected(mpdin->dash, i))
			continue;
#endif
		mudta = gf_dash_get_group_udta(mpdin->dash, i);
		if (!mudta) continue;
		if (mudta->service_descriptor_fetched) continue;

		desc = mudta->segment_ifce->GetServiceDescriptor(mudta->segment_ifce, expect_type, sub_url);
		if (desc) mudta->service_descriptor_fetched = 1;
		gf_odf_desc_del(desc);
	}
	return NULL;
}
Esempio n. 16
0
File: odf_dec.c Progetto: erelh/gpac
static GF_Err ODS_UpdateESD(ODPriv *priv, GF_ESDUpdate *ESDs)
{
    GF_ESD *esd, *prev;
    GF_ObjectManager *odm;
    u32 count, i;

    odm = gf_scene_find_odm(priv->scene, ESDs->ODID);
    /*spec: "ignore"*/
    if (!odm) return GF_OK;

    count = gf_list_count(ESDs->ESDescriptors);

    while (count) {
        esd = (GF_ESD*)gf_list_get(ESDs->ESDescriptors, 0);
        /*spec: "ES_Descriptors with ES_IDs that have already been received within the same name scope shall be ignored."*/
        prev = NULL;
        i=0;
        while ((prev = (GF_ESD*)gf_list_enum(odm->OD->ESDescriptors, &i))) {
            if (prev->ESID == esd->ESID) break;
        }
        if (prev) {
            gf_odf_desc_del((GF_Descriptor *)esd);
        } else {
            /*and register new stream*/
            gf_list_add(odm->OD->ESDescriptors, esd);
            gf_odm_setup_es(odm, esd, odm->net_service, NULL);
        }

        /*remove the desc from the AU*/
        gf_list_rem(ESDs->ESDescriptors, 0);
        count--;
    }
    /*resetup object since a new ES has been inserted
    (typically an empty object first sent, then a stream added - cf how ogg demuxer works)*/
    gf_scene_setup_object(priv->scene, odm);
    return GF_OK;
}
Esempio n. 17
0
static GF_Err gf_sm_setup_lsrenc(GF_SceneEngine *seng, GF_StreamContext *sc, GF_ESD *esd)
{
	char *data;
	u32 data_len;
	GF_LASERConfig lsr_cfg;

	if (!esd->decoderConfig || (esd->decoderConfig->streamType != GF_STREAM_SCENE)) return GF_BAD_PARAM;

	seng->lsrenc = gf_laser_encoder_new(seng->ctx->scene_graph);

	/*inputctx is not properly setup, do it*/
	if (!esd->decoderConfig->decoderSpecificInfo) {
		memset(&lsr_cfg, 0, sizeof(GF_LASERConfig));
	}
	/*regular case*/
	else if (esd->decoderConfig->decoderSpecificInfo->tag == GF_ODF_LASER_CFG_TAG) {
		memcpy(&lsr_cfg, (GF_LASERConfig *)esd->decoderConfig->decoderSpecificInfo, sizeof(GF_LASERConfig) );
	}
	/*happens when loading from MP4 in which case BIFSc is not decoded*/
	else {
		gf_odf_get_laser_config(esd->decoderConfig->decoderSpecificInfo, &lsr_cfg);
	}

	gf_laser_encoder_new_stream(seng->lsrenc, esd->ESID , &lsr_cfg);

	gf_laser_encoder_get_config(seng->lsrenc, esd->ESID, &data, &data_len);

	if (esd->decoderConfig->decoderSpecificInfo) gf_odf_desc_del((GF_Descriptor *) esd->decoderConfig->decoderSpecificInfo);
	esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG);
	esd->decoderConfig->decoderSpecificInfo->data = data;
	esd->decoderConfig->decoderSpecificInfo->dataLength = data_len;
		
	sc->dec_cfg = gf_malloc(sizeof(char)*data_len);
	memcpy(sc->dec_cfg, data, data_len);
	sc->dec_cfg_len = data_len;
	return GF_OK;
}
Esempio n. 18
0
static void RP_cleanup(RTPClient *rtp)
{
	RTSPSession *sess;

	while (gf_list_count(rtp->channels)) {
		RTPStream *ch = (RTPStream *)gf_list_get(rtp->channels, 0);
		gf_list_rem(rtp->channels, 0);
		RP_DeleteStream(ch);
	}

	while ( (sess = (RTSPSession *)gf_list_last(rtp->sessions)) ) {
		gf_list_rem_last(rtp->sessions);
		RP_DelSession(sess);
	}

	if (rtp->session_desc) gf_odf_desc_del(rtp->session_desc);
	rtp->session_desc = NULL;

	if (rtp->sdp_temp) {
		gf_free(rtp->sdp_temp->remote_url);
		gf_free(rtp->sdp_temp);
	}
	rtp->sdp_temp = NULL;
}
Esempio n. 19
0
static GF_Err gf_isom_streamer_setup_sdp(GF_ISOMRTPStreamer *streamer, char*sdpfilename, char **out_sdp_buffer)
{
	GF_RTPTrack *track;
	FILE *sdp_out;
	char filename[GF_MAX_PATH];
	char sdpLine[20000];
	u32 t, count;
	u8 *payload_type;

	strcpy(filename, sdpfilename ? sdpfilename : "videosession.sdp");
	sdp_out = gf_fopen(filename, "wt");
	if (!sdp_out) return GF_IO_ERR;

	if (!out_sdp_buffer) {
		sprintf(sdpLine, "v=0");
		fprintf(sdp_out, "%s\n", sdpLine);
		sprintf(sdpLine, "o=MP4Streamer 3357474383 1148485440000 IN IP%d %s", gf_net_is_ipv6(streamer->dest_ip) ? 6 : 4, streamer->dest_ip);
		fprintf(sdp_out, "%s\n", sdpLine);
		sprintf(sdpLine, "s=livesession");
		fprintf(sdp_out, "%s\n", sdpLine);
		sprintf(sdpLine, "i=This is an MP4 time-sliced Streaming demo");
		fprintf(sdp_out, "%s\n", sdpLine);
		sprintf(sdpLine, "u=http://gpac.sourceforge.net");
		fprintf(sdp_out, "%s\n", sdpLine);
		sprintf(sdpLine, "e=admin@");
		fprintf(sdp_out, "%s\n", sdpLine);
		sprintf(sdpLine, "c=IN IP%d %s", gf_net_is_ipv6(streamer->dest_ip) ? 6 : 4, streamer->dest_ip);
		fprintf(sdp_out, "%s\n", sdpLine);
		sprintf(sdpLine, "t=0 0");
		fprintf(sdp_out, "%s\n", sdpLine);
		sprintf(sdpLine, "a=x-copyright: Streamed with GPAC (C)2000-200X - http://gpac.sourceforge.net");
		fprintf(sdp_out, "%s\n", sdpLine);
		if (streamer->base_track)
		{
			sprintf(sdpLine, "a=group:DDP L%d", streamer->base_track);
			fprintf(sdp_out, "%s", sdpLine);
			count = gf_isom_get_track_count(streamer->isom);
			for (t = 0; t < count; t++)
			{
				if (gf_isom_has_track_reference(streamer->isom, t+1, GF_ISOM_REF_BASE, gf_isom_get_track_id(streamer->isom, streamer->base_track)))
				{
					sprintf(sdpLine, " L%d", t+1);
					fprintf(sdp_out, "%s", sdpLine);
				}
			}
			fprintf(sdp_out, "\n");
		}
	}

	/*prepare array of payload type*/
	count = gf_isom_get_track_count(streamer->isom);
	payload_type = (u8 *)gf_malloc(count * sizeof(u8));
	track = streamer->stream;
	while (track) {
		payload_type[track->track_num-1] = gf_rtp_streamer_get_payload_type(track->rtp);
		track = track->next;
	}


	track = streamer->stream;
	while (track) {
		char *sdp_media=NULL;
		const char *KMS = NULL;
		char *dsi = NULL;
		u32 w, h;
		u32 dsi_len = 0;
		GF_DecoderConfig *dcd;
		//use inspect mode so that we don't aggregate xPS from the base in the enhancement ESD
		gf_isom_set_nalu_extract_mode(streamer->isom, track->track_num, GF_ISOM_NALU_EXTRACT_INSPECT);
		dcd = gf_isom_get_decoder_config(streamer->isom, track->track_num, 1);

		if (dcd && dcd->decoderSpecificInfo) {
			dsi = dcd->decoderSpecificInfo->data;
			dsi_len = dcd->decoderSpecificInfo->dataLength;
		}
		w = h = 0;
		if (gf_isom_get_media_type(streamer->isom, track->track_num) == GF_ISOM_MEDIA_VISUAL) {
			gf_isom_get_visual_info(streamer->isom, track->track_num, 1, &w, &h);
		}

		gf_isom_get_ismacryp_info(streamer->isom, track->track_num, 1, NULL, NULL, NULL, NULL, &KMS, NULL, NULL, NULL);

		/*TODO retrieve DIMS content encoding from track to set the flags */
		gf_rtp_streamer_append_sdp_extended(track->rtp, gf_isom_get_track_id(streamer->isom, track->track_num), dsi, dsi_len, streamer->isom, track->track_num, (char *)KMS, w, h, &sdp_media);
		if (streamer->base_track)
			gf_rtp_streamer_append_sdp_decoding_dependency(streamer->isom, track->track_num, payload_type, &sdp_media);
		if (sdp_media) {
			fprintf(sdp_out, "%s", sdp_media);
			gf_free(sdp_media);
		}

		if (dcd) gf_odf_desc_del((GF_Descriptor *)dcd);

		track = track->next;
	}
	fprintf(sdp_out, "\n");

	gf_fclose(sdp_out);
	if (out_sdp_buffer) {
		u64 size;
		sdp_out = gf_fopen(filename, "r");
		gf_fseek(sdp_out, 0, SEEK_END);
		size = gf_ftell(sdp_out);
		gf_fseek(sdp_out, 0, SEEK_SET);
		if (*out_sdp_buffer) gf_free(*out_sdp_buffer);
		*out_sdp_buffer = gf_malloc(sizeof(char)*(size_t)(size+1));
		size = fread(*out_sdp_buffer, 1, (size_t)size, sdp_out);
		gf_fclose(sdp_out);
		(*out_sdp_buffer)[size]=0;
	}

	gf_free(payload_type);
	return GF_OK;
}
Esempio n. 20
0
GF_Err Track_SetStreamDescriptor(GF_TrackBox *trak, u32 StreamDescriptionIndex, u32 DataReferenceIndex, GF_ESD *esd, u32 *outStreamIndex)
{
    GF_Err e;
    GF_MPEGSampleEntryBox *entry;
    GF_MPEGVisualSampleEntryBox *entry_v;
    GF_MPEGAudioSampleEntryBox *entry_a;
    GF_TrackReferenceBox *tref;
    GF_TrackReferenceTypeBox *dpnd;
    u16 tmpRef;

    entry = NULL;
    tref = NULL;

    if (!trak || !esd || (!outStreamIndex && !DataReferenceIndex) ) return GF_BAD_PARAM;
    if (!Track_IsMPEG4Stream(trak->Media->handler->handlerType)) return GF_ISOM_INVALID_MEDIA;


    esd->ESID = 0;
    //set SL to predefined if no url
    if (esd->URLString == NULL) {
        if (!esd->slConfig) esd->slConfig = (GF_SLConfig*) gf_odf_desc_new(GF_ODF_SLC_TAG);
        esd->slConfig->predefined = SLPredef_MP4;
        esd->slConfig->durationFlag = 0;
        esd->slConfig->useTimestampsFlag = 1;
    }

    //get the REF box if needed
    if (esd->dependsOnESID  || esd->OCRESID ) {
        if (!trak->References) {
            tref = (GF_TrackReferenceBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TREF);
            e = trak_AddBox((GF_Box*)trak, (GF_Box *)tref);
            if (e) return e;
        }
        tref = trak->References;
    }

    //Update Stream dependancies
    e = Track_FindRef(trak, GF_ISOM_REF_DECODE, &dpnd);
    if (e) return e;
    if (!dpnd && esd->dependsOnESID) {
        dpnd = (GF_TrackReferenceTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_REFT);
        dpnd->reference_type = GF_ISOM_BOX_TYPE_DPND;
        e = tref_AddBox((GF_Box*)tref, (GF_Box *) dpnd);
        if (e) return e;
        e = reftype_AddRefTrack(dpnd, esd->dependsOnESID, NULL);
        if (e) return e;
    } else if (dpnd && !esd->dependsOnESID) {
        Track_RemoveRef(trak, GF_ISOM_BOX_TYPE_DPND);
    }
    esd->dependsOnESID = 0;

    //Update GF_Clock dependancies
    e = Track_FindRef(trak, GF_ISOM_REF_OCR, &dpnd);
    if (e) return e;
    if (!dpnd && esd->OCRESID) {
        dpnd = (GF_TrackReferenceTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_REFT);
        dpnd->reference_type = GF_ISOM_BOX_TYPE_SYNC;
        e = tref_AddBox((GF_Box*)tref, (GF_Box *) dpnd);
        if (e) return e;
        e = reftype_AddRefTrack(dpnd, esd->OCRESID, NULL);
        if (e) return e;
    } else if (dpnd && !esd->OCRESID) {
        Track_RemoveRef(trak, GF_ISOM_BOX_TYPE_SYNC);
    } else if (dpnd && esd->OCRESID) {
        if (dpnd->trackIDCount != 1) return GF_ISOM_INVALID_MEDIA;
        dpnd->trackIDs[0] = esd->OCRESID;
    }
    esd->OCRESID = 0;

    //brand new case: we have to change the IPI desc
    if (esd->ipiPtr) {
        e = Track_FindRef(trak, GF_ISOM_REF_IPI, &dpnd);
        if (e) return e;
        if (!dpnd) {
            tmpRef = 0;
            dpnd = (GF_TrackReferenceTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_REFT);
            dpnd->reference_type = GF_ISOM_BOX_TYPE_IPIR;
            e = tref_AddBox((GF_Box*)tref, (GF_Box *) dpnd);
            if (e) return e;
            e = reftype_AddRefTrack(dpnd, esd->ipiPtr->IPI_ES_Id, &tmpRef);
            if (e) return e;
            //and replace the tag and value...
            esd->ipiPtr->IPI_ES_Id = tmpRef;
            esd->ipiPtr->tag = GF_ODF_ISOM_IPI_PTR_TAG;
        } else {
            //Watch out! ONLY ONE IPI dependancy is allowed per stream
            if (dpnd->trackIDCount != 1) return GF_ISOM_INVALID_MEDIA;
            //if an existing one is there, what shall we do ???
            //donno, erase it
            dpnd->trackIDs[0] = esd->ipiPtr->IPI_ES_Id;
            //and replace the tag and value...
            esd->ipiPtr->IPI_ES_Id = 1;
            esd->ipiPtr->tag = GF_ODF_ISOM_IPI_PTR_TAG;
        }
    }

    /*don't store the lang desc in ESD, use the media header language info*/
    if (esd->langDesc) {
        trak->Media->mediaHeader->packedLanguage[0] = (esd->langDesc->langCode>>16)&0xFF;
        trak->Media->mediaHeader->packedLanguage[1] = (esd->langDesc->langCode>>8)&0xFF;
        trak->Media->mediaHeader->packedLanguage[2] = (esd->langDesc->langCode)&0xFF;
        gf_odf_desc_del((GF_Descriptor *)esd->langDesc);
        esd->langDesc = NULL;
    }
Esempio n. 21
0
//extraction of the ESD from the track
GF_Err GetESD(GF_MovieBox *moov, u32 trackID, u32 StreamDescIndex, GF_ESD **outESD)
{
    GF_Err e;
    GF_ESD *esd;
    u32 track_num = 0;
    GF_SampleTableBox *stbl;
    GF_TrackBox *trak, *OCRTrack;
    GF_TrackReferenceTypeBox *dpnd;
    GF_SLConfig *slc;
    GF_MPEGSampleEntryBox *entry;

    track_num = gf_isom_get_tracknum_from_id(moov, trackID);
    dpnd = NULL;
    *outESD = NULL;

    trak = gf_isom_get_track(moov, track_num);
    if (!trak) return GF_ISOM_INVALID_FILE;

    e = Media_GetESD(trak->Media, StreamDescIndex, &esd, 0);
    if (e) return e;

    e = Media_GetSampleDesc(trak->Media, StreamDescIndex, (GF_SampleEntryBox **) &entry, NULL);
    if (e) return e;
    //set the ID
    esd->ESID = trackID;

    //find stream dependencies
    e = Track_FindRef(trak, GF_ISOM_BOX_TYPE_DPND , &dpnd);
    if (e) return e;
    if (dpnd) {
        //ONLY ONE STREAM DEPENDENCY IS ALLOWED
        if (dpnd->trackIDCount != 1) return GF_ISOM_INVALID_MEDIA;
        //fix the spec: where is the index located ??
        esd->dependsOnESID = dpnd->trackIDs[0];
    } else {
        esd->dependsOnESID = 0;
    }

    if (trak->udta) {
        GF_UserDataMap *map;
        u32 i = 0;
        while ((map = (GF_UserDataMap*)gf_list_enum(trak->udta->recordList, &i))) {
            if (map->boxType == GF_4CC('A','U','X','V')) {
                GF_Descriptor *d = gf_odf_desc_new(GF_ODF_AUX_VIDEO_DATA);
                gf_list_add(esd->extensionDescriptors, d);
                break;
            }
        }
    }

    //OK, get the OCR (in a REAL MP4File, OCR is 0 in ESD and is specified through track reference
    dpnd = NULL;
    OCRTrack = NULL;
    //find OCR dependencies
    e = Track_FindRef(trak, GF_ISOM_BOX_TYPE_SYNC, &dpnd);
    if (e) return e;
    if (dpnd) {
        if (dpnd->trackIDCount != 1) return GF_ISOM_INVALID_MEDIA;
        esd->OCRESID = dpnd->trackIDs[0];
        OCRTrack = gf_isom_get_track_from_id(trak->moov, dpnd->trackIDs[0]);

        while (OCRTrack) {
            /*if we have a dependency on a track that doesn't have OCR dep, remove that dependency*/
            e = Track_FindRef(OCRTrack, GF_ISOM_BOX_TYPE_SYNC, &dpnd);
            if (e || !dpnd || !dpnd->trackIDCount) {
                OCRTrack = NULL;
                goto default_sync;
            }
            /*this is explicit desync*/
            if (dpnd && ((dpnd->trackIDs[0]==0) || (dpnd->trackIDs[0]==OCRTrack->Header->trackID))) break;
            /*loop in OCRs, break it*/
            if (esd->ESID == OCRTrack->Header->trackID) {
                OCRTrack = NULL;
                goto default_sync;
            }
            /*check next*/
            OCRTrack = gf_isom_get_track_from_id(trak->moov, dpnd->trackIDs[0]);
        }
        if (!OCRTrack) goto default_sync;
    } else {
default_sync:
        /*all tracks are sync'ed by default*/
        if (trak->moov->mov->es_id_default_sync<0) {
            if (esd->OCRESID)
                trak->moov->mov->es_id_default_sync = esd->OCRESID;
            else
                trak->moov->mov->es_id_default_sync = esd->ESID;
        }
        if (trak->moov->mov->es_id_default_sync) esd->OCRESID = (u16) trak->moov->mov->es_id_default_sync;
        /*cf ESD writer*/
        if (esd->OCRESID == esd->ESID) esd->OCRESID = 0;
    }



    //update the IPI stuff if needed
    if (esd->ipiPtr != NULL) {
        dpnd = NULL;
        e = Track_FindRef(trak, GF_ISOM_BOX_TYPE_IPIR, &dpnd);
        if (e) return e;
        if (dpnd) {
            if (esd->ipiPtr->tag != GF_ODF_ISOM_IPI_PTR_TAG) return GF_ISOM_INVALID_FILE;
            //OK, retrieve the ID: the IPI_ES_Id is currently the ref track
            esd->ipiPtr->IPI_ES_Id = dpnd->trackIDs[esd->ipiPtr->IPI_ES_Id - 1];
            //and change the tag
            esd->ipiPtr->tag = GF_ODF_IPI_PTR_TAG;
        } else {
            return GF_ISOM_INVALID_FILE;
        }
    }

    if ((trak->Media->mediaHeader->packedLanguage[0] != 'u')
            || (trak->Media->mediaHeader->packedLanguage[1] != 'n')
            || (trak->Media->mediaHeader->packedLanguage[2] != 'd') ) {
        if (!esd->langDesc) esd->langDesc = (GF_Language *) gf_odf_desc_new(GF_ODF_LANG_TAG);

        esd->langDesc->langCode = trak->Media->mediaHeader->packedLanguage[0];
        esd->langDesc->langCode <<= 8;
        esd->langDesc->langCode |= trak->Media->mediaHeader->packedLanguage[1];
        esd->langDesc->langCode <<= 8;
        esd->langDesc->langCode |= trak->Media->mediaHeader->packedLanguage[2];
    }


    {
        u16 rvc_predefined;
        char *rvc_cfg_data;
        const char *mime_type;
        u32 rvc_cfg_size;
        e = gf_isom_get_rvc_config(moov->mov, track_num, 1, &rvc_predefined, &rvc_cfg_data, &rvc_cfg_size, &mime_type);
        if (e==GF_OK) {
            if (rvc_predefined) {
                esd->decoderConfig->predefined_rvc_config = rvc_predefined;
            } else {
                esd->decoderConfig->rvc_config = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG);
                if (mime_type && !strcmp(mime_type, "application/rvc-config+xml+gz") ) {
#if !defined(GPAC_DISABLE_CORE_TOOLS) && !defined(GPAC_DISABLE_ZLIB)
                    gf_gz_decompress_payload(rvc_cfg_data, rvc_cfg_size, &esd->decoderConfig->rvc_config->data, &esd->decoderConfig->rvc_config->dataLength);
                    gf_free(rvc_cfg_data);
#endif
                } else {
                    esd->decoderConfig->rvc_config->data = rvc_cfg_data;
                    esd->decoderConfig->rvc_config->dataLength = rvc_cfg_size;
                }
            }
        }
    }


    /*normally all files shall be stored with predefined=SLPredef_MP4, but of course some are broken (philips)
    so we just check the ESD_URL. If set, use the given cfg, otherwise always rewrite it*/
    if (esd->URLString != NULL) {
        *outESD = esd;
        return GF_OK;
    }

    //if we are in publishing mode and we have an SLConfig specified, use it as is
    switch (entry->type) {
    case GF_ISOM_BOX_TYPE_MP4V:
        slc = ((GF_MPEGVisualSampleEntryBox *)entry)->slc;
        break;
    case GF_ISOM_BOX_TYPE_MP4A:
        slc = ((GF_MPEGAudioSampleEntryBox *)entry)->slc;
        break;
    case GF_ISOM_BOX_TYPE_MP4S:
        slc = entry->slc;
        break;
    default:
        slc = NULL;
        break;
    }
    if (slc) {
        gf_odf_desc_del((GF_Descriptor *)esd->slConfig);
        gf_odf_desc_copy((GF_Descriptor *)slc, (GF_Descriptor **)&esd->slConfig);
        *outESD = esd;
        return GF_OK;
    }
    //otherwise use the regular mapping

    //this is a desc for a media in the file, let's rewrite some param
    esd->slConfig->timestampLength = 32;
    esd->slConfig->timestampResolution = trak->Media->mediaHeader->timeScale;
    //NO OCR from MP4File streams (eg, constant OC Res one)
    esd->slConfig->OCRLength = 0;
    esd->slConfig->OCRResolution = 0;
//	if (OCRTrack) esd->slConfig->OCRResolution = OCRTrack->Media->mediaHeader->timeScale;

    stbl = trak->Media->information->sampleTable;
    // a little optimization here: if all our samples are sync,
    //set the RAPOnly to true... for external users...
    if (! stbl->SyncSample) {
        esd->slConfig->hasRandomAccessUnitsOnlyFlag = 1;
        esd->slConfig->useRandomAccessPointFlag = 0;
    } else {
        esd->slConfig->hasRandomAccessUnitsOnlyFlag = 0;
        //signal we are NOT using sync points if no info is present in the table
        esd->slConfig->useRandomAccessPointFlag = stbl->SyncSample->nb_entries ? 1 : 0;
    }
    //do we have DegradationPriority ?
    if (stbl->DegradationPriority) {
        esd->slConfig->degradationPriorityLength = 15;
    } else {
        esd->slConfig->degradationPriorityLength = 0;
    }
    //paddingBits
    if (stbl->PaddingBits) {
        esd->slConfig->usePaddingFlag = 1;
    }
    //change to support reflecting OD streams
    esd->slConfig->useAccessUnitEndFlag = 1;
    esd->slConfig->useAccessUnitStartFlag = 1;

    //signal we do have padding flag (since we only use logical SL packet
    //the user can decide whether to use the info or not
    esd->slConfig->usePaddingFlag = stbl->PaddingBits ? 1 : 0;

    //same with degradation priority
    esd->slConfig->degradationPriorityLength = stbl->DegradationPriority ? 32 : 0;

    //this new SL will be OUT OF THE FILE. Let's set its predefined to 0
    esd->slConfig->predefined = 0;


    *outESD = esd;
    return GF_OK;
}
Esempio n. 22
0
static void term_on_media_add(void *user_priv, GF_ClientService *service, GF_Descriptor *media_desc, Bool no_scene_check)
{
	u32 i, min_od_id;
	GF_MediaObject *the_mo;
	GF_Scene *scene;
	GF_ObjectManager *odm, *root;
	GF_ObjectDescriptor *od;
	GET_TERM();

	root = service->owner;
	if (!root) {
	  GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[Service %s] has not root, aborting !\n", service->url));
	  return;
	}
	if (root->flags & GF_ODM_DESTROYED) {
	  GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[Service %s] root has been scheduled for destruction - aborting !\n", service->url));
	  return;
	}
	scene = root->subscene ? root->subscene : root->parentscene;

	GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Service %s] %s\n", service->url, media_desc ? "Adding new media object" : "Regenerating scene graph"));
	if (!media_desc) {
		if (!no_scene_check) gf_scene_regenerate(scene);
		return;
	}

	switch (media_desc->tag) {
	case GF_ODF_OD_TAG:
	case GF_ODF_IOD_TAG:
		if (root && (root->net_service == service)) {
			od = (GF_ObjectDescriptor *) media_desc;
			break;
		}
	default:
		gf_odf_desc_del(media_desc);
		return;
	}

	gf_term_lock_net(term, 1);
	/*object declared this way are not part of an OD stream and are considered as dynamic*/
/*	od->objectDescriptorID = GF_MEDIA_EXTERNAL_ID; */

	/*check if we have a mediaObject in the scene not attached and matching this object*/
	the_mo = NULL;
	odm = NULL;
	min_od_id = 0;
	for (i=0; i<gf_list_count(scene->scene_objects); i++) {
		char *frag, *ext;
		GF_ESD *esd;
		char *url;
		u32 match_esid = 0;
		GF_MediaObject *mo = gf_list_get(scene->scene_objects, i);

		if ((mo->OD_ID != GF_MEDIA_EXTERNAL_ID) && (min_od_id<mo->OD_ID))
			min_od_id = mo->OD_ID;

		if (!mo->odm) continue;
		/*if object is attached to a service, don't bother looking in a different one*/
		if (mo->odm->net_service && (mo->odm->net_service != service)) continue;

		/*already assigned object - this may happen since the compositor has no control on when objects are declared by the service,
		therefore opening file#video and file#audio may result in the objects being declared twice if the service doesn't
		keep track of declared objects*/
		if (mo->odm->OD) {
			if (od->objectDescriptorID && is_same_od(mo->odm->OD, od)) {
				/*reassign OD ID*/
				mo->OD_ID = od->objectDescriptorID;
				gf_odf_desc_del(media_desc);
				gf_term_lock_net(term, 0);
				return;
			}
			continue;
		}
		if (mo->OD_ID != GF_MEDIA_EXTERNAL_ID) {
			if (mo->OD_ID == od->objectDescriptorID) {
				the_mo = mo;
				odm = mo->odm;
				break;
			}
			continue;
		}
		if (!mo->URLs.count || !mo->URLs.vals[0].url) continue;

		frag = NULL;
		ext = strrchr(mo->URLs.vals[0].url, '#');
		if (ext) {
			frag = strchr(ext, '=');
			ext[0] = 0;
		}
		url = mo->URLs.vals[0].url;
		if (!strnicmp(url, "file://localhost", 16)) url += 16;
		else if (!strnicmp(url, "file://", 7)) url += 7;
		else if (!strnicmp(url, "gpac://", 7)) url += 7;
		else if (!strnicmp(url, "pid://", 6)) match_esid = atoi(url+6);

		if (!match_esid && !strstr(service->url, url)) {
			if (ext) ext[0] = '#';
			continue;
		}
		if (ext) ext[0] = '#';

		esd = gf_list_get(od->ESDescriptors, 0);
		if (match_esid && (esd->ESID != match_esid))
			continue;
		/*match type*/
		switch (esd->decoderConfig->streamType) {
		case GF_STREAM_VISUAL:
			if (mo->type != GF_MEDIA_OBJECT_VIDEO) continue;
			break;
		case GF_STREAM_AUDIO:
			if (mo->type != GF_MEDIA_OBJECT_AUDIO) continue;
			break;
		case GF_STREAM_PRIVATE_MEDIA:
			if ((mo->type != GF_MEDIA_OBJECT_AUDIO) && (mo->type != GF_MEDIA_OBJECT_VIDEO)) continue;
			break;
		case GF_STREAM_SCENE:
			if (mo->type != GF_MEDIA_OBJECT_UPDATES) continue;
			break;
		default:
			continue;
		}
		if (frag) {
			u32 frag_id = 0;
			u32 ID = od->objectDescriptorID;
			if (ID==GF_MEDIA_EXTERNAL_ID) ID = esd->ESID;
			frag++;
			frag_id = atoi(frag);
			if (ID!=frag_id) continue;
		}
		the_mo = mo;
		odm = mo->odm;
		break;
	}

	/*add a pass on scene->resource to check for min_od_id,
	otherwise we may have another modules declaring an object with ID 0 from
	another thread, which will assert (only one object with a givne OD ID)*/
	for (i=0; i<gf_list_count(scene->resources); i++) {
		GF_ObjectManager *an_odm = gf_list_get(scene->resources, i);

		if (an_odm->OD && (an_odm->OD->objectDescriptorID != GF_MEDIA_EXTERNAL_ID) && (min_od_id < an_odm->OD->objectDescriptorID))
			min_od_id = an_odm->OD->objectDescriptorID;
	}

	if (!odm) {
		odm = gf_odm_new();
		odm->term = term;
		odm->parentscene = scene;
		gf_list_add(scene->resources, odm);
	}
	odm->OD = od;
	odm->mo = the_mo;
	odm->flags |= GF_ODM_NOT_IN_OD_STREAM;
	if (!od->objectDescriptorID) {
		od->objectDescriptorID = min_od_id + 1;
	}

	if (the_mo) the_mo->OD_ID = od->objectDescriptorID;
	if (!scene->selected_service_id)
		scene->selected_service_id = od->ServiceID;


	/*net is unlocked before seting up the object as this might trigger events going into JS and deadlocks
	with the compositor*/
	gf_term_lock_net(term, 0);

	GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM%d] setup object - MO %08x\n", odm->OD->objectDescriptorID, odm->mo));
	gf_odm_setup_object(odm, service);

	/*OD inserted by service: resetup scene*/
	if (!no_scene_check && scene->is_dynamic_scene) gf_scene_regenerate(scene);
}
Esempio n. 23
0
GF_EXPORT
GF_Err gf_hinter_finalize(GF_ISOFile *file, u32 IOD_Profile, u32 bandwidth)
{
	u32 i, sceneT, odT, descIndex, size, size64;
	GF_InitialObjectDescriptor *iod;
	GF_SLConfig slc;
	GF_ESD *esd;
	GF_ISOSample *samp;
	Bool remove_ocr;
	char *buffer;
	char buf64[5000], sdpLine[2300];


	gf_isom_sdp_clean(file);

	if (bandwidth) {
		sprintf(buf64, "b=AS:%d", bandwidth);
		gf_isom_sdp_add_line(file, buf64);
	}
	//xtended attribute for copyright
	sprintf(buf64, "a=x-copyright: %s", "MP4/3GP File hinted with GPAC " GPAC_FULL_VERSION " (C)2000-2005 - http://gpac.sourceforge.net");
	gf_isom_sdp_add_line(file, buf64);

	if (IOD_Profile == GF_SDP_IOD_NONE) return GF_OK;

	odT = sceneT = 0;
	for (i=0; i<gf_isom_get_track_count(file); i++) {
		if (!gf_isom_is_track_in_root_od(file, i+1)) continue;
		switch (gf_isom_get_media_type(file,i+1)) {
		case GF_ISOM_MEDIA_OD:
			odT = i+1;
			break;
		case GF_ISOM_MEDIA_SCENE:
			sceneT = i+1;
			break;
		}
	}
	remove_ocr = 0;
	if (IOD_Profile == GF_SDP_IOD_ISMA_STRICT) {
		IOD_Profile = GF_SDP_IOD_ISMA;
		remove_ocr = 1;
	}

	/*if we want ISMA like iods, we need at least BIFS */
	if ( (IOD_Profile == GF_SDP_IOD_ISMA) && !sceneT ) return GF_BAD_PARAM;

	/*do NOT change PLs, we assume they are correct*/
	iod = (GF_InitialObjectDescriptor *) gf_isom_get_root_od(file);
	if (!iod) return GF_NOT_SUPPORTED;

	/*rewrite an IOD with good SL config - embbed data if possible*/
	if (IOD_Profile == GF_SDP_IOD_ISMA) {
		Bool is_ok = 1;
		while (gf_list_count(iod->ESDescriptors)) {
			esd = (GF_ESD*)gf_list_get(iod->ESDescriptors, 0);
			gf_odf_desc_del((GF_Descriptor *) esd);
			gf_list_rem(iod->ESDescriptors, 0);
		}


		/*get OD esd, and embbed stream data if possible*/
		if (odT) {
			esd = gf_isom_get_esd(file, odT, 1);
			if (gf_isom_get_sample_count(file, odT)==1) {
				samp = gf_isom_get_sample(file, odT, 1, &descIndex);
				if (gf_hinter_can_embbed_data(samp->data, samp->dataLength, GF_STREAM_OD)) {
					InitSL_NULL(&slc);
					slc.predefined = 0;
					slc.hasRandomAccessUnitsOnlyFlag = 1;
					slc.timeScale = slc.timestampResolution = gf_isom_get_media_timescale(file, odT);	
					slc.OCRResolution = 1000;
					slc.startCTS = samp->DTS+samp->CTS_Offset;
					slc.startDTS = samp->DTS;
					//set the SL for future extraction
					gf_isom_set_extraction_slc(file, odT, 1, &slc);

					size64 = gf_base64_encode(samp->data, samp->dataLength, buf64, 2000);
					buf64[size64] = 0;
					sprintf(sdpLine, "data:application/mpeg4-od-au;base64,%s", buf64);

					esd->decoderConfig->avgBitrate = 0;
					esd->decoderConfig->bufferSizeDB = samp->dataLength;
					esd->decoderConfig->maxBitrate = 0;
					size64 = strlen(sdpLine)+1;
					esd->URLString = (char*)gf_malloc(sizeof(char) * size64);
					strcpy(esd->URLString, sdpLine);
				} else {
					GF_LOG(GF_LOG_WARNING, GF_LOG_RTP, ("[rtp hinter] OD sample too large to be embedded in IOD - ISMA disabled\n"));
					is_ok = 0;
				}
				gf_isom_sample_del(&samp);
			}
			if (remove_ocr) esd->OCRESID = 0;
			else if (esd->OCRESID == esd->ESID) esd->OCRESID = 0;
			
			//OK, add this to our IOD
			gf_list_add(iod->ESDescriptors, esd);
		}

		esd = gf_isom_get_esd(file, sceneT, 1);
		if (gf_isom_get_sample_count(file, sceneT)==1) {
			samp = gf_isom_get_sample(file, sceneT, 1, &descIndex);
			if (gf_hinter_can_embbed_data(samp->data, samp->dataLength, GF_STREAM_SCENE)) {

				slc.timeScale = slc.timestampResolution = gf_isom_get_media_timescale(file, sceneT);	
				slc.OCRResolution = 1000;
				slc.startCTS = samp->DTS+samp->CTS_Offset;
				slc.startDTS = samp->DTS;
				//set the SL for future extraction
				gf_isom_set_extraction_slc(file, sceneT, 1, &slc);
				//encode in Base64 the sample
				size64 = gf_base64_encode(samp->data, samp->dataLength, buf64, 2000);
				buf64[size64] = 0;
				sprintf(sdpLine, "data:application/mpeg4-bifs-au;base64,%s", buf64);

				esd->decoderConfig->avgBitrate = 0;
				esd->decoderConfig->bufferSizeDB = samp->dataLength;
				esd->decoderConfig->maxBitrate = 0;
				esd->URLString = (char*)gf_malloc(sizeof(char) * (strlen(sdpLine)+1));
				strcpy(esd->URLString, sdpLine);
			} else {
				GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("[rtp hinter] Scene description sample too large to be embedded in IOD - ISMA disabled\n"));
				is_ok = 0;
			}
			gf_isom_sample_del(&samp);
		}
		if (remove_ocr) esd->OCRESID = 0;
		else if (esd->OCRESID == esd->ESID) esd->OCRESID = 0;

		gf_list_add(iod->ESDescriptors, esd);

		if (is_ok) {
			u32 has_a, has_v, has_i_a, has_i_v;
			has_a = has_v = has_i_a = has_i_v = 0;
			for (i=0; i<gf_isom_get_track_count(file); i++) {
				esd = gf_isom_get_esd(file, i+1, 1);
				if (!esd) continue;
				if (esd->decoderConfig->streamType==GF_STREAM_VISUAL) {
					if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_VIDEO_MPEG4_PART2) has_i_v ++;
					else has_v++;
				} else if (esd->decoderConfig->streamType==GF_STREAM_AUDIO) {
					if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_AUDIO_AAC_MPEG4) has_i_a ++;
					else has_a++;
				}
				gf_odf_desc_del((GF_Descriptor *)esd);
			}
			/*only 1 MPEG-4 visual max and 1 MPEG-4 audio max for ISMA compliancy*/
			if (!has_v && !has_a && (has_i_v<=1) && (has_i_a<=1)) {
				sprintf(sdpLine, "a=isma-compliance:1,1.0,1");
				gf_isom_sdp_add_line(file, sdpLine);
			}
		}
	}

	//encode the IOD
	buffer = NULL;
	size = 0;
	gf_odf_desc_write((GF_Descriptor *) iod, &buffer, &size);
	gf_odf_desc_del((GF_Descriptor *)iod);

	//encode in Base64 the iod
	size64 = gf_base64_encode(buffer, size, buf64, 2000);
	buf64[size64] = 0;
	gf_free(buffer);

	sprintf(sdpLine, "a=mpeg4-iod:\"data:application/mpeg4-iod;base64,%s\"", buf64);
	gf_isom_sdp_add_line(file, sdpLine);

	return GF_OK;
}
Esempio n. 24
0
GF_EXPORT
GF_Err gf_hinter_track_finalize(GF_RTPHinter *tkHint, Bool AddSystemInfo)
{
	u32 Width, Height;
	GF_ESD *esd;
	char sdpLine[20000];
	char mediaName[30], payloadName[30];

	Width = Height = 0;
	gf_isom_sdp_clean_track(tkHint->file, tkHint->TrackNum);
	if (gf_isom_get_media_type(tkHint->file, tkHint->TrackNum) == GF_ISOM_MEDIA_VISUAL)
		gf_isom_get_visual_info(tkHint->file, tkHint->TrackNum, 1, &Width, &Height);

	gf_rtp_builder_get_payload_name(tkHint->rtp_p, payloadName, mediaName);

	/*TODO- extract out of rtp_p for future live tools*/
	sprintf(sdpLine, "m=%s 0 RTP/%s %d", mediaName, tkHint->rtp_p->slMap.IV_length ? "SAVP" : "AVP", tkHint->rtp_p->PayloadType);
	gf_isom_sdp_add_track_line(tkHint->file, tkHint->HintTrack, sdpLine);
	if (tkHint->bandwidth) {
		sprintf(sdpLine, "b=AS:%d", tkHint->bandwidth);
		gf_isom_sdp_add_track_line(tkHint->file, tkHint->HintTrack, sdpLine);
	}
	if (tkHint->nb_chan) {
		sprintf(sdpLine, "a=rtpmap:%d %s/%d/%d", tkHint->rtp_p->PayloadType, payloadName, tkHint->rtp_p->sl_config.timestampResolution, tkHint->nb_chan);
	} else {
		sprintf(sdpLine, "a=rtpmap:%d %s/%d", tkHint->rtp_p->PayloadType, payloadName, tkHint->rtp_p->sl_config.timestampResolution);
	}
	gf_isom_sdp_add_track_line(tkHint->file, tkHint->HintTrack, sdpLine);
	/*control for MPEG-4*/
	if (AddSystemInfo) {
		sprintf(sdpLine, "a=mpeg4-esid:%d", gf_isom_get_track_id(tkHint->file, tkHint->TrackNum));
		gf_isom_sdp_add_track_line(tkHint->file, tkHint->HintTrack, sdpLine);
	}
	/*control for QTSS/DSS*/
	sprintf(sdpLine, "a=control:trackID=%d", gf_isom_get_track_id(tkHint->file, tkHint->HintTrack));
	gf_isom_sdp_add_track_line(tkHint->file, tkHint->HintTrack, sdpLine);

	/*H263 extensions*/
	if (tkHint->rtp_p->rtp_payt == GF_RTP_PAYT_H263) {
		sprintf(sdpLine, "a=cliprect:0,0,%d,%d", Height, Width);
		gf_isom_sdp_add_track_line(tkHint->file, tkHint->HintTrack, sdpLine);
	}
	/*AMR*/
	else if ((tkHint->rtp_p->rtp_payt == GF_RTP_PAYT_AMR) || (tkHint->rtp_p->rtp_payt == GF_RTP_PAYT_AMR_WB)) {
		sprintf(sdpLine, "a=fmtp:%d octet-align=1", tkHint->rtp_p->PayloadType);
		gf_isom_sdp_add_track_line(tkHint->file, tkHint->HintTrack, sdpLine);
	}
	/*Text*/
	else if (tkHint->rtp_p->rtp_payt == GF_RTP_PAYT_3GPP_TEXT) {
		gf_media_format_ttxt_sdp(tkHint->rtp_p, payloadName, sdpLine, tkHint->file, tkHint->TrackNum);
		gf_isom_sdp_add_track_line(tkHint->file, tkHint->HintTrack, sdpLine);
	}
	/*EVRC/SMV in non header-free mode*/
	else if ((tkHint->rtp_p->rtp_payt == GF_RTP_PAYT_EVRC_SMV) && (tkHint->rtp_p->auh_size>1)) {
		sprintf(sdpLine, "a=fmtp:%d maxptime=%d", tkHint->rtp_p->PayloadType, tkHint->rtp_p->auh_size*20);
		gf_isom_sdp_add_track_line(tkHint->file, tkHint->HintTrack, sdpLine);
	}
	/*H264/AVC*/
	else if (tkHint->rtp_p->rtp_payt == GF_RTP_PAYT_H264_AVC) {
		GF_AVCConfig *avcc = gf_isom_avc_config_get(tkHint->file, tkHint->TrackNum, 1);
		sprintf(sdpLine, "a=fmtp:%d profile-level-id=%02X%02X%02X; packetization-mode=1", tkHint->rtp_p->PayloadType, avcc->AVCProfileIndication, avcc->profile_compatibility, avcc->AVCLevelIndication);
		if (gf_list_count(avcc->pictureParameterSets) || gf_list_count(avcc->sequenceParameterSets)) {
			u32 i, count, b64s;
			char b64[200];
			strcat(sdpLine, "; sprop-parameter-sets=");
			count = gf_list_count(avcc->sequenceParameterSets);
			for (i=0; i<count; i++) {
				GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(avcc->sequenceParameterSets, i);
				b64s = gf_base64_encode(sl->data, sl->size, b64, 200);
				b64[b64s]=0;
				strcat(sdpLine, b64);
				if (i+1<count) strcat(sdpLine, ",");
			}
			if (i) strcat(sdpLine, ",");
			count = gf_list_count(avcc->pictureParameterSets);
			for (i=0; i<count; i++) {
				GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(avcc->pictureParameterSets, i);
				b64s = gf_base64_encode(sl->data, sl->size, b64, 200);
				b64[b64s]=0;
				strcat(sdpLine, b64);
				if (i+1<count) strcat(sdpLine, ",");
			}
		}
		gf_isom_sdp_add_track_line(tkHint->file, tkHint->HintTrack, sdpLine);
		gf_odf_avc_cfg_del(avcc);
	}
	/*MPEG-4 decoder config*/
	else if (tkHint->rtp_p->rtp_payt==GF_RTP_PAYT_MPEG4) {
		esd = gf_isom_get_esd(tkHint->file, tkHint->TrackNum, 1);

		if (esd && esd->decoderConfig && esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) {
			gf_rtp_builder_format_sdp(tkHint->rtp_p, payloadName, sdpLine, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength);
		} else {
			gf_rtp_builder_format_sdp(tkHint->rtp_p, payloadName, sdpLine, NULL, 0);
		}
		if (esd) gf_odf_desc_del((GF_Descriptor *)esd);

		if (tkHint->rtp_p->slMap.IV_length) {
			const char *kms;
			gf_isom_get_ismacryp_info(tkHint->file, tkHint->TrackNum, 1, NULL, NULL, NULL, NULL, &kms, NULL, NULL, NULL);
			if (!strnicmp(kms, "(key)", 5) || !strnicmp(kms, "(ipmp)", 6) || !strnicmp(kms, "(uri)", 5)) {
				strcat(sdpLine, "; ISMACrypKey=");
			} else {
				strcat(sdpLine, "; ISMACrypKey=(uri)");
			}
			strcat(sdpLine, kms);
		}

		gf_isom_sdp_add_track_line(tkHint->file, tkHint->HintTrack, sdpLine);
	}
	/*MPEG-4 Audio LATM*/
	else if (tkHint->rtp_p->rtp_payt==GF_RTP_PAYT_LATM) { 
		GF_BitStream *bs; 
		char *config_bytes; 
		u32 config_size; 
 
		/* form config string */ 
		bs = gf_bs_new(NULL, 32, GF_BITSTREAM_WRITE); 
		gf_bs_write_int(bs, 0, 1); /* AudioMuxVersion */ 
		gf_bs_write_int(bs, 1, 1); /* all streams same time */ 
		gf_bs_write_int(bs, 0, 6); /* numSubFrames */ 
		gf_bs_write_int(bs, 0, 4); /* numPrograms */ 
		gf_bs_write_int(bs, 0, 3); /* numLayer */ 
 
		/* audio-specific config */ 
		esd = gf_isom_get_esd(tkHint->file, tkHint->TrackNum, 1); 
		if (esd && esd->decoderConfig && esd->decoderConfig->decoderSpecificInfo) { 
			/*PacketVideo patch: don't signal SBR and PS stuff, not allowed in LATM with audioMuxVersion=0*/
			gf_bs_write_data(bs, esd->decoderConfig->decoderSpecificInfo->data, MIN(esd->decoderConfig->decoderSpecificInfo->dataLength, 2) ); 
		} 
		if (esd) gf_odf_desc_del((GF_Descriptor *)esd); 
 
		/* other data */ 
		gf_bs_write_int(bs, 0, 3); /* frameLengthType */ 
		gf_bs_write_int(bs, 0xff, 8); /* latmBufferFullness */ 
		gf_bs_write_int(bs, 0, 1); /* otherDataPresent */ 
		gf_bs_write_int(bs, 0, 1); /* crcCheckPresent */ 
		gf_bs_get_content(bs, &config_bytes, &config_size); 
		gf_bs_del(bs); 
 
		gf_rtp_builder_format_sdp(tkHint->rtp_p, payloadName, sdpLine, config_bytes, config_size); 
		gf_isom_sdp_add_track_line(tkHint->file, tkHint->HintTrack, sdpLine); 
		gf_free(config_bytes); 
	}
	/*3GPP DIMS*/
	else if (tkHint->rtp_p->rtp_payt==GF_RTP_PAYT_3GPP_DIMS) { 
		GF_DIMSDescription dims;
		char fmt[200];
		gf_isom_get_visual_info(tkHint->file, tkHint->TrackNum, 1, &Width, &Height);

		gf_isom_get_dims_description(tkHint->file, tkHint->TrackNum, 1, &dims);
		sprintf(sdpLine, "a=fmtp:%d Version-profile=%d", tkHint->rtp_p->PayloadType, dims.profile);
		if (! dims.fullRequestHost) {
			strcat(sdpLine, ";useFullRequestHost=0");
			sprintf(fmt, ";pathComponents=%d", dims.pathComponents);
			strcat(sdpLine, fmt);
		}
		if (!dims.streamType) strcat(sdpLine, ";stream-type=secondary");
		if (dims.containsRedundant == 1) strcat(sdpLine, ";contains-redundant=main");
		else if (dims.containsRedundant == 2) strcat(sdpLine, ";contains-redundant=redundant");

		if (dims.textEncoding && strlen(dims.textEncoding)) {
			strcat(sdpLine, ";text-encoding=");
			strcat(sdpLine, dims.textEncoding);
		}
		if (dims.contentEncoding && strlen(dims.contentEncoding)) {
			strcat(sdpLine, ";content-coding=");
			strcat(sdpLine, dims.contentEncoding);
		}
		if (dims.content_script_types && strlen(dims.content_script_types) ) {
			strcat(sdpLine, ";content-script-types=");
			strcat(sdpLine, dims.contentEncoding);
		}
		gf_isom_sdp_add_track_line(tkHint->file, tkHint->HintTrack, sdpLine);
	}
	/*extensions for some mobile phones*/
	if (Width && Height) {
		sprintf(sdpLine, "a=framesize:%d %d-%d", tkHint->rtp_p->PayloadType, Width, Height);
		gf_isom_sdp_add_track_line(tkHint->file, tkHint->HintTrack, sdpLine);
	}

	esd = gf_isom_get_esd(tkHint->file, tkHint->TrackNum, 1);
	if (esd && esd->decoderConfig && (esd->decoderConfig->rvc_config || esd->decoderConfig->predefined_rvc_config)) {
		if (esd->decoderConfig->predefined_rvc_config) {
			sprintf(sdpLine, "a=rvc-config-predef:%d", esd->decoderConfig->predefined_rvc_config);
		} else {
			/*temporary ...*/
			if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_VIDEO_AVC) {
				sprintf(sdpLine, "a=rvc-config:%s", "http://download.tsi.telecom-paristech.fr/gpac/RVC/rvc_config_avc.xml");
			} else {
				sprintf(sdpLine, "a=rvc-config:%s", "http://download.tsi.telecom-paristech.fr/gpac/RVC/rvc_config_sp.xml");
			}
		}
		gf_isom_sdp_add_track_line(tkHint->file, tkHint->HintTrack, sdpLine);
	}
	if (esd) gf_odf_desc_del((GF_Descriptor *)esd);

	gf_isom_set_track_enabled(tkHint->file, tkHint->HintTrack, 1);
	return GF_OK;
}
Esempio n. 25
0
GF_EXPORT
GF_RTPHinter *gf_hinter_track_new(GF_ISOFile *file, u32 TrackNum, 
							u32 Path_MTU, u32 max_ptime, u32 default_rtp_rate, u32 flags, u8 PayloadID, 
							Bool copy_media, u32 InterleaveGroupID, u8 InterleaveGroupPriority, GF_Err *e)
{

	GF_SLConfig my_sl;
	u32 descIndex, MinSize, MaxSize, avgTS, streamType, oti, const_dur, nb_ch, maxDTSDelta;
	u8 OfficialPayloadID;
	u32 TrackMediaSubType, TrackMediaType, hintType, nbEdts, required_rate, force_dts_delta, avc_nalu_size, PL_ID, bandwidth, IV_length, KI_length;
	const char *url, *urn;
	char *mpeg4mode;
	Bool is_crypted, has_mpeg4_mapping;
	GF_RTPHinter *tmp;
	GF_ESD *esd;

	*e = GF_BAD_PARAM;
	if (!file || !TrackNum || !gf_isom_get_track_id(file, TrackNum)) return NULL;

	if (!gf_isom_get_sample_count(file, TrackNum)) {
		*e = GF_OK;
		return NULL;
	}
	*e = GF_NOT_SUPPORTED;
	nbEdts = gf_isom_get_edit_segment_count(file, TrackNum);
	if (nbEdts>1) {
		u64 et, sd, mt;
		u8 em;
		gf_isom_get_edit_segment(file, TrackNum, 1, &et, &sd, &mt, &em);
		if ((nbEdts>2) || (em!=GF_ISOM_EDIT_EMPTY)) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("[rtp hinter] Cannot hint track whith EditList\n"));
			return NULL;
		}
	}
	if (nbEdts) gf_isom_remove_edit_segments(file, TrackNum);

	if (!gf_isom_is_track_enabled(file, TrackNum)) return NULL;

	/*by default NO PL signaled*/
	PL_ID = 0;
	OfficialPayloadID = 0;
	force_dts_delta = 0;
	streamType = oti = 0;
	mpeg4mode = NULL;
	required_rate = 0;
	is_crypted = 0;
	IV_length = KI_length = 0;
	oti = 0;
	nb_ch = 0;
	avc_nalu_size = 0;
	has_mpeg4_mapping = 1;
	TrackMediaType = gf_isom_get_media_type(file, TrackNum);
	TrackMediaSubType = gf_isom_get_media_subtype(file, TrackNum, 1);
	
	/*for max compatibility with QT*/
	if (!default_rtp_rate) default_rtp_rate = 90000;

	/*timed-text is a bit special, we support multiple stream descriptions & co*/
	if ( (TrackMediaType==GF_ISOM_MEDIA_TEXT) || (TrackMediaType==GF_ISOM_MEDIA_SUBT)) {
		hintType = GF_RTP_PAYT_3GPP_TEXT;
		oti = GPAC_OTI_TEXT_MPEG4;
		streamType = GF_STREAM_TEXT;
		/*fixme - this works cos there's only one PL for text in mpeg4 at the current time*/
		PL_ID = 0x10;
	} else {
		if (gf_isom_get_sample_description_count(file, TrackNum) > 1) return NULL;

		TrackMediaSubType = gf_isom_get_media_subtype(file, TrackNum, 1);
		switch (TrackMediaSubType) {
		case GF_ISOM_SUBTYPE_MPEG4_CRYP: 
			is_crypted = 1;
		case GF_ISOM_SUBTYPE_MPEG4:
			esd = gf_isom_get_esd(file, TrackNum, 1);
			hintType = GF_RTP_PAYT_MPEG4;
			if (esd) {
				streamType = esd->decoderConfig->streamType;
				oti = esd->decoderConfig->objectTypeIndication;
				if (esd->URLString) hintType = 0;
				/*AAC*/
				if ((streamType==GF_STREAM_AUDIO) && esd->decoderConfig->decoderSpecificInfo
				/*(nb: we use mpeg4 for MPEG-2 AAC)*/
				&& ((oti==GPAC_OTI_AUDIO_AAC_MPEG4) || (oti==GPAC_OTI_AUDIO_AAC_MPEG4) || (oti==GPAC_OTI_AUDIO_AAC_MPEG2_MP) || (oti==GPAC_OTI_AUDIO_AAC_MPEG2_LCP) || (oti==GPAC_OTI_AUDIO_AAC_MPEG2_SSRP)) ) {

					u32 sample_rate;
					GF_M4ADecSpecInfo a_cfg;
					gf_m4a_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &a_cfg);
					nb_ch = a_cfg.nb_chan;
					sample_rate = a_cfg.base_sr;
					PL_ID = a_cfg.audioPL;
					switch (a_cfg.base_object_type) {
					case GF_M4A_AAC_MAIN:
					case GF_M4A_AAC_LC:
						if (flags & GP_RTP_PCK_USE_LATM_AAC) {
							hintType = GF_RTP_PAYT_LATM;
							break;
						}
					case GF_M4A_AAC_SBR:
					case GF_M4A_AAC_PS:
					case GF_M4A_AAC_LTP:
					case GF_M4A_AAC_SCALABLE:
					case GF_M4A_ER_AAC_LC:
					case GF_M4A_ER_AAC_LTP:
					case GF_M4A_ER_AAC_SCALABLE:
						mpeg4mode = "AAC";
						break;
					case GF_M4A_CELP:
					case GF_M4A_ER_CELP:
						mpeg4mode = "CELP";
						break;
					}
					required_rate = sample_rate;
				}
				/*MPEG1/2 audio*/
				else if ((streamType==GF_STREAM_AUDIO) && ((oti==GPAC_OTI_AUDIO_MPEG2_PART3) || (oti==GPAC_OTI_AUDIO_MPEG1))) {
					u32 sample_rate;
					if (!is_crypted) {
						GF_ISOSample *samp = gf_isom_get_sample(file, TrackNum, 1, NULL);
						u32 hdr = GF_4CC((u8)samp->data[0], (u8)samp->data[1], (u8)samp->data[2], (u8)samp->data[3]);
						nb_ch = gf_mp3_num_channels(hdr);
						sample_rate = gf_mp3_sampling_rate(hdr);
						gf_isom_sample_del(&samp);
						hintType = GF_RTP_PAYT_MPEG12_AUDIO;
						/*use official RTP/AVP payload type*/
						OfficialPayloadID = 14;
						required_rate = 90000;
					}
					/*encrypted MP3 must be sent through MPEG-4 generic to signal all ISMACryp stuff*/
					else {
						u8 bps;
						gf_isom_get_audio_info(file, TrackNum, 1, &sample_rate, &nb_ch, &bps);
						required_rate = sample_rate;
					}
				}
				/*QCELP audio*/
				else if ((streamType==GF_STREAM_AUDIO) && (oti==GPAC_OTI_AUDIO_13K_VOICE)) {
					hintType = GF_RTP_PAYT_QCELP;
					OfficialPayloadID = 12;
					required_rate = 8000;
					streamType = GF_STREAM_AUDIO;
					nb_ch = 1;
				}
				/*EVRC/SVM audio*/
				else if ((streamType==GF_STREAM_AUDIO) && ((oti==GPAC_OTI_AUDIO_EVRC_VOICE) || (oti==GPAC_OTI_AUDIO_SMV_VOICE)) ) {
					hintType = GF_RTP_PAYT_EVRC_SMV;
					required_rate = 8000;
					streamType = GF_STREAM_AUDIO;
					nb_ch = 1;
				}
				/*visual streams*/
				else if (streamType==GF_STREAM_VISUAL) {
					if (oti==GPAC_OTI_VIDEO_MPEG4_PART2) {
						GF_M4VDecSpecInfo dsi;
						gf_m4v_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi);
						PL_ID = dsi.VideoPL;
					}
					/*MPEG1/2 video*/
					if ( ((oti>=GPAC_OTI_VIDEO_MPEG2_SIMPLE) && (oti<=GPAC_OTI_VIDEO_MPEG2_422)) || (oti==GPAC_OTI_VIDEO_MPEG1)) {
						if (!is_crypted) {
							hintType = GF_RTP_PAYT_MPEG12_VIDEO;
							OfficialPayloadID = 32;
						}
					}
					/*for ISMA*/
					if (is_crypted) {
						/*that's another pain with ISMACryp, even if no B-frames the DTS is signaled...*/
						if (oti==GPAC_OTI_VIDEO_MPEG4_PART2) force_dts_delta = 22;
						else if (oti==GPAC_OTI_VIDEO_AVC) {
							flags &= ~GP_RTP_PCK_USE_MULTI;
							force_dts_delta = 22;
						}
						flags |= GP_RTP_PCK_SIGNAL_RAP | GP_RTP_PCK_SIGNAL_TS;
					}

					required_rate = default_rtp_rate;
				}
				/*systems streams*/
				else if (gf_isom_has_sync_shadows(file, TrackNum) || gf_isom_has_sample_dependency(file, TrackNum)) {
					flags |= GP_RTP_PCK_SYSTEMS_CAROUSEL;
				}
				gf_odf_desc_del((GF_Descriptor*)esd);
			}
			break;
		case GF_ISOM_SUBTYPE_3GP_H263:
			hintType = GF_RTP_PAYT_H263;
			required_rate = 90000;
			streamType = GF_STREAM_VISUAL;
			OfficialPayloadID = 34;
			/*not 100% compliant (short header is missing) but should still work*/
			oti = GPAC_OTI_VIDEO_MPEG4_PART2;
			PL_ID = 0x01;
			break;
		case GF_ISOM_SUBTYPE_3GP_AMR:
			required_rate = 8000;
			hintType = GF_RTP_PAYT_AMR;
			streamType = GF_STREAM_AUDIO;
			has_mpeg4_mapping = 0;
			nb_ch = 1;
			break;
		case GF_ISOM_SUBTYPE_3GP_AMR_WB:
			required_rate = 16000;
			hintType = GF_RTP_PAYT_AMR_WB;
			streamType = GF_STREAM_AUDIO;
			has_mpeg4_mapping = 0;
			nb_ch = 1;
			break;
		case GF_ISOM_SUBTYPE_AVC_H264:
		case GF_ISOM_SUBTYPE_AVC2_H264:
		case GF_ISOM_SUBTYPE_SVC_H264:
		{
			GF_AVCConfig *avcc = gf_isom_avc_config_get(file, TrackNum, 1);
			required_rate = 90000;	/* "90 kHz clock rate MUST be used"*/
			hintType = GF_RTP_PAYT_H264_AVC;
			streamType = GF_STREAM_VISUAL;
			avc_nalu_size = avcc->nal_unit_size;
			oti = GPAC_OTI_VIDEO_AVC;
			PL_ID = 0x0F;
			gf_odf_avc_cfg_del(avcc);
		}
			break;
		case GF_ISOM_SUBTYPE_3GP_QCELP:
			required_rate = 8000;
			hintType = GF_RTP_PAYT_QCELP;
			streamType = GF_STREAM_AUDIO;
			oti = GPAC_OTI_AUDIO_13K_VOICE;
			OfficialPayloadID = 12;
			nb_ch = 1;
			break;
		case GF_ISOM_SUBTYPE_3GP_EVRC:
		case GF_ISOM_SUBTYPE_3GP_SMV:
			required_rate = 8000;
			hintType = GF_RTP_PAYT_EVRC_SMV;
			streamType = GF_STREAM_AUDIO;
			oti = (TrackMediaSubType==GF_ISOM_SUBTYPE_3GP_EVRC) ? GPAC_OTI_AUDIO_EVRC_VOICE : GPAC_OTI_AUDIO_SMV_VOICE;
			nb_ch = 1;
			break;
		case GF_ISOM_SUBTYPE_3GP_DIMS:
			hintType = GF_RTP_PAYT_3GPP_DIMS;
			streamType = GF_STREAM_SCENE;
			break;
		case GF_ISOM_SUBTYPE_AC3:
			hintType = GF_RTP_PAYT_AC3;
			streamType = GF_STREAM_AUDIO;
			gf_isom_get_audio_info(file, TrackNum, 1, NULL, &nb_ch, NULL);
			break;
		default:
			/*ERROR*/
			hintType = 0;
			break;
		}
	}

	/*not hintable*/
	if (!hintType) return NULL;
	/*we only support self-contained files for hinting*/
	gf_isom_get_data_reference(file, TrackNum, 1, &url, &urn);
	if (url || urn) return NULL;
	
	*e = GF_OUT_OF_MEM;
	GF_SAFEALLOC(tmp, GF_RTPHinter);
	if (!tmp) return NULL;

	/*override hinter type if requested and possible*/
	if (has_mpeg4_mapping && (flags & GP_RTP_PCK_FORCE_MPEG4)) {
		hintType = GF_RTP_PAYT_MPEG4;
		avc_nalu_size = 0;
	}
	/*use static payload ID if enabled*/
	else if (OfficialPayloadID && (flags & GP_RTP_PCK_USE_STATIC_ID) ) {
		PayloadID = OfficialPayloadID;
	}

	tmp->file = file;
	tmp->TrackNum = TrackNum;
	tmp->avc_nalu_size = avc_nalu_size;
	tmp->nb_chan = nb_ch;

	/*spatial scalability check*/
	tmp->has_ctts = gf_isom_has_time_offset(file, TrackNum);

	/*get sample info*/
	gf_media_get_sample_average_infos(file, TrackNum, &MinSize, &MaxSize, &avgTS, &maxDTSDelta, &const_dur, &bandwidth);

	/*systems carousel: we need at least IDX and RAP signaling*/
	if (flags & GP_RTP_PCK_SYSTEMS_CAROUSEL) {
		flags |= GP_RTP_PCK_SIGNAL_RAP;
	}

	/*update flags in MultiSL*/
	if (flags & GP_RTP_PCK_USE_MULTI) {
		if (MinSize != MaxSize) flags |= GP_RTP_PCK_SIGNAL_SIZE;
		if (!const_dur) flags |= GP_RTP_PCK_SIGNAL_TS;
	}
	if (tmp->has_ctts) flags |= GP_RTP_PCK_SIGNAL_TS;

	/*default SL for RTP */
	InitSL_RTP(&my_sl);

	my_sl.timestampResolution = gf_isom_get_media_timescale(file, TrackNum);
	/*override clockrate if set*/
	if (required_rate) {
		Double sc = required_rate;
		sc /= my_sl.timestampResolution;
		maxDTSDelta = (u32) (maxDTSDelta*sc);
		my_sl.timestampResolution = required_rate;
	}
	/*switch to RTP TS*/
	max_ptime = (u32) (max_ptime * my_sl.timestampResolution / 1000);

	my_sl.AUSeqNumLength = gf_get_bit_size(gf_isom_get_sample_count(file, TrackNum));
	my_sl.CUDuration = const_dur;

	if (gf_isom_has_sync_points(file, TrackNum)) {
		my_sl.useRandomAccessPointFlag = 1;
	} else {
		my_sl.useRandomAccessPointFlag = 0;
		my_sl.hasRandomAccessUnitsOnlyFlag = 1;
	}

	if (is_crypted) {
		Bool use_sel_enc;
		gf_isom_get_ismacryp_info(file, TrackNum, 1, NULL, NULL, NULL, NULL, NULL, &use_sel_enc, &IV_length, &KI_length);
		if (use_sel_enc) flags |= GP_RTP_PCK_SELECTIVE_ENCRYPTION;
	}

	// in case a different timescale was provided
	tmp->OrigTimeScale = gf_isom_get_media_timescale(file, TrackNum);
	tmp->rtp_p = gf_rtp_builder_new(hintType, &my_sl, flags, tmp, 
								MP4T_OnNewPacket, MP4T_OnPacketDone, 
								/*if copy, no data ref*/
								copy_media ? NULL : MP4T_OnDataRef, 
								MP4T_OnData);

	//init the builder
	gf_rtp_builder_init(tmp->rtp_p, PayloadID, Path_MTU, max_ptime,
					   streamType, oti, PL_ID, MinSize, MaxSize, avgTS, maxDTSDelta, IV_length, KI_length, mpeg4mode);

	/*ISMA compliance is a pain...*/
	if (force_dts_delta) tmp->rtp_p->slMap.DTSDeltaLength = force_dts_delta;


	/*		Hint Track Setup	*/
	tmp->TrackID = gf_isom_get_track_id(file, TrackNum);
	tmp->HintID = tmp->TrackID + 65535;
	while (gf_isom_get_track_by_id(file, tmp->HintID)) tmp->HintID++;

	tmp->HintTrack = gf_isom_new_track(file, tmp->HintID, GF_ISOM_MEDIA_HINT, my_sl.timestampResolution);
	gf_isom_setup_hint_track(file, tmp->HintTrack, GF_ISOM_HINT_RTP);
	/*create a hint description*/
	gf_isom_new_hint_description(file, tmp->HintTrack, -1, -1, 0, &descIndex);
	gf_isom_rtp_set_timescale(file, tmp->HintTrack, descIndex, my_sl.timestampResolution);

	if (hintType==GF_RTP_PAYT_MPEG4) {
		tmp->rtp_p->slMap.ObjectTypeIndication = oti;
		/*set this SL for extraction.*/
		gf_isom_set_extraction_slc(file, TrackNum, 1, &my_sl);
	}
	tmp->bandwidth = bandwidth;

	/*set interleaving*/
	gf_isom_set_track_group(file, TrackNum, InterleaveGroupID);
	if (!copy_media) {
		/*if we don't copy data set hint track and media track in the same group*/
		gf_isom_set_track_group(file, tmp->HintTrack, InterleaveGroupID);
	} else {
		gf_isom_set_track_group(file, tmp->HintTrack, InterleaveGroupID + OFFSET_HINT_GROUP_ID);
	}
	/*use user-secified priority*/
	InterleaveGroupPriority*=2;
	gf_isom_set_track_priority_in_group(file, TrackNum, InterleaveGroupPriority+1);
	gf_isom_set_track_priority_in_group(file, tmp->HintTrack, InterleaveGroupPriority);

#if 0
	/*QT FF: not setting these flags = server uses a random offset*/
	gf_isom_rtp_set_time_offset(file, tmp->HintTrack, 1, 0);
	/*we don't use seq offset for maintainance pruposes*/
	gf_isom_rtp_set_time_sequence_offset(file, tmp->HintTrack, 1, 0);
#endif
	*e = GF_OK;
	return tmp;
}
Esempio n. 26
0
static GF_Err gf_isom_streamer_setup_sdp(GF_ISOMRTPStreamer *streamer, char*sdpfilename, char **out_sdp_buffer) 
{	
	GF_RTPTrack *track;
	FILE *sdp_out;
	char filename[GF_MAX_PATH];
	char sdpLine[20000];

	strcpy(filename, sdpfilename ? sdpfilename : "videosession.sdp");
	sdp_out = gf_f64_open(filename, "wt");
	if (!sdp_out) return GF_IO_ERR;

	if (!out_sdp_buffer) {
		sprintf(sdpLine, "v=0");
		fprintf(sdp_out, "%s\n", sdpLine);
		sprintf(sdpLine, "o=MP4Streamer 3357474383 1148485440000 IN IP%d %s", gf_net_is_ipv6(streamer->dest_ip) ? 6 : 4, streamer->dest_ip);
		fprintf(sdp_out, "%s\n", sdpLine);
		sprintf(sdpLine, "s=livesession");
		fprintf(sdp_out, "%s\n", sdpLine);
		sprintf(sdpLine, "i=This is an MP4 time-sliced Streaming demo");
		fprintf(sdp_out, "%s\n", sdpLine);
		sprintf(sdpLine, "u=http://gpac.sourceforge.net");
		fprintf(sdp_out, "%s\n", sdpLine);
		sprintf(sdpLine, "e=admin@");
		fprintf(sdp_out, "%s\n", sdpLine);
		sprintf(sdpLine, "c=IN IP%d %s", gf_net_is_ipv6(streamer->dest_ip) ? 6 : 4, streamer->dest_ip);
		fprintf(sdp_out, "%s\n", sdpLine);
		sprintf(sdpLine, "t=0 0");
		fprintf(sdp_out, "%s\n", sdpLine);
		sprintf(sdpLine, "a=x-copyright: Streamed with GPAC (C)2000-200X - http://gpac.sourceforge.net\n");
		fprintf(sdp_out, "%s\n", sdpLine);
	}

	track = streamer->stream;
	while (track) {
		char *sdp_media=NULL;
		const char *KMS = NULL;
		char *dsi = NULL;
		u32 w, h;
		u32 dsi_len = 0;
		GF_DecoderConfig *dcd = gf_isom_get_decoder_config(streamer->isom, track->track_num, 1);

		if (dcd && dcd->decoderSpecificInfo) {
			dsi = dcd->decoderSpecificInfo->data;
			dsi_len = dcd->decoderSpecificInfo->dataLength;
		}
		w = h = 0;
		if (gf_isom_get_media_type(streamer->isom, track->track_num) == GF_ISOM_MEDIA_VISUAL) {
			gf_isom_get_visual_info(streamer->isom, track->track_num, 1, &w, &h);
		}

		gf_isom_get_ismacryp_info(streamer->isom, track->track_num, 1, NULL, NULL, NULL, NULL, &KMS, NULL, NULL, NULL);

	        /*TODO retrieve DIMS content encoding from track to set the flags */
		gf_rtp_streamer_append_sdp_extended(track->rtp, gf_isom_get_track_id(streamer->isom, track->track_num), dsi, dsi_len, streamer->isom, track->track_num, (char *)KMS, w, h, &sdp_media);
		if (sdp_media) {
			fprintf(sdp_out, "%s", sdp_media);
			gf_free(sdp_media);
		}

		if (dcd) gf_odf_desc_del((GF_Descriptor *)dcd);
		
		track = track->next;
	}
	fprintf(sdp_out, "\n");

	fclose(sdp_out);
	if (out_sdp_buffer) {
		u64 size;
		sdp_out = gf_f64_open(filename, "r");
		gf_f64_seek(sdp_out, 0, SEEK_END);
		size = gf_f64_tell(sdp_out);
		gf_f64_seek(sdp_out, 0, SEEK_SET);
		if (*out_sdp_buffer) gf_free(*out_sdp_buffer);
		*out_sdp_buffer = gf_malloc(sizeof(char)*(size_t)(size+1));
		size = fread(*out_sdp_buffer, 1, (size_t)size, sdp_out);
		fclose(sdp_out);
		(*out_sdp_buffer)[size]=0;
	}

	return GF_OK;
} 
Esempio n. 27
0
GF_EXPORT
GF_ISOMRTPStreamer *gf_isom_streamer_new(const char *file_name, const char *ip_dest, u16 port, Bool loop, Bool force_mpeg4, u32 path_mtu, u32 ttl, char *ifce_addr)
{
	GF_ISOMRTPStreamer *streamer;
	GF_Err e = GF_OK;
	const char *opt = NULL;
	/*GF_Config *configFile = NULL;	*/
	u32 i, max_ptime, au_sn_len;	
	u8 payt;			
	GF_ISOFile *file;
	GF_RTPTrack *track, *prev_track;
	u16 first_port;
	u32 nb_tracks;
	u32 sess_data_size;

	if (!ip_dest) ip_dest = "127.0.0.1";
	if (!port) port = 7000;
	if (!path_mtu) path_mtu = 1450;

	GF_SAFEALLOC(streamer, GF_ISOMRTPStreamer);
	streamer->dest_ip = gf_strdup(ip_dest);

	payt = 96;
	max_ptime = au_sn_len = 0;

	file = gf_isom_open(file_name, GF_ISOM_OPEN_READ, NULL);
	if (!file) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("Error opening file %s: %s\n", opt, gf_error_to_string(gf_isom_last_error(NULL))));
		return NULL;
	}

	streamer->isom = file;
	streamer->loop = loop;
	streamer->force_mpeg4_generic = force_mpeg4;
	first_port = port;

	sess_data_size = 0;
	prev_track = NULL;
	
	nb_tracks = gf_isom_get_track_count(streamer->isom);
	for (i=0; i<nb_tracks; i++) {
		u32 mediaSize, mediaDuration, flags, MinSize, MaxSize, avgTS, streamType, oti, const_dur, nb_ch, samplerate, maxDTSDelta, TrackMediaSubType, TrackMediaType, bandwidth, IV_length, KI_length, dsi_len;
		const char *url, *urn;
		char *dsi;
		Bool is_crypted;
		
		dsi_len = samplerate = streamType = oti = nb_ch = IV_length = KI_length = 0;
		is_crypted = 0;
		dsi = NULL;

		flags = 0;

		/*we only support self-contained files for hinting*/
		gf_isom_get_data_reference(streamer->isom, i+1, 1, &url, &urn);
		if (url || urn) continue;

		TrackMediaType = gf_isom_get_media_type(streamer->isom, i+1);
		TrackMediaSubType = gf_isom_get_media_subtype(streamer->isom, i+1, 1);

		switch (TrackMediaType) {
		case GF_ISOM_MEDIA_TEXT:
			break;
		case GF_ISOM_MEDIA_VISUAL:
		case GF_ISOM_MEDIA_AUDIO:
		case GF_ISOM_MEDIA_SUBT:
		case GF_ISOM_MEDIA_OD:
		case GF_ISOM_MEDIA_SCENE:
			if (gf_isom_get_sample_description_count(streamer->isom, i+1) > 1) continue;
			break;
		default:
			continue;
		}

		GF_SAFEALLOC(track, GF_RTPTrack);
		if (prev_track) prev_track->next = track;
		else streamer->stream = track;
		prev_track = track;

		track->track_num = i+1;

		track->nb_aus = gf_isom_get_sample_count(streamer->isom, track->track_num);
		track->timescale = gf_isom_get_media_timescale(streamer->isom, track->track_num);
		mediaDuration = (u32)(gf_isom_get_media_duration(streamer->isom, track->track_num)*1000/track->timescale); // ms
		mediaSize = (u32)gf_isom_get_media_data_size(streamer->isom, track->track_num);

		sess_data_size += mediaSize;
		if (mediaDuration > streamer->duration_ms) streamer->duration_ms = mediaDuration;

		track->port = check_next_port(streamer, first_port);
		first_port = track->port+2;

		/*init packetizer*/
		if (streamer->force_mpeg4_generic) flags = GP_RTP_PCK_SIGNAL_RAP | GP_RTP_PCK_FORCE_MPEG4;


		switch (TrackMediaSubType) {
		case GF_ISOM_SUBTYPE_MPEG4_CRYP: 
			is_crypted = 1;
		case GF_ISOM_SUBTYPE_MPEG4:
		{	
			GF_ESD *esd = gf_isom_get_esd(streamer->isom, track->track_num, 1);
			if (esd) {
				streamType = esd->decoderConfig->streamType;
				oti = esd->decoderConfig->objectTypeIndication;

				/*systems streams*/
				if (streamType==GF_STREAM_AUDIO) {
					gf_isom_get_audio_info(streamer->isom, track->track_num, 1, &samplerate, &nb_ch, NULL);
				}
				/*systems streams*/
				else if (streamType==GF_STREAM_SCENE) {
					if (gf_isom_has_sync_shadows(streamer->isom, track->track_num) || gf_isom_has_sample_dependency(streamer->isom, track->track_num))
						flags |= GP_RTP_PCK_SYSTEMS_CAROUSEL;
				}
				
				if (esd->decoderConfig->decoderSpecificInfo) {
					dsi = esd->decoderConfig->decoderSpecificInfo->data;
					dsi_len = esd->decoderConfig->decoderSpecificInfo->dataLength;
					esd->decoderConfig->decoderSpecificInfo->data = NULL;
					esd->decoderConfig->decoderSpecificInfo->dataLength = 0;
				}
				gf_odf_desc_del((GF_Descriptor*)esd);
			}
		}
			break;
		case GF_ISOM_SUBTYPE_AVC_H264:
		case GF_ISOM_SUBTYPE_AVC2_H264:
		case GF_ISOM_SUBTYPE_SVC_H264:
		{
			GF_AVCConfig *avcc = gf_isom_avc_config_get(streamer->isom, track->track_num, 1);
			track->avc_nalu_size = avcc->nal_unit_size;
			gf_odf_avc_cfg_del(avcc);
			streamType = GF_STREAM_VISUAL;
			oti = GPAC_OTI_VIDEO_AVC;
		}
			break;
		default:
			streamType = GF_STREAM_4CC;
			oti = TrackMediaSubType;
			break;
		}
		
		/*get sample info*/
		gf_media_get_sample_average_infos(streamer->isom, track->track_num, &MinSize, &MaxSize, &avgTS, &maxDTSDelta, &const_dur, &bandwidth);

		if (is_crypted) {
			Bool use_sel_enc;
			gf_isom_get_ismacryp_info(streamer->isom, track->track_num, 1, NULL, NULL, NULL, NULL, NULL, &use_sel_enc, &IV_length, &KI_length);
			if (use_sel_enc) flags |= GP_RTP_PCK_SELECTIVE_ENCRYPTION;
		}

		track->rtp = gf_rtp_streamer_new_extended(streamType, oti, track->timescale, 
									(char *) streamer->dest_ip, track->port, path_mtu, ttl, ifce_addr, 
									flags, dsi, dsi_len, 								 
									 payt, samplerate, nb_ch,
									 is_crypted, IV_length, KI_length,
									 MinSize, MaxSize, avgTS, maxDTSDelta, const_dur, bandwidth, max_ptime, au_sn_len);

		if (!track->rtp) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("Could not initialize RTP streamer: %s\n", gf_error_to_string(e)));
			goto exit;
		}		

		payt++;
		track->microsec_ts_scale = 1000000;
		track->microsec_ts_scale /= gf_isom_get_media_timescale(streamer->isom, track->track_num);
	}
	return streamer;

exit:
	gf_free(streamer);
	return NULL;
} 
Esempio n. 28
0
static GF_Err gf_sm_setup_bifsenc(GF_SceneEngine *seng, GF_StreamContext *sc, GF_ESD *esd)
{
	char *data;
	u32 data_len;
	u32	nbb;
	Bool encode_names, delete_bcfg;
	GF_BIFSConfig *bcfg;

	if (!esd->decoderConfig || (esd->decoderConfig->streamType != GF_STREAM_SCENE)) return GF_BAD_PARAM;

	if (!seng->bifsenc)
		seng->bifsenc = gf_bifs_encoder_new(seng->ctx->scene_graph);

	delete_bcfg = 0;
	/*inputctx is not properly setup, do it*/
	if (!esd->decoderConfig->decoderSpecificInfo) {
		bcfg = (GF_BIFSConfig*)gf_odf_desc_new(GF_ODF_BIFS_CFG_TAG);
		bcfg->pixelMetrics = seng->ctx->is_pixel_metrics;
		bcfg->pixelWidth = seng->ctx->scene_width;
		bcfg->pixelHeight = seng->ctx->scene_height;
		delete_bcfg = 1;
	}
	/*regular case*/
	else if (esd->decoderConfig->decoderSpecificInfo->tag == GF_ODF_BIFS_CFG_TAG) {
		bcfg = (GF_BIFSConfig *)esd->decoderConfig->decoderSpecificInfo;
	}
	/*happens when loading from MP4 in which case BIFSc is not decoded*/
	else {
		bcfg = gf_odf_get_bifs_config(esd->decoderConfig->decoderSpecificInfo, esd->decoderConfig->objectTypeIndication);
		delete_bcfg = 1;
	}

	/*NO CHANGE TO BIFSC otherwise the generated update will not match the input context
	The only case we modify the bifs config is when XXXBits is not specified*/
	nbb = gf_get_bit_size(seng->ctx->max_node_id);
	if (!bcfg->nodeIDbits) bcfg->nodeIDbits = nbb;
	else if (bcfg->nodeIDbits<nbb) {
		GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[BIFS] BIFSConfig.NodeIDBits too small (%d bits vs %d nodes)\n", bcfg->nodeIDbits, seng->ctx->max_node_id));
	}
	nbb = gf_get_bit_size(seng->ctx->max_route_id);
	if (!bcfg->routeIDbits) bcfg->routeIDbits = nbb;
	else if (bcfg->routeIDbits<nbb) {
		GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[BIFS] BIFSConfig.RouteIDBits too small (%d bits vs %d routes)\n", bcfg->routeIDbits, seng->ctx->max_route_id));
	}
	nbb = gf_get_bit_size(seng->ctx->max_proto_id);
	if (!bcfg->protoIDbits) bcfg->protoIDbits=nbb;
	else if (bcfg->protoIDbits<nbb) {
		GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[BIFS] BIFSConfig.ProtoIDBits too small (%d bits vs %d protos)\n", bcfg->protoIDbits, seng->ctx->max_proto_id));
	}

	/*this is the real pb, not stored in cfg or file level, set at EACH replaceScene*/
	encode_names = 0;

	/* The BIFS Config that is passed here should be the BIFSConfig from the IOD */
	gf_bifs_encoder_new_stream(seng->bifsenc, esd->ESID, bcfg, encode_names, 0);
	if (delete_bcfg) gf_odf_desc_del((GF_Descriptor *)bcfg);

	gf_bifs_encoder_get_config(seng->bifsenc, esd->ESID, &data, &data_len);

	if (esd->decoderConfig->decoderSpecificInfo) gf_odf_desc_del((GF_Descriptor *) esd->decoderConfig->decoderSpecificInfo);
	esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG);
	esd->decoderConfig->decoderSpecificInfo->data = data;
	esd->decoderConfig->decoderSpecificInfo->dataLength = data_len;
		
	sc->dec_cfg = gf_malloc(sizeof(char)*data_len);
	memcpy(sc->dec_cfg, data, data_len);
	sc->dec_cfg_len = data_len;

	esd->decoderConfig->objectTypeIndication = gf_bifs_encoder_get_version(seng->bifsenc, esd->ESID);		

	return GF_OK;
}
Esempio n. 29
0
GF_Err gf_odf_codec_apply_com(GF_ODCodec *codec, GF_ODCom *command)
{
	GF_ODCom *com;
	GF_ODUpdate *odU, *odU_o;
	u32 i, count;
	count = gf_list_count(codec->CommandList);

	switch (command->tag) {
	case GF_ODF_OD_REMOVE_TAG:
		for (i = 0; i<count; i++) {
			com = (GF_ODCom *)gf_list_get(codec->CommandList, i);
			/*process OD updates*/
			if (com->tag == GF_ODF_OD_UPDATE_TAG) {
				u32 count, j, k;
				GF_ODRemove *odR = (GF_ODRemove *)command;
				odU = (GF_ODUpdate *)com;
				count = gf_list_count(odU->objectDescriptors);
				/*remove all descs*/
				for (k = 0; k<count; k++) {
					GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, k);
					for (j = 0; j<odR->NbODs; j++) {
						if (od->objectDescriptorID == odR->OD_ID[j]) {
							gf_list_rem(odU->objectDescriptors, k);
							k--;
							count--;
							gf_odf_desc_del((GF_Descriptor *)od);
							break;
						}
					}
				}
				if (!gf_list_count(odU->objectDescriptors)) {
					gf_list_rem(codec->CommandList, i);
					i--;
					count--;
				}
			}
			/*process ESD updates*/
			else if (com->tag == GF_ODF_ESD_UPDATE_TAG) {
				u32 j;
				GF_ODRemove *odR = (GF_ODRemove *)command;
				GF_ESDUpdate *esdU = (GF_ESDUpdate*)com;
				for (j = 0; j<odR->NbODs; j++) {
					if (esdU->ODID == odR->OD_ID[j]) {
						gf_list_rem(codec->CommandList, i);
						i--;
						count--;
						gf_odf_com_del((GF_ODCom**)&esdU);
						break;
					}
				}
			}
		}
		return GF_OK;
	case GF_ODF_OD_UPDATE_TAG:
		odU_o = NULL;
		for (i = 0; i<count; i++) {
			odU_o = (GF_ODUpdate*)gf_list_get(codec->CommandList, i);
			/*process OD updates*/
			if (odU_o->tag == GF_ODF_OD_UPDATE_TAG) break;
			odU_o = NULL;
		}
		if (!odU_o) {
			odU_o = (GF_ODUpdate *)gf_odf_com_new(GF_ODF_OD_UPDATE_TAG);
			gf_list_add(codec->CommandList, odU_o);
		}
		odU = (GF_ODUpdate*)command;
		count = gf_list_count(odU->objectDescriptors);
		for (i = 0; i<count; i++) {
			Bool found = GF_FALSE;
			GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, i);
			u32 j, count2 = gf_list_count(odU_o->objectDescriptors);
			for (j = 0; j<count2; j++) {
				GF_ObjectDescriptor *od2 = (GF_ObjectDescriptor *)gf_list_get(odU_o->objectDescriptors, j);
				if (od2->objectDescriptorID == od->objectDescriptorID) {
					found = GF_TRUE;
					break;
				}
			}
			if (!found) {
				GF_ObjectDescriptor *od_new;
				GF_Err e = gf_odf_desc_copy((GF_Descriptor*)od, (GF_Descriptor**)&od_new);
				if (e == GF_OK)
					gf_list_add(odU_o->objectDescriptors, od_new);
			}

		}
		return GF_OK;
	}
	return GF_NOT_SUPPORTED;
}
Esempio n. 30
0
static GF_Err gf_sm_live_setup(GF_SceneEngine *seng)
{
	GF_Err e;
	GF_StreamContext *sc;
	GF_InitialObjectDescriptor *iod;
	GF_ESD *esd;
	u32	i, j;

	e = GF_OK;

	iod = (GF_InitialObjectDescriptor *) seng->ctx->root_od;

	/*build an IOD*/
	if (!iod) {
		seng->ctx->root_od = (GF_ObjectDescriptor*) gf_odf_desc_new(GF_ODF_IOD_TAG);
		iod = (GF_InitialObjectDescriptor *) seng->ctx->root_od;

		i=0;
		while ((sc = gf_list_enum(seng->ctx->streams, &i))) {
			if (sc->streamType != GF_STREAM_SCENE) continue;

			if (!sc->ESID) sc->ESID = 1;

			esd = gf_odf_desc_esd_new(2);
			gf_odf_desc_del((GF_Descriptor *) esd->decoderConfig->decoderSpecificInfo);
			esd->decoderConfig->decoderSpecificInfo = NULL;
			esd->ESID = sc->ESID;
			esd->decoderConfig->streamType = GF_STREAM_SCENE;
			esd->decoderConfig->objectTypeIndication = sc->objectType;
			gf_list_add(iod->ESDescriptors, esd);
		
			if (!sc->timeScale) sc->timeScale = 1000;
			esd->slConfig->timestampResolution = sc->timeScale;
		}
	}

	i=0;
	while ((sc = (GF_StreamContext*)gf_list_enum(seng->ctx->streams, &i))) {

		j=0;
		while ((esd = gf_list_enum(seng->ctx->root_od->ESDescriptors, &j))) {
			if (sc->ESID==esd->ESID) {
				break;
			}
		}
		if (!esd) continue;

		if (!esd->slConfig) esd->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG);
		if (!esd->slConfig->timestampResolution) esd->slConfig->timestampResolution = 1000;
		if (!sc->timeScale) sc->timeScale = esd->slConfig->timestampResolution;


		if (sc->streamType == GF_STREAM_SCENE) {	
			switch (sc->objectType) {
#ifndef GPAC_DISABLE_BIFS_ENC
			case GPAC_OTI_SCENE_BIFS:
			case GPAC_OTI_SCENE_BIFS_V2:
				e = gf_sm_setup_bifsenc(seng, sc, esd);
				break;
#endif

#ifndef GPAC_DISABLE_LASER
			case GPAC_OTI_SCENE_LASER:
				e = gf_sm_setup_lsrenc(seng, sc, esd);
				break;
#endif
			case GPAC_OTI_SCENE_DIMS:
				/* Nothing to be done here */			
				break;
			default:
				e = GF_NOT_SUPPORTED;
				break;
			}	
			if (e) return e;
		}
	}
	return e;
}