621029cb24fe061d9e913e8f995163d1908c556b
[jacinto7_multimedia/viddec-test-app.git] / main.c
1 /*
2  * Texas Instruments IMG video driver test application.
3  *
4  * Copyright (c) 2018 Texas Instruments Incorporated - http://www.ti.com/
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation version 2.
9  *
10  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
11  * kind, whether express or implied; without even the implied warranty
12  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
16 #include <stdio.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <assert.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <errno.h>
23 #include <malloc.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <sys/time.h>
27 #include <sys/mman.h>
28 #include <sys/ioctl.h>
29 #include <signal.h>
30 #include <poll.h>
31 #include <dirent.h>
33 #include <asm/types.h>
34 #include <linux/videodev2.h>
35 #include <linux/v4l2-controls.h>
37 #include <drm.h>
38 #include <xf86drm.h>
39 #include <xf86drmMode.h>
40 #include <drm_fourcc.h>
42 #include "demux.h"
44 /* HEVC aka H.265 */
45 #define V4L2_PIX_FMT_HEVC     v4l2_fourcc('H', 'E', 'V', 'C')
46 /* TI NV12 10-bit, two bytes per channel */
47 #define V4L2_PIX_FMT_TI1210   v4l2_fourcc('T', 'I', '1', '2')
48 /* TI YUV422 10-bit, two bytes per channel */
49 #define V4L2_PIX_FMT_TI1610   v4l2_fourcc('T', 'I', '1', '6')
51 static const struct AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
52                 [AV_PIX_FMT_YUV420P] = {
53                                 .name = "yuv420p",
54                 },
55                 [AV_PIX_FMT_YUYV422] = {
56                                 .name = "yuyv422",
57                 },
58                 [AV_PIX_FMT_YVYU422] = {
59                                 .name = "yvyu422",
60                 },
61                 [AV_PIX_FMT_YUV422P] = {
62                                 .name = "yuv422p",
63                 },
64                 [AV_PIX_FMT_YUV444P] = {
65                                 .name = "yuv444p",
66                 },
67                 [AV_PIX_FMT_YUV410P] = {
68                                 .name = "yuv410p",
69                 },
70                 [AV_PIX_FMT_YUV411P] = {
71                                 .name = "yuv411p",
72                 },
73                 [AV_PIX_FMT_YUVJ411P] = {
74                                 .name = "yuvj411p",
75                 },
76                 [AV_PIX_FMT_YUVJ420P] = {
77                                 .name = "yuvj420p",
78                 },
79                 [AV_PIX_FMT_YUVJ422P] = {
80                                 .name = "yuvj422p",
81                 },
82                 [AV_PIX_FMT_YUVJ444P] = {
83                                 .name = "yuvj444p",
84                 },
85                 [AV_PIX_FMT_XVMC] = {
86                                 .name = "xvmc",
87                                 .flags = AV_PIX_FMT_FLAG_HWACCEL,
88                 },
89                 [AV_PIX_FMT_UYVY422] = {
90                                 .name = "uyvy422",
91                 },
92                 [AV_PIX_FMT_UYYVYY411] = {
93                                 .name = "uyyvyy411",
94                 },
95                 [AV_PIX_FMT_NV12] = {
96                                 .name = "nv12",
97                 },
98                 [AV_PIX_FMT_NV21] = {
99                                 .name = "nv21",
100                 },
101                 [AV_PIX_FMT_YUV440P] = {
102                                 .name = "yuv440p",
103                 },
104                 [AV_PIX_FMT_YUVJ440P] = {
105                                 .name = "yuvj440p",
106                 },
107                 [AV_PIX_FMT_YUV440P10LE] = {
108                                 .name = "yuv440p10le",
109                 },
110                 [AV_PIX_FMT_YUV440P10BE] = {
111                                 .name = "yuv440p10be",
112                 },
113                 [AV_PIX_FMT_YUV440P12LE] = {
114                                 .name = "yuv440p12le",
115                 },
116                 [AV_PIX_FMT_YUV440P12BE] = {
117                                 .name = "yuv440p12be",
118                 },
119                 [AV_PIX_FMT_YUVA420P] = {
120                                 .name = "yuva420p",
121                 },
122                 [AV_PIX_FMT_YUVA422P] = {
123                                 .name = "yuva422p",
124                 },
125                 [AV_PIX_FMT_YUVA444P] = {
126                                 .name = "yuva444p",
127                 },
128                 [AV_PIX_FMT_YUVA420P9BE] = {
129                                 .name = "yuva420p9be",
130                 },
131                 [AV_PIX_FMT_YUVA420P9LE] = {
132                                 .name = "yuva420p9le",
133                 },
134                 [AV_PIX_FMT_YUVA422P9BE] = {
135                                 .name = "yuva422p9be",
136                 },
137                 [AV_PIX_FMT_YUVA422P9LE] = {
138                                 .name = "yuva422p9le",
139                 },
140                 [AV_PIX_FMT_YUVA444P9BE] = {
141                                 .name = "yuva444p9be",
142                 },
143                 [AV_PIX_FMT_YUVA444P9LE] = {
144                                 .name = "yuva444p9le",
145                 },
146                 [AV_PIX_FMT_YUVA420P10BE] = {
147                                 .name = "yuva420p10be",
148                 },
149                 [AV_PIX_FMT_YUVA420P10LE] = {
150                                 .name = "yuva420p10le",
151                 },
152                 [AV_PIX_FMT_YUVA422P10BE] = {
153                                 .name = "yuva422p10be",
154                 },
155                 [AV_PIX_FMT_YUVA422P10LE] = {
156                                 .name = "yuva422p10le",
157                 },
158                 [AV_PIX_FMT_YUVA444P10BE] = {
159                                 .name = "yuva444p10be",
160                 },
161                 [AV_PIX_FMT_YUVA444P10LE] = {
162                                 .name = "yuva444p10le",
163                 },
164                 [AV_PIX_FMT_YUVA420P16BE] = {
165                                 .name = "yuva420p16be",
166                 },
167                 [AV_PIX_FMT_YUVA420P16LE] = {
168                                 .name = "yuva420p16le",
169                 },
170                 [AV_PIX_FMT_YUVA422P16BE] = {
171                                 .name = "yuva422p16be",
172                 },
173                 [AV_PIX_FMT_YUVA422P16LE] = {
174                                 .name = "yuva422p16le",
175                 },
176                 [AV_PIX_FMT_YUVA444P16BE] = {
177                                 .name = "yuva444p16be",
178                 },
179                 [AV_PIX_FMT_YUVA444P16LE] = {
180                                 .name = "yuva444p16le",
181                 },
182                 [AV_PIX_FMT_YUV420P9LE] = {
183                                 .name = "yuv420p9le",
184                 },
185                 [AV_PIX_FMT_YUV420P9BE] = {
186                                 .name = "yuv420p9be",
187                 },
188                 [AV_PIX_FMT_YUV420P10LE] = {
189                                 .name = "yuv420p10le",
190                 },
191                 [AV_PIX_FMT_YUV420P10BE] = {
192                                 .name = "yuv420p10be",
193                 },
194                 [AV_PIX_FMT_YUV420P12LE] = {
195                                 .name = "yuv420p12le",
196                 },
197                 [AV_PIX_FMT_YUV420P12BE] = {
198                                 .name = "yuv420p12be",
199                 },
200                 [AV_PIX_FMT_YUV420P14LE] = {
201                                 .name = "yuv420p14le",
202                 },
203                 [AV_PIX_FMT_YUV420P14BE] = {
204                                 .name = "yuv420p14be",
205                 },
206                 [AV_PIX_FMT_YUV420P16LE] = {
207                                 .name = "yuv420p16le",
208                 },
209                 [AV_PIX_FMT_YUV420P16BE] = {
210                                 .name = "yuv420p16be",
211                 },
212                 [AV_PIX_FMT_YUV422P9LE] = {
213                                 .name = "yuv422p9le",
214                 },
215                 [AV_PIX_FMT_YUV422P9BE] = {
216                                 .name = "yuv422p9be",
217                 },
218                 [AV_PIX_FMT_YUV422P10LE] = {
219                                 .name = "yuv422p10le",
220                 },
221                 [AV_PIX_FMT_YUV422P10BE] = {
222                                 .name = "yuv422p10be",
223                 },
224                 [AV_PIX_FMT_YUV422P12LE] = {
225                                 .name = "yuv422p12le",
226                 },
227                 [AV_PIX_FMT_YUV422P12BE] = {
228                                 .name = "yuv422p12be",
229                 },
230                 [AV_PIX_FMT_YUV422P14LE] = {
231                                 .name = "yuv422p14le",
232                 },
233                 [AV_PIX_FMT_YUV422P14BE] = {
234                                 .name = "yuv422p14be",
235                 },
236                 [AV_PIX_FMT_YUV422P16LE] = {
237                                 .name = "yuv422p16le",
238                 },
239                 [AV_PIX_FMT_YUV422P16BE] = {
240                                 .name = "yuv422p16be",
241                 },
242                 [AV_PIX_FMT_YUV444P16LE] = {
243                                 .name = "yuv444p16le",
244                 },
245                 [AV_PIX_FMT_YUV444P16BE] = {
246                                 .name = "yuv444p16be",
247                 },
248                 [AV_PIX_FMT_YUV444P10LE] = {
249                                 .name = "yuv444p10le",
250                 },
251                 [AV_PIX_FMT_YUV444P10BE] = {
252                                 .name = "yuv444p10be",
253                 },
254                 [AV_PIX_FMT_YUV444P9LE] = {
255                                 .name = "yuv444p9le",
256                 },
257                 [AV_PIX_FMT_YUV444P9BE] = {
258                                 .name = "yuv444p9be",
259                 },
260                 [AV_PIX_FMT_YUV444P12LE] = {
261                                 .name = "yuv444p12le",
262                 },
263                 [AV_PIX_FMT_YUV444P12BE] = {
264                                 .name = "yuv444p12be",
265                 },
266                 [AV_PIX_FMT_YUV444P14LE] = {
267                                 .name = "yuv444p14le",
268                 },
269                 [AV_PIX_FMT_YUV444P14BE] = {
270                                 .name = "yuv444p14be",
271                 },
272                 [AV_PIX_FMT_P010LE] = {
273                                 .name = "p010le",
274                 },
275                 [AV_PIX_FMT_P010BE] = {
276                                 .name = "p010be",
277                 },
278                 [AV_PIX_FMT_P016LE] = {
279                                 .name = "p016le",
280                 },
281                 [AV_PIX_FMT_P016BE] = {
282                                 .name = "p016be",
283                 }
284 };
286 #define memzero(x)      memset(&(x), 0, sizeof (x))
287 #define MAX_TEST_FDS    10
288 #define MAX_FRAMES      1000
289 #define ALIGN(x,a)      (((x) + (a) - 1L) & ~((a) - 1L))
290 #define HW_ALIGN        64
292 #define MAX_OUTBUFS 2
294 #define DISPLAY_LAG 3
296 #define MAX_CAPBUFS_H264 16
297 #define MAX_CAPBUFS (MAX_CAPBUFS_H264 + DISPLAY_LAG)
299 #define MIN(a, b) ((a < b) ? a : b)
301 #define DEVICE_NAME "cardx"
303 //#define DEBUG
304 #ifdef DEBUG
305 #define debug_printf(fmt, arg...) printf(fmt, ##arg);
306 #else
307 #define debug_printf(fmt, arg...)
308 #endif
310 /* Enable the below option for converting YUV422 decoded output to NV12 format*/
311 #define CC_YUV422PLANAR_TO_NV12
313 #define PROFILE
314 #ifdef PROFILE
315 #define perf_printf(fmt, arg...) printf(fmt, ##arg);
316 #else
317         perf_printf(fmt, arg...)
318 #endif
320 static int drmfd1 = -1;
321 #define FMT_NUM_PLANES 1 /* Used when creating V4l2 buffers for capture buffers */
322 #define FMT_NUM_MJPEG_PLANES 3 /* Used when creating V4l2 buffers for capture buffers */
324 /*
325  * @bo_handle: drm buffer handle
326  * @dbuf_fd: dma buffer handle
327  * @mapped: Pointer to mmap'ed buffer memory
328  * @offset: offset of buffer
329  * @length: Buffer length for munmap
330  */
331 struct buffer {
332         unsigned int bo_handle;
333         int dbuf_fd;
334         void *mapped;
335         int offset;
336         int length;
337 };
339 struct stream_context
341         size_t frame_sizes[MAX_FRAMES];
342         int width;
343         int height;
344         int bitdepth;
345         int num_bytes_per_pix;
346         enum AVPixelFormat pix_fmt;
347         enum AVCodecID codec;
348 };
350 /*
351  *
352  * @fourcc: The V4L2 fourcc value
353  * @size_num: The numerator to multiply image size by
354  * @size_den: The denominator to divide image size by
355  */
356 struct output_format
358         uint32_t fourcc;
359         int size_num;
360         int size_den;
361 };
363 static void errno_exit(const char *s)
365         printf("%s error %d, %s\n", s, errno, strerror(errno));
366         exit(EXIT_FAILURE);
369 static int handle_outbuf(int fd, int index, int rdfd, struct buffer buff,
370         struct stream_context *str, int nframes, int sleep_time)
372         struct v4l2_buffer buf;
373         struct v4l2_plane buf_planes[1];
374         struct v4l2_decoder_cmd cmd = {};
375         int ret = 0;
376         int send_cmd = 0;
377         static int fs_ind = 0;
379         memset(buff.mapped, 0, (str->width * str->height));
380         read(rdfd, buff.mapped, str->frame_sizes[fs_ind]);
382         memzero(buf);
383         memzero(buf_planes[0]);
385         buf_planes[0].bytesused = str->frame_sizes[fs_ind];
386         buf_planes[0].m.mem_offset = buff.offset;
387         buf_planes[0].data_offset = 0;
389         fs_ind++;
391         /* Stop queueing OUTPUT buffers if no more content */
392         if (fs_ind > nframes)
393                 return ret;
395         if (fs_ind == nframes) {
396                 debug_printf("[fd%d] handle_outbuf sending DEC_CMD_STOP\n", fd);
397                 cmd.cmd = V4L2_DEC_CMD_STOP;
398                 ret = ioctl(fd, VIDIOC_TRY_DECODER_CMD, &cmd);
399                 if (ret < 0) {
400                         printf("[fd%d] handle_outbuf TRY_DECODER_CMD failed trying FLAG_LAST ret=%d err=%s\n",
401                                         fd, ret, strerror(errno));
402                         buf.flags |= V4L2_BUF_FLAG_LAST;
403                 } else {
404                         send_cmd = 1;
405                 }
406         }
408         buf.index = index;
409         buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
410         buf.memory = V4L2_MEMORY_MMAP;
411         buf.m.planes = buf_planes;
412         buf.length = 1;
414         ret = ioctl(fd, VIDIOC_QBUF, &buf);
415         if (ret < 0)
416                 printf("[fd%d] handle_outbuf QBUF failed ret=%d err=%s\n",
417                                 fd, ret, strerror(errno));
418         else
419                 debug_printf("[fd%d] handle_outbuf QBUF success\n", fd);
421         if (send_cmd) {
422                 debug_printf("[fd%d] handle_outbuf sending DEC_CMD_STOP after %d ms delay\n", fd, sleep_time / 1000);
423                 usleep(sleep_time);
424                 cmd.cmd = V4L2_DEC_CMD_STOP;
425                 ret = ioctl(fd, VIDIOC_DECODER_CMD, &cmd);
426                 if (ret < 0)
427                         printf("[fd%d] handle_outbuf DECODER_CMD failed ret=%d err=%s\n",
428                                         fd, ret, strerror(errno));
429         }
431         return ret;
434 static int handle_capbuf(int fd, int wrfd, int index, struct buffer buff[],
435                 int save, struct stream_context *str, struct output_format fmt, int usedrmbuff)
437         struct v4l2_buffer buf;
438         struct v4l2_plane buf_planes[3];
439         int ret = 0;
440         int i;
441         int h = ALIGN(str->height, HW_ALIGN);
442         int s = ALIGN(str->width, HW_ALIGN) * str->num_bytes_per_pix;
444         if(save && (wrfd >= 0))
445         {
446                 switch (fmt.fourcc) {
447                         case (V4L2_PIX_FMT_NV12):
448                         case (V4L2_PIX_FMT_TI1210):
449                                 /*
450                                 for(i=0; i<str->height; i++)
451                                         write(wrfd, buff.mapped + (i * s),
452                                                         str->width);
454                                 for(i=0; i<(str->height/2); i++)
455                                         write(wrfd, buff.mapped + (h * s) +
456                                                         (i * s), str->width);
457                                 */
458                                 for(i=0; i<str->height; i++)
459                                         write(wrfd, buff[index].mapped + (i * s),
460                                                         (str->width *
461                                                          str->num_bytes_per_pix));
463                                 for(i=0; i<(str->height/2); i++)
464                                         write(wrfd, buff[index].mapped + (h * s) +
465                                                         (i * s),
466                                                         (str->width *
467                                                          str->num_bytes_per_pix));
468                                 break;
469                         case (V4L2_PIX_FMT_NV16):
470                         case (V4L2_PIX_FMT_TI1610):
471 #ifdef CC_YUV422PLANAR_TO_NV12
472                                 for (i = 0; i < str->height; i++)
473                                         write(wrfd, buff[index].mapped + (i * s),
474                                                 str->width * str->num_bytes_per_pix);
475                                 for (i = 0; i < str->height; i+=2)
476                                         write(wrfd, buff[index].mapped + (h * s) + (i * s), str->width * str->num_bytes_per_pix);
478 #else
479                                 for (i = 0; i < str->height; i++)
480                                         write(wrfd, buff[index].mapped + (i * s),
481                                                         2* str->width * str->num_bytes_per_pix);
482 #endif
483                                 break;
484                         case V4L2_PIX_FMT_YUV420M:
486                                 for(i=0; i<str->height; i++)
487                                         write(wrfd, buff[(index*3)].mapped + (i * s),
488                                                 (str->width *
489                                                  str->num_bytes_per_pix));
492                                 for(i=0; i<(str->height/2); i++)
493                                         write(wrfd, buff[(index*3)+1].mapped + (i * s),
494                                                 (str->width *
495                                                 str->num_bytes_per_pix) / 2);
497                                 for(i=0; i<(str->height/2); i++)
498                                         write(wrfd, buff[(index*3)+2].mapped + (i * s),
499                                                 (str->width *
500                                                 str->num_bytes_per_pix) / 2);
501                                 break;
502                         case V4L2_PIX_FMT_YUV422M:
503                                 for(i=0; i<str->height; i++)
504                                         write(wrfd, buff[(index*3)].mapped + (i * s),
505                                                 (str->width *
506                                                  str->num_bytes_per_pix));
508                                 for(i=0; i<(str->height); i++)
509                                         write(wrfd, buff[(index*3)+1].mapped + (i * s),
510                                                 (str->width *
511                                                 str->num_bytes_per_pix) / 2);
513                                 for(i=0; i<(str->height); i++)
514                                         write(wrfd, buff[(index*3)+2].mapped + (i * s),
515                                                 (str->width *
516                                                 str->num_bytes_per_pix) / 2);
517                                 break;
518                         default:
519                                 break;
520                 }
521         }
523         memzero(buf);
524         memzero(buf_planes[0]);
526         if(str->codec == AV_CODEC_ID_MJPEG) {
527                 memzero(buf_planes[1]);
528                 memzero(buf_planes[2]);
529         }
531         if(str->codec == AV_CODEC_ID_MJPEG) {
532                 buf_planes[0].m.fd = buff[(index*3)].dbuf_fd;
533                 buf_planes[0].length = buff[(index*3)].length;
535                 buf_planes[1].m.fd = buff[((index*3) + 1)].dbuf_fd;
536                 buf_planes[1].length = buff[((index*3) + 1)].length;
538                 buf_planes[2].m.fd = buff[((index*3) + 2)].dbuf_fd;
539                 buf_planes[2].length = buff[((index*3) + 2)].length;
540         } else {
541                 buf_planes[0].m.fd = buff[index].dbuf_fd;
542                 buf_planes[0].length = buff[index].length;
543         }
545         buf.index = index;
546         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
547         if (usedrmbuff == 0) {
548                 /* Using v4l2 buffers for capture */
549                 buf.memory = V4L2_MEMORY_MMAP;
550         } else {
551                 /* Using drm buffers for capture */
552                 buf.memory = V4L2_MEMORY_DMABUF;
553         }
554         buf.m.planes = buf_planes;
555         if(str->codec == AV_CODEC_ID_MJPEG)
556                 buf.length = 3;
557         else
558                 buf.length = 1;
560         ret = ioctl(fd, VIDIOC_QBUF, &buf);
561         if (ret < 0)
562                 printf("[fd%d] handle_capbuf QBUF failed ret=%d err=%s\n",
563                                 fd, ret, strerror(errno));
564         else
565                 debug_printf("[fd%d] handle_capbuf QBUF success\n", fd);
567         return ret;
570 static int mainloop(int fd, int rdfd, int wrfd,
571                 struct stream_context *str, struct buffer outbufs[],
572                 struct buffer capbufs[], int n_outbufs,
573                 int n_capbufs, int nframes, int enable_prof,
574                 struct output_format fmt, int sleep_time, int usedrmbuff)
576         int type, i, ret = 0;
577         uint32_t flags = 0;
578         struct v4l2_buffer buf;
579         struct v4l2_plane buf_planes[3];
580         struct pollfd pfd;
581         struct timeval times;
582         long curr_time = 0;
583         static long prev_time = 0;
584         struct v4l2_event event;
586         debug_printf("[fd%d] MAINLOOP\n", fd);
588         pfd.fd = fd;
589         pfd.events = POLLIN | POLLOUT | POLLPRI;
590         pfd.revents = 0;
592         for (i = 0; i < n_outbufs; i++)
593                 handle_outbuf(fd, i, rdfd, outbufs[i], str, nframes, 0);
595         if(str->codec == AV_CODEC_ID_MJPEG) {
596                 for (i = 0; i < (n_capbufs / 3); i++)
597                         handle_capbuf(fd, wrfd, i, capbufs, 0, str, fmt, usedrmbuff);
598         } else {
599                 for (i = 0; i < n_capbufs; i++)
600                         handle_capbuf(fd, wrfd, i, capbufs, 0, str, fmt, usedrmbuff);
601         }
602         type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
603         ret = ioctl(fd, VIDIOC_STREAMON, &type);
604         if (ret) {
605                 printf("[fd%d] OUTPUT VIDIOC_STREAMON failed with ret %d\n",
606                         fd, ret);
607                 return ret;
608         }
610         type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
611         ret = ioctl(fd, VIDIOC_STREAMON, &type);
612         if (ret)
613                 printf("[fd%d] CAPTURE VIDIOC_STREAMON failed with ret %d\n",
614                         fd, ret);
616         i = 0;
617         while (!(flags & V4L2_BUF_FLAG_LAST)) {
618                 pfd.revents = 0;
620                 /* Poll for any event for 100ms */
621                 ret = poll(&pfd, 1, 100);
622                 if (ret < 0) {
623                         printf("poll had an error %d: %s\n",
624                                 errno, strerror(errno));
625                 } else if (ret > 0) {
626                         if (pfd.revents & POLLOUT) {
627                                 while (1) {
628                                         /* Check for OUTPUT buffer */
629                                         memzero(buf);
630                                         buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
631                                         buf.memory = V4L2_MEMORY_MMAP;
632                                         buf.m.planes = buf_planes;
633                                         buf.length = 1;
634                                         ret = ioctl(fd, VIDIOC_DQBUF, &buf);
635                                         if (ret < 0) {
636                                                 if (errno != EAGAIN) {
637                                                         printf("[fd%d] OUTPUT VIDIOC_DQBUF failed: ret=%d errno=%d: %s\n",
638                                                                 fd, ret, errno,
639                                                                 strerror(errno));
640                                                 } else {
641                                                         debug_printf("[fd%d] OUTPUT EAGAIN\n", fd);
642                                                         break;
643                                                 }
644                                         } else {
646                                                 handle_outbuf(fd, buf.index, rdfd,
647                                                                 outbufs[buf.index],
648                                                                 str, nframes,
649                                                                 sleep_time);
650                                         }
651                                 }
652                         }
653                         if (pfd.revents & POLLIN) {
654                                 while (1) {
655                                         /* Check for CAPTURE buffer */
656                                         memzero(buf);
657                                         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
658                                         if (usedrmbuff == 0) {
659                                                 /* Using v4l2 bufffers for capture */
660                                                 buf.memory = V4L2_MEMORY_MMAP;
661                                         } else {
662                                                 /* Using drm buffers for capture */
663                                                 buf.memory = V4L2_MEMORY_DMABUF;
664                                         }
665                                         buf.m.planes = buf_planes;
666                                         if(str->codec == AV_CODEC_ID_MJPEG)
667                                                 buf.length = 3;
668                                         else
669                                                 buf.length = 2;
670                                         ret = ioctl(fd, VIDIOC_DQBUF, &buf);
671                                         if (ret < 0) {
672                                                 if (errno != EAGAIN) {
673                                                         printf("[fd%d] CAPTURE VIDIOC_DQBUF failed: ret=%d errno=%d: %s\n",
674                                                                 fd, ret, errno,
675                                                                 strerror(errno));
676                                                 } else {
677                                                         debug_printf("[fd%d] CAPTURE EAGAIN\n", fd);
678                                                         break;
679                                                 }
680                                         } else {
682                                                 if (enable_prof) {
683                                                         gettimeofday(&times, NULL);
684                                                         curr_time =
685                                                         (times.tv_sec * 1000000 + times.tv_usec);
687                                                         perf_printf("Picture buffer dequeue time is %ld us\n",
688                                                                         (curr_time - prev_time));
690                                                         prev_time = curr_time;
691                                                 }
692                                                 debug_printf("[fd%d] CAPTURE VIDIOC_DQBUF bytesused=%d\n",
693                                                                 fd, buf.m.planes[0].bytesused);
694                                                 if (buf.m.planes[0].bytesused)
695                                                         handle_capbuf(fd, wrfd,
696                                                                       buf.index,
697                                                                       capbufs,
698                                                                       1, str,
699                                                                       fmt, usedrmbuff);
700                                                 flags = buf.flags;
701                                                 debug_printf("[fd%d] CAPTURE VIDIOC_DQBUF buffer %d flags=%08x FLAG_LAST=%08x\n",
702                                                                 fd, buf.index,
703                                                                 flags,
704                                                                 V4L2_BUF_FLAG_LAST);
705                                                 if (buf.flags & V4L2_BUF_FLAG_LAST)
706                                                         break;
707                                         }
708                                 }
709                         }
710                         if (pfd.revents & POLLPRI) {
711                                 /* Check for events */
712                                 memzero(event);
713                                 ret = ioctl(fd, VIDIOC_DQEVENT, &event);
714                                 if (ret < 0) {
715                                         printf("[fd%d] VIDIOC_DQEVENT failed:: ret=%d errno=%d: %s\n",
716                                                         fd, ret, errno,
717                                                         strerror(errno));
718                                 } else if (event.type == V4L2_EVENT_EOS) {
719                                         debug_printf("[fd%d] GOT EVENT\n", fd);
720                                 } else {
721                                         printf("[fd%d] VIDIOC_DQEVENT got unexpected event %d\n",
722                                                         fd, event.type);
723                                 }
724                         }
725                 }
726         }
728         debug_printf("Stream ended, calling STREAMOFF\n");
729         type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
730         ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
731         if (ret) {
732                 printf("[fd%d] VIDIOC_STREAMOFF on OUTPUT failed with ret %d\n",
733                                 fd, ret);
734                 return ret;
735         }
737         type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
738         ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
739         if (ret)
740                 printf("[fd%d] VIDIOC_STREAMOFF on CAPTURE failed with ret %d\n",
741                                 fd, ret);
743         return ret;
746 static void uninit_device(int fd, struct buffer outbufs[],
747                 struct buffer capbufs[], int *n_outbufs, int *n_capbufs, int usedrmbuff)
749         struct drm_mode_destroy_dumb gem_destroy;
750         int i, ret = 0;
751         struct v4l2_event_subscription sub;
753         debug_printf("[fd%d] uninit_device\n", fd);
755         for (i = 0; i < *n_outbufs; i++) {
756                 debug_printf("[fd%d] munmap outbuf %d mapped=0x%p length=%d\n",
757                                 fd, i, outbufs[i].mapped, outbufs[i].length);
758                 ret = munmap(outbufs[i].mapped, outbufs[i].length);
759                 if (ret) {
760                         printf("[fd%d] munmap failed for outbuf %d: %d %s\n",
761                                         fd, i, errno, strerror(errno));
762                 }
763         }
765 /* For unint capbufs, check which was used, drm or v4l2*/
766         if (usedrmbuff == 0) {
767                 /* Using v4l2 bufffers for capture */
768                 for (i = 0; i < *n_capbufs; i++) {
769                         debug_printf("[fd%d] munmap capbuf %d mapped=0x%p length=%d\n", fd, i, capbufs[i].mapped, capbufs[i].length);
770                         ret = munmap(capbufs[i].mapped, capbufs[i].length);
771                         if (ret) {
772                                 printf("[fd%d] munmap failed for capbuf %d: %d %s\n", fd, i, errno, strerror(errno));
773                         }
774                 }
775         } else {
776                 /* Using drm bufffers for capture */
777                 for (i = 0; i < *n_capbufs; i++) {
778                         debug_printf("[fd%d] munmap capbuf %d mapped=0x%p length=%d\n", fd, i, capbufs[i].mapped, capbufs[i].length);
779                         ret = munmap(capbufs[i].mapped, capbufs[i].length);
780                         if (ret) {
781                                 printf("[fd%d] munmap failed for  %d: %d %s\n", fd, i, errno, strerror(errno));
782                         }
783                         debug_printf("[fd%d] destroy gem capbuf %d handle=%d\n",
784                                         fd, i, capbufs[i].bo_handle);
785                         memset(&gem_destroy, 0, sizeof(gem_destroy));
786                         gem_destroy.handle = capbufs[i].bo_handle;
787                         ret = ioctl(drmfd1, DRM_IOCTL_MODE_DESTROY_DUMB, &gem_destroy);
788                         if (ret)
789                                 printf("    DRM_IOCTL_MODE_DESTROY_DUMB failed\n");
790                 }
791         }
793         memset(&sub, 0, sizeof(sub));
794         sub.type = V4L2_EVENT_ALL;
796         debug_printf("[fd%d] Calling V4L2 IOCTL VIDIOC_SUBSCRIBE_EVENT\n", fd);
797         ret = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
798         if (ret != 0) {
799                 printf("[fd%d] Failed to unsubscribe to events: err: %d %s\n",
800                                 fd, errno, strerror(errno));
801         }
804 static int create_drm_buffer(struct buffer *b,
805         unsigned int width, unsigned int height)
807         struct drm_mode_create_dumb gem;
808         struct drm_mode_map_dumb gem_map;
809         struct drm_mode_destroy_dumb gem_destroy;
810         int ret;
812         memset(&gem, 0, sizeof gem);
813         gem.width = width;
814         gem.height = height;
815         gem.bpp = 8;
817         ret = ioctl(drmfd1, DRM_IOCTL_MODE_CREATE_DUMB, &gem);
818         if (ret) {
819                 printf("    DRM_IOCTL_MODE_CREATE_DUMB failed\n");
820                 return ret;
821         }
823         b->bo_handle = gem.handle;
825         struct drm_prime_handle prime;
826         memset(&prime, 0, sizeof prime);
827         prime.handle = b->bo_handle;
829         ret = ioctl(drmfd1, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime);
830         if (ret) {
831                 printf("    DRM_IOCTL_PRIME_HANDLE_TO_FD failed\n");
832                 goto fail_gem;
833         }
834         b->dbuf_fd = prime.fd;
836         memset(&gem_map, 0, sizeof(gem_map));
837         gem_map.handle = gem.handle;
839         ret = ioctl(drmfd1, DRM_IOCTL_MODE_MAP_DUMB, &gem_map);
840         if (ret) {
841                 printf("    DRM_IOCTL_MODE_MAP_DUMB failed\n");
842                 goto fail_gem;
843         }
845         b->mapped = mmap(NULL, (size_t)gem.size, PROT_READ,
846                         MAP_SHARED, drmfd1, gem_map.offset);
847         if (MAP_FAILED == b->mapped) {
848                 printf("    mmap failed %d: %s\n", errno, strerror(errno));
849                 goto fail_gem;
850         }
851         b->offset = gem_map.offset;
852         b->length = gem.size;
854         return 0;
855 fail_gem:
856         memset(&gem_destroy, 0, sizeof gem_destroy);
857         gem_destroy.handle = b->bo_handle;
858         ret = ioctl(drmfd1, DRM_IOCTL_MODE_DESTROY_DUMB, &gem_destroy);
860         return ret;
863 int stream_framelevel_parsing(struct stream_context *str, char *input_file, int max_frames)
865         struct demux *demux;
866         int inp_buf_len = 0;
867         int inp_width, inp_height;
868         int frame_num = 0;
869         int frame_size = 0;
870         int bitdepth = 0;
871         enum AVPixelFormat pix_fmt;
872         enum AVCodecID codec;
874         /* Demux initialization */
875         demux = demux_init(input_file, &inp_width, &inp_height, &bitdepth, &pix_fmt, &codec);
876         if (!demux)
877         {
878                 printf("%s: could not open demuxer\n", __FUNCTION__);
879                 return -1;
880         }
882         debug_printf("\n%s: bitdepth: %d\n",__FUNCTION__, bitdepth);
883         debug_printf("%s: pix_fmt: %d\n",__FUNCTION__, pix_fmt);
884         debug_printf("%s: pix_fmt_string: %s\n",__FUNCTION__, pix_fmt != AV_PIX_FMT_NONE ?
885                         av_pix_fmt_descriptors[pix_fmt].name : "unknown");
886         debug_printf("\n%s: codec: %d\n",__FUNCTION__, codec);
887         if(codec == AV_CODEC_ID_H264)
888                 debug_printf("\n%s: codec: H264",__FUNCTION__);
889         if(codec == AV_CODEC_ID_HEVC)
890                 debug_printf("\n%s: codec format: HEVC\n",__FUNCTION__);
891         if(codec == AV_CODEC_ID_MJPEG)
892                 debug_printf("\n%s: codec format: MJPEG\n",__FUNCTION__);
894         inp_buf_len = (inp_width * inp_height);
896         unsigned char *inp_buf = malloc(inp_buf_len);
897         if(inp_buf == NULL)
898         {
899                 printf("%s: Memory allocation failed for inp_buf\n",
900                                 __FUNCTION__);
901                 return -1;
902         }
904         debug_printf("%s: demuxer is initialized, width=%d, height=%d\n",
905                 __FUNCTION__, inp_width, inp_height);
906         str->width = inp_width;
907         str->height = inp_height;
908         str->bitdepth = bitdepth;
909         str->pix_fmt = pix_fmt;
910         str->codec = codec;
912         if(bitdepth == 8 || pix_fmt == AV_PIX_FMT_YUV420P ||
913                         pix_fmt == AV_PIX_FMT_YUV422P)
914                 str->num_bytes_per_pix = 1;
915         if(bitdepth == 10 || pix_fmt == AV_PIX_FMT_YUV420P10LE ||
916                         pix_fmt == AV_PIX_FMT_YUV422P10LE)
917                 str->num_bytes_per_pix = 2;
919         /*read the frame size and store into array*/
920         while(1)
921         {
922                 frame_size = demux_read(demux, inp_buf, inp_buf_len);
923                 if (frame_size)
924                 {
925                         debug_printf("frame %d frame size in demux %d\n",
926                                 frame_num, frame_size);
927                         str->frame_sizes[frame_num] = frame_size;
928                         frame_num++;
929                 }
930                 else
931                 {
932                         /*if the input file contains less number frames*/
933                         break;
934                 }
935                 if (max_frames > 0 && frame_num >= max_frames)
936                         break;
937         }
939         /* Demux de-initialization */
940         demux_deinit(demux);
941         free(inp_buf);
943         debug_printf("H264 frame sizes update is done\n");
944         return frame_num;
947 static int init_device(int fd, int rdfd,
948                 struct stream_context *str, struct buffer outbufs[],
949                 struct buffer capbufs[], int *n_outbufs, int *n_capbufs,
950                 struct output_format format, int usedrmbuff)
952         struct v4l2_format fmt;
953         struct v4l2_requestbuffers reqbuf;
954         struct v4l2_buffer buffer;
955         struct v4l2_plane buf_planes[1];
956         int ret = 0;
957         int i, j;
958         /*for v4l2 based capture buffers*/
959         struct v4l2_buffer buffer_cap;
961         debug_printf("[fd%d] init_device\n", fd);
963         memzero(fmt);
964         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
965         fmt.fmt.pix_mp.width = str->width;
966         fmt.fmt.pix_mp.height = str->height;
967         fmt.fmt.pix_mp.plane_fmt[0].sizeimage = (str->width * str->height);
968         fmt.fmt.pix_mp.num_planes = 1;
970         if(str->codec == AV_CODEC_ID_H264)
971                 fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
972         if(str->codec == AV_CODEC_ID_HEVC)
973                 fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_HEVC;
974         if(str->codec == AV_CODEC_ID_MJPEG)
975                 fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_MJPEG;
977         ret = ioctl(fd, VIDIOC_S_FMT, &fmt);
978         if (ret != 0) {
979                 printf("[fd%d] VIDIOC_S_FMT errorno %d, %s\n",
980                         fd, errno, strerror(errno));
981                 return ret;
982         }
984         debug_printf("[fd%d] After S_FMT on OUTPUT\n", fd);
986         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
987         fmt.fmt.pix_mp.pixelformat = format.fourcc;
989         if(str->codec == AV_CODEC_ID_MJPEG) {
990                 fmt.fmt.pix_mp.plane_fmt[0].sizeimage =
991                                 ((fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height) * (str->num_bytes_per_pix));
992                 fmt.fmt.pix_mp.plane_fmt[1].sizeimage =
993                                 ((fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height) * (str->num_bytes_per_pix)) / 2;
994                 fmt.fmt.pix_mp.plane_fmt[2].sizeimage =
995                                 ((fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height) * (str->num_bytes_per_pix)) / 2;
997                 fmt.fmt.pix_mp.width = ALIGN(str->width, HW_ALIGN);
998                 fmt.fmt.pix_mp.height = ALIGN(str->height, HW_ALIGN);
999                 fmt.fmt.pix_mp.num_planes = 3;
1000                 fmt.fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(str->width, HW_ALIGN) * str->num_bytes_per_pix;
1001                 fmt.fmt.pix_mp.plane_fmt[1].bytesperline = ALIGN(str->width, HW_ALIGN) * str->num_bytes_per_pix;
1002                 fmt.fmt.pix_mp.plane_fmt[2].bytesperline = ALIGN(str->width, HW_ALIGN) * str->num_bytes_per_pix;
1003         } else {
1004                 fmt.fmt.pix_mp.plane_fmt[0].sizeimage =
1005                                 ((fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height) *
1006                                                 format.size_num) * (str->num_bytes_per_pix) / format.size_den;
1007                 fmt.fmt.pix_mp.width = ALIGN(str->width, HW_ALIGN);
1008                 fmt.fmt.pix_mp.height = ALIGN(str->height, HW_ALIGN);
1009                 fmt.fmt.pix_mp.num_planes = 1;
1010                 fmt.fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(str->width, HW_ALIGN) * str->num_bytes_per_pix;
1011         }
1013         ret = ioctl(fd, VIDIOC_S_FMT, &fmt);
1014         if (ret) {
1015                 printf("[fd%d] VIDIOC_S_FMT errorno %d, %s\n",
1016                         fd, errno, strerror(errno));
1017                 return ret;
1018         }
1020         debug_printf("[fd%d] After S_FMT on CAPTURE\n", fd);
1022         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1024         ret = ioctl(fd, VIDIOC_G_FMT, &fmt);
1025         if (ret) {
1026                 printf("[fd%d] VIDIOC_G_FMT errorno %d, %s\n",
1027                         fd, errno, strerror(errno));
1028                 return ret;
1029         }
1031         debug_printf("[fd%d] After G_FMT on OUTPUT\n", fd);
1032         debug_printf("[fd%d] After G_FMT fmt.fmt.pix_mp.pixelformat = %c%c%c%c numplanes %d\n",
1033                         fd, fmt.fmt.pix_mp.pixelformat & 0xff,
1034                         (fmt.fmt.pix_mp.pixelformat >> 8) & 0xff,
1035                         (fmt.fmt.pix_mp.pixelformat >>16) & 0xff,
1036                         (fmt.fmt.pix_mp.pixelformat >> 24) & 0xff,
1037                         fmt.fmt.pix_mp.num_planes);
1039         debug_printf("[fd%d] fmt.fmt.pix_mp.width %d fmt.fmt.pix_mp.height %d"
1040                         " sizeimage %d bytesperline %d\n",
1041                         fd, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
1042                         fmt.fmt.pix_mp.plane_fmt[0].sizeimage,
1043                         fmt.fmt.pix_mp.plane_fmt[0].bytesperline);
1045         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1047         ret = ioctl(fd, VIDIOC_G_FMT, &fmt);
1048         if (ret) {
1049                 printf("[fd%d] VIDIOC_G_FMT errorno %d, %s\n",
1050                         fd, errno, strerror(errno));
1051                 return ret;
1052         }
1054         debug_printf("[fd%d] After G_FMT on CAPTURE\n", fd);
1055         debug_printf("[fd%d] After G_FMT fmt.fmt.pix_mp.pixelformat = %c%c%c%c numplanes %d\n",
1056                         fd, fmt.fmt.pix_mp.pixelformat & 0xff,
1057                         (fmt.fmt.pix_mp.pixelformat >> 8) & 0xff,
1058                         (fmt.fmt.pix_mp.pixelformat >>16) & 0xff,
1059                         (fmt.fmt.pix_mp.pixelformat >> 24) & 0xff,
1060                         fmt.fmt.pix_mp.num_planes);
1062         debug_printf("[fd%d] fmt.fmt.pix_mp.width %d fmt.fmt.pix_mp.height %d"
1063                         " sizeimage %d bytesperline %d\n",
1064                         fd, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
1065                         fmt.fmt.pix_mp.plane_fmt[1].sizeimage,
1066                         fmt.fmt.pix_mp.plane_fmt[1].bytesperline);
1068         /* Setup Decoder OUTPUT (SRC buffer) through VIDIOC_REQBUFS */
1069         debug_printf("[fd%d] Setup decoding OUTPUT with VIDIOC_REQBUFS buffer size %u\n",
1070                 fd, fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
1072         memzero(reqbuf);
1073         reqbuf.count = *n_outbufs;
1074         reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1075         reqbuf.memory = V4L2_MEMORY_MMAP;
1077         ret = ioctl(fd, VIDIOC_REQBUFS, &reqbuf);
1078         if (ret) {
1079                 printf("[fd%d] Err REQBUFS failed on OUTPUT queue ret %d errno %d\n",
1080                         fd, ret, errno);
1081                 return ret;
1082         }
1083         debug_printf("[fd%d] After VIDIOC_REQBUFS getting buf_cnt %d\n",
1084                 fd, reqbuf.count);
1085         *n_outbufs = reqbuf.count;
1087         /* QUERYBUF on OUTPUT - memory of V4L2_MEMORY_MMAP */
1088         for (i = 0; i < *n_outbufs; i++) {
1089                 memset(&buffer, 0, sizeof(buffer));
1090                 buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1091                 buffer.index = i;
1092                 buffer.m.planes = buf_planes;
1093                 buffer.length = 1;
1095                 ret = ioctl(fd, VIDIOC_QUERYBUF, &buffer);
1096                 if (ret < 0) {
1097                         printf("[fd%d] CANNOT QUERY BUFFERS ret = %d\n",
1098                                 fd, ret);
1099                         return -1;
1100                 }
1102                 debug_printf("[fd%d] query buf, buffer %p plane 0 = %d buffer.length %d buffer.data_offset %d buffer.mem_offset %d\n",
1103                                 fd, &buffer, buffer.m.planes[0].length,
1104                                 buffer.length, buffer.m.planes[0].data_offset,
1105                                 buffer.m.planes[0].m.mem_offset);
1107                 outbufs[i].mapped = mmap(NULL, buffer.m.planes[0].length,
1108                                 PROT_READ | PROT_WRITE, MAP_SHARED,
1109                                 fd, buffer.m.planes[0].m.mem_offset);
1110                 outbufs[i].offset = buffer.m.planes[0].m.mem_offset;
1111                 outbufs[i].length = buffer.m.planes[0].length;
1113                 debug_printf("[fd%d] After mmap -> outbufs[%d].mapped = 0x%p\n",
1114                         fd, i, outbufs[i].mapped);
1116                 if (MAP_FAILED == outbufs[i].mapped) {
1117                         while (i >= 0) {
1118                                 /* Unmap all previous buffers */
1119                                 i--;
1120                                 munmap(outbufs[i].mapped,
1121                                         fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
1122                                 outbufs[i].mapped = NULL;
1123                         }
1124                         printf("[fd%d] Cant mmap buffers Y", fd);
1125                         return -1;
1126                 }
1127         }
1129         /* Setup Decoder CAPTURE (DST buffer) through VIDIOC_REQBUFS */
1131         if (usedrmbuff == 0) {
1132                 /* Setup Decoder CAPTURE (DST buffer) through VIDIOC_REQBUFS */
1133                 debug_printf("[fd%d] Setup decoding CAPTURE with VIDIOC_REQBUFS\n", fd);
1134                 debug_printf("[fd%d] buffer(y) size %u buffer(uv) size %u\n",
1135                                         fd, fmt.fmt.pix_mp.plane_fmt[0].sizeimage,
1136                                         fmt.fmt.pix_mp.plane_fmt[1].sizeimage);
1138                 memzero(reqbuf);
1139                 reqbuf.count = *n_capbufs;
1140                 reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1141                 reqbuf.memory = V4L2_MEMORY_MMAP;
1143                 ret = ioctl(fd, VIDIOC_REQBUFS, &reqbuf);
1144                 if (ret) {
1145                         printf("[fd%d] Err REQBUFS failed on CAPTURE queue ret %d errno %d\n",
1146                                 fd, ret, errno);
1147                         return ret;
1148                 }
1149                 debug_printf("[fd%d] After VIDIOC_REQBUFS getting buf_cnt %d\n",
1150                         fd, reqbuf.count);
1151                 *n_capbufs = reqbuf.count;
1152                 /*Creating Capbuffers with v4l2 BUFFERS*/
1153                 /* QUERYBUF on Capture - memory of V4L2_MEMORY_MMAP */
1155                 if(str->codec == AV_CODEC_ID_MJPEG) {
1156                         struct v4l2_plane buf_planes_cap[FMT_NUM_MJPEG_PLANES];
1158                         for (j = 0; j < (*n_capbufs / 3); j++) {
1159                                 memset(&buffer_cap, 0, sizeof(buffer_cap));
1160                                 buffer_cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1161                                 buffer_cap.index = j;
1162                                 buffer_cap.m.planes = buf_planes_cap;
1163                                 buffer_cap.length = FMT_NUM_MJPEG_PLANES;
1164                                 buffer_cap.memory = V4L2_MEMORY_MMAP;
1167                                 ret = ioctl(fd, VIDIOC_QUERYBUF, &buffer_cap);
1168                                 if (ret < 0) {
1169                                         printf("[fd%d] CANNOT QUERY BUFFERS for Capture ret = %d\n", fd, ret);
1170                                         return -1;
1171                                 }
1172                                 for (i = 0; i < buffer_cap.length; i++) {
1173                                 debug_printf("[fd%d] query buf, buffer %p plane %d = %d buffer_cap.length %d buffer_cap.data_offset %d buffer_cap.mem_offset %d\n",
1174                                                 fd, &buffer_cap, i,buffer_cap.m.planes[i].length,
1175                                                 buffer_cap.length, buffer_cap.m.planes[i].data_offset,
1176                                                 buffer_cap.m.planes[i].m.mem_offset);
1178                                 capbufs[(j*3)+i].mapped = mmap(NULL, buffer_cap.m.planes[i].length,
1179                                                 PROT_READ, MAP_SHARED,
1180                                                 fd, buffer_cap.m.planes[i].m.mem_offset);
1181                                 capbufs[(j*3)+i].offset = buffer_cap.m.planes[i].m.mem_offset;
1182                                 capbufs[(j*3)+i].length = buffer_cap.m.planes[i].length;
1184                                 debug_printf("[fd%d] After mmap -> capbufs[%d].mapped = 0x%p\n",
1185                                         fd, (j*3)+i, capbufs[(j*3)+i].mapped);
1187                                 if (MAP_FAILED == capbufs[(j*3)+i].mapped) {
1188                                         while (j >= 0) {
1189                                                 /* Unmap all previous buffers */
1190                                                 j--;
1191                                                 munmap(capbufs[(j*3)+i].mapped,
1192                                                          fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
1193                                                          capbufs[(j*3)+i].mapped = NULL;
1194                                         }
1195                                         printf("[fd%d] Cant mmap capture buffers Y\n", fd);
1196                                         return -1;
1197                                 }
1198                                 }
1199                         }
1200                 } else {
1201                         struct v4l2_plane buf_planes_cap[FMT_NUM_PLANES];
1202                 for (j = 0; j < *n_capbufs; j++) {
1203                         memset(&buffer_cap, 0, sizeof(buffer_cap));
1204                         buffer_cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1205                         buffer_cap.index = j;
1206                         buffer_cap.m.planes = buf_planes_cap;
1207                         buffer_cap.length = FMT_NUM_PLANES;
1208                         buffer_cap.memory = V4L2_MEMORY_MMAP;
1211                         ret = ioctl(fd, VIDIOC_QUERYBUF, &buffer_cap);
1212                         if (ret < 0) {
1213                                 printf("[fd%d] CANNOT QUERY BUFFERS for Capture ret = %d\n",
1214                                                 fd, ret);
1215                                 return -1;
1216                         }
1217                         debug_printf("[fd%d] query buf, buffer %p plane 0 = %d buffer_cap.length %d buffer_cap.data_offset %d buffer_cap.mem_offset %d\n",
1218                                         fd, &buffer_cap,
1219                                         buffer_cap.m.planes[0].length,
1220                                         buffer_cap.length,
1221                                         buffer_cap.m.planes[0].data_offset,
1222                                         buffer_cap.m.planes[0].m.mem_offset);
1224                         capbufs[j].mapped = mmap(NULL, buffer_cap.m.planes[0].length,
1225                                         PROT_READ, MAP_SHARED,
1226                                         fd, buffer_cap.m.planes[0].m.mem_offset);
1227                         capbufs[j].offset = buffer_cap.m.planes[0].m.mem_offset;
1228                         capbufs[j].length = buffer_cap.m.planes[0].length;
1230                         debug_printf("[fd%d] After mmap -> capbufs[%d].mapped = 0x%p\n",
1231                                         fd, j, capbufs[j].mapped);
1233                         if (MAP_FAILED == capbufs[j].mapped) {
1234                                 while (j >= 0) {
1235                                         /* Unmap all previous buffers */
1236                                         j--;
1237                                         munmap(capbufs[j].mapped,
1238                                                  fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
1239                                                  capbufs[j].mapped = NULL;
1240                                 }
1241                                 printf("[fd%d] Cant mmap capture buffers Y\n", fd);
1242                                 return -1;
1243                         }
1244                 }
1245                 }
1246         } else {
1247                 debug_printf("[fd%d] Setup decoding CAPTURE with VIDIOC_REQBUFS\n", fd);
1248                 debug_printf("[fd%d] buffer(y) size %u buffer(uv) size %u\n",
1249                                 fd, fmt.fmt.pix_mp.plane_fmt[0].sizeimage,
1250                                 fmt.fmt.pix_mp.plane_fmt[1].sizeimage);
1252                 memzero(reqbuf);
1253                 reqbuf.count = *n_capbufs;
1254                 reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1255                 reqbuf.memory = V4L2_MEMORY_DMABUF;
1257                 ret = ioctl(fd, VIDIOC_REQBUFS, &reqbuf);
1258                 if (ret) {
1259                         printf("[fd%d] Err REQBUFS failed on CAPTURE queue ret %d errno %d\n",
1260                                         fd, ret, errno);
1261                         return ret;
1262                 }
1263                 debug_printf("[fd%d] After VIDIOC_REQBUFS getting buf_cnt %d\n",
1264                                 fd, reqbuf.count);
1265                 *n_capbufs = reqbuf.count;
1267                 /* Create DRM buffers */
1268                 for (i = 0; i < *n_capbufs; i++) {
1269                         ret = create_drm_buffer(&capbufs[i],
1270                                         ALIGN(fmt.fmt.pix_mp.width, HW_ALIGN),
1271                                         ((str->num_bytes_per_pix *
1272                                                 fmt.fmt.pix_mp.height * format.size_num) /
1273                                          format.size_den));
1274                         if (ret) {
1275                                 printf("[fd%d] failed to create drm buffers\n", fd);
1276                                 return -1;
1277                         }
1278                         debug_printf("[fd%d] Create_DRM_BUFFERS drm_y_buffer[%d].dbuf_fd 0x%x, length %d offset %d\n",
1279                                         fd, i, capbufs[i].dbuf_fd, capbufs[i].length, capbufs[i].offset);
1280                 }
1281         }
1282         return ret;
1285 static void close_device(int fd)
1287         debug_printf("[fd%d] close_device\n", fd);
1288         if (-1 == close(fd))
1289                 errno_exit ("close");
1290         fd = -1;
1293 static int open_device(char *dev_name)
1295         struct v4l2_capability cap;
1296         struct v4l2_fmtdesc argp;
1297         int ret = 0;
1298         int fd = -1;
1299         struct v4l2_event_subscription sub;
1301         fd = open(dev_name, O_RDWR | O_NONBLOCK, 0);
1302         if (-1 == fd) {
1303                 printf("Cannot open '%s': %d, %s\n",
1304                                 dev_name, errno, strerror(errno));
1305                 return -1;
1306         }
1308         ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
1309         if (ret != 0) {
1310                 printf("Failed to verify capabilities\n");
1311                 return -1;
1312         }
1314         debug_printf("[fd%d] Info (%s): driver\"%s\" bus_info=\"%s\" card=\"%s\" fd=0x%x\n",
1315                         fd, dev_name, cap.driver, cap.bus_info, cap.card, fd);
1317         debug_printf("[fd%d] Info (%s): capabilities\"0x%x\" device_caps=\"0x%x\" \n",
1318                         fd, dev_name, cap.capabilities, cap.device_caps);
1320         memset(&argp, 0, sizeof(argp));
1321         argp.index = 0;
1322         argp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1324         debug_printf("[fd%d] Calling V4L2 IOCTL VIDIOC_ENUM_FMT on CAPTURE\n",
1325                         fd);
1326         while ((ret = ioctl(fd, VIDIOC_ENUM_FMT, &argp)) == 0) {
1327                 debug_printf("[fd%d] argp.index = %d, {pixelformat = %c%c%c%c}, description = '%s'\n",
1328                                 fd, argp.index, argp.pixelformat & 0xff,
1329                                 (argp.pixelformat >> 8) & 0xff,
1330                                 (argp.pixelformat >>16) & 0xff,
1331                                 (argp.pixelformat >> 24) & 0xff,
1332                                 argp.description);
1333                 argp.index ++;
1334         }
1336         argp.index = 0;
1337         argp.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1339         debug_printf("[fd%d] Calling V4L2 IOCTL VIDIOC_ENUM_FMT on OUTPUT\n",
1340                         fd);
1341         while ((ret = ioctl(fd, VIDIOC_ENUM_FMT, &argp)) == 0) {
1342                 debug_printf("[fd%d] argp.index = %d, {pixelformat = %c%c%c%c}, description = '%s'\n",
1343                                 fd, argp.index, argp.pixelformat & 0xff,
1344                                 (argp.pixelformat >> 8) & 0xff,
1345                                 (argp.pixelformat >>16) & 0xff,
1346                                 (argp.pixelformat >> 24) & 0xff,
1347                                 argp.description);
1348                 argp.index ++;
1349         }
1351         memset(&sub, 0, sizeof(sub));
1352         sub.type = V4L2_EVENT_EOS;
1354         debug_printf("[fd%d] Calling V4L2 IOCTL VIDIOC_SUBSCRIBE_EVENT\n", fd);
1355         ret = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
1356         if (ret != 0) {
1357                 printf("[fd%d] Failed to subscribe to events: err: %d %s\n",
1358                                 fd, errno, strerror(errno));
1359         }
1361         return fd;
1364 int main(int argc, char **argv)
1366         char *dev_name = "/dev/video0";
1367         int i = 0;
1368         int ret = 0;
1369         unsigned int num_devs = 1;
1370         int fds[MAX_TEST_FDS];
1371         int rdfd = -1;
1372         int wrfd = -1;
1373         int c;
1374         int n_outbufs, n_capbufs, n_frames;
1375         struct buffer outbufs[MAX_OUTBUFS];
1376         struct buffer capbufs[MAX_CAPBUFS];
1377         struct stream_context str_context;
1378         char input_file[256];
1379         char output_file_base[120];
1380         char output_file[128];
1381         const char *dir_path = "/dev/dri/";
1382         char drm_file_name[20];
1383         DIR *d;
1384         struct dirent *dir;
1385         drmModeResPtr res;
1386         int max_frames = -1;
1387         int enable_prof = 0;
1388         int sleep_time = 0;
1389         struct output_format fmt;
1390         int use_drm_capbuff = 1; /* Defaulting to use drm dss Capture Buffers */
1392         printf("TI DEC V4L2 Codec decoding example application\n");
1393         printf("Copyright (c) 2018 Texas Instruments, Inc.\n");
1395         /* Parse the input args */
1396         while (1)
1397         {
1398                 c = getopt (argc, argv, "nf:hbi:o:d:te:");
1399                 if (c == -1)
1400                         break;
1402                 switch (c) {
1403                         case 'n':
1404                                 num_devs = atoi(optarg);
1405                                 break;
1406                         case 'h':
1407                                 printf("Use:\n");
1408                                 printf("\t./tidec_decode -i <input_file> [OPTIONS]\n");
1409                                 printf("\tThe final output file/s will be '<output_file_base>_xx.out'\n");
1410                                 printf("\twhere xx ranges from 00, 01, 02, ...\n");
1411                                 printf("\tdepending on how many fds are specified to -n\n");
1412                                 printf("\tOPTIONS:\n");
1413                                 printf("\t\t-h help\n");
1414                                 printf("\t\t-b DO NOT use drm dss device capture buffer (instead, use v4l2)\n");
1415                                 printf("\t\t-n <number> number of fds to open\n");
1416                                 printf("\t\t-o <output_file_base> Dump output stream to file\n");
1417                                 printf("\t\t\tThe final output file/s will be '<output_file_base>_xx.out'\n");
1418                                 printf("\t\t\twhere xx ranges from 00, 01, 02, ...\n");
1419                                 printf("\t\t\tdepending on how many fds are specified to -n\n");
1420                                 printf("\t\t-f <number of frames to decode> Maximum number of frames to decode\n");
1421                                 printf("\t\t-d <path> Path to which drm device to use for buffer allocation\n");
1422                                 printf("\t\t-t for enable time profiling\n");
1423                                 printf("\t\t-e <number of ms> Number of milliseconds to sleep between\n");
1424                                 printf("\t\t\tqueueing the last bitstream buffer and sending CMD_STOP\n");
1425                                 printf("\t\t\tUsed to test various timing scenarios for EOS\n");
1426                                 break;
1427                         case 'b':
1428                                 use_drm_capbuff = 0; /* DO NOT use drm dss device*/
1429                                 break;
1430                         case 'i':
1431                                 snprintf(input_file, sizeof(input_file),
1432                                                 "%s", optarg);
1433                                 break;
1434                         case 'o':
1435                                 snprintf(output_file_base,
1436                                                 sizeof(output_file_base),
1437                                                 "%s", optarg);
1438                                 break;
1439                         case 'f':
1440                                 max_frames = atoi(optarg);
1441                                 break;
1442                         case 'd':
1443                                 snprintf(drm_file_name, sizeof(drm_file_name),
1444                                                 "%s", optarg);
1445                                 break;
1446                         case 't':
1447                                 enable_prof = 1;
1448                                 break;
1449                         case 'e':
1450                                 sleep_time = 1000 * atoi(optarg);
1451                                 break;
1452                         default:
1453                                 printf("Unrecognized argument %c\n", c);
1454                 }
1455         }
1457         if (0 == strlen(input_file)) {
1458                 printf("Requires an input value\n");
1459                 printf("\t./tidec_decode -i <input_file> [OPTIONS]\n");
1460                 return EXIT_FAILURE;
1461         }
1463         /* validate input args */
1464         if (num_devs > MAX_TEST_FDS) {
1465                 printf("Invalid value passed for number of devices %d\n",
1466                                 num_devs);
1467                 return EXIT_FAILURE;
1468         }
1470         for (i = 0; i < num_devs; i++) {
1471                 debug_printf("*** Calling open_device for device %d \n", i);
1472                 fds[i] = open_device(dev_name);
1473                 if (fds[i] < 0)
1474                         return EXIT_FAILURE;
1475                 debug_printf("*** device %d is fd %d", i, fds[i]);
1476         }
1478         if (use_drm_capbuff == 0) {
1479                 printf("\nUsing v4l2 for capture buffers\n");
1480         } else {
1481                 if (strlen(drm_file_name) > 0) {
1482                         drmfd1 = open(drm_file_name, O_CLOEXEC);
1483                         if (drmfd1 < 0) {
1484                                 printf("Failed to open drm device\n");
1485                                 return EXIT_FAILURE;
1486                         }
1487                 } else {
1488                         d = opendir(dir_path);
1489                         if (!d) {
1490                                 printf("Failed to open drm device directory\n");
1491                                 return EXIT_FAILURE;
1492                         }
1493                         while ((dir = readdir(d)) != NULL) {
1494                                 if(strncmp(dir->d_name, DEVICE_NAME, 4) == 0) {
1495                                         strcpy(drm_file_name, dir_path);
1496                                         strncat(drm_file_name, dir->d_name,
1497                                                 sizeof(DEVICE_NAME));
1498                                         drmfd1 = open(drm_file_name, O_CLOEXEC);
1499                                         if (drmfd1 < 0) {
1500                                                 printf("Failed to open drm device %s\n",
1501                                                                 drm_file_name);
1502                                         }
1503                                         printf("No drm device specified, testing %s\n",
1504                                                         drm_file_name);
1505                                         res = drmModeGetResources(drmfd1);
1506                                         if (res && res->count_crtcs > 0 &&
1507                                                         res->count_connectors > 0 &&
1508                                                         res->count_encoders > 0) {
1509                                                 printf("No drm device specified, using %s\n",
1510                                                                 drm_file_name);
1511                                                 break;
1512                                         }
1513                                         close(drmfd1);
1514                                         drmfd1 = -1;
1515                                 }
1516                         }
1517                 }
1518                 if (drmfd1 < 0) {
1519                         printf("Failed to open drm device\n");
1520                         return EXIT_FAILURE;
1521                 }
1522         }
1524         /* Get the stream width, height and framesizes of H264 stream */
1525         n_frames = stream_framelevel_parsing(&str_context, input_file, max_frames);
1526         if (n_frames < 0) {
1527                 printf("Failed to init frame sizes\n");
1528                 return EXIT_FAILURE;
1529         }
1531         switch (str_context.pix_fmt) {
1532                 case AV_PIX_FMT_YUV420P:
1533                         fmt.fourcc = V4L2_PIX_FMT_NV12;
1534                         fmt.size_num = 3;
1535                         fmt.size_den = 2;
1536                         break;
1537                 case AV_PIX_FMT_YUV422P:
1538                         fmt.fourcc = V4L2_PIX_FMT_NV16;
1539                         fmt.size_num = 2;
1540                         fmt.size_den = 1;
1541                         break;
1542                 case AV_PIX_FMT_YUV420P10LE:
1543                         fmt.fourcc = V4L2_PIX_FMT_TI1210;
1544                         fmt.size_num = 3;
1545                         fmt.size_den = 2;
1546                         break;
1547                 case AV_PIX_FMT_YUV422P10LE:
1548                         fmt.fourcc = V4L2_PIX_FMT_TI1610;
1549                         fmt.size_num = 2;
1550                         fmt.size_den = 1;
1551                         break;
1552                 case AV_PIX_FMT_YUVJ420P:
1553                         fmt.fourcc = V4L2_PIX_FMT_YUV420M;
1554                         fmt.size_num = 1;
1555                         fmt.size_den = 1;
1556                         break;
1557                 case AV_PIX_FMT_YUVJ422P:
1558                         fmt.fourcc = V4L2_PIX_FMT_YUV422M;
1559                         fmt.size_num = 1;
1560                         fmt.size_den = 1;
1561                         break;
1562                 default:
1563                         printf("Invalid pixel format detected\n");
1564                         return -1;
1565         }
1567         for (i = 0; i < num_devs; i++) {
1568                 n_outbufs = MAX_OUTBUFS;
1569                 /* Request number of output buffers based on h264 spec
1570                  * + display delay */
1571                 n_capbufs = MIN(MAX_CAPBUFS_H264, (32768 /
1572                                         ((str_context.width / 16) *
1573                                         (str_context.height / 16)))) +
1574                                         DISPLAY_LAG;
1576                 debug_printf("Opening input file\n");
1577                 rdfd = open(input_file, O_RDONLY);
1578                 if (rdfd < 0) {
1579                         printf("Failed to open input file %s", input_file);
1580                 }
1582                 if (strcmp(output_file_base, "")) {
1583                         snprintf(output_file, sizeof(output_file),
1584                                         "%s_%02d.raw", output_file_base, i);
1585                         wrfd = open(output_file,
1586                                         O_CREAT | O_WRONLY | O_SYNC | O_TRUNC,
1587                                         0777);
1588                 }
1590                 if (wrfd < 0) {
1591                         if (strcmp(output_file_base, "")) {
1592                                 printf("Failed to open output file %s\n",
1593                                                 output_file);
1594                                 return EXIT_FAILURE;
1595                         } else {
1596                                 printf("No output file specified\n");
1597                         }
1598                 } else {
1599                         debug_printf("Opened output file %s\n", output_file);
1600                 }
1602                 ret = init_device(fds[i], rdfd, &str_context, outbufs,
1603                                 capbufs, &n_outbufs, &n_capbufs, fmt, use_drm_capbuff);
1604                 if (ret) {
1605                         printf("init_device failed with ret %d for device %d [fd%d]\n",
1606                                         ret, i, fds[i]);
1607                         return EXIT_FAILURE;
1608                 }
1610                 if (mainloop(fds[i], rdfd, wrfd, &str_context, outbufs,
1611                                         capbufs, n_outbufs,
1612                                         n_capbufs, n_frames,
1613                                         enable_prof, fmt,
1614                                         sleep_time, use_drm_capbuff)) {
1615                         return EXIT_FAILURE;
1616                 }
1618                 close(rdfd);
1619                 if (!(wrfd < 0))
1620                         close(wrfd);
1621                 rdfd = -1;
1622                 wrfd = -1;
1624                 uninit_device(fds[i], outbufs, capbufs, &n_outbufs, &n_capbufs, use_drm_capbuff);
1626                 debug_printf("*** Calling close_device for device %d [fd%d]\n",
1627                                 i, fds[i]);
1628                 close_device(fds[i]);
1629         }
1631         if (use_drm_capbuff && drmfd1)
1632                 close(drmfd1);
1634         printf("test app completed successfully\n");
1635         return 0;