Home | History | Annotate | Download | only in src
      1 /* Copyright (c) 2012-2013, 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 #include "mm_qcamera_dbg.h"
     31 #include "mm_qcamera_app.h"
     32 
     33 /* This callback is received once the complete JPEG encoding is done */
     34 static void jpeg_encode_cb(jpeg_job_status_t status,
     35                            uint32_t client_hdl,
     36                            uint32_t jobId,
     37                            mm_jpeg_output_t *p_buf,
     38                            void *userData)
     39 {
     40     int i = 0;
     41     mm_camera_test_obj_t *pme = NULL;
     42     CDBG("%s: BEGIN\n", __func__);
     43 
     44     pme = (mm_camera_test_obj_t *)userData;
     45     if (pme->jpeg_hdl != client_hdl ||
     46         jobId != pme->current_job_id ||
     47         !pme->current_job_frames) {
     48         CDBG_ERROR("%s: NULL current job frames or not matching job ID (%d, %d)",
     49                    __func__, jobId, pme->current_job_id);
     50         return;
     51     }
     52 
     53     /* dump jpeg img */
     54     CDBG_ERROR("%s: job %d, status=%d", __func__, jobId, status);
     55     if (status == JPEG_JOB_STATUS_DONE && p_buf != NULL) {
     56         mm_app_dump_jpeg_frame(p_buf->buf_vaddr, p_buf->buf_filled_len, "jpeg_dump", "jpg", jobId);
     57     }
     58 
     59     /* buf done current encoding frames */
     60     pme->current_job_id = 0;
     61     for (i = 0; i < pme->current_job_frames->num_bufs; i++) {
     62         if (MM_CAMERA_OK != pme->cam->ops->qbuf(pme->current_job_frames->camera_handle,
     63                                                 pme->current_job_frames->ch_id,
     64                                                 pme->current_job_frames->bufs[i])) {
     65             CDBG_ERROR("%s: Failed in Qbuf\n", __func__);
     66         }
     67     }
     68     free(pme->current_job_frames);
     69     pme->current_job_frames = NULL;
     70 
     71     /* signal snapshot is done */
     72     mm_camera_app_done();
     73 }
     74 
     75 int encodeData(mm_camera_test_obj_t *test_obj, mm_camera_super_buf_t* recvd_frame,
     76                mm_camera_stream_t *m_stream)
     77 {
     78     cam_capability_t *cam_cap = (cam_capability_t *)(test_obj->cap_buf.buf.buffer);
     79 
     80     int rc = -MM_CAMERA_E_GENERAL;
     81     mm_jpeg_job_t job;
     82 
     83     /* remember current frames being encoded */
     84     test_obj->current_job_frames =
     85         (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
     86     if (!test_obj->current_job_frames) {
     87         CDBG_ERROR("%s: No memory for current_job_frames", __func__);
     88         return rc;
     89     }
     90     *(test_obj->current_job_frames) = *recvd_frame;
     91 
     92     memset(&job, 0, sizeof(job));
     93     job.job_type = JPEG_JOB_TYPE_ENCODE;
     94     job.encode_job.session_id = test_obj->current_jpeg_sess_id;
     95 
     96     job.encode_job.rotation = 0;
     97     if (cam_cap->position == CAM_POSITION_BACK) {
     98         /* back camera, rotate 90 */
     99         job.encode_job.rotation = 90;
    100     }
    101 
    102     /* fill in main src img encode param */
    103     job.encode_job.main_dim.src_dim = m_stream->s_config.stream_info->dim;
    104     job.encode_job.main_dim.dst_dim = m_stream->s_config.stream_info->dim;
    105     job.encode_job.src_index = 0;
    106 
    107     job.encode_job.thumb_dim.src_dim = m_stream->s_config.stream_info->dim;
    108     job.encode_job.thumb_dim.dst_dim.width = DEFAULT_PREVIEW_WIDTH;
    109     job.encode_job.thumb_dim.dst_dim.height = DEFAULT_PREVIEW_HEIGHT;
    110 
    111     /* fill in sink img param */
    112     job.encode_job.dst_index = 0;
    113 
    114     rc = test_obj->jpeg_ops.start_job(&job, &test_obj->current_job_id);
    115     if ( 0 != rc ) {
    116         free(test_obj->current_job_frames);
    117         test_obj->current_job_frames = NULL;
    118     }
    119 
    120     return rc;
    121 }
    122 
    123 int createEncodingSession(mm_camera_test_obj_t *test_obj,
    124                           mm_camera_stream_t *m_stream,
    125                           mm_camera_buf_def_t *m_frame)
    126 {
    127     mm_jpeg_encode_params_t encode_param;
    128 
    129     memset(&encode_param, 0, sizeof(mm_jpeg_encode_params_t));
    130     encode_param.jpeg_cb = jpeg_encode_cb;
    131     encode_param.userdata = (void*)test_obj;
    132     encode_param.encode_thumbnail = 1;
    133     encode_param.quality = 85;
    134     encode_param.color_format = MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
    135 
    136     /* fill in main src img encode param */
    137     encode_param.num_src_bufs = 1;
    138     encode_param.src_main_buf[0].index = 0;
    139     encode_param.src_main_buf[0].buf_size = m_frame->frame_len;
    140     encode_param.src_main_buf[0].buf_vaddr = (uint8_t *)m_frame->buffer;
    141     encode_param.src_main_buf[0].fd = m_frame->fd;
    142     encode_param.src_main_buf[0].format = MM_JPEG_FMT_YUV;
    143     encode_param.src_main_buf[0].offset = m_stream->offset;
    144 
    145     /* fill in sink img param */
    146     encode_param.num_dst_bufs = 1;
    147     encode_param.dest_buf[0].index = 0;
    148     encode_param.dest_buf[0].buf_size = test_obj->jpeg_buf.buf.frame_len;
    149     encode_param.dest_buf[0].buf_vaddr = (uint8_t *)test_obj->jpeg_buf.buf.buffer;
    150     encode_param.dest_buf[0].fd = test_obj->jpeg_buf.buf.fd;
    151     encode_param.dest_buf[0].format = MM_JPEG_FMT_YUV;
    152 
    153     return test_obj->jpeg_ops.create_session(test_obj->jpeg_hdl,
    154                                              &encode_param,
    155                                              &test_obj->current_jpeg_sess_id);
    156 }
    157 
    158 static void mm_app_snapshot_notify_cb(mm_camera_super_buf_t *bufs,
    159                                       void *user_data)
    160 {
    161 
    162     int rc;
    163     int i = 0;
    164     mm_camera_test_obj_t *pme = (mm_camera_test_obj_t *)user_data;
    165     mm_camera_channel_t *channel = NULL;
    166     mm_camera_stream_t *p_stream = NULL;
    167     mm_camera_stream_t *m_stream = NULL;
    168     mm_camera_buf_def_t *p_frame = NULL;
    169     mm_camera_buf_def_t *m_frame = NULL;
    170 
    171     CDBG("%s: BEGIN\n", __func__);
    172 
    173     /* find channel */
    174     for (i = 0; i < MM_CHANNEL_TYPE_MAX; i++) {
    175         if (pme->channels[i].ch_id == bufs->ch_id) {
    176             channel = &pme->channels[i];
    177             break;
    178         }
    179     }
    180     if (NULL == channel) {
    181         CDBG_ERROR("%s: Wrong channel id (%d)", __func__, bufs->ch_id);
    182         rc = -1;
    183         goto error;
    184     }
    185 
    186     /* find snapshot stream */
    187     for (i = 0; i < channel->num_streams; i++) {
    188         if (channel->streams[i].s_config.stream_info->stream_type == CAM_STREAM_TYPE_SNAPSHOT) {
    189             m_stream = &channel->streams[i];
    190             break;
    191         }
    192     }
    193     if (NULL == m_stream) {
    194         CDBG_ERROR("%s: cannot find snapshot stream", __func__);
    195         rc = -1;
    196         goto error;
    197     }
    198 
    199     /* find snapshot frame */
    200     for (i = 0; i < bufs->num_bufs; i++) {
    201         if (bufs->bufs[i]->stream_id == m_stream->s_id) {
    202             m_frame = bufs->bufs[i];
    203             break;
    204         }
    205     }
    206     if (NULL == m_frame) {
    207         CDBG_ERROR("%s: main frame is NULL", __func__);
    208         rc = -1;
    209         goto error;
    210     }
    211 
    212     mm_app_dump_frame(m_frame, "main", "yuv", m_frame->frame_idx);
    213 
    214     /* find postview stream */
    215     for (i = 0; i < channel->num_streams; i++) {
    216         if (channel->streams[i].s_config.stream_info->stream_type == CAM_STREAM_TYPE_POSTVIEW) {
    217             p_stream = &channel->streams[i];
    218             break;
    219         }
    220     }
    221     if (NULL != p_stream) {
    222         /* find preview frame */
    223         for (i = 0; i < bufs->num_bufs; i++) {
    224             if (bufs->bufs[i]->stream_id == p_stream->s_id) {
    225                 p_frame = bufs->bufs[i];
    226                 break;
    227             }
    228         }
    229         if (NULL != p_frame) {
    230             mm_app_dump_frame(p_frame, "postview", "yuv", p_frame->frame_idx);
    231         }
    232     }
    233 
    234     mm_app_cache_ops((mm_camera_app_meminfo_t *)m_frame->mem_info,
    235                      ION_IOC_CLEAN_INV_CACHES);
    236 
    237     /* create a new jpeg encoding session */
    238     rc = createEncodingSession(pme, m_stream, m_frame);
    239     if (0 != rc) {
    240         CDBG_ERROR("%s: error creating jpeg session", __func__);
    241         goto error;
    242     }
    243 
    244     /* start jpeg encoding job */
    245     rc = encodeData(pme, bufs, m_stream);
    246 
    247 error:
    248     /* buf done rcvd frames in error case */
    249     if ( 0 != rc ) {
    250         for (i=0; i<bufs->num_bufs; i++) {
    251             if (MM_CAMERA_OK != pme->cam->ops->qbuf(bufs->camera_handle,
    252                                                     bufs->ch_id,
    253                                                     bufs->bufs[i])) {
    254                 CDBG_ERROR("%s: Failed in Qbuf\n", __func__);
    255             }
    256             mm_app_cache_ops((mm_camera_app_meminfo_t *)bufs->bufs[i]->mem_info,
    257                              ION_IOC_INV_CACHES);
    258         }
    259     }
    260 
    261     CDBG("%s: END\n", __func__);
    262 }
    263 
    264 mm_camera_channel_t * mm_app_add_snapshot_channel(mm_camera_test_obj_t *test_obj)
    265 {
    266     mm_camera_channel_t *channel = NULL;
    267     mm_camera_stream_t *stream = NULL;
    268 
    269     channel = mm_app_add_channel(test_obj,
    270                                  MM_CHANNEL_TYPE_SNAPSHOT,
    271                                  NULL,
    272                                  NULL,
    273                                  NULL);
    274     if (NULL == channel) {
    275         CDBG_ERROR("%s: add channel failed", __func__);
    276         return NULL;
    277     }
    278 
    279     stream = mm_app_add_snapshot_stream(test_obj,
    280                                         channel,
    281                                         mm_app_snapshot_notify_cb,
    282                                         (void *)test_obj,
    283                                         1,
    284                                         1);
    285     if (NULL == stream) {
    286         CDBG_ERROR("%s: add snapshot stream failed\n", __func__);
    287         mm_app_del_channel(test_obj, channel);
    288         return NULL;
    289     }
    290 
    291     return channel;
    292 }
    293 
    294 mm_camera_stream_t * mm_app_add_postview_stream(mm_camera_test_obj_t *test_obj,
    295                                                 mm_camera_channel_t *channel,
    296                                                 mm_camera_buf_notify_t stream_cb,
    297                                                 void *userdata,
    298                                                 uint8_t num_bufs,
    299                                                 uint8_t num_burst)
    300 {
    301     int rc = MM_CAMERA_OK;
    302     mm_camera_stream_t *stream = NULL;
    303     cam_capability_t *cam_cap = (cam_capability_t *)(test_obj->cap_buf.buf.buffer);
    304 
    305     stream = mm_app_add_stream(test_obj, channel);
    306     if (NULL == stream) {
    307         CDBG_ERROR("%s: add stream failed\n", __func__);
    308         return NULL;
    309     }
    310 
    311     stream->s_config.mem_vtbl.get_bufs = mm_app_stream_initbuf;
    312     stream->s_config.mem_vtbl.put_bufs = mm_app_stream_deinitbuf;
    313     stream->s_config.mem_vtbl.clean_invalidate_buf =
    314       mm_app_stream_clean_invalidate_buf;
    315     stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
    316     stream->s_config.mem_vtbl.user_data = (void *)stream;
    317     stream->s_config.stream_cb = stream_cb;
    318     stream->s_config.userdata = userdata;
    319     stream->num_of_bufs = num_bufs;
    320 
    321     stream->s_config.stream_info = (cam_stream_info_t *)stream->s_info_buf.buf.buffer;
    322     memset(stream->s_config.stream_info, 0, sizeof(cam_stream_info_t));
    323     stream->s_config.stream_info->stream_type = CAM_STREAM_TYPE_POSTVIEW;
    324     if (num_burst == 0) {
    325         stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
    326     } else {
    327         stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_BURST;
    328         stream->s_config.stream_info->num_of_burst = num_burst;
    329     }
    330     stream->s_config.stream_info->fmt = DEFAULT_PREVIEW_FORMAT;
    331     stream->s_config.stream_info->dim.width = DEFAULT_PREVIEW_WIDTH;
    332     stream->s_config.stream_info->dim.height = DEFAULT_PREVIEW_HEIGHT;
    333     stream->s_config.padding_info = cam_cap->padding_info;
    334 
    335     rc = mm_app_config_stream(test_obj, channel, stream, &stream->s_config);
    336     if (MM_CAMERA_OK != rc) {
    337         CDBG_ERROR("%s:config preview stream err=%d\n", __func__, rc);
    338         return NULL;
    339     }
    340 
    341     return stream;
    342 }
    343 
    344 int mm_app_start_capture(mm_camera_test_obj_t *test_obj,
    345                          uint8_t num_snapshots)
    346 {
    347     int32_t rc = MM_CAMERA_OK;
    348     mm_camera_channel_t *channel = NULL;
    349     mm_camera_stream_t *s_main = NULL;
    350     mm_camera_stream_t *s_postview = NULL;
    351     mm_camera_channel_attr_t attr;
    352 
    353     memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
    354     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
    355     attr.max_unmatched_frames = 3;
    356     channel = mm_app_add_channel(test_obj,
    357                                  MM_CHANNEL_TYPE_CAPTURE,
    358                                  &attr,
    359                                  mm_app_snapshot_notify_cb,
    360                                  test_obj);
    361     if (NULL == channel) {
    362         CDBG_ERROR("%s: add channel failed", __func__);
    363         return -MM_CAMERA_E_GENERAL;
    364     }
    365 
    366     s_postview = mm_app_add_postview_stream(test_obj,
    367                                             channel,
    368                                             NULL,
    369                                             NULL,
    370                                             num_snapshots,
    371                                             num_snapshots);
    372     if (NULL == s_postview) {
    373         CDBG_ERROR("%s: add preview stream failed\n", __func__);
    374         mm_app_del_channel(test_obj, channel);
    375         return rc;
    376     }
    377 
    378     s_main = mm_app_add_snapshot_stream(test_obj,
    379                                         channel,
    380                                         NULL,
    381                                         NULL,
    382                                         num_snapshots,
    383                                         num_snapshots);
    384     if (NULL == s_main) {
    385         CDBG_ERROR("%s: add main snapshot stream failed\n", __func__);
    386         mm_app_del_stream(test_obj, channel, s_postview);
    387         mm_app_del_channel(test_obj, channel);
    388         return rc;
    389     }
    390 
    391     rc = mm_app_start_channel(test_obj, channel);
    392     if (MM_CAMERA_OK != rc) {
    393         CDBG_ERROR("%s:start zsl failed rc=%d\n", __func__, rc);
    394         mm_app_del_stream(test_obj, channel, s_postview);
    395         mm_app_del_stream(test_obj, channel, s_main);
    396         mm_app_del_channel(test_obj, channel);
    397         return rc;
    398     }
    399 
    400     return rc;
    401 }
    402 
    403 int mm_app_stop_capture(mm_camera_test_obj_t *test_obj)
    404 {
    405     int rc = MM_CAMERA_OK;
    406     mm_camera_channel_t *ch = NULL;
    407 
    408     ch = mm_app_get_channel_by_type(test_obj, MM_CHANNEL_TYPE_CAPTURE);
    409 
    410     rc = mm_app_stop_channel(test_obj, ch);
    411     if (MM_CAMERA_OK != rc) {
    412         CDBG_ERROR("%s:stop recording failed rc=%d\n", __func__, rc);
    413     }
    414 
    415     return rc;
    416 }
    417