427 lines
12 KiB
C++
427 lines
12 KiB
C++
/***************************************************************************************
|
|
*
|
|
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
|
*
|
|
* By downloading, copying, installing or using the software you agree to this license.
|
|
* If you do not agree to this license, do not download, install,
|
|
* copy or use the software.
|
|
*
|
|
* Copyright (C) 2014-2022, Happytimesoft Corporation, all rights reserved.
|
|
*
|
|
* Redistribution and use in binary forms, with or without modification, are permitted.
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software distributed
|
|
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
|
|
* language governing permissions and limitations under the License.
|
|
*
|
|
****************************************************************************************/
|
|
|
|
#include "gb28181device.h"
|
|
#include "utils.h"
|
|
#include "video_capture_qt.h"
|
|
#include "gb28181.h"
|
|
#include "About.h"
|
|
#include "MediaSetting.h"
|
|
#include "ChannelSetting.h"
|
|
#include <QUrl>
|
|
#include <QCloseEvent>
|
|
#include <QCameraInfo>
|
|
#include <QMessageBox>
|
|
#include <QAndroidJniObject>
|
|
#include <QAndroidJniEnvironment>
|
|
#include <QDesktopServices>
|
|
#include <QtAndroid>
|
|
|
|
/**************************************************************************************/
|
|
|
|
QAndroidJniEnvironment g_env;
|
|
|
|
/**************************************************************************************/
|
|
|
|
GB28181Device::GB28181Device(QWidget *parent) :
|
|
QDialog(parent),
|
|
ui(new Ui::GB28181Device)
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
initDialog();
|
|
connSignalSlot();
|
|
|
|
CQVideoCapture::initJNI(g_env.operator _JNIEnv *());
|
|
|
|
QAndroidJniObject::callStaticMethod<void>("org/happytimesoft/gb28181device/GB28181DeviceActivity", "disableLockScreen");
|
|
|
|
requestPermission("android.permission.CAMERA");
|
|
requestPermission("android.permission.RECORD_AUDIO");
|
|
|
|
#ifdef DEMO
|
|
QMessageBox::information(this, tr("Tips"), tr("Happytime GB28181 Device DEMO version"));
|
|
#endif
|
|
}
|
|
|
|
GB28181Device::~GB28181Device()
|
|
{
|
|
QAndroidJniObject::callStaticMethod<void>("org/happytimesoft/gb28181device/GB28181DeviceActivity", "enableLockScreen");
|
|
|
|
#ifdef DEMO
|
|
QDesktopServices::openUrl(QUrl("http://www.happytimesoft.com/", QUrl::TolerantMode));
|
|
#endif
|
|
|
|
delete ui;
|
|
}
|
|
|
|
void GB28181Device::closeEvent(QCloseEvent * event)
|
|
{
|
|
if (QMessageBox::Yes == QMessageBox::question(this, tr("Quit"), tr("Are you sure want to quit?")))
|
|
{
|
|
event->accept();
|
|
}
|
|
else
|
|
{
|
|
event->ignore();
|
|
}
|
|
}
|
|
|
|
void GB28181Device::initDialog()
|
|
{
|
|
ui->cmbProtocol->addItem("UDP");
|
|
ui->cmbProtocol->addItem("TCP");
|
|
|
|
ui->cmbLogLevel->addItem("TRACE");
|
|
ui->cmbLogLevel->addItem("DEBUG");
|
|
ui->cmbLogLevel->addItem("INFO");
|
|
ui->cmbLogLevel->addItem("WARNING");
|
|
ui->cmbLogLevel->addItem("ERROR");
|
|
ui->cmbLogLevel->addItem("FATAL");
|
|
|
|
ui->editServerIp->setText(getServerIp());
|
|
ui->editServerPort->setText(QString("%1").arg(getServerPort()));
|
|
ui->editServerId->setText(getServerId());
|
|
ui->editServerDomain->setText(getServerDomain());
|
|
ui->editDeviceId->setText(getDeviceId());
|
|
ui->editDeviceName->setText(getDeviceName());
|
|
ui->editPassword->setText(getPassword());
|
|
ui->cmbProtocol->setCurrentIndex(getProtocol());
|
|
ui->editRegExpires->setText(QString("%1").arg(getRegExpires()));
|
|
ui->editHeartbeatInterval->setText(QString("%1").arg(getHeartbeatInterval()));
|
|
ui->editHeartbeatCount->setText(QString("%1").arg(getHeartbeatCount()));
|
|
ui->chkLogEnable->setChecked(getLogEnable());
|
|
ui->cmbLogLevel->setCurrentIndex(getLogLevel());
|
|
|
|
ui->btnStop->setEnabled(false);
|
|
ui->labStatus->setText(tr("Ready, ") + tr("Local IP : ") + get_local_ip());
|
|
}
|
|
|
|
void GB28181Device::connSignalSlot()
|
|
{
|
|
connect(ui->btnStart, SIGNAL(clicked()), this, SLOT(slotStart()));
|
|
connect(ui->btnStop, SIGNAL(clicked()), this, SLOT(slotStop()));
|
|
connect(ui->btnAbout, SIGNAL(clicked()), this, SLOT(slotAbout()));
|
|
connect(ui->btnMediaSetting, SIGNAL(clicked()), this, SLOT(slotMediaSetting()));
|
|
connect(ui->btnChannelSetting, SIGNAL(clicked()), this, SLOT(slotChannelSetting()));
|
|
}
|
|
|
|
void GB28181Device::slotMediaSetting()
|
|
{
|
|
MediaSetting dlg;
|
|
|
|
dlg.exec();
|
|
}
|
|
|
|
void GB28181Device::slotChannelSetting()
|
|
{
|
|
ChannelSetting dlg;
|
|
|
|
dlg.exec();
|
|
}
|
|
|
|
void GB28181Device::slotStart()
|
|
{
|
|
int nValue;
|
|
QString sValue;
|
|
|
|
memset(&g_gb28181_cfg, 0, sizeof(g_gb28181_cfg));
|
|
|
|
sValue = ui->editServerIp->text();
|
|
if (sValue.isEmpty())
|
|
{
|
|
QMessageBox::information(this, tr("Tips"), tr("Please input the server ip!"));
|
|
ui->editServerIp->setFocus();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
strncpy(g_gb28181_cfg.server_ip, sValue.toStdString().c_str(), sizeof(g_gb28181_cfg.server_ip)-1);
|
|
}
|
|
|
|
nValue = ui->editServerPort->text().toInt();
|
|
if (nValue <= 0 || nValue > 65535)
|
|
{
|
|
QMessageBox::information(this, tr("Tips"), tr("Invalid server port!"));
|
|
ui->editServerPort->setFocus();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
g_gb28181_cfg.server_port = nValue;
|
|
}
|
|
|
|
sValue = ui->editServerId->text();
|
|
if (sValue.isEmpty())
|
|
{
|
|
QMessageBox::information(this, tr("Tips"), tr("Please input the server id!"));
|
|
ui->editServerId->setFocus();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
strncpy(g_gb28181_cfg.server_id, sValue.toStdString().c_str(), sizeof(g_gb28181_cfg.server_id)-1);
|
|
}
|
|
|
|
sValue = ui->editServerDomain->text();
|
|
if (sValue.isEmpty())
|
|
{
|
|
QMessageBox::information(this, tr("Tips"), tr("Please input the server domain!"));
|
|
ui->editServerDomain->setFocus();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
strncpy(g_gb28181_cfg.server_domain, sValue.toStdString().c_str(), sizeof(g_gb28181_cfg.server_domain)-1);
|
|
}
|
|
|
|
sValue = ui->editDeviceId->text();
|
|
if (sValue.isEmpty())
|
|
{
|
|
QMessageBox::information(this, tr("Tips"), tr("Please input the device id!"));
|
|
ui->editDeviceId->setFocus();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
strncpy(g_gb28181_cfg.device_id, sValue.toStdString().c_str(), sizeof(g_gb28181_cfg.device_id)-1);
|
|
}
|
|
|
|
sValue = ui->editDeviceName->text();
|
|
if (sValue.isEmpty())
|
|
{
|
|
QMessageBox::information(this, tr("Tips"), tr("Please input the device name!"));
|
|
ui->editDeviceName->setFocus();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
strncpy(g_gb28181_cfg.device_name, sValue.toStdString().c_str(), sizeof(g_gb28181_cfg.device_name)-1);
|
|
}
|
|
|
|
sValue = ui->editPassword->text();
|
|
if (sValue.isEmpty())
|
|
{
|
|
QMessageBox::information(this, tr("Tips"), tr("Please input the password!"));
|
|
ui->editPassword->setFocus();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
strncpy(g_gb28181_cfg.password, sValue.toStdString().c_str(), sizeof(g_gb28181_cfg.password)-1);
|
|
}
|
|
|
|
g_gb28181_cfg.protocol = ui->cmbProtocol->currentIndex();
|
|
|
|
nValue = ui->editRegExpires->text().toInt();
|
|
if (nValue < 60)
|
|
{
|
|
QMessageBox::information(this, tr("Tips"), tr("Invalid reg expires!"));
|
|
ui->editRegExpires->setFocus();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
g_gb28181_cfg.reg_expires = nValue;
|
|
}
|
|
|
|
nValue = ui->editHeartbeatInterval->text().toInt();
|
|
if (nValue <= 0)
|
|
{
|
|
QMessageBox::information(this, tr("Tips"), tr("Invalid heartbeat interval!"));
|
|
ui->editHeartbeatInterval->setFocus();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
g_gb28181_cfg.heartbeat_interval = nValue;
|
|
}
|
|
|
|
nValue = ui->editHeartbeatCount->text().toInt();
|
|
if (nValue < 0)
|
|
{
|
|
QMessageBox::information(this, tr("Tips"), tr("Invalid heartbeat count!"));
|
|
ui->editHeartbeatCount->setFocus();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
g_gb28181_cfg.heartbeat_count = nValue;
|
|
}
|
|
|
|
g_gb28181_cfg.media_protocol = 1;
|
|
g_gb28181_cfg.media_base_port = 19000;
|
|
|
|
g_gb28181_cfg.log_enable = ui->chkLogEnable->isChecked();
|
|
|
|
g_gb28181_cfg.log_level = ui->cmbLogLevel->currentIndex();
|
|
|
|
if (g_gb28181_cfg.log_enable && requestPermission("android.permission.WRITE_EXTERNAL_STORAGE"))
|
|
{
|
|
log_init(GB28181_LOG_FILE);
|
|
log_set_level(g_gb28181_cfg.log_level);
|
|
}
|
|
else
|
|
{
|
|
log_close();
|
|
}
|
|
|
|
char media_url[256] = {'\0'};
|
|
|
|
int video = getVideoFlag();
|
|
int audio = getAudioFlag();
|
|
int cameraidx = getCameraIndex();
|
|
|
|
if (video && audio)
|
|
{
|
|
if (cameraidx > 0)
|
|
{
|
|
sprintf(media_url, "videodevice%d+audiodevice", cameraidx);
|
|
}
|
|
else
|
|
{
|
|
sprintf(media_url, "videodevice+audiodevice");
|
|
}
|
|
}
|
|
else if (video)
|
|
{
|
|
if (cameraidx > 0)
|
|
{
|
|
sprintf(media_url, "videodevice%d", cameraidx);
|
|
}
|
|
else
|
|
{
|
|
sprintf(media_url, "videodevice");
|
|
}
|
|
}
|
|
else if (audio)
|
|
{
|
|
sprintf(media_url, "audiodevice");
|
|
}
|
|
else
|
|
{
|
|
QMessageBox::information(this, tr("Tips"), tr("Please check video or audio."));
|
|
return;
|
|
}
|
|
|
|
QSize size = getResolution();
|
|
|
|
GBCHANNEL * p_channel = &g_gb28181_cfg.channels[0];
|
|
|
|
strcpy(p_channel->media_url, media_url);
|
|
|
|
p_channel->output.video.codec = getVideoCodec();
|
|
p_channel->output.video.width = size.width();
|
|
p_channel->output.video.height = size.height();
|
|
p_channel->output.video.framerate = getFrameRate();
|
|
p_channel->output.video.bitrate = getVideoBitrate();
|
|
|
|
p_channel->output.audio.codec = getAudioCodec();
|
|
p_channel->output.audio.samplerate = getSampleRate();
|
|
p_channel->output.audio.channels = getChannel();
|
|
p_channel->output.audio.bitrate = getAudioBitrate();
|
|
|
|
int i;
|
|
QList<GBCHANNEL> channels;
|
|
|
|
if (!getChannels(channels) || channels.size() == 0)
|
|
{
|
|
// add default channel
|
|
strcpy(g_gb28181_cfg.channels[0].cid, "34020000001310000001");
|
|
strcpy(g_gb28181_cfg.channels[0].cname, "channel1");
|
|
g_gb28181_cfg.channel_nums = 1;
|
|
}
|
|
|
|
for (i = 0; i < channels.size() && i < MAX_CH_NUMS; i++)
|
|
{
|
|
strcpy(g_gb28181_cfg.channels[i].cid, channels[i].cid);
|
|
strcpy(g_gb28181_cfg.channels[i].cname, channels[i].cname);
|
|
|
|
g_gb28181_cfg.channel_nums++;
|
|
}
|
|
|
|
for (i = 1; i < g_gb28181_cfg.channel_nums; i++)
|
|
{
|
|
strcpy(g_gb28181_cfg.channels[i].media_url, g_gb28181_cfg.channels[0].media_url);
|
|
memcpy(&g_gb28181_cfg.channels[i].output, &g_gb28181_cfg.channels[0].output, sizeof(MEDIA_INFO));
|
|
}
|
|
|
|
saveServerIp(g_gb28181_cfg.server_ip);
|
|
saveServerPort(g_gb28181_cfg.server_port);
|
|
saveServerId(g_gb28181_cfg.server_id);
|
|
saveServerDomain(g_gb28181_cfg.server_domain);
|
|
saveDeviceId(g_gb28181_cfg.device_id);
|
|
saveDeviceName(g_gb28181_cfg.device_name);
|
|
savePassword(g_gb28181_cfg.password);
|
|
saveProtocol(g_gb28181_cfg.protocol);
|
|
saveRegExpires(g_gb28181_cfg.reg_expires);
|
|
saveHeartbeatInterval(g_gb28181_cfg.heartbeat_interval);
|
|
saveHeartbeatCount(g_gb28181_cfg.heartbeat_count);
|
|
saveLogEnable(g_gb28181_cfg.log_enable);
|
|
saveLogLevel(g_gb28181_cfg.log_level);
|
|
|
|
if (gb28181_start1())
|
|
{
|
|
ui->labStatus->setText(tr("Started"));
|
|
|
|
ui->btnStart->setEnabled(false);
|
|
ui->btnStop->setEnabled(true);
|
|
}
|
|
else
|
|
{
|
|
ui->labStatus->setText(tr("Start failed"));
|
|
}
|
|
}
|
|
|
|
void GB28181Device::slotStop()
|
|
{
|
|
gb28181_stop();
|
|
|
|
ui->btnStart->setEnabled(true);
|
|
ui->btnStop->setEnabled(false);
|
|
|
|
ui->labStatus->setText(tr("Ready, ") + tr("Local IP : ") + get_local_ip());
|
|
}
|
|
|
|
void GB28181Device::slotAbout()
|
|
{
|
|
About dlg;
|
|
|
|
dlg.exec();
|
|
}
|
|
|
|
bool GB28181Device::requestPermission(QString permission)
|
|
{
|
|
QtAndroid::PermissionResult r = QtAndroid::checkPermission(permission);
|
|
if (r == QtAndroid::PermissionResult::Denied)
|
|
{
|
|
QtAndroid::requestPermissionsSync(QStringList() << permission);
|
|
r = QtAndroid::checkPermission(permission);
|
|
if (r == QtAndroid::PermissionResult::Denied)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|