/// RFC2250 3. Encapsulation of MPEG Elementary Streams (p4) #include "rtp-packet.h" #include "rtp-profile.h" #include "rtp-payload-helper.h" #include "rtp-payload-internal.h" #include #include #include #include #define MPEG2VIDEO_EXTENSION_HEADER 0x04 static int rtp_decode_mpeg2es(void* p, const void* packet, int bytes) { int n; struct rtp_packet_t pkt; struct rtp_payload_helper_t *helper; helper = (struct rtp_payload_helper_t *)p; if (!helper || 0 != rtp_packet_deserialize(&pkt, packet, bytes) || pkt.payloadlen < 4) return -EINVAL; if (RTP_PAYLOAD_MP3 != pkt.rtp.pt && RTP_PAYLOAD_MPV != pkt.rtp.pt) { assert(0); return -EINVAL; } rtp_payload_check(helper, &pkt); // save payload if (!helper->lost) { n = 4; // skip 3.4 MPEG Video-specific header if (RTP_PAYLOAD_MPV == pkt.rtp.pt && (((uint8_t*)pkt.payload)[4] & MPEG2VIDEO_EXTENSION_HEADER)) n += 4; // 3.4.1 MPEG-2 Video-specific header extension assert(pkt.payloadlen > 4); if (pkt.payload && pkt.payloadlen > n) { pkt.payload = (uint8_t*)pkt.payload + n; pkt.payloadlen -= n; rtp_payload_write(helper, &pkt); } } // M bit: For video, set to 1 on packet containing MPEG frame end code, 0 otherwise. // For audio, set to 1 on first packet of a "talk-spurt," 0 otherwise. if (pkt.rtp.m && RTP_PAYLOAD_MPV == pkt.rtp.pt) { rtp_payload_onframe(helper); } return helper->lost ? 0 : 1; // packet handled } struct rtp_payload_decode_t *rtp_mpeg1or2es_decode() { static struct rtp_payload_decode_t unpacker = { rtp_payload_helper_create, rtp_payload_helper_destroy, rtp_decode_mpeg2es, }; return &unpacker; }