summaryrefslogtreecommitdiffstats
path: root/gst/rtp/gstrtph264pay.c
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2008-05-20 11:33:05 +0000
committerWim Taymans <wim.taymans@gmail.com>2008-05-20 11:33:05 +0000
commitbe0e73ee6bd042a349a79b0d4b34fdc6d5366a47 (patch)
tree4f67b41ccf070337c0fe75ace68a3303f0f946d9 /gst/rtp/gstrtph264pay.c
parent3d3f7cd6dafbf0b5a49f94627fa638e493e6ca8f (diff)
gst/rtp/gstrtph264depay.*: Add experimental support for outputting quicktime-like AVC output in addition to the exist...
Original commit message from CVS: * gst/rtp/gstrtph264depay.c: (gst_rtp_h264_depay_class_init), (gst_rtp_h264_depay_init), (gst_rtp_h264_depay_set_property), (gst_rtp_h264_depay_get_property), (gst_rtp_h264_depay_setcaps), (gst_rtp_h264_depay_process): * gst/rtp/gstrtph264depay.h: Add experimental support for outputting quicktime-like AVC output in addition to the existing bytestream output. * gst/rtp/gstrtph264pay.c: (gst_h264_scan_mode_get_type), (gst_rtp_h264_pay_class_init), (gst_rtp_h264_pay_init), (gst_rtp_h264_pay_setcaps), (gst_rtp_h264_pay_payload_nal), (gst_rtp_h264_pay_handle_buffer), (gst_rtp_h264_pay_set_property), (gst_rtp_h264_pay_get_property): * gst/rtp/gstrtph264pay.h: Make the parsing mode configurable, for some inputs we don't need to scan every byte for start codes. Only set the marker bit on ACCESS units.
Diffstat (limited to 'gst/rtp/gstrtph264pay.c')
-rw-r--r--gst/rtp/gstrtph264pay.c109
1 files changed, 87 insertions, 22 deletions
diff --git a/gst/rtp/gstrtph264pay.c b/gst/rtp/gstrtph264pay.c
index f638b174..4c014b9a 100644
--- a/gst/rtp/gstrtph264pay.c
+++ b/gst/rtp/gstrtph264pay.c
@@ -64,16 +64,46 @@ GST_STATIC_PAD_TEMPLATE ("src",
"clock-rate = (int) 90000, " "encoding-name = (string) \"H264\"")
);
+#define GST_TYPE_H264_SCAN_MODE (gst_h264_scan_mode_get_type())
+static GType
+gst_h264_scan_mode_get_type (void)
+{
+ static GType h264_scan_mode_type = 0;
+ static const GEnumValue h264_scan_modes[] = {
+ {GST_H264_SCAN_MODE_BYTESTREAM,
+ "Scan complete bytestream for NALUs (not implemented)",
+ "bytestream"},
+ {GST_H264_SCAN_MODE_MULTI_NAL, "Buffers contain multiple complete NALUs",
+ "multiple"},
+ {GST_H264_SCAN_MODE_SINLE_NAL, "Buffers contain a single complete NALU",
+ "single"},
+ {0, NULL, NULL},
+ };
+
+ if (!h264_scan_mode_type) {
+ h264_scan_mode_type =
+ g_enum_register_static ("GstH264PayScanMode", h264_scan_modes);
+ }
+ return h264_scan_mode_type;
+}
+
#define DEFAULT_PROFILE_LEVEL_ID NULL
#define DEFAULT_SPROP_PARAMETER_SETS NULL
+#define DEFAULT_SPROP_PARAMETER_SETS NULL
+#define DEFAULT_SCAN_MODE GST_H264_SCAN_MODE_MULTI_NAL
enum
{
- ARG_0,
- ARG_PROFILE_LEVEL_ID,
- ARG_SPROP_PARAMETER_SETS
+ PROP_0,
+ PROP_PROFILE_LEVEL_ID,
+ PROP_SPROP_PARAMETER_SETS,
+ PROP_SCAN_MODE,
+ PROP_LAST
};
+
+#define IS_ACCESS_UNIT(x) (((x) > 0x00) && ((x) < 0x06))
+
static void gst_rtp_h264_pay_finalize (GObject * object);
static GstStateChangeReturn gst_rtp_h264_pay_change_state (GstElement * element,
@@ -119,19 +149,29 @@ gst_rtp_h264_pay_class_init (GstRtpH264PayClass * klass)
gobject_class->set_property = gst_rtp_h264_pay_set_property;
gobject_class->get_property = gst_rtp_h264_pay_get_property;
- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PROFILE_LEVEL_ID,
- g_param_spec_string ("profile-level-id", "profile-level-id",
- "The base64 profile-level-id to set in out caps (set to NULL to extract from stream)",
+ g_object_class_install_property (G_OBJECT_CLASS (klass),
+ PROP_PROFILE_LEVEL_ID, g_param_spec_string ("profile-level-id",
+ "profile-level-id",
+ "The base64 profile-level-id to set in out caps (set to NULL to "
+ "extract from stream)",
DEFAULT_PROFILE_LEVEL_ID,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (G_OBJECT_CLASS (klass),
- ARG_SPROP_PARAMETER_SETS, g_param_spec_string ("sprop-parameter-sets",
+ PROP_SPROP_PARAMETER_SETS, g_param_spec_string ("sprop-parameter-sets",
"sprop-parameter-sets",
- "The base64 sprop-parameter-sets to set in out caps (set to NULL to extract from stream)",
+ "The base64 sprop-parameter-sets to set in out caps (set to NULL to "
+ "extract from stream)",
DEFAULT_SPROP_PARAMETER_SETS,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SCAN_MODE,
+ g_param_spec_enum ("scan-mode", "Scan Mode",
+ "How to scan the input buffers for NAL units. Performance can be "
+ "increased when certain assumptions are made about the input buffers",
+ GST_TYPE_H264_SCAN_MODE, DEFAULT_SCAN_MODE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
gobject_class->finalize = gst_rtp_h264_pay_finalize;
gstelement_class->change_state = gst_rtp_h264_pay_change_state;
@@ -149,6 +189,7 @@ gst_rtp_h264_pay_init (GstRtpH264Pay * rtph264pay, GstRtpH264PayClass * klass)
rtph264pay->profile = 0;
rtph264pay->sps = NULL;
rtph264pay->pps = NULL;
+ rtph264pay->scan_mode = GST_H264_SCAN_MODE_MULTI_NAL;
}
static void
@@ -239,6 +280,8 @@ gst_rtp_h264_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
GST_DEBUG_OBJECT (rtph264pay, "profile %06x", profile);
/* 6 bits reserved | 2 bits lengthSizeMinusOne */
+ /* this is the number of bytes in front of the NAL units to mark their
+ * length */
rtph264pay->nal_length_size = (data[4] & 0x03) + 1;
GST_DEBUG_OBJECT (rtph264pay, "nal length %u", rtph264pay->nal_length_size);
/* 3 bits reserved | 5 bits numOfSequenceParameterSets */
@@ -277,6 +320,7 @@ gst_rtp_h264_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
if (size < 1)
goto avcc_error;
+ /* 8 bits numOfPictureParameterSets */
num_pps = data[0];
data += 1;
size -= 1;
@@ -579,7 +623,10 @@ gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload, guint8 * data,
outbuf = gst_rtp_buffer_new_allocate (size, 0, 0);
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
- gst_rtp_buffer_set_marker (outbuf, 1);
+ /* only set the marker bit on packets containing access units */
+ if (IS_ACCESS_UNIT (nalType)) {
+ gst_rtp_buffer_set_marker (outbuf, 1);
+ }
payload = gst_rtp_buffer_get_payload (outbuf);
GST_DEBUG_OBJECT (basepayload, "Copying %d bytes to outbuf", size);
@@ -621,7 +668,9 @@ gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload, guint8 * data,
GST_DEBUG_OBJECT (basepayload, "end size=%d iteration=%d", size, ii);
end = 1;
}
- gst_rtp_buffer_set_marker (outbuf, end);
+ if (IS_ACCESS_UNIT (nalType)) {
+ gst_rtp_buffer_set_marker (outbuf, end);
+ }
/* FU indicator */
payload[0] = (nalHeader & 0x60) | 28;
@@ -723,14 +772,20 @@ gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * basepayload,
data += 4;
size -= 4;
- /* use next_start_code() to scan buffer.
- * next_start_code() returns the offset in data,
- * starting from zero to the first byte of 0.0.0.1
- * If no start code is found, it returns the value of the
- * 'size' parameter.
- * data is unchanged by the call to next_start_code()
- */
- next = next_start_code (data, size);
+ if (rtph264pay->scan_mode == GST_H264_SCAN_MODE_SINLE_NAL) {
+ /* we are told that there is only a single NAL in this packet so that we
+ * can avoid scanning for the next NAL. */
+ next = size;
+ } else {
+ /* use next_start_code() to scan buffer.
+ * next_start_code() returns the offset in data,
+ * starting from zero to the first byte of 0.0.0.1
+ * If no start code is found, it returns the value of the
+ * 'size' parameter.
+ * data is unchanged by the call to next_start_code()
+ */
+ next = next_start_code (data, size);
+ }
/* nal length is distance to next start code */
nal_len = next;
@@ -804,15 +859,21 @@ gst_rtp_h264_pay_set_property (GObject * object, guint prop_id,
rtph264pay = GST_RTP_H264_PAY (object);
switch (prop_id) {
- case ARG_PROFILE_LEVEL_ID:
+ case PROP_PROFILE_LEVEL_ID:
+ g_free (rtph264pay->profile_level_id);
rtph264pay->profile_level_id = g_value_dup_string (value);
rtph264pay->update_caps = TRUE;
break;
- case ARG_SPROP_PARAMETER_SETS:
+ case PROP_SPROP_PARAMETER_SETS:
+ g_free (rtph264pay->sprop_parameter_sets);
rtph264pay->sprop_parameter_sets = g_value_dup_string (value);
rtph264pay->update_caps = TRUE;
break;
+ case PROP_SCAN_MODE:
+ rtph264pay->scan_mode = g_value_get_enum (value);
+ break;
default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
@@ -826,13 +887,17 @@ gst_rtp_h264_pay_get_property (GObject * object, guint prop_id,
rtph264pay = GST_RTP_H264_PAY (object);
switch (prop_id) {
- case ARG_PROFILE_LEVEL_ID:
+ case PROP_PROFILE_LEVEL_ID:
g_value_set_string (value, rtph264pay->profile_level_id);
break;
- case ARG_SPROP_PARAMETER_SETS:
+ case PROP_SPROP_PARAMETER_SETS:
g_value_set_string (value, rtph264pay->sprop_parameter_sets);
break;
+ case PROP_SCAN_MODE:
+ g_value_set_enum (value, rtph264pay->scan_mode);
+ break;
default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}