From 114520d70b731ab4e4a1c13d3f7b750d698b2179 Mon Sep 17 00:00:00 2001 From: Anunay Maheshwari Date: Tue, 20 Jan 2026 19:55:57 +0530 Subject: [PATCH] move mime to new pkg --- codecs/codecs.go | 49 +++-- codecs/mime/mimetype.go | 365 +++++++++++++++++++++++++++++++ {codecs => mimetype}/mimetype.go | 0 3 files changed, 390 insertions(+), 24 deletions(-) create mode 100644 codecs/mime/mimetype.go rename {codecs => mimetype}/mimetype.go (100%) diff --git a/codecs/codecs.go b/codecs/codecs.go index 3f3ce8a9..9c64e59d 100644 --- a/codecs/codecs.go +++ b/codecs/codecs.go @@ -17,6 +17,7 @@ package codecs import ( "strings" + "github.com/livekit/protocol/codecs/mime" "github.com/livekit/protocol/livekit" "github.com/livekit/protocol/logger" "github.com/pion/webrtc/v4" @@ -25,7 +26,7 @@ import ( var ( OpusCodecParameters = webrtc.RTPCodecParameters{ RTPCodecCapability: webrtc.RTPCodecCapability{ - MimeType: MimeTypeOpus.String(), + MimeType: mime.MimeTypeOpus.String(), ClockRate: 48000, Channels: 2, SDPFmtpLine: "minptime=10;useinbandfec=1", @@ -35,7 +36,7 @@ var ( RedCodecParameters = webrtc.RTPCodecParameters{ RTPCodecCapability: webrtc.RTPCodecCapability{ - MimeType: MimeTypeRED.String(), + MimeType: mime.MimeTypeRED.String(), ClockRate: 48000, Channels: 2, SDPFmtpLine: "111/111", @@ -45,7 +46,7 @@ var ( PCMUCodecParameters = webrtc.RTPCodecParameters{ RTPCodecCapability: webrtc.RTPCodecCapability{ - MimeType: MimeTypePCMU.String(), + MimeType: mime.MimeTypePCMU.String(), ClockRate: 8000, }, PayloadType: 0, @@ -53,7 +54,7 @@ var ( PCMACodecParameters = webrtc.RTPCodecParameters{ RTPCodecCapability: webrtc.RTPCodecCapability{ - MimeType: MimeTypePCMA.String(), + MimeType: mime.MimeTypePCMA.String(), ClockRate: 8000, }, PayloadType: 8, @@ -61,14 +62,14 @@ var ( VideoRTXCodecParameters = webrtc.RTPCodecParameters{ RTPCodecCapability: webrtc.RTPCodecCapability{ - MimeType: MimeTypeRTX.String(), + MimeType: mime.MimeTypeRTX.String(), ClockRate: 90000, }, } VP8CodecParameters = webrtc.RTPCodecParameters{ RTPCodecCapability: webrtc.RTPCodecCapability{ - MimeType: MimeTypeVP8.String(), + MimeType: mime.MimeTypeVP8.String(), ClockRate: 90000, }, PayloadType: 96, @@ -76,7 +77,7 @@ var ( VP9ProfileId0CodecParameters = webrtc.RTPCodecParameters{ RTPCodecCapability: webrtc.RTPCodecCapability{ - MimeType: MimeTypeVP9.String(), + MimeType: mime.MimeTypeVP9.String(), ClockRate: 90000, SDPFmtpLine: "profile-id=0", }, @@ -85,7 +86,7 @@ var ( VP9ProfileId1CodecParameters = webrtc.RTPCodecParameters{ RTPCodecCapability: webrtc.RTPCodecCapability{ - MimeType: MimeTypeVP9.String(), + MimeType: mime.MimeTypeVP9.String(), ClockRate: 90000, SDPFmtpLine: "profile-id=1", }, @@ -94,7 +95,7 @@ var ( H264ProfileLevelId42e01fPacketizationMode0CodecParameters = webrtc.RTPCodecParameters{ RTPCodecCapability: webrtc.RTPCodecCapability{ - MimeType: MimeTypeH264.String(), + MimeType: mime.MimeTypeH264.String(), ClockRate: 90000, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f", }, @@ -103,7 +104,7 @@ var ( H264ProfileLevelId42e01fPacketizationMode1CodecParameters = webrtc.RTPCodecParameters{ RTPCodecCapability: webrtc.RTPCodecCapability{ - MimeType: MimeTypeH264.String(), + MimeType: mime.MimeTypeH264.String(), ClockRate: 90000, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f", }, @@ -113,7 +114,7 @@ var ( H264HighProfileFmtp = "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=640032" H264HighProfileCodecParameters = webrtc.RTPCodecParameters{ RTPCodecCapability: webrtc.RTPCodecCapability{ - MimeType: MimeTypeH264.String(), + MimeType: mime.MimeTypeH264.String(), ClockRate: 90000, SDPFmtpLine: H264HighProfileFmtp, }, @@ -122,7 +123,7 @@ var ( AV1CodecParameters = webrtc.RTPCodecParameters{ RTPCodecCapability: webrtc.RTPCodecCapability{ - MimeType: MimeTypeAV1.String(), + MimeType: mime.MimeTypeAV1.String(), ClockRate: 90000, }, PayloadType: 35, @@ -130,7 +131,7 @@ var ( H265CodecParameters = webrtc.RTPCodecParameters{ RTPCodecCapability: webrtc.RTPCodecCapability{ - MimeType: MimeTypeH265.String(), + MimeType: mime.MimeTypeH265.String(), ClockRate: 90000, }, PayloadType: 116, @@ -176,28 +177,28 @@ func ToWebrtcCodecParameters(codec *livekit.Codec) webrtc.RTPCodecParameters { fmtp := codec.GetFmtpLine() var params webrtc.RTPCodecParameters - switch NormalizeMimeType(codec.GetMime()) { - case MimeTypeOpus: + switch mime.NormalizeMimeType(codec.GetMime()) { + case mime.MimeTypeOpus: params = OpusCodecParameters - case MimeTypeRED: + case mime.MimeTypeRED: params = RedCodecParameters - case MimeTypePCMU: + case mime.MimeTypePCMU: params = PCMUCodecParameters - case MimeTypePCMA: + case mime.MimeTypePCMA: params = PCMACodecParameters - case MimeTypeRTX: + case mime.MimeTypeRTX: params = VideoRTXCodecParameters - case MimeTypeVP8: + case mime.MimeTypeVP8: params = VP8CodecParameters - case MimeTypeVP9: + case mime.MimeTypeVP9: if strings.Contains(fmtp, "profile-id=1") { params = VP9ProfileId1CodecParameters } else { params = VP9ProfileId0CodecParameters } - case MimeTypeAV1: + case mime.MimeTypeAV1: params = AV1CodecParameters - case MimeTypeH264: + case mime.MimeTypeH264: if strings.Contains(fmtp, "profile-level-id=640032") { params = H264HighProfileCodecParameters } else if strings.Contains(fmtp, "packetization-mode=0") { @@ -205,7 +206,7 @@ func ToWebrtcCodecParameters(codec *livekit.Codec) webrtc.RTPCodecParameters { } else { params = H264ProfileLevelId42e01fPacketizationMode1CodecParameters } - case MimeTypeH265: + case mime.MimeTypeH265: params = H265CodecParameters default: return webrtc.RTPCodecParameters{} diff --git a/codecs/mime/mimetype.go b/codecs/mime/mimetype.go new file mode 100644 index 00000000..dea4a9b4 --- /dev/null +++ b/codecs/mime/mimetype.go @@ -0,0 +1,365 @@ +// Copyright 2026 LiveKit, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mime + +import ( + "strings" + + "github.com/pion/webrtc/v4" + + "github.com/livekit/protocol/observability/roomobs" +) + +const ( + MimeTypePrefixAudio = "audio/" + MimeTypePrefixVideo = "video/" +) + +type MimeTypeCodec int + +const ( + MimeTypeCodecUnknown MimeTypeCodec = iota + MimeTypeCodecH264 + MimeTypeCodecH265 + MimeTypeCodecOpus + MimeTypeCodecRED + MimeTypeCodecVP8 + MimeTypeCodecVP9 + MimeTypeCodecAV1 + MimeTypeCodecG722 + MimeTypeCodecPCMU + MimeTypeCodecPCMA + MimeTypeCodecRTX + MimeTypeCodecFlexFEC + MimeTypeCodecULPFEC +) + +func (m MimeTypeCodec) String() string { + switch m { + case MimeTypeCodecUnknown: + return "MimeTypeCodecUnknown" + case MimeTypeCodecH264: + return "H264" + case MimeTypeCodecH265: + return "H265" + case MimeTypeCodecOpus: + return "opus" + case MimeTypeCodecRED: + return "red" + case MimeTypeCodecVP8: + return "VP8" + case MimeTypeCodecVP9: + return "VP9" + case MimeTypeCodecAV1: + return "AV1" + case MimeTypeCodecG722: + return "G722" + case MimeTypeCodecPCMU: + return "PCMU" + case MimeTypeCodecPCMA: + return "PCMA" + case MimeTypeCodecRTX: + return "rtx" + case MimeTypeCodecFlexFEC: + return "flexfec" + case MimeTypeCodecULPFEC: + return "ulpfec" + } + + return "MimeTypeCodecUnknown" +} + +func (m MimeTypeCodec) ToMimeType() MimeType { + switch m { + case MimeTypeCodecUnknown: + return MimeTypeUnknown + case MimeTypeCodecH264: + return MimeTypeH264 + case MimeTypeCodecH265: + return MimeTypeH265 + case MimeTypeCodecOpus: + return MimeTypeOpus + case MimeTypeCodecRED: + return MimeTypeRED + case MimeTypeCodecVP8: + return MimeTypeVP8 + case MimeTypeCodecVP9: + return MimeTypeVP9 + case MimeTypeCodecAV1: + return MimeTypeAV1 + case MimeTypeCodecG722: + return MimeTypeG722 + case MimeTypeCodecPCMU: + return MimeTypePCMU + case MimeTypeCodecPCMA: + return MimeTypePCMA + case MimeTypeCodecRTX: + return MimeTypeRTX + case MimeTypeCodecFlexFEC: + return MimeTypeFlexFEC + case MimeTypeCodecULPFEC: + return MimeTypeULPFEC + } + + return MimeTypeUnknown +} + +func NormalizeMimeTypeCodec(codec string) MimeTypeCodec { + switch { + case strings.EqualFold(codec, "h264"): + return MimeTypeCodecH264 + case strings.EqualFold(codec, "h265"): + return MimeTypeCodecH265 + case strings.EqualFold(codec, "opus"): + return MimeTypeCodecOpus + case strings.EqualFold(codec, "red"): + return MimeTypeCodecRED + case strings.EqualFold(codec, "vp8"): + return MimeTypeCodecVP8 + case strings.EqualFold(codec, "vp9"): + return MimeTypeCodecVP9 + case strings.EqualFold(codec, "av1"): + return MimeTypeCodecAV1 + case strings.EqualFold(codec, "g722"): + return MimeTypeCodecG722 + case strings.EqualFold(codec, "pcmu"): + return MimeTypeCodecPCMU + case strings.EqualFold(codec, "pcma"): + return MimeTypeCodecPCMA + case strings.EqualFold(codec, "rtx"): + return MimeTypeCodecRTX + case strings.EqualFold(codec, "flexfec"): + return MimeTypeCodecFlexFEC + case strings.EqualFold(codec, "ulpfec"): + return MimeTypeCodecULPFEC + } + + return MimeTypeCodecUnknown +} + +func GetMimeTypeCodec(mime string) MimeTypeCodec { + i := strings.IndexByte(mime, '/') + if i == -1 { + return MimeTypeCodecUnknown + } + + return NormalizeMimeTypeCodec(mime[i+1:]) +} + +func IsMimeTypeCodecStringOpus(codec string) bool { + return NormalizeMimeTypeCodec(codec) == MimeTypeCodecOpus +} + +func IsMimeTypeCodecStringRED(codec string) bool { + return NormalizeMimeTypeCodec(codec) == MimeTypeCodecRED +} + +func IsMimeTypeCodecStringPCMA(codec string) bool { + return NormalizeMimeTypeCodec(codec) == MimeTypeCodecPCMA +} + +func IsMimeTypeCodecStringPCMU(codec string) bool { + return NormalizeMimeTypeCodec(codec) == MimeTypeCodecPCMU +} + +func IsMimeTypeCodecStringH264(codec string) bool { + return NormalizeMimeTypeCodec(codec) == MimeTypeCodecH264 +} + +type MimeType int + +const ( + MimeTypeUnknown MimeType = iota + MimeTypeH264 + MimeTypeH265 + MimeTypeOpus + MimeTypeRED + MimeTypeVP8 + MimeTypeVP9 + MimeTypeAV1 + MimeTypeG722 + MimeTypePCMU + MimeTypePCMA + MimeTypeRTX + MimeTypeFlexFEC + MimeTypeULPFEC +) + +func (m MimeType) String() string { + switch m { + case MimeTypeUnknown: + return "MimeTypeUnknown" + case MimeTypeH264: + return webrtc.MimeTypeH264 + case MimeTypeH265: + return webrtc.MimeTypeH265 + case MimeTypeOpus: + return webrtc.MimeTypeOpus + case MimeTypeRED: + return "audio/red" + case MimeTypeVP8: + return webrtc.MimeTypeVP8 + case MimeTypeVP9: + return webrtc.MimeTypeVP9 + case MimeTypeAV1: + return webrtc.MimeTypeAV1 + case MimeTypeG722: + return webrtc.MimeTypeG722 + case MimeTypePCMU: + return webrtc.MimeTypePCMU + case MimeTypePCMA: + return webrtc.MimeTypePCMA + case MimeTypeRTX: + return webrtc.MimeTypeRTX + case MimeTypeFlexFEC: + return webrtc.MimeTypeFlexFEC + case MimeTypeULPFEC: + return "video/ulpfec" + } + + return "MimeTypeUnknown" +} + +func (m MimeType) ReporterType() roomobs.MimeType { + switch m { + case MimeTypeUnknown: + return roomobs.MimeTypeUndefined + case MimeTypeH264: + return roomobs.MimeTypeVideoH264 + case MimeTypeH265: + return roomobs.MimeTypeVideoH265 + case MimeTypeOpus: + return roomobs.MimeTypeAudioOpus + case MimeTypeRED: + return roomobs.MimeTypeAudioRed + case MimeTypeVP8: + return roomobs.MimeTypeVideoVp8 + case MimeTypeVP9: + return roomobs.MimeTypeVideoVp9 + case MimeTypeAV1: + return roomobs.MimeTypeVideoAv1 + case MimeTypeG722: + return roomobs.MimeTypeAudioG722 + case MimeTypePCMU: + return roomobs.MimeTypeAudioPcmu + case MimeTypePCMA: + return roomobs.MimeTypeAudioPcma + case MimeTypeRTX: + return roomobs.MimeTypeVideoRtx + case MimeTypeFlexFEC: + return roomobs.MimeTypeVideoFlexfec + case MimeTypeULPFEC: + return roomobs.MimeTypeVideoUlpfec + } + + return roomobs.MimeTypeUndefined +} + +func NormalizeMimeType(mime string) MimeType { + switch { + case strings.EqualFold(mime, webrtc.MimeTypeH264): + return MimeTypeH264 + case strings.EqualFold(mime, webrtc.MimeTypeH265): + return MimeTypeH265 + case strings.EqualFold(mime, webrtc.MimeTypeOpus): + return MimeTypeOpus + case strings.EqualFold(mime, "audio/red"): + return MimeTypeRED + case strings.EqualFold(mime, webrtc.MimeTypeVP8): + return MimeTypeVP8 + case strings.EqualFold(mime, webrtc.MimeTypeVP9): + return MimeTypeVP9 + case strings.EqualFold(mime, webrtc.MimeTypeAV1): + return MimeTypeAV1 + case strings.EqualFold(mime, webrtc.MimeTypeG722): + return MimeTypeG722 + case strings.EqualFold(mime, webrtc.MimeTypePCMU): + return MimeTypePCMU + case strings.EqualFold(mime, webrtc.MimeTypePCMA): + return MimeTypePCMA + case strings.EqualFold(mime, webrtc.MimeTypeRTX): + return MimeTypeRTX + case strings.EqualFold(mime, webrtc.MimeTypeFlexFEC): + return MimeTypeFlexFEC + case strings.EqualFold(mime, "video/ulpfec"): + return MimeTypeULPFEC + } + + return MimeTypeUnknown +} + +func IsMimeTypeStringEqual(mime1 string, mime2 string) bool { + return NormalizeMimeType(mime1) == NormalizeMimeType(mime2) +} + +func IsMimeTypeStringAudio(mime string) bool { + return strings.HasPrefix(mime, MimeTypePrefixAudio) +} + +func IsMimeTypeAudio(mimeType MimeType) bool { + return strings.HasPrefix(mimeType.String(), MimeTypePrefixAudio) +} + +func IsMimeTypeStringVideo(mime string) bool { + return strings.HasPrefix(mime, MimeTypePrefixVideo) +} + +func IsMimeTypeVideo(mimeType MimeType) bool { + return strings.HasPrefix(mimeType.String(), MimeTypePrefixVideo) +} + +func IsMimeTypeSVCCapable(mimeType MimeType) bool { + switch mimeType { + case MimeTypeAV1, MimeTypeVP9: + return true + } + return false +} + +func IsMimeTypeStringSVCCapable(mime string) bool { + return IsMimeTypeSVCCapable(NormalizeMimeType(mime)) +} + +func IsMimeTypeStringRED(mime string) bool { + return NormalizeMimeType(mime) == MimeTypeRED +} + +func IsMimeTypeStringOpus(mime string) bool { + return NormalizeMimeType(mime) == MimeTypeOpus +} + +func IsMimeTypeStringPCMA(mime string) bool { + return NormalizeMimeType(mime) == MimeTypePCMA +} + +func IsMimeTypeStringPCMU(mime string) bool { + return NormalizeMimeType(mime) == MimeTypePCMU +} + +func IsMimeTypeStringRTX(mime string) bool { + return NormalizeMimeType(mime) == MimeTypeRTX +} + +func IsMimeTypeStringVP8(mime string) bool { + return NormalizeMimeType(mime) == MimeTypeVP8 +} + +func IsMimeTypeStringVP9(mime string) bool { + return NormalizeMimeType(mime) == MimeTypeVP9 +} + +func IsMimeTypeStringH264(mime string) bool { + return NormalizeMimeType(mime) == MimeTypeH264 +} diff --git a/codecs/mimetype.go b/mimetype/mimetype.go similarity index 100% rename from codecs/mimetype.go rename to mimetype/mimetype.go