added support of different surface formats to VideoWriter_GPU
authorVladislav Vinogradov <no@email>
Tue, 17 Apr 2012 11:08:08 +0000 (11:08 +0000)
committerVladislav Vinogradov <no@email>
Tue, 17 Apr 2012 11:08:08 +0000 (11:08 +0000)
added key frame handling to ffmpeg wrappers

3rdparty/ffmpeg/opencv_ffmpeg.dll
3rdparty/ffmpeg/opencv_ffmpeg_64.dll
modules/gpu/include/opencv2/gpu/gpu.hpp
modules/gpu/src/video_writer.cpp
modules/highgui/src/cap_ffmpeg_api.hpp
modules/highgui/src/cap_ffmpeg_impl.hpp
modules/highgui/src/cap_ffmpeg_impl_v2.hpp

index eb02a95..f4101c0 100644 (file)
Binary files a/3rdparty/ffmpeg/opencv_ffmpeg.dll and b/3rdparty/ffmpeg/opencv_ffmpeg.dll differ
index cd3c499..604f581 100644 (file)
Binary files a/3rdparty/ffmpeg/opencv_ffmpeg_64.dll and b/3rdparty/ffmpeg/opencv_ffmpeg_64.dll differ
index 6c60958..03399a0 100644 (file)
@@ -1898,18 +1898,29 @@ public:
     // Callbacks for video encoder, use it if you want to work with raw video stream\r
     class EncoderCallBack;\r
 \r
+    enum SurfaceFormat\r
+    {\r
+        SF_UYVY = 0,\r
+        SF_YUY2,\r
+        SF_YV12,\r
+        SF_NV12,\r
+        SF_IYUV,\r
+        SF_BGR,\r
+        SF_GRAY = SF_BGR\r
+    };\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(const std::string& fileName, cv::Size frameSize, double fps, SurfaceFormat format = SF_BGR);\r
+    VideoWriter_GPU(const std::string& fileName, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format = SF_BGR);\r
+    VideoWriter_GPU(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps, SurfaceFormat format = SF_BGR);\r
+    VideoWriter_GPU(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format = SF_BGR);\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
+    void open(const std::string& fileName, cv::Size frameSize, double fps, SurfaceFormat format = SF_BGR);\r
+    void open(const std::string& fileName, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format = SF_BGR);\r
+    void open(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps, SurfaceFormat format = SF_BGR);\r
+    void open(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format = SF_BGR);\r
 \r
     bool isOpened() const;\r
     void close();\r
index 4bacc0b..fc7f718 100644 (file)
 #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(const std::string&, cv::Size, double, SurfaceFormat) { throw_nogpu(); }\r
+cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const std::string&, cv::Size, double, const EncoderParams&, SurfaceFormat) { throw_nogpu(); }\r
+cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const cv::Ptr<EncoderCallBack>&, cv::Size, double, SurfaceFormat) { throw_nogpu(); }\r
+cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const cv::Ptr<EncoderCallBack>&, cv::Size, double, const EncoderParams&, SurfaceFormat) { 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
+void cv::gpu::VideoWriter_GPU::open(const std::string&, cv::Size, double, SurfaceFormat) { throw_nogpu(); }\r
+void cv::gpu::VideoWriter_GPU::open(const std::string&, cv::Size, double, const EncoderParams&, SurfaceFormat) { throw_nogpu(); }\r
+void cv::gpu::VideoWriter_GPU::open(const cv::Ptr<EncoderCallBack>&, cv::Size, double, SurfaceFormat) { throw_nogpu(); }\r
+void cv::gpu::VideoWriter_GPU::open(const cv::Ptr<EncoderCallBack>&, cv::Size, double, const EncoderParams&, SurfaceFormat) { 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
@@ -124,8 +124,8 @@ namespace
 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
+    Impl(const cv::Ptr<EncoderCallBack>& callback, cv::Size frameSize, double fps, SurfaceFormat format, CodecType codec = H264);\r
+    Impl(const cv::Ptr<EncoderCallBack>& callback, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format, CodecType codec = H264);\r
 \r
     void write(const cv::gpu::GpuMat& image, bool lastFrame);\r
 \r
@@ -143,6 +143,7 @@ private:
     cv::Size frameSize_;\r
 \r
     CodecType codec_;\r
+    SurfaceFormat inputFormat_;\r
     NVVE_SurfaceFormat surfaceFormat_;\r
 \r
     NVEncoderWrapper encoder_;\r
@@ -158,13 +159,15 @@ private:
     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
+cv::gpu::VideoWriter_GPU::Impl::Impl(const cv::Ptr<EncoderCallBack>& callback, cv::Size frameSize, double fps, SurfaceFormat format, CodecType codec) :\r
     callback_(callback),\r
     frameSize_(frameSize),\r
     codec_(codec),\r
-    surfaceFormat_(YV12),\r
+    inputFormat_(format),\r
     cuCtxLock_(0)\r
 {\r
+    surfaceFormat_ = inputFormat_ == SF_BGR ? YV12 : static_cast<NVVE_SurfaceFormat>(inputFormat_);\r
+\r
     initEncoder(fps);\r
 \r
     initGpuMemory();\r
@@ -174,13 +177,15 @@ cv::gpu::VideoWriter_GPU::Impl::Impl(const cv::Ptr<EncoderCallBack>& callback, c
     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
+cv::gpu::VideoWriter_GPU::Impl::Impl(const cv::Ptr<EncoderCallBack>& callback, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format, CodecType codec) :\r
     callback_(callback),\r
     frameSize_(frameSize),\r
     codec_(codec),\r
-    surfaceFormat_(YV12),\r
+    inputFormat_(format),\r
     cuCtxLock_(0)\r
 {\r
+    surfaceFormat_ = inputFormat_ == SF_BGR ? YV12 : static_cast<NVVE_SurfaceFormat>(inputFormat_);\r
+\r
     initEncoder(fps);\r
 \r
     setEncodeParams(params);\r
@@ -401,10 +406,153 @@ namespace cv { namespace gpu { namespace device
     }\r
 }}}\r
 \r
+namespace\r
+{\r
+    // UYVY/YUY2 are both 4:2:2 formats (16bpc)\r
+    // Luma, U, V are interleaved, chroma is subsampled (w/2,h)\r
+    void copyUYVYorYUY2Frame(cv::Size frameSize, const cv::gpu::GpuMat& src, cv::gpu::GpuMat& dst)\r
+    {\r
+        CUresult res;\r
+\r
+        // Source is YUVY/YUY2 4:2:2, the YUV data in a packed and interleaved\r
+\r
+        // YUV Copy setup\r
+        CUDA_MEMCPY2D stCopyYUV422;\r
+        memset((void*)&stCopyYUV422, 0, sizeof(stCopyYUV422));\r
+        stCopyYUV422.srcXInBytes          = 0;\r
+        stCopyYUV422.srcY                 = 0;\r
+        stCopyYUV422.srcMemoryType        = CU_MEMORYTYPE_DEVICE;\r
+        stCopyYUV422.srcHost              = 0;\r
+        stCopyYUV422.srcDevice            = (CUdeviceptr) src.data;\r
+        stCopyYUV422.srcArray             = 0;\r
+        stCopyYUV422.srcPitch             = src.step;\r
+\r
+        stCopyYUV422.dstXInBytes          = 0;\r
+        stCopyYUV422.dstY                 = 0;\r
+        stCopyYUV422.dstMemoryType        = CU_MEMORYTYPE_DEVICE;\r
+        stCopyYUV422.dstHost              = 0;\r
+        stCopyYUV422.dstDevice            = (CUdeviceptr) dst.data;\r
+        stCopyYUV422.dstArray             = 0;\r
+        stCopyYUV422.dstPitch             = dst.step;\r
+\r
+        stCopyYUV422.WidthInBytes         = frameSize.width * 2;\r
+        stCopyYUV422.Height               = frameSize.height;\r
+\r
+        // DMA Luma/Chroma\r
+        res = cuMemcpy2D(&stCopyYUV422);\r
+        CV_Assert( res == CUDA_SUCCESS );\r
+    }\r
+\r
+    // YV12/IYUV are both 4:2:0 planar formats (12bpc)\r
+    // Luma, U, V chroma planar (12bpc), chroma is subsampled (w/2,h/2)\r
+    void copyYV12orIYUVFrame(cv::Size frameSize, const cv::gpu::GpuMat& src, cv::gpu::GpuMat& dst)\r
+    {\r
+        CUresult res;\r
+\r
+        // Source is YV12/IYUV, this native format is converted to NV12 format by the video encoder\r
+\r
+        // (1) luma copy setup\r
+        CUDA_MEMCPY2D stCopyLuma;\r
+        memset((void*)&stCopyLuma, 0, sizeof(stCopyLuma));\r
+        stCopyLuma.srcXInBytes          = 0;\r
+        stCopyLuma.srcY                 = 0;\r
+        stCopyLuma.srcMemoryType        = CU_MEMORYTYPE_DEVICE;\r
+        stCopyLuma.srcHost              = 0;\r
+        stCopyLuma.srcDevice            = (CUdeviceptr) src.data;\r
+        stCopyLuma.srcArray             = 0;\r
+        stCopyLuma.srcPitch             = src.step;\r
+\r
+        stCopyLuma.dstXInBytes          = 0;\r
+        stCopyLuma.dstY                 = 0;\r
+        stCopyLuma.dstMemoryType        = CU_MEMORYTYPE_DEVICE;\r
+        stCopyLuma.dstHost              = 0;\r
+        stCopyLuma.dstDevice            = (CUdeviceptr) dst.data;\r
+        stCopyLuma.dstArray             = 0;\r
+        stCopyLuma.dstPitch             = dst.step;\r
+\r
+        stCopyLuma.WidthInBytes         = frameSize.width;\r
+        stCopyLuma.Height               = frameSize.height;\r
+\r
+        // (2) chroma copy setup, U/V can be done together\r
+        CUDA_MEMCPY2D stCopyChroma;\r
+        memset((void*)&stCopyChroma, 0, sizeof(stCopyChroma));\r
+        stCopyChroma.srcXInBytes        = 0;\r
+        stCopyChroma.srcY               = frameSize.height << 1; // U/V chroma offset\r
+        stCopyChroma.srcMemoryType      = CU_MEMORYTYPE_DEVICE;\r
+        stCopyChroma.srcHost            = 0;\r
+        stCopyChroma.srcDevice          = (CUdeviceptr) src.data;\r
+        stCopyChroma.srcArray           = 0;\r
+        stCopyChroma.srcPitch           = src.step >> 1; // chroma is subsampled by 2 (but it has U/V are next to each other)\r
+\r
+        stCopyChroma.dstXInBytes        = 0;\r
+        stCopyChroma.dstY               = frameSize.height << 1; // chroma offset (srcY*srcPitch now points to the chroma planes)\r
+        stCopyChroma.dstMemoryType      = CU_MEMORYTYPE_DEVICE;\r
+        stCopyChroma.dstHost            = 0;\r
+        stCopyChroma.dstDevice          = (CUdeviceptr) dst.data;\r
+        stCopyChroma.dstArray           = 0;\r
+        stCopyChroma.dstPitch           = dst.step >> 1;\r
+\r
+        stCopyChroma.WidthInBytes       = frameSize.width >> 1;\r
+        stCopyChroma.Height             = frameSize.height; // U/V are sent together\r
+\r
+        // DMA Luma\r
+        res = cuMemcpy2D(&stCopyLuma);\r
+        CV_Assert( res == CUDA_SUCCESS );\r
+\r
+        // DMA Chroma channels (UV side by side)\r
+        res = cuMemcpy2D(&stCopyChroma);\r
+        CV_Assert( res == CUDA_SUCCESS );\r
+    }\r
+\r
+    // NV12 is 4:2:0 format (12bpc)\r
+    // Luma followed by U/V chroma interleaved (12bpc), chroma is subsampled (w/2,h/2)\r
+    void copyNV12Frame(cv::Size frameSize, const cv::gpu::GpuMat& src, cv::gpu::GpuMat& dst)\r
+    {\r
+        CUresult res;\r
+\r
+        // Source is NV12 in pitch linear memory\r
+        // 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\r
+\r
+        // Luma/Chroma can be done in a single transfer\r
+        CUDA_MEMCPY2D stCopyNV12;\r
+        memset((void*)&stCopyNV12, 0, sizeof(stCopyNV12));\r
+        stCopyNV12.srcXInBytes          = 0;\r
+        stCopyNV12.srcY                 = 0;\r
+        stCopyNV12.srcMemoryType        = CU_MEMORYTYPE_DEVICE;\r
+        stCopyNV12.srcHost              = 0;\r
+        stCopyNV12.srcDevice            = (CUdeviceptr) src.data;\r
+        stCopyNV12.srcArray             = 0;\r
+        stCopyNV12.srcPitch             = src.step;\r
+\r
+        stCopyNV12.dstXInBytes          = 0;\r
+        stCopyNV12.dstY                 = 0;\r
+        stCopyNV12.dstMemoryType        = CU_MEMORYTYPE_DEVICE;\r
+        stCopyNV12.dstHost              = 0;\r
+        stCopyNV12.dstDevice            = (CUdeviceptr) dst.data;\r
+        stCopyNV12.dstArray             = 0;\r
+        stCopyNV12.dstPitch             = dst.step;\r
+\r
+        stCopyNV12.WidthInBytes         = frameSize.width;\r
+        stCopyNV12.Height               =(frameSize.height * 3) >> 1;\r
+\r
+        // DMA Luma/Chroma\r
+        res = cuMemcpy2D(&stCopyNV12);\r
+        CV_Assert( res == CUDA_SUCCESS );\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
+    if (inputFormat_ == SF_BGR)\r
+    {\r
+        CV_Assert( frame.size() == frameSize_ );\r
+        CV_Assert( frame.type() == CV_8UC1 || frame.type() == CV_8UC3 || frame.type() == CV_8UC4 );\r
+    }\r
+    else\r
+    {\r
+        CV_Assert( frame.size() == videoFrame_.size() );\r
+        CV_Assert( frame.type() == videoFrame_.type() );\r
+    }\r
 \r
     NVVE_EncodeFrameParams efparams;\r
     efparams.Width = frameSize_.width;\r
@@ -422,8 +570,27 @@ void cv::gpu::VideoWriter_GPU::Impl::write(const cv::gpu::GpuMat& frame, bool la
     CUresult res = cuvidCtxLock(cuCtxLock_, 0);\r
     CV_Assert( res == CUDA_SUCCESS );\r
 \r
-    if (surfaceFormat_ == YV12)\r
+    if (inputFormat_ == SF_BGR)\r
         cv::gpu::device::video_encoding::YV12_gpu(frame, frame.channels(), videoFrame_);\r
+    else\r
+    {\r
+        switch (surfaceFormat_)\r
+        {\r
+        case UYVY: // UYVY (4:2:2)\r
+        case YUY2:     // YUY2 (4:2:2)\r
+            copyUYVYorYUY2Frame(frameSize_, frame, videoFrame_);\r
+            break;\r
+\r
+        case YV12: // YV12 (4:2:0), Y V U\r
+        case IYUV: // IYUV (4:2:0), Y U V\r
+            copyYV12orIYUVFrame(frameSize_, frame, videoFrame_);\r
+            break;\r
+\r
+        case NV12: // NV12 (4:2:0)\r
+            copyNV12Frame(frameSize_, frame, videoFrame_);\r
+            break;\r
+        }\r
+    }\r
 \r
     res = cuvidCtxUnlock(cuCtxLock_, 0);\r
     CV_Assert( res == CUDA_SUCCESS );\r
@@ -480,6 +647,7 @@ private:
 \r
     struct OutputMediaStream_FFMPEG* stream_;\r
     std::vector<uchar> buf_;\r
+    bool isKeyFrame_;\r
 };\r
 \r
 namespace\r
@@ -528,7 +696,7 @@ namespace
 }\r
 \r
 EncoderCallBackFFMPEG::EncoderCallBackFFMPEG(const std::string& fileName, cv::Size frameSize, double fps) :\r
-    stream_(0)\r
+    stream_(0), isKeyFrame_(false)\r
 {\r
     int buf_size = std::max(frameSize.area() * 4, 1024 * 1024);\r
     buf_.resize(buf_size);\r
@@ -552,11 +720,12 @@ unsigned char* EncoderCallBackFFMPEG::acquireBitStream(int* bufferSize)
 \r
 void EncoderCallBackFFMPEG::releaseBitStream(unsigned char* data, int size)\r
 {\r
-    write_OutputMediaStream_FFMPEG_p(stream_, data, size);\r
+    write_OutputMediaStream_FFMPEG_p(stream_, data, size, isKeyFrame_);\r
 }\r
 \r
 void EncoderCallBackFFMPEG::onBeginFrame(int frameNumber, PicType picType)\r
 {\r
+    isKeyFrame_ = picType == IFRAME;\r
 }\r
 \r
 void EncoderCallBackFFMPEG::onEndFrame(int frameNumber, PicType picType)\r
@@ -570,24 +739,24 @@ cv::gpu::VideoWriter_GPU::VideoWriter_GPU()
 {\r
 }\r
 \r
-cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const std::string& fileName, cv::Size frameSize, double fps)\r
+cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const std::string& fileName, cv::Size frameSize, double fps, SurfaceFormat format)\r
 {\r
-    open(fileName, frameSize, fps);\r
+    open(fileName, frameSize, fps, format);\r
 }\r
 \r
-cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const std::string& fileName, cv::Size frameSize, double fps, const EncoderParams& params)\r
+cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const std::string& fileName, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format)\r
 {\r
-    open(fileName, frameSize, fps, params);\r
+    open(fileName, frameSize, fps, params, format);\r
 }\r
 \r
-cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps)\r
+cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps, SurfaceFormat format)\r
 {\r
-    open(encoderCallback, frameSize, fps);\r
+    open(encoderCallback, frameSize, fps, format);\r
 }\r
 \r
-cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps, const EncoderParams& params)\r
+cv::gpu::VideoWriter_GPU::VideoWriter_GPU(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format)\r
 {\r
-    open(encoderCallback, frameSize, fps, params);\r
+    open(encoderCallback, frameSize, fps, params, format);\r
 }\r
 \r
 cv::gpu::VideoWriter_GPU::~VideoWriter_GPU()\r
@@ -595,30 +764,30 @@ cv::gpu::VideoWriter_GPU::~VideoWriter_GPU()
     close();\r
 }\r
 \r
-void cv::gpu::VideoWriter_GPU::open(const std::string& fileName, cv::Size frameSize, double fps)\r
+void cv::gpu::VideoWriter_GPU::open(const std::string& fileName, cv::Size frameSize, double fps, SurfaceFormat format)\r
 {\r
     close();\r
     cv::Ptr<EncoderCallBack> encoderCallback(new EncoderCallBackFFMPEG(fileName, frameSize, fps));\r
-    open(encoderCallback, frameSize, fps);\r
+    open(encoderCallback, frameSize, fps, format);\r
 }\r
 \r
-void cv::gpu::VideoWriter_GPU::open(const std::string& fileName, cv::Size frameSize, double fps, const EncoderParams& params)\r
+void cv::gpu::VideoWriter_GPU::open(const std::string& fileName, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format)\r
 {\r
     close();\r
     cv::Ptr<EncoderCallBack> encoderCallback(new EncoderCallBackFFMPEG(fileName, frameSize, fps));\r
-    open(encoderCallback, frameSize, fps, params);\r
+    open(encoderCallback, frameSize, fps, params, format);\r
 }\r
 \r
-void cv::gpu::VideoWriter_GPU::open(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps)\r
+void cv::gpu::VideoWriter_GPU::open(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps, SurfaceFormat format)\r
 {\r
     close();\r
-    impl_.reset(new Impl(encoderCallback, frameSize, fps));\r
+    impl_.reset(new Impl(encoderCallback, frameSize, fps, format));\r
 }\r
 \r
-void cv::gpu::VideoWriter_GPU::open(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps, const EncoderParams& params)\r
+void cv::gpu::VideoWriter_GPU::open(const cv::Ptr<EncoderCallBack>& encoderCallback, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format)\r
 {\r
     close();\r
-    impl_.reset(new Impl(encoderCallback, frameSize, fps, params));\r
+    impl_.reset(new Impl(encoderCallback, frameSize, fps, params, format));\r
 }\r
 \r
 bool cv::gpu::VideoWriter_GPU::isOpened() const\r
index 5aad37a..3ce80d4 100644 (file)
@@ -71,11 +71,11 @@ typedef void (*CvReleaseVideoWriter_Plugin)( void** writer );
  
 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);
+OPENCV_FFMPEG_API void write_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream, unsigned char* data, int size, int keyFrame);
 
 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);
+typedef void (*Write_OutputMediaStream_FFMPEG_Plugin)(struct OutputMediaStream_FFMPEG* stream, unsigned char* data, int size, int keyFrame);
 
 #ifdef __cplusplus
 }
index 973d392..b269543 100644 (file)
@@ -1454,9 +1454,9 @@ void CvVideoWriter_FFMPEG::close()
 struct OutputMediaStream_FFMPEG
 {
     bool open(const char* fileName, int width, int height, double fps);
-    void write(unsigned char* data, int size);
-
     void close();
+    
+    void write(unsigned char* data, int size, int keyFrame);
 
     // 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);
@@ -1698,13 +1698,16 @@ bool OutputMediaStream_FFMPEG::open(const char* fileName, int width, int height,
     return true;
 }
 
-void OutputMediaStream_FFMPEG::write(unsigned char* data, int size)
+void OutputMediaStream_FFMPEG::write(unsigned char* data, int size, int keyFrame)
 {
     // if zero size, it means the image was buffered
     if (size > 0) 
     {
         AVPacket pkt;
         av_init_packet(&pkt);
+        
+        if (keyFrame)
+            pkt.flags |= PKT_FLAG_KEY;
 
         pkt.stream_index = video_st_->index;
         pkt.data = data;
@@ -1734,7 +1737,7 @@ void release_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream)
     free(stream);
 }
 
-void write_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream, unsigned char* data, int size)
+void write_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream, unsigned char* data, int size, int keyFrame)
 {
-    stream->write(data, size);
+    stream->write(data, size, keyFrame);
 }
index 4e5b425..8298208 100755 (executable)
@@ -1620,9 +1620,9 @@ void CvVideoWriter_FFMPEG::close()
 struct OutputMediaStream_FFMPEG
 {
     bool open(const char* fileName, int width, int height, double fps);
-    void write(unsigned char* data, int size);
-
     void close();
+    
+    void write(unsigned char* data, int size, int keyFrame);
 
     // 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);
@@ -1864,7 +1864,7 @@ bool OutputMediaStream_FFMPEG::open(const char* fileName, int width, int height,
     return true;
 }
 
-void OutputMediaStream_FFMPEG::write(unsigned char* data, int size)
+void OutputMediaStream_FFMPEG::write(unsigned char* data, int size, int keyFrame)
 {
     // if zero size, it means the image was buffered
     if (size > 0) 
@@ -1872,6 +1872,9 @@ void OutputMediaStream_FFMPEG::write(unsigned char* data, int size)
         AVPacket pkt;
         av_init_packet(&pkt);
 
+        if (keyFrame)
+            pkt.flags |= PKT_FLAG_KEY;
+
         pkt.stream_index = video_st_->index;
         pkt.data = data;
         pkt.size = size;
@@ -1900,7 +1903,7 @@ void release_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream)
     free(stream);
 }
 
-void write_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream, unsigned char* data, int size)
+void write_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream, unsigned char* data, int size, int keyFrame)
 {
-    stream->write(data, size);
+    stream->write(data, size, keyFrame);
 }