OSDN Git Service

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