OSDN Git Service

LinGui: make Help->Guide work on windows/mingw
[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
255     if( pv->ibytes == 0 )
256     {
257         *npackets = 0;
258         hb_log( "CoreAudio: no data to use in inInputDataProc" );
259         return noErr;
260     }
261
262     if( pv->buf != NULL )
263         free( pv->buf );
264
265     uint64_t pts, pos;
266     buffers->mBuffers[0].mDataByteSize = MIN( *npackets * pv->isamplesiz, pv->ibytes );
267     buffers->mBuffers[0].mData = pv->buf = calloc(1 , buffers->mBuffers[0].mDataByteSize );
268
269     if( hb_list_bytes( pv->list ) >= buffers->mBuffers[0].mDataByteSize )
270     {
271         hb_list_getbytes( pv->list, buffers->mBuffers[0].mData,
272                           buffers->mBuffers[0].mDataByteSize, &pts, &pos );
273     }
274     else
275     {
276         hb_log( "CoreAudio: Not enought data, exiting inInputDataProc" );
277         *npackets = 0;
278         return 1;
279     }
280
281     *npackets = buffers->mBuffers[0].mDataByteSize / pv->isamplesiz;
282
283     /* transform data from [-32768,32767] to [-1.0,1.0] */
284     float *fdata = buffers->mBuffers[0].mData;
285     int i;
286
287     for( i = 0; i < *npackets * pv->nchannels; i++ ) {
288         fdata[i] = fdata[i] / 32768.f;
289     }
290
291     pv->ibytes -= buffers->mBuffers[0].mDataByteSize;
292
293     return noErr;
294 }
295
296 /***********************************************************************
297  * Encode
298  ***********************************************************************
299  *
300  **********************************************************************/
301 static hb_buffer_t * Encode( hb_work_object_t * w )
302 {
303     hb_work_private_t * pv = w->private_data;
304     UInt32 npackets = 1;
305
306     /* check if we need more data */
307     if( ( pv->ibytes = hb_list_bytes( pv->list ) ) < pv->isamples * pv->isamplesiz )
308         return NULL;
309
310     hb_buffer_t * obuf;
311     AudioStreamPacketDescription odesc = { 0 };
312     AudioBufferList obuflist = { .mNumberBuffers = 1,
313                                  .mBuffers = { { .mNumberChannels = pv->nchannels } },
314                                };
315
316     obuf = hb_buffer_init( pv->omaxpacket );
317     obuflist.mBuffers[0].mDataByteSize = obuf->size;
318     obuflist.mBuffers[0].mData = obuf->data;
319
320     OSStatus err = AudioConverterFillComplexBuffer( pv->converter, inInputDataProc, pv, 
321                                      &npackets, &obuflist, &odesc );
322     if( err ) {
323         hb_log( "CoreAudio: Not enough data" );
324         return NULL;
325     }
326     if( odesc.mDataByteSize == 0 || npackets == 0 ) {
327         return NULL;
328         hb_log( "CoreAudio: 0 packets returned " );
329     }
330
331     obuf->start = pv->pts;
332     pv->pts += 90000LL * pv->isamples / pv->osamplerate;
333     obuf->stop  = pv->pts;
334     obuf->size  = odesc.mDataByteSize;
335     obuf->frametype = HB_FRAME_AUDIO;
336
337     return obuf;
338 }
339
340 static hb_buffer_t *Flush( hb_work_object_t *w, hb_buffer_t *bufin )
341 {
342     hb_work_private_t *pv = w->private_data;
343
344     // pad whatever data we have out to four input frames.
345     int nbytes = hb_list_bytes( pv->list );
346     int pad = pv->isamples * pv->isamplesiz - nbytes;
347     if ( pad > 0 )
348     {
349         hb_buffer_t *tmp = hb_buffer_init( pad );
350         memset( tmp->data, 0, pad );
351         hb_list_add( pv->list, tmp );
352     }
353
354     hb_buffer_t *bufout = NULL, *buf = NULL;
355     while ( hb_list_bytes( pv->list ) >= pv->isamples * pv->isamplesiz )
356     {
357         hb_buffer_t *b = Encode( w );
358         if ( b )
359         {
360             if ( bufout == NULL )
361             {
362                 bufout = b;
363             }
364             else
365             {
366                 buf->next = b;
367             }
368             buf = b;
369         }
370     }
371     // add the eof marker to the end of our buf chain
372     if ( buf )
373         buf->next = bufin;
374     else
375         bufout = bufin;
376     return bufout;
377 }
378
379 /***********************************************************************
380  * Work
381  ***********************************************************************
382  *
383  **********************************************************************/
384 int encCoreAudioWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
385                   hb_buffer_t ** buf_out )
386 {
387     hb_work_private_t * pv = w->private_data;
388     hb_buffer_t * buf;
389
390     if( (*buf_in)->size <= 0 )
391     {
392         // EOF on input. Finish encoding what we have buffered then send
393         // it & the eof downstream.
394         *buf_out = Flush( w, *buf_in );
395         *buf_in = NULL;
396         return HB_WORK_DONE;
397     }
398
399     hb_list_add( pv->list, *buf_in );
400     *buf_in = NULL;
401
402     *buf_out = buf = Encode( w );
403
404     while( buf )
405     {
406         buf->next = Encode( w );
407         buf       = buf->next;
408     }
409
410     return HB_WORK_OK;
411 }