Skip to content

Commit 626320a

Browse files
Merge branch 'release-1.36' of github.com:ZoneMinder/zoneminder into release-1.36
2 parents 280d18c + ea1f1db commit 626320a

File tree

15 files changed

+175
-56
lines changed

15 files changed

+175
-56
lines changed

src/zm_ffmpeg.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -320,26 +320,29 @@ void zm_dump_codecpar(const AVCodecParameters *par);
320320
);
321321

322322
#if LIBAVUTIL_VERSION_CHECK(54, 4, 0, 74, 100)
323-
#define zm_dump_video_frame(frame, text) Debug(1, "%s: format %d %s %dx%d linesize:%dx%d pts: %" PRId64 " keyframe: %d", \
323+
#define zm_dump_video_frame(frame, text) Debug(1, "%s: format %d %s %dx%d linesize:%dx%d pts: %" PRId64 " pkt_dts %" PRId64 " keyframe: %d", \
324324
text, \
325325
frame->format, \
326326
av_get_pix_fmt_name((AVPixelFormat)frame->format), \
327327
frame->width, \
328328
frame->height, \
329329
frame->linesize[0], frame->linesize[1], \
330330
frame->pts, \
331+
frame->pkt_pts, \
331332
frame->key_frame \
332333
);
333334

334335
#else
335-
#define zm_dump_video_frame(frame,text) Debug(1, "%s: format %d %s %dx%d linesize:%dx%d pts: %" PRId64, \
336+
#define zm_dump_video_frame(frame,text) Debug(1, "%s: format %d %s %dx%d linesize:%dx%d pts: %" PRId64 " pkt_pts %" PRId64 " pkt_dts %" PRId64, \
336337
text, \
337338
frame->format, \
338339
"unsupported", \
339340
frame->width, \
340341
frame->height, \
341342
frame->linesize[0], frame->linesize[1], \
342-
frame->pts \
343+
frame->pts, \
344+
frame->pkt_pts, \
345+
frame->pkt_dts \
343346
);
344347
#endif
345348

src/zm_ffmpeg_camera.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,8 @@ FfmpegCamera::FfmpegCamera(
131131
hwaccel_name(p_hwaccel_name),
132132
hwaccel_device(p_hwaccel_device)
133133
{
134-
mMaskedPath = mask_authentication(mPath);
135-
mMaskedSecondPath = mask_authentication(mSecondPath);
134+
mMaskedPath = remove_authentication(mPath);
135+
mMaskedSecondPath = remove_authentication(mSecondPath);
136136
if ( capture ) {
137137
FFMPEGInit();
138138
}

src/zm_ffmpeg_input.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ int FFmpeg_Input::Open(
4343
}
4444

4545
int FFmpeg_Input::Open(const char *filepath) {
46-
4746
int error;
4847

4948
/** Open the input file to read from it. */
@@ -198,12 +197,24 @@ AVFrame *FFmpeg_Input::get_frame(int stream_id) {
198197
} else {
199198
zm_dump_frame(frame, "resulting frame");
200199
}
200+
if (frame->pts == AV_NOPTS_VALUE) {
201+
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
202+
frame->pts = frame->pkt_dts;
203+
#else
204+
frame->pts = frame->pkt_pts;
205+
#endif
206+
}
201207
}
202208

203209
frameComplete = 1;
204210

205-
zm_av_packet_unref(&packet);
211+
// Convert timestamps to stream timebase instead of codec timebase
212+
frame->pts = av_rescale_q(frame->pts,
213+
context->time_base,
214+
input_format_context->streams[stream_id]->time_base
215+
);
206216

217+
zm_av_packet_unref(&packet);
207218
} // end while !frameComplete
208219
return frame;
209220
} // end AVFrame *FFmpeg_Input::get_frame
@@ -263,6 +274,17 @@ AVFrame *FFmpeg_Input::get_frame(int stream_id, double at) {
263274

264275
last_seek_request = seek_target;
265276

277+
if (frame->pts + frame->pkt_duration < seek_target) {
278+
Debug(1, "Jumping ahead");
279+
if (( ret = av_seek_frame(input_format_context, stream_id, seek_target,
280+
AVSEEK_FLAG_FRAME
281+
) ) < 0) {
282+
Error("Unable to seek in stream %d", ret);
283+
return nullptr;
284+
}
285+
// Have to grab a frame to update our current frame to know where we are
286+
get_frame(stream_id);
287+
}
266288
// Seeking seems to typically seek to a keyframe, so then we have to decode until we get the frame we want.
267289
if ( frame->pts <= seek_target ) {
268290
if ( is_video_stream(input_format_context->streams[stream_id]) ) {

src/zm_stream.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ void StreamBase::updateFrameRate(double fps) {
100100
fps, maxfps, base_fps, effective_fps, frame_mod, replay_rate);
101101
// Min frame repeat?
102102
// We want to keep the frame skip easy... problem is ... if effective = 31 and max = 30 then we end up with 15.5 fps.
103-
while ( effective_fps > maxfps ) {
103+
while ( (int)effective_fps > (int)maxfps ) {
104104
effective_fps /= 2.0;
105105
frame_mod *= 2;
106106
Debug(3, "Changing fps to be < max %.2f EffectiveFPS:%.2f, FrameMod:%d",

src/zm_utils.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,3 +440,30 @@ std::string mask_authentication(const std::string &url) {
440440
}
441441
return masked_url;
442442
}
443+
444+
std::string remove_authentication(const std::string &url) {
445+
std::size_t at_at = url.find("@");
446+
if (at_at == std::string::npos) {
447+
return url;
448+
}
449+
std::string result;
450+
std::size_t password_at = url.rfind(":", at_at);
451+
452+
if (password_at == std::string::npos) {
453+
// no : means no http:// either so something like [email protected]
454+
result = url.substr(at_at+1);
455+
} else if (url[password_at+1] == '/') {
456+
// no password, something like http://[email protected]
457+
result = url.substr(0, password_at+3) + url.substr(at_at+1);
458+
} else {
459+
std::size_t username_at = url.rfind("/", password_at);
460+
if (username_at == std::string::npos) {
461+
// Something like username:[email protected]
462+
result = url.substr(at_at+1);
463+
} else {
464+
// have username and password, something like http://username:[email protected]/
465+
result = url.substr(0, username_at+1) + url.substr(at_at+1);
466+
}
467+
}
468+
return result;
469+
}

src/zm_utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ typedef std::chrono::steady_clock::time_point TimePoint;
110110
typedef std::chrono::system_clock::time_point SystemTimePoint;
111111

112112
std::string mask_authentication(const std::string &url);
113+
std::string remove_authentication(const std::string &url);
113114

114115
std::string UriDecode(const std::string &encoded);
115116

src/zm_videostore.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ extern "C" {
2727
#include "libavutil/time.h"
2828
}
2929

30+
#include <string>
31+
3032
/*
3133
AVCodecID codec_id;
3234
char *codec_codec;
@@ -140,16 +142,16 @@ bool VideoStore::open() {
140142
ret = av_dict_set(&pmetadata, "title", "Zoneminder Security Recording", 0);
141143
if (ret < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__);
142144

143-
AVDictionary *opts = 0;
145+
AVDictionary *opts = nullptr;
144146
std::string options = monitor->GetEncoderOptions();
145147
ret = av_dict_parse_string(&opts, options.c_str(), "=", ",#\n", 0);
146148
if (ret < 0) {
147149
Warning("Could not parse ffmpeg encoder options list '%s'", options.c_str());
148150
} else {
149151
const AVDictionaryEntry *entry = av_dict_get(opts, "reorder_queue_size", nullptr, AV_DICT_MATCH_CASE);
150152
if (entry) {
151-
reorder_queue_size = atoi(entry->value);
152-
Debug(1, "reorder_queue_size set to %d", reorder_queue_size);
153+
reorder_queue_size = std::stoul(entry->value);
154+
Debug(1, "reorder_queue_size set to %zu", reorder_queue_size);
153155
// remove it to prevent complaining later.
154156
av_dict_set(&opts, "reorder_queue_size", nullptr, AV_DICT_MATCH_CASE);
155157
}
@@ -323,7 +325,11 @@ bool VideoStore::open() {
323325
while ((e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != nullptr) {
324326
Warning("Encoder Option %s not recognized by ffmpeg codec", e->key);
325327
}
326-
av_dict_free(&opts);
328+
av_dict_parse_string(&opts, options.c_str(), "=", ",#\n", 0);
329+
if (reorder_queue_size) {
330+
// remove it to prevent complaining later.
331+
av_dict_set(&opts, "reorder_queue_size", nullptr, AV_DICT_MATCH_CASE);
332+
}
327333

328334
if (video_out_codec) break;
329335
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)

src/zm_videostore.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class VideoStore {
107107

108108
int max_stream_index;
109109

110-
int reorder_queue_size;
110+
size_t reorder_queue_size;
111111
std::map<int, std::list<std::shared_ptr<ZMPacket>>> reorder_queues;
112112

113113
bool setup_resampler();

tests/zm_utils.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,3 +238,59 @@ TEST_CASE("QueryString") {
238238
REQUIRE(p2->values()[0] == "value2");
239239
}
240240
}
241+
242+
TEST_CASE("mask_authentication") {
243+
SECTION("no authentication") {
244+
std::string url("http://192.168.1.1");
245+
std::string result = mask_authentication(url);
246+
REQUIRE(url == result);
247+
}
248+
SECTION("has username no password has scheme") {
249+
std::string url("http://[email protected]");
250+
std::string result = mask_authentication(url);
251+
REQUIRE(result == "http://********@192.168.1.1");
252+
}
253+
SECTION("has username no password no scheme") {
254+
std::string url("[email protected]");
255+
std::string result = mask_authentication(url);
256+
REQUIRE(result == "********@192.168.1.1");
257+
}
258+
SECTION("has username has password no scheme") {
259+
std::string url("username:[email protected]");
260+
std::string result = mask_authentication(url);
261+
REQUIRE(result == "********:********@192.168.1.1");
262+
}
263+
SECTION("has username has password has scheme") {
264+
std::string url("http://username:[email protected]");
265+
std::string result = mask_authentication(url);
266+
REQUIRE(result == "http://********:********@192.168.1.1");
267+
}
268+
}
269+
270+
TEST_CASE("remove_authentication") {
271+
SECTION("no authentication") {
272+
std::string url("http://192.168.1.1");
273+
std::string result = remove_authentication(url);
274+
REQUIRE(url == result);
275+
}
276+
SECTION("has username no password has scheme") {
277+
std::string url("http://[email protected]");
278+
std::string result = remove_authentication(url);
279+
REQUIRE(result == "http://192.168.1.1");
280+
}
281+
SECTION("has username no password no scheme") {
282+
std::string url("[email protected]");
283+
std::string result = remove_authentication(url);
284+
REQUIRE(result == "192.168.1.1");
285+
}
286+
SECTION("has username has password no scheme") {
287+
std::string url("username:[email protected]");
288+
std::string result = remove_authentication(url);
289+
REQUIRE(result == "192.168.1.1");
290+
}
291+
SECTION("has username has password has scheme") {
292+
std::string url("http://username:[email protected]");
293+
std::string result = remove_authentication(url);
294+
REQUIRE(result == "http://192.168.1.1");
295+
}
296+
}

web/ajax/modals/state.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
<div class="modal-dialog modal-dialog-centered">
4545
<div class="modal-content">
4646
<div class="modal-header">
47-
<h5 class="modal-title">Run State</h5>
47+
<h5 class="modal-title"><?php echo translate('Run State')?> </h5>
4848
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
4949
<span aria-hidden="true">&times;</span>
5050
</button>
@@ -59,7 +59,7 @@
5959
<input type="hidden" name="action" value="state"/>
6060
<input type="hidden" name="apply" value="1"/>
6161
<div class="form-group">
62-
<label for="runState" class="col-md-3 col-form-label float-left">Change State</label>
62+
<label for="runState" class="col-md-3 col-form-label float-left"><?php echo translate('Change State')?></label>
6363
<div class="col-md-9">
6464
<select id="runState" name="runState" class="form-control">
6565
<?php echo $content ?>

0 commit comments

Comments
 (0)