Example #1
0
static int close_file( hnd_t handle, int64_t largest_pts, int64_t second_largest_pts )
{
    mp4_hnd_t *p_mp4 = handle;

    if( !p_mp4 )
        return 0;

    if( p_mp4->p_config )
        gf_odf_avc_cfg_del( p_mp4->p_config );

    if( p_mp4->p_sample )
    {
        if( p_mp4->p_sample->data )
            free( p_mp4->p_sample->data );

        p_mp4->p_sample->dataLength = 0;
        gf_isom_sample_del( &p_mp4->p_sample );
    }

    if( p_mp4->p_file )
    {
        if( p_mp4->i_track )
        {
            /* The mdhd duration is defined as CTS[final] - CTS[0] + duration of last frame.
             * The mdhd duration (in seconds) should be able to be longer than the tkhd duration since the track is managed by edts.
             * So, if mdhd duration is equal to the last DTS or less, we give the last composition time delta to the last sample duration.
             * And then, the mdhd duration is updated, but it time-wise doesn't give the actual duration.
             * The tkhd duration is the actual track duration. */
            uint64_t mdhd_duration = (2 * largest_pts - second_largest_pts) * p_mp4->i_time_inc;
            if( mdhd_duration != gf_isom_get_media_duration( p_mp4->p_file, p_mp4->i_track ) )
            {
                uint64_t last_dts = gf_isom_get_sample_dts( p_mp4->p_file, p_mp4->i_track, p_mp4->i_numframe );
                uint32_t last_duration = (uint32_t)( mdhd_duration > last_dts ? mdhd_duration - last_dts : (largest_pts - second_largest_pts) * p_mp4->i_time_inc );
                gf_isom_set_last_sample_duration( p_mp4->p_file, p_mp4->i_track, last_duration );
            }

            /* Write an Edit Box if the first CTS offset is positive.
             * A media_time is given by not the mvhd timescale but rather the mdhd timescale.
             * The reason is that an Edit Box maps the presentation time-line to the media time-line.
             * Any demuxers should follow the Edit Box if it exists. */
            GF_ISOSample *sample = gf_isom_get_sample_info( p_mp4->p_file, p_mp4->i_track, 1, NULL, NULL );
            if( sample && sample->CTS_Offset > 0 )
            {
                uint32_t mvhd_timescale = gf_isom_get_timescale( p_mp4->p_file );
                uint64_t tkhd_duration = (uint64_t)( mdhd_duration * ( (double)mvhd_timescale / p_mp4->i_time_res ) );
                gf_isom_append_edit_segment( p_mp4->p_file, p_mp4->i_track, tkhd_duration, sample->CTS_Offset, GF_ISOM_EDIT_NORMAL );
            }
            gf_isom_sample_del( &sample );

            recompute_bitrate_mp4( p_mp4->p_file, p_mp4->i_track );
        }
        gf_isom_set_pl_indication( p_mp4->p_file, GF_ISOM_PL_VISUAL, 0x15 );
        gf_isom_set_storage_mode( p_mp4->p_file, GF_ISOM_STORE_FLAT );
        gf_isom_close( p_mp4->p_file );
    }

    free( p_mp4 );

    return 0;
}
Example #2
0
int dc_gpac_audio_moov_create(AudioOutputFile *audio_output_file, char *filename)
{
	GF_Err ret;
	u32 di, track;
	u8 bpsample;
	GF_ESD *esd;
#ifndef GPAC_DISABLE_AV_PARSERS
	GF_M4ADecSpecInfo acfg;
#endif
	AVCodecContext *audio_codec_ctx = audio_output_file->codec_ctx;

	audio_output_file->isof = gf_isom_open(filename, GF_ISOM_OPEN_WRITE, NULL);
	if (!audio_output_file->isof) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Cannot open iso file %s\n", filename));
		return -1;
	}

	esd = gf_odf_desc_esd_new(2);
	if (!esd) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Cannot create GF_ESD\n"));
		return -1;
	}

	esd->decoderConfig = (GF_DecoderConfig *) gf_odf_desc_new(GF_ODF_DCD_TAG);
	esd->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG);
	esd->decoderConfig->streamType = GF_STREAM_AUDIO;
	if (!strcmp(audio_output_file->codec_ctx->codec->name, "aac")) { //TODO: find an automatic table
		esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_AAC_MPEG4;
		esd->decoderConfig->bufferSizeDB = 20;
		esd->slConfig->timestampResolution = audio_codec_ctx->sample_rate;
		esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG);
		esd->ESID = 1;

#ifndef GPAC_DISABLE_AV_PARSERS
		memset(&acfg, 0, sizeof(GF_M4ADecSpecInfo));
		acfg.base_object_type = GF_M4A_AAC_LC;
		acfg.base_sr = audio_codec_ctx->sample_rate;
		acfg.nb_chan = audio_codec_ctx->channels;
		acfg.sbr_object_type = 0;
		acfg.audioPL = gf_m4a_get_profile(&acfg);

		ret = gf_m4a_write_config(&acfg, &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength);
		assert(ret == GF_OK);
#endif
	} else {
		if (strcmp(audio_output_file->codec_ctx->codec->name, "mp2")) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("Unlisted codec, setting GPAC_OTI_AUDIO_MPEG1 descriptor.\n"));
		}
		esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_MPEG1;
		esd->decoderConfig->bufferSizeDB = 20;
		esd->slConfig->timestampResolution = audio_codec_ctx->sample_rate;
		esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG);
		esd->ESID = 1;

#ifndef GPAC_DISABLE_AV_PARSERS
		memset(&acfg, 0, sizeof(GF_M4ADecSpecInfo));
		acfg.base_object_type = GF_M4A_LAYER2;
		acfg.base_sr = audio_codec_ctx->sample_rate;
		acfg.nb_chan = audio_codec_ctx->channels;
		acfg.sbr_object_type = 0;
		acfg.audioPL = gf_m4a_get_profile(&acfg);

		ret = gf_m4a_write_config(&acfg, &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength);
		assert(ret == GF_OK);
#endif
	}

	//gf_isom_store_movie_config(video_output_file->isof, 0);
	track = gf_isom_new_track(audio_output_file->isof, esd->ESID, GF_ISOM_MEDIA_AUDIO, audio_codec_ctx->sample_rate);
	GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("TimeScale: %d \n", audio_codec_ctx->time_base.den));
	if (!track) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Cannot create new track\n"));
		return -1;
	}

	ret = gf_isom_set_track_enabled(audio_output_file->isof, track, 1);
	if (ret != GF_OK) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("%s: gf_isom_set_track_enabled\n", gf_error_to_string(ret)));
		return -1;
	}

//	if (!esd->ESID) esd->ESID = gf_isom_get_track_id(audio_output_file->isof, track);

	ret = gf_isom_new_mpeg4_description(audio_output_file->isof, track, esd, NULL, NULL, &di);
	if (ret != GF_OK) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("%s: gf_isom_new_mpeg4_description\n", gf_error_to_string(ret)));
		return -1;
	}

	gf_odf_desc_del((GF_Descriptor *) esd);
	esd = NULL;

	bpsample = av_get_bytes_per_sample(audio_output_file->codec_ctx->sample_fmt) * 8;

	ret = gf_isom_set_audio_info(audio_output_file->isof, track, di, audio_codec_ctx->sample_rate, audio_output_file->codec_ctx->channels, bpsample);
	if (ret != GF_OK) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("%s: gf_isom_set_audio_info\n", gf_error_to_string(ret)));
		return -1;
	}

#ifndef GPAC_DISABLE_AV_PARSERS
	ret = gf_isom_set_pl_indication(audio_output_file->isof, GF_ISOM_PL_AUDIO, acfg.audioPL);
	if (ret != GF_OK) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("%s: gf_isom_set_pl_indication\n", gf_error_to_string(ret)));
		return -1;
	}
#endif

	GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("time scale: %d  sample dur: %d \n", audio_codec_ctx->time_base.den, audio_output_file->codec_ctx->frame_size));

	ret = gf_isom_setup_track_fragment(audio_output_file->isof, track, 1, audio_output_file->codec_ctx->frame_size, 0, 0, 0, 0);
	if (ret != GF_OK) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("%s: gf_isom_setup_track_fragment\n", gf_error_to_string(ret)));
		return -1;
	}

	//gf_isom_add_track_to_root_od(video_output_file->isof,1);

	ret = gf_isom_finalize_for_fragment(audio_output_file->isof, 1);
	if (ret != GF_OK) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("%s: gf_isom_finalize_for_fragment\n", gf_error_to_string(ret)));
		return -1;
	}

	ret = gf_media_get_rfc_6381_codec_name(audio_output_file->isof, track, audio_output_file->audio_data_conf->codec6381, GF_FALSE, GF_FALSE);
	if (ret != GF_OK) return -1;
	return 0;
}
Example #3
0
int dc_gpac_audio_moov_create(AudioOutputFile * p_aoutf, char * psz_name) {

	GF_Err ret;

	AVCodecContext * p_audio_codec_ctx = p_aoutf->p_codec_ctx;
	u32 di;
	u32 track;
	GF_M4ADecSpecInfo acfg;

	p_aoutf->p_isof = gf_isom_open(psz_name,
			GF_ISOM_OPEN_WRITE, NULL);

	if (!p_aoutf->p_isof) {
		fprintf(stderr, "Cannot open iso file %s\n",
				psz_name);
		return -1;
	}

	memset(&acfg, 0, sizeof(GF_M4ADecSpecInfo));
	acfg.base_object_type = GF_M4A_AAC_LC;
	acfg.base_sr = p_audio_codec_ctx->sample_rate;
	acfg.nb_chan = p_audio_codec_ctx->channels;
	acfg.sbr_object_type = 0;

	acfg.audioPL = gf_m4a_get_profile(&acfg);

	GF_ESD * p_esd = gf_odf_desc_esd_new(2);

	if (!p_esd) {
		fprintf(stderr, "Cannot create GF_ESD\n");
		return -1;
	}

	p_esd->decoderConfig = (GF_DecoderConfig *) gf_odf_desc_new(GF_ODF_DCD_TAG);
	p_esd->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG);
	p_esd->decoderConfig->streamType = GF_STREAM_AUDIO;
	p_esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_AAC_MPEG4;
	p_esd->decoderConfig->bufferSizeDB = 20;
	p_esd->slConfig->timestampResolution = p_audio_codec_ctx->sample_rate;
	p_esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG);
	p_esd->ESID = 1;

	ret = gf_m4a_write_config(&acfg, &p_esd->decoderConfig->decoderSpecificInfo->data, &p_esd->decoderConfig->decoderSpecificInfo->dataLength);

	//gf_isom_store_movie_config(p_voutf->p_isof, 0);
	track = gf_isom_new_track(p_aoutf->p_isof, p_esd->ESID,
			GF_ISOM_MEDIA_AUDIO, p_audio_codec_ctx->sample_rate);

	//printf("TimeScale: %d \n", p_video_codec_ctx->time_base.den);
	if (!track) {
		fprintf(stderr, "Cannot create new track\n");
		return -1;
	}

	ret = gf_isom_set_track_enabled(p_aoutf->p_isof, track, 1);
	if (ret != GF_OK) {
		fprintf(stderr, "%s: gf_isom_set_track_enabled\n",
				gf_error_to_string(ret));
		return -1;
	}

//	if (!p_esd->ESID) p_esd->ESID = gf_isom_get_track_id(p_aoutf->p_isof, track);

	ret = gf_isom_new_mpeg4_description(p_aoutf->p_isof, track, p_esd, NULL,
			NULL, &di);
	if (ret != GF_OK) {
		fprintf(stderr, "%s: gf_isom_new_mpeg4_description\n",
				gf_error_to_string(ret));
		return -1;
	}

	gf_odf_desc_del((GF_Descriptor *) p_esd);
	p_esd = NULL;

	u8 bpsample = av_get_bytes_per_sample(p_aoutf->p_codec_ctx->sample_fmt) * 8;

	ret = gf_isom_set_audio_info(p_aoutf->p_isof, track, di,
			p_audio_codec_ctx->sample_rate, p_aoutf->p_codec_ctx->channels,
			bpsample);

	if (ret != GF_OK) {
		fprintf(stderr, "%s: gf_isom_set_audio_info\n",
				gf_error_to_string(ret));
		return -1;
	}

	ret = gf_isom_set_pl_indication(p_aoutf->p_isof, GF_ISOM_PL_AUDIO, acfg.audioPL);

	if (ret != GF_OK) {
		fprintf(stderr, "%s: gf_isom_set_pl_indication\n",
				gf_error_to_string(ret));
		return -1;
	}

	//printf("time scale: %d  sample dur: %d \n",
	//		p_video_codec_ctx->time_base.den, p_aoutf->p_codec_ctx->frame_size);

	ret = gf_isom_setup_track_fragment(p_aoutf->p_isof, track, 1,
			p_aoutf->p_codec_ctx->frame_size, 0, 0, 0, 0);
	if (ret != GF_OK) {
		fprintf(stderr, "%s: gf_isom_setup_track_fragment\n",
				gf_error_to_string(ret));
		return -1;
	}

	//gf_isom_add_track_to_root_od(p_voutf->p_isof,1);

	ret = gf_isom_finalize_for_fragment(p_aoutf->p_isof, 1);
	if (ret != GF_OK) {
		fprintf(stderr, "%s: gf_isom_finalize_for_fragment\n",
				gf_error_to_string(ret));
		return -1;
	}

	return 0;
}