Ignore:
Timestamp:
Feb 5, 2009 10:59:14 AM (12 years ago)
Author:
nanang
Message:
  • Added new API for sound & sound port to create/open sound device with extended setting, to allow opening sound device with non-PCM format and other settings.
  • Updated symbian_ua/ua.cpp to be able to reopen sound device when audio stream session is using non-PCM data/passthrough codec.
  • Updated stream.c to allow it works with non-PCM data.
  • Added PCMU/A frames processing into non-PCM play/record callbacks in symbian_audio_aps.cpp.
  • Added passthrough codec init/deinitialization in pjsua-lib.
  • Added a new pjmedia_frame_ext helper function, pjmedia_frame_ext_pop_subframes, to pop-out/remove some subframes.
  • Other minor updates/fixes.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/stream.c

    r2394 r2438  
    411411 
    412412 
     413/* The other version of get_frame callback used when stream port format 
     414 * is non linear PCM. 
     415 */ 
     416static pj_status_t get_frame_ext( pjmedia_port *port, pjmedia_frame *frame) 
     417{ 
     418    pjmedia_stream *stream = (pjmedia_stream*) port->port_data.pdata; 
     419    pjmedia_channel *channel = stream->dec; 
     420    pjmedia_frame_ext *f = (pjmedia_frame_ext*)frame; 
     421    unsigned samples_per_frame, samples_required; 
     422    pj_status_t status; 
     423 
     424    /* Return no frame if channel is paused */ 
     425    if (channel->paused) { 
     426        frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     427        return PJ_SUCCESS; 
     428    } 
     429 
     430    /* Repeat get frame from the jitter buffer and decode the frame 
     431     * until we have enough frames according to codec's ptime. 
     432     */ 
     433 
     434    samples_required = stream->port.info.samples_per_frame; 
     435    samples_per_frame = stream->codec_param.info.frm_ptime * 
     436                        stream->codec_param.info.clock_rate * 
     437                        stream->codec_param.info.channel_cnt /  
     438                        1000; 
     439 
     440    pj_bzero(f, sizeof(pjmedia_frame_ext)); 
     441    f->base.type = PJMEDIA_FRAME_TYPE_EXTENDED; 
     442 
     443    while (f->samples_cnt < samples_required) { 
     444        char frame_type; 
     445        pj_size_t frame_size; 
     446        pj_uint32_t bit_info; 
     447 
     448        /* Lock jitter buffer mutex first */ 
     449        pj_mutex_lock( stream->jb_mutex ); 
     450 
     451        /* Get frame from jitter buffer. */ 
     452        pjmedia_jbuf_get_frame2(stream->jb, channel->out_pkt, &frame_size, 
     453                                &frame_type, &bit_info); 
     454         
     455        /* Unlock jitter buffer mutex. */ 
     456        pj_mutex_unlock( stream->jb_mutex ); 
     457 
     458        if (frame_type == PJMEDIA_JB_NORMAL_FRAME) { 
     459            /* Got "NORMAL" frame from jitter buffer */ 
     460            pjmedia_frame frame_in; 
     461 
     462            /* Decode */ 
     463            frame_in.buf = channel->out_pkt; 
     464            frame_in.size = frame_size; 
     465            frame_in.bit_info = bit_info; 
     466            frame_in.type = PJMEDIA_FRAME_TYPE_AUDIO; 
     467 
     468            status = stream->codec->op->decode( stream->codec, &frame_in, 
     469                                                0, frame); 
     470            if (status != PJ_SUCCESS) { 
     471                LOGERR_((port->info.name.ptr, "codec decode() error",  
     472                         status)); 
     473                pjmedia_frame_ext_append_subframe(f, NULL, 0, 
     474                                            (pj_uint16_t)samples_per_frame); 
     475            } 
     476        } else { 
     477            status = (*stream->codec->op->recover)(stream->codec, 
     478                                                   0, frame); 
     479            if (status != PJ_SUCCESS) { 
     480                pjmedia_frame_ext_append_subframe(f, NULL, 0, 
     481                                            (pj_uint16_t)samples_per_frame); 
     482            } 
     483 
     484            if (frame_type == PJMEDIA_JB_MISSING_FRAME) { 
     485                PJ_LOG(1,(stream->port.info.name.ptr,  "Frame lost!")); 
     486            } else if (frame_type == PJMEDIA_JB_ZERO_EMPTY_FRAME) { 
     487                /* Jitter buffer is empty. Check if this is the first "empty"  
     488                 * state. 
     489                 */ 
     490                if (frame_type != stream->jb_last_frm) { 
     491                    pjmedia_jb_state jb_state; 
     492 
     493                    /* Report the state of jitter buffer */ 
     494                    pjmedia_jbuf_get_state(stream->jb, &jb_state); 
     495                    PJ_LOG(1,(stream->port.info.name.ptr,  
     496                              "Jitter buffer empty (prefetch=%d)",  
     497                              jb_state.prefetch)); 
     498                } 
     499            } else { 
     500                pjmedia_jb_state jb_state; 
     501 
     502                /* It can only be PJMEDIA_JB_ZERO_PREFETCH frame */ 
     503                pj_assert(frame_type == PJMEDIA_JB_ZERO_PREFETCH_FRAME); 
     504 
     505                /* Get the state of jitter buffer */ 
     506                pjmedia_jbuf_get_state(stream->jb, &jb_state); 
     507 
     508                if (stream->jb_last_frm != frame_type) { 
     509                    PJ_LOG(1,(stream->port.info.name.ptr,  
     510                              "Jitter buffer is bufferring (prefetch=%d)", 
     511                              jb_state.prefetch)); 
     512                } 
     513            } 
     514        } 
     515 
     516        stream->jb_last_frm = frame_type; 
     517    } 
     518 
     519    return PJ_SUCCESS; 
     520} 
     521 
     522 
    413523/* 
    414524 * Transmit DTMF 
     
    689799    if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO) 
    690800        ts_len = (frame->size >> 1) / stream->codec_param.info.channel_cnt; 
     801    else if (frame->type == PJMEDIA_FRAME_TYPE_EXTENDED) 
     802        ts_len = stream->port.info.samples_per_frame /  
     803                 stream->port.info.channel_count; 
    691804    else 
    692805        ts_len = 0; 
     
    755868    } else if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO && 
    756869               frame->buf == NULL && 
     870               (stream->port.info.format.u32 == 0 || 
     871                stream->port.info.format.u32 == PJMEDIA_FOURCC_L16) && 
    757872               (stream->dir & PJMEDIA_DIR_ENCODING) && 
    758873               stream->codec_param.info.frm_ptime * 
     
    14921607    stream->port.info.clock_rate = info->fmt.clock_rate; 
    14931608    stream->port.info.channel_count = info->fmt.channel_cnt; 
     1609    stream->port.info.format = info->param->info.format; 
    14941610    stream->port.port_data.pdata = stream; 
    1495     stream->port.put_frame = &put_frame; 
    1496     stream->port.get_frame = &get_frame; 
     1611    if (stream->port.info.format.u32 == 0 || 
     1612        stream->port.info.format.u32 == PJMEDIA_FOURCC_L16) 
     1613    { 
     1614        stream->port.put_frame = &put_frame; 
     1615        stream->port.get_frame = &get_frame; 
     1616    } else { 
     1617        stream->port.put_frame = &put_frame; 
     1618        stream->port.get_frame = &get_frame_ext; 
     1619    } 
    14971620 
    14981621 
Note: See TracChangeset for help on using the changeset viewer.