v4l2_dec_test.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2021 StarFive Technology Co., Ltd.
  4. */
  5. #include <stdio.h>
  6. #include <unistd.h>
  7. #include <signal.h>
  8. #include <getopt.h>
  9. #include <fcntl.h>
  10. #include "libavformat/avformat.h"
  11. #include "libavcodec/avcodec.h"
  12. #include <libv4l2.h>
  13. #include <poll.h>
  14. #include <sys/time.h>
  15. #include <sys/types.h>
  16. #include <sys/ipc.h>
  17. #include <sys/ioctl.h>
  18. #include <sys/msg.h>
  19. #include <sys/mman.h>
  20. #include <stdlib.h>
  21. #include <stdint.h>
  22. #include <stdbool.h>
  23. #include <sys/stat.h>
  24. #include <time.h>
  25. #include <asm/types.h>
  26. #include <linux/videodev2.h>
  27. #include <string.h>
  28. #include <errno.h>
  29. #include <fcntl.h>
  30. #include <malloc.h>
  31. #define MAX_BUF_CNT 10
  32. #define BUFCOUNT 5
  33. #define MAX_PLANES 3
  34. #define MAX_VIDEO_CNT 24
  35. #define VPU_DEC_DRV_NAME "wave5-dec"
  36. #define CLEAR(x) memset (&(x), 0, sizeof (x))
  37. #define PCLEAR(x) memset ((x), 0, sizeof (*x))
  38. //typedef enum __bool { false = 0, true = 1, } bool;
  39. typedef struct v4l2_buffer v4l2_buffer;
  40. typedef enum IOMethod {
  41. IO_METHOD_MMAP,
  42. IO_METHOD_USERPTR,
  43. IO_METHOD_DMABUF,
  44. IO_METHOD_READ
  45. } IOMethod;
  46. typedef struct buffer {
  47. void* start[MAX_PLANES];
  48. size_t length[MAX_PLANES];
  49. int dmabuf_fd[MAX_PLANES];
  50. int index;
  51. }buffer;
  52. typedef struct DecodeTestContext
  53. {
  54. int fd;
  55. IOMethod io_mthd; // IO_METHOD_MMAP
  56. enum v4l2_memory mem_type;
  57. char sOutputFilePath[256];
  58. char sInputFilePath[256];
  59. char sOutputFormat[64];
  60. uint32_t ScaleWidth;
  61. uint32_t ScaleHeight;
  62. uint32_t StreamFormat;
  63. uint32_t format;
  64. uint32_t n_inputbuffers;
  65. uint32_t n_outputbuffers;
  66. uint32_t inputBufSize;
  67. uint32_t outputBufSize;
  68. uint32_t width; // = 1920;
  69. uint32_t height; // = 1080;
  70. v4l2_buffer InputV4L2BufArray[MAX_BUF_CNT];
  71. v4l2_buffer OutputV4L2BufArray[MAX_BUF_CNT];
  72. buffer InputBufArray[MAX_BUF_CNT];
  73. buffer OutputBufArray[MAX_BUF_CNT];
  74. AVFormatContext *avContext;
  75. int32_t video_stream_idx;
  76. } DecodeTestContext;
  77. DecodeTestContext *decodeTestContext;
  78. struct v4l2_plane *gInput_v4l2_plane;
  79. struct v4l2_plane *gOutput_v4l2_plane;
  80. static char devPath[16];
  81. static int32_t FillInputBuffer(DecodeTestContext *decodeTestContext, struct v4l2_buffer *buf, int32_t pIndex);
  82. static bool justQuit = false;
  83. static bool bitsteamEnd = false;
  84. static bool testFPS =false;
  85. static FILE *fb = NULL;
  86. static int xioctl(int fd, int request, void* argp)
  87. {
  88. int r;
  89. // TODO: the orign is v4l2_ioctl()
  90. do r = ioctl(fd, request, argp);
  91. while (-1 == r && EINTR == errno);
  92. return r;
  93. }
  94. static void convert_v4l2_mem_type(int iomthd, enum v4l2_memory *mem_type)
  95. {
  96. if (iomthd < IO_METHOD_MMAP || iomthd > IO_METHOD_READ) {
  97. printf("iomthd %d out of range\n", iomthd);
  98. return;
  99. }
  100. switch (iomthd) {
  101. case IO_METHOD_MMAP:
  102. *mem_type = V4L2_MEMORY_MMAP;
  103. break;
  104. case IO_METHOD_USERPTR:
  105. *mem_type = V4L2_MEMORY_USERPTR;
  106. break;
  107. case IO_METHOD_DMABUF:
  108. *mem_type = V4L2_MEMORY_DMABUF;
  109. break;
  110. case IO_METHOD_READ:
  111. *mem_type = 0; // not use memory machanism
  112. break;
  113. default:
  114. *mem_type = 0; // not use memory machanism
  115. break;
  116. }
  117. }
  118. static void help()
  119. {
  120. printf("v4l2_dec_test - v4l2 hardware decode unit test case\r\n\r\n");
  121. printf("Usage:\r\n\r\n");
  122. printf("./v4l2_dec_test -i <input file> input file\r\n");
  123. printf(" -o <output file> output file\r\n");
  124. printf(" -f <format> i420/nv12/nv21\r\n");
  125. printf(" --scaleW=<width> (optional) scale width down. ceil32(width/8) <= scaledW <= width\r\n");
  126. printf(" --scaleH=<heitht> (optional) scale height down, ceil8(height/8) <= scaledH <= height\r\n\r\n");
  127. printf("./v4l2_dec_test --help: show this message\r\n");
  128. }
  129. static void signal_handle(int sig)
  130. {
  131. printf("[%s,%d]: receive sig=%d \n", __FUNCTION__, __LINE__, sig);
  132. justQuit = true;
  133. }
  134. static int32_t FillInputBuffer(DecodeTestContext *decodeTestContext, struct v4l2_buffer *buf, int32_t pIndex)
  135. {
  136. AVFormatContext *avFormatContext = decodeTestContext->avContext;
  137. AVPacket *avpacket;
  138. int32_t error = 0;
  139. avpacket = av_packet_alloc();
  140. while (error >= 0)
  141. {
  142. error = av_read_frame(avFormatContext, avpacket);
  143. if (avpacket->stream_index == decodeTestContext->video_stream_idx)
  144. break;
  145. printf("get audio frame\n");
  146. }
  147. if (error < 0)
  148. {
  149. if (error == AVERROR_EOF || avFormatContext->pb->eof_reached)
  150. {
  151. printf("get stream eos\n");
  152. buf->m.planes[pIndex].bytesused = 0;
  153. return 0;
  154. }
  155. else
  156. {
  157. printf("%s:%d failed to av_read_frame, error: %s\n",
  158. __FUNCTION__, __LINE__, av_err2str(error));
  159. buf->m.planes[pIndex].bytesused = 0;
  160. return 0;
  161. }
  162. }
  163. if (decodeTestContext->InputBufArray[buf->index].length[pIndex] >= avpacket->size){
  164. memcpy(decodeTestContext->InputBufArray[buf->index].start[pIndex], avpacket->data, avpacket->size);
  165. buf->m.planes[pIndex].bytesused = avpacket->size;
  166. return avpacket->size;
  167. }else{
  168. printf("buff size too small %ld<%d\n",decodeTestContext->InputBufArray[buf->index].length[pIndex], avpacket->size);
  169. buf->m.planes[pIndex].bytesused = 0;
  170. return 0;
  171. }
  172. }
  173. static void mainloop()
  174. {
  175. int r, i, j, fps, dec_cnt = 0;
  176. uint64_t diff_time;
  177. struct pollfd* fds = NULL;
  178. struct v4l2_event event;
  179. struct v4l2_format fmt;
  180. struct v4l2_requestbuffers req;
  181. struct v4l2_buffer buf;
  182. struct v4l2_plane planes[MAX_PLANES];
  183. struct timeval tv_old, tv;
  184. enum v4l2_buf_type type;
  185. fds = (struct pollfd*)malloc(sizeof(struct pollfd));
  186. PCLEAR(fds);
  187. fds->fd = decodeTestContext->fd;
  188. fds->events = POLLIN | POLLOUT | POLLPRI;
  189. while (true){
  190. if (justQuit)
  191. break;
  192. r = poll(fds, 1, 3000);
  193. if (-1 == r) {
  194. if (EINTR == errno) {
  195. continue;
  196. }
  197. printf("error in poll %d", errno);
  198. break;
  199. }
  200. if (0 == r) {
  201. printf("poll timeout, %d\n", errno);
  202. break;
  203. }
  204. if (fds->revents & POLLPRI) {
  205. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_DQEVENT, &event)) {
  206. printf("get event fail\n");
  207. break;
  208. }
  209. printf("get event %d\n",event.type);
  210. if (event.type == V4L2_EVENT_SOURCE_CHANGE &&
  211. event.u.src_change.changes == V4L2_EVENT_SRC_CH_RESOLUTION){
  212. printf("request dist buffer\n");
  213. CLEAR(req);
  214. req.count = BUFCOUNT;
  215. req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
  216. req.memory = V4L2_MEMORY_MMAP;
  217. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_REQBUFS, &req)) {
  218. printf("%s request buffer fail %d\n", devPath, errno);
  219. break;
  220. }
  221. decodeTestContext->n_outputbuffers = req.count;
  222. printf("get dist q format\n");
  223. CLEAR(fmt);
  224. fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
  225. fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
  226. if (-1 == ioctl(decodeTestContext->fd, VIDIOC_G_FMT, &fmt)) {
  227. printf("VIDIOC_G_FMT fail\n");
  228. break;
  229. }
  230. printf("VIDIOC_G_FMT: type=%d, Fourcc format=%c%c%c%c\n",
  231. fmt.type, fmt.fmt.pix_mp.pixelformat & 0xff,
  232. (fmt.fmt.pix_mp.pixelformat >> 8) &0xff,
  233. (fmt.fmt.pix_mp.pixelformat >> 16) &0xff,
  234. (fmt.fmt.pix_mp.pixelformat >> 24) &0xff);
  235. printf(" \t width=%d, height=%d, field=%d, bytesperline=%d, sizeimage=%d\n",
  236. fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.field,
  237. fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
  238. if (fmt.fmt.pix_mp.pixelformat != decodeTestContext->format) {
  239. printf("v4l2 didn't accept format %d. Can't proceed.\n", decodeTestContext->format);
  240. break;
  241. }
  242. /* Note VIDIOC_S_FMT may change width and height. */
  243. if (decodeTestContext->width != fmt.fmt.pix_mp.width) {
  244. decodeTestContext->width = fmt.fmt.pix_mp.width;
  245. printf("Correct image width set to %i by device %s.\n", decodeTestContext->width, devPath);
  246. }
  247. if (decodeTestContext->height != fmt.fmt.pix_mp.height) {
  248. decodeTestContext->height = fmt.fmt.pix_mp.height;
  249. printf("Correct image height set to %i by device %s.\n", decodeTestContext->height, devPath);
  250. }
  251. for (i = 0; i < decodeTestContext->n_outputbuffers; i++) {
  252. decodeTestContext->OutputV4L2BufArray[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
  253. decodeTestContext->OutputV4L2BufArray[i].memory = V4L2_MEMORY_MMAP;
  254. decodeTestContext->OutputV4L2BufArray[i].index = i;
  255. // VIDIOC_PREPARE_BUF
  256. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_PREPARE_BUF, &decodeTestContext->OutputV4L2BufArray[i]))
  257. {
  258. printf("VIDIOC_PREPARE_BUF fail\n");
  259. break;
  260. }
  261. // VIDIOC_PREPARE_BUF end
  262. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_QUERYBUF, &decodeTestContext->OutputV4L2BufArray[i]))
  263. {
  264. printf("VIDIOC_QUERYBUF fail\n");
  265. break;
  266. }
  267. printf("src buffer %d type %d method %d n_plane %d\n",i ,decodeTestContext->OutputV4L2BufArray[i].type,
  268. decodeTestContext->OutputV4L2BufArray[i].memory, decodeTestContext->OutputV4L2BufArray[i].length);
  269. for (j = 0; j < decodeTestContext->OutputV4L2BufArray[i].length; j++){
  270. printf(" plane %d length 0x%x offset 0x%x\n", j,
  271. decodeTestContext->OutputV4L2BufArray[i].m.planes[j].length, decodeTestContext->OutputV4L2BufArray[i].m.planes[j].m.mem_offset);
  272. decodeTestContext->OutputBufArray[i].length[j] = decodeTestContext->OutputV4L2BufArray[i].m.planes[j].length;
  273. decodeTestContext->OutputBufArray[i].start[j] = v4l2_mmap(NULL, /* start anywhere */
  274. decodeTestContext->OutputV4L2BufArray[i].m.planes[j].length, PROT_READ | PROT_WRITE, /* required */
  275. MAP_SHARED, /* recommended */
  276. decodeTestContext->fd, decodeTestContext->OutputV4L2BufArray[i].m.planes[j].m.mem_offset);
  277. if (MAP_FAILED == decodeTestContext->OutputBufArray[i].start[j]) {
  278. printf("map fail %d err %d\n",i, errno);
  279. break;
  280. }
  281. }
  282. }
  283. for (i = 0; i < decodeTestContext->n_outputbuffers; i++){
  284. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_QBUF, &decodeTestContext->OutputV4L2BufArray[i])) {
  285. printf("VIDIOC_QBUF fail\n");
  286. break;
  287. }
  288. }
  289. printf("start dst stream\n");
  290. type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
  291. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_STREAMON, &type)) {
  292. printf("start dst stream fail\n");
  293. break;
  294. }
  295. }else if (event.type == V4L2_EVENT_EOS){
  296. printf("finished, end\n");
  297. break;
  298. }
  299. }
  300. if (fds->revents & POLLIN) {
  301. CLEAR(buf);
  302. memset(planes, 0, sizeof(struct v4l2_plane) * MAX_PLANES);
  303. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
  304. buf.memory = decodeTestContext->mem_type;
  305. buf.length = MAX_PLANES;
  306. buf.m.planes = planes;
  307. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_DQBUF, &buf)) {
  308. switch (errno) {
  309. case EAGAIN:
  310. continue;
  311. case EIO:
  312. /* Could ignore EIO, see spec. */
  313. /* fall through */
  314. default:
  315. printf("pollin VIDIOC_DQBUF fail\n");
  316. }
  317. }
  318. if (buf.index > decodeTestContext->n_outputbuffers)
  319. {
  320. printf("error capture index %d\n",buf.index);
  321. break;
  322. }
  323. if (testFPS)
  324. {
  325. if (dec_cnt == 0) {
  326. gettimeofday(&tv_old, NULL);
  327. }
  328. if (dec_cnt++ >= 50) {
  329. gettimeofday(&tv, NULL);
  330. diff_time = (tv.tv_sec - tv_old.tv_sec) * 1000 + (tv.tv_usec - tv_old.tv_usec) / 1000;
  331. fps = 1000 * (dec_cnt - 1) / diff_time;
  332. dec_cnt = 0;
  333. printf("Decoding fps: %d \r\n", fps);
  334. }
  335. }
  336. else
  337. {
  338. for (i = 0; i < buf.length; i++){
  339. fwrite(decodeTestContext->OutputBufArray[buf.index].start[i], 1, buf.m.planes[i].bytesused, fb);
  340. }
  341. }
  342. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_QBUF, &buf)) {
  343. printf("VIDIOC_QBUF fail\n");
  344. break;
  345. }
  346. if (buf.flags & V4L2_BUF_FLAG_LAST){
  347. printf("get last buffer\n");
  348. justQuit = true;
  349. }
  350. }
  351. if (fds->revents & POLLOUT) {
  352. CLEAR(buf);
  353. memset(planes, 0, sizeof(struct v4l2_plane) * MAX_PLANES);
  354. buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
  355. buf.memory = decodeTestContext->mem_type;
  356. buf.length = MAX_PLANES;
  357. buf.m.planes = planes;
  358. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_DQBUF, &buf)) {
  359. switch (errno) {
  360. case EAGAIN:
  361. continue;
  362. case EIO:
  363. /* Could ignore EIO, see spec. */
  364. /* fall through */
  365. default:
  366. printf("pollout VIDIOC_DQBUF fail %d\n", errno);
  367. }
  368. }
  369. if (buf.index > decodeTestContext->n_inputbuffers)
  370. {
  371. printf("error out index %d\n",buf.index);
  372. break;
  373. }
  374. //if (bitsteamEnd)
  375. // continue;
  376. if(!FillInputBuffer(decodeTestContext, &buf, 0)){
  377. bitsteamEnd = true;
  378. }
  379. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_QBUF, &buf)) {
  380. printf("VIDIOC_QBUF fail\n");
  381. break;
  382. }
  383. }
  384. }
  385. if (fds) {
  386. free(fds);
  387. fds = NULL;
  388. }
  389. }
  390. int main(int argc, char **argv)
  391. {
  392. printf("=============================\r\n");
  393. int32_t error,i,j;
  394. struct stat st;
  395. struct v4l2_capability cap;
  396. struct v4l2_format fmt;
  397. struct v4l2_requestbuffers req;
  398. struct v4l2_event_subscription argp;
  399. enum v4l2_buf_type type;
  400. decodeTestContext = malloc(sizeof(DecodeTestContext));
  401. gInput_v4l2_plane = malloc(sizeof(struct v4l2_plane) * MAX_BUF_CNT * MAX_PLANES);
  402. gOutput_v4l2_plane = malloc(sizeof(struct v4l2_plane) * MAX_BUF_CNT * MAX_PLANES);
  403. if (!decodeTestContext || !gInput_v4l2_plane || !gInput_v4l2_plane){
  404. return -1;
  405. }
  406. PCLEAR(decodeTestContext);
  407. PCLEAR(gInput_v4l2_plane);
  408. PCLEAR(gOutput_v4l2_plane);
  409. for (i = 0; i < MAX_BUF_CNT; i++){
  410. decodeTestContext->InputV4L2BufArray[i].m.planes = gInput_v4l2_plane + i * MAX_PLANES;
  411. decodeTestContext->OutputV4L2BufArray[i].m.planes = gOutput_v4l2_plane + i * MAX_PLANES;
  412. decodeTestContext->InputV4L2BufArray[i].length = MAX_PLANES;
  413. decodeTestContext->OutputV4L2BufArray[i].length = MAX_PLANES;
  414. }
  415. struct option longOpt[] = {
  416. {"output", required_argument, NULL, 'o'},
  417. {"input", required_argument, NULL, 'i'},
  418. {"format", required_argument, NULL, 'f'},
  419. {"scaleW", required_argument, NULL, 'w'},
  420. {"scaleH", required_argument, NULL, 'h'},
  421. {"test", required_argument, NULL, 't'},
  422. {"help", no_argument, NULL, '0'},
  423. {NULL, no_argument, NULL, 0},
  424. };
  425. char *shortOpt = "i:o:f:w:h:t";
  426. uint32_t c;
  427. int32_t l;
  428. if (argc == 0)
  429. {
  430. help();
  431. return -1;
  432. }
  433. while ((c = getopt_long(argc, argv, shortOpt, longOpt, (int *)&l)) != -1)
  434. {
  435. switch (c)
  436. {
  437. case 'i':
  438. printf("input: %s\r\n", optarg);
  439. if (access(optarg, R_OK) != -1)
  440. {
  441. memcpy(decodeTestContext->sInputFilePath, optarg, strlen(optarg));
  442. }
  443. else
  444. {
  445. printf("input file not exist!\r\n");
  446. return -1;
  447. }
  448. break;
  449. case 'o':
  450. printf("output: %s\r\n", optarg);
  451. memcpy(decodeTestContext->sOutputFilePath, optarg, strlen(optarg));
  452. break;
  453. case 'f':
  454. printf("format: %s\r\n", optarg);
  455. memcpy(decodeTestContext->sOutputFormat, optarg, strlen(optarg));
  456. break;
  457. case 'w':
  458. printf("ScaleWidth: %s\r\n", optarg);
  459. decodeTestContext->ScaleWidth = atoi(optarg);
  460. break;
  461. case 'h':
  462. printf("ScaleHeight: %s\r\n", optarg);
  463. decodeTestContext->ScaleHeight = atoi(optarg);
  464. break;
  465. case 't':
  466. testFPS = true;
  467. break;
  468. case '0':
  469. default:
  470. help();
  471. return -1;
  472. }
  473. }
  474. decodeTestContext->io_mthd = IO_METHOD_MMAP; //for now
  475. if (strstr(decodeTestContext->sOutputFormat, "nv12") != NULL)
  476. {
  477. decodeTestContext->format = V4L2_PIX_FMT_NV12M;
  478. }
  479. else if (strstr(decodeTestContext->sOutputFormat, "nv21") != NULL)
  480. {
  481. decodeTestContext->format = V4L2_PIX_FMT_NV21M;
  482. }
  483. else if (strstr(decodeTestContext->sOutputFormat, "i420") != NULL)
  484. {
  485. decodeTestContext->format = V4L2_PIX_FMT_YUV420M;
  486. }
  487. else
  488. {
  489. printf("Unsupported color format!\r\n");
  490. return -1;
  491. }
  492. /*ffmpeg init*/
  493. printf("init ffmpeg\r\n");
  494. AVFormatContext *avContext = NULL;
  495. AVCodecParameters *codecParameters = NULL;
  496. AVInputFormat *avfmt = NULL;
  497. int32_t videoIndex;
  498. if ((avContext = avformat_alloc_context()) == NULL)
  499. {
  500. printf("avformat_alloc_context fail\r\n");
  501. return -1;
  502. }
  503. avContext->flags |= AV_CODEC_FLAG_TRUNCATED;
  504. printf("avformat_open_input\r\n");
  505. if ((error = avformat_open_input(&avContext, decodeTestContext->sInputFilePath, avfmt, NULL)))
  506. {
  507. printf("%s:%d failed to av_open_input_file error(%s), %s\n",
  508. __FILE__, __LINE__, av_err2str(error), decodeTestContext->sInputFilePath);
  509. avformat_free_context(avContext);
  510. return -1;
  511. }
  512. printf("avformat_find_stream_info\r\n");
  513. if ((error = avformat_find_stream_info(avContext, NULL)) < 0)
  514. {
  515. printf("%s:%d failed to avformat_find_stream_info. error(%s)\n",
  516. __FUNCTION__, __LINE__, av_err2str(error));
  517. avformat_close_input(&avContext);
  518. avformat_free_context(avContext);
  519. return -1;
  520. }
  521. printf("av_find_best_stream\r\n");
  522. videoIndex = av_find_best_stream(avContext, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
  523. if (videoIndex < 0)
  524. {
  525. printf("%s:%d failed to av_find_best_stream.\n", __FUNCTION__, __LINE__);
  526. return -1;
  527. }
  528. printf("video index = %d\r\n", videoIndex);
  529. decodeTestContext->video_stream_idx = videoIndex;
  530. decodeTestContext->avContext = avContext;
  531. /*get video info*/
  532. codecParameters = avContext->streams[videoIndex]->codecpar;
  533. printf("codec_id = %d, width = %d, height = %d\r\n", (int)codecParameters->codec_id,
  534. codecParameters->width, codecParameters->height);
  535. decodeTestContext->width = codecParameters->width;
  536. decodeTestContext->height = codecParameters->height;
  537. if (codecParameters->codec_id == AV_CODEC_ID_H264)
  538. {
  539. decodeTestContext->StreamFormat = V4L2_PIX_FMT_H264;
  540. }
  541. else if (codecParameters->codec_id == AV_CODEC_ID_HEVC)
  542. {
  543. decodeTestContext->StreamFormat = V4L2_PIX_FMT_HEVC;
  544. }
  545. else
  546. {
  547. printf("not support stream %d \n",(int)codecParameters->codec_id);
  548. goto end;
  549. }
  550. if (decodeTestContext->ScaleWidth)
  551. {
  552. int scalew = codecParameters->width / decodeTestContext->ScaleWidth;
  553. if (scalew > 8 || scalew < 1)
  554. {
  555. printf("orign width %d scale width %d.\n",codecParameters->width, decodeTestContext->ScaleWidth);
  556. printf("Scaling should be 1 to 1/8 (down-scaling only)! Use input parameter, end.\n");
  557. goto end;
  558. }
  559. }
  560. if (decodeTestContext->ScaleHeight)
  561. {
  562. int scaleh= codecParameters->height / decodeTestContext->ScaleHeight;
  563. if (scaleh > 8 || scaleh < 1)
  564. {
  565. printf("orign height %d scale height %d.\n",codecParameters->height, decodeTestContext->ScaleHeight);
  566. printf("Scaling should be 1 to 1/8 (down-scaling only)! Use input parameter, end.\n");
  567. goto end;
  568. }
  569. }
  570. signal(SIGINT, signal_handle);
  571. /* find video device */
  572. for (i = 0; i < MAX_VIDEO_CNT; i++){
  573. sprintf(devPath, "/dev/video%d", i);
  574. if (-1 == stat(devPath, &st)) {
  575. continue;
  576. }
  577. decodeTestContext->fd = v4l2_open(devPath, O_RDWR /* required */ | O_NONBLOCK, 0);
  578. if (-1 == decodeTestContext->fd) {
  579. printf("Cannot open '%s': %d, %s\n", devPath, errno, strerror(errno));
  580. continue;
  581. }
  582. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_QUERYCAP, &cap)) {
  583. if (EINVAL == errno) {
  584. printf("%s is no V4L2 device\n", devPath);
  585. v4l2_close(decodeTestContext->fd);
  586. continue;
  587. } else {
  588. printf("%s can not VIDIOC_QUERYCAP fail\n", devPath);
  589. v4l2_close(decodeTestContext->fd);
  590. continue;
  591. }
  592. }
  593. if (strncmp((const char *)cap.driver, VPU_DEC_DRV_NAME, 9)) {
  594. v4l2_close(decodeTestContext->fd);
  595. continue;
  596. }
  597. printf("find %s %s\n", VPU_DEC_DRV_NAME, devPath);
  598. break;
  599. }
  600. if (i == MAX_VIDEO_CNT){
  601. printf("can not find decoder, end\n");
  602. goto end;
  603. }
  604. fb = fopen(decodeTestContext->sOutputFilePath, "wb+");
  605. if (!fb)
  606. {
  607. fprintf(stderr, "output file open err or no output file patch %d\n", errno);
  608. goto end;
  609. }
  610. printf("init V4L2 device\n");
  611. switch (decodeTestContext->io_mthd) {
  612. case IO_METHOD_MMAP:
  613. case IO_METHOD_USERPTR:
  614. case IO_METHOD_DMABUF:
  615. if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
  616. printf("%s does not support streaming i/o\n", devPath);
  617. goto end;
  618. }
  619. break;
  620. default:
  621. printf("%s does not specify streaming i/o\n", devPath);
  622. goto end;
  623. break;
  624. }
  625. argp.type = V4L2_EVENT_SOURCE_CHANGE;
  626. argp.id = 0;
  627. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_SUBSCRIBE_EVENT, &argp)) {
  628. printf("VIDIOC_SUBSCRIBE_EVENT fail\n");
  629. goto end;
  630. }
  631. argp.type = V4L2_EVENT_EOS;
  632. argp.id = 0;
  633. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_SUBSCRIBE_EVENT, &argp)) {
  634. printf("VIDIOC_SUBSCRIBE_EVENT fail\n");
  635. goto end;
  636. }
  637. printf("set src q format\n");
  638. fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
  639. fmt.fmt.pix_mp.width = codecParameters->width;
  640. fmt.fmt.pix_mp.height = codecParameters->height;
  641. fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
  642. fmt.fmt.pix_mp.pixelformat = decodeTestContext->StreamFormat;
  643. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_S_FMT, &fmt)) {
  644. printf("VIDIOC_S_FMT fail\n");
  645. goto end;
  646. }
  647. CLEAR(fmt);
  648. fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
  649. fmt.fmt.pix_mp.width = decodeTestContext->ScaleWidth? decodeTestContext->ScaleWidth: codecParameters->width;
  650. fmt.fmt.pix_mp.height = decodeTestContext->ScaleHeight? decodeTestContext->ScaleHeight: codecParameters->height;
  651. fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
  652. fmt.fmt.pix_mp.pixelformat = decodeTestContext->format;
  653. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_S_FMT, &fmt)) {
  654. printf("VIDIOC_S_FMT fail\n");
  655. goto end;
  656. }
  657. convert_v4l2_mem_type(decodeTestContext->io_mthd, &decodeTestContext->mem_type);
  658. printf("get dist q format\n");
  659. CLEAR(fmt);
  660. fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
  661. fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
  662. if (-1 == ioctl(decodeTestContext->fd, VIDIOC_G_FMT, &fmt)) {
  663. printf("VIDIOC_G_FMT fail\n");
  664. goto end;
  665. }
  666. printf("VIDIOC_G_FMT: type=%d, Fourcc format=%c%c%c%c\n",
  667. fmt.type, fmt.fmt.pix_mp.pixelformat & 0xff,
  668. (fmt.fmt.pix_mp.pixelformat >> 8) &0xff,
  669. (fmt.fmt.pix_mp.pixelformat >> 16) &0xff,
  670. (fmt.fmt.pix_mp.pixelformat >> 24) &0xff);
  671. printf(" \t width=%d, height=%d, field=%d, bytesperline=%d, sizeimage=%d\n",
  672. fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.field,
  673. fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
  674. if (fmt.fmt.pix_mp.pixelformat != decodeTestContext->format) {
  675. printf("v4l2 didn't accept format %d. Can't proceed.\n", decodeTestContext->format);
  676. goto end;
  677. }
  678. /* Note VIDIOC_S_FMT may change width and height. */
  679. if (decodeTestContext->width != fmt.fmt.pix_mp.width) {
  680. decodeTestContext->width = fmt.fmt.pix_mp.width;
  681. printf("Correct image width set to %i by device %s.\n", decodeTestContext->width, devPath);
  682. }
  683. if (decodeTestContext->height != fmt.fmt.pix_mp.height) {
  684. decodeTestContext->height = fmt.fmt.pix_mp.height;
  685. printf("Correct image height set to %i by device %s.\n", decodeTestContext->height,devPath);
  686. }
  687. /* prepare and start v4l2 stream */
  688. printf("request src buffer\n");
  689. CLEAR(req);
  690. req.count = BUFCOUNT;
  691. req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
  692. req.memory = V4L2_MEMORY_MMAP;
  693. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_REQBUFS, &req)) {
  694. printf("%s request buffer fail %d\n", devPath, errno);
  695. goto end;
  696. }
  697. decodeTestContext->n_inputbuffers = req.count;
  698. for (i = 0; i < decodeTestContext->n_inputbuffers; i++) {
  699. if (bitsteamEnd)
  700. break;
  701. decodeTestContext->InputV4L2BufArray[i].type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
  702. decodeTestContext->InputV4L2BufArray[i].memory = V4L2_MEMORY_MMAP;
  703. decodeTestContext->InputV4L2BufArray[i].index = i;
  704. // test prepare
  705. //if (-1 == xioctl(decodeTestContext->fd, VIDIOC_PREPARE_BUF, &decodeTestContext->InputV4L2BufArray[i]))
  706. //{
  707. // printf("VIDIOC_PREPARE_BUF fail %d\n",errno);
  708. // goto end;
  709. //}
  710. // test prepare end
  711. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_QUERYBUF, &decodeTestContext->InputV4L2BufArray[i]))
  712. {
  713. printf("VIDIOC_QUERYBUF fail %d\n",errno);
  714. goto end;
  715. }
  716. printf("src buffer %d type %d method %d n_plane %d\n",i ,decodeTestContext->InputV4L2BufArray[i].type,
  717. decodeTestContext->InputV4L2BufArray[i].memory, decodeTestContext->InputV4L2BufArray[i].length);
  718. for (j = 0; j < decodeTestContext->InputV4L2BufArray[i].length; j++){
  719. printf(" plane %d length 0x%x offset 0x%x\n", j,
  720. decodeTestContext->InputV4L2BufArray[i].m.planes[j].length, decodeTestContext->InputV4L2BufArray[i].m.planes[j].m.mem_offset);
  721. decodeTestContext->InputBufArray[i].length[j] = decodeTestContext->InputV4L2BufArray[i].m.planes[j].length;
  722. decodeTestContext->InputBufArray[i].start[j] = v4l2_mmap(NULL, /* start anywhere */
  723. decodeTestContext->InputV4L2BufArray[i].m.planes[j].length, PROT_READ | PROT_WRITE, /* required */
  724. MAP_SHARED, /* recommended */
  725. decodeTestContext->fd, decodeTestContext->InputV4L2BufArray[i].m.planes[j].m.mem_offset);
  726. if (MAP_FAILED == decodeTestContext->InputBufArray[i].start[j]) {
  727. printf("map fail %d\n",i);
  728. goto end;
  729. }
  730. }
  731. if(!FillInputBuffer(decodeTestContext, &decodeTestContext->InputV4L2BufArray[i], 0)){
  732. bitsteamEnd = true;
  733. }
  734. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_QBUF, &decodeTestContext->InputV4L2BufArray[i])) {
  735. printf("VIDIOC_QBUF fail\n");
  736. goto end;
  737. }
  738. }
  739. printf("start src stream\n");
  740. type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
  741. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_STREAMON, &type)) {
  742. printf("start src stream fail\n");
  743. goto end;
  744. }
  745. mainloop();
  746. printf("stop src stream\n");
  747. type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
  748. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_STREAMOFF, &type)) {
  749. printf("stop src stream fail\n");
  750. goto end;
  751. }
  752. printf("stop dist stream\n");
  753. type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
  754. if (-1 == xioctl(decodeTestContext->fd, VIDIOC_STREAMOFF, &type)) {
  755. printf("stop dist stream fail\n");
  756. goto end;
  757. }
  758. v4l2_close(decodeTestContext->fd);
  759. end:
  760. /*free resource*/
  761. if (fb)
  762. fclose(fb);
  763. avformat_close_input(&avContext);
  764. avformat_free_context(avContext);
  765. }