@Override protected DecoderInfo getDecoderInfo(MediaCodecSelector codecSelector, String mimeType, boolean requiresSecureDecoder) throws MediaCodecUtil.DecoderQueryException { try { if (mIsSwCodecEnabled && mCodecIsSwPreferred) { DecoderInfo swCodec = MediaSoftwareCodecUtil.getSoftwareDecoderInfo( mimeType, requiresSecureDecoder); if (swCodec != null) { return swCodec; } } } catch (MediaSoftwareCodecUtil.DecoderQueryException e) { } return super.getDecoderInfo(codecSelector, mimeType,requiresSecureDecoder); }
@Override protected boolean handlesTrack(MediaFormat mediaFormat) throws DecoderQueryException { // TODO: Use MediaCodecList.findDecoderForFormat on API 23. String mimeType = mediaFormat.mimeType; return MimeTypes.isVideo(mimeType) && (MimeTypes.VIDEO_UNKNOWN.equals(mimeType) || MediaCodecUtil.getDecoderInfo(mimeType, false) != null); }
private boolean shouldSkipAdaptiveTest(String mimeType) throws IOException { if (!MediaCodecUtil.getDecoderInfo(mimeType, false).adaptive) { assertTrue(Util.SDK_INT < 21); return true; } return false; }
/** * Determines whether an individual format is playable, given an array of allowed container types, * whether HD formats should be filtered and a maximum decodable frame size in pixels. */ private static boolean isFormatPlayable(Format format, String[] allowedContainerMimeTypes, boolean filterHdFormats) throws DecoderQueryException { if (allowedContainerMimeTypes != null && !Util.contains(allowedContainerMimeTypes, format.mimeType)) { // Filtering format based on its container mime type. return false; } if (filterHdFormats && (format.width >= 1280 || format.height >= 720)) { // Filtering format because it's HD. return false; } if (format.width > 0 && format.height > 0) { if (Util.SDK_INT >= 21) { String videoMediaMimeType = MimeTypes.getVideoMediaMimeType(format.codecs); if (MimeTypes.VIDEO_UNKNOWN.equals(videoMediaMimeType)) { // Assume the video is H.264. videoMediaMimeType = MimeTypes.VIDEO_H264; } if (format.frameRate > 0) { return MediaCodecUtil.isSizeAndRateSupportedV21(videoMediaMimeType, false, format.width, format.height, format.frameRate); } else { return MediaCodecUtil.isSizeSupportedV21(videoMediaMimeType, false, format.width, format.height); } } // Assume the video is H.264. if (format.width * format.height > MediaCodecUtil.maxH264DecodableFrameSize()) { // Filtering format because it exceeds the maximum decodable frame size. return false; } } return true; }
@Override public DecoderInfo getDecoderInfo(String mimeType, boolean requiresSecureDecoder) throws MediaCodecUtil.DecoderQueryException { Log.d("Kaltura", "DeviceInfo: " + Util.getDeviceInfo() + ", mimeType:" + mimeType + ", requiresSecureDecoder" + requiresSecureDecoder); if (!requiresSecureDecoder && !isVendorSupportDefaultDecoder()) { DecoderInfo decoderInfo = MediaCodecUtil.getDecoderInfo(mimeType, requiresSecureDecoder); Log.d("Kaltura", "Using Decoder = " + decoderInfo.name); return decoderInfo; } Log.d("Kaltura", "Using Default Decoder"); return MediaCodecSelector.DEFAULT.getDecoderInfo(mimeType,requiresSecureDecoder); }
@Override public void onManifest(String contentId, SmoothStreamingManifest manifest) { Handler mainHandler = playerActivity.getMainHandler(); LoadControl loadControl = new DefaultLoadControl(new BufferPool(BUFFER_SEGMENT_SIZE)); DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); // Obtain stream elements for playback. int maxDecodableFrameSize = MediaCodecUtil.maxH264DecodableFrameSize(); int audioStreamElementIndex = -1; int videoStreamElementIndex = -1; ArrayList<Integer> videoTrackIndexList = new ArrayList<Integer>(); for (int i = 0; i < manifest.streamElements.length; i++) { if (audioStreamElementIndex == -1 && manifest.streamElements[i].type == StreamElement.TYPE_AUDIO) { audioStreamElementIndex = i; } else if (videoStreamElementIndex == -1 && manifest.streamElements[i].type == StreamElement.TYPE_VIDEO) { videoStreamElementIndex = i; StreamElement streamElement = manifest.streamElements[i]; for (int j = 0; j < streamElement.tracks.length; j++) { TrackElement trackElement = streamElement.tracks[j]; if (trackElement.maxWidth * trackElement.maxHeight <= maxDecodableFrameSize) { videoTrackIndexList.add(j); } else { // The device isn't capable of playing this stream. } } } } int[] videoTrackIndices = Util.toArray(videoTrackIndexList); // Build the video renderer. DataSource videoDataSource = new UriDataSource(userAgent, bandwidthMeter); ChunkSource videoChunkSource = new SmoothStreamingChunkSource(manifestFetcher, videoStreamElementIndex, videoTrackIndices, videoDataSource, new AdaptiveEvaluator(bandwidthMeter), LIVE_EDGE_LATENCY_MS); ChunkSampleSource videoSampleSource = new ChunkSampleSource(videoChunkSource, loadControl, VIDEO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, true); MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(videoSampleSource, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 0, mainHandler, playerActivity, 50); // Build the audio renderer. DataSource audioDataSource = new UriDataSource(userAgent, bandwidthMeter); ChunkSource audioChunkSource = new SmoothStreamingChunkSource(manifestFetcher, audioStreamElementIndex, new int[] {0}, audioDataSource, new FormatEvaluator.FixedEvaluator(), LIVE_EDGE_LATENCY_MS); SampleSource audioSampleSource = new ChunkSampleSource(audioChunkSource, loadControl, AUDIO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, true); MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer( audioSampleSource); callback.onRenderers(videoRenderer, audioRenderer); }
@Override public void onError(Exception e) { String errMsg = "Player Error"; LOGE(TAG, errMsg, e); String errorString = ""; if (e instanceof UnsupportedDrmException) { // Special case DRM failures. UnsupportedDrmException unsupportedDrmException = (UnsupportedDrmException) e; errorString = (Util.SDK_INT < 18) ? "error_drm_not_supported" : unsupportedDrmException.reason == UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME ? "error_drm_unsupported_scheme" : "error_drm_unknown"; } else if (e instanceof ExoPlaybackException && e.getCause() instanceof FileNotFoundException) { errorString = "DRM License Unavailable"; // probably license issue } else if (e instanceof ExoPlaybackException && e.getCause() instanceof BehindLiveWindowException) { LOGE(TAG, "Recovering BehindLiveWindowException"); // happens if network is bad and no more chunk in hte buffer mExoPlayer.prepare(); return; } else if (e instanceof ExoPlaybackException && e.getCause() instanceof android.media.MediaCodec.CryptoException) { errorString = "DRM Error. Trying to recover"; // probably license issue mExoPlayer.prepare(); return; } else if (e instanceof ExoPlaybackException && e.getCause() instanceof MediaCodecTrackRenderer.DecoderInitializationException) { // Special case for decoder initialization failures. MediaCodecTrackRenderer.DecoderInitializationException decoderInitializationException = (MediaCodecTrackRenderer.DecoderInitializationException) e.getCause(); if (decoderInitializationException.decoderName == null) { if (decoderInitializationException.getCause() instanceof MediaCodecUtil.DecoderQueryException) { errorString = "error_querying_decoders "; } else if (decoderInitializationException.secureDecoderRequired) { errorString = "error_no_secure_decoder " + decoderInitializationException.mimeType; } else { errorString = "error_no_decoder " + decoderInitializationException.mimeType; } } else { errorString = "error_instantiating_decoder " + decoderInitializationException.decoderName; } } else if (e.getCause() instanceof com.google.android.exoplayer.upstream.HttpDataSource.HttpDataSourceException) { mExoPlayer.prepare(); errorString = "HttpDataSourceException . Trying to recover"; LOGE(TAG, errorString); return; } else if (e.getCause() instanceof java.net.UnknownHostException) { mExoPlayer.prepare(); errorString = "UnknownHostException . Trying to recover"; LOGE(TAG, errorString); return; } else if (e.getCause() instanceof java.net.ConnectException) { mExoPlayer.prepare(); errorString = "ConnectException . Trying to recover"; LOGE(TAG, errorString); return; } else if (e.getCause() instanceof java.lang.IllegalStateException) { mExoPlayer.prepare(); errorString = "IllegalStateException . Trying to recover"; LOGE(TAG, errorString); return; } if (!"".equals(errorString)) { LOGE(TAG, errorString); errorString += "-"; } mPlayerListener.eventWithValue(KExoPlayer.this, KPlayerListener.ErrorKey, TAG + "-" + errMsg + "-" + errorString + e.getMessage()); }
@Override public DecoderInfo getPassthroughDecoderInfo() throws MediaCodecUtil.DecoderQueryException { return MediaCodecSelector.DEFAULT.getPassthroughDecoderInfo(); }