OSDN Git Service

CLI: Add support for naming audio tracks to the HandBrakeCLI, thanks to LePetomane...
[handbrake-jp/handbrake-jp-git.git] / libhb / encfaac.c
1 /* $Id: encfaac.c,v 1.13 2005/03/03 17:21:57 titer Exp $
2
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. */
6
7 #include "hb.h"
8
9 #include "faac.h"
10
11 struct hb_work_private_s
12 {
13     hb_job_t   * job;
14
15     faacEncHandle * faac;
16     unsigned long   input_samples;
17     unsigned long   output_bytes;
18     uint8_t       * buf;
19     uint8_t       * obuf;
20     hb_list_t     * list;
21     int64_t         pts;
22     int64_t         framedur;
23         int             out_discrete_channels;
24 };
25
26 int  encfaacInit( hb_work_object_t *, hb_job_t * );
27 int  encfaacWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
28 void encfaacClose( hb_work_object_t * );
29
30 hb_work_object_t hb_encfaac =
31 {
32     WORK_ENCFAAC,
33     "AAC encoder (libfaac)",
34     encfaacInit,
35     encfaacWork,
36     encfaacClose
37 };
38
39 /***********************************************************************
40  * hb_work_encfaac_init
41  ***********************************************************************
42  *
43  **********************************************************************/
44 int encfaacInit( hb_work_object_t * w, hb_job_t * job )
45 {
46     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
47     hb_audio_t * audio = w->audio;
48     faacEncConfigurationPtr cfg;
49     uint8_t * bytes;
50     unsigned long length;
51
52     w->private_data = pv;
53
54     pv->job   = job;
55
56         /* pass the number of channels used into the private work data */
57     pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);
58
59     pv->faac = faacEncOpen( audio->config.out.samplerate, pv->out_discrete_channels,
60                             &pv->input_samples, &pv->output_bytes );
61     pv->buf  = malloc( pv->input_samples * sizeof( float ) );
62     pv->obuf = malloc( pv->output_bytes );
63     pv->framedur = 90000LL * pv->input_samples /
64                    ( audio->config.out.samplerate * pv->out_discrete_channels );
65
66     cfg                = faacEncGetCurrentConfiguration( pv->faac );
67     cfg->mpegVersion   = MPEG4;
68     cfg->aacObjectType = LOW;
69     cfg->allowMidside  = 1;
70
71         if (pv->out_discrete_channels == 6) {
72                 /* we are preserving 5.1 audio into 6-channel AAC,
73                 so indicate that we have an lfe channel */
74                 cfg->useLfe    = 1;
75         } else {
76                 cfg->useLfe    = 0;
77         }
78
79     cfg->useTns        = 0;
80     cfg->bitRate       = audio->config.out.bitrate * 1000 / pv->out_discrete_channels; /* Per channel */
81     cfg->bandWidth     = 0;
82     cfg->outputFormat  = 0;
83     cfg->inputFormat   =  FAAC_INPUT_FLOAT;
84
85     if (audio->config.out.mixdown == HB_AMIXDOWN_6CH && audio->config.in.codec == HB_ACODEC_AC3)
86     {
87         /* we are preserving 5.1 AC-3 audio into 6-channel AAC, and need to
88         re-map the output of deca52 into our own mapping - the mapping
89         below is the default mapping expected by QuickTime */
90         /* DTS output from libdca is already in the right mapping for QuickTime */
91         /* This doesn't seem to be correct for VLC on Linux */
92         cfg->channel_map[0] = 2;
93         cfg->channel_map[1] = 1;
94         cfg->channel_map[2] = 3;
95         cfg->channel_map[3] = 4;
96         cfg->channel_map[4] = 5;
97         cfg->channel_map[5] = 0;
98         }
99
100     if( !faacEncSetConfiguration( pv->faac, cfg ) )
101     {
102         hb_log( "faacEncSetConfiguration failed" );
103         *job->die = 1;
104         return 0;
105     }
106
107     if( faacEncGetDecoderSpecificInfo( pv->faac, &bytes, &length ) < 0 )
108     {
109         hb_log( "faacEncGetDecoderSpecificInfo failed" );
110         *job->die = 1;
111         return 0;
112     }
113     memcpy( w->config->aac.bytes, bytes, length );
114     w->config->aac.length = length;
115     free( bytes );
116
117     pv->list = hb_list_init();
118
119     return 0;
120 }
121
122 /***********************************************************************
123  * Close
124  ***********************************************************************
125  *
126  **********************************************************************/
127 void encfaacClose( hb_work_object_t * w )
128 {
129     hb_work_private_t * pv = w->private_data;
130     if ( pv )
131     {
132         if ( pv->faac )
133         {
134             faacEncClose( pv->faac );
135             pv->faac = NULL;
136         }
137         if ( pv->buf )
138         {
139             free( pv->buf );
140             pv->buf = NULL;
141         }
142         if ( pv->obuf )
143         {
144             free( pv->obuf );
145             pv->obuf = NULL;
146         }
147         if ( pv->list )
148             hb_list_empty( &pv->list );
149
150         free( pv );
151         w->private_data = NULL;
152     }
153 }
154
155 /***********************************************************************
156  * Encode
157  ***********************************************************************
158  *
159  **********************************************************************/
160 static hb_buffer_t * Encode( hb_work_object_t * w )
161 {
162     hb_work_private_t * pv = w->private_data;
163
164     if( hb_list_bytes( pv->list ) < pv->input_samples * sizeof( float ) )
165     {
166         /* Need more data */
167         return NULL;
168     }
169
170     uint64_t pts, pos;
171     hb_list_getbytes( pv->list, pv->buf, pv->input_samples * sizeof( float ),
172                       &pts, &pos );
173     int size = faacEncEncode( pv->faac, (int32_t *)pv->buf, pv->input_samples,
174                               pv->obuf, pv->output_bytes );
175
176     // AAC needs four frames before it can start encoding so we'll get nothing
177     // on the first three calls to the encoder.
178     if ( size > 0 )
179     {
180         hb_buffer_t * buf = hb_buffer_init( size );
181         memcpy( buf->data, pv->obuf, size );
182         buf->size = size;
183         buf->start = pv->pts;
184         pv->pts += pv->framedur;
185         buf->stop = pv->pts;
186         buf->frametype   = HB_FRAME_AUDIO;
187         return buf;
188     }
189     return NULL;
190 }
191
192 static hb_buffer_t *Flush( hb_work_object_t *w, hb_buffer_t *bufin )
193 {
194     hb_work_private_t *pv = w->private_data;
195
196     // pad whatever data we have out to four input frames.
197     int nbytes = hb_list_bytes( pv->list );
198     int pad = pv->input_samples * sizeof(float) * 4 - nbytes;
199     if ( pad > 0 )
200     {
201         hb_buffer_t *tmp = hb_buffer_init( pad );
202         memset( tmp->data, 0, pad );
203         hb_list_add( pv->list, tmp );
204     }
205
206     // There are up to three frames buffered in the encoder plus one
207     // in our list buffer so four calls to Encode should get them all.
208     hb_buffer_t *bufout = NULL, *buf = NULL;
209     while ( hb_list_bytes( pv->list ) >= pv->input_samples * sizeof(float) )
210     {
211         hb_buffer_t *b = Encode( w );
212         if ( b )
213         {
214             if ( bufout == NULL )
215             {
216                 bufout = b;
217             }
218             else
219             {
220                 buf->next = b;
221             }
222             buf = b;
223         }
224     }
225     // add the eof marker to the end of our buf chain
226     if ( buf )
227         buf->next = bufin;
228     else
229         bufout = bufin;
230     return bufout;
231 }
232
233 /***********************************************************************
234  * Work
235  ***********************************************************************
236  *
237  **********************************************************************/
238 int encfaacWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
239                  hb_buffer_t ** buf_out )
240 {
241     hb_work_private_t * pv = w->private_data;
242     hb_buffer_t * buf;
243
244     if ( (*buf_in)->size <= 0 )
245     {
246         // EOF on input. Finish encoding what we have buffered then send
247         // it & the eof downstream.
248
249         *buf_out = Flush( w, *buf_in );
250         *buf_in = NULL;
251         return HB_WORK_DONE;
252     }
253
254     hb_list_add( pv->list, *buf_in );
255     *buf_in = NULL;
256
257     *buf_out = buf = Encode( w );
258
259     while( buf )
260     {
261         buf->next = Encode( w );
262         buf       = buf->next;
263     }
264
265     return HB_WORK_OK;
266 }
267