Ignore:
Timestamp:
Mar 17, 2011 11:33:34 AM (10 years ago)
Author:
bennylp
Message:

Re #1215 (framework):

  • vstream:
    • allow NULL pool parameter which means vstream will create one
    • Updated remote FPS detection to only be performed if decoder returns frame (however the FPS detection is currently disabled as some endpoints changes fps continuously, causing renderer restart continuously too).
  • codec:
    • Updated video codec info to have RTP packetization support flag, also update endpoint in generating SDP to only include codecs whose RTP packetization support.
    • Added dynamic payload types for video codecs.
    • (minor) separate video PT into separate enum in pjmedia-codec/types.h
  • H264 initial experiment.

generated frames (for libx264 sake).

  • Replaced PJ_EUNKNOWN in some places with the appropriate error code.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/vid_stream.c

    r3435 r3461  
    5555#endif 
    5656 
     57#ifndef PJMEDIA_VSTREAM_SIZE 
     58#   define PJMEDIA_VSTREAM_SIZE 1000 
     59#endif 
     60 
     61#ifndef PJMEDIA_VSTREAM_INC 
     62#   define PJMEDIA_VSTREAM_INC  1000 
     63#endif 
    5764 
    5865 
     
    8390struct pjmedia_vid_stream 
    8491{ 
     92    pj_pool_t               *own_pool;      /**< Internal pool.             */ 
    8593    pjmedia_endpt           *endpt;         /**< Media endpoint.            */ 
    8694    pjmedia_vid_codec_mgr   *codec_mgr;     /**< Codec manager.             */ 
     
    766774 
    767775    while (processed < frame_out.size) { 
    768         pj_uint8_t *payload, *rtp_pkt; 
     776        pj_uint8_t *payload; 
     777        pj_uint8_t *rtp_pkt; 
    769778        pj_size_t payload_len; 
    770779 
     
    775784                                           frame_out.size, 
    776785                                           &processed, 
    777                                            &payload, &payload_len); 
     786                                           (const pj_uint8_t**)&payload, 
     787                                           &payload_len); 
    778788        if (status != PJ_SUCCESS) { 
    779789            LOGERR_((channel->port.info.name.ptr,  
     
    843853    pjmedia_vid_channel *channel = stream->dec; 
    844854    pjmedia_frame frame_in; 
    845     pj_bool_t fps_changed = PJ_FALSE; 
    846     pjmedia_ratio new_fps = {0}; 
     855    pj_uint32_t last_ts = 0; 
     856    int frm_first_seq = 0, frm_last_seq = 0; 
    847857    pj_status_t status; 
    848858 
     
    860870        char ptype; 
    861871        pj_size_t psize, data_len; 
    862         pj_uint32_t ts, last_ts; 
     872        pj_uint32_t ts; 
    863873        int seq; 
    864         pj_bool_t got_frame, check_fps; 
     874        pj_bool_t got_frame; 
    865875        unsigned i; 
    866876 
    867877        channel->buf_len = 0; 
    868         last_ts = 0; 
    869878        got_frame = PJ_FALSE; 
    870         check_fps = PJ_FALSE; 
    871879 
    872880        /* Lock jitter buffer mutex first */ 
     
    875883        for (i=0; ; ++i) { 
    876884            /* Get frame from jitter buffer. */ 
    877             pjmedia_jbuf_peek_frame(stream->jb, i, &p, &psize, &ptype, 
    878                                     NULL, &ts, &seq); 
     885            pjmedia_jbuf_peek_frame(stream->jb, i, (const void**)&p, 
     886                                    &psize, &ptype, NULL, &ts, &seq); 
    879887            if (ptype == PJMEDIA_JB_NORMAL_FRAME) { 
    880888                if (last_ts == 0) { 
    881889                    last_ts = ts; 
    882                     check_fps = stream->last_dec_ts && 
    883                                 (seq - stream->last_dec_seq == 1) && 
    884                                 (last_ts > stream->last_dec_ts); 
     890                    frm_first_seq = seq; 
    885891                } 
    886892 
     
    897903                                                           data, &data_len); 
    898904                channel->buf_len += data_len; 
     905                frm_last_seq = seq; 
    899906            } else if (ptype == PJMEDIA_JB_ZERO_EMPTY_FRAME) { 
    900907                /* No more packet in the jitter buffer */ 
     
    911918            return PJ_SUCCESS; 
    912919        } 
    913  
    914         /* Learn remote frame rate */ 
    915         if (check_fps) { 
    916             pj_uint32_t ts_diff; 
    917             pjmedia_video_format_detail *vfd; 
    918  
    919             ts_diff = last_ts - stream->last_dec_ts; 
    920             vfd = pjmedia_format_get_video_format_detail( 
    921                                     &channel->port.info.fmt, PJ_TRUE); 
    922             if (ts_diff * vfd->fps.num != 
    923                 stream->info.codec_info.clock_rate * vfd->fps.denum) 
    924             { 
    925                 /* Frame rate changed */ 
    926                 fps_changed = PJ_TRUE; 
    927                 new_fps.num = stream->info.codec_info.clock_rate; 
    928                 new_fps.denum = ts_diff; 
    929             } 
    930         } 
    931  
    932         /* Update last frame seq and timestamp */ 
    933         stream->last_dec_seq = seq - 1; 
    934         stream->last_dec_ts = last_ts; 
    935920    } 
    936921 
     
    940925    frame_in.bit_info = 0; 
    941926    frame_in.type = PJMEDIA_FRAME_TYPE_VIDEO; 
     927    frame_in.timestamp.u64 = last_ts; 
    942928 
    943929    status = stream->codec->op->decode(stream->codec, &frame_in, 
     
    960946    } 
    961947 
    962     if (fps_changed) { 
    963         pjmedia_video_format_detail *vfd; 
    964  
    965         /* Update decoding channel port info */ 
    966         vfd = pjmedia_format_get_video_format_detail( 
    967                                 &channel->port.info.fmt, PJ_TRUE); 
    968         vfd->fps = new_fps; 
    969  
    970         /* Update stream info */ 
    971         vfd = pjmedia_format_get_video_format_detail( 
    972                                 &stream->info.codec_param->dec_fmt, PJ_TRUE); 
    973         vfd->fps = new_fps; 
    974  
    975         /* Set bit_info */ 
    976         frame->bit_info |= PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED; 
    977  
    978         PJ_LOG(4, (channel->port.info.name.ptr, "Frame rate changed to %.2ffps", 
    979                    (1.0 * new_fps.num / new_fps.denum))); 
    980     } 
     948    /* Learn remote frame rate after successful decoding */ 
     949    if (0 && frame->type == PJMEDIA_FRAME_TYPE_VIDEO && frame->size) 
     950    { 
     951        /* Only check remote frame rate when timestamp is not wrapping and 
     952         * sequence is increased by 1. 
     953         */ 
     954        if (last_ts > stream->last_dec_ts && 
     955            frm_first_seq - stream->last_dec_seq == 1) 
     956        { 
     957            pj_uint32_t ts_diff; 
     958            pjmedia_video_format_detail *vfd; 
     959 
     960            ts_diff = last_ts - stream->last_dec_ts; 
     961            vfd = pjmedia_format_get_video_format_detail( 
     962                                    &channel->port.info.fmt, PJ_TRUE); 
     963            if ((int)(stream->info.codec_info.clock_rate / ts_diff) != 
     964                vfd->fps.num / vfd->fps.denum) 
     965            { 
     966                /* Frame rate changed, update decoding port info */ 
     967                vfd->fps.num = stream->info.codec_info.clock_rate; 
     968                vfd->fps.denum = ts_diff; 
     969 
     970                /* Update stream info */ 
     971                stream->info.codec_param->dec_fmt.det.vid.fps = vfd->fps; 
     972 
     973                /* Set bit_info */ 
     974                frame->bit_info |= PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED; 
     975 
     976                PJ_LOG(5, (channel->port.info.name.ptr, "Frame rate changed to %.2ffps", 
     977                           (1.0 * vfd->fps.num / vfd->fps.denum))); 
     978            } 
     979        } 
     980 
     981        /* Update last frame seq and timestamp */ 
     982        stream->last_dec_seq = frm_last_seq; 
     983        stream->last_dec_ts = last_ts; 
     984    } 
     985 
     986#if PJ_LOG_MAX_LEVEL >= 5 
     987    if (frame->bit_info & PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED) { 
     988        pjmedia_port_info *pi = &channel->port.info; 
     989 
     990        PJ_LOG(5, (channel->port.info.name.ptr, 
     991                   "Decoding format changed to %dx%d %c%c%c%c %.2ffps", 
     992                   pi->fmt.det.vid.size.w, pi->fmt.det.vid.size.h, 
     993                   ((pi->fmt.id & 0x000000FF) >> 0), 
     994                   ((pi->fmt.id & 0x0000FF00) >> 8), 
     995                   ((pi->fmt.id & 0x00FF0000) >> 16), 
     996                   ((pi->fmt.id & 0xFF000000) >> 24), 
     997                   (1.0*pi->fmt.det.vid.fps.num/pi->fmt.det.vid.fps.denum))); 
     998    } 
     999#endif 
    9811000 
    9821001    return PJ_SUCCESS; 
     
    10011020    const char *type_name; 
    10021021    pjmedia_format *fmt; 
     1022    pjmedia_port_info *pi; 
    10031023     
    10041024    pj_assert(info->type == PJMEDIA_TYPE_VIDEO); 
     
    10171037        fmt = &info->codec_param->enc_fmt; 
    10181038    } 
    1019  
    10201039    name.ptr = (char*) pj_pool_alloc(pool, M); 
    10211040    name.slen = pj_ansi_snprintf(name.ptr, M, "%s%p", type_name, stream); 
     1041    pi = &channel->port.info; 
    10221042 
    10231043    /* Init channel info. */ 
     
    10591079 
    10601080    /* Init port. */ 
    1061     pjmedia_port_info_init2(&channel->port.info, &name, 
     1081    pjmedia_port_info_init2(pi, &name, 
    10621082                            PJMEDIA_PORT_SIGNATURE('V', 'C', 'H', 'N'), 
    10631083                            dir, fmt); 
     
    10651085        channel->port.get_frame = &get_frame; 
    10661086    } else { 
     1087        pi->fmt.id = info->codec_param->dec_fmt.id; 
    10671088        channel->port.put_frame = &put_frame; 
    10681089    } 
     
    10701091    /* Init port. */ 
    10711092    channel->port.port_data.pdata = stream; 
     1093 
     1094    PJ_LOG(5, (name.ptr, "%s channel created %dx%d %c%c%c%c%s%.*s %.2ffps", 
     1095               (dir==PJMEDIA_DIR_ENCODING?"Encoding":"Decoding"), 
     1096               pi->fmt.det.vid.size.w, pi->fmt.det.vid.size.h, 
     1097               ((pi->fmt.id & 0x000000FF) >> 0), 
     1098               ((pi->fmt.id & 0x0000FF00) >> 8), 
     1099               ((pi->fmt.id & 0x00FF0000) >> 16), 
     1100               ((pi->fmt.id & 0xFF000000) >> 24), 
     1101               (dir==PJMEDIA_DIR_ENCODING?"->":"<-"), 
     1102               info->codec_info.encoding_name.slen, 
     1103               info->codec_info.encoding_name.ptr, 
     1104               (1.0*pi->fmt.det.vid.fps.num/pi->fmt.det.vid.fps.denum))); 
    10721105 
    10731106    /* Done. */ 
     
    10831116                                        pjmedia_endpt *endpt, 
    10841117                                        pj_pool_t *pool, 
    1085                                         const pjmedia_vid_stream_info *info, 
     1118                                        pjmedia_vid_stream_info *info, 
    10861119                                        pjmedia_transport *tp, 
    10871120                                        void *user_data, 
     
    10891122{ 
    10901123    enum { M = 32 }; 
     1124    pj_pool_t *own_pool = NULL; 
    10911125    pjmedia_vid_stream *stream; 
    10921126    unsigned jb_init, jb_max, jb_min_pre, jb_max_pre, len; 
     
    10961130    pj_status_t status; 
    10971131 
     1132    if (!pool) { 
     1133        own_pool = pjmedia_endpt_create_pool( endpt, "vstrm%p", 
     1134                                              PJMEDIA_VSTREAM_SIZE, 
     1135                                              PJMEDIA_VSTREAM_INC); 
     1136        PJ_ASSERT_RETURN(own_pool != NULL, PJ_ENOMEM); 
     1137        pool = own_pool; 
     1138    } 
     1139 
    10981140    /* Allocate stream */ 
    10991141    stream = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_stream); 
    11001142    PJ_ASSERT_RETURN(stream != NULL, PJ_ENOMEM); 
    1101  
    1102     /* Copy stream info */ 
    1103     pj_memcpy(&stream->info, info, sizeof(*info)); 
     1143    stream->own_pool = own_pool; 
    11041144 
    11051145    /* Get codec manager */ 
     
    11211161 
    11221162    /* Get codec param: */ 
    1123     if (info->codec_param) { 
    1124         stream->info.codec_param = pjmedia_vid_codec_param_clone( 
    1125                                                         pool, 
    1126                                                         info->codec_param); 
    1127     } else { 
     1163    if (!info->codec_param) { 
    11281164        pjmedia_vid_codec_param def_param; 
    11291165 
     
    11331169        if (status != PJ_SUCCESS) 
    11341170            return status; 
    1135         stream->info.codec_param = pjmedia_vid_codec_param_clone( 
    1136                                                         pool, 
    1137                                                         &def_param); 
    1138         pj_assert(stream->info.codec_param); 
     1171 
     1172        info->codec_param = pjmedia_vid_codec_param_clone(pool, &def_param); 
     1173        pj_assert(info->codec_param); 
    11391174    } 
    11401175 
    11411176    vfd_enc = pjmedia_format_get_video_format_detail( 
    1142                                         &stream->info.codec_param->enc_fmt, 
    1143                                         PJ_TRUE); 
     1177                                        &info->codec_param->enc_fmt, PJ_TRUE); 
    11441178 
    11451179    /* Init stream: */ 
     
    11741208 
    11751209    /* Init codec param */ 
    1176     stream->info.codec_param->dir = info->dir; 
    1177     stream->info.codec_param->enc_mtu = PJMEDIA_MAX_MTU -  
    1178                                         sizeof(pjmedia_rtp_hdr); 
     1210    info->codec_param->dir = info->dir; 
     1211    info->codec_param->enc_mtu = PJMEDIA_MAX_MTU - sizeof(pjmedia_rtp_hdr); 
    11791212 
    11801213    /* Init and open the codec. */ 
     
    11821215    if (status != PJ_SUCCESS) 
    11831216        return status; 
    1184     status = stream->codec->op->open(stream->codec, stream->info.codec_param); 
     1217    status = stream->codec->op->open(stream->codec, info->codec_param); 
    11851218    if (status != PJ_SUCCESS) 
    11861219        return status; 
     
    13311364#endif 
    13321365 
     1366    /* Save the stream info */ 
     1367    pj_memcpy(&stream->info, info, sizeof(*info)); 
     1368    stream->info.codec_param = pjmedia_vid_codec_param_clone( 
     1369                                                pool, info->codec_param); 
     1370 
    13331371    /* Success! */ 
    13341372    *p_stream = stream; 
    13351373 
    1336     PJ_LOG(5,(THIS_FILE, "Stream %s created", stream->name.ptr)); 
     1374    PJ_LOG(5,(THIS_FILE, "Video stream %s created", stream->name.ptr)); 
    13371375 
    13381376    return PJ_SUCCESS; 
     
    14351473#endif 
    14361474 
     1475    if (stream->own_pool) { 
     1476        pj_pool_t *pool = stream->own_pool; 
     1477        stream->own_pool = NULL; 
     1478        pj_pool_release(pool); 
     1479    } 
     1480 
    14371481    return PJ_SUCCESS; 
    14381482} 
    1439  
    14401483 
    14411484 
Note: See TracChangeset for help on using the changeset viewer.