Esempio n. 1
0
static
PP_Resource
do_ppb_audio_create(PP_Instance instance, PP_Resource audio_config,
                    PPB_Audio_Callback_1_0 audio_callback_1_0,
                    PPB_Audio_Callback     audio_callback_1_1, void *user_data)
{
    struct pp_instance_s *pp_i = tables_get_pp_instance(instance);
    if (!pp_i) {
        trace_error("%s, bad instance\n", __func__);
        return 0;
    }

    if (!audio_callback_1_0 && !audio_callback_1_1)
        return PP_ERROR_BADARGUMENT;

    PP_Resource audio = pp_resource_allocate(PP_RESOURCE_AUDIO, pp_i);
    struct pp_audio_s *a = pp_resource_acquire(audio, PP_RESOURCE_AUDIO);
    if (!a) {
        trace_error("%s, resource allocation failure\n", __func__);
        return 0;
    }

    struct pp_audio_config_s *ac = pp_resource_acquire(audio_config, PP_RESOURCE_AUDIO_CONFIG);
    if (!ac) {
        trace_error("%s, bad audio config\n", __func__);
        goto err;
    }

    a->sample_rate = ac->sample_rate;
    a->sample_frame_count = ac->sample_frame_count;
    pp_resource_release(audio_config);

    a->callback_1_0 = audio_callback_1_0;
    a->callback_1_1 = audio_callback_1_1;
    a->user_data = user_data;
    a->stream_ops = audio_select_implementation();
    if (a->stream_ops == NULL) {
        trace_error("%s, no viable audio implementation\n", __func__);
        goto err;
    }

    a->stream = a->stream_ops->create_playback_stream(a->sample_rate, a->sample_frame_count,
                                                      playback_cb, a);
    if (!a->stream) {
        trace_error("%s, can't create playback stream\n", __func__);
        goto err;
    }

    pp_resource_release(audio);
    return audio;
err:
    pp_resource_release(audio);
    pp_resource_expunge(audio);
    return 0;
}
PP_Resource
ppb_graphics3d_create(PP_Instance instance, PP_Resource share_context, const int32_t attrib_list[])
{
    struct pp_instance_s *pp_i = tables_get_pp_instance(instance);
    if (!pp_i) {
        trace_error("%s, bad instance\n", __func__);
        return 0;
    }

    PP_Resource context = pp_resource_allocate(PP_RESOURCE_GRAPHICS3D, pp_i);
    struct pp_graphics3d_s *g3d = pp_resource_acquire(context, PP_RESOURCE_GRAPHICS3D);
    if (!g3d) {
        trace_error("%s, can't create context\n", __func__);
        return 0;
    }

    int attrib_len = 0;
    while (attrib_list[attrib_len] != PP_GRAPHICS3DATTRIB_NONE) {
        attrib_len += 2;
    }
    attrib_len ++;

    EGLint *egl_attribute_list = calloc(attrib_len + 3 * 2, sizeof(EGLint));
    int done = 0, k1 = 0, k2 = 0;
    egl_attribute_list[k2++] = EGL_SURFACE_TYPE;
    egl_attribute_list[k2++] = EGL_PIXMAP_BIT | EGL_WINDOW_BIT;
    egl_attribute_list[k2++] = EGL_RENDERABLE_TYPE;
    egl_attribute_list[k2++] = EGL_OPENGL_ES2_BIT;

    while (!done) {
        switch (attrib_list[k1]) {
        case PP_GRAPHICS3DATTRIB_HEIGHT:
            g3d->height = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_WIDTH:
            g3d->width = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_GPU_PREFERENCE:
        case PP_GRAPHICS3DATTRIB_SWAP_BEHAVIOR:
            // TODO: save these values
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_NONE:
            egl_attribute_list[k2++] = EGL_NONE;
            done = 1;
            break;
        case PP_GRAPHICS3DATTRIB_ALPHA_SIZE:
            egl_attribute_list[k2++] = EGL_ALPHA_SIZE;
            egl_attribute_list[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_BLUE_SIZE:
            egl_attribute_list[k2++] = EGL_BLUE_SIZE;
            egl_attribute_list[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_GREEN_SIZE:
            egl_attribute_list[k2++] = EGL_GREEN_SIZE;
            egl_attribute_list[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_RED_SIZE:
            egl_attribute_list[k2++] = EGL_RED_SIZE;
            egl_attribute_list[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_DEPTH_SIZE:
            egl_attribute_list[k2++] = EGL_DEPTH_SIZE;
            egl_attribute_list[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_STENCIL_SIZE:
            egl_attribute_list[k2++] = EGL_STENCIL_SIZE;
            egl_attribute_list[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_SAMPLES:
            egl_attribute_list[k2++] = EGL_SAMPLES;
            egl_attribute_list[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS:
            egl_attribute_list[k2++] = EGL_SAMPLE_BUFFERS;
            egl_attribute_list[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        default:
            // skip unknown attribute
            trace_error("%s, unknown attribute 0x%x\n", __func__, attrib_list[k1]);
            k1 += 1;
            break;
        }
    }

    pthread_mutex_lock(&display.lock);
    int nconfigs = 0;
    EGLBoolean ret = eglChooseConfig(display.egl, egl_attribute_list,
                                     &g3d->egl_config, 1, &nconfigs);
    free(egl_attribute_list);
    if (!ret) {
        trace_error("%s, eglChooseConfig returned FALSE\n", __func__);
        goto err;
    }

    if (nconfigs != 1) {
        trace_error("%s, eglChooseConfig returned %d configs, expected 1\n", __func__, nconfigs);
        goto err;
    }

    // TODO: support shared_context
    EGLint ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
    g3d->glc = eglCreateContext(display.egl, g3d->egl_config, EGL_NO_CONTEXT, ctxattr);
    if (g3d->glc == EGL_NO_CONTEXT) {
        trace_error("%s, eglCreateContext returned EGL_NO_CONTEXT\n", __func__);
        goto err;
    }

    g3d->pixmap = XCreatePixmap(display.x, DefaultRootWindow(display.x), g3d->width, g3d->height,
                                DefaultDepth(display.x, 0));
    g3d->egl_surf = eglCreatePixmapSurface(display.egl, g3d->egl_config, g3d->pixmap, NULL);
    if (g3d->egl_surf == EGL_NO_SURFACE) {
        trace_error("%s, failed to create EGL pixmap surface\n", __func__);
        goto err;
    }

    ret = eglMakeCurrent(display.egl, g3d->egl_surf, g3d->egl_surf, g3d->glc);
    if (!ret) {
        trace_error("%s, eglMakeCurrent failed\n", __func__);
        goto err;
    }

    // clear surface
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

    if (pp_i->is_transparent) {
        // create texture for plugin content
        glGenTextures(1, &g3d->tex_front);
        glBindTexture(GL_TEXTURE_2D, g3d->tex_front);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

        if (create_presentation_egl_context(g3d) != 0) {
            trace_error("%s, can't create EGL context for transparency processing\n", __func__);
            goto err;
        }
    }

    eglMakeCurrent(display.egl, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);

    g3d->sub_maps = g_hash_table_new(g_direct_hash, g_direct_equal);
    pthread_mutex_unlock(&display.lock);

    pp_resource_release(context);
    return context;
err:
    pthread_mutex_unlock(&display.lock);
    pp_resource_release(context);
    pp_resource_expunge(context);
    return 0;
}
Esempio n. 3
0
PP_Resource
ppb_graphics3d_create(PP_Instance instance, PP_Resource share_context, const int32_t attrib_list[])
{
    struct pp_instance_s *pp_i = tables_get_pp_instance(instance);
    if (!pp_i) {
        trace_error("%s, bad instance\n", __func__);
        return 0;
    }

    GLXContext share_glc = (share_context == 0) ? NULL
                                                : peek_gl_context(share_context);
    // check for required GLX extensions
#if HAVE_GLES2
    if (!display.glx_arb_create_context || !display.glx_arb_create_context_profile ||
        !display.glx_ext_create_context_es2_profile)
    {
        trace_warning("%s, some of GLX_ARB_create_context, GLX_ARB_create_context_profile, "
                      "GLX_EXT_create_context_es2_profile missing\n", __func__);
        return 0;
    }

    if (!display.glXCreateContextAttribsARB) {
        trace_warning("%s, no glXCreateContextAttribsARB found\n", __func__);
        return 0;
    }
#endif

    PP_Resource context = pp_resource_allocate(PP_RESOURCE_GRAPHICS3D, pp_i);
    struct pp_graphics3d_s *g3d = pp_resource_acquire(context, PP_RESOURCE_GRAPHICS3D);
    if (!g3d) {
        trace_error("%s, can't create context\n", __func__);
        return 0;
    }

    int attrib_len = 0;
    while (attrib_list[attrib_len] != PP_GRAPHICS3DATTRIB_NONE) {
        attrib_len += 2;
    }
    attrib_len ++;

    int *cfg_attrs = calloc(attrib_len + 3 * 2, sizeof(int));
    int k2 = 0;
    cfg_attrs[k2++] = GLX_X_RENDERABLE;
    cfg_attrs[k2++] = True;
    cfg_attrs[k2++] = GLX_DRAWABLE_TYPE;
    cfg_attrs[k2++] = GLX_WINDOW_BIT | GLX_PIXMAP_BIT;

    int done = 0;
    int k1 = 0;
    while (!done) {
        switch (attrib_list[k1]) {
        case PP_GRAPHICS3DATTRIB_HEIGHT:
            g3d->height = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_WIDTH:
            g3d->width = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_GPU_PREFERENCE:
        case PP_GRAPHICS3DATTRIB_SWAP_BEHAVIOR:
            // TODO: save these values
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_NONE:
            cfg_attrs[k2++] = None;
            done = 1;
            break;
        case PP_GRAPHICS3DATTRIB_ALPHA_SIZE:
            cfg_attrs[k2++] = GLX_ALPHA_SIZE;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_BLUE_SIZE:
            cfg_attrs[k2++] = GLX_BLUE_SIZE;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_GREEN_SIZE:
            cfg_attrs[k2++] = GLX_GREEN_SIZE;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_RED_SIZE:
            cfg_attrs[k2++] = GLX_RED_SIZE;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_DEPTH_SIZE:
            cfg_attrs[k2++] = GLX_DEPTH_SIZE;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_STENCIL_SIZE:
            cfg_attrs[k2++] = GLX_STENCIL_SIZE;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_SAMPLES:
            cfg_attrs[k2++] = GLX_SAMPLES;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS:
            cfg_attrs[k2++] = GLX_SAMPLE_BUFFERS;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case GLX_Y_INVERTED_EXT:
            cfg_attrs[k2++] = GLX_Y_INVERTED_EXT;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case GLX_BIND_TO_TEXTURE_RGBA_EXT:
            cfg_attrs[k2++] = GLX_BIND_TO_TEXTURE_RGBA_EXT;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        default:
            // skip unknown attribute
            trace_error("%s, unknown attribute 0x%x\n", __func__, attrib_list[k1]);
            k1 += 1;
            break;
        }
    }

    pthread_mutex_lock(&display.lock);
    int screen = DefaultScreen(display.x);
    int nconfigs = 0;
    GLXFBConfig *fb_cfgs = glXChooseFBConfig(display.x, screen, cfg_attrs, &nconfigs);
    free(cfg_attrs);

    if (!fb_cfgs) {
        trace_error("%s, glXChooseFBConfig returned NULL\n", __func__);
        goto err;
    }

    trace_info_f("%s, glXChooseFBConfig returned %d configs, choosing first one\n", __func__,
                 nconfigs);
    g3d->fb_config = fb_cfgs[0];
    XFree(fb_cfgs);

#if HAVE_GLES2
    // create context implementing OpenGL ES 2.0
    const int ctx_attrs[] = {
        GLX_RENDER_TYPE,                GLX_RGBA_TYPE,
        GLX_CONTEXT_MAJOR_VERSION_ARB,  2,
        GLX_CONTEXT_MINOR_VERSION_ARB,  0,
        GLX_CONTEXT_PROFILE_MASK_ARB,   GLX_CONTEXT_ES2_PROFILE_BIT_EXT,
        None,
    };
#else
    // create context implementing OpenGL 2.0
    // OpenGL ES 2.0 will be emulated with help of shader translator
    const int ctx_attrs[] = {
        GLX_RENDER_TYPE,                GLX_RGBA_TYPE,
        GLX_CONTEXT_MAJOR_VERSION_ARB,  2,
        GLX_CONTEXT_MINOR_VERSION_ARB,  0,
        None,
    };
#endif

    if (display.glXCreateContextAttribsARB) {
        g3d->glc = display.glXCreateContextAttribsARB(display.x, g3d->fb_config, share_glc, True,
                                                      ctx_attrs);
        if (!g3d->glc)
            trace_warning("%s, glXCreateContextAttribsARB returned NULL\n", __func__);

    } else {
        g3d->glc = NULL;
    }

    if (!g3d->glc) {
        // if glXCreateContextAttribsARB is not present or returned NULL,
        // request any GL context
        g3d->glc = glXCreateNewContext(display.x, g3d->fb_config, GLX_RGBA_TYPE, share_glc, True);
        if (!g3d->glc) {
            trace_error("%s, glXCreateNewContext returned NULL\n", __func__);
            goto err;
        }
    }

    g3d->depth = pp_i->is_transparent ? 32 : DefaultDepth(display.x, screen);
    switch (g3d->depth) {
    case 24:
        g3d->xr_pictfmt = display.pictfmt_rgb24;
        break;
    case 32:
        g3d->xr_pictfmt = display.pictfmt_argb32;
        break;
    default:
        trace_error("%s, unsupported g3d->depth (%d)\n", __func__, g3d->depth);
        goto err;
    }

    g3d->pixmap = XCreatePixmap(display.x, DefaultRootWindow(display.x), g3d->width, g3d->height,
                                g3d->depth);
    g3d->glx_pixmap = glXCreatePixmap(display.x, g3d->fb_config, g3d->pixmap, NULL);
    if (g3d->glx_pixmap == None) {
        trace_error("%s, failed to create GLX pixmap\n", __func__);
        goto err;
    }

    XFlush(display.x);
    g3d->xr_pict = XRenderCreatePicture(display.x, g3d->pixmap, g3d->xr_pictfmt, 0, 0);

    int ret = glXMakeCurrent(display.x, g3d->glx_pixmap, g3d->glc);
    if (!ret) {
        trace_error("%s, glXMakeCurrent failed\n", __func__);
        goto err;
    }

    // clear surface
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

    glXMakeCurrent(display.x, None, NULL);

    g3d->sub_maps = g_hash_table_new(g_direct_hash, g_direct_equal);
    pthread_mutex_unlock(&display.lock);

    pp_resource_release(context);
    return context;
err:
    pthread_mutex_unlock(&display.lock);
    pp_resource_release(context);
    pp_resource_expunge(context);
    return 0;
}
PP_Resource
ppb_video_decoder_create(PP_Instance instance, PP_Resource context, PP_VideoDecoder_Profile profile)
{
    if (!config.enable_hwdec) {
        trace_info_f("      hardware-accelerated decoding was disabled in config file\n");
        return 0;
    }

    if (!display.va_available) {
        trace_info_f("      no hw acceleration available\n");
        return 0;
    }

    if (!display.glXBindTexImageEXT) {
        trace_info_f("      no glXBindTexImageEXT available\n");
        return 0;
    }

    switch (profile) {
    case PP_VIDEODECODER_H264PROFILE_BASELINE:
    case PP_VIDEODECODER_H264PROFILE_MAIN:
    case PP_VIDEODECODER_H264PROFILE_EXTENDED:
    case PP_VIDEODECODER_H264PROFILE_HIGH:
        // pass, there is an implementation below
        break;

    case PP_VIDEODECODER_H264PROFILE_NONE:
    case PP_VIDEODECODER_H264PROFILE_HIGH10PROFILE:
    case PP_VIDEODECODER_H264PROFILE_HIGH422PROFILE:
    case PP_VIDEODECODER_H264PROFILE_HIGH444PREDICTIVEPROFILE:
    case PP_VIDEODECODER_H264PROFILE_SCALABLEBASELINE:
    case PP_VIDEODECODER_H264PROFILE_SCALABLEHIGH:
    case PP_VIDEODECODER_H264PROFILE_STEREOHIGH:
    case PP_VIDEODECODER_H264PROFILE_MULTIVIEWHIGH:
    case PP_VIDEODECODER_VP8PROFILE_ANY:
    case PP_VIDEODECODER_PROFILE_UNKNOWN:
    default:
        trace_error("%s, profile %d is not supported\n", __func__, profile);
        return 0;
    }

    const struct PPP_VideoDecoder_Dev_0_11 *ppp_video_decoder_dev = NULL;
    struct pp_instance_s *pp_i = tables_get_pp_instance(instance);
    if (!pp_i) {
        trace_error("%s, bad instance\n", __func__);
        return 0;
    }

    ppp_video_decoder_dev = ppp_get_interface(PPP_VIDEODECODER_DEV_INTERFACE);
    if (!ppp_video_decoder_dev) {
        trace_error("%s, no viable %s\n", __func__, PPP_VIDEODECODER_DEV_INTERFACE);
        return 0;
    }

    if (pp_resource_get_type(context) != PP_RESOURCE_GRAPHICS3D) {
        trace_error("%s, bad resource\n", __func__);
        return 0;
    }

    PP_Resource video_decoder = pp_resource_allocate(PP_RESOURCE_VIDEO_DECODER, pp_i);
    struct pp_video_decoder_s *vd = pp_resource_acquire(video_decoder, PP_RESOURCE_VIDEO_DECODER);
    if (!vd) {
        trace_error("%s, resource allocation failed\n", __func__);
        return 0;
    }

    vd->orig_graphics3d = pp_resource_ref(context);
    vd->ppp_video_decoder_dev = ppp_video_decoder_dev;

    // create auxiliary GL context
    int32_t attribs[] = {
        PP_GRAPHICS3DATTRIB_WIDTH,      32,     // dimensions can be arbitrary
        PP_GRAPHICS3DATTRIB_HEIGHT,     32,
        PP_GRAPHICS3DATTRIB_RED_SIZE,   8,
        PP_GRAPHICS3DATTRIB_GREEN_SIZE, 8,
        PP_GRAPHICS3DATTRIB_BLUE_SIZE,  8,
        PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
        PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 16,
        GLX_Y_INVERTED_EXT,             True,
        GLX_BIND_TO_TEXTURE_RGBA_EXT,   True,
        PP_GRAPHICS3DATTRIB_NONE,
    };

    vd->graphics3d = ppb_graphics3d_create(vd->instance->id, vd->orig_graphics3d, attribs);
    if (!vd->graphics3d) {
        trace_error("%s, can't create graphics3d context\n", __func__);
        goto err_1;
    }

    vd->codec_id = AV_CODEC_ID_H264;        // TODO: other codecs
    vd->avcodec = avcodec_find_decoder(vd->codec_id);
    if (!vd->avcodec) {
        trace_error("%s, can't create codec\n", __func__);
        goto err_1;
    }

    vd->avparser = av_parser_init(vd->codec_id);
    if (!vd->avparser) {
        trace_error("%s, can't create parser\n", __func__);
        goto err_1;
    }

    vd->avctx = avcodec_alloc_context3(vd->avcodec);
    if (!vd->avctx) {
        trace_error("%s, can't create codec context\n", __func__);
        goto err_1;
    }

    if (vd->avcodec->capabilities & CODEC_CAP_TRUNCATED) {
        trace_info("%s, codec have CODEC_CAP_TRUNCATED\n", __func__);
        vd->avctx->flags |= CODEC_FLAG_TRUNCATED;
    }

    vd->avctx->opaque = vd;
    vd->avctx->thread_count = 1;
    vd->avctx->get_format = get_format;

#if AVCTX_HAVE_REFCOUNTED_BUFFERS
    vd->avctx->get_buffer2 = get_buffer2;
    vd->avctx->refcounted_frames = 1;
#else
    vd->avctx->get_buffer = get_buffer;
    vd->avctx->release_buffer = release_buffer;
#endif

    if (avcodec_open2(vd->avctx, vd->avcodec, NULL) < 0) {
        trace_error("%s, can't open codec\n", __func__);
        goto err_1;
    }

    vd->avframe = av_frame_alloc();
    if (!vd->avframe) {
        trace_error("%s, can't alloc frame\n", __func__);
        goto err_1;
    }

    pp_resource_release(video_decoder);
    return video_decoder;

err_1:
    ppb_video_decoder_destroy_priv(vd);

    pp_resource_release(video_decoder);
    pp_resource_expunge(video_decoder);
    return 0;
}