Home | History | Annotate | Download | only in src
      1 /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
      2  *
      3  * Redistribution and use in source and binary forms, with or without
      4  * modification, are permitted provided that the following conditions are
      5  * met:
      6  *     * Redistributions of source code must retain the above copyright
      7  *       notice, this list of conditions and the following disclaimer.
      8  *     * Redistributions in binary form must reproduce the above
      9  *       copyright notice, this list of conditions and the following
     10  *       disclaimer in the documentation and/or other materials provided
     11  *       with the distribution.
     12  *     * Neither the name of The Linux Foundation nor the names of its
     13  *       contributors may be used to endorse or promote products derived
     14  *       from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  *
     28  */
     29 
     30 // To remove
     31 #include <utils/Log.h>
     32 
     33 // System dependencies
     34 #include <errno.h>
     35 #include <fcntl.h>
     36 #include <poll.h>
     37 #include <pthread.h>
     38 #include <sys/ioctl.h>
     39 #include <sys/prctl.h>
     40 #include <sys/stat.h>
     41 #include <sys/types.h>
     42 
     43 // Camera dependencies
     44 #include "img_common.h"
     45 #include "img_comp.h"
     46 #include "img_comp_factory.h"
     47 #include "img_buffer.h"
     48 #include "lib2d.h"
     49 #include "mm_lib2d.h"
     50 #include "img_meta.h"
     51 
     52 /** lib2d_job_private_info
     53  * @jobid: Job id of this process request
     54  * @userdata: Client userdata that will be passed on callback
     55  * @lib2d_client_cb: Application's callback function pointer
     56  *     which will be called upon completion of current job.
     57 **/
     58 typedef struct lib2d_job_private_info_t {
     59   int   jobid;
     60   void *userdata;
     61   lib2d_error (*lib2d_client_cb) (void *userdata, int jobid);
     62 } lib2d_job_private_info;
     63 
     64 /** img_lib_t
     65  * @ptr: handle to imglib library
     66  * @img_core_get_comp: function pointer for img_core_get_comp
     67  * @img_wait_for_completion: function pointer for img_wait_for_completion
     68 **/
     69 typedef struct {
     70   void *ptr;
     71   int (*img_core_get_comp) (img_comp_role_t role, char *name,
     72     img_core_ops_t *p_ops);
     73   int (*img_wait_for_completion) (pthread_cond_t *p_cond,
     74     pthread_mutex_t *p_mutex, int32_t ms);
     75 } img_lib_t;
     76 
     77 /** mm_lib2d_obj
     78  * @core_ops: image core ops structure handle
     79  * @comp: component structure handle
     80  * @comp_mode: underlying component mode
     81  * @lib2d_mode: lib2d mode requested by client
     82  * @img_lib: imglib library, function ptrs handle
     83  * @mutex: lib2d mutex used for synchronization
     84  * @cond: librd cond used for synchronization
     85 **/
     86 typedef struct mm_lib2d_obj_t {
     87   img_core_ops_t      core_ops;
     88   img_component_ops_t comp;
     89   img_comp_mode_t     comp_mode;
     90   lib2d_mode          lib2d_mode;
     91   img_lib_t           img_lib;
     92   pthread_mutex_t     mutex;
     93   pthread_cond_t      cond;
     94 } mm_lib2d_obj;
     95 
     96 
     97 /**
     98  * Function: lib2d_event_handler
     99  *
    100  * Description: Event handler. All the component events
    101  *     are received here.
    102  *
    103  * Input parameters:
    104  *   p_appdata - lib2d test object
    105  *   p_event - pointer to the event
    106  *
    107  * Return values:
    108  *   IMG_SUCCESS
    109  *   IMG_ERR_INVALID_INPUT
    110  *
    111  * Notes: none
    112  **/
    113 int lib2d_event_handler(void* p_appdata, img_event_t *p_event)
    114 {
    115   mm_lib2d_obj *lib2d_obj = (mm_lib2d_obj *)p_appdata;
    116 
    117   if ((NULL == p_event) || (NULL == p_appdata)) {
    118     LOGE("invalid event");
    119     return IMG_ERR_INVALID_INPUT;
    120   }
    121 
    122   LOGD("type %d", p_event->type);
    123 
    124   switch (p_event->type) {
    125     case QIMG_EVT_DONE:
    126       pthread_cond_signal(&lib2d_obj->cond);
    127       break;
    128     default:;
    129   }
    130   return IMG_SUCCESS;
    131 }
    132 
    133 /**
    134  * Function: lib2d_callback_handler
    135  *
    136  * Description: Callback handler. Registered with Component
    137  *     on IMG_COMP_INIT. Will be called when processing
    138  *     of current request is completed. If component running in
    139  *     async mode, this is where client will know the execution
    140  *     is finished for in, out frames.
    141  *
    142  * Input parameters:
    143  *   p_appdata - lib2d test object
    144  *   p_in_frame - pointer to input frame
    145  *   p_out_frame - pointer to output frame
    146  *   p_meta - pointer to meta data
    147  *
    148  * Return values:
    149  *   IMG_SUCCESS
    150  *   IMG_ERR_GENERAL
    151  *
    152  * Notes: none
    153  **/
    154 int lib2d_callback_handler(void *userdata, img_frame_t *p_in_frame,
    155   img_frame_t *p_out_frame, img_meta_t *p_meta)
    156 {
    157   lib2d_job_private_info *job_info = NULL;
    158 
    159   if (NULL == userdata) {
    160     LOGE("invalid event");
    161     return IMG_ERR_INVALID_INPUT;
    162   }
    163 
    164   // assert(p_in_frame->private_data == p_out_frame->private_data);
    165 
    166   job_info = (lib2d_job_private_info *)p_in_frame->private_data;
    167   if (job_info->lib2d_client_cb != NULL) {
    168     job_info->lib2d_client_cb(job_info->userdata, job_info->jobid);
    169   }
    170 
    171   free(p_in_frame->private_data);
    172   free(p_in_frame);
    173   free(p_out_frame);
    174   free(p_meta);
    175 
    176   return IMG_SUCCESS;
    177 }
    178 
    179 /**
    180  * Function: lib2d_fill_img_frame
    181  *
    182  * Description: Setup img_frame_t for given buffer
    183  *
    184  * Input parameters:
    185  *   p_frame - pointer to img_frame_t that needs to be setup
    186  *   lib2d_buffer - pointer to input buffer
    187  *   jobid - job id
    188  *
    189  * Return values:
    190  *   MM_LIB2D_SUCCESS
    191  *   MM_LIB2D_ERR_GENERAL
    192  *
    193  * Notes: none
    194  **/
    195 lib2d_error lib2d_fill_img_frame(img_frame_t *p_frame,
    196   mm_lib2d_buffer* lib2d_buffer, int jobid)
    197 {
    198   // use job id for now
    199   p_frame->frame_cnt = jobid;
    200   p_frame->idx       = jobid;
    201   p_frame->frame_id  = jobid;
    202 
    203   if (lib2d_buffer->buffer_type == MM_LIB2D_BUFFER_TYPE_RGB) {
    204     mm_lib2d_rgb_buffer *rgb_buffer = &lib2d_buffer->rgb_buffer;
    205 
    206     p_frame->info.num_planes = 1;
    207     p_frame->info.width      = rgb_buffer->width;
    208     p_frame->info.height     = rgb_buffer->height;
    209 
    210     p_frame->frame[0].plane_cnt = 1;
    211     p_frame->frame[0].plane[0].plane_type = PLANE_ARGB;
    212     p_frame->frame[0].plane[0].addr       = rgb_buffer->buffer;
    213     p_frame->frame[0].plane[0].stride     = rgb_buffer->stride;
    214     p_frame->frame[0].plane[0].length     = (rgb_buffer->stride *
    215                                              rgb_buffer->height);
    216     p_frame->frame[0].plane[0].fd         = rgb_buffer->fd;
    217     p_frame->frame[0].plane[0].height     = rgb_buffer->height;
    218     p_frame->frame[0].plane[0].width      = rgb_buffer->width;
    219     p_frame->frame[0].plane[0].offset     = 0;
    220     p_frame->frame[0].plane[0].scanline   = rgb_buffer->height;
    221   } else if (lib2d_buffer->buffer_type == MM_LIB2D_BUFFER_TYPE_YUV) {
    222     mm_lib2d_yuv_buffer *yuv_buffer = &lib2d_buffer->yuv_buffer;
    223 
    224     p_frame->info.num_planes = 2;
    225     p_frame->info.width      = yuv_buffer->width;
    226     p_frame->info.height     = yuv_buffer->height;
    227 
    228     p_frame->frame[0].plane_cnt = 2;
    229     p_frame->frame[0].plane[0].plane_type = PLANE_Y;
    230     p_frame->frame[0].plane[0].addr       = yuv_buffer->plane0;
    231     p_frame->frame[0].plane[0].stride     = yuv_buffer->stride0;
    232     p_frame->frame[0].plane[0].length     = (yuv_buffer->stride0 *
    233                                              yuv_buffer->height);
    234     p_frame->frame[0].plane[0].fd         = yuv_buffer->fd;
    235     p_frame->frame[0].plane[0].height     = yuv_buffer->height;
    236     p_frame->frame[0].plane[0].width      = yuv_buffer->width;
    237     p_frame->frame[0].plane[0].offset     = 0;
    238     p_frame->frame[0].plane[0].scanline   = yuv_buffer->height;
    239 
    240     if (yuv_buffer->format == CAM_FORMAT_YUV_420_NV12) {
    241       p_frame->frame[0].plane[1].plane_type = PLANE_CB_CR;
    242     } else if(yuv_buffer->format == CAM_FORMAT_YUV_420_NV21) {
    243       p_frame->frame[0].plane[1].plane_type = PLANE_CR_CB;
    244     }
    245     p_frame->frame[0].plane[1].addr       = yuv_buffer->plane1;
    246     p_frame->frame[0].plane[1].stride     = yuv_buffer->stride1;
    247     p_frame->frame[0].plane[1].length     = (yuv_buffer->stride1 *
    248                                              yuv_buffer->height / 2);
    249     p_frame->frame[0].plane[1].fd         = yuv_buffer->fd;
    250     p_frame->frame[0].plane[1].height     = yuv_buffer->height;
    251     p_frame->frame[0].plane[1].width      = yuv_buffer->width;
    252     p_frame->frame[0].plane[1].offset     = 0;
    253     p_frame->frame[0].plane[1].scanline   = yuv_buffer->height;
    254   } else {
    255     return MM_LIB2D_ERR_GENERAL;
    256   }
    257 
    258   return MM_LIB2D_SUCCESS;
    259 }
    260 
    261 /**
    262  * Function: mm_lib2d_init
    263  *
    264  * Description: Initialization function for Lib2D. src_format, dst_format
    265  *     are hints to the underlying component to initialize.
    266  *
    267  * Input parameters:
    268  *   mode - Mode (sync/async) in which App wants lib2d to run.
    269  *   src_format - source surface format
    270  *   dst_format - Destination surface format
    271  *   my_obj - handle that will be returned on succesful Init. App has to
    272  *       call other lib2d functions by passing this handle.
    273  *
    274  * Return values:
    275  *   MM_LIB2D_SUCCESS
    276  *   MM_LIB2D_ERR_MEMORY
    277  *   MM_LIB2D_ERR_BAD_PARAM
    278  *   MM_LIB2D_ERR_GENERAL
    279  *
    280  * Notes: none
    281  **/
    282 
    283 lib2d_error mm_lib2d_init(lib2d_mode mode, cam_format_t src_format,
    284   cam_format_t dst_format, void **my_obj)
    285 {
    286   int32_t              rc         = IMG_SUCCESS;
    287   mm_lib2d_obj        *lib2d_obj  = NULL;
    288   img_core_ops_t      *p_core_ops = NULL;
    289   img_component_ops_t *p_comp     = NULL;
    290 
    291   if (my_obj == NULL) {
    292     return MM_LIB2D_ERR_BAD_PARAM;
    293   }
    294 
    295   // validate src_format, dst_format to check whether we support these.
    296   // Currently support NV21 to ARGB conversions only. Others not tested.
    297   if ((src_format != CAM_FORMAT_YUV_420_NV21) ||
    298     (dst_format != CAM_FORMAT_8888_ARGB)) {
    299     LOGE("Formats conversion from %d to %d not supported",
    300         src_format, dst_format);
    301   }
    302 
    303   lib2d_obj = malloc(sizeof(mm_lib2d_obj));
    304   if (lib2d_obj == NULL) {
    305     return MM_LIB2D_ERR_MEMORY;
    306   }
    307 
    308   // Open libmmcamera_imglib
    309   lib2d_obj->img_lib.ptr = dlopen("libmmcamera_imglib.so", RTLD_NOW);
    310   if (!lib2d_obj->img_lib.ptr) {
    311     LOGE("ERROR: couldn't dlopen libmmcamera_imglib.so: %s",
    312        dlerror());
    313     goto FREE_LIB2D_OBJ;
    314   }
    315 
    316   /* Get function pointer for functions supported by C2D */
    317   *(void **)&lib2d_obj->img_lib.img_core_get_comp =
    318       dlsym(lib2d_obj->img_lib.ptr, "img_core_get_comp");
    319   *(void **)&lib2d_obj->img_lib.img_wait_for_completion =
    320       dlsym(lib2d_obj->img_lib.ptr, "img_wait_for_completion");
    321 
    322   /* Validate function pointers */
    323   if ((lib2d_obj->img_lib.img_core_get_comp == NULL) ||
    324     (lib2d_obj->img_lib.img_wait_for_completion == NULL)) {
    325     LOGE(" ERROR mapping symbols from libc2d2.so");
    326     goto FREE_LIB2D_OBJ;
    327   }
    328 
    329   p_core_ops = &lib2d_obj->core_ops;
    330   p_comp     = &lib2d_obj->comp;
    331 
    332   pthread_mutex_init(&lib2d_obj->mutex, NULL);
    333   pthread_cond_init(&lib2d_obj->cond, NULL);
    334 
    335   rc = lib2d_obj->img_lib.img_core_get_comp(IMG_COMP_LIB2D,
    336     "qti.lib2d", p_core_ops);
    337   if (rc != IMG_SUCCESS) {
    338     LOGE("rc %d", rc);
    339     goto FREE_LIB2D_OBJ;
    340   }
    341 
    342   rc = IMG_COMP_LOAD(p_core_ops, NULL);
    343   if (rc != IMG_SUCCESS) {
    344     LOGE("rc %d", rc);
    345     goto FREE_LIB2D_OBJ;
    346   }
    347 
    348   rc = IMG_COMP_CREATE(p_core_ops, p_comp);
    349   if (rc != IMG_SUCCESS) {
    350     LOGE("rc %d", rc);
    351     goto COMP_UNLOAD;
    352   }
    353 
    354   rc = IMG_COMP_INIT(p_comp, (void *)lib2d_obj, lib2d_callback_handler);
    355   if (rc != IMG_SUCCESS) {
    356     LOGE("rc %d", rc);
    357     goto COMP_UNLOAD;
    358   }
    359 
    360   rc = IMG_COMP_SET_CB(p_comp, lib2d_event_handler);
    361   if (rc != IMG_SUCCESS) {
    362     LOGE("rc %d", rc);
    363     goto COMP_DEINIT;
    364   }
    365 
    366   lib2d_obj->lib2d_mode = mode;
    367   img_comp_mode_t comp_mode;
    368   if (lib2d_obj->lib2d_mode == MM_LIB2D_SYNC_MODE) {
    369     comp_mode = IMG_SYNC_MODE;
    370   } else {
    371     comp_mode = IMG_ASYNC_MODE;
    372   }
    373 
    374   // Set source format
    375   rc = IMG_COMP_SET_PARAM(p_comp, QLIB2D_SOURCE_FORMAT, (void *)&src_format);
    376   if (rc != IMG_SUCCESS) {
    377     LOGE("rc %d", rc);
    378     goto COMP_DEINIT;
    379   }
    380 
    381   // Set destination format
    382   rc = IMG_COMP_SET_PARAM(p_comp, QLIB2D_DESTINATION_FORMAT,
    383     (void *)&dst_format);
    384   if (rc != IMG_SUCCESS) {
    385     LOGE("rc %d", rc);
    386     goto COMP_DEINIT;
    387   }
    388 
    389   // Try setting the required mode.
    390   rc = IMG_COMP_SET_PARAM(p_comp, QIMG_PARAM_MODE, (void *)&comp_mode);
    391   if (rc != IMG_SUCCESS) {
    392     LOGE("rc %d", rc);
    393     goto COMP_DEINIT;
    394   }
    395 
    396   // Get the mode to make sure whether the component is really running
    397   // in the mode what we set.
    398   rc = IMG_COMP_GET_PARAM(p_comp, QIMG_PARAM_MODE,
    399     (void *)&lib2d_obj->comp_mode);
    400   if (rc != IMG_SUCCESS) {
    401     LOGE("rc %d", rc);
    402     goto COMP_DEINIT;
    403   }
    404 
    405   if (comp_mode != lib2d_obj->comp_mode) {
    406     LOGD("Component is running in %d mode",
    407       lib2d_obj->comp_mode);
    408   }
    409 
    410   *my_obj = (void *)lib2d_obj;
    411 
    412   return MM_LIB2D_SUCCESS;
    413 
    414 COMP_DEINIT :
    415   rc = IMG_COMP_DEINIT(p_comp);
    416   if (rc != IMG_SUCCESS) {
    417     LOGE("rc %d", rc);
    418     return MM_LIB2D_ERR_GENERAL;
    419   }
    420 
    421 COMP_UNLOAD :
    422   rc = IMG_COMP_UNLOAD(p_core_ops);
    423   if (rc != IMG_SUCCESS) {
    424     LOGE("rc %d", rc);
    425     return MM_LIB2D_ERR_GENERAL;
    426   }
    427 
    428 FREE_LIB2D_OBJ :
    429   free(lib2d_obj);
    430   return MM_LIB2D_ERR_GENERAL;
    431 }
    432 
    433 /**
    434  * Function: mm_lib2d_deinit
    435  *
    436  * Description: De-Initialization function for Lib2D
    437  *
    438  * Input parameters:
    439  *   lib2d_obj_handle - handle tto the lib2d object
    440  *
    441  * Return values:
    442  *   MM_LIB2D_SUCCESS
    443  *   MM_LIB2D_ERR_GENERAL
    444  *
    445  * Notes: none
    446  **/
    447 lib2d_error mm_lib2d_deinit(void *lib2d_obj_handle)
    448 {
    449   mm_lib2d_obj        *lib2d_obj  = (mm_lib2d_obj *)lib2d_obj_handle;
    450   int                  rc         = IMG_SUCCESS;
    451   img_core_ops_t      *p_core_ops = &lib2d_obj->core_ops;
    452   img_component_ops_t *p_comp     = &lib2d_obj->comp;
    453 
    454   rc = IMG_COMP_DEINIT(p_comp);
    455   if (rc != IMG_SUCCESS) {
    456     LOGE("rc %d", rc);
    457     return MM_LIB2D_ERR_GENERAL;
    458   }
    459 
    460   rc = IMG_COMP_UNLOAD(p_core_ops);
    461   if (rc != IMG_SUCCESS) {
    462     LOGE("rc %d", rc);
    463     return MM_LIB2D_ERR_GENERAL;
    464   }
    465 
    466   dlclose(lib2d_obj->img_lib.ptr);
    467   free(lib2d_obj);
    468 
    469   return MM_LIB2D_SUCCESS;
    470 }
    471 
    472 /**
    473  * Function: mm_lib2d_start_job
    474  *
    475  * Description: Start executing the job
    476  *
    477  * Input parameters:
    478  *   lib2d_obj_handle - handle tto the lib2d object
    479  *   src_buffer - pointer to the source buffer
    480  *   dst_buffer - pointer to the destination buffer
    481  *   jobid - job id of this request
    482  *   userdata - userdata that will be pass through callback function
    483  *   cb - callback function that will be called on completion of this job
    484  *   rotation - rotation to be applied
    485  *
    486  * Return values:
    487  *   MM_LIB2D_SUCCESS
    488  *   MM_LIB2D_ERR_MEMORY
    489  *   MM_LIB2D_ERR_GENERAL
    490  *
    491  * Notes: none
    492  **/
    493 lib2d_error mm_lib2d_start_job(void *lib2d_obj_handle,
    494   mm_lib2d_buffer* src_buffer, mm_lib2d_buffer* dst_buffer,
    495   int jobid, void *userdata, lib2d_client_cb cb, uint32_t rotation)
    496 {
    497   mm_lib2d_obj        *lib2d_obj  = (mm_lib2d_obj *)lib2d_obj_handle;
    498   int                  rc         = IMG_SUCCESS;
    499   img_component_ops_t *p_comp     = &lib2d_obj->comp;
    500 
    501   img_frame_t *p_in_frame = malloc(sizeof(img_frame_t));
    502   if (p_in_frame == NULL) {
    503     return MM_LIB2D_ERR_MEMORY;
    504   }
    505 
    506   img_frame_t *p_out_frame = malloc(sizeof(img_frame_t));
    507   if (p_out_frame == NULL) {
    508     free(p_in_frame);
    509     return MM_LIB2D_ERR_MEMORY;
    510   }
    511 
    512   img_meta_t *p_meta = malloc(sizeof(img_meta_t));
    513   if (p_meta == NULL) {
    514     free(p_in_frame);
    515     free(p_out_frame);
    516     return MM_LIB2D_ERR_MEMORY;
    517   }
    518 
    519   lib2d_job_private_info *p_job_info = malloc(sizeof(lib2d_job_private_info));
    520   if (p_out_frame == NULL) {
    521     free(p_in_frame);
    522     free(p_out_frame);
    523     free(p_meta);
    524     return MM_LIB2D_ERR_MEMORY;
    525   }
    526 
    527   memset(p_in_frame,  0x0, sizeof(img_frame_t));
    528   memset(p_out_frame, 0x0, sizeof(img_frame_t));
    529   memset(p_meta, 0x0, sizeof(img_meta_t));
    530   memset(p_job_info,  0x0, sizeof(lib2d_job_private_info));
    531 
    532   // Fill up job info private data structure that can be used in callback to
    533   // inform back to the client.
    534   p_job_info->jobid           = jobid;
    535   p_job_info->userdata        = userdata;
    536   p_job_info->lib2d_client_cb = cb;
    537 
    538   p_in_frame->private_data  = (void *)p_job_info;
    539   p_out_frame->private_data = (void *)p_job_info;
    540 
    541   // convert the input info into component understandble data structures
    542 
    543   // Prepare Input, output frames
    544   lib2d_fill_img_frame(p_in_frame, src_buffer, jobid);
    545   lib2d_fill_img_frame(p_out_frame, dst_buffer, jobid);
    546 
    547   p_meta->frame_id = jobid;
    548   p_meta->rotation.device_rotation = (int32_t)rotation;
    549   p_meta->rotation.frame_rotation = (int32_t)rotation;
    550 
    551   // call set_param to set the source, destination formats
    552 
    553   rc = IMG_COMP_Q_BUF(p_comp, p_in_frame, IMG_IN);
    554   if (rc != IMG_SUCCESS) {
    555     LOGE("rc %d", rc);
    556     goto ERROR;
    557   }
    558 
    559   rc = IMG_COMP_Q_BUF(p_comp, p_out_frame, IMG_OUT);
    560   if (rc != IMG_SUCCESS) {
    561     LOGE("rc %d", rc);
    562     goto ERROR;
    563   }
    564 
    565   rc = IMG_COMP_Q_META_BUF(p_comp, p_meta);
    566   if (rc != IMG_SUCCESS) {
    567     LOGE("rc %d", rc);
    568     goto ERROR;
    569   }
    570 
    571   rc = IMG_COMP_START(p_comp, NULL);
    572   if (rc != IMG_SUCCESS) {
    573     LOGE("rc %d", rc);
    574     goto ERROR;
    575   }
    576 
    577   if (lib2d_obj->lib2d_mode == MM_LIB2D_SYNC_MODE) {
    578     if (lib2d_obj->comp_mode == IMG_ASYNC_MODE) {
    579       LOGD("before wait rc %d", rc);
    580       rc = lib2d_obj->img_lib.img_wait_for_completion(&lib2d_obj->cond,
    581         &lib2d_obj->mutex, 10000);
    582       if (rc != IMG_SUCCESS) {
    583         LOGE("rc %d", rc);
    584         goto ERROR;
    585       }
    586     }
    587   }
    588 
    589   rc = IMG_COMP_ABORT(p_comp, NULL);
    590   if (IMG_ERROR(rc)) {
    591     LOGE("comp abort failed %d", rc);
    592     return rc;
    593   }
    594 
    595   return MM_LIB2D_SUCCESS;
    596 ERROR:
    597   free(p_in_frame);
    598   free(p_out_frame);
    599   free(p_meta);
    600   free(p_job_info);
    601 
    602   return MM_LIB2D_ERR_GENERAL;
    603 }
    604 
    605