Skip to content

Open VideoCapture from data stream#25584

Merged
asmorkalov merged 43 commits intoopencv:4.xfrom
dkurt:videocapture_from_buffer
Dec 26, 2024
Merged

Open VideoCapture from data stream#25584
asmorkalov merged 43 commits intoopencv:4.xfrom
dkurt:videocapture_from_buffer

Conversation

@dkurt
Copy link
Copy Markdown
Member

@dkurt dkurt commented May 14, 2024

Pull Request Readiness Checklist

Add VideoCapture option to read a raw binary video data from std::streambuf.

There are multiple motivations:

  1. Avoid disk file creation in case of video already in memory (received by network or from database).
  2. Streaming mode. Frames decoding starts during sequential file transfer by chunks.

Suppoted backends:

  • FFmpeg
  • MSMF (no streaming mode)

Supporter interfaces:

  • C++ (std::streambuf)
  • Python (io.BufferedIOBase)

resolves #24400

  • test h264
  • test IP camera like approach with no metadata but key frame only?
  • C API plugin

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • 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
  • The PR is proposed to the proper branch
  • There is a reference to the original bug report and related work
  • There is accuracy test, performance test and test data in opencv_extra repository, if applicable
    Patch to opencv_extra has the same branch name.
  • The feature is well documented and sample code can be built with the project CMake

@dkurt dkurt force-pushed the videocapture_from_buffer branch from 2bd1a39 to 023eeb5 Compare May 14, 2024 12:42
@dkurt dkurt changed the title Open VideoCapture from memory buffer Open VideoCapture from memory buffer (FFmpeg backend only) May 15, 2024
@dkurt dkurt marked this pull request as ready for review May 15, 2024 14:50
@dkurt dkurt changed the title Open VideoCapture from memory buffer (FFmpeg backend only) Open VideoCapture from memory buffer May 16, 2024
@dkurt dkurt force-pushed the videocapture_from_buffer branch from 4dace6c to b71844d Compare May 16, 2024 19:24
Copy link
Copy Markdown
Contributor

@opencv-alalek opencv-alalek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plugin support is necessary - it is mandatory for FFmpeg support on Windows.

@asmorkalov asmorkalov added this to the 4.11.0 milestone May 17, 2024
@dkurt dkurt force-pushed the videocapture_from_buffer branch from ec90def to eeae54d Compare June 5, 2024 06:04
@dkurt
Copy link
Copy Markdown
Member Author

dkurt commented Jun 7, 2024

Discussed on OpenCV weekly sync about potential improvements:

  1. On current PR state, do not use std::vector but allow user pass just pointer/buffer_size.
  2. Consider alternative API with a kind of streaming by chunks. Might be more efficient with GPU decoders.

@dkurt dkurt marked this pull request as draft June 7, 2024 07:10
@mshabunin
Copy link
Copy Markdown
Contributor

mshabunin commented Jun 7, 2024

We have something similar in cudacodec module:

RawVideoSource object is an iterator over encoded data stream (https://github.com/opencv/opencv_contrib/blob/b236c71c2f8d983403c35a0cea8bec0432a4b0fe/modules/cudacodec/include/opencv2/cudacodec.hpp#L508-L555) and can be used to construct VideoReader (https://github.com/opencv/opencv_contrib/blob/b236c71c2f8d983403c35a0cea8bec0432a4b0fe/modules/cudacodec/include/opencv2/cudacodec.hpp#L604).

Following example in the test decodes key frames (if I understand corretly): https://github.com/opencv/opencv_contrib/blob/b236c71c2f8d983403c35a0cea8bec0432a4b0fe/modules/cudacodec/test/test_video.cpp#L178-L209

@gdippolito
Copy link
Copy Markdown

Hello, what is left to complete this work? Would anyone be able to complete this work by any chance?

@dkurt
Copy link
Copy Markdown
Member Author

dkurt commented Aug 16, 2024

@gdippolito, I can complete this one once I can figure out which API is better. Last time we discussed in the team, more generic is to introduce kind of streaming API which returns chunks of video buffer.

@dkurt dkurt force-pushed the videocapture_from_buffer branch from eeae54d to 175f070 Compare September 28, 2024 07:40
@dkurt dkurt force-pushed the videocapture_from_buffer branch 3 times, most recently from 214cd8a to 62cd53a Compare October 10, 2024 19:22
@dkurt dkurt marked this pull request as ready for review October 14, 2024 11:05
@dkurt dkurt changed the title Open VideoCapture from memory buffer Open VideoCapture from std::streambuf Oct 15, 2024
@gdippolito
Copy link
Copy Markdown

Hey @dkurt thanks for your work on this PR. Do you think this is ready for some testing?

@dkurt
Copy link
Copy Markdown
Member Author

dkurt commented Oct 21, 2024

@gdippolito, thanks! Yes, it's ready and any feedback is welcome.

@dkurt
Copy link
Copy Markdown
Member Author

dkurt commented Dec 24, 2024

std::streambuf is the I/O stream object at first (but "buffered" variant).
They are not buffers.

Totally fine to keep stream notation everywhere. There is just a conflict in public API with filename (getStreamBackends)

@opencv-alalek opencv-alalek self-assigned this Dec 24, 2024
try
{
cv::VideoCaptureParameters parameters(params, n_params);
cap = new CvCapture_FFMPEG_proxy(makePtr<ReadStreamPluginProvider>(opaque, read, seek), parameters);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makePtr<ReadStreamPluginProvider>(opaque, read, seek)

Released right after this call because it is not saved anywhere.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a workaround, readStream = stream for now

@opencv-pushbot opencv-pushbot force-pushed the videocapture_from_buffer branch from ffb04fd to ad2b7b3 Compare December 24, 2024 16:40
@opencv-pushbot opencv-pushbot force-pushed the videocapture_from_buffer branch from ad2b7b3 to 64a7d96 Compare December 24, 2024 17:55

/** @brief Read data stream interface
*/
class CV_EXPORTS_W IReadStream
Copy link
Copy Markdown
Member Author

@dkurt dkurt Dec 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@opencv-alalek, @asmorkalov , need your opinion on naming as we ready to move it to the public API. There are VideoCapture, IStreamSource , VideoReader, VideoWriter. So does it make sense to keep the order and name it IStreamReader? Moreover, it matches PyTorch's naming: https://pytorch.org/audio/main/generated/torchaudio.io.StreamReader.html#streamreader

IReadStream -> IStreamReader
ReadStreamPluginProvider -> PluginStreamReader
PythonReadStream -> PythonStreamReader
BufferBackend -> StreamBufferedBackend
@dkurt dkurt changed the title Open VideoCapture from std::streambuf Open VideoCapture from data stream Dec 24, 2024
@opencv-alalek
Copy link
Copy Markdown
Contributor

BTW, there is leftover with Python typing generator (map to io.BufferedIOBase or even io.BufferedReader)

@dkurt dkurt force-pushed the videocapture_from_buffer branch from 2a02297 to cfed93c Compare December 25, 2024 07:59
@opencv-alalek
Copy link
Copy Markdown
Contributor

There is problem with iOS/Swift bindings:

<module-includes>:1:9: note: in file included from <module-includes>:1:
#import "Headers/opencv2.h"
        ^
/Users/opencv-cn/GHA-OCV-4/_work/opencv/opencv/ios/build/build-armv7-iphoneos/lib/Release/opencv2.framework/Headers/opencv2.h:151:9: note: in file included from /Users/opencv-cn/GHA-OCV-4/_work/opencv/opencv/ios/build/build-armv7-iphoneos/lib/Release/opencv2.framework/Headers/opencv2.h:151:
#import <opencv2/VideoCapture.h>
        ^
/Users/opencv-cn/GHA-OCV-4/_work/opencv/opencv/ios/build/build-armv7-iphoneos/lib/Release/opencv2.framework/Headers/VideoCapture.h:288:1: error: duplicate declaration of method 'open:apiPreference:params:'
- (BOOL)open:(IStreamReader*)source apiPreference:(int)apiPreference params:(IntVector*)params NS_SWIFT_NAME(open(source:apiPreference:params:));
^
/Users/opencv-cn/GHA-OCV-4/_work/opencv/opencv/ios/build/build-armv7-iphoneos/lib/Release/opencv2.framework/Headers/VideoCapture.h:224:1: note: previous declaration is here
- (BOOL)open:(NSString*)filename apiPreference:(int)apiPreference params:(IntVector*)params NS_SWIFT_NAME(open(filename:apiPreference:params:));
^
<unknown>:0: error: could not build Objective-C module 'opencv2'

Error message is not very clear to me

@opencv-alalek
Copy link
Copy Markdown
Contributor

Looks like fix works: https://github.com/opencv/opencv/actions/runs/12491953263/job/34858615536?pr=25584

@dkurt Feel free to push your changes.

@dkurt
Copy link
Copy Markdown
Member Author

dkurt commented Dec 25, 2024

@opencv-alalek no pending changes left

/** @brief Sets the stream position
*
* @param offset Seek offset
* @param origin SEEK_SET / SEEK_END / SEEK_CUR
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be better to completely avoid C/C++ constants in public interface and introduce our own?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FFmpeg (basically) and Python use them too (with same values).
IMHO, it is not necessary to introduce extra conversions to/from own values.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, we can add such enum but potential user will still cast to integer or introduce long if/else/switch

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My concern was that user would be required to include <stdio.h>/<cstdio> in order to use this seemingly unrelated class. Though perhaps it's fine.

@asmorkalov asmorkalov merged commit e9982e8 into opencv:4.x Dec 26, 2024
@asmorkalov asmorkalov mentioned this pull request Jan 15, 2025
@dkurt dkurt deleted the videocapture_from_buffer branch January 16, 2025 18:12
shyama7004 pushed a commit to shyama7004/opencv that referenced this pull request Jan 20, 2025
Open VideoCapture from data stream opencv#25584

### Pull Request Readiness Checklist

Add VideoCapture option to read a raw binary video data from `std::streambuf`.

There are multiple motivations:
1. Avoid disk file creation in case of video already in memory (received by network or from database).
2. Streaming mode. Frames decoding starts during sequential file transfer by chunks.

Suppoted backends:
* FFmpeg
* MSMF (no streaming mode)

Supporter interfaces:
* C++ (std::streambuf)
* Python (io.BufferedIOBase)

resolves opencv#24400

- [x] test h264
- [x]  test IP camera like approach with no metadata but key frame only?
- [x] C API plugin

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
NanQin555 pushed a commit to NanQin555/opencv that referenced this pull request Feb 24, 2025
Open VideoCapture from data stream opencv#25584

### Pull Request Readiness Checklist

Add VideoCapture option to read a raw binary video data from `std::streambuf`.

There are multiple motivations:
1. Avoid disk file creation in case of video already in memory (received by network or from database).
2. Streaming mode. Frames decoding starts during sequential file transfer by chunks.

Suppoted backends:
* FFmpeg
* MSMF (no streaming mode)

Supporter interfaces:
* C++ (std::streambuf)
* Python (io.BufferedIOBase)

resolves opencv#24400

- [x] test h264
- [x]  test IP camera like approach with no metadata but key frame only?
- [x] C API plugin

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

VideoCapture add support for byte buffer

6 participants