I managed to remove most of the synchronous code that was being used to try and coordinate everything and instead I'm using a centrally coordinated sequence number.
Every packet and frame created has a sequence number associated with it which is maintained through the data flow graph. Every time a seek operation is performed the sequence number is incremented. This feeds through to each stage and lets them make cheap decisions on what to do:
- Decoders just flush if the sequence number changes.
- Decoders discard any packets which have the wrong number.
- Renderers discard any frames which have the wrong number.
- Renderers reset any output they need to (i.e. audio flush, re-sync).
I also use similar code to JJMediaReader so that after a seek it discards any frames which come through before desired seek position.
I still need some out-of-band callbacks for seek and pause because all of the above means the renderers may never see anything, but they don't need to do much.
The android player is somewhat broken so I need to fix that before committing anything.
Update: Got it working well enough and checked everything in. The new sync code causes some extra 'recovery time' after seeking, but once it's settled down it ends up with better sync. The recovery time is only noticeable on slow hardware.