GF_Err gf_seng_encode_from_commands(GF_SceneEngine *seng, u16 ESID, Bool disable_aggregation, u32 time, GF_List *commands, gf_seng_callback callback)
{
	GF_Err e;
	u32	size;
	char *data;
	GF_StreamContext *sc;
	u32	i, nb_streams;
	GF_AUContext *new_au;

	if (!callback) return GF_BAD_PARAM;
	if (!commands || !gf_list_count(commands)) return GF_BAD_PARAM;

	e = GF_OK;

	/* if the ESID is not provided we try to use the first scene stream */
	sc = NULL;
	nb_streams = gf_list_count(seng->ctx->streams);
	for (i=0; i<nb_streams; i++) {
		GF_StreamContext *tmp_sc = gf_list_get(seng->ctx->streams, i);
		if (tmp_sc->streamType != GF_STREAM_SCENE) continue;
		sc = tmp_sc;
		if (!ESID) break;
		else if (sc->ESID == ESID) break;
	}
	if (!sc) return GF_BAD_PARAM;
	/* We need to create an empty AU for the parser to correctly parse a LASeR Command without SceneUnit */
	new_au = gf_seng_create_new_au(sc, time);

	if (disable_aggregation) new_au->flags = GF_SM_AU_NOT_AGGREGATED;



	/* Removing the commands from the input list to avoid destruction
	   and setting the RAP flag */
	while (gf_list_count(commands)) {
		GF_Command *com = gf_list_get(commands, 0);
		gf_list_rem(commands, 0);
		switch (com->tag) {
#ifndef GPAC_DISABLE_VRML
		case GF_SG_SCENE_REPLACE:
			new_au->flags |= GF_SM_AU_RAP;
			break;
#endif
		case GF_SG_LSR_NEW_SCENE:
			new_au->flags |= GF_SM_AU_RAP;
			break;
		}
		gf_list_add(new_au->commands, com);
	}

	data = NULL;
	size = 0;

	switch(sc->codec_id) {
#ifndef GPAC_DISABLE_BIFS_ENC
	case GF_CODECID_BIFS:
	case GF_CODECID_BIFS_V2:
		e = gf_bifs_encode_au(seng->bifsenc, ESID, new_au->commands, &data, &size);
		break;
#endif

#ifndef GPAC_DISABLE_LASER
	case GF_CODECID_LASER:
		e = gf_laser_encode_au(seng->lsrenc, ESID, new_au->commands, 0, &data, &size);
		break;
#endif
	case GF_CODECID_DIMS:
		e = gf_seng_encode_dims_au(seng, ESID, new_au->commands, &data, &size, GF_TRUE);
		break;
	default:
		GF_LOG(GF_LOG_ERROR, GF_LOG_SCENE, ("Cannot encode commands for Scene OTI %x\n", sc->codec_id));
		break;
	}
	callback(seng->calling_object, ESID, data, size, 0);
	gf_free(data);
	return e;
}
GF_Err gf_seng_encode_from_commands(GF_SceneEngine *seng, u16 ESID, Bool disable_aggregation, u32 time, GF_List *commands, gf_seng_callback callback)
{
	GF_Err e;
	u32	size;
	char *data;
	GF_StreamContext *sc;
	u32	i, nb_streams;
	GF_AUContext *new_au;

	if (!callback) return GF_BAD_PARAM;
	if (!commands || !gf_list_count(commands)) return GF_BAD_PARAM;

	e = GF_OK;

	 
	sc = NULL;
	nb_streams = gf_list_count(seng->ctx->streams);
	for (i=0; i<nb_streams; i++) {
		GF_StreamContext *tmp_sc = gf_list_get(seng->ctx->streams, i);
		if (tmp_sc->streamType != GF_STREAM_SCENE) continue;
		sc = tmp_sc;
		if (!ESID) break;
		else if (sc->ESID == ESID) break;
	}
	if (!sc) return GF_BAD_PARAM;
	 
	new_au = gf_seng_create_new_au(sc, time);

	if (disable_aggregation) new_au->flags = GF_SM_AU_NOT_AGGREGATED;



	 
	while (gf_list_count(commands)) {
		GF_Command *com = gf_list_get(commands, 0);
		gf_list_rem(commands, 0);
		switch (com->tag) {
#ifndef GPAC_DISABLE_VRML
		case GF_SG_SCENE_REPLACE:
			new_au->flags |= GF_SM_AU_RAP;
			break;
#endif
		case GF_SG_LSR_NEW_SCENE:
			new_au->flags |= GF_SM_AU_RAP;
			break;
		}
		gf_list_add(new_au->commands, com);
	}

	data = NULL;
	size = 0;

	switch(sc->codec_id) {
#ifndef GPAC_DISABLE_BIFS_ENC
	case GF_CODECID_BIFS:
	case GF_CODECID_BIFS_V2:
		e = gf_bifs_encode_au(seng->bifsenc, ESID, new_au->commands, &data, &size);
		break;
#endif

#ifndef GPAC_DISABLE_LASER
	case GF_CODECID_LASER:
		e = gf_laser_encode_au(seng->lsrenc, ESID, new_au->commands, 0, &data, &size);
		break;
#endif
	case GF_CODECID_DIMS:
		e = gf_seng_encode_dims_au(seng, ESID, new_au->commands, &data, &size, GF_TRUE);
		break;
	default:
		GF_LOG(GF_LOG_ERROR, GF_LOG_SCENE, ("Cannot encode commands for Scene OTI %x\n", sc->codec_id));
		break;
	}
	callback(seng->calling_object, ESID, data, size, 0);
	gf_free(data);
	return e;
}