winlin

Merge branch 'srs.master'

@@ -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