@ -12,6 +12,7 @@
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
@ -42,36 +43,32 @@
# include "precomp.hpp"
using namespace cv ;
using namespace cv : : gpu ;
using namespace cv : : gpucodec ;
# if !defined(HAVE_NVCUVID) || !defined(WIN32)
class cv : : gpu : : VideoWriter_GPU : : Impl
{
} ;
cv : : gpu : : VideoWriter_GPU : : VideoWriter_GPU ( ) { throw_no_cuda ( ) ; }
cv : : gpu : : VideoWriter_GPU : : VideoWriter_GPU ( const String & , cv : : Size , double , SurfaceFormat ) { throw_no_cuda ( ) ; }
cv : : gpu : : VideoWriter_GPU : : VideoWriter_GPU ( const String & , cv : : Size , double , const EncoderParams & , SurfaceFormat ) { throw_no_cuda ( ) ; }
cv : : gpu : : VideoWriter_GPU : : VideoWriter_GPU ( const cv : : Ptr < EncoderCallBack > & , cv : : Size , double , SurfaceFormat ) { throw_no_cuda ( ) ; }
cv : : gpu : : VideoWriter_GPU : : VideoWriter_GPU ( const cv : : Ptr < EncoderCallBack > & , cv : : Size , double , const EncoderParams & , SurfaceFormat ) { throw_no_cuda ( ) ; }
cv : : gpu : : VideoWriter_GPU : : ~ VideoWriter_GPU ( ) { }
void cv : : gpu : : VideoWriter_GPU : : open ( const String & , cv : : Size , double , SurfaceFormat ) { throw_no_cuda ( ) ; }
void cv : : gpu : : VideoWriter_GPU : : open ( const String & , cv : : Size , double , const EncoderParams & , SurfaceFormat ) { throw_no_cuda ( ) ; }
void cv : : gpu : : VideoWriter_GPU : : open ( const cv : : Ptr < EncoderCallBack > & , cv : : Size , double , SurfaceFormat ) { throw_no_cuda ( ) ; }
void cv : : gpu : : VideoWriter_GPU : : open ( const cv : : Ptr < EncoderCallBack > & , cv : : Size , double , const EncoderParams & , SurfaceFormat ) { throw_no_cuda ( ) ; }
bool cv : : gpu : : VideoWriter_GPU : : isOpened ( ) const { return false ; }
void cv : : gpu : : VideoWriter_GPU : : close ( ) { }
void cv : : gpu : : VideoWriter_GPU : : write ( const cv : : gpu : : GpuMat & , bool ) { throw_no_cuda ( ) ; }
cv : : gpu : : VideoWriter_GPU : : EncoderParams cv : : gpu : : VideoWriter_GPU : : getParams ( ) const { EncoderParams params ; throw_no_cuda ( ) ; return params ; }
cv : : gpu : : VideoWriter_GPU : : EncoderParams : : EncoderParams ( ) { throw_no_cuda ( ) ; }
cv : : gpu : : VideoWriter_GPU : : EncoderParams : : EncoderParams ( const String & ) { throw_no_cuda ( ) ; }
void cv : : gpu : : VideoWriter_GPU : : EncoderParams : : load ( const String & ) { throw_no_cuda ( ) ; }
void cv : : gpu : : VideoWriter_GPU : : EncoderParams : : save ( const String & ) const { throw_no_cuda ( ) ; }
cv : : gpucodec : : EncoderParams : : EncoderParams ( ) { throw_no_cuda ( ) ; }
cv : : gpucodec : : EncoderParams : : EncoderParams ( const String & ) { throw_no_cuda ( ) ; }
void cv : : gpucodec : : EncoderParams : : load ( const String & ) { throw_no_cuda ( ) ; }
void cv : : gpucodec : : EncoderParams : : save ( const String & ) const { throw_no_cuda ( ) ; }
Ptr < VideoWriter > cv : : gpucodec : : createVideoWriter ( const String & , Size , double , SurfaceFormat ) { throw_no_cuda ( ) ; return Ptr < VideoWriter > ( ) ; }
Ptr < VideoWriter > cv : : gpucodec : : createVideoWriter ( const String & , Size , double , const EncoderParams & , SurfaceFormat ) { throw_no_cuda ( ) ; return Ptr < VideoWriter > ( ) ; }
Ptr < VideoWriter > cv : : gpucodec : : createVideoWriter ( const Ptr < EncoderCallBack > & , Size , double , SurfaceFormat ) { throw_no_cuda ( ) ; return Ptr < VideoWriter > ( ) ; }
Ptr < VideoWriter > cv : : gpucodec : : createVideoWriter ( const Ptr < EncoderCallBack > & , Size , double , const EncoderParams & , SurfaceFormat ) { throw_no_cuda ( ) ; return Ptr < VideoWriter > ( ) ; }
# else // !defined HAVE_CUDA || !defined WIN32
namespace cv { namespace gpu { namespace cudev
{
void RGB_to_YV12 ( const PtrStepSzb src , int cn , PtrStepSzb dst , cudaStream_t stream = 0 ) ;
} } }
///////////////////////////////////////////////////////////////////////////
// VideoWriter_GPU::Impl
// VideoWriterImpl
namespace
{
@ -84,7 +81,7 @@ namespace
err = NVGetHWEncodeCaps ( ) ;
if ( err )
CV_Error ( cv : : Error : : GpuNotSupported , " No CUDA capability present " ) ;
CV_Error ( Error : : GpuNotSupported , " No CUDA capability present " ) ;
// Create the Encoder API Interface
err = NVCreateEncoder ( & encoder_ ) ;
@ -108,35 +105,31 @@ namespace
enum CodecType
{
MPEG1 , //not supported yet
MPEG2 , //not supported yet
MPEG4 , //not supported yet
MPEG1 , // not supported yet
MPEG2 , // not supported yet
MPEG4 , // not supported yet
H264
} ;
}
class cv : : gpu : : VideoWriter_GPU : : Impl
{
public :
Impl ( const cv : : Ptr < EncoderCallBack > & callback , cv : : Size frameSize , double fps , SurfaceFormat format , CodecType codec = H264 ) ;
Impl ( const cv : : Ptr < EncoderCallBack > & callback , cv : : Size frameSize , double fps , const EncoderParams & params , SurfaceFormat format , CodecType codec = H264 ) ;
void write ( const cv : : gpu : : GpuMat & image , bool lastFrame ) ;
class VideoWriterImpl : public VideoWriter
{
public :
VideoWriterImpl ( const Ptr < EncoderCallBack > & callback , Size frameSize , double fps , SurfaceFormat format , CodecType codec = H264 ) ;
VideoWriterImpl ( const Ptr < EncoderCallBack > & callback , Size frameSize , double fps , const EncoderParams & params , SurfaceFormat format , CodecType codec = H264 ) ;
EncoderParams getParams ( ) const ;
void write ( InputArray frame , bool lastFrame = false ) ;
private :
Impl ( const Impl & ) ;
Impl & operator = ( const Impl & ) ;
EncoderParams getEncoderParams ( ) const ;
private :
void initEncoder ( double fps ) ;
void setEncodeParams ( const EncoderParams & params ) ;
void initGpuMemory ( ) ;
void initCallBacks ( ) ;
void createHWEncoder ( ) ;
cv : : Ptr < EncoderCallBack > callback_ ;
cv : : Size frameSize_ ;
Ptr < EncoderCallBack > callback_ ;
Size frameSize_ ;
CodecType codec_ ;
SurfaceFormat inputFormat_ ;
@ -144,7 +137,7 @@ private:
NVEncoderWrapper encoder_ ;
cv : : gpu : : GpuMat videoFrame_ ;
GpuMat videoFrame_ ;
CUvideoctxlock cuCtxLock_ ;
// CallBacks
@ -153,16 +146,16 @@ private:
static void NVENCAPI HandleReleaseBitStream ( int nBytesInBuffer , unsigned char * cb , void * pUserdata ) ;
static void NVENCAPI HandleOnBeginFrame ( const NVVE_BeginFrameInfo * pbfi , void * pUserdata ) ;
static void NVENCAPI HandleOnEndFrame ( const NVVE_EndFrameInfo * pefi , void * pUserdata ) ;
} ;
} ;
cv : : gpu : : VideoWriter_GPU : : Impl : : Impl ( const cv : : Ptr < EncoderCallBack > & callback , cv : : Size frameSize , double fps , SurfaceFormat format , CodecType codec ) :
VideoWriterImpl : : VideoWriter Impl( const Ptr < EncoderCallBack > & callback , Size frameSize , double fps , SurfaceFormat format , CodecType codec ) :
callback_ ( callback ) ,
frameSize_ ( frameSize ) ,
codec_ ( codec ) ,
inputFormat_ ( format ) ,
cuCtxLock_ ( 0 )
{
surfaceFormat_ = inputFormat_ = = SF_BGR ? YV12 : static_cast < NVVE_SurfaceFormat > ( inputFormat_ ) ;
{
surfaceFormat_ = ( inputFormat_ = = SF_BGR ? YV12 : static_cast < NVVE_SurfaceFormat > ( inputFormat_ ) ) ;
initEncoder ( fps ) ;
@ -171,16 +164,16 @@ cv::gpu::VideoWriter_GPU::Impl::Impl(const cv::Ptr<EncoderCallBack>& callback, c
initCallBacks ( ) ;
createHWEncoder ( ) ;
}
}
cv : : gpu : : VideoWriter_GPU : : Impl : : Impl ( const cv : : Ptr < EncoderCallBack > & callback , cv : : Size frameSize , double fps , const EncoderParams & params , SurfaceFormat format , CodecType codec ) :
VideoWriterImpl : : VideoWriter Impl( const Ptr < EncoderCallBack > & callback , Size frameSize , double fps , const EncoderParams & params , SurfaceFormat format , CodecType codec ) :
callback_ ( callback ) ,
frameSize_ ( frameSize ) ,
codec_ ( codec ) ,
inputFormat_ ( format ) ,
cuCtxLock_ ( 0 )
{
surfaceFormat_ = inputFormat_ = = SF_BGR ? YV12 : static_cast < NVVE_SurfaceFormat > ( inputFormat_ ) ;
{
surfaceFormat_ = ( inputFormat_ = = SF_BGR ? YV12 : static_cast < NVVE_SurfaceFormat > ( inputFormat_ ) ) ;
initEncoder ( fps ) ;
@ -191,10 +184,10 @@ cv::gpu::VideoWriter_GPU::Impl::Impl(const cv::Ptr<EncoderCallBack>& callback, c
initCallBacks ( ) ;
createHWEncoder ( ) ;
}
}
void cv : : gpu : : VideoWriter_GPU : : Impl : : initEncoder ( double fps )
{
void VideoWriterImpl : : initEncoder ( double fps )
{
int err ;
// Set codec
@ -205,7 +198,7 @@ void cv::gpu::VideoWriter_GPU::Impl::initEncoder(double fps)
} ;
err = NVSetCodec ( encoder_ , codecs_id [ codec_ ] ) ;
if ( err )
CV_Error ( cv : : Error : : StsNotImplemented , " Codec format is not supported " ) ;
CV_Error ( Error : : StsNotImplemented , " Codec format is not supported " ) ;
// Set default params
@ -239,13 +232,13 @@ void cv::gpu::VideoWriter_GPU::Impl::initEncoder(double fps)
// Select device for encoding
int gpuID = cv : : gpu : : getDevice ( ) ;
int gpuID = getDevice ( ) ;
err = NVSetParamValue ( encoder_ , NVVE_FORCE_GPU_SELECTION , & gpuID ) ;
CV_Assert ( err = = 0 ) ;
}
}
void cv : : gpu : : VideoWriter_GPU : : Impl : : setEncodeParams ( const EncoderParams & params )
{
void VideoWriterImpl : : setEncodeParams ( const EncoderParams & params )
{
int err ;
int P_Interval = params . P_Interval ;
@ -312,24 +305,24 @@ void cv::gpu::VideoWriter_GPU::Impl::setEncodeParams(const EncoderParams& params
{
NVVE_PRESETS_TARGET Presets = static_cast < NVVE_PRESETS_TARGET > ( params . Presets ) ;
err = NVSetParamValue ( encoder_ , NVVE_PRESETS , & Presets ) ;
CV_Assert ( err = = 0 ) ;
CV_Assert ( err = = 0 ) ;
}
int DisableCabac = params . DisableCabac ;
err = NVSetParamValue ( encoder_ , NVVE_DISABLE_CABAC , & DisableCabac ) ;
CV_Assert ( err = = 0 ) ;
CV_Assert ( err = = 0 ) ;
int NaluFramingType = params . NaluFramingType ;
err = NVSetParamValue ( encoder_ , NVVE_CONFIGURE_NALU_FRAMING_TYPE , & NaluFramingType ) ;
CV_Assert ( err = = 0 ) ;
CV_Assert ( err = = 0 ) ;
int DisableSPSPPS = params . DisableSPSPPS ;
err = NVSetParamValue ( encoder_ , NVVE_DISABLE_SPS_PPS , & DisableSPSPPS ) ;
CV_Assert ( err = = 0 ) ;
}
CV_Assert ( err = = 0 ) ;
}
cv : : gpu : : VideoWriter_GPU : : EncoderParams cv : : gpu : : VideoWriter_GPU : : Impl : : getParams ( ) const
{
EncoderParams VideoWriterImpl : : getEncoder Params ( ) const
{
int err ;
EncoderParams params ;
@ -413,29 +406,28 @@ cv::gpu::VideoWriter_GPU::EncoderParams cv::gpu::VideoWriter_GPU::Impl::getParam
int DisableCabac ;
err = NVGetParamValue ( encoder_ , NVVE_DISABLE_CABAC , & DisableCabac ) ;
CV_Assert ( err = = 0 ) ;
CV_Assert ( err = = 0 ) ;
params . DisableCabac = DisableCabac ;
int NaluFramingType ;
err = NVGetParamValue ( encoder_ , NVVE_CONFIGURE_NALU_FRAMING_TYPE , & NaluFramingType ) ;
CV_Assert ( err = = 0 ) ;
CV_Assert ( err = = 0 ) ;
params . NaluFramingType = NaluFramingType ;
int DisableSPSPPS ;
err = NVGetParamValue ( encoder_ , NVVE_DISABLE_SPS_PPS , & DisableSPSPPS ) ;
CV_Assert ( err = = 0 ) ;
CV_Assert ( err = = 0 ) ;
params . DisableSPSPPS = DisableSPSPPS ;
return params ;
}
}
void cv : : gpu : : VideoWriter_GPU : : Impl : : initGpuMemory ( )
{
void VideoWriterImpl : : initGpuMemory ( )
{
int err ;
CUresult cuRes ;
// initialize context
cv : : gpu : : GpuMat temp ( 1 , 1 , CV_8U ) ;
GpuMat temp ( 1 , 1 , CV_8U ) ;
temp . release ( ) ;
static const int bpp [ ] =
@ -448,8 +440,7 @@ void cv::gpu::VideoWriter_GPU::Impl::initGpuMemory()
} ;
CUcontext cuContext ;
cuRes = cuCtxGetCurrent ( & cuContext ) ;
CV_Assert ( cuRes = = CUDA_SUCCESS ) ;
cuSafeCall ( cuCtxGetCurrent ( & cuContext ) ) ;
// Allocate the CUDA memory Pitched Surface
if ( surfaceFormat_ = = UYVY | | surfaceFormat_ = = YUY2 )
@ -458,22 +449,21 @@ void cv::gpu::VideoWriter_GPU::Impl::initGpuMemory()
videoFrame_ . create ( ( frameSize_ . height * bpp [ surfaceFormat_ ] ) / 8 , frameSize_ . width , CV_8UC1 ) ;
// Create the Video Context Lock (used for synchronization)
cuRes = cuvidCtxLockCreate ( & cuCtxLock_ , cuContext ) ;
CV_Assert ( cuRes = = CUDA_SUCCESS ) ;
cuSafeCall ( cuvidCtxLockCreate ( & cuCtxLock_ , cuContext ) ) ;
// If we are using GPU Device Memory with NVCUVENC, it is necessary to create a
// CUDA Context with a Context Lock cuvidCtxLock. The Context Lock needs to be passed to NVCUVENC
int iUseDeviceMem = 1 ;
err = NVSetParamValue ( encoder_ , NVVE_DEVICE_MEMORY_INPUT , & iUseDeviceMem ) ;
CV_Assert ( err = = 0 ) ;
CV_Assert ( err = = 0 ) ;
err = NVSetParamValue ( encoder_ , NVVE_DEVICE_CTX_LOCK , & cuCtxLock_ ) ;
CV_Assert ( err = = 0 ) ;
}
CV_Assert ( err = = 0 ) ;
}
void cv : : gpu : : VideoWriter_GPU : : Impl : : initCallBacks ( )
{
void VideoWriterImpl : : initCallBacks ( )
{
NVVE_CallbackParams cb ;
memset ( & cb , 0 , sizeof ( NVVE_CallbackParams ) ) ;
@ -483,30 +473,27 @@ void cv::gpu::VideoWriter_GPU::Impl::initCallBacks()
cb . pfnreleasebitstream = HandleReleaseBitStream ;
NVRegisterCB ( encoder_ , cb , this ) ;
}
}
void cv : : gpu : : VideoWriter_GPU : : Impl : : createHWEncoder ( )
{
void VideoWriterImpl : : createHWEncoder ( )
{
int err ;
// Create the NVIDIA HW resources for Encoding on NVIDIA hardware
err = NVCreateHWEncoder ( encoder_ ) ;
CV_Assert ( err = = 0 ) ;
}
}
namespace
{
// UYVY/YUY2 are both 4:2:2 formats (16bpc)
// Luma, U, V are interleaved, chroma is subsampled (w/2,h)
void copyUYVYorYUY2Frame ( cv : : Size frameSize , const cv : : gpu : : GpuMat & src , cv : : gpu : : GpuMat & dst )
void copyUYVYorYUY2Frame ( Size frameSize , const GpuMat & src , GpuMat & dst )
{
CUresult res ;
// Source is YUVY/YUY2 4:2:2, the YUV data in a packed and interleaved
// YUV Copy setup
CUDA_MEMCPY2D stCopyYUV422 ;
memset ( ( void * ) & stCopyYUV422 , 0 , sizeof ( stCopyYUV422 ) ) ;
memset ( & stCopyYUV422 , 0 , sizeof ( CUDA_MEMCPY2D ) ) ;
stCopyYUV422 . srcXInBytes = 0 ;
stCopyYUV422 . srcY = 0 ;
stCopyYUV422 . srcMemoryType = CU_MEMORYTYPE_DEVICE ;
@ -527,21 +514,19 @@ namespace
stCopyYUV422 . Height = frameSize . height ;
// DMA Luma/Chroma
res = cuMemcpy2D ( & stCopyYUV422 ) ;
CV_Assert ( res = = CUDA_SUCCESS ) ;
cuSafeCall ( cuMemcpy2D ( & stCopyYUV422 ) ) ;
}
// YV12/IYUV are both 4:2:0 planar formats (12bpc)
// Luma, U, V chroma planar (12bpc), chroma is subsampled (w/2,h/2)
void copyYV12orIYUVFrame ( cv : : Size frameSize , const cv : : gpu : : GpuMat & src , cv : : gpu : : GpuMat & dst )
void copyYV12orIYUVFrame ( Size frameSize , const GpuMat & src , GpuMat & dst )
{
CUresult res ;
// Source is YV12/IYUV, this native format is converted to NV12 format by the video encoder
// (1) luma copy setup
CUDA_MEMCPY2D stCopyLuma ;
memset ( ( void * ) & stCopyLuma , 0 , sizeof ( stCopyLuma ) ) ;
memset ( & stCopyLuma , 0 , sizeof ( CUDA_MEMCPY2D ) ) ;
stCopyLuma . srcXInBytes = 0 ;
stCopyLuma . srcY = 0 ;
stCopyLuma . srcMemoryType = CU_MEMORYTYPE_DEVICE ;
@ -563,7 +548,8 @@ namespace
// (2) chroma copy setup, U/V can be done together
CUDA_MEMCPY2D stCopyChroma ;
memset ( ( void * ) & stCopyChroma , 0 , sizeof ( stCopyChroma ) ) ;
memset ( & stCopyChroma , 0 , sizeof ( CUDA_MEMCPY2D ) ) ;
stCopyChroma . srcXInBytes = 0 ;
stCopyChroma . srcY = frameSize . height < < 1 ; // U/V chroma offset
stCopyChroma . srcMemoryType = CU_MEMORYTYPE_DEVICE ;
@ -584,26 +570,23 @@ namespace
stCopyChroma . Height = frameSize . height ; // U/V are sent together
// DMA Luma
res = cuMemcpy2D ( & stCopyLuma ) ;
CV_Assert ( res = = CUDA_SUCCESS ) ;
cuSafeCall ( cuMemcpy2D ( & stCopyLuma ) ) ;
// DMA Chroma channels (UV side by side)
res = cuMemcpy2D ( & stCopyChroma ) ;
CV_Assert ( res = = CUDA_SUCCESS ) ;
cuSafeCall ( cuMemcpy2D ( & stCopyChroma ) ) ;
}
// NV12 is 4:2:0 format (12bpc)
// Luma followed by U/V chroma interleaved (12bpc), chroma is subsampled (w/2,h/2)
void copyNV12Frame ( cv : : Size frameSize , const cv : : gpu : : GpuMat & src , cv : : gpu : : GpuMat & dst )
void copyNV12Frame ( Size frameSize , const GpuMat & src , GpuMat & dst )
{
CUresult res ;
// Source is NV12 in pitch linear memory
// Because we are assume input is NV12 (if we take input in the native format), the encoder handles NV12 as a native format in pitch linear memory
// Luma/Chroma can be done in a single transfer
CUDA_MEMCPY2D stCopyNV12 ;
memset ( ( void * ) & stCopyNV12 , 0 , sizeof ( stCopyNV12 ) ) ;
memset ( & stCopyNV12 , 0 , sizeof ( CUDA_MEMCPY2D ) ) ;
stCopyNV12 . srcXInBytes = 0 ;
stCopyNV12 . srcY = 0 ;
stCopyNV12 . srcMemoryType = CU_MEMORYTYPE_DEVICE ;
@ -621,21 +604,16 @@ namespace
stCopyNV12 . dstPitch = dst . step ;
stCopyNV12 . WidthInBytes = frameSize . width ;
stCopyNV12 . Height = ( frameSize . height * 3 ) > > 1 ;
stCopyNV12 . Height = ( frameSize . height * 3 ) > > 1 ;
// DMA Luma/Chroma
res = cuMemcpy2D ( & stCopyNV12 ) ;
CV_Assert ( res = = CUDA_SUCCESS ) ;
cuSafeCall ( cuMemcpy2D ( & stCopyNV12 ) ) ;
}
}
namespace cv { namespace gpu { namespace cudev
{
void RGB_to_YV12 ( const PtrStepSzb src , int cn , PtrStepSzb dst , cudaStream_t stream = 0 ) ;
} } }
void VideoWriterImpl : : write ( InputArray _frame , bool lastFrame )
{
GpuMat frame = _frame . getGpuMat ( ) ;
void cv : : gpu : : VideoWriter_GPU : : Impl : : write ( const cv : : gpu : : GpuMat & frame , bool lastFrame )
{
if ( inputFormat_ = = SF_BGR )
{
CV_Assert ( frame . size ( ) = = frameSize_ ) ;
@ -660,11 +638,12 @@ void cv::gpu::VideoWriter_GPU::Impl::write(const cv::gpu::GpuMat& frame, bool la
efparams . picBuf = 0 ; // Must be set to NULL in order to support device memory input
// Don't forget we need to lock/unlock between memcopies
CUresult res = cuvidCtxLock ( cuCtxLock_ , 0 ) ;
CV_Assert ( res = = CUDA_SUCCESS ) ;
cuSafeCall ( cuvidCtxLock ( cuCtxLock_ , 0 ) ) ;
if ( inputFormat_ = = SF_BGR )
cv : : gpu : : cudev : : RGB_to_YV12 ( frame , frame . channels ( ) , videoFrame_ ) ;
{
cudev : : RGB_to_YV12 ( frame , frame . channels ( ) , videoFrame_ ) ;
}
else
{
switch ( surfaceFormat_ )
@ -685,48 +664,47 @@ void cv::gpu::VideoWriter_GPU::Impl::write(const cv::gpu::GpuMat& frame, bool la
}
}
res = cuvidCtxUnlock ( cuCtxLock_ , 0 ) ;
CV_Assert ( res = = CUDA_SUCCESS ) ;
cuSafeCall ( cuvidCtxUnlock ( cuCtxLock_ , 0 ) ) ;
int err = NVEncodeFrame ( encoder_ , & efparams , 0 , videoFrame_ . data ) ;
CV_Assert ( err = = 0 ) ;
}
}
unsigned char * NVENCAPI cv : : gpu : : VideoWriter_GPU : : Impl : : HandleAcquireBitStream ( int * pBufferSize , void * pUserdata )
{
Impl * thiz = static_cast < Impl * > ( pUserdata ) ;
unsigned char * NVENCAPI VideoWriterImpl : : HandleAcquireBitStream ( int * pBufferSize , void * pUserdata )
{
VideoWriter Impl* thiz = static_cast < VideoWriter Impl* > ( pUserdata ) ;
return thiz - > callback_ - > acquireBitStream ( pBufferSize ) ;
}
}
void NVENCAPI cv : : gpu : : VideoWriter_GPU : : Impl : : HandleReleaseBitStream ( int nBytesInBuffer , unsigned char * cb , void * pUserdata )
{
Impl * thiz = static_cast < Impl * > ( pUserdata ) ;
void NVENCAPI VideoWriterImpl : : HandleReleaseBitStream ( int nBytesInBuffer , unsigned char * cb , void * pUserdata )
{
VideoWriter Impl* thiz = static_cast < VideoWriter Impl* > ( pUserdata ) ;
thiz - > callback_ - > releaseBitStream ( cb , nBytesInBuffer ) ;
}
}
void NVENCAPI cv : : gpu : : VideoWriter_GPU : : Impl : : HandleOnBeginFrame ( const NVVE_BeginFrameInfo * pbfi , void * pUserdata )
{
Impl * thiz = static_cast < Impl * > ( pUserdata ) ;
void NVENCAPI VideoWriterImpl : : HandleOnBeginFrame ( const NVVE_BeginFrameInfo * pbfi , void * pUserdata )
{
VideoWriter Impl* thiz = static_cast < VideoWriter Impl* > ( pUserdata ) ;
thiz - > callback_ - > onBeginFrame ( pbfi - > nFrameNumber , static_cast < EncoderCallBack : : PicType > ( pbfi - > nPicType ) ) ;
}
}
void NVENCAPI cv : : gpu : : VideoWriter_GPU : : Impl : : HandleOnEndFrame ( const NVVE_EndFrameInfo * pefi , void * pUserdata )
{
Impl * thiz = static_cast < Impl * > ( pUserdata ) ;
void NVENCAPI VideoWriterImpl : : HandleOnEndFrame ( const NVVE_EndFrameInfo * pefi , void * pUserdata )
{
VideoWriter Impl* thiz = static_cast < VideoWriter Impl* > ( pUserdata ) ;
thiz - > callback_ - > onEndFrame ( pefi - > nFrameNumber , static_cast < EncoderCallBack : : PicType > ( pefi - > nPicType ) ) ;
}
}
///////////////////////////////////////////////////////////////////////////
// FFMPEG
///////////////////////////////////////////////////////////////////////////
// FFMPEG
class EncoderCallBackFFMPEG : public cv : : gpu : : VideoWriter_GPU : : EncoderCallBack
{
public :
EncoderCallBackFFMPEG ( const cv : : String & fileName , cv : : Size frameSize , double fps ) ;
class EncoderCallBackFFMPEG : public EncoderCallBack
{
public :
EncoderCallBackFFMPEG ( const String & fileName , Size frameSize , double fps ) ;
~ EncoderCallBackFFMPEG ( ) ;
unsigned char * acquireBitStream ( int * bufferSize ) ;
@ -734,28 +712,29 @@ public:
void onBeginFrame ( int frameNumber , PicType picType ) ;
void onEndFrame ( int frameNumber , PicType picType ) ;
private :
EncoderCallBackFFMPEG ( const EncoderCallBackFFMPEG & ) ;
EncoderCallBackFFMPEG & operator = ( const EncoderCallBackFFMPEG & ) ;
private :
static bool init_MediaStream_FFMPEG ( ) ;
struct OutputMediaStream_FFMPEG * stream_ ;
std : : vector < uchar > buf_ ;
bool isKeyFrame_ ;
} ;
namespace
{
Create_OutputMediaStream_FFMPEG_Plugin create_OutputMediaStream_FFMPEG_p = 0 ;
Release_OutputMediaStream_FFMPEG_Plugin release_OutputMediaStream_FFMPEG_p = 0 ;
Write_OutputMediaStream_FFMPEG_Plugin write_OutputMediaStream_FFMPEG_p = 0 ;
static Create_OutputMediaStream_FFMPEG_Plugin create_OutputMediaStream_FFMPEG_p ;
static Release_OutputMediaStream_FFMPEG_Plugin release_OutputMediaStream_FFMPEG_p ;
static Write_OutputMediaStream_FFMPEG_Plugin write_OutputMediaStream_FFMPEG_p ;
} ;
bool init_MediaStream_FFMPEG ( )
Create_OutputMediaStream_FFMPEG_Plugin EncoderCallBackFFMPEG : : create_OutputMediaStream_FFMPEG_p = 0 ;
Release_OutputMediaStream_FFMPEG_Plugin EncoderCallBackFFMPEG : : release_OutputMediaStream_FFMPEG_p = 0 ;
Write_OutputMediaStream_FFMPEG_Plugin EncoderCallBackFFMPEG : : write_OutputMediaStream_FFMPEG_p = 0 ;
bool EncoderCallBackFFMPEG : : init_MediaStream_FFMPEG ( )
{
static bool initialized = 0 ;
static bool initialized = false ;
if ( ! initialized )
{
# if defined WIN32 || defined _WIN32
# if defined(WIN32) || defined(_WIN32)
const char * module_name = " opencv_ffmpeg "
CVAUX_STR ( CV_VERSION_EPOCH ) CVAUX_STR ( CV_VERSION_MAJOR ) CVAUX_STR ( CV_VERSION_MINOR )
# if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__)
@ -776,7 +755,7 @@ namespace
initialized = create_OutputMediaStream_FFMPEG_p ! = 0 & & release_OutputMediaStream_FFMPEG_p ! = 0 & & write_OutputMediaStream_FFMPEG_p ! = 0 ;
}
# elif defined HAVE_FFMPEG
# elif defined(HAVE_FFMPEG)
create_OutputMediaStream_FFMPEG_p = create_OutputMediaStream_FFMPEG ;
release_OutputMediaStream_FFMPEG_p = release_OutputMediaStream_FFMPEG ;
write_OutputMediaStream_FFMPEG_p = write_OutputMediaStream_FFMPEG ;
@ -787,11 +766,10 @@ namespace
return initialized ;
}
}
EncoderCallBackFFMPEG : : EncoderCallBackFFMPEG ( const cv : : String & fileName , cv : : Size frameSize , double fps ) :
EncoderCallBackFFMPEG : : EncoderCallBackFFMPEG ( const String & fileName , Size frameSize , double fps ) :
stream_ ( 0 ) , isKeyFrame_ ( false )
{
{
int buf_size = std : : max ( frameSize . area ( ) * 4 , 1024 * 1024 ) ;
buf_ . resize ( buf_size ) ;
@ -799,122 +777,41 @@ EncoderCallBackFFMPEG::EncoderCallBackFFMPEG(const cv::String& fileName, cv::Siz
stream_ = create_OutputMediaStream_FFMPEG_p ( fileName . c_str ( ) , frameSize . width , frameSize . height , fps ) ;
CV_Assert ( stream_ ! = 0 ) ;
}
}
EncoderCallBackFFMPEG : : ~ EncoderCallBackFFMPEG ( )
{
EncoderCallBackFFMPEG : : ~ EncoderCallBackFFMPEG ( )
{
release_OutputMediaStream_FFMPEG_p ( stream_ ) ;
}
}
unsigned char * EncoderCallBackFFMPEG : : acquireBitStream ( int * bufferSize )
{
unsigned char * EncoderCallBackFFMPEG : : acquireBitStream ( int * bufferSize )
{
* bufferSize = static_cast < int > ( buf_ . size ( ) ) ;
return & buf_ [ 0 ] ;
}
}
void EncoderCallBackFFMPEG : : releaseBitStream ( unsigned char * data , int size )
{
void EncoderCallBackFFMPEG : : releaseBitStream ( unsigned char * data , int size )
{
write_OutputMediaStream_FFMPEG_p ( stream_ , data , size , isKeyFrame_ ) ;
}
}
void EncoderCallBackFFMPEG : : onBeginFrame ( int frameNumber , PicType picType )
{
void EncoderCallBackFFMPEG : : onBeginFrame ( int frameNumber , PicType picType )
{
( void ) frameNumber ;
isKeyFrame_ = picType = = IFRAME ;
}
isKeyFrame_ = ( picType = = IFRAME ) ;
}
void EncoderCallBackFFMPEG : : onEndFrame ( int frameNumber , PicType picType )
{
void EncoderCallBackFFMPEG : : onEndFrame ( int frameNumber , PicType picType )
{
( void ) frameNumber ;
( void ) picType ;
}
}
///////////////////////////////////////////////////////////////////////////
// VideoWriter_GPU
cv : : gpu : : VideoWriter_GPU : : VideoWriter_GPU ( )
{
}
cv : : gpu : : VideoWriter_GPU : : VideoWriter_GPU ( const String & fileName , cv : : Size frameSize , double fps , SurfaceFormat format )
{
open ( fileName , frameSize , fps , format ) ;
}
cv : : gpu : : VideoWriter_GPU : : VideoWriter_GPU ( const String & fileName , cv : : Size frameSize , double fps , const EncoderParams & params , SurfaceFormat format )
{
open ( fileName , frameSize , fps , params , format ) ;
}
cv : : gpu : : VideoWriter_GPU : : VideoWriter_GPU ( const cv : : Ptr < EncoderCallBack > & encoderCallback , cv : : Size frameSize , double fps , SurfaceFormat format )
{
open ( encoderCallback , frameSize , fps , format ) ;
}
cv : : gpu : : VideoWriter_GPU : : VideoWriter_GPU ( const cv : : Ptr < EncoderCallBack > & encoderCallback , cv : : Size frameSize , double fps , const EncoderParams & params , SurfaceFormat format )
{
open ( encoderCallback , frameSize , fps , params , format ) ;
}
cv : : gpu : : VideoWriter_GPU : : ~ VideoWriter_GPU ( )
{
close ( ) ;
}
void cv : : gpu : : VideoWriter_GPU : : open ( const String & fileName , cv : : Size frameSize , double fps , SurfaceFormat format )
{
close ( ) ;
cv : : Ptr < EncoderCallBack > encoderCallback ( new EncoderCallBackFFMPEG ( fileName , frameSize , fps ) ) ;
open ( encoderCallback , frameSize , fps , format ) ;
}
void cv : : gpu : : VideoWriter_GPU : : open ( const String & fileName , cv : : Size frameSize , double fps , const EncoderParams & params , SurfaceFormat format )
{
close ( ) ;
cv : : Ptr < EncoderCallBack > encoderCallback ( new EncoderCallBackFFMPEG ( fileName , frameSize , fps ) ) ;
open ( encoderCallback , frameSize , fps , params , format ) ;
}
void cv : : gpu : : VideoWriter_GPU : : open ( const cv : : Ptr < EncoderCallBack > & encoderCallback , cv : : Size frameSize , double fps , SurfaceFormat format )
{
close ( ) ;
impl_ = new Impl ( encoderCallback , frameSize , fps , format ) ;
}
void cv : : gpu : : VideoWriter_GPU : : open ( const cv : : Ptr < EncoderCallBack > & encoderCallback , cv : : Size frameSize , double fps , const EncoderParams & params , SurfaceFormat format )
{
close ( ) ;
impl_ = new Impl ( encoderCallback , frameSize , fps , params , format ) ;
}
bool cv : : gpu : : VideoWriter_GPU : : isOpened ( ) const
{
return ! impl_ . empty ( ) ;
}
void cv : : gpu : : VideoWriter_GPU : : close ( )
{
impl_ . release ( ) ;
}
void cv : : gpu : : VideoWriter_GPU : : write ( const cv : : gpu : : GpuMat & image , bool lastFrame )
{
CV_Assert ( isOpened ( ) ) ;
impl_ - > write ( image , lastFrame ) ;
}
cv : : gpu : : VideoWriter_GPU : : EncoderParams cv : : gpu : : VideoWriter_GPU : : getParams ( ) const
{
CV_Assert ( isOpened ( ) ) ;
return impl_ - > getParams ( ) ;
}
///////////////////////////////////////////////////////////////////////////
// VideoWriter_GPU::EncoderParams
// EncoderParams
cv : : gpu : : VideoWriter_GPU : : EncoderParams : : EncoderParams ( )
cv : : gpucodec : : EncoderParams : : EncoderParams ( )
{
P_Interval = 3 ;
IDR_Period = 15 ;
@ -937,66 +834,86 @@ cv::gpu::VideoWriter_GPU::EncoderParams::EncoderParams()
DisableSPSPPS = 0 ;
}
cv : : gpu : : VideoWriter_GPU : : EncoderParams : : EncoderParams ( const String & configFile )
cv : : gpucodec : : EncoderParams : : EncoderParams ( const String & configFile )
{
load ( configFile ) ;
}
void cv : : gpu : : VideoWriter_GPU : : EncoderParams : : load ( const String & configFile )
void cv : : gpucodec : : EncoderParams : : load ( const String & configFile )
{
cv : : FileStorage fs ( configFile , cv : : FileStorage : : READ ) ;
FileStorage fs ( configFile , FileStorage : : READ ) ;
CV_Assert ( fs . isOpened ( ) ) ;
cv : : read ( fs [ " P_Interval " ] , P_Interval , 3 ) ;
cv : : read ( fs [ " IDR_Period " ] , IDR_Period , 15 ) ;
cv : : read ( fs [ " DynamicGOP " ] , DynamicGOP , 0 ) ;
cv : : read ( fs [ " RCType " ] , RCType , 1 ) ;
cv : : read ( fs [ " AvgBitrate " ] , AvgBitrate , 4000000 ) ;
cv : : read ( fs [ " PeakBitrate " ] , PeakBitrate , 10000000 ) ;
cv : : read ( fs [ " QP_Level_Intra " ] , QP_Level_Intra , 25 ) ;
cv : : read ( fs [ " QP_Level_InterP " ] , QP_Level_InterP , 28 ) ;
cv : : read ( fs [ " QP_Level_InterB " ] , QP_Level_InterB , 31 ) ;
cv : : read ( fs [ " DeblockMode " ] , DeblockMode , 1 ) ;
cv : : read ( fs [ " ProfileLevel " ] , ProfileLevel , 65357 ) ;
cv : : read ( fs [ " ForceIntra " ] , ForceIntra , 0 ) ;
cv : : read ( fs [ " ForceIDR " ] , ForceIDR , 0 ) ;
cv : : read ( fs [ " ClearStat " ] , ClearStat , 0 ) ;
cv : : read ( fs [ " DIMode " ] , DIMode , 1 ) ;
cv : : read ( fs [ " Presets " ] , Presets , 2 ) ;
cv : : read ( fs [ " DisableCabac " ] , DisableCabac , 0 ) ;
cv : : read ( fs [ " NaluFramingType " ] , NaluFramingType , 0 ) ;
cv : : read ( fs [ " DisableSPSPPS " ] , DisableSPSPPS , 0 ) ;
read ( fs [ " P_Interval " ] , P_Interval , 3 ) ;
read ( fs [ " IDR_Period " ] , IDR_Period , 15 ) ;
read ( fs [ " DynamicGOP " ] , DynamicGOP , 0 ) ;
read ( fs [ " RCType " ] , RCType , 1 ) ;
read ( fs [ " AvgBitrate " ] , AvgBitrate , 4000000 ) ;
read ( fs [ " PeakBitrate " ] , PeakBitrate , 10000000 ) ;
read ( fs [ " QP_Level_Intra " ] , QP_Level_Intra , 25 ) ;
read ( fs [ " QP_Level_InterP " ] , QP_Level_InterP , 28 ) ;
read ( fs [ " QP_Level_InterB " ] , QP_Level_InterB , 31 ) ;
read ( fs [ " DeblockMode " ] , DeblockMode , 1 ) ;
read ( fs [ " ProfileLevel " ] , ProfileLevel , 65357 ) ;
read ( fs [ " ForceIntra " ] , ForceIntra , 0 ) ;
read ( fs [ " ForceIDR " ] , ForceIDR , 0 ) ;
read ( fs [ " ClearStat " ] , ClearStat , 0 ) ;
read ( fs [ " DIMode " ] , DIMode , 1 ) ;
read ( fs [ " Presets " ] , Presets , 2 ) ;
read ( fs [ " DisableCabac " ] , DisableCabac , 0 ) ;
read ( fs [ " NaluFramingType " ] , NaluFramingType , 0 ) ;
read ( fs [ " DisableSPSPPS " ] , DisableSPSPPS , 0 ) ;
}
void cv : : gpucodec : : EncoderParams : : save ( const String & configFile ) const
{
FileStorage fs ( configFile , FileStorage : : WRITE ) ;
CV_Assert ( fs . isOpened ( ) ) ;
write ( fs , " P_Interval " , P_Interval ) ;
write ( fs , " IDR_Period " , IDR_Period ) ;
write ( fs , " DynamicGOP " , DynamicGOP ) ;
write ( fs , " RCType " , RCType ) ;
write ( fs , " AvgBitrate " , AvgBitrate ) ;
write ( fs , " PeakBitrate " , PeakBitrate ) ;
write ( fs , " QP_Level_Intra " , QP_Level_Intra ) ;
write ( fs , " QP_Level_InterP " , QP_Level_InterP ) ;
write ( fs , " QP_Level_InterB " , QP_Level_InterB ) ;
write ( fs , " DeblockMode " , DeblockMode ) ;
write ( fs , " ProfileLevel " , ProfileLevel ) ;
write ( fs , " ForceIntra " , ForceIntra ) ;
write ( fs , " ForceIDR " , ForceIDR ) ;
write ( fs , " ClearStat " , ClearStat ) ;
write ( fs , " DIMode " , DIMode ) ;
write ( fs , " Presets " , Presets ) ;
write ( fs , " DisableCabac " , DisableCabac ) ;
write ( fs , " NaluFramingType " , NaluFramingType ) ;
write ( fs , " DisableSPSPPS " , DisableSPSPPS ) ;
}
void cv : : gpu : : VideoWriter_GPU : : EncoderParams : : save ( const String & configFile ) const
///////////////////////////////////////////////////////////////////////////
// createVideoWriter
Ptr < VideoWriter > cv : : gpucodec : : createVideoWriter ( const String & fileName , Size frameSize , double fps , SurfaceFormat format )
{
cv : : FileStorage fs ( configFile , cv : : FileStorage : : WRITE ) ;
CV_Assert ( fs . isOpened ( ) ) ;
Ptr < EncoderCallBack > encoderCallback ( new EncoderCallBackFFMPEG ( fileName , frameSize , fps ) ) ;
return createVideoWriter ( encoderCallback , frameSize , fps , format ) ;
}
cv : : write ( fs , " P_Interval " , P_Interval ) ;
cv : : write ( fs , " IDR_Period " , IDR_Period ) ;
cv : : write ( fs , " DynamicGOP " , DynamicGOP ) ;
cv : : write ( fs , " RCType " , RCType ) ;
cv : : write ( fs , " AvgBitrate " , AvgBitrate ) ;
cv : : write ( fs , " PeakBitrate " , PeakBitrate ) ;
cv : : write ( fs , " QP_Level_Intra " , QP_Level_Intra ) ;
cv : : write ( fs , " QP_Level_InterP " , QP_Level_InterP ) ;
cv : : write ( fs , " QP_Level_InterB " , QP_Level_InterB ) ;
cv : : write ( fs , " DeblockMode " , DeblockMode ) ;
cv : : write ( fs , " ProfileLevel " , ProfileLevel ) ;
cv : : write ( fs , " ForceIntra " , ForceIntra ) ;
cv : : write ( fs , " ForceIDR " , ForceIDR ) ;
cv : : write ( fs , " ClearStat " , ClearStat ) ;
cv : : write ( fs , " DIMode " , DIMode ) ;
cv : : write ( fs , " Presets " , Presets ) ;
cv : : write ( fs , " DisableCabac " , DisableCabac ) ;
cv : : write ( fs , " NaluFramingType " , NaluFramingType ) ;
cv : : write ( fs , " DisableSPSPPS " , DisableSPSPPS ) ;
Ptr < VideoWriter > cv : : gpucodec : : createVideoWriter ( const String & fileName , Size frameSize , double fps , const EncoderParams & params , SurfaceFormat format )
{
Ptr < EncoderCallBack > encoderCallback ( new EncoderCallBackFFMPEG ( fileName , frameSize , fps ) ) ;
return createVideoWriter ( encoderCallback , frameSize , fps , params , format ) ;
}
# endif // !defined HAVE_CUDA || !defined WIN32
Ptr < VideoWriter > cv : : gpucodec : : createVideoWriter ( const Ptr < EncoderCallBack > & encoderCallback , Size frameSize , double fps , SurfaceFormat format )
{
return new VideoWriterImpl ( encoderCallback , frameSize , fps , format ) ;
}
template < > void cv : : Ptr < cv : : gpu : : VideoWriter_GPU : : Impl > : : delete_obj ( )
Ptr < VideoWriter > cv : : gpucodec : : createVideoWriter ( const Ptr < EncoderCallBack > & encoderCallback , Size frameSize , double fps , const EncoderParams & params , SurfaceFormat format )
{
if ( obj ) delete obj ;
return new VideoWriterImpl ( encoderCallback , frameSize , fps , params , format ) ;
}
# endif // !defined HAVE_CUDA || !defined WIN32