mirror of
https://github.com/samsonjs/media.git
synced 2026-03-25 09:25:53 +00:00
Parse Label elements for adaptation sets
Issue: #6297 PiperOrigin-RevId: 273297284
This commit is contained in:
parent
48bfb37e93
commit
b052ea9bed
5 changed files with 151 additions and 14 deletions
|
|
@ -24,8 +24,11 @@
|
|||
* Remove the `DataSpec.FLAG_ALLOW_ICY_METADATA` flag. Instead, set the header
|
||||
`IcyHeaders.REQUEST_HEADER_ENABLE_METADATA_NAME` in the `DataSpec`
|
||||
`httpRequestHeaders`.
|
||||
* DASH: Support negative @r values in segment timelines
|
||||
([#1787](https://github.com/google/ExoPlayer/issues/1787)).
|
||||
* DASH:
|
||||
* Support negative @r values in segment timelines
|
||||
([#1787](https://github.com/google/ExoPlayer/issues/1787)).
|
||||
* Support `Label` elements
|
||||
([#6297](https://github.com/google/ExoPlayer/issues/6297)).
|
||||
* Add `allowedCapturePolicy` field to `AudioAttributes` wrapper to allow to
|
||||
opt-out of audio recording.
|
||||
* Add `DataSpec.httpRequestHeaders` to set HTTP request headers when connecting
|
||||
|
|
|
|||
|
|
@ -1099,6 +1099,39 @@ public final class Format implements Parcelable {
|
|||
exoMediaCryptoType);
|
||||
}
|
||||
|
||||
public Format copyWithLabel(@Nullable String label) {
|
||||
return new Format(
|
||||
id,
|
||||
label,
|
||||
selectionFlags,
|
||||
roleFlags,
|
||||
bitrate,
|
||||
codecs,
|
||||
metadata,
|
||||
containerMimeType,
|
||||
sampleMimeType,
|
||||
maxInputSize,
|
||||
initializationData,
|
||||
drmInitData,
|
||||
subsampleOffsetUs,
|
||||
width,
|
||||
height,
|
||||
frameRate,
|
||||
rotationDegrees,
|
||||
pixelWidthHeightRatio,
|
||||
projectionData,
|
||||
stereoMode,
|
||||
colorInfo,
|
||||
channelCount,
|
||||
sampleRate,
|
||||
pcmEncoding,
|
||||
encoderDelay,
|
||||
encoderPadding,
|
||||
language,
|
||||
accessibilityChannel,
|
||||
exoMediaCryptoType);
|
||||
}
|
||||
|
||||
public Format copyWithContainerInfo(
|
||||
@Nullable String id,
|
||||
@Nullable String label,
|
||||
|
|
|
|||
|
|
@ -316,7 +316,6 @@ public class DashManifestParser extends DefaultHandler
|
|||
parseRepresentation(
|
||||
xpp,
|
||||
baseUrl,
|
||||
label,
|
||||
mimeType,
|
||||
codecs,
|
||||
width,
|
||||
|
|
@ -343,6 +342,8 @@ public class DashManifestParser extends DefaultHandler
|
|||
xpp, (SegmentTemplate) segmentBase, supplementalProperties, periodDurationMs);
|
||||
} else if (XmlPullParserUtil.isStartTag(xpp, "InbandEventStream")) {
|
||||
inbandEventStreams.add(parseDescriptor(xpp, "InbandEventStream"));
|
||||
} else if (XmlPullParserUtil.isStartTag(xpp, "Label")) {
|
||||
label = parseLabel(xpp);
|
||||
} else if (XmlPullParserUtil.isStartTag(xpp)) {
|
||||
parseAdaptationSetChild(xpp);
|
||||
}
|
||||
|
|
@ -353,7 +354,11 @@ public class DashManifestParser extends DefaultHandler
|
|||
for (int i = 0; i < representationInfos.size(); i++) {
|
||||
representations.add(
|
||||
buildRepresentation(
|
||||
representationInfos.get(i), drmSchemeType, drmSchemeDatas, inbandEventStreams));
|
||||
representationInfos.get(i),
|
||||
label,
|
||||
drmSchemeType,
|
||||
drmSchemeDatas,
|
||||
inbandEventStreams));
|
||||
}
|
||||
|
||||
return buildAdaptationSet(id, contentType, representations, accessibilityDescriptors,
|
||||
|
|
@ -482,7 +487,6 @@ public class DashManifestParser extends DefaultHandler
|
|||
protected RepresentationInfo parseRepresentation(
|
||||
XmlPullParser xpp,
|
||||
String baseUrl,
|
||||
@Nullable String label,
|
||||
@Nullable String adaptationSetMimeType,
|
||||
@Nullable String adaptationSetCodecs,
|
||||
int adaptationSetWidth,
|
||||
|
|
@ -553,7 +557,6 @@ public class DashManifestParser extends DefaultHandler
|
|||
Format format =
|
||||
buildFormat(
|
||||
id,
|
||||
label,
|
||||
mimeType,
|
||||
width,
|
||||
height,
|
||||
|
|
@ -574,7 +577,6 @@ public class DashManifestParser extends DefaultHandler
|
|||
|
||||
protected Format buildFormat(
|
||||
@Nullable String id,
|
||||
@Nullable String label,
|
||||
@Nullable String containerMimeType,
|
||||
int width,
|
||||
int height,
|
||||
|
|
@ -598,7 +600,7 @@ public class DashManifestParser extends DefaultHandler
|
|||
if (MimeTypes.isVideo(sampleMimeType)) {
|
||||
return Format.createVideoContainerFormat(
|
||||
id,
|
||||
label,
|
||||
/* label= */ null,
|
||||
containerMimeType,
|
||||
sampleMimeType,
|
||||
codecs,
|
||||
|
|
@ -613,7 +615,7 @@ public class DashManifestParser extends DefaultHandler
|
|||
} else if (MimeTypes.isAudio(sampleMimeType)) {
|
||||
return Format.createAudioContainerFormat(
|
||||
id,
|
||||
label,
|
||||
/* label= */ null,
|
||||
containerMimeType,
|
||||
sampleMimeType,
|
||||
codecs,
|
||||
|
|
@ -636,7 +638,7 @@ public class DashManifestParser extends DefaultHandler
|
|||
}
|
||||
return Format.createTextContainerFormat(
|
||||
id,
|
||||
label,
|
||||
/* label= */ null,
|
||||
containerMimeType,
|
||||
sampleMimeType,
|
||||
codecs,
|
||||
|
|
@ -649,7 +651,7 @@ public class DashManifestParser extends DefaultHandler
|
|||
}
|
||||
return Format.createContainerFormat(
|
||||
id,
|
||||
label,
|
||||
/* label= */ null,
|
||||
containerMimeType,
|
||||
sampleMimeType,
|
||||
codecs,
|
||||
|
|
@ -661,10 +663,14 @@ public class DashManifestParser extends DefaultHandler
|
|||
|
||||
protected Representation buildRepresentation(
|
||||
RepresentationInfo representationInfo,
|
||||
@Nullable String label,
|
||||
@Nullable String extraDrmSchemeType,
|
||||
ArrayList<SchemeData> extraDrmSchemeDatas,
|
||||
ArrayList<Descriptor> extraInbandEventStreams) {
|
||||
Format format = representationInfo.format;
|
||||
if (label != null) {
|
||||
format = format.copyWithLabel(label);
|
||||
}
|
||||
String drmSchemeType = representationInfo.drmSchemeType != null
|
||||
? representationInfo.drmSchemeType : extraDrmSchemeType;
|
||||
ArrayList<SchemeData> drmSchemeDatas = representationInfo.drmSchemeDatas;
|
||||
|
|
@ -1132,6 +1138,32 @@ public class DashManifestParser extends DefaultHandler
|
|||
return new ProgramInformation(title, source, copyright, moreInformationURL, lang);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a Label element.
|
||||
*
|
||||
* @param xpp The parser from which to read.
|
||||
* @throws XmlPullParserException If an error occurs parsing the element.
|
||||
* @throws IOException If an error occurs reading the element.
|
||||
* @return The parsed label.
|
||||
*/
|
||||
protected String parseLabel(XmlPullParser xpp) throws XmlPullParserException, IOException {
|
||||
return parseText(xpp, "Label");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a BaseURL element.
|
||||
*
|
||||
* @param xpp The parser from which to read.
|
||||
* @param parentBaseUrl A base URL for resolving the parsed URL.
|
||||
* @throws XmlPullParserException If an error occurs parsing the element.
|
||||
* @throws IOException If an error occurs reading the element.
|
||||
* @return The parsed and resolved URL.
|
||||
*/
|
||||
protected String parseBaseUrl(XmlPullParser xpp, String parentBaseUrl)
|
||||
throws XmlPullParserException, IOException {
|
||||
return UriUtil.resolve(parentBaseUrl, parseText(xpp, "BaseURL"));
|
||||
}
|
||||
|
||||
// AudioChannelConfiguration parsing.
|
||||
|
||||
protected int parseAudioChannelConfiguration(XmlPullParser xpp)
|
||||
|
|
@ -1487,10 +1519,18 @@ public class DashManifestParser extends DefaultHandler
|
|||
}
|
||||
}
|
||||
|
||||
protected static String parseBaseUrl(XmlPullParser xpp, String parentBaseUrl)
|
||||
protected static String parseText(XmlPullParser xpp, String label)
|
||||
throws XmlPullParserException, IOException {
|
||||
xpp.next();
|
||||
return UriUtil.resolve(parentBaseUrl, xpp.getText());
|
||||
String text = "";
|
||||
do {
|
||||
xpp.next();
|
||||
if (xpp.getEventType() == XmlPullParser.TEXT) {
|
||||
text = xpp.getText();
|
||||
} else {
|
||||
maybeSkipTag(xpp);
|
||||
}
|
||||
} while (!XmlPullParserUtil.isEndTag(xpp, label));
|
||||
return text;
|
||||
}
|
||||
|
||||
protected static int parseInt(XmlPullParser xpp, String name, int defaultValue) {
|
||||
|
|
|
|||
21
library/dash/src/test/assets/sample_mpd_labels
Normal file
21
library/dash/src/test/assets/sample_mpd_labels
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MPD type="static" duration="1s" mediaPresentationDuration="PT1S">
|
||||
<Period>
|
||||
<SegmentTemplate startNumber="0" timescale="1000" media="sq/$Number$">
|
||||
<SegmentTimeline>
|
||||
<S d="1000"/>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<AdaptationSet id="0" mimeType="audio/mp4" subsegmentAlignment="true" label="audio label">
|
||||
<Representation id="0" codecs="mp4a.40.2" audioSamplingRate="48000" bandwidth="144000">
|
||||
<BaseURL>https://test.com/0</BaseURL>
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
<AdaptationSet id="1" mimeType="video/mp4" subsegmentAlignment="true" label="ignored label">
|
||||
<Representation id="1" codecs="avc1.4d4015" width="426" height="240" bandwidth="258000">
|
||||
<BaseURL>https://test.com/1</BaseURL>
|
||||
</Representation>
|
||||
<Label>video label</Label>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
</MPD>
|
||||
|
|
@ -44,6 +44,7 @@ public class DashManifestParserTest {
|
|||
private static final String SAMPLE_MPD_UNKNOWN_MIME_TYPE = "sample_mpd_unknown_mime_type";
|
||||
private static final String SAMPLE_MPD_SEGMENT_TEMPLATE = "sample_mpd_segment_template";
|
||||
private static final String SAMPLE_MPD_EVENT_STREAM = "sample_mpd_event_stream";
|
||||
private static final String SAMPLE_MPD_LABELS = "sample_mpd_labels";
|
||||
|
||||
private static final String NEXT_TAG_NAME = "Next";
|
||||
private static final String NEXT_TAG = "<" + NEXT_TAG_NAME + "/>";
|
||||
|
|
@ -176,6 +177,21 @@ public class DashManifestParserTest {
|
|||
assertThat(mpd.programInformation).isEqualTo(expectedProgramInformation);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseMediaPresentationDescription_labels() throws IOException {
|
||||
DashManifestParser parser = new DashManifestParser();
|
||||
DashManifest manifest =
|
||||
parser.parse(
|
||||
Uri.parse("https://example.com/test.mpd"),
|
||||
TestUtil.getInputStream(
|
||||
ApplicationProvider.getApplicationContext(), SAMPLE_MPD_LABELS));
|
||||
|
||||
List<AdaptationSet> adaptationSets = manifest.getPeriod(0).adaptationSets;
|
||||
|
||||
assertThat(adaptationSets.get(0).representations.get(0).format.label).isEqualTo("audio label");
|
||||
assertThat(adaptationSets.get(1).representations.get(0).format.label).isEqualTo("video label");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseSegmentTimeline_repeatCount() throws Exception {
|
||||
DashManifestParser parser = new DashManifestParser();
|
||||
|
|
@ -251,6 +267,30 @@ public class DashManifestParserTest {
|
|||
assertNextTag(xpp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseLabel() throws Exception {
|
||||
DashManifestParser parser = new DashManifestParser();
|
||||
XmlPullParser xpp = XmlPullParserFactory.newInstance().newPullParser();
|
||||
xpp.setInput(new StringReader("<Label>test label</Label>" + NEXT_TAG));
|
||||
xpp.next();
|
||||
|
||||
String label = parser.parseLabel(xpp);
|
||||
assertThat(label).isEqualTo("test label");
|
||||
assertNextTag(xpp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseLabel_noText() throws Exception {
|
||||
DashManifestParser parser = new DashManifestParser();
|
||||
XmlPullParser xpp = XmlPullParserFactory.newInstance().newPullParser();
|
||||
xpp.setInput(new StringReader("<Label/>" + NEXT_TAG));
|
||||
xpp.next();
|
||||
|
||||
String label = parser.parseLabel(xpp);
|
||||
assertThat(label).isEqualTo("");
|
||||
assertNextTag(xpp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseCea608AccessibilityChannel() {
|
||||
assertThat(
|
||||
|
|
|
|||
Loading…
Reference in a new issue