]> git.sesse.net Git - vlc/blob - modules/hw/vdpau/deinterlace.c
vdpau_avcodec: fix mismatched alloc/free
[vlc] / modules / hw / vdpau / deinterlace.c
1 /*****************************************************************************
2  * deinterlace.c: VDPAU deinterlacing filter
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 <assert.h>
27
28 #include <vlc_common.h>
29 #include <vlc_plugin.h>
30 #include <vlc_filter.h>
31 #include "vlc_vdpau.h"
32
33 struct filter_sys_t
34 {
35     mtime_t last_pts;
36 };
37
38 static picture_t *Deinterlace(filter_t *filter, picture_t *src)
39 {
40     filter_sys_t *sys = filter->p_sys;
41     mtime_t last_pts = sys->last_pts;
42
43     sys->last_pts = src->date;
44
45     vlc_vdp_video_field_t *f1 = src->context;
46     if (unlikely(f1 == NULL))
47         return src;
48     if (f1->structure != VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME)
49         return src; /* cannot deinterlace twice */
50
51 #ifdef VOUT_CORE_GETS_A_CLUE
52     picture_t *dst = filter_NewPicture(filter);
53 #else
54     picture_t *dst = picture_NewFromFormat(&src->format);
55 #endif
56     if (dst == NULL)
57         return src; /* cannot deinterlace without copying fields */
58
59     vlc_vdp_video_field_t *f2 = vlc_vdp_video_copy(f1); // shallow copy
60     if (unlikely(f2 == NULL))
61     {
62         picture_Release(dst);
63         return src;
64     }
65
66     picture_CopyProperties(dst, src);
67     dst->context = f2;
68
69     if (last_pts != VLC_TS_INVALID)
70         dst->date = (3 * src->date - last_pts) / 2;
71     else
72     if (filter->fmt_in.video.i_frame_rate != 0)
73         dst->date = src->date + ((filter->fmt_in.video.i_frame_rate_base
74                             * CLOCK_FREQ) / filter->fmt_in.video.i_frame_rate);
75     dst->b_top_field_first = !src->b_top_field_first;
76     dst->i_nb_fields = 1;
77     src->i_nb_fields = 1;
78
79     assert(src->p_next == NULL);
80     src->p_next = dst;
81
82     if (src->b_progressive || src->b_top_field_first)
83     {
84         f1->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
85         f2->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
86     }
87     else
88     {
89         f1->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
90         f2->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
91     }
92
93     src->b_progressive = true;
94     return src;
95 }
96
97 static int Open(vlc_object_t *obj)
98 {
99     filter_t *filter = (filter_t *)obj;
100
101     if (filter->fmt_in.video.i_chroma != VLC_CODEC_VDPAU_VIDEO_422
102      && filter->fmt_in.video.i_chroma != VLC_CODEC_VDPAU_VIDEO_420)
103         return VLC_EGENERIC;
104     if (!video_format_IsSimilar(&filter->fmt_in.video, &filter->fmt_out.video))
105         return VLC_EGENERIC;
106
107     filter_sys_t *sys = malloc(sizeof (*sys));
108     if (unlikely(sys == NULL))
109         return VLC_ENOMEM;
110
111     /* NOTE: Only weave and bob are mandatory for the hardware to implement.
112      * The other modes and IVTC should be checked. */
113
114     sys->last_pts = VLC_TS_INVALID;
115
116     filter->pf_video_filter = Deinterlace;
117     filter->p_sys = sys;
118     filter->fmt_out.video.i_frame_rate *= 2;
119     return VLC_SUCCESS;
120 }
121
122 static void Close(vlc_object_t *obj)
123 {
124     filter_t *filter = (filter_t *)obj;
125     filter_sys_t *sys = filter->p_sys;
126
127     free(sys);
128 }
129
130 vlc_module_begin()
131     set_description(N_("VDPAU deinterlacing filter"))
132     set_capability("video filter2", 0)
133     set_category(CAT_VIDEO)
134     set_subcategory(SUBCAT_VIDEO_VFILTER)
135     set_callbacks(Open, Close)
136     add_shortcut ("deinterlace")
137 vlc_module_end()