diff --git a/trunk/research/librtmp/srs_h264_raw_publish.c b/trunk/research/librtmp/srs_h264_raw_publish.c index df1a76c40..b0b6d7379 100644 --- a/trunk/research/librtmp/srs_h264_raw_publish.c +++ b/trunk/research/librtmp/srs_h264_raw_publish.c @@ -65,6 +65,27 @@ int main(int argc, char** argv) goto rtmp_destroy; } + off_t file_size = lseek(raw_fd, 0, SEEK_END); + if (file_size <= 0) { + srs_trace("h264 raw file %s empty.", raw_file); + goto rtmp_destroy; + } + srs_trace("read entirely h264 raw file, size=%dKB", (int)(file_size / 1024)); + + char* h264_raw = (char*)malloc(file_size); + if (!h264_raw) { + srs_trace("alloc raw buffer failed for file %s.", raw_file); + goto rtmp_destroy; + } + + lseek(raw_fd, 0, SEEK_SET); + ssize_t nb_read = 0; + if ((nb_read = read(raw_fd, h264_raw, file_size)) != file_size) { + srs_trace("buffer %s failed, expect=%dKB, actual=%dKB.", + raw_file, (int)(file_size / 1024), (int)(nb_read / 1024)); + goto rtmp_destroy; + } + // connect rtmp context srs_rtmp_t rtmp = srs_rtmp_create(rtmp_url); @@ -86,10 +107,13 @@ int main(int argc, char** argv) } srs_trace("publish stream success"); + // @remark, the dts and pts if read from device, for instance, the encode lib, + // so we assume the fps is 25, and each h264 frame is 1000ms/25fps=40ms/f. + u_int32_t fps = 25; u_int32_t dts = 0; u_int32_t pts = 0; for (;;) { - // read from file, or get h264 raw data from device, whatever. + // get h264 raw data from device, whatever. int size = 4096; char* data = (char*)malloc(4096); if ((size = read(raw_fd, data, size)) < 0) { @@ -101,26 +125,37 @@ int main(int argc, char** argv) goto rtmp_destroy; } + // convert the h264 packet to rtmp packet. char* rtmp_data = NULL; int rtmp_size = 0; u_int32_t timestamp = 0; - if (srs_h264_to_rtmp(data, size, dts, pts, &rtmp_data, &rtmp_size, ×tamp) < 0) { + if (srs_h264_to_rtmp(data, size, dts, pts, &rtmp_data, &rtmp_size, ×tamp) != 0) { srs_trace("h264 raw data to rtmp data failed."); goto rtmp_destroy; } + // send out the rtmp packet. int type = SRS_RTMP_TYPE_VIDEO; if (srs_write_packet(rtmp, type, timestamp, rtmp_data, rtmp_size) != 0) { goto rtmp_destroy; } - srs_trace("sent packet: type=%s, time=%d, size=%d", srs_type2string(type), timestamp, rtmp_size); + srs_trace("sent packet: type=%s, time=%d, size=%d, fps=%d", + srs_type2string(type), timestamp, rtmp_size, fps); + + // @remark, please get the dts and pts from device, + // we assume there is no B frame, and the fps can guess the fps and dts, + // while the dts and pts must read from encode lib or device. + dts += 1000 / fps; + pts = dts; - usleep(40 * 1000); + // @remark, when use encode device, it not need to sleep. + usleep(1000 / fps * 1000); } rtmp_destroy: srs_rtmp_destroy(rtmp); close(raw_fd); + free(h264_raw); return 0; } diff --git a/trunk/src/libs/srs_librtmp.hpp b/trunk/src/libs/srs_librtmp.hpp index a4f770907..f6e988fae 100644 --- a/trunk/src/libs/srs_librtmp.hpp +++ b/trunk/src/libs/srs_librtmp.hpp @@ -54,6 +54,7 @@ typedef void* srs_rtmp_t; * create/destroy a rtmp protocol stack. * @url rtmp url, for example: * rtmp://localhost/live/livestream +* * @return a rtmp handler, or NULL if error occured. */ extern srs_rtmp_t srs_rtmp_create(const char* url); @@ -63,6 +64,8 @@ extern srs_rtmp_t srs_rtmp_create(const char* url); * rtmp://localhost/live * @remark this is used to create application connection-oriented, * for example, the bandwidth client used this, no stream specified. +* +* @return a rtmp handler, or NULL if error occured. */ extern srs_rtmp_t srs_rtmp_create2(const char* url); /** @@ -81,7 +84,8 @@ extern void srs_rtmp_destroy(srs_rtmp_t rtmp); * category: publish/play * previous: rtmp-create * next: connect-app -* @return 0, success; otherwise, failed. +* +* @return 0, success; otherswise, failed. */ /** * simple handshake specifies in rtmp 1.0, @@ -107,7 +111,8 @@ extern int __srs_do_simple_handshake(srs_rtmp_t rtmp); * category: publish/play * previous: handshake * next: publish or play -* @return 0, success; otherwise, failed. +* +* @return 0, success; otherswise, failed. */ extern int srs_connect_app(srs_rtmp_t rtmp); @@ -121,6 +126,8 @@ extern int srs_connect_app(srs_rtmp_t rtmp); * @param srs_version, 32bytes, server version. * @param srs_id, int, debug info, client id in server log. * @param srs_pid, int, debug info, server pid in log. +* +* @return 0, success; otherswise, failed. */ extern int srs_connect_app2(srs_rtmp_t rtmp, char srs_server_ip[128], char srs_server[128], char srs_primary_authors[128], @@ -157,6 +164,8 @@ extern int srs_publish_stream(srs_rtmp_t rtmp); * @param publish_bytes, output the publish/upload bytes. * @param play_duration, output the play/download test duration, in ms. * @param publish_duration, output the publish/upload test duration, in ms. +* +* @return 0, success; otherswise, failed. */ extern int srs_bandwidth_check(srs_rtmp_t rtmp, int64_t* start_time, int64_t* end_time, @@ -200,6 +209,8 @@ extern const char* srs_type2string(int type); * * @remark: for read, user must free the data. * @remark: for write, user should never free the data, even if error. +* +* @return 0, success; otherswise, failed. */ extern int srs_read_packet(srs_rtmp_t rtmp, int* type, u_int32_t* timestamp, char** data, int* size @@ -334,6 +345,9 @@ convert h264 stream data to rtmp packet. @param prtmp_data the output rtmp format packet, which can be send by srs_write_packet. @param prtmp_size the size of rtmp packet, for srs_write_packet. @param ptimestamp the timestamp of rtmp packet, for srs_write_packet. +@remark, user should never free the h264_raw_data. +@remark, user should free the prtmp_data if success. +@return 0, success; otherswise, failed. */ extern int srs_h264_to_rtmp( char* h264_raw_data, int h264_raw_size, u_int32_t dts, u_int32_t pts,