added flush_buffer routine in decoder.
[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 };
43
44 typedef struct _CodecHeader {
45   int32_t   api_index;
46   uint32_t  mem_offset;
47 } CodecHeader;
48
49 #define SMALL_BUFFER    (256 * 1024)
50 #define MEDIUM_BUFFER   (2 * 1024 * 1024)
51 #define LARGE_BUFFER    (4 * 1024 * 1024)
52
53 #define CODEC_META_DATA_SIZE 256
54
55 static int
56 _codec_header (int32_t api_index, uint32_t mem_offset, uint8_t *device_buf)
57 {
58   CodecHeader header = { 0 };
59
60   CODEC_LOG (DEBUG, "enter, %s\n", __func__);
61
62   header.api_index = api_index;
63   header.mem_offset = mem_offset;
64
65   memcpy(device_buf, &header, sizeof(header));
66
67   CODEC_LOG (DEBUG, "leave, %s\n", __func__);
68
69   return sizeof(header);
70 }
71
72 static void
73 _codec_write_to_qemu (int32_t ctx_index, int32_t api_index,
74                           uint32_t mem_offset, int fd)
75 {
76   CodecIOParams ioparam;
77
78   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
79
80   memset(&ioparam, 0, sizeof(ioparam));
81   ioparam.api_index = api_index;
82   ioparam.ctx_index = ctx_index;
83   ioparam.mem_offset = mem_offset;
84   if (write (fd, &ioparam, 1) < 0) {
85     CODEC_LOG (ERR, "failed to write input data\n");
86   }
87
88   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
89 }
90
91 static struct mem_info
92 secure_device_mem (guint buf_size)
93 {
94   int ret = 0;
95   uint32_t mem_offset = 0, cmd = 0;
96   struct mem_info info = {0, };
97
98   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
99
100   if (buf_size < SMALL_BUFFER) {
101     cmd = CODEC_CMD_SECURE_SMALL_BUFFER;
102     CODEC_LOG (DEBUG, "small buffer size\n");
103   } else if (buf_size < MEDIUM_BUFFER) {
104     // HD Video(2MB)
105     cmd = CODEC_CMD_SECURE_MEDIUM_BUFFER;
106     CODEC_LOG (DEBUG, "HD buffer size\n");
107   } else {
108     // FULL HD Video(4MB)
109     cmd = CODEC_CMD_SECURE_LARGE_BUFFER;
110     CODEC_LOG (DEBUG, "FULL HD buffer size\n");
111   }
112
113   ret = ioctl (device_fd, cmd, &mem_offset);
114   if (ret < 0) {
115     CODEC_LOG (ERR, "failed to get available buffer\n");
116     // FIXME:
117   } else {
118     if (mem_offset == (LARGE_BUFFER * 8)) {
119       CODEC_LOG (ERR, "acquired memory is over!!\n");
120     } else {
121       info.start = (gpointer)((uint32_t)device_mem + mem_offset);
122       info.offset = mem_offset;
123
124       CODEC_LOG (DEBUG, "acquire device_memory: 0x%x\n", mem_offset);
125     }
126   }
127
128   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
129
130   return info;
131 }
132
133 static void
134 release_device_mem (gpointer start)
135 {
136   int ret;
137   uint32_t offset = start - device_mem;
138
139   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
140
141   CODEC_LOG (DEBUG, "release device_mem start: %p, offset: 0x%x\n", start, offset);
142   ret = ioctl (device_fd, CODEC_CMD_RELEASE_BUFFER, &offset);
143   if (ret < 0) {
144     CODEC_LOG (ERR, "failed to release buffer\n");
145   }
146
147   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
148 }
149
150 static void
151 codec_buffer_free (gpointer start)
152 {
153   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
154
155   release_device_mem (start);
156
157   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
158 }
159
160 GstFlowReturn
161 codec_buffer_alloc (GstPad *pad, guint64 offset, guint size,
162                   GstCaps *caps, GstBuffer **buf)
163 {
164   struct mem_info info;
165
166   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
167
168   *buf = gst_buffer_new ();
169
170   info = secure_device_mem (size);
171
172   CODEC_LOG (DEBUG, "memory start: 0x%p, offset 0x%x\n",
173             info.start, info.offset);
174
175   GST_BUFFER_DATA (*buf) = GST_BUFFER_MALLOCDATA (*buf) = info.start;
176   GST_BUFFER_SIZE (*buf) = size;
177   GST_BUFFER_FREE_FUNC (*buf) = codec_buffer_free;
178   GST_BUFFER_OFFSET (*buf) = offset;
179
180   if (caps) {
181     gst_buffer_set_caps (*buf, caps);
182   }
183
184   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
185
186   return GST_FLOW_OK;
187 }
188
189 int
190 codec_init (CodecContext *ctx, CodecElement *codec, CodecDevice *dev)
191 {
192   int fd, ret = 0;
193   int opened, size = 0;
194   uint8_t *mmapbuf = NULL;
195   uint32_t meta_offset = 0;
196
197   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
198
199   fd = dev->fd;
200   if (fd < 0) {
201     GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
202     return -1;
203   }
204
205   mmapbuf = (uint8_t *)dev->buf;
206   if (!mmapbuf) {
207     GST_ERROR ("failed to get mmaped memory address.\n");
208     return -1;
209   }
210
211   ret = ioctl(fd, CODEC_CMD_GET_CONTEXT_INDEX, &ctx->index);
212   if (ret < 0) {
213     GST_ERROR ("failed to get context index\n");
214     return -1;
215   }
216   CODEC_LOG (DEBUG, "get context index: %d\n", ctx->index);
217
218   meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
219   CODEC_LOG (DEBUG,
220     "init. ctx: %d meta_offset = 0x%x\n", ctx->index, meta_offset);
221
222 //  size = _codec_header (CODEC_INIT, 0, mmapbuf + meta_offset);
223   size = 8;
224   _codec_init_meta_to (ctx, codec, mmapbuf + meta_offset + size);
225
226   _codec_write_to_qemu (ctx->index, CODEC_INIT, 0, fd);
227
228   CODEC_LOG (DEBUG,
229     "init. ctx: %d meta_offset = 0x%x, size: %d\n", ctx->index, meta_offset, size);
230
231 #if 0
232   if (codec->media_type == AVMEDIA_TYPE_AUDIO) {
233     CODEC_LOG (DEBUG,
234         "opened: %d, audio_sample_fmt: %d\n",
235         *(int *)(mmapbuf + meta_offset + size),
236         *(int *)(mmapbuf + meta_offset + size + 4));
237   }
238 #endif
239
240   opened =
241     _codec_init_meta_from (ctx, codec->media_type, mmapbuf + meta_offset + size);
242   ctx->codec= codec;
243
244   CODEC_LOG (DEBUG, "opened: %d\n", opened);
245
246   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
247
248   return opened;
249 }
250
251 void
252 codec_deinit (CodecContext *ctx, CodecDevice *dev)
253 {
254   int fd;
255   void *mmapbuf = NULL;
256
257   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
258
259   fd = dev->fd;
260   if (fd < 0) {
261     GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
262     return;
263   }
264
265   mmapbuf = dev->buf;
266   if (!mmapbuf) {
267     GST_ERROR ("failed to get mmaped memory address.\n");
268     return;
269   }
270
271   CODEC_LOG (INFO, "close. context index: %d\n", ctx->index);
272   _codec_write_to_qemu (ctx->index, CODEC_DEINIT, 0, fd);
273
274   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
275 }
276
277 void
278 codec_flush_buffers (CodecContext *ctx, CodecDevice *dev)
279 {
280   int fd;
281   void *mmapbuf = NULL;
282
283   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
284
285   fd = dev->fd;
286   if (fd < 0) {
287     GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
288     return;
289   }
290
291   mmapbuf = dev->buf;
292   if (!mmapbuf) {
293     GST_ERROR ("failed to get mmaped memory address.\n");
294     return;
295   }
296
297   CODEC_LOG (DEBUG, "flush buffers. context index: %d\n", ctx->index);
298   _codec_write_to_qemu (ctx->index, CODEC_FLUSH_BUFFERS, 0, fd);
299
300   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
301 }
302
303 int
304 codec_decode_video (CodecContext *ctx, uint8_t *in_buf, int in_size,
305                     gint idx, gint64 in_offset, GstBuffer **out_buf,
306                     int *got_picture_ptr, CodecDevice *dev)
307 {
308   int fd, len = 0;
309   int ret, size = 0;
310   uint8_t *mmapbuf = NULL;
311   uint32_t mem_offset = 0, meta_offset = 0;
312
313   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
314
315   fd = dev->fd;
316   if (fd < 0) {
317     GST_ERROR ("failed to get %s fd\n", CODEC_DEV);
318     return -1;
319   }
320
321   mmapbuf = dev->buf;
322   if (!mmapbuf) {
323     GST_ERROR ("failed to get mmaped memory address\n");
324     return -1;
325   }
326
327   ret = ioctl (fd, CODEC_CMD_SECURE_SMALL_BUFFER, &mem_offset);
328   if (ret < 0) {
329     CODEC_LOG (ERR,
330       "decode_audio. failed to get available memory to write inbuf\n");
331     return -1;
332   }
333   CODEC_LOG (DEBUG, "decode_video. mem_offset = 0x%x\n", mem_offset);
334
335   meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
336   CODEC_LOG (DEBUG, "decode_video. meta_offset = 0x%x\n", meta_offset);
337
338 //  size = _codec_header (CODEC_DECODE_VIDEO, mem_offset, mmapbuf + meta_offset);
339   size = 8;
340   _codec_decode_video_meta_to (in_size, idx, in_offset, mmapbuf + meta_offset + size);
341   _codec_decode_video_inbuf (in_buf, in_size, mmapbuf + mem_offset);
342
343   dev->mem_info.offset = mem_offset;
344
345   _codec_write_to_qemu (ctx->index, CODEC_DECODE_VIDEO, mem_offset, fd);
346
347   // after decoding video, no need to get outbuf.
348   len =
349     _codec_decode_video_meta_from (&ctx->video, got_picture_ptr, mmapbuf + meta_offset + size);
350
351   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
352
353   return len;
354 }
355
356 void
357 codec_picture_copy (CodecContext *ctx, uint8_t *pict,
358                     uint32_t pict_size, CodecDevice *dev)
359 {
360   int fd, ret = 0;
361   void *mmapbuf = NULL;
362
363   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
364
365   fd = dev->fd;
366   if (fd < 0) {
367     GST_ERROR ("failed to get %s fd\n", CODEC_DEV);
368     return;
369   }
370
371   mmapbuf = dev->buf;
372   if (!mmapbuf) {
373     GST_ERROR ("failed to get mmaped memory address\n");
374     return;
375   }
376
377   CODEC_LOG (DEBUG, "pict_size: %d\n",  pict_size);
378
379   if (pict_size < (SMALL_BUFFER)) {
380     dev->mem_info.offset = (uint32_t)pict - (uint32_t)mmapbuf;
381     CODEC_LOG (DEBUG, "pict: %p , device_mem: %p\n",  pict, mmapbuf);
382     CODEC_LOG (DEBUG, "picture_copy, mem_offset = 0x%x\n",  dev->mem_info.offset);
383   }
384
385   _codec_write_to_qemu (ctx->index, CODEC_PICTURE_COPY,
386                         dev->mem_info.offset, fd);
387   if (pict_size < SMALL_BUFFER) {
388     CODEC_LOG (DEBUG,
389       "set the mem_offset as outbuf: 0x%x\n",  dev->mem_info.offset);
390     ret = ioctl (fd, CODEC_CMD_USE_DEVICE_MEM, &(dev->mem_info.offset));
391     if (ret < 0) {
392     // FIXME:
393     }
394   } else if (pict_size < MEDIUM_BUFFER) {
395     uint32_t mem_offset = 0;
396     CODEC_LOG (DEBUG, "need to use medium size of memory\n");
397
398     ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_MEDIUM_BUFFER, &mem_offset);
399     if (ret < 0) {
400       return;
401     }
402     CODEC_LOG (DEBUG, "picture_copy, mem_offset = 0x%x\n",  mem_offset);
403
404     memcpy (pict, mmapbuf + mem_offset, pict_size);
405
406     ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
407     if (ret < 0) {
408       CODEC_LOG (ERR, "failed to release used memory\n");
409     }
410   } else {
411     uint32_t mem_offset = 0;
412     CODEC_LOG (DEBUG, "need to use large size of memory\n");
413
414     ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_LARGE_BUFFER, &mem_offset);
415     if (ret < 0) {
416       return;
417     }
418     CODEC_LOG (DEBUG, "picture_copy, mem_offset = 0x%x\n",  mem_offset);
419
420     memcpy (pict, mmapbuf + mem_offset, pict_size);
421
422     ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
423     if (ret < 0) {
424       CODEC_LOG (ERR, "failed to release used memory\n");
425     }
426   }
427
428   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
429 }
430
431 int
432 codec_decode_audio (CodecContext *ctx, int16_t *samples,
433                     int *have_data, uint8_t *in_buf,
434                     int in_size, CodecDevice *dev)
435 {
436   int fd, len = 0;
437   int ret, size = 0;
438   uint8_t *mmapbuf = NULL;
439   uint32_t mem_offset = 0, meta_offset = 0;
440
441   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
442
443   fd = dev->fd;
444   if (fd < 0) {
445     GST_ERROR("failed to get %s fd\n", CODEC_DEV);
446     return -1;
447   }
448
449   mmapbuf = (uint8_t *)dev->buf;
450   if (!mmapbuf) {
451     GST_ERROR("failed to get mmaped memory address\n");
452     return -1;
453   }
454
455   ret = ioctl (fd, CODEC_CMD_SECURE_SMALL_BUFFER, &mem_offset);
456   if (ret < 0) {
457     CODEC_LOG (ERR,
458       "decode_audio. failed to get available memory to write inbuf\n");
459     return -1;
460   }
461   CODEC_LOG (DEBUG, "decode audio. mem_offset = 0x%x\n", mem_offset);
462
463   meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
464   CODEC_LOG (DEBUG, "decode_audio. meta_offset = 0x%x\n", meta_offset);
465
466 //  size = _codec_header (CODEC_DECODE_AUDIO, mem_offset, mmapbuf + meta_offset);
467   size = 8;
468   _codec_decode_audio_meta_to (in_size, mmapbuf + meta_offset + size);
469   _codec_decode_audio_inbuf (in_buf, in_size, mmapbuf + mem_offset);
470
471   dev->mem_info.offset = mem_offset;
472   _codec_write_to_qemu (ctx->index, CODEC_DECODE_AUDIO, mem_offset, fd);
473
474   ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_SMALL_BUFFER, &mem_offset);
475   if (ret < 0) {
476     return -1;
477   }
478
479   len =
480     _codec_decode_audio_meta_from (&ctx->audio, have_data, mmapbuf + meta_offset + size);
481   if (len > 0) {
482     _codec_decode_audio_outbuf (*have_data, samples, mmapbuf + mem_offset);
483   }
484   memset(mmapbuf + mem_offset, 0x00, sizeof(len));
485
486   ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
487   if (ret < 0) {
488     CODEC_LOG (ERR, "failed release used memory\n");
489   }
490
491   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
492
493   return len;
494 }
495
496 int
497 codec_encode_video (CodecContext *ctx, uint8_t *out_buf,
498                     int out_size, uint8_t *in_buf,
499                     int in_size, int64_t in_timestamp, CodecDevice *dev)
500 {
501   int fd, len = 0;
502   int ret, size;
503   uint8_t *mmapbuf = NULL;
504   uint32_t mem_offset = 0, meta_offset = 0;
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 (in_size < SMALL_BUFFER) {
521     CODEC_LOG (DEBUG, "use small size of buffer\n");
522
523     ret = ioctl (fd, CODEC_CMD_SECURE_SMALL_BUFFER, &mem_offset);
524     if (ret < 0) {
525       CODEC_LOG (ERR, "failed to small size of buffer.\n");
526       return -1;
527     }
528   } else if (in_size < MEDIUM_BUFFER) {
529     CODEC_LOG (DEBUG, "use medium size of buffer\n");
530
531     ret = ioctl (fd, CODEC_CMD_SECURE_MEDIUM_BUFFER, &mem_offset);
532     if (ret < 0) {
533       CODEC_LOG (ERR, "failed to small size of buffer.\n");
534       return -1;
535     }
536   } else {
537     CODEC_LOG (DEBUG, "use large size of buffer\n");
538     ret = ioctl (fd, CODEC_CMD_SECURE_LARGE_BUFFER, &mem_offset);
539     if (ret < 0) {
540       CODEC_LOG (ERR, "failed to large size of buffer.\n");
541       return -1;
542     }
543   }
544   CODEC_LOG (DEBUG, "encode_video. mem_offset = 0x%x\n", mem_offset);
545
546   meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
547   CODEC_LOG (DEBUG, "encode_video. meta_offset = 0x%x\n", meta_offset);
548
549 //  size =
550 //    _codec_header (CODEC_ENCODE_VIDEO, mem_offset, mmapbuf + meta_offset);
551   size = 8;
552   meta_offset += size;
553   _codec_encode_video_meta_to (in_size, in_timestamp, mmapbuf + meta_offset);
554   _codec_encode_video_inbuf (in_buf, in_size, mmapbuf + mem_offset);
555
556   dev->mem_info.offset = mem_offset;
557   _codec_write_to_qemu (ctx->index, CODEC_ENCODE_VIDEO, mem_offset, fd);
558
559 #ifndef DIRECT_BUFFER
560   ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_SMALL_BUFFER, &mem_offset);
561   if (ret < 0) {
562     return -1;
563   }
564   CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", mem_offset);
565
566   memcpy (&len, mmapbuf + meta_offset, sizeof(len));
567   CODEC_LOG (DEBUG, "encode_video. outbuf size: %d\n", len);
568   if (len > 0) {
569     memcpy (out_buf, mmapbuf + mem_offset, len);
570     out_buf = mmapbuf + mem_offset;
571   }
572
573   dev->mem_info.offset = mem_offset;
574 #if 0
575   len =
576     _codec_encode_video_outbuf (out_buf, mmapbuf + mem_offset);
577 //  memset(mmapbuf + mem_offset, 0x00, sizeof(len));
578 #endif
579
580 #if 1
581   ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
582   if (ret < 0) {
583     CODEC_LOG (ERR, "failed release used memory\n");
584   }
585 #endif
586 #else
587   dev->mem_info.offset = (uint32_t)pict - (uint32_t)mmapbuf;
588   CODEC_LOG (DEBUG, "outbuf: %p , device_mem: %p\n",  pict, mmapbuf);
589   CODEC_LOG (DEBUG, "encoded video. mem_offset = 0x%x\n",  dev->mem_info.offset);
590
591   ret = ioctl (fd, CODEC_CMD_USE_DEVICE_MEM, &(dev->mem_info.offset));
592   if (ret < 0) {
593     // FIXME:
594   }
595 #endif
596   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
597
598   return len;
599 }
600
601 int
602 codec_encode_audio (CodecContext *ctx, uint8_t *out_buf,
603                     int max_size, uint8_t *in_buf,
604                     int in_size, CodecDevice *dev)
605 {
606   int fd, len = 0;
607   int ret, size;
608   void *mmapbuf = NULL;
609   uint32_t mem_offset = 0, meta_offset = 0;
610
611   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
612
613   fd = dev->fd;
614   if (fd < 0) {
615     GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
616     return -1;
617   }
618
619   mmapbuf = dev->buf;
620   if (!mmapbuf) {
621     GST_ERROR ("failed to get mmaped memory address.\n");
622     return -1;
623   }
624
625   ret = ioctl (fd, CODEC_CMD_SECURE_SMALL_BUFFER, &mem_offset);
626   if (ret < 0) {
627     return -1;
628   }
629
630   CODEC_LOG (DEBUG, "write, encode_audio. mem_offset = 0x%x\n", mem_offset);
631
632   meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
633   CODEC_LOG (DEBUG, "encode_audio. meta mem_offset = 0x%x\n", meta_offset);
634
635   size = _codec_header (CODEC_ENCODE_AUDIO, mem_offset,
636                             mmapbuf + meta_offset);
637   _codec_encode_audio_meta_to (max_size, in_size, mmapbuf + meta_offset + size);
638   _codec_encode_audio_inbuf (in_buf, in_size, mmapbuf + mem_offset);
639
640   dev->mem_info.offset = mem_offset;
641   _codec_write_to_qemu (ctx->index, CODEC_ENCODE_AUDIO, mem_offset, fd);
642
643   ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_SMALL_BUFFER, &mem_offset);
644   if (ret < 0) {
645     return -1;
646   }
647
648   CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", mem_offset);
649
650   len = _codec_encode_audio_outbuf (out_buf, mmapbuf + mem_offset);
651   memset(mmapbuf + mem_offset, 0x00, sizeof(len));
652
653   ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
654   if (ret < 0) {
655     return -1;
656   }
657
658   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
659
660   return len;
661 }