2014-06-28 13 views
3

我的目標是獲取一個M4V視頻文件,將一段視頻解碼爲PNG幀,修改這些幀並對修剪過的視頻(也轉換爲M4V)進行重新編碼。將位圖幀渲染到Surface進行編碼

工作流程如下:[Input Video] -> Export Frames -> Modify Frames -> Encode Frames -> [Output Video]

對於解碼過程,我一直在參考bigflake的例子。使用ExtractMpegFramesTest示例代碼,我能夠從.m4v文件生成Bitmap幀,並將幀導出爲PNG文件。

現在我正在嘗試重新編碼過程,嘗試使用EncodeAndMuxTest示例創建另一組編碼類。

我遇到的問題是,示例代碼似乎在OpenGL中生成原始幀。我有一系列Bitmaps,我想編碼/渲染到對象。幾乎與解碼過程所做的相反。

大部分示例代碼都很好,似乎我只需修改generateSurfaceFrame()即可將Bitmap轉換爲Surface與OpenGL。

這裏是我迄今爲止代碼:我覺得我應該能夠使用STextureRenderExtractMpegFramesTest例子來實現類似的

// Member variables (see EncodeAndMuxTest example) 
private MediaCodec encoder; 
private CodeInputSurface inputSurface; 
private MediaMuxer muxer; 
private int trackIndex; 
private boolean hasMuxerStarted; 
private MediaCodec.BufferInfo bufferInfo; 

// This is called for each frame to be rendered into the video file 
private void encodeFrame(Bitmap bitmap) 
{ 
    int textureId = 0; 

    try 
    { 
     textureId = loadTexture(bitmap); 

     // render the texture here? 
    } 
    finally 
    { 
     unloadTexture(textureId); 
    } 
} 

// Loads a texture into OpenGL 
private int loadTexture(Bitmap bitmap) 
{ 
    final int[] textures = new int[1]; 
    GLES20.glGenTextures(1, textures, 0); 

    int textureWidth = bitmap.getWidth(); 
    int textureHeight = bitmap.getHeight(); 

    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]); 
    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); 

    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, 
      GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, 
      GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, 
      GLES20.GL_CLAMP_TO_EDGE); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, 
      GLES20.GL_CLAMP_TO_EDGE); 

    return textures[0]; 
} 

// Unloads a texture from OpenGL 
private void unloadTexture(int textureId) 
{ 
    final int[] textures = new int[1]; 
    textures[0] = textureId; 

    GLES20.glDeleteTextures(1, textures, 0); 
} 

,但它只是不點擊我。

另一件事是性能,我真的想要獲得高效的編碼。我將編碼90-450幀視頻(3-15秒@ 30fps),所以這應該只需要幾秒鐘。

+0

您可以使用glTexImage()將位圖像素轉換爲GLES紋理,然後渲染紋理......這似乎是迄今爲止所做的。什麼不工作? Grafika中的一些代碼(https://github.com/google/grafika)可能有用。你正在進行什麼樣的修改?如果它很簡單,您可以使用GLES片段着色器進行處理,速度會更快(請參閱例如Grafika中的「顯示+捕獲」活動)。 – fadden

+0

Woo @fadden,感謝您的評論!我正在執行的操作是修剪(從電影中選擇片段),縮放/平移(縮放+變換),調整幀大小以添加信箱(用於文本)以及在信箱區域中渲染文本。這些步驟中的每一個都需要用戶交互,例如捏縮放,拖動平移以及在相應的頂部/底部區域輸入文本。我使用'Canvas' /'Paint' /'Bitmap'對象完成所有工作,但着色器會很整齊。我對OpenGL有一個基本的瞭解,但着色器語言對我來說是新的。 – Erik

+0

另外,我想這不像我在做什麼時有心理障礙那樣工作。在理論上,我應該能夠渲染它來繪製一個'GL_TRIANGLE_STRIP'四元組,類似於'ExtractMpegFramesTest示例中'STextureRender'的功能。我確實看過Grafika示例代碼,但我不確定在哪裏尋找示例,我會稍後再看看,看看我能想出什麼。 – Erik

回答

1

您可以嘗試英特爾INDE媒體包,它允許修改幀,剪切片段,加入文件等等。這些是針對幀修改的幾個示例效果:顏色修改,文本覆蓋等,您可以輕鬆修改或添加新效果。它樹立了很好的範例和指導如何構建和運行應用程序:https://software.intel.com/en-us/articles/intel-inde-media-pack-for-android-tutorials-running-samples

框架的修改是基於這樣的GL着色器,例如用於棕褐色:

@Override 
protected String getFragmentShader() { 
    return "#extension GL_OES_EGL_image_external : require\n" + 
      "precision mediump float;\n" + 
      "varying vec2 vTextureCoord;\n" + 
      "uniform mat3 uWeightsMatrix;\n" + 
      "uniform samplerExternalOES sTexture;\n" + 
      "void main() {\n" + 
      " vec4 color = texture2D(sTexture, vTextureCoord);\n" + 
      " vec3 color_new = min(uWeightsMatrix * color.rgb, 1.0);\n" + 
      " gl_FragColor = vec4(color_new.rgb, color.a);\n" + 
      "}\n"; 

} 

其中uWeightsMatrix設置爲通過getAttributeLocation着色器和glUniformMatrix3fv

protected float[] getWeights() { 
    return new float[]{ 
      805.0f/2048.0f, 715.0f/2048.0f, 557.0f/2048.0f, 
      1575.0f/2048.0f, 1405.0f/2048.0f, 1097.0f/2048.0f, 
      387.0f/2048.0f, 344.0f/2048.0f, 268.0f/2048.0f 
    }; 
} 
0

請注意,原始STextureRender從SurfaceTexture呈現外部紋理。如果你想它使你的紋理(從位圖創建),你必須做如下修改:

  1. 變化目標參數GLES11Ext.GL_TEXTURE_EXTERNAL_OESGLES20.GL_TEXTURE_2D

  2. 變化着色器定義"uniform samplerExternalOES sTexture;\n"此行「uniform sampler2D sTexture;\n」

  3. drawFrame

刪除

該解決方案適用於我。