st/omx/dec: add initial omx hevc support
authorLeo Liu <leo.liu@amd.com>
Mon, 29 Aug 2016 17:09:12 +0000 (13:09 -0400)
committerLeo Liu <leo.liu@amd.com>
Tue, 6 Sep 2016 14:08:01 +0000 (10:08 -0400)
Mainly based on the h264 implementation.

Signed-off-by: Leo Liu <leo.liu@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
src/gallium/state_trackers/omx/Makefile.sources
src/gallium/state_trackers/omx/vid_dec.h
src/gallium/state_trackers/omx/vid_dec_h265.c [new file with mode: 0644]

index d25cd2e393449d4c31b28c239b5d947ec5b1250f..ab60ce803cbcebc9866249759cb55afac57c36da 100644 (file)
@@ -5,5 +5,6 @@ C_SOURCES := \
        vid_dec.h \
        vid_dec_mpeg12.c \
        vid_dec_h264.c \
+       vid_dec_h265.c \
        vid_enc.c \
        vid_enc.h
index d268925ab264244a67b80022a66767dc0c36877e..4568e6d6b9d211cc30a4267cbd2fe6aed557c06d 100644 (file)
@@ -94,11 +94,19 @@ DERIVEDCLASS(vid_dec_PrivateType, omx_base_filter_PrivateType)
          struct list_head dpb_list; \
          unsigned dpb_num; \
       } h264; \
+      struct { \
+         unsigned level_idc; \
+         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]; \
@@ -126,4 +134,7 @@ void vid_dec_mpeg12_Init(vid_dec_PrivateType *priv);
 /* vid_dec_h264.c */
 void vid_dec_h264_Init(vid_dec_PrivateType *priv);
 
+/* vid_dec_h265.c */
+void vid_dec_h265_Init(vid_dec_PrivateType *priv);
+
 #endif
diff --git a/src/gallium/state_trackers/omx/vid_dec_h265.c b/src/gallium/state_trackers/omx/vid_dec_h265.c
new file mode 100644 (file)
index 0000000..49936b0
--- /dev/null
@@ -0,0 +1,148 @@
+/**************************************************************************
+ *
+ * Copyright 2016 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 "pipe/p_video_codec.h"
+#include "util/u_memory.h"
+#include "util/u_video.h"
+#include "vl/vl_rbsp.h"
+
+#include "entrypoint.h"
+#include "vid_dec.h"
+
+#define DPB_MAX_SIZE 16
+
+struct dpb_list {
+   struct list_head list;
+   struct pipe_video_buffer *buffer;
+   unsigned poc;
+};
+
+static void vid_dec_h265_BeginFrame(vid_dec_PrivateType *priv)
+{
+   if (priv->frame_started)
+      return;
+
+   vid_dec_NeedTarget(priv);
+
+   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.expect_chunked_decode = true;
+      templat.width = align(port->sPortParam.format.video.nFrameWidth, 4);
+      templat.height = align(port->sPortParam.format.video.nFrameHeight, 4);
+      templat.level =  priv->codec_data.h265.level_idc;
+      priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat);
+   }
+   priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base);
+   priv->frame_started = true;
+}
+
+static struct pipe_video_buffer *vid_dec_h265_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.h265.dpb_list, list) {
+
+      if (result && entry->poc == 0)
+         break;
+
+      if (!result || entry->poc < result->poc)
+         result = entry;
+   }
+
+   if (!result)
+      return NULL;
+
+   buf = result->buffer;
+
+   --priv->codec_data.h265.dpb_num;
+   LIST_DEL(&result->list);
+   FREE(result);
+
+   return buf;
+}
+
+static void vid_dec_h265_EndFrame(vid_dec_PrivateType *priv)
+{
+   struct dpb_list *entry = NULL;
+   struct pipe_video_buffer *tmp;
+
+   if (!priv->frame_started)
+      return;
+
+   priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base);
+   priv->frame_started = false;
+
+   /* add the decoded picture to the dpb list */
+   entry = CALLOC_STRUCT(dpb_list);
+   if (!entry)
+      return;
+
+   entry->buffer = priv->target;
+
+   LIST_ADDTAIL(&entry->list, &priv->codec_data.h265.dpb_list);
+   ++priv->codec_data.h265.dpb_num;
+   priv->target = NULL;
+
+   if (priv->codec_data.h265.dpb_num <= DPB_MAX_SIZE)
+      return;
+
+   tmp = priv->in_buffers[0]->pInputPortPrivate;
+   priv->in_buffers[0]->pInputPortPrivate = vid_dec_h265_Flush(priv, NULL);
+   priv->target = tmp;
+   priv->frame_finished = priv->in_buffers[0]->pInputPortPrivate != NULL;
+}
+
+static void vid_dec_h265_Decode(vid_dec_PrivateType *priv,
+                                struct vl_vlc *vlc,
+                                unsigned min_bits_left)
+{
+   /* TODO */
+
+   /* resync to byte boundary */
+   vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8);
+}
+
+void vid_dec_h265_Init(vid_dec_PrivateType *priv)
+{
+   priv->picture.base.profile = PIPE_VIDEO_PROFILE_HEVC_MAIN;
+
+   LIST_INITHEAD(&priv->codec_data.h265.dpb_list);
+
+   priv->Decode = vid_dec_h265_Decode;
+   priv->EndFrame = vid_dec_h265_EndFrame;
+   priv->Flush = vid_dec_h265_Flush;
+}