visl-core.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * A virtual stateless decoder device for stateless uAPI development purposes.
  4. *
  5. * This tool's objective is to help the development and testing of userspace
  6. * applications that use the V4L2 stateless API to decode media.
  7. *
  8. * A userspace implementation can use visl to run a decoding loop even when no
  9. * hardware is available or when the kernel uAPI for the codec has not been
  10. * upstreamed yet. This can reveal bugs at an early stage.
  11. *
  12. * This driver can also trace the contents of the V4L2 controls submitted to it.
  13. * It can also dump the contents of the vb2 buffers through a debugfs
  14. * interface. This is in many ways similar to the tracing infrastructure
  15. * available for other popular encode/decode APIs out there and can help develop
  16. * a userspace application by using another (working) one as a reference.
  17. *
  18. * Note that no actual decoding of video frames is performed by visl. The V4L2
  19. * test pattern generator is used to write various debug information to the
  20. * capture buffers instead.
  21. *
  22. * Copyright (C) 2022 Collabora, Ltd.
  23. *
  24. * Based on the vim2m driver, that is:
  25. *
  26. * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
  27. * Pawel Osciak, <pawel@osciak.com>
  28. * Marek Szyprowski, <m.szyprowski@samsung.com>
  29. *
  30. * Based on the vicodec driver, that is:
  31. *
  32. * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
  33. *
  34. * Based on the Cedrus VPU driver, that is:
  35. *
  36. * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
  37. * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
  38. * Copyright (C) 2018 Bootlin
  39. */
  40. #include <linux/debugfs.h>
  41. #include <linux/module.h>
  42. #include <linux/platform_device.h>
  43. #include <media/v4l2-ctrls.h>
  44. #include <media/v4l2-device.h>
  45. #include <media/v4l2-ioctl.h>
  46. #include <media/v4l2-mem2mem.h>
  47. #include "visl.h"
  48. #include "visl-dec.h"
  49. #include "visl-debugfs.h"
  50. #include "visl-video.h"
  51. unsigned int visl_debug;
  52. module_param(visl_debug, uint, 0644);
  53. MODULE_PARM_DESC(visl_debug, " activates debug info");
  54. unsigned int visl_transtime_ms;
  55. module_param(visl_transtime_ms, uint, 0644);
  56. MODULE_PARM_DESC(visl_transtime_ms, " simulated process time in milliseconds.");
  57. /*
  58. * dprintk can be slow through serial. This lets one limit the tracing to a
  59. * particular number of frames
  60. */
  61. int visl_dprintk_frame_start = -1;
  62. module_param(visl_dprintk_frame_start, int, 0444);
  63. MODULE_PARM_DESC(visl_dprintk_frame_start,
  64. " a frame number to start tracing with dprintk");
  65. unsigned int visl_dprintk_nframes;
  66. module_param(visl_dprintk_nframes, uint, 0444);
  67. MODULE_PARM_DESC(visl_dprintk_nframes,
  68. " the number of frames to trace with dprintk");
  69. bool keep_bitstream_buffers;
  70. module_param(keep_bitstream_buffers, bool, 0444);
  71. MODULE_PARM_DESC(keep_bitstream_buffers,
  72. " keep bitstream buffers in debugfs after streaming is stopped");
  73. int bitstream_trace_frame_start = -1;
  74. module_param(bitstream_trace_frame_start, int, 0444);
  75. MODULE_PARM_DESC(bitstream_trace_frame_start,
  76. " a frame number to start dumping the bitstream through debugfs");
  77. unsigned int bitstream_trace_nframes;
  78. module_param(bitstream_trace_nframes, uint, 0444);
  79. MODULE_PARM_DESC(bitstream_trace_nframes,
  80. " the number of frames to dump the bitstream through debugfs");
  81. bool tpg_verbose;
  82. module_param(tpg_verbose, bool, 0644);
  83. MODULE_PARM_DESC(tpg_verbose,
  84. " add more verbose information on the generated output frames");
  85. static const struct visl_ctrl_desc visl_fwht_ctrl_descs[] = {
  86. {
  87. .cfg.id = V4L2_CID_STATELESS_FWHT_PARAMS,
  88. },
  89. };
  90. const struct visl_ctrls visl_fwht_ctrls = {
  91. .ctrls = visl_fwht_ctrl_descs,
  92. .num_ctrls = ARRAY_SIZE(visl_fwht_ctrl_descs)
  93. };
  94. static const struct visl_ctrl_desc visl_mpeg2_ctrl_descs[] = {
  95. {
  96. .cfg.id = V4L2_CID_STATELESS_MPEG2_SEQUENCE,
  97. },
  98. {
  99. .cfg.id = V4L2_CID_STATELESS_MPEG2_PICTURE,
  100. },
  101. {
  102. .cfg.id = V4L2_CID_STATELESS_MPEG2_QUANTISATION,
  103. },
  104. };
  105. const struct visl_ctrls visl_mpeg2_ctrls = {
  106. .ctrls = visl_mpeg2_ctrl_descs,
  107. .num_ctrls = ARRAY_SIZE(visl_mpeg2_ctrl_descs),
  108. };
  109. static const struct visl_ctrl_desc visl_vp8_ctrl_descs[] = {
  110. {
  111. .cfg.id = V4L2_CID_STATELESS_VP8_FRAME,
  112. },
  113. };
  114. const struct visl_ctrls visl_vp8_ctrls = {
  115. .ctrls = visl_vp8_ctrl_descs,
  116. .num_ctrls = ARRAY_SIZE(visl_vp8_ctrl_descs),
  117. };
  118. static const struct visl_ctrl_desc visl_vp9_ctrl_descs[] = {
  119. {
  120. .cfg.id = V4L2_CID_STATELESS_VP9_FRAME,
  121. },
  122. {
  123. .cfg.id = V4L2_CID_STATELESS_VP9_COMPRESSED_HDR,
  124. },
  125. };
  126. const struct visl_ctrls visl_vp9_ctrls = {
  127. .ctrls = visl_vp9_ctrl_descs,
  128. .num_ctrls = ARRAY_SIZE(visl_vp9_ctrl_descs),
  129. };
  130. static const struct visl_ctrl_desc visl_h264_ctrl_descs[] = {
  131. {
  132. .cfg.id = V4L2_CID_STATELESS_H264_DECODE_PARAMS,
  133. },
  134. {
  135. .cfg.id = V4L2_CID_STATELESS_H264_SPS,
  136. },
  137. {
  138. .cfg.id = V4L2_CID_STATELESS_H264_PPS,
  139. },
  140. {
  141. .cfg.id = V4L2_CID_STATELESS_H264_SCALING_MATRIX,
  142. },
  143. {
  144. .cfg.id = V4L2_CID_STATELESS_H264_DECODE_MODE,
  145. .cfg.min = V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED,
  146. .cfg.max = V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED,
  147. .cfg.def = V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED,
  148. },
  149. {
  150. .cfg.id = V4L2_CID_STATELESS_H264_START_CODE,
  151. .cfg.min = V4L2_STATELESS_H264_START_CODE_NONE,
  152. .cfg.max = V4L2_STATELESS_H264_START_CODE_ANNEX_B,
  153. .cfg.def = V4L2_STATELESS_H264_START_CODE_NONE,
  154. },
  155. {
  156. .cfg.id = V4L2_CID_STATELESS_H264_SLICE_PARAMS,
  157. },
  158. {
  159. .cfg.id = V4L2_CID_STATELESS_H264_PRED_WEIGHTS,
  160. },
  161. };
  162. const struct visl_ctrls visl_h264_ctrls = {
  163. .ctrls = visl_h264_ctrl_descs,
  164. .num_ctrls = ARRAY_SIZE(visl_h264_ctrl_descs),
  165. };
  166. static const struct visl_ctrl_desc visl_hevc_ctrl_descs[] = {
  167. {
  168. .cfg.id = V4L2_CID_STATELESS_HEVC_SPS,
  169. },
  170. {
  171. .cfg.id = V4L2_CID_STATELESS_HEVC_PPS,
  172. },
  173. {
  174. .cfg.id = V4L2_CID_STATELESS_HEVC_SLICE_PARAMS,
  175. /* The absolute maximum for level > 6 */
  176. .cfg.dims = { 600 },
  177. },
  178. {
  179. .cfg.id = V4L2_CID_STATELESS_HEVC_SCALING_MATRIX,
  180. },
  181. {
  182. .cfg.id = V4L2_CID_STATELESS_HEVC_DECODE_PARAMS,
  183. },
  184. {
  185. .cfg.id = V4L2_CID_STATELESS_HEVC_DECODE_MODE,
  186. .cfg.min = V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED,
  187. .cfg.max = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED,
  188. .cfg.def = V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED,
  189. },
  190. {
  191. .cfg.id = V4L2_CID_STATELESS_HEVC_START_CODE,
  192. .cfg.min = V4L2_STATELESS_HEVC_START_CODE_NONE,
  193. .cfg.max = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B,
  194. .cfg.def = V4L2_STATELESS_HEVC_START_CODE_NONE,
  195. },
  196. {
  197. .cfg.id = V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS,
  198. .cfg.dims = { 256 },
  199. .cfg.max = 0xffffffff,
  200. .cfg.step = 1,
  201. },
  202. };
  203. const struct visl_ctrls visl_hevc_ctrls = {
  204. .ctrls = visl_hevc_ctrl_descs,
  205. .num_ctrls = ARRAY_SIZE(visl_hevc_ctrl_descs),
  206. };
  207. static const struct visl_ctrl_desc visl_av1_ctrl_descs[] = {
  208. {
  209. .cfg.id = V4L2_CID_STATELESS_AV1_FRAME,
  210. },
  211. {
  212. .cfg.id = V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY,
  213. .cfg.dims = { V4L2_AV1_MAX_TILE_COUNT },
  214. },
  215. {
  216. .cfg.id = V4L2_CID_STATELESS_AV1_SEQUENCE,
  217. },
  218. {
  219. .cfg.id = V4L2_CID_STATELESS_AV1_FILM_GRAIN,
  220. },
  221. };
  222. const struct visl_ctrls visl_av1_ctrls = {
  223. .ctrls = visl_av1_ctrl_descs,
  224. .num_ctrls = ARRAY_SIZE(visl_av1_ctrl_descs),
  225. };
  226. struct v4l2_ctrl *visl_find_control(struct visl_ctx *ctx, u32 id)
  227. {
  228. struct v4l2_ctrl_handler *hdl = &ctx->hdl;
  229. return v4l2_ctrl_find(hdl, id);
  230. }
  231. void *visl_find_control_data(struct visl_ctx *ctx, u32 id)
  232. {
  233. struct v4l2_ctrl *ctrl;
  234. ctrl = visl_find_control(ctx, id);
  235. if (ctrl)
  236. return ctrl->p_cur.p;
  237. return NULL;
  238. }
  239. u32 visl_control_num_elems(struct visl_ctx *ctx, u32 id)
  240. {
  241. struct v4l2_ctrl *ctrl;
  242. ctrl = visl_find_control(ctx, id);
  243. if (ctrl)
  244. return ctrl->elems;
  245. return 0;
  246. }
  247. static void visl_device_release(struct video_device *vdev)
  248. {
  249. struct visl_dev *dev = container_of(vdev, struct visl_dev, vfd);
  250. v4l2_device_unregister(&dev->v4l2_dev);
  251. v4l2_m2m_release(dev->m2m_dev);
  252. media_device_cleanup(&dev->mdev);
  253. visl_debugfs_deinit(dev);
  254. kfree(dev);
  255. }
  256. #define VISL_CONTROLS_COUNT ARRAY_SIZE(visl_controls)
  257. static int visl_init_ctrls(struct visl_ctx *ctx)
  258. {
  259. struct visl_dev *dev = ctx->dev;
  260. struct v4l2_ctrl_handler *hdl = &ctx->hdl;
  261. unsigned int ctrl_cnt = 0;
  262. unsigned int i;
  263. unsigned int j;
  264. const struct visl_ctrls *ctrls;
  265. for (i = 0; i < num_coded_fmts; i++)
  266. ctrl_cnt += visl_coded_fmts[i].ctrls->num_ctrls;
  267. v4l2_ctrl_handler_init(hdl, ctrl_cnt);
  268. for (i = 0; i < num_coded_fmts; i++) {
  269. ctrls = visl_coded_fmts[i].ctrls;
  270. for (j = 0; j < ctrls->num_ctrls; j++)
  271. v4l2_ctrl_new_custom(hdl, &ctrls->ctrls[j].cfg, NULL);
  272. }
  273. if (hdl->error) {
  274. v4l2_err(&dev->v4l2_dev,
  275. "Failed to initialize control handler\n");
  276. v4l2_ctrl_handler_free(hdl);
  277. return hdl->error;
  278. }
  279. ctx->fh.ctrl_handler = hdl;
  280. v4l2_ctrl_handler_setup(hdl);
  281. return 0;
  282. }
  283. static int visl_open(struct file *file)
  284. {
  285. struct visl_dev *dev = video_drvdata(file);
  286. struct visl_ctx *ctx = NULL;
  287. int rc = 0;
  288. if (mutex_lock_interruptible(&dev->dev_mutex))
  289. return -ERESTARTSYS;
  290. ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
  291. if (!ctx) {
  292. rc = -ENOMEM;
  293. goto unlock;
  294. }
  295. ctx->tpg_str_buf = kzalloc(TPG_STR_BUF_SZ, GFP_KERNEL);
  296. v4l2_fh_init(&ctx->fh, video_devdata(file));
  297. file->private_data = &ctx->fh;
  298. ctx->dev = dev;
  299. rc = visl_init_ctrls(ctx);
  300. if (rc)
  301. goto free_ctx;
  302. ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &visl_queue_init);
  303. mutex_init(&ctx->vb_mutex);
  304. if (IS_ERR(ctx->fh.m2m_ctx)) {
  305. rc = PTR_ERR(ctx->fh.m2m_ctx);
  306. goto free_hdl;
  307. }
  308. rc = visl_set_default_format(ctx);
  309. if (rc)
  310. goto free_m2m_ctx;
  311. v4l2_fh_add(&ctx->fh);
  312. dprintk(dev, "Created instance: %p, m2m_ctx: %p\n",
  313. ctx, ctx->fh.m2m_ctx);
  314. mutex_unlock(&dev->dev_mutex);
  315. return rc;
  316. free_m2m_ctx:
  317. v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
  318. free_hdl:
  319. v4l2_ctrl_handler_free(&ctx->hdl);
  320. v4l2_fh_exit(&ctx->fh);
  321. free_ctx:
  322. kfree(ctx->tpg_str_buf);
  323. kfree(ctx);
  324. unlock:
  325. mutex_unlock(&dev->dev_mutex);
  326. return rc;
  327. }
  328. static int visl_release(struct file *file)
  329. {
  330. struct visl_dev *dev = video_drvdata(file);
  331. struct visl_ctx *ctx = visl_file_to_ctx(file);
  332. dprintk(dev, "Releasing instance %p\n", ctx);
  333. tpg_free(&ctx->tpg);
  334. v4l2_fh_del(&ctx->fh);
  335. v4l2_fh_exit(&ctx->fh);
  336. v4l2_ctrl_handler_free(&ctx->hdl);
  337. mutex_lock(&dev->dev_mutex);
  338. v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
  339. mutex_unlock(&dev->dev_mutex);
  340. kfree(ctx->tpg_str_buf);
  341. kfree(ctx);
  342. return 0;
  343. }
  344. static const struct v4l2_file_operations visl_fops = {
  345. .owner = THIS_MODULE,
  346. .open = visl_open,
  347. .release = visl_release,
  348. .poll = v4l2_m2m_fop_poll,
  349. .unlocked_ioctl = video_ioctl2,
  350. .mmap = v4l2_m2m_fop_mmap,
  351. };
  352. static const struct video_device visl_videodev = {
  353. .name = VISL_NAME,
  354. .vfl_dir = VFL_DIR_M2M,
  355. .fops = &visl_fops,
  356. .ioctl_ops = &visl_ioctl_ops,
  357. .minor = -1,
  358. .release = visl_device_release,
  359. .device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING,
  360. };
  361. static const struct v4l2_m2m_ops visl_m2m_ops = {
  362. .device_run = visl_device_run,
  363. };
  364. static const struct media_device_ops visl_m2m_media_ops = {
  365. .req_validate = visl_request_validate,
  366. .req_queue = v4l2_m2m_request_queue,
  367. };
  368. static int visl_probe(struct platform_device *pdev)
  369. {
  370. struct visl_dev *dev;
  371. struct video_device *vfd;
  372. int ret;
  373. int rc;
  374. dev = kzalloc(sizeof(*dev), GFP_KERNEL);
  375. if (!dev)
  376. return -ENOMEM;
  377. ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
  378. if (ret)
  379. goto error_visl_dev;
  380. mutex_init(&dev->dev_mutex);
  381. dev->vfd = visl_videodev;
  382. vfd = &dev->vfd;
  383. vfd->lock = &dev->dev_mutex;
  384. vfd->v4l2_dev = &dev->v4l2_dev;
  385. video_set_drvdata(vfd, dev);
  386. platform_set_drvdata(pdev, dev);
  387. dev->m2m_dev = v4l2_m2m_init(&visl_m2m_ops);
  388. if (IS_ERR(dev->m2m_dev)) {
  389. v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
  390. ret = PTR_ERR(dev->m2m_dev);
  391. dev->m2m_dev = NULL;
  392. goto error_dev;
  393. }
  394. dev->mdev.dev = &pdev->dev;
  395. strscpy(dev->mdev.model, "visl", sizeof(dev->mdev.model));
  396. strscpy(dev->mdev.bus_info, "platform:visl",
  397. sizeof(dev->mdev.bus_info));
  398. media_device_init(&dev->mdev);
  399. dev->mdev.ops = &visl_m2m_media_ops;
  400. dev->v4l2_dev.mdev = &dev->mdev;
  401. ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1);
  402. if (ret) {
  403. v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
  404. goto error_m2m;
  405. }
  406. v4l2_info(&dev->v4l2_dev,
  407. "Device registered as /dev/video%d\n", vfd->num);
  408. ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd,
  409. MEDIA_ENT_F_PROC_VIDEO_DECODER);
  410. if (ret) {
  411. v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller\n");
  412. goto error_v4l2;
  413. }
  414. ret = media_device_register(&dev->mdev);
  415. if (ret) {
  416. v4l2_err(&dev->v4l2_dev, "Failed to register mem2mem media device\n");
  417. goto error_m2m_mc;
  418. }
  419. rc = visl_debugfs_init(dev);
  420. if (rc)
  421. dprintk(dev, "visl_debugfs_init failed: %d\n"
  422. "Continuing without debugfs support\n", rc);
  423. return 0;
  424. error_m2m_mc:
  425. v4l2_m2m_unregister_media_controller(dev->m2m_dev);
  426. error_v4l2:
  427. video_unregister_device(&dev->vfd);
  428. /* visl_device_release called by video_unregister_device to release various objects */
  429. return ret;
  430. error_m2m:
  431. v4l2_m2m_release(dev->m2m_dev);
  432. error_dev:
  433. v4l2_device_unregister(&dev->v4l2_dev);
  434. error_visl_dev:
  435. kfree(dev);
  436. return ret;
  437. }
  438. static void visl_remove(struct platform_device *pdev)
  439. {
  440. struct visl_dev *dev = platform_get_drvdata(pdev);
  441. v4l2_info(&dev->v4l2_dev, "Removing " VISL_NAME);
  442. #ifdef CONFIG_MEDIA_CONTROLLER
  443. if (media_devnode_is_registered(dev->mdev.devnode)) {
  444. media_device_unregister(&dev->mdev);
  445. v4l2_m2m_unregister_media_controller(dev->m2m_dev);
  446. }
  447. #endif
  448. video_unregister_device(&dev->vfd);
  449. }
  450. static struct platform_driver visl_pdrv = {
  451. .probe = visl_probe,
  452. .remove_new = visl_remove,
  453. .driver = {
  454. .name = VISL_NAME,
  455. },
  456. };
  457. static void visl_dev_release(struct device *dev) {}
  458. static struct platform_device visl_pdev = {
  459. .name = VISL_NAME,
  460. .dev.release = visl_dev_release,
  461. };
  462. static void __exit visl_exit(void)
  463. {
  464. platform_driver_unregister(&visl_pdrv);
  465. platform_device_unregister(&visl_pdev);
  466. }
  467. static int __init visl_init(void)
  468. {
  469. int ret;
  470. ret = platform_device_register(&visl_pdev);
  471. if (ret)
  472. return ret;
  473. ret = platform_driver_register(&visl_pdrv);
  474. if (ret)
  475. platform_device_unregister(&visl_pdev);
  476. return ret;
  477. }
  478. MODULE_DESCRIPTION("Virtual stateless decoder device");
  479. MODULE_AUTHOR("Daniel Almeida <daniel.almeida@collabora.com>");
  480. MODULE_LICENSE("GPL");
  481. module_init(visl_init);
  482. module_exit(visl_exit);