diff options
author | Dongwon Kang <dwkang@google.com> | 2019-03-21 21:38:57 -0700 |
---|---|---|
committer | Dongwon Kang <dwkang@google.com> | 2019-03-21 22:05:48 -0700 |
commit | 77ab98645a941d879fe26021e7820ccdbe523c25 (patch) | |
tree | 17fbe8257062f69138e9efe1d70869cf4ea10366 | |
parent | 8a5b8f7c6406b035349534af6a55b95c986775f2 (diff) |
Use ProxyFileDescriptorCallback instead of DataSourceCallback
Test: MediaPlayer2Test
Bug: 128461264, Bug: 126701061
Change-Id: Id971c77bf9a3003e2f24b716ad784b5f2f56f55f
-rw-r--r-- | api/current.txt | 7 | ||||
-rw-r--r-- | api/test-current.txt | 4 | ||||
-rw-r--r-- | media/Android.bp | 2 | ||||
-rw-r--r-- | media/apex/java/android/media/CallbackDataSourceDesc.java | 48 | ||||
-rw-r--r-- | media/apex/java/android/media/DataSourceCallback.java | 6 | ||||
-rw-r--r-- | media/apex/java/android/media/DataSourceDesc.java | 32 | ||||
-rw-r--r-- | media/apex/java/android/media/MediaPlayer2.java | 35 | ||||
-rw-r--r-- | media/apex/java/android/media/ProxyDataSourceCallback.java | 68 |
8 files changed, 99 insertions, 103 deletions
diff --git a/api/current.txt b/api/current.txt index 9f9c7de8c1e7..9190c86f6ed6 100644 --- a/api/current.txt +++ b/api/current.txt @@ -23759,12 +23759,6 @@ package android.media { field public static final int QUALITY_MEDIUM = 1; // 0x1 } - public abstract class DataSourceCallback implements java.io.Closeable { - ctor public DataSourceCallback(); - method public abstract long getSize() throws java.io.IOException; - method public abstract int readAt(long, @NonNull byte[], int, int) throws java.io.IOException; - } - public class DataSourceDesc { method public long getEndPosition(); method @Nullable public String getMediaId(); @@ -23781,7 +23775,6 @@ package android.media { method @NonNull public android.media.DataSourceDesc.Builder setDataSource(@NonNull android.net.Uri, @Nullable java.util.Map<java.lang.String,java.lang.String>, @Nullable java.util.List<java.net.HttpCookie>); method @NonNull public android.media.DataSourceDesc.Builder setDataSource(@NonNull android.os.ParcelFileDescriptor); method @NonNull public android.media.DataSourceDesc.Builder setDataSource(@NonNull android.os.ParcelFileDescriptor, long, long); - method @NonNull public android.media.DataSourceDesc.Builder setDataSource(@NonNull android.media.DataSourceCallback); method @NonNull public android.media.DataSourceDesc.Builder setEndPosition(long); method @NonNull public android.media.DataSourceDesc.Builder setMediaId(@Nullable String); method @NonNull public android.media.DataSourceDesc.Builder setStartPosition(long); diff --git a/api/test-current.txt b/api/test-current.txt index 16fdc941bb28..79fb6db8d06a 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1078,10 +1078,6 @@ package android.media { method public android.media.BufferingParams.Builder setResumePlaybackMarkMs(int); } - public class CallbackDataSourceDesc extends android.media.DataSourceDesc { - method @NonNull public android.media.DataSourceCallback getDataSourceCallback(); - } - public class FileDataSourceDesc extends android.media.DataSourceDesc { method public long getLength(); method public long getOffset(); diff --git a/media/Android.bp b/media/Android.bp index 86dc509501a4..34801813ee87 100644 --- a/media/Android.bp +++ b/media/Android.bp @@ -90,7 +90,6 @@ filegroup { "apex/java/android/media/DataSourceDesc.java", "apex/java/android/media/UriDataSourceDesc.java", "apex/java/android/media/FileDataSourceDesc.java", - "apex/java/android/media/CallbackDataSourceDesc.java", "apex/java/android/media/Media2Utils.java", "apex/java/android/media/MediaPlayer2Utils.java", "apex/java/android/media/MediaPlayer2.java", @@ -98,6 +97,7 @@ filegroup { "apex/java/android/media/Media2HTTPConnection.java", "apex/java/android/media/RoutingDelegate.java", "apex/java/android/media/BufferingParams.java", + "apex/java/android/media/ProxyDataSourceCallback.java", ], } diff --git a/media/apex/java/android/media/CallbackDataSourceDesc.java b/media/apex/java/android/media/CallbackDataSourceDesc.java deleted file mode 100644 index d9db62e99126..000000000000 --- a/media/apex/java/android/media/CallbackDataSourceDesc.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.media; - -import android.annotation.NonNull; -import android.annotation.TestApi; - -/** - * Structure of data source descriptor for sources using callback. - * - * Used by {@link MediaPlayer2#setDataSource}, {@link MediaPlayer2#setNextDataSource} and - * {@link MediaPlayer2#setNextDataSources} to set data source for playback. - * - * <p>Users should use {@link Builder} to create {@link CallbackDataSourceDesc}. - * @hide - */ -@TestApi -public class CallbackDataSourceDesc extends DataSourceDesc { - private DataSourceCallback mDataSourceCallback; - - CallbackDataSourceDesc(String mediaId, long startPositionMs, long endPositionMs, - DataSourceCallback dataSourceCallback) { - super(mediaId, startPositionMs, endPositionMs); - mDataSourceCallback = dataSourceCallback; - } - - /** - * Return the DataSourceCallback of this data source. - * @return the DataSourceCallback of this data source - */ - public @NonNull DataSourceCallback getDataSourceCallback() { - return mDataSourceCallback; - } -} diff --git a/media/apex/java/android/media/DataSourceCallback.java b/media/apex/java/android/media/DataSourceCallback.java index 6515bd6a2c09..c297ecda249c 100644 --- a/media/apex/java/android/media/DataSourceCallback.java +++ b/media/apex/java/android/media/DataSourceCallback.java @@ -32,8 +32,12 @@ import java.io.IOException; * you don't need to do your own synchronization unless you're modifying the * DataSourceCallback from another thread while it's being used by the framework.</p> * + * @hide */ public abstract class DataSourceCallback implements Closeable { + + public static final int END_OF_STREAM = -1; + /** * Called to request data from the given position. * @@ -49,7 +53,7 @@ public abstract class DataSourceCallback implements Closeable { * @param offset the offset within buffer to read the data into. * @param size the number of bytes to read. * @throws IOException on fatal errors. - * @return the number of bytes read, or -1 if end of stream is reached. + * @return the number of bytes read, or {@link #END_OF_STREAM} if end of stream is reached. */ public abstract int readAt(long position, @NonNull byte[] buffer, int offset, int size) throws IOException; diff --git a/media/apex/java/android/media/DataSourceDesc.java b/media/apex/java/android/media/DataSourceDesc.java index be80c2255844..d00ff2a70955 100644 --- a/media/apex/java/android/media/DataSourceDesc.java +++ b/media/apex/java/android/media/DataSourceDesc.java @@ -125,7 +125,6 @@ public class DataSourceDesc { private static final int SOURCE_TYPE_UNKNOWN = 0; private static final int SOURCE_TYPE_URI = 1; private static final int SOURCE_TYPE_FILE = 2; - private static final int SOURCE_TYPE_CALLBACK = 3; private int mSourceType = SOURCE_TYPE_UNKNOWN; private String mMediaId; @@ -142,9 +141,6 @@ public class DataSourceDesc { private long mOffset = 0; private long mLength = FileDataSourceDesc.FD_LENGTH_UNKNOWN; - // For CallbackDataSourceDesc - private DataSourceCallback mDataSourceCallback; - /** * Constructs a new BuilderBase with the defaults. */ @@ -173,9 +169,6 @@ public class DataSourceDesc { mUri = ((UriDataSourceDesc) dsd).getUri(); mHeader = ((UriDataSourceDesc) dsd).getHeaders(); mCookies = ((UriDataSourceDesc) dsd).getCookies(); - } else if (dsd instanceof CallbackDataSourceDesc) { - mSourceType = SOURCE_TYPE_CALLBACK; - mDataSourceCallback = ((CallbackDataSourceDesc) dsd).getDataSourceCallback(); } else { throw new IllegalStateException("Unknown source type:" + mSourceType); } @@ -204,9 +197,6 @@ public class DataSourceDesc { } else if (mSourceType == SOURCE_TYPE_URI) { desc = new UriDataSourceDesc( mMediaId, mStartPositionMs, mEndPositionMs, mUri, mHeader, mCookies); - } else if (mSourceType == SOURCE_TYPE_CALLBACK) { - desc = new CallbackDataSourceDesc( - mMediaId, mStartPositionMs, mEndPositionMs, mDataSourceCallback); } else { throw new IllegalStateException("Unknown source type:" + mSourceType); } @@ -326,7 +316,7 @@ public class DataSourceDesc { /** * Sets the data source (ParcelFileDescriptor) to use. The ParcelFileDescriptor must be - * seekable (N.B. a LocalSocket is not seekable). When the {@link FileDataSourceDesc} + * seekable (N.B. a LocalSocket is not seekable). When the {@link DataSourceDesc} * created by this builder is passed to {@link MediaPlayer2} via * {@link MediaPlayer2#setDataSource}, * {@link MediaPlayer2#setNextDataSource} or @@ -347,7 +337,7 @@ public class DataSourceDesc { /** * Sets the data source (ParcelFileDescriptor) to use. The ParcelFileDescriptor must be - * seekable (N.B. a LocalSocket is not seekable). When the {@link FileDataSourceDesc} + * seekable (N.B. a LocalSocket is not seekable). When the {@link DataSourceDesc} * created by this builder is passed to {@link MediaPlayer2} via * {@link MediaPlayer2#setDataSource}, * {@link MediaPlayer2#setNextDataSource} or @@ -367,7 +357,9 @@ public class DataSourceDesc { public Builder setDataSource( @NonNull ParcelFileDescriptor pfd, long offset, long length) { setSourceType(SOURCE_TYPE_FILE); - Media2Utils.checkArgument(pfd != null, "pfd cannot be null."); + if (pfd == null) { + throw new NullPointerException("pfd cannot be null."); + } if (offset < 0) { offset = 0; } @@ -380,20 +372,6 @@ public class DataSourceDesc { return this; } - /** - * Sets the data source (DataSourceCallback) to use. - * - * @param dscb the DataSourceCallback for the media to play - * @return the same Builder instance. - * @throws NullPointerException if dscb is null. - */ - public @NonNull Builder setDataSource(@NonNull DataSourceCallback dscb) { - setSourceType(SOURCE_TYPE_CALLBACK); - Media2Utils.checkArgument(dscb != null, "data source cannot be null."); - mDataSourceCallback = dscb; - return this; - } - private void setSourceType(int type) { if (mSourceType != SOURCE_TYPE_UNKNOWN) { throw new IllegalStateException("Source is already set. type=" + mSourceType); diff --git a/media/apex/java/android/media/MediaPlayer2.java b/media/apex/java/android/media/MediaPlayer2.java index 68a46ed5b8b8..21b1167aadb0 100644 --- a/media/apex/java/android/media/MediaPlayer2.java +++ b/media/apex/java/android/media/MediaPlayer2.java @@ -878,22 +878,27 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { throws IOException { Media2Utils.checkArgument(dsd != null, "the DataSourceDesc cannot be null"); - if (dsd instanceof CallbackDataSourceDesc) { - CallbackDataSourceDesc cbDSD = (CallbackDataSourceDesc) dsd; - handleDataSource(isCurrent, - srcId, - cbDSD.getDataSourceCallback(), - cbDSD.getStartPosition(), - cbDSD.getEndPosition()); - } else if (dsd instanceof FileDataSourceDesc) { + if (dsd instanceof FileDataSourceDesc) { FileDataSourceDesc fileDSD = (FileDataSourceDesc) dsd; - handleDataSource(isCurrent, - srcId, - fileDSD.getParcelFileDescriptor(), - fileDSD.getOffset(), - fileDSD.getLength(), - fileDSD.getStartPosition(), - fileDSD.getEndPosition()); + ParcelFileDescriptor pfd = fileDSD.getParcelFileDescriptor(); + if (pfd.getStatSize() == -1) { + // Underlying pipeline doesn't understand '-1' size. Create a wrapper for + // translation. + // TODO: Make native code handle '-1' size. + handleDataSource(isCurrent, + srcId, + new ProxyDataSourceCallback(pfd), + fileDSD.getStartPosition(), + fileDSD.getEndPosition()); + } else { + handleDataSource(isCurrent, + srcId, + pfd, + fileDSD.getOffset(), + fileDSD.getLength(), + fileDSD.getStartPosition(), + fileDSD.getEndPosition()); + } } else if (dsd instanceof UriDataSourceDesc) { UriDataSourceDesc uriDSD = (UriDataSourceDesc) dsd; handleDataSource(isCurrent, diff --git a/media/apex/java/android/media/ProxyDataSourceCallback.java b/media/apex/java/android/media/ProxyDataSourceCallback.java new file mode 100644 index 000000000000..14d3ce87f03d --- /dev/null +++ b/media/apex/java/android/media/ProxyDataSourceCallback.java @@ -0,0 +1,68 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +import android.os.ParcelFileDescriptor; +import android.system.ErrnoException; +import android.system.Os; +import android.system.OsConstants; +import android.util.Log; + +import java.io.FileDescriptor; +import java.io.IOException; + +/** + * A DataSourceCallback that is backed by a ParcelFileDescriptor. + */ +class ProxyDataSourceCallback extends DataSourceCallback { + private static final String TAG = "TestDataSourceCallback"; + + ParcelFileDescriptor mPFD; + FileDescriptor mFD; + + ProxyDataSourceCallback(ParcelFileDescriptor pfd) throws IOException { + mPFD = pfd.dup(); + mFD = mPFD.getFileDescriptor(); + } + + @Override + public synchronized int readAt(long position, byte[] buffer, int offset, int size) + throws IOException { + try { + Os.lseek(mFD, position, OsConstants.SEEK_SET); + int ret = Os.read(mFD, buffer, offset, size); + return (ret == 0) ? END_OF_STREAM : ret; + } catch (ErrnoException e) { + throw new IOException(e); + } + } + + @Override + public synchronized long getSize() throws IOException { + return mPFD.getStatSize(); + } + + @Override + public synchronized void close() { + try { + mPFD.close(); + } catch (IOException e) { + Log.e(TAG, "Failed to close the PFD.", e); + } + } +} + |