Re #1219:
 - Initial version of H264 implementation (codec & packetization).
 - Added vid_codec_util.h/c for video codec utilities (e.g: fmtp parser).
 - Updated video RTP packetizations to be configurable and have internal state (to be more resilient to packet lost, etc).
 - Fixed wrong SPF calculation in PJMEDIA_SPF2.
 - Updated vid_codec_test.c to also have RTP packetization test.
 - Updated sdp_neg.c to verify H.264 capability match.



git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/projects/2.0-dev@3493 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjmedia/include/pjmedia-codec/h263_packetizer.h b/pjmedia/include/pjmedia-codec/h263_packetizer.h
index 930115a..b80faf8 100644
--- a/pjmedia/include/pjmedia-codec/h263_packetizer.h
+++ b/pjmedia/include/pjmedia-codec/h263_packetizer.h
@@ -22,121 +22,122 @@
 
 /**
  * @file h263_packetizer.h
- * @brief Packetizes H.263 bitstream into RTP payload.
+ * @brief Packetizes/unpacketizes H.263 bitstream into RTP payload.
  */
 
-#include <pj/errno.h>
+#include <pj/pool.h>
+#include <pj/types.h>
 
 PJ_BEGIN_DECL
 
-/**
- * Find synchronization point (PSC, slice, GSBC, EOS, EOSBS) in H.263 
- * bitstream, in reversed manner.
- */
-PJ_INLINE(pj_uint8_t*) pjmedia_h263_find_sync_point_rev(pj_uint8_t *data,
-                                                        pj_size_t data_len)
-{
-    pj_uint8_t *p = data+data_len-1;
-
-    while (p > data && *p && *(p+1))
-        --p;
-
-    if (p == data)
-        return (data + data_len);
-        
-    return p;
-}
 
 /**
- * Generate an RTP payload from H.263 frame bitstream, in-place processing.
+ * Opaque declaration for H.263 packetizer.
  */
-PJ_INLINE(pj_status_t) pjmedia_h263_packetize(pj_uint8_t *buf,
-                                              pj_size_t buf_len,
-                                              unsigned *pos,
-                                              int max_payload_len,
-                                              const pj_uint8_t **payload,
-                                              pj_size_t *payload_len)
+typedef struct pjmedia_h263_packetizer pjmedia_h263_packetizer;
+
+
+/**
+ * Enumeration of H.263 packetization modes.
+ */
+typedef enum
 {
-    pj_uint8_t *p, *p_end;
-
-    p = buf + *pos;
-    p_end = buf + buf_len;
-
-    /* Put two octets payload header */
-    if ((p_end-p > 2) && *p==0 && *(p+1)==0) {
-        /* The bitstream starts with synchronization point, just override
-         * the two zero octets (sync point mark) for payload header.
-         */
-        *p = 0x04;
-    } else {
-        /* Not started in synchronization point, we will use two octets
-         * preceeding the bitstream for payload header!
-         */
-
-	if (*pos < 2) {
-	    /* Invalid H263 bitstream, it's not started with PSC */
-	    return PJ_EINVAL;
-	}
-
-	p -= 2;
-        *p = 0;
-    }
-    *(p+1) = 0;
-
-    /* When bitstream truncation needed because of payload length/MTU 
-     * limitation, try to use sync point for the payload boundary.
+    /**
+     * H.263 RTP packetization using RFC 4629.
      */
-    if (p_end-p > max_payload_len) {
-        p_end = pjmedia_h263_find_sync_point_rev(p+2, max_payload_len-2);
-    }
+    PJMEDIA_H263_PACKETIZER_MODE_RFC4629,
 
-    *payload = p;
-    *payload_len = p_end-p;
-    *pos = p_end - buf;
+    /**
+     * H.263 RTP packetization using legacy RFC 2190.
+     * This is currently not supported.
+     */
+    PJMEDIA_H263_PACKETIZER_MODE_RFC2190,
 
-    return PJ_SUCCESS;
-}
+} pjmedia_h263_packetizer_mode;
+
 
 /**
- * Append RTP payload to a H.263 picture bitstream.
+ * H.263 packetizer configuration.
  */
-PJ_INLINE(pj_status_t) pjmedia_h263_unpacketize(const pj_uint8_t *payload,
-                                                pj_size_t   payload_len,
-                                                pj_uint8_t *bits,
-                                                pj_size_t  *bits_len)
+typedef struct pjmedia_h263_packetizer_cfg
 {
-    pj_uint8_t P, V, PLEN;
-    const pj_uint8_t *p=payload;
-    pj_size_t max_len = *bits_len;
+    /**
+     * Maximum payload length.
+     * Default: PJMEDIA_MAX_MTU
+     */
+    int	mtu;
 
-    P = *p & 0x04;
-    V = *p & 0x02;
-    PLEN = ((*p & 0x01) << 5) + ((*(p+1) & 0xF8)>>3);
+    /**
+     * Packetization mode.
+     * Default: PJMEDIA_H263_PACKETIZER_MODE_RFC4629
+     */
+    pjmedia_h263_packetizer_mode mode;
 
-    /* Get bitstream pointer */
-    p += 2;
-    if (V)
-        p += 1; /* Skip VRC data */
-    if (PLEN)
-        p += PLEN; /* Skip extra picture header data */
+} pjmedia_h263_packetizer_cfg;
 
-    /* Get bitstream length */
-    payload_len -= (p-payload);
 
-    *bits_len = payload_len + (P?2:0);
-    PJ_ASSERT_RETURN(max_len >= *bits_len, PJ_ETOOSMALL);
+/**
+ * Create H.263 packetizer.
+ *
+ * @param pool		The memory pool.
+ * @param cfg		Packetizer settings, if NULL, default setting
+ *			will be used.
+ * @param p_pktz	Pointer to receive the packetizer.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_h263_packetizer_create(
+				    pj_pool_t *pool,
+				    const pjmedia_h263_packetizer_cfg *cfg,
+				    pjmedia_h263_packetizer **p_pktz);
 
-    /* Add two zero octets when payload flagged with sync point */
-    if (P) {
-        *bits++ = 0;
-        *bits++ = 0;
-    }
 
-    /* Add the bitstream */
-    pj_memcpy(bits, p, payload_len);
+/**
+ * Generate an RTP payload from a H.263 picture bitstream. Note that this
+ * function will apply in-place processing, so the bitstream may be modified
+ * during the packetization.
+ *
+ * @param pktz		The packetizer.
+ * @param bits		The picture bitstream to be packetized.
+ * @param bits_len	The length of the bitstream.
+ * @param bits_pos	The bitstream offset to be packetized.
+ * @param payload	The output payload.
+ * @param payload_len	The output payload length.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_h263_packetize(pjmedia_h263_packetizer *pktz,
+					    pj_uint8_t *bits,
+                                            pj_size_t bits_len,
+                                            unsigned *bits_pos,
+                                            const pj_uint8_t **payload,
+                                            pj_size_t *payload_len);
 
-    return PJ_SUCCESS;
-}
+
+/**
+ * Append an RTP payload to an H.263 picture bitstream. Note that in case of
+ * noticing packet lost, application should keep calling this function with
+ * payload pointer set to NULL, as the packetizer need to update its internal
+ * state.
+ *
+ * @param pktz		The packetizer.
+ * @param payload	The payload to be unpacketized.
+ * @param payload_len	The payload length.
+ * @param bits		The bitstream buffer.
+ * @param bits_size	The bitstream buffer size.
+ * @param bits_pos	The bitstream offset to put the unpacketized payload
+ *			in the bitstream, upon return, this will be updated
+ *			to the latest offset as a result of the unpacketized
+ *			payload.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_h263_unpacketize(pjmedia_h263_packetizer *pktz,
+					      const pj_uint8_t *payload,
+                                              pj_size_t payload_len,
+                                              pj_uint8_t *bits,
+                                              pj_size_t bits_size,
+					      unsigned *bits_pos);
 
 
 PJ_END_DECL
diff --git a/pjmedia/include/pjmedia-codec/h264_packetizer.h b/pjmedia/include/pjmedia-codec/h264_packetizer.h
new file mode 100644
index 0000000..a676a04
--- /dev/null
+++ b/pjmedia/include/pjmedia-codec/h264_packetizer.h
@@ -0,0 +1,157 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#ifndef __PJMEDIA_H264_PACKETIZER_H__
+#define __PJMEDIA_H264_PACKETIZER_H__
+
+/**
+ * @file h264_packetizer.h
+ * @brief Packetizes H.264 bitstream into RTP payload and vice versa.
+ */
+
+#include <pj/types.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * Opaque declaration for H.264 packetizer.
+ */
+typedef struct pjmedia_h264_packetizer pjmedia_h264_packetizer;
+
+
+/**
+ * Enumeration of H.264 packetization modes.
+ */
+typedef enum
+{
+    /**
+     * Single NAL unit packetization mode will only generate payloads
+     * containing a complete single NAL unit packet. As H.264 NAL unit
+     * size can be very large, this mode is usually not applicable for
+     * network environments with MTU size limitation.
+     */
+    PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL,
+    
+    /**
+     * Non-interleaved packetization mode will generate payloads with the
+     * following possible formats:
+     * - single NAL unit packets,
+     * - NAL units aggregation STAP-A packets,
+     * - fragmented NAL unit FU-A packets.
+     */
+    PJMEDIA_H264_PACKETIZER_MODE_NON_INTERLEAVED,
+
+    /**
+     * Interleaved packetization mode will generate payloads with the
+     * following possible formats:
+     * - single NAL unit packets,
+     * - NAL units aggregation STAP-A & STAP-B packets,
+     * - fragmented NAL unit FU-A & FU-B packets.
+     * This packetization mode is currently unsupported.
+     */
+    PJMEDIA_H264_PACKETIZER_MODE_INTERLEAVED,
+} pjmedia_h264_packetizer_mode;
+
+
+/**
+ * H.264 packetizer setting.
+ */
+typedef struct pjmedia_h264_packetizer_cfg
+{
+    /**
+     * Maximum payload length.
+     * Default: PJMEDIA_MAX_MTU
+     */
+    int	mtu;
+
+    /**
+     * Packetization mode.
+     * Default: PJMEDIA_H264_PACKETIZER_MODE_NON_INTERLEAVED
+     */
+    pjmedia_h264_packetizer_mode mode;
+}
+pjmedia_h264_packetizer_cfg;
+
+
+/**
+ * Create H.264 packetizer.
+ *
+ * @param pool		The memory pool.
+ * @param cfg		Packetizer settings, if NULL, default setting
+ *			will be used.
+ * @param p_pktz	Pointer to receive the packetizer.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_h264_packetizer_create(
+				    pj_pool_t *pool,
+				    const pjmedia_h264_packetizer_cfg *cfg,
+				    pjmedia_h264_packetizer **p_pktz);
+
+
+/**
+ * Generate an RTP payload from a H.264 picture bitstream. Note that this
+ * function will apply in-place processing, so the bitstream may be modified
+ * during the packetization.
+ *
+ * @param pktz		The packetizer.
+ * @param bits		The picture bitstream to be packetized.
+ * @param bits_len	The length of the bitstream.
+ * @param bits_pos	The bitstream offset to be packetized.
+ * @param payload	The output payload.
+ * @param payload_len	The output payload length.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_h264_packetize(pjmedia_h264_packetizer *pktz,
+					    pj_uint8_t *bits,
+                                            pj_size_t bits_len,
+                                            unsigned *bits_pos,
+                                            const pj_uint8_t **payload,
+                                            pj_size_t *payload_len);
+
+
+/**
+ * Append an RTP payload to an H.264 picture bitstream. Note that in case of
+ * noticing packet lost, application should keep calling this function with
+ * payload pointer set to NULL, as the packetizer need to update its internal
+ * state.
+ *
+ * @param pktz		The packetizer.
+ * @param payload	The payload to be unpacketized.
+ * @param payload_len	The payload length.
+ * @param bits		The bitstream buffer.
+ * @param bits_size	The bitstream buffer size.
+ * @param bits_pos	The bitstream offset to put the unpacketized payload
+ *			in the bitstream, upon return, this will be updated
+ *			to the latest offset as a result of the unpacketized
+ *			payload.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_h264_unpacketize(pjmedia_h264_packetizer *pktz,
+					      const pj_uint8_t *payload,
+                                              pj_size_t   payload_len,
+                                              pj_uint8_t *bits,
+                                              pj_size_t   bits_len,
+					      unsigned   *bits_pos);
+
+
+PJ_END_DECL
+
+#endif	/* __PJMEDIA_H264_PACKETIZER_H__ */