deinterlace: show the interlaced picture rather than nothing in case of error
[vlc.git] / modules / video_filter / deinterlace / common.c
blob1791190ff8bd28fb8439848c5ef2118c0aa86590
1 /*****************************************************************************
2 * common.c : Common helper function for the VLC deinterlacer
3 *****************************************************************************
4 * Copyright (C) 2000-2017 VLC authors and VideoLAN
5 * $Id$
7 * Author: Sam Hocevar <sam@zoy.org>
8 * Christophe Massiot <massiot@via.ecp.fr>
9 * Laurent Aimar <fenrir@videolan.org>
10 * Juha Jeronen <juha.jeronen@jyu.fi>
11 * Steve Lhomme <robux4@gmail.com>
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU Lesser General Public License as published by
15 * the Free Software Foundation; either version 2.1 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with this program; if not, write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26 *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
32 #include <vlc_picture.h>
34 #include "common.h"
36 void InitDeinterlacingContext( struct deinterlace_ctx *p_context )
38 p_context->settings.b_double_rate = false;
39 p_context->settings.b_half_height = false;
40 p_context->settings.b_use_frame_history = false;
41 p_context->settings.b_custom_pts = false;
43 p_context->meta[0].pi_date = VLC_TS_INVALID;
44 p_context->meta[0].pi_nb_fields = 2;
45 p_context->meta[0].pb_top_field_first = true;
46 for( int i = 1; i < METADATA_SIZE; i++ )
47 p_context->meta[i] = p_context->meta[i-1];
49 p_context->i_frame_offset = 0; /* start with default value (first-ever frame
50 cannot have offset) */
51 for( int i = 0; i < HISTORY_SIZE; i++ )
52 p_context->pp_history[i] = NULL;
55 void FlushDeinterlacing(struct deinterlace_ctx *p_context)
57 p_context->meta[0].pi_date = VLC_TS_INVALID;
58 p_context->meta[0].pi_nb_fields = 2;
59 p_context->meta[0].pb_top_field_first = true;
60 for( int i = 1; i < METADATA_SIZE; i++ )
61 p_context->meta[i] = p_context->meta[i-1];
63 p_context->i_frame_offset = 0; /* reset to default value (first frame after
64 flush cannot have offset) */
65 for( int i = 0; i < HISTORY_SIZE; i++ )
67 if( p_context->pp_history[i] )
68 picture_Release( p_context->pp_history[i] );
69 p_context->pp_history[i] = NULL;
73 mtime_t GetFieldDuration(const struct deinterlace_ctx *p_context,
74 const video_format_t *fmt, const picture_t *p_pic )
76 mtime_t i_field_dur = 0;
78 /* Calculate one field duration. */
79 int i = 0;
80 int iend = METADATA_SIZE-1;
81 /* Find oldest valid logged date.
82 The current input frame doesn't count. */
83 for( ; i < iend; i++ )
84 if( p_context->meta[i].pi_date > VLC_TS_INVALID )
85 break;
86 if( i < iend )
88 /* Count how many fields the valid history entries
89 (except the new frame) represent. */
90 int i_fields_total = 0;
91 for( int j = i ; j < iend; j++ )
92 i_fields_total += p_context->meta[j].pi_nb_fields;
93 /* One field took this long. */
94 i_field_dur = (p_pic->date - p_context->meta[i].pi_date) / i_fields_total;
96 else if (fmt->i_frame_rate_base)
97 i_field_dur = CLOCK_FREQ * fmt->i_frame_rate_base / fmt->i_frame_rate;
99 /* Note that we default to field duration 0 if it could not be
100 determined. This behaves the same as the old code - leaving the
101 extra output frame dates the same as p_pic->date if the last cached
102 date was not valid.
104 return i_field_dur;
107 void GetDeinterlacingOutput( const struct deinterlace_ctx *p_context,
108 video_format_t *p_dst, const video_format_t *p_src )
110 *p_dst = *p_src;
112 if( p_context->settings.b_half_height )
114 p_dst->i_height /= 2;
115 p_dst->i_visible_height /= 2;
116 p_dst->i_y_offset /= 2;
117 p_dst->i_sar_den *= 2;
120 if( p_context->settings.b_double_rate )
122 p_dst->i_frame_rate *= 2;
126 #define CUSTOM_PTS -1
128 picture_t *DoDeinterlacing( filter_t *p_filter,
129 struct deinterlace_ctx *p_context, picture_t *p_pic )
131 picture_t *p_dst[DEINTERLACE_DST_SIZE];
132 int i_double_rate_alloc_end;
133 /* Remember the frame offset that we should use for this frame.
134 The value in p_sys will be updated to reflect the correct value
135 for the *next* frame when we call the renderer. */
136 int i_frame_offset;
137 int i_meta_idx;
139 bool b_top_field_first;
141 /* Request output picture */
142 p_dst[0] = filter_NewPicture( p_filter );
143 if( p_dst[0] == NULL )
145 picture_Release( p_pic );
146 return NULL;
148 picture_CopyProperties( p_dst[0], p_pic );
150 /* Any unused p_dst pointers must be NULL, because they are used to
151 check how many output frames we have. */
152 for( int i = 1; i < DEINTERLACE_DST_SIZE; ++i )
153 p_dst[i] = NULL;
155 /* Update the input frame history, if the currently active algorithm
156 needs it. */
157 if( p_context->settings.b_use_frame_history )
159 /* Keep reference for the picture */
160 picture_t *p_dup = picture_Hold( p_pic );
162 /* Slide the history */
163 if( p_context->pp_history[0] )
164 picture_Release( p_context->pp_history[0] );
165 for( int i = 1; i < HISTORY_SIZE; i++ )
166 p_context->pp_history[i-1] = p_context->pp_history[i];
167 p_context->pp_history[HISTORY_SIZE-1] = p_dup;
170 /* Slide the metadata history. */
171 for( int i = 1; i < METADATA_SIZE; i++ )
172 p_context->meta[i-1] = p_context->meta[i];
173 /* The last element corresponds to the current input frame. */
174 p_context->meta[METADATA_SIZE-1].pi_date = p_pic->date;
175 p_context->meta[METADATA_SIZE-1].pi_nb_fields = p_pic->i_nb_fields;
176 p_context->meta[METADATA_SIZE-1].pb_top_field_first = p_pic->b_top_field_first;
178 /* Remember the frame offset that we should use for this frame.
179 The value in p_sys will be updated to reflect the correct value
180 for the *next* frame when we call the renderer. */
181 i_frame_offset = p_context->i_frame_offset;
182 i_meta_idx = (METADATA_SIZE-1) - i_frame_offset;
184 int i_nb_fields;
186 /* These correspond to the current *outgoing* frame. */
187 if( i_frame_offset != CUSTOM_PTS )
189 /* Pick the correct values from the history. */
190 b_top_field_first = p_context->meta[i_meta_idx].pb_top_field_first;
191 i_nb_fields = p_context->meta[i_meta_idx].pi_nb_fields;
193 else
195 /* Framerate doublers must not request CUSTOM_PTS, as they need the
196 original field timings, and need Deinterlace() to allocate the
197 correct number of output frames. */
198 assert( !p_context->settings.b_double_rate );
200 /* NOTE: i_nb_fields is only used for framerate doublers, so it is
201 unused in this case. b_top_field_first is only passed to the
202 algorithm. We assume that algorithms that request CUSTOM_PTS
203 will, if necessary, extract the TFF/BFF information themselves.
205 b_top_field_first = p_pic->b_top_field_first; /* this is not guaranteed
206 to be meaningful */
207 i_nb_fields = p_pic->i_nb_fields; /* unused */
210 /* For framerate doublers, determine field duration and allocate
211 output frames. */
212 i_double_rate_alloc_end = 0; /* One past last for allocated output
213 frames in p_dst[]. Used only for
214 framerate doublers. Will be inited
215 below. Declared here because the
216 PTS logic needs the result. */
217 if( p_context->settings.b_double_rate )
219 i_double_rate_alloc_end = i_nb_fields;
220 if( i_nb_fields > DEINTERLACE_DST_SIZE )
222 /* Note that the effective buffer size depends also on the constant
223 private_picture in vout_wrapper.c, since that determines the
224 maximum number of output pictures filter_NewPicture() will
225 successfully allocate for one input frame.
227 msg_Err( p_filter, "Framerate doubler: output buffer too small; "\
228 "fields = %d, buffer size = %d. Dropping the "\
229 "remaining fields.",
230 i_nb_fields, DEINTERLACE_DST_SIZE );
231 i_double_rate_alloc_end = DEINTERLACE_DST_SIZE;
234 /* Allocate output frames. */
235 for( int i = 1; i < i_double_rate_alloc_end ; ++i )
237 p_dst[i-1]->p_next =
238 p_dst[i] = filter_NewPicture( p_filter );
239 if( p_dst[i] )
241 picture_CopyProperties( p_dst[i], p_pic );
243 else
245 msg_Err( p_filter, "Framerate doubler: could not allocate "\
246 "output frame %d", i+1 );
247 i_double_rate_alloc_end = i; /* Inform the PTS logic about the
248 correct end position. */
249 break; /* If this happens, the rest of the allocations
250 aren't likely to work, either... */
253 /* Now we have allocated *up to* the correct number of frames;
254 normally, exactly the correct number. Upon alloc failure,
255 we may have succeeded in allocating *some* output frames,
256 but fewer than were desired. In such a case, as many will
257 be rendered as were successfully allocated.
259 Note that now p_dst[i] != NULL
260 for 0 <= i < i_double_rate_alloc_end. */
262 assert( p_context->settings.b_double_rate || p_dst[1] == NULL );
263 assert( i_nb_fields > 2 || p_dst[2] == NULL );
265 /* Render */
266 if ( !p_context->settings.b_double_rate )
268 if ( p_context->pf_render_single_pic( p_filter, p_dst[0], p_pic ) )
269 goto drop;
271 else
273 /* Note: RenderIVTC will automatically drop the duplicate frames
274 produced by IVTC. This is part of normal operation. */
275 if ( p_context->pf_render_ordered( p_filter, p_dst[0], p_pic,
276 0, !b_top_field_first ) )
277 goto drop;
278 if ( p_dst[1] )
279 p_context->pf_render_ordered( p_filter, p_dst[1], p_pic,
280 1, b_top_field_first );
281 if ( p_dst[2] )
282 p_context->pf_render_ordered( p_filter, p_dst[1], p_pic,
283 2, !b_top_field_first );
286 if ( p_context->settings.b_custom_pts )
288 assert(p_context->settings.b_use_frame_history);
289 if( p_context->pp_history[0] && p_context->pp_history[1] )
291 /* The next frame will get a custom timestamp, too. */
292 p_context->i_frame_offset = CUSTOM_PTS;
294 else if( !p_context->pp_history[0] && !p_context->pp_history[1] ) /* first frame */
297 else /* second frame */
299 /* At the next frame, the filter starts. The next frame will get
300 a custom timestamp. */
301 p_context->i_frame_offset = CUSTOM_PTS;
305 /* Set output timestamps, if the algorithm didn't request CUSTOM_PTS
306 for this frame. */
307 assert( i_frame_offset <= METADATA_SIZE ||
308 i_frame_offset == CUSTOM_PTS );
309 if( i_frame_offset != CUSTOM_PTS )
311 mtime_t i_base_pts = p_context->meta[i_meta_idx].pi_date;
313 /* Note: in the usual case (i_frame_offset = 0 and
314 b_double_rate = false), this effectively does nothing.
315 This is needed to correct the timestamp
316 when i_frame_offset > 0. */
317 p_dst[0]->date = i_base_pts;
319 if( p_context->settings.b_double_rate )
321 mtime_t i_field_dur = GetFieldDuration( p_context, &p_filter->fmt_out.video, p_pic );
322 /* Processing all actually allocated output frames. */
323 for( int i = 1; i < i_double_rate_alloc_end; ++i )
325 /* XXX it's not really good especially for the first picture, but
326 * I don't think that delaying by one frame is worth it */
327 if( i_base_pts > VLC_TS_INVALID )
328 p_dst[i]->date = i_base_pts + i * i_field_dur;
329 else
330 p_dst[i]->date = VLC_TS_INVALID;
335 for( int i = 0; i < DEINTERLACE_DST_SIZE; ++i )
337 if( p_dst[i] )
339 p_dst[i]->b_progressive = true;
340 p_dst[i]->i_nb_fields = 2;
344 picture_Release( p_pic );
345 return p_dst[0];
347 drop:
348 picture_Release( p_dst[0] );
349 for( int i = 1; i < DEINTERLACE_DST_SIZE; ++i )
351 if( p_dst[i] )
352 picture_Release( p_dst[i] );
354 #ifndef NDEBUG
355 picture_Release( p_pic );
356 return NULL;
357 #else
358 return p_pic;
359 #endif