moer cppcheck fixes

This commit is contained in:
Isaac Connor 2017-11-17 07:52:26 -05:00
parent 22ff831859
commit 159c0a7165
22 changed files with 178 additions and 322 deletions

View File

@ -526,19 +526,19 @@ int cURLCamera::progress_callback(void *userdata, double dltotal, double dlnow,
/* These functions call the functions in the class for the correct object */
size_t data_callback_dispatcher(void *buffer, size_t size, size_t nmemb, void *userdata) {
return ((cURLCamera*)userdata)->data_callback(buffer,size,nmemb,userdata);
return reinterpret_cast<cURLCamera*>(userdata)->data_callback(buffer,size,nmemb,userdata);
}
size_t header_callback_dispatcher(void *buffer, size_t size, size_t nmemb, void *userdata) {
return ((cURLCamera*)userdata)->header_callback(buffer,size,nmemb,userdata);
return reinterpret_cast<cURLCamera*>(userdata)->header_callback(buffer,size,nmemb,userdata);
}
int progress_callback_dispatcher(void *userdata, double dltotal, double dlnow, double ultotal, double ulnow) {
return ((cURLCamera*)userdata)->progress_callback(userdata,dltotal,dlnow,ultotal,ulnow);
return reinterpret_cast<cURLCamera*>(userdata)->progress_callback(userdata,dltotal,dlnow,ultotal,ulnow);
}
void* thread_func_dispatcher(void* object) {
return ((cURLCamera*)object)->thread_func();
return reinterpret_cast<cURLCamera*>(object)->thread_func();
}
#endif // HAVE_LIBCURL

View File

@ -241,11 +241,11 @@ Event::~Event() {
void Event::createNotes( std::string &notes ) {
notes.clear();
for ( StringSetMap::const_iterator mapIter = noteSetMap.begin(); mapIter != noteSetMap.end(); mapIter++ ) {
for ( StringSetMap::const_iterator mapIter = noteSetMap.begin(); mapIter != noteSetMap.end(); ++mapIter ) {
notes += mapIter->first;
notes += ": ";
const StringSet &stringSet = mapIter->second;
for ( StringSet::const_iterator setIter = stringSet.begin(); setIter != stringSet.end(); setIter++ ) {
for ( StringSet::const_iterator setIter = stringSet.begin(); setIter != stringSet.end(); ++setIter ) {
if ( setIter != stringSet.begin() )
notes += ", ";
notes += *setIter;
@ -316,7 +316,7 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap ) {
noteSetMap = newNoteSetMap;
update = true;
} else {
for ( StringSetMap::const_iterator newNoteSetMapIter = newNoteSetMap.begin(); newNoteSetMapIter != newNoteSetMap.end(); newNoteSetMapIter++ ) {
for ( StringSetMap::const_iterator newNoteSetMapIter = newNoteSetMap.begin(); newNoteSetMapIter != newNoteSetMap.end(); ++newNoteSetMapIter ) {
const std::string &newNoteGroup = newNoteSetMapIter->first;
const StringSet &newNoteSet = newNoteSetMapIter->second;
//Info( "Got %d new strings", newNoteSet.size() );
@ -329,7 +329,7 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap ) {
} else {
StringSet &noteSet = noteSetMapIter->second;
//Info( "Found note group %s, got %d strings", newNoteGroup.c_str(), newNoteSet.size() );
for ( StringSet::const_iterator newNoteSetIter = newNoteSet.begin(); newNoteSetIter != newNoteSet.end(); newNoteSetIter++ ) {
for ( StringSet::const_iterator newNoteSetIter = newNoteSet.begin(); newNoteSetIter != newNoteSet.end(); ++newNoteSetIter ) {
const std::string &newNote = *newNoteSetIter;
StringSet::iterator noteSetIter = noteSet.find( newNote );
if ( noteSetIter == noteSet.end() ) {
@ -390,7 +390,6 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap ) {
}
strncpy( notesStr, notes.c_str(), sizeof(notesStr) );
notesLen = notes.length();
if ( mysql_stmt_execute( stmt ) ) {
Fatal( "Unable to execute sql '%s': %s", sql, mysql_stmt_error(stmt) );

View File

@ -176,13 +176,13 @@ bool EventStream::loadEventData( int event_id ) {
event_data->n_frames = mysql_num_rows( result );
event_data->frames = new FrameData[event_data->frame_count];
int id, last_id = 0;
int last_id = 0;
time_t timestamp, last_timestamp = event_data->start_time;
double delta, last_delta = 0.0;
double last_delta = 0.0;
while ( ( dbrow = mysql_fetch_row( result ) ) ) {
id = atoi(dbrow[0]);
int id = atoi(dbrow[0]);
timestamp = atoi(dbrow[1]);
delta = atof(dbrow[2]);
double delta = atof(dbrow[2]);
int id_diff = id - last_id;
double frame_delta = (delta-last_delta)/id_diff;
if ( id_diff > 1 ) {
@ -414,7 +414,6 @@ void EventStream::processCommand( const CmdMsg *msg ) {
}
send_frame = true;
break;
send_frame = true;
}
case CMD_PAN :
{

View File

@ -97,6 +97,7 @@ class EventStream : public StreamBase {
curr_frame_id = 0;
curr_stream_time = 0.0;
send_frame = false;
event_data = 0;

View File

@ -109,8 +109,6 @@ int av_dict_parse_string(AVDictionary **pm, const char *str,
const char *key_val_sep, const char *pairs_sep,
int flags)
{
int ret;
if (!str)
return 0;
@ -118,7 +116,7 @@ int av_dict_parse_string(AVDictionary **pm, const char *str,
flags &= ~(AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
while (*str) {
if ((ret = parse_key_value_pair(pm, &str, key_val_sep, pairs_sep, flags)) < 0)
if ((int ret = parse_key_value_pair(pm, &str, key_val_sep, pairs_sep, flags)) < 0)
return ret;
if (*str)

View File

@ -205,7 +205,6 @@ int FfmpegCamera::Capture( Image &image ) {
int frameComplete = false;
while ( !frameComplete ) {
int ret;
int avResult = av_read_frame( mFormatContext, &packet );
char errbuf[AV_ERROR_MAX_STRING_SIZE];
if ( avResult < 0 ) {
@ -231,6 +230,7 @@ int FfmpegCamera::Capture( Image &image ) {
Debug( 5, "Got packet from stream %d dts (%d) pts(%d)", packet.stream_index, packet.pts, packet.dts );
// What about audio stream? Maybe someday we could do sound detection...
if ( ( packet.stream_index == mVideoStreamId ) && ( keyframe || have_video_keyframe ) ) {
int ret;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
ret = avcodec_send_packet( mVideoCodecContext, &packet );
if ( ret < 0 ) {
@ -838,7 +838,6 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
videoStore = NULL;
} else {
strcpy(oldDirectory, event_file);
monitor->SetVideoWriterEventId( last_event_id );
// Need to write out all the frames from the last keyframe?

View File

@ -85,7 +85,6 @@ class FfmpegCamera : public Camera {
#endif // HAVE_LIBAVFORMAT
VideoStore *videoStore;
char oldDirectory[4096];
unsigned int old_event_id;
zm_packetqueue packetqueue;
bool have_video_keyframe;

View File

@ -457,7 +457,6 @@ void Image::Initialise() {
/* Requests a writeable buffer to the image. This is safer than buffer() because this way we can guarantee that a buffer of required size exists */
uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder) {
unsigned int newsize;
if ( p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32 ) {
Error("WriteBuffer called with unexpected colours: %d",p_colours);
@ -470,7 +469,7 @@ uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_hei
}
if ( p_width != width || p_height != height || p_colours != colours || p_subpixelorder != subpixelorder ) {
newsize = (p_width * p_height) * p_colours;
unsigned int newsize = (p_width * p_height) * p_colours;
if ( buffer == NULL ) {
AllocImgBuffer(newsize);
@ -2102,8 +2101,8 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
void Image::Timestamp( const char *label, const time_t when, const Coord &coord, const int size ) {
char time_text[64];
strftime( time_text, sizeof(time_text), "%y/%m/%d %H:%M:%S", localtime( &when ) );
char text[64];
if ( label ) {
char text[64];
snprintf( text, sizeof(text), "%s - %s", label, time_text );
Annotate( text, coord, size );
} else {
@ -2625,8 +2624,7 @@ void Image::Rotate( int angle )
unsigned int new_width = width;
uint8_t* rotate_buffer = AllocBuffer(size);
switch( angle )
{
switch( angle ) {
case 90 :
{
new_height = width;
@ -2635,41 +2633,27 @@ void Image::Rotate( int angle )
unsigned int line_bytes = new_width*colours;
unsigned char *s_ptr = buffer;
if ( colours == ZM_COLOUR_GRAY8 )
{
unsigned char *d_ptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_ptr = rotate_buffer+(i-1);
for ( unsigned int j = new_height; j > 0; j-- )
{
if ( colours == ZM_COLOUR_GRAY8 ) {
for ( unsigned int i = new_width; i > 0; i-- ) {
unsigned char *d_ptr = rotate_buffer+(i-1);
for ( unsigned int j = new_height; j > 0; j-- ) {
*d_ptr = *s_ptr++;
d_ptr += line_bytes;
}
}
}
else if ( colours == ZM_COLOUR_RGB32 )
{
} else if ( colours == ZM_COLOUR_RGB32 ) {
Rgb* s_rptr = (Rgb*)s_ptr;
Rgb* d_rptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2));
for ( unsigned int j = new_height; j > 0; j-- )
{
for ( unsigned int i = new_width; i > 0; i-- ) {
Rgb* d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2));
for ( unsigned int j = new_height; j > 0; j-- ) {
*d_rptr = *s_rptr++;
d_rptr += new_width;
}
}
}
else /* Assume RGB24 */
{
unsigned char *d_ptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_ptr = rotate_buffer+((i-1)*3);
for ( unsigned int j = new_height; j > 0; j-- )
{
} else /* Assume RGB24 */ {
for ( unsigned int i = new_width; i > 0; i-- ) {
unsigned char *d_ptr = rotate_buffer+((i-1)*3);
for ( unsigned int j = new_height; j > 0; j-- ) {
*d_ptr = *s_ptr++;
*(d_ptr+1) = *s_ptr++;
*(d_ptr+2) = *s_ptr++;
@ -2684,28 +2668,20 @@ void Image::Rotate( int angle )
unsigned char *s_ptr = buffer+size;
unsigned char *d_ptr = rotate_buffer;
if ( colours == ZM_COLOUR_GRAY8 )
{
while( s_ptr > buffer )
{
if ( colours == ZM_COLOUR_GRAY8 ) {
while( s_ptr > buffer ) {
s_ptr--;
*d_ptr++ = *s_ptr;
}
}
else if ( colours == ZM_COLOUR_RGB32 )
{
} else if ( colours == ZM_COLOUR_RGB32 ) {
Rgb* s_rptr = (Rgb*)s_ptr;
Rgb* d_rptr = (Rgb*)d_ptr;
while( s_rptr > (Rgb*)buffer )
{
while( s_rptr > (Rgb*)buffer ) {
s_rptr--;
*d_rptr++ = *s_rptr;
}
}
else /* Assume RGB24 */
{
while( s_ptr > buffer )
{
} else /* Assume RGB24 */ {
while( s_ptr > buffer ) {
s_ptr -= 3;
*d_ptr++ = *s_ptr;
*d_ptr++ = *(s_ptr+1);
@ -2722,43 +2698,29 @@ void Image::Rotate( int angle )
unsigned int line_bytes = new_width*colours;
unsigned char *s_ptr = buffer+size;
if ( colours == ZM_COLOUR_GRAY8 )
{
unsigned char *d_ptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_ptr = rotate_buffer+(i-1);
for ( unsigned int j = new_height; j > 0; j-- )
{
if ( colours == ZM_COLOUR_GRAY8 ) {
for ( unsigned int i = new_width; i > 0; i-- ) {
unsigned char *d_ptr = rotate_buffer+(i-1);
for ( unsigned int j = new_height; j > 0; j-- ) {
s_ptr--;
*d_ptr = *s_ptr;
d_ptr += line_bytes;
}
}
}
else if ( colours == ZM_COLOUR_RGB32 )
{
} else if ( colours == ZM_COLOUR_RGB32 ) {
Rgb* s_rptr = (Rgb*)s_ptr;
Rgb* d_rptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2));
for ( unsigned int j = new_height; j > 0; j-- )
{
for ( unsigned int i = new_width; i > 0; i-- ) {
Rgb* d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2));
for ( unsigned int j = new_height; j > 0; j-- ) {
s_rptr--;
*d_rptr = *s_rptr;
d_rptr += new_width;
}
}
}
else /* Assume RGB24 */
{
unsigned char *d_ptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_ptr = rotate_buffer+((i-1)*3);
for ( unsigned int j = new_height; j > 0; j-- )
{
} else /* Assume RGB24 */ {
for ( unsigned int i = new_width; i > 0; i-- ) {
unsigned char *d_ptr = rotate_buffer+((i-1)*3);
for ( unsigned int j = new_height; j > 0; j-- ) {
*(d_ptr+2) = *(--s_ptr);
*(d_ptr+1) = *(--s_ptr);
*d_ptr = *(--s_ptr);
@ -2771,18 +2733,15 @@ void Image::Rotate( int angle )
}
AssignDirect( new_width, new_height, colours, subpixelorder, rotate_buffer, size, ZM_BUFTYPE_ZM);
}
/* RGB32 compatible: complete */
void Image::Flip( bool leftright )
{
void Image::Flip( bool leftright ) {
uint8_t* flip_buffer = AllocBuffer(size);
unsigned int line_bytes = width*colours;
unsigned int line_bytes2 = 2*line_bytes;
if ( leftright )
{
if ( leftright ) {
// Horizontal flip, left to right
unsigned char *s_ptr = buffer+line_bytes;
unsigned char *d_ptr = flip_buffer;

View File

@ -276,8 +276,7 @@ static boolean fill_input_buffer (j_decompress_ptr cinfo)
memcpy( src->buffer, src->inbuffer, (size_t) src->inbuffer_size );
nbytes = src->inbuffer_size;
if ( nbytes <= 0 )
{
if ( nbytes == 0 ) {
if ( src->start_of_data ) /* Treat empty input file as fatal error */
ERREXIT(cinfo, JERR_INPUT_EMPTY);
WARNMS(cinfo, JWRN_JPEG_EOF);

View File

@ -1579,20 +1579,20 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
sprintf( output+strlen(output), "Video Capabilities\n" );
sprintf( output+strlen(output), " Name: %s\n", vid_cap.name );
sprintf( output+strlen(output), " Type: %d\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s", vid_cap.type,
vid_cap.type&VID_TYPE_CAPTURE?" Can capture\n":"",
vid_cap.type&VID_TYPE_TUNER?" Can tune\n":"",
vid_cap.type&VID_TYPE_TELETEXT?" Does teletext\n":"",
vid_cap.type&VID_TYPE_OVERLAY?" Overlay onto frame buffer\n":"",
vid_cap.type&VID_TYPE_CHROMAKEY?" Overlay by chromakey\n":"",
vid_cap.type&VID_TYPE_CLIPPING?" Can clip\n":"",
vid_cap.type&VID_TYPE_FRAMERAM?" Uses the frame buffer memory\n":"",
vid_cap.type&VID_TYPE_SCALES?" Scalable\n":"",
vid_cap.type&VID_TYPE_MONOCHROME?" Monochrome only\n":"",
vid_cap.type&VID_TYPE_SUBCAPTURE?" Can capture subareas of the image\n":"",
vid_cap.type&VID_TYPE_MPEG_DECODER?" Can decode MPEG streams\n":"",
vid_cap.type&VID_TYPE_MPEG_ENCODER?" Can encode MPEG streams\n":"",
vid_cap.type&VID_TYPE_MJPEG_DECODER?" Can decode MJPEG streams\n":"",
vid_cap.type&VID_TYPE_MJPEG_ENCODER?" Can encode MJPEG streams\n":""
(vid_cap.type&VID_TYPE_CAPTURE)?" Can capture\n":"",
(vid_cap.type&VID_TYPE_TUNER)?" Can tune\n":"",
(vid_cap.type&VID_TYPE_TELETEXT)?" Does teletext\n":"",
(vid_cap.type&VID_TYPE_OVERLAY)?" Overlay onto frame buffer\n":"",
(vid_cap.type&VID_TYPE_CHROMAKEY)?" Overlay by chromakey\n":"",
(vid_cap.type&VID_TYPE_CLIPPING)?" Can clip\n":"",
(vid_cap.type&VID_TYPE_FRAMERAM)?" Uses the frame buffer memory\n":"",
(vid_cap.type&VID_TYPE_SCALES)?" Scalable\n":"",
(vid_cap.type&VID_TYPE_MONOCHROME)?" Monochrome only\n":"",
(vid_cap.type&VID_TYPE_SUBCAPTURE)?" Can capture subareas of the image\n":"",
(vid_cap.type&VID_TYPE_MPEG_DECODER)?" Can decode MPEG streams\n":"",
(vid_cap.type&VID_TYPE_MPEG_ENCODER)?" Can encode MPEG streams\n":"",
(vid_cap.type&VID_TYPE_MJPEG_DECODER)?" Can decode MJPEG streams\n":"",
(vid_cap.type&VID_TYPE_MJPEG_ENCODER)?" Can encode MJPEG streams\n":""
);
sprintf( output+strlen(output), " Video Channels: %d\n", vid_cap.channels );
sprintf( output+strlen(output), " Audio Channels: %d\n", vid_cap.audios );

View File

@ -184,7 +184,7 @@ void Logger::initialise( const std::string &id, const Options &options ) {
StringVector targets = split( config.log_debug_target, "|" );
for ( unsigned int i = 0; i < targets.size(); i++ ) {
const std::string &target = targets[i];
if ( target == mId || target == "_"+mId || target == "_"+mIdRoot || target == "_"+mIdRoot || target == "" ) {
if ( target == mId || target == "_"+mId || target == "_"+mIdRoot || target == "" ) {
if ( config.log_debug_level > NOLOG ) {
tempLevel = config.log_debug_level;
if ( config.log_debug_file[0] ) {
@ -277,11 +277,10 @@ std::string Logger::strEnv( const std::string &name, const std::string &defaultV
}
char *Logger::getTargettedEnv( const std::string &name ) {
char *envPtr = NULL;
std::string envName;
envName = name+"_"+mId;
envPtr = getenv( envName.c_str() );
char *envPtr = getenv( envName.c_str() );
if ( !envPtr && mId != mIdRoot ) {
envName = name+"_"+mIdRoot;
envPtr = getenv( envName.c_str() );

View File

@ -88,7 +88,7 @@ void VideoStream::SetupFormat( ) {
if (s->oformat->priv_data_size > 0) {
s->priv_data = av_mallocz(s->oformat->priv_data_size);
if (!s->priv_data) {
if ( !(s->priv_data) ) {
Fatal( "Could not allocate private data for output format." );
}
#if LIBAVFORMAT_VERSION_CHECK(52, 92, 0, 92, 0)
@ -286,19 +286,19 @@ const char *VideoStream::MimeType( ) const {
}
void VideoStream::OpenStream( ) {
int avRet;
int ret;
/* now that all the parameters are set, we can open the
video codecs and allocate the necessary encode buffers */
if ( ost ) {
/* open the codec */
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
if ( (avRet = avcodec_open( codec_context, codec )) < 0 )
if ( (ret = avcodec_open( codec_context, codec )) < 0 )
#else
if ( (avRet = avcodec_open2( codec_context, codec, 0 )) < 0 )
if ( (ret = avcodec_open2( codec_context, codec, 0 )) < 0 )
#endif
{
Fatal( "Could not open codec. Error code %d \"%s\"", avRet, av_err2str( avRet ) );
Fatal( "Could not open codec. Error code %d \"%s\"", ret, av_err2str(ret) );
}
Debug( 1, "Opened codec" );
@ -364,7 +364,6 @@ void VideoStream::OpenStream( ) {
/* open the output file, if needed */
if ( !(of->flags & AVFMT_NOFILE) ) {
int ret;
#if LIBAVFORMAT_VERSION_CHECK(53, 15, 0, 21, 0)
ret = avio_open2( &ofc->pb, filename, AVIO_FLAG_WRITE, NULL, NULL );
#elif LIBAVFORMAT_VERSION_CHECK(52, 102, 0, 102, 0)
@ -405,9 +404,9 @@ void VideoStream::OpenStream( ) {
#endif
#if !LIBAVFORMAT_VERSION_CHECK(53, 2, 0, 4, 0)
int ret = av_write_header( ofc );
ret = av_write_header( ofc );
#else
int ret = avformat_write_header( ofc, NULL );
ret = avformat_write_header( ofc, NULL );
#endif
if ( ret < 0 ) {

View File

@ -25,6 +25,8 @@
using namespace std;
ZMPacket::ZMPacket( AVPacket *p ) {
frame = NULL;
image = NULL;
av_init_packet( &packet );
if ( zm_av_packet_ref( &packet, p ) < 0 ) {
Error("error refing packet");
@ -33,6 +35,8 @@ ZMPacket::ZMPacket( AVPacket *p ) {
}
ZMPacket::ZMPacket( AVPacket *p, struct timeval *t ) {
frame = NULL;
image = NULL;
av_init_packet( &packet );
if ( zm_av_packet_ref( &packet, p ) < 0 ) {
Error("error refing packet");

View File

@ -42,7 +42,9 @@ RemoteCamera::RemoteCamera(
host( p_host ),
port( p_port ),
path( p_path ),
hp( 0 )
hp( 0 ),
mNeedAuth(false),
mAuthenticator(NULL)
{
if ( path[0] != '/' )
path = '/'+path;
@ -97,14 +99,13 @@ void RemoteCamera::Initialise() {
int RemoteCamera::Read( int fd, char *buf, int size ) {
int ReceivedBytes = 0;
int bytes;
while ( ReceivedBytes < size ) {
// recv blocks until we get data, but it may be of ARBITRARY LENGTH and INCOMPLETE
int bytes_to_recv = size - ReceivedBytes;
if ( SOCKET_BUF_SIZE < bytes_to_recv )
bytes_to_recv = SOCKET_BUF_SIZE;
//Debug(3, "Aiming to receive %d of %d bytes", bytes_to_recv, size );
bytes = recv(fd, &buf[ReceivedBytes], bytes_to_recv, 0); //socket, buffer, len, flags
int bytes = recv(fd, &buf[ReceivedBytes], bytes_to_recv, 0); //socket, buffer, len, flags
if ( bytes <= 0 ) {
Error("RemoteCamera::Read Recv error. Closing Socket\n");
return -1;

View File

@ -588,10 +588,6 @@ int RemoteCameraHttp::GetResponse()
else
#endif // HAVE_LIBPCRE
{
if ( method == REGEXP )
{
Warning( "Unable to use netcam regexps as not compiled with libpcre" );
}
static const char *http_match = "HTTP/";
static const char *connection_match = "Connection:";
static const char *content_length_match = "Content-length:";

View File

@ -332,7 +332,7 @@ int RtpCtrlThread::run()
timeout = false;
last_receive = time(NULL);
}
for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); iter++ )
for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); ++iter )
{
if ( UdpInetSocket *socket = dynamic_cast<UdpInetSocket *>(*iter) )
{

View File

@ -94,7 +94,7 @@ int RtpDataThread::run()
mStop = true;
break;
}
for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); iter++ )
for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); ++iter )
{
if ( UdpInetServer *socket = dynamic_cast<UdpInetServer *>(*iter) )
{

View File

@ -36,8 +36,7 @@ int RtspThread::smMinDataPort = 0;
int RtspThread::smMaxDataPort = 0;
RtspThread::PortSet RtspThread::smAssignedPorts;
bool RtspThread::sendCommand( std::string message )
{
bool RtspThread::sendCommand( std::string message ) {
if ( mNeedAuth ) {
StringVector parts = split( message, " " );
if (parts.size() > 1)
@ -46,20 +45,15 @@ bool RtspThread::sendCommand( std::string message )
message += stringtf( "User-Agent: ZoneMinder/%s\r\n", ZM_VERSION );
message += stringtf( "CSeq: %d\r\n\r\n", ++mSeq );
Debug( 2, "Sending RTSP message: %s", message.c_str() );
if ( mMethod == RTP_RTSP_HTTP )
{
if ( mMethod == RTP_RTSP_HTTP ) {
message = base64Encode( message );
Debug( 2, "Sending encoded RTSP message: %s", message.c_str() );
if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() )
{
if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() ) {
Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) );
return( false );
}
}
else
{
if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() )
{
} else {
if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() ) {
Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) );
return( false );
}
@ -67,77 +61,60 @@ bool RtspThread::sendCommand( std::string message )
return( true );
}
bool RtspThread::recvResponse( std::string &response )
{
bool RtspThread::recvResponse( std::string &response ) {
if ( mRtspSocket.recv( response ) < 0 )
Error( "Recv failed; %s", strerror(errno) );
Debug( 2, "Received RTSP response: %s (%zd bytes)", response.c_str(), response.size() );
float respVer = 0;
respCode = -1;
char respText[ZM_NETWORK_BUFSIZ];
if ( sscanf( response.c_str(), "RTSP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 )
{
if ( isalnum(response[0]) )
{
if ( sscanf( response.c_str(), "RTSP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 ) {
if ( isalnum(response[0]) ) {
Error( "Response parse failure in '%s'", response.c_str() );
}
else
{
} else {
Error( "Response parse failure, %zd bytes follow", response.size() );
if ( response.size() )
Hexdump( Logger::ERROR, response.data(), min(response.size(),16) );
}
return( false );
}
if ( respCode == 401)
{
if ( respCode == 401) {
Debug( 2, "Got 401 access denied response code, check WWW-Authenticate header and retry");
mAuthenticator->checkAuthResponse(response);
mNeedAuth = true;
return( false );
}
else if ( respCode != 200 )
{
} else if ( respCode != 200 ) {
Error( "Unexpected response code %d, text is '%s'", respCode, respText );
return( false );
}
return( true );
}
int RtspThread::requestPorts()
{
if ( !smMinDataPort )
{
int RtspThread::requestPorts() {
if ( !smMinDataPort ) {
char sql[ZM_SQL_SML_BUFSIZ];
strncpy( sql, "select Id from Monitors where Function != 'None' and Type = 'Remote' and Protocol = 'rtsp' and Method = 'rtpUni' order by Id asc", sizeof(sql) );
if ( mysql_query( &dbconn, sql ) )
{
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
MYSQL_RES *result = mysql_store_result( &dbconn );
if ( !result )
{
if ( !result ) {
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
int nMonitors = mysql_num_rows( result );
int position = 0;
if ( nMonitors )
{
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ )
{
if ( nMonitors ) {
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) {
int id = atoi(dbrow[0]);
if ( mId == id )
{
if ( mId == id ) {
position = i;
break;
}
}
}
else
{
} else {
// Minor hack for testing when not strictly enabled
nMonitors = 1;
position = 0;
@ -148,11 +125,9 @@ int RtspThread::requestPorts()
smMaxDataPort = smMinDataPort + portRange - 1;
Debug( 2, "Assigned RTP port range is %d-%d", smMinDataPort, smMaxDataPort );
}
for ( int i = smMinDataPort; i <= smMaxDataPort; i++ )
{
for ( int i = smMinDataPort; i <= smMaxDataPort; i++ ) {
PortSet::const_iterator iter = smAssignedPorts.find( i );
if ( iter == smAssignedPorts.end() )
{
if ( iter == smAssignedPorts.end() ) {
smAssignedPorts.insert( i );
return( i );
}
@ -161,8 +136,7 @@ int RtspThread::requestPorts()
return( -1 );
}
void RtspThread::releasePorts( int port )
{
void RtspThread::releasePorts( int port ) {
if ( port > 0 )
smAssignedPorts.erase( port );
}
@ -185,8 +159,7 @@ RtspThread::RtspThread( int id, RtspMethod method, const std::string &protocol,
mStop( false )
{
mUrl = mProtocol+"://"+mHost+":"+mPort;
if ( !mPath.empty() )
{
if ( !mPath.empty() ) {
if ( mPath[0] == '/' )
mUrl += mPath;
else
@ -208,10 +181,8 @@ RtspThread::RtspThread( int id, RtspMethod method, const std::string &protocol,
mAuthenticator = new zm::Authenticator(parts[0], "");
}
RtspThread::~RtspThread()
{
if ( mFormatContext )
{
RtspThread::~RtspThread() {
if ( mFormatContext ) {
#if LIBAVFORMAT_VERSION_CHECK(52, 96, 0, 96, 0)
avformat_free_context( mFormatContext );
#else
@ -219,16 +190,14 @@ RtspThread::~RtspThread()
#endif
mFormatContext = NULL;
}
if ( mSessDesc )
{
if ( mSessDesc ) {
delete mSessDesc;
mSessDesc = NULL;
}
delete mAuthenticator;
}
int RtspThread::run()
{
int RtspThread::run() {
std::string message;
std::string response;
@ -246,8 +215,7 @@ int RtspThread::run()
bool authTried = false;
if ( mMethod == RTP_RTSP_HTTP )
{
if ( mMethod == RTP_RTSP_HTTP ) {
if ( !mRtspSocket2.connect( mHost.c_str(), mPort.c_str() ) )
Fatal( "Unable to connect auxiliary RTSP/HTTP socket" );
//Select select( 0.25 );
@ -271,13 +239,11 @@ int RtspThread::run()
message += "Accept: application/x-rtsp-tunnelled\r\n";
message += "\r\n";
Debug( 2, "Sending HTTP message: %s", message.c_str() );
if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() )
{
if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() ) {
Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) );
return( -1 );
}
if ( mRtspSocket.recv( response ) < 0 )
{
if ( mRtspSocket.recv( response ) < 0 ) {
Error( "Recv failed; %s", strerror(errno) );
return( -1 );
}
@ -285,14 +251,10 @@ int RtspThread::run()
Debug( 2, "Received HTTP response: %s (%zd bytes)", response.c_str(), response.size() );
float respVer = 0;
respCode = -1;
if ( sscanf( response.c_str(), "HTTP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 )
{
if ( isalnum(response[0]) )
{
if ( sscanf( response.c_str(), "HTTP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 ) {
if ( isalnum(response[0]) ) {
Error( "Response parse failure in '%s'", response.c_str() );
}
else
{
} else {
Error( "Response parse failure, %zd bytes follow", response.size() );
if ( response.size() )
Hexdump( Logger::ERROR, response.data(), min(response.size(),16) );
@ -313,8 +275,7 @@ int RtspThread::run()
} while (respCode == 401 && !authTried);
if ( respCode != 200 )
{
if ( respCode != 200 ) {
Error( "Unexpected response code %d, text is '%s'", respCode, respText );
return( -1 );
}
@ -327,8 +288,7 @@ int RtspThread::run()
message += "Content-Type: application/x-rtsp-tunnelled\r\n";
message += "\r\n";
Debug( 2, "Sending HTTP message: %s", message.c_str() );
if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() )
{
if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() ) {
Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) );
return( -1 );
}
@ -383,17 +343,14 @@ int RtspThread::run()
if( sdpStart == std::string::npos )
return( -1 );
if ( mRtspDescribe )
{
if ( mRtspDescribe ) {
std::string DescHeader = response.substr( 0,sdpStart );
Debug( 1, "Processing DESCRIBE response header '%s'", DescHeader.c_str() );
lines = split( DescHeader, "\r\n" );
for ( size_t i = 0; i < lines.size(); i++ )
{
for ( size_t i = 0; i < lines.size(); i++ ) {
// If the device sends us a url value for Content-Base in the response header, we should use that instead
if ( ( lines[i].size() > 13 ) && ( lines[i].substr( 0, 13 ) == "Content-Base:" ) )
{
if ( ( lines[i].size() > 13 ) && ( lines[i].substr( 0, 13 ) == "Content-Base:" ) ) {
mUrl = trimSpaces( lines[i].substr( 13 ) );
Info("Received new Content-Base in DESCRIBE response header. Updated device Url to: '%s'", mUrl.c_str() );
break;
@ -406,13 +363,10 @@ int RtspThread::run()
std::string sdp = response.substr( sdpStart );
Debug( 1, "Processing SDP '%s'", sdp.c_str() );
try
{
try {
mSessDesc = new SessionDescriptor( mUrl, sdp );
mFormatContext = mSessDesc->generateFormatContext();
}
catch( const Exception &e )
{
} catch( const Exception &e ) {
Error( e.getMessage().c_str() );
return( -1 );
}
@ -436,10 +390,8 @@ int RtspThread::run()
_AVCODECID codecId;
if ( mFormatContext->nb_streams >= 1 )
{
for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ )
{
if ( mFormatContext->nb_streams >= 1 ) {
for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ ) {
SessionDescriptor::MediaDescriptor *mediaDesc = mSessDesc->getStream( i );
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO )
@ -449,12 +401,9 @@ int RtspThread::run()
{
// Check if control Url is absolute or relative
controlUrl = mediaDesc->getControlUrl();
if (std::equal(trackUrl.begin(), trackUrl.end(), controlUrl.begin()))
{
if (std::equal(trackUrl.begin(), trackUrl.end(), controlUrl.begin())) {
trackUrl = controlUrl;
}
else
{
} else {
if ( *trackUrl.rbegin() != '/') {
trackUrl += "/" + controlUrl;
} else {
@ -470,8 +419,7 @@ int RtspThread::run()
}
}
switch( mMethod )
{
switch( mMethod ) {
case RTP_UNICAST :
{
localPorts[0] = requestPorts();
@ -508,10 +456,8 @@ int RtspThread::run()
int timeout = 0;
char transport[256] = "";
for ( size_t i = 0; i < lines.size(); i++ )
{
if ( ( lines[i].size() > 8 ) && ( lines[i].substr( 0, 8 ) == "Session:" ) )
{
for ( size_t i = 0; i < lines.size(); i++ ) {
if ( ( lines[i].size() > 8 ) && ( lines[i].substr( 0, 8 ) == "Session:" ) ) {
StringVector sessionLine = split( lines[i].substr(9), ";" );
session = trimSpaces( sessionLine[0] );
if ( sessionLine.size() == 2 )
@ -536,41 +482,31 @@ int RtspThread::run()
std::string distribution = "";
unsigned long ssrc = 0;
StringVector parts = split( transport, ";" );
for ( size_t i = 0; i < parts.size(); i++ )
{
for ( size_t i = 0; i < parts.size(); i++ ) {
if ( parts[i] == "unicast" || parts[i] == "multicast" )
distribution = parts[i];
else if ( startsWith( parts[i], "server_port=" ) )
{
else if ( startsWith( parts[i], "server_port=" ) ) {
method = "RTP/UNICAST";
StringVector subparts = split( parts[i], "=" );
StringVector ports = split( subparts[1], "-" );
remotePorts[0] = strtol( ports[0].c_str(), NULL, 10 );
remotePorts[1] = strtol( ports[1].c_str(), NULL, 10 );
}
else if ( startsWith( parts[i], "interleaved=" ) )
{
} else if ( startsWith( parts[i], "interleaved=" ) ) {
method = "RTP/RTSP";
StringVector subparts = split( parts[i], "=" );
StringVector channels = split( subparts[1], "-" );
remoteChannels[0] = strtol( channels[0].c_str(), NULL, 10 );
remoteChannels[1] = strtol( channels[1].c_str(), NULL, 10 );
}
else if ( startsWith( parts[i], "port=" ) )
{
} else if ( startsWith( parts[i], "port=" ) ) {
method = "RTP/MULTICAST";
StringVector subparts = split( parts[i], "=" );
StringVector ports = split( subparts[1], "-" );
localPorts[0] = strtol( ports[0].c_str(), NULL, 10 );
localPorts[1] = strtol( ports[1].c_str(), NULL, 10 );
}
else if ( startsWith( parts[i], "destination=" ) )
{
} else if ( startsWith( parts[i], "destination=" ) ) {
StringVector subparts = split( parts[i], "=" );
localHost = subparts[1];
}
else if ( startsWith( parts[i], "ssrc=" ) )
{
} else if ( startsWith( parts[i], "ssrc=" ) ) {
StringVector subparts = split( parts[i], "=" );
ssrc = strtoll( subparts[1].c_str(), NULL, 16 );
}
@ -592,13 +528,11 @@ int RtspThread::run()
lines = split( response, "\r\n" );
std::string rtpInfo;
for ( size_t i = 0; i < lines.size(); i++ )
{
for ( size_t i = 0; i < lines.size(); i++ ) {
if ( ( lines[i].size() > 9 ) && ( lines[i].substr( 0, 9 ) == "RTP-Info:" ) )
rtpInfo = trimSpaces( lines[i].substr( 9 ) );
// Check for a timeout again. Some rtsp devices don't send a timeout until after the PLAY command is sent
if ( ( lines[i].size() > 8 ) && ( lines[i].substr( 0, 8 ) == "Session:" ) && ( timeout == 0 ) )
{
if ( ( lines[i].size() > 8 ) && ( lines[i].substr( 0, 8 ) == "Session:" ) && ( timeout == 0 ) ) {
StringVector sessionLine = split( lines[i].substr(9), ";" );
if ( sessionLine.size() == 2 )
sscanf( trimSpaces( sessionLine[1] ).c_str(), "timeout=%d", &timeout );
@ -610,31 +544,22 @@ int RtspThread::run()
int seq = 0;
unsigned long rtpTime = 0;
StringVector streams;
if ( rtpInfo.empty() )
{
if ( rtpInfo.empty() ) {
Debug( 1, "RTP Info Empty. Starting values for Sequence and Rtptime shall be zero.");
}
else
{
} else {
Debug( 2, "Got RTP Info %s", rtpInfo.c_str() );
// More than one stream can be included in the RTP Info
streams = split( rtpInfo.c_str(), "," );
for ( size_t i = 0; i < streams.size(); i++ )
{
for ( size_t i = 0; i < streams.size(); i++ ) {
// We want the stream that matches the trackUrl we are using
if ( streams[i].find(controlUrl.c_str()) != std::string::npos )
{
if ( streams[i].find(controlUrl.c_str()) != std::string::npos ) {
// Parse the sequence and rtptime values
parts = split( streams[i].c_str(), ";" );
for ( size_t j = 0; j < parts.size(); j++ )
{
if ( startsWith( parts[j], "seq=" ) )
{
for ( size_t j = 0; j < parts.size(); j++ ) {
if ( startsWith( parts[j], "seq=" ) ) {
StringVector subparts = split( parts[j], "=" );
seq = strtol( subparts[1].c_str(), NULL, 10 );
}
else if ( startsWith( parts[j], "rtptime=" ) )
{
} else if ( startsWith( parts[j], "rtptime=" ) ) {
StringVector subparts = split( parts[j], "=" );
rtpTime = strtol( subparts[1].c_str(), NULL, 10 );
}
@ -651,8 +576,7 @@ int RtspThread::run()
time_t now;
message = "GET_PARAMETER "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n";
switch( mMethod )
{
switch( mMethod ) {
case RTP_UNICAST :
{
RtpSource *source = new RtpSource( mId, "", localPorts[0], mHost, remotePorts[0], ssrc, seq, rtpClock, rtpTime, codecId );
@ -663,13 +587,11 @@ int RtspThread::run()
rtpDataThread.start();
rtpCtrlThread.start();
while( !mStop )
{
while( !mStop ) {
now = time(NULL);
// Send a keepalive message if the server supports this feature and we are close to the timeout expiration
Debug(5, "sendkeepalive %d, timeout %d, now: %d last: %d since: %d", sendKeepalive, timeout, now, lastKeepalive, (now-lastKeepalive) );
if ( sendKeepalive && (timeout > 0) && ((now-lastKeepalive) > (timeout-5)) )
{
if ( sendKeepalive && (timeout > 0) && ((now-lastKeepalive) > (timeout-5)) ) {
if ( !sendCommand( message ) )
return( -1 );
lastKeepalive = now;
@ -721,11 +643,9 @@ Debug(5, "sendkeepalive %d, timeout %d, now: %d last: %d since: %d", sendKeepali
Buffer buffer( ZM_NETWORK_BUFSIZ );
std::string keepaliveMessage = "OPTIONS "+mUrl+" RTSP/1.0\r\n";
std::string keepaliveResponse = "RTSP/1.0 200 OK\r\n";
while ( !mStop && select.wait() >= 0 )
{
while ( !mStop && select.wait() >= 0 ) {
Select::CommsList readable = select.getReadable();
if ( readable.size() == 0 )
{
if ( readable.size() == 0 ) {
Error( "RTSP timed out" );
break;
}
@ -735,23 +655,19 @@ Debug(5, "sendkeepalive %d, timeout %d, now: %d last: %d since: %d", sendKeepali
buffer.append( tempBuffer, nBytes );
Debug( 4, "Read %zd bytes on sd %d, %d total", nBytes, mRtspSocket.getReadDesc(), buffer.size() );
while( buffer.size() > 0 )
{
if ( buffer[0] == '$' )
{
while( buffer.size() > 0 ) {
if ( buffer[0] == '$' ) {
if ( buffer.size() < 4 )
break;
unsigned char channel = buffer[1];
unsigned short len = ntohs( *((unsigned short *)(buffer+2)) );
Debug( 4, "Got %d bytes left, expecting %d byte packet on channel %d", buffer.size(), len, channel );
if ( (unsigned short)buffer.size() < (len+4) )
{
if ( (unsigned short)buffer.size() < (len+4) ) {
Debug( 4, "Missing %d bytes, rereading", (len+4)-buffer.size() );
break;
}
if ( channel == remoteChannels[0] )
{
if ( channel == remoteChannels[0] ) {
Debug( 4, "Got %d bytes on data channel %d, packet length is %d", buffer.size(), channel, len );
Hexdump( 4, (char *)buffer, 16 );
rtpDataThread.recvPacket( buffer+4, len );

View File

@ -31,8 +31,7 @@
#include <set>
#include <map>
class RtspThread : public Thread
{
class RtspThread : public Thread {
public:
typedef enum { RTP_UNICAST, RTP_MULTICAST, RTP_RTSP, RTP_RTSP_HTTP } RtspMethod;
typedef enum { UNDEFINED, UNICAST, MULTICAST } RtspDist;

View File

@ -26,7 +26,11 @@
namespace zm {
Authenticator::Authenticator(std::string &username, std::string password) {
Authenticator::Authenticator( const std::string &username, const std::string &password) :
fCnonce( "0a4f113b" ),
fUsername(username),
fPassword(password)
{
#ifdef HAVE_GCRYPT_H
// Special initialisation for libgcrypt
if ( !gcry_check_version( GCRYPT_VERSION ) )
@ -38,10 +42,7 @@ Authenticator::Authenticator(std::string &username, std::string password) {
#endif // HAVE_GCRYPT_H
fAuthMethod = AUTH_UNDEFINED;
fUsername = username;
fPassword = password;
nc = 1;
fCnonce = "0a4f113b";
}
Authenticator::~Authenticator() {
@ -96,13 +97,11 @@ void Authenticator::authHandleHeader(std::string headerData)
}
}
std::string Authenticator::quote(std::string src)
{
std::string Authenticator::quote( const std::string &src ) {
return replaceAll(replaceAll(src, "\\", "\\\\"), "\"", "\\\"");
}
std::string Authenticator::getAuthHeader(std::string method, std::string uri)
{
std::string Authenticator::getAuthHeader(std::string method, std::string uri) {
std::string result = "Authorization: ";
if (fAuthMethod == AUTH_BASIC)
{

View File

@ -37,7 +37,7 @@ namespace zm {
enum AuthMethod { AUTH_UNDEFINED = 0, AUTH_BASIC = 1, AUTH_DIGEST = 2 };
class Authenticator {
public:
Authenticator(std::string &username, std::string password);
Authenticator(const std::string &username, const std::string &password);
virtual ~Authenticator();
void reset();
@ -60,7 +60,7 @@ private:
std::string fQop;
std::string fUsername;
std::string fPassword;
std::string quote( std::string src );
std::string quote( const std::string &src );
int nc;
};

View File

@ -71,7 +71,7 @@ public:
int mNoAddresses;
public:
ConnInfo( const std::string &connInfo );
explicit ConnInfo( const std::string &connInfo );
};
class BandInfo {
@ -80,7 +80,7 @@ public:
int mValue;
public:
BandInfo( const std::string &bandInfo );
explicit BandInfo( const std::string &bandInfo );
};
class MediaDescriptor {
@ -138,48 +138,38 @@ public:
{
return( mControlUrl );
}
void setControlUrl( const std::string &controlUrl )
{
void setControlUrl( const std::string &controlUrl ) {
mControlUrl = controlUrl;
}
const int getClock() const
{
const int getClock() const {
return( mClock );
}
void setClock( int clock )
{
void setClock( int clock ) {
mClock = clock;
}
void setFrameSize( int width, int height )
{
void setFrameSize( int width, int height ) {
mWidth = width;
mHeight = height;
}
int getWidth() const
{
int getWidth() const {
return( mWidth );
}
int getHeight() const
{
int getHeight() const {
return( mHeight );
}
void setSprops(const std::string props)
{
void setSprops(const std::string &props) {
mSprops = props;
}
const std::string getSprops() const
{
const std::string getSprops() const {
return ( mSprops );
}
const double getFrameRate() const
{
const double getFrameRate() const {
return( mFrameRate );
}
void setFrameRate( double frameRate )
{
void setFrameRate( double frameRate ) {
mFrameRate = frameRate;
}
};