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 #define CODEC_META_DATA_SIZE 256
51 #define GET_OFFSET(buffer) ((uint32_t)buffer - (uint32_t)device_mem)
55 _codec_header (int32_t api_index, uint32_t mem_offset, uint8_t *device_buf)
57 CodecHeader header = { 0 };
59 CODEC_LOG (DEBUG, "enter, %s\n", __func__);
61 header.api_index = api_index;
62 header.mem_offset = mem_offset;
64 memcpy(device_buf, &header, sizeof(header));
66 CODEC_LOG (DEBUG, "leave, %s\n", __func__);
68 return sizeof(header);
72 _codec_write_to_qemu (int32_t ctx_index, int32_t api_index,
73 uint32_t mem_offset, int fd)
75 CodecIOParams ioparam;
77 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
79 memset(&ioparam, 0, sizeof(ioparam));
80 ioparam.api_index = api_index;
81 ioparam.ctx_index = ctx_index;
82 ioparam.mem_offset = mem_offset;
83 if (write (fd, &ioparam, 1) < 0) {
84 CODEC_LOG (ERR, "failed to write input data\n");
87 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
91 secure_device_mem (int fd, guint buf_size, gpointer* buffer)
95 struct mem_info info = {0, };
97 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
100 ret = ioctl (fd, CODEC_CMD_SECURE_BUFFER, &opaque);
101 *buffer = (gpointer)((uint32_t)device_mem + opaque);
102 CODEC_LOG (DEBUG, "buffer: 0x%x\n", (int)buffer);
104 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
110 release_device_mem (int fd, gpointer start)
113 uint32_t offset = start - device_mem;
115 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
117 CODEC_LOG (DEBUG, "release device_mem start: %p, offset: 0x%x\n", start, offset);
119 // FIXME: We use device_fd now...
122 ret = ioctl (fd, CODEC_CMD_RELEASE_BUFFER, &offset);
124 CODEC_LOG (ERR, "failed to release buffer\n");
127 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
131 codec_buffer_free (gpointer start)
133 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
135 release_device_mem (-1, start);
137 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
141 codec_buffer_alloc_and_copy (GstPad *pad, guint64 offset, guint size,
142 GstCaps *caps, GstBuffer **buf)
144 struct mem_info info;
149 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
153 *buf = gst_buffer_new ();
155 marudec = (GstMaruDec *)gst_pad_get_element_private(pad);
157 _codec_write_to_qemu (marudec->context->index, CODEC_PICTURE_COPY,
158 0, marudec->dev->fd);
160 ret = ioctl (marudec->dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque);
163 CODEC_LOG (DEBUG, "failed to get available buffer\n");
164 } else if (ret == 1) {
165 // FIXME: we must aligned buffer offset.
166 info.start = g_malloc (size);
169 GST_BUFFER_FREE_FUNC (*buf) = g_free;
171 memcpy (info.start, (uint32_t)device_mem + opaque, size);
172 release_device_mem(marudec->dev->fd, (uint32_t)device_mem + opaque);
174 CODEC_LOG (DEBUG, "we secured last buffer, so we will use heap buffer\n");
176 // address of "device_mem" and "opaque" is aleady aligned.
177 info.start = (gpointer)((uint32_t)device_mem + opaque);
178 info.offset = opaque;
180 GST_BUFFER_FREE_FUNC (*buf) = codec_buffer_free;
182 CODEC_LOG (DEBUG, "device memory start: 0x%p, offset 0x%x\n", info.start, info.offset);
185 GST_BUFFER_DATA (*buf) = GST_BUFFER_MALLOCDATA (*buf) = info.start;
186 GST_BUFFER_SIZE (*buf) = size;
187 GST_BUFFER_OFFSET (*buf) = offset;
190 gst_buffer_set_caps (*buf, caps);
193 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
199 codec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
201 int ret = 0, opened = 0, size = 8;
202 uint32_t meta_offset = 0;
204 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
206 ret = ioctl(dev->fd, CODEC_CMD_GET_CONTEXT_INDEX, &ctx->index);
208 GST_ERROR ("failed to get context index\n");
211 CODEC_LOG (DEBUG, "get context index: %d\n", ctx->index);
213 meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
215 "init. ctx: %d meta_offset = 0x%x\n", ctx->index, meta_offset);
217 _codec_init_meta_to (ctx, codec, device_mem + meta_offset + size);
219 _codec_write_to_qemu (ctx->index, CODEC_INIT, 0, dev->fd);
222 "init. ctx: %d meta_offset = 0x%x, size: %d\n", ctx->index, meta_offset, size);
225 _codec_init_meta_from (ctx, codec->media_type, device_mem + meta_offset + size);
228 CODEC_LOG (DEBUG, "opened: %d\n", opened);
230 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
236 codec_deinit (CodecContext *ctx, CodecDevice *dev)
238 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
240 CODEC_LOG (INFO, "close. context index: %d\n", ctx->index);
241 _codec_write_to_qemu (ctx->index, CODEC_DEINIT, 0, dev->fd);
243 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
247 codec_flush_buffers (CodecContext *ctx, CodecDevice *dev)
249 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
251 CODEC_LOG (DEBUG, "flush buffers. context index: %d\n", ctx->index);
252 _codec_write_to_qemu (ctx->index, CODEC_FLUSH_BUFFERS, 0, dev->fd);
254 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
258 codec_decode_video (CodecContext *ctx, uint8_t *in_buf, int in_size,
259 gint idx, gint64 in_offset, GstBuffer **out_buf,
260 int *got_picture_ptr, CodecDevice *dev)
262 int len = 0, ret = 0, size = 8;
263 gpointer buffer = NULL;
264 uint32_t meta_offset = 0;
266 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
268 meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
269 CODEC_LOG (DEBUG, "decode_video. meta_offset = 0x%x\n", meta_offset);
270 _codec_decode_video_meta_to (in_size, idx, in_offset, device_mem + meta_offset + size);
272 ret = secure_device_mem(dev->fd, in_size, &buffer);
275 "decode_video. failed to get available memory to write inbuf\n");
279 _codec_decode_video_inbuf (in_buf, in_size, buffer);
280 dev->mem_info.offset = GET_OFFSET(buffer);
281 _codec_write_to_qemu (ctx->index, CODEC_DECODE_VIDEO, GET_OFFSET(buffer), dev->fd);
283 // after decoding video, no need to get outbuf.
285 _codec_decode_video_meta_from (&ctx->video, got_picture_ptr, device_mem + meta_offset + size);
287 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
293 codec_decode_audio (CodecContext *ctx, int16_t *samples,
294 int *have_data, uint8_t *in_buf,
295 int in_size, CodecDevice *dev)
297 int len = 0, ret = 0, size = 8;
298 gpointer buffer = NULL;
299 uint32_t meta_offset = 0, opaque = 0;
301 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
303 meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
304 CODEC_LOG (DEBUG, "decode_audio. ctx_id: %d meta_offset = 0x%x\n", ctx->index, meta_offset);
305 _codec_decode_audio_meta_to (in_size, device_mem + meta_offset + size);
307 ret = secure_device_mem(dev->fd, in_size, &buffer);
310 "decode_audio. failed to get available memory to write inbuf\n");
314 _codec_decode_audio_inbuf (in_buf, in_size, buffer);
315 dev->mem_info.offset = GET_OFFSET(buffer);
316 _codec_write_to_qemu (ctx->index, CODEC_DECODE_AUDIO, GET_OFFSET(buffer), dev->fd);
318 opaque = SMALLDATA; // FIXME: how can we know output data size ?
319 ret = ioctl (dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque);
323 CODEC_LOG (DEBUG, "after decode_audio. ctx_id: %d, buffer = 0x%x\n", ctx->index, (int)buffer);
326 _codec_decode_audio_meta_from (&ctx->audio, have_data, device_mem + meta_offset + size);
328 _codec_decode_audio_outbuf (*have_data, samples, buffer);
330 CODEC_LOG (DEBUG, "decode_audio failure. ctx_id: %d\n", ctx->index);
333 release_device_mem(dev->fd, buffer);
335 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
341 codec_encode_video (CodecContext *ctx, uint8_t *out_buf,
342 int out_size, uint8_t *in_buf,
343 int in_size, int64_t in_timestamp, CodecDevice *dev)
345 int len = 0, ret = 0, size = 8;
346 gpointer buffer = NULL;
347 uint32_t meta_offset = 0, opaque = 0;
349 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
351 meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
352 CODEC_LOG (DEBUG, "encode_video. meta_offset = 0x%x\n", meta_offset);
353 _codec_encode_video_meta_to (in_size, in_timestamp, device_mem + meta_offset + size);
355 ret = secure_device_mem(dev->fd, in_size, &buffer);
357 CODEC_LOG (ERR, "failed to small size of buffer.\n");
361 _codec_encode_video_inbuf (in_buf, in_size, buffer);
362 dev->mem_info.offset = GET_OFFSET(buffer);
363 _codec_write_to_qemu (ctx->index, CODEC_ENCODE_VIDEO, GET_OFFSET(buffer), dev->fd);
365 opaque = SMALLDATA; // FIXME: how can we know output data size ?
366 ret = ioctl (dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque);
370 CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", opaque);
372 memcpy (&len, device_mem + meta_offset + size, sizeof(len));
374 CODEC_LOG (DEBUG, "encode_video. outbuf size: %d\n", len);
376 memcpy (out_buf, buffer, len);
377 dev->mem_info.offset = GET_OFFSET(buffer);
380 release_device_mem(dev->fd, buffer);
382 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
388 codec_encode_audio (CodecContext *ctx, uint8_t *out_buf,
389 int max_size, uint8_t *in_buf,
390 int in_size, CodecDevice *dev)
392 int len = 0, ret = 0, size = 8;
393 gpointer buffer = NULL;
394 uint32_t meta_offset = 0, opaque = 0;
396 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
398 meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
399 CODEC_LOG (DEBUG, "encode_audio. meta mem_offset = 0x%x\n", meta_offset);
400 size = _codec_header (CODEC_ENCODE_AUDIO, opaque,
401 device_mem + meta_offset);
402 _codec_encode_audio_meta_to (max_size, in_size, device_mem + meta_offset + size);
404 ret = secure_device_mem(dev->fd, in_size, &buffer);
409 _codec_encode_audio_inbuf (in_buf, in_size, buffer);
410 dev->mem_info.offset = GET_OFFSET(buffer);
411 _codec_write_to_qemu (ctx->index, CODEC_ENCODE_AUDIO, GET_OFFSET(buffer), dev->fd);
413 opaque = SMALLDATA; // FIXME: how can we know output data size ?
414 ret = ioctl (dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque);
419 CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", opaque);
421 len = _codec_encode_audio_outbuf (out_buf, buffer);
423 release_device_mem(dev->fd, buffer);
425 CODEC_LOG (DEBUG, "leave: %s\n", __func__);