mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Use AVERAGE-BANDWIDTH instead of BANDWIDTH when available
Also prevent BANDWIDTH's regex from matching the AVERAGE-BANDWIDTH attribute. Issue:#2863 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=157219453
This commit is contained in:
parent
26728142ee
commit
53b52e784c
2 changed files with 36 additions and 17 deletions
|
|
@ -51,6 +51,15 @@ public class HlsMasterPlaylistParserTest extends TestCase {
|
||||||
+ "#EXT-X-STREAM-INF:BANDWIDTH=65000,CODECS=\"mp4a.40.5\"\n"
|
+ "#EXT-X-STREAM-INF:BANDWIDTH=65000,CODECS=\"mp4a.40.5\"\n"
|
||||||
+ "http://example.com/audio-only.m3u8";
|
+ "http://example.com/audio-only.m3u8";
|
||||||
|
|
||||||
|
private static final String AVG_BANDWIDTH_MASTER_PLAYLIST = " #EXTM3U \n"
|
||||||
|
+ "\n"
|
||||||
|
+ "#EXT-X-STREAM-INF:BANDWIDTH=1280000,CODECS=\"mp4a.40.2,avc1.66.30\",RESOLUTION=304x128\n"
|
||||||
|
+ "http://example.com/low.m3u8\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "#EXT-X-STREAM-INF:BANDWIDTH=1280000,AVERAGE-BANDWIDTH=1270000,"
|
||||||
|
+ "CODECS=\"mp4a.40.2 , avc1.66.30 \"\n"
|
||||||
|
+ "http://example.com/spaces_in_codecs.m3u8\n";
|
||||||
|
|
||||||
private static final String PLAYLIST_WITH_INVALID_HEADER = "#EXTMU3\n"
|
private static final String PLAYLIST_WITH_INVALID_HEADER = "#EXTMU3\n"
|
||||||
+ "#EXT-X-STREAM-INF:BANDWIDTH=1280000,CODECS=\"mp4a.40.2,avc1.66.30\",RESOLUTION=304x128\n"
|
+ "#EXT-X-STREAM-INF:BANDWIDTH=1280000,CODECS=\"mp4a.40.2,avc1.66.30\",RESOLUTION=304x128\n"
|
||||||
+ "http://example.com/low.m3u8\n";
|
+ "http://example.com/low.m3u8\n";
|
||||||
|
|
@ -70,42 +79,48 @@ public class HlsMasterPlaylistParserTest extends TestCase {
|
||||||
HlsMasterPlaylist masterPlaylist = parseMasterPlaylist(PLAYLIST_URI, MASTER_PLAYLIST);
|
HlsMasterPlaylist masterPlaylist = parseMasterPlaylist(PLAYLIST_URI, MASTER_PLAYLIST);
|
||||||
|
|
||||||
List<HlsMasterPlaylist.HlsUrl> variants = masterPlaylist.variants;
|
List<HlsMasterPlaylist.HlsUrl> variants = masterPlaylist.variants;
|
||||||
assertNotNull(variants);
|
|
||||||
assertEquals(5, variants.size());
|
assertEquals(5, variants.size());
|
||||||
assertNull(masterPlaylist.muxedCaptionFormats);
|
assertNull(masterPlaylist.muxedCaptionFormats);
|
||||||
|
|
||||||
assertEquals(1280000, variants.get(0).format.bitrate);
|
assertEquals(1280000, variants.get(0).format.bitrate);
|
||||||
assertNotNull(variants.get(0).format.codecs);
|
|
||||||
assertEquals("mp4a.40.2,avc1.66.30", variants.get(0).format.codecs);
|
assertEquals("mp4a.40.2,avc1.66.30", variants.get(0).format.codecs);
|
||||||
assertEquals(304, variants.get(0).format.width);
|
assertEquals(304, variants.get(0).format.width);
|
||||||
assertEquals(128, variants.get(0).format.height);
|
assertEquals(128, variants.get(0).format.height);
|
||||||
assertEquals("http://example.com/low.m3u8", variants.get(0).url);
|
assertEquals("http://example.com/low.m3u8", variants.get(0).url);
|
||||||
|
|
||||||
assertEquals(1280000, variants.get(1).format.bitrate);
|
assertEquals(1280000, variants.get(1).format.bitrate);
|
||||||
assertNotNull(variants.get(1).format.codecs);
|
|
||||||
assertEquals("mp4a.40.2 , avc1.66.30 ", variants.get(1).format.codecs);
|
assertEquals("mp4a.40.2 , avc1.66.30 ", variants.get(1).format.codecs);
|
||||||
assertEquals("http://example.com/spaces_in_codecs.m3u8", variants.get(1).url);
|
assertEquals("http://example.com/spaces_in_codecs.m3u8", variants.get(1).url);
|
||||||
|
|
||||||
assertEquals(2560000, variants.get(2).format.bitrate);
|
assertEquals(2560000, variants.get(2).format.bitrate);
|
||||||
assertEquals(null, variants.get(2).format.codecs);
|
assertNull(variants.get(2).format.codecs);
|
||||||
assertEquals(384, variants.get(2).format.width);
|
assertEquals(384, variants.get(2).format.width);
|
||||||
assertEquals(160, variants.get(2).format.height);
|
assertEquals(160, variants.get(2).format.height);
|
||||||
assertEquals("http://example.com/mid.m3u8", variants.get(2).url);
|
assertEquals("http://example.com/mid.m3u8", variants.get(2).url);
|
||||||
|
|
||||||
assertEquals(7680000, variants.get(3).format.bitrate);
|
assertEquals(7680000, variants.get(3).format.bitrate);
|
||||||
assertEquals(null, variants.get(3).format.codecs);
|
assertNull(variants.get(3).format.codecs);
|
||||||
assertEquals(Format.NO_VALUE, variants.get(3).format.width);
|
assertEquals(Format.NO_VALUE, variants.get(3).format.width);
|
||||||
assertEquals(Format.NO_VALUE, variants.get(3).format.height);
|
assertEquals(Format.NO_VALUE, variants.get(3).format.height);
|
||||||
assertEquals("http://example.com/hi.m3u8", variants.get(3).url);
|
assertEquals("http://example.com/hi.m3u8", variants.get(3).url);
|
||||||
|
|
||||||
assertEquals(65000, variants.get(4).format.bitrate);
|
assertEquals(65000, variants.get(4).format.bitrate);
|
||||||
assertNotNull(variants.get(4).format.codecs);
|
|
||||||
assertEquals("mp4a.40.5", variants.get(4).format.codecs);
|
assertEquals("mp4a.40.5", variants.get(4).format.codecs);
|
||||||
assertEquals(Format.NO_VALUE, variants.get(4).format.width);
|
assertEquals(Format.NO_VALUE, variants.get(4).format.width);
|
||||||
assertEquals(Format.NO_VALUE, variants.get(4).format.height);
|
assertEquals(Format.NO_VALUE, variants.get(4).format.height);
|
||||||
assertEquals("http://example.com/audio-only.m3u8", variants.get(4).url);
|
assertEquals("http://example.com/audio-only.m3u8", variants.get(4).url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testMasterPlaylistWithBandwdithAverage() throws IOException {
|
||||||
|
HlsMasterPlaylist masterPlaylist = parseMasterPlaylist(PLAYLIST_URI,
|
||||||
|
AVG_BANDWIDTH_MASTER_PLAYLIST);
|
||||||
|
|
||||||
|
List<HlsMasterPlaylist.HlsUrl> variants = masterPlaylist.variants;
|
||||||
|
|
||||||
|
assertEquals(1280000, variants.get(0).format.bitrate);
|
||||||
|
assertEquals(1270000, variants.get(1).format.bitrate);
|
||||||
|
}
|
||||||
|
|
||||||
public void testPlaylistWithInvalidHeader() throws IOException {
|
public void testPlaylistWithInvalidHeader() throws IOException {
|
||||||
try {
|
try {
|
||||||
parseMasterPlaylist(PLAYLIST_URI, PLAYLIST_WITH_INVALID_HEADER);
|
parseMasterPlaylist(PLAYLIST_URI, PLAYLIST_WITH_INVALID_HEADER);
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,9 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||||
|
|
||||||
private static final String ATTR_CLOSED_CAPTIONS_NONE = "CLOSED-CAPTIONS=NONE";
|
private static final String ATTR_CLOSED_CAPTIONS_NONE = "CLOSED-CAPTIONS=NONE";
|
||||||
|
|
||||||
private static final Pattern REGEX_BANDWIDTH = Pattern.compile("BANDWIDTH=(\\d+)\\b");
|
private static final Pattern REGEX_AVERAGE_BANDWIDTH =
|
||||||
|
Pattern.compile("AVERAGE-BANDWIDTH=(\\d+)\\b");
|
||||||
|
private static final Pattern REGEX_BANDWIDTH = Pattern.compile("[^-]BANDWIDTH=(\\d+)\\b");
|
||||||
private static final Pattern REGEX_CODECS = Pattern.compile("CODECS=\"(.+?)\"");
|
private static final Pattern REGEX_CODECS = Pattern.compile("CODECS=\"(.+?)\"");
|
||||||
private static final Pattern REGEX_RESOLUTION = Pattern.compile("RESOLUTION=(\\d+x\\d+)");
|
private static final Pattern REGEX_RESOLUTION = Pattern.compile("RESOLUTION=(\\d+x\\d+)");
|
||||||
private static final Pattern REGEX_TARGET_DURATION = Pattern.compile(TAG_TARGET_DURATION
|
private static final Pattern REGEX_TARGET_DURATION = Pattern.compile(TAG_TARGET_DURATION
|
||||||
|
|
@ -235,6 +237,11 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||||
}
|
}
|
||||||
} else if (line.startsWith(TAG_STREAM_INF)) {
|
} else if (line.startsWith(TAG_STREAM_INF)) {
|
||||||
int bitrate = parseIntAttr(line, REGEX_BANDWIDTH);
|
int bitrate = parseIntAttr(line, REGEX_BANDWIDTH);
|
||||||
|
String averageBandwidthString = parseOptionalStringAttr(line, REGEX_AVERAGE_BANDWIDTH);
|
||||||
|
if (averageBandwidthString != null) {
|
||||||
|
// If available, the average bandwidth attribute is used as the variant's bitrate.
|
||||||
|
bitrate = Integer.parseInt(averageBandwidthString);
|
||||||
|
}
|
||||||
String codecs = parseOptionalStringAttr(line, REGEX_CODECS);
|
String codecs = parseOptionalStringAttr(line, REGEX_CODECS);
|
||||||
String resolutionString = parseOptionalStringAttr(line, REGEX_RESOLUTION);
|
String resolutionString = parseOptionalStringAttr(line, REGEX_RESOLUTION);
|
||||||
noClosedCaptions |= line.contains(ATTR_CLOSED_CAPTIONS_NONE);
|
noClosedCaptions |= line.contains(ATTR_CLOSED_CAPTIONS_NONE);
|
||||||
|
|
@ -406,14 +413,6 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||||
initializationSegment, segments);
|
initializationSegment, segments);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String parseStringAttr(String line, Pattern pattern) throws ParserException {
|
|
||||||
Matcher matcher = pattern.matcher(line);
|
|
||||||
if (matcher.find() && matcher.groupCount() == 1) {
|
|
||||||
return matcher.group(1);
|
|
||||||
}
|
|
||||||
throw new ParserException("Couldn't match " + pattern.pattern() + " in " + line);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int parseIntAttr(String line, Pattern pattern) throws ParserException {
|
private static int parseIntAttr(String line, Pattern pattern) throws ParserException {
|
||||||
return Integer.parseInt(parseStringAttr(line, pattern));
|
return Integer.parseInt(parseStringAttr(line, pattern));
|
||||||
}
|
}
|
||||||
|
|
@ -424,10 +423,15 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||||
|
|
||||||
private static String parseOptionalStringAttr(String line, Pattern pattern) {
|
private static String parseOptionalStringAttr(String line, Pattern pattern) {
|
||||||
Matcher matcher = pattern.matcher(line);
|
Matcher matcher = pattern.matcher(line);
|
||||||
if (matcher.find()) {
|
return matcher.find() ? matcher.group(1) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String parseStringAttr(String line, Pattern pattern) throws ParserException {
|
||||||
|
Matcher matcher = pattern.matcher(line);
|
||||||
|
if (matcher.find() && matcher.groupCount() == 1) {
|
||||||
return matcher.group(1);
|
return matcher.group(1);
|
||||||
}
|
}
|
||||||
return null;
|
throw new ParserException("Couldn't match " + pattern.pattern() + " in " + line);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean parseBooleanAttribute(String line, Pattern pattern, boolean defaultValue) {
|
private static boolean parseBooleanAttribute(String line, Pattern pattern, boolean defaultValue) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue