]> git.sesse.net Git - vlc/blob - modules/hw/vdpau/picture.c
vdpau: add support for 4:4:4 chroma sampling
[vlc] / modules / hw / vdpau / picture.c
1 /*****************************************************************************
2  * picture.c: VDPAU instance management for VLC
3  *****************************************************************************
4  * Copyright (C) 2013 RĂ©mi Denis-Courmont
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <vlc_common.h>
30 #include <vlc_picture.h>
31 #include "vlc_vdpau.h"
32
33 #pragma GCC visibility push(default)
34
35 static void SurfaceDestroy(void *opaque)
36 {
37     vlc_vdp_video_field_t *field = opaque;
38     vlc_vdp_video_frame_t *frame = field->frame;
39     VdpStatus err;
40
41     /* Destroy field-specific infos */
42     free(field);
43
44     if (atomic_fetch_sub(&frame->refs, 1) != 1)
45         return;
46
47     /* Destroy frame (video surface) */
48     err = vdp_video_surface_destroy(frame->vdp, frame->surface);
49     if (err != VDP_STATUS_OK)
50         fprintf(stderr, "video surface destruction failure: %s\n",
51                 vdp_get_error_string(frame->vdp, err));
52     vdp_release_x11(frame->vdp);
53     free(frame);
54 }
55
56 static const VdpProcamp procamp_default =
57 {
58     .struct_version = VDP_PROCAMP_VERSION,
59     .brightness = 0.f,
60     .contrast = 1.f,
61     .saturation = 1.f,
62     .hue = 0.f,
63 };
64
65 vlc_vdp_video_field_t *vlc_vdp_video_create(vdp_t *vdp,
66                                             VdpVideoSurface surface)
67 {
68     vlc_vdp_video_field_t *field = malloc(sizeof (*field));
69     vlc_vdp_video_frame_t *frame = malloc(sizeof (*frame));
70
71     if (unlikely(field == NULL || frame == NULL))
72     {
73         free(frame);
74         free(field);
75         vdp_video_surface_destroy(vdp, surface);
76         return NULL;
77     }
78
79     field->destroy = SurfaceDestroy;
80     field->frame = frame;
81     field->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
82     field->procamp = procamp_default;
83     field->sharpen = 0.f;
84
85     atomic_init(&frame->refs, 1);
86     frame->surface = surface;
87     frame->vdp = vdp_hold_x11(vdp, &frame->device);
88     return field;
89 }
90
91 VdpStatus vlc_vdp_video_attach(vdp_t *vdp, VdpVideoSurface surface,
92                                picture_t *pic)
93 {
94     vlc_vdp_video_field_t *field = vlc_vdp_video_create(vdp, surface);
95     if (unlikely(field == NULL))
96         return VDP_STATUS_RESOURCES;
97
98     assert(pic->format.i_chroma == VLC_CODEC_VDPAU_VIDEO_420
99         || pic->format.i_chroma == VLC_CODEC_VDPAU_VIDEO_422
100         || pic->format.i_chroma == VLC_CODEC_VDPAU_VIDEO_444);
101     assert(!picture_IsReferenced(pic));
102     assert(pic->context == NULL);
103     pic->context = field;
104     return VDP_STATUS_OK;
105 }
106
107 vlc_vdp_video_field_t *vlc_vdp_video_copy(vlc_vdp_video_field_t *fold)
108 {
109     vlc_vdp_video_frame_t *frame = fold->frame;
110     vlc_vdp_video_field_t *fnew = malloc(sizeof (*fnew));
111     if (unlikely(fnew == NULL))
112         return NULL;
113
114     fnew->destroy = SurfaceDestroy;
115     fnew->frame = frame;
116     fnew->structure = fold->structure;
117     fnew->procamp = fold->procamp;
118     fnew->sharpen = fold->sharpen;
119
120     atomic_fetch_add(&frame->refs, 1);
121     return fnew;
122 }