/** * * @param media * @param vlcTracks * @param lib * @return */ static com.google.android.exoplayer.TrackInfo[] vlc2exoTracks(long duration, org.videolan.libvlc.Media.Track[] vlcTracks, LibVLC lib) { com.google.android.exoplayer.TrackInfo[] res = new com.google.android.exoplayer.TrackInfo[vlcTracks.length]; System.out.println("ExoVlcUtil.vlc2exoTracks() vlcTracks = " + vlcTracks.length); // Media.Track for (int i = 0; i < res.length; i++) { MediaFormat mf = track2mediaFormat(vlcTracks[i]); res[i] = new TrackInfo(mf.getString(MediaFormat.KEY_MIME), duration); System.out.println("\t track " + i + " mime type =" + mf.getString(MediaFormat.KEY_MIME) + " duration =" + duration); } /* * System.out.println(">>>> ExoVlcUtil.vlc2exoTracks() vlcTracks.length = " * +vlcTracks.length); long l; for (int i = 0; i < vlcTracks.length; * i++) { org.videolan.libvlc.TrackInfo vt = vlcTracks[i]; * System.out.println("\t\t >>>>>Codec("+i+") "+vlcTracks[i].Codec); * res[i] = new TrackInfo( vt.Codec, (l=lib.getLength()) == -1 ? * com.google.android.exoplayer.C.UNKNOWN_TIME_US : l * MS_2_MICRO); } */ return res; }
@Override public boolean prepare() throws IOException { if (context != null) { mediaExtractor.setDataSource(context, uri, headers); } else { mediaExtractor.setDataSource(fileDescriptor, fileDescriptorOffset, fileDescriptorLength); } int trackCount = mediaExtractor.getTrackCount(); trackInfos = new TrackInfo[trackCount]; for (int i = 0; i < trackCount; i++) { android.media.MediaFormat format = mediaExtractor.getTrackFormat(i); long durationUs = format.containsKey(android.media.MediaFormat.KEY_DURATION) ? format.getLong(android.media.MediaFormat.KEY_DURATION) : C.UNKNOWN_TIME_US; String mime = format.getString(android.media.MediaFormat.KEY_MIME); trackInfos[i] = new TrackInfo(mime, durationUs); } return true; }
@Override public boolean prepare() throws IOException { if (!prepared) { extractor = new MediaExtractor(); extractor.setDataSource(context, uri, headers); trackStates = new int[extractor.getTrackCount()]; pendingDiscontinuities = new boolean[trackStates.length]; trackInfos = new TrackInfo[trackStates.length]; for (int i = 0; i < trackStates.length; i++) { android.media.MediaFormat format = extractor.getTrackFormat(i); long duration = format.containsKey(android.media.MediaFormat.KEY_DURATION) ? format.getLong(android.media.MediaFormat.KEY_DURATION) : TrackRenderer.UNKNOWN_TIME_US; String mime = format.getString(android.media.MediaFormat.KEY_MIME); trackInfos[i] = new TrackInfo(mime, duration); } prepared = true; } return true; }
/** * @param dataSource A {@link DataSource} suitable for loading the sample data. * @param dataSpec Defines the location of the sample. * @param format The format of the sample. * @param durationUs The duration of the sample in microseconds, or {@link C#UNKNOWN_TIME_US} if * the duration is unknown, or {@link C#MATCH_LONGEST_US} if the duration should match the * duration of the longest track whose duration is known. * @param mediaFormat The sample media format. May be null. */ public SingleSampleChunkSource(DataSource dataSource, DataSpec dataSpec, Format format, long durationUs, MediaFormat mediaFormat) { this.dataSource = dataSource; this.dataSpec = dataSpec; this.format = format; this.durationUs = durationUs; this.mediaFormat = mediaFormat; trackInfo = new TrackInfo(format.mimeType, durationUs); }
/** * @param dataSource A {@link DataSource} suitable for loading the sample data. * @param dataSpec Defines the location of the sample. * @param format The format of the sample. * @param durationUs The duration of the sample in microseconds, or {@link C#UNKNOWN_TIME_US} if * the duration is unknown. * @param mediaFormat The sample media format. May be null. */ public SingleSampleChunkSource(DataSource dataSource, DataSpec dataSpec, Format format, long durationUs, MediaFormat mediaFormat) { this.dataSource = dataSource; this.dataSpec = dataSpec; this.format = format; this.durationUs = durationUs; this.mediaFormat = mediaFormat; trackInfo = new TrackInfo(format.mimeType, durationUs); }
private DashChunkSource(ManifestFetcher<MediaPresentationDescription> manifestFetcher, MediaPresentationDescription initialManifest, int adaptationSetIndex, int[] representationIndices, DataSource dataSource, FormatEvaluator formatEvaluator, long liveEdgeLatencyUs) { this.manifestFetcher = manifestFetcher; this.currentManifest = initialManifest; this.adaptationSetIndex = adaptationSetIndex; this.representationIndices = representationIndices; this.dataSource = dataSource; this.evaluator = formatEvaluator; this.liveEdgeLatencyUs = liveEdgeLatencyUs; this.evaluation = new Evaluation(); this.headerBuilder = new StringBuilder(); psshInfo = getPsshInfo(currentManifest, adaptationSetIndex); Representation[] representations = getFilteredRepresentations(currentManifest, adaptationSetIndex, representationIndices); long periodDurationUs = (representations[0].periodDurationMs == TrackRenderer.UNKNOWN_TIME_US) ? TrackRenderer.UNKNOWN_TIME_US : representations[0].periodDurationMs * 1000; this.trackInfo = new TrackInfo(representations[0].format.mimeType, periodDurationUs); this.formats = new Format[representations.length]; this.representationHolders = new HashMap<String, RepresentationHolder>(); int maxWidth = 0; int maxHeight = 0; for (int i = 0; i < representations.length; i++) { formats[i] = representations[i].format; maxWidth = Math.max(formats[i].width, maxWidth); maxHeight = Math.max(formats[i].height, maxHeight); Extractor extractor = mimeTypeIsWebm(formats[i].mimeType) ? new WebmExtractor() : new FragmentedMp4Extractor(); representationHolders.put(formats[i].id, new RepresentationHolder(representations[i], extractor)); } this.maxWidth = maxWidth; this.maxHeight = maxHeight; Arrays.sort(formats, new DecreasingBandwidthComparator()); }
@Override public TrackInfo[] getTrackInfos() { Assertions.checkState(prepared); TrackInfo[] r = new TrackInfo[trackInfos.length]; System.arraycopy(trackInfos, 0, r, 0, trackInfos.length); return r; }
boolean isActiveTrack(int track) { Assertions.checkState(prepared); System.out.println(">>> VLCSampleExtractor.isActiveTrack() track = " + track); System.out.println(">>> VLCSampleExtractor.isActiveTrack() vlctracks.length = " + vlctracks.length); System.out.println(">>> VLCSampleExtractor.isActiveTrack() trackInfos.length = " + trackInfos.length); if (vlctracks.length != trackInfos.length) { if ((track < 0) && (track >= trackInfos.length)) { ExoVlcUtil.log(this, "getTrackMediaFormat() out of range : " + track + "; track len=" + trackInfos.length); return false; } /* * if(track == trackInfos.length - 1 ) return true; */ TrackInfo t = trackInfos[track]; System.out.println(">>> VLCSampleExtractor.isActiveTrack() track mime = " + t.mimeType); System.out.println(">>> VLCSampleExtractor.isActiveTrack() isVLCAudioMimeType = " + ExoVlcUtil.isVLCAudioMimeType(t.mimeType)); System.out.println(">>> VLCSampleExtractor.isActiveTrack() isVLCVideoMimeType= " + ExoVlcUtil.isVLCVideoMimeType(t.mimeType)); if ((ExoVlcUtil.isVLCAudioMimeType(t.mimeType) && track == lib.getAudioTrack()) || (ExoVlcUtil.isVLCVideoMimeType(t.mimeType))) return true; return false; } if ((track < 0) && (track >= vlctracks.length)) { ExoVlcUtil.log(this, "getTrackMediaFormat() out of range : " + track + "; track len=" + vlctracks.length); return false; } Track vt = vlctracks[track]; if ((vt.type == Track.Type.Video) || (vt.type == Track.Type.Audio && track == lib.getAudioTrack()) || (vt.type == Track.Type.Text && track == lib.getSpuTrack())) return true; return false; }
@Override public TrackInfo getTrackInfo(int track) { Assertions.checkState(prepared); TrackInfo[] infos = extractor.getTrackInfos(); if (track >= 0 && track < infos.length) return infos[track]; ExoVlcUtil.log(this, " getTrackInfo : track=" + track + " is out of range [strat:0,lenght:" + infos.length + "] => ret NULL"); return null; }
/** * @param dataSource A {@link DataSource} suitable for loading the media data. * @param evaluator Selects from the available formats. * @param representations The representations to be considered by the source. */ public DashChunkSource(DataSource dataSource, FormatEvaluator evaluator, Representation... representations) { this.dataSource = dataSource; this.evaluator = evaluator; this.formats = new Format[representations.length]; this.extractors = new HashMap<String, Extractor>(); this.segmentIndexes = new HashMap<String, DashSegmentIndex>(); this.representations = new HashMap<String, Representation>(); this.trackInfo = new TrackInfo(representations[0].format.mimeType, representations[0].periodDurationMs * 1000); this.evaluation = new Evaluation(); int maxWidth = 0; int maxHeight = 0; for (int i = 0; i < representations.length; i++) { formats[i] = representations[i].format; maxWidth = Math.max(formats[i].width, maxWidth); maxHeight = Math.max(formats[i].height, maxHeight); Extractor extractor = formats[i].mimeType.startsWith(MimeTypes.VIDEO_WEBM) ? new WebmExtractor() : new FragmentedMp4Extractor(); extractors.put(formats[i].id, extractor); this.representations.put(formats[i].id, representations[i]); DashSegmentIndex segmentIndex = representations[i].getIndex(); if (segmentIndex != null) { segmentIndexes.put(formats[i].id, segmentIndex); } } this.maxWidth = maxWidth; this.maxHeight = maxHeight; Arrays.sort(formats, new DecreasingBandwidthComparator()); }
@Override public TrackInfo getTrackInfo(int track) { Assertions.checkState(prepared); return trackInfos[track]; }
@Override public TrackInfo getTrackInfo() { return selectedSource.getTrackInfo(); }
@Override public TrackInfo getTrackInfo() { return trackInfo; }
@Override public TrackInfo getTrackInfo(int track) { Assertions.checkState(state == STATE_PREPARED || state == STATE_ENABLED); Assertions.checkState(track == 0); return chunkSource.getTrackInfo(); }
DashChunkSource(ManifestFetcher<MediaPresentationDescription> manifestFetcher, MediaPresentationDescription initialManifest, int adaptationSetIndex, int[] representationIndices, DataSource dataSource, FormatEvaluator formatEvaluator, Clock systemClock, long liveEdgeLatencyUs, long elapsedRealtimeOffsetUs, boolean startAtLiveEdge, Handler eventHandler, EventListener eventListener) { this.manifestFetcher = manifestFetcher; this.currentManifest = initialManifest; this.adaptationSetIndex = adaptationSetIndex; this.representationIndices = representationIndices; this.dataSource = dataSource; this.formatEvaluator = formatEvaluator; this.systemClock = systemClock; this.liveEdgeLatencyUs = liveEdgeLatencyUs; this.elapsedRealtimeOffsetUs = elapsedRealtimeOffsetUs; this.startAtLiveEdge = startAtLiveEdge; this.eventHandler = eventHandler; this.eventListener = eventListener; this.evaluation = new Evaluation(); this.headerBuilder = new StringBuilder(); this.seekRangeValues = new long[2]; drmInitData = getDrmInitData(currentManifest, adaptationSetIndex); Representation[] representations = getFilteredRepresentations(currentManifest, adaptationSetIndex, representationIndices); long periodDurationUs = (representations[0].periodDurationMs == TrackRenderer.UNKNOWN_TIME_US) ? TrackRenderer.UNKNOWN_TIME_US : representations[0].periodDurationMs * 1000; this.trackInfo = new TrackInfo(representations[0].format.mimeType, periodDurationUs); this.formats = new Format[representations.length]; this.representationHolders = new HashMap<>(); int maxWidth = 0; int maxHeight = 0; for (int i = 0; i < representations.length; i++) { formats[i] = representations[i].format; maxWidth = Math.max(formats[i].width, maxWidth); maxHeight = Math.max(formats[i].height, maxHeight); Extractor extractor = mimeTypeIsWebm(formats[i].mimeType) ? new WebmExtractor() : new FragmentedMp4Extractor(); representationHolders.put(formats[i].id, new RepresentationHolder(representations[i], new ChunkExtractorWrapper(extractor))); } this.maxWidth = maxWidth; this.maxHeight = maxHeight; Arrays.sort(formats, new DecreasingBandwidthComparator()); }
@Override public final TrackInfo getTrackInfo() { return trackInfo; }
private SmoothStreamingChunkSource(ManifestFetcher<SmoothStreamingManifest> manifestFetcher, SmoothStreamingManifest initialManifest, int streamElementIndex, int[] trackIndices, DataSource dataSource, FormatEvaluator formatEvaluator, long liveEdgeLatencyMs) { this.manifestFetcher = manifestFetcher; this.streamElementIndex = streamElementIndex; this.currentManifest = initialManifest; this.dataSource = dataSource; this.formatEvaluator = formatEvaluator; this.liveEdgeLatencyUs = liveEdgeLatencyMs * 1000; StreamElement streamElement = getElement(initialManifest); trackInfo = new TrackInfo(streamElement.tracks[0].format.mimeType, initialManifest.durationUs); evaluation = new Evaluation(); TrackEncryptionBox[] trackEncryptionBoxes = null; ProtectionElement protectionElement = initialManifest.protectionElement; if (protectionElement != null) { byte[] keyId = getKeyId(protectionElement.data); trackEncryptionBoxes = new TrackEncryptionBox[1]; trackEncryptionBoxes[0] = new TrackEncryptionBox(true, INITIALIZATION_VECTOR_SIZE, keyId); DrmInitData.Mapped drmInitData = new DrmInitData.Mapped(MimeTypes.VIDEO_MP4); drmInitData.put(protectionElement.uuid, protectionElement.data); this.drmInitData = drmInitData; } else { drmInitData = null; } int trackCount = trackIndices != null ? trackIndices.length : streamElement.tracks.length; formats = new Format[trackCount]; extractorWrappers = new SparseArray<>(); mediaFormats = new SparseArray<>(); int maxWidth = 0; int maxHeight = 0; for (int i = 0; i < trackCount; i++) { int trackIndex = trackIndices != null ? trackIndices[i] : i; formats[i] = streamElement.tracks[trackIndex].format; maxWidth = Math.max(maxWidth, formats[i].width); maxHeight = Math.max(maxHeight, formats[i].height); MediaFormat mediaFormat = getMediaFormat(streamElement, trackIndex); int trackType = streamElement.type == StreamElement.TYPE_VIDEO ? Track.TYPE_VIDEO : Track.TYPE_AUDIO; FragmentedMp4Extractor extractor = new FragmentedMp4Extractor( FragmentedMp4Extractor.WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME); extractor.setTrack(new Track(trackIndex, trackType, streamElement.timescale, initialManifest.durationUs, mediaFormat, trackEncryptionBoxes, trackType == Track.TYPE_VIDEO ? 4 : -1)); extractorWrappers.put(trackIndex, new ChunkExtractorWrapper(extractor)); mediaFormats.put(trackIndex, mediaFormat); } this.maxWidth = maxWidth; this.maxHeight = maxHeight; Arrays.sort(formats, new DecreasingBandwidthComparator()); }
@Override public TrackInfo getTrackInfo(int track) { Assertions.checkState(state != STATE_UNPREPARED); Assertions.checkState(track == 0); return chunkSource.getTrackInfo(); }
private SmoothStreamingChunkSource(ManifestFetcher<SmoothStreamingManifest> manifestFetcher, SmoothStreamingManifest initialManifest, int streamElementIndex, int[] trackIndices, DataSource dataSource, FormatEvaluator formatEvaluator, long liveEdgeLatencyMs) { this.manifestFetcher = manifestFetcher; this.streamElementIndex = streamElementIndex; this.currentManifest = initialManifest; this.dataSource = dataSource; this.formatEvaluator = formatEvaluator; this.liveEdgeLatencyUs = liveEdgeLatencyMs * 1000; StreamElement streamElement = getElement(initialManifest); trackInfo = new TrackInfo(streamElement.tracks[0].mimeType, initialManifest.durationUs); evaluation = new Evaluation(); TrackEncryptionBox[] trackEncryptionBoxes = null; ProtectionElement protectionElement = initialManifest.protectionElement; if (protectionElement != null) { byte[] keyId = getKeyId(protectionElement.data); trackEncryptionBoxes = new TrackEncryptionBox[1]; trackEncryptionBoxes[0] = new TrackEncryptionBox(true, INITIALIZATION_VECTOR_SIZE, keyId); psshInfo = Collections.singletonMap(protectionElement.uuid, protectionElement.data); } else { psshInfo = null; } int trackCount = trackIndices != null ? trackIndices.length : streamElement.tracks.length; formats = new SmoothStreamingFormat[trackCount]; extractors = new SparseArray<FragmentedMp4Extractor>(); int maxWidth = 0; int maxHeight = 0; for (int i = 0; i < trackCount; i++) { int trackIndex = trackIndices != null ? trackIndices[i] : i; TrackElement trackElement = streamElement.tracks[trackIndex]; formats[i] = new SmoothStreamingFormat(String.valueOf(trackIndex), trackElement.mimeType, trackElement.maxWidth, trackElement.maxHeight, trackElement.numChannels, trackElement.sampleRate, trackElement.bitrate, trackIndex); maxWidth = Math.max(maxWidth, trackElement.maxWidth); maxHeight = Math.max(maxHeight, trackElement.maxHeight); MediaFormat mediaFormat = getMediaFormat(streamElement, trackIndex); int trackType = streamElement.type == StreamElement.TYPE_VIDEO ? Track.TYPE_VIDEO : Track.TYPE_AUDIO; FragmentedMp4Extractor extractor = new FragmentedMp4Extractor( FragmentedMp4Extractor.WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME); extractor.setTrack(new Track(trackIndex, trackType, streamElement.timescale, mediaFormat, trackEncryptionBoxes)); extractors.put(trackIndex, extractor); } this.maxHeight = maxHeight; this.maxWidth = maxWidth; Arrays.sort(formats, new DecreasingBandwidthComparator()); }
static TrackInfo[] getDummyVdoTrack(org.videolan.libvlc.Media media, String mime) { System.out.println(">>> ExoVlcUtil.getDummyVdoTrack() ---> duration = " + media.getDuration()); return new TrackInfo[] { new TrackInfo(mime, media.getDuration()) }; }
@Override public TrackInfo[] getTrackInfos() { return trackInfos; }
/** Returns track information about all tracks that can be selected. */ TrackInfo[] getTrackInfos();