Modify secure_device_mem function and source 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 typedef struct _CodecBufferId {
51   uint32_t  buffer_index;
52   uint32_t  buffer_size;
53 } CodecBufferId;
54
55 #define CODEC_META_DATA_SIZE    256
56 #define GET_OFFSET(buffer)      ((uint32_t)buffer - (uint32_t)device_mem)
57 #define SMALLDATA               0
58
59 static void
60 _codec_invoke_qemu (int32_t ctx_index, int32_t api_index,
61                           uint32_t mem_offset, int fd)
62 {
63   CodecIOParams ioparam = { 0 };
64
65   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
66
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");
72   }
73
74   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
75 }
76
77 static int
78 secure_device_mem (int fd, guint ctx_id, guint buf_size, gpointer* buffer)
79 {
80   int ret = 0;
81 //  uint32_t opaque = 0;
82   CodecBufferId opaque;
83
84   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
85   opaque.buffer_index = ctx_id;
86   opaque.buffer_size = buf_size;
87
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);
91
92   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
93
94   return ret;
95 }
96
97 static void
98 release_device_mem (int fd, gpointer start)
99 {
100   int ret;
101   uint32_t offset = start - device_mem;
102
103   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
104
105   CODEC_LOG (DEBUG, "release device_mem start: %p, offset: 0x%x\n", start, offset);
106   ret = ioctl (fd, CODEC_CMD_RELEASE_BUFFER, &offset);
107   if (ret < 0) {
108     CODEC_LOG (ERR, "failed to release buffer\n");
109   }
110
111   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
112 }
113
114 static void
115 codec_buffer_free (gpointer start)
116 {
117   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
118
119   release_device_mem (device_fd, start);
120
121   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
122 }
123
124 GstFlowReturn
125 codec_buffer_alloc_and_copy (GstPad *pad, guint64 offset, guint size,
126                   GstCaps *caps, GstBuffer **buf)
127 {
128   struct mem_info info;
129   CodecBufferId opaque;
130   int ret = 0;
131   GstMaruDec *marudec;
132
133   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
134
135   *buf = gst_buffer_new ();
136
137   marudec = (GstMaruDec *)gst_pad_get_element_private(pad);
138
139   opaque.buffer_index = marudec->context->index;
140   opaque.buffer_size = size;
141
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);
145
146   ret = ioctl (marudec->dev->fd, CODEC_CMD_PUT_DATA_INTO_BUFFER, &opaque);
147
148   if (ret < 0) {
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);
153     info.offset = 0;
154
155     GST_BUFFER_FREE_FUNC (*buf) = g_free;
156
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);
159
160     CODEC_LOG (DEBUG, "we secured last buffer, so we will use heap buffer\n");
161   } else {
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;
165
166     GST_BUFFER_FREE_FUNC (*buf) = codec_buffer_free;
167
168     CODEC_LOG (DEBUG, "device memory start: 0x%p, offset 0x%x\n", info.start, info.offset);
169   }
170
171   GST_BUFFER_DATA (*buf) = GST_BUFFER_MALLOCDATA (*buf) = info.start;
172   GST_BUFFER_SIZE (*buf) = size;
173   GST_BUFFER_OFFSET (*buf) = offset;
174
175   if (caps) {
176     gst_buffer_set_caps (*buf, caps);
177   }
178
179   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
180
181   return GST_FLOW_OK;
182 }
183
184 int
185 codec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
186 {
187   int ret = 0, opened = 0, size = 8;
188   uint32_t meta_offset = 0;
189
190   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
191
192   ret = ioctl(dev->fd, CODEC_CMD_GET_CONTEXT_INDEX, &ctx->index);
193   if (ret < 0) {
194     GST_ERROR ("failed to get context index\n");
195     return -1;
196   }
197   CODEC_LOG (DEBUG, "get context index: %d\n", ctx->index);
198
199   meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
200   CODEC_LOG (DEBUG,
201     "init. ctx: %d meta_offset = 0x%x\n", ctx->index, meta_offset);
202
203   _codec_init_meta_to (ctx, codec, device_mem + meta_offset + size);
204
205   _codec_invoke_qemu (ctx->index, CODEC_INIT, 0, dev->fd);
206
207   CODEC_LOG (DEBUG,
208     "init. ctx: %d meta_offset = 0x%x, size: %d\n", ctx->index, meta_offset, size);
209
210   opened =
211     _codec_init_meta_from (ctx, codec->media_type, device_mem + meta_offset + size);
212   ctx->codec = codec;
213
214   CODEC_LOG (DEBUG, "opened: %d\n", opened);
215
216   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
217
218   return opened;
219 }
220
221 void
222 codec_deinit (CodecContext *ctx, CodecDevice *dev)
223 {
224   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
225
226   CODEC_LOG (INFO, "close. context index: %d\n", ctx->index);
227   _codec_invoke_qemu (ctx->index, CODEC_DEINIT, 0, dev->fd);
228
229   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
230 }
231
232 void
233 codec_flush_buffers (CodecContext *ctx, CodecDevice *dev)
234 {
235   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
236
237   CODEC_LOG (DEBUG, "flush buffers. context index: %d\n", ctx->index);
238   _codec_invoke_qemu (ctx->index, CODEC_FLUSH_BUFFERS, 0, dev->fd);
239
240   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
241 }
242
243 int
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)
247 {
248   int len = 0, ret = 0, size = 8;
249   gpointer buffer = NULL;
250   uint32_t meta_offset = 0;
251
252   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
253
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);
257
258   ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
259   if (ret < 0) {
260     CODEC_LOG (ERR,
261       "decode_video. failed to get available memory to write inbuf\n");
262     return -1;
263   }
264
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);
268
269   // after decoding video, no need to get outbuf.
270   len =
271     _codec_decode_video_meta_from (&ctx->video, got_picture_ptr, device_mem + meta_offset + size);
272
273   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
274
275   return len;
276 }
277
278 int
279 codec_decode_audio (CodecContext *ctx, int16_t *samples,
280                     int *have_data, uint8_t *in_buf,
281                     int in_size, CodecDevice *dev)
282 {
283   int len = 0, ret = 0, size = 8;
284   gpointer buffer = NULL;
285   uint32_t meta_offset = 0;
286   CodecBufferId opaque;
287
288   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
289
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);
293
294   ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
295   if (ret < 0) {
296     CODEC_LOG (ERR,
297       "decode_audio. failed to get available memory to write inbuf\n");
298     return -1;
299   }
300
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);
304
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);
309   if (ret < 0) {
310     return -1;
311   }
312   CODEC_LOG (DEBUG, "after decode_audio. ctx_id: %d, buffer = 0x%x\n",
313             ctx->index, (int)device_mem + opaque.buffer_size);
314
315   len =
316     _codec_decode_audio_meta_from (&ctx->audio, have_data, device_mem + meta_offset + size);
317   if (len > 0) {
318     _codec_decode_audio_outbuf (*have_data, samples, device_mem + opaque.buffer_size);
319   } else {
320     CODEC_LOG (DEBUG, "decode_audio failure. ctx_id: %d\n", ctx->index);
321   }
322   CODEC_LOG (DEBUG, "decode_audio. ctx_id: %d len: %d\n", ctx->index, len);
323
324   release_device_mem(dev->fd, device_mem + opaque.buffer_size);
325
326   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
327
328   return len;
329 }
330
331 int
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)
335 {
336   int len = 0, ret = 0, size = 8;
337   gpointer buffer = NULL;
338   uint32_t meta_offset = 0;
339   CodecBufferId opaque;
340
341   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
342
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);
346
347   ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
348   if (ret < 0) {
349     CODEC_LOG (ERR, "failed to small size of buffer.\n");
350     return -1;
351   }
352
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);
356
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);
361   if (ret < 0) {
362     return -1;
363   }
364   CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", opaque.buffer_size);
365
366   memcpy (&len, device_mem + meta_offset + size, sizeof(len));
367
368   CODEC_LOG (DEBUG, "encode_video. outbuf size: %d\n", len);
369   if (len > 0) {
370     memcpy (out_buf, device_mem + opaque.buffer_size, len);
371     dev->mem_info.offset = opaque.buffer_size;
372   }
373
374   release_device_mem(dev->fd, device_mem + opaque.buffer_size);
375
376   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
377
378   return len;
379 }
380
381 int
382 codec_encode_audio (CodecContext *ctx, uint8_t *out_buf,
383                     int max_size, uint8_t *in_buf,
384                     int in_size, CodecDevice *dev)
385 {
386   int len = 0, ret = 0, size = 8;
387   gpointer buffer = NULL;
388   uint32_t meta_offset = 0;
389   CodecBufferId opaque;
390
391   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
392
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);
396
397   ret = secure_device_mem(dev->fd, ctx->index, in_size, &buffer);
398   if (ret < 0) {
399     return -1;
400   }
401
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);
405
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);
410   if (ret < 0) {
411     return -1;
412   }
413
414   CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", opaque.buffer_size);
415
416   len = _codec_encode_audio_outbuf (out_buf, device_mem + opaque.buffer_size);
417
418   release_device_mem(dev->fd, device_mem + opaque.buffer_size);
419
420   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
421
422   return len;
423 }