mirror of
https://github.com/ossrs/srs.git
synced 2025-02-13 03:41:55 +00:00
add api convert h264 to rtmp packet, for bug #66
This commit is contained in:
parent
e4af098d06
commit
1c237a821a
3 changed files with 166 additions and 86 deletions
|
@ -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 <unistd.h>
|
||||
|
||||
// for open h264 raw file.
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "../../objs/include/srs_librtmp.h"
|
||||
|
||||
#define srs_trace(msg, ...) printf(msg, ##__VA_ARGS__);printf("\n")
|
||||
|
@ -40,7 +45,7 @@ int main(int argc, char** argv)
|
|||
|
||||
if (argc <= 2) {
|
||||
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("For example:");
|
||||
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];
|
||||
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);
|
||||
|
||||
if (srs_simple_handshake(rtmp) != 0) {
|
||||
|
@ -73,23 +86,42 @@ int main(int argc, char** argv)
|
|||
}
|
||||
srs_trace("publish stream success");
|
||||
|
||||
u_int32_t timestamp = 0;
|
||||
u_int32_t dts = 0;
|
||||
u_int32_t pts = 0;
|
||||
for (;;) {
|
||||
int type = SRS_RTMP_TYPE_VIDEO;
|
||||
timestamp += 40;
|
||||
// read from file, or get h264 raw data from device, whatever.
|
||||
int size = 4096;
|
||||
char* data = (char*)malloc(4096);
|
||||
|
||||
if (srs_write_packet(rtmp, type, timestamp, data, size) != 0) {
|
||||
if ((size = read(raw_fd, data, size)) < 0) {
|
||||
srs_trace("read h264 raw data failed. nread=%d", size);
|
||||
goto rtmp_destroy;
|
||||
}
|
||||
srs_trace("sent packet: type=%s, time=%d, size=%d", srs_type2string(type), timestamp, size);
|
||||
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, ×tamp) < 0) {
|
||||
srs_trace("h264 raw data to rtmp data failed.");
|
||||
goto rtmp_destroy;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
usleep(40 * 1000);
|
||||
}
|
||||
|
||||
rtmp_destroy:
|
||||
srs_rtmp_destroy(rtmp);
|
||||
close(raw_fd);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -42,6 +42,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
extern "C"{
|
||||
#endif
|
||||
|
||||
/*************************************************************
|
||||
**************************************************************
|
||||
* RTMP protocol context
|
||||
**************************************************************
|
||||
*************************************************************/
|
||||
// the RTMP handler.
|
||||
typedef void* srs_rtmp_t;
|
||||
|
||||
|
@ -51,7 +56,7 @@ typedef void* srs_rtmp_t;
|
|||
* rtmp://localhost/live/livestream
|
||||
* @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.
|
||||
* @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,
|
||||
* 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.
|
||||
* @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
|
||||
* category: publish/play
|
||||
|
@ -84,13 +94,13 @@ void srs_rtmp_destroy(srs_rtmp_t rtmp);
|
|||
* __srs_do_simple_handshake()
|
||||
* 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
|
||||
int __srs_dns_resolve(srs_rtmp_t rtmp);
|
||||
extern int __srs_dns_resolve(srs_rtmp_t rtmp);
|
||||
// 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.
|
||||
int __srs_do_simple_handshake(srs_rtmp_t rtmp);
|
||||
extern int __srs_do_simple_handshake(srs_rtmp_t rtmp);
|
||||
|
||||
/**
|
||||
* connect to rtmp vhost/app
|
||||
|
@ -99,7 +109,7 @@ int __srs_do_simple_handshake(srs_rtmp_t rtmp);
|
|||
* next: publish or play
|
||||
* @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.
|
||||
|
@ -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_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_version[32], int* srs_id, int* srs_pid
|
||||
);
|
||||
|
@ -124,7 +134,7 @@ int srs_connect_app2(srs_rtmp_t rtmp,
|
|||
* next: destroy
|
||||
* @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.
|
||||
|
@ -133,7 +143,7 @@ int srs_play_stream(srs_rtmp_t rtmp);
|
|||
* next: destroy
|
||||
* @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.
|
||||
|
@ -148,7 +158,7 @@ int srs_publish_stream(srs_rtmp_t rtmp);
|
|||
* @param play_duration, output the play/download 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,
|
||||
int* play_kbps, int* publish_kbps,
|
||||
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*,
|
||||
* 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.
|
||||
* @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 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);
|
||||
extern int srs_read_packet(srs_rtmp_t rtmp,
|
||||
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
|
||||
*/
|
||||
int srs_version_major();
|
||||
int srs_version_minor();
|
||||
int srs_version_revision();
|
||||
// get protocol stack version
|
||||
extern int srs_version_major();
|
||||
extern int srs_version_minor();
|
||||
extern int srs_version_revision();
|
||||
|
||||
/**
|
||||
/*************************************************************
|
||||
**************************************************************
|
||||
* utilities
|
||||
*/
|
||||
int64_t srs_get_time_ms();
|
||||
int64_t srs_get_nsend_bytes(srs_rtmp_t rtmp);
|
||||
int64_t srs_get_nrecv_bytes(srs_rtmp_t rtmp);
|
||||
**************************************************************
|
||||
*************************************************************/
|
||||
extern int64_t srs_get_time_ms();
|
||||
extern int64_t srs_get_nsend_bytes(srs_rtmp_t rtmp);
|
||||
extern int64_t srs_get_nrecv_bytes(srs_rtmp_t rtmp);
|
||||
|
||||
/**
|
||||
|
||||
/*************************************************************
|
||||
**************************************************************
|
||||
* flv codec
|
||||
*/
|
||||
**************************************************************
|
||||
*************************************************************/
|
||||
typedef void* srs_flv_t;
|
||||
typedef int flv_bool;
|
||||
/* open flv file for both read/write. */
|
||||
srs_flv_t srs_flv_open_read(const char* file);
|
||||
srs_flv_t srs_flv_open_write(const char* file);
|
||||
void srs_flv_close(srs_flv_t flv);
|
||||
extern srs_flv_t srs_flv_open_read(const char* file);
|
||||
extern srs_flv_t srs_flv_open_write(const char* file);
|
||||
extern void srs_flv_close(srs_flv_t flv);
|
||||
/* 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. */
|
||||
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 */
|
||||
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. */
|
||||
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 */
|
||||
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 */
|
||||
int srs_flv_size_tag(int data_size);
|
||||
extern int srs_flv_size_tag(int data_size);
|
||||
/* file stream */
|
||||
/* 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 */
|
||||
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 */
|
||||
/* 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 */
|
||||
/* 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 */
|
||||
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
|
||||
*/
|
||||
**************************************************************
|
||||
*************************************************************/
|
||||
/* the output handler. */
|
||||
typedef void* srs_amf0_t;
|
||||
typedef int amf0_bool;
|
||||
typedef double amf0_number;
|
||||
srs_amf0_t srs_amf0_parse(char* data, int size, int* nparsed);
|
||||
srs_amf0_t srs_amf0_create_number(amf0_number value);
|
||||
srs_amf0_t srs_amf0_create_ecma_array();
|
||||
srs_amf0_t srs_amf0_create_strict_array();
|
||||
srs_amf0_t srs_amf0_create_object();
|
||||
void srs_amf0_free(srs_amf0_t amf0);
|
||||
void srs_amf0_free_bytes(char* data);
|
||||
extern srs_amf0_t srs_amf0_parse(char* data, int size, int* nparsed);
|
||||
extern srs_amf0_t srs_amf0_create_number(amf0_number value);
|
||||
extern srs_amf0_t srs_amf0_create_ecma_array();
|
||||
extern srs_amf0_t srs_amf0_create_strict_array();
|
||||
extern srs_amf0_t srs_amf0_create_object();
|
||||
extern void srs_amf0_free(srs_amf0_t amf0);
|
||||
extern void srs_amf0_free_bytes(char* data);
|
||||
/* size and to bytes */
|
||||
int srs_amf0_size(srs_amf0_t amf0);
|
||||
int srs_amf0_serialize(srs_amf0_t amf0, char* data, int size);
|
||||
extern int srs_amf0_size(srs_amf0_t amf0);
|
||||
extern int srs_amf0_serialize(srs_amf0_t amf0, char* data, int size);
|
||||
/* type detecter */
|
||||
amf0_bool srs_amf0_is_string(srs_amf0_t amf0);
|
||||
amf0_bool srs_amf0_is_boolean(srs_amf0_t amf0);
|
||||
amf0_bool srs_amf0_is_number(srs_amf0_t amf0);
|
||||
amf0_bool srs_amf0_is_null(srs_amf0_t amf0);
|
||||
amf0_bool srs_amf0_is_object(srs_amf0_t amf0);
|
||||
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_string(srs_amf0_t amf0);
|
||||
extern amf0_bool srs_amf0_is_boolean(srs_amf0_t amf0);
|
||||
extern amf0_bool srs_amf0_is_number(srs_amf0_t amf0);
|
||||
extern amf0_bool srs_amf0_is_null(srs_amf0_t amf0);
|
||||
extern amf0_bool srs_amf0_is_object(srs_amf0_t amf0);
|
||||
extern amf0_bool srs_amf0_is_ecma_array(srs_amf0_t amf0);
|
||||
extern amf0_bool srs_amf0_is_strict_array(srs_amf0_t amf0);
|
||||
/* value converter */
|
||||
const char* srs_amf0_to_string(srs_amf0_t amf0);
|
||||
amf0_bool srs_amf0_to_boolean(srs_amf0_t amf0);
|
||||
amf0_number srs_amf0_to_number(srs_amf0_t amf0);
|
||||
extern const char* srs_amf0_to_string(srs_amf0_t amf0);
|
||||
extern amf0_bool srs_amf0_to_boolean(srs_amf0_t amf0);
|
||||
extern amf0_number srs_amf0_to_number(srs_amf0_t amf0);
|
||||
/* 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 */
|
||||
int srs_amf0_object_property_count(srs_amf0_t amf0);
|
||||
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);
|
||||
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);
|
||||
void srs_amf0_object_clear(srs_amf0_t amf0);
|
||||
extern int srs_amf0_object_property_count(srs_amf0_t amf0);
|
||||
extern const char* srs_amf0_object_property_name_at(srs_amf0_t amf0, int index);
|
||||
extern srs_amf0_t srs_amf0_object_property_value_at(srs_amf0_t amf0, int index);
|
||||
extern srs_amf0_t srs_amf0_object_property(srs_amf0_t amf0, const char* name);
|
||||
extern void srs_amf0_object_property_set(srs_amf0_t amf0, const char* name, srs_amf0_t value);
|
||||
extern void srs_amf0_object_clear(srs_amf0_t amf0);
|
||||
/* ecma array value converter */
|
||||
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);
|
||||
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);
|
||||
void srs_amf0_ecma_array_property_set(srs_amf0_t amf0, const char* name, srs_amf0_t value);
|
||||
extern int srs_amf0_ecma_array_property_count(srs_amf0_t amf0);
|
||||
extern const char* srs_amf0_ecma_array_property_name_at(srs_amf0_t amf0, int index);
|
||||
extern 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(srs_amf0_t amf0, const char* name);
|
||||
extern void srs_amf0_ecma_array_property_set(srs_amf0_t amf0, const char* name, srs_amf0_t value);
|
||||
/* strict array value converter */
|
||||
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);
|
||||
void srs_amf0_strict_array_append(srs_amf0_t amf0, srs_amf0_t value);
|
||||
extern int srs_amf0_strict_array_property_count(srs_amf0_t amf0);
|
||||
extern srs_amf0_t srs_amf0_strict_array_property_at(srs_amf0_t amf0, int index);
|
||||
extern void srs_amf0_strict_array_append(srs_amf0_t amf0, srs_amf0_t value);
|
||||
/**
|
||||
* human readable print
|
||||
* @param pdata, output the heap data, NULL to ignore.
|
||||
* user must use srs_amf0_free_bytes to free it.
|
||||
* @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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue