Question

I am receiving a stream from android client which is compressed using standard zlib (linked against -lz). The following way when trying to inflate it, i get Z_BUF_ERROR error

if(!rawData)
    rawData= (char *)malloc(480 * 800 * 8);
int bufferLength = 128 * 1024;
char *tmpbuffer = malloc(bufferLength);
zUnzip.next_in = (Bytef *)inputStream;
zUnzip.avail_in = size;
zUnzip.next_out = (Bytef *)tmpbuffer; //output location of uncompressed stream
zUnzip.avail_out = bufferLength; //total size of output buffer
zUnzip.data_type = Z_BINARY;

inflateResult = inflateInit( &zUnzip); //standard zlib function, see <zlib.h>
if ( inflateResult != Z_OK ) {
    LOGE("inflateInit returned error: %d, msg: %s\n",inflateResult,zUnzip.msg);
}

do{
    inflateResult = inflate( &zUnzip, Z_SYNC_FLUSH );
    LOGE("avail_out = %d : difference = %d",zUnzip.avail_out,bufferLength-zUnzip.avail_out);
    memcpy(rawData,tmpbuffer,bufferLength);
    rawData+=bufferLength;
    zUnzip.next_out = (Bytef *)tmpbuffer; //output location of uncompressed stream
    zUnzip.avail_out = bufferLength; //total size of output buffer

}while(( inflateResult == Z_STREAM_END )) ;

if ( inflateResult < 0 ) {
        LOGE("zlib inflate returned error: %d, msg: %s\n",inflateResult,zUnzip.msg);
        return FALSE;
    }

The logcat output for an inputStream of size 16741 bytes

04-03 07:32:01.900: E/sc_client(25100): avail_out = 0 : difference = 131072
04-03 07:32:01.900: E/sc_client(25100): avail_out = 0 : difference = 131072
04-03 07:32:01.905: E/sc_client(25100): avail_out = 45672 : difference = 85400
04-03 07:32:01.905: E/sc_client(25100): avail_out = 131072 : difference = 0
04-03 07:32:01.905: E/sc_client(25100): zlib inflate returned error: -5, msg: (null)

NOTE: The input stream is raw compressed stream(direct output from zlib deflate call)!

Update: deflate part

rfbBool zrleOutStreamFlush(zrleOutStream *os){
  os->zs.next_in = os->in.start;
  os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in);

  while (os->zs.avail_in != 0) {
    do {
      int ret;
      os->zs.next_out = os->out.ptr;
      os->zs.avail_out = os->out.end - os->out.ptr;


      if ((ret = deflate(&os->zs, Z_SYNC_FLUSH)) != Z_OK) {
        Log("zrleOutStreamFlush: deflate failed with error code %d\n", ret);
        return FALSE;
      }

      os->out.ptr = os->zs.next_out;
    } while (os->zs.avail_out == 0);
  }

  os->in.ptr = os->in.start;
  LOGE("zrleOutStreamFlush: total_in %ld : total_out %ld ", os->zs.total_in,os->zs.total_out);
  return TRUE;
}

Structure definitions:

typedef struct {
  zrle_U8 *start; 
  zrle_U8 *ptr; //from start to ptr, we have data
  zrle_U8 *end;
} zrleBuffer;

typedef struct {
  zrleBuffer in; //input buffer
  zrleBuffer out; //output buffer

  z_stream   zs;
} zrleOutStream;
Was it helpful?

Solution

The compressed stream you are providing, inputStream[0..size-1] is not complete. The third call of inflate() has processed all of the input data you have provided, but it has not yet seen the end of the deflate stream. If you check avail_in at that point, you will see that it's zero.

By the way, you don't need to set data_type. That gets set by zlib. It is just for information and can be ignored.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top