PR #23607 opened by hit-labvn
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23607
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23607.patch

Some DirectShow devices report uncompressed RGB formats with RGB555, RGB565, 
RGB24, or RGB32 media subtype values instead of BI_RGB or BI_BITFIELDS. FFmpeg 
currently treats those subtypes as unsupported, so capture from such devices 
fails even though the frames are raw RGB.

Map those values to rawvideo pixel formats and include them in the bottom-up 
RGB handling. Clear codec_tag once the subtype has been translated so rawvideo 
receives the selected pixel format instead of the DirectShow subtype.

Signed-off-by: Hao Truong <[email protected]>

# Summary of changes

Briefly describe what this PR does and why.

<!--
If this PR requires new FATE test samples, attach them to the PR and
list their target paths below (relative to the fate-suite root).

Attached filenames must match the sample's filename:

```fate-samples
# e.g. vorbis/new-sample.ogg
```
-->



>From a50a6feba200d76f529d2b899fe9ed84a05fbe2f Mon Sep 17 00:00:00 2001
From: Hao Truong <[email protected]>
Date: Fri, 26 Jun 2026 23:18:34 +0700
Subject: [PATCH] avdevice/dshow: handle DirectShow RGB media subtypes

Some DirectShow devices report uncompressed RGB formats with RGB555, RGB565, 
RGB24, or RGB32 media subtype values instead of BI_RGB or BI_BITFIELDS. FFmpeg 
currently treats those subtypes as unsupported, so capture from such devices 
fails even though the frames are raw RGB.

Map those values to rawvideo pixel formats and include them in the bottom-up 
RGB handling. Clear codec_tag once the subtype has been translated so rawvideo 
receives the selected pixel format instead of the DirectShow subtype.

Signed-off-by: Hao Truong <[email protected]>
---
 libavdevice/dshow.c | 31 +++++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
index 6e97304850..6a555846b7 100644
--- a/libavdevice/dshow.c
+++ b/libavdevice/dshow.c
@@ -56,6 +56,10 @@
 #   define AMCONTROL_COLORINFO_PRESENT 0x00000080 // if set, indicates DXVA 
color info is present in the upper (24) bits of the dwControlFlags
 #endif
 
+#define DSHOW_MEDIASUBTYPE_RGB565 0xe436eb7b
+#define DSHOW_MEDIASUBTYPE_RGB555 0xe436eb7c
+#define DSHOW_MEDIASUBTYPE_RGB24  0xe436eb7d
+#define DSHOW_MEDIASUBTYPE_RGB32  0xe436eb7e
 
 static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount)
 {
@@ -76,10 +80,33 @@ static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, 
WORD biBitCount)
             case 32:
                 return AV_PIX_FMT_0RGB32;
         }
+    case DSHOW_MEDIASUBTYPE_RGB565:
+        return AV_PIX_FMT_RGB565;
+    case DSHOW_MEDIASUBTYPE_RGB555:
+        return AV_PIX_FMT_RGB555;
+    case DSHOW_MEDIASUBTYPE_RGB24:
+        return AV_PIX_FMT_BGR24;
+    case DSHOW_MEDIASUBTYPE_RGB32:
+        return AV_PIX_FMT_0RGB32;
     }
     return avpriv_pix_fmt_find(PIX_FMT_LIST_RAW, biCompression); // all others
 }
 
+static int dshow_is_bottomup_rgb(DWORD biCompression)
+{
+    switch (biCompression) {
+    case BI_RGB:
+    case BI_BITFIELDS:
+    case DSHOW_MEDIASUBTYPE_RGB565:
+    case DSHOW_MEDIASUBTYPE_RGB555:
+    case DSHOW_MEDIASUBTYPE_RGB24:
+    case DSHOW_MEDIASUBTYPE_RGB32:
+        return 1;
+    default:
+        return 0;
+    }
+}
+
 static enum AVColorRange dshow_color_range(DXVA2_ExtendedFormat *fmt_info)
 {
     switch (fmt_info->NominalRange)
@@ -1581,7 +1608,7 @@ dshow_add_device(AVFormatContext *avctx,
         par->codec_type = AVMEDIA_TYPE_VIDEO;
         par->width      = fmt_info->width;
         par->height     = fmt_info->height;
-        par->codec_tag  = bih->biCompression;
+        par->codec_tag  = fmt_info->pix_fmt == AV_PIX_FMT_NONE ? 
bih->biCompression : 0;
         par->format     = fmt_info->pix_fmt;
         if (bih->biCompression == MKTAG('H', 'D', 'Y', 'C')) {
             av_log(avctx, AV_LOG_DEBUG, "attempt to use full range for 
HDYC...\n");
@@ -1594,7 +1621,7 @@ dshow_add_device(AVFormatContext *avctx,
         par->chroma_location = fmt_info->chroma_loc;
         par->codec_id = fmt_info->codec_id;
         if (par->codec_id == AV_CODEC_ID_RAWVIDEO) {
-            if (bih->biCompression == BI_RGB || bih->biCompression == 
BI_BITFIELDS) {
+            if (dshow_is_bottomup_rgb(bih->biCompression)) {
                 par->bits_per_coded_sample = bih->biBitCount;
                 if (par->height < 0) {
                     par->height *= -1;
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to