• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
jpeg_encode_cb(jpeg_job_status_t status,uint32_t client_hdl,uint32_t jobId,mm_jpeg_output_t * p_buf,void * userData)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 
encodeData(mm_camera_test_obj_t * test_obj,mm_camera_super_buf_t * recvd_frame,mm_camera_stream_t * m_stream)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 
createEncodingSession(mm_camera_test_obj_t * test_obj,mm_camera_stream_t * m_stream,mm_camera_buf_def_t * m_frame)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 
mm_app_snapshot_notify_cb(mm_camera_super_buf_t * bufs,void * user_data)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 
mm_app_add_snapshot_channel(mm_camera_test_obj_t * test_obj)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 
mm_app_add_postview_stream(mm_camera_test_obj_t * test_obj,mm_camera_channel_t * channel,mm_camera_buf_notify_t stream_cb,void * userdata,uint8_t num_bufs,uint8_t num_burst)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 
mm_app_start_capture(mm_camera_test_obj_t * test_obj,uint8_t num_snapshots)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 
mm_app_stop_capture(mm_camera_test_obj_t * test_obj)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