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