static GstFlowReturn gst_rtp_j2k_depay_flush_pu (GstRTPBaseDepayload * depayload) { GstRtpJ2KDepay *rtpj2kdepay; GstBuffer *mheader; guint avail, MHF, mh_id; rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload); /* take all available buffers */ avail = gst_adapter_available (rtpj2kdepay->pu_adapter); if (avail == 0) goto done; MHF = rtpj2kdepay->pu_MHF; mh_id = rtpj2kdepay->last_mh_id; GST_DEBUG_OBJECT (rtpj2kdepay, "flushing PU of size %u", avail); if (MHF == 0) { GList *packets, *walk; packets = gst_adapter_take_list (rtpj2kdepay->pu_adapter, avail); /* append packets */ for (walk = packets; walk; walk = g_list_next (walk)) { GstBuffer *buf = GST_BUFFER_CAST (walk->data); GST_DEBUG_OBJECT (rtpj2kdepay, "append pu packet of size %" G_GSIZE_FORMAT, gst_buffer_get_size (buf)); gst_adapter_push (rtpj2kdepay->t_adapter, buf); } g_list_free (packets); } else { /* we have a header */ GST_DEBUG_OBJECT (rtpj2kdepay, "keeping header %u", mh_id); /* we managed to see the start and end of the header, take all from * adapter and keep in header */ mheader = gst_adapter_take_buffer (rtpj2kdepay->pu_adapter, avail); store_mheader (rtpj2kdepay, mh_id, mheader); } done: rtpj2kdepay->have_sync = FALSE; return GST_FLOW_OK; }
static GstFlowReturn gst_rtp_j2k_depay_flush_frame (GstBaseRTPDepayload * depayload) { GstRtpJ2KDepay *rtpj2kdepay; guint8 end[2]; guint8 *data; guint avail; GstFlowReturn ret = GST_FLOW_OK; rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload); /* flush pending tile */ gst_rtp_j2k_depay_flush_tile (depayload); /* last buffer take all data out of the adapter */ avail = gst_adapter_available (rtpj2kdepay->f_adapter); if (avail == 0) goto done; if (avail > 2) { GstBuffer *outbuf; /* take the last bytes of the JPEG 2000 data to see if there is an EOC * marker */ gst_adapter_copy (rtpj2kdepay->f_adapter, end, avail - 2, 2); if (end[0] != 0xff && end[1] != 0xd9) { GST_DEBUG_OBJECT (rtpj2kdepay, "no EOC marker, adding one"); /* no EOI marker, add one */ outbuf = gst_buffer_new_and_alloc (2); data = GST_BUFFER_DATA (outbuf); data[0] = 0xff; data[1] = 0xd9; gst_adapter_push (rtpj2kdepay->f_adapter, outbuf); avail += 2; } if (rtpj2kdepay->buffer_list) { GList *list; GstBufferList *buflist; GstBufferListIterator *it; GST_DEBUG_OBJECT (rtpj2kdepay, "pushing buffer list of %u bytes", avail); list = gst_adapter_take_list (rtpj2kdepay->f_adapter, avail); buflist = gst_buffer_list_new (); it = gst_buffer_list_iterate (buflist); gst_buffer_list_iterator_add_group (it); gst_buffer_list_iterator_add_list (it, list); gst_buffer_list_iterator_free (it); ret = gst_base_rtp_depayload_push_list (depayload, buflist); } else { GST_DEBUG_OBJECT (rtpj2kdepay, "pushing buffer of %u bytes", avail); outbuf = gst_adapter_take_buffer (rtpj2kdepay->f_adapter, avail); ret = gst_base_rtp_depayload_push (depayload, outbuf); } } else { GST_WARNING_OBJECT (rtpj2kdepay, "empty packet"); gst_adapter_clear (rtpj2kdepay->f_adapter); } /* we accept any mh_id now */ rtpj2kdepay->last_mh_id = -1; /* reset state */ rtpj2kdepay->next_frag = 0; rtpj2kdepay->have_sync = FALSE; done: /* we can't keep headers with mh_id of 0 */ store_mheader (rtpj2kdepay, 0, NULL); return ret; }
static GstFlowReturn gst_rtp_j2k_depay_flush_tile (GstBaseRTPDepayload * depayload) { GstRtpJ2KDepay *rtpj2kdepay; guint avail, mh_id; GList *packets, *walk; guint8 end[2]; GstFlowReturn ret = GST_FLOW_OK; rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload); /* flush pending PU */ gst_rtp_j2k_depay_flush_pu (depayload); /* take all available buffers */ avail = gst_adapter_available (rtpj2kdepay->t_adapter); if (avail == 0) goto done; mh_id = rtpj2kdepay->last_mh_id; GST_DEBUG_OBJECT (rtpj2kdepay, "flushing tile of size %u", avail); if (gst_adapter_available (rtpj2kdepay->f_adapter) == 0) { GstBuffer *mheader; /* we need a header now */ if ((mheader = rtpj2kdepay->MH[mh_id]) == NULL) goto waiting_header; /* push header in the adapter */ GST_DEBUG_OBJECT (rtpj2kdepay, "pushing header %u", mh_id); gst_adapter_push (rtpj2kdepay->f_adapter, gst_buffer_ref (mheader)); } /* check for last bytes */ gst_adapter_copy (rtpj2kdepay->t_adapter, end, avail - 2, 2); /* now append the tile packets to the frame */ packets = gst_adapter_take_list (rtpj2kdepay->t_adapter, avail); for (walk = packets; walk; walk = g_list_next (walk)) { GstBuffer *buf = GST_BUFFER_CAST (walk->data); if (walk == packets) { guint8 *data; guint size; /* first buffer should contain the SOT */ data = GST_BUFFER_DATA (buf); size = GST_BUFFER_SIZE (buf); if (size < 12) goto invalid_tile; if (data[0] == 0xff && data[1] == J2K_MARKER_SOT) { guint Psot, nPsot; if (end[0] == 0xff && end[1] == J2K_MARKER_EOC) nPsot = avail - 2; else nPsot = avail; Psot = GST_READ_UINT32_BE (&data[6]); if (Psot != nPsot && Psot != 0) { /* Psot must match the size of the tile */ GST_DEBUG_OBJECT (rtpj2kdepay, "set Psot from %u to %u", Psot, nPsot); buf = gst_buffer_make_writable (buf); data = GST_BUFFER_DATA (buf); GST_WRITE_UINT32_BE (&data[6], nPsot); } } } GST_DEBUG_OBJECT (rtpj2kdepay, "append pu packet of size %u", GST_BUFFER_SIZE (buf)); gst_adapter_push (rtpj2kdepay->f_adapter, buf); } g_list_free (packets); done: rtpj2kdepay->last_tile = -1; return ret; /* errors */ waiting_header: { GST_DEBUG_OBJECT (rtpj2kdepay, "waiting for header %u", mh_id); gst_adapter_clear (rtpj2kdepay->t_adapter); rtpj2kdepay->last_tile = -1; return ret; } invalid_tile: { GST_ELEMENT_WARNING (rtpj2kdepay, STREAM, DECODE, ("Invalid tile"), (NULL)); gst_adapter_clear (rtpj2kdepay->t_adapter); rtpj2kdepay->last_tile = -1; return ret; } }