OSDN Git Service

LinGui: make Help->Guide work on windows/mingw
[handbrake-jp/handbrake-jp-git.git] / libhb / platform / macosx / encca_aac.c
index 69b29ec..762559c 100644 (file)
@@ -29,6 +29,7 @@ struct hb_work_private_s
     hb_list_t *list;
     unsigned long isamples, isamplesiz, omaxpacket, nchannels;
     uint64_t pts, ibytes;
+    Float64 osamplerate;
 };
 
 #define MP4ESDescrTag                   0x03
@@ -57,7 +58,7 @@ static int readDescr(UInt8 **buffer, int *tag)
 }
 
 // based off of mov_read_esds from mov.c in ffmpeg's libavformat
-static long ReadESDSDescExt(void* descExt, UInt8 **buffer, int *size, int versionFlags)
+static long ReadESDSDescExt(void* descExt, UInt8 **buffer, UInt32 *size, int versionFlags)
 {
        UInt8 *esds = (UInt8 *) descExt;
        int tag, len;
@@ -121,8 +122,8 @@ int encCoreAudioInit( hb_work_object_t * w, hb_job_t * job )
     input.mBitsPerChannel = 32;
 
     bzero( &output, sizeof( AudioStreamBasicDescription ) );
-    output.mSampleRate = ( Float64 ) audio->config.out.samplerate;
     output.mFormatID = kAudioFormatMPEG4AAC;
+    output.mSampleRate = ( Float64 ) audio->config.out.samplerate;
     output.mChannelsPerFrame = pv->nchannels;
     // let CoreAudio decide the rest...
 
@@ -130,12 +131,22 @@ int encCoreAudioInit( hb_work_object_t * w, hb_job_t * job )
     err = AudioConverterNew( &input, &output, &pv->converter );
     if( err != noErr)
     {
-        hb_log( "Error creating an AudioConverter %x %d", err, output.mBytesPerFrame );
-        *job->die = 1;
-        return 0;
+        // Retry without the samplerate
+        bzero( &output, sizeof( AudioStreamBasicDescription ) );
+        output.mFormatID = kAudioFormatMPEG4AAC;
+        output.mChannelsPerFrame = pv->nchannels;
+
+        err = AudioConverterNew( &input, &output, &pv->converter );
+
+        if( err != noErr)
+        {
+            hb_log( "Error creating an AudioConverter err=%"PRId64" %"PRIu64, (int64_t)err, (uint64_t)output.mBytesPerFrame );
+            *job->die = 1;
+            return 0;
+        }
     }
 
-    if( audio->config.out.mixdown == HB_AMIXDOWN_6CH && audio->config.in.codec == HB_ACODEC_AC3 )
+    if( ( audio->config.out.mixdown == HB_AMIXDOWN_6CH ) && ( audio->config.in.codec == HB_ACODEC_AC3) )
     {
         SInt32 channelMap[6] = { 2, 1, 3, 4, 5, 0 };
         AudioConverterSetProperty( pv->converter, kAudioConverterChannelMap,
@@ -154,7 +165,7 @@ int encCoreAudioInit( hb_work_object_t * w, hb_job_t * job )
 
     // get available bitrates
     AudioValueRange *bitrates;
-    ssize_t bitrateCounts, n;
+    ssize_t bitrateCounts;
     err = AudioConverterGetPropertyInfo( pv->converter, kAudioConverterApplicableEncodeBitRates,
                                          &tmpsiz, NULL);
     bitrates = malloc( tmpsiz );
@@ -184,8 +195,9 @@ int encCoreAudioInit( hb_work_object_t * w, hb_job_t * job )
                                &tmpsiz, &output );
 
     // set sizes
-    pv->isamplesiz = input.mBytesPerPacket;
-    pv->isamples   = output.mFramesPerPacket;
+    pv->isamplesiz  = input.mBytesPerPacket;
+    pv->isamples    = output.mFramesPerPacket;
+    pv->osamplerate = output.mSampleRate;
 
     // get maximum output size
     AudioConverterGetProperty( pv->converter,
@@ -200,7 +212,7 @@ int encCoreAudioInit( hb_work_object_t * w, hb_job_t * job )
                                &tmp, w->config->aac.bytes );
     // CoreAudio returns a complete ESDS, but we only need
     // the DecoderSpecific info.
-    UInt8* buffer;
+    UInt8* buffer = NULL;
     ReadESDSDescExt(w->config->aac.bytes, &buffer, &tmpsiz, 0);
     w->config->aac.length = tmpsiz;
     memmove( w->config->aac.bytes, buffer,
@@ -239,10 +251,11 @@ static OSStatus inInputDataProc( AudioConverterRef converter, UInt32 *npackets,
                           void *userdata )
 {
     hb_work_private_t *pv = userdata;
-    pv->ibytes = hb_list_bytes( pv->list );
 
-    if( pv->ibytes == 0 ) {
+    if( pv->ibytes == 0 )
+    {
         *npackets = 0;
+        hb_log( "CoreAudio: no data to use in inInputDataProc" );
         return noErr;
     }
 
@@ -250,11 +263,20 @@ static OSStatus inInputDataProc( AudioConverterRef converter, UInt32 *npackets,
         free( pv->buf );
 
     uint64_t pts, pos;
-    pv->ibytes = buffers->mBuffers[0].mDataByteSize = MIN( *npackets * pv->isamplesiz, pv->ibytes );
-    buffers->mBuffers[0].mData = pv->buf = malloc( buffers->mBuffers[0].mDataByteSize );
+    buffers->mBuffers[0].mDataByteSize = MIN( *npackets * pv->isamplesiz, pv->ibytes );
+    buffers->mBuffers[0].mData = pv->buf = calloc(1 , buffers->mBuffers[0].mDataByteSize );
 
-    hb_list_getbytes( pv->list, buffers->mBuffers[0].mData,
-                      buffers->mBuffers[0].mDataByteSize, &pts, &pos );
+    if( hb_list_bytes( pv->list ) >= buffers->mBuffers[0].mDataByteSize )
+    {
+        hb_list_getbytes( pv->list, buffers->mBuffers[0].mData,
+                          buffers->mBuffers[0].mDataByteSize, &pts, &pos );
+    }
+    else
+    {
+        hb_log( "CoreAudio: Not enought data, exiting inInputDataProc" );
+        *npackets = 0;
+        return 1;
+    }
 
     *npackets = buffers->mBuffers[0].mDataByteSize / pv->isamplesiz;
 
@@ -262,8 +284,11 @@ static OSStatus inInputDataProc( AudioConverterRef converter, UInt32 *npackets,
     float *fdata = buffers->mBuffers[0].mData;
     int i;
 
-    for( i = 0; i < *npackets * pv->nchannels; i++ )
+    for( i = 0; i < *npackets * pv->nchannels; i++ ) {
         fdata[i] = fdata[i] / 32768.f;
+    }
+
+    pv->ibytes -= buffers->mBuffers[0].mDataByteSize;
 
     return noErr;
 }
@@ -279,7 +304,7 @@ static hb_buffer_t * Encode( hb_work_object_t * w )
     UInt32 npackets = 1;
 
     /* check if we need more data */
-    if( hb_list_bytes( pv->list ) < pv->isamples * pv->isamplesiz )
+    if( ( pv->ibytes = hb_list_bytes( pv->list ) ) < pv->isamples * pv->isamplesiz )
         return NULL;
 
     hb_buffer_t * obuf;
@@ -292,14 +317,19 @@ static hb_buffer_t * Encode( hb_work_object_t * w )
     obuflist.mBuffers[0].mDataByteSize = obuf->size;
     obuflist.mBuffers[0].mData = obuf->data;
 
-    AudioConverterFillComplexBuffer( pv->converter, inInputDataProc, pv, 
+    OSStatus err = AudioConverterFillComplexBuffer( pv->converter, inInputDataProc, pv, 
                                      &npackets, &obuflist, &odesc );
-
-    if( odesc.mDataByteSize == 0 )
+    if( err ) {
+        hb_log( "CoreAudio: Not enough data" );
         return NULL;
+    }
+    if( odesc.mDataByteSize == 0 || npackets == 0 ) {
+        return NULL;
+        hb_log( "CoreAudio: 0 packets returned " );
+    }
 
     obuf->start = pv->pts;
-    pv->pts += 90000LL * pv->isamples / w->audio->config.out.samplerate;
+    pv->pts += 90000LL * pv->isamples / pv->osamplerate;
     obuf->stop  = pv->pts;
     obuf->size  = odesc.mDataByteSize;
     obuf->frametype = HB_FRAME_AUDIO;
@@ -307,6 +337,45 @@ static hb_buffer_t * Encode( hb_work_object_t * w )
     return obuf;
 }
 
+static hb_buffer_t *Flush( hb_work_object_t *w, hb_buffer_t *bufin )
+{
+    hb_work_private_t *pv = w->private_data;
+
+    // pad whatever data we have out to four input frames.
+    int nbytes = hb_list_bytes( pv->list );
+    int pad = pv->isamples * pv->isamplesiz - nbytes;
+    if ( pad > 0 )
+    {
+        hb_buffer_t *tmp = hb_buffer_init( pad );
+        memset( tmp->data, 0, pad );
+        hb_list_add( pv->list, tmp );
+    }
+
+    hb_buffer_t *bufout = NULL, *buf = NULL;
+    while ( hb_list_bytes( pv->list ) >= pv->isamples * pv->isamplesiz )
+    {
+        hb_buffer_t *b = Encode( w );
+        if ( b )
+        {
+            if ( bufout == NULL )
+            {
+                bufout = b;
+            }
+            else
+            {
+                buf->next = b;
+            }
+            buf = b;
+        }
+    }
+    // add the eof marker to the end of our buf chain
+    if ( buf )
+        buf->next = bufin;
+    else
+        bufout = bufin;
+    return bufout;
+}
+
 /***********************************************************************
  * Work
  ***********************************************************************
@@ -320,8 +389,9 @@ int encCoreAudioWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
 
     if( (*buf_in)->size <= 0 )
     {
-        // EOF on input - send it downstream & say we're done
-        *buf_out = *buf_in;
+        // EOF on input. Finish encoding what we have buffered then send
+        // it & the eof downstream.
+        *buf_out = Flush( w, *buf_in );
         *buf_in = NULL;
         return HB_WORK_DONE;
     }