Skip to content

Commit 53b9880

Browse files
cudawarpedalalek
authored andcommitted
Merge pull request #2180 from cudawarped:example_fix_for_cudacodec
OpenCV fix 14774 breaks cudacodec * Example to describe comilation issue * Added required changes, builds with -DWITH_FFMPEG=ON|OFF * Working with standard ffmpeg cap. * Changed cudacodec to use new retrieveRaw() function, to retrieve the raw encoded bitstream, from the videoio module instead of its own implementation. * Fix cv::cudacodec::VideoWriter * Update to use VideoContainer * Remove header used in testing * Remove warning * remove dependence on redundant ffmpeg codecs * cudacodec: use .set(CAP_PROP_FORMAT, -1) to extract RAW streams * whitespace * addressed alalek's comment
1 parent 35972a1 commit 53b9880

15 files changed

+174
-140
lines changed

modules/cudacodec/include/opencv2/cudacodec.hpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@
5959

6060
namespace cv { namespace cudacodec {
6161

62+
using namespace cuda; // Stream
63+
6264
//! @addtogroup cudacodec
6365
//! @{
6466

@@ -253,6 +255,7 @@ enum Codec
253255
HEVC,
254256
VP8,
255257
VP9,
258+
NumCodecs,
256259

257260
Uncompressed_YUV420 = (('I'<<24)|('Y'<<16)|('U'<<8)|('V')), //!< Y,U,V (4:2:0)
258261
Uncompressed_YV12 = (('Y'<<24)|('V'<<16)|('1'<<8)|('2')), //!< Y,V,U (4:2:0)
@@ -268,7 +271,8 @@ enum ChromaFormat
268271
Monochrome = 0,
269272
YUV420,
270273
YUV422,
271-
YUV444
274+
YUV444,
275+
NumFormats
272276
};
273277

274278
/** @brief Struct providing information about video file format. :
@@ -298,7 +302,7 @@ class CV_EXPORTS_W VideoReader
298302
If no frames has been grabbed (there are no more frames in video file), the methods return false .
299303
The method throws Exception if error occurs.
300304
*/
301-
CV_WRAP virtual bool nextFrame(OutputArray frame) = 0;
305+
CV_WRAP virtual bool nextFrame(OutputArray frame, Stream &stream = Stream::Null()) = 0;
302306

303307
/** @brief Returns information about video file format.
304308
*/
@@ -318,9 +322,8 @@ class CV_EXPORTS_W RawVideoSource
318322
319323
@param data Pointer to frame data.
320324
@param size Size in bytes of current frame.
321-
@param endOfFile Indicates that it is end of stream.
322325
*/
323-
virtual bool getNextPacket(unsigned char** data, int* size, bool* endOfFile) = 0;
326+
virtual bool getNextPacket(unsigned char** data, size_t* size) = 0;
324327

325328
/** @brief Returns information about video file format.
326329
*/

modules/cudacodec/perf/perf_video.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,21 @@
4646

4747
namespace opencv_test { namespace {
4848

49+
#if defined(HAVE_NVCUVID)
50+
51+
#if defined(HAVE_FFMPEG_WRAPPER) // should this be set in preprocessor or in cvconfig.h
52+
#define VIDEO_SRC Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi")
53+
#else
54+
// CUDA demuxer has to fall back to ffmpeg to process "gpu/video/768x576.avi"
55+
#define VIDEO_SRC Values( "gpu/video/1920x1080.avi")
56+
#endif
57+
4958
DEF_PARAM_TEST_1(FileName, string);
5059

5160
//////////////////////////////////////////////////////
5261
// VideoReader
5362

54-
#if defined(HAVE_NVCUVID)
55-
56-
PERF_TEST_P(FileName, VideoReader, Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"))
63+
PERF_TEST_P(FileName, VideoReader, VIDEO_SRC)
5764
{
5865
declare.time(20);
5966

@@ -89,7 +96,7 @@ PERF_TEST_P(FileName, VideoReader, Values("gpu/video/768x576.avi", "gpu/video/19
8996

9097
#if defined(HAVE_NVCUVID) && defined(_WIN32)
9198

92-
PERF_TEST_P(FileName, VideoWriter, Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"))
99+
PERF_TEST_P(FileName, VideoWriter, VIDEO_SRC)
93100
{
94101
declare.time(30);
95102

modules/cudacodec/src/cuda/nv12_to_rgb.cu

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
using namespace cv;
6161
using namespace cv::cudev;
6262

63-
void videoDecPostProcessFrame(const GpuMat& decodedFrame, OutputArray _outFrame, int width, int height);
63+
void videoDecPostProcessFrame(const GpuMat& decodedFrame, OutputArray _outFrame, int width, int height, cudaStream_t stream);
6464

6565
namespace
6666
{
@@ -186,7 +186,7 @@ namespace
186186
}
187187
}
188188

189-
void videoDecPostProcessFrame(const GpuMat& decodedFrame, OutputArray _outFrame, int width, int height)
189+
void videoDecPostProcessFrame(const GpuMat& decodedFrame, OutputArray _outFrame, int width, int height, cudaStream_t stream)
190190
{
191191
// Final Stage: NV12toARGB color space conversion
192192

@@ -196,12 +196,13 @@ void videoDecPostProcessFrame(const GpuMat& decodedFrame, OutputArray _outFrame,
196196
dim3 block(32, 8);
197197
dim3 grid(divUp(width, 2 * block.x), divUp(height, block.y));
198198

199-
NV12_to_RGB<<<grid, block>>>(decodedFrame.ptr<uchar>(), decodedFrame.step,
199+
NV12_to_RGB<<<grid, block, 0, stream>>>(decodedFrame.ptr<uchar>(), decodedFrame.step,
200200
outFrame.ptr<uint>(), outFrame.step,
201201
width, height);
202202

203203
CV_CUDEV_SAFE_CALL( cudaGetLastError() );
204-
CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() );
204+
if (stream == 0)
205+
CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() );
205206
}
206207

207208
#endif

modules/cudacodec/src/cuvid_video_source.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ cv::cudacodec::detail::CuvidVideoSource::CuvidVideoSource(const String& fname)
6868
CUVIDEOFORMAT vidfmt;
6969
cuSafeCall( cuvidGetSourceVideoFormat(videoSource_, &vidfmt, 0) );
7070

71+
CV_Assert(Codec::NumCodecs == cudaVideoCodec::cudaVideoCodec_NumCodecs);
7172
format_.codec = static_cast<Codec>(vidfmt.codec);
7273
format_.chromaFormat = static_cast<ChromaFormat>(vidfmt.chroma_format);
7374
format_.nBitDepthMinus8 = vidfmt.bit_depth_luma_minus8;

modules/cudacodec/src/ffmpeg_video_source.cpp

Lines changed: 80 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -44,97 +44,113 @@
4444
#include "precomp.hpp"
4545

4646
#ifdef HAVE_NVCUVID
47-
4847
using namespace cv;
4948
using namespace cv::cudacodec;
5049
using namespace cv::cudacodec::detail;
5150

52-
namespace
51+
#ifndef CV_FOURCC_MACRO
52+
#define CV_FOURCC_MACRO(c1, c2, c3, c4) (((c1) & 255) + (((c2) & 255) << 8) + (((c3) & 255) << 16) + (((c4) & 255) << 24))
53+
#endif
54+
55+
static std::string fourccToString(int fourcc)
5356
{
54-
Create_InputMediaStream_FFMPEG_Plugin create_InputMediaStream_FFMPEG_p = 0;
55-
Release_InputMediaStream_FFMPEG_Plugin release_InputMediaStream_FFMPEG_p = 0;
56-
Read_InputMediaStream_FFMPEG_Plugin read_InputMediaStream_FFMPEG_p = 0;
57+
union {
58+
int u32;
59+
unsigned char c[4];
60+
} i32_c;
61+
i32_c.u32 = fourcc;
62+
return cv::format("%c%c%c%c",
63+
(i32_c.c[0] >= ' ' && i32_c.c[0] < 128) ? i32_c.c[0] : '?',
64+
(i32_c.c[1] >= ' ' && i32_c.c[1] < 128) ? i32_c.c[1] : '?',
65+
(i32_c.c[2] >= ' ' && i32_c.c[2] < 128) ? i32_c.c[2] : '?',
66+
(i32_c.c[3] >= ' ' && i32_c.c[3] < 128) ? i32_c.c[3] : '?');
67+
}
5768

58-
bool init_MediaStream_FFMPEG()
69+
static
70+
Codec FourccToCodec(int codec)
71+
{
72+
switch (codec)
5973
{
60-
static bool initialized = 0;
61-
62-
if (!initialized)
63-
{
64-
#if defined _WIN32
65-
const char* module_name = "opencv_ffmpeg"
66-
CVAUX_STR(CV_VERSION_MAJOR) CVAUX_STR(CV_VERSION_MINOR) CVAUX_STR(CV_VERSION_REVISION)
67-
#if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__)
68-
"_64"
69-
#endif
70-
".dll";
71-
72-
static HMODULE cvFFOpenCV = LoadLibrary(module_name);
73-
74-
if (cvFFOpenCV)
75-
{
76-
create_InputMediaStream_FFMPEG_p =
77-
(Create_InputMediaStream_FFMPEG_Plugin)GetProcAddress(cvFFOpenCV, "create_InputMediaStream_FFMPEG");
78-
release_InputMediaStream_FFMPEG_p =
79-
(Release_InputMediaStream_FFMPEG_Plugin)GetProcAddress(cvFFOpenCV, "release_InputMediaStream_FFMPEG");
80-
read_InputMediaStream_FFMPEG_p =
81-
(Read_InputMediaStream_FFMPEG_Plugin)GetProcAddress(cvFFOpenCV, "read_InputMediaStream_FFMPEG");
82-
83-
initialized = create_InputMediaStream_FFMPEG_p != 0 && release_InputMediaStream_FFMPEG_p != 0 && read_InputMediaStream_FFMPEG_p != 0;
84-
}
85-
#elif defined HAVE_FFMPEG
86-
create_InputMediaStream_FFMPEG_p = create_InputMediaStream_FFMPEG;
87-
release_InputMediaStream_FFMPEG_p = release_InputMediaStream_FFMPEG;
88-
read_InputMediaStream_FFMPEG_p = read_InputMediaStream_FFMPEG;
89-
90-
initialized = true;
91-
#endif
92-
}
93-
94-
return initialized;
74+
case CV_FOURCC_MACRO('m', 'p', 'e', 'g'): // fallthru
75+
case CV_FOURCC_MACRO('M', 'P', 'G', '1'): return MPEG1;
76+
case CV_FOURCC_MACRO('M', 'P', 'G', '2'): return MPEG2;
77+
case CV_FOURCC_MACRO('X', 'V', 'I', 'D'): // fallthru
78+
case CV_FOURCC_MACRO('D', 'I', 'V', 'X'): return MPEG4;
79+
case CV_FOURCC_MACRO('W', 'V', 'C', '1'): return VC1;
80+
case CV_FOURCC_MACRO('H', '2', '6', '4'): // fallthru
81+
case CV_FOURCC_MACRO('h', '2', '6', '4'): // fallthru
82+
case CV_FOURCC_MACRO('a', 'v', 'c', '1'): return H264;
83+
case CV_FOURCC_MACRO('H', '2', '6', '5'): // fallthru
84+
case CV_FOURCC_MACRO('h', '2', '6', '5'): // fallthru
85+
case CV_FOURCC_MACRO('h', 'e', 'v', 'c'): return HEVC;
86+
case CV_FOURCC_MACRO('M', 'J', 'P', 'G'): return JPEG;
87+
case CV_FOURCC_MACRO('V', 'P', '8', '0'): return VP8;
88+
case CV_FOURCC_MACRO('V', 'P', '9', '0'): return VP9;
89+
default:
90+
break;
9591
}
92+
93+
std::string msg = cv::format("Unknown codec FOURCC: 0x%08X (%s)", codec, fourccToString(codec).c_str());
94+
CV_LOG_WARNING(NULL, msg);
95+
CV_Error(Error::StsUnsupportedFormat, msg);
9696
}
9797

98-
cv::cudacodec::detail::FFmpegVideoSource::FFmpegVideoSource(const String& fname) :
99-
stream_(0)
98+
static
99+
void FourccToChromaFormat(const int pixelFormat, ChromaFormat &chromaFormat, int & nBitDepthMinus8)
100100
{
101-
CV_Assert( init_MediaStream_FFMPEG() );
101+
switch (pixelFormat)
102+
{
103+
case CV_FOURCC_MACRO('I', '4', '2', '0'):
104+
chromaFormat = YUV420;
105+
nBitDepthMinus8 = 0;
106+
break;
107+
default:
108+
CV_LOG_WARNING(NULL, cv::format("ChromaFormat not recognized: 0x%08X (%s). Assuming I420", pixelFormat, fourccToString(pixelFormat).c_str()));
109+
chromaFormat = YUV420;
110+
nBitDepthMinus8 = 0;
111+
break;
112+
}
113+
}
102114

103-
int codec;
104-
int chroma_format;
105-
int width;
106-
int height;
115+
cv::cudacodec::detail::FFmpegVideoSource::FFmpegVideoSource(const String& fname)
116+
{
117+
if (!videoio_registry::hasBackend(CAP_FFMPEG))
118+
CV_Error(Error::StsNotImplemented, "FFmpeg backend not found");
107119

108-
stream_ = create_InputMediaStream_FFMPEG_p(fname.c_str(), &codec, &chroma_format, &width, &height);
109-
if (!stream_)
120+
cap.open(fname, CAP_FFMPEG);
121+
if (!cap.isOpened())
110122
CV_Error(Error::StsUnsupportedFormat, "Unsupported video source");
111123

112-
format_.codec = static_cast<Codec>(codec);
113-
format_.chromaFormat = static_cast<ChromaFormat>(chroma_format);
114-
format_.nBitDepthMinus8 = -1;
115-
format_.width = width;
116-
format_.height = height;
124+
if (!cap.set(CAP_PROP_FORMAT, -1)) // turn off video decoder (extract stream)
125+
CV_Error(Error::StsUnsupportedFormat, "Fetching of RAW video streams is not supported");
126+
CV_Assert(cap.get(CAP_PROP_FORMAT) == -1);
127+
128+
int codec = (int)cap.get(CAP_PROP_FOURCC);
129+
int pixelFormat = (int)cap.get(CAP_PROP_CODEC_PIXEL_FORMAT);
130+
131+
format_.codec = FourccToCodec(codec);
132+
format_.height = cap.get(CAP_PROP_FRAME_HEIGHT);
133+
format_.width = cap.get(CAP_PROP_FRAME_WIDTH);
134+
FourccToChromaFormat(pixelFormat, format_.chromaFormat, format_.nBitDepthMinus8);
117135
}
118136

119137
cv::cudacodec::detail::FFmpegVideoSource::~FFmpegVideoSource()
120138
{
121-
if (stream_)
122-
release_InputMediaStream_FFMPEG_p(stream_);
139+
if (cap.isOpened())
140+
cap.release();
123141
}
124142

125143
FormatInfo cv::cudacodec::detail::FFmpegVideoSource::format() const
126144
{
127145
return format_;
128146
}
129147

130-
bool cv::cudacodec::detail::FFmpegVideoSource::getNextPacket(unsigned char** data, int* size, bool* bEndOfFile)
148+
bool cv::cudacodec::detail::FFmpegVideoSource::getNextPacket(unsigned char** data, size_t* size)
131149
{
132-
int endOfFile;
133-
134-
int res = read_InputMediaStream_FFMPEG_p(stream_, data, size, &endOfFile);
135-
136-
*bEndOfFile = (endOfFile != 0);
137-
return res != 0;
150+
cap >> rawFrame;
151+
*data = rawFrame.data;
152+
*size = rawFrame.total();
153+
return *size != 0;
138154
}
139155

140156
#endif // HAVE_CUDA

modules/cudacodec/src/ffmpeg_video_source.hpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@
4646

4747
#include "opencv2/cudacodec.hpp"
4848

49-
struct InputMediaStream_FFMPEG;
50-
5149
namespace cv { namespace cudacodec { namespace detail {
5250

5351
class FFmpegVideoSource : public RawVideoSource
@@ -56,14 +54,14 @@ class FFmpegVideoSource : public RawVideoSource
5654
FFmpegVideoSource(const String& fname);
5755
~FFmpegVideoSource();
5856

59-
bool getNextPacket(unsigned char** data, int* size, bool* endOfFile) CV_OVERRIDE;
57+
bool getNextPacket(unsigned char** data, size_t* size) CV_OVERRIDE;
6058

6159
FormatInfo format() const CV_OVERRIDE;
6260

6361
private:
6462
FormatInfo format_;
65-
66-
InputMediaStream_FFMPEG* stream_;
63+
VideoCapture cap;
64+
Mat rawFrame;
6765
};
6866

6967
}}}

modules/cudacodec/src/precomp.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@
5252
#include <iostream>
5353

5454
#include "opencv2/cudacodec.hpp"
55-
55+
#include "opencv2/videoio.hpp"
56+
#include "opencv2/videoio/registry.hpp"
5657
#include "opencv2/core/private.cuda.hpp"
58+
#include <opencv2/core/utils/logger.hpp>
5759

5860
#ifdef HAVE_NVCUVID
5961
#if CUDA_VERSION >= 9000 && CUDA_VERSION < 10000
@@ -81,7 +83,6 @@
8183
#include "video_decoder.hpp"
8284
#include "video_parser.hpp"
8385

84-
#include "../src/cap_ffmpeg_api.hpp"
8586
#endif
8687

8788
#endif /* OPENCV_PRECOMP_H */

0 commit comments

Comments
 (0)