/** * Grab a frame from x11 (public device demuxer API). * * @param s1 Context from avformat core * @param pkt Packet holding the brabbed frame * @return frame size in bytes */ static int x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt) { struct x11_grab *s = s1->priv_data; Display *dpy = s->dpy; XImage *image = s->image; int x_off = s->x_off; int y_off = s->y_off; int64_t curtime, delay; struct timespec ts; /* Calculate the time of the next frame */ s->time_frame += INT64_C(1000000); /* wait based on the frame rate */ for(;;) { curtime = av_gettime(); delay = s->time_frame * av_q2d(s->time_base) - curtime; if (delay <= 0) { if (delay < INT64_C(-1000000) * av_q2d(s->time_base)) { s->time_frame += INT64_C(1000000); } break; } ts.tv_sec = delay / 1000000; ts.tv_nsec = (delay % 1000000) * 1000; nanosleep(&ts, NULL); } if (av_new_packet(pkt, s->frame_size) < 0) { return AVERROR(EIO); } pkt->pts = curtime; if(s->use_shm) { if (!XShmGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off, AllPlanes)) { av_log (s1, AV_LOG_INFO, "XShmGetImage() failed\n"); } } else { if (!xget_zpixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off)) { av_log (s1, AV_LOG_INFO, "XGetZPixmap() failed\n"); } } if(!s->nomouse){ paint_mouse_pointer(image, s); } /* XXX: avoid memcpy */ memcpy(pkt->data, image->data, s->frame_size); return s->frame_size; }
/** * Grab a frame from x11 (public device demuxer API). * * @param s1 Context from avformat core * @param pkt Packet holding the brabbed frame * @return frame size in bytes */ static int x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt) { struct x11_grab *s = s1->priv_data; Display *dpy = s->dpy; XImage *image = s->image; int x_off = s->x_off; int y_off = s->y_off; int screen; Window root; int follow_mouse = s->follow_mouse; int64_t curtime, delay; struct timespec ts; /* Calculate the time of the next frame */ s->time_frame += INT64_C(1000000); /* wait based on the frame rate */ for(;;) { curtime = av_gettime(); delay = s->time_frame * av_q2d(s->time_base) - curtime; if (delay <= 0) { if (delay < INT64_C(-1000000) * av_q2d(s->time_base)) { s->time_frame += INT64_C(1000000); } break; } ts.tv_sec = delay / 1000000; ts.tv_nsec = (delay % 1000000) * 1000; nanosleep(&ts, NULL); } av_init_packet(pkt); pkt->data = image->data; pkt->size = s->frame_size; pkt->pts = curtime; screen = DefaultScreen(dpy); root = RootWindow(dpy, screen); if (follow_mouse) { int screen_w, screen_h; int pointer_x, pointer_y, _; Window w; screen_w = DisplayWidth(dpy, screen); screen_h = DisplayHeight(dpy, screen); XQueryPointer(dpy, root, &w, &w, &pointer_x, &pointer_y, &_, &_, &_); if (follow_mouse == -1) { // follow the mouse, put it at center of grabbing region x_off += pointer_x - s->width / 2 - x_off; y_off += pointer_y - s->height / 2 - y_off; } else { // follow the mouse, but only move the grabbing region when mouse // reaches within certain pixels to the edge. if (pointer_x > x_off + s->width - follow_mouse) { x_off += pointer_x - (x_off + s->width - follow_mouse); } else if (pointer_x < x_off + follow_mouse) x_off -= (x_off + follow_mouse) - pointer_x; if (pointer_y > y_off + s->height - follow_mouse) { y_off += pointer_y - (y_off + s->height - follow_mouse); } else if (pointer_y < y_off + follow_mouse) y_off -= (y_off + follow_mouse) - pointer_y; } // adjust grabbing region position if it goes out of screen. s->x_off = x_off = FFMIN(FFMAX(x_off, 0), screen_w - s->width); s->y_off = y_off = FFMIN(FFMAX(y_off, 0), screen_h - s->height); if (s->show_region && s->region_win) XMoveWindow(dpy, s->region_win, s->x_off - REGION_WIN_BORDER, s->y_off - REGION_WIN_BORDER); } if (s->show_region) { if (s->region_win) { XEvent evt; // clean up the events, and do the initinal draw or redraw. for (evt.type = NoEventMask; XCheckMaskEvent(dpy, ExposureMask | StructureNotifyMask, &evt); ); if (evt.type) x11grab_draw_region_win(s); } else { x11grab_region_win_init(s); } } if(s->use_shm) { if (!XShmGetImage(dpy, root, image, x_off, y_off, AllPlanes)) { av_log (s1, AV_LOG_INFO, "XShmGetImage() failed\n"); } } else { if (!xget_zpixmap(dpy, root, image, x_off, y_off)) { av_log (s1, AV_LOG_INFO, "XGetZPixmap() failed\n"); } } if (s->draw_mouse) { paint_mouse_pointer(image, s); } return s->frame_size; }
/** * Grabs a frame from gdi (public device demuxer API). * * @param s1 Context from avformat core * @param pkt Packet holding the grabbed frame * @return frame size in bytes */ static int gdigrab_read_packet(AVFormatContext *s1, AVPacket *pkt) { struct gdigrab *gdigrab = s1->priv_data; HDC dest_hdc = gdigrab->dest_hdc; HDC source_hdc = gdigrab->source_hdc; RECT clip_rect = gdigrab->clip_rect; AVRational time_base = gdigrab->time_base; int64_t time_frame = gdigrab->time_frame; BITMAPFILEHEADER bfh; int file_size = gdigrab->header_size + gdigrab->frame_size; int64_t curtime, delay; /* Calculate the time of the next frame */ time_frame += INT64_C(1000000); /* Run Window message processing queue */ if (gdigrab->show_region) gdigrab_region_wnd_update(s1, gdigrab); /* wait based on the frame rate */ for (;;) { curtime = av_gettime(); delay = time_frame * av_q2d(time_base) - curtime; if (delay <= 0) { if (delay < INT64_C(-1000000) * av_q2d(time_base)) { time_frame += INT64_C(1000000); } break; } if (s1->flags & AVFMT_FLAG_NONBLOCK) { return AVERROR(EAGAIN); } else { av_usleep(delay); } } if (av_new_packet(pkt, file_size) < 0) return AVERROR(ENOMEM); pkt->pts = curtime; /* Blit screen grab */ if (!BitBlt(dest_hdc, 0, 0, clip_rect.right - clip_rect.left, clip_rect.bottom - clip_rect.top, source_hdc, clip_rect.left, clip_rect.top, SRCCOPY | CAPTUREBLT)) { WIN32_API_ERROR("Failed to capture image"); return AVERROR(EIO); } if (gdigrab->draw_mouse) paint_mouse_pointer(s1, gdigrab); /* Copy bits to packet data */ bfh.bfType = 0x4d42; /* "BM" in little-endian */ bfh.bfSize = file_size; bfh.bfReserved1 = 0; bfh.bfReserved2 = 0; bfh.bfOffBits = gdigrab->header_size; memcpy(pkt->data, &bfh, sizeof(bfh)); memcpy(pkt->data + sizeof(bfh), &gdigrab->bmi.bmiHeader, sizeof(gdigrab->bmi.bmiHeader)); if (gdigrab->bmi.bmiHeader.biBitCount <= 8) GetDIBColorTable(dest_hdc, 0, 1 << gdigrab->bmi.bmiHeader.biBitCount, (RGBQUAD *) (pkt->data + sizeof(bfh) + sizeof(gdigrab->bmi.bmiHeader))); memcpy(pkt->data + gdigrab->header_size, gdigrab->buffer, gdigrab->frame_size); gdigrab->time_frame = time_frame; return gdigrab->header_size + gdigrab->frame_size; }