win-dshow: Add support for YUY2 in virtualcam
parent
8b30204946
commit
18a73c9a45
|
@ -1 +1 @@
|
|||
Subproject commit 1d9685530922617778ae99f7d45ca427f67d7370
|
||||
Subproject commit 46c9b12f27f70d19c3eac45069ae0e4b37846676
|
|
@ -6,10 +6,10 @@
|
|||
* it's nearest neighbor so not really a huge deal. at the very least it
|
||||
* should be sse2 at some point. */
|
||||
|
||||
void nv12_scale_init(nv12_scale_t *s, bool convert_to_i420, int dst_cx,
|
||||
void nv12_scale_init(nv12_scale_t *s, enum target_format format, int dst_cx,
|
||||
int dst_cy, int src_cx, int src_cy)
|
||||
{
|
||||
s->convert_to_i420 = convert_to_i420;
|
||||
s->format = format;
|
||||
|
||||
s->src_cx = src_cx;
|
||||
s->src_cy = src_cy;
|
||||
|
@ -118,16 +118,89 @@ static void nv12_convert_to_i420(nv12_scale_t *s, uint8_t *dst_start,
|
|||
}
|
||||
}
|
||||
|
||||
static void nv12_scale_nearest_to_yuy2(nv12_scale_t *s, uint8_t *dst_start,
|
||||
const uint8_t *src)
|
||||
{
|
||||
register uint8_t *dst = dst_start;
|
||||
const int src_cx = s->src_cx;
|
||||
const int src_cy = s->src_cy;
|
||||
const int dst_cx = s->dst_cx;
|
||||
const int dst_cy = s->dst_cy;
|
||||
const int src_cx_d2 = src_cx / 2;
|
||||
const int src_cy_d2 = src_cy / 2;
|
||||
const int dst_cx_d2 = dst_cx / 2;
|
||||
const int dst_cy_d2 = dst_cy / 2;
|
||||
const int size = src_cx * src_cy;
|
||||
|
||||
const uint8_t *src_uv = src + size;
|
||||
|
||||
register int uv_flip = 0;
|
||||
|
||||
for (int y = 0; y < dst_cy; y++) {
|
||||
const int src_line = y * src_cy / dst_cy * s->src_cx;
|
||||
const int src_line_d2 =
|
||||
y / 2 * src_cy_d2 / dst_cy_d2 * s->src_cx;
|
||||
|
||||
for (int x = 0; x < dst_cx; x++) {
|
||||
const int src_x = x * src_cx / dst_cx;
|
||||
const int src_x_d2 = x / 2 * src_cx_d2 / dst_cx_d2;
|
||||
const int pos = src_line + src_x;
|
||||
const int pos_uv = src_line_d2 + src_x_d2 * 2 + uv_flip;
|
||||
|
||||
*(dst++) = src[pos];
|
||||
*(dst++) = src_uv[pos_uv];
|
||||
|
||||
uv_flip ^= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void nv12_convert_to_yuy2(nv12_scale_t *s, uint8_t *dst_start,
|
||||
const uint8_t *src_start)
|
||||
{
|
||||
const int size = s->src_cx * s->src_cy;
|
||||
const int size_dst_line = s->src_cx * 4;
|
||||
|
||||
register const uint8_t *src_y = src_start;
|
||||
register const uint8_t *src_uv = src_y + size;
|
||||
register uint8_t *dst = dst_start;
|
||||
register uint8_t *dst_end = dst + size * 2;
|
||||
|
||||
while (dst < dst_end) {
|
||||
register uint8_t *dst_line_end = dst + size_dst_line;
|
||||
const uint8_t *src_uv_start = src_uv;
|
||||
while (dst < dst_line_end) {
|
||||
*(dst++) = *(src_y++);
|
||||
*(dst++) = *(src_uv++);
|
||||
*(dst++) = *(src_y++);
|
||||
*(dst++) = *(src_uv++);
|
||||
}
|
||||
|
||||
dst_line_end = dst + size_dst_line;
|
||||
src_uv = src_uv_start;
|
||||
while (dst < dst_line_end) {
|
||||
*(dst++) = *(src_y++);
|
||||
*(dst++) = *(src_uv++);
|
||||
*(dst++) = *(src_y++);
|
||||
*(dst++) = *(src_uv++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nv12_do_scale(nv12_scale_t *s, uint8_t *dst, const uint8_t *src)
|
||||
{
|
||||
if (s->src_cx == s->dst_cx && s->src_cy == s->dst_cy) {
|
||||
if (s->convert_to_i420)
|
||||
if (s->format == TARGET_FORMAT_I420)
|
||||
nv12_convert_to_i420(s, dst, src);
|
||||
else if (s->format == TARGET_FORMAT_YUY2)
|
||||
nv12_convert_to_yuy2(s, dst, src);
|
||||
else
|
||||
memcpy(dst, src, s->src_cx * s->src_cy * 3 / 2);
|
||||
} else {
|
||||
if (s->convert_to_i420)
|
||||
if (s->format == TARGET_FORMAT_I420)
|
||||
nv12_scale_nearest_to_i420(s, dst, src);
|
||||
else if (s->format == TARGET_FORMAT_YUY2)
|
||||
nv12_scale_nearest_to_yuy2(s, dst, src);
|
||||
else
|
||||
nv12_scale_nearest(s, dst, src);
|
||||
}
|
||||
|
|
|
@ -7,8 +7,14 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum target_format {
|
||||
TARGET_FORMAT_NV12,
|
||||
TARGET_FORMAT_I420,
|
||||
TARGET_FORMAT_YUY2,
|
||||
};
|
||||
|
||||
struct nv12_scale {
|
||||
bool convert_to_i420;
|
||||
enum target_format format;
|
||||
|
||||
int src_cx;
|
||||
int src_cy;
|
||||
|
@ -19,8 +25,8 @@ struct nv12_scale {
|
|||
|
||||
typedef struct nv12_scale nv12_scale_t;
|
||||
|
||||
extern void nv12_scale_init(nv12_scale_t *s, bool convert_to_i420, int dst_cx,
|
||||
int dst_cy, int src_cx, int src_cy);
|
||||
extern void nv12_scale_init(nv12_scale_t *s, enum target_format format,
|
||||
int dst_cx, int dst_cy, int src_cx, int src_cy);
|
||||
extern void nv12_do_scale(nv12_scale_t *s, uint8_t *dst, const uint8_t *src);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -20,6 +20,8 @@ VCamFilter::VCamFilter()
|
|||
|
||||
AddVideoFormat(VideoFormat::I420, DEFAULT_CX, DEFAULT_CY,
|
||||
DEFAULT_INTERVAL);
|
||||
AddVideoFormat(VideoFormat::YUY2, DEFAULT_CX, DEFAULT_CY,
|
||||
DEFAULT_INTERVAL);
|
||||
|
||||
/* ---------------------------------------- */
|
||||
/* load placeholder image */
|
||||
|
@ -90,13 +92,14 @@ VCamFilter::VCamFilter()
|
|||
if (new_cx != cx || new_cy != cy || new_interval != interval) {
|
||||
AddVideoFormat(VideoFormat::NV12, new_cx, new_cy, new_interval);
|
||||
AddVideoFormat(VideoFormat::I420, new_cx, new_cy, new_interval);
|
||||
AddVideoFormat(VideoFormat::YUY2, new_cx, new_cy, new_interval);
|
||||
SetVideoFormat(VideoFormat::NV12, new_cx, new_cy, new_interval);
|
||||
cx = new_cx;
|
||||
cy = new_cy;
|
||||
interval = new_interval;
|
||||
}
|
||||
|
||||
nv12_scale_init(&scaler, false, cx, cy, cx, cy);
|
||||
nv12_scale_init(&scaler, TARGET_FORMAT_NV12, cx, cy, cx, cy);
|
||||
|
||||
/* ---------------------------------------- */
|
||||
|
||||
|
@ -157,7 +160,7 @@ void VCamFilter::Thread()
|
|||
cy = GetCY();
|
||||
interval = GetInterval();
|
||||
|
||||
nv12_scale_init(&scaler, false, GetCX(), GetCY(), cx, cy);
|
||||
nv12_scale_init(&scaler, TARGET_FORMAT_NV12, GetCX(), GetCY(), cx, cy);
|
||||
|
||||
while (!stopped()) {
|
||||
Frame(filter_time);
|
||||
|
@ -201,15 +204,20 @@ void VCamFilter::Frame(uint64_t ts)
|
|||
new_interval);
|
||||
}
|
||||
|
||||
nv12_scale_init(&scaler, false, GetCX(), GetCY(), new_cx,
|
||||
new_cy);
|
||||
nv12_scale_init(&scaler, TARGET_FORMAT_NV12, GetCX(), GetCY(),
|
||||
new_cx, new_cy);
|
||||
|
||||
cx = new_cx;
|
||||
cy = new_cy;
|
||||
interval = new_interval;
|
||||
}
|
||||
|
||||
scaler.convert_to_i420 = GetVideoFormat() == VideoFormat::I420;
|
||||
if (GetVideoFormat() == VideoFormat::I420)
|
||||
scaler.format = TARGET_FORMAT_I420;
|
||||
else if (GetVideoFormat() == VideoFormat::YUY2)
|
||||
scaler.format = TARGET_FORMAT_YUY2;
|
||||
else
|
||||
scaler.format = TARGET_FORMAT_NV12;
|
||||
|
||||
uint8_t *ptr;
|
||||
if (LockSampleData(&ptr)) {
|
||||
|
|
Loading…
Reference in New Issue