1package environment
2
3import (
4 "log"
5 "os"
6 "strconv"
7 "strings"
8
9 "github.com/bnema/dumber/internal/config"
10)
11
12// ApplyCodecConfiguration applies codec preferences to environment variables and GStreamer settings
13func ApplyCodecConfiguration(codecPrefs config.CodecConfig) {
14 log.Printf("[codec] Applying codec preferences: preferred=%s, force_av1=%t, block_vp9=%t",
15 codecPrefs.PreferredCodecs, codecPrefs.ForceAV1, codecPrefs.BlockVP9)
16
17 // Build comprehensive GStreamer plugin rankings
18 var rankSettings []string
19
20 // Get existing GST_PLUGIN_FEATURE_RANK or start fresh
21 existingRank := os.Getenv("GST_PLUGIN_FEATURE_RANK")
22 if existingRank != "" {
23 rankSettings = strings.Split(existingRank, ",")
24 }
25
26 // AV1 decoder promotions (high priority)
27 if codecPrefs.ForceAV1 || strings.Contains(codecPrefs.PreferredCodecs, "av1") {
28 av1Ranks := []string{
29 "vaav1dec:768", // VA-API AV1 decoder (highest priority)
30 "nvav1dec:512", // NVDEC AV1 decoder
31 "av1dec:384", // Software AV1 decoder (fallback)
32 "avdec_av1:256", // libav AV1 decoder
33 }
34 rankSettings = append(rankSettings, av1Ranks...)
35 log.Printf("[codec] Promoted AV1 decoders for maximum priority")
36 }
37
38 // H.264 decoder management
39 if strings.Contains(codecPrefs.PreferredCodecs, "h264") {
40 h264Ranks := []string{
41 "vah264dec:512", // VA-API H.264 decoder
42 "nvh264dec:384", // NVDEC H.264 decoder
43 "avdec_h264:256", // Software H.264 decoder
44 }
45 rankSettings = append(rankSettings, h264Ranks...)
46 }
47
48 // VP9 decoder demotion/blocking
49 if codecPrefs.DisableVP9Hardware || codecPrefs.BlockVP9 {
50 vp9Demotions := []string{
51 "vaapivp9dec:0", // Block VA-API VP9
52 "nvvp9dec:0", // Block NVDEC VP9
53 }
54 if codecPrefs.BlockVP9 {
55 vp9Demotions = append(vp9Demotions, "vp9dec:0", "avdec_vp9:0") // Block all VP9
56 } else {
57 // Allow software VP9 with low priority
58 vp9Demotions = append(vp9Demotions, "vp9dec:64", "avdec_vp9:64")
59 }
60 rankSettings = append(rankSettings, vp9Demotions...)
61 log.Printf("[codec] Demoted/blocked VP9 decoders")
62 }
63
64 // VP8 decoder blocking
65 if codecPrefs.BlockVP8 {
66 vp8Demotions := []string{
67 "vaapivp8dec:0",
68 "vp8dec:0",
69 "avdec_vp8:0",
70 }
71 rankSettings = append(rankSettings, vp8Demotions...)
72 log.Printf("[codec] Blocked VP8 decoders")
73 }
74
75 // Apply the complete ranking system
76 if len(rankSettings) > 0 {
77 finalRank := strings.Join(rankSettings, ",")
78 if err := os.Setenv("GST_PLUGIN_FEATURE_RANK", finalRank); err != nil {
79 log.Printf("[codec] Warning: failed to set GST_PLUGIN_FEATURE_RANK: %v", err)
80 } else {
81 log.Printf("[codec] Set comprehensive GST_PLUGIN_FEATURE_RANK: %s", finalRank)
82 }
83 }
84
85 // Set video buffer sizes if specified
86 if codecPrefs.VideoBufferSizeMB > 0 {
87 bufferSize := strconv.Itoa(codecPrefs.VideoBufferSizeMB * 1024 * 1024)
88
89 if err := os.Setenv("GST_BUFFER_SIZE", bufferSize); err != nil {
90 log.Printf("[codec] Warning: failed to set GST_BUFFER_SIZE: %v", err)
91 }
92
93 if err := os.Setenv("GST_QUEUE2_MAX_SIZE_BYTES", bufferSize); err != nil {
94 log.Printf("[codec] Warning: failed to set GST_QUEUE2_MAX_SIZE_BYTES: %v", err)
95 }
96
97 log.Printf("[codec] Set video buffer size to %dMB", codecPrefs.VideoBufferSizeMB)
98 }
99
100 // Set queue buffer time if specified
101 if codecPrefs.QueueBufferTimeSec > 0 {
102 // Convert seconds to nanoseconds for GStreamer
103 bufferTime := strconv.Itoa(codecPrefs.QueueBufferTimeSec * 1000000000)
104
105 if err := os.Setenv("GST_QUEUE2_MAX_SIZE_TIME", bufferTime); err != nil {
106 log.Printf("[codec] Warning: failed to set GST_QUEUE2_MAX_SIZE_TIME: %v", err)
107 } else {
108 log.Printf("[codec] Set queue buffer time to %ds", codecPrefs.QueueBufferTimeSec)
109 }
110 }
111
112 // Set additional codec-specific environment variables
113 if codecPrefs.ForceAV1 {
114 // Enable AV1 hardware decoding if available
115 if err := os.Setenv("GST_AV1_DECODER_ENABLE_HW", "1"); err != nil {
116 log.Printf("[codec] Warning: failed to set GST_AV1_DECODER_ENABLE_HW: %v", err)
117 }
118 }
119
120 // Disable video post-processing to avoid VA-API issues
121 if err := os.Setenv("GST_VAAPI_DISABLE_VPP", "1"); err != nil {
122 log.Printf("[codec] Warning: failed to set GST_VAAPI_DISABLE_VPP: %v", err)
123 }
124
125 log.Printf("[codec] Codec configuration applied successfully")
126}
127
128// BuildBlockedCodecsList converts config codec blocking preferences to a string slice
129func BuildBlockedCodecsList(codecPrefs config.CodecConfig) []string {
130 var blocked []string
131
132 if codecPrefs.BlockVP9 {
133 blocked = append(blocked, "vp9")
134 }
135 if codecPrefs.BlockVP8 {
136 blocked = append(blocked, "vp8")
137 }
138
139 return blocked
140}