• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above
10       copyright notice, this list of conditions and the following
11       disclaimer in the documentation and/or other materials provided
12       with the distribution.
13     * Neither the name of Code Aurora Forum, Inc. nor the names of its
14       contributors may be used to endorse or promote products derived
15       from this software without specific prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 
30 #include <pthread.h>
31 #include "mm_camera_dbg.h"
32 #include <errno.h>
33 #include <sys/mman.h>
34 #include <sys/ioctl.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <poll.h>
39 #include <linux/msm_ion.h>
40 #include "mm_qcamera_app.h"
41 
42 
43 /*===========================================================================
44  * FUNCTION    - mm_camera_do_mmap_ion -
45  *
46  * DESCRIPTION:
47  *==========================================================================*/
mm_camera_do_mmap_ion(int ion_fd,struct ion_allocation_data * alloc,struct ion_fd_data * ion_info_fd,int * mapFd)48 uint8_t *mm_camera_do_mmap_ion(int ion_fd, struct ion_allocation_data *alloc,
49                                struct ion_fd_data *ion_info_fd, int *mapFd)
50 {
51     void *ret; /* returned virtual address */
52     int rc = 0;
53     struct ion_handle_data handle_data;
54 
55     /* to make it page size aligned */
56     alloc->len = (alloc->len + 4095) & (~4095);
57 
58     rc = ioctl(ion_fd, ION_IOC_ALLOC, alloc);
59     if (rc < 0) {
60         CDBG_ERROR("ION allocation failed %s\n", strerror(errno));
61         goto ION_ALLOC_FAILED;
62     }
63 
64     ion_info_fd->handle = alloc->handle;
65     rc = ioctl(ion_fd, ION_IOC_SHARE, ion_info_fd);
66     if (rc < 0) {
67         CDBG_ERROR("ION map failed %s\n", strerror(errno));
68         goto ION_MAP_FAILED;
69     }
70     *mapFd = ion_info_fd->fd;
71     ret = mmap(NULL,
72                alloc->len,
73                PROT_READ  | PROT_WRITE,
74                MAP_SHARED,
75                *mapFd,
76                0);
77 
78     if (ret == MAP_FAILED) {
79         CDBG_ERROR("ION_MMAP_FAILED: %s (%d)\n", strerror(errno), errno);
80         goto ION_MAP_FAILED;
81     }
82 
83     return ret;
84 
85     ION_MAP_FAILED:
86     handle_data.handle = ion_info_fd->handle;
87     ioctl(ion_fd, ION_IOC_FREE, &handle_data);
88     ION_ALLOC_FAILED:
89     return NULL;
90 }
91 
92 /*===========================================================================
93  * FUNCTION    - mm_camera_do_munmap_ion -
94  *
95  * DESCRIPTION:
96  *==========================================================================*/
mm_camera_do_munmap_ion(int ion_fd,struct ion_fd_data * ion_info_fd,void * addr,size_t size)97 int mm_camera_do_munmap_ion (int ion_fd, struct ion_fd_data *ion_info_fd,
98                              void *addr, size_t size)
99 {
100     int rc = 0;
101     rc = munmap(addr, size);
102     close(ion_info_fd->fd);
103 
104     struct ion_handle_data handle_data;
105     handle_data.handle = ion_info_fd->handle;
106     ioctl(ion_fd, ION_IOC_FREE, &handle_data);
107     return rc;
108 }
109 
110 
mm_app_set_preview_fmt(int cam_id,mm_camera_image_fmt_t * fmt)111 int mm_app_set_preview_fmt(int cam_id,mm_camera_image_fmt_t *fmt)
112 {
113     int rc = MM_CAMERA_OK;
114     mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
115 
116     fmt->meta_header = MM_CAMEAR_META_DATA_TYPE_DEF;
117     fmt->fmt = pme->dim.prev_format;
118     fmt->width = pme->dim.display_width;
119     fmt->height = pme->dim.display_height;
120     return rc;
121 }
122 
123 //void dumpFrameToFile(struct msm_frame* newFrame, int w, int h, char* name, int main_422)
dumpFrameToFile(mm_camera_buf_def_t * newFrame,int w,int h,char * name,int main_422)124 void dumpFrameToFile(mm_camera_buf_def_t* newFrame, int w, int h, char* name, int main_422)
125 {
126     char buf[32];
127     int file_fd;
128     int i;
129     char *ext = "yuv";
130 #if 0
131     if ( newFrame != NULL) {
132         char * str;
133         snprintf(buf, sizeof(buf), "/data/%s.%s", name,ext);
134         file_fd = open(buf, O_RDWR | O_CREAT, 0777);
135         if (file_fd < 0) {
136             CDBG_ERROR("%s: cannot open file\n", __func__);
137         } else {
138             CDBG("%s: %d %d", __func__, newFrame->y_off, newFrame->cbcr_off);
139             write(file_fd, (const void *)(newFrame->buffer+newFrame->y_off), w * h);
140             write(file_fd, (const void *)
141                   (newFrame->buffer + newFrame->cbcr_off), w * h / 2 * main_422);
142             close(file_fd);
143             CDBG("dump %s", buf);
144         }
145     }
146 #endif
147     if ( newFrame != NULL) {
148         char * str;
149         snprintf(buf, sizeof(buf), "/data/%s.%s", name,ext);
150         file_fd = open(buf, O_RDWR | O_CREAT, 0777);
151         if (file_fd < 0) {
152             CDBG_ERROR("%s: cannot open file\n", __func__);
153         } else {
154             int y_off = newFrame->buffer + newFrame->planes[0].data_offset;
155             //int cbcr_off = newFrame->buffer + newFrame->planes[1].data_offset;//newFrame->buffer + newFrame->planes[0].length;
156             int cbcr_off = newFrame->buffer + newFrame->planes[0].length;
157             CDBG("%s: Y_off = %p cbcr_off = %p", __func__, y_off,cbcr_off);
158             CDBG("%s: Y_off length = %d cbcr_off length = %d", __func__, newFrame->planes[0].length,newFrame->planes[1].length);
159 
160             write(file_fd, (const void *)(y_off), newFrame->planes[0].length);
161             write(file_fd, (const void *)(cbcr_off),
162                   (newFrame->planes[1].length * newFrame->num_planes));
163             /*for(i = 1; i < newFrame->num_planes; i++) {
164                 CDBG("%s: CBCR = %d", __func__, newFrame->planes[j].data_offset);
165                 write(file_fd, (const void *)
166                   (newFrame->planes[i].data_offset), w * h / 2 * main_422);
167             }*/
168             close(file_fd);
169             CDBG("dump %s", buf);
170         }
171     }
172 }
173 
mm_app_open_camera(int cam_id)174 int mm_app_open_camera(int cam_id)
175 {
176     int rc = MM_CAMERA_OK;
177     int value = 0;
178     mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
179 
180     if (pme->cam_mode == CAMERA_MODE) {
181         return rc;
182     }
183 
184     if (MM_CAMERA_OK != (rc = mm_app_stop_preview(cam_id))) {
185         CDBG_ERROR("%s:Stop preview err=%d\n", __func__, rc);
186         goto end;
187     }
188 
189     pme->cam->ops->set_parm(pme->cam->camera_handle,MM_CAMERA_PARM_RECORDING_HINT, &value);
190 
191     if (MM_CAMERA_OK != (rc = mm_app_start_preview(cam_id))) {
192         CDBG_ERROR("%s:Start preview err=%d\n", __func__, rc);
193         goto end;
194     }
195 
196     pme->cam_mode = CAMERA_MODE;
197     end:
198     CDBG("%s: END, rc=%d\n", __func__, rc);
199     return rc;
200 }
201 
202 
mm_app_open_zsl(int cam_id)203 int mm_app_open_zsl(int cam_id)
204 {
205     int rc = MM_CAMERA_OK;
206     int value = 0;
207     mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
208 
209     if (pme->cam_mode == ZSL_MODE) {
210         return rc;
211     }
212 
213     if (MM_CAMERA_OK != (rc = mm_app_stop_preview(cam_id))) {
214         CDBG_ERROR("%s:Stop preview err=%d\n", __func__, rc);
215         goto end;
216     }
217 
218     pme->cam->ops->set_parm(pme->cam->camera_handle,MM_CAMERA_PARM_RECORDING_HINT, &value);
219 
220     if (MM_CAMERA_OK != (rc = mm_app_start_preview_zsl(cam_id))) {
221         CDBG_ERROR("%s:stream on preview err=%d\n", __func__, rc);
222         goto end;
223     }
224     pme->cam_mode = ZSL_MODE;
225     end:
226     CDBG("%s: END, rc=%d\n", __func__, rc);
227     return rc;
228 }
229 #if 0
230 int mm_stream_deinit_preview_buf(uint32_t camera_handle,
231                                  uint32_t ch_id, uint32_t stream_id,
232                                  void *user_data, uint8_t num_bufs,
233                                  mm_camera_buf_def_t *bufs)
234 {
235     int i, rc = MM_CAMERA_OK;
236     mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
237     for (i = 0; i < num_bufs; i++) {
238         rc = my_cam_app.hal_lib.mm_camera_do_munmap_ion (pme->ionfd, &(pme->preview_buf.frame[i].fd_data),
239                                                          (void *)pme->preview_buf.frame[i].buffer, bufs[i].frame_len);
240         if (rc != MM_CAMERA_OK) {
241             CDBG("%s: mm_camera_do_munmap err, pmem_fd = %d, rc = %d",
242                  __func__, bufs[i].fd, rc);
243         }
244     }
245     close(pme->ionfd);
246     return rc;
247 }
248 
249 int mm_stream_init_preview_buf(uint32_t camera_handle,
250                                uint32_t ch_id, uint32_t stream_id,
251                                void *user_data,
252                                mm_camera_frame_len_offset *frame_offset_info,
253                                uint8_t num_bufs,
254                                uint8_t *initial_reg_flag,
255                                mm_camera_buf_def_t *bufs)
256 {
257     int i,j,num_planes, frame_len, y_off, cbcr_off;
258     uint32_t planes[VIDEO_MAX_PLANES];
259     uint32_t pmem_addr = 0;
260 
261     mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
262 
263     num_planes = frame_offset_info->num_planes;
264     for ( i = 0; i < num_planes; i++) {
265         planes[i] = frame_offset_info->mp[i].len;
266     }
267 
268     frame_len = frame_offset_info->frame_len;
269     y_off = frame_offset_info->mp[0].offset;
270     cbcr_off = frame_offset_info->mp[1].offset;
271 
272     CDBG("Allocating Preview Memory for %d buffers frame_len = %d",num_bufs,frame_offset_info->frame_len);
273 
274     for (i = 0; i < num_bufs ; i++) {
275         int j;
276         pme->preview_buf.reg[i] = 1;
277         initial_reg_flag[i] = 1;
278 
279         pme->preview_buf.frame_len = frame_len;
280         pme->preview_buf.frame[i].ion_alloc.len = pme->preview_buf.frame_len;
281         pme->preview_buf.frame[i].ion_alloc.flags =
282         (0x1 << CAMERA_ION_HEAP_ID | 0x1 << ION_IOMMU_HEAP_ID);
283         pme->preview_buf.frame[i].ion_alloc.align = 4096;
284 
285         pmem_addr = (unsigned long) my_cam_app.hal_lib.mm_camera_do_mmap_ion(pme->ionfd,
286                                                                              &(pme->preview_buf.frame[i].ion_alloc), &(pme->preview_buf.frame[i].fd_data),
287                                                                              &pme->preview_buf.frame[i].fd);
288 
289         pme->preview_buf.frame[i].buffer = pmem_addr;
290         pme->preview_buf.frame[i].path = OUTPUT_TYPE_P;
291         pme->preview_buf.frame[i].y_off = 0;
292         pme->preview_buf.frame[i].cbcr_off = planes[0];
293         pme->preview_buf.frame[i].phy_offset = 0;
294 
295         CDBG("Buffer allocated Successfully fd = %d",pme->preview_buf.frame[i].fd);
296 
297         bufs[i].fd = pme->preview_buf.frame[i].fd;
298         //bufs[i].buffer = pmem_addr;
299         bufs[i].frame_len = pme->preview_buf.frame[i].ion_alloc.len;
300         bufs[i].num_planes = num_planes;
301 
302         bufs[i].frame = &pme->preview_buf.frame[i];
303 
304         /* Plane 0 needs to be set seperately. Set other planes
305              * in a loop. */
306         bufs[i].planes[0].length = planes[0];
307         bufs[i].planes[0].m.userptr = bufs[i].fd;
308         bufs[i].planes[0].data_offset = y_off;
309         bufs[i].planes[0].reserved[0] = 0;
310         //buf_def->buf.mp[i].frame_offset;
311         for (j = 1; j < num_planes; j++) {
312             bufs[i].planes[j].length = planes[j];
313             bufs[i].planes[j].m.userptr = bufs[i].fd;
314             bufs[i].planes[j].data_offset = cbcr_off;
315             bufs[i].planes[j].reserved[0] =
316             bufs[i].planes[j-1].reserved[0] +
317             bufs[i].planes[j-1].length;
318         }
319     }
320     return MM_CAMERA_OK;
321 }
322 #endif
323 
mm_stream_initbuf(uint32_t camera_handle,uint32_t ch_id,uint32_t stream_id,void * user_data,mm_camera_frame_len_offset * frame_offset_info,uint8_t num_bufs,uint8_t * initial_reg_flag,mm_camera_buf_def_t * bufs)324 int mm_stream_initbuf(uint32_t camera_handle,
325                       uint32_t ch_id, uint32_t stream_id,
326                       void *user_data,
327                       mm_camera_frame_len_offset *frame_offset_info,
328                       uint8_t num_bufs,
329                       uint8_t *initial_reg_flag,
330                       mm_camera_buf_def_t *bufs)
331 {
332     int i,y_off, cbcr_off,num_planes;
333     int plane_len;
334     struct ion_allocation_data ion_alloc;
335     struct ion_fd_data ion_info_fd;
336     uint32_t pmem_addr = 0;
337     uint32_t planes[VIDEO_MAX_PLANES];
338 
339     mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
340 
341     num_planes = frame_offset_info->num_planes;
342     if (num_planes == 1) {
343         y_off = frame_offset_info->mp[0].offset;;
344         cbcr_off = 0;
345     } else {
346         y_off = frame_offset_info->mp[0].offset;
347         cbcr_off = frame_offset_info->mp[1].offset;
348     }
349 
350     CDBG("%s: y_off = %d,cbcr_off = %d,num_planes = %d",__func__,y_off,
351          cbcr_off,num_planes);
352 
353     pme->ionfd = open("/dev/ion", O_RDONLY);
354     if (pme->ionfd < 0) {
355         ALOGE("Ion dev open failed\n");
356         ALOGE("Error is %s\n", strerror(errno));
357     }
358 
359     for (i = 0; i < num_bufs ; i++) {
360         int j;
361 
362         //if(pme->cam_mode != RECORDER_MODE || pme->fullSizeSnapshot) {
363         initial_reg_flag[i] = 1;
364         //}else{
365         //initial_reg_flag[i] = 0;
366         //}
367 
368         ion_alloc.len = frame_offset_info->frame_len;
369         ion_alloc.flags =
370         (0x1 << CAMERA_ION_HEAP_ID | 0x1 << ION_IOMMU_HEAP_ID);
371         ion_alloc.align = 4096;
372 
373         /*bufs[i].buffer = my_cam_app.hal_lib.mm_camera_do_mmap_ion(pme->ionfd,
374                        &ion_alloc, &ion_info_fd,
375                        &bufs[i].fd);*/
376 
377         bufs[i].buffer = mm_camera_do_mmap_ion(pme->ionfd,
378                                                &ion_alloc, &ion_info_fd,
379                                                &bufs[i].fd);
380         CDBG(" %s : Buffer allocated fd = %d, length = %d, y_off = %d cdcr_off = %d",
381              __func__,bufs[i].fd,ion_alloc.len,y_off,cbcr_off);
382 
383         bufs[i].frame_len = ion_alloc.len;
384         bufs[i].num_planes = num_planes;
385 
386         /* Plane 0 needs to be set seperately. Set other planes
387              * in a loop. */
388         bufs[i].planes[0].length = frame_offset_info->mp[0].len;
389         bufs[i].planes[0].m.userptr = bufs[i].fd;
390         bufs[i].planes[0].data_offset = y_off;
391         bufs[i].planes[0].reserved[0] = 0;
392         //buf_def->buf.mp[i].frame_offset;
393         for (j = 1; j < num_planes; j++) {
394             bufs[i].planes[j].length = frame_offset_info->mp[j].len;
395             bufs[i].planes[j].m.userptr = bufs[i].fd;
396             bufs[i].planes[j].data_offset = cbcr_off;
397             bufs[i].planes[j].reserved[0] =
398             bufs[i].planes[j-1].reserved[0] +
399             bufs[i].planes[j-1].length;
400         }
401     }
402     CDBG("%s: X",__func__);
403     return MM_CAMERA_OK;
404 }
405 
406 #if 0
407 int mm_stream_initbuf_1(uint32_t camera_handle,
408                         uint32_t ch_id, uint32_t stream_id,
409                         void *user_data,
410                         mm_camera_frame_len_offset *frame_offset_info,
411                         uint8_t num_bufs,
412                         uint8_t *initial_reg_flag,
413                         mm_camera_buf_def_t *bufs)
414 {
415     int i;
416     int streamType = 0;
417 
418     mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
419 
420     CDBG("%s : E ", __FUNCTION__);
421 
422     for (i= 0; i < 5; i++) {
423         if (pme->stream[i].id == stream_id) {
424             CDBG("Allocate Memory for Stream %d",i);
425             streamType = i;
426             break;
427         }
428     }
429 
430     streamType = MM_CAMERA_PREVIEW;
431     switch (streamType) {
432     case MM_CAMERA_PREVIEW:
433         mm_stream_init_preview_buf( camera_handle,
434                                     ch_id, stream_id,
435                                     user_data,
436                                     frame_offset_info,
437                                     num_bufs,
438                                     initial_reg_flag,
439                                     bufs);
440         break;
441     case MM_CAMERA_VIDEO:
442         mm_stream_init_video_buf( camera_handle,
443                                   ch_id, stream_id,
444                                   user_data,
445                                   frame_offset_info,
446                                   num_bufs,
447                                   initial_reg_flag,
448                                   bufs);
449         break;
450     case MM_CAMERA_SNAPSHOT_MAIN:
451         mm_stream_init_main_buf( camera_handle,
452                                  ch_id, stream_id,
453                                  user_data,
454                                  frame_offset_info,
455                                  num_bufs,
456                                  initial_reg_flag,
457                                  bufs);
458         break;
459     case MM_CAMERA_SNAPSHOT_THUMBNAIL:
460         mm_stream_init_thumbnail_buf( camera_handle,
461                                       ch_id, stream_id,
462                                       user_data,
463                                       frame_offset_info,
464                                       num_bufs,
465                                       initial_reg_flag,
466                                       bufs);
467         break;
468     default:
469         break;
470     }
471 
472     CDBG(" %s : X ",__FUNCTION__);
473     return MM_CAMERA_OK;
474 }
475 #endif
mm_stream_deinitbuf(uint32_t camera_handle,uint32_t ch_id,uint32_t stream_id,void * user_data,uint8_t num_bufs,mm_camera_buf_def_t * bufs)476 int mm_stream_deinitbuf(uint32_t camera_handle,
477                         uint32_t ch_id, uint32_t stream_id,
478                         void *user_data, uint8_t num_bufs,
479                         mm_camera_buf_def_t *bufs)
480 {
481     int i, rc = MM_CAMERA_OK;
482     mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
483 
484     CDBG("%s: E",__func__);
485 
486     for (i = 0; i < num_bufs; i++) {
487         /*rc = my_cam_app.hal_lib.mm_camera_do_munmap_ion (pme->ionfd, &bufs[i].fd,
488                    (void *)bufs[i].buffer, bufs[i].frame_len);*/
489         rc = mm_camera_do_munmap_ion (pme->ionfd, &bufs[i].fd,
490                                       (void *)bufs[i].buffer, bufs[i].frame_len);
491     }
492     close(pme->ionfd);
493     CDBG("%s: X",__func__);
494     return rc;
495 }
496 
497 #if 0
498 static int mm_stream_deinitbuf_1(uint32_t camera_handle,
499                                  uint32_t ch_id, uint32_t stream_id,
500                                  void *user_data, uint8_t num_bufs,
501                                  mm_camera_buf_def_t *bufs)
502 {
503     int i, rc = MM_CAMERA_OK;
504     int streamType = 0;
505     mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
506     CDBG("%s: BEGIN",__func__);
507 
508     for (i= 0; i < 5; i++) {
509         if (pme->stream[i].id == stream_id) {
510             CDBG("Allocate Memory for Stream %d",i);
511             streamType = i;
512             break;
513         }
514     }
515     streamType = MM_CAMERA_PREVIEW;
516     switch (streamType) {
517     case MM_CAMERA_PREVIEW:
518         mm_stream_deinit_preview_buf(camera_handle,
519                                      ch_id, stream_id,
520                                      user_data, num_bufs,
521                                      bufs);
522         break;
523     case MM_CAMERA_VIDEO:
524         mm_stream_deinit_video_buf(camera_handle,
525                                    ch_id, stream_id,
526                                    user_data, num_bufs,
527                                    bufs);
528         break;
529     case MM_CAMERA_SNAPSHOT_MAIN:
530         mm_stream_deinit_main_buf(camera_handle,
531                                   ch_id, stream_id,
532                                   user_data, num_bufs,
533                                   bufs);
534         break;
535     case MM_CAMERA_SNAPSHOT_THUMBNAIL:
536         mm_stream_deinit_thumbnail_buf(camera_handle,
537                                        ch_id, stream_id,
538                                        user_data, num_bufs,
539                                        bufs);
540         break;
541     default:
542         break;
543     }
544 
545     /* zero out the buf stuct */
546     CDBG("%s: END",__func__);
547     return MM_CAMERA_OK;
548 }
549 #endif
550 
preview_cb_signal(mm_camera_app_obj_t * pme)551 void preview_cb_signal(mm_camera_app_obj_t *pme)
552 {
553     if (pme->cam_state == CAMERA_STATE_PREVIEW) {
554         mm_camera_app_done();
555     }
556 }
557 
mm_app_preview_notify_cb(mm_camera_super_buf_t * bufs,void * user_data)558 void mm_app_preview_notify_cb(mm_camera_super_buf_t *bufs,
559                               void *user_data)
560 {
561     int rc;
562     mm_camera_buf_def_t *frame = NULL;
563     mm_camera_app_obj_t *pme = NULL;
564     CDBG("%s: BEGIN\n", __func__);
565     frame = bufs->bufs[MM_CAMERA_PREVIEW] ;
566     pme = (mm_camera_app_obj_t *)user_data;
567 
568     CDBG("%s: BEGIN - length=%d, frame idx = %d\n", __func__, frame->frame_len, frame->frame_idx);
569 
570     //dumpFrameToFile(frame->frame,pme->dim.display_width,pme->dim.display_height,"preview", 1);
571     dumpFrameToFile(frame,pme->dim.display_width,pme->dim.display_height,"preview", 1);
572     if (!my_cam_app.run_sanity) {
573         if (0 != (rc = mm_app_dl_render(frame->fd, NULL))) {
574             CDBG("%s:DL rendering err=%d, frame fd=%d,frame idx = %d\n",
575                  __func__, rc, frame->fd, frame->frame_idx);
576         }
577     }
578 
579     CDBG("In CB function i/p = %p o/p = %p",bufs->bufs[MM_CAMERA_PREVIEW],frame);
580 
581     if (MM_CAMERA_OK != pme->cam->ops->qbuf(pme->cam->camera_handle,pme->ch_id,frame)) {
582         CDBG_ERROR("%s: Failed in Preview Qbuf\n", __func__);
583         return;
584     }
585     if (my_cam_app.run_sanity) {
586         preview_cb_signal(pme);
587     }
588     CDBG("%s: END\n", __func__);
589 
590 }
591 
mm_app_zsl_notify_cb(mm_camera_super_buf_t * bufs,void * user_data)592 static void mm_app_zsl_notify_cb(mm_camera_super_buf_t *bufs,
593                                  void *user_data)
594 {
595     int rc;
596     int i = 0;
597     mm_camera_buf_def_t *preview_frame = NULL;
598     mm_camera_buf_def_t *main_frame = NULL;
599     mm_camera_buf_def_t *thumb_frame = NULL;
600     mm_camera_app_obj_t *pme = NULL;
601     CDBG("%s: BEGIN\n", __func__);
602 
603     pme = (mm_camera_app_obj_t *)user_data;
604 
605     CDBG("%s : total streams = %d",__func__,bufs->num_bufs);
606     preview_frame = bufs->bufs[0] ;
607     main_frame = bufs->bufs[1];
608     thumb_frame = bufs->bufs[0];
609 
610     //dumpFrameToFile(preview_frame->frame,pme->dim.display_width,pme->dim.display_height,"preview", 1);
611     dumpFrameToFile(preview_frame,pme->dim.display_width,pme->dim.display_height,"zsl_preview", 1);
612     if (0 != (rc = mm_app_dl_render(preview_frame->fd, NULL))) {
613         CDBG("%s:DL rendering err=%d, frame fd=%d,frame idx = %d\n",
614              __func__, rc, preview_frame->fd, preview_frame->frame_idx);
615     }
616 
617     if (bufs->num_bufs == 2 && main_frame != NULL) {
618         CDBG("mainframe frame_idx = %d fd = %d frame length = %d",main_frame->frame_idx,main_frame->fd,main_frame->frame_len);
619         CDBG("thumnail frame_idx = %d fd = %d frame length = %d",thumb_frame->frame_idx,thumb_frame->fd,thumb_frame->frame_len);
620 
621         //dumpFrameToFile(main_frame->frame,pme->dim.picture_width,pme->dim.picture_height,"main", 1);
622         //dumpFrameToFile(thumb_frame->frame,pme->dim.thumbnail_width,pme->dim.thumbnail_height,"thumb", 1);
623 
624         dumpFrameToFile(main_frame,pme->dim.picture_width,pme->dim.picture_height,"zsl_main", 1);
625         dumpFrameToFile(thumb_frame,pme->dim.thumbnail_width,pme->dim.thumbnail_height,"zsl_thumb", 1);
626 
627         if (MM_CAMERA_OK != pme->cam->ops->qbuf(pme->cam->camera_handle,pme->ch_id,main_frame)) {
628             CDBG_ERROR("%s: Failed in thumbnail Qbuf\n", __func__);
629         }
630     }
631 
632     if (MM_CAMERA_OK != pme->cam->ops->qbuf(pme->cam->camera_handle,pme->ch_id,preview_frame)) {
633         CDBG_ERROR("%s: Failed in Preview Qbuf\n", __func__);
634     }
635     CDBG("%s: END\n", __func__);
636 }
637 
mm_app_prepare_preview(int cam_id)638 int mm_app_prepare_preview(int cam_id)
639 {
640     int rc = MM_CAMERA_OK;
641     int op_mode;
642 
643     CDBG("%s: E",__func__);
644     mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
645 
646     pme->mem_cam->get_buf = mm_stream_initbuf;
647     pme->mem_cam->put_buf = mm_stream_deinitbuf;
648     pme->mem_cam->user_data = pme;
649 
650     op_mode = MM_CAMERA_OP_MODE_VIDEO;
651     if (MM_CAMERA_OK != (rc = pme->cam->ops->set_parm(
652                                                      pme->cam->camera_handle,MM_CAMERA_PARM_OP_MODE, &op_mode))) {
653         CDBG_ERROR("%s: Set preview op mode error",__func__);
654         goto end;
655     }
656 
657     pme->stream[MM_CAMERA_PREVIEW].id = pme->cam->ops->add_stream(pme->cam->camera_handle,pme->ch_id,
658                                                                   mm_app_preview_notify_cb,pme,
659                                                                   MM_CAMERA_PREVIEW, 0);
660 
661     if (!pme->stream[MM_CAMERA_PREVIEW].id) {
662         CDBG_ERROR("%s:Add stream preview error =%d\n", __func__, rc);
663         rc = -1;
664         goto end;
665     }
666 
667     CDBG("%s :Add stream is successfull stream ID = %d",__func__,pme->stream[MM_CAMERA_PREVIEW].id);
668 
669     mm_app_set_preview_fmt(cam_id,&pme->stream[MM_CAMERA_PREVIEW].str_config.fmt);
670     pme->stream[MM_CAMERA_PREVIEW].str_config.need_stream_on = 1;
671     pme->stream[MM_CAMERA_PREVIEW].str_config.num_of_bufs = PREVIEW_BUF_NUM;
672 
673     if (MM_CAMERA_OK != (rc = pme->cam->ops->config_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_PREVIEW].id,
674                                                            &pme->stream[MM_CAMERA_PREVIEW].str_config))) {
675         CDBG_ERROR("%s:preview streaming err=%d\n", __func__, rc);
676         goto end;
677     }
678     end:
679     return rc;
680 }
681 
mm_app_unprepare_preview(int cam_id)682 int mm_app_unprepare_preview(int cam_id)
683 {
684     int rc = MM_CAMERA_OK;
685     return rc;
686 }
687 
mm_app_streamon_preview(int cam_id)688 int mm_app_streamon_preview(int cam_id)
689 {
690     int rc = MM_CAMERA_OK;
691     int stream[2];
692     mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
693     mm_camera_frame_len_offset frame_offset_info;
694 
695     stream[0] = pme->stream[MM_CAMERA_PREVIEW].id;
696     stream[1] = 0;
697 
698     pme->cam->ops->get_stream_parm(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_PREVIEW].id,MM_CAMERA_STREAM_OFFSET,&frame_offset_info);
699     ALOGE("DEBUG : length = %d",frame_offset_info.frame_len);
700     if (MM_CAMERA_OK != (rc = pme->cam->ops->start_streams(pme->cam->camera_handle,pme->ch_id,1,&stream))) {
701         CDBG_ERROR("%s : Start Stream preview Error",__func__);
702         goto end;
703     }
704     pme->cam_state = CAMERA_STATE_PREVIEW;
705     end:
706     CDBG("%s: X rc = %d",__func__,rc);
707     return rc;
708 }
709 
mm_app_prepare_preview_zsl(int cam_id)710 int mm_app_prepare_preview_zsl(int cam_id)
711 {
712     int rc = MM_CAMERA_OK;
713     mm_camera_bundle_attr_t attr;
714     int stream[3];
715 
716     mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
717     int op_mode = 0;
718 
719     op_mode = MM_CAMERA_OP_MODE_ZSL;
720     if (MM_CAMERA_OK != (rc = pme->cam->ops->set_parm(
721                                                      pme->cam->camera_handle,MM_CAMERA_PARM_OP_MODE, &op_mode))) {
722         CDBG_ERROR("%s: Set preview op mode error",__func__);
723         goto end;
724     }
725 
726     pme->stream[MM_CAMERA_PREVIEW].id = pme->cam->ops->add_stream(pme->cam->camera_handle,pme->ch_id,
727                                                                   mm_app_preview_notify_cb,pme,
728                                                                   MM_CAMERA_PREVIEW, 0);
729 
730     if (!pme->stream[MM_CAMERA_PREVIEW].id) {
731         CDBG_ERROR("%s:Add stream preview error =%d\n", __func__, rc);
732         goto end;
733     }
734 
735     CDBG("%s :Add stream is successfull stream ID = %d",__func__,pme->stream[MM_CAMERA_PREVIEW].id);
736 
737     mm_app_set_preview_fmt(cam_id,&pme->stream[MM_CAMERA_PREVIEW].str_config.fmt);
738     pme->stream[MM_CAMERA_PREVIEW].str_config.need_stream_on = 1;
739     pme->stream[MM_CAMERA_PREVIEW].str_config.num_of_bufs = PREVIEW_BUF_NUM;
740 
741     if (MM_CAMERA_OK != (rc = pme->cam->ops->config_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_PREVIEW].id,
742                                                            &pme->stream[MM_CAMERA_PREVIEW].str_config))) {
743         CDBG_ERROR("%s:preview streaming err=%d\n", __func__, rc);
744         goto end;
745     }
746 
747     pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id = pme->cam->ops->add_stream(pme->cam->camera_handle,pme->ch_id,
748                                                                         NULL,pme,
749                                                                         MM_CAMERA_SNAPSHOT_MAIN, 0);
750 
751     CDBG("Add Snapshot main is successfull stream ID = %d",pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id);
752     if (!pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id) {
753         CDBG_ERROR("%s:preview streaming err=%d\n", __func__, rc);
754         rc = -1;
755         goto end;
756     }
757 
758     pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config.need_stream_on = 1;
759     pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config.num_of_bufs = 7;
760 
761     mm_app_set_snapshot_fmt(cam_id,&pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config.fmt);
762 
763 
764     if (MM_CAMERA_OK != (rc = pme->cam->ops->config_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id,
765                                                            &pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config))) {
766         CDBG_ERROR("%s:preview streaming err=%d\n", __func__, rc);
767         goto end;
768     }
769     end:
770     CDBG("%s: END, rc=%d\n", __func__, rc);
771     return rc;
772 }
773 
mm_app_streamon_preview_zsl(int cam_id)774 int mm_app_streamon_preview_zsl(int cam_id)
775 {
776     int rc = MM_CAMERA_OK;
777     mm_camera_bundle_attr_t attr;
778     int stream[3];
779 
780     mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
781     int op_mode = 0;
782 
783 
784     stream[0] = pme->stream[MM_CAMERA_PREVIEW].id;
785     stream[1] = pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id;
786 
787     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST;
788     attr.burst_num = 1;
789     attr.look_back = 2;
790     attr.post_frame_skip = 0;
791     attr.water_mark = 2;
792 
793     if (MM_CAMERA_OK != (rc = pme->cam->ops->init_stream_bundle(
794                                                                pme->cam->camera_handle,pme->ch_id,mm_app_zsl_notify_cb,pme,&attr,2,stream))) {
795         CDBG_ERROR("%s:init_stream_bundle err=%d\n", __func__, rc);
796         rc = -1;
797         goto end;
798     }
799 
800     if (MM_CAMERA_OK != (rc = pme->cam->ops->start_streams(pme->cam->camera_handle,pme->ch_id,
801                                                            2, stream))) {
802         CDBG_ERROR("%s:start_streams err=%d\n", __func__, rc);
803         rc = -1;
804         goto end;
805     }
806     pme->cam_state = CAMERA_STATE_PREVIEW;
807     end:
808     CDBG("%s: END, rc=%d\n", __func__, rc);
809     return rc;
810 
811 }
812 
initDisplay()813 int initDisplay()
814 {
815     int rc = MM_CAMERA_OK;
816 
817     use_overlay_fb_display_driver();
818     if (launch_camframe_fb_thread()) {
819         CDBG_ERROR("%s:launch_camframe_fb_thread failed!\n", __func__);
820         //rc = -MM_CAMERA_E_GENERAL;
821     }
822     CDBG("%s: launch_camframe_fb_thread done\n", __func__);
823     return rc;
824 }
825 
deinitDisplay()826 int deinitDisplay()
827 {
828     /* stop the display thread */
829     release_camframe_fb_thread();
830     return MM_CAMERA_OK;
831 }
832 
mm_app_start_preview(int cam_id)833 int mm_app_start_preview(int cam_id)
834 {
835     int rc = MM_CAMERA_OK;
836 
837     mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
838     int op_mode = 0;
839 
840     CDBG("pme = %p, pme->cam =%p, pme->cam->camera_handle = %d",
841          pme,pme->cam,pme->cam->camera_handle);
842 
843     if (pme->cam_state == CAMERA_STATE_PREVIEW) {
844         return rc;
845     }
846 
847     if (!my_cam_app.run_sanity) {
848         if (MM_CAMERA_OK != initDisplay()) {
849             CDBG_ERROR("%s : Could not initalize display",__func__);
850             goto end;
851         }
852     }
853 
854     if (MM_CAMERA_OK != (rc = mm_app_prepare_preview(cam_id))) {
855         CDBG_ERROR("%s:Stream On Preview failed rc=%d\n", __func__, rc);
856         goto end;
857     }
858 
859     if (MM_CAMERA_OK != (rc = mm_app_streamon_preview(cam_id))) {
860         CDBG_ERROR("%s:Stream On Preview failed rc=%d\n", __func__, rc);
861         goto end;
862     }
863 
864     end:
865     CDBG("%s: END, rc=%d\n", __func__, rc);
866     return rc;
867 }
868 
mm_app_start_preview_zsl(int cam_id)869 int mm_app_start_preview_zsl(int cam_id)
870 {
871     int rc = MM_CAMERA_OK;
872 
873     mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
874 
875     CDBG("pme = %p, pme->cam =%p, pme->cam->camera_handle = %d",
876          pme,pme->cam,pme->cam->camera_handle);
877 
878     if (!my_cam_app.run_sanity) {
879         if (MM_CAMERA_OK != initDisplay()) {
880             CDBG_ERROR("%s : Could not initalize display",__func__);
881             goto end;
882         }
883     }
884 
885     pme->mem_cam->get_buf = mm_stream_initbuf;
886     pme->mem_cam->put_buf = mm_stream_deinitbuf;
887     pme->mem_cam->user_data = pme;
888 
889     if (MM_CAMERA_OK != (rc = mm_app_prepare_preview_zsl(cam_id))) {
890         CDBG_ERROR("%s:Prepare preview err=%d\n", __func__, rc);
891         goto end;
892     }
893 
894     if (MM_CAMERA_OK != (rc = mm_app_streamon_preview_zsl(cam_id))) {
895         CDBG_ERROR("%s:stream on preview err=%d\n", __func__, rc);
896         goto end;
897     }
898 
899     /*if(MM_CAMERA_OK != (rc = mm_app_bundle_zsl_stream(cam_id))){
900         CDBG_ERROR("%s: bundle and start of ZSl err=%d\n", __func__, rc);
901         goto end;
902     }*/
903 
904     end:
905     CDBG("%s: END, rc=%d\n", __func__, rc);
906     return rc;
907 }
908 
mm_app_streamoff_preview(int cam_id)909 static int mm_app_streamoff_preview(int cam_id)
910 {
911     int rc = MM_CAMERA_OK;
912     int stream[2];
913 
914     mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
915 
916     stream[0] = pme->stream[MM_CAMERA_PREVIEW].id;
917     stream[1] = 0;
918 
919     if (MM_CAMERA_OK != (rc = pme->cam->ops->stop_streams(pme->cam->camera_handle,pme->ch_id,1,&stream))) {
920         CDBG_ERROR("%s : Preview Stream off Error",__func__);
921         goto end;
922     }
923 
924     if (MM_CAMERA_OK != (rc = pme->cam->ops->del_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_PREVIEW].id))) {
925         CDBG_ERROR("%s : Delete Stream Preview error",__func__);
926         goto end;
927     }
928     CDBG("del_stream successfull");
929     pme->cam_state = CAMERA_STATE_OPEN;
930     end:
931     CDBG("%s: END, rc=%d\n", __func__, rc);
932 
933     return rc;
934 }
935 
mm_app_streamoff_preview_zsl(int cam_id)936 static int mm_app_streamoff_preview_zsl(int cam_id)
937 {
938     int rc = MM_CAMERA_OK;
939     int stream[2];
940 
941     mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
942 
943     stream[0] = pme->stream[MM_CAMERA_PREVIEW].id;
944     stream[1] = pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id;
945 
946     if (MM_CAMERA_OK != (rc = pme->cam->ops->destroy_stream_bundle(pme->cam->camera_handle,pme->ch_id))) {
947         CDBG_ERROR("%s : ZSL Snapshot destroy_stream_bundle Error",__func__);
948         goto end;
949     }
950 
951     if (MM_CAMERA_OK != (rc = pme->cam->ops->stop_streams(pme->cam->camera_handle,pme->ch_id,2,&stream))) {
952         CDBG_ERROR("%s : Preview Stream off Error",__func__);
953         goto end;
954     }
955 
956     if (MM_CAMERA_OK != (rc = pme->cam->ops->del_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_PREVIEW].id))) {
957         CDBG_ERROR("%s : Delete Stream Preview error",__func__);
958         goto end;
959     }
960 
961     if (MM_CAMERA_OK != (rc = pme->cam->ops->del_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id))) {
962         CDBG_ERROR("%s : Delete Stream Preview error",__func__);
963         goto end;
964     }
965     CDBG("del_stream successfull");
966     pme->cam_state = CAMERA_STATE_OPEN;
967     end:
968     CDBG("%s: END, rc=%d\n", __func__, rc);
969 
970     return rc;
971 }
972 
startPreview(int cam_id)973 int startPreview(int cam_id)
974 {
975     int rc = MM_CAMERA_OK;
976 
977     mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
978 
979     CDBG("%s: Start Preview",__func__);
980 
981     if (pme->cam_mode == ZSL_MODE || pme->cam_mode == RECORDER_MODE) {
982         switch (pme->cam_state) {
983         case CAMERA_STATE_RECORD:
984             if (MM_CAMERA_OK != mm_app_stop_video(cam_id)) {
985                 CDBG_ERROR("%s:Cannot stop video err=%d\n", __func__, rc);
986                 return -1;
987             }
988         case CAMERA_STATE_PREVIEW:
989             if (MM_CAMERA_OK != mm_app_open_camera(cam_id)) {
990                 CDBG_ERROR("%s: Cannot switch to camera mode=%d\n", __func__);
991                 return -1;
992             }
993             break;
994         case CAMERA_STATE_SNAPSHOT:
995         default:
996             break;
997         }
998     } else if (pme->cam_mode == CAMERA_MODE && pme->cam_state == CAMERA_STATE_OPEN) {
999 
1000         if (MM_CAMERA_OK != (rc = mm_app_start_preview(cam_id))) {
1001             CDBG_ERROR("%s:preview streaming on err=%d\n", __func__, rc);
1002             return -1;
1003         }
1004     }
1005     CDBG("%s: END, rc=%d\n", __func__, rc);
1006     return rc;
1007 }
1008 
stopPreview(int cam_id)1009 int stopPreview(int cam_id)
1010 {
1011     int rc = MM_CAMERA_OK;
1012     mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
1013 
1014     CDBG("%s : pme->cam_mode = %d, pme->cam_state = %d",__func__,pme->cam_mode,pme->cam_state);
1015 
1016     if (pme->cam_mode == CAMERA_MODE && pme->cam_state == CAMERA_STATE_PREVIEW) {
1017         if (MM_CAMERA_OK != (rc = mm_app_stop_preview(cam_id))) {
1018             CDBG("%s:streamoff preview err=%d\n", __func__, rc);
1019             goto end;
1020         }
1021     } else if (pme->cam_mode == ZSL_MODE && pme->cam_state == CAMERA_STATE_PREVIEW) {
1022         if (MM_CAMERA_OK != (rc = mm_app_stop_preview_zsl(cam_id))) {
1023             CDBG("%s:streamoff preview err=%d\n", __func__, rc);
1024             goto end;
1025         }
1026     } else if (pme->cam_mode == RECORDER_MODE && pme->cam_state == CAMERA_STATE_PREVIEW) {
1027         if (MM_CAMERA_OK != (rc = mm_app_stop_preview(cam_id))) {
1028             CDBG("%s:streamoff preview err=%d\n", __func__, rc);
1029             goto end;
1030         }
1031         mm_app_unprepare_video(cam_id);
1032     }
1033     end:
1034     return rc;
1035 }
1036 
mm_app_stop_preview(int cam_id)1037 int mm_app_stop_preview(int cam_id)
1038 {
1039     int rc = MM_CAMERA_OK;
1040 
1041     mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
1042 
1043     if (MM_CAMERA_OK != (rc = mm_app_streamoff_preview(cam_id))) {
1044         CDBG_ERROR("%s : Delete Stream Preview error",__func__);
1045         goto end;
1046     }
1047 
1048     CDBG("Stop Preview successfull");
1049 
1050     if (!my_cam_app.run_sanity) {
1051         deinitDisplay();
1052     }
1053     end:
1054     CDBG("%s: END, rc=%d\n", __func__, rc);
1055     return rc;
1056 }
1057 
mm_app_stop_preview_zsl(int cam_id)1058 int mm_app_stop_preview_zsl(int cam_id)
1059 {
1060     int rc = MM_CAMERA_OK;
1061 
1062     mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
1063 
1064     if (MM_CAMERA_OK != (rc = mm_app_streamoff_preview_zsl(cam_id))) {
1065         CDBG_ERROR("%s : Delete Stream Preview error",__func__);
1066         goto end;
1067     }
1068 
1069     CDBG("Stop Preview successfull");
1070     if (!my_cam_app.run_sanity) {
1071         deinitDisplay();
1072     }
1073     end:
1074     CDBG("%s: END, rc=%d\n", __func__, rc);
1075     return rc;
1076 }
1077