GF_Err gf_lz_decompress_payload(u8 *data, u32 data_len, u8 **uncompressed_data, u32 *out_size)
{
	lzma_stream strm = LZMA_STREAM_INIT;
	lzma_ret ret = lzma_stream_decoder(&strm, UINT64_MAX, 0);
	if (ret != LZMA_OK) return GF_IO_ERR;

	Bool owns_buffer=GF_TRUE;
	u32 block_size = 4096;
	u32 done = 0;
	u32 alloc_size = 0;
	u8 block[4096];
	u8 *dst_buffer = NULL;

	if (*uncompressed_data) {
		owns_buffer = GF_FALSE;
		dst_buffer = (u8 *) *uncompressed_data;
		alloc_size = *out_size;
	} else {
		*out_size = 0;
	}

	strm.next_in = (const uint8_t *) data;
	strm.avail_in = data_len;
	strm.next_out = (uint8_t *) block;
	strm.avail_out = block_size;

	while (1) {
		ret = lzma_code(&strm, LZMA_FINISH);

		if ((strm.avail_out == 0) || (ret == LZMA_STREAM_END)) {
			u32 uncomp_size = block_size - strm.avail_out;

			if (done + uncomp_size > alloc_size) {
				alloc_size = done + uncomp_size;
				dst_buffer = gf_realloc(dst_buffer, alloc_size);
				*out_size = alloc_size;
			}
			memcpy(dst_buffer + done, block, uncomp_size);
			done += uncomp_size;

			strm.next_out = (uint8_t *) block;
			strm.avail_out = block_size;
		}
		if (ret == LZMA_STREAM_END) break;
		if (ret != LZMA_OK) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_CORE, ("[LZMA] error decompressing data: %d\n", ret ));
			if (owns_buffer) gf_free(dst_buffer);
			return GF_IO_ERR;
		}
	}

	*uncompressed_data = dst_buffer;
	*out_size = done;
	return GF_OK;
}
GF_Err gf_lz_decompress_payload(u8 *data, u32 data_len, u8 **uncompressed_data, u32 *out_size)
{
	lzma_stream strm = LZMA_STREAM_INIT;
	lzma_ret ret = lzma_stream_decoder(&strm, UINT64_MAX, 0);
	if (ret != LZMA_OK) return GF_IO_ERR;

	Bool owns_buffer=GF_TRUE;
	u32 block_size = 4096;
	u32 done = 0;
	u32 alloc_size = 0;
	u8 block[4096];
	u8 *dst_buffer = NULL;

	if (*uncompressed_data) {
		owns_buffer = GF_FALSE;
		dst_buffer = (u8 *) *uncompressed_data;
		alloc_size = *out_size;
	} else {
		*out_size = 0;
	}

	strm.next_in = (const uint8_t *) data;
	strm.avail_in = data_len;
	strm.next_out = (uint8_t *) block;
	strm.avail_out = block_size;

	while (1) {
		ret = lzma_code(&strm, LZMA_FINISH);

		if ((strm.avail_out == 0) || (ret == LZMA_STREAM_END)) {
			u32 uncomp_size = block_size - strm.avail_out;

			if (done + uncomp_size > alloc_size) {
				alloc_size = done + uncomp_size;
				dst_buffer = gf_realloc(dst_buffer, alloc_size);
				*out_size = alloc_size;
			}
			memcpy(dst_buffer + done, block, uncomp_size);
			done += uncomp_size;

			strm.next_out = (uint8_t *) block;
			strm.avail_out = block_size;
		}
		if (ret == LZMA_STREAM_END) break;
		if (ret != LZMA_OK) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_CORE, ("[LZMA] error decompressing data: %d\n", ret ));
			if (owns_buffer) gf_free(dst_buffer);
			return GF_IO_ERR;
		}
	}

	*uncompressed_data = dst_buffer;
	*out_size = done;
	return GF_OK;
}