2 * GStreamer codec plugin for Tizen Emulator.
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved.
7 * KiTae Kim <kt920.kim@samsung.com>
8 * SeokYeon Hwang <syeon.hwang@samsung.com>
9 * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Library General Public License for more details.
21 * You should have received a copy of the GNU Library General Public
22 * License along with this library; if not, write to the
23 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 * Boston, MA 02111-1307, USA.
32 #include "gstmaruinterface.h"
33 #include "gstmarumem.h"
34 #include "gstmarudevice.h"
37 extern gpointer device_mem;
45 typedef struct _CodecHeader {
50 typedef struct _CodecBufferId {
51 uint32_t buffer_index;
55 #define CODEC_META_DATA_SIZE 256
56 #define GET_OFFSET(buffer) ((uint32_t)buffer - (uint32_t)device_mem)
60 _codec_invoke_qemu (int32_t ctx_index, int32_t api_index,
61 uint32_t mem_offset, int fd)
63 CodecIOParams ioparam = { 0 };
65 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
67 ioparam.api_index = api_index;
68 ioparam.ctx_index = ctx_index;
69 ioparam.mem_offset = mem_offset;
70 if (ioctl (fd, CODEC_CMD_INVOKE_API_AND_RELEASE_BUFFER, &ioparam) < 0) {
71 CODEC_LOG (ERR, "failed to invoke codec APIs\n");
74 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
78 secure_device_mem (int fd, guint ctx_id, guint buf_size, gpointer* buffer)
83 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
84 opaque.buffer_index = ctx_id;
85 opaque.buffer_size = buf_size;
87 ret = ioctl (fd, CODEC_CMD_SECURE_BUFFER, &opaque);
88 /* ioctl: CODEC_CMD_SECURE_BUFFER
89 * - sets device memory offset into opaque.buffer_size
91 *buffer = (gpointer)((uint32_t)device_mem + opaque.buffer_size);
92 CODEC_LOG (DEBUG, "buffer: 0x%x\n", (int)buffer);
94 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
100 release_device_mem (int fd, gpointer start)
103 uint32_t offset = start - device_mem;
105 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
107 CODEC_LOG (DEBUG, "release device_mem start: %p, offset: 0x%x\n", start, offset);
108 ret = ioctl (fd, CODEC_CMD_RELEASE_BUFFER, &offset);
110 CODEC_LOG (ERR, "failed to release buffer\n");
113 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
117 codec_buffer_free (gpointer start)
119 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
121 release_device_mem (device_fd, start);
123 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
127 codec_buffer_alloc_and_copy (GstPad *pad, guint64 offset, guint size,
128 GstCaps *caps, GstBuffer **buf)
130 struct mem_info info;
131 CodecBufferId opaque;
135 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
137 *buf = gst_buffer_new ();
139 marudec = (GstMaruDec *)gst_pad_get_element_private(pad);
141 opaque.buffer_index = marudec->context->index;
142 opaque.buffer_size = size;
144 CODEC_LOG (DEBUG, "buffer_and_copy. ctx_id: %d\n", marudec->context->index);
145 _codec_invoke_qemu (marudec->context->index, CODEC_PICTURE_COPY,
146 0, marudec->dev->fd);
148 ret = ioctl (marudec->dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque);
151 CODEC_LOG (DEBUG, "failed to get available buffer\n");
152 } else if (ret == 1) {
153 // FIXME: we must aligned buffer offset.
154 info.start = g_malloc (size);
157 GST_BUFFER_FREE_FUNC (*buf) = g_free;
159 memcpy (info.start, device_mem + opaque.buffer_size, size);
160 release_device_mem(marudec->dev->fd, device_mem + opaque.buffer_size);
162 CODEC_LOG (DEBUG, "we secured last buffer, so we will use heap buffer\n");
164 // address of "device_mem" and "opaque" is aleady aligned.
165 info.start = (gpointer)(device_mem + opaque.buffer_size);
166 info.offset = opaque.buffer_size;
168 GST_BUFFER_FREE_FUNC (*buf) = codec_buffer_free;
170 CODEC_LOG (DEBUG, "device memory start: 0x%p, offset 0x%x\n", info.start, info.offset);
173 GST_BUFFER_DATA (*buf) = GST_BUFFER_MALLOCDATA (*buf) = info.start;
174 GST_BUFFER_SIZE (*buf) = size;
175 GST_BUFFER_OFFSET (*buf) = offset;
178 gst_buffer_set_caps (*buf, caps);
181 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
187 codec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
190 gpointer buffer = NULL;
191 CodecBufferId opaque;
193 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
195 if (ioctl(dev->fd, CODEC_CMD_GET_CONTEXT_INDEX, &ctx->index) < 0) {
197 "[%s] failed to get a context index\n", __func__);
200 CODEC_LOG (DEBUG, "get context index: %d\n", ctx->index);
202 /* buffer size is 0. It means that this function is required to
205 if (secure_device_mem(dev->fd, ctx->index, 0, &buffer) < 0) {
207 "[%s] failed to get a memory block\n", __func__);
211 codec_init_data_to (ctx, codec, buffer);
213 dev->mem_info.offset = GET_OFFSET(buffer);
214 _codec_invoke_qemu (ctx->index, CODEC_INIT, GET_OFFSET(buffer), dev->fd);
216 opaque.buffer_index = ctx->index;
217 opaque.buffer_size = SMALLDATA;
219 if (ioctl (dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque) < 0) {
221 "[%s] failed to accquire a memory block\n", __func__);
226 codec_init_data_from (ctx, codec->media_type, device_mem + opaque.buffer_size);
229 CODEC_LOG (ERR, "failed to open Context for %s\n", codec->name);
234 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
236 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
242 codec_deinit (CodecContext *ctx, CodecDevice *dev)
244 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
246 CODEC_LOG (INFO, "close. context index: %d\n", ctx->index);
247 _codec_invoke_qemu (ctx->index, CODEC_DEINIT, 0, dev->fd);
249 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
253 codec_flush_buffers (CodecContext *ctx, CodecDevice *dev)
255 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
257 CODEC_LOG (DEBUG, "flush buffers. context index: %d\n", ctx->index);
258 _codec_invoke_qemu (ctx->index, CODEC_FLUSH_BUFFERS, 0, dev->fd);
260 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
264 codec_decode_video (CodecContext *ctx, uint8_t *in_buf, int in_size,
265 gint idx, gint64 in_offset, GstBuffer **out_buf,
266 int *got_picture_ptr, CodecDevice *dev)
268 int len = 0, ret = 0;
269 gpointer buffer = NULL;
270 CodecBufferId opaque;
272 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
274 ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
277 "decode_video. failed to get available memory to write inbuf\n");
281 codec_decode_video_data_to (in_size, idx, in_offset, in_buf, buffer);
283 dev->mem_info.offset = GET_OFFSET(buffer);
284 _codec_invoke_qemu (ctx->index, CODEC_DECODE_VIDEO, GET_OFFSET(buffer), dev->fd);
286 opaque.buffer_index = ctx->index;
287 opaque.buffer_size = SMALLDATA;
289 if (ioctl (dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque) < 0) {
291 "[%s] failed to accquire a memory block\n", __func__);
295 len = codec_decode_video_data_from (got_picture_ptr, &ctx->video, device_mem + opaque.buffer_size);
297 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
299 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
305 codec_decode_audio (CodecContext *ctx, int16_t *samples,
306 int *have_data, uint8_t *in_buf,
307 int in_size, CodecDevice *dev)
309 int len = 0, ret = 0;
310 gpointer buffer = NULL;
311 CodecBufferId opaque;
313 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
315 ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
318 "decode_audio. failed to get available memory to write inbuf\n");
322 CODEC_LOG (DEBUG, "decode_audio. in_buffer size %d\n", in_size);
323 codec_decode_audio_data_to (in_size, in_buf, buffer);
325 dev->mem_info.offset = GET_OFFSET(buffer);
326 _codec_invoke_qemu (ctx->index, CODEC_DECODE_AUDIO, GET_OFFSET(buffer), dev->fd);
328 opaque.buffer_index = ctx->index;
329 opaque.buffer_size = SMALLDATA;
330 // FIXME: how can we know output data size ?
331 ret = ioctl (dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque);
336 CODEC_LOG (DEBUG, "after decode_audio. ctx_id: %d, buffer = 0x%x\n",
337 ctx->index, device_mem + opaque.buffer_size);
340 codec_decode_audio_data_from (have_data, samples,
341 &ctx->audio, device_mem + opaque.buffer_size);
343 CODEC_LOG (DEBUG, "decode_audio. ctx_id: %d len: %d\n", ctx->index, len);
345 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
347 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
353 codec_encode_video (CodecContext *ctx, uint8_t *out_buf,
354 int out_size, uint8_t *in_buf,
355 int in_size, int64_t in_timestamp, CodecDevice *dev)
357 int len = 0, ret = 0;
358 gpointer buffer = NULL;
359 CodecBufferId opaque;
361 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
363 ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
365 CODEC_LOG (ERR, "failed to small size of buffer.\n");
369 codec_encode_video_data_to (in_size, in_timestamp, in_buf, buffer);
371 dev->mem_info.offset = GET_OFFSET(buffer);
372 _codec_invoke_qemu (ctx->index, CODEC_ENCODE_VIDEO, GET_OFFSET(buffer), dev->fd);
374 opaque.buffer_index = ctx->index;
375 opaque.buffer_size = SMALLDATA;
376 // FIXME: how can we know output data size ?
377 ret = ioctl (dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque);
381 CODEC_LOG (DEBUG, "encode_video. mem_offset = 0x%x\n", opaque.buffer_size);
383 len = codec_encode_video_data_from (out_buf, device_mem + opaque.buffer_size);
384 dev->mem_info.offset = opaque.buffer_size;
386 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
388 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
394 codec_encode_audio (CodecContext *ctx, uint8_t *out_buf,
395 int max_size, uint8_t *in_buf,
396 int in_size, CodecDevice *dev)
398 int len = 0, ret = 0;
399 gpointer buffer = NULL;
400 CodecBufferId opaque;
402 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
404 ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
409 codec_encode_audio_data_to (in_size, max_size, in_buf, buffer);
411 dev->mem_info.offset = GET_OFFSET(buffer);
412 _codec_invoke_qemu (ctx->index, CODEC_ENCODE_AUDIO, GET_OFFSET(buffer), dev->fd);
414 opaque.buffer_index = ctx->index;
415 opaque.buffer_size = SMALLDATA;
416 // FIXME: how can we know output data size ?
417 ret = ioctl (dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque);
422 CODEC_LOG (DEBUG, "encode_video. mem_offset = 0x%x\n", opaque.buffer_size);
424 len = codec_encode_audio_data_from (out_buf, device_mem + opaque.buffer_size);
426 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
428 CODEC_LOG (DEBUG, "leave: %s\n", __func__);