feat: add change subscribe

This commit is contained in:
langhuihui
2024-06-13 17:15:30 +08:00
parent 68a7edf678
commit 00b39aee3e
26 changed files with 890 additions and 406 deletions

34
api.go
View File

@@ -41,7 +41,7 @@ func (s *Server) SysInfo(context.Context, *emptypb.Empty) (res *pb.SysInfoRespon
Arch: runtime.GOARCH,
Cpus: int32(runtime.NumCPU()),
}
for _, p := range s.Plugins.Items {
for p := range s.Plugins.Range {
res.Plugins = append(res.Plugins, &pb.PluginInfo{
Name: p.Meta.Name,
Version: p.Meta.Version,
@@ -101,7 +101,7 @@ func (s *Server) getStreamInfo(pub *Publisher) (res *pb.StreamInfoResponse, err
Path: pub.StreamPath,
State: int32(pub.State),
StartTime: timestamppb.New(pub.StartTime),
Subscribers: int32(len(pub.Subscribers)),
Subscribers: int32(pub.Subscribers.Length),
Type: pub.Plugin.Meta.Name,
}
@@ -148,7 +148,7 @@ func (s *Server) StreamInfo(ctx context.Context, req *pb.StreamSnapRequest) (res
func (s *Server) GetSubscribers(ctx context.Context, req *pb.SubscribersRequest) (res *pb.SubscribersResponse, err error) {
s.Call(func() {
var subscribers []*pb.SubscriberSnapShot
for _, subscriber := range s.Subscribers.Items {
for subscriber := range s.Subscribers.Range {
meta, _ := json.Marshal(subscriber.MetaData)
snap := &pb.SubscriberSnapShot{
Id: uint32(subscriber.ID),
@@ -195,7 +195,7 @@ func (s *Server) AudioTrackSnap(ctx context.Context, req *pb.StreamSnapRequest)
res.Memory = append(res.Memory, &pb.MemoryBlockGroup{List: list, Size: uint32(memlist.Size)})
}
res.Reader = make(map[uint32]uint32)
for sub := range pub.Subscribers {
for sub := range pub.SubscriberRange {
if sub.AudioReader == nil {
continue
}
@@ -259,6 +259,7 @@ func (s *Server) api_VideoTrack_SSE(rw http.ResponseWriter, r *http.Request) {
return
}
}
func (s *Server) VideoTrackSnap(ctx context.Context, req *pb.StreamSnapRequest) (res *pb.TrackSnapShotResponse, err error) {
s.Call(func() {
if pub, ok := s.Streams.Get(req.StreamPath); ok && !pub.VideoTrack.IsEmpty() {
@@ -274,7 +275,7 @@ func (s *Server) VideoTrackSnap(ctx context.Context, req *pb.StreamSnapRequest)
res.Memory = append(res.Memory, &pb.MemoryBlockGroup{List: list, Size: uint32(memlist.Size)})
}
res.Reader = make(map[uint32]uint32)
for sub := range pub.Subscribers {
for sub := range pub.SubscriberRange {
if sub.VideoReader == nil {
continue
}
@@ -325,6 +326,23 @@ func (s *Server) Shutdown(ctx context.Context, req *pb.RequestWithId) (res *empt
return empty, err
}
func (s *Server) ChangeSubscribe(ctx context.Context, req *pb.ChangeSubscribeRequest) (res *pb.SuccessResponse, err error) {
s.Call(func() {
if subscriber, ok := s.Subscribers.Get(int(req.Id)); ok {
if pub, ok := s.Streams.Get(req.StreamPath); ok {
subscriber.Publisher.RemoveSubscriber(subscriber)
subscriber.StreamPath = req.StreamPath
pub.AddSubscriber(subscriber)
return
}
}
err = pkg.ErrNotFound
})
return &pb.SuccessResponse{
Success: err == nil,
}, err
}
func (s *Server) StopSubscribe(ctx context.Context, req *pb.RequestWithId) (res *pb.SuccessResponse, err error) {
s.Call(func() {
if subscriber, ok := s.Subscribers.Get(int(req.Id)); ok {
@@ -342,7 +360,7 @@ func (s *Server) StopSubscribe(ctx context.Context, req *pb.RequestWithId) (res
func (s *Server) StreamList(_ context.Context, req *pb.StreamListRequest) (res *pb.StreamListResponse, err error) {
s.Call(func() {
var streams []*pb.StreamInfoResponse
for _, publisher := range s.Streams.Items {
for publisher := range s.Streams.Range {
info, err := s.getStreamInfo(publisher)
if err != nil {
continue
@@ -359,8 +377,8 @@ func (s *Server) WaitList(context.Context, *emptypb.Empty) (res *pb.StreamWaitLi
res = &pb.StreamWaitListResponse{
List: make(map[string]int32),
}
for streamPath, subs := range s.Waiting {
res.List[streamPath] = int32(len(subs))
for subs := range s.Waiting.Range {
res.List[subs.StreamPath] = int32(subs.Subscribers.Length)
}
})
return

View File

@@ -1680,6 +1680,61 @@ func (x *RequestWithId) GetId() uint32 {
return 0
}
type ChangeSubscribeRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id uint32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
StreamPath string `protobuf:"bytes,2,opt,name=streamPath,proto3" json:"streamPath,omitempty"`
}
func (x *ChangeSubscribeRequest) Reset() {
*x = ChangeSubscribeRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_global_proto_msgTypes[24]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ChangeSubscribeRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ChangeSubscribeRequest) ProtoMessage() {}
func (x *ChangeSubscribeRequest) ProtoReflect() protoreflect.Message {
mi := &file_global_proto_msgTypes[24]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ChangeSubscribeRequest.ProtoReflect.Descriptor instead.
func (*ChangeSubscribeRequest) Descriptor() ([]byte, []int) {
return file_global_proto_rawDescGZIP(), []int{24}
}
func (x *ChangeSubscribeRequest) GetId() uint32 {
if x != nil {
return x.Id
}
return 0
}
func (x *ChangeSubscribeRequest) GetStreamPath() string {
if x != nil {
return x.StreamPath
}
return ""
}
type SubscribersRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1693,7 +1748,7 @@ type SubscribersRequest struct {
func (x *SubscribersRequest) Reset() {
*x = SubscribersRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_global_proto_msgTypes[24]
mi := &file_global_proto_msgTypes[25]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1706,7 +1761,7 @@ func (x *SubscribersRequest) String() string {
func (*SubscribersRequest) ProtoMessage() {}
func (x *SubscribersRequest) ProtoReflect() protoreflect.Message {
mi := &file_global_proto_msgTypes[24]
mi := &file_global_proto_msgTypes[25]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1719,7 +1774,7 @@ func (x *SubscribersRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use SubscribersRequest.ProtoReflect.Descriptor instead.
func (*SubscribersRequest) Descriptor() ([]byte, []int) {
return file_global_proto_rawDescGZIP(), []int{24}
return file_global_proto_rawDescGZIP(), []int{25}
}
func (x *SubscribersRequest) GetStreamPath() string {
@@ -1757,7 +1812,7 @@ type RingReaderSnapShot struct {
func (x *RingReaderSnapShot) Reset() {
*x = RingReaderSnapShot{}
if protoimpl.UnsafeEnabled {
mi := &file_global_proto_msgTypes[25]
mi := &file_global_proto_msgTypes[26]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1770,7 +1825,7 @@ func (x *RingReaderSnapShot) String() string {
func (*RingReaderSnapShot) ProtoMessage() {}
func (x *RingReaderSnapShot) ProtoReflect() protoreflect.Message {
mi := &file_global_proto_msgTypes[25]
mi := &file_global_proto_msgTypes[26]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1783,7 +1838,7 @@ func (x *RingReaderSnapShot) ProtoReflect() protoreflect.Message {
// Deprecated: Use RingReaderSnapShot.ProtoReflect.Descriptor instead.
func (*RingReaderSnapShot) Descriptor() ([]byte, []int) {
return file_global_proto_rawDescGZIP(), []int{25}
return file_global_proto_rawDescGZIP(), []int{26}
}
func (x *RingReaderSnapShot) GetSequence() uint32 {
@@ -1829,7 +1884,7 @@ type SubscriberSnapShot struct {
func (x *SubscriberSnapShot) Reset() {
*x = SubscriberSnapShot{}
if protoimpl.UnsafeEnabled {
mi := &file_global_proto_msgTypes[26]
mi := &file_global_proto_msgTypes[27]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1842,7 +1897,7 @@ func (x *SubscriberSnapShot) String() string {
func (*SubscriberSnapShot) ProtoMessage() {}
func (x *SubscriberSnapShot) ProtoReflect() protoreflect.Message {
mi := &file_global_proto_msgTypes[26]
mi := &file_global_proto_msgTypes[27]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1855,7 +1910,7 @@ func (x *SubscriberSnapShot) ProtoReflect() protoreflect.Message {
// Deprecated: Use SubscriberSnapShot.ProtoReflect.Descriptor instead.
func (*SubscriberSnapShot) Descriptor() ([]byte, []int) {
return file_global_proto_rawDescGZIP(), []int{26}
return file_global_proto_rawDescGZIP(), []int{27}
}
func (x *SubscriberSnapShot) GetId() uint32 {
@@ -1907,7 +1962,7 @@ type SubscribersResponse struct {
func (x *SubscribersResponse) Reset() {
*x = SubscribersResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_global_proto_msgTypes[27]
mi := &file_global_proto_msgTypes[28]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1920,7 +1975,7 @@ func (x *SubscribersResponse) String() string {
func (*SubscribersResponse) ProtoMessage() {}
func (x *SubscribersResponse) ProtoReflect() protoreflect.Message {
mi := &file_global_proto_msgTypes[27]
mi := &file_global_proto_msgTypes[28]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1933,7 +1988,7 @@ func (x *SubscribersResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use SubscribersResponse.ProtoReflect.Descriptor instead.
func (*SubscribersResponse) Descriptor() ([]byte, []int) {
return file_global_proto_rawDescGZIP(), []int{27}
return file_global_proto_rawDescGZIP(), []int{28}
}
func (x *SubscribersResponse) GetTotal() int32 {
@@ -2193,132 +2248,144 @@ var file_global_proto_rawDesc = []byte{
0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73,
0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x1f, 0x0a, 0x0d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x57, 0x69, 0x74, 0x68, 0x49, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x22, 0x6a, 0x0a, 0x12, 0x53, 0x75, 0x62, 0x73, 0x63,
0x72, 0x69, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a,
0x0a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x12, 0x18, 0x0a,
0x07, 0x70, 0x61, 0x67, 0x65, 0x4e, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07,
0x70, 0x61, 0x67, 0x65, 0x4e, 0x75, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53,
0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53,
0x69, 0x7a, 0x65, 0x22, 0x7a, 0x0a, 0x12, 0x52, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x65,
0x72, 0x53, 0x6e, 0x61, 0x70, 0x53, 0x68, 0x6f, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x71,
0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x65, 0x71,
0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01,
0x28, 0x0d, 0x52, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61,
0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22,
0xe8, 0x01, 0x0a, 0x12, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x72, 0x53, 0x6e,
0x61, 0x70, 0x53, 0x68, 0x6f, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x38, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54,
0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65,
0x12, 0x39, 0x0a, 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18,
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x52, 0x69, 0x6e, 0x67,
0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x53, 0x6e, 0x61, 0x70, 0x53, 0x68, 0x6f, 0x74, 0x52, 0x0b,
0x61, 0x75, 0x64, 0x69, 0x6f, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x0b, 0x76,
0x69, 0x64, 0x65, 0x6f, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x17, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x52, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x65,
0x72, 0x53, 0x6e, 0x61, 0x70, 0x53, 0x68, 0x6f, 0x74, 0x52, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f,
0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x05,
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x8e, 0x01, 0x0a, 0x13, 0x53,
0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28,
0x05, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x67, 0x65,
0x4e, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x70, 0x61, 0x67, 0x65, 0x4e,
0x75, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x03,
0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2b,
0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d,
0x37, 0x73, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x72, 0x53, 0x6e, 0x61,
0x70, 0x53, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x32, 0xca, 0x0a, 0x0a, 0x06,
0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x12, 0x4d, 0x0a, 0x07, 0x53, 0x79, 0x73, 0x49, 0x6e, 0x66,
0x6f, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x14, 0x2e, 0x6d, 0x37, 0x73, 0x2e,
0x53, 0x79, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0e, 0x12, 0x0c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x79,
0x73, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x4d, 0x0a, 0x07, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79,
0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x14, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53,
0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0e, 0x12, 0x0c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x75, 0x6d,
0x6d, 0x61, 0x72, 0x79, 0x12, 0x52, 0x0a, 0x08, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e,
0x12, 0x12, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x57, 0x69,
0x74, 0x68, 0x49, 0x64, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x1a, 0x82, 0xd3,
0xe4, 0x93, 0x02, 0x14, 0x22, 0x12, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x68, 0x75, 0x74, 0x64,
0x6f, 0x77, 0x6e, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x50, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x74,
0x61, 0x72, 0x74, 0x12, 0x12, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x57, 0x69, 0x74, 0x68, 0x49, 0x64, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22,
0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x22, 0x11, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65,
0x73, 0x74, 0x61, 0x72, 0x74, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x57, 0x0a, 0x0a, 0x53, 0x74,
0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53,
0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x17, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x73,
0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x12, 0x12, 0x10, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2f, 0x6c,
0x69, 0x73, 0x74, 0x12, 0x5d, 0x0a, 0x08, 0x57, 0x61, 0x69, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12,
0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1b, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53, 0x74,
0x72, 0x65, 0x61, 0x6d, 0x57, 0x61, 0x69, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x61,
0x70, 0x69, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2f, 0x77, 0x61, 0x69, 0x74, 0x6c, 0x69,
0x73, 0x74, 0x12, 0x67, 0x0a, 0x0a, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, 0x6e, 0x66, 0x6f,
0x12, 0x16, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6e, 0x61,
0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53,
0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x61, 0x70, 0x69, 0x2f,
0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2f, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x7b, 0x73, 0x74, 0x72,
0x65, 0x61, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x3d, 0x2a, 0x2a, 0x7d, 0x12, 0x6d, 0x0a, 0x0e, 0x47,
0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x72, 0x73, 0x12, 0x17, 0x2e,
0x6d, 0x37, 0x73, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x72, 0x73, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53, 0x75, 0x62,
0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73,
0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x72, 0x65,
0x61, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x3d, 0x2a, 0x2a, 0x7d, 0x12, 0x72, 0x0a, 0x0e, 0x41, 0x75,
0x64, 0x69, 0x6f, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x53, 0x6e, 0x61, 0x70, 0x12, 0x16, 0x2e, 0x6d,
0x37, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b,
0x53, 0x6e, 0x61, 0x70, 0x53, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, 0x24, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61,
0x75, 0x64, 0x69, 0x6f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x2f, 0x73, 0x6e, 0x61, 0x70, 0x2f, 0x7b,
0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x3d, 0x2a, 0x2a, 0x7d, 0x12, 0x72,
0x0a, 0x0e, 0x56, 0x69, 0x64, 0x65, 0x6f, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x53, 0x6e, 0x61, 0x70,
0x12, 0x16, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6e, 0x61,
0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x54,
0x72, 0x61, 0x63, 0x6b, 0x53, 0x6e, 0x61, 0x70, 0x53, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, 0x24, 0x2f, 0x61,
0x70, 0x69, 0x2f, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x2f, 0x73, 0x6e,
0x61, 0x70, 0x2f, 0x7b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x3d, 0x2a,
0x2a, 0x7d, 0x12, 0x5e, 0x0a, 0x0d, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72,
0x69, 0x62, 0x65, 0x12, 0x12, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x57, 0x69, 0x74, 0x68, 0x49, 0x64, 0x1a, 0x14, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53, 0x75,
0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82,
0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x22, 0x18, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x74, 0x6f, 0x70,
0x2f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a,
0x01, 0x2a, 0x12, 0x5a, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
0x15, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x47, 0x65, 0x74,
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x2f, 0x67, 0x65, 0x74, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x5f,
0x0a, 0x0a, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x15, 0x2e, 0x6d,
0x37, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4,
0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x69, 0x6c, 0x79, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12,
0x67, 0x0a, 0x0c, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
0x18, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x6d, 0x37, 0x73, 0x2e,
0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x22, 0x19, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x2f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x2f, 0x7b, 0x6e, 0x61, 0x6d,
0x65, 0x7d, 0x3a, 0x04, 0x79, 0x61, 0x6d, 0x6c, 0x42, 0x14, 0x5a, 0x12, 0x6d, 0x37, 0x73, 0x2e,
0x6c, 0x69, 0x76, 0x65, 0x2f, 0x6d, 0x37, 0x73, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x62, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x22, 0x48, 0x0a, 0x16, 0x43, 0x68, 0x61, 0x6e, 0x67,
0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69,
0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x74,
0x68, 0x22, 0x6a, 0x0a, 0x12, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x72, 0x73,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61,
0x6d, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x72,
0x65, 0x61, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x67, 0x65, 0x4e,
0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x70, 0x61, 0x67, 0x65, 0x4e, 0x75,
0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20,
0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x7a, 0x0a,
0x12, 0x52, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x53, 0x6e, 0x61, 0x70, 0x53,
0x68, 0x6f, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12,
0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0d, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a,
0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x64, 0x65,
0x6c, 0x61, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01,
0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0xe8, 0x01, 0x0a, 0x12, 0x53, 0x75,
0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x72, 0x53, 0x6e, 0x61, 0x70, 0x53, 0x68, 0x6f, 0x74,
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64,
0x12, 0x38, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52,
0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x61, 0x75,
0x64, 0x69, 0x6f, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x17, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x52, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72,
0x53, 0x6e, 0x61, 0x70, 0x53, 0x68, 0x6f, 0x74, 0x52, 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x52,
0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x52, 0x65,
0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x37, 0x73,
0x2e, 0x52, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x53, 0x6e, 0x61, 0x70, 0x53,
0x68, 0x6f, 0x74, 0x52, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72,
0x12, 0x12, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x6d, 0x65, 0x74, 0x61, 0x22, 0x8e, 0x01, 0x0a, 0x13, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05,
0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x74, 0x6f, 0x74,
0x61, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x67, 0x65, 0x4e, 0x75, 0x6d, 0x18, 0x02, 0x20,
0x01, 0x28, 0x05, 0x52, 0x07, 0x70, 0x61, 0x67, 0x65, 0x4e, 0x75, 0x6d, 0x12, 0x1a, 0x0a, 0x08,
0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08,
0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2b, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74,
0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53, 0x75, 0x62,
0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x72, 0x53, 0x6e, 0x61, 0x70, 0x53, 0x68, 0x6f, 0x74, 0x52,
0x04, 0x6c, 0x69, 0x73, 0x74, 0x32, 0xc7, 0x0b, 0x0a, 0x06, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c,
0x12, 0x4d, 0x0a, 0x07, 0x53, 0x79, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d,
0x70, 0x74, 0x79, 0x1a, 0x14, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53, 0x79, 0x73, 0x49, 0x6e, 0x66,
0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x0e, 0x12, 0x0c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x79, 0x73, 0x69, 0x6e, 0x66, 0x6f, 0x12,
0x4d, 0x0a, 0x07, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70,
0x74, 0x79, 0x1a, 0x14, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0e,
0x12, 0x0c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x52,
0x0a, 0x08, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x12, 0x2e, 0x6d, 0x37, 0x73,
0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x57, 0x69, 0x74, 0x68, 0x49, 0x64, 0x1a, 0x16,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x22, 0x12,
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x2f, 0x7b, 0x69,
0x64, 0x7d, 0x12, 0x50, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x12, 0x2e,
0x6d, 0x37, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x57, 0x69, 0x74, 0x68, 0x49,
0x64, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x13, 0x22, 0x11, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x2f,
0x7b, 0x69, 0x64, 0x7d, 0x12, 0x57, 0x0a, 0x0a, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69,
0x73, 0x74, 0x12, 0x16, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c,
0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6d, 0x37, 0x73,
0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x61, 0x70,
0x69, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2f, 0x6c, 0x69, 0x73, 0x74, 0x12, 0x5d, 0x0a,
0x08, 0x57, 0x61, 0x69, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74,
0x79, 0x1a, 0x1b, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x57, 0x61,
0x69, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x74, 0x72,
0x65, 0x61, 0x6d, 0x2f, 0x77, 0x61, 0x69, 0x74, 0x6c, 0x69, 0x73, 0x74, 0x12, 0x67, 0x0a, 0x0a,
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x6d, 0x37, 0x73,
0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49,
0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4,
0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d,
0x2f, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x7b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x74,
0x68, 0x3d, 0x2a, 0x2a, 0x7d, 0x12, 0x6d, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73,
0x63, 0x72, 0x69, 0x62, 0x65, 0x72, 0x73, 0x12, 0x17, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53, 0x75,
0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x18, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65,
0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x22, 0x12, 0x20, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
0x62, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x74, 0x68,
0x3d, 0x2a, 0x2a, 0x7d, 0x12, 0x72, 0x0a, 0x0e, 0x41, 0x75, 0x64, 0x69, 0x6f, 0x54, 0x72, 0x61,
0x63, 0x6b, 0x53, 0x6e, 0x61, 0x70, 0x12, 0x16, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53, 0x74, 0x72,
0x65, 0x61, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a,
0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x53, 0x6e, 0x61, 0x70, 0x53, 0x68,
0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x26, 0x12, 0x24, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x74, 0x72,
0x61, 0x63, 0x6b, 0x2f, 0x73, 0x6e, 0x61, 0x70, 0x2f, 0x7b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d,
0x50, 0x61, 0x74, 0x68, 0x3d, 0x2a, 0x2a, 0x7d, 0x12, 0x72, 0x0a, 0x0e, 0x56, 0x69, 0x64, 0x65,
0x6f, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x53, 0x6e, 0x61, 0x70, 0x12, 0x16, 0x2e, 0x6d, 0x37, 0x73,
0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x53, 0x6e,
0x61, 0x70, 0x53, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, 0x24, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x69, 0x64,
0x65, 0x6f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x2f, 0x73, 0x6e, 0x61, 0x70, 0x2f, 0x7b, 0x73, 0x74,
0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x3d, 0x2a, 0x2a, 0x7d, 0x12, 0x7b, 0x0a, 0x0f,
0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12,
0x1b, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x62, 0x73,
0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x6d,
0x37, 0x73, 0x2e, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x22, 0x2a, 0x2f, 0x61, 0x70, 0x69,
0x2f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x67,
0x65, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x7b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61,
0x74, 0x68, 0x3d, 0x2a, 0x2a, 0x7d, 0x3a, 0x01, 0x2a, 0x12, 0x5e, 0x0a, 0x0d, 0x53, 0x74, 0x6f,
0x70, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x12, 0x2e, 0x6d, 0x37, 0x73,
0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x57, 0x69, 0x74, 0x68, 0x49, 0x64, 0x1a, 0x14,
0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x22, 0x18, 0x2f, 0x61,
0x70, 0x69, 0x2f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2f, 0x73, 0x74, 0x6f,
0x70, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x01, 0x2a, 0x12, 0x5a, 0x0a, 0x09, 0x47, 0x65, 0x74,
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x15, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x47, 0x65, 0x74,
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e,
0x6d, 0x37, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f,
0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x67, 0x65, 0x74, 0x2f, 0x7b,
0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x5f, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x6d,
0x69, 0x6c, 0x79, 0x12, 0x15, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6d, 0x37, 0x73,
0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x61, 0x70, 0x69,
0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x69, 0x6c, 0x79, 0x2f,
0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x67, 0x0a, 0x0c, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79,
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x4d, 0x6f, 0x64,
0x69, 0x66, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x14, 0x2e, 0x6d, 0x37, 0x73, 0x2e, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x22, 0x19,
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x6d, 0x6f, 0x64, 0x69,
0x66, 0x79, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x3a, 0x04, 0x79, 0x61, 0x6d, 0x6c, 0x42,
0x14, 0x5a, 0x12, 0x6d, 0x37, 0x73, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x2f, 0x6d, 0x37, 0x73, 0x2f,
0x76, 0x35, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -2333,7 +2400,7 @@ func file_global_proto_rawDescGZIP() []byte {
return file_global_proto_rawDescData
}
var file_global_proto_msgTypes = make([]protoimpl.MessageInfo, 33)
var file_global_proto_msgTypes = make([]protoimpl.MessageInfo, 34)
var file_global_proto_goTypes = []interface{}{
(*GetConfigRequest)(nil), // 0: m7s.GetConfigRequest
(*Formily)(nil), // 1: m7s.Formily
@@ -2359,76 +2426,79 @@ var file_global_proto_goTypes = []interface{}{
(*VideoTrackInfo)(nil), // 21: m7s.VideoTrackInfo
(*SuccessResponse)(nil), // 22: m7s.SuccessResponse
(*RequestWithId)(nil), // 23: m7s.RequestWithId
(*SubscribersRequest)(nil), // 24: m7s.SubscribersRequest
(*RingReaderSnapShot)(nil), // 25: m7s.RingReaderSnapShot
(*SubscriberSnapShot)(nil), // 26: m7s.SubscriberSnapShot
(*SubscribersResponse)(nil), // 27: m7s.SubscribersResponse
nil, // 28: m7s.Formily.PropertiesEntry
nil, // 29: m7s.Formily.ComponentPropsEntry
nil, // 30: m7s.FormilyResponse.PropertiesEntry
nil, // 31: m7s.StreamWaitListResponse.ListEntry
nil, // 32: m7s.TrackSnapShotResponse.ReaderEntry
(*timestamppb.Timestamp)(nil), // 33: google.protobuf.Timestamp
(*anypb.Any)(nil), // 34: google.protobuf.Any
(*emptypb.Empty)(nil), // 35: google.protobuf.Empty
(*ChangeSubscribeRequest)(nil), // 24: m7s.ChangeSubscribeRequest
(*SubscribersRequest)(nil), // 25: m7s.SubscribersRequest
(*RingReaderSnapShot)(nil), // 26: m7s.RingReaderSnapShot
(*SubscriberSnapShot)(nil), // 27: m7s.SubscriberSnapShot
(*SubscribersResponse)(nil), // 28: m7s.SubscribersResponse
nil, // 29: m7s.Formily.PropertiesEntry
nil, // 30: m7s.Formily.ComponentPropsEntry
nil, // 31: m7s.FormilyResponse.PropertiesEntry
nil, // 32: m7s.StreamWaitListResponse.ListEntry
nil, // 33: m7s.TrackSnapShotResponse.ReaderEntry
(*timestamppb.Timestamp)(nil), // 34: google.protobuf.Timestamp
(*anypb.Any)(nil), // 35: google.protobuf.Any
(*emptypb.Empty)(nil), // 36: google.protobuf.Empty
}
var file_global_proto_depIdxs = []int32{
28, // 0: m7s.Formily.properties:type_name -> m7s.Formily.PropertiesEntry
29, // 1: m7s.Formily.componentProps:type_name -> m7s.Formily.ComponentPropsEntry
30, // 2: m7s.FormilyResponse.properties:type_name -> m7s.FormilyResponse.PropertiesEntry
29, // 0: m7s.Formily.properties:type_name -> m7s.Formily.PropertiesEntry
30, // 1: m7s.Formily.componentProps:type_name -> m7s.Formily.ComponentPropsEntry
31, // 2: m7s.FormilyResponse.properties:type_name -> m7s.FormilyResponse.PropertiesEntry
6, // 3: m7s.SummaryResponse.memory:type_name -> m7s.Usage
6, // 4: m7s.SummaryResponse.hardDisk:type_name -> m7s.Usage
5, // 5: m7s.SummaryResponse.netWork:type_name -> m7s.NetWorkInfo
33, // 6: m7s.SysInfoResponse.startTime:type_name -> google.protobuf.Timestamp
34, // 6: m7s.SysInfoResponse.startTime:type_name -> google.protobuf.Timestamp
8, // 7: m7s.SysInfoResponse.plugins:type_name -> m7s.PluginInfo
14, // 8: m7s.StreamListResponse.list:type_name -> m7s.StreamInfoResponse
31, // 9: m7s.StreamWaitListResponse.list:type_name -> m7s.StreamWaitListResponse.ListEntry
32, // 9: m7s.StreamWaitListResponse.list:type_name -> m7s.StreamWaitListResponse.ListEntry
19, // 10: m7s.StreamInfoResponse.audioTrack:type_name -> m7s.AudioTrackInfo
21, // 11: m7s.StreamInfoResponse.videoTrack:type_name -> m7s.VideoTrackInfo
33, // 12: m7s.StreamInfoResponse.startTime:type_name -> google.protobuf.Timestamp
33, // 13: m7s.TrackSnapShot.writeTime:type_name -> google.protobuf.Timestamp
34, // 12: m7s.StreamInfoResponse.startTime:type_name -> google.protobuf.Timestamp
34, // 13: m7s.TrackSnapShot.writeTime:type_name -> google.protobuf.Timestamp
15, // 14: m7s.TrackSnapShot.wrap:type_name -> m7s.Wrap
17, // 15: m7s.MemoryBlockGroup.list:type_name -> m7s.MemoryBlock
16, // 16: m7s.TrackSnapShotResponse.ring:type_name -> m7s.TrackSnapShot
32, // 17: m7s.TrackSnapShotResponse.reader:type_name -> m7s.TrackSnapShotResponse.ReaderEntry
33, // 17: m7s.TrackSnapShotResponse.reader:type_name -> m7s.TrackSnapShotResponse.ReaderEntry
18, // 18: m7s.TrackSnapShotResponse.memory:type_name -> m7s.MemoryBlockGroup
33, // 19: m7s.SubscriberSnapShot.startTime:type_name -> google.protobuf.Timestamp
25, // 20: m7s.SubscriberSnapShot.audioReader:type_name -> m7s.RingReaderSnapShot
25, // 21: m7s.SubscriberSnapShot.videoReader:type_name -> m7s.RingReaderSnapShot
26, // 22: m7s.SubscribersResponse.list:type_name -> m7s.SubscriberSnapShot
34, // 19: m7s.SubscriberSnapShot.startTime:type_name -> google.protobuf.Timestamp
26, // 20: m7s.SubscriberSnapShot.audioReader:type_name -> m7s.RingReaderSnapShot
26, // 21: m7s.SubscriberSnapShot.videoReader:type_name -> m7s.RingReaderSnapShot
27, // 22: m7s.SubscribersResponse.list:type_name -> m7s.SubscriberSnapShot
1, // 23: m7s.Formily.PropertiesEntry.value:type_name -> m7s.Formily
34, // 24: m7s.Formily.ComponentPropsEntry.value:type_name -> google.protobuf.Any
35, // 24: m7s.Formily.ComponentPropsEntry.value:type_name -> google.protobuf.Any
1, // 25: m7s.FormilyResponse.PropertiesEntry.value:type_name -> m7s.Formily
35, // 26: m7s.Global.SysInfo:input_type -> google.protobuf.Empty
35, // 27: m7s.Global.Summary:input_type -> google.protobuf.Empty
36, // 26: m7s.Global.SysInfo:input_type -> google.protobuf.Empty
36, // 27: m7s.Global.Summary:input_type -> google.protobuf.Empty
23, // 28: m7s.Global.Shutdown:input_type -> m7s.RequestWithId
23, // 29: m7s.Global.Restart:input_type -> m7s.RequestWithId
10, // 30: m7s.Global.StreamList:input_type -> m7s.StreamListRequest
35, // 31: m7s.Global.WaitList:input_type -> google.protobuf.Empty
36, // 31: m7s.Global.WaitList:input_type -> google.protobuf.Empty
13, // 32: m7s.Global.StreamInfo:input_type -> m7s.StreamSnapRequest
24, // 33: m7s.Global.GetSubscribers:input_type -> m7s.SubscribersRequest
25, // 33: m7s.Global.GetSubscribers:input_type -> m7s.SubscribersRequest
13, // 34: m7s.Global.AudioTrackSnap:input_type -> m7s.StreamSnapRequest
13, // 35: m7s.Global.VideoTrackSnap:input_type -> m7s.StreamSnapRequest
23, // 36: m7s.Global.StopSubscribe:input_type -> m7s.RequestWithId
0, // 37: m7s.Global.GetConfig:input_type -> m7s.GetConfigRequest
0, // 38: m7s.Global.GetFormily:input_type -> m7s.GetConfigRequest
4, // 39: m7s.Global.ModifyConfig:input_type -> m7s.ModifyConfigRequest
9, // 40: m7s.Global.SysInfo:output_type -> m7s.SysInfoResponse
7, // 41: m7s.Global.Summary:output_type -> m7s.SummaryResponse
35, // 42: m7s.Global.Shutdown:output_type -> google.protobuf.Empty
35, // 43: m7s.Global.Restart:output_type -> google.protobuf.Empty
11, // 44: m7s.Global.StreamList:output_type -> m7s.StreamListResponse
12, // 45: m7s.Global.WaitList:output_type -> m7s.StreamWaitListResponse
14, // 46: m7s.Global.StreamInfo:output_type -> m7s.StreamInfoResponse
27, // 47: m7s.Global.GetSubscribers:output_type -> m7s.SubscribersResponse
20, // 48: m7s.Global.AudioTrackSnap:output_type -> m7s.TrackSnapShotResponse
20, // 49: m7s.Global.VideoTrackSnap:output_type -> m7s.TrackSnapShotResponse
22, // 50: m7s.Global.StopSubscribe:output_type -> m7s.SuccessResponse
3, // 51: m7s.Global.GetConfig:output_type -> m7s.GetConfigResponse
3, // 52: m7s.Global.GetFormily:output_type -> m7s.GetConfigResponse
22, // 53: m7s.Global.ModifyConfig:output_type -> m7s.SuccessResponse
40, // [40:54] is the sub-list for method output_type
26, // [26:40] is the sub-list for method input_type
24, // 36: m7s.Global.ChangeSubscribe:input_type -> m7s.ChangeSubscribeRequest
23, // 37: m7s.Global.StopSubscribe:input_type -> m7s.RequestWithId
0, // 38: m7s.Global.GetConfig:input_type -> m7s.GetConfigRequest
0, // 39: m7s.Global.GetFormily:input_type -> m7s.GetConfigRequest
4, // 40: m7s.Global.ModifyConfig:input_type -> m7s.ModifyConfigRequest
9, // 41: m7s.Global.SysInfo:output_type -> m7s.SysInfoResponse
7, // 42: m7s.Global.Summary:output_type -> m7s.SummaryResponse
36, // 43: m7s.Global.Shutdown:output_type -> google.protobuf.Empty
36, // 44: m7s.Global.Restart:output_type -> google.protobuf.Empty
11, // 45: m7s.Global.StreamList:output_type -> m7s.StreamListResponse
12, // 46: m7s.Global.WaitList:output_type -> m7s.StreamWaitListResponse
14, // 47: m7s.Global.StreamInfo:output_type -> m7s.StreamInfoResponse
28, // 48: m7s.Global.GetSubscribers:output_type -> m7s.SubscribersResponse
20, // 49: m7s.Global.AudioTrackSnap:output_type -> m7s.TrackSnapShotResponse
20, // 50: m7s.Global.VideoTrackSnap:output_type -> m7s.TrackSnapShotResponse
22, // 51: m7s.Global.ChangeSubscribe:output_type -> m7s.SuccessResponse
22, // 52: m7s.Global.StopSubscribe:output_type -> m7s.SuccessResponse
3, // 53: m7s.Global.GetConfig:output_type -> m7s.GetConfigResponse
3, // 54: m7s.Global.GetFormily:output_type -> m7s.GetConfigResponse
22, // 55: m7s.Global.ModifyConfig:output_type -> m7s.SuccessResponse
41, // [41:56] is the sub-list for method output_type
26, // [26:41] is the sub-list for method input_type
26, // [26:26] is the sub-list for extension type_name
26, // [26:26] is the sub-list for extension extendee
0, // [0:26] is the sub-list for field type_name
@@ -2729,7 +2799,7 @@ func file_global_proto_init() {
}
}
file_global_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SubscribersRequest); i {
switch v := v.(*ChangeSubscribeRequest); i {
case 0:
return &v.state
case 1:
@@ -2741,7 +2811,7 @@ func file_global_proto_init() {
}
}
file_global_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RingReaderSnapShot); i {
switch v := v.(*SubscribersRequest); i {
case 0:
return &v.state
case 1:
@@ -2753,7 +2823,7 @@ func file_global_proto_init() {
}
}
file_global_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SubscriberSnapShot); i {
switch v := v.(*RingReaderSnapShot); i {
case 0:
return &v.state
case 1:
@@ -2765,6 +2835,18 @@ func file_global_proto_init() {
}
}
file_global_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SubscriberSnapShot); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_global_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SubscribersResponse); i {
case 0:
return &v.state
@@ -2783,7 +2865,7 @@ func file_global_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_global_proto_rawDesc,
NumEnums: 0,
NumMessages: 33,
NumMessages: 34,
NumExtensions: 0,
NumServices: 1,
},

View File

@@ -452,6 +452,86 @@ func local_request_Global_VideoTrackSnap_0(ctx context.Context, marshaler runtim
}
func request_Global_ChangeSubscribe_0(ctx context.Context, marshaler runtime.Marshaler, client GlobalClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ChangeSubscribeRequest
var metadata runtime.ServerMetadata
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.Uint32(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
val, ok = pathParams["streamPath"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "streamPath")
}
protoReq.StreamPath, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "streamPath", err)
}
msg, err := client.ChangeSubscribe(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Global_ChangeSubscribe_0(ctx context.Context, marshaler runtime.Marshaler, server GlobalServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ChangeSubscribeRequest
var metadata runtime.ServerMetadata
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.Uint32(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
val, ok = pathParams["streamPath"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "streamPath")
}
protoReq.StreamPath, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "streamPath", err)
}
msg, err := server.ChangeSubscribe(ctx, &protoReq)
return msg, metadata, err
}
func request_Global_StopSubscribe_0(ctx context.Context, marshaler runtime.Marshaler, client GlobalClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq RequestWithId
var metadata runtime.ServerMetadata
@@ -932,6 +1012,31 @@ func RegisterGlobalHandlerServer(ctx context.Context, mux *runtime.ServeMux, ser
})
mux.Handle("POST", pattern_Global_ChangeSubscribe_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/m7s.Global/ChangeSubscribe", runtime.WithHTTPPathPattern("/api/subscribe/change/{id}/{streamPath=**}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Global_ChangeSubscribe_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Global_ChangeSubscribe_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_Global_StopSubscribe_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -940,7 +1045,7 @@ func RegisterGlobalHandlerServer(ctx context.Context, mux *runtime.ServeMux, ser
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/m7s.Global/StopSubscribe", runtime.WithHTTPPathPattern("/api/stop/subscribe/{id}"))
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/m7s.Global/StopSubscribe", runtime.WithHTTPPathPattern("/api/subscribe/stop/{id}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
@@ -1293,13 +1398,35 @@ func RegisterGlobalHandlerClient(ctx context.Context, mux *runtime.ServeMux, cli
})
mux.Handle("POST", pattern_Global_ChangeSubscribe_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/m7s.Global/ChangeSubscribe", runtime.WithHTTPPathPattern("/api/subscribe/change/{id}/{streamPath=**}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Global_ChangeSubscribe_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Global_ChangeSubscribe_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_Global_StopSubscribe_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/m7s.Global/StopSubscribe", runtime.WithHTTPPathPattern("/api/stop/subscribe/{id}"))
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/m7s.Global/StopSubscribe", runtime.WithHTTPPathPattern("/api/subscribe/stop/{id}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
@@ -1405,7 +1532,9 @@ var (
pattern_Global_VideoTrackSnap_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 3, 0, 4, 1, 5, 3}, []string{"api", "videotrack", "snap", "streamPath"}, ""))
pattern_Global_StopSubscribe_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "stop", "subscribe", "id"}, ""))
pattern_Global_ChangeSubscribe_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 3, 0, 4, 1, 5, 4}, []string{"api", "subscribe", "change", "id", "streamPath"}, ""))
pattern_Global_StopSubscribe_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "subscribe", "stop", "id"}, ""))
pattern_Global_GetConfig_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "config", "get", "name"}, ""))
@@ -1435,6 +1564,8 @@ var (
forward_Global_VideoTrackSnap_0 = runtime.ForwardResponseMessage
forward_Global_ChangeSubscribe_0 = runtime.ForwardResponseMessage
forward_Global_StopSubscribe_0 = runtime.ForwardResponseMessage
forward_Global_GetConfig_0 = runtime.ForwardResponseMessage

View File

@@ -57,9 +57,16 @@ service Global {
get: "/api/videotrack/snap/{streamPath=**}"
};
}
rpc ChangeSubscribe (ChangeSubscribeRequest) returns (SuccessResponse) {
option (google.api.http) = {
post: "/api/subscribe/change/{id}/{streamPath=**}"
body: "*"
};
}
rpc StopSubscribe (RequestWithId) returns (SuccessResponse) {
option (google.api.http) = {
post: "/api/stop/subscribe/{id}"
post: "/api/subscribe/stop/{id}"
body: "*"
};
}
@@ -243,6 +250,11 @@ message RequestWithId {
uint32 id = 1;
}
message ChangeSubscribeRequest {
uint32 id = 1;
string streamPath = 2;
}
message SubscribersRequest {
string streamPath = 1;
int32 pageNum = 2;

View File

@@ -33,6 +33,7 @@ type GlobalClient interface {
GetSubscribers(ctx context.Context, in *SubscribersRequest, opts ...grpc.CallOption) (*SubscribersResponse, error)
AudioTrackSnap(ctx context.Context, in *StreamSnapRequest, opts ...grpc.CallOption) (*TrackSnapShotResponse, error)
VideoTrackSnap(ctx context.Context, in *StreamSnapRequest, opts ...grpc.CallOption) (*TrackSnapShotResponse, error)
ChangeSubscribe(ctx context.Context, in *ChangeSubscribeRequest, opts ...grpc.CallOption) (*SuccessResponse, error)
StopSubscribe(ctx context.Context, in *RequestWithId, opts ...grpc.CallOption) (*SuccessResponse, error)
GetConfig(ctx context.Context, in *GetConfigRequest, opts ...grpc.CallOption) (*GetConfigResponse, error)
GetFormily(ctx context.Context, in *GetConfigRequest, opts ...grpc.CallOption) (*GetConfigResponse, error)
@@ -137,6 +138,15 @@ func (c *globalClient) VideoTrackSnap(ctx context.Context, in *StreamSnapRequest
return out, nil
}
func (c *globalClient) ChangeSubscribe(ctx context.Context, in *ChangeSubscribeRequest, opts ...grpc.CallOption) (*SuccessResponse, error) {
out := new(SuccessResponse)
err := c.cc.Invoke(ctx, "/m7s.Global/ChangeSubscribe", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *globalClient) StopSubscribe(ctx context.Context, in *RequestWithId, opts ...grpc.CallOption) (*SuccessResponse, error) {
out := new(SuccessResponse)
err := c.cc.Invoke(ctx, "/m7s.Global/StopSubscribe", in, out, opts...)
@@ -187,6 +197,7 @@ type GlobalServer interface {
GetSubscribers(context.Context, *SubscribersRequest) (*SubscribersResponse, error)
AudioTrackSnap(context.Context, *StreamSnapRequest) (*TrackSnapShotResponse, error)
VideoTrackSnap(context.Context, *StreamSnapRequest) (*TrackSnapShotResponse, error)
ChangeSubscribe(context.Context, *ChangeSubscribeRequest) (*SuccessResponse, error)
StopSubscribe(context.Context, *RequestWithId) (*SuccessResponse, error)
GetConfig(context.Context, *GetConfigRequest) (*GetConfigResponse, error)
GetFormily(context.Context, *GetConfigRequest) (*GetConfigResponse, error)
@@ -228,6 +239,9 @@ func (UnimplementedGlobalServer) AudioTrackSnap(context.Context, *StreamSnapRequ
func (UnimplementedGlobalServer) VideoTrackSnap(context.Context, *StreamSnapRequest) (*TrackSnapShotResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method VideoTrackSnap not implemented")
}
func (UnimplementedGlobalServer) ChangeSubscribe(context.Context, *ChangeSubscribeRequest) (*SuccessResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ChangeSubscribe not implemented")
}
func (UnimplementedGlobalServer) StopSubscribe(context.Context, *RequestWithId) (*SuccessResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method StopSubscribe not implemented")
}
@@ -433,6 +447,24 @@ func _Global_VideoTrackSnap_Handler(srv interface{}, ctx context.Context, dec fu
return interceptor(ctx, in, info, handler)
}
func _Global_ChangeSubscribe_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ChangeSubscribeRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(GlobalServer).ChangeSubscribe(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/m7s.Global/ChangeSubscribe",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GlobalServer).ChangeSubscribe(ctx, req.(*ChangeSubscribeRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Global_StopSubscribe_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RequestWithId)
if err := dec(in); err != nil {
@@ -552,6 +584,10 @@ var Global_ServiceDesc = grpc.ServiceDesc{
MethodName: "VideoTrackSnap",
Handler: _Global_VideoTrackSnap_Handler,
},
{
MethodName: "ChangeSubscribe",
Handler: _Global_ChangeSubscribe_Handler,
},
{
MethodName: "StopSubscribe",
Handler: _Global_StopSubscribe_Handler,

View File

@@ -16,4 +16,5 @@ var (
ErrInterrupt = errors.New("interrupt")
ErrUnsupportCodec = errors.New("unsupport codec")
ErrMuted = errors.New("muted")
ErrorLost = errors.New("lost")
)

View File

@@ -80,8 +80,11 @@ func (rb *RingWriter) Reduce(size int) (r *util.Ring[AVFrame]) {
return
}
func (rb *RingWriter) Dispose() {
rb.Value.Ready()
}
func (rb *RingWriter) Step() (normal bool) {
// rb.LastValue.Broadcast() // 防止订阅者还在等待
rb.LastValue = &rb.Value
nextSeq := rb.LastValue.Sequence + 1
next := rb.Next()
@@ -91,7 +94,10 @@ func (rb *RingWriter) Step() (normal bool) {
} else {
rb.Reduce(1) //抛弃还有订阅者的节点
rb.Ring = rb.Glow(1) //补充一个新节点
rb.Value.StartWrite()
normal = rb.Value.StartWrite()
if !normal {
panic("RingWriter.Step")
}
}
rb.Value.Sequence = nextSeq
rb.LastValue.Ready()

View File

@@ -20,12 +20,11 @@ func (unit *Unit) Trace(msg string, fields ...any) {
}
func (unit *Unit) IsStopped() bool {
select {
case <-unit.Done():
return true
default:
}
return false
return unit.StopReason() != nil
}
func (unit *Unit) StopReason() error {
return context.Cause(unit.Context)
}
func (unit *Unit) Stop(err error) {

View File

@@ -9,17 +9,17 @@ type (
Start, End int
trees [2]Tree
}
// History struct {
// Malloc bool
// Offset int
// Size int
// }
History struct {
Malloc bool
Offset int
Size int
}
Allocator struct {
pool []*Block
sizeTree *Block
offsetTree *Block
Size int
// history []History
//history []History
}
)
@@ -158,7 +158,7 @@ func (b *Block) delete(block *Block, treeIndex int) *Block {
}
func (a *Allocator) Allocate(size int) (offset int) {
// a.history = append(a.history, History{Malloc: true, Size: size})
//a.history = append(a.history, History{Malloc: true, Size: size})
block := a.findAvailableBlock(a.sizeTree, size)
if block == nil {
return -1
@@ -207,7 +207,7 @@ func (a *Allocator) putBlock(b *Block) {
}
func (a *Allocator) Free(offset, size int) {
// a.history = append(a.history, History{Malloc: false, Offset: offset, Size: size})
//a.history = append(a.history, History{Malloc: false, Offset: offset, Size: size})
block := a.getBlock(offset, offset+size)
a.sizeTree, a.offsetTree = a.sizeTree.insert(block, 0), a.offsetTree.insert(block, 1)
a.mergeAdjacentBlocks(block)

122
pkg/util/buddy.go Normal file
View File

@@ -0,0 +1,122 @@
package util
import (
"errors"
)
type Buddy struct {
size int
longests []int
}
var (
InValidParameterErr = errors.New("buddy: invalid parameter")
NotFoundErr = errors.New("buddy: can't find block")
)
// NewBuddy creates a buddy instance.
// If the parameter isn't valid, return the nil and error as well
func NewBuddy(size int) *Buddy {
if !isPowerOf2(size) {
size = fixSize(size)
}
nodeCount := 2*size - 1
longests := make([]int, nodeCount)
for nodeSize, i := 2*size, 0; i < nodeCount; i++ {
if isPowerOf2(i + 1) {
nodeSize /= 2
}
longests[i] = nodeSize
}
return &Buddy{size, longests}
}
// Alloc find a unused block according to the size
// return the offset of the block(regard 0 as the beginning)
// and parameter error if any
func (b *Buddy) Alloc(size int) (offset int, err error) {
if size <= 0 {
err = InValidParameterErr
return
}
if !isPowerOf2(size) {
size = fixSize(size)
}
if size > b.longests[0] {
err = NotFoundErr
return
}
index := 0
for nodeSize := b.size; nodeSize != size; nodeSize /= 2 {
if left := leftChild(index); b.longests[left] >= size {
index = left
} else {
index = rightChild(index)
}
}
b.longests[index] = 0 // mark zero as used
offset = (index+1)*size - b.size
// update the parent node's size
for index != 0 {
index = parent(index)
b.longests[index] = max(b.longests[leftChild(index)], b.longests[rightChild(index)])
}
return
}
// Free find a block according to the offset and mark it as unused
// return error if not found or parameter invalid
func (b *Buddy) Free(offset int) error {
if offset < 0 || offset >= b.size {
return InValidParameterErr
}
nodeSize := 1
index := offset + b.size - 1
for ; b.longests[index] != 0; index = parent(index) {
nodeSize *= 2
if index == 0 {
return NotFoundErr
}
}
b.longests[index] = nodeSize
// update parent node's size
for index != 0 {
index = parent(index)
nodeSize *= 2
leftSize := b.longests[leftChild(index)]
rightSize := b.longests[rightChild(index)]
if leftSize+rightSize == nodeSize {
b.longests[index] = nodeSize
} else {
b.longests[index] = max(leftSize, rightSize)
}
}
return nil
}
// helpers
func isPowerOf2(size int) bool {
return size&(size-1) == 0
}
func fixSize(size int) int {
size |= size >> 1
size |= size >> 2
size |= size >> 4
size |= size >> 8
size |= size >> 16
return size + 1
}
func leftChild(index int) int {
return 2*index + 1
}
func rightChild(index int) int {
return 2*index + 2
}
func parent(index int) int {
return (index+1)/2 - 1
}

View File

@@ -4,7 +4,7 @@ import (
"io"
)
const defaultBufSize = 65536
const defaultBufSize = 1 << 16
type BufReader struct {
reader io.Reader
@@ -95,6 +95,12 @@ func (r *BufReader) ReadBE32(n int) (num uint32, err error) {
func (r *BufReader) ReadBytes(n int) (mem RecyclableMemory, err error) {
mem.ScalableMemoryAllocator = r.allocator
defer func() {
if err != nil {
mem.Recycle()
mem = RecyclableMemory{}
}
}()
for r.recycleFront(); n > 0 && err == nil; err = r.eat() {
if r.buf.Length > 0 {
if r.buf.Length >= n {

View File

@@ -30,10 +30,11 @@ func (c *Collection[K, T]) Add(item T) {
c.Length++
}
func (c *Collection[K, T]) AddUnique(item T) {
if _, ok := c.Get(item.GetKey()); !ok {
func (c *Collection[K, T]) AddUnique(item T) (ok bool) {
if _, ok = c.Get(item.GetKey()); !ok {
c.Add(item)
}
return !ok
}
func (c *Collection[K, T]) Set(item T) {
@@ -50,6 +51,18 @@ func (c *Collection[K, T]) Set(item T) {
c.Add(item)
}
func (c *Collection[K, T]) Range(f func(T) bool) {
if c.L != nil {
c.L.RLock()
defer c.L.RUnlock()
}
for _, item := range c.Items {
if !f(item) {
break
}
}
}
func (c *Collection[K, T]) Remove(item T) {
c.RemoveByKey(item.GetKey())
}

View File

@@ -6,10 +6,19 @@ import (
"unsafe"
)
const MaxBlockSize = 4 * 1024 * 1024
const (
MaxBlockSize = 1 << 22
BuddySize = MaxBlockSize << 4
MinPowerOf2 = 10
)
var pools sync.Map
var EnableCheckSize bool = false
var (
memoryPool [BuddySize]byte
buddy = NewBuddy(BuddySize >> MinPowerOf2)
lock sync.Mutex
poolStart = int64(uintptr(unsafe.Pointer(&memoryPool[0])))
//EnableCheckSize bool = false
)
type MemoryAllocator struct {
allocator *Allocator
@@ -19,11 +28,19 @@ type MemoryAllocator struct {
}
func GetMemoryAllocator(size int) (ret *MemoryAllocator) {
if value, ok := pools.Load(size); ok {
ret = value.(*sync.Pool).Get().(*MemoryAllocator)
} else {
ret = NewMemoryAllocator(size)
lock.Lock()
offset, err := buddy.Alloc(size >> MinPowerOf2)
lock.Unlock()
if err != nil {
return NewMemoryAllocator(size)
}
offset = offset << MinPowerOf2
ret = &MemoryAllocator{
Size: size,
memory: memoryPool[offset : offset+size],
allocator: NewAllocator(size),
}
ret.start = poolStart + int64(offset)
return
}
@@ -38,14 +55,9 @@ func NewMemoryAllocator(size int) (ret *MemoryAllocator) {
}
func (ma *MemoryAllocator) Recycle() {
ma.allocator = NewAllocator(ma.Size)
size := ma.Size
pool, _ := pools.LoadOrStore(size, &sync.Pool{
New: func() any {
return NewMemoryAllocator(size)
},
})
pool.(*sync.Pool).Put(ma)
lock.Lock()
_ = buddy.Free(int((poolStart - ma.start) >> 10))
lock.Unlock()
}
func (ma *MemoryAllocator) Malloc(size int) (memory []byte) {
@@ -77,10 +89,11 @@ type ScalableMemoryAllocator struct {
totalMalloc int64
totalFree int64
size int
childSize int
}
func NewScalableMemoryAllocator(size int) (ret *ScalableMemoryAllocator) {
return &ScalableMemoryAllocator{children: []*MemoryAllocator{GetMemoryAllocator(size)}, size: size}
return &ScalableMemoryAllocator{children: []*MemoryAllocator{GetMemoryAllocator(size)}, size: size, childSize: size}
}
func (sma *ScalableMemoryAllocator) checkSize() {
@@ -123,9 +136,9 @@ func (sma *ScalableMemoryAllocator) Malloc(size int) (memory []byte) {
if sma == nil {
return make([]byte, size)
}
if EnableCheckSize {
defer sma.checkSize()
}
//if EnableCheckSize {
// defer sma.checkSize()
//}
defer sma.addMallocCount(size)
var child *MemoryAllocator
for _, child = range sma.children {
@@ -133,7 +146,13 @@ func (sma *ScalableMemoryAllocator) Malloc(size int) (memory []byte) {
return
}
}
child = GetMemoryAllocator(max(min(MaxBlockSize, child.Size*2), size))
for sma.childSize <= MaxBlockSize {
sma.childSize = sma.childSize << 1
if sma.childSize >= size {
break
}
}
child = GetMemoryAllocator(sma.childSize)
sma.size += child.Size
memory = child.Malloc(size)
sma.children = append(sma.children, child)
@@ -148,9 +167,9 @@ func (sma *ScalableMemoryAllocator) Free(mem []byte) bool {
if sma == nil {
return false
}
if EnableCheckSize {
defer sma.checkSize()
}
//if EnableCheckSize {
// defer sma.checkSize()
//}
ptr := int64(uintptr(unsafe.Pointer(&mem[0])))
size := len(mem)
for i, child := range sma.children {

View File

@@ -332,12 +332,6 @@ func (p *Plugin) Subscribe(streamPath string, options ...any) (subscriber *Subsc
switch v := option.(type) {
case func(*config.Subscribe):
v(&subscriber.Subscribe)
case SubscriberHandler:
defer func() {
if err == nil {
subscriber.Handle(v)
}
}()
}
}
subscriber.Init(p, streamPath, options...)

View File

@@ -109,11 +109,10 @@ func (p *HDLPlugin) ServeHTTP(w http.ResponseWriter, r *http.Request) {
defer binary.BigEndian.PutUint32(b[:4], uint32(data.Size)+11)
return gotFlvTag(append(net.Buffers{b[:]}, data.Memory.Buffers...))
}
sub.Handle(m7s.SubscriberHandler{
OnAudio: func(audio *rtmp.RTMPAudio) error {
m7s.PlayBlock(sub, func(audio *rtmp.RTMPAudio) error {
return rtmpData2FlvTag(FLV_TAG_TYPE_AUDIO, &audio.RTMPData)
}, OnVideo: func(video *rtmp.RTMPVideo) error {
}, func(video *rtmp.RTMPVideo) error {
return rtmpData2FlvTag(FLV_TAG_TYPE_VIDEO, &video.RTMPData)
}})
})
gotFlvTag(net.Buffers{b[:4]})
}

View File

@@ -104,7 +104,6 @@ func (puller *HDLPuller) Pull(p *m7s.Puller) (err error) {
var frame rtmp.RTMPData
frame.RecyclableMemory, err = puller.ReadBytes(int(dataSize))
if err != nil {
frame.Recycle()
return err
}
puller.absTS = offsetTs + (timestamp - startTs)

View File

@@ -1,7 +1,7 @@
package plugin_rtmp
import (
"context"
"errors"
"io"
"net"
@@ -42,13 +42,17 @@ func (p *RTMPPlugin) OnTCPConnect(conn *net.TCPConn) {
logger := p.Logger.With("remote", conn.RemoteAddr().String())
receivers := make(map[uint32]*RTMPReceiver)
var err error
logger.Info("conn")
nc := NewNetConnection(conn, logger)
defer nc.Destroy()
ctx, cancel := context.WithCancelCause(p)
defer func() {
logger.Info("conn close")
cancel(err)
nc.Destroy()
if p := recover(); p != nil {
err = p.(error)
}
if len(receivers) > 0 {
for _, receiver := range receivers {
receiver.Dispose(err)
}
}
}()
/* Handshake */
if err = nc.Handshake(p.C2); err != nil {
@@ -156,7 +160,7 @@ func (p *RTMPPlugin) OnTCPConnect(conn *net.TCPConn) {
StreamID: cmd.StreamId,
},
}
receiver.Publisher, err = p.Publish(nc.AppName+"/"+cmd.PublishingName, ctx, conn, connectInfo)
receiver.Publisher, err = p.Publish(nc.AppName+"/"+cmd.PublishingName, p.Context, conn, connectInfo)
if err != nil {
delete(receivers, cmd.StreamId)
err = receiver.Response(cmd.TransactionId, NetStream_Publish_BadName, Level_Error)
@@ -176,18 +180,13 @@ func (p *RTMPPlugin) OnTCPConnect(conn *net.TCPConn) {
}
var suber *m7s.Subscriber
// sender.ID = fmt.Sprintf("%s|%d", conn.RemoteAddr().String(), sender.StreamID)
suber, err = p.Subscribe(streamPath, ctx, conn, connectInfo)
suber, err = p.Subscribe(streamPath, p.Context, conn, connectInfo)
if err != nil {
err = ns.Response(cmd.TransactionId, NetStream_Play_Failed, Level_Error)
} else {
ns.BeginPlay(cmd.TransactionId)
audio, video := ns.CreateSender()
go suber.Handle(m7s.SubscriberHandler{
OnAudio: func(a *RTMPAudio) error {
return audio.SendFrame(&a.RTMPData)
}, OnVideo: func(v *RTMPVideo) error {
return video.SendFrame(&v.RTMPData)
}})
audio, video := ns.CreateSender(false)
go m7s.PlayBlock(suber, audio.HandleAudio, video.HandleVideo)
}
if err != nil {
logger.Error("sendMessage play", "error", err)
@@ -209,7 +208,7 @@ func (p *RTMPPlugin) OnTCPConnect(conn *net.TCPConn) {
logger.Warn("ReceiveVideo", "MessageStreamID", msg.MessageStreamID)
}
}
} else if err == io.EOF || err == io.ErrUnexpectedEOF {
} else if err == io.EOF || errors.Is(err, io.ErrUnexpectedEOF) {
logger.Info("rtmp client closed")
return
} else {

View File

@@ -9,7 +9,6 @@ import (
"strings"
"m7s.live/m7s/v5"
. "m7s.live/m7s/v5/pkg"
)
type Client struct {
@@ -104,7 +103,13 @@ func (client *Client) Connect(p *m7s.Client) (err error) {
func (puller *Client) Pull(p *m7s.Puller) (err error) {
p.MetaData = puller.ServerInfo
defer puller.Close()
defer func() {
puller.Close()
if p := recover(); p != nil {
err = p.(error)
}
p.Dispose(err)
}()
err = puller.SendMessage(RTMP_MSG_AMF0_COMMAND, &CommandMessage{"createStream", 2})
for err == nil {
msg, err := puller.RecvMessage()
@@ -185,19 +190,8 @@ func (pusher *Client) Push(p *m7s.Pusher) (err error) {
})
} else if response, ok := msg.MsgData.(*ResponsePublishMessage); ok {
if response.Infomation["code"] == NetStream_Publish_Start {
audio, video := pusher.CreateSender()
go p.Handle(m7s.SubscriberHandler{
OnAudio: func(a *RTMPAudio) error {
if audio.SendFrame(&a.RTMPData) != nil {
return ErrInterrupt
}
return nil
}, OnVideo: func(v *RTMPVideo) error {
if video.SendFrame(&v.RTMPData) != nil {
return ErrInterrupt
}
return nil
}})
audio, video := pusher.CreateSender(true)
go m7s.PlayBlock(&p.Subscriber, audio.HandleAudio, video.HandleVideo)
} else {
return errors.New(response.Infomation["code"].(string))
}

View File

@@ -116,18 +116,18 @@ func (nc *NetConnection) simple_handshake(C1 []byte, checkC2 bool) error {
nc.Write(S0S1)
nc.Write(C1) // S2
C2, err := nc.ReadBytes(C1S1_SIZE)
C2.Recycle()
if err != nil {
return err
}
C2.Recycle()
if checkC2 {
buf := nc.mediaDataPool.NextN(C2.Size)
C2.Read(buf)
_, err = C2.Read(buf)
if !bytes.Equal(buf[8:], S0S1[9:]) {
return errors.New("C2 Error")
}
}
return nil
return err
}
func (nc *NetConnection) complex_handshake(C1 []byte) error {
@@ -178,10 +178,10 @@ func (nc *NetConnection) complex_handshake(C1 []byte) error {
}
buffer := net.Buffers{[]byte{RTMP_HANDSHAKE_VERSION}, S1, S2_Random, S2_Digest}
buffer.WriteTo(nc)
_, err = buffer.WriteTo(nc)
b, _ := nc.ReadBytes(1536)
b.Recycle()
return nil
return err
}
func validateClient(C1 []byte) (scheme int, challenge []byte, digest []byte, ok bool, err error) {

View File

@@ -2,6 +2,7 @@ package rtmp
import (
"errors"
"m7s.live/m7s/v5/pkg"
"runtime"
"m7s.live/m7s/v5"
@@ -10,12 +11,28 @@ import (
type AVSender struct {
*NetConnection
ChunkHeader
errContinue bool
lastAbs uint32
}
func (av *AVSender) HandleAudio(frame *RTMPAudio) (err error) {
return av.SendFrame(&frame.RTMPData)
}
func (av *AVSender) HandleVideo(frame *RTMPVideo) (err error) {
return av.SendFrame(&frame.RTMPData)
}
func (av *AVSender) SendFrame(frame *RTMPData) (err error) {
// seq := frame.Sequence
payloadLen := frame.Size
if av.errContinue {
defer func() {
if err != nil {
err = pkg.ErrInterrupt
}
}()
}
if payloadLen == 0 {
err = errors.New("payload is empty")
// av.Error("payload is empty", zap.Error(err))
@@ -47,7 +64,7 @@ func (av *AVSender) SendFrame(frame *RTMPData) (err error) {
// if seq != frame.Sequence {
// return errors.New("sequence is not equal")
// }
return err
return
}
type RTMPReceiver struct {

View File

@@ -74,13 +74,15 @@ func NewNetConnection(conn net.Conn, logger *slog.Logger) (ret *NetConnection) {
tmpBuf: make(util.Buffer, 4),
chunkHeaderBuf: make(util.Buffer, 0, 20),
}
ret.mediaDataPool.ScalableMemoryAllocator = util.NewScalableMemoryAllocator(1024)
ret.mediaDataPool.ScalableMemoryAllocator = util.NewScalableMemoryAllocator(1 << util.MinPowerOf2)
ret.Info("new connection")
return
}
func (conn *NetConnection) Destroy() {
conn.Conn.Close()
conn.BufReader.Recycle()
conn.mediaDataPool.Recycle()
conn.Info("destroy connection")
}
func (conn *NetConnection) SendStreamID(eventType uint16, streamID uint32) (err error) {
return conn.SendMessage(RTMP_MSG_USER_CONTROL, &StreamIDMessage{UserControlMessage{EventType: eventType}, streamID})
@@ -141,13 +143,15 @@ func (conn *NetConnection) readChunk() (msg *Chunk, err error) {
return nil, errors.New("get chunk type error :" + err.Error())
}
msgLen := int(chunk.MessageLength)
if msgLen == 0 {
return nil, nil
}
var mem util.RecyclableMemory
if unRead := msgLen - chunk.bufLen; unRead < conn.readChunkSize {
mem, err = conn.ReadBytes(unRead)
} else {
mem, err = conn.ReadBytes(conn.readChunkSize)
}
mem.Recycle()
if err != nil {
return nil, err
}

View File

@@ -5,26 +5,28 @@ type NetStream struct {
StreamID uint32
}
func (ns *NetStream) CreateAudioSender() *AVSender {
func (ns *NetStream) CreateAudioSender(c bool) *AVSender {
var av AVSender
av.NetConnection = ns.NetConnection
av.ChunkStreamID = RTMP_CSID_AUDIO
av.MessageTypeID = RTMP_MSG_AUDIO
av.MessageStreamID = ns.StreamID
av.errContinue = c
return &av
}
func (ns *NetStream) CreateVideoSender() *AVSender {
func (ns *NetStream) CreateVideoSender(c bool) *AVSender {
var av AVSender
av.NetConnection = ns.NetConnection
av.ChunkStreamID = RTMP_CSID_VIDEO
av.MessageTypeID = RTMP_MSG_VIDEO
av.MessageStreamID = ns.StreamID
av.errContinue = c
return &av
}
func (ns *NetStream) CreateSender() (audio *AVSender, video *AVSender) {
return ns.CreateAudioSender(), ns.CreateVideoSender()
func (ns *NetStream) CreateSender(c bool) (audio *AVSender, video *AVSender) {
return ns.CreateAudioSender(c), ns.CreateVideoSender(c)
}
func (ns *NetStream) Response(tid uint64, code, level string) error {
@@ -63,7 +65,7 @@ func (ns *NetStream) BeginPlay(tid uint64) (err error) {
func (ns *NetStream) Close() error {
if ns.NetConnection != nil {
return ns.NetConnection.Close()
ns.NetConnection.Destroy()
}
return nil
}

View File

@@ -182,7 +182,7 @@ func (conf *WebRTCPlugin) Push_(w http.ResponseWriter, r *http.Request) {
if !publisher.PubAudio {
return
}
mem := util.NewScalableMemoryAllocator(1460 * 100)
mem := util.NewScalableMemoryAllocator(1 << 12)
defer mem.Recycle()
frame := &mrtp.RTPAudio{}
frame.RTPCodecParameters = &codecP
@@ -222,7 +222,7 @@ func (conf *WebRTCPlugin) Push_(w http.ResponseWriter, r *http.Request) {
return
}
var lastPLISent time.Time
mem := util.NewScalableMemoryAllocator(1460 * 100)
mem := util.NewScalableMemoryAllocator(1 << 12)
defer mem.Recycle()
frame := &mrtp.RTPVideo{}
frame.RTPCodecParameters = &codecP
@@ -432,23 +432,20 @@ func (conf *WebRTCPlugin) Play_(w http.ResponseWriter, r *http.Request) {
if videoSender == nil {
suber.SubVideo = false
}
go suber.Handle(m7s.SubscriberHandler{
OnAudio: func(frame *mrtp.RTPAudio) (err error) {
go m7s.PlayBlock(suber, func(frame *mrtp.RTPAudio) (err error) {
for _, p := range frame.Packets {
if err = audioTLSRTP.WriteRTP(p); err != nil {
return
}
}
return
},
OnVideo: func(frame *mrtp.RTPVideo) error {
}, func(frame *mrtp.RTPVideo) error {
for _, p := range frame.Packets {
if err := videoTLSRTP.WriteRTP(p); err != nil {
return err
}
}
return nil
},
})
}
conn.OnICECandidate(func(ice *ICECandidate) {

View File

@@ -1,6 +1,7 @@
package m7s
import (
"errors"
"reflect"
"sync"
"time"
@@ -17,6 +18,7 @@ const (
PublisherStateTrackAdded
PublisherStateSubscribed
PublisherStateWaitSubscriber
PublisherStateDisposed
)
type SpeedControl struct {
@@ -57,7 +59,7 @@ func (t *AVTracks) IsEmpty() bool {
func (t *AVTracks) CreateSubTrack(dataType reflect.Type) (track *AVTrack) {
track = NewAVTrack(dataType, t.AVTrack)
track.WrapIndex = len(t.Items)
track.WrapIndex = t.Length
t.Add(track)
return
}
@@ -70,12 +72,16 @@ type Publisher struct {
VideoTrack AVTracks
AudioTrack AVTracks
DataTrack *DataTrack
Subscribers map[*Subscriber]struct{} `json:"-" yaml:"-"`
Subscribers util.Collection[int, *Subscriber] `json:"-" yaml:"-"`
GOP int
baseTs time.Duration
lastTs time.Duration
}
func (p *Publisher) SubscriberRange(yield func(sub *Subscriber) bool) {
p.Subscribers.Range(yield)
}
func (p *Publisher) GetKey() string {
return p.StreamPath
}
@@ -118,27 +124,25 @@ func (p *Publisher) checkTimeout() (err error) {
return
}
func (p *Publisher) RemoveSubscriber(subscriber *Subscriber) (err error) {
func (p *Publisher) RemoveSubscriber(subscriber *Subscriber) {
p.Lock()
defer p.Unlock()
delete(p.Subscribers, subscriber)
p.Info("subscriber -1", "count", len(p.Subscribers))
if p.State == PublisherStateSubscribed && len(p.Subscribers) == 0 {
p.Subscribers.Remove(subscriber)
p.Info("subscriber -1", "count", p.Subscribers.Length)
if p.State == PublisherStateSubscribed && p.Subscribers.Length == 0 {
p.State = PublisherStateWaitSubscriber
if p.DelayCloseTimeout > 0 {
p.TimeoutTimer.Reset(p.DelayCloseTimeout)
}
}
return
}
func (p *Publisher) AddSubscriber(subscriber *Subscriber) (err error) {
func (p *Publisher) AddSubscriber(subscriber *Subscriber) {
p.Lock()
defer p.Unlock()
subscriber.Publisher = p
if _, ok := p.Subscribers[subscriber]; !ok {
p.Subscribers[subscriber] = struct{}{}
p.Info("subscriber +1", "count", len(p.Subscribers))
if p.Subscribers.AddUnique(subscriber) {
p.Info("subscriber +1", "count", p.Subscribers.Length)
switch p.State {
case PublisherStateTrackAdded, PublisherStateWaitSubscriber:
p.State = PublisherStateSubscribed
@@ -147,7 +151,6 @@ func (p *Publisher) AddSubscriber(subscriber *Subscriber) (err error) {
}
}
}
return
}
func (p *Publisher) writeAV(t *AVTrack, data IAVFrame) {
@@ -179,11 +182,11 @@ func (p *Publisher) WriteVideo(data IAVFrame) (err error) {
}
t := p.VideoTrack.AVTrack
if t == nil {
t = NewAVTrack(data, p.Logger.With("track", "video"), 50)
t = NewAVTrack(data, p.Logger.With("track", "video"), 100)
p.Lock()
p.VideoTrack.AVTrack = t
p.VideoTrack.Add(t)
if len(p.Subscribers) > 0 {
if p.Subscribers.Length > 0 {
p.State = PublisherStateSubscribed
} else {
p.State = PublisherStateTrackAdded
@@ -294,7 +297,7 @@ func (p *Publisher) WriteAudio(data IAVFrame) (err error) {
p.Lock()
p.AudioTrack.AVTrack = t
p.AudioTrack.Add(t)
if len(p.Subscribers) > 0 {
if p.Subscribers.Length > 0 {
p.State = PublisherStateSubscribed
} else {
p.State = PublisherStateTrackAdded
@@ -319,7 +322,7 @@ func (p *Publisher) WriteData(data IDataFrame) (err error) {
p.DataTrack = &DataTrack{}
p.DataTrack.Logger = p.Logger.With("track", "data")
p.Lock()
if len(p.Subscribers) > 0 {
if p.Subscribers.Length > 0 {
p.State = PublisherStateSubscribed
} else {
p.State = PublisherStateTrackAdded
@@ -354,6 +357,25 @@ func (p *Publisher) GetVideoTrack(dataType reflect.Type) (t *AVTrack) {
return
}
func (p *Publisher) Dispose(err error) {
p.Lock()
defer p.Unlock()
if p.State == PublisherStateDisposed {
return
}
if !errors.Is(p.StopReason(), ErrKick) && p.IsStopped() {
if !p.AudioTrack.IsEmpty() {
p.AudioTrack.Dispose()
}
if !p.VideoTrack.IsEmpty() {
p.VideoTrack.Dispose()
}
p.State = PublisherStateDisposed
return
}
p.Stop(err)
}
func (p *Publisher) TakeOver(old *Publisher) {
p.baseTs = old.lastTs
p.VideoTrack = old.VideoTrack
@@ -363,7 +385,10 @@ func (p *Publisher) TakeOver(old *Publisher) {
p.AudioTrack.ICodecCtx = nil
p.AudioTrack.Logger = p.Logger.With("track", "audio")
p.DataTrack = old.DataTrack
p.Subscribers = old.Subscribers
for subscriber := range old.SubscriberRange {
p.AddSubscriber(subscriber)
}
old.Subscribers = util.Collection[int, *Subscriber]{}
// for _, track := range p.TransTrack {
// track.ICodecCtx = nil
// }

View File

@@ -51,7 +51,7 @@ type Server struct {
Streams util.Collection[string, *Publisher]
Pulls util.Collection[string, *Puller]
Pushs util.Collection[string, *Pusher]
Waiting map[string][]*Subscriber
Waiting util.Collection[string, *Publisher]
Subscribers util.Collection[int, *Subscriber]
LogHandler MultiLogHandler
pidG int
@@ -68,7 +68,6 @@ type Server struct {
func NewServer() (s *Server) {
s = &Server{
ID: int(serverIndexG.Add(1)),
Waiting: make(map[string][]*Subscriber),
eventChan: make(chan any, 10),
}
s.config.HTTP.ListenAddrTLS = ":8443"
@@ -94,7 +93,6 @@ type rawconfig = map[string]map[string]any
func (s *Server) reset() {
server := Server{
ID: s.ID,
Waiting: make(map[string][]*Subscriber),
eventChan: make(chan any, 10),
}
server.Logger = s.Logger
@@ -222,13 +220,13 @@ func (s *Server) run(ctx context.Context, conf any) (err error) {
s.eventLoop()
err = context.Cause(s)
s.Warn("Server is done", "reason", err)
for _, publisher := range s.Streams.Items {
for publisher := range s.Streams.Range {
publisher.Stop(err)
}
for _, subscriber := range s.Subscribers.Items {
for subscriber := range s.Subscribers.Range {
subscriber.Stop(err)
}
for _, p := range s.Plugins.Items {
for p := range s.Plugins.Range {
p.Stop(err)
}
httpConf.StopListen()
@@ -269,13 +267,21 @@ func (s *Server) eventLoop() {
case <-s.Done():
return
case <-pulse.C:
for _, publisher := range s.Streams.Items {
for publisher := range s.Streams.Range {
if err := publisher.checkTimeout(); err != nil {
publisher.Stop(err)
}
}
for subscriber := range s.Waiting {
for _, sub := range s.Waiting[subscriber] {
for publisher := range s.Waiting.Range {
if publisher.Plugin != nil {
if err := publisher.checkTimeout(); err != nil {
publisher.Dispose(err)
newPublisher := &Publisher{}
newPublisher.StreamPath = publisher.StreamPath
s.Waiting.Set(newPublisher)
}
}
for sub := range publisher.SubscriberRange {
select {
case <-sub.TimeoutTimer.C:
sub.Stop(ErrSubscribeTimeout)
@@ -347,7 +353,7 @@ func (s *Server) eventLoop() {
case slog.Handler:
s.LogHandler.Add(v)
}
for _, plugin := range s.Plugins.Items {
for plugin := range s.Plugins.Range {
if plugin.Disabled {
continue
}
@@ -363,7 +369,7 @@ func (s *Server) onUnsubscribe(subscriber *Subscriber) {
if subscriber.Closer != nil {
subscriber.Close()
}
for _, pusher := range s.Pushs.Items {
for pusher := range s.Pushs.Range {
if &pusher.Subscriber == subscriber {
s.Pushs.Remove(pusher)
break
@@ -372,25 +378,17 @@ func (s *Server) onUnsubscribe(subscriber *Subscriber) {
if subscriber.Publisher != nil {
subscriber.Publisher.RemoveSubscriber(subscriber)
}
if subscribers, ok := s.Waiting[subscriber.StreamPath]; ok {
if index := slices.Index(subscribers, subscriber); index >= 0 {
s.Waiting[subscriber.StreamPath] = slices.Delete(subscribers, index, index+1)
if len(subscribers) == 1 {
delete(s.Waiting, subscriber.StreamPath)
}
}
}
}
func (s *Server) onUnpublish(publisher *Publisher) {
s.Streams.Remove(publisher)
s.Waiting.Add(publisher)
s.Info("unpublish", "streamPath", publisher.StreamPath, "count", s.Streams.Length)
for subscriber := range publisher.Subscribers {
s.Waiting[publisher.StreamPath] = append(s.Waiting[publisher.StreamPath], subscriber)
for subscriber := range publisher.SubscriberRange {
subscriber.TimeoutTimer.Reset(publisher.WaitCloseTimeout)
}
if publisher.Closer != nil {
publisher.Close()
_ = publisher.Close()
}
s.Pulls.RemoveByKey(publisher.StreamPath)
}
@@ -401,12 +399,9 @@ func (s *Server) OnPublish(publisher *Publisher) error {
publisher.Warn("kick")
oldPublisher.Stop(ErrKick)
publisher.TakeOver(oldPublisher)
oldPublisher.Subscribers = nil
} else {
return ErrStreamExist
}
} else {
publisher.Subscribers = make(map[*Subscriber]struct{})
}
s.Streams.Set(publisher)
s.pidG++
@@ -415,14 +410,15 @@ func (s *Server) OnPublish(publisher *Publisher) error {
publisher.Logger = p.With("streamPath", publisher.StreamPath, "puber", publisher.ID)
publisher.TimeoutTimer = time.NewTimer(p.config.PublishTimeout)
publisher.Info("publish")
if subscribers, ok := s.Waiting[publisher.StreamPath]; ok {
for i, subscriber := range subscribers {
if i == 0 && subscriber.Publisher != nil {
publisher.TakeOver(subscriber.Publisher)
}
if waiting, ok := s.Waiting.Get(publisher.StreamPath); ok {
if waiting.Plugin != nil {
publisher.TakeOver(waiting)
} else {
for subscriber := range waiting.SubscriberRange {
publisher.AddSubscriber(subscriber)
}
delete(s.Waiting, publisher.StreamPath)
}
s.Waiting.Remove(waiting)
}
return nil
}
@@ -435,9 +431,13 @@ func (s *Server) OnSubscribe(subscriber *Subscriber) error {
s.Subscribers.Add(subscriber)
subscriber.Info("subscribe")
if publisher, ok := s.Streams.Get(subscriber.StreamPath); ok {
return publisher.AddSubscriber(subscriber)
publisher.AddSubscriber(subscriber)
} else if publisher, ok = s.Waiting.Get(subscriber.StreamPath); ok {
publisher.AddSubscriber(subscriber)
} else {
s.Waiting[subscriber.StreamPath] = append(s.Waiting[subscriber.StreamPath], subscriber)
newPublisher := &Publisher{}
newPublisher.StreamPath = subscriber.StreamPath
newPublisher.AddSubscriber(subscriber)
}
return nil
}
@@ -448,7 +448,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}
fmt.Fprintf(w, "visit:%s\nMonibuca Engine %s StartTime:%s\n", r.URL.Path, Version, s.StartTime)
for _, plugin := range s.Plugins.Items {
for plugin := range s.Plugins.Range {
fmt.Fprintf(w, "Plugin %s Version:%s\n", plugin.Meta.Name, plugin.Meta.Version)
}
for _, api := range s.apiList {

View File

@@ -2,6 +2,7 @@ package m7s
import (
"context"
"errors"
"io"
"net"
"net/url"
@@ -70,11 +71,6 @@ type Subscriber struct {
VideoReader *AVRingReader
}
type SubscriberHandler struct {
OnAudio any
OnVideo any
}
func (s *Subscriber) OnVideoFrame(yield func(*AVFrame) bool) {
if !s.SubVideo || s.Publisher == nil {
return
@@ -169,24 +165,24 @@ func HandleVideo[T IAVFrame](s *Subscriber) func(func(T) bool) {
}
}
func (s *Subscriber) Handle(handler SubscriberHandler) {
func PlayBlock[A any, V any](s *Subscriber, onAudio func(A) error, onVideo func(V) error) {
var ar, vr *AVRingReader
var ah, vh reflect.Value
var a1, v1 reflect.Type
var at, vt *AVTrack
var awi, vwi int
var startAudioTs, startVideoTs time.Duration
var initState = 0
var prePublisher *Publisher
var subMode = s.SubMode //订阅模式
if s.Args.Has(s.SubModeArgName) {
subMode, _ = strconv.Atoi(s.Args.Get(s.SubModeArgName))
}
var audioFrame, videoFrame *AVFrame
if handler.OnAudio != nil && s.SubAudio {
a1 = reflect.TypeOf(handler.OnAudio).In(0)
if s.SubAudio {
a1 = reflect.TypeOf(onAudio).In(0)
}
if handler.OnVideo != nil && s.SubVideo {
v1 = reflect.TypeOf(handler.OnVideo).In(0)
if s.SubVideo {
v1 = reflect.TypeOf(onVideo).In(0)
}
createAudioReader := func() {
if s.Publisher == nil || a1 == nil {
@@ -204,9 +200,9 @@ func (s *Subscriber) Handle(handler SubscriberHandler) {
if at != nil {
ar = NewAVRingReader(at)
s.AudioReader = ar
ar.StartTs = startAudioTs
ar.Logger = s.Logger.With("reader", a1.String())
ar.Info("start read")
ah = reflect.ValueOf(handler.OnAudio)
}
}
createVideoReader := func() {
@@ -224,14 +220,15 @@ func (s *Subscriber) Handle(handler SubscriberHandler) {
}
if vt != nil {
vr = NewAVRingReader(vt)
vr.StartTs = startVideoTs
s.VideoReader = vr
vr.Logger = s.Logger.With("reader", v1.String())
vr.Info("start read")
vh = reflect.ValueOf(handler.OnVideo)
}
}
createAudioReader()
createVideoReader()
prePublisher = s.Publisher
defer func() {
if ar != nil {
ar.StopRead()
@@ -240,22 +237,18 @@ func (s *Subscriber) Handle(handler SubscriberHandler) {
vr.StopRead()
}
}()
inputs := make([]reflect.Value, 1)
sendAudioFrame := func() (err error) {
if awi >= 0 {
if s.Enabled(s, TraceLevel) {
s.Trace("send audio frame", "seq", audioFrame.Sequence)
}
inputs[0] = reflect.ValueOf(audioFrame.Wraps[awi])
err = onAudio(audioFrame.Wraps[awi].(A))
} else {
inputs[0] = reflect.ValueOf(audioFrame)
err = onAudio(any(audioFrame).(A))
}
res := ah.Call(inputs)
if len(res) > 0 && !res[0].IsNil() {
if err := res[0].Interface().(error); err != ErrInterrupt {
if err != nil && !errors.Is(err, ErrInterrupt) {
s.Stop(err)
}
}
audioFrame = nil
return
}
@@ -264,19 +257,31 @@ func (s *Subscriber) Handle(handler SubscriberHandler) {
if s.Enabled(s, TraceLevel) {
s.Trace("send video frame", "seq", videoFrame.Sequence, "data", videoFrame.Wraps[vwi].String(), "size", videoFrame.Wraps[vwi].GetSize())
}
inputs[0] = reflect.ValueOf(videoFrame.Wraps[vwi])
err = onVideo(videoFrame.Wraps[vwi].(V))
} else {
inputs[0] = reflect.ValueOf(videoFrame)
err = onVideo(any(videoFrame).(V))
}
res := vh.Call(inputs)
if len(res) > 0 && !res[0].IsNil() {
if err = res[0].Interface().(error); err != ErrInterrupt {
if err != nil && !errors.Is(err, ErrInterrupt) {
s.Stop(err)
}
}
videoFrame = nil
return
}
checkPublisherChange := func() {
if prePublisher != s.Publisher {
if ar != nil {
startAudioTs = time.Duration(ar.AbsTime) * time.Millisecond
ar.StopRead()
}
if vr != nil {
startVideoTs = time.Duration(vr.AbsTime) * time.Millisecond
vr.StopRead()
}
createAudioReader()
createVideoReader()
prePublisher = s.Publisher
}
}
var err error
for err == nil {
err = s.Err()
@@ -297,7 +302,7 @@ func (s *Subscriber) Handle(handler SubscriberHandler) {
vr.LastCodecCtx = vr.Track.ICodecCtx
if seqFrame := vr.Track.SequenceFrame; seqFrame != nil {
s.Debug("video codec changed", "data", seqFrame.String())
vh.Call([]reflect.Value{reflect.ValueOf(seqFrame)})
err = onVideo(seqFrame.(V))
}
}
if ar != nil {
@@ -315,6 +320,9 @@ func (s *Subscriber) Handle(handler SubscriberHandler) {
if !s.IFrameOnly || videoFrame.IDR {
err = sendVideoFrame()
}
if ar == nil {
break
}
}
} else {
createVideoReader()
@@ -347,7 +355,7 @@ func (s *Subscriber) Handle(handler SubscriberHandler) {
if ar.DecConfChanged() {
ar.LastCodecCtx = ar.Track.ICodecCtx
if seqFrame := ar.Track.SequenceFrame; seqFrame != nil {
ah.Call([]reflect.Value{reflect.ValueOf(seqFrame)})
err = onAudio(seqFrame.(A))
}
}
if vr != nil && videoFrame != nil {
@@ -365,5 +373,6 @@ func (s *Subscriber) Handle(handler SubscriberHandler) {
} else {
createAudioReader()
}
checkPublisherChange()
}
}