不同平台需要不同的代码(.java文件)?

3

我有一段代码,其中图像数据从位图传递到FFmpeg帧记录器并转换为视频。但是我需要在LG G3(armv7)上运行它时进行小修改,而不是在Asus zenfone 5(x86)上运行。

以下是创建问题的类变量:(声明在MainActivity类下)

inputWidth = 1024;

inputHeight = 650;

以下是出现问题的方法:

 byte [] getNV21(int inputWidth, int inputHeight, Bitmap bitmap) {

    int [] argb = new int[inputWidth * inputHeight];

    bitmap.getPixels(argb, 0, inputWidth, 0, 0, inputWidth, inputHeight);

    byte [] yuv = new byte[inputWidth*inputHeight*3/2];
    encodeYUV420SP(yuv, argb, inputWidth, inputHeight);

    return yuv;
}

void encodeYUV420SP(byte[] yuv420sp, int[] argb, int width, int height) {
    final int frameSize = width * height;

    int yIndex = 0;
    int uvIndex = frameSize;

    int a, R, G, B, Y, U, V;
    int index = 0;
    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i++) {

            a = (argb[index] & 0xff000000) >> 24; // a is not used obviously
            R = (argb[index] & 0xff0000) >> 16;
            G = (argb[index] & 0xff00) >> 8;
            B = (argb[index] & 0xff) >> 0;

            // well known RGB to YUV algorithm
            Y = ( (  66 * R + 129 * G +  25 * B + 128) >> 8) +  16;
            U = ( ( -38 * R -  74 * G + 112 * B + 128) >> 8) + 128;
            V = ( ( 112 * R -  94 * G -  18 * B + 128) >> 8) + 128;

            // NV21 has a plane of Y and interleaved planes of VU each sampled by a factor of 2
            //    meaning for every 4 Y pixels there are 1 V and 1 U.  Note the sampling is every other
            //    pixel AND every other scanline.
            yuv420sp[yIndex++] = (byte) ((Y < 0) ? 0 : ((Y > 255) ? 255 : Y));
            if (j % 2 == 0 && index % 2 == 0) {
                yuv420sp[uvIndex++] = (byte)((V<0) ? 0 : ((V > 255) ? 255 : V));
                yuv420sp[uvIndex++] = (byte)((U<0) ? 0 : ((U > 255) ? 255 : U));
            }

            index ++;
        }
    }
}

正确的代码:

LG G3:我能够在代码中的任何位置使用上述变量来获得所需的输出。位图大小返回值为2734200。

Asus Zenfone 5:除了创建位图,其他地方都必须使用bitmap.getHeight()和bitmap.getWidth()来获取所需的输出。

令人惊讶的是,这里的Bitmap大小返回值为725760(因此它不是根据设置的位图参数进行设置?)

错误的代码:

LG G3:如果我使用bitmap.getHeight()和bitmap.getWidth(),我会得到java.lang.ArrayIndexOutOfBoundsException:length = 102354,index = 102354。 @getNV21方法

Asus Zenfone 5:如果我使用inputWidth,inputHeight,我会得到java.lang.IllegalArgumentException:x + width must be <= bitmap.width() @getNV21方法

如何将上述代码推广至两种手机?

1个回答

2
在这种情况下,您可以使用策略模式。
策略模式允许您根据环境在运行时更改算法。基本上,您为您的策略定义一个接口。就像这样:
interface MyStrategy {
    byte[] getNV21(int inputWidth, int inputHeight, Bitmap bitmap);
}

然后,您可以创建多个接口实现,一个用于LG,一个用于Asus,例如,一个用于所有其他设备(设备中立):
class MyStrategyForLG implements MyStrategy {

    public byte[] getNV21(int inputWidth, int inputHeight, Bitmap bitmap) {
        // ...
    }

}


class MyStrategyForAsus implements MyStrategy {

    public byte[] getNV21(int inputWidth, int inputHeight, Bitmap bitmap) {
        // ...
    }

}


class DefaultMyStrategy implements MyStrategy {

    public byte[] getNV21(int inputWidth, int inputHeight, Bitmap bitmap) {
        // ...
    }

}

您可以为MyStrategy创建一个工厂,这样您就可以避免在MainActivity中使用if-else。类似于这样:
class MyStrategyFactory {

    public void createMyStrategy() {
        // ...
        if ( deviceIsAsus ) {
            return new MyStrategyForAsus();
        }
        if ( deviceIsLg ) {
            return new MyStrategyForLG();
        }
        return new DefaultMyStrategy();
    }
}

在你的MainActivity中,你可以像这样调用你的策略:
// ...
MyStrategy strategy = new MyStrategyFactory().createMyStrategy();
byte[] bytes = strategy.getNV21(width, height, image);
// ...

这种方法的优点是,当你添加另一个设备时(例如,当你发现三星也有点奇怪时),你不需要修改调用站点。相反,你可以实现MyStrategyForSamsung并在代码在三星设备上执行时更改工厂以返回它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接