mirror of
https://github.com/Motion-Project/motion.git
synced 2026-02-05 12:31:43 -05:00
Revise netcam hander_startup/shutdown
This commit is contained in:
@@ -588,14 +588,14 @@ static void motpls_watchdog(ctx_motapp *motapp, uint camindx)
|
||||
pthread_mutex_unlock(&motapp->cam_list[indx]->netcam->mutex);
|
||||
pthread_mutex_unlock(&motapp->cam_list[indx]->netcam->mutex_pktarray);
|
||||
pthread_mutex_unlock(&motapp->cam_list[indx]->netcam->mutex_transfer);
|
||||
motapp->cam_list[indx]->netcam->finish = true;
|
||||
motapp->cam_list[indx]->netcam->handler_stop = true;
|
||||
}
|
||||
if ((motapp->cam_list[indx]->camera_type == CAMERA_TYPE_NETCAM) &&
|
||||
(motapp->cam_list[indx]->netcam_high != nullptr)) {
|
||||
pthread_mutex_unlock(&motapp->cam_list[indx]->netcam_high->mutex);
|
||||
pthread_mutex_unlock(&motapp->cam_list[indx]->netcam_high->mutex_pktarray);
|
||||
pthread_mutex_unlock(&motapp->cam_list[indx]->netcam_high->mutex_transfer);
|
||||
motapp->cam_list[indx]->netcam_high->finish = true;
|
||||
motapp->cam_list[indx]->netcam_high->handler_stop = true;
|
||||
}
|
||||
|
||||
motapp->cam_list[indx]->stop();
|
||||
|
||||
@@ -1042,7 +1042,7 @@ int cls_movie::passthru_streams()
|
||||
int retcd, indx;
|
||||
AVStream *stream_in;
|
||||
|
||||
if (netcam_data->finish == true) {
|
||||
if (netcam_data->handler_stop == true) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
137
src/netcam.cpp
137
src/netcam.cpp
@@ -26,6 +26,11 @@
|
||||
#include "netcam.hpp"
|
||||
#include "movie.hpp"
|
||||
|
||||
static void *netcam_handler(void *arg)
|
||||
{
|
||||
((cls_netcam *)arg)->handler();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
enum AVPixelFormat netcam_getfmt_vaapi(AVCodecContext *avctx, const enum AVPixelFormat *pix_fmts)
|
||||
{
|
||||
@@ -72,7 +77,7 @@ int netcam_interrupt(void *ctx)
|
||||
{
|
||||
cls_netcam *netcam = (cls_netcam *)ctx;
|
||||
|
||||
if (netcam->finish) {
|
||||
if (netcam->handler_stop) {
|
||||
netcam->interrupted = true;
|
||||
return true;
|
||||
}
|
||||
@@ -515,7 +520,7 @@ int cls_netcam::decode_sw()
|
||||
char errstr[128];
|
||||
|
||||
retcd = avcodec_receive_frame(codec_context, frame);
|
||||
if ((interrupted) || (finish) || (retcd < 0)) {
|
||||
if ((interrupted) || (handler_stop) || (retcd < 0)) {
|
||||
if (retcd == AVERROR(EAGAIN)) {
|
||||
retcd = 0;
|
||||
} else if (retcd == AVERROR_INVALIDDATA) {
|
||||
@@ -556,7 +561,7 @@ int cls_netcam::decode_vaapi()
|
||||
}
|
||||
|
||||
retcd = avcodec_receive_frame(codec_context, hw_frame);
|
||||
if ((interrupted) || (finish) || (retcd < 0)) {
|
||||
if ((interrupted) || (handler_stop) || (retcd < 0)) {
|
||||
if (retcd == AVERROR(EAGAIN)) {
|
||||
retcd = 0;
|
||||
} else if (retcd == AVERROR_INVALIDDATA) {
|
||||
@@ -599,7 +604,7 @@ int cls_netcam::decode_cuda()
|
||||
hw_frame = av_frame_alloc();
|
||||
|
||||
retcd = avcodec_receive_frame(codec_context, hw_frame);
|
||||
if ((interrupted) || (finish) || (retcd < 0) ){
|
||||
if ((interrupted) || (handler_stop) || (retcd < 0) ){
|
||||
if (retcd == AVERROR(EAGAIN)){
|
||||
retcd = 0;
|
||||
} else if (retcd == AVERROR_INVALIDDATA) {
|
||||
@@ -644,7 +649,7 @@ int cls_netcam::decode_drm()
|
||||
hw_frame = av_frame_alloc();
|
||||
|
||||
retcd = avcodec_receive_frame(codec_context, hw_frame);
|
||||
if ((interrupted) || (finish) || (retcd < 0) ){
|
||||
if ((interrupted) || (handler_stop) || (retcd < 0) ){
|
||||
if (retcd == AVERROR(EAGAIN)){
|
||||
retcd = 0;
|
||||
} else if (retcd == AVERROR_INVALIDDATA) {
|
||||
@@ -690,14 +695,14 @@ int cls_netcam::decode_video()
|
||||
* We should consider adding a maximum count of these errors and reset every time
|
||||
* we get a good image.
|
||||
*/
|
||||
if (finish) {
|
||||
if (handler_stop) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
retcd = avcodec_send_packet(codec_context, packet_recv);
|
||||
if ((interrupted) || (finish)) {
|
||||
if ((interrupted) || (handler_stop)) {
|
||||
MOTPLS_LOG(INF, TYPE_NETCAM, NO_ERRNO
|
||||
,_("%s:Interrupted or finish on send")
|
||||
,_("%s:Interrupted or handler_stop on send")
|
||||
,cameratype.c_str());
|
||||
return -1;
|
||||
}
|
||||
@@ -737,7 +742,7 @@ int cls_netcam::decode_packet()
|
||||
int frame_size;
|
||||
int retcd;
|
||||
|
||||
if (finish) {
|
||||
if (handler_stop) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1095,7 +1100,7 @@ int cls_netcam::open_codec()
|
||||
{
|
||||
int retcd;
|
||||
|
||||
if (finish) {
|
||||
if (handler_stop) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1152,7 +1157,7 @@ int cls_netcam::open_codec()
|
||||
|
||||
int cls_netcam::open_sws()
|
||||
{
|
||||
if (finish) {
|
||||
if (handler_stop) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1233,7 +1238,7 @@ int cls_netcam::resize()
|
||||
char errstr[128];
|
||||
uint8_t *buffer_out;
|
||||
|
||||
if (finish) {
|
||||
if (handler_stop) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1327,7 +1332,7 @@ int cls_netcam::read_image()
|
||||
char errstr[128];
|
||||
netcam_buff *xchg;
|
||||
|
||||
if (finish) {
|
||||
if (handler_stop) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1468,7 +1473,7 @@ int cls_netcam::read_image()
|
||||
|
||||
int cls_netcam::ntc()
|
||||
{
|
||||
if ((finish) || (!first_image)) {
|
||||
if ((handler_stop) || (!first_image)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1610,7 +1615,6 @@ void cls_netcam::set_parms ()
|
||||
{
|
||||
p_it it;
|
||||
|
||||
finish = false;
|
||||
motapp = cam->motapp;
|
||||
params = new ctx_params;
|
||||
|
||||
@@ -1666,7 +1670,6 @@ void cls_netcam::set_parms ()
|
||||
pktarray_index = -1;
|
||||
pktarray = nullptr;
|
||||
packet_recv = nullptr;
|
||||
handler_finished = true;
|
||||
first_image = true;
|
||||
reconnect_count = 0;
|
||||
src_fps = -1; /* Default to neg so we know it has not been set */
|
||||
@@ -1763,7 +1766,7 @@ int cls_netcam::open_context()
|
||||
int retcd;
|
||||
char errstr[128];
|
||||
|
||||
if (finish) {
|
||||
if (handler_stop) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1788,7 +1791,7 @@ int cls_netcam::open_context()
|
||||
|
||||
retcd = avformat_open_input(&format_context
|
||||
, path.c_str(), nullptr, &opts);
|
||||
if ((retcd < 0) || (interrupted) || (finish) ) {
|
||||
if ((retcd < 0) || (interrupted) || (handler_stop) ) {
|
||||
if (status == NETCAM_NOTCONNECTED) {
|
||||
av_strerror(retcd, errstr, sizeof(errstr));
|
||||
MOTPLS_LOG(NTC, TYPE_NETCAM, NO_ERRNO
|
||||
@@ -1808,7 +1811,7 @@ int cls_netcam::open_context()
|
||||
|
||||
/* fill out stream information */
|
||||
retcd = avformat_find_stream_info(format_context, nullptr);
|
||||
if ((retcd < 0) || (interrupted) || (finish) ) {
|
||||
if ((retcd < 0) || (interrupted) || (handler_stop) ) {
|
||||
if (status == NETCAM_NOTCONNECTED) {
|
||||
av_strerror(retcd, errstr, sizeof(errstr));
|
||||
MOTPLS_LOG(ERR, TYPE_NETCAM, NO_ERRNO
|
||||
@@ -1827,7 +1830,7 @@ int cls_netcam::open_context()
|
||||
mythreadname_set("av", threadnbr, camera_name.c_str());
|
||||
retcd = open_codec();
|
||||
mythreadname_set(nullptr, 0, threadname.c_str());
|
||||
if ((retcd < 0) || (interrupted) || (finish) ) {
|
||||
if ((retcd < 0) || (interrupted) || (handler_stop) ) {
|
||||
if (status == NETCAM_NOTCONNECTED) {
|
||||
av_strerror(retcd, errstr, sizeof(errstr));
|
||||
MOTPLS_LOG(ERR, TYPE_NETCAM, NO_ERRNO
|
||||
@@ -2072,7 +2075,7 @@ void cls_netcam::handler()
|
||||
,_("%s:Camera handler started")
|
||||
,cameratype.c_str());
|
||||
|
||||
while (finish == false) {
|
||||
while (handler_stop == false) {
|
||||
if (format_context == nullptr) { /* We must have disconnected. Try to reconnect */
|
||||
clock_gettime(CLOCK_MONOTONIC, &frame_prev_tm);
|
||||
handler_reconnect();
|
||||
@@ -2080,7 +2083,7 @@ void cls_netcam::handler()
|
||||
} else { /* We think we are connected...*/
|
||||
clock_gettime(CLOCK_MONOTONIC, &frame_prev_tm);
|
||||
if (read_image() < 0) {
|
||||
if (!finish) { /* Nope. We are not or got bad image. Reconnect*/
|
||||
if (handler_stop == false) { /* Nope. We are not or got bad image. Reconnect*/
|
||||
handler_reconnect();
|
||||
}
|
||||
continue;
|
||||
@@ -2092,22 +2095,31 @@ void cls_netcam::handler()
|
||||
}
|
||||
|
||||
MOTPLS_LOG(INF, TYPE_NETCAM, NO_ERRNO
|
||||
,_("%s:Loop finished."),cameratype.c_str());
|
||||
|
||||
MOTPLS_LOG(INF, TYPE_NETCAM, NO_ERRNO
|
||||
,_("%s:Exiting"),cameratype.c_str());
|
||||
,_("%s:Camera handler stopped"),cameratype.c_str());
|
||||
handler_finished = true;
|
||||
pthread_exit(nullptr);
|
||||
|
||||
}
|
||||
|
||||
void cls_netcam::start_handler()
|
||||
void cls_netcam::handler_startup()
|
||||
{
|
||||
int wait_counter;
|
||||
int wait_counter, retcd;
|
||||
pthread_attr_t thread_attr;
|
||||
|
||||
handler_finished = true;
|
||||
|
||||
net_thread = std::thread(&cls_netcam::handler, this);
|
||||
net_thread.detach();
|
||||
if (handler_finished == true) {
|
||||
handler_finished = false;
|
||||
handler_stop = false;
|
||||
pthread_attr_init(&thread_attr);
|
||||
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
|
||||
retcd = pthread_create(&handler_thread, &thread_attr, &netcam_handler, this);
|
||||
if (retcd != 0) {
|
||||
MOTPLS_LOG(WRN, TYPE_ALL, NO_ERRNO,_("Unable to start camera thread."));
|
||||
handler_finished = true;
|
||||
handler_stop = true;
|
||||
return;
|
||||
}
|
||||
pthread_attr_destroy(&thread_attr);
|
||||
}
|
||||
|
||||
/* Now give a few tries to check that an image has been captured.
|
||||
* This ensures that by the time the setup routine exits, the
|
||||
@@ -2115,13 +2127,11 @@ void cls_netcam::start_handler()
|
||||
*/
|
||||
wait_counter = 60;
|
||||
while (wait_counter > 0) {
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
if (img_latest->ptr != nullptr ) {
|
||||
wait_counter = -1;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
if (wait_counter > 0 ) {
|
||||
MOTPLS_LOG(INF, TYPE_NETCAM, NO_ERRNO
|
||||
,_("%s:Waiting for first image from the handler.")
|
||||
@@ -2133,26 +2143,49 @@ void cls_netcam::start_handler()
|
||||
|
||||
}
|
||||
|
||||
void cls_netcam::shutdown()
|
||||
void cls_netcam::handler_shutdown()
|
||||
{
|
||||
int wait_counter;
|
||||
int waitcnt;
|
||||
|
||||
MOTPLS_LOG(INF, TYPE_NETCAM, NO_ERRNO
|
||||
,_("%s:Shutting down network camera.")
|
||||
,cameratype.c_str());
|
||||
|
||||
finish = true;
|
||||
idur = 0;
|
||||
wait_counter = 0;
|
||||
while ((handler_finished == false) && (wait_counter < 10)) {
|
||||
SLEEP(1,0);
|
||||
wait_counter++;
|
||||
}
|
||||
handler_stop = true;
|
||||
|
||||
if (handler_finished == false) {
|
||||
MOTPLS_LOG(ERR, TYPE_NETCAM, NO_ERRNO
|
||||
,_("%s:No response from handler thread.")
|
||||
,cameratype.c_str());
|
||||
pthread_kill(net_thread.native_handle(), SIGVTALRM);
|
||||
waitcnt = 0;
|
||||
while ((handler_finished == false) && (waitcnt < cam->cfg->watchdog_tmo)){
|
||||
SLEEP(1,0)
|
||||
waitcnt++;
|
||||
}
|
||||
if (waitcnt == cam->cfg->watchdog_tmo) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("Normal shutdown of camera failed"));
|
||||
if (cam->cfg->watchdog_kill > 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
,_("Waiting additional %d seconds (watchdog_kill).")
|
||||
,cam->cfg->watchdog_kill);
|
||||
waitcnt = 0;
|
||||
while ((handler_finished == false) && (waitcnt < cam->cfg->watchdog_kill)){
|
||||
SLEEP(1,0)
|
||||
waitcnt++;
|
||||
}
|
||||
if (waitcnt == cam->cfg->watchdog_kill) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("No response to shutdown. Killing it."));
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("Memory leaks will occur."));
|
||||
pthread_kill(handler_thread, SIGVTALRM);
|
||||
}
|
||||
} else {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("watchdog_kill set to terminate application."));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
handler_finished = true;
|
||||
}
|
||||
|
||||
context_close();
|
||||
@@ -2219,6 +2252,8 @@ cls_netcam::cls_netcam(cls_camera *p_cam, bool p_is_high)
|
||||
|
||||
cam = p_cam;
|
||||
high_resolution = p_is_high;
|
||||
handler_finished = true;
|
||||
handler_stop = false;
|
||||
|
||||
if (high_resolution == false) {
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO,_("Norm: Opening Netcam"));
|
||||
@@ -2235,12 +2270,12 @@ cls_netcam::cls_netcam(cls_camera *p_cam, bool p_is_high)
|
||||
retcd = connect();
|
||||
}
|
||||
if (retcd != 0) {
|
||||
shutdown();
|
||||
handler_shutdown();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (connect() != 0) {
|
||||
shutdown();
|
||||
handler_shutdown();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2248,7 +2283,7 @@ cls_netcam::cls_netcam(cls_camera *p_cam, bool p_is_high)
|
||||
MOTPLS_LOG(NTC, TYPE_NETCAM, NO_ERRNO
|
||||
,_("Failed trying to read first image"));
|
||||
status = NETCAM_NOTCONNECTED;
|
||||
shutdown();
|
||||
handler_shutdown();
|
||||
return;
|
||||
}
|
||||
/* When running dual, there seems to be contamination across norm/high with codec functions. */
|
||||
@@ -2261,7 +2296,7 @@ cls_netcam::cls_netcam(cls_camera *p_cam, bool p_is_high)
|
||||
cam->imgs.height_high = imgsize.height;
|
||||
}
|
||||
|
||||
start_handler();
|
||||
handler_startup();
|
||||
|
||||
cam->device_status = STATUS_OPENED;
|
||||
|
||||
@@ -2269,6 +2304,6 @@ cls_netcam::cls_netcam(cls_camera *p_cam, bool p_is_high)
|
||||
|
||||
cls_netcam::~cls_netcam()
|
||||
{
|
||||
shutdown();
|
||||
handler_shutdown();
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,6 @@ class cls_netcam {
|
||||
int next(ctx_image_data *img_data);
|
||||
|
||||
bool interrupted; /* Boolean for whether interrupt has been tripped */
|
||||
bool finish; /* Boolean for whether we are finishing the application */
|
||||
enum NETCAM_STATUS status; /* Status of whether the camera is connecting, closed, etc*/
|
||||
struct timespec ist_tm; /* The time set before calling the av functions */
|
||||
struct timespec icur_tm; /* Time during the interrupt to determine duration since start*/
|
||||
@@ -85,12 +84,9 @@ class cls_netcam {
|
||||
std::string camera_name; /* The name of the camera as provided in the config file */
|
||||
std::string cameratype; /* String specifying Normal or High for use in logging */
|
||||
|
||||
bool handler_finished; /* Boolean for whether the handler is running or not */
|
||||
|
||||
pthread_mutex_t mutex; /* mutex used with conditional waits */
|
||||
pthread_mutex_t mutex_transfer; /* mutex used with transferring stream info for pass-through */
|
||||
pthread_mutex_t mutex_pktarray; /* mutex used with the packet array */
|
||||
std::thread net_thread;
|
||||
|
||||
AVFormatContext *transfer_format; /* Format context just for transferring to pass-through */
|
||||
ctx_packet_item *pktarray; /* Pointer to array of packets for passthru processing */
|
||||
@@ -98,6 +94,10 @@ class cls_netcam {
|
||||
int video_stream_index; /* Stream index associated with video from camera */
|
||||
int audio_stream_index; /* Stream index associated with video from camera */
|
||||
|
||||
bool handler_stop;
|
||||
bool handler_finished;
|
||||
pthread_t handler_thread;
|
||||
void handler();
|
||||
|
||||
private:
|
||||
cls_camera *cam;
|
||||
@@ -196,11 +196,11 @@ class cls_netcam {
|
||||
int copy_stream();
|
||||
int open_context();
|
||||
int connect();
|
||||
void shutdown();
|
||||
|
||||
void handler_wait();
|
||||
void handler_reconnect();
|
||||
void handler();
|
||||
void start_handler();
|
||||
void handler_startup();
|
||||
void handler_shutdown();
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user