Exemplo n.º 1
0
Arquivo: mp4.c Projeto: zoominla/x264
static int open_file( char *psz_filename, hnd_t *p_handle, cli_output_opt_t *opt )
{
    mp4_hnd_t *p_mp4;

    *p_handle = NULL;
    FILE *fh = fopen( psz_filename, "w" );
    if( !fh )
        return -1;
    FAIL_IF_ERR( !x264_is_regular_file( fh ), "mp4", "MP4 output is incompatible with non-regular file `%s'\n", psz_filename )
    fclose( fh );

    if( !(p_mp4 = malloc( sizeof(mp4_hnd_t) )) )
        return -1;

    memset( p_mp4, 0, sizeof(mp4_hnd_t) );
    p_mp4->p_file = gf_isom_open( psz_filename, GF_ISOM_OPEN_WRITE, NULL );

    p_mp4->b_dts_compress = opt->use_dts_compress;

    if( !(p_mp4->p_sample = gf_isom_sample_new()) )
    {
        close_file( p_mp4, 0, 0 );
        return -1;
    }

    gf_isom_set_brand_info( p_mp4->p_file, GF_ISOM_BRAND_AVC1, 0 );

    *p_handle = p_mp4;

    return 0;
}
Exemplo n.º 2
0
//写入AAC信息
bool EasyMP4Writer::WriteAACInfo(unsigned char*info,int len, int nSampleRate, int nChannel, int nBitsPerSample)
{
	p_audiosample=gf_isom_sample_new();
	p_audiosample->data=(char*)malloc(1024*10);

	GF_ESD*esd=	gf_odf_desc_esd_new(0);
	esd->ESID=gf_isom_get_track_id(p_file,m_audiotrackid);
	esd->OCRESID=gf_isom_get_track_id(p_file,m_audiotrackid);
	esd->decoderConfig->streamType=0x05;
	esd->decoderConfig->objectTypeIndication=0x40;//0x40;
	esd->slConfig->timestampResolution=1000;//1000;//时间单元	
	esd->decoderConfig->decoderSpecificInfo=(GF_DefaultDescriptor*)gf_odf_desc_new(GF_ODF_DSI_TAG);

	esd->decoderConfig->decoderSpecificInfo->data=(char*)malloc(len);
	memcpy(esd->decoderConfig->decoderSpecificInfo->data,info,len);
	esd->decoderConfig->decoderSpecificInfo->dataLength=len;
	

	GF_Err gferr=gf_isom_new_mpeg4_description(p_file, m_audiotrackid, esd,  NULL, NULL, &i_audiodescidx);
	if (gferr!=0)
	{
//		TRACE("mpeg4_description:%d\n",gferr);
	}
	gferr=gf_isom_set_audio_info(p_file,m_audiotrackid,i_audiodescidx, nSampleRate,nChannel, nBitsPerSample);//44100 2 16
	if (gferr!=0)
	{
//		TRACE("gf_isom_set_audio:%d\n",gferr);
	}

	free(esd->decoderConfig->decoderSpecificInfo->data);


	return true;
}
Exemplo n.º 3
0
int dc_audio_muxer_init(AudioOutputFile * p_aoutf, AudioData * p_adata,
		AudioMuxerType muxer_type, int frame_per_seg, int frame_per_frag) {

	char name[256];
	sprintf(name, "audio encoder %s", p_adata->psz_name);
	dc_consumer_init(&p_aoutf->acon, AUDIO_CB_SIZE, name);

	p_aoutf->p_sample = gf_isom_sample_new();
	p_aoutf->p_isof = NULL;
	p_aoutf->muxer_type = muxer_type;

	p_aoutf->i_frame_per_seg = frame_per_seg;
	p_aoutf->i_frame_per_frag = frame_per_frag;

	return 0;
}
Exemplo n.º 4
0
int dc_audio_muxer_init(AudioOutputFile *audio_output_file, AudioDataConf *audio_data_conf, AudioMuxerType muxer_type, int frame_per_seg, int frame_per_frag, u32 seg_marker)
{
	char name[GF_MAX_PATH];
	snprintf(name, sizeof(name), "audio encoder %s", audio_data_conf->filename);
	dc_consumer_init(&audio_output_file->consumer, AUDIO_CB_SIZE, name);

#ifndef GPAC_DISABLE_ISOM
	audio_output_file->sample = gf_isom_sample_new();
	audio_output_file->isof = NULL;
#endif

	audio_output_file->muxer_type = muxer_type;
	audio_output_file->frame_per_seg = frame_per_seg;
	audio_output_file->frame_per_frag = frame_per_frag;
	audio_output_file->seg_marker = seg_marker;
	return 0;
}
Exemplo n.º 5
0
//stores the hint sample in the file
//set IsRandomAccessPoint if you want to indicate that this is a random access point 
//in the stream
GF_Err gf_isom_end_hint_sample(GF_ISOFile *the_file, u32 trackNumber, u8 IsRandomAccessPoint)
{
	GF_TrackBox *trak;
	GF_HintSampleEntryBox *entry;
	u32 dataRefIndex;
	GF_Err e;
	GF_BitStream *bs;
	GF_ISOSample *samp;

	trak = gf_isom_get_track_from_file(the_file, trackNumber);
	if (!trak || !IsHintTrack(trak)) return GF_BAD_PARAM;

	e = Media_GetSampleDesc(trak->Media, trak->Media->information->sampleTable->currentEntryIndex, (GF_SampleEntryBox **) &entry, &dataRefIndex);
	if (e) return e;
	if (!entry->hint_sample) return GF_BAD_PARAM;

	//first of all, we need to adjust the offset for data referenced IN THIS hint sample
	//and get some PckSize
	e = AdjustHintInfo(entry, trak->Media->information->sampleTable->SampleSize->sampleCount + 1);
	if (e) return e;	
	
	//ok, let's write the sample
	bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
	e = gf_isom_hint_sample_write(entry->hint_sample, bs);
	if (e) {
		gf_bs_del(bs);
		return e;
	}
	samp = gf_isom_sample_new();
	samp->CTS_Offset = 0;
	samp->IsRAP = IsRandomAccessPoint;
	samp->DTS = entry->hint_sample->TransmissionTime;
	//get the sample
	gf_bs_get_content(bs, &samp->data, &samp->dataLength);
	gf_bs_del(bs);

	//finally add the sample 
	e = gf_isom_add_sample(the_file, trackNumber, trak->Media->information->sampleTable->currentEntryIndex, samp);
	gf_isom_sample_del(&samp);

	//and delete the sample in our entry ...
	gf_isom_hint_sample_del(entry->hint_sample);
	entry->hint_sample = NULL;
	return e;
}
Exemplo n.º 6
0
GF_ISOSample *gf_isom_webvtt_to_sample(void *s)
{
	GF_Err e = GF_OK;
	GF_ISOSample *res;
	GF_BitStream *bs;
	u32 i;
	GF_WebVTTCue *cue;
	GF_WebVTTSample *samp = (GF_WebVTTSample *)s;
	if (!samp) return NULL;

	bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);

	if (gf_list_count(samp->cues)) {
		i=0;
		while ((cue = (GF_WebVTTCue *)gf_list_enum(samp->cues, &i))) {
			e = webvtt_write_cue(bs, cue);
			if (e) break;
		}
		if (e) {
			gf_bs_del(bs);
			return NULL;
		}
	} else {
		GF_Box *cuebox = (GF_Box *)vtte_New();
		e = gf_isom_box_size((GF_Box *)cuebox);
		if (!e) e = gf_isom_box_write((GF_Box *)cuebox, bs);
		gf_isom_box_del((GF_Box *)cuebox);
		if (e) {
			gf_bs_del(bs);
			return NULL;
		}
	}
	res = gf_isom_sample_new();
	if (!res) {
		gf_bs_del(bs);
		return NULL;
	}
	gf_bs_get_content(bs, &res->data, &res->dataLength);
	gf_bs_del(bs);
	res->IsRAP = RAP;
	return res;
}
Exemplo n.º 7
0
GF_ISOSample *gf_isom_text_to_sample(GF_TextSample *samp)
{
	GF_Err e;
	GF_ISOSample *res;
	GF_BitStream *bs;
	u32 i;
	if (!samp) return NULL;

	bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
	gf_bs_write_u16(bs, samp->len);
	if (samp->len) gf_bs_write_data(bs, samp->text, samp->len);

	e = gpp_write_modifier(bs, (GF_Box *)samp->styles);
	if (!e) e = gpp_write_modifier(bs, (GF_Box *)samp->highlight_color);
	if (!e) e = gpp_write_modifier(bs, (GF_Box *)samp->scroll_delay);
	if (!e) e = gpp_write_modifier(bs, (GF_Box *)samp->box);
	if (!e) e = gpp_write_modifier(bs, (GF_Box *)samp->wrap);

	if (!e) {
		GF_Box *a;
		i=0;
		while ((a = (GF_Box*)gf_list_enum(samp->others, &i))) {
			e = gpp_write_modifier(bs, a);
			if (e) break;
		}
	}
	if (e) {
		gf_bs_del(bs);
		return NULL;
	}
	res = gf_isom_sample_new();
	if (!res) {
		gf_bs_del(bs);
		return NULL;
	}
	gf_bs_get_content(bs, &res->data, &res->dataLength);
	gf_bs_del(bs);
	res->IsRAP = 1;
	return res;
}
Exemplo n.º 8
0
static int open_file( char *psz_filename, hnd_t *p_handle, cli_output_opt_t *opt )
{
    mp4_hnd_t *p_mp4;

    *p_handle = NULL;
    FILE *fh = x264_fopen( psz_filename, "w" );
    if( !fh )
        return -1;
    FAIL_IF_ERR( !x264_is_regular_file( fh ), "mp4", "MP4 output is incompatible with non-regular file `%s'\n", psz_filename )
    fclose( fh );

    if( !(p_mp4 = malloc( sizeof(mp4_hnd_t) )) )
        return -1;

    memset( p_mp4, 0, sizeof(mp4_hnd_t) );

#ifdef _WIN32
    /* GPAC doesn't support Unicode filenames. */
    char ansi_filename[MAX_PATH];
    FAIL_IF_ERR( !x264_ansi_filename( psz_filename, ansi_filename, MAX_PATH, 1 ), "mp4", "invalid ansi filename\n" )
    p_mp4->p_file = gf_isom_open( ansi_filename, GF_ISOM_OPEN_WRITE, NULL );
#else
    p_mp4->p_file = gf_isom_open( psz_filename, GF_ISOM_OPEN_WRITE, NULL );
#endif

    p_mp4->b_dts_compress = opt->use_dts_compress;

    if( !(p_mp4->p_sample = gf_isom_sample_new()) )
    {
        close_file( p_mp4, 0, 0 );
        return -1;
    }

    gf_isom_set_brand_info( p_mp4->p_file, GF_ISOM_BRAND_AVC1, 0 );

    *p_handle = p_mp4;

    return 0;
}
Exemplo n.º 9
0
/*
 * Writing the generic sample structure into a sample buffer
 * 2 options:
 * - putting the text or XML in the sample directly
 * - or using a meta box to structure the sample data
*/
GF_ISOSample *gf_isom_generic_subtitle_to_sample(GF_GenericSubtitleSample *samp)
{
	GF_ISOSample *res;
	GF_BitStream *bs;
	if (!samp) return NULL;

	bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
	//gf_bs_write_u16(bs, samp->len);

	if (samp->len) gf_bs_write_data(bs, samp->text, samp->len);
    else     gf_bs_write_data(bs, "", 1);

	res = gf_isom_sample_new();
	if (!res) {
		gf_bs_del(bs);
		return NULL;
	}
	gf_bs_get_content(bs, &res->data, &res->dataLength);
	gf_bs_del(bs);
	res->IsRAP = 1;
	return res;
}
Exemplo n.º 10
0
Arquivo: hinting.c Projeto: erelh/gpac
static GF_ISOSample *gf_isom_get_data_sample(GF_HintSample *hsamp, GF_TrackBox *trak, u32 sample_num)
{
	GF_ISOSample *samp;
	GF_HintDataCache *hdc;
	u32 i, count;
	count = gf_list_count(hsamp->sample_cache);
	for (i=0; i<count; i++) {
		hdc = (GF_HintDataCache *)gf_list_get(hsamp->sample_cache, i);
		if ((hdc->sample_num==sample_num) && (hdc->trak==trak)) return hdc->samp;
	}

	samp = gf_isom_sample_new();
	Media_GetSample(trak->Media, sample_num, &samp, &i, 0, NULL);
	if (!samp) return NULL;
	GF_SAFEALLOC(hdc, GF_HintDataCache);
	hdc->samp = samp;
	hdc->sample_num = sample_num;
	hdc->trak = trak;
	/*we insert all new samples, since they're more likely to be fetched next (except for audio
	interleaving and other multiplex)*/
	gf_list_insert(hsamp->sample_cache, hdc, 0);
	return samp;
}
Exemplo n.º 11
0
//sps,pps第一个字节为0x67或68,
bool EasyMP4Writer::WriteH264SPSandPPS(unsigned char*sps,int spslen,unsigned char*pps,int ppslen,int width,int height)
{	

	p_videosample=gf_isom_sample_new();
	p_videosample->data=(char*)malloc(1024*1024);


	p_config=gf_odf_avc_cfg_new();	
	gf_isom_avc_config_new(p_file,m_videtrackid,p_config,NULL,NULL,&i_videodescidx);
	gf_isom_set_visual_info(p_file,m_videtrackid,i_videodescidx,width,height);

	GF_AVCConfigSlot m_slotsps={0};
	GF_AVCConfigSlot m_slotpps={0};
	
	p_config->configurationVersion = 1;
	p_config->AVCProfileIndication = sps[1];
	p_config->profile_compatibility = sps[2];
	p_config->AVCLevelIndication = sps[3];
	
	m_slotsps.size=spslen;
	m_slotsps.data=(char*)malloc(spslen);
	memcpy(m_slotsps.data,sps,spslen);	
	gf_list_add(p_config->sequenceParameterSets,&m_slotsps);
	
	m_slotpps.size=ppslen;
	m_slotpps.data=(char*)malloc(ppslen);
	memcpy(m_slotpps.data,pps,ppslen);
	gf_list_add(p_config->pictureParameterSets,&m_slotpps);
	
	gf_isom_avc_config_update(p_file,m_videtrackid,1,p_config);

	free(m_slotsps.data);
	free(m_slotpps.data);

	return true;
}
Exemplo n.º 12
0
int dc_video_muxer_init(VideoOutputFile *video_output_file, VideoDataConf *video_data_conf, VideoMuxerType muxer_type, int frame_per_segment, int frame_per_fragment, u32 seg_marker, int gdr, int seg_dur, int frag_dur, int frame_dur, int gop_size, int video_cb_size)
{
	char name[GF_MAX_PATH];
	memset(video_output_file, 0, sizeof(VideoOutputFile));
	snprintf(name, sizeof(name), "video encoder %s", video_data_conf->filename);
	dc_consumer_init(&video_output_file->consumer, video_cb_size, name);

	video_output_file->sample = gf_isom_sample_new();
	video_output_file->isof = NULL;
	video_output_file->muxer_type = muxer_type;

	video_output_file->frame_per_segment = frame_per_segment;
	video_output_file->frame_per_fragment = frame_per_fragment;

	video_output_file->seg_dur = seg_dur;
	video_output_file->frag_dur = frag_dur;

	video_output_file->seg_marker = seg_marker;
	video_output_file->gdr = gdr;
	video_output_file->gop_size = gop_size;
	video_output_file->frame_dur = frame_dur;

	return 0;
}
Exemplo n.º 13
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;
}
Exemplo n.º 14
0
// Update the dependancies when an OD AU is inserted in the file
GF_Err Media_ParseODFrame(GF_MediaBox *mdia, GF_ISOSample *sample, GF_ISOSample **od_samp)
{
	GF_TrackReferenceBox *tref;
	GF_TrackReferenceTypeBox *mpod;
	GF_Err e;
	GF_ODCom *com;
	GF_ODCodec *ODencode;
	GF_ODCodec *ODdecode;
	u32 i, j;
	//the commands we proceed
	GF_ESDUpdate *esdU, *esdU2;
	GF_ESDRemove *esdR, *esdR2;
	GF_ODUpdate *odU, *odU2;

	//the desc they contain
	GF_ObjectDescriptor *od;
	GF_IsomObjectDescriptor *isom_od;
	GF_ESD *esd;
	GF_ES_ID_Ref *ref;
	GF_Descriptor *desc;

	*od_samp = NULL;
	if (!mdia || !sample || !sample->data || !sample->dataLength) return GF_BAD_PARAM;

	//First find the references, and create them if none
	tref = mdia->mediaTrack->References;
	if (!tref) {
		tref = (GF_TrackReferenceBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TREF);
		e = trak_AddBox((GF_Box*)mdia->mediaTrack, (GF_Box *) tref);
		if (e) return e;
	}
	//then find the OD reference, and create it if none
	e = Track_FindRef(mdia->mediaTrack, GF_ISOM_BOX_TYPE_MPOD, &mpod);
	if (e) return e;
	if (!mpod) {
		mpod = (GF_TrackReferenceTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_REFT);
		mpod->reference_type = GF_ISOM_BOX_TYPE_MPOD;
		e = tref_AddBox((GF_Box*)tref, (GF_Box *)mpod);
		if (e) return e;
	}

	//OK, create our codecs
	ODencode = gf_odf_codec_new();
	if (!ODencode) return GF_OUT_OF_MEM;
	ODdecode = gf_odf_codec_new();
	if (!ODdecode) return GF_OUT_OF_MEM;

	e = gf_odf_codec_set_au(ODdecode, sample->data, sample->dataLength);
	if (e) goto err_exit;
	e = gf_odf_codec_decode(ODdecode);
	if (e) goto err_exit;

	while (1) {
		com = gf_odf_codec_get_com(ODdecode);
		if (!com) break;

		//check our commands
		switch (com->tag) {
		//Rewrite OD Update
		case GF_ODF_OD_UPDATE_TAG:
			//duplicate our command
			odU = (GF_ODUpdate *) com;
			odU2 = (GF_ODUpdate *) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG);

			i=0;
			while ((desc = (GF_Descriptor*)gf_list_enum(odU->objectDescriptors, &i))) {
				//both OD and IODs are accepted
				switch (desc->tag) {
				case GF_ODF_OD_TAG:
				case GF_ODF_IOD_TAG:
					break;
				default:
					e = GF_ODF_INVALID_DESCRIPTOR;
					goto err_exit;
				}
				//get the esd
				e = gf_odf_desc_copy(desc, (GF_Descriptor **)&od);
				if (e) goto err_exit;
				if (desc->tag == GF_ODF_OD_TAG) {
					isom_od = (GF_IsomObjectDescriptor *) gf_malloc(sizeof(GF_IsomObjectDescriptor));
					isom_od->tag = GF_ODF_ISOM_OD_TAG;
				} else {
					isom_od = (GF_IsomObjectDescriptor *) gf_malloc(sizeof(GF_IsomInitialObjectDescriptor));
					isom_od->tag = GF_ODF_ISOM_IOD_TAG;
					//copy PL
					((GF_IsomInitialObjectDescriptor *)isom_od)->inlineProfileFlag = ((GF_InitialObjectDescriptor *)od)->inlineProfileFlag;
					((GF_IsomInitialObjectDescriptor *)isom_od)->graphics_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->graphics_profileAndLevel;
					((GF_IsomInitialObjectDescriptor *)isom_od)->audio_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->audio_profileAndLevel;
					((GF_IsomInitialObjectDescriptor *)isom_od)->OD_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->OD_profileAndLevel;
					((GF_IsomInitialObjectDescriptor *)isom_od)->scene_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->scene_profileAndLevel;
					((GF_IsomInitialObjectDescriptor *)isom_od)->visual_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->visual_profileAndLevel;
					((GF_IsomInitialObjectDescriptor *)isom_od)->IPMPToolList = ((GF_InitialObjectDescriptor *)od)->IPMPToolList;
					((GF_InitialObjectDescriptor *)od)->IPMPToolList = NULL;
				}
				//in OD stream only ref desc are accepted
				isom_od->ES_ID_RefDescriptors = gf_list_new();
				isom_od->ES_ID_IncDescriptors = NULL;
	
				//TO DO: check that a given sampleDescription exists
				isom_od->extensionDescriptors = od->extensionDescriptors;
				od->extensionDescriptors = NULL;
				isom_od->IPMP_Descriptors = od->IPMP_Descriptors;
				od->IPMP_Descriptors = NULL;
				isom_od->OCIDescriptors = od->OCIDescriptors;
				od->OCIDescriptors = NULL;
				isom_od->URLString = od->URLString;
				od->URLString = NULL;
				isom_od->objectDescriptorID = od->objectDescriptorID;

				j=0;
				while ((esd = (GF_ESD*)gf_list_enum(od->ESDescriptors, &j))) {
					ref = (GF_ES_ID_Ref *) gf_odf_desc_new(GF_ODF_ESD_REF_TAG);
					//1 to 1 mapping trackID and ESID. Add this track to MPOD
					//if track does not exist, this will be remove while reading the OD stream
					e = reftype_AddRefTrack(mpod, esd->ESID, &ref->trackRef);
					e = gf_odf_desc_add_desc((GF_Descriptor *)isom_od, (GF_Descriptor *)ref);
					if (e) goto err_exit;
				}
				//delete our desc
				gf_odf_desc_del((GF_Descriptor *)od);
				//and add the new one to our command
				gf_list_add(odU2->objectDescriptors, isom_od);
			}
			//delete the command
			gf_odf_com_del((GF_ODCom **)&odU);
			//and add the new one to the codec
			gf_odf_codec_add_com(ODencode, (GF_ODCom *)odU2);
			break;

		//Rewrite ESD Update
		case GF_ODF_ESD_UPDATE_TAG:
			esdU = (GF_ESDUpdate *) com;
			esdU2 = (GF_ESDUpdate *) gf_odf_com_new(GF_ODF_ESD_UPDATE_TAG);
			esdU2->ODID = esdU->ODID;
			i=0;
			while ((esd = (GF_ESD*)gf_list_enum(esdU->ESDescriptors, &i))) {
				ref = (GF_ES_ID_Ref *) gf_odf_desc_new(GF_ODF_ESD_REF_TAG);
				//1 to 1 mapping trackID and ESID
				e = reftype_AddRefTrack(mpod, esd->ESID, &ref->trackRef);
				e = gf_list_add(esdU2->ESDescriptors, ref);
				if (e) goto err_exit;
			}
			gf_odf_com_del((GF_ODCom **)&esdU);
			gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdU2);
			break;

		//Brand new case: the ESRemove has to be rewritten too according to the specs...
		case GF_ODF_ESD_REMOVE_TAG:
			esdR = (GF_ESDRemove *) com;
			esdR2 = (GF_ESDRemove *) gf_odf_com_new(GF_ODF_ESD_REMOVE_TAG);
			//change the tag for the file format
			esdR2->tag = GF_ODF_ESD_REMOVE_REF_TAG;
			esdR2->ODID = esdR->ODID;
			esdR2->NbESDs = esdR->NbESDs;
			if (esdR->NbESDs) {
				//alloc our stuff
				esdR2->ES_ID = (unsigned short*)gf_malloc(sizeof(u32) * esdR->NbESDs);
				if (!esdR2->ES_ID) {
					e = GF_OUT_OF_MEM;
					goto err_exit;
				}
				for (i = 0; i < esdR->NbESDs; i++) {
					//1 to 1 mapping trackID and ESID
					e = reftype_AddRefTrack(mpod, esdR->ES_ID[i], &esdR2->ES_ID[i]);
					if (e) goto err_exit;
				}
			}
			gf_odf_com_del(&com);
			gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdR2);
			break;

		//Add the command as is
		default:
			e = gf_odf_codec_add_com(ODencode, com);
			if (e) goto err_exit;
		}
	}

	//encode our new AU
	e = gf_odf_codec_encode(ODencode, 1);
	if (e) goto err_exit;

	//and set the buffer in the sample
	*od_samp = gf_isom_sample_new();
	(*od_samp)->CTS_Offset = sample->CTS_Offset;
	(*od_samp)->DTS = sample->DTS;
	(*od_samp)->IsRAP = sample->IsRAP;
	e = gf_odf_codec_get_au(ODencode, & (*od_samp)->data, & (*od_samp)->dataLength);
	if (e) {
		gf_isom_sample_del(od_samp);
		*od_samp = NULL;
	}

err_exit:

	gf_odf_codec_del(ODencode);
	gf_odf_codec_del(ODdecode);
	return e;
}
Exemplo n.º 15
0
Arquivo: main.c Projeto: erelh/gpac
int main(int argc, char **argv)
{
	GF_ISOFile *movie;
	GF_ESD *esd;
	GF_Err e;
	Double gb_size = 5.0;
	u8 store_mode;
	u32 track, di, i, nb_samp;
	GF_ISOSample *samp;

	store_mode = GF_ISOM_OPEN_WRITE;
	for (i=1; i<argc; i++) {
		if (!strcmp(argv[i], "-flat")) store_mode = GF_ISOM_OPEN_WRITE;
		else if (!strcmp(argv[i], "-inter")) store_mode = GF_ISOM_WRITE_EDIT;
		else if (!strcmp(argv[i], "-size") && (i+1<argc)) {
			gb_size = atof(argv[i+1]);
			i++;
		}
		else if (!strcmp(argv[i], "-h")) {
			PrintUsage();
			return 0;
		}
	}

	nb_samp = (u32) (gb_size*1024);
	fprintf(stdout, "Creating test file %s - %g GBytes - %d samples - %s mode\n", TEST_FILE_NAME, gb_size, nb_samp, (store_mode == GF_ISOM_OPEN_WRITE) ? "Flat" : "Interleaved");

	movie = gf_isom_open(TEST_FILE_NAME, store_mode, NULL);
	if (!movie) {
		fprintf(stdout, "Error creating file: %s\n", gf_error_to_string(gf_isom_last_error(NULL)));
		return 1;
	}

	track = gf_isom_new_track(movie, 1, GF_ISOM_MEDIA_VISUAL, 25);
	esd = gf_odf_desc_esd_new(2);
	esd->decoderConfig->streamType = 4;
	gf_isom_new_mpeg4_description(movie, track, esd, NULL, NULL, &di);

	samp = gf_isom_sample_new();
	samp->dataLength = 1024*1024;
	samp->data = gf_malloc(sizeof(char)*samp->dataLength);
  memset(samp->data, 0, sizeof(char)*samp->dataLength);

	for (i=0; i<nb_samp; i++) {
		if (samp->DTS % 25) samp->IsRAP = 0;
		else samp->IsRAP = 1;
		e = gf_isom_add_sample(movie, track, di, samp);
		samp->DTS += 1;

		fprintf(stdout, "Writing sample %d / %d \r", i+1, nb_samp);
		if (e) break;
	}
	gf_isom_sample_del(&samp);

	if (e) {
		fprintf(stdout, "\nError writing sample %d\n", i);
		gf_isom_delete(movie);
		return 1;
	}

	fprintf(stdout, "\nDone writing samples\n");
	e = gf_isom_close(movie);
	if (e) {
		fprintf(stdout, "Error writing file\n");
		return 1;
	}
	return 0;
}