Example #1
0
File: main.c Project: ARSekkat/gpac
int main(int argc, char **argv)
{
	/********************/
	/*   declarations   */
	/********************/
	char *input, *output, tmpstr[GF_MAX_PATH];
	GF_ISOFile *isom_file_in;
	GF_MediaImporter import;
	AdobeHDSCtx ctx;
	GF_Err e;
	u32 i;

	/*****************/
	/*   gpac init   */
	/*****************/
	gf_sys_init(GF_MemTrackerNone);
	gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_WARNING);

	/***********************/
	/*   initialisations   */
	/***********************/
	input = NULL;
	output = NULL;
	isom_file_in = NULL;
	memset(&import, 0, sizeof(GF_MediaImporter));
	e = GF_OK;
	memset(&ctx, 0, sizeof(ctx));

	ctx.curr_time = 0;
	ctx.segnum = 1;

	/*********************************************/
	/*   parse arguments and build HDS context   */
	/*********************************************/
	if (GF_OK != parse_args(argc, argv, &input, &output, &ctx.curr_time, &ctx.segnum)) {
		usage(argv[0]);
		goto exit;
	}

	ctx.multirate_manifest = adobe_alloc_multirate_manifest(output);

#if 0 /*'moov' conversion tests*/
	{
		char metamoov64[GF_MAX_PATH];
		u32 metamoov64_len;
		unsigned char metamoov[GF_MAX_PATH];
		u32 metamoov_len=GF_MAX_PATH;
		FILE *f = gf_fopen("metamoov64"/*input*/, "rt");
		gf_fseek(f, 0, SEEK_END);
		metamoov64_len = (u32)gf_ftell(f);
		gf_fseek(f, 0, SEEK_SET);
		fread(metamoov64, metamoov64_len, 1, f);
		metamoov_len = gf_base64_decode(metamoov64, metamoov64_len, metamoov, metamoov_len);
		gf_fclose(f);
		f = gf_fopen("metamoov", "wb");
		fwrite(metamoov, metamoov_len, 1, f);
		gf_fclose(f);
		return 0;
	}
#endif

#if 0 /*'abst'conversion tests*/
	{
		char bootstrap64[GF_MAX_PATH];
		u32 bootstrap64_len;
		unsigned char bootstrap[GF_MAX_PATH];
		u32 bootstrap_len=GF_MAX_PATH;
		GF_AdobeBootstrapInfoBox *abst = (GF_AdobeBootstrapInfoBox *)abst_New();
		GF_BitStream *bs;
#if 1 //64
		FILE *f = gf_fopen("bootstrap64"/*input*/, "rt");
		gf_fseek(f, 0, SEEK_END);
		bootstrap64_len = (u32)gf_ftell(f);
		gf_fseek(f, 0, SEEK_SET);
		fread(bootstrap64, bootstrap64_len, 1, f);
		bootstrap_len = gf_base64_decode(bootstrap64, bootstrap64_len, bootstrap, bootstrap_len);
#else //binary bootstrap
		FILE *f = gf_fopen("bootstrap.bin"/*input*/, "rb");
		gf_fseek(f, 0, SEEK_END);
		bootstrap_len = (u32)gf_ftell(f);
		gf_fseek(f, 0, SEEK_SET);
		fread(bootstrap, bootstrap_len, 1, f);
#endif
		bs = gf_bs_new(bootstrap+8, bootstrap_len-8, GF_BITSTREAM_READ);
		abst->size = bootstrap[2]*256+bootstrap[3];
		assert(abst->size<GF_MAX_PATH);
		abst_Read((GF_Box*)abst, bs);
		gf_bs_del(bs);
		//then rewrite with just one 'afrt'
		memset(bootstrap, 0, bootstrap_len);
		bs = gf_bs_new(bootstrap, bootstrap_len, GF_BITSTREAM_WRITE);
		abst_Write((GF_Box*)abst, bs);
		bootstrap_len = (u32)gf_bs_get_position(bs);
		gf_bs_del(bs);
		gf_fclose(f);
		f = gf_fopen("bootstrap", "wt");
		bootstrap64_len = gf_base64_encode(bootstrap, bootstrap_len, bootstrap64, GF_MAX_PATH);
		fwrite(bootstrap64, bootstrap64_len, 1, f);
		fprintf(f, "\n\n");
		abst_dump((GF_Box*)abst, f);
		gf_fclose(f);
		abst_del((GF_Box*)abst);
		return 0;
	}
#endif

	/*****************/
	/*   main loop   */
	/*****************/
	import.trackID = 0;
	import.in_name = input;
	import.flags = GF_IMPORT_PROBE_ONLY;

	//create output or open when recovering from a saved state
	sprintf(tmpstr, "%s_import.mp4", input);
	isom_file_in = gf_isom_open(tmpstr, GF_ISOM_WRITE_EDIT, NULL);
	if (!isom_file_in) {
		fprintf(stderr, "Error opening output file %s: %s\n", tmpstr, gf_error_to_string(e));
		assert(0);
		goto exit;
	}
	import.dest = isom_file_in;

	//probe input
	e = gf_media_import(&import);
	if (e) {
		fprintf(stderr, "Error while importing input file %s: %s\n", input, gf_error_to_string(e));
		assert(0);
		goto exit;
	}

	//import input data
	import.flags = 0;
	for (i=0; i<import.nb_tracks; i++) {
		import.trackID = import.tk_info[i].track_num;
		e = gf_media_import(&import);
		if (e) {
			fprintf(stderr, "Error while importing track number %u, input file %s: %s\n", import.trackID, input, gf_error_to_string(e));
			assert(0);
			goto exit;
		}
	}

	//Adobe specific stuff
	e = adobize_segment(isom_file_in, &ctx);
	if (e) {
		fprintf(stderr, "Couldn't turn the ISOM fragmented file into an Adobe f4v segment: %s\n", gf_error_to_string(e));
		assert(0);
		goto exit;
	}

	//interleave data and remove imported file
	//FIXME: set multiple fragments:
	sprintf(tmpstr, "%s_HD_100_Seg%u-Frag1", output, ctx.segnum); //FIXME: "HD", "100" and fragnum: pass as arg
	//e = gf_media_fragment_file(isom_file_in, tmpstr, 1.0);
	e = gf_media_fragment_file(isom_file_in, tmpstr, 1.0+gf_isom_get_duration(isom_file_in)/gf_isom_get_timescale(isom_file_in));
	if (e) {
		fprintf(stderr, "Error while fragmenting file to output %s: %s\n", output, gf_error_to_string(e));
		assert(0);
		goto exit;
	}
	gf_isom_delete(isom_file_in);
	isom_file_in = NULL;

	e = adobe_gen_multirate_manifest(ctx.multirate_manifest, ctx.bootstrap, ctx.bootstrap_size);
	if (e) {
		fprintf(stderr, "Couldn't generate Adobe f4m manifest: %s\n", gf_error_to_string(e));
		assert(0);
		goto exit;
	}

exit:
	//delete intermediate mp4 file
	if (isom_file_in)
		gf_isom_delete(isom_file_in);

	if (ctx.multirate_manifest)
		adobe_free_multirate_manifest(ctx.multirate_manifest);

	if (ctx.bootstrap) {
		gf_free(ctx.bootstrap);
		//ctx.bootstrap = NULL;
		//ctx.bootstrap_size = 0;
	}

	gf_sys_close();

	return !e ? 0 : 1;
}
Example #2
0
GF_Err adobize_segment(GF_ISOFile *isom_file, AdobeHDSCtx *ctx)
{
	GF_Err e;
	GF_BitStream *bs;

	GF_AdobeFragRandomAccessBox *afra = (GF_AdobeFragRandomAccessBox*)	afra_New();
	GF_AfraEntry *ae                  = (GF_AfraEntry*)					gf_calloc(1, sizeof(GF_AfraEntry));
	GF_AdobeBootstrapInfoBox *abst    = (GF_AdobeBootstrapInfoBox*)		abst_New();
	GF_AdobeSegmentRunTableBox *asrt  = (GF_AdobeSegmentRunTableBox*)	asrt_New();
	GF_AdobeSegmentRunEntry *asre     = (GF_AdobeSegmentRunEntry*)		gf_calloc(1, sizeof(GF_AdobeSegmentRunEntry));
	GF_AdobeFragmentRunTableBox *afrt = (GF_AdobeFragmentRunTableBox*)	afrt_New();
	GF_AdobeFragmentRunEntry *afre    = (GF_AdobeFragmentRunEntry*)		gf_calloc(1, sizeof(GF_AdobeFragmentRunEntry));

	u64 init_seg_time = ctx->curr_time;
	u32 seg_duration = (u32)gf_isom_get_duration(isom_file);

	//update context
	ctx->curr_time += seg_duration;

	//Adobe specific boxes
	//Random Access
	afra->type = GF_4CC('a', 'f', 'r', 'a');
	afra->version = 0;
	afra->flags = 0;
	afra->long_ids = 1;
	afra->long_offsets = 1;
	afra->global_entries = 0;
	afra->time_scale = gf_isom_get_timescale(isom_file);

	afra->entry_count = 1;
	ae->time = init_seg_time;
	ae->offset = 3999;
	gf_list_add(afra->local_access_entries, ae);

	afra->global_entries = 0;
	afra->global_entry_count = 0;

	e = gf_list_add(isom_file->TopBoxes, afra);
	if (e) {
		fprintf(stderr, "Impossible to write AFRA box: %s\n", gf_error_to_string(e));
		assert(0);
		return e;
	}

	//Bootstrap Info
	abst->type = GF_4CC('a', 'b', 's', 't');
	abst->version = 0;
	abst->flags = 0;
	abst->bootstrapinfo_version = 1;
	abst->profile = 0;
	abst->live = 1;
	abst->update = 0;
	abst->time_scale = gf_isom_get_timescale(isom_file);
	abst->current_media_time = init_seg_time+seg_duration;
	abst->smpte_time_code_offset = 0;

	abst->movie_identifier = NULL;
	abst->drm_data = NULL;
	abst->meta_data = NULL;

	abst->server_entry_count = 0;
	abst->quality_entry_count = 0;

	abst->segment_run_table_count = 1;
	{
		//Segment Run
		asrt->type = GF_4CC('a', 's', 'r', 't');
		asrt->version = 0;
		asrt->flags = 0;
		asrt->segment_run_entry_count = 1;
		{
			asre->first_segment = ctx->segnum;
			asre->fragment_per_segment = 1;
		}
		e = gf_list_add(asrt->segment_run_entry_table, asre);
		if (e) {
			fprintf(stderr, "Impossible to write ASR Entry: %s\n", gf_error_to_string(e));
			assert(0);
			return e;
		}
	}
	e = gf_list_add(abst->segment_run_table_entries, asrt);
	if (e) {
		fprintf(stderr, "Impossible to write ASRT box: %s\n", gf_error_to_string(e));
		assert(0);
		return e;
	}

	abst->fragment_run_table_count = 1;
	{
		//Fragment Run
		afrt->type = GF_4CC('a', 'f', 'r', 't');
		afrt->version = 0;
		afrt->flags = 0;
		afrt->timescale = gf_isom_get_timescale(isom_file);
		afrt->fragment_run_entry_count = 1;
		{
			afre->first_fragment = 1;
			afre->first_fragment_timestamp = 0;
			afre->fragment_duration = seg_duration;
		}
		e = gf_list_add(afrt->fragment_run_entry_table, afre);
		if (e) {
			fprintf(stderr, "Impossible to write AFR Entry: %s\n", gf_error_to_string(e));
			assert(0);
			return e;
		}
	}
	e = gf_list_add(abst->fragment_run_table_entries, afrt);
	if (e) {
		fprintf(stderr, "Impossible to write AFRT box: %s\n", gf_error_to_string(e));
		assert(0);
		return e;
	}

	e = gf_list_add(isom_file->TopBoxes, abst);
	if (e) {
		fprintf(stderr, "Impossible to write ABST box: %s\n", gf_error_to_string(e));
		assert(0);
		return e;
	}

	e = abst_Size((GF_Box*)abst);
	if (e) {
		fprintf(stderr, "Impossible to compute ABST box size: %s\n", gf_error_to_string(e));
		assert(0);
		return e;
	}
	ctx->bootstrap_size = (size_t)abst->size;
	ctx->bootstrap = gf_malloc(ctx->bootstrap_size);
	bs = gf_bs_new(ctx->bootstrap, ctx->bootstrap_size, GF_BITSTREAM_WRITE);
	e = abst_Write((GF_Box*)abst, bs);
	if (e) {
		fprintf(stderr, "Impossible to code the ABST box: %s\n", gf_error_to_string(e));
		assert(0);
		gf_bs_del(bs);
		return e;
	}
	gf_bs_del(bs);

	//set brands as reversed engineered from f4v files
	/*e = gf_isom_reset_alt_brands(isom_file);
	if (e) {
		fprintf(stderr, "Warning: couldn't reset ISOM brands: %s\n", gf_error_to_string(e));
		assert(0);
	}*/
	gf_isom_set_brand_info(isom_file, GF_4CC('f','4','v',' '), 1);
	gf_isom_modify_alternate_brand(isom_file, GF_4CC('i','s','o','m'), 1);
	gf_isom_modify_alternate_brand(isom_file, GF_4CC('m','p','4','2'), 1);
	gf_isom_modify_alternate_brand(isom_file, GF_4CC('m','4','v',' '), 1);

	return GF_OK;
}