Add retrieve encoded frame to VideoCapture#15290
Conversation
Old flag resulted in software implementation being selected when the Intel decoder is not the primary adapter.
|
Updated to use a separate VideoContainer subclass as suggested by mshabunin |
…VideoContainer as suggested by mshabunin.
|
@cudawarped , I have several general comments/questions:
|
|
@mshabunin thanks for the feedback I have been changing my mind continually regarding your first point.
I would prefer not to mess with the class hierarchy as I have done if possible, but I couldn't think of a sensible way to use all the existing methods inside or to have a completely separate class VideoContainer with member |
|
I was thinking about something like this// videoio.hpp
class VideoContainer {
public:
bool open(const std::string &, int);
size_t read(uchar *, size_t);
bool isOpened() const;
// maybe something like: cv::Codec getCodec() const;
private:
Ptr<IVideoCapture> icap;
};// cap.cpp
bool VideoContainer::open(...) {
// body similar to VideoCapture::open, some parts can be extracted to static function and reused
icap = backend->createRawCapture(...);
}
size_t VideoContainer::read(...) {
// ...
icap->readRaw(...);
// ...
}// backend.hpp (.cpp)
Ptr<IVideoCapture> StaticBackend::createRawCapture(...) {
auto cap = createCapture(...);
if (cap && cap->setRaw(true)) return cap;
return 0;
}
// TODO: implement PluginBackend::createRawCapture later// cap_interface.hpp
class IVideoCapture {
virtual bool setRaw(bool) { return false; }
virtual size_t readRaw(...);
}// cap_ffmpeg.cpp
class CvCapture_FFMPEG_proxy CV_FINAL : public cv::IVideoCapture {
// implement setRaw and readRaw
}Later we can rework internals and create hidden |
-setRaw to disable video decoding and enable bitstream filters from mp4 to h254 and h265. -readRaw to return the raw undecoded/filtered bitstream. Add createRawCapture to initiate a backend with setRaw enabled. Remove inheritance and use an independant VideoContainer subclass with IVideoCapture member.
|
@mshabunin I have added the suggested changes and have a few additional queries.
|
Remove VideoContainer from python bindings as it no longer returns a Mat. Use opencv type uchar instead of unsigned char. Add missing destructor to VideoContainer class.
Change api version defines to be consistent - most recent api version first.
Test files should be added to opencv_extra repository using the same branch name as this PR (ffmpeg_raw_retrieve), then both PRs will be tested together. |
Good point, I am not sure that it is, my only use case for this PR is to decode with cudacodec where it is required. Would you prefer a separate function to initialize this after creation ( |
|
OK, let's leave it enabled then. We will be able to extend interface later. As for test data, I suggest replacing .h264 and .h265 with filtered streams and adding corresponding .mp4 files to leave the test simple. We can restore original files and add filtering test case later. |
|
@mshabunin
The ffmpeg version which OpenCV is currently built against
which is causing (1) to fail in the following way. When big_buck_bunny_h264.mp4 is read and passed through the h264_mp4toannexb filter pre this fix the start code length added to the parameter sets is |
|
@cudawarped , the test (1) should be dropped then. |
|
@mshabunin test dropped and redundant PR opencv/opencv_extra#673 adding additional test data closed. |
|
@mshabunin is there anything I can do to prepare this PR for merging so we can fix cudacodec? |
|
@cudawarped , sorry for delay, I'll take a look next week. |
|
@mshabunin, no worries thanks for all your help.
The cudacodec decoder implementation from the latest commit to opencv/opencv_contrib#2180 should successfully decode frames retrieved using this VideoContainer class and pass the included tests.
Are the test's sufficient? Additionally I don't know if the ffmpeg plugin will compile against this. |
modules/videoio/src/plugin_api.hpp
Outdated
| #endif | ||
|
|
||
| typedef CvResult (CV_API_CALL *cv_videoio_retrieve_cb_t)(int stream_idx, unsigned const char* data, int step, int width, int height, int cn, void* userdata); | ||
| typedef CvResult (CV_API_CALL* cv_videoio_retrieve_raw_cb_t)(unsigned const char* data, int step, void* userdata); |
There was a problem hiding this comment.
int step should be size_t size
There was a problem hiding this comment.
@mshabunin Does Capture_retreive_raw need to use a callback or can it just be defined as
CvResult(CV_API_CALL *Capture_retreive_raw)(CvPluginCapture handle, uchar** data, size_t* size);
modules/videoio/src/plugin_api.hpp
Outdated
| @param callback retrieve callback (synchronous) | ||
| @param userdata callback context data | ||
|
|
||
| @note API-CALL 13, API-Version == 0 |
There was a problem hiding this comment.
I guess it should be API-Version == 1 and API_VERSION should be increased. @alalek, is it correct?
| VideoCodec_NumCodecs, | ||
|
|
||
| // Uncompressed YUV | ||
| VideoCodec_YUV420 = (('I' << 24) | ('Y' << 16) | ('U' << 8) | ('V')), // Y,U,V (4:2:0) |
There was a problem hiding this comment.
Some items have FourCC code, others not. Perhaps we can get rid of this enumeration completely and use FourCC codes for new properties.
There was a problem hiding this comment.
@mshabunin Those
Uncompressed YUV
are codecs returned by the nvcuvid video parser and can be removed, I incorrectly included them here.
I could use FOURCC codes for the remaining codecs but because there can be a many to one mapping from ffmpeg FOURCC codes to codec (h264, x264 etc.) it seemed more suitable to return the ffmpeg codec, do you agree?
modules/videoio/src/cap_ffmpeg.cpp
Outdated
| /* 12*/cv_writer_write | ||
| /* 12*/cv_writer_write, | ||
| /* 13*/cv_capture_read_raw | ||
| /* 14*/cv_capture_set_raw |
There was a problem hiding this comment.
This table is not consistent with one in plugin_api.h. Build with -DVIDEOIO_PLUGIN_LIST=ffmpeg option fails.
There was a problem hiding this comment.
Now builds with -DVIDEOIO_PLUGIN_LIST=ffmpeg flag although the plugin code could still be incorrect.
modules/videoio/src/cap.cpp
Outdated
| } | ||
| } catch(const cv::Exception& e) { | ||
| if(throwOnFail && apiPreference != CAP_ANY) throw; | ||
| } |
There was a problem hiding this comment.
Please restore formatting of this block.
…ncapsulation videoio: Add raw encoded video stream muxing to cv::VideoWriter with CAP_FFMPEG #24363 Allow raw encoded video streams (e.g. h264[5]) to be encapsulated by `cv::VideoWriter` to video containers (e.g. mp4/mkv). Operates in a similar way to #15290 where encapsulation is enabled by setting the `VideoWriterProperties::VIDEOWRITER_PROP_RAW_VIDEO` flag when constructing `cv::VideoWriter` e.g. ``` VideoWriter container(fileNameOut, api, fourcc, fps, { width, height }, { VideoWriterProperties::VIDEOWRITER_PROP_RAW_VIDEO, 1 }); ``` and each raw encoded frame is passed as single row of a `CV_8U` `cv::Mat`. The main reason for this PR is to allow `cudacodec::VideoWriter` to output its encoded streams to a suitable container, see opencv/opencv_contrib#3569. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
…ream_encapsulation videoio: Add raw encoded video stream muxing to cv::VideoWriter with CAP_FFMPEG opencv#24363 Allow raw encoded video streams (e.g. h264[5]) to be encapsulated by `cv::VideoWriter` to video containers (e.g. mp4/mkv). Operates in a similar way to opencv#15290 where encapsulation is enabled by setting the `VideoWriterProperties::VIDEOWRITER_PROP_RAW_VIDEO` flag when constructing `cv::VideoWriter` e.g. ``` VideoWriter container(fileNameOut, api, fourcc, fps, { width, height }, { VideoWriterProperties::VIDEOWRITER_PROP_RAW_VIDEO, 1 }); ``` and each raw encoded frame is passed as single row of a `CV_8U` `cv::Mat`. The main reason for this PR is to allow `cudacodec::VideoWriter` to output its encoded streams to a suitable container, see opencv/opencv_contrib#3569. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
…ream_encapsulation videoio: Add raw encoded video stream muxing to cv::VideoWriter with CAP_FFMPEG opencv#24363 Allow raw encoded video streams (e.g. h264[5]) to be encapsulated by `cv::VideoWriter` to video containers (e.g. mp4/mkv). Operates in a similar way to opencv#15290 where encapsulation is enabled by setting the `VideoWriterProperties::VIDEOWRITER_PROP_RAW_VIDEO` flag when constructing `cv::VideoWriter` e.g. ``` VideoWriter container(fileNameOut, api, fourcc, fps, { width, height }, { VideoWriterProperties::VIDEOWRITER_PROP_RAW_VIDEO, 1 }); ``` and each raw encoded frame is passed as single row of a `CV_8U` `cv::Mat`. The main reason for this PR is to allow `cudacodec::VideoWriter` to output its encoded streams to a suitable container, see opencv/opencv_contrib#3569. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
…ream_encapsulation videoio: Add raw encoded video stream muxing to cv::VideoWriter with CAP_FFMPEG opencv#24363 Allow raw encoded video streams (e.g. h264[5]) to be encapsulated by `cv::VideoWriter` to video containers (e.g. mp4/mkv). Operates in a similar way to opencv#15290 where encapsulation is enabled by setting the `VideoWriterProperties::VIDEOWRITER_PROP_RAW_VIDEO` flag when constructing `cv::VideoWriter` e.g. ``` VideoWriter container(fileNameOut, api, fourcc, fps, { width, height }, { VideoWriterProperties::VIDEOWRITER_PROP_RAW_VIDEO, 1 }); ``` and each raw encoded frame is passed as single row of a `CV_8U` `cv::Mat`. The main reason for this PR is to allow `cudacodec::VideoWriter` to output its encoded streams to a suitable container, see opencv/opencv_contrib#3569. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
This pullrequest adds the functionality to retrieve the encoded bitstream for a grabbed video frame
Since #14774 cudacodec has been broken because it needs the capacity to fall back on ffmpeg for parsing certain video files and rtsp streams. This pull request adds the capacity to retrieve the encoded bit stream for each frame to the VideoCapture class as suggested in opencv/opencv_contrib#2180.
I have only built against the ffmpeg binaries (I am not sure how to build the plugin) I suspect that I may have broken the plugin functionality because I simply copied the existing retrieve method in
plugin_api.handcap_ffmpeg.cpp.