40 #include "libavformat/avformat.h"
42 #include "libavutil/log.h"
43 #include "libavutil/opt.h"
44 #include "libavutil/parseutils.h"
45 #include "libavutil/time.h"
49 #include <X11/Xlibint.h>
50 #include <X11/Xproto.h>
51 #include <X11/Xutil.h>
53 #include <X11/extensions/shape.h>
54 #include <X11/extensions/XShm.h>
55 #include <X11/extensions/Xfixes.h>
84 #define REGION_WIN_BORDER 3
93 Display *dpy = s->
dpy;
98 screen = DefaultScreen(dpy);
99 gc = XCreateGC(dpy, win, 0, 0);
100 XSetForeground(dpy, gc, WhitePixel(dpy, screen));
101 XSetBackground(dpy, gc, BlackPixel(dpy, screen));
103 XDrawRectangle(dpy, win, gc,
118 Display *dpy = s->
dpy;
120 XSetWindowAttributes attribs;
123 screen = DefaultScreen(dpy);
124 attribs.override_redirect = True;
125 s->
region_win = XCreateWindow(dpy, RootWindow(dpy, screen),
131 InputOutput, CopyFromParent,
132 CWOverrideRedirect, &attribs);
135 rect.width = s->
width;
139 &rect, 1, ShapeSubtract, 0);
141 XSelectInput(dpy, s->
region_win, ExposureMask | StructureNotifyMask);
167 char *param, *offset;
175 offset = strchr(param,
'+');
177 sscanf(offset,
"%d,%d", &x_off, &y_off);
178 x11grab->
draw_mouse = !strstr(offset,
"nomouse");
190 av_log(s1,
AV_LOG_INFO,
"device: %s -> display: %s x: %d y: %d width: %d height: %d\n",
193 dpy = XOpenDisplay(param);
207 screen = DefaultScreen(dpy);
210 int screen_w, screen_h;
213 screen_w = DisplayWidth(dpy, screen);
214 screen_h = DisplayHeight(dpy, screen);
215 XQueryPointer(dpy, RootWindow(dpy, screen), &w, &w, &x_off, &y_off, &ret, &ret, &ret);
216 x_off -= x11grab->
width / 2;
217 y_off -= x11grab->
height / 2;
220 av_log(s1,
AV_LOG_INFO,
"followmouse is enabled, resetting grabbing region to x: %d y: %d\n", x_off, y_off);
223 use_shm = XShmQueryExtension(dpy);
224 av_log(s1,
AV_LOG_INFO,
"shared memory extension %s found\n", use_shm ?
"" :
"not");
227 int scr = XDefaultScreen(dpy);
228 image = XShmCreateImage(dpy,
229 DefaultVisual(dpy, scr),
230 DefaultDepth(dpy, scr),
235 x11grab->
shminfo.shmid = shmget(IPC_PRIVATE,
236 image->bytes_per_line * image->height,
238 if (x11grab->
shminfo.shmid == -1) {
243 x11grab->
shminfo.shmaddr = image->data = shmat(x11grab->
shminfo.shmid, 0, 0);
244 x11grab->
shminfo.readOnly = False;
246 if (!XShmAttach(dpy, &x11grab->
shminfo)) {
253 image = XGetImage(dpy, RootWindow(dpy, screen),
259 switch (image->bits_per_pixel) {
265 if ( image->red_mask == 0xf800 &&
266 image->green_mask == 0x07e0 &&
267 image->blue_mask == 0x001f ) {
270 }
else if (image->red_mask == 0x7c00 &&
271 image->green_mask == 0x03e0 &&
272 image->blue_mask == 0x001f ) {
276 av_log(s1,
AV_LOG_ERROR,
"RGB ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel);
277 av_log(s1,
AV_LOG_ERROR,
"color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask);
283 if ( image->red_mask == 0xff0000 &&
284 image->green_mask == 0x00ff00 &&
285 image->blue_mask == 0x0000ff ) {
287 }
else if ( image->red_mask == 0x0000ff &&
288 image->green_mask == 0x00ff00 &&
289 image->blue_mask == 0xff0000 ) {
292 av_log(s1,
AV_LOG_ERROR,
"rgb ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel);
293 av_log(s1,
AV_LOG_ERROR,
"color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask);
302 av_log(s1,
AV_LOG_ERROR,
"image depth %i not supported ... aborting\n", image->bits_per_pixel);
344 XFixesCursorImage *xcim;
347 int to_line, to_column;
348 int pixstride = image->bits_per_pixel >> 3;
356 if (image->bits_per_pixel != 24 && image->bits_per_pixel != 32)
359 xcim = XFixesGetCursorImage(dpy);
361 x = xcim->x - xcim->xhot;
362 y = xcim->y - xcim->yhot;
364 to_line =
FFMIN((y + xcim->height), (height + y_off));
365 to_column =
FFMIN((x + xcim->width), (width + x_off));
367 for (line =
FFMAX(y, y_off); line < to_line; line++) {
368 for (column =
FFMAX(x, x_off); column < to_column; column++) {
369 int xcim_addr = (line - y) * xcim->width + column - x;
370 int image_addr = ((line - y_off) * width + column -
x_off) * pixstride;
371 int r = (
uint8_t)(xcim->pixels[xcim_addr] >> 0);
372 int g = (
uint8_t)(xcim->pixels[xcim_addr] >> 8);
373 int b = (
uint8_t)(xcim->pixels[xcim_addr] >> 16);
374 int a = (
uint8_t)(xcim->pixels[xcim_addr] >> 24);
377 pix[image_addr+0] =
r;
378 pix[image_addr+1] =
g;
379 pix[image_addr+2] =
b;
382 pix[image_addr+0] = r + (pix[image_addr+0]*(255-
a) + 255/2) / 255;
383 pix[image_addr+1] = g + (pix[image_addr+1]*(255-
a) + 255/2) / 255;
384 pix[image_addr+2] = b + (pix[image_addr+2]*(255-
a) + 255/2) / 255;
416 GetReq(GetImage, req);
422 req->width = image->width;
423 req->height = image->height;
424 req->planeMask = (
unsigned int)AllPlanes;
425 req->format = ZPixmap;
427 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.length) {
433 nbytes = (long)rep.length << 2;
434 _XReadPad(dpy, image->data, nbytes);
461 int64_t curtime, delay;
477 ts.tv_sec = delay / 1000000;
478 ts.tv_nsec = (delay % 1000000) * 1000;
479 nanosleep(&ts,
NULL);
483 pkt->
data = image->data;
487 screen = DefaultScreen(dpy);
488 root = RootWindow(dpy, screen);
490 int screen_w, screen_h;
491 int pointer_x, pointer_y,
_;
494 screen_w = DisplayWidth(dpy, screen);
495 screen_h = DisplayHeight(dpy, screen);
496 XQueryPointer(dpy, root, &w, &w, &pointer_x, &pointer_y, &_, &_, &_);
497 if (follow_mouse == -1) {
499 x_off += pointer_x - s->
width / 2 - x_off;
500 y_off += pointer_y - s->
height / 2 - y_off;
504 if (pointer_x > x_off + s->
width - follow_mouse) {
505 x_off += pointer_x - (x_off + s->
width - follow_mouse);
506 }
else if (pointer_x < x_off + follow_mouse)
507 x_off -= (x_off + follow_mouse) - pointer_x;
508 if (pointer_y > y_off + s->
height - follow_mouse) {
509 y_off += pointer_y - (y_off + s->
height - follow_mouse);
510 }
else if (pointer_y < y_off + follow_mouse)
511 y_off -= (y_off + follow_mouse) - pointer_y;
527 for (evt.type = NoEventMask; XCheckMaskEvent(dpy, ExposureMask | StructureNotifyMask, &evt); );
536 if (!XShmGetImage(dpy, root, image, x_off, y_off, AllPlanes)) {
566 shmdt(x11grab->
shminfo.shmaddr);
571 if (x11grab->
image) {
572 XDestroyImage(x11grab->
image);
581 XCloseDisplay(x11grab->
dpy);
585 #define OFFSET(x) offsetof(struct x11grab, x)
586 #define DEC AV_OPT_FLAG_DECODING_PARAM
591 {
"follow_mouse",
"Move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region.",
593 {
"centered",
"Keep the mouse pointer at the center of grabbing region when following.", 0,
AV_OPT_TYPE_CONST, { .i64 = -1 }, INT_MIN, INT_MAX,
DEC,
"follow_mouse" },
609 .priv_data_size =
sizeof(
struct x11grab),
static int x11grab_read_header(AVFormatContext *s1)
Initialize the x11 grab device demuxer (public device demuxer API).
int y_off
Vertical top-left corner coordinate.
AVInputFormat ff_x11grab_demuxer
x11 grabber device demuxer declaration
packed RGB 8:8:8, 24bpp, RGBRGB...
char * av_strdup(const char *s) av_malloc_attrib
Duplicate the string s.
#define REGION_WIN_BORDER
AVCodecContext * codec
Codec context associated with this stream.
void av_log(void *avcl, int level, const char *fmt,...) av_printf_format(3
Send the specified message to the log if the level is less than or equal to the current av_log_level...
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
int show_region
set by a private option.
static int x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
Grab a frame from x11 (public device demuxer API).
int height
Height of the grab frame.
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
XShmSegmentInfo shminfo
When using XShm, keeps track of XShm infos.
static void x11grab_region_win_init(struct x11grab *s)
Initialize grabbing region window.
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
static double av_q2d(AVRational a)
Convert rational to double.
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
AVRational time_base
Time base.
static const AVOption options[]
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
void * priv_data
Format private data.
char filename[1024]
input or output filename
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
static const AVClass x11_class
int draw_mouse
Set by a private option.
static int x11grab_read_close(AVFormatContext *s1)
Close x11 frame grabber (public device demuxer API).
AVPixelFormat
Pixel format.
int av_parse_video_rate(AVRational *rate, const char *str)
Parse str and store the detected values in *rate.
XImage * image
X11 image holding the grab.
char * video_size
String describing video size, set by a private option.
int follow_mouse
Set by a private option.
int64_t av_gettime(void)
Get the current time in microseconds.
static int xget_zpixmap(Display *dpy, Drawable d, XImage *image, int x, int y)
Read new data in the image structure.
int bit_rate
the average bitrate
int width
picture width / height.
static void paint_mouse_pointer(XImage *image, struct x11grab *s)
Paint a mouse pointer in an X11 image.
int use_shm
!0 when using XShm extension
int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
Parse str and put in width_ptr and height_ptr the detected values.
8 bit with PIX_FMT_RGB32 palette
static SDL_Surface * screen
#define AV_LOG_INFO
Standard information.
int frame_size
Size in bytes of a grabbed frame.
enum AVMediaType codec_type
static void x11grab_draw_region_win(struct x11grab *s)
Draw grabbing region window.
#define AV_PIX_FMT_RGB555
char * framerate
Set by a private option.
packed RGB 8:8:8, 24bpp, BGRBGR...
Describe the class of an AVClass context structure.
rational number numerator/denominator
int x_off
Horizontal top-left corner coordinate.
Window region_win
This is used by show_region option.
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31))))#defineSET_CONV_FUNC_GROUP(ofmt, ifmt) staticvoidset_generic_function(AudioConvert *ac){}voidff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, intsample_rate, intapply_map){AudioConvert *ac;intin_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) returnNULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt)>2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);returnNULL;}returnac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}elseif(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;elseac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);returnac;}intff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){intuse_generic=1;intlen=in->nb_samples;intp;if(ac->dc){av_dlog(ac->avr,"%dsamples-audio_convert:%sto%s(dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));returnff_convert_dither(ac-> out
#define AV_PIX_FMT_RGB565
int64_t time_frame
Current time.
X11 Device Demuxer context.
void av_init_packet(AVPacket *pkt)
Initialize optional fields of a packet with default values.
int width
Width of the grab frame.
av_default_item_name
Return the context name.
This structure stores compressed data.
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Display * dpy
X11 display from which x11grab grabs frames.