mirror of
https://github.com/pion/mediadevices.git
synced 2026-04-22 15:57:27 +08:00
Add meta reader helper
Since broadcaster has a ring buffer, we can take advantage of this property to read the meta data for video/audio without losing any data.
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
package mediadevices
|
||||
|
||||
import (
|
||||
"github.com/pion/mediadevices/pkg/io/audio"
|
||||
"github.com/pion/mediadevices/pkg/io/video"
|
||||
"github.com/pion/mediadevices/pkg/prop"
|
||||
)
|
||||
|
||||
// detectCurrentVideoProp is a small helper to get current video property
|
||||
func detectCurrentVideoProp(broadcaster *video.Broadcaster) (prop.Media, error) {
|
||||
var currentProp prop.Media
|
||||
|
||||
// Since broadcaster has a ring buffer internally, a new reader will either read the last
|
||||
// buffered frame or a new frame from the source. This also implies that no frame will be lost
|
||||
// in any case.
|
||||
metaReader := broadcaster.NewReader(false)
|
||||
metaReader = video.DetectChanges(0, func(p prop.Media) { currentProp = p })(metaReader)
|
||||
_, err := metaReader.Read()
|
||||
|
||||
return currentProp, err
|
||||
}
|
||||
|
||||
// detectCurrentAudioProp is a small helper to get current audio property
|
||||
func detectCurrentAudioProp(broadcaster *audio.Broadcaster) (prop.Media, error) {
|
||||
var currentProp prop.Media
|
||||
|
||||
// Since broadcaster has a ring buffer internally, a new reader will either read the last
|
||||
// buffered frame or a new frame from the source. This also implies that no frame will be lost
|
||||
// in any case.
|
||||
metaReader := broadcaster.NewReader(false)
|
||||
metaReader = audio.DetectChanges(0, func(p prop.Media) { currentProp = p })(metaReader)
|
||||
_, err := metaReader.Read()
|
||||
|
||||
return currentProp, err
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package mediadevices
|
||||
|
||||
import (
|
||||
"image"
|
||||
"testing"
|
||||
|
||||
"github.com/pion/mediadevices/pkg/io/audio"
|
||||
"github.com/pion/mediadevices/pkg/io/video"
|
||||
"github.com/pion/mediadevices/pkg/wave"
|
||||
)
|
||||
|
||||
func TestDetectCurrentVideoProp(t *testing.T) {
|
||||
resolution := image.Rect(0, 0, 4, 4)
|
||||
first := image.NewRGBA(resolution)
|
||||
first.Pix[0] = 1
|
||||
second := image.NewRGBA(resolution)
|
||||
second.Pix[0] = 2
|
||||
|
||||
isFirst := true
|
||||
source := video.ReaderFunc(func() (image.Image, error) {
|
||||
if isFirst {
|
||||
isFirst = true
|
||||
return first, nil
|
||||
} else {
|
||||
return second, nil
|
||||
}
|
||||
})
|
||||
|
||||
broadcaster := video.NewBroadcaster(source, nil)
|
||||
|
||||
currentProp, err := detectCurrentVideoProp(broadcaster)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if currentProp.Width != resolution.Dx() {
|
||||
t.Fatalf("Expect the actual width to be %d, but got %d", currentProp.Width, resolution.Dx())
|
||||
}
|
||||
|
||||
if currentProp.Height != resolution.Dy() {
|
||||
t.Fatalf("Expect the actual height to be %d, but got %d", currentProp.Height, resolution.Dy())
|
||||
}
|
||||
|
||||
reader := broadcaster.NewReader(false)
|
||||
img, err := reader.Read()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rgba := img.(*image.RGBA)
|
||||
if rgba.Pix[0] != 1 {
|
||||
t.Fatal("Expect the frame after reading the current prop is not the first frame")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetectCurrentAudioProp(t *testing.T) {
|
||||
info := wave.ChunkInfo{
|
||||
Len: 4,
|
||||
Channels: 2,
|
||||
SamplingRate: 48000,
|
||||
}
|
||||
first := wave.NewInt16Interleaved(info)
|
||||
first.Data[0] = 1
|
||||
second := wave.NewInt16Interleaved(info)
|
||||
second.Data[0] = 2
|
||||
|
||||
isFirst := true
|
||||
source := audio.ReaderFunc(func() (wave.Audio, error) {
|
||||
if isFirst {
|
||||
isFirst = true
|
||||
return first, nil
|
||||
} else {
|
||||
return second, nil
|
||||
}
|
||||
})
|
||||
|
||||
broadcaster := audio.NewBroadcaster(source, nil)
|
||||
|
||||
currentProp, err := detectCurrentAudioProp(broadcaster)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if currentProp.ChannelCount != info.Channels {
|
||||
t.Fatalf("Expect the actual channel count to be %d, but got %d", currentProp.ChannelCount, info.Channels)
|
||||
}
|
||||
|
||||
reader := broadcaster.NewReader(false)
|
||||
chunk, err := reader.Read()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
realChunk := chunk.(*wave.Int16Interleaved)
|
||||
if realChunk.Data[0] != 1 {
|
||||
t.Fatal("Expect the chunk after reading the current prop is not the first chunk")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user