diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in index a6f7395ff..9e75269c8 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in @@ -146,16 +146,16 @@ our $mem_data = "contrast" => { "type"=>"int32", "seq"=>$mem_seq++ }, "alarm_x" => { "type"=>"int32", "seq"=>$mem_seq++ }, "alarm_y" => { "type"=>"int32", "seq"=>$mem_seq++ }, - "valid" => { "type"=>"uchar", "seq"=>$mem_seq++ }, - "active" => { "type"=>"uchar", "seq"=>$mem_seq++ }, - "signal" => { "type"=>"uchar", "seq"=>$mem_seq++ }, - "bpadding" => { "type"=>"uchar", "seq"=>$mem_seq++ }, + "valid" => { "type"=>"uint8", "seq"=>$mem_seq++ }, + "active" => { "type"=>"uint8", "seq"=>$mem_seq++ }, + "signal" => { "type"=>"uint8", "seq"=>$mem_seq++ }, + "bpadding" => { "type"=>"uint8", "seq"=>$mem_seq++ }, "epadding1" => { "type"=>"uint32", "seq"=>$mem_seq++ }, "epadding2" => { "type"=>"uint32", "seq"=>$mem_seq++ }, "epadding3" => { "type"=>"uint32", "seq"=>$mem_seq++ }, "last_write_time" => { "type"=>"time_t64", "seq"=>$mem_seq++ }, "last_read_time" => { "type"=>"time_t64", "seq"=>$mem_seq++ }, - "control_state" => { "type"=>"uchar[256]", "seq"=>$mem_seq++ }, + "control_state" => { "type"=>"uint8[256]", "seq"=>$mem_seq++ }, } }, "trigger_data" => { "type"=>"TriggerData", "seq"=>$mem_seq++, "contents"=> { @@ -163,9 +163,9 @@ our $mem_data = "trigger_state" => { "type"=>"uint32", "seq"=>$mem_seq++ }, "trigger_score" => { "type"=>"uint32", "seq"=>$mem_seq++ }, "padding" => { "type"=>"uint32", "seq"=>$mem_seq++ }, - "trigger_cause" => { "type"=>"char[32]", "seq"=>$mem_seq++ }, - "trigger_text" => { "type"=>"char[256]", "seq"=>$mem_seq++ }, - "trigger_showtext" => { "type"=>"char[256]", "seq"=>$mem_seq++ }, + "trigger_cause" => { "type"=>"int8[32]", "seq"=>$mem_seq++ }, + "trigger_text" => { "type"=>"int8[256]", "seq"=>$mem_seq++ }, + "trigger_showtext" => { "type"=>"int8[256]", "seq"=>$mem_seq++ }, } }, "end" => { "seq"=>$mem_seq++, "size"=> 0 } @@ -205,15 +205,15 @@ sub zmMemInit { $member_data->{size} = $member_data->{align} = 4; } - elsif ( $member_data->{type} eq "short" ) + elsif ($member_data->{type} eq "int16" || $member_data->{type} eq "uint16") { $member_data->{size} = $member_data->{align} = 2; } - elsif ( $member_data->{type} eq "char" || $member_data->{type} eq "uchar" || $member_data->{type} eq "bool1" ) + elsif ( $member_data->{type} eq "int8" || $member_data->{type} eq "uint8" || $member_data->{type} eq "bool1" ) { $member_data->{size} = $member_data->{align} = 1; } - elsif ( $member_data->{type} =~ /^u?char\[(\d+)\]$/ ) + elsif ( $member_data->{type} =~ /^u?int8\[(\d+)\]$/ ) { $member_data->{size} = $1; $member_data->{align} = 1; @@ -313,36 +313,53 @@ sub zmMemRead( $$;$ ) return( undef ); } my $value; - if ( $type eq "long" || $type eq "ulong" || $type eq "size_t") + if ( $type eq "long" ) { ( $value ) = unpack( "l!", $data ); } - elsif ( $type eq "int64" || $type eq "uint64" || $type eq "time_t64" ) + elsif ( $type eq "ulong" || $type eq "size_t" ) { - # The "q" type is only available on 64bit platforms. + ( $value ) = unpack( "L!", $data ); + } + elsif ( $type eq "int64" || $type eq "time_t64" ) + { + # The "q" type is only available on 64bit platforms, so use native. ( $value ) = unpack( "l!", $data ); } - elsif ( $type eq "int32" || $type eq "uint32" || $type eq "bool4" ) + elsif ( $type eq "uint64" ) + { + # The "q" type is only available on 64bit platforms, so use native. + ( $value ) = unpack( "L!", $data ); + } + elsif ( $type eq "int32" ) { ( $value ) = unpack( "l", $data ); } - elsif ( $type eq "short" ) + elsif ( $type eq "uint32" || $type eq "bool4" ) + { + ( $value ) = unpack( "L", $data ); + } + elsif ( $type eq "int16" ) { ( $value ) = unpack( "s", $data ); } - elsif ( $type eq "char" || $type eq "bool1" ) + elsif ( $type eq "uint16" ) + { + ( $value ) = unpack( "S", $data ); + } + elsif ( $type eq "int8" ) { ( $value ) = unpack( "c", $data ); } - elsif ( $type eq "uchar" ) + elsif ( $type eq "uint8" || $type eq "bool1" ) { ( $value ) = unpack( "C", $data ); } - elsif ( $type =~ /^char\[\d+\]$/ ) + elsif ( $type =~ /^int8\[\d+\]$/ ) { ( $value ) = unpack( "Z".$size, $data ); } - elsif ( $type =~ /^uchar\[\d+\]$/ ) + elsif ( $type =~ /^uint8\[\d+\]$/ ) { ( $value ) = unpack( "C".$size, $data ); } @@ -396,39 +413,56 @@ sub zmMemWrite( $$;$ ) my $size = $mem_data->{$section}->{contents}->{$element}->{size}; my $data; - if ( $type eq "long" || $type eq "ulong" || $type eq "size_t") + if ( $type eq "long" ) { - $data = pack( "l!", $value ); + $data = pack( "l!", $data ); } - elsif ( $type eq "int64" || $type eq "uint64" || $type eq "time_t64" ) + elsif ( $type eq "ulong" || $type eq "size_t" ) { - # The "q" type is only available on 64bit platforms. - $data = pack( "l!", $value ); + $data = pack( "L!", $data ); } - elsif ( $type eq "int32" || $type eq "uint32" || $type eq "bool4" ) + elsif ( $type eq "int64" || $type eq "time_t64" ) { - $data = pack( "l", $value ); + # The "q" type is only available on 64bit platforms, so use native. + $data = pack( "l!", $data ); } - elsif ( $type eq "short" ) + elsif ( $type eq "uint64" ) { - $data = pack( "s", $value ); + # The "q" type is only available on 64bit platforms, so use native. + $data = pack( "L!", $data ); } - elsif ( $type eq "char" || $type eq "bool1" ) + elsif ( $type eq "int32" ) { - $data = pack( "c", $value ); + $data = pack( "l", $data ); } - elsif ( $type eq "uchar" ) + elsif ( $type eq "uint32" || $type eq "bool4" ) { - $data = pack( "C", $value ); + $data = pack( "L", $data ); } - elsif ( $type =~ /^char\[\d+\]$/ ) + elsif ( $type eq "int16" ) { - $data = pack( "Z".$size, $value ); + $data = pack( "s", $data ); } - elsif ( $type =~ /^uchar\[\d+\]$/ ) + elsif ( $type eq "uint16" ) { - $data = pack( "C".$size, $value ); + $data = pack( "S", $data ); } + elsif ( $type eq "int8" ) + { + $data = pack( "c", $data ); + } + elsif ( $type eq "uint8" || $type eq "bool1" ) + { + $data = pack( "C", $data ); + } + elsif ( $type =~ /^int8\[\d+\]$/ ) + { + $data = pack( "Z".$size, $data ); + } + elsif ( $type =~ /^uint8\[\d+\]$/ ) + { + $data = pack( "C".$size, $data ); + } else { Fatal( "Unexpected type '".$type."' found for '".$field."'" ); diff --git a/src/zm_event.cpp b/src/zm_event.cpp index ab619192e..b84458e02 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -1206,7 +1206,7 @@ bool EventStream::sendFrame( int delta_us ) if ( !vid_stream ) { - vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, send_image->Colours(), send_image->Width(), send_image->Height() ); + vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, send_image->Colours(), send_image->SubpixelOrder(), send_image->Width(), send_image->Height() ); fprintf( stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType() ); vid_stream->OpenStream(); } @@ -1447,4 +1447,4 @@ void EventStream::runStream() #endif // HAVE_LIBAVCODEC closeComms(); -} \ No newline at end of file +} diff --git a/src/zm_local_camera.cpp b/src/zm_local_camera.cpp index 41c91f530..d9c3da060 100644 --- a/src/zm_local_camera.cpp +++ b/src/zm_local_camera.cpp @@ -676,17 +676,23 @@ void LocalCamera::Initialise() v4l2_data.fmt.fmt.pix.height = height; v4l2_data.fmt.fmt.pix.pixelformat = palette; - if ( config.v4l2_capture_fields ) - { - v4l2_data.fmt.fmt.pix.field = (v4l2_field)config.v4l2_capture_fields; - if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 ) - { - Warning( "Failed to set V4L2 field to %d, falling back to auto", config.v4l2_capture_fields ); - v4l2_data.fmt.fmt.pix.field = V4L2_FIELD_ANY; - } - } - if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 ) - Fatal( "Failed to set video format: %s", strerror(errno) ); + if ( config.v4l2_capture_fields ) + { + v4l2_data.fmt.fmt.pix.field = (v4l2_field)config.v4l2_capture_fields; + + if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 ) + { + Warning( "Failed to set V4L2 field to %d, falling back to auto", config.v4l2_capture_fields ); + v4l2_data.fmt.fmt.pix.field = V4L2_FIELD_ANY; + if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 ) { + Fatal( "Failed to set video format: %s", strerror(errno) ); + } + } + } else { + if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 ) { + Fatal( "Failed to set video format: %s", strerror(errno) ); + } + } /* Note VIDIOC_S_FMT may change width and height. */ Debug( 4, " v4l2_data.fmt.type = %08x", v4l2_data.fmt.type ); diff --git a/src/zm_mem_utils.h b/src/zm_mem_utils.h index 0f9d9acac..04e313330 100644 --- a/src/zm_mem_utils.h +++ b/src/zm_mem_utils.h @@ -39,12 +39,12 @@ inline void* zm_mallocaligned(unsigned int reqalignment, size_t reqsize) { alloc = retptr + sizeof(void*); - if(((long)alloc % reqalignment) != 0) - alloc = alloc + (reqalignment - ((long)alloc % reqalignment)); - - /* Store a pointer before to the start of the block, just before returned aligned memory */ - *(void**)(alloc - sizeof(void*)) = retptr; - + if(((long)alloc % reqalignment) != 0) + alloc = alloc + (reqalignment - ((long)alloc % reqalignment)); + + /* Store a pointer before to the start of the block, just before returned aligned memory */ + *(void**)(alloc - sizeof(void*)) = retptr; + return alloc; #endif } diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 98cff987d..68566ee95 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -3379,7 +3379,7 @@ bool MonitorStream::sendFrame( Image *image, struct timeval *timestamp ) { if ( !vid_stream ) { - vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, send_image->Colours(), send_image->Width(), send_image->Height() ); + vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, send_image->Colours(), send_image->SubpixelOrder(), send_image->Width(), send_image->Height() ); fprintf( stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType() ); vid_stream->OpenStream(); } diff --git a/src/zm_mpeg.cpp b/src/zm_mpeg.cpp index ff5ba944d..f5de2a483 100644 --- a/src/zm_mpeg.cpp +++ b/src/zm_mpeg.cpp @@ -21,6 +21,7 @@ #include #include "zm.h" +#include "zm_rgb.h" #include "zm_mpeg.h" #if HAVE_LIBAVCODEC @@ -68,9 +69,45 @@ void VideoStream::SetupFormat( const char *p_filename, const char *p_format ) snprintf( ofc->filename, sizeof(ofc->filename), "%s", filename ); } -void VideoStream::SetupCodec( int colours, int width, int height, int bitrate, double frame_rate ) +void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int height, int bitrate, double frame_rate ) { - pf = (colours==1?PIX_FMT_GRAY8:PIX_FMT_RGB24); + /* ffmpeg format matching */ + switch(colours) { + case ZM_COLOUR_RGB24: + { + if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { + /* BGR subpixel order */ + pf = PIX_FMT_BGR24; + } else { + /* Assume RGB subpixel order */ + pf = PIX_FMT_RGB24; + } + break; + } + case ZM_COLOUR_RGB32: + { + if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + /* ARGB subpixel order */ + pf = PIX_FMT_ARGB; + } else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + /* ABGR subpixel order */ + pf = PIX_FMT_ABGR; + } else if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + /* BGRA subpixel order */ + pf = PIX_FMT_BGRA; + } else { + /* Assume RGBA subpixel order */ + pf = PIX_FMT_RGBA; + } + break; + } + case ZM_COLOUR_GRAY8: + pf = PIX_FMT_GRAY8; + break; + default: + Panic("Unexpected colours: %d",colours); + break; + } /* add the video streams using the default format codecs and initialize the codecs */ @@ -188,7 +225,7 @@ void VideoStream::OpenStream() Panic( "Could not allocate opicture" ); } int size = avpicture_get_size( c->pix_fmt, c->width, c->height); - uint8_t *opicture_buf = (uint8_t *)malloc(size); + uint8_t *opicture_buf = (uint8_t *)av_malloc(size); if ( !opicture_buf ) { av_free(opicture); @@ -196,7 +233,7 @@ void VideoStream::OpenStream() } avpicture_fill( (AVPicture *)opicture, opicture_buf, c->pix_fmt, c->width, c->height ); - /* if the output format is not RGB24, then a temporary RGB24 + /* if the output format is not identical to the input format, then a temporary picture is needed too. It is then converted to the required output format */ tmp_opicture = NULL; @@ -208,7 +245,7 @@ void VideoStream::OpenStream() Panic( "Could not allocate temporary opicture" ); } int size = avpicture_get_size( pf, c->width, c->height); - uint8_t *tmp_opicture_buf = (uint8_t *)malloc(size); + uint8_t *tmp_opicture_buf = (uint8_t *)av_malloc(size); if (!tmp_opicture_buf) { av_free( tmp_opicture ); @@ -244,7 +281,7 @@ void VideoStream::OpenStream() av_write_header(ofc); } -VideoStream::VideoStream( const char *filename, const char *format, int bitrate, double frame_rate, int colours, int width, int height ) +VideoStream::VideoStream( const char *filename, const char *format, int bitrate, double frame_rate, int colours, int subpixelorder, int width, int height ) { if ( !initialised ) { @@ -252,7 +289,7 @@ VideoStream::VideoStream( const char *filename, const char *format, int bitrate, } SetupFormat( filename, format ); - SetupCodec( colours, width, height, bitrate, frame_rate ); + SetupCodec( colours, subpixelorder, width, height, bitrate, frame_rate ); SetParameters(); } diff --git a/src/zm_mpeg.h b/src/zm_mpeg.h index 4ac88e5ec..c7cb4d26f 100644 --- a/src/zm_mpeg.h +++ b/src/zm_mpeg.h @@ -54,11 +54,11 @@ protected: static void Initialise(); void SetupFormat( const char *p_filename, const char *format ); - void SetupCodec( int colours, int width, int height, int bitrate, double frame_rate ); + void SetupCodec( int colours, int subpixelorder, int width, int height, int bitrate, double frame_rate ); void SetParameters(); public: - VideoStream( const char *filename, const char *format, int bitrate, double frame_rate, int colours, int width, int height ); + VideoStream( const char *filename, const char *format, int bitrate, double frame_rate, int colours, int subpixelorder, int width, int height ); ~VideoStream(); const char *MimeType() const; void OpenStream(); diff --git a/src/zm_stream.cpp b/src/zm_stream.cpp index dc1412b96..41414f495 100644 --- a/src/zm_stream.cpp +++ b/src/zm_stream.cpp @@ -245,7 +245,7 @@ bool StreamBase::sendTextFrame( const char *frame_text ) { if ( !vid_stream ) { - vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, image.Colours(), image.Width(), image.Height() ); + vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, image.Colours(), image.SubpixelOrder(), image.Width(), image.Height() ); fprintf( stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType() ); vid_stream->OpenStream(); }