简体   繁体   English

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

[英]how to use software codec in android using mediacodec

In my i want encode yuv data into h264 using mediacodec software codec. 我希望使用mediacodec软件编解码器将yuv数据编码为h264。

I use Google software encoder OMX.google.h264.encoder 我使用谷歌软件编码器OMX.google.h264.encoder

when i use hardware encoder[OMX.qcom.video.encoder.avc] that time it work but when i use software encoder[OMX.google.h264.encoder] it not encode file.it will give error [see in log]. 当我使用硬件编码器[OMX.qcom.video.encoder.avc]那时它工作,但当我使用软件编码器[OMX.google.h264.encoder]它不编码file.it将给出错误[见日志]。

what is problem i couldn't identify. 什么是我无法识别的问题。

Source : 资源 :

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
    }

But i getting this error. 但是我得到了这个错误。

Log : 记录:

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)

The SW encoder OMX.google.h264.encoder is very limited at the moment (edit: On Android 5.0), close to being unusable. SW编码器OMX.google.h264.encoder目前非常有限(编辑:在Android 5.0上),接近无法使用。

This encoder doesn't allow using resolutions that aren't a multiple of 16. In your case, 1920x1080, the height 1080 isn't evenly dividable by 16, and thus isn't acceptable for this encoder. 此编码器不允许使用不是16的倍数的分辨率。在您的情况下,1920x1080,高度1080不能均匀地分割为16,因此对于此编码器是不可接受的。 (See https://android-review.googlesource.com/38904 for an attempt at fixing this.) (请参阅https://android-review.googlesource.com/38904以尝试解决此问题。)

If you'd change it into 1088, the multiple-of-16 wouldn't be an issue, but the encoder also won't allow you to use it with any resolution above 352x288 (see eg https://android-review.googlesource.com/82133 ). 如果您将其更改为1088,则16的倍数不会成为问题,但编码器也不允许您使用任何高于352x288的分辨率(请参阅https:// android-review。 googlesource.com/82133 )。

Finally, on older Android versions (prior to 5.0), it also did output in a slightly different format (missing startcodes, see https://android-review.googlesource.com/42321 ), which meant that you would have to manually add startcodes at the start of each output packet to be able to use them in certain places (the MediaMuxer might have handled it as it was, though, mostly by chance). 最后,在较旧的Android版本(5.0之前)上,它也以稍微不同的格式输出(缺少启动码,请参阅https://android-review.googlesource.com/42321 ),这意味着您必须手动添加每个输出数据包开始时的启动码能够在某些地方使用它们( MediaMuxer可能已经按MediaMuxer处理它,但主要是偶然的)。

In the current AOSP master (that is, maybe in the next major release, unless that already is being finalized and this change hasn't been included there), the encoder has been replaced with a more capable one, but for existing releases, there's not much you can do other than bundling a better SW encoder within your app. 在当前的AOSP主机中(也就是说,可能在下一个主要版本中,除非已经完成并且此类更改尚未包含在内),编码器已被更强大的编码器取代,但对于现有版本,则有除了在您的应用程序中捆绑更好的SW编码器之外,您无能为力。

Edit: The Android M preview that was released today does include the new SW encoder, which should work fine for this usecase. 编辑:今天发布的Android M预览确实包含新的SW编码器,它应该适用于此用例。

Edit2: The new encoder was included in the Android 6.0 release (M), so since then, it should be usable. Edit2:新的编码器包含在Android 6.0版本(M)中,所以从那时起,它应该可用。

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

相关问题 MediaCodec如何在Android框架内找到编解码器? - How MediaCodec finds the codec inside the framework in Android? 如何在android中的MediaCodec上下文中使用ByteBuffer - How to use ByteBuffer in the MediaCodec context in android Android,将Mediacodec与libstreaming一起使用 - Android, use Mediacodec with libstreaming Android支持的编解码器意味着软件编解码器? - Android supported codec means software codec? 如何知道 Android 解码器 MediaCodec.createDecoderByType(type) 是硬件解码器还是软件解码器? - How to know Android decoder MediaCodec.createDecoderByType(type) is Hardware or software decoder? 如何在 MediaCodec 中为 h264 创建编解码器特定数据 ( csd )? - how to create Codec specific Data ( csd ) for h264 in MediaCodec? 使用MediaCodec和Surface进行Android编码 - Android encoding using MediaCodec and a Surface 如何使用 MediaCodec Android 压缩 mp4 视频? - How to compress mp4 video using MediaCodec Android? 是否可以检测Android编解码器是硬件还是软件? - Is it possible to detect if Android codec is hardware or software? Android:如何使用Mediacodec将两个重叠的视频保存为一个? - Android: How to save two overlapped videos as one using mediacodec?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM