/** * gst_vaapi_surface_put_image: * @surface: a #GstVaapiSurface * @image: a #GstVaapiImage * * Copies data from a #GstVaapiImage into a @surface. The @image must * have a format supported by the @surface. * * Return value: %TRUE on success */ gboolean gst_vaapi_surface_put_image (GstVaapiSurface * surface, GstVaapiImage * image) { GstVaapiDisplay *display; VAImageID image_id; VAStatus status; guint width, height; g_return_val_if_fail (surface != NULL, FALSE); g_return_val_if_fail (image != NULL, FALSE); display = GST_VAAPI_OBJECT_DISPLAY (surface); if (!display) return FALSE; width = GST_VAAPI_IMAGE_WIDTH (image); height = GST_VAAPI_IMAGE_HEIGHT (image); if (width != surface->width || height != surface->height) return FALSE; image_id = GST_VAAPI_OBJECT_ID (image); if (image_id == VA_INVALID_ID) return FALSE; GST_VAAPI_DISPLAY_LOCK (display); status = vaPutImage (GST_VAAPI_DISPLAY_VADISPLAY (display), GST_VAAPI_OBJECT_ID (surface), image_id, 0, 0, width, height, 0, 0, width, height); GST_VAAPI_DISPLAY_UNLOCK (display); if (!vaapi_check_status (status, "vaPutImage()")) return FALSE; return TRUE; }
static void vaapi_unmap_frame(void *opaque, uint8_t *data) { AVHWFramesContext *hwfc = opaque; AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; VAAPISurfaceMap *map = (VAAPISurfaceMap*)data; const AVFrame *src; VASurfaceID surface_id; VAStatus vas; src = map->source; surface_id = (VASurfaceID)(uintptr_t)src->data[3]; av_log(hwfc, AV_LOG_DEBUG, "Unmap surface %#x.\n", surface_id); vas = vaUnmapBuffer(hwctx->display, map->image.buf); if (vas != VA_STATUS_SUCCESS) { av_log(hwfc, AV_LOG_ERROR, "Failed to unmap image from surface " "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas)); } if ((map->flags & VAAPI_MAP_WRITE) && !(map->flags & VAAPI_MAP_DIRECT)) { vas = vaPutImage(hwctx->display, surface_id, map->image.image_id, 0, 0, hwfc->width, hwfc->height, 0, 0, hwfc->width, hwfc->height); if (vas != VA_STATUS_SUCCESS) { av_log(hwfc, AV_LOG_ERROR, "Failed to write image to surface " "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas)); } } vas = vaDestroyImage(hwctx->display, map->image.image_id); if (vas != VA_STATUS_SUCCESS) { av_log(hwfc, AV_LOG_ERROR, "Failed to destroy image from surface " "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas)); } av_free(map); }
static void* putsurface_thread(void *data) { int width=win_width, height=win_height; void *drawable = data; int quit = 0; VAStatus vaStatus; int row_shift = 0; int index = 0; unsigned int frame_num=0, start_time, putsurface_time; VARectangle cliprects[2]; /* client supplied clip list */ int continue_display = 0; if (drawable == drawable_thread0) printf("Enter into thread0\n\n"); if (drawable == drawable_thread1) printf("Enter into thread1\n\n"); putsurface_time = 0; while (!quit) { VASurfaceID surface_id = VA_INVALID_SURFACE; while (surface_id == VA_INVALID_SURFACE) surface_id = get_next_free_surface(&index); if (verbose) printf("Thread: %p Display surface 0x%x,\n", drawable, surface_id); if (multi_thread) upload_surface(va_dpy, surface_id, box_width, row_shift, display_field); if (check_event) pthread_mutex_lock(&gmutex); start_time = get_tick_count(); if ((continue_display == 0) && getenv("FRAME_STOP")) { char c; printf("Press any key to display frame %d...(c/C to continue)\n", frame_num); c = getchar(); if (c == 'c' || c == 'C') continue_display = 1; } if (test_color_conversion) { static int _put_surface_count = 0; if (_put_surface_count++ %50 == 0) { printf("do additional colorcoversion from %s to %s\n", map_vafourcc_to_str(csc_src_fourcc), map_vafourcc_to_str(csc_dst_fourcc)); } // get image from surface, csc_src_fourcc to csc_dst_fourcc conversion happens vaStatus = vaGetImage(va_dpy, surface_id, 0, 0, surface_width, surface_height, csc_dst_fourcc_image.image_id); CHECK_VASTATUS(vaStatus,"vaGetImage"); // render csc_dst_fourcc image to temp surface vaStatus = vaPutImage(va_dpy, csc_render_surface, csc_dst_fourcc_image.image_id, 0, 0, surface_width, surface_height, 0, 0, surface_width, surface_height); CHECK_VASTATUS(vaStatus,"vaPutImage"); // render the temp surface, it should be same with original surface without color conversion test vaStatus = vaPutSurface(va_dpy, csc_render_surface, CAST_DRAWABLE(drawable), 0,0,surface_width,surface_height, 0,0,width,height, (test_clip==0)?NULL:&cliprects[0], (test_clip==0)?0:2, display_field); CHECK_VASTATUS(vaStatus,"vaPutSurface"); } else { vaStatus = vaPutSurface(va_dpy, surface_id, CAST_DRAWABLE(drawable), 0,0,surface_width,surface_height, 0,0,width,height, (test_clip==0)?NULL:&cliprects[0], (test_clip==0)?0:2, display_field); CHECK_VASTATUS(vaStatus,"vaPutSurface"); } putsurface_time += (get_tick_count() - start_time); if (check_event) pthread_mutex_unlock(&gmutex); pthread_mutex_unlock(&surface_mutex[index]); /* locked in get_next_free_surface */ if ((frame_num % 0xff) == 0) { fprintf(stderr, "%.2f FPS \r", 256000.0 / (float)putsurface_time); putsurface_time = 0; update_clipbox(cliprects, width, height); } if (check_event) check_window_event(win_display, drawable, &width, &height, &quit); if (multi_thread) { /* reload surface content */ row_shift++; if (row_shift==(2*box_width)) row_shift= 0; } if (frame_rate != 0) /* rough framerate control */ usleep(1000/frame_rate*1000); frame_num++; if (frame_num >= frame_num_total) quit = 1; } if (drawable == drawable_thread1) pthread_exit(NULL); return 0; }