diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index d0f5beb..c03c780 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -42,6 +42,7 @@ add_library( # Sets the name of the library. src/main/cpp/metadata/media_retriever_jni.cpp src/main/cpp/metadata/metadata_util.c src/main/cpp/metadata/ffmpeg_media_retriever.c + src/main/cpp/yuv2rgb/yuv_2_rgb.cpp ) add_library( ffmpeg diff --git a/app/src/main/cpp/yuv2rgb/yuv_2_rgb.cpp b/app/src/main/cpp/yuv2rgb/yuv_2_rgb.cpp new file mode 100644 index 0000000..9b891cf --- /dev/null +++ b/app/src/main/cpp/yuv2rgb/yuv_2_rgb.cpp @@ -0,0 +1,60 @@ +// +// Created by xu fulong on 2022/7/8. +// + +#include "yuv_to_rgb.h" + +static int range(int val) { + if (val < 0) { + return 0; + } else if (val > 255) { + return 255; + } else { + return val; + } +} + +static void YCbCr_to_RGB(uint8_t *dst, const uint8_t *src, int length) { + if (length < 1) return; + int R, G, B; + int Y, Cb, Cr; + int i, offset; + for (i = 0; i < length; i++) { + offset = (i << 1) + i; + Y = src[offset]; + Cb = src[offset + 1] - 128; + Cr = src[offset + 2] - 128; + R = Y + ((RGBRCrI * Cr + half_shift) >> shift); + G = Y + ((RGBGCbI * Cb + RGBGCrI * Cr + half_shift) >> shift); + B = Y + ((RGBBCbI * Cb + half_shift) >> shift); + R = range(R); + G = range(G); + B = range(B); + offset = i << 2; + dst[offset] = (uint8_t) B; + dst[offset + 1] = (uint8_t) G; + dst[offset + 2] = (uint8_t) R; + dst[offset + 3] = 0xff; + } +} + +static void RGB_to_YCbCr(uint8_t *dst, const uint8_t *src, int length) { + if (length < 1) return; + int R, G, B; + int i, offset; + for (i = 0; i < length; i++) { + offset = i << 2; + B = src[offset]; + G = src[offset + 1]; + R = src[offset + 2]; + offset = (i << 1) + i; + dst[offset] = (uint8_t) ((YCbCrYRI * R + YCbCrYGI * G + YCbCrYBI * B + half_shift) + >> shift); + dst[offset + 1] = (uint8_t) (128 + + ((YCbCrCbRI * R + YCbCrCbGI * G + YCbCrCbBI * B + half_shift) + >> shift)); + dst[offset + 2] = (uint8_t) (128 + + ((YCbCrCrRI * R + YCbCrCrGI * G + YCbCrCrBI * B + half_shift) + >> shift)); + } +} \ No newline at end of file diff --git a/app/src/main/cpp/yuv2rgb/yuv_to_rgb.h b/app/src/main/cpp/yuv2rgb/yuv_to_rgb.h new file mode 100644 index 0000000..6d367eb --- /dev/null +++ b/app/src/main/cpp/yuv2rgb/yuv_to_rgb.h @@ -0,0 +1,47 @@ +// +// Created by xu fulong on 2022/7/8. +// + +#ifndef FFMPEGANDROID_YUV_TO_RGB_H +#define FFMPEGANDROID_YUV_TO_RGB_H + +#include + +const float YCbCrYRF = 0.299F; +const float YCbCrYGF = 0.587F; +const float YCbCrYBF = 0.114F; +const float YCbCrCbRF = -0.168736F; +const float YCbCrCbGF = -0.331264F; +const float YCbCrCbBF = 0.500000F; +const float YCbCrCrRF = 0.500000F; +const float YCbCrCrGF = -0.418688F; +const float YCbCrCrBF = -0.081312F; + +const float RGBRCrF = 1.40200F; +const float RGBGCbF = -0.34414F; +const float RGBGCrF = -0.71414F; +const float RGBBCbF = 1.77200F; + +const int shift = 20; +const int half_shift = 1 << (shift - 1); + +const int YCbCrYRI = (int)(YCbCrYRF * (1 << shift) + 0.5); +const int YCbCrYGI = (int)(YCbCrYGF * (1 << shift) + 0.5); +const int YCbCrYBI = (int)(YCbCrYBF * (1 << shift) + 0.5); +const int YCbCrCbRI = (int)(YCbCrCbRF * (1 << shift) + 0.5); +const int YCbCrCbGI = (int)(YCbCrCbGF * (1 << shift) + 0.5); +const int YCbCrCbBI = (int)(YCbCrCbBF * (1 << shift) + 0.5); +const int YCbCrCrRI = (int)(YCbCrCrRF * (1 << shift) + 0.5); +const int YCbCrCrGI = (int)(YCbCrCrGF * (1 << shift) + 0.5); +const int YCbCrCrBI = (int)(YCbCrCrBF * (1 << shift) + 0.5); + +const int RGBRCrI = (int)(RGBRCrF * (1 << shift) + 0.5); +const int RGBGCbI = (int)(RGBGCbF * (1 << shift) + 0.5); +const int RGBGCrI = (int)(RGBGCrF * (1 << shift) + 0.5); +const int RGBBCbI = (int)(RGBBCbF * (1 << shift) + 0.5); + +static void YCbCr_to_RGB(uint8_t* dst, const uint8_t* src, int length); + +static void RGB_to_YCbCr(uint8_t* dst, const uint8_t* src, int length); + +#endif //FFMPEGANDROID_YUV_TO_RGB_H