use of com.google.android.exoplayer2.C in project ExoPlayer by google.
the class HlsMediaChunk method peekId3PrivTimestamp.
/**
* Peek the presentation timestamp of the first sample in the chunk from an ID3 PRIV as defined in
* the HLS spec, version 20, Section 3.4. Returns {@link C#TIME_UNSET} if the frame is not found.
* This method only modifies the peek position.
*
* @param input The {@link ExtractorInput} to obtain the PRIV frame from.
* @return The parsed, adjusted timestamp in microseconds
* @throws IOException If an error occurred peeking from the input.
*/
private long peekId3PrivTimestamp(ExtractorInput input) throws IOException {
input.resetPeekPosition();
try {
scratchId3Data.reset(Id3Decoder.ID3_HEADER_LENGTH);
input.peekFully(scratchId3Data.getData(), 0, Id3Decoder.ID3_HEADER_LENGTH);
} catch (EOFException e) {
// The input isn't long enough for there to be any ID3 data.
return C.TIME_UNSET;
}
int id = scratchId3Data.readUnsignedInt24();
if (id != Id3Decoder.ID3_TAG) {
return C.TIME_UNSET;
}
// version(2), flags(1).
scratchId3Data.skipBytes(3);
int id3Size = scratchId3Data.readSynchSafeInt();
int requiredCapacity = id3Size + Id3Decoder.ID3_HEADER_LENGTH;
if (requiredCapacity > scratchId3Data.capacity()) {
byte[] data = scratchId3Data.getData();
scratchId3Data.reset(requiredCapacity);
System.arraycopy(data, 0, scratchId3Data.getData(), 0, Id3Decoder.ID3_HEADER_LENGTH);
}
input.peekFully(scratchId3Data.getData(), Id3Decoder.ID3_HEADER_LENGTH, id3Size);
Metadata metadata = id3Decoder.decode(scratchId3Data.getData(), id3Size);
if (metadata == null) {
return C.TIME_UNSET;
}
int metadataLength = metadata.length();
for (int i = 0; i < metadataLength; i++) {
Metadata.Entry frame = metadata.get(i);
if (frame instanceof PrivFrame) {
PrivFrame privFrame = (PrivFrame) frame;
if (PRIV_TIMESTAMP_FRAME_OWNER.equals(privFrame.owner)) {
System.arraycopy(privFrame.privateData, 0, scratchId3Data.getData(), 0, 8);
scratchId3Data.setPosition(0);
scratchId3Data.setLimit(8);
// streaming provider forgot. See: https://github.com/google/ExoPlayer/pull/3495.
return scratchId3Data.readLong() & 0x1FFFFFFFFL;
}
}
}
return C.TIME_UNSET;
}
use of com.google.android.exoplayer2.C in project ExoPlayer by google.
the class TestUtil method seekToTimeUs.
/**
* Seeks to the given seek time of the stream from the given input, and keeps reading from the
* input until we can extract at least one sample following the seek position, or until
* end-of-input is reached.
*
* @param extractor The {@link Extractor} to extract from input.
* @param seekMap The {@link SeekMap} of the stream from the given input.
* @param seekTimeUs The seek time, in micro-seconds.
* @param trackOutput The {@link FakeTrackOutput} to store the extracted samples.
* @param dataSource The {@link DataSource} that will be used to read from the input.
* @param uri The Uri of the input.
* @return The index of the first extracted sample written to the given {@code trackOutput} after
* the seek is completed, or {@link C#INDEX_UNSET} if the seek is completed without any
* extracted sample.
*/
public static int seekToTimeUs(Extractor extractor, SeekMap seekMap, long seekTimeUs, DataSource dataSource, FakeTrackOutput trackOutput, Uri uri) throws IOException {
int numSampleBeforeSeek = trackOutput.getSampleCount();
SeekMap.SeekPoints seekPoints = seekMap.getSeekPoints(seekTimeUs);
long initialSeekLoadPosition = seekPoints.first.position;
extractor.seek(initialSeekLoadPosition, seekTimeUs);
PositionHolder positionHolder = new PositionHolder();
positionHolder.position = C.POSITION_UNSET;
ExtractorInput extractorInput = TestUtil.getExtractorInputFromPosition(dataSource, initialSeekLoadPosition, uri);
int extractorReadResult = Extractor.RESULT_CONTINUE;
while (true) {
try {
// Keep reading until we can read at least one sample after seek
while (extractorReadResult == Extractor.RESULT_CONTINUE && trackOutput.getSampleCount() == numSampleBeforeSeek) {
extractorReadResult = extractor.read(extractorInput, positionHolder);
}
} finally {
DataSourceUtil.closeQuietly(dataSource);
}
if (extractorReadResult == Extractor.RESULT_SEEK) {
extractorInput = TestUtil.getExtractorInputFromPosition(dataSource, positionHolder.position, uri);
extractorReadResult = Extractor.RESULT_CONTINUE;
} else if (extractorReadResult == Extractor.RESULT_END_OF_INPUT && trackOutput.getSampleCount() == numSampleBeforeSeek) {
return C.INDEX_UNSET;
} else if (trackOutput.getSampleCount() > numSampleBeforeSeek) {
// First index after seek = num sample before seek.
return numSampleBeforeSeek;
}
}
}
use of com.google.android.exoplayer2.C in project Slide by ccrama.
the class Reddit method setDefaultErrorHandler.
public static void setDefaultErrorHandler(Context base) {
// START code adapted from https://github.com/QuantumBadger/RedReader/
final Thread.UncaughtExceptionHandler androidHandler = Thread.getDefaultUncaughtExceptionHandler();
final WeakReference<Context> cont = new WeakReference<>(base);
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread thread, Throwable t) {
if (cont.get() != null) {
final Context c = cont.get();
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
t.printStackTrace(printWriter);
String stacktrace = writer.toString().replace(";", ",");
if (stacktrace.contains("UnknownHostException") || stacktrace.contains("SocketTimeoutException") || stacktrace.contains("ConnectException")) {
// is offline
final Handler mHandler = new Handler(Looper.getMainLooper());
mHandler.post(new Runnable() {
@Override
public void run() {
try {
new AlertDialog.Builder(c).setTitle(R.string.err_title).setMessage(R.string.err_connection_failed_msg).setNegativeButton(R.string.btn_close, (dialog, which) -> {
if (!(c instanceof MainActivity)) {
((Activity) c).finish();
}
}).setPositiveButton(R.string.btn_offline, (dialog, which) -> {
Reddit.appRestart.edit().putBoolean("forceoffline", true).apply();
Reddit.forceRestart(c, false);
}).show();
} catch (Exception ignored) {
}
}
});
} else if (stacktrace.contains("403 Forbidden") || stacktrace.contains("401 Unauthorized")) {
// Un-authenticated
final Handler mHandler = new Handler(Looper.getMainLooper());
mHandler.post(new Runnable() {
@Override
public void run() {
try {
new AlertDialog.Builder(c).setTitle(R.string.err_title).setMessage(R.string.err_refused_request_msg).setNegativeButton("No", (dialog, which) -> {
if (!(c instanceof MainActivity)) {
((Activity) c).finish();
}
}).setPositiveButton("Yes", (dialog, which) -> authentication.updateToken(c)).show();
} catch (Exception ignored) {
}
}
});
} else if (stacktrace.contains("404 Not Found") || stacktrace.contains("400 Bad Request")) {
final Handler mHandler = new Handler(Looper.getMainLooper());
mHandler.post(new Runnable() {
@Override
public void run() {
try {
new AlertDialog.Builder(c).setTitle(R.string.err_title).setMessage(R.string.err_could_not_find_content_msg).setNegativeButton("Close", (dialog, which) -> {
if (!(c instanceof MainActivity)) {
((Activity) c).finish();
}
}).show();
} catch (Exception ignored) {
}
}
});
} else if (t instanceof NetworkException) {
Toast.makeText(c, "Error " + ((NetworkException) t).getResponse().getStatusMessage() + ": " + (t).getMessage(), Toast.LENGTH_LONG).show();
} else if (t instanceof NullPointerException && t.getMessage().contains("Attempt to invoke virtual method 'android.content.Context android.view.ViewGroup.getContext()' on a null object reference")) {
t.printStackTrace();
} else if (t instanceof WindowManager.BadTokenException) {
t.printStackTrace();
} else if (t instanceof IllegalArgumentException && t.getMessage().contains("pointerIndex out of range")) {
t.printStackTrace();
} else {
appRestart.edit().putString("startScreen", "a").apply();
try {
SharedPreferences prefs = c.getSharedPreferences("STACKTRACE", Context.MODE_PRIVATE);
prefs.edit().putString("stacktrace", stacktrace).apply();
} catch (Throwable ignored) {
}
androidHandler.uncaughtException(thread, t);
}
} else {
androidHandler.uncaughtException(thread, t);
}
}
});
// END adaptation
}
use of com.google.android.exoplayer2.C in project ExoPlayer by google.
the class MappingTrackSelector method maybeConfigureRenderersForTunneling.
/**
* Determines whether tunneling should be enabled, replacing {@link RendererConfiguration}s in
* {@code rendererConfigurations} with configurations that enable tunneling on the appropriate
* renderers if so.
*
* @param rendererCapabilities The {@link RendererCapabilities} of the renderers for which
* {@link TrackSelection}s are to be generated.
* @param rendererTrackGroupArrays An array of {@link TrackGroupArray}s where each entry
* corresponds to the renderer of equal index in {@code renderers}.
* @param rendererFormatSupports Maps every available track to a specific level of support as
* defined by the renderer {@code FORMAT_*} constants.
* @param rendererConfigurations The renderer configurations. Configurations may be replaced with
* ones that enable tunneling as a result of this call.
* @param trackSelections The renderer track selections.
* @param tunnelingAudioSessionId The audio session id to use when tunneling, or
* {@link C#AUDIO_SESSION_ID_UNSET} if tunneling should not be enabled.
*/
private static void maybeConfigureRenderersForTunneling(RendererCapabilities[] rendererCapabilities, TrackGroupArray[] rendererTrackGroupArrays, int[][][] rendererFormatSupports, RendererConfiguration[] rendererConfigurations, TrackSelection[] trackSelections, int tunnelingAudioSessionId) {
if (tunnelingAudioSessionId == C.AUDIO_SESSION_ID_UNSET) {
return;
}
// Check whether we can enable tunneling. To enable tunneling we require exactly one audio and
// one video renderer to support tunneling and have a selection.
int tunnelingAudioRendererIndex = -1;
int tunnelingVideoRendererIndex = -1;
boolean enableTunneling = true;
for (int i = 0; i < rendererCapabilities.length; i++) {
int rendererType = rendererCapabilities[i].getTrackType();
TrackSelection trackSelection = trackSelections[i];
if ((rendererType == C.TRACK_TYPE_AUDIO || rendererType == C.TRACK_TYPE_VIDEO) && trackSelection != null) {
if (rendererSupportsTunneling(rendererFormatSupports[i], rendererTrackGroupArrays[i], trackSelection)) {
if (rendererType == C.TRACK_TYPE_AUDIO) {
if (tunnelingAudioRendererIndex != -1) {
enableTunneling = false;
break;
} else {
tunnelingAudioRendererIndex = i;
}
} else {
if (tunnelingVideoRendererIndex != -1) {
enableTunneling = false;
break;
} else {
tunnelingVideoRendererIndex = i;
}
}
}
}
}
enableTunneling &= tunnelingAudioRendererIndex != -1 && tunnelingVideoRendererIndex != -1;
if (enableTunneling) {
RendererConfiguration tunnelingRendererConfiguration = new RendererConfiguration(tunnelingAudioSessionId);
rendererConfigurations[tunnelingAudioRendererIndex] = tunnelingRendererConfiguration;
rendererConfigurations[tunnelingVideoRendererIndex] = tunnelingRendererConfiguration;
}
}
use of com.google.android.exoplayer2.C in project ExoPlayer by google.
the class EventSampleStreamTest method readDataOutOfBoundReturnEndOfStreamAfterFormatForNonDynamicEventSampleStream.
/**
* Tests that a non-dynamic {@link EventSampleStream} will return a buffer with {@link
* C#BUFFER_FLAG_END_OF_STREAM} when trying to read sample out-of-bound.
*/
@Test
public void readDataOutOfBoundReturnEndOfStreamAfterFormatForNonDynamicEventSampleStream() {
EventStream eventStream = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, new long[0], new EventMessage[0]);
EventSampleStream sampleStream = new EventSampleStream(eventStream, FORMAT, false);
// first read - read format
readData(sampleStream);
int result = readData(sampleStream);
assertThat(result).isEqualTo(C.RESULT_BUFFER_READ);
assertThat(inputBuffer.isEndOfStream()).isTrue();
}
Aggregations