gstemulutils.c \
gstemulnewdec.c \
gstemulapi.c \
- gstemuldev.c
+ gstemuldev.c \
+ gstemulapi2.c
# compiler and linker flags used to compile this plugin, set in configure.ac
libgstemul_la_CFLAGS = $(GST_CFLAGS) -g
--- /dev/null
+/*
+ * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ * Copyright (c) 2008 Peter Ross
+ *
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_AUDIOCONVERT_H
+#define AVUTIL_AUDIOCONVERT_H
+
+#include <stdint.h>
+
+/**
+ * @file
+ * audio conversion routines
+ */
+
+/* Audio channel masks */
+#define AV_CH_FRONT_LEFT 0x00000001
+#define AV_CH_FRONT_RIGHT 0x00000002
+#define AV_CH_FRONT_CENTER 0x00000004
+#define AV_CH_LOW_FREQUENCY 0x00000008
+#define AV_CH_BACK_LEFT 0x00000010
+#define AV_CH_BACK_RIGHT 0x00000020
+#define AV_CH_FRONT_LEFT_OF_CENTER 0x00000040
+#define AV_CH_FRONT_RIGHT_OF_CENTER 0x00000080
+#define AV_CH_BACK_CENTER 0x00000100
+#define AV_CH_SIDE_LEFT 0x00000200
+#define AV_CH_SIDE_RIGHT 0x00000400
+#define AV_CH_TOP_CENTER 0x00000800
+#define AV_CH_TOP_FRONT_LEFT 0x00001000
+#define AV_CH_TOP_FRONT_CENTER 0x00002000
+#define AV_CH_TOP_FRONT_RIGHT 0x00004000
+#define AV_CH_TOP_BACK_LEFT 0x00008000
+#define AV_CH_TOP_BACK_CENTER 0x00010000
+#define AV_CH_TOP_BACK_RIGHT 0x00020000
+#define AV_CH_STEREO_LEFT 0x20000000 ///< Stereo downmix.
+#define AV_CH_STEREO_RIGHT 0x40000000 ///< See AV_CH_STEREO_LEFT.
+
+/** 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 AV_CH_LAYOUT_NATIVE 0x8000000000000000LL
+
+/* Audio channel convenience macros */
+#define AV_CH_LAYOUT_MONO (AV_CH_FRONT_CENTER)
+#define AV_CH_LAYOUT_STEREO (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT)
+#define AV_CH_LAYOUT_2_1 (AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER)
+#define AV_CH_LAYOUT_SURROUND (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER)
+#define AV_CH_LAYOUT_4POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_CENTER)
+#define AV_CH_LAYOUT_2_2 (AV_CH_LAYOUT_STEREO|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT)
+#define AV_CH_LAYOUT_QUAD (AV_CH_LAYOUT_STEREO|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)
+#define AV_CH_LAYOUT_5POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT)
+#define AV_CH_LAYOUT_5POINT1 (AV_CH_LAYOUT_5POINT0|AV_CH_LOW_FREQUENCY)
+#define AV_CH_LAYOUT_5POINT0_BACK (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)
+#define AV_CH_LAYOUT_5POINT1_BACK (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_LOW_FREQUENCY)
+#define AV_CH_LAYOUT_7POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)
+#define AV_CH_LAYOUT_7POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)
+#define AV_CH_LAYOUT_7POINT1_WIDE (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)
+#define AV_CH_LAYOUT_STEREO_DOWNMIX (AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT)
+
+#if 0
+/**
+ * Return a channel layout id that matches name, 0 if no match.
+ */
+int64_t av_get_channel_layout(const char *name);
+
+/**
+ * Return a description of a channel layout.
+ * If nb_channels is <= 0, it is guessed from the channel_layout.
+ *
+ * @param buf put here the string containing the channel layout
+ * @param buf_size size in bytes of the buffer
+ */
+void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, int64_t channel_layout);
+
+/**
+ * Return the number of channels in the channel layout.
+ */
+int av_get_channel_layout_nb_channels(int64_t channel_layout);
+#endif
+
+#endif /* AVUTIL_AUDIOCONVERT_H */
perror ("failed to open codec device");
}
-#if 0
ioctl (fd, CODEC_CMD_GET_VERSION, &version);
if (version != CODEC_VER) {
printf ("version conflict between device: %d, plugin: %d\n",
version, CODEC_VER);
return FALSE;
}
-#endif
buffer = mmap (NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (!buffer) {
memcpy (&data_length, (uint8_t *)buffer + size, sizeof(data_length));
size += sizeof(data_length);
if (!data_length) {
-// printf ("There is no more avcodec.\n");
break;
}
memcpy (elm, (uint8_t *)buffer + size, data_length);
size += data_length;
-#if 0
+#if 0
printf("codec: %s, longname: %s, decode: %d, media: %d\n",
elm->name, elm->longname, elm->codec_type, elm->media_type);
#endif
{
GST_DEBUG_CATEGORY_INIT (emul_debug,
"tizen-emul", 0, "Tizen Emulator Codec Elements");
- gboolean ret;
gst_emul_init_pix_fmt_info ();
return FALSE;
}
- ret = gst_emuldec_register (plugin, codec_element);
- if (!ret) {
+ if (!gst_emuldec_register (plugin, codec_element)) {
GST_ERROR ("failed to register decoder elements");
return FALSE;
}
#if 0
- ret = gst_emulenc_register (plugin, codec_element);
- if (!ret) {
+ if (!gst_emulenc_register (plugin, codec_element)) {
GST_ERROR ("failed to register encoder elements");
return FALSE;
}
#endif
+ while ((codec_element = g_list_next (codec_element))) {
+ g_list_free (codec_element);
+ }
+
return TRUE;
}
#include "gstemulcommon.h"
#include "gstemulapi.h"
+#include "gstemulapi2.h"
#include "gstemuldev.h"
-gboolean
+enum {
+ CODEC_USER_FROM = 0,
+ CODEC_USER_TO,
+};
+
+int
emul_avcodec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
{
int fd;
- void *mmapbuf;
- int size = 0;
- gboolean ret = TRUE;
+ uint8_t *mmapbuf;
+ int size = 0, ret = 0;
+ int usable, copyback;
CodecIOParams params;
- printf ("enter: %s\n", __func__);
+ CODEC_LOG (DEBUG, "enter: %s\n", __func__);
fd = dev->fd;
if (fd < 0) {
GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
- return FALSE;
+ return -1;
}
- mmapbuf = dev->buf;
+ mmapbuf = (uint8_t *)dev->buf;
if (!mmapbuf) {
GST_ERROR ("failed to get mmaped memory address.\n");
- return FALSE;
+ return -1;
}
-// printf("codec_init media_type: %d, codec_type: %d, name: %s\n",
-// media_type, codec_type, name);
-
- /* copy basic info to initialize codec on the host side.
- * e.g. width, height, FPS ant etc. */
- memcpy ((uint8_t *)mmapbuf, &codec->media_type, sizeof(codec->media_type));
- size = sizeof(codec->media_type);
- memcpy ((uint8_t *)mmapbuf + size, &codec->codec_type, sizeof(codec->codec_type));
- size += sizeof(codec->codec_type);
- memcpy ((uint8_t *)mmapbuf + size, codec->name, sizeof(codec->name));
- size += sizeof(codec->name);
-
- switch (codec->media_type) {
- case AVMEDIA_TYPE_VIDEO:
- memcpy ((uint8_t *)mmapbuf + size, &ctx->video, sizeof(ctx->video));
- size += sizeof(ctx->video);
- break;
- case AVMEDIA_TYPE_AUDIO:
- memcpy ((uint8_t *)mmapbuf + size, &ctx->audio, sizeof(ctx->audio));
- size += sizeof(ctx->audio);
- break;
- default:
- GST_ERROR ("media type is unknown.\n");
- ret = FALSE;
- break;
- }
+ if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
+ emul_avcodec_init_to (ctx, codec, mmapbuf);
+ } else {
+ copyback = CODEC_USER_FROM;
+ ioctl (fd, CODEC_CMD_ADD_TASK_QUEUE, ©back);
+
+ while (1) {
+ ioctl (fd, CODEC_CMD_COPY_TO_DEVICE_MEM, &usable);
+ if (usable) {
+ CODEC_LOG (DEBUG, "[init][%d] failure.\n", __LINE__);
+ continue;
+ }
+
+ emul_avcodec_init_to (ctx, codec, mmapbuf);
+
+#if 0
+ CODEC_LOG (DEBUG, "[init] write data to qemu.\n");
+ size = sizeof(size);
+ memcpy (mmapbuf + size,
+ &codec->media_type, sizeof(codec->media_type));
+ size += sizeof(codec->media_type);
+ memcpy (mmapbuf + size, &codec->codec_type, sizeof(codec->codec_type));
+ size += sizeof(codec->codec_type);
+ memcpy (mmapbuf + size, codec->name, sizeof(codec->name));
+ size += sizeof(codec->name);
+
+ if (codec->media_type == AVMEDIA_TYPE_VIDEO) {
+ memcpy (mmapbuf + size, &ctx->video, sizeof(ctx->video));
+ size += sizeof(ctx->video);
+ } else if (codec->media_type == AVMEDIA_TYPE_AUDIO) {
+ memcpy (mmapbuf + size, &ctx->audio, sizeof(ctx->audio));
+ size += sizeof(ctx->audio);
+ } else {
+ GST_ERROR ("media type is unknown.\n");
+ ret = -1;
+ break;;
+ }
+
+ memcpy (mmapbuf + size,
+ &ctx->codecdata_size, sizeof(ctx->codecdata_size));
+ size += sizeof(ctx->codecdata_size);
+ if (ctx->codecdata_size) {
+ memcpy (mmapbuf + size, ctx->codecdata, ctx->codecdata_size);
+ size += ctx->codecdata_size;
+ }
+ size -= sizeof(size);
+ memcpy (mmapbuf, &size, sizeof(size));
+
+ CODEC_LOG (DEBUG, "[init] write data: %d\n", size);
+#endif
+ break;
+ }
- memcpy ((uint8_t *)mmapbuf + size, &ctx->codecdata_size, sizeof(ctx->codecdata_size));
- size += sizeof(ctx->codecdata_size);
- if (ctx->codecdata_size) {
- memcpy ((uint8_t *)mmapbuf + size, ctx->codecdata, ctx->codecdata_size);
+#if 0
+ if (ret < 0) {
+ return ret;
+ }
+#endif
}
CODEC_PARAM_INIT (params);
params.api_index = CODEC_INIT;
- params.ctx_index = 0;
+ params.mem_offset = dev->mem_info.offset;
CODEC_WRITE_TO_QEMU (fd, ¶ms, 1);
- if (codec->media_type == AVMEDIA_TYPE_AUDIO) {
- memcpy (&ctx->audio.sample_fmt,
- (uint8_t *)mmapbuf, sizeof(ctx->audio.sample_fmt));
+ if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
+ ret = emul_avcodec_init_from (ctx, codec, mmapbuf);
+ } else {
+ while (1) {
+ ioctl (fd, CODEC_CMD_COPY_FROM_DEVICE_MEM, &usable);
+ if (usable) {
+ CODEC_LOG (DEBUG, "[init][%d] failure.\n", __LINE__);
+ continue;
+ }
+
+ ret = emul_avcodec_init_from (ctx, codec, mmapbuf);
+#if 0
+ CODEC_LOG (DEBUG, "[init] read data from qemu.\n");
+ if (codec->media_type == AVMEDIA_TYPE_AUDIO) {
+ memcpy (&ctx->audio.sample_fmt,
+ (uint8_t *)mmapbuf, sizeof(ctx->audio.sample_fmt));
+ size += sizeof(ctx->audio.sample_fmt);
+ CODEC_LOG (DEBUG, "[init] AUDIO sample_fmt: %d\n", ctx->audio.sample_fmt);
+ }
+ CODEC_LOG (DEBUG, "[init] %s\n", codec->media_type ? "AUDIO" : "VIDEO");
+ memcpy (&ret, (uint8_t *)mmapbuf + size, sizeof(ret));
+ size += sizeof(ret);
+ memcpy (&ctx->index, (uint8_t *)mmapbuf + size, sizeof(ctx->index));
+ ctx->codec = codec;
+ CODEC_LOG (DEBUG, "context index: %d\n", ctx->index);
+#endif
+ break;
+ }
+ ioctl (fd, CODEC_CMD_REMOVE_TASK_QUEUE, ©back);
}
- ctx->codec = codec;
-
- printf ("leave: %s\n", __func__);
+ CODEC_LOG (DEBUG, "leave: %s, ret: %d\n", __func__, ret);
return ret;
}
emul_avcodec_deinit (CodecContext *ctx, CodecDevice *dev)
{
int fd;
- void *mmapbuf;
+ int copyback, usable;
+ void *mmapbuf = NULL;
CodecIOParams params;
- printf ("enter: %s\n", __func__);
+ CODEC_LOG (DEBUG, "enter: %s\n", __func__);
fd = dev->fd;
if (fd < 0) {
return;
}
+#if 0
+ copyback = CODEC_USER_FROM;
+ ioctl (fd, CODEC_CMD_ADD_TASK_QUEUE, ©back);
+
+ while (1) {
+ ioctl (fd, CODEC_CMD_COPY_TO_DEVICE_MEM, &usable);
+ if (usable) {
+ CODEC_LOG (DEBUG, "[deinit][%d] failure.\n", __LINE__);
+ continue;
+ }
+ }
+#endif
+
CODEC_PARAM_INIT (params);
params.api_index = CODEC_DEINIT;
- params.ctx_index = 0;
+ params.ctx_index = ctx->index;
+ params.mem_offset = dev->mem_info.offset;
CODEC_WRITE_TO_QEMU (fd, ¶ms, 1);
-#if 0
- /* close device fd and release mapped memory region */
- gst_emul_codec_device_close (dev);
-#endif
+// ioctl (fd, CODEC_CMD_REMOVE_TASK_QUEUE, ©back);
- printf ("leave: %s\n", __func__);
+ CODEC_LOG (DEBUG, "leave: %s\n", __func__);
}
int
-emul_avcodec_decode_video (CodecContext *ctx, guint8 *in_buf, guint in_size,
- GstBuffer **out_buf, int *got_picture_ptr, CodecDevice *dev)
+emul_avcodec_decode_video (CodecContext *ctx, uint8_t *in_buf, int in_size,
+ GstBuffer **out_buf, int *got_picture_ptr, CodecDevice *dev)
{
int fd;
- void *mmapbuf;
+ uint8_t *mmapbuf = NULL;
int len = 0, size = 0;
- guint out_size;
+ int copyback, usable;
CodecIOParams params;
- *out_buf = NULL;
-
- printf ("enter: %s\n", __func__);
+ CODEC_LOG (DEBUG, "enter: %s\n", __func__);
fd = dev->fd;
if (fd < 0) {
return -1;
}
- mmapbuf = dev->buf;
+ mmapbuf = (uint8_t *)dev->buf;
if (!mmapbuf) {
GST_ERROR ("failed to get mmaped memory address\n");
return -1;
}
- memcpy ((uint8_t *)mmapbuf, &in_size, sizeof(guint));
- size = sizeof(guint);
-// memcpy ((uint8_t *)mmapbuf + size, &dec_info->timestamp, sizeof(GstClockTime));
-// size += sizeof(GstClockTime);
- memcpy ((uint8_t *)mmapbuf + size, in_buf, in_size);
+ if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
+ emul_avcodec_decode_video_to (in_buf, in_size, mmapbuf);
+ } else {
+ copyback = CODEC_USER_FROM;
+ ioctl (fd, CODEC_CMD_ADD_TASK_QUEUE, ©back);
+
+ while (1) {
+ ioctl (fd, CODEC_CMD_COPY_TO_DEVICE_MEM, &usable);
+ if (usable) {
+ CODEC_LOG (DEBUG, "[decode_video] wait 1.\n");
+ continue;
+ }
+
+ emul_avcodec_decode_video_to (in_buf, in_size, mmapbuf);
+#if 0
+ CODEC_LOG (DEBUG, "[decode_video] write data to qemu\n");
+ size = sizeof(size);
+ memcpy (mmapbuf + size, &in_size, sizeof(in_size));
+ size += sizeof(in_size);
+ if (in_size > 0) {
+ memcpy (mmapbuf + size, in_buf, in_size);
+ size += in_size;
+ }
+
+ size -= sizeof(size);
+ CODEC_LOG (DEBUG, "[decode_video] total: %d, inbuf size: %d\n", size, in_size);
+ memcpy(mmapbuf, &size, sizeof(size));
+#endif
+ break;
+ }
+ }
/* provide raw image for decoding to qemu */
CODEC_PARAM_INIT (params);
params.api_index = CODEC_DECODE_VIDEO;
- params.ctx_index = 0;
+ params.ctx_index = ctx->index;
+ params.mem_offset = dev->mem_info.offset;
CODEC_WRITE_TO_QEMU (fd, ¶ms, 1);
- memcpy (&len, (uint8_t *)mmapbuf, sizeof(len));
- size = sizeof(len);
+ if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
+ len = emul_avcodec_decode_video_from (ctx, got_picture_ptr, mmapbuf);
+ } else {
+ while (1) {
+ ioctl (fd, CODEC_CMD_COPY_FROM_DEVICE_MEM, &usable);
+ if (usable) {
+ CODEC_LOG (DEBUG, "[decode_video] wait 2.\n");
+ continue;
+ }
+
+ len = emul_avcodec_decode_video_from (ctx, got_picture_ptr, mmapbuf);
+#if 0
+ CODEC_LOG (DEBUG, "[decode_video] read data from qemu.\n");
+ memcpy (&len, (uint8_t *)mmapbuf, sizeof(len));
+ size = sizeof(len);
+ memcpy (got_picture_ptr,
+ (uint8_t *)mmapbuf + size, sizeof(*got_picture_ptr));
+ size += sizeof(*got_picture_ptr);
+ memcpy (&ctx->video, (uint8_t *)mmapbuf + size, sizeof(ctx->video));
+
+ CODEC_LOG (DEBUG, "[decode_video] len: %d, have_date: %d\n", len, *got_picture_ptr);
+#endif
+ break;
+ }
+ ioctl (fd, CODEC_CMD_REMOVE_TASK_QUEUE, ©back);
+ }
+ CODEC_LOG (DEBUG, "leave: %s\n", __func__);
+ return len;
+}
- printf ("leave: %s\n", __func__);
+void
+emul_av_picture_copy (CodecContext *ctx, uint8_t *pict, uint32_t pict_size, CodecDevice *dev)
+{
+ int fd;
+ void *mmapbuf = NULL;
+ int copyback, usable;
+ CodecIOParams params;
- return len;
+ 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;
+ }
+
+ if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
+ } else {
+#if 1
+ copyback = CODEC_USER_FROM;
+ ioctl (fd, CODEC_CMD_ADD_TASK_QUEUE, ©back);
+
+ while (1) {
+ ioctl (fd, CODEC_CMD_COPY_TO_DEVICE_MEM, &usable);
+ if (usable) {
+ CODEC_LOG (DEBUG, "[decode_video] wait 1.\n");
+ continue;
+ }
+ break;
+ }
+ }
+#endif
+
+// printf("before av_picture_copy. ctx: %d\n", ctx->index);
+
+ CODEC_PARAM_INIT (params);
+ params.api_index = CODEC_PICTURE_COPY;
+ params.ctx_index = ctx->index;
+ params.mem_offset = dev->mem_info.offset;
+ CODEC_WRITE_TO_QEMU (fd, ¶ms, 1);
+
+ CODEC_LOG (DEBUG, "[copy_frame] after write.\n");
+
+ if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
+ CODEC_LOG (DEBUG, "[copy_frame] read data from qemu.\n");
+ memcpy (pict, mmapbuf, pict_size);
+ } else {
+ while (1) {
+ ioctl (fd, CODEC_CMD_COPY_FROM_DEVICE_MEM, &usable);
+ if (usable) {
+ CODEC_LOG (DEBUG, "[copy_frame] wait 2.\n");
+ continue;
+ }
+
+ CODEC_LOG (DEBUG, "[copy_frame] read data from qemu.\n");
+ memcpy (pict, mmapbuf, pict_size);
+ break;
+ }
+ ioctl (fd, CODEC_CMD_REMOVE_TASK_QUEUE, ©back);
+ }
+
+ CODEC_LOG (DEBUG, "leave: %s\n", __func__);
}
int
emul_avcodec_decode_audio (CodecContext *ctx, int16_t *samples,
- gint *frame_size_ptr, guint8 *in_buf, guint in_size, CodecDevice *dev)
+ int *frame_size_ptr, uint8_t *in_buf, int in_size, CodecDevice *dev)
{
int fd;
- void *mmapbuf = NULL;
- int size = 0;
- gint out_size = 0, len;
+ uint8_t *mmapbuf = NULL;
+ int size = 0, len;
+ int copyback, usable;
CodecIOParams params;
+ 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;
+ mmapbuf = (uint8_t *)dev->buf;
if (!mmapbuf) {
GST_ERROR("failed to get mmaped memory address\n");
return -1;
}
- memcpy ((uint8_t *)mmapbuf, &in_size, sizeof(guint));
- size = sizeof(guint);
- if (in_size > 0) {
- memcpy ((uint8_t *)mmapbuf + size, in_buf, in_size);
+ if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
+ emul_avcodec_decode_audio_to (in_buf, in_size, mmapbuf);
+ } else {
+ copyback = CODEC_USER_FROM;
+ ioctl (fd, CODEC_CMD_ADD_TASK_QUEUE, ©back);
+
+ while (1) {
+ ioctl (fd, CODEC_CMD_COPY_TO_DEVICE_MEM, &usable);
+ if (usable) {
+ CODEC_LOG (DEBUG, "[decode_audio][%d] wait 1.\n", __LINE__);
+ continue;
+ }
+
+ emul_avcodec_decode_audio_to (in_buf, in_size, mmapbuf);
+#if 0
+ size = sizeof(size);
+ memcpy (mmapbuf + size, &in_size, sizeof(in_size));
+ size += sizeof(in_size);
+ if (in_size > 0) {
+ memcpy (mmapbuf + size, in_buf, in_size);
+ size += in_size;
+ }
+
+ size -= sizeof(size);
+ memcpy (mmapbuf, &size, sizeof(size));
+ CODEC_LOG (DEBUG, "[decode_audio] write size: %d, inbuf_size: %d\n", size, in_size);
+#endif
+ break;
+ }
}
CODEC_PARAM_INIT (params);
params.api_index = CODEC_DECODE_AUDIO;
- params.ctx_index = 0;
- params.device_mem_offset = 0;
+ params.ctx_index = ctx->index;
+ params.mem_offset = dev->mem_info.offset;
CODEC_WRITE_TO_QEMU (fd, ¶ms, 1);
- memcpy (&ctx->audio.channel_layout,
- (uint8_t *)mmapbuf, sizeof(ctx->audio.channel_layout));
- size = sizeof(ctx->audio.channel_layout);
- memcpy (&len, (uint8_t *)mmapbuf + size, sizeof(len));
- size += sizeof(len);
- memcpy (frame_size_ptr, (uint8_t *)mmapbuf + size, sizeof(*frame_size_ptr));
- size += sizeof(*frame_size_ptr);
- if (len > 0) {
- memcpy (samples, (uint8_t *)mmapbuf + size, FF_MAX_AUDIO_FRAME_SIZE);
+ if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
+ len = emul_avcodec_decode_audio_from (ctx, frame_size_ptr, samples, mmapbuf);
+ } else {
+ while (1) {
+ ioctl (fd, CODEC_CMD_COPY_FROM_DEVICE_MEM, &usable);
+ if (usable) {
+ CODEC_LOG (DEBUG, "[decode_audio][%d] wait 2.\n", __LINE__);
+ continue;
+ }
+
+ len = emul_avcodec_decode_audio_from (ctx, frame_size_ptr, samples, mmapbuf);
+#if 0
+ CODEC_LOG (DEBUG, "[decode_audio] read data\n");
+ memcpy (&ctx->audio.channel_layout,
+ (uint8_t *)mmapbuf, sizeof(ctx->audio.channel_layout));
+ size = sizeof(ctx->audio.channel_layout);
+ memcpy (&len, (uint8_t *)mmapbuf + size, sizeof(len));
+ size += sizeof(len);
+ memcpy (frame_size_ptr, (uint8_t *)mmapbuf + size, sizeof(*frame_size_ptr));
+ size += sizeof(*frame_size_ptr);
+ CODEC_LOG (DEBUG, "[decode_audio] len: %d, channel_layout: %lld\n",
+ len, ctx->audio.channel_layout);
+ if (len > 0) {
+ memcpy (samples, (uint8_t *)mmapbuf + size, FF_MAX_AUDIO_FRAME_SIZE);
+ }
+#endif
+ break;
+ }
+ ioctl (fd, CODEC_CMD_REMOVE_TASK_QUEUE, ©back);
}
+ CODEC_LOG (DEBUG, "leave: %s\n", __func__);
return len;
}
int
-emul_avcodec_encode_video (CodecContext *ctx, guint8 *in_buf, guint in_size,
- GstBuffer **out_buf, CodecDevice *dev)
+emul_avcodec_encode_video (CodecContext *ctx, uint8_t*out_buf, int out_size,
+ uint8_t *in_buf, int in_size, CodecDevice *dev)
{
int fd;
void *mmapbuf;
int len = 0, outbuf_size, size = 0;
+ int copyback, usable;
CodecIOParams params;
- printf ("enter: %s\n", __func__);
+ CODEC_LOG (DEBUG, "enter: %s\n", __func__);
fd = dev->fd;
if (fd < 0) {
return FALSE;
}
- memcpy ((uint8_t *)mmapbuf + size, &in_size, sizeof(guint));
- size += sizeof(guint);
-#if 0
- memcpy ((uint8_t *)mmapbuf + size, &in_timestamp, sizeof(GstClockTime));
- size += sizeof(GstClockTime);
-#endif
- memcpy ((uint8_t *)mmapbuf + size, in_buf, in_size);
+ copyback = CODEC_USER_FROM;
+ ioctl (fd, CODEC_CMD_ADD_TASK_QUEUE, ©back);
+
+ while (1) {
+ ioctl (fd, CODEC_CMD_COPY_TO_DEVICE_MEM, &usable);
+ if (usable) {
+ CODEC_LOG (DEBUG, "[init][%d] failure.\n", __LINE__);
+// sleep(1);
+ continue;
+ }
+
+ CODEC_LOG (DEBUG, "[encode_video] write data to qemu\n");
+ memcpy ((uint8_t *)mmapbuf + size, &in_size, sizeof(guint));
+ size += sizeof(guint);
+ memcpy ((uint8_t *)mmapbuf + size, in_buf, in_size);
+ break;
+ }
CODEC_PARAM_INIT (params);
- params.api_index = CODEC_DECODE_AUDIO;
- params.ctx_index = 0;
+ params.api_index = CODEC_ENCODE_VIDEO;
+ params.ctx_index = ctx->index;
+ params.mem_offset = dev->mem_info.offset;
CODEC_WRITE_TO_QEMU (fd, ¶ms, 1);
+ size = 0;
+ while (1) {
+ copyback = CODEC_USER_TO;
+ ioctl (fd, CODEC_CMD_COPY_FROM_DEVICE_MEM, ©back);
+
#if 0
size = 0;
memcpy (&out_size, (uint8_t *)mmapbuf + size, sizeof(uint));
size += sizeof(guint);
ret = gst_pad_alloc_buffer_and_set_caps (emulenc->srcpad,
- GST_BUFFER_OFFSET_NONE, out_size,
- GST_PAD_CAPS (emulenc->srcpad), out_buf);
+ GST_BUFFER_OFFSET_NONE, out_size,
+ GST_PAD_CAPS (emulenc->srcpad), out_buf);
gst_buffer_set_caps (*out_buf, GST_PAD_CAPS (emulenc->srcpad));
if (GST_BUFFER_DATA(*out_buf)) {
- memcpy (GST_BUFFER_DATA(*out_buf), (uint8_t *)mmapbuf + size, out_size);
+ memcpy (GST_BUFFER_DATA(*out_buf), (uint8_t *)mmapbuf + size, out_size);
} else {
- pritnf ("failed to allocate output buffer\n");
+ pritnf ("failed to allocate output buffer\n");
}
#endif
+ break;
+ }
+ ioctl (fd, CODEC_CMD_REMOVE_TASK_QUEUE, ©back);
- printf ("leave: %s\n", __func__);
+ CODEC_LOG (DEBUG, "leave: %s\n", __func__);
return len;
}
int
-emul_avcodec_encode_audio (CodecContext *ctx, CodecDevice *dev)
+emul_avcodec_encode_audio (CodecContext *ctx, uint8_t *outbuf, int outbuf_size,
+ const short *inbuf, int inbuf_size, CodecDevice *dev)
{
int fd;
void *mmapbuf;
int len = 0, size = 0;
+ int copyback, usable;
CodecIOParams params;
- printf ("enter: %s\n", __func__);
+ CODEC_LOG (DEBUG, "enter: %s\n", __func__);
fd = dev->fd;
if (fd < 0) {
return FALSE;
}
-#if 0
- memcpy ((uint8_t *)mmapbuf + size, &in_size, sizeof(guint));
- size += sizeof(guint);
- memcpy ((uint8_t *)mmapbuf + size, &in_timestamp, sizeof(GstClockTime));
- size += sizeof(GstClockTime);
- memcpy ((uint8_t *)mmapbuf + size, in_buf, in_size);
-#endif
+ copyback = CODEC_USER_FROM;
+ ioctl (fd, CODEC_CMD_ADD_TASK_QUEUE, ©back);
+
+ while (1) {
+ ioctl (fd, CODEC_CMD_COPY_TO_DEVICE_MEM, &usable);
+ if (usable) {
+ CODEC_LOG (DEBUG, "[decode_video] wait.\n");
+// sleep(1);
+ continue;
+ }
+
+ CODEC_LOG (DEBUG, "[encode_audio] write data to qemu\n");
+ memcpy ((uint8_t *)mmapbuf + size, &inbuf_size, sizeof(inbuf_size));
+ size += sizeof(inbuf_size);
+ memcpy ((uint8_t *)mmapbuf + size, inbuf, inbuf_size);
+ break;
+ }
CODEC_PARAM_INIT (params);
- params.api_index = CODEC_DECODE_AUDIO;
- params.ctx_index = 0;
+ params.api_index = CODEC_ENCODE_AUDIO;
+ params.ctx_index = ctx->index;
+ params.mem_offset = dev->mem_info.offset;
CODEC_WRITE_TO_QEMU (fd, ¶ms, 1);
-#if 0
- size = 0;
- memcpy (&out_size, (uint8_t *)mmapbuf + size, sizeof(uint));
- size += sizeof(guint);
-
- *out_buf = gst_buffer_new();
- GST_BUFFER_DATA (out_buf) = GST_BUFFER_MALLOCDATA (out_buf) = av_malloc (out_size);
- GST_BUFFER_SIZE (out_buf) = out_size;
- // GST_BUFFER_FREE_FUNC (out_buf) = g_free;
- if (GST_PAD_CAPS(emulenc->srcpad)) {
- gst_buffer_set_caps (*out_buf, GST_PAD_CAPS (emulenc->srcpad));
- }
+ while (1) {
+ ioctl (fd, CODEC_CMD_COPY_FROM_DEVICE_MEM, &usable);
+ if (usable) {
+ CODEC_LOG (DEBUG, "[decode_video] wait. 2\n");
+// sleep(1);
+ continue;
+ }
- if (GST_BUFFER_DATA(*out_buf)) {
- memcpy (GST_BUFFER_DATA(*out_buf), (uint8_t *)mmapbuf + size, out_size);
- } else {
- pritnf ("failed to allocate output buffer\n");
+ CODEC_LOG (DEBUG, "[encode_audio] read data from qemu\n");
+ memcpy (outbuf, (uint8_t *)mmapbuf, outbuf_size);
+ break;
}
-#endif
+ ioctl (fd, CODEC_CMD_REMOVE_TASK_QUEUE, NULL);
- printf ("leave: %s\n", __func__);
+ CODEC_LOG (DEBUG, "leave: %s\n", __func__);
return len;
}
#include "gstemulcommon.h"
-gboolean emul_avcodec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev);
-int emul_avcdoec_deinit (CodecContext *ctx, CodecDevice *dev);
+int emul_avcodec_init (CodecContext *ctx, CodecElement *codec,
+ CodecDevice *dev);
+
+void emul_avcodec_deinit (CodecContext *ctx, CodecDevice *dev);
+
+int emul_avcodec_decode_video (CodecContext *ctx, uint8_t *in_buf,
+ int in_size, GstBuffer **out_buf,
+ int *got_picture_ptr, CodecDevice *dev);
-int emul_avcodec_decode_video (CodecContext *ctx, guint8 *in_buf, guint in_size,
- GstBuffer **out_buf, int *got_picture_ptr, CodecDevice *dev);
int emul_avcodec_decode_audio (CodecContext *ctx, int16_t *samples,
- gint *frame_size_ptr, guint8 *in_buf, guint in_size, CodecDevice *dev);
+ int *frame_size_ptr, uint8_t *in_buf,
+ int in_size, CodecDevice *dev);
+
+int emul_avcodec_encode_video (CodecContext *ctx, uint8_t*out_buf, int out_size,
+ uint8_t *in_buf, int in_size, CodecDevice *dev);
+
+int emul_avcodec_encode_audio (CodecContext *ctx, uint8_t *outbuf,
+ int outbuf_size, const short *inbuf,
+ int inbuf_size, CodecDevice *dev);
-int emul_avcodec_encode_video (CodecContext *ctx, guint8 *in_buf, guint in_size,
- GstBuffer **out_buf, CodecDevice *dev);
-int emul_avcodec_encode_audio (CodecContext *ctx, CodecDevice *dev);
+void
+emul_av_picture_copy (CodecContext *ctx, uint8_t *pict, uint32_t pict_size, CodecDevice *dev);
#endif /* __GST_EMUL_API_H__ */
--- /dev/null
+/*
+ * 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"
+
+void
+emul_avcodec_init_to (CodecContext *ctx, CodecElement *codec, uint8_t *device_buf)
+{
+ int size = 0, codec_size;
+
+ CODEC_LOG (DEBUG, "[init] write data to qemu.\n");
+ size = sizeof(size);
+ codec_size =
+ sizeof(codec->media_type) + sizeof(codec->codec_type) + sizeof(codec->name);
+
+#if 0
+ memcpy (device_buf + size,
+ &codec->media_type, sizeof(codec->media_type));
+ size += sizeof(codec->media_type);
+ memcpy (device_buf + size, &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);
+#endif
+ memcpy (device_buf + size, codec, codec_size);
+ size += codec_size;
+
+ if (codec->media_type == AVMEDIA_TYPE_VIDEO) {
+ memcpy (device_buf + size, &ctx->video, sizeof(ctx->video));
+ size += sizeof(ctx->video);
+ } else if (codec->media_type == AVMEDIA_TYPE_AUDIO) {
+ memcpy (device_buf + size, &ctx->audio, sizeof(ctx->audio));
+ size += sizeof(ctx->audio);
+ } else {
+ GST_ERROR ("media type is unknown.\n");
+ return;
+ }
+
+ memcpy (device_buf + size,
+ &ctx->codecdata_size, sizeof(ctx->codecdata_size));
+ size += sizeof(ctx->codecdata_size);
+ if (ctx->codecdata_size) {
+ memcpy (device_buf + size, ctx->codecdata, ctx->codecdata_size);
+ size += ctx->codecdata_size;
+ }
+ size -= sizeof(size);
+ memcpy (device_buf, &size, sizeof(size));
+
+ CODEC_LOG (DEBUG, "[init] write data: %d\n", size);
+}
+
+int
+emul_avcodec_init_from (CodecContext *ctx, CodecElement *codec, uint8_t *device_buf)
+{
+ int ret = 0, size = 0;
+
+ CODEC_LOG (DEBUG, "[init] read data from qemu.\n");
+ if (codec->media_type == AVMEDIA_TYPE_AUDIO) {
+ memcpy (&ctx->audio.sample_fmt,
+ (uint8_t *)device_buf, sizeof(ctx->audio.sample_fmt));
+ size += sizeof(ctx->audio.sample_fmt);
+ CODEC_LOG (DEBUG, "[init] AUDIO sample_fmt: %d\n", ctx->audio.sample_fmt);
+ }
+ CODEC_LOG (DEBUG, "[init] %s\n", codec->media_type ? "AUDIO" : "VIDEO");
+ memcpy (&ret, (uint8_t *)device_buf + size, sizeof(ret));
+ size += sizeof(ret);
+ memcpy (&ctx->index, (uint8_t *)device_buf + size, sizeof(ctx->index));
+ ctx->codec = codec;
+ CODEC_LOG (DEBUG, "context index: %d\n", ctx->index);
+
+ return ret;
+}
+
+void
+emul_avcodec_decode_video_to (uint8_t *in_buf, int in_size, uint8_t *device_buf)
+{
+ int ret = 0, size = 0;
+
+ CODEC_LOG (DEBUG, "[decode_video] write data to qemu\n");
+ size = sizeof(size);
+ memcpy (device_buf + size, &in_size, sizeof(in_size));
+ size += sizeof(in_size);
+ if (in_size > 0) {
+ memcpy (device_buf + size, in_buf, in_size);
+ size += in_size;
+ }
+
+ size -= sizeof(size);
+ CODEC_LOG (DEBUG, "[decode_video] total: %d, inbuf size: %d\n", size, in_size);
+ memcpy(device_buf, &size, sizeof(size));
+}
+
+int
+emul_avcodec_decode_video_from (CodecContext *ctx, 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, (uint8_t *)device_buf, sizeof(len));
+ size = sizeof(len);
+ memcpy (got_picture_ptr,
+ (uint8_t *)device_buf + size, sizeof(*got_picture_ptr));
+ size += sizeof(*got_picture_ptr);
+ memcpy (&ctx->video, (uint8_t *)device_buf + size, sizeof(ctx->video));
+
+ CODEC_LOG (DEBUG, "[decode_video] len: %d, have_date: %d\n", len, *got_picture_ptr);
+
+ return len;
+}
+
+void
+emul_avcodec_decode_audio_to (uint8_t *in_buf, int in_size, uint8_t *device_buf)
+{
+ int size = 0;
+
+ size = sizeof(size);
+ memcpy (device_buf + size, &in_size, sizeof(in_size));
+ size += sizeof(in_size);
+ if (in_size > 0) {
+ memcpy (device_buf + size, in_buf, in_size);
+ size += in_size;
+ }
+
+ size -= sizeof(size);
+ memcpy (device_buf, &size, sizeof(size));
+ CODEC_LOG (DEBUG, "[decode_audio] write size: %d, inbuf_size: %d\n", size, in_size);
+}
+
+int
+emul_avcodec_decode_audio_from (CodecContext *ctx, int *frame_size_ptr, int16_t *samples, uint8_t *device_buf)
+{
+ int len = 0, size = 0;
+
+ CODEC_LOG (DEBUG, "[decode_audio] read data\n");
+ memcpy (&ctx->audio.channel_layout,
+ (uint8_t *)device_buf, sizeof(ctx->audio.channel_layout));
+ size = sizeof(ctx->audio.channel_layout);
+ memcpy (&len, (uint8_t *)device_buf + size, sizeof(len));
+ size += sizeof(len);
+ memcpy (frame_size_ptr, (uint8_t *)device_buf + size, sizeof(*frame_size_ptr));
+ size += sizeof(*frame_size_ptr);
+ CODEC_LOG (DEBUG, "[decode_audio] len: %d, channel_layout: %lld\n",
+ len, ctx->audio.channel_layout);
+ if (len > 0) {
+ memcpy (samples, (uint8_t *)device_buf + size, FF_MAX_AUDIO_FRAME_SIZE);
+ }
+
+ return len;
+}
--- /dev/null
+/*
+ * 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 emul_avcodec_init_to (CodecContext *ctx, CodecElement *codec, uint8_t *device_buf);
+
+int emul_avcodec_init_from (CodecContext *ctx, CodecElement *codec, uint8_t *device_buf);
+
+void emul_avcodec_decode_video_to (uint8_t *in_buf, int in_size, uint8_t *device_buf);
+
+int emul_avcodec_decode_video_from (CodecContext *ctx, int *got_picture_ptr, uint8_t *device_buf);
+
+void emul_avcodec_decode_audio_to (uint8_t *in_buf, int in_size, uint8_t *device_buf);
+
+int emul_avcodec_decode_audio_from (CodecContext *ctx, int *frame_size_ptr, int16_t *samples, uint8_t *device_buf);
G_BEGIN_DECLS
+enum codec_log_level {
+ ERR,
+ WARN,
+ LOG,
+ DEBUG,
+};
+
#define CODEC_DEV "/dev/newcodec"
-#define CODEC_VER 10
+#define CODEC_VER 1
#define CODEC_PARAM_INIT(var) \
memset (&var, 0x00, sizeof(var))
#define CODEC_WRITE_TO_QEMU(fd, var, size) \
if (write (fd, var, size) < 0) { \
- printf ("[%d] failed to copy data.\n", __LINE__); \
+ printf ("[%s:%d] failed to copy data.\n", __func__, __LINE__); \
}
+#define CODEC_LOG(level, fmt, ...) \
+ do { \
+ if (level <= LOG) \
+ 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_4(x) ROUND_UP_X(1, 2)
+
+#if 0
+struct _CodecIOHeader {
+ uint32_t ctx_index;
+ uint32_t mem_offset;
+};
+
+struct _CodecData {
+ uint16_t mediatype;
+ uint16_t codectype;
+ gchar name[32];
+ uint32_t extradata_size;
+ uint8_t *extradata;
+};
+
+struct _CodecCtxData {
+ int result;
+
+ struct _CodecData codec;
+
+ union {
+ struct _VideoData video;
+ struct _AudioData audio;
+ } media;
+};
+
+struct _CodecBuffer {
+ uint32_t bufsize;
+ uint8_t *buf;
+};
+#endif
+
typedef struct _CodecIOParams {
- uint32_t api_index;
- uint32_t ctx_index;
- uint32_t file_index;
- uint32_t mem_index;
- uint32_t device_mem_offset;
+ int32_t api_index;
+ int32_t ctx_index;
+ uint32_t mem_offset;
+ uint32_t mem_type;
} CodecIOParams;
+typedef struct _CodecDevMemInfo {
+ uint32_t type;
+ uint32_t index;
+ uint32_t offset;
+} CodecDevMemInfo;
+
typedef struct _CodecDevice {
- int fd;
- void *buf;
+ int fd;
+ uint8_t *buf;
uint32_t buf_size;
+ CodecDevMemInfo mem_info;
} CodecDevice;
typedef struct _CodecElement {
- gchar name[32];
- gchar longname[64];
uint16_t codec_type;
uint16_t media_type;
+ gchar name[32];
+ gchar longname[64];
#if 0
union {
struct {
int fps_n, fps_d;
int par_n, par_d;
int pix_fmt, bpp;
+ int ticks_per_frame;
} VideoData;
typedef struct _AudioData {
} AudioData;
typedef struct _CodecContext {
+ CodecElement *codec;
+ int index;
+
uint8_t *codecdata;
int codecdata_size;
VideoData video;
AudioData audio;
-
- CodecElement *codec;
} CodecContext;
enum CODEC_FUNC_TYPE {
CODEC_ELEMENT_INIT = 1,
CODEC_INIT,
- CODEC_DEINIT,
CODEC_DECODE_VIDEO,
CODEC_ENCODE_VIDEO,
CODEC_DECODE_AUDIO,
CODEC_ENCODE_AUDIO,
+ CODEC_PICTURE_COPY,
+ CODEC_DEINIT,
};
enum CODEC_IO_CMD {
- CODEC_CMD_GET_VERSION = 5,
- CODEC_CMD_GET_DEVICE_MEM,
- CODEC_CMD_SET_DEVICE_MEM,
- CODEC_CMD_GET_MMAP_OFFSET,
- CODEC_CMD_SET_MMAP_OFFSET,
+ CODEC_CMD_GET_DEVICE_MEM_INFO = 0,
+ CODEC_CMD_RELEASE_DEVICE_MEM,
+ CODEC_CMD_ADD_TASK_QUEUE,
+ CODEC_CMD_REMOVE_TASK_QUEUE,
+ CODEC_CMD_COPY_FROM_DEVICE_MEM,
+ CODEC_CMD_COPY_TO_DEVICE_MEM,
+ CODEC_CMD_GET_VERSION = 20,
};
enum CODEC_MEDIA_TYPE {
SAMPLE_FMT_NB
};
+enum CODEC_MEMORY_TYPE {
+ CODEC_FIXED_DEVICE_MEM = 0,
+ CODEC_SHARED_DEVICE_MEM,
+};
+
+
/* Define codec types.
* e.g. FFmpeg, x264, libvpx and etc.
*/
#include <sys/mman.h>
#include <sys/stat.h>
-#include "gstemulcommon.h"
+#include "gstemulapi.h"
#include "gstemuldev.h"
gst_emul_codec_device_open (CodecDevice *dev)
{
int fd;
+// CodecDevMemInfo mem_info;
void *mmapbuf;
printf("enter: %s\n", __func__);
perror("Failed to open codec device.");
return -1;
}
- GST_DEBUG("succeeded to open %s.\n", CODEC_DEV);
+
+// GST_DEBUG("succeeded to open %s. %d.\n", CODEC_DEV, fd);
+ printf("succeeded to open %s. %d.\n", CODEC_DEV, fd);
+// memset(&mem_info, 0x00, sizeof(CodecDevMemInfo));
+ dev->mem_info.index = dev->buf_size;
+
+ ioctl(fd, CODEC_CMD_GET_DEVICE_MEM_INFO, &dev->mem_info);
+
+#if 1
+ printf("mem type: %d, index: %d, offset: %d\n",
+ dev->mem_info.type, dev->mem_info.index, dev->mem_info.offset);
+#endif
mmapbuf = mmap (NULL, dev->buf_size, PROT_READ | PROT_WRITE,
- MAP_SHARED, fd, 0);
+ MAP_SHARED, fd, dev->mem_info.offset);
if (!mmapbuf) {
perror("Failed to map device memory of codec.");
close(fd);
return -1;
}
- GST_DEBUG("succeeded to map device memory.\n");
+// GST_DEBUG("succeeded to map device memory.\n");
+ printf("succeeded to map device memory: %p.\n", mmapbuf);
dev->fd = fd;
dev->buf = mmapbuf;
+ printf("leave: %s\n", __func__);
+
return 0;
}
return -1;
}
- GST_DEBUG("Release memory region of %s.\n", CODEC_DEV);
+// GST_DEBUG("Release memory region of %s.\n", CODEC_DEV);
+ CODEC_LOG(LOG, "Release memory region of %s.\n", CODEC_DEV);
+
if (munmap(mmapbuf, dev->buf_size) != 0) {
GST_ERROR("Failed to release memory region of %s.\n", CODEC_DEV);
}
+ dev->buf = NULL;
+
+ ioctl(fd, CODEC_CMD_RELEASE_DEVICE_MEM, &dev->mem_info);
+
+// GST_DEBUG("close %s.\n", CODEC_DEV);
+ CODEC_LOG(LOG, "close %s.\n", CODEC_DEV);
- GST_DEBUG("close %s.\n", CODEC_DEV);
if (close(fd) != 0) {
GST_ERROR("Failed to close %s. fd: %d\n", CODEC_DEV, fd);
}
return 0;
}
+
+static GStaticMutex gst_avcodec_mutex = G_STATIC_MUTEX_INIT;
+
+int
+gst_emul_avcodec_open (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
+{
+ int ret;
+
+ g_static_mutex_lock (&gst_avcodec_mutex);
+
+ if (gst_emul_codec_device_open (dev) < 0) {
+ perror("failed to open device.\n");
+ return -1;
+ }
+ ret = emul_avcodec_init (ctx, codec, dev);
+ g_static_mutex_unlock (&gst_avcodec_mutex);
+
+ return ret;
+}
+
+int
+gst_emul_avcodec_close (CodecContext *ctx, CodecDevice *dev)
+{
+ int ret;
+
+ g_static_mutex_lock (&gst_avcodec_mutex);
+
+ printf ("gst_emul_avcodec_close\n");
+ emul_avcodec_deinit (ctx, dev);
+
+ ret = gst_emul_codec_device_close (dev);
+ g_static_mutex_unlock (&gst_avcodec_mutex);
+
+ return ret;
+}
int gst_emul_codec_device_open (CodecDevice *dev);
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
+++ /dev/null
-/*
- * Emulator
- *
- * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact:
- * KiTae Kim <kt920.kim@samsung.com>
- * SeokYeon Hwang <syeon.hwang@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/* First, include the header file for the plugin, to bring in the
- * object definition and other useful things.
- */
-
-/*
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <gst/gst.h>
-#include "gstemulcommon.h"
-
-typedef struct _GstEmulEnc
-{
- GstElement element;
-
- GstPad *srcpad;
- GstPad *sinkpad;
-
- union {
- struct {
- gint width;
- gint height;
- gint framerate_num;
- gint framerate_den;
- gint pix_fmt;
- } video;
- struct {
- gint channels;
- gint samplerate;
- gint depth;
- } audio;
- } format;
-
- guint extradata_size;
- guint8 *extradata;
-
- CodecDev codecbuf;
-} GstEmulEnc;
-
-typedef struct _GstEmulEncClass
-{
- GstElementClass parent_class;
-
- GstPadTemplate *sinktempl;
- GstPadTemplate *srctempl;
-} GstEmulEncClass;
-
-static GstElementClass *parent_class = NULL;
-
-static void gst_emulenc_base_init (GstEmulEncClass *klass);
-static void gst_emulenc_class_init (GstEmulEncClass *klass);
-static void gst_emulenc_init (GstEmulEnc *emulenc);
-static void gst_emulenc_finalize (GObject *object);
-
-static gboolean gst_emulenc_setcaps (GstPad *pad, GstCaps *caps);
-static gboolean gst_emulenc_sink_event (GstPad *pad, GstEvent *event);
-static GstFlowReturn gst_emulenc_chain (GstPad *pad, GstBuffer *buffer);
-
-static gboolean gst_emulenc_src_event (GstPad *pad, GstEvent *event);
-static GstStateChangeReturn gst_emulenc_change_state (GstElement *element, GstStateChange transition);
-
-int gst_emul_codec_init (GstEmulEnc *emulenc);
-void gst_emul_codec_deinit (GstEmulEnc *emulenc);
-int gst_emul_codec_encode_video (GstEmulEnc *emulenc, guint8 *in_buf, guint in_size,
- GstBuffer **out_buf, GstClockTime in_timestamp);
-
-int gst_emul_codec_dev_open (GstEmulEnc *emulenc);
-
-
-#define GST_EMULENC_PARAMS_QDATA g_quark_from_static_string("emulenc-params");
-
-/*
- * Implementation
- */
- static void
-gst_emulenc_base_init (GstEmulEncClass *klass)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
- GstCaps *sinkcaps, *srccaps;
- GstPadTemplate *sinktempl, *srctempl;
- const char *mimetype = "video/x-h264";
- CodecInfo *info;
- gchar *longname, *classification;
-
- info =
- (CodecInfo *)g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
- GST_EMULENC_PARAMS_QDATA);
-
- longname = g_strdup_printf ("%s Encoder", info->codec_longname);
-
- classification = g_strdup_printf ("Codec/Encoder/%s",
- (info->media_type == AVMEDIA_TYPE_VIDEO) ? "Video" : "Audio");
-
- gst_element_class_set_details_simple (element_class,
- longname,
- classification,
- "accelerated codec for Tizen Emulator",
- "Kitae Kim <kt920.kim@samsung.com>");
-
- g_free (longname);
- g_free (classification);
-
- sinkcaps = gst_caps_new_simple (mimetype,
- "width", GST_TYPE_INT_RANGE, 16, 4096,
- "height", GST_TYPE_INT_RANGE, 16, 4096,
- "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
- if (!sinkcaps) {
- sinkcaps = gst_caps_from_string ("unknown/unknown");
- }
-
- // if type is video
- srccaps = gst_caps_from_string ("video/x-raw-rgb; video/x-raw-yuv");
- // otherwise
- // srcaps = gst_emul_codectype_to_audio_caps ();
-
- 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->sinktempl = sinktempl;
- klass->srctempl = srctempl;
-}
-
- static void
-gst_emulenc_class_init (GstEmulEncClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
- parent_class = g_type_class_peek_parent (klass);
-
-#if 0
- gobject_class->set_property = gst_emulenc_set_property
- gobject_class->get_property = gst_emulenc_get_property
-#endif
-
- gobject_class->finalize = gst_emulenc_finalize;
-
- gstelement_class->change_state = gst_emulenc_change_state;
-}
-
- static void
-gst_emulenc_init (GstEmulEnc *emulenc)
-{
- GstEmulEncClass *oclass;
-
- oclass = (GstEmulEncClass*) (G_OBJECT_GET_CLASS(emulenc));
-
- emulenc->sinkpad = gst_pad_new_from_template (oclass->sinktempl, "sink");
- gst_pad_set_setcaps_function (emulenc->sinkpad,
- GST_DEBUG_FUNCPTR(gst_emulenc_setcaps));
- gst_pad_set_event_function (emulenc->sinkpad,
- GST_DEBUG_FUNCPTR(gst_emulenc_sink_event));
- gst_pad_set_chain_function (emulenc->sinkpad,
- GST_DEBUG_FUNCPTR(gst_emulenc_chain));
- gst_element_add_pad (GST_ELEMENT(emulenc), emulenc->sinkpad);
-
- emulenc->srcpad = gst_pad_new_from_template (oclass->srctempl, "src") ;
- gst_pad_use_fixed_caps (emulenc->srcpad);
- gst_pad_set_event_function (emulenc->srcpad,
- GST_DEBUG_FUNCPTR(gst_emulenc_src_event));
- gst_element_add_pad (GST_ELEMENT(emulenc), emulenc->srcpad);
-}
-
- static void
-gst_emulenc_finalize (GObject *object)
-{
- // Deinit Decoder
- GstEmulEnc *emulenc = (GstEmulEnc *) object;
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
- static gboolean
-gst_emulenc_src_event (GstPad *pad, GstEvent *event)
-{
- return 0;
-}
-
- static void
-gst_emulenc_get_caps (GstEmulEnc *emulenc, GstCaps *caps)
-{
- GstStructure *structure;
-
- int width, height, bits_per_coded_sample;
- const GValue *fps;
- // const GValue *par;
- // guint extradata_size;
- // guint8 *extradata;
-
- /* FFmpeg Specific Values */
- const GstBuffer *buf;
- const GValue *value;
-
- structure = gst_caps_get_structure (caps, 0);
-
- value = gst_structure_get_value (structure, "codec_data");
- if (value) {
- buf = GST_BUFFER_CAST (gst_value_get_mini_object (value));
- emulenc->extradata_size = GST_BUFFER_SIZE (buf);
- emulenc->extradata = GST_BUFFER_DATA (buf);
- } else {
- CODEC_LOG (2, "no codec data\n");
- emulenc->extradata_size = 0;
- emulenc->extradata = NULL;
- }
-
-#if 1 /* video type */
- /* Common Properites, width, height and etc. */
- gst_structure_get_int (structure, "width", &width);
- gst_structure_get_int (structure, "height", &height);
- gst_structure_get_int (structure, "bpp", &bits_per_coded_sample);
-
- emulenc->format.video.width = width;
- emulenc->format.video.height = height;
-
- fps = gst_structure_get_value (structure, "framerate");
- if (fps) {
- emulenc->format.video.framerate_den = gst_value_get_fraction_numerator (fps);
- emulenc->format.video.framerate_num = gst_value_get_fraction_denominator (fps);
- }
-
-#if 0
- par = gst_structure_get_value (structure, "pixel-aspect-ratio");
- if (par) {
- sample_aspect_ratio.num = gst_structure_get_fraction_numerator (par);
- sample_aspect_ratio.den = gst_structure_get_fraction_denominator (par);
- }
-#endif
-#endif
-
-#if 0 /* audio type */
- gst_structure_get_int (structure, "channels", &channels);
- gst_structure_get_int (structure, "rate", &sample_rate);
- gst_structure_get_int (structure, "block_align", &block_align);
- gst_structure_get_int (structure, "bitrate", &bit_rate);
-
- emulenc->format.audio.channels = channels;
- emulenc->format.audio.samplerate = sample_rate;
-#endif
-
-}
-
- static gboolean
-gst_emulenc_setcaps (GstPad *pad, GstCaps *caps)
-{
- GstEmulEnc *emulenc;
- GstEmulEncClass *oclass;
- gboolean ret = TRUE;
-
- emulenc = (GstEmulEnc *) (gst_pad_get_parent (pad));
- oclass = (GstEmulEncClass *) (G_OBJECT_GET_CLASS (emulenc));
-
- GST_OBJECT_LOCK (emulenc);
-
- gst_emulenc_get_caps (emulenc, caps);
-
-#if 0
- if (!emulenc->format.video.framerate_den ||
- !emulenc->format.video.framerate_num) {
- emulenc->format.video.framerate_num = 1;
- emulenc->format.video.framerate_den = 25;
- }
-#endif
-
- if (gst_emul_codec_dev_open (emulenc) < 0) {
- CODEC_LOG(1, "failed to access %s or mmap operation\n", CODEC_DEV);
- GST_OBJECT_UNLOCK (emulenc);
- gst_object_unref (emulenc);
- return FALSE;
- }
-
- if (gst_emul_codec_init (emulenc) < 0) {
- CODEC_LOG(1, "cannot initialize codec\n");
- GST_OBJECT_UNLOCK (emulenc);
- gst_object_unref (emulenc);
- return FALSE;
- }
-
-#if 0 /* open a parser */
- gst_emul_codec_parser (emulenc);
-#endif
-
- GST_OBJECT_UNLOCK (emulenc);
-
- gst_object_unref (emulenc);
-
- return ret;
-}
-
- static gboolean
-gst_emulenc_sink_event (GstPad *pad, GstEvent *event)
-{
- GstEmulEnc *emulenc;
- gboolean ret = FALSE;
-
- emulenc = (GstEmulEnc *) gst_pad_get_parent (pad);
-#if 0
- switch (GST_TYPE_EVENT (event)) {
- case GST_EVENT_EOS:
- CODEC_LOG(2, "received GST_EVENT_EOS\n");
- break;
- case GST_EVENT_NEWSEGMENT:
- CODEC_LOG(2, "received GST_EVENT_NEWSEGMENT\n");
- break;
- }
- ret = gst_pad_push_event (emulenc->srcpad, event);
-#endif
-
- gst_object_unref (emulenc);
-
- return ret;
-}
-
- static GstFlowReturn
-gst_emulenc_chain (GstPad *pad, GstBuffer *buffer)
-{
- GstEmulEnc *emulenc;
- guint8 *in_buf = NULL;
- GstBuffer *out_buf;
- gint in_size = 0;
- GstClockTime in_timestamp;
- GstFlowReturn ret = GST_FLOW_OK;
-
- emulenc = (GstEmulEnc *) (GST_PAD_PARENT (pad));
-
- in_size = GST_BUFFER_SIZE (buffer);
- in_buf = GST_BUFFER_DATA (buffer);
- in_timestamp = GST_BUFFER_TIMESTAMP (buffer);
-
- gst_emul_codec_encode_video (emulenc, in_buf, in_size, &out_buf, in_timestamp);
-
- CODEC_LOG(1, "out_buf:%p, ret:%d\n", out_buf, ret);
-
- ret = gst_pad_push (emulenc->srcpad, out_buf);
-
- // g_free (out_buf);
-
- gst_buffer_unref (buffer);
-
- return ret;
-}
-
- static GstStateChangeReturn
-gst_emulenc_change_state (GstElement *element, GstStateChange transition)
-{
- GstEmulEnc *emulenc = (GstEmulEnc*)element;
- GstStateChangeReturn ret;
-
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- gst_emul_codec_deinit (emulenc);
- default:
- break;
- }
-
- return ret;
-}
-
- gboolean
-gst_emulenc_register (GstPlugin *plugin)
-{
- GTypeInfo typeinfo = {
- sizeof (GstEmulEncClass),
- (GBaseInitFunc) gst_emulenc_base_init,
- NULL,
- (GClassInitFunc) gst_emulenc_class_init,
- NULL,
- NULL,
- sizeof (GstEmulEnc),
- 0,
- (GInstanceInitFunc) gst_emulenc_init,
- };
-
- GType type;
- gchar *type_name;
- gint rank = GST_RANK_PRIMARY;
-
- /* register element */
- {
- int codec_fd, codec_cnt = 0;
- int func_type = CODEC_QUERY;
- int index = 0, size = 0;
- void *buf;
- CodecInfo *codec_info;
-
- codec_fd = open(CODEC_DEV, O_RDWR);
- if (codec_fd < 0) {
- perror("failed to open codec device");
- return FALSE;
- }
-
- printf("[codec] fd:%d\n", codec_fd);
- buf = mmap (NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, codec_fd, 0);
- if (!buf) {
- perror("failed to mmap");
- }
-
- printf("[codec] mmap:%p\n", buf);
-
- write (codec_fd, &func_type, sizeof(int));
- memcpy (&codec_cnt, buf, sizeof(int));
- size = sizeof(uint32_t);
-
- codec_info = g_malloc0 (codec_cnt * sizeof(CodecInfo));
- for (; index < codec_cnt; index++) {
- memcpy(&codec_info[index].media_type, (uint8_t *)buf + size, sizeof(uint16_t));
- size += sizeof(uint16_t);
- memcpy(&codec_info[index].codec_type, (uint8_t *)buf + size, sizeof(uint16_t));
- size += sizeof(uint16_t);
- memcpy(&codec_info[index].codec_name, (uint8_t *)buf + size, 32);
- size += 32;
- memcpy(&codec_info[index].codec_longname, (uint8_t *)buf + size, 64);
- size += 64;
- }
-
- for (index = 0; index < codec_cnt; index++) {
- if (codec_info[index].codec_type != 0) {
- continue;
- }
-
- type_name = g_strdup_printf ("emulenc_%s", codec_info[index].codec_name);
- type = g_type_from_name (type_name);
- if (!type) {
- type = g_type_register_static (GST_TYPE_ELEMENT, type_name, &typeinfo, 0);
- g_type_set_qdata (type, GST_EMULDEC_PARAMS_QDATA, (gpointer) &codec_info[index]);
- }
-
- if (!gst_element_register (plugin, type_name, rank, type)) {
- g_free (type_name);
- return FALSE;
- }
- g_free (type_name);
- }
-
- printf("[codec] close\n");
- munmap (buf, 4096);
- close (codec_fd);
- }
-
- return TRUE;
-}
-
-void *gst_emul_codec_query (GstEmulEnc *emulenc)
-{
- int fd, codec_cnt;
- int size = 0, i;
- void *mmapbuf;
- int func_type = CODEC_QUERY;
- CodecInfo *codec_info;
-
- CODEC_LOG(1, "enter: %s\n", __func__);
-
- fd = emulenc->codecbuf.fd;
- mmapbuf = emulenc->codecbuf.mmapbuf;
- if (fd < 0) {
- CODEC_LOG(1, "failed to get %s fd\n", CODEC_DEV);
- return NULL;
- }
-
- if (!mmapbuf) {
- CODEC_LOG(1, "failed to get mmaped memory address\n");
- return NULL;
- }
-
- write (fd, &func_type, sizeof(func_type));
- memcpy (&codec_cnt, mmapbuf, sizeof(uint32_t));
- size += sizeof(uint32_t);
-
- codec_info = g_malloc0 (codec_cnt * sizeof(CodecInfo));
-
- for (i = 0; i < codec_cnt; i++) {
- memcpy (&codec_info[i].mediatype, (uint8_t *)mmapbuf + size, sizeof(uint16_t));
- size += sizeof(uint16_t);
- memcpy (&codec_info[i].codectype, (uint8_t *)mmapbuf + size, sizeof(uint16_t));
- size += sizeof(uint16_t);
- memcpy (codec_info[i].name, (uint8_t *)mmapbuf + size, 32);
- size += 32;
- memcpy (codec_info[i].long_name, (uint8_t *)mmapbuf + size, 64);
- size += 64;
- }
-
- CODEC_LOG(1, "leave: %s\n", __func__);
-
- return codec_info;
-}
-
-int gst_emul_codec_init (GstEmulEnc *emulenc)
-{
- int fd;
- int size = 0, ret;
- guint extradata_size = 0;
- guint8 *extradata = NULL;
- void *mmapbuf;
- int func_type = CODEC_INIT;
-
- CODEC_LOG(1, "enter: %s\n", __func__);
-
- fd = emulenc->codecbuf.fd;
- mmapbuf = emulenc->codecbuf.mmapbuf;
- if (fd < 0) {
- CODEC_LOG(1, "failed to get %s fd\n", CODEC_DEV);
- return -1;
- }
-
- if (!mmapbuf) {
- CODEC_LOG(1, "failed to get mmaped memory address\n");
- return -1;
- }
-
- extradata_size = emulenc->extradata_size;
- extradata = emulenc->extradata;
-
- /* copy basic info to initialize codec on the host side.
- * e.g. width, height, FPS ant etc. */
- memcpy ((uint8_t *)mmapbuf, &emulenc->format.video, sizeof(emulenc->format.video));
- size += sizeof(emulenc->format.video);
- if (extradata) {
- memcpy ((uint8_t *)mmapbuf + size, &extradata_size, sizeof(extradata_size));
- size += sizeof(extradata_size);
- memcpy ((uint8_t *)mmapbuf + size, extradata, extradata_size);
- }
-
- ret = write (fd, &func_type, sizeof(func_type));
-
- CODEC_LOG(1, "leave: %s\n", __func__);
-
- return ret;
-}
-
-void gst_emul_codec_dev_close (GstEmulEnc *emulenc)
-{
- int fd, ret = 0;
- int size = 0;
- void *mmapbuf;
-
- CODEC_LOG(1, "enter: %s\n", __func__);
-
- fd = emulenc->codecbuf.fd;
- mmapbuf = emulenc->codecbuf.mmapbuf;
-
- if (fd < 0) {
- CODEC_LOG(1, "failed to get %s fd\n", CODEC_DEV);
- return;
- }
-
- if (!mmapbuf) {
- CODEC_LOG(1, "failed to get mmaped memory address\n");
- return;
- }
-
- CODEC_LOG(2, "release mmaped memory region of %s\n", CODEC_DEV);
- ret = munmap(mmapbuf, 12 * 4096);
- if (ret != 0) {
- CODEC_LOG(1, "failed to release mmaped memory region of %s\n", CODEC_DEV);
- }
-
- CODEC_LOG(2, "close %s fd\n", CODEC_DEV);
- ret = close (fd);
- if (ret != 0) {
- CODEC_LOG(1, "failed to close %s\n", CODEC_DEV);
- }
-
- CODEC_LOG(1, "leave: %s\n", __func__);
-}
-
-void gst_emul_codec_deinit (GstEmulEnc *emulenc)
-{
- int fd, ret;
- int func_type = CODEC_DEINIT;
- void *mmapbuf;
-
- CODEC_LOG(1, "enter: %s\n", __func__);
-
- fd = emulenc->codecbuf.fd;
- mmapbuf = emulenc->codecbuf.mmapbuf;
-
- if (fd < 0) {
- CODEC_LOG(1, "failed to get %s fd\n", CODEC_DEV);
- return;
- }
-
- if (!mmapbuf) {
- CODEC_LOG(1, "failed to get mmaped memory address\n");
- return;
- }
-
- ret = write (fd, &func_type, sizeof(func_type));
-
- /* close device fd and release mapped memory region */
- gst_emul_codec_dev_close (emulenc);
-
- CODEC_LOG(1, "leave: %s\n", __func__);
-}
-
-int gst_emul_codec_encode_video (GstEmulEnc *emulenc, guint8 *in_buf, guint in_size,
- GstBuffer **out_buf, GstClockTime in_timestamp)
-{
- int fd, size = 0, ret;
- guint out_size;
- int func_type = CODEC_DECODE_VIDEO;
- void *mmapbuf;
- *out_buf = NULL;
-
- CODEC_LOG(1, "enter: %s\n", __func__);
-
- fd = emulenc->codecbuf.fd;
- mmapbuf = emulenc->codecbuf.mmapbuf;
-
- if (fd < 0) {
- CODEC_LOG(1, "failed to get %s fd\n", CODEC_DEV);
- return -1;
- }
-
- if (!mmapbuf) {
- CODEC_LOG(1, "failed to get mmaped memory address\n");
- return -1;
- }
-
- memcpy ((uint8_t *)mmapbuf + size, &in_size, sizeof(guint));
- size += sizeof(guint);
- memcpy ((uint8_t *)mmapbuf + size, &in_timestamp, sizeof(GstClockTime));
- size += sizeof(GstClockTime);
- memcpy ((uint8_t *)mmapbuf + size, in_buf, in_size);
-
- /* provide raw image for decoding to qemu */
- ret = write (fd, &func_type, sizeof(func_type));
-
- size = 0;
- memcpy (&out_size, (uint8_t *)mmapbuf + size, sizeof(uint));
- size += sizeof(guint);
-
- ret = gst_pad_alloc_buffer_and_set_caps (emulenc->srcpad,
- GST_BUFFER_OFFSET_NONE, out_size,
- GST_PAD_CAPS (emulenc->srcpad), out_buf);
-
- gst_buffer_set_caps (*out_buf, GST_PAD_CAPS (emulenc->srcpad));
-
- if (GST_BUFFER_DATA(*out_buf)) {
- memcpy (GST_BUFFER_DATA(*out_buf), (uint8_t *)mmapbuf + size, out_size);
- } else {
- CODEC_LOG(1, "failed to allocate output buffer\n");
- }
-
- CODEC_LOG(1, "leave: %s\n", __func__);
-
- return ret;
-}
-
-#if 0
-void emulenc_encode_audio ()
-{
- int fd, size = 0, ret;
- guint out_size;
- int func_type = CODEC_DECODE_AUDIO;
- void *mmapbuf;
- *out_buf = NULL;
-
- CODEC_LOG(1, "enter: %s\n", __func__);
-
- fd = emulenc->codecbuf.fd;
- mmapbuf = emulenc->codecbuf.mmapbuf;
-
- if (fd < 0) {
- CODEC_LOG(1, "failed to get %s fd\n", CODEC_DEV);
- return -1;
- }
-
- if (!mmapbuf) {
- CODEC_LOG(1, "failed to get mmaped memory address\n");
- return -1;
- }
-
- memcpy ((uint8_t *)mmapbuf + size, &in_size, sizeof(guint));
- size += sizeof(guint);
- memcpy ((uint8_t *)mmapbuf + size, &in_timestamp, sizeof(GstClockTime));
- size += sizeof(GstClockTime);
- memcpy ((uint8_t *)mmapbuf + size, in_buf, in_size);
-
- /* provide raw image for decoding to qemu */
- ret = write (fd, &func_type, sizeof(func_type));
-
- size = 0;
- memcpy (&out_size, (uint8_t *)mmapbuf + size, sizeof(uint));
- size += sizeof(guint);
-
- *out_buf = gst_buffer_new();
- GST_BUFFER_DATA (out_buf) = GST_BUFFER_MALLOCDATA (out_buf) = av_malloc (out_size);
- GST_BUFFER_SIZE (out_buf) = out_size;
- // GST_BUFFER_FREE_FUNC (out_buf) = av_free;
- if (GST_PAD_CAPS(emulenc->srcpad)) {
- gst_buffer_set_caps (*out_buf, GST_PAD_CAPS (emulenc->srcpad));
- }
-
- if (GST_BUFFER_DATA(*out_buf)) {
- memcpy (GST_BUFFER_DATA(*out_buf), (uint8_t *)mmapbuf + size, out_size);
- } else {
- CODEC_LOG(1, "failed to allocate output buffer\n");
- }
- CODEC_LOG(1, "leave: %s\n", __func__);
-
- return ret;
-}
-#endif
qostime = gst_segment_to_running_time (&emuldec->segment, GST_FORMAT_TIME,
timestamp);
-
if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (qostime))) {
emuldec->processed++;
return res;
}
}
+
+ emuldec->processed++;
+ return TRUE;
}
static void
oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (emuldec));
// TODO: drain
-#if 1
+#if 1
{
gint have_data, len, try = 0;
len =
gst_emuldec_frame (emuldec, NULL, 0, &have_data, &ts_info_none, &ret);
- if (len < 0 || have_data == 0) {
- printf("drain. try: %d\n", try);
+ if (len < 0 || have_data == 0) {
break;
}
} while (try++ < 10);
#endif
if (emuldec->segment.rate < 0.0) {
+ printf ("reverse playback\n");
flush_queued (emuldec);
}
}
if (!emuldec->context) {
printf("failed to allocate memory.\n");
}
+ // set default bit_rate
+ emuldec->context->audio.bit_rate = 64000;
+
emuldec->dev = g_malloc0 (sizeof(CodecDevice));
if (!emuldec->dev) {
printf("failed to allocate memory.\n");
GstEmulDec *emuldec = (GstEmulDec *) object;
printf ("gst_emuldec_finalize\n");
- if (emuldec->context != NULL) {
+ if (emuldec->context) {
g_free (emuldec->context);
emuldec->context = NULL;
}
gst_emuldec_src_event (GstPad *pad, GstEvent *event)
{
GstEmulDec *emuldec;
- gboolean res;
+ gboolean res;
emuldec = (GstEmulDec *) gst_pad_get_parent (pad);
GstClockTimeDiff diff;
GstClockTime timestamp;
- printf("GST_EVENT_QOS\n");
gst_event_parse_qos (event, &proportion, &diff, ×tamp);
- GST_LOG_OBJECT (emuldec, "update QOS: %f, %" GST_TIME_FORMAT,
- proportion, GST_TIME_ARGS (timestamp));
/* update our QoS values */
gst_emuldec_update_qos (emuldec, proportion, timestamp + diff);
-
- /* forward upstream */
- res = gst_pad_push_event (emuldec->sinkpad, event);
break;
}
default:
- /* forward upstream */
- res = gst_pad_push_event (emuldec->sinkpad, event);
break;
}
+ /* forward upstream */
+ res = gst_pad_push_event (emuldec->sinkpad, event);
+
gst_object_unref (emuldec);
- return 0;
+ return res;
}
static gboolean
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS:
- printf("GST_EVENT_EOS\n");
+ printf("GST_EVENT_EOS\n");
gst_emuldec_drain (emuldec);
break;
case GST_EVENT_FLUSH_STOP:
{
- printf("GST_EVENT_FLUSH_STOP\n");
-
+ printf("GST_EVENT_FLUSH_STOP\n");
+#if 0
+ if (emuldec->opened) {
+ emul_avcodec_flush_buffers (emuldec->context, emuldec->dev);
+ }
+#endif
gst_emuldec_reset_ts (emuldec);
-// gst_emuldec_reset_qos (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 queue */
clear_queued (emuldec);
}
break;
printf ("GST_FORMAT_BYTES\n");
if (!bit_rate) {
- // no_bitrate
GST_WARNING_OBJECT (emuldec, "no bitrate to convert BYTES to TIME");
gst_event_unref (event);
gst_object_unref (emuldec);
break;
}
default:
- // invlalid format
- break;
+ GST_WARNING_OBJECT (emuldec, "unknown format received in NEWSEGMENT");
+ gst_event_unref (event);
+ gst_object_unref (emuldec);
+ return ret;
}
-#if 1
if (emuldec->context->codec) {
+ printf("before drain, NEWSEGMENT event\n");
gst_emuldec_drain (emuldec);
}
-#endif
+
+ 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);
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 0
if (format == NULL || strcmp ("format", "raw") == 0) {
emuldec->turnoff_parser = TRUE;
}
-#endif
}
+#endif
if (!gst_emuldec_open (emuldec)) {
GST_DEBUG_OBJECT (emuldec, "Failed to open");
return ret;
}
-static GStaticMutex gst_avcodec_mutex = G_STATIC_MUTEX_INIT;
-
-int
-gst_emul_avcodec_open (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
-{
- int ret;
-
- g_static_mutex_lock (&gst_avcodec_mutex);
-
- if (gst_emul_codec_device_open (dev) < 0) {
- printf("failed to open device.\n");
- return -1;
- }
- ret = emul_avcodec_init (ctx, codec, dev);
- g_static_mutex_unlock (&gst_avcodec_mutex);
-
- return ret;
-}
-
-int
-gst_emul_avcodec_close (CodecContext *ctx, CodecDevice *dev)
-{
- int ret;
-
- g_static_mutex_lock (&gst_avcodec_mutex);
-
- printf ("gst_emul_avcodec_close\n");
- ret = emul_avcodec_deinit (ctx, dev);
-
- gst_emul_codec_device_close (dev);
- g_static_mutex_unlock (&gst_avcodec_mutex);
-
- return ret;
-}
-
static gboolean
gst_emuldec_open (GstEmulDec *emuldec)
{
case AVMEDIA_TYPE_VIDEO:
width = emuldec->context->video.width;
height = emuldec->context->video.height;
- buf_size = gst_emul_avpicture_size (0, width, height);
+ buf_size = gst_emul_avpicture_size (0, width, height) + 100;
break;
case AVMEDIA_TYPE_AUDIO:
-// buf_size = FF_MAX_AUDIO_FRAME_SIZE;
- buf_size = 1024 * 256; // 256K
+ buf_size = FF_MAX_AUDIO_FRAME_SIZE + 100;
break;
default:
buf_size = -1;
return FALSE;
}
- emuldec->dev->buf_size = buf_size;
+ emuldec->dev->buf_size = gst_emul_align_size(buf_size);
if (gst_emul_avcodec_open (emuldec->context, oclass->codec, emuldec->dev) < 0) {
gst_emuldec_close (emuldec);
int ret;
printf ("gst_emuldec_close\n");
+
+ if (emuldec->context->codecdata) {
+ g_free(emuldec->context->codecdata);
+ emuldec->context->codecdata = NULL;
+ }
+
gst_emul_avcodec_close (emuldec->context, emuldec->dev);
+ if (emuldec->dev) {
+ g_free(emuldec->dev);
+ emuldec->dev = NULL;
+ }
+
return TRUE;
}
break;
}
-
-
caps =
gst_emul_codectype_to_caps (oclass->codec->media_type, emuldec->context,
oclass->codec->name, FALSE);
}
break;
case AVMEDIA_TYPE_AUDIO:
+ break;
default:
break;
}
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);
+
+ 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));
+ }
+
+ gst_buffer_set_caps (*outbuf, GST_PAD_CAPS (emuldec->srcpad));
+
+ emul_av_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)
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_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_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);
static gint
gst_emuldec_video_frame (GstEmulDec *emuldec, guint8 *data, guint size,
- const GstTSInfo *dec_info, GstBuffer **outbuf,
- GstFlowReturn *ret)
+ const GstTSInfo *dec_info, GstBuffer **outbuf,
+ GstFlowReturn *ret)
{
- gint len = -1;
- GstClockTime out_timestamp, out_duration;
+ gint len = -1, have_data;
+ gboolean mode_switch;
+ gboolean decode;
+ GstClockTime out_timestamp, out_duration, out_pts;
gint64 out_offset;
+ GstTSInfo *out_info;
-#if 0
+ decode = gst_emuldec_do_qos (emuldec, dec_info->timestamp, &mode_switch);
+
+// printf("decode video: input buffer size: %d\n", size);
len =
emul_avcodec_decode_video (emuldec->context, data, size,
- (int16_t *) GST_BUFFER_DATA (*outbuf), &have_data, emuldec->dev);
+ 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;
+ }
+
+#if 1
+// out_info = gst_ts_info_get (emuldec, emuldec->picture->reordered_opaque);
+ 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;
#endif
+ *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;
}
new_aligned_buffer (FF_MAX_AUDIO_FRAME_SIZE,
GST_PAD_CAPS (emuldec->srcpad));
+// printf("decode audio[%p] input buffer size: %d\n", emuldec, size);
+
len = emul_avcodec_decode_audio (emuldec->context,
(int16_t *) GST_BUFFER_DATA (*outbuf), &have_data,
data, size, emuldec->dev);
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);
if (len == -1 && !strcmp(codec->name, "aac")) {
GST_ELEMENT_ERROR (emuldec, STREAM, DECODE, (NULL),
- ("Decoding of AAC stream by gst-emul-codec failed."));
+ ("Decoding of AAC stream by FFMPEG failed."));
*ret = GST_FLOW_ERROR;
}
static gint
gst_emuldec_frame (GstEmulDec *emuldec, guint8 *data, guint size,
- gint *got_data, const GstTSInfo *dec_info, GstFlowReturn *ret)
+ gint *got_data, const GstTSInfo *dec_info, GstFlowReturn *ret)
{
GstEmulDecClass *oclass;
GstBuffer *outbuf = NULL;
gint have_data = 0, len = 0;
if (G_UNLIKELY (emuldec->context->codec == NULL)) {
- // no_codec
GST_ERROR_OBJECT (emuldec, "no codec context");
return -1;
}
*ret = GST_FLOW_OK;
-
oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (emuldec));
switch (oclass->codec->media_type) {
case AVMEDIA_TYPE_VIDEO:
len = gst_emuldec_video_frame (emuldec, data, size,
- dec_info, &outbuf, ret);
+ dec_info, &outbuf, ret);
break;
case AVMEDIA_TYPE_AUDIO:
len = gst_emuldec_audio_frame (emuldec, oclass->codec, data, size,
- dec_info, &outbuf, ret);
+ dec_info, &outbuf, ret);
if (outbuf == NULL && emuldec->discont) {
GST_DEBUG_OBJECT (emuldec, "no buffer but keeping timestamp");
// emuldec->clear_ts = FALSE;
if (len < 0 || have_data < 0) {
GST_WARNING_OBJECT (emuldec,
- "tzdec_%s: decoding error (len: %d, have_data: %d)",
- oclass->codec->name, len, have_data);
+ "tzdec_%s: decoding error (len: %d, have_data: %d)",
+ oclass->codec->name, len, have_data);
*got_data = 0;
return len;
} else if (len == 0 && have_data == 0) {
} else {
// push reverse
printf("push reverse.\n");
+ GST_DEBUG_OBJECT (emuldec, "queued frame");
emuldec->queued = g_list_prepend (emuldec->queued, outbuf);
*ret = GST_FLOW_OK;
}
GstEmulDec *emuldec;
GstEmulDecClass *oclass;
guint8 *in_buf;
- guint in_size, len, have_data;
+ gint in_size, len, have_data;
GstFlowReturn ret = GST_FLOW_OK;
GstClockTime in_timestamp;
GstClockTime in_duration;
oclass = (GstEmulDecClass *) (G_OBJECT_GET_CLASS (emuldec));
GST_ELEMENT_ERROR (emuldec, CORE, NEGOTIATION, (NULL),
("tzdec_%s: input format was not set before data start",
- oclass->codec->name));
+ oclass->codec->name));
gst_buffer_unref (buffer);
return GST_FLOW_NOT_NEGOTIATED;
}
// FIXME
if (G_UNLIKELY (discont)) {
GST_DEBUG_OBJECT (emuldec, "received DISCONT");
- printf("discont 1\n");
gst_emuldec_drain (emuldec);
- printf("discont 2\n");
// gst_emuldec_flush_pcache (emuldec);
- // flush buffers
+// emul_avcodec_flush buffers (emuldec->context, emuldec->dev);
emuldec->discont = TRUE;
gst_emuldec_reset_ts (emuldec);
}
}
if (emuldec->pcache) {
- GST_LOG_OBJECT (emuldec, "join parse cache");
- buffer = gst_buffer_join (emuldec->pcache, buffer);
- emuldec->pcache = NULL;
+ GST_LOG_OBJECT (emuldec, "join parse cache");
+ buffer = gst_buffer_join (emuldec->pcache, buffer);
+ emuldec->pcache = NULL;
}
#endif
}
GST_LOG_OBJECT (emuldec, "estimated duration %" GST_TIME_FORMAT " %u",
- GST_TIME_ARGS (diff), emuldec->last_frames);
+ GST_TIME_ARGS (diff), emuldec->last_frames);
emuldec->last_diff = diff;
}
}
#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, &ret);
+ gst_emuldec_frame (emuldec, in_buf, in_size, &have_data, dec_info, &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);
clear_queued (emuldec);
break;
default:
+ printf("tzdec: %p, state change: %d\n", emuldec, transition);
break;
}
return ret;
}
-
*
*/
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <gst/gst.h>
-#include "gstemulcommon.h"
-
-#define GST_EMULENC_PARAMS_QDATA g_quark_from_static_string("emulenc-params");
+#include "gstemulutils.h"
+#include "gstemulapi.h"
+#include <gst/base/gstadapter.h>
+
+#define GST_EMULENC_PARAMS_QDATA g_quark_from_static_string("emulenc-params")
typedef struct _GstEmulEnc
{
GstPad *srcpad;
GstPad *sinkpad;
+ CodecContext *context;
+ CodecDevice *dev;
+
union {
struct {
- gint width;
- gint height;
- gint framerate_num;
- gint framerate_den;
- gint pix_fmt;
+ 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;
} audio;
} format;
+ // cache
+ gulong buffer_size;
+
+ gboolean discont;
+
+ GstClockTime adapter_ts;
GstAdapter *adapter;
- // TODO: needs a certain container such as AVCodecContext.
- guint extradata_size;
- guint8 *extradata;
+ guint8 *working_buf;
+ gulong working_buf_size;
- CodecDev codecbuf;
} GstEmulEnc;
typedef struct _GstEmulEncClass
{
GstElementClass parent_class;
- CodecInfo *codecinfo;
- GstPadTemplate *sinktempl, *srctempl;
+ CodecElement *codec;
+ GstPadTemplate *sinktempl;
+ GstPadTemplate *srctempl;
GstCaps *sinkcaps;
} GstEmulEncClass;
static void gst_emulenc_finalize (GObject *object);
static gboolean gst_emulenc_setcaps (GstPad *pad, GstCaps *caps);
-static gboolean gst_emulenc_getcaps (GstPad *pad);
+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);
-static GstStateChangeReturn gst_emulenc_change_state (GstElement *element, GstStateChange transition);
-
-int gst_emul_codec_init (GstEmulEnc *emulenc);
-void gst_emul_codec_deinit (GstEmulEnc *emulenc);
-
-#if 0
-int gst_emul_codec_encode_video (GstEmulEnc *emulenc, guint8 *in_buf, guint in_size,
- GstBuffer **out_buf, GstClockTime in_timestamp);
-int gst_emul_codec_encode_audio (GstEmulEnc *emulenc, guint8 *in_buf, guint in_size,
- GstBuffer **out_buf, GstClockTime in_timestamp);
-#endif
+GstStateChangeReturn gst_emulenc_change_state (GstElement *element, GstStateChange transition);
/*
* Implementation
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
GstPadTemplate *sinktempl = NULL, *srctempl = NULL;
GstCaps *sinkcaps = NULL, *srccaps = NULL;
- CodecInfo *info;
+ CodecElement *codec;
gchar *longname, *classification;
- info =
- (CodecInfo *)g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
+ codec =
+ (CodecElement *)g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
GST_EMULENC_PARAMS_QDATA);
- longname = g_strdup_printf ("%s Encoder", info->codec_longname);
-
+ longname = g_strdup_printf ("%s Encoder", codec->longname);
classification = g_strdup_printf ("Codec/Encoder/%s",
- (info->media_type == AVMEDIA_TYPE_VIDEO) ? "Video" : "Audio");
+ (codec->media_type == AVMEDIA_TYPE_VIDEO) ? "Video" : "Audio");
gst_element_class_set_details_simple (element_class,
longname,
classification,
"accelerated codec for Tizen Emulator",
"Kitae Kim <kt920.kim@samsung.com>");
+
g_free (longname);
g_free (classification);
- if (!(srccaps = gst_emul_codecname_to_caps (info, TRUE))) {
- GST_DEBUG ("Couldn't get source caps for encoder '%s'", info->codec_name);
+ 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 (info->media_type) {
+ 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:
- srccaps = gst_emul_codectype_to_audio_caps (info, TRUE);
+ srccaps = gst_emul_codectype_to_audio_caps (NULL, codec->name, TRUE, codec);
break;
default:
GST_LOG("unknown media type.\n");
}
if (!sinkcaps) {
- GST_DEBUG ("Couldn't get sink caps for encoder '%s'", info->codec_name);
+ GST_DEBUG ("Couldn't get sink caps for encoder '%s'", codec->name);
sinkcaps = gst_caps_new_simple ("unknown/unknown", NULL);
}
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
+static void
gst_emulenc_class_init (GstEmulEncClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
#endif
gobject_class->finalize = gst_emulenc_finalize;
-
gstelement_class->change_state = gst_emulenc_change_state;
}
- static void
+
+#define DEFAULT_VIDEO_BITRATE 300000
+#define DEFAULT_AUDIO_BITRATE 128000
+
+static void
gst_emulenc_init (GstEmulEnc *emulenc)
{
GstEmulEncClass *oclass;
emulenc->sinkpad = gst_pad_new_from_template (oclass->sinktempl, "sink");
gst_pad_set_setcaps_function (emulenc->sinkpad,
- GST_DEBUG_FUNCPTR(gst_emulenc_setcaps));
+ GST_DEBUG_FUNCPTR(gst_emulenc_setcaps));
gst_pad_set_getcaps_function (emulenc->sinkpad,
- GST_DEBUG_FUNCPTR(gst_emulenc_getcaps));
+ GST_DEBUG_FUNCPTR(gst_emulenc_getcaps));
emulenc->srcpad = gst_pad_new_from_template (oclass->srctempl, "src");
gst_pad_use_fixed_caps (emulenc->srcpad);
- switch (oclass->codecinfo->media_type) {
+ switch (oclass->codec->media_type) {
case AVMEDIA_TYPE_VIDEO:
gst_pad_set_chain_function (emulenc->sinkpad, gst_emulenc_chain_video);
gst_pad_set_event_function (emulenc->sinkpad, gst_emulenc_event_video);
- gst_pad_set_event_function (emulenc->srckpad, gst_emulenc_event_src);
-
+ gst_pad_set_event_function (emulenc->srcpad, gst_emulenc_event_src);
+// emulenc->bitrate = DEFAULT_VIDEO_BITRATE;
break;
case AVMEDIA_TYPE_AUDIO:
- gst_pad_set_chain_function (emuldec->sinkpad, gst_emulenc_chain_audio);
+ gst_pad_set_chain_function (emulenc->sinkpad, gst_emulenc_chain_audio);
+// emulenc->bitrate = DEFAULT_AUDIO_BITRATE;
break;
default:
break;
}
- gst_element_add_pad (GST_ELEMENT (emulenc), emuldenc->sinkpad);
- gst_element_add_pad (GST_ELEMENT (emulenc), emuldenc->srcpad);
+ gst_element_add_pad (GST_ELEMENT (emulenc), emulenc->sinkpad);
+ gst_element_add_pad (GST_ELEMENT (emulenc), emulenc->srcpad);
+
+ // init
+ emulenc->context = g_malloc0 (sizeof(CodecContext));
+ if (!emulenc->context) {
+ printf("failed to allocate memory.\n");
+ }
+
+ 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 ();
// Deinit Decoder
GstEmulEnc *emulenc = (GstEmulEnc *) object;
+ if (emulenc->context) {
+ g_free (emulenc->context);
+ emulenc->context = NULL;
+ }
+ g_object_unref (emulenc->adapter);
+
G_OBJECT_CLASS (parent_class)->finalize (object);
+
+
}
- static gboolean
-gst_emulenc_src_event (GstPad *pad, GstEvent *event)
+static GstCaps *
+gst_emulenc_get_possible_sizes (GstEmulEnc *emulenc, GstPad *pad,
+ const GstCaps *caps)
{
- return 0;
+ 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 void
-gst_emulenc_get_caps (GstEmulEnc *emulenc, GstCaps *caps)
+static GstCaps *
+gst_emulenc_getcaps (GstPad *pad)
{
- GstStructure *structure;
-
- int width, height, bits_per_coded_sample;
- const GValue *fps;
- // const GValue *par;
- // guint extradata_size;
- // guint8 *extradata;
+ 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->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;
+ }
- /* FFmpeg Specific Values */
- const GstBuffer *buf;
- const GValue *value;
+ // 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;
+ }
- structure = gst_caps_get_structure (caps, 0);
+ GST_DEBUG_OBJECT (emulenc, "probing caps");
+ i = pixfmt = 0;
- value = gst_structure_get_value (structure, "codec_data");
- if (value) {
- buf = GST_BUFFER_CAST (gst_value_get_mini_object (value));
- emulenc->extradata_size = GST_BUFFER_SIZE (buf);
- emulenc->extradata = GST_BUFFER_DATA (buf);
- } else {
- CODEC_LOG (2, "no codec data\n");
- emulenc->extradata_size = 0;
- emulenc->extradata = NULL;
+#if 0
+ for (pixfmt = 0; ; pixfmt++) {
+ GstCaps *tmpcaps;
+
+ if (oclass->codec->pix_fmts) {
+ 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 = get_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");
}
-#if 1 /* video type */
- /* Common Properites, width, height and etc. */
- gst_structure_get_int (structure, "width", &width);
- gst_structure_get_int (structure, "height", &height);
- gst_structure_get_int (structure, "bpp", &bits_per_coded_sample);
+ GST_DEBUG_OBJECT (emulenc, "pixfmt: %d", pixfmt);
+ if (pixfmt >= PIX_FMT_NB) {
+ GST_WARING ("Invalid pixfmt, breaking out");
+ break;
+ }
- emulenc->format.video.width = width;
- emulenc->format.video.height = height;
+ ctx = g_malloc0 (sizeof(CodecContext));
+ if (!ctx) {
+ GST_DEBUG_OBJECT (emulenc, "no context");
+ break;
+ }
- fps = gst_structure_get_value (structure, "framerate");
- if (fps) {
- emulenc->format.video.framerate_den = gst_value_get_fraction_numerator (fps);
- emulenc->format.video.framerate_num = gst_value_get_fraction_denominator (fps);
+ 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 ();
+ }
+ tmpcasp = 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);
}
#if 0
- par = gst_structure_get_value (structure, "pixel-aspect-ratio");
- if (par) {
- sample_aspect_ratio.num = gst_structure_get_fraction_numerator (par);
- sample_aspect_ratio.den = gst_structure_get_fraction_denominator (par);
+ if (ctx->priv_data) {
+ gst_emul_avcodec_close (ctx, emulenc->dev);
}
#endif
+ g_free (ctx);
+ }
#endif
-#if 0 /* audio type */
- gst_structure_get_int (structure, "channels", &channels);
- gst_structure_get_int (structure, "rate", &sample_rate);
- gst_structure_get_int (structure, "block_align", &block_align);
- gst_structure_get_int (structure, "bitrate", &bit_rate);
+ 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;
+ }
- emulenc->format.audio.channels = channels;
- emulenc->format.audio.samplerate = sample_rate;
-#endif
+ 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
+static gboolean
gst_emulenc_setcaps (GstPad *pad, GstCaps *caps)
{
GstEmulEnc *emulenc;
GstEmulEncClass *oclass;
- gboolean ret = TRUE;
+ GstCaps *other_caps;
+ GstCaps *allowed_caps;
+ GstCaps *icaps;
+ enum PixelFormat pix_fmt;
emulenc = (GstEmulEnc *) (gst_pad_get_parent (pad));
oclass = (GstEmulEncClass *) (G_OBJECT_GET_CLASS (emulenc));
+#if 0
if (emulenc->opend) {
- gst_emul_deinit ();
+ gst_emul_avcodec_close (emulenc->context, emulenc->dev);
emulenc->opened = FALSE;
gst_pad_set_caps (emulenc->srcpad, NULL);
}
+#endif
- gst_emul_caps_with_codectype (codec_type, caps);
-
- if (!time_base.den) {
- time_base.den = 25;
- time_base.num = 1;
- } else if (strcmp( ,"mpeg4") == 0) {
+ gst_emul_caps_with_codectype (oclass->codec->media_type, caps);
+
+ 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;
+
// open codec
+ if (gst_emul_avcodec_open (emulenc->context,
+ oclass->codec, emulenc->dev) < 0) {
+ GST_DEBUG_OBJECT (emulenc, "tzenc_%s: Failed to open codec",
+ oclass->codec->name);
+ return FALSE;
+ }
- if (gst_emul_codec_dev_open (emulenc) < 0) {
- CODEC_LOG(1, "failed to access %s or mmap operation\n", CODEC_DEV);
- gst_object_unref (emulenc);
+ if (pix_fmt != emulenc->context->video.pix_fmt) {
+ gst_emul_avcodec_close (emulenc->context, emulenc->dev);
+ GST_DEBUG_OBJECT (emulenc,
+ "tzenc_%s: AV wants different colorspace (%d given, %d wanted)",
+ oclass->codec->name, pix_fmt, emulenc->context->video.pix_fmt);
return FALSE;
}
- if (gst_emul_codec_init (emulenc) < 0) {
- CODEC_LOG(1, "cannot initialize codec\n");
- gst_object_unref (emulenc);
+ if (oclass->codec->media_type == AVMEDIA_TYPE_VIDEO
+ && pix_fmt == PIX_FMT_NONE) {
+ GST_DEBUG_OBJECT (emulenc, "tzenc_%s: 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_emul_caps_with_codecid (codec_id, codec_type, allowed_caps);
-
- other_caps = gst_emul_codecname_to_caps (codec_id, TRUE);
+ 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) {
- // deinit
+ gst_emul_avcodec_close (emulenc->context, emulenc->dev);
return FALSE;
}
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)) {
- // deinit
+ gst_emul_avcodec_close (emulenc->context, emulenc->dev);
gst_caps_unref (icaps);
return FALSE;
}
return TRUE;
}
-static gboolean
-gst_emulenc_event_video (GstPad *pad, GstEvent *event)
+static void
+gst_emulenc_setup_working_buf (GstEmulEnc *emulenc)
{
- GstEmulEnc *emulenc;
- emulenc = (GstEmulEnc *) gst_pad_get_parent (pad);
+ guint wanted_size =
+ emulenc->context->video.width * emulenc->context->video.height * 6 +
+ FF_MIN_BUFFER_SIZE;
- switch (GST_TYPE_EVENT (event)) {
- case GST_EVENT_EOS:
- CODEC_LOG(2, "received GST_EVENT_EOS\n");
- // flush_buffers
- break;
- case GST_EVENT_CUSTOM_DOWNSTREAM:
- CODEC_LOG(2, "received GST_EVENT_CUSTOM_DOWNSTREAM\n");
- break;
+ 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);
}
-
- return gst_pad_push_event (emulenc->srcpad, event);
+// TODO
+// emulenc->buffer_size = wanted_size;
}
-static gboolean
-gst_emulenc_event_src (GstPad *pad, GstEvent *event)
+GstFlowReturn
+gst_emulenc_chain_video (GstPad *pad, GstBuffer *buffer)
{
- switch (GST_EVENT_TYPE (event)) {
- default:
- break
+ 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
- return TRUE;
-}
+ 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);
-// minimum encoding buffer size.
-// Used to avoid some checks during header writing.
-#define FF_MIN_BUFFER_SIZE 16384
+ gst_emulenc_setup_working_buf (emulenc);
-static inst
-gst_emul_encode_video (uint8_t *outbuf, int buf_size,
- uint8_t *pict_buf, uint32_t pict_buf_size)
-{
- GstEmulEnc *emulenc = (GetEmulEnc *) (GST_PAD_PARENT (pad));
- int size = 0, api_index = CODEC_ENCODE_VIDEO;
- int ret;
+#if 0
+ ret_size =
+ emul_avcodec_encode_video (emulenc->context, emulenc->working_buf,
+ emulenc->working_buf_size, emulenc->picture,
+ GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), emulenc->dev);
+#endif
- ret = write ();
+ if (ret_size < 0) {
+ GstEmulEncClass *oclass =
+ (GstEmulEncClass *) (G_OBJECT_GET_CLASS (emulenc));
+ GST_ERROR_OBJECT (emulenc,
+ "tzenc_%s: failed to encode buffer", oclass->codec->name);
+ gst_buffer_unref (buffer);
+ return GST_FLOW_OK;
+ }
- return ret;
+#if 0
+ 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
+#endif
+
+ 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 (buffer);
+ GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (outbuf);
+#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);
}
-static GstFlowReturn
+GstFlowReturn
gst_emulenc_encode_audio (GstEmulEnc *emulenc, guint8 *audio_in,
guint in_size, guint max_size, GstClockTime timestamp,
GstClockTime duration, gboolean discont)
{
GstBuffer *outbuf;
- guint8_t *audio_out;
+ guint8 *audio_out;
gint res;
GstFlowReturn ret;
- int size = 0, api_index = CODEC_ENCODE_AUDIO;
+ int size = 0;
outbuf = gst_buffer_new_alloc (max_size + FF_MIN_BUFFER_SIZE);
audio_out = GST_BUFFER_DATA (outbuf);
- // copy params to qemu
-
- res = write();
+ GST_LOG_OBJECT (emulenc, "encoding buffer of max size %d", max_size);
+ if (emulenc->buffer_size != max_size) {
+ emulenc->buffer_size = max_size;
+ }
- // copy output and out params from qemu
+ res = emul_avcodec_encode_audio (emulenc->context, audio_out, max_size,
+ (short *) 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
-
+ 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;
}
-#if 0
-static void
-emulenc_setup_working_buf (GstEmulEnc * emulenc)
-{
- guint wanted_size =
- ffmpegenc->context->width * ffmpegenc->context->height * 6 +
- FF_MIN_BUFFER_SIZE;
-
- /* Above is the buffer size used by ffmpeg/ffmpeg.c */
- if (ffmpegenc->working_buf == NULL ||
- ffmpegenc->working_buf_size != wanted_size) {
- if (ffmpegenc->working_buf)
- g_free (ffmpegenc->working_buf);
- ffmpegenc->working_buf_size = wanted_size;
- ffmpegenc->working_buf = g_malloc (ffmpegenc->working_buf_size);
- }
- ffmpegenc->buffer_size = wanted_size;
-}
-#endif
-
-static GstFlowReturn
-gst_emulenc_chain_video (GstPad *pad, GstBuffer *buffer)
-{
- GstEmulEnc *emulenc = (GetEmulEnc *) (GST_PAD_PARENT (pad));
- GstBuffer *outbuf;
- gint in_size = 0;
-
- // setup_working_buf
- // width * height * 6 + FF_MIN_BUFFER_SIZE
- //
-
-// gst_emul_encode_video ();
-
- outbuf = gst_buffer_new_and_alloc (ret_size);
- memcpy (GST_BUFFER_DATA(outbuf), , ret_size);
- GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buffer);
- GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (outbuf);
-
- gst_buffer_set_caps (outbuf, GST_PAD_CAPS (emulenc->srcpad));
-
- gst_buffer_unref (buffer);
-
- return gst_pad_push (emulenc->srcpad, outbuf);
-}
-
static GstFlowReturn
gst_emulenc_chain_audio (GstPad *pad, GstBuffer *buffer)
{
GstEmulEnc *emulenc;
GstEmulEncClass *oclass;
GstClockTime timestamp, duration;
- guint size;
+ guint in_size, frame_size;
+ gint osize;
GstFlowReturn ret;
+ gint out_size;
gboolean discont;
+ gint8 *in_data;
+ CodecContext *ctx;
emulenc = (GstEmulEnc *) (GST_OBJECT_PARENT (pad));
oclass = (GstEmulEncClass *) G_OBJECT_GET_CLASS (emulenc);
- size = GST_BUFFER_SIZE (buffer);
+ 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);
- if (discont) {
- gst_adapter_clear (emulenc->adapter);
- }
-
-// gst_adapter_push (emulenc->adapter, 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);
-// TODO
-// gst_emul_encode_audio
+#if 0
+
+ frame_size = ctx->frame_size;
+ osize = av_get_bits_per_sample_format (ctx->audio.sample_fmt) / 8;
+
+ 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;
+
+ upsteam +=
+ 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 {
+ 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;
+ }
+
+ 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));
+ }
+ }
+#endif
return GST_FLOW_OK;
}
-static GstStateChangeReturn
+static void
+gst_emulenc_flush_buffers (GstEmulEnc *emulenc, gboolean send)
+{
+ GstBuffer *outbuf, *inbuf;
+ gint ret_size;
+
+ GST_DEBUG_OBJECT (emulenc, "flushing buffers with sending %d", send);
+
+#if 0
+ if (!emulenc->opend) {
+ while (!g_queue_is_empty (emulenc->delay)) {
+ gst_buffer_unref (g_queue_pop_head (emulenc->delay));
+ }
+ }
+
+ while (!g_queue_is_empty (emulenc->delay)) {
+ emulenc_setup_working_buf (emulenc);
+
+ ret_size = emul_avcodec_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,
+ "tzenc_%s: 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 0
+ if (gst_structure_has_name (s, "GstForceKeyUnit")) {
+ 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 0
+ if (gst_structure_has_name (s, "GstForceKeyUnit")) {
+ GST_OBJECT_LOCK (emulenc);
+ emulenc->force_keyframe = TRUE;
+ GST_OBJECT_UNLOCK (emulenc);
+ forward = FALSE;
+ gst_event_unref (event);
+ }
+#endif
+ }
+ 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;
+ GstEmulEnc *emulenc = (GstEmulEnc*)element;
+ GstStateChangeReturn ret;
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+ switch (transition) {
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- // flush buffer
- gst_emul_codec_deinit (emulenc);
- default:
- break;
+ switch (transition) {
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ gst_emulenc_flush_buffers (emulenc, FALSE);
+#if 0
+ if (emulenc->opened) {
+ gst_emul_avcodec_close (emulenc->context, emulenc->dev);
+ emulenc->opened = FALSE;
}
+#endif
+ gst_adapter_clear (emulenc->adapter);
- return ret;
+#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
CodecElement *codec = NULL;
/* register element */
- while ((elem = g_list_next (element))) {
+ while ((elem = g_list_next (elem))) {
codec = (CodecElement *)elem->data;
if (!codec) {
ret = FALSE;
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);
+ g_type_set_qdata (type, GST_EMULENC_PARAMS_QDATA, (gpointer) codec);
}
if (!gst_element_register (plugin, type_name, rank, type)) {
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,
buf = GST_BUFFER_CAST (gst_value_get_mini_object (value));
size = GST_BUFFER_SIZE (buf);
data = GST_BUFFER_DATA (buf);
- printf("extradata: %p, size: %d\n", ctx->codecdata, ctx->codecdata_size);
+ printf("extradata: %p, size: %d\n", data, size);
if (ctx->codecdata) {
g_free (ctx->codecdata);
caps = gst_caps_new_simple (mimetype,
"width", G_TYPE_INT, ctx->video.width,
- "height", G_TYPE_INT, ctx->video.height);
+ "height", G_TYPE_INT, ctx->video.height, NULL);
- num = ctx->video.fps_d / 1;
- denom = ctx->video.fps_d;
+ 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);
break;
}
- if (caps != NULL) {
+ if (caps == NULL) {
if (bpp != 0) {
if (r_mask != 0) {
if (a_mask) {
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;
+}
+++ /dev/null
-/*
- * GStreamer
- * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>
- * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
- * Copyright (C) 2012 kt <<user@hostname.org>>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Alternatively, the contents of this file may be used under the
- * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
- * which case the following provisions apply instead of the ones
- * mentioned above:
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:element-myfilter
- *
- * FIXME:Describe myfilter here.
- *
- * <refsect2>
- * <title>Example launch line</title>
- * |[
- * gst-launch -v -m fakesrc ! myfilter ! fakesink silent=TRUE
- * ]|
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <gst/gst.h>
-
-#include "gstmyfilter.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_my_filter_debug);
-#define GST_CAT_DEFAULT gst_my_filter_debug
-
-/* Filter signals and args */
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
-
-enum
-{
- PROP_0,
- PROP_SILENT
-};
-
-/* the capabilities of the inputs and outputs.
- *
- * describe the real formats here.
- */
-static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("ANY")
- );
-
-static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("ANY")
- );
-
-GST_BOILERPLATE (GstMyFilter, gst_my_filter, GstElement,
- GST_TYPE_ELEMENT);
-
-static void gst_my_filter_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_my_filter_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-static gboolean gst_my_filter_set_caps (GstPad * pad, GstCaps * caps);
-static GstFlowReturn gst_my_filter_chain (GstPad * pad, GstBuffer * buf);
-
-/* GObject vmethod implementations */
-
-static void
-gst_my_filter_base_init (gpointer gclass)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
-
- gst_element_class_set_details_simple(element_class,
- "MyFilter",
- "FIXME:Generic",
- "FIXME:Generic Template Element",
- "kt <<user@hostname.org>>");
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&src_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sink_factory));
-}
-
-/* initialize the myfilter's class */
-static void
-gst_my_filter_class_init (GstMyFilterClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
-
- gobject_class->set_property = gst_my_filter_set_property;
- gobject_class->get_property = gst_my_filter_get_property;
-
- g_object_class_install_property (gobject_class, PROP_SILENT,
- g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?",
- FALSE, G_PARAM_READWRITE));
-}
-
-/* initialize the new element
- * instantiate pads and add them to element
- * set pad calback functions
- * initialize instance structure
- */
-static void
-gst_my_filter_init (GstMyFilter * filter,
- GstMyFilterClass * gclass)
-{
- filter->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
- gst_pad_set_setcaps_function (filter->sinkpad,
- GST_DEBUG_FUNCPTR(gst_my_filter_set_caps));
- gst_pad_set_getcaps_function (filter->sinkpad,
- GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps));
- gst_pad_set_chain_function (filter->sinkpad,
- GST_DEBUG_FUNCPTR(gst_my_filter_chain));
-
- filter->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
- gst_pad_set_getcaps_function (filter->srcpad,
- GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps));
-
- gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
- gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
- filter->silent = FALSE;
-}
-
-static void
-gst_my_filter_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstMyFilter *filter = GST_MYFILTER (object);
-
- switch (prop_id) {
- case PROP_SILENT:
- filter->silent = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_my_filter_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstMyFilter *filter = GST_MYFILTER (object);
-
- switch (prop_id) {
- case PROP_SILENT:
- g_value_set_boolean (value, filter->silent);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/* GstElement vmethod implementations */
-
-/* this function handles the link with other elements */
-static gboolean
-gst_my_filter_set_caps (GstPad * pad, GstCaps * caps)
-{
- GstMyFilter *filter;
- GstPad *otherpad;
-
- filter = GST_MYFILTER (gst_pad_get_parent (pad));
- otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad;
- gst_object_unref (filter);
-
- return gst_pad_set_caps (otherpad, caps);
-}
-
-/* chain function
- * this function does the actual processing
- */
-static GstFlowReturn
-gst_my_filter_chain (GstPad * pad, GstBuffer * buf)
-{
- GstMyFilter *filter;
-
- filter = GST_MYFILTER (GST_OBJECT_PARENT (pad));
-
- if (filter->silent == FALSE)
- g_print ("I'm plugged, therefore I'm in.\n");
-
- /* just push out the incoming buffer without touching it */
- return gst_pad_push (filter->srcpad, buf);
-}
-
-
-/* entry point to initialize the plug-in
- * initialize the plug-in itself
- * register the element factories and other features
- */
-static gboolean
-myfilter_init (GstPlugin * myfilter)
-{
- /* debug category for fltering log messages
- *
- * exchange the string 'Template myfilter' with your description
- */
- GST_DEBUG_CATEGORY_INIT (gst_my_filter_debug, "myfilter",
- 0, "Template myfilter");
-
- return gst_element_register (myfilter, "myfilter", GST_RANK_NONE,
- GST_TYPE_MYFILTER);
-}
-
-/* PACKAGE: this is usually set by autotools depending on some _INIT macro
- * in configure.ac and then written into and defined in config.h, but we can
- * just set it ourselves here in case someone doesn't use autotools to
- * compile this code. GST_PLUGIN_DEFINE needs PACKAGE to be defined.
- */
-#ifndef PACKAGE
-#define PACKAGE "myfirstmyfilter"
-#endif
-
-/* gstreamer looks for this structure to register myfilters
- *
- * exchange the string 'Template myfilter' with your myfilter description
- */
-GST_PLUGIN_DEFINE (
- GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "myfilter",
- "Template myfilter",
- myfilter_init,
- VERSION,
- "LGPL",
- "GStreamer",
- "http://gstreamer.net/"
-)
+++ /dev/null
-/*
- * GStreamer
- * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>
- * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
- * Copyright (C) 2012 kt <<user@hostname.org>>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Alternatively, the contents of this file may be used under the
- * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
- * which case the following provisions apply instead of the ones
- * mentioned above:
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_MYFILTER_H__
-#define __GST_MYFILTER_H__
-
-#include <gst/gst.h>
-
-G_BEGIN_DECLS
-
-/* #defines don't like whitespacey bits */
-#define GST_TYPE_MYFILTER \
- (gst_my_filter_get_type())
-#define GST_MYFILTER(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MYFILTER,GstMyFilter))
-#define GST_MYFILTER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MYFILTER,GstMyFilterClass))
-#define GST_IS_MYFILTER(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MYFILTER))
-#define GST_IS_MYFILTER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MYFILTER))
-
-typedef struct _GstMyFilter GstMyFilter;
-typedef struct _GstMyFilterClass GstMyFilterClass;
-
-struct _GstMyFilter
-{
- GstElement element;
-
- GstPad *sinkpad, *srcpad;
-
- gboolean silent;
-};
-
-struct _GstMyFilterClass
-{
- GstElementClass parent_class;
-};
-
-GType gst_my_filter_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_MYFILTER_H__ */
+++ /dev/null
-/*
- * GStreamer
- * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>
- * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
- * Copyright (C) YEAR AUTHOR_NAME AUTHOR_EMAIL
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Alternatively, the contents of this file may be used under the
- * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
- * which case the following provisions apply instead of the ones
- * mentioned above:
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:element-plugin
- *
- * FIXME:Describe plugin here.
- *
- * <refsect2>
- * <title>Example launch line</title>
- * |[
- * gst-launch -v -m fakesrc ! plugin ! fakesink silent=TRUE
- * ]|
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <gst/gst.h>
-
-#include "gstplugin.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_plugin_template_debug);
-#define GST_CAT_DEFAULT gst_plugin_template_debug
-
-/* Filter signals and args */
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
-
-enum
-{
- PROP_0,
- PROP_SILENT
-};
-
-/* the capabilities of the inputs and outputs.
- *
- * describe the real formats here.
- */
-static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("ANY")
- );
-
-static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("ANY")
- );
-
-GST_BOILERPLATE (GstPluginTemplate, gst_plugin_template, GstElement,
- GST_TYPE_ELEMENT);
-
-static void gst_plugin_template_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_plugin_template_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-static gboolean gst_plugin_template_set_caps (GstPad * pad, GstCaps * caps);
-static GstFlowReturn gst_plugin_template_chain (GstPad * pad, GstBuffer * buf);
-
-/* GObject vmethod implementations */
-
-static void
-gst_plugin_template_base_init (gpointer gclass)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
-
- gst_element_class_set_details_simple(element_class,
- "Plugin",
- "FIXME:Generic",
- "FIXME:Generic Template Element",
- "AUTHOR_NAME AUTHOR_EMAIL");
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&src_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sink_factory));
-}
-
-/* initialize the plugin's class */
-static void
-gst_plugin_template_class_init (GstPluginTemplateClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
-
- gobject_class->set_property = gst_plugin_template_set_property;
- gobject_class->get_property = gst_plugin_template_get_property;
-
- g_object_class_install_property (gobject_class, PROP_SILENT,
- g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?",
- FALSE, G_PARAM_READWRITE));
-}
-
-/* initialize the new element
- * instantiate pads and add them to element
- * set pad calback functions
- * initialize instance structure
- */
-static void
-gst_plugin_template_init (GstPluginTemplate * filter,
- GstPluginTemplateClass * gclass)
-{
- filter->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
- gst_pad_set_setcaps_function (filter->sinkpad,
- GST_DEBUG_FUNCPTR(gst_plugin_template_set_caps));
- gst_pad_set_getcaps_function (filter->sinkpad,
- GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps));
- gst_pad_set_chain_function (filter->sinkpad,
- GST_DEBUG_FUNCPTR(gst_plugin_template_chain));
-
- filter->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
- gst_pad_set_getcaps_function (filter->srcpad,
- GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps));
-
- gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
- gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
- filter->silent = FALSE;
-}
-
-static void
-gst_plugin_template_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstPluginTemplate *filter = GST_PLUGIN_TEMPLATE (object);
-
- switch (prop_id) {
- case PROP_SILENT:
- filter->silent = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_plugin_template_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstPluginTemplate *filter = GST_PLUGIN_TEMPLATE (object);
-
- switch (prop_id) {
- case PROP_SILENT:
- g_value_set_boolean (value, filter->silent);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/* GstElement vmethod implementations */
-
-/* this function handles the link with other elements */
-static gboolean
-gst_plugin_template_set_caps (GstPad * pad, GstCaps * caps)
-{
- GstPluginTemplate *filter;
- GstPad *otherpad;
-
- filter = GST_PLUGIN_TEMPLATE (gst_pad_get_parent (pad));
- otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad;
- gst_object_unref (filter);
-
- return gst_pad_set_caps (otherpad, caps);
-}
-
-/* chain function
- * this function does the actual processing
- */
-static GstFlowReturn
-gst_plugin_template_chain (GstPad * pad, GstBuffer * buf)
-{
- GstPluginTemplate *filter;
-
- filter = GST_PLUGIN_TEMPLATE (GST_OBJECT_PARENT (pad));
-
- if (filter->silent == FALSE)
- g_print ("I'm plugged, therefore I'm in.\n");
-
- /* just push out the incoming buffer without touching it */
- return gst_pad_push (filter->srcpad, buf);
-}
-
-
-/* entry point to initialize the plug-in
- * initialize the plug-in itself
- * register the element factories and other features
- */
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- /* debug category for fltering log messages
- *
- * exchange the string 'Template plugin' with your description
- */
- GST_DEBUG_CATEGORY_INIT (gst_plugin_template_debug, "plugin",
- 0, "Template plugin");
-
- return gst_element_register (plugin, "plugin", GST_RANK_NONE,
- GST_TYPE_PLUGIN_TEMPLATE);
-}
-
-/* PACKAGE: this is usually set by autotools depending on some _INIT macro
- * in configure.ac and then written into and defined in config.h, but we can
- * just set it ourselves here in case someone doesn't use autotools to
- * compile this code. GST_PLUGIN_DEFINE needs PACKAGE to be defined.
- */
-#ifndef PACKAGE
-#define PACKAGE "myfirstplugin"
-#endif
-
-/* gstreamer looks for this structure to register plugins
- *
- * exchange the string 'Template plugin' with your plugin description
- */
-GST_PLUGIN_DEFINE (
- GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "plugin",
- "Template plugin",
- plugin_init,
- VERSION,
- "LGPL",
- "GStreamer",
- "http://gstreamer.net/"
-)
+++ /dev/null
-/*
- * GStreamer
- * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>
- * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
- * Copyright (C) YEAR AUTHOR_NAME AUTHOR_EMAIL
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Alternatively, the contents of this file may be used under the
- * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
- * which case the following provisions apply instead of the ones
- * mentioned above:
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_PLUGIN_TEMPLATE_H__
-#define __GST_PLUGIN_TEMPLATE_H__
-
-#include <gst/gst.h>
-
-G_BEGIN_DECLS
-
-/* #defines don't like whitespacey bits */
-#define GST_TYPE_PLUGIN_TEMPLATE \
- (gst_plugin_template_get_type())
-#define GST_PLUGIN_TEMPLATE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PLUGIN_TEMPLATE,GstPluginTemplate))
-#define GST_PLUGIN_TEMPLATE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PLUGIN_TEMPLATE,GstPluginTemplateClass))
-#define GST_IS_PLUGIN_TEMPLATE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PLUGIN_TEMPLATE))
-#define GST_IS_PLUGIN_TEMPLATE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PLUGIN_TEMPLATE))
-
-typedef struct _GstPluginTemplate GstPluginTemplate;
-typedef struct _GstPluginTemplateClass GstPluginTemplateClass;
-
-struct _GstPluginTemplate
-{
- GstElement element;
-
- GstPad *sinkpad, *srcpad;
-
- gboolean silent;
-};
-
-struct _GstPluginTemplateClass
-{
- GstElementClass parent_class;
-};
-
-GType gst_plugin_template_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_PLUGIN_TEMPLATE_H__ */
+++ /dev/null
-/*
- * GStreamer
- * Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
- * Copyright (C) YEAR AUTHOR_NAME AUTHOR_EMAIL
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:element-plugin
- *
- * FIXME:Describe plugin here.
- *
- * <refsect2>
- * <title>Example launch line</title>
- * |[
- * gst-launch -v -m fakesrc ! plugin ! fakesink silent=TRUE
- * ]|
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst.h>
-#include <gst/base/gstbasetransform.h>
-#include <gst/controller/gstcontroller.h>
-
-#include "gsttransform.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_plugin_template_debug);
-#define GST_CAT_DEFAULT gst_plugin_template_debug
-
-/* Filter signals and args */
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
-
-enum
-{
- PROP_0,
- PROP_SILENT,
-};
-
-/* the capabilities of the inputs and outputs.
- *
- * FIXME:describe the real formats here.
- */
-static GstStaticPadTemplate sink_template =
-GST_STATIC_PAD_TEMPLATE (
- "sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("ANY")
-);
-
-static GstStaticPadTemplate src_template =
-GST_STATIC_PAD_TEMPLATE (
- "src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("ANY")
-);
-
-/* debug category for fltering log messages
- *
- * FIXME:exchange the string 'Template plugin' with your description
- */
-#define DEBUG_INIT(bla) \
- GST_DEBUG_CATEGORY_INIT (gst_plugin_template_debug, "plugin", 0, "Template plugin");
-
-GST_BOILERPLATE_FULL (GstPluginTemplate, gst_plugin_template, GstBaseTransform,
- GST_TYPE_BASE_TRANSFORM, DEBUG_INIT);
-
-static void gst_plugin_template_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_plugin_template_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-static GstFlowReturn gst_plugin_template_transform_ip (GstBaseTransform * base,
- GstBuffer * outbuf);
-
-/* GObject vmethod implementations */
-
-static void
-gst_plugin_template_base_init (gpointer klass)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-
- gst_element_class_set_details_simple (element_class,
- "Plugin",
- "Generic/Filter",
- "FIXME:Generic Template Filter",
- "AUTHOR_NAME AUTHOR_EMAIL");
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&src_template));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sink_template));
-}
-
-/* initialize the plugin's class */
-static void
-gst_plugin_template_class_init (GstPluginTemplateClass * klass)
-{
- GObjectClass *gobject_class;
-
- gobject_class = (GObjectClass *) klass;
- gobject_class->set_property = gst_plugin_template_set_property;
- gobject_class->get_property = gst_plugin_template_get_property;
-
- g_object_class_install_property (gobject_class, PROP_SILENT,
- g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?",
- FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
-
- GST_BASE_TRANSFORM_CLASS (klass)->transform_ip =
- GST_DEBUG_FUNCPTR (gst_plugin_template_transform_ip);
-}
-
-/* initialize the new element
- * initialize instance structure
- */
-static void
-gst_plugin_template_init (GstPluginTemplate *filter, GstPluginTemplateClass * klass)
-{
- filter->silent = FALSE;
-}
-
-static void
-gst_plugin_template_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstPluginTemplate *filter = GST_PLUGIN_TEMPLATE (object);
-
- switch (prop_id) {
- case PROP_SILENT:
- filter->silent = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_plugin_template_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstPluginTemplate *filter = GST_PLUGIN_TEMPLATE (object);
-
- switch (prop_id) {
- case PROP_SILENT:
- g_value_set_boolean (value, filter->silent);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/* GstBaseTransform vmethod implementations */
-
-/* this function does the actual processing
- */
-static GstFlowReturn
-gst_plugin_template_transform_ip (GstBaseTransform * base, GstBuffer * outbuf)
-{
- GstPluginTemplate *filter = GST_PLUGIN_TEMPLATE (base);
-
- if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (outbuf)))
- gst_object_sync_values (G_OBJECT (filter), GST_BUFFER_TIMESTAMP (outbuf));
-
- if (filter->silent == FALSE)
- g_print ("I'm plugged, therefore I'm in.\n");
-
- /* FIXME: do something interesting here. This simply copies the source
- * to the destination. */
-
- return GST_FLOW_OK;
-}
-
-
-/* entry point to initialize the plug-in
- * initialize the plug-in itself
- * register the element factories and other features
- */
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- /* initialize gst controller library */
- gst_controller_init(NULL, NULL);
-
- return gst_element_register (plugin, "plugin", GST_RANK_NONE,
- GST_TYPE_PLUGIN_TEMPLATE);
-}
-
-/* gstreamer looks for this structure to register plugins
- *
- * FIXME:exchange the string 'Template plugin' with you plugin description
- */
-GST_PLUGIN_DEFINE (
- GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "plugin",
- "Template plugin",
- plugin_init,
- VERSION,
- "LGPL",
- "GStreamer",
- "http://gstreamer.net/"
-)
+++ /dev/null
-/*
- * GStreamer
- * Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
- * Copyright (C) YEAR AUTHOR_NAME AUTHOR_EMAIL
- *
- * 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.
- */
-
-#ifndef __GST_PLUGIN_TEMPLATE_H__
-#define __GST_PLUGIN_TEMPLATE_H__
-
-#include <gst/gst.h>
-#include <gst/base/gstbasetransform.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_PLUGIN_TEMPLATE \
- (gst_plugin_template_get_type())
-#define GST_PLUGIN_TEMPLATE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PLUGIN_TEMPLATE,GstPluginTemplate))
-#define GST_PLUGIN_TEMPLATE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PLUGIN_TEMPLATE,GstPluginTemplateClass))
-#define GST_IS_PLUGIN_TEMPLATE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PLUGIN_TEMPLATE))
-#define GST_IS_PLUGIN_TEMPLATE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PLUGIN_TEMPLATE))
-
-typedef struct _GstPluginTemplate GstPluginTemplate;
-typedef struct _GstPluginTemplateClass GstPluginTemplateClass;
-
-struct _GstPluginTemplate {
- GstBaseTransform element;
-
- gboolean silent;
-};
-
-struct _GstPluginTemplateClass {
- GstBaseTransformClass parent_class;
-};
-
-GType gst_plugin_template_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_PLUGIN_TEMPLATE_H__ */
--- /dev/null
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_PIXFMT_H
+#define AVUTIL_PIXFMT_H
+
+/**
+ * @file
+ * pixel format definitions
+ *
+ * @warning This file has to be considered an internal but installed
+ * header, so it should not be directly included in your projects.
+ */
+
+// #include "libavutil/avconfig.h"
+
+/**
+ * Pixel format. Notes:
+ *
+ * PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA
+ * color is put together as:
+ * (A << 24) | (R << 16) | (G << 8) | B
+ * This is stored as BGRA on little-endian CPU architectures and ARGB on
+ * big-endian CPUs.
+ *
+ * When the pixel format is palettized RGB (PIX_FMT_PAL8), the palettized
+ * image data is stored in AVFrame.data[0]. The palette is transported in
+ * AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is
+ * formatted the same as in PIX_FMT_RGB32 described above (i.e., it is
+ * also endian-specific). Note also that the individual RGB palette
+ * components stored in AVFrame.data[1] should be in the range 0..255.
+ * This is important as many custom PAL8 video codecs that were designed
+ * to run on the IBM VGA graphics adapter use 6-bit palette components.
+ *
+ * For all the 8bit per pixel formats, an RGB32 palette is in data[1] like
+ * for pal8. This palette is filled in automatically by the function
+ * allocating the picture.
+ *
+ * Note, make sure that all newly added big endian formats have pix_fmt&1==1
+ * and that all newly added little endian formats have pix_fmt&1==0
+ * this allows simpler detection of big vs little endian.
+ */
+enum PixelFormat {
+ PIX_FMT_NONE= -1,
+ PIX_FMT_YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
+ PIX_FMT_YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
+ PIX_FMT_RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB...
+ PIX_FMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR...
+ PIX_FMT_YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
+ PIX_FMT_YUV444P, ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
+ PIX_FMT_YUV410P, ///< planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
+ PIX_FMT_YUV411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
+ PIX_FMT_GRAY8, ///< Y , 8bpp
+ PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb
+ PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb
+ PIX_FMT_PAL8, ///< 8 bit with PIX_FMT_RGB32 palette
+ PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV420P and setting color_range
+ PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV422P and setting color_range
+ PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV444P and setting color_range
+ PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing
+ PIX_FMT_XVMC_MPEG2_IDCT,
+ PIX_FMT_UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
+ PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
+ PIX_FMT_BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
+ PIX_FMT_BGR4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits
+ PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb)
+ PIX_FMT_RGB8, ///< packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
+ PIX_FMT_RGB4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits
+ PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb)
+ PIX_FMT_NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V)
+ PIX_FMT_NV21, ///< as above, but U and V bytes are swapped
+
+ PIX_FMT_ARGB, ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
+ PIX_FMT_RGBA, ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
+ PIX_FMT_ABGR, ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
+ PIX_FMT_BGRA, ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
+
+ PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian
+ PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian
+ PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
+ PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of PIX_FMT_YUV440P and setting color_range
+ PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
+ PIX_FMT_VDPAU_H264,///< H.264 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+ PIX_FMT_VDPAU_MPEG1,///< MPEG-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+ PIX_FMT_VDPAU_MPEG2,///< MPEG-2 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+ PIX_FMT_VDPAU_WMV3,///< WMV3 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+ PIX_FMT_VDPAU_VC1, ///< VC-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+ PIX_FMT_RGB48BE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian
+ PIX_FMT_RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian
+
+ PIX_FMT_RGB565BE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
+ PIX_FMT_RGB565LE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
+ PIX_FMT_RGB555BE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), big-endian, most significant bit to 0
+ PIX_FMT_RGB555LE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), little-endian, most significant bit to 0
+
+ PIX_FMT_BGR565BE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian
+ PIX_FMT_BGR565LE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian
+ PIX_FMT_BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), big-endian, most significant bit to 1
+ PIX_FMT_BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), little-endian, most significant bit to 1
+
+ PIX_FMT_VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers
+ PIX_FMT_VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers
+ PIX_FMT_VAAPI_VLD, ///< HW decoding through VA API, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+
+ PIX_FMT_YUV420P16LE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
+ PIX_FMT_YUV420P16BE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
+ PIX_FMT_YUV422P16LE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
+ PIX_FMT_YUV422P16BE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
+ PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
+ PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+ PIX_FMT_VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+ PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer
+
+ PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), little-endian, most significant bits to 0
+ PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0
+ PIX_FMT_BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), little-endian, most significant bits to 1
+ PIX_FMT_BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), big-endian, most significant bits to 1
+ PIX_FMT_Y400A, ///< 8bit gray, 8bit alpha
+ PIX_FMT_BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian
+ PIX_FMT_BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian
+ PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
+ PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
+ PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
+ PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
+ PIX_FMT_YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
+ PIX_FMT_YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
+ PIX_FMT_YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
+ PIX_FMT_YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+ PIX_FMT_YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
+ PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+ PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
+};
+
+#if AV_HAVE_BIGENDIAN
+# define PIX_FMT_NE(be, le) PIX_FMT_##be
+#else
+# define PIX_FMT_NE(be, le) PIX_FMT_##le
+#endif
+
+#define PIX_FMT_RGB32 PIX_FMT_NE(ARGB, BGRA)
+#define PIX_FMT_RGB32_1 PIX_FMT_NE(RGBA, ABGR)
+#define PIX_FMT_BGR32 PIX_FMT_NE(ABGR, RGBA)
+#define PIX_FMT_BGR32_1 PIX_FMT_NE(BGRA, ARGB)
+
+#define PIX_FMT_GRAY16 PIX_FMT_NE(GRAY16BE, GRAY16LE)
+#define PIX_FMT_RGB48 PIX_FMT_NE(RGB48BE, RGB48LE)
+#define PIX_FMT_RGB565 PIX_FMT_NE(RGB565BE, RGB565LE)
+#define PIX_FMT_RGB555 PIX_FMT_NE(RGB555BE, RGB555LE)
+#define PIX_FMT_RGB444 PIX_FMT_NE(RGB444BE, RGB444LE)
+#define PIX_FMT_BGR48 PIX_FMT_NE(BGR48BE, BGR48LE)
+#define PIX_FMT_BGR565 PIX_FMT_NE(BGR565BE, BGR565LE)
+#define PIX_FMT_BGR555 PIX_FMT_NE(BGR555BE, BGR555LE)
+#define PIX_FMT_BGR444 PIX_FMT_NE(BGR444BE, BGR444LE)
+
+#define PIX_FMT_YUV420P9 PIX_FMT_NE(YUV420P9BE , YUV420P9LE)
+#define PIX_FMT_YUV444P9 PIX_FMT_NE(YUV444P9BE , YUV444P9LE)
+#define PIX_FMT_YUV420P10 PIX_FMT_NE(YUV420P10BE, YUV420P10LE)
+#define PIX_FMT_YUV422P10 PIX_FMT_NE(YUV422P10BE, YUV422P10LE)
+#define PIX_FMT_YUV444P10 PIX_FMT_NE(YUV444P10BE, YUV444P10LE)
+#define PIX_FMT_YUV420P16 PIX_FMT_NE(YUV420P16BE, YUV420P16LE)
+#define PIX_FMT_YUV422P16 PIX_FMT_NE(YUV422P16BE, YUV422P16LE)
+#define PIX_FMT_YUV444P16 PIX_FMT_NE(YUV444P16BE, YUV444P16LE)
+
+#endif /* AVUTIL_PIXFMT_H */