kopia lustrzana https://github.com/ryukoposting/Signal-Android
Create a SignalDataSource class for all of our ExoPlayer needs.
Also fixes an issue around GIF playback within a conversation.fork-5.53.8
rodzic
6f6da699a3
commit
d5fbd10406
|
@ -5,12 +5,12 @@ import com.google.android.exoplayer2.C
|
||||||
import com.google.android.exoplayer2.DefaultLoadControl
|
import com.google.android.exoplayer2.DefaultLoadControl
|
||||||
import com.google.android.exoplayer2.ForwardingPlayer
|
import com.google.android.exoplayer2.ForwardingPlayer
|
||||||
import com.google.android.exoplayer2.SimpleExoPlayer
|
import com.google.android.exoplayer2.SimpleExoPlayer
|
||||||
import org.thoughtcrime.securesms.video.exo.AttachmentMediaSourceFactory
|
import org.thoughtcrime.securesms.video.exo.SignalMediaSourceFactory
|
||||||
|
|
||||||
class VoiceNotePlayer @JvmOverloads constructor(
|
class VoiceNotePlayer @JvmOverloads constructor(
|
||||||
context: Context,
|
context: Context,
|
||||||
val internalPlayer: SimpleExoPlayer = SimpleExoPlayer.Builder(context)
|
val internalPlayer: SimpleExoPlayer = SimpleExoPlayer.Builder(context)
|
||||||
.setMediaSourceFactory(AttachmentMediaSourceFactory(context))
|
.setMediaSourceFactory(SignalMediaSourceFactory(context))
|
||||||
.setLoadControl(
|
.setLoadControl(
|
||||||
DefaultLoadControl.Builder()
|
DefaultLoadControl.Builder()
|
||||||
.setBufferDurationsMs(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE)
|
.setBufferDurationsMs(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE)
|
||||||
|
|
|
@ -389,6 +389,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||||
int defaultTopMargin = readDimen(R.dimen.message_bubble_default_footer_bottom_margin);
|
int defaultTopMargin = readDimen(R.dimen.message_bubble_default_footer_bottom_margin);
|
||||||
int defaultBottomMargin = readDimen(R.dimen.message_bubble_bottom_padding);
|
int defaultBottomMargin = readDimen(R.dimen.message_bubble_bottom_padding);
|
||||||
int collapsedBottomMargin = readDimen(R.dimen.message_bubble_collapsed_bottom_padding);
|
int collapsedBottomMargin = readDimen(R.dimen.message_bubble_collapsed_bottom_padding);
|
||||||
|
|
||||||
if (!updatingFooter &&
|
if (!updatingFooter &&
|
||||||
getActiveFooter(messageRecord) == footer &&
|
getActiveFooter(messageRecord) == footer &&
|
||||||
!hasAudio(messageRecord) &&
|
!hasAudio(messageRecord) &&
|
||||||
|
@ -400,11 +401,13 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||||
int footerWidth = footer.getMeasuredWidth();
|
int footerWidth = footer.getMeasuredWidth();
|
||||||
int availableWidth = getAvailableMessageBubbleWidth(bodyText);
|
int availableWidth = getAvailableMessageBubbleWidth(bodyText);
|
||||||
int collapsedTopMargin = -1 * (dateView.getMeasuredHeight() + ViewUtil.dpToPx(4));
|
int collapsedTopMargin = -1 * (dateView.getMeasuredHeight() + ViewUtil.dpToPx(4));
|
||||||
|
|
||||||
if (bodyText.isSingleLine()) {
|
if (bodyText.isSingleLine()) {
|
||||||
int maxBubbleWidth = hasBigImageLinkPreview(messageRecord) || hasThumbnail(messageRecord) ? readDimen(R.dimen.media_bubble_max_width) : getMaxBubbleWidth();
|
int maxBubbleWidth = hasBigImageLinkPreview(messageRecord) || hasThumbnail(messageRecord) ? readDimen(R.dimen.media_bubble_max_width) : getMaxBubbleWidth();
|
||||||
int bodyMargins = ViewUtil.getLeftMargin(bodyText) + ViewUtil.getRightMargin(bodyText);
|
int bodyMargins = ViewUtil.getLeftMargin(bodyText) + ViewUtil.getRightMargin(bodyText);
|
||||||
int sizeWithMargins = bodyText.getMeasuredWidth() + ViewUtil.dpToPx(6) + footerWidth + bodyMargins;
|
int sizeWithMargins = bodyText.getMeasuredWidth() + ViewUtil.dpToPx(6) + footerWidth + bodyMargins;
|
||||||
int minSize = Math.min(maxBubbleWidth, Math.max(bodyText.getMeasuredWidth() + ViewUtil.dpToPx(6) + footerWidth + bodyMargins, bodyBubble.getMeasuredWidth()));
|
int minSize = Math.min(maxBubbleWidth, Math.max(bodyText.getMeasuredWidth() + ViewUtil.dpToPx(6) + footerWidth + bodyMargins, bodyBubble.getMeasuredWidth()));
|
||||||
|
|
||||||
if (hasQuote(messageRecord) && sizeWithMargins < availableWidth) {
|
if (hasQuote(messageRecord) && sizeWithMargins < availableWidth) {
|
||||||
ViewUtil.setTopMargin(footer, collapsedTopMargin);
|
ViewUtil.setTopMargin(footer, collapsedTopMargin);
|
||||||
ViewUtil.setBottomMargin(footer, collapsedBottomMargin);
|
ViewUtil.setBottomMargin(footer, collapsedBottomMargin);
|
||||||
|
@ -418,6 +421,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||||
updatingFooter = true;
|
updatingFooter = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!updatingFooter && bodyText.getLastLineWidth() + ViewUtil.dpToPx(6) + footerWidth <= bodyText.getMeasuredWidth()) {
|
if (!updatingFooter && bodyText.getLastLineWidth() + ViewUtil.dpToPx(6) + footerWidth <= bodyText.getMeasuredWidth()) {
|
||||||
ViewUtil.setTopMargin(footer, collapsedTopMargin);
|
ViewUtil.setTopMargin(footer, collapsedTopMargin);
|
||||||
ViewUtil.setBottomMargin(footer, collapsedBottomMargin);
|
ViewUtil.setBottomMargin(footer, collapsedBottomMargin);
|
||||||
|
@ -1044,9 +1048,9 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||||
mediaThumbnailStub.require().setMinimumThumbnailWidth(readDimen(isCaptionlessMms(messageRecord) ? R.dimen.media_bubble_min_width_solo
|
mediaThumbnailStub.require().setMinimumThumbnailWidth(readDimen(isCaptionlessMms(messageRecord) ? R.dimen.media_bubble_min_width_solo
|
||||||
: R.dimen.media_bubble_min_width_with_content));
|
: R.dimen.media_bubble_min_width_with_content));
|
||||||
mediaThumbnailStub.require().setImageResource(glideRequests,
|
mediaThumbnailStub.require().setImageResource(glideRequests,
|
||||||
thumbnailSlides,
|
thumbnailSlides,
|
||||||
showControls,
|
showControls,
|
||||||
false);
|
false);
|
||||||
mediaThumbnailStub.require().setThumbnailClickListener(new ThumbnailClickListener());
|
mediaThumbnailStub.require().setThumbnailClickListener(new ThumbnailClickListener());
|
||||||
mediaThumbnailStub.require().setDownloadClickListener(downloadClickListener);
|
mediaThumbnailStub.require().setDownloadClickListener(downloadClickListener);
|
||||||
mediaThumbnailStub.require().setOnLongClickListener(passthroughClickListener);
|
mediaThumbnailStub.require().setOnLongClickListener(passthroughClickListener);
|
||||||
|
|
|
@ -15,7 +15,7 @@ import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.net.ContentProxySelector;
|
import org.thoughtcrime.securesms.net.ContentProxySelector;
|
||||||
import org.thoughtcrime.securesms.video.exo.ChunkedDataSourceFactory;
|
import org.thoughtcrime.securesms.video.exo.SignalDataSource;
|
||||||
|
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ final class GiphyMp4ExoPlayerProvider implements DefaultLifecycleObserver {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final OkHttpClient okHttpClient = ApplicationDependencies.getOkHttpClient().newBuilder().proxySelector(new ContentProxySelector()).build();
|
private final OkHttpClient okHttpClient = ApplicationDependencies.getOkHttpClient().newBuilder().proxySelector(new ContentProxySelector()).build();
|
||||||
private final DataSource.Factory dataSourceFactory = new ChunkedDataSourceFactory(okHttpClient, null);
|
private final DataSource.Factory dataSourceFactory = new SignalDataSource.Factory(ApplicationDependencies.getApplication(), okHttpClient, null);
|
||||||
private final MediaSourceFactory mediaSourceFactory = new ProgressiveMediaSource.Factory(dataSourceFactory);
|
private final MediaSourceFactory mediaSourceFactory = new ProgressiveMediaSource.Factory(dataSourceFactory);
|
||||||
|
|
||||||
GiphyMp4ExoPlayerProvider(@NonNull Context context) {
|
GiphyMp4ExoPlayerProvider(@NonNull Context context) {
|
||||||
|
|
|
@ -27,7 +27,6 @@ import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.MediaItem;
|
import com.google.android.exoplayer2.MediaItem;
|
||||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
|
||||||
import com.google.android.exoplayer2.PlaybackException;
|
import com.google.android.exoplayer2.PlaybackException;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||||
|
@ -36,12 +35,13 @@ import com.google.android.exoplayer2.source.MediaSourceFactory;
|
||||||
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
|
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
|
||||||
import com.google.android.exoplayer2.ui.PlayerControlView;
|
import com.google.android.exoplayer2.ui.PlayerControlView;
|
||||||
import com.google.android.exoplayer2.ui.PlayerView;
|
import com.google.android.exoplayer2.ui.PlayerView;
|
||||||
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||||
|
|
||||||
import org.signal.core.util.logging.Log;
|
import org.signal.core.util.logging.Log;
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.mms.VideoSlide;
|
import org.thoughtcrime.securesms.mms.VideoSlide;
|
||||||
import org.thoughtcrime.securesms.video.exo.AttachmentDataSourceFactory;
|
import org.thoughtcrime.securesms.video.exo.SignalDataSource;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -86,9 +86,8 @@ public class VideoPlayer extends FrameLayout {
|
||||||
Context context = getContext();
|
Context context = getContext();
|
||||||
|
|
||||||
if (exoPlayer == null) {
|
if (exoPlayer == null) {
|
||||||
DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(context, "GenericUserAgent", null);
|
DataSource.Factory attachmentDataSourceFactory = new SignalDataSource.Factory(context, null, null);
|
||||||
AttachmentDataSourceFactory attachmentDataSourceFactory = new AttachmentDataSourceFactory(context, defaultDataSourceFactory, null);
|
MediaSourceFactory mediaSourceFactory = new DefaultMediaSourceFactory(attachmentDataSourceFactory);
|
||||||
MediaSourceFactory mediaSourceFactory = new DefaultMediaSourceFactory(attachmentDataSourceFactory);
|
|
||||||
|
|
||||||
exoPlayer = new SimpleExoPlayer.Builder(context).setMediaSourceFactory(mediaSourceFactory).build();
|
exoPlayer = new SimpleExoPlayer.Builder(context).setMediaSourceFactory(mediaSourceFactory).build();
|
||||||
exoPlayer.addListener(new ExoPlayerListener(this, window, playerStateCallback, playerPositionDiscontinuityCallback));
|
exoPlayer.addListener(new ExoPlayerListener(this, window, playerStateCallback, playerPositionDiscontinuityCallback));
|
||||||
|
|
|
@ -1,70 +0,0 @@
|
||||||
package org.thoughtcrime.securesms.video.exo;
|
|
||||||
|
|
||||||
|
|
||||||
import android.net.Uri;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
|
||||||
import com.google.android.exoplayer2.upstream.DefaultDataSource;
|
|
||||||
import com.google.android.exoplayer2.upstream.TransferListener;
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
|
||||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class AttachmentDataSource implements DataSource {
|
|
||||||
|
|
||||||
private final DefaultDataSource defaultDataSource;
|
|
||||||
private final PartDataSource partDataSource;
|
|
||||||
private final BlobDataSource blobDataSource;
|
|
||||||
|
|
||||||
private DataSource dataSource;
|
|
||||||
|
|
||||||
public AttachmentDataSource(DefaultDataSource defaultDataSource,
|
|
||||||
PartDataSource partDataSource,
|
|
||||||
BlobDataSource blobDataSource)
|
|
||||||
{
|
|
||||||
this.defaultDataSource = defaultDataSource;
|
|
||||||
this.partDataSource = partDataSource;
|
|
||||||
this.blobDataSource = blobDataSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addTransferListener(@NonNull TransferListener transferListener) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long open(DataSpec dataSpec) throws IOException {
|
|
||||||
if (BlobProvider.isAuthority(dataSpec.uri)) dataSource = blobDataSource;
|
|
||||||
else if (PartAuthority.isLocalUri(dataSpec.uri)) dataSource = partDataSource;
|
|
||||||
else dataSource = defaultDataSource;
|
|
||||||
|
|
||||||
return dataSource.open(dataSpec);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read(@NonNull byte[] buffer, int offset, int readLength) throws IOException {
|
|
||||||
return dataSource.read(buffer, offset, readLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Uri getUri() {
|
|
||||||
return dataSource.getUri();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NonNull Map<String, List<String>> getResponseHeaders() {
|
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
dataSource.close();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
package org.thoughtcrime.securesms.video.exo;
|
|
||||||
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
|
||||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
|
||||||
import com.google.android.exoplayer2.upstream.TransferListener;
|
|
||||||
|
|
||||||
public class AttachmentDataSourceFactory implements DataSource.Factory {
|
|
||||||
|
|
||||||
private final Context context;
|
|
||||||
|
|
||||||
private final DefaultDataSourceFactory defaultDataSourceFactory;
|
|
||||||
private final TransferListener listener;
|
|
||||||
|
|
||||||
public AttachmentDataSourceFactory(@NonNull Context context,
|
|
||||||
@NonNull DefaultDataSourceFactory defaultDataSourceFactory,
|
|
||||||
@Nullable TransferListener listener)
|
|
||||||
{
|
|
||||||
this.context = context;
|
|
||||||
this.defaultDataSourceFactory = defaultDataSourceFactory;
|
|
||||||
this.listener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NonNull AttachmentDataSource createDataSource() {
|
|
||||||
return new AttachmentDataSource(defaultDataSourceFactory.createDataSource(),
|
|
||||||
new PartDataSource(context, listener),
|
|
||||||
new BlobDataSource(context, listener));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -20,7 +20,7 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class BlobDataSource implements DataSource {
|
class BlobDataSource implements DataSource {
|
||||||
|
|
||||||
private final @NonNull Context context;
|
private final @NonNull Context context;
|
||||||
private final @Nullable TransferListener listener;
|
private final @Nullable TransferListener listener;
|
||||||
|
|
|
@ -27,7 +27,7 @@ import okhttp3.OkHttpClient;
|
||||||
/**
|
/**
|
||||||
* DataSource which utilizes ChunkedDataFetcher to download video content via Signal content proxy.
|
* DataSource which utilizes ChunkedDataFetcher to download video content via Signal content proxy.
|
||||||
*/
|
*/
|
||||||
public class ChunkedDataSource implements DataSource {
|
class ChunkedDataSource implements DataSource {
|
||||||
|
|
||||||
private final OkHttpClient okHttpClient;
|
private final OkHttpClient okHttpClient;
|
||||||
private final TransferListener transferListener;
|
private final TransferListener transferListener;
|
||||||
|
@ -138,5 +138,4 @@ public class ChunkedDataSource implements DataSource {
|
||||||
}
|
}
|
||||||
cacheEntry = null;
|
cacheEntry = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
package org.thoughtcrime.securesms.video.exo;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
|
||||||
import com.google.android.exoplayer2.upstream.TransferListener;
|
|
||||||
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
|
|
||||||
public class ChunkedDataSourceFactory implements DataSource.Factory {
|
|
||||||
|
|
||||||
private final OkHttpClient okHttpClient;
|
|
||||||
private final TransferListener listener;
|
|
||||||
|
|
||||||
public ChunkedDataSourceFactory(@NonNull OkHttpClient okHttpClient, @Nullable TransferListener listener) {
|
|
||||||
this.okHttpClient = okHttpClient;
|
|
||||||
this.listener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NonNull DataSource createDataSource() {
|
|
||||||
return new ChunkedDataSource(okHttpClient, listener);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,7 +23,7 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class PartDataSource implements DataSource {
|
class PartDataSource implements DataSource {
|
||||||
|
|
||||||
private final @NonNull Context context;
|
private final @NonNull Context context;
|
||||||
private final @Nullable TransferListener listener;
|
private final @Nullable TransferListener listener;
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
package org.thoughtcrime.securesms.video.exo;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
|
import com.google.android.exoplayer2.upstream.DefaultDataSource;
|
||||||
|
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||||
|
import com.google.android.exoplayer2.upstream.TransferListener;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||||
|
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Go-to {@link DataSource} that handles all of our various types of video sources.
|
||||||
|
* Will defer to other {@link DataSource}s depending on the URI.
|
||||||
|
*/
|
||||||
|
public class SignalDataSource implements DataSource {
|
||||||
|
|
||||||
|
private final DefaultDataSource defaultDataSource;
|
||||||
|
private final PartDataSource partDataSource;
|
||||||
|
private final BlobDataSource blobDataSource;
|
||||||
|
private final ChunkedDataSource chunkedDataSource;
|
||||||
|
|
||||||
|
private DataSource dataSource;
|
||||||
|
|
||||||
|
public SignalDataSource(@NonNull DefaultDataSource defaultDataSource,
|
||||||
|
@NonNull PartDataSource partDataSource,
|
||||||
|
@NonNull BlobDataSource blobDataSource,
|
||||||
|
@Nullable ChunkedDataSource chunkedDataSource)
|
||||||
|
{
|
||||||
|
this.defaultDataSource = defaultDataSource;
|
||||||
|
this.partDataSource = partDataSource;
|
||||||
|
this.blobDataSource = blobDataSource;
|
||||||
|
this.chunkedDataSource = chunkedDataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTransferListener(@NonNull TransferListener transferListener) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long open(DataSpec dataSpec) throws IOException {
|
||||||
|
if (BlobProvider.isAuthority(dataSpec.uri)) {
|
||||||
|
dataSource = blobDataSource;
|
||||||
|
} else if (PartAuthority.isLocalUri(dataSpec.uri)) {
|
||||||
|
dataSource = partDataSource;
|
||||||
|
} else if (chunkedDataSource != null && isRemoteUri(dataSpec.uri)) {
|
||||||
|
dataSource = chunkedDataSource;
|
||||||
|
} else {
|
||||||
|
dataSource = defaultDataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataSource.open(dataSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(@NonNull byte[] buffer, int offset, int readLength) throws IOException {
|
||||||
|
return dataSource.read(buffer, offset, readLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Uri getUri() {
|
||||||
|
return dataSource.getUri();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull Map<String, List<String>> getResponseHeaders() {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
dataSource.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isRemoteUri(@Nullable Uri uri) {
|
||||||
|
if (uri != null) {
|
||||||
|
String scheme = uri.getScheme();
|
||||||
|
return "http".equalsIgnoreCase(scheme) || "https".equalsIgnoreCase(scheme);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Factory implements DataSource.Factory {
|
||||||
|
private final Context context;
|
||||||
|
private final OkHttpClient okHttpClient;
|
||||||
|
private final TransferListener listener;
|
||||||
|
|
||||||
|
public Factory(@NonNull Context context,
|
||||||
|
@Nullable OkHttpClient okHttpClient,
|
||||||
|
@Nullable TransferListener listener)
|
||||||
|
{
|
||||||
|
this.context = context;
|
||||||
|
this.okHttpClient = okHttpClient;
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull SignalDataSource createDataSource() {
|
||||||
|
return new SignalDataSource(new DefaultDataSourceFactory(context, "GenericUserAgent", null).createDataSource(),
|
||||||
|
new PartDataSource(context, listener),
|
||||||
|
new BlobDataSource(context, listener),
|
||||||
|
okHttpClient != null ? new ChunkedDataSource(okHttpClient, listener) : null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ import com.google.android.exoplayer2.offline.StreamKey;
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
import com.google.android.exoplayer2.source.MediaSource;
|
||||||
import com.google.android.exoplayer2.source.MediaSourceFactory;
|
import com.google.android.exoplayer2.source.MediaSourceFactory;
|
||||||
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
|
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
|
||||||
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||||
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||||
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
|
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
|
||||||
|
@ -24,17 +25,16 @@ import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is responsible for creating a MediaSource object for a given Uri, using AttachmentDataSourceFactory
|
* This class is responsible for creating a MediaSource object for a given Uri, using {@link SignalDataSource.Factory}.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public final class AttachmentMediaSourceFactory implements MediaSourceFactory {
|
public final class SignalMediaSourceFactory implements MediaSourceFactory {
|
||||||
|
|
||||||
private final ProgressiveMediaSource.Factory progressiveMediaSourceFactory;
|
private final ProgressiveMediaSource.Factory progressiveMediaSourceFactory;
|
||||||
|
|
||||||
public AttachmentMediaSourceFactory(@NonNull Context context) {
|
public SignalMediaSourceFactory(@NonNull Context context) {
|
||||||
DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(context, "GenericUserAgent", null);
|
DataSource.Factory attachmentDataSourceFactory = new SignalDataSource.Factory(context, null, null);
|
||||||
AttachmentDataSourceFactory attachmentDataSourceFactory = new AttachmentDataSourceFactory(context, defaultDataSourceFactory, null);
|
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true);
|
||||||
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true);
|
|
||||||
|
|
||||||
progressiveMediaSourceFactory = new ProgressiveMediaSource.Factory(attachmentDataSourceFactory, extractorsFactory);
|
progressiveMediaSourceFactory = new ProgressiveMediaSource.Factory(attachmentDataSourceFactory, extractorsFactory);
|
||||||
}
|
}
|
Ładowanie…
Reference in New Issue