Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

loadError with EOF exception when extracting media container for fragmented MP4 #7630

Closed
chadacious opened this issue Jul 15, 2020 · 6 comments
Assignees
Labels

Comments

@chadacious
Copy link

chadacious commented Jul 15, 2020

[REQUIRED] Searched documentation and issues

Exoplayer library docs, developer website, stackoverflow, github issues

[REQUIRED] Question

I'm attempting to play a fragmentedMP4 using a DashMediaSource. The content plays if I don't specify a SegmentBase range in the dash manifest, but since the sidx box range is not specified, and apparently not "discovered" by the extractor, trickplay features are not working.

I've examined the media file using a hex editor and the mp4box tool and verified the sidx boxes are there and appear intact. I'm wondering if the mvex box is creating an issue.

When I "do" specify the correct SegmentBase initialization range, I get an EOFException from the extractor. I've tried to determine why this occurs but am looking for some guidance.

The content is DRM protected, but my problem is not with the DRM license acquisition, as I mentioned without specifying the segment base initialization range, the license is issued and the content plays, its just not seekable. The EOF is happening when parsing media container prior to the drm key exchange.

I suspect my media container is somehow not yet supported by exoplayer and I will need to write a custom extractor. If that is the case, could you provide a reference as to "how" to introduce your own extractor in exoplayer? I couldn't figure out how to do it for the DashMediaSource, and then I became confused by the ProgressiveMediaSource as it simply errors out with UnrecognizedInputFormat.

Would someone be able to help me determine why exoplayer's FragmentedMP4Extractor is not able to read my media container?

Would be happy to host a remote session for help with debugging.

A full bug report captured from the device

D/EventLogger: mediaPeriodReadingStarted [eventTime=0.64, mediaPos=0.00, window=0, period=0]
E/EventLogger: internalError [eventTime=1.17, mediaPos=0.00, window=0, period=0, loadError
      java.io.EOFException
        at com.google.android.exoplayer2.extractor.DefaultExtractorInput.readFromDataSource(DefaultExtractorInput.java:292)
        at com.google.android.exoplayer2.extractor.DefaultExtractorInput.skipFully(DefaultExtractorInput.java:104)
        at com.google.android.exoplayer2.extractor.DefaultExtractorInput.skipFully(DefaultExtractorInput.java:112)
        at com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor.readAtomPayload(FragmentedMp4Extractor.java:427)
        at com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor.read(FragmentedMp4Extractor.java:315)
        at com.google.android.exoplayer2.source.chunk.InitializationChunk.load(InitializationChunk.java:102)
        at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:415)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:914)
    ]

Link to test content

A sample manifest: https://pastebin.com/NZLniw0L
and an associated mp4 fragment https://enjoy-staging.sfo2.digitaloceanspaces.com/ExoPlayer-MP4Fragment.fmp4

Some sample code showing the player setup:

  private void initializePlayer() {
    if (player == null) {
      DefaultTrackSelector trackSelector = new DefaultTrackSelector();
      trackSelector.setParameters(trackSelector.buildUponParameters().setMaxVideoSizeSd());
      player = ExoPlayerFactory.newSimpleInstance(this, trackSelector);
      player.addAnalyticsListener(new EventLogger(trackSelector));
    }
    playerView.setPlayer(player);

    Uri uri = Uri.parse(getString(new File(R.string.media_url_dash_mpd)));
    DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this, "ua");

    DrmSessionManager<ExoMediaCrypto> drmSessionManager =
      new DefaultDrmSessionManager.Builder()
              .setMultiSession(true)
              .setUuidAndExoMediaDrmProvider(WIDEVINE_UUID, FrameworkMediaDrm.DEFAULT_PROVIDER)
              .build(new EnjoyWidevineDrmCallback());
    MediaSource mediaSource = new DashMediaSource.Factory(dataSourceFactory)
      .setDrmSessionManager(drmSessionManager)
      .createMediaSource(uri);

    player.setPlayWhenReady(playWhenReady);
    player.seekTo(currentWindow, playbackPosition);
    player.prepare(mediaSource, false, false);
  }
@chadacious
Copy link
Author

Looking at it further, I see that when i "don't" specify a SegmentBase at all, the FragmentedMP4Extractor indeed seems to read the sidx box as well as other parts of the media container.

So I believe my theory that the exoplayer wasn't getting the sidx data is incorrect. Now I'm just stuck trying to figure out why trickmode doesn't work (i.e. when I try to seek to a position just using the scrubber bar from the default player ui, it doesn't doesn't load the proper segment and just seems to load each segment in between taking far too long to resume playback).

I'm missing something somewhere. Is there a particular way one must enable trickmode?

@kim-vde
Copy link
Contributor

kim-vde commented Jul 17, 2020

I think there is something wrong with the manifest. The SegmentBase indexRange is the same for all the representations, which seems very unlikely, and the Initialization range is the same as the SegmentBase indexRange, which shouldn't be the case.

As for trick play, we don’t support it out of the box (see #6054 and #474). It is possible to implement it on top of what we provide but it is a bit tricky (see #474). We have plans to enable trick play by setting a flag in the future.

@chadacious
Copy link
Author

chadacious commented Jul 18, 2020

Thanks for your response. I agree that the SegmentBase indexRange and Initialziation seem incorrect. I've sent a sample app for your examination to the dev.exoplayer@gmail.com email.

@kim-vde
Copy link
Contributor

kim-vde commented Jul 20, 2020

Can you try to fix the SegmentBase indexRange and Initialization range and see if you still have problems?

@chadacious
Copy link
Author

I was able to get the results I needed by swallowing the error in IntializationChunk load method.

while (result == Extractor.RESULT_CONTINUE && !loadCanceled) {
  result = extractor.read(input, DUMMY_POSITION_HOLDER);
}

changed to something like:

while (result == Extractor.RESULT_CONTINUE && !loadCanceled) {
  try {
    result = extractor.read(input, DUMMY_POSITION_HOLDER);
  } catch (Exception error) {
    Log.d("InitializationChunk", "Load Error: " + error);
    break;
  }
}

Perhaps the SegmentBase indexRange is too sensitive and can handle the EOF exception? I'll see if I can do some more research and could make a pull request if I can build a solid case for it.

Thoughts?

@kim-vde
Copy link
Contributor

kim-vde commented Jul 23, 2020

It is expected that seeking is not working if you don't specify the right ranges so I would try to fix these.

@kim-vde kim-vde closed this as completed Aug 17, 2020
@google google locked and limited conversation to collaborators Oct 17, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants