123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (C) 2021 StarFive Technology Co., Ltd.
- */
- #include <stdio.h>
- #include <unistd.h>
- #include <signal.h>
- #include <getopt.h>
- #include <fcntl.h>
- #include "libavformat/avformat.h"
- #include "libavcodec/avcodec.h"
- #include <libv4l2.h>
- #include <poll.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/ioctl.h>
- #include <sys/msg.h>
- #include <sys/mman.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <stdbool.h>
- #include <sys/stat.h>
- #include <time.h>
- #include <asm/types.h>
- #include <linux/videodev2.h>
- #include <string.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <malloc.h>
- #define MAX_BUF_CNT 10
- #define BUFCOUNT 5
- #define MAX_PLANES 3
- #define MAX_VIDEO_CNT 24
- #define VPU_DEC_DRV_NAME "wave5-dec"
- #define CLEAR(x) memset (&(x), 0, sizeof (x))
- #define PCLEAR(x) memset ((x), 0, sizeof (*x))
- //typedef enum __bool { false = 0, true = 1, } bool;
- typedef struct v4l2_buffer v4l2_buffer;
- typedef enum IOMethod {
- IO_METHOD_MMAP,
- IO_METHOD_USERPTR,
- IO_METHOD_DMABUF,
- IO_METHOD_READ
- } IOMethod;
- typedef struct buffer {
- void* start[MAX_PLANES];
- size_t length[MAX_PLANES];
- int dmabuf_fd[MAX_PLANES];
- int index;
- }buffer;
- typedef struct DecodeTestContext
- {
- int fd;
- IOMethod io_mthd; // IO_METHOD_MMAP
- enum v4l2_memory mem_type;
- char sOutputFilePath[256];
- char sInputFilePath[256];
- char sOutputFormat[64];
- uint32_t ScaleWidth;
- uint32_t ScaleHeight;
- uint32_t StreamFormat;
- uint32_t format;
- uint32_t n_inputbuffers;
- uint32_t n_outputbuffers;
- uint32_t inputBufSize;
- uint32_t outputBufSize;
- uint32_t width; // = 1920;
- uint32_t height; // = 1080;
- v4l2_buffer InputV4L2BufArray[MAX_BUF_CNT];
- v4l2_buffer OutputV4L2BufArray[MAX_BUF_CNT];
- buffer InputBufArray[MAX_BUF_CNT];
- buffer OutputBufArray[MAX_BUF_CNT];
- AVFormatContext *avContext;
- int32_t video_stream_idx;
- } DecodeTestContext;
- DecodeTestContext *decodeTestContext;
- struct v4l2_plane *gInput_v4l2_plane;
- struct v4l2_plane *gOutput_v4l2_plane;
- static char devPath[16];
- static int32_t FillInputBuffer(DecodeTestContext *decodeTestContext, struct v4l2_buffer *buf, int32_t pIndex);
- static bool justQuit = false;
- static bool bitsteamEnd = false;
- static bool testFPS =false;
- static FILE *fb = NULL;
- static int xioctl(int fd, int request, void* argp)
- {
- int r;
- // TODO: the orign is v4l2_ioctl()
- do r = ioctl(fd, request, argp);
- while (-1 == r && EINTR == errno);
- return r;
- }
- static void convert_v4l2_mem_type(int iomthd, enum v4l2_memory *mem_type)
- {
- if (iomthd < IO_METHOD_MMAP || iomthd > IO_METHOD_READ) {
- printf("iomthd %d out of range\n", iomthd);
- return;
- }
- switch (iomthd) {
- case IO_METHOD_MMAP:
- *mem_type = V4L2_MEMORY_MMAP;
- break;
- case IO_METHOD_USERPTR:
- *mem_type = V4L2_MEMORY_USERPTR;
- break;
- case IO_METHOD_DMABUF:
- *mem_type = V4L2_MEMORY_DMABUF;
- break;
- case IO_METHOD_READ:
- *mem_type = 0; // not use memory machanism
- break;
- default:
- *mem_type = 0; // not use memory machanism
- break;
- }
- }
- static void help()
- {
- printf("v4l2_dec_test - v4l2 hardware decode unit test case\r\n\r\n");
- printf("Usage:\r\n\r\n");
- printf("./v4l2_dec_test -i <input file> input file\r\n");
- printf(" -o <output file> output file\r\n");
- printf(" -f <format> i420/nv12/nv21\r\n");
- printf(" --scaleW=<width> (optional) scale width down. ceil32(width/8) <= scaledW <= width\r\n");
- printf(" --scaleH=<heitht> (optional) scale height down, ceil8(height/8) <= scaledH <= height\r\n\r\n");
- printf("./v4l2_dec_test --help: show this message\r\n");
- }
- static void signal_handle(int sig)
- {
- printf("[%s,%d]: receive sig=%d \n", __FUNCTION__, __LINE__, sig);
- justQuit = true;
- }
- static int32_t FillInputBuffer(DecodeTestContext *decodeTestContext, struct v4l2_buffer *buf, int32_t pIndex)
- {
- AVFormatContext *avFormatContext = decodeTestContext->avContext;
- AVPacket *avpacket;
- int32_t error = 0;
- avpacket = av_packet_alloc();
- while (error >= 0)
- {
- error = av_read_frame(avFormatContext, avpacket);
- if (avpacket->stream_index == decodeTestContext->video_stream_idx)
- break;
- printf("get audio frame\n");
- }
- if (error < 0)
- {
- if (error == AVERROR_EOF || avFormatContext->pb->eof_reached)
- {
- printf("get stream eos\n");
- buf->m.planes[pIndex].bytesused = 0;
- return 0;
- }
- else
- {
- printf("%s:%d failed to av_read_frame, error: %s\n",
- __FUNCTION__, __LINE__, av_err2str(error));
- buf->m.planes[pIndex].bytesused = 0;
- return 0;
- }
- }
- if (decodeTestContext->InputBufArray[buf->index].length[pIndex] >= avpacket->size){
- memcpy(decodeTestContext->InputBufArray[buf->index].start[pIndex], avpacket->data, avpacket->size);
- buf->m.planes[pIndex].bytesused = avpacket->size;
- return avpacket->size;
- }else{
- printf("buff size too small %ld<%d\n",decodeTestContext->InputBufArray[buf->index].length[pIndex], avpacket->size);
- buf->m.planes[pIndex].bytesused = 0;
- return 0;
- }
- }
- static void mainloop()
- {
- int r, i, j, fps, dec_cnt = 0;
- uint64_t diff_time;
- struct pollfd* fds = NULL;
- struct v4l2_event event;
- struct v4l2_format fmt;
- struct v4l2_requestbuffers req;
- struct v4l2_buffer buf;
- struct v4l2_plane planes[MAX_PLANES];
- struct timeval tv_old, tv;
- enum v4l2_buf_type type;
- fds = (struct pollfd*)malloc(sizeof(struct pollfd));
- PCLEAR(fds);
- fds->fd = decodeTestContext->fd;
- fds->events = POLLIN | POLLOUT | POLLPRI;
- while (true){
- if (justQuit)
- break;
- r = poll(fds, 1, 3000);
- if (-1 == r) {
- if (EINTR == errno) {
- continue;
- }
- printf("error in poll %d", errno);
- break;
- }
- if (0 == r) {
- printf("poll timeout, %d\n", errno);
- break;
- }
- if (fds->revents & POLLPRI) {
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_DQEVENT, &event)) {
- printf("get event fail\n");
- break;
- }
- printf("get event %d\n",event.type);
- if (event.type == V4L2_EVENT_SOURCE_CHANGE &&
- event.u.src_change.changes == V4L2_EVENT_SRC_CH_RESOLUTION){
- printf("request dist buffer\n");
- CLEAR(req);
- req.count = BUFCOUNT;
- req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- req.memory = V4L2_MEMORY_MMAP;
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_REQBUFS, &req)) {
- printf("%s request buffer fail %d\n", devPath, errno);
- break;
- }
- decodeTestContext->n_outputbuffers = req.count;
- printf("get dist q format\n");
- CLEAR(fmt);
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
- if (-1 == ioctl(decodeTestContext->fd, VIDIOC_G_FMT, &fmt)) {
- printf("VIDIOC_G_FMT fail\n");
- break;
- }
- printf("VIDIOC_G_FMT: type=%d, Fourcc format=%c%c%c%c\n",
- fmt.type, fmt.fmt.pix_mp.pixelformat & 0xff,
- (fmt.fmt.pix_mp.pixelformat >> 8) &0xff,
- (fmt.fmt.pix_mp.pixelformat >> 16) &0xff,
- (fmt.fmt.pix_mp.pixelformat >> 24) &0xff);
- printf(" \t width=%d, height=%d, field=%d, bytesperline=%d, sizeimage=%d\n",
- fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.field,
- fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
- if (fmt.fmt.pix_mp.pixelformat != decodeTestContext->format) {
- printf("v4l2 didn't accept format %d. Can't proceed.\n", decodeTestContext->format);
- break;
- }
- /* Note VIDIOC_S_FMT may change width and height. */
- if (decodeTestContext->width != fmt.fmt.pix_mp.width) {
- decodeTestContext->width = fmt.fmt.pix_mp.width;
- printf("Correct image width set to %i by device %s.\n", decodeTestContext->width, devPath);
- }
- if (decodeTestContext->height != fmt.fmt.pix_mp.height) {
- decodeTestContext->height = fmt.fmt.pix_mp.height;
- printf("Correct image height set to %i by device %s.\n", decodeTestContext->height, devPath);
- }
- for (i = 0; i < decodeTestContext->n_outputbuffers; i++) {
- decodeTestContext->OutputV4L2BufArray[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- decodeTestContext->OutputV4L2BufArray[i].memory = V4L2_MEMORY_MMAP;
- decodeTestContext->OutputV4L2BufArray[i].index = i;
- // VIDIOC_PREPARE_BUF
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_PREPARE_BUF, &decodeTestContext->OutputV4L2BufArray[i]))
- {
- printf("VIDIOC_PREPARE_BUF fail\n");
- break;
- }
- // VIDIOC_PREPARE_BUF end
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_QUERYBUF, &decodeTestContext->OutputV4L2BufArray[i]))
- {
- printf("VIDIOC_QUERYBUF fail\n");
- break;
- }
- printf("src buffer %d type %d method %d n_plane %d\n",i ,decodeTestContext->OutputV4L2BufArray[i].type,
- decodeTestContext->OutputV4L2BufArray[i].memory, decodeTestContext->OutputV4L2BufArray[i].length);
- for (j = 0; j < decodeTestContext->OutputV4L2BufArray[i].length; j++){
- printf(" plane %d length 0x%x offset 0x%x\n", j,
- decodeTestContext->OutputV4L2BufArray[i].m.planes[j].length, decodeTestContext->OutputV4L2BufArray[i].m.planes[j].m.mem_offset);
- decodeTestContext->OutputBufArray[i].length[j] = decodeTestContext->OutputV4L2BufArray[i].m.planes[j].length;
- decodeTestContext->OutputBufArray[i].start[j] = v4l2_mmap(NULL, /* start anywhere */
- decodeTestContext->OutputV4L2BufArray[i].m.planes[j].length, PROT_READ | PROT_WRITE, /* required */
- MAP_SHARED, /* recommended */
- decodeTestContext->fd, decodeTestContext->OutputV4L2BufArray[i].m.planes[j].m.mem_offset);
- if (MAP_FAILED == decodeTestContext->OutputBufArray[i].start[j]) {
- printf("map fail %d err %d\n",i, errno);
- break;
- }
- }
- }
- for (i = 0; i < decodeTestContext->n_outputbuffers; i++){
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_QBUF, &decodeTestContext->OutputV4L2BufArray[i])) {
- printf("VIDIOC_QBUF fail\n");
- break;
- }
- }
- printf("start dst stream\n");
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_STREAMON, &type)) {
- printf("start dst stream fail\n");
- break;
- }
- }else if (event.type == V4L2_EVENT_EOS){
- printf("finished, end\n");
- break;
- }
- }
- if (fds->revents & POLLIN) {
- CLEAR(buf);
- memset(planes, 0, sizeof(struct v4l2_plane) * MAX_PLANES);
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- buf.memory = decodeTestContext->mem_type;
- buf.length = MAX_PLANES;
- buf.m.planes = planes;
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_DQBUF, &buf)) {
- switch (errno) {
- case EAGAIN:
- continue;
- case EIO:
- /* Could ignore EIO, see spec. */
- /* fall through */
- default:
- printf("pollin VIDIOC_DQBUF fail\n");
- }
- }
- if (buf.index > decodeTestContext->n_outputbuffers)
- {
- printf("error capture index %d\n",buf.index);
- break;
- }
- if (testFPS)
- {
- if (dec_cnt == 0) {
- gettimeofday(&tv_old, NULL);
- }
- if (dec_cnt++ >= 50) {
- gettimeofday(&tv, NULL);
- diff_time = (tv.tv_sec - tv_old.tv_sec) * 1000 + (tv.tv_usec - tv_old.tv_usec) / 1000;
- fps = 1000 * (dec_cnt - 1) / diff_time;
- dec_cnt = 0;
- printf("Decoding fps: %d \r\n", fps);
- }
- }
- else
- {
- for (i = 0; i < buf.length; i++){
- fwrite(decodeTestContext->OutputBufArray[buf.index].start[i], 1, buf.m.planes[i].bytesused, fb);
- }
- }
-
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_QBUF, &buf)) {
- printf("VIDIOC_QBUF fail\n");
- break;
- }
- if (buf.flags & V4L2_BUF_FLAG_LAST){
- printf("get last buffer\n");
- justQuit = true;
- }
- }
- if (fds->revents & POLLOUT) {
- CLEAR(buf);
- memset(planes, 0, sizeof(struct v4l2_plane) * MAX_PLANES);
- buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- buf.memory = decodeTestContext->mem_type;
- buf.length = MAX_PLANES;
- buf.m.planes = planes;
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_DQBUF, &buf)) {
- switch (errno) {
- case EAGAIN:
- continue;
- case EIO:
- /* Could ignore EIO, see spec. */
- /* fall through */
- default:
- printf("pollout VIDIOC_DQBUF fail %d\n", errno);
- }
- }
- if (buf.index > decodeTestContext->n_inputbuffers)
- {
- printf("error out index %d\n",buf.index);
- break;
- }
- //if (bitsteamEnd)
- // continue;
- if(!FillInputBuffer(decodeTestContext, &buf, 0)){
- bitsteamEnd = true;
- }
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_QBUF, &buf)) {
- printf("VIDIOC_QBUF fail\n");
- break;
- }
- }
- }
- if (fds) {
- free(fds);
- fds = NULL;
- }
- }
- int main(int argc, char **argv)
- {
- printf("=============================\r\n");
- int32_t error,i,j;
- struct stat st;
- struct v4l2_capability cap;
- struct v4l2_format fmt;
- struct v4l2_requestbuffers req;
- struct v4l2_event_subscription argp;
- enum v4l2_buf_type type;
- decodeTestContext = malloc(sizeof(DecodeTestContext));
- gInput_v4l2_plane = malloc(sizeof(struct v4l2_plane) * MAX_BUF_CNT * MAX_PLANES);
- gOutput_v4l2_plane = malloc(sizeof(struct v4l2_plane) * MAX_BUF_CNT * MAX_PLANES);
- if (!decodeTestContext || !gInput_v4l2_plane || !gInput_v4l2_plane){
- return -1;
- }
- PCLEAR(decodeTestContext);
- PCLEAR(gInput_v4l2_plane);
- PCLEAR(gOutput_v4l2_plane);
- for (i = 0; i < MAX_BUF_CNT; i++){
- decodeTestContext->InputV4L2BufArray[i].m.planes = gInput_v4l2_plane + i * MAX_PLANES;
- decodeTestContext->OutputV4L2BufArray[i].m.planes = gOutput_v4l2_plane + i * MAX_PLANES;
- decodeTestContext->InputV4L2BufArray[i].length = MAX_PLANES;
- decodeTestContext->OutputV4L2BufArray[i].length = MAX_PLANES;
- }
- struct option longOpt[] = {
- {"output", required_argument, NULL, 'o'},
- {"input", required_argument, NULL, 'i'},
- {"format", required_argument, NULL, 'f'},
- {"scaleW", required_argument, NULL, 'w'},
- {"scaleH", required_argument, NULL, 'h'},
- {"test", required_argument, NULL, 't'},
- {"help", no_argument, NULL, '0'},
- {NULL, no_argument, NULL, 0},
- };
- char *shortOpt = "i:o:f:w:h:t";
- uint32_t c;
- int32_t l;
- if (argc == 0)
- {
- help();
- return -1;
- }
- while ((c = getopt_long(argc, argv, shortOpt, longOpt, (int *)&l)) != -1)
- {
- switch (c)
- {
- case 'i':
- printf("input: %s\r\n", optarg);
- if (access(optarg, R_OK) != -1)
- {
- memcpy(decodeTestContext->sInputFilePath, optarg, strlen(optarg));
- }
- else
- {
- printf("input file not exist!\r\n");
- return -1;
- }
- break;
- case 'o':
- printf("output: %s\r\n", optarg);
- memcpy(decodeTestContext->sOutputFilePath, optarg, strlen(optarg));
- break;
- case 'f':
- printf("format: %s\r\n", optarg);
- memcpy(decodeTestContext->sOutputFormat, optarg, strlen(optarg));
- break;
- case 'w':
- printf("ScaleWidth: %s\r\n", optarg);
- decodeTestContext->ScaleWidth = atoi(optarg);
- break;
- case 'h':
- printf("ScaleHeight: %s\r\n", optarg);
- decodeTestContext->ScaleHeight = atoi(optarg);
- break;
- case 't':
- testFPS = true;
- break;
- case '0':
- default:
- help();
- return -1;
- }
- }
- decodeTestContext->io_mthd = IO_METHOD_MMAP; //for now
- if (strstr(decodeTestContext->sOutputFormat, "nv12") != NULL)
- {
- decodeTestContext->format = V4L2_PIX_FMT_NV12M;
- }
- else if (strstr(decodeTestContext->sOutputFormat, "nv21") != NULL)
- {
- decodeTestContext->format = V4L2_PIX_FMT_NV21M;
- }
- else if (strstr(decodeTestContext->sOutputFormat, "i420") != NULL)
- {
- decodeTestContext->format = V4L2_PIX_FMT_YUV420M;
- }
- else
- {
- printf("Unsupported color format!\r\n");
- return -1;
- }
- /*ffmpeg init*/
- printf("init ffmpeg\r\n");
- AVFormatContext *avContext = NULL;
- AVCodecParameters *codecParameters = NULL;
- AVInputFormat *avfmt = NULL;
- int32_t videoIndex;
- if ((avContext = avformat_alloc_context()) == NULL)
- {
- printf("avformat_alloc_context fail\r\n");
- return -1;
- }
- avContext->flags |= AV_CODEC_FLAG_TRUNCATED;
- printf("avformat_open_input\r\n");
- if ((error = avformat_open_input(&avContext, decodeTestContext->sInputFilePath, avfmt, NULL)))
- {
- printf("%s:%d failed to av_open_input_file error(%s), %s\n",
- __FILE__, __LINE__, av_err2str(error), decodeTestContext->sInputFilePath);
- avformat_free_context(avContext);
- return -1;
- }
- printf("avformat_find_stream_info\r\n");
- if ((error = avformat_find_stream_info(avContext, NULL)) < 0)
- {
- printf("%s:%d failed to avformat_find_stream_info. error(%s)\n",
- __FUNCTION__, __LINE__, av_err2str(error));
- avformat_close_input(&avContext);
- avformat_free_context(avContext);
- return -1;
- }
- printf("av_find_best_stream\r\n");
- videoIndex = av_find_best_stream(avContext, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
- if (videoIndex < 0)
- {
- printf("%s:%d failed to av_find_best_stream.\n", __FUNCTION__, __LINE__);
- return -1;
- }
- printf("video index = %d\r\n", videoIndex);
- decodeTestContext->video_stream_idx = videoIndex;
- decodeTestContext->avContext = avContext;
- /*get video info*/
- codecParameters = avContext->streams[videoIndex]->codecpar;
- printf("codec_id = %d, width = %d, height = %d\r\n", (int)codecParameters->codec_id,
- codecParameters->width, codecParameters->height);
- decodeTestContext->width = codecParameters->width;
- decodeTestContext->height = codecParameters->height;
- if (codecParameters->codec_id == AV_CODEC_ID_H264)
- {
- decodeTestContext->StreamFormat = V4L2_PIX_FMT_H264;
- }
- else if (codecParameters->codec_id == AV_CODEC_ID_HEVC)
- {
- decodeTestContext->StreamFormat = V4L2_PIX_FMT_HEVC;
- }
- else
- {
- printf("not support stream %d \n",(int)codecParameters->codec_id);
- goto end;
- }
- if (decodeTestContext->ScaleWidth)
- {
- int scalew = codecParameters->width / decodeTestContext->ScaleWidth;
- if (scalew > 8 || scalew < 1)
- {
- printf("orign width %d scale width %d.\n",codecParameters->width, decodeTestContext->ScaleWidth);
- printf("Scaling should be 1 to 1/8 (down-scaling only)! Use input parameter, end.\n");
- goto end;
- }
- }
- if (decodeTestContext->ScaleHeight)
- {
- int scaleh= codecParameters->height / decodeTestContext->ScaleHeight;
- if (scaleh > 8 || scaleh < 1)
- {
- printf("orign height %d scale height %d.\n",codecParameters->height, decodeTestContext->ScaleHeight);
- printf("Scaling should be 1 to 1/8 (down-scaling only)! Use input parameter, end.\n");
- goto end;
- }
- }
- signal(SIGINT, signal_handle);
- /* find video device */
- for (i = 0; i < MAX_VIDEO_CNT; i++){
- sprintf(devPath, "/dev/video%d", i);
- if (-1 == stat(devPath, &st)) {
- continue;
- }
- decodeTestContext->fd = v4l2_open(devPath, O_RDWR /* required */ | O_NONBLOCK, 0);
- if (-1 == decodeTestContext->fd) {
- printf("Cannot open '%s': %d, %s\n", devPath, errno, strerror(errno));
- continue;
- }
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_QUERYCAP, &cap)) {
- if (EINVAL == errno) {
- printf("%s is no V4L2 device\n", devPath);
- v4l2_close(decodeTestContext->fd);
- continue;
- } else {
- printf("%s can not VIDIOC_QUERYCAP fail\n", devPath);
- v4l2_close(decodeTestContext->fd);
- continue;
- }
- }
- if (strncmp((const char *)cap.driver, VPU_DEC_DRV_NAME, 9)) {
- v4l2_close(decodeTestContext->fd);
- continue;
- }
- printf("find %s %s\n", VPU_DEC_DRV_NAME, devPath);
- break;
- }
- if (i == MAX_VIDEO_CNT){
- printf("can not find decoder, end\n");
- goto end;
- }
- fb = fopen(decodeTestContext->sOutputFilePath, "wb+");
- if (!fb)
- {
- fprintf(stderr, "output file open err or no output file patch %d\n", errno);
- goto end;
- }
- printf("init V4L2 device\n");
- switch (decodeTestContext->io_mthd) {
- case IO_METHOD_MMAP:
- case IO_METHOD_USERPTR:
- case IO_METHOD_DMABUF:
- if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
- printf("%s does not support streaming i/o\n", devPath);
- goto end;
- }
- break;
- default:
- printf("%s does not specify streaming i/o\n", devPath);
- goto end;
- break;
- }
- argp.type = V4L2_EVENT_SOURCE_CHANGE;
- argp.id = 0;
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_SUBSCRIBE_EVENT, &argp)) {
- printf("VIDIOC_SUBSCRIBE_EVENT fail\n");
- goto end;
- }
- argp.type = V4L2_EVENT_EOS;
- argp.id = 0;
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_SUBSCRIBE_EVENT, &argp)) {
- printf("VIDIOC_SUBSCRIBE_EVENT fail\n");
- goto end;
- }
- printf("set src q format\n");
- fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- fmt.fmt.pix_mp.width = codecParameters->width;
- fmt.fmt.pix_mp.height = codecParameters->height;
- fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
- fmt.fmt.pix_mp.pixelformat = decodeTestContext->StreamFormat;
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_S_FMT, &fmt)) {
- printf("VIDIOC_S_FMT fail\n");
- goto end;
- }
- CLEAR(fmt);
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- fmt.fmt.pix_mp.width = decodeTestContext->ScaleWidth? decodeTestContext->ScaleWidth: codecParameters->width;
- fmt.fmt.pix_mp.height = decodeTestContext->ScaleHeight? decodeTestContext->ScaleHeight: codecParameters->height;
- fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
- fmt.fmt.pix_mp.pixelformat = decodeTestContext->format;
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_S_FMT, &fmt)) {
- printf("VIDIOC_S_FMT fail\n");
- goto end;
- }
- convert_v4l2_mem_type(decodeTestContext->io_mthd, &decodeTestContext->mem_type);
- printf("get dist q format\n");
- CLEAR(fmt);
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
- if (-1 == ioctl(decodeTestContext->fd, VIDIOC_G_FMT, &fmt)) {
- printf("VIDIOC_G_FMT fail\n");
- goto end;
- }
- printf("VIDIOC_G_FMT: type=%d, Fourcc format=%c%c%c%c\n",
- fmt.type, fmt.fmt.pix_mp.pixelformat & 0xff,
- (fmt.fmt.pix_mp.pixelformat >> 8) &0xff,
- (fmt.fmt.pix_mp.pixelformat >> 16) &0xff,
- (fmt.fmt.pix_mp.pixelformat >> 24) &0xff);
- printf(" \t width=%d, height=%d, field=%d, bytesperline=%d, sizeimage=%d\n",
- fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.field,
- fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
- if (fmt.fmt.pix_mp.pixelformat != decodeTestContext->format) {
- printf("v4l2 didn't accept format %d. Can't proceed.\n", decodeTestContext->format);
- goto end;
- }
- /* Note VIDIOC_S_FMT may change width and height. */
- if (decodeTestContext->width != fmt.fmt.pix_mp.width) {
- decodeTestContext->width = fmt.fmt.pix_mp.width;
- printf("Correct image width set to %i by device %s.\n", decodeTestContext->width, devPath);
- }
- if (decodeTestContext->height != fmt.fmt.pix_mp.height) {
- decodeTestContext->height = fmt.fmt.pix_mp.height;
- printf("Correct image height set to %i by device %s.\n", decodeTestContext->height,devPath);
- }
- /* prepare and start v4l2 stream */
- printf("request src buffer\n");
- CLEAR(req);
- req.count = BUFCOUNT;
- req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- req.memory = V4L2_MEMORY_MMAP;
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_REQBUFS, &req)) {
- printf("%s request buffer fail %d\n", devPath, errno);
- goto end;
- }
- decodeTestContext->n_inputbuffers = req.count;
- for (i = 0; i < decodeTestContext->n_inputbuffers; i++) {
- if (bitsteamEnd)
- break;
- decodeTestContext->InputV4L2BufArray[i].type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- decodeTestContext->InputV4L2BufArray[i].memory = V4L2_MEMORY_MMAP;
- decodeTestContext->InputV4L2BufArray[i].index = i;
- // test prepare
- //if (-1 == xioctl(decodeTestContext->fd, VIDIOC_PREPARE_BUF, &decodeTestContext->InputV4L2BufArray[i]))
- //{
- // printf("VIDIOC_PREPARE_BUF fail %d\n",errno);
- // goto end;
- //}
- // test prepare end
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_QUERYBUF, &decodeTestContext->InputV4L2BufArray[i]))
- {
- printf("VIDIOC_QUERYBUF fail %d\n",errno);
- goto end;
- }
- printf("src buffer %d type %d method %d n_plane %d\n",i ,decodeTestContext->InputV4L2BufArray[i].type,
- decodeTestContext->InputV4L2BufArray[i].memory, decodeTestContext->InputV4L2BufArray[i].length);
- for (j = 0; j < decodeTestContext->InputV4L2BufArray[i].length; j++){
- printf(" plane %d length 0x%x offset 0x%x\n", j,
- decodeTestContext->InputV4L2BufArray[i].m.planes[j].length, decodeTestContext->InputV4L2BufArray[i].m.planes[j].m.mem_offset);
- decodeTestContext->InputBufArray[i].length[j] = decodeTestContext->InputV4L2BufArray[i].m.planes[j].length;
- decodeTestContext->InputBufArray[i].start[j] = v4l2_mmap(NULL, /* start anywhere */
- decodeTestContext->InputV4L2BufArray[i].m.planes[j].length, PROT_READ | PROT_WRITE, /* required */
- MAP_SHARED, /* recommended */
- decodeTestContext->fd, decodeTestContext->InputV4L2BufArray[i].m.planes[j].m.mem_offset);
- if (MAP_FAILED == decodeTestContext->InputBufArray[i].start[j]) {
- printf("map fail %d\n",i);
- goto end;
- }
- }
- if(!FillInputBuffer(decodeTestContext, &decodeTestContext->InputV4L2BufArray[i], 0)){
- bitsteamEnd = true;
- }
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_QBUF, &decodeTestContext->InputV4L2BufArray[i])) {
- printf("VIDIOC_QBUF fail\n");
- goto end;
- }
- }
- printf("start src stream\n");
- type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_STREAMON, &type)) {
- printf("start src stream fail\n");
- goto end;
- }
- mainloop();
- printf("stop src stream\n");
- type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_STREAMOFF, &type)) {
- printf("stop src stream fail\n");
- goto end;
- }
- printf("stop dist stream\n");
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- if (-1 == xioctl(decodeTestContext->fd, VIDIOC_STREAMOFF, &type)) {
- printf("stop dist stream fail\n");
- goto end;
- }
- v4l2_close(decodeTestContext->fd);
- end:
- /*free resource*/
- if (fb)
- fclose(fb);
- avformat_close_input(&avContext);
- avformat_free_context(avContext);
- }
|