大佬教程收集整理的这篇文章主要介绍了android – MediaCodec从视频中获取所有帧,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图将它渲染到曲面或没有任何东西(null),因为我注意到当渲染为null时,outBuffers将获取渲染帧的字节.
这是代码:
private static final String SAMPLE = Environment.getExternalStorageDirectory() + "/test_videos/sample2.mp4"; private PlayerThread mPlayer = null; @Override protected void onCreate(Bundle savedInstanceStatE) { super.onCreate(savedInstanceStatE); SurfaceView sv = new SurfaceView(this); sv.getHolder().addCallBACk(this); setContentView(sv); } protected void onDestroy() { super.onDestroy(); } @Override public void surfaceCreated(SurfaceHolder holder) { } @Override public void surfaceChanged(SurfaceHolder holder,int format,int width,int height) { if (mPlayer == null) { mPlayer = new PlayerThread(holder.getSurface()); mPlayer.start(); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { if (mPlayer != null) { mPlayer.interrupt(); } } private void writeFrameToSDCard(byte[] bytes,int i,int sampleSizE) { try { Bitmap bmp = BitmapFactory.decodeByteArray(bytes,sampleSizE); File file = new File(Environment.getExternalStorageDirectory() + "/test_videos/sample" + i + ".png"); if (file.exists()) file.delete(); file.createNewFile(); FiLeoutputStream out = new FiLeoutputStream(file.getAbsoluteFile()); bmp.compress(Bitmap.CompressFormat.PNG,90,out); out.close(); } catch (Exception E) { e.printStackTrace(); } } private class PlayerThread extends Thread { private MediaExtractor extractor; private MediaCodec decoder; private Surface surface; public PlayerThread(Surface surfacE) { this.surface = surface; } @Override public void run() { extractor = new MediaExtractor(); extractor.setDatasource(SAMPLE); int index = extractor.getTrackCount(); Log.d("MediaCodecTag","Track count: " + indeX); 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(); int i = 0; 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) { decoder.queueInputBuffer(inIndex,MediaCodec.bUFFER_FLAG_END_OF_STREAM); iSEOS = true; } else { decoder.queueInputBuffer(inIndex,sampleSize,extractor.getSampleTime(),0); extractor.advance(); } } } /* saves frame to sdcard */ int outIndex = decoder.dequeueOutputBuffer(info,10000); // outIndex most of the times null 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); // 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); try { byte[] dst = new byte[outputBuffers[outIndex].capacity()]; outputBuffers[outIndex].get(dst); writeFrameToSDCard(dst,i,dst.length); i++; } catch (Exception E) { Log.d("iDecodeActivity","Error while creaTing bitmap with: " + e.getmessage()); } 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(); } }
任何帮助都会很有帮助
如果你配置ByteBuffer解码,数据格式会有所不同,但据我所知,它永远不会是Bitmap理解的ARGB格式.您可以在方法checkFrame()中的CTS EncodeDecodeTest中的缓冲区到缓冲区测试中查看正在检查的两种YUV格式的示例.但请注意,它首先要做的是检查格式,如果无法识别则立即返回.
目前(Android 4.4),唯一可行的方法是解码为SurfaCETexture,使用GLES渲染,然后使用glReadPixels()提取RGB数据. bigflake上提供了示例代码 – 请参阅ExtractMpegFramesTest(需要API 16).
以上是大佬教程为你收集整理的android – MediaCodec从视频中获取所有帧全部内容,希望文章能够帮你解决android – MediaCodec从视频中获取所有帧所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。