+ return AV_CODEC_ID_NONE;
+}
+
+#if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE
+static void list_framesizes(AVFormatContext *ctx, int fd, uint32_t pixelformat)
+{
+ struct v4l2_frmsizeenum vfse = { .pixel_format = pixelformat };
+
+ while(!ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &vfse)) {
+ switch (vfse.type) {
+ case V4L2_FRMSIZE_TYPE_DISCRETE:
+ av_log(ctx, AV_LOG_INFO, " %ux%u",
+ vfse.discrete.width, vfse.discrete.height);
+ break;
+ case V4L2_FRMSIZE_TYPE_CONTINUOUS:
+ case V4L2_FRMSIZE_TYPE_STEPWISE:
+ av_log(ctx, AV_LOG_INFO, " {%u-%u, %u}x{%u-%u, %u}",
+ vfse.stepwise.min_width,
+ vfse.stepwise.max_width,
+ vfse.stepwise.step_width,
+ vfse.stepwise.min_height,
+ vfse.stepwise.max_height,
+ vfse.stepwise.step_height);
+ }
+ vfse.index++;
+ }
+}
+#endif
+
+static void list_formats(AVFormatContext *ctx, int fd, int type)
+{
+ struct v4l2_fmtdesc vfd = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
+
+ while(!ioctl(fd, VIDIOC_ENUM_FMT, &vfd)) {
+ enum AVCodecID codec_id = fmt_v4l2codec(vfd.pixelformat);
+ enum AVPixelFormat pix_fmt = fmt_v4l2ff(vfd.pixelformat, codec_id);
+
+ vfd.index++;
+
+ if (!(vfd.flags & V4L2_FMT_FLAG_COMPRESSED) &&
+ type & V4L_RAWFORMATS) {
+ const char *fmt_name = av_get_pix_fmt_name(pix_fmt);
+ av_log(ctx, AV_LOG_INFO, "R : %9s : %20s :",
+ fmt_name ? fmt_name : "Unsupported",
+ vfd.description);
+ } else if (vfd.flags & V4L2_FMT_FLAG_COMPRESSED &&
+ type & V4L_COMPFORMATS) {
+ const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id);
+ av_log(ctx, AV_LOG_INFO, "C : %9s : %20s :",
+ desc ? desc->name : "Unsupported",
+ vfd.description);
+ } else {
+ continue;
+ }
+
+#ifdef V4L2_FMT_FLAG_EMULATED
+ if (vfd.flags & V4L2_FMT_FLAG_EMULATED) {
+ av_log(ctx, AV_LOG_WARNING, "%s", "Emulated");
+ continue;
+ }
+#endif
+#if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE
+ list_framesizes(ctx, fd, vfd.pixelformat);
+#endif
+ av_log(ctx, AV_LOG_INFO, "\n");
+ }