improve decoding performance as 10 times than before.
[platform/adaptation/emulator/gst-plugins-emulator.git] / src / gstemulapi.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 "gstemulcommon.h"
32 #include "gstemulapi.h"
33 #include "gstemulapi2.h"
34 #include "gstemuldev.h"
35
36 static GStaticMutex codec_mutex = G_STATIC_MUTEX_INIT; 
37
38 void emul_codec_write_to_qemu (int ctx_index, int api_index, CodecDevice *dev)
39 {
40   CodecIOParams ioparam;
41
42 //  memset(&ioparam, 0, sizeof(ioparam));
43   ioparam.api_index = api_index;
44   ioparam.ctx_index = ctx_index;
45   ioparam.mem_offset = dev->mem_info.offset;
46   ioparam.mem_type = dev->mem_info.type;
47   if (write (dev->fd, &ioparam, 1) < 0) {
48     printf ("[%s:%d] failed to copy data.\n", __func__, __LINE__);
49   }
50 }
51
52 int
53 emul_avcodec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
54 {
55   int fd;
56   uint8_t *mmapbuf;
57   int ret = 0;
58   int usable, copyback;
59
60   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
61
62   fd = dev->fd;
63   if (fd < 0) {
64     GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
65     return -1;
66   }
67
68   mmapbuf = (uint8_t *)dev->buf;
69   if (!mmapbuf) {
70     GST_ERROR ("failed to get mmaped memory address.\n");
71     return -1;
72   }
73
74   ioctl(fd, CODEC_CMD_GET_CONTEXT_INDEX, &ctx->index);
75
76   if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
77     emul_avcodec_init_to (ctx, codec, mmapbuf);
78   } else {
79     ret = ioctl (fd, CODEC_CMD_ADD_TASK_QUEUE, &usable);
80     if (ret < 0) {
81       perror("ioctl failure");
82       CODEC_LOG (ERR, "[%d] return value: %d\n", __LINE__, ret);
83     }
84
85     while (1) {
86       ret = ioctl (fd, CODEC_CMD_COPY_TO_DEVICE_MEM, &usable);
87       if (ret < 0) {
88         perror("ioctl failure");
89         CODEC_LOG (ERR, "[%d] return value: %d\n", __LINE__, ret);
90       } else {
91         if (usable) {
92           CODEC_LOG (DEBUG, "[init] waiting after before.\n");
93           usleep (500);
94           continue;
95         }
96
97         emul_avcodec_init_to (ctx, codec, mmapbuf);
98         break;
99       }
100     }
101   }
102   emul_codec_write_to_qemu (ctx->index, CODEC_INIT, dev);
103
104   if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
105     int wait = 0;
106 #if 0
107     while (1) {
108       ret = ioctl (fd, CODEC_CMD_WAIT_TASK, &wait);
109       if (ret < 0) {
110         perror("ioctl failure");
111         CODEC_LOG (ERR, "[%d] return value: %d\n", __LINE__, ret);
112       } else {
113         if (wait) {
114           CODEC_LOG (DEBUG, "[init] waiting after write.\n");
115           usleep (500);
116           continue;
117         }
118
119         ret = emul_avcodec_init_from (ctx, codec, mmapbuf);
120         break;
121       }
122     }
123 #endif
124
125 #if 1 
126     ioctl (fd, CODEC_CMD_WAIT_TASK, &wait);
127     ret = emul_avcodec_init_from (ctx, codec, mmapbuf);
128 #endif
129   } else {
130     while (1) {
131       ret = ioctl (fd, CODEC_CMD_COPY_FROM_DEVICE_MEM, &usable);
132       if (ret < 0) {
133         perror("ioctl failure");
134         CODEC_LOG (ERR, "[%d] return value: %d\n", __LINE__, ret);
135       } else {
136         if (usable) {
137           CODEC_LOG (DEBUG, "[init][%d] waiting after write.\n", __LINE__);
138           usleep (500);
139           continue;
140         }
141
142         ret = emul_avcodec_init_from (ctx, codec, mmapbuf);
143         break;
144       }
145     }
146     ioctl (fd, CODEC_CMD_REMOVE_TASK_QUEUE, &copyback);
147   }
148
149   CODEC_LOG (DEBUG, "leave: %s, ret: %d\n", __func__, ret);
150   return ret;
151 }
152
153 void
154 emul_avcodec_deinit (CodecContext *ctx, CodecDevice *dev)
155 {
156   int fd;
157   void *mmapbuf = NULL;
158
159   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
160
161   fd = dev->fd;
162   if (fd < 0) {
163     GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
164     return;
165   }
166
167   mmapbuf = dev->buf;
168   if (!mmapbuf) {
169     GST_ERROR ("failed to get mmaped memory address.\n");
170     return;
171   }
172
173   emul_codec_write_to_qemu (ctx->index, CODEC_DEINIT, dev);
174
175   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
176 }
177
178 int
179 emul_avcodec_decode_video (CodecContext *ctx, uint8_t *in_buf, int in_size, gint idx, gint64 in_offset,
180     GstBuffer **out_buf, int *got_picture_ptr, CodecDevice *dev)
181 {
182   int fd;
183   uint8_t *mmapbuf = NULL;
184   int len = 0;
185   int copyback, usable;
186
187   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
188
189   fd = dev->fd;
190   if (fd < 0) {
191     GST_ERROR ("failed to get %s fd\n", CODEC_DEV);
192     return -1;
193   }
194
195   mmapbuf = (uint8_t *)dev->buf;
196   if (!mmapbuf) {
197     GST_ERROR ("failed to get mmaped memory address\n");
198     return -1;
199   }
200
201   if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
202     emul_avcodec_decode_video_to (in_buf, in_size, idx, in_offset, mmapbuf);
203   } else {
204     ioctl (fd, CODEC_CMD_ADD_TASK_QUEUE, NULL);
205
206     while (1) {
207       ioctl (fd, CODEC_CMD_COPY_TO_DEVICE_MEM, &usable);
208       if (usable) {
209         CODEC_LOG (DEBUG, "[decode_video] waiting before write.\n");
210         usleep (500);
211         continue;
212       }
213
214       emul_avcodec_decode_video_to (in_buf, in_size, idx, in_offset, mmapbuf);
215       break;
216     }
217   }
218
219   /* provide raw image for decoding to qemu */
220   emul_codec_write_to_qemu (ctx->index, CODEC_DECODE_VIDEO, dev);
221
222   if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
223     int wait = 0;
224 //    ioctl (fd, CODEC_CMD_WAIT_TASK, &wait);
225 #if 0 
226     while (1) {
227       ioctl (fd, CODEC_CMD_WAIT_TASK, &wait);
228       if (wait) {
229         CODEC_LOG (DEBUG, "[decode_video][%d] waiting after write.\n", __LINE__);
230         usleep (500);
231         continue;
232       }
233
234       len = emul_avcodec_decode_video_from (ctx, got_picture_ptr, mmapbuf);
235       break;
236     }
237 #endif
238
239 #if 1
240         ioctl (fd, CODEC_CMD_WAIT_TASK, &wait);
241     len = emul_avcodec_decode_video_from (ctx, got_picture_ptr, mmapbuf);
242 #endif
243   } else {
244     while (1) {
245       ioctl (fd, CODEC_CMD_COPY_FROM_DEVICE_MEM, &usable);
246       if (usable) {
247         CODEC_LOG (DEBUG, "[decode_video] waiting after write.\n");
248         usleep (500);
249         continue;
250       }
251       len = emul_avcodec_decode_video_from (ctx, got_picture_ptr, mmapbuf);
252       break;
253     }
254     ioctl (fd, CODEC_CMD_REMOVE_TASK_QUEUE, &copyback);
255   }
256
257   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
258   return len;
259 }
260
261 void
262 emul_av_picture_copy (CodecContext *ctx, uint8_t *pict,
263                       uint32_t pict_size, CodecDevice *dev)
264 {
265   int fd;
266   void *mmapbuf = NULL;
267   int copyback, usable;
268
269   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
270
271   fd = dev->fd;
272   if (fd < 0) {
273     GST_ERROR ("failed to get %s fd\n", CODEC_DEV);
274     return;
275   }
276
277   mmapbuf = dev->buf;
278   if (!mmapbuf) {
279     GST_ERROR ("failed to get mmaped memory address\n");
280     return;
281   }
282
283   if (dev->mem_info.type == CODEC_SHARED_DEVICE_MEM) {
284     ioctl (fd, CODEC_CMD_ADD_TASK_QUEUE, NULL);
285
286     while (1) {
287       ioctl (fd, CODEC_CMD_COPY_TO_DEVICE_MEM, &usable);
288       if (usable) {
289         CODEC_LOG (DEBUG, "[copy_frame] waiting before write.\n");
290         usleep (500);
291         continue;
292       }
293       break;
294     }
295   }
296
297   emul_codec_write_to_qemu (ctx->index, CODEC_PICTURE_COPY, dev);
298
299   if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
300     int wait = 0;
301 //    ioctl (fd, CODEC_CMD_WAIT_TASK, &wait);
302 #if 0 
303     while (1) {
304       ioctl (fd, CODEC_CMD_WAIT_TASK, &wait);
305       if (wait) {
306         CODEC_LOG (DEBUG, "[copy_frame] waiting after write.\n");
307         usleep (500);
308         continue;
309       }
310       memcpy (pict, mmapbuf, pict_size);
311       break;
312     }
313 #endif
314
315 #if 1
316     ioctl (fd, CODEC_CMD_WAIT_TASK, &wait);
317     memcpy (pict, mmapbuf, pict_size);
318 #endif
319   } else {
320     while (1) {
321       ioctl (fd, CODEC_CMD_COPY_FROM_DEVICE_MEM, &usable);
322       if (usable) {
323         CODEC_LOG (DEBUG, "[copy_frame] waiting after write.\n");
324         usleep (500);
325         continue;
326       }
327       memcpy (pict, mmapbuf, pict_size);
328       break;
329     }
330     ioctl (fd, CODEC_CMD_REMOVE_TASK_QUEUE, &copyback);
331   }
332
333   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
334 }
335
336 int
337 emul_avcodec_decode_audio (CodecContext *ctx, int16_t *samples,
338                           int *frame_size_ptr, uint8_t *in_buf,
339                           int in_size, CodecDevice *dev)
340 {
341   int fd;
342   uint8_t *mmapbuf = NULL;
343   int len;
344   int copyback, usable;
345
346   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
347
348   fd = dev->fd;
349   if (fd < 0) {
350     GST_ERROR("failed to get %s fd\n", CODEC_DEV);
351     return -1;
352   }
353
354   mmapbuf = (uint8_t *)dev->buf;
355   if (!mmapbuf) {
356     GST_ERROR("failed to get mmaped memory address\n");
357     return -1;
358   }
359
360   if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
361     emul_avcodec_decode_audio_to (in_buf, in_size, mmapbuf);
362   } else {
363     ioctl (fd, CODEC_CMD_ADD_TASK_QUEUE, NULL);
364
365     while (1) {
366       ioctl (fd, CODEC_CMD_COPY_TO_DEVICE_MEM, &usable);
367       if (usable) {
368         CODEC_LOG (DEBUG, "[decode_audio] waiting before write.\n");
369         usleep (500);
370         continue;
371       }
372
373       emul_avcodec_decode_audio_to (in_buf, in_size, mmapbuf);
374       break;
375     }
376   }
377
378   emul_codec_write_to_qemu (ctx->index, CODEC_DECODE_AUDIO, dev);
379
380   if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
381     int wait = 0;
382     ioctl (fd, CODEC_CMD_WAIT_TASK, &wait);
383     len =
384                   emul_avcodec_decode_audio_from (ctx, frame_size_ptr, samples, mmapbuf);
385
386 #if 0 
387     while (1) {
388       ioctl (fd, CODEC_CMD_WAIT_TASK, &wait);
389       if (wait) {
390         CODEC_LOG (DEBUG, "[decode_audio] waiting after write.\n");
391         usleep (500);
392         continue;
393       }
394
395       len =
396         emul_avcodec_decode_audio_from (ctx, frame_size_ptr, samples, mmapbuf);
397       break;
398     }
399 #endif
400   } else {
401     while (1) {
402       ioctl (fd, CODEC_CMD_COPY_FROM_DEVICE_MEM, &usable);
403       if (usable) {
404         CODEC_LOG (DEBUG, "[decode_audio] waiting after write.\n");
405         usleep (500);
406         continue;
407       }
408
409       len =
410         emul_avcodec_decode_audio_from (ctx, frame_size_ptr, samples, mmapbuf);
411       break;
412     }
413     ioctl (fd, CODEC_CMD_REMOVE_TASK_QUEUE, &copyback);
414   }
415
416   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
417   return len;
418 }
419
420 int
421 emul_avcodec_encode_video (CodecContext *ctx, uint8_t *out_buf,
422                         int out_size, uint8_t *in_buf,
423                         int in_size, int64_t in_timestamp, CodecDevice *dev)
424 {
425   int fd;
426   void *mmapbuf;
427   int len = 0;
428   int copyback, usable;
429
430   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
431
432   fd = dev->fd;
433   if (fd < 0) {
434     GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
435     return -1;
436   }
437
438   mmapbuf = dev->buf;
439   if (!mmapbuf) {
440     GST_ERROR ("failed to get mmaped memory address.\n");
441     return -1;
442   }
443
444   if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
445     emul_avcodec_encode_video_to (in_buf, in_size, in_timestamp, mmapbuf);
446   } else {
447     ioctl (fd, CODEC_CMD_ADD_TASK_QUEUE, NULL);
448
449     while (1) {
450       ioctl (fd, CODEC_CMD_COPY_TO_DEVICE_MEM, &usable);
451       if (usable) {
452         CODEC_LOG (DEBUG, "[encode_video] waiting before write.\n");
453         usleep (500);
454         continue;
455       }
456
457       emul_avcodec_encode_video_to (in_buf, in_size, in_timestamp, mmapbuf);
458       break;
459     }
460   }
461
462   emul_codec_write_to_qemu (ctx->index, CODEC_ENCODE_VIDEO, dev);
463
464   if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
465     int wait = 0;
466     while (1) {
467       ioctl (fd, CODEC_CMD_WAIT_TASK, &wait);
468       if (wait) {
469         CODEC_LOG (DEBUG, "[encode_video] waiting after write.\n");
470         usleep (500);
471         continue;
472       }
473
474       len = emul_avcodec_encode_video_from (out_buf, out_size, mmapbuf);
475       break;
476     }
477   } else {
478     while (1) {
479       ioctl (fd, CODEC_CMD_COPY_FROM_DEVICE_MEM, &usable);
480       if (usable) {
481         CODEC_LOG (DEBUG, "[encode_video] waiting after write.\n");
482         usleep (500);
483         continue;
484       }
485
486       len = emul_avcodec_encode_video_from (out_buf, out_size, mmapbuf);
487       break;
488     }
489     ioctl (fd, CODEC_CMD_REMOVE_TASK_QUEUE, &copyback);
490   }
491
492   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
493   return len;
494 }
495
496 int
497 emul_avcodec_encode_audio (CodecContext *ctx, uint8_t *out_buf,
498                           int out_size, uint8_t *in_buf,
499                           int in_size, CodecDevice *dev)
500 {
501   int fd;
502   void *mmapbuf;
503   int len = 0;
504   int copyback, usable;
505
506   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
507
508   fd = dev->fd;
509   if (fd < 0) {
510     GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
511     return -1;
512   }
513
514   mmapbuf = dev->buf;
515   if (!mmapbuf) {
516     GST_ERROR ("failed to get mmaped memory address.\n");
517     return -1;
518   }
519
520   if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
521     emul_avcodec_encode_audio_to (out_size, in_size, in_buf, mmapbuf);
522   } else {
523     ioctl (fd, CODEC_CMD_ADD_TASK_QUEUE, NULL);
524
525     while (1) {
526       ioctl (fd, CODEC_CMD_COPY_TO_DEVICE_MEM, &usable);
527       if (usable) {
528         CODEC_LOG (DEBUG, "[encode_audio] waiting before write.\n");
529         usleep (500);
530         continue;
531       }
532
533       emul_avcodec_encode_audio_to (out_size, in_size, in_buf, mmapbuf);
534       break;
535     }
536   }
537
538   emul_codec_write_to_qemu (ctx->index, CODEC_ENCODE_AUDIO, dev);
539
540   if (dev->mem_info.type == CODEC_FIXED_DEVICE_MEM) {
541     int wait = 0;
542     while (1) {
543       ioctl (fd, CODEC_CMD_WAIT_TASK, &wait);
544       if (wait) {
545         CODEC_LOG (DEBUG, "[encode_audio] waiting after write.\n");
546         usleep (500);
547         continue;
548       }
549       len = emul_avcodec_encode_audio_from (out_buf, out_size, mmapbuf);
550       break;
551     }
552
553     len = emul_avcodec_encode_audio_from (out_buf, out_size, mmapbuf);
554   } else {
555     while (1) {
556       ioctl (fd, CODEC_CMD_COPY_FROM_DEVICE_MEM, &usable);
557       if (usable) {
558         CODEC_LOG (DEBUG, "[encode_audio] waiting after write.\n");
559         usleep (500);
560         continue;
561       }
562       len = emul_avcodec_encode_audio_from (out_buf, out_size, mmapbuf);
563       break;
564     }
565     ioctl (fd, CODEC_CMD_REMOVE_TASK_QUEUE, &copyback);
566   }
567
568   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
569   return len;
570 }