--- /dev/null
+/*
+ * 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();
+}