android jni层 opencv读写视频,基于VideoCapture和VideoWriter

开始用正常c++的opencv代码,包括python代码,也都是直接用VideoCapture,在open后面加videofile就可以了

	// read video
    cv::VideoCapture capture;
    capture.open("/storage/emulated/0/DCIM/test.mp4");

但是在android jni层无论读写视频,capture.open那里都会报错

E/cv::error(): OpenCV(4.6.0) Error: Requested object was not found (could not open directory: /data/app/~~sbu7r1TB_QJQDnKVkr9ABQ==/com.tencent.yolov5ncnn-5hoZtN5FqSkRrIkcIlVUuQ==/base.apk!/lib/arm64-v8a) in glob_rec, file /build/master_pack-android/opencv/modules/core/src/glob.cpp, line 279
A/libc: Fatal signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x797302f480 in tid 19587 (cent.yolov5ncnn), pid 19587 (cent.yolov5ncnn)

下面是VideoWriter写入的代码,也是报同样的错

cv::VideoWriter writer;
writer.open("/sdcard/DCIM/test_opencv_write.avi", codec, fps, size, true);

解决方案:
后来查了opencv的文档,发现open后面还有apiPreference,不同的平台使用不用的apiPreference,附1有详细的对应

读取时在选择了cv::CAP_ANDROID就可以正常读取视频了

// read video
cv::VideoCapture capture;
capture.open("/sdcard/DCIM/test.mp4", cv::CAP_ANDROID);

要注意的是,写的时候,也需要apiPreference,但是用cv::CAP_ANDROID也会报错,于是尝试另一个cv::CAP_OPENCV_MJPEG,跟fourcc对应起来,就可以正常跑了

int fps = 25;
int codec = cv::VideoWriter::fourcc('M', 'J', 'P', 'G');
cv::VideoWriter writer;
writer.open("/sdcard/DCIM/test_opencv_write.avi",cv::CAP_OPENCV_MJPEG, codec, fps, size, true);

这个bug的解决真是让我找了好几天,最后发现还是要认真看官方文档,多尝试就能有结果

附1:(为apiPreference 接口的设备ID对应)

> enum VideoCaptureAPIs {
>        CAP_ANY          = 0,            //!< Auto detect == 0
>        CAP_VFW          = 200,          //!< Video For Windows (platform native)
>        CAP_V4L          = 200,          //!< V4L/V4L2 capturing support via libv4l
>        CAP_V4L2         = CAP_V4L,      //!< Same as CAP_V4L
>        CAP_FIREWIRE     = 300,          //!< IEEE 1394 drivers
>        CAP_FIREWARE     = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE
>        CAP_IEEE1394     = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE
>        CAP_DC1394       = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE
>        CAP_CMU1394      = CAP_FIREWIRE, //!< Same as CAP_FIREWIRE
>        CAP_QT           = 500,          //!< QuickTime
>        CAP_UNICAP       = 600,          //!< Unicap drivers
>        CAP_DSHOW        = 700,          //!< DirectShow (via videoInput)
>        CAP_PVAPI        = 800,          //!< PvAPI, Prosilica GigE SDK
>        CAP_OPENNI       = 900,          //!< OpenNI (for Kinect)
>        CAP_OPENNI_ASUS  = 910,          //!< OpenNI (for Asus Xtion)
>        CAP_ANDROID      = 1000,         //!< Android - not used
>        CAP_XIAPI        = 1100,         //!< XIMEA Camera API
>        CAP_AVFOUNDATION = 1200,         //!< AVFoundation framework for iOS (OS X Lion will have the same API)
>        CAP_GIGANETIX    = 1300,         //!< Smartek Giganetix GigEVisionSDK
>        CAP_MSMF         = 1400,         //!< Microsoft Media Foundation (via videoInput)
>        CAP_WINRT        = 1410,         //!< Microsoft Windows Runtime using Media Foundation
>        CAP_INTELPERC    = 1500,         //!< Intel Perceptual Computing SDK
>        CAP_OPENNI2      = 1600,         //!< OpenNI2 (for Kinect)
>        CAP_OPENNI2_ASUS = 1610,         //!< OpenNI2 (for Asus Xtion and Occipital Structure sensors)
>        CAP_GPHOTO2      = 1700,         //!< gPhoto2 connection
>        CAP_GSTREAMER    = 1800,         //!< GStreamer
>        CAP_FFMPEG       = 1900,         //!< Open and record video file or stream using the FFMPEG library
>        CAP_IMAGES       = 2000,         //!< OpenCV Image Sequence (e.g. img_%02d.jpg)
>        CAP_ARAVIS       = 2100,         //!< Aravis SDK
>        CAP_OPENCV_MJPEG = 2200,         //!< Built-in OpenCV MotionJPEG codec
>        CAP_INTEL_MFX    = 2300,         //!< Intel MediaSDK
>        CAP_XINE         = 2400,         //!< XINE engine (Linux)
>      };

你可能感兴趣的:(android,opencv,c++)