@Override public void getTrackMediaFormat(int track, MediaFormatHolder mediaFormatHolder) { int height = ffGetHeight(pFormatCtx, track); int width = ffGetWidth(pFormatCtx, track); // int bitrate = ffGetBitrate(pFormatCtx, track); // int channels = ffGetChannelCount(pFormatCtx, track); // int sampleRate = ffGetSampleRate(pFormatCtx, track); byte[] initData = ffGetInitData(pFormatCtx, track); List<byte[]> initList = new ArrayList<byte[]>(); // Split SPS/PPS data by start code and insert into initialization data int i, start; for (i = 4, start = 0; i < initData.length; i++) { // Found a new start code - add the last byte array to the list if (i + 4 <= initData.length && initData[i] == 0 && initData[i + 1] == 0 && initData[i + 2] == 0 && initData[i + 3] == 1) { byte[] csd = new byte[i - start]; System.arraycopy(initData, start, csd, 0, i - start); initList.add(csd); Log.d(TAG, "inserted csd " + csd.length); start = i; } } // Insert the last csd if (i > start) { byte[] csd = new byte[i - start]; System.arraycopy(initData, start, csd, 0, i - start); initList.add(csd); Log.d(TAG, "inserted final csd " + csd.length); } MediaFormat format = MediaFormat.createVideoFormat( mTrackInfos[track].mimeType, 10 * 1024 * 1024, width, height, 1, initList); mediaFormatHolder.format = format; // Start playing the stream // ffPlay(pFormatCtx); }
private MediaFormat initManifestTrack( SmoothStreamingManifest manifest, int elementIndex, int trackIndex) { int manifestTrackKey = getManifestTrackKey(elementIndex, trackIndex); MediaFormat mediaFormat = mediaFormats.get(manifestTrackKey); if (mediaFormat != null) { // Already initialized. return mediaFormat; } // Build the media format. long durationUs = live ? C.UNKNOWN_TIME_US : manifest.durationUs; StreamElement element = manifest.streamElements[elementIndex]; Format format = element.tracks[trackIndex].format; byte[][] csdArray = element.tracks[trackIndex].csd; int mp4TrackType; switch (element.type) { case StreamElement.TYPE_VIDEO: mediaFormat = MediaFormat.createVideoFormat( format.mimeType, format.bitrate, MediaFormat.NO_VALUE, durationUs, format.width, format.height, 0, Arrays.asList(csdArray)); mp4TrackType = Track.TYPE_vide; break; case StreamElement.TYPE_AUDIO: List<byte[]> csd; if (csdArray != null) { csd = Arrays.asList(csdArray); } else { csd = Collections.singletonList( CodecSpecificDataUtil.buildAacAudioSpecificConfig( format.audioSamplingRate, format.audioChannels)); } mediaFormat = MediaFormat.createAudioFormat( format.mimeType, format.bitrate, MediaFormat.NO_VALUE, durationUs, format.audioChannels, format.audioSamplingRate, csd); mp4TrackType = Track.TYPE_soun; break; case StreamElement.TYPE_TEXT: mediaFormat = MediaFormat.createTextFormat( format.mimeType, format.bitrate, format.language, durationUs); mp4TrackType = Track.TYPE_text; break; default: throw new IllegalStateException("Invalid type: " + element.type); } // Build the extractor. FragmentedMp4Extractor mp4Extractor = new FragmentedMp4Extractor( FragmentedMp4Extractor.WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME); Track mp4Track = new Track( trackIndex, mp4TrackType, element.timescale, durationUs, mediaFormat, trackEncryptionBoxes, mp4TrackType == Track.TYPE_vide ? 4 : -1); mp4Extractor.setTrack(mp4Track); // Store the format and a wrapper around the extractor. mediaFormats.put(manifestTrackKey, mediaFormat); extractorWrappers.put(manifestTrackKey, new ChunkExtractorWrapper(mp4Extractor)); return mediaFormat; }