From de2df49d6443a544091cff6b7b18aa0b16290d46 Mon Sep 17 00:00:00 2001 From: Kfir Itzhak Date: Wed, 22 Jun 2011 18:38:35 +0300 Subject: [PATCH] 1) Added support for the new formats to the mpeg code. 2) Fixed unwanted extra call to set video format for local cameras. 3) Small changes to the perl shared memory types. --- .../ZoneMinder/lib/ZoneMinder/Memory.pm.in | 108 ++++++++++++------ src/zm_event.cpp | 4 +- src/zm_local_camera.cpp | 28 +++-- src/zm_mem_utils.h | 12 +- src/zm_monitor.cpp | 2 +- src/zm_mpeg.cpp | 51 +++++++-- src/zm_mpeg.h | 4 +- src/zm_stream.cpp | 2 +- 8 files changed, 144 insertions(+), 67 deletions(-) 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(); }