]> git.sesse.net Git - vlc/blob - modules/codec/ffmpeg/audio.c
* all: removed block_t->b_discontinuity,b_frame_* and added i_flags
[vlc] / modules / codec / ffmpeg / audio.c
1 /*****************************************************************************
2  * audio.c: audio decoder using ffmpeg library
3  *****************************************************************************
4  * Copyright (C) 1999-2003 VideoLAN
5  * $Id: audio.c,v 1.28 2004/02/25 17:48:52 fenrir Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Gildas Bazin <gbazin@netcourrier.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <vlc/vlc.h>
29 #include <vlc/decoder.h>
30
31 /* ffmpeg header */
32 #ifdef HAVE_FFMPEG_AVCODEC_H
33 #   include <ffmpeg/avcodec.h>
34 #else
35 #   include <avcodec.h>
36 #endif
37
38 #include "ffmpeg.h"
39
40 static unsigned int pi_channels_maps[6] =
41 {
42     0,
43     AOUT_CHAN_CENTER,   AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
44     AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
45     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
46      | AOUT_CHAN_REARRIGHT,
47     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
48      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
49 };
50
51 /*****************************************************************************
52  * decoder_sys_t : decoder descriptor
53  *****************************************************************************/
54 struct decoder_sys_t
55 {
56     /* Common part between video and audio decoder */
57     int i_cat;
58     int i_codec_id;
59     char *psz_namecodec;
60     AVCodecContext      *p_context;
61     AVCodec             *p_codec;
62
63     /* Temporary buffer for libavcodec */
64     uint8_t *p_output;
65
66     /*
67      * Output properties
68      */
69     audio_sample_format_t aout_format;
70     audio_date_t          end_date;
71 };
72
73 /*****************************************************************************
74  * InitAudioDec: initialize audio decoder
75  *****************************************************************************
76  * The ffmpeg codec will be opened, some memory allocated.
77  *****************************************************************************/
78 int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context,
79                       AVCodec *p_codec, int i_codec_id, char *psz_namecodec )
80 {
81     decoder_sys_t *p_sys;
82     vlc_value_t lockval;
83
84     var_Get( p_dec->p_libvlc, "avcodec", &lockval );
85
86     /* Allocate the memory needed to store the decoder's structure */
87     if( ( p_dec->p_sys = p_sys =
88           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
89     {
90         msg_Err( p_dec, "out of memory" );
91         return VLC_EGENERIC;
92     }
93
94     p_dec->p_sys->p_context = p_context;
95     p_dec->p_sys->p_codec = p_codec;
96     p_dec->p_sys->i_codec_id = i_codec_id;
97     p_dec->p_sys->psz_namecodec = psz_namecodec;
98
99     /* ***** Fill p_context with init values ***** */
100     p_sys->p_context->sample_rate = p_dec->fmt_in.audio.i_rate;
101     p_sys->p_context->channels = p_dec->fmt_in.audio.i_channels;
102     p_sys->p_context->block_align = p_dec->fmt_in.audio.i_blockalign;
103     p_sys->p_context->bit_rate = p_dec->fmt_in.i_bitrate;
104
105     if( ( p_sys->p_context->extradata_size = p_dec->fmt_in.i_extra ) > 0 )
106     {
107         p_sys->p_context->extradata =
108             malloc( p_dec->fmt_in.i_extra + FF_INPUT_BUFFER_PADDING_SIZE );
109         memcpy( p_sys->p_context->extradata,
110                 p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
111         memset( p_sys->p_context->extradata + p_dec->fmt_in.i_extra, 0,
112                 FF_INPUT_BUFFER_PADDING_SIZE );
113     }
114
115     /* ***** Open the codec ***** */
116     vlc_mutex_lock( lockval.p_address );
117     if (avcodec_open( p_sys->p_context, p_sys->p_codec ) < 0)
118     {
119         vlc_mutex_unlock( lockval.p_address );
120         msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
121         return VLC_EGENERIC;
122     }
123     vlc_mutex_unlock( lockval.p_address );
124
125     msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec );
126
127     p_sys->p_output = malloc( 3 * AVCODEC_MAX_AUDIO_FRAME_SIZE );
128
129     aout_DateSet( &p_sys->end_date, 0 );
130
131     /* Set output properties */
132     p_dec->fmt_out.i_cat = AUDIO_ES;
133     p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
134
135     return VLC_SUCCESS;
136 }
137
138 /*****************************************************************************
139  * DecodeAudio: Called to decode one frame
140  *****************************************************************************/
141 aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block )
142 {
143     decoder_sys_t *p_sys = p_dec->p_sys;
144     int i_used, i_output, i_samples;
145     uint8_t *p_samples;
146     aout_buffer_t *p_buffer;
147     block_t *p_block;
148
149     if( !pp_block || !*pp_block ) return NULL;
150
151     p_block = *pp_block;
152
153     if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts )
154     {
155         /* We've just started the stream, wait for the first PTS. */
156         block_Release( p_block );
157         return NULL;
158     }
159
160     if( p_block->i_buffer <= 0 ||
161         ( p_block->i_flags&BLOCK_FLAG_DISCONTINUITY ) )
162     {
163         block_Release( p_block );
164         return NULL;
165     }
166
167     i_used = avcodec_decode_audio( p_sys->p_context,
168                                    (int16_t*)p_sys->p_output, &i_output,
169                                    p_block->p_buffer, p_block->i_buffer );
170
171     if( i_used < 0 )//|| i_output == 0 )
172     {
173         if( i_used < 0 )
174             msg_Warn( p_dec, "cannot decode one frame (%d bytes)",
175                       p_block->i_buffer );
176
177         block_Release( p_block );
178         return NULL;
179     }
180     else if( i_used > p_block->i_buffer )
181     {
182         i_used = p_block->i_buffer;
183     }
184
185     p_block->i_buffer -= i_used;
186     p_block->p_buffer += i_used;
187
188     if( p_sys->p_context->channels <= 0 || p_sys->p_context->channels > 6 )
189     {
190         msg_Warn( p_dec, "invalid channels count %d",
191                   p_sys->p_context->channels );
192         block_Release( p_block );
193         return NULL;
194     }
195
196     if( p_dec->fmt_out.audio.i_rate != p_sys->p_context->sample_rate )
197     {
198         aout_DateInit( &p_sys->end_date, p_sys->p_context->sample_rate );
199         aout_DateSet( &p_sys->end_date, p_block->i_pts );
200     }
201
202     /* **** Set audio output parameters **** */
203     p_dec->fmt_out.audio.i_rate     = p_sys->p_context->sample_rate;
204     p_dec->fmt_out.audio.i_channels = p_sys->p_context->channels;
205     p_dec->fmt_out.audio.i_original_channels =
206         p_dec->fmt_out.audio.i_physical_channels =
207             pi_channels_maps[p_sys->p_context->channels];
208
209     if( p_block->i_pts != 0 &&
210         p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
211     {
212         aout_DateSet( &p_sys->end_date, p_block->i_pts );
213     }
214     p_block->i_pts = 0;
215
216     /* **** Now we can output these samples **** */
217     i_samples = i_output / 2 / p_sys->p_context->channels;
218     p_samples = p_sys->p_output;
219
220     p_buffer = p_dec->pf_aout_buffer_new( p_dec, i_samples );
221     if( !p_buffer )
222     {
223         msg_Err( p_dec, "cannot get aout buffer" );
224         block_Release( p_block );
225         return NULL;
226     }
227
228     p_buffer->start_date = aout_DateGet( &p_sys->end_date );
229     p_buffer->end_date = aout_DateIncrement( &p_sys->end_date, i_samples );
230
231     memcpy( p_buffer->p_buffer, p_samples, p_buffer->i_nb_bytes );
232
233     return p_buffer;
234 }
235
236 /*****************************************************************************
237  * EndAudioDec: audio decoder destruction
238  *****************************************************************************/
239 void E_(EndAudioDec)( decoder_t *p_dec )
240 {
241     decoder_sys_t *p_sys = p_dec->p_sys;
242
243     if( p_sys->p_output ) free( p_sys->p_output );
244 }