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_preview.h"
     15 #include "mixvideoconfigparamsenc_preview.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_preview_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_Preview, mix_videoformatenc_preview, MIX_TYPE_VIDEOFORMATENC);
     37 
     38 static void mix_videoformatenc_preview_init(MixVideoFormatEnc_Preview * 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_preview_class_init(
     59         MixVideoFormatEnc_PreviewClass * 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_preview_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_preview_getcaps;
     77     video_formatenc_class->initialize = mix_videofmtenc_preview_initialize;
     78     video_formatenc_class->encode = mix_videofmtenc_preview_encode;
     79     video_formatenc_class->flush = mix_videofmtenc_preview_flush;
     80     video_formatenc_class->eos = mix_videofmtenc_preview_eos;
     81     video_formatenc_class->deinitialize = mix_videofmtenc_preview_deinitialize;
     82 }
     83 
     84 MixVideoFormatEnc_Preview *
     85 mix_videoformatenc_preview_new(void) {
     86     MixVideoFormatEnc_Preview *ret =
     87         g_object_new(MIX_TYPE_VIDEOFORMATENC_PREVIEW, NULL);
     88 
     89     return ret;
     90 }
     91 
     92 void mix_videoformatenc_preview_finalize(GObject * obj) {
     93     /* clean up here. */
     94 
     95     /*MixVideoFormatEnc_Preview *mix = MIX_VIDEOFORMATENC_PREVIEW(obj); */
     96     GObjectClass *root_class = (GObjectClass *) parent_class;
     97 
     98     LOG_V( "\n");
     99 
    100     /* Chain up parent */
    101     if (root_class->finalize) {
    102         root_class->finalize(obj);
    103     }
    104 }
    105 
    106 MixVideoFormatEnc_Preview *
    107 mix_videoformatenc_preview_ref(MixVideoFormatEnc_Preview * mix) {
    108     return (MixVideoFormatEnc_Preview *) g_object_ref(G_OBJECT(mix));
    109 }
    110 
    111 /*Preview vmethods implementation */
    112 MIX_RESULT mix_videofmtenc_preview_getcaps(MixVideoFormatEnc *mix, GString *msg) {
    113 
    114     /* TODO: add codes for Preview format */
    115 
    116     /* TODO: decide if we need to chainup parent method.
    117      * if we do, the following is the code:
    118      */
    119 
    120     LOG_V( "mix_videofmtenc_preview_getcaps\n");
    121 
    122     if (mix == NULL) {
    123         LOG_E( "mix == NULL\n");
    124         return MIX_RESULT_NULL_PTR;
    125     }
    126 
    127 
    128     if (parent_class->getcaps) {
    129         return parent_class->getcaps(mix, msg);
    130     }
    131     return MIX_RESULT_SUCCESS;
    132 }
    133 
    134 MIX_RESULT mix_videofmtenc_preview_initialize(MixVideoFormatEnc *mix,
    135         MixVideoConfigParamsEnc * config_params_enc,
    136         MixFrameManager * frame_mgr,
    137         MixBufferPool * input_buf_pool,
    138         MixSurfacePool ** surface_pool,
    139         VADisplay va_display ) {
    140 
    141     MIX_RESULT ret = MIX_RESULT_SUCCESS;
    142     MixVideoFormatEnc *parent = NULL;
    143     MixVideoConfigParamsEncPreview * config_params_enc_preview;
    144 
    145     VAStatus va_status = VA_STATUS_SUCCESS;
    146     VASurfaceID * surfaces;
    147 
    148     gint va_max_num_profiles, va_max_num_entrypoints, va_max_num_attribs;
    149     gint va_num_profiles,  va_num_entrypoints;
    150 
    151     VAProfile *va_profiles = NULL;
    152     VAEntrypoint *va_entrypoints = NULL;
    153     VAConfigAttrib va_attrib[2];
    154     guint index;
    155 
    156 
    157     /*frame_mgr and input_buf_pool is reservered for future use*/
    158 
    159     if (mix == NULL || config_params_enc == NULL || va_display == NULL) {
    160         LOG_E(
    161                 "mix == NULL || config_params_enc == NULL || va_display == NULL\n");
    162         return MIX_RESULT_NULL_PTR;
    163     }
    164 
    165     LOG_V( "begin\n");
    166 
    167 
    168     //TODO additional parameter checking
    169 
    170     /* Chainup parent method. */
    171 #if 1
    172     if (parent_class->initialize) {
    173         ret = parent_class->initialize(mix, config_params_enc,
    174                 frame_mgr, input_buf_pool, surface_pool,
    175                 va_display);
    176     }
    177 
    178     if (ret != MIX_RESULT_SUCCESS)
    179     {
    180         return ret;
    181     }
    182 
    183 #endif //disable it currently
    184 
    185     if (MIX_IS_VIDEOFORMATENC_PREVIEW(mix))
    186     {
    187         parent = MIX_VIDEOFORMATENC(&(mix->parent));
    188         MixVideoFormatEnc_Preview *self = MIX_VIDEOFORMATENC_PREVIEW(mix);
    189 
    190         if (MIX_IS_VIDEOCONFIGPARAMSENC_PREVIEW (config_params_enc)) {
    191             config_params_enc_preview =
    192                 MIX_VIDEOCONFIGPARAMSENC_PREVIEW (config_params_enc);
    193         } else {
    194             LOG_V(
    195                     "mix_videofmtenc_preview_initialize:  no preview config params found\n");
    196             return MIX_RESULT_FAIL;
    197         }
    198 
    199         g_mutex_lock(parent->objectlock);
    200 
    201 
    202         LOG_V(
    203                 "Get properities from params done\n");
    204 
    205 
    206     	//display = XOpenDisplay(NULL);
    207      	//va_display = vaGetDisplay (videoencobj->display);
    208 
    209         parent->va_display = va_display;
    210 
    211         LOG_V( "Get Display\n");
    212         LOG_I( "Display = 0x%08x\n",
    213                 (guint)va_display);
    214 
    215         //va_status = vaInitialize(va_display, &va_major_ver, &va_minor_ver);
    216         //g_print ("vaInitialize va_status = %d\n", va_status);
    217 
    218 
    219 #if 0
    220         /* query the vender information, can ignore*/
    221         va_vendor = vaQueryVendorString (va_display);
    222         LOG_I( "Vendor = %s\n",
    223                 va_vendor);
    224 #endif
    225 
    226         /*get the max number for profiles/entrypoints/attribs*/
    227         va_max_num_profiles = vaMaxNumProfiles(va_display);
    228         LOG_I( "va_max_num_profiles = %d\n",
    229                 va_max_num_profiles);
    230 
    231         va_max_num_entrypoints = vaMaxNumEntrypoints(va_display);
    232         LOG_I( "va_max_num_entrypoints = %d\n",
    233                 va_max_num_entrypoints);
    234 
    235         va_max_num_attribs = vaMaxNumConfigAttributes(va_display);
    236         LOG_I( "va_max_num_attribs = %d\n",
    237                 va_max_num_attribs);
    238 
    239         va_profiles = g_malloc(sizeof(VAProfile)*va_max_num_profiles);
    240         va_entrypoints = g_malloc(sizeof(VAEntrypoint)*va_max_num_entrypoints);
    241 
    242         if (va_profiles == NULL || va_entrypoints ==NULL)
    243         {
    244             LOG_E(
    245                     "!va_profiles || !va_entrypoints\n");
    246             g_mutex_unlock(parent->objectlock);
    247             return MIX_RESULT_NO_MEMORY;
    248         }
    249 
    250         LOG_I(
    251                 "va_profiles = 0x%08x\n", (guint)va_profiles);
    252 
    253         LOG_V( "vaQueryConfigProfiles\n");
    254 
    255 
    256         va_status = vaQueryConfigProfiles (va_display, va_profiles, &va_num_profiles);
    257 
    258         if (va_status != VA_STATUS_SUCCESS)
    259         {
    260             LOG_E(
    261                     "Failed to call vaQueryConfigProfiles\n");
    262             g_free(va_profiles);
    263             g_free (va_entrypoints);
    264             g_mutex_unlock(parent->objectlock);
    265             return MIX_RESULT_FAIL;
    266         }
    267 
    268         LOG_V( "vaQueryConfigProfiles Done\n");
    269 
    270 
    271 
    272         /*check whether profile is supported*/
    273         for(index= 0; index < va_num_profiles; index++) {
    274             if(parent->va_profile == va_profiles[index])
    275                 break;
    276         }
    277 
    278         if(index == va_num_profiles)
    279         {
    280             LOG_E( "Profile not supported\n");
    281             g_free(va_profiles);
    282             g_free (va_entrypoints);
    283             g_mutex_unlock(parent->objectlock);
    284             return MIX_RESULT_FAIL;  //Todo, add error handling here
    285         }
    286 
    287         LOG_V( "vaQueryConfigEntrypoints\n");
    288 
    289 
    290         /*Check entry point*/
    291         va_status = vaQueryConfigEntrypoints(va_display,
    292                 parent->va_profile,
    293                 va_entrypoints, &va_num_entrypoints);
    294 
    295         if (va_status != VA_STATUS_SUCCESS)
    296         {
    297             LOG_E(
    298                     "Failed to call vaQueryConfigEntrypoints\n");
    299             g_free(va_profiles);
    300             g_free (va_entrypoints);
    301             g_mutex_unlock(parent->objectlock);
    302             return MIX_RESULT_FAIL;
    303         }
    304 
    305         for (index = 0; index < va_num_entrypoints; index ++) {
    306             if (va_entrypoints[index] == VAEntrypointEncSlice) {
    307                 break;
    308             }
    309         }
    310 
    311         if (index == va_num_entrypoints) {
    312             LOG_E( "Entrypoint not found\n");
    313             g_free(va_profiles);
    314             g_free (va_entrypoints);
    315             g_mutex_unlock(parent->objectlock);
    316             return MIX_RESULT_FAIL;  //Todo, add error handling here
    317         }
    318 
    319 
    320         /*free profiles and entrypoints*/
    321         g_free(va_profiles);
    322         g_free (va_entrypoints);
    323 
    324         va_attrib[0].type = VAConfigAttribRTFormat;
    325         va_attrib[1].type = VAConfigAttribRateControl;
    326 
    327         LOG_V( "vaGetConfigAttributes\n");
    328 
    329         va_status = vaGetConfigAttributes(va_display, parent->va_profile,
    330                 parent->va_entrypoint,
    331                 &va_attrib[0], 2);
    332 
    333         if (va_status != VA_STATUS_SUCCESS)
    334         {
    335             LOG_E(
    336                     "Failed to call vaGetConfigAttributes\n");
    337             g_mutex_unlock(parent->objectlock);
    338             return MIX_RESULT_FAIL;
    339         }
    340 
    341         if ((va_attrib[0].value & parent->va_format) == 0) {
    342             LOG_E( "Matched format not found\n");
    343             g_mutex_unlock(parent->objectlock);
    344             return MIX_RESULT_FAIL;  //Todo, add error handling here
    345         }
    346 
    347 
    348         if ((va_attrib[1].value & parent->va_rcmode) == 0) {
    349             LOG_E( "RC mode not found\n");
    350             g_mutex_unlock(parent->objectlock);
    351             return MIX_RESULT_FAIL;  //Todo, add error handling here
    352         }
    353 
    354         va_attrib[0].value = parent->va_format; //VA_RT_FORMAT_YUV420;
    355         va_attrib[1].value = parent->va_rcmode;
    356 
    357         LOG_V( "======VA Configuration======\n");
    358 
    359         LOG_I( "profile = %d\n",
    360                 parent->va_profile);
    361         LOG_I( "va_entrypoint = %d\n",
    362                 parent->va_entrypoint);
    363         LOG_I( "va_attrib[0].type = %d\n",
    364                 va_attrib[0].type);
    365         LOG_I( "va_attrib[1].type = %d\n",
    366                 va_attrib[1].type);
    367         LOG_I( "va_attrib[0].value (Format) = %d\n",
    368                 va_attrib[0].value);
    369         LOG_I( "va_attrib[1].value (RC mode) = %d\n",
    370                 va_attrib[1].value);
    371 
    372         LOG_V( "vaCreateConfig\n");
    373 
    374         va_status = vaCreateConfig(va_display, parent->va_profile,
    375                 parent->va_entrypoint,
    376                 &va_attrib[0], 2, &(parent->va_config));
    377 
    378         if (va_status != VA_STATUS_SUCCESS)
    379         {
    380             LOG_E( "Failed vaCreateConfig\n");
    381             g_mutex_unlock(parent->objectlock);
    382             return MIX_RESULT_FAIL;
    383         }
    384 
    385         /*TODO: compute the surface number*/
    386         int numSurfaces;
    387 
    388         if (parent->share_buf_mode) {
    389             numSurfaces = 2;
    390         }
    391         else {
    392             numSurfaces = 8;
    393             parent->ci_frame_num = 0;
    394         }
    395 
    396         self->surface_num = numSurfaces + parent->ci_frame_num;
    397 
    398         surfaces = g_malloc(sizeof(VASurfaceID)*numSurfaces);
    399 
    400         if (surfaces == NULL)
    401         {
    402             LOG_E(
    403                     "Failed allocate surface\n");
    404             g_mutex_unlock(parent->objectlock);
    405             return MIX_RESULT_NO_MEMORY;
    406         }
    407 
    408         LOG_V( "vaCreateSurfaces\n");
    409 
    410         va_status = vaCreateSurfaces(va_display, parent->picture_width,
    411                 parent->picture_height, parent->va_format,
    412                 numSurfaces, surfaces);
    413         //TODO check vret and return fail if needed
    414 
    415         if (va_status != VA_STATUS_SUCCESS)
    416         {
    417             LOG_E(
    418                     "Failed vaCreateSurfaces\n");
    419             g_mutex_unlock(parent->objectlock);
    420             return MIX_RESULT_FAIL;
    421         }
    422 
    423         if (parent->share_buf_mode) {
    424 
    425             LOG_V(
    426                     "We are in share buffer mode!\n");
    427             self->ci_shared_surfaces =
    428                 g_malloc(sizeof(VASurfaceID) * parent->ci_frame_num);
    429 
    430             if (self->ci_shared_surfaces == NULL)
    431             {
    432                 LOG_E(
    433                         "Failed allocate shared surface\n");
    434                 g_mutex_unlock(parent->objectlock);
    435                 return MIX_RESULT_NO_MEMORY;
    436             }
    437 
    438             guint index;
    439             for(index = 0; index < parent->ci_frame_num; index++) {
    440 
    441                 LOG_I( "ci_frame_id = %lu\n",
    442                         parent->ci_frame_id[index]);
    443 
    444                 LOG_V(
    445                         "vaCreateSurfaceFromCIFrame\n");
    446 
    447                 va_status = vaCreateSurfaceFromCIFrame(va_display,
    448                         (gulong) (parent->ci_frame_id[index]),
    449                         &self->ci_shared_surfaces[index]);
    450                 if (va_status != VA_STATUS_SUCCESS)
    451                 {
    452                     LOG_E(
    453                             "Failed to vaCreateSurfaceFromCIFrame\n");
    454                     g_mutex_unlock(parent->objectlock);
    455                     return MIX_RESULT_FAIL;
    456                 }
    457             }
    458 
    459             LOG_V(
    460                     "vaCreateSurfaceFromCIFrame Done\n");
    461 
    462         }// if (parent->share_buf_mode)
    463 
    464         self->surfaces = g_malloc(sizeof(VASurfaceID) * self->surface_num);
    465 
    466         if (self->surfaces == NULL)
    467         {
    468             LOG_E(
    469                     "Failed allocate private surface\n");
    470             g_free (surfaces);
    471             g_mutex_unlock(parent->objectlock);
    472             return MIX_RESULT_NO_MEMORY;
    473         }
    474 
    475         if (parent->share_buf_mode) {
    476             /*shared surfaces should be put in pool first,
    477              * because we will get it accoring to CI index*/
    478             for(index = 0; index < parent->ci_frame_num; index++)
    479                 self->surfaces[index] = self->ci_shared_surfaces[index];
    480         }
    481 
    482         for(index = 0; index < numSurfaces; index++) {
    483             self->surfaces[index + parent->ci_frame_num] = surfaces[index];
    484         }
    485 
    486         LOG_V( "assign surface Done\n");
    487         LOG_I( "Created %d libva surfaces\n",
    488                 numSurfaces + parent->ci_frame_num);
    489 
    490 #if 0  //current put this in gst
    491         images = g_malloc(sizeof(VAImage)*numSurfaces);
    492         if (images == NULL)
    493         {
    494             g_mutex_unlock(parent->objectlock);
    495             return MIX_RESULT_FAIL;
    496         }
    497 
    498         for (index = 0; index < numSurfaces; index++) {
    499             //Derive an VAImage from an existing surface.
    500             //The image buffer can then be mapped/unmapped for CPU access
    501             va_status = vaDeriveImage(va_display, surfaces[index],
    502                     &images[index]);
    503         }
    504 #endif
    505 
    506         LOG_V( "mix_surfacepool_new\n");
    507 
    508         parent->surfacepool = mix_surfacepool_new();
    509         if (surface_pool)
    510             *surface_pool = parent->surfacepool;
    511         //which is useful to check before encode
    512 
    513         if (parent->surfacepool == NULL)
    514         {
    515             LOG_E(
    516                     "Failed to mix_surfacepool_new\n");
    517             g_free (surfaces);
    518             g_mutex_unlock(parent->objectlock);
    519             return MIX_RESULT_FAIL;
    520         }
    521 
    522         LOG_V(
    523                 "mix_surfacepool_initialize\n");
    524 
    525         ret = mix_surfacepool_initialize(parent->surfacepool,
    526                 self->surfaces, parent->ci_frame_num + numSurfaces);
    527 
    528         switch (ret)
    529         {
    530             case MIX_RESULT_SUCCESS:
    531                 break;
    532             case MIX_RESULT_ALREADY_INIT:
    533                 //TODO cleanup and/or retry
    534                 g_free (surfaces);
    535                 g_mutex_unlock(parent->objectlock);
    536                 return MIX_RESULT_FAIL;
    537             default:
    538                 break;
    539         }
    540 
    541 
    542         //Initialize and save the VA context ID
    543         LOG_V( "vaCreateContext\n");
    544 
    545         va_status = vaCreateContext(va_display, parent->va_config,
    546                 parent->picture_width, parent->picture_height,
    547                 0, self->surfaces, parent->ci_frame_num + numSurfaces,
    548                 &(parent->va_context));
    549 
    550         LOG_I(
    551                 "Created libva context width %d, height %d\n",
    552                 parent->picture_width, parent->picture_height);
    553 
    554         if (va_status != VA_STATUS_SUCCESS)
    555         {
    556             LOG_E(
    557                     "Failed to vaCreateContext\n");
    558             LOG_I( "va_status = %d\n",
    559                     (guint)va_status);
    560             g_free (surfaces);
    561             g_mutex_unlock(parent->objectlock);
    562             return MIX_RESULT_FAIL;
    563         }
    564 
    565         self->coded_buf_size = 4;
    566 
    567         /*Create coded buffer for output*/
    568         va_status = vaCreateBuffer (va_display, parent->va_context,
    569                 VAEncCodedBufferType,
    570                 self->coded_buf_size,  //
    571                 1, NULL,
    572                 &self->coded_buf);
    573 
    574         if (va_status != VA_STATUS_SUCCESS)
    575         {
    576             LOG_E(
    577                     "Failed to vaCreateBuffer: VAEncCodedBufferType\n");
    578             g_free (surfaces);
    579             g_mutex_unlock(parent->objectlock);
    580             return MIX_RESULT_FAIL;
    581         }
    582 
    583 #ifdef SHOW_SRC
    584         Display * display = XOpenDisplay (NULL);
    585 
    586         LOG_I( "display = 0x%08x\n",
    587                 (guint) display);
    588         win = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0,
    589                 parent->picture_width,  parent->picture_height, 0, 0,
    590                 WhitePixel(display, 0));
    591         XMapWindow(display, win);
    592         XSelectInput(display, win, KeyPressMask | StructureNotifyMask);
    593 
    594         XSync(display, False);
    595         LOG_I( "va_display = 0x%08x\n",
    596                 (guint) va_display);
    597 
    598 #endif /* SHOW_SRC */
    599 
    600         parent->initialized = TRUE;
    601 
    602         g_mutex_unlock(parent->objectlock);
    603         g_free (surfaces);
    604 
    605     }
    606     else
    607     {
    608         LOG_E(
    609                 "not Preview video encode Object\n");
    610         return MIX_RESULT_FAIL;
    611 
    612     }
    613 
    614     LOG_V( "end\n");
    615 
    616     return MIX_RESULT_SUCCESS;
    617 }
    618 
    619 MIX_RESULT mix_videofmtenc_preview_encode(MixVideoFormatEnc *mix, MixBuffer * bufin[],
    620         gint bufincnt, MixIOVec * iovout[], gint iovoutcnt,
    621         MixVideoEncodeParams * encode_params) {
    622 
    623     MIX_RESULT ret = MIX_RESULT_SUCCESS;
    624     MixVideoFormatEnc *parent = NULL;
    625 
    626     LOG_V( "Begin\n");
    627 
    628     /*currenly only support one input and output buffer*/
    629     //TODO: params i
    630 
    631     if (bufincnt != 1 || iovoutcnt != 1) {
    632         LOG_E(
    633                 "buffer count not equel to 1\n");
    634         LOG_E(
    635                 "maybe some exception occurs\n");
    636     }
    637 
    638     if (mix == NULL ||bufin[0] == NULL ||  iovout[0] == NULL) {
    639         LOG_E(
    640                 "!mix || !bufin[0] ||!iovout[0]\n");
    641         return MIX_RESULT_NULL_PTR;
    642     }
    643 
    644     //TODO: encode_params is reserved here for future usage.
    645 
    646     /* TODO: decide if we need to chainup parent method.
    647      *      * * if we do, the following is the code:
    648      * */
    649 
    650 #if 0
    651     if (parent_class->encode) {
    652         return parent_class->encode(mix, bufin, bufincnt, iovout,
    653                 iovoutcnt, encode_params);
    654     }
    655 #endif
    656 
    657     if (MIX_IS_VIDEOFORMATENC_PREVIEW(mix))
    658     {
    659 
    660         parent = MIX_VIDEOFORMATENC(&(mix->parent));
    661         MixVideoFormatEnc_Preview *self = MIX_VIDEOFORMATENC_PREVIEW (mix);
    662 
    663         LOG_V( "Locking\n");
    664         g_mutex_lock(parent->objectlock);
    665 
    666 
    667         //TODO: also we could move some encode Preparation work to here
    668 
    669         LOG_V(
    670                 "mix_videofmtenc_preview_process_encode\n");
    671 
    672         ret = mix_videofmtenc_preview_process_encode (self,
    673                 bufin[0], iovout[0]);
    674         if (ret != MIX_RESULT_SUCCESS)
    675         {
    676             LOG_E(
    677                     "Failed mix_videofmtenc_preview_process_encode\n");
    678             return MIX_RESULT_FAIL;
    679         }
    680 
    681 
    682         LOG_V( "UnLocking\n");
    683 
    684         g_mutex_unlock(parent->objectlock);
    685     }
    686     else
    687     {
    688         LOG_E(
    689                 "not Preview video encode Object\n");
    690         return MIX_RESULT_FAIL;
    691     }
    692 
    693     LOG_V( "end\n");
    694 
    695     return MIX_RESULT_SUCCESS;
    696 }
    697 
    698 MIX_RESULT mix_videofmtenc_preview_flush(MixVideoFormatEnc *mix) {
    699 
    700     //MIX_RESULT ret = MIX_RESULT_SUCCESS;
    701 
    702     LOG_V( "Begin\n");
    703 
    704     if (mix == NULL) {
    705         LOG_E( "mix == NULL\n");
    706         return MIX_RESULT_NULL_PTR;
    707     }
    708 
    709 
    710     /*not chain to parent flush func*/
    711 #if 0
    712     if (parent_class->flush) {
    713         return parent_class->flush(mix, msg);
    714     }
    715 #endif
    716 
    717     MixVideoFormatEnc_Preview *self = MIX_VIDEOFORMATENC_PREVIEW(mix);
    718 
    719     g_mutex_lock(mix->objectlock);
    720 
    721 #if 0
    722     /*unref the current source surface*/
    723     if (self->cur_fame != NULL)
    724     {
    725         mix_videoframe_unref (self->cur_fame);
    726         self->cur_fame = NULL;
    727     }
    728 #endif
    729 
    730     /*unref the reconstructed surface*/
    731     if (self->rec_fame != NULL)
    732     {
    733         mix_videoframe_unref (self->rec_fame);
    734         self->rec_fame = NULL;
    735     }
    736 
    737     /*unref the reference surface*/
    738     if (self->ref_fame != NULL)
    739     {
    740         mix_videoframe_unref (self->ref_fame);
    741         self->ref_fame = NULL;
    742     }
    743 
    744     /*reset the properities*/
    745     self->encoded_frames = 0;
    746     self->pic_skipped = FALSE;
    747     self->is_intra = TRUE;
    748 
    749     g_mutex_unlock(mix->objectlock);
    750 
    751     LOG_V( "end\n");
    752 
    753     return MIX_RESULT_SUCCESS;
    754 }
    755 
    756 MIX_RESULT mix_videofmtenc_preview_eos(MixVideoFormatEnc *mix) {
    757 
    758     /* TODO: add codes for preview */
    759 
    760     /* TODO: decide if we need to chainup parent method.
    761      * if we do, the following is the code:
    762      */
    763 
    764     LOG_V( "\n");
    765 
    766     if (mix == NULL) {
    767         LOG_E( "mix == NULL\n");
    768         return MIX_RESULT_NULL_PTR;
    769     }
    770 
    771     if (parent_class->eos) {
    772         return parent_class->eos(mix);
    773     }
    774     return MIX_RESULT_SUCCESS;
    775 }
    776 
    777 MIX_RESULT mix_videofmtenc_preview_deinitialize(MixVideoFormatEnc *mix) {
    778 
    779     MixVideoFormatEnc *parent = NULL;
    780     VAStatus va_status;
    781 
    782     LOG_V( "Begin\n");
    783 
    784     if (mix == NULL) {
    785         LOG_E( "mix == NULL\n");
    786         return MIX_RESULT_NULL_PTR;
    787     }
    788 
    789     parent = MIX_VIDEOFORMATENC(&(mix->parent));
    790     MixVideoFormatEnc_Preview *self = MIX_VIDEOFORMATENC_PREVIEW(mix);
    791 
    792     LOG_V( "Release frames\n");
    793 
    794     g_mutex_lock(parent->objectlock);
    795 
    796 #if 0
    797     /*unref the current source surface*/
    798     if (self->cur_fame != NULL)
    799     {
    800         mix_videoframe_unref (self->cur_fame);
    801         self->cur_fame = NULL;
    802     }
    803 #endif
    804 
    805     /*unref the reconstructed surface*/
    806     if (self->rec_fame != NULL)
    807     {
    808         mix_videoframe_unref (self->rec_fame);
    809         self->rec_fame = NULL;
    810     }
    811 
    812     /*unref the reference surface*/
    813     if (self->ref_fame != NULL)
    814     {
    815         mix_videoframe_unref (self->ref_fame);
    816         self->ref_fame = NULL;
    817     }
    818 
    819     LOG_V( "Release surfaces\n");
    820 
    821     if (self->ci_shared_surfaces)
    822     {
    823         g_free (self->ci_shared_surfaces);
    824         self->ci_shared_surfaces = NULL;
    825     }
    826 
    827     if (self->surfaces)
    828     {
    829         g_free (self->surfaces);
    830         self->surfaces = NULL;
    831     }
    832 
    833     LOG_V( "vaDestroyContext\n");
    834 
    835     va_status = vaDestroyContext (parent->va_display, parent->va_context);
    836     if (va_status != VA_STATUS_SUCCESS)
    837     {
    838         LOG_E(
    839                 "Failed vaDestroyContext\n");
    840         g_mutex_unlock(parent->objectlock);
    841         return MIX_RESULT_FAIL;
    842     }
    843 
    844     LOG_V( "vaDestroyConfig\n");
    845 
    846     va_status = vaDestroyConfig (parent->va_display, parent->va_config);
    847     if (va_status != VA_STATUS_SUCCESS)
    848     {
    849         LOG_E(
    850                 "Failed vaDestroyConfig\n");
    851         g_mutex_unlock(parent->objectlock);
    852         return MIX_RESULT_FAIL;
    853     }
    854 
    855     parent->initialized = TRUE;
    856 
    857     g_mutex_unlock(parent->objectlock);
    858 
    859 #if 1
    860     if (parent_class->deinitialize) {
    861         return parent_class->deinitialize(mix);
    862     }
    863 #endif
    864 
    865     //Most stuff is cleaned up in parent_class->finalize()
    866 
    867     LOG_V( "end\n");
    868 
    869     return MIX_RESULT_SUCCESS;
    870 }
    871 
    872 
    873 MIX_RESULT mix_videofmtenc_preview_process_encode (MixVideoFormatEnc_Preview *mix,
    874         MixBuffer * bufin, MixIOVec * iovout)
    875 {
    876 
    877     MIX_RESULT ret = MIX_RESULT_SUCCESS;
    878     VAStatus va_status = VA_STATUS_SUCCESS;
    879     VADisplay va_display = NULL;
    880     VAContextID va_context;
    881     gulong surface = 0;
    882     guint16 width, height;
    883 
    884     //MixVideoFrame *  tmp_fame;
    885     //guint8 *buf;
    886 
    887     if ((mix == NULL) || (bufin == NULL) || (iovout == NULL)) {
    888         LOG_E(
    889                 "mix == NUL) || bufin == NULL || iovout == NULL\n");
    890         return MIX_RESULT_NULL_PTR;
    891     }
    892 
    893     LOG_V( "Begin\n");
    894 
    895     if (MIX_IS_VIDEOFORMATENC_PREVIEW(mix))
    896     {
    897 
    898         MixVideoFormatEnc *parent = MIX_VIDEOFORMATENC(&(mix->parent));
    899 
    900         va_display = parent->va_display;
    901         va_context = parent->va_context;
    902         width = parent->picture_width;
    903         height = parent->picture_height;
    904 
    905 
    906         LOG_I( "encoded_frames = %d\n",
    907                 mix->encoded_frames);
    908         LOG_I( "is_intra = %d\n",
    909                 mix->is_intra);
    910         LOG_I( "ci_frame_id = 0x%08x\n",
    911                 (guint) parent->ci_frame_id);
    912 
    913         LOG_V(
    914                 "Get Surface from the pool\n");
    915 
    916         /*current we use one surface for source data,
    917          * one for reference and one for reconstructed*/
    918         /*TODO, could be refine here*/
    919 
    920         if (!parent->share_buf_mode) {
    921             LOG_V(
    922                     "We are NOT in share buffer mode\n");
    923 
    924             if (mix->ref_fame == NULL)
    925             {
    926                 ret = mix_surfacepool_get(parent->surfacepool, &mix->ref_fame);
    927                 if (ret != MIX_RESULT_SUCCESS)  //#ifdef SLEEP_SURFACE not used
    928                 {
    929                     LOG_E(
    930                             "Failed to mix_surfacepool_get\n");
    931                     return MIX_RESULT_FAIL;
    932                 }
    933             }
    934 
    935             if (mix->rec_fame == NULL)
    936             {
    937                 ret = mix_surfacepool_get(parent->surfacepool, &mix->rec_fame);
    938                 if (ret != MIX_RESULT_SUCCESS)
    939                 {
    940                     LOG_E(
    941                             "Failed to mix_surfacepool_get\n");
    942                     return MIX_RESULT_FAIL;
    943                 }
    944             }
    945 
    946             if (parent->need_display) {
    947                 mix->cur_fame = NULL;
    948             }
    949 
    950             if (mix->cur_fame == NULL)
    951             {
    952                 ret = mix_surfacepool_get(parent->surfacepool, &mix->cur_fame);
    953                 if (ret != MIX_RESULT_SUCCESS)
    954                 {
    955                     LOG_E(
    956                             "Failed to mix_surfacepool_get\n");
    957                     return MIX_RESULT_FAIL;
    958                 }
    959             }
    960 
    961             LOG_V( "Get Surface Done\n");
    962 
    963 
    964             VAImage src_image;
    965             guint8 *pvbuf;
    966             guint8 *dst_y;
    967             guint8 *dst_uv;
    968             int i,j;
    969 
    970             LOG_V(
    971                     "map source data to surface\n");
    972 
    973             ret = mix_videoframe_get_frame_id(mix->cur_fame, &surface);
    974             if (ret != MIX_RESULT_SUCCESS)
    975             {
    976                 LOG_E(
    977                         "Failed to mix_videoframe_get_frame_id\n");
    978                 return MIX_RESULT_FAIL;
    979             }
    980 
    981 
    982             LOG_I(
    983                     "surface id = 0x%08x\n", (guint) surface);
    984 
    985             va_status = vaDeriveImage(va_display, surface, &src_image);
    986             //need to destroy
    987 
    988             if (va_status != VA_STATUS_SUCCESS)
    989             {
    990                 LOG_E(
    991                         "Failed to vaDeriveImage\n");
    992                 return MIX_RESULT_FAIL;
    993             }
    994 
    995             VAImage *image = &src_image;
    996 
    997             LOG_V( "vaDeriveImage Done\n");
    998 
    999 
   1000             va_status = vaMapBuffer (va_display, image->buf, (void **)&pvbuf);
   1001             if (va_status != VA_STATUS_SUCCESS)
   1002             {
   1003                 LOG_E( "Failed to vaMapBuffer\n");
   1004                 return MIX_RESULT_FAIL;
   1005             }
   1006 
   1007             LOG_V(
   1008                     "vaImage information\n");
   1009             LOG_I(
   1010                     "image->pitches[0] = %d\n", image->pitches[0]);
   1011             LOG_I(
   1012                     "image->pitches[1] = %d\n", image->pitches[1]);
   1013             LOG_I(
   1014                     "image->offsets[0] = %d\n", image->offsets[0]);
   1015             LOG_I(
   1016                     "image->offsets[1] = %d\n", image->offsets[1]);
   1017             LOG_I(
   1018                     "image->num_planes = %d\n", image->num_planes);
   1019             LOG_I(
   1020                     "image->width = %d\n", image->width);
   1021             LOG_I(
   1022                     "image->height = %d\n", image->height);
   1023 
   1024             LOG_I(
   1025                     "input buf size = %d\n", bufin->size);
   1026 
   1027             guint8 *inbuf = bufin->data;
   1028 
   1029             /*need to convert YUV420 to NV12*/
   1030             dst_y = pvbuf +image->offsets[0];
   1031 
   1032             for (i = 0; i < height; i ++) {
   1033                 memcpy (dst_y, inbuf + i * width, width);
   1034                 dst_y += image->pitches[0];
   1035             }
   1036 
   1037             dst_uv = pvbuf + image->offsets[1];
   1038 
   1039             for (i = 0; i < height / 2; i ++) {
   1040                 for (j = 0; j < width; j+=2) {
   1041                     dst_uv [j] = inbuf [width * height + i * width / 2 + j / 2];
   1042                     dst_uv [j + 1] =
   1043                         inbuf [width * height * 5 / 4 + i * width / 2 + j / 2];
   1044                 }
   1045                 dst_uv += image->pitches[1];
   1046             }
   1047 
   1048             vaUnmapBuffer(va_display, image->buf);
   1049             if (va_status != VA_STATUS_SUCCESS)
   1050             {
   1051                 LOG_E(
   1052                         "Failed to vaUnmapBuffer\n");
   1053                 return MIX_RESULT_FAIL;
   1054             }
   1055 
   1056             va_status = vaDestroyImage(va_display, src_image.image_id);
   1057             if (va_status != VA_STATUS_SUCCESS)
   1058             {
   1059                 LOG_E(
   1060                         "Failed to vaDestroyImage\n");
   1061                 return MIX_RESULT_FAIL;
   1062             }
   1063 
   1064             LOG_V(
   1065                     "Map source data to surface done\n");
   1066 
   1067         }
   1068 
   1069         else {//if (!parent->share_buf_mode)
   1070 
   1071             MixVideoFrame * frame = mix_videoframe_new();
   1072 
   1073             if (mix->ref_fame == NULL)
   1074             {
   1075                 ret = mix_videoframe_set_ci_frame_idx (frame, mix->surface_num - 1);
   1076 
   1077                 ret = mix_surfacepool_get_frame_with_ci_frameidx
   1078                     (parent->surfacepool, &mix->ref_fame, frame);
   1079                 if (ret != MIX_RESULT_SUCCESS)  //#ifdef SLEEP_SURFACE not used
   1080                 {
   1081                     LOG_E(
   1082                             "get reference surface from pool failed\n");
   1083                     return MIX_RESULT_FAIL;
   1084                 }
   1085             }
   1086 
   1087             if (mix->rec_fame == NULL)
   1088             {
   1089                 ret = mix_videoframe_set_ci_frame_idx (frame, mix->surface_num - 2);
   1090 
   1091                 ret = mix_surfacepool_get_frame_with_ci_frameidx
   1092                     (parent->surfacepool, &mix->rec_fame, frame);
   1093 
   1094                 if (ret != MIX_RESULT_SUCCESS)
   1095                 {
   1096                     LOG_E(
   1097                             "get recontructed surface from pool failed\n");
   1098                     return MIX_RESULT_FAIL;
   1099                 }
   1100             }
   1101 
   1102             //mix_videoframe_unref (mix->cur_fame);
   1103 
   1104             if (parent->need_display) {
   1105                 mix->cur_fame = NULL;
   1106             }
   1107 
   1108             if (mix->cur_fame == NULL)
   1109             {
   1110                 guint ci_idx;
   1111                 memcpy (&ci_idx, bufin->data, bufin->size);
   1112 
   1113                 LOG_I(
   1114                         "surface_num = %d\n", mix->surface_num);
   1115                 LOG_I(
   1116                         "ci_frame_idx = %d\n", ci_idx);
   1117 
   1118                 if (ci_idx > mix->surface_num - 2) {
   1119                     LOG_E(
   1120                             "the CI frame idx is too bigger than CI frame number\n");
   1121                     return MIX_RESULT_FAIL;
   1122                 }
   1123 
   1124 
   1125                 ret = mix_videoframe_set_ci_frame_idx (frame, ci_idx);
   1126 
   1127                 ret = mix_surfacepool_get_frame_with_ci_frameidx
   1128                     (parent->surfacepool, &mix->cur_fame, frame);
   1129 
   1130                 if (ret != MIX_RESULT_SUCCESS)
   1131                 {
   1132                     LOG_E(
   1133                             "get current working surface from pool failed\n");
   1134                     return MIX_RESULT_FAIL;
   1135                 }
   1136             }
   1137 
   1138             ret = mix_videoframe_get_frame_id(mix->cur_fame, &surface);
   1139 
   1140         }
   1141 
   1142         LOG_V( "vaBeginPicture\n");
   1143         LOG_I( "va_context = 0x%08x\n",(guint)va_context);
   1144         LOG_I( "surface = 0x%08x\n",(guint)surface);
   1145         LOG_I( "va_display = 0x%08x\n",(guint)va_display);
   1146 
   1147         iovout->data_size = 4;
   1148         iovout->data = g_malloc (iovout->data_size);
   1149         if (iovout->data == NULL) {
   1150             return MIX_RESULT_NO_MEMORY;
   1151         }
   1152 
   1153         memset (iovout->data, 0, iovout->data_size);
   1154 
   1155         iovout->buffer_size = iovout->data_size;
   1156 
   1157 
   1158         if (parent->need_display) {
   1159             ret = mix_framemanager_enqueue(parent->framemgr, mix->cur_fame);
   1160             if (ret != MIX_RESULT_SUCCESS)
   1161             {
   1162                 LOG_E(
   1163                         "Failed mix_framemanager_enqueue\n");
   1164                 return MIX_RESULT_FAIL;
   1165             }
   1166         }
   1167 
   1168 
   1169         if (!(parent->need_display)) {
   1170             mix_videoframe_unref (mix->cur_fame);
   1171             mix->cur_fame = NULL;
   1172         }
   1173 
   1174         mix->encoded_frames ++;
   1175     }
   1176     else
   1177     {
   1178         LOG_E(
   1179                 "not Preview video encode Object\n");
   1180         return MIX_RESULT_FAIL;
   1181     }
   1182 
   1183 
   1184     LOG_V( "end\n");
   1185 
   1186     return MIX_RESULT_SUCCESS;
   1187 }
   1188