Changed a way to use device memory effectively.
authorKitae Kim <kt920.kim@samsung.com>
Wed, 11 Sep 2013 12:30:57 +0000 (21:30 +0900)
committerKitae Kim <kt920.kim@samsung.com>
Fri, 13 Sep 2013 06:42:40 +0000 (15:42 +0900)
Divide device memory into small, medium and large size of buffer
to use the memory effectively when decoding many contexts.

In case of meta data such as width, height, framerate and etc,
each context uses 256byte memory region and utilizes the large size of memory
when copying video and audio buffer.

Change-Id: I37e111ec1540694d32380906132d79cd90a658ef
Signed-off-by: Kitae Kim <kt920.kim@samsung.com>
28 files changed:
configure.ac
packaging/gst-plugins-emulator.changes
packaging/gst-plugins-emulator.spec
src/Makefile.am
src/gstemul.c [deleted file]
src/gstemulapi.c [deleted file]
src/gstemulapi.h [deleted file]
src/gstemulapi2.c [deleted file]
src/gstemulapi2.h [deleted file]
src/gstemulcommon.h [deleted file]
src/gstemuldec.c [deleted file]
src/gstemuldev.c [deleted file]
src/gstemuldev.h [deleted file]
src/gstemulenc.c [deleted file]
src/gstemulutils.c [deleted file]
src/gstemulutils.h [deleted file]
src/gstmaru.c [new file with mode: 0644]
src/gstmaru.h [new file with mode: 0644]
src/gstmarudec.c [new file with mode: 0644]
src/gstmarudevice.c [new file with mode: 0644]
src/gstmarudevice.h [new file with mode: 0644]
src/gstmaruenc.c [new file with mode: 0644]
src/gstmaruinterface.c [new file with mode: 0644]
src/gstmaruinterface.h [new file with mode: 0644]
src/gstmarumem.c [new file with mode: 0644]
src/gstmarumem.h [new file with mode: 0644]
src/gstmaruutils.c [new file with mode: 0644]
src/gstmaruutils.h [new file with mode: 0644]

index ef84094f5efe86bbfba8f9328c010c1e489943c7..70d1eb1a4aa93561bec8537eae5433346b386a6c 100644 (file)
@@ -8,7 +8,7 @@ dnl required versions of gstreamer and plugins-base
 GST_REQUIRED=0.10.16
 GSTPB_REQUIRED=0.10.16
 
-AC_CONFIG_SRCDIR([src/gstemul.c])
+AC_CONFIG_SRCDIR([src/gstmaru.c])
 AC_CONFIG_HEADERS([config.h])
 
 dnl required version of automake
index 0bc41b7f229cf58be405794f0d2dbe3c3f5798a3..daf3fae59af37a87ac16e3f87f8db81fe27efb6b 100644 (file)
@@ -1,3 +1,6 @@
+* Wed Sep 11 12:32:26 UTC 2013 Kitae Kim <kt920.kim@samsung.com>
+-  changed a way to use device memory effectively.
+
 * Wed Aug 21 06:04:11 UTC 2013 Kitae Kim <kt920.kim@samsung.com>
 - fixed prevent issues.
 
@@ -8,4 +11,3 @@
 - fixed prevent issues.
 
 * Fri Jun 21 11:49:35 UTC 2013 Kitae Kim <kt920.kim@samsung.com>
-- improved architecture of gstreamer codec plugin.
index 81fd9a4810697318541b53aaf77e6f5acac1ae0f..d386a24b83ec2543db00078ed753fb84238c3df0 100644 (file)
@@ -1,5 +1,5 @@
 Name: gst-plugins-emulator
-Version: 0.1.4
+Version: 0.1.5
 Release: 2 
 Summary: GStreamer Streaming-media framework plug-in for Tizen emulator.
 Group: TO_BE/FILLED_IN
index dba449ecb8a9a16008206499b3f45406ac9dabfd..1fbc451314532c04dc0a77ee97142e9e3dc0d267 100644 (file)
@@ -14,13 +14,13 @@ plugin_LTLIBRARIES = libgstemul.la
 ##############################################################################
 
 # sources used to compile this plug-in
-libgstemul_la_SOURCES = gstemul.c \
-       gstemulutils.c \
-       gstemuldec.c \
-       gstemulenc.c \
-       gstemulapi.c \
-       gstemuldev.c \
-       gstemulapi2.c
+libgstemul_la_SOURCES = gstmaru.c \
+       gstmaruutils.c \
+       gstmarudec.c \
+       gstmaruenc.c \
+       gstmaruinterface.c \
+       gstmarudevice.c \
+       gstmarumem.c
 
 # compiler and linker flags used to compile this plugin, set in configure.ac
 libgstemul_la_CFLAGS = $(GST_CFLAGS) -g
@@ -29,4 +29,4 @@ libgstemul_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 libgstemul_la_LIBTOOLFLAGS = --tag=disable-static
 
 # headers we need but don't want installed
-#noinst_HEADERS = gstemul.h
+#noinst_HEADERS = gstmaru.h
diff --git a/src/gstemul.c b/src/gstemul.c
deleted file mode 100644 (file)
index 54cd4af..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * 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.
- */
-
-/* First, include the header file for the plugin, to bring in the
- * object definition and other useful things.
- */
-
-/*
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-#include "gstemulcommon.h"
-
-GST_DEBUG_CATEGORY (emul_debug);
-
-#define GST_TYPE_EMULDEC \
-  (gst_emul_dec_get_type())
-#define GST_EMULDEC(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_EMULDEC,GstEmulDec))
-#define GST_EMULDEC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_EMULDEC,GstEmulDecClass))
-#define GST_IS_EMULDEC(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_EMULDEC))
-#define GST_IS_EMULDEC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_EMULDEC))
-
-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 = 0, size = 0;
-  int version = 0;
-  int data_length = 0;
-  int i, elem_cnt = 0;
-  void *buffer = NULL;
-  CodecElement *elem = NULL;
-
-  fd = open (CODEC_DEV, O_RDWR);
-  if (fd < 0) {
-    perror ("[gst-emul] failed to open codec device");
-    return FALSE;
-  }
-
-  ioctl (fd, CODEC_CMD_GET_VERSION, &version);
-  if (version != CODEC_VER) {
-    CODEC_LOG (INFO, "version conflict between device: %d, plugin: %d\n",
-              version, CODEC_VER);
-    close (fd);
-    return FALSE;
-  }
-
-  buffer = mmap (NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-  if (!buffer) {
-    perror ("[gst-emul] failure memory mapping.");
-    close (fd);
-    return FALSE;
-  }
-
-  CODEC_LOG (DEBUG, "request a device to get codec element.\n");
-  if (ioctl(fd, CODEC_CMD_GET_ELEMENT, NULL) < 0) {
-    perror ("[gst-emul] failed to get codec elements");
-    munmap (buffer, 4096);
-    close (fd);
-    return FALSE;
-  }
-
-  memcpy(&data_length, (uint8_t *)buffer, sizeof(data_length));
-  size += sizeof(data_length);
-
-  elem = g_malloc0 (data_length);
-  if (!elem) {
-    CODEC_LOG (ERR, "Failed to allocate memory.\n");
-    munmap (buffer, 4096);
-    close (fd);
-    return FALSE;
-  }
-
-  memcpy (elem, (uint8_t *)buffer + size, data_length);
-
-  elem_cnt = data_length / sizeof(CodecElement);
-  for (i = 0; i < elem_cnt; i++) {
-    codec_element = g_list_append (codec_element, &elem[i]);
-  }
-
-  munmap (buffer, 4096);
-  close (fd);
-
-  return TRUE;
-}
-
-static gboolean
-plugin_init (GstPlugin *plugin)
-{
-  GST_DEBUG_CATEGORY_INIT (emul_debug,
-      "tizen-emul", 0, "Tizen Emulator Codec Elements");
-
-  gst_emul_init_pix_fmt_info ();
-
-  if (!gst_emul_codec_element_init ()) {
-    GST_ERROR ("failed to get codec elements from QEMU");
-    return FALSE;
-  }
-
-  if (!gst_emuldec_register (plugin, codec_element)) {
-    GST_ERROR ("failed to register decoder elements");
-    return FALSE;
-  }
-  if (!gst_emulenc_register (plugin, codec_element)) {
-    GST_ERROR ("failed to register encoder elements");
-    return FALSE;
-  }
-
-#if 0
-  while ((codec_element = g_list_next (codec_element))) {
-    g_list_free (codec_element);
-  }
-#endif
-
-  return TRUE;
-}
-
-#ifndef PACKAGE
-#define PACKAGE "gst-plugins-emulator"
-#endif
-
-GST_PLUGIN_DEFINE (
-  GST_VERSION_MAJOR,
-  GST_VERSION_MINOR,
-  "tizen-emul",
-  "Codecs for Tizen Emulator",
-  plugin_init,
-  "0.1.1",
-  "LGPL",
-  "gst-plugins-emulator",
-  "http://tizen.org"
-)
diff --git a/src/gstemulapi.c b/src/gstemulapi.c
deleted file mode 100644 (file)
index 81f2f0a..0000000
+++ /dev/null
@@ -1,629 +0,0 @@
-/*
- * 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 "gstemulapi2.h"
-#include "gstemuldev.h"
-
-extern int device_fd;
-extern gpointer device_mem;
-
-struct mem_info {
-    gpointer start;
-    uint32_t offset;
-};
-
-typedef struct _CodecHeader {
-  int32_t   api_index;
-  uint32_t  mem_offset;
-} CodecHeader;
-
-static int
-_codec_header (int32_t api_index, uint32_t mem_offset, uint8_t *device_buf)
-{
-  CodecHeader header = { 0 };
-
-  CODEC_LOG (DEBUG, "enter, %s\n", __func__);
-
-  header.api_index = api_index;
-  header.mem_offset = mem_offset;
-
-  memcpy(device_buf, &header, sizeof(header));
-
-  CODEC_LOG (DEBUG, "leave, %s\n", __func__);
-
-  return sizeof(header);
-}
-
-static void
-_codec_write_to_qemu (int32_t ctx_index, int32_t api_index,
-                          uint32_t mem_offset, int fd)
-{
-  CodecIOParams ioparam;
-
-  memset(&ioparam, 0, sizeof(ioparam));
-  ioparam.api_index = api_index;
-  ioparam.ctx_index = ctx_index;
-  ioparam.mem_offset = mem_offset;
-  if (write (fd, &ioparam, 1) < 0) {
-    fprintf (stderr, "%s, failed to write copy data.\n", __func__);
-  }
-}
-
-#define SMALL_BUFFER    (256 * 1024)
-#define MEDIUM_BUFFER   (2 * 1024 * 1024)
-#define LARGE_BUFFER    (4 * 1024 * 1024)
-
-static struct mem_info
-secure_device_mem (guint buf_size)
-{
-  int ret = 0;
-  uint32_t mem_offset = 0, cmd;
-  struct mem_info info;
-
-  CODEC_LOG (DEBUG, "enter: %s\n", __func__);
-
-  if (buf_size < SMALL_BUFFER) {
-    cmd = CODEC_CMD_S_SECURE_BUFFER;
-    CODEC_LOG (DEBUG, "small buffer size\n");
-  } else if (buf_size < MEDIUM_BUFFER) {
-    // HD Video(2MB)
-    cmd = CODEC_CMD_M_SECURE_BUFFER;
-    CODEC_LOG (DEBUG, "HD buffer size\n");
-  } else {
-    // FULL HD Video(4MB)
-    cmd = CODEC_CMD_L_SECURE_BUFFER;
-    CODEC_LOG (DEBUG, "FULL HD buffer size\n");
-  }
-
-  ret = ioctl (device_fd, cmd, &mem_offset);
-  if (ret < 0) {
-    CODEC_LOG (ERR, "failed to get available buffer\n");
-    // FIXME:
-  } else {
-    if (mem_offset == (LARGE_BUFFER * 8)) {
-      CODEC_LOG (ERR, "acquired memory is over!!\n");
-    } else {
-      info.start = (gpointer)((uint32_t)device_mem + mem_offset);
-      info.offset = mem_offset;
-
-      CODEC_LOG (DEBUG, "acquire device_memory: 0x%x\n", mem_offset);
-    }
-  }
-
-  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
-
-  return info;
-}
-
-static void
-release_device_mem (gpointer start)
-{
-  int ret;     
-  uint32_t offset = start - device_mem;
-
-  CODEC_LOG (DEBUG, "enter: %s\n", __func__);
-
-  CODEC_LOG (DEBUG, "release device_mem start: %p, offset: 0x%x\n", start, offset);
-  ret = ioctl (device_fd, CODEC_CMD_RELEASE_MEMORY, &offset);
-  if (ret < 0) {
-    CODEC_LOG (ERR, "failed to release buffer\n");
-  }
-
-  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
-}
-
-static void
-codec_buffer_free (gpointer start)
-{
-  CODEC_LOG (DEBUG, "enter: %s\n", __func__);
-
-  release_device_mem (start);
-
-  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
-}
-
-GstFlowReturn
-codec_buffer_alloc (GstPad *pad, guint64 offset, guint size,
-                  GstCaps *caps, GstBuffer **buf)
-{
-  struct mem_info info;
-
-  CODEC_LOG (DEBUG, "enter: %s\n", __func__);
-
-  *buf = gst_buffer_new ();
-
-  info = secure_device_mem (size);
-
-  CODEC_LOG (DEBUG, "memory start: 0x%p, offset 0x%x\n",
-            info.start, info.offset);
-
-  GST_BUFFER_DATA (*buf) = GST_BUFFER_MALLOCDATA (*buf) = info.start;
-  GST_BUFFER_SIZE (*buf) = size;
-  GST_BUFFER_FREE_FUNC (*buf) = codec_buffer_free;
-  GST_BUFFER_OFFSET (*buf) = offset;
-
-  if (caps) {
-    gst_buffer_set_caps (*buf, caps);
-  }
-
-  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
-
-  return GST_FLOW_OK;
-}
-
-int
-codec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
-{
-  int fd, ret = 0;
-  int opened, size = 0;
-  uint8_t *mmapbuf = NULL;
-  uint32_t meta_offset = 0;
-
-  CODEC_LOG (DEBUG, "enter: %s\n", __func__);
-
-  fd = dev->fd;
-  if (fd < 0) {
-    GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
-    return -1;
-  }
-
-  mmapbuf = (uint8_t *)dev->buf;
-  if (!mmapbuf) {
-    GST_ERROR ("failed to get mmaped memory address.\n");
-    return -1;
-  }
-
-  ret = ioctl(fd, CODEC_CMD_GET_CONTEXT_INDEX, &ctx->index);
-  if (ret < 0) {
-    GST_ERROR ("failed to get context index\n");
-    return -1;
-  }
-  CODEC_LOG (INFO, "get context index: %d\n", ctx->index);
-
-  meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
-  CODEC_LOG (DEBUG,
-    "init. ctx: %d meta_offset = 0x%x\n", ctx->index, meta_offset);
-
-//  size = _codec_header (CODEC_INIT, 0, mmapbuf + meta_offset);
-  size = 8;
-  _codec_init_meta_to (ctx, codec, mmapbuf + meta_offset + size);
-
-  _codec_write_to_qemu (ctx->index, CODEC_INIT, 0, fd);
-
-  CODEC_LOG (DEBUG,
-    "init. ctx: %d meta_offset = 0x%x, size: %d\n", ctx->index, meta_offset, size);
-
-#if 0
-  if (codec->media_type == AVMEDIA_TYPE_AUDIO) {
-    CODEC_LOG (DEBUG,
-        "opened: %d, audio_sample_fmt: %d\n",
-        *(int *)(mmapbuf + meta_offset + size),
-        *(int *)(mmapbuf + meta_offset + size + 4));
-  }
-#endif
-
-  opened =
-    _codec_init_meta_from (ctx, codec->media_type, mmapbuf + meta_offset + size);
-  ctx->codec= codec;
-
-  CODEC_LOG (DEBUG, "leave: %s, opened: %d\n", __func__, opened);
-
-  return opened;
-}
-
-void
-codec_deinit (CodecContext *ctx, CodecDevice *dev)
-{
-  int fd;
-  void *mmapbuf = NULL;
-
-  CODEC_LOG (DEBUG, "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_LOG (INFO, "close. context index: %d\n", ctx->index);
-  _codec_write_to_qemu (ctx->index, CODEC_DEINIT, 0, fd);
-
-  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
-}
-
-int
-codec_decode_video (CodecContext *ctx, uint8_t *in_buf, int in_size,
-                    gint idx, gint64 in_offset, GstBuffer **out_buf,
-                    int *got_picture_ptr, CodecDevice *dev)
-{
-  int fd, len = 0;
-  int ret, size = 0;
-  uint8_t *mmapbuf = NULL;
-  uint32_t mem_offset = 0, meta_offset = 0;
-
-  CODEC_LOG (DEBUG, "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;
-  }
-
-  ret = ioctl (fd, CODEC_CMD_S_SECURE_BUFFER, &mem_offset);
-  if (ret < 0) {
-    CODEC_LOG (ERR,
-      "decode_audio. failed to get available memory to write inbuf\n");
-    return -1;
-  }
-//  CODEC_LOG (INFO, "write, decode_video. mem_offset = 0x%x\n", mem_offset);
-
-  meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
-  CODEC_LOG (DEBUG, "decode_video. meta mem_offset = 0x%x\n", meta_offset);
-
-//  size = _codec_header (CODEC_DECODE_VIDEO, mem_offset, mmapbuf + meta_offset);
-  size = 8;
-  _codec_decode_video_meta_to (in_size, idx, in_offset, mmapbuf + meta_offset + size);
-  _codec_decode_video_inbuf (in_buf, in_size, mmapbuf + mem_offset);
-
-  dev->mem_info.offset = mem_offset;
-  _codec_write_to_qemu (ctx->index, CODEC_DECODE_VIDEO, mem_offset, fd);
-
-  // after decoding video, no need to get outbuf.
-  len =
-    _codec_decode_video_meta_from (&ctx->video, got_picture_ptr, mmapbuf + meta_offset + size);
-
-  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
-
-  return len;
-}
-
-void
-codec_picture_copy (CodecContext *ctx, uint8_t *pict,
-                    uint32_t pict_size, CodecDevice *dev)
-{
-  int fd, ret = 0;
-  void *mmapbuf = NULL;
-
-  CODEC_LOG (DEBUG, "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_LOG (DEBUG, "pict_size: %d\n",  pict_size);
-
-//     if (pict_size < MEDIUM_BUFFER) {
-  if (pict_size < (SMALL_BUFFER)) {
-    dev->mem_info.offset = (uint32_t)pict - (uint32_t)mmapbuf;
-    CODEC_LOG (DEBUG, "pict: %p , device_mem: %p\n",  pict, mmapbuf);
-    CODEC_LOG (DEBUG, "picture_copy, mem_offset = 0x%x\n",  dev->mem_info.offset);
-  }
-
-  _codec_write_to_qemu (ctx->index, CODEC_PICTURE_COPY,
-                        dev->mem_info.offset, fd);
-//     if (pict_size < MEDIUM_BUFFER) {
-  if (pict_size < SMALL_BUFFER) {
-    CODEC_LOG (DEBUG,
-      "set the mem_offset as outbuf: 0x%x\n",  dev->mem_info.offset);
-    ret = ioctl (fd, CODEC_CMD_USE_DEVICE_MEM, &(dev->mem_info.offset));
-    if (ret < 0) {
-      // FIXME:
-    }
-  } else if (pict_size < MEDIUM_BUFFER) {
-    uint32_t mem_offset = 0;
-    CODEC_LOG (DEBUG, "require to use medium size of memory\n");
-
-    ret = ioctl (fd, CODEC_CMD_REQ_FROM_MEDIUM_MEMORY, &mem_offset);
-    if (ret < 0) {
-      return;
-    }
-    CODEC_LOG (DEBUG, "picture_copy, mem_offset = 0x%x\n",  mem_offset);
-
-    memcpy (pict, mmapbuf + mem_offset, pict_size);
-
-    ret = ioctl(fd, CODEC_CMD_RELEASE_MEMORY, &mem_offset);
-    if (ret < 0) {
-      CODEC_LOG (ERR, "failed release used memory\n");
-    }
-  } else {
-    uint32_t mem_offset = 0;
-    CODEC_LOG (DEBUG, "require to use large size of memory\n");
-
-    ret = ioctl (fd, CODEC_CMD_REQ_FROM_LARGE_MEMORY, &mem_offset);
-    if (ret < 0) {
-      return;
-    }
-    CODEC_LOG (DEBUG, "picture_copy, mem_offset = 0x%x\n",  mem_offset);
-
-    memcpy (pict, mmapbuf + mem_offset, pict_size);
-
-    ret = ioctl(fd, CODEC_CMD_RELEASE_MEMORY, &mem_offset);
-    if (ret < 0) {
-      CODEC_LOG (ERR, "failed release used memory\n");
-    }
-  }
-
-  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
-}
-
-int
-codec_decode_audio (CodecContext *ctx, int16_t *samples,
-                    int *have_data, uint8_t *in_buf,
-                    int in_size, CodecDevice *dev)
-{
-  int fd, len = 0;
-  int ret, size = 0;
-  uint8_t *mmapbuf = NULL;
-  uint32_t mem_offset = 0, meta_offset = 0;
-
-  CODEC_LOG (DEBUG, "enter: %s\n", __func__);
-
-  fd = dev->fd;
-  if (fd < 0) {
-    GST_ERROR("failed to get %s fd\n", CODEC_DEV);
-    return -1;
-  }
-
-  mmapbuf = (uint8_t *)dev->buf;
-  if (!mmapbuf) {
-    GST_ERROR("failed to get mmaped memory address\n");
-    return -1;
-  }
-
-  ret = ioctl (fd, CODEC_CMD_S_SECURE_BUFFER, &mem_offset);
-  if (ret < 0) {
-    CODEC_LOG (ERR,
-      "decode_audio. failed to get available memory to write inbuf\n");
-    return -1;
-  }
-//  CODEC_LOG (INFO, "decode audio1 mem_offset = 0x%x\n", mem_offset);
-
-  meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
-  CODEC_LOG (DEBUG, "decode_audio. meta_offset = 0x%x\n", meta_offset);
-
-//  size = _codec_header (CODEC_DECODE_AUDIO, mem_offset, mmapbuf + meta_offset);
-  size = 8;
-  _codec_decode_audio_meta_to (in_size, mmapbuf + meta_offset + size);
-  _codec_decode_audio_inbuf (in_buf, in_size, mmapbuf + mem_offset);
-
-  dev->mem_info.offset = mem_offset;
-  _codec_write_to_qemu (ctx->index, CODEC_DECODE_AUDIO, mem_offset, fd);
-
-  ret = ioctl (fd, CODEC_CMD_REQ_FROM_SMALL_MEMORY, &mem_offset);
-  if (ret < 0) {
-    return -1;
-  }
-//  CODEC_LOG (INFO, "decode audio2. mem_offset = 0x%x\n", mem_offset);
-
-  len =
-    _codec_decode_audio_meta_from (&ctx->audio, have_data, mmapbuf + meta_offset + size);
-  if (len > 0) {
-    _codec_decode_audio_outbuf (*have_data, samples, mmapbuf + mem_offset);
-  }
-  memset(mmapbuf + mem_offset, 0x00, sizeof(len));
-
-  ret = ioctl(fd, CODEC_CMD_RELEASE_MEMORY, &mem_offset);
-  if (ret < 0) {
-    CODEC_LOG (ERR, "failed release used memory\n");
-  }
-
-  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
-
-  return len;
-}
-
-int
-codec_encode_video (CodecContext *ctx, uint8_t *out_buf,
-                    int out_size, uint8_t *in_buf,
-                    int in_size, int64_t in_timestamp, CodecDevice *dev)
-{
-  int fd, len = 0;
-  int ret, size;
-  uint8_t *mmapbuf = NULL;
-  uint32_t mem_offset = 0, meta_offset = 0;
-
-  CODEC_LOG (DEBUG, "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;
-  }
-
-  if (in_size < SMALL_BUFFER) {
-    CODEC_LOG (DEBUG, "use small size of buffer\n");
-
-    ret = ioctl (fd, CODEC_CMD_S_SECURE_BUFFER, &mem_offset);
-    if (ret < 0) {
-      CODEC_LOG (ERR, "failed to small size of buffer.\n");
-      return -1;
-    }
-  } else if (in_size < MEDIUM_BUFFER) {
-    CODEC_LOG (DEBUG, "use medium size of buffer\n");
-
-    ret = ioctl (fd, CODEC_CMD_M_SECURE_BUFFER, &mem_offset);
-    if (ret < 0) {
-      CODEC_LOG (ERR, "failed to small size of buffer.\n");
-      return -1;
-    }
-  } else {
-    CODEC_LOG (DEBUG, "use large size of buffer\n");
-    ret = ioctl (fd, CODEC_CMD_L_SECURE_BUFFER, &mem_offset);
-    if (ret < 0) {
-      CODEC_LOG (ERR, "failed to large size of buffer.\n");
-      return -1;
-    }
-  }
-  CODEC_LOG (DEBUG, "encode_video. mem_offset = 0x%x\n", mem_offset);
-
-  meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
-  CODEC_LOG (DEBUG, "encode_video. meta_offset = 0x%x\n", meta_offset);
-
-//  size =
-//    _codec_header (CODEC_ENCODE_VIDEO, mem_offset, mmapbuf + meta_offset);
-  size = 8;
-  meta_offset += size;
-  _codec_encode_video_meta_to (in_size, in_timestamp, mmapbuf + meta_offset);
-  _codec_encode_video_inbuf (in_buf, in_size, mmapbuf + mem_offset);
-
-  dev->mem_info.offset = mem_offset;
-  _codec_write_to_qemu (ctx->index, CODEC_ENCODE_VIDEO, mem_offset, fd);
-
-#ifndef DIRECT_BUFFER
-  ret = ioctl (fd, CODEC_CMD_REQ_FROM_SMALL_MEMORY, &mem_offset);
-  if (ret < 0) {
-    return -1;
-  }
-  CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", mem_offset);
-
-  memcpy (&len, mmapbuf + meta_offset, sizeof(len));
-  CODEC_LOG (DEBUG, "encode_video. outbuf size: %d\n", len);
-  if (len > 0) {
-    memcpy (out_buf, mmapbuf + mem_offset, len);
-    out_buf = mmapbuf + mem_offset;
-  }
-
-  dev->mem_info.offset = mem_offset;
-#if 0
-  len =
-    _codec_encode_video_outbuf (out_buf, mmapbuf + mem_offset);
-//  memset(mmapbuf + mem_offset, 0x00, sizeof(len));
-#endif
-
-#if 1
-  ret = ioctl(fd, CODEC_CMD_RELEASE_MEMORY, &mem_offset);
-  if (ret < 0) {
-    CODEC_LOG (ERR, "failed release used memory\n");
-  }
-#endif
-#else
-  dev->mem_info.offset = (uint32_t)pict - (uint32_t)mmapbuf;
-  CODEC_LOG (DEBUG, "outbuf: %p , device_mem: %p\n",  pict, mmapbuf);
-  CODEC_LOG (DEBUG, "encoded video. mem_offset = 0x%x\n",  dev->mem_info.offset);
-
-  ret = ioctl (fd, CODEC_CMD_USE_DEVICE_MEM, &(dev->mem_info.offset));
-  if (ret < 0) {
-    // FIXME:
-  }
-#endif
-  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
-
-  return len;
-}
-
-int
-codec_encode_audio (CodecContext *ctx, uint8_t *out_buf,
-                    int max_size, uint8_t *in_buf,
-                    int in_size, CodecDevice *dev)
-{
-  int fd, len = 0;
-  int ret, size;
-  void *mmapbuf = NULL;
-  uint32_t mem_offset = 0, meta_offset = 0;
-
-  CODEC_LOG (DEBUG, "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;
-  }
-
-  ret = ioctl (fd, CODEC_CMD_S_SECURE_BUFFER, &mem_offset);
-  if (ret < 0) {
-    return -1;
-  }
-
-  CODEC_LOG (DEBUG, "write, encode_audio. mem_offset = 0x%x\n", mem_offset);
-
-  meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
-  CODEC_LOG (DEBUG, "encode_audio. meta mem_offset = 0x%x\n", meta_offset);
-
-  size = _codec_header (CODEC_ENCODE_AUDIO, mem_offset,
-                            mmapbuf + meta_offset);
-  _codec_encode_audio_meta_to (max_size, in_size, mmapbuf + meta_offset + size);
-  _codec_encode_audio_inbuf (in_buf, in_size, mmapbuf + mem_offset);
-
-  dev->mem_info.offset = mem_offset;
-  _codec_write_to_qemu (ctx->index, CODEC_ENCODE_AUDIO, mem_offset, fd);
-
-  ret = ioctl (fd, CODEC_CMD_REQ_FROM_SMALL_MEMORY, &mem_offset);
-  if (ret < 0) {
-    return -1;
-  }
-
-  CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", mem_offset);
-
-  len = _codec_encode_audio_outbuf (out_buf, mmapbuf + mem_offset);
-  memset(mmapbuf + mem_offset, 0x00, sizeof(len));
-
-  ret = ioctl(fd, CODEC_CMD_RELEASE_MEMORY, &mem_offset);
-  if (ret < 0) {
-    return -1;
-  }
-
-  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
-
-  return len;
-}
diff --git a/src/gstemulapi.h b/src/gstemulapi.h
deleted file mode 100644 (file)
index 84ced71..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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"
-
-int
-codec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev);
-
-void
-codec_deinit (CodecContext *ctx, CodecDevice *dev);
-
-int
-codec_decode_video (CodecContext *ctx, uint8_t *in_buf, int in_size,
-                    gint idx, gint64 in_offset, GstBuffer **out_buf,
-                    int *got_picture_ptr, CodecDevice *dev);
-
-
-int
-codec_decode_audio (CodecContext *ctx, int16_t *samples,
-                    int *frame_size_ptr, uint8_t *in_buf,
-                    int in_size, CodecDevice *dev);
-
-int
-codec_encode_video (CodecContext *ctx, uint8_t*out_buf,
-                    int out_size, uint8_t *in_buf,
-                    int in_size, int64_t in_timestamp,
-                    CodecDevice *dev);
-
-int
-codec_encode_audio (CodecContext *ctx, uint8_t *out_buf,
-                    int out_size, uint8_t *in_buf,
-                    int in_size, CodecDevice *dev);
-
-void
-codec_picture_copy (CodecContext *ctx, uint8_t *pict,
-                uint32_t pict_size, CodecDevice *dev);
-
-GstFlowReturn
-codec_buffer_alloc (GstPad *pad, guint64 offset,
-                    guint size, GstCaps *caps, GstBuffer **buf);
-
-#endif /* __GST_EMUL_API_H__ */
diff --git a/src/gstemulapi2.c b/src/gstemulapi2.c
deleted file mode 100644 (file)
index 323ccfa..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * 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 "gstemulapi2.h"
-
-/*
- *  codec data such as codec name, longname, media type and etc.
- */
-static int
-_codec_info_data (CodecElement *codec, uint8_t *device_buf)
-{
-  int size = 0;
-
-  CODEC_LOG (DEBUG, "enter, %s\n", __func__);
-
-  CODEC_LOG (DEBUG, "type: %d, name: %s\n", codec->codec_type, codec->name);
-  memcpy (device_buf, &codec->codec_type, sizeof(codec->codec_type));
-  size = sizeof(codec->codec_type);
-
-  memcpy (device_buf + size, codec->name, sizeof(codec->name));
-  size += sizeof(codec->name);
-
-  CODEC_LOG (DEBUG, "leave, %s\n", __func__);
-
-  return size;
-}
-
-void
-_codec_init_meta_to (CodecContext *ctx,
-                      CodecElement *codec,
-                      uint8_t *device_buf)
-{
-  int size = 0;
-
-  CODEC_LOG (DEBUG, "enter, %s\n", __func__);
-
-  size = _codec_info_data (codec, device_buf);
-
-  if (codec->media_type == AVMEDIA_TYPE_AUDIO) {
-      CODEC_LOG (INFO,
-        "before init. audio sample_fmt: %d\n", ctx->audio.sample_fmt);
-  }
-
-  CODEC_LOG (DEBUG, "init. write data to qemu, size: %d\n", size);
-  memcpy (device_buf + size, ctx, sizeof(CodecContext) - 12);
-  size += (sizeof(CodecContext) - 12);
-  memcpy (device_buf + size, ctx->codecdata, ctx->codecdata_size);
-
-  CODEC_LOG (DEBUG, "leave, %s\n", __func__);
-}
-
-int
-_codec_init_meta_from (CodecContext *ctx,
-                        int media_type,
-                        uint8_t *device_buf)
-{
-  int ret = 0, size = 0;
-
-  CODEC_LOG (DEBUG, "after init. read data from device.\n");
-
-  memcpy (&ret, device_buf, sizeof(ret));
-  size = sizeof(ret);
-  if (!ret) {
-    if (media_type == AVMEDIA_TYPE_AUDIO) {
-      AudioData audio = { 0 };
-
-#if 0
-      memcpy(&audio, device_buf + size, sizeof(AudioData));
-      ctx->audio.sample_fmt = audio.sample_fmt;
-      ctx->audio.frame_size = audio.frame_size;
-      ctx->audio.bits_per_sample_fmt = audio.bits_per_sample_fmt;
-#endif
-      CODEC_LOG (INFO,
-        "audio sample_fmt: %d\n", *(int *)(device_buf + size));
-
-      memcpy(&ctx->audio.sample_fmt, device_buf + size, sizeof(audio.sample_fmt));
-      size += sizeof(audio.sample_fmt);
-      memcpy(&ctx->audio.frame_size, device_buf + size, sizeof(audio.frame_size));
-      size += sizeof(audio.frame_size);
-      memcpy(&ctx->audio.bits_per_sample_fmt, device_buf + size, sizeof(audio.bits_per_sample_fmt));
-
-      CODEC_LOG (INFO,
-        "after init. audio sample_fmt: %d\n", ctx->audio.sample_fmt);
-    }
-  } else {
-    CODEC_LOG (ERR, "failed to open codec context\n");
-  }
-
-  return ret;
-}
-
-void
-_codec_decode_video_meta_to (int in_size, int idx, int64_t in_offset, uint8_t *device_buf)
-{
-  memcpy (device_buf, &in_size, sizeof(in_size));
-  memcpy (device_buf + sizeof(in_size), &idx, sizeof(idx));
-  memcpy (device_buf + sizeof(idx), &in_offset, sizeof(in_offset));
-}
-
-void
-_codec_decode_video_inbuf (uint8_t *in_buf, int in_size,
-                              uint8_t *device_buf)
-{
-  int size = 0;
-
-  memcpy(device_buf, &in_size, sizeof(in_size));
-  size = sizeof(in_size);
-  if (in_size > 0 ) {
-    memcpy (device_buf + size, in_buf, in_size);
-  }
-
-  CODEC_LOG (DEBUG, "decode_video. inbuf_size: %d\n", in_size);
-}
-
-
-int
-_codec_decode_video_meta_from (VideoData *video,
-                              int *got_picture_ptr,
-                              uint8_t *device_buf)
-{
-  int len = 0, size = 0;
-
-  CODEC_LOG (DEBUG, "decode_video. read data from qemu.\n");
-
-  memcpy (&len, device_buf, sizeof(len));
-  size = sizeof(len);
-  memcpy (got_picture_ptr,
-    device_buf + size, sizeof(*got_picture_ptr));
-  size += sizeof(*got_picture_ptr);
-  memcpy (video, device_buf + size, sizeof(VideoData));
-
-  CODEC_LOG (DEBUG, "decode_video. len: %d, have_data: %d\n",
-    len, *got_picture_ptr);
-
-  return len;
-}
-
-void
-_codec_decode_audio_meta_to (int in_size, uint8_t *device_buf)
-{
-  memcpy (device_buf, &in_size, sizeof(in_size));
-}
-
-
-void
-_codec_decode_audio_inbuf (uint8_t *in_buf, int in_size, uint8_t *device_buf)
-{
-  int size = 0;
-
-  memcpy (device_buf, &in_size, sizeof(in_size));
-  size = sizeof(in_size);
-  if (in_size > 0) {
-    memcpy (device_buf + size, in_buf, in_size);
-  }
-
-  CODEC_LOG (DEBUG, "decode_audio. inbuf_size: %d\n", in_size);
-}
-
-int
-_codec_decode_audio_meta_from (AudioData *audio, int *frame_size_ptr,
-                                uint8_t *device_buf)
-{
-  int len = 0, size = 0;
-
-  CODEC_LOG (DEBUG, "decode_audio. read data from device.\n");
-
-  memcpy (&audio->channel_layout,
-    device_buf, sizeof(audio->channel_layout));
-  size = sizeof(audio->channel_layout);
-  memcpy (&len, device_buf + size, sizeof(len));
-  size += sizeof(len);
-  memcpy (frame_size_ptr, device_buf + size, sizeof(*frame_size_ptr));
-
-  CODEC_LOG (DEBUG, "decode_audio. len: %d, frame_size: %d\n",
-          len, (*frame_size_ptr));
-
-  return len;
-}
-
-void
-_codec_decode_audio_outbuf (int outbuf_size, int16_t *samples, uint8_t *device_buf)
-{
-  CODEC_LOG (DEBUG, "decode_audio. read outbuf %d\n", outbuf_size);
-  memcpy (samples, device_buf, outbuf_size);
-}
-
-void
-_codec_encode_video_meta_to (int in_size, int64_t in_timestamp, uint8_t *device_buf)
-{
-  CODEC_LOG (DEBUG, "encode_video. write data to device.\n");
-
-  memcpy (device_buf, &in_size, sizeof(in_size));
-  memcpy (device_buf + sizeof(in_size), &in_timestamp, sizeof(in_timestamp));
-}
-
-void
-_codec_encode_video_inbuf (uint8_t *in_buf, int in_size, uint8_t *device_buf)
-{
-  int size = 0;
-
-  memcpy ((uint8_t *)device_buf, &in_size, sizeof(in_size));
-  size += sizeof(in_size);
-  if (in_size > 0) {
-    memcpy (device_buf + size, in_buf, in_size);
-  }
-  CODEC_LOG (DEBUG, "encode_video. inbuf_size: %d\n", in_size);
-}
-
-void
-_codec_encode_video_outbuf (int len, uint8_t *out_buf, uint8_t *device_buf)
-{
-//  int len, size;
-
-  CODEC_LOG (DEBUG, "encode_video. read data from device.\n");
-
-//  memcpy (&len, device_buf, sizeof(len));
-//  size = sizeof(len);
-  memcpy (out_buf, device_buf, len);
-
-//  return len;
-}
-
-void
-_codec_encode_audio_meta_to (int max_size, int in_size, uint8_t *device_buf)
-{
-  int size = 0;
-  
-  CODEC_LOG (DEBUG, "encode_audio. write data to device.\n");
-
-  memcpy (device_buf, &in_size, sizeof(in_size));
-  size = sizeof(in_size);
-  memcpy (device_buf + size, &max_size, sizeof(max_size));
-}
-
-void
-_codec_encode_audio_inbuf (uint8_t *in_buf, int in_size, uint8_t *device_buf)
-{
-  int size = 0;
-
-  memcpy (device_buf, &in_size, sizeof(in_size));
-  size = sizeof(in_size);
-  if (in_size > 0) {
-    memcpy (device_buf + size, in_buf, in_size);
-  }
-  CODEC_LOG (DEBUG, "encode_audio. inbuf_size: %d\n", in_size);
-}
-
-int
-_codec_encode_audio_outbuf (uint8_t *out_buf, uint8_t *device_buf)
-{
-  int len, size;
-
-  CODEC_LOG (DEBUG, "encode_audio. read data from device\n");
-
-  memcpy (&len, (uint8_t *)device_buf, sizeof(len));
-  size = sizeof(len);
-  memcpy (out_buf, (uint8_t *)device_buf + size, len);
-
-  return len;
-}
diff --git a/src/gstemulapi2.h b/src/gstemulapi2.h
deleted file mode 100644 (file)
index 7d882b9..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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"
-
-void _codec_init_meta_to (CodecContext *ctx, CodecElement *codec, uint8_t *device_buf);
-
-int _codec_init_meta_from (CodecContext *ctx, int media_type, uint8_t *device_buf);
-
-void _codec_decode_video_meta_to (int in_size, int idx, int64_t in_offset, uint8_t *device_buf);
-
-void _codec_decode_video_inbuf (uint8_t *in_buf, int in_size, uint8_t *device_buf);
-
-int _codec_decode_video_meta_from (VideoData *video, int *got_picture_ptr,
-                                  uint8_t *device_buf);
-
-void _codec_decode_audio_meta_to (int in_size, uint8_t *device_buf);
-
-
-void _codec_decode_audio_inbuf (uint8_t *in_buf, int in_size,
-                                  uint8_t *device_buf);
-
-int _codec_decode_audio_meta_from (AudioData *audio, int *frame_size_ptr,
-                                  uint8_t *device_buf);
-
-void _codec_decode_audio_outbuf (int outbuf_size, int16_t *samples,
-                                  uint8_t *device_buf);
-
-void _codec_encode_video_meta_to (int in_size, int64_t in_timestamp, uint8_t *device_buf);
-
-void _codec_encode_video_inbuf (uint8_t *in_buf, int in_size,
-                                  uint8_t *device_buf);
-
-// int _codec_encode_video_outbuf (uint8_t *out_buf, uint8_t *device_buf);
-void _codec_encode_video_outbuf (int len, uint8_t *outbuf, uint8_t *device_buf);
-
-void _codec_encode_audio_meta_to (int max_size, int in_size, uint8_t *device_buf);
-
-void _codec_encode_audio_inbuf (uint8_t *in_buf, int in_size, uint8_t *device_buf);
-
-int _codec_encode_audio_outbuf (uint8_t *out_buf, uint8_t *device_buf);
diff --git a/src/gstemulcommon.h b/src/gstemulcommon.h
deleted file mode 100644 (file)
index ee4ee50..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * 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 <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-// #include <semaphore.h>
-#include <glib.h>
-#include <gst/gst.h>
-#include "pixfmt.h"
-
-GST_DEBUG_CATEGORY_EXTERN (emul_debug);
-#define GST_CAT_DEFAULT emul_debug
-
-G_BEGIN_DECLS
-
-enum codec_log_level {
-  ERR,
-  WARN,
-  INFO,
-  DEBUG,
-};
-
-#define CODEC_DEV   "/dev/newcodec"
-#define CODEC_VER   1
-
-#define CODEC_LOG(level, fmt, ...) \
-  do { \
-    if (level <= INFO) \
-      printf("[gst-emul][%d] " fmt, __LINE__, ##__VA_ARGS__); \
-  } while (0)
-
-#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
-
-#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))
-
-typedef struct _CodecIOParams {
-  int32_t   api_index;
-  int32_t   ctx_index;
-  uint32_t  mem_offset;
-} CodecIOParams;
-
-typedef struct _CodecDeviceMem {
-  uint32_t  index;
-  uint32_t  offset;
-} CodecDeviceMem;
-
-typedef struct _CodecDevice {
-  int       fd;
-  uint8_t   *buf;
-  uint32_t  buf_size;
-  CodecDeviceMem mem_info;
-} CodecDevice;
-
-typedef struct _CodecElement {
-  int32_t codec_type;
-  int32_t media_type;
-  gchar name[32];
-  gchar longname[64];
-  union {
-    int32_t pix_fmts[4];
-    int32_t sample_fmts[4];
-  };
-} CodecElement;
-
-typedef struct _VideoData {
-  int32_t width, height;
-  int32_t fps_n, fps_d;
-  int32_t par_n, par_d;
-  int32_t pix_fmt, bpp;
-  int32_t ticks_per_frame;
-} VideoData;
-
-typedef struct _AudioData {
-  int32_t channels, sample_rate;
-  int32_t block_align, depth;
-  int32_t sample_fmt, frame_size;
-  int32_t bits_per_sample_fmt;
-  int64_t channel_layout;
-} AudioData;
-
-typedef struct _CodecContext {
-  union {      
-    VideoData video;
-    AudioData audio;
-  };
-
-  int32_t bit_rate;
-  int32_t codec_tag;   
-
-  int32_t codecdata_size;
-  uint8_t *codecdata;
-
-  CodecElement *codec;
-  int32_t index;
-} CodecContext;
-
-enum CODEC_FUNC_TYPE {
-  CODEC_INIT = 0,
-  CODEC_DECODE_VIDEO,
-  CODEC_ENCODE_VIDEO,
-  CODEC_DECODE_AUDIO,
-  CODEC_ENCODE_AUDIO,
-  CODEC_PICTURE_COPY,
-  CODEC_DEINIT,
-};
-
-enum CODEC_IO_CMD {
-  CODEC_CMD_COPY_TO_DEVICE_MEM = 5,
-  CODEC_CMD_COPY_FROM_DEVICE_MEM,
-  CODEC_CMD_GET_VERSION = 20,
-  CODEC_CMD_GET_ELEMENT,
-  CODEC_CMD_GET_CONTEXT_INDEX,
-  CODEC_CMD_SECURE_MEMORY = 30,
-  CODEC_CMD_RELEASE_MEMORY,
-  CODEC_CMD_USE_DEVICE_MEM,
-  CODEC_CMD_REQ_FROM_SMALL_MEMORY,
-  CODEC_CMD_REQ_FROM_MEDIUM_MEMORY,
-  CODEC_CMD_REQ_FROM_LARGE_MEMORY,
-  CODEC_CMD_S_SECURE_BUFFER,
-  CODEC_CMD_M_SECURE_BUFFER,
-  CODEC_CMD_L_SECURE_BUFFER,
-};
-
-
-#define CODEC_META_DATA_SIZE 256
-
-// CODEC_CMD_REQ_TO_SMALL_MEMORY
-// CODEC_CMD_REQ_FROM_SMALL_MEMORY
-// CODEC_CMD_REQ_TO_LARGE_MEMORY
-// CODEC_CMD_REQ_FROM_LARGE_MEMORY
-
-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,
-  SAMPLE_FMT_S16,
-  SAMPLE_FMT_S32,
-  SAMPLE_FMT_FLT,
-  SAMPLE_FMT_DBL,
-  SAMPLE_FMT_NB
-};
-
-/* Define codec types.
- * e.g. FFmpeg, x264, libvpx and etc.
- */
-enum {
-  FFMPEG_TYPE = 1,
-};
-
-G_END_DECLS
-#endif
diff --git a/src/gstemuldec.c b/src/gstemuldec.c
deleted file mode 100644 (file)
index 3e1943f..0000000
+++ /dev/null
@@ -1,1566 +0,0 @@
-/*
- * 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"
-#include "gstemuldev.h"
-
-#define GST_EMULDEC_PARAMS_QDATA g_quark_from_static_string("marudec-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 opened;
-  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, gint64 in_offset, GstFlowReturn *ret);
-
-static gboolean gst_emuldec_open (GstEmulDec *emuldec);
-static int 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;
-    }
-  }
-
-  emuldec->processed++;
-  return TRUE;
-}
-
-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;
-
-  CODEC_LOG (DEBUG, "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, 0, &ret);
-
-      if (len < 0 || have_data == 0) {
-        break;
-      }
-    } while (try++ < 10);
-  }
-#endif
-
-  if (emuldec->segment.rate < 0.0) {
-    CODEC_LOG (DEBUG, "reverse playback\n");
-    flush_queued (emuldec);
-  }
-}
-
-/*
- * Implementation
- */
-static void
-gst_emuldec_base_init (GstEmulDecClass *klass)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-  GstCaps *sinkcaps = NULL, *srccaps = NULL;
-  GstPadTemplate *sinktempl, *srctempl;
-  CodecElement *codec;
-  gchar *longname, *classification, *description;
-
-  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");
-  description = g_strdup_printf("%s Decoder", codec->name);
-
-  gst_element_class_set_details_simple (element_class,
-            longname,
-            classification,
-            description,
-            "Kitae Kim <kt920.kim@samsung.com>");
-
-  g_free (longname);
-  g_free (classification);
-  g_free (description);
-
-  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);
-
-  emuldec->context = g_malloc0 (sizeof(CodecContext));
-  emuldec->context->video.pix_fmt = PIX_FMT_NONE;
-  emuldec->context->audio.sample_fmt = SAMPLE_FMT_NONE;
-
-  emuldec->opened = FALSE;
-  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);
-
-  emuldec->dev = g_malloc0 (sizeof(CodecDevice));
-  if (!emuldec->dev) {
-    CODEC_LOG (ERR, "failed to allocate memory.\n");
-  }
-}
-
-static void
-gst_emuldec_finalize (GObject *object)
-{
-  GstEmulDec *emuldec = (GstEmulDec *) object;
-
-  if (emuldec->context) {
-    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;
-
-    gst_event_parse_qos (event, &proportion, &diff, &timestamp);
-
-    /* update our QoS values */
-    gst_emuldec_update_qos (emuldec, proportion, timestamp + diff);
-    break;
-  }
-  default:
-    break;
-  }
-
-  /* forward upstream */
-  res = gst_pad_push_event (emuldec->sinkpad, event);
-
-  gst_object_unref (emuldec);
-
-  return res;
-}
-
-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:
-    gst_emuldec_drain (emuldec);
-    break;
-  case GST_EVENT_FLUSH_STOP:
-  {
-    printf("[%s][%d] GST_EVET_FLUSH_STOP\n", __func__, __LINE__);
-#if 0
-    if (emuldec->opened) {
-        // TODO: what does avcodec_flush_buffers do?
-        emul_avcodec_flush_buffers (emuldec->context, emuldec->dev);
-    }
-#endif
-    gst_emuldec_reset_ts (emuldec);
-    gst_emuldec_reset_qos (emuldec);
-#if 0
-    gst_emuldec_flush_pcache (emuldec);
-    emuldec->waiting_for_key = TRUE;
-#endif
-    gst_segment_init (&emuldec->segment, GST_FORMAT_TIME);
-    clear_queued (emuldec);
-  }
-    break;
-  case GST_EVENT_NEWSEGMENT:
-  {
-    gboolean update;
-    GstFormat format;
-    gint64 start, stop, time;
-    gdouble rate, arate;
-
-    gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
-        &start, &stop, &time);
-
-    switch (format) {
-    case GST_FORMAT_TIME:
-      break;
-    case GST_FORMAT_BYTES:
-    {
-      gint bit_rate;
-      bit_rate = emuldec->context->bit_rate;
-
-      if (!bit_rate) {
-        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:
-      GST_WARNING_OBJECT (emuldec, "unknown format received in NEWSEGMENT");
-      gst_event_unref (event);
-      gst_object_unref (emuldec);
-      return ret;
-    }
-
-    if (emuldec->context->codec) {
-      gst_emuldec_drain (emuldec);
-    }
-
-    GST_DEBUG_OBJECT (emuldec,
-      "NEWSEGMENT in time start %" GST_TIME_FORMAT " -- stop %"
-      GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
-
-    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 (emuldec->opened) {
-    GST_OBJECT_UNLOCK (emuldec);
-    gst_emuldec_drain (emuldec);
-    GST_OBJECT_LOCK (emuldec);
-    gst_emuldec_close (emuldec);
-  }
-
-  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 0
-  if (strcmp (oclass->codec->name, "aac") == 0) {
-    const gchar *format = gst_structure_get_string (structure, "stream-format");
-    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 gboolean
-gst_emuldec_open (GstEmulDec *emuldec)
-{
-  GstEmulDecClass *oclass;
-
-  oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (emuldec));
-
-  if (!emuldec->dev) {
-    return FALSE;
-  }
-
-  if (gst_emul_avcodec_open (emuldec->context,
-                            oclass->codec, emuldec->dev) < 0) {
-    gst_emuldec_close (emuldec);
-    GST_ERROR_OBJECT (emuldec,
-      "maru_%sdec: Failed to open codec", oclass->codec->name);
-    return FALSE;
-  }
-
-  emuldec->opened = TRUE;
-  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 int
-gst_emuldec_close (GstEmulDec *emuldec)
-{
-  int ret = 0;
-
-  if (emuldec->context->codecdata) {
-    g_free(emuldec->context->codecdata);
-    emuldec->context->codecdata = NULL;
-  }
-
-  if (!emuldec->dev) {
-    return -1;
-  }
-
-  ret = gst_emul_avcodec_close (emuldec->context, emuldec->dev);
-
-  if (emuldec->dev) {
-    g_free(emuldec->dev);
-    emuldec->dev = NULL;
-  }
-
-  return ret;
-}
-
-
-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:
-    break;
-  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 GstFlowReturn
-get_output_buffer (GstEmulDec *emuldec, GstBuffer **outbuf)
-{
-  gint pict_size;
-  GstFlowReturn ret;
-
-  ret = GST_FLOW_OK;
-
-  *outbuf = NULL;
-
-  if (G_UNLIKELY (!gst_emuldec_negotiate (emuldec, FALSE))) {
-    GST_DEBUG_OBJECT (emuldec, "negotiate failed");
-    return GST_FLOW_NOT_NEGOTIATED;
-  }
-
-  pict_size = gst_emul_avpicture_size (emuldec->context->video.pix_fmt,
-    emuldec->context->video.width, emuldec->context->video.height);
-  if (pict_size < 0) {
-    GST_DEBUG_OBJECT (emuldec, "size of a picture is negative. "
-      "pixel format: %d, width: %d, height: %d",
-      emuldec->context->video.pix_fmt, emuldec->context->video.width,
-      emuldec->context->video.height);
-    return GST_FLOW_ERROR;
-  }
-
-       CODEC_LOG (DEBUG, "outbuf size of decoded video: %d\n", pict_size);
-
-       if (pict_size < (256 * 1024)) {
-  /* GstPadBufferAllocFunction is mostly overridden by elements that can
-   * provide a hardware buffer in order to avoid additional memcpy operations.
-   */
-    gst_pad_set_bufferalloc_function(
-      GST_PAD_PEER(emuldec->srcpad),
-      (GstPadBufferAllocFunction) codec_buffer_alloc);
-       } else {
-    CODEC_LOG (DEBUG, "request a large size of memory\n");
-       }
-
-  ret = gst_pad_alloc_buffer_and_set_caps (emuldec->srcpad,
-    GST_BUFFER_OFFSET_NONE, pict_size,
-    GST_PAD_CAPS (emuldec->srcpad), outbuf);
-  if (G_UNLIKELY (ret != GST_FLOW_OK)) {
-    GST_DEBUG_OBJECT (emuldec, "pad_alloc failed %d (%s)", ret,
-      gst_flow_get_name (ret));
-    return ret;
-  }
-
-  if ((uintptr_t) GST_BUFFER_DATA (*outbuf) % 16) {
-    GST_DEBUG_OBJECT (emuldec,
-      "Downstream can't allocate aligned buffers.");
-    gst_buffer_unref (*outbuf);
-    *outbuf = new_aligned_buffer (pict_size, GST_PAD_CAPS (emuldec->srcpad));
-  }
-
-  codec_picture_copy (emuldec->context, GST_BUFFER_DATA (*outbuf),
-    GST_BUFFER_SIZE (*outbuf), emuldec->dev);
-
-  return ret;
-}
-
-static gboolean
-clip_video_buffer (GstEmulDec *dec, GstBuffer *buf,
-    GstClockTime in_ts, GstClockTime in_dur)
-{
-  gboolean res = TRUE;
-
-  return res;
-}
-
-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, gint64 in_offset, GstBuffer **outbuf,
-    GstFlowReturn *ret)
-{
-  gint len = -1, have_data;
-  gboolean mode_switch;
-  gboolean decode;
-  GstClockTime out_timestamp, out_duration, out_pts;
-  gint64 out_offset;
-  const GstTSInfo *out_info;
-
-  decode = gst_emuldec_do_qos (emuldec, dec_info->timestamp, &mode_switch);
-
-  CODEC_LOG (DEBUG, "decode video: input buffer size: %d\n", size);
-  len =
-    codec_decode_video (emuldec->context, data, size,
-                          dec_info->idx, in_offset, outbuf,
-                          &have_data, emuldec->dev);
-
-  if (!decode) {
-    // skip_frame
-  }
-
-  GST_DEBUG_OBJECT (emuldec, "after decode: len %d, have_data %d",
-    len, have_data);
-
-#if 0
-  if (len < 0 && (mode_switch || emuldec->context->skip_frame)) {
-    len = 0;
-  }
-
-  if (len > 0 && have_data <= 0 && (mode_switch
-      || emuldec->context->skip_frame)) {
-    emuldec->last_out = -1;
-  }
-#endif
-
-  if (len < 0 || have_data <= 0) {
-    GST_DEBUG_OBJECT (emuldec, "return flow %d, out %p, len %d",
-      *ret, *outbuf, len);
-    return len;
-  }
-
-  out_info = gst_ts_info_get (emuldec, dec_info->idx);
-  out_pts = out_info->timestamp;
-  out_duration = out_info->duration;
-  out_offset = out_info->offset;
-
-  *ret = get_output_buffer (emuldec, outbuf);
-  if (G_UNLIKELY (*ret != GST_FLOW_OK)) {
-    GST_DEBUG_OBJECT (emuldec, "no output buffer");
-    len = -1;
-    GST_DEBUG_OBJECT (emuldec, "return flow %d, out %p, len %d",
-      *ret, *outbuf, len);
-    return len;
-  }
-
-  /* Timestamps */
-  out_timestamp = -1;
-  if (out_pts != -1) {
-    out_timestamp = (GstClockTime) out_pts;
-    GST_LOG_OBJECT (emuldec, "using timestamp %" GST_TIME_FORMAT
-      " returned by ffmpeg", GST_TIME_ARGS (out_timestamp));
-  }
-
-  if (!GST_CLOCK_TIME_IS_VALID (out_timestamp) && emuldec->next_out != -1) {
-    out_timestamp = emuldec->next_out;
-    GST_LOG_OBJECT (emuldec, "using next timestamp %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (out_timestamp));
-  }
-
-  if (!GST_CLOCK_TIME_IS_VALID (out_timestamp)) {
-    out_timestamp = dec_info->timestamp;
-    GST_LOG_OBJECT (emuldec, "using in timestamp %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (out_timestamp));
-  }
-  GST_BUFFER_TIMESTAMP (*outbuf) = out_timestamp;
-
-  /* Offset */
-  if (out_offset != GST_BUFFER_OFFSET_NONE) {
-    GST_LOG_OBJECT (emuldec, "Using offset returned by ffmpeg");
-  } else if (out_timestamp != GST_CLOCK_TIME_NONE) {
-    GstFormat out_fmt = GST_FORMAT_DEFAULT;
-    GST_LOG_OBJECT (emuldec, "Using offset converted from timestamp");
-
-    gst_pad_query_peer_convert (emuldec->sinkpad,
-      GST_FORMAT_TIME, out_timestamp, &out_fmt, &out_offset);
-  } else if (dec_info->offset != GST_BUFFER_OFFSET_NONE) {
-    GST_LOG_OBJECT (emuldec, "using in_offset %" G_GINT64_FORMAT,
-      dec_info->offset);
-    out_offset = dec_info->offset;
-  } else {
-    GST_LOG_OBJECT (emuldec, "no valid offset found");
-    out_offset = GST_BUFFER_OFFSET_NONE;
-  }
-  GST_BUFFER_OFFSET (*outbuf) = out_offset;
-
-  /* Duration */
-  if (GST_CLOCK_TIME_IS_VALID (out_duration)) {
-    GST_LOG_OBJECT (emuldec, "Using duration returned by ffmpeg");
-  } else if (GST_CLOCK_TIME_IS_VALID (dec_info->duration)) {
-    GST_LOG_OBJECT (emuldec, "Using in_duration");
-    out_duration = dec_info->duration;
-#if 0
-  } else if (GST_CLOCK_TIME_IS_VALID (emuldec->last_diff)) {
-    GST_LOG_OBJECT (emuldec, "Using last-diff");
-    out_duration = emuldec->last_diff;
-#endif
-  } else {
-    if (emuldec->format.video.fps_n != -1 &&
-        (emuldec->format.video.fps_n != 1000 &&
-        emuldec->format.video.fps_d != 1)) {
-      GST_LOG_OBJECT (emuldec, "using input framerate for duration");
-      out_duration = gst_util_uint64_scale_int (GST_SECOND,
-        emuldec->format.video.fps_d, emuldec->format.video.fps_n);
-    } else {
-      if (emuldec->context->video.fps_n != 0 &&
-          (emuldec->context->video.fps_d > 0 &&
-            emuldec->context->video.fps_d < 1000)) {
-        GST_LOG_OBJECT (emuldec, "using decoder's framerate for duration");
-        out_duration = gst_util_uint64_scale_int (GST_SECOND,
-          emuldec->context->video.fps_n * 1,
-          emuldec->context->video.fps_d);
-      } else {
-        GST_LOG_OBJECT (emuldec, "no valid duration found");
-      }
-    }
-  }
-
-#if 0
-  if (GST_CLOCK_TIME_IS_VALID (out_duration)) {
-    out_duration += out_duration * emuldec->picture->repeat_pict / 2;
-  }
-  GST_BUFFER_DURATION (*outbuf) = out_duration;
-
-  if (out_timestamp != -1 && out_duration != -1 && out_duration != 0) {
-    emuldec->next_out = out_timestamp + out_duration;
-  } else {
-    emuldec->next_out = -1;
-  }
-#endif
-
-  if (G_UNLIKELY (!clip_video_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;
-  }
-
-  GST_DEBUG_OBJECT (emuldec, "return flow %d, out %p, len %d",
-    *ret, *outbuf, len);
-  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));
-
-  CODEC_LOG (DEBUG, "decode audio, input buffer size: %d\n", size);
-
-  len = codec_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);
-
-//  CODEC_LOG (INFO, "decode audio, sample_fmt: %d\n", emuldec->context->audio.sample_fmt);
-
-  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;
-    }
-
-    /* calculate based on number of samples */
-    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 FFMPEG 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, gint64 in_offset, GstFlowReturn *ret)
-{
-  GstEmulDecClass *oclass;
-  GstBuffer *outbuf = NULL;
-  gint have_data = 0, len = 0;
-
-  if (G_UNLIKELY (emuldec->context->codec == NULL)) {
-    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, in_offset, &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,
-        "maru_%sdec: 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
-      GST_DEBUG_OBJECT (emuldec, "queued frame");
-      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;
-  gint 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 (G_UNLIKELY (!emuldec->opened)) {
-    // not_negotiated
-    oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (emuldec));
-    GST_ELEMENT_ERROR (emuldec, CORE, NEGOTIATION, (NULL),
-      ("maru_%sdec: input format was not set before data start",
-        oclass->codec->name));
-    gst_buffer_unref (buffer);
-    return GST_FLOW_NOT_NEGOTIATED;
-  }
-
-  discont = GST_BUFFER_IS_DISCONT (buffer);
-
-// FIXME
-  if (G_UNLIKELY (discont)) {
-    GST_DEBUG_OBJECT (emuldec, "received DISCONT");
-    gst_emuldec_drain (emuldec);
-//    gst_emuldec_flush_pcache (emuldec);
-//    emul_avcodec_flush buffers (emuldec->context, emuldec->dev);
-    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
-
-  GST_LOG_OBJECT (emuldec,
-    "Received new data of size %u, offset: %" G_GUINT64_FORMAT ", ts:%"
-    GST_TIME_FORMAT ", dur: %" GST_TIME_FORMAT ", info %d",
-    GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer),
-    GST_TIME_ARGS (in_timestamp), GST_TIME_ARGS (in_duration), in_info->idx);
-
-  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, in_offset, &ret);
-
-#if 0
-  if (emuldec->clear_ts) {
-    in_timestamp = GST_CLOCK_TIME_NONE;
-    in_duration = GST_CLOCK_TIME_NONE;
-    in_offset = GST_BUFFER_OFFSET_NONE;
-    in_info = GST_TS_INFO_NONE;
-  } else {
-    emuldec->clear_ts = TRUE;
-  }
-#endif
-
-  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_NONE;
-  GList *elem = element;
-  CodecElement *codec = NULL;
-
-  if (!elem) {
-    return FALSE;
-  }
-
-  /* register element */
-  do {
-    codec = (CodecElement *)(elem->data);
-    if (!codec) {
-      return FALSE;
-    }
-
-    if (codec->codec_type != CODEC_TYPE_DECODE) {
-      continue;
-    }
-
-    type_name = g_strdup_printf ("maru_%sdec", 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);
-  } while ((elem = elem->next));
-
-  return TRUE;
-}
diff --git a/src/gstemuldev.c b/src/gstemuldev.c
deleted file mode 100644 (file)
index 642ed2e..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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 <fcntl.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-
-#include "gstemulapi.h"
-#include "gstemuldev.h"
-
-static GStaticMutex gst_avcodec_mutex = G_STATIC_MUTEX_INIT;
-
-#define CODEC_DEVICE_MEM_SIZE 32 * 1024 * 1024
-
-gpointer device_mem;
-int device_fd;
-
-int
-gst_emul_codec_device_open (CodecDevice *dev, int media_type)
-{
-  int fd;
-  void *mmapbuf;
-
-  CODEC_LOG (DEBUG, "enter: %s\n", __func__);
-
-  CODEC_LOG (INFO, "before opening a device. %d\n", dev->fd);
-  if ((fd = open(CODEC_DEV, O_RDWR)) < 0) {
-    perror("Failed to open codec device.");
-    return -1;
-  }
-  dev->fd = fd;
-
-//  GST_DEBUG("succeeded to open %s. %d.\n", CODEC_DEV, fd);
-  CODEC_LOG (INFO, "succeeded to open %s. %d.\n", CODEC_DEV, fd);
-  dev->mem_info.index = dev->buf_size;
-
-  CODEC_LOG (DEBUG, "before mmap. buf_size: %d\n", dev->buf_size);
-  mmapbuf = mmap (NULL, CODEC_DEVICE_MEM_SIZE, PROT_READ | PROT_WRITE,
-                  MAP_SHARED, fd, 0);
-  if (mmapbuf == MAP_FAILED) {
-    perror("Failed to map device memory of codec.");
-    dev->buf = NULL;
-    return -1;
-  }
-
-//  GST_DEBUG("succeeded to map device memory.\n");
-  CODEC_LOG (INFO, "succeeded to map device memory: %p.\n", mmapbuf);
-  dev->fd = fd;
-  dev->buf = mmapbuf;
-
-  if (media_type == AVMEDIA_TYPE_VIDEO) {
-    device_mem = mmapbuf;
-    device_fd = fd;
-    CODEC_LOG (INFO, "video type! mmapbuf: %p fd: %d\n", mmapbuf, fd);
-  }
-#if 0
-  else {
-    CODEC_LOG (INFO, "don't need to set device_mem because media type is not video. %d\n", media_type); 
-  }
-#endif
-
-  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
-
-  return 0;
-}
-
-int
-gst_emul_codec_device_close (CodecDevice *dev)
-{
-  int fd = 0;
-  void *mmapbuf = NULL;
-
-  CODEC_LOG (DEBUG, "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;
-  }
-
-  CODEC_LOG (INFO, "Release memory region of %p.\n", mmapbuf);
-  if (munmap(mmapbuf, CODEC_DEVICE_MEM_SIZE) != 0) {
-    CODEC_LOG(ERR, "Failed to release memory region of %s.\n", CODEC_DEV);
-  }
-  dev->buf = NULL;
-
-  ioctl(fd, CODEC_CMD_RELEASE_MEMORY, &dev->mem_info.offset);
-
-  CODEC_LOG (INFO, "close %s.\n", CODEC_DEV);
-  if (close(fd) != 0) {
-    GST_ERROR("Failed to close %s. fd: %d\n", CODEC_DEV, fd);
-  }
-
-  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
-
-  return 0;
-}
-
-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, codec->media_type) < 0) {
-    perror("failed to open device.\n");
-    return -1;
-  }
-  ret = codec_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);
-
-  CODEC_LOG (DEBUG, "gst_emul_avcodec_close\n");
-  codec_deinit (ctx, dev);
-
-  ret = gst_emul_codec_device_close (dev);
-  g_static_mutex_unlock (&gst_avcodec_mutex);
-
-  return ret;
-}
diff --git a/src/gstemuldev.h b/src/gstemuldev.h
deleted file mode 100644 (file)
index 141a268..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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_DEV_H__
-#define __GST_EMUL_DEV_H__
-
-int gst_emul_codec_device_open (CodecDevice *dev, int media_type);
-int gst_emul_codec_device_close (CodecDevice *dev);
-
-int gst_emul_avcodec_open (CodecContext *ctx,
-                          CodecElement *codec,
-                          CodecDevice *dev);
-int gst_emul_avcodec_close (CodecContext *ctx, CodecDevice *dev);
-#endif
diff --git a/src/gstemulenc.c b/src/gstemulenc.c
deleted file mode 100644 (file)
index 78317d7..0000000
+++ /dev/null
@@ -1,1170 +0,0 @@
-/*
- * 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 "gstemulapi.h"
-#include "gstemuldev.h"
-#include <gst/base/gstadapter.h>
-
-#define GST_EMULENC_PARAMS_QDATA g_quark_from_static_string("maruenc-params")
-
-typedef struct _GstEmulEnc
-{
-  GstElement element;
-
-  GstPad *srcpad;
-  GstPad *sinkpad;
-
-  CodecContext *context;
-  CodecDevice *dev;
-  gboolean opened;
-  GstClockTime adapter_ts;
-  guint64 adapter_consumed;
-  GstAdapter *adapter;
-  gboolean discont;
-
-  // cache
-  gulong bitrate;
-  gint gop_size;
-  gulong buffer_size;
-
-  guint8 *working_buf;
-  gulong working_buf_size;
-
-  GQueue *delay;
-
-} GstEmulEnc;
-
-typedef struct _GstEmulEncClass
-{
-  GstElementClass parent_class;
-
-  CodecElement *codec;
-  GstPadTemplate *sinktempl;
-  GstPadTemplate *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 GstCaps *gst_emulenc_getcaps (GstPad *pad);
-
-static GstCaps *gst_emulenc_get_possible_sizes (GstEmulEnc *emulenc,
-  GstPad *pad, const GstCaps *caps);
-
-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);
-
-GstStateChangeReturn gst_emulenc_change_state (GstElement *element, GstStateChange transition);
-
-#define DEFAULT_VIDEO_BITRATE   300000
-#define DEFAULT_VIDEO_GOP_SIZE  15
-#define DEFAULT_AUDIO_BITRATE   128000
-
-#define DEFAULT_WIDTH 352
-#define DEFAULT_HEIGHT 288
-
-/*
- * 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;
-    CodecElement *codec;
-    gchar *longname, *classification, *description;
-
-    codec =
-        (CodecElement *)g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
-         GST_EMULENC_PARAMS_QDATA);
-
-    longname = g_strdup_printf ("%s Encoder", codec->longname);
-    classification = g_strdup_printf ("Codec/Encoder/%s",
-            (codec->media_type == AVMEDIA_TYPE_VIDEO) ? "Video" : "Audio");
-    description = g_strdup_printf ("%s Encoder", codec->name);
-
-    gst_element_class_set_details_simple (element_class,
-            longname,
-            classification,
-            description,
-//            "accelerated codec for Tizen Emulator",
-            "Kitae Kim <kt920.kim@samsung.com>");
-
-    g_free (longname);
-    g_free (classification);
-
-
-  if (!(srccaps = gst_emul_codecname_to_caps (codec->name, NULL, TRUE))) {
-    GST_DEBUG ("Couldn't get source caps for encoder '%s'", codec->name);
-    srccaps = gst_caps_new_simple ("unknown/unknown", NULL);
-  }
-
-  switch (codec->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:
-    sinkcaps = gst_emul_codectype_to_audio_caps (NULL, codec->name, TRUE, codec);
-    break;
-  default:
-    GST_LOG("unknown media type.\n");
-    break;
-  }
-
-  if (!sinkcaps) {
-      GST_DEBUG ("Couldn't get sink caps for encoder '%s'", 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->codec = codec;
-  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
-
-  gstelement_class->change_state = gst_emulenc_change_state;
-
-  gobject_class->finalize = gst_emulenc_finalize;
-}
-
-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);
-
-  if (oclass->codec->media_type == 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->srcpad, gst_emulenc_event_src);
-
-    emulenc->bitrate = DEFAULT_VIDEO_BITRATE;
-    emulenc->buffer_size = 512 * 1024;
-    emulenc->gop_size = DEFAULT_VIDEO_GOP_SIZE;
-#if 0
-    emulenc->lmin = 2;
-    emulenc->lmax = 31;
-#endif
-  } else if (oclass->codec->media_type == AVMEDIA_TYPE_AUDIO){
-    gst_pad_set_chain_function (emulenc->sinkpad, gst_emulenc_chain_audio);
-    emulenc->bitrate = DEFAULT_AUDIO_BITRATE;
-  }
-
-  gst_element_add_pad (GST_ELEMENT (emulenc), emulenc->sinkpad);
-  gst_element_add_pad (GST_ELEMENT (emulenc), emulenc->srcpad);
-
-  emulenc->context = g_malloc0 (sizeof(CodecContext));
-  emulenc->context->video.pix_fmt = PIX_FMT_NONE;
-  emulenc->context->audio.sample_fmt = SAMPLE_FMT_NONE;
-
-  emulenc->opened = FALSE;
-
-#if 0
-  emulenc->file = NULL;
-#endif
-  emulenc->delay = g_queue_new ();
-
-  emulenc->dev = g_malloc0 (sizeof(CodecDevice));
-  if (!emulenc->dev) {
-    printf("failed to allocate memory.\n");
-  }
-
-  // need to know what adapter does.
-  emulenc->adapter = gst_adapter_new ();
-}
-
-static void
-gst_emulenc_finalize (GObject *object)
-{
-  // Deinit Decoder
-  GstEmulEnc *emulenc = (GstEmulEnc *) object;
-
-  if (emulenc->opened) {
-    gst_emul_avcodec_close (emulenc->context, emulenc->dev);
-    emulenc->opened = FALSE;
-  }
-
-  if (emulenc->context) {
-    g_free (emulenc->context);
-    emulenc->context = NULL;
-  }
-
-  g_queue_free (emulenc->delay);
-#if 0
-  g_free (emulenc->filename);
-#endif
-
-  g_object_unref (emulenc->adapter);
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static GstCaps *
-gst_emulenc_get_possible_sizes (GstEmulEnc *emulenc, GstPad *pad,
-  const GstCaps *caps)
-{
-  GstCaps *othercaps = NULL;
-  GstCaps *tmpcaps = NULL;
-  GstCaps *intersect = NULL;
-  guint i;
-
-  othercaps = gst_pad_peer_get_caps (emulenc->srcpad);
-
-  if (!othercaps) {
-    return gst_caps_copy (caps);
-  }
-
-  intersect = gst_caps_intersect (othercaps,
-    gst_pad_get_pad_template_caps (emulenc->srcpad));
-  gst_caps_unref (othercaps);
-
-  if (gst_caps_is_empty (intersect)) {
-    return intersect;
-  }
-
-  if (gst_caps_is_any (intersect)) {
-    return gst_caps_copy (caps);
-  }
-
-  tmpcaps = gst_caps_new_empty ();
-
-  for (i = 0; i <gst_caps_get_size (intersect); i++) {
-    GstStructure *s = gst_caps_get_structure (intersect, i);
-    const GValue *height = NULL;
-    const GValue *width = NULL;
-    const GValue *framerate = NULL;
-    GstStructure *tmps;
-
-    height = gst_structure_get_value (s, "height");
-    width = gst_structure_get_value (s, "width");
-    framerate = gst_structure_get_value (s, "framerate");
-
-    tmps = gst_structure_new ("video/x-rwa-rgb", NULL);
-    if (width) {
-      gst_structure_set_value (tmps, "width", width);
-    }
-    if (height) {
-      gst_structure_set_value (tmps, "height", height);
-    }
-    if (framerate) {
-      gst_structure_set_value (tmps, "framerate", framerate);
-    }
-    gst_caps_merge_structure (tmpcaps, gst_structure_copy (tmps));
-
-    gst_structure_set_name (tmps, "video/x-raw-yuv");
-    gst_caps_merge_structure (tmpcaps, gst_structure_copy (tmps));
-
-    gst_structure_set_name (tmps, "video/x-raw-gray");
-    gst_caps_merge_structure (tmpcaps, tmps);
-  }
-  gst_caps_unref (intersect);
-
-  intersect = gst_caps_intersect (caps, tmpcaps);
-  gst_caps_unref (tmpcaps);
-
-  return intersect;
-}
-
-static GstCaps *
-gst_emulenc_getcaps (GstPad *pad)
-{
-  GstEmulEnc *emulenc = (GstEmulEnc *) GST_PAD_PARENT (pad);
-  GstEmulEncClass *oclass =
-    (GstEmulEncClass *) G_OBJECT_GET_CLASS (emulenc);
-  CodecContext *ctx = NULL;
-  enum PixelFormat pixfmt;
-  GstCaps *caps = NULL;
-  GstCaps *finalcaps = NULL;
-  gint i;
-
-  GST_DEBUG_OBJECT (emulenc, "getting caps");
-
-  if (!oclass->codec) {
-    GST_ERROR_OBJECT (emulenc, "codec element is null.");
-    return NULL;
-  }
-
-  if (oclass->codec->media_type == AVMEDIA_TYPE_AUDIO) {
-    caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
-
-    GST_DEBUG_OBJECT (emulenc, "audio caps, return template %" GST_PTR_FORMAT,
-      caps);
-    return caps;
-  }
-
-  // cached
-  if (oclass->sinkcaps) {
-    caps = gst_emulenc_get_possible_sizes (emulenc, pad, oclass->sinkcaps);
-    GST_DEBUG_OBJECT (emulenc, "return cached caps %" GST_PTR_FORMAT, caps);
-    return caps;
-  }
-
-  GST_DEBUG_OBJECT (emulenc, "probing caps");
-  i = pixfmt = 0;
-
-  for (pixfmt = 0;; pixfmt++) {
-    GstCaps *tmpcaps;
-
-    if ((pixfmt = oclass->codec->pix_fmts[i++]) == PIX_FMT_NONE) {
-      GST_DEBUG_OBJECT (emulenc,
-          "At the end of official pixfmt for this codec, breaking out");
-      break;
-    }
-
-    GST_DEBUG_OBJECT (emulenc,
-        "Got an official pixfmt [%d], attempting to get caps", pixfmt);
-    tmpcaps = gst_emul_pixfmt_to_caps (pixfmt, NULL, oclass->codec->name);
-    if (tmpcaps) {
-      GST_DEBUG_OBJECT (emulenc, "Got caps, breaking out");
-      if (!caps) {
-        caps = gst_caps_new_empty ();
-      }
-      gst_caps_append (caps, tmpcaps);
-      continue;
-    }
-
-    GST_DEBUG_OBJECT (emulenc,
-        "Couldn't figure out caps without context, trying again with a context");
-
-    GST_DEBUG_OBJECT (emulenc, "pixfmt: %d", pixfmt);
-    if (pixfmt >= PIX_FMT_NB) {
-      GST_WARNING ("Invalid pixfmt, breaking out");
-      break;
-    }
-
-    ctx = g_malloc0 (sizeof(CodecContext));
-    if (!ctx) {
-      GST_DEBUG_OBJECT (emulenc, "no context");
-      break;
-    }
-
-    ctx->video.width = DEFAULT_WIDTH;
-    ctx->video.height = DEFAULT_HEIGHT;
-    ctx->video.fps_n = 1;
-    ctx->video.fps_d = 25;
-    ctx->video.ticks_per_frame = 1;
-    ctx->bit_rate = DEFAULT_VIDEO_BITRATE;
-
-//  ctx->strict_std_compliance = -1;
-    ctx->video.pix_fmt = pixfmt;
-
-    GST_DEBUG ("Attempting to open codec");
-    if (gst_emul_avcodec_open (ctx, oclass->codec, emulenc->dev) >= 0
-        && ctx->video.pix_fmt == pixfmt) {
-      ctx->video.width = -1;
-      if (!caps) {
-        caps = gst_caps_new_empty ();
-      }
-      tmpcaps = gst_emul_codectype_to_caps (oclass->codec->media_type, ctx,
-          oclass->codec->name, TRUE);
-      if (tmpcaps) {
-        gst_caps_append (caps, tmpcaps);
-      } else {
-        GST_LOG_OBJECT (emulenc,
-            "Couldn't get caps for codec: %s", oclass->codec->name);
-      }
-      gst_emul_avcodec_close (ctx, emulenc->dev);
-    } else {
-      GST_DEBUG_OBJECT (emulenc, "Opening codec failed with pixfmt: %d", pixfmt);
-    }
-
-    gst_emul_avcodec_close (ctx, emulenc->dev);
-#if 0
-    if (ctx->priv_data) {
-      gst_emul_avcodec_close (ctx, emulenc->dev);
-    }
-#endif
-    g_free (ctx);
-  }
-
-  if (!caps) {
-    caps = gst_emulenc_get_possible_sizes (emulenc, pad,
-      gst_pad_get_pad_template_caps (pad));
-    GST_DEBUG_OBJECT (emulenc, "probing gave nothing, "
-      "return template %" GST_PTR_FORMAT, caps);
-    return caps;
-  }
-
-  GST_DEBUG_OBJECT (emulenc, "probed caps gave %" GST_PTR_FORMAT, caps);
-  oclass->sinkcaps = gst_caps_copy (caps);
-
-  finalcaps = gst_emulenc_get_possible_sizes (emulenc, pad, caps);
-  gst_caps_unref (caps);
-
-  return finalcaps;
-}
-
-static gboolean
-gst_emulenc_setcaps (GstPad *pad, GstCaps *caps)
-{
-  GstEmulEnc *emulenc;
-  GstEmulEncClass *oclass;
-  GstCaps *other_caps;
-  GstCaps *allowed_caps;
-  GstCaps *icaps;
-  enum PixelFormat pix_fmt;
-  int32_t buf_size;
-
-  emulenc = (GstEmulEnc *) (gst_pad_get_parent (pad));
-  oclass = (GstEmulEncClass *) (G_OBJECT_GET_CLASS (emulenc));
-
-  if (emulenc->opened) {
-    gst_emul_avcodec_close (emulenc->context, emulenc->dev);
-    emulenc->opened = FALSE;
-
-    gst_pad_set_caps (emulenc->srcpad, NULL);
-  }
-
-  emulenc->context->bit_rate = emulenc->bitrate;
-  GST_DEBUG_OBJECT (emulenc, "Setting context to bitrate %lu, gop_size %d",
-      emulenc->bitrate, emulenc->gop_size);
-
-#if 0
-
-  // user defined properties
-  emulenc->context->gop_size = emulenc->gop_size;
-  emulenc->context->lmin = (emulenc->lmin * FF_QP2LAMBDA + 0.5);
-  emulenc->context->lmax = (emulenc->lmax * FF_QP2LAMBDA + 0.5);
-
-  // some other defaults
-  emulenc->context->b_frame_strategy = 0;
-  emulenc->context->coder_type = 0;
-  emulenc->context->context_model = 0;
-  emulenc->context->scenechange_threshold = 0;
-  emulenc->context->inter_threshold = 0;
-
-  if (emulenc->interlaced) {
-    emulenc->context->flags |=
-      CODEC_FLAG_INTERLACED_DCT | CODEC_FLAG_INTERLACED_ME;
-    emulenc->picture->interlaced_frame = TRUE;
-
-    emulenc->picture->top_field_first = TRUE;
-  }
-#endif
-
-  gst_emul_caps_with_codectype (oclass->codec->media_type, caps, emulenc->context);
-
-  if (!emulenc->context->video.fps_d) {
-    emulenc->context->video.fps_d = 25;
-    emulenc->context->video.fps_n = 1;
-  } else if (!strcmp(oclass->codec->name ,"mpeg4")
-      && (emulenc->context->video.fps_d > 65535)) {
-      emulenc->context->video.fps_n =
-        (gint) gst_util_uint64_scale_int (emulenc->context->video.fps_n,
-            65535, emulenc->context->video.fps_d);
-      emulenc->context->video.fps_d = 65535;
-      GST_LOG_OBJECT (emulenc, "MPEG4 : scaled down framerate to %d / %d",
-          emulenc->context->video.fps_d, emulenc->context->video.fps_n);
-  }
-
-  pix_fmt = emulenc->context->video.pix_fmt;
-
-  {
-    switch (oclass->codec->media_type) {
-    case AVMEDIA_TYPE_VIDEO:
-    {
-      int width, height;
-
-      width = emulenc->context->video.width;
-      height = emulenc->context->video.height;
-      buf_size = width * height * 6 + FF_MIN_BUFFER_SIZE + 100;
-      break;
-    }
-    case AVMEDIA_TYPE_AUDIO:
-        buf_size = FF_MAX_AUDIO_FRAME_SIZE + 100;
-        break;
-    default:
-        buf_size = -1;
-        break;
-    }
-  }
-
-  emulenc->dev->buf_size = gst_emul_align_size(buf_size);
-
-  // open codec
-  if (gst_emul_avcodec_open (emulenc->context,
-      oclass->codec, emulenc->dev) < 0) {
-    GST_DEBUG_OBJECT (emulenc, "maru_%senc: Failed to open codec",
-        oclass->codec->name);
-    return FALSE;
-  }
-
-  if (pix_fmt != emulenc->context->video.pix_fmt) {
-    gst_emul_avcodec_close (emulenc->context, emulenc->dev);
-    GST_DEBUG_OBJECT (emulenc,
-      "maru_%senc: AV wants different colorspace (%d given, %d wanted)",
-      oclass->codec->name, pix_fmt, emulenc->context->video.pix_fmt);
-    return FALSE;
-  }
-
-  if (oclass->codec->media_type == AVMEDIA_TYPE_VIDEO
-    && pix_fmt == PIX_FMT_NONE) {
-    GST_DEBUG_OBJECT (emulenc, "maru_%senc: Failed to determine input format",
-      oclass->codec->name);
-    return FALSE;
-  }
-
-  GST_DEBUG_OBJECT (emulenc, "picking an output format.");
-  allowed_caps = gst_pad_get_allowed_caps (emulenc->srcpad);
-  if (!allowed_caps) {
-    GST_DEBUG_OBJECT (emulenc, "but no peer, using template caps");
-    allowed_caps =
-      gst_caps_copy (gst_pad_get_pad_template_caps (emulenc->srcpad));
-  }
-
-  GST_DEBUG_OBJECT (emulenc, "chose caps %" GST_PTR_FORMAT, allowed_caps);
-  gst_emul_caps_with_codecname (oclass->codec->name,
-    oclass->codec->media_type, allowed_caps, emulenc->context);
-
-  other_caps =
-  gst_emul_codecname_to_caps (oclass->codec->name, emulenc->context, TRUE);
-  if (!other_caps) {
-  GST_DEBUG("Unsupported codec - no caps found");
-    gst_emul_avcodec_close (emulenc->context, emulenc->dev);
-    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);
-    gst_caps_unref (icaps);
-    icaps = newcaps;
-  }
-
-  if (!gst_pad_set_caps (emulenc->srcpad, icaps)) {
-    gst_emul_avcodec_close (emulenc->context, emulenc->dev);
-    gst_caps_unref (icaps);
-    return FALSE;
-  }
-  gst_object_unref (emulenc);
-
-  emulenc->opened = TRUE;
-
-  return TRUE;
-}
-
-static void
-gst_emulenc_setup_working_buf (GstEmulEnc *emulenc)
-{
-  guint wanted_size =
-      emulenc->context->video.width * emulenc->context->video.height * 6 +
-      FF_MIN_BUFFER_SIZE;
-
-  if (emulenc->working_buf == NULL ||
-    emulenc->working_buf_size != wanted_size) {
-    if (emulenc->working_buf) {
-      g_free (emulenc->working_buf);
-    }
-    emulenc->working_buf_size = wanted_size;
-    emulenc->working_buf = g_malloc0 (emulenc->working_buf_size);
-  }
-  emulenc->buffer_size = wanted_size;
-}
-
-GstFlowReturn
-gst_emulenc_chain_video (GstPad *pad, GstBuffer *buffer)
-{
-  GstEmulEnc *emulenc = (GstEmulEnc *) (GST_PAD_PARENT (pad));
-  GstBuffer *outbuf;
-  gint ret_size = 0, frame_size;
-
-  GST_DEBUG_OBJECT (emulenc,
-      "Received buffer of time %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
-
-#if 0
-  GST_OBJECT_LOCK (emulenc);
-  force_keyframe = emulenc->force_keyframe;
-  emulenc->force_keyframe = FALSE;
-  GST_OBJECT_UNLOCK (emulenc);
-
-  if (force_keyframe) {
-    emulenc->picture->pict_type = FF_I_TYPE;
-  }
-#endif
-
-  frame_size = gst_emul_avpicture_size (emulenc->context->video.pix_fmt,
-      emulenc->context->video.width, emulenc->context->video.height);
-  g_return_val_if_fail (frame_size == GST_BUFFER_SIZE (buffer),
-      GST_FLOW_ERROR);
-
-#if 0
-  pts = gst_emul_time_gst_to_ff (GST_BUFFER_TIMESTAMP (buffer) /
-    emulenc->context.video.ticks_per_frame,
-    emulenc->context.video.fps_n, emulen->context.video.fps_d);
-#endif
-
-  // TODO: check whether this func needs or not.
-  gst_emulenc_setup_working_buf (emulenc);
-
-  ret_size =
-    codec_encode_video (emulenc->context, emulenc->working_buf,
-                emulenc->working_buf_size, GST_BUFFER_DATA (buffer),
-                GST_BUFFER_SIZE (buffer), GST_BUFFER_TIMESTAMP (buffer),
-                emulenc->dev);
-
-  if (ret_size < 0) {
-    GstEmulEncClass *oclass =
-      (GstEmulEncClass *) (G_OBJECT_GET_CLASS (emulenc));
-    GST_ERROR_OBJECT (emulenc,
-        "maru_%senc: failed to encode buffer", oclass->codec->name);
-    gst_buffer_unref (buffer);
-    return GST_FLOW_OK;
-  }
-
-  g_queue_push_tail (emulenc->delay, buffer);
-  if (ret_size) {
-    buffer = g_queue_pop_head (emulenc->delay);
-  } else {
-    return GST_FLOW_OK;
-  }
-
-#if 0
-  if (emulenc->file && emulenc->context->stats_out) {
-    if (fprintf (emulenc->file, "%s", emulenc->context->stats_out) < 0) {
-      GST_ELEMENT_ERROR (emulenc, RESOURCE, WRITE,
-        (("Could not write to file \"%s\"."), emulenc->filename),
-        GST_ERROR_SYSTEM);
-    }
-  }
-#endif
-#if 1
-  {
-    int ret;
-    uint32_t mem_offset;
-    uint8_t *working_buf = NULL;
-
-    mem_offset = emulenc->dev->mem_info.offset;
-    working_buf = emulenc->dev->buf + mem_offset;
-    if (!working_buf) {
-    } else {
-      CODEC_LOG (INFO,
-          "encoded video. mem_offset = 0x%x\n",  mem_offset);
-
-      outbuf = gst_buffer_new_and_alloc (ret_size);
-//    memcpy (GST_BUFFER_DATA (outbuf), emulenc->working_buf, ret_size);
-      memcpy (GST_BUFFER_DATA (outbuf), working_buf, ret_size);
-      GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buffer);
-      GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buffer);
-    }
-
-    ret = ioctl(emulenc->dev->fd, CODEC_CMD_RELEASE_MEMORY, &mem_offset);
-    if (ret < 0) {
-      CODEC_LOG (ERR, "failed to release used buffer\n");
-    }
-  }
-#endif
-
-#if 0
-  if (emulenc->context->coded_frame) {
-    if (!emulenc->context->coded_frame->key_frame) {
-      GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
-    }
-  } else {
-    GST_WARNING_OBJECT (emulenc, "codec did not provide keyframe info");
-  }
-#endif
-  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (emulenc->srcpad));
-
-  gst_buffer_unref (buffer);
-
-#if 0
-
-  if (force_keyframe) {
-    gst_pad_push_event (emulenc->srcpad,
-      gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
-      gst_structure_new ("GstForceKeyUnit", "timestamp",
-                         G_TYPE_UINT64, GST_BUFFER_TIMESTAMP (outbuf), NULL)));
-  }
-#endif
-
-  return gst_pad_push (emulenc->srcpad, outbuf);
-}
-
-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 *audio_out;
-  gint res;
-  GstFlowReturn ret;
-
-  outbuf = gst_buffer_new_and_alloc (max_size + FF_MIN_BUFFER_SIZE);
-  audio_out = GST_BUFFER_DATA (outbuf);
-
-  GST_LOG_OBJECT (emulenc, "encoding buffer of max size %d", max_size);
-  if (emulenc->buffer_size != max_size) {
-    emulenc->buffer_size = max_size;
-  }
-
-  res = codec_encode_audio (emulenc->context, audio_out, max_size,
-                                  audio_in, in_size, emulenc->dev);
-
-  if (res < 0) {
-    GST_ERROR_OBJECT (emulenc, "Failed to encode buffer: %d", res);
-    gst_buffer_unref (outbuf);
-    return GST_FLOW_OK;
-  }
-  GST_LOG_OBJECT (emulenc, "got output size %d", res);
-
-  GST_BUFFER_SIZE (outbuf) = res;
-  GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
-  GST_BUFFER_DURATION (outbuf) = duration;
-  if (discont) {
-    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
-  }
-  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (emulenc->srcpad));
-
-  GST_LOG_OBJECT (emulenc, "pushing size %d, timestamp %",
-      GST_TIME_FORMAT, res, GST_TIME_ARGS (timestamp));
-
-  ret = gst_pad_push (emulenc->srcpad, outbuf);
-
-  return ret;
-}
-
-static GstFlowReturn
-gst_emulenc_chain_audio (GstPad *pad, GstBuffer *buffer)
-{
-  GstEmulEnc *emulenc;
-  GstEmulEncClass *oclass;
-  GstClockTime timestamp, duration;
-  guint in_size, frame_size;
-  gint osize;
-  GstFlowReturn ret;
-  gint out_size = 0;
-  gboolean discont;
-  guint8 *in_data;
-  CodecContext *ctx;
-
-  emulenc = (GstEmulEnc *) (GST_OBJECT_PARENT (pad));
-  oclass = (GstEmulEncClass *) G_OBJECT_GET_CLASS (emulenc);
-
-  ctx = emulenc->context;
-
-  in_size = GST_BUFFER_SIZE (buffer);
-  timestamp = GST_BUFFER_TIMESTAMP (buffer);
-  duration = GST_BUFFER_DURATION (buffer);
-  discont = GST_BUFFER_IS_DISCONT (buffer);
-
-  GST_DEBUG_OBJECT (emulenc,
-    "Received time %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT
-    ", size %d", GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration), in_size);
-
-  frame_size = ctx->audio.frame_size;
-  osize = ctx->audio.bits_per_sample_fmt;
-
-  if (frame_size > 1) {
-    guint avail, frame_bytes;
-
-    if (discont) {
-      GST_LOG_OBJECT (emulenc, "DISCONT, clear adapter");
-      gst_adapter_clear (emulenc->adapter);
-      emulenc->discont = TRUE;
-    }
-
-    if (gst_adapter_available (emulenc->adapter) == 0) {
-      GST_LOG_OBJECT (emulenc, "taking buffer timestamp %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (timestamp));
-      emulenc->adapter_ts = timestamp;
-      emulenc->adapter_consumed = 0;
-    } else {
-      GstClockTime upstream_time;
-      GstClockTime consumed_time;
-      guint64 bytes;
-
-      consumed_time =
-        gst_util_uint64_scale (emulenc->adapter_consumed, GST_SECOND,
-            ctx->audio.sample_rate);
-      timestamp = emulenc->adapter_ts + consumed_time;
-      GST_LOG_OBJECT (emulenc, "taking adapter timestamp %" GST_TIME_FORMAT
-        " and adding consumed time %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (emulenc->adapter_ts), GST_TIME_ARGS (consumed_time));
-
-      upstream_time = gst_adapter_prev_timestamp (emulenc->adapter, &bytes);
-      if (GST_CLOCK_TIME_IS_VALID (upstream_time)) {
-        GstClockTimeDiff diff;
-
-        upstream_time +=
-          gst_util_uint64_scale (bytes, GST_SECOND,
-            ctx->audio.sample_rate * osize * ctx->audio.channels);
-        diff = upstream_time - timestamp;
-
-        if (diff > GST_SECOND / 10 || diff < -GST_SECOND / 10) {
-          GST_DEBUG_OBJECT (emulenc, "adapter timestamp drifting, "
-            "taking upstream timestamp %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (upstream_time));
-          timestamp = upstream_time;
-
-          emulenc->adapter_consumed = bytes / (osize * ctx->audio.channels);
-          emulenc->adapter_ts =
-            upstream_time - gst_util_uint64_scale (emulenc->adapter_consumed,
-                GST_SECOND, ctx->audio.sample_rate);
-          emulenc->discont = TRUE;
-        }
-      }
-    }
-
-    GST_LOG_OBJECT (emulenc, "pushing buffer in adapter");
-    gst_adapter_push (emulenc->adapter, buffer);
-
-    frame_bytes = frame_size * osize * ctx->audio.channels;
-    avail = gst_adapter_available (emulenc->adapter);
-
-    GST_LOG_OBJECT (emulenc, "frame_bytes %u, avail %u", frame_bytes, avail);
-
-    while (avail >= frame_bytes) {
-      GST_LOG_OBJECT (emulenc, "taking %u bytes from the adapter", frame_bytes);
-
-      in_data = (guint8 *) gst_adapter_peek (emulenc->adapter, frame_bytes);
-      emulenc->adapter_consumed += frame_size;
-
-      duration =
-        gst_util_uint64_scale (emulenc->adapter_consumed, GST_SECOND,
-          ctx->audio.sample_rate);
-      duration -= (timestamp - emulenc->adapter_ts);
-
-      out_size = frame_bytes * 4;
-
-      ret =
-        gst_emulenc_encode_audio (emulenc, in_data, frame_bytes, out_size,
-          timestamp, duration, emulenc->discont);
-
-      gst_adapter_flush (emulenc->adapter, frame_bytes);
-      if (ret != GST_FLOW_OK) {
-        GST_DEBUG_OBJECT (emulenc, "Failed to push buffer %d (%s)", ret,
-          gst_flow_get_name (ret));
-      }
-
-      timestamp += duration;
-
-      emulenc->discont = FALSE;
-      avail = gst_adapter_available (emulenc->adapter);
-    }
-    GST_LOG_OBJECT (emulenc, "%u bytes left in the adapter", avail);
-  } else {
-#if 0
-    int coded_bps = av_get_bits_per_sample (oclass->codec->name);
-
-    GST_LOG_OBJECT (emulenc, "coded bps %d, osize %d", coded_bps, osize);
-
-    out_size = in_size / osize;
-    if (coded_bps) {
-      out_size = (out_size * coded_bps) / 8;
-    }
-#endif
-    in_data = (guint8 *) GST_BUFFER_DATA (buffer);
-    ret = gst_emulenc_encode_audio (emulenc, in_data, in_size, out_size,
-      timestamp, duration, discont);
-    gst_buffer_unref (buffer);
-    if (ret != GST_FLOW_OK) {
-      GST_DEBUG_OBJECT (emulenc, "Failed to push buffer %d (%s)", ret,
-        gst_flow_get_name (ret));
-    }
-  }
-
-  return GST_FLOW_OK;
-}
-
-static void
-gst_emulenc_flush_buffers (GstEmulEnc *emulenc, gboolean send)
-{
-  GstBuffer *outbuf, *inbuf;
-  gint ret_size = 0;
-
-  GST_DEBUG_OBJECT (emulenc, "flushing buffers with sending %d", send);
-
-  if (!emulenc->opened) {
-    while (!g_queue_is_empty (emulenc->delay)) {
-      gst_buffer_unref (g_queue_pop_head (emulenc->delay));
-    }
-  }
-
-#if 0
-  while (!g_queue_is_empty (emulenc->delay)) {
-    emulenc_setup_working_buf (emulenc);
-
-    ret_size = codec_encode_video (emulenc->context,
-      emulenc->working_buf, emulenc->working_buf_size, NULL, NULL, 0,
-      emulenc->dev);
-
-    if (ret_size < 0) {
-      GstEmulEncClass *oclass =
-        (GstEmulEncClass *) (G_OBJECT_GET_CLASS (emulenc));
-      GST_WARNING_OBJECT (emulenc,
-        "maru_%senc: failed to flush buffer", oclass->codec->name);
-      break;
-    }
-
-    if (emulenc->file && emulenc->context->stats_out) {
-      if (fprintf (emulenc->file, "%s", emulenc->context->stats_out) < 0) {
-        GST_ELEMENT_ERROR (emeulenc, RESOURCE, WRITE,
-          (("Could not write to file \"%s\"."), emulenc->filename),
-          GST_ERROR_SYSTEM);
-      }
-    }
-
-    inbuf = g_queue_pop_head (emulenc->delay);
-
-    outbuf = gst_buffer_new_and_alloc (ret_size);
-    memcpy (GST_BUFFER_DATA (outbuf), emulenc->working_buf, ret_size);
-    GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (inbuf);
-    GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (inbuf);
-
-    if (!emulenc->context->coded_frame->key_frame) {
-      GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
-    }
-    gst_buffer_set_caps (outbuf, GST_PAD_CAPS (emulenc->srcpad));
-
-    gst_buffer_unref (inbuf);
-
-    if (send) {
-      gst_pad_push (emulenc->srcpad, outbuf);
-    } else {
-      gst_buffer_unref (outbuf);
-    }
-  }
-
-  while (!g_queue_is_empty (emulenc->delay)) {
-    gst_buffer_unref (g_queue_pop_head (emulenc->delay));
-  }
-#endif
-}
-
-static gboolean
-gst_emulenc_event_video (GstPad *pad, GstEvent *event)
-{
-  GstEmulEnc *emulenc;
-  emulenc = (GstEmulEnc *) gst_pad_get_parent (pad);
-
-  switch (GST_EVENT_TYPE (event)) {
-  case GST_EVENT_EOS:
-    gst_emulenc_flush_buffers (emulenc, TRUE);
-    break;
-  case GST_EVENT_CUSTOM_DOWNSTREAM:
-  {
-    const GstStructure *s;
-    s = gst_event_get_structure (event);
-
-    if (gst_structure_has_name (s, "GstForceKeyUnit")) {
-#if 0
-      emulenc->picture->pict_type = FF_I_TYPE;
-#endif
-    }
-  }
-    break;
-  default:
-    break;
-  }
-
-  return gst_pad_push_event (emulenc->srcpad, event);
-}
-
-static gboolean
-gst_emulenc_event_src (GstPad *pad, GstEvent *event)
-{
-  GstEmulEnc *emulenc = (GstEmulEnc *) (GST_PAD_PARENT (pad));
-  gboolean forward = TRUE;
-
-  switch (GST_EVENT_TYPE (event)) {
-  case GST_EVENT_CUSTOM_UPSTREAM:
-  {
-    const GstStructure *s;
-    s = gst_event_get_structure (event);
-
-    if (gst_structure_has_name (s, "GstForceKeyUnit")) {
-#if 0
-      GST_OBJECT_LOCK (emulenc);
-      emulenc->force_keyframe = TRUE;
-      GST_OBJECT_UNLOCK (emulenc);
-#endif
-      forward = FALSE;
-      gst_event_unref (event);
-    }
-  }
-    break;
-  default:
-    break;
-  }
-
-  if (forward) {
-    return gst_pad_push_event (emulenc->sinkpad, event);
-  }
-
-  return TRUE;
-}
-
-GstStateChangeReturn
-gst_emulenc_change_state (GstElement *element, GstStateChange transition)
-{
-  GstEmulEnc *emulenc = (GstEmulEnc*)element;
-  GstStateChangeReturn ret;
-
-  switch (transition) {
-  default:
-    break;
-  }
-
-  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
-  switch (transition) {
-  case GST_STATE_CHANGE_PAUSED_TO_READY:
-    gst_emulenc_flush_buffers (emulenc, FALSE);
-    if (emulenc->opened) {
-      gst_emul_avcodec_close (emulenc->context, emulenc->dev);
-      emulenc->opened = FALSE;
-    }
-    gst_adapter_clear (emulenc->adapter);
-
-#if 0
-    if (emulenc->flie) {
-      fclose (emulenc->file);
-      emulenc->file = NULL;
-    }
-#endif
-
-    if (emulenc->working_buf) {
-      g_free (emulenc->working_buf);
-      emulenc->working_buf = NULL;
-    }
-    break;
-  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_NONE;
-  GList *elem = element;
-  CodecElement *codec = NULL;
-
-  if (!elem) {
-    return FALSE;
-  }
-
-  /* register element */
-  do {
-    codec = (CodecElement *)(elem->data);
-    if (!codec) {
-      return FALSE;
-    }
-
-    if (codec->codec_type != CODEC_TYPE_ENCODE) {
-      continue;
-    }
-
-    type_name = g_strdup_printf ("maru_%senc", 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_EMULENC_PARAMS_QDATA, (gpointer) codec);
-    }
-
-    if (!gst_element_register (plugin, type_name, rank, type)) {
-      g_free (type_name);
-      return FALSE;
-    }
-    g_free (type_name);
-  } while ((elem = elem->next));
-
-  return TRUE;
-}
diff --git a/src/gstemulutils.c b/src/gstemulutils.c
deleted file mode 100644 (file)
index 04ae7c1..0000000
+++ /dev/null
@@ -1,1172 +0,0 @@
-/*
- * 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, pixel format: %d",
-      ctx, name, encode, ctx->video.pix_fmt);
-
-  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 (ctx) {
-    caps = gst_emul_smpfmt_to_caps (ctx->audio.sample_fmt, ctx, name);
-#if 1
-  } else if (codec && codec->sample_fmts[0] != -1){
-    GstCaps *temp;
-    int i;
-
-    caps = gst_caps_new_empty ();
-    for (i = 0; codec->sample_fmts[i] != -1; i++) {
-      temp =
-          gst_emul_smpfmt_to_caps (codec->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);
-  ctx->video.ticks_per_frame = 1;
-
-    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;
-      }
-    }
-//    printf ("get pixel format: %d, fourcc: %d\n", ctx->video.pix_fmt, fourcc);
-  } 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);
-  gst_structure_get_int (str, "bitrate", &ctx->bit_rate);
-
-  if (!raw) {
-    return;
-  }
-
-  name = gst_structure_get_name (str);
-
-  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 (gst_structure_get_int (str, "width", &width) &&
-      gst_structure_get_int (str, "depth", &depth) &&
-      gst_structure_get_boolean (str, "signed", &signedness) &&
-      gst_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 = SAMPLE_FMT_S32;
-        }
-      }
-    }
-  }
-}
-
-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);
-    GST_DEBUG ("extradata: %p, size: %d\n", data, 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 (!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');
-    }
-#if 0
-  } else if (strcmp (name, "h263p") == 0) {
-    gboolean val;
-
-    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;
-  }
-
-}
-
-void
-gst_emul_caps_with_codectype (int media_type, const GstCaps *caps, CodecContext *ctx)
-{
-  if (ctx == NULL) {
-    return;
-  }
-
-  switch (media_type) {
-  case AVMEDIA_TYPE_VIDEO:
-    gst_emul_caps_to_pixfmt (caps, ctx, TRUE);
-    break;
-  case AVMEDIA_TYPE_AUDIO:
-    gst_emul_caps_to_smpfmt (caps, ctx, TRUE);
-    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, NULL);
-
-    num = ctx->video.fps_d / ctx->video.ticks_per_frame;
-    denom = ctx->video.fps_n;
-
-    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 (strcmp (name, "h263") == 0) {
-      /* 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 if (strcmp (name, "none") == 0) {
-      GST_LOG ("default caps");
-    }
-  }
-
-  /* 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, "none", "video/x-h263",
-                  "variant", G_TYPE_STRING, "itu", 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
-    switch (ctx->codec_tag) {
-    case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
-      caps = gst_emul_video_caps_new (ctx, name, "video/x-divx",
-        "divxversion", G_TYPE_INT, 5, NULL);
-      break;
-    case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
-    default:
-      caps = gst_emul_video_caps_new (ctx, name, "video/mpeg",
-        "systemstream", G_TYPE_BOOLEAN, FALSE,
-        "mpegversion", G_TYPE_INT, 4, NULL);
-      break;
-    }
-    } 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 (ctx && ctx->codecdata_size > 0) {
-          gst_codec_utils_aac_caps_set_level_and_profile (caps,
-            ctx->codecdata, ctx->codecdata_size);
-        }
-    }
-  } 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 (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 {
-      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];
-
-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;
-}
-
-int
-gst_emul_align_size (int buf_size)
-{
-  int i, align_size;
-
-  align_size = buf_size / 1024;
-
-  for (i = 0; i < 14; i++) {
-    if (align_size < (1 << i)) {
-      align_size = 1024 * (1 << i);
-      break;
-    }
-  }
-
-  return align_size;
-}
diff --git a/src/gstemulutils.h b/src/gstemulutils.h
deleted file mode 100644 (file)
index 17efc7e..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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);
-
-void gst_emul_caps_with_codectype (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);
-
-void gst_emul_init_pix_fmt_info (void);
-
-int gst_emul_avpicture_size (int pix_fmt, int width, int height);
-
-int gst_emul_align_size (int buf_size);
-
-gint gst_emul_smpfmt_depth (int smp_fmt);
-
-#endif
diff --git a/src/gstmaru.c b/src/gstmaru.c
new file mode 100644 (file)
index 0000000..0407765
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+
+/* First, include the header file for the plugin, to bring in the
+ * object definition and other useful things.
+ */
+
+/*
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#include "gstmaru.h"
+
+GST_DEBUG_CATEGORY (maru_debug);
+
+#define GST_TYPE_EMULDEC \
+  (gst_maru_dec_get_type())
+#define GST_EMULDEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_EMULDEC,GstEmulDec))
+#define GST_EMULDEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_EMULDEC,GstEmulDecClass))
+#define GST_IS_EMULDEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_EMULDEC))
+#define GST_IS_EMULDEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_EMULDEC))
+
+gboolean gst_marudec_register (GstPlugin *plugin, GList *element);
+gboolean gst_maruenc_register (GstPlugin *plugin, GList *element);
+
+static GList *codec_element = NULL;
+
+static gboolean
+gst_maru_codec_element_init ()
+{
+  int fd = 0, size = 0;
+  int version = 0;
+  int data_length = 0;
+  int i, elem_cnt = 0;
+  void *buffer = NULL;
+  CodecElement *elem = NULL;
+
+  fd = open (CODEC_DEV, O_RDWR);
+  if (fd < 0) {
+    perror ("[gst-maru] failed to open codec device");
+    return FALSE;
+  }
+
+  ioctl (fd, CODEC_CMD_GET_VERSION, &version);
+  if (version != CODEC_VER) {
+    CODEC_LOG (INFO, "version conflict between device: %d, plugin: %d\n",
+              version, CODEC_VER);
+    close (fd);
+    return FALSE;
+  }
+
+  buffer = mmap (NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if (!buffer) {
+    perror ("[gst-maru] failure memory mapping.");
+    close (fd);
+    return FALSE;
+  }
+
+  CODEC_LOG (DEBUG, "request a device to get codec element.\n");
+  if (ioctl(fd, CODEC_CMD_GET_ELEMENT, NULL) < 0) {
+    perror ("[gst-maru] failed to get codec elements");
+    munmap (buffer, 4096);
+    close (fd);
+    return FALSE;
+  }
+
+  memcpy(&data_length, (uint8_t *)buffer, sizeof(data_length));
+  size += sizeof(data_length);
+
+  elem = g_malloc0 (data_length);
+  if (!elem) {
+    CODEC_LOG (ERR, "Failed to allocate memory.\n");
+    munmap (buffer, 4096);
+    close (fd);
+    return FALSE;
+  }
+
+  memcpy (elem, (uint8_t *)buffer + size, data_length);
+
+  elem_cnt = data_length / sizeof(CodecElement);
+  for (i = 0; i < elem_cnt; i++) {
+    codec_element = g_list_append (codec_element, &elem[i]);
+  }
+
+  munmap (buffer, 4096);
+  close (fd);
+
+  return TRUE;
+}
+
+static gboolean
+plugin_init (GstPlugin *plugin)
+{
+  GST_DEBUG_CATEGORY_INIT (maru_debug,
+      "tizen-maru", 0, "Tizen Emulator Codec Elements");
+
+  gst_maru_init_pix_fmt_info ();
+
+  if (!gst_maru_codec_element_init ()) {
+    GST_ERROR ("failed to get codec elements from QEMU");
+    return FALSE;
+  }
+
+  if (!gst_marudec_register (plugin, codec_element)) {
+    GST_ERROR ("failed to register decoder elements");
+    return FALSE;
+  }
+  if (!gst_maruenc_register (plugin, codec_element)) {
+    GST_ERROR ("failed to register encoder elements");
+    return FALSE;
+  }
+
+#if 0
+  while ((codec_element = g_list_next (codec_element))) {
+    g_list_free (codec_element);
+  }
+#endif
+
+  return TRUE;
+}
+
+#ifndef PACKAGE
+#define PACKAGE "gst-plugins-maruator"
+#endif
+
+GST_PLUGIN_DEFINE (
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "tizen-emul",
+  "Codecs for Tizen Emulator",
+  plugin_init,
+  "0.1.1",
+  "LGPL",
+  "gst-plugins-emulator",
+  "http://tizen.org"
+)
diff --git a/src/gstmaru.h b/src/gstmaru.h
new file mode 100644 (file)
index 0000000..e7ab644
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * 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_MARU_H__
+#define __GST_MARU_H__
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.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 (maru_debug);
+#define GST_CAT_DEFAULT maru_debug
+
+G_BEGIN_DECLS
+
+enum codec_log_level {
+  ERR,
+  WARN,
+  INFO,
+  DEBUG,
+};
+
+#define CODEC_DEV   "/dev/brillcodec"
+#define CODEC_VER   1
+
+#define CODEC_LOG(level, fmt, ...) \
+  do { \
+    if (level <= INFO) \
+      printf("[gst-maru][%d] " fmt, __LINE__, ##__VA_ARGS__); \
+  } while (0)
+
+#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
+
+#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))
+
+typedef struct _CodecIOParams {
+  int32_t   api_index;
+  int32_t   ctx_index;
+  uint32_t  mem_offset;
+} CodecIOParams;
+
+typedef struct _CodecDeviceMem {
+  uint32_t  index;
+  uint32_t  offset;
+} CodecDeviceMem;
+
+typedef struct _CodecDevice {
+  int       fd;
+  uint8_t   *buf;
+  uint32_t  buf_size;
+  CodecDeviceMem mem_info;
+} CodecDevice;
+
+typedef struct _CodecElement {
+  int32_t codec_type;
+  int32_t media_type;
+  gchar name[32];
+  gchar longname[64];
+  union {
+    int32_t pix_fmts[4];
+    int32_t sample_fmts[4];
+  };
+} CodecElement;
+
+typedef struct _VideoData {
+  int32_t width, height;
+  int32_t fps_n, fps_d;
+  int32_t par_n, par_d;
+  int32_t pix_fmt, bpp;
+  int32_t ticks_per_frame;
+} VideoData;
+
+typedef struct _AudioData {
+  int32_t channels, sample_rate;
+  int32_t block_align, depth;
+  int32_t sample_fmt, frame_size;
+  int32_t bits_per_sample_fmt;
+  int64_t channel_layout;
+} AudioData;
+
+typedef struct _CodecContext {
+//  union {
+    VideoData video;
+    AudioData audio;
+//  };
+
+  int32_t bit_rate;
+  int32_t codec_tag;
+
+  int32_t codecdata_size;
+  uint8_t *codecdata;
+
+  CodecElement *codec;
+  int32_t index;
+} CodecContext;
+
+enum CODEC_FUNC_TYPE {
+  CODEC_INIT = 0,
+  CODEC_DECODE_VIDEO,
+  CODEC_ENCODE_VIDEO,
+  CODEC_DECODE_AUDIO,
+  CODEC_ENCODE_AUDIO,
+  CODEC_PICTURE_COPY,
+  CODEC_DEINIT,
+};
+
+#if 0
+enum CODEC_IO_CMD {
+  CODEC_CMD_COPY_TO_DEVICE_MEM = 5,
+  CODEC_CMD_COPY_FROM_DEVICE_MEM,
+  CODEC_CMD_GET_VERSION = 20,
+  CODEC_CMD_GET_ELEMENT,
+  CODEC_CMD_GET_CONTEXT_INDEX,
+  CODEC_CMD_SECURE_MEMORY = 30,
+  CODEC_CMD_RELEASE_MEMORY,
+  CODEC_CMD_USE_DEVICE_MEM,
+  CODEC_CMD_REQ_FROM_SMALL_MEMORY,
+  CODEC_CMD_REQ_FROM_MEDIUM_MEMORY,
+  CODEC_CMD_REQ_FROM_LARGE_MEMORY,
+  CODEC_CMD_S_SECURE_BUFFER,
+  CODEC_CMD_M_SECURE_BUFFER,
+  CODEC_CMD_L_SECURE_BUFFER,
+};
+#endif
+
+enum CODEC_IO_CMD {
+  CODEC_CMD_GET_VERSION = 20,
+  CODEC_CMD_GET_ELEMENT,
+  CODEC_CMD_GET_CONTEXT_INDEX,
+  CODEC_CMD_USE_DEVICE_MEM = 40,
+  CODEC_CMD_GET_DATA_FROM_SMALL_BUFFER,
+  CODEC_CMD_GET_DATA_FROM_MEDIUM_BUFFER,
+  CODEC_CMD_GET_DATA_FROM_LARGE_BUFFER,
+  CODEC_CMD_SECURE_SMALL_BUFFER,
+  CODEC_CMD_SECURE_MEDIUM_BUFFER,
+  CODEC_CMD_SECURE_LARGE_BUFFER,
+  CODEC_CMD_RELEASE_BUFFER,
+};
+
+
+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,
+  SAMPLE_FMT_S16,
+  SAMPLE_FMT_S32,
+  SAMPLE_FMT_FLT,
+  SAMPLE_FMT_DBL,
+  SAMPLE_FMT_NB
+};
+
+G_END_DECLS
+#endif
diff --git a/src/gstmarudec.c b/src/gstmarudec.c
new file mode 100644 (file)
index 0000000..70bd6b6
--- /dev/null
@@ -0,0 +1,1568 @@
+/*
+ * 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 "gstmaru.h"
+#include "gstmaruutils.h"
+#include "gstmaruinterface.h"
+#include "gstmarudevice.h"
+
+#define GST_MARUDEC_PARAMS_QDATA g_quark_from_static_string("marudec-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 opened;
+  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_marudec_base_init (GstEmulDecClass *klass);
+static void gst_marudec_class_init (GstEmulDecClass *klass);
+static void gst_marudec_init (GstEmulDec *marudec);
+static void gst_marudec_finalize (GObject *object);
+
+static gboolean gst_marudec_setcaps (GstPad *pad, GstCaps *caps);
+
+// sinkpad
+static gboolean gst_marudec_sink_event (GstPad *pad, GstEvent *event);
+static GstFlowReturn gst_marudec_chain (GstPad *pad, GstBuffer *buffer);
+
+// srcpad
+static gboolean gst_marudec_src_event (GstPad *pad, GstEvent *event);
+static GstStateChangeReturn gst_marudec_change_state (GstElement *element,
+                                                GstStateChange transition);
+
+static gboolean gst_marudec_negotiate (GstEmulDec *dec, gboolean force);
+
+static gint gst_marudec_frame (GstEmulDec *marudec, guint8 *data,
+                              guint size, gint *got_data,
+                              const GstTSInfo *dec_info, gint64 in_offset, GstFlowReturn *ret);
+
+static gboolean gst_marudec_open (GstEmulDec *marudec);
+static int gst_marudec_close (GstEmulDec *marudec);
+
+
+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_marudec_reset_ts (GstEmulDec *marudec)
+{
+  marudec->next_out = GST_CLOCK_TIME_NONE;
+}
+
+static void
+gst_marudec_update_qos (GstEmulDec *marudec, gdouble proportion,
+  GstClockTime timestamp)
+{
+  GST_LOG_OBJECT (marudec, "update QOS: %f, %" GST_TIME_FORMAT,
+      proportion, GST_TIME_ARGS (timestamp));
+
+  GST_OBJECT_LOCK (marudec);
+  marudec->proportion = proportion;
+  marudec->earliest_time = timestamp;
+  GST_OBJECT_UNLOCK (marudec);
+}
+
+static void
+gst_marudec_reset_qos (GstEmulDec *marudec)
+{
+  gst_marudec_update_qos (marudec, 0.5, GST_CLOCK_TIME_NONE);
+  marudec->processed = 0;
+  marudec->dropped = 0;
+}
+
+static gboolean
+gst_marudec_do_qos (GstEmulDec *marudec, 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))) {
+    marudec->processed++;
+    return TRUE;
+  }
+
+  proportion = marudec->proportion;
+  earliest_time = marudec->earliest_time;
+
+  qostime = gst_segment_to_running_time (&marudec->segment, GST_FORMAT_TIME,
+    timestamp);
+
+  if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (qostime))) {
+    marudec->processed++;
+    return TRUE;
+  }
+
+  diff = GST_CLOCK_DIFF (qostime, earliest_time);
+
+  if (proportion < 0.4 && diff < 0 ){
+    marudec->processed++;
+    return TRUE;
+  } else {
+    if (diff >= 0) {
+//      if (marudec->waiting_for_key) {
+      if (0) {
+        res = FALSE;
+      } else {
+      }
+
+      GstClockTime stream_time, jitter;
+      GstMessage *qos_msg;
+
+      marudec->dropped++;
+      stream_time =
+          gst_segment_to_stream_time (&marudec->segment, GST_FORMAT_TIME,
+                  timestamp);
+      jitter = GST_CLOCK_DIFF (qostime, earliest_time);
+      qos_msg =
+          gst_message_new_qos (GST_OBJECT_CAST (marudec), 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,
+              marudec->processed, marudec->dropped);
+      gst_element_post_message (GST_ELEMENT_CAST (marudec), qos_msg);
+
+      return res;
+    }
+  }
+
+  marudec->processed++;
+  return TRUE;
+}
+
+static void
+clear_queued (GstEmulDec *marudec)
+{
+  g_list_foreach (marudec->queued, (GFunc) gst_mini_object_unref, NULL);
+  g_list_free (marudec->queued);
+  marudec->queued = NULL;
+}
+
+static GstFlowReturn
+flush_queued (GstEmulDec *marudec)
+{
+  GstFlowReturn res = GST_FLOW_OK;
+
+  CODEC_LOG (DEBUG, "flush queued\n");
+
+  while (marudec->queued) {
+    GstBuffer *buf = GST_BUFFER_CAST (marudec->queued->data);
+
+    GST_LOG_OBJECT (marudec, "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 (marudec->srcpad, buf);
+
+    marudec->queued =
+      g_list_delete_link (marudec->queued, marudec->queued);
+  }
+
+  return res;
+}
+
+static void
+gst_marudec_drain (GstEmulDec *marudec)
+{
+  GstEmulDecClass *oclass;
+
+  oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (marudec));
+
+  // TODO: drain
+#if 1
+  {
+    gint have_data, len, try = 0;
+
+    do {
+      GstFlowReturn ret;
+
+      len =
+        gst_marudec_frame (marudec, NULL, 0, &have_data, &ts_info_none, 0, &ret);
+
+      if (len < 0 || have_data == 0) {
+        break;
+      }
+    } while (try++ < 10);
+  }
+#endif
+
+  if (marudec->segment.rate < 0.0) {
+    CODEC_LOG (DEBUG, "reverse playback\n");
+    flush_queued (marudec);
+  }
+}
+
+/*
+ * Implementation
+ */
+static void
+gst_marudec_base_init (GstEmulDecClass *klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstCaps *sinkcaps = NULL, *srccaps = NULL;
+  GstPadTemplate *sinktempl, *srctempl;
+  CodecElement *codec;
+  gchar *longname, *classification, *description;
+
+  codec =
+      (CodecElement *)g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
+                                      GST_MARUDEC_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");
+  description = g_strdup_printf("%s Decoder", codec->name);
+
+  gst_element_class_set_details_simple (element_class,
+            longname,
+            classification,
+            description,
+            "Kitae Kim <kt920.kim@samsung.com>");
+
+  g_free (longname);
+  g_free (classification);
+  g_free (description);
+
+  sinkcaps = gst_maru_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_maru_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_marudec_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_marudec_set_property
+  gobject_class->get_property = gst_marudec_get_property
+#endif
+
+  gobject_class->finalize = gst_marudec_finalize;
+  gstelement_class->change_state = gst_marudec_change_state;
+}
+
+static void
+gst_marudec_init (GstEmulDec *marudec)
+{
+  GstEmulDecClass *oclass;
+
+  oclass = (GstEmulDecClass*) (G_OBJECT_GET_CLASS(marudec));
+
+  marudec->sinkpad = gst_pad_new_from_template (oclass->sinktempl, "sink");
+  gst_pad_set_setcaps_function (marudec->sinkpad,
+    GST_DEBUG_FUNCPTR(gst_marudec_setcaps));
+  gst_pad_set_event_function (marudec->sinkpad,
+    GST_DEBUG_FUNCPTR(gst_marudec_sink_event));
+  gst_pad_set_chain_function (marudec->sinkpad,
+    GST_DEBUG_FUNCPTR(gst_marudec_chain));
+
+  marudec->srcpad = gst_pad_new_from_template (oclass->srctempl, "src") ;
+  gst_pad_use_fixed_caps (marudec->srcpad);
+  gst_pad_set_event_function (marudec->srcpad,
+    GST_DEBUG_FUNCPTR(gst_marudec_src_event));
+
+  gst_element_add_pad (GST_ELEMENT(marudec), marudec->sinkpad);
+  gst_element_add_pad (GST_ELEMENT(marudec), marudec->srcpad);
+
+  marudec->context = g_malloc0 (sizeof(CodecContext));
+  marudec->context->video.pix_fmt = PIX_FMT_NONE;
+  marudec->context->audio.sample_fmt = SAMPLE_FMT_NONE;
+
+  marudec->opened = FALSE;
+  marudec->format.video.par_n = -1;
+  marudec->format.video.fps_n = -1;
+  marudec->format.video.old_fps_n = -1;
+
+  marudec->queued = NULL;
+  gst_segment_init (&marudec->segment, GST_FORMAT_TIME);
+
+  marudec->dev = g_malloc0 (sizeof(CodecDevice));
+  if (!marudec->dev) {
+    CODEC_LOG (ERR, "failed to allocate memory.\n");
+  }
+}
+
+static void
+gst_marudec_finalize (GObject *object)
+{
+  GstEmulDec *marudec = (GstEmulDec *) object;
+
+  if (marudec->context) {
+    g_free (marudec->context);
+    marudec->context = NULL;
+  }
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+gst_marudec_src_event (GstPad *pad, GstEvent *event)
+{
+  GstEmulDec *marudec;
+  gboolean res;
+
+  marudec = (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;
+
+    gst_event_parse_qos (event, &proportion, &diff, &timestamp);
+
+    /* update our QoS values */
+    gst_marudec_update_qos (marudec, proportion, timestamp + diff);
+    break;
+  }
+  default:
+    break;
+  }
+
+  /* forward upstream */
+  res = gst_pad_push_event (marudec->sinkpad, event);
+
+  gst_object_unref (marudec);
+
+  return res;
+}
+
+static gboolean
+gst_marudec_sink_event (GstPad *pad, GstEvent *event)
+{
+  GstEmulDec *marudec;
+  gboolean ret = FALSE;
+
+  marudec = (GstEmulDec *) gst_pad_get_parent (pad);
+
+  GST_DEBUG_OBJECT (marudec, "Handling %s event",
+    GST_EVENT_TYPE_NAME (event));
+
+  switch (GST_EVENT_TYPE (event)) {
+  case GST_EVENT_EOS:
+    gst_marudec_drain (marudec);
+    break;
+  case GST_EVENT_FLUSH_STOP:
+  {
+#if 0
+    if (marudec->opened) {
+        // TODO: what does avcodec_flush_buffers do?
+        maru_avcodec_flush_buffers (marudec->context, marudec->dev);
+    }
+#endif
+    gst_marudec_reset_ts (marudec);
+    gst_marudec_reset_qos (marudec);
+#if 0
+    gst_marudec_flush_pcache (marudec);
+    marudec->waiting_for_key = TRUE;
+#endif
+    gst_segment_init (&marudec->segment, GST_FORMAT_TIME);
+    clear_queued (marudec);
+  }
+    break;
+  case GST_EVENT_NEWSEGMENT:
+  {
+    gboolean update;
+    GstFormat format;
+    gint64 start, stop, time;
+    gdouble rate, arate;
+
+    gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
+        &start, &stop, &time);
+
+    switch (format) {
+    case GST_FORMAT_TIME:
+      break;
+    case GST_FORMAT_BYTES:
+    {
+      gint bit_rate;
+      bit_rate = marudec->context->bit_rate;
+
+      if (!bit_rate) {
+        GST_WARNING_OBJECT (marudec, "no bitrate to convert BYTES to TIME");
+        gst_event_unref (event);
+        gst_object_unref (marudec);
+        return ret;
+      }
+
+      GST_DEBUG_OBJECT (marudec, "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:
+      GST_WARNING_OBJECT (marudec, "unknown format received in NEWSEGMENT");
+      gst_event_unref (event);
+      gst_object_unref (marudec);
+      return ret;
+    }
+
+    if (marudec->context->codec) {
+      gst_marudec_drain (marudec);
+    }
+
+    GST_DEBUG_OBJECT (marudec,
+      "NEWSEGMENT in time start %" GST_TIME_FORMAT " -- stop %"
+      GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
+
+    gst_segment_set_newsegment_full (&marudec->segment, update,
+        rate, arate, format, start, stop, time);
+    break;
+  }
+  default:
+    break;
+  }
+
+  ret = gst_pad_push_event (marudec->srcpad, event);
+
+  gst_object_unref (marudec);
+
+  return ret;
+}
+
+
+
+static gboolean
+gst_marudec_setcaps (GstPad *pad, GstCaps *caps)
+{
+  GstEmulDec *marudec;
+  GstEmulDecClass *oclass;
+  GstStructure *structure;
+  const GValue *par;
+  const GValue *fps;
+  gboolean ret = TRUE;
+
+  GST_DEBUG_OBJECT (pad, "setcaps called.");
+
+  marudec = (GstEmulDec *) (gst_pad_get_parent (pad));
+  oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (marudec));
+
+  GST_OBJECT_LOCK (marudec);
+
+  if (marudec->opened) {
+    GST_OBJECT_UNLOCK (marudec);
+    gst_marudec_drain (marudec);
+    GST_OBJECT_LOCK (marudec);
+    gst_marudec_close (marudec);
+  }
+
+  GST_LOG_OBJECT (marudec, "size %dx%d", marudec->context->video.width,
+      marudec->context->video.height);
+
+  if (!strcmp(oclass->codec->name, "wmv3") ||
+      !strcmp(oclass->codec->name, "vc1")) {
+    gst_maru_caps_to_codecname (caps, oclass->codec->name, NULL);
+  }
+
+  gst_maru_caps_with_codecname (oclass->codec->name, oclass->codec->media_type,
+                                caps, marudec->context);
+
+  GST_LOG_OBJECT (marudec, "size after %dx%d", marudec->context->video.width,
+      marudec->context->video.height);
+
+  if (!marudec->context->video.fps_d || !marudec->context->video.fps_n) {
+    GST_DEBUG_OBJECT (marudec, "forcing 25/1 framerate");
+    marudec->context->video.fps_n = 1;
+    marudec->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 (marudec, "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 (marudec->par) {
+      g_free(marudec->par);
+    }
+    marudec->par = g_new0 (GValue, 1);
+    gst_value_init_and_copy (marudec->par, par);
+#endif
+  }
+
+  fps = gst_structure_get_value (structure, "framerate");
+  if (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps)) {
+    marudec->format.video.fps_n = gst_value_get_fraction_numerator (fps);
+    marudec->format.video.fps_d = gst_value_get_fraction_denominator (fps);
+    GST_DEBUG_OBJECT (marudec, "Using framerate %d/%d from incoming",
+        marudec->format.video.fps_n, marudec->format.video.fps_d);
+  } else {
+    marudec->format.video.fps_n = -1;
+    GST_DEBUG_OBJECT (marudec, "Using framerate from codec");
+  }
+
+#if 0
+  if (strcmp (oclass->codec->name, "aac") == 0) {
+    const gchar *format = gst_structure_get_string (structure, "stream-format");
+    if (format == NULL || strcmp ("format", "raw") == 0) {
+      marudec->turnoff_parser = TRUE;
+    }
+  }
+#endif
+
+  if (!gst_marudec_open (marudec)) {
+    GST_DEBUG_OBJECT (marudec, "Failed to open");
+#if 0
+    if (marudec->par) {
+      g_free(marudec->par);
+      marudec->par = NULL;
+    }
+#endif
+    GST_OBJECT_UNLOCK (marudec);
+    gst_object_unref (marudec);
+
+    return FALSE;
+  }
+
+  gst_structure_get_int (structure, "width",
+    &marudec->format.video.clip_width);
+  gst_structure_get_int (structure, "height",
+    &marudec->format.video.clip_height);
+
+  GST_DEBUG_OBJECT (pad, "clipping to %dx%d",
+    marudec->format.video.clip_width, marudec->format.video.clip_height);
+
+  GST_OBJECT_UNLOCK (marudec);
+  gst_object_unref (marudec);
+
+  return ret;
+}
+
+static gboolean
+gst_marudec_open (GstEmulDec *marudec)
+{
+  GstEmulDecClass *oclass;
+
+  oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (marudec));
+
+  if (!marudec->dev) {
+    return FALSE;
+  }
+
+  if (gst_maru_avcodec_open (marudec->context,
+                            oclass->codec, marudec->dev) < 0) {
+    gst_marudec_close (marudec);
+    GST_ERROR_OBJECT (marudec,
+      "maru_%sdec: Failed to open codec", oclass->codec->name);
+    return FALSE;
+  }
+
+  marudec->opened = TRUE;
+  GST_LOG_OBJECT (marudec, "Opened codec %s", oclass->codec->name);
+
+  switch (oclass->codec->media_type) {
+  case AVMEDIA_TYPE_VIDEO:
+    marudec->format.video.width = 0;
+    marudec->format.video.height = 0;
+    marudec->format.video.clip_width = -1;
+    marudec->format.video.clip_height = -1;
+    marudec->format.video.pix_fmt = PIX_FMT_NB;
+    marudec->format.video.interlaced = FALSE;
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+    marudec->format.audio.samplerate = 0;
+    marudec->format.audio.channels = 0;
+    marudec->format.audio.depth = 0;
+    break;
+  default:
+    break;
+  }
+
+  gst_marudec_reset_ts (marudec);
+
+  marudec->proportion = 0.0;
+  marudec->earliest_time = -1;
+
+  return TRUE;
+}
+
+static int
+gst_marudec_close (GstEmulDec *marudec)
+{
+  int ret = 0;
+
+  if (marudec->context->codecdata) {
+    g_free(marudec->context->codecdata);
+    marudec->context->codecdata = NULL;
+  }
+
+  if (!marudec->dev) {
+    return -1;
+  }
+
+  ret = gst_maru_avcodec_close (marudec->context, marudec->dev);
+
+  if (marudec->dev) {
+    g_free(marudec->dev);
+    marudec->dev = NULL;
+  }
+
+  return ret;
+}
+
+
+static gboolean
+gst_marudec_negotiate (GstEmulDec *marudec, gboolean force)
+{
+  GstEmulDecClass *oclass;
+  GstCaps *caps;
+
+  oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (marudec));
+
+  switch (oclass->codec->media_type) {
+  case AVMEDIA_TYPE_VIDEO:
+    if (!force && marudec->format.video.width == marudec->context->video.width
+      && marudec->format.video.height == marudec->context->video.height
+      && marudec->format.video.fps_n == marudec->format.video.old_fps_n
+      && marudec->format.video.fps_d == marudec->format.video.old_fps_d
+      && marudec->format.video.pix_fmt == marudec->context->video.pix_fmt
+      && marudec->format.video.par_n == marudec->context->video.par_n
+      && marudec->format.video.par_d == marudec->context->video.par_d) {
+      return TRUE;
+    }
+    marudec->format.video.width = marudec->context->video.width;
+    marudec->format.video.height = marudec->context->video.height;
+    marudec->format.video.old_fps_n = marudec->format.video.fps_n;
+    marudec->format.video.old_fps_d = marudec->format.video.fps_d;
+    marudec->format.video.pix_fmt = marudec->context->video.pix_fmt;
+    marudec->format.video.par_n = marudec->context->video.par_n;
+    marudec->format.video.par_d = marudec->context->video.par_d;
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+  {
+    gint depth = gst_maru_smpfmt_depth (marudec->context->audio.sample_fmt);
+    if (!force && marudec->format.audio.samplerate ==
+      marudec->context->audio.sample_rate &&
+      marudec->format.audio.channels == marudec->context->audio.channels &&
+      marudec->format.audio.depth == depth) {
+      return TRUE;
+    }
+    marudec->format.audio.samplerate = marudec->context->audio.sample_rate;
+    marudec->format.audio.channels = marudec->context->audio.channels;
+    marudec->format.audio.depth = depth;
+  }
+    break;
+  default:
+    break;
+  }
+
+  caps =
+    gst_maru_codectype_to_caps (oclass->codec->media_type, marudec->context,
+      oclass->codec->name, FALSE);
+
+  if (caps == NULL) {
+    GST_ELEMENT_ERROR (marudec, 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 = marudec->format.video.clip_width;
+    height = marudec->format.video.clip_height;
+    interlaced = marudec->format.video.interlaced;
+
+    if (width != -1 && height != -1) {
+      if (width < marudec->context->video.width) {
+        gst_caps_set_simple (caps, "width", G_TYPE_INT, width, NULL);
+      }
+      if (height < marudec->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 (marudec->format.video.fps_n != -1) {
+          gst_caps_set_simple (caps, "framerate",
+            GST_TYPE_FRACTION, marudec->format.video.fps_n,
+            marudec->format.video.fps_d, NULL);
+      }
+#if 0
+      gst_marudec_add_pixel_aspect_ratio (marudec,
+        gst_caps_get_structure (caps, 0));
+#endif
+    }
+  }
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+    break;
+  default:
+    break;
+  }
+
+  if (!gst_pad_set_caps (marudec->srcpad, caps)) {
+    GST_ELEMENT_ERROR (marudec, 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 GstFlowReturn
+get_output_buffer (GstEmulDec *marudec, GstBuffer **outbuf)
+{
+  gint pict_size;
+  GstFlowReturn ret;
+
+  ret = GST_FLOW_OK;
+
+  *outbuf = NULL;
+
+  if (G_UNLIKELY (!gst_marudec_negotiate (marudec, FALSE))) {
+    GST_DEBUG_OBJECT (marudec, "negotiate failed");
+    return GST_FLOW_NOT_NEGOTIATED;
+  }
+
+  pict_size = gst_maru_avpicture_size (marudec->context->video.pix_fmt,
+    marudec->context->video.width, marudec->context->video.height);
+  if (pict_size < 0) {
+    GST_DEBUG_OBJECT (marudec, "size of a picture is negative. "
+      "pixel format: %d, width: %d, height: %d",
+      marudec->context->video.pix_fmt, marudec->context->video.width,
+      marudec->context->video.height);
+    return GST_FLOW_ERROR;
+  }
+
+       CODEC_LOG (DEBUG, "outbuf size of decoded video: %d\n", pict_size);
+
+       if (pict_size < (256 * 1024)) {
+  /* GstPadBufferAllocFunction is mostly overridden by elements that can
+   * provide a hardware buffer in order to avoid additional memcpy operations.
+   */
+    gst_pad_set_bufferalloc_function(
+      GST_PAD_PEER(marudec->srcpad),
+      (GstPadBufferAllocFunction) codec_buffer_alloc);
+       } else {
+    CODEC_LOG (DEBUG, "request a large size of memory\n");
+       }
+
+  ret = gst_pad_alloc_buffer_and_set_caps (marudec->srcpad,
+    GST_BUFFER_OFFSET_NONE, pict_size,
+    GST_PAD_CAPS (marudec->srcpad), outbuf);
+  if (G_UNLIKELY (ret != GST_FLOW_OK)) {
+    GST_DEBUG_OBJECT (marudec, "pad_alloc failed %d (%s)", ret,
+      gst_flow_get_name (ret));
+    return ret;
+  }
+
+  if ((uintptr_t) GST_BUFFER_DATA (*outbuf) % 16) {
+    GST_DEBUG_OBJECT (marudec,
+      "Downstream can't allocate aligned buffers.");
+    gst_buffer_unref (*outbuf);
+    *outbuf = new_aligned_buffer (pict_size, GST_PAD_CAPS (marudec->srcpad));
+  }
+
+  codec_picture_copy (marudec->context, GST_BUFFER_DATA (*outbuf),
+    GST_BUFFER_SIZE (*outbuf), marudec->dev);
+
+  return ret;
+}
+
+static gboolean
+clip_video_buffer (GstEmulDec *dec, GstBuffer *buf,
+    GstClockTime in_ts, GstClockTime in_dur)
+{
+  gboolean res = TRUE;
+
+  return res;
+}
+
+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_marudec_video_frame (GstEmulDec *marudec, guint8 *data, guint size,
+    const GstTSInfo *dec_info, gint64 in_offset, GstBuffer **outbuf,
+    GstFlowReturn *ret)
+{
+  gint len = -1, have_data;
+  gboolean mode_switch;
+  gboolean decode;
+  GstClockTime out_timestamp, out_duration, out_pts;
+  gint64 out_offset;
+  const GstTSInfo *out_info;
+
+  decode = gst_marudec_do_qos (marudec, dec_info->timestamp, &mode_switch);
+
+  CODEC_LOG (DEBUG, "decode video: input buffer size: %d\n", size);
+  len =
+    codec_decode_video (marudec->context, data, size,
+                          dec_info->idx, in_offset, outbuf,
+                          &have_data, marudec->dev);
+
+  if (!decode) {
+    // skip_frame
+  }
+
+  GST_DEBUG_OBJECT (marudec, "after decode: len %d, have_data %d",
+    len, have_data);
+
+#if 0
+  if (len < 0 && (mode_switch || marudec->context->skip_frame)) {
+    len = 0;
+  }
+
+  if (len > 0 && have_data <= 0 && (mode_switch
+      || marudec->context->skip_frame)) {
+    marudec->last_out = -1;
+  }
+#endif
+
+  if (len < 0 || have_data <= 0) {
+    GST_DEBUG_OBJECT (marudec, "return flow %d, out %p, len %d",
+      *ret, *outbuf, len);
+    return len;
+  }
+
+  out_info = gst_ts_info_get (marudec, dec_info->idx);
+  out_pts = out_info->timestamp;
+  out_duration = out_info->duration;
+  out_offset = out_info->offset;
+
+  *ret = get_output_buffer (marudec, outbuf);
+  if (G_UNLIKELY (*ret != GST_FLOW_OK)) {
+    GST_DEBUG_OBJECT (marudec, "no output buffer");
+    len = -1;
+    GST_DEBUG_OBJECT (marudec, "return flow %d, out %p, len %d",
+      *ret, *outbuf, len);
+    return len;
+  }
+
+  /* Timestamps */
+  out_timestamp = -1;
+  if (out_pts != -1) {
+    out_timestamp = (GstClockTime) out_pts;
+    GST_LOG_OBJECT (marudec, "using timestamp %" GST_TIME_FORMAT
+      " returned by ffmpeg", GST_TIME_ARGS (out_timestamp));
+  }
+
+  if (!GST_CLOCK_TIME_IS_VALID (out_timestamp) && marudec->next_out != -1) {
+    out_timestamp = marudec->next_out;
+    GST_LOG_OBJECT (marudec, "using next timestamp %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (out_timestamp));
+  }
+
+  if (!GST_CLOCK_TIME_IS_VALID (out_timestamp)) {
+    out_timestamp = dec_info->timestamp;
+    GST_LOG_OBJECT (marudec, "using in timestamp %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (out_timestamp));
+  }
+  GST_BUFFER_TIMESTAMP (*outbuf) = out_timestamp;
+
+  /* Offset */
+  if (out_offset != GST_BUFFER_OFFSET_NONE) {
+    GST_LOG_OBJECT (marudec, "Using offset returned by ffmpeg");
+  } else if (out_timestamp != GST_CLOCK_TIME_NONE) {
+    GstFormat out_fmt = GST_FORMAT_DEFAULT;
+    GST_LOG_OBJECT (marudec, "Using offset converted from timestamp");
+
+    gst_pad_query_peer_convert (marudec->sinkpad,
+      GST_FORMAT_TIME, out_timestamp, &out_fmt, &out_offset);
+  } else if (dec_info->offset != GST_BUFFER_OFFSET_NONE) {
+    GST_LOG_OBJECT (marudec, "using in_offset %" G_GINT64_FORMAT,
+      dec_info->offset);
+    out_offset = dec_info->offset;
+  } else {
+    GST_LOG_OBJECT (marudec, "no valid offset found");
+    out_offset = GST_BUFFER_OFFSET_NONE;
+  }
+  GST_BUFFER_OFFSET (*outbuf) = out_offset;
+
+  /* Duration */
+  if (GST_CLOCK_TIME_IS_VALID (out_duration)) {
+    GST_LOG_OBJECT (marudec, "Using duration returned by ffmpeg");
+  } else if (GST_CLOCK_TIME_IS_VALID (dec_info->duration)) {
+    GST_LOG_OBJECT (marudec, "Using in_duration");
+    out_duration = dec_info->duration;
+#if 0
+  } else if (GST_CLOCK_TIME_IS_VALID (marudec->last_diff)) {
+    GST_LOG_OBJECT (marudec, "Using last-diff");
+    out_duration = marudec->last_diff;
+#endif
+  } else {
+    if (marudec->format.video.fps_n != -1 &&
+        (marudec->format.video.fps_n != 1000 &&
+        marudec->format.video.fps_d != 1)) {
+      GST_LOG_OBJECT (marudec, "using input framerate for duration");
+      out_duration = gst_util_uint64_scale_int (GST_SECOND,
+        marudec->format.video.fps_d, marudec->format.video.fps_n);
+    } else {
+      if (marudec->context->video.fps_n != 0 &&
+          (marudec->context->video.fps_d > 0 &&
+            marudec->context->video.fps_d < 1000)) {
+        GST_LOG_OBJECT (marudec, "using decoder's framerate for duration");
+        out_duration = gst_util_uint64_scale_int (GST_SECOND,
+          marudec->context->video.fps_n * 1,
+          marudec->context->video.fps_d);
+      } else {
+        GST_LOG_OBJECT (marudec, "no valid duration found");
+      }
+    }
+  }
+
+#if 0
+  if (GST_CLOCK_TIME_IS_VALID (out_duration)) {
+    out_duration += out_duration * marudec->picture->repeat_pict / 2;
+  }
+  GST_BUFFER_DURATION (*outbuf) = out_duration;
+
+  if (out_timestamp != -1 && out_duration != -1 && out_duration != 0) {
+    marudec->next_out = out_timestamp + out_duration;
+  } else {
+    marudec->next_out = -1;
+  }
+#endif
+
+  if (G_UNLIKELY (!clip_video_buffer (marudec, *outbuf, out_timestamp,
+      out_duration))) {
+    GST_DEBUG_OBJECT (marudec, "buffer clipped");
+    gst_buffer_unref (*outbuf);
+    *outbuf = NULL;
+    GST_DEBUG_OBJECT (marudec, "return flow %d, out %p, len %d",
+      *ret, *outbuf, len);
+    return len;
+  }
+
+  GST_DEBUG_OBJECT (marudec, "return flow %d, out %p, len %d",
+    *ret, *outbuf, len);
+  return len;
+}
+
+static gint
+gst_marudec_audio_frame (GstEmulDec *marudec, 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 (marudec->srcpad));
+
+  CODEC_LOG (DEBUG, "decode audio, input buffer size: %d\n", size);
+
+  len = codec_decode_audio (marudec->context,
+      (int16_t *) GST_BUFFER_DATA (*outbuf), &have_data,
+      data, size, marudec->dev);
+
+  GST_DEBUG_OBJECT (marudec,
+    "Decode audio: len=%d, have_data=%d", len, have_data);
+
+  if (len >= 0 && have_data > 0) {
+    GST_DEBUG_OBJECT (marudec, "Creating output buffer");
+    if (!gst_marudec_negotiate (marudec, FALSE)) {
+      gst_buffer_unref (*outbuf);
+      *outbuf = NULL;
+      len = -1;
+      GST_DEBUG_OBJECT (marudec, "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 = marudec->next_out;
+    }
+
+    /* calculate based on number of samples */
+    out_duration = gst_util_uint64_scale (have_data, GST_SECOND,
+        marudec->format.audio.depth * marudec->format.audio.channels *
+        marudec->format.audio.samplerate);
+
+    out_offset = dec_info->offset;
+
+    GST_DEBUG_OBJECT (marudec,
+        "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 (marudec->srcpad));
+
+    if (GST_CLOCK_TIME_IS_VALID (out_timestamp)) {
+      marudec->next_out = out_timestamp + out_duration;
+    }
+
+    if (G_UNLIKELY (!clip_audio_buffer (marudec, *outbuf,
+        out_timestamp, out_duration))) {
+      GST_DEBUG_OBJECT (marudec, "buffer_clipped");
+      gst_buffer_unref (*outbuf);
+      *outbuf = NULL;
+      GST_DEBUG_OBJECT (marudec, "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 (marudec, STREAM, DECODE, (NULL),
+        ("Decoding of AAC stream by FFMPEG failed."));
+    *ret = GST_FLOW_ERROR;
+  }
+
+  GST_DEBUG_OBJECT (marudec, "return flow %d, out %p, len %d",
+    *ret, *outbuf, len);
+  return len;
+}
+
+static gint
+gst_marudec_frame (GstEmulDec *marudec, guint8 *data, guint size,
+    gint *got_data, const GstTSInfo *dec_info, gint64 in_offset, GstFlowReturn *ret)
+{
+  GstEmulDecClass *oclass;
+  GstBuffer *outbuf = NULL;
+  gint have_data = 0, len = 0;
+
+  if (G_UNLIKELY (marudec->context->codec == NULL)) {
+    GST_ERROR_OBJECT (marudec, "no codec context");
+    return -1;
+  }
+
+  *ret = GST_FLOW_OK;
+  oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (marudec));
+
+  switch (oclass->codec->media_type) {
+  case AVMEDIA_TYPE_VIDEO:
+    len = gst_marudec_video_frame (marudec, data, size,
+        dec_info, in_offset, &outbuf, ret);
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+    len = gst_marudec_audio_frame (marudec, oclass->codec, data, size,
+        dec_info, &outbuf, ret);
+    if (outbuf == NULL && marudec->discont) {
+      GST_DEBUG_OBJECT (marudec, "no buffer but keeping timestamp");
+//      marudec->clear_ts = FALSE;
+    }
+    break;
+  default:
+    GST_ERROR_OBJECT (marudec, "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 (marudec,
+        "maru_%sdec: 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 (marudec,
+        "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 (marudec->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);
+      marudec->discont = FALSE;
+    }
+
+    if (marudec->segment.rate > 0.0) {
+      // push forward
+      *ret = gst_pad_push (marudec->srcpad, outbuf);
+    } else {
+      // push reverse
+      GST_DEBUG_OBJECT (marudec, "queued frame");
+      marudec->queued = g_list_prepend (marudec->queued, outbuf);
+      *ret = GST_FLOW_OK;
+    }
+  } else {
+    GST_DEBUG_OBJECT (marudec, "Didn't get a decoded buffer");
+  }
+
+  return len;
+}
+
+static GstFlowReturn
+gst_marudec_chain (GstPad *pad, GstBuffer *buffer)
+{
+  GstEmulDec *marudec;
+  GstEmulDecClass *oclass;
+  guint8 *in_buf;
+  gint 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;
+
+  marudec = (GstEmulDec *) (GST_PAD_PARENT (pad));
+
+  if (G_UNLIKELY (!marudec->opened)) {
+    // not_negotiated
+    oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (marudec));
+    GST_ELEMENT_ERROR (marudec, CORE, NEGOTIATION, (NULL),
+      ("maru_%sdec: input format was not set before data start",
+        oclass->codec->name));
+    gst_buffer_unref (buffer);
+    return GST_FLOW_NOT_NEGOTIATED;
+  }
+
+  discont = GST_BUFFER_IS_DISCONT (buffer);
+
+// FIXME
+  if (G_UNLIKELY (discont)) {
+    GST_DEBUG_OBJECT (marudec, "received DISCONT");
+    gst_marudec_drain (marudec);
+//    gst_marudec_flush_pcache (marudec);
+//    maru_avcodec_flush buffers (marudec->context, marudec->dev);
+    marudec->discont = TRUE;
+    gst_marudec_reset_ts (marudec);
+  }
+//  marudec->clear_ts = TRUE;
+
+  oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (marudec));
+#if 0
+  if (G_UNLIKELY (marudec->waiting_for_key)) {
+    if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT) &&
+      oclass->codec->media_type != AVMEDIA_TYPE_AUDIO) {
+      // skip_keyframe
+    }
+    marudec->waiting_for_key = FALSE;
+  }
+
+  if (marudec->pcache) {
+    GST_LOG_OBJECT (marudec, "join parse cache");
+    buffer = gst_buffer_join (marudec->pcache, buffer);
+    marudec->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 (marudec, in_timestamp, in_duration, in_offset);
+
+#if 0
+  if (in_timestamp != -1) {
+    if (!marudec->reordered_in && marudec->last_in != -1) {
+      if (in_timestamp < marudec->last_in) {
+        GST_LOG_OBJECT (marudec, "detected reordered input timestamps");
+        marudec->reordered_in = TRUE;
+        marudec->last_diff = GST_CLOCK_TIME_NONE;
+      } else if (in_timestamp > marudec->last_in) {
+        GstClockTime diff;
+        diff = in_timestamp - marudec->last_in;
+        if (marudec->last_frames) {
+          diff /= marudec->last_frames;
+        }
+
+        GST_LOG_OBJECT (marudec, "estimated duration %" GST_TIME_FORMAT " %u",
+          GST_TIME_ARGS (diff), marudec->last_frames);
+
+        marudec->last_diff = diff;
+      }
+    }
+    marudec->last_in = in_timestamp;
+    marudec->last_frames;
+  }
+#endif
+
+  GST_LOG_OBJECT (marudec,
+    "Received new data of size %u, offset: %" G_GUINT64_FORMAT ", ts:%"
+    GST_TIME_FORMAT ", dur: %" GST_TIME_FORMAT ", info %d",
+    GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer),
+    GST_TIME_ARGS (in_timestamp), GST_TIME_ARGS (in_duration), in_info->idx);
+
+  in_buf = GST_BUFFER_DATA (buffer);
+  in_size = GST_BUFFER_SIZE (buffer);
+
+  dec_info = in_info;
+
+  len =
+    gst_marudec_frame (marudec, in_buf, in_size, &have_data, dec_info, in_offset, &ret);
+
+#if 0
+  if (marudec->clear_ts) {
+    in_timestamp = GST_CLOCK_TIME_NONE;
+    in_duration = GST_CLOCK_TIME_NONE;
+    in_offset = GST_BUFFER_OFFSET_NONE;
+    in_info = GST_TS_INFO_NONE;
+  } else {
+    marudec->clear_ts = TRUE;
+  }
+#endif
+
+  gst_buffer_unref (buffer);
+
+  return ret;
+}
+
+static GstStateChangeReturn
+gst_marudec_change_state (GstElement *element, GstStateChange transition)
+{
+  GstEmulDec *marudec = (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 (marudec);
+    gst_marudec_close (marudec);
+    GST_OBJECT_UNLOCK (marudec);
+
+    /* clear queue */
+    clear_queued (marudec);
+    break;
+  default:
+    break;
+  }
+
+  return ret;
+}
+
+gboolean
+gst_marudec_register (GstPlugin *plugin, GList *element)
+{
+  GTypeInfo typeinfo = {
+      sizeof (GstEmulDecClass),
+      (GBaseInitFunc) gst_marudec_base_init,
+      NULL,
+      (GClassInitFunc) gst_marudec_class_init,
+      NULL,
+      NULL,
+      sizeof (GstEmulDec),
+      0,
+      (GInstanceInitFunc) gst_marudec_init,
+  };
+
+  GType type;
+  gchar *type_name;
+  gint rank = GST_RANK_PRIMARY;
+  GList *elem = element;
+  CodecElement *codec = NULL;
+
+  if (!elem) {
+    return FALSE;
+  }
+
+  /* register element */
+  do {
+    codec = (CodecElement *)(elem->data);
+    if (!codec) {
+      return FALSE;
+    }
+
+    if (codec->codec_type != CODEC_TYPE_DECODE) {
+      continue;
+    }
+
+    type_name = g_strdup_printf ("maru_%sdec", 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_MARUDEC_PARAMS_QDATA, (gpointer) codec);
+    }
+
+    if (!gst_element_register (plugin, type_name, rank, type)) {
+      g_free (type_name);
+      return FALSE;
+    }
+    g_free (type_name);
+  } while ((elem = elem->next));
+
+  return TRUE;
+}
diff --git a/src/gstmarudevice.c b/src/gstmarudevice.c
new file mode 100644 (file)
index 0000000..3d0f6a4
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * 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 <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include "gstmaruinterface.h"
+#include "gstmarudevice.h"
+
+static GStaticMutex gst_avcodec_mutex = G_STATIC_MUTEX_INIT;
+
+#define CODEC_DEVICE_MEM_SIZE 32 * 1024 * 1024
+
+gpointer device_mem;
+int device_fd;
+
+int
+gst_maru_codec_device_open (CodecDevice *dev, int media_type)
+{
+  int fd;
+  void *mmapbuf;
+
+  CODEC_LOG (DEBUG, "enter: %s\n", __func__);
+
+  CODEC_LOG (INFO, "before opening a device. %d\n", dev->fd);
+  if ((fd = open(CODEC_DEV, O_RDWR)) < 0) {
+    perror("Failed to open codec device.");
+    return -1;
+  }
+  dev->fd = fd;
+
+//  GST_DEBUG("succeeded to open %s. %d.\n", CODEC_DEV, fd);
+  CODEC_LOG (INFO, "succeeded to open %s. %d.\n", CODEC_DEV, fd);
+  dev->mem_info.index = dev->buf_size;
+
+  CODEC_LOG (DEBUG, "before mmap. buf_size: %d\n", dev->buf_size);
+  mmapbuf = mmap (NULL, CODEC_DEVICE_MEM_SIZE, PROT_READ | PROT_WRITE,
+                  MAP_SHARED, fd, 0);
+  if (mmapbuf == MAP_FAILED) {
+    perror("Failed to map device memory of codec.");
+    dev->buf = NULL;
+    return -1;
+  }
+
+//  GST_DEBUG("succeeded to map device memory.\n");
+  CODEC_LOG (INFO, "succeeded to map device memory: %p.\n", mmapbuf);
+  dev->fd = fd;
+  dev->buf = mmapbuf;
+
+  if (media_type == AVMEDIA_TYPE_VIDEO) {
+    device_mem = mmapbuf;
+    device_fd = fd;
+    CODEC_LOG (INFO, "video type! mmapbuf: %p fd: %d\n", mmapbuf, fd);
+  }
+#if 0
+  else {
+    CODEC_LOG (INFO, "don't need to set device_mem because media type is not video. %d\n", media_type); 
+  }
+#endif
+
+  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
+
+  return 0;
+}
+
+int
+gst_maru_codec_device_close (CodecDevice *dev)
+{
+  int fd = 0;
+  void *mmapbuf = NULL;
+
+  CODEC_LOG (DEBUG, "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;
+  }
+
+  CODEC_LOG (INFO, "Release memory region of %p.\n", mmapbuf);
+  if (munmap(mmapbuf, CODEC_DEVICE_MEM_SIZE) != 0) {
+    CODEC_LOG(ERR, "Failed to release memory region of %s.\n", CODEC_DEV);
+  }
+  dev->buf = NULL;
+
+  ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &dev->mem_info.offset);
+
+  CODEC_LOG (INFO, "close %s.\n", CODEC_DEV);
+  if (close(fd) != 0) {
+    GST_ERROR("Failed to close %s. fd: %d\n", CODEC_DEV, fd);
+  }
+
+  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
+
+  return 0;
+}
+
+int
+gst_maru_avcodec_open (CodecContext *ctx,
+                      CodecElement *codec,
+                      CodecDevice *dev)
+{
+  int ret;
+
+  g_static_mutex_lock (&gst_avcodec_mutex);
+
+  if (gst_maru_codec_device_open (dev, codec->media_type) < 0) {
+    perror("failed to open device.\n");
+    return -1;
+  }
+  ret = codec_init (ctx, codec, dev);
+  g_static_mutex_unlock (&gst_avcodec_mutex);
+
+  return ret;
+}
+
+int
+gst_maru_avcodec_close (CodecContext *ctx, CodecDevice *dev)
+{
+  int ret;
+
+  g_static_mutex_lock (&gst_avcodec_mutex);
+
+  CODEC_LOG (DEBUG, "gst_maru_avcodec_close\n");
+  codec_deinit (ctx, dev);
+
+  ret = gst_maru_codec_device_close (dev);
+  g_static_mutex_unlock (&gst_avcodec_mutex);
+
+  return ret;
+}
diff --git a/src/gstmarudevice.h b/src/gstmarudevice.h
new file mode 100644 (file)
index 0000000..3603b30
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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_MARU_DEVICE_H__
+#define __GST_MARU_DEVICE_H__
+
+int gst_emul_codec_device_open (CodecDevice *dev, int media_type);
+int gst_emul_codec_device_close (CodecDevice *dev);
+
+int gst_emul_avcodec_open (CodecContext *ctx,
+                          CodecElement *codec,
+                          CodecDevice *dev);
+int gst_emul_avcodec_close (CodecContext *ctx, CodecDevice *dev);
+#endif
diff --git a/src/gstmaruenc.c b/src/gstmaruenc.c
new file mode 100644 (file)
index 0000000..1af5a9f
--- /dev/null
@@ -0,0 +1,1170 @@
+/*
+ * 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 "gstmaruutils.h"
+#include "gstmaruinterface.h"
+#include "gstmarudevice.h"
+#include <gst/base/gstadapter.h>
+
+#define GST_MARUENC_PARAMS_QDATA g_quark_from_static_string("maruenc-params")
+
+typedef struct _GstEmulEnc
+{
+  GstElement element;
+
+  GstPad *srcpad;
+  GstPad *sinkpad;
+
+  CodecContext *context;
+  CodecDevice *dev;
+  gboolean opened;
+  GstClockTime adapter_ts;
+  guint64 adapter_consumed;
+  GstAdapter *adapter;
+  gboolean discont;
+
+  // cache
+  gulong bitrate;
+  gint gop_size;
+  gulong buffer_size;
+
+  guint8 *working_buf;
+  gulong working_buf_size;
+
+  GQueue *delay;
+
+} GstEmulEnc;
+
+typedef struct _GstEmulEncClass
+{
+  GstElementClass parent_class;
+
+  CodecElement *codec;
+  GstPadTemplate *sinktempl;
+  GstPadTemplate *srctempl;
+  GstCaps *sinkcaps;
+} GstEmulEncClass;
+
+static GstElementClass *parent_class = NULL;
+
+static void gst_maruenc_base_init (GstEmulEncClass *klass);
+static void gst_maruenc_class_init (GstEmulEncClass *klass);
+static void gst_maruenc_init (GstEmulEnc *maruenc);
+static void gst_maruenc_finalize (GObject *object);
+
+static gboolean gst_maruenc_setcaps (GstPad *pad, GstCaps *caps);
+static GstCaps *gst_maruenc_getcaps (GstPad *pad);
+
+static GstCaps *gst_maruenc_get_possible_sizes (GstEmulEnc *maruenc,
+  GstPad *pad, const GstCaps *caps);
+
+static GstFlowReturn gst_maruenc_chain_video (GstPad *pad, GstBuffer *buffer);
+static GstFlowReturn gst_maruenc_chain_audio (GstPad *pad, GstBuffer *buffer);
+
+static gboolean gst_maruenc_event_video (GstPad *pad, GstEvent *event);
+static gboolean gst_maruenc_event_src (GstPad *pad, GstEvent *event);
+
+GstStateChangeReturn gst_maruenc_change_state (GstElement *element, GstStateChange transition);
+
+#define DEFAULT_VIDEO_BITRATE   300000
+#define DEFAULT_VIDEO_GOP_SIZE  15
+#define DEFAULT_AUDIO_BITRATE   128000
+
+#define DEFAULT_WIDTH 352
+#define DEFAULT_HEIGHT 288
+
+/*
+ * Implementation
+ */
+static void
+gst_maruenc_base_init (GstEmulEncClass *klass)
+{
+    GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+    GstPadTemplate *sinktempl = NULL, *srctempl = NULL;
+    GstCaps *sinkcaps = NULL, *srccaps = NULL;
+    CodecElement *codec;
+    gchar *longname, *classification, *description;
+
+    codec =
+        (CodecElement *)g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
+         GST_MARUENC_PARAMS_QDATA);
+
+    longname = g_strdup_printf ("%s Encoder", codec->longname);
+    classification = g_strdup_printf ("Codec/Encoder/%s",
+            (codec->media_type == AVMEDIA_TYPE_VIDEO) ? "Video" : "Audio");
+    description = g_strdup_printf ("%s Encoder", codec->name);
+
+    gst_element_class_set_details_simple (element_class,
+            longname,
+            classification,
+            description,
+//            "accelerated codec for Tizen Emulator",
+            "Kitae Kim <kt920.kim@samsung.com>");
+
+    g_free (longname);
+    g_free (classification);
+
+
+  if (!(srccaps = gst_maru_codecname_to_caps (codec->name, NULL, TRUE))) {
+    GST_DEBUG ("Couldn't get source caps for encoder '%s'", codec->name);
+    srccaps = gst_caps_new_simple ("unknown/unknown", NULL);
+  }
+
+  switch (codec->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:
+    sinkcaps = gst_maru_codectype_to_audio_caps (NULL, codec->name, TRUE, codec);
+    break;
+  default:
+    GST_LOG("unknown media type.\n");
+    break;
+  }
+
+  if (!sinkcaps) {
+      GST_DEBUG ("Couldn't get sink caps for encoder '%s'", 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->codec = codec;
+  klass->sinktempl = sinktempl;
+  klass->srctempl = srctempl;
+  klass->sinkcaps = NULL;
+}
+
+static void
+gst_maruenc_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_maruenc_set_property
+  gobject_class->get_property = gst_maruenc_get_property
+#endif
+
+  gstelement_class->change_state = gst_maruenc_change_state;
+
+  gobject_class->finalize = gst_maruenc_finalize;
+}
+
+static void
+gst_maruenc_init (GstEmulEnc *maruenc)
+{
+  GstEmulEncClass *oclass;
+  oclass = (GstEmulEncClass*) (G_OBJECT_GET_CLASS(maruenc));
+
+  maruenc->sinkpad = gst_pad_new_from_template (oclass->sinktempl, "sink");
+  gst_pad_set_setcaps_function (maruenc->sinkpad,
+    GST_DEBUG_FUNCPTR(gst_maruenc_setcaps));
+  gst_pad_set_getcaps_function (maruenc->sinkpad,
+    GST_DEBUG_FUNCPTR(gst_maruenc_getcaps));
+
+  maruenc->srcpad = gst_pad_new_from_template (oclass->srctempl, "src");
+  gst_pad_use_fixed_caps (maruenc->srcpad);
+
+  if (oclass->codec->media_type == AVMEDIA_TYPE_VIDEO) {
+    gst_pad_set_chain_function (maruenc->sinkpad, gst_maruenc_chain_video);
+    gst_pad_set_event_function (maruenc->sinkpad, gst_maruenc_event_video);
+    gst_pad_set_event_function (maruenc->srcpad, gst_maruenc_event_src);
+
+    maruenc->bitrate = DEFAULT_VIDEO_BITRATE;
+    maruenc->buffer_size = 512 * 1024;
+    maruenc->gop_size = DEFAULT_VIDEO_GOP_SIZE;
+#if 0
+    maruenc->lmin = 2;
+    maruenc->lmax = 31;
+#endif
+  } else if (oclass->codec->media_type == AVMEDIA_TYPE_AUDIO){
+    gst_pad_set_chain_function (maruenc->sinkpad, gst_maruenc_chain_audio);
+    maruenc->bitrate = DEFAULT_AUDIO_BITRATE;
+  }
+
+  gst_element_add_pad (GST_ELEMENT (maruenc), maruenc->sinkpad);
+  gst_element_add_pad (GST_ELEMENT (maruenc), maruenc->srcpad);
+
+  maruenc->context = g_malloc0 (sizeof(CodecContext));
+  maruenc->context->video.pix_fmt = PIX_FMT_NONE;
+  maruenc->context->audio.sample_fmt = SAMPLE_FMT_NONE;
+
+  maruenc->opened = FALSE;
+
+#if 0
+  maruenc->file = NULL;
+#endif
+  maruenc->delay = g_queue_new ();
+
+  maruenc->dev = g_malloc0 (sizeof(CodecDevice));
+  if (!maruenc->dev) {
+    printf("[gst-maru][%d] failed to allocate memory\n", __LINE__);
+  }
+
+  // need to know what adapter does.
+  maruenc->adapter = gst_adapter_new ();
+}
+
+static void
+gst_maruenc_finalize (GObject *object)
+{
+  // Deinit Decoder
+  GstEmulEnc *maruenc = (GstEmulEnc *) object;
+
+  if (maruenc->opened) {
+    gst_maru_avcodec_close (maruenc->context, maruenc->dev);
+    maruenc->opened = FALSE;
+  }
+
+  if (maruenc->context) {
+    g_free (maruenc->context);
+    maruenc->context = NULL;
+  }
+
+  g_queue_free (maruenc->delay);
+#if 0
+  g_free (maruenc->filename);
+#endif
+
+  g_object_unref (maruenc->adapter);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static GstCaps *
+gst_maruenc_get_possible_sizes (GstEmulEnc *maruenc, GstPad *pad,
+  const GstCaps *caps)
+{
+  GstCaps *othercaps = NULL;
+  GstCaps *tmpcaps = NULL;
+  GstCaps *intersect = NULL;
+  guint i;
+
+  othercaps = gst_pad_peer_get_caps (maruenc->srcpad);
+
+  if (!othercaps) {
+    return gst_caps_copy (caps);
+  }
+
+  intersect = gst_caps_intersect (othercaps,
+    gst_pad_get_pad_template_caps (maruenc->srcpad));
+  gst_caps_unref (othercaps);
+
+  if (gst_caps_is_empty (intersect)) {
+    return intersect;
+  }
+
+  if (gst_caps_is_any (intersect)) {
+    return gst_caps_copy (caps);
+  }
+
+  tmpcaps = gst_caps_new_empty ();
+
+  for (i = 0; i <gst_caps_get_size (intersect); i++) {
+    GstStructure *s = gst_caps_get_structure (intersect, i);
+    const GValue *height = NULL;
+    const GValue *width = NULL;
+    const GValue *framerate = NULL;
+    GstStructure *tmps;
+
+    height = gst_structure_get_value (s, "height");
+    width = gst_structure_get_value (s, "width");
+    framerate = gst_structure_get_value (s, "framerate");
+
+    tmps = gst_structure_new ("video/x-rwa-rgb", NULL);
+    if (width) {
+      gst_structure_set_value (tmps, "width", width);
+    }
+    if (height) {
+      gst_structure_set_value (tmps, "height", height);
+    }
+    if (framerate) {
+      gst_structure_set_value (tmps, "framerate", framerate);
+    }
+    gst_caps_merge_structure (tmpcaps, gst_structure_copy (tmps));
+
+    gst_structure_set_name (tmps, "video/x-raw-yuv");
+    gst_caps_merge_structure (tmpcaps, gst_structure_copy (tmps));
+
+    gst_structure_set_name (tmps, "video/x-raw-gray");
+    gst_caps_merge_structure (tmpcaps, tmps);
+  }
+  gst_caps_unref (intersect);
+
+  intersect = gst_caps_intersect (caps, tmpcaps);
+  gst_caps_unref (tmpcaps);
+
+  return intersect;
+}
+
+static GstCaps *
+gst_maruenc_getcaps (GstPad *pad)
+{
+  GstEmulEnc *maruenc = (GstEmulEnc *) GST_PAD_PARENT (pad);
+  GstEmulEncClass *oclass =
+    (GstEmulEncClass *) G_OBJECT_GET_CLASS (maruenc);
+  CodecContext *ctx = NULL;
+  enum PixelFormat pixfmt;
+  GstCaps *caps = NULL;
+  GstCaps *finalcaps = NULL;
+  gint i;
+
+  GST_DEBUG_OBJECT (maruenc, "getting caps");
+
+  if (!oclass->codec) {
+    GST_ERROR_OBJECT (maruenc, "codec element is null.");
+    return NULL;
+  }
+
+  if (oclass->codec->media_type == AVMEDIA_TYPE_AUDIO) {
+    caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
+
+    GST_DEBUG_OBJECT (maruenc, "audio caps, return template %" GST_PTR_FORMAT,
+      caps);
+    return caps;
+  }
+
+  // cached
+  if (oclass->sinkcaps) {
+    caps = gst_maruenc_get_possible_sizes (maruenc, pad, oclass->sinkcaps);
+    GST_DEBUG_OBJECT (maruenc, "return cached caps %" GST_PTR_FORMAT, caps);
+    return caps;
+  }
+
+  GST_DEBUG_OBJECT (maruenc, "probing caps");
+  i = pixfmt = 0;
+
+  for (pixfmt = 0;; pixfmt++) {
+    GstCaps *tmpcaps;
+
+    if ((pixfmt = oclass->codec->pix_fmts[i++]) == PIX_FMT_NONE) {
+      GST_DEBUG_OBJECT (maruenc,
+          "At the end of official pixfmt for this codec, breaking out");
+      break;
+    }
+
+    GST_DEBUG_OBJECT (maruenc,
+        "Got an official pixfmt [%d], attempting to get caps", pixfmt);
+    tmpcaps = gst_maru_pixfmt_to_caps (pixfmt, NULL, oclass->codec->name);
+    if (tmpcaps) {
+      GST_DEBUG_OBJECT (maruenc, "Got caps, breaking out");
+      if (!caps) {
+        caps = gst_caps_new_empty ();
+      }
+      gst_caps_append (caps, tmpcaps);
+      continue;
+    }
+
+    GST_DEBUG_OBJECT (maruenc,
+        "Couldn't figure out caps without context, trying again with a context");
+
+    GST_DEBUG_OBJECT (maruenc, "pixfmt: %d", pixfmt);
+    if (pixfmt >= PIX_FMT_NB) {
+      GST_WARNING ("Invalid pixfmt, breaking out");
+      break;
+    }
+
+    ctx = g_malloc0 (sizeof(CodecContext));
+    if (!ctx) {
+      GST_DEBUG_OBJECT (maruenc, "no context");
+      break;
+    }
+
+    ctx->video.width = DEFAULT_WIDTH;
+    ctx->video.height = DEFAULT_HEIGHT;
+    ctx->video.fps_n = 1;
+    ctx->video.fps_d = 25;
+    ctx->video.ticks_per_frame = 1;
+    ctx->bit_rate = DEFAULT_VIDEO_BITRATE;
+
+//  ctx->strict_std_compliance = -1;
+    ctx->video.pix_fmt = pixfmt;
+
+    GST_DEBUG ("Attempting to open codec");
+    if (gst_maru_avcodec_open (ctx, oclass->codec, maruenc->dev) >= 0
+        && ctx->video.pix_fmt == pixfmt) {
+      ctx->video.width = -1;
+      if (!caps) {
+        caps = gst_caps_new_empty ();
+      }
+      tmpcaps = gst_maru_codectype_to_caps (oclass->codec->media_type, ctx,
+          oclass->codec->name, TRUE);
+      if (tmpcaps) {
+        gst_caps_append (caps, tmpcaps);
+      } else {
+        GST_LOG_OBJECT (maruenc,
+            "Couldn't get caps for codec: %s", oclass->codec->name);
+      }
+      gst_maru_avcodec_close (ctx, maruenc->dev);
+    } else {
+      GST_DEBUG_OBJECT (maruenc, "Opening codec failed with pixfmt: %d", pixfmt);
+    }
+
+    gst_maru_avcodec_close (ctx, maruenc->dev);
+#if 0
+    if (ctx->priv_data) {
+      gst_maru_avcodec_close (ctx, maruenc->dev);
+    }
+#endif
+    g_free (ctx);
+  }
+
+  if (!caps) {
+    caps = gst_maruenc_get_possible_sizes (maruenc, pad,
+      gst_pad_get_pad_template_caps (pad));
+    GST_DEBUG_OBJECT (maruenc, "probing gave nothing, "
+      "return template %" GST_PTR_FORMAT, caps);
+    return caps;
+  }
+
+  GST_DEBUG_OBJECT (maruenc, "probed caps gave %" GST_PTR_FORMAT, caps);
+  oclass->sinkcaps = gst_caps_copy (caps);
+
+  finalcaps = gst_maruenc_get_possible_sizes (maruenc, pad, caps);
+  gst_caps_unref (caps);
+
+  return finalcaps;
+}
+
+static gboolean
+gst_maruenc_setcaps (GstPad *pad, GstCaps *caps)
+{
+  GstEmulEnc *maruenc;
+  GstEmulEncClass *oclass;
+  GstCaps *other_caps;
+  GstCaps *allowed_caps;
+  GstCaps *icaps;
+  enum PixelFormat pix_fmt;
+  int32_t buf_size;
+
+  maruenc = (GstEmulEnc *) (gst_pad_get_parent (pad));
+  oclass = (GstEmulEncClass *) (G_OBJECT_GET_CLASS (maruenc));
+
+  if (maruenc->opened) {
+    gst_maru_avcodec_close (maruenc->context, maruenc->dev);
+    maruenc->opened = FALSE;
+
+    gst_pad_set_caps (maruenc->srcpad, NULL);
+  }
+
+  maruenc->context->bit_rate = maruenc->bitrate;
+  GST_DEBUG_OBJECT (maruenc, "Setting context to bitrate %lu, gop_size %d",
+      maruenc->bitrate, maruenc->gop_size);
+
+#if 0
+
+  // user defined properties
+  maruenc->context->gop_size = maruenc->gop_size;
+  maruenc->context->lmin = (maruenc->lmin * FF_QP2LAMBDA + 0.5);
+  maruenc->context->lmax = (maruenc->lmax * FF_QP2LAMBDA + 0.5);
+
+  // some other defaults
+  maruenc->context->b_frame_strategy = 0;
+  maruenc->context->coder_type = 0;
+  maruenc->context->context_model = 0;
+  maruenc->context->scenechange_threshold = 0;
+  maruenc->context->inter_threshold = 0;
+
+  if (maruenc->interlaced) {
+    maruenc->context->flags |=
+      CODEC_FLAG_INTERLACED_DCT | CODEC_FLAG_INTERLACED_ME;
+    maruenc->picture->interlaced_frame = TRUE;
+
+    maruenc->picture->top_field_first = TRUE;
+  }
+#endif
+
+  gst_maru_caps_with_codectype (oclass->codec->media_type, caps, maruenc->context);
+
+  if (!maruenc->context->video.fps_d) {
+    maruenc->context->video.fps_d = 25;
+    maruenc->context->video.fps_n = 1;
+  } else if (!strcmp(oclass->codec->name ,"mpeg4")
+      && (maruenc->context->video.fps_d > 65535)) {
+      maruenc->context->video.fps_n =
+        (gint) gst_util_uint64_scale_int (maruenc->context->video.fps_n,
+            65535, maruenc->context->video.fps_d);
+      maruenc->context->video.fps_d = 65535;
+      GST_LOG_OBJECT (maruenc, "MPEG4 : scaled down framerate to %d / %d",
+          maruenc->context->video.fps_d, maruenc->context->video.fps_n);
+  }
+
+  pix_fmt = maruenc->context->video.pix_fmt;
+
+  {
+    switch (oclass->codec->media_type) {
+    case AVMEDIA_TYPE_VIDEO:
+    {
+      int width, height;
+
+      width = maruenc->context->video.width;
+      height = maruenc->context->video.height;
+      buf_size = width * height * 6 + FF_MIN_BUFFER_SIZE + 100;
+      break;
+    }
+    case AVMEDIA_TYPE_AUDIO:
+        buf_size = FF_MAX_AUDIO_FRAME_SIZE + 100;
+        break;
+    default:
+        buf_size = -1;
+        break;
+    }
+  }
+
+  maruenc->dev->buf_size = gst_maru_align_size(buf_size);
+
+  // open codec
+  if (gst_maru_avcodec_open (maruenc->context,
+      oclass->codec, maruenc->dev) < 0) {
+    GST_DEBUG_OBJECT (maruenc, "maru_%senc: Failed to open codec",
+        oclass->codec->name);
+    return FALSE;
+  }
+
+  if (pix_fmt != maruenc->context->video.pix_fmt) {
+    gst_maru_avcodec_close (maruenc->context, maruenc->dev);
+    GST_DEBUG_OBJECT (maruenc,
+      "maru_%senc: AV wants different colorspace (%d given, %d wanted)",
+      oclass->codec->name, pix_fmt, maruenc->context->video.pix_fmt);
+    return FALSE;
+  }
+
+  if (oclass->codec->media_type == AVMEDIA_TYPE_VIDEO
+    && pix_fmt == PIX_FMT_NONE) {
+    GST_DEBUG_OBJECT (maruenc, "maru_%senc: Failed to determine input format",
+      oclass->codec->name);
+    return FALSE;
+  }
+
+  GST_DEBUG_OBJECT (maruenc, "picking an output format.");
+  allowed_caps = gst_pad_get_allowed_caps (maruenc->srcpad);
+  if (!allowed_caps) {
+    GST_DEBUG_OBJECT (maruenc, "but no peer, using template caps");
+    allowed_caps =
+      gst_caps_copy (gst_pad_get_pad_template_caps (maruenc->srcpad));
+  }
+
+  GST_DEBUG_OBJECT (maruenc, "chose caps %" GST_PTR_FORMAT, allowed_caps);
+  gst_maru_caps_with_codecname (oclass->codec->name,
+    oclass->codec->media_type, allowed_caps, maruenc->context);
+
+  other_caps =
+  gst_maru_codecname_to_caps (oclass->codec->name, maruenc->context, TRUE);
+  if (!other_caps) {
+  GST_DEBUG("Unsupported codec - no caps found");
+    gst_maru_avcodec_close (maruenc->context, maruenc->dev);
+    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);
+    gst_caps_unref (icaps);
+    icaps = newcaps;
+  }
+
+  if (!gst_pad_set_caps (maruenc->srcpad, icaps)) {
+    gst_maru_avcodec_close (maruenc->context, maruenc->dev);
+    gst_caps_unref (icaps);
+    return FALSE;
+  }
+  gst_object_unref (maruenc);
+
+  maruenc->opened = TRUE;
+
+  return TRUE;
+}
+
+static void
+gst_maruenc_setup_working_buf (GstEmulEnc *maruenc)
+{
+  guint wanted_size =
+      maruenc->context->video.width * maruenc->context->video.height * 6 +
+      FF_MIN_BUFFER_SIZE;
+
+  if (maruenc->working_buf == NULL ||
+    maruenc->working_buf_size != wanted_size) {
+    if (maruenc->working_buf) {
+      g_free (maruenc->working_buf);
+    }
+    maruenc->working_buf_size = wanted_size;
+    maruenc->working_buf = g_malloc0 (maruenc->working_buf_size);
+  }
+  maruenc->buffer_size = wanted_size;
+}
+
+GstFlowReturn
+gst_maruenc_chain_video (GstPad *pad, GstBuffer *buffer)
+{
+  GstEmulEnc *maruenc = (GstEmulEnc *) (GST_PAD_PARENT (pad));
+  GstBuffer *outbuf;
+  gint ret_size = 0, frame_size;
+
+  GST_DEBUG_OBJECT (maruenc,
+      "Received buffer of time %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
+
+#if 0
+  GST_OBJECT_LOCK (maruenc);
+  force_keyframe = maruenc->force_keyframe;
+  maruenc->force_keyframe = FALSE;
+  GST_OBJECT_UNLOCK (maruenc);
+
+  if (force_keyframe) {
+    maruenc->picture->pict_type = FF_I_TYPE;
+  }
+#endif
+
+  frame_size = gst_maru_avpicture_size (maruenc->context->video.pix_fmt,
+      maruenc->context->video.width, maruenc->context->video.height);
+  g_return_val_if_fail (frame_size == GST_BUFFER_SIZE (buffer),
+      GST_FLOW_ERROR);
+
+#if 0
+  pts = gst_maru_time_gst_to_ff (GST_BUFFER_TIMESTAMP (buffer) /
+    maruenc->context.video.ticks_per_frame,
+    maruenc->context.video.fps_n, maruen->context.video.fps_d);
+#endif
+
+  // TODO: check whether this func needs or not.
+  gst_maruenc_setup_working_buf (maruenc);
+
+  ret_size =
+    codec_encode_video (maruenc->context, maruenc->working_buf,
+                maruenc->working_buf_size, GST_BUFFER_DATA (buffer),
+                GST_BUFFER_SIZE (buffer), GST_BUFFER_TIMESTAMP (buffer),
+                maruenc->dev);
+
+  if (ret_size < 0) {
+    GstEmulEncClass *oclass =
+      (GstEmulEncClass *) (G_OBJECT_GET_CLASS (maruenc));
+    GST_ERROR_OBJECT (maruenc,
+        "maru_%senc: failed to encode buffer", oclass->codec->name);
+    gst_buffer_unref (buffer);
+    return GST_FLOW_OK;
+  }
+
+  g_queue_push_tail (maruenc->delay, buffer);
+  if (ret_size) {
+    buffer = g_queue_pop_head (maruenc->delay);
+  } else {
+    return GST_FLOW_OK;
+  }
+
+#if 0
+  if (maruenc->file && maruenc->context->stats_out) {
+    if (fprintf (maruenc->file, "%s", maruenc->context->stats_out) < 0) {
+      GST_ELEMENT_ERROR (maruenc, RESOURCE, WRITE,
+        (("Could not write to file \"%s\"."), maruenc->filename),
+        GST_ERROR_SYSTEM);
+    }
+  }
+#endif
+#if 1
+  {
+    int ret;
+    uint32_t mem_offset;
+    uint8_t *working_buf = NULL;
+
+    mem_offset = maruenc->dev->mem_info.offset;
+    working_buf = maruenc->dev->buf + mem_offset;
+    if (!working_buf) {
+    } else {
+      CODEC_LOG (INFO,
+          "encoded video. mem_offset = 0x%x\n",  mem_offset);
+
+      outbuf = gst_buffer_new_and_alloc (ret_size);
+//    memcpy (GST_BUFFER_DATA (outbuf), maruenc->working_buf, ret_size);
+      memcpy (GST_BUFFER_DATA (outbuf), working_buf, ret_size);
+      GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buffer);
+      GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buffer);
+    }
+
+    ret = ioctl(maruenc->dev->fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
+    if (ret < 0) {
+      CODEC_LOG (ERR, "failed to release used buffer\n");
+    }
+  }
+#endif
+
+#if 0
+  if (maruenc->context->coded_frame) {
+    if (!maruenc->context->coded_frame->key_frame) {
+      GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
+    }
+  } else {
+    GST_WARNING_OBJECT (maruenc, "codec did not provide keyframe info");
+  }
+#endif
+  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (maruenc->srcpad));
+
+  gst_buffer_unref (buffer);
+
+#if 0
+
+  if (force_keyframe) {
+    gst_pad_push_event (maruenc->srcpad,
+      gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
+      gst_structure_new ("GstForceKeyUnit", "timestamp",
+                         G_TYPE_UINT64, GST_BUFFER_TIMESTAMP (outbuf), NULL)));
+  }
+#endif
+
+  return gst_pad_push (maruenc->srcpad, outbuf);
+}
+
+GstFlowReturn
+gst_maruenc_encode_audio (GstEmulEnc *maruenc, guint8 *audio_in,
+  guint in_size, guint max_size, GstClockTime timestamp,
+  GstClockTime duration, gboolean discont)
+{
+  GstBuffer *outbuf;
+  guint8 *audio_out;
+  gint res;
+  GstFlowReturn ret;
+
+  outbuf = gst_buffer_new_and_alloc (max_size + FF_MIN_BUFFER_SIZE);
+  audio_out = GST_BUFFER_DATA (outbuf);
+
+  GST_LOG_OBJECT (maruenc, "encoding buffer of max size %d", max_size);
+  if (maruenc->buffer_size != max_size) {
+    maruenc->buffer_size = max_size;
+  }
+
+  res = codec_encode_audio (maruenc->context, audio_out, max_size,
+                                  audio_in, in_size, maruenc->dev);
+
+  if (res < 0) {
+    GST_ERROR_OBJECT (maruenc, "Failed to encode buffer: %d", res);
+    gst_buffer_unref (outbuf);
+    return GST_FLOW_OK;
+  }
+  GST_LOG_OBJECT (maruenc, "got output size %d", res);
+
+  GST_BUFFER_SIZE (outbuf) = res;
+  GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
+  GST_BUFFER_DURATION (outbuf) = duration;
+  if (discont) {
+    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
+  }
+  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (maruenc->srcpad));
+
+  GST_LOG_OBJECT (maruenc, "pushing size %d, timestamp %",
+      GST_TIME_FORMAT, res, GST_TIME_ARGS (timestamp));
+
+  ret = gst_pad_push (maruenc->srcpad, outbuf);
+
+  return ret;
+}
+
+static GstFlowReturn
+gst_maruenc_chain_audio (GstPad *pad, GstBuffer *buffer)
+{
+  GstEmulEnc *maruenc;
+  GstEmulEncClass *oclass;
+  GstClockTime timestamp, duration;
+  guint in_size, frame_size;
+  gint osize;
+  GstFlowReturn ret;
+  gint out_size = 0;
+  gboolean discont;
+  guint8 *in_data;
+  CodecContext *ctx;
+
+  maruenc = (GstEmulEnc *) (GST_OBJECT_PARENT (pad));
+  oclass = (GstEmulEncClass *) G_OBJECT_GET_CLASS (maruenc);
+
+  ctx = maruenc->context;
+
+  in_size = GST_BUFFER_SIZE (buffer);
+  timestamp = GST_BUFFER_TIMESTAMP (buffer);
+  duration = GST_BUFFER_DURATION (buffer);
+  discont = GST_BUFFER_IS_DISCONT (buffer);
+
+  GST_DEBUG_OBJECT (maruenc,
+    "Received time %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT
+    ", size %d", GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration), in_size);
+
+  frame_size = ctx->audio.frame_size;
+  osize = ctx->audio.bits_per_sample_fmt;
+
+  if (frame_size > 1) {
+    guint avail, frame_bytes;
+
+    if (discont) {
+      GST_LOG_OBJECT (maruenc, "DISCONT, clear adapter");
+      gst_adapter_clear (maruenc->adapter);
+      maruenc->discont = TRUE;
+    }
+
+    if (gst_adapter_available (maruenc->adapter) == 0) {
+      GST_LOG_OBJECT (maruenc, "taking buffer timestamp %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (timestamp));
+      maruenc->adapter_ts = timestamp;
+      maruenc->adapter_consumed = 0;
+    } else {
+      GstClockTime upstream_time;
+      GstClockTime consumed_time;
+      guint64 bytes;
+
+      consumed_time =
+        gst_util_uint64_scale (maruenc->adapter_consumed, GST_SECOND,
+            ctx->audio.sample_rate);
+      timestamp = maruenc->adapter_ts + consumed_time;
+      GST_LOG_OBJECT (maruenc, "taking adapter timestamp %" GST_TIME_FORMAT
+        " and adding consumed time %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (maruenc->adapter_ts), GST_TIME_ARGS (consumed_time));
+
+      upstream_time = gst_adapter_prev_timestamp (maruenc->adapter, &bytes);
+      if (GST_CLOCK_TIME_IS_VALID (upstream_time)) {
+        GstClockTimeDiff diff;
+
+        upstream_time +=
+          gst_util_uint64_scale (bytes, GST_SECOND,
+            ctx->audio.sample_rate * osize * ctx->audio.channels);
+        diff = upstream_time - timestamp;
+
+        if (diff > GST_SECOND / 10 || diff < -GST_SECOND / 10) {
+          GST_DEBUG_OBJECT (maruenc, "adapter timestamp drifting, "
+            "taking upstream timestamp %" GST_TIME_FORMAT,
+            GST_TIME_ARGS (upstream_time));
+          timestamp = upstream_time;
+
+          maruenc->adapter_consumed = bytes / (osize * ctx->audio.channels);
+          maruenc->adapter_ts =
+            upstream_time - gst_util_uint64_scale (maruenc->adapter_consumed,
+                GST_SECOND, ctx->audio.sample_rate);
+          maruenc->discont = TRUE;
+        }
+      }
+    }
+
+    GST_LOG_OBJECT (maruenc, "pushing buffer in adapter");
+    gst_adapter_push (maruenc->adapter, buffer);
+
+    frame_bytes = frame_size * osize * ctx->audio.channels;
+    avail = gst_adapter_available (maruenc->adapter);
+
+    GST_LOG_OBJECT (maruenc, "frame_bytes %u, avail %u", frame_bytes, avail);
+
+    while (avail >= frame_bytes) {
+      GST_LOG_OBJECT (maruenc, "taking %u bytes from the adapter", frame_bytes);
+
+      in_data = (guint8 *) gst_adapter_peek (maruenc->adapter, frame_bytes);
+      maruenc->adapter_consumed += frame_size;
+
+      duration =
+        gst_util_uint64_scale (maruenc->adapter_consumed, GST_SECOND,
+          ctx->audio.sample_rate);
+      duration -= (timestamp - maruenc->adapter_ts);
+
+      out_size = frame_bytes * 4;
+
+      ret =
+        gst_maruenc_encode_audio (maruenc, in_data, frame_bytes, out_size,
+          timestamp, duration, maruenc->discont);
+
+      gst_adapter_flush (maruenc->adapter, frame_bytes);
+      if (ret != GST_FLOW_OK) {
+        GST_DEBUG_OBJECT (maruenc, "Failed to push buffer %d (%s)", ret,
+          gst_flow_get_name (ret));
+      }
+
+      timestamp += duration;
+
+      maruenc->discont = FALSE;
+      avail = gst_adapter_available (maruenc->adapter);
+    }
+    GST_LOG_OBJECT (maruenc, "%u bytes left in the adapter", avail);
+  } else {
+#if 0
+    int coded_bps = av_get_bits_per_sample (oclass->codec->name);
+
+    GST_LOG_OBJECT (maruenc, "coded bps %d, osize %d", coded_bps, osize);
+
+    out_size = in_size / osize;
+    if (coded_bps) {
+      out_size = (out_size * coded_bps) / 8;
+    }
+#endif
+    in_data = (guint8 *) GST_BUFFER_DATA (buffer);
+    ret = gst_maruenc_encode_audio (maruenc, in_data, in_size, out_size,
+      timestamp, duration, discont);
+    gst_buffer_unref (buffer);
+    if (ret != GST_FLOW_OK) {
+      GST_DEBUG_OBJECT (maruenc, "Failed to push buffer %d (%s)", ret,
+        gst_flow_get_name (ret));
+    }
+  }
+
+  return GST_FLOW_OK;
+}
+
+static void
+gst_maruenc_flush_buffers (GstEmulEnc *maruenc, gboolean send)
+{
+  GstBuffer *outbuf, *inbuf;
+  gint ret_size = 0;
+
+  GST_DEBUG_OBJECT (maruenc, "flushing buffers with sending %d", send);
+
+  if (!maruenc->opened) {
+    while (!g_queue_is_empty (maruenc->delay)) {
+      gst_buffer_unref (g_queue_pop_head (maruenc->delay));
+    }
+  }
+
+#if 0
+  while (!g_queue_is_empty (maruenc->delay)) {
+    maruenc_setup_working_buf (maruenc);
+
+    ret_size = codec_encode_video (maruenc->context,
+      maruenc->working_buf, maruenc->working_buf_size, NULL, NULL, 0,
+      maruenc->dev);
+
+    if (ret_size < 0) {
+      GstEmulEncClass *oclass =
+        (GstEmulEncClass *) (G_OBJECT_GET_CLASS (maruenc));
+      GST_WARNING_OBJECT (maruenc,
+        "maru_%senc: failed to flush buffer", oclass->codec->name);
+      break;
+    }
+
+    if (maruenc->file && maruenc->context->stats_out) {
+      if (fprintf (maruenc->file, "%s", maruenc->context->stats_out) < 0) {
+        GST_ELEMENT_ERROR (emeulenc, RESOURCE, WRITE,
+          (("Could not write to file \"%s\"."), maruenc->filename),
+          GST_ERROR_SYSTEM);
+      }
+    }
+
+    inbuf = g_queue_pop_head (maruenc->delay);
+
+    outbuf = gst_buffer_new_and_alloc (ret_size);
+    memcpy (GST_BUFFER_DATA (outbuf), maruenc->working_buf, ret_size);
+    GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (inbuf);
+    GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (inbuf);
+
+    if (!maruenc->context->coded_frame->key_frame) {
+      GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
+    }
+    gst_buffer_set_caps (outbuf, GST_PAD_CAPS (maruenc->srcpad));
+
+    gst_buffer_unref (inbuf);
+
+    if (send) {
+      gst_pad_push (maruenc->srcpad, outbuf);
+    } else {
+      gst_buffer_unref (outbuf);
+    }
+  }
+
+  while (!g_queue_is_empty (maruenc->delay)) {
+    gst_buffer_unref (g_queue_pop_head (maruenc->delay));
+  }
+#endif
+}
+
+static gboolean
+gst_maruenc_event_video (GstPad *pad, GstEvent *event)
+{
+  GstEmulEnc *maruenc;
+  maruenc = (GstEmulEnc *) gst_pad_get_parent (pad);
+
+  switch (GST_EVENT_TYPE (event)) {
+  case GST_EVENT_EOS:
+    gst_maruenc_flush_buffers (maruenc, TRUE);
+    break;
+  case GST_EVENT_CUSTOM_DOWNSTREAM:
+  {
+    const GstStructure *s;
+    s = gst_event_get_structure (event);
+
+    if (gst_structure_has_name (s, "GstForceKeyUnit")) {
+#if 0
+      maruenc->picture->pict_type = FF_I_TYPE;
+#endif
+    }
+  }
+    break;
+  default:
+    break;
+  }
+
+  return gst_pad_push_event (maruenc->srcpad, event);
+}
+
+static gboolean
+gst_maruenc_event_src (GstPad *pad, GstEvent *event)
+{
+  GstEmulEnc *maruenc = (GstEmulEnc *) (GST_PAD_PARENT (pad));
+  gboolean forward = TRUE;
+
+  switch (GST_EVENT_TYPE (event)) {
+  case GST_EVENT_CUSTOM_UPSTREAM:
+  {
+    const GstStructure *s;
+    s = gst_event_get_structure (event);
+
+    if (gst_structure_has_name (s, "GstForceKeyUnit")) {
+#if 0
+      GST_OBJECT_LOCK (maruenc);
+      maruenc->force_keyframe = TRUE;
+      GST_OBJECT_UNLOCK (maruenc);
+#endif
+      forward = FALSE;
+      gst_event_unref (event);
+    }
+  }
+    break;
+  default:
+    break;
+  }
+
+  if (forward) {
+    return gst_pad_push_event (maruenc->sinkpad, event);
+  }
+
+  return TRUE;
+}
+
+GstStateChangeReturn
+gst_maruenc_change_state (GstElement *element, GstStateChange transition)
+{
+  GstEmulEnc *maruenc = (GstEmulEnc*)element;
+  GstStateChangeReturn ret;
+
+  switch (transition) {
+  default:
+    break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+  switch (transition) {
+  case GST_STATE_CHANGE_PAUSED_TO_READY:
+    gst_maruenc_flush_buffers (maruenc, FALSE);
+    if (maruenc->opened) {
+      gst_maru_avcodec_close (maruenc->context, maruenc->dev);
+      maruenc->opened = FALSE;
+    }
+    gst_adapter_clear (maruenc->adapter);
+
+#if 0
+    if (maruenc->flie) {
+      fclose (maruenc->file);
+      maruenc->file = NULL;
+    }
+#endif
+
+    if (maruenc->working_buf) {
+      g_free (maruenc->working_buf);
+      maruenc->working_buf = NULL;
+    }
+    break;
+  default:
+    break;
+  }
+
+  return ret;
+}
+
+gboolean
+gst_maruenc_register (GstPlugin *plugin, GList *element)
+{
+  GTypeInfo typeinfo = {
+      sizeof (GstEmulEncClass),
+      (GBaseInitFunc) gst_maruenc_base_init,
+      NULL,
+      (GClassInitFunc) gst_maruenc_class_init,
+      NULL,
+      NULL,
+      sizeof (GstEmulEnc),
+      0,
+      (GInstanceInitFunc) gst_maruenc_init,
+  };
+
+  GType type;
+  gchar *type_name;
+  gint rank = GST_RANK_NONE;
+  GList *elem = element;
+  CodecElement *codec = NULL;
+
+  if (!elem) {
+    return FALSE;
+  }
+
+  /* register element */
+  do {
+    codec = (CodecElement *)(elem->data);
+    if (!codec) {
+      return FALSE;
+    }
+
+    if (codec->codec_type != CODEC_TYPE_ENCODE) {
+      continue;
+    }
+
+    type_name = g_strdup_printf ("maru_%senc", 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_MARUENC_PARAMS_QDATA, (gpointer) codec);
+    }
+
+    if (!gst_element_register (plugin, type_name, rank, type)) {
+      g_free (type_name);
+      return FALSE;
+    }
+    g_free (type_name);
+  } while ((elem = elem->next));
+
+  return TRUE;
+}
diff --git a/src/gstmaruinterface.c b/src/gstmaruinterface.c
new file mode 100644 (file)
index 0000000..d2bc2ad
--- /dev/null
@@ -0,0 +1,632 @@
+/*
+ * 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 "gstmaru.h"
+#include "gstmaruinterface.h"
+#include "gstmarumem.h"
+#include "gstmarudevice.h"
+
+extern int device_fd;
+extern gpointer device_mem;
+
+struct mem_info {
+    gpointer start;
+    uint32_t offset;
+};
+
+typedef struct _CodecHeader {
+  int32_t   api_index;
+  uint32_t  mem_offset;
+} CodecHeader;
+
+#define SMALL_BUFFER    (256 * 1024)
+#define MEDIUM_BUFFER   (2 * 1024 * 1024)
+#define LARGE_BUFFER    (4 * 1024 * 1024)
+
+#define CODEC_META_DATA_SIZE 256
+
+static int
+_codec_header (int32_t api_index, uint32_t mem_offset, uint8_t *device_buf)
+{
+  CodecHeader header = { 0 };
+
+  CODEC_LOG (DEBUG, "enter, %s\n", __func__);
+
+  header.api_index = api_index;
+  header.mem_offset = mem_offset;
+
+  memcpy(device_buf, &header, sizeof(header));
+
+  CODEC_LOG (DEBUG, "leave, %s\n", __func__);
+
+  return sizeof(header);
+}
+
+static void
+_codec_write_to_qemu (int32_t ctx_index, int32_t api_index,
+                          uint32_t mem_offset, int fd)
+{
+  CodecIOParams ioparam;
+
+  memset(&ioparam, 0, sizeof(ioparam));
+  ioparam.api_index = api_index;
+  ioparam.ctx_index = ctx_index;
+  ioparam.mem_offset = mem_offset;
+  if (write (fd, &ioparam, 1) < 0) {
+    fprintf (stderr, "%s, failed to write copy data.\n", __func__);
+  }
+}
+
+static struct mem_info
+secure_device_mem (guint buf_size)
+{
+  int ret = 0;
+  uint32_t mem_offset = 0, cmd;
+  struct mem_info info;
+
+  CODEC_LOG (DEBUG, "enter: %s\n", __func__);
+
+  if (buf_size < SMALL_BUFFER) {
+    cmd = CODEC_CMD_SECURE_SMALL_BUFFER;
+    CODEC_LOG (DEBUG, "small buffer size\n");
+  } else if (buf_size < MEDIUM_BUFFER) {
+    // HD Video(2MB)
+    cmd = CODEC_CMD_SECURE_MEDIUM_BUFFER;
+    CODEC_LOG (DEBUG, "HD buffer size\n");
+  } else {
+    // FULL HD Video(4MB)
+    cmd = CODEC_CMD_SECURE_LARGE_BUFFER;
+    CODEC_LOG (DEBUG, "FULL HD buffer size\n");
+  }
+
+  ret = ioctl (device_fd, cmd, &mem_offset);
+  if (ret < 0) {
+    CODEC_LOG (ERR, "failed to get available buffer\n");
+    // FIXME:
+  } else {
+    if (mem_offset == (LARGE_BUFFER * 8)) {
+      CODEC_LOG (ERR, "acquired memory is over!!\n");
+    } else {
+      info.start = (gpointer)((uint32_t)device_mem + mem_offset);
+      info.offset = mem_offset;
+
+      CODEC_LOG (DEBUG, "acquire device_memory: 0x%x\n", mem_offset);
+    }
+  }
+
+  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
+
+  return info;
+}
+
+static void
+release_device_mem (gpointer start)
+{
+  int ret;     
+  uint32_t offset = start - device_mem;
+
+  CODEC_LOG (DEBUG, "enter: %s\n", __func__);
+
+  CODEC_LOG (DEBUG, "release device_mem start: %p, offset: 0x%x\n", start, offset);
+  ret = ioctl (device_fd, CODEC_CMD_RELEASE_BUFFER, &offset);
+  if (ret < 0) {
+    CODEC_LOG (ERR, "failed to release buffer\n");
+  }
+
+  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
+}
+
+static void
+codec_buffer_free (gpointer start)
+{
+  CODEC_LOG (DEBUG, "enter: %s\n", __func__);
+
+  release_device_mem (start);
+
+  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
+}
+
+GstFlowReturn
+codec_buffer_alloc (GstPad *pad, guint64 offset, guint size,
+                  GstCaps *caps, GstBuffer **buf)
+{
+  struct mem_info info;
+
+  CODEC_LOG (DEBUG, "enter: %s\n", __func__);
+
+  *buf = gst_buffer_new ();
+
+  info = secure_device_mem (size);
+
+  CODEC_LOG (DEBUG, "memory start: 0x%p, offset 0x%x\n",
+            info.start, info.offset);
+
+  GST_BUFFER_DATA (*buf) = GST_BUFFER_MALLOCDATA (*buf) = info.start;
+  GST_BUFFER_SIZE (*buf) = size;
+  GST_BUFFER_FREE_FUNC (*buf) = codec_buffer_free;
+  GST_BUFFER_OFFSET (*buf) = offset;
+
+  if (caps) {
+    gst_buffer_set_caps (*buf, caps);
+  }
+
+  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
+
+  return GST_FLOW_OK;
+}
+
+int
+codec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
+{
+  int fd, ret = 0;
+  int opened, size = 0;
+  uint8_t *mmapbuf = NULL;
+  uint32_t meta_offset = 0;
+
+  CODEC_LOG (DEBUG, "enter: %s\n", __func__);
+
+  fd = dev->fd;
+  if (fd < 0) {
+    GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
+    return -1;
+  }
+
+  mmapbuf = (uint8_t *)dev->buf;
+  if (!mmapbuf) {
+    GST_ERROR ("failed to get mmaped memory address.\n");
+    return -1;
+  }
+
+  ret = ioctl(fd, CODEC_CMD_GET_CONTEXT_INDEX, &ctx->index);
+  if (ret < 0) {
+    GST_ERROR ("failed to get context index\n");
+    return -1;
+  }
+  CODEC_LOG (DEBUG, "get context index: %d\n", ctx->index);
+
+  meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
+  CODEC_LOG (DEBUG,
+    "init. ctx: %d meta_offset = 0x%x\n", ctx->index, meta_offset);
+
+//  size = _codec_header (CODEC_INIT, 0, mmapbuf + meta_offset);
+  size = 8;
+  _codec_init_meta_to (ctx, codec, mmapbuf + meta_offset + size);
+
+  _codec_write_to_qemu (ctx->index, CODEC_INIT, 0, fd);
+
+  CODEC_LOG (DEBUG,
+    "init. ctx: %d meta_offset = 0x%x, size: %d\n", ctx->index, meta_offset, size);
+
+#if 0
+  if (codec->media_type == AVMEDIA_TYPE_AUDIO) {
+    CODEC_LOG (DEBUG,
+        "opened: %d, audio_sample_fmt: %d\n",
+        *(int *)(mmapbuf + meta_offset + size),
+        *(int *)(mmapbuf + meta_offset + size + 4));
+  }
+#endif
+
+  opened =
+    _codec_init_meta_from (ctx, codec->media_type, mmapbuf + meta_offset + size);
+  ctx->codec= codec;
+
+  CODEC_LOG (DEBUG, "opened: %d\n", opened);
+
+  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
+
+  return opened;
+}
+
+void
+codec_deinit (CodecContext *ctx, CodecDevice *dev)
+{
+  int fd;
+  void *mmapbuf = NULL;
+
+  CODEC_LOG (DEBUG, "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_LOG (INFO, "close. context index: %d\n", ctx->index);
+  _codec_write_to_qemu (ctx->index, CODEC_DEINIT, 0, fd);
+
+  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
+}
+
+int
+codec_decode_video (CodecContext *ctx, uint8_t *in_buf, int in_size,
+                    gint idx, gint64 in_offset, GstBuffer **out_buf,
+                    int *got_picture_ptr, CodecDevice *dev)
+{
+  int fd, len = 0;
+  int ret, size = 0;
+  uint8_t *mmapbuf = NULL;
+  uint32_t mem_offset = 0, meta_offset = 0;
+
+  CODEC_LOG (DEBUG, "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;
+  }
+
+  ret = ioctl (fd, CODEC_CMD_SECURE_SMALL_BUFFER, &mem_offset);
+  if (ret < 0) {
+    CODEC_LOG (ERR,
+      "decode_audio. failed to get available memory to write inbuf\n");
+    return -1;
+  }
+  CODEC_LOG (DEBUG, "decode_video. mem_offset = 0x%x\n", mem_offset);
+
+  meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
+  CODEC_LOG (DEBUG, "decode_video. meta_offset = 0x%x\n", meta_offset);
+
+//  size = _codec_header (CODEC_DECODE_VIDEO, mem_offset, mmapbuf + meta_offset);
+  size = 8;
+  _codec_decode_video_meta_to (in_size, idx, in_offset, mmapbuf + meta_offset + size);
+  _codec_decode_video_inbuf (in_buf, in_size, mmapbuf + mem_offset);
+
+  dev->mem_info.offset = mem_offset;
+  _codec_write_to_qemu (ctx->index, CODEC_DECODE_VIDEO, mem_offset, fd);
+
+  // after decoding video, no need to get outbuf.
+  len =
+    _codec_decode_video_meta_from (&ctx->video, got_picture_ptr, mmapbuf + meta_offset + size);
+
+  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
+
+  return len;
+}
+
+void
+codec_picture_copy (CodecContext *ctx, uint8_t *pict,
+                    uint32_t pict_size, CodecDevice *dev)
+{
+  int fd, ret = 0;
+  void *mmapbuf = NULL;
+
+  CODEC_LOG (DEBUG, "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_LOG (DEBUG, "pict_size: %d\n",  pict_size);
+
+//     if (pict_size < MEDIUM_BUFFER) {
+  if (pict_size < (SMALL_BUFFER)) {
+    dev->mem_info.offset = (uint32_t)pict - (uint32_t)mmapbuf;
+    CODEC_LOG (DEBUG, "pict: %p , device_mem: %p\n",  pict, mmapbuf);
+    CODEC_LOG (DEBUG, "picture_copy, mem_offset = 0x%x\n",  dev->mem_info.offset);
+  }
+
+  _codec_write_to_qemu (ctx->index, CODEC_PICTURE_COPY,
+                        dev->mem_info.offset, fd);
+//     if (pict_size < MEDIUM_BUFFER) {
+  if (pict_size < SMALL_BUFFER) {
+    CODEC_LOG (DEBUG,
+      "set the mem_offset as outbuf: 0x%x\n",  dev->mem_info.offset);
+    ret = ioctl (fd, CODEC_CMD_USE_DEVICE_MEM, &(dev->mem_info.offset));
+    if (ret < 0) {
+      // FIXME:
+    }
+  } else if (pict_size < MEDIUM_BUFFER) {
+    uint32_t mem_offset = 0;
+    CODEC_LOG (DEBUG, "require to use medium size of memory\n");
+
+    ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_MEDIUM_BUFFER, &mem_offset);
+    if (ret < 0) {
+      return;
+    }
+    CODEC_LOG (DEBUG, "picture_copy, mem_offset = 0x%x\n",  mem_offset);
+
+    memcpy (pict, mmapbuf + mem_offset, pict_size);
+
+    ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
+    if (ret < 0) {
+      CODEC_LOG (ERR, "failed release used memory\n");
+    }
+  } else {
+    uint32_t mem_offset = 0;
+    CODEC_LOG (DEBUG, "require to use large size of memory\n");
+
+    ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_LARGE_BUFFER, &mem_offset);
+    if (ret < 0) {
+      return;
+    }
+    CODEC_LOG (DEBUG, "picture_copy, mem_offset = 0x%x\n",  mem_offset);
+
+    memcpy (pict, mmapbuf + mem_offset, pict_size);
+
+    ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
+    if (ret < 0) {
+      CODEC_LOG (ERR, "failed release used memory\n");
+    }
+  }
+
+  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
+}
+
+int
+codec_decode_audio (CodecContext *ctx, int16_t *samples,
+                    int *have_data, uint8_t *in_buf,
+                    int in_size, CodecDevice *dev)
+{
+  int fd, len = 0;
+  int ret, size = 0;
+  uint8_t *mmapbuf = NULL;
+  uint32_t mem_offset = 0, meta_offset = 0;
+
+  CODEC_LOG (DEBUG, "enter: %s\n", __func__);
+
+  fd = dev->fd;
+  if (fd < 0) {
+    GST_ERROR("failed to get %s fd\n", CODEC_DEV);
+    return -1;
+  }
+
+  mmapbuf = (uint8_t *)dev->buf;
+  if (!mmapbuf) {
+    GST_ERROR("failed to get mmaped memory address\n");
+    return -1;
+  }
+
+  ret = ioctl (fd, CODEC_CMD_SECURE_SMALL_BUFFER, &mem_offset);
+  if (ret < 0) {
+    CODEC_LOG (ERR,
+      "decode_audio. failed to get available memory to write inbuf\n");
+    return -1;
+  }
+  CODEC_LOG (DEBUG, "decode audio. mem_offset = 0x%x\n", mem_offset);
+
+  meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
+  CODEC_LOG (DEBUG, "decode_audio. meta_offset = 0x%x\n", meta_offset);
+
+//  size = _codec_header (CODEC_DECODE_AUDIO, mem_offset, mmapbuf + meta_offset);
+  size = 8;
+  _codec_decode_audio_meta_to (in_size, mmapbuf + meta_offset + size);
+  _codec_decode_audio_inbuf (in_buf, in_size, mmapbuf + mem_offset);
+
+  dev->mem_info.offset = mem_offset;
+  _codec_write_to_qemu (ctx->index, CODEC_DECODE_AUDIO, mem_offset, fd);
+
+  ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_SMALL_BUFFER, &mem_offset);
+  if (ret < 0) {
+    return -1;
+  }
+
+  len =
+    _codec_decode_audio_meta_from (&ctx->audio, have_data, mmapbuf + meta_offset + size);
+  if (len > 0) {
+    _codec_decode_audio_outbuf (*have_data, samples, mmapbuf + mem_offset);
+  }
+  memset(mmapbuf + mem_offset, 0x00, sizeof(len));
+
+  ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
+  if (ret < 0) {
+    CODEC_LOG (ERR, "failed release used memory\n");
+  }
+
+  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
+
+  return len;
+}
+
+int
+codec_encode_video (CodecContext *ctx, uint8_t *out_buf,
+                    int out_size, uint8_t *in_buf,
+                    int in_size, int64_t in_timestamp, CodecDevice *dev)
+{
+  int fd, len = 0;
+  int ret, size;
+  uint8_t *mmapbuf = NULL;
+  uint32_t mem_offset = 0, meta_offset = 0;
+
+  CODEC_LOG (DEBUG, "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;
+  }
+
+  if (in_size < SMALL_BUFFER) {
+    CODEC_LOG (DEBUG, "use small size of buffer\n");
+
+    ret = ioctl (fd, CODEC_CMD_SECURE_SMALL_BUFFER, &mem_offset);
+    if (ret < 0) {
+      CODEC_LOG (ERR, "failed to small size of buffer.\n");
+      return -1;
+    }
+  } else if (in_size < MEDIUM_BUFFER) {
+    CODEC_LOG (DEBUG, "use medium size of buffer\n");
+
+    ret = ioctl (fd, CODEC_CMD_SECURE_MEDIUM_BUFFER, &mem_offset);
+    if (ret < 0) {
+      CODEC_LOG (ERR, "failed to small size of buffer.\n");
+      return -1;
+    }
+  } else {
+    CODEC_LOG (DEBUG, "use large size of buffer\n");
+    ret = ioctl (fd, CODEC_CMD_SECURE_LARGE_BUFFER, &mem_offset);
+    if (ret < 0) {
+      CODEC_LOG (ERR, "failed to large size of buffer.\n");
+      return -1;
+    }
+  }
+  CODEC_LOG (DEBUG, "encode_video. mem_offset = 0x%x\n", mem_offset);
+
+  meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
+  CODEC_LOG (DEBUG, "encode_video. meta_offset = 0x%x\n", meta_offset);
+
+//  size =
+//    _codec_header (CODEC_ENCODE_VIDEO, mem_offset, mmapbuf + meta_offset);
+  size = 8;
+  meta_offset += size;
+  _codec_encode_video_meta_to (in_size, in_timestamp, mmapbuf + meta_offset);
+  _codec_encode_video_inbuf (in_buf, in_size, mmapbuf + mem_offset);
+
+  dev->mem_info.offset = mem_offset;
+  _codec_write_to_qemu (ctx->index, CODEC_ENCODE_VIDEO, mem_offset, fd);
+
+#ifndef DIRECT_BUFFER
+  ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_SMALL_BUFFER, &mem_offset);
+  if (ret < 0) {
+    return -1;
+  }
+  CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", mem_offset);
+
+  memcpy (&len, mmapbuf + meta_offset, sizeof(len));
+  CODEC_LOG (DEBUG, "encode_video. outbuf size: %d\n", len);
+  if (len > 0) {
+    memcpy (out_buf, mmapbuf + mem_offset, len);
+    out_buf = mmapbuf + mem_offset;
+  }
+
+  dev->mem_info.offset = mem_offset;
+#if 0
+  len =
+    _codec_encode_video_outbuf (out_buf, mmapbuf + mem_offset);
+//  memset(mmapbuf + mem_offset, 0x00, sizeof(len));
+#endif
+
+#if 1
+  ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
+  if (ret < 0) {
+    CODEC_LOG (ERR, "failed release used memory\n");
+  }
+#endif
+#else
+  dev->mem_info.offset = (uint32_t)pict - (uint32_t)mmapbuf;
+  CODEC_LOG (DEBUG, "outbuf: %p , device_mem: %p\n",  pict, mmapbuf);
+  CODEC_LOG (DEBUG, "encoded video. mem_offset = 0x%x\n",  dev->mem_info.offset);
+
+  ret = ioctl (fd, CODEC_CMD_USE_DEVICE_MEM, &(dev->mem_info.offset));
+  if (ret < 0) {
+    // FIXME:
+  }
+#endif
+  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
+
+  return len;
+}
+
+int
+codec_encode_audio (CodecContext *ctx, uint8_t *out_buf,
+                    int max_size, uint8_t *in_buf,
+                    int in_size, CodecDevice *dev)
+{
+  int fd, len = 0;
+  int ret, size;
+  void *mmapbuf = NULL;
+  uint32_t mem_offset = 0, meta_offset = 0;
+
+  CODEC_LOG (DEBUG, "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;
+  }
+
+  ret = ioctl (fd, CODEC_CMD_SECURE_SMALL_BUFFER, &mem_offset);
+  if (ret < 0) {
+    return -1;
+  }
+
+  CODEC_LOG (DEBUG, "write, encode_audio. mem_offset = 0x%x\n", mem_offset);
+
+  meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
+  CODEC_LOG (DEBUG, "encode_audio. meta mem_offset = 0x%x\n", meta_offset);
+
+  size = _codec_header (CODEC_ENCODE_AUDIO, mem_offset,
+                            mmapbuf + meta_offset);
+  _codec_encode_audio_meta_to (max_size, in_size, mmapbuf + meta_offset + size);
+  _codec_encode_audio_inbuf (in_buf, in_size, mmapbuf + mem_offset);
+
+  dev->mem_info.offset = mem_offset;
+  _codec_write_to_qemu (ctx->index, CODEC_ENCODE_AUDIO, mem_offset, fd);
+
+  ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_SMALL_BUFFER, &mem_offset);
+  if (ret < 0) {
+    return -1;
+  }
+
+  CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", mem_offset);
+
+  len = _codec_encode_audio_outbuf (out_buf, mmapbuf + mem_offset);
+  memset(mmapbuf + mem_offset, 0x00, sizeof(len));
+
+  ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
+  if (ret < 0) {
+    return -1;
+  }
+
+  CODEC_LOG (DEBUG, "leave: %s\n", __func__);
+
+  return len;
+}
diff --git a/src/gstmaruinterface.h b/src/gstmaruinterface.h
new file mode 100644 (file)
index 0000000..72b4b8a
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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_MARU_INTERFACE_H__
+#define __GST_MARU_INTERFACE_H__
+
+#include "gstmaru.h"
+
+int
+codec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev);
+
+void
+codec_deinit (CodecContext *ctx, CodecDevice *dev);
+
+int
+codec_decode_video (CodecContext *ctx, uint8_t *in_buf, int in_size,
+                    gint idx, gint64 in_offset, GstBuffer **out_buf,
+                    int *got_picture_ptr, CodecDevice *dev);
+
+
+int
+codec_decode_audio (CodecContext *ctx, int16_t *samples,
+                    int *frame_size_ptr, uint8_t *in_buf,
+                    int in_size, CodecDevice *dev);
+
+int
+codec_encode_video (CodecContext *ctx, uint8_t*out_buf,
+                    int out_size, uint8_t *in_buf,
+                    int in_size, int64_t in_timestamp,
+                    CodecDevice *dev);
+
+int
+codec_encode_audio (CodecContext *ctx, uint8_t *out_buf,
+                    int out_size, uint8_t *in_buf,
+                    int in_size, CodecDevice *dev);
+
+void
+codec_picture_copy (CodecContext *ctx, uint8_t *pict,
+                uint32_t pict_size, CodecDevice *dev);
+
+GstFlowReturn
+codec_buffer_alloc (GstPad *pad, guint64 offset,
+                    guint size, GstCaps *caps, GstBuffer **buf);
+
+#endif /* __GST_EMUL_API_H__ */
diff --git a/src/gstmarumem.c b/src/gstmarumem.c
new file mode 100644 (file)
index 0000000..42df415
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * 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 "gstmarumem.h"
+
+/*
+ *  codec data such as codec name, longname, media type and etc.
+ */
+static int
+_codec_info_data (CodecElement *codec, uint8_t *device_buf)
+{
+  int size = 0;
+
+  CODEC_LOG (DEBUG, "enter, %s\n", __func__);
+
+  CODEC_LOG (DEBUG, "type: %d, name: %s\n", codec->codec_type, codec->name);
+  memcpy (device_buf, &codec->codec_type, sizeof(codec->codec_type));
+  size = sizeof(codec->codec_type);
+
+  memcpy (device_buf + size, codec->name, sizeof(codec->name));
+  size += sizeof(codec->name);
+
+  CODEC_LOG (DEBUG, "leave, %s\n", __func__);
+
+  return size;
+}
+
+void
+_codec_init_meta_to (CodecContext *ctx,
+                      CodecElement *codec,
+                      uint8_t *device_buf)
+{
+  int size = 0;
+
+  CODEC_LOG (DEBUG, "enter, %s\n", __func__);
+
+  size = _codec_info_data (codec, device_buf);
+
+  if (codec) {
+  CODEC_LOG (INFO, "name: %s, media type: %s\n",
+    codec->name, codec->media_type ? "AUDIO" : "VIDEO");
+  }
+
+  if (codec->media_type == AVMEDIA_TYPE_AUDIO) {
+    CODEC_LOG (DEBUG,
+      "before init. audio sample_fmt: %d\n", ctx->audio.sample_fmt);
+    CODEC_LOG (DEBUG,
+      "before init. audio block_align: %d\n", ctx->audio.block_align);
+  }
+
+  CODEC_LOG (DEBUG, "init. write data to qemu, size: %d\n", size);
+  memcpy (device_buf + size, ctx, sizeof(CodecContext) - 12);
+  size += (sizeof(CodecContext) - 12);
+  memcpy (device_buf + size, ctx->codecdata, ctx->codecdata_size);
+
+  CODEC_LOG (DEBUG, "leave, %s\n", __func__);
+}
+
+int
+_codec_init_meta_from (CodecContext *ctx,
+                        int media_type,
+                        uint8_t *device_buf)
+{
+  int ret = 0, size = 0;
+
+  CODEC_LOG (DEBUG, "after init. read data from device.\n");
+
+  memcpy (&ret, device_buf, sizeof(ret));
+  size = sizeof(ret);
+  if (!ret) {
+    if (media_type == AVMEDIA_TYPE_AUDIO) {
+      AudioData audio = { 0 };
+
+#if 0
+      memcpy(&audio, device_buf + size, sizeof(AudioData));
+      ctx->audio.sample_fmt = audio.sample_fmt;
+      ctx->audio.frame_size = audio.frame_size;
+      ctx->audio.bits_per_sample_fmt = audio.bits_per_sample_fmt;
+#endif
+      CODEC_LOG (INFO,
+        "audio sample_fmt: %d\n", *(int *)(device_buf + size));
+
+      memcpy(&ctx->audio.sample_fmt, device_buf + size, sizeof(audio.sample_fmt));
+      size += sizeof(audio.sample_fmt);
+      memcpy(&ctx->audio.frame_size, device_buf + size, sizeof(audio.frame_size));
+      size += sizeof(audio.frame_size);
+      memcpy(&ctx->audio.bits_per_sample_fmt, device_buf + size, sizeof(audio.bits_per_sample_fmt));
+
+      CODEC_LOG (INFO,
+        "after init. audio sample_fmt: %d\n", ctx->audio.sample_fmt);
+    }
+  } else {
+    CODEC_LOG (ERR, "failed to open codec context\n");
+  }
+
+  return ret;
+}
+
+void
+_codec_decode_video_meta_to (int in_size, int idx, int64_t in_offset, uint8_t *device_buf)
+{
+  memcpy (device_buf, &in_size, sizeof(in_size));
+  memcpy (device_buf + sizeof(in_size), &idx, sizeof(idx));
+  memcpy (device_buf + sizeof(idx), &in_offset, sizeof(in_offset));
+}
+
+void
+_codec_decode_video_inbuf (uint8_t *in_buf, int in_size,
+                              uint8_t *device_buf)
+{
+  int size = 0;
+
+  memcpy(device_buf, &in_size, sizeof(in_size));
+  size = sizeof(in_size);
+  if (in_size > 0 ) {
+    memcpy (device_buf + size, in_buf, in_size);
+  }
+
+  CODEC_LOG (DEBUG, "decode_video. inbuf_size: %d\n", in_size);
+}
+
+
+int
+_codec_decode_video_meta_from (VideoData *video,
+                              int *got_picture_ptr,
+                              uint8_t *device_buf)
+{
+  int len = 0, size = 0;
+
+  CODEC_LOG (DEBUG, "decode_video. read data from qemu.\n");
+
+  memcpy (&len, device_buf, sizeof(len));
+  size = sizeof(len);
+  memcpy (got_picture_ptr,
+    device_buf + size, sizeof(*got_picture_ptr));
+  size += sizeof(*got_picture_ptr);
+  memcpy (video, device_buf + size, sizeof(VideoData));
+
+  CODEC_LOG (DEBUG, "decode_video. len: %d, have_data: %d\n",
+    len, *got_picture_ptr);
+
+  return len;
+}
+
+void
+_codec_decode_audio_meta_to (int in_size, uint8_t *device_buf)
+{
+  memcpy (device_buf, &in_size, sizeof(in_size));
+}
+
+
+void
+_codec_decode_audio_inbuf (uint8_t *in_buf, int in_size, uint8_t *device_buf)
+{
+  int size = 0;
+
+  memcpy (device_buf, &in_size, sizeof(in_size));
+  size = sizeof(in_size);
+  if (in_size > 0) {
+    memcpy (device_buf + size, in_buf, in_size);
+  }
+
+  CODEC_LOG (DEBUG, "decode_audio. inbuf_size: %d\n", in_size);
+}
+
+int
+_codec_decode_audio_meta_from (AudioData *audio, int *frame_size_ptr,
+                                uint8_t *device_buf)
+{
+  int len = 0, size = 0;
+
+  CODEC_LOG (DEBUG, "decode_audio. read data from device.\n");
+
+  memcpy (&audio->channel_layout,
+    device_buf, sizeof(audio->channel_layout));
+  size = sizeof(audio->channel_layout);
+  memcpy (&len, device_buf + size, sizeof(len));
+  size += sizeof(len);
+  memcpy (frame_size_ptr, device_buf + size, sizeof(*frame_size_ptr));
+
+  CODEC_LOG (DEBUG, "decode_audio. len: %d, frame_size: %d\n",
+          len, (*frame_size_ptr));
+
+  return len;
+}
+
+void
+_codec_decode_audio_outbuf (int outbuf_size, int16_t *samples, uint8_t *device_buf)
+{
+  CODEC_LOG (DEBUG, "decode_audio. read outbuf %d\n", outbuf_size);
+  memcpy (samples, device_buf, outbuf_size);
+}
+
+void
+_codec_encode_video_meta_to (int in_size, int64_t in_timestamp, uint8_t *device_buf)
+{
+  CODEC_LOG (DEBUG, "encode_video. write data to device.\n");
+
+  memcpy (device_buf, &in_size, sizeof(in_size));
+  memcpy (device_buf + sizeof(in_size), &in_timestamp, sizeof(in_timestamp));
+}
+
+void
+_codec_encode_video_inbuf (uint8_t *in_buf, int in_size, uint8_t *device_buf)
+{
+  int size = 0;
+
+  memcpy ((uint8_t *)device_buf, &in_size, sizeof(in_size));
+  size += sizeof(in_size);
+  if (in_size > 0) {
+    memcpy (device_buf + size, in_buf, in_size);
+  }
+  CODEC_LOG (DEBUG, "encode_video. inbuf_size: %d\n", in_size);
+}
+
+void
+_codec_encode_video_outbuf (int len, uint8_t *out_buf, uint8_t *device_buf)
+{
+//  int len, size;
+
+  CODEC_LOG (DEBUG, "encode_video. read data from device.\n");
+
+//  memcpy (&len, device_buf, sizeof(len));
+//  size = sizeof(len);
+  memcpy (out_buf, device_buf, len);
+
+//  return len;
+}
+
+void
+_codec_encode_audio_meta_to (int max_size, int in_size, uint8_t *device_buf)
+{
+  int size = 0;
+
+  CODEC_LOG (DEBUG, "encode_audio. write data to device.\n");
+
+  memcpy (device_buf, &in_size, sizeof(in_size));
+  size = sizeof(in_size);
+  memcpy (device_buf + size, &max_size, sizeof(max_size));
+}
+
+void
+_codec_encode_audio_inbuf (uint8_t *in_buf, int in_size, uint8_t *device_buf)
+{
+  int size = 0;
+
+  memcpy (device_buf, &in_size, sizeof(in_size));
+  size = sizeof(in_size);
+  if (in_size > 0) {
+    memcpy (device_buf + size, in_buf, in_size);
+  }
+  CODEC_LOG (DEBUG, "encode_audio. inbuf_size: %d\n", in_size);
+}
+
+int
+_codec_encode_audio_outbuf (uint8_t *out_buf, uint8_t *device_buf)
+{
+  int len, size;
+
+  CODEC_LOG (DEBUG, "encode_audio. read data from device\n");
+
+  memcpy (&len, (uint8_t *)device_buf, sizeof(len));
+  size = sizeof(len);
+  memcpy (out_buf, (uint8_t *)device_buf + size, len);
+
+  return len;
+}
diff --git a/src/gstmarumem.h b/src/gstmarumem.h
new file mode 100644 (file)
index 0000000..9aff8ff
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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_MARU_MEM_H__
+#define __GST_MARU_MEM_H__
+
+#include "gstmaru.h"
+
+void _codec_init_meta_to (CodecContext *ctx, CodecElement *codec, uint8_t *device_buf);
+
+int _codec_init_meta_from (CodecContext *ctx, int media_type, uint8_t *device_buf);
+
+void _codec_decode_video_meta_to (int in_size, int idx, int64_t in_offset, uint8_t *device_buf);
+
+void _codec_decode_video_inbuf (uint8_t *in_buf, int in_size, uint8_t *device_buf);
+
+int _codec_decode_video_meta_from (VideoData *video, int *got_picture_ptr,
+                                  uint8_t *device_buf);
+
+void _codec_decode_audio_meta_to (int in_size, uint8_t *device_buf);
+
+
+void _codec_decode_audio_inbuf (uint8_t *in_buf, int in_size,
+                                  uint8_t *device_buf);
+
+int _codec_decode_audio_meta_from (AudioData *audio, int *frame_size_ptr,
+                                  uint8_t *device_buf);
+
+void _codec_decode_audio_outbuf (int outbuf_size, int16_t *samples,
+                                  uint8_t *device_buf);
+
+void _codec_encode_video_meta_to (int in_size, int64_t in_timestamp, uint8_t *device_buf);
+
+void _codec_encode_video_inbuf (uint8_t *in_buf, int in_size,
+                                  uint8_t *device_buf);
+
+void _codec_encode_video_outbuf (int len, uint8_t *outbuf, uint8_t *device_buf);
+
+void _codec_encode_audio_meta_to (int max_size, int in_size, uint8_t *device_buf);
+
+void _codec_encode_audio_inbuf (uint8_t *in_buf, int in_size, uint8_t *device_buf);
+
+int _codec_encode_audio_outbuf (uint8_t *out_buf, uint8_t *device_buf);
+
+#endif
diff --git a/src/gstmaruutils.c b/src/gstmaruutils.c
new file mode 100644 (file)
index 0000000..91d929e
--- /dev/null
@@ -0,0 +1,1237 @@
+/*
+ * 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 "gstmaruutils.h"
+#include <gst/audio/multichannel.h>
+#include <gst/pbutils/codec-utils.h>
+
+gint
+gst_maru_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_maru_codectype_to_video_caps (CodecContext *ctx, const char *name,
+    gboolean encode, CodecElement *codec)
+{
+  GstCaps *caps;
+
+  GST_DEBUG ("context: %p, codec: %s, encode: %d, pixel format: %d",
+      ctx, name, encode, ctx->video.pix_fmt);
+
+  if (ctx) {
+    caps = gst_maru_pixfmt_to_caps (ctx->video.pix_fmt, ctx, name);
+  } else {
+    GstCaps *temp;
+    enum PixelFormat i;
+    CodecContext ctx;
+
+    caps = gst_caps_new_empty ();
+    for (i = 0; i <= PIX_FMT_NB; i++) {
+      temp = gst_maru_pixfmt_to_caps (i, encode ? &ctx : NULL, name);
+      if (temp != NULL) {
+        gst_caps_append (caps, temp);
+      }
+    }
+  }
+
+  return caps;
+}
+
+GstCaps *
+gst_maru_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 (ctx) {
+    caps = gst_maru_smpfmt_to_caps (ctx->audio.sample_fmt, ctx, name);
+#if 1
+  } else if (codec && codec->sample_fmts[0] != -1){
+    GstCaps *temp;
+    int i;
+
+    caps = gst_caps_new_empty ();
+    for (i = 0; codec->sample_fmts[i] != -1; i++) {
+      temp =
+          gst_maru_smpfmt_to_caps (codec->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_maru_smpfmt_to_caps (i, encode ? &ctx : NULL, name);
+      if (temp != NULL) {
+        gst_caps_append (caps, temp);
+      }
+    }
+  }
+
+  return caps;
+}
+
+GstCaps*
+gst_maru_codectype_to_caps (int media_type, CodecContext *ctx,
+    const char *name, gboolean encode)
+{
+  GstCaps *caps;
+
+  switch (media_type) {
+  case AVMEDIA_TYPE_VIDEO:
+    caps =
+        gst_maru_codectype_to_video_caps (ctx, name, encode, NULL);
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+    caps =
+        gst_maru_codectype_to_audio_caps (ctx, name, encode, NULL);
+   break;
+  default:
+    caps = NULL;
+    break;
+  }
+
+  return caps;
+}
+
+void
+gst_maru_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);
+  ctx->video.ticks_per_frame = 1;
+
+    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;
+      }
+    }
+//    printf ("get pixel format: %d, fourcc: %d\n", ctx->video.pix_fmt, fourcc);
+  } 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_maru_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);
+  gst_structure_get_int (str, "bitrate", &ctx->bit_rate);
+
+  if (!raw) {
+    return;
+  }
+
+  name = gst_structure_get_name (str);
+
+  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 (gst_structure_get_int (str, "width", &width) &&
+      gst_structure_get_int (str, "depth", &depth) &&
+      gst_structure_get_boolean (str, "signed", &signedness) &&
+      gst_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 = SAMPLE_FMT_S32;
+        }
+      }
+    }
+  }
+}
+
+void
+gst_maru_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);
+    GST_DEBUG ("extradata: %p, size: %d\n", data, 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 (!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');
+    }
+#if 0
+  } else if (strcmp (name, "h263p") == 0) {
+    gboolean val;
+
+    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_maru_caps_to_pixfmt (caps, ctx, FALSE);
+  // get_palette
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+    gst_maru_caps_to_smpfmt (caps, ctx, FALSE);
+    break;
+  default:
+    break;
+  }
+}
+
+void
+gst_maru_caps_to_codecname (const GstCaps *caps, gchar *codec_name, CodecContext *context)
+{
+  const gchar *mimetype;
+  const GstStructure *str;
+  gint wmvversion = 0;
+
+  str = gst_caps_get_structure (caps, 0);
+
+  mimetype = gst_structure_get_name (str);
+
+  if (!strcmp (mimetype, "video/x-wmv")) {
+    gint wmvversion = 0;
+
+    if (gst_structure_get_int (str, "wmvversion", &wmvversion)) {
+      switch (wmvversion) {
+        case 1:
+          g_strlcpy(codec_name, "wmv1", 32);
+          break;
+        case 2:
+          g_strlcpy(codec_name, "wmv2", 32);
+          break;
+        case 3:
+        {
+          guint32 fourcc;
+
+          g_strlcpy(codec_name, "wmv3", 32);
+
+          if (gst_structure_get_fourcc (str, "format", &fourcc)) {
+            if ((fourcc == GST_MAKE_FOURCC ('W', 'V', 'C', '1')) ||
+                (fourcc == GST_MAKE_FOURCC ('W', 'M', 'V', 'A'))) {
+              g_strlcpy(codec_name, "vc1", 32);
+            }
+          }
+        }
+          break;
+      }
+    }
+  }
+
+#if 0 // check other types if it needs.
+  } else if () {
+  }
+#endif
+
+#if 0
+  if (context != NULL) {
+    if (video == TRUE) {
+      context->codec_type = CODEC_TYPE_VIDEO;
+    } else if (audio == TRUE) {
+      context->codec_type = CODEC_TYPE_AUDIO;
+    } else {
+      context->codec_type = CODEC_TYPE_UNKNOWN;
+    }
+    context->codec_id = id;
+    gst_maru_caps_with_codecname (name, context->codec_type, caps, context);
+  }
+#endif
+
+  if (codec_name != NULL) {
+    GST_DEBUG ("The %s belongs to the caps %" GST_PTR_FORMAT, codec_name, caps);
+  } else {
+    GST_WARNING ("Couldn't figure out the name for caps %" GST_PTR_FORMAT, caps);
+  }
+}
+
+void
+gst_maru_caps_with_codectype (int media_type, const GstCaps *caps, CodecContext *ctx)
+{
+  if (ctx == NULL) {
+    return;
+  }
+
+  switch (media_type) {
+  case AVMEDIA_TYPE_VIDEO:
+    gst_maru_caps_to_pixfmt (caps, ctx, TRUE);
+    break;
+  case AVMEDIA_TYPE_AUDIO:
+    gst_maru_caps_to_smpfmt (caps, ctx, TRUE);
+    break;
+  default:
+    break;
+  }
+}
+
+GstCaps *
+gst_maru_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, NULL);
+
+    num = ctx->video.fps_d / ctx->video.ticks_per_frame;
+    denom = ctx->video.fps_n;
+
+    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 (strcmp (name, "h263") == 0) {
+      /* 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 if (strcmp (name, "none") == 0) {
+      GST_LOG ("default caps");
+    }
+  }
+
+  /* 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_maru_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_maru_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_maru_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_maru_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_maru_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_maru_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_maru_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_maru_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_maru_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_maru_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_maru_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_maru_video_caps_new (ctx, name, "video/x-h263",
+                  "variant", G_TYPE_STRING, "itu", NULL);
+    } else {
+      caps = gst_maru_video_caps_new (ctx, "none", "video/x-h263",
+                  "variant", G_TYPE_STRING, "itu", NULL);
+    }
+  } else if (strcmp (name, "h263p") == 0) {
+    caps = gst_maru_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
+    switch (ctx->codec_tag) {
+    case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
+      caps = gst_maru_video_caps_new (ctx, name, "video/x-divx",
+        "divxversion", G_TYPE_INT, 5, NULL);
+      break;
+    case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
+    default:
+      caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
+        "systemstream", G_TYPE_BOOLEAN, FALSE,
+        "mpegversion", G_TYPE_INT, 4, NULL);
+      break;
+    }
+    } else {
+      caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
+            "mpegversion", G_TYPE_INT, 4,
+            "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
+      if (encode) {
+        caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
+            "mpegversion", G_TYPE_INT, 4,
+            "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
+      } else {
+        gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
+            "video/x-divx", "divxversion", GST_TYPE_INT_RANGE, 4, 5, NULL));
+        gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
+            "video/x-xvid", NULL));
+        gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
+            "video/x-3ivx", NULL));
+      }
+    }
+  } else if (strcmp (name, "h264") == 0) {
+      caps = gst_maru_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_maru_video_caps_new (ctx, name, "video/x-msmpeg",
+          "msmpegversion", G_TYPE_INT, version, NULL);
+    if (!encode && !strcmp (name, "msmpeg4")) {
+       gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
+            "video/x-divx", "divxversion", G_TYPE_INT, 3, NULL));
+    }
+  } else if (strcmp (name, "wmv3") == 0) {
+    caps = gst_maru_video_caps_new (ctx, name, "video/x-wmv",
+                "wmvversion", G_TYPE_INT, 3, NULL);
+  } else if (strcmp (name, "vc1") == 0) {
+    caps = gst_maru_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_maru_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 (ctx && ctx->codecdata_size > 0) {
+          gst_codec_utils_aac_caps_set_level_and_profile (caps,
+            ctx->codecdata, ctx->codecdata_size);
+        }
+    }
+  } else if (strcmp (name, "ac3") == 0) {
+    caps = gst_maru_audio_caps_new (ctx, name, "audio/x-ac3", NULL);
+  } else if (strcmp (name, "mp3") == 0) {
+    if (encode) {
+      caps = gst_maru_audio_caps_new (ctx, name, "audio/mpeg",
+              "mpegversion", G_TYPE_INT, 1,
+              "layer", GST_TYPE_INT_RANGE, 1, 3, NULL);
+    } else {
+      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_maru_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_maru_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];
+
+void
+gst_maru_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_maru_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;
+}
+
+int
+gst_maru_align_size (int buf_size)
+{
+  int i, align_size;
+
+  align_size = buf_size / 1024;
+
+  for (i = 0; i < 14; i++) {
+    if (align_size < (1 << i)) {
+      align_size = 1024 * (1 << i);
+      break;
+    }
+  }
+
+  return align_size;
+}
diff --git a/src/gstmaruutils.h b/src/gstmaruutils.h
new file mode 100644 (file)
index 0000000..3b57176
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * 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_MARU_UTIL_H__
+#define __GST_MARU_UTIL_H__
+
+#include "gstmaru.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_maru_codectype_to_video_caps (CodecContext *ctx, const char *name,
+    gboolean encode, CodecElement *codec);
+
+GstCaps *gst_maru_codectype_to_audio_caps (CodecContext *ctx, const char *name,
+    gboolean encode, CodecElement *codec);
+
+
+GstCaps *gst_maru_codectype_to_caps (int media_type, CodecContext *ctx,
+    const char *name, gboolean encode);
+
+void gst_maru_caps_with_codecname (const char *name, int media_type,
+    const GstCaps *caps, CodecContext *ctx);
+
+void gst_maru_caps_with_codectype (int media_type, const GstCaps *caps, CodecContext *ctx);
+
+GstCaps *gst_maru_video_caps_new (CodecContext *ctx, const char *name,
+        const char *mimetype, const char *fieldname, ...);
+
+GstCaps *gst_maru_audio_caps_new (CodecContext *ctx, const char *name,
+        const char *mimetype, const char *fieldname, ...);
+
+GstCaps *gst_maru_pixfmt_to_caps (enum PixelFormat pix_fmt, CodecContext *ctx, const char *name);
+
+GstCaps *gst_maru_smpfmt_to_caps (int8_t sample_fmt, CodecContext *ctx, const char *name);
+
+GstCaps *gst_maru_codecname_to_caps (const char *name, CodecContext *ctx, gboolean encode);
+
+void gst_maru_init_pix_fmt_info (void);
+
+int gst_maru_avpicture_size (int pix_fmt, int width, int height);
+
+int gst_maru_align_size (int buf_size);
+
+gint gst_maru_smpfmt_depth (int smp_fmt);
+
+#endif