Opencv 如何在Android中打开cv::VideoWriter

Opencv 如何在Android中打开cv::VideoWriter,opencv,android-ndk,java-native-interface,video-capture,Opencv,Android Ndk,Java Native Interface,Video Capture,我使用JNI在Android中使用OpenCV 2.4.8 我打开摄像机,想把它录下来。我有一个cv::Mat中的图像,它正确地显示在屏幕上 但是,当我试图打开VideoCapture时,它总是返回false // Camera resolution is 640x480 and its fine. _camera_resolution = calc_optimal_camera_resolution(u.name, 640, 480); //

我使用JNI在Android中使用OpenCV 2.4.8

我打开摄像机,想把它录下来。我有一个cv::Mat中的图像,它正确地显示在屏幕上

但是,当我试图打开VideoCapture时,它总是返回false

       // Camera resolution is 640x480 and its fine.
       _camera_resolution = calc_optimal_camera_resolution(u.name, 640, 480);  

        // Store in sdcard, I have permission in AndroidManifest.xml
        const char * videoName = "/sdcard/videoTest.avi"; 

             // Segmentation fault 11! this method doesnt work in Android?  so commented
            //const int ex = static_cast<int>(_reader.get(CV_CAP_PROP_FOURCC)); 

            // Segmentation fault 11! too!!! so commented
            //const double fps = _reader.get(CV_CAP_PROP_FPS);      

            // Try to open
            _isRecording = _writer.open(videoName, -1, 30, _camera_resolution, true); 
            // Return FALSE always
            if(!_writer.isOpened())
            {
                LOGE("rec - Error opening video writer");
            }
            else
            {
                LOGD("rec - Video writer opened in startRecording");
            }
//摄像机分辨率为640x480,很好。
_相机分辨率=计算最佳相机分辨率(u.name,640480);
//存储在SD卡中,我在AndroidManifest.xml中拥有权限
const char*videoName=“/sdcard/videoTest.avi”;
//分段错误11!这种方法在Android中不起作用?如此评论
//const int ex=static_cast(_reader.get(CV_CAP_PROP_FOURCC));
//分段错误11!也如此评论
//const double fps=\u reader.get(CV\u CAP\u PROP\u fps);
//试着打开
_isRecording=\u writer.open(videoName,-1,30,\u摄像机\u分辨率,true);
//始终返回FALSE
如果(!\u writer.isopend())
{
LOGE(“rec-打开视频写入程序时出错”);
}
其他的
{
LOGD(“rec-在startRecording中打开的视频编写器”);
}
我已尝试使用as FOURCC:

CV_FOURCC('M','J','p','G')和CV_FOURCC('M','p','4','V')//它不起作用

我尝试了不同的fps比率,15.0,30.0

相机分辨率似乎可以工作,因为当我打印值是正确的


为什么不能正确打开?

据我所知,OpenCV4adnroid不支持视频读写。 尝试使用编码器选项重建Opencv: (例如:带_FFMPEG=YES或带_VFW=YES)

或者尝试保存一个图像序列,然后从java代码中对该序列中的视频进行编码 我尝试了下一个建议()

public void imageToMP4(buffereImage bi){
//将RGB转换为YUV颜色空间的变换
RgbToYuv420变换=新的RgbToYuv420(0,0);
//将源图像保存在YUV颜色空间中的JCodec本机图片
Picture-toEncode=Picture.create(bi.getWidth()、bi.getHeight()、ColorSpace.YUV420);
//执行转换
transform.transform(AWTUtil.fromBuffereImage(bi),yuv);
//创建MP4多路复用器
MP4Muxer muxer=新的MP4Muxer(水槽,品牌.MP4);
//添加视频曲目
CompressedTrack outTrack=muxer.addTrackForCompressed(TrackType.VIDEO,25);
//创建H.264编码器
H264编码器=新的H264编码器(rc);
//分配一个将保存编码帧的缓冲区
ByteBuffer _out=ByteBuffer.allocate(ine.getWidth()*ine.getHeight()*6);
//为SP/PP分配存储,它们需要单独存储在MP4文件的特殊位置
List spsList=new ArrayList();
List ppsList=新建ArrayList();
//将图像编码到H.264帧中,结果存储在“\u out”缓冲区中
ByteBuffer结果=编码器.encodeFrame(_out,toEncode);
//基于上面的帧形成正确的MP4数据包
H264Utils.encodeMOVPacket(结果、spsList、PPList);
//将数据包添加到视频曲目
addFrame(新的MP4Package(结果,0,25,1,0,true,null,0,0));
//将保存的SP/PP推送到MP4中的特殊存储器
outTrack.addSampleEntry(H264Utils.createMOVSampleEntry(spsList,ppsList));
//写入MP4标题并完成录制
muxer.writeHeader();
}
您可以从项目网站或通过Maven下载JCodec库,为此,请将以下代码段添加到pom.xml中:

<dependency>
    <groupId>org.jcodec</groupId>
    <artifactId>jcodec</artifactId>
    <version>0.1.3</version>
</dependency>

org.jcodec
jcodec
0.1.3
安卓: Android用户可以使用如下方式将Android位图对象转换为JCodec本机格式:

public static Picture fromBitmap(Bitmap src) {
    Picture dst = Picture.create((int)src.getWidth(), (int)src.getHeight(), RGB);
    fromBitmap(src, dst);
    return dst;
}

public static void fromBitmap(Bitmap src, Picture dst) {
    int[] dstData = dst.getPlaneData(0);
    int[] packed = new int[src.getWidth() * src.getHeight()];

    src.getPixels(packed, 0, src.getWidth(), 0, 0, src.getWidth(), src.getHeight());

    for (int i = 0, srcOff = 0, dstOff = 0; i < src.getHeight(); i++) {
        for (int j = 0; j < src.getWidth(); j++, srcOff++, dstOff += 3) {
            int rgb = packed[srcOff];
            dstData[dstOff]     = (rgb >> 16) & 0xff;
            dstData[dstOff + 1] = (rgb >> 8) & 0xff;
            dstData[dstOff + 2] = rgb & 0xff;
        }
    }
}
位图中的公共静态图片(位图src){
Picture dst=Picture.create((int)src.getWidth(),(int)src.getHeight(),RGB);
fromBitmap(src、dst);
返回dst;
}
位图中的公共静态无效(位图src、图片dst){
int[]dstData=dst.getPlaneData(0);
int[]packed=new int[src.getWidth()*src.getHeight()];
src.getPixels(压缩,0,src.getWidth(),0,0,src.getWidth(),src.getHeight());
for(inti=0,srcOff=0,dstOff=0;i>16)和0xff;
dstData[dstOff+1]=(rgb>>8)&0xff;
dstData[dstOff+2]=rgb&0xff;
}
}
}

('M'、'J'、'p'、'G')是android在使用.avi ext时唯一支持的。最重要的是包含stdio.h,否则你将无法打开VideoWriter视频

你有写的权限吗?正如我在帖子中所说,我的AndroidManifest有写的权限:可能SD卡位置错误,在我的应用程序中,我使用了类似于/mnt/sdcard/filename的东西。我可以用imwrite(“/sdcard/image.jpg”,mat)拍摄图像;顺便说一句,由于缺少ffmpeg后端,videowriter无法在android上工作。我正在使用本机版本。要使用Java制作视频,我必须共享抛出JNI的数据,这并不容易。顺便说一下,在Java中,可以使用Media Codec()>=Android 4.3来录制视频和音频。
public static Picture fromBitmap(Bitmap src) {
    Picture dst = Picture.create((int)src.getWidth(), (int)src.getHeight(), RGB);
    fromBitmap(src, dst);
    return dst;
}

public static void fromBitmap(Bitmap src, Picture dst) {
    int[] dstData = dst.getPlaneData(0);
    int[] packed = new int[src.getWidth() * src.getHeight()];

    src.getPixels(packed, 0, src.getWidth(), 0, 0, src.getWidth(), src.getHeight());

    for (int i = 0, srcOff = 0, dstOff = 0; i < src.getHeight(); i++) {
        for (int j = 0; j < src.getWidth(); j++, srcOff++, dstOff += 3) {
            int rgb = packed[srcOff];
            dstData[dstOff]     = (rgb >> 16) & 0xff;
            dstData[dstOff + 1] = (rgb >> 8) & 0xff;
            dstData[dstOff + 2] = rgb & 0xff;
        }
    }
}