Skip to content

Commit

Permalink
Added two new image specific properties 'tileCountHorizontal' and 'ti…
Browse files Browse the repository at this point in the history
…leCountVertical' to class Format. DashManifestParser adjusted to parse these values from an EssentialProperty tag of an Image AdaptationSet. With this change, DashManifest does not have to do any parsing inside the new getThumbnailDescriptions() method. Moreover, both classes ThumbnailDescription and ThumbnailProvider adjusted to use these two properties / naming scheme accordingly.
  • Loading branch information
gorkemg committed Dec 5, 2022
1 parent 158cf0c commit 2f8fd87
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 31 deletions.
Expand Up @@ -92,7 +92,7 @@ private Bitmap getThumbnailInternal(long position, ThumbnailDescription thumbnai

if (position < thumbnailDescription.getStartTimeMs() || position > thumbnailDescription.getStartTimeMs() + thumbnailDescription.getDurationMs()) return null;

int count = thumbnailDescription.getColumns() * thumbnailDescription.getRows();
int count = thumbnailDescription.getTileCountHorizontal() * thumbnailDescription.getTileCountVertical();

int durationPerImage = (int)(thumbnailDescription.getDurationMs() / count);

Expand All @@ -101,12 +101,12 @@ private Bitmap getThumbnailInternal(long position, ThumbnailDescription thumbnai
//handle special case if position == duration
if (imageNumberToUseWithinTile > count-1) imageNumberToUseWithinTile = count-1;

int intRowToUse = (int)(imageNumberToUseWithinTile / thumbnailDescription.getColumns());
int intRowToUse = (int)(imageNumberToUseWithinTile / thumbnailDescription.getTileCountHorizontal());

int intColToUse = imageNumberToUseWithinTile - intRowToUse * thumbnailDescription.getColumns();
int intColToUse = imageNumberToUseWithinTile - intRowToUse * thumbnailDescription.getTileCountHorizontal();

double thumbnailWidth = (double) thumbnailDescription.getImageWidth() / thumbnailDescription.getColumns();
double thumbnailHeight = (double) thumbnailDescription.getImageHeight() / thumbnailDescription.getRows();
double thumbnailWidth = (double) thumbnailDescription.getImageWidth() / thumbnailDescription.getTileCountHorizontal();
double thumbnailHeight = (double) thumbnailDescription.getImageHeight() / thumbnailDescription.getTileCountVertical();

int cropXLeft = (int)Math.round(intColToUse * thumbnailWidth);
int cropYTop = (int)Math.round(intRowToUse * thumbnailHeight);
Expand Down
Expand Up @@ -115,6 +115,13 @@
* <ul>
* <li>{@link #accessibilityChannel}
* </ul>
*
* <h2 id="image-formats">Fields relevant to image formats</h2>
*
* <ul>
* <li>{@link #tileCountHorizontal}
* <li>{@link #tileCountVertical}
* </ul>
*/
public final class Format implements Bundleable {

Expand Down Expand Up @@ -174,6 +181,11 @@ public static final class Builder {

private int accessibilityChannel;

// Image specific

private int tileCountHorizontal;
private int tileCountVertical;

// Provided by the source.

private @C.CryptoType int cryptoType;
Expand All @@ -197,6 +209,9 @@ public Builder() {
pcmEncoding = NO_VALUE;
// Text specific.
accessibilityChannel = NO_VALUE;
// Image specific.
tileCountHorizontal = NO_VALUE;
tileCountVertical = NO_VALUE;
// Provided by the source.
cryptoType = C.CRYPTO_TYPE_NONE;
}
Expand Down Expand Up @@ -241,6 +256,9 @@ private Builder(Format format) {
this.encoderPadding = format.encoderPadding;
// Text specific.
this.accessibilityChannel = format.accessibilityChannel;
// Image specific.
this.tileCountHorizontal = format.tileCountHorizontal;
this.tileCountVertical = format.tileCountVertical;
// Provided by the source.
this.cryptoType = format.cryptoType;
}
Expand Down Expand Up @@ -616,6 +634,30 @@ public Builder setAccessibilityChannel(int accessibilityChannel) {
return this;
}

// Image specific.

/**
* Sets {@link Format#tileCountHorizontal}. The default value is {@link #NO_VALUE}.
*
* @param tileCountHorizontal The {@link Format#accessibilityChannel}.
* @return The builder.
*/
public Builder setTileCountHorizontal(int tileCountHorizontal) {
this.tileCountHorizontal = tileCountHorizontal;
return this;
}

/**
* Sets {@link Format#tileCountVertical}. The default value is {@link #NO_VALUE}.
*
* @param tileCountVertical The {@link Format#accessibilityChannel}.
* @return The builder.
*/
public Builder setTileCountVertical(int tileCountVertical) {
this.tileCountVertical = tileCountVertical;
return this;
}

// Provided by source.

/**
Expand Down Expand Up @@ -788,6 +830,12 @@ public Format build() {
/** The Accessibility channel, or {@link #NO_VALUE} if not known or applicable. */
public final int accessibilityChannel;

// Image specific.

/** Thumbnail tile count horizontal and vertical, or {@link #NO_VALUE} if not known or applicable. */
public final int tileCountHorizontal;
public final int tileCountVertical;

// Provided by source.

/**
Expand Down Expand Up @@ -1011,6 +1059,9 @@ private Format(Builder builder) {
encoderPadding = builder.encoderPadding == NO_VALUE ? 0 : builder.encoderPadding;
// Text specific.
accessibilityChannel = builder.accessibilityChannel;
// Image specific.
tileCountHorizontal = builder.tileCountHorizontal;
tileCountVertical = builder.tileCountVertical;
// Provided by source.
if (builder.cryptoType == C.CRYPTO_TYPE_NONE && drmInitData != null) {
// Encrypted content cannot use CRYPTO_TYPE_NONE.
Expand Down Expand Up @@ -1257,6 +1308,9 @@ public int hashCode() {
result = 31 * result + encoderPadding;
// Text specific.
result = 31 * result + accessibilityChannel;
// Image specific.
result = 31 * result + tileCountHorizontal;
result = 31 * result + tileCountVertical;
// Provided by the source.
result = 31 * result + cryptoType;
hashCode = result;
Expand Down Expand Up @@ -1293,6 +1347,8 @@ public boolean equals(@Nullable Object obj) {
&& encoderDelay == other.encoderDelay
&& encoderPadding == other.encoderPadding
&& accessibilityChannel == other.accessibilityChannel
&& tileCountHorizontal == other.tileCountHorizontal
&& tileCountVertical == other.tileCountVertical
&& cryptoType == other.cryptoType
&& Float.compare(frameRate, other.frameRate) == 0
&& Float.compare(pixelWidthHeightRatio, other.pixelWidthHeightRatio) == 0
Expand Down Expand Up @@ -1490,6 +1546,8 @@ public static String toLogString(@Nullable Format format) {
FIELD_ENCODER_PADDING,
FIELD_ACCESSIBILITY_CHANNEL,
FIELD_CRYPTO_TYPE,
FIELD_TILE_COUNT_HORIZONTAL,
FIELD_TILE_COUNT_VERTICAL,
})
private @interface FieldNumber {}

Expand Down Expand Up @@ -1523,6 +1581,8 @@ public static String toLogString(@Nullable Format format) {
private static final int FIELD_ENCODER_PADDING = 27;
private static final int FIELD_ACCESSIBILITY_CHANNEL = 28;
private static final int FIELD_CRYPTO_TYPE = 29;
private static final int FIELD_TILE_COUNT_HORIZONTAL = 30;
private static final int FIELD_TILE_COUNT_VERTICAL = 31;

@Override
public Bundle toBundle() {
Expand Down Expand Up @@ -1578,6 +1638,9 @@ public Bundle toBundle(boolean excludeMetadata) {
bundle.putInt(keyForField(FIELD_ENCODER_PADDING), encoderPadding);
// Text specific.
bundle.putInt(keyForField(FIELD_ACCESSIBILITY_CHANNEL), accessibilityChannel);
// Image specific.
bundle.putInt(keyForField(FIELD_TILE_COUNT_HORIZONTAL), tileCountHorizontal);
bundle.putInt(keyForField(FIELD_TILE_COUNT_VERTICAL), tileCountVertical);
// Source specific.
bundle.putInt(keyForField(FIELD_CRYPTO_TYPE), cryptoType);
return bundle;
Expand Down Expand Up @@ -1652,6 +1715,11 @@ private static Format fromBundle(Bundle bundle) {
// Text specific.
.setAccessibilityChannel(
bundle.getInt(keyForField(FIELD_ACCESSIBILITY_CHANNEL), DEFAULT.accessibilityChannel))
// Image specific.
.setTileCountHorizontal(
bundle.getInt(keyForField(FIELD_TILE_COUNT_HORIZONTAL), DEFAULT.tileCountHorizontal))
.setTileCountVertical(
bundle.getInt(keyForField(FIELD_TILE_COUNT_VERTICAL), DEFAULT.tileCountVertical))
// Source specific.
.setCryptoType(bundle.getInt(keyForField(FIELD_CRYPTO_TYPE), DEFAULT.cryptoType));

Expand Down
Expand Up @@ -7,19 +7,19 @@ public class ThumbnailDescription {
private final String id;
private final Uri uri;
private final int bitrate;
private final int rows;
private final int columns;
private final int tileCountHorizontal;
private final int tileCountVertical;
private final long startTimeMs;
private final long durationMs;
private final int imageWidth; // Image width (Pixel)
private final int imageHeight; // Image height (Pixel)

public ThumbnailDescription(String id, Uri uri, int bitrate, int rows, int columns, long startTimeMs, long durationMs, int imageWidth, int imageHeight) {
public ThumbnailDescription(String id, Uri uri, int bitrate, int tileCountHorizontal, int tileCountVertical, long startTimeMs, long durationMs, int imageWidth, int imageHeight) {
this.id = id;
this.uri = uri;
this.bitrate = bitrate;
this.rows = rows;
this.columns = columns;
this.tileCountHorizontal = tileCountHorizontal;
this.tileCountVertical = tileCountVertical;
this.startTimeMs = startTimeMs;
this.durationMs = durationMs;
this.imageWidth = imageWidth;
Expand All @@ -34,12 +34,12 @@ public int getBitrate() {
return bitrate;
}

public int getRows() {
return rows;
public int getTileCountHorizontal() {
return tileCountHorizontal;
}

public int getColumns() {
return columns;
public int getTileCountVertical() {
return tileCountVertical;
}

public long getStartTimeMs() {
Expand Down
Expand Up @@ -185,22 +185,9 @@ public List<ThumbnailDescription> getThumbnailDescriptions(long periodPositionMs
int bitrate = representation.format.bitrate;
int imageWidth = representation.format.width;
int imageHeight = representation.format.height;

// get size XxY, e.g. 10x20, where 10 is column count and 20 is row count
int rows = 1;
int cols = 1;
for (int m = 0; m < representation.essentialProperties.size(); m++) {
Descriptor descriptor = representation.essentialProperties.get(m);
if ((Ascii.equalsIgnoreCase("http://dashif.org/thumbnail_tile", descriptor.schemeIdUri) || Ascii.equalsIgnoreCase("http://dashif.org/guidelines/thumbnail_tile", descriptor.schemeIdUri)) && descriptor.value != null) {
String size = descriptor.value;
String[] sizeSplit = size.split("x");
if (sizeSplit.length != 2) {
continue;
}
cols = Integer.parseInt(sizeSplit[0]);
rows = Integer.parseInt(sizeSplit[1]);
}
}
int tileCountHorizontal = representation.format.tileCountHorizontal;
int tileCountVertical = representation.format.tileCountVertical;

long now = Util.getNowUnixTimeMs(C.TIME_UNSET);
String baseUrl = castNonNull(baseUrlExclusionList.selectBaseUrl(representation.baseUrls)).url;
Expand All @@ -217,7 +204,7 @@ public List<ThumbnailDescription> getThumbnailDescriptions(long periodPositionMs
RangedUri rangedUri = index.getSegmentUrl(segmentNumber);
DataSpec dataSpec = DashUtil.buildDataSpec(representation, baseUrl, rangedUri, /* flags= */ 0);
Uri uri = dataSpec.uri;
ThumbnailDescription thumbnailDescription = new ThumbnailDescription(id, uri, bitrate, rows, cols, Util.usToMs(segmentStartTimeUs - (dynamic ? firstStartTimeUs : 0)), Util.usToMs(segmentDurationUs), imageWidth, imageHeight);
ThumbnailDescription thumbnailDescription = new ThumbnailDescription(id, uri, bitrate, tileCountHorizontal, tileCountVertical, Util.usToMs(segmentStartTimeUs - (dynamic ? firstStartTimeUs : 0)), Util.usToMs(segmentDurationUs), imageWidth, imageHeight);
thumbnailDescriptions.add(thumbnailDescription);
}
}
Expand Down
Expand Up @@ -811,6 +811,8 @@ protected Format buildFormat(
roleFlags |= parseRoleFlagsFromProperties(essentialProperties);
roleFlags |= parseRoleFlagsFromProperties(supplementalProperties);

Pair<Integer,Integer> tileCounts = parseTileCountFromProperties(essentialProperties);

Format.Builder formatBuilder =
new Format.Builder()
.setId(id)
Expand All @@ -820,7 +822,9 @@ protected Format buildFormat(
.setPeakBitrate(bitrate)
.setSelectionFlags(selectionFlags)
.setRoleFlags(roleFlags)
.setLanguage(language);
.setLanguage(language)
.setTileCountHorizontal(tileCounts != null ? tileCounts.first : Format.NO_VALUE)
.setTileCountVertical(tileCounts != null ? tileCounts.second : Format.NO_VALUE);

if (MimeTypes.isVideo(sampleMimeType)) {
formatBuilder.setWidth(width).setHeight(height).setFrameRate(frameRate);
Expand Down Expand Up @@ -1629,6 +1633,31 @@ protected String[] parseProfiles(XmlPullParser xpp, String attributeName, String
return attributeValue.split(",");
}

// Thumbnail tile information parsing

/**
* Parses given descriptors for thumbnail tile information
* @param essentialProperties List of descriptor that contain thumbnail tile information
* @return A pair of Integer values, where the first is the count of horizontal tiles
* and the second is the count of vertical tiles, or null if no thumbnail tile information is found.
*/
@Nullable
protected Pair<Integer,Integer> parseTileCountFromProperties(List<Descriptor> essentialProperties) {
for (Descriptor descriptor : essentialProperties) {
if ((Ascii.equalsIgnoreCase("http://dashif.org/thumbnail_tile", descriptor.schemeIdUri) || Ascii.equalsIgnoreCase("http://dashif.org/guidelines/thumbnail_tile", descriptor.schemeIdUri)) && descriptor.value != null) {
String size = descriptor.value;
String[] sizeSplit = size.split("x");
if (sizeSplit.length != 2) {
continue;
}
int tileCountHorizontal = Integer.parseInt(sizeSplit[0]);
int tileCountVertical = Integer.parseInt(sizeSplit[1]);
return Pair.create(tileCountHorizontal, tileCountVertical);
}
}
return null;
}

// Utility methods.

/**
Expand Down

0 comments on commit 2f8fd87

Please sign in to comment.