Changeset 3776 for pjproject/trunk


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
Location:
pjproject/trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia-codec/ffmpeg_codecs.h

    r3715 r3776  
    2727PJ_BEGIN_DECL 
    2828 
     29/** 
     30 * @defgroup PJMEDIA_CODEC_VID_FFMPEG FFmpeg Codecs 
     31 * @ingroup PJMEDIA_CODEC_VID_CODECS 
     32 * @{ 
     33 */ 
    2934 
    3035/** 
  • pjproject/trunk/pjmedia/include/pjmedia/vid_codec.h

    r3715 r3776  
    3636PJ_BEGIN_DECL 
    3737 
     38/** 
     39 * @defgroup PJMEDIA_VID_CODEC Video Codecs 
     40 * @ingroup PJMEDIA_CODEC 
     41 * @{ 
     42 */ 
     43 
    3844#define PJMEDIA_VID_CODEC_MAX_DEC_FMT_CNT    8 
    3945#define PJMEDIA_VID_CODEC_MAX_FPS_CNT        16 
     46 
     47/** 
     48 * This enumeration specifies the packetization property of video encoding 
     49 * process. The value is bitmask, and smaller value will have higher priority 
     50 * to be used. 
     51 */ 
     52typedef enum pjmedia_vid_packing 
     53{ 
     54    /** 
     55     * This specifies that the packetization is unknown, or if nothing 
     56     * is supported. 
     57     */ 
     58    PJMEDIA_VID_PACKING_UNKNOWN, 
     59 
     60    /** 
     61     * This specifies that the result of video encoding process will be 
     62     * segmented into packets, which is suitable for RTP transmission. 
     63     * The maximum size of the packets is set in \a enc_mtu field of 
     64     * pjmedia_vid_codec_param. 
     65     */ 
     66    PJMEDIA_VID_PACKING_PACKETS = 1, 
     67 
     68    /** 
     69     * This specifies that video encoding function will produce a whole 
     70     * or full frame from the source frame. This is normally used for 
     71     * encoding video for offline storage such as to an AVI file. The 
     72     * maximum size of the packets is set in \a enc_mtu field of 
     73     * pjmedia_vid_codec_param. 
     74     */ 
     75    PJMEDIA_VID_PACKING_WHOLE = 2 
     76 
     77} pjmedia_vid_packing; 
    4078 
    4179/**  
     
    5694                                        /**< Supported encoding source  
    5795                                             format IDs                     */ 
     96    unsigned            packings;       /**< Supported or requested packings, 
     97                                             strategies, bitmask from 
     98                                             pjmedia_vid_packing            */ 
    5899    unsigned            fps_cnt;        /**< # of supported frame-rates, can be 
    59100                                             zero (support any frame-rate)  */ 
    60101    pjmedia_ratio       fps[PJMEDIA_VID_CODEC_MAX_FPS_CNT]; 
    61102                                        /**< Supported frame-rates          */ 
    62     pj_bool_t           has_rtp_pack;   /**< Support RTP packetization      */ 
     103 
    63104} pjmedia_vid_codec_info; 
    64105 
     
    77118{ 
    78119    pjmedia_dir         dir;            /**< Direction                      */ 
     120    pjmedia_vid_packing packing;        /**< Packetization strategy.        */ 
     121 
    79122    pjmedia_format      enc_fmt;        /**< Encoded format                 */ 
     123    pjmedia_codec_fmtp  enc_fmtp;       /**< Encoder fmtp params            */ 
     124    unsigned            enc_mtu;        /**< MTU or max payload size setting*/ 
     125 
    80126    pjmedia_format      dec_fmt;        /**< Decoded format                 */ 
    81  
    82     pjmedia_codec_fmtp  enc_fmtp;       /**< Encoder fmtp params            */ 
    83127    pjmedia_codec_fmtp  dec_fmtp;       /**< Decoder fmtp params            */ 
    84128 
    85     unsigned            enc_mtu;        /**< MTU or max payload size setting*/ 
    86129} pjmedia_vid_codec_param; 
    87130 
     
    112155{ 
    113156    /**  
    114      * Initialize codec using the specified attribute. 
    115      * 
    116      * Application should call #pjmedia_vid_codec_init() instead of  
    117      * calling this function directly. 
    118      * 
    119      * @param codec     The codec instance. 
    120      * @param pool      Pool to use when the codec needs to allocate 
    121      *                  some memory. 
    122      * 
    123      * @return          PJ_SUCCESS on success. 
     157     * See #pjmedia_vid_codec_init(). 
    124158     */ 
    125159    pj_status_t (*init)(pjmedia_vid_codec *codec,  
     
    127161 
    128162    /**  
    129      * Open the codec and initialize with the specified parameter. 
    130      * Upon successful initialization, the codec may modify the parameter 
    131      * and fills in the unspecified values (such as size or frame rate of 
    132      * the encoder format, as it may need to be negotiated with remote 
    133      * preferences via SDP fmtp). 
    134      * 
    135      * Application should call #pjmedia_vid_codec_open() instead of  
    136      * calling this function directly. 
    137      * 
    138      * @param codec     The codec instance. 
    139      * @param param     Codec initialization parameter. 
    140      * 
    141      * @return          PJ_SUCCESS on success. 
     163     * See #pjmedia_vid_codec_open(). 
    142164     */ 
    143165    pj_status_t (*open)(pjmedia_vid_codec *codec,  
     
    145167 
    146168    /**  
    147      * Close and shutdown codec, releasing all resources allocated by 
    148      * this codec, if any. 
    149      * 
    150      * Application should call #pjmedia_vid_codec_close() instead of  
    151      * calling this function directly. 
    152      * 
    153      * @param codec     The codec instance. 
    154      * 
    155      * @return          PJ_SUCCESS on success. 
     169     * See #pjmedia_vid_codec_close(). 
    156170     */ 
    157171    pj_status_t (*close)(pjmedia_vid_codec *codec); 
    158172 
    159173    /**  
    160      * Modify the codec parameter after the codec is open.  
    161      * Note that not all codec parameters can be modified during run-time.  
    162      * When the parameter cannot be changed, this function will return  
    163      * non-PJ_SUCCESS, and the original parameters will not be changed. 
    164      * 
    165      * Application should call #pjmedia_vid_codec_modify() instead of  
    166      * calling this function directly. 
    167      * 
    168      * @param codec     The codec instance. 
    169      * @param param     The new codec parameter. 
    170      * 
    171      * @return          PJ_SUCCESS on success. 
     174     * See #pjmedia_vid_codec_modify(). 
    172175     */ 
    173176    pj_status_t (*modify)(pjmedia_vid_codec *codec,  
     
    175178 
    176179    /**  
    177      * Get the codec parameter after the codec is opened.  
    178      * 
    179      * Application should call #pjmedia_vid_codec_get_param() instead of  
    180      * calling this function directly. 
    181      * 
    182      * @param codec     The codec instance. 
    183      * @param param     The codec parameter. 
    184      * 
    185      * @return          PJ_SUCCESS on success. 
     180     * See #pjmedia_vid_codec_get_param(). 
    186181     */ 
    187182    pj_status_t (*get_param)(pjmedia_vid_codec *codec, 
     
    189184 
    190185    /** 
    191      * Instruct the codec to generate a payload/packet from a picture 
    192      * bitstream to be sent (via network). The maximum payload size or 
    193      * MTU is configurable via enc_mtu field of #pjmedia_vid_codec_param. 
    194      * For a long bitstream, application usually need to call this function 
    195      * multiple times until the whole bitstream is sent. Note that, for 
    196      * performance reason, the packetization will be done in-place, so the 
    197      * original bitstream may be modified by this function. 
    198      * 
    199      * Application should call #pjmedia_vid_codec_packetize() instead of  
    200      * calling this function directly. 
    201      * 
    202      * @param codec     The codec instance 
    203      * @param bits      The picture bitstream. 
    204      * @param bits_len  The length of the bitstream. 
    205      * @param bits_pos  On input, the start position of the bitstream 
    206      *                  to be packetized. On output, the next position for 
    207      *                  next packet. 
    208      * @param pkt       The pointer of the generated payload. 
    209      * @param pkt_len   The payload length. 
    210      * 
    211      * @return          PJ_SUCCESS on success. 
    212      */ 
    213     pj_status_t (*packetize) (pjmedia_vid_codec *codec, 
    214                               pj_uint8_t *bits, 
    215                               pj_size_t bits_len, 
    216                               unsigned *bits_pos, 
    217                               const pj_uint8_t **pkt, 
    218                               pj_size_t *pkt_len); 
     186     * See #pjmedia_vid_codec_encode_begin(). 
     187     */ 
     188    pj_status_t (*encode_begin)(pjmedia_vid_codec *codec, 
     189                                const pjmedia_frame *input, 
     190                                unsigned out_size, 
     191                                pjmedia_frame *output, 
     192                                pj_bool_t *has_more); 
    219193 
    220194    /** 
    221      * Instruct the codec to parse a payload and append it into a picture 
    222      * bitstream. A picture bitstreams may need to be reconstructed from 
    223      * one or more payloads. Note that this function will not provide the 
    224      * detection of picture boundary, so application should manage the 
    225      * picture boundary detection by itself, e.g: for RTP delivery, payloads 
    226      * belong to the same picture will share the same RTP timestamp and also 
    227      * there is marker bit in the RTP header that is usually reserved for 
    228      * end-of-picture flag. Also note that in case of noticing packet lost, 
    229      * application should keep calling this function with payload pointer 
    230      * set to NULL, as the packetizer need to update its internal state. 
    231      * 
    232      * Application should call #pjmedia_vid_codec_unpacketize() instead of  
    233      * calling this function directly. 
    234      * 
    235      * @param codec     The codec instance 
    236      * @param pkt       The input packet. 
    237      * @param pkt_size  Size of the packet. 
    238      * @param timestamp The timestamp of the first sample in the packet. 
    239      * @param frame_cnt On input, specifies the maximum number of frames 
    240      *                  in the array. On output, the codec must fill 
    241      *                  with number of frames detected in the packet. 
    242      * @param frames    On output, specifies the frames that have been 
    243      *                  detected in the packet. 
    244      * 
    245      * @return          PJ_SUCCESS on success. 
    246      */ 
    247     pj_status_t (*unpacketize)(pjmedia_vid_codec *codec, 
    248                                const pj_uint8_t *payload, 
    249                                pj_size_t   payload_len, 
    250                                pj_uint8_t *bits, 
    251                                pj_size_t   bits_len, 
    252                                unsigned   *bits_pos); 
    253  
    254     /**  
    255      * Instruct the codec to encode the specified input frame. The input 
    256      * MUST contain only one picture with appropriate format as specified 
    257      * in opening the codec. 
    258      * 
    259      * Application should call #pjmedia_vid_codec_encode() instead of  
    260      * calling this function directly. 
    261      * 
    262      * @param codec     The codec instance. 
    263      * @param input     The input frame. 
    264      * @param out_size  The length of buffer in the output frame. 
    265      * @param output    The output frame. 
    266      * 
    267      * @return          PJ_SUCCESS on success; 
    268      */ 
    269     pj_status_t (*encode)(pjmedia_vid_codec *codec,  
    270                           const pjmedia_frame *input, 
    271                           unsigned out_size,  
     195     * See #pjmedia_vid_codec_encode_more() 
     196     */ 
     197    pj_status_t (*encode_more)(pjmedia_vid_codec *codec, 
     198                               unsigned out_size, 
     199                               pjmedia_frame *output, 
     200                               pj_bool_t *has_more); 
     201 
     202 
     203    /* 
     204     * See #pjmedia_vid_codec_decode(). 
     205     */ 
     206    pj_status_t (*decode)(pjmedia_vid_codec *codec, 
     207                          pj_size_t count, 
     208                          pjmedia_frame packets[], 
     209                          unsigned out_size, 
    272210                          pjmedia_frame *output); 
    273211 
    274     /**  
    275      * Instruct the codec to decode the specified input frame. The input 
    276      * frame MUST contain exactly one picture. Note that the decoded picture 
    277      * format may different to the current setting, e.g: the format specified 
    278      * in the #pjmedia_vid_codec_param when opening the codec, in this case the 
    279      * PJMEDIA_EVENT_FMT_CHANGED event will be emitted by the codec. The codec 
    280      * parameter will also be updated, and application can query the format by 
    281      * using #get_param(). 
    282      * 
    283      * Application should call #pjmedia_vid_codec_decode() instead of  
    284      * calling this function directly. 
    285      * 
    286      * @param codec     The codec instance. 
    287      * @param input     The input frame. 
    288      * @param out_size  The length of buffer in the output frame. 
    289      * @param output    The output frame. 
    290      * 
    291      * @return          PJ_SUCCESS on success; 
    292      */ 
    293     pj_status_t (*decode)(pjmedia_vid_codec *codec,  
    294                           const pjmedia_frame *input, 
    295                           unsigned out_size,  
    296                           pjmedia_frame *output); 
    297  
    298212    /** 
    299      * Instruct the codec to recover a missing frame. 
    300      * 
    301      * Application should call #pjmedia_vid_codec_recover() instead of  
    302      * calling this function directly. 
    303      * 
    304      * @param codec     The codec instance. 
    305      * @param out_size  The length of buffer in the output frame. 
    306      * @param output    The output frame where generated signal 
    307      *                  will be placed. 
    308      * 
    309      * @return          PJ_SUCCESS on success; 
     213     * See #pjmedia_vid_codec_recover() 
    310214     */ 
    311215    pj_status_t (*recover)(pjmedia_vid_codec *codec, 
     
    554458 * @return          PJ_SUCCESS on success. 
    555459 */ 
    556 PJ_DECL(pj_status_t) pjmedia_vid_codec_mgr_enum_codecs(  
    557                                             pjmedia_vid_codec_mgr *mgr,  
    558                                             unsigned *count,  
    559                                             pjmedia_vid_codec_info info[], 
    560                                             unsigned *prio); 
     460PJ_DECL(pj_status_t) 
     461pjmedia_vid_codec_mgr_enum_codecs(pjmedia_vid_codec_mgr *mgr, 
     462                                  unsigned *count, 
     463                                  pjmedia_vid_codec_info info[], 
     464                                  unsigned *prio); 
    561465 
    562466 
     
    605509 *                  the buffer is not long enough. 
    606510 */ 
    607 PJ_DECL(char*) pjmedia_vid_codec_info_to_id( 
    608                                         const pjmedia_vid_codec_info *info, 
    609                                         char *id, unsigned max_len ); 
     511PJ_DECL(char*) pjmedia_vid_codec_info_to_id(const pjmedia_vid_codec_info *info, 
     512                                            char *id, unsigned max_len ); 
    610513 
    611514 
     
    758661 * @return          PJ_SUCCESS on success. 
    759662 */ 
    760 PJ_INLINE(pj_status_t) pjmedia_vid_codec_open( 
    761                                             pjmedia_vid_codec *codec,  
    762                                             pjmedia_vid_codec_param *param ) 
     663PJ_INLINE(pj_status_t) pjmedia_vid_codec_open(pjmedia_vid_codec *codec, 
     664                                              pjmedia_vid_codec_param *param) 
    763665{ 
    764666    return (*codec->op->open)(codec, param); 
     
    791693 * @return              PJ_SUCCESS on success. 
    792694 */ 
    793 PJ_INLINE(pj_status_t) pjmedia_vid_codec_modify( 
    794                                     pjmedia_vid_codec *codec,  
    795                                     const pjmedia_vid_codec_param *param) 
     695PJ_INLINE(pj_status_t) 
     696pjmedia_vid_codec_modify(pjmedia_vid_codec *codec, 
     697                         const pjmedia_vid_codec_param *param) 
    796698{ 
    797699    return (*codec->op->modify)(codec, param); 
     
    807709 * @return              PJ_SUCCESS on success. 
    808710 */ 
    809 PJ_INLINE(pj_status_t) pjmedia_vid_codec_get_param( 
    810                                     pjmedia_vid_codec *codec,  
    811                                     pjmedia_vid_codec_param *param) 
     711PJ_INLINE(pj_status_t) 
     712pjmedia_vid_codec_get_param(pjmedia_vid_codec *codec, 
     713                            pjmedia_vid_codec_param *param) 
    812714{ 
    813715    return (*codec->op->get_param)(codec, param); 
    814716} 
    815717 
    816  
    817 /** 
    818  * Instruct the codec to generate a payload/packet from a picture 
    819  * bitstream to be sent (via network). The maximum payload size or 
    820  * MTU is configurable via enc_mtu field of #pjmedia_vid_codec_param. 
    821  * For a long bitstream, application usually need to call this function 
    822  * multiple times until the whole bitstream is sent. Note that, for 
    823  * performance reason, the packetization will be done in-place, so the 
    824  * original bitstream may be modified by this function. 
    825  * 
    826  * @param codec The codec instance 
    827  * @param bits  The picture bitstream. 
    828  * @param bits_len      The length of the bitstream. 
    829  * @param bits_pos      On input, the start position of the bitstream 
    830  *                      to be packetized. On output, the next position for 
    831  *                      next packet. 
    832  * @param pkt   The pointer of the generated payload. 
    833  * @param pkt_len       The payload length. 
    834  * 
    835  * @return              PJ_SUCCESS on success. 
    836  */ 
    837 PJ_INLINE(pj_status_t) pjmedia_vid_codec_packetize( 
    838                                             pjmedia_vid_codec *codec, 
    839                                             pj_uint8_t *bits, 
    840                                             pj_size_t bits_len, 
    841                                             unsigned *bits_pos, 
    842                                             const pj_uint8_t **pkt, 
    843                                             pj_size_t *pkt_len ) 
    844 { 
    845     return (*codec->op->packetize)(codec, bits, bits_len, bits_pos, 
    846                                    pkt, pkt_len); 
     718/**  
     719 * Encode the specified input frame. The input MUST contain only one picture 
     720 * with the appropriate format as specified when opening the codec. Depending 
     721 * on the packing or packetization set in the \a packing param, the process 
     722 * may produce multiple encoded packets or payloads to represent the picture. 
     723 * This is true for example for PJMEDIA_VID_PACKING_PACKETS packing. In this 
     724 * case, the \a has_more field will be set to PJ_TRUE, and application should 
     725 * call pjmedia_vid_codec_encode_more() to get the remaining results from the 
     726 * codec. 
     727 * 
     728 * @param codec         The codec instance. 
     729 * @param input         The input frame. 
     730 * @param out_size      The length of buffer in the output frame. This 
     731 *                      should be at least the same as the configured 
     732 *                      encoding MTU of the codec. 
     733 * @param output        The output frame. 
     734 * @param has_more      PJ_TRUE if more payloads are available; application 
     735 *                      should then call pjmedia_vid_codec_encode_more() 
     736 *                      to retrieve the remaining results. 
     737 * 
     738 * @return              PJ_SUCCESS on success; 
     739 */ 
     740PJ_INLINE(pj_status_t) 
     741pjmedia_vid_codec_encode_begin( pjmedia_vid_codec *codec, 
     742                                const pjmedia_frame *input, 
     743                                unsigned out_size, 
     744                                pjmedia_frame *output, 
     745                                pj_bool_t *has_more) 
     746{ 
     747    return (*codec->op->encode_begin)(codec, input, out_size, output, 
     748                                      has_more); 
    847749} 
    848750 
    849  
    850 /** 
    851  * Instruct the codec to parse a payload and append it into a picture 
    852  * bitstream. A picture bitstreams may need to be reconstructed from 
    853  * one or more payloads. Note that this function will not provide the 
    854  * detection of picture boundary, so application should manage the 
    855  * picture boundary detection by itself, e.g: for RTP delivery, payloads 
    856  * belong to the same picture will share the same RTP timestamp and also 
    857  * there is marker bit in the RTP header that is usually reserved for 
    858  * end-of-picture flag. Also note that in case of noticing packet lost, 
    859  * application should keep calling this function with payload pointer 
    860  * set to NULL, as the packetizer need to update its internal state. 
    861  * 
    862  * @param codec The codec instance 
    863  * @param pkt   The input packet. 
    864  * @param pkt_size      Size of the packet. 
    865  * @param timestamp     The timestamp of the first sample in the packet. 
    866  * @param frame_cnt     On input, specifies the maximum number of frames 
    867  *                      in the array. On output, the codec must fill 
    868  *                      with number of frames detected in the packet. 
    869  * @param frames        On output, specifies the frames that have been 
    870  *                      detected in the packet. 
    871  * 
    872  * @return              PJ_SUCCESS on success. 
    873  */ 
    874 PJ_INLINE(pj_status_t) pjmedia_vid_codec_unpacketize( 
    875                                                 pjmedia_vid_codec *codec, 
    876                                                 const pj_uint8_t *payload, 
    877                                                 pj_size_t payload_len, 
    878                                                 pj_uint8_t *bits, 
    879                                                 pj_size_t bits_len, 
    880                                                 unsigned *bits_pos ) 
    881 { 
    882     return (*codec->op->unpacketize)(codec, payload, payload_len, bits, 
    883                                      bits_len, bits_pos); 
     751/** 
     752 * Retrieve more encoded packets/payloads from the codec. Application 
     753 * should call this function repeatedly until \a has_more flag is set 
     754 * to PJ_FALSE. 
     755 * 
     756 * @param codec         The codec instance. 
     757 * @param out_size      The length of buffer in the output frame. This 
     758 *                      should be at least the same as as the configured 
     759 *                      encoding MTU of the codec. 
     760 * @param output        The output frame. 
     761 * @param has_more      PJ_TRUE if more payloads are available, which in 
     762 *                      this case application should call \a encode_more() 
     763 *                      to retrieve them. 
     764 * 
     765 * @return              PJ_SUCCESS on success; 
     766 */ 
     767PJ_INLINE(pj_status_t) 
     768pjmedia_vid_codec_encode_more( pjmedia_vid_codec *codec, 
     769                               unsigned out_size, 
     770                               pjmedia_frame *output, 
     771                               pj_bool_t *has_more) 
     772{ 
     773    return (*codec->op->encode_more)(codec, out_size, output, has_more); 
    884774} 
    885775 
    886  
    887 /**  
    888  * Instruct the codec to encode the specified input frame. The input 
    889  * MUST contain only one picture with appropriate format as specified 
    890  * in opening the codec. 
    891  * 
    892  * @param codec The codec instance. 
    893  * @param input The input frame. 
     776/**  
     777 * Decode the input packets into one picture. If the packing is set to 
     778 * PJMEDIA_VID_PACKING_PACKETS when opening the codec, the codec is set 
     779 * to decode multiple encoded packets into one picture. These encoded 
     780 * packets are typically retrieved from the jitter buffer. If the packing 
     781 * is set to PJMEDIA_VID_PACKING_WHOLE, then this decode function can only 
     782 * accept one frame as the input. 
     783 * 
     784 * Note that the decoded picture format may different to the configured 
     785 * setting (i.e. the format specified in the #pjmedia_vid_codec_param when 
     786 * opening the codec), in this case the PJMEDIA_EVENT_FMT_CHANGED event will 
     787 * be emitted by the codec to notify the event. The codec parameter will 
     788 * also be updated, and application can query the format by using 
     789 * pjmedia_vid_codec_get_param(). 
     790 * 
     791 * @param codec         The codec instance. 
     792 * @param pkt_count     Number of packets in the input. 
     793 * @param packets       Array of input packets, each containing an encoded 
     794 *                      frame. 
    894795 * @param out_size      The length of buffer in the output frame. 
    895796 * @param output        The output frame. 
     
    897798 * @return              PJ_SUCCESS on success; 
    898799 */ 
    899 PJ_INLINE(pj_status_t) pjmedia_vid_codec_encode( 
    900                                             pjmedia_vid_codec *codec,  
    901                                             const pjmedia_frame *input, 
    902                                             unsigned out_size,  
    903                                             pjmedia_frame *output) 
    904 { 
    905     return (*codec->op->encode)(codec, input, out_size, output); 
     800PJ_INLINE(pj_status_t) pjmedia_vid_codec_decode(pjmedia_vid_codec *codec, 
     801                                                pj_size_t pkt_count, 
     802                                                pjmedia_frame packets[], 
     803                                                unsigned out_size, 
     804                                                pjmedia_frame *output) 
     805{ 
     806    return (*codec->op->decode)(codec, pkt_count, packets, out_size, output); 
    906807} 
    907808 
    908  
    909 /**  
    910  * Instruct the codec to decode the specified input frame. The input 
    911  * frame MUST contain exactly one picture. Note that the decoded picture 
    912  * format may different to the current setting, e.g: the format specified 
    913  * in the #pjmedia_vid_codec_param when opening the codec, in this case the 
    914  * PJMEDIA_EVENT_FMT_CHANGED event will be emitted by the codec. The codec 
    915  * parameter will also be updated, and application can query the format by 
    916  * using #get_param(). 
    917  * 
    918  * @param codec The codec instance. 
    919  * @param input The input frame. 
    920  * @param out_size      The length of buffer in the output frame. 
    921  * @param output        The output frame. 
    922  * 
    923  * @return              PJ_SUCCESS on success; 
    924  */ 
    925 PJ_INLINE(pj_status_t) pjmedia_vid_codec_decode( 
    926                                             pjmedia_vid_codec *codec,  
    927                                             const pjmedia_frame *input, 
    928                                             unsigned out_size,  
    929                                             pjmedia_frame *output) 
    930 { 
    931     return (*codec->op->decode)(codec, input, out_size, output); 
    932 } 
    933  
    934  
    935 /** 
    936  * Instruct the codec to recover a missing frame. 
    937  * 
    938  * @param codec The codec instance. 
     809/** 
     810 * Recover a missing frame. 
     811 * 
     812 * @param codec         The codec instance. 
    939813 * @param out_size      The length of buffer in the output frame. 
    940814 * @param output        The output frame where generated signal 
     
    943817 * @return              PJ_SUCCESS on success; 
    944818 */ 
    945 PJ_INLINE(pj_status_t) pjmedia_vid_codec_recover( 
    946                                             pjmedia_vid_codec *codec,  
    947                                             unsigned out_size,  
    948                                             pjmedia_frame *output) 
     819PJ_INLINE(pj_status_t) pjmedia_vid_codec_recover(pjmedia_vid_codec *codec, 
     820                                                 unsigned out_size, 
     821                                                 pjmedia_frame *output) 
    949822{ 
    950823    if (codec->op && codec->op->recover) 
     
    961834/** 
    962835 * @defgroup PJMEDIA_CODEC_VID_CODECS Supported video codecs 
    963  * @ingroup PJMEDIA_CODEC 
    964  * @brief Documentation about individual video codec supported by PJMEDIA 
    965  * @{ 
    966  * Please see the APIs provided by the individual codecs below. 
    967  */ 
    968 /** 
    969  * @} 
     836 * @ingroup PJMEDIA_VID_CODEC 
    970837 */ 
    971838 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/ffmpeg_codecs.c

    r3734 r3776  
    7171static pj_status_t  ffmpeg_codec_get_param(pjmedia_vid_codec *codec, 
    7272                                           pjmedia_vid_codec_param *param); 
    73 static pj_status_t  ffmpeg_packetize ( pjmedia_vid_codec *codec, 
    74                                        pj_uint8_t *buf, 
    75                                        pj_size_t buf_len, 
    76                                        unsigned *pos, 
    77                                        const pj_uint8_t **payload, 
    78                                        pj_size_t *payload_len); 
    79 static pj_status_t  ffmpeg_unpacketize(pjmedia_vid_codec *codec, 
    80                                        const pj_uint8_t *payload, 
    81                                        pj_size_t   payload_len, 
    82                                        pj_uint8_t *buf, 
    83                                        pj_size_t   buf_len, 
    84                                        unsigned   *pos); 
    85 static pj_status_t  ffmpeg_codec_encode( pjmedia_vid_codec *codec,  
    86                                          const pjmedia_frame *input, 
    87                                          unsigned output_buf_len,  
    88                                          pjmedia_frame *output); 
    89 static pj_status_t  ffmpeg_codec_decode( pjmedia_vid_codec *codec,  
    90                                          const pjmedia_frame *input, 
    91                                          unsigned output_buf_len,  
    92                                          pjmedia_frame *output); 
     73static pj_status_t ffmpeg_codec_encode_begin( pjmedia_vid_codec *codec, 
     74                                              const pjmedia_frame *input, 
     75                                              unsigned out_size, 
     76                                              pjmedia_frame *output, 
     77                                              pj_bool_t *has_more); 
     78static pj_status_t ffmpeg_codec_encode_more(pjmedia_vid_codec *codec, 
     79                                            unsigned out_size, 
     80                                            pjmedia_frame *output, 
     81                                            pj_bool_t *has_more); 
     82static pj_status_t ffmpeg_codec_decode( pjmedia_vid_codec *codec, 
     83                                        pj_size_t pkt_count, 
     84                                        pjmedia_frame packets[], 
     85                                        unsigned out_size, 
     86                                        pjmedia_frame *output); 
    9387 
    9488/* Definition for FFMPEG codecs operations. */ 
     
    10094    &ffmpeg_codec_modify, 
    10195    &ffmpeg_codec_get_param, 
    102     &ffmpeg_packetize, 
    103     &ffmpeg_unpacketize, 
    104     &ffmpeg_codec_encode, 
     96    &ffmpeg_codec_encode_begin, 
     97    &ffmpeg_codec_encode_more, 
    10598    &ffmpeg_codec_decode, 
    10699    NULL 
     
    145138    const pjmedia_video_format_info *dec_vfi; 
    146139    pjmedia_video_apply_fmt_param    dec_vafp; 
     140 
     141    /* Buffers, only needed for multi-packets */ 
     142    pj_bool_t                        whole; 
     143    void                            *enc_buf; 
     144    unsigned                         enc_buf_size; 
     145    unsigned                         enc_frame_len; 
     146    unsigned                         enc_processed; 
     147    void                            *dec_buf; 
     148    unsigned                         dec_buf_size; 
    147149 
    148150    /* The ffmpeg codec states. */ 
     
    236238 
    237239/* Internal codec info */ 
    238 ffmpeg_codec_desc codec_desc[] = 
     240static ffmpeg_codec_desc codec_desc[] = 
    239241{ 
    240242#if ENABLE_H264 
     
    478480            (desc->info.fmt_id == info->fmt_id) && 
    479481            ((desc->info.dir & info->dir) == info->dir) && 
    480             (desc->info.pt == info->pt)) 
     482            (desc->info.pt == info->pt) && 
     483            (desc->info.packings & info->packings)) 
    481484        { 
    482485            return desc; 
     
    540543 
    541544    /* Enum FFMPEG codecs */ 
    542     for (c=av_codec_next(NULL); c; c=av_codec_next(c))  
    543     { 
     545    for (c=av_codec_next(NULL); c; c=av_codec_next(c)) { 
    544546        ffmpeg_codec_desc *desc; 
    545547        pjmedia_format_id fmt_id; 
     
    659661            desc->info.clock_rate = 90000; 
    660662 
    661         /* Set RTP packetization support flag in the codec info */ 
    662         desc->info.has_rtp_pack = (desc->packetize != NULL) && 
    663                                   (desc->unpacketize != NULL); 
     663        /* Set supported packings */ 
     664        desc->info.packings |= PJMEDIA_VID_PACKING_WHOLE; 
     665        if (desc->packetize && desc->unpacketize) 
     666            desc->info.packings |= PJMEDIA_VID_PACKING_PACKETS; 
     667 
    664668    } 
    665669 
     
    707711            desc->info.dir |= copied_dir; 
    708712            desc->enabled = (desc->info.dir != PJMEDIA_DIR_NONE); 
    709             desc->info.has_rtp_pack = (desc->packetize != NULL) && 
    710                                       (desc->unpacketize != NULL); 
     713 
     714            /* Set supported packings */ 
     715            desc->info.packings |= PJMEDIA_VID_PACKING_WHOLE; 
     716            if (desc->packetize && desc->unpacketize) 
     717                desc->info.packings |= PJMEDIA_VID_PACKING_PACKETS; 
    711718 
    712719            if (copied_dir != PJMEDIA_DIR_NONE) { 
     
    802809{ 
    803810    const ffmpeg_codec_desc *desc; 
     811    unsigned i; 
    804812 
    805813    PJ_ASSERT_RETURN(factory==&ffmpeg_factory.base, PJ_EINVAL); 
     
    812820 
    813821    pj_bzero(attr, sizeof(pjmedia_vid_codec_param)); 
     822 
     823    /* Scan the requested packings and use the lowest number */ 
     824    attr->packing = 0; 
     825    for (i=0; i<15; ++i) { 
     826        unsigned packing = (1 << i); 
     827        if ((desc->info.packings & info->packings) & packing) { 
     828            attr->packing = (pjmedia_vid_packing)packing; 
     829            break; 
     830        } 
     831    } 
     832    if (attr->packing == 0) { 
     833        /* No supported packing in info */ 
     834        return PJMEDIA_CODEC_EUNSUP; 
     835    } 
    814836 
    815837    /* Direction */ 
     
    11531175    } 
    11541176 
     1177    /* Alloc buffers if needed */ 
     1178    ff->whole = (ff->param.packing == PJMEDIA_VID_PACKING_WHOLE); 
     1179    if (!ff->whole) { 
     1180        ff->enc_buf_size = ff->enc_vafp.framebytes; 
     1181        ff->enc_buf = pj_pool_alloc(ff->pool, ff->enc_buf_size); 
     1182 
     1183        ff->dec_buf_size = ff->dec_vafp.framebytes; 
     1184        ff->dec_buf = pj_pool_alloc(ff->pool, ff->dec_buf_size); 
     1185    } 
     1186 
    11551187    /* Update codec attributes, e.g: encoding format may be changed by 
    11561188     * SDP fmtp negotiation. 
     
    12601292 * Encode frames. 
    12611293 */ 
    1262 static pj_status_t ffmpeg_codec_encode( pjmedia_vid_codec *codec,  
    1263                                         const pjmedia_frame *input, 
    1264                                         unsigned output_buf_len,  
    1265                                         pjmedia_frame *output) 
     1294static pj_status_t ffmpeg_codec_encode_whole(pjmedia_vid_codec *codec, 
     1295                                             const pjmedia_frame *input, 
     1296                                             unsigned output_buf_len, 
     1297                                             pjmedia_frame *output) 
    12661298{ 
    12671299    ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data; 
     
    13121344} 
    13131345 
     1346static pj_status_t ffmpeg_codec_encode_begin( pjmedia_vid_codec *codec, 
     1347                                              const pjmedia_frame *input, 
     1348                                              unsigned out_size, 
     1349                                              pjmedia_frame *output, 
     1350                                              pj_bool_t *has_more) 
     1351{ 
     1352    ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data; 
     1353    pj_status_t status; 
     1354 
     1355    *has_more = PJ_FALSE; 
     1356 
     1357    if (ff->whole) { 
     1358        status = ffmpeg_codec_encode_whole(codec, input, out_size, output); 
     1359    } else { 
     1360        pjmedia_frame whole_frm; 
     1361        const pj_uint8_t *payload; 
     1362        pj_size_t payload_len; 
     1363 
     1364        pj_bzero(&whole_frm, sizeof(whole_frm)); 
     1365        whole_frm.buf = ff->enc_buf; 
     1366        whole_frm.size = ff->enc_buf_size; 
     1367        status = ffmpeg_codec_encode_whole(codec, input, 
     1368                                           whole_frm.size, &whole_frm); 
     1369        if (status != PJ_SUCCESS) 
     1370            return status; 
     1371 
     1372        ff->enc_frame_len = (unsigned)whole_frm.size; 
     1373        ff->enc_processed = 0; 
     1374        status = ffmpeg_packetize(codec, (pj_uint8_t*)whole_frm.buf, 
     1375                                  whole_frm.size, &ff->enc_processed, 
     1376                                  &payload, &payload_len); 
     1377        if (status != PJ_SUCCESS) 
     1378            return status; 
     1379 
     1380        if (out_size < payload_len) 
     1381            return PJMEDIA_CODEC_EFRMTOOSHORT; 
     1382 
     1383        output->type = PJMEDIA_FRAME_TYPE_VIDEO; 
     1384        pj_memcpy(output->buf, payload, payload_len); 
     1385        output->size = payload_len; 
     1386 
     1387        *has_more = (ff->enc_processed < ff->enc_frame_len); 
     1388    } 
     1389 
     1390    return status; 
     1391} 
     1392 
     1393static pj_status_t ffmpeg_codec_encode_more(pjmedia_vid_codec *codec, 
     1394                                            unsigned out_size, 
     1395                                            pjmedia_frame *output, 
     1396                                            pj_bool_t *has_more) 
     1397{ 
     1398    ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data; 
     1399    const pj_uint8_t *payload; 
     1400    pj_size_t payload_len; 
     1401    pj_status_t status; 
     1402 
     1403    *has_more = PJ_FALSE; 
     1404 
     1405    if (ff->enc_processed >= ff->enc_frame_len) { 
     1406        /* No more frame */ 
     1407        return PJ_EEOF; 
     1408    } 
     1409 
     1410    status = ffmpeg_packetize(codec, (pj_uint8_t*)ff->enc_buf, 
     1411                              ff->enc_frame_len, &ff->enc_processed, 
     1412                              &payload, &payload_len); 
     1413    if (status != PJ_SUCCESS) 
     1414        return status; 
     1415 
     1416    if (out_size < payload_len) 
     1417        return PJMEDIA_CODEC_EFRMTOOSHORT; 
     1418 
     1419    output->type = PJMEDIA_FRAME_TYPE_VIDEO; 
     1420    pj_memcpy(output->buf, payload, payload_len); 
     1421    output->size = payload_len; 
     1422 
     1423    *has_more = (ff->enc_processed < ff->enc_frame_len); 
     1424 
     1425    return PJ_SUCCESS; 
     1426} 
     1427 
     1428 
    13141429/* 
    13151430 * Decode frame. 
    13161431 */ 
    1317 static pj_status_t ffmpeg_codec_decode( pjmedia_vid_codec *codec,  
    1318                                         const pjmedia_frame *input, 
    1319                                         unsigned output_buf_len,  
    1320                                         pjmedia_frame *output) 
     1432static pj_status_t ffmpeg_codec_decode_whole(pjmedia_vid_codec *codec, 
     1433                                             const pjmedia_frame *input, 
     1434                                             unsigned output_buf_len, 
     1435                                             pjmedia_frame *output) 
    13211436{ 
    13221437    ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data; 
     
    14171532                return status; 
    14181533 
     1534            /* Realloc buffer if necessary */ 
     1535            if (ff->dec_vafp.framebytes > ff->dec_buf_size) { 
     1536                PJ_LOG(5,(THIS_FILE, "Reallocating decoding buffer %u --> %u", 
     1537                           (unsigned)ff->dec_buf_size, 
     1538                           (unsigned)ff->dec_vafp.framebytes)); 
     1539                ff->dec_buf_size = ff->dec_vafp.framebytes; 
     1540                ff->dec_buf = pj_pool_alloc(ff->pool, ff->dec_buf_size); 
     1541            } 
     1542 
    14191543            /* Broadcast event */ 
    14201544            if (pjmedia_event_publisher_has_sub(&codec->epub)) { 
     
    14761600} 
    14771601 
     1602static pj_status_t ffmpeg_codec_decode( pjmedia_vid_codec *codec, 
     1603                                        pj_size_t pkt_count, 
     1604                                        pjmedia_frame packets[], 
     1605                                        unsigned out_size, 
     1606                                        pjmedia_frame *output) 
     1607{ 
     1608    ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data; 
     1609    pj_status_t status; 
     1610 
     1611    PJ_ASSERT_RETURN(codec && pkt_count > 0 && packets && output, 
     1612                     PJ_EINVAL); 
     1613 
     1614    if (ff->whole) { 
     1615        pj_assert(pkt_count==1); 
     1616        return ffmpeg_codec_decode_whole(codec, &packets[0], out_size, output); 
     1617    } else { 
     1618        pjmedia_frame whole_frm; 
     1619        unsigned whole_len = 0; 
     1620        unsigned i; 
     1621 
     1622        for (i=0; i<pkt_count; ++i) { 
     1623            if (whole_len + packets[i].size > ff->dec_buf_size) { 
     1624                PJ_LOG(5,(THIS_FILE, "Decoding buffer overflow")); 
     1625                break; 
     1626            } 
     1627 
     1628            status = ffmpeg_unpacketize(codec, packets[i].buf, packets[i].size, 
     1629                                        ff->dec_buf, ff->dec_buf_size, 
     1630                                        &whole_len); 
     1631            if (status != PJ_SUCCESS) { 
     1632                PJ_PERROR(5,(THIS_FILE, status, "Unpacketize error")); 
     1633                continue; 
     1634            } 
     1635        } 
     1636 
     1637        whole_frm.buf = ff->dec_buf; 
     1638        whole_frm.size = whole_len; 
     1639        whole_frm.timestamp = output->timestamp = packets[i].timestamp; 
     1640        whole_frm.bit_info = 0; 
     1641 
     1642        return ffmpeg_codec_decode_whole(codec, &whole_frm, out_size, output); 
     1643    } 
     1644} 
     1645 
    14781646 
    14791647#ifdef _MSC_VER 
  • pjproject/trunk/pjmedia/src/pjmedia/endpoint.c

    r3667 r3776  
    585585 
    586586        /* Must support RTP packetization and bidirectional */ 
    587         if (!codec_info[i].has_rtp_pack || 
     587        if ((codec_info[i].packings & PJMEDIA_VID_PACKING_PACKETS) == 0 || 
    588588            codec_info[i].dir != PJMEDIA_DIR_ENCODING_DECODING) 
    589589        { 
  • 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); 
  • pjproject/trunk/pjmedia/src/test/vid_codec_test.c

    r3715 r3776  
    2929#define THIS_FILE "vid_codec.c" 
    3030 
    31 #define BYPASS_CODEC        0 
    32 #define BYPASS_PACKETIZER   0 
    33  
    3431/*  
    3532 * Capture device setting:  
     
    8178                                   pjmedia_frame *frame) 
    8279{ 
     80    enum { MAX_PACKETS = 50 }; 
    8381    codec_port_data_t *port_data = (codec_port_data_t*)port->port_data.pdata; 
    8482    pj_status_t status; 
    85  
    86 #if !BYPASS_CODEC 
    87     { 
    88         pjmedia_vid_codec *codec = port_data->codec; 
    89         pjmedia_frame enc_frame; 
    90  
    91         enc_frame.buf = port_data->enc_buf; 
    92         enc_frame.size = port_data->enc_buf_size; 
    93  
    94         status = pjmedia_vid_codec_encode(codec, frame, enc_frame.size, 
    95                                           &enc_frame); 
    96         if (status != PJ_SUCCESS) goto on_error; 
    97  
    98 #if !BYPASS_PACKETIZER 
    99         if (enc_frame.size) { 
    100             unsigned pos = 0; 
    101             pj_bool_t packetized = PJ_FALSE; 
    102             unsigned unpack_pos = 0; 
    103              
    104             while (pos < enc_frame.size) { 
    105                 pj_uint8_t *payload; 
    106                 pj_size_t payload_len; 
    107  
    108                 status = pjmedia_vid_codec_packetize( 
    109                                                 codec,  
    110                                                 (pj_uint8_t*)enc_frame.buf, 
    111                                                 enc_frame.size, &pos, 
    112                                                 (const pj_uint8_t**)&payload, 
    113                                                 &payload_len); 
    114                 if (status == PJ_ENOTSUP) 
    115                     break; 
    116                 if (status != PJ_SUCCESS) 
    117                     goto on_error; 
    118  
    119                 status = pjmedia_vid_codec_unpacketize( 
    120                                                 codec, payload, payload_len, 
    121                                                 port_data->pack_buf, 
    122                                                 port_data->pack_buf_size, 
    123                                                 &unpack_pos); 
    124                 if (status != PJ_SUCCESS) 
    125                     goto on_error; 
    126  
    127                 // what happen if the bitstream is broken? 
    128                 //if (i++ != 1) unpack_pos -= 10; 
    129  
    130                 packetized = PJ_TRUE; 
    131             } 
    132  
    133             if (packetized) { 
    134                 enc_frame.buf  = port_data->pack_buf; 
    135                 enc_frame.size = unpack_pos; 
    136             } 
     83    pjmedia_vid_codec *codec = port_data->codec; 
     84    unsigned enc_cnt = 0; 
     85    pj_uint8_t *enc_buf; 
     86    unsigned enc_size_left; 
     87    pjmedia_frame enc_frames[MAX_PACKETS]; 
     88    pj_bool_t has_more = PJ_FALSE; 
     89 
     90    enc_buf = port_data->enc_buf; 
     91    enc_size_left = port_data->enc_buf_size; 
     92 
     93    /* 
     94     * Encode 
     95     */ 
     96    enc_frames[enc_cnt].buf = enc_buf; 
     97    enc_frames[enc_cnt].size = enc_size_left; 
     98 
     99    status = pjmedia_vid_codec_encode_begin(codec, frame, enc_size_left, 
     100                                            &enc_frames[enc_cnt], &has_more); 
     101    if (status != PJ_SUCCESS) goto on_error; 
     102 
     103    enc_buf += enc_frames[enc_cnt].size; 
     104    enc_size_left -= enc_frames[enc_cnt].size; 
     105 
     106    ++enc_cnt; 
     107    while (has_more) { 
     108        enc_frames[enc_cnt].buf = enc_buf; 
     109        enc_frames[enc_cnt].size = enc_size_left; 
     110 
     111        status = pjmedia_vid_codec_encode_more(codec, enc_size_left, 
     112                                                &enc_frames[enc_cnt], 
     113                                                &has_more); 
     114        if (status != PJ_SUCCESS) 
     115            break; 
     116 
     117        enc_buf += enc_frames[enc_cnt].size; 
     118        enc_size_left -= enc_frames[enc_cnt].size; 
     119 
     120        ++enc_cnt; 
     121 
     122        if (enc_cnt >= MAX_PACKETS) { 
     123            assert(!"Too many packets!"); 
     124            break; 
    137125        } 
    138 #endif 
    139  
    140         status = pjmedia_vid_codec_decode(codec, &enc_frame, 
    141                                           frame->size, frame); 
    142         if (status != PJ_SUCCESS) goto on_error; 
    143     } 
    144 #endif 
    145  
     126    } 
     127 
     128    /* 
     129     * Decode 
     130     */ 
     131    status = pjmedia_vid_codec_decode(codec, enc_cnt, enc_frames, 
     132                                      frame->size, frame); 
     133    if (status != PJ_SUCCESS) goto on_error; 
     134 
     135    /* Display */ 
    146136    status = pjmedia_port_put_frame( 
    147137                        pjmedia_vid_port_get_passive_port(port_data->rdr_port), 
     
    196186} 
    197187 
    198 static int encode_decode_test(pj_pool_t *pool, const char *codec_id) 
     188static int encode_decode_test(pj_pool_t *pool, const char *codec_id, 
     189                              pjmedia_vid_packing packing) 
    199190{ 
    200191    const pj_str_t port_name = {"codec", 5}; 
     
    205196    pjmedia_vid_codec_param codec_param; 
    206197    const pjmedia_vid_codec_info *codec_info; 
    207  
     198    const char *packing_name; 
    208199    pjmedia_vid_dev_index cap_idx, rdr_idx; 
    209200    pjmedia_vid_port *capture=NULL, *renderer=NULL; 
     
    211202    pjmedia_video_format_detail *vfd; 
    212203    pjmedia_event_subscription esub; 
     204    char codec_name[5]; 
    213205    pj_status_t status; 
    214206    int rc = 0; 
    215207 
    216     PJ_LOG(3, (THIS_FILE, "  encode decode test")); 
     208    switch (packing) { 
     209    case PJMEDIA_VID_PACKING_PACKETS: 
     210        packing_name = "framed"; 
     211        break; 
     212    case PJMEDIA_VID_PACKING_WHOLE: 
     213        packing_name = "whole"; 
     214        break; 
     215    default: 
     216        packing_name = "unknown"; 
     217        break; 
     218    } 
     219 
     220    PJ_LOG(3, (THIS_FILE, "  encode decode test: codec=%s, packing=%s", 
     221               codec_id, packing_name)); 
    217222 
    218223    /* Lookup codec */ 
     
    294299        } 
    295300 
    296 #if !BYPASS_CODEC 
     301        codec_param.packing = packing; 
    297302 
    298303        /* Open codec */ 
     
    322327                                        &codec_port_data); 
    323328        pjmedia_event_subscribe(&codec->epub, &esub); 
    324 #endif /* !BYPASS_CODEC */ 
    325329    } 
    326330 
     
    393397    } 
    394398 
    395 #if BYPASS_CODEC 
    396     PJ_LOG(3, (THIS_FILE, "  starting loopback test: %c%c%c%c %dx%d", 
    397         ((codec_param.dec_fmt.id & 0x000000FF) >> 0), 
    398         ((codec_param.dec_fmt.id & 0x0000FF00) >> 8), 
    399         ((codec_param.dec_fmt.id & 0x00FF0000) >> 16), 
    400         ((codec_param.dec_fmt.id & 0xFF000000) >> 24), 
    401         codec_param.dec_fmt.det.vid.size.w, 
    402         codec_param.dec_fmt.det.vid.size.h 
    403         )); 
    404 #else 
    405     PJ_LOG(3, (THIS_FILE, "  starting codec test: %c%c%c%c<->%.*s %dx%d", 
    406         ((codec_param.dec_fmt.id & 0x000000FF) >> 0), 
    407         ((codec_param.dec_fmt.id & 0x0000FF00) >> 8), 
    408         ((codec_param.dec_fmt.id & 0x00FF0000) >> 16), 
    409         ((codec_param.dec_fmt.id & 0xFF000000) >> 24), 
     399    PJ_LOG(3, (THIS_FILE, "    starting codec test: %s<->%.*s %dx%d", 
     400        pjmedia_fourcc_name(codec_param.dec_fmt.id, codec_name), 
    410401        codec_info->encoding_name.slen, 
    411402        codec_info->encoding_name.ptr, 
     
    413404        codec_param.dec_fmt.det.vid.size.h 
    414405        )); 
    415 #endif 
    416406 
    417407    /* Start streaming.. */ 
     
    456446     
    457447    orig_log_level = pj_log_get_level(); 
    458     pj_log_set_level(6); 
     448    pj_log_set_level(3); 
    459449 
    460450    PJ_LOG(3, (THIS_FILE, "Performing video codec tests..")); 
     
    476466        goto on_return; 
    477467 
    478     rc = encode_decode_test(pool, "h263-1998"); 
     468    rc = encode_decode_test(pool, "h263-1998", PJMEDIA_VID_PACKING_WHOLE); 
     469    if (rc != 0) 
     470        goto on_return; 
     471 
     472    rc = encode_decode_test(pool, "h263-1998", PJMEDIA_VID_PACKING_PACKETS); 
    479473    if (rc != 0) 
    480474        goto on_return; 
  • pjproject/trunk/pjsip-apps/src/samples/aviplay.c

    r3688 r3776  
    154154        if (status != PJ_SUCCESS) goto on_error; 
    155155         
    156         status = pjmedia_vid_codec_decode(codec, frame, frame->size, &enc_frame); 
     156        status = pjmedia_vid_codec_decode(codec, 1, frame, 
     157                                          frame->size, &enc_frame); 
    157158        if (status != PJ_SUCCESS) goto on_error; 
    158159         
     
    167168    if (status != PJ_SUCCESS) goto on_error; 
    168169     
    169     status = pjmedia_vid_codec_decode(codec, &enc_frame, frame->size, frame); 
     170    status = pjmedia_vid_codec_decode(codec, 1, &enc_frame, 
     171                                      frame->size, frame); 
    170172    if (status != PJ_SUCCESS) goto on_error; 
    171173     
     
    292294             
    293295            pjmedia_format_copy(&codec_param.dec_fmt, &param.vidparam.fmt); 
    294              
     296            codec_param.packing = PJMEDIA_VID_PACKING_WHOLE; 
    295297            status = pjmedia_vid_codec_open(codec, &codec_param); 
    296298            if (status != PJ_SUCCESS) { 
  • pjproject/trunk/pjsip-apps/src/samples/vid_streamutil.c

    r3667 r3776  
    302302        write_frame.buf = play_file->dec_buf; 
    303303        write_frame.size = play_file->dec_buf_size; 
    304         status = decoder->op->decode(decoder, &read_frame, write_frame.size, 
    305                                     &write_frame); 
     304        status = pjmedia_vid_codec_decode(decoder, 1, &read_frame, 
     305                                          write_frame.size, &write_frame); 
    306306        if (status != PJ_SUCCESS) 
    307307            return; 
     
    616616        pjmedia_video_format_detail *file_vfd; 
    617617        pjmedia_clock_param clock_param; 
     618        char fmt_name[5]; 
    618619 
    619620        /* Create file player */ 
     
    625626        file_vfd = pjmedia_format_get_video_format_detail(&play_port->info.fmt, 
    626627                                                          PJ_TRUE); 
    627         PJ_LOG(2, (THIS_FILE, "Reading video stream %dx%d %c%c%c%c @%.2ffps", 
     628        PJ_LOG(2, (THIS_FILE, "Reading video stream %dx%d %s @%.2ffps", 
    628629                   file_vfd->size.w, file_vfd->size.h, 
    629                    ((play_port->info.fmt.id & 0x000000FF) >> 0), 
    630                    ((play_port->info.fmt.id & 0x0000FF00) >> 8), 
    631                    ((play_port->info.fmt.id & 0x00FF0000) >> 16), 
    632                    ((play_port->info.fmt.id & 0xFF000000) >> 24), 
     630                   pjmedia_fourcc_name(play_port->info.fmt.id, fmt_name), 
    633631                   (1.0*file_vfd->fps.num/file_vfd->fps.denum))); 
    634632 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_vid.c

    r3774 r3776  
    225225 
    226226    for (i=0, j=0; i<count && j<*p_count; ++i) { 
    227         if (info[i].has_rtp_pack) { 
     227        if (info[i].packings & PJMEDIA_VID_PACKING_PACKETS) { 
    228228            pj_bzero(&id[j], sizeof(pjsua_codec_info)); 
    229229 
Note: See TracChangeset for help on using the changeset viewer.