2016-03-02 92 views
2

我有一个代码,图像数据从位图传递到FFmpeg帧记录器并转换为视频。但是我需要在华硕zenfone 5(x86)的LG G3(armv7)上运行它时做一些小的修改。针对不同平台的不同代码(.java文件)?

以下是创造这一问题的类变量:

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

华硕Zenfone 5:除了创建位图之外,我必须在其他位置使用bitmap.getHeight()和bitmap.getWidth()来获得所需的输出。

令人惊讶这里的位图大小返回= 725760(所以它不是设置根据设定的参数位图?)

不正确的代码:

LG G3:如果我用bitmap.getHeight()和位图。的getWidth(),我得到java.lang.ArrayIndexOutOfBoundsException:长度= 102354,索引= 102354. @ getNV21方法

华硕Zenfone 5:如果我使用inputWidth,inputHeight我得到 java.lang.IllegalArgumentException异常:X +宽度必须是< = bit map.width()@ getNV21方法

我该如何推广上述两种手机的代码?

回答

1

在这种情况下,您可以使用Strategy模式。

策略模式允许您在运行期间根据您的环境更改算法。基本上你可以为你的战略定义一个界面。事情是这样的:

interface MyStrategy { 
    byte[] getNV21(int inputWidth, int inputHeight, Bitmap bitmap); 
} 

然后你让你的界面,一个是LG,一个华硕的多个实现,例如,一个用于所有其他设备(设备中性):

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并更改工厂以在三星设备上执行代码时将其返回。