如何使用mediacodec在android中使用软件编解码器

时间:2015-05-28 11:53:22

标签: android mediacodec

我希望使用mediacodec软件编解码器将yuv数据编码为h264。

我使用Google软件编码器 OMX.google.h264.encoder

当我使用硬件编码器[OMX.qcom.video.encoder.avc]那时它工作但当我使用软件编码器[OMX.google.h264.encoder]它不编码file.it将给出错误[见日志]。

我无法识别的问题是什么。

来源:

mediaCodec = MediaCodec.createByCodecName("OMX.google.h264.encoder");
    //mediaCodec = MediaCodec.createByCodecName(codecInfo.getName());
    Log.i(TAG,"codec name : "+ mediaCodec.getName());
    int mBitrate  = (int) ((MainActivity.mHeight * MainActivity.mWidth * MainActivity.frameRate)*2*0.07);
    MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc",MainActivity.mWidth,MainActivity.mHeight);
    mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE,mBitrate);
    mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, MainActivity.frameRate);
    //   mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 320*240);
    mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,colorFormat);
    //mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,MediaCodecInfo.CodecProfileLevel.AVCLevel12);
    mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,1);
    try{
        mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        mediaCodec.start();
        Log.i(TAG,"H264 Encoder init success");


    }catch(IllegalArgumentException e)
    {
        e.printStackTrace();
    }catch (IllegalStateException e) {
        e.printStackTrace();
    }catch (Exception e) { 
        e.printStackTrace();// TODO: handle exception
    }

但是我收到了这个错误。

记录:

I/H264Encoder(7772): outputStream initialized
I/OMXClient(7772): Using client-side OMX mux.
I/H264Encoder(7772): found colorFormat: 21
I/OMXClient(7772): Using client-side OMX mux.
E/OMXMaster(7772): A component of name 'OMX.qcom.audio.decoder.aac' already exists, ignoring this one.
I/SoftAVCEncoder(7772): Construct SoftAVCEncoder
I/H264Encoder(7772): codec name : OMX.google.h264.encoder
E/SoftAVCEncoder(7772): internalSetParameter: StoreMetadataInBuffersParams.nPortIndex not zero!
E/OMXNodeInstance(7772): OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x80001001
E/ACodec(7772): [OMX.google.h264.encoder] storeMetaDataInBuffers (output) failed w/ err -2147483648
I/ACodec(7772): setupVideoEncoder succeeded
I/H264Encoder(7772): H264 Encoder init success
E/SoftAVCEncoder(7772): Video frame size 1920x1080 must be a multiple of 16
E/SoftAVCEncoder(7772): Failed to initialized encoder params
E/ACodec(7772): [OMX.google.h264.encoder] ERROR(0x80001001)
E/MediaCodec(7772): Codec reported an error. (omx error 0x80001001, internalError -2147483648)
   W/System.err(7772): java.lang.IllegalStateException
   W/System.err(7772):  at android.media.MediaCodec.getBuffers(Native Method)
    W/System.err(7772):     at android.media.MediaCodec.getInputBuffers(MediaCodec.java:542)
  W/System.err(7772):   at com.ei.encodertest.H264Encoder.offerEncoder(H264Encoder.java:170)
  W/System.err(7772):   at com.ei.encodertest.MainActivity$ReadRawFileTask.doInBackground(MainActivity.java:113)
 W/System.err(7772):    at com.ei.encodertest.MainActivity$ReadRawFileTask.doInBackground(MainActivity.java:1)
 W/System.err(7772):    at android.os.AsyncTask$2.call(AsyncTask.java:288)
 W/System.err(7772):    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
 W/System.err(7772):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
 W/System.err(7772):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
   W/System.err(7772):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
  W/System.err(7772):   at java.lang.Thread.run(Thread.java:841)

1 个答案:

答案 0 :(得分:11)

SW编码器OMX.google.h264.encoder目前非常有限(编辑:在Android 5.0上),接近无法使用。

此编码器不允许使用不是16的倍数的分辨率。在1920x1080的情况下,高度1080不能均匀分割为16,因此对于此编码器是不可接受的。 (请参阅https://android-review.googlesource.com/38904以尝试解决此问题。)

如果您将其更改为1088,则16的倍数不会成为问题,但编码器也不允许您使用任何高于352x288的分辨率(请参阅https://android-review.googlesource.com/82133 )。

最后,在较旧的Android版本(5.0之前)上,它也以稍微不同的格式输出(缺少启动码,请参阅https://android-review.googlesource.com/42321),这意味着您必须在开始时手动添加启动码每个输出数据包都可以在某些地方使用它们(MediaMuxer可能已经按原样处理了它,但主要是偶然的。)

在当前的AOSP主机中(也就是说,可能在下一个主要版本中,除非已经完成并且此更改尚未包含在那里),编码器已被替换为功能更强的编码器,但对于现有的发布,除了在您的应用程序中捆绑更好的SW编码器之外,您无能为力。

编辑:今天发布的Android M预览确实包含了新的SW编码器,该编码器应该适用于此用例。

Edit2:新编码器包含在Android 6.0版本(M)中,所以从那时起,它应该可用。