Android 三星galaxy note 4中的MediaCodec编解码器例外

Android 三星galaxy note 4中的MediaCodec编解码器例外,android,android-mediacodec,Android,Android Mediacodec,我正在尝试使用录制屏幕,并提供了一些相关的代码片段: @Override void prepare() throws IOException { if (DEBUG) Log.i(TAG, "prepare: "); mSurface = prepare_surface_encoder(MIME_TYPE, fps, bitrate); mMediaCodec.start(); mIsRecording = true; new Thread(mScreen

我正在尝试使用录制屏幕,并提供了一些相关的代码片段:

@Override
void prepare() throws IOException {
    if (DEBUG) Log.i(TAG, "prepare: ");
    mSurface = prepare_surface_encoder(MIME_TYPE, fps, bitrate);
    mMediaCodec.start();
    mIsRecording = true;
    new Thread(mScreenCaptureTask, "ScreenCaptureThread").start();
    if (DEBUG) Log.i(TAG, "prepare finishing");
    if (mListener != null) {
        try {
            mListener.onPrepared(this);
        } catch (final Exception e) {
            Log.e(TAG, "prepare:", e);
        }
    }
}   
protected MediaFormat create_encoder_format(final String mime, final int frame_rate, final int bitrate) {
    if (DEBUG) Log.v(TAG, String.format("create_encoder_format:(%d,%d),mime=%s,frame_rate=%d,bitrate=%d", mWidth, mHeight, mime, frame_rate, bitrate));
    final MediaFormat format = MediaFormat.createVideoFormat(mime, mWidth, mHeight);
    format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);  // API >= 18
    format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate > 0 ? bitrate : calcBitRate(frame_rate)); //800000
    format.setInteger(MediaFormat.KEY_FRAME_RATE,30);
    format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);
    return format;
}

protected Surface prepare_surface_encoder(final String mime, final int frame_rate, final int bitrate)
    throws IOException, IllegalArgumentException {

    if (DEBUG) Log.v(TAG, String.format("prepare_surface_encoder:(%d,%d),mime=%s,frame_rate=%d,bitrate=%d", mWidth, mHeight, mime, frame_rate, bitrate));

    mTrackIndex = -1;
    mMuxerStarted = mIsEOS = false;

    final MediaCodecInfo videoCodecInfo = selectVideoCodec(mime);
    if (videoCodecInfo == null) {
        throw new IllegalArgumentException("Unable to find an appropriate codec for " + mime);
    }
    if (DEBUG) Log.i(TAG, "selected codec: " + videoCodecInfo.getName());

    final MediaFormat format = create_encoder_format(mime, frame_rate, bitrate);
    if (DEBUG) Log.i(TAG, "format: " + format);

    mMediaCodec = MediaCodec.createEncoderByType(mime);
    mMediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    // get Surface for encoder input
    // this method only can call between #configure and #start
    return mMediaCodec.createInputSurface();    // API >= 18
}
它适用于大多数设备,但不适用于运行安卓6.0.1的三星Galaxy note 4。在这里我得到以下错误

`Non-fatal Exception: android.media.MediaCodec$CodecException: Error 0xffffec77
   at android.media.MediaCodec.native_configure(MediaCodec.java)
   at android.media.MediaCodec.configure(MediaCodec.java:1778)
   at com.urcaddy.utilities.utils.media.MediaVideoEncoderBase.prepare_surface_encoder(MediaVideoEncoderBase.java:90)
   at com.urcaddy.utilities.utils.media.MediaScreenEncoder.prepare(MediaScreenEncoder.java:87)
   at com.urcaddy.utilities.utils.media.MediaMuxerWrapper.prepare(MediaMuxerWrapper.java:74)
   at com.urcaddy.services.backgroundservices.ScreenRecorderService.startScreenRecord(ScreenRecorderService.java:229)
   at com.urcaddy.services.backgroundservices.ScreenRecorderService.onStartCommand(ScreenRecorderService.java:139)
   at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4062)
   at android.app.ActivityThread.access$2400(ActivityThread.java:221)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1897)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:158)
   at android.app.ActivityThread.main(ActivityThread.java:7225)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)`

经过大量的脑力激荡,我们发现问题在于高度和宽度。下面是为我们工作的代码

protected MediaFormat create_encoder_format(final String mime, final int frame_rate, final int bitrate) {
if (DEBUG) Log.v(TAG, String.format("create_encoder_format:(%d,%d),mime=%s,frame_rate=%d,bitrate=%d", 720, 1280, mime, frame_rate, bitrate));
final MediaFormat format = MediaFormat.createVideoFormat(mime, 720, 1280);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);  // API >= 18
format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate > 0 ? bitrate : calcBitRate(frame_rate)); //800000
format.setInteger(MediaFormat.KEY_FRAME_RATE,30);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);
return format;
}

请同时发布LogCat输出。您可以使用三星在线测试实验室获得它:有一个解决方案。你可以试试:有一个解决办法。看一看:我在尝试配置avc编码时遇到了错误,错误代码完全相同。92%的受影响设备是三星设备:主要是galaxy j7和A系列。首先,我认为问题是1080p宽度,我把它改为640,但它没有解决任何问题。知道吗?知道!我们公司给这个问题起了个绰号叫“黑屏虫”。问题是我们没有适当地释放一些ExoPlayer,这导致我们的编码器不可用。发布ExoPlayer解决了这个问题,但如果不是这样,也要确保编写一个编解码器选择器。您应该查询设备上可用的编解码器,并选择一个在准备时不会失败的编解码器。一台设备上有多个编解码器,因此您可能会找到一个。如果什么都不起作用,我们就退回到涉及ffmpeg的替代编码路径。希望这有帮助。@WPMed在创建另一个之前,请确保发布
MediaCodec
,这是正确的。但是,当其他应用程序没有处理
MediaCodec
的发布时,也可能导致此问题。我对此提出了一个问题,请参见下面的链接。我将在developers.google上打开一个问题单,因为我无法发布另一个应用程序的
MediaCodec
实例。