Added HuffYuv and A-law codes for low bitrate and CPU load encodings/transcoding
[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.5 2003/07/28 20:25:30 jpsaman 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         case VLC_FOURCC( 'h', 'u', 'f', 'f' ):
85             break;
86         default:
87             return VLC_EGENERIC;
88     }
89
90     /* *** init library */
91     avcodec_init();
92     avcodec_register_all();
93
94     /* *** fix parameters *** */
95     switch( p_encoder->i_chroma )
96     {
97         /* Planar YUV formats */
98         case VLC_FOURCC('I','4','4','4'):
99         case VLC_FOURCC('I','4','2','2'):
100         case VLC_FOURCC('Y','V','1','2'):
101         case VLC_FOURCC('I','4','2','0'):
102         case VLC_FOURCC('I','Y','U','V'):
103         case VLC_FOURCC('I','4','1','1'):
104         case VLC_FOURCC('I','4','1','0'):
105         /* Packed YUV formats */
106         case VLC_FOURCC('Y','U','Y','2'):
107         case VLC_FOURCC('U','Y','V','Y'):
108         /* Packed RGB formats */
109         case VLC_FOURCC('R','V','3','2'):
110         case VLC_FOURCC('R','V','2','4'):
111         case VLC_FOURCC('R','V','1','6'):
112         case VLC_FOURCC('R','V','1','5'):
113         case VLC_FOURCC('R','G','B','2'):
114             break;
115         default:
116             return VLC_EGENERIC;
117     }
118 #if 0
119     p_encoder->i_width = ( p_encoder->i_width + 15 )&0xfffff8;
120     p_encoder->i_height = ( p_encoder->i_height + 15 )&0xfffff8;
121 #endif
122
123     /* *** set exported functions *** */
124     p_encoder->pf_init = Init;
125     p_encoder->pf_encode = Encode;
126     p_encoder->pf_end = End;
127
128     return VLC_SUCCESS;
129 }
130
131 /*****************************************************************************
132  * CloseEncoderVideo:
133  *****************************************************************************
134  *
135  *****************************************************************************/
136 void E_( CloseEncoderVideo )( vlc_object_t *p_this )
137 {
138     ;
139 }
140
141 /*****************************************************************************
142  * Init:
143  *****************************************************************************
144  *
145  *****************************************************************************/
146 static int  Init     ( video_encoder_t *p_encoder )
147 {
148     encoder_sys_t *p_sys;
149     int           i_codec;
150
151     /* *** allocate memory *** */
152     if( !( p_encoder->p_sys = p_sys = malloc( sizeof( encoder_sys_t ) ) ) )
153     {
154         msg_Err( p_encoder, "out of memory" );
155         return VLC_EGENERIC;
156     }
157     memset( p_sys, 0, sizeof( encoder_sys_t ) );
158
159     /* *** ask for the codec *** */
160     switch( p_encoder->i_codec )
161     {
162         case VLC_FOURCC( 'm', 'p', '1', 'v' ):
163         case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
164             p_encoder->p_sys->psz_codec = "MPEG I";
165             i_codec = CODEC_ID_MPEG1VIDEO;
166             break;
167         case VLC_FOURCC( 'm', 'p', '4', 'v' ):
168             p_encoder->p_sys->psz_codec = "MPEG-4";
169             i_codec = CODEC_ID_MPEG4;
170             break;
171         case VLC_FOURCC( 'h', 'u', 'f', 'f' ):
172             p_encoder->p_sys->psz_codec = "Huff YUV";
173             i_codec = CODEC_ID_HUFFYUV;
174             break;
175         default:
176             return VLC_EGENERIC;
177     }
178     if( ( p_sys->p_codec = avcodec_find_encoder( i_codec ) ) == NULL )
179     {
180         msg_Err( p_encoder, "cannot find encoder for %s",
181                  p_encoder->p_sys->psz_codec );
182         return VLC_EGENERIC;
183     }
184
185     msg_Dbg( p_encoder, "encoding with %s", p_encoder->p_sys->psz_codec );
186
187 #define p_frame   p_sys->p_frame
188 #define p_context p_sys->p_context
189     /* *** set context properties  *** */
190     p_context = avcodec_alloc_context();
191     p_context->bit_rate = config_GetInt( p_encoder, "encoder-ffmpeg-video-bitrate" ) * 1000;
192     p_context->width = p_encoder->i_width;
193     p_context->height= p_encoder->i_height;
194 #if LIBAVCODEC_BUILD >= 4662
195     p_context->frame_rate = 25 * DEFAULT_FRAME_RATE_BASE;
196 #else
197     p_context->frame_rate = 25 * FRAME_RATE_BASE;
198 #endif
199     p_context->gop_size = config_GetInt( p_encoder, "encoder-ffmpeg-video-max-key-interval" );
200     p_context->qmin = __MAX( __MIN( config_GetInt( p_encoder, "encoder-ffmpeg-video-min-quant" ), 31 ), 1 );
201     p_context->qmax = __MAX( __MIN( config_GetInt( p_encoder, "encoder-ffmpeg-video-max-quant" ), 31 ), 1 );
202
203     if( avcodec_open( p_context, p_encoder->p_sys->p_codec ) < 0 )
204     {
205         msg_Err( p_encoder, "failed to open %s codec",
206                  p_encoder->p_sys->psz_codec );
207         return VLC_EGENERIC;
208     }
209
210     p_frame = avcodec_alloc_frame();
211
212     switch( p_encoder->i_chroma )
213     {
214         /* Planar YUV formats */
215         case VLC_FOURCC('I','4','4','4'):
216             p_frame->pict_type = PIX_FMT_YUV444P;
217             break;
218
219         case VLC_FOURCC('I','4','2','2'):
220             p_frame->pict_type = PIX_FMT_YUV422P;
221             break;
222
223         case VLC_FOURCC('Y','V','1','2'):
224         case VLC_FOURCC('I','4','2','0'):
225         case VLC_FOURCC('I','Y','U','V'):
226             p_frame->pict_type = PIX_FMT_YUV420P;
227             break;
228
229         case VLC_FOURCC('I','4','1','1'):
230             p_frame->pict_type = PIX_FMT_YUV411P;
231             break;
232
233         case VLC_FOURCC('I','4','1','0'):
234             p_frame->pict_type = PIX_FMT_YUV410P;
235             break;
236
237         /* Packed YUV formats */
238
239         case VLC_FOURCC('Y','U','Y','2'):
240         case VLC_FOURCC('U','Y','V','Y'):
241             p_frame->pict_type = PIX_FMT_YUV422;
242             break;
243            
244         /* Packed RGB formats */
245
246         case VLC_FOURCC('R','V','3','2'):
247             p_frame->pict_type = PIX_FMT_RGBA32;
248             break;
249
250         case VLC_FOURCC('R','V','2','4'):
251             p_frame->pict_type = PIX_FMT_RGB24;
252             //p_frame->pict_type = PIX_FMT_BGR24;
253             break;
254
255         case VLC_FOURCC('R','V','1','6'):
256             p_frame->pict_type = PIX_FMT_RGB565;
257             break;
258
259         case VLC_FOURCC('R','V','1','5'):
260             p_frame->pict_type = PIX_FMT_RGB555;
261             break;
262
263         case VLC_FOURCC('R','G','B','2'):
264             p_frame->pict_type = PIX_FMT_GRAY8;
265             break;
266
267         default:
268             return VLC_EGENERIC;
269     }
270
271     return VLC_SUCCESS;
272
273 #undef  p_context
274 #undef  p_frame
275 }
276
277 /*****************************************************************************
278  * Encode:
279  *****************************************************************************
280  *
281  *****************************************************************************/
282 static int Encode( video_encoder_t *p_encoder,
283                    picture_t *p_pic, void *p_data, size_t *pi_data )
284 {
285 #define p_frame   p_encoder->p_sys->p_frame
286 #define p_context p_encoder->p_sys->p_context
287     int i;
288
289     for( i = 0; i < p_pic->i_planes; i++ )
290     {
291         p_frame->linesize[i] = p_pic->p[i].i_pitch;
292         p_frame->data[i]     = p_pic->p[i].p_pixels;
293     }
294     *pi_data = avcodec_encode_video( p_context, p_data, *pi_data, p_frame );
295
296     return VLC_SUCCESS;
297 #undef  p_context
298 #undef  p_frame
299 }
300
301 /*****************************************************************************
302  * End:
303  *****************************************************************************
304  *
305  *****************************************************************************/
306 static void End( video_encoder_t *p_encoder )
307 {
308     avcodec_close( p_encoder->p_sys->p_context );
309     free( p_encoder->p_sys->p_context );
310
311     p_encoder->p_sys->p_context = NULL;
312     p_encoder->p_sys->p_codec = NULL;
313 }
314