Remove unused DashMpdParser (but kept in git history)

This commit is contained in:
Stypox 2022-04-30 19:46:23 +02:00 committed by TiA4f8R
parent 50272db946
commit 159d05c91b
No known key found for this signature in database
GPG key ID: E6D3E7F5949450DD

View file

@ -1,244 +0,0 @@
/*
* Created by Christian Schabesberger on 02.02.16.
*
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* DashMpdParser.java is part of NewPipe Extractor.
*
* NewPipe Extractor is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe Extractor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe Extractor. If not, see <https://www.gnu.org/licenses/>.
*/
package org.schabi.newpipe.extractor.services.youtube;
import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.downloader.Downloader;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.stream.DeliveryMethod;
import org.schabi.newpipe.extractor.stream.VideoStream;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.annotation.Nonnull;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
/**
* Class to extract streams from a DASH manifest.
*
* <p>
* Note that this class relies on the YouTube's {@link ItagItem} class and should be made generic
* in order to be used on other services.
* </p>
*
* <p>
* This class is not used by the extractor itself, as all streams are supported by the extractor.
* </p>
*/
public final class DashMpdParser {
private DashMpdParser() {
}
/**
* Exception class which is thrown when something went wrong when using
* {@link DashMpdParser#getStreams(String)}.
*/
public static class DashMpdParsingException extends ParsingException {
DashMpdParsingException(final String message, final Exception e) {
super(message, e);
}
}
/**
* Class which represents the result of a DASH MPD file parsing by {@link DashMpdParser}.
*
* <p>
* The result contains video, video-only and audio streams.
* </p>
*/
public static class Result {
private final List<VideoStream> videoStreams;
private final List<VideoStream> videoOnlyStreams;
private final List<AudioStream> audioStreams;
Result(final List<VideoStream> videoStreams,
final List<VideoStream> videoOnlyStreams,
final List<AudioStream> audioStreams) {
this.videoStreams = videoStreams;
this.videoOnlyStreams = videoOnlyStreams;
this.audioStreams = audioStreams;
}
public List<VideoStream> getVideoStreams() {
return videoStreams;
}
public List<VideoStream> getVideoOnlyStreams() {
return videoOnlyStreams;
}
public List<AudioStream> getAudioStreams() {
return audioStreams;
}
}
/**
* This method will try to download and parse the YouTube DASH MPD manifest URL provided to get
* supported {@link AudioStream}s and {@link VideoStream}s.
*
* <p>
* The parser supports video, video-only and audio streams.
* </p>
*
* @param dashMpdUrl the URL of the DASH MPD manifest
* @return a {@link Result} which contains all video, video-only and audio streams extracted
* and supported by the extractor (so the ones for which {@link ItagItem#isSupported(int)}
* returns {@code true}).
* @throws DashMpdParsingException if something went wrong when downloading or parsing the
* manifest
* @see <a href="https://www.brendanlong.com/the-structure-of-an-mpeg-dash-mpd.html">
* www.brendanlong.com's page about the structure of an MPEG-DASH MPD manifest</a>
*/
@Nonnull
public static Result getStreams(final String dashMpdUrl)
throws DashMpdParsingException, ReCaptchaException {
final String dashDoc;
final Downloader downloader = NewPipe.getDownloader();
try {
dashDoc = downloader.get(dashMpdUrl).responseBody();
} catch (final IOException e) {
throw new DashMpdParsingException("Could not fetch DASH manifest: " + dashMpdUrl, e);
}
try {
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder builder = factory.newDocumentBuilder();
final InputStream stream = new ByteArrayInputStream(dashDoc.getBytes());
final Document doc = builder.parse(stream);
final NodeList representationList = doc.getElementsByTagName("Representation");
final List<VideoStream> videoStreams = new ArrayList<>();
final List<AudioStream> audioStreams = new ArrayList<>();
final List<VideoStream> videoOnlyStreams = new ArrayList<>();
for (int i = 0; i < representationList.getLength(); i++) {
final Element representation = (Element) representationList.item(i);
try {
final String mimeType = ((Element) representation.getParentNode())
.getAttribute("mimeType");
final String id = representation.getAttribute("id");
final ItagItem itag = ItagItem.getItag(Integer.parseInt(id));
final Element segmentationList = (Element) representation
.getElementsByTagName("SegmentList").item(0);
if (segmentationList == null) {
continue;
}
final MediaFormat mediaFormat = MediaFormat.getFromMimeType(mimeType);
if (itag.itagType.equals(ItagItem.ItagType.AUDIO)) {
audioStreams.add(new AudioStream.Builder()
.setId(String.valueOf(itag.id))
.setContent(manualDashFromRepresentation(doc, representation),
false)
.setMediaFormat(mediaFormat)
.setDeliveryMethod(DeliveryMethod.DASH)
.setAverageBitrate(itag.getAverageBitrate())
.setBaseUrl(dashMpdUrl)
.setItagItem(itag)
.build());
} else {
final boolean isVideoOnly = itag.itagType == ItagItem.ItagType.VIDEO_ONLY;
final VideoStream videoStream = new VideoStream.Builder()
.setId(String.valueOf(itag.id))
.setContent(manualDashFromRepresentation(doc, representation),
false)
.setMediaFormat(mediaFormat)
.setDeliveryMethod(DeliveryMethod.DASH)
.setResolution(Objects.requireNonNull(itag.getResolutionString()))
.setIsVideoOnly(isVideoOnly)
.setBaseUrl(dashMpdUrl)
.setItagItem(itag)
.build();
if (isVideoOnly) {
videoOnlyStreams.add(videoStream);
} else {
videoStreams.add(videoStream);
}
}
} catch (final Exception ignored) {
}
}
return new Result(videoStreams, videoOnlyStreams, audioStreams);
} catch (final Exception e) {
throw new DashMpdParsingException("Could not parse DASH MPD", e);
}
}
@Nonnull
private static String manualDashFromRepresentation(@Nonnull final Document document,
@Nonnull final Element representation)
throws TransformerException {
final Element mpdElement = (Element) document.getElementsByTagName("MPD").item(0);
// Clone the element so we can freely modify it
final Element adaptationSet = (Element) representation.getParentNode();
final Element adaptationSetClone = (Element) adaptationSet.cloneNode(true);
// Remove other representations from the adaptation set
final NodeList representations = adaptationSetClone.getElementsByTagName("Representation");
for (int i = representations.getLength() - 1; i >= 0; i--) {
final Node item = representations.item(i);
if (!item.isEqualNode(representation)) {
adaptationSetClone.removeChild(item);
}
}
final Element newMpdRootElement = (Element) mpdElement.cloneNode(false);
final Element periodElement = newMpdRootElement.getOwnerDocument().createElement("Period");
periodElement.appendChild(adaptationSetClone);
newMpdRootElement.appendChild(periodElement);
return nodeToString(newMpdRootElement);
}
private static String nodeToString(final Node node) throws TransformerException {
final StringWriter result = new StringWriter();
final Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.VERSION, "1.0");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.transform(new DOMSource(node), new StreamResult(result));
return result.toString();
}
}