2013-12-13 01:45:29 +08:00
|
|
|
/*
|
|
|
|
* ZoneMinder Libvlc Camera Class Implementation, $Date$, $Revision$
|
|
|
|
* Copyright (C) 2001-2008 Philip Coombes
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "zm.h"
|
|
|
|
#include "zm_libvlc_camera.h"
|
|
|
|
|
|
|
|
#if HAVE_LIBVLC
|
|
|
|
|
|
|
|
void* LibvlcLockBuffer(void* opaque, void** planes)
|
|
|
|
{
|
|
|
|
LibvlcPrivateData* data = (LibvlcPrivateData*)opaque;
|
|
|
|
data->mutex.lock();
|
|
|
|
*planes = data->buffer;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes)
|
|
|
|
{
|
|
|
|
LibvlcPrivateData* data = (LibvlcPrivateData*)opaque;
|
|
|
|
data->mutex.unlock();
|
2013-12-13 02:09:30 +08:00
|
|
|
data->newImage.updateValueSignal(true);
|
2013-12-13 01:45:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
LibvlcCamera::LibvlcCamera( int p_id, const std::string &p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) :
|
|
|
|
Camera( p_id, LIBVLC_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ),
|
|
|
|
mPath( p_path )
|
|
|
|
{
|
|
|
|
mLibvlcInstance = NULL;
|
|
|
|
mLibvlcMedia = NULL;
|
|
|
|
mLibvlcMediaPlayer = NULL;
|
|
|
|
|
|
|
|
/* Has to be located inside the constructor so other components such as zma will receive correct colours and subpixel order */
|
|
|
|
if(colours == ZM_COLOUR_RGB32) {
|
|
|
|
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
|
|
|
mTargetChroma = "RV32";
|
|
|
|
mBpp = 4;
|
|
|
|
} else if(colours == ZM_COLOUR_RGB24) {
|
|
|
|
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
|
|
|
mTargetChroma = "RV24";
|
|
|
|
mBpp = 3;
|
|
|
|
} else if(colours == ZM_COLOUR_GRAY8) {
|
|
|
|
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
|
|
|
mTargetChroma = "RGB8";
|
|
|
|
mBpp = 1;
|
|
|
|
} else {
|
|
|
|
Panic("Unexpected colours: %d",colours);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( capture )
|
|
|
|
{
|
|
|
|
Initialise();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LibvlcCamera::~LibvlcCamera()
|
|
|
|
{
|
|
|
|
if ( capture )
|
|
|
|
{
|
|
|
|
Terminate();
|
|
|
|
}
|
|
|
|
if(mLibvlcMediaPlayer != NULL)
|
|
|
|
{
|
|
|
|
libvlc_media_player_release(mLibvlcMediaPlayer);
|
|
|
|
mLibvlcMediaPlayer = NULL;
|
|
|
|
}
|
|
|
|
if(mLibvlcMedia != NULL)
|
|
|
|
{
|
|
|
|
libvlc_media_release(mLibvlcMedia);
|
|
|
|
mLibvlcMedia = NULL;
|
|
|
|
}
|
|
|
|
if(mLibvlcInstance != NULL)
|
|
|
|
{
|
|
|
|
libvlc_release(mLibvlcInstance);
|
|
|
|
mLibvlcInstance = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LibvlcCamera::Initialise()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void LibvlcCamera::Terminate()
|
|
|
|
{
|
|
|
|
libvlc_media_player_stop(mLibvlcMediaPlayer);
|
|
|
|
|
|
|
|
zm_freealigned(mLibvlcData.buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
int LibvlcCamera::PrimeCapture()
|
|
|
|
{
|
|
|
|
Info("Priming capture from %s", mPath.c_str());
|
|
|
|
|
|
|
|
mLibvlcInstance = libvlc_new (0, NULL);
|
|
|
|
if(mLibvlcInstance == NULL)
|
|
|
|
Fatal("Unable to create libvlc instance due to: %s", strerror(errno));
|
|
|
|
|
|
|
|
mLibvlcMedia = libvlc_media_new_location(mLibvlcInstance, mPath.c_str());
|
|
|
|
if(mLibvlcMedia == NULL)
|
|
|
|
Fatal( "Unable to open input %s due to: %s", mPath.c_str(), strerror(errno) );
|
|
|
|
|
|
|
|
mLibvlcMediaPlayer = libvlc_media_player_new_from_media(mLibvlcMedia);
|
|
|
|
if(mLibvlcMediaPlayer == NULL)
|
|
|
|
Fatal( "Unable to create player for %s due to: %s", mPath.c_str(), strerror(errno) );
|
|
|
|
|
|
|
|
libvlc_video_set_format(mLibvlcMediaPlayer, mTargetChroma.c_str(), width, height, width * mBpp);
|
|
|
|
libvlc_video_set_callbacks(mLibvlcMediaPlayer, &LibvlcLockBuffer, &LibvlcUnlockBuffer, NULL, &mLibvlcData);
|
|
|
|
|
|
|
|
mLibvlcData.buffer = (uint8_t*)zm_mallocaligned(32, width * height * mBpp);
|
|
|
|
mLibvlcData.newImage.setValueImmediate(false);
|
|
|
|
|
|
|
|
libvlc_media_player_play(mLibvlcMediaPlayer);
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int LibvlcCamera::PreCapture()
|
|
|
|
{
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should not return -1 as cancels capture. Always wait for image if available.
|
|
|
|
int LibvlcCamera::Capture( Image &image )
|
|
|
|
{
|
2013-12-13 02:09:30 +08:00
|
|
|
while(!mLibvlcData.newImage.getValueImmediate())
|
2013-12-13 01:45:29 +08:00
|
|
|
mLibvlcData.newImage.getUpdatedValue(1);
|
|
|
|
|
|
|
|
mLibvlcData.mutex.lock();
|
|
|
|
image.Assign(width, height, colours, subpixelorder, mLibvlcData.buffer, width * height * mBpp);
|
|
|
|
mLibvlcData.newImage.setValueImmediate(false);
|
|
|
|
mLibvlcData.mutex.unlock();
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int LibvlcCamera::PostCapture()
|
|
|
|
{
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // HAVE_LIBVLC
|