Skip to content

Buffer-based streams.#583

Closed
ghost wants to merge 2 commits intouclouvain:masterfrom
UltraLinq:upstream
Closed

Buffer-based streams.#583
ghost wants to merge 2 commits intouclouvain:masterfrom
UltraLinq:upstream

Conversation

@ghost
Copy link
Copy Markdown

@ghost ghost commented Sep 12, 2015

FWIW, we're using this patch to implement buffer-based encoding and decoding to and from JPEG-2000 in our imaging software. As for attributions this is based on work done by Aron Boxer in another fork.

@detonin detonin added this to the OPJv2.2 milestone Sep 18, 2015
* src/lib/openjp2/openjpeg.c (opj_seek_from_buffer): changed signature
  to match opj_stream_seek_fn typedef.

The incorrect signature resulted in a sliced pointer.
@ghost
Copy link
Copy Markdown
Author

ghost commented Sep 22, 2015

Unfortunately, a bug slipped in the pull request. The second commit addresses the bug. The bug only shows up in 32-bit builds, when the size of off_t does not match the size of size_t, so it might have gone unnoticed.

@chafey
Copy link
Copy Markdown
Contributor

chafey commented Sep 13, 2016

Any chance we can get this integrated into master?

@jubalh
Copy link
Copy Markdown

jubalh commented Apr 5, 2019

Curious what is the state of this. Seems noone replied at all?

@MarkusPfundstein
Copy link
Copy Markdown

It would be great to have this in master. Just wrote the same functionality myself and I do think more people will need this.

@ghost
Copy link
Copy Markdown
Author

ghost commented May 8, 2019

Is there anything I might help with?

@kentf
Copy link
Copy Markdown

kentf commented Aug 26, 2019

Hi, I believe I've found two bugs in this pull request.

  1. Memory leak when encoding into memory based buffer.
  2. Error when encoding with 32-bit builds.

PS: I'm not able to create a proper pull request with this fix at the moment.

Memory leak

When encoding, this pull request will resize memory as it needs. But after the encoding is finished, opj_free should be called on the buffer, but opj_free is not available to the consumers. Add this method on the same level as opj_stream_create_buffer_stream.

void 
opj_stream_destroy_buffer_stream(opj_buffer_info_t* buffer)
{
	if (buffer == 00)
		return;

	if (buffer->buf == 00)
		return;

	/* Free buffer */
	opj_free(buffer->buf);

	/* Zero out buffer */
	buffer->buf = 00;
	buffer->cur = 00;
	buffer->len = 0;
}

Usage:

/* Output stream */
opj_buffer_info_t buffer;
buffer.buf = nullptr;
buffer.cur = nullptr;
buffer.len = 0;

stream_wrapper_t stream = opj_stream_create_buffer_stream(&buffer, /* input */false);

/* Compression, encoding, error handling */

opj_stream_destroy_buffer_stream(&buffer);

32-bit encoding error

The user function opj_skip_from_buffer has the wrong signature. It should use OPJ_OFF_T, not OPJ_SIZE_T.

The complete method should be:

static OPJ_OFF_T
opj_skip_from_buffer(OPJ_OFF_T len, opj_buffer_info_t* psrc)
{
	OPJ_OFF_T n = psrc->buf + psrc->len - psrc->cur;

	if (n) {
		if (n > len)
			n = len;

		psrc->cur += len;
	}
	else
		n = (OPJ_OFF_T)-1;

	return n;
}

I hope this helps.

@ghost
Copy link
Copy Markdown
Author

ghost commented Aug 27, 2019

It surely helps. There is a commit in that branch that addresses the off_t argument. I could spend some time creating a different patch and create a pull request but it will be from a different fork since I no longer have access to that repository.

@ghost
Copy link
Copy Markdown
Author

ghost commented Sep 7, 2019

Alright, I think I am going to close this pull request. I am currently putting together a different enhancement and, perhaps, we'll get that in.

@ghost ghost closed this Sep 7, 2019
@ghost ghost mentioned this pull request Sep 9, 2019
@gizmocuz
Copy link
Copy Markdown

gizmocuz commented Oct 7, 2019

@thinkoid , is it possible you could show me(us) how to use this ? How to add data to the buffer from memory ?

@gizmocuz
Copy link
Copy Markdown

gizmocuz commented Oct 9, 2019

@thinkoid , sorry found it, we could use the existing code in the repo to do memory based decoding via

		opj_buffer_info_t my_buffer = { 0 };
		my_buffer.buf = (uint8_t*)pData;
		my_buffer.cur = (uint8_t*)pData;
		my_buffer.len = Len;


		opj_stream_t* pStream = opj_stream_create_buffer_stream(&my_buffer, TRUE);
		if (!pStream)
			return false;

@ghost
Copy link
Copy Markdown
Author

ghost commented Oct 9, 2019

@thinkoid , sorry found it, we could use the existing code in the repo to do memory based decoding ...

That is correct for decompression. For compression you pass in an empty opj_buffer_info_t; the buffer will be initialized and resized as needed by the library. At the end of compression you will be left with the buffer containing the compressed stream data. It is your responsibility to dispose of it. The buffer is allocated with malloc, you free it after you are done.

This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants