[MPlayer-dev-eng] [PATCH] much faster parse_es.c

Reimar Döffinger Reimar.Doeffinger at stud.uni-karlsruhe.de
Sat Jan 14 14:33:24 CET 2006


Hi,
On Sat, Dec 17, 2005 at 12:23:06PM +0100, Reimar Döffinger wrote:
> the attached patch makes MPEG-ES parsing/demuxing about 25% faster,
> tested on an AMD64 with the following command:
> ./mplayer -cache-min 90 -cache 409600 -vc null -vo null -benchmark -nosound
> /debian/home/reimar/mpl-tests/THX_Science_FLT_1920.gxf
> Though it will hardly be relevant considering the whole decoding step.
> Nevertheless, do you think it is okay to apply? It is a bit ugly since
> it operates directly on the demuxer buffer and thus makes it harder to
> change that part, so I'm undecided if it is worth it.

Ok, I removed the uglyness. I also think it would be a good idea to
apply since I didn't see any checks for the size of videobuffer in the
old code...
I guess a bit of testing would be a good idea, I do not have many
samples.
What do you think?

Greetings,
Reimar Döffinger
-------------- next part --------------
Index: libmpdemux/demuxer.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/demuxer.h,v
retrieving revision 1.84
diff -u -r1.84 demuxer.h
--- libmpdemux/demuxer.h	17 Sep 2005 18:05:55 -0000	1.84
+++ libmpdemux/demuxer.h	7 Jan 2006 19:25:32 -0000
@@ -256,6 +256,8 @@
 
 int demux_read_data(demux_stream_t *ds,unsigned char* mem,int len);
 int demux_read_data_pack(demux_stream_t *ds,unsigned char* mem,int len);
+int demux_pattern_3(demux_stream_t *ds, unsigned char *mem, int maxlen,
+                    int *read, uint32_t pattern);
 
 #define demux_peekc(ds) (\
      (likely(ds->buffer_pos<ds->buffer_size)) ? ds->buffer[ds->buffer_pos] \
Index: libmpdemux/demuxer.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/demuxer.c,v
retrieving revision 1.211
diff -u -r1.211 demuxer.c
--- libmpdemux/demuxer.c	17 Dec 2005 10:46:48 -0000	1.211
+++ libmpdemux/demuxer.c	7 Jan 2006 19:25:35 -0000
@@ -424,6 +424,41 @@
 return bytes;
 }
 
+/**
+ * \brief read data until the given 3-byte pattern is encountered, upt to maxlen
+ * \param mem memory to read data into, may be NULL to discard data
+ * \param maxlen maximum number of bytes to read
+ * \param read number of bytes actually read
+ * \param pattern pattern to search for (lowest 8 bits are ignored)
+ * \return whether pattern was found
+ */
+int demux_pattern_3(demux_stream_t *ds, unsigned char *mem, int maxlen,
+                    int *read, uint32_t pattern) {
+  register uint32_t head = 0xffffff00;
+  register uint32_t pat = pattern & 0xffffff00;
+  int total_len = 0;
+  do {
+    register unsigned char *ds_buf = &ds->buffer[ds->buffer_size];
+    int len = ds->buffer_size - ds->buffer_pos;
+    register long pos = -len;
+    if (unlikely(pos >= 0)) { // buffer is empty
+      ds_fill_buffer(ds);
+      continue;
+    }
+    do {
+      head |= ds_buf[pos];
+      head <<= 8;
+    } while (++pos && head != pat);
+    len += pos;
+    if (total_len + len > maxlen)
+      len = maxlen - total_len;
+    len = demux_read_data(ds, mem ? &mem[total_len] : NULL, len);
+    total_len += len;
+  } while ((head != pat || total_len < 3) && total_len < maxlen && !ds->eof);
+  if (read)
+    *read = total_len;
+  return total_len >= 3 && head == pat;
+}
 
 void ds_free_packs(demux_stream_t *ds){
   demux_packet_t *dp=ds->first;
Index: libmpdemux/parse_es.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/parse_es.c,v
retrieving revision 1.8
diff -u -r1.8 parse_es.c
--- libmpdemux/parse_es.c	3 Sep 2005 08:58:34 -0000	1.8
+++ libmpdemux/parse_es.c	7 Jan 2006 19:25:35 -0000
@@ -15,43 +15,37 @@
 //static unsigned char videobuffer[MAX_VIDEO_PACKET_SIZE];
 unsigned char* videobuffer=NULL;
 int videobuf_len=0;
-unsigned char videobuf_code[4];
+int next_nal = -1;
+///! legacy variable, 4 if stream is synced, 0 if not
 int videobuf_code_len=0;
 
+#define MAX_SYNCLEN (10 * 1024 * 1024)
 // sync video stream, and returns next packet code
 int sync_video_packet(demux_stream_t *ds){
+  if (!videobuf_code_len) {
   int skipped=0;
-  // we need enough bytes in the buffer:
-  while(videobuf_code_len<4){
-#if 0
-    int c;
-    c=demux_getc(ds);if(c<0){ return 0;} // EOF
-    videobuf_code[videobuf_code_len++]=c;
-#else
-    videobuf_code[videobuf_code_len++]=demux_getc(ds);
-#endif
+    if (!demux_pattern_3(ds, NULL, MAX_SYNCLEN, &skipped, 0x100)) {
+      mp_msg(MSGT_DEMUXER, MSGL_ERR, "parse_es: could not sync video stream!\n", skipped);
+      goto eof_out;
+    }
+    next_nal = demux_getc(ds);
+    if (next_nal < 0)
+      goto eof_out;
+    videobuf_code_len = 4;
+  if(skipped) mp_dbg(MSGT_PARSEES,MSGL_DBG2,"videobuf: %d bytes skipped  (next: 0x1%02X)\n",skipped,next_nal);
   }
-  // sync packet:
-  while(1){
-    int c;
-    if(videobuf_code[0]==0 &&
-       videobuf_code[1]==0 &&
-       videobuf_code[2]==1) break; // synced
-    // shift buffer, drop first byte
-    ++skipped;
-    videobuf_code[0]=videobuf_code[1];
-    videobuf_code[1]=videobuf_code[2];
-    videobuf_code[2]=videobuf_code[3];
-    c=demux_getc(ds);if(c<0){ return 0;} // EOF
-    videobuf_code[3]=c;
-  }
-  if(skipped) mp_dbg(MSGT_PARSEES,MSGL_DBG2,"videobuf: %d bytes skipped  (next: 0x1%02X)\n",skipped,videobuf_code[3]);
-  return 0x100|videobuf_code[3];
+  return 0x100|next_nal;
+
+eof_out:
+  next_nal = -1;
+  videobuf_code_len = 0;
+  return 0;
 }
 
 // return: packet length
 int read_video_packet(demux_stream_t *ds){
 int packet_start;
+  int res, read;
   
   if (VIDEOBUFFER_SIZE - videobuf_len < 5)
     return 0;
@@ -60,46 +54,35 @@
 
   // COPY STARTCODE:
   packet_start=videobuf_len;
-  videobuffer[videobuf_len+0]=videobuf_code[0];
-  videobuffer[videobuf_len+1]=videobuf_code[1];
-  videobuffer[videobuf_len+2]=videobuf_code[2];
-  videobuffer[videobuf_len+3]=videobuf_code[3];
+  videobuffer[videobuf_len+0]=0;
+  videobuffer[videobuf_len+1]=0;
+  videobuffer[videobuf_len+2]=1;
+  videobuffer[videobuf_len+3]=next_nal;
   videobuf_len+=4;
   
   // READ PACKET:
-  {
-    register uint32_t head = 0xffffffff;
-    register unsigned char *buf = &videobuffer[VIDEOBUFFER_SIZE];
-    register int pos = videobuf_len - VIDEOBUFFER_SIZE;
-    do {
-      int c=demux_getc(ds);
-      if(c<0) break; // EOF
-      buf[pos]=c;
-      head<<=8;
-      if(head==0x100) break; // synced
-      head|=c;
-    } while (++pos);
-    if (pos) pos++; // increment missed because of break
-    videobuf_len = &buf[pos] - videobuffer;
-  }
-  
-  if(ds->eof){
-    videobuf_code_len=0; // EOF, no next code
-    return videobuf_len-packet_start;
-  }
-  
-  videobuf_len-=4;
+  res = demux_pattern_3(ds, &videobuffer[videobuf_len],
+          VIDEOBUFFER_SIZE - videobuf_len, &read, 0x100);
+  videobuf_len += read;
+  if (!res)
+    goto eof_out;
+ 
+  videobuf_len-=3;
 
   mp_dbg(MSGT_PARSEES,MSGL_DBG2,"videobuf: packet 0x1%02X  len=%d  (total=%d)\n",videobuffer[packet_start+3],videobuf_len-packet_start,videobuf_len);
 
   // Save next packet code:
-  videobuf_code[0]=videobuffer[videobuf_len];
-  videobuf_code[1]=videobuffer[videobuf_len+1];
-  videobuf_code[2]=videobuffer[videobuf_len+2];
-  videobuf_code[3]=videobuffer[videobuf_len+3];
+  next_nal = demux_getc(ds);
+  if (next_nal < 0)
+    goto eof_out;
   videobuf_code_len=4;
 
   return videobuf_len-packet_start;
+
+eof_out:
+  next_nal = -1;
+  videobuf_code_len = 0;
+  return videobuf_len - packet_start;
 }
 
 // return: next packet code


More information about the MPlayer-dev-eng mailing list