Search code examples
androidexceptionexoplayerandroid-tvsony

IllegalStateException using ExoPlayer on Sony TV


I'm trying to write a simple TvInputService for Android TV using ExoPlayer. On the emulator everything works fine, but on Sony TV (KDL-43WF804) I get IllegalStateException from video codec after a few seconds of video playing. What am I doing wrong?

Logs:

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

Code:

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();
        }
    }
}

Solution

  • I figured it out. In my case, this exception is caused by the crash of the system tv application, which owns the Surface object. The codec goes into the Error state when the Surface becomes invalid and at the same moment the ExoPlayer tries to work with the codec's buffers, not knowing that the codec has changed the Executing state to Error.

    And the reason for the crash of the system tv app was the following exception:

    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$3.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)
    

    The fix is simple: you need to specify a bitmap for android:banner in AndroidManifest.xml instead of a vector image.

    Because Sony has its own app instead of Live Channels, the problem only occurred on the physical device and not on the emulator where Live Channels is installed.