/* * 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(); data->newImage.updateValueSignal(true); } 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_BGRA; mTargetChroma = "RV32"; mBpp = 4; } else if(colours == ZM_COLOUR_RGB24) { subpixelorder = ZM_SUBPIX_ORDER_BGR; mTargetChroma = "RV24"; mBpp = 3; } else if(colours == ZM_COLOUR_GRAY8) { subpixelorder = ZM_SUBPIX_ORDER_NONE; mTargetChroma = "GREY"; 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 ) { while(!mLibvlcData.newImage.getValueImmediate()) 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