美文网首页ijkplayer秘籍
Android平台硬件编码总结一

Android平台硬件编码总结一

作者: deep_sadness | 来源:发表于2018-04-27 16:48 被阅读12次

    MediaCodec编码的套路

    状态

    来自官网的状态图


    codec_status.png

    创建

    • find Support Codec
      通过这种方式可以得到当前设备所有的MedaCodecInfo
    public static final String VIDEO_AVC = MIMETYPE_VIDEO_AVC; // H.264 Advanced Video Coding
        public static final String AUDIO_AAC = MIMETYPE_AUDIO_AAC; // H.264 Advanced Audio Coding
    
        //得到制定的MimeType的Codec
        public static Single<List<MediaCodecInfo>> getAdaptiveEncoderCodec(String mimeType) {
            return Observable
                    .fromArray(getMediaCodecInfos())
                    .filter(mediaCodecInfo -> {
                        if (mediaCodecInfo.isEncoder()) {
                            try {
                                MediaCodecInfo.CodecCapabilities capabilitiesForType = mediaCodecInfo.getCapabilitiesForType(mimeType);
                                return capabilitiesForType != null;
                            } catch (Exception e) {
                                e.printStackTrace();
                                return false;
                            }
                        }
                        return false;
                    })
                    .toList()
                    ;
        }
    
        private static MediaCodecInfo[] getMediaCodecInfos() {
            //获取当前可以支持的MediaCodec
            MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
            //得到所有CodecInfos
            return mediaCodecList.getCodecInfos();
        }
    
    • MediaFormat
      再通过我们自己的配置和选择的MediaCodecInfo进行创建MediaFormat
    MediaFormat toFormat() {
            //通过MimeType创建宽和高
            MediaFormat format = MediaFormat.createVideoFormat(mimeType, width, height);
            //设置ColorFormat .因为这里是mediaProjection来的数据,所以是 Color_FomatSurface
            //如果是使用camera,则这里是 COLOR_FormatYUV420SemiPlanar
            format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
    
            format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
            format.setInteger(MediaFormat.KEY_FRAME_RATE, framerate);
            format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, iframeInterval);
            if (codecProfileLevel != null && codecProfileLevel.profile != 0 && codecProfileLevel.level != 0) {
                format.setInteger(MediaFormat.KEY_PROFILE, codecProfileLevel.profile);
                format.setInteger("level", codecProfileLevel.level);
            }
            // maybe useful
            // format.setInteger(MediaFormat.KEY_REPEAT_PREVIOUS_FRAME_AFTER, 10_000_000);
            return format;
        }
    
    • 启动MediaCodec
    MediaFormat format = createMediaFormat();
    Log.d("Encoder", "Create media format: " + format);
    
    String mimeType = format.getString(MediaFormat.KEY_MIME);
    final MediaCodec encoder = createEncoder(mimeType);
    try {
        //这里是通过异步的方式创建
         encoder.setCallback(this.mCallback == null ? null : mCodecCallback);
        //调用configure方法,让Codec进入configured状态
         encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        //如果需要codec提供输入的surface,则在configured状态后,创建
         onEncoderConfigured(encoder);
        //开启encoder
         encoder.start();
     } catch (MediaCodec.CodecException e) {
         Log.e("Encoder", "Configure codec failure!\n  with format" + format, e);
         throw e;
    }
    

    Input

    • 实例1:从Camera中得到数据


      camera_input.png
    • 实例2:从MediaProjection创建的VirtualDisplay中得到数据


      virtualdisplay_input.png

    output

    从MediaCodec中得到编码好的数据。例如H264裸流数据进行处理。

    • 同步的方式


      sync_output.png
    • 异步的方式


      async_output.png

    相关文章

      网友评论

        本文标题:Android平台硬件编码总结一

        本文链接:https://www.haomeiwen.com/subject/pabblftx.html