IllegalStateException 在索尼电视上使用 ExoPlayer

IllegalStateException using ExoPlayer on Sony TV

我正在尝试使用 ExoPlayer 为 Android 电视编写一个简单的 TvInputService。在模拟器上一切正常,但在索尼电视 (KDL-43WF804) 上,我在视频播放几秒钟后从视频编解码器中得到 IllegalStateException。我做错了什么?

日志:

D/MtkACodecPlugin: MtkACodecPlugin createAPlugin
D/MtkACodecPlugin: OMX.MTK.VIDEO.DECODER.AVC needRmClient (673)
D/MtkACodecPlugin: OMX.MTK.VIDEO.DECODER.AVC mNeedVdpImgrz (679)
I/OMXClient: IOmx service obtained
D/SurfaceUtils: connecting to surface 0x8e25d808, reason connectToSurface
I/MediaCodec: [OMX.MTK.VIDEO.DECODER.AVC] setting surface generation to 21334017
D/SurfaceUtils: disconnecting from surface 0x8e25d808, reason connectToSurface(reconnect)
D/SurfaceUtils: connecting to surface 0x8e25d808, reason connectToSurface(reconnect)
D/MtkMediaCodecPlugin: [OMX.MTK.VIDEO.DECODER.AVC] set mOutputPath = 0 L(150)
E/ACodec: [OMX.MTK.VIDEO.DECODER.AVC] setPortMode on output to DynamicANWBuffer failed w/ err -1010
I/ACodec: codec does not support config priority (err -1010)
D/MtkACodecPlugin: add usage GRALLOC_USAGE_PATH_VDP0
D/SurfaceUtils: disconnecting from surface 0x8e25d808, reason setNativeWindowSizeFormatAndUsage
D/SurfaceUtils: connecting to surface 0x8e25d808, reason setNativeWindowSizeFormatAndUsage
D/SurfaceUtils: set up nativeWindow 0x8e25d808 for 1920x1088, color 0x7f000103, rotation 0, usage 0x30002900
D/MtkACodecPlugin: MtkACodecPlugin createAPlugin
I/OMXClient: IOmx service obtained
D/MtkMediaCodecPlugin: No surfaceTextureClient, [OMX.google.aac.decoder] set mOutputPath = 1024 L(159)
I/ACodec: codec does not support config priority (err -2147483648)
I/ACodec: codec does not support config operating rate (err -2147483648)
W/v.rudnev.tvlak: Accessing hidden method Landroid/media/AudioTrack$Builder;->setOffloadedPlayback(Z)Landroid/media/AudioTrack$Builder; (dark greylist, linking)
W/v.rudnev.tvlak: Accessing hidden method Landroid/media/AudioTrack$Builder;->setOffloadedPlayback(Z)Landroid/media/AudioTrack$Builder; (dark greylist, linking)
E/Surface: queueBuffer: error queuing buffer to SurfaceTexture, -19
E/ACodec: queueBuffer failed in onOutputBufferDrained: -19
E/ACodec: signalError(omxError 0x80001001, internalError -19)
E/MediaCodec: Codec reported err 0xffffffed, actionCode 0, while in state 6
D/SurfaceUtils: disconnecting from surface 0x8e25d808, reason disconnectFromSurface
E/MediaCodecVideoRenderer: Video codec error
      java.lang.IllegalStateException
        at android.media.MediaCodec.native_dequeueInputBuffer(Native Method)
        at android.media.MediaCodec.dequeueInputBuffer(MediaCodec.java:2635)
        at com.google.android.exoplayer2.mediacodec.SynchronousMediaCodecAdapter.dequeueInputBufferIndex(SynchronousMediaCodecAdapter.java:115)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.feedInputBuffer(MediaCodecRenderer.java:1139)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:780)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:982)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:486)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:193)
        at android.os.HandlerThread.run(HandlerThread.java:65)
E/ExoPlayerImplInternal: Playback error
      com.google.android.exoplayer2.ExoPlaybackException: MediaCodecVideoRenderer error, index=0, format=Format(0, null, null, video/avc, avc1.4D4020, 5049176, null, [1920, 1080, 25.0], [-1, -1]), format_supported=YES
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:562)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:193)
        at android.os.HandlerThread.run(HandlerThread.java:65)
     Caused by: com.google.android.exoplayer2.video.MediaCodecVideoDecoderException: Decoder failed: OMX.MTK.VIDEO.DECODER.AVC
        at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.createDecoderException(MediaCodecVideoRenderer.java:1470)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:799)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:982)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:486)
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.os.HandlerThread.run(HandlerThread.java:65) 
     Caused by: java.lang.IllegalStateException
        at android.media.MediaCodec.native_dequeueInputBuffer(Native Method)
        at android.media.MediaCodec.dequeueInputBuffer(MediaCodec.java:2635)
        at com.google.android.exoplayer2.mediacodec.SynchronousMediaCodecAdapter.dequeueInputBufferIndex(SynchronousMediaCodecAdapter.java:115)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.feedInputBuffer(MediaCodecRenderer.java:1139)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:780)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:982) 
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:486) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.os.HandlerThread.run(HandlerThread.java:65) 
E/ExoPlayerImplInternal: Disable failed.
      java.lang.IllegalStateException
        at android.media.MediaCodec.native_flush(Native Method)
        at android.media.MediaCodec.flush(MediaCodec.java:2131)
        at com.google.android.exoplayer2.mediacodec.SynchronousMediaCodecAdapter.flush(SynchronousMediaCodecAdapter.java:188)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.flushCodec(MediaCodecRenderer.java:850)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.flushOrReleaseCodec(MediaCodecRenderer.java:843)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.onDisabled(MediaCodecRenderer.java:696)
        at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.onDisabled(MediaCodecVideoRenderer.java:529)
        at com.google.android.exoplayer2.BaseRenderer.disable(BaseRenderer.java:178)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.disableRenderer(ExoPlayerImplInternal.java:1642)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.resetInternal(ExoPlayerImplInternal.java:1382)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.stopInternal(ExoPlayerImplInternal.java:1345)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:578)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:193)
        at android.os.HandlerThread.run(HandlerThread.java:65)
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8b2a6d00
W/ACodec: [OMX.MTK.VIDEO.DECODER.AVC] can not return buffer 22 to native window
D/gralloc: unregister FBM buffer
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8b2a6c00
W/ACodec: [OMX.MTK.VIDEO.DECODER.AVC] can not return buffer 21 to native window
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8b2a6700
W/ACodec: [OMX.MTK.VIDEO.DECODER.AVC] can not return buffer 16 to native window
D/gralloc: unregister FBM buffer
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8b2a6600
W/ACodec: [OMX.MTK.VIDEO.DECODER.AVC] can not return buffer 15 to native window
D/gralloc: unregister FBM buffer
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8b2a6500
W/ACodec: [OMX.MTK.VIDEO.DECODER.AVC] can not return buffer 14 to native window
D/gralloc: unregister FBM buffer
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8b2a6400
W/ACodec: [OMX.MTK.VIDEO.DECODER.AVC] can not return buffer 13 to native window
D/gralloc: unregister FBM buffer
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8b2a6300
W/ACodec: [OMX.MTK.VIDEO.DECODER.AVC] can not return buffer 12 to native window
D/gralloc: unregister FBM buffer
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8b2a6200
W/ACodec: [OMX.MTK.VIDEO.DECODER.AVC] can not return buffer 11 to native window
D/gralloc: unregister FBM buffer
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8b2a6100
W/ACodec: [OMX.MTK.VIDEO.DECODER.AVC] can not return buffer 10 to native window
D/gralloc: unregister FBM buffer
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8b2a6000
W/ACodec: [OMX.MTK.VIDEO.DECODER.AVC] can not return buffer 9 to native window
D/gralloc: unregister FBM buffer
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8b290f00
W/ACodec: [OMX.MTK.VIDEO.DECODER.AVC] can not return buffer 8 to native window
D/gralloc: unregister FBM buffer
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8b290e00
W/ACodec: [OMX.MTK.VIDEO.DECODER.AVC] can not return buffer 7 to native window
D/gralloc: unregister FBM buffer
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8b290d00
W/ACodec: [OMX.MTK.VIDEO.DECODER.AVC] can not return buffer 6 to native window
D/gralloc: unregister FBM buffer
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8b290c00
W/ACodec: [OMX.MTK.VIDEO.DECODER.AVC] can not return buffer 5 to native window
D/gralloc: unregister FBM buffer
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8b290b00
W/ACodec: [OMX.MTK.VIDEO.DECODER.AVC] can not return buffer 4 to native window
D/gralloc: unregister FBM buffer
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8b290a00
W/ACodec: [OMX.MTK.VIDEO.DECODER.AVC] can not return buffer 3 to native window
D/gralloc: unregister FBM buffer
D/MediaCodec: mState = 0, mHaveKick = 0, L(703)
D/MtkACodecPlugin: MtkACodecPlugin destoryAPlugin
D/gralloc: unregister FBM buffer
I/chatty: uid=10178(dev.rudnev.tvlake) identical 3 lines
D/gralloc: unregister FBM buffer
I/ExoPlayerImpl: Release b6e9764 [ExoPlayerLib/2.16.1] [BRAVIA_ATV3_2K, BRAVIA 2K GB ATV3, Sony, 28] [goog.exo.core, goog.exo.decoder, goog.exo.exoplayer, goog.exo.hls, goog.exo.datasource, goog.exo.extractor]
D/MediaCodec: mState = 0, mHaveKick = 0, L(703)
D/MtkACodecPlugin: MtkACodecPlugin destoryAPlugin

代码:

public class IptvInputService extends TvInputService {
    private static final String TAG = "IptvInputService";

    @Override
    public Session onCreateSession(String inputId) {
        return new Session(this);
    }

    public static class Session extends TvInputService.Session {
        private final Context mContext;
        private final ExoPlayer mPlayer;

        public Session(Context context) {
            super(context);
            mContext = context;
            mPlayer = new ExoPlayer.Builder(context).build();
            mPlayer.addListener(new PlayerListener(this));
        }

        @Override
        public void onRelease() {
            mPlayer.release();
        }

        @Override
        public boolean onSetSurface(@Nullable Surface surface) {
            mPlayer.setVideoSurface(surface);
            return true;
        }

        @Override
        public void onSetStreamVolume(float volume) {
            mPlayer.setVolume(volume);
        }

        @Override
        public boolean onTune(Uri uri) {
            try {
                notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING);

                String streamUrl = "https://okkotv-live.cdnvideo.ru/channel/Viasat_Explore_HD.m3u8";

                mPlayer.setMediaItem(MediaItem.fromUri(streamUrl));
                mPlayer.prepare();
                mPlayer.play();

                return true;
            } catch (Throwable ex) {
                notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN);
                Log.e(TAG, "Unable to play stream", ex);
            }

            return false;
        }

        @Override
        public void onSetCaptionEnabled(boolean b) {
        }
    }

    private static class PlayerListener implements Player.Listener {
        private final Session mSession;

        public PlayerListener(Session session) {
            mSession = session;
        }

        @Override
        public void onRenderedFirstFrame() {
            mSession.notifyVideoAvailable();
        }
    }
}

我明白了。就我而言,此异常是由拥有 Surface 对象的系统电视应用程序崩溃引起的。当 Surface 无效时,编解码器进入 Error 状态,同时 ExoPlayer 尝试使用编解码器的缓冲区,不知道编解码器已将 Executing 状态更改为Error.

系统电视应用程序崩溃的原因是以下异常:

02-10 21:31:39.606  7036  7218 E AndroidRuntime: FATAL EXCEPTION: TvCardUpdater-0
02-10 21:31:39.606  7036  7218 E AndroidRuntime: Process: com.sony.dtv.tvx, PID: 7036
02-10 21:31:39.606  7036  7218 E AndroidRuntime: java.lang.RuntimeException: An error occurred while executing doInBackground()
02-10 21:31:39.606  7036  7218 E AndroidRuntime:        at android.os.AsyncTask.done(AsyncTask.java:354)
02-10 21:31:39.606  7036  7218 E AndroidRuntime:        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
02-10 21:31:39.606  7036  7218 E AndroidRuntime:        at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
02-10 21:31:39.606  7036  7218 E AndroidRuntime:        at java.util.concurrent.FutureTask.run(FutureTask.java:271)
02-10 21:31:39.606  7036  7218 E AndroidRuntime:        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
02-10 21:31:39.606  7036  7218 E AndroidRuntime:        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
02-10 21:31:39.606  7036  7218 E AndroidRuntime:        at java.lang.Thread.run(Thread.java:764)
02-10 21:31:39.606  7036  7218 E AndroidRuntime: Caused by: java.lang.ClassCastException: android.graphics.drawable.VectorDrawable cannot be cast to android.graphics.drawable.BitmapDrawable
02-10 21:31:39.606  7036  7218 E AndroidRuntime:        at com.sony.dtv.tvx.tvplayer.function.actionmenu.tvcardstate.AppLinkItemCreator.makeStateOfAppLink(AppLinkItemCreator.java:59)

解决方法很简单:您需要在 AndroidManifest.xml 中为 android:banner 指定位图,而不是矢量图。

因为索尼有自己的应用程序而不是 Live Channels,所以问题只出现在物理设备上,而不是安装 Live Channels 的模拟器上。