enable encoder and add hevc encoder 73/127273/5
authorSejun Park <sejun79.park@samsung.com>
Thu, 27 Apr 2017 02:08:05 +0000 (11:08 +0900)
committerSejun Park <sejun79.park@samsung.com>
Thu, 27 Apr 2017 11:28:43 +0000 (20:28 +0900)
Change-Id: Idc8b228b4d51a2ddb4d17eecbf16b492802d27f6

12 files changed:
config/exynos/gstomx.conf
omx/Makefile.am
omx/gstomx.c
omx/gstomx.h
omx/gstomxh264enc.c
omx/gstomxh264enc.h
omx/gstomxh265enc.c [new file with mode: 0644]
omx/gstomxh265enc.h [new file with mode: 0644]
omx/gstomxvideodec.c
omx/gstomxvideodec.h
omx/gstomxvideoenc.c
omx/gstomxvideoenc.h

index c667b34..e83ec55 100644 (file)
@@ -95,11 +95,22 @@ rank=258
 in-port-index=0
 out-port-index=1
 in-port-usebuffer=1
-out-port-usebuffer=1
+out-port-usebuffer=0
 hacks=no-disable-outport;no-component-role
 sink-template-caps=video/x-raw, format=(string)SN12, width=(int) [1,1920], height=(int) [1,1080], framerate=(fraction)[0/1, MAX]
 src-template-caps=video/x-h264, width=(int) [1,1920], height=(int) [1,1080], framerate=(fraction) [0/1, MAX], alignment=(string) au, stream-format = (string){ avc, byte-stream }
 
+[omxenc_h265]
+type-name=GstOMXH265Enc
+core-name=/usr/lib/libExynosOMX_Core.so
+component-name=OMX.Exynos.HEVC.Encoder
+rank=258
+in-port-index=0
+out-port-index=1
+in-port-usebuffer=1
+out-port-usebuffer=0
+hacks=no-disable-outport;no-component-role
+
 [omxenc_mpeg4]
 type-name=GstOMXMPEG4VideoEnc
 core-name=/usr/lib/libExynosOMX_Core.so
@@ -108,7 +119,7 @@ rank=258
 in-port-index=0
 out-port-index=1
 in-port-usebuffer=1
-out-port-usebuffer=1
+out-port-usebuffer=0
 hacks=no-component-role;no-disable-outport
 
 [omxenc_h263]
@@ -119,5 +130,5 @@ rank=258
 in-port-index=0
 out-port-index=1
 in-port-usebuffer=1
-out-port-usebuffer=1
+out-port-usebuffer=0
 hacks=no-component-role;no-disable-outport
index ad740bf..23742f3 100644 (file)
@@ -16,8 +16,10 @@ THEORA_H_FILES=gstomxtheoradec.h
 endif
 
 if HAVE_HEVC
-HEVC_C_FILES=gstomxh265dec.c
-HEVC_H_FILES=gstomxh265dec.h
+HEVC_C_FILES=gstomxh265dec.c   \
+                       gstomxh265enc.c
+HEVC_H_FILES=gstomxh265dec.h   \
+                       gstomxh265enc.h
 endif
 
 libgstomx_la_SOURCES = \
index 4f263e5..3269dfd 100644 (file)
@@ -39,6 +39,7 @@
 #include "gstomxtheoradec.h"
 #include "gstomxwmvdec.h"
 #include "gstomxmpeg4videoenc.h"
+#include "gstomxh265enc.h"
 #include "gstomxh264enc.h"
 #include "gstomxh263enc.h"
 #include "gstomxaacdec.h"
@@ -1447,7 +1448,7 @@ gst_omx_port_release_buffer (GstOMXPort * port, GstOMXBuffer * buf)
     err = OMX_EmptyThisBuffer (comp->handle, buf->omx_buf);
   } else {
     GST_LOG_OBJECT (comp->parent,"Calling OMX_FillThisBuffer. dmabuf_fd : [%d(%p)]\n",
-        buf->mm_vbuffer->handle.dmabuf_fd[0], buf);
+        buf->mm_vbuffer ? buf->mm_vbuffer->handle.dmabuf_fd[0] : 0, buf);
     err = OMX_FillThisBuffer (comp->handle, buf->omx_buf);
   }
   GST_DEBUG_OBJECT (comp->parent, "Released buffer %p to %s port %u: %s "
@@ -1818,12 +1819,13 @@ gst_omx_port_tbm_allocate_dec_buffers (GstOMXPort * port, tbm_bufmgr bufmgr, int
 
 /* NOTE: Uses comp->lock and comp->messages_lock */
 OMX_ERRORTYPE
-gst_omx_port_tbm_allocate_enc_buffers (GstOMXPort * port, tbm_bufmgr bufmgr, int eCompressionFormat)
+gst_omx_port_tbm_allocate_enc_buffers (GstOMXPort * port, tbm_bufmgr bufmgr, int eCompressionFormat, gboolean use_buffer)
 {
   int y_size = 0;
   int uv_size = 0;
   OMX_ERRORTYPE err = OMX_ErrorNone;
   guint n = 0;
+  gint num = 0;
   GList *buffers = NULL;
   tbm_bo_handle handle_bo;
   MMVideoBuffer *mm_vbuffer[MAX_INPUT_BUFFER];
@@ -1834,27 +1836,29 @@ gst_omx_port_tbm_allocate_enc_buffers (GstOMXPort * port, tbm_bufmgr bufmgr, int
 
   /*deallocate previous allocated buffers...*/
   if (port->buffers)
-    gst_omx_port_deallocate_buffers(port);
+    gst_omx_port_deallocate_buffers (port);
   n = port->port_def.nBufferCountActual;
 
-  for (int i = 0; i < n; i++) {
-    mm_vbuffer[i] = (MMVideoBuffer*)malloc(sizeof(MMVideoBuffer));
+  if (use_buffer) {
+    for (int i = 0; i < n; i++) {
+      mm_vbuffer[i] = (MMVideoBuffer*)malloc(sizeof(MMVideoBuffer));
 
-    if (port->index == 1) {
-      mm_vbuffer[i]->handle.bo[0] = tbm_bo_alloc(bufmgr, port->port_def.nBufferSize, TBM_BO_WC);
-      handle_bo = tbm_bo_get_handle(mm_vbuffer[i]->handle.bo[0], TBM_DEVICE_MM);
-      mm_vbuffer[i]->handle.dmabuf_fd[0] = handle_bo.u32;
+      if (port->index == 1) {
+        mm_vbuffer[i]->handle.bo[0] = tbm_bo_alloc (bufmgr, port->port_def.nBufferSize, TBM_BO_WC);
+        handle_bo = tbm_bo_get_handle (mm_vbuffer[i]->handle.bo[0], TBM_DEVICE_MM);
+        mm_vbuffer[i]->handle.dmabuf_fd[0] = handle_bo.u32;
 
-      handle_bo = tbm_bo_get_handle(mm_vbuffer[i]->handle.bo[0], TBM_DEVICE_CPU);
-      mm_vbuffer[i]->data[0] = handle_bo.ptr;
-      mm_vbuffer[i]->type = MM_VIDEO_BUFFER_TYPE_TBM_BO;
-      mm_vbuffer[i]->size[0] = port->port_def.nBufferSize;
-      mm_vbuffer[i]->handle_num = 1;
+        handle_bo = tbm_bo_get_handle (mm_vbuffer[i]->handle.bo[0], TBM_DEVICE_CPU);
+        mm_vbuffer[i]->data[0] = handle_bo.ptr;
+        mm_vbuffer[i]->type = MM_VIDEO_BUFFER_TYPE_TBM_BO;
+        mm_vbuffer[i]->size[0] = port->port_def.nBufferSize;
+        mm_vbuffer[i]->handle_num = 1;
+      }
+      buffers = g_list_append (buffers, (gpointer)mm_vbuffer[i]);
     }
-    buffers = g_list_append(buffers,(gpointer)mm_vbuffer[i]);
   }
 
-  n = g_list_length ((GList *) buffers);
+  num = use_buffer ? g_list_length ((GList *) buffers) : -1;
   err = gst_omx_port_allocate_buffers_unlocked (port, buffers, NULL, n);
   g_mutex_unlock (&port->comp->lock);
 
@@ -2435,6 +2439,7 @@ static const GGetTypeFunction types[] = {
 #endif
 #ifdef HAVE_HEVC
       , gst_omx_h265_dec_get_type
+      , gst_omx_h265_enc_get_type
 #endif
 #ifdef HAVE_THEORA
       , gst_omx_theora_dec_get_type
index a245b88..c0273da 100644 (file)
@@ -78,6 +78,15 @@ G_BEGIN_DECLS
   (st)->nVersion.s.nStep = OMX_VERSION_STEP; \
 } G_STMT_END
 
+#ifdef USE_OMX_TARGET_EXYNOS
+#define OMX_INIT_PARAM(param) G_STMT_START { \
+  memset (&(param), 0, sizeof ((param))); \
+  (param).nSize = sizeof (param); \
+  (param).nVersion.s.nVersionMajor = 1; \
+  (param).nVersion.s.nVersionMinor = 1; \
+} G_STMT_END
+#endif
+
 /* Different hacks that are required to work around
  * bugs in different OpenMAX implementations
  */
@@ -145,6 +154,7 @@ typedef enum GOmxVendor GOmxVendor; /* check omx vender */
 typedef struct _TBMBuffer TBMBuffer;
 typedef struct _TBMInputBuffer TBMInputBuffer;
 typedef struct _TBMOutputBuffer TBMOutputBuffer;
+typedef struct _EnableGemBuffersParams EnableGemBuffersParams;
 
 struct _TBMBuffer
 {
@@ -168,8 +178,6 @@ struct _TBMOutputBuffer
     GList *buffers;
 };
 
-typedef struct _EnableGemBuffersParams EnableGemBuffersParams;
-
 struct _EnableGemBuffersParams
 {
   OMX_U32 nSize;
@@ -449,7 +457,7 @@ gboolean          gst_omx_port_is_flushing (GstOMXPort *port);
 OMX_ERRORTYPE     gst_omx_port_allocate_buffers (GstOMXPort *port);
 #ifdef TIZEN_FEATURE_OMX
 OMX_ERRORTYPE     gst_omx_port_tbm_allocate_dec_buffers (GstOMXPort * port, tbm_bufmgr  bufMgr, int eCompressionFormat, gboolean use_buffer);
-OMX_ERRORTYPE     gst_omx_port_tbm_allocate_enc_buffers (GstOMXPort * port, tbm_bufmgr  bufMgr, int eCompressionFormat);
+OMX_ERRORTYPE     gst_omx_port_tbm_allocate_enc_buffers (GstOMXPort * port, tbm_bufmgr  bufMgr, int eCompressionFormat, gboolean use_buffer);
 #endif
 OMX_ERRORTYPE     gst_omx_port_use_buffers (GstOMXPort *port, const GList *buffers);
 OMX_ERRORTYPE     gst_omx_port_use_eglimages (GstOMXPort *port, const GList *images);
index aa33ae5..6ddfe85 100644 (file)
@@ -54,6 +54,10 @@ enum
 #ifdef USE_OMX_TARGET_RPI
   PROP_INLINESPSPPSHEADERS,
 #endif
+#ifdef USE_OMX_TARGET_EXYNOS
+  PROP_NUM_REF_FRAME,
+  PROP_NUM_B_FRAME,
+#endif
   PROP_PERIODICITYOFIDRFRAMES,
   PROP_INTERVALOFCODINGINTRAFRAMES
 };
@@ -61,6 +65,12 @@ enum
 #ifdef USE_OMX_TARGET_RPI
 #define GST_OMX_H264_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT      TRUE
 #endif
+#ifdef USE_OMX_TARGET_EXYNOS
+#define GST_OMX_VIDEO_ENC_NUM_REF_FRAME_DEFAULT (0x00000001)
+#define GST_OMX_VIDEO_ENC_NUM_REF_FRAME_MAX (0x00000002)
+#define GST_OMX_VIDEO_ENC_NUM_B_FRAME_DEFAULT (0x00000001)
+#define GST_OMX_VIDEO_ENC_NUM_B_FRAME_MAX (0x00000002)
+#endif
 #define GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT    (0xffffffff)
 #define GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT (0xffffffff)
 
@@ -98,7 +108,23 @@ gst_omx_h264_enc_class_init (GstOMXH264EncClass * klass)
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
           GST_PARAM_MUTABLE_READY));
 #endif
+#ifdef USE_OMX_TARGET_EXYNOS
+  g_object_class_install_property (gobject_class, PROP_NUM_REF_FRAME,
+      g_param_spec_uint ("reference-frame", "set number of reference frame",
+          "The number of reference frame (0x00000001=component default)",
+          GST_OMX_VIDEO_ENC_NUM_REF_FRAME_DEFAULT, GST_OMX_VIDEO_ENC_NUM_REF_FRAME_MAX,
+          GST_OMX_VIDEO_ENC_NUM_REF_FRAME_DEFAULT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+          GST_PARAM_MUTABLE_READY));
 
+  g_object_class_install_property (gobject_class, PROP_NUM_B_FRAME,
+      g_param_spec_uint ("b-frame", "set number of b frame",
+          "The number of reference frame (0x00000001=component default)",
+          GST_OMX_VIDEO_ENC_NUM_B_FRAME_DEFAULT, GST_OMX_VIDEO_ENC_NUM_B_FRAME_MAX,
+          GST_OMX_VIDEO_ENC_NUM_B_FRAME_DEFAULT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+          GST_PARAM_MUTABLE_READY));
+#endif
   g_object_class_install_property (gobject_class, PROP_PERIODICITYOFIDRFRAMES,
       g_param_spec_uint ("periodicty-idr", "Target Bitrate",
           "Periodicity of IDR frames (0xffffffff=component default)",
@@ -146,6 +172,14 @@ gst_omx_h264_enc_set_property (GObject * object, guint prop_id,
       self->inline_sps_pps_headers = g_value_get_boolean (value);
       break;
 #endif
+#ifdef USE_OMX_TARGET_EXYNOS
+    case PROP_NUM_REF_FRAME:
+      self->reference_frame = g_value_get_int (value);
+      break;
+    case PROP_NUM_B_FRAME:
+      self->b_frame = g_value_get_int (value);
+      break;
+#endif
     case PROP_PERIODICITYOFIDRFRAMES:
       self->periodicty_idr = g_value_get_uint (value);
       break;
@@ -170,6 +204,14 @@ gst_omx_h264_enc_get_property (GObject * object, guint prop_id, GValue * value,
       g_value_set_boolean (value, self->inline_sps_pps_headers);
       break;
 #endif
+#ifdef USE_OMX_TARGET_EXYNOS
+    case PROP_NUM_REF_FRAME:
+      g_value_set_uint (value, self->reference_frame);
+      break;
+    case PROP_NUM_B_FRAME:
+      g_value_set_uint (value, self->b_frame);
+      break;
+#endif
     case PROP_PERIODICITYOFIDRFRAMES:
       g_value_set_uint (value, self->periodicty_idr);
       break;
@@ -189,6 +231,9 @@ gst_omx_h264_enc_init (GstOMXH264Enc * self)
   self->inline_sps_pps_headers =
       GST_OMX_H264_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT;
 #endif
+#ifdef USE_OMX_TARGET_EXYNOS
+  self->reference_frame = GST_OMX_VIDEO_ENC_NUM_REF_FRAME_DEFAULT;
+#endif
   self->periodicty_idr =
       GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT;
   self->interval_intraframes =
@@ -229,6 +274,9 @@ gst_omx_h264_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
 #ifdef USE_OMX_TARGET_RPI
   OMX_CONFIG_PORTBOOLEANTYPE config_inline_header;
 #endif
+#ifdef USE_OMX_TARGET_EXYNOS
+  OMX_VIDEO_PARAM_AVCTYPE avc_param;
+#endif
   OMX_ERRORTYPE err;
   const gchar *profile_string, *level_string;
 
@@ -262,6 +310,36 @@ gst_omx_h264_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
     return FALSE;
   }
 #endif
+#ifdef USE_OMX_TARGET_EXYNOS
+  GST_OMX_INIT_STRUCT (&avc_param);
+
+  err =
+      gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+      OMX_IndexParamVideoAvc, &avc_param);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self,
+        "can't get OMX_IndexParamVideoAvc %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  GST_DEBUG_OBJECT (self, "default nRefFrames:%u, nBFrames:%u",
+      (guint) avc_param.nRefFrames,
+      (guint) avc_param.nBFrames);
+
+  avc_param.nRefFrames = self->reference_frame;
+  avc_param.nBFrames = self->b_frame;
+  err =
+      gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+      OMX_IndexParamVideoAvc, &avc_param);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self,
+        "can't set OMX_IndexParamVideoAvc %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+#endif
 
   if (self->periodicty_idr !=
       GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT
index 03326e1..51757f5 100644 (file)
@@ -49,6 +49,10 @@ struct _GstOMXH264Enc
 #ifdef USE_OMX_TARGET_RPI
   gboolean inline_sps_pps_headers;
 #endif
+#ifdef USE_OMX_TARGET_EXYNOS
+  guint32 reference_frame;
+  guint32 b_frame;
+#endif
   guint32 periodicty_idr;
   guint32 interval_intraframes;
 
diff --git a/omx/gstomxh265enc.c b/omx/gstomxh265enc.c
new file mode 100644 (file)
index 0000000..d86e3bb
--- /dev/null
@@ -0,0 +1,613 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *   Author: Sejun Park <sejun79.park@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxh265enc.h"
+
+#ifdef USE_OMX_TARGET_RPI
+#include <OMX_Broadcom.h>
+#include <OMX_Index.h>
+#endif
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_h265_enc_debug_category);
+#define GST_CAT_DEFAULT gst_omx_h265_enc_debug_category
+
+/* prototypes */
+static gboolean gst_omx_h265_enc_set_format (GstOMXVideoEnc * enc,
+    GstOMXPort * port, GstVideoCodecState * state);
+static GstCaps *gst_omx_h265_enc_get_caps (GstOMXVideoEnc * enc,
+    GstOMXPort * port, GstVideoCodecState * state);
+static GstFlowReturn gst_omx_h265_enc_handle_output_frame (GstOMXVideoEnc *
+    self, GstOMXPort * port, GstOMXBuffer * buf, GstVideoCodecFrame * frame);
+static gboolean gst_omx_h265_enc_flush (GstVideoEncoder * enc);
+static gboolean gst_omx_h265_enc_stop (GstVideoEncoder * enc);
+static void gst_omx_h265_enc_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_omx_h265_enc_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+enum
+{
+  PROP_0,
+#ifdef USE_OMX_TARGET_RPI
+  PROP_INLINESPSPPSHEADERS,
+#endif
+  PROP_PERIODICITYOFIDRFRAMES,
+  PROP_INTERVALOFCODINGINTRAFRAMES
+};
+
+#ifdef USE_OMX_TARGET_RPI
+#define GST_OMX_H265_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT      TRUE
+#endif
+#define GST_OMX_H265_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT    (0xffffffff)
+#define GST_OMX_H265_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT (0xffffffff)
+
+
+/* class initialization */
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_omx_h265_enc_debug_category, "omxh265enc", 0, \
+      "debug category for gst-omx video encoder base class");
+
+#define parent_class gst_omx_h265_enc_parent_class
+G_DEFINE_TYPE_WITH_CODE (GstOMXH265Enc, gst_omx_h265_enc,
+    GST_TYPE_OMX_VIDEO_ENC, DEBUG_INIT);
+
+static void
+gst_omx_h265_enc_class_init (GstOMXH265EncClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstVideoEncoderClass *basevideoenc_class = GST_VIDEO_ENCODER_CLASS (klass);
+  GstOMXVideoEncClass *videoenc_class = GST_OMX_VIDEO_ENC_CLASS (klass);
+
+  videoenc_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_h265_enc_set_format);
+  videoenc_class->get_caps = GST_DEBUG_FUNCPTR (gst_omx_h265_enc_get_caps);
+
+  gobject_class->set_property = gst_omx_h265_enc_set_property;
+  gobject_class->get_property = gst_omx_h265_enc_get_property;
+
+#ifdef USE_OMX_TARGET_RPI
+  g_object_class_install_property (gobject_class, PROP_INLINESPSPPSHEADERS,
+      g_param_spec_boolean ("inline-header",
+          "Inline SPS/PPS headers before IDR",
+          "Inline SPS/PPS header before IDR",
+          GST_OMX_H265_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+          GST_PARAM_MUTABLE_READY));
+#endif
+
+  g_object_class_install_property (gobject_class, PROP_PERIODICITYOFIDRFRAMES,
+      g_param_spec_uint ("periodicty-idr", "Target Bitrate",
+          "Periodicity of IDR frames (0xffffffff=component default)",
+          0, G_MAXUINT,
+          GST_OMX_H265_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+          GST_PARAM_MUTABLE_READY));
+
+  g_object_class_install_property (gobject_class,
+      PROP_INTERVALOFCODINGINTRAFRAMES,
+      g_param_spec_uint ("interval-intraframes",
+          "Interval of coding Intra frames",
+          "Interval of coding Intra frames (0xffffffff=component default)", 0,
+          G_MAXUINT,
+          GST_OMX_H265_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+          GST_PARAM_MUTABLE_READY));
+
+  basevideoenc_class->flush = gst_omx_h265_enc_flush;
+  basevideoenc_class->stop = gst_omx_h265_enc_stop;
+
+  videoenc_class->cdata.default_src_template_caps = "video/x-h265, "
+      "width=(int) [ 1, MAX ], " "height=(int) [ 1, MAX ],"
+         "framerate = (fraction) [0, MAX], "
+         "stream-format=(string) { byte-stream }, "
+         "alignment=(string) au ";
+  videoenc_class->handle_output_frame =
+      GST_DEBUG_FUNCPTR (gst_omx_h265_enc_handle_output_frame);
+
+  gst_element_class_set_static_metadata (element_class,
+      "OpenMAX H.265 Video Encoder",
+      "Codec/Encoder/Video",
+      "Encode H.265 video streams",
+      "Sejun Park <sejun79.park@samsung.com>");
+
+  gst_omx_set_default_role (&videoenc_class->cdata, "video_encoder.hevc");
+}
+
+static void
+gst_omx_h265_enc_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstOMXH265Enc *self = GST_OMX_H265_ENC (object);
+
+  switch (prop_id) {
+#ifdef USE_OMX_TARGET_RPI
+    case PROP_INLINESPSPPSHEADERS:
+      self->inline_sps_pps_headers = g_value_get_boolean (value);
+      break;
+#endif
+    case PROP_PERIODICITYOFIDRFRAMES:
+      self->periodicty_idr = g_value_get_uint (value);
+      break;
+    case PROP_INTERVALOFCODINGINTRAFRAMES:
+      self->interval_intraframes = g_value_get_uint (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_omx_h265_enc_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstOMXH265Enc *self = GST_OMX_H265_ENC (object);
+
+  switch (prop_id) {
+#ifdef USE_OMX_TARGET_RPI
+    case PROP_INLINESPSPPSHEADERS:
+      g_value_set_boolean (value, self->inline_sps_pps_headers);
+      break;
+#endif
+    case PROP_PERIODICITYOFIDRFRAMES:
+      g_value_set_uint (value, self->periodicty_idr);
+      break;
+    case PROP_INTERVALOFCODINGINTRAFRAMES:
+      g_value_set_uint (value, self->interval_intraframes);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_omx_h265_enc_init (GstOMXH265Enc * self)
+{
+#ifdef USE_OMX_TARGET_RPI
+  self->inline_sps_pps_headers =
+      GST_OMX_H265_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT;
+#endif
+  self->periodicty_idr =
+      GST_OMX_H265_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT;
+  self->interval_intraframes =
+      GST_OMX_H265_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT;
+}
+
+static gboolean
+gst_omx_h265_enc_flush (GstVideoEncoder * enc)
+{
+  GstOMXH265Enc *self = GST_OMX_H265_ENC (enc);
+
+  g_list_free_full (self->headers, (GDestroyNotify) gst_buffer_unref);
+  self->headers = NULL;
+
+  return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (enc);
+}
+
+static gboolean
+gst_omx_h265_enc_stop (GstVideoEncoder * enc)
+{
+  GstOMXH265Enc *self = GST_OMX_H265_ENC (enc);
+
+  g_list_free_full (self->headers, (GDestroyNotify) gst_buffer_unref);
+  self->headers = NULL;
+
+  return GST_VIDEO_ENCODER_CLASS (parent_class)->stop (enc);
+}
+
+static gboolean
+gst_omx_h265_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
+    GstVideoCodecState * state)
+{
+  GstOMXH265Enc *self = GST_OMX_H265_ENC (enc);
+  GstCaps *peercaps;
+  OMX_PARAM_PORTDEFINITIONTYPE port_def;
+  OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+  OMX_VIDEO_CONFIG_AVCINTRAPERIOD config_avcintraperiod;
+#ifdef USE_OMX_TARGET_RPI
+  OMX_CONFIG_PORTBOOLEANTYPE config_inline_header;
+#endif
+  OMX_ERRORTYPE err;
+  const gchar *profile_string, *level_string;
+
+#ifdef USE_OMX_TARGET_RPI
+  GST_OMX_INIT_STRUCT (&config_inline_header);
+  config_inline_header.nPortIndex =
+      GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+  err =
+      gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+      OMX_IndexParamBrcmVideoAVCInlineHeaderEnable, &config_inline_header);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self,
+        "can't get OMX_IndexParamBrcmVideoAVCInlineHeaderEnable %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  if (self->inline_sps_pps_headers) {
+    config_inline_header.bEnabled = OMX_TRUE;
+  } else {
+    config_inline_header.bEnabled = OMX_FALSE;
+  }
+
+  err =
+      gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+      OMX_IndexParamBrcmVideoAVCInlineHeaderEnable, &config_inline_header);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self,
+        "can't set OMX_IndexParamBrcmVideoAVCInlineHeaderEnable %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+#endif
+
+  if (self->periodicty_idr !=
+      GST_OMX_H265_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT
+      || self->interval_intraframes !=
+      GST_OMX_H265_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT) {
+
+
+    GST_OMX_INIT_STRUCT (&config_avcintraperiod);
+    config_avcintraperiod.nPortIndex =
+        GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+    err =
+        gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+        OMX_IndexConfigVideoAVCIntraPeriod, &config_avcintraperiod);
+    if (err != OMX_ErrorNone) {
+      GST_ERROR_OBJECT (self,
+          "can't get OMX_IndexConfigVideoAVCIntraPeriod %s (0x%08x)",
+          gst_omx_error_to_string (err), err);
+      return FALSE;
+    }
+
+    GST_DEBUG_OBJECT (self, "default nPFrames:%u, nIDRPeriod:%u",
+        (guint) config_avcintraperiod.nPFrames,
+        (guint) config_avcintraperiod.nIDRPeriod);
+
+    if (self->periodicty_idr !=
+        GST_OMX_H265_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT) {
+      config_avcintraperiod.nIDRPeriod = self->periodicty_idr;
+    }
+
+    if (self->interval_intraframes !=
+        GST_OMX_H265_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT) {
+      config_avcintraperiod.nPFrames = self->interval_intraframes;
+    }
+
+    err =
+        gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+        OMX_IndexConfigVideoAVCIntraPeriod, &config_avcintraperiod);
+    if (err != OMX_ErrorNone) {
+      GST_ERROR_OBJECT (self,
+          "can't set OMX_IndexConfigVideoAVCIntraPeriod %s (0x%08x)",
+          gst_omx_error_to_string (err), err);
+      return FALSE;
+    }
+  }
+
+  gst_omx_port_get_port_definition (GST_OMX_VIDEO_ENC (self)->enc_out_port,
+      &port_def);
+  port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
+  err =
+      gst_omx_port_update_port_definition (GST_OMX_VIDEO_ENC
+      (self)->enc_out_port, &port_def);
+  if (err != OMX_ErrorNone)
+    return FALSE;
+
+  GST_OMX_INIT_STRUCT (&param);
+  param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+
+  err =
+      gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+      OMX_IndexParamVideoProfileLevelCurrent, &param);
+  if (err != OMX_ErrorNone) {
+    GST_WARNING_OBJECT (self,
+        "Setting profile/level not supported by component");
+    return TRUE;
+  }
+
+  peercaps = gst_pad_peer_query_caps (GST_VIDEO_ENCODER_SRC_PAD (enc),
+      gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (enc)));
+  if (peercaps) {
+    GstStructure *s;
+
+    if (gst_caps_is_empty (peercaps)) {
+      gst_caps_unref (peercaps);
+      GST_ERROR_OBJECT (self, "Empty caps");
+      return FALSE;
+    }
+
+    s = gst_caps_get_structure (peercaps, 0);
+    profile_string = gst_structure_get_string (s, "profile");
+    if (profile_string) {
+      if (g_str_equal (profile_string, "main")) {
+        param.eProfile = OMX_VIDEO_HEVCProfileMain;
+      } else if (g_str_equal (profile_string, "main-10")) {
+        param.eProfile = OMX_VIDEO_HEVCProfileMain10;
+      } else {
+        goto unsupported_profile;
+      }
+    }
+    level_string = gst_structure_get_string (s, "level");
+    if (level_string) {
+      if (g_str_equal (level_string, "main1")) {
+        param.eLevel = OMX_VIDEO_HEVCMainTierLevel1;
+      } else if (g_str_equal (level_string, "high1")) {
+        param.eLevel = OMX_VIDEO_HEVCHighTierLevel1;
+      } else if (g_str_equal (level_string, "main2")) {
+        param.eLevel = OMX_VIDEO_HEVCMainTierLevel2;
+      } else if (g_str_equal (level_string, "high2")) {
+        param.eLevel = OMX_VIDEO_HEVCHighTierLevel2;
+      } else if (g_str_equal (level_string, "main2.1")) {
+        param.eLevel = OMX_VIDEO_HEVCMainTierLevel21;
+      } else if (g_str_equal (level_string, "high2.1")) {
+        param.eLevel = OMX_VIDEO_HEVCHighTierLevel21;
+      } else if (g_str_equal (level_string, "main3")) {
+        param.eLevel = OMX_VIDEO_HEVCMainTierLevel3;
+      } else if (g_str_equal (level_string, "high3")) {
+        param.eLevel = OMX_VIDEO_HEVCHighTierLevel3;
+      } else if (g_str_equal (level_string, "main3.1")) {
+        param.eLevel = OMX_VIDEO_HEVCMainTierLevel31;
+      } else if (g_str_equal (level_string, "high3.1")) {
+        param.eLevel = OMX_VIDEO_HEVCHighTierLevel31;
+      } else if (g_str_equal (level_string, "main4")) {
+        param.eLevel = OMX_VIDEO_HEVCMainTierLevel4;
+      } else if (g_str_equal (level_string, "high4")) {
+        param.eLevel = OMX_VIDEO_HEVCHighTierLevel4;
+      } else if (g_str_equal (level_string, "main4.1")) {
+        param.eLevel = OMX_VIDEO_HEVCMainTierLevel41;
+      } else if (g_str_equal (level_string, "high4.1")) {
+        param.eLevel = OMX_VIDEO_HEVCHighTierLevel41;
+      } else if (g_str_equal (level_string, "main5")) {
+        param.eLevel = OMX_VIDEO_HEVCMainTierLevel5;
+      } else if (g_str_equal (level_string, "high5")) {
+        param.eLevel = OMX_VIDEO_HEVCHighTierLevel5;
+      } else if (g_str_equal (level_string, "main5.1")) {
+        param.eLevel = OMX_VIDEO_HEVCMainTierLevel51;
+      } else if (g_str_equal (level_string, "high5.1")) {
+        param.eLevel = OMX_VIDEO_HEVCHighTierLevel51;
+      } else if (g_str_equal (level_string, "main5.2")) {
+        param.eLevel = OMX_VIDEO_HEVCMainTierLevel52;
+      } else if (g_str_equal (level_string, "high5.2")) {
+        param.eLevel = OMX_VIDEO_HEVCHighTierLevel52;
+      } else if (g_str_equal (level_string, "main6")) {
+        param.eLevel = OMX_VIDEO_HEVCMainTierLevel6;
+      } else if (g_str_equal (level_string, "high6")) {
+        param.eLevel = OMX_VIDEO_HEVCHighTierLevel6;
+      } else if (g_str_equal (level_string, "main61")) {
+        param.eLevel = OMX_VIDEO_HEVCMainTierLevel61;
+      } else if (g_str_equal (level_string, "high61")) {
+        param.eLevel = OMX_VIDEO_HEVCHighTierLevel61;
+      } else if (g_str_equal (level_string, "main62")) {
+        param.eLevel = OMX_VIDEO_HEVCMainTierLevel62;
+      } else if (g_str_equal (level_string, "high62")) {
+        param.eLevel = OMX_VIDEO_HEVCHighTierLevel62;
+      } else {
+        goto unsupported_level;
+      }
+    }
+    gst_caps_unref (peercaps);
+  }
+
+  err =
+      gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+      OMX_IndexParamVideoProfileLevelCurrent, &param);
+  if (err == OMX_ErrorUnsupportedIndex) {
+    GST_WARNING_OBJECT (self,
+        "Setting profile/level not supported by component");
+  } else if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self,
+        "Error setting profile %u and level %u: %s (0x%08x)",
+        (guint) param.eProfile, (guint) param.eLevel,
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  return TRUE;
+
+unsupported_profile:
+  GST_ERROR_OBJECT (self, "Unsupported profile %s", profile_string);
+  gst_caps_unref (peercaps);
+  return FALSE;
+
+unsupported_level:
+  GST_ERROR_OBJECT (self, "Unsupported level %s", level_string);
+  gst_caps_unref (peercaps);
+  return FALSE;
+}
+
+static GstCaps *
+gst_omx_h265_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
+    GstVideoCodecState * state)
+{
+  GstOMXH265Enc *self = GST_OMX_H265_ENC (enc);
+  GstCaps *caps;
+  OMX_ERRORTYPE err;
+  OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+  const gchar *profile, *level;
+
+  caps = gst_caps_new_simple ("video/x-h265",
+      "stream-format", G_TYPE_STRING, "byte-stream",
+      "alignment", G_TYPE_STRING, "au", NULL);
+
+  GST_OMX_INIT_STRUCT (&param);
+  param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+
+  err =
+      gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+      OMX_IndexParamVideoProfileLevelCurrent, &param);
+  if (err != OMX_ErrorNone && err != OMX_ErrorUnsupportedIndex)
+    return NULL;
+
+  if (err == OMX_ErrorNone) {
+    switch (param.eProfile) {
+      case OMX_VIDEO_HEVCProfileMain:
+        profile = "main";
+        break;
+      case OMX_VIDEO_HEVCProfileMain10:
+        profile = "main-10";
+        break;
+      default:
+        g_assert_not_reached ();
+        return NULL;
+    }
+
+    switch (param.eLevel) {
+      case OMX_VIDEO_HEVCMainTierLevel1:
+        level = "main1";
+        break;
+      case OMX_VIDEO_HEVCHighTierLevel1:
+        level = "high1";
+        break;
+      case OMX_VIDEO_HEVCMainTierLevel2:
+        level = "main2";
+        break;
+      case OMX_VIDEO_HEVCHighTierLevel2:
+        level = "high2";
+        break;
+      case OMX_VIDEO_HEVCMainTierLevel21:
+        level = "main2.1";
+        break;
+      case OMX_VIDEO_HEVCHighTierLevel21:
+        level = "high2.1";
+        break;
+      case OMX_VIDEO_HEVCMainTierLevel3:
+        level = "main3";
+        break;
+      case OMX_VIDEO_HEVCHighTierLevel3:
+        level = "high3";
+        break;
+      case OMX_VIDEO_HEVCMainTierLevel31:
+        level = "main3.1";
+        break;
+      case OMX_VIDEO_HEVCHighTierLevel31:
+        level = "high3.1";
+        break;
+      case OMX_VIDEO_HEVCMainTierLevel4:
+        level = "main4";
+        break;
+      case OMX_VIDEO_HEVCHighTierLevel4:
+        level = "high4";
+        break;
+      case OMX_VIDEO_HEVCMainTierLevel41:
+        level = "main4.1";
+        break;
+      case OMX_VIDEO_HEVCHighTierLevel41:
+        level = "high4.1";
+        break;
+      case OMX_VIDEO_HEVCMainTierLevel5:
+        level = "main5";
+        break;
+      case OMX_VIDEO_HEVCHighTierLevel5:
+        level = "high5";
+        break;
+      case OMX_VIDEO_HEVCMainTierLevel51:
+        level = "main5.1";
+        break;
+      case OMX_VIDEO_HEVCHighTierLevel51:
+        level = "high5.1";
+        break;
+      case OMX_VIDEO_HEVCMainTierLevel52:
+        level = "main5.2";
+        break;
+      case OMX_VIDEO_HEVCHighTierLevel52:
+        level = "high5.2";
+        break;
+      case OMX_VIDEO_HEVCMainTierLevel6:
+        level = "main6";
+        break;
+      case OMX_VIDEO_HEVCHighTierLevel6:
+        level = "high6";
+        break;
+      case OMX_VIDEO_HEVCMainTierLevel61:
+        level = "main6.1";
+        break;
+      case OMX_VIDEO_HEVCHighTierLevel61:
+        level = "high6.1";
+        break;
+      case OMX_VIDEO_HEVCMainTierLevel62:
+        level = "main6.2";
+        break;
+      case OMX_VIDEO_HEVCHighTierLevel62:
+        level = "high6.2";
+        break;
+      default:
+        g_assert_not_reached ();
+        return NULL;
+    }
+
+    gst_caps_set_simple (caps,
+        "profile", G_TYPE_STRING, profile, "level", G_TYPE_STRING, level, NULL);
+  }
+
+  return caps;
+}
+
+static GstFlowReturn
+gst_omx_h265_enc_handle_output_frame (GstOMXVideoEnc * enc, GstOMXPort * port,
+    GstOMXBuffer * buf, GstVideoCodecFrame * frame)
+{
+  GstOMXH265Enc *self = GST_OMX_H265_ENC (enc);
+
+  if (buf->omx_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
+    /* The codec data is SPS/PPS with a startcode => bytestream stream format
+     * For bytestream stream format the SPS/PPS is only in-stream and not
+     * in the caps!
+     */
+    if (buf->omx_buf->nFilledLen >= 4 &&
+        GST_READ_UINT32_BE (buf->omx_buf->pBuffer +
+            buf->omx_buf->nOffset) == 0x00000001) {
+      GstBuffer *hdrs;
+      GstMapInfo map = GST_MAP_INFO_INIT;
+
+      GST_DEBUG_OBJECT (self, "got codecconfig in byte-stream format");
+
+      hdrs = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
+
+      gst_buffer_map (hdrs, &map, GST_MAP_WRITE);
+      memcpy (map.data,
+          buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+          buf->omx_buf->nFilledLen);
+      gst_buffer_unmap (hdrs, &map);
+      self->headers = g_list_append (self->headers, hdrs);
+
+      if (frame)
+        gst_video_codec_frame_unref (frame);
+
+      return GST_FLOW_OK;
+    }
+  } else if (self->headers) {
+    gst_video_encoder_set_headers (GST_VIDEO_ENCODER (self), self->headers);
+    self->headers = NULL;
+  }
+
+  return
+      GST_OMX_VIDEO_ENC_CLASS
+      (gst_omx_h265_enc_parent_class)->handle_output_frame (enc, port, buf,
+      frame);
+}
diff --git a/omx/gstomxh265enc.h b/omx/gstomxh265enc.h
new file mode 100644 (file)
index 0000000..0c34918
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *   Author: Sejun Park <sejun79.park@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifndef __GST_OMX_H265_ENC_H__
+#define __GST_OMX_H265_ENC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideoenc.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_H265_ENC \
+  (gst_omx_h265_enc_get_type())
+#define GST_OMX_H265_ENC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_H265_ENC,GstOMXH265Enc))
+#define GST_OMX_H265_ENC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_H265_ENC,GstOMXH265EncClass))
+#define GST_OMX_H265_ENC_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_H265_ENC,GstOMXH265EncClass))
+#define GST_IS_OMX_H265_ENC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_H265_ENC))
+#define GST_IS_OMX_H265_ENC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_H265_ENC))
+
+typedef struct _GstOMXH265Enc GstOMXH265Enc;
+typedef struct _GstOMXH265EncClass GstOMXH265EncClass;
+
+struct _GstOMXH265Enc
+{
+  GstOMXVideoEnc parent;
+
+#ifdef USE_OMX_TARGET_RPI
+  gboolean inline_sps_pps_headers;
+#endif
+  guint32 periodicty_idr;
+  guint32 interval_intraframes;
+
+  GList *headers;
+};
+
+struct _GstOMXH265EncClass
+{
+  GstOMXVideoEncClass parent_class;
+};
+
+GType gst_omx_h265_enc_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_H265_ENC_H__ */
+
index 1b1732f..872d306 100644 (file)
@@ -213,7 +213,7 @@ gst_omx_video_dec_open (GstVideoDecoder * decoder)
 
 #ifdef TIZEN_FEATURE_OMX
   self->bufmgr = tbm_bufmgr_init(self->drm_fd);
-  if(self->bufmgr == NULL) {
+  if (self->bufmgr == NULL) {
     GST_ERROR_OBJECT (self, "TBM initialization failed.");
     return FALSE;
   }
@@ -1922,8 +1922,7 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
 #ifdef TIZEN_FEATURE_OMX
   gchar *format_tmp;
   int i;
-  EnableGemBuffersParams gemBuffers;
-  EnableGemBuffersParams config;
+  EnableGemBuffersParams gem_param;
 #endif
 
   GST_DEBUG_OBJECT (self, "Trying to negotiate a video format with downstream");
@@ -2026,18 +2025,18 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
 
     /* Set platform specific buffer settings. to avoid plane support error.. */
 #ifdef TIZEN_FEATURE_OMX
-  OMX_INIT_STRUCTURE(gemBuffers);
-  gemBuffers.enable = OMX_TRUE;
-  gemBuffers.nPortIndex = 1;
+  OMX_INIT_PARAM (gem_param);
+  gem_param.enable = OMX_TRUE;
+  gem_param.nPortIndex = 1;
 
   OMX_INDEXTYPE index = OMX_IndexComponentStartUnused;
 
-  err = OMX_GetExtensionIndex(self->dec->handle, "OMX.SEC.index.enablePlatformSpecificBuffers", &index);
+  err = OMX_GetExtensionIndex (self->dec->handle, "OMX.SEC.index.enablePlatformSpecificBuffers", &index);
   if (err != OMX_ErrorNone || index == OMX_IndexComponentStartUnused) {
     GST_INFO_OBJECT (self, "can not get index for OMX_GetExtensionIndex enablePlatformSpecificBuffers");
   }
 
-  err = gst_omx_component_set_parameter(self->dec, index, &gemBuffers);
+  err = gst_omx_component_set_parameter(self->dec, index, &gem_param);
 
 #if 0
   err =
@@ -2049,13 +2048,13 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
         gst_omx_error_to_string (err), err);
   }
 
-  OMX_INIT_STRUCTURE(config);
-  config.enable = OMX_TRUE;
-  config.nPortIndex = 0;
+  OMX_INIT_PARAM (gem_param);
+  gem_param.enable = OMX_TRUE;
+  gem_param.nPortIndex = 0;
 
   err =
       gst_omx_component_set_parameter (self->dec,
-      OMX_IndexParamEnableTimestampReorder, &config);
+      OMX_IndexParamEnableTimestampReorder, &gem_param);
 
   if (err != OMX_ErrorNone) {
     GST_ERROR_OBJECT (self, "Failed to set timestamp reorder: %s (0x%08x)",
index 0511f31..fd08a83 100644 (file)
 
 #include "gstomx.h"
 
-#define OMX_VERSION_MAJOR 1
-#define OMX_VERSION_MINOR 1
-#define OMX_VERSION_REVISION 2
-#define OMX_VERSION_STEP 0
-#define EXTRA_DECODER_OUTPUT_BUF 4
-
-#define OMX_VERSION ((OMX_VERSION_STEP<<24) | (OMX_VERSION_REVISION<<16) | (OMX_VERSION_MINOR<<8) | OMX_VERSION_MAJOR)
-
-#define OMX_INIT_STRUCTURE(a) \
-    memset(&(a), 0, sizeof(a)); \
-    (a).nSize = sizeof(a); \
-    (a).nVersion.nVersion = OMX_VERSION; \
-    (a).nVersion.s.nVersionMajor = OMX_VERSION_MAJOR; \
-    (a).nVersion.s.nVersionMinor = OMX_VERSION_MINOR; \
-    (a).nVersion.s.nRevision = OMX_VERSION_REVISION; \
-    (a).nVersion.s.nStep = OMX_VERSION_STEP
-
 G_BEGIN_DECLS
 
 #define GST_TYPE_OMX_VIDEO_DEC \
@@ -63,6 +46,8 @@ G_BEGIN_DECLS
 #define GST_IS_OMX_VIDEO_DEC_CLASS(obj) \
   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_VIDEO_DEC))
 
+#define EXTRA_DECODER_OUTPUT_BUF 4
+
 typedef struct _GstOMXVideoDec GstOMXVideoDec;
 typedef struct _GstOMXVideoDecClass GstOMXVideoDecClass;
 
index 965ceb1..d0cf315 100644 (file)
@@ -116,6 +116,7 @@ enum
 #define GST_OMX_VIDEO_ENC_QUANT_P_FRAMES_DEFAULT (0xffffffff)
 #define GST_OMX_VIDEO_ENC_QUANT_B_FRAMES_DEFAULT (0xffffffff)
 
+
 /* class initialization */
 
 #define DEBUG_INIT \
@@ -211,7 +212,7 @@ gst_omx_video_enc_init (GstOMXVideoEnc * self)
   g_mutex_init (&self->drain_lock);
   g_cond_init (&self->drain_cond);
 #ifdef TIZEN_FEATURE_OMX
-  self->hTBMBufMgr = NULL;
+  self->bufmgr = NULL;
   self->drm_fd = -1;
 #endif
 }
@@ -246,6 +247,41 @@ gst_omx_video_enc_input_dump (MMVideoBuffer *inbuf)
 }
 #endif
 
+#ifdef TIZEN_FEATURE_OMX
+static void
+set_enable_platformSpecificBuffer(GstOMXVideoEnc * self)
+{
+  OMX_INDEXTYPE index = OMX_IndexComponentStartUnused;
+  OMX_ERRORTYPE err = OMX_ErrorNone;
+  EnableGemBuffersParams params;
+
+  GST_LOG_OBJECT (self, "set_enable_platformSpecificBuffer enter");
+
+  err = OMX_GetExtensionIndex(self->enc->handle, "OMX.SEC.index.enablePlatformSpecificBuffers", &index);
+  if (err != OMX_ErrorNone || index == OMX_IndexComponentStartUnused) {
+    GST_INFO_OBJECT (self, "can not get index for OMX_GetExtensionIndex enablePlatformSpecificBuffers");
+    return;
+  }
+
+  GST_INFO ("index= %x", index);
+
+  OMX_INIT_PARAM (params);
+
+  params.nPortIndex = self->enc_in_port->index;
+  params.enable = OMX_TRUE;
+
+  err = OMX_SetParameter(self->enc->handle, index, &params);
+  if (err == OMX_ErrorNone) {
+    GST_INFO_OBJECT (self, "set_enable_platformSpecificBuffer success.");
+  }
+  else {
+    GST_ERROR_OBJECT (self, "set OMX_IndexParamEnablePlatformSpecificBuffers failed with error %d (0x%08x)", err, err);
+  }
+
+  return;
+}
+#endif
+
 static gboolean
 gst_omx_video_enc_open (GstVideoEncoder * encoder)
 {
@@ -295,6 +331,11 @@ gst_omx_video_enc_open (GstVideoEncoder * encoder)
   self->enc_in_port = gst_omx_component_add_port (self->enc, in_port_index);
   self->enc_out_port = gst_omx_component_add_port (self->enc, out_port_index);
 
+#ifdef TIZEN_FEATURE_OMX
+  /* get extension index and set platform specific buffer enable */
+  set_enable_platformSpecificBuffer (self);
+#endif
+
   if (!self->enc_in_port || !self->enc_out_port)
     return FALSE;
 
@@ -366,6 +407,11 @@ gst_omx_video_enc_open (GstVideoEncoder * encoder)
         if (self->quant_b_frames != 0xffffffff)
           quant_param.nQpB = self->quant_b_frames;
 
+#ifdef TIZEN_FEATURE_OMX
+        quant_param.nQpI = 20;
+        quant_param.nQpP = 20;
+        quant_param.nQpB = 20;
+#endif
         err =
             gst_omx_component_set_parameter (self->enc,
             OMX_IndexParamVideoQuantization, &quant_param);
@@ -389,13 +435,34 @@ gst_omx_video_enc_open (GstVideoEncoder * encoder)
 
       }
     }
+/*
+#ifdef TIZEN_FEATURE_OMX
+    {
+      OMX_VIDEO_PARAM_AVCTYPE param;
+
+      GST_OMX_INIT_STRUCT (&param);
+      param.nPortIndex = self->enc_out_port->index;
+      err = gst_omx_component_get_parameter (self->enc, OMX_IndexParamVideoAvc, &param);
+      if (err != OMX_ErrorNone)
+        GST_ERROR_OBJECT (self, "Failed to get OMX_IndexParamVideoAvc parameter. ret = %d", err);
+
+      param.nPFrames = self->idr_period - 1;
+      err = gst_omx_component_set_parameter (self->enc, OMX_IndexParamVideoAvc, &param);
+      if (err != OMX_ErrorNone)
+        GST_ERROR_OBJECT (self, "Failed to set OMX_IndexParamVideoAvc. IDR period = %d  ret = %d", self->idr_period, err);
+    }
+#endif
+*/
   }
 #ifdef TIZEN_FEATURE_OMX
-   self->hTBMBufMgr = tbm_bufmgr_init(self->drm_fd);
-   if(self->hTBMBufMgr == NULL){
+   self->bufmgr = tbm_bufmgr_init (self->drm_fd);
+   if (self->bufmgr == NULL){
     GST_ERROR_OBJECT (self, "TBM initialization failed.");
     return FALSE;
    }
+
+  self->enc_in_port->use_buffer = klass->cdata.in_port_usebuffer;
+  self->enc_out_port->use_buffer = klass->cdata.out_port_usebuffer;
 #endif
   return TRUE;
 }
@@ -618,11 +685,20 @@ gst_omx_video_enc_handle_output_frame (GstOMXVideoEnc * self, GstOMXPort * port,
         self->input_state);
     state->codec_data = codec_data;
     gst_video_codec_state_unref (state);
+#ifdef TIZEN_FEATURE_OMX
+    /*Modification : codec data already set_caps, so unref frame whenever negotiate ok or not*/
+    if (!gst_video_encoder_negotiate (GST_VIDEO_ENCODER (self)))
+      flow_ret = GST_FLOW_NOT_NEGOTIATED;
+    else
+      flow_ret = GST_FLOW_OK;
+    gst_video_codec_frame_unref (frame);
+#else
     if (!gst_video_encoder_negotiate (GST_VIDEO_ENCODER (self))) {
       gst_video_codec_frame_unref (frame);
       return GST_FLOW_NOT_NEGOTIATED;
     }
     flow_ret = GST_FLOW_OK;
+#endif
   } else if (buf->omx_buf->nFilledLen > 0) {
     GstBuffer *outbuf;
     GstMapInfo map = GST_MAP_INFO_INIT;
@@ -757,8 +833,8 @@ gst_omx_video_enc_loop (GstOMXVideoEnc * self)
       if (err != OMX_ErrorNone)
         goto reconfigure_error;
 #ifdef TIZEN_FEATURE_OMX
-    err = gst_omx_port_tbm_allocate_enc_buffers(port, self->hTBMBufMgr,
-        self->enc_in_port->port_def.format.video.eCompressionFormat);
+    err = gst_omx_port_tbm_allocate_enc_buffers(port, self->bufmgr,
+        self->enc_in_port->port_def.format.video.eCompressionFormat, port->use_buffer);
 #else
       err = gst_omx_port_allocate_buffers (port);
 #endif
@@ -1095,15 +1171,23 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
   }
 
   port_def.format.video.nFrameWidth = info->width;
+#ifdef TIZEN_FEATURE_OMX
+  port_def.format.video.nStride = ALIGN(info->width, 16);
+#else
   if (port_def.nBufferAlignment)
     port_def.format.video.nStride =
         (info->width + port_def.nBufferAlignment - 1) &
         (~(port_def.nBufferAlignment - 1));
   else
     port_def.format.video.nStride = GST_ROUND_UP_4 (info->width);       /* safe (?) default */
+#endif
 
   port_def.format.video.nFrameHeight = info->height;
+#ifdef TIZEN_FEATURE_OMX
+  port_def.format.video.nSliceHeight = ALIGN(info->width, 16);
+#else
   port_def.format.video.nSliceHeight = info->height;
+#endif
 
   switch (port_def.format.video.eColorFormat) {
     case OMX_COLOR_FormatYUV420Planar:
@@ -1146,6 +1230,18 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
           &port_def) != OMX_ErrorNone)
     return FALSE;
 
+#ifdef TIZEN_FEATURE_OMX
+  /*MODIFICATION : Output port configuration*/
+  GST_DEBUG_OBJECT (self, "Updating outport port definition");
+  gst_omx_port_get_port_definition (self->enc_out_port, &port_def);
+
+  port_def.format.video.nFrameWidth = info->width;
+  port_def.format.video.nFrameHeight = info->height;
+
+  if (gst_omx_port_update_port_definition (self->enc_out_port, &port_def) != OMX_ErrorNone)
+    return FALSE;
+#endif
+
 #ifdef USE_OMX_TARGET_RPI
   /* aspect ratio */
   {
@@ -1216,8 +1312,9 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
     if (gst_omx_port_set_enabled (self->enc_in_port, TRUE) != OMX_ErrorNone)
       return FALSE;
 #ifdef TIZEN_FEATURE_OMX
-    if(gst_omx_port_tbm_allocate_enc_buffers(self->enc_in_port, self->hTBMBufMgr,
-        self->enc_in_port->port_def.format.video.eCompressionFormat) != OMX_ErrorNone)
+    if (gst_omx_port_tbm_allocate_enc_buffers (self->enc_in_port, self->bufmgr,
+        self->enc_in_port->port_def.format.video.eCompressionFormat,
+        self->enc_in_port->use_buffer) != OMX_ErrorNone)
         return FALSE;
 #else
     if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
@@ -1264,8 +1361,9 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
 
       /* Need to allocate buffers to reach Idle state */
 #ifdef TIZEN_FEATURE_OMX
-    if(gst_omx_port_tbm_allocate_enc_buffers(self->enc_in_port, self->hTBMBufMgr,
-        self->enc_in_port->port_def.format.video.eCompressionFormat) != OMX_ErrorNone)
+    if (gst_omx_port_tbm_allocate_enc_buffers(self->enc_in_port, self->bufmgr,
+        self->enc_in_port->port_def.format.video.eCompressionFormat,
+        self->enc_in_port->use_buffer) != OMX_ErrorNone)
         return FALSE;
 #else
       if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
@@ -1273,8 +1371,9 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
 #endif
 
 #ifdef TIZEN_FEATURE_OMX
-    if(gst_omx_port_tbm_allocate_enc_buffers(self->enc_out_port, self->hTBMBufMgr,
-        self->enc_out_port->port_def.format.video.eCompressionFormat) != OMX_ErrorNone)
+    if (gst_omx_port_tbm_allocate_enc_buffers(self->enc_out_port, self->bufmgr,
+        self->enc_out_port->port_def.format.video.eCompressionFormat,
+        self->enc_out_port->use_buffer) != OMX_ErrorNone)
 #else
       if (gst_omx_port_allocate_buffers (self->enc_out_port) != OMX_ErrorNone)
 #endif
@@ -1644,8 +1743,8 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
         goto reconfigure_error;
       }
 #ifdef TIZEN_FEATURE_OMX
-    err = gst_omx_port_tbm_allocate_enc_buffers(port, self->hTBMBufMgr,
-        self->enc_in_port->port_def.format.video.eCompressionFormat);
+    err = gst_omx_port_tbm_allocate_enc_buffers (port, self->bufmgr,
+        self->enc_in_port->port_def.format.video.eCompressionFormat, port->use_buffer);
 #else
       err = gst_omx_port_allocate_buffers (port);
 #endif
index 497ca54..06748c0 100644 (file)
@@ -78,7 +78,7 @@ struct _GstOMXVideoEnc
   GstFlowReturn downstream_flow_ret;
 #ifdef TIZEN_FEATURE_OMX
   gint drm_fd;
-  tbm_bufmgr hTBMBufMgr;
+  tbm_bufmgr bufmgr;
 #endif
 };