Ignore:
Timestamp:
Sep 29, 2011 8:31:15 AM (13 years ago)
Author:
bennylp
Message:

Closed #1361: codec API change. Details:

  • changed encode(), packetize(), unpacketize(), and decode() to encode_begin(), encode_more(), and decode()
  • codec has new "packing" setting
  • updated stream, aviplay, codec-test, and stream-util due to above
  • minor doxygen documentation fixes here and there
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/vid_stream.c

    r3667 r3776  
    124124    unsigned                 frame_ts_len;  /**< Frame length in timestamp. */ 
    125125 
     126    unsigned                 rx_frame_cnt;  /**< # of array in rx_frames    */ 
     127    pjmedia_frame           *rx_frames;     /**< Temp. buffer for incoming 
     128                                                 frame assembly.            */ 
     129 
    126130#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0 
    127131    pj_bool_t                use_ka;           /**< Stream keep-alive with non- 
     
    732736    void *rtphdr; 
    733737    int rtphdrlen; 
    734     unsigned processed = 0; 
     738    pj_bool_t has_more_data = PJ_FALSE; 
     739    pj_size_t total_sent = 0; 
    735740 
    736741 
     
    767772 
    768773    /* Encode! */ 
    769     status = pjmedia_vid_codec_encode(stream->codec, frame,  
    770                                       channel->buf_size -  
    771                                       sizeof(pjmedia_rtp_hdr), 
    772                                       &frame_out); 
     774    status = pjmedia_vid_codec_encode_begin(stream->codec, frame, 
     775                                            channel->buf_size - 
     776                                               sizeof(pjmedia_rtp_hdr), 
     777                                            &frame_out, 
     778                                            &has_more_data); 
    773779    if (status != PJ_SUCCESS) { 
    774         LOGERR_((channel->port.info.name.ptr,  
    775                 "Codec encode() error", status)); 
     780        LOGERR_((channel->port.info.name.ptr, 
     781                "Codec encode_begin() error", status)); 
    776782 
    777783        /* Update RTP timestamp */ 
    778784        pjmedia_rtp_encode_rtp(&channel->rtp, channel->pt, 1, 0, 
    779                                rtp_ts_len,  (const void**)&rtphdr, &rtphdrlen); 
    780         return status; 
    781     } 
    782  
    783  
    784     while (processed < frame_out.size) { 
    785         pj_uint8_t *payload; 
    786         pj_uint8_t *rtp_pkt; 
    787         pj_size_t payload_len; 
    788  
    789         /* Generate RTP payload */ 
    790         status = pjmedia_vid_codec_packetize(stream->codec, 
    791                                              (pj_uint8_t*)frame_out.buf, 
    792                                              frame_out.size, 
    793                                              &processed, 
    794                                              (const pj_uint8_t**)&payload, 
    795                                              &payload_len); 
    796         if (status != PJ_SUCCESS) { 
    797             LOGERR_((channel->port.info.name.ptr,  
    798                     "Codec pack() error", status)); 
    799  
    800             /* Update RTP timestamp */ 
    801             pjmedia_rtp_encode_rtp(&channel->rtp, channel->pt, 1, 0, 
    802                                    rtp_ts_len,  (const void**)&rtphdr, 
    803                                    &rtphdrlen); 
    804             return status; 
    805         } 
    806  
    807         /* Encapsulate. */ 
    808         status = pjmedia_rtp_encode_rtp( &channel->rtp,  
    809                                          channel->pt, 
    810                                          (processed==frame_out.size?1:0), 
    811                                          payload_len, 
    812                                          rtp_ts_len,  
    813                                          (const void**)&rtphdr,  
    814                                          &rtphdrlen); 
    815  
    816         if (status != PJ_SUCCESS) { 
    817             LOGERR_((channel->port.info.name.ptr,  
     785                               rtp_ts_len,  (const void**)&rtphdr, 
     786                               &rtphdrlen); 
     787        return status; 
     788    } 
     789 
     790    /* Loop while we have frame to send */ 
     791    for (;;) { 
     792        status = pjmedia_rtp_encode_rtp(&channel->rtp, 
     793                                        channel->pt, 
     794                                        (has_more_data == PJ_FALSE ? 1 : 0), 
     795                                        frame_out.size, 
     796                                        rtp_ts_len, 
     797                                        (const void**)&rtphdr, 
     798                                        &rtphdrlen); 
     799        if (status != PJ_SUCCESS) { 
     800            LOGERR_((channel->port.info.name.ptr, 
    818801                    "RTP encode_rtp() error", status)); 
    819802            return status; 
    820         } 
    821  
    822         /* Next packets use same timestamp */ 
    823         rtp_ts_len = 0; 
    824  
    825         rtp_pkt = payload - sizeof(pjmedia_rtp_hdr); 
    826  
    827         /* Copy RTP header to the beginning of packet */ 
    828         pj_memcpy(rtp_pkt, rtphdr, sizeof(pjmedia_rtp_hdr)); 
    829  
    830         /* Send the RTP packet to the transport. */ 
    831         pjmedia_transport_send_rtp(stream->transport, rtp_pkt,  
    832                                    payload_len + sizeof(pjmedia_rtp_hdr)); 
     803        } 
     804 
     805        // Copy RTP header to the beginning of packet 
     806        pj_memcpy(channel->buf, rtphdr, sizeof(pjmedia_rtp_hdr)); 
     807 
     808        // Send the RTP packet to the transport. 
     809        status = pjmedia_transport_send_rtp(stream->transport, 
     810                                            (char*)channel->buf, 
     811                                            frame_out.size + 
     812                                                sizeof(pjmedia_rtp_hdr)); 
     813        if (status != PJ_SUCCESS) { 
     814            LOGERR_((channel->port.info.name.ptr, 
     815                     "Transport send_rtp() error", status)); 
     816            /* Ignore this error */ 
     817        } 
     818 
     819        total_sent += frame_out.size; 
     820 
     821        if (!has_more_data) 
     822            break; 
     823 
     824        /* Next packets use same timestamp */ 
     825        rtp_ts_len = 0; 
     826 
     827        frame_out.size = 0; 
     828 
     829        /* Encode more! */ 
     830        status = pjmedia_vid_codec_encode_more(stream->codec, 
     831                                               channel->buf_size - 
     832                                                   sizeof(pjmedia_rtp_hdr), 
     833                                               &frame_out, 
     834                                               &has_more_data); 
     835        if (status != PJ_SUCCESS) { 
     836            LOGERR_((channel->port.info.name.ptr, 
     837                     "Codec encode_more() error", status)); 
     838            /* Ignore this error (?) */ 
     839            break; 
     840        } 
    833841    } 
    834842 
     
    842850 
    843851    /* Do nothing if we have nothing to transmit */ 
    844     if (frame_out.size == 0) { 
     852    if (total_sent == 0) { 
    845853        return PJ_SUCCESS; 
    846854    } 
    847855 
    848856    /* Update stat */ 
    849     pjmedia_rtcp_tx_rtp(&stream->rtcp, frame_out.size); 
     857    pjmedia_rtcp_tx_rtp(&stream->rtcp, total_sent); 
    850858    stream->rtcp.stat.rtp_tx_last_ts = pj_ntohl(stream->enc->rtp.out_hdr.ts); 
    851859    stream->rtcp.stat.rtp_tx_last_seq = pj_ntohs(stream->enc->rtp.out_hdr.seq); 
     
    864872    pjmedia_vid_stream *stream = (pjmedia_vid_stream*) port->port_data.pdata; 
    865873    pjmedia_vid_channel *channel = stream->dec; 
    866     pjmedia_frame frame_in; 
    867874    pj_uint32_t last_ts = 0; 
    868875    int frm_first_seq = 0, frm_last_seq = 0; 
     876    pj_bool_t got_frame = PJ_FALSE; 
     877    unsigned cnt; 
    869878    pj_status_t status; 
    870879 
     
    876885 
    877886    /* Repeat get payload from the jitter buffer until all payloads with same 
    878      * timestamp are collected (a complete frame unpacketized). 
     887     * timestamp are collected. 
    879888     */ 
    880     { 
    881         pj_bool_t got_frame; 
    882         unsigned cnt; 
    883  
    884         channel->buf_len = 0; 
    885         got_frame = PJ_FALSE; 
    886  
    887         /* Lock jitter buffer mutex first */ 
    888         pj_mutex_lock( stream->jb_mutex ); 
    889  
    890         /* Check if we got a decodable frame */ 
    891         for (cnt=0; ; ++cnt) { 
    892             char ptype; 
    893             pj_uint32_t ts; 
    894             int seq; 
    895  
    896             /* Peek frame from jitter buffer. */ 
    897             pjmedia_jbuf_peek_frame(stream->jb, cnt, NULL, NULL, 
    898                                     &ptype, NULL, &ts, &seq); 
    899             if (ptype == PJMEDIA_JB_NORMAL_FRAME) { 
    900                 if (last_ts == 0) { 
    901                     last_ts = ts; 
    902                     frm_first_seq = seq; 
    903                 } 
    904                 if (ts != last_ts) { 
    905                     got_frame = PJ_TRUE; 
    906                     break; 
    907                 } 
    908                 frm_last_seq = seq; 
    909             } else if (ptype == PJMEDIA_JB_ZERO_EMPTY_FRAME) { 
    910                 /* No more packet in the jitter buffer */ 
     889    channel->buf_len = 0; 
     890 
     891    /* Lock jitter buffer mutex first */ 
     892    pj_mutex_lock( stream->jb_mutex ); 
     893 
     894    /* Check if we got a decodable frame */ 
     895    for (cnt=0; ; ++cnt) { 
     896        char ptype; 
     897        pj_uint32_t ts; 
     898        int seq; 
     899 
     900        /* Peek frame from jitter buffer. */ 
     901        pjmedia_jbuf_peek_frame(stream->jb, cnt, NULL, NULL, 
     902                                &ptype, NULL, &ts, &seq); 
     903        if (ptype == PJMEDIA_JB_NORMAL_FRAME) { 
     904            if (last_ts == 0) { 
     905                last_ts = ts; 
     906                frm_first_seq = seq; 
     907            } 
     908            if (ts != last_ts) { 
     909                got_frame = PJ_TRUE; 
    911910                break; 
    912911            } 
     912            frm_last_seq = seq; 
     913        } else if (ptype == PJMEDIA_JB_ZERO_EMPTY_FRAME) { 
     914            /* No more packet in the jitter buffer */ 
     915            break; 
    913916        } 
    914  
    915         if (got_frame) { 
    916             unsigned i; 
    917  
    918             /* Generate frame bitstream from the payload */ 
    919             channel->buf_len = 0; 
    920             for (i = 0; i < cnt; ++i) { 
    921                 const pj_uint8_t *p; 
    922                 pj_size_t psize; 
    923                 char ptype; 
    924  
    925                 /* We use jbuf_peek_frame() as it will returns the pointer of 
    926                  * the payload (no buffer and memcpy needed), just as we need. 
    927                  */ 
    928                 pjmedia_jbuf_peek_frame(stream->jb, i, (const void**)&p, 
    929                                         &psize, &ptype, NULL, NULL, NULL); 
    930  
    931                 if (ptype != PJMEDIA_JB_NORMAL_FRAME) { 
    932                     /* Packet lost, must set payload to NULL and keep going */ 
    933                     p = NULL; 
    934                     psize = 0; 
    935                 } 
    936  
    937                 status = pjmedia_vid_codec_unpacketize( 
    938                                                 stream->codec, 
    939                                                 p, psize, 
    940                                                 (pj_uint8_t*)channel->buf, 
    941                                                 channel->buf_size, 
    942                                                 &channel->buf_len); 
    943                 if (status != PJ_SUCCESS) { 
    944                     LOGERR_((channel->port.info.name.ptr,  
    945                             "Codec unpack() error", status)); 
    946                     /* Just ignore this unpack error */ 
    947                 } 
     917    } 
     918 
     919    if (got_frame) { 
     920        unsigned i; 
     921 
     922        /* Generate frame bitstream from the payload */ 
     923        channel->buf_len = 0; 
     924 
     925        if (cnt > stream->rx_frame_cnt) { 
     926            PJ_LOG(1,(port->info.name.ptr, 
     927                      "Discarding %u frames because array is full!", 
     928                      cnt - stream->rx_frame_cnt)); 
     929            pjmedia_jbuf_remove_frame(stream->jb, cnt - stream->rx_frame_cnt); 
     930            cnt = stream->rx_frame_cnt; 
     931        } 
     932 
     933        for (i = 0; i < cnt; ++i) { 
     934            char ptype; 
     935 
     936            stream->rx_frames[i].type = PJMEDIA_FRAME_TYPE_VIDEO; 
     937            stream->rx_frames[i].timestamp.u64 = last_ts; 
     938            stream->rx_frames[i].bit_info = 0; 
     939 
     940            /* We use jbuf_peek_frame() as it will returns the pointer of 
     941             * the payload (no buffer and memcpy needed), just as we need. 
     942             */ 
     943            pjmedia_jbuf_peek_frame(stream->jb, i, 
     944                                    (const void**)&stream->rx_frames[i].buf, 
     945                                    &stream->rx_frames[i].size, &ptype, 
     946                                    NULL, NULL, NULL); 
     947 
     948            if (ptype != PJMEDIA_JB_NORMAL_FRAME) { 
     949                /* Packet lost, must set payload to NULL and keep going */ 
     950                stream->rx_frames[i].buf = NULL; 
     951                stream->rx_frames[i].size = 0; 
     952                stream->rx_frames[i].type = PJMEDIA_FRAME_TYPE_NONE; 
     953                continue; 
    948954            } 
    949  
    950             pjmedia_jbuf_remove_frame(stream->jb, cnt); 
    951955        } 
    952956 
    953         /* Unlock jitter buffer mutex. */ 
    954         pj_mutex_unlock( stream->jb_mutex ); 
    955  
    956         if (!got_frame) { 
     957        /* Decode */ 
     958        status = pjmedia_vid_codec_decode(stream->codec, cnt, 
     959                                          stream->rx_frames, 
     960                                          frame->size, frame); 
     961        if (status != PJ_SUCCESS) { 
     962            LOGERR_((port->info.name.ptr, "codec decode() error", 
     963                     status)); 
    957964            frame->type = PJMEDIA_FRAME_TYPE_NONE; 
    958965            frame->size = 0; 
    959             return PJ_SUCCESS; 
    960966        } 
    961     } 
    962  
    963     /* Decode */ 
    964     frame_in.buf = channel->buf; 
    965     frame_in.size = channel->buf_len; 
    966     frame_in.bit_info = 0; 
    967     frame_in.type = PJMEDIA_FRAME_TYPE_VIDEO; 
    968     frame_in.timestamp.u64 = last_ts; 
    969  
    970     status = pjmedia_vid_codec_decode(stream->codec, &frame_in, 
    971                                       frame->size, frame); 
    972     if (status != PJ_SUCCESS) { 
    973         LOGERR_((port->info.name.ptr, "codec decode() error",  
    974                  status)); 
    975         frame->type = PJMEDIA_FRAME_TYPE_NONE; 
    976         frame->size = 0; 
    977     } 
     967 
     968        pjmedia_jbuf_remove_frame(stream->jb, cnt); 
     969    } 
     970 
     971    /* Unlock jitter buffer mutex. */ 
     972    pj_mutex_unlock( stream->jb_mutex ); 
    978973 
    979974    /* Learn remote frame rate after successful decoding */ 
     
    10141009 
    10151010                    pjmedia_event_init(&event, PJMEDIA_EVENT_FMT_CHANGED, 
    1016                                        &frame_in.timestamp, &stream->epub); 
     1011                                       &frame->timestamp, &stream->epub); 
    10171012                    event.data.fmt_changed.dir = PJMEDIA_DIR_DECODING; 
    10181013                    pj_memcpy(&event.data.fmt_changed.new_fmt, 
     
    11571152    pjmedia_video_format_detail *vfd_enc; 
    11581153    char *p; 
     1154    unsigned mtu; 
    11591155    pj_status_t status; 
    11601156 
     
    11881184        return status; 
    11891185 
    1190  
    11911186    /* Get codec param: */ 
    11921187    if (!info->codec_param) { 
     
    12021197        pj_assert(info->codec_param); 
    12031198    } 
     1199 
     1200    /* Init codec param and adjust MTU */ 
     1201    info->codec_param->dir = info->dir; 
     1202    info->codec_param->enc_mtu -= (sizeof(pjmedia_rtp_hdr) + 
     1203                                   PJMEDIA_STREAM_RESV_PAYLOAD_LEN); 
     1204    if (info->codec_param->enc_mtu > PJMEDIA_MAX_MTU) 
     1205        info->codec_param->enc_mtu = PJMEDIA_MAX_MTU; 
     1206    mtu = info->codec_param->enc_mtu; 
    12041207 
    12051208    vfd_enc = pjmedia_format_get_video_format_detail( 
     
    12351238    if (status != PJ_SUCCESS) 
    12361239        return status; 
    1237  
    1238     /* Init codec param */ 
    1239     info->codec_param->dir = info->dir; 
    1240     info->codec_param->enc_mtu = PJMEDIA_MAX_MTU - sizeof(pjmedia_rtp_hdr) -  
    1241                                  PJMEDIA_STREAM_RESV_PAYLOAD_LEN; 
    12421240 
    12431241    /* Init and open the codec. */ 
     
    12951293    /* Init jitter buffer parameters: */ 
    12961294    frm_ptime       = 1000 * vfd_enc->fps.denum / vfd_enc->fps.num; 
    1297     chunks_per_frm  = stream->frame_size / PJMEDIA_MAX_MTU; 
     1295    chunks_per_frm  = stream->frame_size / mtu; 
     1296    if (chunks_per_frm == 0) chunks_per_frm = 1; 
    12981297 
    12991298    /* JB max count, default 500ms */ 
     
    13211320        jb_init  = 0; 
    13221321 
     1322    /* Allocate array for temporary storage for assembly of incoming 
     1323     * frames. Add more just in case. 
     1324     */ 
     1325    stream->rx_frame_cnt = chunks_per_frm * 2; 
     1326    stream->rx_frames = pj_pool_calloc(pool, stream->rx_frame_cnt, 
     1327                                       sizeof(stream->rx_frames[0])); 
     1328 
    13231329    /* Create jitter buffer */ 
    13241330    status = pjmedia_jbuf_create(pool, &stream->dec->port.info.name, 
    1325                                  PJMEDIA_MAX_MTU,  
     1331                                 mtu + PJMEDIA_STREAM_RESV_PAYLOAD_LEN, 
    13261332                                 1000 * vfd_enc->fps.denum / vfd_enc->fps.num, 
    13271333                                 jb_max, &stream->jb); 
     
    14611467 
    14621468    /* Destroy jitter buffer */ 
    1463     if (stream->jb) 
     1469    if (stream->jb) { 
    14641470        pjmedia_jbuf_destroy(stream->jb); 
     1471        stream->jb = NULL; 
     1472    } 
    14651473 
    14661474#if TRACE_JB 
     
    17081716    } 
    17091717 
    1710    
     1718 
     1719    /* Request for codec with the correct packing for streaming */ 
     1720    si->codec_info.packings = PJMEDIA_VID_PACKING_PACKETS; 
     1721 
    17111722    /* Now that we have codec info, get the codec param. */ 
    17121723    si->codec_param = PJ_POOL_ALLOC_T(pool, pjmedia_vid_codec_param); 
Note: See TracChangeset for help on using the changeset viewer.