Changed a way to query codec element.
[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 = 8;
223   _codec_init_meta_to (ctx, codec, mmapbuf + meta_offset + size);
224
225   _codec_write_to_qemu (ctx->index, CODEC_INIT, 0, fd);
226
227   CODEC_LOG (DEBUG,
228     "init. ctx: %d meta_offset = 0x%x, size: %d\n", ctx->index, meta_offset, size);
229
230   opened =
231     _codec_init_meta_from (ctx, codec->media_type, mmapbuf + meta_offset + size);
232   ctx->codec= codec;
233
234   CODEC_LOG (DEBUG, "opened: %d\n", opened);
235
236   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
237
238   return opened;
239 }
240
241 void
242 codec_deinit (CodecContext *ctx, CodecDevice *dev)
243 {
244   int fd;
245   void *mmapbuf = NULL;
246
247   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
248
249   fd = dev->fd;
250   if (fd < 0) {
251     GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
252     return;
253   }
254
255   mmapbuf = dev->buf;
256   if (!mmapbuf) {
257     GST_ERROR ("failed to get mmaped memory address.\n");
258     return;
259   }
260
261   CODEC_LOG (INFO, "close. context index: %d\n", ctx->index);
262   _codec_write_to_qemu (ctx->index, CODEC_DEINIT, 0, fd);
263
264   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
265 }
266
267 void
268 codec_flush_buffers (CodecContext *ctx, CodecDevice *dev)
269 {
270   int fd;
271   void *mmapbuf = NULL;
272
273   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
274
275   fd = dev->fd;
276   if (fd < 0) {
277     GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
278     return;
279   }
280
281   mmapbuf = dev->buf;
282   if (!mmapbuf) {
283     GST_ERROR ("failed to get mmaped memory address.\n");
284     return;
285   }
286
287   CODEC_LOG (DEBUG, "flush buffers. context index: %d\n", ctx->index);
288   _codec_write_to_qemu (ctx->index, CODEC_FLUSH_BUFFERS, 0, fd);
289
290   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
291 }
292
293 int
294 codec_decode_video (CodecContext *ctx, uint8_t *in_buf, int in_size,
295                     gint idx, gint64 in_offset, GstBuffer **out_buf,
296                     int *got_picture_ptr, CodecDevice *dev)
297 {
298   int fd, len = 0;
299   int ret, size = 0;
300   uint8_t *mmapbuf = NULL;
301   uint32_t mem_offset = 0, meta_offset = 0;
302
303   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
304
305   fd = dev->fd;
306   if (fd < 0) {
307     GST_ERROR ("failed to get %s fd\n", CODEC_DEV);
308     return -1;
309   }
310
311   mmapbuf = dev->buf;
312   if (!mmapbuf) {
313     GST_ERROR ("failed to get mmaped memory address\n");
314     return -1;
315   }
316
317   ret = ioctl (fd, CODEC_CMD_SECURE_SMALL_BUFFER, &mem_offset);
318   if (ret < 0) {
319     CODEC_LOG (ERR,
320       "decode_video. failed to get available memory to write inbuf\n");
321     return -1;
322   }
323   CODEC_LOG (DEBUG, "decode_video. mem_offset = 0x%x\n", mem_offset);
324
325   meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
326   CODEC_LOG (DEBUG, "decode_video. meta_offset = 0x%x\n", meta_offset);
327
328   size = 8;
329   _codec_decode_video_meta_to (in_size, idx, in_offset, mmapbuf + meta_offset + size);
330   _codec_decode_video_inbuf (in_buf, in_size, mmapbuf + mem_offset);
331
332   dev->mem_info.offset = mem_offset;
333
334   _codec_write_to_qemu (ctx->index, CODEC_DECODE_VIDEO, mem_offset, fd);
335
336   // after decoding video, no need to get outbuf.
337   len =
338     _codec_decode_video_meta_from (&ctx->video, got_picture_ptr, mmapbuf + meta_offset + size);
339
340   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
341
342   return len;
343 }
344
345 void
346 codec_picture_copy (CodecContext *ctx, uint8_t *pict,
347                     uint32_t pict_size, CodecDevice *dev)
348 {
349   int fd, ret = 0;
350   void *mmapbuf = NULL;
351
352   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
353
354   fd = dev->fd;
355   if (fd < 0) {
356     GST_ERROR ("failed to get %s fd\n", CODEC_DEV);
357     return;
358   }
359
360   mmapbuf = dev->buf;
361   if (!mmapbuf) {
362     GST_ERROR ("failed to get mmaped memory address\n");
363     return;
364   }
365
366   CODEC_LOG (DEBUG, "pict_size: %d\n",  pict_size);
367
368   if (pict_size < (SMALL_BUFFER)) {
369     dev->mem_info.offset = (uint32_t)pict - (uint32_t)mmapbuf;
370     CODEC_LOG (DEBUG, "pict: %p , device_mem: %p\n",  pict, mmapbuf);
371     CODEC_LOG (DEBUG, "picture_copy, mem_offset = 0x%x\n",  dev->mem_info.offset);
372   }
373
374   _codec_write_to_qemu (ctx->index, CODEC_PICTURE_COPY,
375                         dev->mem_info.offset, fd);
376   if (pict_size < SMALL_BUFFER) {
377     CODEC_LOG (DEBUG,
378       "set the mem_offset as outbuf: 0x%x\n",  dev->mem_info.offset);
379     ret = ioctl (fd, CODEC_CMD_USE_DEVICE_MEM, &(dev->mem_info.offset));
380     if (ret < 0) {
381     // FIXME:
382     }
383   } else if (pict_size < MEDIUM_BUFFER) {
384     uint32_t mem_offset = 0;
385     CODEC_LOG (DEBUG, "need to use medium size of memory\n");
386
387     ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_MEDIUM_BUFFER, &mem_offset);
388     if (ret < 0) {
389       return;
390     }
391     CODEC_LOG (DEBUG, "picture_copy, mem_offset = 0x%x\n",  mem_offset);
392
393     memcpy (pict, mmapbuf + mem_offset, pict_size);
394
395     ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
396     if (ret < 0) {
397       CODEC_LOG (ERR, "failed to release used memory\n");
398     }
399   } else {
400     uint32_t mem_offset = 0;
401     CODEC_LOG (DEBUG, "need to use large size of memory\n");
402
403     ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_LARGE_BUFFER, &mem_offset);
404     if (ret < 0) {
405       return;
406     }
407     CODEC_LOG (DEBUG, "picture_copy, mem_offset = 0x%x\n",  mem_offset);
408
409     memcpy (pict, mmapbuf + mem_offset, pict_size);
410
411     ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
412     if (ret < 0) {
413       CODEC_LOG (ERR, "failed to release used memory\n");
414     }
415   }
416
417   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
418 }
419
420 int
421 codec_decode_audio (CodecContext *ctx, int16_t *samples,
422                     int *have_data, uint8_t *in_buf,
423                     int in_size, CodecDevice *dev)
424 {
425   int fd, len = 0;
426   int ret, size = 0;
427   uint8_t *mmapbuf = NULL;
428   uint32_t mem_offset = 0, meta_offset = 0;
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 = (uint8_t *)dev->buf;
439   if (!mmapbuf) {
440     GST_ERROR("failed to get mmaped memory address\n");
441     return -1;
442   }
443
444   ret = ioctl (fd, CODEC_CMD_SECURE_SMALL_BUFFER, &mem_offset);
445   if (ret < 0) {
446     CODEC_LOG (ERR,
447       "decode_audio. failed to get available memory to write inbuf\n");
448     return -1;
449   }
450 //  CODEC_LOG (DEBUG, "decode audio. mem_offset = 0x%x\n", mem_offset);
451   CODEC_LOG (DEBUG, "decode_audio. ctx_id: %d mem_offset = 0x%x\n", ctx->index, mem_offset);
452
453   meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
454   CODEC_LOG (DEBUG, "decode_audio. ctx_id: %d meta_offset = 0x%x\n", ctx->index, meta_offset);
455
456   size = 8;
457   _codec_decode_audio_meta_to (in_size, mmapbuf + meta_offset + size);
458   _codec_decode_audio_inbuf (in_buf, in_size, mmapbuf + mem_offset);
459
460   dev->mem_info.offset = mem_offset;
461   _codec_write_to_qemu (ctx->index, CODEC_DECODE_AUDIO, mem_offset, fd);
462
463   ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_SMALL_BUFFER, &mem_offset);
464   if (ret < 0) {
465     return -1;
466   }
467   CODEC_LOG (DEBUG, "after decode_audio. ctx_id: %d mem_offset = 0x%x\n", ctx->index, mem_offset);
468
469   len =
470     _codec_decode_audio_meta_from (&ctx->audio, have_data, mmapbuf + meta_offset + size);
471   if (len > 0) {
472     _codec_decode_audio_outbuf (*have_data, samples, mmapbuf + mem_offset);
473   } else {
474     CODEC_LOG (DEBUG, "decode_audio failure. ctx_id: %d\n", ctx->index);
475   }
476
477   memset(mmapbuf + mem_offset, 0x00, sizeof(len));
478
479   ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
480   if (ret < 0) {
481     CODEC_LOG (ERR, "failed release used memory\n");
482   }
483
484   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
485
486   return len;
487 }
488
489 int
490 codec_encode_video (CodecContext *ctx, uint8_t *out_buf,
491                     int out_size, uint8_t *in_buf,
492                     int in_size, int64_t in_timestamp, CodecDevice *dev)
493 {
494   int fd, len = 0;
495   int ret, size;
496   uint8_t *mmapbuf = NULL;
497   uint32_t mem_offset = 0, meta_offset = 0;
498
499   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
500
501   fd = dev->fd;
502   if (fd < 0) {
503     GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
504     return -1;
505   }
506
507   mmapbuf = dev->buf;
508   if (!mmapbuf) {
509     GST_ERROR ("failed to get mmaped memory address.\n");
510     return -1;
511   }
512
513   if (in_size < SMALL_BUFFER) {
514     CODEC_LOG (DEBUG, "use small size of buffer\n");
515
516     ret = ioctl (fd, CODEC_CMD_SECURE_SMALL_BUFFER, &mem_offset);
517     if (ret < 0) {
518       CODEC_LOG (ERR, "failed to small size of buffer.\n");
519       return -1;
520     }
521   } else if (in_size < MEDIUM_BUFFER) {
522     CODEC_LOG (DEBUG, "use medium size of buffer\n");
523
524     ret = ioctl (fd, CODEC_CMD_SECURE_MEDIUM_BUFFER, &mem_offset);
525     if (ret < 0) {
526       CODEC_LOG (ERR, "failed to small size of buffer.\n");
527       return -1;
528     }
529   } else {
530     CODEC_LOG (DEBUG, "use large size of buffer\n");
531     ret = ioctl (fd, CODEC_CMD_SECURE_LARGE_BUFFER, &mem_offset);
532     if (ret < 0) {
533       CODEC_LOG (ERR, "failed to large size of buffer.\n");
534       return -1;
535     }
536   }
537   CODEC_LOG (DEBUG, "encode_video. mem_offset = 0x%x\n", mem_offset);
538
539   meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
540   CODEC_LOG (DEBUG, "encode_video. meta_offset = 0x%x\n", meta_offset);
541
542   size = 8;
543   meta_offset += size;
544   _codec_encode_video_meta_to (in_size, in_timestamp, mmapbuf + meta_offset);
545   _codec_encode_video_inbuf (in_buf, in_size, mmapbuf + mem_offset);
546
547   dev->mem_info.offset = mem_offset;
548   _codec_write_to_qemu (ctx->index, CODEC_ENCODE_VIDEO, mem_offset, fd);
549
550 #ifndef DIRECT_BUFFER
551   ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_SMALL_BUFFER, &mem_offset);
552   if (ret < 0) {
553     return -1;
554   }
555   CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", mem_offset);
556
557   memcpy (&len, mmapbuf + meta_offset, sizeof(len));
558   CODEC_LOG (DEBUG, "encode_video. outbuf size: %d\n", len);
559   if (len > 0) {
560     memcpy (out_buf, mmapbuf + mem_offset, len);
561     out_buf = mmapbuf + mem_offset;
562   }
563
564   dev->mem_info.offset = mem_offset;
565 #if 0
566   len =
567     _codec_encode_video_outbuf (out_buf, mmapbuf + mem_offset);
568 //  memset(mmapbuf + mem_offset, 0x00, sizeof(len));
569 #endif
570
571 #if 1
572   ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
573   if (ret < 0) {
574     CODEC_LOG (ERR, "failed release used memory\n");
575   }
576 #endif
577 #else
578   dev->mem_info.offset = (uint32_t)pict - (uint32_t)mmapbuf;
579   CODEC_LOG (DEBUG, "outbuf: %p , device_mem: %p\n",  pict, mmapbuf);
580   CODEC_LOG (DEBUG, "encoded video. mem_offset = 0x%x\n",  dev->mem_info.offset);
581
582   ret = ioctl (fd, CODEC_CMD_USE_DEVICE_MEM, &(dev->mem_info.offset));
583   if (ret < 0) {
584     // FIXME:
585   }
586 #endif
587   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
588
589   return len;
590 }
591
592 int
593 codec_encode_audio (CodecContext *ctx, uint8_t *out_buf,
594                     int max_size, uint8_t *in_buf,
595                     int in_size, CodecDevice *dev)
596 {
597   int fd, len = 0;
598   int ret, size;
599   void *mmapbuf = NULL;
600   uint32_t mem_offset = 0, meta_offset = 0;
601
602   CODEC_LOG (DEBUG, "enter: %s\n", __func__);
603
604   fd = dev->fd;
605   if (fd < 0) {
606     GST_ERROR ("failed to get %s fd.\n", CODEC_DEV);
607     return -1;
608   }
609
610   mmapbuf = dev->buf;
611   if (!mmapbuf) {
612     GST_ERROR ("failed to get mmaped memory address.\n");
613     return -1;
614   }
615
616   ret = ioctl (fd, CODEC_CMD_SECURE_SMALL_BUFFER, &mem_offset);
617   if (ret < 0) {
618     return -1;
619   }
620
621   CODEC_LOG (DEBUG, "write, encode_audio. mem_offset = 0x%x\n", mem_offset);
622
623   meta_offset = (ctx->index - 1) * CODEC_META_DATA_SIZE;
624   CODEC_LOG (DEBUG, "encode_audio. meta mem_offset = 0x%x\n", meta_offset);
625
626   size = _codec_header (CODEC_ENCODE_AUDIO, mem_offset,
627                             mmapbuf + meta_offset);
628   _codec_encode_audio_meta_to (max_size, in_size, mmapbuf + meta_offset + size);
629   _codec_encode_audio_inbuf (in_buf, in_size, mmapbuf + mem_offset);
630
631   dev->mem_info.offset = mem_offset;
632   _codec_write_to_qemu (ctx->index, CODEC_ENCODE_AUDIO, mem_offset, fd);
633
634   ret = ioctl (fd, CODEC_CMD_GET_DATA_FROM_SMALL_BUFFER, &mem_offset);
635   if (ret < 0) {
636     return -1;
637   }
638
639   CODEC_LOG (DEBUG, "read, encode_video. mem_offset = 0x%x\n", mem_offset);
640
641   len = _codec_encode_audio_outbuf (out_buf, mmapbuf + mem_offset);
642   memset(mmapbuf + mem_offset, 0x00, sizeof(len));
643
644   ret = ioctl(fd, CODEC_CMD_RELEASE_BUFFER, &mem_offset);
645   if (ret < 0) {
646     return -1;
647   }
648
649   CODEC_LOG (DEBUG, "leave: %s\n", __func__);
650
651   return len;
652 }