ExoPlayer icon indicating copy to clipboard operation
ExoPlayer copied to clipboard

Caused by org.json.JSONException: No value for mediaItem when casting (Chromecast)

Open ameerprpt opened this issue 1 year ago • 3 comments

ExoPlayer Version

2.18.1

Devices that reproduce the issue

All Android devices

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

Not tested

Reproduction steps

When casting the video to Chromecast, mediaitem is getting null and getting JSONException. It is working fine in 2.15.1 version. I am using exoplayer with exoplayer:extension-cast

private val castPlayer = CastPlayer(castContext)
val mediaInfo = MediaInfo.Builder(streamItem.streamUrl)
            .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
            .setMetadata(createMetadata(streamItem)).setCustomData(customJson)
            .build()

        mediaClient.load(
            MediaLoadRequestData.Builder()
                .setMediaInfo(mediaInfo)
                .setAutoplay(true)
                .setCurrentTime(startPosition)
                .build()
        )

Expected result

With normal exoplayer video is playing, also I am able to connect Chromecast device

Actual result

Caused by org.json.JSONException: No value for mediaItem at org.json.JSONObject.get(JSONObject.java:400) at org.json.JSONObject.getJSONObject(JSONObject.java:620) at com.google.android.exoplayer2.ext.cast.DefaultMediaItemConverter.getMediaItem(DefaultMediaItemConverter.java:148) at com.google.android.exoplayer2.ext.cast.DefaultMediaItemConverter.toMediaItem(DefaultMediaItemConverter.java:85) at com.google.android.exoplayer2.ext.cast.CastTimelineTracker.getCastTimeline(CastTimelineTracker.java:129) at com.google.android.exoplayer2.ext.cast.CastPlayer.updateTimeline(CastPlayer.java:982) at com.google.android.exoplayer2.ext.cast.CastPlayer.updateTimelineAndNotifyIfChanged(CastPlayer.java:907) at com.google.android.exoplayer2.ext.cast.CastPlayer.updateInternalStateAndNotifyIfChanged(CastPlayer.java:783) at com.google.android.exoplayer2.ext.cast.CastPlayer.access$800(CastPlayer.java:81) at com.google.android.exoplayer2.ext.cast.CastPlayer$StatusListener.onStatusUpdated(CastPlayer.java:1319) at com.google.android.gms.cast.framework.media.zzbo.zzm(com.google.android.gms:play-services-cast-framework@@20.1.0:6) at com.google.android.gms.cast.internal.zzap.zzaa(com.google.android.gms:play-services-cast@@20.1.0:1) at com.google.android.gms.cast.internal.zzap.zzQ(com.google.android.gms:play-services-cast@@20.1.0:63) at com.google.android.gms.cast.framework.media.RemoteMediaClient.onMessageReceived(com.google.android.gms:play-services-cast-framework@@20.1.0:1) at com.google.android.gms.cast.zzbn.run(com.google.android.gms:play-services-cast@@20.1.0:4) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:250) at android.app.ActivityThread.main(ActivityThread.java:7877) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)

Media

image

Bug Report

  • [X] You will email the zip file produced by adb bugreport to [email protected] after filing this issue.

ameerprpt avatar Sep 07 '22 10:09 ameerprpt

If the DefaultMediaItemConverter is sending a MediaItemQueueItem to the cast device it includes the data of the MediaItem in a JSON document that is stored as the custom data.

In the case that generated the stack trace from above the mediaItem in the map is null like you mention. So it tries to read from the custom JSON data that is not available.

I wonder a) why the media item is null in this case and b) why there isn't such a JSON in the media item that should have been created by us.

Did you override DefaultMediaItemConverter.toMediaQueueItem?

Probably not. So I'm trying to understand in which situation CastPlayer ends up in this invalid state:

Do you know at which moment this happens? Are you trying to connect to a Cast device that is already playing? Like with a second Android device that reads the queue that has been added to the cast device by another Android device running your app? Or is this after you restart/redeploy your app and the cast device has still the queue loaded from the previous app instance that was running?

I think we would want to support either cases, so something is not working as expected. So I'm trying to repro this behaviour. Can you give me some more information when in the application life-cycle and in what situation this happens?

You are correct that this has been introduced by 2.18.x. We didn't read the JSON from the session custom data before.

marcbaechinger avatar Sep 07 '22 12:09 marcbaechinger

I am not overriding DefaultMediaItemConverter.toMediaQueueItem. Just passing castContext to CastPlayer The Chromecast was already connected and just trying to play the video in the Casting device. The video is playing in the TV and the app got crashed with this Exception.

I have checked remoteMediaClient for the CastSession mediaInfo and currentItem are null here. Our video format is DASH.

val mediaClient = castContext.sessionManager.currentCastSession?.remoteMediaClient

        mediaClient?.let {
            val sameItemPlaying = (it.isPlaying && it.mediaInfo?.contentId == streamItem.streamUrl)
            if (sameItemPlaying) {
                listenersHandler.sendPlayerStateEvent( Player.STATE_READY)
            } else {
                startPlayback(it, streamItem, startPosition)
            }
        }

ameerprpt avatar Sep 07 '22 12:09 ameerprpt

i have same Problem, when i create json object by myself and add to media item it works:

JSONObject jsonObject = new JSONObject();
            try {
                JSONObject mediaItem = new JSONObject();
                mediaItem.put("uri", channelUrl);
                mediaItem.put("mediaId", tvgId);
                jsonObject.put("mediaItem", mediaItem);
            } catch (JSONException e) {
                e.printStackTrace();
            }

            MediaInfo.Builder mediaInfoBuilder = new MediaInfo.Builder(channelUrl);
            mediaInfoBuilder.setStreamType(MediaInfo.STREAM_TYPE_LIVE);
            mediaInfoBuilder.setCustomData(jsonObject);
            mediaInfoBuilder.setContentType(mimeType);
            mediaInfoBuilder.setStreamDuration(castPlayer.getDuration() * 1000);
            mediaInfoBuilder.setMetadata(metadata);
            MediaInfo mediaInfo = mediaInfoBuilder.build();

            RemoteMediaClient remoteMediaClient = castContext.getSessionManager().getCurrentCastSession().getRemoteMediaClient();
remoteMediaClient.load(new MediaLoadRequestData.Builder().setCustomData(jsonObject).setMediaInfo(mediaInfo).build());

koshisinthehouse avatar Sep 21 '22 12:09 koshisinthehouse

I'm experiencing this problem, but I'm seeing this issue only when adding items to a queue, and with r2.17.1. (Same outcome, same failure in DefaultMediaItemConverter.getMediaItem parsing the JSONObject at line 145 of the 2.17.1 version of that class). Considering the difference in ExoPlayer versions, I'm not sure whether I've come across a different issue entirely, or a different way to make this issue happen.

In our case, we are configuring the queuing like this: The goal is to call castPlayer.addMediaItems(List<MediaItem>) In order to do that: 2. Add items to be queued to a List<MediaQueueItem> 3. Convert each MediaQueueItem in this List<MediaQueueItem> to a MediaItem, using DefaultMediaItemConverter.toMediaItem(MediaQueueItem) - the failure occurs here:

java.lang.RuntimeException: org.json.JSONException: No value for mediaItem
at com.google.android.exoplayer2.ext.cast.DefaultMediaItemConverter.getMediaItem(DefaultMediaItemConverter.java:159)
at com.google.android.exoplayer2.ext.cast.DefaultMediaItemConverter.toMediaItem(DefaultMediaItemConverter.java:85)
at com.brightcove.cast.GoogleCastComponent.convertMediaQueueItemToMediaItem(GoogleCastComponent.java:656)

I'm going to give @koshisinthehouse 's approach a try to see if that provides a workaround to my circumstance.

jrw95 avatar Oct 17 '22 00:10 jrw95

I'm going to give @koshisinthehouse 's approach a try to see if that provides a workaround to my circumstance.

Turns out that our Cast receiver app does not have support for queueing, however I was able to try @koshisinthehouse 's approach, and it worked, as far as sending a mediaItem to the receiver (which ultimately ignored it).

jrw95 avatar Nov 03 '22 17:11 jrw95