From 43e0fa504305f239f4eec2e61d47a07cd24c6ed9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Rydh=C3=A9?= Date: Fri, 27 Mar 2015 12:33:33 +0100 Subject: [PATCH] Move to first offset after prepare If a file contained meta data at the end, the datasource would reach end of file during prepare phase. When the playback was started the datasource needed to be reconnected at the first sample offset, meaning that no data had been buffered between prepare() and start(). --- .../media/internal/BufferedDataSource.java | 5 +++ .../android/media/internal/DataSource.java | 4 ++ .../internal/HttpBufferedDataSource.java | 12 +++++ .../android/media/internal/ISOBMFFParser.java | 45 ++++++++++++++----- 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/library/src/main/java/com/sonymobile/android/media/internal/BufferedDataSource.java b/library/src/main/java/com/sonymobile/android/media/internal/BufferedDataSource.java index 84f350b..4458847 100644 --- a/library/src/main/java/com/sonymobile/android/media/internal/BufferedDataSource.java +++ b/library/src/main/java/com/sonymobile/android/media/internal/BufferedDataSource.java @@ -486,6 +486,11 @@ protected void doCloseSilently(Closeable c) { @Override public abstract int readAt(long offset, byte[] buffer, int size) throws IOException; + @Override + public void requestReadPosition(long offset) throws IOException { + // Empty implementation, interested subclasses should override. + } + class ReconnectHandler extends Handler { private int mPreviousAvailable = 0; diff --git a/library/src/main/java/com/sonymobile/android/media/internal/DataSource.java b/library/src/main/java/com/sonymobile/android/media/internal/DataSource.java index 2dfe904..7a92bf1 100644 --- a/library/src/main/java/com/sonymobile/android/media/internal/DataSource.java +++ b/library/src/main/java/com/sonymobile/android/media/internal/DataSource.java @@ -180,6 +180,10 @@ public DataAvailability hasDataAvailable(long offset, int size) { return DataAvailability.AVAILABLE; } + public void requestReadPosition(long offset) throws IOException { + // Empty implementation, interested subclasses should override. + } + public abstract void seek(long offset) throws IOException; protected long peekLong(byte[] src, int offset) { diff --git a/library/src/main/java/com/sonymobile/android/media/internal/HttpBufferedDataSource.java b/library/src/main/java/com/sonymobile/android/media/internal/HttpBufferedDataSource.java index e26887a..4eec559 100644 --- a/library/src/main/java/com/sonymobile/android/media/internal/HttpBufferedDataSource.java +++ b/library/src/main/java/com/sonymobile/android/media/internal/HttpBufferedDataSource.java @@ -202,6 +202,18 @@ public synchronized DataAvailability hasDataAvailable(long offset, int size) { return toReturn; } + @Override + public synchronized void requestReadPosition(long offset) throws IOException { + if (LOGS_ENABLED) + Log.d(TAG, "Request reconnect now at " + offset); + + mCurrentOffset = offset; + mOffset = offset; + + doCloseSync(); + openConnectionsAndStreams(); + } + public int getBuffering() { int percentage = 0; try { diff --git a/library/src/main/java/com/sonymobile/android/media/internal/ISOBMFFParser.java b/library/src/main/java/com/sonymobile/android/media/internal/ISOBMFFParser.java index 24c8c1a..53353b1 100644 --- a/library/src/main/java/com/sonymobile/android/media/internal/ISOBMFFParser.java +++ b/library/src/main/java/com/sonymobile/android/media/internal/ISOBMFFParser.java @@ -403,20 +403,45 @@ public boolean parse() { mMetaDataValues.put(MetaData.KEY_SEEK_AVAILABLE, 1); mMetaDataValues.put(MetaData.KEY_NUM_TRACKS, mTracks.size()); - updateAspectRatio(); + if (parseOK) { + updateAspectRatio(); - updateRotation(); + updateRotation(); - if (mCurrentAudioTrack != null) { - mCurrentAudioTrack.buildSampleTable(); - } + if (mCurrentAudioTrack != null) { + mCurrentAudioTrack.buildSampleTable(); + } - if (mCurrentVideoTrack != null) { - mCurrentVideoTrack.buildSampleTable(); - } + if (mCurrentVideoTrack != null) { + mCurrentVideoTrack.buildSampleTable(); + } + + if (mCurrentSubtitleTrack != null) { + mCurrentSubtitleTrack.buildSampleTable(); + } - if (mCurrentSubtitleTrack != null) { - mCurrentSubtitleTrack.buildSampleTable(); + long firstOffset = 0; + if (mIsFragmented) { + firstOffset = mFirstMoofOffset; + } else { + if (mCurrentVideoTrack != null) { + firstOffset = mCurrentVideoTrack.getSampleTable().getOffset(0); + } + + if (mCurrentAudioTrack != null) { + long audioOffset = mCurrentAudioTrack.getSampleTable().getOffset(0); + if (firstOffset == 0 || audioOffset < firstOffset) { + firstOffset = audioOffset; + } + } + } + + if (mDataSource.hasDataAvailable(firstOffset, 1) == DataAvailability.NOT_AVAILABLE) { + try { + mDataSource.requestReadPosition(firstOffset); + } catch (IOException e) { + } + } } return parseOK;