1) Removed the mmap file removal at shutdown.

2) ZoneMinder should now compile cleanly wihout swscale
3) Fixed multiple monitors capturing from the same device and channel.
Current code allows for multiple monitors sharing the same device, each on a different channel
Or, multiple monitors sharing the same device, all on the same channel.
In both cases, capture method, width, height and palette must be identical on all monitors.
However, target colorspace can be different because each monitor handles the format conversion separately.
This commit is contained in:
Kfir Itzhak 2011-05-08 16:32:42 +03:00
parent 37cc9199b2
commit ea3a1a9072
4 changed files with 81 additions and 85 deletions

View File

@ -338,9 +338,11 @@ LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel,
#if HAVE_LIBSWSCALE #if HAVE_LIBSWSCALE
if( capture ) {
/* Get ffmpeg pixel format based on capture palette and endianness */ /* Get ffmpeg pixel format based on capture palette and endianness */
capturePixFormat = getFfPixFormatFromV4lPalette( v4l_version, palette ); capturePixFormat = getFfPixFormatFromV4lPalette( v4l_version, palette );
imagePixFormat = PIX_FMT_NONE; imagePixFormat = PIX_FMT_NONE;
}
#endif // HAVE_LIBSWSCALE #endif // HAVE_LIBSWSCALE
@ -393,6 +395,7 @@ LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel,
} else { } else {
Panic("Unexpected colours: %d",colours); Panic("Unexpected colours: %d",colours);
} }
if( capture ) {
if(!sws_isSupportedInput(capturePixFormat)) { if(!sws_isSupportedInput(capturePixFormat)) {
Error("swscale does not support the used capture format"); Error("swscale does not support the used capture format");
conversion_type = 2; /* Try ZM format conversions */ conversion_type = 2; /* Try ZM format conversions */
@ -401,6 +404,7 @@ LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel,
Error("swscale does not support the target format"); Error("swscale does not support the target format");
conversion_type = 2; /* Try ZM format conversions */ conversion_type = 2; /* Try ZM format conversions */
} }
}
#else #else
/* Don't have swscale, see what we can do */ /* Don't have swscale, see what we can do */
conversion_type = 2; conversion_type = 2;
@ -447,7 +451,7 @@ LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel,
conversion_fptr = &zm_convert_rgb565_rgba; conversion_fptr = &zm_convert_rgb565_rgba;
subpixelorder = ZM_SUBPIX_ORDER_RGBA; subpixelorder = ZM_SUBPIX_ORDER_RGBA;
} else { } else {
Panic("Unable to find suitable conversion for selected palette and target colourspace."); Fatal("Unable to find suitable conversion for selected palette and target colourspace.");
} }
} }
} }
@ -501,6 +505,7 @@ LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel,
} else { } else {
Panic("Unexpected colours: %d",colours); Panic("Unexpected colours: %d",colours);
} }
if( capture ) {
if(!sws_isSupportedInput(capturePixFormat)) { if(!sws_isSupportedInput(capturePixFormat)) {
Error("swscale does not support the used capture format"); Error("swscale does not support the used capture format");
conversion_type = 2; /* Try ZM format conversions */ conversion_type = 2; /* Try ZM format conversions */
@ -509,6 +514,7 @@ LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel,
Error("swscale does not support the target format"); Error("swscale does not support the target format");
conversion_type = 2; /* Try ZM format conversions */ conversion_type = 2; /* Try ZM format conversions */
} }
}
#else #else
/* Don't have swscale, see what we can do */ /* Don't have swscale, see what we can do */
conversion_type = 2; conversion_type = 2;
@ -566,12 +572,47 @@ LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel,
last_camera = this; last_camera = this;
Debug(3,"Selected subpixelorder: %d",subpixelorder); Debug(3,"Selected subpixelorder: %d",subpixelorder);
#if HAVE_LIBSWSCALE
/* Initialize swscale stuff */
if(capture && conversion_type == 1) {
tmpPicture = avcodec_alloc_frame();
if ( !tmpPicture )
Fatal( "Could not allocate temporary picture" );
int pSize = avpicture_get_size( imagePixFormat, width, height );
if( pSize != imagesize) {
Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize);
}
if(config.cpu_extensions && sseversion >= 20) {
imgConversionContext = sws_getContext(width, height, capturePixFormat, width, height, imagePixFormat, SWS_BICUBIC | SWS_CPU_CAPS_SSE2, NULL, NULL, NULL );
} else {
imgConversionContext = sws_getContext(width, height, capturePixFormat, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL );
}
if ( !imgConversionContext )
Fatal( "Unable to initialise image scaling context" );
}
#endif
} }
LocalCamera::~LocalCamera() LocalCamera::~LocalCamera()
{ {
if ( device_prime && capture ) if ( device_prime && capture )
Terminate(); Terminate();
#if HAVE_LIBSWSCALE
/* Clean up swscale stuff */
if(capture && conversion_type == 1) {
sws_freeContext(imgConversionContext);
imgConversionContext = NULL;
av_free(tmpPicture);
tmpPicture = NULL;
}
#endif
} }
void LocalCamera::Initialise() void LocalCamera::Initialise()
@ -723,12 +764,10 @@ void LocalCamera::Initialise()
Fatal( "Can't map video buffer %d (%d bytes) to memory: %s(%d)", i, vid_buf.length, strerror(errno), errno ); Fatal( "Can't map video buffer %d (%d bytes) to memory: %s(%d)", i, vid_buf.length, strerror(errno), errno );
#if HAVE_LIBSWSCALE #if HAVE_LIBSWSCALE
if (conversion_type == 1) {
capturePictures[i] = avcodec_alloc_frame(); capturePictures[i] = avcodec_alloc_frame();
if ( !capturePictures[i] ) if ( !capturePictures[i] )
Fatal( "Could not allocate picture" ); Fatal( "Could not allocate picture" );
avpicture_fill( (AVPicture *)capturePictures[i], (uint8_t*)v4l2_data.buffers[i].start, capturePixFormat, v4l2_data.fmt.fmt.pix.width, v4l2_data.fmt.fmt.pix.height ); avpicture_fill( (AVPicture *)capturePictures[i], (uint8_t*)v4l2_data.buffers[i].start, capturePixFormat, v4l2_data.fmt.fmt.pix.width, v4l2_data.fmt.fmt.pix.height );
}
#endif // HAVE_LIBSWSCALE #endif // HAVE_LIBSWSCALE
} }
@ -879,14 +918,11 @@ void LocalCamera::Initialise()
v4l1_data.buffers[i].height = height; v4l1_data.buffers[i].height = height;
v4l1_data.buffers[i].format = palette; v4l1_data.buffers[i].format = palette;
if (conversion_type == 1)
{
capturePictures[i] = avcodec_alloc_frame(); capturePictures[i] = avcodec_alloc_frame();
if ( !capturePictures[i] ) if ( !capturePictures[i] )
Fatal( "Could not allocate picture" ); Fatal( "Could not allocate picture" );
avpicture_fill( (AVPicture *)capturePictures[i], (unsigned char *)v4l1_data.bufptr+v4l1_data.frames.offsets[i], capturePixFormat, width, height ); avpicture_fill( (AVPicture *)capturePictures[i], (unsigned char *)v4l1_data.bufptr+v4l1_data.frames.offsets[i], capturePixFormat, width, height );
} }
}
#endif // HAVE_LIBSWSCALE #endif // HAVE_LIBSWSCALE
Debug( 3, "Configuring video source" ); Debug( 3, "Configuring video source" );
@ -935,29 +971,6 @@ void LocalCamera::Initialise()
Debug( 4, "New Cn:%d", vid_pic.contrast ); Debug( 4, "New Cn:%d", vid_pic.contrast );
} }
#endif // ZM_HAS_V4L1 #endif // ZM_HAS_V4L1
#if HAVE_LIBSWSCALE
if(conversion_type == 1) {
tmpPicture = avcodec_alloc_frame();
if ( !tmpPicture )
Fatal( "Could not allocate temporary picture" );
int pSize = avpicture_get_size( imagePixFormat, width, height );
if( pSize != imagesize) {
Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize);
}
if(config.cpu_extensions && sseversion >= 20) {
imgConversionContext = sws_getContext(width, height, capturePixFormat, width, height, imagePixFormat, SWS_BICUBIC | SWS_CPU_CAPS_SSE2, NULL, NULL, NULL );
} else {
imgConversionContext = sws_getContext(width, height, capturePixFormat, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL );
}
if ( !imgConversionContext )
Fatal( "Unable to initialise image scaling context" );
}
#endif
} }
void LocalCamera::Terminate() void LocalCamera::Terminate()
@ -974,11 +987,9 @@ void LocalCamera::Terminate()
Debug( 3, "Unmapping video buffers" ); Debug( 3, "Unmapping video buffers" );
for ( int i = 0; i < v4l2_data.reqbufs.count; i++ ) { for ( int i = 0; i < v4l2_data.reqbufs.count; i++ ) {
#if HAVE_LIBSWSCALE #if HAVE_LIBSWSCALE
if(conversion_type == 1) {
/* Free capture pictures */ /* Free capture pictures */
av_free(capturePictures[i]); av_free(capturePictures[i]);
capturePictures[i] = NULL; capturePictures[i] = NULL;
}
#endif #endif
if ( munmap( v4l2_data.buffers[i].start, v4l2_data.buffers[i].length ) < 0 ) if ( munmap( v4l2_data.buffers[i].start, v4l2_data.buffers[i].length ) < 0 )
Error( "Failed to munmap buffer %d: %s", i, strerror(errno) ); Error( "Failed to munmap buffer %d: %s", i, strerror(errno) );
@ -993,13 +1004,11 @@ void LocalCamera::Terminate()
if ( v4l_version == 1 ) if ( v4l_version == 1 )
{ {
#if HAVE_LIBSWSCALE #if HAVE_LIBSWSCALE
if(conversion_type == 1) {
for(unsigned int i=0; i < v4l1_data.frames.frames; i++) { for(unsigned int i=0; i < v4l1_data.frames.frames; i++) {
/* Free capture pictures */ /* Free capture pictures */
av_free(capturePictures[i]); av_free(capturePictures[i]);
capturePictures[i] = NULL; capturePictures[i] = NULL;
} }
}
#endif #endif
Debug( 3, "Unmapping video buffers" ); Debug( 3, "Unmapping video buffers" );
@ -1012,17 +1021,6 @@ void LocalCamera::Terminate()
close( vid_fd ); close( vid_fd );
#if HAVE_LIBSWSCALE
/* Clean up swscale stuff */
if(conversion_type == 1) {
sws_freeContext(imgConversionContext);
imgConversionContext = NULL;
av_free(tmpPicture);
tmpPicture = NULL;
}
#endif
} }
#define capString(test,prefix,yesString,noString,capability) \ #define capString(test,prefix,yesString,noString,capability) \
@ -1821,8 +1819,9 @@ int LocalCamera::PreCapture()
int LocalCamera::Capture( Image &image ) int LocalCamera::Capture( Image &image )
{ {
Debug( 3, "Capturing" ); Debug( 3, "Capturing" );
uint8_t* buffer = NULL; static uint8_t* buffer = NULL;
uint8_t* directbuffer = NULL; static uint8_t* directbuffer = NULL;
static int capture_frame = -1;
int captures_per_frame = 1; int captures_per_frame = 1;
if ( channel_count > 1 ) if ( channel_count > 1 )
@ -1832,7 +1831,6 @@ int LocalCamera::Capture( Image &image )
// Do the capture, unless we are the second or subsequent camera on a channel, in which case just reuse the buffer // Do the capture, unless we are the second or subsequent camera on a channel, in which case just reuse the buffer
if ( channel_prime ) if ( channel_prime )
{ {
int capture_frame = -1;
#if ZM_HAS_V4L2 #if ZM_HAS_V4L2
if ( v4l_version == 2 ) if ( v4l_version == 2 )
{ {
@ -1907,6 +1905,8 @@ int LocalCamera::Capture( Image &image )
buffer = v4l1_data.bufptr+v4l1_data.frames.offsets[capture_frame]; buffer = v4l1_data.bufptr+v4l1_data.frames.offsets[capture_frame];
#endif // ZM_HAS_V4L1 #endif // ZM_HAS_V4L1
} }
} /* prime capture */
if(conversion_type != 0) { if(conversion_type != 0) {
Debug( 3, "Performing format conversion" ); Debug( 3, "Performing format conversion" );
@ -1939,7 +1939,6 @@ int LocalCamera::Capture( Image &image )
image.Assign( width, height, colours, subpixelorder, buffer, imagesize); image.Assign( width, height, colours, subpixelorder, buffer, imagesize);
} }
} /* prime capture */
return( 0 ); return( 0 );
} }
@ -1948,7 +1947,7 @@ int LocalCamera::PostCapture()
{ {
Debug( 2, "Post-capturing" ); Debug( 2, "Post-capturing" );
// Requeue the buffer unless we need to switch or are a duplicate camera on a channel // Requeue the buffer unless we need to switch or are a duplicate camera on a channel
if ( channel_count == 1 || channel_prime ) if ( channel_count > 1 || channel_prime )
{ {
#if ZM_HAS_V4L2 #if ZM_HAS_V4L2
if ( v4l_version == 2 ) if ( v4l_version == 2 )

View File

@ -99,9 +99,9 @@ protected:
#endif // ZM_HAS_V4L1 #endif // ZM_HAS_V4L1
#if HAVE_LIBSWSCALE #if HAVE_LIBSWSCALE
static AVFrame **capturePictures;
PixelFormat imagePixFormat; PixelFormat imagePixFormat;
PixelFormat capturePixFormat; PixelFormat capturePixFormat;
static AVFrame **capturePictures;
struct SwsContext *imgConversionContext; struct SwsContext *imgConversionContext;
AVFrame *tmpPicture; AVFrame *tmpPicture;
#endif // HAVE_LIBSWSCALE #endif // HAVE_LIBSWSCALE

View File

@ -556,9 +556,6 @@ Monitor::~Monitor()
if ( munmap( mem_ptr, mem_size ) < 0 ) if ( munmap( mem_ptr, mem_size ) < 0 )
Fatal( "Can't munmap: %s", strerror(errno) ); Fatal( "Can't munmap: %s", strerror(errno) );
close( map_fd ); close( map_fd );
/* Remove the memory file to avoid getting unexpected memory size error */
if( purpose == CAPTURE )
unlink(mem_file);
#else // ZM_MEM_MAPPED #else // ZM_MEM_MAPPED
struct shmid_ds shm_data; struct shmid_ds shm_data;
if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 ) if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 )

View File

@ -235,7 +235,7 @@ int RemoteCameraRtsp::Capture( Image &image )
{ {
/* the picture is allocated by the decoder. no need to free it */ /* the picture is allocated by the decoder. no need to free it */
Debug( 1, "Got picture %d", frameCount ); Debug( 1, "Got picture %d", frameCount );
#if HAVE_LIBSWSCALE
static struct SwsContext *img_convert_ctx = 0; static struct SwsContext *img_convert_ctx = 0;
if ( !img_convert_ctx ) if ( !img_convert_ctx )
@ -246,7 +246,7 @@ int RemoteCameraRtsp::Capture( Image &image )
} }
sws_scale( img_convert_ctx, picture->data, picture->linesize, 0, height, tmp_picture->data, tmp_picture->linesize ); sws_scale( img_convert_ctx, picture->data, picture->linesize, 0, height, tmp_picture->data, tmp_picture->linesize );
#endif
image.Assign( width, height, colours, subpixelorder, tmp_picture->data[0], imagesize); image.Assign( width, height, colours, subpixelorder, tmp_picture->data[0], imagesize);
frameCount++; frameCount++;