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)
81 // uint32_t opaque = 0;
84 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
85 opaque.buffer_index = ctx_id;
86 opaque.buffer_size = buf_size;
88 ret = ioctl (fd, CODEC_CMD_SECURE_BUFFER, &opaque);
89 *buffer = (gpointer)((uint32_t)device_mem + opaque.buffer_size);
90 CODEC_LOG (DEBUG, "buffer: 0x%x\n", (int)buffer);
92 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
98 release_device_mem (int fd, gpointer start)
101 uint32_t offset = start - device_mem;
103 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
105 CODEC_LOG (DEBUG, "release device_mem start: %p, offset: 0x%x\n", start, offset);
106 ret = ioctl (fd, CODEC_CMD_RELEASE_BUFFER, &offset);
108 CODEC_LOG (ERR, "failed to release buffer\n");
111 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
115 codec_buffer_free (gpointer start)
117 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
119 release_device_mem (device_fd, start);
121 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
125 codec_buffer_alloc_and_copy (GstPad *pad, guint64 offset, guint size,
126 GstCaps *caps, GstBuffer **buf)
128 struct mem_info info;
129 CodecBufferId opaque;
133 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
135 *buf = gst_buffer_new ();
137 marudec = (GstMaruDec *)gst_pad_get_element_private(pad);
139 opaque.buffer_index = marudec->context->index;
140 opaque.buffer_size = size;
142 CODEC_LOG (DEBUG, "buffer_and_copy. ctx_id: %d\n", marudec->context->index);
143 _codec_invoke_qemu (marudec->context->index, CODEC_PICTURE_COPY,
144 0, marudec->dev->fd);
146 ret = ioctl (marudec->dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque);
149 CODEC_LOG (DEBUG, "failed to get available buffer\n");
150 } else if (ret == 1) {
151 // FIXME: we must aligned buffer offset.
152 info.start = g_malloc (size);
155 GST_BUFFER_FREE_FUNC (*buf) = g_free;
157 memcpy (info.start, (uint32_t)device_mem + opaque.buffer_size, size);
158 release_device_mem(marudec->dev->fd, (uint32_t)device_mem + opaque.buffer_size);
160 CODEC_LOG (DEBUG, "we secured last buffer, so we will use heap buffer\n");
162 // address of "device_mem" and "opaque" is aleady aligned.
163 info.start = (gpointer)((uint32_t)device_mem + opaque.buffer_size);
164 info.offset = opaque.buffer_size;
166 GST_BUFFER_FREE_FUNC (*buf) = codec_buffer_free;
168 CODEC_LOG (DEBUG, "device memory start: 0x%p, offset 0x%x\n", info.start, info.offset);
171 GST_BUFFER_DATA (*buf) = GST_BUFFER_MALLOCDATA (*buf) = info.start;
172 GST_BUFFER_SIZE (*buf) = size;
173 GST_BUFFER_OFFSET (*buf) = offset;
176 gst_buffer_set_caps (*buf, caps);
179 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
185 codec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
187 int ret = 0, opened = 0, size = 8;
188 uint32_t meta_offset = 0;
190 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
192 ret = ioctl(dev->fd, CODEC_CMD_GET_CONTEXT_INDEX, &ctx->index);
194 GST_ERROR ("failed to get context index\n");
197 CODEC_LOG (DEBUG, "get context index: %d\n", ctx->index);
199 meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
201 "init. ctx: %d meta_offset = 0x%x\n", ctx->index, meta_offset);
203 _codec_init_meta_to (ctx, codec, device_mem + meta_offset + size);
205 _codec_invoke_qemu (ctx->index, CODEC_INIT, 0, dev->fd);
208 "init. ctx: %d meta_offset = 0x%x, size: %d\n", ctx->index, meta_offset, size);
211 _codec_init_meta_from (ctx, codec->media_type, device_mem + meta_offset + size);
214 CODEC_LOG (DEBUG, "opened: %d\n", opened);
216 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
222 codec_deinit (CodecContext *ctx, CodecDevice *dev)
224 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
226 CODEC_LOG (INFO, "close. context index: %d\n", ctx->index);
227 _codec_invoke_qemu (ctx->index, CODEC_DEINIT, 0, dev->fd);
229 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
233 codec_flush_buffers (CodecContext *ctx, CodecDevice *dev)
235 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
237 CODEC_LOG (DEBUG, "flush buffers. context index: %d\n", ctx->index);
238 _codec_invoke_qemu (ctx->index, CODEC_FLUSH_BUFFERS, 0, dev->fd);
240 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
244 codec_decode_video (CodecContext *ctx, uint8_t *in_buf, int in_size,
245 gint idx, gint64 in_offset, GstBuffer **out_buf,
246 int *got_picture_ptr, CodecDevice *dev)
248 int len = 0, ret = 0, size = 8;
249 gpointer buffer = NULL;
250 uint32_t meta_offset = 0;
252 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
254 meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
255 CODEC_LOG (DEBUG, "decode_video. ctx_id: %d meta_offset = 0x%x\n", ctx->index, meta_offset);
256 _codec_decode_video_meta_to (in_size, idx, in_offset, device_mem + meta_offset + size);
258 ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
261 "decode_video. failed to get available memory to write inbuf\n");
265 _codec_decode_video_inbuf (in_buf, in_size, buffer);
266 dev->mem_info.offset = GET_OFFSET(buffer);
267 _codec_invoke_qemu (ctx->index, CODEC_DECODE_VIDEO, GET_OFFSET(buffer), dev->fd);
269 // after decoding video, no need to get outbuf.
271 _codec_decode_video_meta_from (&ctx->video, got_picture_ptr, device_mem + meta_offset + size);
273 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
279 codec_decode_audio (CodecContext *ctx, int16_t *samples,
280 int *have_data, uint8_t *in_buf,
281 int in_size, CodecDevice *dev)
283 int len = 0, ret = 0, size = 8;
284 gpointer buffer = NULL;
285 uint32_t meta_offset = 0;
286 CodecBufferId opaque;
288 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
290 meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
291 CODEC_LOG (DEBUG, "decode_audio. ctx_id: %d meta_offset = 0x%x\n", ctx->index, meta_offset);
292 _codec_decode_audio_meta_to (in_size, device_mem + meta_offset + size);
294 ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
297 "decode_audio. failed to get available memory to write inbuf\n");
301 _codec_decode_audio_inbuf (in_buf, in_size, buffer);
302 dev->mem_info.offset = GET_OFFSET(buffer);
303 _codec_invoke_qemu (ctx->index, CODEC_DECODE_AUDIO, GET_OFFSET(buffer), dev->fd);
305 opaque.buffer_index = ctx->index;
306 opaque.buffer_size = SMALLDATA;
307 // FIXME: how can we know output data size ?
308 ret = ioctl (dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque);
312 CODEC_LOG (DEBUG, "after decode_audio. ctx_id: %d, buffer = 0x%x\n",
313 ctx->index, (int)device_mem + opaque.buffer_size);
316 _codec_decode_audio_meta_from (&ctx->audio, have_data, device_mem + meta_offset + size);
318 _codec_decode_audio_outbuf (*have_data, samples, device_mem + opaque.buffer_size);
320 CODEC_LOG (DEBUG, "decode_audio failure. ctx_id: %d\n", ctx->index);
322 CODEC_LOG (DEBUG, "decode_audio. ctx_id: %d len: %d\n", ctx->index, len);
324 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
326 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
332 codec_encode_video (CodecContext *ctx, uint8_t *out_buf,
333 int out_size, uint8_t *in_buf,
334 int in_size, int64_t in_timestamp, CodecDevice *dev)
336 int len = 0, ret = 0, size = 8;
337 gpointer buffer = NULL;
338 uint32_t meta_offset = 0;
339 CodecBufferId opaque;
341 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
343 meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
344 CODEC_LOG (DEBUG, "encode_video. meta_offset = 0x%x\n", meta_offset);
345 _codec_encode_video_meta_to (in_size, in_timestamp, device_mem + meta_offset + size);
347 ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
349 CODEC_LOG (ERR, "failed to small size of buffer.\n");
353 _codec_encode_video_inbuf (in_buf, in_size, buffer);
354 dev->mem_info.offset = GET_OFFSET(buffer);
355 _codec_invoke_qemu (ctx->index, CODEC_ENCODE_VIDEO, GET_OFFSET(buffer), dev->fd);
357 opaque.buffer_index = ctx->index;
358 opaque.buffer_size = SMALLDATA;
359 // FIXME: how can we know output data size ?
360 ret = ioctl (dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque);
364 CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", opaque.buffer_size);
366 memcpy (&len, device_mem + meta_offset + size, sizeof(len));
368 CODEC_LOG (DEBUG, "encode_video. outbuf size: %d\n", len);
370 memcpy (out_buf, device_mem + opaque.buffer_size, len);
371 dev->mem_info.offset = opaque.buffer_size;
374 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
376 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
382 codec_encode_audio (CodecContext *ctx, uint8_t *out_buf,
383 int max_size, uint8_t *in_buf,
384 int in_size, CodecDevice *dev)
386 int len = 0, ret = 0, size = 8;
387 gpointer buffer = NULL;
388 uint32_t meta_offset = 0;
389 CodecBufferId opaque;
391 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
393 meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
394 CODEC_LOG (DEBUG, "encode_audio. meta mem_offset = 0x%x\n", meta_offset);
395 _codec_encode_audio_meta_to (max_size, in_size, device_mem + meta_offset + size);
397 ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
402 _codec_encode_audio_inbuf (in_buf, in_size, buffer);
403 dev->mem_info.offset = GET_OFFSET(buffer);
404 _codec_invoke_qemu (ctx->index, CODEC_ENCODE_AUDIO, GET_OFFSET(buffer), dev->fd);
406 opaque.buffer_index = ctx->index;
407 opaque.buffer_size = SMALLDATA;
408 // FIXME: how can we know output data size ?
409 ret = ioctl (dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque);
414 CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", opaque.buffer_size);
416 len = _codec_encode_audio_outbuf (out_buf, device_mem + opaque.buffer_size);
418 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
420 CODEC_LOG (DEBUG, "leave: %s\n", __func__);