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;
44 typedef struct _CodecHeader {
49 #define SMALL_BUFFER (256 * 1024)
50 #define MEDIUM_BUFFER (2 * 1024 * 1024)
51 #define LARGE_BUFFER (4 * 1024 * 1024)
53 #define CODEC_META_DATA_SIZE 256
56 _codec_header (int32_t api_index, uint32_t mem_offset, uint8_t *device_buf)
58 CodecHeader header = { 0 };
60 CODEC_LOG (DEBUG, "enter, %s\n", __func__);
62 header.api_index = api_index;
63 header.mem_offset = mem_offset;
65 memcpy(device_buf, &header, sizeof(header));
67 CODEC_LOG (DEBUG, "leave, %s\n", __func__);
69 return sizeof(header);
73 _codec_write_to_qemu (int32_t ctx_index, int32_t api_index,
74 uint32_t mem_offset, int fd)
76 CodecIOParams ioparam;
78 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
80 memset(&ioparam, 0, sizeof(ioparam));
81 ioparam.api_index = api_index;
82 ioparam.ctx_index = ctx_index;
83 ioparam.mem_offset = mem_offset;
84 if (write (fd, &ioparam, 1) < 0) {
85 CODEC_LOG (ERR, "failed to write input data\n");
88 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
91 static struct mem_info
92 secure_device_mem (guint buf_size)
95 uint32_t mem_offset = 0, cmd = 0;
96 struct mem_info info = {0, };
98 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
100 if (buf_size < SMALL_BUFFER) {
101 cmd = CODEC_CMD_SECURE_SMALL_BUFFER;
102 CODEC_LOG (DEBUG, "small buffer size\n");
103 } else if (buf_size < MEDIUM_BUFFER) {
105 cmd = CODEC_CMD_SECURE_MEDIUM_BUFFER;
106 CODEC_LOG (DEBUG, "HD buffer size\n");
108 // FULL HD Video(4MB)
109 cmd = CODEC_CMD_SECURE_LARGE_BUFFER;
110 CODEC_LOG (DEBUG, "FULL HD buffer size\n");
113 ret = ioctl (device_fd, cmd, &mem_offset);
115 CODEC_LOG (ERR, "failed to get available buffer\n");
118 if (mem_offset == (LARGE_BUFFER * 8)) {
119 CODEC_LOG (ERR, "acquired memory is over!!\n");
121 info.start = (gpointer)((uint32_t)device_mem + mem_offset);
122 info.offset = mem_offset;
124 CODEC_LOG (DEBUG, "acquire device_memory: 0x%x\n", mem_offset);
128 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
134 release_device_mem (gpointer start)
137 uint32_t offset = start - device_mem;
139 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
141 CODEC_LOG (DEBUG, "release device_mem start: %p, offset: 0x%x\n", start, offset);
142 ret = ioctl (device_fd, CODEC_CMD_RELEASE_BUFFER, &offset);
144 CODEC_LOG (ERR, "failed to release buffer\n");
147 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
151 codec_buffer_free (gpointer start)
153 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
155 release_device_mem (start);
157 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
161 codec_buffer_alloc (GstPad *pad, guint64 offset, guint size,
162 GstCaps *caps, GstBuffer **buf)
164 struct mem_info info;
166 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
168 *buf = gst_buffer_new ();
170 info = secure_device_mem (size);
172 CODEC_LOG (DEBUG, "memory start: 0x%p, offset 0x%x\n",
173 info.start, info.offset);
175 GST_BUFFER_DATA (*buf) = GST_BUFFER_MALLOCDATA (*buf) = info.start;
176 GST_BUFFER_SIZE (*buf) = size;
177 GST_BUFFER_FREE_FUNC (*buf) = codec_buffer_free;
178 GST_BUFFER_OFFSET (*buf) = offset;
181 gst_buffer_set_caps (*buf, caps);
184 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
190 codec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
193 int opened, size = 0;
194 uint8_t *mmapbuf = NULL;
195 uint32_t meta_offset = 0;
197 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
201 GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
205 mmapbuf = (uint8_t *)dev->buf;
207 GST_ERROR ("failed to get mmaped memory address.\n");
211 ret = ioctl(fd, CODEC_CMD_GET_CONTEXT_INDEX, &ctx->index);
213 GST_ERROR ("failed to get context index\n");
216 CODEC_LOG (DEBUG, "get context index: %d\n", ctx->index);
218 meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
220 "init. ctx: %d meta_offset = 0x%x\n", ctx->index, meta_offset);
222 // size = _codec_header (CODEC_INIT, 0, mmapbuf + meta_offset);
224 _codec_init_meta_to (ctx, codec, mmapbuf + meta_offset + size);
226 _codec_write_to_qemu (ctx->index, CODEC_INIT, 0, fd);
229 "init. ctx: %d meta_offset = 0x%x, size: %d\n", ctx->index, meta_offset, size);
232 if (codec->media_type == AVMEDIA_TYPE_AUDIO) {
234 "opened: %d, audio_sample_fmt: %d\n",
235 *(int *)(mmapbuf + meta_offset + size),
236 *(int *)(mmapbuf + meta_offset + size + 4));
241 _codec_init_meta_from (ctx, codec->media_type, mmapbuf + meta_offset + size);
244 CODEC_LOG (DEBUG, "opened: %d\n", opened);
246 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
252 codec_deinit (CodecContext *ctx, CodecDevice *dev)
255 void *mmapbuf = NULL;
257 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
261 GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
267 GST_ERROR ("failed to get mmaped memory address.\n");
271 CODEC_LOG (INFO, "close. context index: %d\n", ctx->index);
272 _codec_write_to_qemu (ctx->index, CODEC_DEINIT, 0, fd);
274 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
278 codec_flush_buffers (CodecContext *ctx, CodecDevice *dev)
281 void *mmapbuf = NULL;
283 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
287 GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
293 GST_ERROR ("failed to get mmaped memory address.\n");
297 CODEC_LOG (DEBUG, "flush buffers. context index: %d\n", ctx->index);
298 _codec_write_to_qemu (ctx->index, CODEC_FLUSH_BUFFERS, 0, fd);
300 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
304 codec_decode_video (CodecContext *ctx, uint8_t *in_buf, int in_size,
305 gint idx, gint64 in_offset, GstBuffer **out_buf,
306 int *got_picture_ptr, CodecDevice *dev)
310 uint8_t *mmapbuf = NULL;
311 uint32_t mem_offset = 0, meta_offset = 0;
313 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
317 GST_ERROR ("failed to get %s fd\n", CODEC_DEV);
323 GST_ERROR ("failed to get mmaped memory address\n");
327 ret = ioctl (fd, CODEC_CMD_SECURE_SMALL_BUFFER, &mem_offset);
330 "decode_audio. failed to get available memory to write inbuf\n");
333 CODEC_LOG (DEBUG, "decode_video. mem_offset = 0x%x\n", mem_offset);
335 meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
336 CODEC_LOG (DEBUG, "decode_video. meta_offset = 0x%x\n", meta_offset);
338 // size = _codec_header (CODEC_DECODE_VIDEO, mem_offset, mmapbuf + meta_offset);
340 _codec_decode_video_meta_to (in_size, idx, in_offset, mmapbuf + meta_offset + size);
341 _codec_decode_video_inbuf (in_buf, in_size, mmapbuf + mem_offset);
343 dev->mem_info.offset = mem_offset;
345 _codec_write_to_qemu (ctx->index, CODEC_DECODE_VIDEO, mem_offset, fd);
347 // after decoding video, no need to get outbuf.
349 _codec_decode_video_meta_from (&ctx->video, got_picture_ptr, mmapbuf + meta_offset + size);
351 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
357 codec_picture_copy (CodecContext *ctx, uint8_t *pict,
358 uint32_t pict_size, CodecDevice *dev)
361 void *mmapbuf = NULL;
363 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
367 GST_ERROR ("failed to get %s fd\n", CODEC_DEV);
373 GST_ERROR ("failed to get mmaped memory address\n");
377 CODEC_LOG (DEBUG, "pict_size: %d\n", pict_size);
379 if (pict_size < (SMALL_BUFFER)) {
380 dev->mem_info.offset = (uint32_t)pict - (uint32_t)mmapbuf;
381 CODEC_LOG (DEBUG, "pict: %p , device_mem: %p\n", pict, mmapbuf);
382 CODEC_LOG (DEBUG, "picture_copy, mem_offset = 0x%x\n", dev->mem_info.offset);
385 _codec_write_to_qemu (ctx->index, CODEC_PICTURE_COPY,
386 dev->mem_info.offset, fd);
387 if (pict_size < SMALL_BUFFER) {
389 "set the mem_offset as outbuf: 0x%x\n", dev->mem_info.offset);
390 ret = ioctl (fd, CODEC_CMD_USE_DEVICE_MEM, &(dev->mem_info.offset));
394 } else if (pict_size < MEDIUM_BUFFER) {
395 uint32_t mem_offset = 0;
396 CODEC_LOG (DEBUG, "need to use medium size of memory\n");
398 ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_MEDIUM_BUFFER, &mem_offset);
402 CODEC_LOG (DEBUG, "picture_copy, mem_offset = 0x%x\n", mem_offset);
404 memcpy (pict, mmapbuf + mem_offset, pict_size);
406 ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
408 CODEC_LOG (ERR, "failed to release used memory\n");
411 uint32_t mem_offset = 0;
412 CODEC_LOG (DEBUG, "need to use large size of memory\n");
414 ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_LARGE_BUFFER, &mem_offset);
418 CODEC_LOG (DEBUG, "picture_copy, mem_offset = 0x%x\n", mem_offset);
420 memcpy (pict, mmapbuf + mem_offset, pict_size);
422 ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
424 CODEC_LOG (ERR, "failed to release used memory\n");
428 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
432 codec_decode_audio (CodecContext *ctx, int16_t *samples,
433 int *have_data, uint8_t *in_buf,
434 int in_size, CodecDevice *dev)
438 uint8_t *mmapbuf = NULL;
439 uint32_t mem_offset = 0, meta_offset = 0;
441 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
445 GST_ERROR("failed to get %s fd\n", CODEC_DEV);
449 mmapbuf = (uint8_t *)dev->buf;
451 GST_ERROR("failed to get mmaped memory address\n");
455 ret = ioctl (fd, CODEC_CMD_SECURE_SMALL_BUFFER, &mem_offset);
458 "decode_audio. failed to get available memory to write inbuf\n");
461 CODEC_LOG (DEBUG, "decode audio. mem_offset = 0x%x\n", mem_offset);
463 meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
464 CODEC_LOG (DEBUG, "decode_audio. meta_offset = 0x%x\n", meta_offset);
466 // size = _codec_header (CODEC_DECODE_AUDIO, mem_offset, mmapbuf + meta_offset);
468 _codec_decode_audio_meta_to (in_size, mmapbuf + meta_offset + size);
469 _codec_decode_audio_inbuf (in_buf, in_size, mmapbuf + mem_offset);
471 dev->mem_info.offset = mem_offset;
472 _codec_write_to_qemu (ctx->index, CODEC_DECODE_AUDIO, mem_offset, fd);
474 ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_SMALL_BUFFER, &mem_offset);
480 _codec_decode_audio_meta_from (&ctx->audio, have_data, mmapbuf + meta_offset + size);
482 _codec_decode_audio_outbuf (*have_data, samples, mmapbuf + mem_offset);
484 memset(mmapbuf + mem_offset, 0x00, sizeof(len));
486 ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
488 CODEC_LOG (ERR, "failed release used memory\n");
491 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
497 codec_encode_video (CodecContext *ctx, uint8_t *out_buf,
498 int out_size, uint8_t *in_buf,
499 int in_size, int64_t in_timestamp, CodecDevice *dev)
503 uint8_t *mmapbuf = NULL;
504 uint32_t mem_offset = 0, meta_offset = 0;
506 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
510 GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
516 GST_ERROR ("failed to get mmaped memory address.\n");
520 if (in_size < SMALL_BUFFER) {
521 CODEC_LOG (DEBUG, "use small size of buffer\n");
523 ret = ioctl (fd, CODEC_CMD_SECURE_SMALL_BUFFER, &mem_offset);
525 CODEC_LOG (ERR, "failed to small size of buffer.\n");
528 } else if (in_size < MEDIUM_BUFFER) {
529 CODEC_LOG (DEBUG, "use medium size of buffer\n");
531 ret = ioctl (fd, CODEC_CMD_SECURE_MEDIUM_BUFFER, &mem_offset);
533 CODEC_LOG (ERR, "failed to small size of buffer.\n");
537 CODEC_LOG (DEBUG, "use large size of buffer\n");
538 ret = ioctl (fd, CODEC_CMD_SECURE_LARGE_BUFFER, &mem_offset);
540 CODEC_LOG (ERR, "failed to large size of buffer.\n");
544 CODEC_LOG (DEBUG, "encode_video. mem_offset = 0x%x\n", mem_offset);
546 meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
547 CODEC_LOG (DEBUG, "encode_video. meta_offset = 0x%x\n", meta_offset);
550 // _codec_header (CODEC_ENCODE_VIDEO, mem_offset, mmapbuf + meta_offset);
553 _codec_encode_video_meta_to (in_size, in_timestamp, mmapbuf + meta_offset);
554 _codec_encode_video_inbuf (in_buf, in_size, mmapbuf + mem_offset);
556 dev->mem_info.offset = mem_offset;
557 _codec_write_to_qemu (ctx->index, CODEC_ENCODE_VIDEO, mem_offset, fd);
559 #ifndef DIRECT_BUFFER
560 ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_SMALL_BUFFER, &mem_offset);
564 CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", mem_offset);
566 memcpy (&len, mmapbuf + meta_offset, sizeof(len));
567 CODEC_LOG (DEBUG, "encode_video. outbuf size: %d\n", len);
569 memcpy (out_buf, mmapbuf + mem_offset, len);
570 out_buf = mmapbuf + mem_offset;
573 dev->mem_info.offset = mem_offset;
576 _codec_encode_video_outbuf (out_buf, mmapbuf + mem_offset);
577 // memset(mmapbuf + mem_offset, 0x00, sizeof(len));
581 ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
583 CODEC_LOG (ERR, "failed release used memory\n");
587 dev->mem_info.offset = (uint32_t)pict - (uint32_t)mmapbuf;
588 CODEC_LOG (DEBUG, "outbuf: %p , device_mem: %p\n", pict, mmapbuf);
589 CODEC_LOG (DEBUG, "encoded video. mem_offset = 0x%x\n", dev->mem_info.offset);
591 ret = ioctl (fd, CODEC_CMD_USE_DEVICE_MEM, &(dev->mem_info.offset));
596 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
602 codec_encode_audio (CodecContext *ctx, uint8_t *out_buf,
603 int max_size, uint8_t *in_buf,
604 int in_size, CodecDevice *dev)
608 void *mmapbuf = NULL;
609 uint32_t mem_offset = 0, meta_offset = 0;
611 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
615 GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
621 GST_ERROR ("failed to get mmaped memory address.\n");
625 ret = ioctl (fd, CODEC_CMD_SECURE_SMALL_BUFFER, &mem_offset);
630 CODEC_LOG (DEBUG, "write, encode_audio. mem_offset = 0x%x\n", mem_offset);
632 meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
633 CODEC_LOG (DEBUG, "encode_audio. meta mem_offset = 0x%x\n", meta_offset);
635 size = _codec_header (CODEC_ENCODE_AUDIO, mem_offset,
636 mmapbuf + meta_offset);
637 _codec_encode_audio_meta_to (max_size, in_size, mmapbuf + meta_offset + size);
638 _codec_encode_audio_inbuf (in_buf, in_size, mmapbuf + mem_offset);
640 dev->mem_info.offset = mem_offset;
641 _codec_write_to_qemu (ctx->index, CODEC_ENCODE_AUDIO, mem_offset, fd);
643 ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_SMALL_BUFFER, &mem_offset);
648 CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", mem_offset);
650 len = _codec_encode_audio_outbuf (out_buf, mmapbuf + mem_offset);
651 memset(mmapbuf + mem_offset, 0x00, sizeof(len));
653 ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
658 CODEC_LOG (DEBUG, "leave: %s\n", __func__);