Code clean-up.
[platform/adaptation/emulator/gst-plugins-emulator.git] / src / gstmaruinterface.c
1 /*
2  * GStreamer codec plugin for Tizen Emulator.
3  *
4  * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  * KiTae Kim <kt920.kim@samsung.com>
8  * SeokYeon Hwang <syeon.hwang@samsung.com>
9  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
10  *
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.
15  *
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.
20  *
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.
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  *
29  */
30
31 #include "gstmaru.h"
32 #include "gstmaruinterface.h"
33 #include "gstmarumem.h"
34 #include "gstmarudevice.h"
35
36 extern int device_fd;
37 extern gpointer device_mem;
38
39 struct mem_info {
40     gpointer start;
41     uint32_t offset;
42     uint32_t size;
43 };
44
45 typedef struct _CodecHeader {
46   int32_t   api_index;
47   uint32_t  mem_offset;
48 } CodecHeader;
49
50 #define CODEC_META_DATA_SIZE    256
51 #define GET_OFFSET(buffer)      ((uint32_t)buffer - (uint32_t)device_mem)
52 #define SMALLDATA               0
53
54 static int
55 _codec_header (int32_t api_index, uint32_t mem_offset, uint8_t *device_buf)
56 {
57   CodecHeader header = { 0 };
58
59   CODEC_LOG (DEBUG, "enter, %s\n", __func__);
60
61   header.api_index = api_index;
62   header.mem_offset = mem_offset;
63
64   memcpy(device_buf, &header, sizeof(header));
65
66   CODEC_LOG (DEBUG, "leave, %s\n", __func__);
67
68   return sizeof(header);
69 }
70
71 static void
72 _codec_write_to_qemu (int32_t ctx_index, int32_t api_index,
73                           uint32_t mem_offset, int fd)
74 {
75   CodecIOParams ioparam;
76
77   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
78
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");
85   }
86
87   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
88 }
89
90 static int
91 secure_device_mem (int fd, guint buf_size, gpointer* buffer)
92 {
93   int ret = 0;
94   uint32_t opaque = 0;
95   struct mem_info info = {0, };
96
97   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
98   opaque = buf_size;
99
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);
103
104   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
105
106   return ret;
107 }
108
109 static void
110 release_device_mem (int fd, gpointer start)
111 {
112   int ret;
113   uint32_t offset = start - device_mem;
114
115   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
116
117   CODEC_LOG (DEBUG, "release device_mem start: %p, offset: 0x%x\n", start, offset);
118   if (fd == -1) {
119     // FIXME: We use device_fd now...
120     fd = device_fd;
121   }
122   ret = ioctl (fd, CODEC_CMD_RELEASE_BUFFER, &offset);
123   if (ret < 0) {
124     CODEC_LOG (ERR, "failed to release buffer\n");
125   }
126
127   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
128 }
129
130 static void
131 codec_buffer_free (gpointer start)
132 {
133   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
134
135   release_device_mem (-1, start);
136
137   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
138 }
139
140 GstFlowReturn
141 codec_buffer_alloc_and_copy (GstPad *pad, guint64 offset, guint size,
142                   GstCaps *caps, GstBuffer **buf)
143 {
144   struct mem_info info;
145   uint32_t opaque;
146   int ret = 0;
147   GstMaruDec *marudec;
148
149   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
150
151   opaque = size;
152
153   *buf = gst_buffer_new ();
154
155   marudec = (GstMaruDec *)gst_pad_get_element_private(pad);
156
157   _codec_write_to_qemu (marudec->context->index, CODEC_PICTURE_COPY,
158                         0, marudec->dev->fd);
159
160   ret = ioctl (marudec->dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque);
161
162   if (ret < 0) {
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);
167     info.offset = 0;
168
169     GST_BUFFER_FREE_FUNC (*buf) = g_free;
170
171     memcpy (info.start, (uint32_t)device_mem + opaque, size);
172     release_device_mem(marudec->dev->fd, (uint32_t)device_mem + opaque);
173
174     CODEC_LOG (DEBUG, "we secured last buffer, so we will use heap buffer\n");
175   } else {
176     // address of "device_mem" and "opaque" is aleady aligned.
177     info.start = (gpointer)((uint32_t)device_mem + opaque);
178     info.offset = opaque;
179
180     GST_BUFFER_FREE_FUNC (*buf) = codec_buffer_free;
181
182     CODEC_LOG (DEBUG, "device memory start: 0x%p, offset 0x%x\n", info.start, info.offset);
183   }
184
185   GST_BUFFER_DATA (*buf) = GST_BUFFER_MALLOCDATA (*buf) = info.start;
186   GST_BUFFER_SIZE (*buf) = size;
187   GST_BUFFER_OFFSET (*buf) = offset;
188
189   if (caps) {
190     gst_buffer_set_caps (*buf, caps);
191   }
192
193   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
194
195   return GST_FLOW_OK;
196 }
197
198 int
199 codec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
200 {
201   int ret = 0, opened = 0, size = 8;
202   uint32_t meta_offset = 0;
203
204   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
205
206   ret = ioctl(dev->fd, CODEC_CMD_GET_CONTEXT_INDEX, &ctx->index);
207   if (ret < 0) {
208     GST_ERROR ("failed to get context index\n");
209     return -1;
210   }
211   CODEC_LOG (DEBUG, "get context index: %d\n", ctx->index);
212
213   meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
214   CODEC_LOG (DEBUG,
215     "init. ctx: %d meta_offset = 0x%x\n", ctx->index, meta_offset);
216
217   _codec_init_meta_to (ctx, codec, device_mem + meta_offset + size);
218
219   _codec_write_to_qemu (ctx->index, CODEC_INIT, 0, dev->fd);
220
221   CODEC_LOG (DEBUG,
222     "init. ctx: %d meta_offset = 0x%x, size: %d\n", ctx->index, meta_offset, size);
223
224   opened =
225     _codec_init_meta_from (ctx, codec->media_type, device_mem + meta_offset + size);
226   ctx->codec = codec;
227
228   CODEC_LOG (DEBUG, "opened: %d\n", opened);
229
230   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
231
232   return opened;
233 }
234
235 void
236 codec_deinit (CodecContext *ctx, CodecDevice *dev)
237 {
238   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
239
240   CODEC_LOG (INFO, "close. context index: %d\n", ctx->index);
241   _codec_write_to_qemu (ctx->index, CODEC_DEINIT, 0, dev->fd);
242
243   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
244 }
245
246 void
247 codec_flush_buffers (CodecContext *ctx, CodecDevice *dev)
248 {
249   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
250
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);
253
254   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
255 }
256
257 int
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)
261 {
262   int len = 0, ret = 0, size = 8;
263   gpointer buffer = NULL;
264   uint32_t meta_offset = 0;
265
266   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
267
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);
271
272   ret = secure_device_mem(dev->fd, in_size, &buffer);
273   if (ret < 0) {
274     CODEC_LOG (ERR,
275       "decode_video. failed to get available memory to write inbuf\n");
276     return -1;
277   }
278
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);
282
283   // after decoding video, no need to get outbuf.
284   len =
285     _codec_decode_video_meta_from (&ctx->video, got_picture_ptr, device_mem + meta_offset + size);
286
287   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
288
289   return len;
290 }
291
292 int
293 codec_decode_audio (CodecContext *ctx, int16_t *samples,
294                     int *have_data, uint8_t *in_buf,
295                     int in_size, CodecDevice *dev)
296 {
297   int len = 0, ret = 0, size = 8;
298   gpointer buffer = NULL;
299   uint32_t meta_offset = 0, opaque = 0;
300
301   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
302
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);
306
307   ret = secure_device_mem(dev->fd, in_size, &buffer);
308   if (ret < 0) {
309     CODEC_LOG (ERR,
310       "decode_audio. failed to get available memory to write inbuf\n");
311     return -1;
312   }
313
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);
317
318   opaque = SMALLDATA; // FIXME: how can we know output data size ?
319   ret = ioctl (dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque);
320   if (ret < 0) {
321     return -1;
322   }
323   CODEC_LOG (DEBUG, "after decode_audio. ctx_id: %d, buffer = 0x%x\n", ctx->index, (int)buffer);
324
325   len =
326     _codec_decode_audio_meta_from (&ctx->audio, have_data, device_mem + meta_offset + size);
327   if (len > 0) {
328     _codec_decode_audio_outbuf (*have_data, samples, buffer);
329   } else {
330     CODEC_LOG (DEBUG, "decode_audio failure. ctx_id: %d\n", ctx->index);
331   }
332
333   release_device_mem(dev->fd, buffer);
334
335   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
336
337   return len;
338 }
339
340 int
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)
344 {
345   int len = 0, ret = 0, size = 8;
346   gpointer buffer = NULL;
347   uint32_t meta_offset = 0, opaque = 0;
348
349   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
350
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);
354
355   ret = secure_device_mem(dev->fd, in_size, &buffer);
356   if (ret < 0) {
357     CODEC_LOG (ERR, "failed to small size of buffer.\n");
358     return -1;
359   }
360
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);
364
365   opaque = SMALLDATA; // FIXME: how can we know output data size ?
366   ret = ioctl (dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque);
367   if (ret < 0) {
368     return -1;
369   }
370   CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", opaque);
371
372   memcpy (&len, device_mem + meta_offset + size, sizeof(len));
373
374   CODEC_LOG (DEBUG, "encode_video. outbuf size: %d\n", len);
375   if (len > 0) {
376     memcpy (out_buf, buffer, len);
377     dev->mem_info.offset = GET_OFFSET(buffer);
378   }
379
380   release_device_mem(dev->fd, buffer);
381
382   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
383
384   return len;
385 }
386
387 int
388 codec_encode_audio (CodecContext *ctx, uint8_t *out_buf,
389                     int max_size, uint8_t *in_buf,
390                     int in_size, CodecDevice *dev)
391 {
392   int len = 0, ret = 0, size = 8;
393   gpointer buffer = NULL;
394   uint32_t meta_offset = 0, opaque = 0;
395
396   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
397
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);
403
404   ret = secure_device_mem(dev->fd, in_size, &buffer);
405   if (ret < 0) {
406     return -1;
407   }
408
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);
412
413   opaque = SMALLDATA; // FIXME: how can we know output data size ?
414   ret = ioctl (dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque);
415   if (ret < 0) {
416     return -1;
417   }
418
419   CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", opaque);
420
421   len = _codec_encode_audio_outbuf (out_buf, buffer);
422
423   release_device_mem(dev->fd, buffer);
424
425   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
426
427   return len;
428 }