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