Zeta--S3 Linux抓取一帧YUV图像后使用硬件编码器编码成H.264

时间:2023-01-29 21:43:26
 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <asm/types.h>
#include <linux/videodev2.h>
#include <pthread.h>
#include <memoryAdapter.h>
#include <vencoder.h> static VideoEncoder *gVideoEnc;
static VencBaseConfig baseConfig;
static int gWidth = ;
static int gHeight = ; #define ALIGN_4K(x) (((x) + (4095)) & ~(4095))
#define ALIGN_1K(x) (((x) + (1023)) & ~(1023))
#define ALIGN_32B(x) (((x) + (31)) & ~(31))
#define ALIGN_16B(x) (((x) + (15)) & ~(15))
#define ALIGN_8B(x) (((x) + (7)) & ~(7)) #define REQ_COUNT 10 struct buffer
{
void *start;
size_t length;
char *addrVirY;
char *addrVirC;
}; static int fd = -;
struct buffer *buffers = NULL; struct v4l2_capability cap;
struct v4l2_format fmt;
struct v4l2_buffer buf[REQ_COUNT];
struct v4l2_requestbuffers req;
struct v4l2_buffer tmp_buf;
enum v4l2_buf_type type; int H264EncodeOneFrame(unsigned char *AddrVirY, unsigned char *AddrVirC, FILE *fpH264)
{
int result = ;
VencInputBuffer inputBuffer;
VencOutputBuffer outputBuffer;
int value;
unsigned int head_num = ;
VencHeaderData sps_pps_data; VencH264Param h264Param;
//* h264 param
h264Param.bEntropyCodingCABAC = ;
h264Param.nBitrate = * * ;
h264Param.nFramerate = ;
h264Param.nCodingMode = VENC_FRAME_CODING;
//h264Param.nCodingMode = VENC_FIELD_CODING;
h264Param.nMaxKeyInterval = ;
h264Param.sProfileLevel.nProfile = VENC_H264ProfileMain;
h264Param.sProfileLevel.nLevel = VENC_H264Level31;
h264Param.sQPRange.nMinqp = ;
h264Param.sQPRange.nMaxqp = ;
memset(&baseConfig, , sizeof(VencBaseConfig)); if (baseConfig.memops == NULL)
{
baseConfig.memops = MemAdapterGetOpsS();
if (baseConfig.memops == NULL)
{
printf("MemAdapterGetOpsS failed\n"); return -;
}
CdcMemOpen(baseConfig.memops);
} baseConfig.nInputWidth = gWidth;
baseConfig.nInputHeight = gHeight;
baseConfig.nStride = gWidth;
baseConfig.nDstWidth = gWidth;
baseConfig.nDstHeight = gHeight;
baseConfig.eInputFormat = VENC_PIXEL_YVU420SP; if (gVideoEnc == NULL)
{
printf("get SPS PPS\n");
gVideoEnc = VideoEncCreate((VENC_CODEC_TYPE)VENC_CODEC_H264);
VideoEncSetParameter(gVideoEnc, VENC_IndexParamH264Param, &h264Param);
value = ;
VideoEncSetParameter(gVideoEnc, VENC_IndexParamIfilter, &value);
value = ; //degree
VideoEncSetParameter(gVideoEnc, VENC_IndexParamRotation, &value);
value = ;
VideoEncSetParameter(gVideoEnc, VENC_IndexParamSetPSkip, &value);
VideoEncInit(gVideoEnc, &baseConfig);
}
VideoEncGetParameter(gVideoEnc, VENC_IndexParamH264SPSPPS, &sps_pps_data); fwrite(sps_pps_data.pBuffer, , sps_pps_data.nLength, fpH264); VencAllocateBufferParam bufferParam;
memset(&bufferParam, , sizeof(VencAllocateBufferParam));
memset(&inputBuffer, , sizeof(VencInputBuffer)); bufferParam.nSizeY = baseConfig.nInputWidth * baseConfig.nInputHeight;
bufferParam.nSizeC = baseConfig.nInputWidth * baseConfig.nInputHeight / ;
bufferParam.nBufferNum = ;
AllocInputBuffer(gVideoEnc, &bufferParam); GetOneAllocInputBuffer(gVideoEnc, &inputBuffer); memcpy(inputBuffer.pAddrVirY, AddrVirY, baseConfig.nInputWidth * baseConfig.nInputHeight);
memcpy(inputBuffer.pAddrVirC, AddrVirC, baseConfig.nInputWidth * baseConfig.nInputHeight / );
inputBuffer.bEnableCorp = ;
inputBuffer.sCropInfo.nLeft = ;
inputBuffer.sCropInfo.nTop = ;
inputBuffer.sCropInfo.nWidth = ;
inputBuffer.sCropInfo.nHeight = ;
FlushCacheAllocInputBuffer(gVideoEnc, &inputBuffer);
AddOneInputBuffer(gVideoEnc, &inputBuffer);
if (VENC_RESULT_OK != VideoEncodeOneFrame(gVideoEnc))
{
printf("VideoEncodeOneFrame failed.\n");
return -;
}
AlreadyUsedInputBuffer(gVideoEnc, &inputBuffer);
ReturnOneAllocInputBuffer(gVideoEnc, &inputBuffer); GetOneBitstreamFrame(gVideoEnc, &outputBuffer);
if (outputBuffer.nSize0 > )
{
printf("write pData0\n");
fwrite(outputBuffer.pData0, , outputBuffer.nSize0, fpH264);
}
if (outputBuffer.nSize1 > )
{
printf("write pData1\n");
fwrite(outputBuffer.pData1, , outputBuffer.nSize1, fpH264);
}
// outputBuffer.pData0;
// outputBuffer.nSize0;
// outputBuffer.pData1;
// outputBuffer.nSize1; FreeOneBitStreamFrame(gVideoEnc, &outputBuffer); if (baseConfig.memops != NULL)
{
CdcMemClose(baseConfig.memops);
baseConfig.memops = NULL;
}
VideoEncDestroy(gVideoEnc);
gVideoEnc = NULL; return ;
} int main(int argc, char **argv)
{
int iCounterCamera = ;
int iCounter100frame = ;
struct v4l2_fmtdesc fmtd;
int ret = ;
int index = ;
struct v4l2_format fmt2; if ((fd = open("/dev/video0", O_RDWR | O_NONBLOCK, )) < )
{
printf("open video0 failed.\n");
return -;
} memset(&fmtd, , sizeof(fmtd));
fmtd.index = ;
fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; while ((ret = ioctl(fd, VIDIOC_ENUM_FMT, &fmtd)) == )
{
fmtd.index++;
}
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < )
{
printf("Error:VIDIOC_QUERYCAP\n");
return -;
} if (ioctl(fd, VIDIOC_S_INPUT, &index) < )
{
printf("Error:VIDIOC_S_INPUT\n");
return -;
} fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(fd, VIDIOC_G_FMT, &fmt2);
printf("VIDIOC_G_FMT ret=%d \n", ret); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = gWidth;
fmt.fmt.pix.height = gHeight; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_NV21;
if (ioctl(fd, VIDIOC_S_FMT, &fmt) < )
{
printf("Error:VIDIOC_S_FMT\n");
return -;
} req.count = REQ_COUNT;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd, VIDIOC_REQBUFS, &req) < )
{
printf("Error:VIDIOC_REQBUFS\n");
return -;
} buffers = calloc(req.count, sizeof(*buffers)); for (int i = ; i < req.count; i++)
{
buf[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf[i].memory = V4L2_MEMORY_MMAP;
buf[i].index = i;
if (ioctl(fd, VIDIOC_QUERYBUF, buf + i) < )
{
printf("Error:VIDIOC_QUERYBUF\n");
return -;
} buffers[i].length = buf[i].length;
buffers[i].start = mmap(NULL, buf[i].length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf[i].m.offset); buf[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf[i].memory = V4L2_MEMORY_MMAP;
buf[i].index = i; if (ioctl(fd, VIDIOC_QBUF, buf + i) < )
{
printf("Error: VIDIOC_QBUF\n");
return -;
} buffers[i].addrVirY = buffers[i].start;
buffers[i].addrVirC = buffers[i].addrVirY + ALIGN_16B(gWidth) * ALIGN_16B(gHeight);
} type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_STREAMON, &type) < )
{
printf("Error: VIDIOC_STREAMON\n");
return -;
} FILE *fpYUV = NULL;
FILE *fpH264 = NULL;
char yuv_path[];
char h264_path[];
for (int i = ; i < req.count; i++)
{
struct v4l2_buffer buf; /*帧出列*/
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
ioctl(fd, VIDIOC_DQBUF, &buf); memset(yuv_path, , );
memset(h264_path, , );
sprintf(yuv_path, "/mnt/extsd/src%04d.yuv", buf.index);
sprintf(h264_path, "/mnt/extsd/dst%04d.h264", buf.index);
fpYUV = fopen(yuv_path, "w");
fwrite(buffers[buf.index].addrVirY, , gWidth * gHeight, fpYUV);
fwrite(buffers[buf.index].addrVirC, , gWidth * gHeight / , fpYUV);
fpH264 = fopen(h264_path, "w");
H264EncodeOneFrame(buffers[buf.index].addrVirY, buffers[buf.index].addrVirC, fpH264);
fclose(fpYUV);
fpYUV = NULL;
fclose(fpH264);
fpH264 = NULL; /*buf入列*/
ioctl(fd, VIDIOC_QBUF, &buf);
} if (ioctl(fd, VIDIOC_STREAMOFF, &type) < )
{
printf("Error:VIDIOC_STREAMOFF\n"); // return 0;
return;
} for (int i = ; i < req.count; i++)
{
munmap(buffers[i].start, buf[i].length);
} close(fd); return ;
}