Skip to content
This repository was archived by the owner on Apr 16, 2026. It is now read-only.

Commit b356793

Browse files
Adds a privacy mode..
It add a black background, a message, and mute the audio. Regarding the implementation, I preferred to use a black background mask instead of disabling the output, because I want it to be recorded that at such a time the privacy mode was enabled if an NVR is recording from RTSP. This is how Tapo cameras behave. I don't know about others. Regarding the configuration and activation, I would like to ask for help from anyone who has a better understanding of the codebase.
1 parent 4b5d3d7 commit b356793

8 files changed

Lines changed: 126 additions & 11 deletions

File tree

src/AudioWorker.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ void AudioWorker::run()
145145
while (global_audio[encChn]->running)
146146
{
147147
if (global_audio[encChn]->hasDataCallback && cfg->audio.input_enabled
148-
&& (global_video[0]->hasDataCallback || global_video[1]->hasDataCallback))
148+
&& (global_video[0]->hasDataCallback || global_video[1]->hasDataCallback)
149+
&& (!cfg->general.privacy_mode))
149150
{
150151
if (IMP_AI_PollingFrame(global_audio[encChn]->devId,
151152
global_audio[encChn]->aiChn,

src/Config.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ std::vector<ConfigItem<bool>> CFG::getBoolItems()
103103
#endif
104104
{"image.vflip", image.vflip, false, validateBool},
105105
{"image.hflip", image.hflip, false, validateBool},
106+
{"general.privacy_mode", general.privacy_mode, true, validateBool},
106107
{"motion.enabled", motion.enabled, false, validateBool},
107108
{"rtsp.auth_required", rtsp.auth_required, true, validateBool},
108109
#if defined(AUDIO_SUPPORT)
@@ -156,6 +157,7 @@ std::vector<ConfigItem<const char *>> CFG::getCharItems()
156157
{"stream0.osd.time_format", stream0.osd.time_format, "%F %T", validateCharNotEmpty},
157158
{"stream0.osd.uptime_format", stream0.osd.uptime_format, "Up: %02lud %02lu:%02lu", validateCharNotEmpty},
158159
{"stream0.osd.user_text_format", stream0.osd.user_text_format, "%hostname", validateCharNotEmpty},
160+
{"stream0.osd.privacy_format", stream0.osd.privacy_format, "%hostname in private mode", validateCharNotEmpty},
159161
{"stream0.mode", stream0.mode, DEFAULT_ENC_MODE_0, [](const char *v) {
160162
std::set<std::string> a = {"CBR", "VBR", "SMART", "FIXQP", "CAPPED_VBR", "CAPPED_QUALITY"};
161163
return a.count(std::string(v)) == 1;
@@ -168,6 +170,7 @@ std::vector<ConfigItem<const char *>> CFG::getCharItems()
168170
{"stream1.osd.time_format", stream1.osd.time_format, "%F %T", validateCharNotEmpty},
169171
{"stream1.osd.uptime_format", stream1.osd.uptime_format, "Up: %02lud %02lu:%02lu", validateCharNotEmpty},
170172
{"stream1.osd.user_text_format", stream1.osd.user_text_format, "%hostname", validateCharNotEmpty},
173+
{"stream1.osd.privacy_format", stream1.osd.privacy_format, "%hostname in private mode", validateCharNotEmpty},
171174
{"stream1.mode", stream1.mode, DEFAULT_ENC_MODE_1, [](const char *v) {
172175
std::set<std::string> a = {"CBR", "VBR", "SMART", "FIXQP", "CAPPED_VBR", "CAPPED_QUALITY"};
173176
return a.count(std::string(v)) == 1;

src/Config.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ struct _stream_stats {
9090
};
9191

9292
struct _regions {
93+
int priv_back;
94+
int priv_text;
9395
int time;
9496
int user;
9597
int uptime;
@@ -99,6 +101,7 @@ struct _general {
99101
const char *loglevel;
100102
int osd_pool_size;
101103
int imp_polling_timeout;
104+
bool privacy_mode;
102105
};
103106
struct _rtsp {
104107
int port;
@@ -203,6 +206,7 @@ struct _osd {
203206
const char *time_format;
204207
const char *uptime_format;
205208
const char *user_text_format;
209+
const char *privacy_format;
206210
const char *logo_path;
207211
unsigned int font_color;
208212
unsigned int font_stroke_color;

src/IMPAudio.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,11 @@ int IMPAudio::init()
140140
ret = IMP_AI_GetPubAttr(devId, &ioattr);
141141
LOG_DEBUG_OR_ERROR(ret, "IMP_AI_GetPubAttr(" << devId << ")");
142142

143-
ret = IMP_AI_Enable(devId);
144-
LOG_DEBUG_OR_ERROR(ret, "IMP_AI_Enable(" << devId << ")");
143+
if (!cfg->general.privacy_mode)
144+
{
145+
ret = IMP_AI_Enable(devId);
146+
LOG_DEBUG_OR_ERROR(ret, "IMP_AI_Enable(" << devId << ")");
147+
}
145148

146149
IMPAudioIChnParam chnParam = {
147150
.usrFrmDepth = 30, // frame buffer depth

src/Motion.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ int Motion::init()
136136
LOG_ERROR("Monitor stream is disabled, abort.");
137137
return -1;
138138
}
139+
140+
if (cfg->general.privacy_mode) {
141+
LOG_ERROR("Privacy mode enabled, abort.");
142+
return -1;
143+
}
144+
139145
int ret;
140146

141147
ret = IMP_IVS_CreateGroup(0);

src/OSD.cpp

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,71 @@ void OSD::init()
545545
LOG_DEBUG("libschrift init failed.");
546546
}
547547

548+
if (cfg->general.privacy_mode)
549+
{
550+
/* OSD Privacy Background */
551+
osdPrivBack.data = nullptr;
552+
osdPrivBack.imp_rgn = IMP_OSD_CreateRgn(nullptr);
553+
IMP_OSD_RegisterRgn(osdPrivBack.imp_rgn, osdGrp, nullptr);
554+
osd.regions.priv_back = osdPrivBack.imp_rgn;
555+
556+
memset(&osdPrivBack.rgnAttr, 0, sizeof(IMPOSDRgnAttr));
557+
558+
osdPrivBack.rgnAttr.type = OSD_REG_COVER;
559+
osdPrivBack.rgnAttr.fmt = PIX_FMT_BGRA;
560+
osdPrivBack.rgnAttr.rect.p0.x = 0;
561+
osdPrivBack.rgnAttr.rect.p0.y = 0;
562+
osdPrivBack.rgnAttr.rect.p1.x = stream_width - 1;
563+
osdPrivBack.rgnAttr.rect.p1.y = stream_height - 1;
564+
osdPrivBack.rgnAttr.data.coverData.color = 0xff000000;
565+
566+
IMP_OSD_SetRgnAttr(osdPrivBack.imp_rgn, &osdPrivBack.rgnAttr);
567+
568+
IMPOSDGrpRgnAttr grpRgnAttrBack;
569+
570+
memset(&grpRgnAttrBack, 0, sizeof(IMPOSDGrpRgnAttr));
571+
grpRgnAttrBack.show = 1;
572+
grpRgnAttrBack.layer = 1;
573+
grpRgnAttrBack.gAlphaEn = 0;
574+
grpRgnAttrBack.fgAlhpa = 0;
575+
IMP_OSD_SetGrpRgnAttr(osdPrivBack.imp_rgn, osdGrp, &grpRgnAttrBack);
576+
577+
/* OSD Privacy Message */
578+
int posPrivacyTextX = round(stream_width / 2);
579+
int posPrivacyTextY = round(stream_height / 2);
580+
581+
osdPrivText.data = nullptr;
582+
osdPrivText.imp_rgn = IMP_OSD_CreateRgn(nullptr);
583+
IMP_OSD_RegisterRgn(osdPrivText.imp_rgn, osdGrp, nullptr);
584+
osd.regions.priv_text = osdPrivText.imp_rgn;
585+
586+
memset(&osdPrivText.rgnAttr, 0, sizeof(IMPOSDRgnAttr));
587+
osdPrivText.rgnAttr.type = OSD_REG_PIC;
588+
osdPrivText.rgnAttr.fmt = PIX_FMT_BGRA;
589+
590+
std::string privacy_text = osd.privacy_format;
591+
if (strstr(osd.privacy_format, "%hostname") != nullptr)
592+
{
593+
replace(privacy_text, "%hostname", hostname);
594+
}
595+
596+
set_text(&osdPrivText, &osdPrivText.rgnAttr, privacy_text.c_str(),
597+
posPrivacyTextX, posPrivacyTextY, 0);
598+
599+
privacy_text.clear();
600+
601+
IMP_OSD_SetRgnAttr(osdPrivText.imp_rgn, &osdPrivText.rgnAttr);
602+
603+
IMPOSDGrpRgnAttr grpRgnAttrText;
604+
memset(&grpRgnAttrText, 0, sizeof(IMPOSDGrpRgnAttr));
605+
grpRgnAttrText.show = 1;
606+
grpRgnAttrText.layer = 2;
607+
grpRgnAttrText.gAlphaEn = 1;
608+
grpRgnAttrText.fgAlhpa = osd.user_text_transparency;
609+
IMP_OSD_SetGrpRgnAttr(osdPrivText.imp_rgn, osdGrp, &grpRgnAttrText);
610+
}
611+
612+
548613
if (osd.time_enabled)
549614
{
550615
/* OSD Time */
@@ -573,7 +638,7 @@ void OSD::init()
573638
IMPOSDGrpRgnAttr grpRgnAttr;
574639
memset(&grpRgnAttr, 0, sizeof(IMPOSDGrpRgnAttr));
575640
grpRgnAttr.show = 1;
576-
grpRgnAttr.layer = 1;
641+
grpRgnAttr.layer = 3;
577642
grpRgnAttr.gAlphaEn = 0;
578643
grpRgnAttr.fgAlhpa = osd.time_transparency;
579644
IMP_OSD_SetGrpRgnAttr(osdTime.imp_rgn, osdGrp, &grpRgnAttr);
@@ -611,7 +676,7 @@ void OSD::init()
611676
IMPOSDGrpRgnAttr grpRgnAttr;
612677
memset(&grpRgnAttr, 0, sizeof(IMPOSDGrpRgnAttr));
613678
grpRgnAttr.show = 1;
614-
grpRgnAttr.layer = 2;
679+
grpRgnAttr.layer = 4;
615680
grpRgnAttr.gAlphaEn = 1;
616681
grpRgnAttr.fgAlhpa = osd.user_text_transparency;
617682
IMP_OSD_SetGrpRgnAttr(osdUser.imp_rgn, osdGrp, &grpRgnAttr);
@@ -646,7 +711,7 @@ void OSD::init()
646711
IMPOSDGrpRgnAttr grpRgnAttr;
647712
memset(&grpRgnAttr, 0, sizeof(IMPOSDGrpRgnAttr));
648713
grpRgnAttr.show = 1;
649-
grpRgnAttr.layer = 3;
714+
grpRgnAttr.layer = 5;
650715
grpRgnAttr.gAlphaEn = 1;
651716
grpRgnAttr.fgAlhpa = osd.uptime_transparency;
652717
IMP_OSD_SetGrpRgnAttr(osdUptm.imp_rgn, osdGrp, &grpRgnAttr);
@@ -708,7 +773,7 @@ void OSD::init()
708773
IMPOSDGrpRgnAttr grpRgnAttr;
709774
memset(&grpRgnAttr, 0, sizeof(IMPOSDGrpRgnAttr));
710775
grpRgnAttr.show = 1;
711-
grpRgnAttr.layer = 4;
776+
grpRgnAttr.layer = 6;
712777
grpRgnAttr.gAlphaEn = 1;
713778
grpRgnAttr.fgAlhpa = osd.logo_transparency;
714779
IMP_OSD_SetGrpRgnAttr(osdLogo.imp_rgn, osdGrp, &grpRgnAttr);
@@ -742,6 +807,12 @@ int OSD::exit()
742807
ret = IMP_OSD_Stop(osdGrp);
743808
LOG_DEBUG_OR_ERROR(ret, "IMP_OSD_Stop(" << osdGrp << ")");
744809

810+
ret = IMP_OSD_ShowRgn(osdPrivBack.imp_rgn, osdGrp, 0);
811+
LOG_DEBUG_OR_ERROR(ret, "IMP_OSD_ShowRgn(osdPrivBack.imp_rgn, " << osdGrp << ", 0)");
812+
813+
ret = IMP_OSD_ShowRgn(osdPrivText.imp_rgn, osdGrp, 0);
814+
LOG_DEBUG_OR_ERROR(ret, "IMP_OSD_ShowRgn(osdPrivText.imp_rgn, " << osdGrp << ", 0)");
815+
745816
ret = IMP_OSD_ShowRgn(osdTime.imp_rgn, osdGrp, 0);
746817
LOG_DEBUG_OR_ERROR(ret, "IMP_OSD_ShowRgn(osdTime.imp_rgn, " << osdGrp << ", 0)");
747818

@@ -766,6 +837,8 @@ int OSD::exit()
766837
ret = IMP_OSD_UnRegisterRgn(osdLogo.imp_rgn, osdGrp);
767838
LOG_DEBUG_OR_ERROR(ret, "IMP_OSD_UnRegisterRgn(osdUptm.imp_rgn, " << osdGrp << ")");
768839

840+
IMP_OSD_DestroyRgn(osdPrivBack.imp_rgn);
841+
IMP_OSD_DestroyRgn(osdPrivText.imp_rgn);
769842
IMP_OSD_DestroyRgn(osdTime.imp_rgn);
770843
IMP_OSD_DestroyRgn(osdUser.imp_rgn);
771844
IMP_OSD_DestroyRgn(osdUptm.imp_rgn);
@@ -775,6 +848,8 @@ int OSD::exit()
775848
LOG_DEBUG_OR_ERROR(ret, "IMP_OSD_DestroyGroup(" << osdGrp << ")");
776849

777850
// cleanup osd image data
851+
free(osdPrivBack.data);
852+
free(osdPrivText.data);
778853
free(osdTime.data);
779854
free(osdUser.data);
780855
free(osdUptm.data);

src/OSD.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,9 @@ class OSD
7575

7676
_osd &osd;
7777
int last_updated_second;
78-
7978

79+
OSDItem osdPrivBack{};
80+
OSDItem osdPrivText{};
8081
OSDItem osdTime{};
8182
OSDItem osdUser{};
8283
OSDItem osdUptm{};

src/WS.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,16 @@ enum
109109
{
110110
PNT_GENERAL_LOGLEVEL = 1,
111111
PNT_GENERAL_OSD_POOL_SIZE,
112-
PNT_GENERAL_IMP_POLLING_TIMEOUT
112+
PNT_GENERAL_IMP_POLLING_TIMEOUT,
113+
PNT_GENERAL_PRIVACY_MODE
113114
};
114115

115116
static const char *const general_keys[] = {
116117
"loglevel",
117118
"osd_pool_size",
118-
"imp_polling_timeout"};
119+
"imp_polling_timeout",
120+
"privacy_mode",
121+
};
119122

120123
/* RTSP */
121124
enum
@@ -661,6 +664,25 @@ signed char WS::general_callback(struct lejp_ctx *ctx, char reason)
661664
}
662665
add_json_str(u_ctx->message, cfg->get<const char *>(u_ctx->path));
663666
break;
667+
case PNT_GENERAL_PRIVACY_MODE:
668+
if (reason == LEJPCB_VAL_TRUE)
669+
{
670+
if (cfg->set<bool>(u_ctx->path, true))
671+
{
672+
global_restart_audio = true;
673+
global_restart_rtsp = true;
674+
}
675+
}
676+
else if (reason == LEJPCB_VAL_FALSE)
677+
{
678+
if (cfg->set<bool>(u_ctx->path, true))
679+
{
680+
global_restart_audio = true;
681+
global_restart_rtsp = true;
682+
}
683+
}
684+
add_json_bool(u_ctx->message, cfg->get<bool>(u_ctx->path));
685+
break;
664686
default:
665687
u_ctx->flag &= ~PNT_FLAG_SEPARATOR;
666688
break;
@@ -1498,7 +1520,7 @@ signed char WS::osd_callback(struct lejp_ctx *ctx, char reason)
14981520
if (cfg->set<int>(u_ctx->path, atoi(ctx->buf)))
14991521
{
15001522

1501-
_regions regions{-1,-1,-1,-1};
1523+
_regions regions{-1,-1,-1,-1,-1,-1};
15021524

15031525
if (u_ctx->value == 0)
15041526
{

0 commit comments

Comments
 (0)