Пример #1
0
GF_EXPORT
GF_Err gf_webvtt_dump_iso_track(GF_MediaExporter *dumper, char *szName, u32 track, Bool merge, Bool box_dump)
{
#ifdef GPAC_DISABLE_MEDIA_IMPORT
	return GF_NOT_SUPPORTED;
#else
	GF_Err  e;
	u32     i;
	u32     count;
	u32     timescale;
	FILE    *out;
	u32     di;
	u64     duration;
	GF_WebVTTParser *parser;

	out = szName ? gf_fopen(szName, "wt") : (dumper->dump_file ? dumper->dump_file : stdout);
	if (!out) return GF_IO_ERR;// gf_export_message(dumper, GF_IO_ERR, "Error opening %s for writing - check disk access & permissions", szName);

	parser = gf_webvtt_parser_new();
	parser->user = out;
	parser->on_cue_read = gf_webvtt_dump_cue;

	if (box_dump)
		fprintf(out, "<WebVTTTrack trackID=\"%d\">\n", gf_isom_get_track_id(dumper->file, track) );

	e = gf_webvtt_dump_header(out, dumper->file, track, box_dump, 1);
	if (e) goto exit;

	timescale = gf_isom_get_media_timescale(dumper->file, track);

	count = gf_isom_get_sample_count(dumper->file, track);
	for (i=0; i<count; i++) {
		GF_ISOSample *samp = gf_isom_get_sample(dumper->file, track, i+1, &di);
		if (!samp) {
			e = gf_isom_last_error(dumper->file);
			goto exit;
		}
		e = gf_webvtt_parse_iso_sample(parser, timescale, samp, merge, box_dump);
		if (e) {
			goto exit;
		}
		gf_isom_sample_del(&samp);
	}
	duration = gf_isom_get_media_duration(dumper->file, track);
	gf_webvtt_parser_dump_finalize(parser, duration);

	if (box_dump)
		fprintf(out, "</WebVTTTrack>\n");

exit:
	gf_webvtt_parser_del(parser);
	if (szName) gf_fclose(out);
	return e;
#endif
}
Пример #2
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 );
}
Пример #3
0
void gf_media_get_sample_average_infos(GF_ISOFile *file, u32 Track, u32 *avgSize, u32 *MaxSize, u32 *TimeDelta, u32 *maxCTSDelta, u32 *const_duration, u32 *bandwidth)
{
	u32 i, count, ts_diff;
	u64 prevTS, DTS, tdelta;
	Double bw;
	GF_ISOSample *samp;

	*avgSize = *MaxSize = 0;
	*TimeDelta = 0;
	*maxCTSDelta = 0;
	bw = 0;
	prevTS = 0;
	DTS = 0;
	tdelta = 0;

	count = gf_isom_get_sample_count(file, Track);
	*const_duration = 0;

	for (i=0; i<count; i++) {
		samp = gf_isom_get_sample_info(file, Track, i+1, NULL, NULL);
		//get the size
		*avgSize += samp->dataLength;
		if (*MaxSize < samp->dataLength) *MaxSize = samp->dataLength;
		ts_diff = (u32) (samp->DTS+samp->CTS_Offset - prevTS);
		//get the time
		tdelta += ts_diff;

		if (i==1) {
			*const_duration = ts_diff;
		} else if ( (i<count-1) && (*const_duration != ts_diff) ) {
			*const_duration = 0;
		}

		prevTS = samp->DTS+samp->CTS_Offset;
		bw += 8*samp->dataLength;
		
		//get the CTS delta
		if (samp->CTS_Offset > *maxCTSDelta) *maxCTSDelta = samp->CTS_Offset;
		gf_isom_sample_del(&samp);
	}
	if (count>1) *TimeDelta = (u32) (tdelta/ (count-1) );
	else *TimeDelta = (u32) tdelta;
	*avgSize /= count;
	bw *= gf_isom_get_media_timescale(file, Track);
	bw /= (s64) gf_isom_get_media_duration(file, Track);
	bw /= 1000;
	(*bandwidth) = (u32) (bw+0.5);

	//delta is NOT an average, we need to know exactly how many bits are
	//needed to encode CTS-DTS for ANY samples
}
Пример #4
0
GF_Err get_laser_track_size(GF_ISOFile *mp4, u32 *size)
{
	GF_Err e = GF_OK;
	u32 j;
	u32 track_id, trackNum;
	
	*size = 0;
	track_id = gf_isom_get_track_id(mp4, 1);
	trackNum = gf_isom_get_track_by_id(mp4, track_id);
	for (j=0; j<gf_isom_get_sample_count(mp4, trackNum); j++) {
		GF_ISOSample *samp = gf_isom_get_sample_info(mp4, trackNum, j+1, NULL, NULL);
		*size += samp->dataLength;
		gf_isom_sample_del(&samp);
	}
	return e;
}
Пример #5
0
static GF_Err TTIn_ChannelGetSLP(GF_InputService *plug, LPNETCHANNEL channel, char **out_data_ptr, u32 *out_data_size, GF_SLHeader *out_sl_hdr, Bool *sl_compressed, GF_Err *out_reception_status, Bool *is_new_data)
{
    TTIn *tti = (TTIn *)plug->priv;

    *out_reception_status = GF_OK;
    *sl_compressed = 0;
    *is_new_data = 0;

    memset(&tti->sl_hdr, 0, sizeof(GF_SLHeader));
    tti->sl_hdr.randomAccessPointFlag = 1;
    tti->sl_hdr.compositionTimeStampFlag = 1;
    tti->sl_hdr.accessUnitStartFlag = tti->sl_hdr.accessUnitEndFlag = 1;

    /*fetching es data*/
    if (tti->ch == channel) {
        if (tti->samp_num>=gf_isom_get_sample_count(tti->mp4, tti->tt_track)) {
            *out_reception_status = GF_EOS;
            return GF_OK;
        }

        if (!tti->samp) {
            u32 di;
            if (tti->start_range) {
                u32 di;
                *out_reception_status = gf_isom_get_sample_for_movie_time(tti->mp4, tti->tt_track, tti->start_range, &di, GF_ISOM_SEARCH_SYNC_BACKWARD, &tti->samp, &tti->samp_num);
                tti->start_range = 0;
            } else {
                tti->samp = gf_isom_get_sample(tti->mp4, tti->tt_track, tti->samp_num+1, &di);
            }
            if (!tti->samp) {
                *out_reception_status = GF_CORRUPTED_DATA;
                return GF_OK;
            }
            *is_new_data = 1;
        }
        tti->sl_hdr.compositionTimeStamp = tti->sl_hdr.decodingTimeStamp = tti->samp->DTS;
        *out_data_ptr = tti->samp->data;
        *out_data_size = tti->samp->dataLength;
        *out_sl_hdr = tti->sl_hdr;
        return GF_OK;
    }
    return GF_STREAM_NOT_FOUND;
}
Пример #6
0
GF_Err gf_webvtt_dump_iso_track(GF_MediaExporter *dumper, char *szName, u32 track, Bool merge)
{
	GF_Err  e;
	u32     i;
	u32     count;
	u32     timescale;
	FILE    *out;
	u32     di;
	u64     duration;
	GF_WebVTTParser *parser;

	out = szName ? gf_fopen(szName, "wt") : stdout;
	if (!out) return GF_IO_ERR;// gf_export_message(dumper, GF_IO_ERR, "Error opening %s for writing - check disk access & permissions", szName);

	parser = gf_webvtt_parser_new();
	parser->user = out;
	parser->on_cue_read = gf_webvtt_dump_cue;

	e = gf_webvtt_dump_header(out, dumper->file, track, 1);
	if (e) goto exit;

	timescale = gf_isom_get_media_timescale(dumper->file, track);

	count = gf_isom_get_sample_count(dumper->file, track);
	for (i=0; i<count; i++) {
		GF_ISOSample *samp = gf_isom_get_sample(dumper->file, track, i+1, &di);
		if (!samp) {
			e = gf_isom_last_error(dumper->file);
			goto exit;
		}
		e = gf_webvtt_parse_iso_sample(parser, timescale, samp, merge);
		if (e) goto exit;
		//gf_webvtt_dump_iso_sample(out, timescale, samp);
	}
	duration = gf_isom_get_media_duration(dumper->file, track);
	gf_webvtt_parser_dump_finalize(parser, duration);

exit:
	gf_webvtt_parser_del(parser);
	if (szName) gf_fclose(out);
	return e;
}
Пример #7
0
static void process_samples_from_track(GF_ISOFile *movie, u32 track_id, u32 *sample_index)
{
	u32 track_number;
	u32 sample_count;
	/* Error indicator */
	GF_Err e;
	/* Number of bytes required to finish the current ISO Box reading */
	u64 missing_bytes;

	track_number = gf_isom_get_track_by_id(movie, track_id);
	if (track_number == 0) {
		fprintf(stdout, "Could not find track ID=%u. Ignore segment.\n", track_id);
		return;
	}

	sample_count = gf_isom_get_sample_count(movie, track_number);
	while (*sample_index <= sample_count) {
		GF_ISOSample *iso_sample;
		u32 sample_description_index;

		iso_sample = gf_isom_get_sample(movie, track_number, *sample_index, &sample_description_index);
		if (iso_sample) {
			fprintf(stdout, "Found sample #%5d/%5d of length %8d, RAP: %d, DTS: "LLD", CTS: "LLD"\n", *sample_index, sample_count, iso_sample->dataLength, iso_sample->IsRAP, iso_sample->DTS, iso_sample->DTS+iso_sample->CTS_Offset);
			(*sample_index)++;

			/* Release the sample data, once you're done with it*/
			gf_isom_sample_del(&iso_sample);
		} else {
			e = gf_isom_last_error(movie);
			if (e == GF_ISOM_INCOMPLETE_FILE) {
				missing_bytes = gf_isom_get_missing_bytes(movie, track_number);
				fprintf(stdout, "Missing "LLU" bytes on input file\n", missing_bytes);
				gf_sleep(1000);
			}
		}
	}
}
Пример #8
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;
}
Пример #9
0
/*import cubic QTVR to mp4*/
GF_Err gf_sm_load_init_qt(GF_SceneLoader *load)
{
	u32 i, di, w, h, tk, nb_samp;
	Bool has_qtvr;
	GF_ISOSample *samp;
	GF_ISOFile *src;
	GF_StreamContext *st;
	GF_AUContext *au;
	GF_Command *com;
	M_Background *back;
	M_NavigationInfo *ni;
	M_Group *gr;
	GF_ODUpdate *odU;
	GF_SceneGraph *sg;
	GF_ObjectDescriptor *od;
	GF_ESD *esd;

	if (!load->ctx) return GF_NOT_SUPPORTED;

	src = gf_isom_open(load->fileName, GF_ISOM_OPEN_READ, NULL);
	if (!src) return gf_qt_report(load, GF_URL_ERROR, "Opening file %s failed", load->fileName);

	w = h = tk = 0;
	nb_samp = 0;

	has_qtvr = 0;
	for (i=0; i<gf_isom_get_track_count(src); i++) {
		switch (gf_isom_get_media_type(src, i+1)) {
		case GF_ISOM_MEDIA_VISUAL:
			if (gf_isom_get_media_subtype(src, i+1, 1) == GF_4CC('j', 'p', 'e', 'g')) {
				GF_GenericSampleDescription *udesc = gf_isom_get_generic_sample_description(src, i+1, 1);
				if ((udesc->width>w) || (udesc->height>h)) {
					w = udesc->width;
					h = udesc->height;
					tk = i+1;
					nb_samp = gf_isom_get_sample_count(src, i+1);
				}
				if (udesc->extension_buf) gf_free(udesc->extension_buf);
				gf_free(udesc);
			}
			break;
		case GF_4CC('q','t','v','r'):
			has_qtvr = 1;
			break;
		}
	}
	if (!has_qtvr) {
		gf_isom_delete(src);
		return gf_qt_report(load, GF_NOT_SUPPORTED, "QTVR not found - no conversion available for this QuickTime movie");
	}
	if (!tk) {
		gf_isom_delete(src);
		return gf_qt_report(load, GF_NON_COMPLIANT_BITSTREAM, "No associated visual track with QTVR movie");
	}
	if (nb_samp!=6) {
		gf_isom_delete(src);
		return gf_qt_report(load, GF_NOT_SUPPORTED, "Movie %s doesn't look a Cubic QTVR - sorry...", load->fileName);
	}

	GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("QT: Importing Cubic QTVR Movie"));

	/*create scene*/
	sg = load->ctx->scene_graph;
	gr = (M_Group *) gf_node_new(sg, TAG_MPEG4_Group);
	gf_node_register((GF_Node *)gr, NULL);
	st = gf_sm_stream_new(load->ctx, 1, GF_STREAM_SCENE, 1);
	au = gf_sm_stream_au_new(st, 0, 0, 1);
	com = gf_sg_command_new(load->ctx->scene_graph, GF_SG_SCENE_REPLACE);
	gf_list_add(au->commands, com);
	com->node = (GF_Node *)gr;

	back = (M_Background *) gf_node_new(sg, TAG_MPEG4_Background);
	gf_node_list_add_child( &gr->children, (GF_Node*)back);
	gf_node_register((GF_Node *)back, (GF_Node *)gr);

	gf_sg_vrml_mf_alloc(&back->leftUrl, GF_SG_VRML_MFURL, 1);
	back->leftUrl.vals[0].OD_ID = 2;
	gf_sg_vrml_mf_alloc(&back->frontUrl, GF_SG_VRML_MFURL, 1);
	back->frontUrl.vals[0].OD_ID = 3;
	gf_sg_vrml_mf_alloc(&back->rightUrl, GF_SG_VRML_MFURL, 1);
	back->rightUrl.vals[0].OD_ID = 4;
	gf_sg_vrml_mf_alloc(&back->backUrl, GF_SG_VRML_MFURL, 1);
	back->backUrl.vals[0].OD_ID = 5;
	gf_sg_vrml_mf_alloc(&back->topUrl, GF_SG_VRML_MFURL, 1);
	back->topUrl.vals[0].OD_ID = 6;
	gf_sg_vrml_mf_alloc(&back->bottomUrl, GF_SG_VRML_MFURL, 1);
	back->bottomUrl.vals[0].OD_ID = 7;

	ni = (M_NavigationInfo *) gf_node_new(sg, TAG_MPEG4_NavigationInfo);
	gf_node_list_add_child(&gr->children, (GF_Node*)ni);
	gf_node_register((GF_Node *)ni, (GF_Node *)gr);
	gf_sg_vrml_mf_reset(&ni->type, GF_SG_VRML_MFSTRING);
	gf_sg_vrml_mf_alloc(&ni->type, GF_SG_VRML_MFSTRING, 1);
	ni->type.vals[0] = gf_strdup("QTVR");

	/*create ODs*/
	st = gf_sm_stream_new(load->ctx, 2, GF_STREAM_OD, 1);
	au = gf_sm_stream_au_new(st, 0, 0, 1);
	odU = (GF_ODUpdate*) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG);
	gf_list_add(au->commands, odU);
	for (i=0; i<6; i++) {
		GF_MuxInfo *mi;
		FILE *img;
		char szName[1024];
		od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
		od->objectDescriptorID = 2+i;
		esd = gf_odf_desc_esd_new(2);
		esd->decoderConfig->streamType = GF_STREAM_VISUAL;
		esd->decoderConfig->objectTypeIndication = GPAC_OTI_IMAGE_JPEG;
		esd->ESID = 3+i;
		/*extract image and remember it*/
		mi = (GF_MuxInfo *) gf_odf_desc_new(GF_ODF_MUXINFO_TAG);
		gf_list_add(esd->extensionDescriptors, mi);
		mi->delete_file = 1;
		sprintf(szName, "%s_img%d.jpg", load->fileName, esd->ESID);
		mi->file_name = gf_strdup(szName);
		
		gf_list_add(od->ESDescriptors, esd);
		gf_list_add(odU->objectDescriptors, od);

		samp = gf_isom_get_sample(src, tk, i+1, &di);
		img = gf_f64_open(mi->file_name, "wb");
		fwrite(samp->data, samp->dataLength, 1, img);
		fclose(img);
		gf_isom_sample_del(&samp);
	}
	gf_isom_delete(src);
	return GF_OK;
}
Пример #10
0
static GF_Err ISOW_Write(GF_StreamingCache *mc, LPNETCHANNEL ch, char *data, u32 data_size, GF_SLHeader *sl_hdr)
{
	ISOMChannel *mch;
	GF_ESD *esd;
	u32 di, mtype;
	u64 DTS, CTS;
	ISOMReader *cache = (ISOMReader *)mc->priv;
	if (!cache->mov || !cache->service) return GF_BAD_PARAM;

	mch = isor_get_channel(cache, ch);
	if (!mch) {
		Bool mapped;
		GF_NetworkCommand com;
		com.base.on_channel = ch;
		com.base.command_type = GF_NET_CHAN_GET_ESD;
		gf_service_command(cache->service, &com, GF_OK);
		if (!com.cache_esd.esd) return GF_SERVICE_ERROR;

		esd = (GF_ESD *)com.cache_esd.esd;
		switch (esd->decoderConfig->streamType) {
		case GF_STREAM_OD:
			mtype = GF_ISOM_MEDIA_OD;
			break;
		case GF_STREAM_SCENE:
			mtype = GF_ISOM_MEDIA_SCENE;
			break;
		case GF_STREAM_VISUAL:
			mtype = GF_ISOM_MEDIA_VISUAL;
			break;
		case GF_STREAM_AUDIO:
			mtype = GF_ISOM_MEDIA_AUDIO;
			break;
		case GF_STREAM_MPEG7:
			mtype = GF_ISOM_MEDIA_MPEG7;
			break;
		case GF_STREAM_OCI:
			mtype = GF_ISOM_MEDIA_OCI;
			break;
		case GF_STREAM_IPMP:
			mtype = GF_ISOM_MEDIA_IPMP;
			break;
		case GF_STREAM_MPEGJ:
			mtype = GF_ISOM_MEDIA_MPEGJ;
			break;
		case GF_STREAM_TEXT:
			mtype = GF_ISOM_MEDIA_TEXT;
			break;
		default:
			return GF_NOT_SUPPORTED;
		}
		GF_SAFEALLOC(mch, ISOMChannel);
		if (!mch) {
			return GF_OUT_OF_MEM;
		}
		mch->time_scale = esd->slConfig->timestampResolution;
		mch->streamType = esd->decoderConfig->streamType;
		mch->track = gf_isom_new_track(cache->mov, com.cache_esd.esd->ESID, mtype, mch->time_scale);
		mch->is_playing = GF_TRUE;
		mch->channel = ch;
		mch->owner = cache;
		gf_isom_set_track_enabled(cache->mov, mch->track, 1);
		/*translate 3GP streams to MP4*/
		mapped = GF_FALSE;
		if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_MEDIA_GENERIC) {
			char szCode[5];
			strncpy(szCode, esd->decoderConfig->decoderSpecificInfo->data, 4);
			szCode[4]=0;
			if (!stricmp(szCode, "samr") || !stricmp(szCode, "amr ") || !stricmp(szCode, "sawb")) {
				GF_3GPConfig amrc;
				mapped = GF_TRUE;
				memset(&amrc, 0, sizeof(GF_3GPConfig));

				amrc.frames_per_sample = (u32) esd->decoderConfig->decoderSpecificInfo->data[13];
				amrc.type = (!stricmp(szCode, "sawb")) ? GF_ISOM_SUBTYPE_3GP_AMR_WB : GF_ISOM_SUBTYPE_3GP_AMR;
				amrc.vendor = GF_VENDOR_GPAC;
				gf_isom_3gp_config_new(cache->mov, mch->track, &amrc, NULL, NULL, &di);
			} else if (!stricmp(szCode, "h263")) {
				GF_3GPConfig h263c;
				memset(&h263c, 0, sizeof(GF_3GPConfig));
				h263c.type = GF_ISOM_SUBTYPE_3GP_H263;
				h263c.vendor = GF_VENDOR_GPAC;
				gf_isom_3gp_config_new(cache->mov, mch->track, &h263c, NULL, NULL, &di);
				mapped = GF_TRUE;
			}
		}
		if (!mapped) gf_isom_new_mpeg4_description(cache->mov, mch->track, esd, NULL, NULL, &di);
		if (com.cache_esd.is_iod_stream) gf_isom_add_track_to_root_od(cache->mov, mch->track);
		gf_list_add(cache->channels, mch);
	}

	/*first sample, cache it*/
	if (!mch->cache_sample) {
		mch->cache_seed_ts = sl_hdr->decodingTimeStamp;
		mch->cache_sample = gf_isom_sample_new();
		mch->cache_sample->IsRAP = sl_hdr->randomAccessPointFlag;
		mch->cache_sample->dataLength = data_size;
		mch->cache_sample->data = (char*)gf_malloc(sizeof(char)*data_size);
		memcpy(mch->cache_sample->data, data, sizeof(char)*data_size);
		return GF_OK;
	}

	/*adjust DTS/CTS*/
	DTS = sl_hdr->decodingTimeStamp - mch->cache_seed_ts;

	if ((mch->streamType==GF_STREAM_VISUAL) && (DTS<=mch->cache_sample->DTS)) {
		assert(DTS>mch->prev_dts);
		CTS = mch->cache_sample->DTS + mch->cache_sample->CTS_Offset;
		mch->cache_sample->CTS_Offset = 0;

		/*first time, shift all CTS*/
		if (!mch->frame_cts_offset) {
			u32 i, count = gf_isom_get_sample_count(cache->mov, mch->track);
			mch->frame_cts_offset = (u32) (DTS-mch->prev_dts);
			for (i=0; i<count; i++) {
				gf_isom_modify_cts_offset(cache->mov, mch->track, i+1, mch->frame_cts_offset);
			}
			mch->cache_sample->CTS_Offset += mch->frame_cts_offset;
		}
		mch->cache_sample->DTS = mch->prev_dts + mch->frame_cts_offset;
		mch->cache_sample->CTS_Offset += (u32) (CTS-mch->cache_sample->DTS);
	}
	/*deal with reference picture insertion: if no CTS offset and biggest CTS until now, this is
	a reference insertion - we must check that in order to make sure we have strictly increasing DTSs*/
	if (mch->max_cts && !mch->cache_sample->CTS_Offset && (mch->cache_sample->DTS+mch->cache_sample->CTS_Offset > mch->max_cts)) {
		assert(mch->cache_sample->DTS > mch->prev_dts + mch->frame_cts_offset);
		CTS = mch->cache_sample->DTS + mch->cache_sample->CTS_Offset;
		mch->cache_sample->DTS = mch->prev_dts + mch->frame_cts_offset;
		mch->cache_sample->CTS_Offset = (u32) (CTS-mch->cache_sample->DTS);
	}
	if (mch->cache_sample->CTS_Offset)
		mch->max_cts = mch->cache_sample->DTS+mch->cache_sample->CTS_Offset;

	/*add cache*/
	gf_isom_add_sample(cache->mov, mch->track, 1, mch->cache_sample);
	assert(!mch->prev_dts || (mch->prev_dts < mch->cache_sample->DTS));
	mch->prev_dts = mch->cache_sample->DTS;
	mch->duration = MAX(mch->max_cts, mch->prev_dts);
	gf_isom_sample_del(&mch->cache_sample);

	/*store sample*/
	mch->cache_sample = gf_isom_sample_new();
	mch->cache_sample->IsRAP = sl_hdr->randomAccessPointFlag;
	mch->cache_sample->DTS = DTS + mch->frame_cts_offset;
	mch->cache_sample->CTS_Offset = (u32) (sl_hdr->compositionTimeStamp - mch->cache_seed_ts - DTS);
	mch->cache_sample->dataLength = data_size;
	mch->cache_sample->data = (char*)gf_malloc(sizeof(char)*data_size);
	memcpy(mch->cache_sample->data, data, sizeof(char)*data_size);
	return GF_OK;
}
Пример #11
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;
} 
Пример #12
0
static GF_Err gf_sm_load_run_isom(GF_SceneLoader *load)
{
	GF_Err e;
	FILE *logs;
	u32 i, j, di, nbBifs, nbLaser, nb_samp, samp_done, init_offset;
	GF_StreamContext *sc;
	GF_ESD *esd;
	GF_ODCodec *od_dec;
#ifndef GPAC_DISABLE_BIFS
	GF_BifsDecoder *bifs_dec;
#endif
#ifndef GPAC_DISABLE_LASER
	GF_LASeRCodec *lsr_dec;
#endif

	if (!load || !load->isom) return GF_BAD_PARAM;

	nbBifs = nbLaser = 0;
	e = GF_OK;
#ifndef GPAC_DISABLE_BIFS
	bifs_dec = gf_bifs_decoder_new(load->scene_graph, 1);
	gf_bifs_decoder_set_extraction_path(bifs_dec, load->localPath, load->fileName);
#endif
	od_dec = gf_odf_codec_new();
	logs = NULL;
#ifndef GPAC_DISABLE_LASER
	lsr_dec = gf_laser_decoder_new(load->scene_graph);
#endif
	esd = NULL;
	/*load each stream*/
	nb_samp = 0;
	for (i=0; i<gf_isom_get_track_count(load->isom); i++) {
		u32 type = gf_isom_get_media_type(load->isom, i+1);
		switch (type) {
		case GF_ISOM_MEDIA_SCENE:
		case GF_ISOM_MEDIA_OD:
			nb_samp += gf_isom_get_sample_count(load->isom, i+1);
			break;
		default:
			break;
		}
	}
	samp_done = 1;
	gf_isom_text_set_streaming_mode(load->isom, 1);

	for (i=0; i<gf_isom_get_track_count(load->isom); i++) {
		u32 type = gf_isom_get_media_type(load->isom, i+1);
		switch (type) {
		case GF_ISOM_MEDIA_SCENE:
		case GF_ISOM_MEDIA_OD:
			break;
		default:
			continue;
		}
		esd = gf_isom_get_esd(load->isom, i+1, 1);
		if (!esd) continue;


		if ((esd->decoderConfig->objectTypeIndication == GPAC_OTI_SCENE_AFX) ||
		        (esd->decoderConfig->objectTypeIndication == GPAC_OTI_SCENE_SYNTHESIZED_TEXTURE)
		   ) {
			nb_samp += gf_isom_get_sample_count(load->isom, i+1);
			continue;
		}
		sc = gf_sm_stream_new(load->ctx, esd->ESID, esd->decoderConfig->streamType, esd->decoderConfig->objectTypeIndication);
		sc->streamType = esd->decoderConfig->streamType;
		sc->ESID = esd->ESID;
		sc->objectType = esd->decoderConfig->objectTypeIndication;
		sc->timeScale = gf_isom_get_media_timescale(load->isom, i+1);

		/*we still need to reconfig the BIFS*/
		if (esd->decoderConfig->streamType==GF_STREAM_SCENE) {
#ifndef GPAC_DISABLE_BIFS
			/*BIFS*/
			if (esd->decoderConfig->objectTypeIndication<=2) {
				if (!esd->dependsOnESID && nbBifs && !i)
					mp4_report(load, GF_OK, "several scene namespaces used or improper scene dependencies in file - import may be incorrect");
				if (!esd->decoderConfig->decoderSpecificInfo) {
					/* Hack for T-DMB non compliant streams */
					e = gf_bifs_decoder_configure_stream(bifs_dec, esd->ESID, NULL, 0, esd->decoderConfig->objectTypeIndication);
				} else {
					e = gf_bifs_decoder_configure_stream(bifs_dec, esd->ESID, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, esd->decoderConfig->objectTypeIndication);
				}
				if (e) goto exit;
				nbBifs++;
			}
#endif

#ifndef GPAC_DISABLE_LASER
			/*LASER*/
			if (esd->decoderConfig->objectTypeIndication==0x09) {
				if (!esd->dependsOnESID && nbBifs && !i)
					mp4_report(load, GF_OK, "several scene namespaces used or improper scene dependencies in file - import may be incorrect");
				e = gf_laser_decoder_configure_stream(lsr_dec, esd->ESID, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength);
				if (e) goto exit;
				nbLaser++;
			}
#endif
		}

		init_offset = 0;
		/*dump all AUs*/
		for (j=0; j<gf_isom_get_sample_count(load->isom, i+1); j++) {
			GF_AUContext *au;
			GF_ISOSample *samp = gf_isom_get_sample(load->isom, i+1, j+1, &di);
			if (!samp) {
				mp4_report(load, gf_isom_last_error(load->isom), "Unable to fetch sample %d from track ID %d - aborting track import", j+1, gf_isom_get_track_id(load->isom, i+1));
				break;
			}
			/*check if track has initial offset*/
			if (!j && gf_isom_get_edit_segment_count(load->isom, i+1)) {
				u64 EditTime, dur, mtime;
				u8 mode;
				gf_isom_get_edit_segment(load->isom, i+1, 1, &EditTime, &dur, &mtime, &mode);
				if (mode==GF_ISOM_EDIT_EMPTY) {
					init_offset = (u32) (dur * sc->timeScale / gf_isom_get_timescale(load->isom) );
				}
			}
			samp->DTS += init_offset;

			au = gf_sm_stream_au_new(sc, samp->DTS, ((Double)(s64) samp->DTS) / sc->timeScale, (samp->IsRAP==RAP) ? 1 : 0);

			if (esd->decoderConfig->streamType==GF_STREAM_SCENE) {
#ifndef GPAC_DISABLE_BIFS
				if (esd->decoderConfig->objectTypeIndication<=2)
					e = gf_bifs_decode_command_list(bifs_dec, esd->ESID, samp->data, samp->dataLength, au->commands);
#endif
#ifndef GPAC_DISABLE_LASER
				if (esd->decoderConfig->objectTypeIndication==0x09)
					e = gf_laser_decode_command_list(lsr_dec, esd->ESID, samp->data, samp->dataLength, au->commands);
#endif
			} else {
				e = gf_odf_codec_set_au(od_dec, samp->data, samp->dataLength);
				if (!e) e = gf_odf_codec_decode(od_dec);
				if (!e) {
					while (1) {
						GF_ODCom *odc = gf_odf_codec_get_com(od_dec);
						if (!odc) break;
						/*update ESDs if any*/
						UpdateODCommand(load->isom, odc);
						gf_list_add(au->commands, odc);
					}
				}
			}
			gf_isom_sample_del(&samp);
			if (e) {
				mp4_report(load, gf_isom_last_error(load->isom), "decoding sample %d from track ID %d failed", j+1, gf_isom_get_track_id(load->isom, i+1));
				goto exit;
			}

			samp_done++;
			gf_set_progress("MP4 Loading", samp_done, nb_samp);
		}
		gf_odf_desc_del((GF_Descriptor *) esd);
		esd = NULL;
	}
	gf_isom_text_set_streaming_mode(load->isom, 0);

exit:
#ifndef GPAC_DISABLE_BIFS
	gf_bifs_decoder_del(bifs_dec);
#endif
	gf_odf_codec_del(od_dec);
#ifndef GPAC_DISABLE_LASER
	gf_laser_decoder_del(lsr_dec);
#endif
	if (esd) gf_odf_desc_del((GF_Descriptor *) esd);
	if (logs) gf_fclose(logs);
	return e;
}
Пример #13
0
int main(int argc, char **argv)
{
	/* The ISO progressive reader */
	GF_ISOFile *movie;
	/* Error indicator */
	GF_Err e;
	/* Number of bytes required to finish the current ISO Box reading */
	u64 missing_bytes;
	/* Return value for the program */
	int ret = 0;
	/* Maximum index of the segments*/
	u32 seg_max = argc-2;
	/* Number of the segment being processed*/
	u32 seg_curr = 0;
	u32 track_id = 1;
	u32 sample_index = 1;

	/* Usage */
	if (argc < 2) {
		fprintf(stdout, "Usage: %s filename0 [filename1 filename2 ...]\n", argv[0]);
		return 1;
	}

#if defined(DEBUG) || defined(_DEBUG)
	/* Enables GPAC memory tracking in debug mode only */
	gf_sys_init(GF_TRUE);
	gf_log_set_tool_level(GF_LOG_CONTAINER, GF_LOG_INFO);
	gf_log_set_tool_level(GF_LOG_MEMORY, GF_LOG_INFO);
#endif

	/* First or init segment */
	fprintf(stdout, "Process segment %5d/%5d: %s\n", seg_curr, seg_max, argv[seg_curr+1]);
	e = gf_isom_open_progressive(argv[seg_curr+1], 0, 0, &movie, &missing_bytes);
	if ((e != GF_OK && e != GF_ISOM_INCOMPLETE_FILE) || movie == NULL) {
		fprintf(stdout, "Could not open file %s for reading (%s).\n", argv[seg_curr+1], gf_error_to_string(e));
		return 1;
	}
	process_samples_from_track(movie, track_id, &sample_index);
	seg_curr++;

	/* Process segments */
	while (seg_curr <= seg_max) {
		fprintf(stdout, "Process segment %5d/%5d: %s\n", seg_curr, seg_max, argv[seg_curr+1]);

		/* Open the segment */
		e = gf_isom_open_segment(movie, argv[seg_curr+1], 0, 0, GF_FALSE);
		if (e != GF_OK) {
			fprintf(stdout, "Could not open segment %s for reading (%s).\n", argv[seg_curr+1], gf_error_to_string(e));
			ret = 1;
			goto exit;
		}

		/* Process the segment */
		process_samples_from_track(movie, track_id, &sample_index);

		/* Release the segment */
		gf_isom_release_segment(movie, 1);

		seg_curr++;
	}

exit:
	fprintf(stdout, "Total nb Samples: %d\n", gf_isom_get_sample_count(movie, gf_isom_get_track_by_id(movie, track_id) ) );
	gf_isom_release_segment(movie, 1);
	gf_isom_close(movie);
#if defined(DEBUG) || defined(_DEBUG)
	/* Closes GPAC memory tracking in debug mode only */
	gf_sys_close();
#endif

	return ret;
}
Пример #14
0
GF_EXPORT
GF_Err gf_hinter_track_process(GF_RTPHinter *tkHint)
{
	GF_Err e;
	u32 i, descIndex, duration;
	u64 ts;
	u8 PadBits;
	Double ft;
	GF_ISOSample *samp;

	tkHint->HintSample = tkHint->RTPTime = 0;

	tkHint->TotalSample = gf_isom_get_sample_count(tkHint->file, tkHint->TrackNum);
	ft = tkHint->rtp_p->sl_config.timestampResolution;
	ft /= tkHint->OrigTimeScale;
	
	e = GF_OK;
	for (i=0; i<tkHint->TotalSample; i++) {
		samp = gf_isom_get_sample(tkHint->file, tkHint->TrackNum, i+1, &descIndex);
		if (!samp) return GF_IO_ERR;

		//setup SL
		tkHint->CurrentSample = i + 1;

		/*keep same AU indicator if sync shadow - TODO FIXME: this assumes shadows are placed interleaved with 
		the track content which is the case for GPAC scene carousel generation, but may not always be true*/
		if (samp->IsRAP==2) {
			tkHint->rtp_p->sl_header.AU_sequenceNumber -= 1;
			samp->IsRAP = 1;
		}

		ts = (u64) (ft * (s64) (samp->DTS+samp->CTS_Offset));
		tkHint->rtp_p->sl_header.compositionTimeStamp = ts;

		ts = (u64) (ft * (s64)(samp->DTS));
		tkHint->rtp_p->sl_header.decodingTimeStamp = ts;
		tkHint->rtp_p->sl_header.randomAccessPointFlag = samp->IsRAP;

		tkHint->base_offset_in_sample = 0;
		/*crypted*/
		if (tkHint->rtp_p->slMap.IV_length) {
			GF_ISMASample *s = gf_isom_get_ismacryp_sample(tkHint->file, tkHint->TrackNum, samp, descIndex);
			/*one byte take for selective_enc flag*/
			if (s->flags & GF_ISOM_ISMA_USE_SEL_ENC) tkHint->base_offset_in_sample += 1;
			if (s->flags & GF_ISOM_ISMA_IS_ENCRYPTED) tkHint->base_offset_in_sample += s->IV_length + s->KI_length;
			gf_free(samp->data);
			samp->data = s->data;
			samp->dataLength = s->dataLength;
			gp_rtp_builder_set_cryp_info(tkHint->rtp_p, s->IV, (char*)s->key_indicator, (s->flags & GF_ISOM_ISMA_IS_ENCRYPTED) ? 1 : 0);
			s->data = NULL;
			s->dataLength = 0;
			gf_isom_ismacryp_delete_sample(s);
		}

		if (tkHint->rtp_p->sl_config.usePaddingFlag) {
			gf_isom_get_sample_padding_bits(tkHint->file, tkHint->TrackNum, i+1, &PadBits);
			tkHint->rtp_p->sl_header.paddingBits = PadBits;
		} else {
			tkHint->rtp_p->sl_header.paddingBits = 0;
		}
		
		duration = gf_isom_get_sample_duration(tkHint->file, tkHint->TrackNum, i+1);
		ts = (u32) (ft * (s64) (duration));

		/*unpack nal units*/
		if (tkHint->avc_nalu_size) {
			u32 v, size;
			u32 remain = samp->dataLength;
			char *ptr = samp->data;

			tkHint->rtp_p->sl_header.accessUnitStartFlag = 1;
			tkHint->rtp_p->sl_header.accessUnitEndFlag = 0;
			while (remain) {
				size = 0;
				v = tkHint->avc_nalu_size;
				while (v) {
					size |= (u8) *ptr;
					ptr++;
					remain--;
					v-=1;
					if (v) size<<=8;
				}
				tkHint->base_offset_in_sample = samp->dataLength-remain;
				remain -= size;
				tkHint->rtp_p->sl_header.accessUnitEndFlag = remain ? 0 : 1;
				e = gf_rtp_builder_process(tkHint->rtp_p, ptr, size, (u8) !remain, samp->dataLength, duration, (u8) (descIndex + GF_RTP_TX3G_SIDX_OFFSET) );
				ptr += size;
				tkHint->rtp_p->sl_header.accessUnitStartFlag = 0;
			}
		} else {
			e = gf_rtp_builder_process(tkHint->rtp_p, samp->data, samp->dataLength, 1, samp->dataLength, duration, (u8) (descIndex + GF_RTP_TX3G_SIDX_OFFSET) );
		}
		tkHint->rtp_p->sl_header.packetSequenceNumber += 1;

		//signal some progress
		gf_set_progress("Hinting", tkHint->CurrentSample, tkHint->TotalSample);

		tkHint->rtp_p->sl_header.AU_sequenceNumber += 1;
		gf_isom_sample_del(&samp);

		if (e) return e;
	}

	//flush
	gf_rtp_builder_process(tkHint->rtp_p, NULL, 0, 1, 0, 0, 0);

	gf_isom_end_hint_sample(tkHint->file, tkHint->HintTrack, (u8) tkHint->SampleIsRAP);
	return GF_OK;
}
Пример #15
0
Файл: main.c Проект: Bevara/GPAC
void bifs_to_vid(GF_ISOFile *file, char *szConfigFile, u32 width, u32 height, char *rad_name, u32 dump_type, char *out_dir, Double fps, s32 frameID, s32 dump_time)
{
	GF_User user;
	BIFSVID b2v;
	u16 es_id;
	Bool first_dump, needs_raw;
	u32 i, j, di, count, timescale, frameNum;
	u32 duration, cur_time;
	GF_VideoSurface fb;
	GF_Err e;
	char old_driv[1024];
	const char *test;
	char config_path[GF_MAX_PATH];
	avi_t *avi_out;
	Bool reset_fps;
	GF_ESD *esd;
	char comp[5];
	char *conv_buf;

	memset(&user, 0, sizeof(GF_User));
	if (szConfigFile && strlen(szConfigFile)) {
		user.config = gf_cfg_init(config_path, NULL);
	} else {
		user.config = gf_cfg_init(NULL, NULL);
	}

	if (!user.config) {
		fprintf(stdout, "Error: Configuration File \"%s\" not found in %s\n", GPAC_CFG_FILE, config_path);
		return;
	}
	avi_out = NULL;
	conv_buf = NULL;
	esd = NULL;
	needs_raw = 0;
	test = gf_cfg_get_key(user.config, "General", "ModulesDirectory");
	user.modules = gf_modules_new((const unsigned char *) test, user.config);
	strcpy(old_driv, "raw_out");
	if (!gf_modules_get_count(user.modules)) {
		printf("Error: no modules found\n");
		goto err_exit;
	}

	/*switch driver to raw_driver*/
	test = gf_cfg_get_key(user.config, "Video", "DriverName");
	if (test) strcpy(old_driv, test);

	test = gf_cfg_get_key(user.config, "Compositor", "RendererName");
	/*since we only support RGB24 for MP42AVI force using RAW out with 2D driver*/
	if (test && strstr(test, "2D")) {
		gf_cfg_set_key(user.config, "Video", "DriverName", "Raw Video Output");
		needs_raw = 1;
	}

	needs_raw = 0;
	user.init_flags = GF_TERM_NO_AUDIO | GF_TERM_FORCE_3D;
	b2v.sr = gf_sc_new(&user, 0, NULL);
	gf_sc_set_option(b2v.sr, GF_OPT_VISIBLE, 0);

	b2v.sg = gf_sg_new();
	gf_sg_set_scene_time_callback(b2v.sg, get_scene_time, &b2v);
	gf_sg_set_init_callback(b2v.sg, node_init, &b2v);
	gf_sg_set_modified_callback(b2v.sg, node_modif, &b2v);

	/*load config*/
	gf_sc_set_option(b2v.sr, GF_OPT_RELOAD_CONFIG, 1);

	b2v.bifs = gf_bifs_decoder_new(b2v.sg, 0);

	if (needs_raw) {
		test = gf_cfg_get_key(user.config, "Video", "DriverName");
		if (stricmp(test, "raw_out") && stricmp(test, "Raw Video Output")) {
			printf("couldn't load raw output driver (%s used)\n", test);
			goto err_exit;
		}
	}

	strcpy(config_path, "");
	if (out_dir) {
		strcat(config_path, out_dir);
		if (config_path[strlen(config_path)-1] != '\\') strcat(config_path, "\\");
	}
	strcat(config_path, rad_name);
	strcat(config_path, "_bifs");
	if (!dump_type) {
		strcat(config_path, ".avi");
		avi_out = AVI_open_output_file(config_path);
		comp[0] = comp[1] = comp[2] = comp[3] = comp[4] = 0;
		if (!avi_out) goto err_exit;
	}


	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->dependsOnESID && (esd->decoderConfig->streamType == GF_STREAM_SCENE)) break;
		gf_odf_desc_del((GF_Descriptor *) esd);
		esd = NULL;
	}
	if (!esd) {
		printf("no bifs track found\n");
		goto err_exit;
	}

	b2v.duration = gf_isom_get_media_duration(file, i+1);
	timescale = gf_isom_get_media_timescale(file, i+1);
	es_id = (u16) gf_isom_get_track_id(file, i+1);
	e = gf_bifs_decoder_configure_stream(b2v.bifs, es_id, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, esd->decoderConfig->objectTypeIndication);
	if (e) {
		printf("BIFS init error %s\n", gf_error_to_string(e));
		gf_odf_desc_del((GF_Descriptor *) esd);
		esd = NULL;
		goto err_exit;
	}
	if (dump_time>=0) dump_time = dump_time *1000 / timescale;

	gf_sc_set_scene(b2v.sr, b2v.sg);
	count = gf_isom_get_sample_count(file, i+1);

	reset_fps = 0;
	if (!fps) {
		fps = (Float) (count * timescale);
		fps /= (Double) (s64) b2v.duration;
		printf("Estimated BIFS FrameRate %g\n", fps);
		reset_fps = 1;
	}

	if (!width || !height) {
		gf_sg_get_scene_size_info(b2v.sg, &width, &height);
	}
	/*we work in RGB24, and we must make sure the pitch is %4*/
	if ((width*3)%4) {
		printf("Adjusting width (%d) to have a stride multiple of 4\n", width);
		while ((width*3)%4) width--;
	}

	gf_sc_set_size(b2v.sr, width, height);
	gf_sc_draw_frame(b2v.sr);

	gf_sc_get_screen_buffer(b2v.sr, &fb);
	width = fb.width;
	height = fb.height;
	if (avi_out) {
		AVI_set_video(avi_out, width, height, fps, comp);
		conv_buf = gf_malloc(sizeof(char) * width * height * 3);
	}
	printf("Dumping at BIFS resolution %d x %d\n\n", width, height);
	gf_sc_release_screen_buffer(b2v.sr, &fb);

	cur_time = 0;

	duration = (u32)(timescale / fps);
	if (reset_fps) fps = 0;

	frameNum = 1;
	first_dump = 1;
	for (j=0; j<count; j++) {
		GF_ISOSample *samp = gf_isom_get_sample(file, i+1, j+1, &di);

		b2v.cts = samp->DTS + samp->CTS_Offset;
		/*apply command*/
		gf_bifs_decode_au(b2v.bifs, es_id, samp->data, samp->dataLength, ((Double)(s64)b2v.cts)/1000.0);
		gf_isom_sample_del(&samp);

		if ((frameID>=0) && (j<(u32)frameID)) continue;
		if ((dump_time>=0) && ((u32) dump_time>b2v.cts)) continue;
		/*render frame*/
		gf_sc_draw_frame(b2v.sr);
		/*needed for background2D !!*/
		if (first_dump) {
			gf_sc_draw_frame(b2v.sr);
			first_dump = 0;
		}

		if (fps) {
			if (cur_time > b2v.cts) continue;

			while (1) {
				printf("dumped frame time %f (frame %d - sample %d)\r", ((Float)cur_time)/timescale, frameNum, j+1);
				dump_frame(b2v, conv_buf, config_path, dump_type, avi_out, frameNum);
				frameNum++;
				cur_time += duration;
				if (cur_time > b2v.cts) break;
			}
		} else {
			dump_frame(b2v, conv_buf, config_path, dump_type, avi_out, (frameID>=0) ? frameID : frameNum);
			if (frameID>=0 || dump_time>=0) break;
			frameNum++;
			printf("dumped frame %d / %d\r", j+1, count);
		}

	}
	gf_odf_desc_del((GF_Descriptor *) esd);

	/*destroy everything*/
	gf_bifs_decoder_del(b2v.bifs);
	gf_sg_del(b2v.sg);
	gf_sc_set_scene(b2v.sr, NULL);
	gf_sc_del(b2v.sr);

err_exit:
	if (avi_out) AVI_close(avi_out);
	if (conv_buf) gf_free(conv_buf);
	if (user.modules) gf_modules_del(user.modules);
	if (needs_raw) gf_cfg_set_key(user.config, "Video", "DriverName", old_driv);
	gf_cfg_del(user.config);
}
Пример #16
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;
}
Пример #17
0
static u32 iso_progressive_read_thread(void *param)
{
	ISOProgressiveReader *reader = (ISOProgressiveReader *)param;
	u32 track_number;
	GF_ISOSample *iso_sample;
	u32 samples_processed;
	u32 sample_index;
	u32 sample_count;

	samples_processed = 0;
	sample_count = 0;
	track_number = 0;
	/* samples are numbered starting from 1 */
	sample_index = 1;

	while (reader->do_run == GF_TRUE) {

		/* we can only parse if there is a movie */
		if (reader->movie) {

			/* block the data input until we are done in the parsing */
			gf_mx_p(reader->mutex);

			/* get the track number we want */
			if (track_number == 0) {
				track_number = gf_isom_get_track_by_id(reader->movie, reader->track_id);
			}

			/* only if we have the track number can we try to get the sample data */
			if (track_number != 0) {
				u32 new_sample_count;
				u32 di; /*descriptor index*/

				/* let's see how many samples we have since the last parsed */
				new_sample_count = gf_isom_get_sample_count(reader->movie, track_number);
				if (new_sample_count > sample_count) {
					/* New samples have been added to the file */
					fprintf(stdout, "Found %d new samples (total: %d)\n", new_sample_count - sample_count, new_sample_count);
					if (sample_count == 0) {
						sample_count = new_sample_count;
					}
				}
				if (sample_count == 0) {
					/*let the reader push new data */
					gf_mx_v(reader->mutex);
					//gf_sleep(1000);
				} else {
					/* let's analyze the samples we have parsed so far one by one */
					iso_sample = gf_isom_get_sample(reader->movie, track_number, sample_index, &di);
					if (iso_sample) {
						/* if you want the sample description data, you can call:
						   GF_Descriptor *desc = gf_isom_get_decoder_config(reader->movie, reader->track_handle, di);
						*/

						samples_processed++;
						/*here we dump some sample info: samp->data, samp->dataLength, samp->isRAP, samp->DTS, samp->CTS_Offset */
						fprintf(stdout, "Found sample #%5d (#%5d) of length %8d, RAP: %d, DTS: "LLD", CTS: "LLD"\r", sample_index, samples_processed, iso_sample->dataLength, iso_sample->IsRAP, iso_sample->DTS, iso_sample->DTS+iso_sample->CTS_Offset);
						sample_index++;

						/*release the sample data, once you're done with it*/
						gf_isom_sample_del(&iso_sample);

						/* once we have read all the samples, we can release some data and force a reparse of the input buffer */
						if (sample_index > sample_count) {
							u64 new_buffer_start;
							u64 missing_bytes;

							fprintf(stdout, "\nReleasing unnecessary buffers\n");
							/* release internal structures associated with the samples read so far */
							gf_isom_reset_tables(reader->movie, GF_TRUE);

#if 1
							/* release the associated input data as well */
							gf_isom_reset_data_offset(reader->movie, &new_buffer_start);
							if (new_buffer_start) {
								u32 offset = (u32)new_buffer_start;
								memmove(reader->data, reader->data+offset, reader->data_size-offset);
								reader->valid_data_size -= offset;
							}
							sprintf(reader->data_url, "gmem://%d@%p", reader->valid_data_size, reader->data);
							gf_isom_refresh_fragmented(reader->movie, &missing_bytes, reader->data_url);
#endif

							/* update the sample count and sample index */
							sample_count = new_sample_count - sample_count;
							assert(sample_count == 0);
							sample_index = 1;
						}
					} else {
						GF_Err e = gf_isom_last_error(reader->movie);
						fprintf(stdout, "Could not get sample %s\r", gf_error_to_string(e));
					}
					/* and finally, let the data reader push more data */
					gf_mx_v(reader->mutex);
				}
			}
		} else {
			//gf_sleep(1);
		}
	}
	return 0;
}