Exemplo n.º 1
0
static int socksserver_on_clientconnect (void* userdata, struct sockaddr_storage* clientaddr, int fd) {
    socksserver* srv = (socksserver*) userdata;
    char buffer[256];
    (void) buffer;
    if(CONFIG_LOG && srv->log && clientaddr) {
        logstart();
        printfd(fd);
        LOGPUT(1, VARISL(" connect from: "), VARIC(get_client_ip(clientaddr, buffer, sizeof(buffer))), NULL);
    }

    if(fd < 3 || fd >= MAX_FD) {
        rocksockserver_disconnect_client(&srv->serva, fd);
        return -2;
    }

    fdinfo* client = &srv->clients[fdindex(fd)];

    // put into nonblocking mode, so that writes will not block the server
    int flags = fcntl(fd, F_GETFL);
    if(flags == -1) return -1;
    if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) return -2;

    client->data = find_free_buffer(srv);
    if (!client->data) {
        if(CONFIG_LOG && srv->log) {
            logstart();
            LOGPUTS(1, SPL("warning: couldnt find free buffer\n"));
        }
        rocksockserver_disconnect_client(&srv->serva, fd);
        return -2;
    }

    client->state = SS_CONNECTED;
    client->data->state = BS_IDLE;
    client->data->start = 0;
    client->target_fd = -1;

    return 0;
}
static
void
request_buffers(struct pp_video_decoder_s *vd)
{
    const PP_Instance instance = vd->instance->id;
    const struct PP_Size dimensions = { .width = vd->avctx->width,
                                        .height = vd->avctx->height };

    pp_resource_release(vd->self_id);
    // TODO: how many surfaces do we need?
    vd->ppp_video_decoder_dev->ProvidePictureBuffers(instance, vd->self_id, 21, &dimensions,
                                                     GL_TEXTURE_2D);
    pp_resource_acquire(vd->self_id, PP_RESOURCE_VIDEO_DECODER);
}

static
uint32_t
find_free_buffer(struct pp_video_decoder_s *vd)
{
    for (uint32_t idx = 0; idx < vd->buffer_count; idx ++) {
        if (!vd->buffers[idx].used) {
            vd->buffers[idx].used = 1;
            return idx;
        }
    }

    return (uint32_t)-1;
}

static
void
issue_frame(struct pp_video_decoder_s *vd)
{
    AVFrame *frame = vd->avframe;
    uint32_t idx = find_free_buffer(vd);
    int32_t  bitstream_buffer_id = (int32_t)frame->pkt_pts;

    if (idx == (uint32_t)-1) {
        trace_warning("%s, no free buffer available\n", __func__);
        return;
    }

    struct pp_graphics3d_s *g3d = pp_resource_acquire(vd->graphics3d, PP_RESOURCE_GRAPHICS3D);
    if (!g3d) {
        trace_error("%s, bad resource\n", __func__);
        return;
    }

    VASurfaceID va_surf = GPOINTER_TO_SIZE(frame->data[3]);

    pthread_mutex_lock(&display.lock);
    glXMakeCurrent(display.x, g3d->glx_pixmap, g3d->glc);
    glBindTexture(GL_TEXTURE_2D, vd->buffers[idx].texture_id);
    display.glXBindTexImageEXT(display.x, vd->buffers[idx].glx_pixmap, GLX_FRONT_EXT, NULL);
    XFlush(display.x);
    vaPutSurface(display.va, va_surf, vd->buffers[idx].pixmap,
                 0, 0, frame->width, frame->height,
                 0, 0, frame->width, frame->height,
                 NULL, 0, VA_FRAME_PICTURE);
    XFlush(display.x);
    glXMakeCurrent(display.x, None, NULL);
    pthread_mutex_unlock(&display.lock);

    pp_resource_release(vd->graphics3d);

    const PP_Instance instance = vd->instance->id;
    const struct PP_Picture_Dev picture = {
        .picture_buffer_id = vd->buffers[idx].id,
        .bitstream_buffer_id = bitstream_buffer_id,
    };

    pp_resource_release(vd->self_id);
    vd->ppp_video_decoder_dev->PictureReady(instance, vd->self_id, &picture);
    pp_resource_acquire(vd->self_id, PP_RESOURCE_VIDEO_DECODER);
}

static
void
decode_frame(struct pp_video_decoder_s *vd, uint8_t *data, size_t data_len,
             int32_t bitstream_buffer_id)
{
    AVPacket packet;
    av_init_packet(&packet);
    packet.data = data;
    packet.size = data_len;
    packet.pts = bitstream_buffer_id;

    // libavcodec can call hw functions, which in turn can call Xlib functions,
    // therefore we need to lock
    pthread_mutex_lock(&display.lock);
    int got_frame = 0;
    int len = avcodec_decode_video2(vd->avctx, vd->avframe, &got_frame, &packet);
    pthread_mutex_unlock(&display.lock);
    if (len < 0) {
        trace_error("%s, error %d while decoding frame\n", __func__, len);
        return;
    }

    if (got_frame) {
        if (!vd->buffers_were_requested) {
            request_buffers(vd);
            vd->buffers_were_requested = 1;
        }

        issue_frame(vd);
    }
}