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 = 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.user_data = (void *)stream;
154    stream->s_config.stream_cb = stream_cb;
155    stream->s_config.stream_cb_sync = NULL;
156    stream->s_config.userdata = userdata;
157    stream->num_of_bufs = num_bufs;
158
159    stream->s_config.stream_info = (cam_stream_info_t *)stream->s_info_buf.buf.buffer;
160    memset(stream->s_config.stream_info, 0, sizeof(cam_stream_info_t));
161    stream->s_config.stream_info->stream_type = CAM_STREAM_TYPE_RAW;
162    if (num_burst == 0) {
163        stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
164    } else {
165        stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_BURST;
166        stream->s_config.stream_info->num_of_burst = num_burst;
167    }
168    stream->s_config.stream_info->fmt = DEFAULT_RAW_FORMAT;
169    LOGD(" RAW: w: %d, h: %d ",
170       cam_cap->raw_dim[0].width, cam_cap->raw_dim[0].height);
171
172    stream->s_config.stream_info->dim.width = cam_cap->raw_dim[0].width;
173    stream->s_config.stream_info->dim.height = cam_cap->raw_dim[0].height;
174    stream->s_config.padding_info = cam_cap->padding_info;
175
176    rc = mm_app_config_stream(test_obj, channel, stream, &stream->s_config);
177    if (MM_CAMERA_OK != rc) {
178        LOGE("config rdi stream err=%d\n",  rc);
179        return NULL;
180    }
181
182    buf_planes = &stream->s_config.stream_info->buf_planes;
183    rdi_len = buf_planes->plane_info.mp[0].len;
184    LOGD(" plane_info %dx%d len:%d frame_len:%d\n",
185        buf_planes->plane_info.mp[0].stride, buf_planes->plane_info.mp[0].scanline,
186        buf_planes->plane_info.mp[0].len, buf_planes->plane_info.frame_len);
187
188    return stream;
189}
190
191mm_camera_stream_t * mm_app_add_rdi_snapshot_stream(mm_camera_test_obj_t *test_obj,
192                                                mm_camera_channel_t *channel,
193                                                mm_camera_buf_notify_t stream_cb,
194                                                void *userdata,
195                                                uint8_t num_bufs,
196                                                uint8_t num_burst)
197{
198    int rc = MM_CAMERA_OK;
199    mm_camera_stream_t *stream = NULL;
200    cam_capability_t *cam_cap = (cam_capability_t *)(test_obj->cap_buf.buf.buffer);
201
202    stream = mm_app_add_stream(test_obj, channel);
203    if (NULL == stream) {
204        LOGE(" add stream failed\n");
205        return NULL;
206    }
207
208    stream->s_config.mem_vtbl.get_bufs = mm_app_stream_initbuf;
209    stream->s_config.mem_vtbl.put_bufs = mm_app_stream_deinitbuf;
210    stream->s_config.mem_vtbl.clean_invalidate_buf =
211      mm_app_stream_clean_invalidate_buf;
212    stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
213    stream->s_config.mem_vtbl.user_data = (void *)stream;
214    stream->s_config.stream_cb = stream_cb;
215    stream->s_config.stream_cb_sync = NULL;
216    stream->s_config.userdata = userdata;
217    stream->num_of_bufs = num_bufs;
218
219    stream->s_config.stream_info = (cam_stream_info_t *)stream->s_info_buf.buf.buffer;
220    memset(stream->s_config.stream_info, 0, sizeof(cam_stream_info_t));
221    stream->s_config.stream_info->stream_type = CAM_STREAM_TYPE_SNAPSHOT;
222    if (num_burst == 0) {
223        stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
224    } else {
225        stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_BURST;
226        stream->s_config.stream_info->num_of_burst = num_burst;
227    }
228    stream->s_config.stream_info->fmt = DEFAULT_SNAPSHOT_FORMAT;
229    stream->s_config.stream_info->dim.width = DEFAULT_SNAPSHOT_WIDTH;
230    stream->s_config.stream_info->dim.height = DEFAULT_SNAPSHOT_HEIGHT;
231    stream->s_config.padding_info = cam_cap->padding_info;
232
233    rc = mm_app_config_stream(test_obj, channel, stream, &stream->s_config);
234    if (MM_CAMERA_OK != rc) {
235        LOGE("config rdi stream err=%d\n",  rc);
236        return NULL;
237    }
238
239    return stream;
240}
241
242mm_camera_channel_t * mm_app_add_rdi_channel(mm_camera_test_obj_t *test_obj, uint8_t num_burst)
243{
244    mm_camera_channel_t *channel = NULL;
245    mm_camera_stream_t *stream = NULL;
246
247    channel = mm_app_add_channel(test_obj,
248                                 MM_CHANNEL_TYPE_RDI,
249                                 NULL,
250                                 NULL,
251                                 NULL);
252    if (NULL == channel) {
253        LOGE(" add channel failed");
254        return NULL;
255    }
256
257    stream = mm_app_add_rdi_stream(test_obj,
258                                       channel,
259                                       mm_app_rdi_notify_cb,
260                                       (void *)test_obj,
261                                       RDI_BUF_NUM,
262                                       num_burst);
263    if (NULL == stream) {
264        LOGE(" add stream failed\n");
265        mm_app_del_channel(test_obj, channel);
266        return NULL;
267    }
268
269    LOGD(" channel=%d stream=%d\n",  channel->ch_id, stream->s_id);
270    return channel;
271}
272
273int mm_app_stop_and_del_rdi_channel(mm_camera_test_obj_t *test_obj,
274                                mm_camera_channel_t *channel)
275{
276    int rc = MM_CAMERA_OK;
277    mm_camera_stream_t *stream = NULL;
278    uint8_t i;
279    cam_stream_size_info_t abc ;
280    memset (&abc , 0, sizeof (cam_stream_size_info_t));
281
282    rc = mm_app_stop_channel(test_obj, channel);
283    if (MM_CAMERA_OK != rc) {
284        LOGE("Stop RDI failed rc=%d\n",  rc);
285    }
286
287    if (channel->num_streams <= MAX_STREAM_NUM_IN_BUNDLE) {
288        for (i = 0; i < channel->num_streams; i++) {
289            stream = &channel->streams[i];
290            rc = mm_app_del_stream(test_obj, channel, stream);
291            if (MM_CAMERA_OK != rc) {
292                LOGE("del stream(%d) failed rc=%d\n",  i, rc);
293            }
294        }
295    } else {
296        LOGE(" num_streams = %d. Should not be more than %d\n",
297             channel->num_streams, MAX_STREAM_NUM_IN_BUNDLE);
298    }
299    rc = setmetainfoCommand(test_obj, &abc);
300    if (rc != MM_CAMERA_OK) {
301       LOGE(" meta info command failed\n");
302    }
303    rc = mm_app_del_channel(test_obj, channel);
304    if (MM_CAMERA_OK != rc) {
305        LOGE("delete channel failed rc=%d\n",  rc);
306    }
307
308    return rc;
309}
310
311int mm_app_start_rdi(mm_camera_test_obj_t *test_obj, uint8_t num_burst)
312{
313    int rc = MM_CAMERA_OK;
314    mm_camera_channel_t *channel = NULL;
315
316    channel = mm_app_add_rdi_channel(test_obj, num_burst);
317    if (NULL == channel) {
318        LOGE(" add channel failed");
319        return -MM_CAMERA_E_GENERAL;
320    }
321
322    rc = mm_app_start_channel(test_obj, channel);
323    if (MM_CAMERA_OK != rc) {
324        LOGE("start rdi failed rc=%d\n",  rc);
325        mm_app_del_channel(test_obj, channel);
326        return rc;
327    }
328
329    return rc;
330}
331
332int mm_app_stop_rdi(mm_camera_test_obj_t *test_obj)
333{
334    int rc = MM_CAMERA_OK;
335
336    mm_camera_channel_t *channel =
337        mm_app_get_channel_by_type(test_obj, MM_CHANNEL_TYPE_RDI);
338
339    rc = mm_app_stop_and_del_rdi_channel(test_obj, channel);
340    if (MM_CAMERA_OK != rc) {
341        LOGE("Stop RDI failed rc=%d\n",  rc);
342    }
343
344    return rc;
345}
346
347