Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEC-10771 Dash Thumbnails #686

Merged
merged 39 commits into from
Mar 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
6ff02cc
add ImageTrack entity
giladna Feb 14, 2021
b7dfdaa
add getThumbnailInfo API
giladna Feb 14, 2021
6b20280
fox position in case of live stream
giladna Feb 15, 2021
b513d6d
Merge branch 'dev' into FEC-10771
giladna Feb 16, 2021
34201e4
standalone manifest parser
giladna Feb 21, 2021
3fef697
add parser
giladna Feb 21, 2021
0bd1909
fix image tracks build and clean up
giladna Feb 21, 2021
581c22d
avoid exo parsing error
giladna Feb 21, 2021
61cba03
fix npe - last selected index for image was not set.
giladna Feb 22, 2021
b1b44ae
test: Expose for vod Map<ImageRangeInfo, Rect> getVodThumbnailInfo();
giladna Feb 23, 2021
910c3cb
ThumbnailVodInfo cont
giladna Feb 23, 2021
dd0072a
- Made tile width to be calculated with Math.round
GouravSna Feb 23, 2021
06ef02e
- Remove Math.floor from tile height and width
GouravSna Feb 23, 2021
0f3364f
remove import
giladna Feb 25, 2021
dce63fa
format
giladna Feb 25, 2021
4b1b9c9
fix dash manifest is not received on time
giladna Feb 25, 2021
e430d6d
cleanup
giladna Feb 25, 2021
04c6994
remove imports
giladna Feb 25, 2021
9b301bf
rename methid getThumbnailVodInfo
giladna Feb 25, 2021
6d67a00
remove. public api getThumbnailVodInfo
giladna Mar 1, 2021
b6aed2f
- Firing imageTrackChanged after tracksAvailable
GouravSna Mar 1, 2021
c5b49e3
Merge branch 'dev' into FEC-10771_parser
giladna Mar 2, 2021
3ec54a7
Update PlayerDecoratorBase.java
giladna Mar 3, 2021
c5bf894
Update ExoPlayerWrapper.java
giladna Mar 3, 2021
30e9af0
clean up
giladna Mar 3, 2021
00345db
fix warning
giladna Mar 3, 2021
f5e8ecd
Update PlayerEngineWrapper.java
giladna Mar 3, 2021
5f5b9f9
Update Player.java
giladna Mar 3, 2021
fa76c99
remove import
giladna Mar 3, 2021
fec94ec
remove import
giladna Mar 3, 2021
bcc864a
fix imports
giladna Mar 3, 2021
c1bb425
cleanup
giladna Mar 3, 2021
9172e0a
Merge branch 'dev' into FEC-10771_parser
giladna Mar 7, 2021
c69aae5
cleanup
giladna Mar 7, 2021
fa54cd2
remove public modifier
giladna Mar 7, 2021
c87f3d8
cleanup
giladna Mar 8, 2021
a755a8d
getThumbnailInfo - position is optional now if not passed will be usi…
giladna Mar 8, 2021
89be1e6
Merge branch 'dev' into FEC-10771_parser
giladna Mar 15, 2021
622f3ec
code review changes
giladna Mar 16, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions playkit/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ dependencies {
// Ok is (optionally) used by ExoPlayer now
api 'com.squareup.okhttp3:okhttp:3.12.11'

def checkerframeworkVersion = '3.3.0'
def checkerframeworkCompatVersion = '2.5.0'

compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion
compileOnly 'org.checkerframework:checker-compat-qual:' + checkerframeworkCompatVersion

def guavaVersion = '27.1-android'

api ('com.google.guava:guava:' + guavaVersion) {
exclude group: 'org.checkerframework', module: 'checker-compat-qual'
}
// Tests
testImplementation 'junit:junit:4.12'
testImplementation 'org.hamcrest:hamcrest-library:1.3'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.kaltura.android.exoplayer2.dashmanifestparser;

import com.kaltura.android.exoplayer2.source.dash.manifest.Descriptor;
import com.kaltura.android.exoplayer2.source.dash.manifest.Representation;

import java.util.Collections;
import java.util.List;

/**
* Represents a set of interchangeable encoded versions of a media content component.
*/
public class CustomAdaptationSet {

/**
* Value of {@link #id} indicating no value is set.=
*/
public static final int ID_UNSET = -1;

/**
* A non-negative identifier for the adaptation set that's unique in the scope of its containing
* period, or {@link #ID_UNSET} if not specified.
*/
public final int id;

/**
* The type of the adaptation set. One of the {@link com.kaltura.android.exoplayer2.C}
* {@code TRACK_TYPE_*} constants.
*/
public final int type;

/**
* {@link Representation}s in the adaptation set.
*/
public final List<CustomRepresentation> representations;

/**
* Accessibility descriptors in the adaptation set.
*/
public final List<Descriptor> accessibilityDescriptors;

/** Essential properties in the adaptation set. */
public final List<Descriptor> essentialProperties;

/** Supplemental properties in the adaptation set. */
public final List<Descriptor> supplementalProperties;

/**
* @param id A non-negative identifier for the adaptation set that's unique in the scope of its
* containing period, or {@link #ID_UNSET} if not specified.
* @param type The type of the adaptation set. One of the {@link com.kaltura.android.exoplayer2.C}
* {@code TRACK_TYPE_*} constants.
* @param representations {@link Representation}s in the adaptation set.
* @param accessibilityDescriptors Accessibility descriptors in the adaptation set.
* @param essentialProperties Essential properties in the adaptation set.
* @param supplementalProperties Supplemental properties in the adaptation set.
*/
public CustomAdaptationSet(
int id,
int type,
List<CustomRepresentation> representations,
List<Descriptor> accessibilityDescriptors,
List<Descriptor> essentialProperties,
List<Descriptor> supplementalProperties) {
this.id = id;
this.type = type;
this.representations = Collections.unmodifiableList(representations);
this.accessibilityDescriptors = Collections.unmodifiableList(accessibilityDescriptors);
this.essentialProperties = Collections.unmodifiableList(essentialProperties);
this.supplementalProperties = Collections.unmodifiableList(supplementalProperties);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
package com.kaltura.android.exoplayer2.dashmanifestparser;

import android.net.Uri;
import androidx.annotation.Nullable;
import com.kaltura.android.exoplayer2.C;
import com.kaltura.android.exoplayer2.offline.FilterableManifest;
import com.kaltura.android.exoplayer2.offline.StreamKey;
import com.kaltura.android.exoplayer2.source.dash.manifest.ProgramInformation;
import com.kaltura.android.exoplayer2.source.dash.manifest.ServiceDescriptionElement;
import com.kaltura.android.exoplayer2.source.dash.manifest.UtcTimingElement;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
* Represents a DASH media presentation description (mpd), as defined by ISO/IEC 23009-1:2014
* Section 5.3.1.2.
*/
public class CustomDashManifest implements FilterableManifest<CustomDashManifest> {

/**
* The {@code availabilityStartTime} value in milliseconds since epoch, or {@link C#TIME_UNSET} if
* not present.
*/
public final long availabilityStartTimeMs;

/**
* The duration of the presentation in milliseconds, or {@link C#TIME_UNSET} if not applicable.
*/
public final long durationMs;

/**
* The {@code minBufferTime} value in milliseconds, or {@link C#TIME_UNSET} if not present.
*/
public final long minBufferTimeMs;

/**
* Whether the manifest has value "dynamic" for the {@code type} attribute.
*/
public final boolean dynamic;

/**
* The {@code minimumUpdatePeriod} value in milliseconds, or {@link C#TIME_UNSET} if not
* applicable.
*/
public final long minUpdatePeriodMs;

/**
* The {@code timeShiftBufferDepth} value in milliseconds, or {@link C#TIME_UNSET} if not
* present.
*/
public final long timeShiftBufferDepthMs;

/**
* The {@code suggestedPresentationDelay} value in milliseconds, or {@link C#TIME_UNSET} if not
* present.
*/
public final long suggestedPresentationDelayMs;

/**
* The {@code publishTime} value in milliseconds since epoch, or {@link C#TIME_UNSET} if
* not present.
*/
public final long publishTimeMs;

/**
* The {@link UtcTimingElement}, or null if not present. Defined in DVB A168:7/2016, Section
* 4.7.2.
*/
@Nullable public final UtcTimingElement utcTiming;

/** The {@link ServiceDescriptionElement}, or null if not present. */
@Nullable public final ServiceDescriptionElement serviceDescription;

/** The location of this manifest, or null if not present. */
@Nullable public final Uri location;

/** The {@link ProgramInformation}, or null if not present. */
@Nullable public final ProgramInformation programInformation;

private final List<CustomPeriod> periods;

/**
* @deprecated Use {@link #CustomDashManifest(long, long, long, boolean, long, long, long, long,
* ProgramInformation, UtcTimingElement, ServiceDescriptionElement, Uri, List)}.
*/
@Deprecated
public CustomDashManifest(
long availabilityStartTimeMs,
long durationMs,
long minBufferTimeMs,
boolean dynamic,
long minUpdatePeriodMs,
long timeShiftBufferDepthMs,
long suggestedPresentationDelayMs,
long publishTimeMs,
@Nullable UtcTimingElement utcTiming,
@Nullable Uri location,
List<CustomPeriod> periods) {
this(
availabilityStartTimeMs,
durationMs,
minBufferTimeMs,
dynamic,
minUpdatePeriodMs,
timeShiftBufferDepthMs,
suggestedPresentationDelayMs,
publishTimeMs,
/* programInformation= */ null,
utcTiming,
/* serviceDescription= */ null,
location,
periods);
}

public CustomDashManifest(
long availabilityStartTimeMs,
long durationMs,
long minBufferTimeMs,
boolean dynamic,
long minUpdatePeriodMs,
long timeShiftBufferDepthMs,
long suggestedPresentationDelayMs,
long publishTimeMs,
@Nullable ProgramInformation programInformation,
@Nullable UtcTimingElement utcTiming,
@Nullable ServiceDescriptionElement serviceDescription,
@Nullable Uri location,
List<CustomPeriod> periods) {
this.availabilityStartTimeMs = availabilityStartTimeMs;
this.durationMs = durationMs;
this.minBufferTimeMs = minBufferTimeMs;
this.dynamic = dynamic;
this.minUpdatePeriodMs = minUpdatePeriodMs;
this.timeShiftBufferDepthMs = timeShiftBufferDepthMs;
this.suggestedPresentationDelayMs = suggestedPresentationDelayMs;
this.publishTimeMs = publishTimeMs;
this.programInformation = programInformation;
this.utcTiming = utcTiming;
this.location = location;
this.serviceDescription = serviceDescription;
this.periods = periods == null ? Collections.emptyList() : periods;
}

public final int getPeriodCount() {
return periods.size();
}

public final CustomPeriod getPeriod(int index) {
return periods.get(index);
}

public final long getPeriodDurationMs(int index) {
return index == periods.size() - 1
? (durationMs == C.TIME_UNSET ? C.TIME_UNSET : (durationMs - periods.get(index).startMs))
: (periods.get(index + 1).startMs - periods.get(index).startMs);
}

public final long getPeriodDurationUs(int index) {
return C.msToUs(getPeriodDurationMs(index));
}

@Override
public final CustomDashManifest copy(List<StreamKey> streamKeys) {
LinkedList<StreamKey> keys = new LinkedList<>(streamKeys);
Collections.sort(keys);
keys.add(new StreamKey(-1, -1, -1)); // Add a stopper key to the end

ArrayList<CustomPeriod> copyPeriods = new ArrayList<>();
long shiftMs = 0;
for (int periodIndex = 0; periodIndex < getPeriodCount(); periodIndex++) {
if (keys.peek().periodIndex != periodIndex) {
// No representations selected in this period.
long periodDurationMs = getPeriodDurationMs(periodIndex);
if (periodDurationMs != C.TIME_UNSET) {
shiftMs += periodDurationMs;
}
} else {
CustomPeriod period = getPeriod(periodIndex);
ArrayList<CustomAdaptationSet> copyAdaptationSets =
copyAdaptationSets(period.adaptationSets, keys);
CustomPeriod copiedPeriod = new CustomPeriod(period.id, period.startMs - shiftMs, copyAdaptationSets,
period.eventStreams);
copyPeriods.add(copiedPeriod);
}
}
long newDuration = durationMs != C.TIME_UNSET ? durationMs - shiftMs : C.TIME_UNSET;
return new CustomDashManifest(
availabilityStartTimeMs,
newDuration,
minBufferTimeMs,
dynamic,
minUpdatePeriodMs,
timeShiftBufferDepthMs,
suggestedPresentationDelayMs,
publishTimeMs,
programInformation,
utcTiming,
serviceDescription,
location,
copyPeriods);
}

private static ArrayList<CustomAdaptationSet> copyAdaptationSets(
List<CustomAdaptationSet> adaptationSets, LinkedList<StreamKey> keys) {
StreamKey key = keys.poll();
int periodIndex = key.periodIndex;
ArrayList<CustomAdaptationSet> copyAdaptationSets = new ArrayList<>();
do {
int adaptationSetIndex = key.groupIndex;
CustomAdaptationSet adaptationSet = adaptationSets.get(adaptationSetIndex);

List<CustomRepresentation> representations = adaptationSet.representations;
ArrayList<CustomRepresentation> copyRepresentations = new ArrayList<>();
do {
CustomRepresentation representation = representations.get(key.trackIndex);
copyRepresentations.add(representation);
key = keys.poll();
} while (key.periodIndex == periodIndex && key.groupIndex == adaptationSetIndex);

copyAdaptationSets.add(
new CustomAdaptationSet(
adaptationSet.id,
adaptationSet.type,
copyRepresentations,
adaptationSet.accessibilityDescriptors,
adaptationSet.essentialProperties,
adaptationSet.supplementalProperties));
} while(key.periodIndex == periodIndex);
// Add back the last key which doesn't belong to the period being processed
keys.addFirst(key);
return copyAdaptationSets;
}

}
Loading