1/*
2 INTEL CONFIDENTIAL
3 Copyright 2009 Intel Corporation All Rights Reserved.
4 The source code contained or described herein and all documents related to the source code ("Material") are owned by Intel Corporation or its suppliers or licensors. Title to the Material remains with Intel Corporation or its suppliers and licensors. The Material contains trade secrets and proprietary and confidential information of Intel or its suppliers and licensors. The Material is protected by worldwide copyright and trade secret laws and treaty provisions. No part of the Material may be used, copied, reproduced, modified, published, uploaded, posted, transmitted, distributed, or disclosed in any way without Intel’s prior express written permission.
5
6 No license under any patent, copyright, trade secret or other intellectual property right is granted to or conferred upon you by disclosure or delivery of the Materials, either expressly, by implication, inducement, estoppel or otherwise. Any license under such intellectual property rights must be express and approved by Intel in writing.
7 */
8#include <glib.h>
9#include <string.h>
10#include <stdlib.h>
11
12#include "mixvideolog.h"
13
14#include "mixvideoformatenc_mpeg4.h"
15#include "mixvideoconfigparamsenc_mpeg4.h"
16
17#define MDEBUG
18#undef SHOW_SRC
19
20#ifdef SHOW_SRC
21Window win = 0;
22#endif /* SHOW_SRC */
23
24
25/* The parent class. The pointer will be saved
26 * in this class's initialization. The pointer
27 * can be used for chaining method call if needed.
28 */
29static MixVideoFormatEncClass *parent_class = NULL;
30
31static void mix_videoformatenc_mpeg4_finalize(GObject * obj);
32
33/*
34 * Please note that the type we pass to G_DEFINE_TYPE is MIX_TYPE_VIDEOFORMATENC
35 */
36G_DEFINE_TYPE (MixVideoFormatEnc_MPEG4, mix_videoformatenc_mpeg4, MIX_TYPE_VIDEOFORMATENC);
37
38static void mix_videoformatenc_mpeg4_init(MixVideoFormatEnc_MPEG4 * self) {
39    MixVideoFormatEnc *parent = MIX_VIDEOFORMATENC(self);
40
41    /* TODO: public member initialization */
42
43    /* TODO: private member initialization */
44    self->encoded_frames = 0;
45    self->pic_skipped = FALSE;
46    self->is_intra = TRUE;
47    self->cur_fame = NULL;
48    self->ref_fame = NULL;
49    self->rec_fame = NULL;
50
51    self->ci_shared_surfaces = NULL;
52    self->surfaces= NULL;
53    self->surface_num = 0;
54
55    parent->initialized = FALSE;
56}
57
58static void mix_videoformatenc_mpeg4_class_init(
59        MixVideoFormatEnc_MPEG4Class * klass) {
60
61    /* root class */
62    GObjectClass *gobject_class = (GObjectClass *) klass;
63
64    /* direct parent class */
65    MixVideoFormatEncClass *video_formatenc_class =
66        MIX_VIDEOFORMATENC_CLASS(klass);
67
68    /* parent class for later use */
69    parent_class = g_type_class_peek_parent(klass);
70
71    /* setup finializer */
72    gobject_class->finalize = mix_videoformatenc_mpeg4_finalize;
73
74    /* setup vmethods with base implementation */
75    /* TODO: decide if we need to override the parent's methods */
76    video_formatenc_class->getcaps = mix_videofmtenc_mpeg4_getcaps;
77    video_formatenc_class->initialize = mix_videofmtenc_mpeg4_initialize;
78    video_formatenc_class->encode = mix_videofmtenc_mpeg4_encode;
79    video_formatenc_class->flush = mix_videofmtenc_mpeg4_flush;
80    video_formatenc_class->eos = mix_videofmtenc_mpeg4_eos;
81    video_formatenc_class->deinitialize = mix_videofmtenc_mpeg4_deinitialize;
82    video_formatenc_class->getmaxencodedbufsize = mix_videofmtenc_mpeg4_get_max_encoded_buf_size;
83}
84
85MixVideoFormatEnc_MPEG4 *
86mix_videoformatenc_mpeg4_new(void) {
87    MixVideoFormatEnc_MPEG4 *ret =
88        g_object_new(MIX_TYPE_VIDEOFORMATENC_MPEG4, NULL);
89
90    return ret;
91}
92
93void mix_videoformatenc_mpeg4_finalize(GObject * obj) {
94    /* clean up here. */
95
96    /*MixVideoFormatEnc_MPEG4 *mix = MIX_VIDEOFORMATENC_MPEG4(obj); */
97    GObjectClass *root_class = (GObjectClass *) parent_class;
98
99    LOG_V( "\n");
100
101    /* Chain up parent */
102    if (root_class->finalize) {
103        root_class->finalize(obj);
104    }
105}
106
107MixVideoFormatEnc_MPEG4 *
108mix_videoformatenc_mpeg4_ref(MixVideoFormatEnc_MPEG4 * mix) {
109    return (MixVideoFormatEnc_MPEG4 *) g_object_ref(G_OBJECT(mix));
110}
111
112/*MPEG-4:2 vmethods implementation */
113MIX_RESULT mix_videofmtenc_mpeg4_getcaps(MixVideoFormatEnc *mix, GString *msg) {
114
115    /* TODO: add codes for MPEG-4:2 */
116
117    /* TODO: decide if we need to chainup parent method.
118     * if we do, the following is the code:
119     */
120
121    LOG_V( "mix_videofmtenc_mpeg4_getcaps\n");
122
123    if (mix == NULL) {
124        LOG_E( "mix == NULL\n");
125        return MIX_RESULT_NULL_PTR;
126    }
127
128
129    if (parent_class->getcaps) {
130        return parent_class->getcaps(mix, msg);
131    }
132    return MIX_RESULT_SUCCESS;
133}
134
135MIX_RESULT mix_videofmtenc_mpeg4_initialize(MixVideoFormatEnc *mix,
136        MixVideoConfigParamsEnc * config_params_enc,
137        MixFrameManager * frame_mgr,
138        MixBufferPool * input_buf_pool,
139        MixSurfacePool ** surface_pool,
140        VADisplay va_display ) {
141
142    MIX_RESULT ret = MIX_RESULT_SUCCESS;
143    MixVideoFormatEnc *parent = NULL;
144    MixVideoConfigParamsEncMPEG4 * config_params_enc_mpeg4;
145
146    VAStatus va_status = VA_STATUS_SUCCESS;
147    VASurfaceID * surfaces;
148
149    gint va_max_num_profiles, va_max_num_entrypoints, va_max_num_attribs;
150    gint va_num_profiles,  va_num_entrypoints;
151
152    VAProfile *va_profiles = NULL;
153    VAEntrypoint *va_entrypoints = NULL;
154    VAConfigAttrib va_attrib[2];
155    guint index;
156
157
158    /*frame_mgr and input_buf_pool is reservered for future use*/
159
160    if (mix == NULL || config_params_enc == NULL || va_display == NULL) {
161        LOG_E(
162                "mix == NULL || config_params_enc == NULL || va_display == NULL\n");
163        return MIX_RESULT_NULL_PTR;
164    }
165
166    LOG_V( "begin\n");
167
168
169    //TODO additional parameter checking
170
171    /* Chainup parent method. */
172#if 1
173    if (parent_class->initialize) {
174        ret = parent_class->initialize(mix, config_params_enc,
175                frame_mgr, input_buf_pool, surface_pool,
176                va_display);
177    }
178
179    if (ret != MIX_RESULT_SUCCESS)
180    {
181        return ret;
182    }
183
184#endif //disable it currently
185
186    if (MIX_IS_VIDEOFORMATENC_MPEG4(mix))
187    {
188        parent = MIX_VIDEOFORMATENC(&(mix->parent));
189        MixVideoFormatEnc_MPEG4 *self = MIX_VIDEOFORMATENC_MPEG4(mix);
190
191        if (MIX_IS_VIDEOCONFIGPARAMSENC_MPEG4 (config_params_enc)) {
192            config_params_enc_mpeg4 =
193                MIX_VIDEOCONFIGPARAMSENC_MPEG4 (config_params_enc);
194        } else {
195            LOG_V(
196                    "mix_videofmtenc_mpeg4_initialize:  no mpeg4 config params found\n");
197            return MIX_RESULT_FAIL;
198        }
199
200        g_mutex_lock(parent->objectlock);
201
202        LOG_V(
203                "Start to get properities from MPEG-4:2 params\n");
204
205        /* get properties from MPEG4 params Object, which is special to MPEG4 format*/
206
207        ret = mix_videoconfigparamsenc_mpeg4_get_profile_level (config_params_enc_mpeg4,
208                &self->profile_and_level_indication);
209
210        if (ret != MIX_RESULT_SUCCESS) {
211            //TODO cleanup
212            LOG_E(
213                    "Failed to mix_videoconfigparamsenc_mpeg4_get_profile_level\n");
214            g_mutex_unlock(parent->objectlock);
215            return MIX_RESULT_FAIL;
216        }
217
218        ret = mix_videoconfigparamsenc_mpeg4_get_fixed_vti (config_params_enc_mpeg4,
219                &(self->fixed_vop_time_increment));
220
221        if (ret != MIX_RESULT_SUCCESS) {
222            //TODO cleanup
223            LOG_E(
224                    "Failed to mix_videoconfigparamsenc_mpeg4_get_fixed_vti\n");
225            g_mutex_unlock(parent->objectlock);
226            return MIX_RESULT_FAIL;
227        }
228
229        ret = mix_videoconfigparamsenc_mpeg4_get_dlk (config_params_enc_mpeg4,
230                &(self->disable_deblocking_filter_idc));
231
232        if (ret != MIX_RESULT_SUCCESS) {
233            //TODO cleanup
234            LOG_E(
235                    "Failed to config_params_enc_mpeg4\n");
236            g_mutex_unlock(parent->objectlock);
237            return MIX_RESULT_FAIL;
238        }
239
240
241        LOG_V(
242                "======MPEG4 Encode Object properities======:\n");
243
244        LOG_I( "self->profile_and_level_indication = %d\n",
245                self->profile_and_level_indication);
246        LOG_I( "self->fixed_vop_time_increment = %d\n\n",
247                self->fixed_vop_time_increment);
248
249        LOG_V(
250                "Get properities from params done\n");
251
252
253    	//display = XOpenDisplay(NULL);
254     	//va_display = vaGetDisplay (videoencobj->display);
255
256        parent->va_display = va_display;
257
258        LOG_V( "Get Display\n");
259        LOG_I( "Display = 0x%08x\n",
260                (guint)va_display);
261
262        //va_status = vaInitialize(va_display, &va_major_ver, &va_minor_ver);
263        //g_print ("vaInitialize va_status = %d\n", va_status);
264
265
266#if 0
267        /* query the vender information, can ignore*/
268        va_vendor = vaQueryVendorString (va_display);
269        LOG_I( "Vendor = %s\n",
270                va_vendor);
271#endif
272
273        /*get the max number for profiles/entrypoints/attribs*/
274        va_max_num_profiles = vaMaxNumProfiles(va_display);
275        LOG_I( "va_max_num_profiles = %d\n",
276                va_max_num_profiles);
277
278        va_max_num_entrypoints = vaMaxNumEntrypoints(va_display);
279        LOG_I( "va_max_num_entrypoints = %d\n",
280                va_max_num_entrypoints);
281
282        va_max_num_attribs = vaMaxNumConfigAttributes(va_display);
283        LOG_I( "va_max_num_attribs = %d\n",
284                va_max_num_attribs);
285
286        va_profiles = g_malloc(sizeof(VAProfile)*va_max_num_profiles);
287        va_entrypoints = g_malloc(sizeof(VAEntrypoint)*va_max_num_entrypoints);
288
289        if (va_profiles == NULL || va_entrypoints ==NULL)
290        {
291            LOG_E(
292                    "!va_profiles || !va_entrypoints\n");
293            g_mutex_unlock(parent->objectlock);
294            return MIX_RESULT_NO_MEMORY;
295        }
296
297        LOG_I(
298                "va_profiles = 0x%08x\n", (guint)va_profiles);
299
300        LOG_V( "vaQueryConfigProfiles\n");
301
302
303        va_status = vaQueryConfigProfiles (va_display, va_profiles, &va_num_profiles);
304
305        if (va_status != VA_STATUS_SUCCESS)
306        {
307            LOG_E(
308                    "Failed to call vaQueryConfigProfiles\n");
309            g_free(va_profiles);
310            g_free (va_entrypoints);
311            g_mutex_unlock(parent->objectlock);
312            return MIX_RESULT_FAIL;
313        }
314
315        LOG_V( "vaQueryConfigProfiles Done\n");
316
317
318
319        /*check whether profile is supported*/
320        for(index= 0; index < va_num_profiles; index++) {
321            if(parent->va_profile == va_profiles[index])
322                break;
323        }
324
325        if(index == va_num_profiles)
326        {
327            LOG_E( "Profile not supported\n");
328            g_free(va_profiles);
329            g_free (va_entrypoints);
330            g_mutex_unlock(parent->objectlock);
331            return MIX_RESULT_FAIL;  //Todo, add error handling here
332        }
333
334        LOG_V( "vaQueryConfigEntrypoints\n");
335
336
337        /*Check entry point*/
338        va_status = vaQueryConfigEntrypoints(va_display,
339                parent->va_profile,
340                va_entrypoints, &va_num_entrypoints);
341
342        if (va_status != VA_STATUS_SUCCESS)
343        {
344            LOG_E(
345                    "Failed to call vaQueryConfigEntrypoints\n");
346            g_free(va_profiles);
347            g_free (va_entrypoints);
348            g_mutex_unlock(parent->objectlock);
349            return MIX_RESULT_FAIL;
350        }
351
352        for (index = 0; index < va_num_entrypoints; index ++) {
353            if (va_entrypoints[index] == VAEntrypointEncSlice) {
354                break;
355            }
356        }
357
358        if (index == va_num_entrypoints) {
359            LOG_E( "Entrypoint not found\n");
360            g_free(va_profiles);
361            g_free (va_entrypoints);
362            g_mutex_unlock(parent->objectlock);
363            return MIX_RESULT_FAIL;  //Todo, add error handling here
364        }
365
366
367        /*free profiles and entrypoints*/
368        g_free(va_profiles);
369        g_free (va_entrypoints);
370
371        va_attrib[0].type = VAConfigAttribRTFormat;
372        va_attrib[1].type = VAConfigAttribRateControl;
373
374        LOG_V( "vaGetConfigAttributes\n");
375
376        va_status = vaGetConfigAttributes(va_display, parent->va_profile,
377                parent->va_entrypoint,
378                &va_attrib[0], 2);
379
380        if (va_status != VA_STATUS_SUCCESS)
381        {
382            LOG_E(
383                    "Failed to call vaGetConfigAttributes\n");
384            g_mutex_unlock(parent->objectlock);
385            return MIX_RESULT_FAIL;
386        }
387
388        if ((va_attrib[0].value & parent->va_format) == 0) {
389            LOG_E( "Matched format not found\n");
390            g_mutex_unlock(parent->objectlock);
391            return MIX_RESULT_FAIL;  //Todo, add error handling here
392        }
393
394
395        if ((va_attrib[1].value & parent->va_rcmode) == 0) {
396            LOG_E( "RC mode not found\n");
397            g_mutex_unlock(parent->objectlock);
398            return MIX_RESULT_FAIL;  //Todo, add error handling here
399        }
400
401        va_attrib[0].value = parent->va_format; //VA_RT_FORMAT_YUV420;
402        va_attrib[1].value = parent->va_rcmode;
403
404        LOG_V( "======VA Configuration======\n");
405
406        LOG_I( "profile = %d\n",
407                parent->va_profile);
408        LOG_I( "va_entrypoint = %d\n",
409                parent->va_entrypoint);
410        LOG_I( "va_attrib[0].type = %d\n",
411                va_attrib[0].type);
412        LOG_I( "va_attrib[1].type = %d\n",
413                va_attrib[1].type);
414        LOG_I( "va_attrib[0].value (Format) = %d\n",
415                va_attrib[0].value);
416        LOG_I( "va_attrib[1].value (RC mode) = %d\n",
417                va_attrib[1].value);
418
419        LOG_V( "vaCreateConfig\n");
420
421        va_status = vaCreateConfig(va_display, parent->va_profile,
422                parent->va_entrypoint,
423                &va_attrib[0], 2, &(parent->va_config));
424
425        if (va_status != VA_STATUS_SUCCESS)
426        {
427            LOG_E( "Failed vaCreateConfig\n");
428            g_mutex_unlock(parent->objectlock);
429            return MIX_RESULT_FAIL;
430        }
431
432        /*TODO: compute the surface number*/
433        int numSurfaces;
434
435        if (parent->share_buf_mode) {
436            numSurfaces = 2;
437        }
438        else {
439            numSurfaces = 8;
440            parent->ci_frame_num = 0;
441        }
442
443        self->surface_num = numSurfaces + parent->ci_frame_num;
444
445        surfaces = g_malloc(sizeof(VASurfaceID)*numSurfaces);
446
447        if (surfaces == NULL)
448        {
449            LOG_E(
450                    "Failed allocate surface\n");
451            g_mutex_unlock(parent->objectlock);
452            return MIX_RESULT_NO_MEMORY;
453        }
454
455        LOG_V( "vaCreateSurfaces\n");
456
457        va_status = vaCreateSurfaces(va_display, parent->picture_width,
458                parent->picture_height, parent->va_format,
459                numSurfaces, surfaces);
460        //TODO check vret and return fail if needed
461
462        if (va_status != VA_STATUS_SUCCESS)
463        {
464            LOG_E(
465                    "Failed vaCreateSurfaces\n");
466            g_mutex_unlock(parent->objectlock);
467            return MIX_RESULT_FAIL;
468        }
469
470        if (parent->share_buf_mode) {
471
472            LOG_V(
473                    "We are in share buffer mode!\n");
474            self->ci_shared_surfaces =
475                g_malloc(sizeof(VASurfaceID) * parent->ci_frame_num);
476
477            if (self->ci_shared_surfaces == NULL)
478            {
479                LOG_E(
480                        "Failed allocate shared surface\n");
481                g_mutex_unlock(parent->objectlock);
482                return MIX_RESULT_NO_MEMORY;
483            }
484
485            guint index;
486            for(index = 0; index < parent->ci_frame_num; index++) {
487
488                LOG_I( "ci_frame_id = %lu\n",
489                        parent->ci_frame_id[index]);
490
491                LOG_V(
492                        "vaCreateSurfaceFromCIFrame\n");
493
494                va_status = vaCreateSurfaceFromCIFrame(va_display,
495                        (gulong) (parent->ci_frame_id[index]),
496                        &self->ci_shared_surfaces[index]);
497                if (va_status != VA_STATUS_SUCCESS)
498                {
499                    LOG_E(
500                            "Failed to vaCreateSurfaceFromCIFrame\n");
501                    g_mutex_unlock(parent->objectlock);
502                    return MIX_RESULT_FAIL;
503                }
504            }
505
506            LOG_V(
507                    "vaCreateSurfaceFromCIFrame Done\n");
508
509        }// if (parent->share_buf_mode)
510
511        self->surfaces = g_malloc(sizeof(VASurfaceID) * self->surface_num);
512
513        if (self->surfaces == NULL)
514        {
515            LOG_E(
516                    "Failed allocate private surface\n");
517            g_free (surfaces);
518            g_mutex_unlock(parent->objectlock);
519            return MIX_RESULT_NO_MEMORY;
520        }
521
522        if (parent->share_buf_mode) {
523            /*shared surfaces should be put in pool first,
524             * because we will get it accoring to CI index*/
525            for(index = 0; index < parent->ci_frame_num; index++)
526                self->surfaces[index] = self->ci_shared_surfaces[index];
527        }
528
529        for(index = 0; index < numSurfaces; index++) {
530            self->surfaces[index + parent->ci_frame_num] = surfaces[index];
531        }
532
533        LOG_V( "assign surface Done\n");
534        LOG_I( "Created %d libva surfaces\n",
535                numSurfaces + parent->ci_frame_num);
536
537#if 0  //current put this in gst
538        images = g_malloc(sizeof(VAImage)*numSurfaces);
539        if (images == NULL)
540        {
541            g_mutex_unlock(parent->objectlock);
542            return MIX_RESULT_FAIL;
543        }
544
545        for (index = 0; index < numSurfaces; index++) {
546            //Derive an VAImage from an existing surface.
547            //The image buffer can then be mapped/unmapped for CPU access
548            va_status = vaDeriveImage(va_display, surfaces[index],
549                    &images[index]);
550        }
551#endif
552
553        LOG_V( "mix_surfacepool_new\n");
554
555        parent->surfacepool = mix_surfacepool_new();
556        if (surface_pool)
557            *surface_pool = parent->surfacepool;
558        //which is useful to check before encode
559
560        if (parent->surfacepool == NULL)
561        {
562            LOG_E(
563                    "Failed to mix_surfacepool_new\n");
564            g_free (surfaces);
565            g_mutex_unlock(parent->objectlock);
566            return MIX_RESULT_FAIL;
567        }
568
569        LOG_V(
570                "mix_surfacepool_initialize\n");
571
572        ret = mix_surfacepool_initialize(parent->surfacepool,
573                self->surfaces, parent->ci_frame_num + numSurfaces);
574
575        switch (ret)
576        {
577            case MIX_RESULT_SUCCESS:
578                break;
579            case MIX_RESULT_ALREADY_INIT:
580                //TODO cleanup and/or retry
581                g_free (surfaces);
582                g_mutex_unlock(parent->objectlock);
583                return MIX_RESULT_FAIL;
584            default:
585                break;
586        }
587
588
589        //Initialize and save the VA context ID
590        LOG_V( "vaCreateContext\n");
591
592        va_status = vaCreateContext(va_display, parent->va_config,
593                parent->picture_width, parent->picture_height,
594                VA_PROGRESSIVE, self->surfaces, parent->ci_frame_num + numSurfaces,
595                &(parent->va_context));
596
597        LOG_I(
598                "Created libva context width %d, height %d\n",
599                parent->picture_width, parent->picture_height);
600
601        if (va_status != VA_STATUS_SUCCESS)
602        {
603            LOG_E(
604                    "Failed to vaCreateContext\n");
605            LOG_I( "va_status = %d\n",
606                    (guint)va_status);
607            g_free (surfaces);
608            g_mutex_unlock(parent->objectlock);
609            return MIX_RESULT_FAIL;
610        }
611
612	 guint max_size = 0;
613        ret = mix_videofmtenc_mpeg4_get_max_encoded_buf_size (parent, &max_size);
614        if (ret != MIX_RESULT_SUCCESS)
615        {
616            LOG_E(
617                    "Failed to mix_videofmtenc_mpeg4_get_max_encoded_buf_size\n");
618            g_free (surfaces);
619            g_mutex_unlock(parent->objectlock);
620            return MIX_RESULT_FAIL;
621
622        }
623
624        /*Create coded buffer for output*/
625        va_status = vaCreateBuffer (va_display, parent->va_context,
626                VAEncCodedBufferType,
627                self->coded_buf_size,  //
628                1, NULL,
629                &self->coded_buf);
630
631        if (va_status != VA_STATUS_SUCCESS)
632        {
633            LOG_E(
634                    "Failed to vaCreateBuffer: VAEncCodedBufferType\n");
635            g_free (surfaces);
636            g_mutex_unlock(parent->objectlock);
637            return MIX_RESULT_FAIL;
638        }
639
640#ifdef SHOW_SRC
641        Display * display = XOpenDisplay (NULL);
642
643        LOG_I( "display = 0x%08x\n",
644                (guint) display);
645        win = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0,
646                parent->picture_width,  parent->picture_height, 0, 0,
647                WhitePixel(display, 0));
648        XMapWindow(display, win);
649        XSelectInput(display, win, KeyPressMask | StructureNotifyMask);
650
651        XSync(display, False);
652        LOG_I( "va_display = 0x%08x\n",
653                (guint) va_display);
654
655#endif /* SHOW_SRC */
656
657        parent->initialized = TRUE;
658
659        g_mutex_unlock(parent->objectlock);
660        g_free (surfaces);
661
662    }
663    else
664    {
665        LOG_E(
666                "not MPEG4 video encode Object\n");
667        return MIX_RESULT_FAIL;
668
669    }
670
671    LOG_V( "end\n");
672
673    return MIX_RESULT_SUCCESS;
674}
675
676MIX_RESULT mix_videofmtenc_mpeg4_encode(MixVideoFormatEnc *mix, MixBuffer * bufin[],
677        gint bufincnt, MixIOVec * iovout[], gint iovoutcnt,
678        MixVideoEncodeParams * encode_params) {
679
680    MIX_RESULT ret = MIX_RESULT_SUCCESS;
681    MixVideoFormatEnc *parent = NULL;
682
683    LOG_V( "Begin\n");
684
685    /*currenly only support one input and output buffer*/
686    //TODO: params i
687
688    if (bufincnt != 1 || iovoutcnt != 1) {
689        LOG_E(
690                "buffer count not equel to 1\n");
691        LOG_E(
692                "maybe some exception occurs\n");
693    }
694
695    if (mix == NULL ||bufin[0] == NULL ||  iovout[0] == NULL) {
696        LOG_E(
697                "!mix || !bufin[0] ||!iovout[0]\n");
698        return MIX_RESULT_NULL_PTR;
699    }
700
701    //TODO: encode_params is reserved here for future usage.
702
703    /* TODO: decide if we need to chainup parent method.
704     *      * * if we do, the following is the code:
705     * */
706
707#if 0
708    if (parent_class->encode) {
709        return parent_class->encode(mix, bufin, bufincnt, iovout,
710                iovoutcnt, encode_params);
711    }
712#endif
713
714    if (MIX_IS_VIDEOFORMATENC_MPEG4(mix))
715    {
716
717        parent = MIX_VIDEOFORMATENC(&(mix->parent));
718        MixVideoFormatEnc_MPEG4 *self = MIX_VIDEOFORMATENC_MPEG4 (mix);
719
720        LOG_V( "Locking\n");
721        g_mutex_lock(parent->objectlock);
722
723
724        //TODO: also we could move some encode Preparation work to here
725
726        LOG_V(
727                "mix_videofmtenc_mpeg4_process_encode\n");
728
729        ret = mix_videofmtenc_mpeg4_process_encode (self,
730                bufin[0], iovout[0]);
731        if (ret != MIX_RESULT_SUCCESS)
732        {
733            LOG_E(
734                    "Failed mix_videofmtenc_mpeg4_process_encode\n");
735            return MIX_RESULT_FAIL;
736        }
737
738
739        LOG_V( "UnLocking\n");
740
741        g_mutex_unlock(parent->objectlock);
742    }
743    else
744    {
745        LOG_E(
746                "not MPEG4 video encode Object\n");
747        return MIX_RESULT_FAIL;
748    }
749
750    LOG_V( "end\n");
751
752    return MIX_RESULT_SUCCESS;
753}
754
755MIX_RESULT mix_videofmtenc_mpeg4_flush(MixVideoFormatEnc *mix) {
756
757    //MIX_RESULT ret = MIX_RESULT_SUCCESS;
758
759    LOG_V( "Begin\n");
760
761    if (mix == NULL) {
762        LOG_E( "mix == NULL\n");
763        return MIX_RESULT_NULL_PTR;
764    }
765
766
767    /*not chain to parent flush func*/
768#if 0
769    if (parent_class->flush) {
770        return parent_class->flush(mix, msg);
771    }
772#endif
773
774    MixVideoFormatEnc_MPEG4 *self = MIX_VIDEOFORMATENC_MPEG4(mix);
775
776    g_mutex_lock(mix->objectlock);
777
778    /*unref the current source surface*/
779    if (self->cur_fame != NULL)
780    {
781        mix_videoframe_unref (self->cur_fame);
782        self->cur_fame = NULL;
783    }
784
785    /*unref the reconstructed surface*/
786    if (self->rec_fame != NULL)
787    {
788        mix_videoframe_unref (self->rec_fame);
789        self->rec_fame = NULL;
790    }
791
792    /*unref the reference surface*/
793    if (self->ref_fame != NULL)
794    {
795        mix_videoframe_unref (self->ref_fame);
796        self->ref_fame = NULL;
797    }
798
799    /*reset the properities*/
800    self->encoded_frames = 0;
801    self->pic_skipped = FALSE;
802    self->is_intra = TRUE;
803
804    g_mutex_unlock(mix->objectlock);
805
806    LOG_V( "end\n");
807
808    return MIX_RESULT_SUCCESS;
809}
810
811MIX_RESULT mix_videofmtenc_mpeg4_eos(MixVideoFormatEnc *mix) {
812
813    /* TODO: add codes for MPEG-4:2 */
814
815    /* TODO: decide if we need to chainup parent method.
816     * if we do, the following is the code:
817     */
818
819    LOG_V( "\n");
820
821    if (mix == NULL) {
822        LOG_E( "mix == NULL\n");
823        return MIX_RESULT_NULL_PTR;
824    }
825
826    if (parent_class->eos) {
827        return parent_class->eos(mix);
828    }
829    return MIX_RESULT_SUCCESS;
830}
831
832MIX_RESULT mix_videofmtenc_mpeg4_deinitialize(MixVideoFormatEnc *mix) {
833
834    MixVideoFormatEnc *parent = NULL;
835    VAStatus va_status;
836
837    LOG_V( "Begin\n");
838
839    if (mix == NULL) {
840        LOG_E( "mix == NULL\n");
841        return MIX_RESULT_NULL_PTR;
842    }
843
844    parent = MIX_VIDEOFORMATENC(&(mix->parent));
845    MixVideoFormatEnc_MPEG4 *self = MIX_VIDEOFORMATENC_MPEG4(mix);
846
847    LOG_V( "Release frames\n");
848
849    g_mutex_lock(parent->objectlock);
850
851#if 0
852    /*unref the current source surface*/
853    if (self->cur_fame != NULL)
854    {
855        mix_videoframe_unref (self->cur_fame);
856        self->cur_fame = NULL;
857    }
858#endif
859
860    /*unref the reconstructed surface*/
861    if (self->rec_fame != NULL)
862    {
863        mix_videoframe_unref (self->rec_fame);
864        self->rec_fame = NULL;
865    }
866
867    /*unref the reference surface*/
868    if (self->ref_fame != NULL)
869    {
870        mix_videoframe_unref (self->ref_fame);
871        self->ref_fame = NULL;
872    }
873
874    LOG_V( "Release surfaces\n");
875
876    if (self->ci_shared_surfaces)
877    {
878        g_free (self->ci_shared_surfaces);
879        self->ci_shared_surfaces = NULL;
880    }
881
882    if (self->surfaces)
883    {
884        g_free (self->surfaces);
885        self->surfaces = NULL;
886    }
887
888    LOG_V( "vaDestroyContext\n");
889
890    va_status = vaDestroyContext (parent->va_display, parent->va_context);
891    if (va_status != VA_STATUS_SUCCESS)
892    {
893        LOG_E(
894                "Failed vaDestroyContext\n");
895        g_mutex_unlock(parent->objectlock);
896        return MIX_RESULT_FAIL;
897    }
898
899    LOG_V( "vaDestroyConfig\n");
900
901    va_status = vaDestroyConfig (parent->va_display, parent->va_config);
902    if (va_status != VA_STATUS_SUCCESS)
903    {
904        LOG_E(
905                "Failed vaDestroyConfig\n");
906        g_mutex_unlock(parent->objectlock);
907        return MIX_RESULT_FAIL;
908    }
909
910    parent->initialized = TRUE;
911
912    g_mutex_unlock(parent->objectlock);
913
914#if 1
915    if (parent_class->deinitialize) {
916        return parent_class->deinitialize(mix);
917    }
918#endif
919
920    //Most stuff is cleaned up in parent_class->finalize()
921
922    LOG_V( "end\n");
923
924    return MIX_RESULT_SUCCESS;
925}
926
927MIX_RESULT mix_videofmtenc_mpeg4_send_seq_params (MixVideoFormatEnc_MPEG4 *mix)
928{
929
930    VAStatus va_status;
931    VAEncSequenceParameterBufferMPEG4 mpeg4_seq_param;
932    VABufferID				seq_para_buf_id;
933
934
935    MixVideoFormatEnc *parent = NULL;
936
937    if (mix == NULL)
938        return MIX_RESULT_NULL_PTR;
939
940    LOG_V( "Begin\n\n");
941
942    if (MIX_IS_VIDEOFORMATENC_MPEG4(mix))
943    {
944        parent = MIX_VIDEOFORMATENC(&(mix->parent));
945
946        /*set up the sequence params for HW*/
947        mpeg4_seq_param.profile_and_level_indication = mix->profile_and_level_indication;  //TODO, hard code now
948        mpeg4_seq_param.video_object_layer_width= parent->picture_width;
949        mpeg4_seq_param.video_object_layer_height= parent->picture_height;
950        mpeg4_seq_param.vop_time_increment_resolution =
951			(unsigned int) (parent->frame_rate_num + parent->frame_rate_denom /2 ) / parent->frame_rate_denom;
952        mpeg4_seq_param.fixed_vop_time_increment= mix->fixed_vop_time_increment;
953        mpeg4_seq_param.bits_per_second= parent->bitrate;
954        mpeg4_seq_param.frame_rate =
955			(unsigned int) (parent->frame_rate_num + parent->frame_rate_denom /2 ) / parent->frame_rate_denom;
956        mpeg4_seq_param.initial_qp = parent->initial_qp;
957        mpeg4_seq_param.min_qp = parent->min_qp;
958        mpeg4_seq_param.intra_period = parent->intra_period;
959
960
961        //mpeg4_seq_param.fixed_vop_rate = 30;
962
963
964
965        LOG_V(
966                "===mpeg4 sequence params===\n");
967
968        LOG_I( "profile_and_level_indication = %d\n",
969                (guint)mpeg4_seq_param.profile_and_level_indication);
970        LOG_I( "intra_period = %d\n",
971                mpeg4_seq_param.intra_period);
972        LOG_I( "video_object_layer_width = %d\n",
973                mpeg4_seq_param.video_object_layer_width);
974        LOG_I( "video_object_layer_height = %d\n",
975                mpeg4_seq_param.video_object_layer_height);
976        LOG_I( "vop_time_increment_resolution = %d\n",
977                mpeg4_seq_param.vop_time_increment_resolution);
978        LOG_I( "fixed_vop_rate = %d\n",
979                mpeg4_seq_param.fixed_vop_rate);
980        LOG_I( "fixed_vop_time_increment = %d\n",
981                mpeg4_seq_param.fixed_vop_time_increment);
982        LOG_I( "bitrate = %d\n",
983                mpeg4_seq_param.bits_per_second);
984        LOG_I( "frame_rate = %d\n",
985                mpeg4_seq_param.frame_rate);
986        LOG_I( "initial_qp = %d\n",
987                mpeg4_seq_param.initial_qp);
988        LOG_I( "min_qp = %d\n",
989                mpeg4_seq_param.min_qp);
990        LOG_I( "intra_period = %d\n\n",
991                mpeg4_seq_param.intra_period);
992
993        va_status = vaCreateBuffer(parent->va_display, parent->va_context,
994                VAEncSequenceParameterBufferType,
995                sizeof(mpeg4_seq_param),
996                1, &mpeg4_seq_param,
997                &seq_para_buf_id);
998        if (va_status != VA_STATUS_SUCCESS)
999        {
1000            LOG_E(
1001                    "Failed to vaCreateBuffer\n");
1002            return MIX_RESULT_FAIL;
1003        }
1004
1005        va_status = vaRenderPicture(parent->va_display, parent->va_context,
1006                &seq_para_buf_id, 1);
1007        if (va_status != VA_STATUS_SUCCESS)
1008        {
1009            LOG_E(
1010                    "Failed to vaRenderPicture\n");
1011            LOG_I( "va_status = %d\n", va_status);
1012            return MIX_RESULT_FAIL;
1013        }
1014    }
1015    else
1016    {
1017        LOG_E(
1018                "not MPEG4 video encode Object\n");
1019        return MIX_RESULT_FAIL;
1020    }
1021
1022    LOG_V( "end\n");
1023
1024    return MIX_RESULT_SUCCESS;
1025
1026
1027}
1028
1029MIX_RESULT mix_videofmtenc_mpeg4_send_picture_parameter (MixVideoFormatEnc_MPEG4 *mix)
1030{
1031    VAStatus va_status;
1032    VAEncPictureParameterBufferMPEG4 mpeg4_pic_param;
1033    MixVideoFormatEnc *parent = NULL;
1034
1035    if (mix == NULL)
1036        return MIX_RESULT_NULL_PTR;
1037
1038    LOG_V( "Begin\n\n");
1039
1040#if 0 //not needed currently
1041    MixVideoConfigParamsEncMPEG4 * params_mpeg4
1042        = MIX_VIDEOCONFIGPARAMSENC_MPEG4 (config_params_enc);
1043#endif
1044
1045    if (MIX_IS_VIDEOFORMATENC_MPEG4(mix)) {
1046
1047        parent = MIX_VIDEOFORMATENC(&(mix->parent));
1048
1049        /*set picture params for HW*/
1050        mpeg4_pic_param.reference_picture = mix->ref_fame->frame_id;
1051        mpeg4_pic_param.reconstructed_picture = mix->rec_fame->frame_id;
1052        mpeg4_pic_param.coded_buf = mix->coded_buf;
1053        mpeg4_pic_param.picture_width = parent->picture_width;
1054        mpeg4_pic_param.picture_height = parent->picture_height;
1055        mpeg4_pic_param.vop_time_increment= mix->encoded_frames;
1056        mpeg4_pic_param.picture_type = mix->is_intra ? VAEncPictureTypeIntra : VAEncPictureTypePredictive;
1057
1058
1059
1060        LOG_V(
1061                "======mpeg4 picture params======\n");
1062        LOG_I( "reference_picture = 0x%08x\n",
1063                mpeg4_pic_param.reference_picture);
1064        LOG_I( "reconstructed_picture = 0x%08x\n",
1065                mpeg4_pic_param.reconstructed_picture);
1066        LOG_I( "coded_buf = 0x%08x\n",
1067                mpeg4_pic_param.coded_buf);
1068        LOG_I( "picture_width = %d\n",
1069                mpeg4_pic_param.picture_width);
1070        LOG_I( "picture_height = %d\n",
1071                mpeg4_pic_param.picture_height);
1072        LOG_I( "vop_time_increment = %d\n",
1073                mpeg4_pic_param.vop_time_increment);
1074        LOG_I( "picture_type = %d\n\n",
1075                mpeg4_pic_param.picture_type);
1076
1077        va_status = vaCreateBuffer(parent->va_display, parent->va_context,
1078                VAEncPictureParameterBufferType,
1079                sizeof(mpeg4_pic_param),
1080                1,&mpeg4_pic_param,
1081                &mix->pic_param_buf);
1082
1083        if (va_status != VA_STATUS_SUCCESS)
1084        {
1085            LOG_E(
1086                    "Failed to vaCreateBuffer\n");
1087            return MIX_RESULT_FAIL;
1088        }
1089
1090
1091        va_status = vaRenderPicture(parent->va_display, parent->va_context,
1092                &mix->pic_param_buf, 1);
1093
1094        if (va_status != VA_STATUS_SUCCESS)
1095        {
1096            LOG_E(
1097                    "Failed to vaRenderPicture\n");
1098            LOG_I( "va_status = %d\n", va_status);
1099            return MIX_RESULT_FAIL;
1100        }
1101    }
1102    else
1103    {
1104        LOG_E(
1105                "not MPEG4 video encode Object\n");
1106        return MIX_RESULT_FAIL;
1107    }
1108
1109    LOG_V( "end\n");
1110    return MIX_RESULT_SUCCESS;
1111
1112}
1113
1114
1115MIX_RESULT mix_videofmtenc_mpeg4_send_slice_parameter (MixVideoFormatEnc_MPEG4 *mix)
1116{
1117    VAStatus va_status;
1118
1119    guint slice_height;
1120    guint slice_index;
1121    guint slice_height_in_mb;
1122
1123    if (mix == NULL)
1124        return MIX_RESULT_NULL_PTR;
1125
1126    LOG_V( "Begin\n\n");
1127
1128
1129    MixVideoFormatEnc *parent = NULL;
1130
1131    if (MIX_IS_VIDEOFORMATENC_MPEG4(mix))
1132    {
1133        parent = MIX_VIDEOFORMATENC(&(mix->parent));
1134
1135        slice_height = parent->picture_height;
1136
1137        slice_height += 15;
1138        slice_height &= (~15);
1139
1140        VAEncSliceParameterBuffer slice_param;
1141        slice_index = 0;
1142        slice_height_in_mb = slice_height / 16;
1143        slice_param.start_row_number = 0;
1144        slice_param.slice_height = slice_height / 16;
1145        slice_param.slice_flags.bits.is_intra = mix->is_intra;
1146        slice_param.slice_flags.bits.disable_deblocking_filter_idc
1147            = mix->disable_deblocking_filter_idc;
1148
1149            LOG_V(
1150                    "======mpeg4 slice params======\n");
1151
1152            LOG_I( "start_row_number = %d\n",
1153                    (gint) slice_param.start_row_number);
1154            LOG_I( "slice_height_in_mb = %d\n",
1155                    (gint) slice_param.slice_height);
1156            LOG_I( "slice.is_intra = %d\n",
1157                    (gint) slice_param.slice_flags.bits.is_intra);
1158            LOG_I(
1159                    "disable_deblocking_filter_idc = %d\n\n",
1160                    (gint) mix->disable_deblocking_filter_idc);
1161
1162        va_status = vaCreateBuffer (parent->va_display, parent->va_context,
1163                VAEncSliceParameterBufferType,
1164                sizeof(VAEncSliceParameterBuffer),
1165                1, &slice_param,
1166                &mix->slice_param_buf);
1167
1168        if (va_status != VA_STATUS_SUCCESS)
1169        {
1170            LOG_E(
1171                    "Failed to vaCreateBuffer\n");
1172            return MIX_RESULT_FAIL;
1173        }
1174
1175        va_status = vaRenderPicture(parent->va_display, parent->va_context,
1176                &mix->slice_param_buf, 1);
1177
1178        if (va_status != VA_STATUS_SUCCESS)
1179        {
1180            LOG_E(
1181                    "Failed to vaRenderPicture\n");
1182            return MIX_RESULT_FAIL;
1183        }
1184
1185    }
1186    else
1187    {
1188        LOG_E(
1189                "not MPEG4 video encode Object\n");
1190        return MIX_RESULT_FAIL;
1191    }
1192
1193    LOG_V( "end\n");
1194
1195    return MIX_RESULT_SUCCESS;
1196}
1197
1198MIX_RESULT mix_videofmtenc_mpeg4_process_encode (MixVideoFormatEnc_MPEG4 *mix,
1199        MixBuffer * bufin, MixIOVec * iovout)
1200{
1201
1202    MIX_RESULT ret = MIX_RESULT_SUCCESS;
1203    VAStatus va_status = VA_STATUS_SUCCESS;
1204    VADisplay va_display = NULL;
1205    VAContextID va_context;
1206    gulong surface = 0;
1207    guint16 width, height;
1208
1209    MixVideoFrame *  tmp_fame;
1210    guint8 *buf;
1211
1212    if ((mix == NULL) || (bufin == NULL) || (iovout == NULL)) {
1213        LOG_E(
1214                "mix == NUL) || bufin == NULL || iovout == NULL\n");
1215        return MIX_RESULT_NULL_PTR;
1216    }
1217
1218    LOG_V( "Begin\n");
1219
1220    if (MIX_IS_VIDEOFORMATENC_MPEG4(mix))
1221    {
1222
1223        MixVideoFormatEnc *parent = MIX_VIDEOFORMATENC(&(mix->parent));
1224
1225        va_display = parent->va_display;
1226        va_context = parent->va_context;
1227        width = parent->picture_width;
1228        height = parent->picture_height;
1229
1230
1231        LOG_I( "encoded_frames = %d\n",
1232                mix->encoded_frames);
1233        LOG_I( "is_intra = %d\n",
1234                mix->is_intra);
1235        LOG_I( "ci_frame_id = 0x%08x\n",
1236                (guint) parent->ci_frame_id);
1237
1238        /* determine the picture type*/
1239        if ((mix->encoded_frames % parent->intra_period) == 0) {
1240            mix->is_intra = TRUE;
1241        } else {
1242            mix->is_intra = FALSE;
1243        }
1244
1245        LOG_I( "is_intra_picture = %d\n",
1246                mix->is_intra);
1247
1248        LOG_V(
1249                "Get Surface from the pool\n");
1250
1251        /*current we use one surface for source data,
1252         * one for reference and one for reconstructed*/
1253        /*TODO, could be refine here*/
1254
1255        if (!parent->share_buf_mode) {
1256            LOG_V(
1257                    "We are NOT in share buffer mode\n");
1258
1259            if (mix->ref_fame == NULL)
1260            {
1261                ret = mix_surfacepool_get(parent->surfacepool, &mix->ref_fame);
1262                if (ret != MIX_RESULT_SUCCESS)  //#ifdef SLEEP_SURFACE not used
1263                {
1264                    LOG_E(
1265                            "Failed to mix_surfacepool_get\n");
1266                    return MIX_RESULT_FAIL;
1267                }
1268            }
1269
1270            if (mix->rec_fame == NULL)
1271            {
1272                ret = mix_surfacepool_get(parent->surfacepool, &mix->rec_fame);
1273                if (ret != MIX_RESULT_SUCCESS)
1274                {
1275                    LOG_E(
1276                            "Failed to mix_surfacepool_get\n");
1277                    return MIX_RESULT_FAIL;
1278                }
1279            }
1280
1281            if (parent->need_display) {
1282                mix->cur_fame = NULL;
1283            }
1284
1285            if (mix->cur_fame == NULL)
1286            {
1287                ret = mix_surfacepool_get(parent->surfacepool, &mix->cur_fame);
1288                if (ret != MIX_RESULT_SUCCESS)
1289                {
1290                    LOG_E(
1291                            "Failed to mix_surfacepool_get\n");
1292                    return MIX_RESULT_FAIL;
1293                }
1294            }
1295
1296            LOG_V( "Get Surface Done\n");
1297
1298
1299            VAImage src_image;
1300            guint8 *pvbuf;
1301            guint8 *dst_y;
1302            guint8 *dst_uv;
1303            int i,j;
1304
1305            LOG_V(
1306                    "map source data to surface\n");
1307
1308            ret = mix_videoframe_get_frame_id(mix->cur_fame, &surface);
1309            if (ret != MIX_RESULT_SUCCESS)
1310            {
1311                LOG_E(
1312                        "Failed to mix_videoframe_get_frame_id\n");
1313                return MIX_RESULT_FAIL;
1314            }
1315
1316
1317            LOG_I(
1318                    "surface id = 0x%08x\n", (guint) surface);
1319
1320            va_status = vaDeriveImage(va_display, surface, &src_image);
1321            //need to destroy
1322
1323            if (va_status != VA_STATUS_SUCCESS)
1324            {
1325                LOG_E(
1326                        "Failed to vaDeriveImage\n");
1327                return MIX_RESULT_FAIL;
1328            }
1329
1330            VAImage *image = &src_image;
1331
1332            LOG_V( "vaDeriveImage Done\n");
1333
1334
1335            va_status = vaMapBuffer (va_display, image->buf, (void **)&pvbuf);
1336            if (va_status != VA_STATUS_SUCCESS)
1337            {
1338                LOG_E( "Failed to vaMapBuffer\n");
1339                return MIX_RESULT_FAIL;
1340            }
1341
1342            LOG_V(
1343                    "vaImage information\n");
1344            LOG_I(
1345                    "image->pitches[0] = %d\n", image->pitches[0]);
1346            LOG_I(
1347                    "image->pitches[1] = %d\n", image->pitches[1]);
1348            LOG_I(
1349                    "image->offsets[0] = %d\n", image->offsets[0]);
1350            LOG_I(
1351                    "image->offsets[1] = %d\n", image->offsets[1]);
1352            LOG_I(
1353                    "image->num_planes = %d\n", image->num_planes);
1354            LOG_I(
1355                    "image->width = %d\n", image->width);
1356            LOG_I(
1357                    "image->height = %d\n", image->height);
1358
1359            LOG_I(
1360                    "input buf size = %d\n", bufin->size);
1361
1362            guint8 *inbuf = bufin->data;
1363
1364            /*need to convert YUV420 to NV12*/
1365            dst_y = pvbuf +image->offsets[0];
1366
1367            for (i = 0; i < height; i ++) {
1368                memcpy (dst_y, inbuf + i * width, width);
1369                dst_y += image->pitches[0];
1370            }
1371
1372            dst_uv = pvbuf + image->offsets[1];
1373
1374            for (i = 0; i < height / 2; i ++) {
1375                for (j = 0; j < width; j+=2) {
1376                    dst_uv [j] = inbuf [width * height + i * width / 2 + j / 2];
1377                    dst_uv [j + 1] =
1378                        inbuf [width * height * 5 / 4 + i * width / 2 + j / 2];
1379                }
1380                dst_uv += image->pitches[1];
1381            }
1382
1383            vaUnmapBuffer(va_display, image->buf);
1384            if (va_status != VA_STATUS_SUCCESS)
1385            {
1386                LOG_E(
1387                        "Failed to vaUnmapBuffer\n");
1388                return MIX_RESULT_FAIL;
1389            }
1390
1391            va_status = vaDestroyImage(va_display, src_image.image_id);
1392            if (va_status != VA_STATUS_SUCCESS)
1393            {
1394                LOG_E(
1395                        "Failed to vaDestroyImage\n");
1396                return MIX_RESULT_FAIL;
1397            }
1398
1399            LOG_V(
1400                    "Map source data to surface done\n");
1401
1402        }
1403
1404        else {//if (!parent->share_buf_mode)
1405
1406            MixVideoFrame * frame = mix_videoframe_new();
1407
1408            if (mix->ref_fame == NULL)
1409            {
1410                ret = mix_videoframe_set_ci_frame_idx (frame, mix->surface_num - 1);
1411
1412                ret = mix_surfacepool_get_frame_with_ci_frameidx
1413                    (parent->surfacepool, &mix->ref_fame, frame);
1414                if (ret != MIX_RESULT_SUCCESS)  //#ifdef SLEEP_SURFACE not used
1415                {
1416                    LOG_E(
1417                            "get reference surface from pool failed\n");
1418                    return MIX_RESULT_FAIL;
1419                }
1420            }
1421
1422            if (mix->rec_fame == NULL)
1423            {
1424                ret = mix_videoframe_set_ci_frame_idx (frame, mix->surface_num - 2);
1425
1426                ret = mix_surfacepool_get_frame_with_ci_frameidx
1427                    (parent->surfacepool, &mix->rec_fame, frame);
1428
1429                if (ret != MIX_RESULT_SUCCESS)
1430                {
1431                    LOG_E(
1432                            "get recontructed surface from pool failed\n");
1433                    return MIX_RESULT_FAIL;
1434                }
1435            }
1436
1437            if (parent->need_display) {
1438                mix->cur_fame = NULL;
1439            }
1440
1441            if (mix->cur_fame == NULL)
1442            {
1443                guint ci_idx;
1444                memcpy (&ci_idx, bufin->data, bufin->size);
1445
1446                LOG_I(
1447                        "surface_num = %d\n", mix->surface_num);
1448                LOG_I(
1449                        "ci_frame_idx = %d\n", ci_idx);
1450
1451                if (ci_idx > mix->surface_num - 2) {
1452                    LOG_E(
1453                            "the CI frame idx is too bigger than CI frame number\n");
1454                    return MIX_RESULT_FAIL;
1455                }
1456
1457
1458                ret = mix_videoframe_set_ci_frame_idx (frame, ci_idx);
1459
1460                ret = mix_surfacepool_get_frame_with_ci_frameidx
1461                    (parent->surfacepool, &mix->cur_fame, frame);
1462
1463                if (ret != MIX_RESULT_SUCCESS)
1464                {
1465                    LOG_E(
1466                            "get current working surface from pool failed\n");
1467                    return MIX_RESULT_FAIL;
1468                }
1469            }
1470
1471            ret = mix_videoframe_get_frame_id(mix->cur_fame, &surface);
1472
1473        }
1474
1475        LOG_V( "vaBeginPicture\n");
1476        LOG_I( "va_context = 0x%08x\n",(guint)va_context);
1477        LOG_I( "surface = 0x%08x\n",(guint)surface);
1478        LOG_I( "va_display = 0x%08x\n",(guint)va_display);
1479
1480        va_status = vaBeginPicture(va_display, va_context, surface);
1481        if (va_status != VA_STATUS_SUCCESS)
1482        {
1483            LOG_E( "Failed vaBeginPicture\n");
1484            return MIX_RESULT_FAIL;
1485        }
1486
1487        LOG_V( "mix_videofmtenc_mpeg4_send_seq_params\n");
1488
1489        if (mix->encoded_frames == 0) {
1490            mix_videofmtenc_mpeg4_send_seq_params (mix);
1491            if (ret != MIX_RESULT_SUCCESS)
1492            {
1493                LOG_E(
1494                        "Failed mix_videofmtenc_mpeg4_send_seq_params\n");
1495                return MIX_RESULT_FAIL;
1496            }
1497        }
1498
1499        ret = mix_videofmtenc_mpeg4_send_picture_parameter (mix);
1500
1501        if (ret != MIX_RESULT_SUCCESS)
1502        {
1503           LOG_E(
1504                   "Failed mix_videofmtenc_mpeg4_send_picture_parameter\n");
1505           return MIX_RESULT_FAIL;
1506        }
1507
1508        ret = mix_videofmtenc_mpeg4_send_slice_parameter (mix);
1509        if (ret != MIX_RESULT_SUCCESS)
1510        {
1511            LOG_E(
1512                    "Failed mix_videofmtenc_mpeg4_send_slice_parameter\n");
1513            return MIX_RESULT_FAIL;
1514        }
1515
1516        LOG_V( "before vaEndPicture\n");
1517
1518        va_status = vaEndPicture (va_display, va_context);
1519        if (va_status != VA_STATUS_SUCCESS)
1520        {
1521            LOG_E( "Failed vaEndPicture\n");
1522            return MIX_RESULT_FAIL;
1523        }
1524
1525
1526        LOG_V( "vaSyncSurface\n");
1527
1528        va_status = vaSyncSurface(va_display, surface);
1529        if (va_status != VA_STATUS_SUCCESS)
1530        {
1531            LOG_E( "Failed vaSyncSurface\n");
1532            return MIX_RESULT_FAIL;
1533        }
1534
1535
1536        LOG_V(
1537                "Start to get encoded data\n");
1538
1539        /*get encoded data from the VA buffer*/
1540        va_status = vaMapBuffer (va_display, mix->coded_buf, (void **)&buf);
1541        if (va_status != VA_STATUS_SUCCESS)
1542        {
1543            LOG_E( "Failed vaMapBuffer\n");
1544            return MIX_RESULT_FAIL;
1545        }
1546
1547        // first 4 bytes is the size of the buffer
1548		memcpy (&(iovout->data_size), (void*)buf, 4);
1549        //size = (guint*) buf;
1550
1551        if (iovout->data == NULL) { //means app doesn't allocate the buffer, so _encode will allocate it.
1552
1553            iovout->data = g_malloc (iovout->data_size);
1554            if (iovout->data == NULL) {
1555                return MIX_RESULT_NO_MEMORY;
1556            }
1557        }
1558
1559        memcpy (iovout->data, buf + 16, iovout->data_size);
1560
1561        iovout->buffer_size = iovout->data_size;
1562
1563        LOG_I(
1564                "out size is = %d\n", iovout->data_size);
1565
1566        va_status = vaUnmapBuffer (va_display, mix->coded_buf);
1567        if (va_status != VA_STATUS_SUCCESS)
1568        {
1569            LOG_E( "Failed vaUnmapBuffer\n");
1570            return MIX_RESULT_FAIL;
1571        }
1572
1573        LOG_V( "get encoded data done\n");
1574
1575#if 0
1576        if (parent->drawable) {
1577            va_status = vaPutSurface(va_display, surface, (Drawable)parent->drawable,
1578                    0,0, width, height,
1579                    0,0, width, height,
1580                    NULL,0,0);
1581        }
1582
1583#ifdef SHOW_SRC
1584        else {
1585
1586            va_status = vaPutSurface(va_display, surface, win,
1587                    0,0, width, height,
1588                    0,0, width, height,
1589                    NULL,0,0);
1590        }
1591#endif //SHOW_SRC
1592#endif
1593
1594        VASurfaceStatus status;
1595
1596        /*query the status of current surface*/
1597        va_status = vaQuerySurfaceStatus(va_display, surface,  &status);
1598        if (va_status != VA_STATUS_SUCCESS)
1599        {
1600            LOG_E(
1601                    "Failed vaQuerySurfaceStatus\n");
1602            return MIX_RESULT_FAIL;
1603        }
1604        mix->pic_skipped = status & VASurfaceSkipped;
1605
1606	//ret = mix_framemanager_enqueue(parent->framemgr, mix->rec_fame);
1607
1608       if (parent->need_display) {
1609	ret = mix_framemanager_enqueue(parent->framemgr, mix->cur_fame);
1610        if (ret != MIX_RESULT_SUCCESS)
1611        {
1612            LOG_E(
1613                    "Failed mix_framemanager_enqueue\n");
1614            return MIX_RESULT_FAIL;
1615        }
1616        }
1617
1618
1619        /*update the reference surface and reconstructed surface */
1620        if (!mix->pic_skipped) {
1621            tmp_fame = mix->rec_fame;
1622            mix->rec_fame= mix->ref_fame;
1623            mix->ref_fame = tmp_fame;
1624        }
1625
1626
1627#if 0
1628        if (mix->ref_fame != NULL)
1629            mix_videoframe_unref (mix->ref_fame);
1630        mix->ref_fame = mix->rec_fame;
1631
1632        mix_videoframe_unref (mix->cur_fame);
1633#endif
1634
1635        if (!(parent->need_display)) {
1636            mix_videoframe_unref (mix->cur_fame);
1637            mix->cur_fame = NULL;
1638        }
1639
1640        mix->encoded_frames ++;
1641    }
1642    else
1643    {
1644        LOG_E(
1645                "not MPEG4 video encode Object\n");
1646        return MIX_RESULT_FAIL;
1647    }
1648
1649
1650    LOG_V( "end\n");
1651
1652    return MIX_RESULT_SUCCESS;
1653}
1654
1655MIX_RESULT mix_videofmtenc_mpeg4_get_max_encoded_buf_size (
1656        MixVideoFormatEnc *mix, guint * max_size)
1657{
1658
1659    MixVideoFormatEnc *parent = NULL;
1660
1661    if (mix == NULL)
1662    {
1663        LOG_E(
1664                "mix == NULL\n");
1665            return MIX_RESULT_NULL_PTR;
1666    }
1667
1668    LOG_V( "Begin\n");
1669
1670    parent = MIX_VIDEOFORMATENC(mix);
1671    MixVideoFormatEnc_MPEG4 *self = MIX_VIDEOFORMATENC_MPEG4 (mix);
1672
1673    if (MIX_IS_VIDEOFORMATENC_MPEG4(self)) {
1674
1675        if (self->coded_buf_size > 0) {
1676            *max_size = self->coded_buf_size;
1677            LOG_V ("Already calculate the max encoded size, get the value directly");
1678            return MIX_RESULT_SUCCESS;
1679        }
1680
1681        /*base on the rate control mode to calculate the defaule encoded buffer size*/
1682        if (self->va_rcmode == VA_RC_NONE) {
1683            self->coded_buf_size =
1684                (parent->picture_width* parent->picture_height * 400) / (16 * 16);
1685            // set to value according to QP
1686        }
1687        else {
1688            self->coded_buf_size = parent->bitrate/ 4;
1689        }
1690
1691        self->coded_buf_size =
1692            max (self->coded_buf_size ,
1693                    (parent->picture_width* parent->picture_height * 400) / (16 * 16));
1694
1695        /*in case got a very large user input bit rate value*/
1696        self->coded_buf_size =
1697            max(self->coded_buf_size,
1698                    (parent->picture_width * parent->picture_height * 1.5 * 8));
1699        self->coded_buf_size =  (self->coded_buf_size + 15) &(~15);
1700    }
1701    else
1702    {
1703        LOG_E(
1704                "not MPEG4 video encode Object\n");
1705        return MIX_RESULT_FAIL;
1706    }
1707
1708    *max_size = self->coded_buf_size;
1709
1710    LOG_V( "end\n");
1711
1712    return MIX_RESULT_SUCCESS;
1713}
1714