Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sdp-utils: add AV1 fmtp parsing #3485

Open
wants to merge 1 commit into
base: 0.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 44 additions & 6 deletions sdp-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ int janus_sdp_get_codec_pt_full(janus_sdp *sdp, const char *codec, const char *p
if(sdp == NULL || codec == NULL)
return -1;
/* Check the format string (note that we only parse what browsers can negotiate) */
gboolean video = FALSE, vp9 = FALSE, h264 = FALSE;
gboolean video = FALSE, vp9 = FALSE, av1 = FALSE, h264 = FALSE;
const char *format = NULL, *format2 = NULL;
if(!strcasecmp(codec, "opus")) {
format = "opus/48000/2";
Expand Down Expand Up @@ -734,7 +734,7 @@ int janus_sdp_get_codec_pt_full(janus_sdp *sdp, const char *codec, const char *p
if(pt < 0) {
JANUS_LOG(LOG_ERR, "Invalid payload type (%s)\n", a->value);
} else if(strstr(a->value, format) || strstr(a->value, format2)) {
if(profile != NULL && (vp9 || h264)) {
if(profile != NULL && (vp9 || h264 || av1)) {
/* Let's keep track of this payload type */
pts = g_list_append(pts, GINT_TO_POINTER(pt));
} else {
Expand Down Expand Up @@ -790,6 +790,15 @@ int janus_sdp_get_codec_pt_full(janus_sdp *sdp, const char *codec, const char *p
g_list_free(pts);
return pt;
}
} else if(av1) {
char av1_profile[20];
g_snprintf(av1_profile, sizeof(profile), "profile=%s", profile);
if(strstr(a->value, av1_profile) != NULL) {
/* Found */
JANUS_LOG(LOG_VERB, "AV1 profile %s found --> %d\n", profile, pt);
g_list_free(pts);
return pt;
}
}
}
ma = ma->next;
Expand Down Expand Up @@ -1214,8 +1223,8 @@ janus_sdp *janus_sdp_generate_offer(const char *name, const char *address, ...)
gboolean do_audio = TRUE, do_video = TRUE, do_data = TRUE,
audio_dtmf = FALSE, video_rtcpfb = TRUE, data_legacy = TRUE;
const char *audio_codec = NULL, *video_codec = NULL,
*vp9_profile = NULL, *h264_profile = NULL,
*audio_fmtp = NULL, *video_fmtp = NULL;
*vp9_profile = NULL, *av1_profile = NULL, *av1_level_idx = NULL,
*av1_tier = NULL, *h264_profile = NULL, *audio_fmtp = NULL, *video_fmtp = NULL;
int audio_pt = 111, video_pt = 96, opusred_pt = 0;
janus_sdp_mdirection audio_dir = JANUS_SDP_SENDRECV, video_dir = JANUS_SDP_SENDRECV;
GHashTable *audio_extmaps = NULL, *audio_extids = NULL,
Expand All @@ -1238,6 +1247,12 @@ janus_sdp *janus_sdp_generate_offer(const char *name, const char *address, ...)
video_codec = va_arg(args, char *);
} else if(property == JANUS_SDP_OA_VP9_PROFILE) {
vp9_profile = va_arg(args, char *);
} else if(property == JANUS_SDP_OA_AV1_PROFILE) {
av1_profile = va_arg(args, char *);
} else if(property == JANUS_SDP_OA_AV1_LEVEL_IDX) {
av1_level_idx = va_arg(args, char *);
} else if(property == JANUS_SDP_OA_AV1_TIER) {
av1_tier = va_arg(args, char *);
} else if(property == JANUS_SDP_OA_H264_PROFILE) {
h264_profile = va_arg(args, char *);
} else if(property == JANUS_SDP_OA_AUDIO_PT) {
Expand Down Expand Up @@ -1430,6 +1445,13 @@ janus_sdp *janus_sdp_generate_offer(const char *name, const char *address, ...)
/* Add a profile-id fmtp attribute */
a = janus_sdp_attribute_create("fmtp", "%d profile-id=%s", video_pt, vp9_profile);
m->attributes = g_list_append(m->attributes, a);
} else if(!strcasecmp(video_codec, "av1")) {
/* Add a profile fmtp attribute */
a = janus_sdp_attribute_create("fmtp", "%d profile=%s;level-idx=%s;tier=%s",
video_pt, av1_profile ? av1_profile : "0", /* If not present, it MUST be inferred to be 0 ("Main" profile). */
av1_level_idx ? av1_level_idx : "5", /* If not present, it MUST be inferred to be 5. */
av1_tier ? av1_tier : "0"); /* If not present, it MUST be inferred to be 0. */
m->attributes = g_list_append(m->attributes, a);
} else if(!strcasecmp(video_codec, "h264") && h264_profile) {
/* Add a profile-level-id fmtp attribute */
a = janus_sdp_attribute_create("fmtp", "%d profile-level-id=%s;packetization-mode=1", video_pt, h264_profile);
Expand Down Expand Up @@ -1484,8 +1506,8 @@ janus_sdp *janus_sdp_generate_answer(janus_sdp *offer, ...) {
gboolean do_audio = TRUE, do_video = TRUE, do_data = TRUE,
audio_dtmf = FALSE, audio_opusred = FALSE, video_rtcpfb = TRUE;
const char *audio_codec = NULL, *video_codec = NULL,
*vp9_profile = NULL, *h264_profile = NULL,
*audio_fmtp = NULL, *video_fmtp = NULL;
*vp9_profile = NULL, *av1_profile = NULL, *av1_level_idx = NULL, *av1_tier = NULL,
*h264_profile = NULL, *audio_fmtp = NULL, *video_fmtp = NULL;
char *custom_audio_fmtp = NULL;
GList *extmaps = NULL;
janus_sdp_mdirection audio_dir = JANUS_SDP_SENDRECV, video_dir = JANUS_SDP_SENDRECV;
Expand All @@ -1507,6 +1529,12 @@ janus_sdp *janus_sdp_generate_answer(janus_sdp *offer, ...) {
video_codec = va_arg(args, char *);
} else if(property == JANUS_SDP_OA_VP9_PROFILE) {
vp9_profile = va_arg(args, char *);
} else if(property == JANUS_SDP_OA_AV1_PROFILE) {
av1_profile = va_arg(args, char *);
} else if(property == JANUS_SDP_OA_AV1_LEVEL_IDX) {
av1_level_idx = va_arg(args, char *);
} else if(property == JANUS_SDP_OA_AV1_TIER) {
av1_tier = va_arg(args, char *);
} else if(property == JANUS_SDP_OA_H264_PROFILE) {
h264_profile = va_arg(args, char *);
} else if(property == JANUS_SDP_OA_AUDIO_DTMF) {
Expand Down Expand Up @@ -1704,6 +1732,8 @@ janus_sdp *janus_sdp_generate_answer(janus_sdp *offer, ...) {
const char *video_profile = NULL;
if(codec && !strcasecmp(codec, "vp9"))
video_profile = vp9_profile;
else if(codec && !strcasecmp(codec, "av1"))
video_profile = av1_profile;
else if(codec && !strcasecmp(codec, "h264"))
video_profile = h264_profile;
int pt = janus_sdp_get_codec_pt_full(offer, codec, video_profile);
Expand Down Expand Up @@ -1802,6 +1832,13 @@ janus_sdp *janus_sdp_generate_answer(janus_sdp *offer, ...) {
/* Add a profile-id fmtp attribute */
a = janus_sdp_attribute_create("fmtp", "%d profile-id=%s", pt, vp9_profile);
am->attributes = g_list_append(am->attributes, a);
} else if(!strcasecmp(codec, "av1")) {
/* Add a profile fmtp attribute */
a = janus_sdp_attribute_create("fmtp", "%d profile=%s;level-idx=%s;tier=%s", pt,
av1_profile ? av1_profile : "0",
av1_level_idx ? av1_level_idx : "5",
av1_tier ? av1_tier : "0");
am->attributes = g_list_append(am->attributes, a);
} else if(!strcasecmp(codec, "h264") && h264_profile) {
/* Add a profile-level-id fmtp attribute */
a = janus_sdp_attribute_create("fmtp", "%d profile-level-id=%s;packetization-mode=1", pt, h264_profile);
Expand Down Expand Up @@ -1856,6 +1893,7 @@ janus_sdp *janus_sdp_generate_answer(janus_sdp *offer, ...) {
/* Check if we need to copy the fmtp attribute too */
if(((!strcasecmp(codec, "vp8") && video_fmtp == NULL)) ||
((!strcasecmp(codec, "vp9") && vp9_profile == NULL && video_fmtp == NULL)) ||
((!strcasecmp(codec, "av1") && av1_profile == NULL && av1_tier == NULL && av1_level_idx == NULL && video_fmtp == NULL)) ||
((!strcasecmp(codec, "h264") && h264_profile == NULL && video_fmtp == NULL))) {
/* FIXME Copy the fmtp attribute (we should check if we support it) */
a = janus_sdp_attribute_create("fmtp", "%s", a->value);
Expand Down
6 changes: 6 additions & 0 deletions sdp-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,12 @@ JANUS_SDP_OA_AUDIO_CODEC,
JANUS_SDP_OA_VIDEO_CODEC,
/*! \brief When generating an offer or answer automatically, use this profile for VP9 (depends on value that follows) */
JANUS_SDP_OA_VP9_PROFILE,
/*! \brief When generating an offer or answer automatically, use this profile for AV1 (depends on value that follows) */
JANUS_SDP_OA_AV1_PROFILE,
/*! \brief When generating an offer or answer automatically, use this level-idx for AV1 (depends on value that follows) */
JANUS_SDP_OA_AV1_LEVEL_IDX,
/*! \brief When generating an offer or answer automatically, use this tier for AV1 (depends on value that follows) */
JANUS_SDP_OA_AV1_TIER,
/*! \brief When generating an offer or answer automatically, use this profile for H.264 (depends on value that follows) */
JANUS_SDP_OA_H264_PROFILE,
/*! \brief When generating an offer (this is ignored for answers), use this payload type for audio (depends on value that follows) */
Expand Down