2016-03-02 47 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並更改工廠以在三星設備上執行代碼時將其返回。

相關問題