win-dshow: Add support for YUY2 in virtualcam
This commit is contained in:
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
|
* it's nearest neighbor so not really a huge deal. at the very least it
|
||||||
* should be sse2 at some point. */
|
* 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)
|
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_cx = src_cx;
|
||||||
s->src_cy = src_cy;
|
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)
|
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->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);
|
nv12_convert_to_i420(s, dst, src);
|
||||||
|
else if (s->format == TARGET_FORMAT_YUY2)
|
||||||
|
nv12_convert_to_yuy2(s, dst, src);
|
||||||
else
|
else
|
||||||
memcpy(dst, src, s->src_cx * s->src_cy * 3 / 2);
|
memcpy(dst, src, s->src_cx * s->src_cy * 3 / 2);
|
||||||
} else {
|
} else {
|
||||||
if (s->convert_to_i420)
|
if (s->format == TARGET_FORMAT_I420)
|
||||||
nv12_scale_nearest_to_i420(s, dst, src);
|
nv12_scale_nearest_to_i420(s, dst, src);
|
||||||
|
else if (s->format == TARGET_FORMAT_YUY2)
|
||||||
|
nv12_scale_nearest_to_yuy2(s, dst, src);
|
||||||
else
|
else
|
||||||
nv12_scale_nearest(s, dst, src);
|
nv12_scale_nearest(s, dst, src);
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,14 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum target_format {
|
||||||
|
TARGET_FORMAT_NV12,
|
||||||
|
TARGET_FORMAT_I420,
|
||||||
|
TARGET_FORMAT_YUY2,
|
||||||
|
};
|
||||||
|
|
||||||
struct nv12_scale {
|
struct nv12_scale {
|
||||||
bool convert_to_i420;
|
enum target_format format;
|
||||||
|
|
||||||
int src_cx;
|
int src_cx;
|
||||||
int src_cy;
|
int src_cy;
|
||||||
@ -19,8 +25,8 @@ struct nv12_scale {
|
|||||||
|
|
||||||
typedef struct nv12_scale nv12_scale_t;
|
typedef struct nv12_scale nv12_scale_t;
|
||||||
|
|
||||||
extern void nv12_scale_init(nv12_scale_t *s, bool convert_to_i420, int dst_cx,
|
extern void nv12_scale_init(nv12_scale_t *s, enum target_format format,
|
||||||
int dst_cy, int src_cx, int src_cy);
|
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);
|
extern void nv12_do_scale(nv12_scale_t *s, uint8_t *dst, const uint8_t *src);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -20,6 +20,8 @@ VCamFilter::VCamFilter()
|
|||||||
|
|
||||||
AddVideoFormat(VideoFormat::I420, DEFAULT_CX, DEFAULT_CY,
|
AddVideoFormat(VideoFormat::I420, DEFAULT_CX, DEFAULT_CY,
|
||||||
DEFAULT_INTERVAL);
|
DEFAULT_INTERVAL);
|
||||||
|
AddVideoFormat(VideoFormat::YUY2, DEFAULT_CX, DEFAULT_CY,
|
||||||
|
DEFAULT_INTERVAL);
|
||||||
|
|
||||||
/* ---------------------------------------- */
|
/* ---------------------------------------- */
|
||||||
/* load placeholder image */
|
/* load placeholder image */
|
||||||
@ -90,13 +92,14 @@ VCamFilter::VCamFilter()
|
|||||||
if (new_cx != cx || new_cy != cy || new_interval != interval) {
|
if (new_cx != cx || new_cy != cy || new_interval != interval) {
|
||||||
AddVideoFormat(VideoFormat::NV12, new_cx, new_cy, new_interval);
|
AddVideoFormat(VideoFormat::NV12, new_cx, new_cy, new_interval);
|
||||||
AddVideoFormat(VideoFormat::I420, 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);
|
SetVideoFormat(VideoFormat::NV12, new_cx, new_cy, new_interval);
|
||||||
cx = new_cx;
|
cx = new_cx;
|
||||||
cy = new_cy;
|
cy = new_cy;
|
||||||
interval = new_interval;
|
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();
|
cy = GetCY();
|
||||||
interval = GetInterval();
|
interval = GetInterval();
|
||||||
|
|
||||||
nv12_scale_init(&scaler, false, GetCX(), GetCY(), cx, cy);
|
nv12_scale_init(&scaler, TARGET_FORMAT_NV12, GetCX(), GetCY(), cx, cy);
|
||||||
|
|
||||||
while (!stopped()) {
|
while (!stopped()) {
|
||||||
Frame(filter_time);
|
Frame(filter_time);
|
||||||
@ -201,15 +204,20 @@ void VCamFilter::Frame(uint64_t ts)
|
|||||||
new_interval);
|
new_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
nv12_scale_init(&scaler, false, GetCX(), GetCY(), new_cx,
|
nv12_scale_init(&scaler, TARGET_FORMAT_NV12, GetCX(), GetCY(),
|
||||||
new_cy);
|
new_cx, new_cy);
|
||||||
|
|
||||||
cx = new_cx;
|
cx = new_cx;
|
||||||
cy = new_cy;
|
cy = new_cy;
|
||||||
interval = new_interval;
|
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;
|
uint8_t *ptr;
|
||||||
if (LockSampleData(&ptr)) {
|
if (LockSampleData(&ptr)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user