Add codec hal testcases 31/187031/1 accepted/tizen/unified/20180820.060042 submit/tizen/20180817.093636
authorSejun Park <sejun79.park@samsung.com>
Fri, 17 Aug 2018 09:26:31 +0000 (18:26 +0900)
committerSejun Park <sejun79.park@samsung.com>
Fri, 17 Aug 2018 09:26:31 +0000 (18:26 +0900)
Change-Id: Id51b346f07a0a72de402c4541447b1370e82a43b

15 files changed:
Makefile.am [changed mode: 0644->0755]
codec-hal-interface.pc.in [new file with mode: 0644]
configure.ac [changed mode: 0644->0755]
include/codec/codec_hal_interface.h [new file with mode: 0644]
mm-hal-interface-codec.manifest [new file with mode: 0644]
packaging/mm-hal-interface.spec [changed mode: 0644->0755]
src/Makefile.am [changed mode: 0644->0755]
src/codec/Makefile.am [new file with mode: 0644]
src/codec/codec_hal_interface.c [new file with mode: 0644]
testcase/Makefile.am [changed mode: 0644->0755]
testcase/codec/Makefile.am [new file with mode: 0644]
testcase/codec/codec_haltests.cpp [new file with mode: 0644]
testcase/codec/res/meerkat.mp4 [new file with mode: 0755]
testcase/codec/res/mv.MP4 [new file with mode: 0755]
testcase/codec/res/she.3gp [new file with mode: 0755]

old mode 100644 (file)
new mode 100755 (executable)
index a00a6d9..c335d49
@@ -1,7 +1,9 @@
 SUBDIRS = src testcase
 
 pcfiles = camera-hal-interface.pc \
-         radio-hal-interface.pc
+          radio-hal-interface.pc \
+          codec-hal-interface.pc
+
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = $(pcfiles)
 EXTRA_DIST = $(pcfiles)
diff --git a/codec-hal-interface.pc.in b/codec-hal-interface.pc.in
new file mode 100644 (file)
index 0000000..753b5fe
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: codec-hal-interface
+Description: Multimedia Framework Codec HAL Interface library
+Requires: glib-2.0 dlog
+Version: $VERSION
+Libs: -L${libdir} -lcodec_hal_interface
+Cflags: -I${includedir}/
old mode 100644 (file)
new mode 100755 (executable)
index 9616f12..330e936
@@ -30,6 +30,24 @@ PKG_CHECK_MODULES(SYSTEM_INFO, capi-system-info)
 AC_SUBST(SYSTEM_INFO_CFLAGS)
 AC_SUBST(SYSTEM_INFO_LIBS)
 
+PKG_CHECK_MODULES(GST, gstreamer-1.0 >= 1.2.0)
+AC_SUBST(GST_CFLAGS)
+AC_SUBST(GST_LIBS)
+
+PKG_CHECK_MODULES(GST_PLUGIN_BASE, gstreamer-plugins-base-1.0 >= 1.2.0)
+AC_SUBST(GST_PLUGIN_BASE_CFLAGS)
+AC_SUBST(GST_PLUGIN_BASE_LIBS)
+
+PKG_CHECK_MODULES(INIPARSER, iniparser)
+AC_SUBST(INIPARSER_CFLAGS)
+AC_SUBST(INIPARSER_LIBS)
+
+PKG_CHECK_MODULES(TBM, libtbm)
+AC_SUBST(TBM_CFLAGS)
+AC_SUBST(TBM_LIBS)
+
+PKG_CHECK_MODULES([GST_ALLOCATORS], [gstreamer-allocators-1.0])
+
 # Checks for library functions.
 AC_CONFIG_FILES([
 Makefile
@@ -37,12 +55,15 @@ src/Makefile
 src/camera/Makefile
 src/radio/Makefile
 src/audio/Makefile
+src/codec/Makefile
 testcase/Makefile
 testcase/camera/Makefile
 testcase/radio/Makefile
 testcase/audio/Makefile
+testcase/codec/Makefile
 camera-hal-interface.pc
 radio-hal-interface.pc
+codec-hal-interface.pc
 ])
 AC_OUTPUT
 
diff --git a/include/codec/codec_hal_interface.h b/include/codec/codec_hal_interface.h
new file mode 100644 (file)
index 0000000..7e24112
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * codec_hal_interface.h
+ *
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Sejun Park <sejun79.park@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/mm-hal-interface-codec.manifest b/mm-hal-interface-codec.manifest
new file mode 100644 (file)
index 0000000..a76fdba
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_" />
+       </request>
+</manifest>
old mode 100644 (file)
new mode 100755 (executable)
index 9d8fa87..3f53eee
@@ -11,6 +11,10 @@ BuildRequires:  pkgconfig(glib-2.0)
 BuildRequires:  pkgconfig(dlog)
 BuildRequires:  pkgconfig(capi-system-info)
 BuildRequires:  gtest-devel
+BuildRequires:  pkgconfig(libtbm)
+BuildRequires:  pkgconfig(gstreamer-1.0)
+BuildRequires:  pkgconfig(gstreamer-plugins-base-1.0)
+BuildRequires:  pkgconfig(iniparser)
 
 %description
 Multimedia framework hardware abstraction layer interface package.
@@ -40,6 +44,14 @@ Version:    %{version}
 %description audio
 Multimedia framework hardware abstraction layer interface library for audio.
 
+%package codec
+Summary:    Multimedia framework hardware abstraction layer interface library for codec
+Group:      Multimedia/Libraries
+Version:    %{version}
+
+%description codec
+Multimedia framework hardware abstraction layer interface library for codec.
+
 %package devel
 Summary:    Multimedia framework hardware abstraction layer interface development package
 Group:      libdevel
@@ -68,8 +80,6 @@ Version:    %{version}
 %description -n audio-haltests
 gtest for audio HAL APIs.
 
-
-
 %package -n radio-haltests
 Summary:    gtest for radio HAL APIs
 Group:      Development/Tools
@@ -79,12 +89,21 @@ Version:    %{version}
 gtest for radio HAL APIs.
 
 
+%package -n codec-haltests
+Summary:    gtest for codec HAL APIs
+Group:      Development/Tools
+Version:    %{version}
+
+%description -n codec-haltests
+gtest for codec HAL APIs.
+
 %prep
 %setup -q
 
 %build
 export CFLAGS+=" -D_LARGEFILE64_SOURCE"
 export CFLAGS+=" -DPATH_LIBDIR=\\\"%{_libdir}\\\""
+export CFLAGS+=" -D_LARGEFILE64_SOURCE -DSYSCONFDIR=\\\"%{_sysconfdir}\\\""
 ./autogen.sh
 %configure --disable-static
 make %{?jobs:-j%jobs}
@@ -94,12 +113,15 @@ install -d -m 755 %{buildroot}%{_includedir}
 install -m 644 include/audio/*.h %{buildroot}%{_includedir}
 install -m 644 include/camera/*.h %{buildroot}%{_includedir}
 install -m 644 include/radio/*.h %{buildroot}%{_includedir}
-
 install -d -m 755 %{buildroot}%{_datadir}/testcase/res/audio/
 install -m 644 testcase/audio/*.raw %{buildroot}%{_datadir}/testcase/res/audio/
+install -d -m 755 %{buildroot}%{_datadir}/testcase/res/codec/
+install -m 644 testcase/codec/res/* %{buildroot}%{_datadir}/testcase/res/codec/
 %make_install
 
 %post -p /sbin/ldconfig
+cp -arf %{_datadir}/testcase/res/* /
+rm -rf  %{_datadir}/testcase/res/
 %postun -p /sbin/ldconfig
 
 %post -n camera-haltests -p /sbin/ldconfig
@@ -108,6 +130,9 @@ install -m 644 testcase/audio/*.raw %{buildroot}%{_datadir}/testcase/res/audio/
 %post -n radio-haltests -p /sbin/ldconfig
 %postun -n radio-haltests -p /sbin/ldconfig
 
+%post -n codec-haltests -p /sbin/ldconfig
+%postun -n codec-haltests -p /sbin/ldconfig
+
 %files camera
 %manifest mm-hal-interface-camera.manifest
 %license LICENSE.APLv2
@@ -126,6 +151,12 @@ install -m 644 testcase/audio/*.raw %{buildroot}%{_datadir}/testcase/res/audio/
 %defattr(-,root,root,-)
 %{_libdir}/libaudio*.so.*
 
+%files codec
+%manifest mm-hal-interface-codec.manifest
+%license LICENSE.APLv2
+%defattr(-,root,root,-)
+%{_libdir}/*.so.*
+
 %files devel
 %defattr(-,root,root,-)
 %{_includedir}/*.h
@@ -150,3 +181,10 @@ install -m 644 testcase/audio/*.raw %{buildroot}%{_datadir}/testcase/res/audio/
 %defattr(-,root,root,-)
 %{_bindir}/audio_*
 %{_datadir}/testcase/res/audio/*
+
+%files -n codec-haltests
+%manifest mm-haltests.manifest
+%license LICENSE.APLv2
+%defattr(-,root,root,-)
+%{_bindir}/codec_*
+%{_datadir}/testcase/res/codec/*
old mode 100644 (file)
new mode 100755 (executable)
index 4c6082d..df53b82
@@ -1,4 +1,5 @@
 SUBDIRS = camera \
-               radio \
-               audio
+          radio \
+          audio \
+          codec
 
diff --git a/src/codec/Makefile.am b/src/codec/Makefile.am
new file mode 100644 (file)
index 0000000..09bd3ea
--- /dev/null
@@ -0,0 +1,6 @@
+lib_LTLIBRARIES = libcodec_hal_interface.la
+
+libcodec_hal_interface_la_SOURCES = codec_hal_interface.c
+libcodec_hal_interface_la_CFLAGS = $(GLIB_CFLAGS) $(DLOG_CFLAGS) -I$(srcdir)/../../include/codec
+libcodec_hal_interface_la_LIBADD = $(GLIB_LIBS) $(DLOG_LIBS) -ldl
+
diff --git a/src/codec/codec_hal_interface.c b/src/codec/codec_hal_interface.c
new file mode 100644 (file)
index 0000000..a247c73
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * codec_hal_interface.c
+ *
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Sejun Park <sejun79.park@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <dlfcn.h>
+#include <glib.h>
+#include <dlog.h>
+#include "codec_hal_interface.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif /* LOG_TAG */
+#define LOG_TAG "CODEC_HAL_INTF"
+
+#define LIB_TIZEN_CODEC "libtizen-codec.so"
+
old mode 100644 (file)
new mode 100755 (executable)
index 4c6082d..91f7b0f
@@ -1,4 +1,4 @@
 SUBDIRS = camera \
-               radio \
-               audio
-
+          radio \
+          audio \
+          codec
diff --git a/testcase/codec/Makefile.am b/testcase/codec/Makefile.am
new file mode 100644 (file)
index 0000000..d82559e
--- /dev/null
@@ -0,0 +1,35 @@
+# with gtest
+bin_PROGRAMS = codec_haltests
+
+TEST_FILES_DIRECTORY = /usr/share/testcase/res
+
+codec_haltests_SOURCES = \
+       codec_haltests.cpp
+
+codec_haltests_CPPFLAGS = \
+       $(CFLAGS) \
+       $(GST_CFLAGS) \
+       $(GST_PLUGIN_BASE_CFLAGS) \
+       $(GLIB_CFLAGS) \
+       $(DLOG_CFLAGS) \
+       $(INIPARSER_CFLAGS) \
+       $(TBM_CFLAGS) \
+       $(GST_ALLOCATORS_CFLAGS) \
+       $(SYSTEM_INFO_CFLAGS) \
+       -DTEST_FILES_PATH="\"$(TEST_FILES_DIRECTORY)\"" \
+       -I$(srcdir)/../../include/codec
+
+codec_haltests_LDADD = \
+       -ldl\
+       -lgtest\
+       -lgstapp-1.0 \
+       $(top_builddir)/src/codec/libcodec_hal_interface.la\
+       $(GST_LIBS) \
+       $(GST_PLUGIN_BASE_LIBS) \
+       $(GLIB_LIBS) \
+       $(DLOG_LIBS) \
+       $(INIPARSER_LIBS) \
+       $(TBM_LIBS) \
+       $(GST_ALLOCATORS_LIBS) \
+       $(SYSTEM_INFO_LIBS)
+
diff --git a/testcase/codec/codec_haltests.cpp b/testcase/codec/codec_haltests.cpp
new file mode 100644 (file)
index 0000000..6026b2c
--- /dev/null
@@ -0,0 +1,788 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <glib.h>
+#include <string.h>
+#include <gtest/gtest.h>
+#include <gst/gst.h>
+#include <unistd.h>
+#include <iostream>
+#include <iniparser.h>
+#include <codec_hal_interface.h>
+#include <gst/app/gstappsrc.h>
+#include <gst/allocators/gsttizenmemory.h>
+#include <tbm_surface_internal.h>
+
+using namespace std;
+typedef struct _codec_list_t codec_list_t;
+#define CNAME_SIZE 512
+#define CODEC_INI_MAX_STRLEN     256
+#define DEFAULT_PORT "GST_PORT"
+#define CODEC_INI_DEFAULT_PATH   SYSCONFDIR"/multimedia/mmfw_media_codec.ini"
+
+#define CODEC_INI_GET_STRING(x_dict, x_item, x_ini, x_default) \
+do {\
+       gchar* str = iniparser_getstring(x_dict, x_ini, x_default); \
+       \
+       if (str &&  \
+                       (strlen(str) > 0) && \
+                       (strlen(str) < CODEC_INI_MAX_STRLEN)) \
+               strncpy(x_item, str, strlen(str) + 1); \
+       else \
+               strncpy(x_item, x_default, strlen(x_default) + 1); \
+} while (0)
+
+typedef enum {
+       H263,
+       H264,
+       MPEG4
+} codec_list_e;
+
+struct _codec_list_t {
+       codec_list_e ename;
+       gchar cname[CODEC_INI_MAX_STRLEN];
+       gchar plugins[2][CODEC_INI_MAX_STRLEN];
+};
+
+static codec_list_t codec_list[] = {
+       { H263, "h263", },
+       { H264, "h264", },
+       { MPEG4, "mpeg4" },
+};
+
+void get_plugins_list_from_ini(dictionary *dict, codec_list_t *codec_list, int codec_num)
+{
+       int i, j;
+       int index = 0;
+       char *token = NULL;
+       char *usr_ptr = NULL;
+       const char *delimiters = " ,";
+       size_t len;
+       gchar port_name[CNAME_SIZE];
+       gchar temp[CNAME_SIZE];
+       gchar cname[CNAME_SIZE];
+       const char *type[2];
+       type[0] = ":hw_decoder";
+       type[1] = ":hw_encoder";
+
+       CODEC_INI_GET_STRING(dict, port_name, "port_in_use:media_codec_port", DEFAULT_PORT);
+
+       if (strcmp(port_name, "GST_PORT") == 0) {
+               for (i = 0; i < 2; i++) {
+                       for (j = 0; j < codec_num; j++) {
+                               index = 0;
+
+                               snprintf(cname, CNAME_SIZE, "%s", codec_list[j].cname);
+                               len = strlen(cname);
+                               snprintf(cname + len, CNAME_SIZE - len, "%s", type[i]);
+                               CODEC_INI_GET_STRING(dict, temp, cname, "");
+                               token = strtok_r(temp, delimiters, &usr_ptr);
+
+                               while (token) {
+                                       if (token && index == 0)
+                                               strncpy(codec_list[j].plugins[i], token, strlen(token) + 1);
+                                       token = strtok_r(NULL, delimiters, &usr_ptr);
+                                       index++;
+                               }
+                       }
+               }
+       }
+}
+
+static void
+pad_added_cb(GstElement * demux, GstPad * pad, GstBin * pipeline)
+{
+  GstElement *sink, *parse, *codec;
+  GstCaps *caps;
+
+  GST_INFO_OBJECT(pad, "got pad");
+
+  caps = gst_pad_query_caps(pad, NULL);
+  gchar *caps_str = gst_caps_to_string(caps);
+
+  if (strstr(caps_str, "h264")) {
+    parse = gst_element_factory_make("h264parse", NULL);
+    codec = gst_element_factory_make(codec_list[H264].plugins[0], NULL);
+    sink = gst_element_factory_make("fakesink", NULL);
+
+    gst_bin_add_many(GST_BIN(pipeline), parse, codec, sink, NULL);
+    gst_element_link_many(demux, parse, codec, sink, NULL);
+
+    gst_element_set_state(parse, GST_STATE_PAUSED);
+    gst_element_set_state(codec, GST_STATE_PAUSED);
+    gst_element_set_state(sink, GST_STATE_PAUSED);
+  } else if (strstr(caps_str, "h263")) {
+    parse = gst_element_factory_make("h263parse", NULL);
+    codec = gst_element_factory_make(codec_list[H263].plugins[0], NULL);
+    sink = gst_element_factory_make("fakesink", NULL);
+
+    gst_bin_add_many(GST_BIN(pipeline), codec, sink, NULL);
+    gst_element_link_many(demux, codec, sink, NULL);
+
+    gst_element_set_state(parse, GST_STATE_PAUSED);
+    gst_element_set_state(codec, GST_STATE_PAUSED);
+    gst_element_set_state(sink, GST_STATE_PAUSED);
+  } else if (strstr(caps_str, "video/mpeg")) {
+    parse = gst_element_factory_make("mpeg4videoparse", NULL);
+    codec = gst_element_factory_make(codec_list[MPEG4].plugins[0], NULL);
+    sink = gst_element_factory_make("fakesink", NULL);
+
+    gst_bin_add_many(GST_BIN(pipeline), parse, codec, sink, NULL);
+    gst_element_link_many(demux, parse, codec, sink, NULL);
+
+    gst_element_set_state(parse, GST_STATE_PAUSED);
+    gst_element_set_state(codec, GST_STATE_PAUSED);
+    gst_element_set_state(sink, GST_STATE_PAUSED);
+  } else {
+    GST_WARNING_OBJECT(pad, "non video pad");
+  }
+
+  gst_caps_unref(caps);
+}
+
+static GstBusSyncReply
+error_cb(GstBus * bus, GstMessage * msg, gpointer user_data)
+{
+  if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) {
+    const gchar *file = (const gchar *)user_data;
+    GError *err = NULL;
+    gchar *dbg = NULL;
+
+    gst_message_parse_error(msg, &err, &dbg);
+    g_error("ERROR for %s: %s\n%s\n", file, err->message, dbg);
+  }
+
+  return GST_BUS_PASS;
+}
+
+gboolean bus_callback(GstBus *bus, GstMessage *msg, gpointer data)
+{
+       switch (GST_MESSAGE_TYPE(msg)) {
+       case GST_MESSAGE_EOS:
+               break;
+       case GST_MESSAGE_ERROR:
+               break;
+       default:
+               break;
+       }
+       return TRUE;
+}
+
+void buffer_add(GstElement *element, GstBuffer *buffer, GstPad *pad, gpointer data)
+{
+}
+
+/*
+ * main class
+ */
+class CodecHalTest : public testing::Test
+{
+       public:
+
+               virtual void SetUp()
+               {
+                       return;
+               }
+
+               virtual void TearDown()
+               {
+
+                       return;
+               }
+
+};
+
+/**
+ * @testcase           InitH263DecoderP
+ * @sizen_tizen                5.0
+ * @author                     SR(sejun79.park)
+ * @reviewer           SR(heechul.jeon)
+ * @type                       auto
+ * @description                Positive, Initialize H.263 Decoder Plugin
+ * @apicovered         N/A
+ * @passcase           when h263 decoder plugin exists pipeline can be changed to GST_STATE_PAUSED
+ * @failcase           when the state is not changed to GST_STATE_PAUSED
+ * @precondition       None
+ * @postcondition      None
+ */
+TEST_F(CodecHalTest, InitH263DecoderP)
+{
+       GstElement *sink, *src, *codec, *pipeline;
+       GstStateChangeReturn ret;
+
+       pipeline = gst_pipeline_new("pipeline");
+       src = gst_element_factory_make("fakesrc", NULL);
+       codec = gst_element_factory_make(codec_list[H263].plugins[0], NULL);
+       sink = gst_element_factory_make("fakesink", NULL);
+
+       gst_bin_add_many(GST_BIN(pipeline), src, codec, sink, NULL);
+
+       ret = gst_element_set_state(pipeline, GST_STATE_PAUSED);
+       EXPECT_NE(ret, GST_STATE_CHANGE_FAILURE);
+
+       gst_object_unref(pipeline);
+}
+
+/**
+ * @testcase           InitH264DecoderP
+ * @sizen_tizen                5.0
+ * @author                     SR(sejun79.park)
+ * @reviewer           SR(heechul.jeon)
+ * @type                       auto
+ * @description                Positive, Initialize H.263 Decoder Plugin
+ * @apicovered         N/A
+ * @passcase           when h264 decoder plugin exists pipeline can be changed to GST_STATE_PAUSED
+ * @failcase           when the state is not changed to GST_STATE_PAUSED
+ * @precondition       None
+ * @postcondition      None
+ */
+TEST_F(CodecHalTest, InitH264DecoderP)
+{
+       GstElement *sink, *src, *codec, *pipeline;
+       GstStateChangeReturn ret;
+
+       pipeline = gst_pipeline_new("pipeline");
+       src = gst_element_factory_make("fakesrc", NULL);
+       codec = gst_element_factory_make(codec_list[H264].plugins[0], NULL);
+       sink = gst_element_factory_make("fakesink", NULL);
+
+       gst_bin_add_many(GST_BIN(pipeline), src, codec, sink, NULL);
+
+       ret = gst_element_set_state(pipeline, GST_STATE_PAUSED);
+       EXPECT_NE(ret, GST_STATE_CHANGE_FAILURE);
+
+       gst_object_unref(pipeline);
+}
+
+/**
+ * @testcase           InitMpeg4DecoderP
+ * @sizen_tizen                5.0
+ * @author                     SR(sejun79.park)
+ * @reviewer           SR(heechul.jeon)
+ * @type                       auto
+ * @description                Positive, Initialize MPEG4 Decoder Plugin
+ * @apicovered         N/A
+ * @passcase           when MPEG4 decoder plugin exists pipeline can be changed to GST_STATE_PAUSED
+ * @failcase           when the state is not changed to GST_STATE_PAUSED
+ * @precondition       None
+ * @postcondition      None
+ */
+TEST_F(CodecHalTest, InitMpeg4DecoderP)
+{
+       GstElement *sink, *src, *codec, *pipeline;
+       GstStateChangeReturn ret;
+
+       pipeline = gst_pipeline_new("pipeline");
+       src = gst_element_factory_make("fakesrc", NULL);
+       codec = gst_element_factory_make(codec_list[MPEG4].plugins[0], NULL);
+       sink = gst_element_factory_make("fakesink", NULL);
+
+       gst_bin_add_many(GST_BIN(pipeline), src, codec, sink, NULL);
+
+       ret = gst_element_set_state(pipeline, GST_STATE_PAUSED);
+       EXPECT_NE(ret, GST_STATE_CHANGE_FAILURE);
+
+       gst_object_unref(pipeline);
+}
+
+/**
+ * @testcase           InitH263EncoderP
+ * @sizen_tizen                5.0
+ * @author                     SR(sejun79.park)
+ * @reviewer           SR(heechul.jeon)
+ * @type                       auto
+ * @description                Positive, Initialize H.263 Encoder Plugin
+ * @apicovered         N/A
+ * @passcase           when H.263 encoder plugin exists pipeline can be changed to GST_STATE_PAUSED
+ * @failcase           when the state is not changed to GST_STATE_PAUSED
+ * @precondition       None
+ * @postcondition      None
+ */
+TEST_F(CodecHalTest, InitH263EncoderP)
+{
+       GstElement *sink, *src, *codec, *pipeline;
+       GstStateChangeReturn ret;
+
+       pipeline = gst_pipeline_new("pipeline");
+       src = gst_element_factory_make("fakesrc", NULL);
+       codec = gst_element_factory_make(codec_list[H263].plugins[1], NULL);
+       sink = gst_element_factory_make("fakesink", NULL);
+
+       gst_bin_add_many(GST_BIN(pipeline), src, codec, sink, NULL);
+
+       ret = gst_element_set_state(pipeline, GST_STATE_PAUSED);
+       EXPECT_NE(ret, GST_STATE_CHANGE_FAILURE);
+
+       gst_object_unref(pipeline);
+}
+
+/**
+ * @testcase           InitH264EncoderP
+ * @sizen_tizen                5.0
+ * @author                     SR(sejun79.park)
+ * @reviewer           SR(heechul.jeon)
+ * @type                       auto
+ * @description                Positive, Initialize H.264 Encoder Plugin
+ * @apicovered         N/A
+ * @passcase           when H.264 encoder plugin exists pipeline can be changed to GST_STATE_PAUSED
+ * @failcase           when the state is not changed to GST_STATE_PAUSED
+ * @precondition       None
+ * @postcondition      None
+ */
+TEST_F(CodecHalTest, InitH264EncoderP)
+{
+       GstElement *sink, *src, *codec, *pipeline;
+       GstStateChangeReturn ret;
+
+       pipeline = gst_pipeline_new("pipeline");
+       src = gst_element_factory_make("fakesrc", NULL);
+       codec = gst_element_factory_make(codec_list[H264].plugins[1], NULL);
+       sink = gst_element_factory_make("fakesink", NULL);
+
+       gst_bin_add_many(GST_BIN(pipeline), src, codec, sink, NULL);
+
+       ret = gst_element_set_state(pipeline, GST_STATE_PAUSED);
+       EXPECT_NE(ret, GST_STATE_CHANGE_FAILURE);
+
+       gst_object_unref(pipeline);
+}
+
+/**
+ * @testcase           InitMPEG4EncoderP
+ * @sizen_tizen                5.0
+ * @author                     SR(sejun79.park)
+ * @reviewer           SR(heechul.jeon)
+ * @type                       auto
+ * @description                Positive, Initialize H.264 Encoder Plugin
+ * @apicovered         N/A
+ * @passcase           when MPEG4 encoder plugin exists pipeline can be changed to GST_STATE_PAUSED
+ * @failcase           when the state is not changed to GST_STATE_PAUSED
+ * @precondition       None
+ * @postcondition      None
+ */
+TEST_F(CodecHalTest, InitMpeg4EncoderP)
+{
+       GstElement *sink, *src, *codec, *pipeline;
+       GstStateChangeReturn ret;
+
+       pipeline = gst_pipeline_new("pipeline");
+       src = gst_element_factory_make("fakesrc", NULL);
+       codec = gst_element_factory_make(codec_list[MPEG4].plugins[1], NULL);
+       sink = gst_element_factory_make("fakesink", NULL);
+
+       gst_bin_add_many(GST_BIN(pipeline), src, codec, sink, NULL);
+
+       ret = gst_element_set_state(pipeline, GST_STATE_PAUSED);
+       EXPECT_NE(ret, GST_STATE_CHANGE_FAILURE);
+
+       gst_object_unref(pipeline);
+}
+
+/**
+ * @testcase           DecodeH264P
+ * @sizen_tizen                5.0
+ * @author                     SR(sejun79.park)
+ * @reviewer           SR(heechul.jeon)
+ * @type                       auto
+ * @description                Positive, Decode H.264 Decoder Plugin
+ * @apicovered         N/A
+ * @passcase           when h264 decoder decode stream, pipeline can be changed to GST_STATE_PLAYING
+ * @failcase           when the state is not changed to GST_STATE_PLAYING
+ * @precondition       None
+ * @postcondition      None
+ */
+TEST_F(CodecHalTest, DecodeH264P)
+{
+  GstStateChangeReturn state_ret;
+  GstElement *src, *demux, *pipeline;
+  GstMessage *msg;
+  GstBus *bus;
+  gchar *path;
+
+  pipeline = gst_pipeline_new("pipeline");
+
+  src = gst_element_factory_make("filesrc", NULL);
+
+  demux = gst_element_factory_make("qtdemux", NULL);
+
+  bus = gst_element_get_bus(pipeline);
+
+  /* kids, don't use a sync handler for this at home, really; we do because
+   * we just want to abort and nothing else */
+  gst_bus_set_sync_handler(bus, error_cb, (gpointer) "meerkat.mp4", NULL);
+
+  gst_bin_add_many(GST_BIN(pipeline), src, demux, NULL);
+
+  gst_element_link(src, demux);
+
+  path = g_build_filename(TEST_FILES_PATH, "meerkat.mp4", NULL);
+  GST_LOG("reading file '%s'", path);
+  g_object_set(src, "location", path, NULL);
+
+  /* can't link uridecodebin and sink yet, do that later */
+  g_signal_connect(demux, "pad-added", G_CALLBACK(pad_added_cb), pipeline);
+
+  state_ret = gst_element_set_state(pipeline, GST_STATE_PAUSED);
+
+  if (state_ret == GST_STATE_CHANGE_ASYNC) {
+    GST_LOG("waiting for pipeline to reach PAUSED state");
+    state_ret = gst_element_get_state(pipeline, NULL, NULL, -1);
+  }
+
+  state_ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
+  EXPECT_NE(state_ret, GST_STATE_CHANGE_FAILURE);
+
+  GST_LOG("PAUSED, let's decode");
+  msg = gst_bus_timed_pop_filtered(bus, 10 * GST_SECOND, GST_MESSAGE_EOS);
+  GST_LOG("Done, got EOS message");
+
+  gst_message_unref(msg);
+  gst_object_unref(bus);
+
+  gst_element_set_state(pipeline, GST_STATE_NULL);
+  EXPECT_EQ(state_ret, GST_STATE_CHANGE_SUCCESS);
+
+  gst_object_unref(pipeline);
+  g_free(path);
+}
+
+/**
+ * @testcase           DecodeH263P
+ * @sizen_tizen                5.0
+ * @author                     SR(sejun79.park)
+ * @reviewer           SR(heechul.jeon)
+ * @type                       auto
+ * @description                Positive, Decode H.263 Decoder Plugin
+ * @apicovered         N/A
+ * @passcase           when h263 decoder decode stream, pipeline can be changed to GST_STATE_PLAYING
+ * @failcase           when the state is not changed to GST_STATE_PLAYING
+ * @precondition       None
+ * @postcondition      None
+ */
+TEST_F(CodecHalTest, DecodeH263P)
+{
+  GstStateChangeReturn state_ret;
+  GstElement *src, *demux, *pipeline;
+  GstMessage *msg;
+  GstBus *bus;
+  gchar *path;
+
+  pipeline = gst_pipeline_new("pipeline");
+
+  src = gst_element_factory_make("filesrc", NULL);
+
+  demux = gst_element_factory_make("qtdemux", NULL);
+
+  bus = gst_element_get_bus(pipeline);
+
+  /* kids, don't use a sync handler for this at home, really; we do because
+   * we just want to abort and nothing else */
+  gst_bus_set_sync_handler(bus, error_cb, (gpointer)"she.3gp", NULL);
+
+  gst_bin_add_many(GST_BIN(pipeline), src, demux, NULL);
+
+  gst_element_link(src, demux);
+
+  path = g_build_filename(TEST_FILES_PATH, "she.3gp", NULL);
+  GST_LOG("reading file '%s'", path);
+  g_object_set(src, "location", path, NULL);
+
+  /* can't link uridecodebin and sink yet, do that later */
+  g_signal_connect(demux, "pad-added", G_CALLBACK(pad_added_cb), pipeline);
+
+  state_ret = gst_element_set_state(pipeline, GST_STATE_PAUSED);
+
+  if (state_ret == GST_STATE_CHANGE_ASYNC) {
+    GST_LOG("waiting for pipeline to reach PAUSED state");
+    state_ret = gst_element_get_state(pipeline, NULL, NULL, -1);
+  }
+
+  state_ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
+  EXPECT_NE(state_ret, GST_STATE_CHANGE_FAILURE);
+
+  GST_LOG("PAUSED, let's decode");
+  msg = gst_bus_timed_pop_filtered(bus, 10 * GST_SECOND, GST_MESSAGE_EOS);
+  GST_LOG("Done, got EOS message");
+
+  gst_message_unref(msg);
+  gst_object_unref(bus);
+
+  state_ret = gst_element_set_state(pipeline, GST_STATE_NULL);
+  EXPECT_EQ(state_ret, GST_STATE_CHANGE_SUCCESS);
+  gst_object_unref(pipeline);
+
+  g_free(path);
+}
+
+/**
+ * @testcase           DecodeMPEG4P
+ * @sizen_tizen                5.0
+ * @author                     SR(sejun79.park)
+ * @reviewer           SR(heechul.jeon)
+ * @type                       auto
+ * @description                Positive, Decode MPEG4 Decoder Plugin
+ * @apicovered         N/A
+ * @passcase           when MPEG4 decoder decode stream, pipeline can be changed to GST_STATE_PLAYING
+ * @failcase           when the state is not changed to GST_STATE_PLAYING
+ * @precondition       None
+ * @postcondition      None
+ */
+TEST_F(CodecHalTest, DecodeMPEG4P)
+{
+  GstStateChangeReturn state_ret;
+  GstElement *src, *demux, *pipeline;
+  GstMessage *msg;
+  GstBus *bus;
+  gchar *path;
+
+  pipeline = gst_pipeline_new("pipeline");
+
+  src = gst_element_factory_make("filesrc", NULL);
+
+  demux = gst_element_factory_make("qtdemux", NULL);
+
+  bus = gst_element_get_bus(pipeline);
+
+  /* kids, don't use a sync handler for this at home, really; we do because
+   * we just want to abort and nothing else */
+  gst_bus_set_sync_handler(bus, error_cb, (gpointer)"mv.MP4", NULL);
+
+  gst_bin_add_many(GST_BIN(pipeline), src, demux, NULL);
+
+  gst_element_link(src, demux);
+
+  path = g_build_filename(TEST_FILES_PATH, "mv.MP4", NULL);
+  GST_LOG("reading file '%s'", path);
+  g_object_set(src, "location", path, NULL);
+
+  /* can't link uridecodebin and sink yet, do that later */
+  g_signal_connect(demux, "pad-added", G_CALLBACK(pad_added_cb), pipeline);
+
+  state_ret = gst_element_set_state(pipeline, GST_STATE_PAUSED);
+
+  if (state_ret == GST_STATE_CHANGE_ASYNC) {
+    GST_LOG("waiting for pipeline to reach PAUSED state");
+    state_ret = gst_element_get_state(pipeline, NULL, NULL, -1);
+  }
+
+  state_ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
+  EXPECT_NE(state_ret, GST_STATE_CHANGE_FAILURE);
+
+  GST_LOG("PAUSED, let's decode");
+  msg = gst_bus_timed_pop_filtered(bus, 10 * GST_SECOND, GST_MESSAGE_EOS);
+  GST_LOG("Done, got EOS message");
+
+  gst_message_unref(msg);
+  gst_object_unref(bus);
+
+  state_ret = gst_element_set_state(pipeline, GST_STATE_NULL);
+  EXPECT_EQ(state_ret, GST_STATE_CHANGE_SUCCESS);
+  gst_object_unref(pipeline);
+
+  g_free(path);
+}
+
+#if 0
+/**
+ * @testcase           EncodeH264P
+ * @sizen_tizen                5.0
+ * @author                     SR(sejun79.park)
+ * @reviewer           SR(heechul.jeon)
+ * @type                       auto
+ * @description                Positive, Encode H.264 Decoder Plugin
+ * @apicovered         N/A
+ * @passcase           when H.264 encoder encode buffer, outbuffer will be dequed
+ * @failcase           when the state is not changed to GST_STATE_PLAYING or the error occur
+ * @precondition       None
+ * @postcondition      None
+ */
+TEST_F(CodecHalTest, EncodeH264P)
+{
+  GstStateChangeReturn state_ret;
+  GstElement *sink, *src, *codec, *pipeline;
+  GstMessage *msg;
+  GstBus *bus;
+  gchar *path;
+  gint bus_watch_id;
+  gulong signal_handoff;
+  GstBuffer *buffer;
+  GstAllocator *allocator;
+  GstMemory *mem;
+  GstVideoInfo vinfo;
+  tbm_surface_h surface;
+  int i;
+  int ret;
+
+  pipeline = gst_pipeline_new("pipeline");
+
+  src = gst_element_factory_make("appsrc", NULL);
+
+  codec = gst_element_factory_make(codec_list[H264].plugins[1], NULL);
+
+  bus = gst_element_get_bus(pipeline);
+  bus_watch_id = gst_bus_add_watch(bus, bus_callback, NULL);
+  gst_bin_add_many(GST_BIN(pipeline), src, codec, sink, NULL);
+  gst_element_link_many(src, codec, sink, NULL);
+
+  signal_handoff = g_signal_connect(sink, "handoff", G_CALLBACK(buffer_add), NULL);
+  state_ret = gst_element_set_state(pipeline, GST_STATE_PAUSED);
+
+  if (state_ret == GST_STATE_CHANGE_ASYNC) {
+    GST_LOG("waiting for pipeline to reach PAUSED state");
+    state_ret = gst_element_get_state(pipeline, NULL, NULL, -1);
+  }
+
+  state_ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
+  EXPECT_NE(state_ret, GST_STATE_CHANGE_FAILURE);
+
+  allocator = gst_tizen_allocator_new();
+
+  for (i = 0; i < 5; i++) {
+    surface = tbm_surface_internal_create_with_flags(640, 480, TBM_FORMAT_NV12, TBM_BO_NONCACHABLE);
+    mem = gst_tizen_allocator_alloc_surface(allocator, &vinfo, surface, NULL, NULL);
+       gst_buffer_append_memory(buffer, mem);
+       ret = gst_app_src_push_buffer((GstAppSrc*)src, buffer);
+  }
+
+  g_signal_handler_disconnect(sink, signal_handoff);
+  gst_object_unref(bus);
+
+  state_ret = gst_element_set_state(pipeline, GST_STATE_NULL);
+  EXPECT_EQ(state_ret, GST_STATE_CHANGE_SUCCESS);
+
+  gst_object_unref(pipeline);
+}
+
+/**
+ * @testcase           EncodeH263P
+ * @sizen_tizen                5.0
+ * @author                     SR(sejun79.park)
+ * @reviewer           SR(heechul.jeon)
+ * @type                       auto
+ * @description                Positive, Encode H.263 Decoder Plugin
+ * @apicovered         N/A
+ * @passcase           when H.263 encoder encode buffer, outbuffer will be dequed
+ * @failcase           when the state is not changed to GST_STATE_PLAYING or the error occur
+ * @precondition       None
+ * @postcondition      None
+ */
+TEST_F(CodecHalTest, EncodeH263P)
+{
+  GstStateChangeReturn state_ret;
+  GstElement *sink, *src, *codec, *pipeline;
+  GstMessage *msg;
+  GstBus *bus;
+  gchar *path;
+  gint bus_watch_id;
+
+  pipeline = gst_pipeline_new("pipeline");
+
+  src = gst_element_factory_make("appsrc", NULL);
+
+  codec = gst_element_factory_make(codec_list[H263].plugins[1], NULL);
+
+  bus = gst_element_get_bus(pipeline);
+  bus_watch_id = gst_bus_add_watch(bus, bus_callback, NULL);
+  gst_bin_add_many(GST_BIN(pipeline), src, codec, sink, NULL);
+  gst_element_link_many(src, codec, sink, NULL);
+
+  state_ret = gst_element_set_state(pipeline, GST_STATE_PAUSED);
+
+  if (state_ret == GST_STATE_CHANGE_ASYNC) {
+    GST_LOG("waiting for pipeline to reach PAUSED state");
+    state_ret = gst_element_get_state(pipeline, NULL, NULL, -1);
+  }
+
+  state_ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
+  EXPECT_NE(state_ret, GST_STATE_CHANGE_FAILURE);
+
+  GST_LOG("PAUSED, let's encode");
+  gst_object_unref(bus);
+
+  state_ret = gst_element_set_state(pipeline, GST_STATE_NULL);
+  EXPECT_EQ(state_ret, GST_STATE_CHANGE_SUCCESS);
+  gst_object_unref(pipeline);
+}
+
+/**
+ * @testcase           EncodeMPEG4P
+ * @sizen_tizen                5.0
+ * @author                     SR(sejun79.park)
+ * @reviewer           SR(heechul.jeon)
+ * @type                       auto
+ * @description                Positive, Encode MPEG4 Decoder Plugin
+ * @apicovered         N/A
+ * @passcase           when MPEG4 encoder encode buffer, outbuffer will be dequed
+ * @failcase           when the state is not changed to GST_STATE_PLAYING or the error occur
+ * @precondition       None
+ * @postcondition      None
+ */
+TEST_F(CodecHalTest, EncodeMPEG4P)
+{
+  GstStateChangeReturn state_ret;
+  GstElement *sink, *src, *codec, *pipeline;
+  GstMessage *msg;
+  GstBus *bus;
+  gchar *path;
+  gint bus_watch_id;
+
+  pipeline = gst_pipeline_new("pipeline");
+
+  src = gst_element_factory_make("appsrc", NULL);
+
+  codec = gst_element_factory_make(codec_list[MPEG4].plugins[1], NULL);
+
+  bus = gst_element_get_bus(pipeline);
+  bus_watch_id = gst_bus_add_watch(bus, bus_callback, NULL);
+  gst_bin_add_many(GST_BIN(pipeline), src, codec, sink, NULL);
+  gst_element_link_many(src, codec, sink, NULL);
+
+  state_ret = gst_element_set_state(pipeline, GST_STATE_PAUSED);
+
+  if (state_ret == GST_STATE_CHANGE_ASYNC) {
+    GST_LOG("waiting for pipeline to reach PAUSED state");
+    state_ret = gst_element_get_state(pipeline, NULL, NULL, -1);
+  }
+
+  state_ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
+  EXPECT_NE(state_ret, GST_STATE_CHANGE_FAILURE);
+
+  GST_LOG("PAUSED, let's encode");
+  gst_object_unref(bus);
+
+  state_ret = gst_element_set_state(pipeline, GST_STATE_NULL);
+  EXPECT_EQ(state_ret, GST_STATE_CHANGE_SUCCESS);
+  gst_object_unref(pipeline);
+}
+#endif
+
+int main(int argc, char **argv)
+{
+       int codec_num;
+       dictionary *dict;
+
+       gst_init(&argc, &argv);
+       dict = iniparser_load(CODEC_INI_DEFAULT_PATH);
+
+       codec_num = sizeof(codec_list) / sizeof(codec_list[0]);
+       get_plugins_list_from_ini(dict, codec_list, codec_num);
+       iniparser_freedict(dict);
+       testing::InitGoogleTest(&argc, argv);
+
+       return RUN_ALL_TESTS();
+}
diff --git a/testcase/codec/res/meerkat.mp4 b/testcase/codec/res/meerkat.mp4
new file mode 100755 (executable)
index 0000000..69270dc
Binary files /dev/null and b/testcase/codec/res/meerkat.mp4 differ
diff --git a/testcase/codec/res/mv.MP4 b/testcase/codec/res/mv.MP4
new file mode 100755 (executable)
index 0000000..15b0e54
Binary files /dev/null and b/testcase/codec/res/mv.MP4 differ
diff --git a/testcase/codec/res/she.3gp b/testcase/codec/res/she.3gp
new file mode 100755 (executable)
index 0000000..419d465
Binary files /dev/null and b/testcase/codec/res/she.3gp differ