私は Android カメラ アプリケーションを開発しています。フレームを扱うとき、いくつかのトラブルに遭遇しました。
Camera のonPreviewFrame(byte[] data, Camera camera)関数で、 NV21 はすべての Android デバイスがサポートされているため、データの形式をNV21 fromat に設定しました。
MediaCodec を使用してフレームをコーデックする場合、KEY_COLOR_FORMAT は COLOR_FormatYUV420SemiPlanar ( NV12 ) です。
したがって、NV21 を NV12 に変換する必要があります。
また、フレームは -90 度回転します。回転したいのは、元に戻す、90 度回転するという意味です。
Javaを使用して作成しました:
// 1. rotate 90 degree clockwise
// 2. convert NV21 to NV12
private byte[] rotateYUV420SemiPlannerFrame(byte[] input, int width, int height) {
//from:https://github.com/upyun/android-push-sdk/blob/7d74e3c941bbede0b6f9f588b1d4e7926a5f2733/uppush/src/main/java/com/upyun/hardware/VideoEncoder.java
int frameSize = width * height;
byte[] output = new byte[frameSize * 3 / 2];
int i = 0;
for (int col = 0; col < width; col++) {
for (int row = height - 1; row >= 0; row--) {
output[i++] = input[width * row + col]; // Y
}
}
i = 0;
for (int col = 0; col < width / 2; col++) {
for (int row = height / 2 - 1; row >= 0; row--) {
int i2 = i * 2;
int fwrc2 = frameSize + width * row + col * 2;
output[frameSize + i2 + 1] = input[fwrc2]; // Cb (U)
output[frameSize + i2] = input[fwrc2 + 1]; // Cr (V)
i++;
}
}
return output;
}
関数はうまく機能しますが、50ms 以上の長い時間がかかります。
私が知っているように、libyuvは YUV img をより高速に処理し、Android Camera アプリケーションで使用したいと考えています。
libyuv では、次の3 つの関数が役立つ可能性があることがわかりました。
// Convert NV21 to I420.
LIBYUV_API
int NV21ToI420(const uint8* src_y, int src_stride_y,
const uint8* src_vu, int src_stride_vu,
uint8* dst_y, int dst_stride_y,
uint8* dst_u, int dst_stride_u,
uint8* dst_v, int dst_stride_v,
int width, int height);
// Rotate I420 frame.
LIBYUV_API
int I420Rotate(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v,
uint8* dst_y, int dst_stride_y,
uint8* dst_u, int dst_stride_u,
uint8* dst_v, int dst_stride_v,
int src_width, int src_height, enum RotationMode mode);
LIBYUV_API
int I420ToNV12(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v,
uint8* dst_y, int dst_stride_y,
uint8* dst_uv, int dst_stride_uv,
int width, int height);
これらの関数を使用すると、動作する場合があります。ただし、変換と回転には時間がかかる場合があります(推測します..)。
より少ない関数を使用して目標を達成する方法はありますか? ありがとう。
私が望むものではなく、ここでいくつかの答えも見つけました。