github.com/puellanivis/breton@v0.2.16/lib/mpeg/ts/packet/adaptationfield.go (about) 1 package packet 2 3 import ( 4 "bytes" 5 "fmt" 6 "strings" 7 8 "github.com/pkg/errors" 9 "github.com/puellanivis/breton/lib/mpeg/ts/pcr" 10 ) 11 12 // AdaptationField defines the MPEG-TS Adaptation Field structure of a packet. 13 type AdaptationField struct { 14 Discontinuity bool 15 RandomAccess bool 16 Priority bool 17 18 PCR *pcr.PCR 19 OPCR *pcr.PCR 20 21 SpliceCountdown *byte 22 23 PrivateData []byte 24 25 LegalTimeWindow struct { 26 Valid bool 27 Value *uint16 28 } 29 30 PiecewiseRate *uint32 31 32 SeamlessSplice struct { 33 Type uint8 34 DTS *uint64 35 } 36 37 Stuffing int 38 } 39 40 func (af *AdaptationField) String() string { 41 if af == nil { 42 return "{}" 43 } 44 45 var out []string 46 47 if af.Discontinuity { 48 out = append(out, "DISCONT") 49 } 50 51 if af.RandomAccess { 52 out = append(out, "RAND") 53 } 54 55 if af.Priority { 56 out = append(out, "PRI") 57 } 58 59 if af.PCR != nil { 60 out = append(out, fmt.Sprintf("PCR:%v", af.PCR)) 61 } 62 63 if af.OPCR != nil { 64 out = append(out, fmt.Sprintf("OPCR:%v", af.OPCR)) 65 } 66 67 if af.SpliceCountdown != nil { 68 out = append(out, fmt.Sprintf("SpliceCountdown:%d", *af.SpliceCountdown)) 69 } 70 71 if len(af.PrivateData) > 0 { 72 out = append(out, fmt.Sprintf("priv[%d]", len(af.PrivateData))) 73 } 74 75 if af.LegalTimeWindow.Value != nil { 76 valid := "" 77 if af.LegalTimeWindow.Valid { 78 valid = "(VALID)" 79 } 80 out = append(out, fmt.Sprintf("LTW%s:x%04X", valid, *af.LegalTimeWindow.Value)) 81 } 82 83 if af.PiecewiseRate != nil { 84 out = append(out, fmt.Sprintf("PWR:x%06X", *af.PiecewiseRate)) 85 } 86 87 if af.SeamlessSplice.DTS != nil { 88 out = append(out, fmt.Sprintf("SeamlessSplice(%02X):x%09X", af.SeamlessSplice.Type, *af.SeamlessSplice.DTS)) 89 } 90 91 if af.Stuffing > 0 { 92 out = append(out, fmt.Sprintf("Stuffing[%d]", af.Stuffing)) 93 } 94 95 return fmt.Sprintf("{%s}", strings.Join(out, " ")) 96 } 97 98 const ( 99 flagAFDiscontinuity = 0x80 100 flagAFRandomAccess = 0x40 101 flagAFPriority = 0x20 102 flagAFPCR = 0x10 103 flagAFOPCR = 0x08 104 flagAFSplicePoint = 0x04 105 flagAFPrivateData = 0x02 106 flagAFExtension = 0x01 107 108 flagAFExtLTW = 0x80 109 flagAFExtPiecewiseRate = 0x40 110 flagAFExtSeamlessSplice = 0x20 111 112 flagAFExtLTWValid = 0x80 113 114 // AdaptationFieldMinLength is the minimum length (in bytes) that an Adaptation Field can encode into. 115 AdaptationFieldMinLength = 2 116 ) 117 118 // Len returns the actual length in bytes that the AdaptationField would encode into. 119 func (af *AdaptationField) Len() int { 120 if af == nil { 121 return 0 122 } 123 124 l := 2 125 126 if af.PCR != nil { 127 l += 6 128 } 129 130 if af.OPCR != nil { 131 l += 6 132 } 133 134 if af.SpliceCountdown != nil { 135 l++ 136 } 137 138 l += len(af.PrivateData) 139 140 if af.LegalTimeWindow.Value != nil || af.PiecewiseRate != nil || af.SeamlessSplice.DTS != nil { 141 l += 2 142 143 if af.LegalTimeWindow.Value != nil { 144 l += 2 145 } 146 147 if af.PiecewiseRate != nil { 148 l += 3 149 } 150 151 if af.SeamlessSplice.DTS != nil { 152 l += 5 153 } 154 } 155 156 return l + af.Stuffing 157 } 158 159 func (af *AdaptationField) marshal() ([]byte, error) { 160 if af == nil { 161 // If we got here, we already set that there is an AdaptationField… 162 // If so, return an empty AdaptationField, not a not-there AdaptationField. 163 return []byte{1, 0}, nil 164 } 165 166 b := make([]byte, 2) 167 168 if af.Discontinuity { 169 b[1] |= flagAFDiscontinuity 170 } 171 if af.RandomAccess { 172 b[1] |= flagAFRandomAccess 173 } 174 if af.Priority { 175 b[1] |= flagAFPriority 176 } 177 178 if af.PCR != nil { 179 b[1] |= flagAFPCR 180 181 pcr, err := af.PCR.Marshal() 182 if err != nil { 183 return nil, err 184 } 185 186 b = append(b, pcr...) 187 } 188 189 if af.OPCR != nil { 190 b[1] |= flagAFOPCR 191 192 opcr, err := af.OPCR.Marshal() 193 if err != nil { 194 return nil, err 195 } 196 197 b = append(b, opcr...) 198 } 199 200 if af.SpliceCountdown != nil { 201 b[1] |= flagAFSplicePoint 202 b = append(b, *af.SpliceCountdown) 203 } 204 205 if af.PrivateData != nil { 206 if len(af.PrivateData) > 0xFF { 207 return nil, errors.Errorf("private_data length exceeds 255: %d", len(af.PrivateData)) 208 } 209 210 b[1] |= flagAFPrivateData 211 b = append(b, byte(len(af.PrivateData)&0xFF)) 212 b = append(b, af.PrivateData...) 213 } 214 215 if af.LegalTimeWindow.Value != nil || af.PiecewiseRate != nil || af.SeamlessSplice.DTS != nil { 216 ext := make([]byte, 2) 217 218 if af.LegalTimeWindow.Value != nil { 219 ext[1] |= flagAFExtLTW 220 221 ext = append(ext, 222 byte((*af.LegalTimeWindow.Value>>8)&0x7F), 223 byte(*af.LegalTimeWindow.Value&0xFF), 224 ) 225 226 if af.LegalTimeWindow.Valid { 227 ext[2] |= flagAFExtLTWValid 228 } 229 } 230 231 if af.PiecewiseRate != nil { 232 ext[1] |= flagAFExtPiecewiseRate 233 234 ext = append(ext, 235 byte((*af.PiecewiseRate>>16)&0x3F), 236 byte((*af.PiecewiseRate>>8)&0xFF), 237 byte(*af.PiecewiseRate&0xFF), 238 ) 239 } 240 241 if af.SeamlessSplice.DTS != nil { 242 ext[1] |= flagAFExtSeamlessSplice 243 244 ext = append(ext, 245 byte((af.SeamlessSplice.Type&0x0F)<<4)|byte((*af.SeamlessSplice.DTS>>29)&0xE)|1, 246 byte((*af.SeamlessSplice.DTS>>23)&0xFF), 247 byte((*af.SeamlessSplice.DTS>>14)&0xFE)|1, 248 byte((*af.SeamlessSplice.DTS>>7)&0xFF), 249 byte((*af.SeamlessSplice.DTS<<1)&0xFE)|1, 250 ) 251 } 252 253 ext[0] = byte(len(ext) - 1) 254 255 b = append(b, ext...) 256 } 257 258 if af.Stuffing > 0 { 259 b = append(b, bytes.Repeat([]byte{0xFF}, af.Stuffing)...) 260 } 261 262 b[0] = byte(len(b) - 1) 263 return b, nil 264 } 265 266 func (af *AdaptationField) unmarshal(b []byte) (int, error) { 267 if b[0] == 0 { 268 return 1, nil 269 } 270 271 length := int(b[0]) + 1 272 273 // trim so that OOB access will panic 274 b = b[:length] 275 276 af.Discontinuity = b[1]&flagAFDiscontinuity != 0 277 af.RandomAccess = b[1]&flagAFRandomAccess != 0 278 af.Priority = b[1]&flagAFPriority != 0 279 280 start := 2 281 282 if b[1]&flagAFPCR != 0 { 283 af.PCR = new(pcr.PCR) 284 285 _ = af.PCR.Unmarshal(b[start : start+6]) 286 287 start += 6 288 } 289 290 if b[1]&flagAFOPCR != 0 { 291 af.OPCR = new(pcr.PCR) 292 293 _ = af.OPCR.Unmarshal(b[start : start+6]) 294 295 start += 6 296 } 297 298 if b[1]&flagAFSplicePoint != 0 { 299 sc := b[start] 300 af.SpliceCountdown = &sc 301 start++ 302 } 303 304 if b[1]&flagAFPrivateData != 0 { 305 l := int(b[start]) 306 start++ 307 308 af.PrivateData = append([]byte{}, b[start:start+l]...) 309 start += l 310 } 311 312 if b[1]&flagAFExtension != 0 { 313 l := int(b[start]) 314 start++ 315 316 ext := b[start : start+l] 317 start += l 318 319 if ext[0]&flagAFExtLTW != 0 { 320 b := ext[start:] 321 322 af.LegalTimeWindow.Valid = b[0]&0x80 != 0 323 324 ltw := uint16(b[0]&0x7F)<<8 | uint16(b[1]) 325 af.LegalTimeWindow.Value = <w 326 327 start += 2 328 } 329 330 if ext[0]&flagAFExtPiecewiseRate != 0 { 331 b := ext[start:] 332 333 pwr := uint32(b[0]&0x3F)<<16 | uint32(b[1])<<8 | uint32(b[2]) 334 af.PiecewiseRate = &pwr 335 336 start += 3 337 } 338 339 if ext[0]&flagAFExtSeamlessSplice != 0 { 340 b := ext[start:] 341 342 af.SeamlessSplice.Type = (b[0] >> 4) & 0x0F 343 344 ts := uint64(b[start]>>1) & 0x07 345 ts = (ts << 8) | uint64(b[1]) 346 ts = (ts << 7) | uint64((b[2]>>1)&0x7F) 347 ts = (ts << 8) | uint64(b[3]) 348 ts = (ts << 7) | uint64((b[4]>>1)&0x7F) 349 350 af.SeamlessSplice.DTS = &ts 351 352 start += 5 353 } 354 } 355 356 af.Stuffing = len(b) - start 357 358 return length, nil 359 }