1 /* $Id: encac3.c,v 1.23 2005/10/13 23:47:06 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.fr/>.
5 It may be used under the terms of the GNU General Public License. */
11 struct hb_work_private_s
14 AVCodecContext * context;
16 int out_discrete_channels;
17 unsigned long input_samples;
18 unsigned long output_bytes;
24 int encac3Init( hb_work_object_t *, hb_job_t * );
25 int encac3Work( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
26 void encac3Close( hb_work_object_t * );
28 #define AC3_SAMPLES_PER_FRAME 1536
29 #define AC3_MAX_CODED_FRAME_SIZE 3840
31 hb_work_object_t hb_encac3 =
34 "AC-3 encoder (libavcodec)",
40 int encac3Init( hb_work_object_t * w, hb_job_t * job )
43 AVCodecContext * context;
44 hb_audio_t * audio = w->audio;
46 hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
51 pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);
52 pv->input_samples = AC3_SAMPLES_PER_FRAME * pv->out_discrete_channels;
53 pv->output_bytes = AC3_MAX_CODED_FRAME_SIZE;
55 pv->buf = malloc( pv->input_samples * sizeof( float ) );
56 pv->samples = malloc( pv->input_samples * sizeof( float ) );
58 codec = avcodec_find_encoder( CODEC_ID_AC3 );
61 hb_log( "encac3Init: avcodec_find_encoder "
64 context = avcodec_alloc_context();
65 avcodec_get_context_defaults3(context, codec);
67 context->channel_layout = CH_LAYOUT_STEREO;
68 switch( audio->config.out.mixdown )
70 case HB_AMIXDOWN_MONO:
71 context->channel_layout = CH_LAYOUT_MONO;
74 case HB_AMIXDOWN_STEREO:
75 case HB_AMIXDOWN_DOLBY:
76 case HB_AMIXDOWN_DOLBYPLII:
77 context->channel_layout = CH_LAYOUT_STEREO;
81 context->channel_layout = CH_LAYOUT_5POINT0|CH_LOW_FREQUENCY;
85 hb_log(" encac3Init: bad mixdown" );
89 context->bit_rate = audio->config.out.bitrate * 1000;
90 context->sample_rate = audio->config.out.samplerate;
91 context->channels = pv->out_discrete_channels;
92 context->sample_fmt = AV_SAMPLE_FMT_FLT;
94 if( hb_avcodec_open( context, codec ) )
96 hb_log( "encac3Init: avcodec_open failed" );
98 pv->context = context;
100 pv->list = hb_list_init();
105 /***********************************************************************
107 ***********************************************************************
109 **********************************************************************/
110 void encac3Close( hb_work_object_t * w )
112 hb_work_private_t * pv = w->private_data;
118 hb_deep_log( 2, "encac3: closing libavcodec" );
119 if ( pv->context->codec )
120 avcodec_flush_buffers( pv->context );
121 hb_avcodec_close( pv->context );
137 hb_list_empty( &pv->list );
140 w->private_data = NULL;
144 static hb_buffer_t * Encode( hb_work_object_t * w )
146 hb_work_private_t * pv = w->private_data;
148 hb_audio_t * audio = w->audio;
152 if( hb_list_bytes( pv->list ) < pv->input_samples * sizeof( float ) )
157 hb_list_getbytes( pv->list, pv->buf, pv->input_samples * sizeof( float ),
160 hb_chan_map_t *map = NULL;
161 if ( audio->config.in.codec == HB_ACODEC_AC3 )
163 map = &hb_ac3_chan_map;
165 else if ( audio->config.in.codec == HB_ACODEC_DCA )
167 map = &hb_qt_chan_map;
172 switch (audio->config.out.mixdown)
174 case HB_AMIXDOWN_MONO:
175 layout = HB_INPUT_CH_LAYOUT_MONO;
177 case HB_AMIXDOWN_STEREO:
178 case HB_AMIXDOWN_DOLBY:
179 case HB_AMIXDOWN_DOLBYPLII:
180 layout = HB_INPUT_CH_LAYOUT_STEREO;
182 case HB_AMIXDOWN_6CH:
184 layout = HB_INPUT_CH_LAYOUT_3F2R | HB_INPUT_CH_LAYOUT_HAS_LFE;
187 hb_layout_remap( map, &hb_smpte_chan_map, layout,
188 (float*)pv->buf, AC3_SAMPLES_PER_FRAME);
191 for (ii = 0; ii < pv->input_samples; ii++)
193 // ffmpeg float samples are -1.0 to 1.0
194 pv->samples[ii] = ((float*)pv->buf)[ii] / 32768.0;
197 buf = hb_buffer_init( pv->output_bytes );
198 buf->size = avcodec_encode_audio( pv->context, buf->data, buf->alloc,
199 (short*)pv->samples );
201 buf->start = pts + 90000 * pos / pv->out_discrete_channels / sizeof( float ) / audio->config.out.samplerate;
202 buf->stop = buf->start + 90000 * AC3_SAMPLES_PER_FRAME / audio->config.out.samplerate;
204 buf->frametype = HB_FRAME_AUDIO;
208 hb_buffer_close( &buf );
211 else if (buf->size < 0)
213 hb_log( "encac3: avcodec_encode_audio failed" );
214 hb_buffer_close( &buf );
221 /***********************************************************************
223 ***********************************************************************
225 **********************************************************************/
226 int encac3Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
227 hb_buffer_t ** buf_out )
229 hb_work_private_t * pv = w->private_data;
230 hb_buffer_t * in = *buf_in, * buf;
234 /* EOF on input - send it downstream & say we're done */
240 if ( pv->context == NULL || pv->context->codec == NULL )
242 // No encoder context. Nothing we can do.
246 hb_list_add( pv->list, in );
249 *buf_out = buf = Encode( w );
253 buf->next = Encode( w );