1 /*****************************************************************************
2 * common.c : Common helper function for the VLC deinterlacer
3 *****************************************************************************
4 * Copyright (C) 2000-2017 VLC authors and VideoLAN
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 *****************************************************************************/
32 #include <vlc_picture.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. */
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
)
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
107 void GetDeinterlacingOutput( const struct deinterlace_ctx
*p_context
,
108 video_format_t
*p_dst
, const video_format_t
*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. */
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
);
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
)
155 /* Update the input frame history, if the currently active algorithm
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
;
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
;
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
207 i_nb_fields
= p_pic
->i_nb_fields
; /* unused */
210 /* For framerate doublers, determine field duration and allocate
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 "\
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
)
238 p_dst
[i
] = filter_NewPicture( p_filter
);
241 picture_CopyProperties( p_dst
[i
], p_pic
);
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
);
266 if ( !p_context
->settings
.b_double_rate
)
268 if ( p_context
->pf_render_single_pic( p_filter
, p_dst
[0], p_pic
) )
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
) )
279 p_context
->pf_render_ordered( p_filter
, p_dst
[1], p_pic
,
280 1, b_top_field_first
);
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
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
;
330 p_dst
[i
]->date
= VLC_TS_INVALID
;
335 for( int i
= 0; i
< DEINTERLACE_DST_SIZE
; ++i
)
339 p_dst
[i
]->b_progressive
= true;
340 p_dst
[i
]->i_nb_fields
= 2;
344 picture_Release( p_pic
);
348 picture_Release( p_dst
[0] );
349 for( int i
= 1; i
< DEINTERLACE_DST_SIZE
; ++i
)
352 picture_Release( p_dst
[i
] );
355 picture_Release( p_pic
);