+ uint8_t* buf = bufptr ? *bufptr : NULL;
+ int ret, flags = 0;
+ uint32_t timestamp;
+ int rv= 0;
+
+ if (!buf) {
+ /* If parsing of the previous packet actually returned 0 or an error,
+ * there's nothing more to be parsed from that packet, but we may have
+ * indicated that we can return the next enqueued packet. */
+ if (s->prev_ret <= 0)
+ return rtp_parse_queued_packet(s, pkt);
+ /* return the next packets, if any */
+ if(s->st && s->parse_packet) {
+ /* timestamp should be overwritten by parse_packet, if not,
+ * the packet is left with pts == AV_NOPTS_VALUE */
+ timestamp = RTP_NOTS_VALUE;
+ rv= s->parse_packet(s->ic, s->dynamic_protocol_context,
+ s->st, pkt, ×tamp, NULL, 0, flags);
+ finalize_packet(s, pkt, timestamp);
+ return rv;
+ } else {
+ // TODO: Move to a dynamic packet handler (like above)
+ if (s->read_buf_index >= s->read_buf_size)
+ return AVERROR(EAGAIN);
+ ret = ff_mpegts_parse_packet(s->ts, pkt, s->buf + s->read_buf_index,
+ s->read_buf_size - s->read_buf_index);
+ if (ret < 0)
+ return AVERROR(EAGAIN);
+ s->read_buf_index += ret;
+ if (s->read_buf_index < s->read_buf_size)
+ return 1;
+ else
+ return 0;
+ }
+ }
+
+ if (len < 12)
+ return -1;
+
+ if ((buf[0] & 0xc0) != (RTP_VERSION << 6))
+ return -1;
+ if (RTP_PT_IS_RTCP(buf[1])) {
+ return rtcp_parse_packet(s, buf, len);
+ }
+
+ if ((s->seq == 0 && !s->queue) || s->queue_size <= 1) {
+ /* First packet, or no reordering */
+ return rtp_parse_packet_internal(s, pkt, buf, len);
+ } else {
+ uint16_t seq = AV_RB16(buf + 2);
+ int16_t diff = seq - s->seq;
+ if (diff < 0) {
+ /* Packet older than the previously emitted one, drop */
+ av_log(s->st ? s->st->codec : NULL, AV_LOG_WARNING,
+ "RTP: dropping old packet received too late\n");
+ return -1;
+ } else if (diff <= 1) {
+ /* Correct packet */
+ rv = rtp_parse_packet_internal(s, pkt, buf, len);
+ return rv;
+ } else {
+ /* Still missing some packet, enqueue this one. */
+ enqueue_packet(s, buf, len);
+ *bufptr = NULL;
+ /* Return the first enqueued packet if the queue is full,
+ * even if we're missing something */
+ if (s->queue_len >= s->queue_size)
+ return rtp_parse_queued_packet(s, pkt);
+ return -1;
+ }
+ }
+}
+
+/**
+ * Parse an RTP or RTCP packet directly sent as a buffer.
+ * @param s RTP parse context.
+ * @param pkt returned packet
+ * @param bufptr pointer to the input buffer or NULL to read the next packets
+ * @param len buffer len
+ * @return 0 if a packet is returned, 1 if a packet is returned and more can follow
+ * (use buf as NULL to read the next). -1 if no packet (error or no more packet).
+ */
+int ff_rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
+ uint8_t **bufptr, int len)
+{
+ int rv = rtp_parse_one_packet(s, pkt, bufptr, len);
+ s->prev_ret = rv;
+ while (rv == AVERROR(EAGAIN) && has_next_packet(s))
+ rv = rtp_parse_queued_packet(s, pkt);
+ return rv ? rv : has_next_packet(s);
+}
+
+void ff_rtp_parse_close(RTPDemuxContext *s)
+{
+ ff_rtp_reset_packet_queue(s);