Java 使用Mediacodec解码并使用OpenCV
我正在使用OpenCV开发android应用程序 我有mp4视频文件,我需要从中读取300帧1920x1080,并对它们进行一些图像处理操作 经过大量的搜索,我最后只找到了一些例子 我的问题是,我需要做一件简单的事情,我只想读取帧并将其保存在设备内存中,或者只是将其转换为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
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();
提取器。释放();
}
在本例中,我读取了帧并将其显示为曲面
要将其保存为位图/矩阵或保存到设备中,我需要更改什么
谢谢我看到您的代码有两条路径:
无论哪种方式,你都需要时间、耐心和精力,因为这都离不开奋斗 你看到了吗?是的,但我不明白从这个例子中我如何才能得到我想要的。我想知道,如果从上面的例子,我可以得到的框架不是表面,或者如果我需要采取另一个例子?感谢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();
}