modality_vision/video_helper : add video_helper directory for helping video load... 86/265186/1
authordyamy-lee <dyamy.lee@samsung.com>
Sun, 10 Oct 2021 05:32:23 +0000 (14:32 +0900)
committerSung-Jin Park <sj76.park@samsung.com>
Tue, 12 Oct 2021 14:33:08 +0000 (23:33 +0900)
Change-Id: Ie4e4ec71e70aadfbb82fb5a9546e1484b08e9179

src/modules/modality_vision/video_helper/meson.build [new file with mode: 0644]
src/modules/modality_vision/video_helper/mv_log_cfg.h [new file with mode: 0644]
src/modules/modality_vision/video_helper/mv_video_helper.c [new file with mode: 0644]
src/modules/modality_vision/video_helper/mv_video_helper.h [new file with mode: 0644]

diff --git a/src/modules/modality_vision/video_helper/meson.build b/src/modules/modality_vision/video_helper/meson.build
new file mode 100644 (file)
index 0000000..41cf816
--- /dev/null
@@ -0,0 +1,34 @@
+video_helper_srcs = [
+       'mv_video_helper.c',
+]
+
+video_helper_include_dirs = include_directories('.')
+
+media_vision_dep = dependency('capi-media-vision', method : 'pkg-config')
+gstreamer_dep = dependency('gstreamer-1.0', method : 'pkg-config')
+gstreamer_app_dep = dependency('gstreamer-app-1.0', method : 'pkg-config')
+gstreamer_video_dep = dependency('gstreamer-video-1.0', method : 'pkg-config')
+
+video_helper_deps = [
+       dlog_dep,
+       media_vision_dep,
+       gstreamer_dep,
+       gstreamer_app_dep,
+       gstreamer_video_dep
+]
+
+lib_video_helper = static_library(
+       'video_helper',
+       video_helper_srcs,
+       include_directories : [video_helper_include_dirs],
+       dependencies : [video_helper_deps, image_helper_declared_dep],
+       install_dir : mmi_manager_prefix_libdir,
+       install : false,
+       #pie : true
+)
+
+video_helper_declared_dep = declare_dependency(
+       link_with : lib_video_helper,
+       dependencies : [video_helper_deps],
+       include_directories : [video_helper_include_dirs]
+)
\ No newline at end of file
diff --git a/src/modules/modality_vision/video_helper/mv_log_cfg.h b/src/modules/modality_vision/video_helper/mv_log_cfg.h
new file mode 100644 (file)
index 0000000..424aad4
--- /dev/null
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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.
+ */
+
+#ifndef __MEDIA_VISION_MV_LOG_CFG_H__
+#define __MEDIA_VISION_MV_LOG_CFG_H__
+
+#include <dlog.h>
+
+/* #define ROOTSTRAP_OUT // enables logs to console */
+#define ROOTSTRAP_OUT
+#define TEXT_RED     "\x1b[31m"
+#define TEXT_GREEN   "\x1b[32m"
+#define TEXT_YELLOW  "\x1b[33m"
+#define TEXT_BLUE    "\x1b[34m"
+#define TEXT_MAGENTA "\x1b[35m"
+#define TEXT_CYAN    "\x1b[36m"
+#define TEXT_RESET   "\x1b[0m"
+
+#ifdef ROOTSTRAP_OUT
+
+#define LOGD(...)                                 \
+do {                                              \
+       printf("<%s:%d>", __FUNCTION__, __LINE__);    \
+       printf(TEXT_CYAN);                            \
+       printf(__VA_ARGS__);                          \
+       printf(TEXT_RESET "\n");                      \
+} while (0)
+
+#define LOGI(...)                                 \
+do  {                                             \
+       printf("<%s:%d>", __FUNCTION__, __LINE__);    \
+       printf(TEXT_GREEN);                           \
+       printf(__VA_ARGS__);                          \
+       printf(TEXT_RESET "\n");                      \
+} while (0)
+
+#define LOGW(...)                                 \
+do {                                              \
+       printf("<%s:%d>", __FUNCTION__, __LINE__);    \
+       printf(TEXT_YELLOW);                          \
+       printf(__VA_ARGS__);                          \
+       printf(TEXT_RESET "\n");                      \
+} while (0)
+
+#define LOGE(...)                                 \
+do {                                              \
+       printf("<%s:%d>", __FUNCTION__, __LINE__);    \
+       printf(TEXT_RED);                             \
+       printf(__VA_ARGS__);                          \
+       printf(TEXT_RESET "\n");                      \
+} while (0)
+
+#endif
+
+#endif /* __MEDIA_VISON_MV_LOG_CFG_H__ */
diff --git a/src/modules/modality_vision/video_helper/mv_video_helper.c b/src/modules/modality_vision/video_helper/mv_video_helper.c
new file mode 100644 (file)
index 0000000..37e9975
--- /dev/null
@@ -0,0 +1,600 @@
+/**
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <mv_common.h>
+#include "mv_video_helper.h"
+#include "mv_log_cfg.h"
+
+#include <gst/gst.h>
+#include <gst/app/gstappsink.h>
+#include <gst/app/gstappsrc.h>
+#include <gst/video/video.h>
+
+#include <pthread.h>
+
+typedef struct _mv_video_reader_s {
+       /* Main bin */
+       GstElement *pl;
+
+       /* Pipeline structure */
+       GstElement *filesrc;
+       GstElement *decodebin;
+       GstElement *videoconvert;
+       GstElement *queue;
+       GstElement *appsink;
+       GstElement *videorate;
+
+       void *new_sample_cb_user_data;
+       void *eos_cb_user_data;
+
+       GstCaps *caps;
+       gulong pad_probe_id;
+
+       pthread_spinlock_t new_sample_cb_guard;
+       pthread_spinlock_t eos_cb_guard;
+
+       mv_video_reader_new_sample_cb new_sample_cb;
+       mv_video_reader_eos_cb eos_cb;
+} mv_video_reader_s;
+
+/* video reader internal funcitons */
+static int _mv_video_reader_create_internals(mv_video_reader_s *reader);
+static int _mv_video_reader_link_internals(mv_video_reader_s *reader);
+static int _mv_video_reader_state_change(mv_video_reader_s *reader, GstState state);
+
+static void appsink_eos(GstAppSink *appsink, gpointer user_data);
+static void cb_newpad(GstElement *decodebin, GstPad *new_pad, gpointer user_data);
+static GstFlowReturn appsink_newsample(GstAppSink *appsink, gpointer user_data);
+
+static GstPadProbeReturn pad_probe_data_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data);
+
+/* Internal functions */
+static int _mv_video_reader_create_internals(
+               mv_video_reader_s *reader)
+{
+       pthread_spin_init(&(reader->new_sample_cb_guard), PTHREAD_PROCESS_SHARED);
+       pthread_spin_init(&(reader->eos_cb_guard), PTHREAD_PROCESS_SHARED);
+
+       reader->pl = gst_pipeline_new(NULL);
+
+       reader->filesrc = gst_element_factory_make("filesrc", "filesrc");
+       reader->decodebin = gst_element_factory_make("decodebin3", "decoder");
+       reader->videoconvert = gst_element_factory_make("videoconvert", "convert");
+       reader->videorate = gst_element_factory_make("videorate", "videorate");
+       reader->queue = gst_element_factory_make("queue", "queue");
+       reader->appsink = gst_element_factory_make("appsink", "appsink");
+
+       if ((!reader->pl) ||
+                       (!reader->filesrc) ||
+                       (!reader->decodebin) ||
+                       (!reader->videoconvert) ||
+                       (!reader->videorate) ||
+                       (!reader->queue) ||
+                       (!reader->appsink)) {
+               LOGE("Unable to create video read pipeline elements");
+               return MEDIA_VISION_ERROR_INVALID_OPERATION;
+       }
+
+       gst_bin_add_many(GST_BIN(reader->pl),
+                       reader->filesrc,
+                       reader->decodebin,
+                       reader->videoconvert,
+                       reader->videorate,
+                       reader->queue,
+                       reader->appsink,
+                       NULL);
+
+       return MEDIA_VISION_ERROR_NONE;
+}
+
+static int _mv_video_reader_link_internals(
+               mv_video_reader_s *reader)
+{
+       GstCaps *caps = NULL;
+       GstPad *pad = NULL;
+
+       if (!gst_element_link_many(reader->filesrc,
+                               reader->decodebin,
+                               NULL)) {
+               LOGE("Unable to link filesrc to decodebin");
+               return MEDIA_VISION_ERROR_INVALID_OPERATION;
+       }
+
+       g_object_set(G_OBJECT(reader->decodebin), "force-sw-decoders-for-video", true, NULL);
+
+       /* Decodebin pad will be linked during state change */
+       g_signal_connect(reader->decodebin,
+                       "pad-added",
+                       G_CALLBACK(cb_newpad),
+                       reader);
+
+       if (!gst_element_link_many(reader->videoconvert, reader->videorate,
+                       reader->queue, reader->appsink, NULL)) {
+
+               LOGE("Unable to link videocovnert-queue-appsink");
+               return MEDIA_VISION_ERROR_INVALID_OPERATION;
+       }
+
+       caps = gst_caps_new_simple("video/x-raw",
+                       "format", G_TYPE_STRING, "RGB",
+                       "framerate", GST_TYPE_FRACTION, 10 ,3,
+                       NULL);
+
+       gst_app_sink_set_caps(GST_APP_SINK(reader->appsink), caps);
+       gst_caps_unref(caps);
+
+       /* Configure appsink */
+       gst_app_sink_set_emit_signals(GST_APP_SINK(reader->appsink), TRUE);
+       g_signal_connect(reader->appsink,
+                       "new-sample",
+                       G_CALLBACK(appsink_newsample),
+                       reader);
+       g_signal_connect(reader->appsink,
+                       "eos",
+                       G_CALLBACK(appsink_eos),
+                       reader);
+       g_object_set(G_OBJECT(reader->appsink),
+                       "drop", TRUE,
+                       "enable-last-sample", TRUE,
+                       "sync", FALSE,
+                       NULL);
+
+       /* pad probe */
+       pad = gst_element_get_static_pad(reader->queue, "src");
+
+       gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER,
+                       (GstPadProbeCallback)pad_probe_data_cb, reader, NULL);
+       gst_object_unref(pad);
+
+       return MEDIA_VISION_ERROR_NONE;
+}
+
+/* video reader */
+int mv_create_video_reader(
+               mv_video_reader_h *reader)
+{
+       mv_video_reader_s *handle = NULL;
+       int err = MEDIA_VISION_ERROR_NONE;
+
+       if (reader == NULL) {
+               LOGE("NULL pointer passed");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       gst_init(NULL, NULL);
+
+       handle = (mv_video_reader_s *) malloc(sizeof(mv_video_reader_s));
+       if (!handle) {
+               LOGE("Not enough memory");
+               return MEDIA_VISION_ERROR_INVALID_OPERATION;
+       }
+       memset(handle, 0, sizeof(mv_video_reader_s));
+
+       err = _mv_video_reader_create_internals(handle);
+       if (MEDIA_VISION_ERROR_NONE != err) {
+               LOGE("Failed to create internals");
+               free(handle);
+               return err;
+       }
+
+       err = _mv_video_reader_link_internals(handle);
+       if (MEDIA_VISION_ERROR_NONE != err) {
+               LOGE("Failed to link internals");
+               free(handle);
+               return err;
+       }
+
+       *reader = (mv_video_reader_h *) handle;
+
+       return err;
+}
+
+int mv_destroy_video_reader(
+               mv_video_reader_h reader)
+{
+       mv_video_reader_s *handle = NULL;
+
+       if (reader == NULL) {
+               LOGE("NULL pointer passed");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       handle = (mv_video_reader_s *) reader;
+
+       if (handle->caps && GST_OBJECT_REFCOUNT(handle->caps))
+               gst_caps_unref(handle->caps);
+
+       if (handle->pl)
+               gst_object_unref(handle->pl);
+
+       handle->pl = NULL;
+
+       pthread_spin_destroy(&(handle->new_sample_cb_guard));
+       pthread_spin_destroy(&(handle->eos_cb_guard));
+
+       LOGD("video reader destroyed %p", handle);
+
+       free(handle);
+
+       return MEDIA_VISION_ERROR_NONE;
+}
+
+int mv_video_reader_set_eos_cb(
+               mv_video_reader_h reader,
+               mv_video_reader_eos_cb callback,
+               void *user_data)
+{
+       mv_video_reader_s *handle = NULL;
+
+       if (reader == NULL || callback == NULL) {
+               LOGE("NULL pointer passed");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       handle = (mv_video_reader_s *) reader;
+
+       pthread_spin_lock(&(handle->eos_cb_guard));
+       handle->eos_cb = callback;
+       handle->eos_cb_user_data = user_data;
+       pthread_spin_unlock(&(handle->eos_cb_guard));
+
+       return MEDIA_VISION_ERROR_NONE;
+}
+
+int mv_video_reader_load(
+               mv_video_reader_h reader,
+               const char *path,
+               image_data_s *image_data,
+               unsigned int *fps)
+{
+       mv_video_reader_s *handle = NULL;
+       GstVideoInfo info;
+
+       if (reader == NULL || path == NULL ||
+                       image_data == NULL || fps == NULL) {
+               LOGE("NULL pointer passed");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       handle = (mv_video_reader_s *) reader;
+
+       /* Set input file location from path */
+       g_object_set(G_OBJECT(handle->filesrc),
+                       "location", path,
+                       NULL);
+
+       /* Start playback */
+       if (_mv_video_reader_state_change(handle, GST_STATE_PLAYING)) {
+               LOGE("Unable to change state");
+               return MEDIA_VISION_ERROR_INVALID_OPERATION;
+       }
+
+       if (_mv_video_reader_state_change(handle, GST_STATE_PAUSED)) {
+               LOGE("Unable to change state");
+               return MEDIA_VISION_ERROR_INVALID_OPERATION;
+       }
+
+       if (handle->caps == NULL) {
+               LOGE("Unable to get caps from decodebin");
+               return MEDIA_VISION_ERROR_INVALID_OPERATION;
+       }
+
+       gst_video_info_from_caps(&info, handle->caps);
+
+       gst_caps_unref(handle->caps);
+
+       *fps = info.fps_n/info.fps_d;
+
+       /* Fill image data */
+       image_data->image_width = info.width;
+       image_data->image_height = info.height;
+
+       switch (GST_VIDEO_FORMAT_INFO_FORMAT(info.finfo)) {
+       case GST_VIDEO_FORMAT_GRAY8:
+               image_data->image_colorspace = MEDIA_VISION_COLORSPACE_Y800;
+               break;
+       case GST_VIDEO_FORMAT_I420:
+               image_data->image_colorspace = MEDIA_VISION_COLORSPACE_I420;
+               break;
+       case GST_VIDEO_FORMAT_NV12:
+               image_data->image_colorspace = MEDIA_VISION_COLORSPACE_NV12;
+               break;
+       case GST_VIDEO_FORMAT_YV12:
+               image_data->image_colorspace = MEDIA_VISION_COLORSPACE_YV12;
+               break;
+       case GST_VIDEO_FORMAT_NV21:
+               image_data->image_colorspace = MEDIA_VISION_COLORSPACE_NV21;
+               break;
+       case GST_VIDEO_FORMAT_YUY2:
+               image_data->image_colorspace = MEDIA_VISION_COLORSPACE_YUYV;
+               break;
+       case GST_VIDEO_FORMAT_UYVY:
+               image_data->image_colorspace = MEDIA_VISION_COLORSPACE_UYVY;
+               break;
+       case GST_VIDEO_FORMAT_RGB:
+               image_data->image_colorspace = MEDIA_VISION_COLORSPACE_RGB888;
+               break;
+       case GST_VIDEO_FORMAT_RGBA:
+               image_data->image_colorspace = MEDIA_VISION_COLORSPACE_RGBA;
+               break;
+       default:
+               LOGE("Video pixel format is not supported\n");
+               return MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT;
+       }
+       return MEDIA_VISION_ERROR_NONE;
+}
+
+static int _mv_video_reader_state_change(
+               mv_video_reader_s *reader,
+               GstState state)
+{
+       LOGE("_mv_video_reader_state_change");
+       mv_video_reader_s *handle = (mv_video_reader_s *) reader;
+       GstStateChangeReturn state_ret = GST_STATE_CHANGE_FAILURE;
+       GstState pipeline_state = GST_STATE_NULL;
+
+       state_ret = gst_element_set_state(handle->pl,
+                       state);
+
+       if (GST_STATE_CHANGE_FAILURE == state_ret) {
+               LOGE("Set state failure");
+               return MEDIA_VISION_ERROR_INVALID_OPERATION;
+       }
+
+       LOGI("Set state [%d], change return [%d]",
+                       state, state_ret);
+
+       state_ret = gst_element_get_state(handle->pl,
+                       &pipeline_state,
+                       NULL,
+                       GST_CLOCK_TIME_NONE);
+
+       if (GST_STATE_CHANGE_FAILURE == state_ret) {
+               LOGE("get state failure");
+               return MEDIA_VISION_ERROR_INVALID_OPERATION;
+       }
+
+       return MEDIA_VISION_ERROR_NONE;
+       LOGE("_mv_video_reader_state_change end");
+}
+
+/* Callbacks */
+static GstFlowReturn appsink_newsample(
+               GstAppSink *appsink,
+               gpointer user_data)
+{
+       mv_video_reader_s *handle = NULL;
+       GstSample *sample = gst_app_sink_pull_sample(appsink);
+
+       if (user_data == NULL) {
+               LOGE("NULL pointer passed");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       if (sample != NULL) {
+               handle = (mv_video_reader_s *) user_data;
+               GstVideoInfo vinfo;
+               GstMapInfo info = GST_MAP_INFO_INIT;
+               GstBuffer *buf = gst_sample_get_buffer(sample);
+               GstCaps *caps = gst_sample_get_caps(sample);
+               image_data_s im_data;
+               char *buffer = NULL;
+
+               LOGD("Received sample from appsink");
+
+               /* map buffer */
+               gst_buffer_map(buf, &info, GST_MAP_READ);
+               buffer = (char *) info.data;
+
+
+               /* Fill image data */
+               gst_video_info_from_caps(&vinfo, caps);
+               im_data.image_width = vinfo.width;
+               im_data.image_height = vinfo.height;
+
+               switch (GST_VIDEO_FORMAT_INFO_FORMAT(vinfo.finfo)) {
+               case GST_VIDEO_FORMAT_GRAY8:
+                       im_data.image_colorspace = MEDIA_VISION_COLORSPACE_Y800;
+                       break;
+               case GST_VIDEO_FORMAT_I420:
+                       im_data.image_colorspace = MEDIA_VISION_COLORSPACE_I420;
+                       break;
+               case GST_VIDEO_FORMAT_NV12:
+                       im_data.image_colorspace = MEDIA_VISION_COLORSPACE_NV12;
+                       break;
+               case GST_VIDEO_FORMAT_YV12:
+                       im_data.image_colorspace = MEDIA_VISION_COLORSPACE_YV12;
+                       break;
+               case GST_VIDEO_FORMAT_NV21:
+                       im_data.image_colorspace = MEDIA_VISION_COLORSPACE_NV21;
+                       break;
+               case GST_VIDEO_FORMAT_YUY2:
+                       im_data.image_colorspace = MEDIA_VISION_COLORSPACE_YUYV;
+                       break;
+               case GST_VIDEO_FORMAT_UYVY:
+                       im_data.image_colorspace = MEDIA_VISION_COLORSPACE_UYVY;
+                       break;
+               case GST_VIDEO_FORMAT_RGB:
+                       im_data.image_colorspace = MEDIA_VISION_COLORSPACE_RGB888;
+                       break;
+               case GST_VIDEO_FORMAT_RGBA:
+                       im_data.image_colorspace = MEDIA_VISION_COLORSPACE_RGBA;
+                       break;
+               default:
+                       LOGE("Video pixel format is not supported\n");
+                       gst_buffer_unmap(buf, &info);
+                       gst_sample_unref(sample);
+                       return GST_FLOW_ERROR;
+               }
+
+               pthread_spin_lock(&(handle->new_sample_cb_guard));
+               LOGE("call new_sample_cb in appsink");
+               if (handle->new_sample_cb != NULL) {
+                       handle->new_sample_cb(
+                               buffer,
+                               info.size,
+                               im_data,
+                               handle->new_sample_cb_user_data);
+               }
+               pthread_spin_unlock(&(handle->new_sample_cb_guard));
+
+               gst_buffer_unmap(buf, &info);
+               gst_sample_unref(sample);
+       } else {
+               LOGE("Failed to pull sample from appsink");
+               return GST_FLOW_ERROR;
+       }
+
+       return GST_FLOW_OK;
+}
+
+int mv_video_reader_start(
+               mv_video_reader_h reader)
+{
+       mv_video_reader_s *handle = NULL;
+
+       if (reader == NULL) {
+               LOGE("NULL pointer passed");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       handle = (mv_video_reader_s *) reader;
+
+       /* Start playback */
+       if (_mv_video_reader_state_change(handle, GST_STATE_PLAYING)) {
+               LOGE("Unable to change state");
+               return MEDIA_VISION_ERROR_INVALID_OPERATION;
+       }
+
+       return MEDIA_VISION_ERROR_NONE;
+}
+
+int mv_video_reader_stop(
+               mv_video_reader_h reader)
+{
+       mv_video_reader_s *handle = NULL;
+       LOGE("mv_video_reader_stop");
+
+       if (reader == NULL) {
+               LOGE("NULL pointer passed");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       handle = (mv_video_reader_s *) reader;
+
+       /* Stop playback (NULL or READY) */
+       if (_mv_video_reader_state_change(handle, GST_STATE_PAUSED)) {
+               LOGE("Unable to change state");
+               return MEDIA_VISION_ERROR_INVALID_OPERATION;
+       }
+
+       LOGE("mv_video_reader_stop end");
+       //mv_destroy_video_reader(reader);
+       return MEDIA_VISION_ERROR_NONE;
+}
+
+static void appsink_eos(
+               GstAppSink *appsink,
+               gpointer user_data)
+{
+       if (user_data == NULL) {
+               LOGE("NULL pointer passed");
+               return;
+       }
+       mv_video_reader_s *handle = (mv_video_reader_s *) user_data;
+       mv_video_reader_h *reader = (mv_video_reader_h *) user_data;
+
+       /* EOS callback to terminate reading */
+       pthread_spin_lock(&(handle->eos_cb_guard));
+       if (handle->eos_cb != NULL){
+               handle->eos_cb(reader, handle->eos_cb_user_data);
+       }
+
+       pthread_spin_unlock(&(handle->eos_cb_guard));
+
+       gst_pad_remove_probe(gst_element_get_static_pad(handle->queue, "src"), handle->pad_probe_id);
+}
+
+static void cb_newpad(
+               GstElement *decodebin,
+               GstPad *pad,
+               gpointer user_data)
+{
+       mv_video_reader_s *reader = (mv_video_reader_s *) user_data;
+       GstStructure *str = NULL;
+       GstCaps *caps = NULL;
+       GstPad *video_pad = NULL;
+
+       LOGI("Received pad from decodebin. Linking");
+       video_pad = gst_element_get_static_pad(reader->videoconvert, "sink");
+       if (GST_PAD_IS_LINKED(video_pad)) {
+               LOGI("Already linked");
+               g_object_unref(video_pad);
+               return;
+       }
+
+       /* Check for pad is video */
+       caps = gst_pad_query_caps(pad, NULL);
+       str = gst_caps_get_structure(caps, 0);
+       if (!g_strrstr(gst_structure_get_name(str), "video")) {
+               LOGI("Not a video pad");
+               gst_object_unref(video_pad);
+               return;
+       }
+       gst_caps_unref(caps);
+       gst_pad_link(pad, video_pad);
+       g_object_unref(video_pad);
+}
+
+static GstPadProbeReturn pad_probe_data_cb(
+               GstPad *pad,
+               GstPadProbeInfo *info,
+               gpointer user_data)
+{
+       if (user_data == NULL)
+               return GST_PAD_PROBE_PASS;
+
+       mv_video_reader_s *reader = (mv_video_reader_s *) user_data;
+
+       if (reader->caps == NULL) {
+               reader->caps = gst_pad_get_current_caps(pad);
+               reader->pad_probe_id = GST_PAD_PROBE_INFO_ID(info);
+       }
+
+       return GST_PAD_PROBE_OK;
+}
+
+int mv_video_reader_set_new_sample_cb(
+               mv_video_reader_h reader,
+               mv_video_reader_new_sample_cb callback,
+               void *user_data)
+{
+       mv_video_reader_s *handle = NULL;
+
+       if (reader == NULL || callback == NULL) {
+               LOGE("NULL pointer passed");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       handle = (mv_video_reader_s *) reader;
+
+       pthread_spin_lock(&(handle->new_sample_cb_guard));
+       handle->new_sample_cb = callback;
+       handle->new_sample_cb_user_data = user_data;
+       pthread_spin_unlock(&(handle->new_sample_cb_guard));
+
+       return MEDIA_VISION_ERROR_NONE;
+}
diff --git a/src/modules/modality_vision/video_helper/mv_video_helper.h b/src/modules/modality_vision/video_helper/mv_video_helper.h
new file mode 100644 (file)
index 0000000..2176d05
--- /dev/null
@@ -0,0 +1,199 @@
+/**
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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.
+ */
+
+#ifndef __MEDIA_VISION_MV_VIDEO_HELPER_H__
+#define __MEDIA_VISION_MV_VIDEO_HELPER_H__
+
+#include <mv_common.h>
+#include <image_helper.h>
+
+/**
+ * @brief The handle to the video reader.
+ *
+ * @since_tizen 3.0
+ */
+typedef void *mv_video_reader_h;
+
+/**
+ * @brief Called when new sample is available from video reader.
+ *
+ * @since_tizen 3.0
+ * @remarks You don't need release @a buffer independently
+ * @param [in] buffer            Raw video buffer
+ * @param [in] buffer_size       Size of video buffer
+ * @param [in] image_data        Image data for corresponding video buffer
+ * @param [in] user_data         User data
+ *
+ * @pre Create a reader handle by calling mv_video_reader_create()
+ * @pre Set callback by calling mv_video_reader_set_new_sample_cb()
+ *
+ * @see mv_video_reader_set_new_sample_cb()
+ */
+typedef void (*mv_video_reader_new_sample_cb) (
+               char *buffer,
+               unsigned int buffer_size,
+               image_data_s image_data,
+               void *user_data);
+
+/**
+ * @brief Called when stream from video reader is finished.
+ *
+ * @since_tizen 3.0
+ * @param [in] user_data         User data
+ *
+ * @pre Create a reader handle by calling mv_video_reader_create()
+ * @pre Set callback by calling mv_video_reader_set_eos_cb()
+ *
+ * @see mv_video_reader_set_eos_cb()
+ */
+typedef void (*mv_video_reader_eos_cb) (mv_video_reader_h reader,
+               void *user_data);
+
+
+/**
+ * @brief Creates a video reader handle.
+ *
+ * @since_tizen 3.0
+ * @remarks You must release @a reader by using @ref mv_destroy_video_reader().
+ * @param [out] reader    A new handle to the video reader
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIA_VISION_ERROR_NONE Successful
+ * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @see mv_destroy_video_reader()
+ */
+int mv_create_video_reader(
+               mv_video_reader_h *reader);
+
+/**
+ * @brief Destroys the video reader handle and releases all its resources.
+ *
+ * @since_tizen 3.0
+ * @param [in] reader    The handle to the video reader to be destroyed
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIA_VISION_ERROR_NONE Successful
+ * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see mv_create_video_reader()
+ */
+int mv_destroy_video_reader(
+               mv_video_reader_h reader);
+
+/**
+ * @brief Loads video from file.
+ *
+ * @since_tizen 3.0
+ * @param [in]  reader      The handle to the video reader
+ * @param [in]  path        Path to the video file to be loaded
+ * @param [out] image_data  Image data for corresponding video buffer
+ * @param [out] fps         Frame per second of corresponding video file
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIA_VISION_ERROR_NONE Successful
+ * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT Not supported video format
+ *
+ * @pre Create a video reader handle by calling @ref mv_create_video_reader()
+ */
+int mv_video_reader_load(
+               mv_video_reader_h reader,
+               const char *path,
+               image_data_s *image_data,
+               unsigned int *fps);
+
+/**
+ * @brief Starts reader playback.
+ *
+ * @since_tizen 3.0
+ * @param [in] reader       The handle to the video reader
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIA_VISION_ERROR_NONE Successful
+ * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @pre Create a video reader handle by calling @ref mv_create_video_reader()
+ *      and call @ref mv_video_reader_load()
+ *
+ * @post Stop reader playback by calling @ref mv_video_reader_stop()
+ */
+int mv_video_reader_start(
+               mv_video_reader_h reader);
+
+/**
+ * @brief Stops reader playback.
+ *
+ * @since_tizen 3.0
+ * @param [in] reader       The handle to the video reader
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIA_VISION_ERROR_NONE Successful
+ * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @pre Create a video reader handle by calling @ref mv_create_video_reader()
+ *      and call @ref mv_video_reader_load()
+ */
+int mv_video_reader_stop(
+               mv_video_reader_h reader);
+
+
+/**
+ * @brief Sets new sample callback to video reader.
+ *
+ * @since_tizen 3.0
+ * @param [in] reader      The handle to the video reader
+ * @param [in] callback    Callback that will be called
+ * @param [in] user_data  User data
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIA_VISION_ERROR_NONE Successful
+ * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre Create a video reader handle by calling @ref mv_create_video_reader()
+ *      and load video with @ref mv_video_reader_load()
+ *
+ * @see mv_create_video_reader()
+ * @see mv_video_reader_load()
+ *
+ */
+int mv_video_reader_set_new_sample_cb(
+               mv_video_reader_h reader,
+               mv_video_reader_new_sample_cb callback,
+               void *user_data);
+
+/**
+ * @brief Sets end of stream callback to video reader.
+ *
+ * @since_tizen 3.0
+ * @param [in] reader     The handle to the video reader
+ * @param [in] callback   Callback that will be called
+ * @param [in] user_data  User data
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIA_VISION_ERROR_NONE Successful
+ * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre Create a video reader handle by calling @ref mv_create_video_reader()
+ *      and load video with @ref mv_video_reader_load()
+ *
+ * @see mv_create_video_reader()
+ * @see mv_video_reader_load()
+ *
+ */
+int mv_video_reader_set_eos_cb(
+               mv_video_reader_h reader,
+               mv_video_reader_eos_cb callback,
+               void *user_data);
+
+#endif /* __MEDIA_VISION_MV_VIDEO_HELPER_H__ */