Exemple #1
0
static void put_updated_rectangle(rfbClient *client, int x, int y, int width, int height, int f_width, int f_height, int first_for_frame)
{
    if (curr_surface == VA_INVALID_ID) {
        rfbClientErr("%s: called, but current surface is invalid\n", __FUNCTION__);
        return;
    }

    VAStatus va_status;

    if (client->outputWindow) {
        /* use efficient vaPutSurface() method of putting the framebuffer on the screen */
        if (first_for_frame) {
            /* vaPutSurface() clears window contents outside the given destination rectangle => always update full screen. */
            va_status = vaPutSurface(va_dpy, curr_surface, client->outputWindow, 0, 0, f_width, f_height, 0, 0, f_width, f_height, NULL, 0, VA_FRAME_PICTURE);
            CHECK_VASTATUS(va_status, "vaPutSurface");
        }
    }
    else if (client->frameBuffer) {
        /* ... or copy the changed framebuffer region manually as a fallback */
        VAImage decoded_image;
        decoded_image.image_id = VA_INVALID_ID;
        decoded_image.buf      = VA_INVALID_ID;
        va_status = vaDeriveImage(va_dpy, curr_surface, &decoded_image);
        CHECK_VASTATUS(va_status, "vaDeriveImage");

        if ((decoded_image.image_id == VA_INVALID_ID) || (decoded_image.buf == VA_INVALID_ID)) {
            rfbClientErr("%s: vaDeriveImage() returned success but VA image is invalid (id: %d, buf: %d)\n", __FUNCTION__, decoded_image.image_id, decoded_image.buf);
        }

        nv12_to_rgba(decoded_image, client, x, y, width, height);

        va_status = vaDestroyImage(va_dpy, decoded_image.image_id);
        CHECK_VASTATUS(va_status, "vaDestroyImage");
    }
}
Exemple #2
0
int csc_preparation ()
{
    VAStatus va_status;
    
    // 1. make sure dst fourcc is supported for vaImage
    if (!lookup_image_format(csc_dst_fourcc)) {
        test_color_conversion = 0;
        printf("VA driver doesn't support %s image, skip additional color conversion\n",  map_vafourcc_to_str(csc_dst_fourcc));
        goto cleanup;
    }

    // 2. make sure src_fourcc is supported for vaSurface
    VASurfaceAttrib surface_attribs[1], * const s_attrib = &surface_attribs[0];
    s_attrib->type = VASurfaceAttribPixelFormat;
    s_attrib->flags = VA_SURFACE_ATTRIB_SETTABLE;
    s_attrib->value.type = VAGenericValueTypeInteger;
    s_attrib->value.value.i = csc_src_fourcc;

    if (!lookup_surface_attrib(VASurfaceAttribPixelFormat, &s_attrib->value)) {
        printf("VA driver doesn't support %s surface, skip additional color conversion\n",  map_vafourcc_to_str(csc_src_fourcc));
        test_color_conversion = 0;
        goto cleanup;
    }

    // 3 create all objs required by csc
    // 3.1 vaSurface with src fourcc
    va_status = vaCreateSurfaces(
        va_dpy,
        VA_RT_FORMAT_YUV420, surface_width, surface_height,
        &surface_id[0], SURFACE_NUM,
        surface_attribs, 1
    );
    CHECK_VASTATUS(va_status,"vaCreateSurfaces");

    // 3.2 vaImage with dst fourcc
    VAImageFormat image_format;
    image_format.fourcc = csc_dst_fourcc;
    image_format.byte_order = VA_LSB_FIRST;
    image_format.bits_per_pixel = 16;
    
    va_status = vaCreateImage(va_dpy, &image_format,
                    surface_width, surface_height,
                    &csc_dst_fourcc_image);
    CHECK_VASTATUS(va_status,"vaCreateImage");
    

    // 3.3 create a temp VASurface for final rendering(vaPutSurface)
    s_attrib->value.value.i = VA_FOURCC_NV12;
    va_status = vaCreateSurfaces(va_dpy, VA_RT_FORMAT_YUV420, 
                                 surface_width, surface_height,
                                 &csc_render_surface, 1, 
                                 surface_attribs, 1);
    CHECK_VASTATUS(va_status,"vaCreateSurfaces");


cleanup:
    return test_color_conversion;
}
Exemple #3
0
static float run(const char* infile, const char* outfile1, const char* outfile2, bool doInterop)
{
    VASurfaceID surface;
    VAStatus status;
    Timer t;

    // initialize CL context for CL/VA interop
    cv::va_intel::ocl::initializeContextFromVA(va::display, doInterop);

    // load input image
    cv::UMat u1 = readImage(infile);
    cv::Size size2 = u1.size();
    status = vaCreateSurfaces(va::display, VA_RT_FORMAT_YUV420, size2.width, size2.height, &surface, 1, NULL, 0);
    CHECK_VASTATUS(status, "vaCreateSurfaces");

    // transfer image into VA surface, make sure all CL initialization is done (kernels etc)
    cv::va_intel::convertToVASurface(va::display, u1, surface, size2);
    cv::va_intel::convertFromVASurface(va::display, surface, size2, u1);
    cv::UMat u2;
    cv::blur(u1, u2, cv::Size(7, 7), cv::Point(-3, -3));

    // measure performance on some image processing
    writeImage(u1, outfile1, doInterop);
    t.start();
    cv::va_intel::convertFromVASurface(va::display, surface, size2, u1);
    cv::blur(u1, u2, cv::Size(7, 7), cv::Point(-3, -3));
    cv::va_intel::convertToVASurface(va::display, u2, surface, size2);
    t.stop();
    writeImage(u2, outfile2, doInterop);

    vaDestroySurfaces(va::display, &surface,1);

    return t.time(Timer::MSEC);
}
Exemple #4
0
static int
ensure_image_formats(void)
{
    VAStatus va_status;
    VAImageFormat *image_formats;
    int num_image_formats;

    if (va_num_image_formats >= 0)
        return va_num_image_formats;

    num_image_formats = vaMaxNumImageFormats(va_dpy);
    if (num_image_formats == 0)
        return 0;

    image_formats = malloc(num_image_formats * sizeof(*image_formats));
    if (!image_formats)
        return 0;

    va_status = vaQueryImageFormats(va_dpy, image_formats, &num_image_formats);
    CHECK_VASTATUS(va_status, "vaQuerySurfaceAttributes()");

    va_image_formats = image_formats;
    va_num_image_formats = num_image_formats;
    return num_image_formats;
}
Exemple #5
0
static int
ensure_surface_attribs(void)
{
    VAStatus va_status;
    VASurfaceAttrib *surface_attribs;
    unsigned int num_image_formats, num_surface_attribs;

    if (va_num_surface_attribs >= 0)
        return va_num_surface_attribs;

    num_image_formats = vaMaxNumImageFormats(va_dpy);
    if (num_image_formats == 0)
        return 0;

    va_status = vaCreateConfig(va_dpy, VAProfileNone, VAEntrypointVideoProc,
        NULL, 0, &vpp_config_id);
    CHECK_VASTATUS(va_status, "vaCreateConfig()");

    /* Guess the number of surface attributes, thus including any
       pixel-format supported by the VA driver */
    num_surface_attribs = VASurfaceAttribCount + num_image_formats;
    surface_attribs = malloc(num_surface_attribs * sizeof(*surface_attribs));
    if (!surface_attribs)
        return 0;

    va_status = vaQuerySurfaceAttributes(va_dpy, vpp_config_id,
        surface_attribs, &num_surface_attribs);
    if (va_status == VA_STATUS_SUCCESS)
        va_surface_attribs =  surface_attribs;
    else if (va_status == VA_STATUS_ERROR_MAX_NUM_EXCEEDED) {
        va_surface_attribs = realloc(surface_attribs,
            num_surface_attribs * sizeof(*va_surface_attribs));
        if (!va_surface_attribs) {
            free(surface_attribs);
            return 0;
        }
        va_status = vaQuerySurfaceAttributes(va_dpy, vpp_config_id,
            va_surface_attribs, &num_surface_attribs);
    }
    CHECK_VASTATUS(va_status, "vaQuerySurfaceAttributes()");
    va_num_surface_attribs = num_surface_attribs;
    return num_surface_attribs;
}
Exemple #6
0
static void h264_cleanup_decoder()
{
    VAStatus va_status;

    rfbClientLog("%s()\n", __FUNCTION__);

    if (va_surface_id[0] != VA_INVALID_ID) {
        va_status = vaDestroySurfaces(va_dpy, &va_surface_id[0], SURFACE_NUM);
        CHECK_VASTATUS(va_status, "vaDestroySurfaces");
    }

    if (va_context_id) {
        va_status = vaDestroyContext(va_dpy, va_context_id);
        CHECK_VASTATUS(va_status, "vaDestroyContext");
        va_context_id = 0;
    }

    num_frames = 0;
    sid = 0;
    frame_id = 0;
    field_order_count = 0;
}
Exemple #7
0
static void checkIfAvailableYUV420()
{
    VAEntrypoint entrypoints[5];
    int num_entrypoints,vld_entrypoint;
    VAConfigAttrib attrib;
    VAStatus status;

    status = vaQueryConfigEntrypoints(va::display, VAProfileMPEG2Main, entrypoints, &num_entrypoints);
    CHECK_VASTATUS(status, "vaQueryConfigEntrypoints");

    for (vld_entrypoint = 0; vld_entrypoint < num_entrypoints; ++vld_entrypoint)
    {
        if (entrypoints[vld_entrypoint] == VAEntrypointVLD)
            break;
    }
    if (vld_entrypoint == num_entrypoints)
        throw std::runtime_error("Failed to find VLD entry point");

    attrib.type = VAConfigAttribRTFormat;
    vaGetConfigAttributes(va::display, VAProfileMPEG2Main, VAEntrypointVLD, &attrib, 1);
    if ((attrib.value & VA_RT_FORMAT_YUV420) == 0)
        throw std::runtime_error("Desired YUV420 RT format not found");
}
Exemple #8
0
int main(int argc,char **argv)
{
    int major_ver, minor_ver;
    VAStatus va_status;
    pthread_t thread1;
    int ret;
    char c;
    int i;
    char str_src_fmt[5], str_dst_fmt[5];

    static struct option long_options[] =
                 {
                   {"fmt1",  required_argument,       NULL, '1'},
                   {"fmt2",  required_argument,       NULL, '2'},
                   {0, 0, 0, 0}
                 };

    while ((c =getopt_long(argc,argv,"w:h:g:r:d:f:tcep?n:1:2:v", long_options, NULL)) != EOF) {
        switch (c) {
            case '?':
                printf("putsurface <options>\n");
                printf("           -g <widthxheight+x_location+y_location> window geometry\n");
                printf("           -w/-h resolution of surface\n");
                printf("           -r <framerate>\n");
                printf("           -d the dimension of black/write square box, default is 32\n");
                printf("           -t multi-threads\n");
                printf("           -c test clipbox\n");
                printf("           -f <1/2> top field, or bottom field\n");
                printf("           -1 source format (fourcc) for color conversion test\n");
                printf("           -2 dest   format (fourcc) for color conversion test\n");
                printf("           --fmt1 same to -1\n");
                printf("           --fmt2 same to -2\n");
                printf("           -v verbose output\n");
                exit(0);
                break;
            case 'g':
                ret = sscanf(optarg, "%dx%d+%d+%d", &win_width, &win_height, &win_x, &win_y);
                if (ret != 4) {
                    printf("invalid window geometry, must be widthxheight+x_location+y_location\n");
                    exit(0);
                } else
                    printf("Create window at (%d, %d), width = %d, height = %d\n",
                           win_x, win_y, win_width, win_height);
                break;
            case 'r':
                frame_rate = atoi(optarg);
                break;
            case 'w':
                surface_width = atoi(optarg);
                break;
            case 'h':
                surface_height = atoi(optarg);
                break;
            case 'n':
                frame_num_total = atoi(optarg);
                break;
            case 'd':
                box_width = atoi(optarg);
                break;
            case 't':
                multi_thread = 1;
                printf("Two threads to do vaPutSurface\n");
                break;
            case 'e':
                check_event = 0;
                break;
            case 'p':
                put_pixmap = 1;
                break;
            case 'c':
                test_clip = 1;
                break;
            case 'f':
                if (atoi(optarg) == 1) {
                    printf("Display TOP field\n");
                    display_field = VA_TOP_FIELD;
                } else if (atoi(optarg) == 2) {
                    printf("Display BOTTOM field\n");
                    display_field = VA_BOTTOM_FIELD;
                } else
                    printf("The validate input for -f is: 1(top field)/2(bottom field)\n");
                break;
            case '1':
                sscanf(optarg, "%s", str_src_fmt);
                csc_src_fourcc = map_str_to_vafourcc (str_src_fmt);
                
				if (!csc_src_fourcc) {
                    printf("invalid fmt1: %s\n", str_src_fmt );
                    exit(0);
                }
                break;
            case '2':
                sscanf(optarg, "%s", str_dst_fmt);
                csc_dst_fourcc = map_str_to_vafourcc (str_dst_fmt);
                
				if (!csc_dst_fourcc) {
                    printf("invalid fmt1: %s\n", str_dst_fmt );
                    exit(0);
                }
                break;
            case 'v':
                verbose = 1;
                printf("Enable verbose output\n");
                break;
        }
    }

    if (csc_src_fourcc && csc_dst_fourcc) {
        test_color_conversion = 1;
    }
    
    win_display = (void *)open_display();
    if (win_display == NULL) {
        fprintf(stderr, "Can't open the connection of display!\n");
        exit(-1);
    }
    create_window(win_display, win_x, win_y, win_width, win_height);

    va_dpy = vaGetDisplay(win_display);
    va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
    CHECK_VASTATUS(va_status, "vaInitialize");

    if (test_color_conversion) {
        ret = csc_preparation();
    }
    if (!test_color_conversion || !ret ) {
        va_status = vaCreateSurfaces(
            va_dpy,
            VA_RT_FORMAT_YUV420, surface_width, surface_height,
            &surface_id[0], SURFACE_NUM,
            NULL, 0
        );
	}
    CHECK_VASTATUS(va_status, "vaCreateSurfaces");
    if (multi_thread == 0) /* upload the content for all surfaces */
        upload_source_YUV_once_for_all();
    
    if (check_event)
        pthread_mutex_init(&gmutex, NULL);
   
    for(i = 0; i< SURFACE_NUM; i++)
        pthread_mutex_init(&surface_mutex[i], NULL);
    
    if (multi_thread == 1) 
        ret = pthread_create(&thread1, NULL, putsurface_thread, (void*)drawable_thread1);

    putsurface_thread((void *)drawable_thread0);

    if (multi_thread == 1) 
        pthread_join(thread1, (void **)&ret);
    printf("thread1 is free\n");

    if (test_color_conversion) {
        // destroy temp surface/image
        va_status = vaDestroySurfaces(va_dpy, &csc_render_surface, 1);
        CHECK_VASTATUS(va_status,"vaDestroySurfaces");
        
        va_status = vaDestroyImage(va_dpy, csc_dst_fourcc_image.image_id);
        CHECK_VASTATUS(va_status,"vaDestroyImage");
    }

    if (vpp_config_id != VA_INVALID_ID) {
        vaDestroyConfig (va_dpy, vpp_config_id);
        vpp_config_id = VA_INVALID_ID;
    }

    vaDestroySurfaces(va_dpy,&surface_id[0],SURFACE_NUM);    
    vaTerminate(va_dpy);

    free(va_image_formats);
    free(va_surface_attribs);
    close_display(win_display);
    
    return 0;
}
Exemple #9
0
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;
}
Exemple #10
0
static void nv12_to_rgba(const VAImage vaImage, rfbClient *client, int ch_x, int ch_y, int ch_w, int ch_h)
{
    DebugLog(("%s: converting region (%d, %d)-(%d, %d) from NV12->RGBA\n", __FUNCTION__, ch_x, ch_y, ch_w, ch_h));

    VAStatus va_status;
    uint8_t *nv12_buf;
    va_status = vaMapBuffer(va_dpy, vaImage.buf, (void **)&nv12_buf);
    CHECK_VASTATUS(va_status, "vaMapBuffer(DecodedData)");

    /* adjust x, y, width, height of the affected area so
     * x, y, width and height are always even.
     */
    if (ch_x % 2) { --ch_x; ++ch_w; }
    if (ch_y % 2) { --ch_y; ++ch_h; }
    if ((ch_x + ch_w) % 2) { ++ch_w; }
    if ((ch_y + ch_h) % 2) { ++ch_h; }

    /* point nv12_buf and dst to upper left corner of changed area */
    uint8_t *nv12_y  = &nv12_buf[vaImage.offsets[0] + vaImage.pitches[0] * ch_y + ch_x];
    uint8_t *nv12_uv = &nv12_buf[vaImage.offsets[1] + vaImage.pitches[1] * (ch_y / 2) + ch_x];
    uint32_t *dst    = &((uint32_t*)client->frameBuffer)[client->width * ch_y + ch_x];

    /* TODO: optimize R, G, B calculation. Possible ways to do this:
     *       - use lookup tables
     *       - convert from floating point to integer arithmetic
     *       - use MMX/SSE to vectorize calculations
     *       - use GPU (VA VPP, shader...)
     */
    int src_x, src_y;
    for (src_y = 0; src_y < ch_h; src_y += 2) {
        for (src_x = 0; src_x < ch_w; src_x += 2) {
            uint8_t nv_u = nv12_uv[src_x];
            uint8_t nv_v = nv12_uv[src_x + 1];
            uint8_t nv_y[4] = { nv12_y[                     src_x], nv12_y[                     src_x + 1],
                                nv12_y[vaImage.pitches[0] + src_x], nv12_y[vaImage.pitches[0] + src_x + 1] };

        int i;
            for (i = 0; i < 4; ++i) {
                double R = 1.164 * (nv_y[i] - 16)                        + 1.596 * (nv_v - 128);
                double G = 1.164 * (nv_y[i] - 16) - 0.391 * (nv_u - 128) - 0.813 * (nv_v - 128);
                double B = 1.164 * (nv_y[i] - 16) + 2.018 * (nv_u - 128);

                /* clamp R, G, B values. For some Y, U, V combinations,
                 * the results of the above calculations fall outside of
                 * the range 0-255.
                 */
                if (R < 0.0) R = 0.0;
                if (G < 0.0) G = 0.0;
                if (B < 0.0) B = 0.0;
                if (R > 255.0) R = 255.0;
                if (G > 255.0) G = 255.0;
                if (B > 255.0) B = 255.0;

                dst[client->width * (i / 2) + src_x + (i % 2)] = 0
                               | ((unsigned int)(R + 0.5) << client->format.redShift)
                               | ((unsigned int)(G + 0.5) << client->format.greenShift)
                               | ((unsigned int)(B + 0.5) << client->format.blueShift);
            }
        }

        nv12_y  += 2 * vaImage.pitches[0];
        nv12_uv += vaImage.pitches[1];
        dst     += 2 * client->width;
    }

    CHECK_SURF(va_surface_id[sid]);
    va_status = vaUnmapBuffer(va_dpy, vaImage.buf);
    CHECK_VASTATUS(va_status, "vaUnmapBuffer(DecodedData)");
}
Exemple #11
0
static void h264_decode_frame(int f_width, int f_height, char *framedata, int framesize, int slice_type)
{
    VAStatus va_status;

    DebugLog(("%s: called for frame of %d bytes (%dx%d) slice_type=%d\n", __FUNCTION__, framesize, width, height, slice_type));

    /* Initialize decode pipeline if necessary */
    if ( (f_width > cur_width) || (f_height > cur_height) ) {
        if (va_dpy != NULL)
            h264_cleanup_decoder();
        cur_width = f_width;
        cur_height = f_height;

        h264_init_decoder(f_width, f_height);
        rfbClientLog("%s: decoder initialized\n", __FUNCTION__);
    }

    /* Decode frame */
    static VAPictureH264 va_picture_h264, va_old_picture_h264;

    /* The server should always send an I-frame when a new client connects
     * or when the resolution of the framebuffer changes, but we check
     * just in case.
     */
    if ( (slice_type != SLICE_TYPE_I) && (num_frames == 0) ) {
        rfbClientLog("First frame is not an I frame !!! Skipping!!!\n");
        return;
    }

    DebugLog(("%s: frame_id=%d va_surface_id[%d]=0x%x field_order_count=%d\n", __FUNCTION__, frame_id, sid, va_surface_id[sid], field_order_count));

    va_picture_h264.picture_id = va_surface_id[sid];
    va_picture_h264.frame_idx  = frame_id;
    va_picture_h264.flags = 0;
    va_picture_h264.BottomFieldOrderCnt = field_order_count;
    va_picture_h264.TopFieldOrderCnt = field_order_count;

    /* Set up picture parameter buffer */
    if (va_pic_param_buf_id[sid] == VA_INVALID_ID) {
        va_status = vaCreateBuffer(va_dpy, va_context_id, VAPictureParameterBufferType, sizeof(VAPictureParameterBufferH264), 1, NULL, &va_pic_param_buf_id[sid]);
        CHECK_VASTATUS(va_status, "vaCreateBuffer(PicParam)");
    }
    CHECK_SURF(va_surface_id[sid]);

    VAPictureParameterBufferH264 *pic_param_buf = NULL;
    va_status = vaMapBuffer(va_dpy, va_pic_param_buf_id[sid], (void **)&pic_param_buf);
    CHECK_VASTATUS(va_status, "vaMapBuffer(PicParam)");

    SetVAPictureParameterBufferH264(pic_param_buf, f_width, f_height);
    memcpy(&pic_param_buf->CurrPic, &va_picture_h264, sizeof(VAPictureH264));

    if (slice_type == SLICE_TYPE_P) {
        memcpy(&pic_param_buf->ReferenceFrames[0], &va_old_picture_h264, sizeof(VAPictureH264));
        pic_param_buf->ReferenceFrames[0].flags = 0;
    }
    else if (slice_type != SLICE_TYPE_I) {
        rfbClientLog("Frame type %d not supported!!!\n");
        return;
    }
    pic_param_buf->frame_num = frame_id;

    va_status = vaUnmapBuffer(va_dpy, va_pic_param_buf_id[sid]);
    CHECK_VASTATUS(va_status, "vaUnmapBuffer(PicParam)");

    /* Set up IQ matrix buffer */
    if (va_mat_param_buf_id[sid] == VA_INVALID_ID) {
        va_status = vaCreateBuffer(va_dpy, va_context_id, VAIQMatrixBufferType, sizeof(VAIQMatrixBufferH264), 1, NULL, &va_mat_param_buf_id[sid]);
        CHECK_VASTATUS(va_status, "vaCreateBuffer(IQMatrix)");
    }
    CHECK_SURF(va_surface_id[sid]);

    VAIQMatrixBufferH264 *iq_matrix_buf = NULL;
    va_status = vaMapBuffer(va_dpy, va_mat_param_buf_id[sid], (void **)&iq_matrix_buf);
    CHECK_VASTATUS(va_status, "vaMapBuffer(IQMatrix)");

    static const unsigned char m_MatrixBufferH264[]= {
        /* ScalingList4x4[6][16] */
        0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
        0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
        0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
        0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
        0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
        0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
        /* ScalingList8x8[2][64] */
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
    };

    memcpy(iq_matrix_buf, m_MatrixBufferH264, 224);
    va_status = vaUnmapBuffer(va_dpy, va_mat_param_buf_id[sid]);
    CHECK_VASTATUS(va_status, "vaUnmapBuffer(IQMatrix)");

    VABufferID buffer_ids[2];
    buffer_ids[0] = va_pic_param_buf_id[sid];
    buffer_ids[1] = va_mat_param_buf_id[sid];

    CHECK_SURF(va_surface_id[sid]);
    va_status = vaRenderPicture(va_dpy, va_context_id, buffer_ids, 2);
    CHECK_VASTATUS(va_status, "vaRenderPicture");

    /* Set up slice parameter buffer */
    if (va_sp_param_buf_id[sid] == VA_INVALID_ID) {
        va_status = vaCreateBuffer(va_dpy, va_context_id, VASliceParameterBufferType, sizeof(VASliceParameterBufferH264), 1, NULL, &va_sp_param_buf_id[sid]);
        CHECK_VASTATUS(va_status, "vaCreateBuffer(SliceParam)");
    }
    CHECK_SURF(va_surface_id[sid]);

    VASliceParameterBufferH264 *slice_param_buf = NULL;
    va_status = vaMapBuffer(va_dpy, va_sp_param_buf_id[sid], (void **)&slice_param_buf);
    CHECK_VASTATUS(va_status, "vaMapBuffer(SliceParam)");

    static int t2_first = 1;
    if (slice_type == SLICE_TYPE_I) {
        SetVASliceParameterBufferH264_Intra(slice_param_buf, t2_first);
        t2_first = 0;
    } else {
        SetVASliceParameterBufferH264(slice_param_buf);
        memcpy(&slice_param_buf->RefPicList0[0], &va_old_picture_h264, sizeof(VAPictureH264));
        slice_param_buf->RefPicList0[0].flags = 0;
    }
    slice_param_buf->slice_data_bit_offset = 0;
    slice_param_buf->slice_data_size = framesize;

    va_status = vaUnmapBuffer(va_dpy, va_sp_param_buf_id[sid]);
    CHECK_VASTATUS(va_status, "vaUnmapBuffer(SliceParam)");
    CHECK_SURF(va_surface_id[sid]);

    /* Set up slice data buffer and copy H.264 encoded data */
    if (va_d_param_buf_id[sid] == VA_INVALID_ID) {
        /* TODO use estimation matching framebuffer dimensions instead of this large value */
        va_status = vaCreateBuffer(va_dpy, va_context_id, VASliceDataBufferType, 4177920, 1, NULL, &va_d_param_buf_id[sid]); /* 1080p size */
        CHECK_VASTATUS(va_status, "vaCreateBuffer(SliceData)");
    }

    char *slice_data_buf;
    va_status = vaMapBuffer(va_dpy, va_d_param_buf_id[sid], (void **)&slice_data_buf);
    CHECK_VASTATUS(va_status, "vaMapBuffer(SliceData)");
    memcpy(slice_data_buf, framedata, framesize);

    CHECK_SURF(va_surface_id[sid]);
    va_status = vaUnmapBuffer(va_dpy, va_d_param_buf_id[sid]);
    CHECK_VASTATUS(va_status, "vaUnmapBuffer(SliceData)");

    buffer_ids[0] = va_sp_param_buf_id[sid];
    buffer_ids[1] = va_d_param_buf_id[sid];

    CHECK_SURF(va_surface_id[sid]);
    va_status = vaRenderPicture(va_dpy, va_context_id, buffer_ids, 2);
    CHECK_VASTATUS(va_status, "vaRenderPicture");

    va_status = vaEndPicture(va_dpy, va_context_id);
    CHECK_VASTATUS(va_status, "vaEndPicture");

    /* Prepare next one... */
    int sid_new = (sid + 1) % SURFACE_NUM;
    DebugLog(("%s: new Surface ID = %d\n", __FUNCTION__, sid_new));
    va_status = vaBeginPicture(va_dpy, va_context_id, va_surface_id[sid_new]);
    CHECK_VASTATUS(va_status, "vaBeginPicture");

    /* Get decoded data */
    va_status = vaSyncSurface(va_dpy, va_surface_id[sid]);
    CHECK_VASTATUS(va_status, "vaSyncSurface");
    CHECK_SURF(va_surface_id[sid]);

    curr_surface = va_surface_id[sid];

    sid = sid_new;

    field_order_count += 2;
    ++frame_id;
    if (frame_id > 15) {
        frame_id = 0;
    }

    ++num_frames;

    memcpy(&va_old_picture_h264, &va_picture_h264, sizeof(VAPictureH264));
}
Exemple #12
0
static void h264_init_decoder(int width, int height)
{
    VAStatus va_status;

    if (va_context_id) {
        rfbClientLog("%s: va_dpy already initialized\n", __FUNCTION__);
    }

    if (va_dpy != NULL) {
        rfbClientLog("%s: Re-initializing H.264 decoder\n", __FUNCTION__);
    }
    else {
        rfbClientLog("%s: initializing H.264 decoder\n", __FUNCTION__);

        /* Attach VA display to local X display */
        Display *win_display = (Display *)XOpenDisplay(":0.0");
        if (win_display == NULL) {
            rfbClientErr("Can't connect to local display\n");
            exit(-1);
        }

        int major_ver, minor_ver;
        va_dpy = vaGetDisplay(win_display);
        va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
        CHECK_VASTATUS(va_status, "vaInitialize");
        rfbClientLog("%s: libva version %d.%d found\n", __FUNCTION__, major_ver, minor_ver);
    }

    /* Check for VLD entrypoint */
    int num_entrypoints;
    VAEntrypoint    entrypoints[5];
    int vld_entrypoint_found = 0;

    /* Change VAProfileH264High if needed */
    VAProfile profile = VAProfileH264High;
    va_status = vaQueryConfigEntrypoints(va_dpy, profile, entrypoints, &num_entrypoints);
    CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
    int i;
    for (i = 0; i < num_entrypoints; ++i) {
        if (entrypoints[i] == VAEntrypointVLD) {
            vld_entrypoint_found = 1;
            break;
        }
    }

    if (vld_entrypoint_found == 0) {
        rfbClientErr("VLD entrypoint not found\n");
        exit(1);
    }

    /* Create configuration for the decode pipeline */
    VAConfigAttrib attrib;
    attrib.type = VAConfigAttribRTFormat;
    va_status = vaCreateConfig(va_dpy, profile, VAEntrypointVLD, &attrib, 1, &va_config_id);
    CHECK_VASTATUS(va_status, "vaCreateConfig");

    /* Create VA surfaces */
    for (i = 0; i < SURFACE_NUM; ++i) {
        va_surface_id[i]       = VA_INVALID_ID;
        va_pic_param_buf_id[i] = VA_INVALID_ID;
        va_mat_param_buf_id[i] = VA_INVALID_ID;
        va_sp_param_buf_id[i]  = VA_INVALID_ID;
        va_d_param_buf_id[i]   = VA_INVALID_ID;
    }
    va_status = vaCreateSurfaces(va_dpy, width, height, VA_RT_FORMAT_YUV420, SURFACE_NUM, &va_surface_id[0]);
    CHECK_VASTATUS(va_status, "vaCreateSurfaces");
    for (i = 0; i < SURFACE_NUM; ++i) {
        DebugLog(("%s: va_surface_id[%d] = %p\n", __FUNCTION__, i, va_surface_id[i]));
    }

    /* Create VA context */
    va_status = vaCreateContext(va_dpy, va_config_id, width, height, 0/*VA_PROGRESSIVE*/,  &va_surface_id[0], SURFACE_NUM, &va_context_id);
    CHECK_VASTATUS(va_status, "vaCreateContext");
    DebugLog(("%s: VA context created (id: %d)\n", __FUNCTION__, va_context_id));


    /* Instantiate decode pipeline */
    va_status = vaBeginPicture(va_dpy, va_context_id, va_surface_id[0]);
    CHECK_VASTATUS(va_status, "vaBeginPicture");

    rfbClientLog("%s: H.264 decoder initialized\n", __FUNCTION__);
}
Exemple #13
0
int main(int argc,char **argv)
{
    int major_ver, minor_ver;
    VAStatus va_status;
    pthread_t thread1;
    int ret;
    char c;
    int i;

    while ((c =getopt(argc,argv,"w:h:g:r:d:f:tcep?n:v") ) != EOF) {
        switch (c) {
        case '?':
            printf("putsurface <options>\n");
            printf("           -g <widthxheight+x_location+y_location> window geometry\n");
            printf("           -w/-h resolution of surface\n");
            printf("           -r <framerate>\n");
            printf("           -d the dimension of black/write square box, default is 32\n");
            printf("           -t multi-threads\n");
            printf("           -c test clipbox\n");
            printf("           -f <1/2> top field, or bottom field\n");
            printf("           -v verbose output\n");
            exit(0);
            break;
        case 'g':
            ret = sscanf(optarg, "%dx%d+%d+%d", &win_width, &win_height, &win_x, &win_y);
            if (ret != 4) {
                printf("invalid window geometry, must be widthxheight+x_location+y_location\n");
                exit(0);
            } else
                printf("Create window at (%d, %d), width = %d, height = %d\n",
                       win_x, win_y, win_width, win_height);
            break;
        case 'r':
            frame_rate = atoi(optarg);
            break;
        case 'w':
            surface_width = atoi(optarg);
            break;
        case 'h':
            surface_height = atoi(optarg);
            break;
        case 'n':
            frame_num_total = atoi(optarg);
            break;
        case 'd':
            box_width = atoi(optarg);
            break;
        case 't':
            multi_thread = 1;
            printf("Two threads to do vaPutSurface\n");
            break;
        case 'e':
            check_event = 0;
            break;
        case 'p':
            put_pixmap = 1;
            break;
        case 'c':
            test_clip = 1;
            break;
        case 'f':
            if (atoi(optarg) == 1) {
                printf("Display TOP field\n");
                display_field = VA_TOP_FIELD;
            } else if (atoi(optarg) == 2) {
                printf("Display BOTTOM field\n");
                display_field = VA_BOTTOM_FIELD;
            } else
                printf("The validate input for -f is: 1(top field)/2(bottom field)\n");
            break;
        case 'v':
            verbose = 1;
            printf("Enable verbose output\n");
            break;
        }
    }

    win_display = (void *)open_display();
    if (win_display == NULL) {
        fprintf(stderr, "Can't open the connection of display!\n");
        exit(-1);
    }
    create_window(win_display, win_x, win_y, win_width, win_height);

    va_dpy = vaGetDisplay(win_display);
    va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
    CHECK_VASTATUS(va_status, "vaInitialize");

    va_status = vaCreateSurfaces(va_dpy,surface_width, surface_height,
                                 VA_RT_FORMAT_YUV420, SURFACE_NUM, &surface_id[0]);
    CHECK_VASTATUS(va_status, "vaCreateSurfaces");
    if (multi_thread == 0) /* upload the content for all surfaces */
        upload_source_YUV_once_for_all();

    if (check_event)
        pthread_mutex_init(&gmutex, NULL);

    for(i = 0; i< SURFACE_NUM; i++)
        pthread_mutex_init(&surface_mutex[i], NULL);

    if (multi_thread == 1)
        ret = pthread_create(&thread1, NULL, putsurface_thread, (void*)drawable_thread1);

    putsurface_thread((void *)drawable_thread0);

    if (multi_thread == 1)
        pthread_join(thread1, (void **)&ret);
    printf("thread1 is free\n");

    vaDestroySurfaces(va_dpy,&surface_id[0],SURFACE_NUM);
    vaTerminate(va_dpy);

    close_display(win_display);

    return 0;
}
Exemple #14
0
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 %x Display surface 0x%p,\n", (unsigned int)drawable, (void *)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;
        }
        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;
}