mirror of
https://github.com/Tha14/toxic.git
synced 2024-12-23 04:23:24 +01:00
Fixed v4l2 capture crash, and refactored to prepare for new features
This commit is contained in:
parent
d359ba6a54
commit
c2c612b85a
21
cfg/checks/audio.mk
Normal file
21
cfg/checks/audio.mk
Normal file
@ -0,0 +1,21 @@
|
||||
# Variables for audio call support
|
||||
AUDIO_LIBS = libtoxav openal
|
||||
AUDIO_CFLAGS = -DAUDIO
|
||||
ifneq (, $(findstring audio_device.o, $(OBJ)))
|
||||
AUDIO_OBJ = audio_call.o
|
||||
else
|
||||
AUDIO_OBJ = audio_call.o audio_device.o
|
||||
endif
|
||||
|
||||
# Check if we can build audio support
|
||||
CHECK_AUDIO_LIBS = $(shell pkg-config --exists $(AUDIO_LIBS) || echo -n "error")
|
||||
ifneq ($(CHECK_AUDIO_LIBS), error)
|
||||
LIBS += $(AUDIO_LIBS)
|
||||
CFLAGS += $(AUDIO_CFLAGS)
|
||||
OBJ += $(AUDIO_OBJ)
|
||||
else ifneq ($(MAKECMDGOALS), clean)
|
||||
MISSING_AUDIO_LIBS = $(shell for lib in $(AUDIO_LIBS) ; do if ! pkg-config --exists $$lib ; then echo $$lib ; fi ; done)
|
||||
$(warning WARNING -- Toxic will be compiled without audio support)
|
||||
$(warning WARNING -- You need these libraries for audio support)
|
||||
$(warning WARNING -- $(MISSING_AUDIO_LIBS))
|
||||
endif
|
@ -1,43 +0,0 @@
|
||||
# Variables for audio call support
|
||||
AUDIO_LIBS = libtoxav openal
|
||||
AUDIO_CFLAGS = -DAUDIO
|
||||
ifneq (, $(findstring audio_device.o, $(OBJ)))
|
||||
AUDIO_OBJ = audio_call.o
|
||||
else
|
||||
AUDIO_OBJ = audio_call.o audio_device.o
|
||||
endif
|
||||
|
||||
# Variables for video call support
|
||||
VIDEO_LIBS = libtoxav vpx x11
|
||||
VIDEO_CFLAGS = -DVIDEO
|
||||
ifneq (, $(findstring video_device.o, $(OBJ)))
|
||||
VIDEO_OBJ = video_call.o
|
||||
else
|
||||
VIDEO_OBJ = video_call.o video_device.o
|
||||
endif
|
||||
|
||||
# Check if we can build audio support
|
||||
CHECK_AUDIO_LIBS = $(shell $(PKG_CONFIG) --exists $(AUDIO_LIBS) || echo -n "error")
|
||||
ifneq ($(CHECK_AUDIO_LIBS), error)
|
||||
LIBS += $(AUDIO_LIBS)
|
||||
CFLAGS += $(AUDIO_CFLAGS)
|
||||
OBJ += $(AUDIO_OBJ)
|
||||
else ifneq ($(MAKECMDGOALS), clean)
|
||||
MISSING_AUDIO_LIBS = $(shell for lib in $(AUDIO_LIBS) ; do if ! $(PKG_CONFIG) --exists $$lib ; then echo $$lib ; fi ; done)
|
||||
$(warning WARNING -- Toxic will be compiled without audio support)
|
||||
$(warning WARNING -- You need these libraries for audio support)
|
||||
$(warning WARNING -- $(MISSING_AUDIO_LIBS))
|
||||
endif
|
||||
|
||||
# Check if we can build video support
|
||||
CHECK_VIDEO_LIBS = $(shell pkg-config --exists $(VIDEO_LIBS) || echo -n "error")
|
||||
ifneq ($(CHECK_VIDEO_LIBS), error)
|
||||
LIBS += $(VIDEO_LIBS)
|
||||
CFLAGS += $(VIDEO_CFLAGS)
|
||||
OBJ += $(VIDEO_OBJ)
|
||||
else ifneq ($(MAKECMDGOALS), clean)
|
||||
MISSING_VIDEO_LIBS = $(shell for lib in $(VIDEO_LIBS) ; do if ! pkg-config --exists $$lib ; then echo $$lib ; fi ; done)
|
||||
$(warning WARNING -- Toxic will be compiled without video support)
|
||||
$(warning WARNING -- You will need these libraries for video support)
|
||||
$(warning WARNING -- $(MISSING_VIDEO_LIBS))
|
||||
endif
|
@ -9,7 +9,15 @@ endif
|
||||
# Check if we want build audio support
|
||||
AUDIO = $(shell if [ -z "$(DISABLE_AV)" ] || [ "$(DISABLE_AV)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
ifneq ($(AUDIO), disabled)
|
||||
-include $(CHECKS_DIR)/av.mk
|
||||
-include $(CHECKS_DIR)/audio.mk
|
||||
endif
|
||||
|
||||
# Check if we want build video support
|
||||
VIDEO = $*shell if [ -z "$(DISABLE_AV)" ] || [ "$(DISABLE_AV)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
ifneq ($(AUDIO), disabled)
|
||||
ifneq ($(VIDEO), disabled)
|
||||
-include $(CHECKS_DIR)/video.mk
|
||||
endif
|
||||
endif
|
||||
|
||||
# Check if we want build sound notifications support
|
||||
|
21
cfg/checks/video.mk
Normal file
21
cfg/checks/video.mk
Normal file
@ -0,0 +1,21 @@
|
||||
# Variables for video call support
|
||||
VIDEO_LIBS = libtoxav vpx x11
|
||||
VIDEO_CFLAGS = -DVIDEO
|
||||
ifneq (, $(findstring video_device.o, $(OBJ)))
|
||||
VIDEO_OBJ = video_call.o
|
||||
else
|
||||
VIDEO_OBJ = video_call.o video_device.o
|
||||
endif
|
||||
|
||||
# Check if we can build video support
|
||||
CHECK_VIDEO_LIBS = $(shell pkg-config --exists $(VIDEO_LIBS) || echo -n "error")
|
||||
ifneq ($(CHECK_VIDEO_LIBS), error)
|
||||
LIBS += $(VIDEO_LIBS)
|
||||
CFLAGS += $(VIDEO_CFLAGS)
|
||||
OBJ += $(VIDEO_OBJ)
|
||||
else ifneq ($(MAKECMDGOALS), clean)
|
||||
MISSING_VIDEO_LIBS = $(shell for lib in $(VIDEO_LIBS) ; do if ! pkg-config --exists $$lib ; then echo $$lib ; fi ; done)
|
||||
$(warning WARNING -- Toxic will be compiled without video support)
|
||||
$(warning WARNING -- You will need these libraries for video support)
|
||||
$(warning WARNING -- $(MISSING_VIDEO_LIBS))
|
||||
endif
|
25
src/help.c
25
src/help.c
@ -167,6 +167,15 @@ static void help_draw_global(ToxWindow *self)
|
||||
wprintw(win, " /sdev <type> <id> : Set active device\n");
|
||||
#endif /* AUDIO */
|
||||
|
||||
#ifdef VIDEO
|
||||
wattron(win, A_BOLD);
|
||||
wprintw(win, "\n Video:\n");
|
||||
wattroff(win, A_BOLD);
|
||||
|
||||
wprintw(win, " /lsvdev <type> : List video devices where type: in|out\n");
|
||||
wprintw(win, " /svdev <type> <id> : Set active video device\n");
|
||||
#endif /* VIDEO */
|
||||
|
||||
help_draw_bottom_menu(win);
|
||||
|
||||
box(win, ACS_VLINE, ACS_HLINE);
|
||||
@ -203,6 +212,14 @@ static void help_draw_chat(ToxWindow *self)
|
||||
wprintw(win, " /sense <n> : VAD sensitivity threshold\n");
|
||||
#endif /* AUDIO */
|
||||
|
||||
#ifdef VIDEO
|
||||
wattron(win, A_BOLD);
|
||||
wprintw(win, "\n Video:\n");
|
||||
wattroff(win, A_BOLD);
|
||||
wprintw(win, " /video : Send video capture\n");
|
||||
wprintw(win, " /endvideo : Close all video windows\n");
|
||||
#endif /* VIDEO */
|
||||
|
||||
help_draw_bottom_menu(win);
|
||||
|
||||
box(win, ACS_VLINE, ACS_HLINE);
|
||||
@ -282,7 +299,9 @@ void help_onKey(ToxWindow *self, wint_t key)
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
#ifdef AUDIO
|
||||
#ifdef VIDEO
|
||||
help_init_window(self, 23, 80);
|
||||
#elif AUDIO
|
||||
help_init_window(self, 19, 80);
|
||||
#else
|
||||
help_init_window(self, 9, 80);
|
||||
@ -291,7 +310,9 @@ void help_onKey(ToxWindow *self, wint_t key)
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
#ifdef AUDIO
|
||||
#ifdef VIDEO
|
||||
help_init_window(self, 28, 80);
|
||||
#elif AUDIO
|
||||
help_init_window(self, 24, 80);
|
||||
#else
|
||||
help_init_window(self, 20, 80);
|
||||
|
@ -80,11 +80,11 @@ void write_video_device_callback(uint32_t friend_number, uint16_t width, uint16_
|
||||
int32_t ystride, int32_t ustride, int32_t vstride,
|
||||
void *user_data)
|
||||
{
|
||||
CallControl* cc = (CallControl*)user_data;
|
||||
Call* this_call = &cc->calls[friend_number];
|
||||
Call* this_call = &CallContrl.calls[friend_number];
|
||||
|
||||
if(write_video_out(width, height, y, u, v, ystride, ustride, vstride, user_data) == vde_DeviceNotActive)
|
||||
callback_recv_video_starting(cc->av, friend_number, cc);
|
||||
if(write_video_out(width, height, y, u, v, ystride, ustride, vstride, user_data) == vde_DeviceNotActive) {
|
||||
callback_recv_video_starting(CallContrl.av, friend_number, &CallContrl);
|
||||
}
|
||||
}
|
||||
|
||||
int start_video_transmission(ToxWindow *self, ToxAV *av, Call *call)
|
||||
@ -155,7 +155,7 @@ void callback_recv_video_starting(void* av, uint32_t friend_number, void *arg)
|
||||
Call* this_call = &cc->calls[friend_number];
|
||||
|
||||
open_primary_video_device(vdt_output, &this_call->out_idx);
|
||||
CallContrl.video_call = true;
|
||||
cc->video_call = true;
|
||||
}
|
||||
|
||||
void callback_video_starting(void* av, uint32_t friend_number, void *arg)
|
||||
@ -167,16 +167,18 @@ void callback_video_starting(void* av, uint32_t friend_number, void *arg)
|
||||
int i;
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i].is_call && windows[i].num == friend_number) {
|
||||
cc->video_call = true;
|
||||
if(0 != start_video_transmission(&windows[i], av, this_call)) {
|
||||
line_info_add(&windows[i], NULL, NULL, NULL, SYS_MSG, 0, 0, "Error starting transmission!");
|
||||
cc->video_call = false;
|
||||
return;
|
||||
}
|
||||
|
||||
line_info_add(&windows[i], NULL, NULL, NULL, SYS_MSG, 0, 0, "Video capture starting.");
|
||||
cc->video_call = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void callback_video_ending(void* av, uint32_t friend_number, void *arg)
|
||||
{
|
||||
CallControl *cc = (CallControl*)arg;
|
||||
@ -191,8 +193,11 @@ void callback_video_ending(void* av, uint32_t friend_number, void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_CALLS; ++i)
|
||||
stop_video_transmission(&CallContrl.calls[i], i);
|
||||
|
||||
cc->video_call = false;
|
||||
terminate_video();
|
||||
|
||||
}
|
||||
/*
|
||||
* End of Callbacks
|
||||
|
@ -113,6 +113,54 @@ static int xioctl(int fh, unsigned long request, void *arg)
|
||||
return r;
|
||||
}
|
||||
|
||||
static void yuv420tobgr(uint16_t width, uint16_t height, const uint8_t *y,
|
||||
const uint8_t *u, const uint8_t *v, unsigned int ystride,
|
||||
unsigned int ustride, unsigned int vstride, uint8_t *out)
|
||||
{
|
||||
unsigned long int i, j;
|
||||
for (i = 0; i < height; ++i) {
|
||||
for (j = 0; j < width; ++j) {
|
||||
uint8_t *point = out + 4 * ((i * width) + j);
|
||||
int t_y = y[((i * ystride) + j)];
|
||||
int t_u = u[(((i / 2) * ustride) + (j / 2))];
|
||||
int t_v = v[(((i / 2) * vstride) + (j / 2))];
|
||||
t_y = t_y < 16 ? 16 : t_y;
|
||||
|
||||
int r = (298 * (t_y - 16) + 409 * (t_v - 128) + 128) >> 8;
|
||||
int g = (298 * (t_y - 16) - 100 * (t_u - 128) - 208 * (t_v - 128) + 128) >> 8;
|
||||
int b = (298 * (t_y - 16) + 516 * (t_u - 128) + 128) >> 8;
|
||||
|
||||
point[2] = r>255? 255 : r<0 ? 0 : r;
|
||||
point[1] = g>255? 255 : g<0 ? 0 : g;
|
||||
point[0] = b>255? 255 : b<0 ? 0 : b;
|
||||
point[3] = ~0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void yuv422to420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v,
|
||||
uint8_t *input, uint16_t width, uint16_t height)
|
||||
{
|
||||
uint8_t *end = input + width * height * 2;
|
||||
while(input != end) {
|
||||
uint8_t *line_end = input + width * 2;
|
||||
while(input != line_end) {
|
||||
*plane_y++ = *input++;
|
||||
*plane_u++ = *input++;
|
||||
*plane_y++ = *input++;
|
||||
*plane_v++ = *input++;
|
||||
}
|
||||
|
||||
line_end = input + width * 2;
|
||||
while(input != line_end) {
|
||||
*plane_y++ = *input++;
|
||||
input++;//u
|
||||
*plane_y++ = *input++;
|
||||
input++;//v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Meet devices */
|
||||
#ifdef VIDEO
|
||||
VideoDeviceError init_video_devices(ToxAV* av_)
|
||||
@ -124,7 +172,6 @@ VideoDeviceError init_video_devices()
|
||||
|
||||
#ifdef __linux__
|
||||
for(; size[vdt_input] <= MAX_DEVICES; ++size[vdt_input]) {
|
||||
//size[vdt_input] = i;
|
||||
int fd;
|
||||
char device_address[] = "/dev/videoXX";
|
||||
snprintf(device_address + 10, sizeof(char) * strlen(device_address) - 10, "%i", size[vdt_input]);
|
||||
@ -199,6 +246,7 @@ VideoDeviceError register_video_device_callback(int32_t friend_number, uint32_t
|
||||
VideoDeviceError set_primary_video_device(VideoDeviceType type, int32_t selection)
|
||||
{
|
||||
if (size[type] <= selection || selection < 0) return vde_InvalidSelection;
|
||||
|
||||
primary_video_device[type] = selection;
|
||||
|
||||
return vde_None;
|
||||
@ -247,6 +295,8 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
||||
}
|
||||
|
||||
if (type == vdt_input) {
|
||||
video_thread_paused = true;
|
||||
|
||||
#ifdef __linux__
|
||||
char device_address[] = "/dev/videoXX";
|
||||
snprintf(device_address + 10 , sizeof(device_address) - 10, "%i", selection);
|
||||
@ -259,7 +309,7 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
||||
/* Obtain video device capabilities */
|
||||
struct v4l2_capability cap;
|
||||
if (-1 == xioctl(device->fd, VIDIOC_QUERYCAP, &cap)) {
|
||||
return vde_UnsupportedMode;
|
||||
return vde_FailedStart;
|
||||
}
|
||||
|
||||
/* Setup video format */
|
||||
@ -269,30 +319,29 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
|
||||
if(-1 == xioctl(device->fd, VIDIOC_G_FMT, &fmt)) {
|
||||
return vde_UnsupportedMode;
|
||||
return vde_FailedStart;
|
||||
}
|
||||
|
||||
device->video_width = fmt.fmt.pix.width;
|
||||
device->video_height = fmt.fmt.pix.height;
|
||||
|
||||
|
||||
|
||||
/* Request buffers */
|
||||
struct v4l2_requestbuffers req;
|
||||
memset(&(req), 0, sizeof(req));
|
||||
|
||||
req.count = 4;
|
||||
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
req.memory = V4L2_MEMORY_MMAP;
|
||||
|
||||
if (-1 == xioctl(device->fd, VIDIOC_REQBUFS, &req)) {
|
||||
assert(0);
|
||||
return vde_UnsupportedMode;
|
||||
return vde_FailedStart;
|
||||
}
|
||||
|
||||
if(req.count < 2) {
|
||||
return vde_UnsupportedMode;
|
||||
return vde_FailedStart;
|
||||
}
|
||||
|
||||
device->buffers = calloc(req.count, sizeof(*device->buffers));
|
||||
device->buffers = calloc(req.count, sizeof(struct VideoBuffer));
|
||||
|
||||
for(i = 0; i < req.count; ++i) {
|
||||
struct v4l2_buffer buf;
|
||||
@ -300,11 +349,10 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
||||
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
buf.index = device->n_buffers;
|
||||
device->n_buffers = i;
|
||||
buf.index = i;
|
||||
|
||||
if (-1 == xioctl(device->fd, VIDIOC_QUERYBUF, &buf)) {
|
||||
return vde_UnsupportedMode;
|
||||
return vde_FailedStart;
|
||||
}
|
||||
|
||||
device->buffers[i].length = buf.length;
|
||||
@ -315,14 +363,16 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
||||
device->fd, buf.m.offset);
|
||||
|
||||
if(MAP_FAILED == device->buffers[i].start) {
|
||||
return vde_UnsupportedMode;
|
||||
return vde_FailedStart;
|
||||
}
|
||||
}
|
||||
device->n_buffers = i;
|
||||
|
||||
enum v4l2_buf_type type;
|
||||
|
||||
for (i = 0; i < device->n_buffers; ++i) {
|
||||
struct v4l2_buffer buf;
|
||||
memset(&(buf), 0, sizeof(buf));
|
||||
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
@ -353,7 +403,7 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
||||
if ((device->x_window = XCreateSimpleWindow(device->x_display, RootWindow(device->x_display, screen),
|
||||
0, 0, device->video_width, device->video_height, 0,
|
||||
BlackPixel(device->x_display, screen),
|
||||
WhitePixel(device->x_display, screen))) == NULL) {
|
||||
BlackPixel(device->x_display, screen))) == NULL) {
|
||||
return vde_FailedStart;
|
||||
}
|
||||
|
||||
@ -383,7 +433,7 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
||||
if ((device->x_window = XCreateSimpleWindow(device->x_display, RootWindow(device->x_display, screen),
|
||||
0, 0, 100, 100, 0,
|
||||
BlackPixel(device->x_display, screen),
|
||||
WhitePixel(device->x_display, screen))) == NULL) {
|
||||
BlackPixel(device->x_display, screen))) == NULL) {
|
||||
return vde_FailedStart;
|
||||
}
|
||||
|
||||
@ -419,6 +469,20 @@ __inline VideoDeviceError write_video_out(uint16_t width, uint16_t height,
|
||||
|
||||
pthread_mutex_lock(device->mutex);
|
||||
|
||||
int screen = DefaultScreen(device->x_display);
|
||||
|
||||
/* Recreate missing window */
|
||||
if(!device->x_window) {
|
||||
device->x_window = XCreateSimpleWindow(device->x_display, RootWindow(device->x_display, screen),
|
||||
0, 0, device->video_width, device->video_height, 0,
|
||||
BlackPixel(device->x_display, screen),
|
||||
BlackPixel(device->x_display, screen));
|
||||
XMapWindow(device->x_display, device->x_window);
|
||||
XClearWindow(device->x_display, device->x_window);
|
||||
XMapRaised(device->x_display, device->x_window);
|
||||
XFlush(device->x_display);
|
||||
}
|
||||
|
||||
/* Resize X11 window to correct size */
|
||||
if(device->video_width != width || device->video_height != height) {
|
||||
device->video_width = width;
|
||||
@ -427,13 +491,11 @@ __inline VideoDeviceError write_video_out(uint16_t width, uint16_t height,
|
||||
vpx_img_free(&device->input);
|
||||
vpx_img_alloc(&device->input, VPX_IMG_FMT_I420, width, height, 1);
|
||||
}
|
||||
int screen = DefaultScreen(device->x_display);
|
||||
|
||||
/* Display video image */
|
||||
ystride = abs(ystride);
|
||||
ustride = abs(ustride);
|
||||
vstride = abs(vstride);
|
||||
line_info_add(CallContrl.window, NULL, NULL, NULL, SYS_MSG, 0, 0, "ystride: %i ustride: %i vstride: %i", ystride, ustride, vstride);
|
||||
|
||||
uint8_t *img_data = malloc(width * height * 4);
|
||||
yuv420tobgr(width, height, y, u, v, ystride, ustride, vstride, img_data);
|
||||
@ -558,7 +620,7 @@ VideoDeviceError close_video_device(VideoDeviceType type, uint32_t device_idx)
|
||||
if (device_idx >= MAX_DEVICES) return vde_InvalidSelection;
|
||||
|
||||
lock;
|
||||
VideoDevice* device = video_devices_running[type][device_idx];
|
||||
VideoDevice *device = video_devices_running[type][device_idx];
|
||||
VideoDeviceError rc = vde_None;
|
||||
|
||||
if (!device) {
|
||||
@ -571,17 +633,16 @@ VideoDeviceError close_video_device(VideoDeviceType type, uint32_t device_idx)
|
||||
if ( !device->ref_count ) {
|
||||
|
||||
if (type == vdt_input) {
|
||||
|
||||
enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
if(-1 == xioctl(device->fd, VIDIOC_STREAMOFF, &buf_type)) {}
|
||||
|
||||
int i;
|
||||
for(i = 0; i < device->n_buffers; ++i) {
|
||||
if (-1 == munmap(device->buffers[i].start, device->buffers[i].length)) {}
|
||||
if (-1 == munmap(device->buffers[i].start, device->buffers[i].length)) {
|
||||
}
|
||||
}
|
||||
close(device->fd);
|
||||
|
||||
vpx_img_free(&device->input);
|
||||
//vpx_img_free(&device->input);
|
||||
XDestroyWindow(device->x_display, device->x_window);
|
||||
XFlush(device->x_display);
|
||||
XCloseDisplay(device->x_display);
|
||||
@ -604,54 +665,6 @@ VideoDeviceError close_video_device(VideoDeviceType type, uint32_t device_idx)
|
||||
return rc;
|
||||
}
|
||||
|
||||
void yuv420tobgr(uint16_t width, uint16_t height, const uint8_t *y,
|
||||
const uint8_t *u, const uint8_t *v, unsigned int ystride,
|
||||
unsigned int ustride, unsigned int vstride, uint8_t *out)
|
||||
{
|
||||
unsigned long int i, j;
|
||||
for (i = 0; i < height; ++i) {
|
||||
for (j = 0; j < width; ++j) {
|
||||
uint8_t *point = out + 4 * ((i * width) + j);
|
||||
int t_y = y[((i * ystride) + j)];
|
||||
int t_u = u[(((i / 2) * ustride) + (j / 2))];
|
||||
int t_v = v[(((i / 2) * vstride) + (j / 2))];
|
||||
t_y = t_y < 16 ? 16 : t_y;
|
||||
|
||||
int r = (298 * (t_y - 16) + 409 * (t_v - 128) + 128) >> 8;
|
||||
int g = (298 * (t_y - 16) - 100 * (t_u - 128) - 208 * (t_v - 128) + 128) >> 8;
|
||||
int b = (298 * (t_y - 16) + 516 * (t_u - 128) + 128) >> 8;
|
||||
|
||||
point[2] = r>255? 255 : r<0 ? 0 : r;
|
||||
point[1] = g>255? 255 : g<0 ? 0 : g;
|
||||
point[0] = b>255? 255 : b<0 ? 0 : b;
|
||||
point[3] = ~0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void yuv422to420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v,
|
||||
uint8_t *input, uint16_t width, uint16_t height)
|
||||
{
|
||||
uint8_t *end = input + width * height * 2;
|
||||
while(input != end) {
|
||||
uint8_t *line_end = input + width * 2;
|
||||
while(input != line_end) {
|
||||
*plane_y++ = *input++;
|
||||
*plane_u++ = *input++;
|
||||
*plane_y++ = *input++;
|
||||
*plane_v++ = *input++;
|
||||
}
|
||||
|
||||
line_end = input + width * 2;
|
||||
while(input != line_end) {
|
||||
*plane_y++ = *input++;
|
||||
input++;//u
|
||||
*plane_y++ = *input++;
|
||||
input++;//v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void print_video_devices(ToxWindow* self, VideoDeviceType type)
|
||||
{
|
||||
int i;
|
||||
|
@ -153,7 +153,9 @@ struct ToxWindow {
|
||||
int ringing_sound;
|
||||
|
||||
#ifdef VIDEO
|
||||
|
||||
int video_device_selection[2]; /* -1 if not set, if set uses these selections instead of primary video device */
|
||||
|
||||
#endif /* VIDEO */
|
||||
|
||||
#endif /* AUDIO */
|
||||
|
Loading…
Reference in New Issue
Block a user