You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Kotlin下强制ExoPlayer2使用H264解码RTSP流

解决ExoPlayer 2.18.5强制优先选择H264播放RTSP流的方案

针对RTSP流同时包含H264和H265轨道、且H265因参数缺失导致播放失败的问题,以下是几个可行的解决思路:

1. 自定义RTSP媒体源工厂,在SDP解析阶段过滤H265轨道

ExoPlayer处理RTSP流时会先解析SDP描述,我们可以拦截SDP内容,移除其中的H265媒体轨道信息,让播放器只能识别到H264轨道:

// 自定义RTSPMediaSource.Factory,重写createMediaSource方法
RTSPMediaSource.Factory rtspFactory = new RTSPMediaSource.Factory() {
    @Override
    public MediaSource createMediaSource(MediaItem mediaItem) {
        return new RTSPMediaSource(mediaItem, createDataSourceFactory(), eventListener, looper) {
            @Override
            protected SdpParser createSdpParser() {
                return new DefaultSdpParser() {
                    @Override
                    public Sdp parse(String sdpText) throws IOException {
                        // 修改SDP文本,移除H265相关的媒体描述
                        String filteredSdp = filterH265FromSdp(sdpText);
                        return super.parse(filteredSdp);
                    }
                };
            }
        };
    }
};

// 实现SDP过滤方法
private String filterH265FromSdp(String sdpText) {
    StringBuilder filtered = new StringBuilder();
    String[] lines = sdpText.split("\n");
    boolean skipH265Track = false;
    for (String line : lines) {
        // 检测是否是H265的媒体轨道(匹配负载类型102或H265标识)
        if (line.startsWith("m=video") && (line.contains("H265") || line.contains("102"))) {
            skipH265Track = true;
        }
        // 跳过当前H265轨道的所有行,直到遇到下一个媒体轨道定义
        if (skipH265Track) {
            if (line.startsWith("m=") && !line.contains("H265") && !line.contains("102")) {
                skipH265Track = false;
                filtered.append(line).append("\n");
            }
            continue;
        }
        filtered.append(line).append("\n");
    }
    return filtered.toString();
}

2. 使用自定义TrackSelector强制选择H264轨道

TrackSelector是ExoPlayer负责选择播放轨道的核心组件,通过设置规则可直接限制仅选择H264视频轨道:

// 创建DefaultTrackSelector并添加全局过滤规则
DefaultTrackSelector trackSelector = new DefaultTrackSelector(context);
trackSelector.setParameters(
    trackSelector.buildUponParameters()
        .setVideoMimeTypeFilter(MimeTypes.VIDEO_H264) // 仅允许H264格式的视频轨道
);

// 初始化播放器时传入该TrackSelector
ExoPlayer player = new ExoPlayer.Builder(context)
    .setTrackSelector(trackSelector)
    .build();

如果需要更精细的轨道控制,可自定义TrackSelection.Factory:

trackSelector.setTrackSelectionFactory(new TrackSelection.Factory() {
    @Override
    public TrackSelection createTrackSelection(TrackSelection.Definition definition) {
        // 过滤掉所有H265轨道
        List<TrackInfo> filteredTracks = new ArrayList<>();
        for (TrackInfo track : definition.getTrackInfos()) {
            if (track.getFormat().sampleMimeType.equals(MimeTypes.VIDEO_H264)) {
                filteredTracks.add(track);
            }
        }
        if (filteredTracks.isEmpty()) {
            // 无H264轨道时的 fallback 逻辑,可根据需求调整
            return new AdaptiveTrackSelection(definition);
        }
        return new AdaptiveTrackSelection(new TrackSelection.Definition(
            definition.getTrackGroupArray(),
            filteredTracks.stream().mapToInt(TrackInfo::getTrackIndex).toArray()
        ));
    }
});

3. 修正自定义MediaCodecSelector的实现

你之前的MediaCodecSelector无效,可能是实现逻辑存在漏洞,确保完全排除H265解码器:

MediaCodecSelector customCodecSelector = new MediaCodecSelector() {
    @Override
    public List<MediaCodecInfo> getDecoderInfos(String mimeType, boolean requiresSecureDecoder, boolean requiresTunnelingDecoder) throws DecoderQueryException {
        List<MediaCodecInfo> originalList = MediaCodecSelector.DEFAULT.getDecoderInfos(mimeType, requiresSecureDecoder, requiresTunnelingDecoder);
        // 查询H265解码器时直接返回空列表
        if (MimeTypes.VIDEO_H265.equals(mimeType)) {
            return Collections.emptyList();
        }
        return originalList;
    }
};

// 初始化播放器时设置该CodecSelector
ExoPlayer player = new ExoPlayer.Builder(context)
    .setMediaCodecSelector(customCodecSelector)
    .build();

建议结合TrackSelector的方法一起使用,避免播放器因H265轨道存在而优先尝试解码。


内容的提问来源于stack exchange,提问作者Lennart Zinn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 03:47:41