PR #23535 opened by qwerzoid
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23535
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23535.patch

This commit adds support for vp8 and vp9 video codecs in addition
to the existing h264 so that the streams can be published using
either of them.

Signed-off-by: Aditya Banavi <[email protected]>


>From b4ed6d615830475ed1957f85474dcdc50294fa29 Mon Sep 17 00:00:00 2001
From: Aditya Banavi <[email protected]>
Date: Thu, 18 Jun 2026 18:37:57 +0000
Subject: [PATCH] avformat/whip: Support for vp8 and vp9 video codecs

This commit adds support for vp8 and vp9 video codecs in addition
to the existing h264 so that the streams can be published using
either of them.

Signed-off-by: Aditya Banavi <[email protected]>
---
 libavformat/whip.c | 288 ++++++++++++++++++++++++++++++---------------
 1 file changed, 190 insertions(+), 98 deletions(-)

diff --git a/libavformat/whip.c b/libavformat/whip.c
index edd9136d3e..79bc2fba50 100644
--- a/libavformat/whip.c
+++ b/libavformat/whip.c
@@ -96,8 +96,12 @@
  */
 #define MAX_UDP_BUFFER_SIZE 4096
 
-/* Referring to Chrome's definition of RTP payload types. */
-#define WHIP_RTP_PAYLOAD_TYPE_H264 106
+/* Referring to Chrome's definition of RTP payload types. ( 
webrtc/media/base/constant.cc )*/
+#define WHIP_RTP_PAYLOAD_TYPE_VIDEO_VP8_RTX 96
+#define WHIP_RTP_PAYLOAD_TYPE_VIDEO_VP9_RTX 97
+#define WHIP_RTP_PAYLOAD_TYPE_VP8 100
+#define WHIP_RTP_PAYLOAD_TYPE_VP9 101
+#define WHIP_RTP_PAYLOAD_TYPE_H264 107
 #define WHIP_RTP_PAYLOAD_TYPE_OPUS 111
 #define WHIP_RTP_PAYLOAD_TYPE_VIDEO_RTX 105
 
@@ -484,39 +488,42 @@ static int parse_profile_level(AVFormatContext *s, 
AVCodecParameters *par)
     uint32_t state;
     WHIPContext *whip = s->priv_data;
 
-    if (par->codec_id != AV_CODEC_ID_H264)
+    if (par->codec_id != AV_CODEC_ID_H264 && par->codec_id != AV_CODEC_ID_VP8 
&& par->codec_id != AV_CODEC_ID_VP9)
         return ret;
 
-    if (par->profile != AV_PROFILE_UNKNOWN && par->level != AV_LEVEL_UNKNOWN)
-        return ret;
+    if (par->codec_id == AV_CODEC_ID_H264) {
 
-    if (!par->extradata || par->extradata_size <= 0) {
-        av_log(whip, AV_LOG_ERROR, "Unable to parse profile from empty 
extradata=%p, size=%d\n",
-            par->extradata, par->extradata_size);
-        return AVERROR(EINVAL);
-    }
+        if (par->profile != AV_PROFILE_UNKNOWN && par->level != 
AV_LEVEL_UNKNOWN)
+            return ret;
 
-    while (1) {
-        r = avpriv_find_start_code(r, end, &state);
-        if (r >= end)
-            break;
-
-        r1 = ff_nal_find_startcode(r, end);
-        if ((state & 0x1f) == H264_NAL_SPS) {
-            ret = ff_avc_decode_sps(sps, r, r1 - r);
-            if (ret < 0) {
-                av_log(whip, AV_LOG_ERROR, "Failed to decode SPS, state=%x, 
size=%d\n",
-                    state, (int)(r1 - r));
-                return ret;
-            }
-
-            av_log(whip, AV_LOG_VERBOSE, "Parse profile=%d, level=%d from 
SPS\n",
-                sps->profile_idc, sps->level_idc);
-            par->profile = sps->profile_idc;
-            par->level = sps->level_idc;
+        if (!par->extradata || par->extradata_size <= 0) {
+            av_log(whip, AV_LOG_ERROR, "Unable to parse profile from empty 
extradata=%p, size=%d\n",
+                par->extradata, par->extradata_size);
+            return AVERROR(EINVAL);
         }
 
-        r = r1;
+        while (1) {
+            r = avpriv_find_start_code(r, end, &state);
+            if (r >= end)
+                break;
+
+            r1 = ff_nal_find_startcode(r, end);
+            if ((state & 0x1f) == H264_NAL_SPS) {
+                ret = ff_avc_decode_sps(sps, r, r1 - r);
+                if (ret < 0) {
+                    av_log(whip, AV_LOG_ERROR, "Failed to decode SPS, 
state=%x, size=%d\n",
+                        state, (int)(r1 - r));
+                    return ret;
+                }
+
+                av_log(whip, AV_LOG_VERBOSE, "Parse profile=%d, level=%d from 
SPS\n",
+                    sps->profile_idc, sps->level_idc);
+                par->profile = sps->profile_idc;
+                par->level = sps->level_idc;
+            }
+
+            r = r1;
+        }
     }
 
     return ret;
@@ -559,32 +566,35 @@ static int parse_codec(AVFormatContext *s)
                 return AVERROR_PATCHWELCOME;
             }
 
-            if ((ret = parse_profile_level(s, par)) < 0) {
-                av_log(whip, AV_LOG_ERROR, "Failed to parse SPS/PPS from 
extradata\n");
-                return AVERROR(EINVAL);
-            }
+            if (par->codec_id == AV_CODEC_ID_H264) {
 
-            if (par->profile == AV_PROFILE_UNKNOWN) {
-                av_log(whip, AV_LOG_WARNING, "No profile found in extradata, 
consider baseline\n");
-                return AVERROR(EINVAL);
-            }
-            if (par->level == AV_LEVEL_UNKNOWN) {
-                av_log(whip, AV_LOG_WARNING, "No level found in extradata, 
consider 3.1\n");
-                return AVERROR(EINVAL);
-            }
-            break;
-        case AVMEDIA_TYPE_AUDIO:
-            whip->audio_par = par;
+                if ((ret = parse_profile_level(s, par)) < 0) {
+                    av_log(whip, AV_LOG_ERROR, "Failed to parse SPS/PPS from 
extradata\n");
+                    return AVERROR(EINVAL);
+                }
 
-            if (par->ch_layout.nb_channels != 2) {
-                av_log(whip, AV_LOG_ERROR, "Unsupported audio channels %d by 
RTC, choose stereo\n",
-                    par->ch_layout.nb_channels);
-                return AVERROR_PATCHWELCOME;
-            }
+                if (par->profile == AV_PROFILE_UNKNOWN) {
+                    av_log(whip, AV_LOG_WARNING, "No profile found in 
extradata, consider baseline\n");
+                    return AVERROR(EINVAL);
+                }
+                if (par->level == AV_LEVEL_UNKNOWN) {
+                    av_log(whip, AV_LOG_WARNING, "No level found in extradata, 
consider 3.1\n");
+                    return AVERROR(EINVAL);
+                }
+                break;
+            case AVMEDIA_TYPE_AUDIO:
+                whip->audio_par = par;
 
-            if (par->sample_rate != 48000) {
-                av_log(whip, AV_LOG_ERROR, "Unsupported audio sample rate %d 
by RTC, choose 48000\n", par->sample_rate);
-                return AVERROR_PATCHWELCOME;
+                if (par->ch_layout.nb_channels != 2) {
+                    av_log(whip, AV_LOG_ERROR, "Unsupported audio channels %d 
by RTC, choose stereo\n",
+                        par->ch_layout.nb_channels);
+                    return AVERROR_PATCHWELCOME;
+                }
+
+                if (par->sample_rate != 48000) {
+                    av_log(whip, AV_LOG_ERROR, "Unsupported audio sample rate 
%d by RTC, choose 48000\n", par->sample_rate);
+                    return AVERROR_PATCHWELCOME;
+                }
             }
             break;
         default:
@@ -632,10 +642,6 @@ static int generate_sdp_offer(AVFormatContext *s)
     whip->video_ssrc = whip->audio_ssrc + 1;
     whip->video_rtx_ssrc = whip->video_ssrc + 1;
 
-    whip->audio_payload_type = WHIP_RTP_PAYLOAD_TYPE_OPUS;
-    whip->video_payload_type = WHIP_RTP_PAYLOAD_TYPE_H264;
-    whip->video_rtx_payload_type = WHIP_RTP_PAYLOAD_TYPE_VIDEO_RTX;
-
     if (whip->audio_par) {
         bundle[bundle_index++] = '0';
         bundle[bundle_index++] = ' ';
@@ -659,8 +665,10 @@ static int generate_sdp_offer(AVFormatContext *s)
         bundle);
 
     if (whip->audio_par) {
-        if (whip->audio_par->codec_id == AV_CODEC_ID_OPUS)
+        if (whip->audio_par->codec_id == AV_CODEC_ID_OPUS) {
             acodec_name = "opus";
+            whip->audio_payload_type = WHIP_RTP_PAYLOAD_TYPE_OPUS;
+        }
 
         av_bprintf(&bp, ""
             "m=audio 9 UDP/TLS/RTP/SAVPF %u\r\n"
@@ -693,51 +701,135 @@ static int generate_sdp_offer(AVFormatContext *s)
         level = whip->video_par->level;
         if (whip->video_par->codec_id == AV_CODEC_ID_H264) {
             vcodec_name = "H264";
+            whip->video_payload_type = WHIP_RTP_PAYLOAD_TYPE_H264;
+            whip->video_rtx_payload_type = WHIP_RTP_PAYLOAD_TYPE_VIDEO_RTX;
             profile_iop |= whip->video_par->profile & 
AV_PROFILE_H264_CONSTRAINED ? 1 << 6 : 0;
             profile_iop |= whip->video_par->profile & AV_PROFILE_H264_INTRA ? 
1 << 4 : 0;
             profile_idc = whip->video_par->profile & 0x00ff;
-        }
 
-        av_bprintf(&bp, ""
-            "m=video 9 UDP/TLS/RTP/SAVPF %u %u\r\n"
-            "c=IN IP4 0.0.0.0\r\n"
-            "a=ice-ufrag:%s\r\n"
-            "a=ice-pwd:%s\r\n"
-            "a=fingerprint:sha-256 %s\r\n"
-            "a=setup:%s\r\n"
-            "a=mid:1\r\n"
-            "a=sendonly\r\n"
-            "a=msid:FFmpeg video\r\n"
-            "a=rtcp-mux\r\n"
-            "a=rtcp-rsize\r\n"
-            "a=rtpmap:%u %s/90000\r\n"
-            "a=fmtp:%u 
level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=%02x%02x%02x\r\n"
-            "a=rtcp-fb:%u nack\r\n"
-            "a=rtpmap:%u rtx/90000\r\n"
-            "a=fmtp:%u apt=%u\r\n"
-            "a=ssrc-group:FID %u %u\r\n"
-            "a=ssrc:%u cname:FFmpeg\r\n"
-            "a=ssrc:%u msid:FFmpeg video\r\n",
-            whip->video_payload_type,
-            whip->video_rtx_payload_type,
-            whip->ice_ufrag_local,
-            whip->ice_pwd_local,
-            whip->dtls_fingerprint,
-            is_dtls_active ? "active" : "passive",
-            whip->video_payload_type,
-            vcodec_name,
-            whip->video_payload_type,
-            profile_idc,
-            profile_iop,
-            level,
-            whip->video_payload_type,
-            whip->video_rtx_payload_type,
-            whip->video_rtx_payload_type,
-            whip->video_payload_type,
-            whip->video_ssrc,
-            whip->video_rtx_ssrc,
-            whip->video_ssrc,
-            whip->video_ssrc);
+            av_bprintf(&bp, ""
+                "m=video 9 UDP/TLS/RTP/SAVPF %u %u\r\n"
+                "c=IN IP4 0.0.0.0\r\n"
+                "a=ice-ufrag:%s\r\n"
+                "a=ice-pwd:%s\r\n"
+                "a=fingerprint:sha-256 %s\r\n"
+                "a=setup:%s\r\n"
+                "a=mid:1\r\n"
+                "a=sendonly\r\n"
+                "a=msid:FFmpeg video\r\n"
+                "a=rtcp-mux\r\n"
+                "a=rtcp-rsize\r\n"
+                "a=rtpmap:%u %s/90000\r\n"
+                "a=fmtp:%u 
level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=%02x%02x%02x\r\n"
+                "a=rtcp-fb:%u nack\r\n"
+                "a=rtpmap:%u rtx/90000\r\n"
+                "a=fmtp:%u apt=%u\r\n"
+                "a=ssrc-group:FID %u %u\r\n"
+                "a=ssrc:%u cname:FFmpeg\r\n"
+                "a=ssrc:%u msid:FFmpeg video\r\n",
+                whip->video_payload_type,
+                whip->video_rtx_payload_type,
+                whip->ice_ufrag_local,
+                whip->ice_pwd_local,
+                whip->dtls_fingerprint,
+                is_dtls_active ? "active" : "passive",
+                whip->video_payload_type,
+                vcodec_name,
+                whip->video_payload_type,
+                profile_idc,
+                profile_iop,
+                level,
+                whip->video_payload_type,
+                whip->video_rtx_payload_type,
+                whip->video_rtx_payload_type,
+                whip->video_payload_type,
+                whip->video_ssrc,
+                whip->video_rtx_ssrc,
+                whip->video_ssrc,
+                whip->video_ssrc);
+        }
+        else if (whip->video_par->codec_id == AV_CODEC_ID_VP8) {
+            vcodec_name = "VP8";
+            whip->video_payload_type = WHIP_RTP_PAYLOAD_TYPE_VP8;
+            whip->video_rtx_payload_type = WHIP_RTP_PAYLOAD_TYPE_VIDEO_VP8_RTX;
+
+            av_bprintf(&bp, ""
+                "m=video 9 UDP/TLS/RTP/SAVPF %u %u\r\n"
+                "c=IN IP4 0.0.0.0\r\n"
+                "a=ice-ufrag:%s\r\n"
+                "a=ice-pwd:%s\r\n"
+                "a=fingerprint:sha-256 %s\r\n"
+                "a=setup:%s\r\n"
+                "a=mid:1\r\n"
+                "a=sendonly\r\n"
+                "a=msid:FFmpeg video\r\n"
+                "a=rtcp-mux\r\n"
+                "a=rtcp-rsize\r\n"
+                "a=rtpmap:%u %s/90000\r\n"
+                "a=rtcp-fb:%u nack\r\n"
+                "a=rtpmap:%u rtx/90000\r\n"
+                "a=fmtp:%u apt=%u\r\n"
+                "a=ssrc-group:FID %u %u\r\n"
+                "a=ssrc:%u cname:FFmpeg\r\n"
+                "a=ssrc:%u msid:FFmpeg video\r\n",
+                whip->video_payload_type,
+                whip->video_rtx_payload_type,
+                whip->ice_ufrag_local,
+                whip->ice_pwd_local,
+                whip->dtls_fingerprint,
+                is_dtls_active ? "active" : "passive",
+                whip->video_payload_type,
+                vcodec_name,
+                whip->video_payload_type,
+                whip->video_rtx_payload_type,
+                whip->video_rtx_payload_type,
+                whip->video_payload_type,
+                whip->video_ssrc,
+                whip->video_rtx_ssrc,
+                whip->video_ssrc,
+                whip->video_ssrc);
+        }
+        else if (whip->video_par->codec_id == AV_CODEC_ID_VP9) {
+            vcodec_name = "VP9";
+            whip->video_payload_type = WHIP_RTP_PAYLOAD_TYPE_VP9;
+            whip->video_rtx_payload_type = WHIP_RTP_PAYLOAD_TYPE_VIDEO_VP9_RTX;
+
+            av_bprintf(&bp, ""
+                "m=video 9 UDP/TLS/RTP/SAVPF %u %u\r\n"
+                "c=IN IP4 0.0.0.0\r\n"
+                "a=ice-ufrag:%s\r\n"
+                "a=ice-pwd:%s\r\n"
+                "a=fingerprint:sha-256 %s\r\n"
+                "a=setup:%s\r\n"
+                "a=mid:1\r\n"
+                "a=sendonly\r\n"
+                "a=msid:FFmpeg video\r\n"
+                "a=rtcp-mux\r\n"
+                "a=rtcp-rsize\r\n"
+                "a=rtpmap:%u %s/90000\r\n"
+                "a=rtcp-fb:%u nack\r\n"
+                "a=rtpmap:%u rtx/90000\r\n"
+                "a=fmtp:%u apt=%u\r\n"
+                "a=ssrc-group:FID %u %u\r\n"
+                "a=ssrc:%u cname:FFmpeg\r\n"
+                "a=ssrc:%u msid:FFmpeg video\r\n",
+                whip->video_payload_type,
+                whip->video_rtx_payload_type,
+                whip->ice_ufrag_local,
+                whip->ice_pwd_local,
+                whip->dtls_fingerprint,
+                is_dtls_active ? "active" : "passive",
+                whip->video_payload_type,
+                vcodec_name,
+                whip->video_payload_type,
+                whip->video_rtx_payload_type,
+                whip->video_rtx_payload_type,
+                whip->video_payload_type,
+                whip->video_ssrc,
+                whip->video_rtx_ssrc,
+                whip->video_ssrc,
+                whip->video_ssrc);
+        }
     }
 
     if (!av_bprint_is_complete(&bp)) {
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to