yuv_image decode_frame(const xyuv::frame &frame_in) { // Determine the size of each plane. bool has_y = !frame_in.format.channel_blocks[channel::Y].samples.empty(); bool has_u = !frame_in.format.channel_blocks[channel::U].samples.empty(); bool has_v = !frame_in.format.channel_blocks[channel::V].samples.empty(); bool has_a = !frame_in.format.channel_blocks[channel::A].samples.empty(); yuv_image yuva_out = create_yuv_image( frame_in.format.image_w, frame_in.format.image_h, frame_in.format.chroma_siting, has_y, has_u, has_v, has_a ); bool has_negative_line_stride = (frame_in.format.origin == image_origin::LOWER_LEFT); const uint8_t * raw_data = frame_in.data.get(); std::unique_ptr<uint8_t> tmp_buffer; if (needs_reorder(frame_in.format)) { // Todo: If needed optimize this for memory. // At some point we will have allocated 2x frame + 1 plane. tmp_buffer.reset(new uint8_t[frame_in.format.size]); memcpy(tmp_buffer.get(), raw_data, frame_in.format.size); // Use the copy instead. raw_data = tmp_buffer.get(); for (auto & plane : frame_in.format.planes) { reorder_inverse(tmp_buffer.get(), plane); } } if (has_y) decode_channel( raw_data, frame_in.format.channel_blocks[channel::Y], &(yuva_out.y_plane), frame_in.format.planes, frame_in.format.conversion_matrix.y_packed_range, has_negative_line_stride ); if (has_u) decode_channel( raw_data, frame_in.format.channel_blocks[channel::U], &(yuva_out.u_plane), frame_in.format.planes, frame_in.format.conversion_matrix.u_packed_range, has_negative_line_stride ); if (has_v) decode_channel( raw_data, frame_in.format.channel_blocks[channel::V], &(yuva_out.v_plane), frame_in.format.planes, frame_in.format.conversion_matrix.v_packed_range, has_negative_line_stride ); if (has_a) decode_channel( raw_data, frame_in.format.channel_blocks[channel::A], &(yuva_out.a_plane), frame_in.format.planes, std::make_pair<float, float>(0.0f, 1.0f), has_negative_line_stride ); return yuva_out; }
static int video_arch_frame_buffer_alloc(video_canvas_t *canvas, unsigned int width, unsigned int height) { int sizeofpixel = sizeof(BYTE); Display *display; #ifdef USE_MITSHM int (*olderrorhandler)(Display *, XErrorEvent *); #endif #ifdef USE_MITSHM canvas->using_mitshm = use_mitshm; #endif display = x11ui_get_display_ptr(); /* sizeof(PIXEL) is not always what we are using. I guess this should be checked from the XImage but I'm lazy... */ if (canvas->depth > 8) { sizeofpixel *= 2; } if (canvas->depth > 16) { sizeofpixel *= 2; } canvas->videoconfig->readable = 1; /* it's not direct rendering */ #ifdef HAVE_XVIDEO canvas->xv_image = NULL; if (canvas->videoconfig->hwscale) { #if defined(__QNX__) || defined(MINIX_SUPPORT) XShmSegmentInfo* shminfo = NULL; #else XShmSegmentInfo* shminfo = canvas->using_mitshm ? &canvas->xshm_info : NULL; #endif for (;;) { canvas->xv_image = create_yuv_image(display, canvas->xv_port, canvas->xv_format, width, height, shminfo); if (canvas->xv_image) { break; } if (shminfo) { #ifndef __QNX__ canvas->using_mitshm = 0; #endif shminfo = NULL; continue; } return -1; } XSync(display, False); /* Copy data for architecture independent rendering. */ canvas->yuv_image.width = canvas->xv_image->width; canvas->yuv_image.height = canvas->xv_image->height; canvas->yuv_image.data_size = canvas->xv_image->data_size; canvas->yuv_image.num_planes = canvas->xv_image->num_planes; canvas->yuv_image.pitches = canvas->xv_image->pitches; canvas->yuv_image.offsets = canvas->xv_image->offsets; canvas->yuv_image.data = (unsigned char *)canvas->xv_image->data; log_message(x11video_log, "Successfully initialized using XVideo (%dx%d %.4s)%s shared memory.", width, height, canvas->xv_format.label, #ifndef __QNX__ canvas->using_mitshm ? ", using" : " without"); #else " without"); #endif return 0; }
static int video_arch_frame_buffer_alloc(video_canvas_t *canvas, unsigned int width, unsigned int height) { int sizeofpixel = sizeof(BYTE); Display *display; #ifdef USE_MITSHM int (*olderrorhandler)(Display *, XErrorEvent *); int dummy; #endif #ifdef USE_MITSHM canvas->using_mitshm = use_mitshm; #endif display = x11ui_get_display_ptr(); /* sizeof(PIXEL) is not always what we are using. I guess this should be checked from the XImage but I'm lazy... */ if (canvas->depth > 8) { sizeofpixel *= 2; } if (canvas->depth > 16) { sizeofpixel *= 2; } #ifdef HAVE_XVIDEO canvas->xv_image = NULL; if (canvas->videoconfig->hwscale) { #if defined(__QNX__) || defined(MINIX_SUPPORT) XShmSegmentInfo* shminfo = NULL; #else XShmSegmentInfo* shminfo = use_mitshm ? &canvas->xshm_info : NULL; #endif canvas->xv_image = create_yuv_image(display, canvas->xv_port, canvas->xv_format, width, height, shminfo); if (!(canvas->xv_image)) { return -1; } /* Copy data for architecture independent rendering. */ canvas->yuv_image.width = canvas->xv_image->width; canvas->yuv_image.height = canvas->xv_image->height; canvas->yuv_image.data_size = canvas->xv_image->data_size; canvas->yuv_image.num_planes = canvas->xv_image->num_planes; canvas->yuv_image.pitches = canvas->xv_image->pitches; canvas->yuv_image.offsets = canvas->xv_image->offsets; canvas->yuv_image.data = (unsigned char *)canvas->xv_image->data; log_message(x11video_log, "Successfully initialized using XVideo (%dx%d %.4s).", width, height, canvas->xv_format.label); return 0; } #endif /* HAVE_XVIDEO */ /* Round up to 32-bit boundary (used in XCreateImage). */ width = (width + 3) & ~0x3; #ifdef USE_MITSHM tryagain: if (canvas->using_mitshm) { DEBUG_MITSHM(("frame_buffer_alloc(): allocating XImage with MITSHM, %d x %d pixels...", width, height)); canvas->x_image = XShmCreateImage(display, visual, canvas->depth, ZPixmap, NULL, &(canvas->xshm_info), width, height); if (!canvas->x_image) { log_warning(x11video_log, "Cannot allocate XImage with XShm; falling back to non MITSHM extension mode."); canvas->using_mitshm = 0; goto tryagain; } DEBUG_MITSHM(("Done.")); DEBUG_MITSHM(("frame_buffer_alloc(): shmgetting %ld bytes...", (long)canvas->x_image->bytes_per_line * canvas->x_image->height)); canvas->xshm_info.shmid = shmget(IPC_PRIVATE, canvas->x_image->bytes_per_line * canvas->x_image->height, IPC_CREAT | 0604); if (canvas->xshm_info.shmid == -1) { log_warning(x11video_log, "Cannot get shared memory; falling back to non MITSHM extension mode."); XDestroyImage(canvas->x_image); canvas->using_mitshm = 0; goto tryagain; } DEBUG_MITSHM(("Done, id = 0x%x.", i->xshm_info.shmid)); DEBUG_MITSHM(("frame_buffer_alloc(): getting address... ")); canvas->xshm_info.shmaddr = shmat(canvas->xshm_info.shmid, 0, 0); canvas->x_image->data = canvas->xshm_info.shmaddr; if (canvas->xshm_info.shmaddr == (char *)-1) { log_warning(x11video_log, "Cannot get shared memory address; falling back to non MITSHM extension mode."); shmctl(canvas->xshm_info.shmid,IPC_RMID,0); XDestroyImage(canvas->x_image); canvas->using_mitshm = 0; goto tryagain; } DEBUG_MITSHM(("0x%lx OK.", (unsigned long) i->xshm_info.shmaddr)); canvas->xshm_info.readOnly = True; mitshm_failed = 0; XQueryExtension(display,"MIT-SHM",&shmmajor,&dummy,&dummy); olderrorhandler = XSetErrorHandler(shmhandler); if (!XShmAttach(display, &(canvas->xshm_info))) { log_warning(x11video_log, "Cannot attach shared memory; falling back to non MITSHM extension mode."); shmdt(canvas->xshm_info.shmaddr); shmctl(canvas->xshm_info.shmid,IPC_RMID,0); XDestroyImage(canvas->x_image); canvas->using_mitshm = 0; goto tryagain; } /* Wait for XShmAttach to fail or to succede. */ XSync(display,False); XSetErrorHandler(olderrorhandler); /* Mark memory segment for automatic deletion. */ shmctl(canvas->xshm_info.shmid, IPC_RMID, 0); if (mitshm_failed) { log_warning(x11video_log, "Cannot attach shared memory; falling back to non MITSHM extension mode."); shmdt(canvas->xshm_info.shmaddr); XDestroyImage(canvas->x_image); canvas->using_mitshm = 0; goto tryagain; } DEBUG_MITSHM((_("MITSHM initialization succeed.\n"))); video_refresh_func((void (*)(void))XShmPutImage); } else #endif { /* !i->using_mitshm */ char *data; data = lib_malloc(width * height * sizeofpixel); if (data == NULL) { return -1; } canvas->x_image = XCreateImage(display, visual, canvas->depth, ZPixmap, 0, data, width, height, 32, 0); if (!canvas->x_image) { return -1; } video_refresh_func((void (*)(void))XPutImage); } #ifdef USE_MITSHM log_message(x11video_log, "Successfully initialized%s shared memory.", (canvas->using_mitshm) ? ", using" : " without"); if (!(canvas->using_mitshm)) { log_warning(x11video_log, "Performance will be poor."); } #else log_message(x11video_log, "Successfully initialized without shared memory."); #endif return 0; }