OSDN Git Service

Opens up another way to give x264 a constant QP or RF, by passing a direct value...
[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
20     hb_list_t     * list;
21     int64_t         pts;
22
23         int             out_discrete_channels;
24
25 };
26
27 int  encfaacInit( hb_work_object_t *, hb_job_t * );
28 int  encfaacWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
29 void encfaacClose( hb_work_object_t * );
30
31 hb_work_object_t hb_encfaac =
32 {
33     WORK_ENCFAAC,
34     "AAC encoder (libfaac)",
35     encfaacInit,
36     encfaacWork,
37     encfaacClose
38 };
39
40 /***********************************************************************
41  * hb_work_encfaac_init
42  ***********************************************************************
43  *
44  **********************************************************************/
45 int encfaacInit( hb_work_object_t * w, hb_job_t * job )
46 {
47     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
48     hb_audio_t * audio = w->audio;
49     faacEncConfigurationPtr cfg;
50     uint8_t * bytes;
51     unsigned long length;
52
53     w->private_data = pv;
54
55     pv->job   = job;
56
57         /* pass the number of channels used into the private work data */
58     pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);
59
60     pv->faac = faacEncOpen( audio->config.out.samplerate, pv->out_discrete_channels, &pv->input_samples,
61                            &pv->output_bytes );
62     pv->buf  = malloc( pv->input_samples * sizeof( float ) );
63
64     cfg                = faacEncGetCurrentConfiguration( pv->faac );
65     cfg->mpegVersion   = MPEG4;
66     cfg->aacObjectType = LOW;
67     cfg->allowMidside  = 1;
68
69         if (pv->out_discrete_channels == 6) {
70                 /* we are preserving 5.1 audio into 6-channel AAC,
71                 so indicate that we have an lfe channel */
72                 cfg->useLfe    = 1;
73         } else {
74                 cfg->useLfe    = 0;
75         }
76
77     cfg->useTns        = 0;
78     cfg->bitRate       = audio->config.out.bitrate * 1000 / pv->out_discrete_channels; /* Per channel */
79     cfg->bandWidth     = 0;
80     cfg->outputFormat  = 0;
81     cfg->inputFormat   =  FAAC_INPUT_FLOAT;
82
83     if (audio->config.out.mixdown == HB_AMIXDOWN_6CH && audio->config.in.codec == HB_ACODEC_AC3)
84     {
85         /* we are preserving 5.1 AC-3 audio into 6-channel AAC, and need to
86         re-map the output of deca52 into our own mapping - the mapping
87         below is the default mapping expected by QuickTime */
88         /* DTS output from libdca is already in the right mapping for QuickTime */
89         /* This doesn't seem to be correct for VLC on Linux */
90         cfg->channel_map[0] = 2;
91         cfg->channel_map[1] = 1;
92         cfg->channel_map[2] = 3;
93         cfg->channel_map[3] = 4;
94         cfg->channel_map[4] = 5;
95         cfg->channel_map[5] = 0;
96         }
97
98     if( !faacEncSetConfiguration( pv->faac, cfg ) )
99     {
100         hb_log( "faacEncSetConfiguration failed" );
101         *job->die = 1;
102         return 0;
103     }
104
105     if( faacEncGetDecoderSpecificInfo( pv->faac, &bytes, &length ) < 0 )
106     {
107         hb_log( "faacEncGetDecoderSpecificInfo failed" );
108         *job->die = 1;
109         return 0;
110     }
111     memcpy( w->config->aac.bytes, bytes, length );
112     w->config->aac.length = length;
113     free( bytes );
114
115     pv->list = hb_list_init();
116     pv->pts  = -1;
117
118     return 0;
119 }
120
121 /***********************************************************************
122  * Close
123  ***********************************************************************
124  *
125  **********************************************************************/
126 void encfaacClose( hb_work_object_t * w )
127 {
128     hb_work_private_t * pv = w->private_data;
129     faacEncClose( pv->faac );
130     free( pv->buf );
131     hb_list_empty( &pv->list );
132     free( pv );
133     w->private_data = NULL;
134 }
135
136 /***********************************************************************
137  * Encode
138  ***********************************************************************
139  *
140  **********************************************************************/
141 static hb_buffer_t * Encode( hb_work_object_t * w )
142 {
143     hb_work_private_t * pv = w->private_data;
144     hb_audio_t * audio = w->audio;
145     hb_buffer_t * buf;
146     uint64_t      pts, pos;
147
148     if( hb_list_bytes( pv->list ) < pv->input_samples * sizeof( float ) )
149     {
150         /* Need more data */
151         return NULL;
152     }
153
154     hb_list_getbytes( pv->list, pv->buf, pv->input_samples * sizeof( float ),
155                       &pts, &pos );
156
157     buf        = hb_buffer_init( pv->output_bytes );
158     buf->start = pts + 90000 * pos / pv->out_discrete_channels / sizeof( float ) / audio->config.out.samplerate;
159     buf->stop  = buf->start + 90000 * pv->input_samples / audio->config.out.samplerate / pv->out_discrete_channels;
160     buf->size  = faacEncEncode( pv->faac, (int32_t *) pv->buf,
161             pv->input_samples, buf->data, pv->output_bytes );
162     buf->frametype   = HB_FRAME_AUDIO;
163
164     if( !buf->size )
165     {
166         /* Encoding was successful but we got no data. Try to encode
167            more */
168         hb_buffer_close( &buf );
169         return Encode( w );
170     }
171     else if( buf->size < 0 )
172     {
173         hb_log( "faacEncEncode failed" );
174         hb_buffer_close( &buf );
175         return NULL;
176     }
177
178     return buf;
179 }
180
181 /***********************************************************************
182  * Work
183  ***********************************************************************
184  *
185  **********************************************************************/
186 int encfaacWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
187                  hb_buffer_t ** buf_out )
188 {
189     hb_work_private_t * pv = w->private_data;
190     hb_buffer_t * buf;
191
192     hb_list_add( pv->list, *buf_in );
193     *buf_in = NULL;
194
195     *buf_out = buf = Encode( w );
196
197     while( buf )
198     {
199         buf->next = Encode( w );
200         buf       = buf->next;
201     }
202
203     return HB_WORK_OK;
204 }
205