Ignore:
Timestamp:
Feb 9, 2009 10:39:58 AM (14 years ago)
Author:
nanang
Message:
  • Added support for codec ILBC, G729, and AMR.
  • Updated audio switch board to make user possible to update its port 0 (master port) attributes, this is needed since sound device need to be reopened (e.g: for changing ptime or codec) while conf is not recreated.
  • Added new API to AMR helper to resolve mode/frame-type based on frame len.
  • Updated pmedia_frame_ext helper functions for a bit optimization.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/symbian_sound_aps.cpp

    r2439 r2444  
    9999    pj_int16_t          *rec_buf; 
    100100    pj_uint16_t          rec_buf_len; 
     101    void                *strm_data; 
    101102}; 
    102103 
     
    696697} 
    697698 
     699/* Pack/unpack G.729 frame of S60 DSP codec, taken from:   
     700 * http://wiki.forum.nokia.com/index.php/TSS000776_-_Payload_conversion_for_G.729_audio_format 
     701 */ 
     702#include "s60_g729_bitstream.h" 
     703#include <pjmedia-codec/amr_helper.h> 
     704 
    698705static void RecCb(TAPSCommBuffer &buf, void *user_data) 
    699706{ 
    700707    pjmedia_snd_stream *strm = (pjmedia_snd_stream*) user_data; 
    701708    pjmedia_frame_ext *frame = (pjmedia_frame_ext*) strm->rec_buf; 
    702     unsigned samples_processed = 0; 
    703  
     709     
    704710    switch(strm->setting.format.u32) { 
    705      
    706     case PJMEDIA_FOURCC_G711U: 
    707     case PJMEDIA_FOURCC_G711A: 
    708         pj_assert(buf.iBuffer[0] == 1 && buf.iBuffer[1] == 0); 
    709  
    710         /* Detect the recorder G.711 frame size, player frame size will follow 
    711          * this recorder frame size. 
    712          */ 
    713         if (aps_g711_frame_len == 0) { 
    714             aps_g711_frame_len = buf.iBuffer.Length() < 160? 80 : 160; 
    715             TRACE_((THIS_FILE, "Detected APS G.711 frame size = %u samples", 
    716                     aps_g711_frame_len)); 
    717         } 
    718          
    719         /* Convert APS buffer format into pjmedia_frame_ext. Whenever  
    720          * samples count in the frame is equal to stream's samples per frame, 
    721          * call parent stream callback. 
    722          */ 
    723         while (samples_processed < aps_g711_frame_len) { 
    724             unsigned tmp; 
    725             const pj_uint8_t *pb = (const pj_uint8_t*)buf.iBuffer.Ptr() + 2 + 
    726                                    samples_processed; 
    727  
    728             tmp = PJ_MIN(strm->samples_per_frame - frame->samples_cnt, 
    729                          aps_g711_frame_len - samples_processed); 
     711    case PJMEDIA_FOURCC_AMR: 
     712        { 
     713            const pj_uint8_t *p = (const pj_uint8_t*)buf.iBuffer.Ptr() + 1; 
     714            unsigned len = buf.iBuffer.Length() - 1; 
    730715             
    731             pjmedia_frame_ext_append_subframe(frame, pb, tmp << 3, tmp); 
    732             samples_processed += tmp; 
    733  
     716            pjmedia_frame_ext_append_subframe(frame, p, len << 3, 160); 
    734717            if (frame->samples_cnt == strm->samples_per_frame) { 
    735718                frame->base.type = PJMEDIA_FRAME_TYPE_EXTENDED; 
     
    741724        break; 
    742725         
     726    case PJMEDIA_FOURCC_G729: 
     727        { 
     728            /* Check if we got a normal or SID frame. */ 
     729            if (buf.iBuffer[0] != 0 || buf.iBuffer[1] != 0) { 
     730                enum { NORMAL_LEN = 22, SID_LEN = 8 }; 
     731                TBitStream *bitstream = (TBitStream*)strm->strm_data; 
     732                unsigned src_len = buf.iBuffer.Length()- 2; 
     733                 
     734                pj_assert(src_len == NORMAL_LEN || src_len == SID_LEN); 
     735 
     736                const TDesC8& p = bitstream->CompressG729Frame( 
     737                                            buf.iBuffer.Right(src_len),  
     738                                            src_len == SID_LEN); 
     739                 
     740                pjmedia_frame_ext_append_subframe(frame, p.Ptr(),  
     741                                                  p.Length() << 3, 80); 
     742            } else { /* We got null frame. */ 
     743                pjmedia_frame_ext_append_subframe(frame, NULL, 0, 80); 
     744            } 
     745             
     746            if (frame->samples_cnt == strm->samples_per_frame) { 
     747                frame->base.type = PJMEDIA_FRAME_TYPE_EXTENDED; 
     748                strm->rec_cb(strm->user_data, 0, strm->rec_buf, 0); 
     749                frame->samples_cnt = 0; 
     750                frame->subframe_cnt = 0; 
     751            } 
     752        } 
     753        break; 
     754 
     755    case PJMEDIA_FOURCC_ILBC: 
     756        { 
     757            unsigned samples_got; 
     758             
     759            samples_got = strm->setting.mode == 30? 240 : 160; 
     760             
     761            /* Check if we got a normal frame. */ 
     762            if (buf.iBuffer[0] == 1 && buf.iBuffer[1] == 0) { 
     763                const pj_uint8_t *p = (const pj_uint8_t*)buf.iBuffer.Ptr() + 2; 
     764                unsigned len = buf.iBuffer.Length() - 2; 
     765                 
     766                pjmedia_frame_ext_append_subframe(frame, p, len << 3, 
     767                                                  samples_got); 
     768            } else { /* We got null frame. */ 
     769                pjmedia_frame_ext_append_subframe(frame, NULL, 0, samples_got); 
     770            } 
     771             
     772            if (frame->samples_cnt == strm->samples_per_frame) { 
     773                frame->base.type = PJMEDIA_FRAME_TYPE_EXTENDED; 
     774                strm->rec_cb(strm->user_data, 0, strm->rec_buf, 0); 
     775                frame->samples_cnt = 0; 
     776                frame->subframe_cnt = 0; 
     777            } 
     778        } 
     779        break; 
     780         
     781    case PJMEDIA_FOURCC_G711U: 
     782    case PJMEDIA_FOURCC_G711A: 
     783        { 
     784            unsigned samples_processed = 0; 
     785             
     786            /* Make sure it is normal frame. */ 
     787            pj_assert(buf.iBuffer[0] == 1 && buf.iBuffer[1] == 0); 
     788 
     789            /* Detect the recorder G.711 frame size, player frame size will  
     790             * follow this recorder frame size. 
     791             */ 
     792            if (aps_g711_frame_len == 0) { 
     793                aps_g711_frame_len = buf.iBuffer.Length() < 160? 80 : 160; 
     794                TRACE_((THIS_FILE, "Detected APS G.711 frame size = %u samples", 
     795                        aps_g711_frame_len)); 
     796            } 
     797             
     798            /* Convert APS buffer format into pjmedia_frame_ext. Whenever  
     799             * samples count in the frame is equal to stream's samples per  
     800             * frame, call parent stream callback. 
     801             */ 
     802            while (samples_processed < aps_g711_frame_len) { 
     803                unsigned tmp; 
     804                const pj_uint8_t *pb = (const pj_uint8_t*)buf.iBuffer.Ptr() + 
     805                                       2 + samples_processed; 
     806     
     807                tmp = PJ_MIN(strm->samples_per_frame - frame->samples_cnt, 
     808                             aps_g711_frame_len - samples_processed); 
     809                 
     810                pjmedia_frame_ext_append_subframe(frame, pb, tmp << 3, tmp); 
     811                samples_processed += tmp; 
     812     
     813                if (frame->samples_cnt == strm->samples_per_frame) { 
     814                    frame->base.type = PJMEDIA_FRAME_TYPE_EXTENDED; 
     815                    strm->rec_cb(strm->user_data, 0, strm->rec_buf, 0); 
     816                    frame->samples_cnt = 0; 
     817                    frame->subframe_cnt = 0; 
     818                } 
     819            } 
     820        } 
     821        break; 
     822         
    743823    default: 
    744824        break; 
     
    750830    pjmedia_snd_stream *strm = (pjmedia_snd_stream*) user_data; 
    751831    pjmedia_frame_ext *frame = (pjmedia_frame_ext*) strm->play_buf; 
    752     unsigned g711_frame_len = aps_g711_frame_len; 
    753     unsigned samples_ready = 0; 
    754832 
    755833    /* Init buffer attributes and header. */ 
     
    759837 
    760838    switch(strm->setting.format.u32) { 
     839    case PJMEDIA_FOURCC_AMR: 
     840        { 
     841            if (frame->samples_cnt == 0) { 
     842                frame->base.type = PJMEDIA_FRAME_TYPE_EXTENDED; 
     843                strm->play_cb(strm->user_data, 0, strm->play_buf, 0); 
     844                 
     845                pj_assert(frame->base.type==PJMEDIA_FRAME_TYPE_EXTENDED || 
     846                          frame->base.type==PJMEDIA_FRAME_TYPE_NONE); 
     847            } 
     848 
     849            if (frame->base.type == PJMEDIA_FRAME_TYPE_EXTENDED) {  
     850                pjmedia_frame_ext_subframe *sf; 
     851                unsigned samples_cnt; 
     852                 
     853                sf = pjmedia_frame_ext_get_subframe(frame, 0); 
     854                samples_cnt = frame->samples_cnt / frame->subframe_cnt; 
     855                 
     856                if (sf->data && sf->bitlen) { 
     857                    /* AMR header for APS is one byte, the format (may be!): 
     858                     * 0xxxxy00, where xxxx:frame type, y:not sure.  
     859                     */ 
     860                    unsigned len = sf->bitlen>>3; 
     861                    enum {SID_FT = 8 }; 
     862                    pj_uint8_t amr_header = 4, ft = SID_FT; 
     863 
     864                    if (sf->bitlen & 0x07) 
     865                        ++len; 
     866 
     867                    if (len >= pjmedia_codec_amrnb_framelen[0]) 
     868                        ft = pjmedia_codec_amr_get_mode2(PJ_TRUE, len); 
     869                     
     870                    amr_header |= ft << 3; 
     871                    buf.iBuffer.Append(amr_header); 
     872                     
     873                    buf.iBuffer.Append((TUint8*)sf->data, len); 
     874                } else { 
     875                    buf.iBuffer.Append(0); 
     876                } 
     877 
     878                pjmedia_frame_ext_pop_subframes(frame, 1); 
     879             
     880            } else { /* PJMEDIA_FRAME_TYPE_NONE */ 
     881                buf.iBuffer.Append(0); 
     882                 
     883                frame->samples_cnt = 0; 
     884                frame->subframe_cnt = 0; 
     885            } 
     886        } 
     887        break; 
     888         
     889    case PJMEDIA_FOURCC_G729: 
     890        { 
     891            if (frame->samples_cnt == 0) { 
     892                frame->base.type = PJMEDIA_FRAME_TYPE_EXTENDED; 
     893                strm->play_cb(strm->user_data, 0, strm->play_buf, 0); 
     894                 
     895                pj_assert(frame->base.type==PJMEDIA_FRAME_TYPE_EXTENDED || 
     896                          frame->base.type==PJMEDIA_FRAME_TYPE_NONE); 
     897            } 
     898 
     899            if (frame->base.type == PJMEDIA_FRAME_TYPE_EXTENDED) {  
     900                pjmedia_frame_ext_subframe *sf; 
     901                unsigned samples_cnt; 
     902                 
     903                sf = pjmedia_frame_ext_get_subframe(frame, 0); 
     904                samples_cnt = frame->samples_cnt / frame->subframe_cnt; 
     905                 
     906                if (sf->data && sf->bitlen) { 
     907                    enum { NORMAL_LEN = 10, SID_LEN = 2 }; 
     908                    pj_bool_t sid_frame = ((sf->bitlen >> 3) == SID_LEN); 
     909                    TBitStream *bitstream = (TBitStream*)strm->strm_data; 
     910                    const TPtrC8 src(sf->data, sf->bitlen>>3); 
     911                    const TDesC8 &dst = bitstream->ExpandG729Frame(src, 
     912                                                                   sid_frame);  
     913                    if (sid_frame) { 
     914                        buf.iBuffer.Append(0); 
     915                        buf.iBuffer.Append(1); 
     916                    } else { 
     917                        buf.iBuffer.Append(1); 
     918                        buf.iBuffer.Append(0); 
     919                    } 
     920                    buf.iBuffer.Append(dst); 
     921                } else { 
     922                    buf.iBuffer.Append(0); 
     923                    buf.iBuffer.Append(0); 
     924                } 
     925 
     926                pjmedia_frame_ext_pop_subframes(frame, 1); 
     927             
     928            } else { /* PJMEDIA_FRAME_TYPE_NONE */ 
     929                buf.iBuffer.Append(0); 
     930                buf.iBuffer.Append(0); 
     931                 
     932                frame->samples_cnt = 0; 
     933                frame->subframe_cnt = 0; 
     934            } 
     935        } 
     936        break; 
     937         
     938    case PJMEDIA_FOURCC_ILBC: 
     939        { 
     940            if (frame->samples_cnt == 0) { 
     941                frame->base.type = PJMEDIA_FRAME_TYPE_EXTENDED; 
     942                strm->play_cb(strm->user_data, 0, strm->play_buf, 0); 
     943                 
     944                pj_assert(frame->base.type==PJMEDIA_FRAME_TYPE_EXTENDED || 
     945                          frame->base.type==PJMEDIA_FRAME_TYPE_NONE); 
     946            } 
     947 
     948            if (frame->base.type == PJMEDIA_FRAME_TYPE_EXTENDED) {  
     949                pjmedia_frame_ext_subframe *sf; 
     950                unsigned samples_cnt; 
     951                 
     952                sf = pjmedia_frame_ext_get_subframe(frame, 0); 
     953                samples_cnt = frame->samples_cnt / frame->subframe_cnt; 
     954                pj_assert((strm->setting.mode == 30 && samples_cnt == 240) || 
     955                          (strm->setting.mode == 20 && samples_cnt == 160)); 
     956                 
     957                if (sf->data && sf->bitlen) { 
     958                    buf.iBuffer.Append(1); 
     959                    buf.iBuffer.Append(0); 
     960                    buf.iBuffer.Append((TUint8*)sf->data, sf->bitlen>>3); 
     961                } else { 
     962                    buf.iBuffer.Append(0); 
     963                    buf.iBuffer.Append(0); 
     964                } 
     965 
     966                pjmedia_frame_ext_pop_subframes(frame, 1); 
     967             
     968            } else { /* PJMEDIA_FRAME_TYPE_NONE */ 
     969                buf.iBuffer.Append(0); 
     970                buf.iBuffer.Append(0); 
     971                 
     972                frame->samples_cnt = 0; 
     973                frame->subframe_cnt = 0; 
     974            } 
     975        } 
     976        break; 
     977         
    761978    case PJMEDIA_FOURCC_G711U: 
    762979    case PJMEDIA_FOURCC_G711A: 
    763980        { 
    764             /* Add header. */ 
    765             buf.iBuffer.Append(1); 
    766             buf.iBuffer.Append(0); 
    767      
     981            unsigned samples_ready = 0; 
     982            unsigned samples_req = aps_g711_frame_len; 
     983             
    768984            /* Assume frame size is 10ms if frame size hasn't been known. */ 
    769             if (g711_frame_len == 0) 
    770                 g711_frame_len = 80; 
     985            if (samples_req == 0) 
     986                samples_req = 80; 
    771987             
    772988            /* Call parent stream callback to get samples to play. */ 
    773             while (samples_ready < g711_frame_len) { 
     989            while (samples_ready < samples_req) { 
    774990                if (frame->samples_cnt == 0) { 
    775991                    frame->base.type = PJMEDIA_FRAME_TYPE_EXTENDED; 
    776                     strm->play_cb(strm->user_data, 0, strm->play_buf, 
    777                                   strm->samples_per_frame<<1); 
     992                    strm->play_cb(strm->user_data, 0, strm->play_buf, 0); 
    778993                     
    779994                    pj_assert(frame->base.type==PJMEDIA_FRAME_TYPE_EXTENDED || 
     
    7871002                    sf = pjmedia_frame_ext_get_subframe(frame, 0); 
    7881003                    samples_cnt = frame->samples_cnt / frame->subframe_cnt; 
    789                     if (sf->data && sf->bitlen) 
     1004                    if (sf->data && sf->bitlen) { 
     1005                        buf.iBuffer.Append(1); 
     1006                        buf.iBuffer.Append(0); 
    7901007                        buf.iBuffer.Append((TUint8*)sf->data, sf->bitlen>>3); 
    791                     else { 
    792                         pj_uint8_t silence_code; 
    793                          
    794                         if (strm->setting.format.u32 == PJMEDIA_FOURCC_G711U) 
    795                             silence_code = pjmedia_linear2ulaw(0); 
    796                         else 
    797                             silence_code = pjmedia_linear2alaw(0); 
    798                          
    799                         buf.iBuffer.AppendFill(silence_code, samples_cnt); 
     1008                    } else { 
     1009                        buf.iBuffer.Append(0); 
     1010                        buf.iBuffer.Append(0); 
    8001011                    } 
    8011012                    samples_ready += samples_cnt; 
     
    8041015                 
    8051016                } else { /* PJMEDIA_FRAME_TYPE_NONE */ 
    806                     pj_uint8_t silence_code; 
    807                      
    808                     if (strm->setting.format.u32 == PJMEDIA_FOURCC_G711U) 
    809                         silence_code = pjmedia_linear2ulaw(0); 
    810                     else 
    811                         silence_code = pjmedia_linear2alaw(0); 
    812                      
    813                     buf.iBuffer.AppendFill(silence_code,  
    814                                            g711_frame_len - samples_ready); 
    815                     samples_ready = g711_frame_len; 
     1017                    buf.iBuffer.Append(0); 
     1018                    buf.iBuffer.Append(0); 
     1019 
     1020                    samples_ready = samples_req; 
    8161021                    frame->samples_cnt = 0; 
    8171022                    frame->subframe_cnt = 0; 
     
    9221127    } 
    9231128 
    924     aps_setting.vad = strm->setting.format.u32==PJMEDIA_FOURCC_L16?  
    925                                         EFalse : strm->setting.vad; 
     1129    /* Disable VAD on L16 and G711. */ 
     1130    if (strm->setting.format.u32 == PJMEDIA_FOURCC_L16 || 
     1131        strm->setting.format.u32 == PJMEDIA_FOURCC_G711U || 
     1132        strm->setting.format.u32 == PJMEDIA_FOURCC_G711A) 
     1133    { 
     1134        aps_setting.vad = EFalse; 
     1135    } else { 
     1136        aps_setting.vad = strm->setting.vad; 
     1137    } 
     1138     
    9261139    aps_setting.plc = strm->setting.plc; 
    9271140    aps_setting.cng = strm->setting.cng; 
     
    9581171    strm->rec_buf_len = 0; 
    9591172 
     1173    if (strm->setting.format.u32 == PJMEDIA_FOURCC_G729) { 
     1174        TBitStream *g729_bitstream = new TBitStream; 
     1175         
     1176        PJ_ASSERT_RETURN(g729_bitstream, PJ_ENOMEM); 
     1177        strm->strm_data = (void*)g729_bitstream; 
     1178    } 
     1179         
    9601180    // Done. 
    9611181    *p_snd_strm = strm; 
     
    9841204    pj_bzero(&setting, sizeof(setting)); 
    9851205    setting.format.u32 = PJMEDIA_FOURCC_L16; 
    986     setting.bitrate = 128000; 
    9871206     
    9881207    return sound_open(PJMEDIA_DIR_CAPTURE, clock_rate, channel_count, 
     
    10071226    pj_bzero(&setting, sizeof(setting)); 
    10081227    setting.format.u32 = PJMEDIA_FOURCC_L16; 
    1009     setting.bitrate = 128000; 
    10101228 
    10111229    return sound_open(PJMEDIA_DIR_PLAYBACK, clock_rate, channel_count, 
     
    10331251    pj_bzero(&setting, sizeof(setting)); 
    10341252    setting.format.u32 = PJMEDIA_FOURCC_L16; 
    1035     setting.bitrate = 128000; 
    10361253 
    10371254    return sound_open(PJMEDIA_DIR_CAPTURE_PLAYBACK, clock_rate, channel_count, 
     
    11211338    stream->engine = NULL; 
    11221339 
     1340    if (stream->setting.format.u32 == PJMEDIA_FOURCC_G729) { 
     1341        TBitStream *g729_bitstream = (TBitStream*)stream->strm_data; 
     1342        stream->strm_data = NULL; 
     1343        delete g729_bitstream; 
     1344    } 
     1345 
    11231346    pool = stream->pool; 
    11241347    if (pool) { 
Note: See TracChangeset for help on using the changeset viewer.