Skip to content

Commit 67f6be3

Browse files
committed
Support CELT and hybrid API-rate output
1 parent 81a9c5d commit 67f6be3

14 files changed

Lines changed: 913 additions & 278 deletions

.github/scripts/run-rfc6716-conformance.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ main() {
280280
export OPUS_CONFORMANCE_MARKDOWN="${matrix_file}"
281281

282282
set +e
283-
go test -v -tags conformance -run TestRFC6716Conformance . 2>&1 | tee "${log_file}"
283+
go test -v -timeout 60m -tags conformance -run TestRFC6716Conformance . 2>&1 | tee "${log_file}"
284284
local test_status="${PIPESTATUS[0]}"
285285
set -e
286286

conformance_test.go

Lines changed: 142 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ import (
1515
"runtime"
1616
"strconv"
1717
"strings"
18+
"sync"
1819
"testing"
1920
)
2021

2122
type conformanceKey struct {
22-
vectorSet string
23-
rate int
24-
channels int
25-
vector string
23+
rate int
24+
channels int
25+
vector string
2626
}
2727

2828
type conformanceResult struct {
@@ -48,58 +48,56 @@ func TestRFC6716Conformance(t *testing.T) {
4848
"01", "02", "03", "04", "05", "06",
4949
"07", "08", "09", "10", "11", "12",
5050
}
51-
vectorSets := []string{"rfc6716", "rfc8251"}
5251

5352
refDir, vectorRoot := conformanceDataPaths(t)
5453

5554
opusCompare := buildRFC6716ReferenceTools(t, refDir)
5655
results := make(map[conformanceKey]conformanceResult)
56+
var resultsMu sync.Mutex
57+
58+
t.Run("vectors", func(t *testing.T) {
59+
for _, rate := range rates {
60+
for _, channels := range channelCounts {
61+
for _, vector := range vectors {
62+
key := conformanceKey{
63+
rate: rate,
64+
channels: channels,
65+
vector: vector,
66+
}
67+
t.Run(
68+
fmt.Sprintf("rate_%d/channels_%d/testvector%s", rate, channels, vector),
69+
func(t *testing.T) {
70+
t.Parallel()
5771

58-
for _, vectorSet := range vectorSets {
59-
vectorDir := filepath.Join(vectorRoot, vectorSet)
60-
t.Run(vectorSet, func(t *testing.T) {
61-
for _, rate := range rates {
62-
for _, channels := range channelCounts {
63-
t.Run(fmt.Sprintf("rate_%d/channels_%d", rate, channels), func(t *testing.T) {
64-
for _, vector := range vectors {
65-
key := conformanceKey{
66-
vectorSet: vectorSet,
67-
rate: rate,
68-
channels: channels,
69-
vector: vector,
70-
}
71-
ran := false
7272
quality := ""
73-
passed := t.Run("testvector"+vector, func(t *testing.T) {
74-
ran = true
75-
bitstream := filepath.Join(vectorDir, "testvector"+vector+".bit")
76-
referencePCM := filepath.Join(vectorDir, "testvector"+vector+".dec")
77-
alternateReferencePCM := filepath.Join(vectorDir, "testvector"+vector+"m.dec")
78-
goPCM := filepath.Join(t.TempDir(), "go.pcm")
79-
80-
decodeRFC6716Vector(t, rate, channels, bitstream, goPCM)
81-
quality = compareRFC6716Output(
82-
t,
83-
opusCompare,
84-
rate,
85-
channels,
86-
referencePCM,
87-
alternateReferencePCM,
88-
goPCM,
89-
)
90-
})
91-
if ran {
92-
results[key] = conformanceResult{passed: passed, quality: quality}
93-
}
94-
}
95-
})
73+
defer func() {
74+
resultsMu.Lock()
75+
results[key] = conformanceResult{passed: !t.Failed(), quality: quality}
76+
resultsMu.Unlock()
77+
}()
78+
79+
bitstream := conformanceBitstreamPath(t, vectorRoot, vector)
80+
referencePCMs := conformanceReferencePCMs(vectorRoot, vector)
81+
goPCM := filepath.Join(t.TempDir(), "go.pcm")
82+
83+
decodeRFC6716Vector(t, rate, channels, bitstream, goPCM)
84+
quality = compareRFC6716Output(
85+
t,
86+
opusCompare,
87+
rate,
88+
channels,
89+
referencePCMs,
90+
goPCM,
91+
)
92+
},
93+
)
9694
}
9795
}
98-
})
99-
}
96+
}
97+
})
10098

101-
printConformanceMatrix(results, vectorSets, rates, channelCounts, vectors)
102-
writeConformanceMarkdown(t, os.Getenv(envConformanceMarkdown), results, vectorSets, rates, channelCounts, vectors)
99+
printConformanceMatrix(results, rates, channelCounts, vectors)
100+
writeConformanceMarkdown(t, os.Getenv(envConformanceMarkdown), results, rates, channelCounts, vectors)
103101
}
104102

105103
func conformanceDataPaths(t *testing.T) (refDir, vectorRoot string) {
@@ -118,42 +116,62 @@ func compareRFC6716Output(
118116
t *testing.T,
119117
opusCompare string,
120118
rate, channels int,
121-
referencePCM, alternateReferencePCM, goPCM string,
119+
referencePCMs []string,
120+
goPCM string,
122121
) string {
123122
t.Helper()
124123

125-
out, err := runOpusCompare(opusCompare, rate, channels, referencePCM, goPCM)
126-
if err == nil {
127-
quality := opusCompareQuality(out)
128-
printOpusCompareQuality(t, quality)
124+
checkedReference := false
125+
var failures []string
126+
for _, referencePCM := range referencePCMs {
127+
if _, err := os.Stat(referencePCM); err != nil {
128+
continue
129+
}
130+
checkedReference = true
131+
out, err := runOpusCompare(opusCompare, rate, channels, referencePCM, goPCM)
132+
if err == nil {
133+
quality := opusCompareQuality(out)
134+
printOpusCompareQuality(t, quality)
129135

130-
return quality
136+
return quality
137+
}
138+
failures = append(failures, fmt.Sprintf("%s: %v\n%s", referencePCM, err, out))
139+
}
140+
if !checkedReference {
141+
t.Fatalf("no reference PCM found among %v", referencePCMs)
131142
}
132-
primaryErr := err
133-
primaryOut := out
134143

135-
if _, err := os.Stat(alternateReferencePCM); err != nil {
136-
t.Fatalf("opus_compare failed: %v\n%s", primaryErr, primaryOut)
144+
t.Fatalf("opus_compare failed for all references:\n%s", strings.Join(failures, "\n"))
137145

138-
return ""
139-
}
146+
return ""
147+
}
140148

141-
out, err = runOpusCompare(opusCompare, rate, channels, alternateReferencePCM, goPCM)
142-
if err != nil {
143-
t.Fatalf(
144-
"opus_compare failed for both references: primary=%v alternate=%v\nprimary:\n%s\nalternate:\n%s",
145-
primaryErr,
146-
err,
147-
primaryOut,
148-
out,
149-
)
149+
func conformanceBitstreamPath(t *testing.T, vectorRoot, vector string) string {
150+
t.Helper()
150151

151-
return ""
152+
// RFC 8251 Section 11 keeps the decoder input bitstreams unchanged, so the
153+
// newer archive is the preferred source and the RFC 6716 archive is an
154+
// equivalent fallback when only the legacy bundle is available.
155+
for _, vectorSet := range []string{"rfc8251", "rfc6716"} {
156+
path := filepath.Join(vectorRoot, vectorSet, "testvector"+vector+".bit")
157+
if _, err := os.Stat(path); err == nil {
158+
return path
159+
}
152160
}
153-
quality := opusCompareQuality(out)
154-
printOpusCompareQuality(t, quality)
155161

156-
return quality
162+
t.Fatalf("missing testvector%s.bit in RFC 8251 or RFC 6716 vectors", vector)
163+
164+
return ""
165+
}
166+
167+
func conformanceReferencePCMs(vectorRoot, vector string) []string {
168+
// RFC 8251 Section 11 permits either the original RFC 6716 output set or
169+
// one of the updated output sets for the same unchanged input bitstreams.
170+
return []string{
171+
filepath.Join(vectorRoot, "rfc8251", "testvector"+vector+".dec"),
172+
filepath.Join(vectorRoot, "rfc8251", "testvector"+vector+"m.dec"),
173+
filepath.Join(vectorRoot, "rfc6716", "testvector"+vector+".dec"),
174+
}
157175
}
158176

159177
func buildRFC6716ReferenceTools(t *testing.T, refDir string) (opusCompare string) {
@@ -309,7 +327,6 @@ func printOpusCompareQuality(t *testing.T, quality string) {
309327

310328
func printConformanceMatrix(
311329
results map[conformanceKey]conformanceResult,
312-
vectorSets []string,
313330
rates []int,
314331
channelCounts []int,
315332
vectors []string,
@@ -318,36 +335,33 @@ func printConformanceMatrix(
318335
return
319336
}
320337

321-
fmt.Println("RFC 6716 / 8251 conformation matrix")
338+
fmt.Println("Opus conformance matrix")
322339
fmt.Println("Legend: numeric cells are opus_compare quality percentages; FAIL means the vector did not pass.")
340+
fmt.Println("Inputs use the shared RFC 6716 / RFC 8251 bitstream corpus; accepted references follow RFC 8251 Section 11.")
323341

324-
for _, vectorSet := range vectorSets {
325-
fmt.Printf("\nvector set: %s\n", vectorSet)
326-
printConformanceMatrixRule(vectors)
327-
fmt.Printf("| %-8s | %-2s |", "rate", "ch")
328-
for _, vector := range vectors {
329-
fmt.Printf(" %-*s |", conformanceMatrixVectorCellWidth, vector)
330-
}
331-
fmt.Println()
332-
printConformanceMatrixRule(vectors)
333-
334-
for _, rate := range rates {
335-
for _, channels := range channelCounts {
336-
fmt.Printf("| %-8d | %-2d |", rate, channels)
337-
for _, vector := range vectors {
338-
key := conformanceKey{
339-
vectorSet: vectorSet,
340-
rate: rate,
341-
channels: channels,
342-
vector: vector,
343-
}
344-
fmt.Printf(" %-*s |", conformanceMatrixVectorCellWidth, conformanceMatrixCell(results, key))
342+
printConformanceMatrixRule(vectors)
343+
fmt.Printf("| %-8s | %-2s |", "rate", "ch")
344+
for _, vector := range vectors {
345+
fmt.Printf(" %-*s |", conformanceMatrixVectorCellWidth, vector)
346+
}
347+
fmt.Println()
348+
printConformanceMatrixRule(vectors)
349+
350+
for _, rate := range rates {
351+
for _, channels := range channelCounts {
352+
fmt.Printf("| %-8d | %-2d |", rate, channels)
353+
for _, vector := range vectors {
354+
key := conformanceKey{
355+
rate: rate,
356+
channels: channels,
357+
vector: vector,
345358
}
346-
fmt.Println()
359+
fmt.Printf(" %-*s |", conformanceMatrixVectorCellWidth, conformanceMatrixCell(results, key))
347360
}
361+
fmt.Println()
348362
}
349-
printConformanceMatrixRule(vectors)
350363
}
364+
printConformanceMatrixRule(vectors)
351365
}
352366

353367
const conformanceMatrixVectorCellWidth = 5
@@ -364,7 +378,6 @@ func writeConformanceMarkdown(
364378
t *testing.T,
365379
path string,
366380
results map[conformanceKey]conformanceResult,
367-
vectorSets []string,
368381
rates []int,
369382
channelCounts []int,
370383
vectors []string,
@@ -377,35 +390,32 @@ func writeConformanceMarkdown(
377390

378391
var b strings.Builder
379392
b.WriteString("Legend: numeric cells are `opus_compare` quality percentages; `FAIL` means the vector did not pass.\n\n")
380-
for _, vectorSet := range vectorSets {
381-
fmt.Fprintf(&b, "### %s\n\n", vectorSet)
382-
b.WriteString("| rate | ch |")
383-
for _, vector := range vectors {
384-
fmt.Fprintf(&b, " %s |", vector)
385-
}
386-
b.WriteString("\n| --- | --- |")
387-
for range vectors {
388-
b.WriteString(" --- |")
389-
}
390-
b.WriteString("\n")
391-
392-
for _, rate := range rates {
393-
for _, channels := range channelCounts {
394-
fmt.Fprintf(&b, "| %d | %d |", rate, channels)
395-
for _, vector := range vectors {
396-
key := conformanceKey{
397-
vectorSet: vectorSet,
398-
rate: rate,
399-
channels: channels,
400-
vector: vector,
401-
}
402-
fmt.Fprintf(&b, " %s |", conformanceMatrixCell(results, key))
393+
b.WriteString("Inputs use the shared RFC 6716 / RFC 8251 bitstream corpus; accepted references follow RFC 8251 Section 11.\n\n")
394+
b.WriteString("| rate | ch |")
395+
for _, vector := range vectors {
396+
fmt.Fprintf(&b, " %s |", vector)
397+
}
398+
b.WriteString("\n| --- | --- |")
399+
for range vectors {
400+
b.WriteString(" --- |")
401+
}
402+
b.WriteString("\n")
403+
404+
for _, rate := range rates {
405+
for _, channels := range channelCounts {
406+
fmt.Fprintf(&b, "| %d | %d |", rate, channels)
407+
for _, vector := range vectors {
408+
key := conformanceKey{
409+
rate: rate,
410+
channels: channels,
411+
vector: vector,
403412
}
404-
b.WriteString("\n")
413+
fmt.Fprintf(&b, " %s |", conformanceMatrixCell(results, key))
405414
}
415+
b.WriteString("\n")
406416
}
407-
b.WriteString("\n")
408417
}
418+
b.WriteString("\n")
409419

410420
if err := os.WriteFile(path, []byte(b.String()), 0o600); err != nil {
411421
t.Fatalf("write conformance markdown: %v", err)
@@ -428,7 +438,16 @@ func conformanceMatrixCell(results map[conformanceKey]conformanceResult, key con
428438
}
429439

430440
func conformanceFinalRange(d *Decoder) (uint32, error) {
431-
return d.silkDecoder.FinalRange(), nil
441+
switch d.previousMode {
442+
case configurationModeCELTOnly:
443+
return d.celtDecoder.FinalRange(), nil
444+
case configurationModeSilkOnly:
445+
return d.rangeFinal, nil
446+
case configurationModeHybrid:
447+
return d.rangeFinal, nil
448+
default:
449+
return 0, fmt.Errorf("unsupported final range mode: %s", d.previousMode)
450+
}
432451
}
433452

434453
func conformancePacketSamplesPerChannel(packet []byte, rate int) (int, error) {

0 commit comments

Comments
 (0)