Zeta--S3 Linux抓取一帧YUV图像后使用硬件编码器编码成H.264
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <getopt.h> 5 #include <fcntl.h> 6 #include <unistd.h> 7 #include <errno.h> 8 #include <malloc.h> 9 #include <sys/stat.h> 10 #include <sys/types.h> 11 #include <sys/time.h> 12 #include <sys/mman.h> 13 #include <sys/ioctl.h> 14 #include <asm/types.h> 15 #include <linux/videodev2.h> 16 #include <pthread.h> 17 #include <memoryAdapter.h> 18 #include <vencoder.h> 19 20 static VideoEncoder *gVideoEnc; 21 static VencBaseConfig baseConfig; 22 static int gWidth = 1920; 23 static int gHeight = 1080; 24 25 26 #define ALIGN_4K(x) (((x) + (4095)) & ~(4095)) 27 #define ALIGN_1K(x) (((x) + (1023)) & ~(1023)) 28 #define ALIGN_32B(x) (((x) + (31)) & ~(31)) 29 #define ALIGN_16B(x) (((x) + (15)) & ~(15)) 30 #define ALIGN_8B(x) (((x) + (7)) & ~(7)) 31 32 #define REQ_COUNT 10 33 34 struct buffer 35 { 36 void *start; 37 size_t length; 38 char *addrVirY; 39 char *addrVirC; 40 }; 41 42 static int fd = -1; 43 struct buffer *buffers = NULL; 44 45 struct v4l2_capability cap; 46 struct v4l2_format fmt; 47 struct v4l2_buffer buf[REQ_COUNT]; 48 struct v4l2_requestbuffers req; 49 struct v4l2_buffer tmp_buf; 50 enum v4l2_buf_type type; 51 52 int H264EncodeOneFrame(unsigned char *AddrVirY, unsigned char *AddrVirC, FILE *fpH264) 53 { 54 int result = 0; 55 VencInputBuffer inputBuffer; 56 VencOutputBuffer outputBuffer; 57 int value; 58 unsigned int head_num = 0; 59 VencHeaderData sps_pps_data; 60 61 VencH264Param h264Param; 62 //* h264 param 63 h264Param.bEntropyCodingCABAC = 1; 64 h264Param.nBitrate = 6 * 1024 * 1024; 65 h264Param.nFramerate = 30; 66 h264Param.nCodingMode = VENC_FRAME_CODING; 67 //h264Param.nCodingMode = VENC_FIELD_CODING; 68 h264Param.nMaxKeyInterval = 30; 69 h264Param.sProfileLevel.nProfile = VENC_H264ProfileMain; 70 h264Param.sProfileLevel.nLevel = VENC_H264Level31; 71 h264Param.sQPRange.nMinqp = 10; 72 h264Param.sQPRange.nMaxqp = 40; 73 memset(&baseConfig, 0, sizeof(VencBaseConfig)); 74 75 if (baseConfig.memops == NULL) 76 { 77 baseConfig.memops = MemAdapterGetOpsS(); 78 if (baseConfig.memops == NULL) 79 { 80 printf("MemAdapterGetOpsS failed\n"); 81 82 return -1; 83 } 84 CdcMemOpen(baseConfig.memops); 85 } 86 87 baseConfig.nInputWidth = gWidth; 88 baseConfig.nInputHeight = gHeight; 89 baseConfig.nStride = gWidth; 90 baseConfig.nDstWidth = gWidth; 91 baseConfig.nDstHeight = gHeight; 92 baseConfig.eInputFormat = VENC_PIXEL_YVU420SP; 93 94 if (gVideoEnc == NULL) 95 { 96 printf("get SPS PPS\n"); 97 gVideoEnc = VideoEncCreate((VENC_CODEC_TYPE)VENC_CODEC_H264); 98 VideoEncSetParameter(gVideoEnc, VENC_IndexParamH264Param, &h264Param); 99 value = 0; 100 VideoEncSetParameter(gVideoEnc, VENC_IndexParamIfilter, &value); 101 value = 0; //degree 102 VideoEncSetParameter(gVideoEnc, VENC_IndexParamRotation, &value); 103 value = 0; 104 VideoEncSetParameter(gVideoEnc, VENC_IndexParamSetPSkip, &value); 105 VideoEncInit(gVideoEnc, &baseConfig); 106 } 107 VideoEncGetParameter(gVideoEnc, VENC_IndexParamH264SPSPPS, &sps_pps_data); 108 109 fwrite(sps_pps_data.pBuffer, 1, sps_pps_data.nLength, fpH264); 110 111 VencAllocateBufferParam bufferParam; 112 memset(&bufferParam, 0, sizeof(VencAllocateBufferParam)); 113 memset(&inputBuffer, 0, sizeof(VencInputBuffer)); 114 115 bufferParam.nSizeY = baseConfig.nInputWidth * baseConfig.nInputHeight; 116 bufferParam.nSizeC = baseConfig.nInputWidth * baseConfig.nInputHeight / 2; 117 bufferParam.nBufferNum = 1; 118 AllocInputBuffer(gVideoEnc, &bufferParam); 119 120 GetOneAllocInputBuffer(gVideoEnc, &inputBuffer); 121 122 memcpy(inputBuffer.pAddrVirY, AddrVirY, baseConfig.nInputWidth * baseConfig.nInputHeight); 123 memcpy(inputBuffer.pAddrVirC, AddrVirC, baseConfig.nInputWidth * baseConfig.nInputHeight / 2); 124 inputBuffer.bEnableCorp = 0; 125 inputBuffer.sCropInfo.nLeft = 240; 126 inputBuffer.sCropInfo.nTop = 240; 127 inputBuffer.sCropInfo.nWidth = 240; 128 inputBuffer.sCropInfo.nHeight = 240; 129 FlushCacheAllocInputBuffer(gVideoEnc, &inputBuffer); 130 AddOneInputBuffer(gVideoEnc, &inputBuffer); 131 if (VENC_RESULT_OK != VideoEncodeOneFrame(gVideoEnc)) 132 { 133 printf("VideoEncodeOneFrame failed.\n"); 134 return -1; 135 } 136 AlreadyUsedInputBuffer(gVideoEnc, &inputBuffer); 137 ReturnOneAllocInputBuffer(gVideoEnc, &inputBuffer); 138 139 GetOneBitstreamFrame(gVideoEnc, &outputBuffer); 140 if (outputBuffer.nSize0 > 0) 141 { 142 printf("write pData0\n"); 143 fwrite(outputBuffer.pData0, 1, outputBuffer.nSize0, fpH264); 144 } 145 if (outputBuffer.nSize1 > 0) 146 { 147 printf("write pData1\n"); 148 fwrite(outputBuffer.pData1, 1, outputBuffer.nSize1, fpH264); 149 } 150 // outputBuffer.pData0; 151 // outputBuffer.nSize0; 152 // outputBuffer.pData1; 153 // outputBuffer.nSize1; 154 155 FreeOneBitStreamFrame(gVideoEnc, &outputBuffer); 156 157 if (baseConfig.memops != NULL) 158 { 159 CdcMemClose(baseConfig.memops); 160 baseConfig.memops = NULL; 161 } 162 VideoEncDestroy(gVideoEnc); 163 gVideoEnc = NULL; 164 165 return 0; 166 } 167 168 169 int main(int argc, char **argv) 170 { 171 int iCounterCamera = 0; 172 int iCounter100frame = 0; 173 struct v4l2_fmtdesc fmtd; 174 int ret = 0; 175 int index = 0; 176 struct v4l2_format fmt2; 177 178 if ((fd = open("/dev/video0", O_RDWR | O_NONBLOCK, 0)) < 0) 179 { 180 printf("open video0 failed.\n"); 181 return -1; 182 } 183 184 memset(&fmtd, 0, sizeof(fmtd)); 185 fmtd.index = 0; 186 fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 187 188 while ((ret = ioctl(fd, VIDIOC_ENUM_FMT, &fmtd)) == 0) 189 { 190 fmtd.index++; 191 } 192 if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) 193 { 194 printf("Error:VIDIOC_QUERYCAP\n"); 195 return -1; 196 } 197 198 if (ioctl(fd, VIDIOC_S_INPUT, &index) < 0) 199 { 200 printf("Error:VIDIOC_S_INPUT\n"); 201 return -1; 202 } 203 204 fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 205 ret = ioctl(fd, VIDIOC_G_FMT, &fmt2); 206 printf("VIDIOC_G_FMT ret=%d \n", ret); 207 208 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 209 fmt.fmt.pix.width = gWidth; 210 fmt.fmt.pix.height = gHeight; 211 212 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_NV21; 213 if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) 214 { 215 printf("Error:VIDIOC_S_FMT\n"); 216 return -1; 217 } 218 219 req.count = REQ_COUNT; 220 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 221 req.memory = V4L2_MEMORY_MMAP; 222 if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) 223 { 224 printf("Error:VIDIOC_REQBUFS\n"); 225 return -1; 226 } 227 228 buffers = calloc(req.count, sizeof(*buffers)); 229 230 for (int i = 0; i < req.count; i++) 231 { 232 buf[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 233 buf[i].memory = V4L2_MEMORY_MMAP; 234 buf[i].index = i; 235 if (ioctl(fd, VIDIOC_QUERYBUF, buf + i) < 0) 236 { 237 printf("Error:VIDIOC_QUERYBUF\n"); 238 return -1; 239 } 240 241 buffers[i].length = buf[i].length; 242 buffers[i].start = mmap(NULL, buf[i].length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf[i].m.offset); 243 244 buf[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 245 buf[i].memory = V4L2_MEMORY_MMAP; 246 buf[i].index = i; 247 248 if (ioctl(fd, VIDIOC_QBUF, buf + i) < 0) 249 { 250 printf("Error: VIDIOC_QBUF\n"); 251 return -1; 252 } 253 254 buffers[i].addrVirY = buffers[i].start; 255 buffers[i].addrVirC = buffers[i].addrVirY + ALIGN_16B(gWidth) * ALIGN_16B(gHeight); 256 } 257 258 type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 259 if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) 260 { 261 printf("Error: VIDIOC_STREAMON\n"); 262 return -1; 263 } 264 265 FILE *fpYUV = NULL; 266 FILE *fpH264 = NULL; 267 char yuv_path[128]; 268 char h264_path[128]; 269 for (int i = 0; i < req.count; i++) 270 { 271 struct v4l2_buffer buf; 272 273 /*帧出列*/ 274 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 275 buf.memory = V4L2_MEMORY_MMAP; 276 buf.index = i; 277 ioctl(fd, VIDIOC_DQBUF, &buf); 278 279 memset(yuv_path, 0, 128); 280 memset(h264_path, 0, 128); 281 sprintf(yuv_path, "/mnt/extsd/src%04d.yuv", buf.index); 282 sprintf(h264_path, "/mnt/extsd/dst%04d.h264", buf.index); 283 fpYUV = fopen(yuv_path, "w"); 284 fwrite(buffers[buf.index].addrVirY, 1, gWidth * gHeight, fpYUV); 285 fwrite(buffers[buf.index].addrVirC, 1, gWidth * gHeight / 2, fpYUV); 286 fpH264 = fopen(h264_path, "w"); 287 H264EncodeOneFrame(buffers[buf.index].addrVirY, buffers[buf.index].addrVirC, fpH264); 288 fclose(fpYUV); 289 fpYUV = NULL; 290 fclose(fpH264); 291 fpH264 = NULL; 292 293 /*buf入列*/ 294 ioctl(fd, VIDIOC_QBUF, &buf); 295 } 296 297 if (ioctl(fd, VIDIOC_STREAMOFF, &type) < 0) 298 { 299 printf("Error:VIDIOC_STREAMOFF\n"); 300 301 // return 0; 302 return; 303 } 304 305 for (int i = 0; i < req.count; i++) 306 { 307 munmap(buffers[i].start, buf[i].length); 308 } 309 310 close(fd); 311 312 return 0; 313 }
你无法叫醒一个不回你消息的人,但是红包能。