changeset 16369:8ea2e7ab3106

faster mpg and much faster gxf demuxing
author reimar
date Sat, 03 Sep 2005 08:58:34 +0000
parents 8b7a72777a12
children b2e4d3f3c0af
files libmpdemux/demux_mpg.c libmpdemux/demuxer.h libmpdemux/parse_es.c
diffstat 3 files changed, 71 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/libmpdemux/demux_mpg.c	Sat Sep 03 08:53:48 2005 +0000
+++ b/libmpdemux/demux_mpg.c	Sat Sep 03 08:58:34 2005 +0000
@@ -506,33 +506,70 @@
   return 1;
 }
 
+/**
+ * \brief discard until 0x100 header and return a filled buffer
+ * \param b buffer-end pointer
+ * \param pos current pos in stream, negative since b points to end of buffer
+ * \param s stream to read from
+ * \return new position, differs from original pos when eof hit and thus
+ *             b was modified to point to the new end of buffer
+ */
+static int find_end(unsigned char **b, int pos, stream_t *s) {
+  register int state = 0xffffffff;
+  unsigned char *buf = *b;
+  int start = pos;
+  int read, unused;
+  // search already read part
+  while (state != 0x100 && pos) {
+    state = state << 8 | buf[pos++];
+  }
+  // continue search in stream
+  while (state != 0x100) {
+    register int c = stream_read_char(s);
+    if (c < 0) break;
+    state = state << 8 | c;
+  }
+  // modify previous header (from 0x1bc or 0x1bf to 0x100)
+  buf[start++] = 0;
+  // copy remaining buffer part to current pos
+  memmove(&buf[start], &buf[pos], -pos);
+  unused = start + -pos; // -unused bytes in buffer
+  read = stream_read(s, &buf[unused], -unused);
+  unused += read;
+  // fix buffer so it ends at pos == 0 (eof case)
+  *b = &buf[unused];
+  start -= unused;
+  return start;
+}
+
+/**
+ * This format usually uses an insane bitrate, which makes this function
+ * performance-critical!
+ * Be sure to benchmark any changes with different compiler versions.
+ */
 static int demux_mpg_gxf_fill_buffer(demuxer_t *demux, demux_stream_t *ds) {
   demux_packet_t *pack;
-  uint32_t state = (uint32_t)demux->priv;
-  int pos = 0;
-  int discard = 0;
-  unsigned char *buf;
-  if (demux->stream->eof)
-    return 0;
+  int len;
   demux->filepos = stream_tell(demux->stream);
   pack = new_demux_packet(STREAM_BUFFER_SIZE);
-  buf = pack->buffer;
-  while (pos < STREAM_BUFFER_SIZE) {
-    register int c = stream_read_char(demux->stream);
-    if (c < 0) { // EOF
-      resize_demux_packet(pack, pos);
-      break;
-    }
-    state = state << 8 | c;
-    if (state == 0x1bc || state == 0x1bf)
-      discard = 1;
-    else if (state == 0x100)
-      discard = 0;
-    if (!discard)
-      buf[pos++] = c;
+  len = stream_read(demux->stream, pack->buffer, STREAM_BUFFER_SIZE);
+  if (len <= 0)
+    return 0;
+  {
+    register uint32_t state = (uint32_t)demux->priv;
+    register int pos = -len;
+    unsigned char *buf = &pack->buffer[len];
+    do {
+      state = state << 8 | buf[pos];
+      if (unlikely((state | 3) == 0x1bf))
+        pos = find_end(&buf, pos, demux->stream);
+    } while (++pos);
+    demux->priv = (void *)state;
+    len = buf - pack->buffer;
   }
+  if (len < STREAM_BUFFER_SIZE)
+    resize_demux_packet(pack, len);
   ds_add_packet(ds, pack);
-  demux->priv = (void *)state;
   return 1;
 }
 
--- a/libmpdemux/demuxer.h	Sat Sep 03 08:53:48 2005 +0000
+++ b/libmpdemux/demuxer.h	Sat Sep 03 08:58:34 2005 +0000
@@ -259,8 +259,8 @@
 
 #if 1
 #define demux_getc(ds) (\
-     (ds->buffer_pos<ds->buffer_size) ? ds->buffer[ds->buffer_pos++] \
-     :((!ds_fill_buffer(ds))? (-1) : ds->buffer[ds->buffer_pos++] ) )
+     (likely(ds->buffer_pos<ds->buffer_size)) ? ds->buffer[ds->buffer_pos++] \
+     :((unlikely(!ds_fill_buffer(ds)))? (-1) : ds->buffer[ds->buffer_pos++] ) )
 #else
 inline static int demux_getc(demux_stream_t *ds){
   if(ds->buffer_pos>=ds->buffer_size){
--- a/libmpdemux/parse_es.c	Sat Sep 03 08:53:48 2005 +0000
+++ b/libmpdemux/parse_es.c	Sat Sep 03 08:58:34 2005 +0000
@@ -53,6 +53,8 @@
 int read_video_packet(demux_stream_t *ds){
 int packet_start;
   
+  if (VIDEOBUFFER_SIZE - videobuf_len < 5)
+    return 0;
   // SYNC STREAM
 //  if(!sync_video_packet(ds)) return 0; // cannot sync (EOF)
 
@@ -65,21 +67,20 @@
   videobuf_len+=4;
   
   // READ PACKET:
-  { unsigned int head=-1;
-    while(videobuf_len<VIDEOBUFFER_SIZE){
+  {
+    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
-      videobuffer[videobuf_len++]=c;
-#if 1
+      buf[pos]=c;
       head<<=8;
       if(head==0x100) break; // synced
       head|=c;
-#else
-      if(videobuffer[videobuf_len-4]==0 &&
-         videobuffer[videobuf_len-3]==0 &&
-         videobuffer[videobuf_len-2]==1) break; // synced
-#endif
-    }
+    } while (++pos);
+    if (pos) pos++; // increment missed because of break
+    videobuf_len = &buf[pos] - videobuffer;
   }
   
   if(ds->eof){