Audio/Video Development

Recording MP4 with OpenCV VideoWriter on iOS and Setting Video Bitrate

Recording MP4 with OpenCV VideoWriter and setting video bitrate

Park

Park

Audio/Video Development

Written on

Share
Recording MP4 with OpenCV VideoWriter on iOS and Setting Video Bitrate

OpenCV version opencv-4.5.3

Wrapping the Video Bitrate Logic

Modify the OpenCV source file modules/videoio/include/opencv2/videoio.hpp
At line 197, add VIDEOWRITER_PROP_BITRATE = 9,

enum VideoWriterProperties {
  VIDEOWRITER_PROP_QUALITY = 1,    //!< Current quality (0..100%) of the encoded videostream. Can be adjusted dynamically in some codecs.
  VIDEOWRITER_PROP_FRAMEBYTES = 2, //!< (Read-only): Size of just encoded video frame. Note that the encoding order may be different from representation order.
  VIDEOWRITER_PROP_NSTRIPES = 3,   //!< Number of stripes for parallel encoding. -1 for auto detection.
  VIDEOWRITER_PROP_IS_COLOR = 4,   //!< If it is not zero, the encoder will expect and encode color frames, otherwise it
                                   //!< will work with grayscale frames.
  VIDEOWRITER_PROP_DEPTH = 5,      //!< Defaults to CV_8U.
  VIDEOWRITER_PROP_HW_ACCELERATION = 6, //!< (**open-only**) Hardware acceleration type (see #VideoAccelerationType). Setting supported only via `params` parameter in VideoWriter constructor / .open() method. Default value is backend-specific.
  VIDEOWRITER_PROP_HW_DEVICE       = 7, //!< (**open-only**) Hardware device index (select GPU if multiple available). Device enumeration is acceleration type specific.
  VIDEOWRITER_PROP_HW_ACCELERATION_USE_OPENCL= 8, //!< (**open-only**) If non-zero, create new OpenCL context and bind it to current thread. The OpenCL context created with Video Acceleration context attached it (if not attached yet) for optimized GPU data copy between cv::UMat and HW accelerated encoder.
  VIDEOWRITER_PROP_BITRATE = 9,
#ifndef CV_DOXYGEN
  CV__VIDEOWRITER_PROP_LATEST
#endif
};

Modify modules/videoio/src/cap_avfoundation.mm around line 228 to read the bitrate parameter:

cv::Ptr<cv::IVideoWriter> cv::create_AVFoundation_writer(const std::string& filename, int fourcc,
                                                         double fps, const cv::Size &frameSize,
                                                         const cv::VideoWriterParameters& params)
{
    CvSize sz = { frameSize.width, frameSize.height };
    const bool isColor = params.get(VIDEOWRITER_PROP_IS_COLOR, true);
    const int bitrate = params.get(VIDEOWRITER_PROP_BITRATE, 600000);
    CvVideoWriter_AVFoundation* wrt = new CvVideoWriter_AVFoundation(filename.c_str(), fourcc, fps, sz, bitrate, isColor);
    return cv::makePtr<cv::LegacyWriter>(wrt);
}

Around line 1202, modify the CvVideoWriter_AVFoundation constructor to add an int bitrate parameter:

CvVideoWriter_AVFoundation::CvVideoWriter_AVFoundation(const char* filename, int fourcc,
        double fps, CvSize frame_size,
        int bitrate, int is_color) {

Around line 1306, pass the bitrate to AVAssetWriterInput:

NSDictionary* videoCompressionSetting = [NSDictionary dictionaryWithObjectsAndKeys:
        [NSNumber numberWithInteger:bitrate], AVVideoAverageBitRateKey,
        nil]; // 设置 AVAssetWriterInput 编码码率

NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
        codec, AVVideoCodecKey,
        [NSNumber numberWithInt:movieSize.width], AVVideoWidthKey,
        [NSNumber numberWithInt:movieSize.height], AVVideoHeightKey,
        videoCompressionSetting, AVVideoCompressionPropertiesKey,
        nil];

 mMovieWriterInput = [[AVAssetWriterInput
        assetWriterInputWithMediaType:AVMediaTypeVideo
        outputSettings:videoSettings] retain];

All modifications are complete.

Building OpenCV for iOS

Run the following from the OpenCV source root:

python platforms/ios/build_framework.py ios --iphoneos_archs armv7,arm64 --iphonesimulator_archs i386,x86_64

Usage

Creating and Configuring cv::VideoWriter with Video Bitrate

cv::VideoWriter writer;
cv::Size size = cv::Size(480, 640);
  int myFourcc = cv::VideoWriter::fourcc('H', '2', '6', '4');
  double fps = 30;
  std::vector<int> vect;
  vect.push_back(cv::VIDEOWRITER_PROP_BITRATE);
  vect.push_back(450*1000); // 更改 video 码率
  // outputPath = @"document/video.mp4" 存储路径
  writer.open([outputPath UTF8String], cv::CAP_AVFOUNDATION, myFourcc, fps, size, vect);

You can then record MP4 files and control the output bitrate.

References:

  1. AVAssetWriter Video Data Encoding
  2. AVAssetWriter: High-Resolution Recording with Smaller Output Files
  3. Building OpenCV for iOS