Remove excess whiteline.
[vlc.git] / modules / codec / ffmpeg / chroma.c
1 /*****************************************************************************
2  * chroma.c: chroma conversion using ffmpeg library
3  *****************************************************************************
4  * Copyright (C) 1999-2001 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <vlc/vlc.h>
28 #include <vlc_vout.h>
29
30 /* ffmpeg header */
31 #ifdef HAVE_FFMPEG_AVCODEC_H
32 #   include <ffmpeg/avcodec.h>
33 #else
34 #   include <avcodec.h>
35 #endif
36
37 #include "ffmpeg.h"
38
39 #if !defined(HAVE_FFMPEG_SWSCALE_H) && !defined(HAVE_LIBSWSCALE_TREE)
40 void E_(InitLibavcodec) ( vlc_object_t *p_object );
41 static void ChromaConversion( vout_thread_t *, picture_t *, picture_t * );
42
43 /*****************************************************************************
44  * chroma_sys_t: chroma method descriptor
45  *****************************************************************************
46  * This structure is part of the chroma transformation descriptor, it
47  * describes the chroma plugin specific properties.
48  *****************************************************************************/
49 struct chroma_sys_t
50 {
51     int i_src_vlc_chroma;
52     int i_src_ffmpeg_chroma;
53     int i_dst_vlc_chroma;
54     int i_dst_ffmpeg_chroma;
55     AVPicture tmp_pic;
56     ImgReSampleContext *p_rsc;
57 };
58
59 /*****************************************************************************
60  * OpenChroma: allocate a chroma function
61  *****************************************************************************
62  * This function allocates and initializes a chroma function
63  *****************************************************************************/
64 int E_(OpenChroma)( vlc_object_t *p_this )
65 {
66     vout_thread_t *p_vout = (vout_thread_t *)p_this;
67     int i_ffmpeg_chroma[2], i_vlc_chroma[2], i;
68
69     /*
70      * Check the source chroma first, then the destination chroma
71      */
72     i_vlc_chroma[0] = p_vout->render.i_chroma;
73     i_vlc_chroma[1] = p_vout->output.i_chroma;
74     for( i = 0; i < 2; i++ )
75     {
76         i_ffmpeg_chroma[i] = E_(GetFfmpegChroma)( i_vlc_chroma[i] );
77         if( i_ffmpeg_chroma[i] < 0 ) return VLC_EGENERIC;
78     }
79
80     p_vout->chroma.pf_convert = ChromaConversion;
81
82     p_vout->chroma.p_sys = malloc( sizeof( chroma_sys_t ) );
83     if( p_vout->chroma.p_sys == NULL )
84     {
85         return VLC_ENOMEM;
86     }
87
88     p_vout->chroma.p_sys->i_src_vlc_chroma = p_vout->render.i_chroma;
89     p_vout->chroma.p_sys->i_dst_vlc_chroma = p_vout->output.i_chroma;
90     p_vout->chroma.p_sys->i_src_ffmpeg_chroma = i_ffmpeg_chroma[0];
91     p_vout->chroma.p_sys->i_dst_ffmpeg_chroma = i_ffmpeg_chroma[1];
92
93     if( ( p_vout->render.i_height != p_vout->output.i_height ||
94           p_vout->render.i_width != p_vout->output.i_width ) &&
95         ( p_vout->chroma.p_sys->i_dst_vlc_chroma == VLC_FOURCC('I','4','2','0')  ||
96           p_vout->chroma.p_sys->i_dst_vlc_chroma == VLC_FOURCC('Y','V','1','2') ))
97     {
98         msg_Dbg( p_vout, "preparing to resample picture" );
99         p_vout->chroma.p_sys->p_rsc =
100             img_resample_init( p_vout->output.i_width, p_vout->output.i_height,
101                                p_vout->render.i_width, p_vout->render.i_height );
102         avpicture_alloc( &p_vout->chroma.p_sys->tmp_pic,
103                          p_vout->chroma.p_sys->i_dst_ffmpeg_chroma,
104                          p_vout->render.i_width, p_vout->render.i_height );
105     }
106     else
107     {
108         msg_Dbg( p_vout, "no resampling" );
109         p_vout->chroma.p_sys->p_rsc = NULL;
110     }
111
112     /* libavcodec needs to be initialized for some chroma conversions */
113     E_(InitLibavcodec)(p_this);
114
115     return VLC_SUCCESS;
116 }
117
118 /*****************************************************************************
119  * ChromaConversion: actual chroma conversion function
120  *****************************************************************************/
121 static void ChromaConversion( vout_thread_t *p_vout,
122                               picture_t *p_src, picture_t *p_dest )
123 {
124     AVPicture src_pic;
125     AVPicture dest_pic;
126     int i;
127
128     /* Prepare the AVPictures for converion */
129     for( i = 0; i < p_src->i_planes; i++ )
130     {
131         src_pic.data[i] = p_src->p[i].p_pixels;
132         src_pic.linesize[i] = p_src->p[i].i_pitch;
133     }
134     for( i = 0; i < p_dest->i_planes; i++ )
135     {
136         dest_pic.data[i] = p_dest->p[i].p_pixels;
137         dest_pic.linesize[i] = p_dest->p[i].i_pitch;
138     }
139
140     /* Special cases */
141     if( p_vout->chroma.p_sys->i_src_vlc_chroma == VLC_FOURCC('Y','V','1','2') ||
142         p_vout->chroma.p_sys->i_src_vlc_chroma == VLC_FOURCC('Y','V','U','9') )
143     {
144         /* Invert U and V */
145         src_pic.data[1] = p_src->p[2].p_pixels;
146         src_pic.data[2] = p_src->p[1].p_pixels;
147     }
148     if( p_vout->chroma.p_sys->i_dst_vlc_chroma == VLC_FOURCC('Y','V','1','2') ||
149         p_vout->chroma.p_sys->i_dst_vlc_chroma == VLC_FOURCC('Y','V','U','9') )
150     {
151         /* Invert U and V */
152         dest_pic.data[1] = p_dest->p[2].p_pixels;
153         dest_pic.data[2] = p_dest->p[1].p_pixels;
154     }
155     if( p_vout->chroma.p_sys->i_src_ffmpeg_chroma == PIX_FMT_RGB24 )
156         if( p_vout->render.i_bmask == 0x00ff0000 )
157             p_vout->chroma.p_sys->i_src_ffmpeg_chroma = PIX_FMT_BGR24;
158
159     if( p_vout->chroma.p_sys->p_rsc )
160     {
161         img_convert( &p_vout->chroma.p_sys->tmp_pic,
162                      p_vout->chroma.p_sys->i_dst_ffmpeg_chroma,
163                      &src_pic, p_vout->chroma.p_sys->i_src_ffmpeg_chroma,
164                      p_vout->render.i_width, p_vout->render.i_height );
165         img_resample( p_vout->chroma.p_sys->p_rsc, &dest_pic,
166                       &p_vout->chroma.p_sys->tmp_pic );
167     }
168     else
169     {
170         img_convert( &dest_pic, p_vout->chroma.p_sys->i_dst_ffmpeg_chroma,
171                      &src_pic, p_vout->chroma.p_sys->i_src_ffmpeg_chroma,
172                      p_vout->render.i_width, p_vout->render.i_height );
173     }
174 }
175
176 /*****************************************************************************
177  * CloseChroma: free the chroma function
178  *****************************************************************************
179  * This function frees the previously allocated chroma function
180  *****************************************************************************/
181 void E_(CloseChroma)( vlc_object_t *p_this )
182 {
183     vout_thread_t *p_vout = (vout_thread_t *)p_this;
184     if( p_vout->chroma.p_sys->p_rsc )
185     {
186         img_resample_close( p_vout->chroma.p_sys->p_rsc );
187         avpicture_free( &p_vout->chroma.p_sys->tmp_pic );
188     }
189     free( p_vout->chroma.p_sys );
190 }
191 #endif /* !defined(HAVE_FFMPEG_SWSCALE_H) && !defined(HAVE_LIBSWSCALE_TREE) */