]> git.sesse.net Git - vlc/blob - modules/codec/ffmpeg/video_filter.c
886e95777f655f537aa86f1ee6b6ca88287f223b
[vlc] / modules / codec / ffmpeg / video_filter.c
1 /*****************************************************************************
2  * video filter: video filter doing chroma conversion and resizing
3  *               using the ffmpeg library
4  *****************************************************************************
5  * Copyright (C) 1999-2001 the VideoLAN team
6  * $Id$
7  *
8  * Authors: Gildas Bazin <gbazin@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
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 General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc/vlc.h>
33 #include <vlc_codec.h>
34 #include <vlc_vout.h>
35 #include <vlc_filter.h>
36
37 /* ffmpeg header */
38 #ifdef HAVE_FFMPEG_AVCODEC_H
39 #   include <ffmpeg/avcodec.h>
40 #else
41 #   include <avcodec.h>
42 #endif
43
44 #include "ffmpeg.h"
45
46 #if !defined(HAVE_FFMPEG_SWSCALE_H) && !defined(HAVE_LIBSWSCALE_TREE)
47 void E_(InitLibavcodec) ( vlc_object_t *p_object );
48 static int CheckInit( filter_t *p_filter );
49 static picture_t *Process( filter_t *p_filter, picture_t *p_pic );
50
51 /*****************************************************************************
52  * filter_sys_t : filter descriptor
53  *****************************************************************************/
54 struct filter_sys_t
55 {
56     vlc_bool_t b_resize;
57     vlc_bool_t b_convert;
58     vlc_bool_t b_resize_first;
59     vlc_bool_t b_enable_croppadd;
60
61     es_format_t fmt_in;
62     int i_src_ffmpeg_chroma;
63     es_format_t fmt_out;
64     int i_dst_ffmpeg_chroma;
65
66     AVPicture tmp_pic;
67
68     ImgReSampleContext *p_rsc;
69 };
70
71 /*****************************************************************************
72  * OpenFilterEx: common code to OpenFilter and OpenCropPadd
73  *****************************************************************************/
74 static int OpenFilterEx( vlc_object_t *p_this, vlc_bool_t b_enable_croppadd )
75 {
76     filter_t *p_filter = (filter_t*)p_this;
77     filter_sys_t *p_sys;
78     vlc_bool_t b_convert, b_resize;
79
80     /* Check if we can handle that formats */
81     if( E_(GetFfmpegChroma)( p_filter->fmt_in.video.i_chroma ) < 0 ||
82         E_(GetFfmpegChroma)( p_filter->fmt_out.video.i_chroma ) < 0 )
83     {
84         return VLC_EGENERIC;
85     }
86
87     b_resize =
88         ( p_filter->fmt_in.video.i_width != p_filter->fmt_out.video.i_width ) ||
89         ( p_filter->fmt_in.video.i_height != p_filter->fmt_out.video.i_height );
90
91     if ( b_enable_croppadd )
92     {
93         b_resize = b_resize ||
94            ( p_filter->fmt_in.video.i_visible_width != p_filter->fmt_in.video.i_width ) ||
95            ( p_filter->fmt_in.video.i_visible_height != p_filter->fmt_in.video.i_height ) ||
96            ( p_filter->fmt_in.video.i_x_offset != 0 ) ||
97            ( p_filter->fmt_in.video.i_y_offset != 0 ) ||
98            ( p_filter->fmt_out.video.i_visible_width != p_filter->fmt_out.video.i_width ) ||
99            ( p_filter->fmt_out.video.i_visible_height != p_filter->fmt_out.video.i_height ) ||
100            ( p_filter->fmt_out.video.i_x_offset != 0 ) ||
101            ( p_filter->fmt_out.video.i_y_offset != 0 );
102     }
103
104     b_convert =
105         ( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma );
106
107     if( !b_resize && !b_convert )
108     {
109         /* Nothing to do */
110         return VLC_EGENERIC;
111     }
112
113     /* Allocate the memory needed to store the decoder's structure */
114     if( ( p_filter->p_sys = p_sys =
115           (filter_sys_t *)malloc(sizeof(filter_sys_t)) ) == NULL )
116     {
117         msg_Err( p_filter, "out of memory" );
118         return VLC_EGENERIC;
119     }
120
121     /* Misc init */
122     p_sys->p_rsc = NULL;
123     p_sys->b_enable_croppadd = b_enable_croppadd;
124     p_sys->i_src_ffmpeg_chroma =
125         E_(GetFfmpegChroma)( p_filter->fmt_in.video.i_chroma );
126     p_sys->i_dst_ffmpeg_chroma =
127         E_(GetFfmpegChroma)( p_filter->fmt_out.video.i_chroma );
128     p_filter->pf_video_filter = Process;
129     es_format_Init( &p_sys->fmt_in, 0, 0 );
130     es_format_Init( &p_sys->fmt_out, 0, 0 );
131
132     /* Dummy alloc, will be reallocated in CheckInit */
133     avpicture_alloc( &p_sys->tmp_pic, p_sys->i_src_ffmpeg_chroma,
134                      p_filter->fmt_out.video.i_width,
135                      p_filter->fmt_out.video.i_height );
136
137     if( CheckInit( p_filter ) != VLC_SUCCESS )
138     {
139         if( p_sys->p_rsc ) img_resample_close( p_sys->p_rsc );
140         avpicture_free( &p_sys->tmp_pic );
141         free( p_sys );
142         return VLC_EGENERIC;
143     }
144
145     msg_Dbg( p_filter, "input: %ix%i %4.4s -> %ix%i %4.4s",
146              p_filter->fmt_in.video.i_width, p_filter->fmt_in.video.i_height,
147              (char *)&p_filter->fmt_in.video.i_chroma,
148              p_filter->fmt_out.video.i_width, p_filter->fmt_out.video.i_height,
149              (char *)&p_filter->fmt_out.video.i_chroma );
150
151     /* libavcodec needs to be initialized for some chroma conversions */
152     E_(InitLibavcodec)(p_this);
153
154     return VLC_SUCCESS;
155 }
156
157 /*****************************************************************************
158  * OpenFilter: probe the filter and return score
159  *****************************************************************************/
160 int E_(OpenFilter)( vlc_object_t *p_this )
161 {
162     return OpenFilterEx( p_this, VLC_FALSE );
163 }
164
165 /*****************************************************************************
166  * OpenCropPadd: probe the filter and return score
167  *****************************************************************************/
168 int E_(OpenCropPadd)( vlc_object_t *p_this )
169 {
170     return OpenFilterEx( p_this, VLC_TRUE );
171 }
172
173
174 /*****************************************************************************
175  * CloseFilter: clean up the filter
176  *****************************************************************************/
177 void E_(CloseFilter)( vlc_object_t *p_this )
178 {
179     filter_t *p_filter = (filter_t*)p_this;
180     filter_sys_t *p_sys = p_filter->p_sys;
181
182     if( p_sys->p_rsc ) img_resample_close( p_sys->p_rsc );
183     avpicture_free( &p_sys->tmp_pic );
184
185     free( p_sys );
186 }
187
188 /*****************************************************************************
189  * CheckInit: Initialise filter when necessary
190  *****************************************************************************/
191 static int CheckInit( filter_t *p_filter )
192 {
193     filter_sys_t *p_sys = p_filter->p_sys;
194     vlc_bool_t b_change;
195     int i_croptop=0;
196     int i_cropbottom=0;
197     int i_cropleft=0;
198     int i_cropright=0;
199     int i_paddtop=0;
200     int i_paddbottom=0;
201     int i_paddleft=0;
202     int i_paddright=0;
203
204     b_change = ( p_filter->fmt_in.video.i_width != p_sys->fmt_in.video.i_width ) ||
205         ( p_filter->fmt_in.video.i_height != p_sys->fmt_in.video.i_height ) ||
206         ( p_filter->fmt_out.video.i_width != p_sys->fmt_out.video.i_width ) ||
207         ( p_filter->fmt_out.video.i_height != p_sys->fmt_out.video.i_height );
208
209     if ( p_sys->b_enable_croppadd )
210     {
211         b_change = b_change ||
212             ( p_filter->fmt_in.video.i_y_offset != p_sys->fmt_in.video.i_y_offset ) ||
213             ( p_filter->fmt_in.video.i_x_offset != p_sys->fmt_in.video.i_x_offset ) ||
214             ( p_filter->fmt_in.video.i_visible_width != p_sys->fmt_in.video.i_visible_width ) ||
215             ( p_filter->fmt_in.video.i_visible_height != p_sys->fmt_in.video.i_visible_height ) ||
216             ( p_filter->fmt_out.video.i_y_offset != p_sys->fmt_out.video.i_y_offset ) ||
217             ( p_filter->fmt_out.video.i_x_offset != p_sys->fmt_out.video.i_x_offset ) ||
218             ( p_filter->fmt_out.video.i_visible_width != p_sys->fmt_out.video.i_visible_width ) ||
219             ( p_filter->fmt_out.video.i_visible_height != p_sys->fmt_out.video.i_visible_height );
220     }
221
222     if ( b_change )
223     {
224         if( p_sys->p_rsc ) img_resample_close( p_sys->p_rsc );
225
226         p_sys->p_rsc = NULL;
227         p_sys->b_convert =
228           ( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma );
229
230         p_sys->b_resize =
231           ( p_filter->fmt_in.video.i_width != p_filter->fmt_out.video.i_width ) ||
232           ( p_filter->fmt_in.video.i_height != p_filter->fmt_out.video.i_height );
233
234         p_sys->b_resize_first =
235           ( p_filter->fmt_in.video.i_width * p_filter->fmt_in.video.i_height ) >
236           ( p_filter->fmt_out.video.i_width * p_filter->fmt_out.video.i_height );
237
238         if( p_sys->b_resize &&
239             ( p_sys->i_src_ffmpeg_chroma != PIX_FMT_YUV420P ) &&
240             ( p_sys->i_src_ffmpeg_chroma != PIX_FMT_YUVJ420P ) &&
241             ( p_sys->i_dst_ffmpeg_chroma != PIX_FMT_YUV420P ) &&
242             ( p_sys->i_dst_ffmpeg_chroma != PIX_FMT_YUVJ420P ) )
243         {
244             msg_Err( p_filter, "img_resample_init only deals with I420" );
245             return VLC_EGENERIC;
246         }
247         else if( ( p_sys->i_src_ffmpeg_chroma != PIX_FMT_YUV420P ) &&
248                  ( p_sys->i_src_ffmpeg_chroma != PIX_FMT_YUVJ420P ) )
249         {
250             p_sys->b_resize_first = VLC_FALSE;
251         }
252         else if( ( p_sys->i_dst_ffmpeg_chroma != PIX_FMT_YUV420P ) &&
253                  ( p_sys->i_dst_ffmpeg_chroma != PIX_FMT_YUVJ420P ) )
254         {
255             p_sys->b_resize_first = VLC_TRUE;
256         }
257
258         if ( p_sys->b_enable_croppadd )
259         {
260             p_sys->b_resize = p_sys->b_resize ||
261                 ( p_filter->fmt_in.video.i_visible_width != p_filter->fmt_in.video.i_width ) ||
262                 ( p_filter->fmt_in.video.i_visible_height != p_filter->fmt_in.video.i_height ) ||
263                 ( p_filter->fmt_in.video.i_x_offset != 0 ) ||
264                 ( p_filter->fmt_in.video.i_y_offset != 0 ) ||
265                 ( p_filter->fmt_out.video.i_visible_width != p_filter->fmt_out.video.i_width ) ||
266                 ( p_filter->fmt_out.video.i_visible_height != p_filter->fmt_out.video.i_height ) ||
267                 ( p_filter->fmt_out.video.i_x_offset != 0 ) ||
268                 ( p_filter->fmt_out.video.i_y_offset != 0 );
269         }
270
271         if( p_sys->b_resize )
272         {
273             if ( p_sys->b_enable_croppadd )
274             {
275                 i_croptop = p_filter->fmt_in.video.i_y_offset;
276                 i_cropbottom = p_filter->fmt_in.video.i_height
277                                        - p_filter->fmt_in.video.i_visible_height
278                                        - p_filter->fmt_in.video.i_y_offset;
279                 i_cropleft = p_filter->fmt_in.video.i_x_offset;
280                 i_cropright = p_filter->fmt_in.video.i_width
281                                       - p_filter->fmt_in.video.i_visible_width
282                                       - p_filter->fmt_in.video.i_x_offset;
283
284
285                 i_paddtop = p_filter->fmt_out.video.i_y_offset;
286                 i_paddbottom = p_filter->fmt_out.video.i_height
287                                        - p_filter->fmt_out.video.i_visible_height
288                                        - p_filter->fmt_out.video.i_y_offset;
289                 i_paddleft = p_filter->fmt_out.video.i_x_offset;
290                 i_paddright = p_filter->fmt_out.video.i_width
291                                       - p_filter->fmt_out.video.i_visible_width
292                                       - p_filter->fmt_out.video.i_x_offset;
293             }
294
295             p_sys->p_rsc = img_resample_full_init(
296                                p_filter->fmt_out.video.i_width,
297                                p_filter->fmt_out.video.i_height,
298                                p_filter->fmt_in.video.i_width,
299                                p_filter->fmt_in.video.i_height,
300                                i_croptop,i_cropbottom,
301                                i_cropleft,i_cropright,
302                                i_paddtop,i_paddbottom,
303                                i_paddleft,i_paddright );
304
305             if( !p_sys->p_rsc )
306             {
307                 msg_Err( p_filter, "img_resample_init failed" );
308                 return VLC_EGENERIC;
309             }
310
311             msg_Dbg( p_filter, "input: %ix%i -> %ix%i",
312                 p_filter->fmt_out.video.i_width,
313                 p_filter->fmt_out.video.i_height,
314                 p_filter->fmt_in.video.i_width,
315                 p_filter->fmt_in.video.i_height);
316
317         }
318
319         avpicture_free( &p_sys->tmp_pic );
320
321         if( p_sys->b_resize_first )
322         {
323             /* Resizing then conversion */
324             avpicture_alloc( &p_sys->tmp_pic, p_sys->i_src_ffmpeg_chroma,
325                              p_filter->fmt_out.video.i_width,
326                              p_filter->fmt_out.video.i_height );
327         }
328         else
329         {
330             /* Conversion then resizing */
331             avpicture_alloc( &p_sys->tmp_pic, p_sys->i_dst_ffmpeg_chroma,
332                              p_filter->fmt_in.video.i_width,
333                              p_filter->fmt_in.video.i_height );
334         }
335
336         p_sys->fmt_in = p_filter->fmt_in;
337         p_sys->fmt_out = p_filter->fmt_out;
338     }
339
340     return VLC_SUCCESS;
341 }
342
343 /* fill padd code from ffmpeg */
344 static int padcolor[3] = { 16, 128, 128 };
345
346 /* Expects img to be yuv420 */
347 static void fill_pad_region( AVPicture* img, int height, int width,
348         int padtop, int padbottom, int padleft, int padright, int *color )
349 {
350     int i, y, shift;
351     uint8_t *optr;
352
353     for ( i = 0; i < 3; i++ )
354     {
355         shift = ( i == 0 ) ? 0 : 1;
356
357         if ( padtop || padleft )
358         {
359             memset( img->data[i], color[i], ( ( ( img->linesize[i] * padtop ) +
360                             padleft ) >> shift) );
361         }
362
363         if ( padleft || padright )
364         {
365             optr = img->data[i] + ( img->linesize[i] * ( padtop >> shift ) ) +
366                 ( img->linesize[i] - ( padright >> shift ) );
367
368             for ( y = 0; y < ( ( height - ( padtop + padbottom ) ) >> shift ); y++ )
369             {
370                 memset( optr, color[i], ( padleft + padright ) >> shift );
371                 optr += img->linesize[i];
372             }
373         }
374
375         if (padbottom)
376         {
377             optr = img->data[i] + ( img->linesize[i] * ( ( height - padbottom ) >> shift ) );
378             memset( optr, color[i], ( ( img->linesize[i] * padbottom ) >> shift ) );
379         }
380     }
381 }
382
383 /* Workaround, because old libavcodec doesnt know how to padd */
384 static void img_resample_padd( ImgReSampleContext *s, AVPicture *output,
385         const AVPicture *input, int padtop, int padleft )
386 {
387     AVPicture nopadd_pic = *output;
388
389     /* shift out top and left padding for old ffmpeg */
390     nopadd_pic.data[0] += ( nopadd_pic.linesize[0] * padtop + padleft );
391     nopadd_pic.data[1] += ( nopadd_pic.linesize[1] * padtop + padleft ) >> 1;
392     nopadd_pic.data[2] += ( nopadd_pic.linesize[2] * padtop + padleft ) >> 1;
393     img_resample( s, &nopadd_pic, input );
394 }
395
396
397 /*****************************************************************************
398  * Do the processing here
399  *****************************************************************************/
400 static picture_t *Process( filter_t *p_filter, picture_t *p_pic )
401 {
402     filter_sys_t *p_sys = p_filter->p_sys;
403     AVPicture src_pic, dest_pic;
404     AVPicture *p_src, *p_dst;
405     picture_t *p_pic_dst;
406     int i;
407
408     /* Check if format properties changed */
409     if( CheckInit( p_filter ) != VLC_SUCCESS ) return 0;
410
411     /* Request output picture */
412     p_pic_dst = p_filter->pf_vout_buffer_new( p_filter );
413     if( !p_pic_dst )
414     {
415         msg_Warn( p_filter, "can't get output picture" );
416         p_pic->pf_release( p_pic );
417         return NULL;
418     }
419
420     /* Prepare the AVPictures for the conversion */
421     for( i = 0; i < p_pic->i_planes; i++ )
422     {
423         src_pic.data[i] = p_pic->p[i].p_pixels;
424         src_pic.linesize[i] = p_pic->p[i].i_pitch;
425     }
426     for( i = 0; i < p_pic_dst->i_planes; i++ )
427     {
428         dest_pic.data[i] = p_pic_dst->p[i].p_pixels;
429         dest_pic.linesize[i] = p_pic_dst->p[i].i_pitch;
430     }
431
432     /* Special cases */
433     if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','V','1','2') ||
434         p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','V','U','9') )
435     {
436         /* Invert U and V */
437         src_pic.data[1] = p_pic->p[2].p_pixels;
438         src_pic.data[2] = p_pic->p[1].p_pixels;
439     }
440     if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','V','1','2') ||
441         p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','V','U','9') )
442     {
443         /* Invert U and V */
444         dest_pic.data[1] = p_pic_dst->p[2].p_pixels;
445         dest_pic.data[2] = p_pic_dst->p[1].p_pixels;
446     }
447     if( p_sys->i_src_ffmpeg_chroma == PIX_FMT_RGB24 )
448         if( p_filter->fmt_in.video.i_bmask == 0x00ff0000 )
449             p_sys->i_src_ffmpeg_chroma = PIX_FMT_BGR24;
450
451     p_src = &src_pic;
452
453     if( p_sys->b_resize && p_sys->p_rsc )
454     {
455         p_dst = &dest_pic;
456         if( p_sys->b_resize_first )
457         {
458             if( p_sys->b_convert ) p_dst = &p_sys->tmp_pic;
459
460             img_resample( p_sys->p_rsc, p_dst, p_src );
461
462             if (p_sys->b_enable_croppadd)
463             {
464                 if (p_filter->fmt_out.video.i_visible_width != p_filter->fmt_out.video.i_width ||
465                     p_filter->fmt_out.video.i_visible_height != p_filter->fmt_out.video.i_height ||
466                     p_filter->fmt_out.video.i_x_offset != 0 ||
467                     p_filter->fmt_out.video.i_y_offset != 0)
468                 {
469                     fill_pad_region(p_dst, p_filter->fmt_out.video.i_height,
470                                     p_filter->fmt_out.video.i_width,
471                                     p_filter->fmt_out.video.i_y_offset,
472                                     p_filter->fmt_out.video.i_height
473                                       - p_filter->fmt_out.video.i_visible_height
474                                       - p_filter->fmt_out.video.i_y_offset,
475                                     p_filter->fmt_out.video.i_x_offset,
476                                     p_filter->fmt_out.video.i_width
477                                       - p_filter->fmt_out.video.i_visible_width
478                                       - p_filter->fmt_out.video.i_x_offset,
479                                     padcolor);
480                 }
481             }
482
483             p_src = p_dst;
484         }
485     }
486
487     if( p_sys->b_convert )
488     {
489         video_format_t *p_fmt = &p_filter->fmt_out.video;
490         p_dst = &dest_pic;
491         if( p_sys->b_resize && !p_sys->b_resize_first )
492         {
493             p_dst = &p_sys->tmp_pic;
494             p_fmt = &p_filter->fmt_in.video;
495         }
496
497         img_convert( p_dst, p_sys->i_dst_ffmpeg_chroma,
498                      p_src, p_sys->i_src_ffmpeg_chroma,
499                      p_fmt->i_width, p_fmt->i_height );
500
501         p_src = p_dst;
502     }
503
504     if( p_sys->b_resize && !p_sys->b_resize_first && p_sys->p_rsc )
505     {
506         p_dst = &dest_pic;
507
508         img_resample( p_sys->p_rsc, p_dst, p_src );
509
510         if (p_sys->b_enable_croppadd)
511         {
512             if (p_filter->fmt_out.video.i_visible_width != p_filter->fmt_out.video.i_width ||
513                 p_filter->fmt_out.video.i_visible_height != p_filter->fmt_out.video.i_height ||
514                 p_filter->fmt_out.video.i_x_offset != 0 ||
515                 p_filter->fmt_out.video.i_y_offset != 0)
516             {
517                 fill_pad_region(p_dst, p_filter->fmt_out.video.i_height,
518                                 p_filter->fmt_out.video.i_width,
519                                 p_filter->fmt_out.video.i_y_offset,
520                                 p_filter->fmt_out.video.i_height
521                                   - p_filter->fmt_out.video.i_visible_height
522                                   - p_filter->fmt_out.video.i_y_offset,
523                                 p_filter->fmt_out.video.i_x_offset,
524                                 p_filter->fmt_out.video.i_width
525                                   - p_filter->fmt_out.video.i_visible_width
526                                   - p_filter->fmt_out.video.i_x_offset,
527                                 padcolor);
528             }
529         }
530     }
531
532     /* Special case for RV32 -> YUVA */
533     if( !p_sys->b_resize &&
534         p_filter->fmt_in.video.i_chroma == VLC_FOURCC('R','V','3','2') &&
535         p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','U','V','A') )
536     {
537         uint8_t *p_src = p_pic->p[0].p_pixels;
538         int i_src_pitch = p_pic->p[0].i_pitch;
539         uint8_t *p_dst = p_pic_dst->p[3].p_pixels;
540         int i_dst_pitch = p_pic_dst->p[3].i_pitch;
541         uint32_t l,j;
542
543         for( l = 0; l < p_filter->fmt_out.video.i_height; l++ )
544         {
545             for( j = 0; j < p_filter->fmt_out.video.i_width; j++ )
546             {
547               p_dst[j] = p_src[j*4+3];
548             }
549             p_src += i_src_pitch;
550             p_dst += i_dst_pitch;
551         }
552     }
553     else if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','U','V','A') )
554     {
555         /* Special case for YUVA */
556         memset( p_pic_dst->p[3].p_pixels, 0xFF,
557                 p_pic_dst->p[3].i_pitch * p_pic_dst->p[3].i_lines );
558     }
559
560     p_pic_dst->date = p_pic->date;
561     p_pic_dst->b_force = p_pic->b_force;
562     p_pic_dst->i_nb_fields = p_pic->i_nb_fields;
563     p_pic_dst->b_progressive = p_pic->b_progressive;
564     p_pic_dst->b_top_field_first = p_pic->b_top_field_first;
565
566     p_pic->pf_release( p_pic );
567     return p_pic_dst;
568 }
569 #endif /* ( (defined(HAVE_FFMPEG_SWSCALE_H) || defined(HAVE_LIBSWSCALE_TREE)) */