├── stdafx.h
├── kronos.cpp
├── stdafx.cpp
├── targetver.h
├── k_util
├── k_socket.h
├── k_errno.h
├── k_errno.cpp
├── k_mutex.h
├── k_handler.h
├── k_sockaddr.h
├── k_util.h
├── k_handler.cpp
├── k_sockaddr.cpp
├── k_string.h
├── k_util.cpp
├── k_event.h
├── k_mutex.cpp
├── k_thread_task.h
├── k_string.cpp
├── k_event.cpp
├── k_socket.cpp
└── k_thread_task.cpp
├── k_mobile_handler.cpp
├── ReadMe.txt
├── kronos.vcxproj.user
├── k_media_server.h
├── Makefile
├── k_accept_handler.h
├── k_media_server.cpp
├── k_mobile_handler.h
├── k_rtsp_handler.h
├── kronos.vcxproj.filters
├── kronos.vcxproj
├── k_rtsp_handler.cpp
└── jsoncpp
└── json
├── json-forwards.h
└── json.h
/stdafx.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/greenjim301/kronos/HEAD/stdafx.h
--------------------------------------------------------------------------------
/kronos.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/greenjim301/kronos/HEAD/kronos.cpp
--------------------------------------------------------------------------------
/stdafx.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/greenjim301/kronos/HEAD/stdafx.cpp
--------------------------------------------------------------------------------
/targetver.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/greenjim301/kronos/HEAD/targetver.h
--------------------------------------------------------------------------------
/k_util/k_socket.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/greenjim301/kronos/HEAD/k_util/k_socket.h
--------------------------------------------------------------------------------
/k_mobile_handler.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/greenjim301/kronos/HEAD/k_mobile_handler.cpp
--------------------------------------------------------------------------------
/ReadMe.txt:
--------------------------------------------------------------------------------
1 | 简单的手机推流服务器和RTSP服务器
2 |
3 | 手机采集音视频流推到该服务器
4 |
5 | RTSP客户端向该服务器请求手机采集流
6 |
7 | 简单介绍见https://blog.csdn.net/greenjim301/article/details/80563603
8 |
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/kronos.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 192.168.1.101 9010
5 | WindowsLocalDebugger
6 |
7 |
--------------------------------------------------------------------------------
/k_media_server.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "k_util/k_thread_task.h"
4 | #include "k_rtsp_handler.h"
5 | #include
6 |
7 | class k_media_server : public k_thread_task
8 | {
9 | public:
10 | void regist_sink(k_rtsp_handler* handler);
11 | void unregist_sink(k_rtsp_handler* handler);
12 | void on_video(uint8_t* buf, int len);
13 | void on_audio(uint8_t* buf, int len);
14 |
15 | private:
16 | std::set m_rtsp_handler;
17 | };
18 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | CXX = g++
2 | #2、定义您自己的可执行文件名称
3 | PROGRAM_NAME=kronos
4 | ##################################################################### #
5 | #3、指定您必须生成的工程文件
6 |
7 | SOURCE = $(wildcard *.cpp) \
8 | $(wildcard k_util/*.cpp)
9 |
10 | OBJECTS = $(SOURCE:.cpp=.o)
11 | CFLAGS = -g
12 |
13 | .PHONY: all
14 | all: $(PROGRAM_NAME)
15 |
16 | clean:
17 | @echo "[Cleanning...]"
18 | @rm -f $(OBJECTS) $(PROGRAM_NAME)
19 |
20 | %.o: %.cpp
21 | $(CXX) $(CFLAGS) -o $@ -c $<
22 |
23 |
24 | $(PROGRAM_NAME): $(OBJECTS)
25 | $(CXX) $(CFLAGS) -o $@ $^ -lpthread
26 |
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/k_accept_handler.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "k_util/k_handler.h"
4 |
5 | template
6 | class k_accept_handler : public k_handler
7 | {
8 | public:
9 | virtual int handle_read(k_thread_task* task, k_event* ev, k_socket* sock)
10 | {
11 | printf("accepted\n");
12 |
13 | k_socket* accept_sock = new k_socket;
14 | k_sockaddr addr;
15 | m_read_handler = new T;
16 |
17 | sock->k_accept(addr, *accept_sock);
18 | task->add_event(accept_sock, m_read_handler, k_event::READ_MASK);
19 |
20 | return 0;
21 | }
22 |
23 | private:
24 | T* m_read_handler;
25 | };
26 |
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/k_media_server.cpp:
--------------------------------------------------------------------------------
1 | #include "k_media_server.h"
2 |
3 | void k_media_server::regist_sink(k_rtsp_handler* handler)
4 | {
5 | m_rtsp_handler.insert(handler);
6 | }
7 |
8 | void k_media_server::unregist_sink(k_rtsp_handler* handler)
9 | {
10 | m_rtsp_handler.erase(handler);
11 | }
12 |
13 | void k_media_server::on_video(uint8_t* buf, int len)
14 | {
15 | for (auto it = m_rtsp_handler.begin(); it != m_rtsp_handler.end(); ++it)
16 | {
17 | (*it)->on_video(buf, len);
18 | }
19 | }
20 |
21 | void k_media_server::on_audio(uint8_t* buf, int len)
22 | {
23 | for (auto it = m_rtsp_handler.begin(); it != m_rtsp_handler.end(); ++it)
24 | {
25 | (*it)->on_audio(buf, len);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/k_util/k_util.h:
--------------------------------------------------------------------------------
1 | #ifndef __K_UTIL_H__
2 | #define __K_UTIL_H__
3 |
4 | #include
5 |
6 | class k_util
7 | {
8 | public:
9 | static int init();
10 | static void cleanup();
11 |
12 | static void k_sleep(int seconds);
13 |
14 | static void avio_w8(uint8_t*& s, int b);
15 | static void avio_wb16(uint8_t*& s, unsigned int val);
16 | static void avio_wb32(uint8_t*& s, unsigned int val);
17 | };
18 |
19 | #define AV_RB16(x) ((((const uint8_t*)(x))[0] << 8) | ((const uint8_t*)(x))[1])
20 | #define AV_RB32(x) ((((const uint8_t*)(x))[0] << 24) | \
21 | (((const uint8_t*)(x))[1] << 16) | \
22 | (((const uint8_t*)(x))[2] << 8) | \
23 | ((const uint8_t*)(x))[3])
24 |
25 | #endif
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/k_util/k_string.h:
--------------------------------------------------------------------------------
1 | #ifndef __K_STRING_H__
2 | #define __K_STRING_H__
3 |
4 | #include
5 |
6 | class k_string
7 | {
8 | public:
9 | k_string();
10 | k_string(const char* str);
11 | k_string(const char* str, int size);
12 |
13 | void assign(const char* str, int size);
14 | void append(const char* str, int size);
15 | void append(uint32_t num);
16 |
17 | char* find(const char* str);
18 |
19 | const char* c_str() const;
20 | int size() const;
21 |
22 | bool operator < (const k_string& r_str) const;
23 | bool operator == (const k_string& r_str) const;
24 |
25 | private:
26 | enum
27 | {
28 | STR_MAX_LEN = 256
29 | };
30 |
31 | char m_buf[STR_MAX_LEN];
32 | int m_size;
33 | };
34 |
35 | #endif
36 |
--------------------------------------------------------------------------------
/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::k_sleep(int seconds)
27 | {
28 | #ifdef WIN32
29 | Sleep(seconds * 1000);
30 | #else
31 | sleep(seconds);
32 | #endif
33 | }
34 |
35 | void k_util::avio_w8(uint8_t*& s, int b)
36 | {
37 | *s++ = b;
38 | }
39 |
40 | void k_util::avio_wb16(uint8_t*& s, unsigned int val)
41 | {
42 | avio_w8(s, (int)val >> 8);
43 | avio_w8(s, (uint8_t)val);
44 | }
45 |
46 | void k_util::avio_wb32(uint8_t*& s, unsigned int val)
47 | {
48 | avio_w8(s, val >> 24);
49 | avio_w8(s, (uint8_t)(val >> 16));
50 | avio_w8(s, (uint8_t)(val >> 8));
51 | avio_w8(s, (uint8_t)val);
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/k_mobile_handler.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "k_util/k_handler.h"
4 | #include
5 | #include
6 |
7 | class k_mobile_handler : public k_handler
8 | {
9 | public:
10 | k_mobile_handler();
11 | ~k_mobile_handler();
12 |
13 | enum
14 | {
15 | K_MSG_HEAD_LEN = sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint32_t),
16 | K_MAGIC = 0x1234,
17 | K_VIDEO = 1000,
18 | K_AUDIO = 1001,
19 | K_LOGIN = 1002,
20 | K_LOGIN_RSP = 1003
21 | };
22 |
23 | virtual int handle_read(k_thread_task* task, k_event* ev, k_socket* sock);
24 |
25 | int incoming_msg(uint32_t msg_id, const char* buf, int len,
26 | k_thread_task* task, k_event* ev, k_socket* sock);
27 |
28 | int on_login_msg(const char* buf, int len, k_socket* sock, k_thread_task* task);
29 | int on_media_msg(k_thread_task* task, uint32_t msg_id, uint8_t* buf, int len);
30 |
31 | int ff_h264_handle_frag_packet(const uint8_t *buf, int len,
32 | int start_bit, const uint8_t *nal_header,
33 | int nal_header_len);
34 |
35 | int h264_handle_packet_fu_a(const uint8_t *buf, int len);
36 |
37 |
38 | private:
39 | char buf[4096];
40 | char head_buf[K_MSG_HEAD_LEN];
41 |
42 | char* m_rebuf;
43 | uint32_t m_rebuf_size;
44 | FILE* m_video_fp;
45 | FILE* m_auido_fp;
46 | };
47 |
--------------------------------------------------------------------------------
/k_rtsp_handler.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "k_util/k_handler.h"
4 | #include "k_util/k_string.h"
5 | #include
6 | #include
7 |
8 | class k_rtsp_rsp
9 | {
10 | public:
11 | k_string version;
12 | k_string result;
13 | k_string describe;
14 | k_string session;
15 | k_string transport;
16 |
17 | k_string content_type;
18 | k_string content_base;
19 |
20 | k_string cseq;
21 | k_string rtsp_public;
22 |
23 | std::list sdp;
24 | };
25 |
26 | class k_rtsp_head
27 | {
28 | public:
29 | k_string cmd;
30 | k_string url;
31 | k_string version;
32 | k_string cseq;
33 | k_string session;
34 | k_string transport;
35 | };
36 |
37 | class k_rtsp_handler : public k_handler
38 | {
39 | public:
40 | k_rtsp_handler();
41 | ~k_rtsp_handler();
42 |
43 | virtual int handle_read(k_thread_task* task, k_event* ev, k_socket* sock);
44 | virtual void handle_del(k_thread_task* task, k_event* ev, k_socket* sock);
45 |
46 | void on_video(uint8_t* buf, int len);
47 | void on_audio(uint8_t* buf, int len);
48 |
49 | private:
50 | int parse_rtp_rtcp(uint8_t channel, char* buf, int len);
51 | int next_sapce(char* p, char*& p_sapce);
52 | int skip_space(char*& p);
53 | void next_end(char* p, char*& p_end);
54 | int parse_head_line(char*& p, k_rtsp_head& head);
55 | int parse_line(char*& p, k_rtsp_head& head);
56 | void append_space(char*& p);
57 | void append_line_end(char*& p);
58 | int send_rtsp_rsp(k_rtsp_rsp& rsp, k_socket* sock);
59 | int on_rtsp_head(k_rtsp_head& head, k_thread_task* task, k_socket* sock);
60 |
61 | private:
62 | char m_buf[4096 + 1];
63 | uint32_t m_session_id;
64 | k_socket* m_sock;
65 | char* m_rebuf;
66 | int m_rebuf_size;
67 | };
--------------------------------------------------------------------------------
/k_util/k_thread_task.h:
--------------------------------------------------------------------------------
1 | #ifndef __K_THREAD_TASK_H__
2 | #define __K_THREAD_TASK_H__
3 |
4 | #include