【问题标题】:MediaCodec Crashes on call to start()MediaCodec 在调用 start() 时崩溃
【发布时间】:2015-05-05 19:40:37
【问题描述】:

我正在尝试使用 MediaCodec 作为 h264 流的解码器。我什至无法让 MediaCodec 将其调用传递给 start() 而不会崩溃。

以下是日志。基本上,我的 SurfaceView.Holder 回调发生在创建表面和更改表面时。在 surfaceChanged 上,我启动了一个尝试初始化 MediaCodec 的线程。

_surface 实例来自surfaceChanged(SurfaceHolder.getSurface())

String key_mime = "video/avc";
int w = 480;
int h = 360;
MediaFormat mediaFormat = MediaFormat.createVideoFormat(key_mime, w, h);

mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 2000000);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 25);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);

try
{
decoder = MediaCodec.createDecoderByType(key_mime);
}
catch (IOException e)
{
e.printStackTrace();
return;
}

decoder.configure(mediaFormat, _surface, null, 0);
decoder.start();

日志:

05-05 13:18:14.645  22393-22393/ca.example.app D/StreamActivity﹕ surfaceCreated()
05-05 13:18:14.645  22393-22393/ca.example.app D/StreamActivity﹕ surfaceChanged(android.view.SurfaceView$4@2e73a220, 4, 1368, 765
05-05 13:18:14.655  22393-22586/ca.example.app I/ACodec﹕ [] Now uninitialized
05-05 13:18:14.655  22393-22588/ca.example.app I/OMXClient﹕ Using client-side OMX mux.
05-05 13:18:14.685  22393-22588/ca.example.app I/ACodec﹕ [OMX.qcom.video.decoder.avc] Now Loaded
05-05 13:18:14.685  22393-22588/ca.example.app E/ACodec﹕ onConfigureComponent mime.c_str() = video/avc
05-05 13:18:14.685  22393-22588/ca.example.app E/ACodec﹕ [OMX.qcom.video.decoder.avc] storeMetaDataInBuffers failed w/ err -2147483648
05-05 13:18:14.685  22393-22588/ca.example.app I/ACodec﹕ [OMX.qcom.video.decoder.avc] DRC Mode: Port Reconfig Mode
05-05 13:18:14.685  22393-22588/ca.example.app W/ACodec﹕ do not know color format 0x7fa30c03 = 2141391875
05-05 13:18:14.735  22393-22588/ca.example.app I/ExtendedCodec﹕ Decoder will be in frame by frame mode
05-05 13:18:14.735  22393-22588/ca.example.app I/ACodec﹕ [OMX.qcom.video.decoder.avc] OMX_QCOM_FramePacking_OnlyOneCompleteFrame is setting
05-05 13:18:14.765  22393-22588/ca.example.app I/ACodec﹕ [OMX.qcom.video.decoder.avc] Now Loaded->Idle
05-05 13:18:14.795  22393-22588/ca.example.app I/ACodec﹕ [OMX.qcom.video.decoder.avc] configureOutputBuffersFromNativeWindow setBufferCount : 22, minUndequeuedBuffers : 4
05-05 13:18:14.795  22393-22588/ca.example.app I/ACodec﹕ [OMX.qcom.video.decoder.avc] Allocating 22 buffers from a native window of size 294912 on output port
05-05 13:18:14.805  22393-22588/ca.example.app E/ACodec﹕ dequeueBuffer failed: Invalid argument (22)
05-05 13:18:14.805  22393-22588/ca.example.app E/ACodec﹕ Failed to allocate buffers after transitioning to IDLE state (error 0xffffffea)
05-05 13:18:14.805  22393-22588/ca.example.app E/ACodec﹕ signalError(omxError 0x80001001, internalError -22)
05-05 13:18:14.805  22393-22588/ca.example.app I/ACodec﹕ [OMX.qcom.video.decoder.avc] Now Loaded
05-05 13:18:14.805  22393-22587/ca.example.app E/MediaCodec﹕ Codec reported err 0xffffffea, actionCode 0, while in state 5
05-05 13:18:14.805  22393-22586/ca.example.app E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-2272
    Process: ca.example.app, PID: 22393
    android.media.MediaCodec$CodecException: start failed
            at android.media.MediaCodec.native_start(Native Method)
            at android.media.MediaCodec.start(MediaCodec.java:612)
            at ca.example.app.StreamActivity$StreamingVideoThread.run(StreamActivity.java:975)
            at java.lang.Thread.run(Thread.java:818)

我主要在 Android 5.0.1 的三星 Galaxy S4 上进行测试。我感觉这个设备不支持 MediaCodec?

更新

如果我删除所有 mediaFormat.setInteger 调用,则媒体编解码器可以正常启动。由于我的 h264 流每“n”帧都有 SPS/PPS 信息,因此媒体编解码器也可以正常工作。计时信息已关闭,它正在以快的方式播放视频,但这是另一个问题。

【问题讨论】:

    标签: android android-mediacodec decoder


    【解决方案1】:

    您认为三星 S4 不能很好地支持媒体编解码器的权利。它确实有效,但它非常迂腐,并且不能很好地支持回收。

    三星S4和S6给我带来了极大的困扰。三星 A5 与 HTC、Sont、LG、Nexus 等其他设备一样完美运行。

    对于三星 S4,您需要配置以下内容:

    mediaFormat.SetInteger(MediaFormat.KeyMaxWidth, SelectedPalette.Value.Width);
    mediaFormat.SetInteger(MediaFormat.KeyMaxHeight, SelectedPalette.Value.Height);
    mediaFormat.SetInteger(MediaFormat.KeyMaxInputSize, SelectedPalette.Value.Width * SelectedPalette.Value.Height);
    

    (这是 Xamarin 顺便说一句,但调用在 Java 中是相同的)。然后你必须尝试捕捉 mediaCodec.doSomething() 的所有用法。

    如果您有足够高的 api 级别,您应该使用异步解码器回调 android 21+。你还应该使用 mediaCodec.Reset();在任何例外情况下,您都应尽最大努力将解码器重置为原始状态:

    【讨论】:

    • 上述配置如何适用于三星s4?三星有这方面的文件吗?
    【解决方案2】:

    您使用的 mediaFormat.setInteger 调用仅用于编码器,请参考Android Developer's site

    可以使用presentationTimeUS 控制快速播放的视频。例如,对于 25fps 的视频,presentationTimeUS 值应每帧增加 40000,即 [(1/frame_rate)* 1000000](一帧的持续时间,以微秒为单位)

    decoder.queueInputBuffer(inIndex,0,buffer.length,presentationTimeUS,0);
    

    【讨论】:

      猜你喜欢
      • 2015-12-26
      • 2017-02-08
      • 1970-01-01
      • 1970-01-01
      • 2015-03-14
      • 2019-02-22
      • 2016-02-11
      • 2018-10-25
      • 1970-01-01
      相关资源
      最近更新 更多