* include/video_output.h, ALL: changed api for vout_Request()/vout_Create() to be...
[vlc.git] / modules / codec / ffmpeg / chroma.c
1 /*****************************************************************************
2  * chroma.c: chroma conversion using ffmpeg library
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
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., 59 Temple Place - Suite 330, Boston, MA  02111, 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 void E_(InitLibavcodec) ( vlc_object_t *p_object );
40 static void ChromaConversion( vout_thread_t *, picture_t *, picture_t * );
41
42 /*****************************************************************************
43  * chroma_sys_t: chroma method descriptor
44  *****************************************************************************
45  * This structure is part of the chroma transformation descriptor, it
46  * describes the chroma plugin specific properties.
47  *****************************************************************************/
48 struct chroma_sys_t
49 {
50     int i_src_vlc_chroma;
51     int i_src_ffmpeg_chroma;
52     int i_dst_vlc_chroma;
53     int i_dst_ffmpeg_chroma;
54     AVPicture tmp_pic;
55     ImgReSampleContext *p_rsc;
56 };
57
58 /*****************************************************************************
59  * OpenChroma: allocate a chroma function
60  *****************************************************************************
61  * This function allocates and initializes a chroma function
62  *****************************************************************************/
63 int E_(OpenChroma)( vlc_object_t *p_this )
64 {
65     vout_thread_t *p_vout = (vout_thread_t *)p_this;
66     int i_ffmpeg_chroma[2], i_vlc_chroma[2], i;
67
68     /*
69      * Check the source chroma first, then the destination chroma
70      */
71     i_vlc_chroma[0] = p_vout->render.i_chroma;
72     i_vlc_chroma[1] = p_vout->output.i_chroma;
73     for( i = 0; i < 2; i++ )
74     {
75         i_ffmpeg_chroma[i] = E_(GetFfmpegChroma)( i_vlc_chroma[i] );
76         if( i_ffmpeg_chroma[i] < 0 ) return VLC_EGENERIC;
77     }
78
79     p_vout->chroma.pf_convert = ChromaConversion;
80
81     p_vout->chroma.p_sys = malloc( sizeof( chroma_sys_t ) );
82     if( p_vout->chroma.p_sys == NULL )
83     {
84         return VLC_EGENERIC;
85     }
86
87     p_vout->chroma.p_sys->i_src_vlc_chroma = p_vout->render.i_chroma;
88     p_vout->chroma.p_sys->i_dst_vlc_chroma = p_vout->output.i_chroma;
89     p_vout->chroma.p_sys->i_src_ffmpeg_chroma = i_ffmpeg_chroma[0];
90     p_vout->chroma.p_sys->i_dst_ffmpeg_chroma = i_ffmpeg_chroma[1];
91
92     if( ( p_vout->render.i_height != p_vout->output.i_height ||
93           p_vout->render.i_width != p_vout->output.i_width ) &&
94         ( p_vout->chroma.p_sys->i_dst_vlc_chroma == VLC_FOURCC('I','4','2','0')  ||
95           p_vout->chroma.p_sys->i_dst_vlc_chroma == VLC_FOURCC('Y','V','1','2') ))
96         
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 }