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 // System dependencies
31 #include <dlfcn.h>
32 #include <stdbool.h>
33 #include <stdlib.h>
34 #include <sys/time.h>
35 
36 // Camera dependencies
37 #include "img_buffer.h"
38 #include "mm_lib2d.h"
39 
40 
41 #define ENABLE_OUTPUT_DUMP 1
42 #define ALIGN4K 4032
43 #define ALIGN(a, b) (((a) + (b)) & ~(b))
44 
45 
46 /** DUMP_TO_FILE:
47  *  @filename: file name
48  *  @p_addr: address of the buffer
49  *  @len: buffer length
50  *
51  *  dump the image to the file
52  **/
53 #define DUMP_TO_FILE(filename, p_addr, len) ({ \
54   size_t rc = 0; \
55   FILE *fp = fopen(filename, "w+"); \
56   if (fp) { \
57     rc = fwrite(p_addr, 1, len, fp); \
58     printf(" ] written size %zu \n",  __LINE__, len); \
59     fclose(fp); \
60   } else { \
61     printf(" ] open %s failed \n",  __LINE__, filename); \
62   } \
63 })
64 
65 /** DUMP_TO_FILE2:
66  *  @filename: file name
67  *  @p_addr: address of the buffer
68  *  @len: buffer length
69  *
70  *  dump the image to the file if the memory is non-contiguous
71  **/
72 #define DUMP_TO_FILE2(filename, p_addr1, len1, p_addr2, len2) ({ \
73   size_t rc = 0; \
74   FILE *fp = fopen(filename, "w+"); \
75   if (fp) { \
76     rc = fwrite(p_addr1, 1, len1, fp); \
77     rc = fwrite(p_addr2, 1, len2, fp); \
78     printf(" ] written %zu %zu \n",  __LINE__, len1, len2); \
79     fclose(fp); \
80   } else { \
81     printf(" ] open %s failed \n",  __LINE__, filename); \
82   } \
83 })
84 
85 /** img_lib_buffert
86  * @ptr: handle to the imglib library
87  * @img_buffer_get: function pointer to img_buffer_get
88  * @img_buffer_release: function pointer to img_buffer_release
89  * @img_buffer_cacheops: function pointer to img_buffer_cacheops
90 **/
91 typedef struct {
92   void *ptr;
93   int (*img_buffer_get)(img_buf_type_t type, int heapid, int8_t cached, int length,
94     img_mem_handle_t *p_handle);
95   int (*img_buffer_release)(img_mem_handle_t *p_handle);
96   int (*img_buffer_cacheops)(img_mem_handle_t *p_handle, img_cache_ops_t ops,
97   img_mem_alloc_type_t mem_alloc_type);
98 } img_lib_buffert;
99 
100 /** input_yuv_data
101  * @filename: input test filename
102  * @format: format of the input yuv frame
103  * @wdith: wdith of the input yuv frame
104  * @height: height of the input yuv frame
105  * @stride: stride of the input yuv frame
106  * @offset: offset to the yuv data in the input file
107 **/
108 typedef struct input_yuv_data_t {
109   char filename[512];
110   cam_format_t format;
111   int32_t wdith;
112   int32_t height;
113   int32_t stride;
114   int32_t offset;
115 } input_yuv_data;
116 
117 input_yuv_data input_nv21[] = {
118   {"sample0_768x512.yuv",                             CAM_FORMAT_YUV_420_NV21, 768,  512,  768,  0},
119   {"sample1_3200x2400.yuv",                           CAM_FORMAT_YUV_420_NV21, 3200, 2400, 3200, 0},
120   {"sample2_1920x1080.yuv",                           CAM_FORMAT_YUV_420_NV21, 1920, 1080, 1920, 0},
121   {"sample3_3200x2400.yuv",                           CAM_FORMAT_YUV_420_NV21, 3200, 2400, 3200, 0},
122   {"sample4_4208x3120.yuv",                           CAM_FORMAT_YUV_420_NV21, 4208, 3120, 4208, 0},
123   {"sample5_1984x2592.yuv",                           CAM_FORMAT_YUV_420_NV21, 1984, 2592, 1984, 0},
124   {"sample6_4000_3000.yuv",                           CAM_FORMAT_YUV_420_NV21, 4000, 3000, 4000, 0},
125   {"sample7_3200_2400.yuv",                           CAM_FORMAT_YUV_420_NV21, 3200, 2400, 3200, 0},
126   {"sample8_3008_4000.yuv",                           CAM_FORMAT_YUV_420_NV21, 3008, 4000, 3008, 0},
127   {"sample9_5312x2988.yuv",                           CAM_FORMAT_YUV_420_NV21, 5312, 2988, 5312, 0},
128   {"sample10_4128x3096.yuv",                          CAM_FORMAT_YUV_420_NV21, 4128, 3096, 4128, 0},
129   {"sample11_4208x3120.yuv",                          CAM_FORMAT_YUV_420_NV21, 4208, 3120, 4208, 0},
130   {"sample12_3200x2400.yuv",                          CAM_FORMAT_YUV_420_NV21, 3200, 2400, 3200, 0},
131   {"sample13_width_1080_height_1440_stride_1088.yuv", CAM_FORMAT_YUV_420_NV21, 1080, 1440, 1088, 0},
132   {"sample14_width_1080_height_1920_stride_1088.yuv", CAM_FORMAT_YUV_420_NV21, 1080, 1920, 1088, 0},
133   {"sample15_width_1944_height_2592_stride_1984.yuv", CAM_FORMAT_YUV_420_NV21, 1944, 2592, 1984, 0},
134   {"sample16_width_3000_height_4000_stride_3008.yuv", CAM_FORMAT_YUV_420_NV21, 3000, 4000, 3008, 0},
135   {"sample17_width_3120_height_4208_stride_3136.yuv", CAM_FORMAT_YUV_420_NV21, 3120, 4208, 3136, 0},
136   {"sample18_width_3200_height_2400_stride_3200.yuv", CAM_FORMAT_YUV_420_NV21, 3200, 2400, 3200, 0},
137   {"sample19_width_1944_height_2592_stride_1984.yuv", CAM_FORMAT_YUV_420_NV21, 1944, 2592, 1984, 0},
138 };
139 
140 // assuming buffer format is always ARGB
lib2d_dump_tga(void * addr,cam_format_t format,int width,int height,int stride,char * fname)141 void lib2d_dump_tga(void *addr, cam_format_t format, int width,
142   int height, int stride, char *fname)
143 {
144   int i, j;
145   FILE *f;
146   unsigned char *pb = (unsigned char *)addr;
147   uint32_t *pd = (uint32_t *)addr;
148   int bpp = 32;
149 
150   f = fopen(fname, "wb");
151   if (f) {
152     // header
153     fprintf(f, "%c%c%c%c", 0, 0, 2, 0);
154     fprintf(f, "%c%c%c%c", 0, 0, 0, 0);
155     fprintf(f, "%c%c%c%c", 0, 0, 0, 0);
156     fprintf(f, "%c%c%c%c", width & 0xff, width >> 8, height & 0xff, height >> 8);
157     fprintf(f, "%c%c", bpp, 32);
158 
159     for (i = 0; i < height; i++) {
160       for (j = 0; j < width; j++) {
161         fprintf(f, "%c%c%c%c",
162           pd[(i*stride>>2)+j] & 0xff,           // b
163           (pd[(i*stride>>2)+j] >> 8) & 0xff,    // g
164           (pd[(i*stride>>2)+j] >> 16) & 0xff,   // r
165           (pd[(i*stride>>2)+j] >> 24) & 0xff);  // a
166       }
167     }
168     fclose(f);
169   }
170 }
171 
172 /**
173  * Function: lib2d_test_client_cb
174  *
175  * Description: Callback that is called on completion of requested job.
176  *
177  * Input parameters:
178  *   userdata - App userdata
179  *   jobid - job id that is finished execution
180  *
181  * Return values:
182  *   MM_LIB2D_SUCCESS
183  *   MM_LIB2D_ERR_GENERAL
184  *
185  * Notes: none
186  **/
lib2d_test_client_cb(void * userdata,int jobid)187 lib2d_error lib2d_test_client_cb(void *userdata, int jobid)
188 {
189   printf("%s %d, jobid=%d \n",  __LINE__, jobid);
190   return MM_LIB2D_SUCCESS;
191 }
192 
193 /**
194  * Function: lib2d_test_load_input_yuv_data
195  *
196  * Description: Loads yuv data from input file.
197  *
198  * Input parameters:
199  *   fileName - input yuv filename
200  *   offset - offset to the yuv data in the input file
201  *   y_size - y plane size in input yuv file
202  *   crcb_size - crcb plane size in input yuv file
203  *   crcb_offset - crcb offset in the memory at
204  *       which crcb data need to be loaded
205  *   addr - y plane memory address where y plane
206  *       data need to be loaded.
207  *
208  * Return values:
209  *   MM_LIB2D_SUCCESS
210  *   MM_LIB2D_ERR_GENERAL
211  *
212  * Notes: none
213  **/
lib2d_test_load_input_yuv_data(char * fileName,int offset,int32_t y_size,int32_t crcb_size,int32_t crcb_offset,void * addr)214 lib2d_error lib2d_test_load_input_yuv_data(char *fileName, int offset,
215     int32_t y_size, int32_t crcb_size, int32_t crcb_offset,
216     void *addr)
217 {
218   size_t i;
219   FILE  *fp       = 0;
220   void  *y_ptr    = addr;
221   void  *crcb_ptr = (uint8_t *)addr + crcb_offset;
222 
223   printf("y_ptr=%p, crcb_ptr=%p \n", y_ptr, crcb_ptr);
224 
225   fp = fopen(fileName, "rb");
226   if(fp) {
227     if(offset) {
228       fseek(fp, offset, SEEK_SET);
229     }
230     i = fread(y_ptr, 1, y_size, fp);
231     i = fread(crcb_ptr, 1, crcb_size, fp);
232 
233     fclose( fp );
234   } else {
235     printf("failed to open file %s \n", fileName);
236     return MM_LIB2D_ERR_GENERAL;
237   }
238 
239   return MM_LIB2D_SUCCESS;
240 }
241 
242 /**
243  * Function: lib2d_test_load_input_yuv_data
244  *
245  * Description: Loads yuv data from input file.
246  *
247  * Input parameters:
248  *   fileName - input yuv filename
249  *   offset - offset to the yuv data in the input file
250  *   input_yuv_stride - y plane stride in input yuv file
251  *   y_plane_stride - y plane stride in buffer memory
252  *   height - height of yuv image
253  *   crcb_offset - crcb offset in the memory at
254  *       which crcb data need to be loaded
255  *   addr - y plane memory address where y plane
256  *       data need to be loaded.
257  *
258  * Return values:
259  *   MM_LIB2D_SUCCESS
260  *   MM_LIB2D_ERR_GENERAL
261  *
262  * Notes: none
263  **/
lib2d_test_load_input_yuv_data_linebyline(char * fileName,int offset,int32_t input_yuv_stride,int32_t y_plane_stride,int32_t height,int32_t crcb_offset,void * addr)264 lib2d_error lib2d_test_load_input_yuv_data_linebyline(char *fileName,
265     int offset, int32_t input_yuv_stride, int32_t y_plane_stride,
266     int32_t height, int32_t crcb_offset, void *addr)
267 {
268   size_t i;
269   FILE  *fp       = 0;
270   void  *y_ptr    = addr;
271   void  *crcb_ptr = (uint8_t *)addr + crcb_offset;
272 
273   printf("y_ptr=%p, crcb_ptr=%p \n", y_ptr, crcb_ptr);
274 
275   fp = fopen(fileName, "rb");
276   if(fp) {
277     if(offset) {
278       fseek(fp, offset, SEEK_SET);
279     }
280     if (input_yuv_stride == y_plane_stride) {
281       //load y plane
282       i = fread(y_ptr, 1, (input_yuv_stride * height), fp);
283       // load UV plane
284       i = fread(crcb_ptr, 1, (input_yuv_stride * height / 2), fp);
285     } else {
286       int line = 0;
287       // load Y plane
288       for (line = 0;line < height; line++) {
289         i = fread(y_ptr, 1, input_yuv_stride, fp);
290         y_ptr = (void *)((uint8_t *)y_ptr + y_plane_stride);
291       }
292       for (line = 0;line < height; line++) {
293         i = fread(crcb_ptr, 1, input_yuv_stride, fp);
294         crcb_ptr = (void *)((uint8_t *)crcb_ptr + y_plane_stride);
295       }
296     }
297 
298     fclose( fp );
299   } else {
300     printf("failed to open file %s \n", fileName);
301     return MM_LIB2D_ERR_GENERAL;
302   }
303 
304   return MM_LIB2D_SUCCESS;
305 }
306 
307 /**
308  * Function: main
309  *
310  * Description: main function for execution
311  *
312  * Input parameters:
313  *   argc - no.of input arguments
314  *   argv - list of arguments
315  *
316  * Return values:
317  *   0 on success
318  *   -1 on failure
319  *
320  * Notes: none
321  **/
main(int32_t argc,const char * argv[])322 int main(int32_t argc, const char * argv[])
323 {
324   void            *lib2d_handle       = NULL;
325   lib2d_error      lib2d_err          = MM_LIB2D_SUCCESS;
326   mm_lib2d_buffer  src_buffer         = {0};
327   mm_lib2d_buffer  dst_buffer         = {0};
328   int8_t           ret                = IMG_SUCCESS;
329   int32_t          width              = 0;
330   int32_t          height             = 0;
331   int32_t          input_yuv_stride   = 0;
332   int32_t          stride             = 0;
333   int32_t          y_plane_stride     = 0;
334   int32_t          crcb_plane_stride  = 0;
335   int32_t          y_plane_size       = 0;
336   int32_t          y_plane_size_align = 0;
337   int32_t          crcb_plane_size    = 0;
338   int32_t          yuv_size           = 0;
339   int32_t          rgb_size           = 0;
340   img_mem_handle_t m_yuv_memHandle    = { 0 };
341   img_mem_handle_t m_rgb_memHandle    = { 0 };
342   char             filename_in[512]   = { 0 };
343   char             filename_out[512]  = { 0 };
344   char             filename_raw[512]  = { 0 };
345   int32_t          offset             = 0;
346   unsigned int     total_tests        = 1;
347   cam_format_t     format             = CAM_FORMAT_YUV_420_NV21;
348   unsigned int     index;
349   const char      *filename;
350 
351   // Open Imglib library and get the function pointers for
352   // buffer allocation, free, cacheops
353   img_lib_buffert  img_lib;
354   img_lib.ptr = dlopen("libmmcamera_imglib.so", RTLD_NOW);
355   if (!img_lib.ptr) {
356     printf("%s ERROR: couldn't dlopen libmmcamera_imglib.so: %s",
357        dlerror());
358     return -1;
359   }
360 
361   /* Get function pointer for functions to allocate ion memory */
362   *(void **)&img_lib.img_buffer_get =
363       dlsym(img_lib.ptr, "img_buffer_get");
364   *(void **)&img_lib.img_buffer_release =
365       dlsym(img_lib.ptr, "img_buffer_release");
366   *(void **)&img_lib.img_buffer_cacheops =
367       dlsym(img_lib.ptr, "img_buffer_cacheops");
368 
369   /* Validate function pointers */
370   if ((img_lib.img_buffer_get == NULL) ||
371     (img_lib.img_buffer_release == NULL) ||
372     (img_lib.img_buffer_cacheops == NULL)) {
373     printf(" ERROR mapping symbols from libmmcamera_imglib.so");
374     dlclose(img_lib.ptr);
375     return -1;
376   }
377 
378   lib2d_err = mm_lib2d_init(MM_LIB2D_SYNC_MODE, CAM_FORMAT_YUV_420_NV21,
379     CAM_FORMAT_8888_ARGB, &lib2d_handle);
380   if ((lib2d_err != MM_LIB2D_SUCCESS) || (lib2d_handle == NULL)) {
381     return -1;
382   }
383 
384   bool run_default = FALSE;
385 
386   if ( argc == 7) {
387     filename         = argv[1];
388     width            = (uint32_t)atoi(argv[2]);
389     height           = (uint32_t)atoi(argv[3]);
390     input_yuv_stride = (uint32_t)atoi(argv[4]);
391     offset           = (uint32_t)atoi(argv[5]);
392     format           = (uint32_t)atoi(argv[6]);
393     run_default      = TRUE;
394     printf("Running user provided conversion \n");
395   }
396   else {
397     total_tests = sizeof(input_nv21)/sizeof(input_yuv_data);
398     printf("usage: <binary> <filname> <width> <height> "
399       "<stride> <offset> <format> \n");
400   }
401 
402   for (index = 0; index < total_tests; index++)
403   {
404     if(run_default == FALSE) {
405       filename         = input_nv21[index].filename;
406       width            = input_nv21[index].wdith;
407       height           = input_nv21[index].height;
408       input_yuv_stride = input_nv21[index].stride;
409       offset           = input_nv21[index].offset;
410       format           = input_nv21[index].format;
411     }
412 
413     snprintf(filename_in, 512, "/data/lib2d/input/%s", filename);
414     snprintf(filename_out, 512, "/data/lib2d/output/%s.tga", filename);
415     snprintf(filename_raw, 512, "/data/lib2d/output/%s.rgba", filename);
416 
417     printf("-----------------Running test=%d/%d------------------------- \n",
418       index+1, total_tests);
419     printf("filename=%s, full path=%s, width=%d, height=%d, stride=%d \n",
420       filename, filename_in, width, height, stride);
421 
422     // Allocate NV12 buffer
423     y_plane_stride     = ALIGN(width, 32);
424     y_plane_size       = y_plane_stride * height;
425     y_plane_size_align = ALIGN(y_plane_size, ALIGN4K);
426     crcb_plane_stride  = y_plane_stride;
427     crcb_plane_size    = crcb_plane_stride * height / 2;
428     yuv_size           = y_plane_size_align + crcb_plane_size;
429     ret = img_lib.img_buffer_get(IMG_BUFFER_ION_IOMMU, -1, TRUE,
430           yuv_size, &m_yuv_memHandle);
431     if (ret != IMG_SUCCESS) {
432       printf(" ] Error, img buf get failed \n");
433       goto deinit;
434     }
435 
436     printf("%s %d yuv buffer properties : w=%d, h=%d, y_stride=%d, "
437       "crcb_stride=%d, y_size=%d, crcb_size=%d, yuv_size=%d, "
438       "crcb_offset=%d \n",
439        __LINE__,
440       width, height, y_plane_stride, crcb_plane_stride, y_plane_size,
441       crcb_plane_size, yuv_size, y_plane_size_align);
442     printf("%s %d yuv buffer properties : fd=%d, ptr=%p, size=%d \n",
443        __LINE__, m_yuv_memHandle.fd, m_yuv_memHandle.vaddr,
444       m_yuv_memHandle.length);
445 
446     // Allocate ARGB buffer
447     stride   = width * 4;
448     stride   = ALIGN(stride, 32);
449     rgb_size = stride * height;
450     ret = img_lib.img_buffer_get(IMG_BUFFER_ION_IOMMU, -1, TRUE,
451           rgb_size, &m_rgb_memHandle);
452     if (ret != IMG_SUCCESS) {
453       printf(" ] Error, img buf get failed");
454       img_lib.img_buffer_release(&m_yuv_memHandle);
455       goto deinit;
456     }
457 
458     printf("%s %d rgb buffer properties : w=%d, h=%d, stride=%d, size=%d \n",
459        __LINE__, width, height, stride, rgb_size);
460     printf("%s %d rgb buffer properties : fd=%d, ptr=%p, size=%d \n",
461        __LINE__, m_rgb_memHandle.fd, m_rgb_memHandle.vaddr,
462       m_rgb_memHandle.length);
463 
464 #if 0
465     lib2d_err = lib2d_test_load_input_yuv_data(filename_in, offset,
466       (input_yuv_stride * height), (input_yuv_stride * height / 2), y_plane_size_align,
467       m_yuv_memHandle.vaddr);
468     if (lib2d_err != MM_LIB2D_SUCCESS) {
469       printf(" ] Error loading the input buffer \n");
470       goto release;
471     }
472 #else
473     lib2d_err = lib2d_test_load_input_yuv_data_linebyline(filename_in, offset,
474       input_yuv_stride, y_plane_stride,height, y_plane_size_align,
475       m_yuv_memHandle.vaddr);
476     if (lib2d_err != MM_LIB2D_SUCCESS) {
477       printf(" ] Error loading the input buffer \n");
478       goto release;
479     }
480 #endif
481     // Setup source buffer
482     src_buffer.buffer_type = MM_LIB2D_BUFFER_TYPE_YUV;
483     src_buffer.yuv_buffer.fd      = m_yuv_memHandle.fd;
484     src_buffer.yuv_buffer.format  = format;
485     src_buffer.yuv_buffer.width   = width;
486     src_buffer.yuv_buffer.height  = height;
487     src_buffer.yuv_buffer.plane0  = m_yuv_memHandle.vaddr;
488     src_buffer.yuv_buffer.stride0 = y_plane_stride;
489     src_buffer.yuv_buffer.plane1  = (int8_t *)m_yuv_memHandle.vaddr +
490                                     y_plane_size_align;
491     src_buffer.yuv_buffer.stride1 = crcb_plane_stride;
492 
493     // Setup dst buffer
494     dst_buffer.buffer_type = MM_LIB2D_BUFFER_TYPE_RGB;
495     dst_buffer.rgb_buffer.fd     = m_rgb_memHandle.fd;
496     dst_buffer.rgb_buffer.format = CAM_FORMAT_8888_ARGB;
497     dst_buffer.rgb_buffer.width  = width;
498     dst_buffer.rgb_buffer.height = height;
499     dst_buffer.rgb_buffer.buffer = m_rgb_memHandle.vaddr;
500     dst_buffer.rgb_buffer.stride = stride;
501 
502     img_lib.img_buffer_cacheops(&m_yuv_memHandle,
503       IMG_CACHE_CLEAN_INV, IMG_INTERNAL);
504 
505     lib2d_err = mm_lib2d_start_job(lib2d_handle, &src_buffer, &dst_buffer,
506       index, NULL, lib2d_test_client_cb, 0);
507     if (lib2d_err != MM_LIB2D_SUCCESS) {
508       printf(" ] Error in mm_lib2d_start_job \n");
509       goto release;
510     }
511 
512     img_lib.img_buffer_cacheops(&m_rgb_memHandle,
513       IMG_CACHE_CLEAN_INV, IMG_INTERNAL);
514 
515 #ifdef ENABLE_OUTPUT_DUMP
516     // Dump output files
517     // snprintf(filename_in, 512, "/data/lib2d/output/%s", filename);
518     // DUMP_TO_FILE2(filename_in, src_buffer.yuv_buffer.plane0, y_plane_size, src_buffer.yuv_buffer.plane1, crcb_plane_size);
519     // DUMP_TO_FILE(filename_raw, dst_buffer.rgb_buffer.buffer, rgb_size);
520     printf("Dumping output file %s \n", filename_out);
521     lib2d_dump_tga(dst_buffer.rgb_buffer.buffer, 1,
522       width, height, stride, filename_out);
523 #endif
524 
525     img_lib.img_buffer_release(&m_rgb_memHandle);
526     img_lib.img_buffer_release(&m_yuv_memHandle);
527   }
528 
529   mm_lib2d_deinit(lib2d_handle);
530 
531   return 0;
532 
533 release:
534   img_lib.img_buffer_release(&m_rgb_memHandle);
535   img_lib.img_buffer_release(&m_yuv_memHandle);
536 deinit:
537   mm_lib2d_deinit(lib2d_handle);
538   printf("%s %d some error happened, tests completed = %d/%d \n",
539      __LINE__, index - 1, total_tests);
540   return -1;
541 }
542 
543 
544