Пример #1
0
static u32 FAAD_CanHandleStream(GF_BaseDecoder *dec, u32 StreamType, GF_ESD *esd, u8 PL)
{
#ifndef GPAC_DISABLE_AV_PARSERS
	GF_M4ADecSpecInfo a_cfg;
#endif

	/*audio decs*/
	if (StreamType != GF_STREAM_AUDIO) return GF_CODEC_NOT_SUPPORTED;
	/*media type query*/
	if (!esd) return GF_CODEC_STREAM_TYPE_SUPPORTED;

	switch (esd->decoderConfig->objectTypeIndication) {
	/*MPEG2 aac*/
	case GPAC_OTI_AUDIO_AAC_MPEG2_MP:
	case GPAC_OTI_AUDIO_AAC_MPEG2_LCP:
	case GPAC_OTI_AUDIO_AAC_MPEG2_SSRP:
	/*MPEG4 aac*/
	case GPAC_OTI_AUDIO_AAC_MPEG4:
		break;
	default:
		return GF_CODEC_NOT_SUPPORTED;
	}
	/*this codec currently requires AAC config in ESD*/
	if (!esd->decoderConfig->decoderSpecificInfo || !esd->decoderConfig->decoderSpecificInfo->data) {
		GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] DecoderSpecificInfo missing - cannot initialize\n"));
		return GF_CODEC_NOT_SUPPORTED;
	}
#ifndef GPAC_DISABLE_AV_PARSERS
	if (gf_m4a_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &a_cfg) != GF_OK) return GF_CODEC_NOT_SUPPORTED;

	switch (a_cfg.base_object_type) {
	case GF_M4A_AAC_MAIN:
	case GF_M4A_AAC_LC:
	case GF_M4A_AAC_SSR:
	case GF_M4A_AAC_LTP:
	case GF_M4A_AAC_SBR:
		return GF_CODEC_SUPPORTED;
	case GF_M4A_ER_AAC_LC:
	case GF_M4A_ER_AAC_LTP:
	case GF_M4A_ER_AAC_SCALABLE:
	case GF_M4A_ER_AAC_LD:
	case GF_M4A_AAC_PS:
		return GF_CODEC_MAYBE_SUPPORTED;
	default:
		return GF_CODEC_NOT_SUPPORTED;
	}
#endif

	return GF_CODEC_SUPPORTED;
}
Пример #2
0
GF_EXPORT
GF_RTPStreamer *gf_rtp_streamer_new_extended(u32 streamType, u32 oti, u32 timeScale, 
								const char *ip_dest, u16 port, u32 MTU, u8 TTL, const char *ifce_addr, 
								 u32 flags, char *dsi, u32 dsi_len, 
								 
								 u32 PayloadType, u32 sample_rate, u32 nb_ch,
								 Bool is_crypted, u32 IV_length, u32 KI_length,
								 u32 MinSize, u32 MaxSize, u32 avgTS, u32 maxDTSDelta, u32 const_dur, u32 bandwidth, u32 max_ptime, 
								 u32 au_sn_len
								 )
{
	GF_SLConfig slc;
	GF_RTPStreamer *stream;
	u32 rtp_type, default_rtp_rate;
	u8 OfficialPayloadType;
	u32 required_rate, force_dts_delta, PL_ID;
	char *mpeg4mode;
	Bool has_mpeg4_mapping;
	GF_Err e;

	if (!timeScale) timeScale = 1000;

	GF_SAFEALLOC(stream, GF_RTPStreamer);


	/*by default NO PL signaled*/
	PL_ID = 0;
	OfficialPayloadType = 0;
	force_dts_delta = 0;
	mpeg4mode = NULL;
	required_rate = 0;
	nb_ch = 0;
	has_mpeg4_mapping = 1;
	rtp_type = 0;

	/*for max compatibility with QT*/
	default_rtp_rate = 90000;

	/*timed-text is a bit special, we support multiple stream descriptions & co*/
	switch (streamType) {
	case GF_STREAM_TEXT:
		if (oti!=GPAC_OTI_TEXT_MPEG4)
			return NULL;

		rtp_type = GF_RTP_PAYT_3GPP_TEXT;
		/*fixme - this works cos there's only one PL for text in mpeg4 at the current time*/
		PL_ID = 0x10;
		break;
	case GF_STREAM_AUDIO:
		required_rate = sample_rate;
		switch (oti) {
		/*AAC*/
		case GPAC_OTI_AUDIO_AAC_MPEG4:
		case GPAC_OTI_AUDIO_AAC_MPEG2_MP:
		case GPAC_OTI_AUDIO_AAC_MPEG2_LCP:
		case GPAC_OTI_AUDIO_AAC_MPEG2_SSRP:
			PL_ID = 0x01;
			mpeg4mode = "AAC";
			rtp_type = GF_RTP_PAYT_MPEG4;
			required_rate = sample_rate;

#ifndef GPAC_DISABLE_AV_PARSERS
			if (dsi) {
				GF_M4ADecSpecInfo a_cfg;
				gf_m4a_get_config(dsi, dsi_len, &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) {
						rtp_type = 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;
				}
			} 
#endif
			break;

			/*MPEG1/2 audio*/
		case GPAC_OTI_AUDIO_MPEG2_PART3:
		case GPAC_OTI_AUDIO_MPEG1:
			if (!is_crypted) {
				rtp_type = GF_RTP_PAYT_MPEG12_AUDIO;
				/*use official RTP/AVP payload type*/
				OfficialPayloadType = 14;
				required_rate = 90000;
			}
			/*encrypted MP3 must be sent through MPEG-4 generic to signal all ISMACryp stuff*/
			else {
				rtp_type = GF_RTP_PAYT_MPEG4;
			}
			break;

		/*QCELP audio*/
		case GPAC_OTI_AUDIO_13K_VOICE:
			rtp_type = GF_RTP_PAYT_QCELP;
			OfficialPayloadType = 12;
			required_rate = 8000;
			nb_ch = 1;
			break;

		/*EVRC/SVM audio*/
		case GPAC_OTI_AUDIO_EVRC_VOICE:
		case GPAC_OTI_AUDIO_SMV_VOICE:
			rtp_type = GF_RTP_PAYT_EVRC_SMV;
			required_rate = 8000;
			nb_ch = 1;
		}

		break;

	case GF_STREAM_VISUAL:
		rtp_type = GF_RTP_PAYT_MPEG4;
		required_rate = default_rtp_rate;
		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;
			flags |= GP_RTP_PCK_SIGNAL_RAP | GP_RTP_PCK_SIGNAL_TS;
		}

		switch (oti) {
		/*ISO/IEC 14496-2*/
		case GPAC_OTI_VIDEO_MPEG4_PART2:
			PL_ID = 1;
#ifndef GPAC_DISABLE_AV_PARSERS
			if (dsi) {
				GF_M4VDecSpecInfo vhdr;
				gf_m4v_get_config(dsi, dsi_len, &vhdr);
				PL_ID = vhdr.VideoPL;
			}
#endif
			break;

		/*MPEG1/2 video*/
		case GPAC_OTI_VIDEO_MPEG1:
		case GPAC_OTI_VIDEO_MPEG2_SIMPLE:
		case GPAC_OTI_VIDEO_MPEG2_MAIN:
		case GPAC_OTI_VIDEO_MPEG2_SNR:
		case GPAC_OTI_VIDEO_MPEG2_SPATIAL:
		case GPAC_OTI_VIDEO_MPEG2_HIGH:
		case GPAC_OTI_VIDEO_MPEG2_422:
			if (!is_crypted) {
				rtp_type = GF_RTP_PAYT_MPEG12_VIDEO;
				OfficialPayloadType = 32;
			}
			break;
		/*AVC/H.264*/
		case GPAC_OTI_VIDEO_AVC:
			required_rate = 90000;	/* "90 kHz clock rate MUST be used"*/
			rtp_type = GF_RTP_PAYT_H264_AVC;
			PL_ID = 0x0F;
			break;
		/*H264-SVC*/
		case GPAC_OTI_VIDEO_SVC:
			required_rate = 90000;	/* "90 kHz clock rate MUST be used"*/
			rtp_type = GF_RTP_PAYT_H264_SVC;
			PL_ID = 0x0F;
			break;
		/*HEVC*/
		case GPAC_OTI_VIDEO_HEVC:
			required_rate = 90000;	/* "90 kHz clock rate MUST be used"*/
			rtp_type = GF_RTP_PAYT_HEVC;
			PL_ID = 0x0F;
			break;
		}
		break;

	case GF_STREAM_SCENE:
	case GF_STREAM_OD:
        if (oti == GPAC_OTI_SCENE_DIMS) {
            rtp_type = GF_RTP_PAYT_3GPP_DIMS;
            has_mpeg4_mapping = 0;
        } else {
            rtp_type = GF_RTP_PAYT_MPEG4;
        }
		break;


	case GF_STREAM_4CC:
		switch (oti) {
		case GF_ISOM_SUBTYPE_3GP_H263:
			rtp_type = GF_RTP_PAYT_H263;
			required_rate = 90000;
			streamType = GF_STREAM_VISUAL;
			OfficialPayloadType = 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;
			rtp_type = 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;
			rtp_type = GF_RTP_PAYT_AMR_WB;
			streamType = GF_STREAM_AUDIO;
			has_mpeg4_mapping = 0;
			nb_ch = 1;
			break;
		case GF_ISOM_SUBTYPE_AC3:
			rtp_type = GF_RTP_PAYT_AC3;
			streamType = GF_STREAM_AUDIO;
			has_mpeg4_mapping = 1;
			nb_ch = 1;
			break;
		case GF_ISOM_SUBTYPE_AVC_H264:
		case GF_ISOM_SUBTYPE_AVC2_H264:
		case GF_ISOM_SUBTYPE_AVC3_H264:
		case GF_ISOM_SUBTYPE_AVC4_H264:
		case GF_ISOM_SUBTYPE_SVC_H264:
		{
			required_rate = 90000;	/* "90 kHz clock rate MUST be used"*/
			rtp_type = GF_RTP_PAYT_H264_AVC;
			streamType = GF_STREAM_VISUAL;
			oti = GPAC_OTI_VIDEO_AVC;
			PL_ID = 0x0F;
		}
			break;
		case GF_ISOM_SUBTYPE_3GP_QCELP:
			required_rate = 8000;
			rtp_type = GF_RTP_PAYT_QCELP;
			streamType = GF_STREAM_AUDIO;
			oti = GPAC_OTI_AUDIO_13K_VOICE;
			OfficialPayloadType = 12;
			nb_ch = 1;
			break;
		case GF_ISOM_SUBTYPE_3GP_EVRC:
		case GF_ISOM_SUBTYPE_3GP_SMV:
			required_rate = 8000;
			rtp_type = GF_RTP_PAYT_EVRC_SMV;
			streamType = GF_STREAM_AUDIO;
			oti = (oti==GF_ISOM_SUBTYPE_3GP_EVRC) ? GPAC_OTI_AUDIO_EVRC_VOICE : GPAC_OTI_AUDIO_SMV_VOICE;
			nb_ch = 1;
			break;
		}
		break;

	default:
		GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("[RTP Packetizer] Unsupported stream type %x\n", streamType));
		return NULL;
	}

	/*not supported*/
	if (!rtp_type) return NULL;
	
	/*override hinter type if requested and possible*/
	if (has_mpeg4_mapping && (flags & GP_RTP_PCK_FORCE_MPEG4)) {
		rtp_type = GF_RTP_PAYT_MPEG4;
	}
	/*use static payload ID if enabled*/
	else if (OfficialPayloadType && (flags & GP_RTP_PCK_USE_STATIC_ID) ) {
		PayloadType = OfficialPayloadType;
	}

	/*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;
	}

	/*default SL for RTP */
	memset(&slc, 0, sizeof(GF_SLConfig));
	slc.tag = GF_ODF_SLC_TAG;
	slc.useTimestampsFlag = 1;
	slc.timestampLength = 32;
	slc.timestampResolution = timeScale;

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

	slc.AUSeqNumLength = au_sn_len;
	slc.CUDuration = const_dur;

	if (flags & GP_RTP_PCK_SIGNAL_RAP) {
		slc.useRandomAccessPointFlag = 1;
	} else {
		slc.useRandomAccessPointFlag = 0;
		slc.hasRandomAccessUnitsOnlyFlag = 1;
	}

	stream->packetizer = gf_rtp_builder_new(rtp_type, &slc, flags, 
								stream, 
								rtp_stream_on_new_packet, rtp_stream_on_packet_done, 
								NULL, rtp_stream_on_data);
	
	if (!stream->packetizer) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("[RTP Packetizer] Failed to create packetizer\n"));
		gf_free(stream);
		return NULL;
	}
	
	gf_rtp_builder_init(stream->packetizer, PayloadType, MTU, max_ptime,
					   streamType, oti, PL_ID, MinSize, MaxSize, avgTS, maxDTSDelta, IV_length, KI_length, mpeg4mode);


	if (force_dts_delta) stream->packetizer->slMap.DTSDeltaLength = force_dts_delta;

	e = rtp_stream_init_channel(stream, MTU + 12, ip_dest, port, TTL, ifce_addr);
	if (e) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("[RTP Packetizer] Failed to create RTP channel - error %s\n", gf_error_to_string(e) ));
		gf_free(stream);
		return NULL;
	}
	stream->ts_scale = slc.timestampResolution;
	stream->ts_scale /= timeScale;

	stream->buffer_alloc = MTU+12;
	stream->buffer = gf_malloc(sizeof(char) * stream->buffer_alloc);

	return stream;
}
Пример #3
0
static GF_Err FAAD_AttachStream(GF_BaseDecoder *ifcg, GF_ESD *esd)
{
#ifndef GPAC_DISABLE_AV_PARSERS
	GF_Err e;
	GF_M4ADecSpecInfo a_cfg;
#endif
	FAADCTX();

	if (ctx->ES_ID && ctx->ES_ID!=esd->ESID) return GF_NOT_SUPPORTED;
	if (!esd->decoderConfig->decoderSpecificInfo || !esd->decoderConfig->decoderSpecificInfo->dataLength) return GF_NON_COMPLIANT_BITSTREAM;

	if (!ctx->esd) {
		ctx->esd = esd;
		GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] Attaching stream %d\n", esd->ESID));
	}

	if (ctx->codec) faacDecClose(ctx->codec);
	ctx->codec = faacDecOpen();
	if (!ctx->codec) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FAAD] Error initializing decoder\n"));
		return GF_IO_ERR;
	}

#ifndef GPAC_DISABLE_AV_PARSERS
	e = gf_m4a_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &a_cfg);
	if (e) return e;
#endif
	if (faacDecInit2(ctx->codec, (unsigned char *)esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, (unsigned long*)&ctx->sample_rate, (u8*)&ctx->num_channels) < 0)
	{
#ifndef GPAC_DISABLE_AV_PARSERS
		s8 res;
		char *dsi, *s_base_object_type;
		u32 dsi_len;
		switch (a_cfg.base_object_type) {
		case GF_M4A_AAC_MAIN:
			s_base_object_type = gf_stringizer(GF_M4A_AAC_MAIN);
			goto base_object_type_error;
		case GF_M4A_AAC_LC:
			s_base_object_type = gf_stringizer(GF_M4A_AAC_LC);
			goto base_object_type_error;
		case GF_M4A_AAC_SSR:
			s_base_object_type = gf_stringizer(GF_M4A_AAC_SSR);
			goto base_object_type_error;
		case GF_M4A_AAC_LTP:
			s_base_object_type = gf_stringizer(GF_M4A_AAC_LTP);
			goto base_object_type_error;
		case GF_M4A_AAC_SBR:
			s_base_object_type = gf_stringizer(GF_M4A_AAC_SBR);
			goto base_object_type_error;
		case GF_M4A_AAC_PS:
			s_base_object_type = gf_stringizer(GF_M4A_AAC_PS);
base_object_type_error: /*error case*/
			GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[FAAD] Error: unsupported %s format for stream %d - defaulting to AAC LC\n", s_base_object_type, esd->ESID));
		default:
			break;
		}
		a_cfg.base_object_type = GF_M4A_AAC_LC;
		a_cfg.has_sbr = GF_FALSE;
		a_cfg.nb_chan = a_cfg.nb_chan > 2 ? 1 : a_cfg.nb_chan;

		gf_m4a_write_config(&a_cfg, &dsi, &dsi_len);
		res = faacDecInit2(ctx->codec, (unsigned char *) dsi, dsi_len, (unsigned long *) &ctx->sample_rate, (u8 *) &ctx->num_channels);
		gf_free(dsi);
		if (res < 0)
#endif
		{
			GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FAAD] Error when initializing AAC decoder for stream %d\n", esd->ESID));
			return GF_NOT_SUPPORTED;
		}
	}

#ifndef GPAC_DISABLE_AV_PARSERS
	ctx->is_sbr = a_cfg.has_sbr;
#endif
	ctx->num_samples = 1024;
	ctx->out_size = 2 * ctx->num_samples * ctx->num_channels;
	ctx->ES_ID = esd->ESID;
	ctx->signal_mc = ctx->num_channels>2 ? GF_TRUE : GF_FALSE;
	return GF_OK;
}
Пример #4
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;
}
Пример #5
0
GF_EXPORT
const char *gf_esd_get_textual_description(GF_ESD *esd)
{
	if (!esd || !esd->decoderConfig) return "Bad parameter";

	switch (esd->decoderConfig->streamType) {
	case GF_STREAM_OD:
		return "MPEG-4 Object Descriptor";
	case GF_STREAM_OCR:
		return "MPEG-4 Object Clock Reference";
	case GF_STREAM_SCENE:
		switch (esd->decoderConfig->objectTypeIndication) {
		case 0x0:
		case 0x1:
		case 0x2:
		case 0x3:
		case 0xFF:
			return "MPEG-4 BIFS Scene Description";
		case GPAC_OTI_SCENE_BIFS_EXTENDED:
			return "MPEG-4 Extended BIFS Scene Description";
		case GPAC_OTI_SCENE_AFX:
			if (!esd->decoderConfig->decoderSpecificInfo || !esd->decoderConfig->decoderSpecificInfo->data) 
				return "AFX Unknown";
			return gf_afx_get_type_description(esd->decoderConfig->decoderSpecificInfo->data[0]);
		case GPAC_OTI_SCENE_LASER:
			{
				GF_LASERConfig l_cfg;
				gf_odf_get_laser_config(esd->decoderConfig->decoderSpecificInfo, &l_cfg);
				if (! l_cfg.newSceneIndicator ) return "LASeR Scene Segment Description";
			}
			return "LASeR Scene Description";
		case GPAC_OTI_SCENE_SYNTHESIZED_TEXTURE:
			return "MPEG-4 Synthesized Texture";
		case GPAC_OTI_SCENE_SAF:
			return "MPEG-4 SAF";
		case GPAC_OTI_3GPP2_CMF:
			return "3GPP2 CMF";
		default:
			return "Unknown Scene Type";
		}
		break;
	case GF_STREAM_VISUAL:
		switch (esd->decoderConfig->objectTypeIndication) {
		case GPAC_OTI_VIDEO_MPEG2_SIMPLE:
			return "MPEG-2 Visual Simple Profile";
		case GPAC_OTI_VIDEO_MPEG2_MAIN:
			return "MPEG-2 Visual Main Profile";
		case GPAC_OTI_VIDEO_MPEG2_SNR:
			return "MPEG-2 Visual SNR Profile";
		case GPAC_OTI_VIDEO_MPEG2_SPATIAL:
			return "MPEG-2 Visual SNR Profile";
		case GPAC_OTI_VIDEO_MPEG2_HIGH:
			return "MPEG-2 Visual SNR Profile";
		case GPAC_OTI_VIDEO_MPEG2_422:
			return "MPEG-2 Visual SNR Profile";
		case GPAC_OTI_VIDEO_MPEG1:
			return "MPEG-1 Video";
		case GPAC_OTI_IMAGE_JPEG:
			return "JPEG Image";
		case GPAC_OTI_IMAGE_PNG:
			return "PNG Image";
		case GPAC_OTI_IMAGE_JPEG_2000:
			return "JPEG2000 Image";
		case GPAC_OTI_VIDEO_MPEG4_PART2:
			return "MPEG-4 Part 2 Video";
		case GPAC_OTI_VIDEO_AVC:
			return "MPEG-4 AVC|H264 Video";
		case GPAC_OTI_VIDEO_AVC_PS:
			return "MPEG-4 AVC|H264 Parameter Set";
		case GPAC_OTI_MEDIA_FFMPEG:
			return "GPAC FFMPEG Private Video";
		case GPAC_OTI_VIDEO_SMPTE_VC1:
			return "SMPTE VC-1 Video";
		case GPAC_OTI_VIDEO_DIRAC:
			return "Dirac Video";
		default:
			return "Unknown Video type";
		}
		break;
	case GF_STREAM_AUDIO:
		switch (esd->decoderConfig->objectTypeIndication) {
		case GPAC_OTI_AUDIO_AAC_MPEG2_MP:
			return "MPEG-2 AAC Main Profile";
		case GPAC_OTI_AUDIO_AAC_MPEG2_LCP:
			return "MPEG-2 AAC Low Complexity Profile";
		case GPAC_OTI_AUDIO_AAC_MPEG2_SSRP:
			return "MPEG-2 AAC Scaleable Sampling Rate Profile";
		case GPAC_OTI_AUDIO_MPEG2_PART3:
			return "MPEG-2 Audio Part 3";
		case GPAC_OTI_AUDIO_MPEG1:
			return "MPEG-1 Audio";
		case GPAC_OTI_AUDIO_AAC_MPEG4:
			{
#ifdef GPAC_DISABLE_AV_PARSERS
				return "MPEG-4 AAC";
#else
				GF_M4ADecSpecInfo a_cfg;
				if (!esd->decoderConfig->decoderSpecificInfo) return "MPEG-4 AAC";
				gf_m4a_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &a_cfg);
				return gf_m4a_object_type_name(a_cfg.base_object_type);
#endif
			}
			break;
		case GPAC_OTI_MEDIA_FFMPEG:
			return "GPAC FFMPEG Private Audio";
		case GPAC_OTI_AUDIO_EVRC_VOICE:
			return "EVRC Voice";
		case GPAC_OTI_AUDIO_SMV_VOICE:
			return "SMV Voice";
		case GPAC_OTI_AUDIO_AC3:
			return "AC-3 audio";
		case GPAC_OTI_AUDIO_AC3_ENHANCED:
			return "Enhanced AC-3 Audio";
		case GPAC_OTI_AUDIO_DRA:
			return "DRA Audio";
		case GPAC_OTI_AUDIO_ITU_G719:
			return "ITU G719 Audio";
		case GPAC_OTI_AUDIO_DTS_CA:
			return "DTS Coherent Acoustics audio";
		case GPAC_OTI_AUDIO_DTS_HD_HR:
			return "DTS-HD High Resolution audio";
		case GPAC_OTI_AUDIO_DTS_HD_MASTER:
			return "DTS-HD Master audios";
		default:
			return "Unknown Audio Type";
		}
		break;
	case GF_STREAM_MPEG7:
		return "MPEG-7 Description";
	case GF_STREAM_IPMP:
		return "MPEG-4 IPMP";
	case GF_STREAM_OCI:
		return "MPEG-4 OCI";
	case GF_STREAM_MPEGJ:
		return "MPEG-4 MPEG-J";
	case GF_STREAM_INTERACT:
		return "MPEG-4 User Interaction";
	case GF_STREAM_IPMP_TOOL:
		return "MPEG-4 IPMP Tool";
	case GF_STREAM_FONT:
		return "MPEG-4 Font Data";
	case GF_STREAM_TEXT:
		return "MPEG-4 Streaming Text";
	case GF_STREAM_ND_SUBPIC:
		return "Nero Digital Subpicture";

	case GF_STREAM_PRIVATE_SCENE:
		switch (esd->decoderConfig->objectTypeIndication) {
		case GPAC_OTI_PRIVATE_SCENE_GENERIC:
			{
				char *ext = strchr(esd->decoderConfig->decoderSpecificInfo->data + 4, '.');
				if (!ext) return "GPAC Internal Scene Description";
				ext += 1;
				if (!strnicmp(ext, "bt", 2))
					return "BT Scene Description";
				if (!strnicmp(ext, "xmt", 2))
					return "XMT Scene Description";
				if (!strnicmp(ext, "wrl", 3))
					return "VRML Scene Description";
				if (!strnicmp(ext, "x3d", 3))
					return "W3D Scene Description";
				if (!strnicmp(ext, "x3dv", 4))
					return "X3D Scene Description";
				if (!strnicmp(ext, "swf", 3))
					return "Flash (SWF) Scene Description";
				if (!strnicmp(ext, "xsr", 3))
					return "LASeR-ML Scene Description";
				if (!strnicmp(ext, "wgt", 3))
					return "W3C Widget Package";
				if (!strnicmp(ext, "mgt", 3))
					return "MPEG-U Widget Package";
			}
			return "GPAC Internal Scene Description";
		case GPAC_OTI_PRIVATE_SCENE_SVG:
			return "SVG";
		case GPAC_OTI_PRIVATE_SCENE_LASER:
			return "LASeR (XML)";
		case GPAC_OTI_PRIVATE_SCENE_XBL:
			return "XBL";
		case GPAC_OTI_PRIVATE_SCENE_EPG:
			return "DVB Event Information";
		case GPAC_OTI_PRIVATE_SCENE_WGT:
			return "W3C/MPEG-U Widget";
		case GPAC_OTI_SCENE_SVG:
			return "SVG over RTP";
		case GPAC_OTI_SCENE_SVG_GZ:
			return "SVG+gz over RTP";
		case GPAC_OTI_SCENE_DIMS:
			return "3GPP DIMS";
		default:
			return "Unknown Scene Description";
		}
		break;
	case GF_STREAM_PRIVATE_MEDIA:
		return "Opaque Decoder";
	case GF_STREAM_4CC:
		return gf_4cc_to_str(esd->decoderConfig->objectTypeIndication);
	default:
		return "Unknown Media Type";
	}
}