1/*
2Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
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 The Linux Foundation 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
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
30// System dependencies
31#include <fcntl.h>
32
33// Camera dependencies
34#include "mm_qcamera_app.h"
35#include "mm_qcamera_dbg.h"
36
37static uint32_t rdi_len = 0;
38
39static void mm_app_rdi_dump_frame(mm_camera_buf_def_t *frame,
40                                  char *name,
41                                  char *ext,
42                                  uint32_t frame_idx)
43{
44    char file_name[FILENAME_MAX];
45    int file_fd;
46    int i;
47
48    if (frame != NULL) {
49        snprintf(file_name, sizeof(file_name),
50            QCAMERA_DUMP_FRM_LOCATION"%s_%03u.%s", name, frame_idx, ext);
51        file_fd = open(file_name, O_RDWR | O_CREAT, 0777);
52        if (file_fd < 0) {
53            LOGE(" cannot open file %s \n",  file_name);
54        } else {
55            for (i = 0; i < frame->planes_buf.num_planes; i++) {
56                write(file_fd,
57                      (uint8_t *)frame->buffer + frame->planes_buf.planes[i].data_offset,
58                      rdi_len);
59            }
60
61            close(file_fd);
62            LOGD(" dump rdi frame %s", file_name);
63        }
64    }
65}
66
67static void mm_app_rdi_notify_cb(mm_camera_super_buf_t *bufs,
68                                 void *user_data)
69{
70    char file_name[FILENAME_MAX];
71    mm_camera_buf_def_t *frame = bufs->bufs[0];
72    mm_camera_test_obj_t *pme = (mm_camera_test_obj_t *)user_data;
73
74    LOGD(" BEGIN - length=%zu, frame idx = %d stream_id=%d\n",
75          frame->frame_len, frame->frame_idx, frame->stream_id);
76    snprintf(file_name, sizeof(file_name), "RDI_dump_%d", pme->cam->camera_handle);
77    mm_app_rdi_dump_frame(frame, file_name, "raw", frame->frame_idx);
78
79    if (MM_CAMERA_OK != pme->cam->ops->qbuf(bufs->camera_handle,
80                                            bufs->ch_id,
81                                            frame)) {
82        LOGE(" Failed in RDI Qbuf\n");
83    }
84    mm_app_cache_ops((mm_camera_app_meminfo_t *)frame->mem_info,
85                     ION_IOC_INV_CACHES);
86
87    LOGD(" END\n");
88}
89
90mm_camera_stream_t * mm_app_add_rdi_stream(mm_camera_test_obj_t *test_obj,
91                                               mm_camera_channel_t *channel,
92                                               mm_camera_buf_notify_t stream_cb,
93                                               void *userdata,
94                                               uint8_t num_bufs,
95                                               uint8_t num_burst)
96{
97    int rc = MM_CAMERA_OK;
98    size_t i;
99    mm_camera_stream_t *stream = NULL;
100    cam_capability_t *cam_cap = (cam_capability_t *)(test_obj->cap_buf.buf.buffer);
101    cam_format_t fmt = CAM_FORMAT_MAX;
102    cam_stream_buf_plane_info_t *buf_planes;
103    cam_stream_size_info_t abc ;
104    memset (&abc , 0, sizeof (cam_stream_size_info_t));
105
106
107
108    LOGE(" raw_dim w:%d height:%d\n",  cam_cap->raw_dim[0].width, cam_cap->raw_dim[0].height);
109    for (i = 0;i < cam_cap->supported_raw_fmt_cnt;i++) {
110        LOGE(" supported_raw_fmts[%zd]=%d\n",
111            i, (int)cam_cap->supported_raw_fmts[i]);
112        if (((CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GBRG <= cam_cap->supported_raw_fmts[i]) &&
113            (CAM_FORMAT_BAYER_MIPI_RAW_12BPP_BGGR >= cam_cap->supported_raw_fmts[i])) ||
114            (cam_cap->supported_raw_fmts[i] == CAM_FORMAT_META_RAW_8BIT) ||
115            (cam_cap->supported_raw_fmts[i] == CAM_FORMAT_JPEG_RAW_8BIT) ||
116            (cam_cap->supported_raw_fmts[i] == CAM_FORMAT_BAYER_MIPI_RAW_14BPP_BGGR))
117        {
118            fmt = cam_cap->supported_raw_fmts[i];
119            LOGE(" fmt=%d\n",  fmt);
120        }
121    }
122
123    if (CAM_FORMAT_MAX == fmt) {
124        LOGE(" rdi format not supported\n");
125        return NULL;
126    }
127
128    abc.num_streams = 1;
129    abc.postprocess_mask[0] = 0;
130    abc.stream_sizes[0].width = cam_cap->raw_dim[0].width;
131    abc.stream_sizes[0].height = cam_cap->raw_dim[0].height;
132    abc.type[0] = CAM_STREAM_TYPE_RAW;
133    abc.buffer_info.min_buffers = num_bufs;
134    abc.buffer_info.max_buffers = num_bufs;
135    abc.is_type[0] = IS_TYPE_NONE;
136
137    rc = setmetainfoCommand(test_obj, &abc);
138    if (rc != MM_CAMERA_OK) {
139       LOGE(" meta info command failed\n");
140    }
141
142    stream = mm_app_add_stream(test_obj, channel);
143    if (NULL == stream) {
144        LOGE(" add stream failed\n");
145        return NULL;
146    }
147
148    stream->s_config.mem_vtbl.get_bufs = mm_app_stream_initbuf;
149    stream->s_config.mem_vtbl.put_bufs = mm_app_stream_deinitbuf;
150    stream->s_config.mem_vtbl.clean_invalidate_buf =
151      mm_app_stream_clean_invalidate_buf;
152    stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
153    stream->s_config.mem_vtbl.clean_buf = mm_app_stream_clean_buf;
154    stream->s_config.mem_vtbl.user_data = (void *)stream;
155    stream->s_config.stream_cb = stream_cb;
156    stream->s_config.stream_cb_sync = NULL;
157    stream->s_config.userdata = userdata;
158    stream->num_of_bufs = num_bufs;
159
160    stream->s_config.stream_info = (cam_stream_info_t *)stream->s_info_buf.buf.buffer;
161    memset(stream->s_config.stream_info, 0, sizeof(cam_stream_info_t));
162    stream->s_config.stream_info->stream_type = CAM_STREAM_TYPE_RAW;
163    if (num_burst == 0) {
164        stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
165    } else {
166        stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_BURST;
167        stream->s_config.stream_info->num_of_burst = num_burst;
168    }
169    stream->s_config.stream_info->fmt = DEFAULT_RAW_FORMAT;
170    stream->s_config.stream_info->num_bufs = num_bufs;
171    LOGD(" RAW: w: %d, h: %d ",
172       cam_cap->raw_dim[0].width, cam_cap->raw_dim[0].height);
173
174    stream->s_config.stream_info->dim.width = cam_cap->raw_dim[0].width;
175    stream->s_config.stream_info->dim.height = cam_cap->raw_dim[0].height;
176    stream->s_config.padding_info = cam_cap->padding_info;
177
178    rc = mm_app_config_stream(test_obj, channel, stream, &stream->s_config);
179    if (MM_CAMERA_OK != rc) {
180        LOGE("config rdi stream err=%d\n",  rc);
181        return NULL;
182    }
183
184    buf_planes = &stream->s_config.stream_info->buf_planes;
185    rdi_len = buf_planes->plane_info.mp[0].len;
186    LOGD(" plane_info %dx%d len:%d frame_len:%d\n",
187        buf_planes->plane_info.mp[0].stride, buf_planes->plane_info.mp[0].scanline,
188        buf_planes->plane_info.mp[0].len, buf_planes->plane_info.frame_len);
189
190    return stream;
191}
192
193mm_camera_stream_t * mm_app_add_rdi_snapshot_stream(mm_camera_test_obj_t *test_obj,
194                                                mm_camera_channel_t *channel,
195                                                mm_camera_buf_notify_t stream_cb,
196                                                void *userdata,
197                                                uint8_t num_bufs,
198                                                uint8_t num_burst)
199{
200    int rc = MM_CAMERA_OK;
201    mm_camera_stream_t *stream = NULL;
202    cam_capability_t *cam_cap = (cam_capability_t *)(test_obj->cap_buf.buf.buffer);
203
204    stream = mm_app_add_stream(test_obj, channel);
205    if (NULL == stream) {
206        LOGE(" add stream failed\n");
207        return NULL;
208    }
209
210    stream->s_config.mem_vtbl.get_bufs = mm_app_stream_initbuf;
211    stream->s_config.mem_vtbl.put_bufs = mm_app_stream_deinitbuf;
212    stream->s_config.mem_vtbl.clean_invalidate_buf =
213      mm_app_stream_clean_invalidate_buf;
214    stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
215    stream->s_config.mem_vtbl.clean_buf = mm_app_stream_clean_buf;
216    stream->s_config.mem_vtbl.user_data = (void *)stream;
217    stream->s_config.stream_cb = stream_cb;
218    stream->s_config.stream_cb_sync = NULL;
219    stream->s_config.userdata = userdata;
220    stream->num_of_bufs = num_bufs;
221
222    stream->s_config.stream_info = (cam_stream_info_t *)stream->s_info_buf.buf.buffer;
223    memset(stream->s_config.stream_info, 0, sizeof(cam_stream_info_t));
224    stream->s_config.stream_info->stream_type = CAM_STREAM_TYPE_SNAPSHOT;
225    if (num_burst == 0) {
226        stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
227    } else {
228        stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_BURST;
229        stream->s_config.stream_info->num_of_burst = num_burst;
230    }
231    stream->s_config.stream_info->num_bufs = num_bufs;
232    stream->s_config.stream_info->fmt = DEFAULT_SNAPSHOT_FORMAT;
233    stream->s_config.stream_info->dim.width = DEFAULT_SNAPSHOT_WIDTH;
234    stream->s_config.stream_info->dim.height = DEFAULT_SNAPSHOT_HEIGHT;
235    stream->s_config.padding_info = cam_cap->padding_info;
236
237    rc = mm_app_config_stream(test_obj, channel, stream, &stream->s_config);
238    if (MM_CAMERA_OK != rc) {
239        LOGE("config rdi stream err=%d\n",  rc);
240        return NULL;
241    }
242
243    return stream;
244}
245
246mm_camera_channel_t * mm_app_add_rdi_channel(mm_camera_test_obj_t *test_obj, uint8_t num_burst)
247{
248    mm_camera_channel_t *channel = NULL;
249    mm_camera_stream_t *stream = NULL;
250
251    channel = mm_app_add_channel(test_obj,
252                                 MM_CHANNEL_TYPE_RDI,
253                                 NULL,
254                                 NULL,
255                                 NULL);
256    if (NULL == channel) {
257        LOGE(" add channel failed");
258        return NULL;
259    }
260
261    stream = mm_app_add_rdi_stream(test_obj,
262                                       channel,
263                                       mm_app_rdi_notify_cb,
264                                       (void *)test_obj,
265                                       RDI_BUF_NUM,
266                                       num_burst);
267    if (NULL == stream) {
268        LOGE(" add stream failed\n");
269        mm_app_del_channel(test_obj, channel);
270        return NULL;
271    }
272
273    LOGD(" channel=%d stream=%d\n",  channel->ch_id, stream->s_id);
274    return channel;
275}
276
277int mm_app_stop_and_del_rdi_channel(mm_camera_test_obj_t *test_obj,
278                                mm_camera_channel_t *channel)
279{
280    int rc = MM_CAMERA_OK;
281    mm_camera_stream_t *stream = NULL;
282    uint8_t i;
283    cam_stream_size_info_t abc ;
284    memset (&abc , 0, sizeof (cam_stream_size_info_t));
285
286    rc = mm_app_stop_channel(test_obj, channel);
287    if (MM_CAMERA_OK != rc) {
288        LOGE("Stop RDI failed rc=%d\n",  rc);
289    }
290
291    if (channel->num_streams <= MAX_STREAM_NUM_IN_BUNDLE) {
292        for (i = 0; i < channel->num_streams; i++) {
293            stream = &channel->streams[i];
294            rc = mm_app_del_stream(test_obj, channel, stream);
295            if (MM_CAMERA_OK != rc) {
296                LOGE("del stream(%d) failed rc=%d\n",  i, rc);
297            }
298        }
299    } else {
300        LOGE(" num_streams = %d. Should not be more than %d\n",
301             channel->num_streams, MAX_STREAM_NUM_IN_BUNDLE);
302    }
303    rc = setmetainfoCommand(test_obj, &abc);
304    if (rc != MM_CAMERA_OK) {
305       LOGE(" meta info command failed\n");
306    }
307    rc = mm_app_del_channel(test_obj, channel);
308    if (MM_CAMERA_OK != rc) {
309        LOGE("delete channel failed rc=%d\n",  rc);
310    }
311
312    return rc;
313}
314
315int mm_app_start_rdi(mm_camera_test_obj_t *test_obj, uint8_t num_burst)
316{
317    int rc = MM_CAMERA_OK;
318    mm_camera_channel_t *channel = NULL;
319
320    channel = mm_app_add_rdi_channel(test_obj, num_burst);
321    if (NULL == channel) {
322        LOGE(" add channel failed");
323        return -MM_CAMERA_E_GENERAL;
324    }
325
326    rc = mm_app_start_channel(test_obj, channel);
327    if (MM_CAMERA_OK != rc) {
328        LOGE("start rdi failed rc=%d\n",  rc);
329        mm_app_del_channel(test_obj, channel);
330        return rc;
331    }
332
333    return rc;
334}
335
336int mm_app_stop_rdi(mm_camera_test_obj_t *test_obj)
337{
338    int rc = MM_CAMERA_OK;
339
340    mm_camera_channel_t *channel =
341        mm_app_get_channel_by_type(test_obj, MM_CHANNEL_TYPE_RDI);
342
343    rc = mm_app_stop_and_del_rdi_channel(test_obj, channel);
344    if (MM_CAMERA_OK != rc) {
345        LOGE("Stop RDI failed rc=%d\n",  rc);
346    }
347
348    return rc;
349}
350
351