OSDN Git Service

x264 bump to r1339-82b80ef
[handbrake-jp/handbrake-jp-git.git] / libhb / platform / macosx / encca_aac.c
1 /* This file is part of the HandBrake source code.
2  Homepage: <http://handbrake.fr/>.
3  It may be used under the terms of the GNU General Public License. */
4
5 #include "hb.h"
6 #include <AudioToolbox/AudioToolbox.h>
7 #include <CoreAudio/CoreAudio.h>
8
9 int     encCoreAudioInit( hb_work_object_t *, hb_job_t * );
10 int     encCoreAudioWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
11 void    encCoreAudioClose( hb_work_object_t * );
12
13 hb_work_object_t hb_encca_aac =
14 {
15     WORK_ENC_CA_AAC,
16     "AAC encoder (Apple)",
17     encCoreAudioInit,
18     encCoreAudioWork,
19     encCoreAudioClose
20 };
21
22 struct hb_work_private_s
23 {
24     hb_job_t *job;
25     
26     AudioConverterRef converter;
27     uint8_t  *obuf;
28     uint8_t  *buf;
29     hb_list_t *list;
30     unsigned long isamples, isamplesiz, omaxpacket, nchannels;
31     uint64_t pts, ibytes;
32     Float64 osamplerate;
33 };
34
35 #define MP4ESDescrTag                   0x03
36 #define MP4DecConfigDescrTag            0x04
37 #define MP4DecSpecificDescrTag          0x05
38
39 // based off of mov_mp4_read_descr_len from mov.c in ffmpeg's libavformat
40 static int readDescrLen(UInt8 **buffer)
41 {
42         int len = 0;
43         int count = 4;
44         while (count--) {
45                 int c = *(*buffer)++;
46                 len = (len << 7) | (c & 0x7f);
47                 if (!(c & 0x80))
48                         break;
49         }
50         return len;
51 }
52
53 // based off of mov_mp4_read_descr from mov.c in ffmpeg's libavformat
54 static int readDescr(UInt8 **buffer, int *tag)
55 {
56         *tag = *(*buffer)++;
57         return readDescrLen(buffer);
58 }
59
60 // based off of mov_read_esds from mov.c in ffmpeg's libavformat
61 static long ReadESDSDescExt(void* descExt, UInt8 **buffer, UInt32 *size, int versionFlags)
62 {
63         UInt8 *esds = (UInt8 *) descExt;
64         int tag, len;
65         *size = 0;
66
67     if (versionFlags)
68         esds += 4;              // version + flags
69         readDescr(&esds, &tag);
70         esds += 2;              // ID
71         if (tag == MP4ESDescrTag)
72                 esds++;         // priority
73
74         readDescr(&esds, &tag);
75         if (tag == MP4DecConfigDescrTag) {
76                 esds++;         // object type id
77                 esds++;         // stream type
78                 esds += 3;      // buffer size db
79                 esds += 4;      // max bitrate
80                 esds += 4;      // average bitrate
81
82                 len = readDescr(&esds, &tag);
83                 if (tag == MP4DecSpecificDescrTag) {
84                         *buffer = calloc(1, len + 8);
85                         if (*buffer) {
86                                 memcpy(*buffer, esds, len);
87                                 *size = len;
88                         }
89                 }
90         }
91
92         return noErr;
93 }
94
95 /***********************************************************************
96  * hb_work_encCoreAudio_init
97  ***********************************************************************
98  *
99  **********************************************************************/
100 int encCoreAudioInit( hb_work_object_t * w, hb_job_t * job )
101 {
102     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
103     hb_audio_t * audio = w->audio;
104     AudioStreamBasicDescription input, output;
105     UInt32 tmp, tmpsiz = sizeof( tmp );
106     OSStatus err;
107
108     w->private_data = pv;
109     pv->job = job;
110
111     // pass the number of channels used into the private work data
112     pv->nchannels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT( audio->config.out.mixdown );
113
114     bzero( &input, sizeof( AudioStreamBasicDescription ) );
115     input.mSampleRate = ( Float64 ) audio->config.out.samplerate;
116     input.mFormatID = kAudioFormatLinearPCM;
117     input.mFormatFlags = kLinearPCMFormatFlagIsFloat | kAudioFormatFlagsNativeEndian;
118     input.mBytesPerPacket = 4 * pv->nchannels;
119     input.mFramesPerPacket = 1;
120     input.mBytesPerFrame = input.mBytesPerPacket * input.mFramesPerPacket;
121     input.mChannelsPerFrame = pv->nchannels;
122     input.mBitsPerChannel = 32;
123
124     bzero( &output, sizeof( AudioStreamBasicDescription ) );
125     output.mFormatID = kAudioFormatMPEG4AAC;
126     output.mSampleRate = ( Float64 ) audio->config.out.samplerate;
127     output.mChannelsPerFrame = pv->nchannels;
128     // let CoreAudio decide the rest...
129
130     // initialise encoder
131     err = AudioConverterNew( &input, &output, &pv->converter );
132     if( err != noErr)
133     {
134         // Retry without the samplerate
135         bzero( &output, sizeof( AudioStreamBasicDescription ) );
136         output.mFormatID = kAudioFormatMPEG4AAC;
137         output.mChannelsPerFrame = pv->nchannels;
138
139         err = AudioConverterNew( &input, &output, &pv->converter );
140
141         if( err != noErr)
142         {
143             hb_log( "Error creating an AudioConverter err=%"PRId64" %"PRIu64, (int64_t)err, (uint64_t)output.mBytesPerFrame );
144             *job->die = 1;
145             return 0;
146         }
147     }
148
149     if( audio->config.out.mixdown == HB_AMIXDOWN_6CH && audio->config.in.codec == HB_ACODEC_AC3 )
150     {
151         SInt32 channelMap[6] = { 2, 1, 3, 4, 5, 0 };
152         AudioConverterSetProperty( pv->converter, kAudioConverterChannelMap,
153                                    sizeof( channelMap ), channelMap );
154     }
155
156     // set encoder quality to maximum
157     tmp = kAudioConverterQuality_Max;
158     AudioConverterSetProperty( pv->converter, kAudioConverterCodecQuality,
159                                sizeof( tmp ), &tmp );
160
161     // set encoder bitrate control mode to constrained variable
162     tmp = kAudioCodecBitRateControlMode_VariableConstrained;
163     AudioConverterSetProperty( pv->converter, kAudioCodecPropertyBitRateControlMode,
164                               sizeof( tmp ), &tmp );
165
166     // get available bitrates
167     AudioValueRange *bitrates;
168     ssize_t bitrateCounts;
169     err = AudioConverterGetPropertyInfo( pv->converter, kAudioConverterApplicableEncodeBitRates,
170                                          &tmpsiz, NULL);
171     bitrates = malloc( tmpsiz );
172     err = AudioConverterGetProperty( pv->converter, kAudioConverterApplicableEncodeBitRates,
173                                      &tmpsiz, bitrates);
174     bitrateCounts = tmpsiz / sizeof( AudioValueRange );
175
176     // set bitrate
177     tmp = audio->config.out.bitrate * 1000;
178     if( tmp < bitrates[0].mMinimum )
179         tmp = bitrates[0].mMinimum;
180     if( tmp > bitrates[bitrateCounts-1].mMinimum )
181         tmp = bitrates[bitrateCounts-1].mMinimum;
182     free( bitrates );
183     AudioConverterSetProperty( pv->converter, kAudioConverterEncodeBitRate,
184                               sizeof( tmp ), &tmp );
185
186     // get real input
187     tmpsiz = sizeof( input );
188     AudioConverterGetProperty( pv->converter,
189                                kAudioConverterCurrentInputStreamDescription,
190                                &tmpsiz, &input );
191     // get real output
192     tmpsiz = sizeof( output );
193     AudioConverterGetProperty( pv->converter,
194                                kAudioConverterCurrentOutputStreamDescription,
195                                &tmpsiz, &output );
196
197     // set sizes
198     pv->isamplesiz  = input.mBytesPerPacket;
199     pv->isamples    = output.mFramesPerPacket;
200     pv->osamplerate = output.mSampleRate;
201
202     // get maximum output size
203     AudioConverterGetProperty( pv->converter,
204                                kAudioConverterPropertyMaximumOutputPacketSize,
205                                &tmpsiz, &tmp );
206     pv->omaxpacket = tmp;
207
208     // get magic cookie (elementary stream descriptor)
209     tmp = HB_CONFIG_MAX_SIZE;
210     AudioConverterGetProperty( pv->converter,
211                                kAudioConverterCompressionMagicCookie,
212                                &tmp, w->config->aac.bytes );
213     // CoreAudio returns a complete ESDS, but we only need
214     // the DecoderSpecific info.
215     UInt8* buffer = NULL;
216     ReadESDSDescExt(w->config->aac.bytes, &buffer, &tmpsiz, 0);
217     w->config->aac.length = tmpsiz;
218     memmove( w->config->aac.bytes, buffer,
219              w->config->aac.length );
220
221     pv->list = hb_list_init();
222     pv->buf = NULL;
223
224     return 0;
225 }
226
227 /***********************************************************************
228  * Close
229  ***********************************************************************
230  *
231  **********************************************************************/
232 void encCoreAudioClose( hb_work_object_t * w )
233 {
234     hb_work_private_t * pv = w->private_data;
235
236     if( pv->converter )
237     {
238         AudioConverterDispose( pv->converter );
239         hb_list_empty( &pv->list );
240         free( pv->obuf );
241         free( pv->buf );
242         free( pv );
243         w->private_data = NULL;
244     }
245 }
246
247 /* Called whenever necessary by AudioConverterFillComplexBuffer */
248 static OSStatus inInputDataProc( AudioConverterRef converter, UInt32 *npackets,
249                           AudioBufferList *buffers,
250                           AudioStreamPacketDescription** ignored,
251                           void *userdata )
252 {
253     hb_work_private_t *pv = userdata;
254     pv->ibytes = hb_list_bytes( pv->list );
255
256     if( pv->ibytes == 0 ) {
257         *npackets = 0;
258         return noErr;
259     }
260
261     if( pv->buf != NULL )
262         free( pv->buf );
263
264     uint64_t pts, pos;
265     pv->ibytes = buffers->mBuffers[0].mDataByteSize = MIN( *npackets * pv->isamplesiz, pv->ibytes );
266     buffers->mBuffers[0].mData = pv->buf = malloc( buffers->mBuffers[0].mDataByteSize );
267
268     hb_list_getbytes( pv->list, buffers->mBuffers[0].mData,
269                       buffers->mBuffers[0].mDataByteSize, &pts, &pos );
270
271     *npackets = buffers->mBuffers[0].mDataByteSize / pv->isamplesiz;
272
273     /* transform data from [-32768,32767] to [-1.0,1.0] */
274     float *fdata = buffers->mBuffers[0].mData;
275     int i;
276
277     for( i = 0; i < *npackets * pv->nchannels; i++ )
278         fdata[i] = fdata[i] / 32768.f;
279
280     return noErr;
281 }
282
283 /***********************************************************************
284  * Encode
285  ***********************************************************************
286  *
287  **********************************************************************/
288 static hb_buffer_t * Encode( hb_work_object_t * w )
289 {
290     hb_work_private_t * pv = w->private_data;
291     UInt32 npackets = 1;
292
293     /* check if we need more data */
294     if( hb_list_bytes( pv->list ) < pv->isamples * pv->isamplesiz )
295         return NULL;
296
297     hb_buffer_t * obuf;
298     AudioStreamPacketDescription odesc = { 0 };
299     AudioBufferList obuflist = { .mNumberBuffers = 1,
300                                  .mBuffers = { { .mNumberChannels = pv->nchannels } },
301                                };
302
303     obuf = hb_buffer_init( pv->omaxpacket );
304     obuflist.mBuffers[0].mDataByteSize = obuf->size;
305     obuflist.mBuffers[0].mData = obuf->data;
306
307     AudioConverterFillComplexBuffer( pv->converter, inInputDataProc, pv, 
308                                      &npackets, &obuflist, &odesc );
309
310     if( odesc.mDataByteSize == 0 )
311         return NULL;
312
313     obuf->start = pv->pts;
314     pv->pts += 90000LL * pv->isamples / pv->osamplerate;
315     obuf->stop  = pv->pts;
316     obuf->size  = odesc.mDataByteSize;
317     obuf->frametype = HB_FRAME_AUDIO;
318
319     return obuf;
320 }
321
322 /***********************************************************************
323  * Work
324  ***********************************************************************
325  *
326  **********************************************************************/
327 int encCoreAudioWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
328                   hb_buffer_t ** buf_out )
329 {
330     hb_work_private_t * pv = w->private_data;
331     hb_buffer_t * buf;
332
333     if( (*buf_in)->size <= 0 )
334     {
335         // EOF on input - send it downstream & say we're done
336         *buf_out = *buf_in;
337         *buf_in = NULL;
338         return HB_WORK_DONE;
339     }
340
341     hb_list_add( pv->list, *buf_in );
342     *buf_in = NULL;
343
344     *buf_out = buf = Encode( w );
345
346     while( buf )
347     {
348         buf->next = Encode( w );
349         buf       = buf->next;
350     }
351
352     return HB_WORK_OK;
353 }