Back to index

avfs  1.0.1
Classes | Defines | Functions | Variables
bzread.c File Reference
#include "config.h"
#include "bzfile.h"
#include "bzlib.h"
#include "oper.h"
#include "exit.h"
#include <stdlib.h>
#include <fcntl.h>

Go to the source code of this file.

Classes

struct  bzstreamcache
struct  bzindex
struct  bzcache
struct  bzfile

Defines

#define INBUFSIZE   16384
#define OUTBUFSIZE   32768

Functions

static AV_LOCK_DECL (bzread_lock)
void bz_internal_error (int errorcode)
static avoff_t bz_total_in (bz_stream *s)
static avoff_t bz_total_out (bz_stream *s)
static void bz_delete_stream (bz_stream *s)
static int bz_new_stream (bz_stream **resp)
static void bzfile_scache_delete ()
static void bzfile_scache_save (int id, bz_stream *s)
static int bzfile_reset (struct bzfile *fil)
static int bzfile_seek_index (struct bzfile *fil, struct bzindex *zi)
static struct bzindexbzcache_find_index (struct bzcache *zc, avoff_t offset)
static int bzfile_fill_inbuf (struct bzfile *fil)
static void bzfile_save_state (struct bzcache *zc, bz_stream *s, unsigned int bitsrem, unsigned int bits, unsigned int crc, unsigned int blocksize)
static void bz_block_end (void *data, bz_stream *s, unsigned int bitsrem, unsigned int bits, unsigned int crc, unsigned int blocksize)
static int bzfile_decompress (struct bzfile *fil, struct bzcache *zc)
static int bzfile_read (struct bzfile *fil, struct bzcache *zc, char *buf, avsize_t nbyte)
static int bzfile_skip_to (struct bzfile *fil, struct bzcache *zc, avoff_t offset)
static int bzfile_seek (struct bzfile *fil, struct bzcache *zc, avoff_t offset)
static avssize_t av_bzfile_do_pread (struct bzfile *fil, struct bzcache *zc, char *buf, avsize_t nbyte, avoff_t offset)
avssize_t av_bzfile_pread (struct bzfile *fil, struct bzcache *zc, char *buf, avsize_t nbyte, avoff_t offset)
int av_bzfile_size (struct bzfile *fil, struct bzcache *zc, avoff_t *sizep)
static void bzfile_destroy (struct bzfile *fil)
struct bzfileav_bzfile_new (vfile *vf)
static void bzcache_destroy (struct bzcache *zc)
struct bzcacheav_bzcache_new ()

Variables

static struct bzstreamcache
static int bzread_nextid

Class Documentation

struct bzstreamcache

Definition at line 22 of file bzread.c.

Collaboration diagram for bzstreamcache:
Class Members
int id
bz_stream * s
struct bzindex

Definition at line 34 of file bzread.c.

Class Members
avbyte blocksize
avuint crc
avoff_t inbits
avoff_t offset
avbyte startbits
struct bzcache

Definition at line 42 of file bzread.c.

Collaboration diagram for bzcache:
Class Members
int id
struct bzindex * indexes
unsigned int numindex
avoff_t size
struct bzfile

Definition at line 49 of file bzread.c.

Collaboration diagram for bzfile:
Class Members
int id
char inbuf
vfile * infile
int iseof
int iserror
bz_stream * s

Define Documentation

#define INBUFSIZE   16384

Definition at line 19 of file bzread.c.

#define OUTBUFSIZE   32768

Definition at line 20 of file bzread.c.


Function Documentation

struct bzcache* av_bzcache_new ( ) [read]

Definition at line 509 of file bzread.c.

{
    struct bzcache *zc;

    AV_NEW_OBJ(zc, bzcache_destroy);
    zc->numindex = 0;
    zc->indexes = NULL;
    zc->size = -1;

    AV_LOCK(bzread_lock);
    if(bzread_nextid == 0)
        bzread_nextid = 1;

    zc->id = bzread_nextid ++;
    AV_UNLOCK(bzread_lock);
    
    return zc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static avssize_t av_bzfile_do_pread ( struct bzfile fil,
struct bzcache zc,
char *  buf,
avsize_t  nbyte,
avoff_t  offset 
) [static]

Definition at line 387 of file bzread.c.

{
    avssize_t res;
    avoff_t curroff;

    fil->id = zc->id;

    curroff = bz_total_out(fil->s);
    if(offset != curroff) {
        AV_LOCK(bzread_lock);
#ifndef USE_SYSTEM_BZLIB
        res = bzfile_seek(fil, zc, offset);
#else
        if ( curroff > offset ) {
            res = bzfile_reset( fil );
        } else {
            res = 0;
        }
#endif
        AV_UNLOCK(bzread_lock);
        if(res < 0)
            return res;

        res = bzfile_skip_to(fil, zc, offset);
        if(res < 0)
            return res;
    }

    res = bzfile_read(fil, zc, buf, nbyte);
    
    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

struct bzfile* av_bzfile_new ( vfile *  vf) [read]

Definition at line 486 of file bzread.c.

{
    int res;
    struct bzfile *fil;

    AV_NEW_OBJ(fil, bzfile_destroy);
    fil->iseof = 0;
    fil->iserror = 0;
    fil->infile = vf;
    fil->id = 0;

    res = bz_new_stream(&fil->s);
    if(res < 0)
        fil->iserror = 1;

    return fil;
}

Here is the call graph for this function:

Here is the caller graph for this function:

avssize_t av_bzfile_pread ( struct bzfile fil,
struct bzcache zc,
char *  buf,
avsize_t  nbyte,
avoff_t  offset 
)

Definition at line 421 of file bzread.c.

{
    avssize_t res;

    if(fil->iserror)
        return -EIO;

    res = av_bzfile_do_pread(fil, zc, buf, nbyte, offset);
    if(res < 0)
        fil->iserror = 1;

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int av_bzfile_size ( struct bzfile fil,
struct bzcache zc,
avoff_t sizep 
)

Definition at line 436 of file bzread.c.

{
    int res;
    avoff_t size;

    AV_LOCK(bzread_lock);
    size = zc->size;
    AV_UNLOCK(bzread_lock);

    if(size != -1 || fil == NULL) {
        *sizep = size;
        return 0;
    }

    fil->id = zc->id;

    AV_LOCK(bzread_lock);
#ifndef USE_SYSTEM_BZLIB
    res = bzfile_seek(fil, zc, AV_MAXOFF);
#else
    res = bzfile_reset( fil );
#endif
    AV_UNLOCK(bzread_lock);
    if(res < 0)
        return res;

    res = bzfile_skip_to(fil, zc, AV_MAXOFF);
    if(res < 0)
        return res;
    
    AV_LOCK(bzread_lock);
    size = zc->size;
    AV_UNLOCK(bzread_lock);
    
    if(size == -1) {
        av_log(AVLOG_ERROR, "BZFILE: Internal error: could not find size");
        return -EIO;
    }
    
    *sizep = size;
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static AV_LOCK_DECL ( bzread_lock  ) [static]
static void bz_block_end ( void *  data,
bz_stream s,
unsigned int  bitsrem,
unsigned int  bits,
unsigned int  crc,
unsigned int  blocksize 
) [static]

Definition at line 252 of file bzread.c.

{
    struct bzcache *zc = (struct bzcache *) data;

    AV_LOCK(bzread_lock);
    bzfile_save_state(zc, s, bitsrem, bits, crc, blocksize);
    AV_UNLOCK(bzread_lock);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void bz_delete_stream ( bz_stream s) [static]

Definition at line 74 of file bzread.c.

{
    int res;

    if(s != NULL) {
        res = BZ2_bzDecompressEnd(s);
        if(res != BZ_OK)
            av_log(AVLOG_ERROR, "BZFILE: decompress end error: %i", res);
        
        av_free(s);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bz_internal_error ( int  errorcode)

Definition at line 59 of file bzread.c.

{
    av_log(AVLOG_ERROR, "BZLIB: internal error %i", errorcode);
}

Here is the call graph for this function:

static int bz_new_stream ( bz_stream **  resp) [static]

Definition at line 87 of file bzread.c.

{
    int res;
    bz_stream *s;

    AV_NEW(s);
    memset(s, 0, sizeof(*s));
    res = BZ2_bzDecompressInit(s, 0, 0);
    if(res != BZ_OK) {
        *resp = NULL;
        av_log(AVLOG_ERROR, "BZFILE: decompress init error: %i", res);
        return -EIO;
    }

    *resp = s;
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static avoff_t bz_total_in ( bz_stream s) [static]

Definition at line 64 of file bzread.c.

{
    return (avoff_t) s->total_in_lo32 + ((avoff_t) s->total_in_hi32 << 32);
}

Here is the caller graph for this function:

static avoff_t bz_total_out ( bz_stream s) [static]

Definition at line 69 of file bzread.c.

{
    return (avoff_t) s->total_out_lo32 + ((avoff_t) s->total_out_hi32 << 32);
}

Here is the caller graph for this function:

static void bzcache_destroy ( struct bzcache zc) [static]

Definition at line 504 of file bzread.c.

{
    av_free(zc->indexes);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct bzindex* bzcache_find_index ( struct bzcache zc,
avoff_t  offset 
) [static, read]

Definition at line 192 of file bzread.c.

{
    unsigned int i;

    for(i = 0; i < zc->numindex; i++) {
        if(zc->indexes[i].offset > offset)
            break;
    }
    if(i == 0)
        return NULL;
    
    return &zc->indexes[i-1];
}

Here is the caller graph for this function:

static int bzfile_decompress ( struct bzfile fil,
struct bzcache zc 
) [static]

Definition at line 264 of file bzread.c.

{
    int res;
    unsigned char *start;

    if(fil->s->avail_in == 0) {
        res = bzfile_fill_inbuf(fil);
        if(res < 0)
            return res;
       if(fil->s->avail_in == 0) {
         /* still no byte available */
         av_log(AVLOG_ERROR, "BZFILE: decompress error");
         return -EIO;
       }
    }
    
    start = (unsigned char*)( fil->s->next_out );
#ifndef USE_SYSTEM_BZLIB
    BZ2_bzSetBlockEndHandler(fil->s, bz_block_end, zc);
#endif
    res = BZ2_bzDecompress(fil->s);
    if(res == BZ_STREAM_END) {
        fil->iseof = 1;
        AV_LOCK(bzread_lock);
        zc->size = bz_total_out(fil->s);
        AV_UNLOCK(bzread_lock);
        return 0;
    }
    if(res != BZ_OK) {
        av_log(AVLOG_ERROR, "BZFILE: decompress error: %i", res);
        return -EIO;
    }
    
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void bzfile_destroy ( struct bzfile fil) [static]

Definition at line 479 of file bzread.c.

{
    AV_LOCK(bzread_lock);
    bzfile_scache_save(fil->id, fil->s);
    AV_UNLOCK(bzread_lock);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int bzfile_fill_inbuf ( struct bzfile fil) [static]

Definition at line 207 of file bzread.c.

{
    avssize_t res;
    avoff_t inoff = bz_total_in(fil->s);

    res = av_pread(fil->infile, fil->inbuf, INBUFSIZE, inoff);
    if(res < 0)
        return res;
    
    fil->s->next_in = fil->inbuf;
    fil->s->avail_in = res;

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int bzfile_read ( struct bzfile fil,
struct bzcache zc,
char *  buf,
avsize_t  nbyte 
) [static]

Definition at line 301 of file bzread.c.

{
    int res;

    fil->s->next_out = buf;
    fil->s->avail_out = nbyte;
    while(fil->s->avail_out != 0 && !fil->iseof) {
        res = bzfile_decompress(fil, zc);
        if(res < 0)
            return res;
    }

    return nbyte - fil->s->avail_out;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int bzfile_reset ( struct bzfile fil) [static]

Definition at line 135 of file bzread.c.

{
    /* FIXME: Is it a good idea to save the previous state or not? */
    if (fil->iseof || fil->iserror)
        bz_delete_stream(fil->s);
    else
        bzfile_scache_save(fil->id, fil->s);

    fil->iseof = 0;
    fil->iserror = 0;
    return bz_new_stream(&fil->s);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void bzfile_save_state ( struct bzcache zc,
bz_stream s,
unsigned int  bitsrem,
unsigned int  bits,
unsigned int  crc,
unsigned int  blocksize 
) [static]

Definition at line 223 of file bzread.c.

{
    struct bzindex *zi;
    avoff_t offset = bz_total_out(s);
    int i;
    
    for(i = 0; i < zc->numindex; i++) {
        if(zc->indexes[i].offset >= offset)
            return;
    }

    zc->numindex ++;
    zc->indexes = (struct bzindex *)
        av_realloc(zc->indexes, sizeof(*zc->indexes) * zc->numindex);
    
    zi = &zc->indexes[i];
    zi->offset = offset;
    zi->inbits = (bz_total_in(s) << 3) - bitsrem;
    zi->startbits = bits & ((1 << bitsrem) - 1);
    zi->crc = crc;
    zi->blocksize = blocksize;

    av_log(AVLOG_DEBUG, "BZFILE: new block end: %lli %lli/%i %08x %i",
           zi->offset, bz_total_in(s), bitsrem, zi->crc, zi->blocksize);

}

Here is the call graph for this function:

Here is the caller graph for this function:

static void bzfile_scache_delete ( ) [static]

Definition at line 105 of file bzread.c.

{
    AV_LOCK(bzread_lock);
    if(bzscache.id != 0) {
        bz_delete_stream(bzscache.s);
        bzscache.id = 0;
    }
    AV_UNLOCK(bzread_lock);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void bzfile_scache_save ( int  id,
bz_stream s 
) [static]

Definition at line 115 of file bzread.c.

{
    static int regdestroy = 0;
    if(!regdestroy) {
        regdestroy = 1;
        av_add_exithandler(bzfile_scache_delete);
    }

    if(id == 0 || s == NULL) {
        bz_delete_stream(s);
        return;
    }
    
    if(bzscache.id != 0)
        bz_delete_stream(bzscache.s);

    bzscache.id = id;
    bzscache.s = s;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int bzfile_seek ( struct bzfile fil,
struct bzcache zc,
avoff_t  offset 
) [static]

Definition at line 342 of file bzread.c.

{
    struct bzindex *zi;
    avoff_t curroff = bz_total_out(fil->s);
    avoff_t zcdist;
    avoff_t scdist;
    avoff_t dist;

    if(offset >= curroff)
        dist = offset - curroff;
    else
        dist = -1;

    zi = bzcache_find_index(zc, offset);
    if(zi != NULL)
        zcdist = offset - zi->offset;
    else
        zcdist = offset;

    if(bzscache.id == zc->id) {
        avoff_t scacheoff = bz_total_out(bzscache.s);

        if(offset >= scacheoff) {
            scdist = offset - scacheoff;
            if((dist == -1 || scdist < dist) && scdist < zcdist) {
                bz_stream *tmp = fil->s;
                fil->s = bzscache.s;
                fil->s->avail_in = 0;
                bzscache.s = tmp;
                return 0;
            }
        }
    }

    if(dist == -1 || zcdist < dist) {
        if(zi == NULL)
            return bzfile_reset(fil);
        else
            return bzfile_seek_index(fil, zi);
    }

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int bzfile_seek_index ( struct bzfile fil,
struct bzindex zi 
) [static]

Definition at line 149 of file bzread.c.

{
    int res;
    unsigned int bitsrem;
    avoff_t total_in;
    unsigned int val;
    
    /* FIXME: Is it a good idea to save the previous state or not? */
    bzfile_scache_save(fil->id, fil->s);
    res = bz_new_stream(&fil->s);
    if(res < 0)
        return res;

    total_in = (zi->inbits + 7) >> 3;
    bitsrem = (total_in << 3) - zi->inbits;
    total_in -= 4;
    
    fil->s->next_in = fil->inbuf;
    fil->s->avail_in = 4;

    fil->s->total_in_lo32 = total_in & 0xFFFFFFFF;
    fil->s->total_in_hi32 = (total_in >> 32) & 0xFFFFFFFF;
    fil->s->total_out_lo32 = zi->offset & 0xFFFFFFFF;
    fil->s->total_out_hi32 = (zi->offset >> 32) & 0xFFFFFFFF;
    
    val = ('B' << 24) + ('Z' << 16) + ('h' << 8) + (zi->blocksize + '0');
    val <<= bitsrem;
    val += zi->startbits;

    fil->inbuf[0] = (val >> 24) & 0xFF;
    fil->inbuf[1] = (val >> 16) & 0xFF;
    fil->inbuf[2] = (val >> 8) & 0xFF;
    fil->inbuf[3] = val & 0xFF;

    av_log(AVLOG_DEBUG, "BZFILE: restore: %lli %lli/%i %08x %i",
           bz_total_out(fil->s), bz_total_in(fil->s), bitsrem,
           zi->crc, zi->blocksize);
        
    BZ2_bzRestoreBlockEnd(fil->s, bitsrem, zi->crc);

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int bzfile_skip_to ( struct bzfile fil,
struct bzcache zc,
avoff_t  offset 
) [static]

Definition at line 317 of file bzread.c.

{
    int res;
    char outbuf[OUTBUFSIZE];
    
    while(!fil->iseof) {
        avoff_t curroff = bz_total_out(fil->s);

        if(curroff == offset)
            break;

        /* FIXME: Maybe cache some data as well */
        fil->s->next_out = outbuf;
        fil->s->avail_out = AV_MIN(OUTBUFSIZE, offset - curroff);

        res = bzfile_decompress(fil, zc);
        if(res < 0)
            return res;
    }

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

int bzread_nextid [static]

Definition at line 31 of file bzread.c.

struct bzstreamcache [static]

Definition at line 30 of file bzread.c.