1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.android.exoplayer2.extractor; 17 18 import androidx.annotation.Nullable; 19 import com.google.android.exoplayer2.C; 20 import com.google.android.exoplayer2.util.Assertions; 21 22 /** 23 * Maps seek positions (in microseconds) to corresponding positions (byte offsets) in the stream. 24 */ 25 public interface SeekMap { 26 27 /** A {@link SeekMap} that does not support seeking. */ 28 class Unseekable implements SeekMap { 29 30 private final long durationUs; 31 private final SeekPoints startSeekPoints; 32 33 /** 34 * @param durationUs The duration of the stream in microseconds, or {@link C#TIME_UNSET} if the 35 * duration is unknown. 36 */ Unseekable(long durationUs)37 public Unseekable(long durationUs) { 38 this(durationUs, 0); 39 } 40 41 /** 42 * @param durationUs The duration of the stream in microseconds, or {@link C#TIME_UNSET} if the 43 * duration is unknown. 44 * @param startPosition The position (byte offset) of the start of the media. 45 */ Unseekable(long durationUs, long startPosition)46 public Unseekable(long durationUs, long startPosition) { 47 this.durationUs = durationUs; 48 startSeekPoints = 49 new SeekPoints(startPosition == 0 ? SeekPoint.START : new SeekPoint(0, startPosition)); 50 } 51 52 @Override isSeekable()53 public boolean isSeekable() { 54 return false; 55 } 56 57 @Override getDurationUs()58 public long getDurationUs() { 59 return durationUs; 60 } 61 62 @Override getSeekPoints(long timeUs)63 public SeekPoints getSeekPoints(long timeUs) { 64 return startSeekPoints; 65 } 66 } 67 68 /** Contains one or two {@link SeekPoint}s. */ 69 final class SeekPoints { 70 71 /** The first seek point. */ 72 public final SeekPoint first; 73 /** The second seek point, or {@link #first} if there's only one seek point. */ 74 public final SeekPoint second; 75 76 /** @param point The single seek point. */ SeekPoints(SeekPoint point)77 public SeekPoints(SeekPoint point) { 78 this(point, point); 79 } 80 81 /** 82 * @param first The first seek point. 83 * @param second The second seek point. 84 */ SeekPoints(SeekPoint first, SeekPoint second)85 public SeekPoints(SeekPoint first, SeekPoint second) { 86 this.first = Assertions.checkNotNull(first); 87 this.second = Assertions.checkNotNull(second); 88 } 89 90 @Override toString()91 public String toString() { 92 return "[" + first + (first.equals(second) ? "" : (", " + second)) + "]"; 93 } 94 95 @Override equals(@ullable Object obj)96 public boolean equals(@Nullable Object obj) { 97 if (this == obj) { 98 return true; 99 } 100 if (obj == null || getClass() != obj.getClass()) { 101 return false; 102 } 103 SeekPoints other = (SeekPoints) obj; 104 return first.equals(other.first) && second.equals(other.second); 105 } 106 107 @Override hashCode()108 public int hashCode() { 109 return (31 * first.hashCode()) + second.hashCode(); 110 } 111 } 112 113 /** 114 * Returns whether seeking is supported. 115 * 116 * @return Whether seeking is supported. 117 */ isSeekable()118 boolean isSeekable(); 119 120 /** 121 * Returns the duration of the stream in microseconds. 122 * 123 * @return The duration of the stream in microseconds, or {@link C#TIME_UNSET} if the duration is 124 * unknown. 125 */ getDurationUs()126 long getDurationUs(); 127 128 /** 129 * Obtains seek points for the specified seek time in microseconds. The returned {@link 130 * SeekPoints} will contain one or two distinct seek points. 131 * 132 * <p>Two seek points [A, B] are returned in the case that seeking can only be performed to 133 * discrete points in time, there does not exist a seek point at exactly the requested time, and 134 * there exist seek points on both sides of it. In this case A and B are the closest seek points 135 * before and after the requested time. A single seek point is returned in all other cases. 136 * 137 * @param timeUs A seek time in microseconds. 138 * @return The corresponding seek points. 139 */ getSeekPoints(long timeUs)140 SeekPoints getSeekPoints(long timeUs); 141 } 142