添加诊断
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/core/host"
|
||||
"easyvqd/internal/core/media"
|
||||
"easyvqd/internal/core/vqdsdk"
|
||||
"easyvqd/internal/core/vqdtask"
|
||||
"easyvqd/internal/data"
|
||||
"easyvqd/internal/web/api"
|
||||
"log/slog"
|
||||
@ -30,7 +30,7 @@ func WireApp(bc *conf.Bootstrap, log *slog.Logger) (http.Handler, func(), error)
|
||||
vqdTaskCore := api.NewVqdTaskCore(db)
|
||||
hostCore := host.NewCore(bc)
|
||||
mediaCore := media.NewCore(hostCore)
|
||||
vqdSdkCore := vqdsdk.NewCore(hostCore, vqdTaskCore, bc)
|
||||
vqdSdkCore := vqdtask.NewCore(hostCore, vqdTaskCore, bc)
|
||||
vqdTaskAPI := api.NewVqdTaskAPI(vqdTaskCore, mediaCore,vqdSdkCore,hostCore, bc)
|
||||
|
||||
usecase := &api.Usecase{
|
||||
@ -45,6 +45,6 @@ func WireApp(bc *conf.Bootstrap, log *slog.Logger) (http.Handler, func(), error)
|
||||
}
|
||||
handler := api.NewHTTPHandler(usecase)
|
||||
return handler, func() {
|
||||
//mediaCore.Close()
|
||||
vqdSdkCore.UnVqdTask()
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package host
|
||||
|
||||
import (
|
||||
"context"
|
||||
"easyvqd/internal/conf"
|
||||
"easyvqd/pkg/pluginheart"
|
||||
"encoding/json"
|
||||
@ -12,10 +11,12 @@ import (
|
||||
"git.lnton.com/lnton/pluginsdk/pkg/plugin"
|
||||
)
|
||||
|
||||
type IFrameResultCB func(string, []byte, int)
|
||||
type Core struct {
|
||||
Plugin *plugin.PluginSDK // 用于业务GRPC通信
|
||||
HttpPlugin *pluginheart.Engine // 用于插件管理HTTP通信
|
||||
RtspConfig *ConfigBaseOutput
|
||||
CbIFrame IFrameResultCB
|
||||
}
|
||||
|
||||
var StartOk chan struct{}
|
||||
@ -45,29 +46,33 @@ func NewCore(cfg *conf.Bootstrap) *Core {
|
||||
}, false)
|
||||
}()
|
||||
|
||||
c := &Core{
|
||||
core := &Core{
|
||||
Plugin: sdk,
|
||||
HttpPlugin: engine,
|
||||
}
|
||||
|
||||
sdk.AddResponseHandler("stop", c.stop)
|
||||
sdk.AddResponseHandler("ping", c.ping)
|
||||
sdk.AddResponseHandler("stop", core.stop)
|
||||
sdk.AddResponseHandler("ping", core.ping)
|
||||
|
||||
// 这部分都是收到响应后的回调
|
||||
sdk.AddResponseHandler("findDevices", c.findDevicesRespH)
|
||||
sdk.AddResponseHandler("findChannels", c.findChannelsRespH)
|
||||
sdk.AddResponseHandler("getBaseConfig", c.getBaseConfigRespH)
|
||||
sdk.AddResponseHandler("findTalkUrl", c.findTalkUrlRespH)
|
||||
|
||||
config, err := c.GetBaseConfig(context.TODO(), &ConfigBaseInput{Mode: "rtsp"})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
sdk.AddResponseHandler("findDevices", core.findDevicesRespH)
|
||||
sdk.AddResponseHandler("findChannels", core.findChannelsRespH)
|
||||
sdk.AddResponseHandler("getBaseConfig", core.getBaseConfigRespH)
|
||||
sdk.AddResponseHandler("findTalkUrl", core.findTalkUrlRespH)
|
||||
sdk.AddResponseHandler("iframeData", core.iframeDataRespH)
|
||||
// 响应主机下发的 "iframeData" 命令
|
||||
sdk.AddRequestHandler("iframeData", core.iframeDataReqH)
|
||||
// defer sdk.Close()
|
||||
return &Core{
|
||||
Plugin: sdk,
|
||||
RtspConfig: config,
|
||||
return core
|
||||
}
|
||||
|
||||
func (c *Core) iframeDataReqH(requestID string, args json.RawMessage) (interface{}, error) {
|
||||
//slog.Debug("Received 'iframeData' from host", "request_id", requestID, "args", args)
|
||||
out := IframeOutput{}
|
||||
if err := json.Unmarshal(args, &out); err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
c.CbIFrame(out.StreamName, out.Data, out.Codes)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (c Core) stop(requestID string, args json.RawMessage) (interface{}, error) {
|
||||
@ -76,6 +81,7 @@ func (c Core) stop(requestID string, args json.RawMessage) (interface{}, error)
|
||||
}
|
||||
|
||||
func (c Core) ping(requestID string, args json.RawMessage) (interface{}, error) {
|
||||
slog.Debug("Received 'ping' from host", "request_id", requestID, "args", args)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@ -96,3 +102,7 @@ func (c Core) findTalkUrlRespH(requestID string, args json.RawMessage) (interfac
|
||||
slog.Debug("Received 'findTalkUrl' from host", "request_id", requestID, "args", args)
|
||||
return nil, nil
|
||||
}
|
||||
func (c Core) iframeDataRespH(requestID string, args json.RawMessage) (interface{}, error) {
|
||||
slog.Debug("Received 'iframeData' from host", "request_id", requestID, "args", args)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
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
|
||||
VqdAlarm() VqdAlarmStorer
|
||||
VqdTaskTemplate() VqdTaskTemplateStorer
|
||||
VqdTimeTemplate() VqdTimeTemplateStorer
|
||||
}
|
||||
|
||||
// Core
|
||||
|
||||
@ -18,13 +18,13 @@ const (
|
||||
|
||||
type VqdTask struct {
|
||||
orm.Model
|
||||
Name string `gorm:"column:name;notNull;default:'';comment:名称" json:"name"` // 名称
|
||||
ChannelID string `gorm:"column:channel_id;notNull;default:'';comment:关联通道" json:"channel_id"` // 关联通道
|
||||
ChannelName string `gorm:"column:channel_name;notNull;default:'';comment:关联通道名称" json:"channel_name"` // 关联通道名称
|
||||
TaskTemplateID int64 `gorm:"column:task_template_id;notNull;default:0;comment:关联模板" json:"task_template_id"` //关联模板
|
||||
TaskTemplateName string `gorm:"column:task_template_name;notNull;default:0;comment:关联模板名称" json:"task_template_name"` //关联模板名称
|
||||
Enable bool `gorm:"column:enable;notNull;default:FALSE;comment:启用" json:"enable"` // 启用
|
||||
Des string `gorm:"column:des;notNull;default:'';comment:描述" json:"des"` // 描述
|
||||
Name string `gorm:"column:name;notNull;default:'';comment:名称" json:"name"` // 名称
|
||||
ChannelID string `gorm:"column:channel_id;notNull;default:'';comment:关联通道" json:"channel_id"` // 关联通道
|
||||
ChannelName string `gorm:"column:channel_name;notNull;default:'';comment:关联通道名称" json:"channel_name"` // 关联通道名称
|
||||
TaskTemplateID int64 `gorm:"column:task_template_id;notNull;default:0;comment:关联模板" json:"task_template_id"` // 关联模板
|
||||
TimeTemplateID int64 `gorm:"column:time_template_id;notNull;default:0;comment:关联计划" json:"time_template_id"` // 关联计划
|
||||
Enable bool `gorm:"column:enable;notNull;default:FALSE;comment:启用" json:"enable"` // 启用
|
||||
Des string `gorm:"column:des;notNull;default:'';comment:描述" json:"des"` // 描述
|
||||
}
|
||||
|
||||
// TableName database table name
|
||||
@ -217,8 +217,6 @@ func (i *VqdFlower) Scan(input interface{}) error {
|
||||
type VqdTaskTemplate struct {
|
||||
orm.Model
|
||||
Name string `gorm:"column:name;notNull;default:'';comment:名称" json:"name"`
|
||||
Plans string `gorm:"column:plans;notNull;default:'';comment:计划" json:"plans"`
|
||||
Enable bool `gorm:"column:enable;notNull;default:TRUE;comment:是否启用" json:"enable"`
|
||||
IsDefault bool `gorm:"column:is_default;notNull;default:FALSE;comment:是否默认" json:"is_default"`
|
||||
VqdConfig VqdConfig `gorm:"column:vqd_config;type:jsonb;notNull;default:'{}';comment:诊断基础配置" json:"vqd_config"` // 诊断基础配置
|
||||
VqdLgtDark VqdLgtDark `gorm:"column:vqd_lgt_dark;type:jsonb;notNull;default:'{}';comment:亮度检测" json:"vqd_lgt_dark"` // 亮度检测
|
||||
@ -240,6 +238,20 @@ func (*VqdTaskTemplate) TableName() string {
|
||||
return "vqd_task_template"
|
||||
}
|
||||
|
||||
type VqdTimeTemplate struct {
|
||||
orm.Model
|
||||
Name string `gorm:"column:name;notNull;default:'';comment:名称" json:"name"`
|
||||
Plans string `gorm:"column:plans;notNull;default:'';comment:计划" json:"plans"`
|
||||
Enable bool `gorm:"column:enable;notNull;default:TRUE;comment:是否启用" json:"enable"`
|
||||
IsDefault bool `gorm:"column:is_default;notNull;default:FALSE;comment:是否默认" json:"is_default"`
|
||||
Des string `gorm:"column:des;notNull;default:'';comment:描述" json:"des"` // 描述
|
||||
}
|
||||
|
||||
// TableName database table name
|
||||
func (*VqdTimeTemplate) TableName() string {
|
||||
return "vqd_time_template"
|
||||
}
|
||||
|
||||
type VqdAlarm struct {
|
||||
orm.Model
|
||||
AlarmName string `gorm:"column:alarm_name;notNull;default:'';comment:告警名称" json:"alarm_name"` // 告警名称
|
||||
|
||||
@ -24,6 +24,9 @@ func (d DB) VqdTask() vqd.VqdTaskStorer {
|
||||
func (d DB) VqdTaskTemplate() vqd.VqdTaskTemplateStorer {
|
||||
return VqdTaskTemplate(d)
|
||||
}
|
||||
func (d DB) VqdTimeTemplate() vqd.VqdTimeTemplateStorer {
|
||||
return VqdTimeTemplate(d)
|
||||
}
|
||||
func (d DB) VqdAlarm() vqd.VqdAlarmStorer {
|
||||
return VqdAlarm(d)
|
||||
}
|
||||
@ -36,6 +39,7 @@ func (d DB) AutoMigrate(ok bool) DB {
|
||||
if err := d.db.AutoMigrate(
|
||||
new(vqd.VqdTask),
|
||||
new(vqd.VqdTaskTemplate),
|
||||
new(vqd.VqdTimeTemplate),
|
||||
new(vqd.VqdAlarm),
|
||||
); err != nil {
|
||||
panic(err)
|
||||
|
||||
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 {
|
||||
Name string `json:"name"` // 名称
|
||||
ChannelID string `json:"channel_id"` // 关联通道
|
||||
ChannelName string `json:"channel_name"` // 通道名称
|
||||
TaskTemplateID int `json:"task_template_id"` // 关联模板
|
||||
TaskTemplateName string `json:"task_template_name"` // 模板名称
|
||||
Enable bool `form:"enable"` // 启用
|
||||
Des string `json:"des"` // 描述
|
||||
Name string `json:"name"` // 名称
|
||||
ChannelID string `json:"channel_id"` // 关联通道
|
||||
ChannelName string `json:"channel_name"` // 通道名称
|
||||
TaskTemplateID int `json:"task_template_id"` // 关联模板
|
||||
TimeTemplateID int `json:"time_template_id"` // 关联计划
|
||||
Enable bool `form:"enable"` // 启用
|
||||
Des string `json:"des"` // 描述
|
||||
}
|
||||
|
||||
type AddVqdTaskInput struct {
|
||||
Name string `json:"name"` // 名称
|
||||
ChannelID string `json:"channel_id"` // 关联通道
|
||||
ChannelName string `json:"channel_name"` // 通道名称
|
||||
TaskTemplateID int `json:"task_template_id"` // 关联模板
|
||||
TaskTemplateName string `json:"task_template_name"` // 模板名称
|
||||
Enable bool `form:"enable"` // 启用
|
||||
Des string `json:"des"` // 描述
|
||||
Name string `json:"name"` // 名称
|
||||
ChannelID string `json:"channel_id"` // 关联通道
|
||||
ChannelName string `json:"channel_name"` // 通道名称
|
||||
TaskTemplateID int `json:"task_template_id"` // 关联模板
|
||||
TimeTemplateID int `json:"time_template_id"` // 关联计划
|
||||
Enable bool `form:"enable"` // 启用
|
||||
Des string `json:"des"` // 描述
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ func (c Core) GetNameVqdTaskTemplate(ctx context.Context, name string) (*VqdTask
|
||||
}
|
||||
|
||||
// FirstOrCreateTemplate Insert into database
|
||||
func (c Core) FirstOrCreateTemplate(b any) error {
|
||||
func (c Core) FirstOrCreateTaskTemplate(b any) error {
|
||||
return c.store.VqdTaskTemplate().FirstOrCreate(b)
|
||||
}
|
||||
|
||||
|
||||
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 (
|
||||
"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 {
|
||||
cfg := uc.Conf
|
||||
in := vqd.VqdTaskTemplate{
|
||||
inPlan := vqd.VqdTimeTemplate{
|
||||
Enable: true,
|
||||
IsDefault: true,
|
||||
}
|
||||
inTemplate := vqd.VqdTaskTemplate{
|
||||
|
||||
Name: "默认",
|
||||
Des: "默认诊断模板。",
|
||||
IsDefault: true,
|
||||
VqdConfig: vqd.VqdConfig{
|
||||
Enable: true,
|
||||
FrmNum: cfg.VqdConfig.FrmNum,
|
||||
@ -230,32 +236,37 @@ func InitTemplate(uc *Usecase) error {
|
||||
MosaicThr: cfg.VqdFlower.MosaicThr,
|
||||
},
|
||||
}
|
||||
|
||||
in.Name = "每天"
|
||||
in.Model.ID = 1
|
||||
in.Model.CreatedAt = orm.Time{Time: time.Now()}
|
||||
in.Plans = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
|
||||
in.Des = "每天分析,启用全部分析模块。"
|
||||
if err := uc.VqdTaskCore.FirstOrCreateTemplate(&in); err != nil {
|
||||
slog.Error("FirstOrCreateTemplate", "err", err)
|
||||
inTemplate.ID = 1
|
||||
inTemplate.Model.CreatedAt = orm.Time{Time: time.Now()}
|
||||
if err := uc.VqdTaskCore.FirstOrCreateTaskTemplate(&inTemplate); err != nil {
|
||||
slog.Error("FirstOrCreateTaskTemplate", "err", err)
|
||||
return err
|
||||
}
|
||||
in.Name = "工作日"
|
||||
in.Model.ID = 2
|
||||
in.Model.CreatedAt = orm.Time{Time: time.Now()}
|
||||
in.Plans = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000"
|
||||
in.Des = "工作日分析,启用全部分析模块。"
|
||||
if err := uc.VqdTaskCore.FirstOrCreateTemplate(&in); err != nil {
|
||||
slog.Error("FirstOrCreateTemplate", "err", err)
|
||||
inPlan.Name = "每天"
|
||||
inPlan.Model.ID = 1
|
||||
inPlan.Model.CreatedAt = orm.Time{Time: time.Now()}
|
||||
inPlan.Plans = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
|
||||
inPlan.Des = "每天分析"
|
||||
if err := uc.VqdTaskCore.FirstOrCreateTimeTemplate(&inPlan); err != nil {
|
||||
slog.Error("FirstOrCreateTimeTemplate", "err", err)
|
||||
return err
|
||||
}
|
||||
in.Name = "双休日"
|
||||
in.Model.ID = 3
|
||||
in.Model.CreatedAt = orm.Time{Time: time.Now()}
|
||||
in.Plans = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111"
|
||||
in.Des = "休息日分析,启用全部分析模块。"
|
||||
if err := uc.VqdTaskCore.FirstOrCreateTemplate(&in); err != nil {
|
||||
slog.Error("FirstOrCreateTemplate", "err", err)
|
||||
inPlan.Name = "工作日"
|
||||
inPlan.Model.ID = 2
|
||||
inPlan.Model.CreatedAt = orm.Time{Time: time.Now()}
|
||||
inPlan.Plans = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000"
|
||||
inPlan.Des = "工作日分析"
|
||||
if err := uc.VqdTaskCore.FirstOrCreateTimeTemplate(&inPlan); err != nil {
|
||||
slog.Error("FirstOrCreateTimeTemplate", "err", err)
|
||||
return err
|
||||
}
|
||||
inPlan.Name = "双休日"
|
||||
inPlan.Model.ID = 3
|
||||
inPlan.Model.CreatedAt = orm.Time{Time: time.Now()}
|
||||
inPlan.Plans = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111"
|
||||
inPlan.Des = "休息日分析"
|
||||
if err := uc.VqdTaskCore.FirstOrCreateTimeTemplate(&inPlan); err != nil {
|
||||
slog.Error("FirstOrCreateTimeTemplate", "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
@ -5,7 +5,7 @@ import (
|
||||
"easyvqd/internal/core/media"
|
||||
"easyvqd/internal/core/vqd"
|
||||
"easyvqd/internal/core/vqd/store/audioencodedb"
|
||||
"easyvqd/internal/core/vqdsdk"
|
||||
"easyvqd/internal/core/vqdtask"
|
||||
"net/http"
|
||||
|
||||
"easyvqd/domain/uniqueid"
|
||||
@ -41,7 +41,7 @@ type Usecase struct {
|
||||
VqdTaskAPI VqdTaskAPI
|
||||
HostCore *host.Core
|
||||
MediaCore *media.Core
|
||||
VqdSdkCore *vqdsdk.Core
|
||||
VqdSdkCore *vqdtask.Core
|
||||
}
|
||||
|
||||
// NewHTTPHandler 生成Gin框架路由内容
|
||||
|
||||
@ -37,7 +37,7 @@ func (a VqdTaskAPI) getVqdAlarm(c *gin.Context, _ *struct{}) (any, error) {
|
||||
ID, _ := strconv.Atoi(c.Param("id"))
|
||||
item, err := a.core.GetVqdAlarm(c.Request.Context(), ID)
|
||||
if err != nil {
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqd [%d] err [%s]`, ID, err.Error()))
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqdcms [%d] err [%s]`, ID, err.Error()))
|
||||
}
|
||||
row := make(map[string]interface{})
|
||||
|
||||
@ -61,18 +61,18 @@ func (a VqdTaskAPI) delVqdAlarm(c *gin.Context, _ *struct{}) (any, error) {
|
||||
ID, _ := strconv.Atoi(c.Param("id"))
|
||||
_, err := a.core.DelVqdAlarm(c.Request.Context(), ID)
|
||||
if err != nil {
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqd [%d] err [%s]`, ID, err.Error()))
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqdcms [%d] err [%s]`, ID, err.Error()))
|
||||
}
|
||||
|
||||
return gin.H{"data": "OK!"}, err
|
||||
}
|
||||
func (a VqdTaskAPI) delVqdAlarmAll(c *gin.Context, in *vqd.DelVqdAlarmInput) (any, error) {
|
||||
if len(in.IDs) == 0 {
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqd ids is empty`))
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqdcms ids is empty`))
|
||||
}
|
||||
_, err := a.core.DelVqdAlarmAll(c.Request.Context(), in.IDs)
|
||||
if err != nil {
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqd [%d] err [%s]`, in.IDs, err.Error()))
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqdcms [%d] err [%s]`, in.IDs, err.Error()))
|
||||
}
|
||||
return gin.H{"data": "OK!"}, err
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import (
|
||||
"easyvqd/internal/core/host"
|
||||
"easyvqd/internal/core/media"
|
||||
"easyvqd/internal/core/vqd"
|
||||
"easyvqd/internal/core/vqdsdk"
|
||||
"easyvqd/internal/core/vqdtask"
|
||||
"fmt"
|
||||
"git.lnton.com/lnton/pkg/reason"
|
||||
"github.com/gin-gonic/gin"
|
||||
@ -16,12 +16,12 @@ import (
|
||||
type VqdTaskAPI struct {
|
||||
core *vqd.Core
|
||||
meidaCore *media.Core
|
||||
vqdSdkCore *vqdsdk.Core
|
||||
vqdSdkCore *vqdtask.Core
|
||||
cfg *conf.Bootstrap
|
||||
HostCore *host.Core
|
||||
}
|
||||
|
||||
func NewVqdTaskAPI(core *vqd.Core, meidaCore *media.Core, vqdSdkCore *vqdsdk.Core, HostCore *host.Core, cfg *conf.Bootstrap) VqdTaskAPI {
|
||||
func NewVqdTaskAPI(core *vqd.Core, meidaCore *media.Core, vqdSdkCore *vqdtask.Core, HostCore *host.Core, cfg *conf.Bootstrap) VqdTaskAPI {
|
||||
return VqdTaskAPI{core: core, meidaCore: meidaCore, vqdSdkCore: vqdSdkCore, HostCore: HostCore, cfg: cfg}
|
||||
}
|
||||
|
||||
@ -42,6 +42,13 @@ func RegisterVqdTask(g gin.IRouter, api VqdTaskAPI, handler ...gin.HandlerFunc)
|
||||
groupTemplate.POST("", web.WarpH(api.addVqdTaskTemplate))
|
||||
groupTemplate.DELETE("/:id", web.WarpH(api.delVqdTaskTemplate))
|
||||
|
||||
groupTime := g.Group("/api/plan", handler...)
|
||||
groupTime.GET("", web.WarpH(api.findVqdTimeTemplate))
|
||||
groupTime.GET("/:id", web.WarpH(api.getVqdTimeTemplate))
|
||||
groupTime.PUT("/:id", web.WarpH(api.editVqdTimeTemplate))
|
||||
groupTime.POST("", web.WarpH(api.addVqdTimeTemplate))
|
||||
groupTime.DELETE("/:id", web.WarpH(api.delVqdTimeTemplate))
|
||||
|
||||
groupAlarm := g.Group("/api/alarm", handler...)
|
||||
groupAlarm.GET("", web.WarpH(api.findVqdAlarm))
|
||||
groupAlarm.GET("/:id", web.WarpH(api.getVqdAlarm))
|
||||
@ -60,14 +67,21 @@ func (a VqdTaskAPI) findVqdTask(c *gin.Context, in *vqd.FindVqdTaskInput) (any,
|
||||
row := make(map[string]interface{})
|
||||
row["name"] = item.Name
|
||||
row["id"] = item.ID
|
||||
row["enable"] = item.Enable
|
||||
row["channel_id"] = item.ChannelID
|
||||
row["channel_name"] = item.ChannelName
|
||||
row["task_template_id"] = item.TaskTemplateID
|
||||
row["task_template_name"] = item.TaskTemplateName
|
||||
row["time_template_id"] = item.TimeTemplateID
|
||||
row["task_template_name"] = ""
|
||||
row["time_template_name"] = ""
|
||||
template, errs := a.core.GetIDVqdTaskTemplate(c.Request.Context(), item.TaskTemplateID)
|
||||
if errs == nil && template != nil {
|
||||
row["task_template_name"] = template.Name
|
||||
}
|
||||
timeTemplate, errs := a.core.GetIDVqdTimeTemplate(c.Request.Context(), item.TimeTemplateID)
|
||||
if errs == nil && template != nil {
|
||||
row["time_template_name"] = timeTemplate.Name
|
||||
}
|
||||
row["created_at"] = item.CreatedAt
|
||||
row["updated_at"] = item.UpdatedAt
|
||||
|
||||
@ -80,16 +94,27 @@ func (a VqdTaskAPI) getVqdTask(c *gin.Context, _ *struct{}) (any, error) {
|
||||
ID, _ := strconv.Atoi(c.Param("id"))
|
||||
item, err := a.core.GetVqdTask(c.Request.Context(), ID)
|
||||
if err != nil {
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqd [%d] err [%s]`, ID, err.Error()))
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqdcms [%d] err [%s]`, ID, err.Error()))
|
||||
}
|
||||
row := make(map[string]interface{})
|
||||
|
||||
row["name"] = item.Name
|
||||
row["id"] = item.ID
|
||||
row["enable"] = item.Enable
|
||||
row["channel_id"] = item.ChannelID
|
||||
row["channel_name"] = item.ChannelName
|
||||
row["task_template_id"] = item.TaskTemplateID
|
||||
row["task_template_name"] = item.TaskTemplateName
|
||||
row["time_template_id"] = item.TimeTemplateID
|
||||
row["task_template_name"] = ""
|
||||
row["time_template_name"] = ""
|
||||
template, errs := a.core.GetIDVqdTaskTemplate(c.Request.Context(), item.TaskTemplateID)
|
||||
if errs == nil && template != nil {
|
||||
row["task_template_name"] = template.Name
|
||||
}
|
||||
timeTemplate, errs := a.core.GetIDVqdTimeTemplate(c.Request.Context(), item.TimeTemplateID)
|
||||
if errs == nil && template != nil {
|
||||
row["time_template_name"] = timeTemplate.Name
|
||||
}
|
||||
row["created_at"] = item.CreatedAt
|
||||
row["updated_at"] = item.UpdatedAt
|
||||
|
||||
@ -99,7 +124,7 @@ func (a VqdTaskAPI) getVqdTask(c *gin.Context, _ *struct{}) (any, error) {
|
||||
func (a VqdTaskAPI) addVqdTask(c *gin.Context, in *vqd.AddVqdTaskInput) (any, error) {
|
||||
_, err := a.core.AddVqdTask(c.Request.Context(), in)
|
||||
if err != nil {
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`add vqd err [%s]`, err.Error()))
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`add vqdcms err [%s]`, err.Error()))
|
||||
}
|
||||
|
||||
return gin.H{"data": "OK!"}, err
|
||||
@ -109,12 +134,12 @@ func (a VqdTaskAPI) editVqdTask(c *gin.Context, in *vqd.EditVqdTaskInput) (any,
|
||||
ID, _ := strconv.Atoi(c.Param("id"))
|
||||
_, err := a.core.GetVqdTask(c.Request.Context(), ID)
|
||||
if err != nil {
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqd [%d] err [%s]`, ID, err.Error()))
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqdcms [%d] err [%s]`, ID, err.Error()))
|
||||
}
|
||||
|
||||
_, err = a.core.EditVqdTask(c.Request.Context(), in, ID)
|
||||
if err != nil {
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`edit vqd err [%s]`, err.Error()))
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`edit vqdcms err [%s]`, err.Error()))
|
||||
}
|
||||
return gin.H{"data": "OK!"}, err
|
||||
}
|
||||
@ -123,7 +148,7 @@ func (a VqdTaskAPI) delVqdTask(c *gin.Context, _ *struct{}) (any, error) {
|
||||
ID, _ := strconv.Atoi(c.Param("id"))
|
||||
_, err := a.core.DelVqdTask(c.Request.Context(), ID)
|
||||
if err != nil {
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqd [%d] err [%s]`, ID, err.Error()))
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqdcms [%d] err [%s]`, ID, err.Error()))
|
||||
}
|
||||
|
||||
return gin.H{"data": "OK!"}, err
|
||||
|
||||
@ -18,8 +18,6 @@ func (a VqdTaskAPI) findVqdTaskTemplate(c *gin.Context, in *vqd.FindVqdTaskTempl
|
||||
row["id"] = item.ID
|
||||
row["name"] = item.Name
|
||||
row["des"] = item.Des
|
||||
row["plans"] = item.Plans
|
||||
row["enable"] = item.Enable
|
||||
row["is_default"] = item.IsDefault
|
||||
row["vqd_config"] = item.VqdConfig
|
||||
row["vqd_lgt_dark"] = item.VqdLgtDark
|
||||
@ -45,7 +43,7 @@ func (a VqdTaskAPI) getVqdTaskTemplate(c *gin.Context, _ *struct{}) (any, error)
|
||||
ID, _ := strconv.Atoi(c.Param("id"))
|
||||
item, err := a.core.GetVqdTaskTemplate(c.Request.Context(), ID)
|
||||
if err != nil {
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqd [%d] err [%s]`, ID, err.Error()))
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqdcms [%d] err [%s]`, ID, err.Error()))
|
||||
}
|
||||
row := make(map[string]interface{})
|
||||
|
||||
@ -65,8 +63,6 @@ func (a VqdTaskAPI) getVqdTaskTemplate(c *gin.Context, _ *struct{}) (any, error)
|
||||
row["vqd_mosaic"] = item.VqdMosaic
|
||||
row["vqd_flower"] = item.VqdFlower
|
||||
row["des"] = item.Des
|
||||
row["plans"] = item.Plans
|
||||
row["enable"] = item.Enable
|
||||
row["created_at"] = item.CreatedAt
|
||||
row["updated_at"] = item.UpdatedAt
|
||||
|
||||
@ -75,7 +71,7 @@ func (a VqdTaskAPI) getVqdTaskTemplate(c *gin.Context, _ *struct{}) (any, error)
|
||||
func (a VqdTaskAPI) addVqdTaskTemplate(c *gin.Context, in *vqd.AddVqdTaskTemplateInput) (any, error) {
|
||||
_, err := a.core.AddVqdTaskTemplate(c.Request.Context(), in)
|
||||
if err != nil {
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`add vqd err [%s]`, err.Error()))
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`add vqdcms err [%s]`, err.Error()))
|
||||
}
|
||||
|
||||
return gin.H{"data": "OK!"}, err
|
||||
@ -85,12 +81,12 @@ func (a VqdTaskAPI) editVqdTaskTemplate(c *gin.Context, in *vqd.EditVqdTaskTempl
|
||||
ID, _ := strconv.Atoi(c.Param("id"))
|
||||
_, err := a.core.GetVqdTaskTemplate(c.Request.Context(), ID)
|
||||
if err != nil {
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqd [%d] err [%s]`, ID, err.Error()))
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqdcms [%d] err [%s]`, ID, err.Error()))
|
||||
}
|
||||
|
||||
_, err = a.core.EditVqdTaskTemplate(c.Request.Context(), in, ID)
|
||||
if err != nil {
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`edit vqd err [%s]`, err.Error()))
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`edit vqdcms err [%s]`, err.Error()))
|
||||
}
|
||||
return gin.H{"data": "OK!"}, err
|
||||
}
|
||||
@ -99,7 +95,7 @@ func (a VqdTaskAPI) delVqdTaskTemplate(c *gin.Context, _ *struct{}) (any, error)
|
||||
ID, _ := strconv.Atoi(c.Param("id"))
|
||||
info, err := a.core.GetVqdTaskTemplate(c.Request.Context(), ID)
|
||||
if err != nil {
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqd [%d] err [%s]`, ID, err.Error()))
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqdcms [%d] err [%s]`, ID, err.Error()))
|
||||
}
|
||||
if info.IsDefault {
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`默认模板不支持删除 [%s] `, info.Name))
|
||||
@ -112,7 +108,7 @@ func (a VqdTaskAPI) delVqdTaskTemplate(c *gin.Context, _ *struct{}) (any, error)
|
||||
}
|
||||
_, err = a.core.DelVqdTaskTemplate(c.Request.Context(), ID)
|
||||
if err != nil {
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqd [%d] err [%s]`, ID, err.Error()))
|
||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqdcms [%d] err [%s]`, ID, err.Error()))
|
||||
}
|
||||
|
||||
return gin.H{"data": "OK!"}, err
|
||||
|
||||
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) {
|
||||
const { id, ...payload } = data;
|
||||
console.log(data);
|
||||
|
||||
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 { Modal, Form, Input, Select, Button, message, Space } from "antd";
|
||||
import { Modal, Form, Input, Select, Button, message, Space, Switch } from "antd";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { CreateVqdTask, UpdateVqdTask } from "../api/vqdtask";
|
||||
import { GetVqdTaskTemplate } from "../api/vqdtasktemplate";
|
||||
import { GetVqdTimeTemplate } from "../api/vqdtimetemplate";
|
||||
import type { CreateVqdTaskReq, VqdTaskItem } from "../types/vqdtask";
|
||||
import { useGlobal } from "../Context";
|
||||
import ChannelModel, { IChannelModelFunc } from "./channel/Channel";
|
||||
@ -42,9 +43,9 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
||||
} else {
|
||||
setEditing(false);
|
||||
form.resetFields();
|
||||
// form.setFieldsValue({
|
||||
// bid: "2",
|
||||
// });
|
||||
form.setFieldsValue({
|
||||
enable: true,
|
||||
});
|
||||
}
|
||||
setOpen(true);
|
||||
},
|
||||
@ -55,11 +56,9 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
||||
name: ""
|
||||
});
|
||||
|
||||
// 获取任务列表
|
||||
// 获取模板列表
|
||||
const {
|
||||
data: storageResponse,
|
||||
isLoading,
|
||||
refetch,
|
||||
} = useQuery({
|
||||
queryKey: ["storage", pagination],
|
||||
queryFn: () =>
|
||||
@ -72,6 +71,21 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
||||
// refetchInterval: 4000,
|
||||
retry: 1,
|
||||
});
|
||||
// 获取计划列表
|
||||
const {
|
||||
data: storageTimeResponse,
|
||||
} = useQuery({
|
||||
queryKey: ["storages", pagination],
|
||||
queryFn: () =>
|
||||
GetVqdTimeTemplate({ ...pagination })
|
||||
.then((res) => res.data)
|
||||
.catch((err) => {
|
||||
ErrorHandle(err);
|
||||
throw err;
|
||||
}),
|
||||
// refetchInterval: 4000,
|
||||
retry: 1,
|
||||
});
|
||||
const { mutate: createMutate, isPending: creating } = useMutation({
|
||||
mutationFn: CreateVqdTask,
|
||||
onSuccess: () => {
|
||||
@ -101,7 +115,7 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
||||
|
||||
return (
|
||||
<Modal
|
||||
style={{ top: '-180px' }} // 距离顶部 80px(可改为 10% 等百分比)
|
||||
// style={{ top: '-180px' }} // 距离顶部 80px(可改为 10% 等百分比)
|
||||
title={title}
|
||||
destroyOnHidden={true}
|
||||
open={open}
|
||||
@ -123,7 +137,7 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
||||
channel_id,
|
||||
channel_name,
|
||||
task_template_id,
|
||||
task_template_name,
|
||||
time_template_id,
|
||||
enable } = values as {
|
||||
name: string;
|
||||
des: string;
|
||||
@ -131,7 +145,7 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
||||
channel_id: string;
|
||||
channel_name: string;
|
||||
task_template_id: number;
|
||||
task_template_name: string;
|
||||
time_template_id: number;
|
||||
enable: boolean;
|
||||
};
|
||||
const payload: CreateVqdTaskReq = {
|
||||
@ -140,7 +154,7 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
||||
channel_id,
|
||||
channel_name,
|
||||
task_template_id,
|
||||
task_template_name,
|
||||
time_template_id,
|
||||
enable,
|
||||
};
|
||||
|
||||
@ -174,7 +188,7 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
||||
}}>选择通道</Button>
|
||||
</Space.Compact>
|
||||
</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
|
||||
placeholder="请选择模板"
|
||||
onChange={(res, item: any) => {
|
||||
@ -189,12 +203,35 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
||||
></Select>
|
||||
|
||||
</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
|
||||
name="des"
|
||||
label="描述"
|
||||
>
|
||||
<Input placeholder="请输入描述" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
style={{ width: '20%' }}
|
||||
name="enable"
|
||||
label="启用"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
{editing && (
|
||||
<Form.Item name="id" hidden>
|
||||
<Input />
|
||||
@ -203,9 +240,6 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
||||
<Form.Item name="channel_name" hidden>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item name="task_template_name" hidden>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<ChannelModel ref={channelRef} onCallback={(id: any, name: any) => {
|
||||
form.setFieldsValue({ channel_id: id, channel_name: name });
|
||||
|
||||
@ -1,63 +1,18 @@
|
||||
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 { forwardRef, useImperativeHandle, useState, createContext, useContext } from "react";
|
||||
import { Modal, Form, Input, InputNumber, message, Flex, Switch, FormInstance } from "antd";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { GetVqdConfigDefault } from "../api/config";
|
||||
import { CreateVqdTaskTemplate, UpdateVqdTaskTemplate, } from "../api/vqdtasktemplate";
|
||||
import type { CreateVqdTaskTemplateReq, VqdTaskTemplateItem } from "../types/vqdtasktemplate";
|
||||
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 {
|
||||
title: string;
|
||||
onSuccess: () => void;
|
||||
}
|
||||
interface IAddTemplateContext {
|
||||
editing: boolean;
|
||||
checkList: number[][];
|
||||
form: FormInstance<CreateVqdTaskTemplateReq>;
|
||||
setCheckList: React.Dispatch<React.SetStateAction<number[][]>>;
|
||||
onDelPullDeviceData: (index: number) => void;
|
||||
}
|
||||
const layout = {
|
||||
@ -80,54 +35,21 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
||||
({ 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 itemsTabs: TabsProps['items'] = [
|
||||
{
|
||||
key: '1',
|
||||
forceRender: true,
|
||||
label: '诊断参数',
|
||||
children: <TemplateConfig />
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
forceRender: true,
|
||||
label: '诊断时间',
|
||||
children: <TemplatePlans />
|
||||
},
|
||||
];
|
||||
const { mutate: getVqdConfigDefault } = useMutation({
|
||||
mutationFn: GetVqdConfigDefault,
|
||||
onSuccess: (res) => {
|
||||
const formValues = {
|
||||
name: '',
|
||||
des: '',
|
||||
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,
|
||||
@ -162,8 +84,6 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
||||
const formValues = {
|
||||
name: task.name,
|
||||
id: task.id,
|
||||
plans: task.plans,
|
||||
enable: task.enable,
|
||||
des: task.des,
|
||||
vqd_config: task.vqd_config,
|
||||
vqd_lgt_dark: task.vqd_lgt_dark,
|
||||
@ -178,7 +98,6 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
||||
vqd_mosaic: task.vqd_mosaic,
|
||||
vqd_flower: task.vqd_flower,
|
||||
};
|
||||
setCheckList(parsePlans(task.plans))
|
||||
form.setFieldsValue(formValues);
|
||||
} else {
|
||||
getVqdConfigDefault()
|
||||
@ -224,9 +143,7 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
||||
<AddTemplateContext.Provider
|
||||
value={{
|
||||
form,
|
||||
checkList,
|
||||
editing,
|
||||
setCheckList,
|
||||
onDelPullDeviceData
|
||||
}}
|
||||
>
|
||||
@ -247,7 +164,7 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
||||
onFinish={(values: CreateVqdTaskTemplateReq) => {
|
||||
if (creating || updating) return
|
||||
const payload = values as CreateVqdTaskTemplateReq;
|
||||
payload.plans = arrayToString(checkList)
|
||||
|
||||
console.log(payload);
|
||||
if (editing) {
|
||||
const id = (values as any).id;
|
||||
@ -276,17 +193,9 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
||||
>
|
||||
<Input placeholder="请输入描述" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
style={{ width: '20%' }}
|
||||
name="enable"
|
||||
label="启用"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</Flex>
|
||||
|
||||
<Tabs defaultActiveKey="1" items={itemsTabs} onChange={onChange} />
|
||||
|
||||
<TemplateConfig />
|
||||
|
||||
{editing && (
|
||||
<Form.Item name="id" hidden>
|
||||
@ -302,182 +211,6 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
||||
|
||||
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<{
|
||||
parent: 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 { formatSecondsToHMS } from "../utils/time";
|
||||
import Filter from "./Filter";
|
||||
import AlarmSnap from './snap';
|
||||
import AlarmSnap from './Snap';
|
||||
const variants = ['filled'] as const;
|
||||
export default function VqdAlarmPage() {
|
||||
const { ErrorHandle } = useGlobal();
|
||||
const [pagination, setPagination] = useState({
|
||||
page: 1,
|
||||
size: 10,
|
||||
size: 12,
|
||||
name: ""
|
||||
});
|
||||
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">
|
||||
{/* <Space className="pl-2">
|
||||
<Flex justify="space-between" className="mr-2" align="center">
|
||||
<Space className="pl-2">
|
||||
|
||||
<Popconfirm
|
||||
title="确定要批量删除文件吗?"
|
||||
|
||||
onConfirm={() => {
|
||||
deleteMutationAll({ ids: selectedRowKeys as number[] })
|
||||
const ids = storageResponse?.items.map(item => item.id);
|
||||
deleteMutationAll({ ids: ids as number[] })
|
||||
}}
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
>
|
||||
<Button color="danger" variant="solid" loading={delAllLoadings} disabled={selectedRowKeys.length == 0} >
|
||||
批量删除
|
||||
<Button color="danger" variant="solid" loading={delAllLoadings} >
|
||||
批量删除本页
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
|
||||
</Space> */}
|
||||
</Space>
|
||||
{/* <DatePicker
|
||||
defaultDate={moment().format('YYYY-MM-DD')}
|
||||
moonData={moonReq}
|
||||
@ -284,7 +285,7 @@ export default function VqdAlarmPage() {
|
||||
title="删除告警"
|
||||
description="确定要删除此告警吗?"
|
||||
onConfirm={() => {
|
||||
// delAlarmSnapshot([item.id])
|
||||
deleteMutation(item.id)
|
||||
}}
|
||||
>
|
||||
{/* loading={isDelLoading} */}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
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 { useQuery, useMutation } from "@tanstack/react-query";
|
||||
import { GetVqdTask, DeleteVqdTask } from "../api/vqdtask";
|
||||
import type { VqdTaskItem } from "../types/vqdtask";
|
||||
import { GetVqdTask, DeleteVqdTask, UpdateVqdTask } from "../api/vqdtask";
|
||||
import type { VqdTaskItem, CreateVqdTaskReq } from "../types/vqdtask";
|
||||
import type { ColumnsType } from "antd/es/table";
|
||||
import AddVqdTask, { AddVqdTaskRef } from "./AddVqdTask";
|
||||
import { useGlobal } from "../Context";
|
||||
@ -91,6 +91,21 @@ export default function VqdTaskPage() {
|
||||
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> = [
|
||||
{
|
||||
@ -109,7 +124,7 @@ export default function VqdTaskPage() {
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "模板",
|
||||
title: "诊断模板",
|
||||
dataIndex: "task_template_name",
|
||||
align: "center",
|
||||
render: (text, record) => (
|
||||
@ -118,11 +133,33 @@ export default function VqdTaskPage() {
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "任务计划",
|
||||
dataIndex: "time_template_name",
|
||||
align: "center",
|
||||
render: (text, record) => (
|
||||
<Space>
|
||||
{text}
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "描述",
|
||||
dataIndex: "des",
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: "启用",
|
||||
dataIndex: "enable",
|
||||
align: "center",
|
||||
render: (text, record) => (
|
||||
<Space>
|
||||
<Switch value={text} defaultChecked onChange={(t) => {
|
||||
saveTemplate(record, t)
|
||||
}} />
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "创建日期",
|
||||
dataIndex: "created_at",
|
||||
@ -136,7 +173,7 @@ export default function VqdTaskPage() {
|
||||
fixed: "right",
|
||||
render: (_, record) => (
|
||||
<Space>
|
||||
|
||||
|
||||
<Tooltip placement="top" title="编辑" color="#fff">
|
||||
<Button icon={<EditOutlined />} onClick={() => handleEdit(record)} />
|
||||
</Tooltip>
|
||||
@ -166,7 +203,7 @@ export default function VqdTaskPage() {
|
||||
<Flex justify="space-between" align="center" className="mb-4">
|
||||
<Space>
|
||||
<Button type="primary" icon={<PlusOutlined />} onClick={handleAdd}>
|
||||
新增任务
|
||||
新增诊断任务
|
||||
</Button>
|
||||
{/* <Popconfirm
|
||||
title="确定要批量删除文件吗?"
|
||||
@ -213,7 +250,7 @@ export default function VqdTaskPage() {
|
||||
{/* 编辑模态框 */}
|
||||
<AddVqdTask
|
||||
ref={dialogRef}
|
||||
title="编辑"
|
||||
title="添加/编辑诊断任务"
|
||||
onSuccess={() => refetch()}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -64,11 +64,6 @@ export default function VqdTaskTemplatePage() {
|
||||
const handleEdit = (disk: VqdTaskTemplateItem) => {
|
||||
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) => {
|
||||
@ -111,18 +106,6 @@ export default function VqdTaskTemplatePage() {
|
||||
dataIndex: "name",
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: "启用",
|
||||
dataIndex: "enable",
|
||||
align: "center",
|
||||
render: (text, record) => (
|
||||
<Space>
|
||||
<Switch value={text} defaultChecked onChange={(t) => {
|
||||
saveTemplate(record, t)
|
||||
}} />
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "诊断模块",
|
||||
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 {
|
||||
FileSearchOutlined,
|
||||
AlertOutlined,
|
||||
FileTextOutlined,
|
||||
SettingOutlined
|
||||
CarryOutOutlined,
|
||||
SettingOutlined,
|
||||
FileProtectOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import Box from "../components/Box";
|
||||
import { useState } from "react";
|
||||
import VqdTaskPage from "../components/VqdTask";
|
||||
import VqdTaskTemplatePage from "../components/VqdTaskTemplate";
|
||||
import VqdTimeTemplatePage from "../components/VqdTimeTemplate";
|
||||
import VqdAlarmPage from "../components/VqdAlarm";
|
||||
import VqdConfigPage from "../components/VqdConfig";
|
||||
|
||||
@ -19,21 +21,26 @@ export default function Home() {
|
||||
const items: MenuItem[] = [
|
||||
{
|
||||
key: "sub0",
|
||||
label: "任务管理",
|
||||
label: "设备视频诊断",
|
||||
icon: <FileSearchOutlined />,
|
||||
},
|
||||
{
|
||||
key: "sub1",
|
||||
label: "任务模板",
|
||||
icon: <FileTextOutlined />,
|
||||
},
|
||||
{
|
||||
key: "sub2",
|
||||
label: "诊断告警",
|
||||
label: "诊断结果查询",
|
||||
icon: <AlertOutlined />,
|
||||
},
|
||||
{
|
||||
key: "sub2",
|
||||
label: "诊断计划",
|
||||
icon: <CarryOutOutlined />,
|
||||
},
|
||||
{
|
||||
key: "sub3",
|
||||
label: "诊断参数",
|
||||
icon: <FileProtectOutlined />,
|
||||
},
|
||||
{
|
||||
key: "sub4",
|
||||
label: "基础配置",
|
||||
icon: <SettingOutlined />,
|
||||
},
|
||||
@ -82,15 +89,20 @@ export default function Home() {
|
||||
)}
|
||||
{currentMenu == "sub1" && (
|
||||
<Box>
|
||||
<VqdTaskTemplatePage />
|
||||
<VqdAlarmPage />
|
||||
</Box>
|
||||
)}
|
||||
{currentMenu == "sub2" && (
|
||||
<Box>
|
||||
<VqdAlarmPage />
|
||||
<VqdTimeTemplatePage />
|
||||
</Box>
|
||||
)}
|
||||
{currentMenu == "sub3" && (
|
||||
<Box>
|
||||
<VqdTaskTemplatePage />
|
||||
</Box>
|
||||
)}
|
||||
{currentMenu == "sub4" && (
|
||||
<Box>
|
||||
<VqdConfigPage />
|
||||
</Box>
|
||||
|
||||
@ -27,7 +27,9 @@ export type VqdTaskItem = {
|
||||
channel_id: string;
|
||||
channel_name: string;
|
||||
task_template_id: number;
|
||||
time_template_id: number;
|
||||
task_template_name: string;
|
||||
time_template_name: string;
|
||||
enable: boolean;
|
||||
created_at?: string;
|
||||
updated_at?: string;
|
||||
@ -70,9 +72,9 @@ export type CreateVqdTaskReq = {
|
||||
*/
|
||||
task_template_id: number;
|
||||
/**
|
||||
* 模板名称
|
||||
* 关联计划
|
||||
*/
|
||||
task_template_name: string;
|
||||
time_template_id: number;
|
||||
/**
|
||||
* 启用
|
||||
*/
|
||||
@ -99,12 +101,14 @@ export type UpdateVqdTaskReq = Partial<CreateVqdTaskReq> & {
|
||||
export type VqdTaskDetailRes = {
|
||||
id: number;
|
||||
name: string;
|
||||
size: number;
|
||||
mode: string;
|
||||
encode_status: number;
|
||||
file_name: string;
|
||||
source_url: string;
|
||||
channel_id: string;
|
||||
channel_name: string;
|
||||
task_template_id: number;
|
||||
time_template_id: number;
|
||||
task_template_name: string;
|
||||
time_template_name: string;
|
||||
enable: boolean;
|
||||
created_at?: string;
|
||||
updated_at?: string;
|
||||
des?: string;
|
||||
des: string;
|
||||
}
|
||||
@ -24,8 +24,6 @@ export type VqdTaskTemplateRes = {
|
||||
export type VqdTaskTemplateItem = {
|
||||
id: number;
|
||||
name: string;
|
||||
plans: string;
|
||||
enable: boolean;
|
||||
is_default: boolean;
|
||||
vqd_config: VqdConfig;
|
||||
vqd_lgt_dark: VqdLgtDark;
|
||||
@ -131,14 +129,6 @@ export type CreateVqdTaskTemplateReq = {
|
||||
* 名称
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* 计划
|
||||
*/
|
||||
plans: string;
|
||||
/**
|
||||
* 启用
|
||||
*/
|
||||
enable: boolean;
|
||||
vqd_config: VqdConfig;
|
||||
vqd_lgt_dark: VqdLgtDark;
|
||||
vqd_blue: VqdBlue;
|
||||
@ -173,8 +163,6 @@ export type UpdateVqdTaskTemplateReq = Partial<CreateVqdTaskTemplateReq> & {
|
||||
export type VqdTaskTemplateDetailRes = {
|
||||
id: number;
|
||||
name: string;
|
||||
plans: string;
|
||||
enable: boolean;
|
||||
is_default: boolean;
|
||||
vqd_config: VqdConfig;
|
||||
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