├── 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 |
7 |
8 |
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