天天看點

Android native層實作MediaCodec編碼H264/HEVC

Android平台在上層實作mediacodec的編碼,資料泛濫,已經不再是難事,今天給大家介紹下,如何在Android native層實作MediaCodec編碼H264/HEVC,網上千篇一律的接口說明,這裡不再贅述,本文主要介紹下,一些需要注意的點,權當抛磚引玉,相關設計界面如下:

Android native層實作MediaCodec編碼H264/HEVC

問題1:有了上層MediaCodec編碼方案,為什麼還要開發Native層解決方案?

回答:由于我們的資料流向是編碼前YV12/NV21/NV12/I420/RGB24/RGBA32/RGB565等資料類型,底層統一處理後,實作H264、HEVC的編碼,減少了上下層之間的互動,效率更高,支援的編碼前video資料接口設計如下:

/**
    * Set live video data(no encoded data).
    *
    * @param cameraType: CAMERA_FACING_BACK with 0, CAMERA_FACING_FRONT with 1
    * 
    * @param curOrg:
         * PORTRAIT = 1; //豎屏
         * LANDSCAPE = 2;    //橫屏 home鍵在右邊的情況
         * LANDSCAPE_LEFT_HOME_KEY = 3; //橫屏 home鍵在左邊的情況
    *
    * @return {0} if successful
    */
    public native int SmartPublisherOnCaptureVideoData(long handle, byte[] data, int len, int cameraType, int curOrg);


    /**
     * YV12資料接口
     *
     * @param data: YV12 data
     *
     * @param width: 圖像寬
     *
     * @param height: 圖像高
     *
     * @param y_stride:  y面步長
     *
     * @param v_stride: v面步長
     *
     * @param u_stride: u面步長
     *
     * rotation_degree: 順時針旋轉, 必須是0, 90, 180, 270
     *
     * @return {0} if successful
     */
    public native int SmartPublisherOnYV12Data(long handle, byte[] data, int width, int height, int y_stride,  int v_stride, int u_stride, int rotation_degree);


    /**
     * NV21資料接口
     *
     * @param data: nv21 data
     *
     * @param len: data length
     *
     * @param width: 圖像寬
     *
     * @param height: 圖像高
     *
     * @param y_stride:  y面步長
     *
     * @param uv_stride:  uv面步長
     *
     * rotation_degree: 順時針旋轉, 必須是0, 90, 180, 270
     *
     * @return {0} if successful
     */
    public native int SmartPublisherOnNV21Data(long handle, byte[] data, int len, int width, int height, int y_stride,  int uv_stride, int rotation_degree);


    /**
     * NV21資料接口
     *
     * @param data: nv21 data
     *
     * @param len: data length
     *
     * @param width: 圖像寬
     *
     * @param height: 圖像高
     *
     * @param y_stride:  y面步長
     *
     * @param uv_stride:  uv面步長
     *
     * rotation_degree: 順時針旋轉, 必須是0, 90, 180, 270
     *
     * @param  is_vertical_flip: 是否垂直翻轉, 0不翻轉, 1翻轉
     *
     * @param  is_horizontal_flip:是否水準翻轉, 0不翻轉, 1翻轉
     *
     * @return {0} if successful
     */
    public native int SmartPublisherOnNV21DataV2(long handle, byte[] data, int len, int width, int height, int y_stride,  int uv_stride, int rotation_degree,
                                                 int is_vertical_flip, int is_horizontal_flip);


    /**
     * NV21轉換到I420并旋轉
     *
     * @param src: nv21 data
     *
     * @param dst: 輸出I420 data
     *
     * @param width: 圖像寬
     *
     * @param height: 圖像高
     *
     * rotation_degree: 順時針旋轉, 必須是0, 90, 180, 270
     *
     * @return {0} if successful
     */
    public native int SmartPublisherNV21ToI420Rotate(long handle, byte[] src, int src_y_stride, int src_uv_stride, byte[] dst,
                                                     int dst_y_stride, int dst_u_stride, int dst_v_stride,
                                                     int width, int height,
                                                     int rotation_degree);


    /**
    * Set live video data(no encoded data).
    *
    * @param data: I420 data
    * 
    * @param len: I420 data length
    * 
    * @param yStride: y stride
    * 
    * @param uStride: u stride
    * 
    * @param vStride: v stride
    *
    * @return {0} if successful
    */
    public native int SmartPublisherOnCaptureVideoI420Data(long handle,  byte[] data, int len, int yStride, int uStride, int vStride);


    /**
     * 傳I420圖像接口
     *
     * @param data: I420 data
     *
     * @param width: 圖像寬
     *
     * @param height: 圖像高
     *
     * @param y_stride: y stride
     *
     * @param u_stride: u stride
     *
     * @param v_stride: v stride
     *
     * @return {0} if successful
     */
    public native int SmartPublisherOnCaptureVideoI420DataV2(long handle, byte[] data, int width, int height, int y_stride, int u_stride, int v_stride);


    /**
     * Set live video data(no encoded data).
     *
     * @param buffer: RGB24 data
     *
     * @param length: data length
     *
     * @param rowStride: stride information
     *
     * @param width: width
     *
     * @param height: height
     *
     * @param  is_vertical_flip: 是否垂直翻轉, 0不翻轉, 1翻轉
     *
     * @param  is_horizontal_flip:是否水準翻轉, 0不翻轉, 1翻轉
     *
     * @param  rotation_degree: 順時針旋轉, 必須是0, 90, 180, 270
     *
     * @param  scale_width: 縮放寬,必須是8的倍數, 0不縮放
     *
     * @param  scale_height: 縮放高, 必須是8的倍數, 0不縮放
     *
     * @param  scale_filter_mode: 縮放品質, 範圍必須是[1,3], 傳0使用預設品質
     *
     * @return {0} if successful
     */
    public native int SmartPublisherOnCaptureVideoRGB24Data(long handle, long buffer, int length, int rowStride, int width, int height,
                                                               int is_vertical_flip, int is_horizontal_flip,int rotation_degree,
                                                               int scale_width, int scale_height, int scale_filter_mode);

    /**
     * Set live video data(no encoded data).
     *
     * @param buffer: RGBA data
     *
     * @param length: data length
     *
     * @param rowStride: stride information
     *
     * @param width: width
     *
     * @param height: height
     *
     * @param  is_vertical_flip: 是否垂直翻轉, 0不翻轉, 1翻轉
     *
     * @param  is_horizontal_flip:是否水準翻轉, 0不翻轉, 1翻轉
     *
     * @param  rotation_degree: 順時針旋轉, 必須是0, 90, 180, 270
     *
     * @param  scale_width: 縮放寬,必須是8的倍數, 0不縮放
     *
     * @param  scale_height: 縮放高, 必須是8的倍數, 0不縮放
     *
     * @param  scale_filter_mode: 縮放品質, 範圍必須是[1,3], 傳0使用預設品質
     *
     * @return {0} if successful
     */
    public native int SmartPublisherOnCaptureVideoRGBA32Data(long handle, long buffer, int length, int rowStride, int width, int height,
                                                              int is_vertical_flip, int is_horizontal_flip,int rotation_degree,
                                                              int scale_width, int scale_height, int scale_filter_mode);

    /**
    * Set live video data(no encoded data).
    *
    * @param data: RGBA data
    * 
    * @param rowStride: stride information
    * 
    * @param width: width
    * 
    * @param height: height
    *
    * @return {0} if successful
    */
    public native int SmartPublisherOnCaptureVideoRGBAData(long handle,  ByteBuffer data, int rowStride, int width, int height);

    /**
     * 投遞裁剪過的RGBA資料
     *
     * @param data: RGBA data
     *
     * @param rowStride: stride information
     *
     * @param width: width
     *
     * @param height: height
     *
     * @param clipedLeft: 左;  clipedTop: 上; clipedwidth: 裁剪後的寬; clipedHeight: 裁剪後的高; 確定傳下去裁剪後的寬、高均為偶數
     *
     * @return {0} if successful
     */
    public native int SmartPublisherOnCaptureVideoClipedRGBAData(long handle,  ByteBuffer data, int rowStride, int width, int height, int clipedLeft, int clipedTop, int clipedWidth, int clipedHeight);

    /**
     * Set live video data(no encoded data).
     *
     * @param data: ABGR flip vertical(垂直翻轉) data
     *
     * @param rowStride: stride information
     *
     * @param width: width
     *
     * @param height: height
     *
     * @return {0} if successful
     */
    public native int SmartPublisherOnCaptureVideoABGRFlipVerticalData(long handle,  ByteBuffer data, int rowStride, int width, int height);


    /**
     * Set live video data(no encoded data).
     *
     * @param data: RGB565 data
     *
     * @param row_stride: stride information
     *
     * @param width: width
     *
     * @param height: height
     *
     * @return {0} if successful
     */
    public native int SmartPublisherOnCaptureVideoRGB565Data(long handle,ByteBuffer data, int row_stride, int width, int height);


    /*
    *  專門為android.media.Image的android.graphics.ImageFormat.YUV_420_888格式提供的接口
    *
    * @param  width: 必須是8的倍數
    *
    * @param  height: 必須是8的倍數
    *
    * @param  crop_left: 剪切左上角水準坐标, 一般根據android.media.Image.getCropRect() 填充
    *
    * @param  crop_top: 剪切左上角垂直坐标, 一般根據android.media.Image.getCropRect() 填充
    *
    * @param  crop_width: 必須是8的倍數, 填0将忽略這個參數, 一般根據android.media.Image.getCropRect() 填充
    *
    * @param  crop_height: 必須是8的倍數, 填0将忽略這個參數,一般根據android.media.Image.getCropRect() 填充
    *
    * @param y_plane 對應android.media.Image.Plane[0].getBuffer()
    *
    * @param y_row_stride 對應android.media.Image.Plane[0].getRowStride()
    *
    * @param u_plane 對應android.media.Image.Plane[1].getBuffer()
    *
    * @param v_plane 對應android.media.Image.Plane[2].getBuffer()
    *
    * @param uv_row_stride 對應android.media.Image.Plane[1].getRowStride()
    *
    * @param uv_pixel_stride 對應android.media.Image.Plane[1].getPixelStride()
    *
    * @param  rotation_degree: 順時針旋轉, 必須是0, 90, 180, 270
    *
    * @param  is_vertical_flip: 是否垂直翻轉, 0不翻轉, 1翻轉
    *
    * @param  is_horizontal_flip:是否水準翻轉, 0不翻轉, 1翻轉
    *
    * @param  scale_width: 縮放寬,必須是8的倍數, 0不縮放
    *
    * @param  scale_height: 縮放高, 必須是8的倍數, 0不縮放
    *
    * @param  scale_filter_mode: 縮放品質, 範圍必須是[1,3], 傳0使用預設速度
    *
    * @return {0} if successful
    */
    public native int SmartPublisherOnImageYUV420888(long handle, int width, int height,
                                                     int crop_left, int crop_top, int crop_width, int crop_height,
                                                     ByteBuffer y_plane, int y_row_stride,
                                                     ByteBuffer u_plane, ByteBuffer v_plane, int uv_row_stride, int uv_pixel_stride,
                                                     int rotation_degree, int is_vertical_flip, int is_horizontal_flip,
                                                     int scale_width, int scale_height, int scale_filter_mode);


    /**
     * 啟用或者停用視訊層, 這個接口必須在StartXXX之後調用.
     *
     * @param index: 層索引, 必須大于0, 注意第0層不能停用
     *
     * @param  is_enable: 是否啟用, 0停用, 1啟用
     *
     * @return {0} if successful
     */
    public native int EnableLayer(long handle, int index, int is_enable);


    /**
     * 移除視訊層, 這個接口必須在StartXXX之後調用.
     *
     * @param index: 層索引, 必須大于0, 注意第0層不能移除
     *
     * @return {0} if successful
     */
    public native int RemoveLayer(long handle, int index);


    /**
     * 投遞層RGBA8888圖像,如果不需要Aplpha通道的話, 請使用RGBX8888接口, 效率高
     *
     * @param index: 層索引, 必須大于等于0, 注意:如果index是0的話,将忽略Alpha通道
     *
     * @param left: 層疊加的左上角坐标, 對于第0層的話傳0
     *
     * @param top: 層疊加的左上角坐标, 對于第0層的話傳0
     *
     * @param rgba_plane: rgba 圖像資料
     *
     * @param offset: 圖像偏移, 這個主要目的是用來做clip的, 一般傳0
     *
     * @param row_stride: stride information
     *
     * @param width: width, 必須大于1, 如果是奇數, 将減1
     *
     * @param height: height, 必須大于1, 如果是奇數, 将減1
     *
     * @param  is_vertical_flip: 是否垂直翻轉, 0不翻轉, 1翻轉
     *
     * @param  is_horizontal_flip:是否水準翻轉, 0不翻轉, 1翻轉
     *
     * @param  scale_width: 縮放寬,必須是偶數, 0或負數不縮放
     *
     * @param  scale_height: 縮放高, 必須是偶數, 0或負數不縮放
     *
     * @param  scale_filter_mode: 縮放品質, 傳0使用預設速度,可選等級範圍是:[1,3],值越大縮放品質越好, 但速度越慢
     *
     * @param  rotation_degree: 順時針旋轉, 必須是0, 90, 180, 270, 注意:旋轉是在縮放, 垂直/水品反轉之後再做, 請留意順序
     *
     * @return {0} if successful
     */
    public native int PostLayerImageRGBA8888ByteBuffer(long handle, int index, int left, int top,
                                             ByteBuffer rgba_plane, int offset, int row_stride, int width, int height,
                                             int is_vertical_flip,  int is_horizontal_flip,
                                             int scale_width,  int scale_height, int scale_filter_mode,
                                             int rotation_degree);


    /**
     * 投遞層RGBA8888圖像, 詳細說明請參考PostLayerImageRGBA8888ByteBuffer
     *
     * @return {0} if successful
     */
    public native int PostLayerImageRGBA8888ByteArray(long handle, int index, int left, int top,
                                                      byte[] rgba_plane, int offset, int row_stride, int width, int height,
                                                      int is_vertical_flip,  int is_horizontal_flip,
                                                      int scale_width,  int scale_height, int scale_filter_mode,
                                                      int rotation_degree);


    /**
     * 投遞層RGBA8888圖像, 詳細說明請參考PostLayerImageRGBA8888ByteBuffer
     *
     * @return {0} if successful
     */
    public native int PostLayerImageRGBA8888Native(long handle, int index, int left, int top,
                                                   long rgba_plane, int offset, int row_stride, int width, int height,
                                                   int is_vertical_flip,  int is_horizontal_flip,
                                                   int scale_width,  int scale_height, int scale_filter_mode,
                                                   int rotation_degree);


    /**
     * 投遞層RGBX8888圖像
     *
     * @param index: 層索引, 必須大于等于0
     *
     * @param left: 層疊加的左上角坐标, 對于第0層的話傳0
     *
     * @param top: 層疊加的左上角坐标, 對于第0層的話傳0
     *
     * @param rgbx_plane: rgbx 圖像資料
     *
     * @param offset: 圖像偏移, 這個主要目的是用來做clip的,一般傳0
     *
     * @param row_stride: stride information
     *
     * @param width: width, 必須大于1, 如果是奇數, 将減1
     *
     * @param height: height, 必須大于1, 如果是奇數, 将減1
     *
     * @param  is_vertical_flip: 是否垂直翻轉, 0不翻轉, 1翻轉
     *
     * @param  is_horizontal_flip:是否水準翻轉, 0不翻轉, 1翻轉
     *
     * @param  scale_width: 縮放寬,必須是偶數, 0或負數不縮放
     *
     * @param  scale_height: 縮放高, 必須是偶數, 0或負數不縮放
     *
     * @param  scale_filter_mode: 縮放品質, 傳0使用預設速度,可選等級範圍是:[1,3],值越大縮放品質越好, 但速度越慢
     *
     * @param  rotation_degree: 順時針旋轉, 必須是0, 90, 180, 270, 注意:旋轉是在縮放, 垂直/水品反轉之後再做, 請留意順序
     *
     * @return {0} if successful
     */
    public native int PostLayerImageRGBX8888ByteBuffer(long handle, int index, int left, int top,
                                                       ByteBuffer rgbx_plane, int offset, int row_stride, int width, int height,
                                                       int is_vertical_flip,  int is_horizontal_flip,
                                                       int scale_width,  int scale_height, int scale_filter_mode,
                                                       int rotation_degree);


    /**
     * 投遞層RGBX8888圖像, 詳細說明請參考PostLayerImageRGBX8888ByteBuffer
     *
     * @return {0} if successful
     */
    public native int PostLayerImageRGBX8888ByteArray(long handle, int index, int left, int top,
                                                      byte[] rgbx_plane, int offset, int row_stride, int width, int height,
                                                      int is_vertical_flip,  int is_horizontal_flip,
                                                      int scale_width,  int scale_height, int scale_filter_mode,
                                                      int rotation_degree);


    /**
     * 投遞層RGBX8888圖像, 詳細說明請參考PostLayerImageRGBX8888ByteBuffer
     *
     * @return {0} if successful
     */
    public native int PostLayerImageRGBX8888Native(long handle, int index, int left, int top,
                                                   long rgbx_plane, int offset, int row_stride, int width, int height,
                                                   int is_vertical_flip,  int is_horizontal_flip,
                                                   int scale_width,  int scale_height, int scale_filter_mode,
                                                   int rotation_degree);


    /**
     * 投遞層RGB888圖像
     *
     * @param index: 層索引, 必須大于等于0
     *
     * @param left: 層疊加的左上角坐标, 對于第0層的話傳0
     *
     * @param top: 層疊加的左上角坐标, 對于第0層的話傳0
     *
     * @param rgb_plane: rgb888 圖像資料
     *
     * @param offset: 圖像偏移, 這個主要目的是用來做clip的,一般傳0
     *
     * @param row_stride: stride information
     *
     * @param width: width, 必須大于1, 如果是奇數, 将減1
     *
     * @param height: height, 必須大于1, 如果是奇數, 将減1
     *
     * @param  is_vertical_flip: 是否垂直翻轉, 0不翻轉, 1翻轉
     *
     * @param  is_horizontal_flip:是否水準翻轉, 0不翻轉, 1翻轉
     *
     * @param  scale_width: 縮放寬,必須是偶數, 0或負數不縮放
     *
     * @param  scale_height: 縮放高, 必須是偶數, 0或負數不縮放
     *
     * @param  scale_filter_mode: 縮放品質, 傳0使用預設速度,可選等級範圍是:[1,3],值越大縮放品質越好, 但速度越慢
     *
     * @param  rotation_degree: 順時針旋轉, 必須是0, 90, 180, 270, 注意:旋轉是在縮放, 垂直/水品反轉之後再做, 請留意順序
     *
     * @return {0} if successful
     */
    public native int PostLayerImageRGB888Native(long handle, int index, int left, int top,
                                                       long rgb_plane, int offset, int row_stride, int width, int height,
                                                       int is_vertical_flip,  int is_horizontal_flip,
                                                       int scale_width,  int scale_height, int scale_filter_mode,
                                                       int rotation_degree);


    /**
     * 投遞層NV21圖像
     *
     * @param index: 層索引, 必須大于等于0
     *
     * @param left: 層疊加的左上角坐标, 對于第0層的話傳0
     *
     * @param top: 層疊加的左上角坐标, 對于第0層的話傳0
     *
     * @param y_plane: y平面圖像資料
     *
     * @param y_offset: 圖像偏移, 這個主要目的是用來做clip的,一般傳0
     *
     * @param y_row_stride: stride information
     *
     * @param uv_plane: uv平面圖像資料
     *
     * @param uv_offset: 圖像偏移, 這個主要目的是用來做clip的,一般傳0
     *
     * @param uv_row_stride: stride information
     *
     * @param width: width, 必須大于1, 且必須是偶數
     *
     * @param height: height, 必須大于1, 且必須是偶數
     *
     * @param  is_vertical_flip: 是否垂直翻轉, 0不翻轉, 1翻轉
     *
     * @param  is_horizontal_flip:是否水準翻轉, 0不翻轉, 1翻轉
     *
     * @param  scale_width: 縮放寬,必須是偶數, 0或負數不縮放
     *
     * @param  scale_height: 縮放高, 必須是偶數, 0或負數不縮放
     *
     * @param  scale_filter_mode: 縮放品質, 傳0使用預設速度,可選等級範圍是:[1,3],值越大縮放品質越好, 但速度越慢
     *
     * @param  rotation_degree: 順時針旋轉, 必須是0, 90, 180, 270, 注意:旋轉是在縮放, 垂直/水品反轉之後再做, 請留意順序
     *
     * @return {0} if successful
     */
    public native int PostLayerImageNV21ByteBuffer(long handle, int index, int left, int top,
                                                       ByteBuffer y_plane, int y_offset, int y_row_stride,
                                                       ByteBuffer uv_plane, int uv_offset, int uv_row_stride,
                                                       int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                                                       int scale_width,  int scale_height, int scale_filter_mode,
                                                       int rotation_degree);


    /**
     * 投遞層NV21圖像, 詳細說明請參考PostLayerImageNV21ByteBuffer
     *
     * @return {0} if successful
     */
    public native int PostLayerImageNV21ByteArray(long handle, int index, int left, int top,
                                                   byte[] y_plane, int y_offset, int y_row_stride,
                                                   byte[] uv_plane, int uv_offset, int uv_row_stride,
                                                   int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                                                   int scale_width,  int scale_height, int scale_filter_mode,
                                                   int rotation_degree);


    /**
     * 投遞層NV12圖像, 詳細說明請參考PostLayerImageNV21ByteBuffer
     *
     * @return {0} if successful
     */
    public native int PostLayerImageNV12ByteBuffer(long handle, int index, int left, int top,
                                                   ByteBuffer y_plane, int y_offset, int y_row_stride,
                                                   ByteBuffer uv_plane, int uv_offset, int uv_row_stride,
                                                   int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                                                   int scale_width,  int scale_height, int scale_filter_mode,
                                                   int rotation_degree);


    /**
     * 投遞層NV12圖像, 詳細說明請參考PostLayerImageNV21ByteBuffer
     *
     * @return {0} if successful
     */
    public native int PostLayerImageNV12ByteArray(long handle, int index, int left, int top,
                                                  byte[] y_plane, int y_offset, int y_row_stride,
                                                  byte[] uv_plane, int uv_offset, int uv_row_stride,
                                                  int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                                                  int scale_width,  int scale_height, int scale_filter_mode,
                                                  int rotation_degree);


    /**
     * 投遞層I420圖像
     *
     * @param index: 層索引, 必須大于等于0
     *
     * @param left: 層疊加的左上角坐标, 對于第0層的話傳0
     *
     * @param top: 層疊加的左上角坐标, 對于第0層的話傳0
     *
     * @param y_plane: y平面圖像資料
     *
     * @param y_offset: 圖像偏移, 這個主要目的是用來做clip的,一般傳0
     *
     * @param y_row_stride: stride information
     *
     * @param u_plane: u平面圖像資料
     *
     * @param u_offset: 圖像偏移, 這個主要目的是用來做clip的,一般傳0
     *
     * @param u_row_stride: stride information
     *                    *
     * @param v_plane: v平面圖像資料
     *
     * @param v_offset: 圖像偏移, 這個主要目的是用來做clip的,一般傳0
     *
     * @param v_row_stride: stride information
     *
     * @param width: width, 必須大于1, 且必須是偶數
     *
     * @param height: height, 必須大于1, 且必須是偶數
     *
     * @param  is_vertical_flip: 是否垂直翻轉, 0不翻轉, 1翻轉
     *
     * @param  is_horizontal_flip:是否水準翻轉, 0不翻轉, 1翻轉
     *
     * @param  scale_width: 縮放寬,必須是偶數, 0或負數不縮放
     *
     * @param  scale_height: 縮放高, 必須是偶數, 0或負數不縮放
     *
     * @param  scale_filter_mode: 縮放品質, 傳0使用預設速度,可選等級範圍是:[1,3],值越大縮放品質越好, 但速度越慢
     *
     * @param  rotation_degree: 順時針旋轉, 必須是0, 90, 180, 270, 注意:旋轉是在縮放, 垂直/水品反轉之後再做, 請留意順序
     *
     * @return {0} if successful
     */
    public native int PostLayerImageI420ByteBuffer(long handle, int index, int left, int top,
                                                   ByteBuffer y_plane, int y_offset, int y_row_stride,
                                                   ByteBuffer u_plane, int u_offset, int u_row_stride,
                                                   ByteBuffer v_plane, int v_offset, int v_row_stride,
                                                   int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                                                   int scale_width,  int scale_height, int scale_filter_mode,
                                                   int rotation_degree);


    /**
     * 投遞層I420圖像, 詳細說明請參考PostLayerImageI420ByteBuffer
     *
     * @return {0} if successful
     */
    public native int PostLayerImageI420ByteArray(long handle, int index, int left, int top,
                                                   byte[] y_plane, int y_offset, int y_row_stride,
                                                   byte[] u_plane, int u_offset, int u_row_stride,
                                                   byte[] v_plane, int v_offset, int v_row_stride,
                                                   int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                                                   int scale_width,  int scale_height, int scale_filter_mode,
                                                   int rotation_degree);


    /**
     * 投遞層YUV420888圖像, 專門為android.media.Image的android.graphics.ImageFormat.YUV_420_888格式提供的接口
     *
     * @param index: 層索引, 必須大于等于0
     *
     * @param left: 層疊加的左上角坐标, 對于第0層的話傳0
     *
     * @param top: 層疊加的左上角坐标, 對于第0層的話傳0
     *
     * @param y_plane: 對應android.media.Image.Plane[0].getBuffer()
     *
     * @param y_offset: 圖像偏移, 這個主要目的是用來做clip的,一般傳0
     *
     * @param y_row_stride: 對應android.media.Image.Plane[0].getRowStride()
     *
     * @param u_plane: android.media.Image.Plane[1].getBuffer()
     *
     * @param u_offset: 圖像偏移, 這個主要目的是用來做clip的,一般傳0
     *
     * @param u_row_stride: android.media.Image.Plane[1].getRowStride()
     *
     * @param v_plane: 對應android.media.Image.Plane[2].getBuffer()
     *
     * @param v_offset: 圖像偏移, 這個主要目的是用來做clip的,一般傳0
     *
     * @param v_row_stride: 對應android.media.Image.Plane[2].getRowStride()
     *
     * @param uv_pixel_stride: 對應android.media.Image.Plane[1].getPixelStride()
     *
     * @param width: width, 必須大于1, 且必須是偶數
     *
     * @param height: height, 必須大于1, 且必須是偶數
     *
     * @param  is_vertical_flip: 是否垂直翻轉, 0不翻轉, 1翻轉
     *
     * @param  is_horizontal_flip:是否水準翻轉, 0不翻轉, 1翻轉
     *
     * @param  scale_width: 縮放寬,必須是偶數, 0或負數不縮放
     *
     * @param  scale_height: 縮放高, 必須是偶數, 0或負數不縮放
     *
     * @param  scale_filter_mode: 縮放品質, 傳0使用預設速度,可選等級範圍是:[1,3],值越大縮放品質越好, 但速度越慢
     *
     * @param  rotation_degree: 順時針旋轉, 必須是0, 90, 180, 270, 注意:旋轉是在縮放, 垂直/水品反轉之後再做, 請留意順序
     *
     * @return {0} if successful
     */
    public native int PostLayerImageYUV420888ByteBuffer(long handle, int index, int left, int top,
                                                         ByteBuffer y_plane, int y_offset, int y_row_stride,
                                                         ByteBuffer u_plane, int u_offset, int u_row_stride,
                                                         ByteBuffer v_plane, int v_offset, int v_row_stride, int uv_pixel_stride,
                                                         int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                                                         int scale_width,  int scale_height, int scale_filter_mode,
                                                         int rotation_degree);      

問題2:Android Native層MediaCodec編碼,從什麼版本開始支援的,支援什麼架構?

回答:從5.0開始,armv8,如果像我們一樣,想支援armv7也未嘗不可,需要底層動态加載lib so,然後接口再做一層封裝即可,設定MediaCodec Native寫死時,底層需要判斷下系統版本,相關設計接口如下:

/**
   * 設定視訊寫死是否使用 Native Media NDK, 預設是不使用, 安卓5.0以下裝置不支援
   * @param handle
   * @param is_native: 0表示不使用, 1表示使用, sdk預設是0.
   * @return {0} if successful
   */
  public native int SetNativeMediaNDK(long handle, int is_native);      

問題3:看了下MediaCodec的接口,底層接口好像不像上層的那麼全,是不是會導緻編碼效果大打折扣?

回答:MediaCodec的native接口的調用,确實不如上層的那麼友善,比如,判斷系統是否支援特定編碼類型硬編或支援的color format等資訊,可以采用上下層結合的形式。

問題4:底層如何判斷關鍵幀?

回答:和上層一樣,參考以下代碼:

bool is_key_frame = info.flags & AMEDIACODEC_BUFFER_FLAG_KEY_FRAME;      

問題5:如何擷取codec config?

回答:和上層類似,參考以下代碼:

if (info.flags & AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG) {
  config_info.clear();
  config_info.insert(config_info_.end(), output_buffer + info.offset, output_buffer + info.offset + info.size);
}      

問題6:建立MediaFormat有什麼特别之處嗎?

回答:沒啥特别之處,設定下如mine_type、width、height,編碼碼率、fps、關鍵幀間隔等資訊即可。

問題7:編碼過程中,比如發生橫豎屏切換等,導緻分辨率變化怎麼辦?

回答:重新開機encoder即可。

問題8:我想比較下到底native層編碼效率高,還是上層高?