diff --git a/trunk/research/librtmp/srs_play.c b/trunk/research/librtmp/srs_play.c index 586d8626d..ab6142df0 100644 --- a/trunk/research/librtmp/srs_play.c +++ b/trunk/research/librtmp/srs_play.c @@ -31,11 +31,16 @@ int main(int argc, char** argv) { srs_rtmp_t rtmp; + // packet data + int type, size; + u_int32_t timestamp; + char* data; + printf("suck rtmp stream like rtmpdump\n"); printf("srs(simple-rtmp-server) client librtmp library.\n"); printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); - rtmp = srs_rtmp_create("rtmp://127.0.0.1:1935/live/show?vhost=__defaultVhost__/livestream"); + rtmp = srs_rtmp_create("rtmp://127.0.0.1:1935/live?vhost=__defaultVhost__/livestream"); if (srs_simple_handshake(rtmp) != 0) { printf("simple handshake failed.\n"); @@ -55,6 +60,15 @@ int main(int argc, char** argv) } printf("play stream success\n"); + for (;;) { + if (srs_read_packet(rtmp, &type, ×tamp, &data, &size) != 0) { + goto rtmp_destroy; + } + printf("got packet: type=%s, time=%d, size=%d\n", srs_type2string(type), timestamp, size); + + free(data); + } + rtmp_destroy: srs_rtmp_destroy(rtmp); diff --git a/trunk/src/libs/srs_librtmp.cpp b/trunk/src/libs/srs_librtmp.cpp index 1683299a2..15ad38459 100644 --- a/trunk/src/libs/srs_librtmp.cpp +++ b/trunk/src/libs/srs_librtmp.cpp @@ -33,6 +33,8 @@ using namespace std; #include #include #include +#include +#include // if user want to define log, define the folowing macro. #ifndef SRS_RTMP_USER_DEFINED_LOG @@ -256,6 +258,79 @@ int srs_publish_stream(srs_rtmp_t rtmp) return ret; } +const char* srs_type2string(int type) +{ + switch (type) { + case SRS_RTMP_TYPE_AUDIO: return "Audio"; + case SRS_RTMP_TYPE_VIDEO: return "Video"; + case SRS_RTMP_TYPE_SCRIPT: return "Data"; + default: return "Unknown"; + } + + return "Unknown"; +} + +int srs_read_packet(srs_rtmp_t rtmp, int* type, u_int32_t* timestamp, char** data, int* size) +{ + *type = 0; + *timestamp = 0; + *data = NULL; + *size = 0; + + int ret = ERROR_SUCCESS; + + srs_assert(rtmp != NULL); + Context* context = (Context*)rtmp; + + for (;;) { + SrsCommonMessage* msg = NULL; + if ((ret = context->rtmp->recv_message(&msg)) != ERROR_SUCCESS) { + return ret; + } + if (!msg) { + continue; + } + + SrsAutoFree(SrsCommonMessage, msg, false); + + if (msg->header.is_audio()) { + *type = SRS_RTMP_TYPE_AUDIO; + *timestamp = (u_int32_t)msg->header.timestamp; + *data = (char*)msg->payload; + *size = (int)msg->size; + // detach bytes from packet. + msg->payload = NULL; + } else if (msg->header.is_video()) { + *type = SRS_RTMP_TYPE_VIDEO; + *timestamp = (u_int32_t)msg->header.timestamp; + *data = (char*)msg->payload; + *size = (int)msg->size; + // detach bytes from packet. + msg->payload = NULL; + } else if (msg->header.is_amf0_data() || msg->header.is_amf3_data()) { + *type = SRS_RTMP_TYPE_SCRIPT; + *data = (char*)msg->payload; + *size = (int)msg->size; + // detach bytes from packet. + msg->payload = NULL; + } else { + // ignore and continue + continue; + } + + // got expected message. + break; + } + + return ret; +} + +int srs_write_packet(srs_rtmp_t rtmp, int type, u_int32_t timestamp, char* data, int size) +{ + int ret = ERROR_SUCCESS; + return ret; +} + int srs_ssl_enabled() { #ifndef SRS_SSL diff --git a/trunk/src/libs/srs_librtmp.hpp b/trunk/src/libs/srs_librtmp.hpp index 2d88d41a5..1734e39e6 100644 --- a/trunk/src/libs/srs_librtmp.hpp +++ b/trunk/src/libs/srs_librtmp.hpp @@ -28,6 +28,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include */ +#include + /** * srs-librtmp is a librtmp like library, * used to play/publish rtmp stream from/to rtmp server. @@ -100,6 +102,43 @@ int srs_play_stream(srs_rtmp_t rtmp); */ int srs_publish_stream(srs_rtmp_t rtmp); +/** +* E.4.1 FLV Tag, page 75 +*/ +// 8 = audio +#define SRS_RTMP_TYPE_AUDIO 8 +// 9 = video +#define SRS_RTMP_TYPE_VIDEO 9 +// 18 = script data +#define SRS_RTMP_TYPE_SCRIPT 18 +/** +* convert the flv tag type to string. +* SRS_RTMP_TYPE_AUDIO to "Audio" +* SRS_RTMP_TYPE_VIDEO to "Video" +* SRS_RTMP_TYPE_SCRIPT to "Data" +* otherwise, "Unknown" +*/ +const char* srs_type2string(int type); +/** +* read a audio/video/script-data packet from rtmp stream. +* @param type, output the packet type, macros: +* SRS_RTMP_TYPE_AUDIO, FlvTagAudio +* SRS_RTMP_TYPE_VIDEO, FlvTagVideo +* SRS_RTMP_TYPE_SCRIPT, FlvTagScript +* @param timestamp, in ms, overflow in 50days +* @param data, the packet data, according to type: +* FlvTagAudio, @see "E.4.2.1 AUDIODATA" +* FlvTagVideo, @see "E.4.3.1 VIDEODATA" +* FlvTagScript, @see "E.4.4.1 SCRIPTDATA" +* @param size, size of packet. +* @return the error code. 0 for success; otherwise, error. +* +* @remark: for read, user must free the data. +* @remark: for write, user should never free the data, even if error. +*/ +int srs_read_packet(srs_rtmp_t rtmp, int* type, u_int32_t* timestamp, char** data, int* size); +int srs_write_packet(srs_rtmp_t rtmp, int type, u_int32_t timestamp, char* data, int size); + /** * whether srs is compiled with ssl, * that is, compile srs with ssl: ./configure --with-ssl,. diff --git a/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp b/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp index e2b99c70a..575caf1b5 100644 --- a/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp +++ b/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp @@ -1025,6 +1025,14 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz // ffmpeg/librtmp may donot send this filed, need to detect the value. // @see also: http://blog.csdn.net/win_lin/article/details/13363699 + // the extended-timestamp must be unsigned-int, + // 24bits timestamp: 0xffffff = 16777215ms = 16777.215s = 4.66h + // 32bits timestamp: 0xffffffff = 4294967295ms = 4294967.295s = 1193.046h = 49.71d + // because the rtmp protocol says the 32bits timestamp is about "50 days": + // 3. Byte Order, Alignment, and Time Format + // Because timestamps are generally only 32 bits long, they will roll + // over after fewer than 50 days. + // so, use u_int32_t is right. u_int32_t timestamp = 0x00; char* pp = (char*)×tamp; pp[3] = *p++;