get rid of snapshots + was blocking stream and corrupted recordings

This commit is contained in:
Cedric Verstraeten
2023-12-07 21:33:32 +01:00
parent 8cfcfe4643
commit fd01fc640e
3 changed files with 56 additions and 44 deletions

View File

@@ -7,14 +7,10 @@ package capture
import "C"
import (
"bufio"
"bytes"
"context"
"encoding/base64"
"errors"
"fmt"
"image"
"image/jpeg"
"reflect"
"strconv"
"sync"
@@ -351,8 +347,6 @@ func (g *Golibrtsp) ConnectBackChannel(ctx context.Context) (err error) {
func (g *Golibrtsp) Start(ctx context.Context, queue *packets.Queue, configuration *models.Configuration, communication *models.Communication) (err error) {
log.Log.Debug("RTSPClient(Golibrtsp).Start(): started")
config := configuration.Config
// called when a MULAW audio RTP packet arrives
if g.AudioG711Media != nil {
g.Client.OnPacketRTP(g.AudioG711Media, g.AudioG711Forma, func(rtppkt *rtp.Packet) {
@@ -515,22 +509,6 @@ func (g *Golibrtsp) Start(ctx context.Context, queue *packets.Queue, configurati
queue.WritePacket(pkt)
// Store snapshots (jpg) for hull.
// We'll store the last snapshot, so we can use it for hull on the frontend.
// But we'll also store the last 10 snapshots, so we can use it for the timelapse.
if config.Capture.Snapshots != "false" {
image, err := g.DecodePacket(pkt)
if err == nil {
buffer := new(bytes.Buffer)
w := bufio.NewWriter(buffer)
err := jpeg.Encode(w, &image, &jpeg.Options{Quality: 15})
if err == nil {
snapshot := base64.StdEncoding.EncodeToString(buffer.Bytes())
communication.Image = snapshot
}
}
}
// This will check if we need to stop the thread,
// because of a reconfiguration.
select {
@@ -641,22 +619,6 @@ func (g *Golibrtsp) Start(ctx context.Context, queue *packets.Queue, configurati
queue.WritePacket(pkt)
// Store snapshots (jpg) for hull.
// We'll store the last snapshot, so we can use it for hull on the frontend.
// This will also be used to retrieve the last snapshot from the API.
if config.Capture.Snapshots != "false" {
image, err := g.DecodePacket(pkt)
if err == nil {
buffer := new(bytes.Buffer)
w := bufio.NewWriter(buffer)
err := jpeg.Encode(w, &image, &jpeg.Options{Quality: 15})
if err == nil {
snapshot := base64.StdEncoding.EncodeToString(buffer.Bytes())
communication.Image = snapshot
}
}
}
// This will check if we need to stop the thread,
// because of a reconfiguration.
select {

View File

@@ -7,6 +7,9 @@ import './ImageCanvas.css';
class ImageCanvas extends React.Component {
componentDidMount() {
this.width = 0;
this.height = 0;
this.loadImage = this.loadImage.bind(this);
this.generateRandomTagsDescriptor =
this.generateRandomTagsDescriptor.bind(this);
@@ -55,14 +58,27 @@ class ImageCanvas extends React.Component {
const { image } = this.props;
this.loadImage(image, (img) => {
this.loadData(img);
if (this.width !== img.width || this.height !== img.height) {
this.width = img.width;
this.height = img.height;
this.loadData(img);
} else {
this.editor.addContentSource(img);
}
});
}
componentDidUpdate() {
const { image } = this.props;
this.loadImage(image, (img) => {
this.loadData(img);
if (this.width !== img.width || this.height !== img.height) {
this.width = img.width;
this.height = img.height;
this.loadData(img);
} else {
// alert('ok');
this.editor.addContentSource(img);
}
});
}

View File

@@ -19,6 +19,8 @@ import {
} from '@kerberos-io/ui';
import { Link, withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import { interval } from 'rxjs';
import { send } from '@giantmachines/redux-websocket';
import ImageCanvas from '../../components/ImageCanvas/ImageCanvas';
import './Settings.scss';
import timezones from './timezones';
@@ -121,6 +123,7 @@ class Settings extends React.Component {
this.onUpdateToggle = this.onUpdateToggle.bind(this);
this.onUpdateNumberField = this.onUpdateNumberField.bind(this);
this.onUpdateTimeline = this.onUpdateTimeline.bind(this);
this.initialiseLiveview = this.initialiseLiveview.bind(this);
this.verifyPersistenceSettings = this.verifyPersistenceSettings.bind(this);
this.verifyHubSettings = this.verifyHubSettings.bind(this);
this.verifyCameraSettings = this.verifyCameraSettings.bind(this);
@@ -144,11 +147,18 @@ class Settings extends React.Component {
}));
this.calculateTimetable(config.timetable);
});
this.initialiseLiveview();
}
componentWillUnmount() {
document.removeEventListener('keydown', this.escFunction, false);
clearInterval(this.interval);
const { dispatchSend } = this.props;
const message = {
message_type: 'stop-sd',
};
dispatchSend(message);
}
onAddRegion(device, id, polygon) {
@@ -227,6 +237,24 @@ class Settings extends React.Component {
]);
}
initialiseLiveview() {
const message = {
message_type: 'stream-sd',
};
const { connected, dispatchSend } = this.props;
if (connected) {
dispatchSend(message);
}
const requestStreamInterval = interval(2000);
this.requestStreamSubscription = requestStreamInterval.subscribe(() => {
const { connected: isConnected } = this.props;
if (isConnected) {
dispatchSend(message);
}
});
}
calculateTimetable(timetable) {
this.timetable = timetable;
if (this.timetable) {
@@ -521,8 +549,8 @@ class Settings extends React.Component {
loadingHub,
} = this.state;
const { config: c, t } = this.props;
const { config, snapshot } = c;
const { config: c, t, images } = this.props;
const { config } = c;
const snapshotBase64 = 'data:image/png;base64,';
// Determine which section(s) to be shown, depending on the searching criteria.
@@ -1160,9 +1188,9 @@ class Settings extends React.Component {
</BlockHeader>
<BlockBody>
<p>{t('settings.conditions.description_regionofinterest')}</p>
{config.region && (
{config.region && images && images.length > 0 && (
<ImageCanvas
image={snapshotBase64 + snapshot}
image={snapshotBase64 + images[0]}
polygons={config.region.polygon}
rendered={false}
onAddRegion={this.onAddRegion}
@@ -2379,6 +2407,8 @@ class Settings extends React.Component {
const mapStateToProps = (state /* , ownProps */) => ({
config: state.agent.config,
connected: state.wss.connected,
images: state.wss.images,
});
const mapDispatchToProps = (dispatch /* , ownProps */) => ({
@@ -2397,11 +2427,14 @@ const mapDispatchToProps = (dispatch /* , ownProps */) => ({
dispatchAddRegion: (id, polygon) => dispatch(addRegion(id, polygon)),
dispatchRemoveRegion: (id, polygon) => dispatch(removeRegion(id, polygon)),
dispatchUpdateRegion: (id, polygon) => dispatch(updateRegion(id, polygon)),
dispatchSend: (message) => dispatch(send(message)),
});
Settings.propTypes = {
t: PropTypes.func.isRequired,
connected: PropTypes.bool.isRequired,
config: PropTypes.objectOf(PropTypes.object).isRequired,
images: PropTypes.array.isRequired,
dispatchVerifyHub: PropTypes.func.isRequired,
dispatchVerifyPersistence: PropTypes.func.isRequired,
dispatchGetConfig: PropTypes.func.isRequired,
@@ -2412,6 +2445,7 @@ Settings.propTypes = {
dispatchRemoveRegion: PropTypes.func.isRequired,
dispatchVerifyCamera: PropTypes.func.isRequired,
dispatchVerifyOnvif: PropTypes.func.isRequired,
dispatchSend: PropTypes.func.isRequired,
};
export default withTranslation()(