|
44 | 44 | #include "precomp.hpp"
|
45 | 45 |
|
46 | 46 | #ifdef HAVE_NVCUVID
|
47 |
| - |
48 | 47 | using namespace cv;
|
49 | 48 | using namespace cv::cudacodec;
|
50 | 49 | using namespace cv::cudacodec::detail;
|
51 | 50 |
|
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) |
53 | 56 | {
|
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 | +} |
57 | 68 |
|
58 |
| - bool init_MediaStream_FFMPEG() |
| 69 | +static |
| 70 | +Codec FourccToCodec(int codec) |
| 71 | +{ |
| 72 | + switch (codec) |
59 | 73 | {
|
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; |
95 | 91 | }
|
| 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); |
96 | 96 | }
|
97 | 97 |
|
98 |
| -cv::cudacodec::detail::FFmpegVideoSource::FFmpegVideoSource(const String& fname) : |
99 |
| - stream_(0) |
| 98 | +static |
| 99 | +void FourccToChromaFormat(const int pixelFormat, ChromaFormat &chromaFormat, int & nBitDepthMinus8) |
100 | 100 | {
|
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 | +} |
102 | 114 |
|
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"); |
107 | 119 |
|
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()) |
110 | 122 | CV_Error(Error::StsUnsupportedFormat, "Unsupported video source");
|
111 | 123 |
|
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); |
117 | 135 | }
|
118 | 136 |
|
119 | 137 | cv::cudacodec::detail::FFmpegVideoSource::~FFmpegVideoSource()
|
120 | 138 | {
|
121 |
| - if (stream_) |
122 |
| - release_InputMediaStream_FFMPEG_p(stream_); |
| 139 | + if (cap.isOpened()) |
| 140 | + cap.release(); |
123 | 141 | }
|
124 | 142 |
|
125 | 143 | FormatInfo cv::cudacodec::detail::FFmpegVideoSource::format() const
|
126 | 144 | {
|
127 | 145 | return format_;
|
128 | 146 | }
|
129 | 147 |
|
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) |
131 | 149 | {
|
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; |
138 | 154 | }
|
139 | 155 |
|
140 | 156 | #endif // HAVE_CUDA
|
0 commit comments