diff libmpdemux/demuxer.h @ 6192:f03fe2e84efd

clone_demux_packet(), using refcounting to avoid memcpy() based on (sligtly simplified) patch by Alexander Neundorf <neundorf@dellingsoft.de>
author arpi
date Sat, 25 May 2002 22:13:23 +0000
parents 68cac7ecaf05
children 79b2b4c3c435
line wrap: on
line diff
--- 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);
 }