diff --git a/VqdSDK/libdrm.so.2 b/VqdSDK/libdrm.so.2 new file mode 100644 index 0000000..af37117 Binary files /dev/null and b/VqdSDK/libdrm.so.2 differ diff --git a/VqdSDK/libgomp.so.1 b/VqdSDK/libgomp.so.1 new file mode 100644 index 0000000..91f3964 Binary files /dev/null and b/VqdSDK/libgomp.so.1 differ diff --git a/VqdSDK/libva-drm.so.1 b/VqdSDK/libva-drm.so.1 new file mode 100644 index 0000000..59e0dc1 Binary files /dev/null and b/VqdSDK/libva-drm.so.1 differ diff --git a/VqdSDK/libva.so.1 b/VqdSDK/libva.so.1 new file mode 100644 index 0000000..1eb9403 Binary files /dev/null and b/VqdSDK/libva.so.1 differ diff --git a/check_tip.h264 b/check_tip.h264 new file mode 100644 index 0000000..6e4c3a5 Binary files /dev/null and b/check_tip.h264 differ diff --git a/internal/app/wire_gen.go b/internal/app/wire_gen.go index 83c74d8..7541b45 100644 --- a/internal/app/wire_gen.go +++ b/internal/app/wire_gen.go @@ -11,7 +11,7 @@ import ( "easyvqd/internal/conf" "easyvqd/internal/core/host" "easyvqd/internal/core/media" - "easyvqd/internal/core/vqdsdk" + "easyvqd/internal/core/vqdtask" "easyvqd/internal/data" "easyvqd/internal/web/api" "log/slog" @@ -30,7 +30,7 @@ func WireApp(bc *conf.Bootstrap, log *slog.Logger) (http.Handler, func(), error) vqdTaskCore := api.NewVqdTaskCore(db) hostCore := host.NewCore(bc) mediaCore := media.NewCore(hostCore) - vqdSdkCore := vqdsdk.NewCore(hostCore, vqdTaskCore, bc) + vqdSdkCore := vqdtask.NewCore(hostCore, vqdTaskCore, bc) vqdTaskAPI := api.NewVqdTaskAPI(vqdTaskCore, mediaCore,vqdSdkCore,hostCore, bc) usecase := &api.Usecase{ @@ -45,6 +45,6 @@ func WireApp(bc *conf.Bootstrap, log *slog.Logger) (http.Handler, func(), error) } handler := api.NewHTTPHandler(usecase) return handler, func() { - //mediaCore.Close() + vqdSdkCore.UnVqdTask() }, nil } diff --git a/internal/core/host/core.go b/internal/core/host/core.go index bcaaee1..1ec129c 100644 --- a/internal/core/host/core.go +++ b/internal/core/host/core.go @@ -1,7 +1,6 @@ package host import ( - "context" "easyvqd/internal/conf" "easyvqd/pkg/pluginheart" "encoding/json" @@ -12,10 +11,12 @@ import ( "git.lnton.com/lnton/pluginsdk/pkg/plugin" ) +type IFrameResultCB func(string, []byte, int) type Core struct { Plugin *plugin.PluginSDK // 用于业务GRPC通信 HttpPlugin *pluginheart.Engine // 用于插件管理HTTP通信 RtspConfig *ConfigBaseOutput + CbIFrame IFrameResultCB } var StartOk chan struct{} @@ -45,29 +46,33 @@ func NewCore(cfg *conf.Bootstrap) *Core { }, false) }() - c := &Core{ + core := &Core{ Plugin: sdk, HttpPlugin: engine, } - - sdk.AddResponseHandler("stop", c.stop) - sdk.AddResponseHandler("ping", c.ping) + sdk.AddResponseHandler("stop", core.stop) + sdk.AddResponseHandler("ping", core.ping) // 这部分都是收到响应后的回调 - sdk.AddResponseHandler("findDevices", c.findDevicesRespH) - sdk.AddResponseHandler("findChannels", c.findChannelsRespH) - sdk.AddResponseHandler("getBaseConfig", c.getBaseConfigRespH) - sdk.AddResponseHandler("findTalkUrl", c.findTalkUrlRespH) - - config, err := c.GetBaseConfig(context.TODO(), &ConfigBaseInput{Mode: "rtsp"}) - if err != nil { - panic(err) - } + sdk.AddResponseHandler("findDevices", core.findDevicesRespH) + sdk.AddResponseHandler("findChannels", core.findChannelsRespH) + sdk.AddResponseHandler("getBaseConfig", core.getBaseConfigRespH) + sdk.AddResponseHandler("findTalkUrl", core.findTalkUrlRespH) + sdk.AddResponseHandler("iframeData", core.iframeDataRespH) + // 响应主机下发的 "iframeData" 命令 + sdk.AddRequestHandler("iframeData", core.iframeDataReqH) // defer sdk.Close() - return &Core{ - Plugin: sdk, - RtspConfig: config, + return core +} + +func (c *Core) iframeDataReqH(requestID string, args json.RawMessage) (interface{}, error) { + //slog.Debug("Received 'iframeData' from host", "request_id", requestID, "args", args) + out := IframeOutput{} + if err := json.Unmarshal(args, &out); err != nil { + return nil, nil } + c.CbIFrame(out.StreamName, out.Data, out.Codes) + return nil, nil } func (c Core) stop(requestID string, args json.RawMessage) (interface{}, error) { @@ -76,6 +81,7 @@ func (c Core) stop(requestID string, args json.RawMessage) (interface{}, error) } func (c Core) ping(requestID string, args json.RawMessage) (interface{}, error) { + slog.Debug("Received 'ping' from host", "request_id", requestID, "args", args) return nil, nil } @@ -96,3 +102,7 @@ func (c Core) findTalkUrlRespH(requestID string, args json.RawMessage) (interfac slog.Debug("Received 'findTalkUrl' from host", "request_id", requestID, "args", args) return nil, nil } +func (c Core) iframeDataRespH(requestID string, args json.RawMessage) (interface{}, error) { + slog.Debug("Received 'iframeData' from host", "request_id", requestID, "args", args) + return nil, nil +} diff --git a/internal/core/host/iframe.go b/internal/core/host/iframe.go new file mode 100644 index 0000000..43dfdef --- /dev/null +++ b/internal/core/host/iframe.go @@ -0,0 +1,9 @@ +package host + +type IframeOutput struct { + ServerId string `json:"server_id"` + ServerAddr string `json:"server_addr"` + StreamName string `json:"stream_name,omitempty"` + Data []byte `json:"data"` + Codes int `json:"codes"` +} diff --git a/internal/core/vqd/core.go b/internal/core/vqd/core.go index a74a08d..a9e00d5 100644 --- a/internal/core/vqd/core.go +++ b/internal/core/vqd/core.go @@ -6,6 +6,7 @@ type Storer interface { VqdTask() VqdTaskStorer VqdAlarm() VqdAlarmStorer VqdTaskTemplate() VqdTaskTemplateStorer + VqdTimeTemplate() VqdTimeTemplateStorer } // Core diff --git a/internal/core/vqd/model.go b/internal/core/vqd/model.go index f598ca8..acc0a75 100644 --- a/internal/core/vqd/model.go +++ b/internal/core/vqd/model.go @@ -18,13 +18,13 @@ const ( type VqdTask struct { orm.Model - Name string `gorm:"column:name;notNull;default:'';comment:名称" json:"name"` // 名称 - ChannelID string `gorm:"column:channel_id;notNull;default:'';comment:关联通道" json:"channel_id"` // 关联通道 - ChannelName string `gorm:"column:channel_name;notNull;default:'';comment:关联通道名称" json:"channel_name"` // 关联通道名称 - TaskTemplateID int64 `gorm:"column:task_template_id;notNull;default:0;comment:关联模板" json:"task_template_id"` //关联模板 - TaskTemplateName string `gorm:"column:task_template_name;notNull;default:0;comment:关联模板名称" json:"task_template_name"` //关联模板名称 - Enable bool `gorm:"column:enable;notNull;default:FALSE;comment:启用" json:"enable"` // 启用 - Des string `gorm:"column:des;notNull;default:'';comment:描述" json:"des"` // 描述 + Name string `gorm:"column:name;notNull;default:'';comment:名称" json:"name"` // 名称 + ChannelID string `gorm:"column:channel_id;notNull;default:'';comment:关联通道" json:"channel_id"` // 关联通道 + ChannelName string `gorm:"column:channel_name;notNull;default:'';comment:关联通道名称" json:"channel_name"` // 关联通道名称 + TaskTemplateID int64 `gorm:"column:task_template_id;notNull;default:0;comment:关联模板" json:"task_template_id"` // 关联模板 + TimeTemplateID int64 `gorm:"column:time_template_id;notNull;default:0;comment:关联计划" json:"time_template_id"` // 关联计划 + Enable bool `gorm:"column:enable;notNull;default:FALSE;comment:启用" json:"enable"` // 启用 + Des string `gorm:"column:des;notNull;default:'';comment:描述" json:"des"` // 描述 } // TableName database table name @@ -217,8 +217,6 @@ func (i *VqdFlower) Scan(input interface{}) error { type VqdTaskTemplate struct { orm.Model Name string `gorm:"column:name;notNull;default:'';comment:名称" json:"name"` - Plans string `gorm:"column:plans;notNull;default:'';comment:计划" json:"plans"` - Enable bool `gorm:"column:enable;notNull;default:TRUE;comment:是否启用" json:"enable"` IsDefault bool `gorm:"column:is_default;notNull;default:FALSE;comment:是否默认" json:"is_default"` VqdConfig VqdConfig `gorm:"column:vqd_config;type:jsonb;notNull;default:'{}';comment:诊断基础配置" json:"vqd_config"` // 诊断基础配置 VqdLgtDark VqdLgtDark `gorm:"column:vqd_lgt_dark;type:jsonb;notNull;default:'{}';comment:亮度检测" json:"vqd_lgt_dark"` // 亮度检测 @@ -240,6 +238,20 @@ func (*VqdTaskTemplate) TableName() string { return "vqd_task_template" } +type VqdTimeTemplate struct { + orm.Model + Name string `gorm:"column:name;notNull;default:'';comment:名称" json:"name"` + Plans string `gorm:"column:plans;notNull;default:'';comment:计划" json:"plans"` + Enable bool `gorm:"column:enable;notNull;default:TRUE;comment:是否启用" json:"enable"` + IsDefault bool `gorm:"column:is_default;notNull;default:FALSE;comment:是否默认" json:"is_default"` + Des string `gorm:"column:des;notNull;default:'';comment:描述" json:"des"` // 描述 +} + +// TableName database table name +func (*VqdTimeTemplate) TableName() string { + return "vqd_time_template" +} + type VqdAlarm struct { orm.Model AlarmName string `gorm:"column:alarm_name;notNull;default:'';comment:告警名称" json:"alarm_name"` // 告警名称 diff --git a/internal/core/vqd/store/audioencodedb/db.go b/internal/core/vqd/store/audioencodedb/db.go index e641f34..03a32cd 100644 --- a/internal/core/vqd/store/audioencodedb/db.go +++ b/internal/core/vqd/store/audioencodedb/db.go @@ -24,6 +24,9 @@ func (d DB) VqdTask() vqd.VqdTaskStorer { func (d DB) VqdTaskTemplate() vqd.VqdTaskTemplateStorer { return VqdTaskTemplate(d) } +func (d DB) VqdTimeTemplate() vqd.VqdTimeTemplateStorer { + return VqdTimeTemplate(d) +} func (d DB) VqdAlarm() vqd.VqdAlarmStorer { return VqdAlarm(d) } @@ -36,6 +39,7 @@ func (d DB) AutoMigrate(ok bool) DB { if err := d.db.AutoMigrate( new(vqd.VqdTask), new(vqd.VqdTaskTemplate), + new(vqd.VqdTimeTemplate), new(vqd.VqdAlarm), ); err != nil { panic(err) diff --git a/internal/core/vqd/store/audioencodedb/vqdtimetemplate.go b/internal/core/vqd/store/audioencodedb/vqdtimetemplate.go new file mode 100644 index 0000000..53dcfc2 --- /dev/null +++ b/internal/core/vqd/store/audioencodedb/vqdtimetemplate.go @@ -0,0 +1,60 @@ +// Code generated by gowebx, DO AVOID EDIT. +package audioencodedb + +import ( + "context" + "easyvqd/internal/core/vqd" + "git.lnton.com/lnton/pkg/orm" +) + +var _ vqd.VqdTimeTemplateStorer = VqdTimeTemplate{} + +// VqdTimeTemplate Related business namespaces +type VqdTimeTemplate DB + +// FindAll implements vqd.VqdTimeTemplateStorer. +func (d VqdTimeTemplate) FindAll(bs *[]*vqd.VqdTimeTemplate) (int64, error) { + db := d.db.Model(&vqd.VqdTimeTemplate{}) + var total int64 + if err := db.Count(&total).Error; err != nil || total <= 0 { + // 如果统计失败或者数量为0,则返回错误 + return 0, err + } + return total, db.Find(bs).Error +} + +// Find implements vqd.VqdTimeTemplateStorer. +func (d VqdTimeTemplate) Find(ctx context.Context, bs *[]*vqd.VqdTimeTemplate, page orm.Pager, opts ...orm.QueryOption) (int64, error) { + return orm.FindWithContext(ctx, d.db, bs, page, opts...) +} + +// Get implements vqd.VqdTimeTemplateStorer. +func (d VqdTimeTemplate) Get(ctx context.Context, model *vqd.VqdTimeTemplate, opts ...orm.QueryOption) error { + return orm.FirstWithContext(ctx, d.db, model, opts...) +} + +// Add implements vqd.VqdTimeTemplateStorer. +func (d VqdTimeTemplate) Add(ctx context.Context, model *vqd.VqdTimeTemplate) error { + return d.db.WithContext(ctx).Create(model).Error +} + +// Edit implements vqd.VqdTimeTemplateStorer. +func (d VqdTimeTemplate) Edit(ctx context.Context, model *vqd.VqdTimeTemplate, changeFn func(*vqd.VqdTimeTemplate), opts ...orm.QueryOption) error { + return orm.UpdateWithContext(ctx, d.db, model, changeFn, opts...) +} + +// Del implements vqd.VqdTimeTemplateStorer. +func (d VqdTimeTemplate) Del(ctx context.Context, model *vqd.VqdTimeTemplate, opts ...orm.QueryOption) error { + return orm.DeleteWithContext(ctx, d.db, model, opts...) +} + +// EditStatus implements vqd.VqdTimeTemplateStorer. +func (d VqdTimeTemplate) EditStatus(status vqd.EncodeStatus, id int) error { + if err := d.db.Model(&vqd.VqdTimeTemplate{}).Where(`id = ?`, id).Update("encode_status", status).Error; err != nil { + return err + } + return nil +} +func (d VqdTimeTemplate) FirstOrCreate(b any) error { + return d.db.FirstOrCreate(b).Error +} diff --git a/internal/core/vqd/vqdtask.param.go b/internal/core/vqd/vqdtask.param.go index 122829e..9304a53 100644 --- a/internal/core/vqd/vqdtask.param.go +++ b/internal/core/vqd/vqdtask.param.go @@ -11,21 +11,21 @@ type FindVqdTaskInput struct { } type EditVqdTaskInput struct { - Name string `json:"name"` // 名称 - ChannelID string `json:"channel_id"` // 关联通道 - ChannelName string `json:"channel_name"` // 通道名称 - TaskTemplateID int `json:"task_template_id"` // 关联模板 - TaskTemplateName string `json:"task_template_name"` // 模板名称 - Enable bool `form:"enable"` // 启用 - Des string `json:"des"` // 描述 + Name string `json:"name"` // 名称 + ChannelID string `json:"channel_id"` // 关联通道 + ChannelName string `json:"channel_name"` // 通道名称 + TaskTemplateID int `json:"task_template_id"` // 关联模板 + TimeTemplateID int `json:"time_template_id"` // 关联计划 + Enable bool `form:"enable"` // 启用 + Des string `json:"des"` // 描述 } type AddVqdTaskInput struct { - Name string `json:"name"` // 名称 - ChannelID string `json:"channel_id"` // 关联通道 - ChannelName string `json:"channel_name"` // 通道名称 - TaskTemplateID int `json:"task_template_id"` // 关联模板 - TaskTemplateName string `json:"task_template_name"` // 模板名称 - Enable bool `form:"enable"` // 启用 - Des string `json:"des"` // 描述 + Name string `json:"name"` // 名称 + ChannelID string `json:"channel_id"` // 关联通道 + ChannelName string `json:"channel_name"` // 通道名称 + TaskTemplateID int `json:"task_template_id"` // 关联模板 + TimeTemplateID int `json:"time_template_id"` // 关联计划 + Enable bool `form:"enable"` // 启用 + Des string `json:"des"` // 描述 } diff --git a/internal/core/vqd/vqdtasktemplate.go b/internal/core/vqd/vqdtasktemplate.go index bd11ada..4697b38 100644 --- a/internal/core/vqd/vqdtasktemplate.go +++ b/internal/core/vqd/vqdtasktemplate.go @@ -83,7 +83,7 @@ func (c Core) GetNameVqdTaskTemplate(ctx context.Context, name string) (*VqdTask } // FirstOrCreateTemplate Insert into database -func (c Core) FirstOrCreateTemplate(b any) error { +func (c Core) FirstOrCreateTaskTemplate(b any) error { return c.store.VqdTaskTemplate().FirstOrCreate(b) } diff --git a/internal/core/vqd/vqdtimetemplate.go b/internal/core/vqd/vqdtimetemplate.go new file mode 100644 index 0000000..af60e5e --- /dev/null +++ b/internal/core/vqd/vqdtimetemplate.go @@ -0,0 +1,122 @@ +// Code generated by gowebx, DO AVOID EDIT. +package vqd + +import ( + "context" + "git.lnton.com/lnton/pkg/orm" + "git.lnton.com/lnton/pkg/reason" + "github.com/jinzhu/copier" + "log/slog" +) + +// VqdTimeTemplateStorer Instantiation interface +type VqdTimeTemplateStorer interface { + Find(context.Context, *[]*VqdTimeTemplate, orm.Pager, ...orm.QueryOption) (int64, error) + FindAll(dp *[]*VqdTimeTemplate) (int64, error) + Get(context.Context, *VqdTimeTemplate, ...orm.QueryOption) error + Add(context.Context, *VqdTimeTemplate) error + Edit(context.Context, *VqdTimeTemplate, func(*VqdTimeTemplate), ...orm.QueryOption) error + Del(context.Context, *VqdTimeTemplate, ...orm.QueryOption) error + + FirstOrCreate(b any) error +} + +// FindVqdTimeTemplateAll Paginated search +func (c Core) FindVqdTimeTemplateAll() ([]*VqdTimeTemplate, int64, error) { + items := make([]*VqdTimeTemplate, 0) + total, err := c.store.VqdTimeTemplate().FindAll(&items) + if err != nil { + return nil, 0, reason.ErrDB.Withf(`Find err[%s]`, err.Error()) + } + return items, total, nil +} + +// FindVqdTimeTemplate Paginated search +func (c Core) FindVqdTimeTemplate(ctx context.Context, in *FindVqdTimeTemplateInput) ([]*VqdTimeTemplate, int64, error) { + items := make([]*VqdTimeTemplate, 0) + if in.Name != "" { + query := orm.NewQuery(8).Where("name like ? ", "%"+in.Name+"%") + total, err := c.store.VqdTimeTemplate().Find(ctx, &items, in, query.Encode()...) + if err != nil { + return nil, 0, reason.ErrDB.Withf(`Find err[%s]`, err.Error()) + } + return items, total, nil + } else { + total, err := c.store.VqdTimeTemplate().Find(ctx, &items, in) + if err != nil { + return nil, 0, reason.ErrDB.Withf(`Find err[%s]`, err.Error()) + } + return items, total, nil + } +} + +// GetVqdTimeTemplate Query a single object +func (c Core) GetVqdTimeTemplate(ctx context.Context, id int) (*VqdTimeTemplate, error) { + var out VqdTimeTemplate + if err := c.store.VqdTimeTemplate().Get(ctx, &out, orm.Where("id=?", id)); err != nil { + if orm.IsErrRecordNotFound(err) { + return nil, reason.ErrNotFound.Withf(`Get err[%s]`, err.Error()) + } + return nil, reason.ErrDB.Withf(`Get err[%s]`, err.Error()) + } + return &out, nil +} +func (c Core) GetIDVqdTimeTemplate(ctx context.Context, ID int64) (*VqdTimeTemplate, error) { + var out VqdTimeTemplate + if err := c.store.VqdTimeTemplate().Get(ctx, &out, orm.Where("id=?", ID)); err != nil { + if orm.IsErrRecordNotFound(err) { + return nil, reason.ErrNotFound.Withf(`Get err[%s]`, err.Error()) + } + return nil, reason.ErrDB.Withf(`Get err[%s]`, err.Error()) + } + return &out, nil +} +func (c Core) GetNameVqdTimeTemplate(ctx context.Context, name string) (*VqdTimeTemplate, error) { + var out VqdTimeTemplate + if err := c.store.VqdTimeTemplate().Get(ctx, &out, orm.Where("name=?", name)); err != nil { + if orm.IsErrRecordNotFound(err) { + return nil, reason.ErrNotFound.Withf(`Get err[%s]`, err.Error()) + } + return nil, reason.ErrDB.Withf(`Get err[%s]`, err.Error()) + } + return &out, nil +} + +// FirstOrCreateTemplate Insert into database +func (c Core) FirstOrCreateTimeTemplate(b any) error { + return c.store.VqdTimeTemplate().FirstOrCreate(b) +} + +// AddVqdTimeTemplate Insert into database +func (c Core) AddVqdTimeTemplate(ctx context.Context, in *AddVqdTimeTemplateInput) (*VqdTimeTemplate, error) { + var out VqdTimeTemplate + if err := copier.Copy(&out, in); err != nil { + slog.Error("Copy", "err", err) + } + if err := c.store.VqdTimeTemplate().Add(ctx, &out); err != nil { + return nil, reason.ErrDB.Withf(`Add err[%s]`, err.Error()) + } + return &out, nil +} + +// EditVqdTimeTemplate Update object information +func (c Core) EditVqdTimeTemplate(ctx context.Context, in *EditVqdTimeTemplateInput, id int) (*VqdTimeTemplate, error) { + var out VqdTimeTemplate + if err := c.store.VqdTimeTemplate().Edit(ctx, &out, func(b *VqdTimeTemplate) { + if err := copier.Copy(b, in); err != nil { + slog.Error("Copy", "err", err) + } + }, orm.Where("id=?", id)); err != nil { + return nil, reason.ErrDB.Withf(`Edit err[%s]`, err.Error()) + } + return &out, nil +} + +// DelVqdTimeTemplate Delete object +func (c Core) DelVqdTimeTemplate(ctx context.Context, id int) (*VqdTimeTemplate, error) { + var out VqdTimeTemplate + if err := c.store.VqdTimeTemplate().Del(ctx, &out, orm.Where("id=?", id)); err != nil { + return nil, reason.ErrDB.Withf(`Del err[%s]`, err.Error()) + } + return &out, nil +} diff --git a/internal/core/vqd/vqdtimetemplate.param.go b/internal/core/vqd/vqdtimetemplate.param.go new file mode 100644 index 0000000..46cd0b6 --- /dev/null +++ b/internal/core/vqd/vqdtimetemplate.param.go @@ -0,0 +1,25 @@ +// Code generated by gowebx, DO AVOID EDIT. +package vqd + +import ( + "git.lnton.com/lnton/pkg/web" +) + +type FindVqdTimeTemplateInput struct { + web.PagerFilter + Name string `form:"name"` // 名称 +} + +type EditVqdTimeTemplateInput struct { + Name string `json:"name"` + Plans string `json:"plans"` + Enable bool `json:"enable"` + Des string ` json:"des"` // 描述 +} + +type AddVqdTimeTemplateInput struct { + Name string `json:"name"` + Plans string `json:"plans"` + Enable bool `json:"enable"` + Des string ` json:"des"` // 描述 +} diff --git a/internal/core/vqdsdk/core.go b/internal/core/vqdsdk/core.go deleted file mode 100644 index 5892e26..0000000 --- a/internal/core/vqdsdk/core.go +++ /dev/null @@ -1,56 +0,0 @@ -package vqdsdk - -import ( - "context" - "easyvqd/internal/conf" - "easyvqd/internal/core/host" - "easyvqd/internal/core/vqd" - "time" -) - -type Core struct { - HostCore *host.Core - VqdTaskCore *vqd.Core - Cfg *conf.Bootstrap -} - -func NewCore(HostCore *host.Core, VqdTaskCore *vqd.Core, Cfg *conf.Bootstrap) *Core { - core := &Core{ - HostCore: HostCore, - VqdTaskCore: VqdTaskCore, - Cfg: Cfg, - } - time.AfterFunc(time.Duration(5)*time.Second, func() { - in := &vqd.AddVqdAlarmInput{ - AlarmName: "遮挡告警", - AlarmValue: "", - ChannelID: "", - ChannelName: "", - TaskTemplateID: 0, - TaskTemplateName: "", - TaskID: 0, - TaskName: "", - FilePath: "", - } - for i := 0; i < 40; i++ { - core.VqdTaskCore.AddVqdAlarm(context.TODO(), in) - } - - }) - // 启用定时清理任务 - core.scheduleCleanTask() - // 启用任务管理器 - return core -} - -// -//func OpenVqdTask(VqdTaskCore *vqd.Core) *Workflow { -// wf := NewWorkflow(WorkflowConfig{ -// MaxConcurrency: 100, // 并发 -// CleanupInterval: 30 * time.Second, // 每30秒清理一次 -// MaxTaskHistory: 500, // 最多保留500个任务历史 -// RetentionTime: 60 * time.Second, // 任务保留1分钟 -// }) -// -// return wf -//} diff --git a/internal/core/vqdsdk/mode.go b/internal/core/vqdsdk/mode.go deleted file mode 100644 index c703511..0000000 --- a/internal/core/vqdsdk/mode.go +++ /dev/null @@ -1 +0,0 @@ -package vqdsdk diff --git a/internal/core/vqdsdk/clean.go b/internal/core/vqdtask/clean.go similarity index 99% rename from internal/core/vqdsdk/clean.go rename to internal/core/vqdtask/clean.go index f7a07c8..7b37b08 100644 --- a/internal/core/vqdsdk/clean.go +++ b/internal/core/vqdtask/clean.go @@ -1,4 +1,4 @@ -package vqdsdk +package vqdtask import ( "fmt" diff --git a/internal/core/vqdtask/core.go b/internal/core/vqdtask/core.go new file mode 100644 index 0000000..40b7c7e --- /dev/null +++ b/internal/core/vqdtask/core.go @@ -0,0 +1,284 @@ +package vqdtask + +import ( + "bufio" + "easyvqd/internal/conf" + "easyvqd/internal/core/host" + "easyvqd/internal/core/vqd" + "easyvqd/pkg/vqdcms" + "fmt" + "log/slog" + "os" + "os/exec" + "path/filepath" + "strings" + "time" +) + +type Core struct { + HostCore *host.Core + VqdTaskCore *vqd.Core + Cfg *conf.Bootstrap +} + +var ( + VqdTaskMap = vqdcms.VqdTaskMap{M: make(map[string]*vqdcms.VQDHandle)} +) + +func NewCore(HostCore *host.Core, VqdTaskCore *vqd.Core, Cfg *conf.Bootstrap) *Core { + core := &Core{ + HostCore: HostCore, + VqdTaskCore: VqdTaskCore, + Cfg: Cfg, + } + core.HostCore.CbIFrame = func(s string, data []byte, codes int) { + //fmt.Println("res", s, codes, len(data)) + v, ok := VqdTaskMap.LoadTaskMap(s) + if ok { + v.SendData(data, codes) + } + } + + time.AfterFunc(time.Duration(5)*time.Second, func() { + //in := &vqd.AddVqdAlarmInput{ + // AlarmName: "遮挡告警", + // AlarmValue: "", + // ChannelID: "", + // ChannelName: "", + // TaskTemplateID: 0, + // TaskTemplateName: "", + // TaskID: 0, + // TaskName: "", + // FilePath: "", + //} + //for i := 0; i < 2; i++ { + // core.VqdTaskCore.AddVqdAlarm(context.TODO(), in) + //} + + // 启用诊断分析 + core.InitVqdTask() + core.AddTaskVqd(1, "PVWPQBPIv32UI_01") + }) + // 启用定时清理任务 + go core.scheduleCleanTask() + // 测试 + //go core.OpenStartVqd() + // 启用任务管理器 + return core +} + +func (c Core) InitVqdTask() { + err := vqdcms.VQDInit() + if err != nil { + slog.Error("vqd cms open", "err", err.Error()) + return + } + + return +} +func (c Core) UnVqdTask() { + vqdcms.VQDUnInit() + return +} +func (c Core) AddTaskVqd(taskId int, chnId string) { + cb := func(res vqdcms.AbnormalModel) { + fmt.Println("res", res) + } + para := vqdcms.NewVQDPara() + v := vqdcms.NewVQDHandle(cb, taskId, chnId).Create(para) + VqdTaskMap.StoreChildMap(fmt.Sprintf("%s", chnId), v) +} + +//func (c Core) OpenStartVqd() { +// +// err := vqdcms.VQDInit() +// if err != nil { +// fmt.Println("程序异常", err.Error()) +// return +// } +// dir, _ := os.Getwd() +// rootPath := filepath.Join(dir, "gbs_buf264") // 你的H.264裸流文件路径 +// +// v := vqdcms.NewVQDHandle(nil, 1) +// +// para := vqdcms.NewVQDPara() +// v.SetVQDConfig(para) +// v.Create(para) +// entries, err := os.ReadDir(rootPath) +// if err != nil { +// fmt.Printf("读取目录失败: %v\n", err) +// return +// } +// +// fmt.Printf("目录 %s 下的内容:\n", dir) +// for _, entry := range entries { +// if entry.IsDir() { +// fmt.Printf("[目录] %s\n", entry.Name()) +// } else { +// h264Paths := filepath.Join(rootPath, entry.Name()) // 你的H.264裸流文件路径 +// fmt.Println(h264Paths) +// data, err := os.ReadFile(h264Paths) +// if err == nil { +// datap := GetIFramePointer(data) +// width, height, buf, err := v.de.PushDataEx(uintptr(datap.Pointer), datap.Length, VIDEO_CODEC_H264) +// if err == nil { +// v.SendData(buf, width, height) +// slog.Info("I帧转YUV成功: ", "h264Paths", h264Paths) +// } else { +// //slog.Error("I帧转YUV失败: ", "h264Paths", h264Paths ) +// } +// } +// } +// } +// +// return +//} +// +//// H264IFrameData 封装I帧数据和指针信息 +//type H264IFrameData struct { +// Data []byte // I帧原始字节数据 +// Pointer unsafe.Pointer // 指向数据的原始指针 +// Length int // 数据长度(字节数) +// IsValid bool // 指针是否有效 +//} +// +//// GetIFramePointer 将字节切片转换为原始指针 +//// 注意:unsafe包的使用会绕过Go的内存安全检查,需谨慎 +//func GetIFramePointer(data []byte) *H264IFrameData { +// if len(data) == 0 { +// return &H264IFrameData{ +// IsValid: false, +// Length: 0, +// } +// } +// +// // 方式1:直接通过unsafe获取切片底层数组的指针(推荐,高效) +// // 切片的底层结构是:指向数组的指针 + 长度 + 容量 +// ptr := unsafe.Pointer(&data[0]) +// +// // 方式2:通过reflect获取指针(更直观展示切片结构,可选) +// // sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&data)) +// // ptr := unsafe.Pointer(sliceHeader.Data) +// +// return &H264IFrameData{ +// Data: data, +// Pointer: ptr, +// Length: len(data), +// IsValid: true, +// } +//} + +// 测试i帧数据是否可以转为图片文件 +func CheckIFramesToJpg() { + dir, _ := os.Getwd() + + h264Path := filepath.Join(dir, "check_tip.h264") // 你的H.264裸流文件路径 + //1. 检查FFmpeg + ok, err := CheckFFmpeg() + if !ok { + fmt.Println("错误:", err) + os.Exit(1) + } + + // 2. 配置参数(根据你的H.264文件调整) + + imageFormat := "jpg" // 输出图片格式 + videoWidth := 0 // 分辨率自动探测(如需指定则改为实际值,如1920) + videoHeight := 0 // 分辨率自动探测(如需指定则改为实际值,如1080) + + // 3. 提取H.264关键帧并转图片 + if err := ExtractH264KeyFrames(h264Path, dir, imageFormat, videoWidth, videoHeight); err != nil { + fmt.Println("提取H.264关键帧失败:", err) + os.Exit(1) + } +} + +// CheckFFmpeg 检查系统是否安装了FFmpeg +func CheckFFmpeg() (bool, error) { + cmd := exec.Command("ffmpeg", "-version") + err := cmd.Run() + if err != nil { + return false, fmt.Errorf("FFmpeg 未安装或未添加到系统PATH: %v", err) + } + return true, nil +} + +// ExtractH264KeyFrames 将H.264裸流的关键帧转为图片 +// h264Path: H.264裸流文件路径(.264/.h264) +// outputDir: 图片输出目录 +// format: 输出图片格式 (jpg/png) +// width/height: 视频分辨率(若不指定,FFmpeg会自动探测) +func ExtractH264KeyFrames(h264Path, outputDir, format string, width, height int) error { + // 验证输入文件 + if _, err := os.Stat(h264Path); os.IsNotExist(err) { + return fmt.Errorf("H.264文件不存在: %s", h264Path) + } + + // 创建输出目录 + if err := os.MkdirAll(outputDir, 0755); err != nil { + return fmt.Errorf("创建输出目录失败: %v", err) + } + + // 构造FFmpeg命令(适配H.264裸流) + outputPattern := filepath.Join(outputDir, "h264_keyframe_%04d."+format) + args := []string{ + "-f", "h264", // 明确输入格式为H.264裸流 + "-i", h264Path, // 输入H.264裸流文件 + "-skip_frame", "nokey", // 只处理关键帧(I帧) + "-vsync", "0", // 禁用帧同步,保证每个I帧都输出 + "-q:v", "2", // 图片质量(1-31,值越小质量越高) + } + + // 可选:指定分辨率(如果FFmpeg自动探测失败时使用) + if width > 0 && height > 0 { + args = append(args, "-s", fmt.Sprintf("%dx%d", width, height)) + } + + // 补全输出参数 + args = append(args, + "-f", "image2", // 输出图片序列格式 + outputPattern, // 输出文件模板 + "-y", // 覆盖已存在的文件 + ) + + // 创建命令并捕获输出 + cmd := exec.Command("ffmpeg", args...) + _, err := cmd.StdoutPipe() + if err != nil { + return fmt.Errorf("创建标准输出管道失败: %v", err) + } + stderr, err := cmd.StderrPipe() + if err != nil { + return fmt.Errorf("创建标准错误管道失败: %v", err) + } + + // 启动命令 + if err := cmd.Start(); err != nil { + return fmt.Errorf("启动FFmpeg失败: %v", err) + } + + // 实时打印FFmpeg日志(便于调试H.264解析问题) + scanner := bufio.NewScanner(stderr) + for scanner.Scan() { + line := scanner.Text() + fmt.Println("FFmpeg日志:", line) + // 捕获关键错误信息 + if strings.Contains(line, "error") && strings.Contains(line, "H.264") { + fmt.Println("⚠️ H.264解析警告:", line) + } + } + + // 等待命令执行完成 + if err := cmd.Wait(); err != nil { + return fmt.Errorf("FFmpeg执行失败: %v", err) + } + + // 统计输出的关键帧图片数量 + files, err := filepath.Glob(filepath.Join(outputDir, "h264_keyframe_*."+format)) + if err != nil { + return fmt.Errorf("统计输出图片失败: %v", err) + } + + fmt.Printf("成功从H.264裸流提取 %d 个关键帧,保存至: %s\n", len(files), outputDir) + return nil +} diff --git a/internal/core/vqdtask/mode.go b/internal/core/vqdtask/mode.go new file mode 100644 index 0000000..8888525 --- /dev/null +++ b/internal/core/vqdtask/mode.go @@ -0,0 +1,6 @@ +package vqdtask + +const ( + VIDEO_CODEC_H264 = 0x1C + VIDEO_CODEC_H265 = 0xAE +) diff --git a/internal/web/api/api.go b/internal/web/api/api.go index 95b33da..089bd47 100644 --- a/internal/web/api/api.go +++ b/internal/web/api/api.go @@ -163,9 +163,15 @@ type KV struct { func InitTemplate(uc *Usecase) error { cfg := uc.Conf - in := vqd.VqdTaskTemplate{ + inPlan := vqd.VqdTimeTemplate{ Enable: true, IsDefault: true, + } + inTemplate := vqd.VqdTaskTemplate{ + + Name: "默认", + Des: "默认诊断模板。", + IsDefault: true, VqdConfig: vqd.VqdConfig{ Enable: true, FrmNum: cfg.VqdConfig.FrmNum, @@ -230,32 +236,37 @@ func InitTemplate(uc *Usecase) error { MosaicThr: cfg.VqdFlower.MosaicThr, }, } - - in.Name = "每天" - in.Model.ID = 1 - in.Model.CreatedAt = orm.Time{Time: time.Now()} - in.Plans = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" - in.Des = "每天分析,启用全部分析模块。" - if err := uc.VqdTaskCore.FirstOrCreateTemplate(&in); err != nil { - slog.Error("FirstOrCreateTemplate", "err", err) + inTemplate.ID = 1 + inTemplate.Model.CreatedAt = orm.Time{Time: time.Now()} + if err := uc.VqdTaskCore.FirstOrCreateTaskTemplate(&inTemplate); err != nil { + slog.Error("FirstOrCreateTaskTemplate", "err", err) return err } - in.Name = "工作日" - in.Model.ID = 2 - in.Model.CreatedAt = orm.Time{Time: time.Now()} - in.Plans = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000" - in.Des = "工作日分析,启用全部分析模块。" - if err := uc.VqdTaskCore.FirstOrCreateTemplate(&in); err != nil { - slog.Error("FirstOrCreateTemplate", "err", err) + inPlan.Name = "每天" + inPlan.Model.ID = 1 + inPlan.Model.CreatedAt = orm.Time{Time: time.Now()} + inPlan.Plans = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + inPlan.Des = "每天分析" + if err := uc.VqdTaskCore.FirstOrCreateTimeTemplate(&inPlan); err != nil { + slog.Error("FirstOrCreateTimeTemplate", "err", err) return err } - in.Name = "双休日" - in.Model.ID = 3 - in.Model.CreatedAt = orm.Time{Time: time.Now()} - in.Plans = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111" - in.Des = "休息日分析,启用全部分析模块。" - if err := uc.VqdTaskCore.FirstOrCreateTemplate(&in); err != nil { - slog.Error("FirstOrCreateTemplate", "err", err) + inPlan.Name = "工作日" + inPlan.Model.ID = 2 + inPlan.Model.CreatedAt = orm.Time{Time: time.Now()} + inPlan.Plans = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000" + inPlan.Des = "工作日分析" + if err := uc.VqdTaskCore.FirstOrCreateTimeTemplate(&inPlan); err != nil { + slog.Error("FirstOrCreateTimeTemplate", "err", err) + return err + } + inPlan.Name = "双休日" + inPlan.Model.ID = 3 + inPlan.Model.CreatedAt = orm.Time{Time: time.Now()} + inPlan.Plans = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111" + inPlan.Des = "休息日分析" + if err := uc.VqdTaskCore.FirstOrCreateTimeTemplate(&inPlan); err != nil { + slog.Error("FirstOrCreateTimeTemplate", "err", err) return err } return nil diff --git a/internal/web/api/provider.go b/internal/web/api/provider.go index ae39f1e..cab51e8 100644 --- a/internal/web/api/provider.go +++ b/internal/web/api/provider.go @@ -5,7 +5,7 @@ import ( "easyvqd/internal/core/media" "easyvqd/internal/core/vqd" "easyvqd/internal/core/vqd/store/audioencodedb" - "easyvqd/internal/core/vqdsdk" + "easyvqd/internal/core/vqdtask" "net/http" "easyvqd/domain/uniqueid" @@ -41,7 +41,7 @@ type Usecase struct { VqdTaskAPI VqdTaskAPI HostCore *host.Core MediaCore *media.Core - VqdSdkCore *vqdsdk.Core + VqdSdkCore *vqdtask.Core } // NewHTTPHandler 生成Gin框架路由内容 diff --git a/internal/web/api/vqdalarm.go b/internal/web/api/vqdalarm.go index f018ade..1e14c9a 100644 --- a/internal/web/api/vqdalarm.go +++ b/internal/web/api/vqdalarm.go @@ -37,7 +37,7 @@ func (a VqdTaskAPI) getVqdAlarm(c *gin.Context, _ *struct{}) (any, error) { ID, _ := strconv.Atoi(c.Param("id")) item, err := a.core.GetVqdAlarm(c.Request.Context(), ID) if err != nil { - return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqd [%d] err [%s]`, ID, err.Error())) + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqdcms [%d] err [%s]`, ID, err.Error())) } row := make(map[string]interface{}) @@ -61,18 +61,18 @@ func (a VqdTaskAPI) delVqdAlarm(c *gin.Context, _ *struct{}) (any, error) { ID, _ := strconv.Atoi(c.Param("id")) _, err := a.core.DelVqdAlarm(c.Request.Context(), ID) if err != nil { - return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqd [%d] err [%s]`, ID, err.Error())) + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqdcms [%d] err [%s]`, ID, err.Error())) } return gin.H{"data": "OK!"}, err } func (a VqdTaskAPI) delVqdAlarmAll(c *gin.Context, in *vqd.DelVqdAlarmInput) (any, error) { if len(in.IDs) == 0 { - return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqd ids is empty`)) + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqdcms ids is empty`)) } _, err := a.core.DelVqdAlarmAll(c.Request.Context(), in.IDs) if err != nil { - return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqd [%d] err [%s]`, in.IDs, err.Error())) + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqdcms [%d] err [%s]`, in.IDs, err.Error())) } return gin.H{"data": "OK!"}, err } diff --git a/internal/web/api/vqdtask.go b/internal/web/api/vqdtask.go index f2dd3d1..f6a7031 100644 --- a/internal/web/api/vqdtask.go +++ b/internal/web/api/vqdtask.go @@ -5,7 +5,7 @@ import ( "easyvqd/internal/core/host" "easyvqd/internal/core/media" "easyvqd/internal/core/vqd" - "easyvqd/internal/core/vqdsdk" + "easyvqd/internal/core/vqdtask" "fmt" "git.lnton.com/lnton/pkg/reason" "github.com/gin-gonic/gin" @@ -16,12 +16,12 @@ import ( type VqdTaskAPI struct { core *vqd.Core meidaCore *media.Core - vqdSdkCore *vqdsdk.Core + vqdSdkCore *vqdtask.Core cfg *conf.Bootstrap HostCore *host.Core } -func NewVqdTaskAPI(core *vqd.Core, meidaCore *media.Core, vqdSdkCore *vqdsdk.Core, HostCore *host.Core, cfg *conf.Bootstrap) VqdTaskAPI { +func NewVqdTaskAPI(core *vqd.Core, meidaCore *media.Core, vqdSdkCore *vqdtask.Core, HostCore *host.Core, cfg *conf.Bootstrap) VqdTaskAPI { return VqdTaskAPI{core: core, meidaCore: meidaCore, vqdSdkCore: vqdSdkCore, HostCore: HostCore, cfg: cfg} } @@ -42,6 +42,13 @@ func RegisterVqdTask(g gin.IRouter, api VqdTaskAPI, handler ...gin.HandlerFunc) groupTemplate.POST("", web.WarpH(api.addVqdTaskTemplate)) groupTemplate.DELETE("/:id", web.WarpH(api.delVqdTaskTemplate)) + groupTime := g.Group("/api/plan", handler...) + groupTime.GET("", web.WarpH(api.findVqdTimeTemplate)) + groupTime.GET("/:id", web.WarpH(api.getVqdTimeTemplate)) + groupTime.PUT("/:id", web.WarpH(api.editVqdTimeTemplate)) + groupTime.POST("", web.WarpH(api.addVqdTimeTemplate)) + groupTime.DELETE("/:id", web.WarpH(api.delVqdTimeTemplate)) + groupAlarm := g.Group("/api/alarm", handler...) groupAlarm.GET("", web.WarpH(api.findVqdAlarm)) groupAlarm.GET("/:id", web.WarpH(api.getVqdAlarm)) @@ -60,14 +67,21 @@ func (a VqdTaskAPI) findVqdTask(c *gin.Context, in *vqd.FindVqdTaskInput) (any, row := make(map[string]interface{}) row["name"] = item.Name row["id"] = item.ID + row["enable"] = item.Enable row["channel_id"] = item.ChannelID row["channel_name"] = item.ChannelName row["task_template_id"] = item.TaskTemplateID - row["task_template_name"] = item.TaskTemplateName + row["time_template_id"] = item.TimeTemplateID + row["task_template_name"] = "" + row["time_template_name"] = "" template, errs := a.core.GetIDVqdTaskTemplate(c.Request.Context(), item.TaskTemplateID) if errs == nil && template != nil { row["task_template_name"] = template.Name } + timeTemplate, errs := a.core.GetIDVqdTimeTemplate(c.Request.Context(), item.TimeTemplateID) + if errs == nil && template != nil { + row["time_template_name"] = timeTemplate.Name + } row["created_at"] = item.CreatedAt row["updated_at"] = item.UpdatedAt @@ -80,16 +94,27 @@ func (a VqdTaskAPI) getVqdTask(c *gin.Context, _ *struct{}) (any, error) { ID, _ := strconv.Atoi(c.Param("id")) item, err := a.core.GetVqdTask(c.Request.Context(), ID) if err != nil { - return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqd [%d] err [%s]`, ID, err.Error())) + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqdcms [%d] err [%s]`, ID, err.Error())) } row := make(map[string]interface{}) row["name"] = item.Name row["id"] = item.ID + row["enable"] = item.Enable row["channel_id"] = item.ChannelID row["channel_name"] = item.ChannelName row["task_template_id"] = item.TaskTemplateID - row["task_template_name"] = item.TaskTemplateName + row["time_template_id"] = item.TimeTemplateID + row["task_template_name"] = "" + row["time_template_name"] = "" + template, errs := a.core.GetIDVqdTaskTemplate(c.Request.Context(), item.TaskTemplateID) + if errs == nil && template != nil { + row["task_template_name"] = template.Name + } + timeTemplate, errs := a.core.GetIDVqdTimeTemplate(c.Request.Context(), item.TimeTemplateID) + if errs == nil && template != nil { + row["time_template_name"] = timeTemplate.Name + } row["created_at"] = item.CreatedAt row["updated_at"] = item.UpdatedAt @@ -99,7 +124,7 @@ func (a VqdTaskAPI) getVqdTask(c *gin.Context, _ *struct{}) (any, error) { func (a VqdTaskAPI) addVqdTask(c *gin.Context, in *vqd.AddVqdTaskInput) (any, error) { _, err := a.core.AddVqdTask(c.Request.Context(), in) if err != nil { - return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`add vqd err [%s]`, err.Error())) + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`add vqdcms err [%s]`, err.Error())) } return gin.H{"data": "OK!"}, err @@ -109,12 +134,12 @@ func (a VqdTaskAPI) editVqdTask(c *gin.Context, in *vqd.EditVqdTaskInput) (any, ID, _ := strconv.Atoi(c.Param("id")) _, err := a.core.GetVqdTask(c.Request.Context(), ID) if err != nil { - return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqd [%d] err [%s]`, ID, err.Error())) + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqdcms [%d] err [%s]`, ID, err.Error())) } _, err = a.core.EditVqdTask(c.Request.Context(), in, ID) if err != nil { - return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`edit vqd err [%s]`, err.Error())) + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`edit vqdcms err [%s]`, err.Error())) } return gin.H{"data": "OK!"}, err } @@ -123,7 +148,7 @@ func (a VqdTaskAPI) delVqdTask(c *gin.Context, _ *struct{}) (any, error) { ID, _ := strconv.Atoi(c.Param("id")) _, err := a.core.DelVqdTask(c.Request.Context(), ID) if err != nil { - return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqd [%d] err [%s]`, ID, err.Error())) + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqdcms [%d] err [%s]`, ID, err.Error())) } return gin.H{"data": "OK!"}, err diff --git a/internal/web/api/vqdtasktemplate.go b/internal/web/api/vqdtasktemplate.go index db40782..c37a8d0 100644 --- a/internal/web/api/vqdtasktemplate.go +++ b/internal/web/api/vqdtasktemplate.go @@ -18,8 +18,6 @@ func (a VqdTaskAPI) findVqdTaskTemplate(c *gin.Context, in *vqd.FindVqdTaskTempl row["id"] = item.ID row["name"] = item.Name row["des"] = item.Des - row["plans"] = item.Plans - row["enable"] = item.Enable row["is_default"] = item.IsDefault row["vqd_config"] = item.VqdConfig row["vqd_lgt_dark"] = item.VqdLgtDark @@ -45,7 +43,7 @@ func (a VqdTaskAPI) getVqdTaskTemplate(c *gin.Context, _ *struct{}) (any, error) ID, _ := strconv.Atoi(c.Param("id")) item, err := a.core.GetVqdTaskTemplate(c.Request.Context(), ID) if err != nil { - return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqd [%d] err [%s]`, ID, err.Error())) + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqdcms [%d] err [%s]`, ID, err.Error())) } row := make(map[string]interface{}) @@ -65,8 +63,6 @@ func (a VqdTaskAPI) getVqdTaskTemplate(c *gin.Context, _ *struct{}) (any, error) row["vqd_mosaic"] = item.VqdMosaic row["vqd_flower"] = item.VqdFlower row["des"] = item.Des - row["plans"] = item.Plans - row["enable"] = item.Enable row["created_at"] = item.CreatedAt row["updated_at"] = item.UpdatedAt @@ -75,7 +71,7 @@ func (a VqdTaskAPI) getVqdTaskTemplate(c *gin.Context, _ *struct{}) (any, error) func (a VqdTaskAPI) addVqdTaskTemplate(c *gin.Context, in *vqd.AddVqdTaskTemplateInput) (any, error) { _, err := a.core.AddVqdTaskTemplate(c.Request.Context(), in) if err != nil { - return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`add vqd err [%s]`, err.Error())) + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`add vqdcms err [%s]`, err.Error())) } return gin.H{"data": "OK!"}, err @@ -85,12 +81,12 @@ func (a VqdTaskAPI) editVqdTaskTemplate(c *gin.Context, in *vqd.EditVqdTaskTempl ID, _ := strconv.Atoi(c.Param("id")) _, err := a.core.GetVqdTaskTemplate(c.Request.Context(), ID) if err != nil { - return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqd [%d] err [%s]`, ID, err.Error())) + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqdcms [%d] err [%s]`, ID, err.Error())) } _, err = a.core.EditVqdTaskTemplate(c.Request.Context(), in, ID) if err != nil { - return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`edit vqd err [%s]`, err.Error())) + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`edit vqdcms err [%s]`, err.Error())) } return gin.H{"data": "OK!"}, err } @@ -99,7 +95,7 @@ func (a VqdTaskAPI) delVqdTaskTemplate(c *gin.Context, _ *struct{}) (any, error) ID, _ := strconv.Atoi(c.Param("id")) info, err := a.core.GetVqdTaskTemplate(c.Request.Context(), ID) if err != nil { - return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqd [%d] err [%s]`, ID, err.Error())) + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqdcms [%d] err [%s]`, ID, err.Error())) } if info.IsDefault { return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`默认模板不支持删除 [%s] `, info.Name)) @@ -112,7 +108,7 @@ func (a VqdTaskAPI) delVqdTaskTemplate(c *gin.Context, _ *struct{}) (any, error) } _, err = a.core.DelVqdTaskTemplate(c.Request.Context(), ID) if err != nil { - return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqd [%d] err [%s]`, ID, err.Error())) + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqdcms [%d] err [%s]`, ID, err.Error())) } return gin.H{"data": "OK!"}, err diff --git a/internal/web/api/vqdtimetemplate.go b/internal/web/api/vqdtimetemplate.go new file mode 100644 index 0000000..eb9a85b --- /dev/null +++ b/internal/web/api/vqdtimetemplate.go @@ -0,0 +1,95 @@ +package api + +import ( + "easyvqd/internal/core/vqd" + "fmt" + "git.lnton.com/lnton/pkg/reason" + "github.com/gin-gonic/gin" + "strconv" +) + +func (a VqdTaskAPI) findVqdTimeTemplate(c *gin.Context, in *vqd.FindVqdTimeTemplateInput) (any, error) { + items, total, err := a.core.FindVqdTimeTemplate(c.Request.Context(), in) + rows := make([]map[string]interface{}, 0) + + for _, item := range items { + //row := structs.Map(item) + row := make(map[string]interface{}) + row["id"] = item.ID + row["name"] = item.Name + row["des"] = item.Des + row["plans"] = item.Plans + row["enable"] = item.Enable + row["is_default"] = item.IsDefault + row["created_at"] = item.CreatedAt + row["updated_at"] = item.UpdatedAt + + rows = append(rows, row) + } + + return gin.H{"items": rows, "total": total}, err +} +func (a VqdTaskAPI) getVqdTimeTemplate(c *gin.Context, _ *struct{}) (any, error) { + ID, _ := strconv.Atoi(c.Param("id")) + item, err := a.core.GetVqdTimeTemplate(c.Request.Context(), ID) + if err != nil { + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqdcms [%d] err [%s]`, ID, err.Error())) + } + row := make(map[string]interface{}) + + row["id"] = item.ID + row["name"] = item.Name + row["is_default"] = item.IsDefault + row["des"] = item.Des + row["plans"] = item.Plans + row["enable"] = item.Enable + row["created_at"] = item.CreatedAt + row["updated_at"] = item.UpdatedAt + + return gin.H{"data": row}, err +} +func (a VqdTaskAPI) addVqdTimeTemplate(c *gin.Context, in *vqd.AddVqdTimeTemplateInput) (any, error) { + _, err := a.core.AddVqdTimeTemplate(c.Request.Context(), in) + if err != nil { + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`add vqdcms err [%s]`, err.Error())) + } + + return gin.H{"data": "OK!"}, err +} + +func (a VqdTaskAPI) editVqdTimeTemplate(c *gin.Context, in *vqd.EditVqdTimeTemplateInput) (any, error) { + ID, _ := strconv.Atoi(c.Param("id")) + _, err := a.core.GetVqdTimeTemplate(c.Request.Context(), ID) + if err != nil { + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqdcms [%d] err [%s]`, ID, err.Error())) + } + + _, err = a.core.EditVqdTimeTemplate(c.Request.Context(), in, ID) + if err != nil { + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`edit vqdcms err [%s]`, err.Error())) + } + return gin.H{"data": "OK!"}, err +} + +func (a VqdTaskAPI) delVqdTimeTemplate(c *gin.Context, _ *struct{}) (any, error) { + ID, _ := strconv.Atoi(c.Param("id")) + info, err := a.core.GetVqdTimeTemplate(c.Request.Context(), ID) + if err != nil { + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqdcms [%d] err [%s]`, ID, err.Error())) + } + if info.IsDefault { + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`默认模板不支持删除 [%s] `, info.Name)) + } + //templateInfo, err := a.core.FindVqdTimeTemplateID(c.Request.Context(), ID) + //if err == nil { + // if templateInfo != nil { + // return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`模板关联【%s】任务,需先清理【%s】任务后才能删除模板!`, templateInfo.Name, templateInfo.Name)) + // } + //} + _, err = a.core.DelVqdTimeTemplate(c.Request.Context(), ID) + if err != nil { + return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqdcms [%d] err [%s]`, ID, err.Error())) + } + + return gin.H{"data": "OK!"}, err +} diff --git a/pkg/decoder/core.go b/pkg/decoder/core.go new file mode 100644 index 0000000..dd03a5b --- /dev/null +++ b/pkg/decoder/core.go @@ -0,0 +1,121 @@ +package decoder + +/* +#cgo CFLAGS: -w -I${SRCDIR}/include -fPIC +#cgo CPPFLAGS: -w -I${SRCDIR}/include -fPIC +#cgo windows LDFLAGS: -L${SRCDIR}/include -L${SRCDIR}/../ -lez_decoder +#cgo linux LDFLAGS: -Wl,-rpath=./ -L${SRCDIR}/include/linux -L${SRCDIR}/include/RTSP/lib -lez_decoder -lavfilter -lavformat -lavcodec -lavdevice -lswscale -lpostproc -lswresample -lavutil -lx264 -lm -ldl -lstdc++ -pthread -lrt -lssl -lcrypto -lz -lbz2 +#include "ez_decoder.h" +#include +#include +#include + +void CToBytes(unsigned char *dst, unsigned char *src, int src_len) +{ + //memset(dst, 0, src_len); + memcpy(dst, src, src_len); +} +*/ +import "C" +import ( + "fmt" + "log/slog" + "os" + "sync" + "unsafe" +) + +type VideoDecoder struct { + handle C.EZ_DECODER_HANDLE + sync.RWMutex + IsStart bool + + file *os.File +} + +func (v *VideoDecoder) WriteFile(data string) { + if v.file != nil { + v.file.WriteString(data) + } +} + +func (v *VideoDecoder) Create() error { + v.Lock() + defer v.Unlock() + if v.IsStart { + return nil + } + //if v.file == nil { + // filename := filepath.Join(utils.CWD(), "logs", fmt.Sprintf("%016p_decoder.log", v)) + // file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, os.ModePerm) + // if err == nil { + // v.file = file + // v.file.WriteString("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓\r\n") + // } else { + // llog.Info("创建文件失败:%s", filename) + // } + //} + ret := int(C.ez_decoder_create(&v.handle)) + v.IsStart = true + return IsReturnErrorf(ret, "ez_decoder_create") +} + +func (v *VideoDecoder) Destroy() error { + v.Lock() + defer v.Unlock() + if !v.IsStart { + return nil + } + v.IsStart = false + if v.file != nil { + v.file.WriteString("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑\r\n") + v.file.Close() + v.file = nil + } + slog.Info("====>>ez_decoder_destroy", "v", v) + ret := int(C.ez_decoder_destroy(&v.handle)) + return IsReturnErrorf(ret, "ez_decoder_destroy") +} +func (v *VideoDecoder) PushDataEx(buf uintptr, size, codec int) (w, h int, data []byte, err error) { + v.Lock() + defer v.Unlock() + if !v.IsStart { + return 0, 0, nil, fmt.Errorf("decoder fail") + } + if v.file != nil { + v.file.WriteString(fmt.Sprintf("[start] function:PushData;buf len:%d; codec:%x\r\n", size, codec)) + } + info := &C.EZDecoderInfo{} + var out_data *C.uchar + //llog.Info("=======================>>>>>>:%v:%d", buf, size) + ret := int(C.ez_decoder_push_data(v.handle, (*C.uchar)(unsafe.Pointer(buf)), C.int(size), C.int(codec), &out_data, info)) + //var out_data uintptr + //ret := int(C.ez_decoder_push_data(v.handle, (*C.char)(unsafe.Pointer(buf)), C.int(size), C.int(codec), (**C.char)(unsafe.Pointer(&out_data)), info)) + if v.file != nil { + v.file.WriteString(fmt.Sprintf("[end] function:PushData;buf len:%d; codec:%x; ret:%d\r\n", size, codec, ret)) + } + //return 0, 0, nil, fmt.Errorf("test") // 252 + if ret == 0 { + data_size := int(info.data_size) + _w := int(info.width) + _h := int(info.height) + //llog.Info("=======================>>>>>>789:%v:%p:%d", out_data, v, data_size) + yuv := C.GoBytes(unsafe.Pointer(out_data), info.data_size) + _data := make([]byte, data_size) + copy(_data, yuv) + //llog.Info("=======================>>>>>>22222") + return _w, _h, _data, nil + + //_data := make([]byte, data_size) + //C.CToBytes((*C.uchar)(unsafe.Pointer(&_data[0])), out_data, C.int(data_size)) + //return _w, _h, _data, nil + } + return 0, 0, nil, fmt.Errorf("ez_decoder_push_data fail %d", ret) +} + +func IsReturnErrorf(ret int, str string) error { + if int(ret) != 0 { + return fmt.Errorf("%s error:%d", str, ret) + } + return nil +} diff --git a/pkg/decoder/include/RTSP/aarch64/libEasyStreamClient.a b/pkg/decoder/include/RTSP/aarch64/libEasyStreamClient.a new file mode 100644 index 0000000..fd76615 Binary files /dev/null and b/pkg/decoder/include/RTSP/aarch64/libEasyStreamClient.a differ diff --git a/pkg/decoder/include/RTSP/include/EasyAIFilterAPI.h b/pkg/decoder/include/RTSP/include/EasyAIFilterAPI.h new file mode 100644 index 0000000..e2046d5 Binary files /dev/null and b/pkg/decoder/include/RTSP/include/EasyAIFilterAPI.h differ diff --git a/pkg/decoder/include/RTSP/include/EasyRTMPAPI.h b/pkg/decoder/include/RTSP/include/EasyRTMPAPI.h new file mode 100644 index 0000000..126d330 Binary files /dev/null and b/pkg/decoder/include/RTSP/include/EasyRTMPAPI.h differ diff --git a/pkg/decoder/include/RTSP/include/EasyStreamClientAPI.h b/pkg/decoder/include/RTSP/include/EasyStreamClientAPI.h new file mode 100644 index 0000000..bd98b6e --- /dev/null +++ b/pkg/decoder/include/RTSP/include/EasyStreamClientAPI.h @@ -0,0 +1,90 @@ +/* + Copyright (c) 2013-2015 EasyDarwin.ORG. All rights reserved. + Github: https://github.com/EasyDarwin + WEChat: EasyDarwin + Website: http://www.easydarwin.org +*/ +#ifndef _EASY_STREAM_CLIENT_API_H +#define _EASY_STREAM_CLIENT_API_H + +#include "EasyTypes.h" + +/* ¼Ͷ */ +typedef enum __EASY_STREAM_CLIENT_STATE_T +{ + EASY_STREAM_CLIENT_STATE_CONNECTING = 1, /* */ + EASY_STREAM_CLIENT_STATE_CONNECTED, /* ӳɹ */ + EASY_STREAM_CLIENT_STATE_CONNECT_FAILED, /* ʧ */ + EASY_STREAM_CLIENT_STATE_CONNECT_ABORT, /* ж */ + EASY_STREAM_CLIENT_STATE_PUSHING, /* */ + EASY_STREAM_CLIENT_STATE_DISCONNECTED, /* Ͽ */ + EASY_STREAM_CLIENT_STATE_EXIT, /* ˳ */ + EASY_STREAM_CLIENT_STATE_ERROR +} EASY_STREAM_CLIENT_STATE_T; + +/* +_channelPtr: ͨӦ,ʱ +_frameType: EASY_SDK_VIDEO_FRAME_FLAG/EASY_SDK_AUDIO_FRAME_FLAG/EASY_SDK_EVENT_FRAME_FLAG/... +_pBuf: صݲ֣÷Demo +_frameInfo: ֡ṹ +*/ +typedef int (Easy_APICALL *EasyStreamClientCallBack)(void *_channelPtr, int _frameType, void *pBuf, EASY_FRAME_INFO* _frameInfo); +typedef int (Easy_APICALL *EasyDownloadCallBack)(void *userptr, const char* path); + +#ifdef __cplusplus +extern "C" +{ +#endif +#ifdef ANDROID + Easy_API Easy_I32 Easy_APICALL EasyStreamClient_Activate(char *license, char* userPtr); +#else + Easy_API Easy_I32 Easy_APICALL EasyStreamClient_Activate(char *license); +#endif + + /* EasyStreamClient 0ʾɹط0ʾʧ ; loglevel : 0 - quiet 1 - debug*/ + Easy_API int Easy_APICALL EasyStreamClient_Init(Easy_Handle *handle, int loglevel); + + /* ͷEasyStreamClient ΪEasyStreamClient */ + Easy_API int Easy_APICALL EasyStreamClient_Deinit(Easy_Handle handle); + + /* ñ flag: 1 0:ر url:·ļ ret: 0ɹ < 0ʧ 1:ֱ֧*/ + Easy_API int Easy_APICALL EasyStreamClient_SetBackAudio(Easy_Handle handle, int flag, char* url); + + /* ݻص */ + Easy_API int Easy_APICALL EasyStreamClient_SetCallback(Easy_Handle handle, EasyStreamClientCallBack callback); + + /* õͼƬ */ + Easy_API int Easy_APICALL EasyStreamClient_SetOverlayImage(Easy_Handle handle, int left, int top, int scaleWidth, int scaleHeight, const char* imageFilePath); + + /* */ + Easy_API int Easy_APICALL EasyStreamClient_OpenStream(Easy_Handle handle, char *url, EASY_RTP_CONNECT_TYPE connType, void *userPtr, int reconn, int timeout, int useExtraData); + + /* ȡcontext */ + Easy_API int Easy_APICALL EasyStreamClient_GetStreamContext(Easy_Handle handle, void** avFormatContext, void** avCodecContext); + + /* ȡ */ + Easy_API int Easy_APICALL EasyStreamClient_GetSnap(Easy_Handle handle); + + + Easy_API int Easy_APICALL EasyStreamClient_ConvertFrame2Image(const unsigned int videoCodec, const unsigned char* keyFrameData, int keyFrameDataSize, unsigned char** outImage, int* outImageSize); + Easy_API int Easy_APICALL EasyStreamClient_ReleaseImageData(unsigned char** imageData); + + + + /* ƵǷ */ + Easy_API int Easy_APICALL EasyStreamClient_SetAudioEnable(Easy_Handle handle, int enable); + + Easy_API int Easy_APICALL EasyStreamClient_SetAudioOutFormat(Easy_Handle handle, unsigned int audioFormat, int samplerate, int channels); + + /* ȡƵǷ */ + Easy_API int Easy_APICALL EasyStreamClient_GetAudioEnable(Easy_Handle handle); + + /*¼*/ + Easy_API int Easy_APICALL EasyStreamClient_SetDownloadCallback(EasyDownloadCallBack callback); + Easy_API int Easy_APICALL EasyStreamClient_DownloadOneRecord(const char* rootPath, const char* streamName, const char* startTime, void* userPtr); + Easy_API int Easy_APICALL EasyStreamClient_DownloadPeriod(const char* rootPath, const char* streamName, const char* startTime, const char* endTime, void* userPtr); +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/pkg/decoder/include/RTSP/include/EasyTypes.h b/pkg/decoder/include/RTSP/include/EasyTypes.h new file mode 100644 index 0000000..8e7f29e --- /dev/null +++ b/pkg/decoder/include/RTSP/include/EasyTypes.h @@ -0,0 +1,167 @@ +/* + Copyright (c) 2012-2019 TSINGSEE.COM. All rights reserved. + Github: https://github.com/tsingsee + WEChat: tsingsee + Website: http://www.tsingsee.com +*/ +#ifndef _Easy_Types_H +#define _Easy_Types_H + +#ifdef _WIN32 +#define Easy_API __declspec(dllexport) +#define Easy_APICALL __stdcall +#define WIN32_LEAN_AND_MEAN +#else +#define Easy_API __attribute__ ((visibility("default"))) +#define Easy_APICALL __attribute__ ((visibility("default"))) +#endif + +#define Easy_Handle void* + +typedef int Easy_I32; +typedef unsigned char Easy_U8; +typedef unsigned char Easy_UChar; +typedef unsigned short Easy_U16; +typedef unsigned int Easy_U32; +typedef unsigned char Easy_Bool; + +enum +{ + Easy_NoErr = 0, + Easy_RequestFailed = -1, + Easy_Unimplemented = -2, + Easy_RequestArrived = -3, + Easy_OutOfState = -4, + Easy_NotAModule = -5, + Easy_WrongVersion = -6, + Easy_IllegalService = -7, + Easy_BadIndex = -8, + Easy_ValueNotFound = -9, + Easy_BadArgument = -10, + Easy_ReadOnly = -11, + Easy_NotPreemptiveSafe = -12, + Easy_NotEnoughSpace = -13, + Easy_WouldBlock = -14, + Easy_NotConnected = -15, + Easy_FileNotFound = -16, + Easy_NoMoreData = -17, + Easy_AttrDoesntExist = -18, + Easy_AttrNameExists = -19, + Easy_InstanceAttrsNotAllowed = -20, + Easy_InvalidSocket = -21, + Easy_MallocError = -22, + Easy_ConnectError = -23, + Easy_SendError = -24 +}; +typedef int Easy_Error; + +typedef enum __EASY_ACTIVATE_ERR_CODE_ENUM +{ + EASY_ACTIVATE_INVALID_KEY = -1, /* ЧKey */ + EASY_ACTIVATE_TIME_ERR = -2, /* ʱ */ + EASY_ACTIVATE_PROCESS_NAME_LEN_ERR = -3, /* ƳȲƥ */ + EASY_ACTIVATE_PROCESS_NAME_ERR = -4, /* Ʋƥ */ + EASY_ACTIVATE_VALIDITY_PERIOD_ERR= -5, /* ЧУ鲻һ */ + EASY_ACTIVATE_PLATFORM_ERR = -6, /* ƽ̨ƥ */ + EASY_ACTIVATE_COMPANY_ID_LEN_ERR= -7, /* Ȩʹ̲ƥ */ + EASY_ACTIVATE_SUCCESS = 9999, /* ɹ */ + +}EASY_ACTIVATE_ERR_CODE_ENUM; + +/* Ƶ */ +#define EASY_SDK_VIDEO_CODEC_H264 0x1C /* H264 */ +#define EASY_SDK_VIDEO_CODEC_H265 0xAE /* H265 */ +#define EASY_SDK_VIDEO_CODEC_MJPEG 0x08 /* MJPEG */ +#define EASY_SDK_VIDEO_CODEC_MPEG4 0x0D /* MPEG4 */ + +/* Ƶ */ +#define EASY_SDK_AUDIO_CODEC_AAC 0x15002 /* AAC */ +#define EASY_SDK_AUDIO_CODEC_G711U 0x10006 /* G711 ulaw*/ +#define EASY_SDK_AUDIO_CODEC_G711A 0x10007 /* G711 alaw*/ +#define EASY_SDK_AUDIO_CODEC_G726 0x1100B /* G726 */ + +#define EASY_SDK_EVENT_CODEC_ERROR 0x63657272 /* ERROR */ +#define EASY_SDK_EVENT_CODEC_EXIT 0x65786974 /* EXIT */ + +/* Ƶ֡ʶ */ +#define EASY_SDK_VIDEO_FRAME_FLAG 0x00000001 /* Ƶ֡־ */ +#define EASY_SDK_AUDIO_FRAME_FLAG 0x00000002 /* Ƶ֡־ */ +#define EASY_SDK_EVENT_FRAME_FLAG 0x00000004 /* ¼֡־ */ +#define EASY_SDK_RTP_FRAME_FLAG 0x00000008 /* RTP֡־ */ +#define EASY_SDK_SDP_FRAME_FLAG 0x00000010 /* SDP֡־ */ +#define EASY_SDK_MEDIA_INFO_FLAG 0x00000020 /* ýͱ־*/ +#define EASY_SDK_SNAP_FRAME_FLAG 0x00000040 /* ͼƬ־*/ + +/* Ƶؼֱʶ */ +#define EASY_SDK_VIDEO_FRAME_I 0x01 /* I֡ */ +#define EASY_SDK_VIDEO_FRAME_P 0x02 /* P֡ */ +#define EASY_SDK_VIDEO_FRAME_B 0x03 /* B֡ */ +#define EASY_SDK_VIDEO_FRAME_J 0x04 /* JPEG */ + +/* */ +typedef enum __EASY_RTP_CONNECT_TYPE +{ + EASY_RTP_OVER_TCP = 0x01, /* RTP Over TCP */ + EASY_RTP_OVER_UDP, /* RTP Over UDP */ + EASY_RTP_OVER_MULTICAST /* RTP Over MULTICAST */ +}EASY_RTP_CONNECT_TYPE; + +typedef struct __EASY_AV_Frame +{ + Easy_U32 u32AVFrameFlag; /* ֡־ Ƶ or Ƶ */ + Easy_U32 u32AVFrameLen; /* ֡ij */ + Easy_U32 u32VFrameType; /* ƵͣI֡P֡ */ + Easy_U8 *pBuffer; /* */ + Easy_U32 u32TimestampSec; /* ʱ()*/ + Easy_U32 u32TimestampUsec; /* ʱ(΢) */ + Easy_U32 u32PTS; +} EASY_AV_Frame; + +/* ýϢ */ +typedef struct __EASY_MEDIA_INFO_T +{ + Easy_U32 u32VideoCodec; /* Ƶ */ + Easy_U32 u32VideoFps; /* Ƶ֡ */ + + Easy_U32 u32AudioCodec; /* Ƶ */ + Easy_U32 u32AudioSamplerate; /* Ƶ */ + Easy_U32 u32AudioChannel; /* Ƶͨ */ + Easy_U32 u32AudioBitsPerSample; /* Ƶ */ + + Easy_U32 u32VpsLength; + Easy_U32 u32SpsLength; + Easy_U32 u32PpsLength; + Easy_U32 u32SeiLength; + Easy_U8 u8Vps[256]; + Easy_U8 u8Sps[256]; + Easy_U8 u8Pps[128]; + Easy_U8 u8Sei[128]; +}EASY_MEDIA_INFO_T; + +/* ֡Ϣ */ +typedef struct +{ + unsigned int codec; /* Ƶʽ */ + + unsigned int type; /* Ƶ֡ */ + unsigned char fps; /* Ƶ֡ */ + unsigned short width; /* Ƶ */ + unsigned short height; /* Ƶ */ + + unsigned int reserved1; /* 1 */ + unsigned int reserved2; /* 2 */ + + unsigned int sample_rate; /* Ƶ */ + unsigned int channels; /* Ƶ */ + unsigned int bits_per_sample; /* Ƶ */ + + unsigned int length; /* Ƶ֡С */ + unsigned int timestamp_usec; /* ʱ,΢ */ + unsigned int timestamp_sec; /* ʱ */ + unsigned int pts; + + float bitrate; /* */ + float losspacket; /* */ +}EASY_FRAME_INFO; + +#endif diff --git a/pkg/decoder/include/RTSP/lib/libEasyStreamClient.a b/pkg/decoder/include/RTSP/lib/libEasyStreamClient.a new file mode 100644 index 0000000..a29501a Binary files /dev/null and b/pkg/decoder/include/RTSP/lib/libEasyStreamClient.a differ diff --git a/pkg/decoder/include/RTSP/lib/libavcodec.a b/pkg/decoder/include/RTSP/lib/libavcodec.a new file mode 100644 index 0000000..c7f71c6 Binary files /dev/null and b/pkg/decoder/include/RTSP/lib/libavcodec.a differ diff --git a/pkg/decoder/include/RTSP/lib/libavdevice.a b/pkg/decoder/include/RTSP/lib/libavdevice.a new file mode 100644 index 0000000..7f1a3e6 Binary files /dev/null and b/pkg/decoder/include/RTSP/lib/libavdevice.a differ diff --git a/pkg/decoder/include/RTSP/lib/libavfilter.a b/pkg/decoder/include/RTSP/lib/libavfilter.a new file mode 100644 index 0000000..0425b5e Binary files /dev/null and b/pkg/decoder/include/RTSP/lib/libavfilter.a differ diff --git a/pkg/decoder/include/RTSP/lib/libavformat.a b/pkg/decoder/include/RTSP/lib/libavformat.a new file mode 100644 index 0000000..c710ee9 Binary files /dev/null and b/pkg/decoder/include/RTSP/lib/libavformat.a differ diff --git a/pkg/decoder/include/RTSP/lib/libavutil.a b/pkg/decoder/include/RTSP/lib/libavutil.a new file mode 100644 index 0000000..e97585a Binary files /dev/null and b/pkg/decoder/include/RTSP/lib/libavutil.a differ diff --git a/pkg/decoder/include/RTSP/lib/libbz2.a b/pkg/decoder/include/RTSP/lib/libbz2.a new file mode 100644 index 0000000..279bdb2 Binary files /dev/null and b/pkg/decoder/include/RTSP/lib/libbz2.a differ diff --git a/pkg/decoder/include/RTSP/lib/libeasyaacencoder.a b/pkg/decoder/include/RTSP/lib/libeasyaacencoder.a new file mode 100644 index 0000000..3708f9e Binary files /dev/null and b/pkg/decoder/include/RTSP/lib/libeasyaacencoder.a differ diff --git a/pkg/decoder/include/RTSP/lib/libfdk-aac.a b/pkg/decoder/include/RTSP/lib/libfdk-aac.a new file mode 100644 index 0000000..dc81b6f Binary files /dev/null and b/pkg/decoder/include/RTSP/lib/libfdk-aac.a differ diff --git a/pkg/decoder/include/RTSP/lib/libfreetype.a b/pkg/decoder/include/RTSP/lib/libfreetype.a new file mode 100644 index 0000000..e032724 Binary files /dev/null and b/pkg/decoder/include/RTSP/lib/libfreetype.a differ diff --git a/pkg/decoder/include/RTSP/lib/libpostproc.a b/pkg/decoder/include/RTSP/lib/libpostproc.a new file mode 100644 index 0000000..71a9609 Binary files /dev/null and b/pkg/decoder/include/RTSP/lib/libpostproc.a differ diff --git a/pkg/decoder/include/RTSP/lib/libswresample.a b/pkg/decoder/include/RTSP/lib/libswresample.a new file mode 100644 index 0000000..670332f Binary files /dev/null and b/pkg/decoder/include/RTSP/lib/libswresample.a differ diff --git a/pkg/decoder/include/RTSP/lib/libswscale.a b/pkg/decoder/include/RTSP/lib/libswscale.a new file mode 100644 index 0000000..a954656 Binary files /dev/null and b/pkg/decoder/include/RTSP/lib/libswscale.a differ diff --git a/pkg/decoder/include/RTSP/lib/libx264.a b/pkg/decoder/include/RTSP/lib/libx264.a new file mode 100644 index 0000000..924d258 Binary files /dev/null and b/pkg/decoder/include/RTSP/lib/libx264.a differ diff --git a/pkg/decoder/include/RTSP/lib/libz.a b/pkg/decoder/include/RTSP/lib/libz.a new file mode 100644 index 0000000..95ef242 Binary files /dev/null and b/pkg/decoder/include/RTSP/lib/libz.a differ diff --git a/pkg/decoder/include/ez_decoder.h b/pkg/decoder/include/ez_decoder.h new file mode 100644 index 0000000..ad3677a --- /dev/null +++ b/pkg/decoder/include/ez_decoder.h @@ -0,0 +1 @@ +#pragma once #ifdef __cplusplus extern "C" { #endif #ifdef _WIN32 #define EZ_DECODER_EXPORTS_API __declspec(dllexport) #define EZ_DECODER_EXPORTS_APICALL __stdcall #else #define EZ_DECODER_EXPORTS_API #define EZ_DECODER_EXPORTS_APICALL #endif typedef void* EZ_DECODER_HANDLE; typedef struct __EZ_DECODER_INFO__ { int width; int height; int data_size; }EZDecoderInfo; EZ_DECODER_EXPORTS_API int EZ_DECODER_EXPORTS_APICALL ez_decoder_create(EZ_DECODER_HANDLE *handle); EZ_DECODER_EXPORTS_API int EZ_DECODER_EXPORTS_APICALL ez_decoder_destroy(EZ_DECODER_HANDLE* handle); EZ_DECODER_EXPORTS_API int EZ_DECODER_EXPORTS_APICALL ez_decoder_push_data(EZ_DECODER_HANDLE handle, const unsigned char *data, int data_size, int video_id, unsigned char **out_data, EZDecoderInfo *info); /* ����־ */ EZ_DECODER_EXPORTS_API int EZ_DECODER_EXPORTS_APICALL ez_activate_log(const char* logDir, int logDirSize); //typedef void* PullStream_Handle; #define PullStream_Handle void* typedef int (EZ_DECODER_EXPORTS_APICALL* PullStreamCallBack)(void* _channelPtr, int _frameType, void* pBuf, int puf_len, int frameCodec, int frameFlag); EZ_DECODER_EXPORTS_API int EZ_DECODER_EXPORTS_APICALL PullStream_Init(PullStream_Handle* handle); EZ_DECODER_EXPORTS_API int EZ_DECODER_EXPORTS_APICALL PullStream_DeInit(PullStream_Handle handle); EZ_DECODER_EXPORTS_API int EZ_DECODER_EXPORTS_APICALL PullStream_SetCallback(PullStream_Handle handle, PullStreamCallBack callback); EZ_DECODER_EXPORTS_API int EZ_DECODER_EXPORTS_APICALL PullStream_Open(PullStream_Handle handle, void* userPtr, char *url, int timeout); #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/pkg/decoder/include/linux/libez_decoder.a b/pkg/decoder/include/linux/libez_decoder.a new file mode 100644 index 0000000..c9b00e9 Binary files /dev/null and b/pkg/decoder/include/linux/libez_decoder.a differ diff --git a/pkg/vqdcms/core.go b/pkg/vqdcms/core.go new file mode 100644 index 0000000..05bbb7c --- /dev/null +++ b/pkg/vqdcms/core.go @@ -0,0 +1,32 @@ +package vqdcms + +import ( + "sync" +) + +type VqdTaskMap struct { + M map[string]*VQDHandle // 自定义K-V的类型; + sync.RWMutex +} + +// 读出相应Key的子Map +func (m *VqdTaskMap) LoadTaskMap(key string) (value *VQDHandle, ok bool) { + m.RLock() + defer m.RUnlock() + value, ok = m.M[key] + return +} + +// 删除相应Key的子Map +func (m *VqdTaskMap) DeleteTaskMap(key string) { + m.Lock() + defer m.Unlock() + delete(m.M, key) +} + +// 增加或修改相应Key的子Map +func (m *VqdTaskMap) StoreChildMap(key string, value *VQDHandle) { + m.Lock() + defer m.Unlock() + m.M[key] = value +} diff --git a/pkg/vqdcms/include/ez_vqd.h b/pkg/vqdcms/include/ez_vqd.h new file mode 100644 index 0000000..1ad07f2 --- /dev/null +++ b/pkg/vqdcms/include/ez_vqd.h @@ -0,0 +1,73 @@ +#pragma once + +#include "nxu_vqd_api.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifdef _WIN32 +#define Easy_NXU_EXPORTS_API __declspec(dllexport) +#define Easy_NXU_EXPORTS_APICALL __stdcall +#else +#define Easy_NXU_EXPORTS_API +#define Easy_NXU_EXPORTS_APICALL +#endif + + typedef struct __tagVideoInfo__ + { + NXU_HANDLE phVQD; + NXU_HANDLE VideoHandle; + int interval; + NXU_VQD_Para_S stPara; + char url[256]; + } VideoInfo; + + + // ��ȡ�汾 + Easy_NXU_EXPORTS_API int Easy_NXU_EXPORTS_APICALL + ez_vqd_version(char* version); + + // ������� + Easy_NXU_EXPORTS_API int Easy_NXU_EXPORTS_APICALL + ez_vqd_create(VideoInfo *handle); + // ע����� + Easy_NXU_EXPORTS_API int Easy_NXU_EXPORTS_APICALL + ez_vqd_destroy(VideoInfo *handle); + + // ��ʼ���� + Easy_NXU_EXPORTS_API int Easy_NXU_EXPORTS_APICALL + ez_vqd_run(VideoInfo handle, int frameNum, char *save_filename, int save_filename_size, NXU_VQD_Result_S *out_stResult); + + /*typedef struct __tagVideoInfoCVR__ + { + NXU_HANDLE phVQD; + int interval; + NXU_VQD_Para_S stPara; + int width; + int height; + } VideoInfoCVR;*/ + + typedef void* VideoInfoCVR; + + Easy_NXU_EXPORTS_API int Easy_NXU_EXPORTS_APICALL + ez_cvr_vqd_load(char *path, int path_size, char* errmsg); + Easy_NXU_EXPORTS_API int Easy_NXU_EXPORTS_APICALL + ez_cvr_vqd_unload(); + + Easy_NXU_EXPORTS_API int Easy_NXU_EXPORTS_APICALL + ez_cvr_vqd_create(VideoInfoCVR* handle); + Easy_NXU_EXPORTS_API int Easy_NXU_EXPORTS_APICALL + ez_cvr_vqd_destroy(VideoInfoCVR* handle); + Easy_NXU_EXPORTS_API int Easy_NXU_EXPORTS_APICALL + ez_cvr_vqd_config(VideoInfoCVR handle, NXU_VQD_Para_S *stPara, int interval); + // ��ʼ���� + Easy_NXU_EXPORTS_API int Easy_NXU_EXPORTS_APICALL + ez_cvr_vqd_run(VideoInfoCVR handle, int width, int height, char* data, int frameNum, char* save_filename, int save_filename_size, NXU_VQD_Result_S* out_stResult); + + Easy_NXU_EXPORTS_API int Easy_NXU_EXPORTS_APICALL + ez_cvr_vqd_img(VideoInfoCVR handle, char* jpg_path, int jpg_path_size, NXU_VQD_Result_S* out_stResult); +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/pkg/vqdcms/include/nxu_common.h b/pkg/vqdcms/include/nxu_common.h new file mode 100644 index 0000000..247bcfc --- /dev/null +++ b/pkg/vqdcms/include/nxu_common.h @@ -0,0 +1,597 @@ +/************************************************************************ +* Copyright (C), 2023 NXU Network Tech. Co., Ltd. +* LET AI CONNECT FUTURE +************************************************************************* +* +* File Name : nxu_common.h +* Version : 1.0.0 +* Author : 007 @ TECH TEAM (zhou24388@163.com) +* Created : 2023/06/12 +* Description : The common data type defination +******************************************************************************/ +#ifndef __NXU_COMMON_H__ +#define __NXU_COMMON_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + #ifndef NULL + #define NULL 0L + #endif + #define NXU_NULL 0L + #define NXU_NULL_PTR 0L + + #define NXU_MAX(a, b) ((a) > (b) ? (a) : (b)) + #define NXU_MIN(a, b) ((a) < (b) ? (a) : (b)) + #define NXU_ABS(a) ((a) >= 0 ? (a) : (-(a))) + /* Clip Data between min to max*/ + #define NXU_CLIP(val, min_val, max_val) ((val) >= (min_val) ? ((val) <= (max_val) ? (val) : (max_val)) : (min_val)) + +#define NXU_ASSERT(a) assert(a) + + /** NXU_EXPORTS */ +#if defined(NXU_API_EXPORTS) + #define NXU_EXPORTS __declspec(dllexport) +#elif defined(NXU_API_IMPORTS) + #define NXU_EXPORTS __declspec(dllimport) +#else + #define NXU_EXPORTS extern +#endif + + /** NXU_INLINE */ +#ifndef NXU_INLINE +#if defined __cplusplus + #define NXU_INLINE inline +#elif (defined WIN32 || defined WIN64) && !defined __GNUC__ + #define NXU_INLINE __inline +#else + #define NXU_INLINE static +#endif +#endif + + /* META Type Definitions */ + typedef unsigned char NXU_U8; + typedef unsigned char NXU_UCHAR; + typedef unsigned short NXU_U16; + typedef unsigned int NXU_U32; + + typedef char NXU_S8; + typedef char NXU_CHAR; + typedef char * NXU_PCHAR; + typedef short NXU_S16; + typedef int NXU_S32; + +#ifndef _M_IX86 + typedef unsigned long long NXU_U64; + typedef long long NXU_S64; +#else + typedef __int64 NXU_U64; + typedef __int64 NXU_S64; +#endif + + typedef float NXU_FLOAT; + typedef double NXU_DOUBLE; + typedef unsigned long NXU_SIZE_T; + typedef unsigned long NXU_LENGTH_T; + + /* Handle */ + typedef void NXU_VOID; + typedef void * NXU_HANDLE; + typedef void * NXU_PVOID; + + /* ------------------ Fixed Point Type ------------------------*/ + /* u8bit */ + typedef unsigned char NXU_U0Q8; + typedef unsigned char NXU_U1Q7; + typedef unsigned char NXU_U5Q3; + + /* u16bit */ + typedef unsigned short NXU_U0Q16; + typedef unsigned short NXU_U4Q12; + typedef unsigned short NXU_U5Q11; + typedef unsigned short NXU_U6Q9; + typedef unsigned short NXU_U8Q8; + typedef unsigned short NXU_U9Q7; + typedef unsigned short NXU_U12Q4; + typedef unsigned short NXU_U14Q2; + + /* s16bit */ + typedef short NXU_S9Q7; + typedef short NXU_S14Q2; + typedef short NXU_S1Q15; + + /* u32bit */ + typedef unsigned int NXU_U22Q10; + typedef unsigned int NXU_U25Q7; + typedef unsigned int NXU_U21Q11; + + /* s32bit */ + typedef int NXU_S25Q7; + typedef int NXU_S16Q16; + + /* Boolean */ + typedef enum _nxubool_e_ + { + NXU_FALSE = 0, + NXU_TRUE = 1, + } NXU_BOOL; + + /* Shape Enum */ + typedef enum _nxushape_e_ + { + NXU_SHAPE_POINT = 0, /* Point */ + NXU_SHAPE_LINE = 1, /* Line */ + NXU_SHAPE_RECT = 2, /* Rect */ + NXU_SHAPE_CIRCLE = 3, /* Circle */ + NXU_SHAPE_ELLIPSE = 4, /* Ellipse */ + NXU_SHAPE_POLYGON = 5, /* Polygon */ + NXU_SHAPE_POLYLINE = 6, /* Polyline */ + NXU_SHAPE_FREEHAND = 7 /* Free */ + } NXU_SHAPE_E; + + + /************************************************************************/ + /* Point definition */ + /************************************************************************/ + /* 2D Point Definition */ + typedef struct _nxu2dpoint_s_ + { + NXU_S32 s32X; /* X */ + NXU_S32 s32Y; /* Y */ + } NXU_POINT_S, NXU_2DPOINT_S; + + /* 2D Point with float data */ + typedef struct _nxu2dpoint32f_s_ + { + NXU_FLOAT f32X; /* X */ + NXU_FLOAT f32Y; /* Y */ + } NXU_POINT32F_S, NXU_2DPOINT32F_S; + + /* 3D Point */ + typedef struct _nxu3dpoint_s_ + { + NXU_S32 s32X; /* X */ + NXU_S32 s32Y; /* Y */ + NXU_S32 s32Z; /* Z */ + } NXU_3DPOINT_S; + + /* 3D Point with float data */ + typedef struct _nxu3dpoint32f_s_ + { + NXU_FLOAT f32X; /* X */ + NXU_FLOAT f32Y; /* Y */ + NXU_FLOAT f32Z; /* Z */ + } NXU_3DPOINT32F_S; + + /** + * @brief Multi-Points Definition. + * + * NXU_POLYGON_S: adjacent point order loop, first->two->three....->last->first, + * closed plane area, polygon shape. + * NXU_POLYLINE_S: adjacent point order, first->two->three....->last, open no loop + * NXU_POINTS_SET_S: adjacent point order, first, two, three, ...., last, points set + * NXU_FREEHAND_S: just points set, no order, no loop + */ + typedef struct _nxumultipoints_s_ + { + NXU_S32 s32Num; /* Points Num */ + NXU_POINT_S* pstPoints; /* Points set */ + } NXU_POINTS_SET_S, NXU_POLYGON_S, NXU_POLYLINE_S, NXU_FREEHAND_S; + + /* 2D Points Set with float data */ + typedef struct _nxu2dpointsset32f_s_ + { + NXU_S32 s32PtNum; /* Points Num */ + NXU_POINT32F_S* pstPoints; /* Points Set */ + } NXU_POINTS32F_SET_S; + + /* Polygon, normally used in the config para */ +#define NXU_MAX_VERTEX_NUM 16 /* max vertex num of the polygon */ + typedef struct _nxupolygon_s_ + { + NXU_U8 u8VertexNum; /* Points Num */ + NXU_POINT_S astVertex[NXU_MAX_VERTEX_NUM]; /* Points Array */ + } NXU_Polygon_S; + + // 3D Points Set + typedef struct _nxu3dpointsset_s_ + { + NXU_S32 s32PtNum; /* Points Num */ + NXU_3DPOINT_S* pstPoints; /* Points Set */ + } NXU_3DPOINTS_SET_S; + + // 3D Points Set with float data + typedef struct _nxu3dpintsset32f_s_ + { + NXU_S32 s32PtNum; /* Points Num */ + NXU_3DPOINT32F_S* pstPoints; /* Points Set */ + } NXU_3DPOINTS32F_SET_S; + + + /************************************************************************/ + /* Line definition */ + /************************************************************************/ + /* Line */ + /** + * @brief Multi-lines definition. + * + * maybe used for key-points set, or line-sets, or curve-sets, or ... + * bIsDirect: Defaults to NXU_FALSE. + * if true, the line is direct from start to end, + * otherwise, the line is not direct + */ + typedef struct _nxuline_s_ + { + NXU_BOOL bIsDirect; /* Direct or Not */ + NXU_POINT_S stStart; /* Start Point */ + NXU_POINT_S stEnd; /* End Point */ + } NXU_LINE_S; + + /* Line with float data */ + typedef struct _nxuline32f_s_ + { + NXU_BOOL bIsDirect; /* Direct or Not */ + NXU_POINT32F_S stStart; /* Start Point */ + NXU_POINT32F_S stEnd; /* End Point */ + } NXU_LINE32F_S; + + /* Lines Set with default data */ + typedef struct _nxu2dlineset_s_ + { + NXU_S32 s32LineNum; /* Lines Num */ + NXU_LINE_S* pstLines; /* Lines Set */ + } NXU_LINES_SET_S; + + /* Lines Set with float data */ + typedef struct _nxu2Dlinesets32f_s_ + { + NXU_S32 s32LineNum; /* Lines Num */ + NXU_LINE32F_S* pstLineSet; /* Lines Set */ + } NXU_2DLINES32F_SET_S; + + + /************************************************************************/ + /* Shape Definition: Rect, Circle, Ellipse */ + /************************************************************************/ + /* Rect */ + typedef struct _nxurect2p_s_ + { + NXU_POINT_S stTopLeft; /* Top Left Point */ + NXU_POINT_S stBottomRight; /* Bottom Right Point */ + } NXU_RECT_S; + + /* Rect use width and height */ + typedef struct _nuxrectwh_s_ + { + NXU_S32 s32X1; /* Top left x */ + NXU_S32 s32Y1; /* Top left y */ + NXU_S32 s32Width; /* Rect Width */ + NXU_S32 s32Height; /* Rect Height */ + }NXU_Rect_S; + + /* Rect with float data */ + typedef struct _nxurect32f2p_s_ + { + NXU_POINT32F_S stTopLeft; /* Top Left Point */ + NXU_POINT32F_S stBottomRight; /* Bottom Right Point */ + } NXU_RECT32F_S; + + /* Rect with float data use width and height */ + typedef struct _nuxrect32fwh_s_ + { + NXU_FLOAT f32X1; /* Top left x */ + NXU_FLOAT f32Y1; /* Top left y */ + NXU_FLOAT f32Width; /* Rect Width */ + NXU_FLOAT f32Height; /* Rect Height */ + } NXU_Rect32F_S; + + /* Rotate Rect */ + typedef struct _nxurotate_rect_s_ + { + NXU_Rect32F_S stRect; /* Rectangle */ + NXU_FLOAT f32Angle; /* Angle */ + } NXU_ROTATE_Rect_S; + + /* Circle */ + typedef struct _nxucircle_s_ + { + NXU_POINT_S stCenter; /* Center Point */ + NXU_S32 s32Radius; /* Radius */ + } NXU_CIRCLE_S; + + /* Circle with float data */ + typedef struct _nxucircle32f_s_ + { + NXU_POINT32F_S stCenter; /* Center Point */ + NXU_FLOAT f32Radius; /* Radius */ + } NXU_CIRCLE32F_S; + + /* Ellipse */ + typedef struct _nxuellipse_s_ + { + NXU_POINT_S stCenter; /* Center Point */ + NXU_S32 s32RadiusX; /* Radius X */ + NXU_S32 s32RadiusY; /* Radius Y */ + } NXU_ELLIPSE_S; + + /* Ellipse with float data */ + typedef struct _nxuellipse32f_s_ + { + NXU_POINT32F_S stCenter; /* Center Point */ + NXU_FLOAT f32RadiusX; /* Radius X */ + NXU_FLOAT f32RadiusY; /* Radius Y */ + } NXU_ELLIPSE32F_S; + + + + /************************************************************************/ + /* STATUS_CODE */ + /************************************************************************/ + /** + * @brief all zero is ok, good status + * we can use the 'binary shift' and 'binary xor' or 'binary or' to get the status + */ + typedef enum _nxustatuscode_e_ + { + NXU_SUCCESS = 0x00000000, /* Success */ + NXU_FAILURE = 0x80000000, /* Failure */ + + /* memory failure */ + NXU_MEM_FAIL = 0x80000001, /* memory failure */ + NXU_MEM_FAIL_MALLOC = 0x80000002, /* memory allocation failure */ + NXU_MEM_FAIL_CALLOC = 0x80000003, /* calloc */ + NXU_MEM_FAIL_REALLOC = 0x80000004, /* realloc failure */ + NXU_MEM_FAIL_FREE = 0x80000005, /* free memory failure */ + + /* image failure */ + NXU_IMAGE_FAIL = 0x80000010, /* image failure */ + NXU_IMAGE_FAIL_SIZE = 0x80000020, /* image size error */ + NXU_IMAGE_FAIL_FORMAT = 0x80000030, /* image format error */ + NXU_IMAGE_FAIL_READ = 0x80000040, /* read image file failure */ + NXU_IMAGE_FAIL_WRITE = 0x80000050, /* write failure */ + + /* file failure */ + NXU_FILE_FAIL = 0x80000100, /* file operation failure */ + NXU_FILE_FAIL_READ = 0x80000200, /* read file failure */ + NXU_FILE_FAIL_WRITE = 0x80000300, /* write file failure */ + + /* para failure */ + NXU_PARA_FAIL = 0x80001000, /* parameter error */ + NXU_PARA_FAIL_CONFIG = 0x80002000, /* config file failure */ + NXU_PARA_FAIL_INVALID = 0x80003000, /* invalid parameter */ + NXU_PARA_FAIL_UNSUPPORT = 0x80004000, /* not support */ + + /* license failure */ + NXU_LICENSE_FAIL = 0x80010000, /* license failure */ + NXU_LICENSE_FAIL_TIMEOUT = 0x80020000, /* license timeout */ + NXU_LICENSE_FAIL_READ_MAC = 0x80030000, /* read mac failure */ + NXU_LICENSE_FAIL_CHECK = 0x80040000, /* license check failure */ + NXU_LICENSE_FAIL_INVALID = 0x80050000, /* license invalid */ + + /* net failure */ + NXU_NETWORK_FAIL = 0x80100000, /* network failure */ + NXU_NETWORK_CONNECT = 0x80200000, /* network connect failure */ + NXU_NETWORK_PUSH = 0x80300000, /* network push failure */ + NXU_NETWORK_GET = 0x80400000, /* network get failure */ + } NXU_STATUS_CODE_E; + + /** + * @brief if f32Real = 2, f32Imag = 3, then the complex number is 2+3i + * maybe used in Fourier + */ + typedef struct _nxucomplexdata_s_ + { + NXU_FLOAT f32Real; + NXU_FLOAT f32Imag; + } NXU_Complex_S; + + /************************************************************************/ + /* Image and Matrix Definition */ + /************************************************************************/ + /** + * @brief the packed pixel, maybe rgb, yuv, hsv, gray, ... + */ + typedef struct _nxupackedpixel_s_ + { + NXU_U8 u8ColorA; + NXU_U8 u8ColorB; + NXU_U8 u8ColorC; + NXU_U8 u8ColorReserved; + } NXU_PACKED_PIXEL_S; + + /* BGR pixel value */ + typedef struct _nxupixel_s_ + { + NXU_U8 u8B; /* B */ + NXU_U8 u8G; /* G */ + NXU_U8 u8R; /* R */ + } NXU_PIXEL_S, NXU_BGR_PIXEL_S; + + /* HSV pixel value */ + typedef struct _nxuhsvpixel_s_ + { + NXU_FLOAT f32H; /* H */ + NXU_FLOAT f32S; /* S */ + NXU_FLOAT f32V; /* V */ + } NXU_HSV_PIXEL_S; + + /* HSL pixel value */ + typedef struct _nxuhslpixel_s_ + { + NXU_FLOAT f32H; /* H */ + NXU_FLOAT f32S; /* S */ + NXU_FLOAT f32L; /* L */ + } NXU_HSL_PIXEL_S; + + /** + * @brief Usual image format + * U(Cb), V(Cr) + */ + typedef enum _nxuimageformat_e_ + { + NXU_IMAGE_FORMAT_UNKNOWN = 0, /* Unknown */ + NXU_IMAGE_FORMAT_GRAY, /* GRAY GRAY GRAY GRAY */ + NXU_IMAGE_FORMAT_RGB_PACKED, /* RGB RGB RGB RGB RGB RGB RGB RGB */ + NXU_IMAGE_FORMAT_RGB_PLANAR, /* RRRRRRRR GGGGGGGG BBBBBBBBB */ + NXU_IMAGE_FORMAT_BGR_PACKED, /* BGR BGR BGR BGR BGR BGR BGR BGR */ + NXU_IMAGE_FORMAT_BGR_PLANAR, /* BBBBBBBBB GGGGGGGG RRRRRRRR */ + NXU_IMAGE_FORMAT_HSV, /* hsv, but not often used */ + NXU_IMAGE_FORMAT_HLS, /* hls, but not often used */ + NXU_IMAGE_FORMAT_YUV444P, /* YYYYYYYY VVVVVVVV UUUUUUU */ + NXU_IMAGE_FORMAT_YUV422P, /* YYYYYYYY VVVV UUUU */ + NXU_IMAGE_FORMAT_YUV422_YUYV, /* YUYV YUYV YUYV YUYV */ + NXU_IMAGE_FORMAT_YUV422_UYVY, /* UYVY UYVY UYVY UYVY */ + NXU_IMAGE_FORMAT_YUV420p_YV12, /* YYYYYYYY VV UU */ + NXU_IMAGE_FORMAT_YUV420p_I420, /* YYYYYYYY UU VV */ + NXU_IMAGE_FORMAT_YUV420sp, /* YYYYYYYY UVUV, default */ + NXU_IMAGE_FORMAT_YUV420_NV12, /* YYYYYYYY UVUV */ + NXU_IMAGE_FORMAT_YUV420_NV21, /* YYYYYYYY VUVU */ + NXU_IMAGE_FORMAT_YUV400, /* YYYYYYYY, only y */ + NXU_IMAGE_FORMAT_BayerRGGB, /* RGGB RGGB RGGB RGGB RGGB RGGB */ + NXU_IMAGE_FORMAT_BayerGRBG, /* GRBG GRBG GRBG GRBG GRBG GRBG */ + NXU_IMAGE_FORMAT_BayerGBRG, /* GBRG GBRG GBRG GBRG GBRG GBRG */ + NXU_IMAGE_FORMAT_BayerBGGR, /* BGGR BGGR BGGR BGGR BGGR BGGR */ + NXU_IMAGE_FORMAT_BayerGR, /* GBRG GBRG GBRG GBRG GBRG GBRG */ + NXU_IMAGE_FORMAT_BayerRG, /* RGGB RGGB RGGB RGGB RGGB RGGB */ + NXU_IMAGE_FORMAT_BayerGB, /* GBRG GBRG GBRG GBRG GBRG GBRG */ + NXU_IMAGE_FORMAT_BayerBG, /* BGGR BGGR BGGR BGGR BGGR BGGR */ + NXU_IMAGE_FORMAT_UNSUPPORTED, /* unsupported format */ + } NXU_IMAGE_FORMAT_E; + + /** + * @brief + * DO REMEMBER: That the image is a matrix, not a Vector + * DO REMEMBER: FREE the memory after Use + * DO REMEMBER: How to store the data in the memory accord to the image format + * + */ + typedef struct _nxuimage_s_ + { + NXU_S32 s32W; /* Width */ + NXU_S32 s32H; /* Height */ + NXU_U8* pData; /* Image Data */ + NXU_IMAGE_FORMAT_E eFormat; /* Image Format */ + } NXU_IMAGE_S; + + /* 3-ch uchar Image Definition */ + typedef struct _nxuimages3_s_ + { + NXU_S32 s32W; /* Image width */ + NXU_S32 s32H; /* Image height */ + NXU_U8 *pu8D1; /* Channel 1 data pointer */ + NXU_U8 *pu8D2; /* Channel 2 data pointer */ + NXU_U8 *pu8D3; /* Channel 3 data pointer */ + NXU_U32 u32Time; /* Time tag */ + NXU_IMAGE_FORMAT_E enFormat; /* image format pointer */ + NXU_U32 u32Flag; /* Reserved flag */ + } NXU_IMAGE3_S; + + /* Matrix with uchar data */ + typedef struct _nxudatamat8u_s_ + { + NXU_S32 s32Rows; /* Rows */ + NXU_S32 s32Cols; /* Columns */ + NXU_S32 s32Chns; /* Channels */ + NXU_U8 *pu8Data; /* Data Buffer */ + } NXU_MAT_8U_S; + + /* Matrix with short data */ + typedef struct _nxudatamat16s_s_ + { + NXU_S32 s32Rows; /* Rows */ + NXU_S32 s32Cols; /* Columns */ + NXU_S32 s32Chns; /* Channels */ + NXU_S16* ps16Data; /* Data Buffer */ + } NXU_MAT_16S_S; + + /* Matrix with int data */ + typedef struct _nxudatamat32s_s_ + { + NXU_S32 s32Rows; /* data rows */ + NXU_S32 s32Cols; /* Columns */ + NXU_S32 s32Chns; /* Channels */ + NXU_S32* ps32Data; /* Data Buffer */ + } NXU_MAT_32S_S; + + /* Matrix with float data */ + typedef struct _nxudatamat32f_s_ + { + NXU_S32 s32Rows; /* data rows */ + NXU_S32 s32Cols; /* Columns */ + NXU_S32 s32Chns; /* Channels */ + NXU_FLOAT* pf32Data; /* Data Buffer */ + } NXU_MAT_32F_S; + + /** + * @brief + * Do REMEMBER: How to store the data in the memory. + * if the mat store the image, do remember the data organization + * DO REMEMBER: Free the memory after use the matrix or image. + */ + typedef struct _nxumat_s_ + { + NXU_S32 s32C; /* Channel */ + NXU_S32 s32W; /* Width */ + NXU_S32 s32H; /* Height */ + NXU_VOID* pData; /* Data */ + } NXU_EXIMAGE_S, NXU_MAT_S, NXU_MATRIX_S; + + /* Image in RGB format */ + typedef struct _nxurgbimage_s_ + { + NXU_S32 s32W; /* Image width */ + NXU_S32 s32H; /* Image height */ + NXU_U8* pu8Data; /* Image data buffer */ + NXU_U32 u32Time; /* Time tag */ + } NXU_RGB_IMAGE_S; + + /* Image in HSV format */ + typedef struct _nxuhsvimage_s_ + { + NXU_S32 s32W; /* Image width */ + NXU_S32 s32H; /* Image height */ + NXU_FLOAT *pf32Data; /* Image data buffer */ + NXU_U32 u32Time; /* Time tag */ + } NXU_HSV_IMAGE_S; + + /* Gray image with uchar data */ + typedef struct _nxugrayimage_s_ + { + NXU_S32 s32W; /* Image width */ + NXU_S32 s32H; /* Image height */ + NXU_U8* pu8Data; /* Image data buffer */ + } NXU_GRAY_IMAGE_S; + + /* Gray image with short data, */ + typedef struct _nxugrayimage16s_s_ + { + NXU_S32 s32W; /* Image width */ + NXU_S32 s32H; /* Image height */ + NXU_S16* ps16Data; /* Image data buffer */ + } NXU_GRAY_IMAGE16_S; + + /* Gray Image with int data, maybe used in intergral image */ + typedef struct _nxugrayimage32s_s_ + { + NXU_S32 s32W; /* Image width */ + NXU_S32 s32H; /* Image height */ + NXU_S32* ps32Data; /* Image data buffer */ + } NXU_GRAY_IMAGE32_S; + + /************************************************************************/ + /* Deep learning or Machine Learning object. */ + /************************************************************************/ + typedef struct _nxudlmltgt_s_ + { + NXU_S32 s32LabelID; /* Label ID, name accord to project */ + NXU_RECT_S stRect; /* Target Bounding Box */ + NXU_FLOAT f32Prob; /* Probability */ + } NXU_Target_S; + +#ifdef __cplusplus +} +#endif /* end of __cplusplus*/ + +#endif /* end of file*/ \ No newline at end of file diff --git a/pkg/vqdcms/include/nxu_vqd_api.h b/pkg/vqdcms/include/nxu_vqd_api.h new file mode 100644 index 0000000..dbb41dd --- /dev/null +++ b/pkg/vqdcms/include/nxu_vqd_api.h @@ -0,0 +1,453 @@ +/** + * @file nxu_vqd_api.h + * @brief VQD: Video Quality Diagnostic + * + * 视频质量诊断, 包括偏色, 过亮, 过暗, 模糊, 噪点等 + * + * @author jwzhou (zhou24388@163.com) + * @version 1.0.0 + * @date 2024-06-26 + * + * @copyright Copyright (c) 2024 NXU Co,.Ltd. + * + * @par 修订历史: + * Date : 2024-07-17 + * version : 2.0.0 + * Author : jwzhou + * Log : 新增花屏和马赛克,内部识别增加深度学习版本 + * copyright: Copyright (c) 2024 NXU Co,.Ltd. + * + * @par 修改日志: + * Date : 2024-06-29 + * version : 1.0.1 + * Author : jwzhou + * Log : 修改几个默认的值 + * copyright: Copyright (c) 2024 NXU Co,.Ltd. + */ +#ifndef __NXU_VQD_API_H__ +#define __NXU_VQD_API_H__ + +#include "nxu_common.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* ********************************************************************** */ + /* .............................. Para Start ........................ */ + /* ********************************************************************** */ + /* 偏色参数 + NEW: 新增深度学习版本 20240717 + */ + typedef struct __nxu_vqd_color_para_s + { + /* 偏色判断值, 大于该值即为偏色, + 默认为0.18, 取值范围: 0~1, 建议范围: 0.1~0.5, + 该值设置过小, 误报会增多, 值设置的越大, 越不灵敏, 就是偏色严重才算偏色 + + NEW: 新增深度学习版本 20240717 + 默认为 0.1 取值范围: 0~1, 建议范围: 0.1~0.9, + 大于该值判定为偏色, 小于该值判定为正常, + */ + NXU_FLOAT f32ColorThr; + + /* 偏色次数比例, + 默认为0.5, 取值范围: 0~1, 建议范围: 0.3~0.9 */ + NXU_FLOAT f32ColorAbnNumRatio; + + NXU_FLOAT f32Resverd1; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd2; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd3; /* 保留,暂时不设置,默认 -999 */ + } NXU_VQD_Color_Para_S; + + /* 亮暗参数 + NEW: 新增深度学习版本 20240717 + */ + typedef struct __nxu_vqd_lightdark_para_s + { + /* 超过200的像素比例,过亮阈值, + 默认 0.1, 取值范围: 0~1, 建议范围: 0.1~0.5, + 值设置的越大, 越不灵敏, 就是非常亮才算过亮 + 值设置的越小, 越灵敏, 太小的话误报会很多 + + NEW: 新增深度学习版本 20240717 + 默认为 0.1 取值范围: 0~1, 建议范围: 0.1~0.9, + 大于该值判定为偏色, 小于该值判定为正常, + */ + NXU_FLOAT f32LightThr; + + /* 低于55的像素比例,过暗阈值, + 默认 0.4, 取值范围: 0~1, 建议范围: 0.2~0.6 + 值设置的越大, 越不灵敏, 就是非常暗才算过暗 + 值设置的越小, 越灵敏, 太小的话误报会很多 + + NEW: 新增深度学习版本 20240717 + 默认为 0.1 取值范围: 0~1, 建议范围: 0.1~0.9, + 大于该值判定为偏色, 小于该值判定为正常, + */ + NXU_FLOAT f32DarkThr; + + /* 偏暗或者偏亮次数比例, 连续多次检测出现的次数比例 + 默认为0.5, 取值范围: 0~1, 建议范围: 0.3~0.9 */ + NXU_FLOAT f32LgtDarkAbnNumRatio; + + NXU_FLOAT f32Resverd1; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd2; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd3; /* 保留,暂时不设置,默认 -999 */ + } NXU_VQD_LgtDark_Para_S; + + /* 清晰度参数 + NEW: 新增深度学习版本 20240717 + */ + typedef struct __nxu_vqd_clarity_para_s + { + /* 清晰度判断阈值, 小于该值判定为模糊, + 默认为0.4, 取值范围: 0~1, 建议范围: 0.3~0.99 + 值设置的越大, 越不灵敏, 太大的话误报模糊会很多 + 值设置的越小, 就是非常模糊才算模糊 + + NEW: 新增深度学习版本 20240717 + 默认为 0.1 取值范围: 0~1, 建议范围: 0.1~0.9, + 大于该值判定为偏色, 小于该值判定为正常, + */ + NXU_FLOAT f32ClarityThr; + + /* 清晰度异常次数比例, + 默认为0.5, 取值范围: 0~1, 建议范围: 0.3~0.9 */ + NXU_FLOAT f32ClarityAbnNumRatio; + + NXU_FLOAT f32Resverd1; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd2; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd3; /* 保留,暂时不设置,默认 -999 */ + } NXU_VQD_Clarity_Para_S; + + /* 噪声参数 + NEW: 新增深度学习版本 20240717 + */ + typedef struct __nxu_vqd_noise_para_s + { + /* 噪声判断阈值, + 默认为 0.3, 取值范围: 0~1, 建议范围: 0.2~0.8 + 设置过小, 容易误报, 设置过大, 容易漏报, 根据情况进行调整 + + NEW: 新增深度学习版本 20240717 + 默认为 0.1 取值范围: 0~1, 建议范围: 0.1~0.9, + 大于该值判定为偏色, 小于该值判定为正常, + */ + NXU_FLOAT f32NoiseThr; + + /* 噪声次数比例, + 默认为0.6, 取值范围: 0~1, 建议范围: 0.3~0.9 */ + NXU_FLOAT f32NoiseAbnNumRatio; + + NXU_FLOAT f32Resverd1; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd2; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd3; /* 保留,暂时不设置,默认 -999 */ + } NXU_VQD_Noise_Para_S; + + /* 遮挡参数 */ + typedef struct __nxu_vqd_occlusion_para_s + { + /* 遮挡判断阈值, 大于该值判定为遮挡 + 默认为0.1, 取值范围: 0~1, 建议范围: 0.05~0.5 + 设置过小, 容易误报, 设置过大, 容易漏报, 根据情况进行调整 */ + NXU_FLOAT f32OcclusionThr; + + /* 遮挡次数比例 + 默认为0.5, 取值范围: 0~1, 建议范围: 0.3~0.9 */ + NXU_FLOAT f32OcclusionAbnNumRatio; + + NXU_FLOAT f32Resverd1; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd2; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd3; /* 保留,暂时不设置,默认 -999 */ + } NXU_VQD_Occlusion_Para_S; + + /* 对比度参数 + NEW: 新增深度学习版本 20240717 + */ + typedef struct __nxu_vqd_contrast_para_s + { + /* 低对比度判断阈值, 低于此值判定为低对比度, + 默认为 0.2, 取值范围: 0~1, 建议范围: 0.1~0.3 + + NEW: 新增深度学习版本 20240717 + 默认为 0.1 取值范围: 0~1, 建议范围: 0.1~0.9, + 大于该值判定为偏色, 小于该值判定为正常, + */ + NXU_FLOAT f32CtraLowThr; + + /* 高对比度判断阈值, 高于该值判定为高对比度, + 默认为 0.8, 取值范围: 0~1, 建议范围: 0.7~0.9 */ + NXU_FLOAT f32CtraHighThr; + + /* 对比度异常次数比例, + 默认为0.5, 取值范围: 0~1, 建议范围: 0.3~0.9 */ + NXU_FLOAT f32CtraAbnNumRatio; + + NXU_FLOAT f32Resverd1; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd2; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd3; /* 保留,暂时不设置,默认 -999 */ + + } NXU_VQD_Contrast_Para_S; + + /* 蓝屏参数 + NEW: 新增深度学习版本 20240717 + */ + typedef struct __nxu_vqd_blue_para_s + { + /* 蓝屏判断阈值, 蓝色像素占图像面积比例, + 默认为 0.6, 取值范围: 0~1, 建议范围 0.4~0.9 + + NEW: 新增深度学习版本 20240717 + 默认为 0.1 取值范围: 0~1, 建议范围: 0.1~0.9, + 大于该值判定为偏色, 小于该值判定为正常, + */ + NXU_FLOAT f32BlueThr; + + /* 蓝屏次数比例, 连续多帧中蓝色占比 + 默认为0.5, 取值范围: 0~1, 建议范围: 0.3~0.9 */ + NXU_FLOAT f32BlueAbnNumRatio; + + NXU_FLOAT f32Resverd1; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd2; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd3; /* 保留,暂时不设置,默认 -999 */ + } NXU_VQD_Blue_Para_S; + + /* 抖动参数, 做抖动检测, 尽量隔帧取帧做, */ + typedef struct __nxu_vqd_shark_para_s + { + /* 抖动阈值参数 + 全局运动均值, 无论是目标移动还是画面抖动, 全局运动均值相对来讲都会比较大, + 默认为 0.2, 取值范围: 0~10, 建议范围: 0.1~0.8 */ + NXU_FLOAT f32SharkThr; + + /* 出现抖动次数的比例, + 默认为0.2, 取值范围: 0~1, 建议范围: 0.1~0.6 */ + NXU_FLOAT f32SharkAbnNumRatio; + + /* 全局运动幅度方差阈值, 理论上来讲, 抖动为全局画面移动, 方向幅度具有一致性, 方差应较小 + 默认为0.2, 取值范围: 0~1, 建议范围: 0.05~0.5 + 如果内部有很多运动目标, 该值较大, 所以设置较大, 会使得在有运动目标时, 判定为抖动 */ + NXU_FLOAT f32Resverd1; + + /* 全局运动方向方差阈值, 小于该值时, 判定为全局运动, 可能会抖动 + 默认为0.2, 取值范围: 0~1, 建议范围: 0.05~0.5 + 如果内部有很多运动目标, 该值较大, 所以设置较大, 会使得在有运动目标时, 判定为抖动 */ + NXU_FLOAT f32Resverd2; + + NXU_FLOAT f32Resverd3; /* 保留,暂时不设置,默认 -999 */ + } NXU_VQD_Shark_Para_S; + + /* 冻结参数 */ + typedef struct __nxu_vqd_freeze_para_s + { + /* 冻结阈值参数 + 静止的像素比例, 默认为0.999, 取值范围: 0.8~1, 建议范围: 0.99~1 + 如果画面静止, 该值比较大, 甚至会接近于1, */ + NXU_FLOAT f32FreezeThr; /* 冻结阈值 */ + + /* 冻结帧数占得比例, 尽量设置的大一些, 避免那些无运动目标的静止监控画面 + 默认为0.99, 取值范围: 0.8~1, 建议范围: 0.95~1, */ + NXU_FLOAT f32FreezeAbnNumRatio; + + NXU_FLOAT f32Resverd1; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd2; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd3; /* 保留,暂时不设置,默认 -999 */ + } NXU_VQD_Freeze_Para_S; + + /* 马赛克检测 + NEW: 新增深度学习版本 20240717 + */ + typedef struct __nxu_vqd_mosaic_para_s + { + /* 马赛克阈值参数 + NEW: 新增深度学习版本 20240717 + 默认为 0.1 取值范围: 0~1, 建议范围: 0.1~0.9, + 大于该值判定为偏色, 小于该值判定为正常, + */ + NXU_FLOAT f32MosaicThr; + + /* 马赛克次数比例, 连续多帧中马赛克占比 + 默认为0.5,取值范围: 0~1, 建议范围: 0.3 + 连续多帧中马赛克占比 */ + NXU_FLOAT f32MosaicAbnNumRatio; + + NXU_FLOAT f32Resverd1; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd2; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd3; /* 保留,暂时不设置,默认 -999 */ + } NXU_VQD_Mosaic_Para_S; + + /* 花屏检测 NEW NEW NEW NEW NEW + NEW: 新增深度学习版本 20240717 + */ + typedef struct __nxu_vqd_flower_para_s + { + /* 花屏阈值参数 + NEW: 新增深度学习版本 20240717 + 默认为 0.1 取值范围: 0~1, 建议范围: 0.1~0.9, + 大于该值判定为偏色, 小于该值判定为正常, + */ + NXU_FLOAT f32FlowerThr; + + /* 花屏次数比例, 连续多帧中花屏占比 + 默认为0.5, 取值范围: 0~1, 建议范围: 0.3 + 连续多帧中花屏占比 */ + NXU_FLOAT f32FlowerAbnNumRatio; + + NXU_FLOAT f32Resverd1; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd2; /* 保留,暂时不设置,默认 -999 */ + NXU_FLOAT f32Resverd3; /* 保留,暂时不设置,默认 -999 */ + } NXU_VQD_Flower_Para_S; + + typedef enum __nxu_vqd_func_enable_type_e + { + NXU_VQD_DISABLE_ALL = 0x00000000, /* 所有功能关闭 */ + NXU_VQD_ENABLE_COLOR = 0x00000001, /* 偏色检测 */ + NXU_VQD_ENABLE_LGTDARK = 0x00000002, /* 亮度检测 */ + NXU_VQD_ENABLE_CLARITY = 0x00000004, /* 模糊检测 */ + NXU_VQD_ENABLE_NOISE = 0x0000008, /* 噪声检测 */ + NXU_VQD_ENABLE_CONTRAST = 0x00000010, /* 对比度检测 */ + NXU_VQD_ENABLE_OCCLUSION = 0x00000020, /* 遮挡检测 */ + NXU_VQD_ENABLE_BLUE = 0x00000040, /* 蓝屏检测 */ + NXU_VQD_ENABLE_SHARK = 0x00000100, /* 抖动检测 */ + NXU_VQD_ENABLE_FREEZE = 0x00000200, /* 冻结检测 */ + NXU_VQD_ENABLE_MOSAIC = 0x00000400, /* 马赛克检测 NEW: 新增深度学习版本 20240717*/ + NXU_VQD_ENABLE_FLOWER = 0x00000800, /* 花屏检测 NEW: 新增深度学习版本 20240717*/ + NXU_VQD_ENABLE_ALL = 0x0FFFFFFF, /* 所有功能打开 */ + } NXU_VQD_FuncEnable_Type_E; + + /* 总参数 */ + typedef struct __nxu_vqd_para_s + { + NXU_S32 s32VecFrmNum; /* 连续分析帧数(2-64), 默认为10, 最大为 64 */ + NXU_S32 s32EnableFunc; /* 功能使能,默认为 NXU_VQD_ENABLE_ALL,多项功能用或 */ + NXU_VQD_Color_Para_S stColorPara; /* 偏色参数 */ + NXU_VQD_LgtDark_Para_S stLgtDarkPara; /* 亮暗参数 */ + NXU_VQD_Clarity_Para_S stClarityPara; /* 清晰度参数 */ + NXU_VQD_Noise_Para_S stNoisePara; /* 噪声参数 */ + NXU_VQD_Contrast_Para_S stContrastPara; /* 对比度参数 */ + NXU_VQD_Occlusion_Para_S stOcclusionPara; /* 遮挡参数 */ + NXU_VQD_Blue_Para_S stBluePara; /* 蓝屏参数 */ + NXU_VQD_Shark_Para_S stSharkPara; /* 抖动参数 */ + NXU_VQD_Freeze_Para_S stFreezePara; /* 冻结参数 */ + NXU_VQD_Mosaic_Para_S stMosaicPara; /* 马赛克参数 NEW: 新增深度学习版本 20240717*/ + NXU_VQD_Flower_Para_S stFlowerPara; /* 花屏参数 NEW: 新增深度学习版本 20240717*/ + + NXU_BOOL bUseDeepLearning; /* 是否使用深度学习版本, 默认使用深度学习版本 NEW: 20240717*/ + } NXU_VQD_Para_S; + + /** + * 如果返回的是多个异常类型, 则可以用与或来确定具体异常类型 + */ + typedef enum __nxu_vqd_abnormal_type_e + { + NXU_VQD_NORMAL = 0x00000000, /* 正常, 无异常 */ + NXU_VQD_ABN_COLORDEV = 0x00000001, /* 偏色异常 */ + NXU_VQD_ABN_LIGHT = 0x00000002, /* 过亮异常 */ + NXU_VQD_ABN_DARK = 0x00000004, /* 过暗异常 */ + NXU_VQD_ABN_CLARITY = 0x00000008, /* 清晰度异常 */ + NXU_VQD_ABN_NOISE = 0x00000010, /* 噪声异常 */ + NXU_VQD_ABN_CONTRAST = 0x00000020, /* 对比度异常 */ + NXU_VQD_ABN_OCCLUSION = 0x00000040, /* 遮挡异常 */ + NXU_VQD_ABN_BLUE = 0x00000080, /* 蓝屏异常 */ + NXU_VQD_ABN_SHARK = 0x00000100, /* 抖动异常 */ + NXU_VQD_ABN_FREEZE = 0x00000200, /* 冻结异常 */ + NXU_VQD_ABN_MOSAIC = 0x00000400, /* 马赛克异常 NEW: 新增深度学习版本 20240717*/ + NXU_VQD_ABN_FLOWER = 0x00000800, /* 花屏异常 NEW: 新增深度学习版本 20240717*/ + NXU_VQD_ABN_ALL = 0x0FFFFFFF, /* 所有的异常 */ + NXU_VQD_ABN_UNKNOWN = 0xF0000000, /* 序列不满时, 返回未知 */ + } NXU_VQD_Abnormal_Type_E; + + /* 异常结果 + 当前各异常返回出来的值,作为参考,外面也可以存到列表中进行应用 */ + typedef struct __nxu_vqd_result_s + { + NXU_S32 s32AbnormalType; /* 异常类型,多种类型的,利用与或来确定异常类型 */ + NXU_FLOAT f32ColorDev; /* 偏色检测 */ + NXU_FLOAT f32LgtDark; /* 亮度检测 */ + NXU_FLOAT f32Dark; /* 暗度检测 */ + NXU_FLOAT f32Clarity; /* 清晰度检测 */ + NXU_FLOAT f32Noise; /* 噪声检测 */ + NXU_FLOAT f32Contrast; /* 对比度检测 */ + NXU_FLOAT f32Blue; /* 蓝屏检测 */ + + NXU_FLOAT f32Occlusion; /* 遮挡检测 */ + NXU_FLOAT f32Shark; /* 抖动检测 */ + NXU_FLOAT f32Freeze; /* 冻结检测 */ + + NXU_FLOAT f32Mosaic; /* 马赛克检测 NEW: 新增深度学习版本 20240717*/ + NXU_FLOAT f32Flower; /* 花屏检测 NEW: 新增深度学习版本 20240717*/ + + NXU_S32 s32Resverd1; /* 保留,暂时不设置,默认 -999 */ + NXU_S32 s32Resverd2; /* 保留,暂时不设置,默认 -999 */ + NXU_S32 s32Resverd3; /* 保留,暂时不设置,默认 -999 */ + } NXU_VQD_Result_S; + + /* ********************************************************************** */ + /* .............................. API Start ........................ */ + /* ********************************************************************** */ + /** + * @brief 创建算法句柄,加载算法模型,只用创建一次,就可以循环使用,每一次创建对应一次销毁 + * + * @param phVQD 算法句柄 + * @return NXU_EXPORTS + */ + NXU_EXPORTS NXU_STATUS_CODE_E NXU_VQD_Create(NXU_HANDLE *phVQD); + + /** + * @brief 销毁算法句柄,使用完后记得销毁算法句柄 + * + * @param hVQD 算法句柄 + * @return 算法状态 + */ + NXU_EXPORTS NXU_STATUS_CODE_E NXU_VQD_Destroy(NXU_HANDLE hVQD); + + /** + * @brief 获取算法的版本号 + * + * @param pcLibVerStr 算法库版本号 + * @return 算法状态 + */ + NXU_EXPORTS NXU_STATUS_CODE_E NXU_VQD_GetLibVer(NXU_S8 *pcLibVerStr); + + /** + * @brief 算法配置 + * + * @param hVQD 算法句柄 + * @param pstPara 算法参数 + * + * @return 算法状态 + */ + NXU_EXPORTS NXU_STATUS_CODE_E + NXU_VQD_Config(NXU_HANDLE hVQD, const NXU_VQD_Para_S *pstPara); + + /** + * @brief 算法处理 + * + * @param hVQD 算法句柄 + * @param pstImage 图像数据 + * @return 算法状态 + */ + NXU_EXPORTS NXU_STATUS_CODE_E + NXU_VQD_Process(NXU_HANDLE hVQD, const NXU_IMAGE_S *pstImage); + + /** + * @brief 获取结果 + * + * @param hVQD 算法句柄 + * @param pstVQDResult 结果 + * @return 算法状态 + */ + NXU_EXPORTS NXU_STATUS_CODE_E + NXU_VQD_GetResults(NXU_HANDLE hVQD, NXU_VQD_Result_S *pstVQDResult); + /* ********************************************************************** */ + /* .............................. API END.............................. */ + /* ********************************************************************** */ + +#ifdef __cplusplus +} +#endif + +#endif // !__NXU_VQD_API_H__ \ No newline at end of file diff --git a/pkg/vqdcms/mode.go b/pkg/vqdcms/mode.go new file mode 100644 index 0000000..8551d50 --- /dev/null +++ b/pkg/vqdcms/mode.go @@ -0,0 +1,347 @@ +package vqdcms + +import ( + "database/sql/driver" + "encoding/json" + "time" +) + +type Abnormal struct { + Value float32 `json:"value"` + Name string `json:"name"` +} + +type abnormal []Abnormal + +func (r *abnormal) Scan(val interface{}) error { + b, _ := val.([]byte) + return json.Unmarshal(b, r) +} + +func (r abnormal) Value() (driver.Value, error) { + return json.Marshal(r) +} + +type DefaultValue struct { + Thr1 float32 `json:"thr1"` + Name1 string `json:"name1"` + Thr2 float32 `json:"thr2"` + Name2 string `json:"name2"` + Ratio float32 `json:"ratio"` //比例 +} + +type defaultValue []DefaultValue + +func (r *defaultValue) Scan(val interface{}) error { + b, _ := val.([]byte) + return json.Unmarshal(b, r) +} + +func (r defaultValue) Value() (driver.Value, error) { + return json.Marshal(r) +} + +type AbnormalModel struct { + ID int `gorm:"primary_key" json:"id"` + ChannelID string `json:"channel_id"` + ChannelName string `json:"channel_name"` + AlgoID int `json:"algo_id"` + AlgoName string `json:"algo_name"` + TaskName string `json:"task_name"` + FilePath string `json:"file_path"` + IsDeep bool `json:"is_deep"` + Abnormals abnormal `gorm:"type:json" json:"abnormals"` + DefaultValues defaultValue `gorm:"type:json" json:"default_values"` //设置的默认阈值 + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +/* 偏色参数 */ +type VQDColorPara struct { + ColorThr float32 /* 偏色判断值,*/ + + /* 偏色次数比例, + 默认为0.5, 取值范围: 0~1, 建议范围: 0.1~0.9 */ + ColorAbnNumRatio float32 + + Resverd1 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd2 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd3 float32 /* 保留,暂时不设置,默认 -999 */ +} + +/* 亮暗参数 */ +// OK +type VQDLgtDarkPara struct { + /* 超过200的像素比例,过亮阈值, + 默认 0.1, 取值范围: 0~1, 建议范围: 0.1~0.5, + 值设置的越大, 越不灵敏, 就是非常亮才算过亮 + 值设置的越小, 越灵敏, 太小的话误报会很多 */ + LightThr float32 + + /* 低于55的像素比例,过暗阈值, + 默认 0.4, 取值范围: 0~1, 建议范围: 0.2~0.6 + 值设置的越大, 越不灵敏, 就是非常暗才算过暗 + 值设置的越小, 越灵敏, 太小的话误报会很多 */ + DarkThr float32 + + /* 偏暗或者偏亮次数比例, 连续多次检测出现的次数比例 + 默认为0.5, 取值范围: 0~1, 建议范围: 0.1~0.9 */ + LgtDarkAbnNumRatio float32 + + Resverd1 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd2 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd3 float32 /* 保留,暂时不设置,默认 -999 */ +} + +/* 清晰度参数 */ +// OK +type VQDClarityPara struct { + /* 清晰度判断阈值, 小于该值判定为模糊, + 默认为0.4, 取值范围: 0~1, 建议范围: 0.3~0.99 + 值设置的越大, 越不灵敏, 太大的话误报模糊会很多 + 值设置的越小, 就是非常模糊才算模糊 */ + ClarityThr float32 + + /* 清晰度异常次数比例, + 默认为0.5, 取值范围: 0~1, 建议范围: 0.1~0.9 */ + ClarityAbnNumRatio float32 + + Resverd1 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd2 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd3 float32 /* 保留,暂时不设置,默认 -999 */ +} + +/* 噪声参数 */ +type VQDNoisePara struct { + NoiseThr float32 /* 噪声判断阈值,默认为 35 */ + + /* 噪声次数比例, + 默认为0.5, 取值范围: 0~1, 建议范围: 0.1~0.9 */ + NoiseAbnNumRatio float32 + Resverd1 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd2 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd3 float32 /* 保留,暂时不设置,默认 -999 */ +} + +/* 对比度参数 */ +type VQDContrastPara struct { + CtraLowThr float32 /* 低对比度判断阈值,默认为 30 */ + CtraHighThr float32 /* 高对比度判断阈值,默认为 120 */ + + /* 对比度异常次数比例, + 默认为0.5, 取值范围: 0~1, 建议范围: 0.1~0.9 */ + CtraAbnNumRatio float32 + Resverd1 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd2 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd3 float32 /* 保留,暂时不设置,默认 -999 */ +} + +/* 遮挡参数 */ +type VQDOcclusionPara struct { + OcclusionThr float32 /* 遮挡判断阈值,默认为 6 */ + + /* 遮挡次数比例 + 默认为0.5, 取值范围: 0~1, 建议范围: 0.1~0.9 */ + OcclusionAbnNumRatio float32 + Resverd1 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd2 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd3 float32 /* 保留,暂时不设置,默认 -999 */ +} + +/* 蓝屏参数 */ +// OK +type VQDBluePara struct { + /* 蓝屏判断阈值, 蓝色像素占图像面积比例, + 默认为 0.6, 取值范围: 0~1, 建议范围 0.4~0.9 */ + BlueThr float32 + + /* 蓝屏次数比例, 连续多帧中蓝色占比 + 默认为0.5, 取值范围: 0~1, 建议范围: 0.1~0.9 */ + BlueAbnNumRatio float32 + Resverd1 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd2 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd3 float32 /* 保留,暂时不设置,默认 -999 */ +} + +/* 抖动参数, 做抖动检测, 尽量隔帧取帧做, */ +// OK +type VQDSharkPara struct { + /* 抖动阈值参数 + 全局运动均值, 无论是目标移动还是画面抖动, 全局运动均值相对来讲都会比较大, + 默认为 0.2, 取值范围: 0~10, 建议范围: 0.1~0.8 */ + SharkThr float32 + + /* 出现抖动次数的比例, + 默认为0.2, 取值范围: 0~1, 建议范围: 0.1~0.6 */ + SharkAbnNumRatio float32 + + /* 全局运动幅度方差阈值, 理论上来讲, 抖动为全局画面移动, 方向幅度具有一致性, 方差应较小 + 默认为0.2, 取值范围: 0~1, 建议范围: 0.05~0.5 + 如果内部有很多运动目标, 该值较大, 所以设置较大, 会使得在有运动目标时, 判定为抖动 */ + Resverd1 float32 + + /* 全局运动方向方差阈值, 小于该值时, 判定为全局运动, 可能会抖动 + 默认为0.2, 取值范围: 0~1, 建议范围: 0.05~0.5 + 如果内部有很多运动目标, 该值较大, 所以设置较大, 会使得在有运动目标时, 判定为抖动 */ + Resverd2 float32 + Resverd3 float32 /* 保留,暂时不设置,默认 -999 */ +} + +/* 冻结参数 */ +// OK +type VQDFreezePara struct { + /* 冻结阈值参数 + 静止的像素比例, 默认为0.999, 取值范围: 0.8~1, 建议范围: 0.99~1 + 如果画面静止, 该值比较大, 甚至会接近于1, */ + FreezeThr float32 /* 冻结阈值 */ + + /* 冻结帧数占得比例, 尽量设置的大一些, 避免那些无运动目标的静止监控画面 + 默认为0.99, 取值范围: 0.8~1, 建议范围: 0.95~1, */ + FreezeAbnNumRatio float32 + Resverd1 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd2 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd3 float32 /* 保留,暂时不设置,默认 -999 */ +} + +/* +马赛克检测 + + NEW: 新增深度学习版本 2.0.0 +*/ +type VQDMosaicPara struct { + /* 马赛克阈值参数 + NEW: 新增深度学习版本 20240717 + 默认为 0.1 取值范围: 0~1, 建议范围: 0.1~0.9, + 大于该值判定为偏色, 小于该值判定为正常, + */ + MosaicThr float32 + + /* 马赛克次数比例, 连续多帧中马赛克占比 + 默认为0.5,取值范围: 0~1, 建议范围: 0.3 + 连续多帧中马赛克占比 */ + MosaicAbnNumRatio float32 + + Resverd1 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd2 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd3 float32 /* 保留,暂时不设置,默认 -999 */ +} + +/* +花屏检测 NEW NEW NEW NEW NEW + + NEW: 新增深度学习版本 2.0.0 +*/ +type VQDFlowerPara struct { + /* 花屏阈值参数 + NEW: 新增深度学习版本 20240717 + 默认为 0.1 取值范围: 0~1, 建议范围: 0.1~0.9, + 大于该值判定为偏色, 小于该值判定为正常, + */ + FlowerThr float32 + + /* 花屏次数比例, 连续多帧中花屏占比 + 默认为0.5, 取值范围: 0~1, 建议范围: 0.3 + 连续多帧中花屏占比 */ + FlowerAbnNumRatio float32 + + Resverd1 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd2 float32 /* 保留,暂时不设置,默认 -999 */ + Resverd3 float32 /* 保留,暂时不设置,默认 -999 */ +} + +type VQDPara struct { + VecFrmNum int /* 连续分析帧数(2-64), 默认为10, 最大为 64 */ + UseDeepLearning bool /* 是否使用深度学习版本, 默认使用深度学习版本 NEW: 20240717 */ + EnableFunc int /* 功能使能,默认为 NXU_VQD_ENABLE_ALL,多项功能用或 */ + ColorPara VQDColorPara /* 偏色参数 */ + LgtDarkPara VQDLgtDarkPara /* 亮暗参数 */ + ClarityPara VQDClarityPara /* 清晰度参数 */ + NoisePara VQDNoisePara /* 噪声参数 */ + ContrastPara VQDContrastPara /* 对比度参数 */ + OcclusionPara VQDOcclusionPara /* 遮挡参数 */ + BluePara VQDBluePara /* 蓝屏参数 */ + SharkPara VQDSharkPara /* 抖动参数 */ + FreezePara VQDFreezePara /* 冻结参数 */ + + MosaicPara VQDMosaicPara /* 马赛克检测 */ + FlowerPara VQDFlowerPara /* 花屏检测 */ +} + +// config cvrdo.VQDAlgoConfig +func NewVQDPara() VQDPara { + return VQDPara{ + VecFrmNum: 2, + UseDeepLearning: true, + EnableFunc: GetAlgoEnable([]string{"vqd_config", "vqd_lgt_dark", "vqd_blue", "vqd_clarity", "vqd_shark", "vqd_freeze", + "vqd_color", "vqd_occlusion", "vqd_noise", "vqd_contrast", "vqd_mosaic", "vqd_flower"}), + ColorPara: VQDColorPara{ + ColorThr: 0.3, + ColorAbnNumRatio: 0.6, + }, + LgtDarkPara: VQDLgtDarkPara{ + LightThr: 0.3, + DarkThr: 0.4, + LgtDarkAbnNumRatio: 0.6, + }, + ClarityPara: VQDClarityPara{ + ClarityThr: 0.5, + ClarityAbnNumRatio: 0.6, + }, + NoisePara: VQDNoisePara{ + NoiseThr: 0.3, + NoiseAbnNumRatio: 0.6, + }, + ContrastPara: VQDContrastPara{ + CtraLowThr: 0.3, + CtraHighThr: 0.8, + CtraAbnNumRatio: 0.6, + }, + OcclusionPara: VQDOcclusionPara{ + OcclusionThr: 0.1, + OcclusionAbnNumRatio: 0.6, + }, + BluePara: VQDBluePara{ + BlueThr: 0.3, + BlueAbnNumRatio: 0.6, + }, + SharkPara: VQDSharkPara{ + SharkThr: 0.2, + SharkAbnNumRatio: 0.2, + }, + FreezePara: VQDFreezePara{ + FreezeThr: 0.999, + FreezeAbnNumRatio: 0.99, + }, + MosaicPara: VQDMosaicPara{ + MosaicThr: 0.3, + MosaicAbnNumRatio: 0.6, + }, + FlowerPara: VQDFlowerPara{ + FlowerThr: 0.3, + FlowerAbnNumRatio: 0.6, + }, + } +} + +/* +异常结果 + + 当前各异常返回出来的值,作为参考,外面也可以存到列表中进行应用 +*/ +type VQDResult struct { + AbnormalType int /* 异常类型,多种类型的,利用与或来确定异常类型 */ + ColorDev float32 /* 偏色检测 */ + LgtDark float32 /* 亮暗检测 */ + Clarity float32 /* 清晰度检测 */ + Noise float32 /* 噪声检测 */ + Contrast float32 /* 对比度检测 */ + Occlusion float32 /* 遮挡检测 */ + Blue float32 /* 蓝屏检测 */ + Shark float32 /* 抖动检测 */ + Freeze float32 /* 冻结检测 */ + Mosaic float32 /* 马赛克检测 NEW: 新增深度学习版本 2.0.0*/ + Flower float32 /* 花屏检测 NEW: 新增深度学习版本 2.0.0*/ + Resverd1 int /* 保留,暂时不设置,默认 -999 */ + Resverd2 int /* 保留,暂时不设置,默认 -999 */ + Resverd3 int /* 保留,暂时不设置,默认 -999 */ +} diff --git a/pkg/vqdcms/type.go b/pkg/vqdcms/type.go new file mode 100644 index 0000000..5163db7 --- /dev/null +++ b/pkg/vqdcms/type.go @@ -0,0 +1,92 @@ +package vqdcms + +const NXU_VQD_DISABLE_ALL = 0x00000000 /* 所有功能关闭 */ +const NXU_VQD_ENABLE_COLOR = 0x00000001 /* 偏色检测 */ +const NXU_VQD_ENABLE_LGTDARK = 0x00000002 /* 过亮过暗检测 */ +const NXU_VQD_ENABLE_CLARITY = 0x00000004 /* 模糊检测 */ +const NXU_VQD_ENABLE_NOISE = 0x0000008 /* 噪声检测 */ +const NXU_VQD_ENABLE_CONTRAST = 0x00000010 /* 对比度检测 */ +const NXU_VQD_ENABLE_OCCLUSION = 0x00000020 /* 遮挡检测 */ +const NXU_VQD_ENABLE_BLUE = 0x00000040 /* 蓝屏检测 */ +const NXU_VQD_ENABLE_SHARK = 0x00000100 /* 抖动检测 */ +const NXU_VQD_ENABLE_FREEZE = 0x00000200 /* 冻结检测 */ +const NXU_VQD_ENABLE_MOSAIC = 0x00000400 /* 马赛克检测 NEW: 新增深度学习版本 20240717*/ +const NXU_VQD_ENABLE_FLOWER = 0x00000800 /* 花屏检测 NEW: 新增深度学习版本 20240717*/ +const NXU_VQD_ENABLE_ALL = 0x0FFFFFFF /* 所有功能打开 */ + +var TypeMap = map[string]int{ + "vqd_color": NXU_VQD_ENABLE_COLOR, + "vqd_lgt_dark": NXU_VQD_ENABLE_LGTDARK, + "vqd_clarity": NXU_VQD_ENABLE_CLARITY, + "vqd_noise": NXU_VQD_ENABLE_NOISE, + "vqd_contrast": NXU_VQD_ENABLE_CONTRAST, + "vqd_occlusion": NXU_VQD_ENABLE_OCCLUSION, + "vqd_blue": NXU_VQD_ENABLE_BLUE, + "vqd_shark": NXU_VQD_ENABLE_SHARK, + "vqd_freeze": NXU_VQD_ENABLE_FREEZE, + "vqd_mosaic": NXU_VQD_ENABLE_MOSAIC, + "vqd_flower": NXU_VQD_ENABLE_FLOWER, +} + +func GetAlgoEnable(str []string) int { + v := NXU_VQD_DISABLE_ALL + if len(str) <= 0 { + return v + } + for i := 0; i < len(str); i++ { + if vqd, ok := TypeMap[str[i]]; ok { + v |= vqd + } + } + return v +} + +/** + * 如果返回的是多个异常类型, 则可以用与或来确定具体异常类型 + */ +const NXU_VQD_NORMAL = 0x00000000 /* 正常, 无异常 */ +const NXU_VQD_ABN_COLORDEV = 0x00000001 /* 偏色异常 */ +const NXU_VQD_ABN_LIGHT = 0x00000002 /* 过亮异常 */ +const NXU_VQD_ABN_DARK = 0x00000004 /* 过暗异常 */ +const NXU_VQD_ABN_CLARITY = 0x00000008 /* 清晰度异常 */ +const NXU_VQD_ABN_NOISE = 0x00000010 /* 噪声异常 */ +const NXU_VQD_ABN_CONTRAST = 0x00000020 /* 对比度异常 */ +const NXU_VQD_ABN_OCCLUSION = 0x00000040 /* 遮挡异常 */ +const NXU_VQD_ABN_BLUE = 0x00000080 /* 蓝屏异常 */ +const NXU_VQD_ABN_SHARK = 0x00000100 /* 抖动异常 */ +const NXU_VQD_ABN_FREEZE = 0x00000200 /* 冻结异常 */ +const NXU_VQD_ABN_MOSAIC = 0x00000400 /* 马赛克异常 NEW: 新增深度学习版本 20240717*/ +const NXU_VQD_ABN_FLOWER = 0x00000800 /* 花屏异常 NEW: 新增深度学习版本 20240717*/ +const NXU_VQD_ABN_ALL = 0x0FFFFFFF /* 所有的异常 */ +const NXU_VQD_ABN_UNKNOWN = 0xF0000000 /* 序列不满时, 返回位置 */ + +var ALNORMAL_NAMES = map[int]string{ + NXU_VQD_NORMAL: "无异常", + NXU_VQD_ABN_COLORDEV: "偏色异常", + NXU_VQD_ABN_LIGHT: "过亮异常", + NXU_VQD_ABN_DARK: "过暗异常", + NXU_VQD_ABN_CLARITY: "清晰度异常", + NXU_VQD_ABN_NOISE: "噪声异常", + NXU_VQD_ABN_CONTRAST: "对比度异常", + NXU_VQD_ABN_OCCLUSION: "遮挡异常", + NXU_VQD_ABN_BLUE: "蓝屏异常", + NXU_VQD_ABN_SHARK: "抖动异常", + NXU_VQD_ABN_FREEZE: "冻结异常", + NXU_VQD_ABN_MOSAIC: "马赛克异常", + NXU_VQD_ABN_FLOWER: "花屏异常", + NXU_VQD_ABN_ALL: "所有的异常", + NXU_VQD_ABN_UNKNOWN: "序列不满", +} + +type Children struct { + Name string `json:"name"` + Type string `json:"type"` + Placeholder string `json:"placeholder"` + Value interface{} `json:"value"` +} + +type ArithmeticType struct { + Name string `json:"name"` + Type string `json:"type"` + Children []Children `json:"children"` +} diff --git a/pkg/vqdcms/vqd.go b/pkg/vqdcms/vqd.go new file mode 100644 index 0000000..1fbd3fd --- /dev/null +++ b/pkg/vqdcms/vqd.go @@ -0,0 +1,437 @@ +package vqdcms + +/* +#include +#include +#include +*/ +import "C" +import ( + "easyvqd/pkg/decoder" + "fmt" + "github.com/shirou/gopsutil/v4/mem" + "log/slog" + "os" + "path/filepath" + "runtime/debug" + "strings" + "sync" + "sync/atomic" + "time" + "unsafe" +) + +const MAX_STREAM_CHAN_NUM = 256 + +type VideoInfoVQD struct { + mu sync.RWMutex + VQDHandle uintptr + Params VQDPara + IsCreateSuccess bool +} + +type VQDHandle struct { + running uint32 + TaskID int // 标识ID + ChnID string // 通道ID + Plans string // 任务计划 + data chan ChanData + dataLock sync.RWMutex + cb VQDResultCB + handle *VideoInfoVQD + name string // 算法名称 + file *os.File + decoder *decoder.VideoDecoder + fileLock sync.RWMutex +} + +type VQDResultCB func(AbnormalModel) + +type ChanData struct { + data []byte + w int + h int + now time.Time +} + +func IsCurTimeInRecordPlan(recordPlanNew string, now time.Time) bool { + return false +} + +func NewVQDHandle(cb VQDResultCB, taskId int, chnId string) *VQDHandle { + v := &VQDHandle{ + running: 0, + decoder: &decoder.VideoDecoder{}, + ChnID: chnId, + TaskID: taskId, + data: make(chan ChanData, MAX_STREAM_CHAN_NUM), + cb: cb, + handle: &VideoInfoVQD{}, + } + err := v.decoder.Create() + if err != nil { + slog.Error("decoder Create ", "taskId", chnId, "err", err) + } + return v +} + +func (v *VQDHandle) SetVQDConfig(params VQDPara) error { + return v.handle.Config(params, params.EnableFunc, 10) +} + +func (v *VQDHandle) GetHandle() *VideoInfoVQD { + return v.handle +} +func (v *VQDHandle) Create(params VQDPara) *VQDHandle { + if atomic.LoadUint32(&v.running) == 1 { + return v + } + //if v.file == nil { + // filename := filepath.Join(utils.CWD(), "logs", fmt.Sprintf("%016p_vqdhandle.log", v)) + // file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, os.ModePerm) + // if err == nil { + // v.fileLock.Lock() + // v.file = file + // v.file.WriteString("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓\r\n") + // v.fileLock.Unlock() + // } else { + // llog.Info("创建文件失败:%s", filename) + // } + //} + err := v.handle.Create(params, params.EnableFunc, 10) + if err != nil { + //llog.Info("vqd create fail:%s", err.Error()) + return v + } + atomic.StoreUint32(&v.running, 1) + go v.RunFrame() + return v +} + +func (v *VQDHandle) Destroy() { + if v.file != nil { + v.fileLock.Lock() + v.file.WriteString("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑\r\n") + v.file.Close() + v.file = nil + v.fileLock.Unlock() + } + if v.data != nil { + close(v.data) + } + v.data = nil + if atomic.LoadUint32(&v.running) == 1 { + atomic.StoreUint32(&v.running, 0) + v.handle.Destroy() + } +} + +func (v *VQDHandle) RunFrame() { + defer func() { + if e := recover(); e != nil { + print(fmt.Sprintf("RunFrame---%s\n", e)) + print(fmt.Sprintf("%s\n", string(debug.Stack()))) + } + }() + cvqdImgsDir := filepath.Join(CWD(), "vqd_images", fmt.Sprintf("%d", v.TaskID)) + cvqdImgsDir = filepath.ToSlash(cvqdImgsDir) + if err := os.MkdirAll(cvqdImgsDir, os.ModePerm); err != nil { + //llog.Info("%s:%s", cvqdImgsDir, err.Error()) + } + + hyper := 0 + index := 0 + cdata := ChanData{} + for { + select { + case data, ok := <-v.data: + if !ok { + return + } + if len(v.data) >= (MAX_STREAM_CHAN_NUM - 6) { + //llog.Info("vqd channel num >= %d", MAX_STREAM_CHAN_NUM) + hyper = MAX_STREAM_CHAN_NUM / 10 + } + if hyper > 0 { + hyper-- + break + } + cdata = data + //if !IsCurTimeInRecordPlan(v.analysisTime, cdata.now) { + // continue + //} + if v.file != nil { + v.fileLock.Lock() + v.file.WriteString(fmt.Sprintf("vqd START data[%d] w[%d] h[%d]\r\n", len(cdata.data), cdata.w, cdata.h)) + v.fileLock.Unlock() + } + now := time.Now().UnixMilli() + fpath := filepath.Join(cvqdImgsDir, fmt.Sprintf("%d_%s_%d.jpg", v.TaskID, v.ChnID, now)) + fpath = filepath.ToSlash(fpath) + result := VQDResult{} + ret := v.handle.Frame(cdata.data, cdata.w, cdata.h, index, fpath, &result) + if ret == 0 { + index = 0 + if value, b := v.parseVQD(result); b { + value.FilePath = strings.TrimPrefix(filepath.ToSlash(fpath), filepath.ToSlash(CWD())) + value.ChannelID = v.ChnID + value.AlgoName = v.name + if v.cb != nil { + v.cb(value) + } else { + // 保存数据库 + //CreateAbnormalModel(&value) + } + } + } + if v.file != nil { + me, err := mem.VirtualMemory() + if err != nil { + v.fileLock.Lock() + v.file.WriteString(fmt.Sprintf("vqd END ret[%d] mem is nil\r\n", ret)) + v.fileLock.Unlock() + } else { + v.fileLock.Lock() + v.file.WriteString(fmt.Sprintf("vqd END ret[%d] mem[%.2f%s]\r\n", ret, me.UsedPercent, "%")) + v.fileLock.Unlock() + } + } + //C.free(fp) + //C.free(yuvBuf) + index++ + } + } +} + +func (v *VQDHandle) parseVQD(result VQDResult) (AbnormalModel, bool) { + isabnormal := false + abnormals := AbnormalModel{ + IsDeep: v.handle.Params.UseDeepLearning, + Abnormals: make([]Abnormal, 0), + } + + if (result.AbnormalType & NXU_VQD_ABN_COLORDEV) != 0 { + isabnormal = true + abnormals.Abnormals = append(abnormals.Abnormals, Abnormal{ + Value: result.ColorDev, + Name: ALNORMAL_NAMES[NXU_VQD_ABN_COLORDEV], + }) + } + abnormals.DefaultValues = append(abnormals.DefaultValues, DefaultValue{ + Thr1: v.handle.Params.ColorPara.ColorThr, + Name1: "偏色阈值", + Ratio: v.handle.Params.ColorPara.ColorAbnNumRatio, + }) + + if (result.AbnormalType & NXU_VQD_ABN_LIGHT) != 0 { + isabnormal = true + abnormals.Abnormals = append(abnormals.Abnormals, Abnormal{ + Value: result.LgtDark, + Name: ALNORMAL_NAMES[NXU_VQD_ABN_LIGHT], + }) + } + + if (result.AbnormalType & NXU_VQD_ABN_DARK) != 0 { + isabnormal = true + abnormals.Abnormals = append(abnormals.Abnormals, Abnormal{ + Value: result.LgtDark, + Name: ALNORMAL_NAMES[NXU_VQD_ABN_DARK], + }) + } + abnormals.DefaultValues = append(abnormals.DefaultValues, DefaultValue{ + Thr1: v.handle.Params.LgtDarkPara.LightThr, + Name1: "过亮阈值", + Thr2: v.handle.Params.LgtDarkPara.DarkThr, + Name2: "过暗阈值", + Ratio: v.handle.Params.LgtDarkPara.LgtDarkAbnNumRatio, + }) + + if (result.AbnormalType & NXU_VQD_ABN_CLARITY) != 0 { + isabnormal = true + abnormals.Abnormals = append(abnormals.Abnormals, Abnormal{ + Value: result.Clarity, + Name: ALNORMAL_NAMES[NXU_VQD_ABN_CLARITY], + }) + } + abnormals.DefaultValues = append(abnormals.DefaultValues, DefaultValue{ + Thr1: v.handle.Params.ClarityPara.ClarityThr, + Name1: "清晰度阈值", + Ratio: v.handle.Params.ClarityPara.ClarityAbnNumRatio, + }) + + if (result.AbnormalType & NXU_VQD_ABN_NOISE) != 0 { + isabnormal = true + abnormals.Abnormals = append(abnormals.Abnormals, Abnormal{ + Value: result.Noise, + Name: ALNORMAL_NAMES[NXU_VQD_ABN_NOISE], + }) + } + abnormals.DefaultValues = append(abnormals.DefaultValues, DefaultValue{ + Thr1: v.handle.Params.NoisePara.NoiseThr, + Name1: "噪声阈值", + Ratio: v.handle.Params.NoisePara.NoiseAbnNumRatio, + }) + + if (result.AbnormalType & NXU_VQD_ABN_CONTRAST) != 0 { + isabnormal = true + abnormals.Abnormals = append(abnormals.Abnormals, Abnormal{ + Value: result.Contrast, + Name: ALNORMAL_NAMES[NXU_VQD_ABN_CONTRAST], + }) + } + abnormals.DefaultValues = append(abnormals.DefaultValues, DefaultValue{ + Thr1: v.handle.Params.ContrastPara.CtraLowThr, + Name1: "低对比度阈值", + Thr2: v.handle.Params.ContrastPara.CtraHighThr, + Name2: "高对比度阈值", + Ratio: v.handle.Params.ContrastPara.CtraAbnNumRatio, + }) + + if (result.AbnormalType & NXU_VQD_ABN_OCCLUSION) != 0 { + isabnormal = true + abnormals.Abnormals = append(abnormals.Abnormals, Abnormal{ + Value: result.Occlusion, + Name: ALNORMAL_NAMES[NXU_VQD_ABN_OCCLUSION], + }) + } + abnormals.DefaultValues = append(abnormals.DefaultValues, DefaultValue{ + Thr1: v.handle.Params.OcclusionPara.OcclusionThr, + Name1: "遮挡阈值", + Ratio: v.handle.Params.OcclusionPara.OcclusionAbnNumRatio, + }) + + if (result.AbnormalType & NXU_VQD_ABN_BLUE) != 0 { + isabnormal = true + abnormals.Abnormals = append(abnormals.Abnormals, Abnormal{ + Value: result.Blue, + Name: ALNORMAL_NAMES[NXU_VQD_ABN_BLUE], + }) + } + abnormals.DefaultValues = append(abnormals.DefaultValues, DefaultValue{ + Thr1: v.handle.Params.BluePara.BlueThr, + Name1: "蓝屏阈值", + Ratio: v.handle.Params.BluePara.BlueAbnNumRatio, + }) + + if (result.AbnormalType & NXU_VQD_ABN_SHARK) != 0 { + isabnormal = true + abnormals.Abnormals = append(abnormals.Abnormals, Abnormal{ + Value: result.Shark, + Name: ALNORMAL_NAMES[NXU_VQD_ABN_SHARK], + }) + } + abnormals.DefaultValues = append(abnormals.DefaultValues, DefaultValue{ + Thr1: v.handle.Params.SharkPara.SharkThr, + Name1: "抖动阈值", + Ratio: v.handle.Params.SharkPara.SharkAbnNumRatio, + }) + + if (result.AbnormalType & NXU_VQD_ABN_FREEZE) != 0 { + isabnormal = true + abnormals.Abnormals = append(abnormals.Abnormals, Abnormal{ + Value: result.Freeze, + Name: ALNORMAL_NAMES[NXU_VQD_ABN_FREEZE], + }) + } + abnormals.DefaultValues = append(abnormals.DefaultValues, DefaultValue{ + Thr1: v.handle.Params.FreezePara.FreezeThr, + Name1: "冻结阈值", + Ratio: v.handle.Params.FreezePara.FreezeAbnNumRatio, + }) + + if (result.AbnormalType & NXU_VQD_ABN_MOSAIC) != 0 { + isabnormal = true + abnormals.Abnormals = append(abnormals.Abnormals, Abnormal{ + Value: result.Mosaic, + Name: ALNORMAL_NAMES[NXU_VQD_ABN_MOSAIC], + }) + } + abnormals.DefaultValues = append(abnormals.DefaultValues, DefaultValue{ + Thr1: v.handle.Params.MosaicPara.MosaicThr, + Name1: "马赛克阈值", + Ratio: v.handle.Params.MosaicPara.MosaicAbnNumRatio, + }) + + if (result.AbnormalType & NXU_VQD_ABN_FLOWER) != 0 { + isabnormal = true + abnormals.Abnormals = append(abnormals.Abnormals, Abnormal{ + Value: result.Flower, + Name: ALNORMAL_NAMES[NXU_VQD_ABN_FLOWER], + }) + } + abnormals.DefaultValues = append(abnormals.DefaultValues, DefaultValue{ + Thr1: v.handle.Params.FlowerPara.FlowerThr, + Name1: "花屏阈值", + Ratio: v.handle.Params.FlowerPara.FlowerAbnNumRatio, + }) + + return abnormals, isabnormal +} +func (v *VQDHandle) SendData(buf []byte, _codec int) { + dataP := GetIFramePointer(buf) + if dataP == nil || !dataP.IsValid { + slog.Error("I帧转指针失败: ", "TaskID", v.TaskID) + return + } + w, h, data, err := v.decoder.PushDataEx(uintptr(dataP.Pointer), dataP.Length, _codec) + if err != nil { + slog.Error("I帧转YUV失败: ", "TaskID", v.TaskID, "err", err) + return + } + if len(data) > 0 && v.data != nil { + dst := make([]byte, len(data)) + copy(dst, data) + now := time.Now() + d := ChanData{ + data: dst, + w: w, + h: h, + now: now, + } + //v.dataLock.Lock() + //v.data = append(v.data, d) + //v.dataLock.Unlock() + v.data <- d + } +} + +// IFrameData 封装I帧数据和指针信息 +type IFrameData struct { + Data []byte // I帧原始字节数据 + Pointer unsafe.Pointer // 指向数据的原始指针 + Length int // 数据长度(字节数) + IsValid bool // 指针是否有效 +} + +// GetIFramePointer 将字节切片转换为原始指针 +// 注意:unsafe包的使用会绕过Go的内存安全检查,需谨慎 +func GetIFramePointer(data []byte) *IFrameData { + if len(data) == 0 { + return &IFrameData{ + IsValid: false, + Length: 0, + } + } + + // 方式1:直接通过unsafe获取切片底层数组的指针(推荐,高效) + // 切片的底层结构是:指向数组的指针 + 长度 + 容量 + ptr := unsafe.Pointer(&data[0]) + + // 方式2:通过reflect获取指针(更直观展示切片结构,可选) + // sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&data)) + // ptr := unsafe.Pointer(sliceHeader.Data) + + return &IFrameData{ + Data: data, + Pointer: ptr, + Length: len(data), + IsValid: true, + } +} +func CWD() string { + geTwd, err := os.Getwd() + if err != nil { + return "" + } + return geTwd +} diff --git a/pkg/vqdcms/vqd_linux.go b/pkg/vqdcms/vqd_linux.go new file mode 100644 index 0000000..d7d892a --- /dev/null +++ b/pkg/vqdcms/vqd_linux.go @@ -0,0 +1,314 @@ +package vqdcms + +/* +#cgo linux CFLAGS: -w -I${SRCDIR}/include -fPIC +#cgo linux CPPFLAGS: -w -I${SRCDIR}/include -fPIC +#cgo linux LDFLAGS: -Wl,-rpath,'$ORIGIN/./VqdSDK' -rdynamic -ldl +#include +#include +#include +#include +#include "nxu_common.h" +#include "nxu_vqd_api.h" +#include "ez_vqd.h" + +#define LIB_NAME_VQD "libEasyVQD.so" + +void *g_hDll = NULL; +typedef int (*vqdLoad)(char *, int , char*); +typedef int (*vqdUnLoad)(); +typedef int (*vqdCreate)(VideoInfoCVR*); +typedef int (*vqdDestroy)(VideoInfoCVR*); +typedef int (*vqdConfig)(VideoInfoCVR, NXU_VQD_Para_S *, int); +typedef int (*vqdRun)(VideoInfoCVR, int, int, char*, int, char*, int, NXU_VQD_Result_S*); + +static vqdLoad _vqdLoad = NULL; +static vqdUnLoad _vqdUnLoad = NULL; +static vqdCreate _vqdCreate = NULL; +static vqdDestroy _vqdDestroy = NULL; +static vqdConfig _vqdConfig = NULL; +static vqdRun _vqdRun = NULL; + +int VQDCreate(VideoInfoCVR* handle) +{ + if (_vqdCreate) + { + return _vqdCreate(handle); + } + return -99; +} +int VQDDestroy(VideoInfoCVR* handle) +{ + if (_vqdDestroy) + { + return _vqdDestroy(handle); + } + return -99; +} +int VQDConfig(VideoInfoCVR handle, NXU_VQD_Para_S *stPara, int interval) +{ + if (_vqdConfig) + { + return _vqdConfig(handle, stPara, interval); + } + return -99; +} +int VQDRun(VideoInfoCVR handle, int width, int height, char* data, int frameNum, char* save_filename, int save_filename_size, NXU_VQD_Result_S* out_stResult) +{ + if (_vqdRun) + { + return _vqdRun(handle, width, height, data, frameNum, save_filename, save_filename_size, out_stResult); + } + return -99; +} + + +void lib_error(char *msg) +{ + const char* err = dlerror(); + sprintf(msg, "load error[%s]:%s\n", LIB_NAME_VQD, err); +} + +int VQDLoad(char *path, int path_size, char *errmsg) +{ + if (g_hDll) + { + return 0; + } + + char sopath[512] = {0}; + memset(sopath, 0x00, 512); + sprintf(sopath, "%s/%s", path, LIB_NAME_VQD); + g_hDll = dlopen(sopath, RTLD_NOW | RTLD_GLOBAL); + if (g_hDll) + { + int ret = 0; + do + { + _vqdLoad = dlsym(g_hDll, "ez_cvr_vqd_load"); + if (_vqdLoad == NULL) + { + ret = -3; + break; + } + _vqdUnLoad = dlsym(g_hDll, "ez_cvr_vqd_unload"); + _vqdCreate = dlsym(g_hDll, "ez_cvr_vqd_create"); + _vqdDestroy = dlsym(g_hDll, "ez_cvr_vqd_destroy"); + _vqdConfig = dlsym(g_hDll, "ez_cvr_vqd_config"); + _vqdRun = dlsym(g_hDll, "ez_cvr_vqd_run"); + ret = _vqdLoad(path, path_size, errmsg); + if (ret != 0) + { + return -5; + } + }while(0); + if (ret != 0) + { + lib_error(errmsg); + } + return ret; + } + lib_error(errmsg); + return -2; +} + +int VQDUnLoad() +{ + if (_vqdUnLoad) + { + _vqdUnLoad(); + } + _vqdUnLoad = NULL; + if (g_hDll) + { + dlclose(g_hDll); + } + g_hDll = NULL; + return 0; +} + + + +*/ +import "C" + +import ( + "fmt" + "log/slog" + "path/filepath" + "unsafe" +) + +var ( + vqdInitDLL = false +) + +func VQDInit() (err error) { + if vqdInitDLL { + return + } + cwd, _ := os.Getwd() + vqdSDKDir := filepath.Join(cwd, "VqdSDK") + var errmsg [128]C.char + ret := C.VQDLoad(C.CString(vqdSDKDir), C.int(len(vqdSDKDir)), &errmsg[0]) + if ret != 0 { + VQDUnInit() + resBuf1 := (*[128]byte)(unsafe.Pointer(&errmsg[0]))[:128:128] + slog.Info("vqd cms open", "ret", int(ret), "err", string(resBuf1)) + return fmt.Errorf("[%d]:%s", int(ret), resBuf1) + } + vqdInitDLL = true + slog.Info("vqd cms open ok") + return +} + +func VQDUnInit() { + C.VQDUnLoad() + vqdInitDLL = false + slog.Info("vqd cms stop ok") +} + +func (v *VideoInfoVQD) Create(params VQDPara, enable int, interval int) error { + v.mu.Lock() + defer v.mu.Unlock() + v.Params = params + var stPara C.NXU_VQD_Para_S + setParams(&stPara, params, enable) + var handle C.VideoInfoCVR + ret := int(C.VQDCreate(&handle)) + if ret != 0 { + return fmt.Errorf("ez_cvr_vqd_create fail:%d", ret) + } + v.VQDHandle = uintptr(handle) + C.VQDConfig((C.VideoInfoCVR)(unsafe.Pointer(v.VQDHandle)), &stPara, C.int(interval)) + v.IsCreateSuccess = true + return nil +} +func (v *VideoInfoVQD) Config(params VQDPara, enable int, interval int) error { + v.mu.Lock() + defer v.mu.Unlock() + if !v.IsCreateSuccess { + return fmt.Errorf("vqd cms is not create") + } + v.Params = params + var stPara C.NXU_VQD_Para_S + setParams(&stPara, params, enable) + ret := int(C.VQDConfig((C.VideoInfoCVR)(unsafe.Pointer(v.VQDHandle)), &stPara, C.int(interval))) + if ret != 0 { + return fmt.Errorf("ez_cvr_vqd_config fail:%d", ret) + } + return nil +} + +func setParams(stPara *C.NXU_VQD_Para_S, params VQDPara, enable int) { + if params.UseDeepLearning { + stPara.bUseDeepLearning = C.NXU_TRUE + } else { + stPara.bUseDeepLearning = C.NXU_FALSE + } + + //enable := NXU_VQD_ENABLE_LGTDARK + // 设置参数 + // 设置亮度检测 + stPara.s32EnableFunc = C.NXU_S32(enable) + stPara.stLgtDarkPara.f32DarkThr = C.NXU_FLOAT(params.LgtDarkPara.DarkThr) + stPara.stLgtDarkPara.f32LightThr = C.NXU_FLOAT(params.LgtDarkPara.LightThr) + stPara.stLgtDarkPara.f32LgtDarkAbnNumRatio = C.NXU_FLOAT(params.LgtDarkPara.LgtDarkAbnNumRatio) + stPara.s32VecFrmNum = C.int(params.VecFrmNum) + + //enable |= NXU_VQD_ENABLE_BLUE + // 设置蓝屏检测 + stPara.stBluePara.f32BlueThr = C.NXU_FLOAT(params.BluePara.BlueThr) + stPara.stBluePara.f32BlueAbnNumRatio = C.NXU_FLOAT(params.BluePara.BlueAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_CLARITY + // 设置清晰度检测 + stPara.stClarityPara.f32ClarityThr = C.NXU_FLOAT(params.ClarityPara.ClarityThr) + stPara.stClarityPara.f32ClarityAbnNumRatio = C.NXU_FLOAT(params.ClarityPara.ClarityAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_SHARK + // 设置抖动检测 + stPara.stSharkPara.f32SharkThr = C.NXU_FLOAT(params.SharkPara.SharkThr) + stPara.stSharkPara.f32SharkAbnNumRatio = C.NXU_FLOAT(params.SharkPara.SharkAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_FREEZE + // 设置冻结检测 + stPara.stFreezePara.f32FreezeThr = C.NXU_FLOAT(params.FreezePara.FreezeThr) + stPara.stFreezePara.f32FreezeAbnNumRatio = C.NXU_FLOAT(params.FreezePara.FreezeAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_COLOR + // 设置偏色检测 + stPara.stColorPara.f32ColorThr = C.NXU_FLOAT(params.ColorPara.ColorThr) + stPara.stColorPara.f32ColorAbnNumRatio = C.NXU_FLOAT(params.ColorPara.ColorAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_OCCLUSION + // 设置遮挡检测 + stPara.stOcclusionPara.f32OcclusionThr = C.NXU_FLOAT(params.OcclusionPara.OcclusionThr) + stPara.stOcclusionPara.f32OcclusionAbnNumRatio = C.NXU_FLOAT(params.OcclusionPara.OcclusionAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_NOISE + // 设置噪声检测参数 + stPara.stNoisePara.f32NoiseThr = C.NXU_FLOAT(params.NoisePara.NoiseThr) + stPara.stNoisePara.f32NoiseAbnNumRatio = C.NXU_FLOAT(params.NoisePara.NoiseAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_CONTRAST + // 设置对比度检测 + stPara.stContrastPara.f32CtraLowThr = C.NXU_FLOAT(params.ContrastPara.CtraLowThr) + stPara.stContrastPara.f32CtraHighThr = C.NXU_FLOAT(params.ContrastPara.CtraHighThr) + stPara.stContrastPara.f32CtraAbnNumRatio = C.NXU_FLOAT(params.ContrastPara.CtraAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_MOSAIC + // 设置马赛克检测 + stPara.stMosaicPara.f32MosaicThr = C.NXU_FLOAT(params.MosaicPara.MosaicThr) + stPara.stMosaicPara.f32MosaicAbnNumRatio = C.NXU_FLOAT(params.MosaicPara.MosaicAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_FLOWER + // 设置花屏检测 + stPara.stFlowerPara.f32FlowerThr = C.NXU_FLOAT(params.FlowerPara.FlowerThr) + stPara.stFlowerPara.f32FlowerAbnNumRatio = C.NXU_FLOAT(params.FlowerPara.FlowerAbnNumRatio) +} + +func (v *VideoInfoVQD) Frame(data []byte, w, h, frameNum int, save_filename string, outResult *VQDResult) int { + v.mu.Lock() + defer v.mu.Unlock() + if !v.IsCreateSuccess { + slog.Info("vqd cms is not create") + return -10 + } + + result := &C.NXU_VQD_Result_S{} + yuv := C.CBytes(data) + defer C.free(yuv) + filename := C.CString(save_filename) + defer C.free(unsafe.Pointer(filename)) + ret := int(C.VQDRun((C.VideoInfoCVR)(unsafe.Pointer(v.VQDHandle)), C.int(w), C.int(h), (*C.char)(yuv), + C.int(frameNum), filename, C.int(len(save_filename)), result)) + if ret == 0 { + // 分析成功 + outResult.AbnormalType = int(result.s32AbnormalType) + outResult.ColorDev = float32(result.f32ColorDev) + outResult.LgtDark = float32(result.f32LgtDark) + outResult.Clarity = float32(result.f32Clarity) + outResult.Noise = float32(result.f32Noise) + outResult.Contrast = float32(result.f32Contrast) + outResult.Occlusion = float32(result.f32Occlusion) + outResult.Blue = float32(result.f32Blue) + outResult.Shark = float32(result.f32Shark) + outResult.Freeze = float32(result.f32Freeze) + outResult.Mosaic = float32(result.f32Mosaic) + outResult.Flower = float32(result.f32Flower) + } + return ret +} + +func (v *VideoInfoVQD) Destroy() { + v.mu.Lock() + defer v.mu.Unlock() + if !v.IsCreateSuccess { + slog.Info("vqd cms Destroy fail") + return + } + h := (C.VideoInfoCVR)(unsafe.Pointer(v.VQDHandle)) + v.IsCreateSuccess = false + C.VQDDestroy(&h) +} diff --git a/pkg/vqdcms/vqd_windows.go b/pkg/vqdcms/vqd_windows.go new file mode 100644 index 0000000..c91f48f --- /dev/null +++ b/pkg/vqdcms/vqd_windows.go @@ -0,0 +1,256 @@ +package vqdcms + +/* +#cgo CFLAGS: -w -I${SRCDIR}/include -fPIC +#cgo CPPFLAGS: -w -I${SRCDIR}/include -fPIC +#include +#include +#include +#include "nxu_common.h" +#include "nxu_vqd_api.h" +#include "ez_vqd.h" +#include + +void LoadDllDir(char *path, int path_size) +{ + SetDllDirectoryA(path); +} + +*/ +import "C" +import ( + "fmt" + "log/slog" + "os" + "path/filepath" + "syscall" + "unsafe" +) + +var ( + vqdDLL *syscall.DLL + vqdLoad *syscall.Proc + vqdUnLoad *syscall.Proc + + vqdCreate, vqdDestroy, vqdConfig, vqdRun *syscall.Proc +) + +func VQDInit() (err error) { + if vqdDLL != nil { + return + } + cwd, _ := os.Getwd() + vqdSDKDir := filepath.Join(cwd, "VqdSDK") + C.LoadDllDir(C.CString(vqdSDKDir), C.int(len(vqdSDKDir))) + vqdDLL, err = syscall.LoadDLL(filepath.Join(vqdSDKDir, "EasyVQD.dll")) + if err != nil { + return + } + vqdLoad, err = vqdDLL.FindProc("ez_cvr_vqd_load") + if err != nil { + VQDUnInit() + return + } + vqdUnLoad, err = vqdDLL.FindProc("ez_cvr_vqd_unload") + if err != nil { + VQDUnInit() + return + } + vqdCreate, err = vqdDLL.FindProc("ez_cvr_vqd_create") + if err != nil { + VQDUnInit() + return + } + vqdDestroy, err = vqdDLL.FindProc("ez_cvr_vqd_destroy") + if err != nil { + VQDUnInit() + return + } + vqdConfig, err = vqdDLL.FindProc("ez_cvr_vqd_config") + if err != nil { + VQDUnInit() + return + } + vqdRun, err = vqdDLL.FindProc("ez_cvr_vqd_run") + if err != nil { + VQDUnInit() + return + } + vqdSDKDir = filepath.ToSlash(vqdSDKDir) + dir, err := syscall.BytePtrFromString(vqdSDKDir) + if err != nil { + VQDUnInit() + return err + } + var errmsg [128]C.char + r1, _, _ := vqdLoad.Call(uintptr(unsafe.Pointer(dir)), uintptr(len(vqdSDKDir)), uintptr(unsafe.Pointer(&errmsg[0]))) + if r1 != 0 { + VQDUnInit() + resBuf1 := (*[128]byte)(unsafe.Pointer(&errmsg[0]))[:128:128] + return fmt.Errorf("%s", resBuf1) + } + slog.Info("vqd cms open ok") + return +} + +func VQDUnInit() { + if vqdUnLoad != nil { + _, _, err := vqdUnLoad.Call() + if err != nil { + slog.Error("vqd cms stop Call err", "err", err) + } + } + vqdUnLoad = nil + if vqdDLL != nil { + err := vqdDLL.Release() + if err != nil { + slog.Error("vqd cms stop Release err", "err", err) + } + } + slog.Info("vqd cms stop ok") + vqdDLL = nil +} +func (v *VideoInfoVQD) Create(params VQDPara, enable int, interval int) error { + v.mu.Lock() + defer v.mu.Unlock() + v.Params = params + var stPara C.NXU_VQD_Para_S + setParams(&stPara, params, enable) + ret, _, _ := vqdCreate.Call(uintptr(unsafe.Pointer(&v.VQDHandle))) + if ret != 0 { + return fmt.Errorf("vqdCreate fail:%d", ret) + } + ret, _, _ = vqdConfig.Call(v.VQDHandle, uintptr(unsafe.Pointer(&stPara)), uintptr(interval)) + if ret != 0 { + return fmt.Errorf("vqdConfig fail:%d", ret) + } + v.IsCreateSuccess = true + return nil +} +func (v *VideoInfoVQD) Config(params VQDPara, enable int, interval int) error { + v.mu.Lock() + defer v.mu.Unlock() + if !v.IsCreateSuccess { + return fmt.Errorf("vqd cms is not create") + } + v.Params = params + var stPara C.NXU_VQD_Para_S + setParams(&stPara, params, enable) + ret, _, _ := vqdConfig.Call(v.VQDHandle, uintptr(unsafe.Pointer(&stPara)), uintptr(interval)) + if ret != 0 { + return fmt.Errorf("vqdConfig fail:%d", ret) + } + return nil +} + +func setParams(stPara *C.NXU_VQD_Para_S, params VQDPara, enable int) { + if params.UseDeepLearning { + stPara.bUseDeepLearning = C.NXU_TRUE + } else { + stPara.bUseDeepLearning = C.NXU_FALSE + } + + //enable := NXU_VQD_ENABLE_LGTDARK + // 设置参数 + // 设置亮度检测 + stPara.s32EnableFunc = C.NXU_S32(enable) + stPara.stLgtDarkPara.f32DarkThr = C.NXU_FLOAT(params.LgtDarkPara.DarkThr) + stPara.stLgtDarkPara.f32LightThr = C.NXU_FLOAT(params.LgtDarkPara.LightThr) + stPara.stLgtDarkPara.f32LgtDarkAbnNumRatio = C.NXU_FLOAT(params.LgtDarkPara.LgtDarkAbnNumRatio) + stPara.s32VecFrmNum = C.int(params.VecFrmNum) + + //enable |= NXU_VQD_ENABLE_BLUE + // 设置蓝屏检测 + stPara.stBluePara.f32BlueThr = C.NXU_FLOAT(params.BluePara.BlueThr) + stPara.stBluePara.f32BlueAbnNumRatio = C.NXU_FLOAT(params.BluePara.BlueAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_CLARITY + // 设置清晰度检测 + stPara.stClarityPara.f32ClarityThr = C.NXU_FLOAT(params.ClarityPara.ClarityThr) + stPara.stClarityPara.f32ClarityAbnNumRatio = C.NXU_FLOAT(params.ClarityPara.ClarityAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_SHARK + // 设置抖动检测 + stPara.stSharkPara.f32SharkThr = C.NXU_FLOAT(params.SharkPara.SharkThr) + stPara.stSharkPara.f32SharkAbnNumRatio = C.NXU_FLOAT(params.SharkPara.SharkAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_FREEZE + // 设置冻结检测 + stPara.stFreezePara.f32FreezeThr = C.NXU_FLOAT(params.FreezePara.FreezeThr) + stPara.stFreezePara.f32FreezeAbnNumRatio = C.NXU_FLOAT(params.FreezePara.FreezeAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_COLOR + // 设置偏色检测 + stPara.stColorPara.f32ColorThr = C.NXU_FLOAT(params.ColorPara.ColorThr) + stPara.stColorPara.f32ColorAbnNumRatio = C.NXU_FLOAT(params.ColorPara.ColorAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_OCCLUSION + // 设置遮挡检测 + stPara.stOcclusionPara.f32OcclusionThr = C.NXU_FLOAT(params.OcclusionPara.OcclusionThr) + stPara.stOcclusionPara.f32OcclusionAbnNumRatio = C.NXU_FLOAT(params.OcclusionPara.OcclusionAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_NOISE + // 设置噪声检测参数 + stPara.stNoisePara.f32NoiseThr = C.NXU_FLOAT(params.NoisePara.NoiseThr) + stPara.stNoisePara.f32NoiseAbnNumRatio = C.NXU_FLOAT(params.NoisePara.NoiseAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_CONTRAST + // 设置对比度检测 + stPara.stContrastPara.f32CtraLowThr = C.NXU_FLOAT(params.ContrastPara.CtraLowThr) + stPara.stContrastPara.f32CtraHighThr = C.NXU_FLOAT(params.ContrastPara.CtraHighThr) + stPara.stContrastPara.f32CtraAbnNumRatio = C.NXU_FLOAT(params.ContrastPara.CtraAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_MOSAIC + // 设置马赛克检测 + stPara.stMosaicPara.f32MosaicThr = C.NXU_FLOAT(params.MosaicPara.MosaicThr) + stPara.stMosaicPara.f32MosaicAbnNumRatio = C.NXU_FLOAT(params.MosaicPara.MosaicAbnNumRatio) + + //enable |= NXU_VQD_ENABLE_FLOWER + // 设置花屏检测 + stPara.stFlowerPara.f32FlowerThr = C.NXU_FLOAT(params.FlowerPara.FlowerThr) + stPara.stFlowerPara.f32FlowerAbnNumRatio = C.NXU_FLOAT(params.FlowerPara.FlowerAbnNumRatio) +} + +func (v *VideoInfoVQD) Frame(data []byte, w, h, frameNum int, save_filename string, outResult *VQDResult) int { + v.mu.Lock() + defer v.mu.Unlock() + if !v.IsCreateSuccess { + slog.Info("vqd cms is not create") + return -10 + } + var result C.NXU_VQD_Result_S + yuv := C.CBytes(data) + defer C.free(yuv) + filename, _ := syscall.BytePtrFromString(save_filename) + ret, _, _ := vqdRun.Call(v.VQDHandle, uintptr(w), uintptr(h), uintptr(yuv), uintptr(frameNum), uintptr(unsafe.Pointer(filename)), uintptr(len(save_filename)), uintptr(unsafe.Pointer(&result))) + if ret == 0 { + // 分析成功 + outResult.AbnormalType = int(result.s32AbnormalType) + outResult.ColorDev = float32(result.f32ColorDev) + outResult.LgtDark = float32(result.f32LgtDark) + outResult.Clarity = float32(result.f32Clarity) + outResult.Noise = float32(result.f32Noise) + outResult.Contrast = float32(result.f32Contrast) + outResult.Occlusion = float32(result.f32Occlusion) + outResult.Blue = float32(result.f32Blue) + outResult.Shark = float32(result.f32Shark) + outResult.Freeze = float32(result.f32Freeze) + outResult.Mosaic = float32(result.f32Mosaic) + outResult.Flower = float32(result.f32Flower) + } + return int(ret) +} +func (v *VideoInfoVQD) Destroy() { + v.mu.Lock() + defer v.mu.Unlock() + if !v.IsCreateSuccess { + slog.Error("vqd cms Destroy fail") + return + } + v.IsCreateSuccess = false + _, _, err := vqdDestroy.Call(uintptr(unsafe.Pointer(&v.VQDHandle))) + if err != nil { + slog.Error("vqd cms Destroy Call", err, err) + return + } +} diff --git a/web/src/api/vqdtasktemplate.ts b/web/src/api/vqdtasktemplate.ts index 28ee60c..5b8a37f 100644 --- a/web/src/api/vqdtasktemplate.ts +++ b/web/src/api/vqdtasktemplate.ts @@ -31,8 +31,6 @@ export async function GetVqdTaskTemplateById(id: string) { */ export async function UpdateVqdTaskTemplate(data: UpdateVqdTaskTemplateReq) { const { id, ...payload } = data; - console.log(data); - return await PUT(`/template/${id}`, payload); } diff --git a/web/src/api/vqdtimetemplate.ts b/web/src/api/vqdtimetemplate.ts new file mode 100644 index 0000000..e7632b7 --- /dev/null +++ b/web/src/api/vqdtimetemplate.ts @@ -0,0 +1,43 @@ +import { GET, POST, PUT, DELETE } from "./http"; +import type { VqdTimeTemplateBaseRes, VqdTimeTemplateRes, CreateVqdTimeTemplateReq, UpdateVqdTimeTemplateReq, VqdTimeTemplateDetailRes, VqdTimeTemplateReq } from "../types/vqdtimetemplate"; + +/** + * 获取列表 + * @returns 列表 + */ +export async function GetVqdTimeTemplate(data: VqdTimeTemplateReq) { + return await GET(`/plan`, data); +} + +/** + * 创建 + * @param data 创建参数 + */ +export async function CreateVqdTimeTemplate(data: CreateVqdTimeTemplateReq) { + return await POST(`/plan`, data); +} + +/** + * 获取详情 + * @param id ID + */ +export async function GetVqdTimeTemplateById(id: string) { + return await GET(`/plan/${id}`); +} + +/** + * 更新 + * @param data 更新参数(需包含 id) + */ +export async function UpdateVqdTimeTemplate(data: UpdateVqdTimeTemplateReq) { + const { id, ...payload } = data; + return await PUT(`/plan/${id}`, payload); +} + +/** + * 删除 + * @param id ID + */ +export async function DeleteVqdTimeTemplate(id: number) { + return await DELETE(`/plan/${id}`); +} diff --git a/web/src/components/AddVqdTask.tsx b/web/src/components/AddVqdTask.tsx index 2501725..f2ccf56 100644 --- a/web/src/components/AddVqdTask.tsx +++ b/web/src/components/AddVqdTask.tsx @@ -1,8 +1,9 @@ import { forwardRef, useImperativeHandle, useState, useRef } from "react"; -import { Modal, Form, Input, Select, Button, message, Space } from "antd"; +import { Modal, Form, Input, Select, Button, message, Space, Switch } from "antd"; import { useMutation, useQuery } from "@tanstack/react-query"; import { CreateVqdTask, UpdateVqdTask } from "../api/vqdtask"; import { GetVqdTaskTemplate } from "../api/vqdtasktemplate"; +import { GetVqdTimeTemplate } from "../api/vqdtimetemplate"; import type { CreateVqdTaskReq, VqdTaskItem } from "../types/vqdtask"; import { useGlobal } from "../Context"; import ChannelModel, { IChannelModelFunc } from "./channel/Channel"; @@ -42,9 +43,9 @@ const AddVqdTask = forwardRef( } else { setEditing(false); form.resetFields(); - // form.setFieldsValue({ - // bid: "2", - // }); + form.setFieldsValue({ + enable: true, + }); } setOpen(true); }, @@ -55,11 +56,9 @@ const AddVqdTask = forwardRef( name: "" }); - // 获取任务列表 + // 获取模板列表 const { data: storageResponse, - isLoading, - refetch, } = useQuery({ queryKey: ["storage", pagination], queryFn: () => @@ -72,6 +71,21 @@ const AddVqdTask = forwardRef( // refetchInterval: 4000, retry: 1, }); + // 获取计划列表 + const { + data: storageTimeResponse, + } = useQuery({ + queryKey: ["storages", pagination], + queryFn: () => + GetVqdTimeTemplate({ ...pagination }) + .then((res) => res.data) + .catch((err) => { + ErrorHandle(err); + throw err; + }), + // refetchInterval: 4000, + retry: 1, + }); const { mutate: createMutate, isPending: creating } = useMutation({ mutationFn: CreateVqdTask, onSuccess: () => { @@ -101,7 +115,7 @@ const AddVqdTask = forwardRef( return ( ( channel_id, channel_name, task_template_id, - task_template_name, + time_template_id, enable } = values as { name: string; des: string; @@ -131,7 +145,7 @@ const AddVqdTask = forwardRef( channel_id: string; channel_name: string; task_template_id: number; - task_template_name: string; + time_template_id: number; enable: boolean; }; const payload: CreateVqdTaskReq = { @@ -140,7 +154,7 @@ const AddVqdTask = forwardRef( channel_id, channel_name, task_template_id, - task_template_name, + time_template_id, enable, }; @@ -174,7 +188,7 @@ const AddVqdTask = forwardRef( }}>选择通道 - + + + + + + + + + {editing && ( - - - - - + {editing && (