implemented decoding audio part, but needs to improve.
[platform/adaptation/emulator/gst-plugins-emulator.git] / src / gstemulenc.c
1 /*
2  * Emulator
3  *
4  * Copyright (C) 2011 - 2012 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
27 /* First, include the header file for the plugin, to bring in the
28  * object definition and other useful things.
29  */
30
31 /*
32  *
33  * Contributors:
34  * - S-Core Co., Ltd
35  *
36  */
37
38 #include <stdint.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <fcntl.h>
44 #include <sys/mman.h>
45 #include <gst/gst.h>
46 #include "gstemulcommon.h"
47
48 typedef struct _GstEmulEnc
49 {
50   GstElement element;
51
52   GstPad *srcpad;
53   GstPad *sinkpad;
54
55   union {
56     struct {
57       gint width;
58       gint height;
59       gint framerate_num;
60       gint framerate_den;
61       gint pix_fmt;   
62     } video;
63     struct {
64       gint channels;
65       gint samplerate;
66       gint depth;
67     } audio;
68   } format;
69
70   guint extradata_size;
71   guint8 *extradata;
72
73   CodecDev codecbuf;
74 } GstEmulEnc;
75
76 typedef struct _GstEmulEncClass
77 {
78   GstElementClass parent_class;
79
80   GstPadTemplate *sinktempl;
81   GstPadTemplate *srctempl;
82 } GstEmulEncClass;
83
84 static GstElementClass *parent_class = NULL;
85
86 static void gst_emulenc_base_init (GstEmulEncClass *klass);
87 static void gst_emulenc_class_init (GstEmulEncClass *klass);
88 static void gst_emulenc_init (GstEmulEnc *emulenc);
89 static void gst_emulenc_finalize (GObject *object);
90
91 static gboolean gst_emulenc_setcaps (GstPad *pad, GstCaps *caps);
92 static gboolean gst_emulenc_sink_event (GstPad *pad, GstEvent *event);
93 static GstFlowReturn gst_emulenc_chain (GstPad *pad, GstBuffer *buffer);
94
95 static gboolean gst_emulenc_src_event (GstPad *pad, GstEvent *event);
96 static GstStateChangeReturn gst_emulenc_change_state (GstElement *element, GstStateChange transition);
97
98 int gst_emul_codec_init (GstEmulEnc *emulenc);
99 void gst_emul_codec_deinit (GstEmulEnc *emulenc);
100 int gst_emul_codec_encode_video (GstEmulEnc *emulenc, guint8 *in_buf, guint in_size,
101         GstBuffer **out_buf, GstClockTime in_timestamp);
102
103 int gst_emul_codec_dev_open (GstEmulEnc *emulenc);
104
105
106 #define GST_EMULENC_PARAMS_QDATA g_quark_from_static_string("emulenc-params"); 
107
108 /*
109  * Implementation
110  */
111     static void
112 gst_emulenc_base_init (GstEmulEncClass *klass)
113 {
114     GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
115     GstCaps *sinkcaps, *srccaps;
116     GstPadTemplate *sinktempl, *srctempl;
117     const char *mimetype = "video/x-h264";
118     CodecInfo *info;
119     gchar *longname, *classification;
120
121     info =
122         (CodecInfo *)g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
123                 GST_EMULENC_PARAMS_QDATA);
124
125     longname = g_strdup_printf ("%s Encoder", info->codec_longname);
126
127     classification = g_strdup_printf ("Codec/Encoder/%s",
128             (info->media_type == AVMEDIA_TYPE_VIDEO) ? "Video" : "Audio");
129
130     gst_element_class_set_details_simple (element_class,
131             longname,
132             classification,
133             "accelerated codec for Tizen Emulator",
134             "Kitae Kim <kt920.kim@samsung.com>");
135
136     g_free (longname);
137     g_free (classification);
138
139     sinkcaps = gst_caps_new_simple (mimetype,
140             "width", GST_TYPE_INT_RANGE, 16, 4096,
141             "height", GST_TYPE_INT_RANGE, 16, 4096,
142             "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
143     if (!sinkcaps) {
144         sinkcaps = gst_caps_from_string ("unknown/unknown");
145     }
146
147     // if type is video
148     srccaps = gst_caps_from_string ("video/x-raw-rgb; video/x-raw-yuv");
149     // otherwise
150     // srcaps = gst_emul_codectype_to_audio_caps ();
151
152     if (!srccaps) {
153         srccaps = gst_caps_from_string ("unknown/unknown");
154     }
155
156     sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK,
157             GST_PAD_ALWAYS, sinkcaps);
158     srctempl = gst_pad_template_new ("src", GST_PAD_SRC,
159             GST_PAD_ALWAYS, srccaps);
160
161     gst_element_class_add_pad_template (element_class, srctempl);
162     gst_element_class_add_pad_template (element_class, sinktempl);
163
164     klass->sinktempl = sinktempl;
165     klass->srctempl = srctempl;
166 }
167
168     static void
169 gst_emulenc_class_init (GstEmulEncClass *klass)
170 {
171     GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
172     GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
173
174     parent_class = g_type_class_peek_parent (klass);
175
176 #if 0
177     gobject_class->set_property = gst_emulenc_set_property
178         gobject_class->get_property = gst_emulenc_get_property
179 #endif
180
181         gobject_class->finalize = gst_emulenc_finalize;
182
183     gstelement_class->change_state = gst_emulenc_change_state; 
184 }
185
186     static void
187 gst_emulenc_init (GstEmulEnc *emulenc)
188 {
189     GstEmulEncClass *oclass;
190
191     oclass = (GstEmulEncClass*) (G_OBJECT_GET_CLASS(emulenc));
192
193     emulenc->sinkpad = gst_pad_new_from_template (oclass->sinktempl, "sink");
194     gst_pad_set_setcaps_function (emulenc->sinkpad,
195             GST_DEBUG_FUNCPTR(gst_emulenc_setcaps));
196     gst_pad_set_event_function (emulenc->sinkpad,
197             GST_DEBUG_FUNCPTR(gst_emulenc_sink_event));
198     gst_pad_set_chain_function (emulenc->sinkpad,
199             GST_DEBUG_FUNCPTR(gst_emulenc_chain));
200     gst_element_add_pad (GST_ELEMENT(emulenc), emulenc->sinkpad);
201
202     emulenc->srcpad = gst_pad_new_from_template (oclass->srctempl, "src") ;
203     gst_pad_use_fixed_caps (emulenc->srcpad);
204     gst_pad_set_event_function (emulenc->srcpad,
205             GST_DEBUG_FUNCPTR(gst_emulenc_src_event));
206     gst_element_add_pad (GST_ELEMENT(emulenc), emulenc->srcpad);
207 }
208
209     static void
210 gst_emulenc_finalize (GObject *object)
211 {
212     // Deinit Decoder
213     GstEmulEnc *emulenc = (GstEmulEnc *) object;
214
215     G_OBJECT_CLASS (parent_class)->finalize (object);
216 }
217
218     static gboolean
219 gst_emulenc_src_event (GstPad *pad, GstEvent *event)
220 {
221     return 0;
222 }
223
224     static void
225 gst_emulenc_get_caps (GstEmulEnc *emulenc, GstCaps *caps)
226 {
227     GstStructure *structure;
228
229     int width, height, bits_per_coded_sample;
230     const GValue *fps;
231     //    const GValue *par;
232     //    guint extradata_size;
233     //    guint8 *extradata;
234
235     /* FFmpeg Specific Values */
236     const GstBuffer *buf;
237     const GValue *value;
238
239     structure = gst_caps_get_structure (caps, 0);
240
241     value = gst_structure_get_value (structure, "codec_data");
242     if (value) {
243         buf = GST_BUFFER_CAST (gst_value_get_mini_object (value));
244         emulenc->extradata_size = GST_BUFFER_SIZE (buf);
245         emulenc->extradata = GST_BUFFER_DATA (buf);
246     } else {
247         CODEC_LOG (2, "no codec data\n");
248         emulenc->extradata_size = 0;
249         emulenc->extradata = NULL;
250     }
251
252 #if 1 /* video type */
253     /* Common Properites, width, height and etc. */
254     gst_structure_get_int (structure, "width", &width);
255     gst_structure_get_int (structure, "height", &height);
256     gst_structure_get_int (structure, "bpp", &bits_per_coded_sample);
257
258     emulenc->format.video.width = width;
259     emulenc->format.video.height = height;
260
261     fps = gst_structure_get_value (structure, "framerate");
262     if (fps) {
263         emulenc->format.video.framerate_den = gst_value_get_fraction_numerator (fps);
264         emulenc->format.video.framerate_num = gst_value_get_fraction_denominator (fps);
265     }
266
267 #if 0
268     par = gst_structure_get_value (structure, "pixel-aspect-ratio");
269     if (par) {
270         sample_aspect_ratio.num = gst_structure_get_fraction_numerator (par);
271         sample_aspect_ratio.den = gst_structure_get_fraction_denominator (par);
272     }
273 #endif
274 #endif
275
276 #if 0 /* audio type */
277     gst_structure_get_int (structure, "channels", &channels);
278     gst_structure_get_int (structure, "rate", &sample_rate);
279     gst_structure_get_int (structure, "block_align", &block_align);
280     gst_structure_get_int (structure, "bitrate", &bit_rate);
281
282     emulenc->format.audio.channels = channels;
283     emulenc->format.audio.samplerate = sample_rate;
284 #endif
285
286 }
287
288     static gboolean
289 gst_emulenc_setcaps (GstPad *pad, GstCaps *caps)
290 {
291     GstEmulEnc *emulenc;
292     GstEmulEncClass *oclass;
293     gboolean ret = TRUE;
294
295     emulenc = (GstEmulEnc *) (gst_pad_get_parent (pad));
296     oclass = (GstEmulEncClass *) (G_OBJECT_GET_CLASS (emulenc));
297
298     GST_OBJECT_LOCK (emulenc);
299
300     gst_emulenc_get_caps (emulenc, caps);
301
302 #if 0
303     if (!emulenc->format.video.framerate_den ||
304             !emulenc->format.video.framerate_num) {
305         emulenc->format.video.framerate_num = 1; 
306         emulenc->format.video.framerate_den = 25;
307     }
308 #endif
309
310     if (gst_emul_codec_dev_open (emulenc) < 0) {
311         CODEC_LOG(1, "failed to access %s or mmap operation\n", CODEC_DEV);
312         GST_OBJECT_UNLOCK (emulenc);
313         gst_object_unref (emulenc);
314         return FALSE;
315     }
316
317     if (gst_emul_codec_init (emulenc) < 0) {
318         CODEC_LOG(1, "cannot initialize codec\n");
319         GST_OBJECT_UNLOCK (emulenc);
320         gst_object_unref (emulenc);
321         return FALSE;
322     }
323
324 #if 0 /* open a parser */
325     gst_emul_codec_parser (emulenc);
326 #endif
327
328     GST_OBJECT_UNLOCK (emulenc);
329
330     gst_object_unref (emulenc);
331
332     return ret;
333 }
334
335     static gboolean
336 gst_emulenc_sink_event (GstPad *pad, GstEvent *event)
337 {
338     GstEmulEnc *emulenc;
339     gboolean ret = FALSE;
340
341     emulenc = (GstEmulEnc *) gst_pad_get_parent (pad);
342 #if 0
343     switch (GST_TYPE_EVENT (event)) {
344         case GST_EVENT_EOS:
345             CODEC_LOG(2, "received GST_EVENT_EOS\n");
346             break;
347         case GST_EVENT_NEWSEGMENT:
348             CODEC_LOG(2, "received GST_EVENT_NEWSEGMENT\n");
349             break;
350     }
351     ret = gst_pad_push_event (emulenc->srcpad, event);
352 #endif
353
354     gst_object_unref (emulenc);
355
356     return ret;
357 }
358
359     static GstFlowReturn
360 gst_emulenc_chain (GstPad *pad, GstBuffer *buffer)
361 {
362     GstEmulEnc *emulenc;
363     guint8 *in_buf = NULL;
364     GstBuffer *out_buf;
365     gint in_size = 0;
366     GstClockTime in_timestamp;
367     GstFlowReturn ret = GST_FLOW_OK;
368
369     emulenc = (GstEmulEnc *) (GST_PAD_PARENT (pad));
370
371     in_size = GST_BUFFER_SIZE (buffer);
372     in_buf = GST_BUFFER_DATA (buffer);
373     in_timestamp = GST_BUFFER_TIMESTAMP (buffer);
374
375     gst_emul_codec_encode_video (emulenc, in_buf, in_size, &out_buf, in_timestamp);
376
377     CODEC_LOG(1, "out_buf:%p, ret:%d\n", out_buf, ret);
378
379     ret = gst_pad_push (emulenc->srcpad, out_buf);
380
381     //  g_free (out_buf);
382
383     gst_buffer_unref (buffer);
384
385     return ret;
386 }
387
388     static GstStateChangeReturn
389 gst_emulenc_change_state (GstElement *element, GstStateChange transition)
390 {
391     GstEmulEnc *emulenc = (GstEmulEnc*)element;
392     GstStateChangeReturn ret;
393
394     ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
395
396     switch (transition) {
397         case GST_STATE_CHANGE_PAUSED_TO_READY:
398             gst_emul_codec_deinit (emulenc);
399         default:
400             break;
401     }
402
403     return ret;
404 }
405
406     gboolean
407 gst_emulenc_register (GstPlugin *plugin)
408 {
409     GTypeInfo typeinfo = {
410         sizeof (GstEmulEncClass),
411         (GBaseInitFunc) gst_emulenc_base_init,
412         NULL,
413         (GClassInitFunc) gst_emulenc_class_init,
414         NULL,
415         NULL,
416         sizeof (GstEmulEnc),
417         0,
418         (GInstanceInitFunc) gst_emulenc_init,
419     };
420
421     GType type;
422     gchar *type_name;
423     gint rank = GST_RANK_PRIMARY;
424
425     /* register element */
426     {
427         int codec_fd, codec_cnt = 0;
428         int func_type = CODEC_QUERY;
429         int index = 0, size = 0;
430         void *buf;
431         CodecInfo *codec_info;
432
433         codec_fd = open(CODEC_DEV, O_RDWR);
434         if (codec_fd < 0) {
435             perror("failed to open codec device");
436             return FALSE;
437         }
438
439         printf("[codec] fd:%d\n", codec_fd);
440         buf = mmap (NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, codec_fd, 0);
441         if (!buf) {
442             perror("failed to mmap");
443         }
444
445         printf("[codec] mmap:%p\n", buf);
446
447         write (codec_fd, &func_type, sizeof(int));
448         memcpy (&codec_cnt, buf, sizeof(int));
449         size = sizeof(uint32_t);
450
451         codec_info = g_malloc0 (codec_cnt * sizeof(CodecInfo));
452         for (; index < codec_cnt; index++) {
453             memcpy(&codec_info[index].media_type, (uint8_t *)buf + size, sizeof(uint16_t));
454             size += sizeof(uint16_t);
455             memcpy(&codec_info[index].codec_type, (uint8_t *)buf + size, sizeof(uint16_t));
456             size += sizeof(uint16_t);
457             memcpy(&codec_info[index].codec_name, (uint8_t *)buf + size, 32);
458             size += 32;
459             memcpy(&codec_info[index].codec_longname, (uint8_t *)buf + size, 64);
460             size += 64;
461         }
462
463         for (index = 0; index < codec_cnt; index++) {
464             if (codec_info[index].codec_type != 0) {
465                 continue;
466             }
467
468             type_name = g_strdup_printf ("emulenc_%s", codec_info[index].codec_name);
469             type = g_type_from_name (type_name);
470             if (!type) {
471                 type = g_type_register_static (GST_TYPE_ELEMENT, type_name, &typeinfo, 0);
472                 g_type_set_qdata (type, GST_EMULDEC_PARAMS_QDATA, (gpointer) &codec_info[index]);
473             }
474
475             if (!gst_element_register (plugin, type_name, rank, type)) {
476                 g_free (type_name);
477                 return FALSE;
478             }
479             g_free (type_name);
480         }
481
482         printf("[codec] close\n");
483         munmap (buf, 4096);
484         close (codec_fd);
485     }
486
487     return TRUE;
488 }
489
490 void *gst_emul_codec_query (GstEmulEnc *emulenc)
491 {
492     int fd, codec_cnt;
493     int size = 0, i;
494     void *mmapbuf;
495     int func_type = CODEC_QUERY;
496     CodecInfo *codec_info;
497
498     CODEC_LOG(1, "enter: %s\n", __func__);
499
500     fd = emulenc->codecbuf.fd;
501     mmapbuf = emulenc->codecbuf.mmapbuf;
502     if (fd < 0) {
503         CODEC_LOG(1, "failed to get %s fd\n", CODEC_DEV);
504         return NULL;
505     }
506
507     if (!mmapbuf) {
508         CODEC_LOG(1, "failed to get mmaped memory address\n");
509         return NULL;
510     }
511
512     write (fd, &func_type, sizeof(func_type));
513     memcpy (&codec_cnt, mmapbuf, sizeof(uint32_t));
514     size += sizeof(uint32_t);
515
516     codec_info = g_malloc0 (codec_cnt * sizeof(CodecInfo));
517
518     for (i = 0; i < codec_cnt; i++) {
519         memcpy (&codec_info[i].mediatype, (uint8_t *)mmapbuf + size, sizeof(uint16_t));
520         size += sizeof(uint16_t);
521         memcpy (&codec_info[i].codectype, (uint8_t *)mmapbuf + size, sizeof(uint16_t));
522         size += sizeof(uint16_t);
523         memcpy (codec_info[i].name, (uint8_t *)mmapbuf + size, 32);
524         size += 32;
525         memcpy (codec_info[i].long_name, (uint8_t *)mmapbuf + size, 64);
526         size += 64;
527     }
528
529     CODEC_LOG(1, "leave: %s\n", __func__);
530
531     return codec_info;
532 }
533
534 int gst_emul_codec_init (GstEmulEnc *emulenc)
535 {
536     int fd;
537     int size = 0, ret;
538     guint extradata_size = 0;
539     guint8 *extradata = NULL;
540     void *mmapbuf;
541     int func_type = CODEC_INIT;
542
543     CODEC_LOG(1, "enter: %s\n", __func__);
544
545     fd = emulenc->codecbuf.fd;
546     mmapbuf = emulenc->codecbuf.mmapbuf;
547     if (fd < 0) {
548         CODEC_LOG(1, "failed to get %s fd\n", CODEC_DEV);
549         return -1;
550     }
551
552     if (!mmapbuf) {
553         CODEC_LOG(1, "failed to get mmaped memory address\n");
554         return -1;
555     }
556
557     extradata_size = emulenc->extradata_size;
558     extradata = emulenc->extradata;
559
560     /* copy basic info to initialize codec on the host side.
561      * e.g. width, height, FPS ant etc. */
562     memcpy ((uint8_t *)mmapbuf, &emulenc->format.video, sizeof(emulenc->format.video));
563     size += sizeof(emulenc->format.video);
564     if (extradata) {
565         memcpy ((uint8_t *)mmapbuf + size, &extradata_size, sizeof(extradata_size));
566         size += sizeof(extradata_size);
567         memcpy ((uint8_t *)mmapbuf + size, extradata, extradata_size);
568     }
569
570     ret = write (fd, &func_type, sizeof(func_type));
571
572     CODEC_LOG(1, "leave: %s\n", __func__);
573
574     return ret; 
575 }
576
577 void gst_emul_codec_dev_close (GstEmulEnc *emulenc)
578 {
579     int fd, ret = 0;
580     int size = 0;
581     void *mmapbuf;
582
583     CODEC_LOG(1, "enter: %s\n", __func__);
584
585     fd = emulenc->codecbuf.fd;
586     mmapbuf = emulenc->codecbuf.mmapbuf;
587
588     if (fd < 0) {
589         CODEC_LOG(1, "failed to get %s fd\n", CODEC_DEV);
590         return;
591     }
592
593     if (!mmapbuf) {
594         CODEC_LOG(1, "failed to get mmaped memory address\n");
595         return;
596     }
597
598     CODEC_LOG(2, "release mmaped memory region of %s\n", CODEC_DEV);
599     ret = munmap(mmapbuf, 12 * 4096);
600     if (ret != 0) {
601         CODEC_LOG(1, "failed to release mmaped memory region of %s\n", CODEC_DEV);
602     }
603
604     CODEC_LOG(2, "close %s fd\n", CODEC_DEV);
605     ret = close (fd);
606     if (ret != 0) {
607         CODEC_LOG(1, "failed to close %s\n", CODEC_DEV);
608     }
609
610     CODEC_LOG(1, "leave: %s\n", __func__);
611 }
612
613 void gst_emul_codec_deinit (GstEmulEnc *emulenc)
614 {
615     int fd, ret;
616     int func_type = CODEC_DEINIT;
617     void *mmapbuf;
618
619     CODEC_LOG(1, "enter: %s\n", __func__);
620
621     fd = emulenc->codecbuf.fd;
622     mmapbuf = emulenc->codecbuf.mmapbuf;
623
624     if (fd < 0) {
625         CODEC_LOG(1, "failed to get %s fd\n", CODEC_DEV);
626         return;
627     }
628
629     if (!mmapbuf) {
630         CODEC_LOG(1, "failed to get mmaped memory address\n");
631         return;
632     }
633
634     ret = write (fd, &func_type, sizeof(func_type));
635
636     /* close device fd and release mapped memory region */
637     gst_emul_codec_dev_close (emulenc);
638
639     CODEC_LOG(1, "leave: %s\n", __func__);
640 }
641
642 int gst_emul_codec_encode_video (GstEmulEnc *emulenc, guint8 *in_buf, guint in_size,
643         GstBuffer **out_buf, GstClockTime in_timestamp)
644 {
645     int fd, size = 0, ret;
646     guint out_size;
647     int func_type = CODEC_DECODE_VIDEO;
648     void *mmapbuf;
649     *out_buf = NULL;
650
651     CODEC_LOG(1, "enter: %s\n", __func__);
652
653     fd = emulenc->codecbuf.fd;
654     mmapbuf = emulenc->codecbuf.mmapbuf;
655
656     if (fd < 0) {
657         CODEC_LOG(1, "failed to get %s fd\n", CODEC_DEV);
658         return -1;
659     }
660
661     if (!mmapbuf) {
662         CODEC_LOG(1, "failed to get mmaped memory address\n");
663         return -1;
664     }
665
666     memcpy ((uint8_t *)mmapbuf + size, &in_size, sizeof(guint));
667     size += sizeof(guint);
668     memcpy ((uint8_t *)mmapbuf + size, &in_timestamp, sizeof(GstClockTime));
669     size += sizeof(GstClockTime);
670     memcpy ((uint8_t *)mmapbuf + size, in_buf, in_size);
671
672     /* provide raw image for decoding to qemu */
673     ret = write (fd, &func_type, sizeof(func_type));
674
675     size = 0;
676     memcpy (&out_size, (uint8_t *)mmapbuf + size, sizeof(uint));
677     size += sizeof(guint);
678
679     ret = gst_pad_alloc_buffer_and_set_caps (emulenc->srcpad,
680             GST_BUFFER_OFFSET_NONE, out_size,
681             GST_PAD_CAPS (emulenc->srcpad), out_buf);
682
683     gst_buffer_set_caps (*out_buf, GST_PAD_CAPS (emulenc->srcpad));
684
685     if (GST_BUFFER_DATA(*out_buf)) {
686         memcpy (GST_BUFFER_DATA(*out_buf), (uint8_t *)mmapbuf + size, out_size);
687     } else {
688         CODEC_LOG(1, "failed to allocate output buffer\n");
689     }
690
691     CODEC_LOG(1, "leave: %s\n", __func__);
692
693     return ret;
694 }
695
696 #if 0
697 void emulenc_encode_audio ()
698 {
699     int fd, size = 0, ret;
700     guint out_size;
701     int func_type = CODEC_DECODE_AUDIO;
702     void *mmapbuf;
703     *out_buf = NULL;
704
705     CODEC_LOG(1, "enter: %s\n", __func__);
706
707     fd = emulenc->codecbuf.fd;
708     mmapbuf = emulenc->codecbuf.mmapbuf;
709
710     if (fd < 0) {
711         CODEC_LOG(1, "failed to get %s fd\n", CODEC_DEV);
712         return -1;
713     }
714
715     if (!mmapbuf) {
716         CODEC_LOG(1, "failed to get mmaped memory address\n");
717         return -1;
718     }
719
720     memcpy ((uint8_t *)mmapbuf + size, &in_size, sizeof(guint));
721     size += sizeof(guint);
722     memcpy ((uint8_t *)mmapbuf + size, &in_timestamp, sizeof(GstClockTime));
723     size += sizeof(GstClockTime);
724     memcpy ((uint8_t *)mmapbuf + size, in_buf, in_size);
725
726     /* provide raw image for decoding to qemu */
727     ret = write (fd, &func_type, sizeof(func_type));
728
729     size = 0;
730     memcpy (&out_size, (uint8_t *)mmapbuf + size, sizeof(uint));
731     size += sizeof(guint);
732
733     *out_buf = gst_buffer_new();
734     GST_BUFFER_DATA (out_buf) = GST_BUFFER_MALLOCDATA (out_buf) = av_malloc (out_size);
735     GST_BUFFER_SIZE (out_buf) = out_size;
736     //  GST_BUFFER_FREE_FUNC (out_buf) = av_free;
737     if (GST_PAD_CAPS(emulenc->srcpad)) {
738         gst_buffer_set_caps (*out_buf, GST_PAD_CAPS (emulenc->srcpad));
739     }
740
741     if (GST_BUFFER_DATA(*out_buf)) {
742         memcpy (GST_BUFFER_DATA(*out_buf), (uint8_t *)mmapbuf + size, out_size);
743     } else {
744         CODEC_LOG(1, "failed to allocate output buffer\n");
745     }
746     CODEC_LOG(1, "leave: %s\n", __func__);
747
748     return ret;
749 }
750 #endif