6356ca2485507c8181f9568a24a871996ee0366f
[vlc.git] / modules / video_filter / swscale_maemo.c
1 /*****************************************************************************
2  * swscale_maemo.c: scaling and chroma conversion using libswscale_nokia770
3  *****************************************************************************
4  * Copyright (C) 1999-2008 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Antoine Lejeune <phytos@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 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_filter.h>
34
35 #include "libswscale_nokia770/arm_jit_swscale.h"
36 #include "libswscale_nokia770/arm_colorconv.h"
37
38 /****************************************************************************
39  * Local prototypes
40  ****************************************************************************/
41 static int  OpenScaler( vlc_object_t * );
42 static void CloseScaler( vlc_object_t * );
43
44 static picture_t *Filter( filter_t *, picture_t * );
45 static int Init( filter_t * );
46
47 /*****************************************************************************
48  * Module descriptor
49  *****************************************************************************/
50 vlc_module_begin();
51     set_description( N_("Video scaling filter") );
52     set_capability( "video filter2", 1000 );
53     set_category( CAT_VIDEO );
54     set_subcategory( SUBCAT_VIDEO_VFILTER );
55     set_callbacks( OpenScaler, CloseScaler );
56 vlc_module_end();
57
58 /*****************************************************************************
59  * filter_sys_t : filter descriptor
60  *****************************************************************************/
61 struct filter_sys_t
62 {
63     struct SwsContextArmJit *ctx;
64
65     es_format_t fmt_in;
66     es_format_t fmt_out;
67 };
68
69 /*****************************************************************************
70  * OpenScaler: probe the filter and return score
71  *****************************************************************************/
72 static int OpenScaler( vlc_object_t *p_this )
73 {
74     filter_t *p_filter = (filter_t*)p_this;
75     filter_sys_t *p_sys;
76
77     /* Allocate the memory needed to store the decoder's structure */
78     if( ( p_filter->p_sys = p_sys =
79           (filter_sys_t *)malloc(sizeof(filter_sys_t)) ) == NULL )
80     {
81         return VLC_ENOMEM;
82     }
83
84     /* Misc init */
85     p_sys->ctx = NULL;
86     p_filter->pf_video_filter = Filter;
87     es_format_Init( &p_sys->fmt_in, 0, 0 );
88     es_format_Init( &p_sys->fmt_out, 0, 0 );
89
90     if( Init( p_filter ) )
91     {
92         free( p_sys );
93         return VLC_EGENERIC;
94     }
95
96     msg_Dbg( p_filter, "%ix%i chroma: %4.4s -> %ix%i chroma: %4.4s",
97              p_filter->fmt_in.video.i_width, p_filter->fmt_in.video.i_height,
98              (char *)&p_filter->fmt_in.video.i_chroma,
99              p_filter->fmt_out.video.i_width, p_filter->fmt_out.video.i_height,
100              (char *)&p_filter->fmt_out.video.i_chroma );
101
102     return VLC_SUCCESS;
103 }
104
105 /*****************************************************************************
106  * CloseFilter: clean up the filter
107  *****************************************************************************/
108 static void CloseScaler( vlc_object_t *p_this )
109 {
110     filter_t *p_filter = (filter_t*)p_this;
111     filter_sys_t *p_sys = p_filter->p_sys;
112
113     if( p_sys->ctx )
114         sws_arm_jit_free( p_sys->ctx );
115     free( p_sys );
116 }
117
118 /*****************************************************************************
119  * Helpers
120  *****************************************************************************/
121
122 static bool IsFmtSimilar( const video_format_t *p_fmt1, const video_format_t *p_fmt2 )
123 {
124     return p_fmt1->i_chroma == p_fmt2->i_chroma &&
125            p_fmt1->i_width  == p_fmt2->i_width &&
126            p_fmt1->i_height == p_fmt2->i_height;
127 }
128
129 static int Init( filter_t *p_filter )
130 {
131     filter_sys_t *p_sys = p_filter->p_sys;
132
133     if( IsFmtSimilar( &p_filter->fmt_in.video, &p_sys->fmt_in ) &&
134         IsFmtSimilar( &p_filter->fmt_out.video, &p_sys->fmt_out ) &&
135         p_sys->ctx )
136     {
137         return VLC_SUCCESS;
138     }
139
140     if( ( p_filter->fmt_in.video.i_chroma != VLC_CODEC_I420 &&
141           p_filter->fmt_in.video.i_chroma != VLC_CODEC_YV12 ) ||
142           p_filter->fmt_out.video.i_chroma != VLC_FOURCC('Y','4','2','0') )
143     {
144         msg_Err( p_filter, "format not supported" );
145         return VLC_EGENERIC;
146     }
147
148     if( p_sys->ctx )
149         sws_arm_jit_free( p_sys->ctx );
150
151     p_sys->ctx =
152         sws_arm_jit_create_omapfb_yuv420_scaler_armv6(
153             p_filter->fmt_in.video.i_width,
154             p_filter->fmt_in.video.i_height,
155             p_filter->fmt_out.video.i_width,
156             p_filter->fmt_out.video.i_height, 2 );
157
158     if( !p_sys->ctx )
159     {
160         msg_Err( p_filter, "could not init SwScaler" );
161         return VLC_EGENERIC;
162     }
163
164     p_sys->fmt_in = p_filter->fmt_in;
165     p_sys->fmt_out = p_filter->fmt_out;
166
167     return VLC_SUCCESS;
168 }
169
170 /****************************************************************************
171  * Filter: the whole thing
172  ****************************************************************************
173  * This function is called just after the thread is launched.
174  ****************************************************************************/
175 static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
176 {
177     filter_sys_t *p_sys = p_filter->p_sys;
178     uint8_t *src[3]; int src_stride[3];
179     uint8_t *dst[3]; int dst_stride[3];
180     picture_t *p_pic_dst;
181     int i_plane;
182     int i_nb_planes = p_pic->i_planes;
183
184     /* Check if format properties changed */
185     if( Init( p_filter ) != VLC_SUCCESS )
186         return NULL;
187
188     /* Request output picture */
189     p_pic_dst = filter_NewPicture( p_filter );
190     if( !p_pic_dst )
191     {
192         msg_Warn( p_filter, "can't get output picture" );
193         return NULL;
194     }
195
196     for( i_plane = 0; i_plane < __MIN(3, p_pic->i_planes); i_plane++ )
197     {
198         src[i_plane] = p_pic->p[i_plane].p_pixels;
199         src_stride[i_plane] = p_pic->p[i_plane].i_pitch;
200     }
201     for( i_plane = 0; i_plane < __MIN(3, i_nb_planes); i_plane++ )
202     {
203         dst[i_plane] = p_pic_dst->p[i_plane].p_pixels;
204         dst_stride[i_plane] = p_pic_dst->p[i_plane].i_pitch;
205     }
206
207     sws_arm_jit_scale( p_sys->ctx, src, src_stride, 0,
208                        p_filter->fmt_in.video.i_height, dst, dst_stride);
209
210     picture_CopyProperties( p_pic_dst, p_pic );
211     picture_Release( p_pic );
212
213     return p_pic_dst;
214 }