Commit Diff


commit - 62d865db8655e6d23b4fccc3280d73c3cdda8ce9
commit + 440f52398d25a5cddd80cefad5ba8631b5e7eaf7
blob - 5512a4cdb4a92941f104cc8e6744c9c2c656ce26
blob + 31da370b55aec9f363a841a38a0c7289fc9f4231
--- scte35/splice.go
+++ scte35/splice.go
@@ -116,6 +116,7 @@ func Encode(splice *Splice) ([]byte, error) {
 	tier := splice.Tier & 0x0fff // just 12 bits
 	// right 4 bits are for command length
 	buf = binary.BigEndian.AppendUint16(buf, tier<<4)
+
 	if splice.Command == nil {
 		return nil, fmt.Errorf("nil command")
 	}
blob - 6a360bdd85a88ac4a54558990481a227ade66c3c
blob + 3626238f69586624ccd14ada2146e32302314a8d
--- scte35/splice_descriptor.go
+++ scte35/splice_descriptor.go
@@ -296,11 +296,24 @@ type AudioChannel struct {
 	Language [3]byte
 	// A 3-bit integer from ATSC A/52 Table 5.7.
 	BitstreamMode uint8
-	// Number of channels as a 4-bit integer, from ATSC A/52 Table A4.5.
-	Count       uint8
+	// Number of channels as a 4 bit field, from ATSC A/52 Table A4.5.
+	Count       NumChannels
 	FullService bool
 }
 
+type NumChannels uint8
+
+const (
+	OneChan NumChannels = 0b10000000 + (iota << 4)
+	TwoChan
+	ThreeChan
+	FourChan
+	FiveChan
+	SixChan
+	_ // Reserved
+	_ // Reserved
+)
+
 type AudioDescriptor []AudioChannel
 
 func (d AudioDescriptor) Tag() uint8 { return TagAudio }
@@ -314,10 +327,10 @@ func (d AudioDescriptor) Data() []byte {
 		b = append(b, ch.ComponentTag)
 		b = append(b, ch.Language[:]...)
 		var c byte
-		c |= (ch.BitstreamMode << 5) // set left 3 bits
-		c |= (ch.Count & 0x0f)       // only want 4 bits
+		c |= (ch.BitstreamMode << 5) // set bits 0-2
+		c |= byte(ch.Count) >> 3     // set bits 3-7
 		if ch.FullService {
-			c |= 0x01 // set last remaining bit
+			c |= 0x01 // set last bit
 		}
 		b = append(b, c)
 	}
blob - d875627cb08f6e0a7684ba84231564bfee9566f3
blob + c839ea9ff3a0b7ec1e16590c23631809266594d3
--- scte35/splice_test.go
+++ scte35/splice_test.go
@@ -165,3 +165,34 @@ func TestEncode(t *testing.T) {
 		})
 	}
 }
+
+const bitstreamModeKaraoke uint8 = 0b00000111
+
+func TestAudioDescriptor(t *testing.T) {
+	desc := []AudioChannel{
+		{
+			ComponentTag:  0xff,                   // should be 0xff if unused.
+			Language:      [3]byte{'e', 'n', 'g'}, // English
+			BitstreamMode: bitstreamModeKaraoke,
+			Count:         SixChan,
+			FullService:   true,
+		},
+	}
+
+	want := [6]byte{
+		0b00010000,    // we have a single channel (above), shifted left 4. reserved bits untoggled.
+		0xff,          // ComponentTag
+		'e', 'n', 'g', // Language
+		// bit layout is
+		//	mode mode mode, count count count count, fullservice
+		0b11111011, // Mode = karaoke, Count = SixChan, FullService = true
+	}
+
+	var got [6]byte
+	marshalled := AudioDescriptor(desc).Data()
+	copy(got[:], marshalled)
+	if got != want {
+		t.Logf("final byte = %#08b, want %#08b", got[5], want[5])
+		t.Fatalf("Data() = %#08bb, want %#08b", got, want)
+	}
+}