Skip to content

Commit

Permalink
core: smarter capabilities check: encoding session limit, verbose err…
Browse files Browse the repository at this point in the history
…ors (#2259)
  • Loading branch information
cyberj0g authored Feb 16, 2022
1 parent 31e6309 commit a8af913
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 14 deletions.
44 changes: 44 additions & 0 deletions core/capabilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,32 @@ const (
Capability_VP9_Encode
)

var CapabilityNameLookup = map[Capability]string {
Capability_Invalid: "Invalid",
Capability_Unused: "Unused",
Capability_H264: "H.264",
Capability_MPEGTS: "MPEGTS",
Capability_MP4: "MP4",
Capability_FractionalFramerates: "Fractional framerates",
Capability_StorageDirect: "Storage direct",
Capability_StorageS3: "Storage S3",
Capability_StorageGCS: "Storage GCS",
Capability_ProfileH264Baseline: "H264 Baseline profile",
Capability_ProfileH264Main: "H264 Main profile",
Capability_ProfileH264High: "H264 High profile",
Capability_ProfileH264ConstrainedHigh: "H264 Constained High profile",
Capability_GOP: "GOP",
Capability_AuthToken: "Auth token",
Capability_SceneClassification: "Scene slassification",
Capability_MPEG7VideoSignature: "MPEG7 signature",
Capability_HEVC_Decode: "HEVC decode",
Capability_HEVC_Encode: "HEVC encode",
Capability_VP8_Decode: "VP8 decode",
Capability_VP9_Decode: "VP9 decode",
Capability_VP8_Encode: "VP8 encode",
Capability_VP9_Encode: "VP9 encode",
}


var CapabilityTestLookup = map[Capability]CapabilityTest{
// 145x145 is the lowest resolution supported by NVENC on Windows
Expand Down Expand Up @@ -77,6 +103,7 @@ var capFormatConv = errors.New("capability: unknown format")
var capStorageConv = errors.New("capability: unknown storage")
var capProfileConv = errors.New("capability: unknown profile")
var capCodecConv = errors.New("capability: unknown codec")
var capUnknown = errors.New("capability: unknown")

func DefaultCapabilities() []Capability {
// Add to this list as new features are added.
Expand Down Expand Up @@ -279,6 +306,23 @@ func NewCapabilities(caps []Capability, m []Capability) *Capabilities {
return c
}

func CapabilityToName(capability Capability) (string, error) {
capName, found := CapabilityNameLookup[capability]
if !found {
return "", capUnknown
}
return capName, nil
}

func InArray(capability Capability, caps []Capability) bool {
for _, c := range caps {
if capability == c {
return true
}
}
return false
}

func inputCodecToCapability(codec ffmpeg.VideoCodec) (Capability, error) {
switch codec {
case ffmpeg.H264:
Expand Down
42 changes: 28 additions & 14 deletions core/transcoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,18 @@ func (nv *NvidiaTranscoder) Transcode(ctx context.Context, md *SegTranscodingMet
func TestTranscoderCapabilities(devices []string) (caps []Capability, fatalError error) {
// default capabilities
allCaps := append(DefaultCapabilities(), OptionalCapabilities()...)
fname := filepath.Join(WorkDir, "testseg.tempfile")
defer os.Remove(fname)
nvTest3Rend := true
// iterate all capabilities and test ones which has test data
for _, c := range allCaps {
capTest, hasTest := CapabilityTestLookup[c]
capName, _ := CapabilityToName(c)
isRequired := InArray(c, DefaultCapabilities())
capKindStr := "Optional capability"
if isRequired {
capKindStr = "Required capability"
}
if hasTest {
b := bytes.NewReader(capTest.inVideoData)
z, err := gzip.NewReader(b)
Expand All @@ -134,13 +143,11 @@ func TestTranscoderCapabilities(devices []string) (caps []Capability, fatalError
glog.Errorf("Error reading test segment for capability %d: %s", c, err)
continue
}
fname := filepath.Join(WorkDir, "testseg.tempfile")
err = ioutil.WriteFile(fname, mp4testSeg, 0644)
if err != nil {
glog.Errorf("Error writing test segment for capability %d: %s", c, err)
continue
}
defer os.Remove(fname)
// check that capability is supported on all devices
for _, device := range devices {
t1 := NewNvidiaTranscoder(device)
Expand All @@ -149,29 +156,36 @@ func TestTranscoderCapabilities(devices []string) (caps []Capability, fatalError
td, err := t1.Transcode(context.Background(), md)
t1.Stop()
if err != nil {
// likely means capability is not supported
glog.Infof("%s %q is not supported on device %s, see other error messages for details", capKindStr, capName, device)
// likely means capability is not supported, don't check on other devices
goto test_fail
}
if len(td.Segments) == 0 || td.Pixels == 0 {
// abnormal behavior
glog.Errorf("Empty result segment when testing for capability %d", c)
glog.Errorf("Empty result segment when testing for %s %q", strings.ToLower(capKindStr), capName)
goto test_fail
}
// no error creating 4 renditions - disable 3 renditions test, as restriction is on driver level, not device
nvTest3Rend = false
}
}
caps = append(caps, c)
test_fail:
}
for _, defCap := range DefaultCapabilities() {
found := false
for _, supportedCap := range caps {
if defCap == supportedCap {
found = true
break
continue
test_fail:
if nvTest3Rend {
// if 4 renditions didn't succeed, try 3 renditions on first device to check if it could be session limit
t1 := NewNvidiaTranscoder(devices[0])
md := &SegTranscodingMetadata{Fname: fname, Profiles: []ffmpeg.VideoProfile{capTest.outProfile, capTest.outProfile, capTest.outProfile}}
td, err := t1.Transcode(context.Background(), md)
t1.Stop()
if err == nil && len(td.Segments) > 0 && td.Pixels > 0 {
glog.Error("Maximum number of simultaneous NVENC video encoding sessions is restricted by driver")
}
// do it only once
nvTest3Rend = false
}
if !found {
return caps, fmt.Errorf("Default capability %d is not supported", defCap)
if isRequired {
return nil, fmt.Errorf("%s %q is not supported on hardware", capKindStr, capName)
}
}
return caps, nil
Expand Down

0 comments on commit a8af913

Please sign in to comment.