68ec6c37bb856b00354eae213c21af935550ae19
[vlc.git] / 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 #include <vlc/vlc.h>
29 #include <vlc_codec.h>
30 #include <vlc_vout.h>
31 #include <vlc_filter.h>
32
33 /* ffmpeg header */
34 #ifdef HAVE_FFMPEG_AVCODEC_H
35 #   include <ffmpeg/avcodec.h>
36 #else
37 #   include <avcodec.h>
38 #endif
39
40 #include "ffmpeg.h"
41
42 #if !defined(HAVE_FFMPEG_SWSCALE_H) && !defined(HAVE_LIBSWSCALE_TREE)
43 void E_(InitLibavcodec) ( vlc_object_t *p_object );
44 static int CheckInit( filter_t *p_filter );
45 static picture_t *Process( filter_t *p_filter, picture_t *p_pic );
46 #endif
47
48 /*****************************************************************************
49  * filter_sys_t : filter descriptor
50  *****************************************************************************/
51 struct filter_sys_t
52 {
53     vlc_bool_t b_resize;
54     vlc_bool_t b_convert;
55     vlc_bool_t b_resize_first;
56     vlc_bool_t b_enable_croppadd;
57
58     es_format_t fmt_in;
59     int i_src_ffmpeg_chroma;
60     es_format_t fmt_out;
61     int i_dst_ffmpeg_chroma;
62
63     AVPicture tmp_pic;
64
65 #if !defined(HAVE_FFMPEG_SWSCALE_H) && !defined(HAVE_LIBSWSCALE_TREE)
66     ImgReSampleContext *p_rsc;
67 #endif
68 };
69
70 #if !defined(HAVE_FFMPEG_SWSCALE_H) && !defined(HAVE_LIBSWSCALE_TREE)
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         free( p_sys );
140         return VLC_EGENERIC;
141     }
142
143     msg_Dbg( p_filter, "input: %ix%i %4.4s -> %ix%i %4.4s",
144              p_filter->fmt_in.video.i_width, p_filter->fmt_in.video.i_height,
145              (char *)&p_filter->fmt_in.video.i_chroma,
146              p_filter->fmt_out.video.i_width, p_filter->fmt_out.video.i_height,
147              (char *)&p_filter->fmt_out.video.i_chroma );
148
149     /* libavcodec needs to be initialized for some chroma conversions */
150     E_(InitLibavcodec)(p_this);
151
152     return VLC_SUCCESS;
153 }
154
155 /*****************************************************************************
156  * OpenFilter: probe the filter and return score
157  *****************************************************************************/
158 int E_(OpenFilter)( vlc_object_t *p_this )
159 {
160     return OpenFilterEx( p_this, VLC_FALSE );
161 }
162
163 /*****************************************************************************
164  * OpenCropPadd: probe the filter and return score
165  *****************************************************************************/
166 int E_(OpenCropPadd)( vlc_object_t *p_this )
167 {
168     return OpenFilterEx( p_this, VLC_TRUE );
169 }
170
171
172 /*****************************************************************************
173  * CloseFilter: clean up the filter
174  *****************************************************************************/
175 void E_(CloseFilter)( vlc_object_t *p_this )
176 {
177     filter_t *p_filter = (filter_t*)p_this;
178     filter_sys_t *p_sys = p_filter->p_sys;
179
180     if( p_sys->p_rsc ) img_resample_close( p_sys->p_rsc );
181     avpicture_free( &p_sys->tmp_pic );
182
183     free( p_sys );
184 }
185
186 /*****************************************************************************
187  * CheckInit: Initialise filter when necessary
188  *****************************************************************************/
189 static int CheckInit( filter_t *p_filter )
190 {
191     filter_sys_t *p_sys = p_filter->p_sys;
192     vlc_bool_t b_change;
193     int i_croptop=0;
194     int i_cropbottom=0;
195     int i_cropleft=0;
196     int i_cropright=0;
197     int i_paddtop=0;
198     int i_paddbottom=0;
199     int i_paddleft=0;
200     int i_paddright=0;
201
202     b_change = ( p_filter->fmt_in.video.i_width != p_sys->fmt_in.video.i_width ) ||
203         ( p_filter->fmt_in.video.i_height != p_sys->fmt_in.video.i_height ) ||
204         ( p_filter->fmt_out.video.i_width != p_sys->fmt_out.video.i_width ) ||
205         ( p_filter->fmt_out.video.i_height != p_sys->fmt_out.video.i_height );
206
207     if ( p_sys->b_enable_croppadd )
208     {
209         b_change = b_change ||
210             ( p_filter->fmt_in.video.i_y_offset != p_sys->fmt_in.video.i_y_offset ) ||
211             ( p_filter->fmt_in.video.i_x_offset != p_sys->fmt_in.video.i_x_offset ) ||
212             ( p_filter->fmt_in.video.i_visible_width != p_sys->fmt_in.video.i_visible_width ) ||
213             ( p_filter->fmt_in.video.i_visible_height != p_sys->fmt_in.video.i_visible_height ) ||
214             ( p_filter->fmt_out.video.i_y_offset != p_sys->fmt_out.video.i_y_offset ) ||
215             ( p_filter->fmt_out.video.i_x_offset != p_sys->fmt_out.video.i_x_offset ) ||
216             ( p_filter->fmt_out.video.i_visible_width != p_sys->fmt_out.video.i_visible_width ) ||
217             ( p_filter->fmt_out.video.i_visible_height != p_sys->fmt_out.video.i_visible_height );
218     }
219
220     if ( b_change )
221     {
222         if( p_sys->p_rsc ) img_resample_close( p_sys->p_rsc );
223
224         p_sys->p_rsc = NULL;
225         p_sys->b_convert =
226           ( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma );
227
228         p_sys->b_resize =
229           ( p_filter->fmt_in.video.i_width != p_filter->fmt_out.video.i_width ) ||
230           ( p_filter->fmt_in.video.i_height != p_filter->fmt_out.video.i_height );
231
232         p_sys->b_resize_first =
233           ( p_filter->fmt_in.video.i_width * p_filter->fmt_in.video.i_height ) >
234           ( p_filter->fmt_out.video.i_width * p_filter->fmt_out.video.i_height );
235
236         if( p_sys->b_resize &&
237             ( p_sys->i_src_ffmpeg_chroma != PIX_FMT_YUV420P ) &&
238             ( p_sys->i_src_ffmpeg_chroma != PIX_FMT_YUVJ420P ) &&
239             ( p_sys->i_dst_ffmpeg_chroma != PIX_FMT_YUV420P ) &&
240             ( p_sys->i_dst_ffmpeg_chroma != PIX_FMT_YUVJ420P ) )
241         {
242             msg_Err( p_filter, "img_resample_init only deals with I420" );
243             return VLC_EGENERIC;
244         }
245         else if( ( p_sys->i_src_ffmpeg_chroma != PIX_FMT_YUV420P ) &&
246                  ( p_sys->i_src_ffmpeg_chroma != PIX_FMT_YUVJ420P ) )
247         {
248             p_sys->b_resize_first = VLC_FALSE;
249         }
250         else if( ( p_sys->i_dst_ffmpeg_chroma != PIX_FMT_YUV420P ) &&
251                  ( p_sys->i_dst_ffmpeg_chroma != PIX_FMT_YUVJ420P ) )
252         {
253             p_sys->b_resize_first = VLC_TRUE;
254         }
255
256         if ( p_sys->b_enable_croppadd )
257         {
258             p_sys->b_resize = p_sys->b_resize ||
259                 ( p_filter->fmt_in.video.i_visible_width != p_filter->fmt_in.video.i_width ) ||
260                 ( p_filter->fmt_in.video.i_visible_height != p_filter->fmt_in.video.i_height ) ||
261                 ( p_filter->fmt_in.video.i_x_offset != 0 ) ||
262                 ( p_filter->fmt_in.video.i_y_offset != 0 ) ||
263                 ( p_filter->fmt_out.video.i_visible_width != p_filter->fmt_out.video.i_width ) ||
264                 ( p_filter->fmt_out.video.i_visible_height != p_filter->fmt_out.video.i_height ) ||
265                 ( p_filter->fmt_out.video.i_x_offset != 0 ) ||
266                 ( p_filter->fmt_out.video.i_y_offset != 0 );
267         }
268
269         if( p_sys->b_resize )
270         {
271             if ( p_sys->b_enable_croppadd )
272             {
273                 i_croptop = p_filter->fmt_in.video.i_y_offset;
274                 i_cropbottom = p_filter->fmt_in.video.i_height
275                                        - p_filter->fmt_in.video.i_visible_height
276                                        - p_filter->fmt_in.video.i_y_offset;
277                 i_cropleft = p_filter->fmt_in.video.i_x_offset;
278                 i_cropright = p_filter->fmt_in.video.i_width
279                                       - p_filter->fmt_in.video.i_visible_width
280                                       - p_filter->fmt_in.video.i_x_offset;
281
282
283                 i_paddtop = p_filter->fmt_out.video.i_y_offset;
284                 i_paddbottom = p_filter->fmt_out.video.i_height
285                                        - p_filter->fmt_out.video.i_visible_height
286                                        - p_filter->fmt_out.video.i_y_offset;
287                 i_paddleft = p_filter->fmt_out.video.i_x_offset;
288                 i_paddright = p_filter->fmt_out.video.i_width
289                                       - p_filter->fmt_out.video.i_visible_width
290                                       - p_filter->fmt_out.video.i_x_offset;
291             }
292
293             p_sys->p_rsc = img_resample_full_init(
294                                p_filter->fmt_out.video.i_width,
295                                p_filter->fmt_out.video.i_height,
296                                p_filter->fmt_in.video.i_width,
297                                p_filter->fmt_in.video.i_height,
298                                i_croptop,i_cropbottom,
299                                i_cropleft,i_cropright,
300                                i_paddtop,i_paddbottom,
301                                i_paddleft,i_paddright );
302
303             if( !p_sys->p_rsc )
304             {
305                 msg_Err( p_filter, "img_resample_init failed" );
306                 return VLC_EGENERIC;
307             }
308
309             msg_Dbg( p_filter, "input: %ix%i -> %ix%i",
310                 p_filter->fmt_out.video.i_width,
311                 p_filter->fmt_out.video.i_height,
312                 p_filter->fmt_in.video.i_width,
313                 p_filter->fmt_in.video.i_height);
314
315         }
316
317         avpicture_free( &p_sys->tmp_pic );
318
319         if( p_sys->b_resize_first )
320         {
321             /* Resizing then conversion */
322             avpicture_alloc( &p_sys->tmp_pic, p_sys->i_src_ffmpeg_chroma,
323                              p_filter->fmt_out.video.i_width,
324                              p_filter->fmt_out.video.i_height );
325         }
326         else
327         {
328             /* Conversion then resizing */
329             avpicture_alloc( &p_sys->tmp_pic, p_sys->i_dst_ffmpeg_chroma,
330                              p_filter->fmt_in.video.i_width,
331                              p_filter->fmt_in.video.i_height );
332         }
333
334         p_sys->fmt_in = p_filter->fmt_in;
335         p_sys->fmt_out = p_filter->fmt_out;
336     }
337
338     return VLC_SUCCESS;
339 }
340
341 /* fill padd code from ffmpeg */
342 static int padcolor[3] = { 16, 128, 128 };
343
344 /* Expects img to be yuv420 */
345 static void fill_pad_region( AVPicture* img, int height, int width,
346         int padtop, int padbottom, int padleft, int padright, int *color )
347 {
348     int i, y, shift;
349     uint8_t *optr;
350
351     for ( i = 0; i < 3; i++ )
352     {
353         shift = ( i == 0 ) ? 0 : 1;
354
355         if ( padtop || padleft )
356         {
357             memset( img->data[i], color[i], ( ( ( img->linesize[i] * padtop ) +
358                             padleft ) >> shift) );
359         }
360
361         if ( padleft || padright )
362         {
363             optr = img->data[i] + ( img->linesize[i] * ( padtop >> shift ) ) +
364                 ( img->linesize[i] - ( padright >> shift ) );
365
366             for ( y = 0; y < ( ( height - ( padtop + padbottom ) ) >> shift ); y++ )
367             {
368                 memset( optr, color[i], ( padleft + padright ) >> shift );
369                 optr += img->linesize[i];
370             }
371         }
372
373         if (padbottom)
374         {
375             optr = img->data[i] + ( img->linesize[i] * ( ( height - padbottom ) >> shift ) );
376             memset( optr, color[i], ( ( img->linesize[i] * padbottom ) >> shift ) );
377         }
378     }
379 }
380
381 /* Workaround, because old libavcodec doesnt know how to padd */
382 static void img_resample_padd( ImgReSampleContext *s, AVPicture *output,
383         const AVPicture *input, int padtop, int padleft )
384 {
385     AVPicture nopadd_pic = *output;
386
387     /* shift out top and left padding for old ffmpeg */
388     nopadd_pic.data[0] += ( nopadd_pic.linesize[0] * padtop + padleft );
389     nopadd_pic.data[1] += ( nopadd_pic.linesize[1] * padtop + padleft ) >> 1;
390     nopadd_pic.data[2] += ( nopadd_pic.linesize[2] * padtop + padleft ) >> 1;
391     img_resample( s, &nopadd_pic, input );
392 }
393
394
395 /*****************************************************************************
396  * Do the processing here
397  *****************************************************************************/
398 static picture_t *Process( filter_t *p_filter, picture_t *p_pic )
399 {
400     filter_sys_t *p_sys = p_filter->p_sys;
401     AVPicture src_pic, dest_pic;
402     AVPicture *p_src, *p_dst;
403     picture_t *p_pic_dst;
404     int i;
405
406     /* Check if format properties changed */
407     if( CheckInit( p_filter ) != VLC_SUCCESS ) return 0;
408
409     /* Request output picture */
410     p_pic_dst = p_filter->pf_vout_buffer_new( p_filter );
411     if( !p_pic_dst )
412     {
413         msg_Warn( p_filter, "can't get output picture" );
414         p_pic->pf_release( p_pic );
415         return NULL;
416     }
417
418     /* Prepare the AVPictures for the conversion */
419     for( i = 0; i < p_pic->i_planes; i++ )
420     {
421         src_pic.data[i] = p_pic->p[i].p_pixels;
422         src_pic.linesize[i] = p_pic->p[i].i_pitch;
423     }
424     for( i = 0; i < p_pic_dst->i_planes; i++ )
425     {
426         dest_pic.data[i] = p_pic_dst->p[i].p_pixels;
427         dest_pic.linesize[i] = p_pic_dst->p[i].i_pitch;
428     }
429
430     /* Special cases */
431     if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','V','1','2') ||
432         p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','V','U','9') )
433     {
434         /* Invert U and V */
435         src_pic.data[1] = p_pic->p[2].p_pixels;
436         src_pic.data[2] = p_pic->p[1].p_pixels;
437     }
438     if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','V','1','2') ||
439         p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','V','U','9') )
440     {
441         /* Invert U and V */
442         dest_pic.data[1] = p_pic_dst->p[2].p_pixels;
443         dest_pic.data[2] = p_pic_dst->p[1].p_pixels;
444     }
445     if( p_sys->i_src_ffmpeg_chroma == PIX_FMT_RGB24 )
446         if( p_filter->fmt_in.video.i_bmask == 0x00ff0000 )
447             p_sys->i_src_ffmpeg_chroma = PIX_FMT_BGR24;
448
449     p_src = &src_pic;
450
451     if( p_sys->b_resize && p_sys->p_rsc )
452     {
453         p_dst = &dest_pic;
454         if( p_sys->b_resize_first )
455         {
456             if( p_sys->b_convert ) p_dst = &p_sys->tmp_pic;
457
458             img_resample( p_sys->p_rsc, p_dst, p_src );
459
460             if (p_sys->b_enable_croppadd)
461             {
462                 if (p_filter->fmt_out.video.i_visible_width != p_filter->fmt_out.video.i_width ||
463                     p_filter->fmt_out.video.i_visible_height != p_filter->fmt_out.video.i_height ||
464                     p_filter->fmt_out.video.i_x_offset != 0 ||
465                     p_filter->fmt_out.video.i_y_offset != 0)
466                 {
467                     fill_pad_region(p_dst, p_filter->fmt_out.video.i_height,
468                                     p_filter->fmt_out.video.i_width,
469                                     p_filter->fmt_out.video.i_y_offset,
470                                     p_filter->fmt_out.video.i_height
471                                       - p_filter->fmt_out.video.i_visible_height
472                                       - p_filter->fmt_out.video.i_y_offset,
473                                     p_filter->fmt_out.video.i_x_offset,
474                                     p_filter->fmt_out.video.i_width
475                                       - p_filter->fmt_out.video.i_visible_width
476                                       - p_filter->fmt_out.video.i_x_offset,
477                                     padcolor);
478                 }
479             }
480
481             p_src = p_dst;
482         }
483     }
484
485     if( p_sys->b_convert )
486     {
487         video_format_t *p_fmt = &p_filter->fmt_out.video;
488         p_dst = &dest_pic;
489         if( p_sys->b_resize && !p_sys->b_resize_first )
490         {
491             p_dst = &p_sys->tmp_pic;
492             p_fmt = &p_filter->fmt_in.video;
493         }
494
495         img_convert( p_dst, p_sys->i_dst_ffmpeg_chroma,
496                      p_src, p_sys->i_src_ffmpeg_chroma,
497                      p_fmt->i_width, p_fmt->i_height );
498
499         p_src = p_dst;
500     }
501
502     if( p_sys->b_resize && !p_sys->b_resize_first && p_sys->p_rsc )
503     {
504         p_dst = &dest_pic;
505
506         img_resample( p_sys->p_rsc, p_dst, p_src );
507
508         if (p_sys->b_enable_croppadd)
509         {
510             if (p_filter->fmt_out.video.i_visible_width != p_filter->fmt_out.video.i_width ||
511                 p_filter->fmt_out.video.i_visible_height != p_filter->fmt_out.video.i_height ||
512                 p_filter->fmt_out.video.i_x_offset != 0 ||
513                 p_filter->fmt_out.video.i_y_offset != 0)
514             {
515                 fill_pad_region(p_dst, p_filter->fmt_out.video.i_height,
516                                 p_filter->fmt_out.video.i_width,
517                                 p_filter->fmt_out.video.i_y_offset,
518                                 p_filter->fmt_out.video.i_height
519                                   - p_filter->fmt_out.video.i_visible_height
520                                   - p_filter->fmt_out.video.i_y_offset,
521                                 p_filter->fmt_out.video.i_x_offset,
522                                 p_filter->fmt_out.video.i_width
523                                   - p_filter->fmt_out.video.i_visible_width
524                                   - p_filter->fmt_out.video.i_x_offset,
525                                 padcolor);
526             }
527         }
528     }
529
530     /* Special case for RV32 -> YUVA */
531     if( !p_sys->b_resize &&
532         p_filter->fmt_in.video.i_chroma == VLC_FOURCC('R','V','3','2') &&
533         p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','U','V','A') )
534     {
535         uint8_t *p_src = p_pic->p[0].p_pixels;
536         int i_src_pitch = p_pic->p[0].i_pitch;
537         uint8_t *p_dst = p_pic_dst->p[3].p_pixels;
538         int i_dst_pitch = p_pic_dst->p[3].i_pitch;
539         uint32_t l,j;
540
541         for( l = 0; l < p_filter->fmt_out.video.i_height; l++ )
542         {
543             for( j = 0; j < p_filter->fmt_out.video.i_width; j++ )
544             {
545               p_dst[j] = p_src[j*4+3];
546             }
547             p_src += i_src_pitch;
548             p_dst += i_dst_pitch;
549         }
550     }
551     else if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','U','V','A') )
552     {
553         /* Special case for YUVA */
554         memset( p_pic_dst->p[3].p_pixels, 0xFF,
555                 p_pic_dst->p[3].i_pitch * p_pic_dst->p[3].i_lines );
556     }
557
558     p_pic_dst->date = p_pic->date;
559     p_pic_dst->b_force = p_pic->b_force;
560     p_pic_dst->i_nb_fields = p_pic->i_nb_fields;
561     p_pic_dst->b_progressive = p_pic->b_progressive;
562     p_pic_dst->b_top_field_first = p_pic->b_top_field_first;
563
564     p_pic->pf_release( p_pic );
565     return p_pic_dst;
566 }
567 #endif /* ( (defined(HAVE_FFMPEG_SWSCALE_H) || defined(HAVE_LIBSWSCALE_TREE)) */