正在显示
8 个修改的文件
包含
128 行增加
和
69 行删除
@@ -37,6 +37,40 @@ gcc srs_h264_raw_publish.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_h | @@ -37,6 +37,40 @@ gcc srs_h264_raw_publish.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_h | ||
37 | 37 | ||
38 | #define srs_trace(msg, ...) printf(msg, ##__VA_ARGS__);printf("\n") | 38 | #define srs_trace(msg, ...) printf(msg, ##__VA_ARGS__);printf("\n") |
39 | 39 | ||
40 | +int read_h264_frame(char* data, int size, char** p, int fps, | ||
41 | + char** frame, int* frame_size, int* dts, int* pts) | ||
42 | +{ | ||
43 | + // @remark, for this demo, to publish h264 raw file to SRS, | ||
44 | + // we search the h264 frame from the buffer which cached the h264 data. | ||
45 | + // please get h264 raw data from device, it always a encoded frame. | ||
46 | + int pnb_start_code = 0; | ||
47 | + if (!srs_h264_startswith_annexb(*p, size - (*p - data), &pnb_start_code)) { | ||
48 | + srs_trace("h264 raw data invalid."); | ||
49 | + return -1; | ||
50 | + } | ||
51 | + *p += pnb_start_code; | ||
52 | + | ||
53 | + *frame = *p; | ||
54 | + for (;*p < data + size; *p = *p + 1) { | ||
55 | + if (srs_h264_startswith_annexb(*p, size - (*p - data), &pnb_start_code)) { | ||
56 | + break; | ||
57 | + } | ||
58 | + } | ||
59 | + *frame_size = *p - *frame; | ||
60 | + if (*frame_size <= 0) { | ||
61 | + srs_trace("h264 raw data invalid."); | ||
62 | + return -1; | ||
63 | + } | ||
64 | + | ||
65 | + // @remark, please get the dts and pts from device, | ||
66 | + // we assume there is no B frame, and the fps can guess the fps and dts, | ||
67 | + // while the dts and pts must read from encode lib or device. | ||
68 | + *dts += 1000 / fps; | ||
69 | + *pts = *dts; | ||
70 | + | ||
71 | + return 0; | ||
72 | +} | ||
73 | + | ||
40 | int main(int argc, char** argv) | 74 | int main(int argc, char** argv) |
41 | { | 75 | { |
42 | srs_trace("publish raw h.264 as rtmp stream to server like FMLE/FFMPEG/Encoder"); | 76 | srs_trace("publish raw h.264 as rtmp stream to server like FMLE/FFMPEG/Encoder"); |
@@ -107,24 +141,22 @@ int main(int argc, char** argv) | @@ -107,24 +141,22 @@ int main(int argc, char** argv) | ||
107 | } | 141 | } |
108 | srs_trace("publish stream success"); | 142 | srs_trace("publish stream success"); |
109 | 143 | ||
144 | + u_int32_t dts = 0; | ||
145 | + u_int32_t pts = 0; | ||
110 | // @remark, the dts and pts if read from device, for instance, the encode lib, | 146 | // @remark, the dts and pts if read from device, for instance, the encode lib, |
111 | // so we assume the fps is 25, and each h264 frame is 1000ms/25fps=40ms/f. | 147 | // so we assume the fps is 25, and each h264 frame is 1000ms/25fps=40ms/f. |
112 | u_int32_t fps = 25; | 148 | u_int32_t fps = 25; |
113 | - u_int32_t dts = 0; | ||
114 | - u_int32_t pts = 0; | ||
115 | - for (;;) { | ||
116 | - // get h264 raw data from device, whatever. | ||
117 | - int size = 4096; | ||
118 | - char* data = (char*)malloc(4096); | ||
119 | - if ((size = read(raw_fd, data, size)) < 0) { | ||
120 | - srs_trace("read h264 raw data failed. nread=%d", size); | 149 | + // @remark, to decode the file. |
150 | + char* p = h264_raw; | ||
151 | + for (;p < h264_raw + file_size;) { | ||
152 | + // @remark, read a frame from file buffer. | ||
153 | + char* data = NULL; | ||
154 | + int size = 0; | ||
155 | + if (read_h264_frame(h264_raw, file_size, &p, fps, &data, &size, &dts, &pts) < 0) { | ||
156 | + srs_trace("read a frame from file buffer failed."); | ||
121 | goto rtmp_destroy; | 157 | goto rtmp_destroy; |
122 | } | 158 | } |
123 | - if (size == 0) { | ||
124 | - srs_trace("publish h264 raw data completed."); | ||
125 | - goto rtmp_destroy; | ||
126 | - } | ||
127 | - | 159 | + |
128 | // convert the h264 packet to rtmp packet. | 160 | // convert the h264 packet to rtmp packet. |
129 | char* rtmp_data = NULL; | 161 | char* rtmp_data = NULL; |
130 | int rtmp_size = 0; | 162 | int rtmp_size = 0; |
@@ -142,15 +174,10 @@ int main(int argc, char** argv) | @@ -142,15 +174,10 @@ int main(int argc, char** argv) | ||
142 | srs_trace("sent packet: type=%s, time=%d, size=%d, fps=%d", | 174 | srs_trace("sent packet: type=%s, time=%d, size=%d, fps=%d", |
143 | srs_type2string(type), timestamp, rtmp_size, fps); | 175 | srs_type2string(type), timestamp, rtmp_size, fps); |
144 | 176 | ||
145 | - // @remark, please get the dts and pts from device, | ||
146 | - // we assume there is no B frame, and the fps can guess the fps and dts, | ||
147 | - // while the dts and pts must read from encode lib or device. | ||
148 | - dts += 1000 / fps; | ||
149 | - pts = dts; | ||
150 | - | ||
151 | // @remark, when use encode device, it not need to sleep. | 177 | // @remark, when use encode device, it not need to sleep. |
152 | usleep(1000 / fps * 1000); | 178 | usleep(1000 / fps * 1000); |
153 | } | 179 | } |
180 | + srs_trace("h264 raw data completed"); | ||
154 | 181 | ||
155 | rtmp_destroy: | 182 | rtmp_destroy: |
156 | srs_rtmp_destroy(rtmp); | 183 | srs_rtmp_destroy(rtmp); |
@@ -28,6 +28,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -28,6 +28,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
28 | #include <srs_kernel_stream.hpp> | 28 | #include <srs_kernel_stream.hpp> |
29 | #include <srs_protocol_amf0.hpp> | 29 | #include <srs_protocol_amf0.hpp> |
30 | #include <srs_app_utility.hpp> | 30 | #include <srs_app_utility.hpp> |
31 | +#include <srs_protocol_utility.hpp> | ||
31 | 32 | ||
32 | SrsCodecSampleUnit::SrsCodecSampleUnit() | 33 | SrsCodecSampleUnit::SrsCodecSampleUnit() |
33 | { | 34 | { |
@@ -107,35 +107,6 @@ int srs_get_log_level(string level) | @@ -107,35 +107,6 @@ int srs_get_log_level(string level) | ||
107 | } | 107 | } |
108 | } | 108 | } |
109 | 109 | ||
110 | -bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code) | ||
111 | -{ | ||
112 | - char* bytes = stream->data() + stream->pos(); | ||
113 | - char* p = bytes; | ||
114 | - | ||
115 | - for (;;) { | ||
116 | - if (!stream->require(p - bytes + 3)) { | ||
117 | - return false; | ||
118 | - } | ||
119 | - | ||
120 | - // not match | ||
121 | - if (p[0] != 0x00 || p[1] != 0x00) { | ||
122 | - return false; | ||
123 | - } | ||
124 | - | ||
125 | - // match N[00] 00 00 01, where N>=0 | ||
126 | - if (p[2] == 0x01) { | ||
127 | - if (pnb_start_code) { | ||
128 | - *pnb_start_code = (int)(p - bytes) + 3; | ||
129 | - } | ||
130 | - return true; | ||
131 | - } | ||
132 | - | ||
133 | - p++; | ||
134 | - } | ||
135 | - | ||
136 | - return false; | ||
137 | -} | ||
138 | - | ||
139 | static SrsRusage _srs_system_rusage; | 110 | static SrsRusage _srs_system_rusage; |
140 | 111 | ||
141 | SrsRusage::SrsRusage() | 112 | SrsRusage::SrsRusage() |
@@ -50,15 +50,6 @@ extern int srs_socket_connect(std::string server, int port, int64_t timeout, st_ | @@ -50,15 +50,6 @@ extern int srs_socket_connect(std::string server, int port, int64_t timeout, st_ | ||
50 | */ | 50 | */ |
51 | extern int srs_get_log_level(std::string level); | 51 | extern int srs_get_log_level(std::string level); |
52 | 52 | ||
53 | -/** | ||
54 | -* whether stream starts with the avc NALU in "AnnexB" | ||
55 | -* from H.264-AVC-ISO_IEC_14496-10.pdf, page 211. | ||
56 | -* start code must be "N[00] 00 00 01" where N>=0 | ||
57 | -* @param pnb_start_code output the size of start code, must >=3. | ||
58 | -* NULL to ignore. | ||
59 | -*/ | ||
60 | -extern bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code = NULL); | ||
61 | - | ||
62 | // current process resouce usage. | 53 | // current process resouce usage. |
63 | // @see: man getrusage | 54 | // @see: man getrusage |
64 | class SrsRusage | 55 | class SrsRusage |
@@ -998,11 +998,24 @@ char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize) | @@ -998,11 +998,24 @@ char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize) | ||
998 | 998 | ||
999 | int srs_h264_to_rtmp(char* h264_raw_data, int h264_raw_size, u_int32_t dts, u_int32_t pts, char** prtmp_data, int* prtmp_size, u_int32_t* ptimestamp) | 999 | int srs_h264_to_rtmp(char* h264_raw_data, int h264_raw_size, u_int32_t dts, u_int32_t pts, char** prtmp_data, int* prtmp_size, u_int32_t* ptimestamp) |
1000 | { | 1000 | { |
1001 | - *prtmp_data = h264_raw_data; | 1001 | + *prtmp_data = new char[h264_raw_size]; |
1002 | + memcpy(*prtmp_data, h264_raw_data, h264_raw_size); | ||
1003 | + | ||
1002 | *prtmp_size = h264_raw_size; | 1004 | *prtmp_size = h264_raw_size; |
1005 | + | ||
1003 | return 0; | 1006 | return 0; |
1004 | } | 1007 | } |
1005 | 1008 | ||
1009 | +int srs_h264_startswith_annexb(char* h264_raw_data, int h264_raw_size, int* pnb_start_code) | ||
1010 | +{ | ||
1011 | + SrsStream stream; | ||
1012 | + if (stream.initialize(h264_raw_data, h264_raw_size) != ERROR_SUCCESS) { | ||
1013 | + return false; | ||
1014 | + } | ||
1015 | + | ||
1016 | + return srs_avc_startswith_annexb(&stream, pnb_start_code); | ||
1017 | +} | ||
1018 | + | ||
1006 | #ifdef __cplusplus | 1019 | #ifdef __cplusplus |
1007 | } | 1020 | } |
1008 | #endif | 1021 | #endif |
@@ -337,22 +337,37 @@ extern char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize); | @@ -337,22 +337,37 @@ extern char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize); | ||
337 | ************************************************************** | 337 | ************************************************************** |
338 | *************************************************************/ | 338 | *************************************************************/ |
339 | /** | 339 | /** |
340 | -convert h264 stream data to rtmp packet. | ||
341 | -@param h264_raw_data the input h264 raw data, a encoded h.264 I/P/B frame data. | ||
342 | -@paam h264_raw_size the size of h264 raw data. | ||
343 | -@param dts the dts of h.264 raw data. | ||
344 | -@param pts the pts of h.264 raw data. | ||
345 | -@param prtmp_data the output rtmp format packet, which can be send by srs_write_packet. | ||
346 | -@param prtmp_size the size of rtmp packet, for srs_write_packet. | ||
347 | -@param ptimestamp the timestamp of rtmp packet, for srs_write_packet. | ||
348 | -@remark, user should never free the h264_raw_data. | ||
349 | -@remark, user should free the prtmp_data if success. | ||
350 | -@return 0, success; otherswise, failed. | 340 | +* convert h264 stream data to rtmp packet. |
341 | +* @param h264_raw_data the input h264 raw data, a encoded h.264 I/P/B frame data. | ||
342 | +* @paam h264_raw_size the size of h264 raw data. | ||
343 | +* @param dts the dts of h.264 raw data. | ||
344 | +* @param pts the pts of h.264 raw data. | ||
345 | +* @param prtmp_data the output rtmp format packet, which can be send by srs_write_packet. | ||
346 | +* @param prtmp_size the size of rtmp packet, for srs_write_packet. | ||
347 | +* @param ptimestamp the timestamp of rtmp packet, for srs_write_packet. | ||
348 | +* @remark, user should free the h264_raw_data. | ||
349 | +* @remark, user should free the prtmp_data if success. | ||
350 | +* | ||
351 | +* @return 0, success; otherswise, failed. | ||
351 | */ | 352 | */ |
352 | extern int srs_h264_to_rtmp( | 353 | extern int srs_h264_to_rtmp( |
353 | char* h264_raw_data, int h264_raw_size, u_int32_t dts, u_int32_t pts, | 354 | char* h264_raw_data, int h264_raw_size, u_int32_t dts, u_int32_t pts, |
354 | char** prtmp_data, int* prtmp_size, u_int32_t* ptimestamp | 355 | char** prtmp_data, int* prtmp_size, u_int32_t* ptimestamp |
355 | ); | 356 | ); |
357 | +/** | ||
358 | +* whether h264 raw data starts with the annexb, | ||
359 | +* which bytes sequence matches N[00] 00 00 01, where N>=0. | ||
360 | +* @param h264_raw_data the input h264 raw data, a encoded h.264 I/P/B frame data. | ||
361 | +* @paam h264_raw_size the size of h264 raw data. | ||
362 | +* @param pnb_start_code output the size of start code, must >=3. | ||
363 | +* NULL to ignore. | ||
364 | +* | ||
365 | +* @return 0 false; otherwise, true. | ||
366 | +*/ | ||
367 | +extern int srs_h264_startswith_annexb( | ||
368 | + char* h264_raw_data, int h264_raw_size, | ||
369 | + int* pnb_start_code | ||
370 | +); | ||
356 | 371 | ||
357 | #ifdef __cplusplus | 372 | #ifdef __cplusplus |
358 | } | 373 | } |
@@ -28,6 +28,7 @@ using namespace std; | @@ -28,6 +28,7 @@ using namespace std; | ||
28 | 28 | ||
29 | #include <srs_kernel_log.hpp> | 29 | #include <srs_kernel_log.hpp> |
30 | #include <srs_kernel_utility.hpp> | 30 | #include <srs_kernel_utility.hpp> |
31 | +#include <srs_kernel_stream.hpp> | ||
31 | 32 | ||
32 | void srs_discovery_tc_url( | 33 | void srs_discovery_tc_url( |
33 | string tcUrl, | 34 | string tcUrl, |
@@ -155,3 +156,32 @@ bool srs_bytes_equals(void* pa, void* pb, int size) | @@ -155,3 +156,32 @@ bool srs_bytes_equals(void* pa, void* pb, int size) | ||
155 | return true; | 156 | return true; |
156 | } | 157 | } |
157 | 158 | ||
159 | +bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code) | ||
160 | +{ | ||
161 | + char* bytes = stream->data() + stream->pos(); | ||
162 | + char* p = bytes; | ||
163 | + | ||
164 | + for (;;) { | ||
165 | + if (!stream->require(p - bytes + 3)) { | ||
166 | + return false; | ||
167 | + } | ||
168 | + | ||
169 | + // not match | ||
170 | + if (p[0] != 0x00 || p[1] != 0x00) { | ||
171 | + return false; | ||
172 | + } | ||
173 | + | ||
174 | + // match N[00] 00 00 01, where N>=0 | ||
175 | + if (p[2] == 0x01) { | ||
176 | + if (pnb_start_code) { | ||
177 | + *pnb_start_code = (int)(p - bytes) + 3; | ||
178 | + } | ||
179 | + return true; | ||
180 | + } | ||
181 | + | ||
182 | + p++; | ||
183 | + } | ||
184 | + | ||
185 | + return false; | ||
186 | +} | ||
187 | + |
@@ -33,6 +33,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -33,6 +33,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
33 | 33 | ||
34 | #include <srs_kernel_consts.hpp> | 34 | #include <srs_kernel_consts.hpp> |
35 | 35 | ||
36 | +class SrsStream; | ||
37 | + | ||
36 | /** | 38 | /** |
37 | * parse the tcUrl, output the schema, host, vhost, app and port. | 39 | * parse the tcUrl, output the schema, host, vhost, app and port. |
38 | * @param tcUrl, the input tcUrl, for example, | 40 | * @param tcUrl, the input tcUrl, for example, |
@@ -85,5 +87,14 @@ extern std::string srs_generate_tc_url( | @@ -85,5 +87,14 @@ extern std::string srs_generate_tc_url( | ||
85 | */ | 87 | */ |
86 | extern bool srs_bytes_equals(void* pa, void* pb, int size); | 88 | extern bool srs_bytes_equals(void* pa, void* pb, int size); |
87 | 89 | ||
90 | +/** | ||
91 | +* whether stream starts with the avc NALU in "AnnexB" | ||
92 | +* from H.264-AVC-ISO_IEC_14496-10.pdf, page 211. | ||
93 | +* start code must be "N[00] 00 00 01" where N>=0 | ||
94 | +* @param pnb_start_code output the size of start code, must >=3. | ||
95 | +* NULL to ignore. | ||
96 | +*/ | ||
97 | +extern bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code = NULL); | ||
98 | + | ||
88 | #endif | 99 | #endif |
89 | 100 |
-
请 注册 或 登录 后发表评论