private void init(Integer segmentNr) throws IOException {
        // Check for segment in caches, and execute blocking download if missing
        // First, check the future cache, without a seek the chance is much higher of finding it there
        CachedSegment cachedSegment = mFutureCache.remove(segmentNr);
        if(cachedSegment == null) {
            // Second, check the already used cache, maybe we had a seek and the segment is already there
            cachedSegment = mUsedCache.get(segmentNr);
            if(cachedSegment == null) {
                // Third, check if a request is already active
                boolean downloading = mSegmentDownloader.isDownloading(mAdaptationSet, segmentNr);
                /* TODO add synchronization to the whole caching code
                 * E.g., a request could have finished between this mFutureCacheRequests call and
                 * the previous mUsedCache call, whose result is missed.
                 */
                if(downloading) {
                    synchronized (mFutureCache) {
                        try {
                            while((cachedSegment = mFutureCache.remove(segmentNr)) == null) {
                                Log.d(TAG, "waiting for request to finish " + segmentNr);
                                mFutureCache.wait();
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                } else {
                    // Fourth, least and worst alternative: blocking download of segment
                    cachedSegment = downloadFile(segmentNr);
                }
            }
        }

        mSegmentPTSOffsetUs = cachedSegment.ptsOffsetUs;
        setDataSource(cachedSegment.file.getPath());

        // If the cache size is smaller than the segment, the segment file will not be cached but
        // deleted immediately (the cache will remove it immediately because it cannot hold it,
        // and thereby delete it). This does not matter, because if we set the cache size that small,
        // we are not interested in caching segments anyway. It's not a problem when a segment gets
        // deleted here, because it has already been set as data source above and as long as the
        // extractor has a reference to the file, it stays accessible.
        // It is important that the deletion happens after the data source is set!
        mUsedCache.put(segmentNr, cachedSegment);

        // Reselect tracks at reinitialization for a successive segment
        if(!mSelectedTracks.isEmpty()) {
            for(int index : mSelectedTracks) {
                super.selectTrack(index);
            }
        }

        // Switch representation
        if(cachedSegment.representation != mRepresentation) {
            //invalidateFutureCache();
            Log.d(TAG, "representation switch: " + mRepresentation + " -> " + cachedSegment.representation);
            mRepresentationSwitched = true;
            mRepresentation = cachedSegment.representation;
        }

        // Switch future caching to the currently best representation
        Representation recommendedRepresentation = mAdaptationLogic.getRecommendedRepresentation(mAdaptationSet);
        fillFutureCache(recommendedRepresentation);
    }
Informs the caller if the representation has changed, and resets the flag. This means, it
returns true only once (the first time) after the representation has changed.
@return true if the representation has changed between the previous and current call, else false
MediaPlayer-DASH/src/main/java/net/protyposis/android/mediaplayer/dash/DashMediaExtractor.java