如何使用rotation-degrees手动旋转(rotate)exoplayer2播放器

效果展示

旋转前的显示:


image.png

旋转处理后的效果:


image.png

如何实现

方法一. 最直接的想法是进行横竖屏切换.

Activity变成横屏显示了, 视频播放自然也就全屏了. 没什么可细说的.
这个做法也有缺点: 有些情况下某些页面不允许进行横竖屏切换, 或者横竖屏切换后, 仍然要保持其他显示元素与竖屏时一样. 我们现在这个产品的需求就是这么要求的. 那就需要另想办法了.

方法二. 旋转view控件.

对于exoplayer2 来说支持surface view 和texture view两种显示. surface view基本就没办法旋转了.
官方的issue里有这方面的讨论, 及示例做法:
https://github.com/google/ExoPlayer/issues/3843
然后这个办法最后呈现出来的效果, 却不是我想要的. 简单的旋转view之后, 效果是这样的:

image.png

方法三. 定制MediaCodecVideoRenderer, 设置rotation-degrees参数

目前我们产品用的exoplayer2的版本是2.6.1 对于最新版本的2.8.3, 做法稍有不同, 但是同样的思路都能实现.
具体来说就是扩展默认的MediaCodecVideoRenderer和DefaultRenderersFactory

先是自定义SogoDefaultRenderersFactory 扩展DefaultRenderersFactory , 从而能够返回我们自定义的MediaCodecVideoRenderer类实例

public class SogoDefaultRenderersFactory extends DefaultRenderersFactory {

    public SogoDefaultRenderersFactory(Context context) {
        super(context);
    }

    public SogoDefaultRenderersFactory(Context context, @Nullable DrmSessionManager<FrameworkMediaCrypto> drmSessionManager) {
        super(context, drmSessionManager);
    }

    public SogoDefaultRenderersFactory(Context context, @Nullable DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, int extensionRendererMode) {
        super(context, drmSessionManager, extensionRendererMode);
    }

    public SogoDefaultRenderersFactory(Context context, @Nullable DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, int extensionRendererMode, long allowedVideoJoiningTimeMs) {
        super(context, drmSessionManager, extensionRendererMode, allowedVideoJoiningTimeMs);
    }


    @Override
    protected void buildVideoRenderers(Context context, @Nullable DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, long allowedVideoJoiningTimeMs, Handler eventHandler, VideoRendererEventListener eventListener, int extensionRendererMode, ArrayList<Renderer> out) {
        super.buildVideoRenderers(context, drmSessionManager, allowedVideoJoiningTimeMs, eventHandler, eventListener, extensionRendererMode, out);
        for (int i = out.size() - 1; i >= 0; i--) {
            Renderer renderer = out.get(i);
            if (renderer instanceof MediaCodecVideoRenderer) {
                out.remove(renderer);
                out.add(i, new SogoMediaCodecVideoRenderer(context, MediaCodecSelector.DEFAULT,
                        allowedVideoJoiningTimeMs, drmSessionManager, false, eventHandler, eventListener,
                        MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY));
            }
        }
    }
}

下面是自定义扩展MediaCodecVideoRenderer类: 在getMediaFormat中对生成的MediaFormat 设置旋转角度. 这里是90度.

ublic class SogoMediaCodecVideoRenderer extends MediaCodecVideoRenderer {
    public SogoMediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector) {
        super(context, mediaCodecSelector);
    }

    public SogoMediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector, long allowedJoiningTimeMs) {
        super(context, mediaCodecSelector, allowedJoiningTimeMs);
    }

    public SogoMediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector, long allowedJoiningTimeMs, @Nullable Handler eventHandler, @Nullable VideoRendererEventListener eventListener, int maxDroppedFrameCountToNotify) {
        super(context, mediaCodecSelector, allowedJoiningTimeMs, eventHandler, eventListener, maxDroppedFrameCountToNotify);
    }

    public SogoMediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector, long allowedJoiningTimeMs, @Nullable DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys, @Nullable Handler eventHandler, @Nullable VideoRendererEventListener eventListener, int maxDroppedFramesToNotify) {
        super(context, mediaCodecSelector, allowedJoiningTimeMs, drmSessionManager, playClearSamplesWithoutKeys, eventHandler, eventListener, maxDroppedFramesToNotify);
    }

    @Override
    protected MediaFormat getMediaFormat(Format format, CodecMaxValues codecMaxValues, boolean deviceNeedsAutoFrcWorkaround, int tunnelingAudioSessionId) {
        MediaFormat mediaFormat = super.getMediaFormat(format, codecMaxValues, deviceNeedsAutoFrcWorkaround, tunnelingAudioSessionId);
        mediaFormat.setInteger("rotation-degrees", 90);
        return mediaFormat;
    }
}

对于竖屏比例视频和横屏比例视频混杂的情况下, 怎么才能判断当前是横屏视频呢?
-- 可以通过为exoplayer设置VideoListener, 来监听视频流的宽高比. 具体接口实现:

public interface VideoListener {

    .............
    void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees,
        float pixelWidthHeightRatio);
....
  }

通过width和heigh参数可知视频流的宽高.
当发现是横屏视频流之后, 我的做法是马上重建了一个exoplayer播放器, 并在创建这个新的播放器时,使用上面定义的两个扩展类.

.....
 var player = ExoPlayerFactory.newSimpleInstance(SogoDefaultRenderersFactory(application),
            mTrackSelector)
....

这个方法有个缺点, 只支持5.0之后的版本, 因为这个参数rotation-degrees只在5.0之后支持

代码示例

马上就来

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266