I guess you are talking about syncing of DLNA push, right?
Just to refresh on the background, in DLNA push MC sends either one of the following command series...
- SetAVTransportURI, Play (repeat)
- SetAVTransportURI, Play, SetNextAVTransportURI (repeat)
And then the renderer fetches each track with an HTTP GET.
So some of my tips for improving Sync would be as follows:
1) Don't use a mix of the two types of push above. If both renderers support SetNext then use it for both. Otherwise use Set for both renderers.
2) Do send the above series of UPnP commands always pairwise together for both renderers, as close to simultaneously as possible.
3) Do wait for the HTTP GET from both renderers to come in before starting to serve the stream to either of them. In other words hold back the faster renderer until the slower one makes its GET. Or to say it again differently, do start sending the stream pairwise for both renderers as close to simultaneously as possible.
4) Do always serve the same exact same byte stream to both renderers. Do not serve different media formats, bit depths, sample rates or whatever. This means basically always either serve the original file to both renderers if supported by both. Or fallback to L16. Or in the worst case fallback to MP3. Note: this requires that MC must check GetProtocolInfo (SinkProtocolInfo) on both renderers to find the highest common denominator between source and the two sink formats.
5) Concerning the pairwise serving in point 3) above, watch out for byte range seeks. Probably it is best to return HTTP headers without Accept-Range headers, in order to avoid any byte range seeks at all...
6) Do not allow the issuing of UPnP Seek commands when playing to synced zones.
7) Do not allow the issuing of UPnP Pause/Play commands (other than the first Play) when playing to synced zones.
8) The above measures will all help to ensure the starting of playing the tracks will be tightly synchronised. It does not solve the issue that some players may play through faster than others. So even if the start is tighter, the endings may float apart. To ameliorate this issue on longer tracks, do not serve media files with cue files as a single track. But rather break the track into individual separate serves based on the cue file.
EDIT: Furthermore, I suggest a possible additional "smart" enhancement as follows:
9) Test the latency of the two renderers, by attempting a Sync Play as described above, and checking the Player Status on both players. Take note of the time difference between the issuance of the Play command and the return of State=PLAYING on each renderer, and apply the delta between those two values to the "simultaneoues" pairwise commands described above. EDIT: you should probably also allow a user setting to turn off this automatic latency detection, and indeed allow a manual input instead.
10) Note by the way, that there may also be a case of sync linking between a DLNA render on one hand, and a local DAC on the other hand. In that case, just hold off pushing the stream to the local DAC until you have received the HTTP GET from the DLNA renderer for that DAC. You may need to push silence while waiting for the remote GET in order to keep the local DAC "warm"..
11) Further to 10) if the GET comes before the Play command has been issued, then ignore the above, but instead syncronise the pushing of the stream to the local DAC with the issuance of the Play command to the renderer...
NOTE: be aware that topics 2) and 3) above could lead to a race condition: if one renderer type does its GET before it receives a Play command, and another renderer type holds its GET until after the Play command. You would need to create a state table for handling this. And a pre test like 10) above would allow you to identify what each renderer's behaviour is...