Skip to content

Instantly share code, notes, and snippets.

@OliverUv
Created October 13, 2014 22:05
Show Gist options
  • Save OliverUv/3d7d3f701a2a26a79aba to your computer and use it in GitHub Desktop.
Save OliverUv/3d7d3f701a2a26a79aba to your computer and use it in GitHub Desktop.
Files that bug unite-outline
#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;
}
#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