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 "gstmaruutils.h"
34 #include "gstmarumem.h"
35 #include "gstmarudevice.h"
38 extern gpointer device_mem;
46 uint32_t buffer_index;
57 CODEC_CMD_GET_VERSION = 20,
58 CODEC_CMD_GET_ELEMENT,
59 CODEC_CMD_GET_CONTEXT_INDEX,
60 CODEC_CMD_GET_ELEMENT_DATA,
61 CODEC_CMD_PUT_DATA_INTO_BUFFER = 40,
62 CODEC_CMD_SECURE_BUFFER,
63 CODEC_CMD_TRY_SECURE_BUFFER,
64 CODEC_CMD_RELEASE_BUFFER,
65 CODEC_CMD_INVOKE_API_AND_RELEASE_BUFFER,
69 #define CODEC_META_DATA_SIZE 256
70 #define GET_OFFSET(buffer) ((uint32_t)buffer - (uint32_t)device_mem)
75 _codec_invoke_qemu(int32_t ctx_index, int32_t api_index,
76 uint32_t mem_offset, int fd, CodecBufferId *buffer_id)
78 CodecIOParams ioparam = { 0, };
81 ioparam.api_index = api_index;
82 ioparam.ctx_index = ctx_index;
83 ioparam.mem_offset = mem_offset;
85 if (ioctl(fd, CODEC_CMD_INVOKE_API_AND_RELEASE_BUFFER, &ioparam) < 0) {
89 ret = ioctl(fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, buffer_id);
96 secure_device_mem (int fd, guint ctx_id, guint buf_size, gpointer* buffer)
101 opaque.buffer_index = ctx_id;
102 opaque.buffer_size = buf_size;
104 ret = ioctl (fd, CODEC_CMD_SECURE_BUFFER, &opaque);
105 /* ioctl: CODEC_CMD_SECURE_BUFFER
106 * - sets device memory offset into opaque.buffer_size
108 *buffer = (gpointer)((uint32_t)device_mem + opaque.buffer_size);
109 GST_DEBUG ("device_mem %p, offset_size 0x%x", device_mem, opaque.buffer_size);
115 release_device_mem (int fd, gpointer start)
118 uint32_t offset = start - device_mem;
120 GST_DEBUG ("release device_mem start: %p, offset: 0x%x", start, offset);
121 ret = ioctl (fd, CODEC_CMD_RELEASE_BUFFER, &offset);
123 GST_ERROR ("failed to release buffer");
128 codec_buffer_free (gpointer start)
130 release_device_mem (device_fd, start);
134 codec_buffer_alloc_and_copy (GstPad *pad, guint64 offset, guint size,
135 GstCaps *caps, GstBuffer **buf)
137 bool is_last_buffer = 0;
139 CodecBufferId opaque;
144 *buf = gst_buffer_new ();
146 marudec = (GstMaruDec *)gst_pad_get_element_private(pad);
147 ctx = marudec->context;
150 ctx = marudec->context;
152 opaque.buffer_index = ctx->index;
153 opaque.buffer_size = size;
155 GST_DEBUG ("buffer_and_copy. ctx_id: %d", ctx->index);
157 int ret = _codec_invoke_qemu(ctx->index, CODEC_PICTURE_COPY, 0, dev->fd, &opaque);
159 GST_DEBUG ("failed to get available buffer");
160 return GST_FLOW_ERROR;
162 is_last_buffer = ret;
163 mem_offset = opaque.buffer_size;
165 gpointer *buffer = NULL;
166 if (is_last_buffer) {
167 // FIXME: we must aligned buffer offset.
168 buffer = g_malloc (size);
170 GST_BUFFER_FREE_FUNC (*buf) = g_free;
172 memcpy (buffer, device_mem + mem_offset, size);
173 release_device_mem(dev->fd, device_mem + mem_offset);
175 GST_DEBUG ("secured last buffer!! Use heap buffer");
177 // address of "device_mem" and "opaque" is aleady aligned.
178 buffer = (gpointer)(device_mem + mem_offset);
179 GST_BUFFER_FREE_FUNC (*buf) = codec_buffer_free;
181 GST_DEBUG ("device memory start: 0x%p, offset 0x%x", (intptr_t)buffer, mem_offset);
184 GST_BUFFER_DATA (*buf) = GST_BUFFER_MALLOCDATA (*buf) = (void *)buffer;
185 GST_BUFFER_SIZE (*buf) = size;
186 GST_BUFFER_OFFSET (*buf) = offset;
189 gst_buffer_set_caps (*buf, caps);
196 codec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
199 gpointer buffer = NULL;
200 CodecBufferId opaque;
203 if (ioctl(dev->fd, CODEC_CMD_GET_CONTEXT_INDEX, &ctx->index) < 0) {
204 GST_ERROR ("failed to get a context index");
207 GST_DEBUG ("get context index: %d", ctx->index);
209 /* buffer size is 0. It means that this function is required to
212 if (secure_device_mem(dev->fd, ctx->index, 0, &buffer) < 0) {
213 GST_ERROR ("failed to get a memory block");
217 codec_init_data_to (ctx, codec, buffer);
219 opaque.buffer_index = ctx->index;
220 opaque.buffer_size = SMALLDATA;
222 ret = _codec_invoke_qemu (ctx->index, CODEC_INIT, GET_OFFSET(buffer), dev->fd, &opaque);
229 codec_init_data_from (ctx, codec->media_type, device_mem + opaque.buffer_size);
232 GST_ERROR ("failed to open Context for %s", codec->name);
237 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
243 codec_deinit (CodecContext *ctx, CodecDevice *dev)
245 GST_INFO ("close context %d", ctx->index);
246 _codec_invoke_qemu (ctx->index, CODEC_DEINIT, 0, dev->fd, NULL);
250 codec_flush_buffers (CodecContext *ctx, CodecDevice *dev)
252 GST_DEBUG ("flush buffers of context: %d", ctx->index);
253 _codec_invoke_qemu (ctx->index, CODEC_FLUSH_BUFFERS, 0, dev->fd, NULL);
257 codec_decode_video (GstMaruDec *marudec, uint8_t *in_buf, int in_size,
258 gint idx, gint64 in_offset, GstBuffer **out_buf, int *have_data)
260 CodecContext *ctx = marudec->context;
261 CodecDevice *dev = marudec->dev;
262 int len = 0, ret = 0;
263 gpointer buffer = NULL;
264 CodecBufferId opaque = { 0, };
266 ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
268 GST_ERROR ("failed to get available memory to write inbuf");
272 codec_decode_video_data_to (in_size, idx, in_offset, in_buf, buffer);
274 opaque.buffer_index = ctx->index;
276 opaque.buffer_size = SMALLDATA;
277 ret = _codec_invoke_qemu(ctx->index, CODEC_DECODE_VIDEO, GET_OFFSET(buffer), dev->fd, &opaque);
283 len = codec_decode_video_data_from (have_data, &ctx->video, device_mem + opaque.buffer_size);
285 GST_DEBUG_OBJECT (marudec, "after decode: len %d, have_data %d",
288 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
290 if (len < 0 || *have_data <= 0) {
291 GST_DEBUG_OBJECT (marudec, "return flow %d, out %p, len %d",
299 codec_decode_audio (CodecContext *ctx, int16_t *samples,
300 int *have_data, uint8_t *in_buf,
301 int in_size, CodecDevice *dev)
303 int len = 0, ret = 0;
304 gpointer buffer = NULL;
305 CodecBufferId opaque;
307 ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
309 GST_ERROR ("failed to get available memory to write inbuf");
313 GST_DEBUG ("decode_audio 1. in_buffer size %d", in_size);
314 codec_decode_audio_data_to (in_size, in_buf, buffer);
316 opaque.buffer_index = ctx->index;
317 opaque.buffer_size = SMALLDATA;
319 ret = _codec_invoke_qemu(ctx->index, CODEC_DECODE_AUDIO, GET_OFFSET(buffer), dev->fd, &opaque);
325 GST_DEBUG ("decode_audio 2. ctx_id: %d, buffer = 0x%x",
326 ctx->index, device_mem + opaque.buffer_size);
328 len = codec_decode_audio_data_from (have_data, samples,
329 &ctx->audio, device_mem + opaque.buffer_size);
331 GST_DEBUG ("decode_audio 3. ctx_id: %d len: %d", ctx->index, len);
333 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
339 codec_encode_video (CodecContext *ctx, uint8_t *out_buf,
340 int out_size, uint8_t *in_buf,
341 int in_size, int64_t in_timestamp,
342 int *coded_frame, int *is_keyframe,
345 int len = 0, ret = 0;
346 gpointer buffer = NULL;
347 CodecBufferId opaque;
349 ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
351 GST_ERROR ("failed to small size of buffer");
355 codec_encode_video_data_to (in_size, in_timestamp, in_buf, buffer);
357 opaque.buffer_index = ctx->index;
358 opaque.buffer_size = SMALLDATA;
360 // FIXME: how can we know output data size ?
361 ret = _codec_invoke_qemu(ctx->index, CODEC_ENCODE_VIDEO, GET_OFFSET(buffer), dev->fd, &opaque);
367 GST_DEBUG ("encode_video. mem_offset = 0x%x", opaque.buffer_size);
369 len = codec_encode_video_data_from (out_buf, coded_frame, is_keyframe, device_mem + opaque.buffer_size);
371 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
377 static codec_encode_audio (CodecContext *ctx, uint8_t *out_buf,
378 int max_size, uint8_t *in_buf,
379 int in_size, int64_t timestamp,
383 gpointer buffer = NULL;
384 CodecBufferId opaque;
386 ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
391 codec_encode_audio_data_to (in_size, max_size, in_buf, timestamp, buffer);
393 opaque.buffer_index = ctx->index;
394 opaque.buffer_size = SMALLDATA;
396 ret = _codec_invoke_qemu(ctx->index, CODEC_ENCODE_AUDIO, GET_OFFSET(buffer), dev->fd, &opaque);
402 GST_DEBUG ("encode_audio. mem_offset = 0x%x", opaque.buffer_size);
404 ret = codec_encode_audio_data_from (out_buf, device_mem + opaque.buffer_size);
406 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
412 get_device_version (int fd)
414 uint32_t device_version;
417 ret = ioctl (fd, CODEC_CMD_GET_VERSION, &device_version);
422 return device_version;
426 prepare_elements (int fd)
429 int ret, elem_cnt, i;
430 GList *elements = NULL;
433 ret = ioctl (fd, CODEC_CMD_GET_ELEMENT, &size);
438 elem = g_malloc(size);
440 ret = ioctl (fd, CODEC_CMD_GET_ELEMENT_DATA, elem);
446 elem_cnt = size / sizeof(CodecElement);
447 for (i = 0; i < elem_cnt; i++) {
448 elements = g_list_append (elements, &elem[i]);
454 Interface *interface_version_2 = &(Interface) {
456 .deinit = codec_deinit,
457 .decode_video = codec_decode_video,
458 .decode_audio = codec_decode_audio,
459 .encode_video = codec_encode_video,
460 .encode_audio = codec_encode_audio,
461 .flush_buffers = codec_flush_buffers,
462 .buffer_alloc_and_copy = codec_buffer_alloc_and_copy,
463 .get_device_version = get_device_version,
464 .prepare_elements = prepare_elements,