* #27232: jni: added pjproject checkout as regular git content

We will remove it once the next release of pjsip (with Android support)
comes out and is merged into SFLphone.
diff --git a/jni/pjproject-android/pjmedia/src/pjmedia-codec/h264_packetizer.c b/jni/pjproject-android/pjmedia/src/pjmedia-codec/h264_packetizer.c
new file mode 100644
index 0000000..9b22334
--- /dev/null
+++ b/jni/pjproject-android/pjmedia/src/pjmedia-codec/h264_packetizer.c
@@ -0,0 +1,535 @@
+/* $Id: h264_packetizer.c 4537 2013-06-19 06:47:43Z riza $ */
+/* 
+ * 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 
+ */
+#include <pjmedia-codec/h264_packetizer.h>
+#include <pjmedia/types.h>
+#include <pj/assert.h>
+#include <pj/errno.h>
+#include <pj/log.h>
+#include <pj/pool.h>
+#include <pj/string.h>
+
+
+#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
+
+
+#define THIS_FILE		"h264_packetizer.c"
+
+#define DBG_PACKETIZE		0
+#define DBG_UNPACKETIZE		0
+
+
+/* H.264 packetizer definition */
+struct pjmedia_h264_packetizer
+{
+    /* Current settings */
+    pjmedia_h264_packetizer_cfg cfg;
+    
+    /* Unpacketizer state */
+    unsigned	    unpack_last_sync_pos;
+    pj_bool_t	    unpack_prev_lost;
+};
+
+
+/* Enumeration of H.264 NAL unit types */
+enum
+{
+    NAL_TYPE_SINGLE_NAL_MIN	= 1,
+    NAL_TYPE_SINGLE_NAL_MAX	= 23,
+    NAL_TYPE_STAP_A		= 24,
+    NAL_TYPE_FU_A		= 28,
+};
+
+
+/*
+ * Find next NAL unit from the specified H.264 bitstream data.
+ */
+static pj_uint8_t* find_next_nal_unit(pj_uint8_t *start,
+                                      pj_uint8_t *end)
+{
+    pj_uint8_t *p = start;
+
+    /* Simply lookup "0x000001" pattern */
+    while (p <= end-3 && (p[0] || p[1] || p[2]!=1))
+        ++p;
+
+    if (p > end-3)
+	/* No more NAL unit in this bitstream */
+        return NULL;
+
+    /* Include 8 bits leading zero */
+    if (p>start && *(p-1)==0)
+	return (p-1);
+
+    return p;
+}
+
+
+/*
+ * Create H264 packetizer.
+ */
+PJ_DEF(pj_status_t) pjmedia_h264_packetizer_create(
+				pj_pool_t *pool,
+				const pjmedia_h264_packetizer_cfg *cfg,
+				pjmedia_h264_packetizer **p)
+{
+    pjmedia_h264_packetizer *p_;
+
+    PJ_ASSERT_RETURN(pool && p, PJ_EINVAL);
+
+    if (cfg &&
+	cfg->mode != PJMEDIA_H264_PACKETIZER_MODE_NON_INTERLEAVED &&
+	cfg->mode != PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL)
+    {
+	return PJ_ENOTSUP;
+    }
+
+    p_ = PJ_POOL_ZALLOC_T(pool, pjmedia_h264_packetizer);
+    if (cfg) {
+	pj_memcpy(&p_->cfg, cfg, sizeof(*cfg));
+    } else {
+	p_->cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_NON_INTERLEAVED;
+	p_->cfg.mtu = PJMEDIA_MAX_VID_PAYLOAD_SIZE;
+    }
+
+    *p = p_;
+
+    return PJ_SUCCESS;
+}
+
+
+
+/*
+ * Generate an RTP payload from H.264 frame bitstream, in-place processing.
+ */
+PJ_DEF(pj_status_t) pjmedia_h264_packetize(pjmedia_h264_packetizer *pktz,
+					   pj_uint8_t *buf,
+                                           pj_size_t buf_len,
+                                           unsigned *pos,
+                                           const pj_uint8_t **payload,
+                                           pj_size_t *payload_len)
+{
+    pj_uint8_t *nal_start = NULL, *nal_end = NULL, *nal_octet = NULL;
+    pj_uint8_t *p, *end;
+    enum { 
+	HEADER_SIZE_FU_A	     = 2,
+	HEADER_SIZE_STAP_A	     = 3,
+    };
+    enum { MAX_NALS_IN_AGGR = 32 };
+
+#if DBG_PACKETIZE
+    if (*pos == 0 && buf_len) {
+	PJ_LOG(3, ("h264pack", "<< Start packing new frame >>"));
+    }
+#endif
+
+    p = buf + *pos;
+    end = buf + buf_len;
+
+    /* Find NAL unit startcode */
+    if (end-p >= 4)
+	nal_start = find_next_nal_unit(p, p+4);
+    if (nal_start) {
+	/* Get NAL unit octet pointer */
+	while (*nal_start++ == 0);
+	nal_octet = nal_start;
+    } else {
+	/* This NAL unit is being fragmented */
+	nal_start = p;
+    }
+
+    /* Get end of NAL unit */
+    p = nal_start+pktz->cfg.mtu+1;
+    if (p > end || pktz->cfg.mode==PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL) 
+	p = end;
+    nal_end = find_next_nal_unit(nal_start, p); 
+    if (!nal_end)
+	nal_end = p;
+
+    /* Validate MTU vs NAL length on single NAL unit packetization */
+    if ((pktz->cfg.mode==PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL) &&
+	nal_end - nal_start > pktz->cfg.mtu)
+    {
+	//pj_assert(!"MTU too small for H.264 single NAL packetization mode");
+	PJ_LOG(2,("h264_packetizer.c",
+		  "MTU too small for H.264 (required=%u, MTU=%u)",
+		  nal_end - nal_start, pktz->cfg.mtu));
+	return PJ_ETOOSMALL;
+    }
+
+    /* Evaluate the proper payload format structure */
+
+    /* Fragmentation (FU-A) packet */
+    if ((pktz->cfg.mode != PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL) &&
+	(!nal_octet || nal_end-nal_start > pktz->cfg.mtu))
+    {
+	pj_uint8_t NRI, TYPE;
+
+	if (nal_octet) {
+	    /* We have NAL unit octet, so this is the first fragment */
+	    NRI = (*nal_octet & 0x60) >> 5;
+	    TYPE = *nal_octet & 0x1F;
+
+	    /* Skip nal_octet in nal_start to be overriden by FU header */
+	    ++nal_start;
+	} else {
+	    /* Not the first fragment, get NRI and NAL unit type
+	     * from the previous fragment.
+	     */
+	    p = nal_start - pktz->cfg.mtu;
+	    NRI = (*p & 0x60) >> 5;
+	    TYPE = *(p+1) & 0x1F;
+	}
+
+	/* Init FU indicator (one octet: F+NRI+TYPE) */
+	p = nal_start - HEADER_SIZE_FU_A;
+	*p = (NRI << 5) | NAL_TYPE_FU_A;
+	++p;
+
+	/* Init FU header (one octed: S+E+R+TYPE) */
+	*p = TYPE;
+	if (nal_octet)
+	    *p |= (1 << 7); /* S bit flag = start of fragmentation */
+	if (nal_end-nal_start+HEADER_SIZE_FU_A <= pktz->cfg.mtu)
+	    *p |= (1 << 6); /* E bit flag = end of fragmentation */
+
+	/* Set payload, payload length */
+	*payload = nal_start - HEADER_SIZE_FU_A;
+	if (nal_end-nal_start+HEADER_SIZE_FU_A > pktz->cfg.mtu)
+	    *payload_len = pktz->cfg.mtu;
+	else
+	    *payload_len = nal_end - nal_start + HEADER_SIZE_FU_A;
+	*pos = (unsigned)(*payload + *payload_len - buf);
+
+#if DBG_PACKETIZE
+	PJ_LOG(3, ("h264pack", "Packetized fragmented H264 NAL unit "
+		   "(pos=%d, type=%d, NRI=%d, S=%d, E=%d, len=%d/%d)",
+		   *payload-buf, TYPE, NRI, *p>>7, (*p>>6)&1, *payload_len,
+		   buf_len));
+#endif
+
+	return PJ_SUCCESS;
+    }
+
+    /* Aggregation (STAP-A) packet */
+    if ((pktz->cfg.mode != PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL) &&
+	(nal_end != end) &&
+	(nal_end - nal_start + HEADER_SIZE_STAP_A) < pktz->cfg.mtu) 
+    {
+	int total_size;
+	unsigned nal_cnt = 1;
+	pj_uint8_t *nal[MAX_NALS_IN_AGGR];
+	pj_size_t nal_size[MAX_NALS_IN_AGGR];
+	pj_uint8_t NRI;
+
+	pj_assert(nal_octet);
+
+	/* Init the first NAL unit in the packet */
+	nal[0] = nal_start;
+	nal_size[0] = nal_end - nal_start;
+	total_size = (int)nal_size[0] + HEADER_SIZE_STAP_A;
+	NRI = (*nal_octet & 0x60) >> 5;
+
+	/* Populate next NAL units */
+	while (nal_cnt < MAX_NALS_IN_AGGR) {
+	    pj_uint8_t *tmp_end;
+
+	    /* Find start address of the next NAL unit */
+	    p = nal[nal_cnt-1] + nal_size[nal_cnt-1];
+	    while (*p++ == 0);
+	    nal[nal_cnt] = p;
+
+	    /* Find end address of the next NAL unit */
+	    tmp_end = p + (pktz->cfg.mtu - total_size);
+	    if (tmp_end > end)
+		tmp_end = end;
+	    p = find_next_nal_unit(p+1, tmp_end);
+	    if (p) {
+		nal_size[nal_cnt] = p - nal[nal_cnt];
+	    } else {
+		break;
+	    }
+
+	    /* Update total payload size (2 octet NAL size + NAL) */
+	    total_size += (2 + (int)nal_size[nal_cnt]);
+	    if (total_size <= pktz->cfg.mtu) {
+		pj_uint8_t tmp_nri;
+
+		/* Get maximum NRI of the aggregated NAL units */
+		tmp_nri = (*(nal[nal_cnt]-1) & 0x60) >> 5;
+		if (tmp_nri > NRI)
+		    NRI = tmp_nri;
+	    } else {
+		break;
+	    }
+
+	    ++nal_cnt;
+	}
+
+	/* Only use STAP-A when we found more than one NAL units */
+	if (nal_cnt > 1) {
+	    unsigned i;
+
+	    /* Init STAP-A NAL header (F+NRI+TYPE) */
+	    p = nal[0] - HEADER_SIZE_STAP_A;
+	    *p++ = (NRI << 5) | NAL_TYPE_STAP_A;
+
+	    /* Append all populated NAL units into payload (SIZE+NAL) */
+	    for (i = 0; i < nal_cnt; ++i) {
+		/* Put size (2 octets in network order) */
+		pj_assert(nal_size[i] <= 0xFFFF);
+		*p++ = (pj_uint8_t)(nal_size[i] >> 8);
+		*p++ = (pj_uint8_t)(nal_size[i] & 0xFF);
+		
+		/* Append NAL unit, watchout memmove()-ing bitstream! */
+		if (p != nal[i])
+		    pj_memmove(p, nal[i], nal_size[i]);
+		p += nal_size[i];
+	    }
+
+	    /* Set payload, payload length, and pos */
+	    *payload = nal[0] - HEADER_SIZE_STAP_A;
+	    pj_assert(*payload >= buf+*pos);
+	    *payload_len = p - *payload;
+	    *pos = (unsigned)(nal[nal_cnt-1] + nal_size[nal_cnt-1] - buf);
+
+#if DBG_PACKETIZE
+	    PJ_LOG(3, ("h264pack", "Packetized aggregation of "
+		       "%d H264 NAL units (pos=%d, NRI=%d len=%d/%d)",
+		       nal_cnt, *payload-buf, NRI, *payload_len, buf_len));
+#endif
+
+	    return PJ_SUCCESS;
+	}
+    }
+
+    /* Single NAL unit packet */
+    *payload = nal_start;
+    *payload_len = nal_end - nal_start;
+    *pos = (unsigned)(nal_end - buf);
+
+#if DBG_PACKETIZE
+    PJ_LOG(3, ("h264pack", "Packetized single H264 NAL unit "
+	       "(pos=%d, type=%d, NRI=%d, len=%d/%d)",
+	       nal_start-buf, *nal_octet&0x1F, (*nal_octet&0x60)>>5,
+	       *payload_len, buf_len));
+#endif
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Append RTP payload to a H.264 picture bitstream. Note that the only
+ * payload format that cares about packet lost is the NAL unit
+ * fragmentation format (FU-A/B), so we will only manage the "prev_lost"
+ * state for the FU-A/B packets.
+ */
+PJ_DEF(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)
+{
+    const pj_uint8_t nal_start_code[3] = {0, 0, 1};
+    enum { MIN_PAYLOAD_SIZE = 2 };
+    pj_uint8_t nal_type;
+
+    PJ_UNUSED_ARG(pktz);
+
+#if DBG_UNPACKETIZE
+    if (*bits_pos == 0 && payload_len) {
+	PJ_LOG(3, ("h264unpack", ">> Start unpacking new frame <<"));
+    }
+#endif
+
+    /* Check if this is a missing/lost packet */
+    if (payload == NULL) {
+	pktz->unpack_prev_lost = PJ_TRUE;
+	return PJ_SUCCESS;
+    }
+
+    /* H264 payload size */
+    if (payload_len < MIN_PAYLOAD_SIZE) {
+	/* Invalid bitstream, discard this payload */
+	pktz->unpack_prev_lost = PJ_TRUE;
+	return PJ_EINVAL;
+    }
+
+    /* Reset last sync point for every new picture bitstream */
+    if (*bits_pos == 0)
+	pktz->unpack_last_sync_pos = 0;
+
+    nal_type = *payload & 0x1F;
+    if (nal_type >= NAL_TYPE_SINGLE_NAL_MIN &&
+	nal_type <= NAL_TYPE_SINGLE_NAL_MAX)
+    {
+	/* Single NAL unit packet */
+	pj_uint8_t *p = bits + *bits_pos;
+
+	/* Validate bitstream length */
+	if (bits_len-*bits_pos < payload_len+PJ_ARRAY_SIZE(nal_start_code)) {
+	    /* Insufficient bistream buffer, discard this payload */
+	    pj_assert(!"Insufficient H.263 bitstream buffer");
+	    return PJ_ETOOSMALL;
+	}
+
+	/* Write NAL unit start code */
+	pj_memcpy(p, &nal_start_code, PJ_ARRAY_SIZE(nal_start_code));
+	p += PJ_ARRAY_SIZE(nal_start_code);
+
+	/* Write NAL unit */
+	pj_memcpy(p, payload, payload_len);
+	p += payload_len;
+
+	/* Update the bitstream writing offset */
+	*bits_pos = (unsigned)(p - bits);
+	pktz->unpack_last_sync_pos = *bits_pos;
+
+#if DBG_UNPACKETIZE
+	PJ_LOG(3, ("h264unpack", "Unpacked single H264 NAL unit "
+		   "(type=%d, NRI=%d, len=%d)",
+		   nal_type, (*payload&0x60)>>5, payload_len));
+#endif
+
+    }
+    else if (nal_type == NAL_TYPE_STAP_A)
+    {
+	/* Aggregation packet */
+	pj_uint8_t *p, *p_end;
+	const pj_uint8_t *q, *q_end;
+	unsigned cnt = 0;
+
+	/* Validate bitstream length */
+	if (bits_len - *bits_pos < payload_len + 32) {
+	    /* Insufficient bistream buffer, discard this payload */
+	    pj_assert(!"Insufficient H.263 bitstream buffer");
+	    return PJ_ETOOSMALL;
+	}
+
+	/* Fill bitstream */
+	p = bits + *bits_pos;
+	p_end = bits + bits_len;
+	q = payload + 1;
+	q_end = payload + payload_len;
+	while (q < q_end && p < p_end) {
+	    pj_uint16_t tmp_nal_size;
+
+	    /* Write NAL unit start code */
+	    pj_memcpy(p, &nal_start_code, PJ_ARRAY_SIZE(nal_start_code));
+	    p += PJ_ARRAY_SIZE(nal_start_code);
+
+	    /* Get NAL unit size */
+	    tmp_nal_size = (*q << 8) | *(q+1);
+	    q += 2;
+	    if (q + tmp_nal_size > q_end) {
+		/* Invalid bitstream, discard the rest of the payload */
+		return PJ_EINVAL;
+	    }
+
+	    /* Write NAL unit */
+	    pj_memcpy(p, q, tmp_nal_size);
+	    p += tmp_nal_size;
+	    q += tmp_nal_size;
+	    ++cnt;
+
+	    /* Update the bitstream writing offset */
+	    *bits_pos = (unsigned)(p - bits);
+	    pktz->unpack_last_sync_pos = *bits_pos;
+	}
+
+#if DBG_UNPACKETIZE
+	PJ_LOG(3, ("h264unpack", "Unpacked %d H264 NAL units (len=%d)",
+		   cnt, payload_len));
+#endif
+
+    }
+    else if (nal_type == NAL_TYPE_FU_A)
+    {
+	/* Fragmentation packet */
+	pj_uint8_t *p;
+	const pj_uint8_t *q = payload;
+	pj_uint8_t NRI, TYPE, S, E;
+
+	p = bits + *bits_pos;
+
+	/* Validate bitstream length */
+	if (bits_len-*bits_pos < payload_len+PJ_ARRAY_SIZE(nal_start_code)) {
+	    /* Insufficient bistream buffer, drop this packet */
+	    pj_assert(!"Insufficient H.263 bitstream buffer");
+	    pktz->unpack_prev_lost = PJ_TRUE;
+	    return PJ_ETOOSMALL;
+	}
+
+	/* Get info */
+	S = *(q+1) & 0x80;    /* Start bit flag	*/
+	E = *(q+1) & 0x40;    /* End bit flag	*/
+	TYPE = *(q+1) & 0x1f;
+	NRI = (*q & 0x60) >> 5;
+
+	/* Fill bitstream */
+	if (S) {
+	    /* This is the first part, write NAL unit start code */
+	    pj_memcpy(p, &nal_start_code, PJ_ARRAY_SIZE(nal_start_code));
+	    p += PJ_ARRAY_SIZE(nal_start_code);
+
+	    /* Write NAL unit octet */
+	    *p++ = (NRI << 5) | TYPE;
+	} else if (pktz->unpack_prev_lost) {
+	    /* If prev packet was lost, revert the bitstream pointer to
+	     * the last sync point.
+	     */
+	    pj_assert(pktz->unpack_last_sync_pos <= *bits_pos);
+	    *bits_pos = pktz->unpack_last_sync_pos;
+	    /* And discard this payload (and the following fragmentation
+	     * payloads carrying this same NAL unit.
+	     */
+	    return PJ_EIGNORED;
+	}
+	q += 2;
+
+	/* Write NAL unit */
+	pj_memcpy(p, q, payload_len - 2);
+	p += (payload_len - 2);
+
+	/* Update the bitstream writing offset */
+	*bits_pos = (unsigned)(p - bits);
+	if (E) {
+	    /* Update the sync pos only if the end bit flag is set */
+	    pktz->unpack_last_sync_pos = *bits_pos;
+	}
+
+#if DBG_UNPACKETIZE
+	PJ_LOG(3, ("h264unpack", "Unpacked fragmented H264 NAL unit "
+		   "(type=%d, NRI=%d, len=%d)",
+		   TYPE, NRI, payload_len));
+#endif
+
+    } else {
+	*bits_pos = 0;
+	return PJ_ENOTSUP;
+    }
+
+    pktz->unpack_prev_lost = PJ_FALSE;
+
+    return PJ_SUCCESS;
+}
+
+
+#endif /* PJMEDIA_HAS_VIDEO */