Skip to content

Commit

Permalink
fix: rtp h266 de-packetize
Browse files Browse the repository at this point in the history
  • Loading branch information
ireader committed Oct 18, 2024
1 parent 2346f6b commit 6d785f1
Show file tree
Hide file tree
Showing 9 changed files with 219 additions and 4 deletions.
7 changes: 7 additions & 0 deletions libmpeg/include/mpeg-util.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#ifndef _mpeg_util_h_
#define _mpeg_util_h_

#ifdef __cplusplus
extern "C" {
#endif

#include "mpeg-types.h"
#include <assert.h>

Expand Down Expand Up @@ -169,4 +173,7 @@ int mpeg_h266_start_with_access_unit_delimiter(const uint8_t* p, size_t bytes);

uint32_t mpeg_crc32(uint32_t crc, const uint8_t *buffer, uint32_t size);

#ifdef __cplusplus
}
#endif
#endif /* !_mpeg_util_h_ */
4 changes: 2 additions & 2 deletions librtp/payload/rtp-h266-unpack.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// https://www.ietf.org/archive/id/draft-ietf-avtcore-rtp-vvc-18.htm
// https://www.rfc-editor.org/rfc/rfc9328.html

#include "rtp-packet.h"
#include "rtp-payload-internal.h"
Expand Down Expand Up @@ -259,7 +259,7 @@ static int rtp_h266_unpack_input(void* p, const void* packet, int bytes)

assert(pkt.payloadlen > 2);
ptr = (const uint8_t*)pkt.payload;
nal = H266_TYPE(ptr[0]);
nal = H266_TYPE(ptr[1]);

if (nal > 31)
return 0; // packet discard, Unsupported (VVC) NAL type
Expand Down
4 changes: 2 additions & 2 deletions librtp/payload/rtp-mp4a-latm-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ static int rtp_mp4a_latm_pack_input(void* pack, const void* data, int bytes, uin
int r;
int n, len;
uint8_t *rtp;
uint8_t hd[400]; // 100KB
uint8_t hd[40]; // 10KB
const uint8_t *ptr;
struct rtp_encode_mp4a_latm_t *packer;
packer = (struct rtp_encode_mp4a_latm_t *)pack;
Expand Down Expand Up @@ -117,7 +117,7 @@ static int rtp_mp4a_latm_pack_input(void* pack, const void* data, int bytes, uin
memcpy(rtp + n + len, packer->pkt.payload, packer->pkt.payloadlen);
r = packer->handler.packet(packer->cbparam, rtp, n + len + packer->pkt.payloadlen, packer->pkt.rtp.timestamp, 0);
packer->handler.free(packer->cbparam, rtp);
len = 0;
len = 0; // write PayloadLengthInfo once only
}

return r;
Expand Down
20 changes: 20 additions & 0 deletions librtsp/include/sdp-a-fmtp.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,26 @@ struct sdp_a_fmtp_h265_t

int sdp_a_fmtp_h265(const char* fmtp, int *format, struct sdp_a_fmtp_h265_t *h265);

// H.266
enum {
SDP_A_FMTP_H266_SPROP_VPS = 0x00000100,
SDP_A_FMTP_H266_SPROP_SPS = 0x00000200,
SDP_A_FMTP_H266_SPROP_PPS = 0x00000400,
SDP_A_FMTP_H266_SPROP_SEI = 0x00000800,
SDP_A_FMTP_H266_SPROP_DCI = 0x00001000,
};
struct sdp_a_fmtp_h266_t
{
int flags; // test with (1<<SDP_A_FMTP_H266_xxx)
char sprop_vps[1];
char sprop_sps[1];
char sprop_pps[1];
char sprop_sei[1];
char sprop_dci[1];
};

int sdp_a_fmtp_h266(const char* fmtp, int* format, struct sdp_a_fmtp_h266_t* h266);

// mpeg4-generic
enum {
SDP_A_FMTP_MPEG4_OBJECTTYPE = 0x0001,
Expand Down
81 changes: 81 additions & 0 deletions librtsp/source/sdp-a-fmtp.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,87 @@ int sdp_a_fmtp_h265(const char* fmtp, int *format, struct sdp_a_fmtp_h265_t *h26
return 0;
}

// RFC9328 RTP Payload Format for Versatile Video Coding(VVC)
// m=video 49170 RTP/AVP 98
// a=rtpmap:98 H266/90000
// a=fmtp:98 profile-id=1; sprop-vps=<video parameter sets data>
int sdp_a_fmtp_h266(const char* fmtp, int* format, struct sdp_a_fmtp_h266_t* h266)
{
size_t nc;
const char* p1, * p2;
const char* p = fmtp;

// payload type
*format = atoi(p);
p1 = strchr(p, ' ');
if (!p1 || ' ' != *p1)
return -1;

h266->flags = 0;
assert(' ' == *p1);
p = p1 + 1;
while (*p)
{
p1 = strchr(p, '=');
if (!p1 || '=' != *p1)
return -1;

p2 = strchr(p1 + 1, ';');
if (!p2)
p2 = p1 + strlen(p1);

while (' ' == *p) p++; // skip space

nc = (size_t)(p1 - p); // ptrdiff_t to size_t
//vc = (size_t)(p2 - p1 - 1); // ptrdiff_t to size_t
switch (*p)
{
case 'i':
// interop-constraints
break;
case 'l':
// level-id
break;
case 'p':
// profile-space
// profile-id
// profile-compatibility-indicator
break;

case 's':
// sprop-dci
// sprop-vps
// sprop-sps
// sprop-pps
// sprop-sei
if (0 == strncasecmp("sprop-vps", p, nc))
{
}
else if (0 == strncasecmp("sprop-sps", p, nc))
{
}
else if (0 == strncasecmp("sprop-pps", p, nc))
{
}
else if (0 == strncasecmp("sprop-sei", p, nc))
{
}
else if (0 == strncasecmp("sprop-dci", p, nc))
{
}
break;

case 't':
// tier-flag
break;
}

p = *p2 ? p2 + 1 : p2;
}

return 0;
}

// RFC3640 RTP Payload Format for Transport of MPEG-4 Elementary Streams
// m=audio 49230 RTP/AVP 96
// a=rtpmap:96 mpeg4-generic/16000/1
Expand Down
92 changes: 92 additions & 0 deletions librtsp/source/sdp/sdp-h266.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// RFC 9328 RTP Payload Format for Versatile Video Coding(VVC)

#include "mpeg4-vvc.h"
#include "sdp-payload.h"
#include "base64.h"
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>

int sdp_h266(uint8_t *data, int bytes, const char* proto, unsigned short port, int payload, int frequence, const void* extra, int extra_size)
{
static const char* pattern =
"m=video %hu %s %d\n"
"a=rtpmap:%d H266/90000\n"
"a=fmtp:%d";

const uint8_t nalu[] = { 13/*dci*/, 14/*vps*/, 15/*sps*/, 16/*pps*/ };
const char* sprop[] = { "sprop-dci", "sprop-vps", "sprop-sps", "sprop-pps" };

int r, n;
int i, j, k;
struct mpeg4_vvc_t vvc;

assert(90000 == frequence);
r = mpeg4_vvc_decoder_configuration_record_load((const uint8_t*)extra, extra_size, &vvc);
if (r < 0)
return r;

n = snprintf((char*)data, bytes, pattern, port, proto && *proto ? proto : "RTP/AVP", payload, payload, payload);

for (i = 0; i < sizeof(nalu) / sizeof(nalu[0]) && n < bytes; i++)
{
if (i > 0 && n < bytes) data[n++] = ';';
n += snprintf((char*)data + n, bytes - n, " %s=", sprop[i]);

for (k = j = 0; j < vvc.numOfArrays; j++)
{
assert(vvc.nalu[j].bytes > 2 && vvc.nalu[j].type == ((vvc.nalu[j].data[1] >> 3) & 0x1F));
if (nalu[i] != vvc.nalu[j].type)
continue;

if (n + 1 + vvc.nalu[j].bytes * 2 > bytes)
return -ENOMEM; // don't have enough memory

if (k++ > 0 && n < bytes) data[n++] = ',';
n += (int)base64_encode((char*)data + n, vvc.nalu[j].data, vvc.nalu[j].bytes);
}
}

if(n < bytes)
data[n++] = '\n';
return n;
}

int sdp_h266_load(uint8_t* data, int bytes, const char* vps, const char* sps, const char* pps, const char* sei, const char* dci)
{
int i, n, len, off;
const char* p, * next;
const char* sprops[5];
const uint8_t startcode[] = { 0x00, 0x00, 0x00, 0x01 };

off = 0;
sprops[0] = vps;
sprops[1] = sps;
sprops[2] = pps;
sprops[3] = sei;
sprops[4] = dci;
for (i = 0; i < sizeof(sprops) / sizeof(sprops[0]); i++)
{
p = sprops[i];
while (p)
{
next = strchr(p, ',');
len = next ? (int)(next - p) : (int)strlen(p);
if (off + (len + 3) / 4 * 3 + (int)sizeof(startcode) > bytes)
return -ENOMEM; // don't have enough space

memcpy(data + off, startcode, sizeof(startcode));
n = (int)base64_decode(data + off + sizeof(startcode), p, len);
assert(n <= (len + 3) / 4 * 3);
off += n + sizeof(startcode);
off += n;

p = next ? next + 1 : NULL;
}
}

return 0;
}
10 changes: 10 additions & 0 deletions librtsp/source/utils/rtsp-demuxer.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ struct rtp_payload_info_t
{
struct sdp_a_fmtp_h264_t h264;
struct sdp_a_fmtp_h265_t h265;
struct sdp_a_fmtp_h266_t h266;
struct sdp_a_fmtp_mpeg4_t mpeg4;

struct mpeg4_aac_t aac;
Expand Down Expand Up @@ -98,6 +99,7 @@ int sdp_aac_latm_load(uint8_t* data, int bytes, const char* config);
int sdp_aac_mpeg4_load(uint8_t* data, int bytes, const char* config);
int sdp_h264_load(uint8_t* data, int bytes, const char* config);
int sdp_h265_load(uint8_t* data, int bytes, const char* vps, const char* sps, const char* pps, const char* sei);
int sdp_h266_load(uint8_t* data, int bytes, const char* vps, const char* sps, const char* pps, const char* sei, const char* dci);

static int rtsp_demuxer_avpbs_onpacket(void* param, struct avpacket_t* pkt)
{
Expand Down Expand Up @@ -457,6 +459,14 @@ int rtsp_demuxer_add_payload(struct rtsp_demuxer_t* demuxer, int frequency, int
onpacket = rtsp_demuxer_onh2645nalu;
break;

case AVCODEC_VIDEO_H266:
if (fmtp && *fmtp && 0 == sdp_a_fmtp_h266(fmtp, &payload, &pt->fmtp.h266))
pt->extra_bytes = sdp_h266_load(pt->extra, len, pt->fmtp.h266.sprop_vps, pt->fmtp.h266.sprop_sps, pt->fmtp.h266.sprop_pps, pt->fmtp.h266.sprop_sei, pt->fmtp.h266.sprop_dci);
pt->avbsf = avbsf_find(AVCODEC_VIDEO_H266);
pt->h2645 = pt->avbsf->create(pt->extra, pt->extra_bytes, rtsp_demuxer_onh2645packet, pt);
onpacket = rtsp_demuxer_onh2645nalu;
break;

case AVCODEC_AUDIO_AAC:
if (0 == strcasecmp(encoding, "MPEG4-GENERIC"))
{
Expand Down
4 changes: 4 additions & 0 deletions test/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ extern "C" DEF_FUN_VOID(mpeg4_hevc_test);
extern "C" DEF_FUN_VOID(mpeg4_vvc_test);
extern "C" DEF_FUN_VOID(avswg_avs3_test);
extern "C" DEF_FUN_VOID(mp3_header_test);
extern "C" DEF_FUN_VOID(opus_head_test);
extern "C" DEF_FUN_VOID(flac_streaminfo_test);
extern "C" DEF_FUN_VOID(h264_mp4toannexb_test);
extern "C" DEF_FUN_VOID(sdp_a_fmtp_test);
extern "C" DEF_FUN_VOID(sdp_a_rtpmap_test);
Expand Down Expand Up @@ -250,6 +252,8 @@ int main(int argc, const char* argv[])
RE_RUN_REG("mpeg4_vvc_test", argc, argv);
RE_RUN_REG("avswg_avs3_test", argc, argv);
RE_RUN_REG("mp3_header_test", argc, argv);
RE_RUN_REG("opus_head_test", argc, argv);
RE_RUN_REG("flac_streaminfo_test", argc, argv);
RE_RUN_REG("h264_mp4toannexb_test", argc, argv);
RE_RUN_REG("sdp_a_fmtp_test", argc, argv);
RE_RUN_REG("sdp_a_rtpmap_test", argc, argv);
Expand Down
1 change: 1 addition & 0 deletions test/test.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@
<ClCompile Include="..\librtsp\source\sdp\sdp-g7xx.c" />
<ClCompile Include="..\librtsp\source\sdp\sdp-h264.c" />
<ClCompile Include="..\librtsp\source\sdp\sdp-h265.c" />
<ClCompile Include="..\librtsp\source\sdp\sdp-h266.c" />
<ClCompile Include="..\librtsp\source\sdp\sdp-mpeg2.c" />
<ClCompile Include="..\librtsp\source\sdp\sdp-mpeg4.c" />
<ClCompile Include="..\librtsp\source\sdp\sdp-opus.c" />
Expand Down

0 comments on commit 6d785f1

Please sign in to comment.