添加诊断
This commit is contained in:
parent
9cfb302777
commit
83a50fa245
BIN
VqdSDK/libdrm.so.2
Normal file
BIN
VqdSDK/libdrm.so.2
Normal file
Binary file not shown.
BIN
VqdSDK/libgomp.so.1
Normal file
BIN
VqdSDK/libgomp.so.1
Normal file
Binary file not shown.
BIN
VqdSDK/libva-drm.so.1
Normal file
BIN
VqdSDK/libva-drm.so.1
Normal file
Binary file not shown.
BIN
VqdSDK/libva.so.1
Normal file
BIN
VqdSDK/libva.so.1
Normal file
Binary file not shown.
BIN
check_tip.h264
Normal file
BIN
check_tip.h264
Normal file
Binary file not shown.
@ -11,7 +11,7 @@ import (
|
|||||||
"easyvqd/internal/conf"
|
"easyvqd/internal/conf"
|
||||||
"easyvqd/internal/core/host"
|
"easyvqd/internal/core/host"
|
||||||
"easyvqd/internal/core/media"
|
"easyvqd/internal/core/media"
|
||||||
"easyvqd/internal/core/vqdsdk"
|
"easyvqd/internal/core/vqdtask"
|
||||||
"easyvqd/internal/data"
|
"easyvqd/internal/data"
|
||||||
"easyvqd/internal/web/api"
|
"easyvqd/internal/web/api"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
@ -30,7 +30,7 @@ func WireApp(bc *conf.Bootstrap, log *slog.Logger) (http.Handler, func(), error)
|
|||||||
vqdTaskCore := api.NewVqdTaskCore(db)
|
vqdTaskCore := api.NewVqdTaskCore(db)
|
||||||
hostCore := host.NewCore(bc)
|
hostCore := host.NewCore(bc)
|
||||||
mediaCore := media.NewCore(hostCore)
|
mediaCore := media.NewCore(hostCore)
|
||||||
vqdSdkCore := vqdsdk.NewCore(hostCore, vqdTaskCore, bc)
|
vqdSdkCore := vqdtask.NewCore(hostCore, vqdTaskCore, bc)
|
||||||
vqdTaskAPI := api.NewVqdTaskAPI(vqdTaskCore, mediaCore,vqdSdkCore,hostCore, bc)
|
vqdTaskAPI := api.NewVqdTaskAPI(vqdTaskCore, mediaCore,vqdSdkCore,hostCore, bc)
|
||||||
|
|
||||||
usecase := &api.Usecase{
|
usecase := &api.Usecase{
|
||||||
@ -45,6 +45,6 @@ func WireApp(bc *conf.Bootstrap, log *slog.Logger) (http.Handler, func(), error)
|
|||||||
}
|
}
|
||||||
handler := api.NewHTTPHandler(usecase)
|
handler := api.NewHTTPHandler(usecase)
|
||||||
return handler, func() {
|
return handler, func() {
|
||||||
//mediaCore.Close()
|
vqdSdkCore.UnVqdTask()
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package host
|
package host
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"easyvqd/internal/conf"
|
"easyvqd/internal/conf"
|
||||||
"easyvqd/pkg/pluginheart"
|
"easyvqd/pkg/pluginheart"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -12,10 +11,12 @@ import (
|
|||||||
"git.lnton.com/lnton/pluginsdk/pkg/plugin"
|
"git.lnton.com/lnton/pluginsdk/pkg/plugin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type IFrameResultCB func(string, []byte, int)
|
||||||
type Core struct {
|
type Core struct {
|
||||||
Plugin *plugin.PluginSDK // 用于业务GRPC通信
|
Plugin *plugin.PluginSDK // 用于业务GRPC通信
|
||||||
HttpPlugin *pluginheart.Engine // 用于插件管理HTTP通信
|
HttpPlugin *pluginheart.Engine // 用于插件管理HTTP通信
|
||||||
RtspConfig *ConfigBaseOutput
|
RtspConfig *ConfigBaseOutput
|
||||||
|
CbIFrame IFrameResultCB
|
||||||
}
|
}
|
||||||
|
|
||||||
var StartOk chan struct{}
|
var StartOk chan struct{}
|
||||||
@ -45,29 +46,33 @@ func NewCore(cfg *conf.Bootstrap) *Core {
|
|||||||
}, false)
|
}, false)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
c := &Core{
|
core := &Core{
|
||||||
Plugin: sdk,
|
Plugin: sdk,
|
||||||
HttpPlugin: engine,
|
HttpPlugin: engine,
|
||||||
}
|
}
|
||||||
|
sdk.AddResponseHandler("stop", core.stop)
|
||||||
sdk.AddResponseHandler("stop", c.stop)
|
sdk.AddResponseHandler("ping", core.ping)
|
||||||
sdk.AddResponseHandler("ping", c.ping)
|
|
||||||
|
|
||||||
// 这部分都是收到响应后的回调
|
// 这部分都是收到响应后的回调
|
||||||
sdk.AddResponseHandler("findDevices", c.findDevicesRespH)
|
sdk.AddResponseHandler("findDevices", core.findDevicesRespH)
|
||||||
sdk.AddResponseHandler("findChannels", c.findChannelsRespH)
|
sdk.AddResponseHandler("findChannels", core.findChannelsRespH)
|
||||||
sdk.AddResponseHandler("getBaseConfig", c.getBaseConfigRespH)
|
sdk.AddResponseHandler("getBaseConfig", core.getBaseConfigRespH)
|
||||||
sdk.AddResponseHandler("findTalkUrl", c.findTalkUrlRespH)
|
sdk.AddResponseHandler("findTalkUrl", core.findTalkUrlRespH)
|
||||||
|
sdk.AddResponseHandler("iframeData", core.iframeDataRespH)
|
||||||
config, err := c.GetBaseConfig(context.TODO(), &ConfigBaseInput{Mode: "rtsp"})
|
// 响应主机下发的 "iframeData" 命令
|
||||||
if err != nil {
|
sdk.AddRequestHandler("iframeData", core.iframeDataReqH)
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
// defer sdk.Close()
|
// defer sdk.Close()
|
||||||
return &Core{
|
return core
|
||||||
Plugin: sdk,
|
}
|
||||||
RtspConfig: config,
|
|
||||||
|
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) {
|
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) {
|
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
|
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)
|
slog.Debug("Received 'findTalkUrl' from host", "request_id", requestID, "args", args)
|
||||||
return nil, nil
|
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
|
||||||
|
}
|
||||||
|
|||||||
9
internal/core/host/iframe.go
Normal file
9
internal/core/host/iframe.go
Normal file
@ -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"`
|
||||||
|
}
|
||||||
@ -6,6 +6,7 @@ type Storer interface {
|
|||||||
VqdTask() VqdTaskStorer
|
VqdTask() VqdTaskStorer
|
||||||
VqdAlarm() VqdAlarmStorer
|
VqdAlarm() VqdAlarmStorer
|
||||||
VqdTaskTemplate() VqdTaskTemplateStorer
|
VqdTaskTemplate() VqdTaskTemplateStorer
|
||||||
|
VqdTimeTemplate() VqdTimeTemplateStorer
|
||||||
}
|
}
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
|
|||||||
@ -18,13 +18,13 @@ const (
|
|||||||
|
|
||||||
type VqdTask struct {
|
type VqdTask struct {
|
||||||
orm.Model
|
orm.Model
|
||||||
Name string `gorm:"column:name;notNull;default:'';comment:名称" json:"name"` // 名称
|
Name string `gorm:"column:name;notNull;default:'';comment:名称" json:"name"` // 名称
|
||||||
ChannelID string `gorm:"column:channel_id;notNull;default:'';comment:关联通道" json:"channel_id"` // 关联通道
|
ChannelID string `gorm:"column:channel_id;notNull;default:'';comment:关联通道" json:"channel_id"` // 关联通道
|
||||||
ChannelName string `gorm:"column:channel_name;notNull;default:'';comment:关联通道名称" json:"channel_name"` // 关联通道名称
|
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"` //关联模板
|
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"` //关联模板名称
|
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"` // 启用
|
Enable bool `gorm:"column:enable;notNull;default:FALSE;comment:启用" json:"enable"` // 启用
|
||||||
Des string `gorm:"column:des;notNull;default:'';comment:描述" json:"des"` // 描述
|
Des string `gorm:"column:des;notNull;default:'';comment:描述" json:"des"` // 描述
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName database table name
|
// TableName database table name
|
||||||
@ -217,8 +217,6 @@ func (i *VqdFlower) Scan(input interface{}) error {
|
|||||||
type VqdTaskTemplate struct {
|
type VqdTaskTemplate struct {
|
||||||
orm.Model
|
orm.Model
|
||||||
Name string `gorm:"column:name;notNull;default:'';comment:名称" json:"name"`
|
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"`
|
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"` // 诊断基础配置
|
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"` // 亮度检测
|
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"
|
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 {
|
type VqdAlarm struct {
|
||||||
orm.Model
|
orm.Model
|
||||||
AlarmName string `gorm:"column:alarm_name;notNull;default:'';comment:告警名称" json:"alarm_name"` // 告警名称
|
AlarmName string `gorm:"column:alarm_name;notNull;default:'';comment:告警名称" json:"alarm_name"` // 告警名称
|
||||||
|
|||||||
@ -24,6 +24,9 @@ func (d DB) VqdTask() vqd.VqdTaskStorer {
|
|||||||
func (d DB) VqdTaskTemplate() vqd.VqdTaskTemplateStorer {
|
func (d DB) VqdTaskTemplate() vqd.VqdTaskTemplateStorer {
|
||||||
return VqdTaskTemplate(d)
|
return VqdTaskTemplate(d)
|
||||||
}
|
}
|
||||||
|
func (d DB) VqdTimeTemplate() vqd.VqdTimeTemplateStorer {
|
||||||
|
return VqdTimeTemplate(d)
|
||||||
|
}
|
||||||
func (d DB) VqdAlarm() vqd.VqdAlarmStorer {
|
func (d DB) VqdAlarm() vqd.VqdAlarmStorer {
|
||||||
return VqdAlarm(d)
|
return VqdAlarm(d)
|
||||||
}
|
}
|
||||||
@ -36,6 +39,7 @@ func (d DB) AutoMigrate(ok bool) DB {
|
|||||||
if err := d.db.AutoMigrate(
|
if err := d.db.AutoMigrate(
|
||||||
new(vqd.VqdTask),
|
new(vqd.VqdTask),
|
||||||
new(vqd.VqdTaskTemplate),
|
new(vqd.VqdTaskTemplate),
|
||||||
|
new(vqd.VqdTimeTemplate),
|
||||||
new(vqd.VqdAlarm),
|
new(vqd.VqdAlarm),
|
||||||
); err != nil {
|
); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|||||||
60
internal/core/vqd/store/audioencodedb/vqdtimetemplate.go
Normal file
60
internal/core/vqd/store/audioencodedb/vqdtimetemplate.go
Normal file
@ -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
|
||||||
|
}
|
||||||
@ -11,21 +11,21 @@ type FindVqdTaskInput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type EditVqdTaskInput struct {
|
type EditVqdTaskInput struct {
|
||||||
Name string `json:"name"` // 名称
|
Name string `json:"name"` // 名称
|
||||||
ChannelID string `json:"channel_id"` // 关联通道
|
ChannelID string `json:"channel_id"` // 关联通道
|
||||||
ChannelName string `json:"channel_name"` // 通道名称
|
ChannelName string `json:"channel_name"` // 通道名称
|
||||||
TaskTemplateID int `json:"task_template_id"` // 关联模板
|
TaskTemplateID int `json:"task_template_id"` // 关联模板
|
||||||
TaskTemplateName string `json:"task_template_name"` // 模板名称
|
TimeTemplateID int `json:"time_template_id"` // 关联计划
|
||||||
Enable bool `form:"enable"` // 启用
|
Enable bool `form:"enable"` // 启用
|
||||||
Des string `json:"des"` // 描述
|
Des string `json:"des"` // 描述
|
||||||
}
|
}
|
||||||
|
|
||||||
type AddVqdTaskInput struct {
|
type AddVqdTaskInput struct {
|
||||||
Name string `json:"name"` // 名称
|
Name string `json:"name"` // 名称
|
||||||
ChannelID string `json:"channel_id"` // 关联通道
|
ChannelID string `json:"channel_id"` // 关联通道
|
||||||
ChannelName string `json:"channel_name"` // 通道名称
|
ChannelName string `json:"channel_name"` // 通道名称
|
||||||
TaskTemplateID int `json:"task_template_id"` // 关联模板
|
TaskTemplateID int `json:"task_template_id"` // 关联模板
|
||||||
TaskTemplateName string `json:"task_template_name"` // 模板名称
|
TimeTemplateID int `json:"time_template_id"` // 关联计划
|
||||||
Enable bool `form:"enable"` // 启用
|
Enable bool `form:"enable"` // 启用
|
||||||
Des string `json:"des"` // 描述
|
Des string `json:"des"` // 描述
|
||||||
}
|
}
|
||||||
|
|||||||
@ -83,7 +83,7 @@ func (c Core) GetNameVqdTaskTemplate(ctx context.Context, name string) (*VqdTask
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FirstOrCreateTemplate Insert into database
|
// FirstOrCreateTemplate Insert into database
|
||||||
func (c Core) FirstOrCreateTemplate(b any) error {
|
func (c Core) FirstOrCreateTaskTemplate(b any) error {
|
||||||
return c.store.VqdTaskTemplate().FirstOrCreate(b)
|
return c.store.VqdTaskTemplate().FirstOrCreate(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
122
internal/core/vqd/vqdtimetemplate.go
Normal file
122
internal/core/vqd/vqdtimetemplate.go
Normal file
@ -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
|
||||||
|
}
|
||||||
25
internal/core/vqd/vqdtimetemplate.param.go
Normal file
25
internal/core/vqd/vqdtimetemplate.param.go
Normal file
@ -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"` // 描述
|
||||||
|
}
|
||||||
@ -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
|
|
||||||
//}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
package vqdsdk
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package vqdsdk
|
package vqdtask
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
284
internal/core/vqdtask/core.go
Normal file
284
internal/core/vqdtask/core.go
Normal file
@ -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
|
||||||
|
}
|
||||||
6
internal/core/vqdtask/mode.go
Normal file
6
internal/core/vqdtask/mode.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package vqdtask
|
||||||
|
|
||||||
|
const (
|
||||||
|
VIDEO_CODEC_H264 = 0x1C
|
||||||
|
VIDEO_CODEC_H265 = 0xAE
|
||||||
|
)
|
||||||
@ -163,9 +163,15 @@ type KV struct {
|
|||||||
|
|
||||||
func InitTemplate(uc *Usecase) error {
|
func InitTemplate(uc *Usecase) error {
|
||||||
cfg := uc.Conf
|
cfg := uc.Conf
|
||||||
in := vqd.VqdTaskTemplate{
|
inPlan := vqd.VqdTimeTemplate{
|
||||||
Enable: true,
|
Enable: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
|
}
|
||||||
|
inTemplate := vqd.VqdTaskTemplate{
|
||||||
|
|
||||||
|
Name: "默认",
|
||||||
|
Des: "默认诊断模板。",
|
||||||
|
IsDefault: true,
|
||||||
VqdConfig: vqd.VqdConfig{
|
VqdConfig: vqd.VqdConfig{
|
||||||
Enable: true,
|
Enable: true,
|
||||||
FrmNum: cfg.VqdConfig.FrmNum,
|
FrmNum: cfg.VqdConfig.FrmNum,
|
||||||
@ -230,32 +236,37 @@ func InitTemplate(uc *Usecase) error {
|
|||||||
MosaicThr: cfg.VqdFlower.MosaicThr,
|
MosaicThr: cfg.VqdFlower.MosaicThr,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
inTemplate.ID = 1
|
||||||
in.Name = "每天"
|
inTemplate.Model.CreatedAt = orm.Time{Time: time.Now()}
|
||||||
in.Model.ID = 1
|
if err := uc.VqdTaskCore.FirstOrCreateTaskTemplate(&inTemplate); err != nil {
|
||||||
in.Model.CreatedAt = orm.Time{Time: time.Now()}
|
slog.Error("FirstOrCreateTaskTemplate", "err", err)
|
||||||
in.Plans = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
|
|
||||||
in.Des = "每天分析,启用全部分析模块。"
|
|
||||||
if err := uc.VqdTaskCore.FirstOrCreateTemplate(&in); err != nil {
|
|
||||||
slog.Error("FirstOrCreateTemplate", "err", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
in.Name = "工作日"
|
inPlan.Name = "每天"
|
||||||
in.Model.ID = 2
|
inPlan.Model.ID = 1
|
||||||
in.Model.CreatedAt = orm.Time{Time: time.Now()}
|
inPlan.Model.CreatedAt = orm.Time{Time: time.Now()}
|
||||||
in.Plans = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000"
|
inPlan.Plans = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
|
||||||
in.Des = "工作日分析,启用全部分析模块。"
|
inPlan.Des = "每天分析"
|
||||||
if err := uc.VqdTaskCore.FirstOrCreateTemplate(&in); err != nil {
|
if err := uc.VqdTaskCore.FirstOrCreateTimeTemplate(&inPlan); err != nil {
|
||||||
slog.Error("FirstOrCreateTemplate", "err", err)
|
slog.Error("FirstOrCreateTimeTemplate", "err", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
in.Name = "双休日"
|
inPlan.Name = "工作日"
|
||||||
in.Model.ID = 3
|
inPlan.Model.ID = 2
|
||||||
in.Model.CreatedAt = orm.Time{Time: time.Now()}
|
inPlan.Model.CreatedAt = orm.Time{Time: time.Now()}
|
||||||
in.Plans = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111"
|
inPlan.Plans = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000"
|
||||||
in.Des = "休息日分析,启用全部分析模块。"
|
inPlan.Des = "工作日分析"
|
||||||
if err := uc.VqdTaskCore.FirstOrCreateTemplate(&in); err != nil {
|
if err := uc.VqdTaskCore.FirstOrCreateTimeTemplate(&inPlan); err != nil {
|
||||||
slog.Error("FirstOrCreateTemplate", "err", err)
|
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 err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import (
|
|||||||
"easyvqd/internal/core/media"
|
"easyvqd/internal/core/media"
|
||||||
"easyvqd/internal/core/vqd"
|
"easyvqd/internal/core/vqd"
|
||||||
"easyvqd/internal/core/vqd/store/audioencodedb"
|
"easyvqd/internal/core/vqd/store/audioencodedb"
|
||||||
"easyvqd/internal/core/vqdsdk"
|
"easyvqd/internal/core/vqdtask"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"easyvqd/domain/uniqueid"
|
"easyvqd/domain/uniqueid"
|
||||||
@ -41,7 +41,7 @@ type Usecase struct {
|
|||||||
VqdTaskAPI VqdTaskAPI
|
VqdTaskAPI VqdTaskAPI
|
||||||
HostCore *host.Core
|
HostCore *host.Core
|
||||||
MediaCore *media.Core
|
MediaCore *media.Core
|
||||||
VqdSdkCore *vqdsdk.Core
|
VqdSdkCore *vqdtask.Core
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHTTPHandler 生成Gin框架路由内容
|
// NewHTTPHandler 生成Gin框架路由内容
|
||||||
|
|||||||
@ -37,7 +37,7 @@ func (a VqdTaskAPI) getVqdAlarm(c *gin.Context, _ *struct{}) (any, error) {
|
|||||||
ID, _ := strconv.Atoi(c.Param("id"))
|
ID, _ := strconv.Atoi(c.Param("id"))
|
||||||
item, err := a.core.GetVqdAlarm(c.Request.Context(), ID)
|
item, err := a.core.GetVqdAlarm(c.Request.Context(), ID)
|
||||||
if err != nil {
|
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 := make(map[string]interface{})
|
||||||
|
|
||||||
@ -61,18 +61,18 @@ func (a VqdTaskAPI) delVqdAlarm(c *gin.Context, _ *struct{}) (any, error) {
|
|||||||
ID, _ := strconv.Atoi(c.Param("id"))
|
ID, _ := strconv.Atoi(c.Param("id"))
|
||||||
_, err := a.core.DelVqdAlarm(c.Request.Context(), ID)
|
_, err := a.core.DelVqdAlarm(c.Request.Context(), ID)
|
||||||
if err != nil {
|
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
|
return gin.H{"data": "OK!"}, err
|
||||||
}
|
}
|
||||||
func (a VqdTaskAPI) delVqdAlarmAll(c *gin.Context, in *vqd.DelVqdAlarmInput) (any, error) {
|
func (a VqdTaskAPI) delVqdAlarmAll(c *gin.Context, in *vqd.DelVqdAlarmInput) (any, error) {
|
||||||
if len(in.IDs) == 0 {
|
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)
|
_, err := a.core.DelVqdAlarmAll(c.Request.Context(), in.IDs)
|
||||||
if err != nil {
|
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
|
return gin.H{"data": "OK!"}, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import (
|
|||||||
"easyvqd/internal/core/host"
|
"easyvqd/internal/core/host"
|
||||||
"easyvqd/internal/core/media"
|
"easyvqd/internal/core/media"
|
||||||
"easyvqd/internal/core/vqd"
|
"easyvqd/internal/core/vqd"
|
||||||
"easyvqd/internal/core/vqdsdk"
|
"easyvqd/internal/core/vqdtask"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.lnton.com/lnton/pkg/reason"
|
"git.lnton.com/lnton/pkg/reason"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@ -16,12 +16,12 @@ import (
|
|||||||
type VqdTaskAPI struct {
|
type VqdTaskAPI struct {
|
||||||
core *vqd.Core
|
core *vqd.Core
|
||||||
meidaCore *media.Core
|
meidaCore *media.Core
|
||||||
vqdSdkCore *vqdsdk.Core
|
vqdSdkCore *vqdtask.Core
|
||||||
cfg *conf.Bootstrap
|
cfg *conf.Bootstrap
|
||||||
HostCore *host.Core
|
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}
|
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.POST("", web.WarpH(api.addVqdTaskTemplate))
|
||||||
groupTemplate.DELETE("/:id", web.WarpH(api.delVqdTaskTemplate))
|
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 := g.Group("/api/alarm", handler...)
|
||||||
groupAlarm.GET("", web.WarpH(api.findVqdAlarm))
|
groupAlarm.GET("", web.WarpH(api.findVqdAlarm))
|
||||||
groupAlarm.GET("/:id", web.WarpH(api.getVqdAlarm))
|
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 := make(map[string]interface{})
|
||||||
row["name"] = item.Name
|
row["name"] = item.Name
|
||||||
row["id"] = item.ID
|
row["id"] = item.ID
|
||||||
|
row["enable"] = item.Enable
|
||||||
row["channel_id"] = item.ChannelID
|
row["channel_id"] = item.ChannelID
|
||||||
row["channel_name"] = item.ChannelName
|
row["channel_name"] = item.ChannelName
|
||||||
row["task_template_id"] = item.TaskTemplateID
|
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)
|
template, errs := a.core.GetIDVqdTaskTemplate(c.Request.Context(), item.TaskTemplateID)
|
||||||
if errs == nil && template != nil {
|
if errs == nil && template != nil {
|
||||||
row["task_template_name"] = template.Name
|
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["created_at"] = item.CreatedAt
|
||||||
row["updated_at"] = item.UpdatedAt
|
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"))
|
ID, _ := strconv.Atoi(c.Param("id"))
|
||||||
item, err := a.core.GetVqdTask(c.Request.Context(), ID)
|
item, err := a.core.GetVqdTask(c.Request.Context(), ID)
|
||||||
if err != nil {
|
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 := make(map[string]interface{})
|
||||||
|
|
||||||
row["name"] = item.Name
|
row["name"] = item.Name
|
||||||
row["id"] = item.ID
|
row["id"] = item.ID
|
||||||
|
row["enable"] = item.Enable
|
||||||
row["channel_id"] = item.ChannelID
|
row["channel_id"] = item.ChannelID
|
||||||
row["channel_name"] = item.ChannelName
|
row["channel_name"] = item.ChannelName
|
||||||
row["task_template_id"] = item.TaskTemplateID
|
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["created_at"] = item.CreatedAt
|
||||||
row["updated_at"] = item.UpdatedAt
|
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) {
|
func (a VqdTaskAPI) addVqdTask(c *gin.Context, in *vqd.AddVqdTaskInput) (any, error) {
|
||||||
_, err := a.core.AddVqdTask(c.Request.Context(), in)
|
_, err := a.core.AddVqdTask(c.Request.Context(), in)
|
||||||
if err != nil {
|
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
|
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"))
|
ID, _ := strconv.Atoi(c.Param("id"))
|
||||||
_, err := a.core.GetVqdTask(c.Request.Context(), ID)
|
_, err := a.core.GetVqdTask(c.Request.Context(), ID)
|
||||||
if err != nil {
|
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)
|
_, err = a.core.EditVqdTask(c.Request.Context(), in, ID)
|
||||||
if err != nil {
|
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
|
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"))
|
ID, _ := strconv.Atoi(c.Param("id"))
|
||||||
_, err := a.core.DelVqdTask(c.Request.Context(), ID)
|
_, err := a.core.DelVqdTask(c.Request.Context(), ID)
|
||||||
if err != nil {
|
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
|
return gin.H{"data": "OK!"}, err
|
||||||
|
|||||||
@ -18,8 +18,6 @@ func (a VqdTaskAPI) findVqdTaskTemplate(c *gin.Context, in *vqd.FindVqdTaskTempl
|
|||||||
row["id"] = item.ID
|
row["id"] = item.ID
|
||||||
row["name"] = item.Name
|
row["name"] = item.Name
|
||||||
row["des"] = item.Des
|
row["des"] = item.Des
|
||||||
row["plans"] = item.Plans
|
|
||||||
row["enable"] = item.Enable
|
|
||||||
row["is_default"] = item.IsDefault
|
row["is_default"] = item.IsDefault
|
||||||
row["vqd_config"] = item.VqdConfig
|
row["vqd_config"] = item.VqdConfig
|
||||||
row["vqd_lgt_dark"] = item.VqdLgtDark
|
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"))
|
ID, _ := strconv.Atoi(c.Param("id"))
|
||||||
item, err := a.core.GetVqdTaskTemplate(c.Request.Context(), ID)
|
item, err := a.core.GetVqdTaskTemplate(c.Request.Context(), ID)
|
||||||
if err != nil {
|
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 := 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_mosaic"] = item.VqdMosaic
|
||||||
row["vqd_flower"] = item.VqdFlower
|
row["vqd_flower"] = item.VqdFlower
|
||||||
row["des"] = item.Des
|
row["des"] = item.Des
|
||||||
row["plans"] = item.Plans
|
|
||||||
row["enable"] = item.Enable
|
|
||||||
row["created_at"] = item.CreatedAt
|
row["created_at"] = item.CreatedAt
|
||||||
row["updated_at"] = item.UpdatedAt
|
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) {
|
func (a VqdTaskAPI) addVqdTaskTemplate(c *gin.Context, in *vqd.AddVqdTaskTemplateInput) (any, error) {
|
||||||
_, err := a.core.AddVqdTaskTemplate(c.Request.Context(), in)
|
_, err := a.core.AddVqdTaskTemplate(c.Request.Context(), in)
|
||||||
if err != nil {
|
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
|
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"))
|
ID, _ := strconv.Atoi(c.Param("id"))
|
||||||
_, err := a.core.GetVqdTaskTemplate(c.Request.Context(), ID)
|
_, err := a.core.GetVqdTaskTemplate(c.Request.Context(), ID)
|
||||||
if err != nil {
|
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)
|
_, err = a.core.EditVqdTaskTemplate(c.Request.Context(), in, ID)
|
||||||
if err != nil {
|
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
|
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"))
|
ID, _ := strconv.Atoi(c.Param("id"))
|
||||||
info, err := a.core.GetVqdTaskTemplate(c.Request.Context(), ID)
|
info, err := a.core.GetVqdTaskTemplate(c.Request.Context(), ID)
|
||||||
if err != nil {
|
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 {
|
if info.IsDefault {
|
||||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`默认模板不支持删除 [%s] `, info.Name))
|
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)
|
_, err = a.core.DelVqdTaskTemplate(c.Request.Context(), ID)
|
||||||
if err != nil {
|
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
|
return gin.H{"data": "OK!"}, err
|
||||||
|
|||||||
95
internal/web/api/vqdtimetemplate.go
Normal file
95
internal/web/api/vqdtimetemplate.go
Normal file
@ -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
|
||||||
|
}
|
||||||
121
pkg/decoder/core.go
Normal file
121
pkg/decoder/core.go
Normal file
@ -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 <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
BIN
pkg/decoder/include/RTSP/aarch64/libEasyStreamClient.a
Normal file
BIN
pkg/decoder/include/RTSP/aarch64/libEasyStreamClient.a
Normal file
Binary file not shown.
BIN
pkg/decoder/include/RTSP/include/EasyAIFilterAPI.h
Normal file
BIN
pkg/decoder/include/RTSP/include/EasyAIFilterAPI.h
Normal file
Binary file not shown.
BIN
pkg/decoder/include/RTSP/include/EasyRTMPAPI.h
Normal file
BIN
pkg/decoder/include/RTSP/include/EasyRTMPAPI.h
Normal file
Binary file not shown.
90
pkg/decoder/include/RTSP/include/EasyStreamClientAPI.h
Normal file
90
pkg/decoder/include/RTSP/include/EasyStreamClientAPI.h
Normal file
@ -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
|
||||||
167
pkg/decoder/include/RTSP/include/EasyTypes.h
Normal file
167
pkg/decoder/include/RTSP/include/EasyTypes.h
Normal file
@ -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; /* 帧的长度 */
|
||||||
|
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
|
||||||
BIN
pkg/decoder/include/RTSP/lib/libEasyStreamClient.a
Normal file
BIN
pkg/decoder/include/RTSP/lib/libEasyStreamClient.a
Normal file
Binary file not shown.
BIN
pkg/decoder/include/RTSP/lib/libavcodec.a
Normal file
BIN
pkg/decoder/include/RTSP/lib/libavcodec.a
Normal file
Binary file not shown.
BIN
pkg/decoder/include/RTSP/lib/libavdevice.a
Normal file
BIN
pkg/decoder/include/RTSP/lib/libavdevice.a
Normal file
Binary file not shown.
BIN
pkg/decoder/include/RTSP/lib/libavfilter.a
Normal file
BIN
pkg/decoder/include/RTSP/lib/libavfilter.a
Normal file
Binary file not shown.
BIN
pkg/decoder/include/RTSP/lib/libavformat.a
Normal file
BIN
pkg/decoder/include/RTSP/lib/libavformat.a
Normal file
Binary file not shown.
BIN
pkg/decoder/include/RTSP/lib/libavutil.a
Normal file
BIN
pkg/decoder/include/RTSP/lib/libavutil.a
Normal file
Binary file not shown.
BIN
pkg/decoder/include/RTSP/lib/libbz2.a
Normal file
BIN
pkg/decoder/include/RTSP/lib/libbz2.a
Normal file
Binary file not shown.
BIN
pkg/decoder/include/RTSP/lib/libeasyaacencoder.a
Normal file
BIN
pkg/decoder/include/RTSP/lib/libeasyaacencoder.a
Normal file
Binary file not shown.
BIN
pkg/decoder/include/RTSP/lib/libfdk-aac.a
Normal file
BIN
pkg/decoder/include/RTSP/lib/libfdk-aac.a
Normal file
Binary file not shown.
BIN
pkg/decoder/include/RTSP/lib/libfreetype.a
Normal file
BIN
pkg/decoder/include/RTSP/lib/libfreetype.a
Normal file
Binary file not shown.
BIN
pkg/decoder/include/RTSP/lib/libpostproc.a
Normal file
BIN
pkg/decoder/include/RTSP/lib/libpostproc.a
Normal file
Binary file not shown.
BIN
pkg/decoder/include/RTSP/lib/libswresample.a
Normal file
BIN
pkg/decoder/include/RTSP/lib/libswresample.a
Normal file
Binary file not shown.
BIN
pkg/decoder/include/RTSP/lib/libswscale.a
Normal file
BIN
pkg/decoder/include/RTSP/lib/libswscale.a
Normal file
Binary file not shown.
BIN
pkg/decoder/include/RTSP/lib/libx264.a
Normal file
BIN
pkg/decoder/include/RTSP/lib/libx264.a
Normal file
Binary file not shown.
BIN
pkg/decoder/include/RTSP/lib/libz.a
Normal file
BIN
pkg/decoder/include/RTSP/lib/libz.a
Normal file
Binary file not shown.
1
pkg/decoder/include/ez_decoder.h
Normal file
1
pkg/decoder/include/ez_decoder.h
Normal file
@ -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);
/* <20><><EFBFBD><EFBFBD>־ */
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
|
||||||
BIN
pkg/decoder/include/linux/libez_decoder.a
Normal file
BIN
pkg/decoder/include/linux/libez_decoder.a
Normal file
Binary file not shown.
32
pkg/vqdcms/core.go
Normal file
32
pkg/vqdcms/core.go
Normal file
@ -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
|
||||||
|
}
|
||||||
73
pkg/vqdcms/include/ez_vqd.h
Normal file
73
pkg/vqdcms/include/ez_vqd.h
Normal file
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
// <20><>ȡ<EFBFBD>汾
|
||||||
|
Easy_NXU_EXPORTS_API int Easy_NXU_EXPORTS_APICALL
|
||||||
|
ez_vqd_version(char* version);
|
||||||
|
|
||||||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
Easy_NXU_EXPORTS_API int Easy_NXU_EXPORTS_APICALL
|
||||||
|
ez_vqd_create(VideoInfo *handle);
|
||||||
|
// ע<><D7A2><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
Easy_NXU_EXPORTS_API int Easy_NXU_EXPORTS_APICALL
|
||||||
|
ez_vqd_destroy(VideoInfo *handle);
|
||||||
|
|
||||||
|
// <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
|
||||||
|
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);
|
||||||
|
// <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
|
||||||
|
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
|
||||||
597
pkg/vqdcms/include/nxu_common.h
Normal file
597
pkg/vqdcms/include/nxu_common.h
Normal file
@ -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*/
|
||||||
453
pkg/vqdcms/include/nxu_vqd_api.h
Normal file
453
pkg/vqdcms/include/nxu_vqd_api.h
Normal file
@ -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 <stdio.h>
|
||||||
|
|
||||||
|
#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__
|
||||||
347
pkg/vqdcms/mode.go
Normal file
347
pkg/vqdcms/mode.go
Normal file
@ -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 */
|
||||||
|
}
|
||||||
92
pkg/vqdcms/type.go
Normal file
92
pkg/vqdcms/type.go
Normal file
@ -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"`
|
||||||
|
}
|
||||||
437
pkg/vqdcms/vqd.go
Normal file
437
pkg/vqdcms/vqd.go
Normal file
@ -0,0 +1,437 @@
|
|||||||
|
package vqdcms
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
}
|
||||||
314
pkg/vqdcms/vqd_linux.go
Normal file
314
pkg/vqdcms/vqd_linux.go
Normal file
@ -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 <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#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)
|
||||||
|
}
|
||||||
256
pkg/vqdcms/vqd_windows.go
Normal file
256
pkg/vqdcms/vqd_windows.go
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
package vqdcms
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -w -I${SRCDIR}/include -fPIC
|
||||||
|
#cgo CPPFLAGS: -w -I${SRCDIR}/include -fPIC
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "nxu_common.h"
|
||||||
|
#include "nxu_vqd_api.h"
|
||||||
|
#include "ez_vqd.h"
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -31,8 +31,6 @@ export async function GetVqdTaskTemplateById(id: string) {
|
|||||||
*/
|
*/
|
||||||
export async function UpdateVqdTaskTemplate(data: UpdateVqdTaskTemplateReq) {
|
export async function UpdateVqdTaskTemplate(data: UpdateVqdTaskTemplateReq) {
|
||||||
const { id, ...payload } = data;
|
const { id, ...payload } = data;
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
return await PUT<VqdTaskTemplateBaseRes>(`/template/${id}`, payload);
|
return await PUT<VqdTaskTemplateBaseRes>(`/template/${id}`, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
43
web/src/api/vqdtimetemplate.ts
Normal file
43
web/src/api/vqdtimetemplate.ts
Normal file
@ -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<VqdTimeTemplateRes>(`/plan`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建
|
||||||
|
* @param data 创建参数
|
||||||
|
*/
|
||||||
|
export async function CreateVqdTimeTemplate(data: CreateVqdTimeTemplateReq) {
|
||||||
|
return await POST<VqdTimeTemplateBaseRes>(`/plan`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情
|
||||||
|
* @param id ID
|
||||||
|
*/
|
||||||
|
export async function GetVqdTimeTemplateById(id: string) {
|
||||||
|
return await GET<VqdTimeTemplateDetailRes>(`/plan/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新
|
||||||
|
* @param data 更新参数(需包含 id)
|
||||||
|
*/
|
||||||
|
export async function UpdateVqdTimeTemplate(data: UpdateVqdTimeTemplateReq) {
|
||||||
|
const { id, ...payload } = data;
|
||||||
|
return await PUT<VqdTimeTemplateBaseRes>(`/plan/${id}`, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
* @param id ID
|
||||||
|
*/
|
||||||
|
export async function DeleteVqdTimeTemplate(id: number) {
|
||||||
|
return await DELETE<VqdTimeTemplateBaseRes>(`/plan/${id}`);
|
||||||
|
}
|
||||||
@ -1,8 +1,9 @@
|
|||||||
import { forwardRef, useImperativeHandle, useState, useRef } from "react";
|
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 { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
import { CreateVqdTask, UpdateVqdTask } from "../api/vqdtask";
|
import { CreateVqdTask, UpdateVqdTask } from "../api/vqdtask";
|
||||||
import { GetVqdTaskTemplate } from "../api/vqdtasktemplate";
|
import { GetVqdTaskTemplate } from "../api/vqdtasktemplate";
|
||||||
|
import { GetVqdTimeTemplate } from "../api/vqdtimetemplate";
|
||||||
import type { CreateVqdTaskReq, VqdTaskItem } from "../types/vqdtask";
|
import type { CreateVqdTaskReq, VqdTaskItem } from "../types/vqdtask";
|
||||||
import { useGlobal } from "../Context";
|
import { useGlobal } from "../Context";
|
||||||
import ChannelModel, { IChannelModelFunc } from "./channel/Channel";
|
import ChannelModel, { IChannelModelFunc } from "./channel/Channel";
|
||||||
@ -42,9 +43,9 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
|||||||
} else {
|
} else {
|
||||||
setEditing(false);
|
setEditing(false);
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
// form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
// bid: "2",
|
enable: true,
|
||||||
// });
|
});
|
||||||
}
|
}
|
||||||
setOpen(true);
|
setOpen(true);
|
||||||
},
|
},
|
||||||
@ -55,11 +56,9 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
|||||||
name: ""
|
name: ""
|
||||||
});
|
});
|
||||||
|
|
||||||
// 获取任务列表
|
// 获取模板列表
|
||||||
const {
|
const {
|
||||||
data: storageResponse,
|
data: storageResponse,
|
||||||
isLoading,
|
|
||||||
refetch,
|
|
||||||
} = useQuery({
|
} = useQuery({
|
||||||
queryKey: ["storage", pagination],
|
queryKey: ["storage", pagination],
|
||||||
queryFn: () =>
|
queryFn: () =>
|
||||||
@ -72,6 +71,21 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
|||||||
// refetchInterval: 4000,
|
// refetchInterval: 4000,
|
||||||
retry: 1,
|
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({
|
const { mutate: createMutate, isPending: creating } = useMutation({
|
||||||
mutationFn: CreateVqdTask,
|
mutationFn: CreateVqdTask,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
@ -101,7 +115,7 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
style={{ top: '-180px' }} // 距离顶部 80px(可改为 10% 等百分比)
|
// style={{ top: '-180px' }} // 距离顶部 80px(可改为 10% 等百分比)
|
||||||
title={title}
|
title={title}
|
||||||
destroyOnHidden={true}
|
destroyOnHidden={true}
|
||||||
open={open}
|
open={open}
|
||||||
@ -123,7 +137,7 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
|||||||
channel_id,
|
channel_id,
|
||||||
channel_name,
|
channel_name,
|
||||||
task_template_id,
|
task_template_id,
|
||||||
task_template_name,
|
time_template_id,
|
||||||
enable } = values as {
|
enable } = values as {
|
||||||
name: string;
|
name: string;
|
||||||
des: string;
|
des: string;
|
||||||
@ -131,7 +145,7 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
|||||||
channel_id: string;
|
channel_id: string;
|
||||||
channel_name: string;
|
channel_name: string;
|
||||||
task_template_id: number;
|
task_template_id: number;
|
||||||
task_template_name: string;
|
time_template_id: number;
|
||||||
enable: boolean;
|
enable: boolean;
|
||||||
};
|
};
|
||||||
const payload: CreateVqdTaskReq = {
|
const payload: CreateVqdTaskReq = {
|
||||||
@ -140,7 +154,7 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
|||||||
channel_id,
|
channel_id,
|
||||||
channel_name,
|
channel_name,
|
||||||
task_template_id,
|
task_template_id,
|
||||||
task_template_name,
|
time_template_id,
|
||||||
enable,
|
enable,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -174,7 +188,7 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
|||||||
}}>选择通道</Button>
|
}}>选择通道</Button>
|
||||||
</Space.Compact>
|
</Space.Compact>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="task_template_id" label="选择模板" rules={[{ required: true, message: "请选择模板" }]}>
|
<Form.Item name="task_template_id" label="关联模板" rules={[{ required: true, message: "请选择模板" }]}>
|
||||||
<Select
|
<Select
|
||||||
placeholder="请选择模板"
|
placeholder="请选择模板"
|
||||||
onChange={(res, item: any) => {
|
onChange={(res, item: any) => {
|
||||||
@ -189,12 +203,35 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
|||||||
></Select>
|
></Select>
|
||||||
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item name="time_template_id" label="关联计划" rules={[{ required: true, message: "请选择计划" }]}>
|
||||||
|
<Select
|
||||||
|
placeholder="请选择计划"
|
||||||
|
onChange={(res, item: any) => {
|
||||||
|
form.setFieldsValue({ task_template_name: item?.label });
|
||||||
|
}}
|
||||||
|
options={storageTimeResponse?.items
|
||||||
|
.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
}))
|
||||||
|
.filter((item) => item.value !== 0)}
|
||||||
|
></Select>
|
||||||
|
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="des"
|
name="des"
|
||||||
label="描述"
|
label="描述"
|
||||||
>
|
>
|
||||||
<Input placeholder="请输入描述" />
|
<Input placeholder="请输入描述" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
style={{ width: '20%' }}
|
||||||
|
name="enable"
|
||||||
|
label="启用"
|
||||||
|
>
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
{editing && (
|
{editing && (
|
||||||
<Form.Item name="id" hidden>
|
<Form.Item name="id" hidden>
|
||||||
<Input />
|
<Input />
|
||||||
@ -203,9 +240,6 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
|||||||
<Form.Item name="channel_name" hidden>
|
<Form.Item name="channel_name" hidden>
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="task_template_name" hidden>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
</Form>
|
||||||
<ChannelModel ref={channelRef} onCallback={(id: any, name: any) => {
|
<ChannelModel ref={channelRef} onCallback={(id: any, name: any) => {
|
||||||
form.setFieldsValue({ channel_id: id, channel_name: name });
|
form.setFieldsValue({ channel_id: id, channel_name: name });
|
||||||
|
|||||||
@ -1,63 +1,18 @@
|
|||||||
import { forwardRef, useImperativeHandle, useState, useRef, createContext, useContext, useEffect } from "react";
|
import { forwardRef, useImperativeHandle, useState, createContext, useContext } from "react";
|
||||||
import { Modal, Form, Input, InputNumber, Button, message, Row, Col, Card, Flex, Switch, Tabs, FormInstance } from "antd";
|
import { Modal, Form, Input, InputNumber, message, Flex, Switch, FormInstance } from "antd";
|
||||||
import { useMutation } from "@tanstack/react-query";
|
import { useMutation } from "@tanstack/react-query";
|
||||||
import { GetVqdConfigDefault } from "../api/config";
|
import { GetVqdConfigDefault } from "../api/config";
|
||||||
import { CreateVqdTaskTemplate, UpdateVqdTaskTemplate, } from "../api/vqdtasktemplate";
|
import { CreateVqdTaskTemplate, UpdateVqdTaskTemplate, } from "../api/vqdtasktemplate";
|
||||||
import type { CreateVqdTaskTemplateReq, VqdTaskTemplateItem } from "../types/vqdtasktemplate";
|
import type { CreateVqdTaskTemplateReq, VqdTaskTemplateItem } from "../types/vqdtasktemplate";
|
||||||
import { useGlobal } from "../Context";
|
import { useGlobal } from "../Context";
|
||||||
|
|
||||||
import type { TabsProps } from 'antd';
|
|
||||||
const week = [
|
|
||||||
'星期一',
|
|
||||||
'星期二',
|
|
||||||
'星期三',
|
|
||||||
'星期四',
|
|
||||||
'星期五',
|
|
||||||
'星期六',
|
|
||||||
'星期日',
|
|
||||||
];
|
|
||||||
|
|
||||||
const hour = [
|
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
|
||||||
22, 23,
|
|
||||||
];
|
|
||||||
|
|
||||||
const gridStyle: React.CSSProperties = {
|
|
||||||
border: '0.1px solid #ccc',
|
|
||||||
textAlign: 'center',
|
|
||||||
lineHeight: '40px',
|
|
||||||
userSelect: 'none',
|
|
||||||
};
|
|
||||||
const titleStyle: React.CSSProperties = {
|
|
||||||
border: '0.1px solid #ccc',
|
|
||||||
width: '90px',
|
|
||||||
textAlign: 'center',
|
|
||||||
lineHeight: '40px',
|
|
||||||
userSelect: 'none',
|
|
||||||
};
|
|
||||||
type PlansSpan = {
|
|
||||||
start: string;
|
|
||||||
end: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const emptyList = [
|
|
||||||
Array(24).fill(0),
|
|
||||||
Array(24).fill(0),
|
|
||||||
Array(24).fill(0),
|
|
||||||
Array(24).fill(0),
|
|
||||||
Array(24).fill(0),
|
|
||||||
Array(24).fill(0),
|
|
||||||
Array(24).fill(0),
|
|
||||||
];
|
|
||||||
interface AddVqdTaskTemplateProps {
|
interface AddVqdTaskTemplateProps {
|
||||||
title: string;
|
title: string;
|
||||||
onSuccess: () => void;
|
onSuccess: () => void;
|
||||||
}
|
}
|
||||||
interface IAddTemplateContext {
|
interface IAddTemplateContext {
|
||||||
editing: boolean;
|
editing: boolean;
|
||||||
checkList: number[][];
|
|
||||||
form: FormInstance<CreateVqdTaskTemplateReq>;
|
form: FormInstance<CreateVqdTaskTemplateReq>;
|
||||||
setCheckList: React.Dispatch<React.SetStateAction<number[][]>>;
|
|
||||||
onDelPullDeviceData: (index: number) => void;
|
onDelPullDeviceData: (index: number) => void;
|
||||||
}
|
}
|
||||||
const layout = {
|
const layout = {
|
||||||
@ -80,54 +35,21 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
|||||||
({ title, onSuccess }, ref) => {
|
({ title, onSuccess }, ref) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [editing, setEditing] = useState<boolean>(false);
|
const [editing, setEditing] = useState<boolean>(false);
|
||||||
const [checkList, setCheckList] = useState<number[][]>([...emptyList.map((list) => [...list])]);
|
|
||||||
|
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const { ErrorHandle } = useGlobal();
|
const { ErrorHandle } = useGlobal();
|
||||||
|
|
||||||
const arrayToString = (arr: number[][]): string => {
|
|
||||||
return arr.map((subArr) => subArr.join('')).join('');
|
|
||||||
}
|
|
||||||
const parsePlans = (value: string | undefined): number[][] => {
|
|
||||||
const result: number[][] = [];
|
|
||||||
if (!value) return result;
|
|
||||||
const binaryArray: number[] = value.split('').map(Number);
|
|
||||||
while (binaryArray.length) {
|
|
||||||
result.push(binaryArray.splice(0, 24));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
const onChange = (key: string) => {
|
|
||||||
console.log(key);
|
|
||||||
};
|
|
||||||
|
|
||||||
const itemsTabs: TabsProps['items'] = [
|
|
||||||
{
|
|
||||||
key: '1',
|
|
||||||
forceRender: true,
|
|
||||||
label: '诊断参数',
|
|
||||||
children: <TemplateConfig />
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: '2',
|
|
||||||
forceRender: true,
|
|
||||||
label: '诊断时间',
|
|
||||||
children: <TemplatePlans />
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const { mutate: getVqdConfigDefault } = useMutation({
|
const { mutate: getVqdConfigDefault } = useMutation({
|
||||||
mutationFn: GetVqdConfigDefault,
|
mutationFn: GetVqdConfigDefault,
|
||||||
onSuccess: (res) => {
|
onSuccess: (res) => {
|
||||||
const formValues = {
|
const formValues = {
|
||||||
|
name: '',
|
||||||
|
des: '',
|
||||||
vqd_config: {
|
vqd_config: {
|
||||||
enable: false,
|
enable: false,
|
||||||
frm_num: res.data.frm_num,
|
frm_num: res.data.frm_num,
|
||||||
is_deep_learn: res.data.is_deep_learn,
|
is_deep_learn: res.data.is_deep_learn,
|
||||||
},
|
},
|
||||||
enable: true,
|
|
||||||
plans: '',
|
|
||||||
des: '',
|
|
||||||
name: '',
|
|
||||||
vqd_lgt_dark: res.data.vqd_lgt_dark,
|
vqd_lgt_dark: res.data.vqd_lgt_dark,
|
||||||
vqd_blue: res.data.vqd_blue,
|
vqd_blue: res.data.vqd_blue,
|
||||||
vqd_clarity: res.data.vqd_clarity,
|
vqd_clarity: res.data.vqd_clarity,
|
||||||
@ -162,8 +84,6 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
|||||||
const formValues = {
|
const formValues = {
|
||||||
name: task.name,
|
name: task.name,
|
||||||
id: task.id,
|
id: task.id,
|
||||||
plans: task.plans,
|
|
||||||
enable: task.enable,
|
|
||||||
des: task.des,
|
des: task.des,
|
||||||
vqd_config: task.vqd_config,
|
vqd_config: task.vqd_config,
|
||||||
vqd_lgt_dark: task.vqd_lgt_dark,
|
vqd_lgt_dark: task.vqd_lgt_dark,
|
||||||
@ -178,7 +98,6 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
|||||||
vqd_mosaic: task.vqd_mosaic,
|
vqd_mosaic: task.vqd_mosaic,
|
||||||
vqd_flower: task.vqd_flower,
|
vqd_flower: task.vqd_flower,
|
||||||
};
|
};
|
||||||
setCheckList(parsePlans(task.plans))
|
|
||||||
form.setFieldsValue(formValues);
|
form.setFieldsValue(formValues);
|
||||||
} else {
|
} else {
|
||||||
getVqdConfigDefault()
|
getVqdConfigDefault()
|
||||||
@ -224,9 +143,7 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
|||||||
<AddTemplateContext.Provider
|
<AddTemplateContext.Provider
|
||||||
value={{
|
value={{
|
||||||
form,
|
form,
|
||||||
checkList,
|
|
||||||
editing,
|
editing,
|
||||||
setCheckList,
|
|
||||||
onDelPullDeviceData
|
onDelPullDeviceData
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -247,7 +164,7 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
|||||||
onFinish={(values: CreateVqdTaskTemplateReq) => {
|
onFinish={(values: CreateVqdTaskTemplateReq) => {
|
||||||
if (creating || updating) return
|
if (creating || updating) return
|
||||||
const payload = values as CreateVqdTaskTemplateReq;
|
const payload = values as CreateVqdTaskTemplateReq;
|
||||||
payload.plans = arrayToString(checkList)
|
|
||||||
console.log(payload);
|
console.log(payload);
|
||||||
if (editing) {
|
if (editing) {
|
||||||
const id = (values as any).id;
|
const id = (values as any).id;
|
||||||
@ -276,17 +193,9 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
|||||||
>
|
>
|
||||||
<Input placeholder="请输入描述" />
|
<Input placeholder="请输入描述" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
style={{ width: '20%' }}
|
|
||||||
name="enable"
|
|
||||||
label="启用"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<Tabs defaultActiveKey="1" items={itemsTabs} onChange={onChange} />
|
<TemplateConfig />
|
||||||
|
|
||||||
|
|
||||||
{editing && (
|
{editing && (
|
||||||
<Form.Item name="id" hidden>
|
<Form.Item name="id" hidden>
|
||||||
@ -302,182 +211,6 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
|||||||
|
|
||||||
export default AddVqdTaskTemplate;
|
export default AddVqdTaskTemplate;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const TemplatePlans: React.FC = () => {
|
|
||||||
const {
|
|
||||||
checkList,
|
|
||||||
editing,
|
|
||||||
setCheckList,
|
|
||||||
form,
|
|
||||||
} = useAddTemplate();
|
|
||||||
// 开始滑动选择
|
|
||||||
const [config, setConfig] = useState<{
|
|
||||||
start: boolean;
|
|
||||||
}>({ start: false });
|
|
||||||
|
|
||||||
const selector = useRef<boolean>(true);
|
|
||||||
|
|
||||||
const [coping, setCoping] = useState<
|
|
||||||
{ index: number; value: number[] } | undefined
|
|
||||||
>();
|
|
||||||
|
|
||||||
const handler = (list: number[]) => {
|
|
||||||
let out: PlansSpan[] = [];
|
|
||||||
let start = false;
|
|
||||||
let timeParam: PlansSpan = { start: '', end: '' };
|
|
||||||
for (let i = 0; i < list.length; i++) {
|
|
||||||
const v = list[i];
|
|
||||||
|
|
||||||
let s = i.toString().padStart(2, '0');
|
|
||||||
if (i == 23 && v == 1) {
|
|
||||||
s = '24';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!start && v == 1) {
|
|
||||||
start = true;
|
|
||||||
timeParam = { start: `${i}:00`, end: '' };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (start && (v == 0 || i == list.length - 1)) {
|
|
||||||
start = false;
|
|
||||||
timeParam.end = `${s}:00`;
|
|
||||||
out.push(timeParam);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
};
|
|
||||||
|
|
||||||
return <>
|
|
||||||
<div style={{ border: '1px solid #999' }}>
|
|
||||||
<Row wrap={false}>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
...titleStyle,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Week/Time
|
|
||||||
</div>
|
|
||||||
<Row wrap={false} style={{ width: '86.5%' }}>
|
|
||||||
{[...hour].map((v, idx) => {
|
|
||||||
return (
|
|
||||||
<Col key={v} span={1} style={gridStyle}>
|
|
||||||
{v}
|
|
||||||
</Col>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Row>
|
|
||||||
</Row>
|
|
||||||
{week.map((v, weekIdx) => {
|
|
||||||
return (
|
|
||||||
<Row
|
|
||||||
key={v}
|
|
||||||
onMouseDown={() => setConfig({ ...config, start: true })}
|
|
||||||
onMouseUp={() => setConfig({ ...config, start: false })}
|
|
||||||
wrap={false}
|
|
||||||
>
|
|
||||||
<div style={titleStyle}>{v}</div>
|
|
||||||
<Row key={v + '1'} wrap={false} style={{ width: '86.5%' }}>
|
|
||||||
{[...hour].map((v, hourIdx) => {
|
|
||||||
// 时间选择
|
|
||||||
return (
|
|
||||||
<Col
|
|
||||||
onMouseOver={() => {
|
|
||||||
if (!config.start) return;
|
|
||||||
setCheckList((v) => {
|
|
||||||
let list = [...v];
|
|
||||||
list[weekIdx][hourIdx] = selector.current ? 1 : 0;
|
|
||||||
return list;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
onMouseDown={() => {
|
|
||||||
selector.current = checkList[weekIdx][hourIdx] == 0;
|
|
||||||
setCheckList((v) => {
|
|
||||||
let list = [...v];
|
|
||||||
list[weekIdx][hourIdx] = selector.current ? 1 : 0;
|
|
||||||
return list;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
key={v}
|
|
||||||
span={1}
|
|
||||||
style={{
|
|
||||||
...gridStyle,
|
|
||||||
backgroundColor:
|
|
||||||
checkList[weekIdx][hourIdx] == 1
|
|
||||||
? '#658EE0'
|
|
||||||
: 'white',
|
|
||||||
}}
|
|
||||||
></Col>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
margin: 'auto',
|
|
||||||
marginLeft: '2px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
type={coping?.index == weekIdx ? 'primary' : 'default'}
|
|
||||||
size="small"
|
|
||||||
style={{ padding: '1px 5px', fontSize: '12px' }}
|
|
||||||
onClick={() => {
|
|
||||||
if (!coping) {
|
|
||||||
setCoping({
|
|
||||||
index: weekIdx,
|
|
||||||
value: checkList[weekIdx],
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setCheckList((v) => {
|
|
||||||
let list = [...v];
|
|
||||||
list[weekIdx] = [...coping.value];
|
|
||||||
return list;
|
|
||||||
});
|
|
||||||
setCoping(undefined);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{!coping || coping?.index == weekIdx ? "复制" : "粘贴"}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</Row>
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ height: '20px' }}></div>
|
|
||||||
|
|
||||||
<Card>
|
|
||||||
<div>
|
|
||||||
<span>时间段</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{week.map((v, weekIdx) => {
|
|
||||||
return (
|
|
||||||
// 周
|
|
||||||
<Row wrap={false} key={v}>
|
|
||||||
<div style={{ color: '#9A9A9A', paddingRight: '5px' }}>
|
|
||||||
<span>{v}</span> :
|
|
||||||
</div>
|
|
||||||
<Row wrap={false}>
|
|
||||||
{handler(checkList[weekIdx]).map((v, idx, arr) => {
|
|
||||||
// 已选时间段
|
|
||||||
return (
|
|
||||||
<Col key={`${v.start}~${v.end}_${idx}_${weekIdx}`}>
|
|
||||||
{`${v.start}~${v.end}` +
|
|
||||||
(idx < arr.length - 1 ? ',' : '')}
|
|
||||||
</Col>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Row>
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
const BoxInputNumber: React.FC<{
|
const BoxInputNumber: React.FC<{
|
||||||
parent: string;
|
parent: string;
|
||||||
children: string;
|
children: string;
|
||||||
|
|||||||
450
web/src/components/AddVqdTimeTemplate.tsx
Normal file
450
web/src/components/AddVqdTimeTemplate.tsx
Normal file
@ -0,0 +1,450 @@
|
|||||||
|
import { forwardRef, useImperativeHandle, useState, useRef, createContext, useContext, useEffect } from "react";
|
||||||
|
import { Modal, Form, Input, InputNumber, Button, message, Row, Col, Card, Flex, Switch, Tabs, FormInstance } from "antd";
|
||||||
|
import { useMutation } from "@tanstack/react-query";
|
||||||
|
import { GetVqdConfigDefault } from "../api/config";
|
||||||
|
import { CreateVqdTimeTemplate, UpdateVqdTimeTemplate, } from "../api/vqdtimetemplate";
|
||||||
|
import type { CreateVqdTimeTemplateReq, VqdTimeTemplateItem } from "../types/vqdtimetemplate";
|
||||||
|
import { useGlobal } from "../Context";
|
||||||
|
|
||||||
|
const week = [
|
||||||
|
'星期一',
|
||||||
|
'星期二',
|
||||||
|
'星期三',
|
||||||
|
'星期四',
|
||||||
|
'星期五',
|
||||||
|
'星期六',
|
||||||
|
'星期日',
|
||||||
|
];
|
||||||
|
|
||||||
|
const hour = [
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
||||||
|
22, 23,
|
||||||
|
];
|
||||||
|
|
||||||
|
const gridStyle: React.CSSProperties = {
|
||||||
|
border: '0.1px solid #ccc',
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: '40px',
|
||||||
|
userSelect: 'none',
|
||||||
|
};
|
||||||
|
const titleStyle: React.CSSProperties = {
|
||||||
|
border: '0.1px solid #ccc',
|
||||||
|
width: '90px',
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: '40px',
|
||||||
|
userSelect: 'none',
|
||||||
|
};
|
||||||
|
type PlansSpan = {
|
||||||
|
start: string;
|
||||||
|
end: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const emptyList = [
|
||||||
|
Array(24).fill(0),
|
||||||
|
Array(24).fill(0),
|
||||||
|
Array(24).fill(0),
|
||||||
|
Array(24).fill(0),
|
||||||
|
Array(24).fill(0),
|
||||||
|
Array(24).fill(0),
|
||||||
|
Array(24).fill(0),
|
||||||
|
];
|
||||||
|
interface AddVqdTimeTemplateProps {
|
||||||
|
title: string;
|
||||||
|
onSuccess: () => void;
|
||||||
|
}
|
||||||
|
interface IAddTemplateContext {
|
||||||
|
editing: boolean;
|
||||||
|
checkList: number[][];
|
||||||
|
form: FormInstance<CreateVqdTimeTemplateReq>;
|
||||||
|
setCheckList: React.Dispatch<React.SetStateAction<number[][]>>;
|
||||||
|
onDelPullDeviceData: (index: number) => void;
|
||||||
|
}
|
||||||
|
const layout = {
|
||||||
|
labelCol: { span: 10 },
|
||||||
|
wrapperCol: { span: 14 },
|
||||||
|
};
|
||||||
|
const AddTemplateContext = createContext<IAddTemplateContext | null>(null);
|
||||||
|
const useAddTemplate = () => {
|
||||||
|
const context = useContext(AddTemplateContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error('useAddTemplate must be used within a AddTemplateProvider');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
export interface AddVqdTimeTemplateRef {
|
||||||
|
open: (task?: VqdTimeTemplateItem) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AddVqdTimeTemplate = forwardRef<AddVqdTimeTemplateRef, AddVqdTimeTemplateProps>(
|
||||||
|
({ title, onSuccess }, ref) => {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [editing, setEditing] = useState<boolean>(false);
|
||||||
|
const [checkList, setCheckList] = useState<number[][]>([...emptyList.map((list) => [...list])]);
|
||||||
|
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const { ErrorHandle } = useGlobal();
|
||||||
|
|
||||||
|
const arrayToString = (arr: number[][]): string => {
|
||||||
|
return arr.map((subArr) => subArr.join('')).join('');
|
||||||
|
}
|
||||||
|
const parsePlans = (value: string | undefined): number[][] => {
|
||||||
|
const result: number[][] = [];
|
||||||
|
if (!value) return result;
|
||||||
|
const binaryArray: number[] = value.split('').map(Number);
|
||||||
|
while (binaryArray.length) {
|
||||||
|
result.push(binaryArray.splice(0, 24));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
const onChange = (key: string) => {
|
||||||
|
console.log(key);
|
||||||
|
};
|
||||||
|
const { mutate: getVqdConfigDefault } = useMutation({
|
||||||
|
mutationFn: GetVqdConfigDefault,
|
||||||
|
onSuccess: (res) => {
|
||||||
|
const formValues = {
|
||||||
|
vqd_config: {
|
||||||
|
enable: false,
|
||||||
|
frm_num: res.data.frm_num,
|
||||||
|
is_deep_learn: res.data.is_deep_learn,
|
||||||
|
},
|
||||||
|
enable: true,
|
||||||
|
plans: '',
|
||||||
|
des: '',
|
||||||
|
name: '',
|
||||||
|
vqd_lgt_dark: res.data.vqd_lgt_dark,
|
||||||
|
vqd_blue: res.data.vqd_blue,
|
||||||
|
vqd_clarity: res.data.vqd_clarity,
|
||||||
|
vqd_shark: res.data.vqd_shark,
|
||||||
|
vqd_freeze: res.data.vqd_freeze,
|
||||||
|
vqd_color: res.data.vqd_color,
|
||||||
|
vqd_occlusion: res.data.vqd_occlusion,
|
||||||
|
vqd_noise: res.data.vqd_noise,
|
||||||
|
vqd_contrast: res.data.vqd_contrast,
|
||||||
|
vqd_mosaic: res.data.vqd_mosaic,
|
||||||
|
vqd_flower: res.data.vqd_flower,
|
||||||
|
};
|
||||||
|
formValues.vqd_lgt_dark.enable = false
|
||||||
|
formValues.vqd_blue.enable = false
|
||||||
|
formValues.vqd_clarity.enable = false
|
||||||
|
formValues.vqd_shark.enable = false
|
||||||
|
formValues.vqd_freeze.enable = false
|
||||||
|
formValues.vqd_color.enable = false
|
||||||
|
formValues.vqd_occlusion.enable = false
|
||||||
|
formValues.vqd_noise.enable = false
|
||||||
|
formValues.vqd_contrast.enable = false
|
||||||
|
formValues.vqd_mosaic.enable = false
|
||||||
|
formValues.vqd_flower.enable = false
|
||||||
|
form.setFieldsValue(formValues);
|
||||||
|
},
|
||||||
|
onError: ErrorHandle,
|
||||||
|
});
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
open: (task?: VqdTimeTemplateItem) => {
|
||||||
|
if (task) {
|
||||||
|
setEditing(true);
|
||||||
|
const formValues = {
|
||||||
|
name: task.name,
|
||||||
|
id: task.id,
|
||||||
|
plans: task.plans,
|
||||||
|
enable: task.enable,
|
||||||
|
des: task.des,
|
||||||
|
};
|
||||||
|
setCheckList(parsePlans(task.plans))
|
||||||
|
form.setFieldsValue(formValues);
|
||||||
|
} else {
|
||||||
|
getVqdConfigDefault()
|
||||||
|
setEditing(false);
|
||||||
|
form.resetFields();
|
||||||
|
form.setFieldsValue({
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setOpen(true);
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const { mutate: createMutate, isPending: creating } = useMutation({
|
||||||
|
mutationFn: CreateVqdTimeTemplate,
|
||||||
|
onSuccess: () => {
|
||||||
|
message.success("创建任务成功");
|
||||||
|
handleClose();
|
||||||
|
onSuccess?.();
|
||||||
|
},
|
||||||
|
onError: ErrorHandle,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { mutate: updateMutate, isPending: updating } = useMutation({
|
||||||
|
mutationFn: UpdateVqdTimeTemplate,
|
||||||
|
onSuccess: () => {
|
||||||
|
message.success("更新任务成功");
|
||||||
|
handleClose();
|
||||||
|
onSuccess?.();
|
||||||
|
},
|
||||||
|
onError: ErrorHandle,
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setOpen(false);
|
||||||
|
setEditing(false);
|
||||||
|
setCheckList([...emptyList.map((list) => [...list])])
|
||||||
|
form.resetFields();
|
||||||
|
};
|
||||||
|
const onDelPullDeviceData = (index: number) => {
|
||||||
|
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<AddTemplateContext.Provider
|
||||||
|
value={{
|
||||||
|
form,
|
||||||
|
checkList,
|
||||||
|
editing,
|
||||||
|
setCheckList,
|
||||||
|
onDelPullDeviceData
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Modal
|
||||||
|
// style={{ top: '-180px' }} // 距离顶部 80px(可改为 10% 等百分比)
|
||||||
|
title={title}
|
||||||
|
width={"64%"}
|
||||||
|
open={open}
|
||||||
|
onCancel={handleClose}
|
||||||
|
destroyOnHidden={true}
|
||||||
|
centered
|
||||||
|
onOk={() => form.submit()}
|
||||||
|
confirmLoading={creating || updating}
|
||||||
|
>
|
||||||
|
<Form
|
||||||
|
form={form}
|
||||||
|
{...layout}
|
||||||
|
onFinish={(values: CreateVqdTimeTemplateReq) => {
|
||||||
|
if (creating || updating) return
|
||||||
|
const payload = values as CreateVqdTimeTemplateReq;
|
||||||
|
payload.plans = arrayToString(checkList)
|
||||||
|
console.log(payload);
|
||||||
|
if (editing) {
|
||||||
|
const id = (values as any).id;
|
||||||
|
updateMutate({ id: String(id), ...payload });
|
||||||
|
} else {
|
||||||
|
createMutate(payload);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<br />
|
||||||
|
<Flex gap="large" >
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
style={{ width: '30%' }}
|
||||||
|
name="name"
|
||||||
|
label="计划名称"
|
||||||
|
rules={[{ required: true, message: "请输入计划名称" }]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入名称" />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
style={{ width: '30%' }}
|
||||||
|
name="des"
|
||||||
|
label="描述"
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入描述" />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
style={{ width: '20%' }}
|
||||||
|
name="enable"
|
||||||
|
label="启用"
|
||||||
|
>
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
|
</Flex>
|
||||||
|
<TemplatePlans />
|
||||||
|
{editing && (
|
||||||
|
<Form.Item name="id" hidden>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
)}
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
</AddTemplateContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export default AddVqdTimeTemplate;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const TemplatePlans: React.FC = () => {
|
||||||
|
const {
|
||||||
|
checkList,
|
||||||
|
editing,
|
||||||
|
setCheckList,
|
||||||
|
form,
|
||||||
|
} = useAddTemplate();
|
||||||
|
// 开始滑动选择
|
||||||
|
const [config, setConfig] = useState<{
|
||||||
|
start: boolean;
|
||||||
|
}>({ start: false });
|
||||||
|
|
||||||
|
const selector = useRef<boolean>(true);
|
||||||
|
|
||||||
|
const [coping, setCoping] = useState<
|
||||||
|
{ index: number; value: number[] } | undefined
|
||||||
|
>();
|
||||||
|
|
||||||
|
const handler = (list: number[]) => {
|
||||||
|
let out: PlansSpan[] = [];
|
||||||
|
let start = false;
|
||||||
|
let timeParam: PlansSpan = { start: '', end: '' };
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
const v = list[i];
|
||||||
|
|
||||||
|
let s = i.toString().padStart(2, '0');
|
||||||
|
if (i == 23 && v == 1) {
|
||||||
|
s = '24';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!start && v == 1) {
|
||||||
|
start = true;
|
||||||
|
timeParam = { start: `${i}:00`, end: '' };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start && (v == 0 || i == list.length - 1)) {
|
||||||
|
start = false;
|
||||||
|
timeParam.end = `${s}:00`;
|
||||||
|
out.push(timeParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<div style={{ border: '1px solid #999' }}>
|
||||||
|
<Row wrap={false}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
...titleStyle,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Week/Time
|
||||||
|
</div>
|
||||||
|
<Row wrap={false} style={{ width: '86.5%' }}>
|
||||||
|
{[...hour].map((v, idx) => {
|
||||||
|
return (
|
||||||
|
<Col key={v} span={1} style={gridStyle}>
|
||||||
|
{v}
|
||||||
|
</Col>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Row>
|
||||||
|
</Row>
|
||||||
|
{week.map((v, weekIdx) => {
|
||||||
|
return (
|
||||||
|
<Row
|
||||||
|
key={v}
|
||||||
|
onMouseDown={() => setConfig({ ...config, start: true })}
|
||||||
|
onMouseUp={() => setConfig({ ...config, start: false })}
|
||||||
|
wrap={false}
|
||||||
|
>
|
||||||
|
<div style={titleStyle}>{v}</div>
|
||||||
|
<Row key={v + '1'} wrap={false} style={{ width: '86.5%' }}>
|
||||||
|
{[...hour].map((v, hourIdx) => {
|
||||||
|
// 时间选择
|
||||||
|
return (
|
||||||
|
<Col
|
||||||
|
onMouseOver={() => {
|
||||||
|
if (!config.start) return;
|
||||||
|
setCheckList((v) => {
|
||||||
|
let list = [...v];
|
||||||
|
list[weekIdx][hourIdx] = selector.current ? 1 : 0;
|
||||||
|
return list;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
onMouseDown={() => {
|
||||||
|
selector.current = checkList[weekIdx][hourIdx] == 0;
|
||||||
|
setCheckList((v) => {
|
||||||
|
let list = [...v];
|
||||||
|
list[weekIdx][hourIdx] = selector.current ? 1 : 0;
|
||||||
|
return list;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
key={v}
|
||||||
|
span={1}
|
||||||
|
style={{
|
||||||
|
...gridStyle,
|
||||||
|
backgroundColor:
|
||||||
|
checkList[weekIdx][hourIdx] == 1
|
||||||
|
? '#658EE0'
|
||||||
|
: 'white',
|
||||||
|
}}
|
||||||
|
></Col>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
margin: 'auto',
|
||||||
|
marginLeft: '2px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type={coping?.index == weekIdx ? 'primary' : 'default'}
|
||||||
|
size="small"
|
||||||
|
style={{ padding: '1px 5px', fontSize: '12px' }}
|
||||||
|
onClick={() => {
|
||||||
|
if (!coping) {
|
||||||
|
setCoping({
|
||||||
|
index: weekIdx,
|
||||||
|
value: checkList[weekIdx],
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setCheckList((v) => {
|
||||||
|
let list = [...v];
|
||||||
|
list[weekIdx] = [...coping.value];
|
||||||
|
return list;
|
||||||
|
});
|
||||||
|
setCoping(undefined);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{!coping || coping?.index == weekIdx ? "复制" : "粘贴"}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ height: '20px' }}></div>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<div>
|
||||||
|
<span>时间段</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{week.map((v, weekIdx) => {
|
||||||
|
return (
|
||||||
|
// 周
|
||||||
|
<Row wrap={false} key={v}>
|
||||||
|
<div style={{ color: '#9A9A9A', paddingRight: '5px' }}>
|
||||||
|
<span>{v}</span> :
|
||||||
|
</div>
|
||||||
|
<Row wrap={false}>
|
||||||
|
{handler(checkList[weekIdx]).map((v, idx, arr) => {
|
||||||
|
// 已选时间段
|
||||||
|
return (
|
||||||
|
<Col key={`${v.start}~${v.end}_${idx}_${weekIdx}`}>
|
||||||
|
{`${v.start}~${v.end}` +
|
||||||
|
(idx < arr.length - 1 ? ',' : '')}
|
||||||
|
</Col>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Row>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</>
|
||||||
|
}
|
||||||
@ -9,13 +9,13 @@ import { useGlobal } from "../Context";
|
|||||||
import { FormatFileSizeToString } from "../utils/rate";
|
import { FormatFileSizeToString } from "../utils/rate";
|
||||||
import { formatSecondsToHMS } from "../utils/time";
|
import { formatSecondsToHMS } from "../utils/time";
|
||||||
import Filter from "./Filter";
|
import Filter from "./Filter";
|
||||||
import AlarmSnap from './snap';
|
import AlarmSnap from './Snap';
|
||||||
const variants = ['filled'] as const;
|
const variants = ['filled'] as const;
|
||||||
export default function VqdAlarmPage() {
|
export default function VqdAlarmPage() {
|
||||||
const { ErrorHandle } = useGlobal();
|
const { ErrorHandle } = useGlobal();
|
||||||
const [pagination, setPagination] = useState({
|
const [pagination, setPagination] = useState({
|
||||||
page: 1,
|
page: 1,
|
||||||
size: 10,
|
size: 12,
|
||||||
name: ""
|
name: ""
|
||||||
});
|
});
|
||||||
const [arrList, setArrList] = useState<any>([{ name: "全部类型", id: 0 }]);
|
const [arrList, setArrList] = useState<any>([{ name: "全部类型", id: 0 }]);
|
||||||
@ -206,24 +206,25 @@ export default function VqdAlarmPage() {
|
|||||||
}}
|
}}
|
||||||
/> */}
|
/> */}
|
||||||
|
|
||||||
<Flex justify="flex-end" className="mr-2" align="center">
|
<Flex justify="space-between" className="mr-2" align="center">
|
||||||
{/* <Space className="pl-2">
|
<Space className="pl-2">
|
||||||
|
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
title="确定要批量删除文件吗?"
|
title="确定要批量删除文件吗?"
|
||||||
|
|
||||||
onConfirm={() => {
|
onConfirm={() => {
|
||||||
deleteMutationAll({ ids: selectedRowKeys as number[] })
|
const ids = storageResponse?.items.map(item => item.id);
|
||||||
|
deleteMutationAll({ ids: ids as number[] })
|
||||||
}}
|
}}
|
||||||
okText="确定"
|
okText="确定"
|
||||||
cancelText="取消"
|
cancelText="取消"
|
||||||
>
|
>
|
||||||
<Button color="danger" variant="solid" loading={delAllLoadings} disabled={selectedRowKeys.length == 0} >
|
<Button color="danger" variant="solid" loading={delAllLoadings} >
|
||||||
批量删除
|
批量删除本页
|
||||||
</Button>
|
</Button>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
|
|
||||||
</Space> */}
|
</Space>
|
||||||
{/* <DatePicker
|
{/* <DatePicker
|
||||||
defaultDate={moment().format('YYYY-MM-DD')}
|
defaultDate={moment().format('YYYY-MM-DD')}
|
||||||
moonData={moonReq}
|
moonData={moonReq}
|
||||||
@ -284,7 +285,7 @@ export default function VqdAlarmPage() {
|
|||||||
title="删除告警"
|
title="删除告警"
|
||||||
description="确定要删除此告警吗?"
|
description="确定要删除此告警吗?"
|
||||||
onConfirm={() => {
|
onConfirm={() => {
|
||||||
// delAlarmSnapshot([item.id])
|
deleteMutation(item.id)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* loading={isDelLoading} */}
|
{/* loading={isDelLoading} */}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import { useRef, useState, useMemo } from "react";
|
import { useRef, useState, useMemo } from "react";
|
||||||
import { Table, Button, Space, Popconfirm, Flex, message, Tooltip } from "antd";
|
import { Table, Button, Space, Popconfirm, Flex, message, Tooltip, Switch } from "antd";
|
||||||
import { EditOutlined, DeleteOutlined, PlusOutlined } from "@ant-design/icons";
|
import { EditOutlined, DeleteOutlined, PlusOutlined } from "@ant-design/icons";
|
||||||
import { useQuery, useMutation } from "@tanstack/react-query";
|
import { useQuery, useMutation } from "@tanstack/react-query";
|
||||||
import { GetVqdTask, DeleteVqdTask } from "../api/vqdtask";
|
import { GetVqdTask, DeleteVqdTask, UpdateVqdTask } from "../api/vqdtask";
|
||||||
import type { VqdTaskItem } from "../types/vqdtask";
|
import type { VqdTaskItem, CreateVqdTaskReq } from "../types/vqdtask";
|
||||||
import type { ColumnsType } from "antd/es/table";
|
import type { ColumnsType } from "antd/es/table";
|
||||||
import AddVqdTask, { AddVqdTaskRef } from "./AddVqdTask";
|
import AddVqdTask, { AddVqdTaskRef } from "./AddVqdTask";
|
||||||
import { useGlobal } from "../Context";
|
import { useGlobal } from "../Context";
|
||||||
@ -91,6 +91,21 @@ export default function VqdTaskPage() {
|
|||||||
setSelectedRowKeys([...newSelectedRowKeys]);
|
setSelectedRowKeys([...newSelectedRowKeys]);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
const { mutate: updateMutate } = useMutation({
|
||||||
|
mutationFn: UpdateVqdTask,
|
||||||
|
onSuccess: () => {
|
||||||
|
message.success("更新成功");
|
||||||
|
setTimeout(() => {
|
||||||
|
refetch()
|
||||||
|
}, 500);
|
||||||
|
},
|
||||||
|
onError: ErrorHandle,
|
||||||
|
});
|
||||||
|
const saveTemplate = (disk: VqdTaskItem, t: boolean) => {
|
||||||
|
const payload = disk as CreateVqdTaskReq;
|
||||||
|
payload.enable = t
|
||||||
|
updateMutate({ id: String(disk.id), ...payload })
|
||||||
|
};
|
||||||
// 表格列定义
|
// 表格列定义
|
||||||
const columns: ColumnsType<VqdTaskItem> = [
|
const columns: ColumnsType<VqdTaskItem> = [
|
||||||
{
|
{
|
||||||
@ -109,7 +124,7 @@ export default function VqdTaskPage() {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "模板",
|
title: "诊断模板",
|
||||||
dataIndex: "task_template_name",
|
dataIndex: "task_template_name",
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
@ -118,11 +133,33 @@ export default function VqdTaskPage() {
|
|||||||
</Space>
|
</Space>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "任务计划",
|
||||||
|
dataIndex: "time_template_name",
|
||||||
|
align: "center",
|
||||||
|
render: (text, record) => (
|
||||||
|
<Space>
|
||||||
|
{text}
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "描述",
|
title: "描述",
|
||||||
dataIndex: "des",
|
dataIndex: "des",
|
||||||
align: "center",
|
align: "center",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "启用",
|
||||||
|
dataIndex: "enable",
|
||||||
|
align: "center",
|
||||||
|
render: (text, record) => (
|
||||||
|
<Space>
|
||||||
|
<Switch value={text} defaultChecked onChange={(t) => {
|
||||||
|
saveTemplate(record, t)
|
||||||
|
}} />
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "创建日期",
|
title: "创建日期",
|
||||||
dataIndex: "created_at",
|
dataIndex: "created_at",
|
||||||
@ -136,7 +173,7 @@ export default function VqdTaskPage() {
|
|||||||
fixed: "right",
|
fixed: "right",
|
||||||
render: (_, record) => (
|
render: (_, record) => (
|
||||||
<Space>
|
<Space>
|
||||||
|
|
||||||
<Tooltip placement="top" title="编辑" color="#fff">
|
<Tooltip placement="top" title="编辑" color="#fff">
|
||||||
<Button icon={<EditOutlined />} onClick={() => handleEdit(record)} />
|
<Button icon={<EditOutlined />} onClick={() => handleEdit(record)} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@ -166,7 +203,7 @@ export default function VqdTaskPage() {
|
|||||||
<Flex justify="space-between" align="center" className="mb-4">
|
<Flex justify="space-between" align="center" className="mb-4">
|
||||||
<Space>
|
<Space>
|
||||||
<Button type="primary" icon={<PlusOutlined />} onClick={handleAdd}>
|
<Button type="primary" icon={<PlusOutlined />} onClick={handleAdd}>
|
||||||
新增任务
|
新增诊断任务
|
||||||
</Button>
|
</Button>
|
||||||
{/* <Popconfirm
|
{/* <Popconfirm
|
||||||
title="确定要批量删除文件吗?"
|
title="确定要批量删除文件吗?"
|
||||||
@ -213,7 +250,7 @@ export default function VqdTaskPage() {
|
|||||||
{/* 编辑模态框 */}
|
{/* 编辑模态框 */}
|
||||||
<AddVqdTask
|
<AddVqdTask
|
||||||
ref={dialogRef}
|
ref={dialogRef}
|
||||||
title="编辑"
|
title="添加/编辑诊断任务"
|
||||||
onSuccess={() => refetch()}
|
onSuccess={() => refetch()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -64,11 +64,6 @@ export default function VqdTaskTemplatePage() {
|
|||||||
const handleEdit = (disk: VqdTaskTemplateItem) => {
|
const handleEdit = (disk: VqdTaskTemplateItem) => {
|
||||||
dialogRef.current?.open(disk);
|
dialogRef.current?.open(disk);
|
||||||
};
|
};
|
||||||
const saveTemplate = (disk: VqdTaskTemplateItem, t: boolean) => {
|
|
||||||
const payload = disk as CreateVqdTaskTemplateReq;
|
|
||||||
payload.enable = t
|
|
||||||
updateMutate({ id: String(disk.id), ...payload })
|
|
||||||
};
|
|
||||||
|
|
||||||
// 处理分页变化
|
// 处理分页变化
|
||||||
const handleTableChange = (page: number, pageSize?: number) => {
|
const handleTableChange = (page: number, pageSize?: number) => {
|
||||||
@ -111,18 +106,6 @@ export default function VqdTaskTemplatePage() {
|
|||||||
dataIndex: "name",
|
dataIndex: "name",
|
||||||
align: "center",
|
align: "center",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: "启用",
|
|
||||||
dataIndex: "enable",
|
|
||||||
align: "center",
|
|
||||||
render: (text, record) => (
|
|
||||||
<Space>
|
|
||||||
<Switch value={text} defaultChecked onChange={(t) => {
|
|
||||||
saveTemplate(record, t)
|
|
||||||
}} />
|
|
||||||
</Space>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: "诊断模块",
|
title: "诊断模块",
|
||||||
align: "center",
|
align: "center",
|
||||||
|
|||||||
234
web/src/components/VqdTimeTemplate.tsx
Normal file
234
web/src/components/VqdTimeTemplate.tsx
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
import { useRef, useState, useMemo } from "react";
|
||||||
|
import { Table, Button, Space, Popconfirm, Flex, message, Tooltip, Switch, Tag } from "antd";
|
||||||
|
import { EditOutlined, DeleteOutlined, PlusOutlined } from "@ant-design/icons";
|
||||||
|
import { useQuery, useMutation } from "@tanstack/react-query";
|
||||||
|
import { GetVqdTimeTemplate, DeleteVqdTimeTemplate, UpdateVqdTimeTemplate } from "../api/vqdtimetemplate";
|
||||||
|
import type { VqdTimeTemplateItem, CreateVqdTimeTemplateReq } from "../types/vqdtimetemplate";
|
||||||
|
import type { ColumnsType } from "antd/es/table";
|
||||||
|
import AddVqdTimeTemplate, { AddVqdTimeTemplateRef } from "./AddVqdTimeTemplate";
|
||||||
|
import { useGlobal } from "../Context";
|
||||||
|
import { FormatFileSizeToString } from "../utils/rate";
|
||||||
|
import { formatSecondsToHMS } from "../utils/time";
|
||||||
|
import Filter from "./Filter";
|
||||||
|
export default function VqdTimeTemplatePage() {
|
||||||
|
const { ErrorHandle } = useGlobal();
|
||||||
|
const dialogRef = useRef<AddVqdTimeTemplateRef>(null);
|
||||||
|
const [pagination, setPagination] = useState({
|
||||||
|
page: 1,
|
||||||
|
size: 10,
|
||||||
|
name: ""
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取任务列表
|
||||||
|
const {
|
||||||
|
data: storageResponse,
|
||||||
|
isLoading,
|
||||||
|
refetch,
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ["storage", pagination],
|
||||||
|
queryFn: () =>
|
||||||
|
GetVqdTimeTemplate({ ...pagination })
|
||||||
|
.then((res) => res.data)
|
||||||
|
.catch((err) => {
|
||||||
|
ErrorHandle(err);
|
||||||
|
throw err;
|
||||||
|
}),
|
||||||
|
// refetchInterval: 4000,
|
||||||
|
retry: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 删除任务
|
||||||
|
const [delLoadings, setDelLoadings] = useState<number[]>([]);
|
||||||
|
const { mutate: deleteMutation } = useMutation({
|
||||||
|
mutationFn: DeleteVqdTimeTemplate,
|
||||||
|
onMutate: (id: number) => {
|
||||||
|
setDelLoadings((prev) => [...prev, id]);
|
||||||
|
},
|
||||||
|
onSuccess: (_, ctx) => {
|
||||||
|
setDelLoadings((prev) => prev.filter((item) => item !== ctx));
|
||||||
|
message.success("删除成功");
|
||||||
|
refetch();
|
||||||
|
},
|
||||||
|
onError: (error: Error, ctx) => {
|
||||||
|
setDelLoadings((prev) => prev.filter((item) => item !== ctx));
|
||||||
|
ErrorHandle(error);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 打开新增模态框
|
||||||
|
const handleAdd = () => {
|
||||||
|
dialogRef.current?.open();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 打开编辑模态框
|
||||||
|
const handleEdit = (disk: VqdTimeTemplateItem) => {
|
||||||
|
dialogRef.current?.open(disk);
|
||||||
|
};
|
||||||
|
const saveTemplate = (disk: VqdTimeTemplateItem, t: boolean) => {
|
||||||
|
const payload = disk as CreateVqdTimeTemplateReq;
|
||||||
|
payload.enable = t
|
||||||
|
updateMutate({ id: String(disk.id), ...payload })
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理分页变化
|
||||||
|
const handleTableChange = (page: number, pageSize?: number) => {
|
||||||
|
setPagination((prev) => ({
|
||||||
|
...prev,
|
||||||
|
page: page,
|
||||||
|
size: pageSize || prev.size,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
// 客户端分页数据
|
||||||
|
const dataSource = useMemo(() => {
|
||||||
|
const items = storageResponse?.items || [];
|
||||||
|
const start = (pagination.page - 1) * pagination.size;
|
||||||
|
const end = start + pagination.size;
|
||||||
|
return items.slice(start, end);
|
||||||
|
}, [storageResponse, pagination]);
|
||||||
|
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
||||||
|
const rowSelection = {
|
||||||
|
selectedRowKeys,
|
||||||
|
onChange: (
|
||||||
|
newSelectedRowKeys: React.Key[],
|
||||||
|
selectedRows: VqdTimeTemplateItem[]
|
||||||
|
) => {
|
||||||
|
setSelectedRowKeys([...newSelectedRowKeys]);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const { mutate: updateMutate } = useMutation({
|
||||||
|
mutationFn: UpdateVqdTimeTemplate,
|
||||||
|
onSuccess: () => {
|
||||||
|
message.success("更新成功");
|
||||||
|
setTimeout(() => {
|
||||||
|
refetch()
|
||||||
|
}, 500);
|
||||||
|
},
|
||||||
|
onError: ErrorHandle,
|
||||||
|
});
|
||||||
|
// 表格列定义
|
||||||
|
const columns: ColumnsType<VqdTimeTemplateItem> = [
|
||||||
|
{
|
||||||
|
title: "名称",
|
||||||
|
dataIndex: "name",
|
||||||
|
align: "center",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "启用",
|
||||||
|
dataIndex: "enable",
|
||||||
|
align: "center",
|
||||||
|
render: (text, record) => (
|
||||||
|
<Space>
|
||||||
|
<Switch value={text} defaultChecked onChange={(t) => {
|
||||||
|
saveTemplate(record, t)
|
||||||
|
}} />
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "描述",
|
||||||
|
dataIndex: "des",
|
||||||
|
align: "center",
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: "日期",
|
||||||
|
// dataIndex: "created_at",
|
||||||
|
// align: "center",
|
||||||
|
// render: (text: string, record) => (
|
||||||
|
// <>
|
||||||
|
// <div>创建:{(text ? new Date(text).toLocaleString() : "-")}</div>
|
||||||
|
// 更新:{(record?.updated_at ? new Date(record?.updated_at).toLocaleString() : "-")}
|
||||||
|
// </>
|
||||||
|
// ),
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: "操作",
|
||||||
|
align: "center",
|
||||||
|
width: 120,
|
||||||
|
fixed: "right",
|
||||||
|
render: (_, record) => (
|
||||||
|
<Space>
|
||||||
|
|
||||||
|
<Tooltip placement="top" title="编辑" color="#fff">
|
||||||
|
<Button icon={<EditOutlined />} onClick={() => handleEdit(record)} />
|
||||||
|
</Tooltip>
|
||||||
|
{!record.is_default && <Popconfirm
|
||||||
|
title="确定要删除这个模板吗?"
|
||||||
|
onConfirm={() => {
|
||||||
|
if (record.id) {
|
||||||
|
deleteMutation(record.id);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
okText="确定"
|
||||||
|
cancelText="取消"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
loading={delLoadings.includes(record.id)}
|
||||||
|
danger
|
||||||
|
icon={<DeleteOutlined />}
|
||||||
|
/>
|
||||||
|
</Popconfirm>}
|
||||||
|
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Flex justify="space-between" align="center" className="mb-4">
|
||||||
|
<Space>
|
||||||
|
<Button type="primary" icon={<PlusOutlined />} onClick={handleAdd}>
|
||||||
|
新增计划
|
||||||
|
</Button>
|
||||||
|
{/* <Popconfirm
|
||||||
|
title="确定要批量删除文件吗?"
|
||||||
|
onConfirm={() => {
|
||||||
|
|
||||||
|
}}
|
||||||
|
okText="确定"
|
||||||
|
cancelText="取消"
|
||||||
|
>
|
||||||
|
<Button color="danger" variant="solid">
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
|
</Popconfirm> */}
|
||||||
|
|
||||||
|
</Space>
|
||||||
|
|
||||||
|
<Filter
|
||||||
|
searchLoading={isLoading}
|
||||||
|
onSearchChange={(value: string) => {
|
||||||
|
setPagination({ ...pagination, name: value });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
{/* 表格 */}
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
// rowSelection={rowSelection}
|
||||||
|
dataSource={storageResponse?.items}
|
||||||
|
rowKey="id"
|
||||||
|
loading={isLoading}
|
||||||
|
scroll={{ x: "max-content" }}
|
||||||
|
pagination={{
|
||||||
|
current: pagination.page,
|
||||||
|
pageSize: pagination.size,
|
||||||
|
total: storageResponse?.total || 0,
|
||||||
|
showSizeChanger: true,
|
||||||
|
showQuickJumper: true,
|
||||||
|
showTotal: (total) => `共 ${total} 条`,
|
||||||
|
onChange: handleTableChange,
|
||||||
|
onShowSizeChange: handleTableChange,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 编辑模态框 */}
|
||||||
|
<AddVqdTimeTemplate
|
||||||
|
ref={dialogRef}
|
||||||
|
title="添加/编辑模板"
|
||||||
|
onSuccess={() => refetch()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -2,13 +2,15 @@ import { Affix, Col, Menu, Row, type MenuProps } from "antd";
|
|||||||
import {
|
import {
|
||||||
FileSearchOutlined,
|
FileSearchOutlined,
|
||||||
AlertOutlined,
|
AlertOutlined,
|
||||||
FileTextOutlined,
|
CarryOutOutlined,
|
||||||
SettingOutlined
|
SettingOutlined,
|
||||||
|
FileProtectOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import Box from "../components/Box";
|
import Box from "../components/Box";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import VqdTaskPage from "../components/VqdTask";
|
import VqdTaskPage from "../components/VqdTask";
|
||||||
import VqdTaskTemplatePage from "../components/VqdTaskTemplate";
|
import VqdTaskTemplatePage from "../components/VqdTaskTemplate";
|
||||||
|
import VqdTimeTemplatePage from "../components/VqdTimeTemplate";
|
||||||
import VqdAlarmPage from "../components/VqdAlarm";
|
import VqdAlarmPage from "../components/VqdAlarm";
|
||||||
import VqdConfigPage from "../components/VqdConfig";
|
import VqdConfigPage from "../components/VqdConfig";
|
||||||
|
|
||||||
@ -19,21 +21,26 @@ export default function Home() {
|
|||||||
const items: MenuItem[] = [
|
const items: MenuItem[] = [
|
||||||
{
|
{
|
||||||
key: "sub0",
|
key: "sub0",
|
||||||
label: "任务管理",
|
label: "设备视频诊断",
|
||||||
icon: <FileSearchOutlined />,
|
icon: <FileSearchOutlined />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "sub1",
|
key: "sub1",
|
||||||
label: "任务模板",
|
label: "诊断结果查询",
|
||||||
icon: <FileTextOutlined />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "sub2",
|
|
||||||
label: "诊断告警",
|
|
||||||
icon: <AlertOutlined />,
|
icon: <AlertOutlined />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: "sub2",
|
||||||
|
label: "诊断计划",
|
||||||
|
icon: <CarryOutOutlined />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: "sub3",
|
key: "sub3",
|
||||||
|
label: "诊断参数",
|
||||||
|
icon: <FileProtectOutlined />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "sub4",
|
||||||
label: "基础配置",
|
label: "基础配置",
|
||||||
icon: <SettingOutlined />,
|
icon: <SettingOutlined />,
|
||||||
},
|
},
|
||||||
@ -82,15 +89,20 @@ export default function Home() {
|
|||||||
)}
|
)}
|
||||||
{currentMenu == "sub1" && (
|
{currentMenu == "sub1" && (
|
||||||
<Box>
|
<Box>
|
||||||
<VqdTaskTemplatePage />
|
<VqdAlarmPage />
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
{currentMenu == "sub2" && (
|
{currentMenu == "sub2" && (
|
||||||
<Box>
|
<Box>
|
||||||
<VqdAlarmPage />
|
<VqdTimeTemplatePage />
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
{currentMenu == "sub3" && (
|
{currentMenu == "sub3" && (
|
||||||
|
<Box>
|
||||||
|
<VqdTaskTemplatePage />
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
{currentMenu == "sub4" && (
|
||||||
<Box>
|
<Box>
|
||||||
<VqdConfigPage />
|
<VqdConfigPage />
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@ -27,7 +27,9 @@ export type VqdTaskItem = {
|
|||||||
channel_id: string;
|
channel_id: string;
|
||||||
channel_name: string;
|
channel_name: string;
|
||||||
task_template_id: number;
|
task_template_id: number;
|
||||||
|
time_template_id: number;
|
||||||
task_template_name: string;
|
task_template_name: string;
|
||||||
|
time_template_name: string;
|
||||||
enable: boolean;
|
enable: boolean;
|
||||||
created_at?: string;
|
created_at?: string;
|
||||||
updated_at?: string;
|
updated_at?: string;
|
||||||
@ -70,9 +72,9 @@ export type CreateVqdTaskReq = {
|
|||||||
*/
|
*/
|
||||||
task_template_id: number;
|
task_template_id: number;
|
||||||
/**
|
/**
|
||||||
* 模板名称
|
* 关联计划
|
||||||
*/
|
*/
|
||||||
task_template_name: string;
|
time_template_id: number;
|
||||||
/**
|
/**
|
||||||
* 启用
|
* 启用
|
||||||
*/
|
*/
|
||||||
@ -99,12 +101,14 @@ export type UpdateVqdTaskReq = Partial<CreateVqdTaskReq> & {
|
|||||||
export type VqdTaskDetailRes = {
|
export type VqdTaskDetailRes = {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
size: number;
|
channel_id: string;
|
||||||
mode: string;
|
channel_name: string;
|
||||||
encode_status: number;
|
task_template_id: number;
|
||||||
file_name: string;
|
time_template_id: number;
|
||||||
source_url: string;
|
task_template_name: string;
|
||||||
|
time_template_name: string;
|
||||||
|
enable: boolean;
|
||||||
created_at?: string;
|
created_at?: string;
|
||||||
updated_at?: string;
|
updated_at?: string;
|
||||||
des?: string;
|
des: string;
|
||||||
}
|
}
|
||||||
@ -24,8 +24,6 @@ export type VqdTaskTemplateRes = {
|
|||||||
export type VqdTaskTemplateItem = {
|
export type VqdTaskTemplateItem = {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
plans: string;
|
|
||||||
enable: boolean;
|
|
||||||
is_default: boolean;
|
is_default: boolean;
|
||||||
vqd_config: VqdConfig;
|
vqd_config: VqdConfig;
|
||||||
vqd_lgt_dark: VqdLgtDark;
|
vqd_lgt_dark: VqdLgtDark;
|
||||||
@ -131,14 +129,6 @@ export type CreateVqdTaskTemplateReq = {
|
|||||||
* 名称
|
* 名称
|
||||||
*/
|
*/
|
||||||
name: string;
|
name: string;
|
||||||
/**
|
|
||||||
* 计划
|
|
||||||
*/
|
|
||||||
plans: string;
|
|
||||||
/**
|
|
||||||
* 启用
|
|
||||||
*/
|
|
||||||
enable: boolean;
|
|
||||||
vqd_config: VqdConfig;
|
vqd_config: VqdConfig;
|
||||||
vqd_lgt_dark: VqdLgtDark;
|
vqd_lgt_dark: VqdLgtDark;
|
||||||
vqd_blue: VqdBlue;
|
vqd_blue: VqdBlue;
|
||||||
@ -173,8 +163,6 @@ export type UpdateVqdTaskTemplateReq = Partial<CreateVqdTaskTemplateReq> & {
|
|||||||
export type VqdTaskTemplateDetailRes = {
|
export type VqdTaskTemplateDetailRes = {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
plans: string;
|
|
||||||
enable: boolean;
|
|
||||||
is_default: boolean;
|
is_default: boolean;
|
||||||
vqd_config: VqdConfig;
|
vqd_config: VqdConfig;
|
||||||
vqd_lgt_dark: VqdLgtDark;
|
vqd_lgt_dark: VqdLgtDark;
|
||||||
|
|||||||
95
web/src/types/vqdtimetemplate.ts
Normal file
95
web/src/types/vqdtimetemplate.ts
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* 基础
|
||||||
|
*/
|
||||||
|
export type VqdTimeTemplateBaseRes = {
|
||||||
|
data: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询列表响应
|
||||||
|
*/
|
||||||
|
export type VqdTimeTemplateRes = {
|
||||||
|
items: VqdTimeTemplateItem[];
|
||||||
|
/**
|
||||||
|
* 总数
|
||||||
|
*/
|
||||||
|
total: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项
|
||||||
|
*/
|
||||||
|
export type VqdTimeTemplateItem = {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
plans: string;
|
||||||
|
enable: boolean;
|
||||||
|
is_default: boolean;
|
||||||
|
created_at?: string;
|
||||||
|
updated_at?: string;
|
||||||
|
des: string;
|
||||||
|
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 创建请求
|
||||||
|
*/
|
||||||
|
export type VqdTimeTemplateReq = {
|
||||||
|
/**
|
||||||
|
* 名称模糊搜索
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
/**
|
||||||
|
* 页码(1~N)
|
||||||
|
*/
|
||||||
|
page: number;
|
||||||
|
/**
|
||||||
|
* 单页元素数量(10~100)
|
||||||
|
*/
|
||||||
|
size: number;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CreateVqdTimeTemplateReq = {
|
||||||
|
/**
|
||||||
|
* 名称
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* 计划
|
||||||
|
*/
|
||||||
|
plans: string;
|
||||||
|
/**
|
||||||
|
* 启用
|
||||||
|
*/
|
||||||
|
enable: boolean;
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
des: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新请求
|
||||||
|
*/
|
||||||
|
export type UpdateVqdTimeTemplateReq = Partial<CreateVqdTimeTemplateReq> & {
|
||||||
|
/**
|
||||||
|
* ID
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 详情响应(Apifox 未提供具体结构,这里用通用对象)
|
||||||
|
*/
|
||||||
|
export type VqdTimeTemplateDetailRes = {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
plans: string;
|
||||||
|
enable: boolean;
|
||||||
|
is_default: boolean;
|
||||||
|
created_at?: string;
|
||||||
|
updated_at?: string;
|
||||||
|
des: string;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user