From 23feac132328876557353731655679eb5e06b42b Mon Sep 17 00:00:00 2001 From: Kurt Kartaltepe Date: Mon, 14 Feb 2022 17:14:02 -0800 Subject: [PATCH] linux-v4l2: Use decoded MJPEG pixel format Previously we assumed mjpeg was always decoded to 422 but it seems some cameras provide frames that decode to different pixel formats such as 420. This change delays setting the obs frame pixel format until after we have decoded the v4l2 frame. fixes #5821 --- plugins/linux-v4l2/v4l2-helpers.h | 2 -- plugins/linux-v4l2/v4l2-input.c | 13 ++++--------- plugins/linux-v4l2/v4l2-mjpeg.c | 16 +++++++++++++++- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/plugins/linux-v4l2/v4l2-helpers.h b/plugins/linux-v4l2/v4l2-helpers.h index 506dfa29d..b14d0199f 100644 --- a/plugins/linux-v4l2/v4l2-helpers.h +++ b/plugins/linux-v4l2/v4l2-helpers.h @@ -79,8 +79,6 @@ static inline enum video_format v4l2_to_obs_video_format(uint_fast32_t format) #endif case V4L2_PIX_FMT_BGR24: return VIDEO_FORMAT_BGR3; - case V4L2_PIX_FMT_MJPEG: - return VIDEO_FORMAT_I422; default: return VIDEO_FORMAT_NONE; } diff --git a/plugins/linux-v4l2/v4l2-input.c b/plugins/linux-v4l2/v4l2-input.c index f6d0a6f0c..adcbb9bae 100644 --- a/plugins/linux-v4l2/v4l2-input.c +++ b/plugins/linux-v4l2/v4l2-input.c @@ -148,13 +148,6 @@ static void v4l2_prep_obs_frame(struct v4l2_data *data, plane_offsets[1] = data->linesize * data->height; plane_offsets[2] = data->linesize * data->height * 5 / 4; break; - case V4L2_PIX_FMT_MJPEG: - frame->linesize[0] = 0; - frame->linesize[1] = 0; - frame->linesize[2] = 0; - plane_offsets[1] = 0; - plane_offsets[2] = 0; - break; default: frame->linesize[0] = data->linesize; break; @@ -479,7 +472,8 @@ static void v4l2_format_list(int dev, obs_property_t *prop) dstr_cat(&buffer, " (Emulated)"); if (v4l2_to_obs_video_format(fmt.pixelformat) != - VIDEO_FORMAT_NONE) { + VIDEO_FORMAT_NONE || + fmt.pixelformat == V4L2_PIX_FMT_MJPEG) { obs_property_list_add_int(prop, buffer.array, fmt.pixelformat); blog(LOG_INFO, "Pixelformat: %s (available)", @@ -1003,7 +997,8 @@ static void v4l2_init(struct v4l2_data *data) blog(LOG_ERROR, "Unable to set format"); goto fail; } - if (v4l2_to_obs_video_format(data->pixfmt) == VIDEO_FORMAT_NONE) { + if (v4l2_to_obs_video_format(data->pixfmt) == VIDEO_FORMAT_NONE && + data->pixfmt != V4L2_PIX_FMT_MJPEG) { blog(LOG_ERROR, "Selected video format not supported"); goto fail; } diff --git a/plugins/linux-v4l2/v4l2-mjpeg.c b/plugins/linux-v4l2/v4l2-mjpeg.c index 45b2b9193..a04293265 100644 --- a/plugins/linux-v4l2/v4l2-mjpeg.c +++ b/plugins/linux-v4l2/v4l2-mjpeg.c @@ -45,7 +45,6 @@ int v4l2_init_mjpeg(struct v4l2_mjpeg_decoder *decoder) } decoder->context->flags2 |= AV_CODEC_FLAG2_FAST; - decoder->context->pix_fmt = AV_PIX_FMT_YUVJ422P; if (avcodec_open2(decoder->context, decoder->codec, NULL) < 0) { blog(LOG_ERROR, "failed to open codec"); @@ -94,5 +93,20 @@ int v4l2_decode_mjpeg(struct obs_source_frame *out, uint8_t *data, out->linesize[i] = decoder->frame->linesize[i]; } + switch (decoder->context->pix_fmt) { + case AV_PIX_FMT_YUVJ422P: + case AV_PIX_FMT_YUV422P: + out->format = VIDEO_FORMAT_I422; + break; + case AV_PIX_FMT_YUVJ420P: + case AV_PIX_FMT_YUV420P: + out->format = VIDEO_FORMAT_I420; + break; + case AV_PIX_FMT_YUVJ444P: + case AV_PIX_FMT_YUV444P: + out->format = VIDEO_FORMAT_I444; + break; + } + return 0; }