]> git.sesse.net Git - vlc/blob - modules/codec/ffmpeg/chroma.c
Split should now be complete (postproc still needs to be fixed).
[vlc] / modules / codec / ffmpeg / chroma.c
1 /*****************************************************************************
2  * chroma.c: chroma conversion using ffmpeg library
3  *****************************************************************************
4  * Copyright (C) 1999-2008 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
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc_common.h>
33 #include <vlc_vout.h>
34 #include <vlc_filter.h>
35
36 /* ffmpeg header */
37 #ifdef HAVE_LIBAVCODEC_AVCODEC_H
38 #   include <libavcodec/avcodec.h>
39 #elif defined(HAVE_FFMPEG_AVCODEC_H)
40 #   include <ffmpeg/avcodec.h>
41 #else
42 #   include <avcodec.h>
43 #endif
44
45 #include "chroma.h"
46
47 static void ChromaConversion( filter_t *, picture_t *, picture_t * );
48 static picture_t *ChromaConversion_Filter( filter_t *, picture_t * );
49
50 /*****************************************************************************
51  * chroma_sys_t: chroma method descriptor
52  *****************************************************************************
53  * This structure is part of the chroma transformation descriptor, it
54  * describes the chroma plugin specific properties.
55  *****************************************************************************/
56 struct filter_sys_t
57 {
58     int i_src_vlc_chroma;
59     int i_src_ffmpeg_chroma;
60     int i_dst_vlc_chroma;
61     int i_dst_ffmpeg_chroma;
62     AVPicture tmp_pic;
63     ImgReSampleContext *p_rsc;
64 };
65
66 /*****************************************************************************
67  * OpenChroma: allocate a chroma function
68  *****************************************************************************
69  * This function allocates and initializes a chroma function
70  *****************************************************************************/
71 int OpenChroma( vlc_object_t *p_this )
72 {
73     filter_t *p_filter = (filter_t *)p_this;
74     int i_ffmpeg_chroma[2], i_vlc_chroma[2], i;
75
76     /*
77      * Check the source chroma first, then the destination chroma
78      */
79     i_vlc_chroma[0] = p_filter->fmt_in.video.i_chroma;
80     i_vlc_chroma[1] = p_filter->fmt_out.video.i_chroma;
81     for( i = 0; i < 2; i++ )
82     {
83         i_ffmpeg_chroma[i] = GetFfmpegChroma( i_vlc_chroma[i] );
84         if( i_ffmpeg_chroma[i] < 0 ) return VLC_EGENERIC;
85     }
86
87     p_filter->pf_video_filter = ChromaConversion_Filter;
88
89     p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
90     if( p_filter->p_sys == NULL )
91     {
92         return VLC_ENOMEM;
93     }
94
95     p_filter->p_sys->i_src_vlc_chroma = p_filter->fmt_in.video.i_chroma;
96     p_filter->p_sys->i_dst_vlc_chroma = p_filter->fmt_out.video.i_chroma;
97     p_filter->p_sys->i_src_ffmpeg_chroma = i_ffmpeg_chroma[0];
98     p_filter->p_sys->i_dst_ffmpeg_chroma = i_ffmpeg_chroma[1];
99
100     if( ( p_filter->fmt_in.video.i_height != p_filter->fmt_out.video.i_height ||
101           p_filter->fmt_in.video.i_width != p_filter->fmt_out.video.i_width ) &&
102         ( p_filter->p_sys->i_dst_vlc_chroma == VLC_FOURCC('I','4','2','0') ||
103           p_filter->p_sys->i_dst_vlc_chroma == VLC_FOURCC('Y','V','1','2') ))
104     {
105         msg_Dbg( p_filter, "preparing to resample picture" );
106         p_filter->p_sys->p_rsc =
107             img_resample_init( p_filter->fmt_out.video.i_width,
108                                p_filter->fmt_out.video.i_height,
109                                p_filter->fmt_in.video.i_width,
110                                p_filter->fmt_in.video.i_height );
111         avpicture_alloc( &p_filter->p_sys->tmp_pic,
112                          p_filter->p_sys->i_dst_ffmpeg_chroma,
113                          p_filter->fmt_in.video.i_width,
114                          p_filter->fmt_in.video.i_height );
115     }
116     else
117     {
118         msg_Dbg( p_filter, "no resampling" );
119         p_filter->p_sys->p_rsc = NULL;
120     }
121
122     return VLC_SUCCESS;
123 }
124
125 VIDEO_FILTER_WRAPPER( ChromaConversion )
126
127 /*****************************************************************************
128  * ChromaConversion: actual chroma conversion function
129  *****************************************************************************/
130 static void ChromaConversion( filter_t *p_filter,
131                               picture_t *p_src, picture_t *p_dest )
132 {
133     AVPicture src_pic;
134     AVPicture dest_pic;
135     int i;
136
137     /* Prepare the AVPictures for converion */
138     for( i = 0; i < p_src->i_planes; i++ )
139     {
140         src_pic.data[i] = p_src->p[i].p_pixels;
141         src_pic.linesize[i] = p_src->p[i].i_pitch;
142     }
143     for( i = 0; i < p_dest->i_planes; i++ )
144     {
145         dest_pic.data[i] = p_dest->p[i].p_pixels;
146         dest_pic.linesize[i] = p_dest->p[i].i_pitch;
147     }
148
149     /* Special cases */
150     if( p_filter->p_sys->i_src_vlc_chroma == VLC_FOURCC('Y','V','1','2') ||
151         p_filter->p_sys->i_src_vlc_chroma == VLC_FOURCC('Y','V','U','9') )
152     {
153         /* Invert U and V */
154         src_pic.data[1] = p_src->p[2].p_pixels;
155         src_pic.data[2] = p_src->p[1].p_pixels;
156     }
157     if( p_filter->p_sys->i_dst_vlc_chroma == VLC_FOURCC('Y','V','1','2') ||
158         p_filter->p_sys->i_dst_vlc_chroma == VLC_FOURCC('Y','V','U','9') )
159     {
160         /* Invert U and V */
161         dest_pic.data[1] = p_dest->p[2].p_pixels;
162         dest_pic.data[2] = p_dest->p[1].p_pixels;
163     }
164     if( p_filter->p_sys->i_src_ffmpeg_chroma == PIX_FMT_RGB24 )
165         if( p_filter->fmt_in.video.i_bmask == 0x00ff0000 )
166             p_filter->p_sys->i_src_ffmpeg_chroma = PIX_FMT_BGR24;
167
168     if( p_filter->p_sys->p_rsc )
169     {
170         img_convert( &p_filter->p_sys->tmp_pic,
171                      p_filter->p_sys->i_dst_ffmpeg_chroma,
172                      &src_pic, p_filter->p_sys->i_src_ffmpeg_chroma,
173                      p_filter->fmt_in.video.i_width,
174                      p_filter->fmt_in.video.i_height );
175         img_resample( p_filter->p_sys->p_rsc, &dest_pic,
176                       &p_filter->p_sys->tmp_pic );
177     }
178     else
179     {
180         img_convert( &dest_pic, p_filter->p_sys->i_dst_ffmpeg_chroma,
181                      &src_pic, p_filter->p_sys->i_src_ffmpeg_chroma,
182                      p_filter->fmt_in.video.i_width,
183                      p_filter->fmt_in.video.i_height );
184     }
185 }
186
187 /*****************************************************************************
188  * CloseChroma: free the chroma function
189  *****************************************************************************
190  * This function frees the previously allocated chroma function
191  *****************************************************************************/
192 void CloseChroma( vlc_object_t *p_this )
193 {
194     filter_t *p_filter = (filter_t *)p_this;
195     if( p_filter->p_sys->p_rsc )
196     {
197         img_resample_close( p_filter->p_sys->p_rsc );
198         avpicture_free( &p_filter->p_sys->tmp_pic );
199     }
200     free( p_filter->p_sys );
201 }