Contribs, Fribidi: allow to not build bins nor tests
[vlc.git] / src / input / decoder_helpers.c
blobe59cdcb3a10be6af58956c245ea95e13bc9ba6cd
1 /*****************************************************************************
2 * decoder_helpers.c: Functions for the management of decoders
3 *****************************************************************************
4 * Copyright (C) 1999-2019 VLC authors and VideoLAN
6 * Authors: Christophe Massiot <massiot@via.ecp.fr>
7 * Gildas Bazin <gbazin@videolan.org>
8 * Laurent Aimar <fenrir@via.ecp.fr>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
29 #include <vlc_common.h>
30 #include <vlc_codec.h>
31 #include <vlc_atomic.h>
32 #include <vlc_meta.h>
33 #include <vlc_modules.h>
34 #include <vlc_picture.h>
35 #include "libvlc.h"
37 void decoder_Init( decoder_t *p_dec, const es_format_t *restrict p_fmt )
39 p_dec->i_extra_picture_buffers = 0;
40 p_dec->b_frame_drop_allowed = false;
42 p_dec->pf_decode = NULL;
43 p_dec->pf_get_cc = NULL;
44 p_dec->pf_packetize = NULL;
45 p_dec->pf_flush = NULL;
46 p_dec->p_module = NULL;
48 es_format_Copy( &p_dec->fmt_in, p_fmt );
49 es_format_Init( &p_dec->fmt_out, p_fmt->i_cat, 0 );
52 void decoder_Clean( decoder_t *p_dec )
54 if ( p_dec->p_module != NULL )
56 module_unneed(p_dec, p_dec->p_module);
57 p_dec->p_module = NULL;
60 es_format_Clean( &p_dec->fmt_in );
61 es_format_Clean( &p_dec->fmt_out );
63 if ( p_dec->p_description )
65 vlc_meta_Delete(p_dec->p_description);
66 p_dec->p_description = NULL;
70 void decoder_Destroy( decoder_t *p_dec )
72 if (p_dec != NULL)
74 decoder_Clean( p_dec );
75 vlc_object_delete(p_dec);
79 int decoder_UpdateVideoFormat( decoder_t *dec )
81 return decoder_UpdateVideoOutput( dec, NULL );
84 int decoder_UpdateVideoOutput( decoder_t *dec, vlc_video_context *vctx_out )
86 vlc_assert( dec->fmt_in.i_cat == VIDEO_ES && dec->cbs != NULL );
87 if ( unlikely(dec->fmt_in.i_cat != VIDEO_ES || dec->cbs == NULL) )
88 return -1;
90 /* */
91 dec->fmt_out.video.i_chroma = dec->fmt_out.i_codec;
93 if( dec->fmt_out.video.i_visible_height == 1088 &&
94 var_CreateGetBool( dec, "hdtv-fix" ) )
96 dec->fmt_out.video.i_visible_height = 1080;
97 if( !(dec->fmt_out.video.i_sar_num % 136))
99 dec->fmt_out.video.i_sar_num *= 135;
100 dec->fmt_out.video.i_sar_den *= 136;
102 msg_Warn( dec, "Fixing broken HDTV stream (display_height=1088)");
105 if( !dec->fmt_out.video.i_sar_num || !dec->fmt_out.video.i_sar_den )
107 dec->fmt_out.video.i_sar_num = 1;
108 dec->fmt_out.video.i_sar_den = 1;
111 vlc_ureduce( &dec->fmt_out.video.i_sar_num, &dec->fmt_out.video.i_sar_den,
112 dec->fmt_out.video.i_sar_num, dec->fmt_out.video.i_sar_den, 50000 );
114 if( vlc_fourcc_IsYUV( dec->fmt_out.video.i_chroma ) )
116 const vlc_chroma_description_t *dsc = vlc_fourcc_GetChromaDescription( dec->fmt_out.video.i_chroma );
117 for( unsigned int i = 0; dsc && i < dsc->plane_count; i++ )
119 while( dec->fmt_out.video.i_width % dsc->p[i].w.den )
120 dec->fmt_out.video.i_width++;
121 while( dec->fmt_out.video.i_height % dsc->p[i].h.den )
122 dec->fmt_out.video.i_height++;
126 if( !dec->fmt_out.video.i_visible_width ||
127 !dec->fmt_out.video.i_visible_height )
129 if( dec->fmt_in.video.i_visible_width &&
130 dec->fmt_in.video.i_visible_height )
132 dec->fmt_out.video.i_visible_width = dec->fmt_in.video.i_visible_width;
133 dec->fmt_out.video.i_visible_height = dec->fmt_in.video.i_visible_height;
134 dec->fmt_out.video.i_x_offset = dec->fmt_in.video.i_x_offset;
135 dec->fmt_out.video.i_y_offset = dec->fmt_in.video.i_y_offset;
137 else
139 dec->fmt_out.video.i_visible_width = dec->fmt_out.video.i_width;
140 dec->fmt_out.video.i_visible_height = dec->fmt_out.video.i_height;
141 dec->fmt_out.video.i_x_offset = 0;
142 dec->fmt_out.video.i_y_offset = 0;
146 video_format_AdjustColorSpace( &dec->fmt_out.video );
148 if (dec->cbs->video.format_update == NULL)
149 return 0;
151 return dec->cbs->video.format_update( dec, vctx_out );
154 picture_t *decoder_NewPicture( decoder_t *dec )
156 vlc_assert( dec->fmt_in.i_cat == VIDEO_ES && dec->cbs != NULL );
157 if (dec->cbs->video.buffer_new == NULL)
158 return picture_NewFromFormat( &dec->fmt_out.video );
159 return dec->cbs->video.buffer_new( dec );
162 void decoder_AbortPictures(decoder_t *dec, bool abort)
164 vlc_assert(dec->fmt_in.i_cat == VIDEO_ES && dec->cbs);
165 if (dec->cbs->video.abort_pictures)
166 dec->cbs->video.abort_pictures(dec, abort);
169 struct vlc_decoder_device_priv
171 struct vlc_decoder_device device;
172 vlc_atomic_rc_t rc;
175 static int decoder_device_Open(void *func, bool forced, va_list ap)
177 VLC_UNUSED(forced);
178 vlc_decoder_device_Open open = func;
179 vlc_decoder_device *device = va_arg(ap, vlc_decoder_device *);
180 vout_window_t *window = va_arg(ap, vout_window_t *);
181 return open(device, window);
184 vlc_decoder_device *
185 vlc_decoder_device_Create(vlc_object_t *o, vout_window_t *window)
187 struct vlc_decoder_device_priv *priv =
188 vlc_object_create(o, sizeof (*priv));
189 if (!priv)
190 return NULL;
191 char *name = var_InheritString(o, "dec-dev");
192 module_t *module = vlc_module_load(&priv->device, "decoder device", name,
193 true, decoder_device_Open, &priv->device,
194 window);
195 free(name);
196 if (module == NULL)
198 vlc_objres_clear(VLC_OBJECT(&priv->device));
199 vlc_object_delete(&priv->device);
200 return NULL;
202 assert(priv->device.ops != NULL);
203 vlc_atomic_rc_init(&priv->rc);
204 return &priv->device;
207 vlc_decoder_device *
208 vlc_decoder_device_Hold(vlc_decoder_device *device)
210 struct vlc_decoder_device_priv *priv =
211 container_of(device, struct vlc_decoder_device_priv, device);
212 vlc_atomic_rc_inc(&priv->rc);
213 return device;
216 void
217 vlc_decoder_device_Release(vlc_decoder_device *device)
219 struct vlc_decoder_device_priv *priv =
220 container_of(device, struct vlc_decoder_device_priv, device);
221 if (vlc_atomic_rc_dec(&priv->rc))
223 if (device->ops->close != NULL)
224 device->ops->close(device);
225 vlc_objres_clear(VLC_OBJECT(device));
226 vlc_object_delete(device);
230 /* video context */
232 struct vlc_video_context
234 vlc_atomic_rc_t rc;
235 vlc_decoder_device *device;
236 const struct vlc_video_context_operations *ops;
237 enum vlc_video_context_type private_type;
238 size_t private_size;
239 uint8_t private[];
242 vlc_video_context * vlc_video_context_Create(vlc_decoder_device *device,
243 enum vlc_video_context_type private_type,
244 size_t private_size,
245 const struct vlc_video_context_operations *ops)
247 assert(private_type != VLC_VIDEO_CONTEXT_NONE); // use a NULL video context for that
248 vlc_video_context *vctx = malloc(sizeof(*vctx) + private_size);
249 if (unlikely(vctx == NULL))
250 return NULL;
251 vlc_atomic_rc_init( &vctx->rc );
252 vctx->private_type = private_type;
253 vctx->private_size = private_size;
254 vctx->device = device;
255 if (vctx->device)
256 vlc_decoder_device_Hold( vctx->device );
257 vctx->ops = ops;
258 return vctx;
261 void *vlc_video_context_GetPrivate(vlc_video_context *vctx, enum vlc_video_context_type type)
263 if (vctx && vctx->private_type == type)
264 return &vctx->private;
265 return NULL;
268 enum vlc_video_context_type vlc_video_context_GetType(const vlc_video_context *vctx)
270 return vctx->private_type;
273 vlc_video_context *vlc_video_context_Hold(vlc_video_context *vctx)
275 vlc_atomic_rc_inc( &vctx->rc );
276 return vctx;
279 void vlc_video_context_Release(vlc_video_context *vctx)
281 if ( vlc_atomic_rc_dec( &vctx->rc ) )
283 if (vctx->device)
284 vlc_decoder_device_Release( vctx->device );
285 if ( vctx->ops && vctx->ops->destroy )
286 vctx->ops->destroy( vlc_video_context_GetPrivate(vctx, vctx->private_type) );
287 free(vctx);
291 vlc_decoder_device* vlc_video_context_HoldDevice(vlc_video_context *vctx)
293 if (!vctx->device)
294 return NULL;
295 return vlc_decoder_device_Hold( vctx->device );
299 /** encoder **/
300 vlc_decoder_device *vlc_encoder_GetDecoderDevice( encoder_t *enc )
302 vlc_assert( enc->fmt_in.i_cat == VIDEO_ES && enc->cbs != NULL );
303 if ( unlikely(enc->fmt_in.i_cat != VIDEO_ES || enc->cbs == NULL ) )
304 return NULL;
306 return enc->cbs->video.get_device( enc );