开始用正常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)
> };