use of com.google.android.exoplayer2.source.dash.manifest.Representation in project ExoPlayer by google.
the class DashManifestParserTest method parseEssentialAndSupplementalProperties.
@Test
public void parseEssentialAndSupplementalProperties() throws IOException {
DashManifestParser parser = new DashManifestParser();
DashManifest manifest = parser.parse(Uri.parse("https://example.com/test.mpd"), TestUtil.getInputStream(ApplicationProvider.getApplicationContext(), SAMPLE_MPD_ESSENTIAL_SUPPLEMENTAL_PROPERTIES));
// Verify test setup.
assertThat(manifest.getPeriodCount()).isEqualTo(1);
assertThat(manifest.getPeriod(0).adaptationSets).hasSize(1);
AdaptationSet adaptationSet = manifest.getPeriod(0).adaptationSets.get(0);
assertThat(adaptationSet.representations).hasSize(2);
Representation representation0 = adaptationSet.representations.get(0);
Representation representation1 = adaptationSet.representations.get(1);
assertThat(representation0).isInstanceOf(SingleSegmentRepresentation.class);
assertThat(representation1).isInstanceOf(MultiSegmentRepresentation.class);
// Verify parsed properties.
assertThat(adaptationSet.essentialProperties).hasSize(1);
assertThat(adaptationSet.essentialProperties.get(0).schemeIdUri).isEqualTo("urn:mpeg:dash:essential-scheme:2050");
assertThat(adaptationSet.essentialProperties.get(0).value).isEqualTo("adaptationEssential");
assertThat(adaptationSet.supplementalProperties).hasSize(1);
assertThat(adaptationSet.supplementalProperties.get(0).schemeIdUri).isEqualTo("urn:mpeg:dash:supplemental-scheme:2050");
assertThat(adaptationSet.supplementalProperties.get(0).value).isEqualTo("adaptationSupplemental");
assertThat(representation0.essentialProperties).hasSize(2);
assertThat(representation0.essentialProperties.get(0).schemeIdUri).isEqualTo("urn:mpeg:dash:essential-scheme:2050");
assertThat(representation0.essentialProperties.get(0).value).isEqualTo("adaptationEssential");
assertThat(representation0.essentialProperties.get(1).schemeIdUri).isEqualTo("urn:mpeg:dash:essential-scheme:2050");
assertThat(representation0.essentialProperties.get(1).value).isEqualTo("representationEssential");
assertThat(representation0.supplementalProperties).hasSize(2);
assertThat(representation0.supplementalProperties.get(0).schemeIdUri).isEqualTo("urn:mpeg:dash:supplemental-scheme:2050");
assertThat(representation0.supplementalProperties.get(0).value).isEqualTo("adaptationSupplemental");
assertThat(representation0.supplementalProperties.get(1).schemeIdUri).isEqualTo("urn:mpeg:dash:supplemental-scheme:2050");
assertThat(representation0.supplementalProperties.get(1).value).isEqualTo("representationSupplemental");
assertThat(representation1.essentialProperties).hasSize(2);
assertThat(representation0.essentialProperties.get(0).schemeIdUri).isEqualTo("urn:mpeg:dash:essential-scheme:2050");
assertThat(representation0.essentialProperties.get(0).value).isEqualTo("adaptationEssential");
assertThat(representation1.essentialProperties.get(1).schemeIdUri).isEqualTo("urn:mpeg:dash:essential-scheme:2050");
assertThat(representation1.essentialProperties.get(1).value).isEqualTo("representationEssential");
assertThat(representation1.supplementalProperties).hasSize(2);
assertThat(representation0.supplementalProperties.get(0).schemeIdUri).isEqualTo("urn:mpeg:dash:supplemental-scheme:2050");
assertThat(representation0.supplementalProperties.get(0).value).isEqualTo("adaptationSupplemental");
assertThat(representation1.supplementalProperties.get(1).schemeIdUri).isEqualTo("urn:mpeg:dash:supplemental-scheme:2050");
assertThat(representation1.supplementalProperties.get(1).value).isEqualTo("representationSupplemental");
}
use of com.google.android.exoplayer2.source.dash.manifest.Representation in project ExoPlayer by google.
the class AvcConfig method parse.
/**
* Parses AVC configuration data.
*
* @param data A {@link ParsableByteArray}, whose position is set to the start of the AVC
* configuration data to parse.
* @return A parsed representation of the AVC configuration data.
* @throws ParserException If an error occurred parsing the data.
*/
public static AvcConfig parse(ParsableByteArray data) throws ParserException {
try {
// Skip to the AVCDecoderConfigurationRecord (defined in 14496-15)
data.skipBytes(4);
int nalUnitLengthFieldLength = (data.readUnsignedByte() & 0x3) + 1;
if (nalUnitLengthFieldLength == 3) {
throw new IllegalStateException();
}
List<byte[]> initializationData = new ArrayList<>();
int numSequenceParameterSets = data.readUnsignedByte() & 0x1F;
for (int j = 0; j < numSequenceParameterSets; j++) {
initializationData.add(buildNalUnitForChild(data));
}
int numPictureParameterSets = data.readUnsignedByte();
for (int j = 0; j < numPictureParameterSets; j++) {
initializationData.add(buildNalUnitForChild(data));
}
int width = Format.NO_VALUE;
int height = Format.NO_VALUE;
float pixelWidthHeightRatio = 1;
@Nullable String codecs = null;
if (numSequenceParameterSets > 0) {
byte[] sps = initializationData.get(0);
SpsData spsData = NalUnitUtil.parseSpsNalUnit(initializationData.get(0), nalUnitLengthFieldLength, sps.length);
width = spsData.width;
height = spsData.height;
pixelWidthHeightRatio = spsData.pixelWidthHeightRatio;
codecs = CodecSpecificDataUtil.buildAvcCodecString(spsData.profileIdc, spsData.constraintsFlagsAndReservedZero2Bits, spsData.levelIdc);
}
return new AvcConfig(initializationData, nalUnitLengthFieldLength, width, height, pixelWidthHeightRatio, codecs);
} catch (ArrayIndexOutOfBoundsException e) {
throw ParserException.createForMalformedContainer("Error parsing AVC config", e);
}
}
use of com.google.android.exoplayer2.source.dash.manifest.Representation in project Slide by ccrama.
the class GifUtils method cacheSaveGif.
/**
* Temporarily cache or permanently save a GIF
*
* @param uri URL of the GIF
* @param a
* @param subreddit Subreddit for saving in sub-specific folders
* @param save Whether to permanently save the GIF of just temporarily cache it
*/
public static void cacheSaveGif(Uri uri, Activity a, String subreddit, String submissionTitle, boolean save) {
if (save) {
try {
Toast.makeText(a, a.getString(R.string.mediaview_notif_title), Toast.LENGTH_SHORT).show();
} catch (Exception ignored) {
}
}
if (Reddit.appRestart.getString("imagelocation", "").isEmpty()) {
showFirstDialog(a);
} else if (!new File(Reddit.appRestart.getString("imagelocation", "")).exists()) {
showErrorDialog(a);
} else {
new AsyncTask<Void, Integer, Boolean>() {
File outFile;
NotificationManager notifMgr = ContextCompat.getSystemService(a, NotificationManager.class);
@Override
protected void onPreExecute() {
super.onPreExecute();
if (save) {
Notification notif = new NotificationCompat.Builder(a, Reddit.CHANNEL_IMG).setContentTitle(a.getString(R.string.mediaview_saving, uri.toString().replace("/DASHPlaylist.mpd", ""))).setSmallIcon(R.drawable.ic_download).setProgress(0, 0, true).setOngoing(true).build();
notifMgr.notify(1, notif);
}
}
@Override
protected Boolean doInBackground(Void... voids) {
String folderPath = Reddit.appRestart.getString("imagelocation", "");
String subFolderPath = "";
if (SettingValues.imageSubfolders && !subreddit.isEmpty()) {
subFolderPath = File.separator + subreddit;
}
String extension = ".mp4";
outFile = FileUtil.getValidFile(folderPath, subFolderPath, submissionTitle, "", extension);
OutputStream out = null;
InputStream in = null;
try {
DataSource.Factory downloader = new OkHttpDataSource.Factory(Reddit.client).setUserAgent(a.getString(R.string.app_name));
DataSource.Factory cacheDataSourceFactory = new CacheDataSource.Factory().setCache(Reddit.videoCache).setUpstreamDataSourceFactory(downloader);
if (uri.getLastPathSegment().endsWith("DASHPlaylist.mpd")) {
InputStream dashManifestStream = new DataSourceInputStream(cacheDataSourceFactory.createDataSource(), new DataSpec(uri));
DashManifest dashManifest = new DashManifestParser().parse(uri, dashManifestStream);
dashManifestStream.close();
Uri audioUri = null;
Uri videoUri = null;
for (int i = 0; i < dashManifest.getPeriodCount(); i++) {
for (AdaptationSet as : dashManifest.getPeriod(i).adaptationSets) {
boolean isAudio = false;
int bitrate = 0;
String hqUri = null;
for (Representation r : as.representations) {
if (r.format.bitrate > bitrate) {
bitrate = r.format.bitrate;
hqUri = r.baseUrl;
}
if (MimeTypes.isAudio(r.format.sampleMimeType)) {
isAudio = true;
}
}
if (isAudio) {
audioUri = Uri.parse(hqUri);
} else {
videoUri = Uri.parse(hqUri);
}
}
}
if (audioUri != null) {
LogUtil.v("Downloading DASH audio from: " + audioUri);
DataSourceInputStream audioInputStream = new DataSourceInputStream(cacheDataSourceFactory.createDataSource(), new DataSpec(audioUri));
if (save) {
FileUtils.copyInputStreamToFile(audioInputStream, new File(a.getCacheDir().getAbsolutePath(), "audio.mp4"));
} else {
IOUtils.copy(audioInputStream, NullOutputStream.NULL_OUTPUT_STREAM);
}
audioInputStream.close();
}
if (videoUri != null) {
LogUtil.v("Downloading DASH video from: " + videoUri);
DataSourceInputStream videoInputStream = new DataSourceInputStream(cacheDataSourceFactory.createDataSource(), new DataSpec(videoUri));
if (save) {
FileUtils.copyInputStreamToFile(videoInputStream, new File(a.getCacheDir().getAbsolutePath(), "video.mp4"));
} else {
IOUtils.copy(videoInputStream, NullOutputStream.NULL_OUTPUT_STREAM);
}
videoInputStream.close();
}
if (!save) {
return true;
} else if (audioUri != null && videoUri != null) {
if (mux(new File(a.getCacheDir().getAbsolutePath(), "video.mp4").getAbsolutePath(), new File(a.getCacheDir().getAbsolutePath(), "audio.mp4").getAbsolutePath(), new File(a.getCacheDir().getAbsolutePath(), "muxed.mp4").getAbsolutePath())) {
in = new FileInputStream(new File(a.getCacheDir().getAbsolutePath(), "muxed.mp4"));
} else {
throw new IOException("Muxing failed!");
}
} else {
in = new FileInputStream(new File(a.getCacheDir().getAbsolutePath(), "video.mp4"));
}
} else {
in = new DataSourceInputStream(cacheDataSourceFactory.createDataSource(), new DataSpec(uri));
}
out = save ? new FileOutputStream(outFile) : NullOutputStream.NULL_OUTPUT_STREAM;
IOUtils.copy(in, out);
out.close();
} catch (Exception e) {
e.printStackTrace();
LogUtil.e("Error saving GIF called with: " + "from = [" + uri + "], in = [" + in + "]");
return false;
} finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException e) {
LogUtil.e("Error closing GIF called with: " + "from = [" + uri + "], out = [" + out + "]");
return false;
}
}
return true;
}
@Override
protected void onPostExecute(Boolean success) {
super.onPostExecute(success);
if (save) {
notifMgr.cancel(1);
if (success) {
doNotifGif(outFile, a);
} else {
showErrorDialog(a);
}
}
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
use of com.google.android.exoplayer2.source.dash.manifest.Representation in project ExoPlayer by google.
the class DashManifest method copyAdaptationSets.
private static ArrayList<AdaptationSet> copyAdaptationSets(List<AdaptationSet> adaptationSets, LinkedList<StreamKey> keys) {
StreamKey key = keys.poll();
int periodIndex = key.periodIndex;
ArrayList<AdaptationSet> copyAdaptationSets = new ArrayList<>();
do {
int adaptationSetIndex = key.groupIndex;
AdaptationSet adaptationSet = adaptationSets.get(adaptationSetIndex);
List<Representation> representations = adaptationSet.representations;
ArrayList<Representation> copyRepresentations = new ArrayList<>();
do {
Representation representation = representations.get(key.streamIndex);
copyRepresentations.add(representation);
key = keys.poll();
} while (key.periodIndex == periodIndex && key.groupIndex == adaptationSetIndex);
copyAdaptationSets.add(new AdaptationSet(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;
}
use of com.google.android.exoplayer2.source.dash.manifest.Representation in project ExoPlayer by google.
the class DashUtilTest method resolveCacheKey_representationCacheKeyIsNull_resolvesRangedUriWithFirstBaseUrl.
@Test
public void resolveCacheKey_representationCacheKeyIsNull_resolvesRangedUriWithFirstBaseUrl() {
ImmutableList<BaseUrl> baseUrls = ImmutableList.of(new BaseUrl("http://www.google.com"), new BaseUrl("http://www.foo.com"));
Representation.SingleSegmentRepresentation representation = new Representation.SingleSegmentRepresentation(/* revisionId= */
1L, new Format.Builder().build(), baseUrls, new SingleSegmentBase(), /* inbandEventStreams= */
null, /* essentialProperties= */
ImmutableList.of(), /* supplementalProperties= */
ImmutableList.of(), /* cacheKey= */
null, /* contentLength= */
1);
RangedUri rangedUri = new RangedUri("path/to/resource", /* start= */
0, /* length= */
1);
String cacheKey = DashUtil.resolveCacheKey(representation, rangedUri);
assertThat(cacheKey).isEqualTo("http://www.google.com/path/to/resource");
}
Aggregations