2 * Copyright (C) 2016 Nexell Co. All Rights Reserved
3 * Nexell Co. Proprietary & Confidential
5 * NEXELL INFORMS THAT THIS CODE AND INFORMATION IS PROVIDED "AS IS" BASE
6 * AND WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING
7 * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS
8 * FOR A PARTICULAR PURPOSE.
10 * File : nx_video_api.c
11 * Brief : V4L2 Video Decoder
12 * Author : SungWon Jo (doriya@nexell.co.kr)
13 * History : 2016.04.25 : Create
24 #include <sys/ioctl.h>
26 #include <linux/videodev2.h>
27 #include <linux/videodev2_nxp_media.h>
29 #include <nx_video_alloc.h>
30 #include <nx_video_api.h>
31 #include "nx_video_log.h"
34 /*----------------------------------------------------------------------------*/
35 #define NX_V4L2_DEC_NAME "nx-vpu-dec"
36 #define VIDEODEV_MINOR_MAX 63
37 #define STREAM_BUFFER_NUM 1
40 struct NX_V4L2DEC_INFO
47 int32_t useExternalFrameBuffer;
48 int32_t numFrameBuffers;
49 NX_VID_MEMORY_HANDLE hImage[MAX_FRAME_BUFFER_NUM];
51 NX_MEMORY_HANDLE hStream[STREAM_BUFFER_NUM];
53 /* Initialize Output Information */
54 uint8_t pSeqData[1024]; /* SPS PPS (H.264) or Decoder Specific Information(for MPEG4) */
57 IMG_DISP_INFO dispInfo;
75 /*----------------------------------------------------------------------------*/
84 char filename[64], name[64];
87 while (!found && (i <= VIDEODEV_MINOR_MAX)) {
88 /* video device node */
89 snprintf (filename, 64, "/dev/video%d", i);
91 /* if the node is video device */
92 if ((lstat (filename, &s) == 0) && S_ISCHR (s.st_mode)
93 && ((int) ((unsigned short) (s.st_rdev) >> 8) == 81)) {
94 /* open sysfs entry */
95 snprintf (filename, 64, "/sys/class/video4linux/video%d/name", i);
96 stream_fd = fopen (filename, "r");
97 if (stream_fd == NULL) {
98 _D ("failed to open sysfs entry for videodev \n");
103 /* read sysfs entry for device name */
104 if (fgets (name, sizeof (name), stream_fd) == 0) {
105 _D ("failed to read sysfs entry for videodev\n");
107 if (strncmp (name, NX_V4L2_DEC_NAME, strlen (NX_V4L2_DEC_NAME)) == 0) {
108 _D ("node found for device %s: /dev/video%d \n", NX_V4L2_DEC_NAME,
121 snprintf (filename, 64, "/dev/video%d", i - 1);
122 fd = open (filename, O_RDWR);
130 #define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
134 #define PUT_LE32(_p, _var) \
135 *_p++ = (uint8_t)((_var) >> 0); \
136 *_p++ = (uint8_t)((_var) >> 8); \
137 *_p++ = (uint8_t)((_var) >> 16); \
138 *_p++ = (uint8_t)((_var) >> 24);
142 #define PUT_BE32(_p, _var) \
143 *_p++ = (uint8_t)((_var) >> 24); \
144 *_p++ = (uint8_t)((_var) >> 16); \
145 *_p++ = (uint8_t)((_var) >> 8); \
146 *_p++ = (uint8_t)((_var) >> 0);
150 #define PUT_LE16(_p, _var) \
151 *_p++ = (uint8_t)((_var) >> 0); \
152 *_p++ = (uint8_t)((_var) >> 8);
156 #define PUT_BE16(_p, _var) \
157 *_p++ = (uint8_t)((_var) >> 8); \
158 *_p++ = (uint8_t)((_var) >> 0);
170 vld_count_leading_zero (uint32_t dwWord)
174 if ((dwWord >> (32 - 16)) == 0)
176 if ((dwWord >> (32 - 8 - iLZ)) == 0)
178 if ((dwWord >> (32 - 4 - iLZ)) == 0)
180 if ((dwWord >> (32 - 2 - iLZ)) == 0)
182 if ((dwWord >> (32 - 1 - iLZ)) == 0)
189 vld_show_bits (VLD_STREAM * pstVldStm, int32_t iBits)
191 uint32_t dwUsedBits = pstVldStm->dwUsedBits;
192 int32_t iBitCnt = 8 - (dwUsedBits & 0x7);
193 uint8_t *pbyRead = (uint8_t *) pstVldStm->pbyStart + (dwUsedBits >> 3);
196 dwRead = *pbyRead++ << 24;
197 if (iBits > iBitCnt) {
198 dwRead += *pbyRead++ << 16;
199 if (iBits > iBitCnt + 8) {
200 dwRead += *pbyRead++ << 8;
201 if (iBits > iBitCnt + 16)
202 dwRead += *pbyRead++;
206 return (dwRead << (8 - iBitCnt)) >> (32 - iBits);
210 vld_get_bits (VLD_STREAM * pstVldStm, int32_t iBits)
212 uint32_t dwUsedBits = pstVldStm->dwUsedBits;
213 int32_t iBitCnt = 8 - (dwUsedBits & 0x7);
214 uint8_t *pbyRead = (uint8_t *) pstVldStm->pbyStart + (dwUsedBits >> 3);
217 pstVldStm->dwUsedBits += iBits;
219 dwRead = *pbyRead++ << 24;
220 if (iBits > iBitCnt) {
221 dwRead += *pbyRead++ << 16;
222 if (iBits > iBitCnt + 8) {
223 dwRead += *pbyRead++ << 8;
224 if (iBits > iBitCnt + 16)
225 dwRead += *pbyRead++;
229 return (dwRead << (8 - iBitCnt)) >> (32 - iBits);
233 vld_flush_bits (VLD_STREAM * pstVldStm, int iBits)
235 pstVldStm->dwUsedBits += iBits;
239 vld_get_uev (VLD_STREAM * pstVldStm)
241 int32_t iLZ = vld_count_leading_zero (vld_show_bits (pstVldStm, 32));
243 vld_flush_bits (pstVldStm, iLZ);
244 return (vld_get_bits (pstVldStm, iLZ + 1) - 1);
248 Mp4DecParseVideoCfg (NX_V4L2DEC_HANDLE hDec, uint8_t * pbyStream,
251 uint8_t *pbyStrm = pbyStream;
252 uint32_t uPreFourByte = (uint32_t) - 1;
254 hDec->vopTimeBits = 0;
257 if (pbyStrm >= (pbyStream + iStreamSize))
260 uPreFourByte = (uPreFourByte << 8) + *pbyStrm++;
262 if (uPreFourByte >= 0x00000120 && uPreFourByte <= 0x0000012F) {
263 VLD_STREAM stStrm = { 0, pbyStrm, iStreamSize };
266 vld_flush_bits (&stStrm, 1 + 8); /* random_accessible_vol, video_object_type_indication */
267 if (vld_get_bits (&stStrm, 1)) /* is_object_layer_identifier */
268 vld_flush_bits (&stStrm, 4 + 3); /* video_object_layer_verid, video_object_layer_priority */
270 if (vld_get_bits (&stStrm, 4) == 0xF) /* aspect_ratio_info */
271 vld_flush_bits (&stStrm, 8 + 8); /* par_width, par_height */
273 if (vld_get_bits (&stStrm, 1)) { /* vol_control_parameters */
274 if (vld_get_bits (&stStrm, 2 + 1 + 1) & 1) { /* chroma_format, low_delay, vbv_parameters */
275 vld_flush_bits (&stStrm, 15 + 1); /* first_half_bit_rate, marker_bit */
276 vld_flush_bits (&stStrm, 15 + 1); /* latter_half_bit_rate, marker_bit */
277 vld_flush_bits (&stStrm, 15 + 1); /* first_half_vbv_buffer_size, marker_bit */
278 vld_flush_bits (&stStrm, 3 + 11 + 1); /* latter_half_vbv_buffer_size, first_half_vbv_occupancy, marker_bit */
279 vld_flush_bits (&stStrm, 15 + 1); /* latter_half_vbv_occupancy, marker_bit */
283 vld_flush_bits (&stStrm, 2 + 1); /* video_object_layer_shape, marker_bit */
285 for (i = 0; i < 16; i++) /* vop_time_increment_resolution */
286 if (vld_get_bits (&stStrm, 1))
288 hDec->vopTimeBits = 16 - i;
295 Mp4DecParseFrameHeader (NX_V4L2DEC_HANDLE hDec, uint8_t * pbyStream,
298 VLD_STREAM stStrm = { 0, pbyStream, iStreamSize };
299 int32_t iSize = iStreamSize;
301 if (vld_get_bits (&stStrm, 32) == 0x000001B6) {
302 vld_flush_bits (&stStrm, 2); /* vop_coding_type */
305 if (vld_get_bits (&stStrm, 1) == 0)
307 } while (stStrm.dwUsedBits < ((uint32_t) iStreamSize << 3));
309 vld_flush_bits (&stStrm, 1 + hDec->vopTimeBits + 1); /* marker_bits, vop_time_increment, marker_bits */
311 if (vld_get_bits (&stStrm, 1) == 0) /* vop_coded */
319 GetSequenceHeader (NX_V4L2DEC_HANDLE hDec, NX_V4L2DEC_SEQ_IN * pSeqIn)
321 uint8_t *pbySrc = pSeqIn->seqBuf;
322 uint8_t *pbyDst = (uint8_t *) hDec->hStream[0]->pBuffer;
323 int32_t iSize = pSeqIn->seqSize;
325 switch (hDec->codecType) {
326 case V4L2_PIX_FMT_H264:
327 if (pSeqIn->seqSize > 0) {
328 memcpy (pbyDst, pbySrc, pSeqIn->seqSize);
330 if ((pbySrc[2] == 0) && (pbySrc[7] > 51))
332 else if ((pbySrc[2] == 1) && (pbySrc[6] > 51))
338 case V4L2_PIX_FMT_DIV3:
339 if (pSeqIn->seqSize == 0) {
340 if ((pSeqIn->width > 0) && (pSeqIn->height > 0)) {
341 PUT_LE32 (pbyDst, MKTAG ('C', 'N', 'M', 'V'));
342 PUT_LE16 (pbyDst, 0x00); /* version */
343 PUT_LE16 (pbyDst, 0x20); /* length of header in bytes */
344 PUT_LE32 (pbyDst, MKTAG ('D', 'I', 'V', '3')); /* codec FourCC */
345 PUT_LE16 (pbyDst, pSeqIn->width);
346 PUT_LE16 (pbyDst, pSeqIn->height);
347 PUT_LE32 (pbyDst, 0); /* frame rate */
348 PUT_LE32 (pbyDst, 0); /* time scale(?) */
349 PUT_LE32 (pbyDst, 0); /* number of frames in file */
350 PUT_LE32 (pbyDst, 0); /* unused */
355 PUT_BE32 (pbyDst, pSeqIn->seqSize);
357 memcpy (pbyDst, pbyDst, pSeqIn->seqSize);
361 case V4L2_PIX_FMT_WMV9:
362 if ((pSeqIn->seqSize > 0) && (pSeqIn->width > 0) && (pSeqIn->height > 0)) {
364 PUT_LE32 (pbyDst, (0xC5 << 24) | 0x00); /* version */
367 PUT_LE32 (pbyDst, (0x85 << 24) | 0x00);
370 PUT_LE32 (pbyDst, pSeqIn->seqSize);
371 memcpy (pbyDst, pbySrc, pSeqIn->seqSize);
372 pbyDst += pSeqIn->seqSize;
373 PUT_LE32 (pbyDst, pSeqIn->height);
374 PUT_LE32 (pbyDst, pSeqIn->width);
377 PUT_LE32 (pbyDst, 12);
378 /* STRUCT_B_FRIST (LEVEL:3|CBR:1:RESERVE:4:HRD_BUFFER|24) */
379 PUT_LE32 (pbyDst, 2 << 29 | 1 << 28 | 0x80 << 24 | 1 << 0);
380 PUT_LE32 (pbyDst, 0); /* bitrate */
381 PUT_LE32 (pbyDst, 0); /* framerate */
388 case V4L2_PIX_FMT_RV8:
389 case V4L2_PIX_FMT_RV9:
390 if ((pSeqIn->seqSize > 0) && (pSeqIn->width > 0) && (pSeqIn->height > 0)) {
393 PUT_BE32 (pbyDst, iSize); /* Length */
394 PUT_LE32 (pbyDst, MKTAG ('V', 'I', 'D', 'O')); /* MOFTag */
396 if (hDec->codecType == V4L2_PIX_FMT_RV8) {
397 PUT_LE32 (pbyDst, MKTAG ('R', 'V', '3', '0'));
399 PUT_LE32 (pbyDst, MKTAG ('R', 'V', '4', '0'));
402 PUT_BE16 (pbyDst, pSeqIn->width);
403 PUT_BE16 (pbyDst, pSeqIn->height);
404 PUT_BE16 (pbyDst, 0x0c); /* BitCount */
405 PUT_BE16 (pbyDst, 0x00); /* PadWidth */
406 PUT_BE16 (pbyDst, 0x00); /* PadHeight */
407 PUT_LE32 (pbyDst, 0); /* framerate */
408 memcpy (pbyDst, pbySrc, pSeqIn->seqSize);
413 case V4L2_PIX_FMT_VP8:
414 if ((pSeqIn->seqSize > 0) && (pSeqIn->width > 0) && (pSeqIn->height > 0)) {
415 PUT_LE32 (pbyDst, MKTAG ('D', 'K', 'I', 'F')); /* signature 'DKIF' */
416 PUT_LE16 (pbyDst, 0x00); /* version */
417 PUT_LE16 (pbyDst, 0x20); /* length of header in bytes */
418 PUT_LE32 (pbyDst, MKTAG ('V', 'P', '8', '0')); /* codec FourCC */
419 PUT_LE16 (pbyDst, pSeqIn->width); /* width */
420 PUT_LE16 (pbyDst, pSeqIn->height); /* height */
421 PUT_LE32 (pbyDst, 0); /* frame rate */
422 PUT_LE32 (pbyDst, 0); /* time scale(?) */
423 PUT_LE32 (pbyDst, 0); /* number of frames in file */
424 PUT_LE32 (pbyDst, 0); /* unused */
427 PUT_LE32 (pbyDst, pSeqIn->seqSize);
428 PUT_LE32 (pbyDst, 0);
429 PUT_LE32 (pbyDst, 0);
430 memcpy (pbyDst, pbySrc, pSeqIn->seqSize);
436 case V4L2_PIX_FMT_XVID:
437 case V4L2_PIX_FMT_DIVX:
438 case V4L2_PIX_FMT_DIV4:
439 case V4L2_PIX_FMT_DIV5:
440 case V4L2_PIX_FMT_DIV6:
441 case V4L2_PIX_FMT_MPEG4:
442 Mp4DecParseVideoCfg (hDec, pbySrc, pSeqIn->seqSize);
445 if (pSeqIn->seqSize > 0)
446 memcpy (pbyDst, pbySrc, pSeqIn->seqSize);
455 GetFrameStream (NX_V4L2DEC_HANDLE hDec, NX_V4L2DEC_IN * pDecIn, int32_t * idx)
457 int32_t iSize = pDecIn->strmSize;
458 uint8_t *pbySrc = pDecIn->strmBuf;
464 *idx = hDec->frameCnt % STREAM_BUFFER_NUM;
465 pbyDst = (uint8_t *) hDec->hStream[*idx]->pBuffer;
467 switch (hDec->codecType) {
468 case V4L2_PIX_FMT_H264:
469 memcpy (pbyDst, pbySrc, iSize);
471 if ((pbySrc[2] == 0) && ((pbySrc[4] & 0x1F) == 7) && (pbySrc[7] > 51))
473 else if ((pbySrc[2] == 1) && ((pbySrc[3] & 0x1F) == 7)
479 case V4L2_PIX_FMT_WVC1:
480 /* check start code as prefix (0x00, 0x00, 0x01) */
481 if (pbySrc[0] != 0 || pbySrc[1] != 0 || pbySrc[2] != 1) {
486 memcpy (pbyDst, pbySrc, iSize);
489 /* no extra header size, there is start code in input stream */
490 memcpy (pbyDst, pbySrc, iSize);
494 case V4L2_PIX_FMT_WMV9:
495 PUT_LE32 (pbyDst, iSize | 0); /* Key Frame = 0x80000000 */
499 PUT_LE32 (pbyDst, 0);
503 memcpy (pbyDst, pbySrc, pDecIn->strmSize);
506 case V4L2_PIX_FMT_RV8:
507 case V4L2_PIX_FMT_RV9:
509 int32_t cSlice, nSlice;
510 int32_t i, val, offset;
512 cSlice = pbySrc[0] + 1;
513 nSlice = iSize - 1 - (cSlice * 8);
515 PUT_BE32 (pbyDst, nSlice);
516 PUT_LE32 (pbyDst, 0);
517 PUT_BE16 (pbyDst, 0); /* frame number */
518 PUT_BE16 (pbyDst, 0x02); /* Flags */
519 PUT_BE32 (pbyDst, 0x00); /* LastPacket */
520 PUT_BE32 (pbyDst, cSlice); /* NumSegments */
523 for (i = 0; i < cSlice; i++) {
525 (pbySrc[offset + 3] << 24) | (pbySrc[offset +
526 2] << 16) | (pbySrc[offset + 1] << 8) | pbySrc[offset];
527 PUT_BE32 (pbyDst, val); /* isValid */
530 (pbySrc[offset + 3] << 24) | (pbySrc[offset +
531 2] << 16) | (pbySrc[offset + 1] << 8) | pbySrc[offset];
532 PUT_BE32 (pbyDst, val); /* Offset */
536 memcpy (pbyDst, pbySrc + (1 + (cSlice * 8)), nSlice);
537 iSize = 20 + (cSlice * 8) + nSlice;
541 case V4L2_PIX_FMT_DIV3:
542 case V4L2_PIX_FMT_VP8:
543 PUT_LE32 (pbyDst, iSize);
544 PUT_LE32 (pbyDst, 0);
545 PUT_LE32 (pbyDst, 0);
546 memcpy (pbyDst, pbySrc, iSize);
550 case V4L2_PIX_FMT_XVID:
551 case V4L2_PIX_FMT_DIVX:
552 case V4L2_PIX_FMT_DIV4:
553 case V4L2_PIX_FMT_DIV5:
554 case V4L2_PIX_FMT_DIV6:
555 case V4L2_PIX_FMT_MPEG4:
557 if (hDec->vopTimeBits > 0) {
558 iSize = Mp4DecParseFrameHeader (hDec, pbySrc, iSize);
562 memcpy ((void *) pbyDst, (void *) pbySrc, iSize);
573 /*----------------------------------------------------------------------------*/
575 NX_V4l2DecOpen (uint32_t codecType)
577 NX_V4L2DEC_HANDLE hDec =
578 (NX_V4L2DEC_HANDLE) malloc (sizeof (struct NX_V4L2DEC_INFO));
580 memset (hDec, 0, sizeof (struct NX_V4L2DEC_INFO));
582 hDec->fd = V4l2DecOpen ();
584 _E ("Failed to open video decoder device\n");
588 /* Query capabilities of Device */
590 struct v4l2_capability cap;
592 memset (&cap, 0, sizeof (cap));
594 if (ioctl (hDec->fd, VIDIOC_QUERYCAP, &cap) != 0) {
595 _E ("failed to ioctl: VIDIOC_QUERYCAP\n");
600 hDec->codecType = codecType;
610 /*----------------------------------------------------------------------------*/
612 NX_V4l2DecClose (NX_V4L2DEC_HANDLE hDec)
617 _E ("Fail, Invalid Handle.\n");
622 enum v4l2_buf_type type;
624 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
625 if (ioctl (hDec->fd, VIDIOC_STREAMOFF, &type) != 0) {
626 _E ("failed to ioctl: VIDIOC_STREAMOFF(Stream)\n");
630 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
631 if (ioctl (hDec->fd, VIDIOC_STREAMOFF, &type) != 0) {
632 _E ("failed to ioctl: VIDIOC_STREAMOFF(Image)\n");
636 for (i = 0; i < STREAM_BUFFER_NUM; i++)
637 NX_FreeMemory (hDec->hStream[i]);
642 if (hDec->useExternalFrameBuffer == 0) {
643 for (i = 0; i < hDec->numFrameBuffers; i++) {
644 if (hDec->hImage[i]) {
645 NX_FreeVideoMemory (hDec->hImage[i]);
646 hDec->hImage[i] = NULL;
656 /*----------------------------------------------------------------------------*/
658 NX_V4l2DecParseVideoCfg (NX_V4L2DEC_HANDLE hDec, NX_V4L2DEC_SEQ_IN * pSeqIn,
659 NX_V4L2DEC_SEQ_OUT * pSeqOut)
661 int32_t imgWidth = pSeqIn->width;
662 int32_t imgHeight = pSeqIn->height;
664 memset (pSeqOut, 0, sizeof (NX_V4L2DEC_SEQ_OUT));
667 _E ("Fail, Invalid Handle.\n");
671 hDec->seqDataSize = (pSeqIn->seqSize < 1024) ? (pSeqIn->seqSize) : (1024);
672 memcpy (hDec->pSeqData, pSeqIn->seqBuf, hDec->seqDataSize);
674 /* Set Stream Formet */
676 struct v4l2_format fmt;
678 memset (&fmt, 0, sizeof (fmt));
680 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
681 fmt.fmt.pix_mp.pixelformat = hDec->codecType;
683 if ((imgWidth == 0) || (imgHeight == 0))
684 fmt.fmt.pix_mp.plane_fmt[0].sizeimage =
685 MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * 3 / 4;
687 fmt.fmt.pix_mp.plane_fmt[0].sizeimage = imgWidth * imgHeight * 3 / 4;
689 fmt.fmt.pix_mp.width = imgWidth;
690 fmt.fmt.pix_mp.height = imgHeight;
691 fmt.fmt.pix_mp.num_planes = 1;
693 if (ioctl (hDec->fd, VIDIOC_S_FMT, &fmt) != 0) {
694 _E ("Failed to ioctx : VIDIOC_S_FMT(Input Stream)\n");
699 /* Malloc Stream Buffer */
701 struct v4l2_requestbuffers req;
702 int32_t i, buffCnt = STREAM_BUFFER_NUM;
704 /* IOCTL : VIDIOC_REQBUFS For Input Stream */
705 memset (&req, 0, sizeof (req));
706 req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
708 req.memory = V4L2_MEMORY_DMABUF;
710 if (ioctl (hDec->fd, VIDIOC_REQBUFS, &req) != 0) {
711 _E ("failed to ioctl: VIDIOC_REQBUFS(Input Stream)\n");
715 for (i = 0; i < buffCnt; i++) {
717 NX_AllocateMemory (MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * 3 / 4, 4096);
718 if (hDec->hStream[i] == NULL) {
719 _E ("Failed to allocate stream buffer(%d, %d)\n", i,
720 MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * 3 / 4);
724 if (NX_MapMemory (hDec->hStream[i]) != 0) {
725 _E ("Stream memory Mapping Failed\n");
733 if (hDec->codecType == V4L2_PIX_FMT_MJPEG) {
734 struct v4l2_control ctrl;
736 ctrl.id = V4L2_CID_MPEG_VIDEO_THUMBNAIL_MODE;
737 ctrl.value = pSeqIn->thumbnailMode;
739 if (ioctl (hDec->fd, VIDIOC_S_CTRL, &ctrl) != 0) {
740 _E ("failed to ioctl: Set Thumbnail Mode\n");
746 /* Parser Sequence Header */
748 struct v4l2_plane planes[1];
749 struct v4l2_buffer buf;
750 enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
751 int32_t iSeqSize = GetSequenceHeader (hDec, pSeqIn);
754 _E ("Fail, input data has error!!");
758 memset (&buf, 0, sizeof (buf));
759 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
760 buf.m.planes = planes;
762 buf.memory = V4L2_MEMORY_DMABUF;
765 buf.m.planes[0].m.userptr = (unsigned long) hDec->hStream[0]->pBuffer;
766 buf.m.planes[0].m.fd = hDec->hStream[0]->dmaFd;
767 buf.m.planes[0].length = hDec->hStream[0]->size;
768 buf.m.planes[0].bytesused = iSeqSize;
769 buf.m.planes[0].data_offset = 0;
771 buf.timestamp.tv_sec = pSeqIn->timeStamp / 1000;
772 buf.timestamp.tv_usec = (pSeqIn->timeStamp % 1000) * 1000;
774 if (ioctl (hDec->fd, VIDIOC_QBUF, &buf) != 0) {
775 _E ("failed to ioctl: VIDIOC_QBUF(Header Stream)\n");
779 if (ioctl (hDec->fd, VIDIOC_STREAMON, &type) != 0) {
780 _E ("Fail, ioctl(): VIDIOC_STREAMON. (Input)\n");
784 memset (&buf, 0, sizeof (buf));
785 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
786 buf.m.planes = planes;
788 buf.memory = V4L2_MEMORY_DMABUF;
790 if (ioctl (hDec->fd, VIDIOC_DQBUF, &buf) != 0) {
791 _E ("failed to ioctl: VIDIOC_DQBUF(Header Stream)\n");
795 pSeqOut->usedByte = buf.bytesused;
797 if (buf.field == V4L2_FIELD_NONE)
798 pSeqOut->interlace = NONE_FIELD;
799 else if (V4L2_FIELD_INTERLACED)
800 pSeqOut->interlace = FIELD_INTERLACED;
802 hDec->iInterlace = pSeqOut->interlace;
805 /* Get Image Information */
807 struct v4l2_format fmt;
808 struct v4l2_crop crop;
810 memset (&fmt, 0, sizeof (fmt));
811 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
813 if (ioctl (hDec->fd, VIDIOC_G_FMT, &fmt) != 0) {
814 _E ("Fail, ioctl(): VIDIOC_G_FMT.\n");
818 pSeqOut->imgFourCC = fmt.fmt.pix_mp.pixelformat;
819 pSeqOut->width = fmt.fmt.pix_mp.width;
820 pSeqOut->height = fmt.fmt.pix_mp.height;
821 pSeqOut->minBuffers = fmt.fmt.pix_mp.reserved[1];
822 hDec->numFrameBuffers = pSeqOut->minBuffers;
824 memset (&crop, 0, sizeof (crop));
825 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
827 if (ioctl (hDec->fd, VIDIOC_G_CROP, &crop) != 0) {
828 _E ("Fail, ioctl(): VIDIOC_G_CROP\n");
832 pSeqOut->dispInfo.dispLeft = crop.c.left;
833 pSeqOut->dispInfo.dispTop = crop.c.top;
834 pSeqOut->dispInfo.dispRight = crop.c.left + crop.c.width;
835 pSeqOut->dispInfo.dispBottom = crop.c.top + crop.c.height;
841 /*----------------------------------------------------------------------------*/
843 NX_V4l2DecInit (NX_V4L2DEC_HANDLE hDec, NX_V4L2DEC_SEQ_IN * pSeqIn)
845 /* Set Output Image */
847 struct v4l2_format fmt;
849 memset (&fmt, 0, sizeof (fmt));
850 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
851 fmt.fmt.pix_mp.pixelformat = pSeqIn->imgFormat;
852 fmt.fmt.pix_mp.width = pSeqIn->width;
853 fmt.fmt.pix_mp.height = pSeqIn->height;
854 fmt.fmt.pix_mp.num_planes = pSeqIn->imgPlaneNum;
856 if (ioctl (hDec->fd, VIDIOC_S_FMT, &fmt) != 0) {
857 _E ("failed to ioctl: VIDIOC_S_FMT(Output Yuv)\n");
861 hDec->planesNum = pSeqIn->imgPlaneNum;
864 /* Malloc Output Image */
866 struct v4l2_requestbuffers req;
867 struct v4l2_plane planes[3];
868 struct v4l2_buffer buf;
869 enum v4l2_buf_type type;
870 int32_t imgBuffCnt, i, j;
872 /* Calculate Buffer Number */
873 if (pSeqIn->pMemHandle == NULL) {
874 hDec->useExternalFrameBuffer = false;
875 imgBuffCnt = hDec->numFrameBuffers + pSeqIn->numBuffers;
877 hDec->useExternalFrameBuffer = true;
878 if (2 > pSeqIn->numBuffers - hDec->numFrameBuffers)
879 _D ("External Buffer too small.(min=%d, buffers=%d)\n",
880 hDec->numFrameBuffers, pSeqIn->numBuffers);
882 imgBuffCnt = pSeqIn->numBuffers;
884 hDec->numFrameBuffers = imgBuffCnt;
886 /* Request Output Buffer */
887 memset (&req, 0, sizeof (req));
888 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
889 req.count = imgBuffCnt;
890 req.memory = V4L2_MEMORY_DMABUF;
892 if (ioctl (hDec->fd, VIDIOC_REQBUFS, &req) != 0) {
893 _E ("failed to ioctl: VIDIOC_REQBUFS(Output YUV)\n");
897 memset (&buf, 0, sizeof (buf));
898 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
899 buf.m.planes = planes;
900 buf.length = pSeqIn->imgPlaneNum;
901 buf.memory = V4L2_MEMORY_DMABUF;
903 /* Allocate Buffer(Internal or External) */
904 for (i = 0; i < imgBuffCnt; i++) {
905 if (true == hDec->useExternalFrameBuffer) {
906 hDec->hImage[i] = pSeqIn->pMemHandle[i];
909 NX_AllocateVideoMemory (pSeqIn->width, pSeqIn->height,
910 pSeqIn->imgPlaneNum, pSeqIn->imgFormat, 4096);
911 if (hDec->hImage[i] == NULL) {
912 _E ("Failed to allocate image buffer(%d, %d, %d)\n", i,
913 pSeqIn->width, pSeqIn->height);
917 if (NX_MapVideoMemory (hDec->hImage[i]) != 0) {
918 _E ("Video Memory Mapping Failed\n");
925 for (j = 0; j < (int32_t) pSeqIn->imgPlaneNum; j++) {
926 buf.m.planes[j].m.fd = hDec->hImage[i]->dmaFd[j];
927 buf.m.planes[j].length = hDec->hImage[i]->size[j];
930 if (ioctl (hDec->fd, VIDIOC_QBUF, &buf) != 0) {
931 _E ("failed to ioctl: VIDIOC_QBUF(Output YUV - %d)\n", i);
936 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
937 if (ioctl (hDec->fd, VIDIOC_STREAMON, &type) != 0) {
938 _E ("failed to ioctl: VIDIOC_STREAMON\n");
946 /*----------------------------------------------------------------------------*/
948 NX_V4l2DecDecodeFrame (NX_V4L2DEC_HANDLE hDec, NX_V4L2DEC_IN * pDecIn,
949 NX_V4L2DEC_OUT * pDecOut)
951 struct v4l2_buffer buf;
952 struct v4l2_plane planes[3];
958 _E ("Fail, Invalid Handle.\n");
962 iStrmSize = GetFrameStream (hDec, pDecIn, &idx);
964 /* Queue Input Buffer */
965 memset (&buf, 0, sizeof (buf));
966 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
967 buf.m.planes = planes;
969 buf.memory = V4L2_MEMORY_DMABUF;
971 buf.timestamp.tv_sec = pDecIn->timeStamp / 1000;
972 buf.timestamp.tv_usec = (pDecIn->timeStamp % 1000) * 1000;
973 buf.flags = pDecIn->eos ? 1 : 0;
975 /* buf.m.planes[0].m.userptr = (unsigned long)hStream->pBuffer; */
976 buf.m.planes[0].m.fd = hDec->hStream[idx]->dmaFd;
977 buf.m.planes[0].length = hDec->hStream[idx]->size;
978 buf.m.planes[0].bytesused = iStrmSize;
979 buf.m.planes[0].data_offset = 0;
981 if (ioctl (hDec->fd, VIDIOC_QBUF, &buf) != 0) {
982 _E ("Fail, ioctl(): VIDIOC_QBUF.(Input)\n");
987 /* Dequeue Input ES Buffer -> Get Decoded Order Result */
988 memset (&buf, 0, sizeof (buf));
989 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
990 buf.m.planes = planes;
992 buf.memory = V4L2_MEMORY_DMABUF;
994 if (ioctl (hDec->fd, VIDIOC_DQBUF, &buf) != 0) {
995 _E ("Fail, ioctl(): VIDIOC_DQBUF.(Input)\n");
999 pDecOut->decIdx = buf.index;
1000 pDecOut->usedByte = buf.bytesused;
1001 pDecOut->outFrmReliable_0_100[DECODED_FRAME] = buf.reserved;
1002 pDecOut->timeStamp[DECODED_FRAME] =
1003 ((uint64_t) buf.timestamp.tv_sec) * 1000 + buf.timestamp.tv_usec / 1000;
1004 frameType = buf.flags;
1006 if (frameType & V4L2_BUF_FLAG_KEYFRAME)
1007 pDecOut->picType[DECODED_FRAME] = PIC_TYPE_I;
1008 else if (frameType & V4L2_BUF_FLAG_PFRAME)
1009 pDecOut->picType[DECODED_FRAME] = PIC_TYPE_P;
1010 else if (frameType & V4L2_BUF_FLAG_BFRAME)
1011 pDecOut->picType[DECODED_FRAME] = PIC_TYPE_B;
1013 pDecOut->picType[DECODED_FRAME] = PIC_TYPE_UNKNOWN;
1015 if (buf.field == V4L2_FIELD_NONE)
1016 pDecOut->interlace[DECODED_FRAME] = NONE_FIELD;
1017 else if (buf.field == V4L2_FIELD_SEQ_TB)
1018 pDecOut->interlace[DECODED_FRAME] = TOP_FIELD_FIRST;
1019 else if (buf.field == V4L2_FIELD_SEQ_BT)
1020 pDecOut->interlace[DECODED_FRAME] = BOTTOM_FIELD_FIRST;
1021 } else if (pDecIn->strmSize > 0) {
1022 pDecOut->usedByte = pDecIn->strmSize;
1025 /* Dequeue Output YUV Buffer -> Get Display Order Result */
1026 memset (&buf, 0, sizeof (buf));
1027 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1028 buf.m.planes = planes;
1029 buf.length = hDec->planesNum;
1030 buf.memory = V4L2_MEMORY_DMABUF;
1032 if (ioctl (hDec->fd, VIDIOC_DQBUF, &buf) != 0) {
1033 _E ("Fail, ioctl(): VIDIOC_DQBUF(Output)\n");
1037 pDecOut->dispIdx = buf.index;
1038 // pDecOut->dispInfo = &hDec->dispInfo; // TBD.
1040 if (pDecOut->dispIdx >= 0) {
1041 pDecOut->hImg = *hDec->hImage[buf.index];
1042 pDecOut->timeStamp[DISPLAY_FRAME] =
1043 ((uint64_t) buf.timestamp.tv_sec) * 1000 + buf.timestamp.tv_usec / 1000;
1044 pDecOut->outFrmReliable_0_100[DISPLAY_FRAME] = buf.reserved;
1045 frameType = buf.flags;
1047 if (frameType & V4L2_BUF_FLAG_KEYFRAME)
1048 pDecOut->picType[DISPLAY_FRAME] = PIC_TYPE_I;
1049 else if (frameType & V4L2_BUF_FLAG_PFRAME)
1050 pDecOut->picType[DISPLAY_FRAME] = PIC_TYPE_P;
1051 else if (frameType & V4L2_BUF_FLAG_BFRAME)
1052 pDecOut->picType[DISPLAY_FRAME] = PIC_TYPE_B;
1054 pDecOut->picType[DISPLAY_FRAME] = PIC_TYPE_UNKNOWN;
1056 if (buf.field == V4L2_FIELD_NONE)
1057 pDecOut->interlace[DISPLAY_FRAME] = NONE_FIELD;
1058 else if (buf.field == V4L2_FIELD_SEQ_TB)
1059 pDecOut->interlace[DISPLAY_FRAME] = TOP_FIELD_FIRST;
1060 else if (buf.field == V4L2_FIELD_SEQ_BT)
1061 pDecOut->interlace[DISPLAY_FRAME] = BOTTOM_FIELD_FIRST;
1066 if (pDecOut->dispIdx == -1)
1072 /*----------------------------------------------------------------------------*/
1074 NX_V4l2DecClrDspFlag (NX_V4L2DEC_HANDLE hDec, NX_VID_MEMORY_HANDLE hFrameBuf,
1077 struct v4l2_buffer buf;
1078 struct v4l2_plane planes[3];
1083 _E ("Fail, Invalid Handle.\n");
1087 if (iFrameIdx >= 0) {
1090 /* Search Buffer Index */
1091 if (hFrameBuf != NULL) {
1092 for (i = 0; i < hDec->numFrameBuffers; i++) {
1093 if (hFrameBuf == hDec->hImage[i]) {
1102 _E ("Fail, Invalid FrameBuffer or FrameIndex.\n");
1106 memset (&buf, 0, sizeof (buf));
1107 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1109 buf.m.planes = planes;
1110 buf.length = hDec->planesNum;
1111 buf.memory = V4L2_MEMORY_DMABUF;
1113 for (i = 0; i < hDec->planesNum; i++) {
1114 buf.m.planes[i].m.fd = hDec->hImage[index]->dmaFd[i];
1115 buf.m.planes[i].length = hDec->hImage[index]->size[i];
1118 /* Queue Output Buffer */
1119 if (ioctl (hDec->fd, VIDIOC_QBUF, &buf) != 0) {
1120 _E ("Fail, ioctl(): VIDIOC_QBUF.(Clear Display Index, index = %d)\n",
1128 /*----------------------------------------------------------------------------*/
1130 NX_V4l2DecFlush (NX_V4L2DEC_HANDLE hDec)
1132 enum v4l2_buf_type type;
1135 _E ("Fail, Invalid Handle.\n");
1139 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1140 if (ioctl (hDec->fd, VIDIOC_STREAMOFF, &type) != 0) {
1141 _E ("failed to ioctl: VIDIOC_STREAMOFF(Stream)\n");
1145 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1146 if (ioctl (hDec->fd, VIDIOC_STREAMOFF, &type) != 0) {
1147 _E ("failed to ioctl: VIDIOC_STREAMOFF(Image)\n");
1151 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1152 if (ioctl (hDec->fd, VIDIOC_STREAMON, &type) != 0) {
1153 _E ("Fail, ioctl(): VIDIOC_STREAMON. (Input)\n");
1157 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1158 if (ioctl (hDec->fd, VIDIOC_STREAMON, &type) != 0) {
1159 _E ("failed to ioctl: VIDIOC_STREAMON\n");
1164 struct v4l2_plane planes[3];
1165 struct v4l2_buffer buf;
1168 memset (&buf, 0, sizeof (buf));
1169 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1170 buf.m.planes = planes;
1171 buf.length = hDec->planesNum;
1172 buf.memory = V4L2_MEMORY_DMABUF;
1174 for (i = 0; i < hDec->numFrameBuffers; i++) {
1177 for (j = 0; j < (int32_t) hDec->planesNum; j++) {
1178 buf.m.planes[j].m.fd = hDec->hImage[i]->dmaFd[j];
1179 buf.m.planes[j].length = hDec->hImage[i]->size[j];
1182 if (ioctl (hDec->fd, VIDIOC_QBUF, &buf) != 0) {
1183 _E ("failed to ioctl: VIDIOC_QBUF(Output YUV - %d)\n", i);
1192 /* Optional Function */
1194 NX_DecGetFrameType (NX_V4L2DEC_HANDLE hDec, NX_V4L2DEC_IN * pDecIn,
1195 uint32_t codecType, int32_t * piFrameType)
1197 uint8_t *pbyStrm = pDecIn->strmBuf;
1198 uint32_t uPreFourByte = (uint32_t) - 1;
1199 int32_t iFrmType = PIC_TYPE_UNKNOWN;
1201 if ((pbyStrm == NULL) || (piFrameType == NULL))
1205 codecType = hDec->codecType;
1207 switch (codecType) {
1208 case V4L2_PIX_FMT_H264:
1210 if (pbyStrm >= (pDecIn->strmBuf + pDecIn->strmSize))
1213 uPreFourByte = (uPreFourByte << 8) + *pbyStrm++;
1215 if ((uPreFourByte == 0x00000001) || (uPreFourByte << 8 == 0x00000100)) {
1216 int32_t iNaluType = pbyStrm[0] & 0x1F;
1218 /* Slice start code */
1219 if (iNaluType == 5) {
1220 iFrmType = PIC_TYPE_IDR;
1222 } else if (iNaluType == 1) {
1223 VLD_STREAM stStrm = { 8, pbyStrm, pDecIn->strmSize };
1225 vld_get_uev (&stStrm); /* First_mb_in_slice */
1226 iFrmType = vld_get_uev (&stStrm); /* Slice type */
1228 if (iFrmType == 0 || iFrmType == 5)
1229 iFrmType = PIC_TYPE_P;
1230 else if (iFrmType == 1 || iFrmType == 6)
1231 iFrmType = PIC_TYPE_B;
1232 else if (iFrmType == 2 || iFrmType == 7)
1233 iFrmType = PIC_TYPE_I;
1240 case V4L2_PIX_FMT_MPEG2:
1242 if (pbyStrm >= (pDecIn->strmBuf + pDecIn->strmSize))
1245 uPreFourByte = (uPreFourByte << 8) + *pbyStrm++;
1247 /* Picture start code */
1248 if (uPreFourByte == 0x00000100) {
1249 VLD_STREAM stStrm = { 0, pbyStrm, pDecIn->strmSize };
1251 vld_flush_bits (&stStrm, 10); /* temporal_reference */
1252 iFrmType = vld_get_bits (&stStrm, 3); /* picture_coding_type */
1255 iFrmType = PIC_TYPE_I;
1256 else if (iFrmType == 2)
1257 iFrmType = PIC_TYPE_P;
1258 else if (iFrmType == 3)
1259 iFrmType = PIC_TYPE_B;
1265 case V4L2_PIX_FMT_WVC1:
1266 if (hDec == NULL || hDec->seqDataSize == 0)
1270 VLD_STREAM stStrm = { 0, pbyStrm, pDecIn->strmSize };
1272 if (hDec->iInterlace != NONE_FIELD) {
1274 if (vld_get_bits (&stStrm, 1) == 1)
1275 vld_flush_bits (&stStrm, 1);
1278 iFrmType = vld_get_bits (&stStrm, 1);
1279 if (iFrmType == 0) {
1280 iFrmType = PIC_TYPE_P;
1282 iFrmType = vld_get_bits (&stStrm, 1);
1283 if (iFrmType == 0) {
1284 iFrmType = PIC_TYPE_B;
1286 iFrmType = vld_get_bits (&stStrm, 1);
1287 if (iFrmType == 0) {
1288 iFrmType = PIC_TYPE_I;
1290 iFrmType = vld_get_bits (&stStrm, 1);
1292 iFrmType = PIC_TYPE_VC1_BI;
1294 iFrmType = PIC_TYPE_SKIP;
1301 case V4L2_PIX_FMT_WMV9:
1302 if (hDec == NULL || hDec->seqDataSize == 0)
1307 int32_t fInterPFlag;
1309 VLD_STREAM stStrm = { 24, hDec->pSeqData, hDec->seqDataSize };
1311 /* Parse Sequece Header */
1312 rangeRed = vld_get_bits (&stStrm, 1);
1313 maxBframes = vld_get_bits (&stStrm, 3);
1314 vld_flush_bits (&stStrm, 2);
1315 fInterPFlag = vld_get_bits (&stStrm, 1);
1317 /* Parse Frame Header */
1318 stStrm.dwUsedBits = 0;
1319 stStrm.pbyStart = pbyStrm;
1320 stStrm.dwPktSize = pDecIn->strmSize;
1322 if (fInterPFlag == 1)
1323 vld_flush_bits (&stStrm, 1); /* INTERPFRM */
1325 vld_flush_bits (&stStrm, 2); /* FRMCNT */
1328 vld_flush_bits (&stStrm, 1); /* RANGEREDFRM */
1330 iFrmType = vld_get_bits (&stStrm, 1);
1331 if (maxBframes > 0) {
1332 if (iFrmType == 1) {
1333 iFrmType = PIC_TYPE_P;
1335 iFrmType = vld_get_bits (&stStrm, 1);
1337 iFrmType = PIC_TYPE_I;
1338 else if (iFrmType == 0)
1339 iFrmType = PIC_TYPE_B; /* or BI */
1343 iFrmType = PIC_TYPE_I;
1344 else if (iFrmType == 1)
1345 iFrmType = PIC_TYPE_P;
1355 *piFrameType = iFrmType;