PATCH: Add support for CoreAVC via dshowserver

View: New views
5 Messages — Rating Filter:   Alert me  

PATCH: Add support for CoreAVC via dshowserver

by Alan Nisota :: Rate this Message:

| View Threaded | Show Only this Message

I was asked to send this patch to xine-devel by Darren Salt.

It implements support for communicating with the dshowserver
(coreavc-for-linux.googlecode.com)
This is mainly useful for using CoreAVC in Linux (a very fast H264
decoder), however it could be made to work with other win32 codecs.
The code is based on mplayer's libloader (which xine already includes in
  modified form) but using a separate server allows for several benefits:
   a) easy to support in multiple players (mythtv, xine, mplayer) since
the dshowserver patch is small, and all the win32 stuff is centralized
   b) can use 32bit win32 codecs with players compiled in 64-bit mode
   c) a crash in the codec does not bring down the player

I have addressed many of the issues he requested I address except for:
   * The plugin description should be translatable (use N_() for this)
I don't see any examples of other plugins doing this, so I wasn't sure
how to proceed.

   * Documentation patches
I have no idea what he wanted here.
   * Fixed-size buffers should be avoided wherever practical, e.g. use
     asprintf() where it makes sense to do so.
I did move the constant-sized strings (snprintf) to use asprintf as
requested, but this really didn't feel like the right thing to do to me.

The code is built against the xinelib 1.1 branch, and will require a
some change to work in 1.2



diff -r 66e1654718fb configure.ac
--- a/configure.ac Mon Apr 14 22:38:03 2008 +0200
+++ b/configure.ac Tue Jun 24 14:06:43 2008 -0700
@@ -2538,6 +2538,14 @@ fi
 
 AM_CONDITIONAL(HAVE_W32DLL, test "x$enable_w32dll" != "xno")
 
+AC_ARG_ENABLE([dshowserver],
+  AS_HELP_STRING([--disable-dshowserver], [Disable dshowserver support]))
+
+if test "x$arch_x86" == "xno"; then
+   enable_dshowserver="no"
+fi
+
+AM_CONDITIONAL(HAVE_DSHOWSERVER, test "x$enable_dshowserver" != "xno")
 
 dnl ---------------------------------------------
 dnl some include paths ( !!! DO NOT REMOVE !!! )
diff -r 66e1654718fb src/libxinevdec/Makefile.am
--- a/src/libxinevdec/Makefile.am Mon Apr 14 22:38:03 2008 +0200
+++ b/src/libxinevdec/Makefile.am Tue Jun 24 14:06:43 2008 -0700
@@ -17,9 +17,14 @@ theora_module = xineplug_decode_theora.l
 theora_module = xineplug_decode_theora.la
 endif
 
+if HAVE_DSHOWSERVER
+dshowserver_module = xineplug_decode_dshowserver.la
+endif
+
 xineplug_LTLIBRARIES = $(image_module) \
  $(gdkpixbuf_module) \
  $(theora_module) \
+ $(dshowserver_module) \
  xineplug_decode_bitplane.la \
  xineplug_decode_rgb.la \
  xineplug_decode_yuv.la
@@ -44,3 +49,7 @@ xineplug_decode_theora_la_SOURCES = xine
 xineplug_decode_theora_la_SOURCES = xine_theora_decoder.c
 xineplug_decode_theora_la_CFLAGS = $(AM_CFLAGS) $(OGG_CFLAGS) $(THEORA_CFLAGS)
 xineplug_decode_theora_la_LIBADD = $(XINE_LIB) $(OGG_LIBS) $(THEORA_LIBS)
+
+xineplug_decode_dshowserver_la_SOURCES = dshowserver.c nal_parser.c
+xineplug_decode_dshowserver_la_LIBADD = $(XINE_LIB) $(RT_LIBS) $(PTHREAD_LIBS)
+noinst_HEADERS = nal_parser.h
diff -r 66e1654718fb src/libxinevdec/dshowserver.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/libxinevdec/dshowserver.c Tue Jun 24 14:06:43 2008 -0700
@@ -0,0 +1,440 @@
+/*
+ * Copyright (C) 2008 Alan Nisota
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Support for dshowserver, which enables using w32 codecs in a seperate process.
+ * This is useful to run 32bit codecs in a 64bit xine.
+ * It is mostly tageted at supporting CoreAVC at the moment.
+ */
+#define _GNU_SOURCE //needed for asprintf
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+
+#include <semaphore.h>
+#include <pthread.h>
+#include <sys/mman.h>
+
+#include "xine_internal.h"
+#include "video_out.h"
+#include "buffer.h"
+#include "xineutils.h"
+
+#include "nal_parser.h"
+
+struct vd_struct {
+  union {
+    uint32_t ret;
+    uint32_t cmd;
+  };
+  uint32_t buflen;
+  uint64_t pts;
+  uint32_t unused[8];
+} __attribute__((__packed__));
+
+enum {
+  VD_END = 1,
+  VD_DECODE = 2,
+  VD_SEEK = 3,
+  VD_RELOAD_BIH = 4,
+  VD_HAS_BIH = 0x10000,
+  VD_VERSION_MASK = 0xFFFF,
+};
+
+typedef struct {
+    int fd;
+    void *mem;
+    char *data;
+    char *picture;
+    char *pagestart;
+    int picsize;
+    int pagesize;
+    sem_t *sem_rd;
+    sem_t *sem_wr;
+    struct vd_struct *vd;
+} ds_mpi_t;
+
+typedef struct {
+  video_decoder_class_t   decoder_class;
+} dshowserver_class_t;
+
+typedef struct {
+  video_decoder_t   video_decoder;
+
+  xine_stream_t    *stream;
+  dshowserver_class_t *class;
+  
+  int64_t           video_step;
+  int               decoder_ok;
+  int               decoder_initialized;
+
+  int               stream_id;
+  int               skipframes;
+
+  int               size;        /* the current size of buf       */
+  int               width;       /* the width of a video frame    */
+  int               height;      /* the height of a video frame   */
+  uint32_t          compression; /* the compression format */
+  double            ratio;       /* the width to height ratio     */
+  int               bpp;
+  int               numpages;
+  int               extra;       /* width & 0x0f */
+  ds_mpi_t          ds_mpi;
+
+  xine_bmiheader    *bih;
+  unsigned char     *extradata;
+  int               extradata_size;
+  struct nal_parser *parser;     /* Parser for H264 */
+
+} dshowserver_decoder_t;
+
+static int sem_twait(sem_t *sem, int t) {
+    struct timespec ts;
+    clock_gettime(CLOCK_REALTIME, &ts);
+    ts.tv_sec += t;
+    return(sem_timedwait(sem, &ts));
+}
+
+static void make_bih(dshowserver_decoder_t *this)
+{
+  if(this->bih) {
+    this->bih = realloc(this->bih, sizeof(xine_bmiheader) + this->extradata_size);
+  } else {
+    this->bih = xine_xmalloc(sizeof(xine_bmiheader) + this->extradata_size);
+    this->bih->biWidth = this->width;
+    this->bih->biHeight = this->height;
+    this->bih->biPlanes = 1;
+    this->bih->biBitCount = 24;
+    this->bih->biCompression = this->compression;
+    this->bih->biSizeImage = 0;
+    this->bih->biXPelsPerMeter=10000;
+    this->bih->biYPelsPerMeter=10000;
+    this->bih->biClrUsed=0;
+    this->bih->biClrImportant=0;
+  }
+  if(this->extradata_size)
+    memcpy((unsigned char *)this->bih + sizeof(xine_bmiheader), this->extradata, this->extradata_size);
+  this->bih->biSize = sizeof(xine_bmiheader) + this->extradata_size;
+}
+
+static void dshowserver_decode_data (video_decoder_t *this_gen, buf_element_t *buf) {
+  dshowserver_decoder_t *this = (dshowserver_decoder_t *) this_gen;
+  int ret                               = 0;
+  vo_frame_t *img                       = 0; /* video out frame */
+  int size_from_nal                     = 0;
+
+  lprintf ("processing packet type = %08x, buf->decoder_flags=%08x\n",
+           buf->type, buf->decoder_flags);
+  
+  if (buf->decoder_flags & BUF_FLAG_PREVIEW)
+    return;
+
+  if (buf->decoder_flags & BUF_FLAG_FRAMERATE) {
+    this->video_step = buf->decoder_info[0];
+    _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step);
+  
+    lprintf ("video_step is %lld\n", this->video_step);
+  }
+
+  if (buf->decoder_flags & BUF_FLAG_SPECIAL) {
+    /* store extradata */
+    if (buf->decoder_info[1] == BUF_SPECIAL_DECODER_CONFIG &&
+        !this->extradata_size)
+    {
+      lprintf("BUF_SPECIAL_DECODER_CONFIG\n");
+      this->extradata_size = buf->decoder_info[2];
+      this->extradata = xine_xmalloc(buf->decoder_info[2]);
+      memcpy(this->extradata, buf->decoder_info_ptr[2],
+              buf->decoder_info[2]);
+      lprintf("Extradata: %d\n", this->extradata_size);
+    }
+  }
+    
+  if(! this->decoder_ok && ! (buf->decoder_flags & BUF_FLAG_STDHEADER)) {
+    int len = 0;
+    unsigned char *tmpbuf;
+    int tmplen;
+    if(! this->parser)
+      this->parser = init_parser();
+
+    while(len < buf->size) {
+      len += parse_frame(this->parser, buf->content + len, buf->size - len,
+                         &tmpbuf, &tmplen);
+      if(tmpbuf)
+        free(tmpbuf);
+      if(this->parser->current_nal->sps != NULL)
+      {
+        this->width = this->parser->current_nal->sps->pic_width;
+        this->height = this->parser->current_nal->sps->pic_height;
+        this->compression = 0x34363248; //H264
+        size_from_nal = 1;
+      }
+    }
+  }
+  if (! this->decoder_ok && (buf->decoder_flags & BUF_FLAG_STDHEADER || size_from_nal)) {
+    if(! size_from_nal) {
+      int size = ((xine_bmiheader *) buf->content)->biSize;
+      this->bih = xine_xmalloc(size);
+      memcpy(this->bih, buf->content, size);
+      this->width                         = this->bih->biWidth;
+      this->height                        = this->bih->biHeight;
+      this->compression                   = this->bih->biCompression;
+    }
+    this->extra                         = this->width & 0x0F;
+    this->bpp                           = 16; //YUY2
+    this->numpages                      = 10;
+
+    if ( buf->type & 0xff )
+      return;
+    
+    lprintf ("processing header ...\n");
+
+    /* init package containing bih */
+
+    this->ratio = (double)this->width/(double)this->height;
+
+    _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH,    this->width);
+    _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT,   this->height);
+
+    //Do dshowserver init here
+    this->decoder_ok = 1;
+
+    if (! this->decoder_ok) {
+      xine_log (this->stream->xine, XINE_LOG_MSG,
+                _("dshowserver: decoder failed to start\n"));
+      _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HANDLED, 0);
+      _x_message(this->stream, XINE_MSG_LIBRARY_LOAD_ERROR,
+                   "dshowserver", NULL);
+    }
+  } else if (this->decoder_ok) {
+    lprintf ("processing packet ...\n");
+    if(! this->decoder_initialized) {
+      //delay initialization until 1st frame in case extradata comes.
+      int memsize                         = 0;
+      char *cmd, *shm, *sem1, *sem2;
+
+      this->decoder_initialized = 1;
+      asprintf(&cmd, "dshowserver -c CoreAVCDecoder.ax -s %dx%d "
+               "-g 09571a4b-f1fe-4c60-9760de6d310c7c31 "
+               "-f 0x%08x -b %d -o 0x%08x -p %d -i %x -n %d %s&",
+               this->width, this->height,
+               this->compression, this->bpp, XINE_IMGFMT_YUY2, getpid(),
+               *(int *)pthread_self(), this->numpages, "");
+      asprintf(&shm, "/dshow_shm.%x", *(int *)pthread_self());
+      asprintf(&sem1, "/dshow_sem1.%x", *(int *)pthread_self());
+      asprintf(&sem2, "/dshow_sem2.%x", *(int *)pthread_self());
+
+      this->ds_mpi.fd = shm_open(shm, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+      this->ds_mpi.picsize =  this->width * this->height * this->bpp / 8;
+      this->ds_mpi.pagesize = this->ds_mpi.picsize + 1024;
+      memsize = sizeof(struct vd_struct) + this->width * this->height + this->ds_mpi.picsize + this->extra + this->ds_mpi.pagesize * this->numpages;
+      ftruncate(this->ds_mpi.fd, memsize);
+      this->ds_mpi.mem = mmap(NULL, memsize, PROT_READ | PROT_WRITE, MAP_SHARED, this->ds_mpi.fd, 0);
+      if(this->ds_mpi.mem == MAP_FAILED) {
+        xine_log (this->stream->xine, XINE_LOG_MSG, _("dschowserver: mmap failed\n"));
+        _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HANDLED, 0);
+        _x_message(this->stream, XINE_MSG_LIBRARY_LOAD_ERROR,
+                     "dshowserver", NULL);
+        return;
+      }
+      memset((char *)this->ds_mpi.mem, 0, sizeof(struct vd_struct));
+      this->ds_mpi.vd = (struct vd_struct *)this->ds_mpi.mem;
+      this->ds_mpi.data = ((char *)this->ds_mpi.mem) + sizeof(struct vd_struct);
+      this->ds_mpi.picture = this->ds_mpi.data + this->width * this->height;
+      this->ds_mpi.pagestart = this->ds_mpi.picture + this->ds_mpi.picsize + this->extra;
+      if (this->extra)
+        memset((char *)this->ds_mpi.picture + this->ds_mpi.picsize, 0, this->extra);
+  
+      if(this->extradata)
+        make_bih(this);
+      if(this->bih && this->bih->biSize > sizeof(xine_bmiheader)) {
+        this->ds_mpi.vd->cmd |= VD_HAS_BIH; //Use embedded bih
+        memcpy(this->ds_mpi.data, this->bih, this->bih->biSize);
+      }
+      //Create read/write semaphores in locked state
+      this->ds_mpi.sem_wr = sem_open(sem1, O_CREAT, 0644, 0);
+      this->ds_mpi.sem_rd = sem_open(sem2, O_CREAT, 0644, 0);
+      system(cmd);
+      ret = sem_twait(this->ds_mpi.sem_rd, 10);
+      shm_unlink(shm);
+      sem_unlink(sem1);
+      sem_unlink(sem2);
+      free(cmd);
+      free(shm);
+      free(sem1);
+      free(sem2);
+      if(ret != 0) {
+        xine_log (this->stream->xine, XINE_LOG_MSG,
+                  _("dshowserver: decoder failed to start\n"));
+        _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HANDLED, 0);
+        _x_message(this->stream, XINE_MSG_LIBRARY_LOAD_ERROR,
+                     "dshowserver", NULL);
+        return;
+      }
+      lprintf("Found DirectShow filter\n");
+    }
+
+    if( (int) buf->size <= 0 )
+        return;
+      
+    if( this->stream_id < 0 )
+       this->stream_id = buf->type & 0xff;
+    
+    if( this->stream_id != (buf->type & 0xff) )
+       return;
+
+    xine_fast_memcpy (this->ds_mpi.data + this->size, buf->content, buf->size);
+    this->size += buf->size;
+    if (! (buf->decoder_flags & BUF_FLAG_FRAME_END))
+      return;
+    this->ds_mpi.vd->cmd = VD_DECODE; //'2' is cmd for decoding
+    this->ds_mpi.vd->pts = buf->pts;
+    this->ds_mpi.vd->buflen = this->size;
+    this->size = 0;
+    sem_post(this->ds_mpi.sem_wr);
+    ret = sem_twait(this->ds_mpi.sem_rd, 10);
+    lprintf("ret: %d/%d PTS: %lld -> %lld\n", ret, this->ds_mpi.vd->ret, buf->pts, this->ds_mpi.vd->pts);
+    //lprintf("PTS (%d): %f(%d) -> %d\n", this->ds_mpi.vd->ret, sh->buffered_pts[0], pts-1, this->ds_mpi.vd->pts);
+    if(ret == 0 && this->ds_mpi.vd->ret && ! (this->ds_mpi.vd->ret & (1<<31))) {
+      int flags = VO_BOTH_FIELDS;
+      if(this->ds_mpi.vd->ret & 0x10)
+        flags |= VO_INTERLACED_FLAG;
+      else
+        flags &= ~VO_INTERLACED_FLAG;
+
+      img = this->stream->video_out->get_frame (this->stream->video_out,
+                                        this->width, this->height,
+                                        this->ratio, XINE_IMGFMT_YUY2,
+                                        flags);
+      if(this->ds_mpi.vd->pts)
+        img->pts = this->ds_mpi.vd->pts;
+      else
+        img->pts = buf->pts;
+      img->bad_frame                    = 0;
+      img->duration                     = this->video_step;
+      if(this->ds_mpi.vd->ret & 0x02) {
+        unsigned char page = this->ds_mpi.vd->ret >> 8;
+        memcpy(img->base[0], this->ds_mpi.pagestart + page * this->ds_mpi.pagesize, this->ds_mpi.picsize);
+      } else {
+        memcpy(img->base[0], this->ds_mpi.picture, this->ds_mpi.picsize);
+      }
+      img->draw(img, this->stream);
+      img->free(img);
+    }
+  }
+}
+
+/* flush gets called by video-decoder to force outputting frames (?) */
+static void dshowserver_flush (video_decoder_t *this_gen) {
+}
+
+/* reset seems to be called after a seek */
+static void dshowserver_reset (video_decoder_t *this_gen) {
+  dshowserver_decoder_t *this = (dshowserver_decoder_t *) this_gen;
+  xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "dshowserver: called reset\n");
+  if(this->decoder_initialized) {
+    this->ds_mpi.vd->cmd = VD_SEEK; //'3' is cmd for seek
+    sem_post(this->ds_mpi.sem_wr);
+    sem_twait(this->ds_mpi.sem_rd, 10);
+  }
+  xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "dshowserver: reset done\n");
+}
+
+static void dshowserver_discontinuity (video_decoder_t *this_gen) {
+}
+
+static void dshowserver_dispose (video_decoder_t *this_gen) {
+  dshowserver_decoder_t *this = (dshowserver_decoder_t *) this_gen;
+  if( this->decoder_initialized )  {  
+    this->decoder_ok = 0;
+    this->stream->video_out->close(this->stream->video_out, this->stream);
+    this->ds_mpi.vd->cmd = VD_END; //'1' is cmd for terminating
+    sem_post(this->ds_mpi.sem_wr);
+    close(this->ds_mpi.fd);
+    sem_close(this->ds_mpi.sem_wr);
+    sem_close(this->ds_mpi.sem_rd);
+  }
+  if(this->parser)
+    free_parser(this->parser);
+  if(this->bih)
+    free(this->bih);
+  free (this);
+}
+
+static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) {
+
+  dshowserver_decoder_t  *this             = (dshowserver_decoder_t *) xine_xmalloc (sizeof (dshowserver_decoder_t));
+
+  this->video_decoder.decode_data       = dshowserver_decode_data;
+  this->video_decoder.flush             = dshowserver_flush;
+  this->video_decoder.reset             = dshowserver_reset;
+  this->video_decoder.discontinuity     = dshowserver_discontinuity;
+  this->video_decoder.dispose           = dshowserver_dispose;
+
+  this->stream                          = stream;
+  this->class                           = (dshowserver_class_t *) class_gen;
+
+  this->decoder_ok                      = 0;
+  return &this->video_decoder;
+}
+
+static char *get_identifier (video_decoder_class_t *this) {
+  return "dshowserver";
+}
+
+static char *get_description (video_decoder_class_t *this) {
+  return "Dshowserver video decoder plugin (mostly used for CoreAVC windows codec)";
+}
+
+static void dispose_class (video_decoder_class_t *this) {
+  free (this);
+}
+
+static void *init_plugin (xine_t *xine, void *data) {
+
+  dshowserver_class_t *this                = (dshowserver_class_t *) xine_xmalloc (sizeof (dshowserver_class_t));
+
+  this->decoder_class.open_plugin       = open_plugin;
+  this->decoder_class.get_identifier    = get_identifier;
+  this->decoder_class.get_description   = get_description;
+  this->decoder_class.dispose           = dispose_class;
+
+  return this;
+}
+
+static uint32_t video_types[] = {
+  BUF_VIDEO_H264,
+  0
+};
+
+static const decoder_info_t dec_info_video = {
+  video_types,         /* supported types */
+  1                    /* priority        */
+};
+
+const plugin_info_t xine_plugin_info[] EXPORTED = {
+  /* type, API, "name", version, special_info, init_function */
+  { PLUGIN_VIDEO_DECODER, 18, "dshowserver", XINE_VERSION_CODE, &dec_info_video, init_plugin },
+  { PLUGIN_NONE, 0, "", 0, NULL, NULL }
+};
diff -r 66e1654718fb src/libxinevdec/nal_parser.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/libxinevdec/nal_parser.c Tue Jun 24 14:06:43 2008 -0700
@@ -0,0 +1,520 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "nal_parser.h"
+
+struct buf_reader {
+    uint8_t *buf;
+    uint8_t *cur_pos;
+    int len;
+    int cur_offset;
+};
+
+static inline uint32_t read_bits(struct buf_reader *buf, int len);
+uint32_t read_exp_golomb(struct buf_reader *buf);
+int32_t read_exp_golomb_s(struct buf_reader *buf);
+void skip_scaling_list(struct buf_reader *buf, int size);
+int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal);
+uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps);
+uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps);
+uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal);
+
+
+static void decode_nal(uint8_t **ret, int *len_ret, uint8_t *buf, int buf_len)
+{
+    uint8_t *end = &buf[buf_len];
+    uint8_t *pos = malloc(buf_len);
+    
+    *ret = pos;
+    while(buf < end) {
+        if(buf < end - 3 && buf[0] == 0x00 && buf[1] == 0x00 &&
+           buf[2] == 0x03) {
+            
+            *pos++ = 0x00;
+            *pos++ = 0x00;
+            
+            buf += 3;
+            continue;
+        }
+        *pos++ = *buf++;
+    }
+    
+    *len_ret = pos - *ret;
+}
+
+/*uint32_t read_bits(struct buf_reader *buf, int len)
+{
+    uint32_t bits = 0x00;
+    int i, j;
+    for(i=0, j=0; i<len; i++) {
+        while(buf->cur_offset >= 8) {
+            buf->cur_pos++;
+            buf->cur_offset -= 8;
+        }
+        uint8_t bit = (*buf->cur_pos >> (7 - buf->cur_offset)) & 0x01;
+        bits |= ((uint32_t)bit) << i;
+        buf->cur_offset++;
+    }
+printf("ret: 0x%08x\n", bits);
+    return bits;
+}*/
+
+static inline uint32_t read_bits (struct buf_reader *buf, int len)
+{
+    static uint32_t i_mask[33] =
+    {  0x00,
+       0x01,      0x03,      0x07,      0x0f,
+       0x1f,      0x3f,      0x7f,      0xff,
+       0x1ff,     0x3ff,     0x7ff,     0xfff,
+       0x1fff,    0x3fff,    0x7fff,    0xffff,
+       0x1ffff,   0x3ffff,   0x7ffff,   0xfffff,
+       0x1fffff,  0x3fffff,  0x7fffff,  0xffffff,
+       0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
+       0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff};
+      
+    int i_shr;
+    uint32_t bits = 0;
+    
+    while(len > 0 && (buf->cur_pos - buf->buf) < buf->len) {
+        if((i_shr = buf->cur_offset-len) >= 0) {
+            bits |= (*buf->cur_pos >> i_shr)&i_mask[len];
+            buf->cur_offset -= len;
+            if(buf->cur_offset == 0) {
+                buf->cur_pos++;
+                buf->cur_offset = 8;
+            }
+            return bits;
+        } else {
+            bits |= (*buf->cur_pos & i_mask[buf->cur_offset]) << -i_shr;
+            len -= buf->cur_offset;
+            buf->cur_pos++;
+            buf->cur_offset = 8;
+        }
+    }
+    return bits;
+}
+
+uint32_t read_exp_golomb(struct buf_reader *buf)
+{
+    int leading_zero_bits = 0;
+
+    while(read_bits(buf, 1) == 0 && leading_zero_bits < 32)
+        leading_zero_bits++;
+
+    uint32_t code = (1<<leading_zero_bits) - 1 + read_bits(buf, leading_zero_bits);
+    return code;
+}
+
+int32_t read_exp_golomb_s(struct buf_reader *buf)
+{
+    uint32_t ue = read_exp_golomb(buf);
+    int32_t code = ue&0x01 ? (ue+1)/2 : -(ue/2);
+    return code;
+}
+
+int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal)
+{
+    if(buf->len < 1)
+        return -1;
+    int ret = -1;
+    
+    nal->nal_ref_idc = (buf->buf[0] >> 5) & 0x03;
+    nal->nal_unit_type = buf->buf[0] & 0x1f;
+    
+    buf->cur_pos = buf->buf + 1;
+    //printf("NAL: %d\n", nal->nal_unit_type);
+    
+    struct buf_reader ibuf;
+    ibuf.cur_offset = 8;
+    
+    switch(nal->nal_unit_type) {
+        case NAL_SPS:
+            decode_nal(&ibuf.buf, &ibuf.len, buf->cur_pos, buf->len-1);
+            ibuf.cur_pos = ibuf.buf;
+            if(!nal->sps)
+                nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp));
+            else
+                memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp));
+            
+            parse_sps(&ibuf, nal->sps);
+            free(ibuf.buf);
+            ret = NAL_SPS;
+            break;
+        case NAL_PPS:
+            if(!nal->pps)
+                nal->pps = malloc(sizeof(struct pic_parameter_set_rbsp));
+            else
+                memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp));
+            
+            parse_pps(buf, nal->pps);
+            ret = NAL_PPS;
+            break;
+        case NAL_SLICE:
+        case NAL_PART_A:
+        case NAL_PART_B:
+        case NAL_PART_C:
+        case NAL_SLICE_IDR:
+            if(nal->sps && nal->pps) {
+                if(!nal->slc)
+                    nal->slc = malloc(sizeof(struct slice_header));
+                else
+                    memset(nal->slc, 0x00, sizeof(struct slice_header));
+                
+                parse_slice_header(buf, nal);
+                ret = nal->nal_unit_type;
+            }
+            break;
+        default:
+            ret = nal->nal_unit_type;
+            break;
+    }
+    
+    return ret;
+}
+
+void skip_scaling_list(struct buf_reader *buf, int size)
+{
+    int i;
+    for(i = 0; i < size; i++) {
+        read_exp_golomb_s(buf);
+    }
+}
+
+uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps)
+{
+    sps->profile_idc = buf->buf[0];
+    sps->constraint_setN_flag = (buf->buf[1] >> 4) & 0x0f;
+    sps->level_idc = buf->buf[2];
+    
+    buf->cur_pos = buf->buf+3;
+    sps->seq_parameter_set_id = read_exp_golomb(buf);
+    if(sps->profile_idc == 100 || sps->profile_idc == 110 ||
+       sps->profile_idc == 122 || sps->profile_idc == 144) {
+        sps->chroma_format_idc = read_exp_golomb(buf);
+        if(sps->chroma_format_idc == 3) {
+            sps->residual_colour_transform_flag = read_bits(buf, 1);
+        }
+
+        sps->bit_depth_luma_minus8 = read_exp_golomb(buf);
+        sps->bit_depth_chroma_minus8 = read_exp_golomb(buf);
+        sps->qpprime_y_zero_transform_bypass_flag = read_bits(buf, 1);
+        sps->seq_scaling_matrix_present_flag = read_bits(buf, 1);
+        if(sps->seq_scaling_matrix_present_flag) {
+            sps->seq_scaling_lists_present_flag = read_bits(buf, 8);
+            int i;
+            for(i=0; i<8; i++) {
+                if((sps->seq_scaling_lists_present_flag >> (7-i)) & 0x01) {
+                    // NOTE: just skip the scaling lists, as we do not
+                    // need their data for parsing
+                    if(i<6)
+                        skip_scaling_list(buf, 16);
+                    else
+                        skip_scaling_list(buf, 64);
+                }
+            }
+        }
+    }
+    
+    sps->log2_max_frame_num_minus4 = read_exp_golomb(buf);
+
+    sps->pic_order_cnt_type = read_exp_golomb(buf);
+    if(!sps->pic_order_cnt_type)
+        sps->log2_max_pic_order_cnt_lsb_minus4 = read_exp_golomb(buf);
+    else {
+        sps->delta_pic_order_always_zero_flag = read_bits(buf, 1);
+        sps->offset_for_non_ref_pic = read_exp_golomb_s(buf);
+        sps->offset_for_top_to_bottom_field = read_exp_golomb_s(buf);
+        sps->num_ref_frames_in_pic_order_cnt_cycle = read_exp_golomb(buf);
+        int i;
+        for(i=0; i<sps->num_ref_frames_in_pic_order_cnt_cycle; i++) {
+            sps->offset_for_ref_frame[i] = read_exp_golomb_s(buf);
+        }
+    }
+    sps->num_ref_frames = read_exp_golomb(buf);
+    sps->gaps_in_frame_num_value_allowed_flag = read_bits(buf, 1);
+    
+    /*sps->pic_width_in_mbs_minus1 = read_exp_golomb(buf);
+    sps->pic_height_in_map_units_minus1 = read_exp_golomb(buf);*/
+    sps->pic_width = 16 * (read_exp_golomb(buf) + 1);
+    sps->pic_height = 16 * (read_exp_golomb(buf) + 1);
+    
+    sps->frame_mbs_only_flag = read_bits(buf, 1);
+
+    /* compute the height correctly even for interlaced material */
+    sps->pic_height = (2-sps->frame_mbs_only_flag) * sps->pic_height;
+    //printf("res: %dx%d\n", sps->pic_width, sps->pic_height);
+
+    if(!sps->frame_mbs_only_flag)
+        sps->mb_adaptive_frame_field_flag = read_bits(buf, 1);
+    
+    sps->direct_8x8_inference_flag = read_bits(buf, 1);
+    sps->frame_cropping_flag = read_bits(buf, 1);
+    if(sps->frame_cropping_flag) {
+        sps->frame_crop_left_offset = read_exp_golomb(buf);
+        sps->frame_crop_right_offset = read_exp_golomb(buf);
+        sps->frame_crop_top_offset = read_exp_golomb(buf);
+        sps->frame_crop_bottom_offset = read_exp_golomb(buf);
+    }
+    sps->vui_parameters_present_flag = read_bits(buf, 1);
+    /*if(sps->vui_parameters_present_flag)
+        printf("ERROR: vui_parameters is not implemented\n");*/
+    
+    return 0;
+}
+
+uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps)
+{
+    pps->pic_parameter_set_id = read_exp_golomb(buf);
+    pps->seq_parameter_set_id = read_exp_golomb(buf);
+    pps->entropy_coding_mode_flag = read_bits(buf, 1);
+    pps->pic_order_present_flag = read_bits(buf, 1);
+    return 0;
+}
+
+uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal)
+{
+    struct seq_parameter_set_rbsp *sps = nal->sps;
+    struct pic_parameter_set_rbsp *pps = nal->pps;
+    struct slice_header *slc = nal->slc;
+    if(!sps || !pps)
+        return -1;
+
+    slc->first_mb_in_slice = read_exp_golomb(buf);
+    slc->slice_type = read_exp_golomb(buf);
+    slc->pic_parameter_set_id = read_exp_golomb(buf);
+    slc->frame_num = read_bits(buf, sps->log2_max_frame_num_minus4 + 4);
+    if(!sps->frame_mbs_only_flag) {
+        slc->field_pic_flag = read_bits(buf, 1);
+        if(slc->field_pic_flag)
+            slc->bottom_field_flag = read_bits(buf, 1);
+        else
+            slc->bottom_field_flag = -1;
+    } else {
+        slc->field_pic_flag = 0;
+        slc->bottom_field_flag = -1;
+    }
+    
+    if(nal->nal_unit_type == NAL_SLICE_IDR)
+        slc->idr_pic_id = read_exp_golomb(buf);
+    
+    if(!sps->pic_order_cnt_type) {
+        slc->pic_order_cnt_lsb = read_bits(buf, sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
+        if(pps->pic_order_present_flag && !slc->field_pic_flag)
+            slc->delta_pic_order_cnt_bottom = read_exp_golomb_s(buf);
+    } else if (sps->pic_order_cnt_type == 1) {
+        slc->delta_pic_order_cnt[0] = read_exp_golomb_s(buf);
+        if(pps->pic_order_present_flag && !slc->field_pic_flag)
+            slc->delta_pic_order_cnt[1] = read_exp_golomb_s(buf);
+    }
+    /* do not need more information for packetizing */
+    
+    return 0;
+}
+
+
+
+/* ----------------- NAL parser ----------------- */
+
+struct nal_parser* init_parser()
+{
+    struct nal_parser *parser = malloc(sizeof(struct nal_parser));
+    memset(parser->buf, 0x00, MAX_FRAME_SIZE);
+    parser->buf_len = 0;
+    parser->found_sps = 0;
+    parser->found_pps = 0;
+    parser->nal0 = malloc(sizeof(struct nal_unit));
+    memset(parser->nal0, 0x00, sizeof(struct nal_unit));
+    parser->nal1 = malloc(sizeof(struct nal_unit));
+    memset(parser->nal1, 0x00, sizeof(struct nal_unit));
+    parser->current_nal = parser->nal0;
+    parser->last_nal = parser->nal1;
+    
+    parser->last_nal_res = 0;
+    parser->slice = 0;
+    parser->field = -1;
+    parser->have_top = 0;
+    
+    return parser;
+}
+
+void free_parser(struct nal_parser *parser)
+{
+    free(parser->nal0);
+    free(parser->nal1);
+    free(parser);    
+}
+
+int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len,
+                uint8_t **ret_buf, int *ret_len)
+{
+    int next_nal;
+    int parsed_len = 0;
+    int search_offset = 0;
+
+    while((next_nal = seek_for_nal(inbuf+search_offset, inbuf_len-parsed_len)) >= 0) {
+        // save buffer up to the nal-start
+        if(parser->buf_len + next_nal + search_offset > MAX_FRAME_SIZE) {
+            printf("buf underrun!!\n");
+            *ret_len = 0;
+            *ret_buf = NULL;
+            return parsed_len;
+        }
+        //if(parser->last_nal_res != 1) {
+            xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, next_nal+search_offset);
+            parser->buf_len += next_nal+search_offset;
+        //}
+        inbuf += next_nal+search_offset;
+        parsed_len += next_nal+search_offset;
+        
+        if((parser->last_nal_res = parse_nal(inbuf+4, inbuf_len-parsed_len, parser)) == 1
+            && parser->buf_len>0) {
+            // parse_nal returned 1 --> detected a frame_boundary
+            *ret_buf = malloc(parser->buf_len);
+            xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len);
+            *ret_len = parser->buf_len;
+        
+            //memset(parser->buf, 0x00, parser->buf_len);
+            parser->buf_len = 0;
+            parser->last_nal_res = 0;
+            return parsed_len;
+        }
+
+        search_offset = 4;
+    }
+    
+    // no further NAL found, copy the rest of the stream
+    // into the buffer
+//    if(parser->last_nal_res != 1) {
+        xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, inbuf_len-parsed_len);
+        parser->buf_len += inbuf_len-parsed_len;
+//    }
+    
+    parsed_len += (inbuf_len-parsed_len);
+    *ret_len = 0;
+    *ret_buf = NULL;
+
+    return parsed_len;
+}
+
+int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser)
+{
+    struct buf_reader bufr;
+    
+    bufr.buf = buf;
+    bufr.cur_pos = buf;
+    bufr.cur_offset = 8;
+    bufr.len = buf_len;
+    
+    struct nal_unit *nal = parser->current_nal;
+    struct nal_unit *last_nal = parser->last_nal;
+    
+    int res = parse_nal_header(&bufr, nal);
+
+    if(res >= NAL_SLICE && res <= NAL_SLICE_IDR) {
+        // now detect if it's a new frame!
+        int ret = 0;
+        if(nal->slc->field_pic_flag == 1)
+            parser->field = nal->slc->bottom_field_flag;
+        else {
+            parser->have_top = 1;
+            parser->field = -1;
+        }
+        
+        if(nal->slc->field_pic_flag == 1 && nal->slc->bottom_field_flag == 0)
+            parser->have_top = 1;
+                    
+        parser->slice = 1;
+        
+        if(nal->slc == NULL || last_nal->slc == NULL) {
+            ret = 1;
+        }
+        if(nal->slc && last_nal->slc &&
+           (nal->slc->frame_num != last_nal->slc->frame_num)) {
+            ret = 1;
+        }
+        if(nal->slc && last_nal->slc &&
+           (nal->slc->pic_parameter_set_id != last_nal->slc->pic_parameter_set_id)) {
+            ret = 1;
+        }
+        if(nal->slc && last_nal->slc &&
+           (nal->slc->field_pic_flag != last_nal->slc->field_pic_flag)) {
+            ret = 1;
+        }
+        if(nal->slc && last_nal->slc &&
+           (nal->slc->bottom_field_flag != -1 &&
+                last_nal->slc->bottom_field_flag != -1 &&
+                nal->slc->bottom_field_flag != last_nal->slc->bottom_field_flag)) {
+            ret = 1;
+        }
+        if(nal->nal_ref_idc != last_nal->nal_ref_idc &&
+                (nal->nal_ref_idc == 0 || last_nal->nal_ref_idc == 0)) {
+            ret = 1;
+        }
+        if(nal->sps && nal->slc && last_nal->slc &&
+           (nal->sps->pic_order_cnt_type == 0 &&
+                (nal->slc->pic_order_cnt_lsb != last_nal->slc->pic_order_cnt_lsb ||
+                 nal->slc->delta_pic_order_cnt_bottom != last_nal->slc->delta_pic_order_cnt_bottom))) {
+            ret = 1;
+        }
+        if(nal->slc && last_nal->slc &&
+           (nal->sps->pic_order_cnt_type == 1 &&
+                (nal->slc->delta_pic_order_cnt[0] != last_nal->slc->delta_pic_order_cnt[0] ||
+                nal->slc->delta_pic_order_cnt[1] != last_nal->slc->delta_pic_order_cnt[1]))) {
+            ret = 1;
+        }
+        if(nal->nal_unit_type != last_nal->nal_unit_type &&
+                (nal->nal_unit_type == 5 || last_nal->nal_unit_type == 5)) {
+            ret = 1;
+        }
+        if(nal->slc && last_nal->slc &&
+           (nal->nal_unit_type == 5 && last_nal->nal_unit_type == 5 &&
+                nal->slc->idr_pic_id != last_nal->slc->idr_pic_id)) {
+            ret = 1;
+        }
+        
+        if(parser->current_nal == parser->nal0) {
+            parser->current_nal = parser->nal1;
+            parser->last_nal = parser->nal0;
+        }
+        else {
+            parser->current_nal = parser->nal0;
+            parser->last_nal = parser->nal1;
+        }
+        if(parser->current_nal->sps == NULL)
+            parser->current_nal->sps = parser->last_nal->sps;
+        if(parser->current_nal->pps == NULL)
+            parser->current_nal->pps = parser->last_nal->pps;
+        
+        /*if(ret)
+            parser->slice = 0;*/
+        /*if(parser->slice && parser->have_top && parser->field != 0) {
+            parser->have_frame = 1;
+            parser->have_top = 0;
+            parser->slice = 0;
+            return ret;
+        }*/
+        return 0;
+    } else if(res == NAL_PPS || res == NAL_SPS) {
+        return 1;
+    } else if (res == NAL_AU_DELIMITER || res == NAL_SEI ||
+               (res >= 13 && res <= 18)) {
+        //printf("New Frame\n");
+        return 1;
+    }
+    
+    return 0;
+}
+
+int seek_for_nal(uint8_t *buf, int buf_len)
+{
+    int i;
+    for(i=0; i<buf_len-3; i++) {
+        if(buf[i] == 0x00 && buf[i+1] == 0x00 &&
+           buf[i+2] == 0x00 && buf[i+3] == 0x01) {
+            //printf("found nal at: %d\n", i);
+            return i;
+           }
+    }
+    
+    return -1;
+}
diff -r 66e1654718fb src/libxinevdec/nal_parser.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/libxinevdec/nal_parser.h Tue Jun 24 14:06:43 2008 -0700
@@ -0,0 +1,141 @@
+#ifndef NAL_PARSER_H_
+#define NAL_PARSER_H_
+
+#include <stdlib.h>
+
+#include "xine_internal.h"
+
+enum nal_unit_types {
+    NAL_UNSPECIFIED = 0,
+    NAL_SLICE,
+    NAL_PART_A,
+    NAL_PART_B,
+    NAL_PART_C,
+    NAL_SLICE_IDR,
+    NAL_SEI,
+    NAL_SPS,
+    NAL_PPS,
+    NAL_AU_DELIMITER,
+    NAL_END_OF_SEQUENCE,
+    NAL_END_OF_STREAM,
+    NAL_FILLER_DATA,
+    NAL_SPS_EXT
+};
+
+
+
+struct nal_unit {
+    uint8_t     nal_ref_idc;    // 0x03
+    uint8_t     nal_unit_type;  // 0x1f
+    
+    struct seq_parameter_set_rbsp   *sps;
+    struct pic_parameter_set_rbsp   *pps;
+    struct slice_header             *slc;
+};
+
+struct seq_parameter_set_rbsp {
+    uint8_t     profile_idc;            // 0xff
+    uint8_t     constraint_setN_flag;   // 0x0f
+    uint8_t     level_idc;              // 0xff
+    uint32_t    seq_parameter_set_id;
+    uint32_t    chroma_format_idc;
+    uint8_t     residual_colour_transform_flag;  // 0x01
+    uint32_t    bit_depth_luma_minus8;
+    uint32_t    bit_depth_chroma_minus8;
+    uint8_t     qpprime_y_zero_transform_bypass_flag;
+    uint8_t     seq_scaling_matrix_present_flag;
+    uint8_t     seq_scaling_lists_present_flag;  // each bit = 1 list flag
+    // TODO: here would be the scaling lists...
+    uint32_t    log2_max_frame_num_minus4;
+    uint32_t    pic_order_cnt_type;
+    // if pic_order_cnt_type==0
+    uint32_t    log2_max_pic_order_cnt_lsb_minus4;
+    // else
+    uint8_t     delta_pic_order_always_zero_flag;
+    int32_t     offset_for_non_ref_pic;
+    int32_t     offset_for_top_to_bottom_field;
+    uint8_t     num_ref_frames_in_pic_order_cnt_cycle;
+    int32_t     offset_for_ref_frame[256];
+    // TODO: some more ignored here
+    uint32_t    num_ref_frames;
+    uint8_t     gaps_in_frame_num_value_allowed_flag;
+    /*uint32_t    pic_width_in_mbs_minus1;
+    uint32_t    pic_height_in_map_units_minus1;*/
+    uint32_t    pic_width;
+    uint32_t    pic_height;
+    uint8_t     frame_mbs_only_flag;
+    uint8_t     mb_adaptive_frame_field_flag;
+    uint8_t     direct_8x8_inference_flag;
+    uint8_t     frame_cropping_flag;
+    uint32_t    frame_crop_left_offset;
+    uint32_t    frame_crop_right_offset;
+    uint32_t    frame_crop_top_offset;
+    uint32_t    frame_crop_bottom_offset;
+    uint8_t     vui_parameters_present_flag;
+    // TODO: add vui_parameters, rtbsp_trailing_bits
+            
+};
+
+struct pic_parameter_set_rbsp {
+    uint32_t    pic_parameter_set_id;
+    uint32_t    seq_parameter_set_id;
+    uint8_t     entropy_coding_mode_flag;
+    uint8_t     pic_order_present_flag;
+    
+    /* we ignore further data, because it's not needed
+        for packetization */
+};
+
+struct slice_header {
+    uint32_t    first_mb_in_slice;
+    uint32_t    slice_type;
+    uint32_t    pic_parameter_set_id;
+    uint32_t    frame_num;
+    int8_t      field_pic_flag;
+    int8_t      bottom_field_flag;
+    uint32_t    idr_pic_id;
+    
+    /* sps->pic_order_cnt_type == 0 */
+    uint32_t    pic_order_cnt_lsb;
+    int32_t     delta_pic_order_cnt_bottom;
+    /* sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag */
+    int32_t     delta_pic_order_cnt[2];
+    
+    /* not needed for packetizing */
+    /*int32_t     redundant_pic_cnt;
+    uint8_t     direct_spatial_mv_pred_flag;
+    uint8_t     num_ref_idx_active_override_flag;
+    uint32_t    num_ref_idx_l0_active_minus1;
+    uint32_t    num_ref_idx_l1_active_minus1;*/
+    
+};
+
+
+#define MAX_FRAME_SIZE  1024*1024
+
+struct nal_parser {
+    uint8_t buf[MAX_FRAME_SIZE];
+    int buf_len;
+    int found_sps;
+    int found_pps;
+    int last_nal_res;
+    int field; // 0=top, 1=bottom, -1=both
+    int slice;
+    int have_top;
+    int have_frame;
+    struct nal_unit *nal0;
+    struct nal_unit *nal1;
+    struct nal_unit *current_nal;
+    struct nal_unit *last_nal;
+};
+
+int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser);
+
+int seek_for_nal(uint8_t *buf, int buf_len);
+
+struct nal_parser* init_parser();
+void free_parser(struct nal_parser *parser);
+int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len,
+                uint8_t **ret_buf, int *ret_len);
+
+#endif

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
xine-devel mailing list
xine-devel@...
https://lists.sourceforge.net/lists/listinfo/xine-devel

Re: PATCH: Add support for CoreAVC via dshowserver

by Bastien Nocera :: Rate this Message:

| View Threaded | Show Only this Message

On Tue, 2008-06-24 at 14:19 -0700, Alan Nisota wrote:
> I was asked to send this patch to xine-devel by Darren Salt.
>
> It implements support for communicating with the dshowserver
> (coreavc-for-linux.googlecode.com)
> This is mainly useful for using CoreAVC in Linux (a very fast H264
> decoder), however it could be made to work with other win32 codecs.

Does dshowserver support the "other" Win32 DLLs?



-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
xine-devel mailing list
xine-devel@...
https://lists.sourceforge.net/lists/listinfo/xine-devel

Re: PATCH: Add support for CoreAVC via dshowserver

by Darren Salt :: Rate this Message:

| View Threaded | Show Only this Message

I demand that Alan Nisota may or may not have written...

> I was asked to send this patch to xine-devel by Darren Salt.
[snip]
> I have addressed many of the issues he requested I address except for:
>    * The plugin description should be translatable (use N_() for this)
> I don't see any examples of other plugins doing this, so I wasn't sure
> how to proceed.

That's really 1.2-only, but I see no harm in doing that in 1.1 as well.

>    * Documentation patches
> I have no idea what he wanted here.

Adding and/or modifying files in doc and possibly doc/faq. (A separate patch
for this is fine.)

>    * Fixed-size buffers should be avoided wherever practical, e.g. use
>      asprintf() where it makes sense to do so.
> I did move the constant-sized strings (snprintf) to use asprintf as
> requested, but this really didn't feel like the right thing to do to me.

A fixed-size buffer is fine if you can be sure that it'll never be
overflowed...

It occurs to me, however, that being able to configure the location of
dshowserver might be useful (with the default determined automatically on
first run, if it's not configured at build time).

[snip]
--
| Darren Salt    | linux or ds at              | nr. Ashington, | Toon
| RISC OS, Linux | youmustbejoking,demon,co,uk | Northumberland | Army
| + Use more efficient products. Use less.          BE MORE ENERGY EFFICIENT.

The soul would have no rainbow had the eyes no tears.

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
xine-devel mailing list
xine-devel@...
https://lists.sourceforge.net/lists/listinfo/xine-devel

Re: PATCH: Add support for CoreAVC via dshowserver

by Igor Nikanov-4 :: Rate this Message:

| View Threaded | Show Only this Message

> >    * Documentation patches
> > I have no idea what he wanted here.
>
> Adding and/or modifying files in doc and possibly doc/faq. (A separate patch
> for this is fine.)

I think your wiki has very useful information for doc/faq

I propose to discuss the issues with xine and this dshowserver patch in xine-user mail list. I already have sent here my
bug report :)

>
> >    * Fixed-size buffers should be avoided wherever practical, e.g. use
> >      asprintf() where it makes sense to do so.
> > I did move the constant-sized strings (snprintf) to use asprintf as
> > requested, but this really didn't feel like the right thing to do to me.
>
> A fixed-size buffer is fine if you can be sure that it'll never be
> overflowed...
>
> It occurs to me, however, that being able to configure the location of
> dshowserver might be useful (with the default determined automatically on
> first run, if it's not configured at build time).
>
> [snip]


-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
xine-devel mailing list
xine-devel@...
https://lists.sourceforge.net/lists/listinfo/xine-devel

Re: PATCH: Add support for CoreAVC via dshowserver

by Igor Nikanov-4 :: Rate this Message:

| View Threaded | Show Only this Message

from coreavc-for-linux@...

Дата: Thu, 26 Jun 2008 09:58:53 +0100
От: Morfsta <morfsta@...>
Кому: alannisota@...
Копия: coreavc-for-linux@...
Тема: CoreAVC Patch for xine


Hi Alan,

Thanks for continuing to work on the CoreAVC patch for xine.

One thing I have noticed is that your aspect ratio setting
(this->ratio), I think, is incorrect.

You always seem to set it to the same value based on the width and
height of the channel which is:

this->ratio = (double)this->width/(double)this->height;

Ideally, this should come from the stream and can be found in the SPS.

In my dirty xine-lib-1.2 patch the following code worked in the
NAL/SPS parser: -

+       if (br_get_bit(&br)) { /* VUI parameters */
+          if (br_get_bit(&br)) { /* Aspect Info */
+             uint32_t aspect_ratio_idc = br_get_u8(&br);
+             printf("H.264 SPS: -> Aspect Ratio IDC %d\n", aspect_ratio_idc);
+             const uint32_t Extended_SAR = 255;
+             if (aspect_ratio_idc == Extended_SAR) {
+                  uint32_t sar_width = br_get_u16(&br);
+                  uint32_t sar_height = br_get_u16(&br);
+                 sps->ratio = (float) sar_width / sar_height;
+                 sps->ratio = (float) ( (float) sar_width /
sar_height ) * ( (float) sps->width / sps->height ) ;
+                  printf("H.264 SPS: -> SAR_Size = %dx%d\n",
sar_width, sar_height);
+                 printf("H.264 SPS: -> Ratio = %f\n", sps->ratio);
+            } else {
+                 AVRational sar = pixel_aspect[aspect_ratio_idc];
+                 printf("H.264 SPS: -> Pixel Aspect = %d / %d\n",
sar.num, sar.den);
+                 sps->ratio = (float) ( (float) sar.num / sar.den ) *
( (float) sps->width / sps->height ) ;
+                 printf("H.264 SPS: -> Ratio = %f\n", sps->ratio);
+             }
+          }
+       }

Of course you can then copy sps->ratio to this->ratio.

Also, is there a CHANGELOG or any way of tracking updates to your
patch? I don't know yet if all the debugging and core information I
sent you awhile ago was used or whether any changes have been made.

Hope this helps,

Kind Regards,

Morfsta


-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
xine-devel mailing list
xine-devel@...
https://lists.sourceforge.net/lists/listinfo/xine-devel