mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-12-24 13:48:04 +08:00
118 lines
2.6 KiB
Go
118 lines
2.6 KiB
Go
package box
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
"io"
|
|
)
|
|
|
|
// UUIDs for different DRM systems
|
|
const (
|
|
UUIDPlayReady = "9a04f07998404286ab92e65be0885f95"
|
|
UUIDWidevine = "edef8ba979d64acea3c827dcd51d21ed"
|
|
UUIDFairPlay = "94CE86FB07FF4F43ADB893D2FA968CA2"
|
|
)
|
|
|
|
// PsshBox - Protection System Specific Header Box
|
|
// Defined in ISO/IEC 23001-7 Section 8.1
|
|
type PsshBox struct {
|
|
FullBox
|
|
SystemID [16]byte
|
|
KIDs [][16]byte
|
|
Data []byte
|
|
}
|
|
|
|
func CreatePsshBox(systemID [16]byte, kids [][16]byte, data []byte) *PsshBox {
|
|
version := uint8(0)
|
|
size := uint32(FullBoxLen + 16 + 4 + len(data))
|
|
if len(kids) > 0 {
|
|
version = 1
|
|
size += 4 + uint32(len(kids)*16)
|
|
}
|
|
return &PsshBox{
|
|
FullBox: FullBox{
|
|
BaseBox: BaseBox{
|
|
typ: TypePSSH,
|
|
size: size,
|
|
},
|
|
Version: version,
|
|
Flags: [3]byte{0, 0, 0},
|
|
},
|
|
SystemID: systemID,
|
|
KIDs: kids,
|
|
Data: data,
|
|
}
|
|
}
|
|
|
|
func (box *PsshBox) WriteTo(w io.Writer) (n int64, err error) {
|
|
var tmp [4]byte
|
|
buffers := make([][]byte, 0, 3+len(box.KIDs))
|
|
buffers = append(buffers, box.SystemID[:])
|
|
|
|
if box.Version > 0 {
|
|
binary.BigEndian.PutUint32(tmp[:], uint32(len(box.KIDs)))
|
|
buffers = append(buffers, tmp[:])
|
|
for _, kid := range box.KIDs {
|
|
buffers = append(buffers, kid[:])
|
|
}
|
|
}
|
|
|
|
binary.BigEndian.PutUint32(tmp[:], uint32(len(box.Data)))
|
|
buffers = append(buffers, tmp[:], box.Data)
|
|
|
|
nn, err := io.Copy(w, io.MultiReader(bytes.NewReader(box.SystemID[:]), bytes.NewReader(tmp[:]), bytes.NewReader(box.Data)))
|
|
return int64(nn), err
|
|
}
|
|
|
|
func (box *PsshBox) Unmarshal(buf []byte) (IBox, error) {
|
|
if len(buf) < 20 {
|
|
return nil, io.ErrShortBuffer
|
|
}
|
|
n := 0
|
|
copy(box.SystemID[:], buf[n:n+16])
|
|
n += 16
|
|
if box.Version > 0 {
|
|
if len(buf) < n+4 {
|
|
return nil, io.ErrShortBuffer
|
|
}
|
|
kidCount := binary.BigEndian.Uint32(buf[n:])
|
|
n += 4
|
|
if len(buf) < n+int(kidCount)*16 {
|
|
return nil, io.ErrShortBuffer
|
|
}
|
|
for i := uint32(0); i < kidCount; i++ {
|
|
var kid [16]byte
|
|
copy(kid[:], buf[n:n+16])
|
|
n += 16
|
|
box.KIDs = append(box.KIDs, kid)
|
|
}
|
|
}
|
|
if len(buf) < n+4 {
|
|
return nil, io.ErrShortBuffer
|
|
}
|
|
dataLen := binary.BigEndian.Uint32(buf[n:])
|
|
n += 4
|
|
if len(buf) < n+int(dataLen) {
|
|
return nil, io.ErrShortBuffer
|
|
}
|
|
box.Data = buf[n : n+int(dataLen)]
|
|
return box, nil
|
|
}
|
|
|
|
func (box *PsshBox) IsWidevine() bool {
|
|
return hex.EncodeToString(box.SystemID[:]) == UUIDWidevine
|
|
}
|
|
|
|
func (box *PsshBox) IsPlayReady() bool {
|
|
return hex.EncodeToString(box.SystemID[:]) == UUIDPlayReady
|
|
}
|
|
|
|
func (box *PsshBox) IsFairPlay() bool {
|
|
return hex.EncodeToString(box.SystemID[:]) == UUIDFairPlay
|
|
}
|
|
|
|
func init() {
|
|
RegisterBox[*PsshBox](TypePSSH)
|
|
}
|