Home | History | Annotate | Download | only in src
      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 Intels 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
     21 Window 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  */
     29 static MixVideoFormatEncClass *parent_class = NULL;
     30 
     31 static 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  */
     36 G_DEFINE_TYPE (MixVideoFormatEnc_MPEG4, mix_videoformatenc_mpeg4, MIX_TYPE_VIDEOFORMATENC);
     37 
     38 static 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 
     58 static 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 
     85 MixVideoFormatEnc_MPEG4 *
     86 mix_videoformatenc_mpeg4_new(void) {
     87     MixVideoFormatEnc_MPEG4 *ret =
     88         g_object_new(MIX_TYPE_VIDEOFORMATENC_MPEG4, NULL);
     89 
     90     return ret;
     91 }
     92 
     93 void 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 
    107 MixVideoFormatEnc_MPEG4 *
    108 mix_videoformatenc_mpeg4_ref(MixVideoFormatEnc_MPEG4 * mix) {
    109     return (MixVideoFormatEnc_MPEG4 *) g_object_ref(G_OBJECT(mix));
    110 }
    111 
    112 /*MPEG-4:2 vmethods implementation */
    113 MIX_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 
    135 MIX_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 
    676 MIX_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 
    755 MIX_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 
    811 MIX_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 
    832 MIX_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 
    927 MIX_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 
   1029 MIX_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 
   1115 MIX_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 
   1198 MIX_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 
   1655 MIX_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