mirror of
https://github.com/Tha14/toxic.git
synced 2024-11-22 20:53:01 +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
|
# Check if we want build audio support
|
||||||
AUDIO = $(shell if [ -z "$(DISABLE_AV)" ] || [ "$(DISABLE_AV)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
AUDIO = $(shell if [ -z "$(DISABLE_AV)" ] || [ "$(DISABLE_AV)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||||
ifneq ($(AUDIO), disabled)
|
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
|
endif
|
||||||
|
|
||||||
# Check if we want build sound notifications support
|
# 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");
|
wprintw(win, " /sdev <type> <id> : Set active device\n");
|
||||||
#endif /* AUDIO */
|
#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);
|
help_draw_bottom_menu(win);
|
||||||
|
|
||||||
box(win, ACS_VLINE, ACS_HLINE);
|
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");
|
wprintw(win, " /sense <n> : VAD sensitivity threshold\n");
|
||||||
#endif /* AUDIO */
|
#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);
|
help_draw_bottom_menu(win);
|
||||||
|
|
||||||
box(win, ACS_VLINE, ACS_HLINE);
|
box(win, ACS_VLINE, ACS_HLINE);
|
||||||
@ -282,7 +299,9 @@ void help_onKey(ToxWindow *self, wint_t key)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
#ifdef AUDIO
|
#ifdef VIDEO
|
||||||
|
help_init_window(self, 23, 80);
|
||||||
|
#elif AUDIO
|
||||||
help_init_window(self, 19, 80);
|
help_init_window(self, 19, 80);
|
||||||
#else
|
#else
|
||||||
help_init_window(self, 9, 80);
|
help_init_window(self, 9, 80);
|
||||||
@ -291,7 +310,9 @@ void help_onKey(ToxWindow *self, wint_t key)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
#ifdef AUDIO
|
#ifdef VIDEO
|
||||||
|
help_init_window(self, 28, 80);
|
||||||
|
#elif AUDIO
|
||||||
help_init_window(self, 24, 80);
|
help_init_window(self, 24, 80);
|
||||||
#else
|
#else
|
||||||
help_init_window(self, 20, 80);
|
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,
|
int32_t ystride, int32_t ustride, int32_t vstride,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
CallControl* cc = (CallControl*)user_data;
|
Call* this_call = &CallContrl.calls[friend_number];
|
||||||
Call* this_call = &cc->calls[friend_number];
|
|
||||||
|
|
||||||
if(write_video_out(width, height, y, u, v, ystride, ustride, vstride, user_data) == vde_DeviceNotActive)
|
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);
|
callback_recv_video_starting(CallContrl.av, friend_number, &CallContrl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int start_video_transmission(ToxWindow *self, ToxAV *av, Call *call)
|
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];
|
Call* this_call = &cc->calls[friend_number];
|
||||||
|
|
||||||
open_primary_video_device(vdt_output, &this_call->out_idx);
|
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)
|
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;
|
int i;
|
||||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
if (windows[i].is_call && windows[i].num == friend_number) {
|
if (windows[i].is_call && windows[i].num == friend_number) {
|
||||||
|
cc->video_call = true;
|
||||||
if(0 != start_video_transmission(&windows[i], av, this_call)) {
|
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!");
|
line_info_add(&windows[i], NULL, NULL, NULL, SYS_MSG, 0, 0, "Error starting transmission!");
|
||||||
|
cc->video_call = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
line_info_add(&windows[i], NULL, NULL, NULL, SYS_MSG, 0, 0, "Video capture starting.");
|
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)
|
void callback_video_ending(void* av, uint32_t friend_number, void *arg)
|
||||||
{
|
{
|
||||||
CallControl *cc = (CallControl*)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;
|
cc->video_call = false;
|
||||||
terminate_video();
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* End of Callbacks
|
* End of Callbacks
|
||||||
|
@ -113,6 +113,54 @@ static int xioctl(int fh, unsigned long request, void *arg)
|
|||||||
return r;
|
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 */
|
/* Meet devices */
|
||||||
#ifdef VIDEO
|
#ifdef VIDEO
|
||||||
VideoDeviceError init_video_devices(ToxAV* av_)
|
VideoDeviceError init_video_devices(ToxAV* av_)
|
||||||
@ -124,7 +172,6 @@ VideoDeviceError init_video_devices()
|
|||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
for(; size[vdt_input] <= MAX_DEVICES; ++size[vdt_input]) {
|
for(; size[vdt_input] <= MAX_DEVICES; ++size[vdt_input]) {
|
||||||
//size[vdt_input] = i;
|
|
||||||
int fd;
|
int fd;
|
||||||
char device_address[] = "/dev/videoXX";
|
char device_address[] = "/dev/videoXX";
|
||||||
snprintf(device_address + 10, sizeof(char) * strlen(device_address) - 10, "%i", size[vdt_input]);
|
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)
|
VideoDeviceError set_primary_video_device(VideoDeviceType type, int32_t selection)
|
||||||
{
|
{
|
||||||
if (size[type] <= selection || selection < 0) return vde_InvalidSelection;
|
if (size[type] <= selection || selection < 0) return vde_InvalidSelection;
|
||||||
|
|
||||||
primary_video_device[type] = selection;
|
primary_video_device[type] = selection;
|
||||||
|
|
||||||
return vde_None;
|
return vde_None;
|
||||||
@ -247,6 +295,8 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type == vdt_input) {
|
if (type == vdt_input) {
|
||||||
|
video_thread_paused = true;
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
char device_address[] = "/dev/videoXX";
|
char device_address[] = "/dev/videoXX";
|
||||||
snprintf(device_address + 10 , sizeof(device_address) - 10, "%i", selection);
|
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 */
|
/* Obtain video device capabilities */
|
||||||
struct v4l2_capability cap;
|
struct v4l2_capability cap;
|
||||||
if (-1 == xioctl(device->fd, VIDIOC_QUERYCAP, &cap)) {
|
if (-1 == xioctl(device->fd, VIDIOC_QUERYCAP, &cap)) {
|
||||||
return vde_UnsupportedMode;
|
return vde_FailedStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup video format */
|
/* 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.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
|
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
|
||||||
if(-1 == xioctl(device->fd, VIDIOC_G_FMT, &fmt)) {
|
if(-1 == xioctl(device->fd, VIDIOC_G_FMT, &fmt)) {
|
||||||
return vde_UnsupportedMode;
|
return vde_FailedStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
device->video_width = fmt.fmt.pix.width;
|
device->video_width = fmt.fmt.pix.width;
|
||||||
device->video_height = fmt.fmt.pix.height;
|
device->video_height = fmt.fmt.pix.height;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Request buffers */
|
/* Request buffers */
|
||||||
struct v4l2_requestbuffers req;
|
struct v4l2_requestbuffers req;
|
||||||
memset(&(req), 0, sizeof(req));
|
memset(&(req), 0, sizeof(req));
|
||||||
|
|
||||||
req.count = 4;
|
req.count = 4;
|
||||||
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
req.memory = V4L2_MEMORY_MMAP;
|
req.memory = V4L2_MEMORY_MMAP;
|
||||||
|
|
||||||
if (-1 == xioctl(device->fd, VIDIOC_REQBUFS, &req)) {
|
if (-1 == xioctl(device->fd, VIDIOC_REQBUFS, &req)) {
|
||||||
assert(0);
|
return vde_FailedStart;
|
||||||
return vde_UnsupportedMode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(req.count < 2) {
|
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) {
|
for(i = 0; i < req.count; ++i) {
|
||||||
struct v4l2_buffer buf;
|
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.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
buf.memory = V4L2_MEMORY_MMAP;
|
buf.memory = V4L2_MEMORY_MMAP;
|
||||||
buf.index = device->n_buffers;
|
buf.index = i;
|
||||||
device->n_buffers = i;
|
|
||||||
|
|
||||||
if (-1 == xioctl(device->fd, VIDIOC_QUERYBUF, &buf)) {
|
if (-1 == xioctl(device->fd, VIDIOC_QUERYBUF, &buf)) {
|
||||||
return vde_UnsupportedMode;
|
return vde_FailedStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
device->buffers[i].length = buf.length;
|
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);
|
device->fd, buf.m.offset);
|
||||||
|
|
||||||
if(MAP_FAILED == device->buffers[i].start) {
|
if(MAP_FAILED == device->buffers[i].start) {
|
||||||
return vde_UnsupportedMode;
|
return vde_FailedStart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
device->n_buffers = i;
|
||||||
|
|
||||||
enum v4l2_buf_type type;
|
enum v4l2_buf_type type;
|
||||||
|
|
||||||
for (i = 0; i < device->n_buffers; ++i) {
|
for (i = 0; i < device->n_buffers; ++i) {
|
||||||
struct v4l2_buffer buf;
|
struct v4l2_buffer buf;
|
||||||
|
memset(&(buf), 0, sizeof(buf));
|
||||||
|
|
||||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
buf.memory = V4L2_MEMORY_MMAP;
|
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),
|
if ((device->x_window = XCreateSimpleWindow(device->x_display, RootWindow(device->x_display, screen),
|
||||||
0, 0, device->video_width, device->video_height, 0,
|
0, 0, device->video_width, device->video_height, 0,
|
||||||
BlackPixel(device->x_display, screen),
|
BlackPixel(device->x_display, screen),
|
||||||
WhitePixel(device->x_display, screen))) == NULL) {
|
BlackPixel(device->x_display, screen))) == NULL) {
|
||||||
return vde_FailedStart;
|
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),
|
if ((device->x_window = XCreateSimpleWindow(device->x_display, RootWindow(device->x_display, screen),
|
||||||
0, 0, 100, 100, 0,
|
0, 0, 100, 100, 0,
|
||||||
BlackPixel(device->x_display, screen),
|
BlackPixel(device->x_display, screen),
|
||||||
WhitePixel(device->x_display, screen))) == NULL) {
|
BlackPixel(device->x_display, screen))) == NULL) {
|
||||||
return vde_FailedStart;
|
return vde_FailedStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,6 +469,20 @@ __inline VideoDeviceError write_video_out(uint16_t width, uint16_t height,
|
|||||||
|
|
||||||
pthread_mutex_lock(device->mutex);
|
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 */
|
/* Resize X11 window to correct size */
|
||||||
if(device->video_width != width || device->video_height != height) {
|
if(device->video_width != width || device->video_height != height) {
|
||||||
device->video_width = width;
|
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_free(&device->input);
|
||||||
vpx_img_alloc(&device->input, VPX_IMG_FMT_I420, width, height, 1);
|
vpx_img_alloc(&device->input, VPX_IMG_FMT_I420, width, height, 1);
|
||||||
}
|
}
|
||||||
int screen = DefaultScreen(device->x_display);
|
|
||||||
|
|
||||||
/* Display video image */
|
/* Display video image */
|
||||||
ystride = abs(ystride);
|
ystride = abs(ystride);
|
||||||
ustride = abs(ustride);
|
ustride = abs(ustride);
|
||||||
vstride = abs(vstride);
|
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);
|
uint8_t *img_data = malloc(width * height * 4);
|
||||||
yuv420tobgr(width, height, y, u, v, ystride, ustride, vstride, img_data);
|
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;
|
if (device_idx >= MAX_DEVICES) return vde_InvalidSelection;
|
||||||
|
|
||||||
lock;
|
lock;
|
||||||
VideoDevice* device = video_devices_running[type][device_idx];
|
VideoDevice *device = video_devices_running[type][device_idx];
|
||||||
VideoDeviceError rc = vde_None;
|
VideoDeviceError rc = vde_None;
|
||||||
|
|
||||||
if (!device) {
|
if (!device) {
|
||||||
@ -571,17 +633,16 @@ VideoDeviceError close_video_device(VideoDeviceType type, uint32_t device_idx)
|
|||||||
if ( !device->ref_count ) {
|
if ( !device->ref_count ) {
|
||||||
|
|
||||||
if (type == vdt_input) {
|
if (type == vdt_input) {
|
||||||
|
|
||||||
enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
if(-1 == xioctl(device->fd, VIDIOC_STREAMOFF, &buf_type)) {}
|
if(-1 == xioctl(device->fd, VIDIOC_STREAMOFF, &buf_type)) {}
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < device->n_buffers; ++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);
|
close(device->fd);
|
||||||
|
//vpx_img_free(&device->input);
|
||||||
vpx_img_free(&device->input);
|
|
||||||
XDestroyWindow(device->x_display, device->x_window);
|
XDestroyWindow(device->x_display, device->x_window);
|
||||||
XFlush(device->x_display);
|
XFlush(device->x_display);
|
||||||
XCloseDisplay(device->x_display);
|
XCloseDisplay(device->x_display);
|
||||||
@ -604,54 +665,6 @@ VideoDeviceError close_video_device(VideoDeviceType type, uint32_t device_idx)
|
|||||||
return rc;
|
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)
|
void print_video_devices(ToxWindow* self, VideoDeviceType type)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -153,7 +153,9 @@ struct ToxWindow {
|
|||||||
int ringing_sound;
|
int ringing_sound;
|
||||||
|
|
||||||
#ifdef VIDEO
|
#ifdef VIDEO
|
||||||
|
|
||||||
int video_device_selection[2]; /* -1 if not set, if set uses these selections instead of primary video device */
|
int video_device_selection[2]; /* -1 if not set, if set uses these selections instead of primary video device */
|
||||||
|
|
||||||
#endif /* VIDEO */
|
#endif /* VIDEO */
|
||||||
|
|
||||||
#endif /* AUDIO */
|
#endif /* AUDIO */
|
||||||
|
Loading…
Reference in New Issue
Block a user