implemented decoding audio part, but needs to improve.
authorKitae Kim <kt920.kim@samsung.com>
Wed, 30 Jan 2013 12:30:07 +0000 (21:30 +0900)
committerKitae Kim <kt920.kim@samsung.com>
Fri, 21 Jun 2013 13:10:04 +0000 (22:10 +0900)
13 files changed:
src/Makefile.am
src/gstaudiofilter.c [deleted file]
src/gstemul.c
src/gstemulapi.c [new file with mode: 0644]
src/gstemulapi.h [new file with mode: 0644]
src/gstemulcommon.h
src/gstemuldec.c [deleted file]
src/gstemuldev.c
src/gstemuldev.h
src/gstemulnewdec.c [new file with mode: 0644]
src/gstemulnewenc.c [new file with mode: 0644]
src/gstemulutils.c [new file with mode: 0644]
src/gstemulutils.h [new file with mode: 0644]

index 8f2bc4bb545750d96e1c80c01a0402e0250e465e..d4f06f26c716270204e3d450b2e4bf4339df1693 100644 (file)
@@ -1,9 +1,9 @@
 # Note: plugindir is set in configure
 
 ##############################################################################
-# TODO: change libgstplugin.la to something else, e.g. libmysomething.la     #
+# TODO: change libgstemul.la to something else, e.g. libmysomething.la     #
 ##############################################################################
-plugin_LTLIBRARIES = libgstplugin.la
+plugin_LTLIBRARIES = libgstemul.la
 
 ##############################################################################
 # TODO: for the next set of variables, name the prefix if you named the .la, #
@@ -14,13 +14,17 @@ plugin_LTLIBRARIES = libgstplugin.la
 ##############################################################################
 
 # sources used to compile this plug-in
-libgstplugin_la_SOURCES = gstplugin.c gstplugin.h
+libgstemul_la_SOURCES = gstemul.c \
+       gstemulutils.c \
+       gstemulnewdec.c \
+       gstemulapi.c \
+       gstemuldev.c
 
 # compiler and linker flags used to compile this plugin, set in configure.ac
-libgstplugin_la_CFLAGS = $(GST_CFLAGS)
-libgstplugin_la_LIBADD = $(GST_LIBS)
-libgstplugin_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-libgstplugin_la_LIBTOOLFLAGS = --tag=disable-static
+libgstemul_la_CFLAGS = $(GST_CFLAGS) -g
+libgstemul_la_LIBADD = $(GST_LIBS) -lgstaudio-0.10 -lgstpbutils-0.10
+libgstemul_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstemul_la_LIBTOOLFLAGS = --tag=disable-static
 
 # headers we need but don't want installed
-noinst_HEADERS = gstplugin.h
+#noinst_HEADERS = gstemul.h
diff --git a/src/gstaudiofilter.c b/src/gstaudiofilter.c
deleted file mode 100644 (file)
index 462b763..0000000
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2003> David Schleef <ds@schleef.org>
- * Copyright (C) YEAR AUTHOR_NAME AUTHOR_EMAIL
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Alternatively, the contents of this file may be used under the
- * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
- * which case the following provisions apply instead of the ones
- * mentioned above:
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:element-plugin
- *
- * FIXME:Describe plugin here.
- *
- * <refsect2>
- * <title>Example launch line</title>
- * |[
- * gst-launch -v -m audiotestsrc ! plugin ! autoaudiosink
- * ]|
- * </refsect2>
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst.h>
-#include <gst/audio/audio.h>
-#include <gst/audio/gstaudiofilter.h>
-#include <string.h>
-
-GST_DEBUG_CATEGORY_STATIC (gst_plugin_template_debug);
-#define GST_CAT_DEFAULT gst_plugin_template_debug
-
-typedef struct _GstPluginTemplate GstPluginTemplate;
-typedef struct _GstPluginTemplateClass GstPluginTemplateClass;
-
-#define GST_TYPE_PLUGIN_TEMPLATE \
-  (gst_plugin_template_get_type())
-#define GST_PLUGIN_TEMPLATE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PLUGIN_TEMPLATE,GstPluginTemplate))
-#define GST_PLUGIN_TEMPLATE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PLUGIN_TEMPLATE,GstPluginTemplateClass))
-#define GST_IS_PLUGIN_TEMPLATE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PLUGIN_TEMPLATE))
-#define GST_IS_PLUGIN_TEMPLATE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PLUGIN_TEMPLATE))
-
-struct _GstPluginTemplate
-{
-  GstAudioFilter audiofilter;
-};
-
-struct _GstPluginTemplateClass
-{
-  GstAudioFilterClass parent_class;
-};
-
-
-enum
-{
-  /* FILL ME */
-  LAST_SIGNAL
-};
-
-enum
-{
-  ARG_0
-  /* FILL ME */
-};
-
-/* debug category for fltering log messages
- *
- * FIXME:exchange the string 'Template plugin' with your description
- */
-#define DEBUG_INIT(bla) \
-  GST_DEBUG_CATEGORY_INIT (gst_plugin_template_debug, "plugin", 0, "Template plugin");
-
-GST_BOILERPLATE_FULL (GstPluginTemplate, gst_plugin_template,
-    GstAudioFilter, GST_TYPE_AUDIO_FILTER, DEBUG_INIT);
-
-static void gst_plugin_template_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_plugin_template_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec);
-
-static gboolean gst_plugin_template_setup (GstAudioFilter * filter,
-    GstRingBufferSpec * spec);
-static GstFlowReturn gst_plugin_template_filter (GstBaseTransform * bt,
-    GstBuffer * outbuf, GstBuffer * inbuf);
-static GstFlowReturn
-gst_plugin_template_filter_inplace (GstBaseTransform * base_transform,
-    GstBuffer * buf);
-
-#define ALLOWED_CAPS_STRING \
-    GST_AUDIO_INT_STANDARD_PAD_TEMPLATE_CAPS
-
-/* GObject vmethod implementations */
-
-static void
-gst_plugin_template_base_init (gpointer klass)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-  GstAudioFilterClass *audiofilter_class = GST_AUDIO_FILTER_CLASS (klass);
-  GstCaps *caps;
-  
-  gst_element_class_set_details_simple (element_class,
-    "Plugin",
-    "Filter/Effect/Audio",
-    "FIXME:Filters audio",
-    "AUTHOR_NAME AUTHOR_EMAIL");
-
-  caps = gst_caps_from_string (ALLOWED_CAPS_STRING);
-  gst_audio_filter_class_add_pad_templates (audiofilter_class, caps);
-  gst_caps_unref (caps);
-}
-
-static void
-gst_plugin_template_class_init (GstPluginTemplateClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstBaseTransformClass *btrans_class;
-  GstAudioFilterClass *audio_filter_class;
-
-  gobject_class = (GObjectClass *) klass;
-  btrans_class = (GstBaseTransformClass *) klass;
-  audio_filter_class = (GstAudioFilterClass *) klass;
-
-#if 0
-  g_object_class_install_property (gobject_class, ARG_METHOD,
-      g_param_spec_enum ("method", "method", "method",
-          GST_TYPE_AUDIOTEMPLATE_METHOD, GST_AUDIOTEMPLATE_METHOD_1,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-#endif
-
-  gobject_class->set_property = gst_plugin_template_set_property;
-  gobject_class->get_property = gst_plugin_template_get_property;
-
-  /* this function will be called whenever the format changes */
-  audio_filter_class->setup = gst_plugin_template_setup;
-
-  /* here you set up functions to process data (either in place, or from
-   * one input buffer to another output buffer); only one is required */
-  btrans_class->transform = gst_plugin_template_filter;
-  btrans_class->transform_ip = gst_plugin_template_filter_inplace;
-}
-
-static void
-gst_plugin_template_init (GstPluginTemplate * plugin_template,
-    GstPluginTemplateClass * g_class)
-{
-  GST_DEBUG ("init");
-
-  /* do stuff if you need to */
-}
-
-static void
-gst_plugin_template_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstPluginTemplate *filter = GST_PLUGIN_TEMPLATE (object);
-
-  GST_OBJECT_LOCK (filter);
-  switch (prop_id) {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-  GST_OBJECT_UNLOCK (filter);
-}
-
-static void
-gst_plugin_template_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstPluginTemplate *filter = GST_PLUGIN_TEMPLATE (object);
-
-  GST_OBJECT_LOCK (filter);
-  switch (prop_id) {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-  GST_OBJECT_UNLOCK (filter);
-}
-
-static gboolean
-gst_plugin_template_setup (GstAudioFilter * filter,
-    GstRingBufferSpec * spec)
-{
-  GstPluginTemplate *plugin_template;
-
-  plugin_template = GST_PLUGIN_TEMPLATE (filter);
-
-  /* if any setup needs to be done, do it here */
-
-  return TRUE;                  /* it's all good */
-}
-
-/* You may choose to implement either a copying filter or an
- * in-place filter (or both).  Implementing only one will give
- * full functionality, however, implementing both will cause
- * audiofilter to use the optimal function in every situation,
- * with a minimum of memory copies. */
-
-static GstFlowReturn
-gst_plugin_template_filter (GstBaseTransform * base_transform,
-    GstBuffer * inbuf, GstBuffer * outbuf)
-{
-  GstPluginTemplate *plugin_template;
-  GstAudioFilter *audiofilter;
-
-  audiofilter = GST_AUDIO_FILTER (base_transform);
-  plugin_template = GST_PLUGIN_TEMPLATE (base_transform);
-
-  /* FIXME: do something interesting here.  This simply copies the source
-   * to the destination. */
-
-  memcpy (GST_BUFFER_DATA (outbuf), GST_BUFFER_DATA (inbuf),
-      GST_BUFFER_SIZE (inbuf));
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_plugin_template_filter_inplace (GstBaseTransform * base_transform,
-    GstBuffer * buf)
-{
-  GstPluginTemplate *plugin_template;
-  GstAudioFilter *audiofilter;
-
-  audiofilter = GST_AUDIO_FILTER (base_transform);
-  plugin_template = GST_PLUGIN_TEMPLATE (base_transform);
-
-  /* FIXME: do something interesting here.  This simply copies the source
-   * to the destination. */
-
-  return GST_FLOW_OK;
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-  return gst_element_register (plugin, "plugin", GST_RANK_NONE,
-      GST_TYPE_PLUGIN_TEMPLATE);
-}
-
-/* gstreamer looks for this structure to register plugins
- *
- * FIXME:exchange the string 'Template plugin' with you plugin description
- */
-GST_PLUGIN_DEFINE (
-    GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    "plugin",
-    "Template plugin",
-    plugin_init,
-    VERSION, "LGPL",
-    "GStreamer",
-    "http://gstreamer.net/"
-);
index e94a06b38839457b08d4e712090b45cd7ada7196..b682d6526b53f40147938d02cf63a22e08f55404 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * Emulator
  *
- * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved.
  *
- * Contact: 
+ * Contact:
  * KiTae Kim <kt920.kim@samsung.com>
  * SeokYeon Hwang <syeon.hwang@samsung.com>
  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
@@ -35,7 +35,7 @@
  *
  */
 
-#include <gst/gst.h>
+#include "gstemulcommon.h"
 
 GST_DEBUG_CATEGORY (emul_debug);
 
@@ -50,17 +50,106 @@ GST_DEBUG_CATEGORY (emul_debug);
 #define GST_IS_EMULDEC_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_EMULDEC))
 
-extern gboolean gst_emuldec_register (GstPlugin *plugin);
-extern gboolean gst_emulenc_register (GstPlugin *plugin);
+gboolean gst_emuldec_register (GstPlugin *plugin, GList *element);
+gboolean gst_emulenc_register (GstPlugin *plugin, GList *element);
+
+static GList *codec_element = NULL;
+
+static gboolean
+gst_emul_codec_element_init ()
+{
+  int fd, size = 0;
+  int version = 0;
+  int data_length = 0;
+  int ret = TRUE;
+  void *buffer = NULL;
+  GList *element = NULL;
+  CodecIOParams params;
+
+  fd = open (CODEC_DEV, O_RDWR);
+  if (fd < 0) {
+    perror ("failed to open codec device");
+  }
+
+#if 0
+  ioctl (fd, CODEC_CMD_GET_VERSION, &version);
+  if (version != CODEC_VER) {
+    printf ("version conflict between device: %d, plugin: %d\n",
+        version, CODEC_VER);
+    return FALSE;
+  }
+#endif
+
+  buffer = mmap (NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if (!buffer) {
+    perror ("failure memory mapping.");
+  }
+
+  CODEC_PARAM_INIT (params);
+  params.api_index = CODEC_ELEMENT_INIT;
+  CODEC_WRITE_TO_QEMU (fd, &params, 1);
+
+  do {
+    CodecElement *elm = NULL;
+
+    elm = g_malloc0 (sizeof(CodecElement));
+    if (!elm) {
+      printf ("Failed to allocate memory.\n");
+      ret = FALSE;
+      break;
+    }
+
+    memcpy (&data_length, (uint8_t *)buffer + size, sizeof(data_length));
+    size += sizeof(data_length);
+    if (!data_length) {
+//      printf ("There is no more avcodec.\n");
+      break;
+    }
+    memcpy (elm, (uint8_t *)buffer + size, data_length);
+    size += data_length;
+#if 0
+    printf("codec: %s, longname: %s, decode: %d, media: %d\n",
+      elm->name, elm->longname, elm->codec_type, elm->media_type);
+#endif
+    element = g_list_append (element, elm);
+  } while (1);
+
+  codec_element = element;
+
+  munmap (buffer, 4096);
+  close (fd);
+
+  return ret;
+}
 
 static gboolean
 plugin_init (GstPlugin *plugin)
 {
-       GST_DEBUG_CATEGORY_INIT (emul_debug, "tizen-emul", 0, "Tizen Emulator Codec Elements");
-//     gst_emulenc_register (plugin);  
-       gst_emuldec_register (plugin);  
+  GST_DEBUG_CATEGORY_INIT (emul_debug,
+      "tizen-emul", 0, "Tizen Emulator Codec Elements");
+  gboolean ret;
+
+  gst_emul_init_pix_fmt_info ();
+
+  if (!gst_emul_codec_element_init ()) {
+    GST_ERROR ("failed to get codec elements from QEMU");
+    return FALSE;
+  }
+
+  ret = gst_emuldec_register (plugin, codec_element);
+  if (!ret) {
+    GST_ERROR ("failed to register decoder elements");
+    return FALSE;
+  }
+#if 0
+  ret = gst_emulenc_register (plugin, codec_element);
+  if (!ret) {
+    GST_ERROR ("failed to register encoder elements");
+    return FALSE;
+  }
+#endif
 
-       return TRUE;
+  return TRUE;
 }
 
 #ifndef PACKAGE
@@ -68,13 +157,13 @@ plugin_init (GstPlugin *plugin)
 #endif
 
 GST_PLUGIN_DEFINE (
-       GST_VERSION_MAJOR,
-       GST_VERSION_MINOR,
-       "tizen-sdk",
-       "Codecs for Tizen Emulator",
-       plugin_init,
-       "0.1.1",
-       "LGPL",
-       "Gst-Emul-Codec",
-       "http://tizen.org"
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "tizen-sdk",
+  "Codecs for Tizen Emulator",
+  plugin_init,
+  "0.1.1",
+  "LGPL",
+  "Gst-Emul-Codec",
+  "http://tizen.org"
 )
diff --git a/src/gstemulapi.c b/src/gstemulapi.c
new file mode 100644 (file)
index 0000000..c4cf537
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * GStreamer codec plugin for Tizen Emulator.
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * KiTae Kim <kt920.kim@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#include "gstemulcommon.h"
+#include "gstemulapi.h"
+#include "gstemuldev.h"
+
+gboolean
+emul_avcodec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
+{
+  int fd;
+  void *mmapbuf;
+  int size = 0;
+  gboolean ret = TRUE;
+  CodecIOParams params;
+
+  printf ("enter: %s\n", __func__);
+
+  fd = dev->fd;
+  if (fd < 0) {
+    GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
+    return FALSE;
+  }
+
+  mmapbuf = dev->buf;
+  if (!mmapbuf) {
+    GST_ERROR ("failed to get mmaped memory address.\n");
+    return FALSE;
+  }
+
+//  printf("codec_init media_type: %d, codec_type: %d, name: %s\n",
+//    media_type, codec_type, name);
+
+  /* copy basic info to initialize codec on the host side.
+   * e.g. width, height, FPS ant etc. */
+  memcpy ((uint8_t *)mmapbuf, &codec->media_type, sizeof(codec->media_type));
+  size = sizeof(codec->media_type);
+  memcpy ((uint8_t *)mmapbuf + size, &codec->codec_type, sizeof(codec->codec_type));
+  size += sizeof(codec->codec_type);
+  memcpy ((uint8_t *)mmapbuf + size, codec->name, sizeof(codec->name));
+  size += sizeof(codec->name);
+
+  switch (codec->media_type) {
+  case AVMEDIA_TYPE_VIDEO:
+    memcpy ((uint8_t *)mmapbuf + size, &ctx->video, sizeof(ctx->video));
+    size += sizeof(ctx->video);
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+    memcpy ((uint8_t *)mmapbuf + size, &ctx->audio, sizeof(ctx->audio));
+    size += sizeof(ctx->audio);
+    break;
+  default:
+    GST_ERROR ("media type is unknown.\n");
+    ret = FALSE;
+    break;
+  }
+
+  memcpy ((uint8_t *)mmapbuf + size, &ctx->codecdata_size, sizeof(ctx->codecdata_size));
+  size += sizeof(ctx->codecdata_size);
+  if (ctx->codecdata_size) {
+    memcpy ((uint8_t *)mmapbuf + size, ctx->codecdata, ctx->codecdata_size);
+  }
+
+  CODEC_PARAM_INIT (params);
+  params.api_index = CODEC_INIT;
+  params.ctx_index = 0;
+  CODEC_WRITE_TO_QEMU (fd, &params, 1);
+
+  if (codec->media_type == AVMEDIA_TYPE_AUDIO) {
+    memcpy (&ctx->audio.sample_fmt,
+                 (uint8_t *)mmapbuf, sizeof(ctx->audio.sample_fmt));
+  }
+  ctx->codec = codec;
+
+  printf ("leave: %s\n", __func__);
+
+  return ret;
+}
+
+void
+emul_avcodec_deinit (CodecContext *ctx, CodecDevice *dev)
+{
+  int fd;
+  void *mmapbuf;
+  CodecIOParams params;
+
+  printf ("enter: %s\n", __func__);
+
+  fd = dev->fd;
+  if (fd < 0) {
+    GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
+    return;
+  }
+
+  mmapbuf = dev->buf;
+  if (!mmapbuf) {
+    GST_ERROR ("failed to get mmaped memory address.\n");
+    return;
+  }
+
+  CODEC_PARAM_INIT (params);
+  params.api_index = CODEC_DEINIT;
+  params.ctx_index = 0;
+  CODEC_WRITE_TO_QEMU (fd, &params, 1);
+
+#if 0
+  /* close device fd and release mapped memory region */
+  gst_emul_codec_device_close (dev);
+#endif
+
+  printf ("leave: %s\n", __func__);
+}
+
+int
+emul_avcodec_decode_video (CodecContext *ctx, guint8 *in_buf, guint in_size,
+        GstBuffer **out_buf, int *got_picture_ptr, CodecDevice *dev)
+{
+  int fd;
+  void *mmapbuf;
+  int len = 0, size = 0;
+  guint out_size;
+  CodecIOParams params;
+
+  *out_buf = NULL;
+
+  printf ("enter: %s\n", __func__);
+
+  fd = dev->fd;
+  if (fd < 0) {
+    GST_ERROR ("failed to get %s fd\n", CODEC_DEV);
+    return -1;
+  }
+
+  mmapbuf = dev->buf;
+  if (!mmapbuf) {
+    GST_ERROR ("failed to get mmaped memory address\n");
+    return -1;
+  }
+
+  memcpy ((uint8_t *)mmapbuf, &in_size, sizeof(guint));
+  size = sizeof(guint);
+//  memcpy ((uint8_t *)mmapbuf + size, &dec_info->timestamp, sizeof(GstClockTime));
+//  size += sizeof(GstClockTime);
+  memcpy ((uint8_t *)mmapbuf + size, in_buf, in_size);
+
+  /* provide raw image for decoding to qemu */
+  CODEC_PARAM_INIT (params);
+  params.api_index = CODEC_DECODE_VIDEO;
+  params.ctx_index = 0;
+  CODEC_WRITE_TO_QEMU (fd, &params, 1);
+
+  memcpy (&len, (uint8_t *)mmapbuf, sizeof(len));
+  size = sizeof(len);
+
+
+  printf ("leave: %s\n", __func__);
+
+  return len;
+}
+
+int
+emul_avcodec_decode_audio (CodecContext *ctx, int16_t *samples,
+               gint *frame_size_ptr, guint8 *in_buf, guint in_size, CodecDevice *dev)
+{
+  int fd;
+  void *mmapbuf = NULL;
+  int size = 0;
+  gint out_size = 0, len;
+  CodecIOParams params;
+
+  fd = dev->fd;
+  if (fd < 0) {
+    GST_ERROR("failed to get %s fd\n", CODEC_DEV);
+    return -1;
+  }
+
+  mmapbuf = dev->buf;
+  if (!mmapbuf) {
+    GST_ERROR("failed to get mmaped memory address\n");
+    return -1;
+  }
+
+  memcpy ((uint8_t *)mmapbuf, &in_size, sizeof(guint));
+  size = sizeof(guint);
+  if (in_size > 0) {
+    memcpy ((uint8_t *)mmapbuf + size, in_buf, in_size);
+  }
+
+  CODEC_PARAM_INIT (params);
+  params.api_index = CODEC_DECODE_AUDIO;
+  params.ctx_index = 0;
+  params.device_mem_offset = 0;
+  CODEC_WRITE_TO_QEMU (fd, &params, 1);
+
+  memcpy (&ctx->audio.channel_layout,
+                 (uint8_t *)mmapbuf, sizeof(ctx->audio.channel_layout));
+  size = sizeof(ctx->audio.channel_layout);
+  memcpy (&len, (uint8_t *)mmapbuf + size, sizeof(len));
+  size += sizeof(len);
+  memcpy (frame_size_ptr, (uint8_t *)mmapbuf + size, sizeof(*frame_size_ptr));
+  size += sizeof(*frame_size_ptr);
+  if (len > 0) {
+    memcpy (samples, (uint8_t *)mmapbuf + size, FF_MAX_AUDIO_FRAME_SIZE);
+  }
+
+  return len;
+}
+
+int
+emul_avcodec_encode_video (CodecContext *ctx, guint8 *in_buf, guint in_size,
+        GstBuffer **out_buf, CodecDevice *dev)
+{
+  int fd;
+  void *mmapbuf;
+  int len = 0, outbuf_size, size = 0;
+  CodecIOParams params;
+
+  printf ("enter: %s\n", __func__);
+
+  fd = dev->fd;
+  if (fd < 0) {
+    GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
+    return FALSE;
+  }
+
+  mmapbuf = dev->buf;
+  if (!mmapbuf) {
+    GST_ERROR ("failed to get mmaped memory address.\n");
+    return FALSE;
+  }
+
+  memcpy ((uint8_t *)mmapbuf + size, &in_size, sizeof(guint));
+  size += sizeof(guint);
+#if 0
+  memcpy ((uint8_t *)mmapbuf + size, &in_timestamp, sizeof(GstClockTime));
+  size += sizeof(GstClockTime);
+#endif
+  memcpy ((uint8_t *)mmapbuf + size, in_buf, in_size);
+
+  CODEC_PARAM_INIT (params);
+  params.api_index = CODEC_DECODE_AUDIO;
+  params.ctx_index = 0;
+  CODEC_WRITE_TO_QEMU (fd, &params, 1);
+
+#if 0
+  size = 0;
+  memcpy (&out_size, (uint8_t *)mmapbuf + size, sizeof(uint));
+  size += sizeof(guint);
+
+  ret = gst_pad_alloc_buffer_and_set_caps (emulenc->srcpad,
+          GST_BUFFER_OFFSET_NONE, out_size,
+          GST_PAD_CAPS (emulenc->srcpad), out_buf);
+
+  gst_buffer_set_caps (*out_buf, GST_PAD_CAPS (emulenc->srcpad));
+
+  if (GST_BUFFER_DATA(*out_buf)) {
+      memcpy (GST_BUFFER_DATA(*out_buf), (uint8_t *)mmapbuf + size, out_size);
+  } else {
+      pritnf ("failed to allocate output buffer\n");
+  }
+#endif
+
+  printf ("leave: %s\n", __func__);
+
+  return len;
+}
+
+int
+emul_avcodec_encode_audio (CodecContext *ctx, CodecDevice *dev)
+{
+  int fd;
+  void *mmapbuf;
+  int len = 0, size = 0;
+  CodecIOParams params;
+
+  printf ("enter: %s\n", __func__);
+
+  fd = dev->fd;
+  if (fd < 0) {
+    GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
+    return FALSE;
+  }
+
+  mmapbuf = dev->buf;
+  if (!mmapbuf) {
+    GST_ERROR ("failed to get mmaped memory address.\n");
+    return FALSE;
+  }
+
+#if 0
+  memcpy ((uint8_t *)mmapbuf + size, &in_size, sizeof(guint));
+  size += sizeof(guint);
+  memcpy ((uint8_t *)mmapbuf + size, &in_timestamp, sizeof(GstClockTime));
+  size += sizeof(GstClockTime);
+  memcpy ((uint8_t *)mmapbuf + size, in_buf, in_size);
+#endif
+
+  CODEC_PARAM_INIT (params);
+  params.api_index = CODEC_DECODE_AUDIO;
+  params.ctx_index = 0;
+  CODEC_WRITE_TO_QEMU (fd, &params, 1);
+
+#if 0
+  size = 0;
+  memcpy (&out_size, (uint8_t *)mmapbuf + size, sizeof(uint));
+  size += sizeof(guint);
+
+  *out_buf = gst_buffer_new();
+  GST_BUFFER_DATA (out_buf) = GST_BUFFER_MALLOCDATA (out_buf) = av_malloc (out_size);
+  GST_BUFFER_SIZE (out_buf) = out_size;
+  //  GST_BUFFER_FREE_FUNC (out_buf) = g_free;
+  if (GST_PAD_CAPS(emulenc->srcpad)) {
+      gst_buffer_set_caps (*out_buf, GST_PAD_CAPS (emulenc->srcpad));
+  }
+
+  if (GST_BUFFER_DATA(*out_buf)) {
+      memcpy (GST_BUFFER_DATA(*out_buf), (uint8_t *)mmapbuf + size, out_size);
+  } else {
+      pritnf ("failed to allocate output buffer\n");
+  }
+#endif
+
+  printf ("leave: %s\n", __func__);
+
+  return len;
+}
diff --git a/src/gstemulapi.h b/src/gstemulapi.h
new file mode 100644 (file)
index 0000000..203d839
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * GStreamer codec plugin for Tizen Emulator.
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * KiTae Kim <kt920.kim@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#ifndef __GST_EMUL_API_H__
+#define __GST_EMUL_API_H__
+
+#include "gstemulcommon.h"
+
+gboolean emul_avcodec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev);
+int emul_avcdoec_deinit (CodecContext *ctx, CodecDevice *dev);
+
+int emul_avcodec_decode_video (CodecContext *ctx, guint8 *in_buf, guint in_size,
+        GstBuffer **out_buf, int *got_picture_ptr, CodecDevice *dev);
+int emul_avcodec_decode_audio (CodecContext *ctx, int16_t *samples,
+        gint *frame_size_ptr, guint8 *in_buf, guint in_size, CodecDevice *dev);
+
+int emul_avcodec_encode_video (CodecContext *ctx, guint8 *in_buf, guint in_size,
+        GstBuffer **out_buf, CodecDevice *dev);
+int emul_avcodec_encode_audio (CodecContext *ctx, CodecDevice *dev);
+
+#endif /* __GST_EMUL_API_H__ */
index 46af0fd8e4ffc0f9ecec68b7fe2b93eeb0000238..67c97e43558c60009549a454318d9a9cc5c7977f 100644 (file)
@@ -1,3 +1,33 @@
+/*
+ * GStreamer codec plugin for Tizen Emulator.
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * KiTae Kim <kt920.kim@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
 #ifndef __GST_EMUL_H__
 #define __GST_EMUL_H__
 
 #include <string.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <sys/ioctl.h>
 #include <sys/mman.h>
+#include <glib.h>
 #include <gst/gst.h>
+#include "pixfmt.h"
 
 GST_DEBUG_CATEGORY_EXTERN (emul_debug);
-#define GST_CAT_DEFAULT        emul_debug
+#define GST_CAT_DEFAULT emul_debug
 
 G_BEGIN_DECLS
 
-static int codec_debug_level = 2;
-#define CODEC_LOG(level, fmt, ...) \
-  do {    \
-    if (codec_debug_level >= (level)) \
-      printf("[gst-ffmpeg-emul][%d] " fmt, __LINE__, ##__VA_ARGS__); \
-  } while (0)
-
-#define CODEC_DEV   "/dev/codec"
+#define CODEC_DEV   "/dev/newcodec"
 #define CODEC_VER   10
 
-typedef struct CodecDev
-{
-  int fd; 
-  void *buffer;  
-} CodecDev;
+#define CODEC_PARAM_INIT(var) \
+  memset (&var, 0x00, sizeof(var))
+
+#define CODEC_WRITE_TO_QEMU(fd, var, size) \
+  if (write (fd, var, size) < 0) { \
+    printf ("[%d] failed to copy data.\n", __LINE__); \
+  }
+
+#define FF_INPUT_BUFFER_PADDING_SIZE  8
+#define FF_MAX_AUDIO_FRAME_SIZE     192000 // 1 second of 48khz 32bit audio
+#define FF_MIN_BUFFER_SIZE        16384
+
+typedef struct _CodecIOParams {
+  uint32_t  api_index;
+  uint32_t  ctx_index;
+  uint32_t  file_index;
+  uint32_t  mem_index;
+  uint32_t  device_mem_offset;
+} CodecIOParams;
+
+typedef struct _CodecDevice {
+  int   fd;
+  void    *buf;
+  uint32_t  buf_size;
+} CodecDevice;
+
+typedef struct _CodecElement {
+  gchar   name[32];
+  gchar   longname[64];
+  uint16_t  codec_type;
+  uint16_t  media_type;
+#if 0
+  union {
+    struct {
+      int8_t pix_fmts[8];
+    } video;
+    struct {
+      int8_t sample_fmts[8];
+    } audio;
+  } format;
+#endif
+} CodecElement;
 
-typedef struct _CodecInfo {
-  uint16_t media_type;
-  uint16_t codec_type;
-  gchar codec_name[32];
-  gchar codec_longname[64];
-  int8_t sample_fmts[8];
-} CodecInfo;
+typedef struct _VideoData {
+  int width, height;
+  int fps_n, fps_d;
+  int par_n, par_d;
+  int pix_fmt, bpp;
+} VideoData;
+
+typedef struct _AudioData {
+  int channels, sample_rate;
+  int bit_rate, block_align;
+  int depth, sample_fmt;
+  int64_t channel_layout;
+} AudioData;
+
+typedef struct _CodecContext {
+  uint8_t *codecdata;
+  int codecdata_size;
+
+  VideoData video;
+  AudioData audio;
+
+  CodecElement *codec;
+} CodecContext;
 
 enum CODEC_FUNC_TYPE {
-  CODEC_QUERY = 1,
+  CODEC_ELEMENT_INIT = 1,
   CODEC_INIT,
   CODEC_DEINIT,
   CODEC_DECODE_VIDEO,
@@ -49,12 +128,26 @@ enum CODEC_FUNC_TYPE {
   CODEC_ENCODE_AUDIO,
 };
 
+enum CODEC_IO_CMD {
+  CODEC_CMD_GET_VERSION = 5,
+  CODEC_CMD_GET_DEVICE_MEM,
+  CODEC_CMD_SET_DEVICE_MEM,
+  CODEC_CMD_GET_MMAP_OFFSET,
+  CODEC_CMD_SET_MMAP_OFFSET,
+};
+
 enum CODEC_MEDIA_TYPE {
   AVMEDIA_TYPE_UNKNOWN = -1,
   AVMEDIA_TYPE_VIDEO,
   AVMEDIA_TYPE_AUDIO,
 };
 
+enum CODEC_TYPE {
+  CODEC_TYPE_UNKNOWN = -1,
+  CODEC_TYPE_DECODE,
+  CODEC_TYPE_ENCODE,
+};
+
 enum SAMPLT_FORMAT {
   SAMPLE_FMT_NONE = -1,
   SAMPLE_FMT_U8,
@@ -69,7 +162,7 @@ enum SAMPLT_FORMAT {
  * e.g. FFmpeg, x264, libvpx and etc.
  */
 enum {
-       FFMPEG_TYPE = 1,
+  FFMPEG_TYPE = 1,
 };
 
 G_END_DECLS
diff --git a/src/gstemuldec.c b/src/gstemuldec.c
deleted file mode 100644 (file)
index 1cd538a..0000000
+++ /dev/null
@@ -1,1585 +0,0 @@
-/*
- * Emulator
- *
- * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact:
- * KiTae Kim <kt920.kim@samsung.com>
- * SeokYeon Hwang <syeon.hwang@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/* First, include the header file for the plugin, to bring in the
- * object definition and other useful things.
- */
-
-/*
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <gst/gst.h>
-//#include <glib.h>
-//#include <glib/gprintf.h>
-#include "gstemulcommon.h"
-
-#define GST_EMULDEC_PARAMS_QDATA g_quark_from_static_string("emuldec-params")
-
-typedef struct
-{
-  gint idx;
-  GstClockTime timestamp;
-  GstClockTime duration;
-  gint64 offset;
-} GstTSInfo;
-
-#define GST_TS_INFO_NONE &ts_info_none
-static const GstTSInfo ts_info_none = { -1, -1, -1, -1 };
-
-#define MAX_TS_MASK 0xff
-
-typedef struct _GstEmulDec
-{
-  GstElement element;
-
-  GstPad *srcpad;
-  GstPad *sinkpad;
-
-  union {
-    struct {
-      gint width;
-      gint height;
-      gint framerate_num;
-      gint framerate_den;
-      gint pix_fmt;
-    } video;
-    struct {
-      gint channels;
-      gint samplerate;
-      gint depth;
-    } audio;
-  } format;
-
-  guint extradata_size;
-  guint8 *extradata;
-
-  GstTSInfo ts_info[MAX_TS_MASK + 1];
-  gint ts_idx;
-
-  CodecDev codecbuf;
-  CodecInfo *codecinfo;
-} GstEmulDec;
-
-typedef struct _GstEmulDecClass
-{
-  GstElementClass parent_class;
-
-  CodecInfo *codecinfo;
-  GstPadTemplate *sinktempl;
-  GstPadTemplate *srctempl;
-} GstEmulDecClass;
-
-
-static GstElementClass *parent_class = NULL;
-
-static void gst_emuldec_base_init (GstEmulDecClass *klass);
-static void gst_emuldec_class_init (GstEmulDecClass *klass);
-static void gst_emuldec_init (GstEmulDec *emuldec);
-static void gst_emuldec_finalize (GObject *object);
-
-static gboolean gst_emuldec_setcaps (GstPad *pad, GstCaps *caps);
-
-// sinkpad
-static gboolean gst_emuldec_sink_event (GstPad *pad, GstEvent *event);
-static GstFlowReturn gst_emuldec_chain (GstPad *pad, GstBuffer *buffer);
-
-// srcpad
-static gboolean gst_emuldec_src_event (GstPad *pad, GstEvent *event);
-static GstStateChangeReturn gst_emuldec_change_state (GstElement *element,
-                                                GstStateChange transition);
-
-int gst_emul_codec_init (GstEmulDec *emuldec, CodecInfo *codec_info);
-void gst_emul_codec_deinit (GstEmulDec *emuldec);
-int gst_emul_decode_video (GstEmulDec *emuldec, guint8 *in_buf, guint in_size,
-                            GstBuffer **out_buf, GstTSInfo *dec_info);
-int gst_emul_decode_audio (GstEmulDec *emuldec, guint8 *in_buf, guint in_size,
-                            GstBuffer **outb_buf, GstTSInfo *dec_info);
-int gst_emul_codec_device_open (GstEmulDec *emuldec);
-int gst_emul_codec_device_close (GstEmulDec *emuldec);
-
-GstCaps *gst_emul_codecname_to_caps (CodecInfo *info);
-GstCaps *gst_emul_codectype_to_video_caps (CodecInfo *info);
-GstCaps *gst_emul_codectype_to_audio_caps (CodecInfo *info);
-static GstCaps * gst_emul_smpfmt_to_caps (int8_t sample_fmt, CodecInfo *info);
-
-static gboolean gst_emuldec_negotiate (GstEmulDec *dec, gboolean force);
-
-
-static CodecInfo *codec;
-
-static const GstTSInfo *
-gst_ts_info_store (GstEmulDec *dec, GstClockTime timestamp,
-    GstClockTime duration, gint64 offset)
-{
-  gint idx = dec->ts_idx;
-  dec->ts_info[idx].idx = idx;
-  dec->ts_info[idx].timestamp = timestamp;
-  dec->ts_info[idx].duration = duration;
-  dec->ts_info[idx].offset = offset;
-  dec->ts_idx = (idx + 1) & MAX_TS_MASK;
-
-  return &dec->ts_info[idx];
-}
-
-static const GstTSInfo *
-gst_ts_info_get (GstEmulDec *dec, gint idx)
-{
-  if (G_UNLIKELY (idx < 0 || idx > MAX_TS_MASK))
-    return GST_TS_INFO_NONE;
-
-  return &dec->ts_info[idx];
-}
-
-/*
- * Implementation
- */
-static void
-gst_emuldec_base_init (GstEmulDecClass *klass)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-  GstCaps *sinkcaps, *srccaps;
-  GstPadTemplate *sinktempl, *srctempl;
-  CodecInfo *info;
-  gchar *longname, *classification;
-
-  info =
-      (CodecInfo *)g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
-                                      GST_EMULDEC_PARAMS_QDATA);
-
-  longname = g_strdup_printf ("%s Decoder", info->codec_longname);
-
-  classification = g_strdup_printf ("Codec/Decoder/%s",
-                    (info->media_type == AVMEDIA_TYPE_VIDEO) ?
-                    "Video" : "Audio");
-
-  gst_element_class_set_details_simple (element_class,
-            longname,                        // longname
-            classification,                  // classification
-            "accelerated codec for Tizen Emulator",       // description
-            "Kitae Kim <kt920.kim@samsung.com>");   // author
-
-  g_free (longname);
-  g_free (classification);
-
-#if 0
-  sinkcaps = gst_caps_new_simple (mimetype,
-          "width", GST_TYPE_INT_RANGE, 16, 4096,
-          "height", GST_TYPE_INT_RANGE, 16, 4096,
-          "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
-#endif
-  sinkcaps = gst_emul_codecname_to_caps (info);
-  if (!sinkcaps) {
-    sinkcaps = gst_caps_from_string ("unknown/unknown");
-  }
-
-  // if type is video
-  switch (info->media_type) {
-       case AVMEDIA_TYPE_VIDEO:
-    srccaps = gst_caps_from_string ("video/x-raw-rgb; video/x-raw-yuv");
-               break;
-  case AVMEDIA_TYPE_AUDIO:
-    srccaps = gst_emul_codectype_to_audio_caps (info);
-               break;
-       default:
-               GST_LOG("unknown media type.\n");
-               break;
-  }
-
-  if (!srccaps) {
-    srccaps = gst_caps_from_string ("unknown/unknown");
-  }
-
-  sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK,
-                GST_PAD_ALWAYS, sinkcaps);
-  srctempl = gst_pad_template_new ("src", GST_PAD_SRC,
-                GST_PAD_ALWAYS, srccaps);
-
-  gst_element_class_add_pad_template (element_class, srctempl);
-  gst_element_class_add_pad_template (element_class, sinktempl);
-
-  klass->codecinfo = info;
-
-  klass->sinktempl = sinktempl;
-  klass->srctempl = srctempl;
-}
-
-static void
-gst_emuldec_class_init (GstEmulDecClass *klass)
-{
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
-  parent_class = g_type_class_peek_parent (klass);
-
-#if 0
-  gobject_class->set_property = gst_emuldec_set_property
-  gobject_class->get_property = gst_emuldec_get_property
-#endif
-
-  gobject_class->finalize = gst_emuldec_finalize;
-  gstelement_class->change_state = gst_emuldec_change_state;
-}
-
-static void
-gst_emuldec_init (GstEmulDec *emuldec)
-{
-  GstEmulDecClass *oclass;
-
-  oclass = (GstEmulDecClass*) (G_OBJECT_GET_CLASS(emuldec));
-
-  emuldec->sinkpad = gst_pad_new_from_template (oclass->sinktempl, "sink");
-  gst_pad_set_setcaps_function (emuldec->sinkpad,
-                              GST_DEBUG_FUNCPTR(gst_emuldec_setcaps));
-  gst_pad_set_event_function (emuldec->sinkpad,
-                              GST_DEBUG_FUNCPTR(gst_emuldec_sink_event));
-  gst_pad_set_chain_function (emuldec->sinkpad,
-                              GST_DEBUG_FUNCPTR(gst_emuldec_chain));
-  gst_element_add_pad (GST_ELEMENT(emuldec), emuldec->sinkpad);
-
-  emuldec->srcpad = gst_pad_new_from_template (oclass->srctempl, "src") ;
-  gst_pad_use_fixed_caps (emuldec->srcpad);
-  gst_pad_set_event_function (emuldec->srcpad,
-                              GST_DEBUG_FUNCPTR(gst_emuldec_src_event));
-  gst_element_add_pad (GST_ELEMENT(emuldec), emuldec->srcpad);
-}
-
-static void
-gst_emuldec_finalize (GObject *object)
-{
-  // Deinit Decoder
-  GstEmulDec *emuldec = (GstEmulDec *) object;
-
-  if (emuldec->extradata) {
-    printf("free extradata.\n");
-    g_free(emuldec->extradata);
-    emuldec->extradata = NULL;
-  }
-
-  if (codec) {
-    printf("free CodecInfo.\n");
-    g_free(codec);
-    codec = NULL;
-  }
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static gboolean
-gst_emuldec_src_event (GstPad *pad, GstEvent *event)
-{
-  GstEmulDec *emuldec;
-  gboolean res; 
-
-  emuldec = (GstEmulDec *) gst_pad_get_parent (pad);
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_QOS:
-    {    
-      gdouble proportion;
-      GstClockTimeDiff diff;
-      GstClockTime timestamp;
-
-      gst_event_parse_qos (event, &proportion, &diff, &timestamp);
-      GST_LOG_OBJECT (emuldec, "update QOS: %f, %" GST_TIME_FORMAT,
-                      proportion, GST_TIME_ARGS (timestamp));
-      /* update our QoS values */
-//      gst_ffmpegdec_update_qos (ffmpegdec, proportion, timestamp + diff);
-
-      /* forward upstream */
-      res = gst_pad_push_event (emuldec->sinkpad, event);
-      break;
-    }    
-    default:
-      /* forward upstream */
-      res = gst_pad_push_event (emuldec->sinkpad, event);
-      break;
-  }
-
-  gst_object_unref (emuldec);
-
-  return 0;
-}
-
-#if 0
-GstCaps*
-gst_emul_codectype_to_video_caps (CodecInfo *info)
-{
-       GstCaps *caps;
-
-       return caps;
-}
-#endif
-
-static GstCaps*
-gst_emul_codectype_to_caps (GstEmulDec *emuldec, CodecInfo *codec_info)
-{
-  GstCaps *caps;
-  guint32 fmt = 0;
-
-       switch (codec_info->media_type) {       
-       case AVMEDIA_TYPE_VIDEO:
-       {
-         const char *mimetype = "video/x-raw-yuv";
-         gint num, denom;
-
-
-               // YUV420P or YUVJ420P
-               fmt = GST_MAKE_FOURCC ('I', '4', '2', '0');
-
-               caps = gst_caps_new_simple (mimetype,
-                                               "width", G_TYPE_INT, emuldec->format.video.width,
-                                               "height", G_TYPE_INT, emuldec->format.video.height, NULL);
-
-               num = emuldec->format.video.framerate_den;
-               denom = emuldec->format.video.framerate_num;
-
-               if (!denom) {
-                       GST_LOG ("invalid framerate: %d/0, -> %d/1", num, num);
-                       denom = 1;
-               }
-
-               if (gst_util_fraction_compare (num, denom, 1000, 1) > 0) {
-                       GST_LOG ("excessive framerate: %d/%d, -> 0/1", num, denom);
-                       num = 0;
-                       denom = 1;
-               }
-
-    GST_LOG ("setting framerate: %d/%d", num, denom);
-               gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, num, denom, NULL);
-
-    // default unfixed setting
-               if (!caps) {
-                       caps = gst_caps_new_simple (mimetype,
-                                                       "width", GST_TYPE_INT_RANGE, 16, 4096,
-                                                       "height", GST_TYPE_INT_RANGE, 16, 4096,
-                                                       "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
-               }
-
-               gst_caps_set_simple (caps, "format", GST_TYPE_FOURCC, fmt, NULL);
-       }
-               break;
-       case AVMEDIA_TYPE_AUDIO:
-  {
-    const char *mimetype="audio/x-raw-int";
-
-    caps = gst_caps_new_simple (mimetype,
-            "rate", G_TYPE_INT, emuldec->format.audio.samplerate,
-            "channels", G_TYPE_INT, emuldec->format.audio.channels,
-            "signed", G_TYPE_BOOLEAN, TRUE,
-            "endianness", G_TYPE_INT, G_BYTE_ORDER,
-            "width", G_TYPE_INT, 16,
-            "depth", G_TYPE_INT, 16, NULL);
-  }
-               break;
-       default:
-               break;
-       }
-
-  return caps;
-}
-
-static void
-gst_emul_caps_with_codecid (GstEmulDec *emuldec,
-                                                                                                               CodecInfo *codec_info,
-                                                                                                               GstCaps *caps)
-{
-  GstStructure *structure;
-
-  int width, height, bits_per_coded_sample;
-  const GValue *fps;
-  //    const GValue *par;
-  //    guint extradata_size;
-  //    guint8 *extradata;
-
-  /* FFmpeg Specific Values */
-  const GstBuffer *buf;
-  const GValue *value;
-
-  structure = gst_caps_get_structure (caps, 0);
-
-  value = gst_structure_get_value (structure, "codec_data");
-  if (value) {
-    buf = GST_BUFFER_CAST (gst_value_get_mini_object (value));
-    emuldec->extradata_size = GST_BUFFER_SIZE (buf);
-    emuldec->extradata = GST_BUFFER_DATA (buf);
-               printf("extradata: %p, size: %d\n", emuldec->extradata, emuldec->extradata_size);
-  } else {
-//    CODEC_LOG(2, "no codec data\n");
-    GST_DEBUG_OBJECT (emuldec, "no extra data.\n");
-    emuldec->extradata_size = 0;
-    emuldec->extradata = g_malloc0 (GST_ROUND_UP_16(8));
-  }
-
-       printf("caps_with_codecid, media_type: %d, codec_name: %s\n", codec_info->media_type, codec_info->codec_name);
-
-  if (!gst_caps_is_fixed (caps)) {
-    return;
-  }
-
-       switch (codec_info->media_type) {
-       case AVMEDIA_TYPE_VIDEO:
-  /* Common Properites, width, height and etc. */
-  gst_structure_get_int (structure, "width", &width);
-  gst_structure_get_int (structure, "height", &height);
-  gst_structure_get_int (structure, "bpp", &bits_per_coded_sample);
-
-  emuldec->format.video.width = width;
-  emuldec->format.video.height = height;
-
-  fps = gst_structure_get_value (structure, "framerate");
-  if (fps) {
-    emuldec->format.video.framerate_den = gst_value_get_fraction_numerator (fps);
-    emuldec->format.video.framerate_num = gst_value_get_fraction_denominator (fps);
-    printf ("framerate: %d/%d.\n", emuldec->format.video.framerate_num, emuldec->format.video.framerate_den);
-
-  }
-
-#if 0
-  par = gst_structure_get_value (structure, "pixel-aspect-ratio");
-  if (par) {
-    sample_aspect_ratio.num = gst_structure_get_fraction_numerator (par);
-    sample_aspect_ratio.den = gst_structure_get_fraction_denominator (par);
-  }
-#endif
-               break;
-  /* audio type */
-       case AVMEDIA_TYPE_AUDIO:
-       {
-               GstStructure *structure;
-               int channels = 0;
-               int sample_rate = 0;
-               int block_align = 0;
-               int bit_rate = 0;
-               
-               g_return_if_fail (gst_caps_get_size (caps) == 1);
-               structure = gst_caps_get_structure (caps, 0);
-
-               gst_structure_get_int (structure, "channels", &channels);
-               gst_structure_get_int (structure, "rate", &sample_rate);
-               gst_structure_get_int (structure, "block_align", &block_align);
-               gst_structure_get_int (structure, "bitrate", &bit_rate);
-
-               printf("channels: %d, sample_rate: %d, block_align: %d, bit_rate: %d\n",
-                                               channels, sample_rate, block_align, bit_rate);
-
-               emuldec->format.audio.channels = channels;
-               emuldec->format.audio.samplerate = sample_rate;
-       }
-               break;
-       default:
-               break;
-       }
-
-}
-
-static gboolean
-gst_emuldec_setcaps (GstPad *pad, GstCaps *caps)
-{
-  GstEmulDec *emuldec;
-  GstEmulDecClass *oclass;
-  gboolean ret = TRUE;
-
-  emuldec = (GstEmulDec *) (gst_pad_get_parent (pad));
-  oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (emuldec));
-
-  GST_OBJECT_LOCK (emuldec);
-
-       emuldec->codecinfo = oclass->codecinfo;
-       printf("setcaps, codec_type: %d, codec_name: %s\n", emuldec->codecinfo->codec_type, emuldec->codecinfo->codec_name);
-
-  gst_emul_caps_with_codecid (emuldec, oclass->codecinfo, caps);
-
-#if 0
-  if (!emuldec->format.video.framerate_den ||
-      !emuldec->format.video.framerate_num) {
-    emuldec->format.video.framerate_num = 1;
-    emuldec->format.video.framerate_den = 25;
-  }
-#endif
-
-  if (gst_emul_codec_device_open (emuldec) < 0) {
-//    CODEC_LOG(1, "failed to access %s or mmap operation\n", CODEC_DEV);
-    GST_LOG_OBJECT (emuldec, "failed to access %s or mmap operation\n", CODEC_DEV);
-    GST_OBJECT_UNLOCK (emuldec);
-    gst_object_unref (emuldec);
-    return FALSE;
-  }
-
-  if (gst_emul_codec_init (emuldec, oclass->codecinfo) < 0) {
-//    CODEC_LOG(1, "cannot initialize codec\n");
-    GST_LOG_OBJECT (emuldec, "cannot initialize codec.\n");
-    GST_OBJECT_UNLOCK (emuldec);
-    gst_object_unref (emuldec);
-    return FALSE;
-  }
-
-#if 0 /* open a parser */
-  gst_emul_codec_parser (emuldec);
-#endif
-
-  GST_OBJECT_UNLOCK (emuldec);
-
-  gst_object_unref (emuldec);
-
-  return ret;
-}
-
-static gboolean
-gst_emuldec_sink_event (GstPad *pad, GstEvent *event)
-{
-  GstEmulDec *emuldec;
-  gboolean ret = FALSE;
-
-  emuldec = (GstEmulDec *) gst_pad_get_parent (pad);
-#if 1 
-    switch (GST_EVENT_TYPE (event)) {
-        case GST_EVENT_EOS:
-//            CODEC_LOG(1, "received GST_EVENT_EOS\n");
-            GST_LOG_OBJECT (emuldec, "received GST_EVENT_EOS\n");
-            break;
-        case GST_EVENT_NEWSEGMENT:
-//            CODEC_LOG(1, "received GST_EVENT_NEWSEGMENT\n");
-            GST_LOG_OBJECT (emuldec, "received GST_EVENT_NEWSEGMENT\n");
-            break;
-    }
-    ret = gst_pad_push_event (emuldec->srcpad, event);
-#endif
-
-  gst_object_unref (emuldec);
-
-  return ret;
-}
-
-static GstFlowReturn
-gst_emuldec_chain (GstPad *pad, GstBuffer *buffer)
-{
-  GstEmulDec *emuldec;
-       CodecInfo *codec_info;
-  guint8 *in_buf, *aud_buf;
-  GstBuffer *out_buf = NULL;
-  gint in_size = 0, aud_size = 0, len = 0;
-  GstFlowReturn ret = GST_FLOW_OK;
-  GstClockTime in_timestamp;
-  GstClockTime in_duration;
-  gint64 in_offset;
-  gboolean discont;
-  const GstTSInfo *in_info;
-  GstTSInfo *dec_info;
-
-  emuldec = (GstEmulDec *) (GST_PAD_PARENT (pad));
-       if (!emuldec) {
-               GST_ERROR ("failed to get GstEmulDec.\n");
-               return GST_FLOW_ERROR;
-       }
-
-  discont = GST_BUFFER_IS_DISCONT (buffer);
-  if (G_UNLIKELY (discont)) {
-    printf("received DISCONT.\n");
-    // TODO
-    // drain
-    // flush pcache
-    // flush buffers
-    // reset timestamp
-  }
-
-       codec_info = emuldec->codecinfo;
-
-  aud_size = in_size = GST_BUFFER_SIZE (buffer);
-  aud_buf = in_buf = GST_BUFFER_DATA (buffer);
-
-  in_timestamp = GST_BUFFER_TIMESTAMP (buffer);
-  in_duration = GST_BUFFER_DURATION (buffer);
-  in_offset = GST_BUFFER_OFFSET (buffer);
-
-  GST_LOG_OBJECT(emuldec, "offset %" G_GUINT64_FORMAT ", ts: %." GST_TIME_FORMAT "\n",
-                in_offset, GST_TIME_ARGS(in_timestamp));
-  in_info = gst_ts_info_store (emuldec, in_timestamp, in_duration, in_offset);
-
-  // TODO
-  dec_info = in_info;
-
-  do { 
-       printf("media_type: %d, name: %s\n", codec_info->media_type, codec_info->codec_name);
-  switch (codec_info->media_type) {
-       case AVMEDIA_TYPE_VIDEO:
-#if 1
-    {
-        /* Caps negotiation */
-        GstCaps *caps;
-
-        caps = gst_emul_codectype_to_caps (emuldec, codec_info);
-
-        if (!gst_pad_set_caps (emuldec->srcpad, caps)) {
-            GST_ERROR_OBJECT(emuldec, "failed to set caps for srcpad.\n");
-            gst_buffer_unref (buffer);
-            return GST_FLOW_NOT_NEGOTIATED;
-        }
-    }
-#endif
-      printf("before decode\n");
-      len = gst_emul_decode_video (emuldec, in_buf, in_size, &out_buf, dec_info);
-      printf("after decode\n");
-      break;
-       case AVMEDIA_TYPE_AUDIO:
-      len = gst_emul_decode_audio (emuldec, in_buf, in_size, &out_buf, dec_info);
-      aud_size -= len;
-      aud_buf += len; 
-                       break;
-       default:
-                       break;
-       }
-  } while (aud_size > 0);
-
-  GST_DEBUG_OBJECT(emuldec, "out_buf:%p, len:%d\n", out_buf, len);
-
-#if 0
-  idx = picture->reordered_opaque;
-  out_info = gst_ts_info_get(emuldec, idx);
-  out_pts = out_info->timestamp;
-  out_duration = out_info->duration;
-  out_offset = out_info->offset;
-  GST_LOG_OBJECT (emuldec, "offset %" G_GUINT64_FORMAT ", ts: %." G_GINT64_FORMAT "\n",
-                  out_offset, out_duration);
-#endif
-  ret = gst_pad_push (emuldec->srcpad, out_buf);
-
-//  g_free (out_buf);
-  gst_buffer_unref (buffer);
-
-  return ret;
-}
-
-static GstStateChangeReturn
-gst_emuldec_change_state (GstElement *element, GstStateChange transition)
-{
-  GstEmulDec *emuldec = (GstEmulDec*)element;
-  GstStateChangeReturn ret;
-
-  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      gst_emul_codec_deinit (emuldec);
-      default:
-        break;
-  }
-
-  return ret;
-}
-
-gboolean
-gst_emuldec_register (GstPlugin *plugin)
-{
-  GTypeInfo typeinfo = {
-    sizeof (GstEmulDecClass),
-    (GBaseInitFunc) gst_emuldec_base_init,
-    NULL,
-    (GClassInitFunc) gst_emuldec_class_init,
-    NULL,
-    NULL,
-    sizeof (GstEmulDec),
-    0,
-    (GInstanceInitFunc) gst_emuldec_init,
-  };
-
-  GType type;
-  gchar *type_name;
-  gint rank = GST_RANK_PRIMARY;
-
-  /* register element */
-  {
-    int codec_fd, codec_cnt = 0;
-    int func_type = CODEC_QUERY;
-    int index = 0, size = 0;
-    uint16_t codec_name_len, codec_longname_len;
-    void *buf;
-    CodecInfo *codec_info;
-
-    codec_fd = open(CODEC_DEV, O_RDWR);
-    if (codec_fd < 0) {
-      perror("[gst-emul-codec] failed to open codec device");
-      return FALSE;
-    }
-
-    buf = mmap (NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, codec_fd, 0);
-    if (!buf) {
-      perror("[gst-emul-codec] failed to mmap");
-    }
-
-    write (codec_fd, &func_type, sizeof(int));
-    memcpy (&codec_cnt, buf, sizeof(int));
-    size = sizeof(uint32_t);
-
-    codec_info = g_malloc0 (codec_cnt * sizeof(CodecInfo));
-    codec = codec_info;
-    for (; index < codec_cnt; index++) {
-      memcpy(&codec_info[index].media_type, (uint8_t *)buf + size, sizeof(uint16_t));
-      size += sizeof(uint16_t);
-      memcpy(&codec_info[index].codec_type, (uint8_t *)buf + size, sizeof(uint16_t));
-      size += sizeof(uint16_t);
-      memcpy(&codec_name_len, (uint8_t *)buf + size, sizeof(uint16_t));
-      size += sizeof(uint16_t);
-      memcpy(&codec_longname_len, (uint8_t *)buf + size, sizeof(uint16_t));
-      size += sizeof(uint16_t);
-      memcpy(&codec_info[index].codec_name, (uint8_t *)buf + size, codec_name_len);
-      size += 32;
-      memcpy(&codec_info[index].codec_longname, (uint8_t *)buf + size, codec_longname_len);
-      size += 64;
-      memcpy (&codec_info[index].sample_fmts, (uint8_t *)buf + size, 8);
-      size += 8;
-    }
-
-    for (index = 0; index < codec_cnt; index++) {
-      if (!codec_info[index].codec_type) {
-        continue;
-      }
-
-      type_name = g_strdup_printf ("tzdec_%s", codec_info[index].codec_name);
-      type = g_type_from_name (type_name);
-      if (!type) {
-        type = g_type_register_static (GST_TYPE_ELEMENT, type_name, &typeinfo, 0);
-        g_type_set_qdata (type, GST_EMULDEC_PARAMS_QDATA, (gpointer) &codec_info[index]);
-      }
-
-      if (!gst_element_register (plugin, type_name, rank, type)) {
-        g_free (type_name);
-        return FALSE;
-      }
-      g_free (type_name);
-    }
-
-    munmap (buf, 4096);
-    close (codec_fd);
-  }
-
-  return TRUE;
-}
-
-#if 0
-void *gst_emul_codec_query (GstEmulDec *emuldec)
-{
-  int fd, codec_cnt = 0;
-  int size = 0, i;
-  void *mmapbuf;
-  int func_type = CODEC_QUERY;
-  CodecInfo *codec_info;
-
-  CODEC_LOG(2, "enter: %s\n", __func__);
-
-  fd = emuldec->codecbuf.fd;
-  mmapbuf = emuldec->codecbuf.mmapbuf;
-  if (fd < 0) {
-//    CODEC_LOG(1, "failed to get %s fd\n", CODEC_DEV);
-    GST_ERROR_OBJECT(emuldec, "failed to get %s fd.\n", CODEC_DEV);
-    return NULL;
-  }
-
-  if (!mmapbuf) {
-//    CODEC_LOG(1, "failed to get mmaped memory address\n");
-    GST_ERROR_OBJECT(emuldec, "failed to get mmaped memory address.\n");
-    return NULL;
-  }
-
-  write (fd, &func_type, sizeof(func_type));
-
-  memcpy (&codec_cnt, mmapbuf, sizeof(uint32_t));
-  size += sizeof(uint32_t);
-  codec_info = g_malloc0 (codec_cnt * sizeof(CodecInfo));
-
-  for (i = 0; i < codec_cnt; i++) {
-    uint16_t codec_name_len, codec_longname_len;
-
-    memcpy (&codec_info[i].media_type, (uint8_t *)mmapbuf + size, sizeof(uint16_t));
-    size += sizeof(uint16_t);
-    memcpy (&codec_info[i].codec_type, (uint8_t *)mmapbuf + size, sizeof(uint16_t));
-    size += sizeof(uint16_t);
-    memcpy (&codec_name_len, (uint8_t *)mmapbuf + size, sizeof(uint16_t));
-    size += sizeof(uint16_t);
-    memcpy (&codec_longname_len, (uint8_t *)mmapbuf + size, sizeof(uint16_t));
-    size += sizeof(uint16_t);
-    memcpy (codec_info[i].codec_name, (uint8_t *)mmapbuf + size, codec_name_len);
-    size += 32;
-    memcpy (codec_info[i].codec_longname, (uint8_t *)mmapbuf + size, codec_longname_len);
-    size += 64;
-    memcpy (&codec_info[i].sample_fmts, (uint8_t *)mmapbuf + size, 8);
-    size += 8;
-  }
-
-  CODEC_LOG(2, "leave: %s\n", __func__);
-
-  return codec_info;
-}
-#endif
-
-int gst_emul_codec_device_open (GstEmulDec *emuldec)
-{
-  int fd;
-  int width, height;
-  void *mmapbuf;
-  uint32_t bufsize;
-
-  CODEC_LOG(2, "enter: %s\n", __func__);
-
-  width = emuldec->format.video.width;
-  height = emuldec->format.video.height;
-  bufsize = ((width * height * 3) / 2) + 32;
-
-  if ((fd = open(CODEC_DEV, O_RDWR)) < 0) {
-    perror("[gst-emul-codec] failed to open codec device");
-//    CODEC_LOG(1, "failed to open %s, fd:%d, err:%d\n", CODEC_DEV, fd, errno);
-    GST_ERROR("failed to open %s, fd:%d, err:%d\n", CODEC_DEV, fd, errno);
-
-    return -1;
-  }
-//  CODEC_LOG(2, "succeeded to open %s, ret:%d\n", CODEC_DEV, fd);
-  GST_DEBUG("succeeded to open %s.\n", CODEC_DEV);
-
-  mmapbuf = mmap (NULL, bufsize, PROT_READ | PROT_WRITE,
-                  MAP_SHARED, fd, 0);
-  if (!mmapbuf) {
-//    CODEC_LOG(1, "failure mmap() func\n");
-    perror("[gst-emul-codec] failed to map memory with codec device.");
-    GST_ERROR("failure mmap() func.\n");
-    return -1;
-  }
-
-  emuldec->codecbuf.fd = fd;
-  emuldec->codecbuf.buffer = mmapbuf;
-
-  return 0;
-}
-
-int gst_emul_codec_init (GstEmulDec *emuldec, CodecInfo *codecinfo)
-{
-  int fd;
-  int size = 0, ret;
-  guint extradata_size = 0;
-  guint8 *extradata = NULL;
-  void *mmapbuf;
-  int func_type = CODEC_INIT;
-
-  CODEC_LOG(2, "enter: %s\n", __func__);
-
-  fd = emuldec->codecbuf.fd;
-  if (fd < 0) {
-    GST_ERROR_OBJECT(emuldec, "failed to get %s fd.\n", CODEC_DEV);
-    return -1;
-  }
-
-  mmapbuf = emuldec->codecbuf.buffer;
-  if (!mmapbuf) {
-    GST_ERROR_OBJECT(emuldec, "failed to get mmaped memory address.\n");
-    return -1;
-  }
-
-  extradata_size = emuldec->extradata_size;
-  extradata = emuldec->extradata;
-
-  GST_DEBUG_OBJECT(emuldec, "extradata: %p, extradata_size: %d\n", extradata, extradata_size);
-
-  /* copy basic info to initialize codec on the host side.
-   * e.g. width, height, FPS ant etc. */
-  memcpy ((uint8_t *)mmapbuf, &codecinfo->media_type, sizeof(codecinfo->media_type));
-  size = sizeof(codecinfo->media_type);
-  memcpy ((uint8_t *)mmapbuf + size, &codecinfo->codec_type, sizeof(codecinfo->codec_type));
-  size += sizeof(codecinfo->codec_type);
-  memcpy ((uint8_t *)mmapbuf + size, codecinfo->codec_name, sizeof(codecinfo->codec_name));
-  size += sizeof(codecinfo->codec_name);
-
-  if (codecinfo->media_type == AVMEDIA_TYPE_VIDEO) {
-         memcpy ((uint8_t *)mmapbuf + size, &emuldec->format.video, sizeof(emuldec->format.video));
-               size += sizeof(emuldec->format.video);
-  } else if (codecinfo->media_type == AVMEDIA_TYPE_AUDIO) {
-         memcpy ((uint8_t *)mmapbuf + size, &emuldec->format.audio, sizeof(emuldec->format.audio));
-               size += sizeof(emuldec->format.audio);
-  } else {
-    GST_ERROR_OBJECT(emuldec, "media type is unknown.\n");
-               return -1;
-       }
-
-  if (extradata) {
-    memcpy ((uint8_t *)mmapbuf + size, &extradata_size, sizeof(extradata_size));
-    size += sizeof(extradata_size);
-    memcpy ((uint8_t *)mmapbuf + size, extradata, extradata_size);
-  }
-
-  ret = write (fd, &func_type, sizeof(func_type));
-
-  CODEC_LOG(2, "leave: %s\n", __func__);
-
-  return ret;
-}
-
-int gst_emul_codec_device_close (GstEmulDec *emuldec)
-{
-  int width, height;
-  uint32_t bufsize;
-  int fd, ret = 0;
-  void *mmapbuf;
-
-  CODEC_LOG(2, "enter: %s\n", __func__);
-
-  fd = emuldec->codecbuf.fd;
-  if (fd < 0) {
-//    CODEC_LOG(1, "failed to get %s fd\n", CODEC_DEV);
-    GST_ERROR("failed to get %s fd.\n", CODEC_DEV);
-    return -1;
-  }
-
-  mmapbuf = emuldec->codecbuf.buffer;
-  if (!mmapbuf) {
-//    CODEC_LOG(1, "failed to get mmaped memory address\n");
-    GST_ERROR("failed to get mmaped memory address.\n");
-    return -1;
-  }
-
-  width = emuldec->format.video.width;
-  height = emuldec->format.video.height;
-  bufsize = ((width * height * 3) / 2) + 32;
-
-//  CODEC_LOG(2, "release mmaped memory region of %s\n", CODEC_DEV);
-  GST_DEBUG("release mmaped memory region of %s.\n", CODEC_DEV);
-  ret = munmap (mmapbuf, bufsize);
-  if (ret != 0) {
-//    CODEC_LOG(1, "failed to release mmaped memory region of %s\n", CODEC_DEV);
-    GST_ERROR("failed to release memory mapped region of %s.\n", CODEC_DEV);
-  }
-
-//  CODEC_LOG(2, "close %s fd\n", CODEC_DEV);
-
-  GST_DEBUG("close %s fd.\n", CODEC_DEV);
-  ret = close(fd);
-  if (ret != 0) {
-//    CODEC_LOG(1, "failed to close %s\n", CODEC_DEV);
-    GST_ERROR("failed to close %s\n", CODEC_DEV);
-  }
-
-  CODEC_LOG(2, "leave: %s\n", __func__);
-
-  return 0;
-}
-
-void gst_emul_codec_deinit (GstEmulDec *emuldec)
-{
-  int fd, ret;
-  int func_type = CODEC_DEINIT;
-  void *mmapbuf;
-
-  CODEC_LOG(2, "enter: %s\n", __func__);
-
-  fd = emuldec->codecbuf.fd;
-  mmapbuf = emuldec->codecbuf.buffer;
-
-  if (fd < 0) {
-//    CODEC_LOG(1, "failed to get %s fd\n", CODEC_DEV);
-    GST_ERROR("failed to get %s fd.\n", CODEC_DEV);
-    return;
-  }
-
-  if (!mmapbuf) {
-//    CODEC_LOG(1, "failed to get mmaped memory address\n");
-    GST_ERROR("failed to get mmaped memory address.\n");
-    return;
-  }
-
-  ret = write (fd, &func_type, sizeof(func_type));
-
-  /* close device fd and release mapped memory region */
-  gst_emul_codec_device_close (emuldec);
-
-  CODEC_LOG(2, "leave: %s\n", __func__);
-}
-
-int gst_emul_decode_video (GstEmulDec *emuldec, guint8 *in_buf, guint in_size,
-        GstBuffer **out_buf, GstTSInfo *dec_info)
-{
-  int fd, size = 0, ret;
-  guint out_size;
-  int api_index = CODEC_DECODE_VIDEO;
-  void *mmapbuf;
-  *out_buf = NULL;
-
-  CODEC_LOG(2, "enter: %s\n", __func__);
-
-#if 0
-  GstCaps *caps;
-  caps = gst_emul_codectype_to_caps (emuldec, emuldec->codecinfo);
-  if (!gst_pad_set_caps (emuldec->srcpad, caps)) {
-      GST_ERROR_OBJECT(emuldec, "failed to set caps for srcpad.\n");
-//      gst_buffer_unref (buffer);
-//     return GST_FLOW_NOT_NEGOTIATED;
-  }
-#endif
-
-  fd = emuldec->codecbuf.fd;
-  if (fd < 0) {
-    GST_ERROR_OBJECT(emuldec, "failed to get %s fd\n", CODEC_DEV);
-    return -1;
-  }
-
-  mmapbuf = emuldec->codecbuf.buffer;
-  if (!mmapbuf) {
-    GST_ERROR_OBJECT(emuldec, "failed to get mmaped memory address\n");
-    return -1;
-  }
-
-  memcpy ((uint8_t *)mmapbuf + size, &in_size, sizeof(guint));
-  size += sizeof(guint);
-  memcpy ((uint8_t *)mmapbuf + size, &dec_info->timestamp, sizeof(GstClockTime));
-  size += sizeof(GstClockTime);
-  memcpy ((uint8_t *)mmapbuf + size, in_buf, in_size);
-
-  /* provide raw image for decoding to qemu */
-  ret = write (fd, &api_index, sizeof(api_index));
-
-  memcpy (&out_size, (uint8_t *)mmapbuf, sizeof(out_size));
-  size = sizeof(out_size);
-  printf("outbuf size: %d\n", out_size);
-
-  ret = gst_pad_alloc_buffer_and_set_caps (emuldec->srcpad,
-            GST_BUFFER_OFFSET_NONE, out_size,
-            GST_PAD_CAPS (emuldec->srcpad), out_buf);
-
-  gst_buffer_set_caps (*out_buf, GST_PAD_CAPS (emuldec->srcpad));
-
-  if (GST_BUFFER_DATA(*out_buf)) {
-    GST_DEBUG_OBJECT(emuldec, "copy decoded frame into out_buf.\n");
-    memcpy (GST_BUFFER_DATA(*out_buf), (uint8_t *)mmapbuf + size, out_size);
-  } else {
-    GST_ERROR_OBJECT(emuldec, "failed to allocate output buffer.\n");
-  }
-
-  CODEC_LOG(2, "leave: %s\n", __func__);
-
-  return ret;
-}
-
-int gst_emul_decode_audio (GstEmulDec *emuldec, guint8 *in_buf, guint in_size,
-    GstBuffer **out_buf, GstTSInfo *dec_info)
-{
-  int fd, size = 0;
-  guint out_size = 0;
-  gint len = -1, have_data = 0;
-  int api_index = CODEC_DECODE_AUDIO;
-  void *mmapbuf = NULL;
-
-  fd = emuldec->codecbuf.fd;
-  if (fd < 0) {
-    GST_ERROR_OBJECT(emuldec, "failed to get %s fd\n", CODEC_DEV);
-    return -1;
-  }
-
-  mmapbuf = emuldec->codecbuf.buffer;
-  if (!mmapbuf) {
-    GST_ERROR_OBJECT(emuldec, "failed to get mmaped memory address\n");
-    return -1;
-  }
-
-  memcpy ((uint8_t *)mmapbuf + size, &in_size, sizeof(guint));
-  size += sizeof(guint);
-  memcpy ((uint8_t *)mmapbuf + size, in_buf, in_size);
-
-  write (fd, &api_index, sizeof(api_index));
-
-  memcpy (&out_size, (uint8_t *)mmapbuf + size, sizeof(out_size));
-  size = sizeof(out_size);
-  memcpy (&len, (uint8_t *)mmapbuf + size, sizeof(len));
-  size += sizeof(len);
-  memcpy (&have_data, (uint8_t *)mmapbuf + size, sizeof(have_data));
-       size += sizeof(have_data);
-
-  printf("decode audio, out_size: %d, len: %d, have_data: %d\n", out_size, len, have_data);
-
-  *out_buf = gst_buffer_new();
-  GST_BUFFER_DATA (*out_buf) = GST_BUFFER_MALLOCDATA (*out_buf) = g_malloc0 (out_size);
-  GST_BUFFER_SIZE (*out_buf) = out_size;
-  GST_BUFFER_FREE_FUNC (*out_buf) = g_free;
-  if (GST_PAD_CAPS(emuldec->srcpad)) {
-    gst_buffer_set_caps (*out_buf, GST_PAD_CAPS (emuldec->srcpad));
-  }
-
-  if (GST_BUFFER_DATA(*out_buf)) {
-    CODEC_LOG(2, "copy decoding audio data.\n");
-//    memcpy (GST_BUFFER_DATA(*out_buf), (uint8_t *)mmapbuf + size, have_data);
-    memcpy (GST_BUFFER_DATA(*out_buf), (uint8_t *)mmapbuf + size, out_size);
-  } else {
-    CODEC_LOG(1, "failed to allocate output buffer\n");
-  }
-
-  if (len >= 0 && have_data > 0) {
-    GstCaps *caps = NULL;
-
-    caps = gst_emul_codectype_to_caps (emuldec, emuldec->codecinfo);
-    if (!gst_pad_set_caps (emuldec->srcpad, caps)) {
-      CODEC_LOG(1, "failed to set caps to srcpad.\n");
-    } else {
-      gst_caps_unref (caps);
-    }
-
-    GstClockTime out_timestamp, out_duration;
-    gint64 out_offset;
-
-    GST_BUFFER_SIZE (*out_buf) = have_data;
-
-    if (GST_CLOCK_TIME_IS_VALID (dec_info->timestamp)) {
-      out_timestamp = dec_info->timestamp;
-    } else {
-      // TODO
-    }
-
-    emuldec->format.audio.depth = 2;
-
-    CODEC_LOG(1, "depth: %d, channels: %d, sample_rate: %d\n",
-              emuldec->format.audio.depth,
-              emuldec->format.audio.channels,
-              emuldec->format.audio.samplerate);
-
-    out_duration = gst_util_uint64_scale (have_data, GST_SECOND,
-              emuldec->format.audio.depth * emuldec->format.audio.channels *
-              emuldec->format.audio.samplerate);
-    out_offset = dec_info->offset;
-
-    GST_BUFFER_TIMESTAMP (*out_buf) = out_timestamp;
-    GST_BUFFER_DURATION (*out_buf) = out_duration;
-    GST_BUFFER_OFFSET (*out_buf) = out_offset;
-    gst_buffer_set_caps (*out_buf, GST_PAD_CAPS (emuldec->srcpad));
-
-    if (GST_CLOCK_TIME_IS_VALID (out_timestamp)) {
-      // TODO
-//       printf("out timestamp is valid.\n");
-    }
-
-    GST_LOG_OBJECT (emuldec,
-            "timestamp:%" GST_TIME_FORMAT ", duration:%" GST_TIME_FORMAT
-            ", size %u", GST_TIME_ARGS (out_timestamp), GST_TIME_ARGS (out_duration),
-            GST_BUFFER_SIZE (*out_buf));
-
-#if 0    
-    {
-      GstClockTime stop;
-      gint64 diff, ctime, cstop;
-
-      stop = out_timestamp + out_duration;
-    }
-#endif
-
-  } else {
-    CODEC_LOG(1, "failed to decode audio.\n");
-    gst_buffer_unref (*out_buf);
-    *out_buf = NULL;
-  }
-#if 0
-    /* the next timestamp we'll use when interpolating */
-    if (GST_CLOCK_TIME_IS_VALID (out_timestamp))
-        emuldec->next_out = out_timestamp + out_duration;
-
-    /* now see if we need to clip the buffer against the segment boundaries. */
-    if (G_UNLIKELY (!clip_audio_buffer (emuldec, *out_buf, out_timestamp,
-                    out_duration)))
-        goto clipped;
-    } else {
-      gst_buffer_unref (*out_buf);
-      *out_buf = NULL;
-    }
-
-    /* If we don't error out after the first failed read with the AAC decoder,
-     * we must *not* carry on pushing data, else we'll cause segfaults... */
-    if (len == -1 && (in_plugin->id == CODEC_ID_AAC
-              || in_plugin->id == CODEC_ID_AAC_LATM)) {
-        GST_ELEMENT_ERROR (emuldec, STREAM, DECODE, (NULL),
-              ("Decoding of AAC stream by FFMPEG failed."));
-        *ret = GST_FLOW_ERROR;
-    }
-
-beach:
-  GST_DEBUG_OBJECT (emuldec, "return flow %d, out %p, len %d",
-      *ret, *out_buf, len);
-  return len;
-
-  /* ERRORS */
-clipped:
-  {
-    GST_DEBUG_OBJECT (emuldec, "buffer clipped");
-    gst_buffer_unref (*out_buf);
-    *out_buf = NULL;
-    goto beach;
-  }
-#endif
-
-  return len;
-}
-
-GstCaps *
-gst_emul_video_caps_new (CodecInfo *info, const char *mimetype,
-        const char *fieldname, ...)
-{
-  GstStructure *structure = NULL;
-  GstCaps *caps = NULL;
-  gint i;
-  va_list var_args;
-
-  if (g_str_has_prefix(info->codec_name, "h263")) {
-    /* 128x96, 176x144, 352x288, 704x576, and 1408x1152. slightly reordered
-     * because we want automatic negotiation to go as close to 320x240 as
-     * possible. */
-    const static gint widths[] = { 352, 704, 176, 1408, 128 };
-    const static gint heights[] = { 288, 576, 144, 1152, 96 };
-    GstCaps *temp;
-    gint n_sizes = G_N_ELEMENTS (widths);
-
-    caps = gst_caps_new_empty ();
-    for (i = 0; i < n_sizes; i++) {
-      temp = gst_caps_new_simple (mimetype,
-                    "width", G_TYPE_INT, widths[i],
-                    "height", G_TYPE_INT, heights[i],
-                    "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
-
-      gst_caps_append (caps, temp);
-    }
-  }
-
-  /* no fixed caps or special restrictions applied;
-   * default unfixed setting */
-  if (!caps) {
-    GST_DEBUG ("Creating default caps");
-    caps = gst_caps_new_simple (mimetype,
-                "width", GST_TYPE_INT_RANGE, 16, 4096,
-                "height", GST_TYPE_INT_RANGE, 16, 4096,
-                "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
-  }
-
-  for (i = 0; i < gst_caps_get_size (caps); i++) {
-    va_start (var_args, fieldname);
-    structure = gst_caps_get_structure (caps, i);
-    gst_structure_set_valist (structure, fieldname, var_args);
-    va_end (var_args);
-  }
-
-  return caps;
-}
-
-GstCaps *
-gst_emul_audio_caps_new (CodecInfo *info, const char *mimetype,
-        const char *fieldname, ...)
-{
-  GstStructure *structure = NULL;
-  GstCaps *caps = NULL;
-  gint i;
-  va_list var_args;
-
-  gint maxchannels = 2;
-  const gint *rates = NULL;
-  gint n_rates = 0;
-
-  if (strcmp(info->codec_name, "aac") == 0) {
-    maxchannels = 6;
-  } else if (g_str_has_prefix(info->codec_name, "ac3")) {  
-    const static gint l_rates[] = { 48000, 44100, 32000 };
-    maxchannels = 6;
-    n_rates = G_N_ELEMENTS (l_rates);
-    rates = l_rates;
-  }
-  caps = gst_caps_new_simple(mimetype,
-          "channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL);
-  if (n_rates) {
-    GValue list = { 0, };
-    GstStructure *structure;
-
-    g_value_init(&list, GST_TYPE_LIST);
-    for (i = 0; i < n_rates; i++) {
-      GValue v = { 0, };
-    
-      g_value_init(&v, G_TYPE_INT);
-      g_value_set_int(&v, rates[i]);
-      gst_value_list_append_value(&list, &v);
-      g_value_unset(&v);
-    }
-    structure = gst_caps_get_structure(caps, 0);
-    gst_structure_set_value(structure, "rate", &list);
-    g_value_unset(&list);
-  } else {
-    gst_caps_set_simple(caps, "rate", GST_TYPE_INT_RANGE, 4000, 96000, NULL);
-  }
-
-  for (i = 0; i < gst_caps_get_size (caps); i++) {
-    va_start (var_args, fieldname);
-    structure = gst_caps_get_structure (caps, i);
-    gst_structure_set_valist (structure, fieldname, var_args);
-    va_end (var_args);
-  }
-
-  return caps;
-}
-
-static GstCaps *
-gst_emul_smpfmt_to_caps (int8_t sample_fmt, CodecInfo *info)
-{
-  GstCaps *caps = NULL;
-
-  int bpp = 0;
-  gboolean integer = TRUE;
-  gboolean signedness = FALSE;
-
-  switch (sample_fmt) {
-  case SAMPLE_FMT_S16:
-    signedness = TRUE;
-    bpp = 16;
-    break;
-  case SAMPLE_FMT_S32:
-    signedness = TRUE;
-    bpp = 32;
-    break;
-  case SAMPLE_FMT_FLT:
-    integer = FALSE;
-    bpp = 32;
-    break;
-  case SAMPLE_FMT_DBL:
-    integer = FALSE;
-    bpp = 64;
-    break;
-  }
-
-  if (bpp) {
-    if (integer) {
-      caps = gst_emul_audio_caps_new (info, "audio/x-raw-int",
-          "signed", G_TYPE_BOOLEAN, signedness,
-          "endianness", G_TYPE_INT, G_BYTE_ORDER,
-          "width", G_TYPE_INT, bpp, "depth", G_TYPE_INT, bpp, NULL);
-    } else {
-      caps = gst_emul_audio_caps_new (info, "audio/x-raw-float",
-          "endianness", G_TYPE_INT, G_BYTE_ORDER,
-          "width", G_TYPE_INT, bpp, NULL);
-    }
-  }
-  
-  if (caps != NULL) {
-    GST_LOG ("caps for sample_fmt=%d: %" GST_PTR_FORMAT, sample_fmt, caps);
-  } else {
-    GST_LOG ("No caps found for sample_fmt=%d", sample_fmt);
-  }
-
-  return caps;
-}
-
-GstCaps *
-gst_emul_codectype_to_audio_caps (CodecInfo *info)
-{
-  GstCaps *caps = NULL;
-
-  if (info->sample_fmts[0] != 0) {
-    GstCaps *temp;
-    int i;
-    caps = gst_caps_new_empty ();
-    for (i = 0; info->sample_fmts[i] != -1; i++) {
-               temp = gst_emul_smpfmt_to_caps (info->sample_fmts[i], info);
-               if (temp != NULL) {
-                       gst_caps_append (caps, temp);
-               }
-    }
-  } else {
-    GstCaps *temp;
-    int i;
-
-    caps = gst_caps_new_empty ();
-    for (i = 0; i <= SAMPLE_FMT_DBL; i++) {
-      temp = gst_emul_smpfmt_to_caps (i, info);
-      if (temp != NULL) {
-        gst_caps_append (caps, temp);
-      }
-    }
-  }
-  
-  return caps;
-}
-
-GstCaps *
-gst_emul_codecname_to_caps (CodecInfo *info)
-{
-  GstCaps *caps = NULL;
-  gchar *mime_type = NULL;
-
-  if (strcmp(info->codec_name, "mpegvideo") == 0) {
-
-    caps = gst_emul_video_caps_new (info, "video/mpeg",
-                "mpegversion", G_TYPE_INT, 1,
-                "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
-
-  } else if (strcmp(info->codec_name, "mpeg4") == 0) {
-
-    caps = gst_emul_video_caps_new (info, "video/mpeg",
-                "mpegversion", G_TYPE_INT, 4,
-                "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
-    if (info->codec_type) { // decode
-      gst_caps_append (caps, gst_emul_video_caps_new (info, "video/x-divx",
-                        "divxversion", GST_TYPE_INT_RANGE, 4, 5, NULL));
-      gst_caps_append (caps, gst_emul_video_caps_new
-                    (info, "video/x-xvid", NULL));
-      gst_caps_append (caps, gst_emul_video_caps_new
-                    (info, "video/x-3ivx", NULL));
-    } else { // encode
-      gst_caps_append (caps, gst_emul_video_caps_new (info, "video/x-divx",
-                        "divxversion", G_TYPE_INT, 5, NULL));
-    }
-
-  } else if (strcmp(info->codec_name, "h263") == 0) {
-
-    if (info->codec_type) {
-      caps = gst_emul_video_caps_new (info, "video/x-h263",
-                    "variant", G_TYPE_STRING, "itu", NULL);
-    } else {
-      caps = gst_emul_video_caps_new (info, "video/x-h263",
-                    "variant", G_TYPE_STRING, "itu",
-                    "h263version", G_TYPE_STRING, "h263", NULL);
-    }
-
-  } else if (strcmp(info->codec_name, "h263p") == 0) {
-
-      caps = gst_emul_video_caps_new (info, "video/x-h263",
-                "variant", G_TYPE_STRING, "itu",
-                "h263version", G_TYPE_STRING, "h263p", NULL);
-
-  } else if (strcmp(info->codec_name, "h264") == 0) {
-
-      caps = gst_emul_video_caps_new (info, "video/x-h264", NULL);
-
-  } else if (g_str_has_prefix(info->codec_name, "msmpeg4")) { // msmpeg4v1,m msmpeg4v2, msmpeg4
-
-    gint version;
-
-    if (strcmp(info->codec_name, "msmpeg4v1") == 0) {
-      version = 41;
-    } else if (strcmp(info->codec_name, "msmpeg4v2") == 0) {
-      version = 42;
-    } else {
-      version = 43;
-    }
-
-    caps = gst_emul_video_caps_new (info, "video/x-msmpeg",
-                "msmpegversion", G_TYPE_INT, version, NULL);
-    if (info->codec_type && !strcmp(info->codec_name, "msmpeg4")) {
-       gst_caps_append (caps, gst_emul_video_caps_new (info, "video/x-divx",
-                        "divxversion", G_TYPE_INT, 3, NULL));
-    }
-
-  } else if (strcmp(info->codec_name, "wmv3") == 0) {
-
-    caps = gst_emul_video_caps_new (info, "video/x-wmv",
-                "wmvversion", G_TYPE_INT, 3, NULL);
-
-  } else if (strcmp(info->codec_name, "vc1") == 0) {
-
-    caps = gst_emul_video_caps_new (info, "video/x-wmv",
-                "wmvversion", G_TYPE_INT, 3, "format", GST_TYPE_FOURCC,
-                GST_MAKE_FOURCC ('W', 'V', 'C', '1'),  NULL);
-#if 0
-  } else if (strcmp(info->codec_name, "vp3") == 0) {
-
-    mime_type = g_strdup ("video/x-vp3");
-
-  } else if (strcmp(info->codec_name, "vp8") == 0) {
-
-    mime_type = g_strdup ("video/x-vp8");
-#endif
-  } else if (strcmp(info->codec_name, "mp3") == 0) {
-
-    mime_type = g_strdup ("audio/mpeg");
-    if (info->codec_type) {
-      caps = gst_caps_new_simple(mime_type, "mpegversion",
-              G_TYPE_INT, 1, "layer", GST_TYPE_INT_RANGE, 1, 3, NULL);
-    }
-  } else if (strcmp(info->codec_name, "mp3adu") == 0) {
-
-    mime_type = g_strdup_printf ("audio/x-gst_ff-%s", info->codec_name);
-    caps = gst_emul_audio_caps_new (info, mime_type, NULL);
-  } else if (strcmp(info->codec_name, "aac") == 0) {
-
-    mime_type = g_strdup ("audio/mpeg");
-    caps = gst_emul_audio_caps_new (info, mime_type, NULL);
-    if (info->codec_type) {
-        GValue arr = { 0, };
-        GValue item = { 0, };
-
-        g_value_init (&arr, GST_TYPE_LIST);
-        g_value_init (&item, G_TYPE_INT);
-        g_value_set_int (&item, 2);
-        gst_value_list_append_value (&arr, &item);
-        g_value_set_int (&item, 4);
-        gst_value_list_append_value (&arr, &item);
-        g_value_unset (&item);
-
-        gst_caps_set_value (caps, "mpegversion", &arr);
-        g_value_unset (&arr);
-
-        g_value_init (&arr, GST_TYPE_LIST);
-        g_value_init (&item, G_TYPE_STRING);
-        g_value_set_string (&item, "raw");
-        gst_value_list_append_value (&arr, &item);
-        g_value_set_string (&item, "adts");
-        gst_value_list_append_value (&arr, &item);
-        g_value_set_string (&item, "adif");
-        gst_value_list_append_value (&arr, &item);
-        g_value_unset (&item);
-
-        gst_caps_set_value (caps, "stream-format", &arr);
-        g_value_unset (&arr);
-    }
-
-  } else if (strcmp(info->codec_name, "ac3") == 0) {
-
-    mime_type = g_strdup ("audio/x-ac3");
-    caps = gst_emul_audio_caps_new (info, mime_type, NULL);
-
-  } else if (g_str_has_prefix(info->codec_name, "wmav")) {
-    gint version = 1;
-    if (strcmp(info->codec_name, "wmav2") == 0) {
-      version = 2;
-    }
-    mime_type = g_strdup ("audio/x-wma");
-    caps = gst_emul_audio_caps_new (info, mime_type, "wmaversion",
-          G_TYPE_INT, version, "block_align", GST_TYPE_INT_RANGE, 0, G_MAXINT,
-          "bitrate", GST_TYPE_INT_RANGE, 0, G_MAXINT, NULL);
-
-  } else {
-    GST_ERROR("failed to new caps for %s.\n", info->codec_name);
-  }
-  
-  if (mime_type) {
-    g_free(mime_type);
-  }
-
-  return caps;
-}
index 1e69249d63f62a2c38f8fe3877c83139545132b1..ea8845da330f7214ee21482b5d9a11cdf721b0f6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * GStreamer codec plugin for Tizen Emulator.
  *
- * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Contact:
  * KiTae Kim <kt920.kim@samsung.com>
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
- */
-
-/* First, include the header file for the plugin, to bring in the
- * object definition and other useful things.
- */
-
-/*
  *
  * Contributors:
  * - S-Core Co., Ltd
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
-#include <gst/gst.h>
+
 #include "gstemulcommon.h"
-// #include "gstemuldev.h"
+#include "gstemuldev.h"
 
-#define CODEC_DEV                              "/dev/codec"
-#define CODEC_MEM_SIZE 16 * 1024 * 1024
 
-int gst_emul_codec_device_open (CodecDev *info)
+int
+gst_emul_codec_device_open (CodecDevice *dev)
 {
   int fd;
   void *mmapbuf;
 
-  CODEC_LOG(2, "enter: %s\n", __func__);
+  printf("enter: %s\n", __func__);
 
   if ((fd = open(CODEC_DEV, O_RDWR)) < 0) {
     perror("Failed to open codec device.");
     return -1;
   }
+  GST_DEBUG("succeeded to open %s.\n", CODEC_DEV);
 
-       GST_DEBUG("succeeded to open %s.\n", CODEC_DEV);
-  mmapbuf = mmap (NULL, CODEC_MEM_SIZE, PROT_READ | PROT_WRITE,
+  mmapbuf = mmap (NULL, dev->buf_size, PROT_READ | PROT_WRITE,
                   MAP_SHARED, fd, 0);
   if (!mmapbuf) {
     perror("Failed to map device memory of codec.");
+    close(fd);
     return -1;
   }
+  GST_DEBUG("succeeded to map device memory.\n");
 
-  info->fd = fd;
-  info->buffer = mmapbuf;
+  dev->fd = fd;
+  dev->buf = mmapbuf;
 
   return 0;
 }
 
-int gst_emul_codec_device_close (CodecDev *info)
+int
+gst_emul_codec_device_close (CodecDevice *dev)
 {
   int fd = 0;
   void *mmapbuf = NULL;
 
-  CODEC_LOG(2, "enter: %s\n", __func__);
+  printf("enter: %s\n", __func__);
 
-  fd = info->fd;
+  fd = dev->fd;
   if (fd < 0) {
     GST_ERROR("Failed to get %s fd.\n", CODEC_DEV);
     return -1;
   }
 
-  mmapbuf = info->buffer;
+  mmapbuf = dev->buf;
   if (!mmapbuf) {
     GST_ERROR("Failed to get mmaped memory address.\n");
     return -1;
   }
 
   GST_DEBUG("Release memory region of %s.\n", CODEC_DEV);
-  if (munmap(mmapbuf, CODEC_MEM_SIZE) != 0) {
+  if (munmap(mmapbuf, dev->buf_size) != 0) {
     GST_ERROR("Failed to release memory region of %s.\n", CODEC_DEV);
   }
 
@@ -106,7 +101,7 @@ int gst_emul_codec_device_close (CodecDev *info)
     GST_ERROR("Failed to close %s. fd: %d\n", CODEC_DEV, fd);
   }
 
-  CODEC_LOG(2, "leave: %s\n", __func__);
+  printf("leave: %s\n", __func__);
 
   return 0;
 }
index 6c011828d5e94ad59714f782ace856bc3e90fcfc..0bb3ccc77dbc41c6ff6972800fc1ca5289ba8d84 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Gstreamer codec plugin for Tizen Emulator.
  *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Contact:
  * KiTae Kim <kt920.kim@samsung.com>
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
- */
-
-/* First, include the header file for the plugin, to bring in the
- * object definition and other useful things.
- */
-
-/*
  *
  * Contributors:
  * - S-Core Co., Ltd
  *
  */
 
-int gst_emul_codec_device_open (void *emuldec);
-int gst_emul_codec_device_close (void *emuldec);
+#ifndef __GST_EMUL_DEV_H__
+#define __GST_EMUL_DEV_H__
+
+int gst_emul_codec_device_open (CodecDevice *dev);
+int gst_emul_codec_device_close (CodecDevice *dev);
+
+#endif
diff --git a/src/gstemulnewdec.c b/src/gstemulnewdec.c
new file mode 100644 (file)
index 0000000..9eaf906
--- /dev/null
@@ -0,0 +1,1381 @@
+/*
+ * GStreamer codec plugin for Tizen Emulator.
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * KiTae Kim <kt920.kim@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#include "gstemulcommon.h"
+#include "gstemulutils.h"
+#include "gstemulapi.h"
+
+#define GST_EMULDEC_PARAMS_QDATA g_quark_from_static_string("emuldec-params")
+
+/* indicate dts, pts, offset in the stream */
+typedef struct
+{
+  gint idx;
+  GstClockTime timestamp;
+  GstClockTime duration;
+  gint64 offset;
+} GstTSInfo;
+
+#define GST_TS_INFO_NONE &ts_info_none
+static const GstTSInfo ts_info_none = { -1, -1, -1, -1 };
+
+#define MAX_TS_MASK 0xff
+
+typedef struct _GstEmulDec
+{
+  GstElement element;
+
+  GstPad *srcpad;
+  GstPad *sinkpad;
+
+  CodecContext *context;
+  CodecDevice *dev;
+
+  union {
+    struct {
+      gint width, height;
+      gint clip_width, clip_height;
+      gint par_n, par_d;
+      gint fps_n, fps_d;
+      gint old_fps_n, old_fps_d;
+      gboolean interlaced;
+
+      enum PixelFormat pix_fmt;
+    } video;
+    struct {
+      gint channels;
+      gint samplerate;
+      gint depth;
+    } audio;
+  } format;
+
+  gboolean discont;
+  gboolean clear_ts;
+
+  /* tracking DTS/PTS */
+  GstClockTime next_out;
+
+  /* Qos stuff */
+  gdouble proportion;
+  GstClockTime earliest_time;
+  gint64 processed;
+  gint64 dropped;
+
+
+  /* GstSegment can be used for two purposes:
+   * 1. performing seeks (handling seek events)
+   * 2. tracking playback regions (handling newsegment events)
+   */
+  GstSegment segment;
+
+  GstTSInfo ts_info[MAX_TS_MASK + 1];
+  gint ts_idx;
+
+  /* reverse playback queue */
+  GList *queued;
+
+} GstEmulDec;
+
+typedef struct _GstEmulDecClass
+{
+  GstElementClass parent_class;
+
+  CodecElement *codec;
+  GstPadTemplate *sinktempl;
+  GstPadTemplate *srctempl;
+} GstEmulDecClass;
+
+
+static GstElementClass *parent_class = NULL;
+
+static void gst_emuldec_base_init (GstEmulDecClass *klass);
+static void gst_emuldec_class_init (GstEmulDecClass *klass);
+static void gst_emuldec_init (GstEmulDec *emuldec);
+static void gst_emuldec_finalize (GObject *object);
+
+static gboolean gst_emuldec_setcaps (GstPad *pad, GstCaps *caps);
+
+// sinkpad
+static gboolean gst_emuldec_sink_event (GstPad *pad, GstEvent *event);
+static GstFlowReturn gst_emuldec_chain (GstPad *pad, GstBuffer *buffer);
+
+// srcpad
+static gboolean gst_emuldec_src_event (GstPad *pad, GstEvent *event);
+static GstStateChangeReturn gst_emuldec_change_state (GstElement *element,
+                                                GstStateChange transition);
+
+static gboolean gst_emuldec_negotiate (GstEmulDec *dec, gboolean force);
+
+static gint gst_emuldec_frame (GstEmulDec *emuldec, guint8 *data,
+                              guint size, gint *got_data,
+                              const GstTSInfo *dec_info, GstFlowReturn *ret);
+
+static gboolean gst_emuldec_open (GstEmulDec *emuldec);
+static gboolean gst_emuldec_close (GstEmulDec *emuldec);
+
+
+
+static const GstTSInfo *
+gst_ts_info_store (GstEmulDec *dec, GstClockTime timestamp,
+    GstClockTime duration, gint64 offset)
+{
+  gint idx = dec->ts_idx;
+  dec->ts_info[idx].idx = idx;
+  dec->ts_info[idx].timestamp = timestamp;
+  dec->ts_info[idx].duration = duration;
+  dec->ts_info[idx].offset = offset;
+  dec->ts_idx = (idx + 1) & MAX_TS_MASK;
+
+  return &dec->ts_info[idx];
+}
+
+static const GstTSInfo *
+gst_ts_info_get (GstEmulDec *dec, gint idx)
+{
+  if (G_UNLIKELY (idx < 0 || idx > MAX_TS_MASK))
+    return GST_TS_INFO_NONE;
+
+  return &dec->ts_info[idx];
+}
+
+static void
+gst_emuldec_reset_ts (GstEmulDec *emuldec)
+{
+  emuldec->next_out = GST_CLOCK_TIME_NONE;
+}
+
+static void
+gst_emuldec_update_qos (GstEmulDec *emuldec, gdouble proportion,
+  GstClockTime timestamp)
+{
+  GST_LOG_OBJECT (emuldec, "update QOS: %f, %" GST_TIME_FORMAT,
+      proportion, GST_TIME_ARGS (timestamp));
+
+  GST_OBJECT_LOCK (emuldec);
+  emuldec->proportion = proportion;
+  emuldec->earliest_time = timestamp;
+  GST_OBJECT_UNLOCK (emuldec);
+}
+
+static void
+gst_emuldec_reset_qos (GstEmulDec *emuldec)
+{
+  gst_emuldec_update_qos (emuldec, 0.5, GST_CLOCK_TIME_NONE);
+  emuldec->processed = 0;
+  emuldec->dropped = 0;
+}
+
+static gboolean
+gst_emuldec_do_qos (GstEmulDec *emuldec, GstClockTime timestamp,
+  gboolean *mode_switch)
+{
+  GstClockTimeDiff diff;
+  gdouble proportion;
+  GstClockTime qostime, earliest_time;
+  gboolean res = TRUE;
+
+  *mode_switch = FALSE;
+
+  if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp))) {
+    emuldec->processed++;
+    return TRUE;
+  }
+
+  proportion = emuldec->proportion;
+  earliest_time = emuldec->earliest_time;
+
+  qostime = gst_segment_to_running_time (&emuldec->segment, GST_FORMAT_TIME,
+    timestamp);
+  
+
+  if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (qostime))) {
+    emuldec->processed++;
+    return TRUE;
+  }
+
+  diff = GST_CLOCK_DIFF (qostime, earliest_time);
+
+  if (proportion < 0.4 && diff < 0 ){
+    emuldec->processed++;
+    return TRUE;
+  } else {
+    if (diff >= 0) {
+//      if (emuldec->waiting_for_key) {
+      if (0) {
+        res = FALSE;
+      } else {
+      }
+
+      GstClockTime stream_time, jitter;
+      GstMessage *qos_msg;
+
+      emuldec->dropped++;
+      stream_time =
+          gst_segment_to_stream_time (&emuldec->segment, GST_FORMAT_TIME,
+                  timestamp);
+      jitter = GST_CLOCK_DIFF (qostime, earliest_time);
+      qos_msg =
+          gst_message_new_qos (GST_OBJECT_CAST (emuldec), FALSE, qostime,
+                  stream_time, timestamp, GST_CLOCK_TIME_NONE);
+      gst_message_set_qos_values (qos_msg, jitter, proportion, 1000000);
+      gst_message_set_qos_stats (qos_msg, GST_FORMAT_BUFFERS,
+              emuldec->processed, emuldec->dropped);
+      gst_element_post_message (GST_ELEMENT_CAST (emuldec), qos_msg);
+
+      return res;
+    }
+  }
+}
+
+static void
+clear_queued (GstEmulDec *emuldec)
+{
+  g_list_foreach (emuldec->queued, (GFunc) gst_mini_object_unref, NULL);
+  g_list_free (emuldec->queued);
+  emuldec->queued = NULL;
+}
+
+static GstFlowReturn
+flush_queued (GstEmulDec *emuldec)
+{
+  GstFlowReturn res = GST_FLOW_OK;
+
+  printf("flush queued\n");
+
+  while (emuldec->queued) {
+    GstBuffer *buf = GST_BUFFER_CAST (emuldec->queued->data);
+
+    GST_LOG_OBJECT (emuldec, "pushing buffer %p, offset %"
+      G_GUINT64_FORMAT ", timestamp %"
+      GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT, buf,
+      GST_BUFFER_OFFSET (buf),
+      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
+      GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
+
+    res = gst_pad_push (emuldec->srcpad, buf);
+
+    emuldec->queued =
+      g_list_delete_link (emuldec->queued, emuldec->queued);
+  }
+
+  return res;
+}
+
+static void
+gst_emuldec_drain (GstEmulDec *emuldec)
+{
+  GstEmulDecClass *oclass;
+
+  oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (emuldec));
+
+  // TODO: drain
+#if 1 
+  {
+    gint have_data, len, try = 0;
+
+    do {
+      GstFlowReturn ret;
+
+      len =
+        gst_emuldec_frame (emuldec, NULL, 0, &have_data, &ts_info_none, &ret);
+      if (len < 0 || have_data == 0) {
+        printf("drain. try: %d\n", try);
+
+        break;
+      }
+    } while (try++ < 10);
+  }
+#endif
+
+  if (emuldec->segment.rate < 0.0) {
+    flush_queued (emuldec);
+  }
+}
+
+/*
+ * Implementation
+ */
+static void
+gst_emuldec_base_init (GstEmulDecClass *klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstCaps *sinkcaps, *srccaps;
+  GstPadTemplate *sinktempl, *srctempl;
+  CodecElement *codec;
+  gchar *longname, *classification;
+
+  codec =
+      (CodecElement *)g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
+                                      GST_EMULDEC_PARAMS_QDATA);
+
+  longname = g_strdup_printf ("%s Decoder", codec->longname);
+  classification = g_strdup_printf ("Codec/Decoder/%s",
+                    (codec->media_type == AVMEDIA_TYPE_VIDEO) ?
+                    "Video" : "Audio");
+
+  gst_element_class_set_details_simple (element_class,
+            longname,                                     // longname
+            classification,                               // classification
+            "accelerated codec for Tizen Emulator",       // description
+            "Kitae Kim <kt920.kim@samsung.com>");         // author
+
+  g_free (longname);
+  g_free (classification);
+
+  sinkcaps = gst_emul_codecname_to_caps (codec->name, NULL, FALSE);
+  if (!sinkcaps) {
+    sinkcaps = gst_caps_from_string ("unknown/unknown");
+  }
+
+  switch (codec->media_type) {
+  case AVMEDIA_TYPE_VIDEO:
+    srccaps = gst_caps_from_string ("video/x-raw-rgb; video/x-raw-yuv");
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+    srccaps = gst_emul_codectype_to_audio_caps (NULL, codec->name, FALSE, codec);
+    break;
+  default:
+    GST_LOG("unknown media type.\n");
+    break;
+  }
+
+  if (!srccaps) {
+    srccaps = gst_caps_from_string ("unknown/unknown");
+  }
+
+  sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK,
+                GST_PAD_ALWAYS, sinkcaps);
+  srctempl = gst_pad_template_new ("src", GST_PAD_SRC,
+                GST_PAD_ALWAYS, srccaps);
+
+  gst_element_class_add_pad_template (element_class, srctempl);
+  gst_element_class_add_pad_template (element_class, sinktempl);
+
+  klass->codec = codec;
+  klass->sinktempl = sinktempl;
+  klass->srctempl = srctempl;
+}
+
+static void
+gst_emuldec_class_init (GstEmulDecClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+
+  parent_class = g_type_class_peek_parent (klass);
+
+#if 0
+  gobject_class->set_property = gst_emuldec_set_property
+  gobject_class->get_property = gst_emuldec_get_property
+#endif
+
+  gobject_class->finalize = gst_emuldec_finalize;
+  gstelement_class->change_state = gst_emuldec_change_state;
+}
+
+static void
+gst_emuldec_init (GstEmulDec *emuldec)
+{
+  GstEmulDecClass *oclass;
+
+  oclass = (GstEmulDecClass*) (G_OBJECT_GET_CLASS(emuldec));
+
+  emuldec->sinkpad = gst_pad_new_from_template (oclass->sinktempl, "sink");
+  gst_pad_set_setcaps_function (emuldec->sinkpad,
+    GST_DEBUG_FUNCPTR(gst_emuldec_setcaps));
+  gst_pad_set_event_function (emuldec->sinkpad,
+    GST_DEBUG_FUNCPTR(gst_emuldec_sink_event));
+  gst_pad_set_chain_function (emuldec->sinkpad,
+    GST_DEBUG_FUNCPTR(gst_emuldec_chain));
+
+  emuldec->srcpad = gst_pad_new_from_template (oclass->srctempl, "src") ;
+  gst_pad_use_fixed_caps (emuldec->srcpad);
+  gst_pad_set_event_function (emuldec->srcpad,
+    GST_DEBUG_FUNCPTR(gst_emuldec_src_event));
+
+  gst_element_add_pad (GST_ELEMENT(emuldec), emuldec->sinkpad);
+  gst_element_add_pad (GST_ELEMENT(emuldec), emuldec->srcpad);
+
+  // init
+  emuldec->context = g_malloc0 (sizeof(CodecContext));
+  if (!emuldec->context) {
+    printf("failed to allocate memory.\n");
+  }
+  emuldec->dev = g_malloc0 (sizeof(CodecDevice));
+  if (!emuldec->dev) {
+    printf("failed to allocate memory.\n");
+  }
+
+  emuldec->format.video.par_n = -1;
+  emuldec->format.video.fps_n = -1;
+  emuldec->format.video.old_fps_n = -1;
+
+  emuldec->queued = NULL;
+  gst_segment_init (&emuldec->segment, GST_FORMAT_TIME);
+}
+
+static void
+gst_emuldec_finalize (GObject *object)
+{
+  // Deinit Decoder
+  GstEmulDec *emuldec = (GstEmulDec *) object;
+
+  printf ("gst_emuldec_finalize\n");
+  if (emuldec->context != NULL) {
+    g_free (emuldec->context);
+    emuldec->context = NULL;
+  }
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+gst_emuldec_src_event (GstPad *pad, GstEvent *event)
+{
+  GstEmulDec *emuldec;
+  gboolean res; 
+
+  emuldec = (GstEmulDec *) gst_pad_get_parent (pad);
+
+  switch (GST_EVENT_TYPE (event)) {
+    /* Quality Of Service (QOS) event contains a report
+      about the current real-time performance of the stream.*/
+  case GST_EVENT_QOS:
+  {
+    gdouble proportion;
+    GstClockTimeDiff diff;
+    GstClockTime timestamp;
+
+       printf("GST_EVENT_QOS\n");
+    gst_event_parse_qos (event, &proportion, &diff, &timestamp);
+    GST_LOG_OBJECT (emuldec, "update QOS: %f, %" GST_TIME_FORMAT,
+      proportion, GST_TIME_ARGS (timestamp));
+
+    /* update our QoS values */
+    gst_emuldec_update_qos (emuldec, proportion, timestamp + diff);
+
+    /* forward upstream */
+    res = gst_pad_push_event (emuldec->sinkpad, event);
+    break;
+  }
+  default:
+    /* forward upstream */
+    res = gst_pad_push_event (emuldec->sinkpad, event);
+    break;
+  }
+
+  gst_object_unref (emuldec);
+
+  return 0;
+}
+
+static gboolean
+gst_emuldec_sink_event (GstPad *pad, GstEvent *event)
+{
+  GstEmulDec *emuldec;
+  gboolean ret = FALSE;
+
+  emuldec = (GstEmulDec *) gst_pad_get_parent (pad);
+
+  GST_DEBUG_OBJECT (emuldec, "Handling %s event",
+    GST_EVENT_TYPE_NAME (event));
+
+  switch (GST_EVENT_TYPE (event)) {
+  case GST_EVENT_EOS:
+       printf("GST_EVENT_EOS\n");
+    gst_emuldec_drain (emuldec);
+    break;
+  case GST_EVENT_FLUSH_STOP:
+  {
+       printf("GST_EVENT_FLUSH_STOP\n");
+
+    gst_emuldec_reset_ts (emuldec);
+//    gst_emuldec_reset_qos (emuldec);
+    gst_segment_init (&emuldec->segment, GST_FORMAT_TIME);
+
+    /* clear queue */
+    clear_queued (emuldec);
+  }
+    break;
+  case GST_EVENT_NEWSEGMENT:
+  {
+    gboolean update;
+    GstFormat format;
+    gint64 start, stop, time;
+    gdouble rate, arate;
+
+    printf ("GST_EVENT_NEWSEGMENT\n");
+    gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
+        &start, &stop, &time);
+
+    switch (format) {
+    case GST_FORMAT_TIME:
+      printf ("GST_FORMAT_TIME\n");
+      break;
+    case GST_FORMAT_BYTES:
+    {
+      gint bit_rate;
+      bit_rate = emuldec->context->audio.bit_rate;
+
+      printf ("GST_FORMAT_BYTES\n");
+      if (!bit_rate) {
+        // no_bitrate
+        GST_WARNING_OBJECT (emuldec, "no bitrate to convert BYTES to TIME");
+        gst_event_unref (event);
+        gst_object_unref (emuldec);
+        return ret;
+      }
+
+      GST_DEBUG_OBJECT (emuldec, "bitrate: %d", bit_rate);
+
+      if (start != -1) {
+        start = gst_util_uint64_scale_int (start, GST_SECOND, bit_rate);
+      }
+      if (stop != -1) {
+        stop = gst_util_uint64_scale_int (stop, GST_SECOND, bit_rate);
+      }
+      if (time != -1) {
+        time = gst_util_uint64_scale_int (time, GST_SECOND, bit_rate);
+      }
+
+      gst_event_unref (event);
+
+      format = GST_FORMAT_TIME;
+
+      stop = -1;
+      event = gst_event_new_new_segment (update, rate, format,
+          start, stop, time);
+      break;
+    }
+    default:
+      // invlalid format
+      break;
+    }
+
+#if 1 
+    if (emuldec->context->codec) {
+      gst_emuldec_drain (emuldec);
+    }
+#endif
+
+    gst_segment_set_newsegment_full (&emuldec->segment, update,
+        rate, arate, format, start, stop, time);
+    break;
+  }
+  default:
+    break;
+  }
+
+  ret = gst_pad_push_event (emuldec->srcpad, event);
+
+  gst_object_unref (emuldec);
+
+  return ret;
+}
+
+
+
+static gboolean
+gst_emuldec_setcaps (GstPad *pad, GstCaps *caps)
+{
+  GstEmulDec *emuldec;
+  GstEmulDecClass *oclass;
+  GstStructure *structure;
+  const GValue *par;
+  const GValue *fps;
+  gboolean ret = TRUE;
+
+  GST_DEBUG_OBJECT (pad, "setcaps called.");
+
+  emuldec = (GstEmulDec *) (gst_pad_get_parent (pad));
+  oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (emuldec));
+
+  GST_OBJECT_LOCK (emuldec);
+
+#if 0
+  if (emuldec->opened) {
+    GST_OBJECT_UNLOCK (emuldec);
+    gst_emuldec_drain (emuldec);
+    GST_OBJECT_LOCK (emuldec);
+    gst_emuldec_close (emuldec);
+  }
+#endif
+
+  GST_LOG_OBJECT (emuldec, "size %dx%d", emuldec->context->video.width,
+      emuldec->context->video.height);
+
+  gst_emul_caps_with_codecname (oclass->codec->name, oclass->codec->media_type,
+      caps, emuldec->context);
+
+  GST_LOG_OBJECT (emuldec, "size after %dx%d", emuldec->context->video.width,
+      emuldec->context->video.height);
+
+  if (!emuldec->context->video.fps_d || !emuldec->context->video.fps_n) {
+    GST_DEBUG_OBJECT (emuldec, "forcing 25/1 framerate");
+    emuldec->context->video.fps_n = 1;
+    emuldec->context->video.fps_d = 25;
+  }
+
+  structure = gst_caps_get_structure (caps, 0);
+
+  par = gst_structure_get_value (structure, "pixel-aspect-ratio");
+  if (par) {
+    GST_DEBUG_OBJECT (emuldec, "sink caps have pixel-aspect-ratio of %d:%d",
+        gst_value_get_fraction_numerator (par),
+        gst_value_get_fraction_denominator (par));
+#if 0 // TODO
+    if (emuldec->par) {
+      g_free(emuldec->par);
+    }
+    emuldec->par = g_new0 (GValue, 1);
+    gst_value_init_and_copy (emuldec->par, par);
+#endif
+  }
+
+  fps = gst_structure_get_value (structure, "framerate");
+  if (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps)) {
+    emuldec->format.video.fps_n = gst_value_get_fraction_numerator (fps);
+    emuldec->format.video.fps_d = gst_value_get_fraction_denominator (fps);
+    GST_DEBUG_OBJECT (emuldec, "Using framerate %d/%d from incoming",
+        emuldec->format.video.fps_n, emuldec->format.video.fps_d);
+  } else {
+    emuldec->format.video.fps_n = -1;
+    GST_DEBUG_OBJECT (emuldec, "Using framerate from codec");
+  }
+
+  if (strcmp (oclass->codec->name, "aac") == 0) {
+    const gchar *format = gst_structure_get_string (structure, "stream-format");
+#if 0
+    if (format == NULL || strcmp ("format", "raw") == 0) {
+      emuldec->turnoff_parser = TRUE;
+    }
+#endif
+  }
+
+  if (!gst_emuldec_open (emuldec)) {
+    GST_DEBUG_OBJECT (emuldec, "Failed to open");
+#if 0
+    if (emuldec->par) {
+      g_free(emuldec->par);
+      emuldec->par = NULL;
+    }
+#endif
+    GST_OBJECT_UNLOCK (emuldec);
+    gst_object_unref (emuldec);
+
+    return FALSE;
+  }
+
+  gst_structure_get_int (structure, "width",
+    &emuldec->format.video.clip_width);
+  gst_structure_get_int (structure, "height",
+    &emuldec->format.video.clip_height);
+
+  GST_DEBUG_OBJECT (pad, "clipping to %dx%d",
+    emuldec->format.video.clip_width, emuldec->format.video.clip_height);
+
+  GST_OBJECT_UNLOCK (emuldec);
+  gst_object_unref (emuldec);
+
+  return ret;
+}
+
+static GStaticMutex gst_avcodec_mutex = G_STATIC_MUTEX_INIT;
+
+int
+gst_emul_avcodec_open (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
+{
+  int ret;
+
+  g_static_mutex_lock (&gst_avcodec_mutex);
+
+  if (gst_emul_codec_device_open (dev) < 0) {
+    printf("failed to open device.\n");
+    return -1;
+  }
+  ret = emul_avcodec_init (ctx, codec, dev);
+  g_static_mutex_unlock (&gst_avcodec_mutex);
+
+  return ret;
+}
+
+int
+gst_emul_avcodec_close (CodecContext *ctx, CodecDevice *dev)
+{
+  int ret;
+
+  g_static_mutex_lock (&gst_avcodec_mutex);
+
+  printf ("gst_emul_avcodec_close\n");
+  ret = emul_avcodec_deinit (ctx, dev);
+
+  gst_emul_codec_device_close (dev);
+  g_static_mutex_unlock (&gst_avcodec_mutex);
+
+  return ret;
+}
+
+static gboolean
+gst_emuldec_open (GstEmulDec *emuldec)
+{
+  GstEmulDecClass *oclass;
+  int width, height, buf_size;
+
+  oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (emuldec));
+
+  if (!emuldec->dev) {
+    return FALSE;
+  }
+
+  switch (oclass->codec->media_type) {
+  case AVMEDIA_TYPE_VIDEO:
+    width = emuldec->context->video.width;
+    height = emuldec->context->video.height;
+    buf_size = gst_emul_avpicture_size (0, width, height);
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+//    buf_size = FF_MAX_AUDIO_FRAME_SIZE;
+    buf_size = 1024 * 256; // 256K
+    break;
+  default:
+    buf_size = -1;
+    break;
+  }
+
+  if (buf_size < 0) {
+    return FALSE;
+  }
+
+  emuldec->dev->buf_size = buf_size;
+
+  if (gst_emul_avcodec_open (emuldec->context, oclass->codec, emuldec->dev) < 0) {
+    gst_emuldec_close (emuldec);
+    GST_DEBUG_OBJECT (emuldec, "tzdec_%s: Failed to open codec",
+        oclass->codec->name);
+  }
+
+#if 0
+  emuldec->opened = TRUE;
+#endif
+
+  GST_LOG_OBJECT (emuldec, "Opened codec %s", oclass->codec->name);
+
+  switch (oclass->codec->media_type) {
+  case AVMEDIA_TYPE_VIDEO:
+    emuldec->format.video.width = 0;
+    emuldec->format.video.height = 0;
+    emuldec->format.video.clip_width = -1;
+    emuldec->format.video.clip_height = -1;
+    emuldec->format.video.pix_fmt = PIX_FMT_NB;
+    emuldec->format.video.interlaced = FALSE;
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+    emuldec->format.audio.samplerate = 0;
+    emuldec->format.audio.channels = 0;
+    emuldec->format.audio.depth = 0;
+    break;
+  default:
+    break;
+  }
+
+  gst_emuldec_reset_ts (emuldec);
+
+  emuldec->proportion = 0.0;
+  emuldec->earliest_time = -1;
+
+  return TRUE;
+}
+
+static gboolean
+gst_emuldec_close (GstEmulDec *emuldec)
+{
+  int ret;
+
+  printf ("gst_emuldec_close\n");
+  gst_emul_avcodec_close (emuldec->context, emuldec->dev);
+
+  return TRUE;
+}
+
+
+static gboolean
+gst_emuldec_negotiate (GstEmulDec *emuldec, gboolean force)
+{
+  GstEmulDecClass *oclass;
+  GstCaps *caps;
+
+  oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (emuldec));
+
+  switch (oclass->codec->media_type) {
+  case AVMEDIA_TYPE_VIDEO:
+    if (!force && emuldec->format.video.width == emuldec->context->video.width
+      && emuldec->format.video.height == emuldec->context->video.height
+      && emuldec->format.video.fps_n == emuldec->format.video.old_fps_n
+      && emuldec->format.video.fps_d == emuldec->format.video.old_fps_d
+      && emuldec->format.video.pix_fmt == emuldec->context->video.pix_fmt
+      && emuldec->format.video.par_n == emuldec->context->video.par_n
+      && emuldec->format.video.par_d == emuldec->context->video.par_d) {
+      return TRUE;
+    }
+    emuldec->format.video.width = emuldec->context->video.width;
+    emuldec->format.video.height = emuldec->context->video.height;
+    emuldec->format.video.old_fps_n = emuldec->format.video.fps_n;
+    emuldec->format.video.old_fps_d = emuldec->format.video.fps_d;
+    emuldec->format.video.pix_fmt = emuldec->context->video.pix_fmt;
+    emuldec->format.video.par_n = emuldec->context->video.par_n;
+    emuldec->format.video.par_d = emuldec->context->video.par_d;
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+  {
+    gint depth = gst_emul_smpfmt_depth (emuldec->context->audio.sample_fmt);
+    if (!force && emuldec->format.audio.samplerate ==
+      emuldec->context->audio.sample_rate &&
+      emuldec->format.audio.channels == emuldec->context->audio.channels &&
+      emuldec->format.audio.depth == depth) {
+      return TRUE;
+    }
+    emuldec->format.audio.samplerate = emuldec->context->audio.sample_rate;
+    emuldec->format.audio.channels = emuldec->context->audio.channels;
+    emuldec->format.audio.depth = depth;
+  }
+    break;
+  default:
+    break;
+  }
+
+
+
+  caps =
+    gst_emul_codectype_to_caps (oclass->codec->media_type, emuldec->context,
+      oclass->codec->name, FALSE);
+
+  if (caps == NULL) {
+    GST_ELEMENT_ERROR (emuldec, CORE, NEGOTIATION,
+      ("Could not find GStreamer caps mapping for codec '%s'.",
+      oclass->codec->name), (NULL));
+    return FALSE;
+  }
+
+  switch (oclass->codec->media_type) {
+  case AVMEDIA_TYPE_VIDEO:
+  {
+    gint width, height;
+    gboolean interlaced;
+
+    width = emuldec->format.video.clip_width;
+    height = emuldec->format.video.clip_height;
+    interlaced = emuldec->format.video.interlaced;
+
+    if (width != -1 && height != -1) {
+      if (width < emuldec->context->video.width) {
+        gst_caps_set_simple (caps, "width", G_TYPE_INT, width, NULL);
+      }
+      if (height < emuldec->context->video.height) {
+          gst_caps_set_simple (caps, "height", G_TYPE_INT, height, NULL);
+      }
+      gst_caps_set_simple (caps, "interlaced", G_TYPE_BOOLEAN, interlaced,
+        NULL);
+
+      if (emuldec->format.video.fps_n != -1) {
+          gst_caps_set_simple (caps, "framerate",
+            GST_TYPE_FRACTION, emuldec->format.video.fps_n,
+            emuldec->format.video.fps_d, NULL);
+      }
+#if 0
+      gst_emuldec_add_pixel_aspect_ratio (emuldec,
+        gst_caps_get_structure (caps, 0));
+#endif
+    }
+  }
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+  default:
+    break;
+  }
+
+  if (!gst_pad_set_caps (emuldec->srcpad, caps)) {
+    GST_ELEMENT_ERROR (emuldec, CORE, NEGOTIATION, (NULL),
+      ("Could not set caps for decoder (%s), not fixed?",
+      oclass->codec->name));
+    gst_caps_unref (caps);
+    return FALSE;
+  }
+
+  gst_caps_unref (caps);
+
+  return TRUE;
+}
+
+GstBuffer *
+new_aligned_buffer (gint size, GstCaps *caps)
+{
+  GstBuffer *buf;
+
+  buf = gst_buffer_new ();
+  GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = g_malloc0 (size);
+  GST_BUFFER_SIZE (buf) = size;
+  GST_BUFFER_FREE_FUNC (buf) = g_free;
+  if (caps) {
+    gst_buffer_set_caps (buf, caps);
+  }
+
+  return buf;
+}
+
+static gboolean
+clip_audio_buffer (GstEmulDec *dec, GstBuffer *buf,
+    GstClockTime in_ts, GstClockTime in_dur)
+{
+  GstClockTime stop;
+  gint64 diff, cstart, cstop;
+  gboolean res = TRUE;
+
+  if (G_UNLIKELY (dec->segment.format != GST_FORMAT_TIME)) {
+    GST_LOG_OBJECT (dec, "%sdropping", (res ? "not " : ""));
+    return res;
+  }
+
+  // in_ts: in_timestamp. check a start time.
+  if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (in_ts))) {
+    GST_LOG_OBJECT (dec, "%sdropping", (res ? "not " : ""));
+    return res;
+  }
+
+  stop =
+    GST_CLOCK_TIME_IS_VALID (in_dur) ? (in_ts + in_dur) : GST_CLOCK_TIME_NONE;
+
+  res = gst_segment_clip (&dec->segment, GST_FORMAT_TIME, in_ts,
+                          stop, &cstart, &cstop);
+  if (G_UNLIKELY (!res)) {
+    GST_LOG_OBJECT (dec, "out of segment");
+    GST_LOG_OBJECT (dec, "%sdropping", (res ? "not " : ""));
+    return res;
+  }
+
+  if (G_UNLIKELY ((diff = cstart - in_ts) > 0)) {
+    diff =
+      gst_util_uint64_scale_int (diff, dec->format.audio.samplerate,
+      GST_SECOND * (dec->format.audio.depth * dec->format.audio.channels));
+
+    GST_DEBUG_OBJECT (dec, "clipping start to %" GST_TIME_FORMAT " %"
+        G_GINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
+
+    GST_BUFFER_SIZE (buf) -= diff;
+    GST_BUFFER_DATA (buf) += diff;
+  }
+
+  if (G_UNLIKELY ((diff = stop - cstop) > 0)) {
+    diff =
+      gst_util_uint64_scale_int (diff, dec->format.audio.samplerate,
+      GST_SECOND * (dec->format.audio.depth * dec->format.audio.channels));
+
+    GST_DEBUG_OBJECT (dec, "clipping stop to %" GST_TIME_FORMAT " %"
+        G_GINT64_FORMAT " bytes", GST_TIME_ARGS (cstop), diff);
+
+    GST_BUFFER_SIZE (buf) -= diff;
+  }
+
+  GST_BUFFER_TIMESTAMP (buf) = cstart;
+  GST_BUFFER_DURATION (buf) = cstop - cstart;
+
+  GST_LOG_OBJECT (dec, "%sdropping", (res ? "not " : ""));
+  return res;
+}
+
+static gint
+gst_emuldec_video_frame (GstEmulDec *emuldec, guint8 *data, guint size,
+               const GstTSInfo *dec_info, GstBuffer **outbuf,
+               GstFlowReturn *ret)
+{
+  gint len = -1;
+  GstClockTime out_timestamp, out_duration;
+  gint64 out_offset;
+
+#if 0
+  len =
+    emul_avcodec_decode_video (emuldec->context, data, size,
+               (int16_t *) GST_BUFFER_DATA (*outbuf), &have_data, emuldec->dev);
+#endif
+
+  return len;
+}
+
+static gint
+gst_emuldec_audio_frame (GstEmulDec *emuldec, CodecElement *codec,
+                          guint8 *data, guint size,
+                          const GstTSInfo *dec_info, GstBuffer **outbuf,
+                          GstFlowReturn *ret)
+{
+  gint len = -1;
+  gint have_data = FF_MAX_AUDIO_FRAME_SIZE;
+  GstClockTime out_timestamp, out_duration;
+  gint64 out_offset;
+
+  *outbuf =
+      new_aligned_buffer (FF_MAX_AUDIO_FRAME_SIZE,
+          GST_PAD_CAPS (emuldec->srcpad));
+
+  len = emul_avcodec_decode_audio (emuldec->context,
+      (int16_t *) GST_BUFFER_DATA (*outbuf), &have_data,
+      data, size, emuldec->dev);
+
+  GST_DEBUG_OBJECT (emuldec,
+    "Decode audio: len=%d, have_data=%d", len, have_data);
+
+  if (len >= 0 && have_data > 0) {
+    GST_DEBUG_OBJECT (emuldec, "Creating output buffer");
+    if (!gst_emuldec_negotiate (emuldec, FALSE)) {
+      gst_buffer_unref (*outbuf);
+      *outbuf = NULL;
+      len = -1;
+      GST_DEBUG_OBJECT (emuldec, "return flow %d, out %p, len %d",
+        *ret, *outbuf, len);
+      return len;
+    }
+
+    GST_BUFFER_SIZE (*outbuf) = have_data;
+
+    if (GST_CLOCK_TIME_IS_VALID (dec_info->timestamp)) {
+      out_timestamp = dec_info->timestamp;
+    } else {
+      out_timestamp = emuldec->next_out;
+    }
+
+    out_duration = gst_util_uint64_scale (have_data, GST_SECOND,
+        emuldec->format.audio.depth * emuldec->format.audio.channels *
+        emuldec->format.audio.samplerate);
+
+    out_offset = dec_info->offset;
+
+    GST_DEBUG_OBJECT (emuldec,
+        "Buffer created. Size: %d, timestamp: %" GST_TIME_FORMAT
+        ", duration: %" GST_TIME_FORMAT, have_data,
+        GST_TIME_ARGS (out_timestamp), GST_TIME_ARGS (out_duration));
+
+    GST_BUFFER_TIMESTAMP (*outbuf) = out_timestamp;
+    GST_BUFFER_DURATION (*outbuf) = out_duration;
+    GST_BUFFER_OFFSET (*outbuf) = out_offset;
+    gst_buffer_set_caps (*outbuf, GST_PAD_CAPS (emuldec->srcpad));
+
+    if (GST_CLOCK_TIME_IS_VALID (out_timestamp)) {
+      emuldec->next_out = out_timestamp + out_duration;
+    }
+
+    if (G_UNLIKELY (!clip_audio_buffer (emuldec, *outbuf,
+        out_timestamp, out_duration))) {
+      GST_DEBUG_OBJECT (emuldec, "buffer_clipped");
+      gst_buffer_unref (*outbuf);
+      *outbuf = NULL;
+      GST_DEBUG_OBJECT (emuldec, "return flow %d, out %p, len %d", *ret, *outbuf, len);
+      return len;
+    }
+  } else {
+    gst_buffer_unref (*outbuf);
+    *outbuf = NULL;
+  }
+
+  if (len == -1 && !strcmp(codec->name, "aac")) {
+    GST_ELEMENT_ERROR (emuldec, STREAM, DECODE, (NULL),
+        ("Decoding of AAC stream by gst-emul-codec failed."));
+    *ret = GST_FLOW_ERROR;
+  }
+
+  GST_DEBUG_OBJECT (emuldec, "return flow %d, out %p, len %d",
+    *ret, *outbuf, len);
+  return len;
+}
+
+static gint
+gst_emuldec_frame (GstEmulDec *emuldec, guint8 *data, guint size,
+               gint *got_data, const GstTSInfo *dec_info, GstFlowReturn *ret)
+{
+  GstEmulDecClass *oclass;
+  GstBuffer *outbuf = NULL;
+  gint have_data = 0, len = 0;
+
+  if (G_UNLIKELY (emuldec->context->codec == NULL)) {
+    // no_codec
+    GST_ERROR_OBJECT (emuldec, "no codec context");
+    return -1;
+  }
+
+  *ret = GST_FLOW_OK;
+
+  oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (emuldec));
+
+  switch (oclass->codec->media_type) {
+  case AVMEDIA_TYPE_VIDEO:
+    len = gst_emuldec_video_frame (emuldec, data, size,
+               dec_info, &outbuf, ret);
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+    len = gst_emuldec_audio_frame (emuldec, oclass->codec, data, size,
+               dec_info, &outbuf, ret);
+    if (outbuf == NULL && emuldec->discont) {
+      GST_DEBUG_OBJECT (emuldec, "no buffer but keeping timestamp");
+//      emuldec->clear_ts = FALSE;
+    }
+    break;
+  default:
+    GST_ERROR_OBJECT (emuldec, "Asked to decode non-audio/video frame!");
+    g_assert_not_reached ();
+    break;
+  }
+
+  if (outbuf) {
+    have_data = 1;
+  }
+
+  if (len < 0 || have_data < 0) {
+    GST_WARNING_OBJECT (emuldec,
+               "tzdec_%s: decoding error (len: %d, have_data: %d)",
+               oclass->codec->name, len, have_data);
+    *got_data = 0;
+    return len;
+  } else if (len == 0 && have_data == 0) {
+    *got_data = 0;
+    return len;
+  } else {
+    *got_data = 1;
+  }
+
+  if (outbuf) {
+    GST_LOG_OBJECT (emuldec,
+        "Decoded data, now pushing buffer %p with offset %" G_GINT64_FORMAT
+        ", timestamp %" GST_TIME_FORMAT " and duration %" GST_TIME_FORMAT,
+        outbuf, GST_BUFFER_OFFSET (outbuf),
+        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
+        GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
+
+    if (emuldec->discont) {
+      /* GST_BUFFER_FLAG_DISCONT :
+       * the buffer marks a data discontinuity in the stream. This typically
+       * occurs after a seek or a dropped buffer from a live or network source.
+       */
+      GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
+      emuldec->discont = FALSE;
+    }
+
+    if (emuldec->segment.rate > 0.0) {
+      // push forward
+      *ret = gst_pad_push (emuldec->srcpad, outbuf);
+    } else {
+      // push reverse
+      printf("push reverse.\n");
+      emuldec->queued = g_list_prepend (emuldec->queued, outbuf);
+      *ret = GST_FLOW_OK;
+    }
+  } else {
+    GST_DEBUG_OBJECT (emuldec, "Didn't get a decoded buffer");
+  }
+
+  return len;
+}
+
+static GstFlowReturn
+gst_emuldec_chain (GstPad *pad, GstBuffer *buffer)
+{
+  GstEmulDec *emuldec;
+  GstEmulDecClass *oclass;
+  guint8 *in_buf;
+  guint in_size, len, have_data;
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstClockTime in_timestamp;
+  GstClockTime in_duration;
+  gboolean discont;
+  gint64 in_offset;
+  const GstTSInfo *in_info;
+  const GstTSInfo *dec_info;
+
+  emuldec = (GstEmulDec *) (GST_PAD_PARENT (pad));
+
+#if 0
+  if (G_UNLIKELY (!emuldec->opened)) {
+    // not_negotiated
+    oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (emuldec));
+    GST_ELEMENT_ERROR (emuldec, CORE, NEGOTIATION, (NULL),
+      ("tzdec_%s: input format was not set before data start",
+               oclass->codec->name));
+    gst_buffer_unref (buffer);
+    return GST_FLOW_NOT_NEGOTIATED;
+  }
+#endif
+
+  discont = GST_BUFFER_IS_DISCONT (buffer);
+
+// FIXME
+  if (G_UNLIKELY (discont)) {
+    GST_DEBUG_OBJECT (emuldec, "received DISCONT");
+    printf("discont 1\n");
+    gst_emuldec_drain (emuldec);
+    printf("discont 2\n");
+//    gst_emuldec_flush_pcache (emuldec);
+    // flush buffers
+    emuldec->discont = TRUE;
+    gst_emuldec_reset_ts (emuldec);
+  }
+//  emuldec->clear_ts = TRUE;
+
+  oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (emuldec));
+#if 0
+  if (G_UNLIKELY (emuldec->waiting_for_key)) {
+    if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT) &&
+      oclass->codec->media_type != AVMEDIA_TYPE_AUDIO) {
+      // skip_keyframe
+    }
+    emuldec->waiting_for_key = FALSE;
+  }
+
+  if (emuldec->pcache) {
+         GST_LOG_OBJECT (emuldec, "join parse cache");
+         buffer = gst_buffer_join (emuldec->pcache, buffer);
+         emuldec->pcache = NULL;
+  }
+#endif
+
+  in_timestamp = GST_BUFFER_TIMESTAMP (buffer);
+  in_duration = GST_BUFFER_DURATION (buffer);
+  in_offset = GST_BUFFER_OFFSET (buffer);
+
+  in_info = gst_ts_info_store (emuldec, in_timestamp, in_duration, in_offset);
+
+#if 0
+  if (in_timestamp != -1) {
+    if (!emuldec->reordered_in && emuldec->last_in != -1) {
+      if (in_timestamp < emuldec->last_in) {
+        GST_LOG_OBJECT (emuldec, "detected reordered input timestamps");
+        emuldec->reordered_in = TRUE;
+        emuldec->last_diff = GST_CLOCK_TIME_NONE;
+      } else if (in_timestamp > emuldec->last_in) {
+        GstClockTime diff;
+        diff = in_timestamp - emuldec->last_in;
+        if (emuldec->last_frames) {
+          diff /= emuldec->last_frames;
+        }
+
+        GST_LOG_OBJECT (emuldec, "estimated duration %" GST_TIME_FORMAT " %u",
+                 GST_TIME_ARGS (diff), emuldec->last_frames);
+
+        emuldec->last_diff = diff;
+      }
+    }
+    emuldec->last_in = in_timestamp;
+    emuldec->last_frames;
+  }
+#endif
+
+  in_buf = GST_BUFFER_DATA (buffer);
+  in_size = GST_BUFFER_SIZE (buffer);
+
+  dec_info = in_info;
+
+  len =
+               gst_emuldec_frame (emuldec, in_buf, in_size, &have_data, dec_info, &ret);
+
+  gst_buffer_unref (buffer);
+
+  return ret;
+}
+
+static GstStateChangeReturn
+gst_emuldec_change_state (GstElement *element, GstStateChange transition)
+{
+  GstEmulDec *emuldec = (GstEmulDec *) element;
+  GstStateChangeReturn ret;
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+  switch (transition) {
+  case GST_STATE_CHANGE_PAUSED_TO_READY:
+    GST_OBJECT_LOCK (emuldec);
+    gst_emuldec_close (emuldec);
+    GST_OBJECT_UNLOCK (emuldec);
+
+    /* clear queue */
+    clear_queued (emuldec);
+    break;
+  default:
+    break;
+  }
+
+  return ret;
+}
+
+gboolean
+gst_emuldec_register (GstPlugin *plugin, GList *element)
+{
+  GTypeInfo typeinfo = {
+      sizeof (GstEmulDecClass),
+      (GBaseInitFunc) gst_emuldec_base_init,
+      NULL,
+      (GClassInitFunc) gst_emuldec_class_init,
+      NULL,
+      NULL,
+      sizeof (GstEmulDec),
+      0,
+      (GInstanceInitFunc) gst_emuldec_init,
+  };
+
+  GType type;
+  gchar *type_name;
+  gint rank = GST_RANK_PRIMARY;
+  gboolean ret = TRUE;
+  GList *elem = element;
+  CodecElement *codec = NULL;
+
+  /* register element */
+  while ((elem = g_list_next (elem))) {
+    codec = (CodecElement *)elem->data;
+    if (!codec) {
+      ret = FALSE;
+      break;
+    }
+
+    if (codec->codec_type != CODEC_TYPE_DECODE) {
+      continue;
+    }
+
+    type_name = g_strdup_printf ("tzdec_%s", codec->name);
+    type = g_type_from_name (type_name);
+    if (!type) {
+      type = g_type_register_static (GST_TYPE_ELEMENT, type_name, &typeinfo, 0);
+      g_type_set_qdata (type, GST_EMULDEC_PARAMS_QDATA, (gpointer) codec);
+    }
+
+    if (!gst_element_register (plugin, type_name, rank, type)) {
+      g_free (type_name);
+      return FALSE;
+    }
+    g_free (type_name);
+  }
+
+  return ret;
+}
+
diff --git a/src/gstemulnewenc.c b/src/gstemulnewenc.c
new file mode 100644 (file)
index 0000000..b6e713a
--- /dev/null
@@ -0,0 +1,617 @@
+/*
+ * GStreamer codec plugin for Tizen Emulator. 
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * KiTae Kim <kt920.kim@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <gst/gst.h>
+#include "gstemulcommon.h"
+
+#define GST_EMULENC_PARAMS_QDATA g_quark_from_static_string("emulenc-params"); 
+
+typedef struct _GstEmulEnc
+{
+  GstElement element;
+
+  GstPad *srcpad;
+  GstPad *sinkpad;
+
+  union {
+    struct {
+      gint width;
+      gint height;
+      gint framerate_num;
+      gint framerate_den;
+      gint pix_fmt;   
+    } video;
+    struct {
+      gint channels;
+      gint samplerate;
+      gint depth;
+    } audio;
+  } format;
+
+  GstAdapter *adapter;
+
+  // TODO: needs a certain container such as AVCodecContext.
+  guint extradata_size;
+  guint8 *extradata;
+
+  CodecDev codecbuf;
+} GstEmulEnc;
+
+typedef struct _GstEmulEncClass
+{
+  GstElementClass parent_class;
+
+  CodecInfo *codecinfo;
+  GstPadTemplate *sinktempl, *srctempl;
+  GstCaps *sinkcaps;
+} GstEmulEncClass;
+
+static GstElementClass *parent_class = NULL;
+
+static void gst_emulenc_base_init (GstEmulEncClass *klass);
+static void gst_emulenc_class_init (GstEmulEncClass *klass);
+static void gst_emulenc_init (GstEmulEnc *emulenc);
+static void gst_emulenc_finalize (GObject *object);
+
+static gboolean gst_emulenc_setcaps (GstPad *pad, GstCaps *caps);
+static gboolean gst_emulenc_getcaps (GstPad *pad);
+
+static GstFlowReturn gst_emulenc_chain_video (GstPad *pad, GstBuffer *buffer);
+static GstFlowReturn gst_emulenc_chain_audio (GstPad *pad, GstBuffer *buffer);
+
+static gboolean gst_emulenc_event_video (GstPad *pad, GstEvent *event);
+static gboolean gst_emulenc_event_src (GstPad *pad, GstEvent *event);
+
+static GstStateChangeReturn gst_emulenc_change_state (GstElement *element, GstStateChange transition);
+
+int gst_emul_codec_init (GstEmulEnc *emulenc);
+void gst_emul_codec_deinit (GstEmulEnc *emulenc);
+
+#if 0
+int gst_emul_codec_encode_video (GstEmulEnc *emulenc, guint8 *in_buf, guint in_size,
+        GstBuffer **out_buf, GstClockTime in_timestamp);
+int gst_emul_codec_encode_audio (GstEmulEnc *emulenc, guint8 *in_buf, guint in_size,
+        GstBuffer **out_buf, GstClockTime in_timestamp);
+#endif
+
+/*
+ * Implementation
+ */
+static void
+gst_emulenc_base_init (GstEmulEncClass *klass)
+{
+    GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+    GstPadTemplate *sinktempl = NULL, *srctempl = NULL;
+    GstCaps *sinkcaps = NULL, *srccaps = NULL;
+    CodecInfo *info;
+    gchar *longname, *classification;
+
+    info =
+        (CodecInfo *)g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
+         GST_EMULENC_PARAMS_QDATA);
+
+    longname = g_strdup_printf ("%s Encoder", info->codec_longname);
+
+    classification = g_strdup_printf ("Codec/Encoder/%s",
+            (info->media_type == AVMEDIA_TYPE_VIDEO) ? "Video" : "Audio");
+
+    gst_element_class_set_details_simple (element_class,
+            longname,
+            classification,
+            "accelerated codec for Tizen Emulator",
+            "Kitae Kim <kt920.kim@samsung.com>");
+    g_free (longname);
+    g_free (classification);
+
+
+  if (!(srccaps = gst_emul_codecname_to_caps (info, TRUE))) {
+    GST_DEBUG ("Couldn't get source caps for encoder '%s'", info->codec_name);
+    srccaps = gst_caps_new_simple ("unknown/unknown", NULL);
+  }
+
+  switch (info->media_type) {
+  case AVMEDIA_TYPE_VIDEO:
+    sinkcaps = gst_caps_from_string ("video/x-raw-rgb; video/x-raw-yuv; video/x-raw-gray");
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+    srccaps = gst_emul_codectype_to_audio_caps (info, TRUE);
+    break;
+  default:
+    GST_LOG("unknown media type.\n");
+    break;
+  }
+
+  if (!sinkcaps) {
+      GST_DEBUG ("Couldn't get sink caps for encoder '%s'", info->codec_name);
+      sinkcaps = gst_caps_new_simple ("unknown/unknown", NULL);
+  }
+
+  sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK,
+          GST_PAD_ALWAYS, sinkcaps);
+  srctempl = gst_pad_template_new ("src", GST_PAD_SRC,
+          GST_PAD_ALWAYS, srccaps);
+
+  gst_element_class_add_pad_template (element_class, srctempl);
+  gst_element_class_add_pad_template (element_class, sinktempl);
+
+  klass->sinktempl = sinktempl;
+  klass->srctempl = srctempl;
+  klass->sinkcaps = NULL;
+}
+
+    static void
+gst_emulenc_class_init (GstEmulEncClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+
+  parent_class = g_type_class_peek_parent (klass);
+
+#if 0
+  gobject_class->set_property = gst_emulenc_set_property
+  gobject_class->get_property = gst_emulenc_get_property
+#endif
+
+  gobject_class->finalize = gst_emulenc_finalize;
+
+  gstelement_class->change_state = gst_emulenc_change_state; 
+}
+
+    static void
+gst_emulenc_init (GstEmulEnc *emulenc)
+{
+  GstEmulEncClass *oclass;
+  oclass = (GstEmulEncClass*) (G_OBJECT_GET_CLASS(emulenc));
+
+  emulenc->sinkpad = gst_pad_new_from_template (oclass->sinktempl, "sink");
+  gst_pad_set_setcaps_function (emulenc->sinkpad,
+                                GST_DEBUG_FUNCPTR(gst_emulenc_setcaps));
+  gst_pad_set_getcaps_function (emulenc->sinkpad,
+                                GST_DEBUG_FUNCPTR(gst_emulenc_getcaps));
+
+  emulenc->srcpad = gst_pad_new_from_template (oclass->srctempl, "src");
+  gst_pad_use_fixed_caps (emulenc->srcpad);
+
+  switch (oclass->codecinfo->media_type) {
+  case AVMEDIA_TYPE_VIDEO:
+    gst_pad_set_chain_function (emulenc->sinkpad, gst_emulenc_chain_video);
+    gst_pad_set_event_function (emulenc->sinkpad, gst_emulenc_event_video);
+    gst_pad_set_event_function (emulenc->srckpad, gst_emulenc_event_src);
+
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+    gst_pad_set_chain_function (emuldec->sinkpad, gst_emulenc_chain_audio);    
+    break;
+  default:
+    break;
+  }
+
+  gst_element_add_pad (GST_ELEMENT (emulenc), emuldenc->sinkpad);
+  gst_element_add_pad (GST_ELEMENT (emulenc), emuldenc->srcpad);
+
+  // need to know what adapter does.
+  emulenc->adapter = gst_adapter_new ();
+}
+
+    static void
+gst_emulenc_finalize (GObject *object)
+{
+    // Deinit Decoder
+    GstEmulEnc *emulenc = (GstEmulEnc *) object;
+
+    G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+    static gboolean
+gst_emulenc_src_event (GstPad *pad, GstEvent *event)
+{
+    return 0;
+}
+
+    static void
+gst_emulenc_get_caps (GstEmulEnc *emulenc, GstCaps *caps)
+{
+    GstStructure *structure;
+
+    int width, height, bits_per_coded_sample;
+    const GValue *fps;
+    //    const GValue *par;
+    //    guint extradata_size;
+    //    guint8 *extradata;
+
+    /* FFmpeg Specific Values */
+    const GstBuffer *buf;
+    const GValue *value;
+
+    structure = gst_caps_get_structure (caps, 0);
+
+    value = gst_structure_get_value (structure, "codec_data");
+    if (value) {
+        buf = GST_BUFFER_CAST (gst_value_get_mini_object (value));
+        emulenc->extradata_size = GST_BUFFER_SIZE (buf);
+        emulenc->extradata = GST_BUFFER_DATA (buf);
+    } else {
+        CODEC_LOG (2, "no codec data\n");
+        emulenc->extradata_size = 0;
+        emulenc->extradata = NULL;
+    }
+
+#if 1 /* video type */
+    /* Common Properites, width, height and etc. */
+    gst_structure_get_int (structure, "width", &width);
+    gst_structure_get_int (structure, "height", &height);
+    gst_structure_get_int (structure, "bpp", &bits_per_coded_sample);
+
+    emulenc->format.video.width = width;
+    emulenc->format.video.height = height;
+
+    fps = gst_structure_get_value (structure, "framerate");
+    if (fps) {
+        emulenc->format.video.framerate_den = gst_value_get_fraction_numerator (fps);
+        emulenc->format.video.framerate_num = gst_value_get_fraction_denominator (fps);
+    }
+
+#if 0
+    par = gst_structure_get_value (structure, "pixel-aspect-ratio");
+    if (par) {
+        sample_aspect_ratio.num = gst_structure_get_fraction_numerator (par);
+        sample_aspect_ratio.den = gst_structure_get_fraction_denominator (par);
+    }
+#endif
+#endif
+
+#if 0 /* audio type */
+    gst_structure_get_int (structure, "channels", &channels);
+    gst_structure_get_int (structure, "rate", &sample_rate);
+    gst_structure_get_int (structure, "block_align", &block_align);
+    gst_structure_get_int (structure, "bitrate", &bit_rate);
+
+    emulenc->format.audio.channels = channels;
+    emulenc->format.audio.samplerate = sample_rate;
+#endif
+
+}
+
+    static gboolean
+gst_emulenc_setcaps (GstPad *pad, GstCaps *caps)
+{
+  GstEmulEnc *emulenc;
+  GstEmulEncClass *oclass;
+  gboolean ret = TRUE;
+
+  emulenc = (GstEmulEnc *) (gst_pad_get_parent (pad));
+  oclass = (GstEmulEncClass *) (G_OBJECT_GET_CLASS (emulenc));
+
+  if (emulenc->opend) {
+    gst_emul_deinit ();
+    emulenc->opened = FALSE;
+
+    gst_pad_set_caps (emulenc->srcpad, NULL);
+  }
+
+  gst_emul_caps_with_codectype (codec_type, caps);
+
+  if (!time_base.den) {
+    time_base.den = 25;
+    time_base.num = 1;
+  } else if (strcmp(  ,"mpeg4") == 0) {
+  }
+
+  // open codec
+
+  if (gst_emul_codec_dev_open (emulenc) < 0) {
+    CODEC_LOG(1, "failed to access %s or mmap operation\n", CODEC_DEV);
+    gst_object_unref (emulenc);
+    return FALSE;
+  }
+
+  if (gst_emul_codec_init (emulenc) < 0) {
+    CODEC_LOG(1, "cannot initialize codec\n");
+    gst_object_unref (emulenc);
+    return FALSE;
+  }
+
+  allowed_caps = gst_pad_get_allowed_caps (emulenc->srcpad);
+  if (!allowed_caps) {
+    allowed_caps =
+      gst_caps_copy (gst_pad_get_pad_template_caps (emulenc->srcpad));
+  }
+
+  gst_emul_caps_with_codecid (codec_id, codec_type, allowed_caps);
+
+  other_caps = gst_emul_codecname_to_caps (codec_id, TRUE);
+
+  if (!other_caps) {
+     // deinit
+    return FALSE;
+  }
+
+  icaps = gst_caps_intersect (allowed_caps, other_caps);
+  gst_caps_unref (allowed_caps);
+  gst_caps_unref (other_caps);
+  if (gst_caps_is_empty (icaps)) {
+    gst_caps_unref (icaps);
+    return FALSE;
+  }
+
+  if (gst_caps_get_size (icaps) > 1) {
+    GstCaps *newcaps;
+  
+    newcaps =
+      gst_caps_new_full (gst_structure_copy (gst_caps_get_structure (icaps,
+              0)), NULL);
+
+  if (!gst_pad_set_caps (emulenc->srcpad, icaps)) {
+    // deinit
+    gst_caps_unref (icaps);
+    return FALSE;
+  }
+  gst_object_unref (emulenc);
+
+  // emulenc->opened = TRUE;
+
+  return TRUE;
+}
+
+static gboolean
+gst_emulenc_event_video (GstPad *pad, GstEvent *event)
+{
+  GstEmulEnc *emulenc;
+  emulenc = (GstEmulEnc *) gst_pad_get_parent (pad);
+
+  switch (GST_TYPE_EVENT (event)) {
+  case GST_EVENT_EOS:
+    CODEC_LOG(2, "received GST_EVENT_EOS\n");
+    // flush_buffers
+    break;
+  case GST_EVENT_CUSTOM_DOWNSTREAM:
+    CODEC_LOG(2, "received GST_EVENT_CUSTOM_DOWNSTREAM\n");
+    break;
+  }
+
+  return gst_pad_push_event (emulenc->srcpad, event);
+}
+
+static gboolean
+gst_emulenc_event_src (GstPad *pad, GstEvent *event)
+{
+  switch (GST_EVENT_TYPE (event)) {
+  default:
+    break    
+  }
+
+  return TRUE;
+}
+
+// minimum encoding buffer size.
+// Used to avoid some checks during header writing.
+#define FF_MIN_BUFFER_SIZE 16384
+
+static inst
+gst_emul_encode_video (uint8_t *outbuf, int buf_size,
+                      uint8_t *pict_buf, uint32_t pict_buf_size)
+{
+  GstEmulEnc *emulenc = (GetEmulEnc *) (GST_PAD_PARENT (pad));
+  int size = 0, api_index = CODEC_ENCODE_VIDEO;
+  int ret;
+
+  ret = write (); 
+
+  return ret;
+}
+
+static GstFlowReturn
+gst_emulenc_encode_audio (GstEmulEnc *emulenc, guint8 *audio_in,
+  guint in_size, guint max_size, GstClockTime timestamp,
+  GstClockTime duration, gboolean discont)
+{
+  GstBuffer *outbuf;
+  guint8_t *audio_out;
+  gint res;
+  GstFlowReturn ret;
+  int size = 0, api_index = CODEC_ENCODE_AUDIO;
+
+  outbuf = gst_buffer_new_alloc (max_size + FF_MIN_BUFFER_SIZE);
+  audio_out = GST_BUFFER_DATA (outbuf);
+
+  // copy params to qemu
+
+  res = write();
+
+  // copy output and out params from qemu
+
+  if (res < 0) {
+    GST_ERROR_OBJECT (emulenc, "Failed to encode buffer: %d", res);
+    gst_buffer_unref (outbuf);
+    return GST_FLOW_OK;
+  }
+
+  GST_BUFFER_SIZE (outbuf) = res;
+  GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
+  GST_BUFFER_DURATION (outbuf) = duration
+
+  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (emulenc->srcpad));
+
+  ret = gst_pad_push (emulenc->srcpad, outbuf);
+
+  return ret;
+}
+
+#if 0
+static void
+emulenc_setup_working_buf (GstEmulEnc * emulenc)
+{
+  guint wanted_size =
+    ffmpegenc->context->width * ffmpegenc->context->height * 6 +
+    FF_MIN_BUFFER_SIZE;
+  /* Above is the buffer size used by ffmpeg/ffmpeg.c */
+  if (ffmpegenc->working_buf == NULL ||
+    ffmpegenc->working_buf_size != wanted_size) {
+    if (ffmpegenc->working_buf)
+      g_free (ffmpegenc->working_buf);
+    ffmpegenc->working_buf_size = wanted_size;
+    ffmpegenc->working_buf = g_malloc (ffmpegenc->working_buf_size);
+  }
+  ffmpegenc->buffer_size = wanted_size;
+}
+#endif
+
+static GstFlowReturn
+gst_emulenc_chain_video (GstPad *pad, GstBuffer *buffer)
+{
+  GstEmulEnc *emulenc = (GetEmulEnc *) (GST_PAD_PARENT (pad));
+  GstBuffer *outbuf;
+  gint in_size = 0;
+
+  // setup_working_buf
+  // width * height * 6 + FF_MIN_BUFFER_SIZE
+  // 
+
+//  gst_emul_encode_video ();
+
+  outbuf = gst_buffer_new_and_alloc (ret_size);
+  memcpy (GST_BUFFER_DATA(outbuf), , ret_size);
+  GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buffer);
+  GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (outbuf);
+
+  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (emulenc->srcpad));
+
+  gst_buffer_unref (buffer);
+  
+  return gst_pad_push (emulenc->srcpad, outbuf);
+}
+
+static GstFlowReturn
+gst_emulenc_chain_audio (GstPad *pad, GstBuffer *buffer)
+{
+  GstEmulEnc *emulenc;
+  GstEmulEncClass *oclass;
+  GstClockTime timestamp, duration;
+  guint size;
+  GstFlowReturn ret;
+  gboolean discont;
+
+  emulenc = (GstEmulEnc *) (GST_OBJECT_PARENT (pad));
+  oclass = (GstEmulEncClass *) G_OBJECT_GET_CLASS (emulenc);
+
+  size = GST_BUFFER_SIZE (buffer);
+  timestamp = GST_BUFFER_TIMESTAMP (buffer);
+  duration = GST_BUFFER_DURATION (buffer);
+  discont = GST_BUFFER_IS_DISCONT (buffer);
+
+  if (discont) {
+    gst_adapter_clear (emulenc->adapter);
+  }
+  
+//  gst_adapter_push (emulenc->adapter, buffer);
+
+// TODO
+// gst_emul_encode_audio
+
+  return GST_FLOW_OK;
+}
+
+static GstStateChangeReturn
+gst_emulenc_change_state (GstElement *element, GstStateChange transition)
+{
+    GstEmulEnc *emulenc = (GstEmulEnc*)element;
+    GstStateChangeReturn ret;
+
+    ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+    switch (transition) {
+        case GST_STATE_CHANGE_PAUSED_TO_READY:
+            // flush buffer
+            gst_emul_codec_deinit (emulenc);
+        default:
+            break;
+    }
+
+    return ret;
+}
+
+gboolean
+gst_emulenc_register (GstPlugin *plugin, GList *element)
+{
+  GTypeInfo typeinfo = {
+      sizeof (GstEmulEncClass),
+      (GBaseInitFunc) gst_emulenc_base_init,
+      NULL,
+      (GClassInitFunc) gst_emulenc_class_init,
+      NULL,
+      NULL,
+      sizeof (GstEmulEnc),
+      0,
+      (GInstanceInitFunc) gst_emulenc_init,
+  };
+
+  GType type;
+  gchar *type_name;
+  gint rank = GST_RANK_PRIMARY;
+  gboolean ret = TRUE;
+  GList *elem = NULL;
+  CodecElement *codec = NULL;
+
+  /* register element */
+  while ((elem = g_list_next (element))) {
+    codec = (CodecElement *)elem->data;
+    if (!codec) {
+      ret = FALSE;
+      break;
+    }
+
+    if (codec->codec_type != CODEC_TYPE_ENCODE) {
+      continue;
+    }
+
+    type_name = g_strdup_printf ("tzenc_%s", codec->name);
+    type = g_type_from_name (type_name);
+    if (!type) {
+      type = g_type_register_static (GST_TYPE_ELEMENT, type_name, &typeinfo, 0);
+      g_type_set_qdata (type, GST_EMULDEC_PARAMS_QDATA, (gpointer) codec);
+    }
+
+    if (!gst_element_register (plugin, type_name, rank, type)) {
+      g_free (type_name);
+      return FALSE;
+    }
+    g_free (type_name);
+  }
+
+  return ret;
+}
diff --git a/src/gstemulutils.c b/src/gstemulutils.c
new file mode 100644 (file)
index 0000000..cff4e33
--- /dev/null
@@ -0,0 +1,1139 @@
+/*
+ * GStreamer codec plugin for Tizen Emulator.
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * KiTae Kim <kt920.kim@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#include "gstemulutils.h"
+#include <gst/audio/multichannel.h>
+#include <gst/pbutils/codec-utils.h>
+
+gint
+gst_emul_smpfmt_depth (int smp_fmt)
+{
+  gint depth = -1;
+
+  switch (smp_fmt) {
+  case SAMPLE_FMT_U8:
+    depth = 1;
+    break;
+  case SAMPLE_FMT_S16:
+    depth = 2;
+    break;
+  case SAMPLE_FMT_S32:
+  case SAMPLE_FMT_FLT:
+    depth = 4;
+    break;
+  case SAMPLE_FMT_DBL:
+    depth = 8;
+    break;
+  default:
+    GST_ERROR ("Unhandled sample format !");
+    break;
+  }
+
+  return depth;
+}
+
+// FFmpeg
+static const struct
+{
+  guint64 ff;
+  GstAudioChannelPosition gst;
+} _ff_to_gst_layout[] = {
+  {
+  CH_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, {
+  CH_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {
+  CH_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, {
+  CH_LOW_FREQUENCY, GST_AUDIO_CHANNEL_POSITION_LFE}, {
+  CH_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT}, {
+  CH_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
+  CH_FRONT_LEFT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, {
+  CH_FRONT_RIGHT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, {
+  CH_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, {
+  CH_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT}, {
+  CH_SIDE_RIGHT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}, {
+  CH_TOP_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, {
+  CH_TOP_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
+  CH_TOP_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, {
+  CH_TOP_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
+  CH_TOP_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
+  CH_TOP_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, {
+  CH_TOP_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
+  CH_STEREO_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, {
+  CH_STEREO_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}
+};
+
+static GstAudioChannelPosition *
+gst_ff_channel_layout_to_gst (guint64 channel_layout, guint channels)
+{
+  guint nchannels = 0, i, j;
+  GstAudioChannelPosition *pos = NULL;
+  gboolean none_layout = FALSE;
+
+  for (i = 0; i < 64; i++) {
+    if ((channel_layout & (G_GUINT64_CONSTANT (1) << i)) != 0) {
+      nchannels++;
+    }
+  }
+
+  if (channel_layout == 0) {
+    nchannels = channels;
+    none_layout = TRUE;
+  }
+
+  if (nchannels != channels) {
+    GST_ERROR ("Number of channels is different (%u != %u)", channels,
+               nchannels);
+    return NULL;
+  }
+
+  pos = g_new (GstAudioChannelPosition, nchannels);
+
+  for (i = 0, j = 0; i < G_N_ELEMENTS (_ff_to_gst_layout); i++) {
+    if ((channel_layout & _ff_to_gst_layout[i].ff) != 0) {
+      pos[j++] = _ff_to_gst_layout[i].gst;
+
+      if (_ff_to_gst_layout[i].gst == GST_AUDIO_CHANNEL_POSITION_NONE) {
+        none_layout = TRUE;
+      }
+    }
+  }
+
+  if (j != nchannels) {
+    GST_WARNING ("Unknown channels in channel layout - assuming NONE layout");
+    none_layout = TRUE;
+  }
+
+  if (!none_layout && !gst_audio_check_channel_positions (pos, nchannels)) {
+    GST_ERROR ("Invalid channel layout %" G_GUINT64_FORMAT
+      " - assuming NONE layout", channel_layout);
+    none_layout = TRUE;
+  }
+
+  if (none_layout) {
+    if (nchannels == 1) {
+      pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO;
+    } else if (nchannels == 2) {
+      pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
+      pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
+    } else if (channel_layout == 0) {
+      g_free (pos);
+      pos = NULL;
+    } else {
+      for (i = 0; i < nchannels; i++) {
+        pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
+      }
+    }
+  }
+
+  if (nchannels == 1 && pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER) {
+    GST_DEBUG ("mono common case; won't set channel positions");
+    g_free (pos);
+    pos = NULL;
+  } else if (nchannels == 2 && pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT
+    && pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT) {
+    GST_DEBUG ("stereo common case; won't set channel positions");
+    g_free (pos);
+    pos = NULL;
+  }
+
+  return pos;
+}
+
+GstCaps*
+gst_emul_codectype_to_video_caps (CodecContext *ctx, const char *name,
+    gboolean encode, CodecElement *codec)
+{
+  GstCaps *caps;
+
+  GST_DEBUG ("context: %p, codec: %s, encode: %d, codec: %p",
+      ctx, name, encode, codec);
+
+  if (ctx) {
+    caps = gst_emul_pixfmt_to_caps (ctx->video.pix_fmt, ctx, name);
+  } else {
+    GstCaps *temp;
+    enum PixelFormat i;
+    CodecContext ctx = { 0, };
+
+    caps = gst_caps_new_empty ();
+    for (i = 0; i <= PIX_FMT_NB; i++) {
+      temp = gst_emul_pixfmt_to_caps (i, encode ? &ctx : NULL, name);
+      if (temp != NULL) {
+        gst_caps_append (caps, temp);
+      }
+    }
+  }
+
+  return caps;
+}
+
+GstCaps *
+gst_emul_codectype_to_audio_caps (CodecContext *ctx, const char *name,
+    gboolean encode, CodecElement *codec)
+{
+  GstCaps *caps = NULL;
+
+  GST_DEBUG ("context: %p, codec: %s, encode: %d, codec: %p",
+      ctx, name, encode, codec);
+#if 0
+  if (codec) {
+  }
+#endif
+
+  if (ctx) {
+    // FIXME
+    caps = gst_emul_smpfmt_to_caps (ctx->audio.sample_fmt, ctx, name);
+#if 0
+  } else if (codec && codec->audio.sample_fmts){
+    GstCaps *temp;
+    int i;
+
+    caps = gst_caps_new_empty ();
+    for (i = 0; codec->audio.sample_fmts[i] != -1; i++) {
+      temp =
+          gst_emul_smpfmt_to_caps (codec->audio.sample_fmts[i], ctx, name);
+      if (temp != NULL) {
+        gst_caps_append (caps, temp);
+      }
+    }
+#endif
+  } else {
+    GstCaps *temp;
+    int i;
+    CodecContext ctx = { 0, };
+
+    ctx.audio.channels = -1;
+    caps = gst_caps_new_empty ();
+    for (i = 0; i <= SAMPLE_FMT_DBL; i++) {
+      temp = gst_emul_smpfmt_to_caps (i, encode ? &ctx : NULL, name);
+      if (temp != NULL) {
+        gst_caps_append (caps, temp);
+      }
+    }
+  }
+
+  return caps;
+}
+
+GstCaps*
+gst_emul_codectype_to_caps (int media_type, CodecContext *ctx,
+    const char *name, gboolean encode)
+{
+  GstCaps *caps;
+
+  switch (media_type) {
+  case AVMEDIA_TYPE_VIDEO:
+    caps =
+        gst_emul_codectype_to_video_caps (ctx, name, encode, NULL);
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+    caps =
+        gst_emul_codectype_to_audio_caps (ctx, name, encode, NULL);
+   break;
+  default:
+    caps = NULL;
+    break;
+  }
+
+  return caps;
+}
+
+void
+gst_emul_caps_to_pixfmt (const GstCaps *caps, CodecContext *ctx, gboolean raw)
+{
+  GstStructure *str;
+  const GValue *fps;
+  const GValue *par = NULL;
+
+  GST_DEBUG ("converting caps %" GST_PTR_FORMAT, caps);
+  g_return_if_fail (gst_caps_get_size (caps) == 1);
+  str = gst_caps_get_structure (caps, 0);
+
+  gst_structure_get_int (str, "width", &ctx->video.width);
+  gst_structure_get_int (str, "height", &ctx->video.height);
+  gst_structure_get_int (str, "bpp", &ctx->video.bpp);
+
+  fps = gst_structure_get_value (str, "framerate");
+  if (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps)) {
+    ctx->video.fps_d = gst_value_get_fraction_numerator (fps);
+    ctx->video.fps_n = gst_value_get_fraction_denominator (fps);
+
+    GST_DEBUG ("setting framerate %d/%d = %lf",
+        ctx->video.fps_d, ctx->video.fps_n,
+        1. * ctx->video.fps_d / ctx->video.fps_n);
+  }
+
+  par = gst_structure_get_value (str, "pixel-aspect-ratio");
+  if (par && GST_VALUE_HOLDS_FRACTION (par)) {
+    ctx->video.par_n = gst_value_get_fraction_numerator (par);
+    ctx->video.par_d = gst_value_get_fraction_denominator (par);
+  }
+
+  if (!raw) {
+    return;
+  }
+
+  g_return_if_fail (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps));
+
+  if (strcmp (gst_structure_get_name (str), "video/x-raw-yuv") == 0) {
+    guint32 fourcc;
+
+    if (gst_structure_get_fourcc (str, "format", &fourcc)) {
+    switch (fourcc) {
+      case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
+        ctx->video.pix_fmt = PIX_FMT_YUYV422;
+        break;
+      case GST_MAKE_FOURCC ('I', '4', '2', '0'):
+        ctx->video.pix_fmt = PIX_FMT_YUV420P;
+        break;
+      case GST_MAKE_FOURCC ('A', '4', '2', '0'):
+        ctx->video.pix_fmt = PIX_FMT_YUVA420P;
+        break;
+      case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
+        ctx->video.pix_fmt = PIX_FMT_YUV411P;
+        break;
+      case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
+        ctx->video.pix_fmt = PIX_FMT_YUV422P;
+        break;
+      case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
+        ctx->video.pix_fmt = PIX_FMT_YUV410P;
+        break;
+      }
+    }
+  } else if (strcmp (gst_structure_get_name (str), "video/x-raw-rgb") == 0) {
+    gint bpp = 0, rmask = 0, endianness = 0;
+
+    if (gst_structure_get_int (str, "bpp", &bpp) &&
+      gst_structure_get_int (str, "endianness", &endianness)) {
+      if (gst_structure_get_int (str, "red_mask", &rmask)) {
+        switch (bpp) {
+        case 32:
+#if (G_BYTE_ORDER == G_BIG_ENDIAN)
+          if (rmask == 0x00ff0000) {
+#else
+          if (rmask == 0x00ff0000) {
+#endif
+            ctx->video.pix_fmt = PIX_FMT_RGB32;
+          }
+          break;
+        case 24:
+          if (rmask == 0x0000FF) {
+            ctx->video.pix_fmt = PIX_FMT_BGR24;
+          } else {
+            ctx->video.pix_fmt = PIX_FMT_RGB24;
+          }
+          break;
+        case 16:
+          if (endianness == G_BYTE_ORDER) {
+            ctx->video.pix_fmt = PIX_FMT_RGB565;
+          }
+          break;
+        case 15:
+          if (endianness == G_BYTE_ORDER) {
+            ctx->video.pix_fmt = PIX_FMT_RGB555;
+          }
+          break;
+        default:
+          break;
+        }
+      }
+    } else {
+      if (bpp == 8) {
+        ctx->video.pix_fmt = PIX_FMT_PAL8;
+        // get palette
+      }
+    }
+  } else if (strcmp (gst_structure_get_name (str), "video/x-raw-gray") == 0) {
+    gint bpp = 0;
+
+    if (gst_structure_get_int (str, "bpp", &bpp)) {
+      switch (bpp) {
+      case 8:
+        ctx->video.pix_fmt = PIX_FMT_GRAY8;
+        break;
+      }
+    }
+  }
+}
+
+void
+gst_emul_caps_to_smpfmt (const GstCaps *caps, CodecContext *ctx, gboolean raw)
+{
+  GstStructure *str;
+  gint depth = 0, width = 0, endianness = 0;
+  gboolean signedness = FALSE;
+  const gchar *name;
+
+  g_return_if_fail (gst_caps_get_size (caps) == 1);
+  str = gst_caps_get_structure (caps, 0);
+
+  gst_structure_get_int (str, "channels", &ctx->audio.channels);
+  gst_structure_get_int (str, "rate", &ctx->audio.sample_rate);
+  gst_structure_get_int (str, "block_align", &ctx->audio.block_align);
+  gst_structure_get_int (str, "bitrate", &ctx->audio.bit_rate);
+
+  if (!raw) {
+    return;
+  }
+
+#if 0
+  if (!strcmp (name, "audio/x-raw-float")) {
+    if (gst_structure_get_int (str, "width, &width") &&
+      gst_structure_get_int (str, "endianness", &endianness)) {
+      if (endianness == G_BYTE_ORDER) {
+        if (width == 32) {
+          ctx->audio.sample_fmt = SAMPLE_FMT_FLT;
+        } else if (width == 64) {
+          ctx->audio.sample_fmt = SAMPLE_FMT_DBL;
+        }
+      }
+    }
+  } else {
+    if (str_structure_get_int (str, "width", &width) &&
+      str_structure_get_int (str, "depth", &depth) &&
+      str_structure_get_int (str, "signed", &signedness) &&
+      str_structure_get_int (str, "endianness", &endianness)) {
+      if ((endianness == G_BYTE_ORDER) && (signedness == TRUE)) {
+        if (width == 16) && (depth == 16)) {
+          ctx->audio.sample_fmt = SAMPLE_FMT_S16;
+        } else if ((width == 32) && (depth == 32)) {
+          ctx->audio.sample_fmt = SMPLE_FMT_S32;
+        }
+      }
+    }
+  }
+#endif
+}
+
+void
+gst_emul_caps_with_codecname (const char *name, int media_type,
+    const GstCaps *caps, CodecContext *ctx)
+{
+  GstStructure *structure;
+  const GValue *value;
+  const GstBuffer *buf;
+
+  if (!ctx || !gst_caps_get_size (caps)) {
+    return;
+  }
+
+  structure = gst_caps_get_structure (caps, 0);
+
+  if ((value = gst_structure_get_value (structure, "codec_data"))) {
+  guint size;
+  guint8 *data;
+
+    buf = GST_BUFFER_CAST (gst_value_get_mini_object (value));
+    size = GST_BUFFER_SIZE (buf);
+    data = GST_BUFFER_DATA (buf);
+    printf("extradata: %p, size: %d\n", ctx->codecdata, ctx->codecdata_size);
+
+    if (ctx->codecdata) {
+      g_free (ctx->codecdata);
+    }
+
+    ctx->codecdata =
+        g_malloc0 (GST_ROUND_UP_16 (size + FF_INPUT_BUFFER_PADDING_SIZE));
+    memcpy (ctx->codecdata, data, size);
+    ctx->codecdata_size = size;
+
+    if ((strcmp(name, "vc1") == 0) && size > 0 && data[0] == 0) {
+      ctx->codecdata[0] = (guint8) size;
+    }
+  } else if (ctx->codecdata == NULL) {
+    ctx->codecdata_size = 0;
+    ctx->codecdata = g_malloc0 (GST_ROUND_UP_16(FF_INPUT_BUFFER_PADDING_SIZE));
+    GST_DEBUG ("no extra data.\n");
+  }
+
+  if ((strcmp (name, "mpeg4") == 0)) {
+    const gchar *mime = gst_structure_get_name (structure);
+
+#if 0
+    if (!strcmp (mime, "video/x-divx")) {
+      ctx->codec_tag = GST_MAKE_FOURCC ('D', 'I', 'V', 'X');
+    } else if (!strcmp (mime, "video/x-xvid")) {
+      ctx->codec_tag = GST_MAKE_FOURCC ('X', 'V', 'I', 'D');
+    } else if (!strcmp (mime, "video/x-3ivx")) {
+      ctx->codec_tag = GST_MAKE_FOURCC ('3', 'I', 'V', '1');
+    } else if (!strcmp (mime, "video/mpeg")) {
+      ctx->codec_tag = GST_MAKE_FOURCC ('m', 'p', '4', 'v');
+    }
+#endif
+  } else if (strcmp (name, "h263p") == 0) {
+    gboolean val;
+
+#if 0
+    if (!gst_structure_get_boolean (structure, "annex-f", &val) || val) {
+      ctx->flags |= CODEC_FLAG_4MV;
+    } else {
+      ctx->flags &= ~CODEC_FLAG_4MV;
+    }
+    if ((!gst_structure_get_boolean (structure, "annex-i", &val) || val) &&
+      (!gst_structure_get_boolean (structure, "annex-t", &val) || val) {
+      ctx->flags |= CODEC_FLAG_AC_PRED;
+    } else {
+      ctx->flags &= ~CODEC_FLAG_AC_PRED;
+    }
+    if ((!gst_structure_get_boolean (structure, "annex-j", &val) || val) {
+      ctx->flags |= CODEC_FLAG_LOOP_FILTER;
+    } else {
+      ctx->flags &= ~CODEC_FLAG_LOOP_FILTER;
+    }
+#endif
+  } else {
+  // TODO
+  }
+
+  if (!gst_caps_is_fixed (caps)) {
+    return;
+  }
+
+  switch (media_type) {
+  case AVMEDIA_TYPE_VIDEO:
+    gst_emul_caps_to_pixfmt (caps, ctx, FALSE);
+  // get_palette
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+    gst_emul_caps_to_smpfmt (caps, ctx, FALSE);
+    break;
+  default:
+    break;
+  }
+
+}
+
+GstCaps *
+gst_emul_video_caps_new (CodecContext *ctx, const char *name,
+        const char *mimetype, const char *fieldname, ...)
+{
+  GstStructure *structure = NULL;
+  GstCaps *caps = NULL;
+  va_list var_args;
+  gint i;
+
+  GST_LOG ("context: %p, name: %s, mimetype: %s", ctx, name, mimetype);
+
+  if (ctx != NULL && ctx->video.width != -1) {
+    gint num, denom;
+
+    caps = gst_caps_new_simple (mimetype,
+      "width", G_TYPE_INT, ctx->video.width,
+      "height", G_TYPE_INT, ctx->video.height);
+
+    num = ctx->video.fps_d / 1;
+    denom = ctx->video.fps_d;
+
+    if (!denom) {
+      GST_LOG ("invalid framerate: %d/0, -> %d/1", num, num);
+    }
+    if (gst_util_fraction_compare (num, denom, 1000, 1) > 0) {
+      GST_LOG ("excessive framerate: %d/%d, -> 0/1", num, denom);
+      num = 0;
+      denom = 1;
+    }
+    GST_LOG ("setting framerate: %d/%d", num, denom);
+    gst_caps_set_simple (caps,
+      "framerate", GST_TYPE_FRACTION, num, denom, NULL);
+  } else {
+    if (g_str_has_prefix(name, "h263")) {
+      /* 128x96, 176x144, 352x288, 704x576, and 1408x1152. slightly reordered
+       * because we want automatic negotiation to go as close to 320x240 as
+       * possible. */
+      const static gint widths[] = { 352, 704, 176, 1408, 128 };
+      const static gint heights[] = { 288, 576, 144, 1152, 96 };
+      GstCaps *temp;
+      gint n_sizes = G_N_ELEMENTS (widths);
+
+      caps = gst_caps_new_empty ();
+      for (i = 0; i < n_sizes; i++) {
+        temp = gst_caps_new_simple (mimetype,
+                      "width", G_TYPE_INT, widths[i],
+                      "height", G_TYPE_INT, heights[i],
+                      "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
+
+        gst_caps_append (caps, temp);
+      }
+    } else {
+      // TODO
+    }
+  }
+
+  /* no fixed caps or special restrictions applied;
+   * default unfixed setting */
+  if (!caps) {
+    GST_DEBUG ("Creating default caps");
+    caps = gst_caps_new_simple (mimetype,
+            "width", GST_TYPE_INT_RANGE, 16, 4096,
+            "height", GST_TYPE_INT_RANGE, 16, 4096,
+             "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
+  }
+
+  for (i = 0; i < gst_caps_get_size (caps); i++) {
+    va_start (var_args, fieldname);
+    structure = gst_caps_get_structure (caps, i);
+    gst_structure_set_valist (structure, fieldname, var_args);
+    va_end (var_args);
+  }
+
+  return caps;
+}
+
+GstCaps *
+gst_emul_audio_caps_new (CodecContext *ctx, const char *name,
+        const char *mimetype, const char *fieldname, ...)
+{
+  GstStructure *structure = NULL;
+  GstCaps *caps = NULL;
+  gint i;
+  va_list var_args;
+
+  if (ctx != NULL && ctx->audio.channels != -1) {
+    GstAudioChannelPosition *pos;
+    guint64 channel_layout = ctx->audio.channel_layout;
+
+    if (channel_layout == 0) {
+      const guint64 default_channel_set[] = {
+        0, 0, CH_LAYOUT_SURROUND, CH_LAYOUT_QUAD, CH_LAYOUT_5POINT0,
+        CH_LAYOUT_5POINT1, 0, CH_LAYOUT_7POINT1
+      };
+
+      if (strcmp(name, "ac3") == 0) {
+        if (ctx->audio.channels > 0 &&
+          ctx->audio.channels < G_N_ELEMENTS (default_channel_set)) {
+          channel_layout = default_channel_set[ctx->audio.channels - 1];
+        }
+      } else {
+        // TODO
+      }
+    }
+
+    caps = gst_caps_new_simple (mimetype,
+            "rate", G_TYPE_INT, ctx->audio.sample_rate,
+            "channels", G_TYPE_INT, ctx->audio.channels, NULL);
+
+    pos = gst_ff_channel_layout_to_gst (channel_layout, ctx->audio.channels);
+    if (pos != NULL) {
+      gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos);
+      g_free (pos);
+    }
+  } else {
+    gint maxchannels = 2;
+    const gint *rates = NULL;
+    gint n_rates = 0;
+
+    if (strcmp(name, "aac") == 0) {
+      maxchannels = 6;
+    } else if (g_str_has_prefix(name, "ac3")) {
+      const static gint l_rates[] = { 48000, 44100, 32000 };
+      maxchannels = 6;
+      n_rates = G_N_ELEMENTS (l_rates);
+      rates = l_rates;
+    } else {
+     // TODO
+    }
+
+    if (maxchannels == 1) {
+      caps = gst_caps_new_simple(mimetype,
+              "channels", G_TYPE_INT, maxchannels, NULL);
+    } else {
+      caps = gst_caps_new_simple(mimetype,
+              "channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL);
+    }
+
+    if (n_rates) {
+      GValue list = { 0, };
+      GstStructure *structure;
+
+      g_value_init(&list, GST_TYPE_LIST);
+      for (i = 0; i < n_rates; i++) {
+        GValue v = { 0, };
+
+        g_value_init(&v, G_TYPE_INT);
+        g_value_set_int(&v, rates[i]);
+        gst_value_list_append_value(&list, &v);
+        g_value_unset(&v);
+      }
+      structure = gst_caps_get_structure(caps, 0);
+      gst_structure_set_value(structure, "rate", &list);
+      g_value_unset(&list);
+    } else {
+      gst_caps_set_simple(caps, "rate", GST_TYPE_INT_RANGE, 4000, 96000, NULL);
+    }
+  }
+
+  for (i = 0; i < gst_caps_get_size (caps); i++) {
+    va_start (var_args, fieldname);
+    structure = gst_caps_get_structure (caps, i);
+    gst_structure_set_valist (structure, fieldname, var_args);
+    va_end (var_args);
+  }
+
+  return caps;
+}
+
+GstCaps *
+gst_emul_pixfmt_to_caps (enum PixelFormat pix_fmt, CodecContext *ctx, const char *name)
+{
+  GstCaps *caps = NULL;
+
+  int bpp = 0, depth = 0, endianness = 0;
+  gulong g_mask = 0, r_mask = 0, b_mask = 0, a_mask = 0;
+  guint32 fmt = 0;
+
+  switch (pix_fmt) {
+  case PIX_FMT_YUV420P:
+    fmt = GST_MAKE_FOURCC ('I', '4', '2', '0');
+    break;
+  case PIX_FMT_YUYV422:
+    fmt = GST_MAKE_FOURCC ('A', '4', '2', '0');
+    break;
+  case PIX_FMT_RGB24:
+    bpp = depth = 24;
+    endianness = G_BIG_ENDIAN;
+    r_mask = 0xff0000;
+    g_mask = 0x00ff00;
+    b_mask = 0x0000ff;
+    break;
+  case PIX_FMT_BGR24:
+    bpp = depth = 24;
+    endianness = G_BIG_ENDIAN;
+    r_mask = 0x0000ff;
+    g_mask = 0x00ff00;
+    b_mask = 0xff0000;
+    break;
+  case PIX_FMT_YUV422P:
+    fmt = GST_MAKE_FOURCC ('Y', '4', '2', 'B');
+    break;
+  case PIX_FMT_YUV444P:
+    fmt = GST_MAKE_FOURCC ('Y', '4', '4', '4');
+    break;
+  case PIX_FMT_RGB32:
+    bpp = 32;
+    depth = 32;
+    endianness = G_BIG_ENDIAN;
+#if (G_BYTE_ORDER == G_BIG_ENDIAN)
+    r_mask = 0x00ff0000;
+    g_mask = 0x0000ff00;
+    b_mask = 0x000000ff;
+    a_mask = 0xff000000;
+#else
+    r_mask = 0x00ff0000;
+    g_mask = 0x0000ff00;
+    b_mask = 0x000000ff;
+    a_mask = 0xff000000;
+#endif
+    break;
+  case PIX_FMT_YUV410P:
+    fmt = GST_MAKE_FOURCC ('Y', 'U', 'V', '9');
+    break;
+  case PIX_FMT_YUV411P:
+    fmt = GST_MAKE_FOURCC ('Y', '4', '1', 'b');
+    break;
+  case PIX_FMT_RGB565:
+    bpp = depth = 16;
+    endianness = G_BYTE_ORDER;
+    r_mask = 0xf800;
+    g_mask = 0x07e0;
+    b_mask = 0x001f;
+    break;
+  case PIX_FMT_RGB555:
+    bpp = 16;
+    depth = 15;
+    endianness = G_BYTE_ORDER;
+    r_mask = 0x7c00;
+    g_mask = 0x03e0;
+    b_mask = 0x001f;
+    break;
+  default:
+    break;
+  }
+
+  if (caps != NULL) {
+    if (bpp != 0) {
+      if (r_mask != 0) {
+        if (a_mask) {
+        caps = gst_emul_video_caps_new (ctx, name, "video/x-raw-rgb",
+                "bpp", G_TYPE_INT, bpp,
+                "depth", G_TYPE_INT, depth,
+                "red_mask", G_TYPE_INT, r_mask,
+                "green_mask", G_TYPE_INT, g_mask,
+                "blue_mask", G_TYPE_INT, b_mask,
+                "alpha_mask", G_TYPE_INT, a_mask,
+                "endianness", G_TYPE_INT, endianness, NULL);
+        } else {
+          caps = gst_emul_video_caps_new (ctx, name, "video/x-raw-rgb",
+                  "bpp", G_TYPE_INT, bpp,
+                  "depth", G_TYPE_INT, depth,
+                  "red_mask", G_TYPE_INT, r_mask,
+                  "green_mask", G_TYPE_INT, g_mask,
+                  "blue_mask", G_TYPE_INT, b_mask,
+                  "alpha_mask", G_TYPE_INT, a_mask,
+                  "endianness", G_TYPE_INT, endianness, NULL);
+        }
+      } else {
+        caps = gst_emul_video_caps_new (ctx, name, "video/x-raw-rgb",
+                  "bpp", G_TYPE_INT, bpp,
+                  "depth", G_TYPE_INT, depth,
+                  "endianness", G_TYPE_INT, endianness, NULL);
+        if (caps && ctx) {
+          // set paletee
+        }
+      }
+    } else if (fmt) {
+      caps = gst_emul_video_caps_new (ctx, name, "video/x-raw-yuv",
+               "format", GST_TYPE_FOURCC, fmt, NULL);
+    }
+  }
+
+  if (caps != NULL) {
+    GST_DEBUG ("caps for pix_fmt=%d: %", GST_PTR_FORMAT, pix_fmt, caps);
+  } else {
+    GST_LOG ("No caps found for pix_fmt=%d", pix_fmt);
+  }
+
+  return caps;
+}
+
+GstCaps *
+gst_emul_smpfmt_to_caps (int8_t sample_fmt, CodecContext *ctx, const char *name)
+{
+  GstCaps *caps = NULL;
+
+  int bpp = 0;
+  gboolean integer = TRUE;
+  gboolean signedness = FALSE;
+
+  switch (sample_fmt) {
+  case SAMPLE_FMT_S16:
+    signedness = TRUE;
+    bpp = 16;
+    break;
+  case SAMPLE_FMT_S32:
+    signedness = TRUE;
+    bpp = 32;
+    break;
+  case SAMPLE_FMT_FLT:
+    integer = FALSE;
+    bpp = 32;
+    break;
+  case SAMPLE_FMT_DBL:
+    integer = FALSE;
+    bpp = 64;
+    break;
+  default:
+    break;
+  }
+
+  if (bpp) {
+    if (integer) {
+      caps = gst_emul_audio_caps_new (ctx, name, "audio/x-raw-int",
+          "signed", G_TYPE_BOOLEAN, signedness,
+          "endianness", G_TYPE_INT, G_BYTE_ORDER,
+          "width", G_TYPE_INT, bpp, "depth", G_TYPE_INT, bpp, NULL);
+    } else {
+      caps = gst_emul_audio_caps_new (ctx, name, "audio/x-raw-float",
+          "endianness", G_TYPE_INT, G_BYTE_ORDER,
+          "width", G_TYPE_INT, bpp, NULL);
+    }
+  }
+
+  if (caps != NULL) {
+    GST_LOG ("caps for sample_fmt=%d: %" GST_PTR_FORMAT, sample_fmt, caps);
+  } else {
+    GST_LOG ("No caps found for sample_fmt=%d", sample_fmt);
+  }
+
+  return caps;
+}
+
+GstCaps *
+gst_emul_codecname_to_caps (const char *name, CodecContext *ctx, gboolean encode)
+{
+  GstCaps *caps = NULL;
+
+  GST_LOG ("codec: %s, context: %p, encode: %d", name, ctx, encode);
+
+  if (strcmp(name, "mpegvideo") == 0) {
+    caps = gst_emul_video_caps_new (ctx, name, "video/mpeg",
+                "mpegversion", G_TYPE_INT, 1,
+                "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
+  } else if (strcmp(name, "h263") == 0) {
+    if (encode) {
+      caps = gst_emul_video_caps_new (ctx, name, "video/x-h263",
+                  "variant", G_TYPE_STRING, "itu", NULL);
+    } else {
+      caps = gst_emul_video_caps_new (ctx, name, "video/x-h263",
+                  "variant", G_TYPE_STRING, "itu",
+                  "h263version", G_TYPE_STRING, "h263", NULL);
+    }
+  } else if (strcmp(name, "h263p") == 0) {
+    caps = gst_emul_video_caps_new (ctx, name, "video/x-h263",
+              "variant", G_TYPE_STRING, "itu",
+              "h263version", G_TYPE_STRING, "h263p", NULL);
+#if 0
+    if (encode && ctx) {
+      gst_caps_set_simple (caps,
+        "annex-f", G_TYPE_BOOLEAN, ctx->flags & CODEC_FLAG_4MV,
+        "annex-j", G_TYPE_BOOLEAN, ctx->flags & CODEC_FLAG_LOOP_FILTER,
+        "annex-i", G_TYPE_BOOLEAN, ctx->flags & CODEC_FLAG_AC_PRED,
+        "annex-t", G_TYPE_BOOLEAN, ctx->flags & CODEC_FLAG_AC_PRED,
+        NULL);
+    }
+#endif
+  } else if (strcmp(name, "mpeg4") == 0) {
+    if (encode && ctx != NULL) {
+      // TODO
+    } else {
+      caps = gst_emul_video_caps_new (ctx, name, "video/mpeg",
+            "mpegversion", G_TYPE_INT, 4,
+            "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
+      if (encode) {
+        caps = gst_emul_video_caps_new (ctx, name, "video/mpeg",
+            "mpegversion", G_TYPE_INT, 4,
+            "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
+      } else {
+        gst_caps_append (caps, gst_emul_video_caps_new (ctx, name,
+            "video/x-divx", "divxversion", GST_TYPE_INT_RANGE, 4, 5, NULL));
+        gst_caps_append (caps, gst_emul_video_caps_new (ctx, name,
+            "video/x-xvid", NULL));
+        gst_caps_append (caps, gst_emul_video_caps_new (ctx, name,
+            "video/x-3ivx", NULL));
+      }
+    }
+  } else if (strcmp(name, "h264") == 0) {
+      caps = gst_emul_video_caps_new (ctx, name, "video/x-h264", NULL);
+  } else if (g_str_has_prefix(name, "msmpeg4")) {
+    // msmpeg4v1,m msmpeg4v2, msmpeg4
+    gint version;
+
+    if (strcmp(name, "msmpeg4v1") == 0) {
+      version = 41;
+    } else if (strcmp(name, "msmpeg4v2") == 0) {
+      version = 42;
+    } else {
+      version = 43;
+    }
+
+    caps = gst_emul_video_caps_new (ctx, name, "video/x-msmpeg",
+          "msmpegversion", G_TYPE_INT, version, NULL);
+    if (!encode && !strcmp(name, "msmpeg4")) {
+       gst_caps_append (caps, gst_emul_video_caps_new (ctx, name,
+            "video/x-divx", "divxversion", G_TYPE_INT, 3, NULL));
+    }
+  } else if (strcmp(name, "wmv3") == 0) {
+    caps = gst_emul_video_caps_new (ctx, name, "video/x-wmv",
+                "wmvversion", G_TYPE_INT, 3, NULL);
+  } else if (strcmp(name, "vc1") == 0) {
+    caps = gst_emul_video_caps_new (ctx, name, "video/x-wmv",
+                "wmvversion", G_TYPE_INT, 3, "format", GST_TYPE_FOURCC,
+                GST_MAKE_FOURCC ('W', 'V', 'C', '1'),  NULL);
+#if 0
+  } else if (strcmp(name, "vp3") == 0) {
+    mime_type = g_strdup ("video/x-vp3");
+  } else if (strcmp(name, "vp8") == 0) {
+    mime_type = g_strdup ("video/x-vp8");
+#endif
+  } else if (strcmp(name, "aac") == 0) {
+    caps = gst_emul_audio_caps_new (ctx, name, "audio/mpeg", NULL);
+    if (!encode) {
+        GValue arr = { 0, };
+        GValue item = { 0, };
+
+        g_value_init (&arr, GST_TYPE_LIST);
+        g_value_init (&item, G_TYPE_INT);
+        g_value_set_int (&item, 2);
+        gst_value_list_append_value (&arr, &item);
+        g_value_set_int (&item, 4);
+        gst_value_list_append_value (&arr, &item);
+        g_value_unset (&item);
+
+        gst_caps_set_value (caps, "mpegversion", &arr);
+        g_value_unset (&arr);
+
+        g_value_init (&arr, GST_TYPE_LIST);
+        g_value_init (&item, G_TYPE_STRING);
+        g_value_set_string (&item, "raw");
+        gst_value_list_append_value (&arr, &item);
+        g_value_set_string (&item, "adts");
+        gst_value_list_append_value (&arr, &item);
+        g_value_set_string (&item, "adif");
+        gst_value_list_append_value (&arr, &item);
+        g_value_unset (&item);
+
+        gst_caps_set_value (caps, "stream-format", &arr);
+        g_value_unset (&arr);
+    } else {
+      gst_caps_set_simple (caps, "mpegversion", G_TYPE_INT, 4,
+        "stream-format", G_TYPE_STRING, "raw",
+        "base-profile", G_TYPE_STRING, "lc", NULL);
+#if 1
+        if (ctx && ctx->codecdata_size > 0) {
+          gst_codec_utils_aac_caps_set_level_and_profile (caps,
+            ctx->codecdata, ctx->codecdata_size);
+        }
+#endif
+    }
+  } else if (strcmp(name, "ac3") == 0) {
+    caps = gst_emul_audio_caps_new (ctx, name, "audio/x-ac3", NULL);
+  } else if (strcmp(name, "mp3") == 0) {
+#if 0
+    if (encode) {
+      caps = gst_emul_audio_caps_new (ctx, name, "audio/mpeg",
+              "mpegversion", G_TYPE_INT, 1,
+              "layer", GST_TYPE_INT_RANGE, 1, 3, NULL);
+    } else {
+#endif
+      caps = gst_caps_new_simple("audio/mpeg",
+              "mpegversion", G_TYPE_INT, 1,
+              "layer", GST_TYPE_INT_RANGE, 1, 3, NULL);
+//    }
+  } else if (strcmp(name, "mp3adu") == 0) {
+    gchar *mime_type;
+
+    mime_type = g_strdup_printf ("audio/x-gst_ff-%s", name);
+    caps = gst_emul_audio_caps_new (ctx, name, mime_type, NULL);
+
+    if (mime_type) {
+      g_free(mime_type);
+    }
+  } else if (g_str_has_prefix(name, "wmav")) {
+    gint version = 1;
+    if (strcmp(name, "wmav2") == 0) {
+      version = 2;
+    }
+    caps = gst_emul_audio_caps_new (ctx, name, "audio/x-wma", "wmaversion",
+          G_TYPE_INT, version, "block_align", GST_TYPE_INT_RANGE, 0, G_MAXINT,
+          "bitrate", GST_TYPE_INT_RANGE, 0, G_MAXINT, NULL);
+  } else {
+    GST_ERROR("failed to new caps for %s.\n", name);
+  }
+
+  return caps;
+}
+
+typedef struct PixFmtInfo
+{
+  uint8_t x_chroma_shift;       /* X chroma subsampling factor is 2 ^ shift */
+  uint8_t y_chroma_shift;       /* Y chroma subsampling factor is 2 ^ shift */
+} PixFmtInfo;
+
+static PixFmtInfo pix_fmt_info[PIX_FMT_NB];
+
+#define GEN_MASK(x) ((1<<(x))-1)
+#define ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) & ~GEN_MASK(x))
+#define ROUND_UP_2(x) ROUND_UP_X(x, 1)
+#define ROUND_UP_4(x) ROUND_UP_X(x, 2)
+#define ROUND_UP_8(x) ROUND_UP_X(x, 3)
+#define DIV_ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) >> (x))
+
+void
+gst_emul_init_pix_fmt_info (void)
+{
+  pix_fmt_info[PIX_FMT_YUV420P].x_chroma_shift = 1,
+  pix_fmt_info[PIX_FMT_YUV420P].y_chroma_shift = 1;
+
+  pix_fmt_info[PIX_FMT_YUV422P].x_chroma_shift = 1;
+  pix_fmt_info[PIX_FMT_YUV422P].y_chroma_shift = 0;
+
+  pix_fmt_info[PIX_FMT_YUV444P].x_chroma_shift = 0;
+  pix_fmt_info[PIX_FMT_YUV444P].y_chroma_shift = 0;
+
+  pix_fmt_info[PIX_FMT_YUYV422].x_chroma_shift = 1;
+  pix_fmt_info[PIX_FMT_YUYV422].y_chroma_shift = 0;
+
+  pix_fmt_info[PIX_FMT_YUV410P].x_chroma_shift = 2;
+  pix_fmt_info[PIX_FMT_YUV410P].y_chroma_shift = 2;
+
+  pix_fmt_info[PIX_FMT_YUV411P].x_chroma_shift = 2;
+  pix_fmt_info[PIX_FMT_YUV411P].y_chroma_shift = 0;
+
+  /* RGB formats */
+  pix_fmt_info[PIX_FMT_RGB24].x_chroma_shift = 0;
+  pix_fmt_info[PIX_FMT_RGB24].y_chroma_shift = 0;
+
+  pix_fmt_info[PIX_FMT_BGR24].x_chroma_shift = 0;
+  pix_fmt_info[PIX_FMT_BGR24].y_chroma_shift = 0;
+
+  pix_fmt_info[PIX_FMT_RGB32].x_chroma_shift = 0;
+  pix_fmt_info[PIX_FMT_RGB32].y_chroma_shift = 0;
+
+  pix_fmt_info[PIX_FMT_RGB565].x_chroma_shift = 0;
+  pix_fmt_info[PIX_FMT_RGB565].y_chroma_shift = 0;
+
+  pix_fmt_info[PIX_FMT_RGB555].x_chroma_shift = 0;
+  pix_fmt_info[PIX_FMT_RGB555].y_chroma_shift = 0;
+}
+
+int
+gst_emul_avpicture_size (int pix_fmt, int width, int height)
+{
+  int size, w2, h2, size2;
+  int stride, stride2;
+  int fsize;
+  PixFmtInfo *pinfo;
+
+  pinfo = &pix_fmt_info[pix_fmt];
+
+  switch (pix_fmt) {
+  case PIX_FMT_YUV420P:
+  case PIX_FMT_YUV422P:
+  case PIX_FMT_YUV444P:
+  case PIX_FMT_YUV410P:
+  case PIX_FMT_YUV411P:
+    stride = ROUND_UP_4(width);
+    h2 = ROUND_UP_X(height, pinfo->y_chroma_shift);
+    size = stride * h2;
+    w2 = DIV_ROUND_UP_X(width, pinfo->x_chroma_shift);
+    stride2 = ROUND_UP_4(w2);
+    h2 = DIV_ROUND_UP_X(height, pinfo->y_chroma_shift);
+    size2 = stride2 * h2;
+    fsize = size + 2 * size2;
+    break;
+  case PIX_FMT_RGB24:
+  case PIX_FMT_BGR24:
+    stride = ROUND_UP_4 (width * 3);
+    fsize = stride * height;
+    break;
+  case PIX_FMT_RGB32:
+    stride = width * 4;
+    fsize = stride * height;
+    break;
+  case PIX_FMT_RGB555:
+  case PIX_FMT_RGB565:
+    stride = ROUND_UP_4 (width * 2);
+    fsize = stride * height;
+    break;
+  default:
+    fsize = -1;
+    break;
+  }
+
+  return fsize;
+}
diff --git a/src/gstemulutils.h b/src/gstemulutils.h
new file mode 100644 (file)
index 0000000..b07076e
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * GStreamer codec plugin for Tizen Emulator.
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * KiTae Kim <kt920.kim@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#ifndef __GST_EMUL_UTIL_H__
+#define __GST_EMUL_UTIL_H__
+
+#include "gstemulcommon.h"
+
+// FFmpeg
+#include "audioconvert.h"
+
+/* Audio channel masks */
+#define CH_FRONT_LEFT            AV_CH_FRONT_LEFT
+#define CH_FRONT_RIGHT           AV_CH_FRONT_RIGHT
+#define CH_FRONT_CENTER          AV_CH_FRONT_CENTER
+#define CH_LOW_FREQUENCY         AV_CH_LOW_FREQUENCY
+#define CH_BACK_LEFT             AV_CH_BACK_LEFT
+#define CH_BACK_RIGHT            AV_CH_BACK_RIGHT
+#define CH_FRONT_LEFT_OF_CENTER  AV_CH_FRONT_LEFT_OF_CENTER
+#define CH_FRONT_RIGHT_OF_CENTER AV_CH_FRONT_RIGHT_OF_CENTER
+#define CH_BACK_CENTER           AV_CH_BACK_CENTER
+#define CH_SIDE_LEFT             AV_CH_SIDE_LEFT
+#define CH_SIDE_RIGHT            AV_CH_SIDE_RIGHT
+#define CH_TOP_CENTER            AV_CH_TOP_CENTER
+#define CH_TOP_FRONT_LEFT        AV_CH_TOP_FRONT_LEFT
+#define CH_TOP_FRONT_CENTER      AV_CH_TOP_FRONT_CENTER
+#define CH_TOP_FRONT_RIGHT       AV_CH_TOP_FRONT_RIGHT
+#define CH_TOP_BACK_LEFT         AV_CH_TOP_BACK_LEFT
+#define CH_TOP_BACK_CENTER       AV_CH_TOP_BACK_CENTER
+#define CH_TOP_BACK_RIGHT        AV_CH_TOP_BACK_RIGHT
+#define CH_STEREO_LEFT           AV_CH_STEREO_LEFT
+#define CH_STEREO_RIGHT          AV_CH_STEREO_RIGHT
+
+/** Channel mask value used for AVCodecContext.request_channel_layout
+    to indicate that the user requests the channel order of the decoder output
+    to be the native codec channel order. */
+#define CH_LAYOUT_NATIVE         AV_CH_LAYOUT_NATIVE
+
+/* Audio channel convenience macros */
+#define CH_LAYOUT_MONO           AV_CH_LAYOUT_MONO
+#define CH_LAYOUT_STEREO         AV_CH_LAYOUT_STEREO
+#define CH_LAYOUT_2_1            AV_CH_LAYOUT_2_1
+#define CH_LAYOUT_SURROUND       AV_CH_LAYOUT_SURROUND
+#define CH_LAYOUT_4POINT0        AV_CH_LAYOUT_4POINT0
+#define CH_LAYOUT_2_2            AV_CH_LAYOUT_2_2
+#define CH_LAYOUT_QUAD           AV_CH_LAYOUT_QUAD
+#define CH_LAYOUT_5POINT0        AV_CH_LAYOUT_5POINT0
+#define CH_LAYOUT_5POINT1        AV_CH_LAYOUT_5POINT1
+#define CH_LAYOUT_5POINT0_BACK   AV_CH_LAYOUT_5POINT0_BACK
+#define CH_LAYOUT_5POINT1_BACK   AV_CH_LAYOUT_5POINT1_BACK
+#define CH_LAYOUT_7POINT0        AV_CH_LAYOUT_7POINT0
+#define CH_LAYOUT_7POINT1        AV_CH_LAYOUT_7POINT1
+#define CH_LAYOUT_7POINT1_WIDE   AV_CH_LAYOUT_7POINT1_WIDE
+#define CH_LAYOUT_STEREO_DOWNMIX AV_CH_LAYOUT_STEREO_DOWNMIX
+
+GstCaps *gst_emul_codectype_to_video_caps (CodecContext *ctx, const char *name,
+    gboolean encode, CodecElement *codec);
+
+GstCaps *gst_emul_codectype_to_audio_caps (CodecContext *ctx, const char *name,
+    gboolean encode, CodecElement *codec);
+
+
+GstCaps *gst_emul_codectype_to_caps (int media_type, CodecContext *ctx,
+    const char *name, gboolean encode);
+
+void gst_emul_caps_with_codecname (const char *name, int media_type,
+    const GstCaps *caps, CodecContext *ctx);
+
+GstCaps *gst_emul_video_caps_new (CodecContext *ctx, const char *name,
+        const char *mimetype, const char *fieldname, ...);
+
+GstCaps *gst_emul_audio_caps_new (CodecContext *ctx, const char *name,
+        const char *mimetype, const char *fieldname, ...);
+
+GstCaps *gst_emul_pixfmt_to_caps (enum PixelFormat pix_fmt, CodecContext *ctx, const char *name);
+
+GstCaps *gst_emul_smpfmt_to_caps (int8_t sample_fmt, CodecContext *ctx, const char *name);
+
+GstCaps *gst_emul_codecname_to_caps (const char *name, CodecContext *ctx, gboolean encode);
+
+#endif