ocv_module_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src/cuda")
+ocv_module_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../highgui/src")
+
file(GLOB lib_hdrs "include/opencv2/${name}/*.hpp" "include/opencv2/${name}/*.h")
file(GLOB lib_int_hdrs "src/*.hpp" "src/*.h")
file(GLOB lib_cuda_hdrs "src/cuda/*.hpp" "src/cuda/*.h")
OCV_CUDA_COMPILE(cuda_objs ${lib_cuda} ${ncv_cuda})
#CUDA_BUILD_CLEAN_TARGET()
- set(cuda_link_libs ${CUDA_LIBRARIES} ${CUDA_npp_LIBRARY})
+ unset(CUDA_nvcuvid_LIBRARY CACHE)
+ find_cuda_helper_libs(nvcuvid)
+
+ if (WIN32)
+ unset(CUDA_nvcuvenc_LIBRARY CACHE)
+ find_cuda_helper_libs(nvcuvenc)
+ endif()
+
+ set(cuda_link_libs ${CUDA_LIBRARIES} ${CUDA_npp_LIBRARY} ${CUDA_nvcuvid_LIBRARY})
+
+ if (WIN32)
+ set(cuda_link_libs ${cuda_link_libs} ${CUDA_nvcuvenc_LIBRARY})
+ endif()
else()
set(lib_cuda "")
set(cuda_objs "")
SOURCES ${lib_int_hdrs} ${lib_cuda_hdrs} ${lib_device_hdrs} ${lib_device_hdrs_detail} ${lib_srcs} ${lib_cuda} ${ncv_files} ${cuda_objs}
)
-ocv_create_module(${cuda_link_libs})
+ocv_create_module(${cuda_link_libs} ${HIGHGUI_LIBRARIES})
if(HAVE_CUDA)
if(HAVE_CUFFT)
\r
#ifndef SKIP_INCLUDES\r
#include <vector>\r
+#include <memory>\r
#endif\r
\r
#include "opencv2/core/gpumat.hpp"\r
\r
CV_EXPORTS void createOpticalFlowNeedleMap(const GpuMat& u, const GpuMat& v, GpuMat& vertex, GpuMat& colors);\r
\r
+\r
+////////////////////////////////// Video Encoding //////////////////////////////////////////\r
+\r
+// Works only under Windows\r
+// Supports olny H264 video codec and AVI files\r
+class CV_EXPORTS VideoWriter_GPU\r
+{\r
+public:\r
+ struct EncoderParams;\r
+\r
+ // Callbacks for video encoder, use it if you want to work with raw video stream\r
+ class EncoderCallBack;\r
+\r
+ VideoWriter_GPU();\r
+ VideoWriter_GPU(const std::string& fileName, cv::Size frameSize, double fps);\r
+ VideoWriter_GPU(const std::string& fileName, cv::Size frameSize, double fps, const EncoderParams& params);\r
+ VideoWriter_GPU(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps);\r
+ VideoWriter_GPU(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps, const EncoderParams& params);\r
+ ~VideoWriter_GPU();\r
+\r
+ // all methods throws cv::Exception if error occurs\r
+ void open(const std::string& fileName, cv::Size frameSize, double fps);\r
+ void open(const std::string& fileName, cv::Size frameSize, double fps, const EncoderParams& params);\r
+ void open(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps);\r
+ void open(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps, const EncoderParams& params);\r
+\r
+ bool isOpened() const;\r
+ void close();\r
+\r
+ void write(const cv::gpu::GpuMat& image, bool lastFrame = false);\r
+\r
+ struct EncoderParams\r
+ {\r
+ int P_Interval; // NVVE_P_INTERVAL,\r
+ int IDR_Period; // NVVE_IDR_PERIOD,\r
+ int DynamicGOP; // NVVE_DYNAMIC_GOP,\r
+ int RCType; // NVVE_RC_TYPE,\r
+ int AvgBitrate; // NVVE_AVG_BITRATE,\r
+ int PeakBitrate; // NVVE_PEAK_BITRATE,\r
+ int QP_Level_Intra; // NVVE_QP_LEVEL_INTRA,\r
+ int QP_Level_InterP; // NVVE_QP_LEVEL_INTER_P,\r
+ int QP_Level_InterB; // NVVE_QP_LEVEL_INTER_B,\r
+ int DeblockMode; // NVVE_DEBLOCK_MODE,\r
+ int ProfileLevel; // NVVE_PROFILE_LEVEL,\r
+ int ForceIntra; // NVVE_FORCE_INTRA,\r
+ int ForceIDR; // NVVE_FORCE_IDR,\r
+ int ClearStat; // NVVE_CLEAR_STAT,\r
+ int DIMode; // NVVE_SET_DEINTERLACE,\r
+ int Presets; // NVVE_PRESETS,\r
+ int DisableCabac; // NVVE_DISABLE_CABAC,\r
+ int NaluFramingType; // NVVE_CONFIGURE_NALU_FRAMING_TYPE\r
+ int DisableSPSPPS; // NVVE_DISABLE_SPS_PPS\r
+\r
+ EncoderParams();\r
+ explicit EncoderParams(const std::string& configFile);\r
+\r
+ void load(const std::string& configFile);\r
+ void save(const std::string& configFile) const;\r
+ };\r
+\r
+ class EncoderCallBack\r
+ {\r
+ public:\r
+ enum PicType\r
+ {\r
+ IFRAME = 1,\r
+ PFRAME = 2,\r
+ BFRAME = 3\r
+ };\r
+\r
+ virtual ~EncoderCallBack() {}\r
+\r
+ // callback function to signal the start of bitstream that is to be encoded\r
+ // must return pointer to buffer\r
+ virtual unsigned char* acquireBitStream(int* bufferSize) = 0;\r
+\r
+ // callback function to signal that the encoded bitstream is ready to be written to file\r
+ virtual void releaseBitStream(unsigned char* data, int size) = 0;\r
+\r
+ // callback function to signal that the encoding operation on the frame has started\r
+ virtual void onBeginFrame(int frameNumber, PicType picType) = 0;\r
+\r
+ // callback function signals that the encoding operation on the frame has finished\r
+ virtual void onEndFrame(int frameNumber, PicType picType) = 0;\r
+ };\r
+\r
+private:\r
+ VideoWriter_GPU(const VideoWriter_GPU&);\r
+ VideoWriter_GPU& operator=(const VideoWriter_GPU&);\r
+\r
+ class Impl;\r
+ std::auto_ptr<Impl> impl_;\r
+};\r
+\r
} // namespace gpu\r
\r
} // namespace cv\r
--- /dev/null
+/*M///////////////////////////////////////////////////////////////////////////////////////\r
+//\r
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.\r
+//\r
+// By downloading, copying, installing or using the software you agree to this license.\r
+// If you do not agree to this license, do not download, install,\r
+// copy or use the software.\r
+//\r
+//\r
+// License Agreement\r
+// For Open Source Computer Vision Library\r
+//\r
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.\r
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.\r
+// Third party copyrights are property of their respective owners.\r
+//\r
+// Redistribution and use in source and binary forms, with or without modification,\r
+// are permitted provided that the following conditions are met:\r
+//\r
+// * Redistribution's of source code must retain the above copyright notice,\r
+// this list of conditions and the following disclaimer.\r
+//\r
+// * Redistribution's in binary form must reproduce the above copyright notice,\r
+// this list of conditions and the following disclaimer in the documentation\r
+// and/or other materials provided with the distribution.\r
+//\r
+// * The name of the copyright holders may not be used to endorse or promote products\r
+// derived from this software without specific prior written permission.\r
+//\r
+// This software is provided by the copyright holders and contributors "as is" and\r
+// any express or bpied warranties, including, but not limited to, the bpied\r
+// warranties of merchantability and fitness for a particular purpose are disclaimed.\r
+// In no event shall the Intel Corporation or contributors be liable for any direct,\r
+// indirect, incidental, special, exemplary, or consequential damages\r
+// (including, but not limited to, procurement of substitute goods or services;\r
+// loss of use, data, or profits; or business interruption) however caused\r
+// and on any theory of liability, whether in contract, strict liability,\r
+// or tort (including negligence or otherwise) arising in any way out of\r
+// the use of this software, even if advised of the possibility of such damage.\r
+//\r
+//M*/\r
+\r
+#include "opencv2/gpu/device/common.hpp"\r
+#include "opencv2/gpu/device/vec_traits.hpp"\r
+\r
+namespace cv { namespace gpu { namespace device \r
+{\r
+ namespace video_encoding\r
+ {\r
+ __device__ __forceinline__ void rgbtoy(const uchar b, const uchar g, const uchar r, uchar& y)\r
+ {\r
+ y = static_cast<uchar>(((int)(30 * r) + (int)(59 * g) + (int)(11 * b)) / 100);\r
+ }\r
+\r
+ __device__ __forceinline__ void rgbtoyuv(const uchar b, const uchar g, const uchar r, uchar& y, uchar& u, uchar& v)\r
+ {\r
+ rgbtoy(b, g, r, y);\r
+ u = static_cast<uchar>(((int)(-17 * r) - (int)(33 * g) + (int)(50 * b) + 12800) / 100);\r
+ v = static_cast<uchar>(((int)(50 * r) - (int)(42 * g) - (int)(8 * b) + 12800) / 100);\r
+ }\r
+\r
+ __global__ void Gray_to_YV12(const DevMem2Db src, PtrStepb dst)\r
+ {\r
+ const int x = (blockIdx.x * blockDim.x + threadIdx.x) * 2;\r
+ const int y = (blockIdx.y * blockDim.y + threadIdx.y) * 2;\r
+\r
+ if (x + 1 >= src.cols || y + 1 >= src.rows)\r
+ return;\r
+\r
+ // get pointers to the data\r
+ const size_t planeSize = src.rows * dst.step;\r
+ PtrStepb y_plane(dst.data, dst.step);\r
+ PtrStepb u_plane(y_plane.data + planeSize, dst.step / 2);\r
+ PtrStepb v_plane(u_plane.data + (planeSize / 4), dst.step / 2);\r
+\r
+ uchar pix;\r
+ uchar y_val, u_val, v_val;\r
+\r
+ pix = src(y, x);\r
+ rgbtoy(pix, pix, pix, y_val);\r
+ y_plane(y, x) = y_val;\r
+\r
+ pix = src(y, x + 1);\r
+ rgbtoy(pix, pix, pix, y_val);\r
+ y_plane(y, x + 1) = y_val;\r
+\r
+ pix = src(y + 1, x);\r
+ rgbtoy(pix, pix, pix, y_val);\r
+ y_plane(y + 1, x) = y_val;\r
+\r
+ pix = src(y + 1, x + 1);\r
+ rgbtoyuv(pix, pix, pix, y_val, u_val, v_val);\r
+ y_plane(y + 1, x + 1) = y_val;\r
+ u_plane(y / 2, x / 2) = u_val;\r
+ v_plane(y / 2, x / 2) = v_val;\r
+ }\r
+\r
+ template <typename T>\r
+ __global__ void BGR_to_YV12(const DevMem2D_<T> src, PtrStepb dst)\r
+ {\r
+ const int x = (blockIdx.x * blockDim.x + threadIdx.x) * 2;\r
+ const int y = (blockIdx.y * blockDim.y + threadIdx.y) * 2;\r
+\r
+ if (x + 1 >= src.cols || y + 1 >= src.rows)\r
+ return;\r
+\r
+ // get pointers to the data\r
+ const size_t planeSize = src.rows * dst.step;\r
+ PtrStepb y_plane(dst.data, dst.step);\r
+ PtrStepb u_plane(y_plane.data + planeSize, dst.step / 2);\r
+ PtrStepb v_plane(u_plane.data + (planeSize / 4), dst.step / 2);\r
+\r
+ T pix;\r
+ uchar y_val, u_val, v_val;\r
+\r
+ pix = src(y, x);\r
+ rgbtoy(pix.z, pix.y, pix.x, y_val);\r
+ y_plane(y, x) = y_val;\r
+\r
+ pix = src(y, x + 1);\r
+ rgbtoy(pix.z, pix.y, pix.x, y_val);\r
+ y_plane(y, x + 1) = y_val;\r
+\r
+ pix = src(y + 1, x);\r
+ rgbtoy(pix.z, pix.y, pix.x, y_val);\r
+ y_plane(y + 1, x) = y_val;\r
+\r
+ pix = src(y + 1, x + 1);\r
+ rgbtoyuv(pix.z, pix.y, pix.x, y_val, u_val, v_val);\r
+ y_plane(y + 1, x + 1) = y_val;\r
+ u_plane(y / 2, x / 2) = u_val;\r
+ v_plane(y / 2, x / 2) = v_val;\r
+ }\r
+\r
+ void Gray_to_YV12_caller(const DevMem2Db src, PtrStepb dst)\r
+ {\r
+ dim3 block(32, 8);\r
+ dim3 grid(divUp(src.cols, block.x * 2), divUp(src.rows, block.y * 2));\r
+\r
+ Gray_to_YV12<<<grid, block>>>(src, dst);\r
+ cudaSafeCall( cudaGetLastError() );\r
+\r
+ cudaSafeCall( cudaDeviceSynchronize() );\r
+ }\r
+ template <int cn>\r
+ void BGR_to_YV12_caller(const DevMem2Db src, PtrStepb dst)\r
+ {\r
+ typedef typename TypeVec<uchar, cn>::vec_type src_t;\r
+\r
+ dim3 block(32, 8);\r
+ dim3 grid(divUp(src.cols, block.x * 2), divUp(src.rows, block.y * 2));\r
+\r
+ BGR_to_YV12<<<grid, block>>>(static_cast< DevMem2D_<src_t> >(src), dst);\r
+ cudaSafeCall( cudaGetLastError() );\r
+\r
+ cudaSafeCall( cudaDeviceSynchronize() );\r
+ }\r
+\r
+ void YV12_gpu(const DevMem2Db src, int cn, DevMem2Db dst)\r
+ {\r
+ typedef void (*func_t)(const DevMem2Db src, PtrStepb dst);\r
+ \r
+ static const func_t funcs[] = \r
+ {\r
+ 0, Gray_to_YV12_caller, 0, BGR_to_YV12_caller<3>, BGR_to_YV12_caller<4>\r
+ };\r
+ \r
+ funcs[cn](src, dst);\r
+ }\r
+ }\r
+}}}\r
\r
#ifdef HAVE_CUDA\r
\r
- #include "cuda.h"\r
- #include "cuda_runtime_api.h"\r
- #include "npp.h"\r
+ #include <cuda.h>\r
+ #include <cuda_runtime.h>\r
+ #include <npp.h>\r
\r
#ifdef HAVE_CUFFT\r
- #include "cufft.h"\r
+ #include <cufft.h>\r
#endif\r
\r
#ifdef HAVE_CUBLAS\r
- #include "cublas.h"\r
+ #include <cublas.h>\r
+ #endif\r
+\r
+ #include <nvcuvid.h>\r
+\r
+ #ifdef WIN32\r
+ #include <NVEncoderAPI.h>\r
#endif\r
\r
#include "internal_shared.hpp"\r
--- /dev/null
+/*M///////////////////////////////////////////////////////////////////////////////////////\r
+//\r
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.\r
+//\r
+// By downloading, copying, installing or using the software you agree to this license.\r
+// If you do not agree to this license, do not download, install,\r
+// copy or use the software.\r
+//\r
+//\r
+// License Agreement\r
+// For Open Source Computer Vision Library\r
+//\r
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.\r
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.\r
+// Third party copyrights are property of their respective owners.\r
+//\r
+// Redistribution and use in source and binary forms, with or without modification,\r
+// are permitted provided that the following conditions are met:\r
+//\r
+// * Redistribution's of source code must retain the above copyright notice,\r
+// this list of conditions and the following disclaimer.\r
+//\r
+// * Redistribution's in binary form must reproduce the above copyright notice,\r
+// this list of conditions and the following disclaimer in the documentation\r
+// and/or other materials provided with the distribution.\r
+//\r
+// * The name of the copyright holders may not be used to endorse or promote products\r
+// derived from this software without specific prior written permission.\r
+//\r
+// This software is provided by the copyright holders and contributors "as is" and\r
+// any express or implied warranties, including, but not limited to, the implied\r
+// warranties of merchantability and fitness for a particular purpose are disclaimed.\r
+// In no event shall the Intel Corporation or contributors be liable for any direct,\r
+// indirect, incidental, special, exemplary, or consequential damages\r
+// (including, but not limited to, procurement of substitute goods or services;\r
+// loss of use, data, or profits; or business interruption) however caused\r
+// and on any theory of liability, whether in contract, strict liability,\r
+// or tort (including negligence or otherwise) arising in any way out of\r
+// the use of this software, even if advised of the possibility of such damage.\r
+//\r
+//M*/\r
+\r
+#include "precomp.hpp"\r
+\r
+#if !defined HAVE_CUDA || !defined WIN32\r
+\r
+cv::gpu::VideoWriter_GPU::VideoWriter_GPU() { throw_nogpu(); }\r
+cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const std::string&, cv::Size, double) { throw_nogpu(); }\r
+cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const std::string&, cv::Size, double, const EncoderParams&) { throw_nogpu(); }\r
+cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const cv::Ptr<EncoderCallBack>&, cv::Size, double) { throw_nogpu(); }\r
+cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const cv::Ptr<EncoderCallBack>&, cv::Size, double, const EncoderParams&) { throw_nogpu(); }\r
+cv::gpu::VideoWriter_GPU::~VideoWriter_GPU() {}\r
+void cv::gpu::VideoWriter_GPU::open(const std::string&, cv::Size, double) { throw_nogpu(); }\r
+void cv::gpu::VideoWriter_GPU::open(const std::string&, cv::Size, double, const EncoderParams&) { throw_nogpu(); }\r
+void cv::gpu::VideoWriter_GPU::open(const cv::Ptr<EncoderCallBack>&, cv::Size, double) { throw_nogpu(); }\r
+void cv::gpu::VideoWriter_GPU::open(const cv::Ptr<EncoderCallBack>&, cv::Size, double, const EncoderParams&) { throw_nogpu(); }\r
+bool cv::gpu::VideoWriter_GPU::isOpened() const { return false; }\r
+void cv::gpu::VideoWriter_GPU::close() {}\r
+void cv::gpu::VideoWriter_GPU::write(const cv::gpu::GpuMat&, bool) { throw_nogpu(); }\r
+\r
+cv::gpu::VideoWriter_GPU::EncoderParams::EncoderParams() { throw_nogpu(); }\r
+cv::gpu::VideoWriter_GPU::EncoderParams::EncoderParams(const std::string&) { throw_nogpu(); }\r
+void cv::gpu::VideoWriter_GPU::EncoderParams::load(const std::string&) { throw_nogpu(); }\r
+void cv::gpu::VideoWriter_GPU::EncoderParams::save(const std::string&) const { throw_nogpu(); }\r
+\r
+#else // !defined HAVE_CUDA || !defined WIN32\r
+\r
+#ifdef HAVE_FFMPEG\r
+ #ifdef NEW_FFMPEG\r
+ #include "cap_ffmpeg_impl_v2.hpp"\r
+ #else\r
+ #include "cap_ffmpeg_impl.hpp"\r
+ #endif\r
+#else\r
+ #include "cap_ffmpeg_api.hpp"\r
+#endif\r
+\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+// VideoWriter_GPU::Impl\r
+\r
+namespace\r
+{\r
+ class NVEncoderWrapper\r
+ {\r
+ public:\r
+ NVEncoderWrapper() : encoder_(0)\r
+ {\r
+ int err;\r
+\r
+ err = NVGetHWEncodeCaps();\r
+ if (err)\r
+ CV_Error(CV_GpuNotSupported, "No CUDA capability present");\r
+\r
+ // Create the Encoder API Interface\r
+ err = NVCreateEncoder(&encoder_);\r
+ CV_Assert( err == 0 );\r
+ }\r
+\r
+ ~NVEncoderWrapper()\r
+ {\r
+ if (encoder_)\r
+ NVDestroyEncoder(encoder_);\r
+ }\r
+\r
+ operator NVEncoder() const\r
+ {\r
+ return encoder_;\r
+ }\r
+\r
+ private:\r
+ NVEncoder encoder_;\r
+ };\r
+\r
+ enum CodecType\r
+ {\r
+ MPEG1, //not supported yet\r
+ MPEG2, //not supported yet\r
+ MPEG4, //not supported yet\r
+ H264\r
+ };\r
+}\r
+\r
+class cv::gpu::VideoWriter_GPU::Impl\r
+{\r
+public:\r
+ Impl(const cv::Ptr<EncoderCallBack>& callback, cv::Size frameSize, double fps, CodecType codec = H264);\r
+ Impl(const cv::Ptr<EncoderCallBack>& callback, cv::Size frameSize, double fps, const EncoderParams& params, CodecType codec = H264);\r
+\r
+ void write(const cv::gpu::GpuMat& image, bool lastFrame);\r
+\r
+private:\r
+ Impl(const Impl&);\r
+ Impl& operator=(const Impl&);\r
+\r
+ void initEncoder(double fps);\r
+ void setEncodeParams(const EncoderParams& params);\r
+ void initGpuMemory();\r
+ void initCallBacks();\r
+ void createHWEncoder();\r
+ \r
+ cv::Ptr<EncoderCallBack> callback_;\r
+ cv::Size frameSize_;\r
+\r
+ CodecType codec_;\r
+ NVVE_SurfaceFormat surfaceFormat_;\r
+\r
+ NVEncoderWrapper encoder_;\r
+\r
+ cv::gpu::GpuMat videoFrame_;\r
+ CUvideoctxlock cuCtxLock_;\r
+\r
+ // CallBacks\r
+\r
+ static unsigned char* NVENCAPI HandleAcquireBitStream(int* pBufferSize, void* pUserdata);\r
+ static void NVENCAPI HandleReleaseBitStream(int nBytesInBuffer, unsigned char* cb, void* pUserdata);\r
+ static void NVENCAPI HandleOnBeginFrame(const NVVE_BeginFrameInfo* pbfi, void* pUserdata);\r
+ static void NVENCAPI HandleOnEndFrame(const NVVE_EndFrameInfo* pefi, void* pUserdata);\r
+};\r
+\r
+cv::gpu::VideoWriter_GPU::Impl::Impl(const cv::Ptr<EncoderCallBack>& callback, cv::Size frameSize, double fps, CodecType codec) :\r
+ callback_(callback),\r
+ frameSize_(frameSize),\r
+ codec_(codec),\r
+ surfaceFormat_(YV12),\r
+ cuCtxLock_(0)\r
+{\r
+ initEncoder(fps);\r
+\r
+ initGpuMemory();\r
+\r
+ initCallBacks();\r
+\r
+ createHWEncoder();\r
+}\r
+\r
+cv::gpu::VideoWriter_GPU::Impl::Impl(const cv::Ptr<EncoderCallBack>& callback, cv::Size frameSize, double fps, const EncoderParams& params, CodecType codec) :\r
+ callback_(callback),\r
+ frameSize_(frameSize),\r
+ codec_(codec),\r
+ surfaceFormat_(YV12),\r
+ cuCtxLock_(0)\r
+{\r
+ initEncoder(fps);\r
+\r
+ setEncodeParams(params);\r
+\r
+ initGpuMemory();\r
+\r
+ initCallBacks();\r
+\r
+ createHWEncoder();\r
+}\r
+\r
+void cv::gpu::VideoWriter_GPU::Impl::initEncoder(double fps)\r
+{\r
+ int err;\r
+\r
+ // Set codec\r
+\r
+ static const unsigned long codecs_id[] = \r
+ {\r
+ NV_CODEC_TYPE_MPEG1, NV_CODEC_TYPE_MPEG2, NV_CODEC_TYPE_MPEG4, NV_CODEC_TYPE_H264, NV_CODEC_TYPE_VC1\r
+ };\r
+ err = NVSetCodec(encoder_, codecs_id[codec_]);\r
+ if (err)\r
+ CV_Error(CV_StsNotImplemented, "Codec format is not supported");\r
+\r
+ // Set default params\r
+\r
+ err = NVSetDefaultParam(encoder_);\r
+ CV_Assert( err == 0 );\r
+\r
+ // Set some common params\r
+\r
+ int inputSize[] = { frameSize_.width, frameSize_.height };\r
+ err = NVSetParamValue(encoder_, NVVE_IN_SIZE, &inputSize);\r
+ CV_Assert( err == 0 );\r
+ err = NVSetParamValue(encoder_, NVVE_OUT_SIZE, &inputSize);\r
+ CV_Assert( err == 0 );\r
+\r
+ //int aspectRatio[] = { frameSize_.width, frameSize_.height, ASPECT_RATIO_DAR };\r
+ int aspectRatio[] = { 16, 9, ASPECT_RATIO_DAR };\r
+ err = NVSetParamValue(encoder_, NVVE_ASPECT_RATIO, &aspectRatio);\r
+ CV_Assert( err == 0 );\r
+\r
+ // FPS\r
+\r
+ int frame_rate = static_cast<int>(fps + 0.5);\r
+ int frame_rate_base = 1;\r
+ while (fabs(static_cast<double>(frame_rate) / frame_rate_base) - fps > 0.001)\r
+ {\r
+ frame_rate_base *= 10;\r
+ frame_rate = static_cast<int>(fps*frame_rate_base + 0.5);\r
+ }\r
+ int FrameRate[] = { frame_rate, frame_rate_base };\r
+ err = NVSetParamValue(encoder_, NVVE_FRAME_RATE, &FrameRate);\r
+ CV_Assert( err == 0 );\r
+\r
+ // Select device for encoding\r
+\r
+ int gpuID = cv::gpu::getDevice();\r
+ err = NVSetParamValue(encoder_, NVVE_FORCE_GPU_SELECTION, &gpuID);\r
+ CV_Assert( err == 0 );\r
+}\r
+\r
+void cv::gpu::VideoWriter_GPU::Impl::setEncodeParams(const EncoderParams& params)\r
+{\r
+ int err;\r
+\r
+ int P_Interval = params.P_Interval;\r
+ err = NVSetParamValue(encoder_, NVVE_P_INTERVAL, &P_Interval);\r
+ CV_Assert( err == 0 );\r
+\r
+ int IDR_Period = params.IDR_Period;\r
+ err = NVSetParamValue(encoder_, NVVE_IDR_PERIOD, &IDR_Period);\r
+ CV_Assert( err == 0 );\r
+\r
+ int DynamicGOP = params.DynamicGOP;\r
+ err = NVSetParamValue(encoder_, NVVE_DYNAMIC_GOP, &DynamicGOP);\r
+ CV_Assert( err == 0 );\r
+\r
+ NVVE_RateCtrlType RCType = static_cast<NVVE_RateCtrlType>(params.RCType);\r
+ err = NVSetParamValue(encoder_, NVVE_RC_TYPE, &RCType);\r
+ CV_Assert( err == 0 );\r
+\r
+ int AvgBitrate = params.AvgBitrate;\r
+ err = NVSetParamValue(encoder_, NVVE_AVG_BITRATE, &AvgBitrate);\r
+ CV_Assert( err == 0 );\r
+\r
+ int PeakBitrate = params.PeakBitrate;\r
+ err = NVSetParamValue(encoder_, NVVE_PEAK_BITRATE, &PeakBitrate);\r
+ CV_Assert( err == 0 );\r
+\r
+ int QP_Level_Intra = params.QP_Level_Intra;\r
+ err = NVSetParamValue(encoder_, NVVE_QP_LEVEL_INTRA, &QP_Level_Intra);\r
+ CV_Assert( err == 0 );\r
+\r
+ int QP_Level_InterP = params.QP_Level_InterP;\r
+ err = NVSetParamValue(encoder_, NVVE_QP_LEVEL_INTER_P, &QP_Level_InterP);\r
+ CV_Assert( err == 0 );\r
+\r
+ int QP_Level_InterB = params.QP_Level_InterB;\r
+ err = NVSetParamValue(encoder_, NVVE_QP_LEVEL_INTER_B, &QP_Level_InterB);\r
+ CV_Assert( err == 0 );\r
+\r
+ int DeblockMode = params.DeblockMode;\r
+ err = NVSetParamValue(encoder_, NVVE_DEBLOCK_MODE, &DeblockMode);\r
+ CV_Assert( err == 0 );\r
+\r
+ int ProfileLevel = params.ProfileLevel;\r
+ err = NVSetParamValue(encoder_, NVVE_PROFILE_LEVEL, &ProfileLevel);\r
+ CV_Assert( err == 0 );\r
+\r
+ int ForceIntra = params.ForceIntra;\r
+ err = NVSetParamValue(encoder_, NVVE_FORCE_INTRA, &ForceIntra);\r
+ CV_Assert( err == 0 );\r
+\r
+ int ForceIDR = params.ForceIDR;\r
+ err = NVSetParamValue(encoder_, NVVE_FORCE_IDR, &ForceIDR);\r
+ CV_Assert( err == 0 );\r
+\r
+ int ClearStat = params.ClearStat;\r
+ err = NVSetParamValue(encoder_, NVVE_CLEAR_STAT, &ClearStat);\r
+ CV_Assert( err == 0 );\r
+\r
+ NVVE_DI_MODE DIMode = static_cast<NVVE_DI_MODE>(params.DIMode);\r
+ err = NVSetParamValue(encoder_, NVVE_SET_DEINTERLACE, &DIMode);\r
+ CV_Assert( err == 0 );\r
+\r
+ if (params.Presets != -1)\r
+ {\r
+ NVVE_PRESETS_TARGET Presets = static_cast<NVVE_PRESETS_TARGET>(params.Presets);\r
+ err = NVSetParamValue(encoder_, NVVE_PRESETS, &Presets);\r
+ CV_Assert ( err == 0 );\r
+ }\r
+\r
+ int DisableCabac = params.DisableCabac;\r
+ err = NVSetParamValue(encoder_, NVVE_DISABLE_CABAC, &DisableCabac);\r
+ CV_Assert ( err == 0 );\r
+\r
+ int NaluFramingType = params.NaluFramingType;\r
+ err = NVSetParamValue(encoder_, NVVE_CONFIGURE_NALU_FRAMING_TYPE, &NaluFramingType);\r
+ CV_Assert ( err == 0 );\r
+\r
+ int DisableSPSPPS = params.DisableSPSPPS;\r
+ err = NVSetParamValue(encoder_, NVVE_DISABLE_SPS_PPS, &DisableSPSPPS);\r
+ CV_Assert ( err == 0 );\r
+}\r
+\r
+void cv::gpu::VideoWriter_GPU::Impl::initGpuMemory()\r
+{\r
+ int err;\r
+ CUresult cuRes;\r
+\r
+ // initialize context\r
+ cv::gpu::GpuMat temp(1, 1, CV_8U);\r
+ temp.release();\r
+\r
+ static const int bpp[] =\r
+ {\r
+ 16, // UYVY, 4:2:2\r
+ 16, // YUY2, 4:2:2\r
+ 12, // YV12, 4:2:0\r
+ 12, // NV12, 4:2:0\r
+ 12, // IYUV, 4:2:0\r
+ };\r
+\r
+ CUcontext cuContext;\r
+ cuRes = cuCtxGetCurrent(&cuContext);\r
+ CV_Assert( cuRes == CUDA_SUCCESS );\r
+\r
+ // Allocate the CUDA memory Pitched Surface\r
+ if (surfaceFormat_ == UYVY || surfaceFormat_ == YUY2)\r
+ videoFrame_.create(frameSize_.height, (frameSize_.width * bpp[surfaceFormat_]) / 8, CV_8UC1);\r
+ else\r
+ videoFrame_.create((frameSize_.height * bpp[surfaceFormat_]) / 8, frameSize_.width, CV_8UC1);\r
+\r
+ // Create the Video Context Lock (used for synchronization)\r
+ cuRes = cuvidCtxLockCreate(&cuCtxLock_, cuContext);\r
+ CV_Assert( cuRes == CUDA_SUCCESS );\r
+\r
+ // If we are using GPU Device Memory with NVCUVENC, it is necessary to create a \r
+ // CUDA Context with a Context Lock cuvidCtxLock. The Context Lock needs to be passed to NVCUVENC\r
+\r
+ int iUseDeviceMem = 1;\r
+ err = NVSetParamValue(encoder_, NVVE_DEVICE_MEMORY_INPUT, &iUseDeviceMem);\r
+ CV_Assert ( err == 0 );\r
+\r
+ err = NVSetParamValue(encoder_, NVVE_DEVICE_CTX_LOCK, &cuCtxLock_);\r
+ CV_Assert ( err == 0 );\r
+}\r
+\r
+void cv::gpu::VideoWriter_GPU::Impl::initCallBacks()\r
+{\r
+ NVVE_CallbackParams cb;\r
+ memset(&cb, 0, sizeof(NVVE_CallbackParams));\r
+\r
+ cb.pfnacquirebitstream = HandleAcquireBitStream;\r
+ cb.pfnonbeginframe = HandleOnBeginFrame;\r
+ cb.pfnonendframe = HandleOnEndFrame;\r
+ cb.pfnreleasebitstream = HandleReleaseBitStream;\r
+\r
+ NVRegisterCB(encoder_, cb, this);\r
+}\r
+\r
+void cv::gpu::VideoWriter_GPU::Impl::createHWEncoder()\r
+{\r
+ int err;\r
+\r
+ // Create the NVIDIA HW resources for Encoding on NVIDIA hardware\r
+ err = NVCreateHWEncoder(encoder_);\r
+ CV_Assert( err == 0 );\r
+}\r
+\r
+namespace cv { namespace gpu { namespace device \r
+{\r
+ namespace video_encoding\r
+ {\r
+ void YV12_gpu(const DevMem2Db src, int cn, DevMem2Db dst);\r
+ }\r
+}}}\r
+\r
+void cv::gpu::VideoWriter_GPU::Impl::write(const cv::gpu::GpuMat& frame, bool lastFrame)\r
+{\r
+ CV_Assert( frame.size() == frameSize_ );\r
+ CV_Assert( frame.type() == CV_8UC1 || frame.type() == CV_8UC3 || frame.type() == CV_8UC4 );\r
+\r
+ NVVE_EncodeFrameParams efparams;\r
+ efparams.Width = frameSize_.width;\r
+ efparams.Height = frameSize_.height;\r
+ efparams.Pitch = static_cast<int>(videoFrame_.step);\r
+ efparams.SurfFmt = surfaceFormat_;\r
+ efparams.PictureStruc = FRAME_PICTURE;\r
+ efparams.topfieldfirst = 0;\r
+ efparams.repeatFirstField = 0;\r
+ efparams.progressiveFrame = (surfaceFormat_ == NV12) ? 1 : 0;\r
+ efparams.bLast = lastFrame;\r
+ efparams.picBuf = 0; // Must be set to NULL in order to support device memory input\r
+\r
+ // Don't forget we need to lock/unlock between memcopies\r
+ CUresult res = cuvidCtxLock(cuCtxLock_, 0);\r
+ CV_Assert( res == CUDA_SUCCESS );\r
+\r
+ if (surfaceFormat_ == YV12)\r
+ cv::gpu::device::video_encoding::YV12_gpu(frame, frame.channels(), videoFrame_);\r
+\r
+ res = cuvidCtxUnlock(cuCtxLock_, 0);\r
+ CV_Assert( res == CUDA_SUCCESS );\r
+\r
+ int err = NVEncodeFrame(encoder_, &efparams, 0, videoFrame_.data);\r
+ CV_Assert( err == 0 );\r
+}\r
+\r
+unsigned char* NVENCAPI cv::gpu::VideoWriter_GPU::Impl::HandleAcquireBitStream(int* pBufferSize, void* pUserdata)\r
+{\r
+ Impl* thiz = static_cast<Impl*>(pUserdata);\r
+\r
+ return thiz->callback_->acquireBitStream(pBufferSize);\r
+}\r
+\r
+void NVENCAPI cv::gpu::VideoWriter_GPU::Impl::HandleReleaseBitStream(int nBytesInBuffer, unsigned char* cb, void* pUserdata)\r
+{\r
+ Impl* thiz = static_cast<Impl*>(pUserdata);\r
+\r
+ thiz->callback_->releaseBitStream(cb, nBytesInBuffer);\r
+}\r
+\r
+void NVENCAPI cv::gpu::VideoWriter_GPU::Impl::HandleOnBeginFrame(const NVVE_BeginFrameInfo* pbfi, void* pUserdata)\r
+{\r
+ Impl* thiz = static_cast<Impl*>(pUserdata);\r
+\r
+ thiz->callback_->onBeginFrame(pbfi->nFrameNumber, static_cast<EncoderCallBack::PicType>(pbfi->nPicType));\r
+}\r
+\r
+void NVENCAPI cv::gpu::VideoWriter_GPU::Impl::HandleOnEndFrame(const NVVE_EndFrameInfo* pefi, void* pUserdata)\r
+{\r
+ Impl* thiz = static_cast<Impl*>(pUserdata);\r
+\r
+ thiz->callback_->onEndFrame(pefi->nFrameNumber, static_cast<EncoderCallBack::PicType>(pefi->nPicType));\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+// FFMPEG\r
+\r
+class EncoderCallBackFFMPEG : public cv::gpu::VideoWriter_GPU::EncoderCallBack\r
+{\r
+public:\r
+ EncoderCallBackFFMPEG(const std::string& fileName, cv::Size frameSize, double fps);\r
+ ~EncoderCallBackFFMPEG();\r
+\r
+ unsigned char* acquireBitStream(int* bufferSize);\r
+ void releaseBitStream(unsigned char* data, int size);\r
+ void onBeginFrame(int frameNumber, PicType picType);\r
+ void onEndFrame(int frameNumber, PicType picType);\r
+\r
+private:\r
+ EncoderCallBackFFMPEG(const EncoderCallBackFFMPEG&);\r
+ EncoderCallBackFFMPEG& operator=(const EncoderCallBackFFMPEG&);\r
+\r
+ struct OutputMediaStream_FFMPEG* stream_;\r
+ std::vector<uchar> buf_;\r
+};\r
+\r
+namespace\r
+{\r
+ Create_OutputMediaStream_FFMPEG_Plugin create_OutputMediaStream_FFMPEG_p = 0;\r
+ Release_OutputMediaStream_FFMPEG_Plugin release_OutputMediaStream_FFMPEG_p = 0;\r
+ Write_OutputMediaStream_FFMPEG_Plugin write_OutputMediaStream_FFMPEG_p = 0;\r
+\r
+ bool init_MediaStream_FFMPEG()\r
+ {\r
+ static bool initialized = 0;\r
+\r
+ if (!initialized)\r
+ {\r
+ #if defined WIN32 || defined _WIN32\r
+ const char* module_name = "opencv_ffmpeg"\r
+ #if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__)\r
+ "_64"\r
+ #endif\r
+ ".dll";\r
+\r
+ static HMODULE cvFFOpenCV = LoadLibrary(module_name);\r
+\r
+ if (cvFFOpenCV)\r
+ {\r
+ create_OutputMediaStream_FFMPEG_p =\r
+ (Create_OutputMediaStream_FFMPEG_Plugin)GetProcAddress(cvFFOpenCV, "create_OutputMediaStream_FFMPEG");\r
+ release_OutputMediaStream_FFMPEG_p =\r
+ (Release_OutputMediaStream_FFMPEG_Plugin)GetProcAddress(cvFFOpenCV, "release_OutputMediaStream_FFMPEG");\r
+ write_OutputMediaStream_FFMPEG_p =\r
+ (Write_OutputMediaStream_FFMPEG_Plugin)GetProcAddress(cvFFOpenCV, "write_OutputMediaStream_FFMPEG");\r
+\r
+ initialized = create_OutputMediaStream_FFMPEG_p != 0 && release_OutputMediaStream_FFMPEG_p != 0 && write_OutputMediaStream_FFMPEG_p != 0;\r
+ }\r
+ #elif defined HAVE_FFMPEG\r
+ create_OutputMediaStream_FFMPEG_p = create_OutputMediaStream_FFMPEG;\r
+ release_OutputMediaStream_FFMPEG_p = release_OutputMediaStream_FFMPEG;\r
+ write_OutputMediaStream_FFMPEG_p = write_OutputMediaStream_FFMPEG;\r
+\r
+ initialized = true;\r
+ #endif\r
+ }\r
+\r
+ return initialized;\r
+ }\r
+}\r
+\r
+EncoderCallBackFFMPEG::EncoderCallBackFFMPEG(const std::string& fileName, cv::Size frameSize, double fps) :\r
+ stream_(0)\r
+{\r
+ int buf_size = std::max(frameSize.area() * 4, 1024 * 1024);\r
+ buf_.resize(buf_size);\r
+\r
+ CV_Assert( init_MediaStream_FFMPEG() );\r
+\r
+ stream_ = create_OutputMediaStream_FFMPEG_p(fileName.c_str(), frameSize.width, frameSize.height, fps);\r
+ CV_Assert( stream_ != 0 );\r
+}\r
+\r
+EncoderCallBackFFMPEG::~EncoderCallBackFFMPEG()\r
+{\r
+ release_OutputMediaStream_FFMPEG_p(stream_);\r
+}\r
+\r
+unsigned char* EncoderCallBackFFMPEG::acquireBitStream(int* bufferSize)\r
+{\r
+ *bufferSize = static_cast<int>(buf_.size());\r
+ return &buf_[0];\r
+}\r
+\r
+void EncoderCallBackFFMPEG::releaseBitStream(unsigned char* data, int size)\r
+{\r
+ write_OutputMediaStream_FFMPEG_p(stream_, data, size);\r
+}\r
+\r
+void EncoderCallBackFFMPEG::onBeginFrame(int frameNumber, PicType picType)\r
+{\r
+}\r
+\r
+void EncoderCallBackFFMPEG::onEndFrame(int frameNumber, PicType picType)\r
+{\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+// VideoWriter_GPU\r
+\r
+cv::gpu::VideoWriter_GPU::VideoWriter_GPU()\r
+{\r
+}\r
+\r
+cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const std::string& fileName, cv::Size frameSize, double fps)\r
+{\r
+ open(fileName, frameSize, fps);\r
+}\r
+\r
+cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const std::string& fileName, cv::Size frameSize, double fps, const EncoderParams& params)\r
+{\r
+ open(fileName, frameSize, fps, params);\r
+}\r
+\r
+cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps)\r
+{\r
+ open(encoderCallback, frameSize, fps);\r
+}\r
+\r
+cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps, const EncoderParams& params)\r
+{\r
+ open(encoderCallback, frameSize, fps, params);\r
+}\r
+\r
+cv::gpu::VideoWriter_GPU::~VideoWriter_GPU()\r
+{\r
+ close();\r
+}\r
+\r
+void cv::gpu::VideoWriter_GPU::open(const std::string& fileName, cv::Size frameSize, double fps)\r
+{\r
+ close();\r
+ cv::Ptr<EncoderCallBack> encoderCallback(new EncoderCallBackFFMPEG(fileName, frameSize, fps));\r
+ open(encoderCallback, frameSize, fps);\r
+}\r
+\r
+void cv::gpu::VideoWriter_GPU::open(const std::string& fileName, cv::Size frameSize, double fps, const EncoderParams& params)\r
+{\r
+ close();\r
+ cv::Ptr<EncoderCallBack> encoderCallback(new EncoderCallBackFFMPEG(fileName, frameSize, fps));\r
+ open(encoderCallback, frameSize, fps, params);\r
+}\r
+\r
+void cv::gpu::VideoWriter_GPU::open(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps)\r
+{\r
+ close();\r
+ impl_.reset(new Impl(encoderCallback, frameSize, fps));\r
+}\r
+\r
+void cv::gpu::VideoWriter_GPU::open(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps, const EncoderParams& params)\r
+{\r
+ close();\r
+ impl_.reset(new Impl(encoderCallback, frameSize, fps, params));\r
+}\r
+\r
+bool cv::gpu::VideoWriter_GPU::isOpened() const\r
+{\r
+ return impl_.get() != 0;\r
+}\r
+\r
+void cv::gpu::VideoWriter_GPU::close()\r
+{\r
+ impl_.reset();\r
+}\r
+\r
+void cv::gpu::VideoWriter_GPU::write(const cv::gpu::GpuMat& image, bool lastFrame)\r
+{\r
+ CV_Assert( isOpened() );\r
+\r
+ impl_->write(image, lastFrame);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+// VideoWriter_GPU::EncoderParams\r
+\r
+cv::gpu::VideoWriter_GPU::EncoderParams::EncoderParams()\r
+{\r
+ P_Interval = 3;\r
+ IDR_Period = 15;\r
+ DynamicGOP = 0;\r
+ RCType = 1;\r
+ AvgBitrate = 4000000;\r
+ PeakBitrate = 10000000;\r
+ QP_Level_Intra = 25;\r
+ QP_Level_InterP = 28;\r
+ QP_Level_InterB = 31;\r
+ DeblockMode = 1;\r
+ ProfileLevel = 65357;\r
+ ForceIntra = 0;\r
+ ForceIDR = 0;\r
+ ClearStat = 0;\r
+ DIMode = 1;\r
+ Presets = 2;\r
+ DisableCabac = 0;\r
+ NaluFramingType = 0;\r
+ DisableSPSPPS = 0;\r
+}\r
+\r
+cv::gpu::VideoWriter_GPU::EncoderParams::EncoderParams(const std::string& configFile)\r
+{\r
+ load(configFile);\r
+}\r
+\r
+void cv::gpu::VideoWriter_GPU::EncoderParams::load(const std::string& configFile)\r
+{\r
+ cv::FileStorage fs(configFile, cv::FileStorage::READ);\r
+ CV_Assert( fs.isOpened() );\r
+\r
+ cv::read(fs["P_Interval" ], P_Interval, 3);\r
+ cv::read(fs["IDR_Period" ], IDR_Period, 15);\r
+ cv::read(fs["DynamicGOP" ], DynamicGOP, 0);\r
+ cv::read(fs["RCType" ], RCType, 1);\r
+ cv::read(fs["AvgBitrate" ], AvgBitrate, 4000000);\r
+ cv::read(fs["PeakBitrate" ], PeakBitrate, 10000000);\r
+ cv::read(fs["QP_Level_Intra" ], QP_Level_Intra, 25);\r
+ cv::read(fs["QP_Level_InterP"], QP_Level_InterP, 28);\r
+ cv::read(fs["QP_Level_InterB"], QP_Level_InterB, 31);\r
+ cv::read(fs["DeblockMode" ], DeblockMode, 1);\r
+ cv::read(fs["ProfileLevel" ], ProfileLevel, 65357);\r
+ cv::read(fs["ForceIntra" ], ForceIntra, 0);\r
+ cv::read(fs["ForceIDR" ], ForceIDR, 0);\r
+ cv::read(fs["ClearStat" ], ClearStat, 0);\r
+ cv::read(fs["DIMode" ], DIMode, 1);\r
+ cv::read(fs["Presets" ], Presets, 2);\r
+ cv::read(fs["DisableCabac" ], DisableCabac, 0);\r
+ cv::read(fs["NaluFramingType"], NaluFramingType, 0);\r
+ cv::read(fs["DisableSPSPPS" ], DisableSPSPPS, 0);\r
+}\r
+\r
+void cv::gpu::VideoWriter_GPU::EncoderParams::save(const std::string& configFile) const\r
+{\r
+ cv::FileStorage fs(configFile, cv::FileStorage::WRITE);\r
+ CV_Assert( fs.isOpened() );\r
+\r
+ cv::write(fs, "P_Interval" , P_Interval);\r
+ cv::write(fs, "IDR_Period" , IDR_Period);\r
+ cv::write(fs, "DynamicGOP" , DynamicGOP);\r
+ cv::write(fs, "RCType" , RCType);\r
+ cv::write(fs, "AvgBitrate" , AvgBitrate);\r
+ cv::write(fs, "PeakBitrate" , PeakBitrate);\r
+ cv::write(fs, "QP_Level_Intra" , QP_Level_Intra);\r
+ cv::write(fs, "QP_Level_InterP", QP_Level_InterP);\r
+ cv::write(fs, "QP_Level_InterB", QP_Level_InterB);\r
+ cv::write(fs, "DeblockMode" , DeblockMode);\r
+ cv::write(fs, "ProfileLevel" , ProfileLevel);\r
+ cv::write(fs, "ForceIntra" , ForceIntra);\r
+ cv::write(fs, "ForceIDR" , ForceIDR);\r
+ cv::write(fs, "ClearStat" , ClearStat);\r
+ cv::write(fs, "DIMode" , DIMode);\r
+ cv::write(fs, "Presets" , Presets);\r
+ cv::write(fs, "DisableCabac" , DisableCabac);\r
+ cv::write(fs, "NaluFramingType", NaluFramingType);\r
+ cv::write(fs, "DisableSPSPPS" , DisableSPSPPS);\r
+}\r
+\r
+#endif // !defined HAVE_CUDA || !defined WIN32\r
testing::Values(FarnebackOptFlowFlags(0), FarnebackOptFlowFlags(cv::OPTFLOW_FARNEBACK_GAUSSIAN)),\r
testing::Values(UseInitFlow(false), UseInitFlow(true))));\r
\r
+/////////////////////////////////////////////////////////////////////////////////////////////////\r
+// VideoWriter\r
+\r
+PARAM_TEST_CASE(VideoWriter, cv::gpu::DeviceInfo, std::string)\r
+{\r
+ cv::gpu::DeviceInfo devInfo;\r
+ std::string inputFile;\r
+\r
+ std::string outputFile;\r
+\r
+ virtual void SetUp()\r
+ {\r
+ devInfo = GET_PARAM(0);\r
+ inputFile = GET_PARAM(1);\r
+\r
+ cv::gpu::setDevice(devInfo.deviceID());\r
+\r
+ inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "video/" + inputFile;\r
+ outputFile = inputFile.substr(0, inputFile.find('.')) + "_test.avi";\r
+ }\r
+};\r
+\r
+TEST_P(VideoWriter, Regression)\r
+{\r
+ const double FPS = 25.0;\r
+\r
+ cv::VideoCapture reader(inputFile);\r
+ ASSERT_TRUE( reader.isOpened() );\r
+\r
+ cv::gpu::VideoWriter_GPU d_writer;\r
+\r
+ cv::Mat frame;\r
+ std::vector<cv::Mat> frames;\r
+ cv::gpu::GpuMat d_frame;\r
+\r
+ for (int i = 1; i < 10; ++i)\r
+ {\r
+ reader >> frame;\r
+\r
+ if (frame.empty())\r
+ break;\r
+\r
+ frames.push_back(frame.clone());\r
+ d_frame.upload(frame);\r
+\r
+ if (!d_writer.isOpened())\r
+ d_writer.open(outputFile, frame.size(), FPS);\r
+\r
+ d_writer.write(d_frame);\r
+ }\r
+\r
+ reader.release();\r
+ d_writer.close();\r
+\r
+ reader.open(outputFile);\r
+ ASSERT_TRUE( reader.isOpened() );\r
+}\r
+\r
+INSTANTIATE_TEST_CASE_P(GPU_Video, VideoWriter, testing::Combine(\r
+ ALL_DEVICES,\r
+ testing::Values("VID00003-20100701-2204.3GP", "big_buck_bunny.mpg")));\r
+\r
} // namespace\r
int width, int height, int cn, int origin);
typedef void (*CvReleaseVideoWriter_Plugin)( void** writer );
+/*
+ * For CUDA encoder
+ */
+
+OPENCV_FFMPEG_API struct OutputMediaStream_FFMPEG* create_OutputMediaStream_FFMPEG(const char* fileName, int width, int height, double fps);
+OPENCV_FFMPEG_API void release_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream);
+OPENCV_FFMPEG_API void write_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream, unsigned char* data, int size);
+
+typedef struct OutputMediaStream_FFMPEG* (*Create_OutputMediaStream_FFMPEG_Plugin)(const char* fileName, int width, int height, double fps);
+typedef void (*Release_OutputMediaStream_FFMPEG_Plugin)(struct OutputMediaStream_FFMPEG* stream);
+typedef void (*Write_OutputMediaStream_FFMPEG_Plugin)(struct OutputMediaStream_FFMPEG* stream, unsigned char* data, int size);
+
#ifdef __cplusplus
}
#endif
return writer->writeFrame(data, step, width, height, cn, origin);
}
+
+/*
+ * For CUDA encoder
+ */
+
+struct OutputMediaStream_FFMPEG
+{
+ bool open(const char* fileName, int width, int height, double fps);
+ void write(unsigned char* data, int size);
+
+ void close();
+
+ // add a video output stream to the container
+ static AVStream* addVideoStream(AVFormatContext *oc, CodecID codec_id, int w, int h, int bitrate, double fps, PixelFormat pixel_format);
+
+ AVOutputFormat* fmt_;
+ AVFormatContext* oc_;
+ AVStream* video_st_;
+};
+
+void OutputMediaStream_FFMPEG::close()
+{
+ // no more frame to compress. The codec has a latency of a few
+ // frames if using B frames, so we get the last frames by
+ // passing the same picture again
+
+ // TODO -- do we need to account for latency here?
+
+ if (oc_)
+ {
+ // write the trailer, if any
+ av_write_trailer(oc_);
+
+ // free the streams
+ for (unsigned int i = 0; i < oc_->nb_streams; ++i)
+ {
+ av_freep(&oc_->streams[i]->codec);
+ av_freep(&oc_->streams[i]);
+ }
+
+ if (!(fmt_->flags & AVFMT_NOFILE) && oc_->pb)
+ {
+ // close the output file
+
+ #if LIBAVCODEC_VERSION_INT < ((52<<16)+(123<<8)+0)
+ #if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0)
+ url_fclose(oc_->pb);
+ #else
+ url_fclose(&oc_->pb);
+ #endif
+ #else
+ avio_close(oc_->pb);
+ #endif
+ }
+
+ // free the stream
+ av_free(oc_);
+ }
+}
+
+AVStream* OutputMediaStream_FFMPEG::addVideoStream(AVFormatContext *oc, CodecID codec_id, int w, int h, int bitrate, double fps, PixelFormat pixel_format)
+{
+ #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 10, 0)
+ AVStream* st = avformat_new_stream(oc, 0);
+ #else
+ AVStream* st = av_new_stream(oc, 0);
+ #endif
+ if (!st)
+ return 0;
+
+ #if LIBAVFORMAT_BUILD > 4628
+ AVCodecContext* c = st->codec;
+ #else
+ AVCodecContext* c = &(st->codec);
+ #endif
+
+ c->codec_id = codec_id;
+ c->codec_type = AVMEDIA_TYPE_VIDEO;
+
+ // put sample parameters
+ unsigned long long lbit_rate = static_cast<unsigned long long>(bitrate);
+ lbit_rate += (bitrate / 4);
+ lbit_rate = std::min(lbit_rate, static_cast<unsigned long long>(std::numeric_limits<int>::max()));
+ c->bit_rate = bitrate;
+
+ // took advice from
+ // http://ffmpeg-users.933282.n4.nabble.com/warning-clipping-1-dct-coefficients-to-127-127-td934297.html
+ c->qmin = 3;
+
+ // resolution must be a multiple of two
+ c->width = w;
+ c->height = h;
+
+ AVCodec* codec = avcodec_find_encoder(c->codec_id);
+
+ // time base: this is the fundamental unit of time (in seconds) in terms
+ // of which frame timestamps are represented. for fixed-fps content,
+ // timebase should be 1/framerate and timestamp increments should be
+ // identically 1
+
+ int frame_rate = static_cast<int>(fps+0.5);
+ int frame_rate_base = 1;
+ while (fabs(static_cast<double>(frame_rate)/frame_rate_base) - fps > 0.001)
+ {
+ frame_rate_base *= 10;
+ frame_rate = static_cast<int>(fps*frame_rate_base + 0.5);
+ }
+ c->time_base.den = frame_rate;
+ c->time_base.num = frame_rate_base;
+
+ #if LIBAVFORMAT_BUILD > 4752
+ // adjust time base for supported framerates
+ if (codec && codec->supported_framerates)
+ {
+ AVRational req = {frame_rate, frame_rate_base};
+ const AVRational* best = NULL;
+ AVRational best_error = {INT_MAX, 1};
+
+ for (const AVRational* p = codec->supported_framerates; p->den!=0; ++p)
+ {
+ AVRational error = av_sub_q(req, *p);
+
+ if (error.num < 0)
+ error.num *= -1;
+
+ if (av_cmp_q(error, best_error) < 0)
+ {
+ best_error= error;
+ best= p;
+ }
+ }
+
+ c->time_base.den= best->num;
+ c->time_base.num= best->den;
+ }
+ #endif
+
+ c->gop_size = 12; // emit one intra frame every twelve frames at most
+ c->pix_fmt = pixel_format;
+
+ if (c->codec_id == CODEC_ID_MPEG2VIDEO)
+ c->max_b_frames = 2;
+
+ if (c->codec_id == CODEC_ID_MPEG1VIDEO || c->codec_id == CODEC_ID_MSMPEG4V3)
+ {
+ // needed to avoid using macroblocks in which some coeffs overflow
+ // this doesnt happen with normal video, it just happens here as the
+ // motion of the chroma plane doesnt match the luma plane
+
+ // avoid FFMPEG warning 'clipping 1 dct coefficients...'
+
+ c->mb_decision = 2;
+ }
+
+ #if LIBAVCODEC_VERSION_INT > 0x000409
+ // some formats want stream headers to be seperate
+ if (oc->oformat->flags & AVFMT_GLOBALHEADER)
+ {
+ c->flags |= CODEC_FLAG_GLOBAL_HEADER;
+ }
+ #endif
+
+ return st;
+}
+
+bool OutputMediaStream_FFMPEG::open(const char* fileName, int width, int height, double fps)
+{
+ fmt_ = 0;
+ oc_ = 0;
+ video_st_ = 0;
+
+ // tell FFMPEG to register codecs
+ av_register_all();
+
+ av_log_set_level(AV_LOG_ERROR);
+
+ // auto detect the output format from the name and fourcc code
+ #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
+ fmt_ = av_guess_format(NULL, fileName, NULL);
+ #else
+ fmt_ = guess_format(NULL, fileName, NULL);
+ #endif
+ if (!fmt_)
+ return false;
+
+ CodecID codec_id = CODEC_ID_H264;
+
+ // alloc memory for context
+ #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
+ oc_ = avformat_alloc_context();
+ #else
+ oc_ = av_alloc_format_context();
+ #endif
+ if (!oc_)
+ return false;
+
+ // set some options
+ oc_->oformat = fmt_;
+ snprintf(oc_->filename, sizeof(oc_->filename), "%s", fileName);
+
+ oc_->max_delay = (int)(0.7 * AV_TIME_BASE); // This reduces buffer underrun warnings with MPEG
+
+ // set a few optimal pixel formats for lossless codecs of interest..
+ PixelFormat codec_pix_fmt = PIX_FMT_YUV420P;
+ int bitrate_scale = 64;
+
+ // TODO -- safe to ignore output audio stream?
+ video_st_ = addVideoStream(oc_, codec_id, width, height, width * height * bitrate_scale, fps, codec_pix_fmt);
+ if (!video_st_)
+ return false;
+
+ // set the output parameters (must be done even if no parameters)
+ #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
+ if (av_set_parameters(oc_, NULL) < 0)
+ return false;
+ #endif
+
+ // now that all the parameters are set, we can open the audio and
+ // video codecs and allocate the necessary encode buffers
+
+ #if LIBAVFORMAT_BUILD > 4628
+ AVCodecContext* c = (video_st_->codec);
+ #else
+ AVCodecContext* c = &(video_st_->codec);
+ #endif
+
+ c->codec_tag = MKTAG('H', '2', '6', '4');
+ c->bit_rate_tolerance = c->bit_rate;
+
+ // open the output file, if needed
+ if (!(fmt_->flags & AVFMT_NOFILE))
+ {
+ #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
+ int err = url_fopen(&oc_->pb, fileName, URL_WRONLY);
+ #else
+ int err = avio_open(&oc_->pb, fileName, AVIO_FLAG_WRITE);
+ #endif
+
+ if (err != 0)
+ return false;
+ }
+
+ // write the stream header, if any
+ #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
+ av_write_header(oc_);
+ #else
+ avformat_write_header(oc_, NULL);
+ #endif
+
+ return true;
+}
+
+void OutputMediaStream_FFMPEG::write(unsigned char* data, int size)
+{
+ // if zero size, it means the image was buffered
+ if (size > 0)
+ {
+ AVPacket pkt;
+ av_init_packet(&pkt);
+
+ pkt.stream_index = video_st_->index;
+ pkt.data = data;
+ pkt.size = size;
+
+ // write the compressed frame in the media file
+ av_write_frame(oc_, &pkt);
+ }
+}
+
+struct OutputMediaStream_FFMPEG* create_OutputMediaStream_FFMPEG(const char* fileName, int width, int height, double fps)
+{
+ OutputMediaStream_FFMPEG* stream = (OutputMediaStream_FFMPEG*) malloc(sizeof(OutputMediaStream_FFMPEG));
+
+ if (stream->open(fileName, width, height, fps))
+ return stream;
+
+ stream->close();
+ free(stream);
+
+ return 0;
+}
+
+void release_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream)
+{
+ stream->close();
+ free(stream);
+}
+
+void write_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream, unsigned char* data, int size)
+{
+ stream->write(data, size);
+}
#include "cap_ffmpeg_api.hpp"
#include <assert.h>
#include <algorithm>
+#include <limits>
#if defined _MSC_VER && _MSC_VER >= 1200
#pragma warning( disable: 4244 4510 4512 4610 )
return writer->writeFrame(data, step, width, height, cn, origin);
}
+
+/*
+ * For CUDA encoder
+ */
+
+struct OutputMediaStream_FFMPEG
+{
+ bool open(const char* fileName, int width, int height, double fps);
+ void write(unsigned char* data, int size);
+
+ void close();
+
+ // add a video output stream to the container
+ static AVStream* addVideoStream(AVFormatContext *oc, CodecID codec_id, int w, int h, int bitrate, double fps, PixelFormat pixel_format);
+
+ AVOutputFormat* fmt_;
+ AVFormatContext* oc_;
+ AVStream* video_st_;
+};
+
+void OutputMediaStream_FFMPEG::close()
+{
+ // no more frame to compress. The codec has a latency of a few
+ // frames if using B frames, so we get the last frames by
+ // passing the same picture again
+
+ // TODO -- do we need to account for latency here?
+
+ if (oc_)
+ {
+ // write the trailer, if any
+ av_write_trailer(oc_);
+
+ // free the streams
+ for (unsigned int i = 0; i < oc_->nb_streams; ++i)
+ {
+ av_freep(&oc_->streams[i]->codec);
+ av_freep(&oc_->streams[i]);
+ }
+
+ if (!(fmt_->flags & AVFMT_NOFILE) && oc_->pb)
+ {
+ // close the output file
+
+ #if LIBAVCODEC_VERSION_INT < ((52<<16)+(123<<8)+0)
+ #if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0)
+ url_fclose(oc_->pb);
+ #else
+ url_fclose(&oc_->pb);
+ #endif
+ #else
+ avio_close(oc_->pb);
+ #endif
+ }
+
+ // free the stream
+ av_free(oc_);
+ }
+}
+
+AVStream* OutputMediaStream_FFMPEG::addVideoStream(AVFormatContext *oc, CodecID codec_id, int w, int h, int bitrate, double fps, PixelFormat pixel_format)
+{
+ #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 10, 0)
+ AVStream* st = avformat_new_stream(oc, 0);
+ #else
+ AVStream* st = av_new_stream(oc, 0);
+ #endif
+ if (!st)
+ return 0;
+
+ #if LIBAVFORMAT_BUILD > 4628
+ AVCodecContext* c = st->codec;
+ #else
+ AVCodecContext* c = &(st->codec);
+ #endif
+
+ c->codec_id = codec_id;
+ c->codec_type = AVMEDIA_TYPE_VIDEO;
+
+ // put sample parameters
+ unsigned long long lbit_rate = static_cast<unsigned long long>(bitrate);
+ lbit_rate += (bitrate / 4);
+ lbit_rate = std::min(lbit_rate, static_cast<unsigned long long>(std::numeric_limits<int>::max()));
+ c->bit_rate = bitrate;
+
+ // took advice from
+ // http://ffmpeg-users.933282.n4.nabble.com/warning-clipping-1-dct-coefficients-to-127-127-td934297.html
+ c->qmin = 3;
+
+ // resolution must be a multiple of two
+ c->width = w;
+ c->height = h;
+
+ AVCodec* codec = avcodec_find_encoder(c->codec_id);
+
+ // time base: this is the fundamental unit of time (in seconds) in terms
+ // of which frame timestamps are represented. for fixed-fps content,
+ // timebase should be 1/framerate and timestamp increments should be
+ // identically 1
+
+ int frame_rate = static_cast<int>(fps+0.5);
+ int frame_rate_base = 1;
+ while (fabs(static_cast<double>(frame_rate)/frame_rate_base) - fps > 0.001)
+ {
+ frame_rate_base *= 10;
+ frame_rate = static_cast<int>(fps*frame_rate_base + 0.5);
+ }
+ c->time_base.den = frame_rate;
+ c->time_base.num = frame_rate_base;
+
+ #if LIBAVFORMAT_BUILD > 4752
+ // adjust time base for supported framerates
+ if (codec && codec->supported_framerates)
+ {
+ AVRational req = {frame_rate, frame_rate_base};
+ const AVRational* best = NULL;
+ AVRational best_error = {INT_MAX, 1};
+
+ for (const AVRational* p = codec->supported_framerates; p->den!=0; ++p)
+ {
+ AVRational error = av_sub_q(req, *p);
+
+ if (error.num < 0)
+ error.num *= -1;
+
+ if (av_cmp_q(error, best_error) < 0)
+ {
+ best_error= error;
+ best= p;
+ }
+ }
+
+ c->time_base.den= best->num;
+ c->time_base.num= best->den;
+ }
+ #endif
+
+ c->gop_size = 12; // emit one intra frame every twelve frames at most
+ c->pix_fmt = pixel_format;
+
+ if (c->codec_id == CODEC_ID_MPEG2VIDEO)
+ c->max_b_frames = 2;
+
+ if (c->codec_id == CODEC_ID_MPEG1VIDEO || c->codec_id == CODEC_ID_MSMPEG4V3)
+ {
+ // needed to avoid using macroblocks in which some coeffs overflow
+ // this doesnt happen with normal video, it just happens here as the
+ // motion of the chroma plane doesnt match the luma plane
+
+ // avoid FFMPEG warning 'clipping 1 dct coefficients...'
+
+ c->mb_decision = 2;
+ }
+
+ #if LIBAVCODEC_VERSION_INT > 0x000409
+ // some formats want stream headers to be seperate
+ if (oc->oformat->flags & AVFMT_GLOBALHEADER)
+ {
+ c->flags |= CODEC_FLAG_GLOBAL_HEADER;
+ }
+ #endif
+
+ return st;
+}
+
+bool OutputMediaStream_FFMPEG::open(const char* fileName, int width, int height, double fps)
+{
+ fmt_ = 0;
+ oc_ = 0;
+ video_st_ = 0;
+
+ // tell FFMPEG to register codecs
+ av_register_all();
+
+ av_log_set_level(AV_LOG_ERROR);
+
+ // auto detect the output format from the name and fourcc code
+ #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
+ fmt_ = av_guess_format(NULL, fileName, NULL);
+ #else
+ fmt_ = guess_format(NULL, fileName, NULL);
+ #endif
+ if (!fmt_)
+ return false;
+
+ CodecID codec_id = CODEC_ID_H264;
+
+ // alloc memory for context
+ #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
+ oc_ = avformat_alloc_context();
+ #else
+ oc_ = av_alloc_format_context();
+ #endif
+ if (!oc_)
+ return false;
+
+ // set some options
+ oc_->oformat = fmt_;
+ snprintf(oc_->filename, sizeof(oc_->filename), "%s", fileName);
+
+ oc_->max_delay = (int)(0.7 * AV_TIME_BASE); // This reduces buffer underrun warnings with MPEG
+
+ // set a few optimal pixel formats for lossless codecs of interest..
+ PixelFormat codec_pix_fmt = PIX_FMT_YUV420P;
+ int bitrate_scale = 64;
+
+ // TODO -- safe to ignore output audio stream?
+ video_st_ = addVideoStream(oc_, codec_id, width, height, width * height * bitrate_scale, fps, codec_pix_fmt);
+ if (!video_st_)
+ return false;
+
+ // set the output parameters (must be done even if no parameters)
+ #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
+ if (av_set_parameters(oc_, NULL) < 0)
+ return false;
+ #endif
+
+ // now that all the parameters are set, we can open the audio and
+ // video codecs and allocate the necessary encode buffers
+
+ #if LIBAVFORMAT_BUILD > 4628
+ AVCodecContext* c = (video_st_->codec);
+ #else
+ AVCodecContext* c = &(video_st_->codec);
+ #endif
+
+ c->codec_tag = MKTAG('H', '2', '6', '4');
+ c->bit_rate_tolerance = c->bit_rate;
+
+ // open the output file, if needed
+ if (!(fmt_->flags & AVFMT_NOFILE))
+ {
+ #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
+ int err = url_fopen(&oc_->pb, fileName, URL_WRONLY);
+ #else
+ int err = avio_open(&oc_->pb, fileName, AVIO_FLAG_WRITE);
+ #endif
+
+ if (err != 0)
+ return false;
+ }
+
+ // write the stream header, if any
+ #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
+ av_write_header(oc_);
+ #else
+ avformat_write_header(oc_, NULL);
+ #endif
+
+ return true;
+}
+
+void OutputMediaStream_FFMPEG::write(unsigned char* data, int size)
+{
+ // if zero size, it means the image was buffered
+ if (size > 0)
+ {
+ AVPacket pkt;
+ av_init_packet(&pkt);
+
+ pkt.stream_index = video_st_->index;
+ pkt.data = data;
+ pkt.size = size;
+
+ // write the compressed frame in the media file
+ av_write_frame(oc_, &pkt);
+ }
+}
+
+struct OutputMediaStream_FFMPEG* create_OutputMediaStream_FFMPEG(const char* fileName, int width, int height, double fps)
+{
+ OutputMediaStream_FFMPEG* stream = (OutputMediaStream_FFMPEG*) malloc(sizeof(OutputMediaStream_FFMPEG));
+
+ if (stream->open(fileName, width, height, fps))
+ return stream;
+
+ stream->close();
+ free(stream);
+
+ return 0;
+}
+
+void release_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream)
+{
+ stream->close();
+ free(stream);
+}
+
+void write_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream, unsigned char* data, int size)
+{
+ stream->write(data, size);
+}
--- /dev/null
+#include <iostream>\r
+#include <vector>\r
+#include <numeric>\r
+\r
+#include "opencv2/core/core.hpp"\r
+#include "opencv2/gpu/gpu.hpp"\r
+#include "opencv2/highgui/highgui.hpp"\r
+#include "opencv2/contrib/contrib.hpp"\r
+\r
+int main(int argc, const char* argv[])\r
+{\r
+ if (argc != 2)\r
+ {\r
+ std::cerr << "Usage : video_writer <input video file>" << std::endl;\r
+ return -1;\r
+ }\r
+\r
+ const double FPS = 25.0;\r
+\r
+ cv::VideoCapture reader(argv[1]);\r
+\r
+ if (!reader.isOpened())\r
+ {\r
+ std::cerr << "Can't open input video file" << std::endl;\r
+ return -1;\r
+ }\r
+\r
+ cv::gpu::printShortCudaDeviceInfo(cv::gpu::getDevice());\r
+\r
+ cv::VideoWriter writer;\r
+ cv::gpu::VideoWriter_GPU d_writer;\r
+\r
+ cv::Mat frame;\r
+ cv::gpu::GpuMat d_frame;\r
+\r
+ std::vector<double> cpu_times;\r
+ std::vector<double> gpu_times;\r
+ cv::TickMeter tm;\r
+\r
+ for (int i = 1;; ++i)\r
+ {\r
+ std::cout << "Read " << i << " frame" << std::endl;\r
+\r
+ reader >> frame;\r
+\r
+ if (frame.empty())\r
+ {\r
+ std::cout << "Stop" << std::endl;\r
+ break;\r
+ }\r
+\r
+ if (!writer.isOpened())\r
+ {\r
+ std::cout << "Frame Size : " << frame.cols << "x" << frame.rows << std::endl;\r
+\r
+ std::cout << "Open CPU Writer" << std::endl;\r
+\r
+ if (!writer.open("output_cpu.avi", CV_FOURCC('X', 'V', 'I', 'D'), FPS, frame.size()))\r
+ return -1;\r
+ }\r
+\r
+ if (!d_writer.isOpened())\r
+ {\r
+ std::cout << "Open GPU Writer" << std::endl;\r
+\r
+ d_writer.open("output_gpu.avi", frame.size(), FPS);\r
+ }\r
+\r
+ d_frame.upload(frame);\r
+\r
+ std::cout << "Write " << i << " frame" << std::endl;\r
+\r
+ tm.reset(); tm.start();\r
+ writer.write(frame);\r
+ tm.stop();\r
+ cpu_times.push_back(tm.getTimeMilli());\r
+\r
+ tm.reset(); tm.start();\r
+ d_writer.write(d_frame);\r
+ tm.stop();\r
+ gpu_times.push_back(tm.getTimeMilli());\r
+ }\r
+\r
+ std::cout << std::endl << "Results:" << std::endl;\r
+\r
+ std::sort(cpu_times.begin(), cpu_times.end());\r
+ std::sort(gpu_times.begin(), gpu_times.end());\r
+\r
+ double cpu_avg = std::accumulate(cpu_times.begin(), cpu_times.end(), 0.0) / cpu_times.size();\r
+ double gpu_avg = std::accumulate(gpu_times.begin(), gpu_times.end(), 0.0) / gpu_times.size();\r
+\r
+ std::cout << "CPU [XVID] : Avg : " << cpu_avg << " ms FPS : " << 1000.0 / cpu_avg << std::endl;\r
+ std::cout << "GPU [H264] : Avg : " << gpu_avg << " ms FPS : " << 1000.0 / gpu_avg << std::endl;\r
+\r
+ return 0;\r
+}\r