GF_Err senc_box_dump(GF_Box *a, FILE * trace)
{
	u32 i, sample_count;
	const char *name;
	GF_BitStream *bs = NULL;
	u32 piff_IV_size = 0;
	Bool use_multikey = GF_FALSE;
	GF_SampleEncryptionBox *ptr = (GF_SampleEncryptionBox *) a;
	if (!a) return GF_BAD_PARAM;

	if (dump_skip_samples)
		return GF_OK;

	if (ptr->internal_4cc == GF_ISOM_BOX_UUID_PSEC)
		name = "PIFFSampleEncryptionBox";
	else
		name = "SampleEncryptionBox";

	gf_isom_box_dump_start(a, name, trace);

	if (ptr->internal_4cc == GF_ISOM_BOX_UUID_PSEC) {
		gf_fprintf(trace, "Version=\"%d\" Flags=\"%d\" ", ptr->version, ptr->flags);
		if (ptr->flags & 1) {
			gf_fprintf(trace, " AlgorithmID=\"%d\" IV_size=\"%d\" KID=\"", ptr->AlgorithmID, ptr->IV_size);
			dump_data(trace, (char *) ptr->KID, 16);
			gf_fprintf(trace, "\"");
			piff_IV_size = ptr->IV_size;
		}
	}

	sample_count = gf_list_count(ptr->samp_aux_info);
	gf_fprintf(trace, "sampleCount=\"%d\">\n", sample_count);
	if (ptr->internal_4cc != GF_ISOM_BOX_UUID_PSEC) {
		//WARNING - PSEC (UUID) IS TYPECASTED TO SENC (FULL BOX) SO WE CANNOT USE USUAL FULL BOX FUNCTIONS
		gf_fprintf(trace, "<FullBoxInfo Version=\"%d\" Flags=\"0x%X\"/>\n", ptr->version, ptr->flags);

		if ((ptr->version==1) && !ptr->piff_type)
			use_multikey = GF_TRUE;
	}


	for (i=0; i<sample_count; i++) {
		u32 nb_keys=0;
		u32 iv_size=0;
		u32 subs_bits=16;
		GF_CENCSampleAuxInfo *sai = (GF_CENCSampleAuxInfo *)gf_list_get(ptr->samp_aux_info, i);
		if (!sai) break;
		if (sai->isNotProtected) continue;

		gf_fprintf(trace, "<SampleEncryptionEntry sampleNumber=\"%d\"", i+1);
		if (sai->key_info) {
			if (!use_multikey) {
				iv_size = sai->key_info[3];
			} else {
				nb_keys = sai->key_info[1];
				nb_keys <<= 8;
				nb_keys |= sai->key_info[2];
				subs_bits = 32;
			}
		}
		//piff
		else {
			iv_size = piff_IV_size ? piff_IV_size : sai->key_info_size;
		}

		if (!bs)
			bs = gf_bs_new(sai->cenc_data, sai->cenc_data_size, GF_BITSTREAM_READ);
		else
			gf_bs_reassign_buffer(bs, sai->cenc_data, sai->cenc_data_size);

		if (!use_multikey) {
			gf_fprintf(trace, " IV_size=\"%u\"", iv_size);
			if (iv_size) {
				gf_fprintf(trace, " IV=\"");
				if (iv_size <= sai->cenc_data_size) {
					dump_data_hex(trace, (char *) sai->cenc_data, iv_size);
				} else {
					gf_fprintf(trace, "CORRUPTED");
				}
				gf_fprintf(trace, "\"");
				gf_bs_skip_bytes(bs, iv_size);
			}
		} else {
			u32 k, nb_ivs = gf_bs_read_u16(bs);
			if (nb_ivs) {
				gf_fprintf(trace, " multiIV=\"[");
			}
			for (k=0; k<nb_ivs; k++) {
				u32 pos;
				u32 idx = gf_bs_read_u16(bs);
				u8 mk_iv_size = key_info_get_iv_size(sai->key_info, sai->key_info_size, idx, NULL, NULL);
				pos = (u32) gf_bs_get_position(bs);
				if (mk_iv_size + pos <= sai->cenc_data_size) {
					gf_fprintf(trace, "%sidx:%d,iv_size:%d,IV:", k ? "," : "", idx, mk_iv_size);
					dump_data_hex(trace, (char *) sai->cenc_data+pos, mk_iv_size);
				} else {
					gf_fprintf(trace, "%sidx:%d,iv_size:%d,IV:CORRUPTED", k ? "," : "", idx, mk_iv_size);
				}
				gf_bs_skip_bytes(bs, mk_iv_size);
			}
			if (nb_ivs) {
				gf_fprintf(trace, "]\"");
			}
		}
		if (use_multikey || ((ptr->flags & 0x2) && (sai->cenc_data_size>iv_size)) ) {
			u32 j, nb_subs;

			nb_subs = gf_bs_read_int(bs, subs_bits);
			gf_fprintf(trace, " SubsampleCount=\"%u\"", nb_subs);
			gf_fprintf(trace, ">\n");

			for (j=0; j<nb_subs; j++) {
				u32 clear, crypt;
				gf_fprintf(trace, "<SubSampleEncryptionEntry");
				if (nb_keys>1) {
					u32 kidx = gf_bs_read_u16(bs);
					gf_fprintf(trace, " MultiKeyIndex=\"%u\"", kidx);
				}
				clear = gf_bs_read_u16(bs);
				crypt = gf_bs_read_u32(bs);
				gf_fprintf(trace, " NumClearBytes=\"%u\" NumEncryptedBytes=\"%u\"/>\n", clear, crypt);
			}
		} else {
			gf_fprintf(trace, ">\n");
		}
		gf_fprintf(trace, "</SampleEncryptionEntry>\n");
	}
	if (bs)
		gf_bs_del(bs);
		
	if (!ptr->size) {
		gf_fprintf(trace, "<SampleEncryptionEntry sampleCount=\"\" IV=\"\" SubsampleCount=\"\">\n");
		gf_fprintf(trace, "<SubSampleEncryptionEntry NumClearBytes=\"\" NumEncryptedBytes=\"\"/>\n");
		gf_fprintf(trace, "</SampleEncryptionEntry>\n");
	}
	gf_isom_box_dump_done(name, a, trace);
	return GF_OK;
}
GF_Err senc_box_dump(GF_Box *a, FILE * trace)
{
	u32 i, sample_count;
	const char *name;
	GF_BitStream *bs = NULL;
	u32 piff_IV_size = 0;
	Bool use_multikey = GF_FALSE;
	GF_SampleEncryptionBox *ptr = (GF_SampleEncryptionBox *) a;
	if (!a) return GF_BAD_PARAM;

	if (dump_skip_samples)
		return GF_OK;

	if (ptr->internal_4cc == GF_ISOM_BOX_UUID_PSEC)
		name = "PIFFSampleEncryptionBox";
	else
		name = "SampleEncryptionBox";

	gf_isom_box_dump_start(a, name, trace);

	if (ptr->internal_4cc == GF_ISOM_BOX_UUID_PSEC) {
		gf_fprintf(trace, "Version=\"%d\" Flags=\"%d\" ", ptr->version, ptr->flags);
		if (ptr->flags & 1) {
			gf_fprintf(trace, " AlgorithmID=\"%d\" IV_size=\"%d\" KID=\"", ptr->AlgorithmID, ptr->IV_size);
			dump_data(trace, (char *) ptr->KID, 16);
			gf_fprintf(trace, "\"");
			piff_IV_size = ptr->IV_size;
		}
	}

	sample_count = gf_list_count(ptr->samp_aux_info);
	gf_fprintf(trace, "sampleCount=\"%d\">\n", sample_count);
	if (ptr->internal_4cc != GF_ISOM_BOX_UUID_PSEC) {
		 
		gf_fprintf(trace, "<FullBoxInfo Version=\"%d\" Flags=\"0x%X\"/>\n", ptr->version, ptr->flags);

		if ((ptr->version==1) && !ptr->piff_type)
			use_multikey = GF_TRUE;
	}


	for (i=0; i<sample_count; i++) {
		u32 nb_keys=0;
		u32 iv_size=0;
		u32 subs_bits=16;
		GF_CENCSampleAuxInfo *sai = (GF_CENCSampleAuxInfo *)gf_list_get(ptr->samp_aux_info, i);
		if (!sai) break;
		if (sai->isNotProtected) continue;

		gf_fprintf(trace, "<SampleEncryptionEntry sampleNumber=\"%d\"", i+1);
		if (sai->key_info) {
			if (!use_multikey) {
				iv_size = sai->key_info[3];
			} else {
				nb_keys = sai->key_info[1];
				nb_keys <<= 8;
				nb_keys |= sai->key_info[2];
				subs_bits = 32;
			}
		}
		 
		else {
			iv_size = piff_IV_size ? piff_IV_size : sai->key_info_size;
		}

		if (!bs)
			bs = gf_bs_new(sai->cenc_data, sai->cenc_data_size, GF_BITSTREAM_READ);
		else
			gf_bs_reassign_buffer(bs, sai->cenc_data, sai->cenc_data_size);

		if (!use_multikey) {
			gf_fprintf(trace, " IV_size=\"%u\"", iv_size);
			if (iv_size) {
				gf_fprintf(trace, " IV=\"");
				if (iv_size <= sai->cenc_data_size) {
					dump_data_hex(trace, (char *) sai->cenc_data, iv_size);
				} else {
					gf_fprintf(trace, "CORRUPTED");
				}
				gf_fprintf(trace, "\"");
				gf_bs_skip_bytes(bs, iv_size);
			}
		} else {
			u32 k, nb_ivs = gf_bs_read_u16(bs);
			if (nb_ivs) {
				gf_fprintf(trace, " multiIV=\"[");
			}
			for (k=0; k<nb_ivs; k++) {
				u32 pos;
				u32 idx = gf_bs_read_u16(bs);
				u8 mk_iv_size = key_info_get_iv_size(sai->key_info, sai->key_info_size, idx, NULL, NULL);
				pos = (u32) gf_bs_get_position(bs);
				if (mk_iv_size + pos <= sai->cenc_data_size) {
					gf_fprintf(trace, "%sidx:%d,iv_size:%d,IV:", k ? "," : "", idx, mk_iv_size);
					dump_data_hex(trace, (char *) sai->cenc_data+pos, mk_iv_size);
				} else {
					gf_fprintf(trace, "%sidx:%d,iv_size:%d,IV:CORRUPTED", k ? "," : "", idx, mk_iv_size);
				}
				gf_bs_skip_bytes(bs, mk_iv_size);
			}
			if (nb_ivs) {
				gf_fprintf(trace, "]\"");
			}
		}
		if (use_multikey || ((ptr->flags & 0x2) && (sai->cenc_data_size>iv_size)) ) {
			u32 j, nb_subs;

			nb_subs = gf_bs_read_int(bs, subs_bits);
			gf_fprintf(trace, " SubsampleCount=\"%u\"", nb_subs);
			gf_fprintf(trace, ">\n");

			for (j=0; j<nb_subs; j++) {
				u32 clear, crypt;
				gf_fprintf(trace, "<SubSampleEncryptionEntry");
				if (nb_keys>1) {
					u32 kidx = gf_bs_read_u16(bs);
					gf_fprintf(trace, " MultiKeyIndex=\"%u\"", kidx);
				}
				clear = gf_bs_read_u16(bs);
				crypt = gf_bs_read_u32(bs);
				gf_fprintf(trace, " NumClearBytes=\"%u\" NumEncryptedBytes=\"%u\"/>\n", clear, crypt);
			}
		} else {
			gf_fprintf(trace, ">\n");
		}
		gf_fprintf(trace, "</SampleEncryptionEntry>\n");
	}
	if (bs)
		gf_bs_del(bs);
		
	if (!ptr->size) {
		gf_fprintf(trace, "<SampleEncryptionEntry sampleCount=\"\" IV=\"\" SubsampleCount=\"\">\n");
		gf_fprintf(trace, "<SubSampleEncryptionEntry NumClearBytes=\"\" NumEncryptedBytes=\"\"/>\n");
		gf_fprintf(trace, "</SampleEncryptionEntry>\n");
	}
	gf_isom_box_dump_done(name, a, trace);
	return GF_OK;
}