winlin

srs-librtmp: implements the read packet.

@@ -31,11 +31,16 @@ int main(int argc, char** argv) @@ -31,11 +31,16 @@ int main(int argc, char** argv)
31 { 31 {
32 srs_rtmp_t rtmp; 32 srs_rtmp_t rtmp;
33 33
  34 + // packet data
  35 + int type, size;
  36 + u_int32_t timestamp;
  37 + char* data;
  38 +
34 printf("suck rtmp stream like rtmpdump\n"); 39 printf("suck rtmp stream like rtmpdump\n");
35 printf("srs(simple-rtmp-server) client librtmp library.\n"); 40 printf("srs(simple-rtmp-server) client librtmp library.\n");
36 printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); 41 printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision());
37 42
38 - rtmp = srs_rtmp_create("rtmp://127.0.0.1:1935/live/show?vhost=__defaultVhost__/livestream"); 43 + rtmp = srs_rtmp_create("rtmp://127.0.0.1:1935/live?vhost=__defaultVhost__/livestream");
39 44
40 if (srs_simple_handshake(rtmp) != 0) { 45 if (srs_simple_handshake(rtmp) != 0) {
41 printf("simple handshake failed.\n"); 46 printf("simple handshake failed.\n");
@@ -55,6 +60,15 @@ int main(int argc, char** argv) @@ -55,6 +60,15 @@ int main(int argc, char** argv)
55 } 60 }
56 printf("play stream success\n"); 61 printf("play stream success\n");
57 62
  63 + for (;;) {
  64 + if (srs_read_packet(rtmp, &type, &timestamp, &data, &size) != 0) {
  65 + goto rtmp_destroy;
  66 + }
  67 + printf("got packet: type=%s, time=%d, size=%d\n", srs_type2string(type), timestamp, size);
  68 +
  69 + free(data);
  70 + }
  71 +
58 rtmp_destroy: 72 rtmp_destroy:
59 srs_rtmp_destroy(rtmp); 73 srs_rtmp_destroy(rtmp);
60 74
@@ -33,6 +33,8 @@ using namespace std; @@ -33,6 +33,8 @@ using namespace std;
33 #include <srs_lib_simple_socket.hpp> 33 #include <srs_lib_simple_socket.hpp>
34 #include <srs_kernel_log.hpp> 34 #include <srs_kernel_log.hpp>
35 #include <srs_protocol_utility.hpp> 35 #include <srs_protocol_utility.hpp>
  36 +#include <srs_core_autofree.hpp>
  37 +#include <srs_protocol_rtmp_stack.hpp>
36 38
37 // if user want to define log, define the folowing macro. 39 // if user want to define log, define the folowing macro.
38 #ifndef SRS_RTMP_USER_DEFINED_LOG 40 #ifndef SRS_RTMP_USER_DEFINED_LOG
@@ -256,6 +258,79 @@ int srs_publish_stream(srs_rtmp_t rtmp) @@ -256,6 +258,79 @@ int srs_publish_stream(srs_rtmp_t rtmp)
256 return ret; 258 return ret;
257 } 259 }
258 260
  261 +const char* srs_type2string(int type)
  262 +{
  263 + switch (type) {
  264 + case SRS_RTMP_TYPE_AUDIO: return "Audio";
  265 + case SRS_RTMP_TYPE_VIDEO: return "Video";
  266 + case SRS_RTMP_TYPE_SCRIPT: return "Data";
  267 + default: return "Unknown";
  268 + }
  269 +
  270 + return "Unknown";
  271 +}
  272 +
  273 +int srs_read_packet(srs_rtmp_t rtmp, int* type, u_int32_t* timestamp, char** data, int* size)
  274 +{
  275 + *type = 0;
  276 + *timestamp = 0;
  277 + *data = NULL;
  278 + *size = 0;
  279 +
  280 + int ret = ERROR_SUCCESS;
  281 +
  282 + srs_assert(rtmp != NULL);
  283 + Context* context = (Context*)rtmp;
  284 +
  285 + for (;;) {
  286 + SrsCommonMessage* msg = NULL;
  287 + if ((ret = context->rtmp->recv_message(&msg)) != ERROR_SUCCESS) {
  288 + return ret;
  289 + }
  290 + if (!msg) {
  291 + continue;
  292 + }
  293 +
  294 + SrsAutoFree(SrsCommonMessage, msg, false);
  295 +
  296 + if (msg->header.is_audio()) {
  297 + *type = SRS_RTMP_TYPE_AUDIO;
  298 + *timestamp = (u_int32_t)msg->header.timestamp;
  299 + *data = (char*)msg->payload;
  300 + *size = (int)msg->size;
  301 + // detach bytes from packet.
  302 + msg->payload = NULL;
  303 + } else if (msg->header.is_video()) {
  304 + *type = SRS_RTMP_TYPE_VIDEO;
  305 + *timestamp = (u_int32_t)msg->header.timestamp;
  306 + *data = (char*)msg->payload;
  307 + *size = (int)msg->size;
  308 + // detach bytes from packet.
  309 + msg->payload = NULL;
  310 + } else if (msg->header.is_amf0_data() || msg->header.is_amf3_data()) {
  311 + *type = SRS_RTMP_TYPE_SCRIPT;
  312 + *data = (char*)msg->payload;
  313 + *size = (int)msg->size;
  314 + // detach bytes from packet.
  315 + msg->payload = NULL;
  316 + } else {
  317 + // ignore and continue
  318 + continue;
  319 + }
  320 +
  321 + // got expected message.
  322 + break;
  323 + }
  324 +
  325 + return ret;
  326 +}
  327 +
  328 +int srs_write_packet(srs_rtmp_t rtmp, int type, u_int32_t timestamp, char* data, int size)
  329 +{
  330 + int ret = ERROR_SUCCESS;
  331 + return ret;
  332 +}
  333 +
259 int srs_ssl_enabled() 334 int srs_ssl_enabled()
260 { 335 {
261 #ifndef SRS_SSL 336 #ifndef SRS_SSL
@@ -28,6 +28,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -28,6 +28,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include <srs_librtmp.h> 28 #include <srs_librtmp.h>
29 */ 29 */
30 30
  31 +#include <sys/types.h>
  32 +
31 /** 33 /**
32 * srs-librtmp is a librtmp like library, 34 * srs-librtmp is a librtmp like library,
33 * used to play/publish rtmp stream from/to rtmp server. 35 * used to play/publish rtmp stream from/to rtmp server.
@@ -101,6 +103,43 @@ int srs_play_stream(srs_rtmp_t rtmp); @@ -101,6 +103,43 @@ int srs_play_stream(srs_rtmp_t rtmp);
101 int srs_publish_stream(srs_rtmp_t rtmp); 103 int srs_publish_stream(srs_rtmp_t rtmp);
102 104
103 /** 105 /**
  106 +* E.4.1 FLV Tag, page 75
  107 +*/
  108 +// 8 = audio
  109 +#define SRS_RTMP_TYPE_AUDIO 8
  110 +// 9 = video
  111 +#define SRS_RTMP_TYPE_VIDEO 9
  112 +// 18 = script data
  113 +#define SRS_RTMP_TYPE_SCRIPT 18
  114 +/**
  115 +* convert the flv tag type to string.
  116 +* SRS_RTMP_TYPE_AUDIO to "Audio"
  117 +* SRS_RTMP_TYPE_VIDEO to "Video"
  118 +* SRS_RTMP_TYPE_SCRIPT to "Data"
  119 +* otherwise, "Unknown"
  120 +*/
  121 +const char* srs_type2string(int type);
  122 +/**
  123 +* read a audio/video/script-data packet from rtmp stream.
  124 +* @param type, output the packet type, macros:
  125 +* SRS_RTMP_TYPE_AUDIO, FlvTagAudio
  126 +* SRS_RTMP_TYPE_VIDEO, FlvTagVideo
  127 +* SRS_RTMP_TYPE_SCRIPT, FlvTagScript
  128 +* @param timestamp, in ms, overflow in 50days
  129 +* @param data, the packet data, according to type:
  130 +* FlvTagAudio, @see "E.4.2.1 AUDIODATA"
  131 +* FlvTagVideo, @see "E.4.3.1 VIDEODATA"
  132 +* FlvTagScript, @see "E.4.4.1 SCRIPTDATA"
  133 +* @param size, size of packet.
  134 +* @return the error code. 0 for success; otherwise, error.
  135 +*
  136 +* @remark: for read, user must free the data.
  137 +* @remark: for write, user should never free the data, even if error.
  138 +*/
  139 +int srs_read_packet(srs_rtmp_t rtmp, int* type, u_int32_t* timestamp, char** data, int* size);
  140 +int srs_write_packet(srs_rtmp_t rtmp, int type, u_int32_t timestamp, char* data, int size);
  141 +
  142 +/**
104 * whether srs is compiled with ssl, 143 * whether srs is compiled with ssl,
105 * that is, compile srs with ssl: ./configure --with-ssl,. 144 * that is, compile srs with ssl: ./configure --with-ssl,.
106 * if no ssl, complex handshake always error. 145 * if no ssl, complex handshake always error.
@@ -1025,6 +1025,14 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz @@ -1025,6 +1025,14 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
1025 1025
1026 // ffmpeg/librtmp may donot send this filed, need to detect the value. 1026 // ffmpeg/librtmp may donot send this filed, need to detect the value.
1027 // @see also: http://blog.csdn.net/win_lin/article/details/13363699 1027 // @see also: http://blog.csdn.net/win_lin/article/details/13363699
  1028 + // the extended-timestamp must be unsigned-int,
  1029 + // 24bits timestamp: 0xffffff = 16777215ms = 16777.215s = 4.66h
  1030 + // 32bits timestamp: 0xffffffff = 4294967295ms = 4294967.295s = 1193.046h = 49.71d
  1031 + // because the rtmp protocol says the 32bits timestamp is about "50 days":
  1032 + // 3. Byte Order, Alignment, and Time Format
  1033 + // Because timestamps are generally only 32 bits long, they will roll
  1034 + // over after fewer than 50 days.
  1035 + // so, use u_int32_t is right.
1028 u_int32_t timestamp = 0x00; 1036 u_int32_t timestamp = 0x00;
1029 char* pp = (char*)&timestamp; 1037 char* pp = (char*)&timestamp;
1030 pp[3] = *p++; 1038 pp[3] = *p++;