├── README.md ├── Titan.iml ├── app ├── .gitignore ├── CMakeLists.txt ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── lisi │ │ └── titan │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── cpp │ │ ├── jsoncpp │ │ │ ├── json │ │ │ │ ├── json-forwards.h │ │ │ │ └── json.h │ │ │ └── jsoncpp.cpp │ │ ├── k_media_sender.cpp │ │ ├── k_media_sender.h │ │ ├── k_rtp_sender.cpp │ │ ├── k_rtp_sender.h │ │ ├── k_server_conn.cpp │ │ ├── k_server_conn.h │ │ ├── k_server_conn_handler.cpp │ │ ├── k_server_conn_handler.h │ │ ├── k_util │ │ │ ├── k_errno.cpp │ │ │ ├── k_errno.h │ │ │ ├── k_event.cpp │ │ │ ├── k_event.h │ │ │ ├── k_handler.cpp │ │ │ ├── k_handler.h │ │ │ ├── k_mutex.cpp │ │ │ ├── k_mutex.h │ │ │ ├── k_sockaddr.cpp │ │ │ ├── k_sockaddr.h │ │ │ ├── k_socket.cpp │ │ │ ├── k_socket.h │ │ │ ├── k_string.cpp │ │ │ ├── k_string.h │ │ │ ├── k_thread_task.cpp │ │ │ ├── k_thread_task.h │ │ │ ├── k_util.cpp │ │ │ └── k_util.h │ │ ├── libyuv │ │ │ ├── include │ │ │ │ └── libyuv │ │ │ │ │ ├── basic_types.h │ │ │ │ │ ├── compare.h │ │ │ │ │ ├── compare_row.h │ │ │ │ │ ├── convert.h │ │ │ │ │ ├── convert_argb.h │ │ │ │ │ ├── convert_from.h │ │ │ │ │ ├── convert_from_argb.h │ │ │ │ │ ├── cpu_id.h │ │ │ │ │ ├── macros_msa.h │ │ │ │ │ ├── mjpeg_decoder.h │ │ │ │ │ ├── planar_functions.h │ │ │ │ │ ├── rotate.h │ │ │ │ │ ├── rotate_argb.h │ │ │ │ │ ├── rotate_row.h │ │ │ │ │ ├── row.h │ │ │ │ │ ├── scale.h │ │ │ │ │ ├── scale_argb.h │ │ │ │ │ ├── scale_row.h │ │ │ │ │ ├── version.h │ │ │ │ │ └── video_common.h │ │ │ └── source │ │ │ │ ├── compare.cc │ │ │ │ ├── compare_common.cc │ │ │ │ ├── compare_gcc.cc │ │ │ │ ├── compare_msa.cc │ │ │ │ ├── compare_neon.cc │ │ │ │ ├── compare_neon64.cc │ │ │ │ ├── compare_win.cc │ │ │ │ ├── convert.cc │ │ │ │ ├── convert_argb.cc │ │ │ │ ├── convert_from.cc │ │ │ │ ├── convert_from_argb.cc │ │ │ │ ├── convert_jpeg.cc │ │ │ │ ├── convert_to_argb.cc │ │ │ │ ├── convert_to_i420.cc │ │ │ │ ├── cpu_id.cc │ │ │ │ ├── mjpeg_decoder.cc │ │ │ │ ├── mjpeg_validate.cc │ │ │ │ ├── planar_functions.cc │ │ │ │ ├── rotate.cc │ │ │ │ ├── rotate_any.cc │ │ │ │ ├── rotate_argb.cc │ │ │ │ ├── rotate_common.cc │ │ │ │ ├── rotate_gcc.cc │ │ │ │ ├── rotate_msa.cc │ │ │ │ ├── rotate_neon.cc │ │ │ │ ├── rotate_neon64.cc │ │ │ │ ├── rotate_win.cc │ │ │ │ ├── row_any.cc │ │ │ │ ├── row_common.cc │ │ │ │ ├── row_gcc.cc │ │ │ │ ├── row_msa.cc │ │ │ │ ├── row_neon.cc │ │ │ │ ├── row_neon64.cc │ │ │ │ ├── row_win.cc │ │ │ │ ├── scale.cc │ │ │ │ ├── scale_any.cc │ │ │ │ ├── scale_argb.cc │ │ │ │ ├── scale_common.cc │ │ │ │ ├── scale_gcc.cc │ │ │ │ ├── scale_msa.cc │ │ │ │ ├── scale_neon.cc │ │ │ │ ├── scale_neon64.cc │ │ │ │ ├── scale_win.cc │ │ │ │ └── video_common.cc │ │ └── native-lib.cpp │ ├── java │ │ └── com │ │ │ └── lisi │ │ │ └── titan │ │ │ ├── CaptureFormat.java │ │ │ ├── MainActivity.java │ │ │ ├── TitanAudioEffects.java │ │ │ ├── TitanAudioEncoder.java │ │ │ ├── TitanAudioRecord.java │ │ │ ├── TitanCameraSession.java │ │ │ ├── TitanNativeLib.java │ │ │ └── TitanVideoEncoder.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── lisi │ └── titan │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── local.properties └── settings.gradle /README.md: -------------------------------------------------------------------------------- 1 | # Titan 2 | Android手机采集音视频流推到服务器,简单介绍参见: 3 | https://blog.csdn.net/greenjim301/article/details/80560283 4 | 5 | -------------------------------------------------------------------------------- /Titan.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html 3 | 4 | # Sets the minimum version of CMake required to build the native library. 5 | 6 | cmake_minimum_required(VERSION 3.4.1) 7 | 8 | # Creates and names a library, sets it as either STATIC 9 | # or SHARED, and provides the relative paths to its source code. 10 | # You can define multiple libraries, and CMake builds them for you. 11 | # Gradle automatically packages shared libraries with your APK. 12 | 13 | add_library( # Sets the name of the library. 14 | native-lib 15 | 16 | # Sets the library as a shared library. 17 | SHARED 18 | 19 | # Provides a relative path to your source file(s). 20 | src/main/cpp/k_util/k_errno.cpp 21 | src/main/cpp/k_util/k_event.cpp 22 | src/main/cpp/k_util/k_handler.cpp 23 | src/main/cpp/k_util/k_mutex.cpp 24 | src/main/cpp/k_util/k_sockaddr.cpp 25 | src/main/cpp/k_util/k_socket.cpp 26 | src/main/cpp/k_util/k_string.cpp 27 | src/main/cpp/k_util/k_thread_task.cpp 28 | src/main/cpp/k_util/k_util.cpp 29 | src/main/cpp/k_rtp_sender.cpp 30 | src/main/cpp/k_media_sender.cpp 31 | src/main/cpp/k_server_conn.cpp 32 | src/main/cpp/k_server_conn_handler.cpp 33 | src/main/cpp/libyuv/source/compare.cc 34 | src/main/cpp/libyuv/source/compare_common.cc 35 | src/main/cpp/libyuv/source/compare_gcc.cc 36 | src/main/cpp/libyuv/source/compare_msa.cc 37 | src/main/cpp/libyuv/source/compare_neon.cc 38 | src/main/cpp/libyuv/source/compare_neon64.cc 39 | src/main/cpp/libyuv/source/convert.cc 40 | src/main/cpp/libyuv/source/convert_argb.cc 41 | src/main/cpp/libyuv/source/convert_from.cc 42 | src/main/cpp/libyuv/source/convert_from_argb.cc 43 | src/main/cpp/libyuv/source/convert_to_argb.cc 44 | src/main/cpp/libyuv/source/convert_to_i420.cc 45 | src/main/cpp/libyuv/source/cpu_id.cc 46 | src/main/cpp/libyuv/source/planar_functions.cc 47 | src/main/cpp/libyuv/source/rotate.cc 48 | src/main/cpp/libyuv/source/rotate_any.cc 49 | src/main/cpp/libyuv/source/rotate_argb.cc 50 | src/main/cpp/libyuv/source/rotate_common.cc 51 | src/main/cpp/libyuv/source/rotate_gcc.cc 52 | src/main/cpp/libyuv/source/rotate_msa.cc 53 | src/main/cpp/libyuv/source/rotate_neon.cc 54 | src/main/cpp/libyuv/source/rotate_neon64.cc 55 | src/main/cpp/libyuv/source/row_any.cc 56 | src/main/cpp/libyuv/source/row_common.cc 57 | src/main/cpp/libyuv/source/row_gcc.cc 58 | src/main/cpp/libyuv/source/row_msa.cc 59 | src/main/cpp/libyuv/source/row_neon.cc 60 | src/main/cpp/libyuv/source/row_neon64.cc 61 | src/main/cpp/libyuv/source/scale.cc 62 | src/main/cpp/libyuv/source/scale_any.cc 63 | src/main/cpp/libyuv/source/scale_argb.cc 64 | src/main/cpp/libyuv/source/scale_common.cc 65 | src/main/cpp/libyuv/source/scale_gcc.cc 66 | src/main/cpp/libyuv/source/scale_msa.cc 67 | src/main/cpp/libyuv/source/scale_neon.cc 68 | src/main/cpp/libyuv/source/scale_neon64.cc 69 | src/main/cpp/libyuv/source/video_common.cc 70 | src/main/cpp/jsoncpp/jsoncpp.cpp 71 | src/main/cpp/native-lib.cpp ) 72 | 73 | include_directories(src/main/cpp/ 74 | src/main/cpp/libyuv/include/ 75 | src/main/cpp/jsoncpp/) 76 | 77 | # Searches for a specified prebuilt library and stores the path as a 78 | # variable. Because CMake includes system libraries in the search path by 79 | # default, you only need to specify the name of the public NDK library 80 | # you want to add. CMake verifies that the library exists before 81 | # completing its build. 82 | 83 | find_library( # Sets the name of the path variable. 84 | log-lib 85 | 86 | # Specifies the name of the NDK library that 87 | # you want CMake to locate. 88 | log ) 89 | 90 | # Specifies libraries CMake should link to your target library. You 91 | # can link multiple libraries, such as libraries you define in this 92 | # build script, prebuilt third-party libraries, or system libraries. 93 | 94 | target_link_libraries( # Specifies the target library. 95 | native-lib 96 | 97 | # Links the target library to the log library 98 | # included in the NDK. 99 | ${log-lib} ) -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | defaultConfig { 6 | applicationId "com.lisi.titan" 7 | minSdkVersion 21 8 | targetSdkVersion 27 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | externalNativeBuild { 13 | cmake { 14 | cppFlags "-frtti","-std=c++11","-fno-exceptions" 15 | arguments "-DANDROID_ARM_NEON=TRUE" 16 | } 17 | } 18 | ndk { 19 | abiFilters 'armeabi-v7a','arm64-v8a','x86', 'x86_64' 20 | } 21 | } 22 | buildTypes { 23 | release { 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | externalNativeBuild { 29 | cmake { 30 | path "CMakeLists.txt" 31 | } 32 | } 33 | 34 | } 35 | 36 | dependencies { 37 | implementation fileTree(dir: 'libs', include: ['*.jar']) 38 | implementation 'com.android.support:appcompat-v7:27.1.1' 39 | implementation 'com.android.support.constraint:constraint-layout:1.0.2' 40 | testImplementation 'junit:junit:4.12' 41 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 42 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 43 | } 44 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/lisi/titan/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.lisi.titan; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.lisi.titan", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/cpp/k_media_sender.cpp: -------------------------------------------------------------------------------- 1 | #include "k_media_sender.h" 2 | #include 3 | 4 | k_media_sender::k_media_sender(k_socket* p_socket) 5 | : m_video_sender(p_socket, 96, 1000) 6 | , m_audio_sender(p_socket, 97, 1001) 7 | { 8 | } 9 | 10 | const uint8_t * k_media_sender::ff_avc_find_startcode_internal( 11 | const uint8_t *p, const uint8_t *end) 12 | { 13 | const uint8_t *a = p + 4 - ((intptr_t)p & 3); 14 | 15 | for (end -= 3; p < a && p < end; p++) { 16 | if (p[0] == 0 && p[1] == 0 && p[2] == 1) 17 | return p; 18 | } 19 | 20 | for (end -= 3; p < end; p += 4) { 21 | uint32_t x = *(const uint32_t*)p; 22 | // if ((x - 0x01000100) & (~x) & 0x80008000) // little endian 23 | // if ((x - 0x00010001) & (~x) & 0x00800080) // big endian 24 | if ((x - 0x01010101) & (~x) & 0x80808080) { // generic 25 | if (p[1] == 0) { 26 | if (p[0] == 0 && p[2] == 1) 27 | return p; 28 | if (p[2] == 0 && p[3] == 1) 29 | return p + 1; 30 | } 31 | if (p[3] == 0) { 32 | if (p[2] == 0 && p[4] == 1) 33 | return p + 2; 34 | if (p[4] == 0 && p[5] == 1) 35 | return p + 3; 36 | } 37 | } 38 | } 39 | 40 | for (end += 3; p < end; p++) { 41 | if (p[0] == 0 && p[1] == 0 && p[2] == 1) 42 | return p; 43 | } 44 | 45 | return end + 3; 46 | } 47 | 48 | const uint8_t * k_media_sender::ff_avc_find_startcode(const uint8_t *p, const uint8_t *end) 49 | { 50 | const uint8_t *out = ff_avc_find_startcode_internal(p, end); 51 | if (p < out && out < end && !out[-1]) out--; 52 | return out; 53 | } 54 | 55 | void k_media_sender::ff_rtp_send_h264(const uint8_t *buf1, int size, uint32_t ts) 56 | { 57 | const uint8_t *r, *end = buf1 + size; 58 | m_video_sender.set_timestamp(ts); 59 | 60 | r = ff_avc_find_startcode(buf1, end); 61 | 62 | while (r < end) { 63 | const uint8_t *r1; 64 | 65 | while (!*(r++)); 66 | r1 = ff_avc_find_startcode(r, end); 67 | 68 | nal_send(r, r1 - r, r1 == end); 69 | r = r1; 70 | } 71 | } 72 | 73 | void k_media_sender::nal_send(const uint8_t *buf, int size, int last) 74 | { 75 | uint8_t* p_buf = m_video_sender.get_payload_buf(); 76 | 77 | if (size <= k_rtp_sender::MAX_PAYLOAD_SIZE) 78 | { 79 | memcpy(p_buf, buf, size); 80 | m_video_sender.ff_rtp_send_data(p_buf, size, last); 81 | } 82 | else { 83 | int flag_byte, header_size; 84 | 85 | uint8_t type = buf[0] & 0x1F; 86 | uint8_t nri = buf[0] & 0x60; 87 | 88 | p_buf[0] = 28; /* FU Indicator; Type = 28 ---> FU-A */ 89 | p_buf[0] |= nri; 90 | p_buf[1] = type; 91 | p_buf[1] |= 1 << 7; 92 | buf += 1; 93 | size -= 1; 94 | 95 | flag_byte = 1; 96 | header_size = 2; 97 | 98 | while (size + header_size > k_rtp_sender::MAX_PAYLOAD_SIZE) { 99 | memcpy(&p_buf[header_size], buf, k_rtp_sender::MAX_PAYLOAD_SIZE - header_size); 100 | m_video_sender.ff_rtp_send_data(p_buf, k_rtp_sender::MAX_PAYLOAD_SIZE, 0); 101 | buf += k_rtp_sender::MAX_PAYLOAD_SIZE - header_size; 102 | size -= k_rtp_sender::MAX_PAYLOAD_SIZE - header_size; 103 | p_buf[flag_byte] &= ~(1 << 7); 104 | } 105 | p_buf[flag_byte] |= 1 << 6; 106 | memcpy(&p_buf[header_size], buf, size); 107 | m_video_sender.ff_rtp_send_data(p_buf, size + header_size, last); 108 | } 109 | } 110 | 111 | void k_media_sender::ff_rtp_send_audio(const uint8_t *buf1, int size, uint32_t ts) { 112 | m_audio_sender.set_timestamp(ts); 113 | 114 | uint8_t * buf = m_audio_sender.get_payload_buf(); 115 | memcpy(buf, buf1, size); 116 | 117 | m_audio_sender.ff_rtp_send_data(buf, size, 1); 118 | } 119 | 120 | -------------------------------------------------------------------------------- /app/src/main/cpp/k_media_sender.h: -------------------------------------------------------------------------------- 1 | #ifndef __K_VIDEO_SENDER_H__ 2 | #define __K_VIDEO_SENDER_H__ 3 | 4 | #include 5 | #include "k_rtp_sender.h" 6 | 7 | class k_media_sender 8 | { 9 | public: 10 | k_media_sender(k_socket* p_socket); 11 | 12 | void ff_rtp_send_h264(const uint8_t *buf1, int size, uint32_t ts); 13 | void ff_rtp_send_audio(const uint8_t *buf1, int size, uint32_t ts); 14 | 15 | private: 16 | static const uint8_t *ff_avc_find_startcode(const uint8_t *p, const uint8_t *end); 17 | static const uint8_t *ff_avc_find_startcode_internal(const uint8_t *p, const uint8_t *end); 18 | 19 | void nal_send(const uint8_t *buf, int size, int last); 20 | 21 | private: 22 | k_rtp_sender m_video_sender; 23 | k_rtp_sender m_audio_sender; 24 | }; 25 | 26 | #endif // __K_VIDEO_SENDER_H__ 27 | -------------------------------------------------------------------------------- /app/src/main/cpp/k_rtp_sender.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "k_rtp_sender.h" 3 | 4 | k_rtp_sender::k_rtp_sender(k_socket* p_socket, int payload, uint32_t msg_id) 5 | : m_socket(p_socket) 6 | , m_payload(payload) 7 | , m_msg_id(msg_id) 8 | , m_seq(0) 9 | , m_timestamp(0) 10 | , m_ssrc(0) 11 | { 12 | 13 | } 14 | 15 | k_rtp_sender::~k_rtp_sender() 16 | { 17 | } 18 | 19 | void k_rtp_sender::ff_rtp_send_data(uint8_t *buf1, int len, int m) 20 | { 21 | uint8_t* p_rtp = buf1 - RTP_HEADER_LENGTH; 22 | uint32_t tot_len = len + RTP_HEADER_LENGTH; 23 | /* build the RTP header */ 24 | k_util::avio_wb16(p_rtp, 0x1234);//magic 25 | k_util::avio_wb32(p_rtp, tot_len); 26 | k_util::avio_wb32(p_rtp, m_msg_id); 27 | 28 | k_util::avio_w8(p_rtp, RTP_VERSION << 6); 29 | k_util::avio_w8(p_rtp, (m_payload & 0x7f) | ((m & 0x01) << 7)); 30 | k_util::avio_wb16(p_rtp, m_seq); 31 | k_util::avio_wb32(p_rtp, m_timestamp); 32 | k_util::avio_wb32(p_rtp, m_ssrc); 33 | 34 | m_seq = (m_seq + 1) & 0xffff; 35 | 36 | m_socket->k_send((char*)buf1 - RTP_HEADER_LENGTH, tot_len); 37 | } 38 | 39 | void k_rtp_sender::set_timestamp(uint32_t ts) 40 | { 41 | m_timestamp = ts; 42 | } 43 | 44 | uint8_t* k_rtp_sender::get_payload_buf() 45 | { 46 | return m_rtp_buf + RTP_HEADER_LENGTH; 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/cpp/k_rtp_sender.h: -------------------------------------------------------------------------------- 1 | #ifndef __K_RTP_CONTEXT_H__ 2 | #define __K_RTP_CONTEXT_H__ 3 | 4 | #include 5 | #include "k_util/k_socket.h" 6 | 7 | class k_rtp_sender 8 | { 9 | public: 10 | enum 11 | { 12 | MAX_PAYLOAD_SIZE = 1000 13 | }; 14 | 15 | k_rtp_sender(k_socket* p_socket, int payload, uint32_t msg_id); 16 | ~k_rtp_sender(); 17 | 18 | void ff_rtp_send_data(uint8_t *buf1, int len, int m); 19 | void set_timestamp(uint32_t ts); 20 | uint8_t* get_payload_buf(); 21 | 22 | private: 23 | enum 24 | { 25 | RTP_VERSION = 2, 26 | RTP_HEADER_LENGTH = 22 27 | }; 28 | 29 | k_socket* m_socket; 30 | uint32_t m_msg_id; 31 | int m_seq; 32 | int m_payload; 33 | uint32_t m_timestamp; 34 | uint32_t m_ssrc; 35 | uint8_t m_rtp_buf[RTP_HEADER_LENGTH + MAX_PAYLOAD_SIZE]; 36 | }; 37 | 38 | #endif -------------------------------------------------------------------------------- /app/src/main/cpp/k_server_conn.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Si_Li on 2018/4/22. 3 | // 4 | 5 | #include "k_util/k_util.h" 6 | #include 7 | #include 8 | #include 9 | #include "k_server_conn.h" 10 | #include "k_server_conn_handler.h" 11 | 12 | JavaVM* k_server_conn::g_jvm = NULL; 13 | 14 | k_server_conn::k_server_conn() 15 | : m_server_socket(NULL) 16 | , m_media_sender(NULL) 17 | , m_jni_env(NULL) 18 | , m_callback(NULL) 19 | { 20 | 21 | } 22 | 23 | int k_server_conn::process_msg(k_msg &msg) { 24 | switch (msg.m_msg_id) 25 | { 26 | case 3: 27 | { 28 | if(m_callback != NULL) 29 | { 30 | m_jni_env->DeleteGlobalRef(m_callback); 31 | m_callback = NULL; 32 | } 33 | 34 | if (m_jni_env) 35 | { 36 | g_jvm->DetachCurrentThread(); 37 | m_jni_env = NULL; 38 | } 39 | return k_thread_task::process_msg(msg); 40 | } 41 | break; 42 | case 600: 43 | { 44 | k_init_conn_msg* pmsg = static_cast (msg.m_data); 45 | this->init_conn(pmsg); 46 | delete pmsg; 47 | 48 | return 0; 49 | } 50 | break; 51 | 52 | case 601: 53 | case 602: 54 | { 55 | k_media_msg* pmsg = static_cast (msg.m_data); 56 | 57 | if (m_media_sender == NULL) 58 | { 59 | LOGE("media sender null"); 60 | } else 61 | { 62 | if(msg.m_msg_id == 601) 63 | { 64 | m_media_sender->ff_rtp_send_h264(pmsg->m_data, pmsg->m_size, pmsg->m_ts); 65 | } else 66 | { 67 | m_media_sender->ff_rtp_send_audio(pmsg->m_data, pmsg->m_size, pmsg->m_ts); 68 | } 69 | } 70 | 71 | free(pmsg->m_data); 72 | delete pmsg; 73 | 74 | return 0; 75 | } 76 | break; 77 | 78 | case 603: 79 | { 80 | if(m_server_socket) 81 | this->del_event(m_server_socket); 82 | 83 | return 0; 84 | } 85 | break; 86 | 87 | default: 88 | return k_thread_task::process_msg(msg); 89 | } 90 | 91 | } 92 | 93 | #define MSG_HEAD_LENGTH 10 94 | 95 | int k_server_conn::init_conn(k_init_conn_msg *pmsg) { 96 | if(m_jni_env == NULL) 97 | { 98 | if(g_jvm->AttachCurrentThread(&m_jni_env, NULL) != JNI_OK) 99 | { 100 | LOGE("%s: AttachCurrentThread() failed", __FUNCTION__); 101 | return -1; 102 | } 103 | } 104 | 105 | if (m_server_socket) 106 | { 107 | LOGE("sock change"); 108 | this->del_event(m_server_socket); 109 | 110 | k_init_conn_msg* msg = new k_init_conn_msg; 111 | msg->m_server_ip = pmsg->m_server_ip; 112 | msg->m_server_port = pmsg->m_server_port; 113 | msg->m_user_id = pmsg->m_user_id; 114 | msg->m_password = pmsg->m_password; 115 | msg->m_callback = pmsg->m_callback; 116 | 117 | k_msg new_msg = {600, msg}; 118 | 119 | if(this->enque_msg(new_msg)) 120 | { 121 | m_jni_env->DeleteGlobalRef(pmsg->m_callback); 122 | delete msg; 123 | } 124 | 125 | return 0; 126 | } 127 | 128 | if(m_callback != NULL) 129 | { 130 | m_jni_env->DeleteGlobalRef(m_callback); 131 | } 132 | 133 | m_callback = pmsg->m_callback; 134 | 135 | LOGE("new sock"); 136 | m_server_socket = new k_socket; 137 | m_server_socket->init(AF_INET, SOCK_STREAM); 138 | k_sockaddr addr; 139 | 140 | if(addr.init(AF_INET, pmsg->m_server_ip, pmsg->m_server_port)) 141 | { 142 | LOGE("addr init failed"); 143 | login_callback(-1); 144 | delete m_server_socket; 145 | m_server_socket = NULL; 146 | return -1; 147 | } 148 | 149 | if (m_server_socket->k_connect(addr)) 150 | { 151 | LOGE("connect failed"); 152 | login_callback(-2); 153 | delete m_server_socket; 154 | m_server_socket = NULL; 155 | return -1; 156 | } 157 | 158 | Json::Value jsonRoot; //定义根节点 159 | jsonRoot["user_id"] = pmsg->m_user_id.c_str(); //添加数据 160 | jsonRoot["password"] = pmsg->m_password.c_str(); 161 | 162 | Json::StreamWriterBuilder writer; 163 | std::string document = Json::writeString(writer, jsonRoot); 164 | 165 | char buf[4096]; 166 | uint8_t * p_buf = (uint8_t*)buf; 167 | int tot_len = document.size() + MSG_HEAD_LENGTH; 168 | int msg_id = 1002; 169 | 170 | k_util::avio_wb16(p_buf, 0x1234);//magic 171 | k_util::avio_wb32(p_buf, tot_len); 172 | k_util::avio_wb32(p_buf, msg_id); 173 | 174 | memcpy(p_buf, document.c_str(), document.size()); 175 | 176 | int ret = m_server_socket->k_send(buf, tot_len); 177 | if (ret != tot_len) 178 | { 179 | LOGE("send failed"); 180 | login_callback(-3); 181 | delete m_server_socket; 182 | m_server_socket = NULL; 183 | return -1; 184 | } 185 | 186 | k_server_conn_hander* handler = new k_server_conn_hander; 187 | this->add_event(m_server_socket, handler, k_event::READ_MASK); 188 | m_media_sender = new k_media_sender(m_server_socket); 189 | 190 | return 0; 191 | } 192 | 193 | void k_server_conn::clear_server_socket() { 194 | LOGE("clear sock"); 195 | m_server_socket = NULL; 196 | delete m_media_sender; 197 | m_media_sender = NULL; 198 | } 199 | 200 | void k_server_conn::login_callback(int ret) { 201 | jclass cls = m_jni_env->GetObjectClass(m_callback); 202 | if(cls == NULL) 203 | { 204 | LOGE("FindClass() Error....."); 205 | return ; 206 | } 207 | 208 | jmethodID mid = m_jni_env->GetMethodID(cls, "onLoginCallback", "(I)V"); 209 | if (mid == NULL) 210 | { 211 | LOGE("GetMethodID() Error....."); 212 | return ; 213 | } 214 | 215 | m_jni_env->CallVoidMethod(m_callback, mid, ret); 216 | } 217 | 218 | void k_server_conn::disconnect_callback(int ret) { 219 | jclass cls = m_jni_env->GetObjectClass(m_callback); 220 | if(cls == NULL) 221 | { 222 | LOGE("FindClass() Error....."); 223 | return ; 224 | } 225 | 226 | jmethodID mid = m_jni_env->GetMethodID(cls, "onDisconnectCallback", "(I)V"); 227 | if (mid == NULL) 228 | { 229 | LOGE("GetMethodID() Error....."); 230 | return ; 231 | } 232 | 233 | m_jni_env->CallVoidMethod(m_callback, mid, ret); 234 | } -------------------------------------------------------------------------------- /app/src/main/cpp/k_server_conn.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Si_Li on 2018/4/22. 3 | // 4 | 5 | #ifndef TITAN_K_SERVER_CONN_H 6 | #define TITAN_K_SERVER_CONN_H 7 | 8 | 9 | #include 10 | #include "k_util/k_thread_task.h" 11 | #include "k_util/k_string.h" 12 | #include "k_media_sender.h" 13 | 14 | struct k_init_conn_msg 15 | { 16 | k_string m_user_id; 17 | k_string m_password; 18 | k_string m_server_ip; 19 | int m_server_port; 20 | jobject m_callback; 21 | }; 22 | 23 | struct k_media_msg 24 | { 25 | uint8_t * m_data; 26 | int m_size; 27 | uint32_t m_ts; 28 | }; 29 | 30 | class k_server_conn : public k_thread_task{ 31 | public: 32 | k_server_conn(); 33 | 34 | virtual int process_msg(k_msg& msg); 35 | 36 | void clear_server_socket(); 37 | void login_callback(int ret); 38 | void disconnect_callback(int ret); 39 | 40 | static JavaVM *g_jvm; 41 | 42 | private: 43 | int init_conn(k_init_conn_msg* pmsg); 44 | 45 | private: 46 | k_socket* m_server_socket; 47 | k_media_sender* m_media_sender; 48 | JNIEnv* m_jni_env; 49 | jobject m_callback; 50 | }; 51 | 52 | 53 | #endif //TITAN_K_SERVER_CONN_H 54 | -------------------------------------------------------------------------------- /app/src/main/cpp/k_server_conn_handler.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Si_Li on 2018/4/23. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "k_server_conn_handler.h" 10 | #include "k_server_conn.h" 11 | 12 | int k_server_conn_hander::handle_read(k_thread_task *task, k_event *ev, k_socket *sock) { 13 | int ret = sock->k_recv(m_buf, 4096); 14 | 15 | if (ret <= 0) { 16 | k_server_conn *conn = dynamic_cast(task); 17 | conn->disconnect_callback(-4); 18 | 19 | printf("rev failed:%d\n", ret); 20 | task->del_event(sock); 21 | return 0; 22 | } 23 | 24 | char *p = m_buf; 25 | uint32_t size = ret; 26 | 27 | while (size > 0) { 28 | if (size < MSG_HEAD_LEN) { 29 | int need = MSG_HEAD_LEN - size; 30 | 31 | memcpy(head_buf, p, size); 32 | if (sock->k_recv_n(head_buf + size, need)) { 33 | printf("recv_n failed\n"); 34 | task->del_event(sock); 35 | return -1; 36 | } 37 | 38 | p = head_buf; 39 | size = MSG_HEAD_LEN; 40 | } 41 | 42 | uint16_t magic = *(uint16_t *) p; 43 | magic = ntohs(magic); 44 | p += sizeof(uint16_t); 45 | size -= sizeof(uint16_t); 46 | 47 | if (magic != 0x1234) { 48 | printf("magic:%d wrong\n", magic); 49 | return -1; 50 | } 51 | 52 | uint32_t msg_len = *(uint32_t *) p; 53 | msg_len = ntohl(msg_len); 54 | msg_len -= MSG_HEAD_LEN; 55 | p += sizeof(uint32_t); 56 | size -= sizeof(uint32_t); 57 | 58 | if (msg_len > size) { 59 | uint32_t need = msg_len - size; 60 | 61 | if (msg_len > m_rebuf_size) { 62 | if (m_rebuf) { 63 | free(m_rebuf); 64 | } 65 | 66 | m_rebuf = (char *) malloc(msg_len); 67 | m_rebuf_size = msg_len; 68 | } 69 | 70 | memcpy(m_rebuf, p, size); 71 | if (sock->k_recv_n(m_rebuf + size, need)) { 72 | printf("recv_n 2 failed\n"); 73 | task->del_event(sock); 74 | return -1; 75 | } 76 | 77 | p = m_rebuf; 78 | size = msg_len; 79 | } 80 | 81 | uint32_t msg_id = *(uint32_t *) p; 82 | msg_id = ntohl(msg_id); 83 | char *mbuf = (char *) p + sizeof(uint32_t); 84 | int mlen = msg_len - sizeof(uint32_t); 85 | 86 | if (msg_id == 1003) { 87 | Json::Reader reader; 88 | Json::Value root; 89 | // reader将Json字符串解析到root,root将包含Json里所有子元素 90 | if (!reader.parse(mbuf, mbuf + mlen, root)) { 91 | printf("json parse failed\n"); 92 | return -1; 93 | } 94 | 95 | int result = root["result"].asInt(); 96 | k_string describe = root["describe"].asCString(); 97 | 98 | LOGE("login rsp %d:%s", result, describe.c_str()); 99 | 100 | k_server_conn *conn = dynamic_cast(task); 101 | conn->login_callback(result); 102 | } 103 | 104 | 105 | p += msg_len; 106 | size -= msg_len; 107 | } 108 | 109 | return 0; 110 | } 111 | 112 | void k_server_conn_hander::handle_del(k_thread_task *task, k_event *ev, k_socket *sock) { 113 | k_server_conn *conn = dynamic_cast(task); 114 | conn->clear_server_socket(); 115 | 116 | k_handler::handle_del(task, ev, sock); 117 | } 118 | 119 | k_server_conn_hander::k_server_conn_hander() 120 | : m_rebuf(NULL), m_rebuf_size(0) { 121 | 122 | } 123 | 124 | k_server_conn_hander::~k_server_conn_hander() { 125 | if (m_rebuf) 126 | free(m_rebuf); 127 | 128 | } 129 | -------------------------------------------------------------------------------- /app/src/main/cpp/k_server_conn_handler.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Si_Li on 2018/4/23. 3 | // 4 | 5 | #ifndef TITAN_K_SERVER_CONN_HANDLER_H 6 | #define TITAN_K_SERVER_CONN_HANDLER_H 7 | 8 | #include "k_util/k_handler.h" 9 | 10 | class k_server_conn_hander : public k_handler 11 | { 12 | public: 13 | k_server_conn_hander(); 14 | ~k_server_conn_hander(); 15 | 16 | enum 17 | { 18 | MSG_HEAD_LEN = sizeof(uint16_t) + sizeof(uint32_t) 19 | }; 20 | 21 | int handle_read(k_thread_task* task, k_event* ev, k_socket* sock); 22 | void handle_del(k_thread_task* task, k_event* ev, k_socket* sock); 23 | 24 | private: 25 | char m_buf[4096]; 26 | char head_buf[MSG_HEAD_LEN]; 27 | char* m_rebuf; 28 | uint32_t m_rebuf_size; 29 | 30 | }; 31 | 32 | #endif //TITAN_K_SERVER_CONN_HANDLER_H 33 | -------------------------------------------------------------------------------- /app/src/main/cpp/k_util/k_errno.cpp: -------------------------------------------------------------------------------- 1 | #include "k_errno.h" 2 | 3 | #ifdef WIN32 4 | #include 5 | #else 6 | #include 7 | #endif 8 | 9 | int k_errno::last_error() 10 | { 11 | #ifdef WIN32 12 | return WSAGetLastError(); 13 | #else 14 | return errno; 15 | #endif 16 | } 17 | 18 | bool k_errno::is_retry_error(int err) 19 | { 20 | #ifdef WIN32 21 | return err == WSAEWOULDBLOCK; 22 | //return false; 23 | #else 24 | return err == EINTR; 25 | #endif 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/cpp/k_util/k_errno.h: -------------------------------------------------------------------------------- 1 | #ifndef __K_ERRNO_H__ 2 | #define __K_ERRNO_H__ 3 | 4 | class k_errno 5 | { 6 | public: 7 | static int last_error(); 8 | static bool is_retry_error(int err); 9 | }; 10 | 11 | 12 | #endif -------------------------------------------------------------------------------- /app/src/main/cpp/k_util/k_event.cpp: -------------------------------------------------------------------------------- 1 | #include "k_event.h" 2 | 3 | k_event::k_event() 4 | : m_socket(NULL) 5 | , m_handler(NULL) 6 | , m_event_mask(0) 7 | #ifdef WIN32 8 | , m_event(NULL) 9 | #endif 10 | { 11 | } 12 | 13 | k_event::~k_event() 14 | { 15 | #ifdef WIN32 16 | if (m_event) 17 | { 18 | WSACloseEvent(m_event); 19 | } 20 | #endif 21 | } 22 | 23 | int k_event::init(k_socket* sock, k_handler* handler, uint32_t event_mask) 24 | { 25 | m_socket = sock; 26 | m_handler = handler; 27 | 28 | #ifdef WIN32 29 | m_event = WSACreateEvent(); 30 | 31 | if (m_event == NULL) 32 | { 33 | return -1; 34 | } 35 | #else 36 | m_event.data.ptr = this; 37 | #endif 38 | 39 | if (m_socket && event_mask) 40 | { 41 | if (this->gen_event_mask(event_mask)) 42 | { 43 | return -1; 44 | } 45 | } 46 | 47 | return 0; 48 | } 49 | 50 | K_EVENT_T k_event::get_event() 51 | { 52 | return m_event; 53 | } 54 | 55 | void k_event::process(k_thread_task* task, uint32_t mask) 56 | { 57 | if (mask & READ_MASK) 58 | { 59 | m_handler->handle_read(task, this, m_socket); 60 | } 61 | 62 | if (mask & WRITE_MASK) 63 | { 64 | m_handler->handle_write(task, this, m_socket); 65 | } 66 | 67 | if (mask & ACCEPT_MASK) 68 | { 69 | m_handler->handle_read(task, this, m_socket); 70 | } 71 | 72 | if (mask & CLOSE_MASK) 73 | { 74 | m_handler->handle_close(task, this, m_socket); 75 | } 76 | } 77 | 78 | void k_event::on_del(k_thread_task* task) 79 | { 80 | m_handler->handle_del(task, this, m_socket); 81 | } 82 | 83 | int k_event::gen_event_mask(uint32_t event_mask) 84 | { 85 | if (event_mask & READ_MASK ) 86 | { 87 | #ifdef WIN32 88 | m_event_mask |= FD_READ; 89 | #else 90 | m_event_mask |= EPOLLIN; 91 | #endif 92 | } 93 | 94 | if (event_mask & WRITE_MASK) 95 | { 96 | #ifdef WIN32 97 | m_event_mask |= FD_WRITE; 98 | #else 99 | m_event_mask |= EPOLLOUT; 100 | #endif 101 | } 102 | 103 | if (event_mask & ACCEPT_MASK) 104 | { 105 | 106 | #ifdef WIN32 107 | m_event_mask |= FD_ACCEPT; 108 | #else 109 | m_event_mask |= EPOLLIN; 110 | #endif 111 | } 112 | 113 | #ifdef WIN32 114 | m_event_mask |= FD_CLOSE; 115 | #else 116 | m_event_mask |= EPOLLRDHUP; 117 | 118 | m_event.events = m_event_mask; 119 | #endif 120 | 121 | return 0; 122 | } 123 | 124 | k_socket *k_event::get_socket() { 125 | return m_socket; 126 | } 127 | 128 | K_EVENT_T *k_event::get_event_ptr() { 129 | return &m_event; 130 | } 131 | 132 | uint32_t k_event::get_event_mask() { 133 | return m_event_mask; 134 | } 135 | 136 | int k_event::parse_event_mask(K_EVENT_T event, uint32_t &mask) 137 | { 138 | #ifdef WIN32 139 | if (!m_socket) 140 | { 141 | mask |= READ_MASK; 142 | return 0; 143 | } 144 | 145 | WSANETWORKEVENTS events; 146 | if (WSAEnumNetworkEvents(m_socket->get_sock(), event, &events)) 147 | { 148 | return -1; 149 | } 150 | 151 | if (events.lNetworkEvents & FD_READ) 152 | { 153 | mask |= READ_MASK; 154 | 155 | if (events.iErrorCode[FD_READ_BIT]) 156 | { 157 | mask |= CLOSE_MASK; 158 | } 159 | } 160 | 161 | if (events.lNetworkEvents & FD_WRITE) 162 | { 163 | if (events.iErrorCode[FD_WRITE_BIT]) 164 | { 165 | mask |= CLOSE_MASK; 166 | } 167 | else 168 | { 169 | mask |= WRITE_MASK; 170 | } 171 | } 172 | 173 | if (events.lNetworkEvents & FD_ACCEPT) 174 | { 175 | if (events.iErrorCode[FD_ACCEPT_BIT]) 176 | { 177 | mask |= CLOSE_MASK; 178 | } 179 | else 180 | { 181 | mask |= READ_MASK; 182 | } 183 | } 184 | 185 | if (events.lNetworkEvents & FD_CLOSE) 186 | { 187 | mask |= CLOSE_MASK; 188 | 189 | if (0 == events.iErrorCode[FD_CLOSE_BIT]) 190 | { 191 | mask |= READ_MASK; 192 | } 193 | } 194 | #else 195 | uint32_t ev = event.events; 196 | 197 | if(ev & EPOLLIN) 198 | { 199 | mask |= READ_MASK; 200 | } 201 | 202 | if(ev & EPOLLOUT) 203 | { 204 | mask |= WRITE_MASK; 205 | } 206 | 207 | if(ev & EPOLLERR) 208 | { 209 | mask |= CLOSE_MASK; 210 | } 211 | 212 | if(ev & EPOLLHUP) 213 | { 214 | mask |= CLOSE_MASK; 215 | } 216 | 217 | if (ev & EPOLLRDHUP) 218 | { 219 | mask |= CLOSE_MASK; 220 | } 221 | 222 | #endif 223 | return 0; 224 | } 225 | -------------------------------------------------------------------------------- /app/src/main/cpp/k_util/k_event.h: -------------------------------------------------------------------------------- 1 | #ifndef __K_EVENT_H__ 2 | #define __K_EVENT_H__ 3 | 4 | #ifdef WIN32 5 | #include 6 | #define K_EVENT_T WSAEVENT 7 | #else 8 | #include 9 | #define K_EVENT_T epoll_event 10 | #endif 11 | 12 | #include "k_handler.h" 13 | #include "k_socket.h" 14 | 15 | class k_event 16 | { 17 | public: 18 | enum 19 | { 20 | READ_MASK = (1 << 0), 21 | WRITE_MASK = (1 << 1), 22 | ACCEPT_MASK = (1 << 3), 23 | CLOSE_MASK = (1 << 4) 24 | }; 25 | 26 | k_event(); 27 | ~k_event(); 28 | 29 | int init(k_socket* sock, k_handler* handler, uint32_t event_mask); 30 | K_EVENT_T get_event(); 31 | K_EVENT_T* get_event_ptr(); 32 | k_socket* get_socket(); 33 | uint32_t get_event_mask(); 34 | 35 | void process(k_thread_task* task, uint32_t mask); 36 | void on_del(k_thread_task* task); 37 | 38 | int parse_event_mask(K_EVENT_T event, uint32_t& mask); 39 | 40 | private: 41 | int gen_event_mask(uint32_t event_mask); 42 | 43 | private: 44 | uint32_t m_event_mask; 45 | K_EVENT_T m_event; 46 | k_handler* m_handler; 47 | k_socket* m_socket; 48 | }; 49 | 50 | #endif -------------------------------------------------------------------------------- /app/src/main/cpp/k_util/k_handler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "k_handler.h" 4 | #include "k_socket.h" 5 | #include "k_thread_task.h" 6 | 7 | k_handler::k_handler() { 8 | 9 | } 10 | 11 | k_handler::~k_handler() { 12 | 13 | } 14 | 15 | void k_handler::handle_del(k_thread_task* task, k_event* ev, k_socket* sock) 16 | { 17 | printf("delete sock %p\n", sock); 18 | delete sock; 19 | delete this; 20 | } 21 | 22 | int k_handler::handle_close(k_thread_task* task, k_event* ev, k_socket* sock) 23 | { 24 | printf("close sock %p\n", sock); 25 | return task->del_event(sock); 26 | } 27 | 28 | int k_handler::handle_write(k_thread_task* task, k_event* ev, k_socket* sock) 29 | { 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/cpp/k_util/k_handler.h: -------------------------------------------------------------------------------- 1 | #ifndef __K_HANDLER_H__ 2 | #define __K_HANDLER_H__ 3 | 4 | class k_event; 5 | class k_thread_task; 6 | class k_socket; 7 | 8 | class k_handler 9 | { 10 | public: 11 | k_handler(); 12 | virtual ~k_handler(); 13 | 14 | virtual int handle_read(k_thread_task* task, k_event* ev, k_socket* sock) = 0; 15 | 16 | virtual void handle_del(k_thread_task* task, k_event* ev, k_socket* sock); 17 | virtual int handle_close(k_thread_task* task, k_event* ev, k_socket* sock); 18 | virtual int handle_write(k_thread_task* task, k_event* ev, k_socket* sock); 19 | }; 20 | 21 | #endif -------------------------------------------------------------------------------- /app/src/main/cpp/k_util/k_mutex.cpp: -------------------------------------------------------------------------------- 1 | #include "k_mutex.h" 2 | 3 | k_mutex::k_mutex() 4 | #ifdef WIN32 5 | : m_mutex(NULL) 6 | #endif 7 | { 8 | 9 | } 10 | 11 | k_mutex::~k_mutex() 12 | { 13 | #ifdef WIN32 14 | if (m_mutex != NULL) 15 | { 16 | CloseHandle(m_mutex); 17 | } 18 | #else 19 | pthread_mutex_destroy(&m_mutex); 20 | #endif 21 | } 22 | 23 | int k_mutex::init() 24 | { 25 | #ifdef WIN32 26 | m_mutex = CreateMutex(NULL, FALSE, NULL); 27 | if (m_mutex == NULL) 28 | { 29 | return -1; 30 | } 31 | #else 32 | if(pthread_mutex_init(&m_mutex, NULL)) 33 | { 34 | return -1; 35 | } 36 | #endif 37 | 38 | return 0; 39 | } 40 | 41 | int k_mutex::acquire() 42 | { 43 | #ifdef WIN32 44 | int ret = WaitForSingleObject(m_mutex, INFINITE); 45 | 46 | if (ret != WAIT_OBJECT_0) 47 | { 48 | return -1; 49 | } 50 | #else 51 | if(pthread_mutex_lock(&m_mutex)) 52 | { 53 | return -1; 54 | } 55 | #endif 56 | 57 | return 0; 58 | } 59 | 60 | void k_mutex::release() 61 | { 62 | #ifdef WIN32 63 | ReleaseMutex(m_mutex); 64 | #else 65 | pthread_mutex_unlock(&m_mutex); 66 | #endif 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/cpp/k_util/k_mutex.h: -------------------------------------------------------------------------------- 1 | #ifndef __K_MUTEX_H__ 2 | #define __K_MUTEX_H__ 3 | 4 | #ifdef WIN32 5 | #include 6 | #include 7 | #define K_MUTEX_T HANDLE 8 | #else 9 | #include 10 | #define K_MUTEX_T pthread_mutex_t 11 | #endif 12 | 13 | class k_mutex 14 | { 15 | public: 16 | k_mutex(); 17 | ~k_mutex(); 18 | 19 | int init(); 20 | int acquire(); 21 | void release(); 22 | 23 | private: 24 | K_MUTEX_T m_mutex; 25 | }; 26 | 27 | #endif -------------------------------------------------------------------------------- /app/src/main/cpp/k_util/k_sockaddr.cpp: -------------------------------------------------------------------------------- 1 | #include "k_sockaddr.h" 2 | 3 | k_sockaddr::k_sockaddr() 4 | : m_size(sizeof(m_sockaddr)) 5 | { 6 | 7 | } 8 | 9 | int k_sockaddr::init(int af, k_string& ip, uint16_t port) 10 | { 11 | m_sockaddr.sin_family = af; 12 | m_sockaddr.sin_port = htons(port); 13 | 14 | int ret = inet_pton(af, ip.c_str(), &m_sockaddr.sin_addr.s_addr); 15 | if (ret != 1) 16 | { 17 | return -1; 18 | } 19 | 20 | return 0; 21 | } 22 | 23 | struct sockaddr* k_sockaddr::get_sockaddr() 24 | { 25 | return (struct sockaddr*)&m_sockaddr; 26 | } 27 | 28 | socklen_t k_sockaddr::get_size() 29 | { 30 | return m_size; 31 | } 32 | 33 | socklen_t* k_sockaddr::get_size_ptr() 34 | { 35 | return &m_size; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/cpp/k_util/k_sockaddr.h: -------------------------------------------------------------------------------- 1 | #ifndef __K_SOCKADDR_H__ 2 | #define __K_SOCKADDR_H__ 3 | 4 | #include 5 | #include "k_string.h" 6 | #ifdef WIN32 7 | #include 8 | #include 9 | #else 10 | #include 11 | #include 12 | #include 13 | #endif 14 | 15 | class k_sockaddr 16 | { 17 | public: 18 | k_sockaddr(); 19 | 20 | int init(int af, k_string& ip, uint16_t port); 21 | struct sockaddr* get_sockaddr(); 22 | socklen_t get_size(); 23 | socklen_t* get_size_ptr(); 24 | 25 | private: 26 | struct sockaddr_in m_sockaddr; 27 | socklen_t m_size; 28 | }; 29 | 30 | #endif -------------------------------------------------------------------------------- /app/src/main/cpp/k_util/k_socket.cpp: -------------------------------------------------------------------------------- 1 | #include "k_socket.h" 2 | #include "k_errno.h" 3 | 4 | #ifdef WIN32 5 | #define K_INVALID_SOCKET INVALID_SOCKET 6 | #else 7 | #define K_INVALID_SOCKET -1 8 | #endif 9 | 10 | k_socket::k_socket() 11 | : m_sock(K_INVALID_SOCKET) 12 | { 13 | } 14 | 15 | k_socket::~k_socket() 16 | { 17 | if (m_sock != K_INVALID_SOCKET) 18 | { 19 | #ifdef WIN32 20 | closesocket(m_sock); 21 | #else 22 | close(m_sock); 23 | #endif 24 | } 25 | } 26 | 27 | void k_socket::set_sock(int sock) 28 | { 29 | m_sock = sock; 30 | } 31 | 32 | int k_socket::get_sock() 33 | { 34 | return m_sock; 35 | } 36 | 37 | int k_socket::init(int af, int type) 38 | { 39 | m_sock = socket(af, type, 0); 40 | if (m_sock == K_INVALID_SOCKET) 41 | { 42 | return -1; 43 | } 44 | 45 | return 0; 46 | } 47 | 48 | int k_socket::k_bind(k_sockaddr& sock_addr) 49 | { 50 | int ret = bind(m_sock, sock_addr.get_sockaddr(), sock_addr.get_size()); 51 | if (ret) 52 | { 53 | return -1; 54 | } 55 | 56 | return 0; 57 | } 58 | 59 | int k_socket::k_listen() 60 | { 61 | int ret = listen(m_sock, SOMAXCONN); 62 | 63 | return ret; 64 | } 65 | 66 | int k_socket::k_accept(k_sockaddr& sock_addr, k_socket& sock) 67 | { 68 | while (true) 69 | { 70 | int fd = accept(m_sock, sock_addr.get_sockaddr(), sock_addr.get_size_ptr()); 71 | 72 | if (fd != K_INVALID_SOCKET) 73 | { 74 | sock.set_sock(fd); 75 | 76 | return 0; 77 | } 78 | else 79 | { 80 | int err = k_errno::last_error(); 81 | if (k_errno::is_retry_error(err)) 82 | { 83 | continue; 84 | } 85 | 86 | return -1; 87 | } 88 | } 89 | } 90 | 91 | int k_socket::k_connect(k_sockaddr& sock_addr) 92 | { 93 | while (true) 94 | { 95 | int ret = connect(m_sock, sock_addr.get_sockaddr(), sock_addr.get_size()); 96 | 97 | if (ret) 98 | { 99 | int err = k_errno::last_error(); 100 | if (k_errno::is_retry_error(err)) 101 | { 102 | continue; 103 | } 104 | } 105 | 106 | return ret; 107 | } 108 | } 109 | 110 | int k_socket::k_send(char* buf, int buf_size) 111 | { 112 | int ret; 113 | int offset = 0; 114 | 115 | do 116 | { 117 | ret = send(m_sock, buf + offset, buf_size - offset, 0); 118 | if (ret < 0) 119 | { 120 | int err = k_errno::last_error(); 121 | if (k_errno::is_retry_error(err)) 122 | { 123 | continue; 124 | } 125 | else 126 | { 127 | break; 128 | } 129 | } 130 | else 131 | { 132 | offset += ret; 133 | } 134 | 135 | } while (offset != buf_size); 136 | 137 | if (offset != buf_size) 138 | { 139 | return ret; 140 | } 141 | else 142 | { 143 | return offset; 144 | } 145 | } 146 | 147 | int k_socket::k_recv(char* buf, int buf_size) 148 | { 149 | while (true) 150 | { 151 | int ret = recv(m_sock, buf, buf_size, 0); 152 | 153 | if (ret < 0) 154 | { 155 | int err = k_errno::last_error(); 156 | if (k_errno::is_retry_error(err)) 157 | { 158 | continue; 159 | } 160 | } 161 | 162 | return ret; 163 | } 164 | } 165 | 166 | int k_socket::k_recv_n(char* buf, int buf_size) 167 | { 168 | int offset = 0; 169 | int ret; 170 | 171 | while (offset < buf_size) 172 | { 173 | ret = this->k_recv(buf + offset, buf_size - offset); 174 | if (ret <= 0) 175 | { 176 | return -1; 177 | } 178 | offset += ret; 179 | } 180 | 181 | return 0; 182 | } 183 | 184 | int k_socket::k_setopt(int level, int optname, const char *optval, socklen_t optlen) 185 | { 186 | return setsockopt(m_sock, level, optname, optval, optlen); 187 | } 188 | 189 | #ifndef WIN32 190 | int k_socket::k_write(char* buf, int buf_size) 191 | { 192 | return write(m_sock, buf, buf_size); 193 | } 194 | 195 | int k_socket::k_read(char* buf, int buf_size) 196 | { 197 | return read(m_sock, buf, buf_size); 198 | } 199 | #endif 200 | 201 | int k_socket::k_recvfrom(char* buf, int buf_size, k_sockaddr& from_addr) 202 | { 203 | while (true) 204 | { 205 | int ret = recvfrom(m_sock, buf, buf_size, 0, 206 | from_addr.get_sockaddr(), from_addr.get_size_ptr()); 207 | 208 | if (ret < 0) 209 | { 210 | int err = k_errno::last_error(); 211 | if (k_errno::is_retry_error(err)) 212 | { 213 | continue; 214 | } 215 | } 216 | 217 | return ret; 218 | } 219 | 220 | } 221 | 222 | int k_socket::k_sendto(char* buf, int buf_size, k_sockaddr& to_addr) 223 | { 224 | int ret; 225 | int offset = 0; 226 | 227 | do 228 | { 229 | ret = sendto(m_sock, buf + offset, buf_size - offset, 0, 230 | to_addr.get_sockaddr(), to_addr.get_size()); 231 | if (ret < 0) 232 | { 233 | int err = k_errno::last_error(); 234 | if (k_errno::is_retry_error(err)) 235 | { 236 | continue; 237 | } 238 | else 239 | { 240 | break; 241 | } 242 | } 243 | else 244 | { 245 | offset += ret; 246 | } 247 | 248 | } while (offset != buf_size); 249 | 250 | if (offset != buf_size) 251 | { 252 | return ret; 253 | } 254 | else 255 | { 256 | return offset; 257 | } 258 | } 259 | -------------------------------------------------------------------------------- /app/src/main/cpp/k_util/k_socket.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenjim301/Titan/f47756ab7d7c1726d5dd06cd3b8c88b34de9d234/app/src/main/cpp/k_util/k_socket.h -------------------------------------------------------------------------------- /app/src/main/cpp/k_util/k_string.cpp: -------------------------------------------------------------------------------- 1 | #include "k_string.h" 2 | #include 3 | 4 | k_string::k_string() 5 | : m_size(0) 6 | { 7 | memset(m_buf, 0, STR_MAX_LEN); 8 | } 9 | 10 | k_string::k_string(const char* str) 11 | { 12 | memset(m_buf, 0, STR_MAX_LEN); 13 | int size = strlen(str); 14 | if (size < STR_MAX_LEN) 15 | { 16 | m_size = size; 17 | memcpy(m_buf, str, m_size); 18 | } 19 | else 20 | { 21 | m_size = 0; 22 | } 23 | } 24 | 25 | const char* k_string::c_str() const 26 | { 27 | return m_buf; 28 | } 29 | 30 | int k_string::size() const 31 | { 32 | return m_size; 33 | } 34 | 35 | bool k_string::operator<(const k_string& r_str) const 36 | { 37 | if (m_size > r_str.size()) 38 | { 39 | if (memcmp(this->c_str(), r_str.c_str(), r_str.size()) <= 0) 40 | { 41 | return true; 42 | } 43 | else 44 | { 45 | return false; 46 | } 47 | } 48 | else 49 | { 50 | if (memcmp(this->c_str(), r_str.c_str(), m_size) >= 0) 51 | { 52 | return false; 53 | } 54 | else 55 | { 56 | return true; 57 | } 58 | } 59 | } 60 | 61 | bool k_string::operator==(const k_string &r_str) const { 62 | if(m_size != r_str.size()) 63 | return false; 64 | 65 | return 0 == memcmp(m_buf, r_str.c_str(), m_size); 66 | } 67 | 68 | -------------------------------------------------------------------------------- /app/src/main/cpp/k_util/k_string.h: -------------------------------------------------------------------------------- 1 | #ifndef __K_STRING_H__ 2 | #define __K_STRING_H__ 3 | 4 | class k_string 5 | { 6 | public: 7 | k_string(); 8 | k_string(const char* str); 9 | 10 | const char* c_str() const; 11 | int size() const; 12 | 13 | bool operator < (const k_string& r_str) const; 14 | bool operator == (const k_string& r_str) const; 15 | 16 | private: 17 | enum 18 | { 19 | STR_MAX_LEN = 256 20 | }; 21 | 22 | char m_buf[STR_MAX_LEN]; 23 | int m_size; 24 | }; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /app/src/main/cpp/k_util/k_thread_task.h: -------------------------------------------------------------------------------- 1 | #ifndef __K_THREAD_TASK_H__ 2 | #define __K_THREAD_TASK_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include "k_event.h" 8 | #include "k_mutex.h" 9 | 10 | struct k_msg 11 | { 12 | int m_msg_id; 13 | void* m_data; 14 | }; 15 | 16 | struct k_add_event 17 | { 18 | k_socket* m_sock; 19 | k_handler* m_handler; 20 | uint32_t m_event_mask; 21 | }; 22 | 23 | struct k_del_event 24 | { 25 | k_socket* m_sock; 26 | }; 27 | 28 | class k_thread_task 29 | { 30 | public: 31 | k_thread_task(); 32 | virtual ~k_thread_task(); 33 | 34 | int init(); 35 | int run(); 36 | int exit(); 37 | 38 | int add_event(k_socket* sock, k_handler* handler, uint32_t event_mask); 39 | int del_event(k_socket* sock); 40 | int enque_msg(k_msg& msg); 41 | virtual int process_msg(k_msg& msg); 42 | 43 | private: 44 | class k_mq_notify_handler : public k_handler 45 | { 46 | public: 47 | int handle_read(k_thread_task* mask, k_event* ev, k_socket* sock); 48 | }; 49 | 50 | int init_msg_que_notify(); 51 | int notify_msg_que(); 52 | void clear_events(); 53 | 54 | void set_process_msg(); 55 | void reset_process_msg(); 56 | 57 | int deque_msg(k_msg& msg); 58 | int process_msg(); 59 | 60 | int add_event_impl(k_event* ev); 61 | int del_event_impl(k_event* ev); 62 | 63 | private: 64 | #ifdef WIN32 65 | k_event* m_mq_event; 66 | #else 67 | int m_epoll_fd; 68 | int m_notify_pipe[2]; 69 | k_socket* m_notify_socket; 70 | #endif 71 | 72 | typedef std::map event_map_type; 73 | event_map_type m_events; 74 | 75 | typedef std::queue msg_que_type; 76 | msg_que_type m_msg_que; 77 | k_mutex m_mq_mutex; 78 | bool m_porcess_msg; 79 | bool m_exit; 80 | }; 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /app/src/main/cpp/k_util/k_util.cpp: -------------------------------------------------------------------------------- 1 | #include "k_util.h" 2 | #ifdef WIN32 3 | #include 4 | #endif 5 | 6 | int k_util::init() 7 | { 8 | #ifdef WIN32 9 | WSADATA wsaData; 10 | if (WSAStartup(MAKEWORD(2, 2), &wsaData)) 11 | { 12 | return -1; 13 | } 14 | #endif 15 | 16 | return 0; 17 | } 18 | 19 | void k_util::cleanup() 20 | { 21 | #ifdef WIN32 22 | WSACleanup(); 23 | #endif 24 | } 25 | 26 | void k_util::avio_w8(uint8_t*& s, int b) 27 | { 28 | *s++ = b; 29 | } 30 | 31 | void k_util::avio_wb16(uint8_t*& s, unsigned int val) 32 | { 33 | avio_w8(s, (int)val >> 8); 34 | avio_w8(s, (uint8_t)val); 35 | } 36 | 37 | void k_util::avio_wb32(uint8_t*& s, unsigned int val) 38 | { 39 | avio_w8(s, val >> 24); 40 | avio_w8(s, (uint8_t)(val >> 16)); 41 | avio_w8(s, (uint8_t)(val >> 8)); 42 | avio_w8(s, (uint8_t)val); 43 | } 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/cpp/k_util/k_util.h: -------------------------------------------------------------------------------- 1 | #ifndef __K_UTIL_H__ 2 | #define __K_UTIL_H__ 3 | 4 | #include 5 | 6 | #define TAG "native-lib" // 这个是自定义的LOG的标识 7 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型 8 | 9 | #include 10 | 11 | class k_util 12 | { 13 | public: 14 | static int init(); 15 | static void cleanup(); 16 | 17 | static void avio_w8(uint8_t*& s, int b); 18 | static void avio_wb16(uint8_t*& s, unsigned int val); 19 | static void avio_wb32(uint8_t*& s, unsigned int val); 20 | }; 21 | 22 | #endif -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/include/libyuv/basic_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_BASIC_TYPES_H_ 12 | #define INCLUDE_LIBYUV_BASIC_TYPES_H_ 13 | 14 | #include // For size_t and NULL 15 | 16 | #if !defined(INT_TYPES_DEFINED) && !defined(GG_LONGLONG) 17 | #define INT_TYPES_DEFINED 18 | 19 | #if defined(_MSC_VER) && (_MSC_VER < 1600) 20 | #include // for uintptr_t on x86 21 | typedef unsigned __int64 uint64_t; 22 | typedef __int64 int64_t; 23 | typedef unsigned int uint32_t; 24 | typedef int int32_t; 25 | typedef unsigned short uint16_t; 26 | typedef short int16_t; 27 | typedef unsigned char uint8_t; 28 | typedef signed char int8_t; 29 | #else 30 | #include // for uintptr_t and C99 types 31 | #endif // defined(_MSC_VER) && (_MSC_VER < 1600) 32 | typedef uint64_t uint64; 33 | typedef int64_t int64; 34 | typedef uint32_t uint32; 35 | typedef int32_t int32; 36 | typedef uint16_t uint16; 37 | typedef int16_t int16; 38 | typedef uint8_t uint8; 39 | typedef int8_t int8; 40 | #endif // INT_TYPES_DEFINED 41 | 42 | #if !defined(LIBYUV_API) 43 | #if defined(_WIN32) || defined(__CYGWIN__) 44 | #if defined(LIBYUV_BUILDING_SHARED_LIBRARY) 45 | #define LIBYUV_API __declspec(dllexport) 46 | #elif defined(LIBYUV_USING_SHARED_LIBRARY) 47 | #define LIBYUV_API __declspec(dllimport) 48 | #else 49 | #define LIBYUV_API 50 | #endif // LIBYUV_BUILDING_SHARED_LIBRARY 51 | #elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__APPLE__) && \ 52 | (defined(LIBYUV_BUILDING_SHARED_LIBRARY) || \ 53 | defined(LIBYUV_USING_SHARED_LIBRARY)) 54 | #define LIBYUV_API __attribute__((visibility("default"))) 55 | #else 56 | #define LIBYUV_API 57 | #endif // __GNUC__ 58 | #endif // LIBYUV_API 59 | 60 | // TODO(fbarchard): Remove bool macros. 61 | #define LIBYUV_BOOL int 62 | #define LIBYUV_FALSE 0 63 | #define LIBYUV_TRUE 1 64 | 65 | #endif // INCLUDE_LIBYUV_BASIC_TYPES_H_ 66 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/include/libyuv/compare.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_COMPARE_H_ 12 | #define INCLUDE_LIBYUV_COMPARE_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | // Compute a hash for specified memory. Seed of 5381 recommended. 22 | LIBYUV_API 23 | uint32_t HashDjb2(const uint8_t* src, uint64_t count, uint32_t seed); 24 | 25 | // Hamming Distance 26 | LIBYUV_API 27 | uint64_t ComputeHammingDistance(const uint8_t* src_a, 28 | const uint8_t* src_b, 29 | int count); 30 | 31 | // Scan an opaque argb image and return fourcc based on alpha offset. 32 | // Returns FOURCC_ARGB, FOURCC_BGRA, or 0 if unknown. 33 | LIBYUV_API 34 | uint32_t ARGBDetect(const uint8_t* argb, 35 | int stride_argb, 36 | int width, 37 | int height); 38 | 39 | // Sum Square Error - used to compute Mean Square Error or PSNR. 40 | LIBYUV_API 41 | uint64_t ComputeSumSquareError(const uint8_t* src_a, 42 | const uint8_t* src_b, 43 | int count); 44 | 45 | LIBYUV_API 46 | uint64_t ComputeSumSquareErrorPlane(const uint8_t* src_a, 47 | int stride_a, 48 | const uint8_t* src_b, 49 | int stride_b, 50 | int width, 51 | int height); 52 | 53 | static const int kMaxPsnr = 128; 54 | 55 | LIBYUV_API 56 | double SumSquareErrorToPsnr(uint64_t sse, uint64_t count); 57 | 58 | LIBYUV_API 59 | double CalcFramePsnr(const uint8_t* src_a, 60 | int stride_a, 61 | const uint8_t* src_b, 62 | int stride_b, 63 | int width, 64 | int height); 65 | 66 | LIBYUV_API 67 | double I420Psnr(const uint8_t* src_y_a, 68 | int stride_y_a, 69 | const uint8_t* src_u_a, 70 | int stride_u_a, 71 | const uint8_t* src_v_a, 72 | int stride_v_a, 73 | const uint8_t* src_y_b, 74 | int stride_y_b, 75 | const uint8_t* src_u_b, 76 | int stride_u_b, 77 | const uint8_t* src_v_b, 78 | int stride_v_b, 79 | int width, 80 | int height); 81 | 82 | LIBYUV_API 83 | double CalcFrameSsim(const uint8_t* src_a, 84 | int stride_a, 85 | const uint8_t* src_b, 86 | int stride_b, 87 | int width, 88 | int height); 89 | 90 | LIBYUV_API 91 | double I420Ssim(const uint8_t* src_y_a, 92 | int stride_y_a, 93 | const uint8_t* src_u_a, 94 | int stride_u_a, 95 | const uint8_t* src_v_a, 96 | int stride_v_a, 97 | const uint8_t* src_y_b, 98 | int stride_y_b, 99 | const uint8_t* src_u_b, 100 | int stride_u_b, 101 | const uint8_t* src_v_b, 102 | int stride_v_b, 103 | int width, 104 | int height); 105 | 106 | #ifdef __cplusplus 107 | } // extern "C" 108 | } // namespace libyuv 109 | #endif 110 | 111 | #endif // INCLUDE_LIBYUV_COMPARE_H_ 112 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/include/libyuv/compare_row.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_COMPARE_ROW_H_ 12 | #define INCLUDE_LIBYUV_COMPARE_ROW_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | #if defined(__pnacl__) || defined(__CLR_VER) || \ 22 | (defined(__native_client__) && defined(__x86_64__)) || \ 23 | (defined(__i386__) && !defined(__SSE__) && !defined(__clang__)) 24 | #define LIBYUV_DISABLE_X86 25 | #endif 26 | #if defined(__native_client__) 27 | #define LIBYUV_DISABLE_NEON 28 | #endif 29 | // MemorySanitizer does not support assembly code yet. http://crbug.com/344505 30 | #if defined(__has_feature) 31 | #if __has_feature(memory_sanitizer) 32 | #define LIBYUV_DISABLE_X86 33 | #endif 34 | #endif 35 | // Visual C 2012 required for AVX2. 36 | #if defined(_M_IX86) && !defined(__clang__) && defined(_MSC_VER) && \ 37 | _MSC_VER >= 1700 38 | #define VISUALC_HAS_AVX2 1 39 | #endif // VisualStudio >= 2012 40 | 41 | // clang >= 3.4.0 required for AVX2. 42 | #if defined(__clang__) && (defined(__x86_64__) || defined(__i386__)) 43 | #if (__clang_major__ > 3) || (__clang_major__ == 3 && (__clang_minor__ >= 4)) 44 | #define CLANG_HAS_AVX2 1 45 | #endif // clang >= 3.4 46 | #endif // __clang__ 47 | 48 | // The following are available for Visual C and GCC: 49 | #if !defined(LIBYUV_DISABLE_X86) && \ 50 | (defined(__x86_64__) || defined(__i386__) || defined(_M_IX86)) 51 | #define HAS_HASHDJB2_SSE41 52 | #define HAS_SUMSQUAREERROR_SSE2 53 | #define HAS_HAMMINGDISTANCE_SSE42 54 | #endif 55 | 56 | // The following are available for Visual C and clangcl 32 bit: 57 | #if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER) && \ 58 | (defined(VISUALC_HAS_AVX2) || defined(CLANG_HAS_AVX2)) 59 | #define HAS_HASHDJB2_AVX2 60 | #define HAS_SUMSQUAREERROR_AVX2 61 | #endif 62 | 63 | // The following are available for GCC and clangcl 64 bit: 64 | #if !defined(LIBYUV_DISABLE_X86) && \ 65 | (defined(__x86_64__) || (defined(__i386__) && !defined(_MSC_VER))) 66 | #define HAS_HAMMINGDISTANCE_SSSE3 67 | #endif 68 | 69 | // The following are available for GCC and clangcl 64 bit: 70 | #if !defined(LIBYUV_DISABLE_X86) && defined(CLANG_HAS_AVX2) && \ 71 | (defined(__x86_64__) || (defined(__i386__) && !defined(_MSC_VER))) 72 | #define HAS_HAMMINGDISTANCE_AVX2 73 | #endif 74 | 75 | // The following are available for Neon: 76 | #if !defined(LIBYUV_DISABLE_NEON) && \ 77 | (defined(__ARM_NEON__) || defined(LIBYUV_NEON) || defined(__aarch64__)) 78 | #define HAS_SUMSQUAREERROR_NEON 79 | #define HAS_HAMMINGDISTANCE_NEON 80 | #endif 81 | 82 | #if !defined(LIBYUV_DISABLE_MSA) && defined(__mips_msa) 83 | #define HAS_HAMMINGDISTANCE_MSA 84 | #define HAS_SUMSQUAREERROR_MSA 85 | #endif 86 | 87 | uint32_t HammingDistance_C(const uint8_t* src_a, 88 | const uint8_t* src_b, 89 | int count); 90 | uint32_t HammingDistance_SSE42(const uint8_t* src_a, 91 | const uint8_t* src_b, 92 | int count); 93 | uint32_t HammingDistance_SSSE3(const uint8_t* src_a, 94 | const uint8_t* src_b, 95 | int count); 96 | uint32_t HammingDistance_AVX2(const uint8_t* src_a, 97 | const uint8_t* src_b, 98 | int count); 99 | uint32_t HammingDistance_NEON(const uint8_t* src_a, 100 | const uint8_t* src_b, 101 | int count); 102 | uint32_t HammingDistance_MSA(const uint8_t* src_a, 103 | const uint8_t* src_b, 104 | int count); 105 | 106 | uint32_t SumSquareError_C(const uint8_t* src_a, 107 | const uint8_t* src_b, 108 | int count); 109 | uint32_t SumSquareError_SSE2(const uint8_t* src_a, 110 | const uint8_t* src_b, 111 | int count); 112 | uint32_t SumSquareError_AVX2(const uint8_t* src_a, 113 | const uint8_t* src_b, 114 | int count); 115 | uint32_t SumSquareError_NEON(const uint8_t* src_a, 116 | const uint8_t* src_b, 117 | int count); 118 | uint32_t SumSquareError_MSA(const uint8_t* src_a, 119 | const uint8_t* src_b, 120 | int count); 121 | 122 | uint32_t HashDjb2_C(const uint8_t* src, int count, uint32_t seed); 123 | uint32_t HashDjb2_SSE41(const uint8_t* src, int count, uint32_t seed); 124 | uint32_t HashDjb2_AVX2(const uint8_t* src, int count, uint32_t seed); 125 | 126 | #ifdef __cplusplus 127 | } // extern "C" 128 | } // namespace libyuv 129 | #endif 130 | 131 | #endif // INCLUDE_LIBYUV_COMPARE_ROW_H_ 132 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/include/libyuv/convert_from_argb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_CONVERT_FROM_ARGB_H_ 12 | #define INCLUDE_LIBYUV_CONVERT_FROM_ARGB_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | // Copy ARGB to ARGB. 22 | #define ARGBToARGB ARGBCopy 23 | LIBYUV_API 24 | int ARGBCopy(const uint8_t* src_argb, 25 | int src_stride_argb, 26 | uint8_t* dst_argb, 27 | int dst_stride_argb, 28 | int width, 29 | int height); 30 | 31 | // Convert ARGB To BGRA. 32 | LIBYUV_API 33 | int ARGBToBGRA(const uint8_t* src_argb, 34 | int src_stride_argb, 35 | uint8_t* dst_bgra, 36 | int dst_stride_bgra, 37 | int width, 38 | int height); 39 | 40 | // Convert ARGB To ABGR. 41 | LIBYUV_API 42 | int ARGBToABGR(const uint8_t* src_argb, 43 | int src_stride_argb, 44 | uint8_t* dst_abgr, 45 | int dst_stride_abgr, 46 | int width, 47 | int height); 48 | 49 | // Convert ARGB To RGBA. 50 | LIBYUV_API 51 | int ARGBToRGBA(const uint8_t* src_argb, 52 | int src_stride_argb, 53 | uint8_t* dst_rgba, 54 | int dst_stride_rgba, 55 | int width, 56 | int height); 57 | 58 | // Aliases 59 | #define ARGBToAB30 ABGRToAR30 60 | #define ABGRToAB30 ARGBToAR30 61 | 62 | // Convert ABGR To AR30. 63 | LIBYUV_API 64 | int ABGRToAR30(const uint8_t* src_abgr, 65 | int src_stride_abgr, 66 | uint8_t* dst_ar30, 67 | int dst_stride_ar30, 68 | int width, 69 | int height); 70 | 71 | // Convert ARGB To AR30. 72 | LIBYUV_API 73 | int ARGBToAR30(const uint8_t* src_argb, 74 | int src_stride_argb, 75 | uint8_t* dst_ar30, 76 | int dst_stride_ar30, 77 | int width, 78 | int height); 79 | 80 | // Convert ARGB To RGB24. 81 | LIBYUV_API 82 | int ARGBToRGB24(const uint8_t* src_argb, 83 | int src_stride_argb, 84 | uint8_t* dst_rgb24, 85 | int dst_stride_rgb24, 86 | int width, 87 | int height); 88 | 89 | // Convert ARGB To RAW. 90 | LIBYUV_API 91 | int ARGBToRAW(const uint8_t* src_argb, 92 | int src_stride_argb, 93 | uint8_t* dst_raw, 94 | int dst_stride_raw, 95 | int width, 96 | int height); 97 | 98 | // Convert ARGB To RGB565. 99 | LIBYUV_API 100 | int ARGBToRGB565(const uint8_t* src_argb, 101 | int src_stride_argb, 102 | uint8_t* dst_rgb565, 103 | int dst_stride_rgb565, 104 | int width, 105 | int height); 106 | 107 | // Convert ARGB To RGB565 with 4x4 dither matrix (16 bytes). 108 | // Values in dither matrix from 0 to 7 recommended. 109 | // The order of the dither matrix is first byte is upper left. 110 | // TODO(fbarchard): Consider pointer to 2d array for dither4x4. 111 | // const uint8_t(*dither)[4][4]; 112 | LIBYUV_API 113 | int ARGBToRGB565Dither(const uint8_t* src_argb, 114 | int src_stride_argb, 115 | uint8_t* dst_rgb565, 116 | int dst_stride_rgb565, 117 | const uint8_t* dither4x4, 118 | int width, 119 | int height); 120 | 121 | // Convert ARGB To ARGB1555. 122 | LIBYUV_API 123 | int ARGBToARGB1555(const uint8_t* src_argb, 124 | int src_stride_argb, 125 | uint8_t* dst_argb1555, 126 | int dst_stride_argb1555, 127 | int width, 128 | int height); 129 | 130 | // Convert ARGB To ARGB4444. 131 | LIBYUV_API 132 | int ARGBToARGB4444(const uint8_t* src_argb, 133 | int src_stride_argb, 134 | uint8_t* dst_argb4444, 135 | int dst_stride_argb4444, 136 | int width, 137 | int height); 138 | 139 | // Convert ARGB To I444. 140 | LIBYUV_API 141 | int ARGBToI444(const uint8_t* src_argb, 142 | int src_stride_argb, 143 | uint8_t* dst_y, 144 | int dst_stride_y, 145 | uint8_t* dst_u, 146 | int dst_stride_u, 147 | uint8_t* dst_v, 148 | int dst_stride_v, 149 | int width, 150 | int height); 151 | 152 | // Convert ARGB To I422. 153 | LIBYUV_API 154 | int ARGBToI422(const uint8_t* src_argb, 155 | int src_stride_argb, 156 | uint8_t* dst_y, 157 | int dst_stride_y, 158 | uint8_t* dst_u, 159 | int dst_stride_u, 160 | uint8_t* dst_v, 161 | int dst_stride_v, 162 | int width, 163 | int height); 164 | 165 | // Convert ARGB To I420. (also in convert.h) 166 | LIBYUV_API 167 | int ARGBToI420(const uint8_t* src_argb, 168 | int src_stride_argb, 169 | uint8_t* dst_y, 170 | int dst_stride_y, 171 | uint8_t* dst_u, 172 | int dst_stride_u, 173 | uint8_t* dst_v, 174 | int dst_stride_v, 175 | int width, 176 | int height); 177 | 178 | // Convert ARGB to J420. (JPeg full range I420). 179 | LIBYUV_API 180 | int ARGBToJ420(const uint8_t* src_argb, 181 | int src_stride_argb, 182 | uint8_t* dst_yj, 183 | int dst_stride_yj, 184 | uint8_t* dst_u, 185 | int dst_stride_u, 186 | uint8_t* dst_v, 187 | int dst_stride_v, 188 | int width, 189 | int height); 190 | 191 | // Convert ARGB to J422. 192 | LIBYUV_API 193 | int ARGBToJ422(const uint8_t* src_argb, 194 | int src_stride_argb, 195 | uint8_t* dst_yj, 196 | int dst_stride_yj, 197 | uint8_t* dst_u, 198 | int dst_stride_u, 199 | uint8_t* dst_v, 200 | int dst_stride_v, 201 | int width, 202 | int height); 203 | 204 | // Convert ARGB to J400. (JPeg full range). 205 | LIBYUV_API 206 | int ARGBToJ400(const uint8_t* src_argb, 207 | int src_stride_argb, 208 | uint8_t* dst_yj, 209 | int dst_stride_yj, 210 | int width, 211 | int height); 212 | 213 | // Convert ARGB to I400. 214 | LIBYUV_API 215 | int ARGBToI400(const uint8_t* src_argb, 216 | int src_stride_argb, 217 | uint8_t* dst_y, 218 | int dst_stride_y, 219 | int width, 220 | int height); 221 | 222 | // Convert ARGB to G. (Reverse of J400toARGB, which replicates G back to ARGB) 223 | LIBYUV_API 224 | int ARGBToG(const uint8_t* src_argb, 225 | int src_stride_argb, 226 | uint8_t* dst_g, 227 | int dst_stride_g, 228 | int width, 229 | int height); 230 | 231 | // Convert ARGB To NV12. 232 | LIBYUV_API 233 | int ARGBToNV12(const uint8_t* src_argb, 234 | int src_stride_argb, 235 | uint8_t* dst_y, 236 | int dst_stride_y, 237 | uint8_t* dst_uv, 238 | int dst_stride_uv, 239 | int width, 240 | int height); 241 | 242 | // Convert ARGB To NV21. 243 | LIBYUV_API 244 | int ARGBToNV21(const uint8_t* src_argb, 245 | int src_stride_argb, 246 | uint8_t* dst_y, 247 | int dst_stride_y, 248 | uint8_t* dst_vu, 249 | int dst_stride_vu, 250 | int width, 251 | int height); 252 | 253 | // Convert ARGB To NV21. 254 | LIBYUV_API 255 | int ARGBToNV21(const uint8_t* src_argb, 256 | int src_stride_argb, 257 | uint8_t* dst_y, 258 | int dst_stride_y, 259 | uint8_t* dst_vu, 260 | int dst_stride_vu, 261 | int width, 262 | int height); 263 | 264 | // Convert ARGB To YUY2. 265 | LIBYUV_API 266 | int ARGBToYUY2(const uint8_t* src_argb, 267 | int src_stride_argb, 268 | uint8_t* dst_yuy2, 269 | int dst_stride_yuy2, 270 | int width, 271 | int height); 272 | 273 | // Convert ARGB To UYVY. 274 | LIBYUV_API 275 | int ARGBToUYVY(const uint8_t* src_argb, 276 | int src_stride_argb, 277 | uint8_t* dst_uyvy, 278 | int dst_stride_uyvy, 279 | int width, 280 | int height); 281 | 282 | #ifdef __cplusplus 283 | } // extern "C" 284 | } // namespace libyuv 285 | #endif 286 | 287 | #endif // INCLUDE_LIBYUV_CONVERT_FROM_ARGB_H_ 288 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/include/libyuv/cpu_id.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_CPU_ID_H_ 12 | #define INCLUDE_LIBYUV_CPU_ID_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | // Internal flag to indicate cpuid requires initialization. 22 | static const int kCpuInitialized = 0x1; 23 | 24 | // These flags are only valid on ARM processors. 25 | static const int kCpuHasARM = 0x2; 26 | static const int kCpuHasNEON = 0x4; 27 | // 0x8 reserved for future ARM flag. 28 | 29 | // These flags are only valid on x86 processors. 30 | static const int kCpuHasX86 = 0x10; 31 | static const int kCpuHasSSE2 = 0x20; 32 | static const int kCpuHasSSSE3 = 0x40; 33 | static const int kCpuHasSSE41 = 0x80; 34 | static const int kCpuHasSSE42 = 0x100; // unused at this time. 35 | static const int kCpuHasAVX = 0x200; 36 | static const int kCpuHasAVX2 = 0x400; 37 | static const int kCpuHasERMS = 0x800; 38 | static const int kCpuHasFMA3 = 0x1000; 39 | static const int kCpuHasF16C = 0x2000; 40 | static const int kCpuHasGFNI = 0x4000; 41 | static const int kCpuHasAVX512BW = 0x8000; 42 | static const int kCpuHasAVX512VL = 0x10000; 43 | static const int kCpuHasAVX512VBMI = 0x20000; 44 | static const int kCpuHasAVX512VBMI2 = 0x40000; 45 | static const int kCpuHasAVX512VBITALG = 0x80000; 46 | static const int kCpuHasAVX512VPOPCNTDQ = 0x100000; 47 | 48 | // These flags are only valid on MIPS processors. 49 | static const int kCpuHasMIPS = 0x200000; 50 | static const int kCpuHasMSA = 0x400000; 51 | 52 | // Optional init function. TestCpuFlag does an auto-init. 53 | // Returns cpu_info flags. 54 | LIBYUV_API 55 | int InitCpuFlags(void); 56 | 57 | // Detect CPU has SSE2 etc. 58 | // Test_flag parameter should be one of kCpuHas constants above. 59 | // Returns non-zero if instruction set is detected 60 | static __inline int TestCpuFlag(int test_flag) { 61 | LIBYUV_API extern int cpu_info_; 62 | #ifdef __ATOMIC_RELAXED 63 | int cpu_info = __atomic_load_n(&cpu_info_, __ATOMIC_RELAXED); 64 | #else 65 | int cpu_info = cpu_info_; 66 | #endif 67 | return (!cpu_info ? InitCpuFlags() : cpu_info) & test_flag; 68 | } 69 | 70 | // Internal function for parsing /proc/cpuinfo. 71 | LIBYUV_API 72 | int ArmCpuCaps(const char* cpuinfo_name); 73 | 74 | // For testing, allow CPU flags to be disabled. 75 | // ie MaskCpuFlags(~kCpuHasSSSE3) to disable SSSE3. 76 | // MaskCpuFlags(-1) to enable all cpu specific optimizations. 77 | // MaskCpuFlags(1) to disable all cpu specific optimizations. 78 | // MaskCpuFlags(0) to reset state so next call will auto init. 79 | // Returns cpu_info flags. 80 | LIBYUV_API 81 | int MaskCpuFlags(int enable_flags); 82 | 83 | // Sets the CPU flags to |cpu_flags|, bypassing the detection code. |cpu_flags| 84 | // should be a valid combination of the kCpuHas constants above and include 85 | // kCpuInitialized. Use this method when running in a sandboxed process where 86 | // the detection code might fail (as it might access /proc/cpuinfo). In such 87 | // cases the cpu_info can be obtained from a non sandboxed process by calling 88 | // InitCpuFlags() and passed to the sandboxed process (via command line 89 | // parameters, IPC...) which can then call this method to initialize the CPU 90 | // flags. 91 | // Notes: 92 | // - when specifying 0 for |cpu_flags|, the auto initialization is enabled 93 | // again. 94 | // - enabling CPU features that are not supported by the CPU will result in 95 | // undefined behavior. 96 | // TODO(fbarchard): consider writing a helper function that translates from 97 | // other library CPU info to libyuv CPU info and add a .md doc that explains 98 | // CPU detection. 99 | static __inline void SetCpuFlags(int cpu_flags) { 100 | LIBYUV_API extern int cpu_info_; 101 | #ifdef __ATOMIC_RELAXED 102 | __atomic_store_n(&cpu_info_, cpu_flags, __ATOMIC_RELAXED); 103 | #else 104 | cpu_info_ = cpu_flags; 105 | #endif 106 | } 107 | 108 | // Low level cpuid for X86. Returns zeros on other CPUs. 109 | // eax is the info type that you want. 110 | // ecx is typically the cpu number, and should normally be zero. 111 | LIBYUV_API 112 | void CpuId(int info_eax, int info_ecx, int* cpu_info); 113 | 114 | #ifdef __cplusplus 115 | } // extern "C" 116 | } // namespace libyuv 117 | #endif 118 | 119 | #endif // INCLUDE_LIBYUV_CPU_ID_H_ 120 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/include/libyuv/mjpeg_decoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_MJPEG_DECODER_H_ 12 | #define INCLUDE_LIBYUV_MJPEG_DECODER_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | // NOTE: For a simplified public API use convert.h MJPGToI420(). 18 | 19 | struct jpeg_common_struct; 20 | struct jpeg_decompress_struct; 21 | struct jpeg_source_mgr; 22 | 23 | namespace libyuv { 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | LIBYUV_BOOL ValidateJpeg(const uint8_t* sample, size_t sample_size); 30 | 31 | #ifdef __cplusplus 32 | } // extern "C" 33 | #endif 34 | 35 | static const uint32_t kUnknownDataSize = 0xFFFFFFFF; 36 | 37 | enum JpegSubsamplingType { 38 | kJpegYuv420, 39 | kJpegYuv422, 40 | kJpegYuv444, 41 | kJpegYuv400, 42 | kJpegUnknown 43 | }; 44 | 45 | struct Buffer { 46 | const uint8_t* data; 47 | int len; 48 | }; 49 | 50 | struct BufferVector { 51 | Buffer* buffers; 52 | int len; 53 | int pos; 54 | }; 55 | 56 | struct SetJmpErrorMgr; 57 | 58 | // MJPEG ("Motion JPEG") is a pseudo-standard video codec where the frames are 59 | // simply independent JPEG images with a fixed huffman table (which is omitted). 60 | // It is rarely used in video transmission, but is common as a camera capture 61 | // format, especially in Logitech devices. This class implements a decoder for 62 | // MJPEG frames. 63 | // 64 | // See http://tools.ietf.org/html/rfc2435 65 | class LIBYUV_API MJpegDecoder { 66 | public: 67 | typedef void (*CallbackFunction)(void* opaque, 68 | const uint8_t* const* data, 69 | const int* strides, 70 | int rows); 71 | 72 | static const int kColorSpaceUnknown; 73 | static const int kColorSpaceGrayscale; 74 | static const int kColorSpaceRgb; 75 | static const int kColorSpaceYCbCr; 76 | static const int kColorSpaceCMYK; 77 | static const int kColorSpaceYCCK; 78 | 79 | MJpegDecoder(); 80 | ~MJpegDecoder(); 81 | 82 | // Loads a new frame, reads its headers, and determines the uncompressed 83 | // image format. 84 | // Returns LIBYUV_TRUE if image looks valid and format is supported. 85 | // If return value is LIBYUV_TRUE, then the values for all the following 86 | // getters are populated. 87 | // src_len is the size of the compressed mjpeg frame in bytes. 88 | LIBYUV_BOOL LoadFrame(const uint8_t* src, size_t src_len); 89 | 90 | // Returns width of the last loaded frame in pixels. 91 | int GetWidth(); 92 | 93 | // Returns height of the last loaded frame in pixels. 94 | int GetHeight(); 95 | 96 | // Returns format of the last loaded frame. The return value is one of the 97 | // kColorSpace* constants. 98 | int GetColorSpace(); 99 | 100 | // Number of color components in the color space. 101 | int GetNumComponents(); 102 | 103 | // Sample factors of the n-th component. 104 | int GetHorizSampFactor(int component); 105 | 106 | int GetVertSampFactor(int component); 107 | 108 | int GetHorizSubSampFactor(int component); 109 | 110 | int GetVertSubSampFactor(int component); 111 | 112 | // Public for testability. 113 | int GetImageScanlinesPerImcuRow(); 114 | 115 | // Public for testability. 116 | int GetComponentScanlinesPerImcuRow(int component); 117 | 118 | // Width of a component in bytes. 119 | int GetComponentWidth(int component); 120 | 121 | // Height of a component. 122 | int GetComponentHeight(int component); 123 | 124 | // Width of a component in bytes with padding for DCTSIZE. Public for testing. 125 | int GetComponentStride(int component); 126 | 127 | // Size of a component in bytes. 128 | int GetComponentSize(int component); 129 | 130 | // Call this after LoadFrame() if you decide you don't want to decode it 131 | // after all. 132 | LIBYUV_BOOL UnloadFrame(); 133 | 134 | // Decodes the entire image into a one-buffer-per-color-component format. 135 | // dst_width must match exactly. dst_height must be <= to image height; if 136 | // less, the image is cropped. "planes" must have size equal to at least 137 | // GetNumComponents() and they must point to non-overlapping buffers of size 138 | // at least GetComponentSize(i). The pointers in planes are incremented 139 | // to point to after the end of the written data. 140 | // TODO(fbarchard): Add dst_x, dst_y to allow specific rect to be decoded. 141 | LIBYUV_BOOL DecodeToBuffers(uint8_t** planes, int dst_width, int dst_height); 142 | 143 | // Decodes the entire image and passes the data via repeated calls to a 144 | // callback function. Each call will get the data for a whole number of 145 | // image scanlines. 146 | // TODO(fbarchard): Add dst_x, dst_y to allow specific rect to be decoded. 147 | LIBYUV_BOOL DecodeToCallback(CallbackFunction fn, 148 | void* opaque, 149 | int dst_width, 150 | int dst_height); 151 | 152 | // The helper function which recognizes the jpeg sub-sampling type. 153 | static JpegSubsamplingType JpegSubsamplingTypeHelper( 154 | int* subsample_x, 155 | int* subsample_y, 156 | int number_of_components); 157 | 158 | private: 159 | void AllocOutputBuffers(int num_outbufs); 160 | void DestroyOutputBuffers(); 161 | 162 | LIBYUV_BOOL StartDecode(); 163 | LIBYUV_BOOL FinishDecode(); 164 | 165 | void SetScanlinePointers(uint8_t** data); 166 | LIBYUV_BOOL DecodeImcuRow(); 167 | 168 | int GetComponentScanlinePadding(int component); 169 | 170 | // A buffer holding the input data for a frame. 171 | Buffer buf_; 172 | BufferVector buf_vec_; 173 | 174 | jpeg_decompress_struct* decompress_struct_; 175 | jpeg_source_mgr* source_mgr_; 176 | SetJmpErrorMgr* error_mgr_; 177 | 178 | // LIBYUV_TRUE iff at least one component has scanline padding. (i.e., 179 | // GetComponentScanlinePadding() != 0.) 180 | LIBYUV_BOOL has_scanline_padding_; 181 | 182 | // Temporaries used to point to scanline outputs. 183 | int num_outbufs_; // Outermost size of all arrays below. 184 | uint8_t*** scanlines_; 185 | int* scanlines_sizes_; 186 | // Temporary buffer used for decoding when we can't decode directly to the 187 | // output buffers. Large enough for just one iMCU row. 188 | uint8_t** databuf_; 189 | int* databuf_strides_; 190 | }; 191 | 192 | } // namespace libyuv 193 | 194 | #endif // __cplusplus 195 | #endif // INCLUDE_LIBYUV_MJPEG_DECODER_H_ 196 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/include/libyuv/rotate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_ROTATE_H_ 12 | #define INCLUDE_LIBYUV_ROTATE_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | // Supported rotation. 22 | typedef enum RotationMode { 23 | kRotate0 = 0, // No rotation. 24 | kRotate90 = 90, // Rotate 90 degrees clockwise. 25 | kRotate180 = 180, // Rotate 180 degrees. 26 | kRotate270 = 270, // Rotate 270 degrees clockwise. 27 | 28 | // Deprecated. 29 | kRotateNone = 0, 30 | kRotateClockwise = 90, 31 | kRotateCounterClockwise = 270, 32 | } RotationModeEnum; 33 | 34 | // Rotate I420 frame. 35 | LIBYUV_API 36 | int I420Rotate(const uint8_t* src_y, 37 | int src_stride_y, 38 | const uint8_t* src_u, 39 | int src_stride_u, 40 | const uint8_t* src_v, 41 | int src_stride_v, 42 | uint8_t* dst_y, 43 | int dst_stride_y, 44 | uint8_t* dst_u, 45 | int dst_stride_u, 46 | uint8_t* dst_v, 47 | int dst_stride_v, 48 | int width, 49 | int height, 50 | enum RotationMode mode); 51 | 52 | // Rotate NV12 input and store in I420. 53 | LIBYUV_API 54 | int NV12ToI420Rotate(const uint8_t* src_y, 55 | int src_stride_y, 56 | const uint8_t* src_uv, 57 | int src_stride_uv, 58 | uint8_t* dst_y, 59 | int dst_stride_y, 60 | uint8_t* dst_u, 61 | int dst_stride_u, 62 | uint8_t* dst_v, 63 | int dst_stride_v, 64 | int width, 65 | int height, 66 | enum RotationMode mode); 67 | 68 | // Rotate a plane by 0, 90, 180, or 270. 69 | LIBYUV_API 70 | int RotatePlane(const uint8_t* src, 71 | int src_stride, 72 | uint8_t* dst, 73 | int dst_stride, 74 | int width, 75 | int height, 76 | enum RotationMode mode); 77 | 78 | // Rotate planes by 90, 180, 270. Deprecated. 79 | LIBYUV_API 80 | void RotatePlane90(const uint8_t* src, 81 | int src_stride, 82 | uint8_t* dst, 83 | int dst_stride, 84 | int width, 85 | int height); 86 | 87 | LIBYUV_API 88 | void RotatePlane180(const uint8_t* src, 89 | int src_stride, 90 | uint8_t* dst, 91 | int dst_stride, 92 | int width, 93 | int height); 94 | 95 | LIBYUV_API 96 | void RotatePlane270(const uint8_t* src, 97 | int src_stride, 98 | uint8_t* dst, 99 | int dst_stride, 100 | int width, 101 | int height); 102 | 103 | LIBYUV_API 104 | void RotateUV90(const uint8_t* src, 105 | int src_stride, 106 | uint8_t* dst_a, 107 | int dst_stride_a, 108 | uint8_t* dst_b, 109 | int dst_stride_b, 110 | int width, 111 | int height); 112 | 113 | // Rotations for when U and V are interleaved. 114 | // These functions take one input pointer and 115 | // split the data into two buffers while 116 | // rotating them. Deprecated. 117 | LIBYUV_API 118 | void RotateUV180(const uint8_t* src, 119 | int src_stride, 120 | uint8_t* dst_a, 121 | int dst_stride_a, 122 | uint8_t* dst_b, 123 | int dst_stride_b, 124 | int width, 125 | int height); 126 | 127 | LIBYUV_API 128 | void RotateUV270(const uint8_t* src, 129 | int src_stride, 130 | uint8_t* dst_a, 131 | int dst_stride_a, 132 | uint8_t* dst_b, 133 | int dst_stride_b, 134 | int width, 135 | int height); 136 | 137 | // The 90 and 270 functions are based on transposes. 138 | // Doing a transpose with reversing the read/write 139 | // order will result in a rotation by +- 90 degrees. 140 | // Deprecated. 141 | LIBYUV_API 142 | void TransposePlane(const uint8_t* src, 143 | int src_stride, 144 | uint8_t* dst, 145 | int dst_stride, 146 | int width, 147 | int height); 148 | 149 | LIBYUV_API 150 | void TransposeUV(const uint8_t* src, 151 | int src_stride, 152 | uint8_t* dst_a, 153 | int dst_stride_a, 154 | uint8_t* dst_b, 155 | int dst_stride_b, 156 | int width, 157 | int height); 158 | 159 | #ifdef __cplusplus 160 | } // extern "C" 161 | } // namespace libyuv 162 | #endif 163 | 164 | #endif // INCLUDE_LIBYUV_ROTATE_H_ 165 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/include/libyuv/rotate_argb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_ROTATE_ARGB_H_ 12 | #define INCLUDE_LIBYUV_ROTATE_ARGB_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | #include "libyuv/rotate.h" // For RotationMode. 16 | 17 | #ifdef __cplusplus 18 | namespace libyuv { 19 | extern "C" { 20 | #endif 21 | 22 | // Rotate ARGB frame 23 | LIBYUV_API 24 | int ARGBRotate(const uint8_t* src_argb, 25 | int src_stride_argb, 26 | uint8_t* dst_argb, 27 | int dst_stride_argb, 28 | int src_width, 29 | int src_height, 30 | enum RotationMode mode); 31 | 32 | #ifdef __cplusplus 33 | } // extern "C" 34 | } // namespace libyuv 35 | #endif 36 | 37 | #endif // INCLUDE_LIBYUV_ROTATE_ARGB_H_ 38 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/include/libyuv/rotate_row.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_ROTATE_ROW_H_ 12 | #define INCLUDE_LIBYUV_ROTATE_ROW_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | #if defined(__pnacl__) || defined(__CLR_VER) || \ 22 | (defined(__native_client__) && defined(__x86_64__)) || \ 23 | (defined(__i386__) && !defined(__SSE__) && !defined(__clang__)) 24 | #define LIBYUV_DISABLE_X86 25 | #endif 26 | #if defined(__native_client__) 27 | #define LIBYUV_DISABLE_NEON 28 | #endif 29 | // MemorySanitizer does not support assembly code yet. http://crbug.com/344505 30 | #if defined(__has_feature) 31 | #if __has_feature(memory_sanitizer) 32 | #define LIBYUV_DISABLE_X86 33 | #endif 34 | #endif 35 | // The following are available for Visual C and clangcl 32 bit: 36 | #if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER) 37 | #define HAS_TRANSPOSEWX8_SSSE3 38 | #define HAS_TRANSPOSEUVWX8_SSE2 39 | #endif 40 | 41 | // The following are available for GCC 32 or 64 bit: 42 | #if !defined(LIBYUV_DISABLE_X86) && (defined(__i386__) || defined(__x86_64__)) 43 | #define HAS_TRANSPOSEWX8_SSSE3 44 | #endif 45 | 46 | // The following are available for 64 bit GCC: 47 | #if !defined(LIBYUV_DISABLE_X86) && defined(__x86_64__) 48 | #define HAS_TRANSPOSEWX8_FAST_SSSE3 49 | #define HAS_TRANSPOSEUVWX8_SSE2 50 | #endif 51 | 52 | #if !defined(LIBYUV_DISABLE_NEON) && \ 53 | (defined(__ARM_NEON__) || defined(LIBYUV_NEON) || defined(__aarch64__)) 54 | #define HAS_TRANSPOSEWX8_NEON 55 | #define HAS_TRANSPOSEUVWX8_NEON 56 | #endif 57 | 58 | #if !defined(LIBYUV_DISABLE_MSA) && defined(__mips_msa) 59 | #define HAS_TRANSPOSEWX16_MSA 60 | #define HAS_TRANSPOSEUVWX16_MSA 61 | #endif 62 | 63 | void TransposeWxH_C(const uint8_t* src, 64 | int src_stride, 65 | uint8_t* dst, 66 | int dst_stride, 67 | int width, 68 | int height); 69 | 70 | void TransposeWx8_C(const uint8_t* src, 71 | int src_stride, 72 | uint8_t* dst, 73 | int dst_stride, 74 | int width); 75 | void TransposeWx16_C(const uint8_t* src, 76 | int src_stride, 77 | uint8_t* dst, 78 | int dst_stride, 79 | int width); 80 | void TransposeWx8_NEON(const uint8_t* src, 81 | int src_stride, 82 | uint8_t* dst, 83 | int dst_stride, 84 | int width); 85 | void TransposeWx8_SSSE3(const uint8_t* src, 86 | int src_stride, 87 | uint8_t* dst, 88 | int dst_stride, 89 | int width); 90 | void TransposeWx8_Fast_SSSE3(const uint8_t* src, 91 | int src_stride, 92 | uint8_t* dst, 93 | int dst_stride, 94 | int width); 95 | void TransposeWx16_MSA(const uint8_t* src, 96 | int src_stride, 97 | uint8_t* dst, 98 | int dst_stride, 99 | int width); 100 | 101 | void TransposeWx8_Any_NEON(const uint8_t* src, 102 | int src_stride, 103 | uint8_t* dst, 104 | int dst_stride, 105 | int width); 106 | void TransposeWx8_Any_SSSE3(const uint8_t* src, 107 | int src_stride, 108 | uint8_t* dst, 109 | int dst_stride, 110 | int width); 111 | void TransposeWx8_Fast_Any_SSSE3(const uint8_t* src, 112 | int src_stride, 113 | uint8_t* dst, 114 | int dst_stride, 115 | int width); 116 | void TransposeWx16_Any_MSA(const uint8_t* src, 117 | int src_stride, 118 | uint8_t* dst, 119 | int dst_stride, 120 | int width); 121 | 122 | void TransposeUVWxH_C(const uint8_t* src, 123 | int src_stride, 124 | uint8_t* dst_a, 125 | int dst_stride_a, 126 | uint8_t* dst_b, 127 | int dst_stride_b, 128 | int width, 129 | int height); 130 | 131 | void TransposeUVWx8_C(const uint8_t* src, 132 | int src_stride, 133 | uint8_t* dst_a, 134 | int dst_stride_a, 135 | uint8_t* dst_b, 136 | int dst_stride_b, 137 | int width); 138 | void TransposeUVWx16_C(const uint8_t* src, 139 | int src_stride, 140 | uint8_t* dst_a, 141 | int dst_stride_a, 142 | uint8_t* dst_b, 143 | int dst_stride_b, 144 | int width); 145 | void TransposeUVWx8_SSE2(const uint8_t* src, 146 | int src_stride, 147 | uint8_t* dst_a, 148 | int dst_stride_a, 149 | uint8_t* dst_b, 150 | int dst_stride_b, 151 | int width); 152 | void TransposeUVWx8_NEON(const uint8_t* src, 153 | int src_stride, 154 | uint8_t* dst_a, 155 | int dst_stride_a, 156 | uint8_t* dst_b, 157 | int dst_stride_b, 158 | int width); 159 | void TransposeUVWx16_MSA(const uint8_t* src, 160 | int src_stride, 161 | uint8_t* dst_a, 162 | int dst_stride_a, 163 | uint8_t* dst_b, 164 | int dst_stride_b, 165 | int width); 166 | 167 | void TransposeUVWx8_Any_SSE2(const uint8_t* src, 168 | int src_stride, 169 | uint8_t* dst_a, 170 | int dst_stride_a, 171 | uint8_t* dst_b, 172 | int dst_stride_b, 173 | int width); 174 | void TransposeUVWx8_Any_NEON(const uint8_t* src, 175 | int src_stride, 176 | uint8_t* dst_a, 177 | int dst_stride_a, 178 | uint8_t* dst_b, 179 | int dst_stride_b, 180 | int width); 181 | void TransposeUVWx16_Any_MSA(const uint8_t* src, 182 | int src_stride, 183 | uint8_t* dst_a, 184 | int dst_stride_a, 185 | uint8_t* dst_b, 186 | int dst_stride_b, 187 | int width); 188 | 189 | #ifdef __cplusplus 190 | } // extern "C" 191 | } // namespace libyuv 192 | #endif 193 | 194 | #endif // INCLUDE_LIBYUV_ROTATE_ROW_H_ 195 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/include/libyuv/scale.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_SCALE_H_ 12 | #define INCLUDE_LIBYUV_SCALE_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | // Supported filtering. 22 | typedef enum FilterMode { 23 | kFilterNone = 0, // Point sample; Fastest. 24 | kFilterLinear = 1, // Filter horizontally only. 25 | kFilterBilinear = 2, // Faster than box, but lower quality scaling down. 26 | kFilterBox = 3 // Highest quality. 27 | } FilterModeEnum; 28 | 29 | // Scale a YUV plane. 30 | LIBYUV_API 31 | void ScalePlane(const uint8_t* src, 32 | int src_stride, 33 | int src_width, 34 | int src_height, 35 | uint8_t* dst, 36 | int dst_stride, 37 | int dst_width, 38 | int dst_height, 39 | enum FilterMode filtering); 40 | 41 | LIBYUV_API 42 | void ScalePlane_16(const uint16_t* src, 43 | int src_stride, 44 | int src_width, 45 | int src_height, 46 | uint16_t* dst, 47 | int dst_stride, 48 | int dst_width, 49 | int dst_height, 50 | enum FilterMode filtering); 51 | 52 | // Scales a YUV 4:2:0 image from the src width and height to the 53 | // dst width and height. 54 | // If filtering is kFilterNone, a simple nearest-neighbor algorithm is 55 | // used. This produces basic (blocky) quality at the fastest speed. 56 | // If filtering is kFilterBilinear, interpolation is used to produce a better 57 | // quality image, at the expense of speed. 58 | // If filtering is kFilterBox, averaging is used to produce ever better 59 | // quality image, at further expense of speed. 60 | // Returns 0 if successful. 61 | 62 | LIBYUV_API 63 | int I420Scale(const uint8_t* src_y, 64 | int src_stride_y, 65 | const uint8_t* src_u, 66 | int src_stride_u, 67 | const uint8_t* src_v, 68 | int src_stride_v, 69 | int src_width, 70 | int src_height, 71 | uint8_t* dst_y, 72 | int dst_stride_y, 73 | uint8_t* dst_u, 74 | int dst_stride_u, 75 | uint8_t* dst_v, 76 | int dst_stride_v, 77 | int dst_width, 78 | int dst_height, 79 | enum FilterMode filtering); 80 | 81 | LIBYUV_API 82 | int I420Scale_16(const uint16_t* src_y, 83 | int src_stride_y, 84 | const uint16_t* src_u, 85 | int src_stride_u, 86 | const uint16_t* src_v, 87 | int src_stride_v, 88 | int src_width, 89 | int src_height, 90 | uint16_t* dst_y, 91 | int dst_stride_y, 92 | uint16_t* dst_u, 93 | int dst_stride_u, 94 | uint16_t* dst_v, 95 | int dst_stride_v, 96 | int dst_width, 97 | int dst_height, 98 | enum FilterMode filtering); 99 | 100 | #ifdef __cplusplus 101 | // Legacy API. Deprecated. 102 | LIBYUV_API 103 | int Scale(const uint8_t* src_y, 104 | const uint8_t* src_u, 105 | const uint8_t* src_v, 106 | int src_stride_y, 107 | int src_stride_u, 108 | int src_stride_v, 109 | int src_width, 110 | int src_height, 111 | uint8_t* dst_y, 112 | uint8_t* dst_u, 113 | uint8_t* dst_v, 114 | int dst_stride_y, 115 | int dst_stride_u, 116 | int dst_stride_v, 117 | int dst_width, 118 | int dst_height, 119 | LIBYUV_BOOL interpolate); 120 | 121 | // For testing, allow disabling of specialized scalers. 122 | LIBYUV_API 123 | void SetUseReferenceImpl(LIBYUV_BOOL use); 124 | #endif // __cplusplus 125 | 126 | #ifdef __cplusplus 127 | } // extern "C" 128 | } // namespace libyuv 129 | #endif 130 | 131 | #endif // INCLUDE_LIBYUV_SCALE_H_ 132 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/include/libyuv/scale_argb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_SCALE_ARGB_H_ 12 | #define INCLUDE_LIBYUV_SCALE_ARGB_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | #include "libyuv/scale.h" // For FilterMode 16 | 17 | #ifdef __cplusplus 18 | namespace libyuv { 19 | extern "C" { 20 | #endif 21 | 22 | LIBYUV_API 23 | int ARGBScale(const uint8_t* src_argb, 24 | int src_stride_argb, 25 | int src_width, 26 | int src_height, 27 | uint8_t* dst_argb, 28 | int dst_stride_argb, 29 | int dst_width, 30 | int dst_height, 31 | enum FilterMode filtering); 32 | 33 | // Clipped scale takes destination rectangle coordinates for clip values. 34 | LIBYUV_API 35 | int ARGBScaleClip(const uint8_t* src_argb, 36 | int src_stride_argb, 37 | int src_width, 38 | int src_height, 39 | uint8_t* dst_argb, 40 | int dst_stride_argb, 41 | int dst_width, 42 | int dst_height, 43 | int clip_x, 44 | int clip_y, 45 | int clip_width, 46 | int clip_height, 47 | enum FilterMode filtering); 48 | 49 | // Scale with YUV conversion to ARGB and clipping. 50 | LIBYUV_API 51 | int YUVToARGBScaleClip(const uint8_t* src_y, 52 | int src_stride_y, 53 | const uint8_t* src_u, 54 | int src_stride_u, 55 | const uint8_t* src_v, 56 | int src_stride_v, 57 | uint32_t src_fourcc, 58 | int src_width, 59 | int src_height, 60 | uint8_t* dst_argb, 61 | int dst_stride_argb, 62 | uint32_t dst_fourcc, 63 | int dst_width, 64 | int dst_height, 65 | int clip_x, 66 | int clip_y, 67 | int clip_width, 68 | int clip_height, 69 | enum FilterMode filtering); 70 | 71 | #ifdef __cplusplus 72 | } // extern "C" 73 | } // namespace libyuv 74 | #endif 75 | 76 | #endif // INCLUDE_LIBYUV_SCALE_ARGB_H_ 77 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/include/libyuv/version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_VERSION_H_ 12 | #define INCLUDE_LIBYUV_VERSION_H_ 13 | 14 | #define LIBYUV_VERSION 1709 15 | 16 | #endif // INCLUDE_LIBYUV_VERSION_H_ 17 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/include/libyuv/video_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | // Common definitions for video, including fourcc and VideoFormat. 12 | 13 | #ifndef INCLUDE_LIBYUV_VIDEO_COMMON_H_ 14 | #define INCLUDE_LIBYUV_VIDEO_COMMON_H_ 15 | 16 | #include "libyuv/basic_types.h" 17 | 18 | #ifdef __cplusplus 19 | namespace libyuv { 20 | extern "C" { 21 | #endif 22 | 23 | ////////////////////////////////////////////////////////////////////////////// 24 | // Definition of FourCC codes 25 | ////////////////////////////////////////////////////////////////////////////// 26 | 27 | // Convert four characters to a FourCC code. 28 | // Needs to be a macro otherwise the OS X compiler complains when the kFormat* 29 | // constants are used in a switch. 30 | #ifdef __cplusplus 31 | #define FOURCC(a, b, c, d) \ 32 | ((static_cast(a)) | (static_cast(b) << 8) | \ 33 | (static_cast(c) << 16) | (static_cast(d) << 24)) 34 | #else 35 | #define FOURCC(a, b, c, d) \ 36 | (((uint32_t)(a)) | ((uint32_t)(b) << 8) | /* NOLINT */ \ 37 | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) /* NOLINT */ 38 | #endif 39 | 40 | // Some pages discussing FourCC codes: 41 | // http://www.fourcc.org/yuv.php 42 | // http://v4l2spec.bytesex.org/spec/book1.htm 43 | // http://developer.apple.com/quicktime/icefloe/dispatch020.html 44 | // http://msdn.microsoft.com/library/windows/desktop/dd206750.aspx#nv12 45 | // http://people.xiph.org/~xiphmont/containers/nut/nut4cc.txt 46 | 47 | // FourCC codes grouped according to implementation efficiency. 48 | // Primary formats should convert in 1 efficient step. 49 | // Secondary formats are converted in 2 steps. 50 | // Auxilliary formats call primary converters. 51 | enum FourCC { 52 | // 9 Primary YUV formats: 5 planar, 2 biplanar, 2 packed. 53 | FOURCC_I420 = FOURCC('I', '4', '2', '0'), 54 | FOURCC_I422 = FOURCC('I', '4', '2', '2'), 55 | FOURCC_I444 = FOURCC('I', '4', '4', '4'), 56 | FOURCC_I400 = FOURCC('I', '4', '0', '0'), 57 | FOURCC_NV21 = FOURCC('N', 'V', '2', '1'), 58 | FOURCC_NV12 = FOURCC('N', 'V', '1', '2'), 59 | FOURCC_YUY2 = FOURCC('Y', 'U', 'Y', '2'), 60 | FOURCC_UYVY = FOURCC('U', 'Y', 'V', 'Y'), 61 | FOURCC_H010 = FOURCC('H', '0', '1', '0'), // unofficial fourcc. 10 bit lsb 62 | 63 | // 1 Secondary YUV format: row biplanar. 64 | FOURCC_M420 = FOURCC('M', '4', '2', '0'), 65 | 66 | // 11 Primary RGB formats: 4 32 bpp, 2 24 bpp, 3 16 bpp, 1 10 bpc 67 | FOURCC_ARGB = FOURCC('A', 'R', 'G', 'B'), 68 | FOURCC_BGRA = FOURCC('B', 'G', 'R', 'A'), 69 | FOURCC_ABGR = FOURCC('A', 'B', 'G', 'R'), 70 | FOURCC_AR30 = FOURCC('A', 'R', '3', '0'), // 10 bit per channel. 2101010. 71 | FOURCC_AB30 = FOURCC('A', 'B', '3', '0'), // ABGR version of 10 bit 72 | FOURCC_24BG = FOURCC('2', '4', 'B', 'G'), 73 | FOURCC_RAW = FOURCC('r', 'a', 'w', ' '), 74 | FOURCC_RGBA = FOURCC('R', 'G', 'B', 'A'), 75 | FOURCC_RGBP = FOURCC('R', 'G', 'B', 'P'), // rgb565 LE. 76 | FOURCC_RGBO = FOURCC('R', 'G', 'B', 'O'), // argb1555 LE. 77 | FOURCC_R444 = FOURCC('R', '4', '4', '4'), // argb4444 LE. 78 | 79 | // 1 Primary Compressed YUV format. 80 | FOURCC_MJPG = FOURCC('M', 'J', 'P', 'G'), 81 | 82 | // 7 Auxiliary YUV variations: 3 with U and V planes are swapped, 1 Alias. 83 | FOURCC_YV12 = FOURCC('Y', 'V', '1', '2'), 84 | FOURCC_YV16 = FOURCC('Y', 'V', '1', '6'), 85 | FOURCC_YV24 = FOURCC('Y', 'V', '2', '4'), 86 | FOURCC_YU12 = FOURCC('Y', 'U', '1', '2'), // Linux version of I420. 87 | FOURCC_J420 = FOURCC('J', '4', '2', '0'), 88 | FOURCC_J400 = FOURCC('J', '4', '0', '0'), // unofficial fourcc 89 | FOURCC_H420 = FOURCC('H', '4', '2', '0'), // unofficial fourcc 90 | 91 | // 14 Auxiliary aliases. CanonicalFourCC() maps these to canonical fourcc. 92 | FOURCC_IYUV = FOURCC('I', 'Y', 'U', 'V'), // Alias for I420. 93 | FOURCC_YU16 = FOURCC('Y', 'U', '1', '6'), // Alias for I422. 94 | FOURCC_YU24 = FOURCC('Y', 'U', '2', '4'), // Alias for I444. 95 | FOURCC_YUYV = FOURCC('Y', 'U', 'Y', 'V'), // Alias for YUY2. 96 | FOURCC_YUVS = FOURCC('y', 'u', 'v', 's'), // Alias for YUY2 on Mac. 97 | FOURCC_HDYC = FOURCC('H', 'D', 'Y', 'C'), // Alias for UYVY. 98 | FOURCC_2VUY = FOURCC('2', 'v', 'u', 'y'), // Alias for UYVY on Mac. 99 | FOURCC_JPEG = FOURCC('J', 'P', 'E', 'G'), // Alias for MJPG. 100 | FOURCC_DMB1 = FOURCC('d', 'm', 'b', '1'), // Alias for MJPG on Mac. 101 | FOURCC_BA81 = FOURCC('B', 'A', '8', '1'), // Alias for BGGR. 102 | FOURCC_RGB3 = FOURCC('R', 'G', 'B', '3'), // Alias for RAW. 103 | FOURCC_BGR3 = FOURCC('B', 'G', 'R', '3'), // Alias for 24BG. 104 | FOURCC_CM32 = FOURCC(0, 0, 0, 32), // Alias for BGRA kCMPixelFormat_32ARGB 105 | FOURCC_CM24 = FOURCC(0, 0, 0, 24), // Alias for RAW kCMPixelFormat_24RGB 106 | FOURCC_L555 = FOURCC('L', '5', '5', '5'), // Alias for RGBO. 107 | FOURCC_L565 = FOURCC('L', '5', '6', '5'), // Alias for RGBP. 108 | FOURCC_5551 = FOURCC('5', '5', '5', '1'), // Alias for RGBO. 109 | 110 | // deprecated formats. Not supported, but defined for backward compatibility. 111 | FOURCC_I411 = FOURCC('I', '4', '1', '1'), 112 | FOURCC_Q420 = FOURCC('Q', '4', '2', '0'), 113 | FOURCC_RGGB = FOURCC('R', 'G', 'G', 'B'), 114 | FOURCC_BGGR = FOURCC('B', 'G', 'G', 'R'), 115 | FOURCC_GRBG = FOURCC('G', 'R', 'B', 'G'), 116 | FOURCC_GBRG = FOURCC('G', 'B', 'R', 'G'), 117 | FOURCC_H264 = FOURCC('H', '2', '6', '4'), 118 | 119 | // Match any fourcc. 120 | FOURCC_ANY = -1, 121 | }; 122 | 123 | enum FourCCBpp { 124 | // Canonical fourcc codes used in our code. 125 | FOURCC_BPP_I420 = 12, 126 | FOURCC_BPP_I422 = 16, 127 | FOURCC_BPP_I444 = 24, 128 | FOURCC_BPP_I411 = 12, 129 | FOURCC_BPP_I400 = 8, 130 | FOURCC_BPP_NV21 = 12, 131 | FOURCC_BPP_NV12 = 12, 132 | FOURCC_BPP_YUY2 = 16, 133 | FOURCC_BPP_UYVY = 16, 134 | FOURCC_BPP_M420 = 12, 135 | FOURCC_BPP_Q420 = 12, 136 | FOURCC_BPP_ARGB = 32, 137 | FOURCC_BPP_BGRA = 32, 138 | FOURCC_BPP_ABGR = 32, 139 | FOURCC_BPP_RGBA = 32, 140 | FOURCC_BPP_AR30 = 32, 141 | FOURCC_BPP_AB30 = 32, 142 | FOURCC_BPP_24BG = 24, 143 | FOURCC_BPP_RAW = 24, 144 | FOURCC_BPP_RGBP = 16, 145 | FOURCC_BPP_RGBO = 16, 146 | FOURCC_BPP_R444 = 16, 147 | FOURCC_BPP_RGGB = 8, 148 | FOURCC_BPP_BGGR = 8, 149 | FOURCC_BPP_GRBG = 8, 150 | FOURCC_BPP_GBRG = 8, 151 | FOURCC_BPP_YV12 = 12, 152 | FOURCC_BPP_YV16 = 16, 153 | FOURCC_BPP_YV24 = 24, 154 | FOURCC_BPP_YU12 = 12, 155 | FOURCC_BPP_J420 = 12, 156 | FOURCC_BPP_J400 = 8, 157 | FOURCC_BPP_H420 = 12, 158 | FOURCC_BPP_H010 = 24, 159 | FOURCC_BPP_MJPG = 0, // 0 means unknown. 160 | FOURCC_BPP_H264 = 0, 161 | FOURCC_BPP_IYUV = 12, 162 | FOURCC_BPP_YU16 = 16, 163 | FOURCC_BPP_YU24 = 24, 164 | FOURCC_BPP_YUYV = 16, 165 | FOURCC_BPP_YUVS = 16, 166 | FOURCC_BPP_HDYC = 16, 167 | FOURCC_BPP_2VUY = 16, 168 | FOURCC_BPP_JPEG = 1, 169 | FOURCC_BPP_DMB1 = 1, 170 | FOURCC_BPP_BA81 = 8, 171 | FOURCC_BPP_RGB3 = 24, 172 | FOURCC_BPP_BGR3 = 24, 173 | FOURCC_BPP_CM32 = 32, 174 | FOURCC_BPP_CM24 = 24, 175 | 176 | // Match any fourcc. 177 | FOURCC_BPP_ANY = 0, // 0 means unknown. 178 | }; 179 | 180 | // Converts fourcc aliases into canonical ones. 181 | LIBYUV_API uint32_t CanonicalFourCC(uint32_t fourcc); 182 | 183 | #ifdef __cplusplus 184 | } // extern "C" 185 | } // namespace libyuv 186 | #endif 187 | 188 | #endif // INCLUDE_LIBYUV_VIDEO_COMMON_H_ 189 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/source/compare_common.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "libyuv/basic_types.h" 12 | 13 | #include "libyuv/compare_row.h" 14 | 15 | #ifdef __cplusplus 16 | namespace libyuv { 17 | extern "C" { 18 | #endif 19 | 20 | #if ORIGINAL_OPT 21 | uint32_t HammingDistance_C1(const uint8_t* src_a, 22 | const uint8_t* src_b, 23 | int count) { 24 | uint32_t diff = 0u; 25 | 26 | int i; 27 | for (i = 0; i < count; ++i) { 28 | int x = src_a[i] ^ src_b[i]; 29 | if (x & 1) 30 | ++diff; 31 | if (x & 2) 32 | ++diff; 33 | if (x & 4) 34 | ++diff; 35 | if (x & 8) 36 | ++diff; 37 | if (x & 16) 38 | ++diff; 39 | if (x & 32) 40 | ++diff; 41 | if (x & 64) 42 | ++diff; 43 | if (x & 128) 44 | ++diff; 45 | } 46 | return diff; 47 | } 48 | #endif 49 | 50 | // Hakmem method for hamming distance. 51 | uint32_t HammingDistance_C(const uint8_t* src_a, 52 | const uint8_t* src_b, 53 | int count) { 54 | uint32_t diff = 0u; 55 | 56 | int i; 57 | for (i = 0; i < count - 3; i += 4) { 58 | uint32_t x = *((const uint32_t*)src_a) ^ *((const uint32_t*)src_b); 59 | uint32_t u = x - ((x >> 1) & 0x55555555); 60 | u = ((u >> 2) & 0x33333333) + (u & 0x33333333); 61 | diff += ((((u + (u >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24); 62 | src_a += 4; 63 | src_b += 4; 64 | } 65 | 66 | for (; i < count; ++i) { 67 | uint32_t x = *src_a ^ *src_b; 68 | uint32_t u = x - ((x >> 1) & 0x55); 69 | u = ((u >> 2) & 0x33) + (u & 0x33); 70 | diff += (u + (u >> 4)) & 0x0f; 71 | src_a += 1; 72 | src_b += 1; 73 | } 74 | 75 | return diff; 76 | } 77 | 78 | uint32_t SumSquareError_C(const uint8_t* src_a, 79 | const uint8_t* src_b, 80 | int count) { 81 | uint32_t sse = 0u; 82 | int i; 83 | for (i = 0; i < count; ++i) { 84 | int diff = src_a[i] - src_b[i]; 85 | sse += (uint32_t)(diff * diff); 86 | } 87 | return sse; 88 | } 89 | 90 | // hash seed of 5381 recommended. 91 | // Internal C version of HashDjb2 with int sized count for efficiency. 92 | uint32_t HashDjb2_C(const uint8_t* src, int count, uint32_t seed) { 93 | uint32_t hash = seed; 94 | int i; 95 | for (i = 0; i < count; ++i) { 96 | hash += (hash << 5) + src[i]; 97 | } 98 | return hash; 99 | } 100 | 101 | #ifdef __cplusplus 102 | } // extern "C" 103 | } // namespace libyuv 104 | #endif 105 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/source/compare_msa.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "libyuv/basic_types.h" 12 | 13 | #include "libyuv/compare_row.h" 14 | #include "libyuv/row.h" 15 | 16 | // This module is for GCC MSA 17 | #if !defined(LIBYUV_DISABLE_MSA) && defined(__mips_msa) 18 | #include "libyuv/macros_msa.h" 19 | 20 | #ifdef __cplusplus 21 | namespace libyuv { 22 | extern "C" { 23 | #endif 24 | 25 | uint32_t HammingDistance_MSA(const uint8_t* src_a, 26 | const uint8_t* src_b, 27 | int count) { 28 | uint32_t diff = 0u; 29 | int i; 30 | v16u8 src0, src1, src2, src3; 31 | v2i64 vec0 = {0}, vec1 = {0}; 32 | 33 | for (i = 0; i < count; i += 32) { 34 | src0 = (v16u8)__msa_ld_b((v16i8*)src_a, 0); 35 | src1 = (v16u8)__msa_ld_b((v16i8*)src_a, 16); 36 | src2 = (v16u8)__msa_ld_b((v16i8*)src_b, 0); 37 | src3 = (v16u8)__msa_ld_b((v16i8*)src_b, 16); 38 | src0 ^= src2; 39 | src1 ^= src3; 40 | vec0 += __msa_pcnt_d((v2i64)src0); 41 | vec1 += __msa_pcnt_d((v2i64)src1); 42 | src_a += 32; 43 | src_b += 32; 44 | } 45 | 46 | vec0 += vec1; 47 | diff = (uint32_t)__msa_copy_u_w((v4i32)vec0, 0); 48 | diff += (uint32_t)__msa_copy_u_w((v4i32)vec0, 2); 49 | return diff; 50 | } 51 | 52 | uint32_t SumSquareError_MSA(const uint8_t* src_a, 53 | const uint8_t* src_b, 54 | int count) { 55 | uint32_t sse = 0u; 56 | int i; 57 | v16u8 src0, src1, src2, src3; 58 | v8i16 vec0, vec1, vec2, vec3; 59 | v4i32 reg0 = {0}, reg1 = {0}, reg2 = {0}, reg3 = {0}; 60 | v2i64 tmp0; 61 | 62 | for (i = 0; i < count; i += 32) { 63 | src0 = (v16u8)__msa_ld_b((v16i8*)src_a, 0); 64 | src1 = (v16u8)__msa_ld_b((v16i8*)src_a, 16); 65 | src2 = (v16u8)__msa_ld_b((v16i8*)src_b, 0); 66 | src3 = (v16u8)__msa_ld_b((v16i8*)src_b, 16); 67 | vec0 = (v8i16)__msa_ilvr_b((v16i8)src2, (v16i8)src0); 68 | vec1 = (v8i16)__msa_ilvl_b((v16i8)src2, (v16i8)src0); 69 | vec2 = (v8i16)__msa_ilvr_b((v16i8)src3, (v16i8)src1); 70 | vec3 = (v8i16)__msa_ilvl_b((v16i8)src3, (v16i8)src1); 71 | vec0 = __msa_hsub_u_h((v16u8)vec0, (v16u8)vec0); 72 | vec1 = __msa_hsub_u_h((v16u8)vec1, (v16u8)vec1); 73 | vec2 = __msa_hsub_u_h((v16u8)vec2, (v16u8)vec2); 74 | vec3 = __msa_hsub_u_h((v16u8)vec3, (v16u8)vec3); 75 | reg0 = __msa_dpadd_s_w(reg0, vec0, vec0); 76 | reg1 = __msa_dpadd_s_w(reg1, vec1, vec1); 77 | reg2 = __msa_dpadd_s_w(reg2, vec2, vec2); 78 | reg3 = __msa_dpadd_s_w(reg3, vec3, vec3); 79 | src_a += 32; 80 | src_b += 32; 81 | } 82 | 83 | reg0 += reg1; 84 | reg2 += reg3; 85 | reg0 += reg2; 86 | tmp0 = __msa_hadd_s_d(reg0, reg0); 87 | sse = (uint32_t)__msa_copy_u_w((v4i32)tmp0, 0); 88 | sse += (uint32_t)__msa_copy_u_w((v4i32)tmp0, 2); 89 | return sse; 90 | } 91 | 92 | #ifdef __cplusplus 93 | } // extern "C" 94 | } // namespace libyuv 95 | #endif 96 | 97 | #endif // !defined(LIBYUV_DISABLE_MSA) && defined(__mips_msa) 98 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/source/compare_neon.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "libyuv/basic_types.h" 12 | 13 | #include "libyuv/compare_row.h" 14 | #include "libyuv/row.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | #if !defined(LIBYUV_DISABLE_NEON) && defined(__ARM_NEON__) && \ 22 | !defined(__aarch64__) 23 | 24 | // 256 bits at a time 25 | // uses short accumulator which restricts count to 131 KB 26 | uint32_t HammingDistance_NEON(const uint8_t* src_a, 27 | const uint8_t* src_b, 28 | int count) { 29 | uint32_t diff; 30 | 31 | asm volatile( 32 | "vmov.u16 q4, #0 \n" // accumulator 33 | 34 | "1: \n" 35 | "vld1.8 {q0, q1}, [%0]! \n" 36 | "vld1.8 {q2, q3}, [%1]! \n" 37 | "veor.32 q0, q0, q2 \n" 38 | "veor.32 q1, q1, q3 \n" 39 | "vcnt.i8 q0, q0 \n" 40 | "vcnt.i8 q1, q1 \n" 41 | "subs %2, %2, #32 \n" 42 | "vadd.u8 q0, q0, q1 \n" // 16 byte counts 43 | "vpadal.u8 q4, q0 \n" // 8 shorts 44 | "bgt 1b \n" 45 | 46 | "vpaddl.u16 q0, q4 \n" // 4 ints 47 | "vpadd.u32 d0, d0, d1 \n" 48 | "vpadd.u32 d0, d0, d0 \n" 49 | "vmov.32 %3, d0[0] \n" 50 | 51 | : "+r"(src_a), "+r"(src_b), "+r"(count), "=r"(diff) 52 | : 53 | : "cc", "q0", "q1", "q2", "q3", "q4"); 54 | return diff; 55 | } 56 | 57 | uint32_t SumSquareError_NEON(const uint8_t* src_a, 58 | const uint8_t* src_b, 59 | int count) { 60 | uint32_t sse; 61 | asm volatile( 62 | "vmov.u8 q8, #0 \n" 63 | "vmov.u8 q10, #0 \n" 64 | "vmov.u8 q9, #0 \n" 65 | "vmov.u8 q11, #0 \n" 66 | 67 | "1: \n" 68 | "vld1.8 {q0}, [%0]! \n" 69 | "vld1.8 {q1}, [%1]! \n" 70 | "subs %2, %2, #16 \n" 71 | "vsubl.u8 q2, d0, d2 \n" 72 | "vsubl.u8 q3, d1, d3 \n" 73 | "vmlal.s16 q8, d4, d4 \n" 74 | "vmlal.s16 q9, d6, d6 \n" 75 | "vmlal.s16 q10, d5, d5 \n" 76 | "vmlal.s16 q11, d7, d7 \n" 77 | "bgt 1b \n" 78 | 79 | "vadd.u32 q8, q8, q9 \n" 80 | "vadd.u32 q10, q10, q11 \n" 81 | "vadd.u32 q11, q8, q10 \n" 82 | "vpaddl.u32 q1, q11 \n" 83 | "vadd.u64 d0, d2, d3 \n" 84 | "vmov.32 %3, d0[0] \n" 85 | : "+r"(src_a), "+r"(src_b), "+r"(count), "=r"(sse) 86 | : 87 | : "memory", "cc", "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11"); 88 | return sse; 89 | } 90 | 91 | #endif // defined(__ARM_NEON__) && !defined(__aarch64__) 92 | 93 | #ifdef __cplusplus 94 | } // extern "C" 95 | } // namespace libyuv 96 | #endif 97 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/source/compare_neon64.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "libyuv/basic_types.h" 12 | 13 | #include "libyuv/compare_row.h" 14 | #include "libyuv/row.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | #if !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__) 22 | 23 | // 256 bits at a time 24 | // uses short accumulator which restricts count to 131 KB 25 | uint32_t HammingDistance_NEON(const uint8_t* src_a, 26 | const uint8_t* src_b, 27 | int count) { 28 | uint32_t diff; 29 | asm volatile( 30 | "movi v4.8h, #0 \n" 31 | 32 | "1: \n" 33 | "ld1 {v0.16b, v1.16b}, [%0], #32 \n" 34 | "ld1 {v2.16b, v3.16b}, [%1], #32 \n" 35 | "eor v0.16b, v0.16b, v2.16b \n" 36 | "eor v1.16b, v1.16b, v3.16b \n" 37 | "cnt v0.16b, v0.16b \n" 38 | "cnt v1.16b, v1.16b \n" 39 | "subs %w2, %w2, #32 \n" 40 | "add v0.16b, v0.16b, v1.16b \n" 41 | "uadalp v4.8h, v0.16b \n" 42 | "b.gt 1b \n" 43 | 44 | "uaddlv s4, v4.8h \n" 45 | "fmov %w3, s4 \n" 46 | : "+r"(src_a), "+r"(src_b), "+r"(count), "=r"(diff) 47 | : 48 | : "cc", "v0", "v1", "v2", "v3", "v4"); 49 | return diff; 50 | } 51 | 52 | uint32_t SumSquareError_NEON(const uint8_t* src_a, 53 | const uint8_t* src_b, 54 | int count) { 55 | uint32_t sse; 56 | asm volatile( 57 | "eor v16.16b, v16.16b, v16.16b \n" 58 | "eor v18.16b, v18.16b, v18.16b \n" 59 | "eor v17.16b, v17.16b, v17.16b \n" 60 | "eor v19.16b, v19.16b, v19.16b \n" 61 | 62 | "1: \n" 63 | "ld1 {v0.16b}, [%0], #16 \n" 64 | "ld1 {v1.16b}, [%1], #16 \n" 65 | "subs %w2, %w2, #16 \n" 66 | "usubl v2.8h, v0.8b, v1.8b \n" 67 | "usubl2 v3.8h, v0.16b, v1.16b \n" 68 | "smlal v16.4s, v2.4h, v2.4h \n" 69 | "smlal v17.4s, v3.4h, v3.4h \n" 70 | "smlal2 v18.4s, v2.8h, v2.8h \n" 71 | "smlal2 v19.4s, v3.8h, v3.8h \n" 72 | "b.gt 1b \n" 73 | 74 | "add v16.4s, v16.4s, v17.4s \n" 75 | "add v18.4s, v18.4s, v19.4s \n" 76 | "add v19.4s, v16.4s, v18.4s \n" 77 | "addv s0, v19.4s \n" 78 | "fmov %w3, s0 \n" 79 | : "+r"(src_a), "+r"(src_b), "+r"(count), "=r"(sse) 80 | : 81 | : "cc", "v0", "v1", "v2", "v3", "v16", "v17", "v18", "v19"); 82 | return sse; 83 | } 84 | 85 | #endif // !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__) 86 | 87 | #ifdef __cplusplus 88 | } // extern "C" 89 | } // namespace libyuv 90 | #endif 91 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/source/compare_win.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "libyuv/basic_types.h" 12 | 13 | #include "libyuv/compare_row.h" 14 | #include "libyuv/row.h" 15 | 16 | #if defined(_MSC_VER) 17 | #include // For __popcnt 18 | #endif 19 | 20 | #ifdef __cplusplus 21 | namespace libyuv { 22 | extern "C" { 23 | #endif 24 | 25 | // This module is for 32 bit Visual C x86 and clangcl 26 | #if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER) 27 | 28 | uint32_t HammingDistance_SSE42(const uint8_t* src_a, 29 | const uint8_t* src_b, 30 | int count) { 31 | uint32_t diff = 0u; 32 | 33 | int i; 34 | for (i = 0; i < count - 3; i += 4) { 35 | uint32_t x = *((uint32_t*)src_a) ^ *((uint32_t*)src_b); // NOLINT 36 | src_a += 4; 37 | src_b += 4; 38 | diff += __popcnt(x); 39 | } 40 | return diff; 41 | } 42 | 43 | __declspec(naked) uint32_t 44 | SumSquareError_SSE2(const uint8_t* src_a, const uint8_t* src_b, int count) { 45 | __asm { 46 | mov eax, [esp + 4] // src_a 47 | mov edx, [esp + 8] // src_b 48 | mov ecx, [esp + 12] // count 49 | pxor xmm0, xmm0 50 | pxor xmm5, xmm5 51 | 52 | wloop: 53 | movdqu xmm1, [eax] 54 | lea eax, [eax + 16] 55 | movdqu xmm2, [edx] 56 | lea edx, [edx + 16] 57 | movdqa xmm3, xmm1 // abs trick 58 | psubusb xmm1, xmm2 59 | psubusb xmm2, xmm3 60 | por xmm1, xmm2 61 | movdqa xmm2, xmm1 62 | punpcklbw xmm1, xmm5 63 | punpckhbw xmm2, xmm5 64 | pmaddwd xmm1, xmm1 65 | pmaddwd xmm2, xmm2 66 | paddd xmm0, xmm1 67 | paddd xmm0, xmm2 68 | sub ecx, 16 69 | jg wloop 70 | 71 | pshufd xmm1, xmm0, 0xee 72 | paddd xmm0, xmm1 73 | pshufd xmm1, xmm0, 0x01 74 | paddd xmm0, xmm1 75 | movd eax, xmm0 76 | ret 77 | } 78 | } 79 | 80 | // Visual C 2012 required for AVX2. 81 | #if _MSC_VER >= 1700 82 | // C4752: found Intel(R) Advanced Vector Extensions; consider using /arch:AVX. 83 | #pragma warning(disable : 4752) 84 | __declspec(naked) uint32_t 85 | SumSquareError_AVX2(const uint8_t* src_a, const uint8_t* src_b, int count) { 86 | __asm { 87 | mov eax, [esp + 4] // src_a 88 | mov edx, [esp + 8] // src_b 89 | mov ecx, [esp + 12] // count 90 | vpxor ymm0, ymm0, ymm0 // sum 91 | vpxor ymm5, ymm5, ymm5 // constant 0 for unpck 92 | sub edx, eax 93 | 94 | wloop: 95 | vmovdqu ymm1, [eax] 96 | vmovdqu ymm2, [eax + edx] 97 | lea eax, [eax + 32] 98 | vpsubusb ymm3, ymm1, ymm2 // abs difference trick 99 | vpsubusb ymm2, ymm2, ymm1 100 | vpor ymm1, ymm2, ymm3 101 | vpunpcklbw ymm2, ymm1, ymm5 // u16. mutates order. 102 | vpunpckhbw ymm1, ymm1, ymm5 103 | vpmaddwd ymm2, ymm2, ymm2 // square + hadd to u32. 104 | vpmaddwd ymm1, ymm1, ymm1 105 | vpaddd ymm0, ymm0, ymm1 106 | vpaddd ymm0, ymm0, ymm2 107 | sub ecx, 32 108 | jg wloop 109 | 110 | vpshufd ymm1, ymm0, 0xee // 3, 2 + 1, 0 both lanes. 111 | vpaddd ymm0, ymm0, ymm1 112 | vpshufd ymm1, ymm0, 0x01 // 1 + 0 both lanes. 113 | vpaddd ymm0, ymm0, ymm1 114 | vpermq ymm1, ymm0, 0x02 // high + low lane. 115 | vpaddd ymm0, ymm0, ymm1 116 | vmovd eax, xmm0 117 | vzeroupper 118 | ret 119 | } 120 | } 121 | #endif // _MSC_VER >= 1700 122 | 123 | uvec32 kHash16x33 = {0x92d9e201, 0, 0, 0}; // 33 ^ 16 124 | uvec32 kHashMul0 = { 125 | 0x0c3525e1, // 33 ^ 15 126 | 0xa3476dc1, // 33 ^ 14 127 | 0x3b4039a1, // 33 ^ 13 128 | 0x4f5f0981, // 33 ^ 12 129 | }; 130 | uvec32 kHashMul1 = { 131 | 0x30f35d61, // 33 ^ 11 132 | 0x855cb541, // 33 ^ 10 133 | 0x040a9121, // 33 ^ 9 134 | 0x747c7101, // 33 ^ 8 135 | }; 136 | uvec32 kHashMul2 = { 137 | 0xec41d4e1, // 33 ^ 7 138 | 0x4cfa3cc1, // 33 ^ 6 139 | 0x025528a1, // 33 ^ 5 140 | 0x00121881, // 33 ^ 4 141 | }; 142 | uvec32 kHashMul3 = { 143 | 0x00008c61, // 33 ^ 3 144 | 0x00000441, // 33 ^ 2 145 | 0x00000021, // 33 ^ 1 146 | 0x00000001, // 33 ^ 0 147 | }; 148 | 149 | __declspec(naked) uint32_t 150 | HashDjb2_SSE41(const uint8_t* src, int count, uint32_t seed) { 151 | __asm { 152 | mov eax, [esp + 4] // src 153 | mov ecx, [esp + 8] // count 154 | movd xmm0, [esp + 12] // seed 155 | 156 | pxor xmm7, xmm7 // constant 0 for unpck 157 | movdqa xmm6, xmmword ptr kHash16x33 158 | 159 | wloop: 160 | movdqu xmm1, [eax] // src[0-15] 161 | lea eax, [eax + 16] 162 | pmulld xmm0, xmm6 // hash *= 33 ^ 16 163 | movdqa xmm5, xmmword ptr kHashMul0 164 | movdqa xmm2, xmm1 165 | punpcklbw xmm2, xmm7 // src[0-7] 166 | movdqa xmm3, xmm2 167 | punpcklwd xmm3, xmm7 // src[0-3] 168 | pmulld xmm3, xmm5 169 | movdqa xmm5, xmmword ptr kHashMul1 170 | movdqa xmm4, xmm2 171 | punpckhwd xmm4, xmm7 // src[4-7] 172 | pmulld xmm4, xmm5 173 | movdqa xmm5, xmmword ptr kHashMul2 174 | punpckhbw xmm1, xmm7 // src[8-15] 175 | movdqa xmm2, xmm1 176 | punpcklwd xmm2, xmm7 // src[8-11] 177 | pmulld xmm2, xmm5 178 | movdqa xmm5, xmmword ptr kHashMul3 179 | punpckhwd xmm1, xmm7 // src[12-15] 180 | pmulld xmm1, xmm5 181 | paddd xmm3, xmm4 // add 16 results 182 | paddd xmm1, xmm2 183 | paddd xmm1, xmm3 184 | 185 | pshufd xmm2, xmm1, 0x0e // upper 2 dwords 186 | paddd xmm1, xmm2 187 | pshufd xmm2, xmm1, 0x01 188 | paddd xmm1, xmm2 189 | paddd xmm0, xmm1 190 | sub ecx, 16 191 | jg wloop 192 | 193 | movd eax, xmm0 // return hash 194 | ret 195 | } 196 | } 197 | 198 | // Visual C 2012 required for AVX2. 199 | #if _MSC_VER >= 1700 200 | __declspec(naked) uint32_t 201 | HashDjb2_AVX2(const uint8_t* src, int count, uint32_t seed) { 202 | __asm { 203 | mov eax, [esp + 4] // src 204 | mov ecx, [esp + 8] // count 205 | vmovd xmm0, [esp + 12] // seed 206 | 207 | wloop: 208 | vpmovzxbd xmm3, [eax] // src[0-3] 209 | vpmulld xmm0, xmm0, xmmword ptr kHash16x33 // hash *= 33 ^ 16 210 | vpmovzxbd xmm4, [eax + 4] // src[4-7] 211 | vpmulld xmm3, xmm3, xmmword ptr kHashMul0 212 | vpmovzxbd xmm2, [eax + 8] // src[8-11] 213 | vpmulld xmm4, xmm4, xmmword ptr kHashMul1 214 | vpmovzxbd xmm1, [eax + 12] // src[12-15] 215 | vpmulld xmm2, xmm2, xmmword ptr kHashMul2 216 | lea eax, [eax + 16] 217 | vpmulld xmm1, xmm1, xmmword ptr kHashMul3 218 | vpaddd xmm3, xmm3, xmm4 // add 16 results 219 | vpaddd xmm1, xmm1, xmm2 220 | vpaddd xmm1, xmm1, xmm3 221 | vpshufd xmm2, xmm1, 0x0e // upper 2 dwords 222 | vpaddd xmm1, xmm1,xmm2 223 | vpshufd xmm2, xmm1, 0x01 224 | vpaddd xmm1, xmm1, xmm2 225 | vpaddd xmm0, xmm0, xmm1 226 | sub ecx, 16 227 | jg wloop 228 | 229 | vmovd eax, xmm0 // return hash 230 | vzeroupper 231 | ret 232 | } 233 | } 234 | #endif // _MSC_VER >= 1700 235 | 236 | #endif // !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) 237 | 238 | #ifdef __cplusplus 239 | } // extern "C" 240 | } // namespace libyuv 241 | #endif 242 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/source/mjpeg_validate.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "libyuv/mjpeg_decoder.h" 12 | 13 | #include // For memchr. 14 | 15 | #ifdef __cplusplus 16 | namespace libyuv { 17 | extern "C" { 18 | #endif 19 | 20 | // Helper function to scan for EOI marker (0xff 0xd9). 21 | static LIBYUV_BOOL ScanEOI(const uint8_t* sample, size_t sample_size) { 22 | if (sample_size >= 2) { 23 | const uint8_t* end = sample + sample_size - 1; 24 | const uint8_t* it = sample; 25 | while (it < end) { 26 | // TODO(fbarchard): scan for 0xd9 instead. 27 | it = (const uint8_t*)(memchr(it, 0xff, end - it)); 28 | if (it == NULL) { 29 | break; 30 | } 31 | if (it[1] == 0xd9) { 32 | return LIBYUV_TRUE; // Success: Valid jpeg. 33 | } 34 | ++it; // Skip over current 0xff. 35 | } 36 | } 37 | // ERROR: Invalid jpeg end code not found. Size sample_size 38 | return LIBYUV_FALSE; 39 | } 40 | 41 | // Helper function to validate the jpeg appears intact. 42 | LIBYUV_BOOL ValidateJpeg(const uint8_t* sample, size_t sample_size) { 43 | // Maximum size that ValidateJpeg will consider valid. 44 | const size_t kMaxJpegSize = 0x7fffffffull; 45 | const size_t kBackSearchSize = 1024; 46 | if (sample_size < 64 || sample_size > kMaxJpegSize || !sample) { 47 | // ERROR: Invalid jpeg size: sample_size 48 | return LIBYUV_FALSE; 49 | } 50 | if (sample[0] != 0xff || sample[1] != 0xd8) { // SOI marker 51 | // ERROR: Invalid jpeg initial start code 52 | return LIBYUV_FALSE; 53 | } 54 | 55 | // Look for the End Of Image (EOI) marker near the end of the buffer. 56 | if (sample_size > kBackSearchSize) { 57 | if (ScanEOI(sample + sample_size - kBackSearchSize, kBackSearchSize)) { 58 | return LIBYUV_TRUE; // Success: Valid jpeg. 59 | } 60 | // Reduce search size for forward search. 61 | sample_size = sample_size - kBackSearchSize + 1; 62 | } 63 | // Step over SOI marker and scan for EOI. 64 | return ScanEOI(sample + 2, sample_size - 2); 65 | } 66 | 67 | #ifdef __cplusplus 68 | } // extern "C" 69 | } // namespace libyuv 70 | #endif 71 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/source/rotate_any.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "libyuv/rotate.h" 12 | #include "libyuv/rotate_row.h" 13 | 14 | #include "libyuv/basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | #define TANY(NAMEANY, TPOS_SIMD, MASK) \ 22 | void NAMEANY(const uint8_t* src, int src_stride, uint8_t* dst, \ 23 | int dst_stride, int width) { \ 24 | int r = width & MASK; \ 25 | int n = width - r; \ 26 | if (n > 0) { \ 27 | TPOS_SIMD(src, src_stride, dst, dst_stride, n); \ 28 | } \ 29 | TransposeWx8_C(src + n, src_stride, dst + n * dst_stride, dst_stride, r); \ 30 | } 31 | 32 | #ifdef HAS_TRANSPOSEWX8_NEON 33 | TANY(TransposeWx8_Any_NEON, TransposeWx8_NEON, 7) 34 | #endif 35 | #ifdef HAS_TRANSPOSEWX8_SSSE3 36 | TANY(TransposeWx8_Any_SSSE3, TransposeWx8_SSSE3, 7) 37 | #endif 38 | #ifdef HAS_TRANSPOSEWX8_FAST_SSSE3 39 | TANY(TransposeWx8_Fast_Any_SSSE3, TransposeWx8_Fast_SSSE3, 15) 40 | #endif 41 | #ifdef HAS_TRANSPOSEWX16_MSA 42 | TANY(TransposeWx16_Any_MSA, TransposeWx16_MSA, 15) 43 | #endif 44 | #undef TANY 45 | 46 | #define TUVANY(NAMEANY, TPOS_SIMD, MASK) \ 47 | void NAMEANY(const uint8_t* src, int src_stride, uint8_t* dst_a, \ 48 | int dst_stride_a, uint8_t* dst_b, int dst_stride_b, \ 49 | int width) { \ 50 | int r = width & MASK; \ 51 | int n = width - r; \ 52 | if (n > 0) { \ 53 | TPOS_SIMD(src, src_stride, dst_a, dst_stride_a, dst_b, dst_stride_b, n); \ 54 | } \ 55 | TransposeUVWx8_C(src + n * 2, src_stride, dst_a + n * dst_stride_a, \ 56 | dst_stride_a, dst_b + n * dst_stride_b, dst_stride_b, r); \ 57 | } 58 | 59 | #ifdef HAS_TRANSPOSEUVWX8_NEON 60 | TUVANY(TransposeUVWx8_Any_NEON, TransposeUVWx8_NEON, 7) 61 | #endif 62 | #ifdef HAS_TRANSPOSEUVWX8_SSE2 63 | TUVANY(TransposeUVWx8_Any_SSE2, TransposeUVWx8_SSE2, 7) 64 | #endif 65 | #ifdef HAS_TRANSPOSEUVWX16_MSA 66 | TUVANY(TransposeUVWx16_Any_MSA, TransposeUVWx16_MSA, 7) 67 | #endif 68 | #undef TUVANY 69 | 70 | #ifdef __cplusplus 71 | } // extern "C" 72 | } // namespace libyuv 73 | #endif 74 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/source/rotate_argb.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "libyuv/rotate.h" 12 | 13 | #include "libyuv/convert.h" 14 | #include "libyuv/cpu_id.h" 15 | #include "libyuv/planar_functions.h" 16 | #include "libyuv/row.h" 17 | #include "libyuv/scale_row.h" /* for ScaleARGBRowDownEven_ */ 18 | 19 | #ifdef __cplusplus 20 | namespace libyuv { 21 | extern "C" { 22 | #endif 23 | 24 | static void ARGBTranspose(const uint8_t* src_argb, 25 | int src_stride_argb, 26 | uint8_t* dst_argb, 27 | int dst_stride_argb, 28 | int width, 29 | int height) { 30 | int i; 31 | int src_pixel_step = src_stride_argb >> 2; 32 | void (*ScaleARGBRowDownEven)( 33 | const uint8_t* src_argb, ptrdiff_t src_stride_argb, int src_step, 34 | uint8_t* dst_argb, int dst_width) = ScaleARGBRowDownEven_C; 35 | #if defined(HAS_SCALEARGBROWDOWNEVEN_SSE2) 36 | if (TestCpuFlag(kCpuHasSSE2)) { 37 | ScaleARGBRowDownEven = ScaleARGBRowDownEven_Any_SSE2; 38 | if (IS_ALIGNED(height, 4)) { // Width of dest. 39 | ScaleARGBRowDownEven = ScaleARGBRowDownEven_SSE2; 40 | } 41 | } 42 | #endif 43 | #if defined(HAS_SCALEARGBROWDOWNEVEN_NEON) 44 | if (TestCpuFlag(kCpuHasNEON)) { 45 | ScaleARGBRowDownEven = ScaleARGBRowDownEven_Any_NEON; 46 | if (IS_ALIGNED(height, 4)) { // Width of dest. 47 | ScaleARGBRowDownEven = ScaleARGBRowDownEven_NEON; 48 | } 49 | } 50 | #endif 51 | #if defined(HAS_SCALEARGBROWDOWNEVEN_MSA) 52 | if (TestCpuFlag(kCpuHasMSA)) { 53 | ScaleARGBRowDownEven = ScaleARGBRowDownEven_Any_MSA; 54 | if (IS_ALIGNED(height, 4)) { // Width of dest. 55 | ScaleARGBRowDownEven = ScaleARGBRowDownEven_MSA; 56 | } 57 | } 58 | #endif 59 | 60 | for (i = 0; i < width; ++i) { // column of source to row of dest. 61 | ScaleARGBRowDownEven(src_argb, 0, src_pixel_step, dst_argb, height); 62 | dst_argb += dst_stride_argb; 63 | src_argb += 4; 64 | } 65 | } 66 | 67 | void ARGBRotate90(const uint8_t* src_argb, 68 | int src_stride_argb, 69 | uint8_t* dst_argb, 70 | int dst_stride_argb, 71 | int width, 72 | int height) { 73 | // Rotate by 90 is a ARGBTranspose with the source read 74 | // from bottom to top. So set the source pointer to the end 75 | // of the buffer and flip the sign of the source stride. 76 | src_argb += src_stride_argb * (height - 1); 77 | src_stride_argb = -src_stride_argb; 78 | ARGBTranspose(src_argb, src_stride_argb, dst_argb, dst_stride_argb, width, 79 | height); 80 | } 81 | 82 | void ARGBRotate270(const uint8_t* src_argb, 83 | int src_stride_argb, 84 | uint8_t* dst_argb, 85 | int dst_stride_argb, 86 | int width, 87 | int height) { 88 | // Rotate by 270 is a ARGBTranspose with the destination written 89 | // from bottom to top. So set the destination pointer to the end 90 | // of the buffer and flip the sign of the destination stride. 91 | dst_argb += dst_stride_argb * (width - 1); 92 | dst_stride_argb = -dst_stride_argb; 93 | ARGBTranspose(src_argb, src_stride_argb, dst_argb, dst_stride_argb, width, 94 | height); 95 | } 96 | 97 | void ARGBRotate180(const uint8_t* src_argb, 98 | int src_stride_argb, 99 | uint8_t* dst_argb, 100 | int dst_stride_argb, 101 | int width, 102 | int height) { 103 | // Swap first and last row and mirror the content. Uses a temporary row. 104 | align_buffer_64(row, width * 4); 105 | const uint8_t* src_bot = src_argb + src_stride_argb * (height - 1); 106 | uint8_t* dst_bot = dst_argb + dst_stride_argb * (height - 1); 107 | int half_height = (height + 1) >> 1; 108 | int y; 109 | void (*ARGBMirrorRow)(const uint8_t* src_argb, uint8_t* dst_argb, int width) = 110 | ARGBMirrorRow_C; 111 | void (*CopyRow)(const uint8_t* src_argb, uint8_t* dst_argb, int width) = 112 | CopyRow_C; 113 | #if defined(HAS_ARGBMIRRORROW_NEON) 114 | if (TestCpuFlag(kCpuHasNEON)) { 115 | ARGBMirrorRow = ARGBMirrorRow_Any_NEON; 116 | if (IS_ALIGNED(width, 4)) { 117 | ARGBMirrorRow = ARGBMirrorRow_NEON; 118 | } 119 | } 120 | #endif 121 | #if defined(HAS_ARGBMIRRORROW_SSE2) 122 | if (TestCpuFlag(kCpuHasSSE2)) { 123 | ARGBMirrorRow = ARGBMirrorRow_Any_SSE2; 124 | if (IS_ALIGNED(width, 4)) { 125 | ARGBMirrorRow = ARGBMirrorRow_SSE2; 126 | } 127 | } 128 | #endif 129 | #if defined(HAS_ARGBMIRRORROW_AVX2) 130 | if (TestCpuFlag(kCpuHasAVX2)) { 131 | ARGBMirrorRow = ARGBMirrorRow_Any_AVX2; 132 | if (IS_ALIGNED(width, 8)) { 133 | ARGBMirrorRow = ARGBMirrorRow_AVX2; 134 | } 135 | } 136 | #endif 137 | #if defined(HAS_ARGBMIRRORROW_MSA) 138 | if (TestCpuFlag(kCpuHasMSA)) { 139 | ARGBMirrorRow = ARGBMirrorRow_Any_MSA; 140 | if (IS_ALIGNED(width, 16)) { 141 | ARGBMirrorRow = ARGBMirrorRow_MSA; 142 | } 143 | } 144 | #endif 145 | #if defined(HAS_COPYROW_SSE2) 146 | if (TestCpuFlag(kCpuHasSSE2)) { 147 | CopyRow = IS_ALIGNED(width * 4, 32) ? CopyRow_SSE2 : CopyRow_Any_SSE2; 148 | } 149 | #endif 150 | #if defined(HAS_COPYROW_AVX) 151 | if (TestCpuFlag(kCpuHasAVX)) { 152 | CopyRow = IS_ALIGNED(width * 4, 64) ? CopyRow_AVX : CopyRow_Any_AVX; 153 | } 154 | #endif 155 | #if defined(HAS_COPYROW_ERMS) 156 | if (TestCpuFlag(kCpuHasERMS)) { 157 | CopyRow = CopyRow_ERMS; 158 | } 159 | #endif 160 | #if defined(HAS_COPYROW_NEON) 161 | if (TestCpuFlag(kCpuHasNEON)) { 162 | CopyRow = IS_ALIGNED(width * 4, 32) ? CopyRow_NEON : CopyRow_Any_NEON; 163 | } 164 | #endif 165 | 166 | // Odd height will harmlessly mirror the middle row twice. 167 | for (y = 0; y < half_height; ++y) { 168 | ARGBMirrorRow(src_argb, row, width); // Mirror first row into a buffer 169 | ARGBMirrorRow(src_bot, dst_argb, width); // Mirror last row into first row 170 | CopyRow(row, dst_bot, width * 4); // Copy first mirrored row into last 171 | src_argb += src_stride_argb; 172 | dst_argb += dst_stride_argb; 173 | src_bot -= src_stride_argb; 174 | dst_bot -= dst_stride_argb; 175 | } 176 | free_aligned_buffer_64(row); 177 | } 178 | 179 | LIBYUV_API 180 | int ARGBRotate(const uint8_t* src_argb, 181 | int src_stride_argb, 182 | uint8_t* dst_argb, 183 | int dst_stride_argb, 184 | int width, 185 | int height, 186 | enum RotationMode mode) { 187 | if (!src_argb || width <= 0 || height == 0 || !dst_argb) { 188 | return -1; 189 | } 190 | 191 | // Negative height means invert the image. 192 | if (height < 0) { 193 | height = -height; 194 | src_argb = src_argb + (height - 1) * src_stride_argb; 195 | src_stride_argb = -src_stride_argb; 196 | } 197 | 198 | switch (mode) { 199 | case kRotate0: 200 | // copy frame 201 | return ARGBCopy(src_argb, src_stride_argb, dst_argb, dst_stride_argb, 202 | width, height); 203 | case kRotate90: 204 | ARGBRotate90(src_argb, src_stride_argb, dst_argb, dst_stride_argb, width, 205 | height); 206 | return 0; 207 | case kRotate270: 208 | ARGBRotate270(src_argb, src_stride_argb, dst_argb, dst_stride_argb, width, 209 | height); 210 | return 0; 211 | case kRotate180: 212 | ARGBRotate180(src_argb, src_stride_argb, dst_argb, dst_stride_argb, width, 213 | height); 214 | return 0; 215 | default: 216 | break; 217 | } 218 | return -1; 219 | } 220 | 221 | #ifdef __cplusplus 222 | } // extern "C" 223 | } // namespace libyuv 224 | #endif 225 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/source/rotate_common.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "libyuv/rotate_row.h" 12 | #include "libyuv/row.h" 13 | 14 | #ifdef __cplusplus 15 | namespace libyuv { 16 | extern "C" { 17 | #endif 18 | 19 | void TransposeWx8_C(const uint8_t* src, 20 | int src_stride, 21 | uint8_t* dst, 22 | int dst_stride, 23 | int width) { 24 | int i; 25 | for (i = 0; i < width; ++i) { 26 | dst[0] = src[0 * src_stride]; 27 | dst[1] = src[1 * src_stride]; 28 | dst[2] = src[2 * src_stride]; 29 | dst[3] = src[3 * src_stride]; 30 | dst[4] = src[4 * src_stride]; 31 | dst[5] = src[5 * src_stride]; 32 | dst[6] = src[6 * src_stride]; 33 | dst[7] = src[7 * src_stride]; 34 | ++src; 35 | dst += dst_stride; 36 | } 37 | } 38 | 39 | void TransposeUVWx8_C(const uint8_t* src, 40 | int src_stride, 41 | uint8_t* dst_a, 42 | int dst_stride_a, 43 | uint8_t* dst_b, 44 | int dst_stride_b, 45 | int width) { 46 | int i; 47 | for (i = 0; i < width; ++i) { 48 | dst_a[0] = src[0 * src_stride + 0]; 49 | dst_b[0] = src[0 * src_stride + 1]; 50 | dst_a[1] = src[1 * src_stride + 0]; 51 | dst_b[1] = src[1 * src_stride + 1]; 52 | dst_a[2] = src[2 * src_stride + 0]; 53 | dst_b[2] = src[2 * src_stride + 1]; 54 | dst_a[3] = src[3 * src_stride + 0]; 55 | dst_b[3] = src[3 * src_stride + 1]; 56 | dst_a[4] = src[4 * src_stride + 0]; 57 | dst_b[4] = src[4 * src_stride + 1]; 58 | dst_a[5] = src[5 * src_stride + 0]; 59 | dst_b[5] = src[5 * src_stride + 1]; 60 | dst_a[6] = src[6 * src_stride + 0]; 61 | dst_b[6] = src[6 * src_stride + 1]; 62 | dst_a[7] = src[7 * src_stride + 0]; 63 | dst_b[7] = src[7 * src_stride + 1]; 64 | src += 2; 65 | dst_a += dst_stride_a; 66 | dst_b += dst_stride_b; 67 | } 68 | } 69 | 70 | void TransposeWxH_C(const uint8_t* src, 71 | int src_stride, 72 | uint8_t* dst, 73 | int dst_stride, 74 | int width, 75 | int height) { 76 | int i; 77 | for (i = 0; i < width; ++i) { 78 | int j; 79 | for (j = 0; j < height; ++j) { 80 | dst[i * dst_stride + j] = src[j * src_stride + i]; 81 | } 82 | } 83 | } 84 | 85 | void TransposeUVWxH_C(const uint8_t* src, 86 | int src_stride, 87 | uint8_t* dst_a, 88 | int dst_stride_a, 89 | uint8_t* dst_b, 90 | int dst_stride_b, 91 | int width, 92 | int height) { 93 | int i; 94 | for (i = 0; i < width * 2; i += 2) { 95 | int j; 96 | for (j = 0; j < height; ++j) { 97 | dst_a[j + ((i >> 1) * dst_stride_a)] = src[i + (j * src_stride)]; 98 | dst_b[j + ((i >> 1) * dst_stride_b)] = src[i + (j * src_stride) + 1]; 99 | } 100 | } 101 | } 102 | 103 | #ifdef __cplusplus 104 | } // extern "C" 105 | } // namespace libyuv 106 | #endif 107 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/source/rotate_win.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "libyuv/rotate_row.h" 12 | #include "libyuv/row.h" 13 | 14 | #ifdef __cplusplus 15 | namespace libyuv { 16 | extern "C" { 17 | #endif 18 | 19 | // This module is for 32 bit Visual C x86 and clangcl 20 | #if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER) 21 | 22 | __declspec(naked) void TransposeWx8_SSSE3(const uint8_t* src, 23 | int src_stride, 24 | uint8_t* dst, 25 | int dst_stride, 26 | int width) { 27 | __asm { 28 | push edi 29 | push esi 30 | push ebp 31 | mov eax, [esp + 12 + 4] // src 32 | mov edi, [esp + 12 + 8] // src_stride 33 | mov edx, [esp + 12 + 12] // dst 34 | mov esi, [esp + 12 + 16] // dst_stride 35 | mov ecx, [esp + 12 + 20] // width 36 | 37 | // Read in the data from the source pointer. 38 | // First round of bit swap. 39 | align 4 40 | convertloop: 41 | movq xmm0, qword ptr [eax] 42 | lea ebp, [eax + 8] 43 | movq xmm1, qword ptr [eax + edi] 44 | lea eax, [eax + 2 * edi] 45 | punpcklbw xmm0, xmm1 46 | movq xmm2, qword ptr [eax] 47 | movdqa xmm1, xmm0 48 | palignr xmm1, xmm1, 8 49 | movq xmm3, qword ptr [eax + edi] 50 | lea eax, [eax + 2 * edi] 51 | punpcklbw xmm2, xmm3 52 | movdqa xmm3, xmm2 53 | movq xmm4, qword ptr [eax] 54 | palignr xmm3, xmm3, 8 55 | movq xmm5, qword ptr [eax + edi] 56 | punpcklbw xmm4, xmm5 57 | lea eax, [eax + 2 * edi] 58 | movdqa xmm5, xmm4 59 | movq xmm6, qword ptr [eax] 60 | palignr xmm5, xmm5, 8 61 | movq xmm7, qword ptr [eax + edi] 62 | punpcklbw xmm6, xmm7 63 | mov eax, ebp 64 | movdqa xmm7, xmm6 65 | palignr xmm7, xmm7, 8 66 | // Second round of bit swap. 67 | punpcklwd xmm0, xmm2 68 | punpcklwd xmm1, xmm3 69 | movdqa xmm2, xmm0 70 | movdqa xmm3, xmm1 71 | palignr xmm2, xmm2, 8 72 | palignr xmm3, xmm3, 8 73 | punpcklwd xmm4, xmm6 74 | punpcklwd xmm5, xmm7 75 | movdqa xmm6, xmm4 76 | movdqa xmm7, xmm5 77 | palignr xmm6, xmm6, 8 78 | palignr xmm7, xmm7, 8 79 | // Third round of bit swap. 80 | // Write to the destination pointer. 81 | punpckldq xmm0, xmm4 82 | movq qword ptr [edx], xmm0 83 | movdqa xmm4, xmm0 84 | palignr xmm4, xmm4, 8 85 | movq qword ptr [edx + esi], xmm4 86 | lea edx, [edx + 2 * esi] 87 | punpckldq xmm2, xmm6 88 | movdqa xmm6, xmm2 89 | palignr xmm6, xmm6, 8 90 | movq qword ptr [edx], xmm2 91 | punpckldq xmm1, xmm5 92 | movq qword ptr [edx + esi], xmm6 93 | lea edx, [edx + 2 * esi] 94 | movdqa xmm5, xmm1 95 | movq qword ptr [edx], xmm1 96 | palignr xmm5, xmm5, 8 97 | punpckldq xmm3, xmm7 98 | movq qword ptr [edx + esi], xmm5 99 | lea edx, [edx + 2 * esi] 100 | movq qword ptr [edx], xmm3 101 | movdqa xmm7, xmm3 102 | palignr xmm7, xmm7, 8 103 | sub ecx, 8 104 | movq qword ptr [edx + esi], xmm7 105 | lea edx, [edx + 2 * esi] 106 | jg convertloop 107 | 108 | pop ebp 109 | pop esi 110 | pop edi 111 | ret 112 | } 113 | } 114 | 115 | __declspec(naked) void TransposeUVWx8_SSE2(const uint8_t* src, 116 | int src_stride, 117 | uint8_t* dst_a, 118 | int dst_stride_a, 119 | uint8_t* dst_b, 120 | int dst_stride_b, 121 | int w) { 122 | __asm { 123 | push ebx 124 | push esi 125 | push edi 126 | push ebp 127 | mov eax, [esp + 16 + 4] // src 128 | mov edi, [esp + 16 + 8] // src_stride 129 | mov edx, [esp + 16 + 12] // dst_a 130 | mov esi, [esp + 16 + 16] // dst_stride_a 131 | mov ebx, [esp + 16 + 20] // dst_b 132 | mov ebp, [esp + 16 + 24] // dst_stride_b 133 | mov ecx, esp 134 | sub esp, 4 + 16 135 | and esp, ~15 136 | mov [esp + 16], ecx 137 | mov ecx, [ecx + 16 + 28] // w 138 | 139 | align 4 140 | // Read in the data from the source pointer. 141 | // First round of bit swap. 142 | convertloop: 143 | movdqu xmm0, [eax] 144 | movdqu xmm1, [eax + edi] 145 | lea eax, [eax + 2 * edi] 146 | movdqa xmm7, xmm0 // use xmm7 as temp register. 147 | punpcklbw xmm0, xmm1 148 | punpckhbw xmm7, xmm1 149 | movdqa xmm1, xmm7 150 | movdqu xmm2, [eax] 151 | movdqu xmm3, [eax + edi] 152 | lea eax, [eax + 2 * edi] 153 | movdqa xmm7, xmm2 154 | punpcklbw xmm2, xmm3 155 | punpckhbw xmm7, xmm3 156 | movdqa xmm3, xmm7 157 | movdqu xmm4, [eax] 158 | movdqu xmm5, [eax + edi] 159 | lea eax, [eax + 2 * edi] 160 | movdqa xmm7, xmm4 161 | punpcklbw xmm4, xmm5 162 | punpckhbw xmm7, xmm5 163 | movdqa xmm5, xmm7 164 | movdqu xmm6, [eax] 165 | movdqu xmm7, [eax + edi] 166 | lea eax, [eax + 2 * edi] 167 | movdqu [esp], xmm5 // backup xmm5 168 | neg edi 169 | movdqa xmm5, xmm6 // use xmm5 as temp register. 170 | punpcklbw xmm6, xmm7 171 | punpckhbw xmm5, xmm7 172 | movdqa xmm7, xmm5 173 | lea eax, [eax + 8 * edi + 16] 174 | neg edi 175 | // Second round of bit swap. 176 | movdqa xmm5, xmm0 177 | punpcklwd xmm0, xmm2 178 | punpckhwd xmm5, xmm2 179 | movdqa xmm2, xmm5 180 | movdqa xmm5, xmm1 181 | punpcklwd xmm1, xmm3 182 | punpckhwd xmm5, xmm3 183 | movdqa xmm3, xmm5 184 | movdqa xmm5, xmm4 185 | punpcklwd xmm4, xmm6 186 | punpckhwd xmm5, xmm6 187 | movdqa xmm6, xmm5 188 | movdqu xmm5, [esp] // restore xmm5 189 | movdqu [esp], xmm6 // backup xmm6 190 | movdqa xmm6, xmm5 // use xmm6 as temp register. 191 | punpcklwd xmm5, xmm7 192 | punpckhwd xmm6, xmm7 193 | movdqa xmm7, xmm6 194 | 195 | // Third round of bit swap. 196 | // Write to the destination pointer. 197 | movdqa xmm6, xmm0 198 | punpckldq xmm0, xmm4 199 | punpckhdq xmm6, xmm4 200 | movdqa xmm4, xmm6 201 | movdqu xmm6, [esp] // restore xmm6 202 | movlpd qword ptr [edx], xmm0 203 | movhpd qword ptr [ebx], xmm0 204 | movlpd qword ptr [edx + esi], xmm4 205 | lea edx, [edx + 2 * esi] 206 | movhpd qword ptr [ebx + ebp], xmm4 207 | lea ebx, [ebx + 2 * ebp] 208 | movdqa xmm0, xmm2 // use xmm0 as the temp register. 209 | punpckldq xmm2, xmm6 210 | movlpd qword ptr [edx], xmm2 211 | movhpd qword ptr [ebx], xmm2 212 | punpckhdq xmm0, xmm6 213 | movlpd qword ptr [edx + esi], xmm0 214 | lea edx, [edx + 2 * esi] 215 | movhpd qword ptr [ebx + ebp], xmm0 216 | lea ebx, [ebx + 2 * ebp] 217 | movdqa xmm0, xmm1 // use xmm0 as the temp register. 218 | punpckldq xmm1, xmm5 219 | movlpd qword ptr [edx], xmm1 220 | movhpd qword ptr [ebx], xmm1 221 | punpckhdq xmm0, xmm5 222 | movlpd qword ptr [edx + esi], xmm0 223 | lea edx, [edx + 2 * esi] 224 | movhpd qword ptr [ebx + ebp], xmm0 225 | lea ebx, [ebx + 2 * ebp] 226 | movdqa xmm0, xmm3 // use xmm0 as the temp register. 227 | punpckldq xmm3, xmm7 228 | movlpd qword ptr [edx], xmm3 229 | movhpd qword ptr [ebx], xmm3 230 | punpckhdq xmm0, xmm7 231 | sub ecx, 8 232 | movlpd qword ptr [edx + esi], xmm0 233 | lea edx, [edx + 2 * esi] 234 | movhpd qword ptr [ebx + ebp], xmm0 235 | lea ebx, [ebx + 2 * ebp] 236 | jg convertloop 237 | 238 | mov esp, [esp + 16] 239 | pop ebp 240 | pop edi 241 | pop esi 242 | pop ebx 243 | ret 244 | } 245 | } 246 | 247 | #endif // !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) 248 | 249 | #ifdef __cplusplus 250 | } // extern "C" 251 | } // namespace libyuv 252 | #endif 253 | -------------------------------------------------------------------------------- /app/src/main/cpp/libyuv/source/video_common.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "libyuv/video_common.h" 12 | 13 | #ifdef __cplusplus 14 | namespace libyuv { 15 | extern "C" { 16 | #endif 17 | 18 | struct FourCCAliasEntry { 19 | uint32_t alias; 20 | uint32_t canonical; 21 | }; 22 | 23 | #define NUM_ALIASES 18 24 | static const struct FourCCAliasEntry kFourCCAliases[NUM_ALIASES] = { 25 | {FOURCC_IYUV, FOURCC_I420}, 26 | {FOURCC_YU12, FOURCC_I420}, 27 | {FOURCC_YU16, FOURCC_I422}, 28 | {FOURCC_YU24, FOURCC_I444}, 29 | {FOURCC_YUYV, FOURCC_YUY2}, 30 | {FOURCC_YUVS, FOURCC_YUY2}, // kCMPixelFormat_422YpCbCr8_yuvs 31 | {FOURCC_HDYC, FOURCC_UYVY}, 32 | {FOURCC_2VUY, FOURCC_UYVY}, // kCMPixelFormat_422YpCbCr8 33 | {FOURCC_JPEG, FOURCC_MJPG}, // Note: JPEG has DHT while MJPG does not. 34 | {FOURCC_DMB1, FOURCC_MJPG}, 35 | {FOURCC_BA81, FOURCC_BGGR}, // deprecated. 36 | {FOURCC_RGB3, FOURCC_RAW}, 37 | {FOURCC_BGR3, FOURCC_24BG}, 38 | {FOURCC_CM32, FOURCC_BGRA}, // kCMPixelFormat_32ARGB 39 | {FOURCC_CM24, FOURCC_RAW}, // kCMPixelFormat_24RGB 40 | {FOURCC_L555, FOURCC_RGBO}, // kCMPixelFormat_16LE555 41 | {FOURCC_L565, FOURCC_RGBP}, // kCMPixelFormat_16LE565 42 | {FOURCC_5551, FOURCC_RGBO}, // kCMPixelFormat_16LE5551 43 | }; 44 | // TODO(fbarchard): Consider mapping kCMPixelFormat_32BGRA to FOURCC_ARGB. 45 | // {FOURCC_BGRA, FOURCC_ARGB}, // kCMPixelFormat_32BGRA 46 | 47 | LIBYUV_API 48 | uint32_t CanonicalFourCC(uint32_t fourcc) { 49 | int i; 50 | for (i = 0; i < NUM_ALIASES; ++i) { 51 | if (kFourCCAliases[i].alias == fourcc) { 52 | return kFourCCAliases[i].canonical; 53 | } 54 | } 55 | // Not an alias, so return it as-is. 56 | return fourcc; 57 | } 58 | 59 | #ifdef __cplusplus 60 | } // extern "C" 61 | } // namespace libyuv 62 | #endif 63 | -------------------------------------------------------------------------------- /app/src/main/cpp/native-lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include "k_util/k_string.h" 9 | #include "k_util/k_sockaddr.h" 10 | #include "k_util/k_socket.h" 11 | #include "k_media_sender.h" 12 | #include "k_server_conn.h" 13 | #include "k_util/k_util.h" 14 | #include "libyuv/rotate.h" 15 | 16 | static k_server_conn* m_server_conn = NULL; 17 | 18 | extern "C" 19 | JNIEXPORT void JNICALL 20 | Java_com_lisi_titan_TitanNativeLib_nativeSendMeidaData(JNIEnv *env, jobject type, 21 | jbyteArray buf_, jint len, jlong timestamp, 22 | jint msgid) { 23 | jbyte *buf = env->GetByteArrayElements(buf_, NULL); 24 | 25 | if (m_server_conn) 26 | { 27 | k_media_msg* media = new k_media_msg; 28 | media->m_size = len; 29 | media->m_ts = timestamp; 30 | media->m_data = (uint8_t*)malloc(len); 31 | memcpy(media->m_data, buf, len); 32 | 33 | k_msg msg = {msgid, media}; 34 | 35 | if(m_server_conn->enque_msg(msg)) 36 | { 37 | LOGE("enque media failed"); 38 | free(media->m_data); 39 | delete media; 40 | } 41 | } else 42 | { 43 | LOGE("server conn null"); 44 | } 45 | 46 | env->ReleaseByteArrayElements(buf_, buf, 0); 47 | } 48 | 49 | 50 | extern "C" 51 | JNIEXPORT void JNICALL 52 | Java_com_lisi_titan_TitanNativeLib_nativeYUVRoate(JNIEnv *env, jobject type, 53 | jbyteArray yuv_, jint src_width, jint src_height, 54 | jint rotate) { 55 | jbyte *yuv = env->GetByteArrayElements(yuv_, NULL); 56 | 57 | int src_i420_y_size = src_width * src_height; 58 | int src_i420_uv_size = ((src_width + 1) / 2) * ((src_height + 1) / 2); 59 | 60 | int dst_width = src_width; 61 | int dst_height = src_height; 62 | 63 | if (rotate == 90 || rotate == 270){ 64 | dst_width = src_height; 65 | dst_height = src_width; 66 | } 67 | 68 | int dst_i420_y_size = dst_width * dst_height; 69 | int dst_i420_uv_size = ((dst_width + 1) / 2) * ((dst_height + 1) / 2); 70 | int dst_i420_size = dst_i420_y_size + dst_i420_uv_size * 2; 71 | 72 | uint8_t * src_i420 = (uint8_t*)yuv; 73 | uint8_t * dst_i420_c = (uint8_t*) malloc(dst_i420_size); 74 | 75 | enum libyuv::RotationMode mode = (enum libyuv::RotationMode)rotate; 76 | 77 | libyuv::I420Rotate(src_i420, src_width, 78 | src_i420 + src_i420_y_size, (src_width + 1) / 2, 79 | src_i420 + src_i420_y_size + src_i420_uv_size, (src_width + 1) / 2, 80 | dst_i420_c, dst_width, 81 | dst_i420_c + dst_i420_y_size, (dst_width + 1) / 2, 82 | dst_i420_c + dst_i420_y_size + dst_i420_uv_size, 83 | (dst_width + 1) / 2, 84 | src_width, src_height, mode); 85 | 86 | memcpy(src_i420, dst_i420_c, dst_i420_size); 87 | free(dst_i420_c); 88 | 89 | env->ReleaseByteArrayElements(yuv_, yuv, 0); 90 | } 91 | 92 | extern "C" 93 | JNIEXPORT void JNICALL 94 | Java_com_lisi_titan_TitanNativeLib_nativeInitServerConn(JNIEnv *env, jobject type, jstring serverIP_, 95 | jint serverPort, jstring userID_, 96 | jstring password_, jobject callback) { 97 | const char *serverIP = env->GetStringUTFChars(serverIP_, 0); 98 | const char *userID = env->GetStringUTFChars(userID_, 0); 99 | const char *password = env->GetStringUTFChars(password_, 0); 100 | 101 | if(!m_server_conn) 102 | { 103 | LOGE("new server conn"); 104 | m_server_conn = new k_server_conn; 105 | m_server_conn->init(); 106 | } 107 | 108 | LOGE("init server conn"); 109 | 110 | k_init_conn_msg* init = new k_init_conn_msg; 111 | init->m_server_port = serverPort; 112 | init->m_server_ip = serverIP; 113 | init->m_user_id = userID; 114 | init->m_password = password; 115 | init->m_callback = env->NewGlobalRef(callback); 116 | 117 | k_msg msg = {600, init}; 118 | 119 | if(m_server_conn->enque_msg(msg)) 120 | { 121 | env->DeleteGlobalRef(init->m_callback); 122 | LOGE("enque init failed"); 123 | delete init; 124 | } 125 | 126 | env->ReleaseStringUTFChars(serverIP_, serverIP); 127 | env->ReleaseStringUTFChars(userID_, userID); 128 | env->ReleaseStringUTFChars(password_, password); 129 | } 130 | 131 | extern "C" 132 | JNIEXPORT void JNICALL 133 | Java_com_lisi_titan_TitanNativeLib_nativeShutServerConn(JNIEnv *env, jobject type) { 134 | if(m_server_conn) 135 | { 136 | LOGE("shut server conn"); 137 | k_msg msg = {603, NULL}; 138 | m_server_conn->enque_msg(msg); 139 | } 140 | } 141 | 142 | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) 143 | { 144 | JNIEnv* env = NULL; 145 | jint result = -1; 146 | 147 | //获取JNI版本 148 | if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) 149 | { 150 | LOGE("GetEnv failed!"); 151 | return result; 152 | } 153 | 154 | k_server_conn::g_jvm = vm; 155 | LOGE("GetEnv success!"); 156 | 157 | return JNI_VERSION_1_6; 158 | } 159 | -------------------------------------------------------------------------------- /app/src/main/java/com/lisi/titan/CaptureFormat.java: -------------------------------------------------------------------------------- 1 | package com.lisi.titan; 2 | 3 | public class CaptureFormat { 4 | // Class to represent a framerate range. The framerate varies because of lightning conditions. 5 | // The values are multiplied by 1000, so 1000 represents one frame per second. 6 | public static class FramerateRange { 7 | public int min; 8 | public int max; 9 | 10 | public FramerateRange(int min, int max) { 11 | this.min = min; 12 | this.max = max; 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | return "[" + (min / 1000.0f) + ":" + (max / 1000.0f) + "]"; 18 | } 19 | 20 | @Override 21 | public boolean equals(Object other) { 22 | if (!(other instanceof FramerateRange)) { 23 | return false; 24 | } 25 | final FramerateRange otherFramerate = (FramerateRange) other; 26 | return min == otherFramerate.min && max == otherFramerate.max; 27 | } 28 | 29 | @Override 30 | public int hashCode() { 31 | // Use prime close to 2^16 to avoid collisions for normal values less than 2^16. 32 | return 1 + 65537 * min + max; 33 | } 34 | } 35 | 36 | public final int width; 37 | public final int height; 38 | public final FramerateRange framerate; 39 | 40 | // TODO(hbos): If VideoCapturer.startCapture is updated to support other image formats then this 41 | // needs to be updated and VideoCapturer.getSupportedFormats need to return CaptureFormats of 42 | // all imageFormats. 43 | 44 | public CaptureFormat(int width, int height, FramerateRange framerate) { 45 | this.width = width; 46 | this.height = height; 47 | this.framerate = framerate; 48 | } 49 | 50 | @Override 51 | public String toString() { 52 | return width + "x" + height + "@" + framerate; 53 | } 54 | 55 | @Override 56 | public boolean equals(Object other) { 57 | if (!(other instanceof CaptureFormat)) { 58 | return false; 59 | } 60 | final CaptureFormat otherFormat = (CaptureFormat) other; 61 | return width == otherFormat.width && height == otherFormat.height 62 | && framerate.equals(otherFormat.framerate); 63 | } 64 | 65 | @Override 66 | public int hashCode() { 67 | return 1 + (width * 65497 + height) * 251 + framerate.hashCode(); 68 | } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/lisi/titan/TitanAudioEffects.java: -------------------------------------------------------------------------------- 1 | package com.lisi.titan; 2 | 3 | import android.annotation.TargetApi; 4 | import android.media.audiofx.AcousticEchoCanceler; 5 | import android.media.audiofx.AudioEffect; 6 | import android.media.audiofx.NoiseSuppressor; 7 | import android.support.annotation.Nullable; 8 | import android.util.Log; 9 | 10 | import java.util.UUID; 11 | 12 | public class TitanAudioEffects { 13 | 14 | private static final String TAG = "TitanAudioEffects"; 15 | 16 | // UUIDs for Software Audio Effects that we want to avoid using. 17 | // The implementor field will be set to "The Android Open Source Project". 18 | private static final UUID AOSP_ACOUSTIC_ECHO_CANCELER = 19 | UUID.fromString("bb392ec0-8d4d-11e0-a896-0002a5d5c51b"); 20 | private static final UUID AOSP_NOISE_SUPPRESSOR = 21 | UUID.fromString("c06c8400-8e06-11e0-9cb6-0002a5d5c51b"); 22 | 23 | // Contains the available effect descriptors returned from the 24 | // AudioEffect.getEffects() call. This result is cached to avoid doing the 25 | // slow OS call multiple times. 26 | private static @Nullable AudioEffect.Descriptor[] cachedEffects = null; 27 | 28 | // Contains the audio effect objects. Created in enable() and destroyed 29 | // in release(). 30 | private @Nullable AcousticEchoCanceler aec = null; 31 | private @Nullable NoiseSuppressor ns = null; 32 | 33 | // Affects the final state given to the setEnabled() method on each effect. 34 | // The default state is set to "disabled" but each effect can also be enabled 35 | // by calling setAEC() and setNS(). 36 | // To enable an effect, both the shouldEnableXXX member and the static 37 | // canUseXXX() must be true. 38 | private boolean shouldEnableAec = false; 39 | private boolean shouldEnableNs = false; 40 | 41 | // Returns true if all conditions for supporting HW Acoustic Echo Cancellation (AEC) are 42 | // fulfilled. 43 | @TargetApi(18) 44 | public static boolean isAcousticEchoCancelerSupported() { 45 | return isEffectTypeAvailable(AudioEffect.EFFECT_TYPE_AEC, AOSP_ACOUSTIC_ECHO_CANCELER); 46 | } 47 | 48 | // Returns true if all conditions for supporting HW Noise Suppression (NS) are fulfilled. 49 | @TargetApi(18) 50 | public static boolean isNoiseSuppressorSupported() { 51 | return isEffectTypeAvailable(AudioEffect.EFFECT_TYPE_NS, AOSP_NOISE_SUPPRESSOR); 52 | } 53 | 54 | public TitanAudioEffects() { 55 | Log.e(TAG, "ctor" ); 56 | } 57 | 58 | // Call this method to enable or disable the platform AEC. It modifies 59 | // |shouldEnableAec| which is used in enable() where the actual state 60 | // of the AEC effect is modified. Returns true if HW AEC is supported and 61 | // false otherwise. 62 | public boolean setAEC(boolean enable) { 63 | Log.e(TAG, "setAEC(" + enable + ")"); 64 | if (!isAcousticEchoCancelerSupported()) { 65 | Log.w(TAG, "Platform AEC is not supported"); 66 | shouldEnableAec = false; 67 | return false; 68 | } 69 | if (aec != null && (enable != shouldEnableAec)) { 70 | Log.e(TAG, "Platform AEC state can't be modified while recording"); 71 | return false; 72 | } 73 | shouldEnableAec = enable; 74 | return true; 75 | } 76 | 77 | // Call this method to enable or disable the platform NS. It modifies 78 | // |shouldEnableNs| which is used in enable() where the actual state 79 | // of the NS effect is modified. Returns true if HW NS is supported and 80 | // false otherwise. 81 | public boolean setNS(boolean enable) { 82 | Log.e(TAG, "setNS(" + enable + ")"); 83 | if (!isNoiseSuppressorSupported()) { 84 | Log.w(TAG, "Platform NS is not supported"); 85 | shouldEnableNs = false; 86 | return false; 87 | } 88 | if (ns != null && (enable != shouldEnableNs)) { 89 | Log.e(TAG, "Platform NS state can't be modified while recording"); 90 | return false; 91 | } 92 | shouldEnableNs = enable; 93 | return true; 94 | } 95 | 96 | public void enable(int audioSession) { 97 | Log.e(TAG, "enable(audioSession=" + audioSession + ")"); 98 | assertTrue(aec == null); 99 | assertTrue(ns == null); 100 | 101 | if (isAcousticEchoCancelerSupported()) { 102 | // Create an AcousticEchoCanceler and attach it to the AudioRecord on 103 | // the specified audio session. 104 | aec = AcousticEchoCanceler.create(audioSession); 105 | if (aec != null) { 106 | boolean enabled = aec.getEnabled(); 107 | boolean enable = shouldEnableAec && isAcousticEchoCancelerSupported(); 108 | if (aec.setEnabled(enable) != AudioEffect.SUCCESS) { 109 | Log.e(TAG, "Failed to set the AcousticEchoCanceler state"); 110 | } 111 | Log.e(TAG, 112 | "AcousticEchoCanceler: was " + (enabled ? "enabled" : "disabled") + ", enable: " 113 | + enable + ", is now: " + (aec.getEnabled() ? "enabled" : "disabled")); 114 | } else { 115 | Log.e(TAG, "Failed to create the AcousticEchoCanceler instance"); 116 | } 117 | } 118 | 119 | if (isNoiseSuppressorSupported()) { 120 | // Create an NoiseSuppressor and attach it to the AudioRecord on the 121 | // specified audio session. 122 | ns = NoiseSuppressor.create(audioSession); 123 | if (ns != null) { 124 | boolean enabled = ns.getEnabled(); 125 | boolean enable = shouldEnableNs && isNoiseSuppressorSupported(); 126 | if (ns.setEnabled(enable) != AudioEffect.SUCCESS) { 127 | Log.e(TAG, "Failed to set the NoiseSuppressor state"); 128 | } 129 | Log.e(TAG, 130 | "NoiseSuppressor: was " + (enabled ? "enabled" : "disabled") + ", enable: " + enable 131 | + ", is now: " + (ns.getEnabled() ? "enabled" : "disabled")); 132 | } else { 133 | Log.e(TAG, "Failed to create the NoiseSuppressor instance"); 134 | } 135 | } 136 | } 137 | 138 | // Releases all native audio effect resources. It is a good practice to 139 | // release the effect engine when not in use as control can be returned 140 | // to other applications or the native resources released. 141 | public void release() { 142 | Log.e(TAG, "release"); 143 | if (aec != null) { 144 | aec.release(); 145 | aec = null; 146 | } 147 | if (ns != null) { 148 | ns.release(); 149 | ns = null; 150 | } 151 | } 152 | 153 | 154 | // Helper method which throws an exception when an assertion has failed. 155 | private static void assertTrue(boolean condition) { 156 | if (!condition) { 157 | throw new AssertionError("Expected condition to be true"); 158 | } 159 | } 160 | 161 | // Returns the cached copy of the audio effects array, if available, or 162 | // queries the operating system for the list of effects. 163 | private static @Nullable AudioEffect.Descriptor[] getAvailableEffects() { 164 | if (cachedEffects != null) { 165 | return cachedEffects; 166 | } 167 | // The caching is best effort only - if this method is called from several 168 | // threads in parallel, they may end up doing the underlying OS call 169 | // multiple times. It's normally only called on one thread so there's no 170 | // real need to optimize for the multiple threads case. 171 | cachedEffects = AudioEffect.queryEffects(); 172 | return cachedEffects; 173 | } 174 | 175 | // Returns true if an effect of the specified type is available. Functionally 176 | // equivalent to (NoiseSuppressor|AutomaticGainControl|...).isAvailable(), but 177 | // faster as it avoids the expensive OS call to enumerate effects. 178 | @TargetApi(18) 179 | private static boolean isEffectTypeAvailable(UUID effectType, UUID blackListedUuid) { 180 | AudioEffect.Descriptor[] effects = getAvailableEffects(); 181 | if (effects == null) { 182 | return false; 183 | } 184 | for (AudioEffect.Descriptor d : effects) { 185 | if (d.type.equals(effectType)) { 186 | return true;//!d.uuid.equals(blackListedUuid); 187 | } 188 | } 189 | return false; 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /app/src/main/java/com/lisi/titan/TitanAudioEncoder.java: -------------------------------------------------------------------------------- 1 | package com.lisi.titan; 2 | 3 | import android.media.MediaCodec; 4 | import android.media.MediaCodecInfo; 5 | import android.media.MediaFormat; 6 | import android.support.annotation.Nullable; 7 | import android.util.Log; 8 | 9 | import java.io.IOException; 10 | import java.nio.ByteBuffer; 11 | 12 | public class TitanAudioEncoder { 13 | 14 | private static final String TAG = "TitanAudioEncoder"; 15 | 16 | private final String MIME_TYPE="audio/mp4a-latm"; 17 | private final int KEY_CHANNEL_COUNT=1; 18 | private final int KEY_SAMPLE_RATE=44100; 19 | private final int KEY_BIT_RATE=64000; 20 | private final int KEY_AAC_PROFILE= MediaCodecInfo.CodecProfileLevel.AACObjectLC; 21 | private static final int DEQUEUE_OUTPUT_BUFFER_TIMEOUT_US = 100000; 22 | private static final int MAX_ENCODER_Q_SIZE = 10; 23 | 24 | private MediaCodec mMeidaCodec; 25 | @Nullable 26 | private Thread outputThread; 27 | private volatile boolean running = false; 28 | 29 | public int initEncode() 30 | { 31 | try { 32 | mMeidaCodec = MediaCodec.createEncoderByType(MIME_TYPE); 33 | } catch (IOException | IllegalArgumentException e) { 34 | Log.e(TAG, "Cannot create media encoder " + MIME_TYPE); 35 | return -1; 36 | } 37 | 38 | MediaFormat mediaFormat = MediaFormat.createAudioFormat(MIME_TYPE, 39 | KEY_SAMPLE_RATE, KEY_CHANNEL_COUNT); 40 | mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, KEY_BIT_RATE); 41 | mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, 42 | KEY_AAC_PROFILE); 43 | mMeidaCodec.configure(mediaFormat, null, null, 44 | MediaCodec.CONFIGURE_FLAG_ENCODE); 45 | mMeidaCodec.start(); 46 | 47 | running = true; 48 | outputThread = createOutputThread(); 49 | outputThread.start(); 50 | 51 | return 0; 52 | } 53 | 54 | private Thread createOutputThread() { 55 | return new Thread() { 56 | @Override 57 | public void run() { 58 | while (running) { 59 | deliverEncodedAudio(); 60 | } 61 | releaseCodecOnOutputThread(); 62 | } 63 | }; 64 | } 65 | 66 | private void deliverEncodedAudio() { 67 | try { 68 | MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); 69 | int index = mMeidaCodec.dequeueOutputBuffer(info, DEQUEUE_OUTPUT_BUFFER_TIMEOUT_US); 70 | if (index < 0) { 71 | return; 72 | } 73 | 74 | ByteBuffer codecOutputBuffer = mMeidaCodec.getOutputBuffer(index); 75 | codecOutputBuffer.position(info.offset); 76 | codecOutputBuffer.limit(info.offset + info.size); 77 | 78 | int length = info.size + 4; 79 | byte[] outData = new byte[length]; 80 | 81 | addAUHead(outData, info.size); 82 | codecOutputBuffer.get(outData,4,info.size); 83 | 84 | long timestamp = Math.round(System.currentTimeMillis() * 44.1d) ; 85 | 86 | TitanNativeLib.nativeSendMeidaData(outData, outData.length, timestamp, 602); 87 | 88 | mMeidaCodec.releaseOutputBuffer(index, false); 89 | } catch (IllegalStateException e) { 90 | Log.e(TAG, "deliverOutput failed", e); 91 | } 92 | } 93 | 94 | private void addADTStoPacket(byte[] packet, int packetLen) { 95 | int profile = 2; //AAC LC 96 | int freqIdx = 4; //44.1KHz 97 | int chanCfg = 1; //CPE 98 | packet[0] = (byte)0xFF; 99 | packet[1] = (byte)0xF9; 100 | packet[2] = (byte)(((profile-1)<<6) + (freqIdx<<2) +(chanCfg>>2)); 101 | packet[3] = (byte)(((chanCfg&3)<<6) + (packetLen>>11)); 102 | packet[4] = (byte)((packetLen&0x7FF) >> 3); 103 | packet[5] = (byte)(((packetLen&7)<<5) + 0x1F); 104 | packet[6] = (byte)0xFC; 105 | } 106 | 107 | private void addAUHead(byte[] packet, int packetLen) { 108 | packet[0] = (byte)0x0; 109 | packet[1] = (byte)0x10; 110 | packet[2] = (byte)((packetLen & 0x1FFF) >> 5); 111 | packet[3] = (byte)((packetLen & 0x1F) << 3); 112 | } 113 | 114 | private void releaseCodecOnOutputThread() { 115 | Log.e(TAG, "Releasing MediaCodec on output thread"); 116 | try { 117 | mMeidaCodec.stop(); 118 | } catch (Exception e) { 119 | Log.e(TAG, "Media encoder stop failed", e); 120 | } 121 | try { 122 | mMeidaCodec.release(); 123 | } catch (Exception e) { 124 | Log.e(TAG, "Media encoder release failed", e); 125 | // Propagate exceptions caught during release back to the main thread. 126 | } 127 | Log.e(TAG, "Release on output thread done"); 128 | } 129 | 130 | public int release() { 131 | 132 | final int returnValue; 133 | if (outputThread == null) { 134 | returnValue = 0; 135 | } else { 136 | // The outputThread actually stops and releases the codec once running is false. 137 | running = false; 138 | 139 | try { 140 | outputThread.join(); 141 | } 142 | catch (InterruptedException e) 143 | { 144 | Log.e(TAG, "Media encoder release exception", e); 145 | } 146 | 147 | returnValue = 0; 148 | } 149 | 150 | mMeidaCodec = null; 151 | outputThread = null; 152 | 153 | return returnValue; 154 | } 155 | 156 | public int encode(byte[] data) { 157 | if (mMeidaCodec == null) { 158 | return -1; 159 | } 160 | 161 | final int returnValue = encodeByteBuffer(data); 162 | // Check if the queue was successful. 163 | 164 | return returnValue; 165 | } 166 | 167 | private int encodeByteBuffer(byte[] inBuffer) 168 | { 169 | int index; 170 | try { 171 | index = mMeidaCodec.dequeueInputBuffer(0 /* timeout */); 172 | } catch (IllegalStateException e) { 173 | Log.e(TAG, "dequeueInputBuffer failed", e); 174 | return -1; 175 | } 176 | 177 | if (index == -1) { 178 | // Encoder is falling behind. No input buffers available. Drop the frame. 179 | Log.d(TAG, "Dropped frame, no input buffers available"); 180 | return -1; // See webrtc bug 2887. 181 | } 182 | 183 | ByteBuffer buffer; 184 | try { 185 | buffer = mMeidaCodec.getInputBuffer(index); 186 | } catch (IllegalStateException e) { 187 | Log.e(TAG, "getInputBuffers failed", e); 188 | return -1; 189 | } 190 | 191 | long pts = (System.nanoTime() + 500) / 1000; 192 | buffer.clear(); 193 | buffer.put(inBuffer); 194 | buffer.limit(inBuffer.length); 195 | 196 | try { 197 | mMeidaCodec.queueInputBuffer( 198 | index, 0 /* offset */, inBuffer.length, pts, 0 /* flags */); 199 | } catch (IllegalStateException e) { 200 | Log.e(TAG, "queueInputBuffer failed", e); 201 | // IllegalStateException thrown when the codec is in the wrong state. 202 | return -1; 203 | } 204 | return 0; 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /app/src/main/java/com/lisi/titan/TitanNativeLib.java: -------------------------------------------------------------------------------- 1 | package com.lisi.titan; 2 | 3 | import android.util.Log; 4 | 5 | public class TitanNativeLib { 6 | // Used to load the 'native-lib' library on application startup. 7 | static { 8 | System.loadLibrary("native-lib"); 9 | } 10 | 11 | public static class TitanNativeCallback 12 | { 13 | private static final String TAG = "TitanNativeCallback"; 14 | 15 | public void onLoginCallback(int ret){} 16 | public void onDisconnectCallback(int ret){} 17 | } 18 | 19 | public static native void nativeInitServerConn(String serverIP, int serverPort, String userID, 20 | String password, TitanNativeCallback callback); 21 | 22 | public static native void nativeShutServerConn(); 23 | public static native void nativeSendMeidaData(byte[] buf, int len, long timestamp, int msgid); 24 | public static native void nativeYUVRoate(byte[] buf, int width, int height, int rotate); 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 22 | 23 | 24 |