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;
40 typedef struct _CodecHeader {
45 typedef struct _CodecBufferId {
46 uint32_t buffer_index;
50 typedef struct _CodecIOParams {
55 CodecBufferId buffer_id;
59 #define CODEC_META_DATA_SIZE 256
60 #define GET_OFFSET(buffer) ((uint32_t)buffer - (uint32_t)device_mem)
63 #define OFFSET_PICTURE_BUFFER 0x100
66 _codec_invoke_qemu(int32_t ctx_index, int32_t api_index,
67 uint32_t mem_offset, int fd, CodecBufferId *buffer_id)
69 CodecIOParams ioparam = { 0, };
72 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
74 ioparam.api_index = api_index;
75 ioparam.ctx_index = ctx_index;
76 ioparam.mem_offset = mem_offset;
78 if (CHECK_VERSION(3)) {
80 ioparam.buffer_id.buffer_index = buffer_id->buffer_index;
81 ioparam.buffer_id.buffer_size = buffer_id->buffer_size;
84 ret = ioctl(fd, CODEC_CMD_INVOKE_API_AND_RELEASE_BUFFER, &ioparam);
87 buffer_id->buffer_index = ioparam.buffer_id.buffer_index;
88 buffer_id->buffer_size = ioparam.buffer_id.buffer_size;
91 if (ioctl(fd, CODEC_CMD_INVOKE_API_AND_RELEASE_BUFFER, &ioparam) < 0) {
95 ret = ioctl(fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, buffer_id);
99 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
105 secure_device_mem (int fd, guint ctx_id, guint buf_size, gpointer* buffer)
108 CodecBufferId opaque;
110 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
111 opaque.buffer_index = ctx_id;
112 opaque.buffer_size = buf_size;
114 ret = ioctl (fd, CODEC_CMD_SECURE_BUFFER, &opaque);
115 /* ioctl: CODEC_CMD_SECURE_BUFFER
116 * - sets device memory offset into opaque.buffer_size
118 *buffer = (gpointer)((uint32_t)device_mem + opaque.buffer_size);
119 GST_DEBUG ("device_mem %p, offset_size 0x%x", device_mem, opaque.buffer_size);
121 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
127 release_device_mem (int fd, gpointer start)
130 uint32_t offset = start - device_mem;
132 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
134 GST_DEBUG ("release device_mem start: %p, offset: 0x%x", start, offset);
135 ret = ioctl (fd, CODEC_CMD_RELEASE_BUFFER, &offset);
137 GST_ERROR ("failed to release buffer\n");
140 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
144 codec_buffer_free (gpointer start)
146 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
148 release_device_mem (device_fd, start);
150 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
154 codec_buffer_free2 (gpointer start)
156 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
158 release_device_mem (device_fd, start - OFFSET_PICTURE_BUFFER);
160 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
164 codec_buffer_alloc_and_copy (GstPad *pad, guint64 offset, guint size,
165 GstCaps *caps, GstBuffer **buf)
167 bool is_last_buffer = 0;
169 CodecBufferId opaque;
174 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
176 *buf = gst_buffer_new ();
178 marudec = (GstMaruDec *)gst_pad_get_element_private(pad);
179 ctx = marudec->context;
182 if (marudec->is_using_new_decode_api) {
183 is_last_buffer = marudec->is_last_buffer;
184 mem_offset = marudec->mem_offset;
186 ctx = marudec->context;
188 opaque.buffer_index = ctx->index;
189 opaque.buffer_size = size;
191 GST_DEBUG ("buffer_and_copy. ctx_id: %d", ctx->index);
193 int ret = _codec_invoke_qemu(ctx->index, CODEC_PICTURE_COPY, 0, dev->fd, &opaque);
195 GST_DEBUG ("failed to get available buffer");
196 return GST_FLOW_ERROR;
198 is_last_buffer = ret;
199 mem_offset = opaque.buffer_size;
202 gpointer *buffer = NULL;
203 if (is_last_buffer) {
204 // FIXME: we must aligned buffer offset.
205 buffer = g_malloc (size);
207 GST_BUFFER_FREE_FUNC (*buf) = g_free;
209 if (marudec->is_using_new_decode_api) {
210 memcpy (buffer, device_mem + mem_offset + OFFSET_PICTURE_BUFFER, size);
212 memcpy (buffer, device_mem + mem_offset, size);
214 release_device_mem(dev->fd, device_mem + mem_offset);
216 GST_DEBUG ("secured last buffer!! Use heap buffer");
218 // address of "device_mem" and "opaque" is aleady aligned.
219 if (marudec->is_using_new_decode_api) {
220 buffer = (gpointer)(device_mem + mem_offset + OFFSET_PICTURE_BUFFER);
221 GST_BUFFER_FREE_FUNC (*buf) = codec_buffer_free2;
223 buffer = (gpointer)(device_mem + mem_offset);
224 GST_BUFFER_FREE_FUNC (*buf) = codec_buffer_free;
228 GST_DEBUG ("device memory start: 0x%p, offset 0x%x", (intptr_t)buffer, mem_offset);
231 GST_BUFFER_DATA (*buf) = GST_BUFFER_MALLOCDATA (*buf) = (void *)buffer;
232 GST_BUFFER_SIZE (*buf) = size;
233 GST_BUFFER_OFFSET (*buf) = offset;
236 gst_buffer_set_caps (*buf, caps);
239 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
245 codec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
248 gpointer buffer = NULL;
249 CodecBufferId opaque;
252 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
254 if (ioctl(dev->fd, CODEC_CMD_GET_CONTEXT_INDEX, &ctx->index) < 0) {
255 GST_ERROR ("failed to get a context index");
258 GST_DEBUG ("get context index: %d", ctx->index);
260 /* buffer size is 0. It means that this function is required to
263 if (secure_device_mem(dev->fd, ctx->index, 0, &buffer) < 0) {
264 GST_ERROR ("failed to get a memory block");
268 codec_init_data_to (ctx, codec, buffer);
270 opaque.buffer_index = ctx->index;
271 opaque.buffer_size = SMALLDATA;
273 ret = _codec_invoke_qemu (ctx->index, CODEC_INIT, GET_OFFSET(buffer), dev->fd, &opaque);
280 codec_init_data_from (ctx, codec->media_type, device_mem + opaque.buffer_size);
283 GST_ERROR ("failed to open Context for %s", codec->name);
288 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
290 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
296 codec_deinit (CodecContext *ctx, CodecDevice *dev)
298 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
300 GST_INFO ("close context %d", ctx->index);
301 _codec_invoke_qemu (ctx->index, CODEC_DEINIT, 0, dev->fd, NULL);
303 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
307 codec_flush_buffers (CodecContext *ctx, CodecDevice *dev)
309 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
311 GST_DEBUG ("flush buffers of context: %d", ctx->index);
312 _codec_invoke_qemu (ctx->index, CODEC_FLUSH_BUFFERS, 0, dev->fd, NULL);
314 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
318 codec_decode_video (GstMaruDec *marudec, uint8_t *in_buf, int in_size,
319 gint idx, gint64 in_offset, GstBuffer **out_buf, int *have_data)
321 CodecContext *ctx = marudec->context;
322 CodecDevice *dev = marudec->dev;
323 int len = 0, ret = 0;
324 gpointer buffer = NULL;
325 CodecBufferId opaque = { 0, };
327 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
329 ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
331 GST_ERROR ("failed to get available memory to write inbuf");
335 codec_decode_video_data_to (in_size, idx, in_offset, in_buf, buffer);
337 opaque.buffer_index = ctx->index;
339 marudec->is_using_new_decode_api = (can_use_new_decode_api() && (ctx->video.pix_fmt != -1));
341 if (marudec->is_using_new_decode_api) {
342 int picture_size = gst_maru_avpicture_size (ctx->video.pix_fmt,
343 ctx->video.width, ctx->video.height);
344 if (picture_size < 0) {
345 GST_ERROR ("Check about it"); // FIXME
346 opaque.buffer_size = SMALLDATA;
348 opaque.buffer_size = picture_size;
350 ret = _codec_invoke_qemu(ctx->index, CODEC_DECODE_VIDEO2, GET_OFFSET(buffer), dev->fd, &opaque);
352 opaque.buffer_size = SMALLDATA;
353 ret = _codec_invoke_qemu(ctx->index, CODEC_DECODE_VIDEO, GET_OFFSET(buffer), dev->fd, &opaque);
360 len = codec_decode_video_data_from (have_data, &ctx->video, device_mem + opaque.buffer_size);
362 GST_DEBUG_OBJECT (marudec, "after decode: len %d, have_data %d",
364 if (len < 0 || *have_data <= 0) {
365 GST_DEBUG_OBJECT (marudec, "return flow %d, out %p, len %d",
368 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
373 if (marudec->is_using_new_decode_api) {
374 marudec->is_last_buffer = ret;
375 marudec->mem_offset = opaque.buffer_size;
377 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
380 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
386 codec_decode_audio (CodecContext *ctx, int16_t *samples,
387 int *have_data, uint8_t *in_buf,
388 int in_size, CodecDevice *dev)
390 int len = 0, ret = 0;
391 gpointer buffer = NULL;
392 CodecBufferId opaque;
394 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
396 ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
398 GST_ERROR ("failed to get available memory to write inbuf");
402 GST_DEBUG ("decode_audio 1. in_buffer size %d", in_size);
403 codec_decode_audio_data_to (in_size, in_buf, buffer);
405 opaque.buffer_index = ctx->index;
406 opaque.buffer_size = SMALLDATA;
408 ret = _codec_invoke_qemu(ctx->index, CODEC_DECODE_AUDIO, GET_OFFSET(buffer), dev->fd, &opaque);
414 GST_DEBUG ("decode_audio 2. ctx_id: %d, buffer = 0x%x",
415 ctx->index, device_mem + opaque.buffer_size);
417 len = codec_decode_audio_data_from (have_data, samples,
418 &ctx->audio, device_mem + opaque.buffer_size);
420 GST_DEBUG ("decode_audio 3. ctx_id: %d len: %d", ctx->index, len);
422 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
424 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
430 codec_encode_video (CodecContext *ctx, uint8_t *out_buf,
431 int out_size, uint8_t *in_buf,
432 int in_size, int64_t in_timestamp,
433 int *coded_frame, int *is_keyframe,
436 int len = 0, ret = 0;
437 gpointer buffer = NULL;
438 CodecBufferId opaque;
440 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
442 ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
444 GST_ERROR ("failed to small size of buffer");
448 codec_encode_video_data_to (in_size, in_timestamp, in_buf, buffer);
450 opaque.buffer_index = ctx->index;
451 opaque.buffer_size = SMALLDATA;
453 // FIXME: how can we know output data size ?
454 ret = _codec_invoke_qemu(ctx->index, CODEC_ENCODE_VIDEO, GET_OFFSET(buffer), dev->fd, &opaque);
460 GST_DEBUG ("encode_video. mem_offset = 0x%x", opaque.buffer_size);
462 len = codec_encode_video_data_from (out_buf, coded_frame, is_keyframe, device_mem + opaque.buffer_size);
464 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
466 CODEC_LOG (DEBUG, "leave: %s\n", __func__);
472 codec_encode_audio (CodecContext *ctx, uint8_t *out_buf,
473 int max_size, uint8_t *in_buf,
474 int in_size, int64_t timestamp,
478 gpointer buffer = NULL;
479 CodecBufferId opaque;
481 CODEC_LOG (DEBUG, "enter: %s\n", __func__);
483 ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
488 codec_encode_audio_data_to (in_size, max_size, in_buf, timestamp, buffer);
490 opaque.buffer_index = ctx->index;
491 opaque.buffer_size = SMALLDATA;
493 ret = _codec_invoke_qemu(ctx->index, CODEC_ENCODE_AUDIO, GET_OFFSET(buffer), dev->fd, &opaque);
499 GST_DEBUG ("encode_audio. mem_offset = 0x%x", opaque.buffer_size);
501 ret = codec_encode_audio_data_from (out_buf, device_mem + opaque.buffer_size);
503 release_device_mem(dev->fd, device_mem + opaque.buffer_size);
505 CODEC_LOG (DEBUG, "leave: %s\n", __func__);