/** * Write an RTP hint (that may contain one or more RTP packets) * for the packets in data. data contains one or more packets with a * BE32 size header. * * @param out buffer where the hints are written * @param data buffer containing RTP packets * @param size the size of the data buffer * @param trk the MOVTrack for the hint track * @param dts pointer where the timestamp for the written RTP hint is stored * @return the number of RTP packets in the written hint */ static int write_hint_packets(AVIOContext *out, const uint8_t *data, int size, MOVTrack *trk, int64_t *dts) { int64_t curpos; int64_t count_pos, entries_pos; int count = 0, entries; count_pos = avio_tell(out); /* RTPsample header */ avio_wb16(out, 0); /* packet count */ avio_wb16(out, 0); /* reserved */ while (size > 4) { uint32_t packet_len = AV_RB32(data); uint16_t seq; uint32_t ts; int32_t ts_diff; data += 4; size -= 4; if (packet_len > size || packet_len <= 12) break; if (RTP_PT_IS_RTCP(data[1])) { /* RTCP packet, just skip */ data += packet_len; size -= packet_len; continue; } if (packet_len > trk->max_packet_size) trk->max_packet_size = packet_len; seq = AV_RB16(&data[2]); ts = AV_RB32(&data[4]); if (trk->prev_rtp_ts == 0) trk->prev_rtp_ts = ts; /* Unwrap the 32-bit RTP timestamp that wraps around often * into a not (as often) wrapping 64-bit timestamp. */ ts_diff = ts - trk->prev_rtp_ts; if (ts_diff > 0) { trk->cur_rtp_ts_unwrapped += ts_diff; trk->prev_rtp_ts = ts; ts_diff = 0; } if (*dts == AV_NOPTS_VALUE) *dts = trk->cur_rtp_ts_unwrapped; count++; /* RTPpacket header */ avio_wb32(out, 0); /* relative_time */ avio_write(out, data, 2); /* RTP header */ avio_wb16(out, seq); /* RTPsequenceseed */ avio_wb16(out, ts_diff ? 4 : 0); /* reserved + flags (extra_flag) */ entries_pos = avio_tell(out); avio_wb16(out, 0); /* entry count */ if (ts_diff) { /* if extra_flag is set */ avio_wb32(out, 16); /* extra_information_length */ avio_wb32(out, 12); /* rtpoffsetTLV box */ avio_write(out, "rtpo", 4); avio_wb32(out, ts_diff); } data += 12; size -= 12; packet_len -= 12; entries = 0; /* Write one or more constructors describing the payload data */ describe_payload(data, packet_len, out, &entries, &trk->sample_queue); data += packet_len; size -= packet_len; curpos = avio_tell(out); avio_seek(out, entries_pos, SEEK_SET); avio_wb16(out, entries); avio_seek(out, curpos, SEEK_SET); } curpos = avio_tell(out); avio_seek(out, count_pos, SEEK_SET); avio_wb16(out, count); avio_seek(out, curpos, SEEK_SET); return count; }
/** * Write an RTP hint (that may contain one or more RTP packets) * for the packets in data. data contains one or more packets with a * BE32 size header. * * @param out buffer where the hints are written * @param data buffer containing RTP packets * @param size the size of the data buffer * @param trk the MOVTrack for the hint track * @param pts pointer where the timestamp for the written RTP hint is stored * @return the number of RTP packets in the written hint */ static int write_hint_packets(ByteIOContext *out, const uint8_t *data, int size, MOVTrack *trk, int64_t *pts) { int64_t curpos; int64_t count_pos, entries_pos; int count = 0, entries; count_pos = url_ftell(out); /* RTPsample header */ put_be16(out, 0); /* packet count */ put_be16(out, 0); /* reserved */ while (size > 4) { uint32_t packet_len = AV_RB32(data); uint16_t seq; uint32_t ts; data += 4; size -= 4; if (packet_len > size || packet_len <= 12) break; if (data[1] >= 200 && data[1] <= 204) { /* RTCP packet, just skip */ data += packet_len; size -= packet_len; continue; } if (packet_len > trk->max_packet_size) trk->max_packet_size = packet_len; seq = AV_RB16(&data[2]); ts = AV_RB32(&data[4]); if (trk->prev_rtp_ts == 0) trk->prev_rtp_ts = ts; /* Unwrap the 32-bit RTP timestamp that wraps around often * into a not (as often) wrapping 64-bit timestamp. */ trk->cur_rtp_ts_unwrapped += (int32_t) (ts - trk->prev_rtp_ts); trk->prev_rtp_ts = ts; if (*pts == AV_NOPTS_VALUE) *pts = trk->cur_rtp_ts_unwrapped; count++; /* RTPpacket header */ put_be32(out, 0); /* relative_time */ put_buffer(out, data, 2); /* RTP header */ put_be16(out, seq); /* RTPsequenceseed */ put_be16(out, 0); /* reserved + flags */ entries_pos = url_ftell(out); put_be16(out, 0); /* entry count */ data += 12; size -= 12; packet_len -= 12; entries = 0; /* Write one or more constructors describing the payload data */ describe_payload(data, packet_len, out, &entries, &trk->sample_queue); data += packet_len; size -= packet_len; curpos = url_ftell(out); url_fseek(out, entries_pos, SEEK_SET); put_be16(out, entries); url_fseek(out, curpos, SEEK_SET); } curpos = url_ftell(out); url_fseek(out, count_pos, SEEK_SET); put_be16(out, count); url_fseek(out, curpos, SEEK_SET); return count; }