#define GST_MARUDEC_PARAMS_QDATA g_quark_from_static_string("marudec-params")
/* indicate dts, pts, offset in the stream */
-typedef struct
-{
- gint idx;
- GstClockTime timestamp;
- GstClockTime duration;
- gint64 offset;
-} GstTSInfo;
#define GST_TS_INFO_NONE &ts_info_none
static const GstTSInfo ts_info_none = { -1, -1, -1, -1 };
-#define MAX_TS_MASK 0xff
-
-typedef struct _GstMaruDec
-{
- GstElement element;
-
- GstPad *srcpad;
- GstPad *sinkpad;
-
- CodecContext *context;
- CodecDevice *dev;
-
- union {
- struct {
- gint width, height;
- gint clip_width, clip_height;
- gint par_n, par_d;
- gint fps_n, fps_d;
- gint old_fps_n, old_fps_d;
- gboolean interlaced;
-
- enum PixelFormat pix_fmt;
- } video;
- struct {
- gint channels;
- gint samplerate;
- gint depth;
- } audio;
- } format;
-
- gboolean opened;
- gboolean discont;
- gboolean clear_ts;
-
- /* tracking DTS/PTS */
- GstClockTime next_out;
-
- /* Qos stuff */
- gdouble proportion;
- GstClockTime earliest_time;
- gint64 processed;
- gint64 dropped;
-
-
- /* GstSegment can be used for two purposes:
- * 1. performing seeks (handling seek events)
- * 2. tracking playback regions (handling newsegment events)
- */
- GstSegment segment;
-
- GstTSInfo ts_info[MAX_TS_MASK + 1];
- gint ts_idx;
-
- /* reverse playback queue */
- GList *queued;
-
-} GstMaruDec;
-
typedef struct _GstMaruDecClass
{
GstElementClass parent_class;
CODEC_LOG (DEBUG, "outbuf size of decoded video: %d\n", pict_size);
-#ifndef USE_HEAP_BUFFER
+ gst_pad_set_element_private(GST_PAD_PEER(marudec->srcpad), (gpointer)marudec);
+
/* GstPadBufferAllocFunction is mostly overridden by elements that can
* provide a hardware buffer in order to avoid additional memcpy operations.
*/
gst_pad_set_bufferalloc_function(
GST_PAD_PEER(marudec->srcpad),
(GstPadBufferAllocFunction) codec_buffer_alloc);
-#endif
ret = gst_pad_alloc_buffer_and_set_caps (marudec->srcpad,
GST_BUFFER_OFFSET_NONE, pict_size,
return ret;
}
- if ((uintptr_t) GST_BUFFER_DATA (*outbuf) % 16) {
- GST_DEBUG_OBJECT (marudec,
- "Downstream can't allocate aligned buffers.");
- gst_buffer_unref (*outbuf);
- *outbuf = new_aligned_buffer (pict_size, GST_PAD_CAPS (marudec->srcpad));
- }
-
- codec_picture_copy (marudec->context, GST_BUFFER_DATA (*outbuf),
- GST_BUFFER_SIZE (*outbuf), marudec->dev);
-
return ret;
}
CODEC_LOG (DEBUG, "leave: %s\n", __func__);
}
-static struct mem_info
-secure_device_mem (guint buf_size)
+static int
+secure_device_mem (guint buf_size, gpointer offset)
{
int ret = 0;
uint32_t opaque = 0;
CODEC_LOG (DEBUG, "enter: %s\n", __func__);
opaque = buf_size;
- ret = ioctl (device_fd, CODEC_CMD_TRY_SECURE_BUFFER, &opaque);
- if (ret == -1) {
- CODEC_LOG (DEBUG, "failed to get available buffer\n");
- info.start = NULL;
- info.offset = 0;
- } else {
- info.start = (gpointer)((uint32_t)device_mem + opaque);
- info.offset = opaque;
- CODEC_LOG (DEBUG, "acquire device_memory: 0x%x\n", opaque);
- }
+ ret = ioctl (device_fd, CODEC_CMD_SECURE_BUFFER, &opaque);
+ offset = opaque;
CODEC_LOG (DEBUG, "leave: %s\n", __func__);
- return info;
+ return ret;
}
-#ifndef USE_HEAP_BUFFER
static void
release_device_mem (gpointer start)
{
GstCaps *caps, GstBuffer **buf)
{
struct mem_info info;
+ uint32_t opaque;
+ int ret = 0;
+ GstMaruDec *marudec;
CODEC_LOG (DEBUG, "enter: %s\n", __func__);
+ opaque = size;
+
*buf = gst_buffer_new ();
- info = secure_device_mem (size);
+ marudec = (GstMaruDec *)gst_pad_get_element_private(pad);
+
+ _codec_write_to_qemu (marudec->context->index, CODEC_PICTURE_COPY,
+ 0, marudec->dev->fd);
- if (info.start == NULL) {
- CODEC_LOG (DEBUG, "can not secure memory now, so we will use heap buffer");
+ ret = ioctl (marudec->dev->fd, CODEC_CMD_GET_DATA_INTO_DEVICE_MEM, &opaque);
+
+ if (ret < 0) {
+ CODEC_LOG (DEBUG, "failed to get available buffer\n");
+ } else if (ret == 1) {
+ // FIXME: we must aligned buffer offset.
info.start = g_malloc (size);
+ info.offset = 0;
+
GST_BUFFER_FREE_FUNC (*buf) = g_free;
+
+ memcpy (info.start, (uint32_t)device_mem + opaque, size);
+ release_device_mem((uint32_t)device_mem + opaque);
+
+ CODEC_LOG (DEBUG, "we secured last buffer, so we will use heap buffer");
} else {
- CODEC_LOG (DEBUG, "device memory start: 0x%p, offset 0x%x\n", info.start, info.offset);
+ // address of "device_mem" and "opaque" is aleady aligned.
+ info.start = (gpointer)((uint32_t)device_mem + opaque);
+ info.offset = opaque;
+
GST_BUFFER_FREE_FUNC (*buf) = codec_buffer_free;
+
+ CODEC_LOG (DEBUG, "device memory start: 0x%p, offset 0x%x\n", info.start, info.offset);
}
GST_BUFFER_DATA (*buf) = GST_BUFFER_MALLOCDATA (*buf) = info.start;
return GST_FLOW_OK;
}
-#endif
int
codec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
return len;
}
-void
-codec_picture_copy (CodecContext *ctx, uint8_t *pict,
- uint32_t pict_size, CodecDevice *dev)
-{
- int fd, ret = 0;
- uint32_t opaque = 0;
- int is_direct_buffer = 0;
-
- CODEC_LOG (DEBUG, "enter: %s\n", __func__);
-
- fd = dev->fd;
- if (fd < 0) {
- GST_ERROR ("failed to get %s fd\n", CODEC_DEV);
- return;
- }
-
- if (!dev->buf) {
- GST_ERROR ("failed to get mmaped memory address\n");
- return;
- }
-
- // determine buffer located in device memory or not.
- if ((uint32_t)pict >= (uint32_t)(dev->buf) &&
- (uint32_t)pict < (uint32_t)(dev->buf) + (dev->buf_size)) {
- is_direct_buffer = 1;
- }
-
- CODEC_LOG (DEBUG, "pict_size: %d\n", pict_size);
-
- _codec_write_to_qemu (ctx->index, CODEC_PICTURE_COPY,
- 0, fd);
-
- if (is_direct_buffer) {
- // if we can use device memory as a output buffer...
-#ifdef USE_HEAP_BUFFER
- GST_ERROR ("failed to get mmaped memory address\n");
-#else
- dev->mem_info.offset = (uint32_t)pict - (uint32_t)(dev->buf);
- CODEC_LOG (DEBUG, "%d of pict: %p , device_mem: %p\n",
- ctx->index, pict, dev->buf);
- CODEC_LOG (DEBUG, "%d of picture_copy, mem_offset = 0x%x\n",
- ctx->index, dev->mem_info.offset);
-
- ret = ioctl (fd, CODEC_CMD_USE_DEVICE_MEM, &(dev->mem_info.offset));
- if (ret < 0) {
- CODEC_LOG (ERR, "failed to use device memory\n");
- return;
- }
-#endif
- } else {
- // if we can not use device memory as a output buffer,
- // we must copy data from device memory to heap buffer.
- CODEC_LOG (DEBUG, "need a memory\n");
- opaque = pict_size;
- ret = ioctl (fd, CODEC_CMD_GET_DATA_INTO_DEVICE_MEM, &opaque);
- if (ret < 0) {
- CODEC_LOG (ERR, "failed to secure device memory\n");
- return;
- }
-
- CODEC_LOG (DEBUG, "picture_copy, mem_offset = 0x%x\n", opaque);
-
- memcpy (pict, (dev->buf) + opaque, pict_size);
-
- ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &opaque);
-
- if (ret < 0) {
- CODEC_LOG (ERR, "failed to release used memory\n");
- }
- }
-
- CODEC_LOG (DEBUG, "leave: %s\n", __func__);
-}
-
int
codec_decode_audio (CodecContext *ctx, int16_t *samples,
int *have_data, uint8_t *in_buf,