# HG changeset patch # User arpi # Date 1022364803 0 # Node ID f03fe2e84efd155aae25259fa375c34b3b463cce # Parent 26a980dbc9a5ad5dd22a68f5fb30e7e96c2bdd69 clone_demux_packet(), using refcounting to avoid memcpy() based on (sligtly simplified) patch by Alexander Neundorf diff -r 26a980dbc9a5 -r f03fe2e84efd libmpdemux/demuxer.c --- a/libmpdemux/demuxer.c Sat May 25 21:43:02 2002 +0000 +++ b/libmpdemux/demuxer.c Sat May 25 22:13:23 2002 +0000 @@ -38,7 +38,7 @@ //--------------- ds->packs=0; ds->bytes=0; - ds->first=ds->last=NULL; + ds->first=ds->last=ds->current=NULL; ds->id=id; ds->demuxer=demuxer; //---------------- @@ -296,7 +296,7 @@ // 1 = succesfull int ds_fill_buffer(demux_stream_t *ds){ demuxer_t *demux=ds->demuxer; - if(ds->buffer) free(ds->buffer); + if(ds->current) free_demux_packet(ds->current); if(verbose>2){ if(ds==demux->audio) mp_dbg(MSGT_DEMUXER,MSGL_DBG3,"ds_fill_buffer(d_audio) called\n");else if(ds==demux->video) mp_dbg(MSGT_DEMUXER,MSGL_DBG3,"ds_fill_buffer(d_video) called\n");else @@ -319,11 +319,11 @@ } ds->pts_bytes+=p->len; // !!! ds->flags=p->flags; - // free packet: + // unlink packet: ds->bytes-=p->len; + ds->current=p; ds->first=p->next; if(!ds->first) ds->last=NULL; - free(p); --ds->packs; return 1; //ds->buffer_size; } @@ -344,6 +344,7 @@ } ds->buffer_pos=ds->buffer_size=0; ds->buffer=NULL; + ds->current=NULL; mp_msg(MSGT_DEMUXER,MSGL_V,"ds_fill_buffer: EOF reached (stream: %s) \n",ds==demux->audio?"audio":"video"); ds->eof=1; return 0; @@ -387,8 +388,7 @@ demux_packet_t *dp=ds->first; while(dp){ demux_packet_t *dn=dp->next; - if(dp->buffer) free(dp->buffer); - free(dp); + free_demux_packet(dp); dp=dn; } if(ds->asf_packet){ @@ -400,7 +400,8 @@ ds->first=ds->last=NULL; ds->packs=0; // !!!!! ds->bytes=0; - if(ds->buffer) free(ds->buffer); + if(ds->current) free_demux_packet(ds->current); + ds->current=NULL; ds->buffer=NULL; ds->buffer_pos=ds->buffer_size; ds->pts=0; ds->pts_bytes=0; diff -r 26a980dbc9a5 -r f03fe2e84efd libmpdemux/demuxer.h --- a/libmpdemux/demuxer.h Sat May 25 21:43:02 2002 +0000 +++ b/libmpdemux/demuxer.h Sat May 25 22:13:23 2002 +0000 @@ -51,13 +51,15 @@ off_t pos; // position in index (AVI) or file (MPG) unsigned char* buffer; int flags; // keyframe, etc + int refcount; //refcounter for the master packet, if 0, buffer can be free()d + struct demux_packet_st* master; //pointer to the master packet if this one is a cloned one struct demux_packet_st* next; } demux_packet_t; typedef struct { int buffer_pos; // current buffer position int buffer_size; // current buffer size - unsigned char* buffer; // current buffer + unsigned char* buffer; // current buffer, never free() it, always use free_demux_packet(buffer_ref); float pts; // current buffer's pts int pts_bytes; // number of bytes read after last pts stamp int eof; // end of demuxed stream? (true if all buffer empty) @@ -70,6 +72,7 @@ int bytes; // total bytes of packets in buffer demux_packet_t *first; // read to current buffer from here demux_packet_t *last; // append new packets from input stream to here + demux_packet_t *current;// needed for refcounting of the buffer int id; // stream ID (for multiple audio/video streams) struct demuxer_st *demuxer; // parent demuxer structure (stream handler) // ---- asf ----- @@ -123,11 +126,33 @@ dp->pts=0; dp->pos=0; dp->flags=0; + dp->refcount=1; + dp->master=NULL; + return dp; +} + +inline static demux_packet_t* clone_demux_packet(demux_packet_t* pack){ + demux_packet_t* dp=malloc(sizeof(demux_packet_t)); + while(pack->master) pack=pack->master; // find the master + memcpy(dp,pack,sizeof(demux_packet_t)); + dp->next=NULL; + dp->refcount=0; + dp->master=pack; + pack->refcount++; return dp; } inline static void free_demux_packet(demux_packet_t* dp){ - free(dp->buffer); + if (dp->master==NULL){ //dp is a master packet + dp->refcount--; + if (dp->refcount==0){ + if (dp->buffer) free(dp->buffer); + free(dp); + } + return; + } + // dp is a clone: + free_demux_packet(dp->master); free(dp); }