00475b3f0c665490e2b4e38527cb999f9ab1af6a
[vlc.git] / modules / encoder / ffmpeg / video.c
1 /*****************************************************************************
2  * video.c : video encoder using ffmpeg library
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id: video.c,v 1.4 2003/04/27 23:16:35 gbazin Exp $
6  *
7  * Authors: Laurent Aimar
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 #include <vlc/input.h>
30 #include <vlc/decoder.h>
31
32 #include <stdlib.h>
33
34 #include "codecs.h"
35 #include "encoder.h"
36
37 /* ffmpeg header */
38 #ifdef HAVE_FFMPEG_AVCODEC_H
39 #   include <ffmpeg/avcodec.h>
40 #else
41 #   include <avcodec.h>
42 #endif
43
44 int  E_( OpenEncoderVideo ) ( vlc_object_t * );
45 void E_( CloseEncoderVideo )( vlc_object_t * );
46
47 /*****************************************************************************
48  * Local prototypes
49  *****************************************************************************/
50 static int  Init     ( video_encoder_t *p_encoder );
51 static int  Encode   ( video_encoder_t *p_encoder,
52                        picture_t *p_pic, void *p_data, size_t *pi_data );
53 static void End      ( video_encoder_t *p_encoder );
54
55 /*****************************************************************************
56  * Local definitions
57  *****************************************************************************/
58 struct encoder_sys_t
59 {
60     char *psz_codec;
61
62     AVCodecContext  *p_context;
63     AVCodec         *p_codec;
64
65     AVFrame         *p_frame;
66 };
67
68 /*****************************************************************************
69  * OpenEncoderVideo:
70  *****************************************************************************
71  *
72  *****************************************************************************/
73 int E_( OpenEncoderVideo ) ( vlc_object_t *p_this )
74 {
75     video_encoder_t *p_encoder = (video_encoder_t*)p_this;
76
77
78     /* *** check supported codec *** */
79     switch( p_encoder->i_codec )
80     {
81         case VLC_FOURCC( 'm', 'p', '1', 'v' ):
82         case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
83         case VLC_FOURCC( 'm', 'p', '4', 'v' ):
84             break;
85         default:
86             return VLC_EGENERIC;
87     }
88
89     /* *** init library */
90     avcodec_init();
91     avcodec_register_all();
92
93     /* *** fix parameters *** */
94     switch( p_encoder->i_chroma )
95     {
96         /* Planar YUV formats */
97         case VLC_FOURCC('I','4','4','4'):
98         case VLC_FOURCC('I','4','2','2'):
99         case VLC_FOURCC('Y','V','1','2'):
100         case VLC_FOURCC('I','4','2','0'):
101         case VLC_FOURCC('I','Y','U','V'):
102         case VLC_FOURCC('I','4','1','1'):
103         case VLC_FOURCC('I','4','1','0'):
104         /* Packed YUV formats */
105         case VLC_FOURCC('Y','U','Y','2'):
106         case VLC_FOURCC('U','Y','V','Y'):
107         /* Packed RGB formats */
108         case VLC_FOURCC('R','V','3','2'):
109         case VLC_FOURCC('R','V','2','4'):
110         case VLC_FOURCC('R','V','1','6'):
111         case VLC_FOURCC('R','V','1','5'):
112         case VLC_FOURCC('R','G','B','2'):
113             break;
114         default:
115             return VLC_EGENERIC;
116     }
117 #if 0
118     p_encoder->i_width = ( p_encoder->i_width + 15 )&0xfffff8;
119     p_encoder->i_height = ( p_encoder->i_height + 15 )&0xfffff8;
120 #endif
121
122     /* *** set exported functions *** */
123     p_encoder->pf_init = Init;
124     p_encoder->pf_encode = Encode;
125     p_encoder->pf_end = End;
126
127     return VLC_SUCCESS;
128 }
129
130 /*****************************************************************************
131  * CloseEncoderVideo:
132  *****************************************************************************
133  *
134  *****************************************************************************/
135 void E_( CloseEncoderVideo )( vlc_object_t *p_this )
136 {
137     ;
138 }
139
140 /*****************************************************************************
141  * Init:
142  *****************************************************************************
143  *
144  *****************************************************************************/
145 static int  Init     ( video_encoder_t *p_encoder )
146 {
147     encoder_sys_t *p_sys;
148     int           i_codec;
149
150     /* *** allocate memory *** */
151     if( !( p_encoder->p_sys = p_sys = malloc( sizeof( encoder_sys_t ) ) ) )
152     {
153         msg_Err( p_encoder, "out of memory" );
154         return VLC_EGENERIC;
155     }
156     memset( p_sys, 0, sizeof( encoder_sys_t ) );
157
158     /* *** ask for the codec *** */
159     switch( p_encoder->i_codec )
160     {
161         case VLC_FOURCC( 'm', 'p', '1', 'v' ):
162         case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
163             p_encoder->p_sys->psz_codec = "MPEG I";
164             i_codec = CODEC_ID_MPEG1VIDEO;
165             break;
166         case VLC_FOURCC( 'm', 'p', '4', 'v' ):
167             p_encoder->p_sys->psz_codec = "MPEG-4";
168             i_codec = CODEC_ID_MPEG4;
169             break;
170         default:
171             return VLC_EGENERIC;
172     }
173     if( ( p_sys->p_codec = avcodec_find_encoder( i_codec ) ) == NULL )
174     {
175         msg_Err( p_encoder, "cannot find encoder for %s",
176                  p_encoder->p_sys->psz_codec );
177         return VLC_EGENERIC;
178     }
179
180     msg_Dbg( p_encoder, "encoding with %s", p_encoder->p_sys->psz_codec );
181
182 #define p_frame   p_sys->p_frame
183 #define p_context p_sys->p_context
184     /* *** set context properties  *** */
185     p_context = avcodec_alloc_context();
186     p_context->bit_rate = config_GetInt( p_encoder, "encoder-ffmpeg-video-bitrate" ) * 1000;
187     p_context->width = p_encoder->i_width;
188     p_context->height= p_encoder->i_height;
189 #if LIBAVCODEC_BUILD >= 4662
190     p_context->frame_rate = 25 * DEFAULT_FRAME_RATE_BASE;
191 #else
192     p_context->frame_rate = 25 * FRAME_RATE_BASE;
193 #endif
194     p_context->gop_size = config_GetInt( p_encoder, "encoder-ffmpeg-video-max-key-interval" );
195     p_context->qmin = __MAX( __MIN( config_GetInt( p_encoder, "encoder-ffmpeg-video-min-quant" ), 31 ), 1 );
196     p_context->qmax = __MAX( __MIN( config_GetInt( p_encoder, "encoder-ffmpeg-video-max-quant" ), 31 ), 1 );
197
198     if( avcodec_open( p_context, p_encoder->p_sys->p_codec ) < 0 )
199     {
200         msg_Err( p_encoder, "failed to open %s codec",
201                  p_encoder->p_sys->psz_codec );
202         return VLC_EGENERIC;
203     }
204
205     p_frame = avcodec_alloc_frame();
206
207     switch( p_encoder->i_chroma )
208     {
209         /* Planar YUV formats */
210         case VLC_FOURCC('I','4','4','4'):
211             p_frame->pict_type = PIX_FMT_YUV444P;
212             break;
213
214         case VLC_FOURCC('I','4','2','2'):
215             p_frame->pict_type = PIX_FMT_YUV422P;
216             break;
217
218         case VLC_FOURCC('Y','V','1','2'):
219         case VLC_FOURCC('I','4','2','0'):
220         case VLC_FOURCC('I','Y','U','V'):
221             p_frame->pict_type = PIX_FMT_YUV420P;
222             break;
223
224         case VLC_FOURCC('I','4','1','1'):
225             p_frame->pict_type = PIX_FMT_YUV411P;
226             break;
227
228         case VLC_FOURCC('I','4','1','0'):
229             p_frame->pict_type = PIX_FMT_YUV410P;
230             break;
231
232         /* Packed YUV formats */
233
234         case VLC_FOURCC('Y','U','Y','2'):
235         case VLC_FOURCC('U','Y','V','Y'):
236             p_frame->pict_type = PIX_FMT_YUV422;
237             break;
238            
239         /* Packed RGB formats */
240
241         case VLC_FOURCC('R','V','3','2'):
242             p_frame->pict_type = PIX_FMT_RGBA32;
243             break;
244
245         case VLC_FOURCC('R','V','2','4'):
246             p_frame->pict_type = PIX_FMT_RGB24;
247             //p_frame->pict_type = PIX_FMT_BGR24;
248             break;
249
250         case VLC_FOURCC('R','V','1','6'):
251             p_frame->pict_type = PIX_FMT_RGB565;
252             break;
253
254         case VLC_FOURCC('R','V','1','5'):
255             p_frame->pict_type = PIX_FMT_RGB555;
256             break;
257
258         case VLC_FOURCC('R','G','B','2'):
259             p_frame->pict_type = PIX_FMT_GRAY8;
260             break;
261
262         default:
263             return VLC_EGENERIC;
264     }
265
266     return VLC_SUCCESS;
267
268 #undef  p_context
269 #undef  p_frame
270 }
271
272 /*****************************************************************************
273  * Encode:
274  *****************************************************************************
275  *
276  *****************************************************************************/
277 static int Encode( video_encoder_t *p_encoder,
278                    picture_t *p_pic, void *p_data, size_t *pi_data )
279 {
280 #define p_frame   p_encoder->p_sys->p_frame
281 #define p_context p_encoder->p_sys->p_context
282     int i;
283
284     for( i = 0; i < p_pic->i_planes; i++ )
285     {
286         p_frame->linesize[i] = p_pic->p[i].i_pitch;
287         p_frame->data[i]     = p_pic->p[i].p_pixels;
288     }
289     *pi_data = avcodec_encode_video( p_context, p_data, *pi_data, p_frame );
290
291     return VLC_SUCCESS;
292 #undef  p_context
293 #undef  p_frame
294 }
295
296 /*****************************************************************************
297  * End:
298  *****************************************************************************
299  *
300  *****************************************************************************/
301 static void End( video_encoder_t *p_encoder )
302 {
303     avcodec_close( p_encoder->p_sys->p_context );
304     free( p_encoder->p_sys->p_context );
305
306     p_encoder->p_sys->p_context = NULL;
307     p_encoder->p_sys->p_codec = NULL;
308 }
309