st/omx/tizonia: Add H.264 decoder
authorGurkirpal Singh <gurkirpal204@gmail.com>
Sat, 20 Jan 2018 00:44:17 +0000 (06:14 +0530)
committerJulien Isorce <jisorce@oblong.com>
Tue, 6 Mar 2018 14:29:42 +0000 (14:29 +0000)
v2: Refactor out screen functions to st/omx

Example Gstreamer pipeline :
gst-launch-1.0 filesrc location=movie.mp4 ! qtdemux ! h264parse ! omxh264dec ! videoconvert ! ximagesink

Acked-by: Leo Liu <leo.liu@amd.com>
Reviewed-by: Julien Isorce <julien.isorce@gmail.com>
25 files changed:
meson.build
src/gallium/state_trackers/omx/Makefile.sources
src/gallium/state_trackers/omx/bellagio/entrypoint.c
src/gallium/state_trackers/omx/bellagio/entrypoint.h
src/gallium/state_trackers/omx/bellagio/vid_dec.c
src/gallium/state_trackers/omx/bellagio/vid_dec.h
src/gallium/state_trackers/omx/bellagio/vid_dec_h264.c
src/gallium/state_trackers/omx/bellagio/vid_enc.c
src/gallium/state_trackers/omx/meson.build
src/gallium/state_trackers/omx/tizonia/Makefile.sources
src/gallium/state_trackers/omx/tizonia/entrypoint.c
src/gallium/state_trackers/omx/tizonia/h264d.c [new file with mode: 0644]
src/gallium/state_trackers/omx/tizonia/h264d.h [new file with mode: 0644]
src/gallium/state_trackers/omx/tizonia/h264dinport.c [new file with mode: 0644]
src/gallium/state_trackers/omx/tizonia/h264dinport.h [new file with mode: 0644]
src/gallium/state_trackers/omx/tizonia/h264dinport_decls.h [new file with mode: 0644]
src/gallium/state_trackers/omx/tizonia/h264dprc.c [new file with mode: 0644]
src/gallium/state_trackers/omx/tizonia/h264dprc.h [new file with mode: 0644]
src/gallium/state_trackers/omx/tizonia/names.h [new file with mode: 0644]
src/gallium/state_trackers/omx/vid_dec_common.c [new file with mode: 0644]
src/gallium/state_trackers/omx/vid_dec_common.h [new file with mode: 0644]
src/gallium/state_trackers/omx/vid_dec_h264_common.c [new file with mode: 0644]
src/gallium/state_trackers/omx/vid_dec_h264_common.h [new file with mode: 0644]
src/gallium/state_trackers/omx/vid_omx_common.c [new file with mode: 0644]
src/gallium/state_trackers/omx/vid_omx_common.h [new file with mode: 0644]

index 6a13e8000841ed092912a75a5d0514d623ca1c36..dd2fa603829f697e9f4ba571e529edb27ffd0a23 100644 (file)
@@ -487,8 +487,10 @@ gallium_omx = _omx
 dep_omx = []
 dep_omx_other = []
 if gallium_omx == 'bellagio'
+  pre_args += '-DENABLE_ST_OMX_BELLAGIO'
   dep_omx = dependency('libomxil-bellagio')
 elif gallium_omx == 'tizonia'
+  pre_args += '-DENABLE_ST_OMX_TIZONIA'
   dep_omx = dependency('libtizonia', version : '>= 0.10.0')
   dep_omx_other = [
     dependency('libtizplatform'),
index 9103ca899dbc2470d467c894565220c3cab11cae..ba9b0beec99de6632a1d709b3fc35257192b5609 100644 (file)
@@ -1 +1,7 @@
-C_SOURCES :=
+C_SOURCES := \
+       vid_dec_common.c \
+       vid_dec_common.h \
+       vid_dec_h264_common.c \
+       vid_dec_h264_common.h \
+       vid_omx_common.c \
+       vid_omx_common.h
index 251cc7d65d52fba8cf38c8f7e7e494dc470016bb..5c75e8dadaa401bb77a35f8ea9d14cd6e79d3ea5 100644 (file)
  *
  */
 
-#include <assert.h>
-#include <string.h>
-#include <stdbool.h>
-
-#if defined(HAVE_X11_PLATFORM)
-#include <X11/Xlib.h>
-#else
-#define XOpenDisplay(x) NULL
-#define XCloseDisplay(x)
-#define Display void
-#endif
-
-#include "os/os_thread.h"
-#include "util/u_memory.h"
-#include "loader/loader.h"
-
 #include "entrypoint.h"
 #include "vid_dec.h"
 #include "vid_enc.h"
 
-static mtx_t omx_lock = _MTX_INITIALIZER_NP;
-static Display *omx_display = NULL;
-static struct vl_screen *omx_screen = NULL;
-static unsigned omx_usecount = 0;
-static const char *omx_render_node = NULL;
-static int drm_fd;
-
 int omx_component_library_Setup(stLoaderComponentType **stComponents)
 {
    OMX_ERRORTYPE r;
@@ -78,66 +55,6 @@ int omx_component_library_Setup(stLoaderComponentType **stComponents)
    return 2;
 }
 
-struct vl_screen *omx_get_screen(void)
-{
-   static bool first_time = true;
-   mtx_lock(&omx_lock);
-
-   if (!omx_screen) {
-      if (first_time) {
-         omx_render_node = debug_get_option("OMX_RENDER_NODE", NULL);
-         first_time = false;
-      }
-      if (omx_render_node) {
-         drm_fd = loader_open_device(omx_render_node);
-         if (drm_fd < 0)
-            goto error;
-
-         omx_screen = vl_drm_screen_create(drm_fd);
-         if (!omx_screen) {
-            close(drm_fd);
-            goto error;
-         }
-      } else {
-         omx_display = XOpenDisplay(NULL);
-         if (!omx_display)
-            goto error;
-
-         omx_screen = vl_dri3_screen_create(omx_display, 0);
-         if (!omx_screen)
-            omx_screen = vl_dri2_screen_create(omx_display, 0);
-         if (!omx_screen) {
-            XCloseDisplay(omx_display);
-            goto error;
-         }
-      }
-   }
-
-   ++omx_usecount;
-
-   mtx_unlock(&omx_lock);
-   return omx_screen;
-
-error:
-   mtx_unlock(&omx_lock);
-   return NULL;
-}
-
-void omx_put_screen(void)
-{
-   mtx_lock(&omx_lock);
-   if ((--omx_usecount) == 0) {
-      omx_screen->destroy(omx_screen);
-      omx_screen = NULL;
-
-      if (omx_render_node)
-         close(drm_fd);
-      else
-         XCloseDisplay(omx_display);
-   }
-   mtx_unlock(&omx_lock);
-}
-
 OMX_ERRORTYPE omx_workaround_Destructor(OMX_COMPONENTTYPE *comp)
 {
    omx_base_component_PrivateType* priv = (omx_base_component_PrivateType*)comp->pComponentPrivate;
index 7625d7a5b031d35ed1e758b14eee76137e485373..d566d1eb5a3c5369851a63e2a2fad5636b79b2e6 100644 (file)
@@ -40,9 +40,6 @@
 
 PUBLIC extern int omx_component_library_Setup(stLoaderComponentType **stComponents);
 
-struct vl_screen *omx_get_screen(void);
-void omx_put_screen(void);
-
 OMX_ERRORTYPE omx_workaround_Destructor(OMX_COMPONENTTYPE *comp);
 
 #endif
index f9fe19f63f0e8d64d3d7f7bb33f03327defac38f..65e612a57fe8fc27917dc4579052bdd18064991d 100644 (file)
@@ -53,6 +53,8 @@
 
 #include "entrypoint.h"
 #include "vid_dec.h"
+#include "vid_omx_common.h"
+#include "vid_dec_h264_common.h"
 
 static OMX_ERRORTYPE vid_dec_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name);
 static OMX_ERRORTYPE vid_dec_Destructor(OMX_COMPONENTTYPE *comp);
@@ -420,50 +422,6 @@ static OMX_ERRORTYPE vid_dec_MessageHandler(OMX_COMPONENTTYPE* comp, internalReq
    return omx_base_component_MessageHandler(comp, msg);
 }
 
-void vid_dec_NeedTarget(vid_dec_PrivateType *priv)
-{
-   struct pipe_video_buffer templat = {};
-   struct vl_screen *omx_screen;
-   struct pipe_screen *pscreen;
-
-   omx_screen = priv->screen;
-   assert(omx_screen);
-
-   pscreen = omx_screen->pscreen;
-   assert(pscreen);
-
-   if (!priv->target) {
-      memset(&templat, 0, sizeof(templat));
-
-      templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
-      templat.width = priv->codec->width;
-      templat.height = priv->codec->height;
-      templat.buffer_format = pscreen->get_video_param(
-            pscreen,
-            PIPE_VIDEO_PROFILE_UNKNOWN,
-            PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
-            PIPE_VIDEO_CAP_PREFERED_FORMAT
-      );
-      templat.interlaced = pscreen->get_video_param(
-          pscreen,
-          PIPE_VIDEO_PROFILE_UNKNOWN,
-          PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
-          PIPE_VIDEO_CAP_PREFERS_INTERLACED
-      );
-      priv->target = priv->pipe->create_video_buffer(priv->pipe, &templat);
-   }
-}
-
-static void vid_dec_FreeInputPortPrivate(OMX_BUFFERHEADERTYPE *buf)
-{
-   struct pipe_video_buffer *vbuf = buf->pInputPortPrivate;
-   if (!vbuf)
-      return;
-
-   vbuf->destroy(vbuf);
-   buf->pInputPortPrivate = NULL;
-}
-
 static OMX_ERRORTYPE vid_dec_DecodeBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf)
 {
    OMX_COMPONENTTYPE* comp = port->standCompContainer;
@@ -541,104 +499,10 @@ static OMX_ERRORTYPE vid_dec_FreeDecBuffer(omx_base_PortType *port, OMX_U32 idx,
    return base_port_FreeBuffer(port, idx, buf);
 }
 
-static void vid_dec_FillOutput(vid_dec_PrivateType *priv, struct pipe_video_buffer *buf,
-                               OMX_BUFFERHEADERTYPE* output)
-{
-   omx_base_PortType *port = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX];
-   OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video;
-
-   struct pipe_sampler_view **views;
-   unsigned i, j;
-   unsigned width, height;
-
-   views = buf->get_sampler_view_planes(buf);
-
-   for (i = 0; i < 2 /* NV12 */; i++) {
-      if (!views[i]) continue;
-      width = def->nFrameWidth;
-      height = def->nFrameHeight;
-      vl_video_buffer_adjust_size(&width, &height, i, buf->chroma_format, buf->interlaced);
-      for (j = 0; j < views[i]->texture->array_size; ++j) {
-         struct pipe_box box = {0, 0, j, width, height, 1};
-         struct pipe_transfer *transfer;
-         uint8_t *map, *dst;
-         map = priv->pipe->transfer_map(priv->pipe, views[i]->texture, 0,
-                  PIPE_TRANSFER_READ, &box, &transfer);
-         if (!map)
-            return;
-
-         dst = ((uint8_t*)output->pBuffer + output->nOffset) + j * def->nStride +
-               i * def->nFrameWidth * def->nFrameHeight;
-         util_copy_rect(dst,
-            views[i]->texture->format,
-            def->nStride * views[i]->texture->array_size, 0, 0,
-            box.width, box.height, map, transfer->stride, 0, 0);
-
-         pipe_transfer_unmap(priv->pipe, transfer);
-      }
-   }
-}
-
 static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input,
                                  OMX_BUFFERHEADERTYPE* output)
 {
    vid_dec_PrivateType *priv = comp->pComponentPrivate;
-   bool eos = !!(input->nFlags & OMX_BUFFERFLAG_EOS);
-   OMX_TICKS timestamp;
-
-   if (!input->pInputPortPrivate) {
-      input->pInputPortPrivate = priv->Flush(priv, &timestamp);
-      if (timestamp != OMX_VID_DEC_TIMESTAMP_INVALID)
-         input->nTimeStamp = timestamp;
-   }
-
-   if (input->pInputPortPrivate) {
-      if (output->pInputPortPrivate && !priv->disable_tunnel) {
-         struct pipe_video_buffer *tmp, *vbuf, *new_vbuf;
-
-         tmp = output->pOutputPortPrivate;
-         vbuf = input->pInputPortPrivate;
-         if (vbuf->interlaced) {
-            /* re-allocate the progressive buffer */
-            omx_base_video_PortType *port;
-            struct pipe_video_buffer templat = {};
-            struct u_rect src_rect, dst_rect;
-
-            port = (omx_base_video_PortType *)
-                    priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];
-            memset(&templat, 0, sizeof(templat));
-            templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
-            templat.width = port->sPortParam.format.video.nFrameWidth;
-            templat.height = port->sPortParam.format.video.nFrameHeight;
-            templat.buffer_format = PIPE_FORMAT_NV12;
-            templat.interlaced = false;
-            new_vbuf = priv->pipe->create_video_buffer(priv->pipe, &templat);
-
-            /* convert the interlaced to the progressive */
-            src_rect.x0 = dst_rect.x0 = 0;
-            src_rect.x1 = dst_rect.x1 = templat.width;
-            src_rect.y0 = dst_rect.y0 = 0;
-            src_rect.y1 = dst_rect.y1 = templat.height;
-
-            vl_compositor_yuv_deint_full(&priv->cstate, &priv->compositor,
-                                         input->pInputPortPrivate, new_vbuf,
-                                         &src_rect, &dst_rect, VL_COMPOSITOR_WEAVE);
-
-            /* set the progrssive buffer for next round */
-            vbuf->destroy(vbuf);
-            input->pInputPortPrivate = new_vbuf;
-         }
-         output->pOutputPortPrivate = input->pInputPortPrivate;
-         input->pInputPortPrivate = tmp;
-      } else {
-         vid_dec_FillOutput(priv, input->pInputPortPrivate, output);
-      }
-      output->nFilledLen = output->nAllocLen;
-      output->nTimeStamp = input->nTimeStamp;
-   }
 
-   if (eos && input->pInputPortPrivate)
-      vid_dec_FreeInputPortPrivate(input);
-   else
-      input->nFilledLen = 0;
+   vid_dec_FrameDecoded_common(priv, input, output);
 }
index 7a10e750d91093d57daf59493db1db4437ee280d..247217810b549c821f8e17085047194ef99056fb 100644 (file)
 
 #include <OMX_Types.h>
 #include <OMX_Component.h>
-#include <OMX_Core.h>
 
-#include <bellagio/st_static_component_loader.h>
-#include <bellagio/omx_base_filter.h>
-#include <bellagio/omx_base_video_port.h>
-
-#include "pipe/p_video_state.h"
 #include "os/os_thread.h"
-#include "util/list.h"
 
-#include "vl/vl_compositor.h"
+#include "vid_dec_common.h"
 
 #define OMX_VID_DEC_BASE_NAME "OMX.mesa.video_decoder"
 
 
 #define OMX_VID_DEC_TIMESTAMP_INVALID ((OMX_TICKS) -1)
 
-struct vl_vlc;
-
-DERIVEDCLASS(vid_dec_PrivateType, omx_base_filter_PrivateType)
-#define vid_dec_PrivateType_FIELDS omx_base_filter_PrivateType_FIELDS \
-   enum pipe_video_profile profile; \
-   struct vl_screen *screen; \
-   struct pipe_context *pipe; \
-   struct pipe_video_codec *codec; \
-   void (*Decode)(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); \
-   void (*EndFrame)(vid_dec_PrivateType *priv); \
-   struct pipe_video_buffer *(*Flush)(vid_dec_PrivateType *priv, OMX_TICKS *timestamp); \
-   struct pipe_video_buffer *target, *shadow; \
-   union { \
-      struct { \
-         uint8_t intra_matrix[64]; \
-         uint8_t non_intra_matrix[64]; \
-      } mpeg12; \
-      struct { \
-         unsigned nal_ref_idc; \
-         bool IdrPicFlag; \
-         unsigned idr_pic_id; \
-         unsigned pic_order_cnt_lsb; \
-         unsigned pic_order_cnt_msb; \
-         unsigned delta_pic_order_cnt_bottom; \
-         unsigned delta_pic_order_cnt[2]; \
-         unsigned prevFrameNumOffset; \
-         struct pipe_h264_sps sps[32]; \
-         struct pipe_h264_pps pps[256]; \
-         struct list_head dpb_list; \
-         unsigned dpb_num; \
-      } h264; \
-      struct { \
-         unsigned temporal_id; \
-         unsigned level_idc; \
-         unsigned pic_width_in_luma_samples; \
-         unsigned pic_height_in_luma_samples; \
-         bool IdrPicFlag; \
-         int slice_prev_poc; \
-         void *ref_pic_set_list; \
-         void *rps; \
-         struct pipe_h265_sps sps[16]; \
-         struct pipe_h265_pps pps[64]; \
-         struct list_head dpb_list; \
-         unsigned dpb_num; \
-      } h265; \
-   } codec_data; \
-   union { \
-      struct pipe_picture_desc base; \
-      struct pipe_mpeg12_picture_desc mpeg12; \
-      struct pipe_h264_picture_desc h264; \
-      struct pipe_h265_picture_desc h265; \
-   } picture; \
-   unsigned num_in_buffers; \
-   OMX_BUFFERHEADERTYPE *in_buffers[2]; \
-   const void *inputs[2]; \
-   unsigned sizes[2]; \
-   OMX_TICKS timestamps[2]; \
-   OMX_TICKS timestamp; \
-   bool first_buf_in_frame; \
-   bool frame_finished; \
-   bool frame_started; \
-   unsigned bytes_left; \
-   const void *slice; \
-   bool disable_tunnel; \
-   struct vl_compositor compositor; \
-   struct vl_compositor_state cstate;
-ENDCLASS(vid_dec_PrivateType)
-
 OMX_ERRORTYPE vid_dec_LoaderComponent(stLoaderComponentType *comp);
 
-/* used by MPEG12 and H264 implementation */
-void vid_dec_NeedTarget(vid_dec_PrivateType *priv);
-
 /* vid_dec_mpeg12.c */
 void vid_dec_mpeg12_Init(vid_dec_PrivateType *priv);
 
index 7ea71c1046b28ff0afd89b2a6bdc6d3593f4e827..e8f7aa5cf18a43c5d33a43bb6a2643909096ae6a 100644 (file)
 
 #include "entrypoint.h"
 #include "vid_dec.h"
-
-#define DPB_MAX_SIZE 5
-
-struct dpb_list {
-   struct list_head list;
-   struct pipe_video_buffer *buffer;
-   OMX_TICKS timestamp;
-   int poc;
-};
-
-static const uint8_t Default_4x4_Intra[16] = {
-    6, 13, 20, 28, 13, 20, 28, 32,
-   20, 28, 32, 37, 28, 32, 37, 42
-};
-
-static const uint8_t Default_4x4_Inter[16] = {
-   10, 14, 20, 24, 14, 20, 24, 27,
-   20, 24, 27, 30, 24, 27, 30, 34
-};
-
-static const uint8_t Default_8x8_Intra[64] = {
-    6, 10, 13, 16, 18, 23, 25, 27,
-   10, 11, 16, 18, 23, 25, 27, 29,
-   13, 16, 18, 23, 25, 27, 29, 31,
-   16, 18, 23, 25, 27, 29, 31, 33,
-   18, 23, 25, 27, 29, 31, 33, 36,
-   23, 25, 27, 29, 31, 33, 36, 38,
-   25, 27, 29, 31, 33, 36, 38, 40,
-   27, 29, 31, 33, 36, 38, 40, 42
-};
-
-static const uint8_t Default_8x8_Inter[64] = {
-    9, 13, 15, 17, 19, 21, 22, 24,
-   13, 13, 17, 19, 21, 22, 24, 25,
-   15, 17, 19, 21, 22, 24, 25, 27,
-   17, 19, 21, 22, 24, 25, 27, 28,
-   19, 21, 22, 24, 25, 27, 28, 30,
-   21, 22, 24, 25, 27, 28, 30, 32,
-   22, 24, 25, 27, 28, 30, 32, 33,
-   24, 25, 27, 28, 30, 32, 33, 35
-};
-
-static void vid_dec_h264_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left);
-static void vid_dec_h264_EndFrame(vid_dec_PrivateType *priv);
-static struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv, OMX_TICKS *timestamp);
+#include "vid_dec_h264_common.h"
 
 void vid_dec_h264_Init(vid_dec_PrivateType *priv)
 {
@@ -97,936 +53,3 @@ void vid_dec_h264_Init(vid_dec_PrivateType *priv)
    priv->picture.h264.field_order_cnt[0] = priv->picture.h264.field_order_cnt[1] = INT_MAX;
    priv->first_buf_in_frame = true;
 }
-
-static void vid_dec_h264_BeginFrame(vid_dec_PrivateType *priv)
-{
-   //TODO: sane buffer handling
-
-   if (priv->frame_started)
-      return;
-
-   if (!priv->codec) {
-      struct pipe_video_codec templat = {};
-      omx_base_video_PortType *port;
-
-      port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];
-      templat.profile = priv->profile;
-      templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM;
-      templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
-      templat.max_references = priv->picture.h264.num_ref_frames;
-      templat.expect_chunked_decode = true;
-      templat.width = port->sPortParam.format.video.nFrameWidth;
-      templat.height = port->sPortParam.format.video.nFrameHeight;
-      templat.level = priv->picture.h264.pps->sps->level_idc;
-
-      priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat);
-   }
-
-   vid_dec_NeedTarget(priv);
-
-   if (priv->first_buf_in_frame)
-      priv->timestamp = priv->timestamps[0];
-   priv->first_buf_in_frame = false;
-
-   priv->picture.h264.num_ref_frames = priv->picture.h264.pps->sps->max_num_ref_frames;
-
-   priv->picture.h264.slice_count = 0;
-   priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base);
-   priv->frame_started = true;
-}
-
-static struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv,
-                                                    OMX_TICKS *timestamp)
-{
-   struct dpb_list *entry, *result = NULL;
-   struct pipe_video_buffer *buf;
-
-   /* search for the lowest poc and break on zeros */
-   LIST_FOR_EACH_ENTRY(entry, &priv->codec_data.h264.dpb_list, list) {
-
-      if (result && entry->poc == 0)
-         break;
-
-      if (!result || entry->poc < result->poc)
-         result = entry;
-   }
-
-   if (!result)
-      return NULL;
-
-   buf = result->buffer;
-   if (timestamp)
-      *timestamp = result->timestamp;
-
-   --priv->codec_data.h264.dpb_num;
-   LIST_DEL(&result->list);
-   FREE(result);
-
-   return buf;
-}
-
-static void vid_dec_h264_EndFrame(vid_dec_PrivateType *priv)
-{
-   struct dpb_list *entry;
-   struct pipe_video_buffer *tmp;
-   bool top_field_first;
-   OMX_TICKS timestamp;
-
-   if (!priv->frame_started)
-      return;
-
-   priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base);
-   priv->frame_started = false;
-
-   // TODO: implement frame number handling
-   priv->picture.h264.frame_num_list[0] = priv->picture.h264.frame_num;
-   priv->picture.h264.field_order_cnt_list[0][0] = priv->picture.h264.frame_num;
-   priv->picture.h264.field_order_cnt_list[0][1] = priv->picture.h264.frame_num;
-
-   top_field_first = priv->picture.h264.field_order_cnt[0] <  priv->picture.h264.field_order_cnt[1];
-
-   if (priv->picture.h264.field_pic_flag && priv->picture.h264.bottom_field_flag != top_field_first)
-      return;
-
-   /* add the decoded picture to the dpb list */
-   entry = CALLOC_STRUCT(dpb_list);
-   if (!entry)
-      return;
-
-   priv->first_buf_in_frame = true;
-   entry->buffer = priv->target;
-   entry->timestamp = priv->timestamp;
-   entry->poc = MIN2(priv->picture.h264.field_order_cnt[0], priv->picture.h264.field_order_cnt[1]);
-   LIST_ADDTAIL(&entry->list, &priv->codec_data.h264.dpb_list);
-   ++priv->codec_data.h264.dpb_num;
-   priv->target = NULL;
-   priv->picture.h264.field_order_cnt[0] = priv->picture.h264.field_order_cnt[1] = INT_MAX;
-
-   if (priv->codec_data.h264.dpb_num <= DPB_MAX_SIZE)
-      return;
-
-   tmp = priv->in_buffers[0]->pInputPortPrivate;
-   priv->in_buffers[0]->pInputPortPrivate = vid_dec_h264_Flush(priv, &timestamp);
-   priv->in_buffers[0]->nTimeStamp = timestamp;
-   priv->target = tmp;
-   priv->frame_finished = priv->in_buffers[0]->pInputPortPrivate != NULL;
-}
-
-static void vui_parameters(struct vl_rbsp *rbsp)
-{
-   // TODO
-}
-
-static void scaling_list(struct vl_rbsp *rbsp, uint8_t *scalingList, unsigned sizeOfScalingList,
-                         const uint8_t *defaultList, const uint8_t *fallbackList)
-{
-   unsigned lastScale = 8, nextScale = 8;
-   const int *list;
-   unsigned i;
-
-   /* (pic|seq)_scaling_list_present_flag[i] */
-   if (!vl_rbsp_u(rbsp, 1)) {
-      if (fallbackList)
-         memcpy(scalingList, fallbackList, sizeOfScalingList);
-      return;
-   }
-
-   list = (sizeOfScalingList == 16) ? vl_zscan_normal_16 : vl_zscan_normal;
-   for (i = 0; i < sizeOfScalingList; ++i ) {
-
-      if (nextScale != 0) {
-         signed delta_scale = vl_rbsp_se(rbsp);
-         nextScale = (lastScale + delta_scale + 256) % 256;
-         if (i == 0 && nextScale == 0) {
-            memcpy(scalingList, defaultList, sizeOfScalingList);
-            return;
-         }
-      }
-      scalingList[list[i]] = nextScale == 0 ? lastScale : nextScale;
-      lastScale = scalingList[list[i]];
-   }
-}
-
-static struct pipe_h264_sps *seq_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp)
-{
-   unsigned id = vl_rbsp_ue(rbsp);
-   if (id >= ARRAY_SIZE(priv->codec_data.h264.sps))
-      return NULL; /* invalid seq_parameter_set_id */
-
-   return &priv->codec_data.h264.sps[id];
-}
-
-static void seq_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp)
-{
-   struct pipe_h264_sps *sps;
-   unsigned profile_idc, level_idc;
-   unsigned i;
-
-   /* Sequence parameter set */
-   profile_idc = vl_rbsp_u(rbsp, 8);
-
-   /* constraint_set0_flag */
-   vl_rbsp_u(rbsp, 1);
-
-   /* constraint_set1_flag */
-   vl_rbsp_u(rbsp, 1);
-
-   /* constraint_set2_flag */
-   vl_rbsp_u(rbsp, 1);
-
-   /* constraint_set3_flag */
-   vl_rbsp_u(rbsp, 1);
-
-   /* constraint_set4_flag */
-   vl_rbsp_u(rbsp, 1);
-
-   /* constraint_set5_flag */
-   vl_rbsp_u(rbsp, 1);
-
-   /* reserved_zero_2bits */
-   vl_rbsp_u(rbsp, 2);
-
-   /* level_idc */
-   level_idc = vl_rbsp_u(rbsp, 8);
-
-   sps = seq_parameter_set_id(priv, rbsp);
-   if (!sps)
-      return;
-
-   memset(sps, 0, sizeof(*sps));
-   memset(sps->ScalingList4x4, 16, sizeof(sps->ScalingList4x4));
-   memset(sps->ScalingList8x8, 16, sizeof(sps->ScalingList8x8));
-
-   sps->level_idc = level_idc;
-
-   if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 ||
-       profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118 ||
-       profile_idc == 128 || profile_idc == 138) {
-
-      sps->chroma_format_idc = vl_rbsp_ue(rbsp);
-
-      if (sps->chroma_format_idc == 3)
-         sps->separate_colour_plane_flag = vl_rbsp_u(rbsp, 1);
-
-      sps->bit_depth_luma_minus8 = vl_rbsp_ue(rbsp);
-
-      sps->bit_depth_chroma_minus8 = vl_rbsp_ue(rbsp);
-
-      /* qpprime_y_zero_transform_bypass_flag */
-      vl_rbsp_u(rbsp, 1);
-
-      sps->seq_scaling_matrix_present_flag = vl_rbsp_u(rbsp, 1);
-      if (sps->seq_scaling_matrix_present_flag) {
-
-         scaling_list(rbsp, sps->ScalingList4x4[0], 16, Default_4x4_Intra, Default_4x4_Intra);
-         scaling_list(rbsp, sps->ScalingList4x4[1], 16, Default_4x4_Intra, sps->ScalingList4x4[0]);
-         scaling_list(rbsp, sps->ScalingList4x4[2], 16, Default_4x4_Intra, sps->ScalingList4x4[1]);
-         scaling_list(rbsp, sps->ScalingList4x4[3], 16, Default_4x4_Inter, Default_4x4_Inter);
-         scaling_list(rbsp, sps->ScalingList4x4[4], 16, Default_4x4_Inter, sps->ScalingList4x4[3]);
-         scaling_list(rbsp, sps->ScalingList4x4[5], 16, Default_4x4_Inter, sps->ScalingList4x4[4]);
-
-         scaling_list(rbsp, sps->ScalingList8x8[0], 64, Default_8x8_Intra, Default_8x8_Intra);
-         scaling_list(rbsp, sps->ScalingList8x8[1], 64, Default_8x8_Inter, Default_8x8_Inter);
-         if (sps->chroma_format_idc == 3) {
-            scaling_list(rbsp, sps->ScalingList8x8[2], 64, Default_8x8_Intra, sps->ScalingList8x8[0]);
-            scaling_list(rbsp, sps->ScalingList8x8[3], 64, Default_8x8_Inter, sps->ScalingList8x8[1]);
-            scaling_list(rbsp, sps->ScalingList8x8[4], 64, Default_8x8_Intra, sps->ScalingList8x8[2]);
-            scaling_list(rbsp, sps->ScalingList8x8[5], 64, Default_8x8_Inter, sps->ScalingList8x8[3]);
-         }
-      }
-   } else if (profile_idc == 183)
-      sps->chroma_format_idc = 0;
-   else
-      sps->chroma_format_idc = 1;
-
-   sps->log2_max_frame_num_minus4 = vl_rbsp_ue(rbsp);
-
-   sps->pic_order_cnt_type = vl_rbsp_ue(rbsp);
-
-   if (sps->pic_order_cnt_type == 0)
-      sps->log2_max_pic_order_cnt_lsb_minus4 = vl_rbsp_ue(rbsp);
-   else if (sps->pic_order_cnt_type == 1) {
-      sps->delta_pic_order_always_zero_flag = vl_rbsp_u(rbsp, 1);
-
-      sps->offset_for_non_ref_pic = vl_rbsp_se(rbsp);
-
-      sps->offset_for_top_to_bottom_field = vl_rbsp_se(rbsp);
-
-      sps->num_ref_frames_in_pic_order_cnt_cycle = vl_rbsp_ue(rbsp);
-
-      for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i)
-         sps->offset_for_ref_frame[i] = vl_rbsp_se(rbsp);
-   }
-
-   sps->max_num_ref_frames = vl_rbsp_ue(rbsp);
-
-   /* gaps_in_frame_num_value_allowed_flag */
-   vl_rbsp_u(rbsp, 1);
-
-   /* pic_width_in_mbs_minus1 */
-   vl_rbsp_ue(rbsp);
-
-   /* pic_height_in_map_units_minus1 */
-   vl_rbsp_ue(rbsp);
-
-   sps->frame_mbs_only_flag = vl_rbsp_u(rbsp, 1);
-   if (!sps->frame_mbs_only_flag)
-      sps->mb_adaptive_frame_field_flag = vl_rbsp_u(rbsp, 1);
-
-   sps->direct_8x8_inference_flag = vl_rbsp_u(rbsp, 1);
-
-   /* frame_cropping_flag */
-   if (vl_rbsp_u(rbsp, 1)) {
-      /* frame_crop_left_offset */
-      vl_rbsp_ue(rbsp);
-
-      /* frame_crop_right_offset */
-      vl_rbsp_ue(rbsp);
-
-      /* frame_crop_top_offset */
-      vl_rbsp_ue(rbsp);
-
-      /* frame_crop_bottom_offset */
-      vl_rbsp_ue(rbsp);
-   }
-
-   /* vui_parameters_present_flag */
-   if (vl_rbsp_u(rbsp, 1))
-      vui_parameters(rbsp);
-}
-
-static struct pipe_h264_pps *pic_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp)
-{
-   unsigned id = vl_rbsp_ue(rbsp);
-   if (id >= ARRAY_SIZE(priv->codec_data.h264.pps))
-      return NULL; /* invalid pic_parameter_set_id */
-
-   return &priv->codec_data.h264.pps[id];
-}
-
-static void picture_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp)
-{
-   struct pipe_h264_sps *sps;
-   struct pipe_h264_pps *pps;
-   unsigned i;
-
-   pps = pic_parameter_set_id(priv, rbsp);
-   if (!pps)
-      return;
-
-   memset(pps, 0, sizeof(*pps));
-
-   sps = pps->sps = seq_parameter_set_id(priv, rbsp);
-   if (!sps)
-      return;
-
-   memcpy(pps->ScalingList4x4, sps->ScalingList4x4, sizeof(pps->ScalingList4x4));
-   memcpy(pps->ScalingList8x8, sps->ScalingList8x8, sizeof(pps->ScalingList8x8));
-
-   pps->entropy_coding_mode_flag = vl_rbsp_u(rbsp, 1);
-
-   pps->bottom_field_pic_order_in_frame_present_flag = vl_rbsp_u(rbsp, 1);
-
-   pps->num_slice_groups_minus1 = vl_rbsp_ue(rbsp);
-   if (pps->num_slice_groups_minus1 > 0) {
-      pps->slice_group_map_type = vl_rbsp_ue(rbsp);
-
-      if (pps->slice_group_map_type == 0) {
-
-         for (i = 0; i <= pps->num_slice_groups_minus1; ++i)
-            /* run_length_minus1[i] */
-            vl_rbsp_ue(rbsp);
-
-      } else if (pps->slice_group_map_type == 2) {
-
-         for (i = 0; i <= pps->num_slice_groups_minus1; ++i) {
-            /* top_left[i] */
-            vl_rbsp_ue(rbsp);
-
-            /* bottom_right[i] */
-            vl_rbsp_ue(rbsp);
-         }
-
-      } else if (pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) {
-
-         /* slice_group_change_direction_flag */
-         vl_rbsp_u(rbsp, 1);
-
-         pps->slice_group_change_rate_minus1 = vl_rbsp_ue(rbsp);
-
-      } else if (pps->slice_group_map_type == 6) {
-
-         unsigned pic_size_in_map_units_minus1;
-
-         pic_size_in_map_units_minus1 = vl_rbsp_ue(rbsp);
-
-         for (i = 0; i <= pic_size_in_map_units_minus1; ++i)
-            /* slice_group_id[i] */
-            vl_rbsp_u(rbsp, log2(pps->num_slice_groups_minus1 + 1));
-      }
-   }
-
-   pps->num_ref_idx_l0_default_active_minus1 = vl_rbsp_ue(rbsp);
-
-   pps->num_ref_idx_l1_default_active_minus1 = vl_rbsp_ue(rbsp);
-
-   pps->weighted_pred_flag = vl_rbsp_u(rbsp, 1);
-
-   pps->weighted_bipred_idc = vl_rbsp_u(rbsp, 2);
-
-   pps->pic_init_qp_minus26 = vl_rbsp_se(rbsp);
-
-   /* pic_init_qs_minus26 */
-   vl_rbsp_se(rbsp);
-
-   pps->chroma_qp_index_offset = vl_rbsp_se(rbsp);
-
-   pps->deblocking_filter_control_present_flag = vl_rbsp_u(rbsp, 1);
-
-   pps->constrained_intra_pred_flag = vl_rbsp_u(rbsp, 1);
-
-   pps->redundant_pic_cnt_present_flag = vl_rbsp_u(rbsp, 1);
-
-   if (vl_rbsp_more_data(rbsp)) {
-      pps->transform_8x8_mode_flag = vl_rbsp_u(rbsp, 1);
-
-      /* pic_scaling_matrix_present_flag */
-      if (vl_rbsp_u(rbsp, 1)) {
-
-         scaling_list(rbsp, pps->ScalingList4x4[0], 16, Default_4x4_Intra,
-                      sps->seq_scaling_matrix_present_flag ? NULL : Default_4x4_Intra);
-         scaling_list(rbsp, pps->ScalingList4x4[1], 16, Default_4x4_Intra, pps->ScalingList4x4[0]);
-         scaling_list(rbsp, pps->ScalingList4x4[2], 16, Default_4x4_Intra, pps->ScalingList4x4[1]);
-         scaling_list(rbsp, pps->ScalingList4x4[3], 16, Default_4x4_Inter,
-                      sps->seq_scaling_matrix_present_flag ? NULL : Default_4x4_Inter);
-         scaling_list(rbsp, pps->ScalingList4x4[4], 16, Default_4x4_Inter, pps->ScalingList4x4[3]);
-         scaling_list(rbsp, pps->ScalingList4x4[5], 16, Default_4x4_Inter, pps->ScalingList4x4[4]);
-
-         if (pps->transform_8x8_mode_flag) {
-            scaling_list(rbsp, pps->ScalingList8x8[0], 64, Default_8x8_Intra,
-                         sps->seq_scaling_matrix_present_flag ? NULL : Default_8x8_Intra);
-            scaling_list(rbsp, pps->ScalingList8x8[1], 64, Default_8x8_Inter,
-                         sps->seq_scaling_matrix_present_flag ? NULL :  Default_8x8_Inter);
-            if (sps->chroma_format_idc == 3) {
-               scaling_list(rbsp, pps->ScalingList8x8[2], 64, Default_8x8_Intra, pps->ScalingList8x8[0]);
-               scaling_list(rbsp, pps->ScalingList8x8[3], 64, Default_8x8_Inter, pps->ScalingList8x8[1]);
-               scaling_list(rbsp, pps->ScalingList8x8[4], 64, Default_8x8_Intra, pps->ScalingList8x8[2]);
-               scaling_list(rbsp, pps->ScalingList8x8[5], 64, Default_8x8_Inter, pps->ScalingList8x8[3]);
-            }
-         }
-      }
-
-      pps->second_chroma_qp_index_offset = vl_rbsp_se(rbsp);
-   }
-}
-
-static void ref_pic_list_mvc_modification(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp)
-{
-   // TODO
-   assert(0);
-}
-
-static void ref_pic_list_modification(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp,
-                                      enum pipe_h264_slice_type slice_type)
-{
-   unsigned modification_of_pic_nums_idc;
-
-   if (slice_type != 2 && slice_type != 4) {
-      /* ref_pic_list_modification_flag_l0 */
-      if (vl_rbsp_u(rbsp, 1)) {
-         do {
-            modification_of_pic_nums_idc = vl_rbsp_ue(rbsp);
-            if (modification_of_pic_nums_idc == 0 ||
-                modification_of_pic_nums_idc == 1)
-               /* abs_diff_pic_num_minus1 */
-               vl_rbsp_ue(rbsp);
-            else if (modification_of_pic_nums_idc == 2)
-               /* long_term_pic_num */
-               vl_rbsp_ue(rbsp);
-         } while (modification_of_pic_nums_idc != 3);
-      }
-   }
-
-   if (slice_type == 1) {
-      /* ref_pic_list_modification_flag_l1 */
-      if (vl_rbsp_u(rbsp, 1)) {
-         do {
-            modification_of_pic_nums_idc = vl_rbsp_ue(rbsp);
-            if (modification_of_pic_nums_idc == 0 ||
-                modification_of_pic_nums_idc == 1)
-               /* abs_diff_pic_num_minus1 */
-               vl_rbsp_ue(rbsp);
-            else if (modification_of_pic_nums_idc == 2)
-               /* long_term_pic_num */
-               vl_rbsp_ue(rbsp);
-         } while (modification_of_pic_nums_idc != 3);
-      }
-   }
-}
-
-static void pred_weight_table(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp,
-                              struct pipe_h264_sps *sps, enum pipe_h264_slice_type slice_type)
-{
-   unsigned ChromaArrayType = sps->separate_colour_plane_flag ? 0 : sps->chroma_format_idc;
-   unsigned i, j;
-
-   /* luma_log2_weight_denom */
-   vl_rbsp_ue(rbsp);
-
-   if (ChromaArrayType != 0)
-      /* chroma_log2_weight_denom */
-      vl_rbsp_ue(rbsp);
-
-   for (i = 0; i <= priv->picture.h264.num_ref_idx_l0_active_minus1; ++i) {
-      /* luma_weight_l0_flag */
-      if (vl_rbsp_u(rbsp, 1)) {
-         /* luma_weight_l0[i] */
-         vl_rbsp_se(rbsp);
-         /* luma_offset_l0[i] */
-         vl_rbsp_se(rbsp);
-      }
-      if (ChromaArrayType != 0) {
-         /* chroma_weight_l0_flag */
-         if (vl_rbsp_u(rbsp, 1)) {
-            for (j = 0; j < 2; ++j) {
-               /* chroma_weight_l0[i][j] */
-               vl_rbsp_se(rbsp);
-               /* chroma_offset_l0[i][j] */
-               vl_rbsp_se(rbsp);
-            }
-         }
-      }
-   }
-
-   if (slice_type == 1) {
-      for (i = 0; i <= priv->picture.h264.num_ref_idx_l1_active_minus1; ++i) {
-         /* luma_weight_l1_flag */
-         if (vl_rbsp_u(rbsp, 1)) {
-            /* luma_weight_l1[i] */
-            vl_rbsp_se(rbsp);
-            /* luma_offset_l1[i] */
-            vl_rbsp_se(rbsp);
-         }
-         if (ChromaArrayType != 0) {
-            /* chroma_weight_l1_flag */
-            if (vl_rbsp_u(rbsp, 1)) {
-               for (j = 0; j < 2; ++j) {
-                  /* chroma_weight_l1[i][j] */
-                  vl_rbsp_se(rbsp);
-                  /* chroma_offset_l1[i][j] */
-                  vl_rbsp_se(rbsp);
-               }
-            }
-         }
-      }
-   }
-}
-
-static void dec_ref_pic_marking(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp,
-                                bool IdrPicFlag)
-{
-   unsigned memory_management_control_operation;
-
-   if (IdrPicFlag) {
-      /* no_output_of_prior_pics_flag */
-      vl_rbsp_u(rbsp, 1);
-      /* long_term_reference_flag */
-      vl_rbsp_u(rbsp, 1);
-   } else {
-      /* adaptive_ref_pic_marking_mode_flag */
-      if (vl_rbsp_u(rbsp, 1)) {
-         do {
-            memory_management_control_operation = vl_rbsp_ue(rbsp);
-
-            if (memory_management_control_operation == 1 ||
-                memory_management_control_operation == 3)
-               /* difference_of_pic_nums_minus1 */
-               vl_rbsp_ue(rbsp);
-
-            if (memory_management_control_operation == 2)
-               /* long_term_pic_num */
-               vl_rbsp_ue(rbsp);
-
-            if (memory_management_control_operation == 3 ||
-                memory_management_control_operation == 6)
-               /* long_term_frame_idx */
-               vl_rbsp_ue(rbsp);
-
-            if (memory_management_control_operation == 4)
-               /* max_long_term_frame_idx_plus1 */
-               vl_rbsp_ue(rbsp);
-         } while (memory_management_control_operation != 0);
-      }
-   }
-}
-
-static void slice_header(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp,
-                         unsigned nal_ref_idc, unsigned nal_unit_type)
-{
-   enum pipe_h264_slice_type slice_type;
-   struct pipe_h264_pps *pps;
-   struct pipe_h264_sps *sps;
-   unsigned frame_num, prevFrameNum;
-   bool IdrPicFlag = nal_unit_type == 5;
-
-   if (IdrPicFlag != priv->codec_data.h264.IdrPicFlag)
-      vid_dec_h264_EndFrame(priv);
-
-   priv->codec_data.h264.IdrPicFlag = IdrPicFlag;
-
-   /* first_mb_in_slice */
-   vl_rbsp_ue(rbsp);
-
-   slice_type = vl_rbsp_ue(rbsp) % 5;
-
-   pps = pic_parameter_set_id(priv, rbsp);
-   if (!pps)
-      return;
-
-   sps = pps->sps;
-   if (!sps)
-      return;
-
-   if (pps != priv->picture.h264.pps)
-      vid_dec_h264_EndFrame(priv);
-
-   priv->picture.h264.pps = pps;
-
-   if (sps->separate_colour_plane_flag == 1 )
-      /* colour_plane_id */
-      vl_rbsp_u(rbsp, 2);
-
-   frame_num = vl_rbsp_u(rbsp, sps->log2_max_frame_num_minus4 + 4);
-
-   if (frame_num != priv->picture.h264.frame_num)
-      vid_dec_h264_EndFrame(priv);
-
-   prevFrameNum = priv->picture.h264.frame_num;
-   priv->picture.h264.frame_num = frame_num;
-
-   priv->picture.h264.field_pic_flag = 0;
-   priv->picture.h264.bottom_field_flag = 0;
-
-   if (!sps->frame_mbs_only_flag) {
-      unsigned field_pic_flag = vl_rbsp_u(rbsp, 1);
-
-      if (!field_pic_flag && field_pic_flag != priv->picture.h264.field_pic_flag)
-         vid_dec_h264_EndFrame(priv);
-
-      priv->picture.h264.field_pic_flag = field_pic_flag;
-
-      if (priv->picture.h264.field_pic_flag) {
-         unsigned bottom_field_flag = vl_rbsp_u(rbsp, 1);
-
-         if (bottom_field_flag != priv->picture.h264.bottom_field_flag)
-            vid_dec_h264_EndFrame(priv);
-
-         priv->picture.h264.bottom_field_flag = bottom_field_flag;
-      }
-   }
-
-   if (IdrPicFlag) {
-      unsigned idr_pic_id = vl_rbsp_ue(rbsp);
-
-      if (idr_pic_id != priv->codec_data.h264.idr_pic_id)
-         vid_dec_h264_EndFrame(priv);
-
-      priv->codec_data.h264.idr_pic_id = idr_pic_id;
-   }
-
-   if (sps->pic_order_cnt_type == 0) {
-      unsigned log2_max_pic_order_cnt_lsb = sps->log2_max_pic_order_cnt_lsb_minus4 + 4;
-      unsigned max_pic_order_cnt_lsb = 1 << log2_max_pic_order_cnt_lsb;
-      int pic_order_cnt_lsb = vl_rbsp_u(rbsp, log2_max_pic_order_cnt_lsb);
-      int pic_order_cnt_msb;
-
-      if (pic_order_cnt_lsb != priv->codec_data.h264.pic_order_cnt_lsb)
-         vid_dec_h264_EndFrame(priv);
-
-      if (IdrPicFlag) {
-         priv->codec_data.h264.pic_order_cnt_msb = 0;
-         priv->codec_data.h264.pic_order_cnt_lsb = 0;
-      }
-
-      if ((pic_order_cnt_lsb < priv->codec_data.h264.pic_order_cnt_lsb) &&
-          (priv->codec_data.h264.pic_order_cnt_lsb - pic_order_cnt_lsb) >= (max_pic_order_cnt_lsb / 2))
-         pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb + max_pic_order_cnt_lsb;
-
-      else if ((pic_order_cnt_lsb > priv->codec_data.h264.pic_order_cnt_lsb) &&
-          (pic_order_cnt_lsb - priv->codec_data.h264.pic_order_cnt_lsb) > (max_pic_order_cnt_lsb / 2))
-         pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb - max_pic_order_cnt_lsb;
-
-      else
-         pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb;
-
-      priv->codec_data.h264.pic_order_cnt_msb = pic_order_cnt_msb;
-      priv->codec_data.h264.pic_order_cnt_lsb = pic_order_cnt_lsb;
-
-      if (pps->bottom_field_pic_order_in_frame_present_flag && !priv->picture.h264.field_pic_flag) {
-         unsigned delta_pic_order_cnt_bottom = vl_rbsp_se(rbsp);
-
-         if (delta_pic_order_cnt_bottom != priv->codec_data.h264.delta_pic_order_cnt_bottom)
-            vid_dec_h264_EndFrame(priv);
-
-         priv->codec_data.h264.delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom;
-      }
-
-      if (!priv->picture.h264.field_pic_flag) {
-         priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb;
-         priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt [0] +
-                                          priv->codec_data.h264.delta_pic_order_cnt_bottom;
-      } else if (!priv->picture.h264.bottom_field_flag)
-         priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb;
-      else
-         priv->picture.h264.field_order_cnt[1] = pic_order_cnt_msb + pic_order_cnt_lsb;
-
-   } else if (sps->pic_order_cnt_type == 1) {
-      unsigned MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
-      unsigned FrameNumOffset, absFrameNum, expectedPicOrderCnt;
-
-      if (!sps->delta_pic_order_always_zero_flag) {
-         unsigned delta_pic_order_cnt[2];
-
-         delta_pic_order_cnt[0] = vl_rbsp_se(rbsp);
-
-         if (delta_pic_order_cnt[0] != priv->codec_data.h264.delta_pic_order_cnt[0])
-            vid_dec_h264_EndFrame(priv);
-
-         priv->codec_data.h264.delta_pic_order_cnt[0] = delta_pic_order_cnt[0];
-
-         if (pps->bottom_field_pic_order_in_frame_present_flag && !priv->picture.h264.field_pic_flag) {
-            delta_pic_order_cnt[1] = vl_rbsp_se(rbsp);
-
-            if (delta_pic_order_cnt[1] != priv->codec_data.h264.delta_pic_order_cnt[1])
-               vid_dec_h264_EndFrame(priv);
-
-            priv->codec_data.h264.delta_pic_order_cnt[1] = delta_pic_order_cnt[1];
-         }
-      }
-
-      if (IdrPicFlag)
-         FrameNumOffset = 0;
-      else if (prevFrameNum > frame_num)
-         FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset + MaxFrameNum;
-      else
-         FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset;
-
-      priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset;
-
-      if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0)
-         absFrameNum = FrameNumOffset + frame_num;
-      else
-         absFrameNum = 0;
-
-      if (nal_ref_idc == 0 && absFrameNum > 0)
-         absFrameNum = absFrameNum - 1;
-
-      if (absFrameNum > 0) {
-         unsigned picOrderCntCycleCnt = (absFrameNum - 1) / sps->num_ref_frames_in_pic_order_cnt_cycle;
-         unsigned frameNumInPicOrderCntCycle = (absFrameNum - 1) % sps->num_ref_frames_in_pic_order_cnt_cycle;
-         signed ExpectedDeltaPerPicOrderCntCycle = 0;
-         unsigned i;
-
-         for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i)
-            ExpectedDeltaPerPicOrderCntCycle += sps->offset_for_ref_frame[i];
-
-         expectedPicOrderCnt = picOrderCntCycleCnt * ExpectedDeltaPerPicOrderCntCycle;
-         for (i = 0; i <= frameNumInPicOrderCntCycle; ++i)
-            expectedPicOrderCnt += sps->offset_for_ref_frame[i];
-
-      } else
-         expectedPicOrderCnt = 0;
-
-      if (nal_ref_idc == 0)
-         expectedPicOrderCnt += sps->offset_for_non_ref_pic;
-
-      if (!priv->picture.h264.field_pic_flag) {
-         priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0];
-         priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt[0] +
-            sps->offset_for_top_to_bottom_field + priv->codec_data.h264.delta_pic_order_cnt[1];
-
-      } else if (!priv->picture.h264.bottom_field_flag)
-         priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0];
-      else
-         priv->picture.h264.field_order_cnt[1] = expectedPicOrderCnt + sps->offset_for_top_to_bottom_field +
-            priv->codec_data.h264.delta_pic_order_cnt[0];
-
-   } else if (sps->pic_order_cnt_type == 2) {
-      unsigned MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
-      unsigned FrameNumOffset, tempPicOrderCnt;
-
-      if (IdrPicFlag)
-         FrameNumOffset = 0;
-      else if (prevFrameNum > frame_num)
-         FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset + MaxFrameNum;
-      else
-         FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset;
-
-      priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset;
-
-      if (IdrPicFlag)
-         tempPicOrderCnt = 0;
-      else if (nal_ref_idc == 0)
-         tempPicOrderCnt = 2 * (FrameNumOffset + frame_num) - 1;
-      else
-         tempPicOrderCnt = 2 * (FrameNumOffset + frame_num);
-
-      if (!priv->picture.h264.field_pic_flag) {
-         priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt;
-         priv->picture.h264.field_order_cnt[1] = tempPicOrderCnt;
-
-      } else if (!priv->picture.h264.bottom_field_flag)
-         priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt;
-      else
-         priv->picture.h264.field_order_cnt[1] = tempPicOrderCnt;
-   }
-
-   if (pps->redundant_pic_cnt_present_flag)
-      /* redundant_pic_cnt */
-      vl_rbsp_ue(rbsp);
-
-   if (slice_type == PIPE_H264_SLICE_TYPE_B)
-      /* direct_spatial_mv_pred_flag */
-      vl_rbsp_u(rbsp, 1);
-
-   priv->picture.h264.num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1;
-   priv->picture.h264.num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1;
-
-   if (slice_type == PIPE_H264_SLICE_TYPE_P ||
-       slice_type == PIPE_H264_SLICE_TYPE_SP ||
-       slice_type == PIPE_H264_SLICE_TYPE_B) {
-
-      /* num_ref_idx_active_override_flag */
-      if (vl_rbsp_u(rbsp, 1)) {
-         priv->picture.h264.num_ref_idx_l0_active_minus1 = vl_rbsp_ue(rbsp);
-
-         if (slice_type == PIPE_H264_SLICE_TYPE_B)
-            priv->picture.h264.num_ref_idx_l1_active_minus1 = vl_rbsp_ue(rbsp);
-      }
-   }
-
-   if (nal_unit_type == 20 || nal_unit_type == 21)
-      ref_pic_list_mvc_modification(priv, rbsp);
-   else
-      ref_pic_list_modification(priv, rbsp, slice_type);
-
-   if ((pps->weighted_pred_flag && (slice_type == PIPE_H264_SLICE_TYPE_P || slice_type == PIPE_H264_SLICE_TYPE_SP)) ||
-       (pps->weighted_bipred_idc == 1 && slice_type == PIPE_H264_SLICE_TYPE_B))
-      pred_weight_table(priv, rbsp, sps, slice_type);
-
-   if (nal_ref_idc != 0)
-      dec_ref_pic_marking(priv, rbsp, IdrPicFlag);
-
-   if (pps->entropy_coding_mode_flag && slice_type != PIPE_H264_SLICE_TYPE_I && slice_type != PIPE_H264_SLICE_TYPE_SI)
-      /* cabac_init_idc */
-      vl_rbsp_ue(rbsp);
-
-   /* slice_qp_delta */
-   vl_rbsp_se(rbsp);
-
-   if (slice_type == PIPE_H264_SLICE_TYPE_SP || slice_type == PIPE_H264_SLICE_TYPE_SI) {
-      if (slice_type == PIPE_H264_SLICE_TYPE_SP)
-         /* sp_for_switch_flag */
-         vl_rbsp_u(rbsp, 1);
-
-      /*slice_qs_delta */
-      vl_rbsp_se(rbsp);
-   }
-
-   if (pps->deblocking_filter_control_present_flag) {
-      unsigned disable_deblocking_filter_idc = vl_rbsp_ue(rbsp);
-
-      if (disable_deblocking_filter_idc != 1) {
-         /* slice_alpha_c0_offset_div2 */
-         vl_rbsp_se(rbsp);
-
-         /* slice_beta_offset_div2 */
-         vl_rbsp_se(rbsp);
-      }
-   }
-
-   if (pps->num_slice_groups_minus1 > 0 && pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5)
-      /* slice_group_change_cycle */
-      vl_rbsp_u(rbsp, 2);
-}
-
-static void vid_dec_h264_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left)
-{
-   unsigned nal_ref_idc, nal_unit_type;
-
-   if (!vl_vlc_search_byte(vlc, vl_vlc_bits_left(vlc) - min_bits_left, 0x00))
-      return;
-
-   if (vl_vlc_peekbits(vlc, 24) != 0x000001) {
-      vl_vlc_eatbits(vlc, 8);
-      return;
-   }
-
-   if (priv->slice) {
-      unsigned bytes = priv->bytes_left - (vl_vlc_bits_left(vlc) / 8);
-      ++priv->picture.h264.slice_count;
-      priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base,
-                                    1, &priv->slice, &bytes);
-      priv->slice = NULL;
-   }
-
-   vl_vlc_eatbits(vlc, 24);
-
-   /* forbidden_zero_bit */
-   vl_vlc_eatbits(vlc, 1);
-
-   nal_ref_idc = vl_vlc_get_uimsbf(vlc, 2);
-
-   if (nal_ref_idc != priv->codec_data.h264.nal_ref_idc &&
-       (nal_ref_idc * priv->codec_data.h264.nal_ref_idc) == 0)
-      vid_dec_h264_EndFrame(priv);
-
-   priv->codec_data.h264.nal_ref_idc = nal_ref_idc;
-
-   nal_unit_type = vl_vlc_get_uimsbf(vlc, 5);
-
-   if (nal_unit_type != 1 && nal_unit_type != 5)
-      vid_dec_h264_EndFrame(priv);
-
-   if (nal_unit_type == 7) {
-      struct vl_rbsp rbsp;
-      vl_rbsp_init(&rbsp, vlc, ~0);
-      seq_parameter_set(priv, &rbsp);
-
-   } else if (nal_unit_type == 8) {
-      struct vl_rbsp rbsp;
-      vl_rbsp_init(&rbsp, vlc, ~0);
-      picture_parameter_set(priv, &rbsp);
-
-   } else if (nal_unit_type == 1 || nal_unit_type == 5) {
-      /* Coded slice of a non-IDR or IDR picture */
-      unsigned bits = vl_vlc_valid_bits(vlc);
-      unsigned bytes = bits / 8 + 4;
-      struct vl_rbsp rbsp;
-      uint8_t buf[8];
-      const void *ptr = buf;
-      unsigned i;
-
-      buf[0] = 0x0;
-      buf[1] = 0x0;
-      buf[2] = 0x1;
-      buf[3] = (nal_ref_idc << 5) | nal_unit_type;
-      for (i = 4; i < bytes; ++i)
-         buf[i] = vl_vlc_peekbits(vlc, bits) >> ((bytes - i - 1) * 8);
-
-      priv->bytes_left = (vl_vlc_bits_left(vlc) - bits) / 8;
-      priv->slice = vlc->data;
-
-      vl_rbsp_init(&rbsp, vlc, 128);
-      slice_header(priv, &rbsp, nal_ref_idc, nal_unit_type);
-
-      vid_dec_h264_BeginFrame(priv);
-
-      ++priv->picture.h264.slice_count;
-      priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base,
-                                    1, &ptr, &bytes);
-   }
-
-   /* resync to byte boundary */
-   vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8);
-}
index 2a777bbb91b0f3e473f4e877aa844af43b9b3746..a6b09f98e25f2fa28d83e12ab7c99cc45d2979ac 100644 (file)
@@ -53,6 +53,7 @@
 
 #include "entrypoint.h"
 #include "vid_enc.h"
+#include "vid_omx_common.h"
 
 struct encode_task {
    struct list_head list;
index f66902221906f726564d490f3ba938cfeb93d035..33e969814f5399d1a7d86155e9fabbb8fab1cfd9 100644 (file)
 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 # SOFTWARE.
 
-if gallium_omx == 'bellagio'
 files_omx = files(
+       'vid_dec_common.c',
+       'vid_dec_h264_common.c',
+       'vid_omx_common.c'
+)
+
+if gallium_omx == 'bellagio'
+files_omx += files(
   'bellagio/entrypoint.c',
   'bellagio/vid_dec.c',
   'bellagio/vid_dec_mpeg12.c',
@@ -28,8 +34,11 @@ files_omx = files(
   'bellagio/vid_enc.c'
 )
 elif gallium_omx == 'tizonia'
-files_omx = files(
+files_omx += files(
   'tizonia/entrypoint.c',
+       'tizonia/h264d.c',
+       'tizonia/h264dprc.c',
+       'tizonia/h264dinport.c'
 )
 endif
 
index de6fcf926bdcfc8d8755438442ce304e8c0cfd3a..41b7a3d41702c93a8b220d6cf556b1889a3a831e 100644 (file)
@@ -1,3 +1,11 @@
 C_SOURCES := \
        entrypoint.c \
-       entrypoint.h
+       entrypoint.h \
+       h264d.c \
+       h264d.h \
+       h264dprc.c \
+       h264dprc.h \
+       h264dinport.c \
+       h264dinport.h \
+       h264dinport_decls.h \
+       names.h
index c89bdfdb10a6e8801f9593ee612fc8bb896b64f6..df81ee3f5174497ef032c4655779eb325266a5f6 100644 (file)
 #include <tizplatform.h>
 #include <tizkernel.h>
 #include <tizscheduler.h>
+#include <tizport.h>
+#include <tizport_decls.h>
+#include <tizvideoport.h>
+#include <tizvideoport_decls.h>
 
+#include "vid_dec_h264_common.h"
 #include "entrypoint.h"
+#include "h264d.h"
+#include "h264dprc.h"
+#include "h264dinport.h"
+#include "names.h"
 
 OMX_ERRORTYPE OMX_ComponentInit (OMX_HANDLETYPE ap_hdl)
 {
+   tiz_role_factory_t h264d_role;
+   const tiz_role_factory_t * rf_list[] = {&h264d_role};
+   tiz_type_factory_t h264dprc_type;
+   tiz_type_factory_t h264d_inport_type;
+   const tiz_type_factory_t * tf_list[] = {&h264dprc_type, &h264d_inport_type};
+
+   /* Settings for roles */
+   strcpy ((OMX_STRING) h264d_role.role, OMX_VID_DEC_AVC_ROLE);
+   h264d_role.pf_cport = instantiate_h264d_config_port;
+   h264d_role.pf_port[0] = instantiate_h264d_input_port;
+   h264d_role.pf_port[1] = instantiate_h264d_output_port;
+   h264d_role.nports = 2;
+   h264d_role.pf_proc = instantiate_h264d_processor;
+
+   /* Settings for classes */
+   strcpy ((OMX_STRING) h264dprc_type.class_name, "h264dprc_class");
+   h264dprc_type.pf_class_init = h264d_prc_class_init;
+   strcpy ((OMX_STRING) h264dprc_type.object_name, "h264dprc");
+   h264dprc_type.pf_object_init = h264d_prc_init;
+
+   strcpy ((OMX_STRING) h264d_inport_type.class_name, "h264dinport_class");
+   h264d_inport_type.pf_class_init = h264d_inport_class_init;
+   strcpy ((OMX_STRING) h264d_inport_type.object_name, "h264dinport");
+   h264d_inport_type.pf_object_init = h264d_inport_init;
+
+   /* Initialize the component infrastructure */
+   tiz_comp_init (ap_hdl, OMX_VID_COMP_NAME);
+
+   /* Classes need to be registered first */
+   tiz_comp_register_types (ap_hdl, tf_list, 2);
+
+   /* Register the component roles */
+   tiz_comp_register_roles (ap_hdl, rf_list, 1);
+
    return OMX_ErrorNone;
 }
diff --git a/src/gallium/state_trackers/omx/tizonia/h264d.c b/src/gallium/state_trackers/omx/tizonia/h264d.c
new file mode 100644 (file)
index 0000000..92019a7
--- /dev/null
@@ -0,0 +1,176 @@
+/**************************************************************************
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <tizport_decls.h>
+
+#include "vid_dec_h264_common.h"
+
+#include "h264dprc.h"
+#include "h264d.h"
+#include "names.h"
+
+static OMX_VERSIONTYPE h264_decoder_version = {{0, 0, 0, 1}};
+
+OMX_PTR instantiate_h264d_input_port(OMX_HANDLETYPE ap_hdl)
+{
+   OMX_VIDEO_PORTDEFINITIONTYPE portdef;
+   OMX_VIDEO_PARAM_AVCTYPE avctype;
+   OMX_VIDEO_CODINGTYPE encodings[] = {
+      OMX_VIDEO_CodingAVC,
+      OMX_VIDEO_CodingMax
+   };
+   OMX_COLOR_FORMATTYPE formats[] = {
+      OMX_COLOR_FormatUnused,
+      OMX_COLOR_FormatMax
+   };
+   tiz_port_options_t avc_port_opts = {
+      OMX_PortDomainVideo,
+      OMX_DirInput,
+      OMX_VID_DEC_AVC_INPUT_PORT_MIN_BUF_COUNT,
+      OMX_VID_DEC_AVC_PORT_MIN_INPUT_BUF_SIZE,
+      OMX_VID_DEC_AVC_PORT_NONCONTIGUOUS,
+      OMX_VID_DEC_AVC_PORT_ALIGNMENT,
+      OMX_VID_DEC_AVC_PORT_SUPPLIERPREF,
+      {OMX_VID_DEC_AVC_INPUT_PORT_INDEX, NULL, NULL, NULL},
+      1                     /* slave port */
+   };
+   OMX_VIDEO_AVCLEVELTYPE levels[] = {
+      OMX_VIDEO_AVCLevel1,
+      OMX_VIDEO_AVCLevel1b,
+      OMX_VIDEO_AVCLevel11,
+      OMX_VIDEO_AVCLevel12,
+      OMX_VIDEO_AVCLevel13,
+      OMX_VIDEO_AVCLevel2,
+      OMX_VIDEO_AVCLevel21,
+      OMX_VIDEO_AVCLevel22,
+      OMX_VIDEO_AVCLevel3,
+      OMX_VIDEO_AVCLevel31,
+      OMX_VIDEO_AVCLevel32,
+      OMX_VIDEO_AVCLevel4,
+      OMX_VIDEO_AVCLevel41,
+      OMX_VIDEO_AVCLevel42,
+      OMX_VIDEO_AVCLevel5,
+      OMX_VIDEO_AVCLevel51,
+      OMX_VIDEO_AVCLevelMax
+   };
+
+   portdef.pNativeRender = NULL;
+   portdef.nFrameWidth = OMX_VID_DEC_AVC_DEFAULT_FRAME_WIDTH;
+   portdef.nFrameHeight = OMX_VID_DEC_AVC_DEFAULT_FRAME_HEIGHT;
+   portdef.nStride = 0;
+   portdef.nSliceHeight = 0;
+   portdef.nBitrate = 64000;
+   portdef.xFramerate = OMX_VID_DEC_AVC_DEFAULT_FRAME_RATE;
+   portdef.bFlagErrorConcealment = OMX_FALSE;
+   portdef.eCompressionFormat = OMX_VIDEO_CodingAVC;
+   portdef.eColorFormat = OMX_COLOR_FormatUnused;
+   portdef.pNativeWindow = NULL;
+
+   avctype.nSize = sizeof (OMX_VIDEO_PARAM_AVCTYPE);
+   avctype.nVersion.nVersion = OMX_VERSION;
+   avctype.nPortIndex = OMX_VID_DEC_AVC_INPUT_PORT_INDEX;
+   avctype.eProfile = OMX_VIDEO_AVCProfileHigh;
+    /* Encoder related, decide if need to initialise these */
+   avctype.nSliceHeaderSpacing = 0;
+   avctype.nPFrames = 0;
+   avctype.nBFrames = 0;
+   avctype.bUseHadamard = OMX_FALSE;
+   avctype.nRefFrames = 1;
+   avctype.nRefIdx10ActiveMinus1 = 1;
+   avctype.nRefIdx11ActiveMinus1 = 0;
+   avctype.bEnableUEP = OMX_FALSE;
+   avctype.bEnableFMO = OMX_FALSE;
+   avctype.bEnableASO = OMX_FALSE;
+   avctype.bEnableRS = OMX_FALSE;
+   avctype.eLevel = OMX_VIDEO_AVCLevel51;
+   avctype.nAllowedPictureTypes = 2;
+   avctype.bFrameMBsOnly = OMX_FALSE;
+   avctype.bMBAFF = OMX_FALSE;
+   avctype.bEntropyCodingCABAC = OMX_FALSE;
+   avctype.bWeightedPPrediction = OMX_FALSE;
+   avctype.nWeightedBipredicitonMode = 0;
+   avctype.bconstIpred = OMX_FALSE;
+   avctype.bDirect8x8Inference = OMX_FALSE;
+   avctype.bDirectSpatialTemporal = OMX_FALSE;
+   avctype.nCabacInitIdc = 0;
+   avctype.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
+
+   return factory_new (tiz_get_type(ap_hdl, "h264dinport"),
+                       &avc_port_opts, &portdef,
+                       &encodings, &formats, &avctype, &levels,
+                       NULL  /* OMX_VIDEO_PARAM_BITRATETYPE */,
+                       NULL  /* OMX_VIDEO_PARAM_QUANTIZATIONTYPE */);
+}
+
+OMX_PTR instantiate_h264d_output_port(OMX_HANDLETYPE ap_hdl)
+{
+   OMX_VIDEO_PORTDEFINITIONTYPE portdef;
+   OMX_VIDEO_CODINGTYPE encodings[] = {
+      OMX_VIDEO_CodingUnused,
+      OMX_VIDEO_CodingMax
+   };
+   OMX_COLOR_FORMATTYPE formats[] = {
+      OMX_COLOR_FormatYUV420SemiPlanar,
+      OMX_COLOR_FormatMax
+   };
+   tiz_port_options_t rawvideo_port_opts = {
+      OMX_PortDomainVideo,
+      OMX_DirOutput,
+      OMX_VID_DEC_AVC_OUTPUT_PORT_MIN_BUF_COUNT,
+      OMX_VID_DEC_AVC_PORT_MIN_OUTPUT_BUF_SIZE,
+      OMX_VID_DEC_AVC_PORT_NONCONTIGUOUS,
+      OMX_VID_DEC_AVC_PORT_ALIGNMENT,
+      OMX_VID_DEC_AVC_PORT_SUPPLIERPREF,
+      {OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, NULL, NULL, NULL},
+      0                     /* Master port */
+   };
+
+   portdef.pNativeRender = NULL;
+   portdef.nFrameWidth = OMX_VID_DEC_AVC_DEFAULT_FRAME_WIDTH;
+   portdef.nFrameHeight = OMX_VID_DEC_AVC_DEFAULT_FRAME_HEIGHT;
+   portdef.nStride = 0;
+   portdef.nSliceHeight = 0;
+   portdef.nBitrate = 64000;
+   portdef.xFramerate = OMX_VID_DEC_AVC_DEFAULT_FRAME_RATE;
+   portdef.bFlagErrorConcealment = OMX_FALSE;
+   portdef.eCompressionFormat = OMX_VIDEO_CodingUnused;
+   portdef.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+   portdef.pNativeWindow = NULL;
+
+   return factory_new(tiz_get_type(ap_hdl, "tizvideoport"),
+                      &rawvideo_port_opts, &portdef,
+                      &encodings, &formats);
+}
+
+OMX_PTR instantiate_h264d_config_port(OMX_HANDLETYPE ap_hdl)
+{
+   return factory_new(tiz_get_type(ap_hdl, "tizconfigport"),
+                      NULL, /* this port does not take options */
+                      OMX_VID_COMP_NAME, h264_decoder_version);
+}
+
+OMX_PTR instantiate_h264d_processor(OMX_HANDLETYPE ap_hdl)
+{
+   return factory_new(tiz_get_type(ap_hdl, "h264dprc"));
+}
diff --git a/src/gallium/state_trackers/omx/tizonia/h264d.h b/src/gallium/state_trackers/omx/tizonia/h264d.h
new file mode 100644 (file)
index 0000000..1733425
--- /dev/null
@@ -0,0 +1,40 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef H264D_H
+#define H264D_H
+
+#include <OMX_Core.h>
+#include <OMX_Types.h>
+#include <OMX_Video.h>
+
+OMX_PTR instantiate_h264d_config_port(OMX_HANDLETYPE ap_hdl);
+OMX_PTR instantiate_h264d_input_port(OMX_HANDLETYPE ap_hdl);
+OMX_PTR instantiate_h264d_output_port(OMX_HANDLETYPE ap_hdl);
+OMX_PTR instantiate_h264d_processor(OMX_HANDLETYPE ap_hdl);
+
+#endif                          /* H264D_H */
diff --git a/src/gallium/state_trackers/omx/tizonia/h264dinport.c b/src/gallium/state_trackers/omx/tizonia/h264dinport.c
new file mode 100644 (file)
index 0000000..858ae76
--- /dev/null
@@ -0,0 +1,147 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <string.h>
+#include <limits.h>
+
+#include <tizplatform.h>
+#include <tizkernel.h>
+
+#include "vl/vl_winsys.h"
+
+#include "h264d.h"
+#include "h264dinport.h"
+#include "h264dinport_decls.h"
+#include "vid_dec_common.h"
+
+/*
+ * h264dinport class
+ */
+
+static void * h264d_inport_ctor(void * ap_obj, va_list * app)
+{
+   return super_ctor(typeOf(ap_obj, "h264dinport"), ap_obj, app);
+}
+
+static void * h264d_inport_dtor(void * ap_obj)
+{
+   return super_dtor(typeOf(ap_obj, "h264dinport"), ap_obj);
+}
+
+/*
+ * from tiz_api
+ */
+
+static OMX_ERRORTYPE h264d_inport_SetParameter(const void * ap_obj, OMX_HANDLETYPE ap_hdl,
+                                               OMX_INDEXTYPE a_index, OMX_PTR ap_struct)
+{
+   OMX_ERRORTYPE err = OMX_ErrorNone;
+
+   assert(ap_obj);
+   assert(ap_hdl);
+   assert(ap_struct);
+
+   if (a_index == OMX_IndexParamPortDefinition) {
+      vid_dec_PrivateType * p_prc = tiz_get_prc(ap_hdl);
+      OMX_VIDEO_PORTDEFINITIONTYPE * p_def = &(p_prc->out_port_def_.format.video);
+      OMX_PARAM_PORTDEFINITIONTYPE * i_def = (OMX_PARAM_PORTDEFINITIONTYPE *) ap_struct;
+
+      /* Make changes only if there is a resolution change */
+      if ((p_def->nFrameWidth == i_def->format.video.nFrameWidth) &&
+          (p_def->nFrameHeight == i_def->format.video.nFrameHeight) &&
+          (p_def->eCompressionFormat == i_def->format.video.eCompressionFormat))
+         return err;
+
+      /* Set some default values if not set */
+      if (i_def->format.video.nStride == 0)
+         i_def->format.video.nStride = i_def->format.video.nFrameWidth;
+      if (i_def->format.video.nSliceHeight == 0)
+         i_def->format.video.nSliceHeight = i_def->format.video.nFrameHeight;
+
+      err = super_SetParameter(typeOf (ap_obj, "h264dinport"), ap_obj,
+                               ap_hdl, a_index, ap_struct);
+      if (err == OMX_ErrorNone) {
+         tiz_port_t * p_obj = (tiz_port_t *) ap_obj;
+
+         /* Set desired buffer size that will be used when allocating input buffers */
+         p_obj->portdef_.nBufferSize = i_def->format.video.nFrameWidth * i_def->format.video.nFrameHeight * 512 / (16*16);
+
+         /* Get a locally copy of port def. Useful for the early return above */
+         tiz_check_omx(tiz_api_GetParameter(tiz_get_krn(handleOf(p_prc)), handleOf(p_prc),
+                       OMX_IndexParamPortDefinition, &(p_prc->out_port_def_)));
+      }
+   }
+
+   return err;
+}
+
+/*
+ * h264dinport_class
+ */
+
+static void * h264d_inport_class_ctor(void * ap_obj, va_list * app)
+{
+   /* NOTE: Class methods might be added in the future. None for now. */
+   return super_ctor (typeOf (ap_obj, "h264dinport_class"), ap_obj, app);
+}
+
+/*
+ * initialization
+ */
+
+void * h264d_inport_class_init(void * ap_tos, void * ap_hdl)
+{
+   void * tizavcport = tiz_get_type(ap_hdl, "tizavcport");
+   void * h264dinport_class
+     = factory_new(classOf(tizavcport), "h264dinport_class",
+                   classOf(tizavcport), sizeof(h264d_inport_class_t),
+                   ap_tos, ap_hdl, ctor, h264d_inport_class_ctor, 0);
+   return h264dinport_class;
+}
+
+void * h264d_inport_init(void * ap_tos, void * ap_hdl)
+{
+   void * tizavcport = tiz_get_type (ap_hdl, "tizavcport");
+   void * h264dinport_class = tiz_get_type (ap_hdl, "h264dinport_class");
+   void * h264dinport = factory_new
+     /* TIZ_CLASS_COMMENT: class type, class name, parent, size */
+     (h264dinport_class, "h264dinport", tizavcport,
+      sizeof (h264d_inport_t),
+      /* TIZ_CLASS_COMMENT: class constructor */
+      ap_tos, ap_hdl,
+      /* TIZ_CLASS_COMMENT: class constructor */
+      ctor, h264d_inport_ctor,
+      /* TIZ_CLASS_COMMENT: class destructor */
+      dtor, h264d_inport_dtor,
+      /* TIZ_CLASS_COMMENT: */
+      tiz_api_SetParameter, h264d_inport_SetParameter,
+      /* TIZ_CLASS_COMMENT: stop value*/
+      0);
+
+   return h264dinport;
+}
diff --git a/src/gallium/state_trackers/omx/tizonia/h264dinport.h b/src/gallium/state_trackers/omx/tizonia/h264dinport.h
new file mode 100644 (file)
index 0000000..f158e4e
--- /dev/null
@@ -0,0 +1,31 @@
+/**************************************************************************
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef H264DINPORT_H
+#define H264DINPORT_H
+
+void * h264d_inport_class_init(void * ap_tos, void * ap_hdl);
+void * h264d_inport_init(void * ap_tos, void * ap_hdl);
+
+#endif /* H264DINPORT_H */
diff --git a/src/gallium/state_trackers/omx/tizonia/h264dinport_decls.h b/src/gallium/state_trackers/omx/tizonia/h264dinport_decls.h
new file mode 100644 (file)
index 0000000..0194f6e
--- /dev/null
@@ -0,0 +1,48 @@
+/**************************************************************************
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef H264DINPORT_DECLS_H
+#define H264DINPORT_DECLS_H
+
+#include <OMX_TizoniaExt.h>
+#include <OMX_Types.h>
+
+#include <tizavcport_decls.h>
+
+typedef struct h264d_inport h264d_inport_t;
+struct h264d_inport
+{
+   /* Object */
+   const tiz_avcport_t _;
+};
+
+typedef struct h264d_inport_class h264d_inport_class_t;
+struct h264d_inport_class
+{
+   /* Class */
+   const tiz_avcport_class_t _;
+   /* NOTE: Class methods might be added in the future */
+};
+
+#endif /* H264DINPORT_DECLS_H */
diff --git a/src/gallium/state_trackers/omx/tizonia/h264dprc.c b/src/gallium/state_trackers/omx/tizonia/h264dprc.c
new file mode 100644 (file)
index 0000000..a55e3e9
--- /dev/null
@@ -0,0 +1,519 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <tizplatform.h>
+#include <tizkernel.h>
+#include <tizutils.h>
+
+#include "entrypoint.h"
+#include "h264d.h"
+#include "h264dprc.h"
+#include "vid_omx_common.h"
+#include "vid_dec_common.h"
+#include "vid_dec_h264_common.h"
+
+#include "vl/vl_video_buffer.h"
+#include "vl/vl_compositor.h"
+#include "util/u_surface.h"
+
+unsigned dec_frame_delta;
+
+static void release_input_headers(vid_dec_PrivateType* priv) {
+   int i;
+   for (i = 0; i < priv->num_in_buffers; i++) {
+      assert(!priv->in_port_disabled_);
+      if (priv->in_buffers[i]->pInputPortPrivate) {
+         vid_dec_FreeInputPortPrivate(priv->in_buffers[i]);
+      }
+      (void) tiz_krn_release_buffer (tiz_get_krn (handleOf (priv)),
+                                     OMX_VID_DEC_AVC_INPUT_PORT_INDEX,
+                                     priv->in_buffers[i]);
+      priv->in_buffers[i] = NULL;
+   }
+   priv->p_inhdr_ = NULL;
+   priv->num_in_buffers = 0;
+}
+
+static void release_output_header(vid_dec_PrivateType* priv) {
+   if (priv->p_outhdr_) {
+      assert(!priv->out_port_disabled_);
+      (void) tiz_krn_release_buffer (tiz_get_krn (handleOf (priv)),
+                                     OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX,
+                                     priv->p_outhdr_);
+      priv->p_outhdr_ = NULL;
+   }
+}
+
+static OMX_ERRORTYPE h264d_release_all_headers(vid_dec_PrivateType* priv)
+{
+   assert(priv);
+   release_input_headers(priv);
+   release_output_header(priv);
+
+   return OMX_ErrorNone;
+}
+
+static void h264d_buffer_emptied(vid_dec_PrivateType* priv, OMX_BUFFERHEADERTYPE * p_hdr)
+{
+   assert(priv);
+   assert(priv->in_buffers[0] == p_hdr);
+
+   if (!priv->out_port_disabled_) {
+      assert (p_hdr->nFilledLen == 0);
+      p_hdr->nOffset = 0;
+
+      if ((p_hdr->nFlags & OMX_BUFFERFLAG_EOS) != 0) {
+         priv->eos_ = true;
+      }
+
+      (void) tiz_krn_release_buffer (tiz_get_krn (handleOf (priv)), 0, p_hdr);
+      priv->p_inhdr_ = NULL;
+      priv->in_buffers[0] = NULL;
+   }
+}
+
+static void h264d_buffer_filled(vid_dec_PrivateType* priv, OMX_BUFFERHEADERTYPE * p_hdr)
+{
+   assert(priv);
+   assert(p_hdr);
+   assert(priv->p_outhdr_ == p_hdr);
+
+   if (!priv->in_port_disabled_) {
+      p_hdr->nOffset = 0;
+
+      if (priv->eos_) {
+         /* EOS has been received and all the input data has been consumed
+          * already, so its time to propagate the EOS flag */
+         priv->p_outhdr_->nFlags |= OMX_BUFFERFLAG_EOS;
+         priv->eos_ = false;
+      }
+
+      (void) tiz_krn_release_buffer(tiz_get_krn (handleOf (priv)),
+                                    OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX,
+                                    p_hdr);
+      priv->p_outhdr_ = NULL;
+   }
+}
+
+static bool h264d_shift_buffers_left(vid_dec_PrivateType* priv) {
+   if (--priv->num_in_buffers) {
+      priv->in_buffers[0] = priv->in_buffers[1];
+      priv->sizes[0] = priv->sizes[1] - dec_frame_delta;
+      priv->inputs[0] = priv->inputs[1] + dec_frame_delta;
+      priv->timestamps[0] = priv->timestamps[1];
+
+      return true;
+   }
+   return false;
+}
+
+static OMX_BUFFERHEADERTYPE * get_input_buffer(vid_dec_PrivateType* priv) {
+   assert(priv);
+
+   if (priv->in_port_disabled_) {
+      return NULL;
+   }
+
+   if (priv->num_in_buffers > 1) {
+      /* The input buffer wasn't cleared last time. */
+      h264d_buffer_emptied(priv, priv->in_buffers[0]);
+      if (priv->in_buffers[0]) {
+         /* Failed to release buffer */
+         return NULL;
+      }
+      h264d_shift_buffers_left(priv);
+   }
+
+   /* Decode_frame expects new buffers each time */
+   assert(priv->p_inhdr_ || priv->first_buf_in_frame);
+   tiz_krn_claim_buffer(tiz_get_krn (handleOf (priv)),
+                        OMX_VID_DEC_AVC_INPUT_PORT_INDEX, 0,
+                        &priv->p_inhdr_);
+   return priv->p_inhdr_;
+}
+
+static OMX_BUFFERHEADERTYPE * get_output_buffer(vid_dec_PrivateType* priv) {
+   assert (priv);
+
+   if (priv->out_port_disabled_) {
+      return NULL;
+   }
+
+   if (!priv->p_outhdr_) {
+      tiz_krn_claim_buffer(tiz_get_krn (handleOf (priv)),
+                           OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, 0,
+                           &priv->p_outhdr_);
+   }
+   return priv->p_outhdr_;
+}
+
+static void reset_stream_parameters(vid_dec_PrivateType* apriv)
+{
+   assert(apriv);
+   TIZ_INIT_OMX_PORT_STRUCT(apriv->out_port_def_,
+                            OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX);
+
+   tiz_api_GetParameter (tiz_get_krn (handleOf (apriv)), handleOf (apriv),
+                          OMX_IndexParamPortDefinition, &(apriv->out_port_def_));
+
+   apriv->p_inhdr_ = 0;
+   apriv->num_in_buffers = 0;
+   apriv->first_buf_in_frame = true;
+   apriv->eos_ = false;
+   apriv->frame_finished = false;
+   apriv->frame_started = false;
+   apriv->picture.h264.field_order_cnt[0] = apriv->picture.h264.field_order_cnt[1] = INT_MAX;
+   apriv->slice = NULL;
+}
+
+/* Replacement for bellagio's omx_base_filter_BufferMgmtFunction */
+static void h264d_manage_buffers(vid_dec_PrivateType* priv) {
+   bool next_is_eos = priv->num_in_buffers == 2 ? !!(priv->in_buffers[1]->nFlags & OMX_BUFFERFLAG_EOS) : false;
+   vid_dec_FrameDecoded_common(priv, priv->in_buffers[0], priv->p_outhdr_);
+
+   priv->p_outhdr_->nTimeStamp = priv->in_buffers[0]->nTimeStamp;
+
+   /* Realase output buffer if filled or eos
+      Keep if two input buffers are being decoded */
+   if ((!next_is_eos) && ((priv->p_outhdr_->nFilledLen > 0) || priv->eos_)) {
+      h264d_buffer_filled(priv, priv->p_outhdr_);
+   }
+
+   /* Release input buffer if possible */
+   if (priv->in_buffers[0]->nFilledLen == 0) {
+      h264d_buffer_emptied(priv, priv->in_buffers[0]);
+   }
+}
+
+static OMX_ERRORTYPE decode_frame(vid_dec_PrivateType*priv,
+                                  OMX_BUFFERHEADERTYPE *in_buf)
+{
+   unsigned i = priv->num_in_buffers++;
+   priv->in_buffers[i] = in_buf;
+   priv->sizes[i] = in_buf->nFilledLen;
+   priv->inputs[i] = in_buf->pBuffer;
+   priv->timestamps[i] = in_buf->nTimeStamp;
+
+   while (priv->num_in_buffers > (!!(in_buf->nFlags & OMX_BUFFERFLAG_EOS) ? 0 : 1)) {
+      priv->eos_ = !!(priv->in_buffers[0]->nFlags & OMX_BUFFERFLAG_EOS);
+      unsigned min_bits_left = priv->eos_ ? 32 : MAX2(in_buf->nFilledLen * 8, 32);
+      struct vl_vlc vlc;
+
+      vl_vlc_init(&vlc, priv->num_in_buffers, priv->inputs, priv->sizes);
+
+      if (priv->slice)
+         priv->bytes_left = vl_vlc_bits_left(&vlc) / 8;
+
+      while (vl_vlc_bits_left (&vlc) > min_bits_left) {
+         vid_dec_h264_Decode(priv, &vlc, min_bits_left);
+         vl_vlc_fillbits(&vlc);
+      }
+
+      if (priv->slice) {
+         unsigned bytes = priv->bytes_left - vl_vlc_bits_left(&vlc) / 8;
+
+         priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base,
+                                 1, &priv->slice, &bytes);
+
+         if (priv->num_in_buffers)
+            priv->slice = priv->inputs[1];
+         else
+            priv->slice = NULL;
+      }
+
+      if (priv->eos_ && priv->frame_started)
+         vid_dec_h264_EndFrame(priv);
+
+      if (priv->frame_finished) {
+         priv->frame_finished = false;
+         h264d_manage_buffers(priv);
+      } else if (priv->eos_) {
+         vid_dec_FreeInputPortPrivate(priv->in_buffers[0]);
+         h264d_manage_buffers(priv);
+      } else {
+         priv->in_buffers[0]->nFilledLen = 0;
+         h264d_buffer_emptied(priv, priv->in_buffers[0]);
+      }
+
+      if (priv->out_port_disabled_) {
+         /* In case out port is disabled, h264d_buffer_emptied will fail to release input port.
+          * We need to wait before shifting the buffers in that case and check in
+          * get_input_buffer when out port is enabled to release and shift the buffers.
+          * Infinite looping occurs if buffer is not released */
+         if (priv->num_in_buffers == 2) {
+            /* Set the delta value for use in get_input_buffer before exiting */
+            dec_frame_delta = MIN2((min_bits_left - vl_vlc_bits_left(&vlc)) / 8, priv->sizes[1]);
+         }
+         break;
+      }
+
+      h264d_shift_buffers_left(priv);
+   }
+
+   return OMX_ErrorNone;
+}
+
+/*
+ * h264dprc
+ */
+
+static void * h264d_prc_ctor(void *ap_obj, va_list * app)
+{
+   vid_dec_PrivateType*priv = super_ctor(typeOf (ap_obj, "h264dprc"), ap_obj, app);
+   assert(priv);
+   priv->p_inhdr_ = 0;
+   priv->p_outhdr_ = 0;
+   priv->first_buf_in_frame = true;
+   priv->eos_ = false;
+   priv->in_port_disabled_   = false;
+   priv->out_port_disabled_   = false;
+   priv->picture.base.profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH;
+   priv->profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH;
+   reset_stream_parameters(priv);
+
+   return priv;
+}
+
+static void * h264d_prc_dtor(void *ap_obj)
+{
+   return super_dtor(typeOf(ap_obj, "h264dprc"), ap_obj);
+}
+
+static OMX_ERRORTYPE h264d_prc_allocate_resources(void *ap_obj, OMX_U32 a_pid)
+{
+   vid_dec_PrivateType*priv = ap_obj;
+   struct pipe_screen *screen;
+
+   assert (priv);
+
+   priv->screen = omx_get_screen();
+   if (!priv->screen)
+      return OMX_ErrorInsufficientResources;
+
+   screen = priv->screen->pscreen;
+   priv->pipe = screen->context_create(screen, priv->screen, 0);
+   if (!priv->pipe)
+      return OMX_ErrorInsufficientResources;
+
+   if (!vl_compositor_init(&priv->compositor, priv->pipe)) {
+      priv->pipe->destroy(priv->pipe);
+      priv->pipe = NULL;
+      return OMX_ErrorInsufficientResources;
+   }
+
+   if (!vl_compositor_init_state(&priv->cstate, priv->pipe)) {
+      vl_compositor_cleanup(&priv->compositor);
+      priv->pipe->destroy(priv->pipe);
+      priv->pipe = NULL;
+      return OMX_ErrorInsufficientResources;
+   }
+
+   LIST_INITHEAD(&priv->codec_data.h264.dpb_list);
+
+   return OMX_ErrorNone;
+}
+
+static OMX_ERRORTYPE h264d_prc_deallocate_resources(void *ap_obj)
+{
+   vid_dec_PrivateType*priv = ap_obj;
+   assert(priv);
+
+   if (priv->pipe) {
+      vl_compositor_cleanup_state(&priv->cstate);
+      vl_compositor_cleanup(&priv->compositor);
+      priv->pipe->destroy(priv->pipe);
+   }
+
+   if (priv->screen)
+      omx_put_screen();
+
+   return OMX_ErrorNone;
+}
+
+static OMX_ERRORTYPE h264d_prc_prepare_to_transfer(void *ap_obj, OMX_U32 a_pid)
+{
+   vid_dec_PrivateType*priv = ap_obj;
+   assert(priv);
+
+   TIZ_INIT_OMX_PORT_STRUCT(priv->out_port_def_,
+                            OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX);
+   tiz_check_omx(
+      tiz_api_GetParameter(tiz_get_krn(handleOf(priv)), handleOf(priv),
+                           OMX_IndexParamPortDefinition, &(priv->out_port_def_)));
+
+   priv->first_buf_in_frame = true;
+   priv->eos_ = false;
+   return OMX_ErrorNone;
+}
+
+static OMX_ERRORTYPE h264d_prc_transfer_and_process(void *ap_obj, OMX_U32 a_pid)
+{
+   return OMX_ErrorNone;
+}
+
+static OMX_ERRORTYPE h264d_prc_stop_and_return(void *ap_obj)
+{
+   vid_dec_PrivateType*priv = (vid_dec_PrivateType*) ap_obj;
+   return h264d_release_all_headers (priv);
+}
+
+static OMX_ERRORTYPE h264d_prc_buffers_ready(const void *ap_obj)
+{
+   vid_dec_PrivateType*priv = (vid_dec_PrivateType*) ap_obj;
+   OMX_BUFFERHEADERTYPE *in_buf = NULL;
+   OMX_BUFFERHEADERTYPE *out_buf = NULL;
+
+   assert(priv);
+
+   /* Set parameters if start of stream */
+   if (!priv->eos_ && priv->first_buf_in_frame && (in_buf = get_input_buffer(priv))) {
+      decode_frame(priv, in_buf);
+   }
+
+   /* Don't get input buffer if output buffer not found */
+   while (!priv->eos_ && (out_buf = get_output_buffer(priv)) && (in_buf = get_input_buffer(priv))) {
+      if (!priv->out_port_disabled_) {
+         decode_frame(priv, in_buf);
+      }
+   }
+
+   return OMX_ErrorNone;
+}
+
+static OMX_ERRORTYPE h264d_prc_port_flush(const void *ap_obj, OMX_U32 a_pid)
+{
+   vid_dec_PrivateType*priv = (vid_dec_PrivateType*) ap_obj;
+   if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_INPUT_PORT_INDEX == a_pid) {
+      release_input_headers(priv);
+      reset_stream_parameters(priv);
+   }
+   if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX == a_pid) {
+      release_output_header(priv);
+   }
+   return OMX_ErrorNone;
+}
+
+static OMX_ERRORTYPE h264d_prc_port_disable(const void *ap_obj, OMX_U32 a_pid)
+{
+   vid_dec_PrivateType*priv = (vid_dec_PrivateType*) ap_obj;
+   assert(priv);
+   if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_INPUT_PORT_INDEX == a_pid) {
+      /* Release all buffers */
+      h264d_release_all_headers(priv);
+      reset_stream_parameters(priv);
+      priv->in_port_disabled_ = true;
+   }
+   if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX == a_pid) {
+      release_output_header(priv);
+      priv->out_port_disabled_ = true;
+   }
+   return OMX_ErrorNone;
+}
+
+static OMX_ERRORTYPE h264d_prc_port_enable(const void *ap_obj, OMX_U32 a_pid)
+{
+   vid_dec_PrivateType* priv = (vid_dec_PrivateType*) ap_obj;
+   assert(priv);
+   if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_INPUT_PORT_INDEX == a_pid) {
+      if (priv->in_port_disabled_) {
+         reset_stream_parameters(priv);
+         priv->in_port_disabled_ = false;
+      }
+   }
+   if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX == a_pid) {
+      priv->out_port_disabled_ = false;
+   }
+   return OMX_ErrorNone;
+}
+
+/*
+ * h264d_prc_class
+ */
+
+static void * h264d_prc_class_ctor(void *ap_obj, va_list * app)
+{
+   /* NOTE: Class methods might be added in the future. None for now. */
+   return super_ctor(typeOf(ap_obj, "h264dprc_class"), ap_obj, app);
+}
+
+/*
+ * initialization
+ */
+
+void * h264d_prc_class_init(void * ap_tos, void * ap_hdl)
+{
+   void * tizprc = tiz_get_type(ap_hdl, "tizprc");
+   void * h264dprc_class = factory_new
+      /* TIZ_CLASS_COMMENT: class type, class name, parent, size */
+      (classOf(tizprc), "h264dprc_class", classOf(tizprc),
+       sizeof(h264d_prc_class_t),
+       /* TIZ_CLASS_COMMENT: */
+       ap_tos, ap_hdl,
+       /* TIZ_CLASS_COMMENT: class constructor */
+       ctor, h264d_prc_class_ctor,
+       /* TIZ_CLASS_COMMENT: stop value*/
+       0);
+   return h264dprc_class;
+}
+
+void * h264d_prc_init(void * ap_tos, void * ap_hdl)
+{
+   void * tizprc = tiz_get_type(ap_hdl, "tizprc");
+   void * h264dprc_class = tiz_get_type(ap_hdl, "h264dprc_class");
+   TIZ_LOG_CLASS (h264dprc_class);
+   void * h264dprc = factory_new
+     /* TIZ_CLASS_COMMENT: class type, class name, parent, size */
+     (h264dprc_class, "h264dprc", tizprc, sizeof(vid_dec_PrivateType),
+      /* TIZ_CLASS_COMMENT: */
+      ap_tos, ap_hdl,
+      /* TIZ_CLASS_COMMENT: class constructor */
+      ctor, h264d_prc_ctor,
+      /* TIZ_CLASS_COMMENT: class destructor */
+      dtor, h264d_prc_dtor,
+      /* TIZ_CLASS_COMMENT: */
+      tiz_srv_allocate_resources, h264d_prc_allocate_resources,
+      /* TIZ_CLASS_COMMENT: */
+      tiz_srv_deallocate_resources, h264d_prc_deallocate_resources,
+      /* TIZ_CLASS_COMMENT: */
+      tiz_srv_prepare_to_transfer, h264d_prc_prepare_to_transfer,
+      /* TIZ_CLASS_COMMENT: */
+      tiz_srv_transfer_and_process, h264d_prc_transfer_and_process,
+      /* TIZ_CLASS_COMMENT: */
+      tiz_srv_stop_and_return, h264d_prc_stop_and_return,
+      /* TIZ_CLASS_COMMENT: */
+      tiz_prc_buffers_ready, h264d_prc_buffers_ready,
+      /* TIZ_CLASS_COMMENT: */
+      tiz_prc_port_flush, h264d_prc_port_flush,
+      /* TIZ_CLASS_COMMENT: */
+      tiz_prc_port_disable, h264d_prc_port_disable,
+      /* TIZ_CLASS_COMMENT: */
+      tiz_prc_port_enable, h264d_prc_port_enable,
+      /* TIZ_CLASS_COMMENT: stop value*/
+      0);
+
+   return h264dprc;
+}
diff --git a/src/gallium/state_trackers/omx/tizonia/h264dprc.h b/src/gallium/state_trackers/omx/tizonia/h264dprc.h
new file mode 100644 (file)
index 0000000..08af549
--- /dev/null
@@ -0,0 +1,31 @@
+/**************************************************************************
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef H264DPRC_H
+#define H264DPRC_H
+
+void * h264d_prc_class_init(void * ap_tos, void * ap_hdl);
+void * h264d_prc_init(void * ap_tos, void * ap_hdl);
+
+#endif                          /* H264DPRC_H */
diff --git a/src/gallium/state_trackers/omx/tizonia/names.h b/src/gallium/state_trackers/omx/tizonia/names.h
new file mode 100644 (file)
index 0000000..edde7df
--- /dev/null
@@ -0,0 +1,30 @@
+/**************************************************************************
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef OMX_TIZ_NAMES_H
+#define OMX_TIZ_NAMES_H
+
+#define OMX_VID_COMP_NAME "OMX.mesa.video.all"
+
+#endif
diff --git a/src/gallium/state_trackers/omx/vid_dec_common.c b/src/gallium/state_trackers/omx/vid_dec_common.c
new file mode 100644 (file)
index 0000000..56010ca
--- /dev/null
@@ -0,0 +1,117 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#if ENABLE_ST_OMX_TIZONIA
+#include <tizkernel.h>
+#endif
+
+#include "util/u_memory.h"
+#include "vl/vl_winsys.h"
+#include "vl/vl_video_buffer.h"
+#include "util/u_surface.h"
+
+#include "vid_dec_common.h"
+#include "vid_dec_h264_common.h"
+
+void vid_dec_NeedTarget(vid_dec_PrivateType *priv)
+{
+   struct pipe_video_buffer templat = {};
+   struct vl_screen *omx_screen;
+   struct pipe_screen *pscreen;
+
+   omx_screen = priv->screen;
+   assert(omx_screen);
+
+   pscreen = omx_screen->pscreen;
+   assert(pscreen);
+
+   if (!priv->target) {
+      memset(&templat, 0, sizeof(templat));
+
+      templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
+      templat.width = priv->codec->width;
+      templat.height = priv->codec->height;
+      templat.buffer_format = pscreen->get_video_param(
+            pscreen,
+            PIPE_VIDEO_PROFILE_UNKNOWN,
+            PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
+            PIPE_VIDEO_CAP_PREFERED_FORMAT
+      );
+      templat.interlaced = pscreen->get_video_param(
+          pscreen,
+          PIPE_VIDEO_PROFILE_UNKNOWN,
+          PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
+          PIPE_VIDEO_CAP_PREFERS_INTERLACED
+      );
+
+      priv->target = priv->pipe->create_video_buffer(priv->pipe, &templat);
+   }
+}
+
+void vid_dec_FillOutput(vid_dec_PrivateType *priv, struct pipe_video_buffer *buf,
+                        OMX_BUFFERHEADERTYPE* output)
+{
+#if ENABLE_ST_OMX_TIZONIA
+   tiz_port_t *out_port = tiz_krn_get_port(tiz_get_krn(handleOf(priv)),
+                                           OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX);
+   OMX_VIDEO_PORTDEFINITIONTYPE *def = &out_port->portdef_.format.video;
+#else
+   omx_base_PortType *port = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX];
+   OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video;
+#endif
+
+   struct pipe_sampler_view **views;
+   unsigned i, j;
+   unsigned width, height;
+
+   views = buf->get_sampler_view_planes(buf);
+
+   for (i = 0; i < 2 /* NV12 */; i++) {
+      if (!views[i]) continue;
+      width = def->nFrameWidth;
+      height = def->nFrameHeight;
+      vl_video_buffer_adjust_size(&width, &height, i, buf->chroma_format, buf->interlaced);
+      for (j = 0; j < views[i]->texture->array_size; ++j) {
+         struct pipe_box box = {0, 0, j, width, height, 1};
+         struct pipe_transfer *transfer;
+         uint8_t *map, *dst;
+         map = priv->pipe->transfer_map(priv->pipe, views[i]->texture, 0,
+                  PIPE_TRANSFER_READ, &box, &transfer);
+         if (!map)
+            return;
+
+         dst = ((uint8_t*)output->pBuffer + output->nOffset) + j * def->nStride +
+               i * def->nFrameWidth * def->nFrameHeight;
+         util_copy_rect(dst,
+            views[i]->texture->format,
+            def->nStride * views[i]->texture->array_size, 0, 0,
+            box.width, box.height, map, transfer->stride, 0, 0);
+
+         pipe_transfer_unmap(priv->pipe, transfer);
+      }
+   }
+}
diff --git a/src/gallium/state_trackers/omx/vid_dec_common.h b/src/gallium/state_trackers/omx/vid_dec_common.h
new file mode 100644 (file)
index 0000000..dea7149
--- /dev/null
@@ -0,0 +1,194 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef VID_DEC_COMMON_H
+#define VID_DEC_COMMON_H
+
+#include "util/list.h"
+
+#include "vl/vl_compositor.h"
+#include "vl/vl_rbsp.h"
+#include "vl/vl_zscan.h"
+
+#include <OMX_Core.h>
+#include <OMX_Types.h>
+
+#if ENABLE_ST_OMX_BELLAGIO
+
+#include <bellagio/st_static_component_loader.h>
+#include <bellagio/omx_base_filter.h>
+#include <bellagio/omx_base_video_port.h>
+
+DERIVEDCLASS(vid_dec_PrivateType, omx_base_filter_PrivateType)
+#define vid_dec_PrivateType_FIELDS omx_base_filter_PrivateType_FIELDS \
+   enum pipe_video_profile profile; \
+   struct vl_screen *screen; \
+   struct pipe_context *pipe; \
+   struct pipe_video_codec *codec; \
+   void (*Decode)(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); \
+   void (*EndFrame)(vid_dec_PrivateType *priv); \
+   struct pipe_video_buffer *(*Flush)(vid_dec_PrivateType *priv, OMX_TICKS *timestamp); \
+   struct pipe_video_buffer *target, *shadow; \
+   union { \
+      struct { \
+         uint8_t intra_matrix[64]; \
+         uint8_t non_intra_matrix[64]; \
+      } mpeg12; \
+      struct { \
+         unsigned nal_ref_idc; \
+         bool IdrPicFlag; \
+         unsigned idr_pic_id; \
+         unsigned pic_order_cnt_lsb; \
+         unsigned pic_order_cnt_msb; \
+         unsigned delta_pic_order_cnt_bottom; \
+         unsigned delta_pic_order_cnt[2]; \
+         unsigned prevFrameNumOffset; \
+         struct pipe_h264_sps sps[32]; \
+         struct pipe_h264_pps pps[256]; \
+         struct list_head dpb_list; \
+         unsigned dpb_num; \
+      } h264; \
+      struct { \
+         unsigned temporal_id; \
+         unsigned level_idc; \
+         unsigned pic_width_in_luma_samples; \
+         unsigned pic_height_in_luma_samples; \
+         bool IdrPicFlag; \
+         int slice_prev_poc; \
+         void *ref_pic_set_list; \
+         void *rps; \
+         struct pipe_h265_sps sps[16]; \
+         struct pipe_h265_pps pps[64]; \
+         struct list_head dpb_list; \
+         unsigned dpb_num; \
+      } h265; \
+   } codec_data; \
+   union { \
+      struct pipe_picture_desc base; \
+      struct pipe_mpeg12_picture_desc mpeg12; \
+      struct pipe_h264_picture_desc h264; \
+      struct pipe_h265_picture_desc h265; \
+   } picture; \
+   unsigned num_in_buffers; \
+   OMX_BUFFERHEADERTYPE *in_buffers[2]; \
+   const void *inputs[2]; \
+   unsigned sizes[2]; \
+   OMX_TICKS timestamps[2]; \
+   OMX_TICKS timestamp; \
+   bool first_buf_in_frame; \
+   bool frame_finished; \
+   bool frame_started; \
+   unsigned bytes_left; \
+   const void *slice; \
+   bool disable_tunnel; \
+   struct vl_compositor compositor; \
+   struct vl_compositor_state cstate;
+ENDCLASS(vid_dec_PrivateType)
+
+#else
+
+#include <tizprc_decls.h>
+#include <tizport_decls.h>
+
+#include "util/list.h"
+
+#include "pipe/p_video_state.h"
+
+typedef struct h264d_prc_class h264d_prc_class_t;
+struct h264d_prc_class
+{
+   /* Class */
+   const tiz_prc_class_t _;
+   /* NOTE: Class methods might be added in the future */
+};
+
+typedef struct h264d_stream_info h264d_stream_info_t;
+struct h264d_stream_info
+{
+   unsigned int width;
+   unsigned int height;
+};
+
+typedef struct h264d_prc vid_dec_PrivateType;
+struct h264d_prc
+{
+   /* Object */
+   const tiz_prc_t _;
+   OMX_BUFFERHEADERTYPE *in_buffers[2];
+   OMX_BUFFERHEADERTYPE *p_inhdr_;
+   OMX_BUFFERHEADERTYPE *p_outhdr_;
+   OMX_PARAM_PORTDEFINITIONTYPE out_port_def_;
+   const void *inputs[2];
+   unsigned sizes[2];
+   OMX_TICKS timestamps[2];
+   OMX_TICKS timestamp;
+   bool eos_;
+   bool in_port_disabled_;
+   bool out_port_disabled_;
+   struct vl_screen *screen;
+   struct pipe_context *pipe;
+   struct pipe_video_codec *codec;
+   struct pipe_video_buffer *target;
+   enum pipe_video_profile profile;
+   union {
+         struct {
+            unsigned nal_ref_idc;
+            bool IdrPicFlag;
+            unsigned idr_pic_id;
+            unsigned pic_order_cnt_lsb;
+            unsigned pic_order_cnt_msb;
+            unsigned delta_pic_order_cnt_bottom;
+            unsigned delta_pic_order_cnt[2];
+            unsigned prevFrameNumOffset;
+            struct pipe_h264_sps sps[32];
+            struct pipe_h264_pps pps[256];
+            struct list_head dpb_list;
+            unsigned dpb_num;
+         } h264;
+   } codec_data;
+   union {
+      struct pipe_picture_desc base;
+      struct pipe_h264_picture_desc h264;
+   } picture;
+   h264d_stream_info_t stream_info;
+   unsigned num_in_buffers;
+   bool first_buf_in_frame;
+   bool frame_finished;
+   bool frame_started;
+   unsigned bytes_left;
+   const void *slice;
+   bool disable_tunnel;
+   struct vl_compositor compositor;
+   struct vl_compositor_state cstate;
+};
+
+#endif
+
+void vid_dec_NeedTarget(vid_dec_PrivateType* priv);
+void vid_dec_FillOutput(vid_dec_PrivateType* priv, struct pipe_video_buffer* buf,
+                        OMX_BUFFERHEADERTYPE* output);
+#endif
diff --git a/src/gallium/state_trackers/omx/vid_dec_h264_common.c b/src/gallium/state_trackers/omx/vid_dec_h264_common.c
new file mode 100644 (file)
index 0000000..1965e68
--- /dev/null
@@ -0,0 +1,1138 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#if ENABLE_ST_OMX_TIZONIA
+#include <tizkernel.h>
+#endif
+
+#include "util/u_memory.h"
+
+#include "vid_dec_h264_common.h"
+
+static void vid_dec_h264_BeginFrame(vid_dec_PrivateType *priv)
+{
+   //TODO: sane buffer handling
+
+   if (priv->frame_started)
+      return;
+
+   if (!priv->codec) {
+      struct pipe_video_codec templat = {};
+      templat.profile = priv->profile;
+      templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM;
+      templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
+      templat.max_references = priv->picture.h264.num_ref_frames;
+      templat.expect_chunked_decode = true;
+#if ENABLE_ST_OMX_BELLAGIO
+      omx_base_video_PortType *port;
+      port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];
+      templat.width = port->sPortParam.format.video.nFrameWidth;
+      templat.height = port->sPortParam.format.video.nFrameHeight;
+#else
+      templat.width = priv->out_port_def_.format.video.nFrameWidth;
+      templat.height = priv->out_port_def_.format.video.nFrameHeight;
+#endif
+      templat.level = priv->picture.h264.pps->sps->level_idc;
+
+      priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat);
+   }
+
+   vid_dec_NeedTarget(priv);
+
+   if (priv->first_buf_in_frame)
+      priv->timestamp = priv->timestamps[0];
+   priv->first_buf_in_frame = false;
+
+   priv->picture.h264.num_ref_frames = priv->picture.h264.pps->sps->max_num_ref_frames;
+
+   priv->picture.h264.slice_count = 0;
+   priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base);
+   priv->frame_started = true;
+}
+
+struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv,
+                                             OMX_TICKS *timestamp)
+{
+   struct dpb_list *entry, *result = NULL;
+   struct pipe_video_buffer *buf;
+
+   /* search for the lowest poc and break on zeros */
+   LIST_FOR_EACH_ENTRY(entry, &priv->codec_data.h264.dpb_list, list) {
+
+      if (result && entry->poc == 0)
+         break;
+
+      if (!result || entry->poc < result->poc)
+         result = entry;
+   }
+
+   if (!result)
+      return NULL;
+
+   buf = result->buffer;
+   if (timestamp)
+      *timestamp = result->timestamp;
+
+   --priv->codec_data.h264.dpb_num;
+   LIST_DEL(&result->list);
+   FREE(result);
+
+   return buf;
+}
+
+void vid_dec_h264_EndFrame(vid_dec_PrivateType *priv)
+{
+   struct dpb_list *entry;
+   struct pipe_video_buffer *tmp;
+   bool top_field_first;
+   OMX_TICKS timestamp;
+
+   if (!priv->frame_started)
+      return;
+
+   priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base);
+   priv->frame_started = false;
+
+   // TODO: implement frame number handling
+   priv->picture.h264.frame_num_list[0] = priv->picture.h264.frame_num;
+   priv->picture.h264.field_order_cnt_list[0][0] = priv->picture.h264.frame_num;
+   priv->picture.h264.field_order_cnt_list[0][1] = priv->picture.h264.frame_num;
+
+   top_field_first = priv->picture.h264.field_order_cnt[0] <  priv->picture.h264.field_order_cnt[1];
+
+   if (priv->picture.h264.field_pic_flag && priv->picture.h264.bottom_field_flag != top_field_first)
+      return;
+
+   /* add the decoded picture to the dpb list */
+   entry = CALLOC_STRUCT(dpb_list);
+   if (!entry)
+      return;
+
+   priv->first_buf_in_frame = true;
+   entry->buffer = priv->target;
+   entry->timestamp = priv->timestamp;
+   entry->poc = MIN2(priv->picture.h264.field_order_cnt[0], priv->picture.h264.field_order_cnt[1]);
+   LIST_ADDTAIL(&entry->list, &priv->codec_data.h264.dpb_list);
+   ++priv->codec_data.h264.dpb_num;
+   priv->target = NULL;
+   priv->picture.h264.field_order_cnt[0] = priv->picture.h264.field_order_cnt[1] = INT_MAX;
+
+   if (priv->codec_data.h264.dpb_num <= DPB_MAX_SIZE)
+      return;
+
+   tmp = priv->in_buffers[0]->pInputPortPrivate;
+   priv->in_buffers[0]->pInputPortPrivate = vid_dec_h264_Flush(priv, &timestamp);
+   priv->in_buffers[0]->nTimeStamp = timestamp;
+   priv->target = tmp;
+   priv->frame_finished = priv->in_buffers[0]->pInputPortPrivate != NULL;
+}
+
+static void vui_parameters(struct vl_rbsp *rbsp)
+{
+   // TODO
+}
+
+static void scaling_list(struct vl_rbsp *rbsp, uint8_t *scalingList, unsigned sizeOfScalingList,
+                         const uint8_t *defaultList, const uint8_t *fallbackList)
+{
+   unsigned lastScale = 8, nextScale = 8;
+   const int *list;
+   unsigned i;
+
+   /* (pic|seq)_scaling_list_present_flag[i] */
+   if (!vl_rbsp_u(rbsp, 1)) {
+      if (fallbackList)
+         memcpy(scalingList, fallbackList, sizeOfScalingList);
+      return;
+   }
+
+   list = (sizeOfScalingList == 16) ? vl_zscan_normal_16 : vl_zscan_normal;
+   for (i = 0; i < sizeOfScalingList; ++i ) {
+
+      if (nextScale != 0) {
+         signed delta_scale = vl_rbsp_se(rbsp);
+         nextScale = (lastScale + delta_scale + 256) % 256;
+         if (i == 0 && nextScale == 0) {
+            memcpy(scalingList, defaultList, sizeOfScalingList);
+            return;
+         }
+      }
+      scalingList[list[i]] = nextScale == 0 ? lastScale : nextScale;
+      lastScale = scalingList[list[i]];
+   }
+}
+
+static struct pipe_h264_sps *seq_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp)
+{
+   unsigned id = vl_rbsp_ue(rbsp);
+   if (id >= ARRAY_SIZE(priv->codec_data.h264.sps))
+      return NULL; /* invalid seq_parameter_set_id */
+
+   return &priv->codec_data.h264.sps[id];
+}
+
+static void seq_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp)
+{
+   struct pipe_h264_sps *sps;
+   unsigned profile_idc, level_idc;
+   unsigned i;
+
+   /* Sequence parameter set */
+   profile_idc = vl_rbsp_u(rbsp, 8);
+
+   /* constraint_set0_flag */
+   vl_rbsp_u(rbsp, 1);
+
+   /* constraint_set1_flag */
+   vl_rbsp_u(rbsp, 1);
+
+   /* constraint_set2_flag */
+   vl_rbsp_u(rbsp, 1);
+
+   /* constraint_set3_flag */
+   vl_rbsp_u(rbsp, 1);
+
+   /* constraint_set4_flag */
+   vl_rbsp_u(rbsp, 1);
+
+   /* constraint_set5_flag */
+   vl_rbsp_u(rbsp, 1);
+
+   /* reserved_zero_2bits */
+   vl_rbsp_u(rbsp, 2);
+
+   /* level_idc */
+   level_idc = vl_rbsp_u(rbsp, 8);
+
+   sps = seq_parameter_set_id(priv, rbsp);
+   if (!sps)
+      return;
+
+   memset(sps, 0, sizeof(*sps));
+   memset(sps->ScalingList4x4, 16, sizeof(sps->ScalingList4x4));
+   memset(sps->ScalingList8x8, 16, sizeof(sps->ScalingList8x8));
+
+   sps->level_idc = level_idc;
+
+   if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 ||
+       profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118 ||
+       profile_idc == 128 || profile_idc == 138) {
+
+      sps->chroma_format_idc = vl_rbsp_ue(rbsp);
+
+      if (sps->chroma_format_idc == 3)
+         sps->separate_colour_plane_flag = vl_rbsp_u(rbsp, 1);
+
+      sps->bit_depth_luma_minus8 = vl_rbsp_ue(rbsp);
+
+      sps->bit_depth_chroma_minus8 = vl_rbsp_ue(rbsp);
+
+      /* qpprime_y_zero_transform_bypass_flag */
+      vl_rbsp_u(rbsp, 1);
+
+      sps->seq_scaling_matrix_present_flag = vl_rbsp_u(rbsp, 1);
+      if (sps->seq_scaling_matrix_present_flag) {
+
+         scaling_list(rbsp, sps->ScalingList4x4[0], 16, Default_4x4_Intra, Default_4x4_Intra);
+         scaling_list(rbsp, sps->ScalingList4x4[1], 16, Default_4x4_Intra, sps->ScalingList4x4[0]);
+         scaling_list(rbsp, sps->ScalingList4x4[2], 16, Default_4x4_Intra, sps->ScalingList4x4[1]);
+         scaling_list(rbsp, sps->ScalingList4x4[3], 16, Default_4x4_Inter, Default_4x4_Inter);
+         scaling_list(rbsp, sps->ScalingList4x4[4], 16, Default_4x4_Inter, sps->ScalingList4x4[3]);
+         scaling_list(rbsp, sps->ScalingList4x4[5], 16, Default_4x4_Inter, sps->ScalingList4x4[4]);
+
+         scaling_list(rbsp, sps->ScalingList8x8[0], 64, Default_8x8_Intra, Default_8x8_Intra);
+         scaling_list(rbsp, sps->ScalingList8x8[1], 64, Default_8x8_Inter, Default_8x8_Inter);
+         if (sps->chroma_format_idc == 3) {
+            scaling_list(rbsp, sps->ScalingList8x8[2], 64, Default_8x8_Intra, sps->ScalingList8x8[0]);
+            scaling_list(rbsp, sps->ScalingList8x8[3], 64, Default_8x8_Inter, sps->ScalingList8x8[1]);
+            scaling_list(rbsp, sps->ScalingList8x8[4], 64, Default_8x8_Intra, sps->ScalingList8x8[2]);
+            scaling_list(rbsp, sps->ScalingList8x8[5], 64, Default_8x8_Inter, sps->ScalingList8x8[3]);
+         }
+      }
+   } else if (profile_idc == 183)
+      sps->chroma_format_idc = 0;
+   else
+      sps->chroma_format_idc = 1;
+
+   sps->log2_max_frame_num_minus4 = vl_rbsp_ue(rbsp);
+
+   sps->pic_order_cnt_type = vl_rbsp_ue(rbsp);
+
+   if (sps->pic_order_cnt_type == 0)
+      sps->log2_max_pic_order_cnt_lsb_minus4 = vl_rbsp_ue(rbsp);
+   else if (sps->pic_order_cnt_type == 1) {
+      sps->delta_pic_order_always_zero_flag = vl_rbsp_u(rbsp, 1);
+
+      sps->offset_for_non_ref_pic = vl_rbsp_se(rbsp);
+
+      sps->offset_for_top_to_bottom_field = vl_rbsp_se(rbsp);
+
+      sps->num_ref_frames_in_pic_order_cnt_cycle = vl_rbsp_ue(rbsp);
+
+      for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i)
+         sps->offset_for_ref_frame[i] = vl_rbsp_se(rbsp);
+   }
+
+   sps->max_num_ref_frames = vl_rbsp_ue(rbsp);
+
+   /* gaps_in_frame_num_value_allowed_flag */
+   vl_rbsp_u(rbsp, 1);
+
+   /* pic_width_in_mbs_minus1 */
+   int pic_width_in_samplesl = (vl_rbsp_ue(rbsp) + 1) * 16;
+   assert(pic_width_in_samplesl);
+
+   /* pic_height_in_map_units_minus1 */
+   int pic_height_in_map_units = vl_rbsp_ue(rbsp) + 1;
+   assert(pic_height_in_map_units);
+
+   sps->frame_mbs_only_flag = vl_rbsp_u(rbsp, 1);
+   if (!sps->frame_mbs_only_flag)
+      sps->mb_adaptive_frame_field_flag = vl_rbsp_u(rbsp, 1);
+
+   sps->direct_8x8_inference_flag = vl_rbsp_u(rbsp, 1);
+
+#if ENABLE_ST_OMX_TIZONIA
+   priv->stream_info.width = pic_width_in_samplesl;
+
+   int frame_height_in_mbs = (2 - sps->frame_mbs_only_flag) * pic_height_in_map_units;
+   int pic_height_in_mbs = frame_height_in_mbs / ( 1 + priv->picture.h264.field_pic_flag );
+   int pic_height_in_samplesl = pic_height_in_mbs * 16;
+   priv->stream_info.height = pic_height_in_samplesl;
+
+
+   /* frame_cropping_flag */
+   if (vl_rbsp_u(rbsp, 1)) {
+      unsigned frame_crop_left_offset = vl_rbsp_ue(rbsp);
+      unsigned frame_crop_right_offset = vl_rbsp_ue(rbsp);
+      unsigned frame_crop_top_offset = vl_rbsp_ue(rbsp);
+      unsigned frame_crop_bottom_offset = vl_rbsp_ue(rbsp);
+
+      priv->stream_info.width -= (frame_crop_left_offset + frame_crop_right_offset) * 2;
+      priv->stream_info.height -= (frame_crop_top_offset + frame_crop_bottom_offset) * 2;
+   }
+#else
+   /* frame_cropping_flag */
+   if (vl_rbsp_u(rbsp, 1)) {
+      /* frame_crop_left_offset */
+      vl_rbsp_ue(rbsp);
+
+      /* frame_crop_right_offset */
+      vl_rbsp_ue(rbsp);
+
+      /* frame_crop_top_offset */
+      vl_rbsp_ue(rbsp);
+
+      /* frame_crop_bottom_offset */
+      vl_rbsp_ue(rbsp);
+   }
+#endif
+
+   /* vui_parameters_present_flag */
+   if (vl_rbsp_u(rbsp, 1))
+      vui_parameters(rbsp);
+}
+
+static struct pipe_h264_pps *pic_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp)
+{
+   unsigned id = vl_rbsp_ue(rbsp);
+   if (id >= ARRAY_SIZE(priv->codec_data.h264.pps))
+      return NULL; /* invalid pic_parameter_set_id */
+
+   return &priv->codec_data.h264.pps[id];
+}
+
+static void picture_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp)
+{
+   struct pipe_h264_sps *sps;
+   struct pipe_h264_pps *pps;
+   unsigned i;
+
+   pps = pic_parameter_set_id(priv, rbsp);
+   if (!pps)
+      return;
+
+   memset(pps, 0, sizeof(*pps));
+
+   sps = pps->sps = seq_parameter_set_id(priv, rbsp);
+   if (!sps)
+      return;
+
+   memcpy(pps->ScalingList4x4, sps->ScalingList4x4, sizeof(pps->ScalingList4x4));
+   memcpy(pps->ScalingList8x8, sps->ScalingList8x8, sizeof(pps->ScalingList8x8));
+
+   pps->entropy_coding_mode_flag = vl_rbsp_u(rbsp, 1);
+
+   pps->bottom_field_pic_order_in_frame_present_flag = vl_rbsp_u(rbsp, 1);
+
+   pps->num_slice_groups_minus1 = vl_rbsp_ue(rbsp);
+   if (pps->num_slice_groups_minus1 > 0) {
+      pps->slice_group_map_type = vl_rbsp_ue(rbsp);
+
+      if (pps->slice_group_map_type == 0) {
+
+         for (i = 0; i <= pps->num_slice_groups_minus1; ++i)
+            /* run_length_minus1[i] */
+            vl_rbsp_ue(rbsp);
+
+      } else if (pps->slice_group_map_type == 2) {
+
+         for (i = 0; i <= pps->num_slice_groups_minus1; ++i) {
+            /* top_left[i] */
+            vl_rbsp_ue(rbsp);
+
+            /* bottom_right[i] */
+            vl_rbsp_ue(rbsp);
+         }
+
+      } else if (pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) {
+
+         /* slice_group_change_direction_flag */
+         vl_rbsp_u(rbsp, 1);
+
+         pps->slice_group_change_rate_minus1 = vl_rbsp_ue(rbsp);
+
+      } else if (pps->slice_group_map_type == 6) {
+
+         unsigned pic_size_in_map_units_minus1;
+
+         pic_size_in_map_units_minus1 = vl_rbsp_ue(rbsp);
+
+         for (i = 0; i <= pic_size_in_map_units_minus1; ++i)
+            /* slice_group_id[i] */
+            vl_rbsp_u(rbsp, log2(pps->num_slice_groups_minus1 + 1));
+      }
+   }
+
+   pps->num_ref_idx_l0_default_active_minus1 = vl_rbsp_ue(rbsp);
+
+   pps->num_ref_idx_l1_default_active_minus1 = vl_rbsp_ue(rbsp);
+
+   pps->weighted_pred_flag = vl_rbsp_u(rbsp, 1);
+
+   pps->weighted_bipred_idc = vl_rbsp_u(rbsp, 2);
+
+   pps->pic_init_qp_minus26 = vl_rbsp_se(rbsp);
+
+   /* pic_init_qs_minus26 */
+   vl_rbsp_se(rbsp);
+
+   pps->chroma_qp_index_offset = vl_rbsp_se(rbsp);
+
+   pps->deblocking_filter_control_present_flag = vl_rbsp_u(rbsp, 1);
+
+   pps->constrained_intra_pred_flag = vl_rbsp_u(rbsp, 1);
+
+   pps->redundant_pic_cnt_present_flag = vl_rbsp_u(rbsp, 1);
+
+   if (vl_rbsp_more_data(rbsp)) {
+      pps->transform_8x8_mode_flag = vl_rbsp_u(rbsp, 1);
+
+      /* pic_scaling_matrix_present_flag */
+      if (vl_rbsp_u(rbsp, 1)) {
+
+         scaling_list(rbsp, pps->ScalingList4x4[0], 16, Default_4x4_Intra,
+                      sps->seq_scaling_matrix_present_flag ? NULL : Default_4x4_Intra);
+         scaling_list(rbsp, pps->ScalingList4x4[1], 16, Default_4x4_Intra, pps->ScalingList4x4[0]);
+         scaling_list(rbsp, pps->ScalingList4x4[2], 16, Default_4x4_Intra, pps->ScalingList4x4[1]);
+         scaling_list(rbsp, pps->ScalingList4x4[3], 16, Default_4x4_Inter,
+                      sps->seq_scaling_matrix_present_flag ? NULL : Default_4x4_Inter);
+         scaling_list(rbsp, pps->ScalingList4x4[4], 16, Default_4x4_Inter, pps->ScalingList4x4[3]);
+         scaling_list(rbsp, pps->ScalingList4x4[5], 16, Default_4x4_Inter, pps->ScalingList4x4[4]);
+
+         if (pps->transform_8x8_mode_flag) {
+            scaling_list(rbsp, pps->ScalingList8x8[0], 64, Default_8x8_Intra,
+                         sps->seq_scaling_matrix_present_flag ? NULL : Default_8x8_Intra);
+            scaling_list(rbsp, pps->ScalingList8x8[1], 64, Default_8x8_Inter,
+                         sps->seq_scaling_matrix_present_flag ? NULL :  Default_8x8_Inter);
+            if (sps->chroma_format_idc == 3) {
+               scaling_list(rbsp, pps->ScalingList8x8[2], 64, Default_8x8_Intra, pps->ScalingList8x8[0]);
+               scaling_list(rbsp, pps->ScalingList8x8[3], 64, Default_8x8_Inter, pps->ScalingList8x8[1]);
+               scaling_list(rbsp, pps->ScalingList8x8[4], 64, Default_8x8_Intra, pps->ScalingList8x8[2]);
+               scaling_list(rbsp, pps->ScalingList8x8[5], 64, Default_8x8_Inter, pps->ScalingList8x8[3]);
+            }
+         }
+      }
+
+      pps->second_chroma_qp_index_offset = vl_rbsp_se(rbsp);
+   }
+}
+
+static void ref_pic_list_mvc_modification(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp)
+{
+   // TODO
+   assert(0);
+}
+
+static void ref_pic_list_modification(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp,
+                                      enum pipe_h264_slice_type slice_type)
+{
+   unsigned modification_of_pic_nums_idc;
+
+   if (slice_type != 2 && slice_type != 4) {
+      /* ref_pic_list_modification_flag_l0 */
+      if (vl_rbsp_u(rbsp, 1)) {
+         do {
+            modification_of_pic_nums_idc = vl_rbsp_ue(rbsp);
+            if (modification_of_pic_nums_idc == 0 ||
+                modification_of_pic_nums_idc == 1)
+               /* abs_diff_pic_num_minus1 */
+               vl_rbsp_ue(rbsp);
+            else if (modification_of_pic_nums_idc == 2)
+               /* long_term_pic_num */
+               vl_rbsp_ue(rbsp);
+         } while (modification_of_pic_nums_idc != 3);
+      }
+   }
+
+   if (slice_type == 1) {
+      /* ref_pic_list_modification_flag_l1 */
+      if (vl_rbsp_u(rbsp, 1)) {
+         do {
+            modification_of_pic_nums_idc = vl_rbsp_ue(rbsp);
+            if (modification_of_pic_nums_idc == 0 ||
+                modification_of_pic_nums_idc == 1)
+               /* abs_diff_pic_num_minus1 */
+               vl_rbsp_ue(rbsp);
+            else if (modification_of_pic_nums_idc == 2)
+               /* long_term_pic_num */
+               vl_rbsp_ue(rbsp);
+         } while (modification_of_pic_nums_idc != 3);
+      }
+   }
+}
+
+static void pred_weight_table(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp,
+                              struct pipe_h264_sps *sps, enum pipe_h264_slice_type slice_type)
+{
+   unsigned ChromaArrayType = sps->separate_colour_plane_flag ? 0 : sps->chroma_format_idc;
+   unsigned i, j;
+
+   /* luma_log2_weight_denom */
+   vl_rbsp_ue(rbsp);
+
+   if (ChromaArrayType != 0)
+      /* chroma_log2_weight_denom */
+      vl_rbsp_ue(rbsp);
+
+   for (i = 0; i <= priv->picture.h264.num_ref_idx_l0_active_minus1; ++i) {
+      /* luma_weight_l0_flag */
+      if (vl_rbsp_u(rbsp, 1)) {
+         /* luma_weight_l0[i] */
+         vl_rbsp_se(rbsp);
+         /* luma_offset_l0[i] */
+         vl_rbsp_se(rbsp);
+      }
+      if (ChromaArrayType != 0) {
+         /* chroma_weight_l0_flag */
+         if (vl_rbsp_u(rbsp, 1)) {
+            for (j = 0; j < 2; ++j) {
+               /* chroma_weight_l0[i][j] */
+               vl_rbsp_se(rbsp);
+               /* chroma_offset_l0[i][j] */
+               vl_rbsp_se(rbsp);
+            }
+         }
+      }
+   }
+
+   if (slice_type == 1) {
+      for (i = 0; i <= priv->picture.h264.num_ref_idx_l1_active_minus1; ++i) {
+         /* luma_weight_l1_flag */
+         if (vl_rbsp_u(rbsp, 1)) {
+            /* luma_weight_l1[i] */
+            vl_rbsp_se(rbsp);
+            /* luma_offset_l1[i] */
+            vl_rbsp_se(rbsp);
+         }
+         if (ChromaArrayType != 0) {
+            /* chroma_weight_l1_flag */
+            if (vl_rbsp_u(rbsp, 1)) {
+               for (j = 0; j < 2; ++j) {
+                  /* chroma_weight_l1[i][j] */
+                  vl_rbsp_se(rbsp);
+                  /* chroma_offset_l1[i][j] */
+                  vl_rbsp_se(rbsp);
+               }
+            }
+         }
+      }
+   }
+}
+
+static void dec_ref_pic_marking(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp,
+                                bool IdrPicFlag)
+{
+   unsigned memory_management_control_operation;
+
+   if (IdrPicFlag) {
+      /* no_output_of_prior_pics_flag */
+      vl_rbsp_u(rbsp, 1);
+      /* long_term_reference_flag */
+      vl_rbsp_u(rbsp, 1);
+   } else {
+      /* adaptive_ref_pic_marking_mode_flag */
+      if (vl_rbsp_u(rbsp, 1)) {
+         do {
+            memory_management_control_operation = vl_rbsp_ue(rbsp);
+
+            if (memory_management_control_operation == 1 ||
+                memory_management_control_operation == 3)
+               /* difference_of_pic_nums_minus1 */
+               vl_rbsp_ue(rbsp);
+
+            if (memory_management_control_operation == 2)
+               /* long_term_pic_num */
+               vl_rbsp_ue(rbsp);
+
+            if (memory_management_control_operation == 3 ||
+                memory_management_control_operation == 6)
+               /* long_term_frame_idx */
+               vl_rbsp_ue(rbsp);
+
+            if (memory_management_control_operation == 4)
+               /* max_long_term_frame_idx_plus1 */
+               vl_rbsp_ue(rbsp);
+         } while (memory_management_control_operation != 0);
+      }
+   }
+}
+
+static void slice_header(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp,
+                         unsigned nal_ref_idc, unsigned nal_unit_type)
+{
+   enum pipe_h264_slice_type slice_type;
+   struct pipe_h264_pps *pps;
+   struct pipe_h264_sps *sps;
+   unsigned frame_num, prevFrameNum;
+   bool IdrPicFlag = nal_unit_type == 5;
+
+   if (IdrPicFlag != priv->codec_data.h264.IdrPicFlag)
+      vid_dec_h264_EndFrame(priv);
+
+   priv->codec_data.h264.IdrPicFlag = IdrPicFlag;
+
+   /* first_mb_in_slice */
+   vl_rbsp_ue(rbsp);
+
+   slice_type = vl_rbsp_ue(rbsp) % 5;
+
+   /* get picture parameter set */
+   pps = pic_parameter_set_id(priv, rbsp);
+   if (!pps)
+      return;
+
+   /* get sequence parameter set */
+   sps = pps->sps;
+   if (!sps)
+      return;
+
+   if (pps != priv->picture.h264.pps)
+      vid_dec_h264_EndFrame(priv);
+
+   priv->picture.h264.pps = pps;
+
+   if (sps->separate_colour_plane_flag == 1 )
+      /* colour_plane_id */
+      vl_rbsp_u(rbsp, 2);
+
+   /* frame number handling */
+   frame_num = vl_rbsp_u(rbsp, sps->log2_max_frame_num_minus4 + 4);
+
+   if (frame_num != priv->picture.h264.frame_num)
+      vid_dec_h264_EndFrame(priv);
+
+   prevFrameNum = priv->picture.h264.frame_num;
+   priv->picture.h264.frame_num = frame_num;
+
+   priv->picture.h264.field_pic_flag = 0;
+   priv->picture.h264.bottom_field_flag = 0;
+
+   if (!sps->frame_mbs_only_flag) {
+      unsigned field_pic_flag = vl_rbsp_u(rbsp, 1);
+
+      if (!field_pic_flag && field_pic_flag != priv->picture.h264.field_pic_flag)
+         vid_dec_h264_EndFrame(priv);
+
+      priv->picture.h264.field_pic_flag = field_pic_flag;
+
+      if (priv->picture.h264.field_pic_flag) {
+         unsigned bottom_field_flag = vl_rbsp_u(rbsp, 1);
+
+         if (bottom_field_flag != priv->picture.h264.bottom_field_flag)
+            vid_dec_h264_EndFrame(priv);
+
+         priv->picture.h264.bottom_field_flag = bottom_field_flag;
+      }
+   }
+
+   if (IdrPicFlag) {
+      /* set idr_pic_id */
+      unsigned idr_pic_id = vl_rbsp_ue(rbsp);
+
+      if (idr_pic_id != priv->codec_data.h264.idr_pic_id)
+         vid_dec_h264_EndFrame(priv);
+
+      priv->codec_data.h264.idr_pic_id = idr_pic_id;
+   }
+
+   if (sps->pic_order_cnt_type == 0) {
+      /* pic_order_cnt_lsb */
+      unsigned log2_max_pic_order_cnt_lsb = sps->log2_max_pic_order_cnt_lsb_minus4 + 4;
+      unsigned max_pic_order_cnt_lsb = 1 << log2_max_pic_order_cnt_lsb;
+      int pic_order_cnt_lsb = vl_rbsp_u(rbsp, log2_max_pic_order_cnt_lsb);
+      int pic_order_cnt_msb;
+
+      if (pic_order_cnt_lsb != priv->codec_data.h264.pic_order_cnt_lsb)
+         vid_dec_h264_EndFrame(priv);
+
+      if (IdrPicFlag) {
+         priv->codec_data.h264.pic_order_cnt_msb = 0;
+         priv->codec_data.h264.pic_order_cnt_lsb = 0;
+      }
+
+      if ((pic_order_cnt_lsb < priv->codec_data.h264.pic_order_cnt_lsb) &&
+          (priv->codec_data.h264.pic_order_cnt_lsb - pic_order_cnt_lsb) >= (max_pic_order_cnt_lsb / 2))
+         pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb + max_pic_order_cnt_lsb;
+
+      else if ((pic_order_cnt_lsb > priv->codec_data.h264.pic_order_cnt_lsb) &&
+          (pic_order_cnt_lsb - priv->codec_data.h264.pic_order_cnt_lsb) > (max_pic_order_cnt_lsb / 2))
+         pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb - max_pic_order_cnt_lsb;
+
+      else
+         pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb;
+
+      priv->codec_data.h264.pic_order_cnt_msb = pic_order_cnt_msb;
+      priv->codec_data.h264.pic_order_cnt_lsb = pic_order_cnt_lsb;
+
+      if (pps->bottom_field_pic_order_in_frame_present_flag && !priv->picture.h264.field_pic_flag) {
+         /* delta_pic_oreder_cnt_bottom */
+         unsigned delta_pic_order_cnt_bottom = vl_rbsp_se(rbsp);
+
+         if (delta_pic_order_cnt_bottom != priv->codec_data.h264.delta_pic_order_cnt_bottom)
+            vid_dec_h264_EndFrame(priv);
+
+         priv->codec_data.h264.delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom;
+      }
+
+      if (!priv->picture.h264.field_pic_flag) {
+         priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb;
+         priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt [0] +
+                                          priv->codec_data.h264.delta_pic_order_cnt_bottom;
+      } else if (!priv->picture.h264.bottom_field_flag)
+         priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb;
+      else
+         priv->picture.h264.field_order_cnt[1] = pic_order_cnt_msb + pic_order_cnt_lsb;
+
+   } else if (sps->pic_order_cnt_type == 1) {
+      /* delta_pic_order_cnt[0] */
+      unsigned MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
+      unsigned FrameNumOffset, absFrameNum, expectedPicOrderCnt;
+
+      if (!sps->delta_pic_order_always_zero_flag) {
+         unsigned delta_pic_order_cnt[2];
+
+         delta_pic_order_cnt[0] = vl_rbsp_se(rbsp);
+
+         if (delta_pic_order_cnt[0] != priv->codec_data.h264.delta_pic_order_cnt[0])
+            vid_dec_h264_EndFrame(priv);
+
+         priv->codec_data.h264.delta_pic_order_cnt[0] = delta_pic_order_cnt[0];
+
+         if (pps->bottom_field_pic_order_in_frame_present_flag && !priv->picture.h264.field_pic_flag) {
+            /* delta_pic_order_cnt[1] */
+            delta_pic_order_cnt[1] = vl_rbsp_se(rbsp);
+
+            if (delta_pic_order_cnt[1] != priv->codec_data.h264.delta_pic_order_cnt[1])
+               vid_dec_h264_EndFrame(priv);
+
+            priv->codec_data.h264.delta_pic_order_cnt[1] = delta_pic_order_cnt[1];
+         }
+      }
+
+      if (IdrPicFlag)
+         FrameNumOffset = 0;
+      else if (prevFrameNum > frame_num)
+         FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset + MaxFrameNum;
+      else
+         FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset;
+
+      priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset;
+
+      if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0)
+         absFrameNum = FrameNumOffset + frame_num;
+      else
+         absFrameNum = 0;
+
+      if (nal_ref_idc == 0 && absFrameNum > 0)
+         absFrameNum = absFrameNum - 1;
+
+      if (absFrameNum > 0) {
+         unsigned picOrderCntCycleCnt = (absFrameNum - 1) / sps->num_ref_frames_in_pic_order_cnt_cycle;
+         unsigned frameNumInPicOrderCntCycle = (absFrameNum - 1) % sps->num_ref_frames_in_pic_order_cnt_cycle;
+         signed ExpectedDeltaPerPicOrderCntCycle = 0;
+         unsigned i;
+
+         for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i)
+            ExpectedDeltaPerPicOrderCntCycle += sps->offset_for_ref_frame[i];
+
+         expectedPicOrderCnt = picOrderCntCycleCnt * ExpectedDeltaPerPicOrderCntCycle;
+         for (i = 0; i <= frameNumInPicOrderCntCycle; ++i)
+            expectedPicOrderCnt += sps->offset_for_ref_frame[i];
+
+      } else
+         expectedPicOrderCnt = 0;
+
+      if (nal_ref_idc == 0)
+         expectedPicOrderCnt += sps->offset_for_non_ref_pic;
+
+      if (!priv->picture.h264.field_pic_flag) {
+         priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0];
+         priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt[0] +
+            sps->offset_for_top_to_bottom_field + priv->codec_data.h264.delta_pic_order_cnt[1];
+
+      } else if (!priv->picture.h264.bottom_field_flag)
+         priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0];
+      else
+         priv->picture.h264.field_order_cnt[1] = expectedPicOrderCnt + sps->offset_for_top_to_bottom_field +
+            priv->codec_data.h264.delta_pic_order_cnt[0];
+
+   } else if (sps->pic_order_cnt_type == 2) {
+      unsigned MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
+      unsigned FrameNumOffset, tempPicOrderCnt;
+
+      if (IdrPicFlag)
+         FrameNumOffset = 0;
+      else if (prevFrameNum > frame_num)
+         FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset + MaxFrameNum;
+      else
+         FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset;
+
+      priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset;
+
+      if (IdrPicFlag)
+         tempPicOrderCnt = 0;
+      else if (nal_ref_idc == 0)
+         tempPicOrderCnt = 2 * (FrameNumOffset + frame_num) - 1;
+      else
+         tempPicOrderCnt = 2 * (FrameNumOffset + frame_num);
+
+      if (!priv->picture.h264.field_pic_flag) {
+         priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt;
+         priv->picture.h264.field_order_cnt[1] = tempPicOrderCnt;
+
+      } else if (!priv->picture.h264.bottom_field_flag)
+         priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt;
+      else
+         priv->picture.h264.field_order_cnt[1] = tempPicOrderCnt;
+   }
+
+   if (pps->redundant_pic_cnt_present_flag)
+      /* redundant_pic_cnt */
+      vl_rbsp_ue(rbsp);
+
+   if (slice_type == PIPE_H264_SLICE_TYPE_B)
+      /* direct_spatial_mv_pred_flag */
+      vl_rbsp_u(rbsp, 1);
+
+   priv->picture.h264.num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1;
+   priv->picture.h264.num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1;
+
+   if (slice_type == PIPE_H264_SLICE_TYPE_P ||
+       slice_type == PIPE_H264_SLICE_TYPE_SP ||
+       slice_type == PIPE_H264_SLICE_TYPE_B) {
+
+      /* num_ref_idx_active_override_flag */
+      if (vl_rbsp_u(rbsp, 1)) {
+         priv->picture.h264.num_ref_idx_l0_active_minus1 = vl_rbsp_ue(rbsp);
+
+         if (slice_type == PIPE_H264_SLICE_TYPE_B)
+            priv->picture.h264.num_ref_idx_l1_active_minus1 = vl_rbsp_ue(rbsp);
+      }
+   }
+
+   if (nal_unit_type == 20 || nal_unit_type == 21)
+      ref_pic_list_mvc_modification(priv, rbsp);
+   else
+      ref_pic_list_modification(priv, rbsp, slice_type);
+
+   if ((pps->weighted_pred_flag && (slice_type == PIPE_H264_SLICE_TYPE_P || slice_type == PIPE_H264_SLICE_TYPE_SP)) ||
+       (pps->weighted_bipred_idc == 1 && slice_type == PIPE_H264_SLICE_TYPE_B))
+      pred_weight_table(priv, rbsp, sps, slice_type);
+
+   if (nal_ref_idc != 0)
+      dec_ref_pic_marking(priv, rbsp, IdrPicFlag);
+
+   if (pps->entropy_coding_mode_flag && slice_type != PIPE_H264_SLICE_TYPE_I && slice_type != PIPE_H264_SLICE_TYPE_SI)
+      /* cabac_init_idc */
+      vl_rbsp_ue(rbsp);
+
+   /* slice_qp_delta */
+   vl_rbsp_se(rbsp);
+
+   if (slice_type == PIPE_H264_SLICE_TYPE_SP || slice_type == PIPE_H264_SLICE_TYPE_SI) {
+      if (slice_type == PIPE_H264_SLICE_TYPE_SP)
+         /* sp_for_switch_flag */
+         vl_rbsp_u(rbsp, 1);
+
+      /*slice_qs_delta */
+      vl_rbsp_se(rbsp);
+   }
+
+   if (pps->deblocking_filter_control_present_flag) {
+      unsigned disable_deblocking_filter_idc = vl_rbsp_ue(rbsp);
+
+      if (disable_deblocking_filter_idc != 1) {
+         /* slice_alpha_c0_offset_div2 */
+         vl_rbsp_se(rbsp);
+
+         /* slice_beta_offset_div2 */
+         vl_rbsp_se(rbsp);
+      }
+   }
+
+   if (pps->num_slice_groups_minus1 > 0 && pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5)
+      /* slice_group_change_cycle */
+      vl_rbsp_u(rbsp, 2);
+}
+
+#if ENABLE_ST_OMX_TIZONIA
+static OMX_ERRORTYPE update_port_parameters(vid_dec_PrivateType* priv) {
+   OMX_VIDEO_PORTDEFINITIONTYPE * p_def = NULL;   /* Output port info */
+   h264d_stream_info_t * i_def = NULL; /* Info read from stream */
+   OMX_ERRORTYPE err = OMX_ErrorNone;
+
+   assert(priv);
+
+   p_def = &(priv->out_port_def_.format.video);
+   i_def = &(priv->stream_info);
+
+   /* Handle dynamic resolution change */
+   if ((p_def->nFrameWidth == i_def->width) && p_def->nFrameHeight == i_def->height)
+      return err;
+
+   p_def->nFrameWidth = i_def->width;
+   p_def->nFrameHeight = i_def->height;
+   p_def->nStride = i_def->width;
+   p_def->nSliceHeight = i_def->height;
+
+   err = tiz_krn_SetParameter_internal(tiz_get_krn(handleOf(priv)), handleOf(priv),
+                                       OMX_IndexParamPortDefinition, &(priv->out_port_def_));
+   if (err == OMX_ErrorNone) {
+      tiz_port_t * p_obj = tiz_krn_get_port(tiz_get_krn(handleOf(priv)), OMX_VID_DEC_AVC_INPUT_PORT_INDEX);
+
+      /* Set desired buffer size that will be used when allocating input buffers */
+      p_obj->portdef_.nBufferSize = p_def->nFrameWidth * p_def->nFrameHeight * 512 / (16*16);
+
+      /* Get a locally copy of port def. Useful for the early return above */
+      tiz_check_omx(tiz_api_GetParameter(tiz_get_krn(handleOf(priv)), handleOf(priv),
+                                         OMX_IndexParamPortDefinition, &(priv->out_port_def_)));
+
+      tiz_srv_issue_event((OMX_PTR) priv, OMX_EventPortSettingsChanged,
+                          OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX,
+                          OMX_IndexParamPortDefinition,
+                          NULL);
+   }
+
+   return err;
+}
+#endif
+
+void vid_dec_h264_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left)
+{
+   unsigned nal_ref_idc, nal_unit_type;
+
+   if (!vl_vlc_search_byte(vlc, vl_vlc_bits_left(vlc) - min_bits_left, 0x00))
+      return;
+
+   if (vl_vlc_peekbits(vlc, 24) != 0x000001) {
+      vl_vlc_eatbits(vlc, 8);
+      return;
+   }
+
+   if (priv->slice) {
+      unsigned bytes = priv->bytes_left - (vl_vlc_bits_left(vlc) / 8);
+      ++priv->picture.h264.slice_count;
+      priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base,
+                                    1, &priv->slice, &bytes);
+      priv->slice = NULL;
+   }
+
+   vl_vlc_eatbits(vlc, 24);
+
+   /* forbidden_zero_bit */
+   vl_vlc_eatbits(vlc, 1);
+
+   nal_ref_idc = vl_vlc_get_uimsbf(vlc, 2);
+
+   if (nal_ref_idc != priv->codec_data.h264.nal_ref_idc &&
+       (nal_ref_idc * priv->codec_data.h264.nal_ref_idc) == 0)
+      vid_dec_h264_EndFrame(priv);
+
+   priv->codec_data.h264.nal_ref_idc = nal_ref_idc;
+
+   nal_unit_type = vl_vlc_get_uimsbf(vlc, 5);
+
+   if (nal_unit_type != 1 && nal_unit_type != 5)
+      vid_dec_h264_EndFrame(priv);
+
+   if (nal_unit_type == 7) {
+      struct vl_rbsp rbsp;
+      vl_rbsp_init(&rbsp, vlc, ~0);
+      seq_parameter_set(priv, &rbsp);
+#if ENABLE_ST_OMX_TIZONIA
+      update_port_parameters(priv);
+#endif
+
+   } else if (nal_unit_type == 8) {
+      struct vl_rbsp rbsp;
+      vl_rbsp_init(&rbsp, vlc, ~0);
+      picture_parameter_set(priv, &rbsp);
+
+   } else if (nal_unit_type == 1 || nal_unit_type == 5) {
+      /* Coded slice of a non-IDR or IDR picture */
+      unsigned bits = vl_vlc_valid_bits(vlc);
+      unsigned bytes = bits / 8 + 4;
+      struct vl_rbsp rbsp;
+      uint8_t buf[8];
+      const void *ptr = buf;
+      unsigned i;
+
+      buf[0] = 0x0;
+      buf[1] = 0x0;
+      buf[2] = 0x1;
+      buf[3] = (nal_ref_idc << 5) | nal_unit_type;
+      for (i = 4; i < bytes; ++i)
+         buf[i] = vl_vlc_peekbits(vlc, bits) >> ((bytes - i - 1) * 8);
+
+      priv->bytes_left = (vl_vlc_bits_left(vlc) - bits) / 8;
+      priv->slice = vlc->data;
+
+      vl_rbsp_init(&rbsp, vlc, 128);
+      slice_header(priv, &rbsp, nal_ref_idc, nal_unit_type);
+
+      vid_dec_h264_BeginFrame(priv);
+
+      ++priv->picture.h264.slice_count;
+      priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base,
+                                    1, &ptr, &bytes);
+   }
+
+   /* resync to byte boundary */
+   vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8);
+}
+
+void vid_dec_FreeInputPortPrivate(OMX_BUFFERHEADERTYPE *buf)
+{
+   struct pipe_video_buffer *vbuf = buf->pInputPortPrivate;
+   if (!vbuf)
+      return;
+
+   vbuf->destroy(vbuf);
+   buf->pInputPortPrivate = NULL;
+}
+
+void vid_dec_FrameDecoded_common(vid_dec_PrivateType* priv, OMX_BUFFERHEADERTYPE* input,
+                          OMX_BUFFERHEADERTYPE* output)
+{
+#if ENABLE_ST_OMX_BELLAGIO
+   bool eos = !!(input->nFlags & OMX_BUFFERFLAG_EOS);
+#else
+   bool eos = priv->eos_;
+#endif
+   OMX_TICKS timestamp;
+
+   if (!input->pInputPortPrivate) {
+#if ENABLE_ST_OMX_BELLAGIO
+      input->pInputPortPrivate = priv->Flush(priv, &timestamp);
+#else
+      input->pInputPortPrivate = vid_dec_h264_Flush(priv, &timestamp);
+#endif
+      if (timestamp != OMX_VID_DEC_AVC_TIMESTAMP_INVALID)
+         input->nTimeStamp = timestamp;
+   }
+
+   if (input->pInputPortPrivate) {
+      if (output->pInputPortPrivate && !priv->disable_tunnel) {
+         struct pipe_video_buffer *tmp, *vbuf, *new_vbuf;
+
+         tmp = output->pOutputPortPrivate;
+         vbuf = input->pInputPortPrivate;
+         if (vbuf->interlaced) {
+            /* re-allocate the progressive buffer */
+            struct pipe_video_buffer templat = {};
+            struct u_rect src_rect, dst_rect;
+
+#if ENABLE_ST_OMX_BELLAGIO
+            omx_base_video_PortType *port;
+            port = (omx_base_video_PortType *)
+                    priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];
+#else
+            tiz_port_t *port;
+            port = tiz_krn_get_port(tiz_get_krn(handleOf (priv)), OMX_VID_DEC_AVC_INPUT_PORT_INDEX);
+#endif
+            memset(&templat, 0, sizeof(templat));
+            templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
+#if ENABLE_ST_OMX_BELLAGIO
+            templat.width = port->sPortParam.format.video.nFrameWidth;
+            templat.height = port->sPortParam.format.video.nFrameHeight;
+#else
+            templat.width = port->portdef_.format.video.nFrameWidth;
+            templat.height = port->portdef_.format.video.nFrameHeight;
+#endif
+            templat.buffer_format = PIPE_FORMAT_NV12;
+            templat.interlaced = false;
+            new_vbuf = priv->pipe->create_video_buffer(priv->pipe, &templat);
+
+            /* convert the interlaced to the progressive */
+            src_rect.x0 = dst_rect.x0 = 0;
+            src_rect.x1 = dst_rect.x1 = templat.width;
+            src_rect.y0 = dst_rect.y0 = 0;
+            src_rect.y1 = dst_rect.y1 = templat.height;
+
+            vl_compositor_yuv_deint_full(&priv->cstate, &priv->compositor,
+                                         input->pInputPortPrivate, new_vbuf,
+                                         &src_rect, &dst_rect, VL_COMPOSITOR_WEAVE);
+
+            /* set the progrssive buffer for next round */
+            vbuf->destroy(vbuf);
+            input->pInputPortPrivate = new_vbuf;
+         }
+         output->pOutputPortPrivate = input->pInputPortPrivate;
+         input->pInputPortPrivate = tmp;
+      } else {
+         vid_dec_FillOutput(priv, input->pInputPortPrivate, output);
+      }
+      output->nFilledLen = output->nAllocLen;
+      output->nTimeStamp = input->nTimeStamp;
+   }
+
+   if (eos && input->pInputPortPrivate)
+      vid_dec_FreeInputPortPrivate(input);
+   else
+      input->nFilledLen = 0;
+}
diff --git a/src/gallium/state_trackers/omx/vid_dec_h264_common.h b/src/gallium/state_trackers/omx/vid_dec_h264_common.h
new file mode 100644 (file)
index 0000000..abde53b
--- /dev/null
@@ -0,0 +1,99 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef VID_DEC_H264_COMMON_H
+#define VID_DEC_H264_COMMON_H
+
+#include "vid_dec_common.h"
+
+#define OMX_VID_DEC_AVC_DEFAULT_FRAME_WIDTH      176
+#define OMX_VID_DEC_AVC_DEFAULT_FRAME_HEIGHT     144
+#define OMX_VID_DEC_AVC_DEFAULT_FRAME_RATE 15<<16
+#define OMX_VID_DEC_AVC_ROLE "video_decoder.avc"
+/* With libtizonia, port indexes must start at index 0 */
+#define OMX_VID_DEC_AVC_INPUT_PORT_INDEX               0
+#define OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX              1
+#define OMX_VID_DEC_AVC_INPUT_PORT_MIN_BUF_COUNT       8
+#define OMX_VID_DEC_AVC_OUTPUT_PORT_MIN_BUF_COUNT      4
+/* 38016 = (width * height) + ((width * height)/2) */
+#define OMX_VID_DEC_AVC_PORT_MIN_INPUT_BUF_SIZE  38016
+#define OMX_VID_DEC_AVC_PORT_MIN_OUTPUT_BUF_SIZE 345600
+#define OMX_VID_DEC_AVC_PORT_NONCONTIGUOUS       OMX_FALSE
+#define OMX_VID_DEC_AVC_PORT_ALIGNMENT           0
+#define OMX_VID_DEC_AVC_PORT_SUPPLIERPREF        OMX_BufferSupplyInput
+#define OMX_VID_DEC_AVC_TIMESTAMP_INVALID ((OMX_TICKS) -1)
+
+#define DPB_MAX_SIZE 5
+
+struct dpb_list {
+   struct list_head list;
+   struct pipe_video_buffer *buffer;
+   OMX_TICKS timestamp;
+   int poc;
+};
+
+static const uint8_t Default_4x4_Intra[16] = {
+    6, 13, 20, 28, 13, 20, 28, 32,
+   20, 28, 32, 37, 28, 32, 37, 42
+};
+
+static const uint8_t Default_4x4_Inter[16] = {
+   10, 14, 20, 24, 14, 20, 24, 27,
+   20, 24, 27, 30, 24, 27, 30, 34
+};
+
+static const uint8_t Default_8x8_Intra[64] = {
+    6, 10, 13, 16, 18, 23, 25, 27,
+   10, 11, 16, 18, 23, 25, 27, 29,
+   13, 16, 18, 23, 25, 27, 29, 31,
+   16, 18, 23, 25, 27, 29, 31, 33,
+   18, 23, 25, 27, 29, 31, 33, 36,
+   23, 25, 27, 29, 31, 33, 36, 38,
+   25, 27, 29, 31, 33, 36, 38, 40,
+   27, 29, 31, 33, 36, 38, 40, 42
+};
+
+static const uint8_t Default_8x8_Inter[64] = {
+    9, 13, 15, 17, 19, 21, 22, 24,
+   13, 13, 17, 19, 21, 22, 24, 25,
+   15, 17, 19, 21, 22, 24, 25, 27,
+   17, 19, 21, 22, 24, 25, 27, 28,
+   19, 21, 22, 24, 25, 27, 28, 30,
+   21, 22, 24, 25, 27, 28, 30, 32,
+   22, 24, 25, 27, 28, 30, 32, 33,
+   24, 25, 27, 28, 30, 32, 33, 35
+};
+
+struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv,
+                                             OMX_TICKS *timestamp);
+void vid_dec_h264_EndFrame(vid_dec_PrivateType *priv);
+void vid_dec_h264_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left);
+void vid_dec_FreeInputPortPrivate(OMX_BUFFERHEADERTYPE *buf);
+void vid_dec_FrameDecoded_common(vid_dec_PrivateType*priv, OMX_BUFFERHEADERTYPE* input,
+                                 OMX_BUFFERHEADERTYPE* output);
+
+#endif
diff --git a/src/gallium/state_trackers/omx/vid_omx_common.c b/src/gallium/state_trackers/omx/vid_omx_common.c
new file mode 100644 (file)
index 0000000..63afa89
--- /dev/null
@@ -0,0 +1,111 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <string.h>
+#include <stdbool.h>
+
+#if defined(HAVE_X11_PLATFORM)
+#include <X11/Xlib.h>
+#else
+#define XOpenDisplay(x) NULL
+#define XCloseDisplay(x)
+#define Display void
+#endif
+
+#include "os/os_thread.h"
+#include "util/u_memory.h"
+#include "loader/loader.h"
+
+#include "vid_omx_common.h"
+
+static mtx_t omx_lock = _MTX_INITIALIZER_NP;
+static Display *omx_display = NULL;
+static struct vl_screen *omx_screen = NULL;
+static unsigned omx_usecount = 0;
+static const char *omx_render_node = NULL;
+static int drm_fd;
+
+struct vl_screen *omx_get_screen(void)
+{
+   static bool first_time = true;
+   mtx_lock(&omx_lock);
+
+   if (!omx_screen) {
+      if (first_time) {
+         omx_render_node = debug_get_option("OMX_RENDER_NODE", NULL);
+         first_time = false;
+      }
+      if (omx_render_node) {
+         drm_fd = loader_open_device(omx_render_node);
+         if (drm_fd < 0)
+            goto error;
+
+         omx_screen = vl_drm_screen_create(drm_fd);
+         if (!omx_screen) {
+            close(drm_fd);
+            goto error;
+         }
+      } else {
+         omx_display = XOpenDisplay(NULL);
+         if (!omx_display)
+            goto error;
+
+         omx_screen = vl_dri3_screen_create(omx_display, 0);
+         if (!omx_screen)
+            omx_screen = vl_dri2_screen_create(omx_display, 0);
+         if (!omx_screen) {
+            XCloseDisplay(omx_display);
+            goto error;
+         }
+      }
+   }
+
+   ++omx_usecount;
+
+   mtx_unlock(&omx_lock);
+   return omx_screen;
+
+error:
+   mtx_unlock(&omx_lock);
+   return NULL;
+}
+
+void omx_put_screen(void)
+{
+   mtx_lock(&omx_lock);
+   if ((--omx_usecount) == 0) {
+      omx_screen->destroy(omx_screen);
+      omx_screen = NULL;
+
+      if (omx_render_node)
+         close(drm_fd);
+      else
+         XCloseDisplay(omx_display);
+   }
+   mtx_unlock(&omx_lock);
+}
diff --git a/src/gallium/state_trackers/omx/vid_omx_common.h b/src/gallium/state_trackers/omx/vid_omx_common.h
new file mode 100644 (file)
index 0000000..e27013d
--- /dev/null
@@ -0,0 +1,36 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef VID_OMX_COMMON_H
+#define VID_OMX_COMMON_H
+
+#include "vl/vl_winsys.h"
+
+struct vl_screen *omx_get_screen(void);
+void omx_put_screen(void);
+
+#endif