blob: 0dbde99e3a277510ca26506f053acc642be8ef28 [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package webrtc
import (
"context"
"time"
"golang.org/x/sync/errgroup"
"chromiumos/tast/common/media/caps"
"chromiumos/tast/local/bundles/cros/webrtc/mediarecorder"
"chromiumos/tast/local/chrome"
"chromiumos/tast/local/chrome/metrics"
"chromiumos/tast/local/media/constants"
"chromiumos/tast/local/media/videotype"
"chromiumos/tast/testing"
)
func init() {
testing.AddTest(&testing.Test{
Func: MediaRecorderMulti,
Desc: "Verifies that MediaRecorder can use multiple encoders in parallel",
Contacts: []string{
"mcasas@chromium.org",
"chromeos-gfx-video@google.com",
},
SoftwareDeps: []string{"chrome"},
Data: []string{"loopback_media_recorder.html"},
Attr: []string{"group:graphics", "graphics_video", "graphics_perbuild"},
Params: []testing.Param{{
Name: "vp8_vp8",
Val: []videotype.Codec{videotype.VP8, videotype.VP8},
ExtraSoftwareDeps: []string{caps.HWEncodeVP8},
Fixture: "chromeVideoWithFakeWebcam",
}, {
Name: "vp8_h264",
Val: []videotype.Codec{videotype.H264, videotype.VP8},
ExtraSoftwareDeps: []string{caps.HWEncodeH264, caps.HWEncodeVP8, "proprietary_codecs"},
Fixture: "chromeVideoWithFakeWebcam",
}, {
Name: "h264_h264",
Val: []videotype.Codec{videotype.H264, videotype.H264},
ExtraSoftwareDeps: []string{caps.HWEncodeH264, "proprietary_codecs"},
Fixture: "chromeVideoWithFakeWebcam",
}},
})
}
// MediaRecorderMulti verifies that multiple video encoders can be used
// in parallel.
func MediaRecorderMulti(ctx context.Context, s *testing.State) {
const (
// Record for several seconds to ensure the encodings are overlapping.
// Also, any interaction between the two encoders may take several
// seconds to occur.
recordDuration = 10 * time.Second
)
cr := s.FixtValue().(*chrome.Chrome)
codecs := s.Param().([]videotype.Codec)
tconn, err := cr.TestAPIConn(ctx)
if err != nil {
s.Fatal("Failed to connect to test API: ", err)
}
initHistogram, err := metrics.GetHistogram(ctx, tconn, constants.MediaRecorderVEAUsed)
if err != nil {
s.Fatal("Failed to get initial histogram: ", err)
}
g, encCtx := errgroup.WithContext(ctx)
for _, codec := range codecs {
// https://golang.org/doc/faq#closures_and_goroutines
c := codec
g.Go(func() error {
s.Log("Running codec ", c)
return mediarecorder.VerifyMediaRecorderUsesEncodeAccelerator(
encCtx, cr, s.DataFileSystem(), c, recordDuration)
})
}
if err := g.Wait(); err != nil {
s.Error("Failed to run VerifyMediaRecorderUsesEncodeAccelerator: ", err)
}
// Ensure that at least len(codecs) HW encoders have been used.
// This condition is "at least" because success count has been observed to be
// higher than expected (crbug.com/985068).
histogramDiff, err := metrics.WaitForHistogramUpdate(ctx, tconn, constants.MediaRecorderVEAUsed, initHistogram, time.Second)
if err != nil {
s.Fatal("Failed to wait for histogram update: ", err)
}
if len(histogramDiff.Buckets) > 1 {
s.Error("Unexpected histogram update: ", histogramDiff)
} else if len(histogramDiff.Buckets) == 0 {
s.Fatal("No histogram update observed")
}
diff := histogramDiff.Buckets[0]
if diff.Max != constants.MediaRecorderVEAUsedSuccess+1 {
s.Error("Unexpected bucket range: ", diff)
} else if diff.Count < int64(len(codecs)) {
s.Errorf("Insufficient histogram updates, got: %d, want: %d",
diff.Count, len(codecs))
}
}