38
38
EXTERN_C const CLSID CLSID_NullRenderer;
39
39
EXTERN_C const CLSID CLSID_SampleGrabber;
40
40
41
+ typedef void (*convert_t )(int width, int height, const unsigned char *in,
42
+ unsigned char *out);
43
+
41
44
using namespace std ;
42
45
43
46
static void DeleteMediaType (AM_MEDIA_TYPE *mediaType);
44
47
static const CHAR * GetSubtypeName (const GUID *pSubtype);
45
48
static codec_t get_ug_codec (const GUID *pSubtype);
49
+ static convert_t get_conversion (const GUID *pSubtype);
46
50
static codec_t get_ug_from_subtype_name (const char *subtype_name);
47
51
static void vidcap_dshow_probe (device_info **available_cards, int *count, void (**deleter)(void *));
48
52
@@ -74,6 +78,7 @@ struct vidcap_dshow_state {
74
78
int modeNumber;
75
79
struct video_desc desc;
76
80
bool convert_YUYV_RGB; // /< @todo check - currently newer set
81
+ convert_t convert;
77
82
78
83
struct video_frame *frame;
79
84
long grabBufferLen;
@@ -143,8 +148,10 @@ class SampleGrabberCallback : public ISampleGrabberCB {
143
148
if (len <= 0 ) return S_OK;
144
149
145
150
EnterCriticalSection (&s->returnBufferCS );
146
- if (s->grabBufferLen != len) {
147
- s->grabBuffer = (BYTE *) realloc ((void *) s->grabBuffer , len * sizeof (BYTE));
151
+ const long req_len = vc_get_datalen (
152
+ s->desc .width , s->desc .height , s->desc .color_spec );
153
+ if (s->grabBufferLen != req_len) {
154
+ s->grabBuffer = (BYTE *) realloc ((void *) s->grabBuffer , req_len);
148
155
if (s->grabBuffer == NULL ) {
149
156
s->grabBufferLen = 0 ;
150
157
return S_OK;
@@ -156,7 +163,9 @@ class SampleGrabberCallback : public ISampleGrabberCB {
156
163
// Apparently DirectShow uses bottom-to-top line ordering so we want make
157
164
// it top-to-bottom
158
165
int linesize = vc_get_linesize (s->desc .width , s->desc .color_spec );
159
- if (s->desc .color_spec == BGR) {
166
+ if (s->convert != nullptr ) {
167
+ s->convert (s->desc .width , s->desc .height , buffer, s->grabBuffer );
168
+ } else if (s->desc .color_spec == BGR) {
160
169
for (unsigned int i = 0 ; i < s->desc .height ; ++i) {
161
170
memcpy ((char *) s->grabBuffer + i * linesize,
162
171
(char *) buffer + (s->desc .height - i - 1 ) * linesize,
@@ -1006,6 +1015,7 @@ static int vidcap_dshow_init(struct vidcap_params *params, void **state) {
1006
1015
}
1007
1016
res = s->streamConfig ->SetFormat (mediaType);
1008
1017
HANDLE_ERR (res, " Cannot set capture format" );
1018
+ s->convert = get_conversion (&mediaType->subtype );
1009
1019
DeleteMediaType (mediaType);
1010
1020
1011
1021
if (s->convert_YUYV_RGB ) {
@@ -1215,6 +1225,25 @@ static void DeleteMediaType(AM_MEDIA_TYPE *pmt) {
1215
1225
CoTaskMemFree ((PVOID)pmt);
1216
1226
}
1217
1227
1228
+ void
1229
+ nv12_to_uyvy (int width, int height, const unsigned char *in, unsigned char *out)
1230
+ {
1231
+ const int uyvy_linesize = vc_get_linesize (width, UYVY);
1232
+ for (int y = 0 ; y < height; ++y) {
1233
+ const unsigned char *src_y = in + width * y;
1234
+ const unsigned char *src_cbcr = in + width * height;
1235
+ unsigned char *dst = out + y * uyvy_linesize;
1236
+
1237
+ OPTIMIZED_FOR (int x = 0 ; x < width / 2 ; ++x)
1238
+ {
1239
+ *dst++ = *src_cbcr++;
1240
+ *dst++ = *src_y++;
1241
+ *dst++ = *src_cbcr++;
1242
+ *dst++ = *src_y++;
1243
+ }
1244
+ }
1245
+ }
1246
+
1218
1247
static GUID GUID_R210 = {0x30313272 , 0x0000 , 0x10 , {0x80 ,0x0 ,0x0 ,0xAA ,0x0 ,0x38 ,0x9B ,0x71 }};
1219
1248
static GUID GUID_v210 = {0x30313276 , 0x0000 , 0x10 , {0x80 ,0x0 ,0x0 ,0xAA ,0x0 ,0x38 ,0x9B ,0x71 }};
1220
1249
static GUID GUID_V210 = {0x30313256 , 0x0000 , 0x10 , {0x80 ,0x0 ,0x0 ,0xAA ,0x0 ,0x38 ,0x9B ,0x71 }};
@@ -1225,32 +1254,40 @@ static const struct {
1225
1254
const GUID *pSubtype;
1226
1255
const CHAR *pName;
1227
1256
codec_t ug_codec;
1257
+ convert_t convert;
1228
1258
} BitCountMap[] = {
1229
- {&MEDIASUBTYPE_RGB1, " RGB Monochrome" , VC_NONE},
1230
- { &MEDIASUBTYPE_RGB4, " RGB VGA" , VC_NONE},
1231
- { &MEDIASUBTYPE_RGB8, " RGB 8" , VC_NONE},
1232
- { &MEDIASUBTYPE_RGB565, " RGB 565 (16 bit)" , VC_NONE},
1233
- { &MEDIASUBTYPE_RGB555, " RGB 555 (16 bit)" , VC_NONE},
1234
- { &MEDIASUBTYPE_RGB24, " RGB 24" , BGR },
1235
- { &MEDIASUBTYPE_RGB32, " RGB 32" , RGBA },
1236
- { &MEDIASUBTYPE_ARGB32, " ARGB 32" , VC_NONE},
1237
- { &MEDIASUBTYPE_Overlay, " Overlay" , VC_NONE},
1238
- { &GUID_I420, " I420" , VC_NONE},
1239
- { &MEDIASUBTYPE_YUY2, " YUY2" , YUYV },
1240
- { &GUID_R210, " r210" , VC_NONE},
1241
- { &GUID_v210, " v210" , v210 },
1242
- { &GUID_V210, " V210" , v210 },
1243
- { &MEDIASUBTYPE_UYVY, " UYVY" , UYVY },
1244
- { &GUID_HDYC, " HDYC" , UYVY },
1245
- { &MEDIASUBTYPE_MJPG, " MJPG" , MJPG },
1246
- { &GUID_NULL, " UNKNOWN" , VC_NONE},
1259
+ {&MEDIASUBTYPE_RGB1, " RGB Monochrome" , VC_NONE, nullptr },
1260
+ { &MEDIASUBTYPE_RGB4, " RGB VGA" , VC_NONE, nullptr },
1261
+ { &MEDIASUBTYPE_RGB8, " RGB 8" , VC_NONE, nullptr },
1262
+ { &MEDIASUBTYPE_RGB565, " RGB 565 (16 bit)" , VC_NONE, nullptr },
1263
+ { &MEDIASUBTYPE_RGB555, " RGB 555 (16 bit)" , VC_NONE, nullptr },
1264
+ { &MEDIASUBTYPE_RGB24, " RGB 24" , BGR, nullptr },
1265
+ { &MEDIASUBTYPE_RGB32, " RGB 32" , RGBA, nullptr },
1266
+ { &MEDIASUBTYPE_ARGB32, " ARGB 32" , VC_NONE, nullptr },
1267
+ { &MEDIASUBTYPE_Overlay, " Overlay" , VC_NONE, nullptr },
1268
+ { &GUID_I420, " I420" , VC_NONE, nullptr },
1269
+ { &MEDIASUBTYPE_YUY2, " YUY2" , YUYV, nullptr },
1270
+ { &GUID_R210, " r210" , VC_NONE, nullptr },
1271
+ { &GUID_v210, " v210" , v210, nullptr },
1272
+ { &GUID_V210, " V210" , v210, nullptr },
1273
+ { &MEDIASUBTYPE_UYVY, " UYVY" , UYVY, nullptr },
1274
+ { &GUID_HDYC, " HDYC" , UYVY, nullptr },
1275
+ { &MEDIASUBTYPE_MJPG, " MJPG" , MJPG, nullptr },
1276
+ { &MEDIASUBTYPE_NV12, " NV12" , UYVY, nv12_to_uyvy},
1277
+ { &GUID_NULL, " UNKNOWN" , VC_NONE, nullptr },
1247
1278
};
1248
1279
1249
1280
static codec_t get_ug_codec (const GUID *pSubtype)
1250
1281
{
1251
1282
return BitCountMap[LocateSubtype (pSubtype)].ug_codec ;
1252
1283
}
1253
1284
1285
+ static convert_t
1286
+ get_conversion (const GUID *pSubtype)
1287
+ {
1288
+ return BitCountMap[LocateSubtype (pSubtype)].convert ;
1289
+ }
1290
+
1254
1291
static codec_t get_ug_from_subtype_name (const char *subtype_name) {
1255
1292
for (unsigned int i = 0 ; i < sizeof BitCountMap / sizeof BitCountMap[0 ]; ++i) {
1256
1293
if (strcmp (BitCountMap[i].pName , subtype_name) == 0 ) {
0 commit comments