google / ExoPlayer

This project is deprecated and stale. The latest ExoPlayer code is available in https://github.com/androidx/media
https://developer.android.com/media/media3/exoplayer
Apache License 2.0
21.74k stars 6.03k forks source link

[QUESTIONS] getting the real media time; mpeg2 in TS; TS seeking/resume. #1078

Closed stuckless closed 8 years ago

stuckless commented 8 years ago

I'll start with the TS Seeking/Resume. I've already found an issue here where someone asked about seeking in TS files, and your reply was that you'd only support seeking in file types that actually send the seek information in the file, and apparently TS files don't. I'm ok with that. I do wonder how I'd go about supporting a RESUME from last playback position, when all I have is the last playback time. Also, when a seek happens, I'm seeing ExoPlayer call an open on the datasource, with a position of 0, and this causes the application to basically reset the stream. ie, I've watched 5 minutes of video, I hit skip forward, and the result is that I'm back to the beginning of the file. If Exo is not going to support seeking in TS file, shouldn't it just drop the seek request instead of re-issuing an open on the datasource from the beginning? Is there a way that I can configure Exo to not work this way? Should/Could the DataSource's DataSpec contain a postion and a positionTS (or US) field, whereby the postionTS field is the "time" requested. In this way, a data source implantation could choose to implement their own mechanism to seek in a non-seekable file.

The second question is about whether or not ExoPlayer support MPEG2 in it's TS parser? Or does the parser not care, and if a device has MPEG2 hardware decoding, it will just work?

The first question about getting the REAL media time from the stream instead of what the player has been tracking. ie, calling getCurrentPosition() appears to return a tracking position that is maintained by the player's clock and not what the stream is actually telling you.

To understand why this important to SageTV, let me run through how a SageTV player typically handles TS streams. As you said, TS files are not seekable, but in the real world, lots of hardware produces TS files. For example, the HDPVR device produced ts files. SageTV handles this by introducing a streaming model that it calls PUSH. The basic premis of this streaming model is that a tread on the client accepts data and stores it in a buffer, and the Player thread reads from the buffer.

Where a user seeks, this is what happens...

  1. The SageTV server handles the request to Seek.
  2. SageTV server sends a FLUSH command to the client
  3. Client receives the FLUSH command and now has to tell the Player clear all of it's player data and start to receive new data.
  4. SageTV server find the stream position, and immediately starts pushing the new data
  5. Client Player starts playing new data.
  6. Server begins requesting current play back time from the Client so it can track and verify that the player is playing the data at the correct location.

So, as you see, under this streaming model, the player doesn't need to know or care if the stream is seekable, since the seeking is handled on the server, and seeks happen extremely quickly.

I've run into a couple of problems here, specifically with items 3 and 6. FLUSH is not something that a player typically handles as a command, but it's something that a player has to be aware of, since when it seeks internally, it has to flush all the prepared frames and start processing new ones. So, as a work around, typically when a FLUSH happen, I'll send a seek(-1) or seek(Long.MAX_VALUE)... both of these cause the player to clear it's buffered frames. The problem is that in doing so, because TS files are not seekable, the player call open on the DataSource again, which for PUSH datasource is basically ignored, and I just keep flush our caches data and start sending the new PUSHed data. But, the player now, internally thinks that is playing from position 0. And when step 6 happens, I call getCurrentPostion to get the media time, I get back values NOT from the TS stream, but rather from the internal clock of the player, and this get sent back to the sagetv server, and it now thinks we are playing from the beginning of the file. And this leaves the client and server in an inconsistent state, since the player is actually playing video 30 seconds ahead (because we seeked forward), but it's getCurrentPosition tells sagetv that we starting over.

So, after all that... if there is a way to tell the player to clear it's frames to start over without calling Seek(-1), that would be great, but I'd still have an issue in that the Player while receiving new data, would not report the time from the TS stream, but instead report it's own internal clock. Is there a way to configure Exo to use the time from the stream?

ojw28 commented 8 years ago
stuckless commented 8 years ago

Thanks the timestampOffsetUs removal fixed the timestamp issue for me. So, ExoPlayer is working greak for this SageTV use case. Thanks.

I know how much you don't want to pollute ExoPlayer with "hacks", but I'm wondering if you'd consider updating the PtsTimestampAdjuster with an option... or allow a custom one to be set, etc, or, do I need to start maintaining my own ExoPlayer repo for this change?

Thanks

ojw28 commented 8 years ago

If we were to allow passing of a "don't offset" value that could be passed to the PtsTimestampAdjuster constructor as the value of firstSampleTimestampUs, would that work for you? Note that you'd need to construct the PtsTimestampAdjuster in your own code, then construct a TsExtractor that uses it, then explicitly pass the extractor to the ExtractorSampleSource constructor.

stuckless commented 8 years ago

That would work for me. Thanks!

ojw28 commented 8 years ago

Opening again to track adding that (only).

stuckless commented 8 years ago

Thank you ;)