Ignore:
Timestamp:
Apr 13, 2010 2:29:56 PM (14 years ago)
Author:
ming
Message:

Implemented ticket #1054: iLBC codec framework for iPhone OS
Implemented iLBC codec framework using Audio Toolbox's Audio Converter. The implementation works on Mac OS as well.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/iphone/pjmedia/src/pjmedia-codec/ilbc.c

    r2834 r3137  
    3131#include <pj/string.h> 
    3232#include <pj/os.h> 
    33 #include "../../third_party/ilbc/iLBC_encode.h" 
    34 #include "../../third_party/ilbc/iLBC_decode.h" 
    35  
     33 
     34#ifdef PJMEDIA_ILBC_CODEC_USE_COREAUDIO 
     35    #include <AudioToolbox/AudioToolbox.h> 
     36    #define iLBC_Enc_Inst_t AudioConverterRef 
     37    #define iLBC_Dec_Inst_t AudioConverterRef 
     38    #define BLOCKL_MAX          1 
     39#else 
     40    #include "../../third_party/ilbc/iLBC_encode.h" 
     41    #include "../../third_party/ilbc/iLBC_decode.h" 
     42#endif 
    3643 
    3744/* 
     
    132139    pj_timestamp         last_tx; 
    133140 
     141 
    134142    pj_bool_t            enc_ready; 
    135143    iLBC_Enc_Inst_t      enc; 
     
    143151    unsigned             dec_samples_per_frame; 
    144152    float                dec_block[BLOCKL_MAX]; 
     153 
     154#ifdef PJMEDIA_ILBC_CODEC_USE_COREAUDIO 
     155    unsigned             enc_total_packets; 
     156    char                 *enc_buffer; 
     157    unsigned             enc_buffer_offset; 
     158 
     159    unsigned             dec_total_packets; 
     160    char                 *dec_buffer; 
     161    unsigned             dec_buffer_offset; 
     162#endif 
    145163}; 
    146164 
     
    353371 
    354372    ilbc_codec = (struct ilbc_codec*) codec; 
     373 
     374#ifdef PJMEDIA_ILBC_CODEC_USE_COREAUDIO 
     375    if (ilbc_codec->enc) { 
     376        AudioConverterDispose(ilbc_codec->enc); 
     377        ilbc_codec->enc = NULL; 
     378    } 
     379    if (ilbc_codec->dec) { 
     380        AudioConverterDispose(ilbc_codec->dec); 
     381        ilbc_codec->dec = NULL; 
     382    } 
     383#endif 
     384 
    355385    pj_pool_release(ilbc_codec->pool); 
    356386 
     
    380410    pj_uint16_t dec_fmtp_mode = DEFAULT_MODE,  
    381411                enc_fmtp_mode = DEFAULT_MODE; 
     412 
     413#ifdef PJMEDIA_ILBC_CODEC_USE_COREAUDIO 
     414    AudioStreamBasicDescription srcFormat, dstFormat; 
     415    UInt32 size; 
     416 
     417    srcFormat.mSampleRate       = attr->info.clock_rate; 
     418    srcFormat.mFormatID         = kAudioFormatLinearPCM; 
     419    srcFormat.mFormatFlags      = kLinearPCMFormatFlagIsSignedInteger 
     420                                  | kLinearPCMFormatFlagIsPacked; 
     421    srcFormat.mBitsPerChannel   = attr->info.pcm_bits_per_sample; 
     422    srcFormat.mChannelsPerFrame = attr->info.channel_cnt; 
     423    srcFormat.mBytesPerFrame    = srcFormat.mChannelsPerFrame 
     424                                  * srcFormat.mBitsPerChannel >> 3; 
     425    srcFormat.mFramesPerPacket  = 1; 
     426    srcFormat.mBytesPerPacket   = srcFormat.mBytesPerFrame * 
     427                                  srcFormat.mFramesPerPacket; 
     428 
     429    memset(&dstFormat, 0, sizeof(dstFormat)); 
     430    dstFormat.mSampleRate       = attr->info.clock_rate; 
     431    dstFormat.mFormatID         = kAudioFormatiLBC; 
     432    dstFormat.mChannelsPerFrame = attr->info.channel_cnt; 
     433#endif 
    382434 
    383435    pj_assert(ilbc_codec != NULL); 
     
    428480 
    429481    /* Create encoder */ 
     482#ifdef PJMEDIA_ILBC_CODEC_USE_COREAUDIO 
     483    dstFormat.mFramesPerPacket  = CLOCK_RATE * enc_fmtp_mode / 1000; 
     484    dstFormat.mBytesPerPacket   = (enc_fmtp_mode == 20? 38 : 50); 
     485 
     486    /* Use AudioFormat API to fill out the rest of the description */ 
     487    size = sizeof(dstFormat); 
     488    AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 
     489                           0, NULL, &size, &dstFormat); 
     490 
     491    if (AudioConverterNew(&srcFormat, &dstFormat, &ilbc_codec->enc) != noErr) 
     492        return PJMEDIA_CODEC_EFAILED; 
     493    ilbc_codec->enc_frame_size = (enc_fmtp_mode == 20? 38 : 50); 
     494#else 
    430495    ilbc_codec->enc_frame_size = initEncode(&ilbc_codec->enc, enc_fmtp_mode); 
     496#endif 
    431497    ilbc_codec->enc_samples_per_frame = CLOCK_RATE * enc_fmtp_mode / 1000; 
    432498    ilbc_codec->enc_ready = PJ_TRUE; 
    433499 
    434500    /* Create decoder */ 
     501#ifdef PJMEDIA_ILBC_CODEC_USE_COREAUDIO 
     502    if (AudioConverterNew(&dstFormat, &srcFormat, &ilbc_codec->dec) != noErr) 
     503        return PJMEDIA_CODEC_EFAILED; 
     504    ilbc_codec->dec_samples_per_frame = CLOCK_RATE * dec_fmtp_mode / 1000; 
     505#else 
    435506    ilbc_codec->dec_samples_per_frame = initDecode(&ilbc_codec->dec, 
    436507                                                   dec_fmtp_mode, 
    437508                                                   attr->setting.penh); 
     509#endif 
    438510    ilbc_codec->dec_frame_size = (dec_fmtp_mode == 20? 38 : 50); 
    439511    ilbc_codec->dec_ready = PJ_TRUE; 
     
    511583        frames[count].size = ilbc_codec->dec_frame_size; 
    512584        frames[count].timestamp.u64 = ts->u64 + count *  
    513                                           ilbc_codec->dec_samples_per_frame; 
     585                                      ilbc_codec->dec_samples_per_frame; 
    514586 
    515587        pkt = ((char*)pkt) + ilbc_codec->dec_frame_size; 
     
    522594    return PJ_SUCCESS; 
    523595} 
     596 
     597#ifdef PJMEDIA_ILBC_CODEC_USE_COREAUDIO 
     598static OSStatus encodeDataProc ( 
     599    AudioConverterRef             inAudioConverter, 
     600    UInt32                        *ioNumberDataPackets, 
     601    AudioBufferList               *ioData, 
     602    AudioStreamPacketDescription  **outDataPacketDescription, 
     603    void                          *inUserData 
     604) 
     605{ 
     606    struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)inUserData; 
     607 
     608    /* Initialize in case of failure */ 
     609    ioData->mBuffers[0].mData = NULL; 
     610    ioData->mBuffers[0].mDataByteSize = 0; 
     611 
     612    if (ilbc_codec->enc_total_packets < *ioNumberDataPackets) { 
     613        *ioNumberDataPackets = ilbc_codec->enc_total_packets; 
     614    } 
     615 
     616    if (*ioNumberDataPackets) { 
     617        ioData->mBuffers[0].mData = ilbc_codec->enc_buffer + 
     618                                    ilbc_codec->enc_buffer_offset; 
     619        ioData->mBuffers[0].mDataByteSize = *ioNumberDataPackets * 
     620                                            ilbc_codec->enc_samples_per_frame 
     621                                            << 1; 
     622        ilbc_codec->enc_buffer_offset += ioData->mBuffers[0].mDataByteSize; 
     623    } 
     624 
     625    ilbc_codec->enc_total_packets -= *ioNumberDataPackets; 
     626    return noErr; 
     627} 
     628 
     629static OSStatus decodeDataProc ( 
     630    AudioConverterRef             inAudioConverter, 
     631    UInt32                        *ioNumberDataPackets, 
     632    AudioBufferList               *ioData, 
     633    AudioStreamPacketDescription  **outDataPacketDescription, 
     634    void                          *inUserData 
     635) 
     636{ 
     637    struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)inUserData; 
     638 
     639    /* Initialize in case of failure */ 
     640    ioData->mBuffers[0].mData = NULL; 
     641    ioData->mBuffers[0].mDataByteSize = 0; 
     642 
     643    if (ilbc_codec->dec_total_packets < *ioNumberDataPackets) { 
     644        *ioNumberDataPackets = ilbc_codec->dec_total_packets; 
     645    } 
     646 
     647    if (*ioNumberDataPackets) { 
     648        ioData->mBuffers[0].mData = ilbc_codec->dec_buffer + 
     649                                    ilbc_codec->dec_buffer_offset; 
     650        ioData->mBuffers[0].mDataByteSize = *ioNumberDataPackets * 
     651                                            ilbc_codec->dec_frame_size; 
     652        ilbc_codec->dec_buffer_offset += ioData->mBuffers[0].mDataByteSize; 
     653    } 
     654 
     655    ilbc_codec->dec_total_packets -= *ioNumberDataPackets; 
     656    return noErr; 
     657} 
     658#endif 
    524659 
    525660/* 
     
    534669    pj_int16_t *pcm_in; 
    535670    unsigned nsamples; 
     671#ifdef PJMEDIA_ILBC_CODEC_USE_COREAUDIO 
     672    UInt32 npackets; 
     673    OSStatus err; 
     674    AudioBufferList theABL; 
     675#endif 
    536676 
    537677    pj_assert(ilbc_codec && input && output); 
     
    574714    /* Encode */ 
    575715    output->size = 0; 
     716#ifdef PJMEDIA_ILBC_CODEC_USE_COREAUDIO 
     717    npackets = nsamples / ilbc_codec->enc_samples_per_frame; 
     718 
     719    theABL.mNumberBuffers = 1; 
     720    theABL.mBuffers[0].mNumberChannels = 1; 
     721    theABL.mBuffers[0].mDataByteSize = output_buf_len; 
     722    theABL.mBuffers[0].mData = output->buf; 
     723 
     724    ilbc_codec->enc_total_packets = npackets; 
     725    ilbc_codec->enc_buffer = (char *)input->buf; 
     726    ilbc_codec->enc_buffer_offset = 0; 
     727 
     728    err = AudioConverterFillComplexBuffer(ilbc_codec->enc, encodeDataProc, 
     729                                          ilbc_codec, &npackets, 
     730                                          &theABL, NULL); 
     731    if (err == noErr) { 
     732        output->size = npackets * ilbc_codec->enc_frame_size; 
     733    } 
     734#else 
    576735    while (nsamples >= ilbc_codec->enc_samples_per_frame) { 
    577736        unsigned i; 
     
    589748        nsamples -= ilbc_codec->enc_samples_per_frame; 
    590749    } 
     750#endif 
    591751 
    592752    output->type = PJMEDIA_FRAME_TYPE_AUDIO; 
     
    605765{ 
    606766    struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec; 
     767#ifdef PJMEDIA_ILBC_CODEC_USE_COREAUDIO 
     768    UInt32 npackets; 
     769    OSStatus err; 
     770    AudioBufferList theABL; 
     771#else 
    607772    unsigned i; 
     773#endif 
    608774 
    609775    pj_assert(ilbc_codec != NULL); 
     
    617783 
    618784    /* Decode to temporary buffer */ 
     785#ifdef PJMEDIA_ILBC_CODEC_USE_COREAUDIO 
     786    npackets = input->size / ilbc_codec->dec_frame_size * 
     787               ilbc_codec->dec_samples_per_frame; 
     788 
     789    theABL.mNumberBuffers = 1; 
     790    theABL.mBuffers[0].mNumberChannels = 1; 
     791    theABL.mBuffers[0].mDataByteSize = output_buf_len; 
     792    theABL.mBuffers[0].mData = output->buf; 
     793 
     794    ilbc_codec->dec_total_packets = npackets; 
     795    ilbc_codec->dec_buffer = (char *)input->buf; 
     796    ilbc_codec->dec_buffer_offset = 0; 
     797 
     798    err = AudioConverterFillComplexBuffer(ilbc_codec->dec, decodeDataProc, 
     799                                          ilbc_codec, &npackets, 
     800                                          &theABL, NULL); 
     801    if (err == noErr) { 
     802        output->size = npackets * (ilbc_codec->dec_samples_per_frame << 1); 
     803    } 
     804#else 
    619805    iLBC_decode(ilbc_codec->dec_block, (unsigned char*) input->buf, 
    620806                &ilbc_codec->dec, 1); 
     
    625811    } 
    626812    output->size = (ilbc_codec->dec_samples_per_frame << 1); 
     813#endif 
     814 
    627815    output->type = PJMEDIA_FRAME_TYPE_AUDIO; 
    628816    output->timestamp = input->timestamp; 
     
    640828{ 
    641829    struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec; 
     830#ifdef PJMEDIA_ILBC_CODEC_USE_COREAUDIO 
     831    UInt32 npackets; 
     832    OSStatus err; 
     833    AudioBufferList theABL; 
     834#else 
    642835    unsigned i; 
     836#endif 
    643837 
    644838    pj_assert(ilbc_codec != NULL); 
     
    649843 
    650844    /* Decode to temporary buffer */ 
     845#ifdef PJMEDIA_ILBC_CODEC_USE_COREAUDIO 
     846    npackets = 1; 
     847 
     848    theABL.mNumberBuffers = 1; 
     849    theABL.mBuffers[0].mNumberChannels = 1; 
     850    theABL.mBuffers[0].mDataByteSize = output_buf_len; 
     851    theABL.mBuffers[0].mData = output->buf; 
     852 
     853    ilbc_codec->dec_total_packets = npackets; 
     854    ilbc_codec->dec_buffer_offset = 0; 
     855    if (ilbc_codec->dec_buffer) { 
     856        err = AudioConverterFillComplexBuffer(ilbc_codec->dec, decodeDataProc, 
     857                                              ilbc_codec, &npackets, 
     858                                              &theABL, NULL); 
     859        if (err == noErr) { 
     860            output->size = npackets * 
     861                           (ilbc_codec->dec_samples_per_frame << 1); 
     862        } 
     863    } else { 
     864        output->size = npackets * (ilbc_codec->dec_samples_per_frame << 1); 
     865        pj_bzero(output->buf, output->size); 
     866    } 
     867#else 
    651868    iLBC_decode(ilbc_codec->dec_block, NULL, &ilbc_codec->dec, 0); 
    652869 
     
    656873    } 
    657874    output->size = (ilbc_codec->dec_samples_per_frame << 1); 
     875#endif 
    658876    output->type = PJMEDIA_FRAME_TYPE_AUDIO; 
    659877 
     
    663881 
    664882#endif  /* PJMEDIA_HAS_ILBC_CODEC */ 
    665  
Note: See TracChangeset for help on using the changeset viewer.