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__ */