summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Boxer <boxerab@gmail.com>2016-05-12 08:41:51 -0400
committerSebastian Dröge <sebastian@centricular.com>2016-05-13 11:01:19 +0300
commit84ff5511de550e3865afe06c2e1d3be78d7660ba (patch)
tree387553929a1b760ac9f6c9bad6890094a6167384
parentd2765be1206e3866a1461221ac9dfa1cbe932814 (diff)
rtpj2kpay: manage fragmented headers correctly
J2K main header framentation across multiple RTP packets is now handled correctly https://bugzilla.gnome.org/show_bug.cgi?id=745187
-rw-r--r--gst/rtp/gstrtpj2kpay.c51
1 files changed, 36 insertions, 15 deletions
diff --git a/gst/rtp/gstrtpj2kpay.c b/gst/rtp/gstrtpj2kpay.c
index 8ce270562..f6c70901b 100644
--- a/gst/rtp/gstrtpj2kpay.c
+++ b/gst/rtp/gstrtpj2kpay.c
@@ -188,6 +188,13 @@ typedef struct
gboolean force_packet;
} RtpJ2KState;
+
+/* Note: The standard recommends that headers be put in their own RTP packets, so we follow
+ * this recommendation in the code. Also, this method groups together all J2K packets
+ * for a tile part and treats this group as a packetization unit. According to the RFC,
+ * only an individual J2K packet is considered a packetization unit.
+ */
+
static guint
find_pu_end (GstRtpJ2KPay * pay, const guint8 * data, guint size,
guint offset, RtpJ2KState * state)
@@ -230,14 +237,18 @@ find_pu_end (GstRtpJ2KPay * pay, const guint8 * data, guint size,
switch (marker) {
case GST_J2K_MARKER_SOC:
GST_LOG_OBJECT (pay, "found SOC at %u", offset);
- state->header.MHF = 1;
+ /* start off by assuming that we will fit the entire header
+ into the RTP payload */
+ state->header.MHF = 3;
break;
case GST_J2K_MARKER_SOT:
{
guint len, Psot;
GST_LOG_OBJECT (pay, "found SOT at %u", offset);
- /* we found SOT but also had a header first */
+ /* SOT for first tile part in code stream:
+ force close of current RTP packet, so that it
+ only contains main header */
if (state->header.MHF) {
state->force_packet = TRUE;
return offset - 2;
@@ -424,18 +435,26 @@ gst_rtp_j2k_pay_handle_buffer (GstRTPBasePayload * basepayload,
header = gst_rtp_buffer_get_payload (&rtp);
pu_size -= data_size;
- if (pu_size == 0) {
- /* reached the end of a packetization unit */
- if (state.header.MHF) {
- /* we were doing a header, see if all fit in one packet or if
- * we had to fragment it */
- if (offset == 0)
- state.header.MHF = 3;
- else
- state.header.MHF = 2;
+
+ /* reached the end of a packetization unit */
+ if (pu_size == 0 && end >= map.size) {
+ gst_rtp_buffer_set_marker (&rtp, TRUE);
+ }
+ /* If we were processing a header, see if all fits in one RTP packet
+ or if we have to fragment it */
+ if (state.header.MHF) {
+ switch (state.header.MHF) {
+ case 3:
+ if (pu_size > 0)
+ state.header.MHF = 1;
+ break;
+ case 1:
+ if (pu_size == 0)
+ state.header.MHF = 2;
+ break;
+ default:
+ break;
}
- if (end >= map.size)
- gst_rtp_buffer_set_marker (&rtp, TRUE);
}
/*
@@ -478,11 +497,13 @@ gst_rtp_j2k_pay_handle_buffer (GstRTPBasePayload * basepayload,
gst_buffer_list_add (list, outbuf);
- /* reset header for next round */
- state.header.MHF = 0;
state.header.T = 1;
state.header.tile = 0;
+ /* set MHF to zero if there is no more main header to process */
+ if (state.header.MHF & 2)
+ state.header.MHF = 0;
+
offset += data_size;
state.header.offset = offset;
}