picture.c 3.86 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*****************************************************************************
 * picture.c: VDPAU instance management for VLC
 *****************************************************************************
 * Copyright (C) 2013 Rémi Denis-Courmont
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <stdlib.h>
#include <stdio.h>
27
#include <string.h>
28
29
30
31
32
33
34
35
36
#include <assert.h>
#include <vlc_common.h>
#include <vlc_picture.h>
#include "vlc_vdpau.h"

#pragma GCC visibility push(default)

static void SurfaceDestroy(void *opaque)
{
37
38
    vlc_vdp_video_field_t *field = opaque;
    vlc_vdp_video_frame_t *frame = field->frame;
39
40
    VdpStatus err;

41
42
43
44
45
46
47
48
    /* Destroy field-specific infos */
    free(field);

    if (atomic_fetch_sub(&frame->refs, 1) != 1)
        return;

    /* Destroy frame (video surface) */
    err = vdp_video_surface_destroy(frame->vdp, frame->surface);
49
50
    if (err != VDP_STATUS_OK)
        fprintf(stderr, "video surface destruction failure: %s\n",
51
52
53
                vdp_get_error_string(frame->vdp, err));
    vdp_release_x11(frame->vdp);
    free(frame);
54
55
}

56
57
58
59
60
61
62
63
64
static const VdpProcamp procamp_default =
{
    .struct_version = VDP_PROCAMP_VERSION,
    .brightness = 0.f,
    .contrast = 1.f,
    .saturation = 1.f,
    .hue = 0.f,
};

65
66
67
VdpStatus vlc_vdp_video_attach(vdp_t *vdp, VdpVideoSurface surface,
                               picture_t *pic)
{
68
69
70
71
    vlc_vdp_video_field_t *field = malloc(sizeof (*field));
    vlc_vdp_video_frame_t *frame = malloc(sizeof (*frame));

    if (unlikely(field == NULL || frame == NULL))
72
    {
73
74
        free(frame);
        free(field);
75
76
77
78
        vdp_video_surface_destroy(vdp, surface);
        return VDP_STATUS_RESOURCES;
    }

79
80
81
    assert(pic->format.i_chroma == VLC_CODEC_VDPAU_VIDEO_420
        || pic->format.i_chroma == VLC_CODEC_VDPAU_VIDEO_422);
    assert(!picture_IsReferenced(pic));
82
    assert(pic->context == NULL);
83
84
85
86
    pic->context = field;

    field->destroy = SurfaceDestroy;
    field->frame = frame;
87
    field->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
88
    field->procamp = procamp_default;
89
    field->sharpen = 0.f;
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

    atomic_init(&frame->refs, 1);
    frame->surface = surface;
    frame->vdp = vdp_hold_x11(vdp, &frame->device);
    return VDP_STATUS_OK;
}

VdpStatus vlc_vdp_video_copy(picture_t *restrict dst, picture_t *restrict src)
{
    vlc_vdp_video_field_t *fold = src->context;
    vlc_vdp_video_frame_t *frame = fold->frame;
    vlc_vdp_video_field_t *fnew = malloc(sizeof (*fnew));
    if (unlikely(fnew == NULL))
        return VDP_STATUS_RESOURCES;

105
106
107
108
109
    assert(src->format.i_chroma == VLC_CODEC_VDPAU_VIDEO_420
        || src->format.i_chroma == VLC_CODEC_VDPAU_VIDEO_422);
    assert(dst->format.i_chroma == VLC_CODEC_VDPAU_VIDEO_420
        || dst->format.i_chroma == VLC_CODEC_VDPAU_VIDEO_422);
    assert(!picture_IsReferenced(dst));
110
111
112
113
114
    assert(dst->context == NULL);
    dst->context = fnew;

    fnew->destroy = SurfaceDestroy;
    fnew->frame = frame;
115
    fnew->structure = fold->structure;
116
    fnew->procamp = fold->procamp;
117
    fnew->sharpen = fold->sharpen;
118
119

    atomic_fetch_add(&frame->refs, 1);
120
121
    return VDP_STATUS_OK;
}