OSDN Git Service

Jamfile - Fixes tab instead of 4 spaces.
[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     faacEncClose( pv->faac );
131     free( pv->buf );
132     free( pv->obuf );
133     hb_list_empty( &pv->list );
134     free( pv );
135     w->private_data = NULL;
136 }
137
138 /***********************************************************************
139  * Encode
140  ***********************************************************************
141  *
142  **********************************************************************/
143 static hb_buffer_t * Encode( hb_work_object_t * w )
144 {
145     hb_work_private_t * pv = w->private_data;
146
147     if( hb_list_bytes( pv->list ) < pv->input_samples * sizeof( float ) )
148     {
149         /* Need more data */
150         return NULL;
151     }
152
153     uint64_t pts, pos;
154     hb_list_getbytes( pv->list, pv->buf, pv->input_samples * sizeof( float ),
155                       &pts, &pos );
156     int size = faacEncEncode( pv->faac, (int32_t *)pv->buf, pv->input_samples,
157                               pv->obuf, pv->output_bytes );
158
159     // AAC needs four frames before it can start encoding so we'll get nothing
160     // on the first three calls to the encoder.
161     if ( size > 0 )
162     {
163         hb_buffer_t * buf = hb_buffer_init( size );
164         memcpy( buf->data, pv->obuf, size );
165         buf->size = size;
166         buf->start = pv->pts;
167         pv->pts += pv->framedur;
168         buf->stop = pv->pts;
169         buf->frametype   = HB_FRAME_AUDIO;
170         return buf;
171     }
172     return NULL;
173 }
174
175 static hb_buffer_t *Flush( hb_work_object_t *w, hb_buffer_t *bufin )
176 {
177     hb_work_private_t *pv = w->private_data;
178
179     // pad whatever data we have out to four input frames.
180     int nbytes = hb_list_bytes( pv->list );
181     int pad = pv->input_samples * sizeof(float) * 4 - nbytes;
182     if ( pad > 0 )
183     {
184         hb_buffer_t *tmp = hb_buffer_init( pad );
185         memset( tmp->data, 0, pad );
186         hb_list_add( pv->list, tmp );
187     }
188
189     // There are up to three frames buffered in the encoder plus one
190     // in our list buffer so four calls to Encode should get them all.
191     hb_buffer_t *bufout = NULL, *buf = NULL;
192     while ( hb_list_bytes( pv->list ) >= pv->input_samples * sizeof(float) )
193     {
194         hb_buffer_t *b = Encode( w );
195         if ( b )
196         {
197             if ( bufout == NULL )
198             {
199                 bufout = b;
200             }
201             else
202             {
203                 buf->next = b;
204             }
205             buf = b;
206         }
207     }
208     // add the eof marker to the end of our buf chain
209     if ( buf )
210         buf->next = bufin;
211     else
212         bufout = bufin;
213     return bufout;
214 }
215
216 /***********************************************************************
217  * Work
218  ***********************************************************************
219  *
220  **********************************************************************/
221 int encfaacWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
222                  hb_buffer_t ** buf_out )
223 {
224     hb_work_private_t * pv = w->private_data;
225     hb_buffer_t * buf;
226
227     if ( (*buf_in)->size <= 0 )
228     {
229         // EOF on input. Finish encoding what we have buffered then send
230         // it & the eof downstream.
231
232         *buf_out = Flush( w, *buf_in );
233         *buf_in = NULL;
234         return HB_WORK_DONE;
235     }
236
237     hb_list_add( pv->list, *buf_in );
238     *buf_in = NULL;
239
240     *buf_out = buf = Encode( w );
241
242     while( buf )
243     {
244         buf->next = Encode( w );
245         buf       = buf->next;
246     }
247
248     return HB_WORK_OK;
249 }
250