简体   繁体   English

将H264帧解码为字节数组

[英]Decode H264 frames to byte array

I have a stream of H264 video that I need to show in my Android app. 我有一些H264视频流,需要在我的Android应用中显示。 If I consigure MediaCodec with a surface, then the video gets decoded to my app no problem, and I can see it in this surface. 如果我将MediaCodec与表面配合使用,则视频可以毫无问题地解码到我的应用程序,并且可以在此表面看到它。

But I also need to obtain a Bitmap of the video in certain moments (ie to store certain frames on the SD card). 但是我还需要在特定时刻获取视频的位图(即在SD卡上存储某些帧)。 Is it possible to configure the MediaCodec library to return an array of bytes instead of working directly towards a surface?? 是否可以将MediaCodec库配置为返回字节数组,而不是直接向表面工作?

Another option would be to obtain the bitmap directly from the surface, but I couldn't find this option on the SDK either. 另一个选择是直接从表面获取位图,但是我在SDK上也找不到该选项。

You can use MediaMetadataRetriever : 您可以使用MediaMetadataRetriever

MediaMetadataRetriever mediaMetadataRetriever=new MediaMetadataRetriever(); //should be stored as an instance variable
mediaMetadataRetriever.setDataSource(mVideo.getVideoUrl(Video.SD));
int time = videoView.getCurrentPosition()* 1000; //micro-to-milliseconds
Bitmap bmFrame = mediaMetadataRetriever.getFrameAtTime(time);

Edit: 编辑:

To retrieve raw byte data without the involvement of UI, you can advance time frame by frame, get the Bitmap and convert it to byte array. 要在不涉及UI的情况下检索原始字节数据,可以逐帧提前时间,获取位图并将其转换为字节数组。

To be more efficient, consider forking FFmpegMediaMetadataRetriever , whose FFmpegMediaMetadataRetriever.java has method private native byte [] _getFrameAtTime(long timeUs, int option); 为了提高效率,请考虑分叉FFmpegMediaMetadataRetriever ,其FFmpegMediaMetadataRetriever.java具有方法private native byte [] _getFrameAtTime(long timeUs, int option); skipping the whole Bitmap conversion process. 跳过整个位图转换过程。

Try this: 尝试这个:

public class GameView extends SurfaceView {
   private Bitmap bmp;
   private SurfaceHolder holder;

   public GameView(Context context) {
         super(context);
         holder = getHolder();
         holder.addCallback(new SurfaceHolder.Callback() {

                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {
                }

                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                       Canvas c = holder.lockCanvas(null);
                       onDraw(c);
                       holder.unlockCanvasAndPost(c);
                }

                @Override
                public void surfaceChanged(SurfaceHolder holder, int format,
                              int width, int height) {
                }
         });
         bmp = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
   }

   @Override
   protected void onDraw(Canvas canvas) {
         canvas.drawColor(Color.BLACK);
         canvas.drawBitmap(bmp, 10, 10, null);
   }

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM