18a4795fa522d6e3ac10b33142f164ccf45783bf
[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.3 2003/04/26 14:54:49 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     /* FIXME be clever, some codec support additional chroma */
95     if( p_encoder->i_chroma != VLC_FOURCC( 'I', '4', '2', '0' ) )
96     switch( p_encoder->i_chroma )
97     {
98         case VLC_FOURCC( 'I', '4', '2', '0' ):
99         case VLC_FOURCC( 'I', '4', '2', '2' ):
100         case VLC_FOURCC( 'Y', 'U', 'Y', '2' ):
101             break;
102         default:
103             p_encoder->i_chroma = VLC_FOURCC( 'I', '4', '2', '0' );
104             return VLC_EGENERIC;
105     }
106 #if 0
107     p_encoder->i_width = ( p_encoder->i_width + 15 )&0xfffff8;
108     p_encoder->i_height = ( p_encoder->i_height + 15 )&0xfffff8;
109 #endif
110
111     /* *** set exported functions *** */
112     p_encoder->pf_init = Init;
113     p_encoder->pf_encode = Encode;
114     p_encoder->pf_end = End;
115
116     return VLC_SUCCESS;
117 }
118
119 /*****************************************************************************
120  * CloseEncoderVideo:
121  *****************************************************************************
122  *
123  *****************************************************************************/
124 void E_( CloseEncoderVideo )( vlc_object_t *p_this )
125 {
126     ;
127 }
128
129 /*****************************************************************************
130  * Init:
131  *****************************************************************************
132  *
133  *****************************************************************************/
134 static int  Init     ( video_encoder_t *p_encoder )
135 {
136     encoder_sys_t *p_sys;
137     int           i_codec;
138
139     /* *** allocate memory *** */
140     if( !( p_encoder->p_sys = p_sys = malloc( sizeof( encoder_sys_t ) ) ) )
141     {
142         msg_Err( p_encoder, "out of memory" );
143         return VLC_EGENERIC;
144     }
145     memset( p_sys, 0, sizeof( encoder_sys_t ) );
146
147     /* *** ask for the codec *** */
148     switch( p_encoder->i_codec )
149     {
150         case VLC_FOURCC( 'm', 'p', '1', 'v' ):
151         case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
152             p_encoder->p_sys->psz_codec = "MPEG I";
153             i_codec = CODEC_ID_MPEG1VIDEO;
154             break;
155         case VLC_FOURCC( 'm', 'p', '4', 'v' ):
156             p_encoder->p_sys->psz_codec = "MPEG-4";
157             i_codec = CODEC_ID_MPEG4;
158             break;
159         default:
160             return VLC_EGENERIC;
161     }
162     if( ( p_sys->p_codec = avcodec_find_encoder( i_codec ) ) == NULL )
163     {
164         msg_Err( p_encoder, "cannot find encoder for %s", p_encoder->p_sys->psz_codec );
165         return VLC_EGENERIC;
166     }
167
168     msg_Dbg( p_encoder, "encoding with %s", p_encoder->p_sys->psz_codec );
169
170 #define p_frame   p_sys->p_frame
171 #define p_context p_sys->p_context
172     /* *** set context properties  *** */
173     p_context = avcodec_alloc_context();
174     p_context->bit_rate = config_GetInt( p_encoder, "encoder-ffmpeg-video-bitrate" ) * 1000;
175     p_context->width = p_encoder->i_width;
176     p_context->height= p_encoder->i_height;
177 #if LIBAVCODEC_BUILD >= 4662
178     p_context->frame_rate = 25 * DEFAULT_FRAME_RATE_BASE;
179 #else
180     p_context->frame_rate = 25 * FRAME_RATE_BASE;
181 #endif
182     p_context->gop_size = config_GetInt( p_encoder, "encoder-ffmpeg-video-max-key-interval" );
183     p_context->qmin = __MAX( __MIN( config_GetInt( p_encoder, "encoder-ffmpeg-video-min-quant" ), 31 ), 1 );
184     p_context->qmax = __MAX( __MIN( config_GetInt( p_encoder, "encoder-ffmpeg-video-max-quant" ), 31 ), 1 );
185
186     if( avcodec_open( p_context, p_encoder->p_sys->p_codec ) < 0 )
187     {
188         msg_Err( p_encoder, "failed to open %s codec", p_encoder->p_sys->psz_codec );
189         return VLC_EGENERIC;
190     }
191
192     p_frame = avcodec_alloc_frame();
193
194     switch( p_encoder->i_chroma )
195     {
196         case VLC_FOURCC( 'I', '4', '2', '0' ):
197             p_frame->pict_type = PIX_FMT_YUV420P;
198             break;
199         case VLC_FOURCC( 'I', '4', '2', '2' ):
200             p_frame->pict_type = PIX_FMT_YUV422P;
201             break;
202         case VLC_FOURCC( 'Y', 'U', 'Y', '2' ):
203             p_frame->pict_type = PIX_FMT_YUV422;
204             break;
205         default:
206             return VLC_EGENERIC;
207     }
208
209     return VLC_SUCCESS;
210
211 #undef  p_context
212 #undef  p_frame
213 }
214
215 /*****************************************************************************
216  * Encode:
217  *****************************************************************************
218  *
219  *****************************************************************************/
220 static int  Encode   ( video_encoder_t *p_encoder,
221                        picture_t *p_pic, void *p_data, size_t *pi_data )
222 {
223 #define p_frame   p_encoder->p_sys->p_frame
224 #define p_context p_encoder->p_sys->p_context
225     int i;
226
227     for( i = 0; i < 3; i++ )
228     {
229         p_frame->linesize[i] = p_pic->p[i].i_pitch;
230         p_frame->data[i]     = p_pic->p[i].p_pixels;
231     }
232     *pi_data = avcodec_encode_video( p_context, p_data, *pi_data, p_frame );
233
234     return VLC_SUCCESS;
235 #undef  p_context
236 #undef  p_frame
237 }
238
239 /*****************************************************************************
240  * End:
241  *****************************************************************************
242  *
243  *****************************************************************************/
244 static void End      ( video_encoder_t *p_encoder )
245 {
246     avcodec_close( p_encoder->p_sys->p_context );
247     free( p_encoder->p_sys->p_context );
248
249     p_encoder->p_sys->p_context = NULL;
250     p_encoder->p_sys->p_codec = NULL;
251 }
252