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

OnPreviewCallback方法下摄像头90度竖屏方向异常问题

解决NV21格式视频90度旋转方向问题

我看到你在做IP流媒体开发时碰到了竖屏模式下视频翻转、方向不正确的问题,而且已经尝试了nv21Converter和一段旋转NV21的代码,咱们来一步步拆解问题,找到靠谱的解决办法。

首先要明确,NV21是Android场景下常用的YUV格式,它的存储顺序是Y亮度分量平面在前,接着是V和U色度分量交替排列的平面。旋转这类格式时,必须同时正确处理Y和UV分量的位置,否则很容易出现画面方向错、颜色失真的情况。

你给出的rotateNV21代码框架是对的,但可能存在UV分量处理不到位的情况,我给你完善这段代码,确保90度旋转时Y和UV分量都能正确转换:

public static byte[] rotateNV21(final byte[] yuv, final int width, final int height, final int rotation) {
    if (rotation == 0) return yuv;
    if (rotation % 90 != 0 || rotation < 0 || rotation > 270) {
        throw new IllegalArgumentException("Rotation must be 0, 90, 180 or 270 degrees");
    }

    // 90/270度旋转时,宽高需要互换
    final int rotatedWidth = rotation % 180 == 0 ? width : height;
    final int rotatedHeight = rotation % 180 == 0 ? height : width;

    byte[] rotatedData = new byte[yuv.length];
    int ySize = width * height;
    int uvSize = ySize / 2;

    switch (rotation) {
        case 90:
            // 处理Y亮度分量
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    rotatedData[x * height + height - y - 1] = yuv[y * width + x];
                }
            }
            // 处理UV色度分量
            for (int y = 0; y < height / 2; y++) {
                for (int x = 0; x < width; x++) {
                    rotatedData[ySize + x * height + height - y - 1] = yuv[ySize + y * width + x];
                }
            }
            break;
        case 180:
            // 补充180度旋转逻辑(按需使用)
            int i = ySize - 1;
            for (int j = 0; j < ySize; j++) {
                rotatedData[i] = yuv[j];
                i--;
            }
            i = yuv.length - 1;
            for (int j = ySize; j < yuv.length; j++) {
                rotatedData[i] = yuv[j];
                i--;
            }
            break;
        case 270:
            // 补充270度旋转逻辑(按需使用)
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    rotatedData[(width - x - 1) * height + y] = yuv[y * width + x];
                }
            }
            for (int y = 0; y < height / 2; y++) {
                for (int x = 0; x < width; x++) {
                    rotatedData[ySize + (width - x - 1) * height + y] = yuv[ySize + y * width + x];
                }
            }
            break;
    }
    return rotatedData;
}

额外注意点:

  • 调用代码时,记得传入正确的原始宽高和旋转角度(竖屏场景传90),代码里已经自动处理了旋转后的宽高互换,后续渲染时要用rotatedWidth和rotatedHeight来设置画面尺寸
  • 还要检查流媒体传输的元数据:有些播放器会依赖SDP或协议头里的旋转标记来自动调整方向,如果只处理了原始数据旋转但没同步元数据,可能还是会出现显示异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 10:08:15