add api convert h264 to rtmp packet, for bug #66

pull/133/head
winlin 10 years ago
parent e4af098d06
commit 1c237a821a

@ -28,6 +28,11 @@ gcc srs_h264_raw_publish.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_h
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
// for open h264 raw file.
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "../../objs/include/srs_librtmp.h" #include "../../objs/include/srs_librtmp.h"
#define srs_trace(msg, ...) printf(msg, ##__VA_ARGS__);printf("\n") #define srs_trace(msg, ...) printf(msg, ##__VA_ARGS__);printf("\n")
@ -40,7 +45,7 @@ int main(int argc, char** argv)
if (argc <= 2) { if (argc <= 2) {
srs_trace("Usage: %s <h264_raw_file> <rtmp_publish_url>", argv[0]); srs_trace("Usage: %s <h264_raw_file> <rtmp_publish_url>", argv[0]);
srs_trace(" h264_raw_file: the raw h264 steam file."); srs_trace(" h264_raw_file: the h264 raw steam file.");
srs_trace(" rtmp_publish_url: the rtmp publish url."); srs_trace(" rtmp_publish_url: the rtmp publish url.");
srs_trace("For example:"); srs_trace("For example:");
srs_trace(" %s ./720p.h264.raw rtmp://127.0.0.1:1935/live/livestream", argv[0]); srs_trace(" %s ./720p.h264.raw rtmp://127.0.0.1:1935/live/livestream", argv[0]);
@ -53,6 +58,14 @@ int main(int argc, char** argv)
const char* rtmp_url = argv[2]; const char* rtmp_url = argv[2];
srs_trace("raw_file=%s, rtmp_url=%s", raw_file, rtmp_url); srs_trace("raw_file=%s, rtmp_url=%s", raw_file, rtmp_url);
// open file
int raw_fd = open(raw_file, O_RDONLY);
if (raw_fd < 0) {
srs_trace("open h264 raw file %s failed.", raw_fd);
goto rtmp_destroy;
}
// connect rtmp context
srs_rtmp_t rtmp = srs_rtmp_create(rtmp_url); srs_rtmp_t rtmp = srs_rtmp_create(rtmp_url);
if (srs_simple_handshake(rtmp) != 0) { if (srs_simple_handshake(rtmp) != 0) {
@ -73,23 +86,42 @@ int main(int argc, char** argv)
} }
srs_trace("publish stream success"); srs_trace("publish stream success");
u_int32_t timestamp = 0; u_int32_t dts = 0;
u_int32_t pts = 0;
for (;;) { for (;;) {
int type = SRS_RTMP_TYPE_VIDEO; // read from file, or get h264 raw data from device, whatever.
timestamp += 40;
int size = 4096; int size = 4096;
char* data = (char*)malloc(4096); char* data = (char*)malloc(4096);
if ((size = read(raw_fd, data, size)) < 0) {
srs_trace("read h264 raw data failed. nread=%d", size);
goto rtmp_destroy;
}
if (size == 0) {
srs_trace("publish h264 raw data completed.");
goto rtmp_destroy;
}
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, &timestamp) < 0) {
srs_trace("h264 raw data to rtmp data failed.");
goto rtmp_destroy;
}
if (srs_write_packet(rtmp, type, timestamp, data, size) != 0) { int type = SRS_RTMP_TYPE_VIDEO;
if (srs_write_packet(rtmp, type, timestamp, rtmp_data, rtmp_size) != 0) {
goto rtmp_destroy; goto rtmp_destroy;
} }
srs_trace("sent packet: type=%s, time=%d, size=%d", srs_type2string(type), timestamp, size); srs_trace("sent packet: type=%s, time=%d, size=%d", srs_type2string(type), timestamp, rtmp_size);
usleep(40 * 1000); usleep(40 * 1000);
} }
rtmp_destroy: rtmp_destroy:
srs_rtmp_destroy(rtmp); srs_rtmp_destroy(rtmp);
close(raw_fd);
return 0; return 0;
} }

@ -996,6 +996,13 @@ char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize)
return any->human_print(pdata, psize); return any->human_print(pdata, psize);
} }
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)
{
*prtmp_data = h264_raw_data;
*prtmp_size = h264_raw_size;
return 0;
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -42,6 +42,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
extern "C"{ extern "C"{
#endif #endif
/*************************************************************
**************************************************************
* RTMP protocol context
**************************************************************
*************************************************************/
// the RTMP handler. // the RTMP handler.
typedef void* srs_rtmp_t; typedef void* srs_rtmp_t;
@ -51,7 +56,7 @@ typedef void* srs_rtmp_t;
* rtmp://localhost/live/livestream * rtmp://localhost/live/livestream
* @return a rtmp handler, or NULL if error occured. * @return a rtmp handler, or NULL if error occured.
*/ */
srs_rtmp_t srs_rtmp_create(const char* url); extern srs_rtmp_t srs_rtmp_create(const char* url);
/** /**
* create rtmp with url, used for connection specified application. * create rtmp with url, used for connection specified application.
* @param url the tcUrl, for exmple: * @param url the tcUrl, for exmple:
@ -59,13 +64,18 @@ srs_rtmp_t srs_rtmp_create(const char* url);
* @remark this is used to create application connection-oriented, * @remark this is used to create application connection-oriented,
* for example, the bandwidth client used this, no stream specified. * for example, the bandwidth client used this, no stream specified.
*/ */
srs_rtmp_t srs_rtmp_create2(const char* url); extern srs_rtmp_t srs_rtmp_create2(const char* url);
/** /**
* close and destroy the rtmp stack. * close and destroy the rtmp stack.
* @remark, user should use the rtmp again. * @remark, user should use the rtmp again.
*/ */
void srs_rtmp_destroy(srs_rtmp_t rtmp); extern void srs_rtmp_destroy(srs_rtmp_t rtmp);
/*************************************************************
**************************************************************
* RTMP protocol stack
**************************************************************
*************************************************************/
/** /**
* connect and handshake with server * connect and handshake with server
* category: publish/play * category: publish/play
@ -84,13 +94,13 @@ void srs_rtmp_destroy(srs_rtmp_t rtmp);
* __srs_do_simple_handshake() * __srs_do_simple_handshake()
* user can use these functions if needed. * user can use these functions if needed.
*/ */
int srs_simple_handshake(srs_rtmp_t rtmp); extern int srs_simple_handshake(srs_rtmp_t rtmp);
// parse uri, create socket, resolve host // parse uri, create socket, resolve host
int __srs_dns_resolve(srs_rtmp_t rtmp); extern int __srs_dns_resolve(srs_rtmp_t rtmp);
// connect socket to server // connect socket to server
int __srs_connect_server(srs_rtmp_t rtmp); extern int __srs_connect_server(srs_rtmp_t rtmp);
// do simple handshake over socket. // do simple handshake over socket.
int __srs_do_simple_handshake(srs_rtmp_t rtmp); extern int __srs_do_simple_handshake(srs_rtmp_t rtmp);
/** /**
* connect to rtmp vhost/app * connect to rtmp vhost/app
@ -99,7 +109,7 @@ int __srs_do_simple_handshake(srs_rtmp_t rtmp);
* next: publish or play * next: publish or play
* @return 0, success; otherwise, failed. * @return 0, success; otherwise, failed.
*/ */
int srs_connect_app(srs_rtmp_t rtmp); extern int srs_connect_app(srs_rtmp_t rtmp);
/** /**
* connect to server, get the debug srs info. * connect to server, get the debug srs info.
@ -112,7 +122,7 @@ int srs_connect_app(srs_rtmp_t rtmp);
* @param srs_id, int, debug info, client id in server log. * @param srs_id, int, debug info, client id in server log.
* @param srs_pid, int, debug info, server pid in log. * @param srs_pid, int, debug info, server pid in log.
*/ */
int srs_connect_app2(srs_rtmp_t rtmp, extern int srs_connect_app2(srs_rtmp_t rtmp,
char srs_server_ip[128], char srs_server[128], char srs_primary_authors[128], char srs_server_ip[128], char srs_server[128], char srs_primary_authors[128],
char srs_version[32], int* srs_id, int* srs_pid char srs_version[32], int* srs_id, int* srs_pid
); );
@ -124,7 +134,7 @@ int srs_connect_app2(srs_rtmp_t rtmp,
* next: destroy * next: destroy
* @return 0, success; otherwise, failed. * @return 0, success; otherwise, failed.
*/ */
int srs_play_stream(srs_rtmp_t rtmp); extern int srs_play_stream(srs_rtmp_t rtmp);
/** /**
* publish a live stream. * publish a live stream.
@ -133,7 +143,7 @@ int srs_play_stream(srs_rtmp_t rtmp);
* next: destroy * next: destroy
* @return 0, success; otherwise, failed. * @return 0, success; otherwise, failed.
*/ */
int srs_publish_stream(srs_rtmp_t rtmp); extern int srs_publish_stream(srs_rtmp_t rtmp);
/** /**
* do bandwidth check with srs server. * do bandwidth check with srs server.
@ -148,7 +158,7 @@ int srs_publish_stream(srs_rtmp_t rtmp);
* @param play_duration, output the play/download test duration, in ms. * @param play_duration, output the play/download test duration, in ms.
* @param publish_duration, output the publish/upload test duration, in ms. * @param publish_duration, output the publish/upload test duration, in ms.
*/ */
int srs_bandwidth_check(srs_rtmp_t rtmp, extern int srs_bandwidth_check(srs_rtmp_t rtmp,
int64_t* start_time, int64_t* end_time, int64_t* start_time, int64_t* end_time,
int* play_kbps, int* publish_kbps, int* play_kbps, int* publish_kbps,
int* play_bytes, int* publish_bytes, int* play_bytes, int* publish_bytes,
@ -173,7 +183,7 @@ int srs_bandwidth_check(srs_rtmp_t rtmp,
* @remark user never free the return char*, * @remark user never free the return char*,
* it's static shared const string. * it's static shared const string.
*/ */
const char* srs_type2string(int type); extern const char* srs_type2string(int type);
/** /**
* read a audio/video/script-data packet from rtmp stream. * read a audio/video/script-data packet from rtmp stream.
* @param type, output the packet type, macros: * @param type, output the packet type, macros:
@ -191,113 +201,144 @@ const char* srs_type2string(int type);
* @remark: for read, user must free the data. * @remark: for read, user must free the data.
* @remark: for write, user should never free the data, even if error. * @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); extern int srs_read_packet(srs_rtmp_t rtmp,
int srs_write_packet(srs_rtmp_t rtmp, int type, u_int32_t timestamp, char* data, int size); int* type, u_int32_t* timestamp, char** data, int* size
);
extern int srs_write_packet(srs_rtmp_t rtmp,
int type, u_int32_t timestamp, char* data, int size
);
/** // get protocol stack version
* get protocol stack version extern int srs_version_major();
*/ extern int srs_version_minor();
int srs_version_major(); extern int srs_version_revision();
int srs_version_minor();
int srs_version_revision();
/** /*************************************************************
**************************************************************
* utilities * utilities
*/ **************************************************************
int64_t srs_get_time_ms(); *************************************************************/
int64_t srs_get_nsend_bytes(srs_rtmp_t rtmp); extern int64_t srs_get_time_ms();
int64_t srs_get_nrecv_bytes(srs_rtmp_t rtmp); extern int64_t srs_get_nsend_bytes(srs_rtmp_t rtmp);
extern int64_t srs_get_nrecv_bytes(srs_rtmp_t rtmp);
/**
/*************************************************************
**************************************************************
* flv codec * flv codec
*/ **************************************************************
*************************************************************/
typedef void* srs_flv_t; typedef void* srs_flv_t;
typedef int flv_bool; typedef int flv_bool;
/* open flv file for both read/write. */ /* open flv file for both read/write. */
srs_flv_t srs_flv_open_read(const char* file); extern srs_flv_t srs_flv_open_read(const char* file);
srs_flv_t srs_flv_open_write(const char* file); extern srs_flv_t srs_flv_open_write(const char* file);
void srs_flv_close(srs_flv_t flv); extern void srs_flv_close(srs_flv_t flv);
/* read the flv header. 9bytes header. drop the 4bytes zero previous tag size */ /* read the flv header. 9bytes header. drop the 4bytes zero previous tag size */
int srs_flv_read_header(srs_flv_t flv, char header[9]); extern int srs_flv_read_header(srs_flv_t flv, char header[9]);
/* read the flv tag header, 1bytes tag, 3bytes data_size, 4bytes time, 3bytes stream id. */ /* read the flv tag header, 1bytes tag, 3bytes data_size, 4bytes time, 3bytes stream id. */
int srs_flv_read_tag_header(srs_flv_t flv, char* ptype, int32_t* pdata_size, u_int32_t* ptime); extern int srs_flv_read_tag_header(srs_flv_t flv,
char* ptype, int32_t* pdata_size, u_int32_t* ptime
);
/* read the tag data. drop the 4bytes previous tag size */ /* read the tag data. drop the 4bytes previous tag size */
int srs_flv_read_tag_data(srs_flv_t flv, char* data, int32_t size); extern int srs_flv_read_tag_data(srs_flv_t flv, char* data, int32_t size);
/* write flv header to file, auto write the 4bytes zero previous tag size. */ /* write flv header to file, auto write the 4bytes zero previous tag size. */
int srs_flv_write_header(srs_flv_t flv, char header[9]); extern int srs_flv_write_header(srs_flv_t flv, char header[9]);
/* write flv tag to file, auto write the 4bytes previous tag size */ /* write flv tag to file, auto write the 4bytes previous tag size */
int srs_flv_write_tag(srs_flv_t flv, char type, int32_t time, char* data, int size); extern int srs_flv_write_tag(srs_flv_t flv, char type, int32_t time, char* data, int size);
/* get the tag size, for flv injecter to adjust offset, size=tag_header+data+previous_tag */ /* get the tag size, for flv injecter to adjust offset, size=tag_header+data+previous_tag */
int srs_flv_size_tag(int data_size); extern int srs_flv_size_tag(int data_size);
/* file stream */ /* file stream */
/* file stream tellg to get offset */ /* file stream tellg to get offset */
int64_t srs_flv_tellg(srs_flv_t flv); extern int64_t srs_flv_tellg(srs_flv_t flv);
/* seek file stream, offset is form the start of file */ /* seek file stream, offset is form the start of file */
void srs_flv_lseek(srs_flv_t flv, int64_t offset); extern void srs_flv_lseek(srs_flv_t flv, int64_t offset);
/* error code */ /* error code */
/* whether the error code indicates EOF */ /* whether the error code indicates EOF */
flv_bool srs_flv_is_eof(int error_code); extern flv_bool srs_flv_is_eof(int error_code);
/* media codec */ /* media codec */
/* whether the video body is sequence header */ /* whether the video body is sequence header */
flv_bool srs_flv_is_sequence_header(char* data, int32_t size); extern flv_bool srs_flv_is_sequence_header(char* data, int32_t size);
/* whether the video body is keyframe */ /* whether the video body is keyframe */
flv_bool srs_flv_is_keyframe(char* data, int32_t size); extern flv_bool srs_flv_is_keyframe(char* data, int32_t size);
/** /*************************************************************
**************************************************************
* amf0 codec * amf0 codec
*/ **************************************************************
*************************************************************/
/* the output handler. */ /* the output handler. */
typedef void* srs_amf0_t; typedef void* srs_amf0_t;
typedef int amf0_bool; typedef int amf0_bool;
typedef double amf0_number; typedef double amf0_number;
srs_amf0_t srs_amf0_parse(char* data, int size, int* nparsed); extern srs_amf0_t srs_amf0_parse(char* data, int size, int* nparsed);
srs_amf0_t srs_amf0_create_number(amf0_number value); extern srs_amf0_t srs_amf0_create_number(amf0_number value);
srs_amf0_t srs_amf0_create_ecma_array(); extern srs_amf0_t srs_amf0_create_ecma_array();
srs_amf0_t srs_amf0_create_strict_array(); extern srs_amf0_t srs_amf0_create_strict_array();
srs_amf0_t srs_amf0_create_object(); extern srs_amf0_t srs_amf0_create_object();
void srs_amf0_free(srs_amf0_t amf0); extern void srs_amf0_free(srs_amf0_t amf0);
void srs_amf0_free_bytes(char* data); extern void srs_amf0_free_bytes(char* data);
/* size and to bytes */ /* size and to bytes */
int srs_amf0_size(srs_amf0_t amf0); extern int srs_amf0_size(srs_amf0_t amf0);
int srs_amf0_serialize(srs_amf0_t amf0, char* data, int size); extern int srs_amf0_serialize(srs_amf0_t amf0, char* data, int size);
/* type detecter */ /* type detecter */
amf0_bool srs_amf0_is_string(srs_amf0_t amf0); extern amf0_bool srs_amf0_is_string(srs_amf0_t amf0);
amf0_bool srs_amf0_is_boolean(srs_amf0_t amf0); extern amf0_bool srs_amf0_is_boolean(srs_amf0_t amf0);
amf0_bool srs_amf0_is_number(srs_amf0_t amf0); extern amf0_bool srs_amf0_is_number(srs_amf0_t amf0);
amf0_bool srs_amf0_is_null(srs_amf0_t amf0); extern amf0_bool srs_amf0_is_null(srs_amf0_t amf0);
amf0_bool srs_amf0_is_object(srs_amf0_t amf0); extern amf0_bool srs_amf0_is_object(srs_amf0_t amf0);
amf0_bool srs_amf0_is_ecma_array(srs_amf0_t amf0); extern amf0_bool srs_amf0_is_ecma_array(srs_amf0_t amf0);
amf0_bool srs_amf0_is_strict_array(srs_amf0_t amf0); extern amf0_bool srs_amf0_is_strict_array(srs_amf0_t amf0);
/* value converter */ /* value converter */
const char* srs_amf0_to_string(srs_amf0_t amf0); extern const char* srs_amf0_to_string(srs_amf0_t amf0);
amf0_bool srs_amf0_to_boolean(srs_amf0_t amf0); extern amf0_bool srs_amf0_to_boolean(srs_amf0_t amf0);
amf0_number srs_amf0_to_number(srs_amf0_t amf0); extern amf0_number srs_amf0_to_number(srs_amf0_t amf0);
/* value setter */ /* value setter */
void srs_amf0_set_number(srs_amf0_t amf0, amf0_number value); extern void srs_amf0_set_number(srs_amf0_t amf0, amf0_number value);
/* object value converter */ /* object value converter */
int srs_amf0_object_property_count(srs_amf0_t amf0); extern int srs_amf0_object_property_count(srs_amf0_t amf0);
const char* srs_amf0_object_property_name_at(srs_amf0_t amf0, int index); extern const char* srs_amf0_object_property_name_at(srs_amf0_t amf0, int index);
srs_amf0_t srs_amf0_object_property_value_at(srs_amf0_t amf0, int index); extern srs_amf0_t srs_amf0_object_property_value_at(srs_amf0_t amf0, int index);
srs_amf0_t srs_amf0_object_property(srs_amf0_t amf0, const char* name); extern srs_amf0_t srs_amf0_object_property(srs_amf0_t amf0, const char* name);
void srs_amf0_object_property_set(srs_amf0_t amf0, const char* name, srs_amf0_t value); extern void srs_amf0_object_property_set(srs_amf0_t amf0, const char* name, srs_amf0_t value);
void srs_amf0_object_clear(srs_amf0_t amf0); extern void srs_amf0_object_clear(srs_amf0_t amf0);
/* ecma array value converter */ /* ecma array value converter */
int srs_amf0_ecma_array_property_count(srs_amf0_t amf0); extern int srs_amf0_ecma_array_property_count(srs_amf0_t amf0);
const char* srs_amf0_ecma_array_property_name_at(srs_amf0_t amf0, int index); extern const char* srs_amf0_ecma_array_property_name_at(srs_amf0_t amf0, int index);
srs_amf0_t srs_amf0_ecma_array_property_value_at(srs_amf0_t amf0, int index); extern srs_amf0_t srs_amf0_ecma_array_property_value_at(srs_amf0_t amf0, int index);
srs_amf0_t srs_amf0_ecma_array_property(srs_amf0_t amf0, const char* name); extern srs_amf0_t srs_amf0_ecma_array_property(srs_amf0_t amf0, const char* name);
void srs_amf0_ecma_array_property_set(srs_amf0_t amf0, const char* name, srs_amf0_t value); extern void srs_amf0_ecma_array_property_set(srs_amf0_t amf0, const char* name, srs_amf0_t value);
/* strict array value converter */ /* strict array value converter */
int srs_amf0_strict_array_property_count(srs_amf0_t amf0); extern int srs_amf0_strict_array_property_count(srs_amf0_t amf0);
srs_amf0_t srs_amf0_strict_array_property_at(srs_amf0_t amf0, int index); extern srs_amf0_t srs_amf0_strict_array_property_at(srs_amf0_t amf0, int index);
void srs_amf0_strict_array_append(srs_amf0_t amf0, srs_amf0_t value); extern void srs_amf0_strict_array_append(srs_amf0_t amf0, srs_amf0_t value);
/** /**
* human readable print * human readable print
* @param pdata, output the heap data, NULL to ignore. * @param pdata, output the heap data, NULL to ignore.
* user must use srs_amf0_free_bytes to free it. * user must use srs_amf0_free_bytes to free it.
* @return return the *pdata for print. NULL to ignore. * @return return the *pdata for print. NULL to ignore.
*/ */
char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize); extern char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize);
/*************************************************************
**************************************************************
* h264 raw codec
**************************************************************
*************************************************************/
/**
convert h264 stream data to rtmp packet.
@param h264_raw_data the input h264 raw data, a encoded h.264 I/P/B frame data.
@paam h264_raw_size the size of h264 raw data.
@param dts the dts of h.264 raw data.
@param pts the pts of h.264 raw data.
@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.
*/
extern 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
);
#ifdef __cplusplus #ifdef __cplusplus
} }

Loading…
Cancel
Save