Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/231.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Mediacodec解码并使用OpenCV_Java_Android_Opencv_Android Mediacodec - Fatal编程技术网

Java 使用Mediacodec解码并使用OpenCV

Java 使用Mediacodec解码并使用OpenCV,java,android,opencv,android-mediacodec,Java,Android,Opencv,Android Mediacodec,我正在使用OpenCV开发android应用程序 我有mp4视频文件,我需要从中读取300帧1920x1080,并对它们进行一些图像处理操作 经过大量的搜索,我最后只找到了一些例子 我的问题是,我需要做一件简单的事情,我只想读取帧并将其保存在设备内存中,或者只是将其转换为OpenCV矩阵 这是我的尝试(最后解释): public void run(){ 提取器=新的媒体提取器(); 提取器.setDataSource(示例); for(int i=0;i=0){ ByteBuffer buffe

我正在使用OpenCV开发android应用程序

我有mp4视频文件,我需要从中读取300帧1920x1080,并对它们进行一些图像处理操作

经过大量的搜索,我最后只找到了一些例子

我的问题是,我需要做一件简单的事情,我只想读取帧并将其保存在设备内存中,或者只是将其转换为OpenCV矩阵

这是我的尝试(最后解释):

public void run(){
提取器=新的媒体提取器();
提取器.setDataSource(示例);
for(int i=0;i=0){
ByteBuffer buffer=inputBuffers[inIndex];
int sampleSize=extractor.readSampleData(缓冲区,0);
如果(样本大小<0){
Log.d(“DecodeActivity”,“InputBuffer BUFFER\u FLAG\u END\u OF_STREAM”);
解码器.queueInputBuffer(inIndex,0,0,0,MediaCodec.BUFFER\u标志\u结束\u流);
isEOS=真;
}否则{
decoder.queueInputBuffer(inIndex,0,sampleSize,提取器.getSampleTime(),0);
提取器;
}
}
}
int OUTIDEX=解码器.dequeueOutputBuffer(信息,10000);
交换机(OUTIDEX){
案例MediaCodec.INFO\u输出\u缓冲区\u已更改:
Log.d(“解码活动”、“信息输出缓冲区更改”);
outputBuffers=解码器。getOutputBuffers();
打破
案例MediaCodec.INFO\u输出\u格式\u已更改:
Log.d(“DecodeActivity”,“新格式”+decoder.getOutputFormat());
打破
case MediaCodec.INFO\u请稍后再试:
Log.d(“DecodeActivity”,“dequeueOutputBuffer超时!”);
打破
违约:
ByteBuffer缓冲区=输出缓冲区[outIndex];
Log.v(“DecodeActivity”,“我们不能使用此缓冲区,但由于API限制而呈现它,”+缓冲区);
byte[]b=新字节[buffer.remaining()];
//我们使用一个非常简单的时钟来保持视频FPS或视频
//播放速度太快
而(info.presentationTimeUs/1000>System.currentTimeMillis()-startMs){
试一试{
睡眠(10);
}捕捉(中断异常e){
e、 printStackTrace();
打破
}
}
解码器.releaseOutputBuffer(outIndex,true);
打破
}
//所有解码帧都已渲染,现在可以停止播放
if((流的info.flags和MediaCodec.BUFFER\u FLAG\u END)!=0){
Log.d(“解码活动”,“输出缓冲缓冲区缓冲区标志\u结束\u流”);
打破
}
}
解码器。停止();
decoder.release();
提取器。释放();
}
在本例中,我读取了帧并将其显示为曲面

要将其保存为位图/矩阵或保存到设备中,我需要更改什么


谢谢

我看到您的代码有两条路径:

  • 对于Android 4.3及以上版本,您可以使用fadden建议的示例。MediaCodec解码器应该为configure方法使用一个曲面,并将布尔渲染设置为“true”时释放OutputBuffer,以便对曲面进行渲染。然后,可以在渲染到曲面时使用着色器执行操作,MediaCodec编码器将使用该曲面将其编码回视频。此解决方案在大多数设备上运行速度很快,但它是新的,仍然出现在设备硬件中
  • 如果您可以接受一个较慢的解决方案,OpenCV有一个,包含代码示例和所有内容,甚至可以使用ffmpeg编码回h264。对于解码,您仍然可以使用MediaCodec(如果将结果渲染到曲面,则需要使用glReadPixels(速度较慢)将数据返回到cpu)。这也适用于以前版本的Android

  • 无论哪种方式,你都需要时间、耐心和精力,因为这都离不开奋斗

    你看到了吗?是的,但我不明白从这个例子中我如何才能得到我想要的。我想知道,如果从上面的例子,我可以得到的框架不是表面,或者如果我需要采取另一个例子?感谢ExtractMpegFramesTest将前10帧从曲面转换为位图,然后将每个帧保存为PNG格式的磁盘。您是如何创建代码中使用的曲面的?感谢您的指导,我将对此进行检查。在这一行中,我配置了Surface解码器;我试图从我的主要活动调用这个类,如下所示:尝试{ExtractMpegFramesTest etmf=new ExtractMpegFramesTest();etmf.testExtractMpegFrames();}catch(Throwable e){//TODO自动生成的catch块e.printStackTrace();}但是我
    public void run() {
    
            extractor = new MediaExtractor();
            extractor.setDataSource(SAMPLE);
    
            for (int i = 0; i < extractor.getTrackCount(); i++) {
                MediaFormat format = extractor.getTrackFormat(i);
                String mime = format.getString(MediaFormat.KEY_MIME);
                if (mime.startsWith("video/")) {
                    extractor.selectTrack(i);
                    decoder = MediaCodec.createDecoderByType(mime);
                    decoder.configure(format, surface, null, 0);
    
                    break;
                }
            }
    
            if (decoder == null) {
                Log.e("DecodeActivity", "Can't find video info!");
                return;
            }
    
            decoder.start();
    
            ByteBuffer[] inputBuffers = decoder.getInputBuffers();
            ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
    
            BufferInfo info = new BufferInfo();
    
            boolean isEOS = false;
            long startMs = System.currentTimeMillis();
    
            while (!Thread.interrupted()) {
                if (!isEOS) {
                    int inIndex = decoder.dequeueInputBuffer(10000);
                    if (inIndex >= 0) {
                        ByteBuffer buffer = inputBuffers[inIndex];
                        int sampleSize = extractor.readSampleData(buffer, 0);
                        if (sampleSize < 0) {
                            Log.d("DecodeActivity", "InputBuffer BUFFER_FLAG_END_OF_STREAM");
                            decoder.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                            isEOS = true;
                        } else {
                            decoder.queueInputBuffer(inIndex, 0, sampleSize, extractor.getSampleTime(), 0);
                            extractor.advance();
                        }
    
                    }
                }
                int outIndex = decoder.dequeueOutputBuffer(info, 10000);
                switch (outIndex) {
                case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
                    Log.d("DecodeActivity", "INFO_OUTPUT_BUFFERS_CHANGED");
                    outputBuffers = decoder.getOutputBuffers();
                    break;
                case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
                    Log.d("DecodeActivity", "New format " + decoder.getOutputFormat());
                    break;
                case MediaCodec.INFO_TRY_AGAIN_LATER:
                    Log.d("DecodeActivity", "dequeueOutputBuffer timed out!");
                    break;
                default:
                    ByteBuffer buffer = outputBuffers[outIndex];
    
                    Log.v("DecodeActivity", "We can't use this buffer but render it due to the API limit, " + buffer);
                    byte[] b = new byte[buffer.remaining()];
    
                    // We use a very simple clock to keep the video FPS, or the video
                    // playback will be too fast
                    while (info.presentationTimeUs / 1000 > System.currentTimeMillis() - startMs) {
                        try {
                            sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            break;
                        }
                    }
                    decoder.releaseOutputBuffer(outIndex, true);
                    break;
                }
    
                // All decoded frames have been rendered, we can stop playing now
                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                    Log.d("DecodeActivity", "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
                    break;
                }
            }
    
            decoder.stop();
            decoder.release();
            extractor.release();
    
        }