static GstFlowReturn
gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload,
- const guint8 * data, guint size, GstClockTime dts, GstClockTime pts,
- gboolean end_of_au);
+ GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au);
static GstFlowReturn
gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload,
{
GstFlowReturn ret = GST_FLOW_OK;
GList *walk;
- GstMapInfo map;
for (walk = rtph264pay->sps; walk; walk = g_list_next (walk)) {
GstBuffer *sps_buf = GST_BUFFER_CAST (walk->data);
GST_DEBUG_OBJECT (rtph264pay, "inserting SPS in the stream");
/* resend SPS */
- gst_buffer_map (sps_buf, &map, GST_MAP_READ);
- ret = gst_rtp_h264_pay_payload_nal (basepayload,
- map.data, map.size, dts, pts, FALSE);
- gst_buffer_unmap (sps_buf, &map);
+ ret = gst_rtp_h264_pay_payload_nal (basepayload, gst_buffer_ref (sps_buf),
+ dts, pts, FALSE);
/* Not critical here; but throw a warning */
if (ret != GST_FLOW_OK)
GST_WARNING ("Problem pushing SPS");
GST_DEBUG_OBJECT (rtph264pay, "inserting PPS in the stream");
/* resend PPS */
- gst_buffer_map (pps_buf, &map, GST_MAP_READ);
- ret = gst_rtp_h264_pay_payload_nal (basepayload,
- map.data, map.size, dts, pts, FALSE);
- gst_buffer_unmap (pps_buf, &map);
+ ret = gst_rtp_h264_pay_payload_nal (basepayload, gst_buffer_ref (pps_buf),
+ dts, pts, FALSE);
/* Not critical here; but throw a warning */
if (ret != GST_FLOW_OK)
GST_WARNING ("Problem pushing PPS");
static GstFlowReturn
gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload,
- const guint8 * data, guint size, GstClockTime dts, GstClockTime pts,
- gboolean end_of_au)
+ GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au)
{
GstRtpH264Pay *rtph264pay;
GstFlowReturn ret;
GstBufferList *list = NULL;
gboolean send_spspps;
GstRTPBuffer rtp = { NULL };
+ guint size = gst_buffer_get_size (paybuf);
rtph264pay = GST_RTP_H264_PAY (basepayload);
mtu = GST_RTP_BASE_PAYLOAD_MTU (rtph264pay);
- nalType = data[0] & 0x1f;
+ gst_buffer_extract (paybuf, 0, &nalType, 1);
+ nalType &= 0x1f;
+
GST_DEBUG_OBJECT (rtph264pay, "Processing Buffer with NAL TYPE=%d", nalType);
/* should set src caps before pushing stuff,
GST_BUFFER_DTS (outbuf) = dts;
/* insert payload memory block */
- gst_buffer_append_memory (outbuf,
- gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY, (guint8 *) data,
- size, 0, size, NULL, NULL));
+ outbuf = gst_buffer_append (outbuf, paybuf);
list = gst_buffer_list_new ();
GST_DEBUG_OBJECT (basepayload,
"NAL Unit DOES NOT fit in one packet datasize=%d mtu=%d", size, mtu);
- nalHeader = *data;
+ gst_buffer_extract (paybuf, 0, &nalHeader, 1);
pos++;
size--;
/* FU Header */
payload[1] = (start << 7) | (end << 6) | (nalHeader & 0x1f);
+ gst_rtp_buffer_unmap (&rtp);
+
/* insert payload memory block */
- gst_buffer_append_memory (outbuf,
- gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
- (guint8 *) data + pos, limitedSize, 0, limitedSize, NULL, NULL));
+ gst_buffer_append (outbuf,
+ gst_buffer_copy_region (paybuf, GST_BUFFER_COPY_MEMORY, pos,
+ limitedSize));
/* add the buffer to the buffer list */
gst_buffer_list_add (list, outbuf);
- gst_rtp_buffer_unmap (&rtp);
size -= limitedSize;
pos += limitedSize;
}
ret = gst_rtp_base_payload_push_list (basepayload, list);
+ gst_buffer_unref (paybuf);
}
return ret;
}
gsize size;
guint nal_len, i;
GstMapInfo map;
- const guint8 *data, *nal_data;
+ const guint8 *data;
GstClockTime dts, pts;
GArray *nal_queue;
- guint pushed = 0;
gboolean avc;
+ GstBuffer *paybuf = NULL;
+ gsize skip;
rtph264pay = GST_RTP_H264_PAY (basepayload);
} else {
dts = gst_adapter_prev_dts (rtph264pay->adapter, NULL);
pts = gst_adapter_prev_pts (rtph264pay->adapter, NULL);
- if (buffer)
- gst_adapter_push (rtph264pay->adapter, buffer);
- size = gst_adapter_available (rtph264pay->adapter);
- data = gst_adapter_map (rtph264pay->adapter, size);
- GST_DEBUG_OBJECT (basepayload,
- "got %" G_GSIZE_FORMAT " bytes (%" G_GSIZE_FORMAT ")", size,
- buffer ? gst_buffer_get_size (buffer) : 0);
-
if (buffer) {
if (!GST_CLOCK_TIME_IS_VALID (dts))
dts = GST_BUFFER_DTS (buffer);
if (!GST_CLOCK_TIME_IS_VALID (pts))
pts = GST_BUFFER_PTS (buffer);
+
+ gst_adapter_push (rtph264pay->adapter, buffer);
}
+ size = gst_adapter_available (rtph264pay->adapter);
+ data = gst_adapter_map (rtph264pay->adapter, size);
+ GST_DEBUG_OBJECT (basepayload,
+ "got %" G_GSIZE_FORMAT " bytes (%" G_GSIZE_FORMAT ")", size,
+ buffer ? gst_buffer_get_size (buffer) : 0);
}
ret = GST_FLOW_OK;
* latency. */
if (avc) {
guint nal_length_size;
+ gsize offset = 0;
nal_length_size = rtph264pay->nal_length_size;
/* skip the length bytes, make sure we don't run past the buffer size */
data += nal_length_size;
+ offset += nal_length_size;
size -= nal_length_size;
if (size >= nal_len) {
end_of_au = TRUE;
}
+ paybuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY, offset,
+ nal_len);
ret =
- gst_rtp_h264_pay_payload_nal (basepayload, data, nal_len, dts, pts,
+ gst_rtp_h264_pay_payload_nal (basepayload, paybuf, dts, pts,
end_of_au);
if (ret != GST_FLOW_OK)
break;
data += nal_len;
+ offset += nal_len;
size -= nal_len;
}
} else {
* will not collect data. */
data += next;
size -= next;
- nal_data = data;
nal_queue = rtph264pay->queue;
+ skip = next;
/* array must be empty when we get here */
g_assert (nal_queue->len == 0);
goto caps_rejected;
/* second pass to payload and push */
- data = nal_data;
- pushed = 0;
+
+ if (nal_queue->len != 0)
+ gst_adapter_flush (rtph264pay->adapter, skip);
for (i = 0; i < nal_queue->len; i++) {
guint size;
nal_len = g_array_index (nal_queue, guint, i);
/* skip start code */
- data += 3;
+ gst_adapter_flush (rtph264pay->adapter, 3);
/* Trim the end unless we're the last NAL in the stream.
* In case we're not at the end of the buffer we know the next block
* starts with 0x000001 so all the 0x00 bytes at the end of this one are
* trailing 0x0 that can be discarded */
size = nal_len;
+ data = gst_adapter_map (rtph264pay->adapter, size);
if (i + 1 != nal_queue->len || buffer != NULL)
for (; size > 1 && data[size - 1] == 0x0; size--)
/* skip */ ;
+
/* If it's the last nal unit we have in non-bytestream mode, we can
* assume it's the end of an access-unit
*
if ((rtph264pay->alignment == GST_H264_ALIGNMENT_AU || buffer == NULL) &&
i == nal_queue->len - 1)
end_of_au = TRUE;
-
+ paybuf = gst_adapter_take_buffer (rtph264pay->adapter, size);
+ g_assert (paybuf);
/* put the data in one or more RTP packets */
ret =
- gst_rtp_h264_pay_payload_nal (basepayload, data, size, dts, pts,
+ gst_rtp_h264_pay_payload_nal (basepayload, paybuf, dts, pts,
end_of_au);
if (ret != GST_FLOW_OK) {
break;
}
/* move to next NAL packet */
- data += nal_len;
- pushed += nal_len + 3;
+ /* Skips the trailing zeros */
+ gst_adapter_flush (rtph264pay->adapter, nal_len - size);
}
g_array_set_size (nal_queue, 0);
}
gst_buffer_unref (buffer);
} else {
gst_adapter_unmap (rtph264pay->adapter);
- gst_adapter_flush (rtph264pay->adapter, pushed);
}
return ret;
}
GST_END_TEST;
+static const guint8 rtp_h264_list_lt_mtu_frame_data_avc[] =
+ /* packetized data */
+{ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
+ 0xad, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0d, 0x00
+};
+
+/* NAL = 4 bytes */
+static int rtp_h264_list_lt_mtu_bytes_sent_avc = 2 * (16 - 2 * 4);
+
+//static int rtp_h264_list_lt_mtu_mtu_size = 1024;
+
+GST_START_TEST (rtp_h264_list_lt_mtu_avc)
+{
+ /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
+ rtp_pipeline_test (rtp_h264_list_lt_mtu_frame_data_avc,
+ rtp_h264_list_lt_mtu_frame_data_size, rtp_h264_list_lt_mtu_frame_count,
+ "video/x-h264,stream-format=(string)avc,alignment=(string)au,"
+ "codec_data=(buffer)01640014ffe1001867640014acd94141fb0110000003001773594000f142996001000568ebecb22c",
+ "rtph264pay", "rtph264depay",
+ rtp_h264_list_lt_mtu_bytes_sent_avc, rtp_h264_list_lt_mtu_mtu_size, TRUE);
+}
+
+GST_END_TEST;
static const guint8 rtp_h264_list_gt_mtu_frame_data[] =
/* not packetized, next NAL starts with 0001 */
{ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}
GST_END_TEST;
+static const guint8 rtp_h264_list_gt_mtu_frame_data_avc[] =
+ /* packetized data */
+{ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* NAL = 4 bytes. When data does not fit into 1 mtu, 1 byte will be skipped */
+static int rtp_h264_list_gt_mtu_bytes_sent_avc = 1 * (64 - 2 * 4 - 2 * 1);
+
+GST_START_TEST (rtp_h264_list_gt_mtu_avc)
+{
+ /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
+ rtp_pipeline_test (rtp_h264_list_gt_mtu_frame_data_avc,
+ rtp_h264_list_gt_mtu_frame_data_size, rtp_h264_list_gt_mtu_frame_count,
+ "video/x-h264,stream-format=(string)avc,alignment=(string)au,"
+ "codec_data=(buffer)01640014ffe1001867640014acd94141fb0110000003001773594000f142996001000568ebecb22c",
+ "rtph264pay", "rtph264depay",
+ rtp_h264_list_gt_mtu_bytes_sent_avc, rtp_h264_list_gt_mtu_mty_size, TRUE);
+}
+
+GST_END_TEST;
+
static const guint8 rtp_L16_frame_data[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
tcase_add_test (tc_chain, rtp_h263p);
tcase_add_test (tc_chain, rtp_h264);
tcase_add_test (tc_chain, rtp_h264_list_lt_mtu);
+ tcase_add_test (tc_chain, rtp_h264_list_lt_mtu_avc);
tcase_add_test (tc_chain, rtp_h264_list_gt_mtu);
+ tcase_add_test (tc_chain, rtp_h264_list_gt_mtu_avc);
tcase_add_test (tc_chain, rtp_L16);
tcase_add_test (tc_chain, rtp_mp2t);
tcase_add_test (tc_chain, rtp_mp4v);