Created
October 13, 2014 22:05
-
-
Save OliverUv/3d7d3f701a2a26a79aba to your computer and use it in GitHub Desktop.
Files that bug unite-outline
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "libsc.h" | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <time.h> | |
#include <math.h> | |
#include <X11/X.h> | |
#include <X11/Xlib.h> | |
#include <X11/Xutil.h> | |
// The internet says this is a bad idea, but it is the easiest way to | |
// include this stuff. Didn't manage to do it properly with an object | |
// file. | |
#include "webm_enc.cpp" | |
static int _XlibErrorHandler(Display *display, XErrorEvent *event) { | |
fprintf( | |
stderr, | |
"An error occured while calling Xlib.\n request id: %lu\n error code: %c\n request code: %d\n minor code: %d\n", | |
event->serial, | |
event->error_code, | |
event->request_code, | |
event->minor_code); | |
return True; | |
} | |
static unsigned long timespec_diff_ms(timespec start, timespec end) { | |
unsigned long diff; | |
timespec temp; | |
if (end.tv_nsec - start.tv_nsec < 0) { | |
// We need to borrow 1 sec so the nsec subtraction's | |
// difference doesn't end up in the negatives. | |
temp.tv_sec = end.tv_sec - start.tv_sec - 1; | |
temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec; | |
} else { | |
temp.tv_sec = end.tv_sec - start.tv_sec; | |
temp.tv_nsec = end.tv_nsec - start.tv_nsec; | |
} | |
diff = (unsigned long) temp.tv_sec * 1000; | |
diff += (unsigned long) temp.tv_nsec / 1000000; | |
return round(diff); | |
} | |
void | |
LinuxScreencapper::bootstrap( | |
int width, | |
int height, | |
int target_bitrate, | |
int screen, | |
unsigned char *byte_array, | |
FrameInfo *frame_info_out) { | |
outframe_dirty = false; | |
w = width; | |
h = height; | |
total_time = 0; | |
arr_argb_size = w*h*4; | |
arr_rgb_size = w*h*3; | |
frame_info = FrameInfo(); | |
clock_gettime(CLOCK_REALTIME, &last_timing); | |
// Setting the error handler causes a crash when running this code | |
// from a wxwidgets gui. Default libX11 behavior on crash is to | |
// print an error message and quit. | |
/* XSetErrorHandler(_XlibErrorHandler); */ | |
dpy = XOpenDisplay(NULL); | |
screen = XDefaultScreen(dpy); | |
target_win = RootWindow(dpy, screen); | |
number_of_screens = XScreenCount(dpy); | |
root_windows = (Window*) malloc(sizeof(Window) * number_of_screens); | |
for (int i = 0; i < number_of_screens; i++) { | |
root_windows[i] = XRootWindow(dpy, i); | |
} | |
// Initialize frame_info | |
unsigned long frame_duration = get_frame_duration(); | |
set_frame_info(frame_duration, total_time); | |
frame_info_out->copy(frame_info); | |
webm_setup(w, h, target_bitrate, reinterpret_cast<char**>(&outframe)); | |
memcpy(byte_array, outframe, 32); // Get file header. | |
} | |
void | |
LinuxScreencapper::cleanup() { | |
XCloseDisplay(dpy); | |
if (outframe_dirty) { | |
free(outframe); // This was malloc'd in webm_enc.c | |
} | |
} | |
void | |
LinuxScreencapper::fetch(unsigned char *byte_array_out, int frame_size, FrameInfo *frame_info_out) { | |
if (outframe_dirty) { | |
frame_info_out->copy(frame_info); | |
memcpy(byte_array_out, outframe, frame_size); | |
free(outframe); // This was malloc'd in webm_enc.c | |
} | |
outframe_dirty = false; | |
} | |
unsigned long | |
LinuxScreencapper::get_frame_duration() { | |
timespec now; | |
clock_gettime(CLOCK_REALTIME, &now); | |
double frame_duration_ms = timespec_diff_ms(last_timing, now); | |
total_time += frame_duration_ms; | |
clock_gettime(CLOCK_REALTIME, &last_timing); | |
if (frame_duration_ms == 0) | |
return 1; | |
return frame_duration_ms; | |
} | |
void | |
LinuxScreencapper::set_frame_info(unsigned long frame_duration, unsigned long total_duration) { | |
Window window_returned; | |
unsigned int mask_return; | |
int root_x, root_y; | |
int win_x, win_y; | |
bool result; | |
for (int i = 0; i < number_of_screens; i++) { | |
result = XQueryPointer(dpy, root_windows[i], &window_returned, | |
&window_returned, &root_x, &root_y, &win_x, &win_y, | |
&mask_return); | |
if (result == 1) { | |
break; | |
} | |
} | |
if (result != True) { | |
root_x = 0; | |
root_y = 0; | |
} else { | |
frame_info.mouse_x = root_x; | |
frame_info.mouse_y = root_y; | |
} | |
frame_info.frame_duration_ms = frame_duration; | |
frame_info.frame_timestamp_ms = total_duration; | |
} | |
int | |
LinuxScreencapper::capture() { | |
XImage* image; | |
image = XGetImage (dpy, target_win, 0, 0, w, h, AllPlanes, ZPixmap); | |
unsigned long frame_duration = get_frame_duration(); | |
set_frame_info(frame_duration, total_time); | |
char* rgb = image->data; | |
int frame_size = webm_encode( | |
(unsigned char*) image->data, | |
w, | |
h, | |
frame_duration, | |
(long) total_time, | |
reinterpret_cast<char**>(&outframe)); | |
if (frame_size > 0) | |
outframe_dirty = true; | |
image->data = rgb; | |
rgb = 0; | |
XDestroyImage(image); | |
return frame_size; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef LINUXSCREENCAPPER_H_PNABFI4H | |
#define LINUXSCREENCAPPER_H_PNABFI4H | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <X11/X.h> | |
#include <X11/Xlib.h> | |
#include <X11/Xutil.h> | |
// TODO Create an interface Screencapper that all native cappers fulfill. | |
class LinuxScreencapper { | |
public: | |
typedef struct FrameInfo { | |
unsigned int mouse_x; | |
unsigned int mouse_y; | |
unsigned long frame_duration_ms; | |
unsigned long frame_timestamp_ms; | |
void copy(const FrameInfo &from) { | |
this->mouse_x = from.mouse_x; | |
this->mouse_y = from.mouse_y; | |
this->frame_duration_ms = from.frame_duration_ms; | |
this->frame_timestamp_ms = from.frame_timestamp_ms; | |
} | |
} FrameInfo; | |
void bootstrap( | |
int width, | |
int height, | |
int taget_bitrate, | |
int screen, | |
// This byte_array has to be allocated by the caller, | |
// and should be 32 * sizeof(unsigned char) in size. (32 bytes.) | |
unsigned char *byte_array, | |
FrameInfo *frame_info_out); | |
void fetch(unsigned char *byte_array_out, int frame_size, FrameInfo *frame_info_out); | |
int capture(); | |
void cleanup(); | |
private: | |
Display *dpy; | |
int screen; | |
Window target_win; | |
Window *root_windows; | |
int w; | |
int h; | |
int arr_argb_size; | |
int arr_rgb_size; | |
int number_of_screens; | |
unsigned char* outframe; | |
bool outframe_dirty; | |
FrameInfo frame_info; | |
timespec last_timing; | |
unsigned long total_time; | |
void set_frame_info(unsigned long frame_duration, unsigned long total_duration); | |
unsigned long get_frame_duration(); | |
}; | |
#endif /* end of include guard: LINUXSCREENCAPPER_H_PNABFI4H */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment