mirror of
https://github.com/ossrs/srs.git
synced 2025-02-13 20:01:56 +00:00
Merge branch 'srs.master'
This commit is contained in:
commit
2d8c4cc7a4
8 changed files with 128 additions and 69 deletions
|
@ -37,6 +37,40 @@ gcc srs_h264_raw_publish.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_h
|
||||||
|
|
||||||
#define srs_trace(msg, ...) printf(msg, ##__VA_ARGS__);printf("\n")
|
#define srs_trace(msg, ...) printf(msg, ##__VA_ARGS__);printf("\n")
|
||||||
|
|
||||||
|
int read_h264_frame(char* data, int size, char** p, int fps,
|
||||||
|
char** frame, int* frame_size, int* dts, int* pts)
|
||||||
|
{
|
||||||
|
// @remark, for this demo, to publish h264 raw file to SRS,
|
||||||
|
// we search the h264 frame from the buffer which cached the h264 data.
|
||||||
|
// please get h264 raw data from device, it always a encoded frame.
|
||||||
|
int pnb_start_code = 0;
|
||||||
|
if (!srs_h264_startswith_annexb(*p, size - (*p - data), &pnb_start_code)) {
|
||||||
|
srs_trace("h264 raw data invalid.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*p += pnb_start_code;
|
||||||
|
|
||||||
|
*frame = *p;
|
||||||
|
for (;*p < data + size; *p = *p + 1) {
|
||||||
|
if (srs_h264_startswith_annexb(*p, size - (*p - data), &pnb_start_code)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*frame_size = *p - *frame;
|
||||||
|
if (*frame_size <= 0) {
|
||||||
|
srs_trace("h264 raw data invalid.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @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;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
srs_trace("publish raw h.264 as rtmp stream to server like FMLE/FFMPEG/Encoder");
|
srs_trace("publish raw h.264 as rtmp stream to server like FMLE/FFMPEG/Encoder");
|
||||||
|
@ -107,21 +141,19 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
srs_trace("publish stream success");
|
srs_trace("publish stream success");
|
||||||
|
|
||||||
|
u_int32_t dts = 0;
|
||||||
|
u_int32_t pts = 0;
|
||||||
// @remark, the dts and pts if read from device, for instance, the encode lib,
|
// @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.
|
// so we assume the fps is 25, and each h264 frame is 1000ms/25fps=40ms/f.
|
||||||
u_int32_t fps = 25;
|
u_int32_t fps = 25;
|
||||||
u_int32_t dts = 0;
|
// @remark, to decode the file.
|
||||||
u_int32_t pts = 0;
|
char* p = h264_raw;
|
||||||
for (;;) {
|
for (;p < h264_raw + file_size;) {
|
||||||
// get h264 raw data from device, whatever.
|
// @remark, read a frame from file buffer.
|
||||||
int size = 4096;
|
char* data = NULL;
|
||||||
char* data = (char*)malloc(4096);
|
int size = 0;
|
||||||
if ((size = read(raw_fd, data, size)) < 0) {
|
if (read_h264_frame(h264_raw, file_size, &p, fps, &data, &size, &dts, &pts) < 0) {
|
||||||
srs_trace("read h264 raw data failed. nread=%d", size);
|
srs_trace("read a frame from file buffer failed.");
|
||||||
goto rtmp_destroy;
|
|
||||||
}
|
|
||||||
if (size == 0) {
|
|
||||||
srs_trace("publish h264 raw data completed.");
|
|
||||||
goto rtmp_destroy;
|
goto rtmp_destroy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,15 +174,10 @@ int main(int argc, char** argv)
|
||||||
srs_trace("sent packet: type=%s, time=%d, size=%d, fps=%d",
|
srs_trace("sent packet: type=%s, time=%d, size=%d, fps=%d",
|
||||||
srs_type2string(type), timestamp, rtmp_size, fps);
|
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;
|
|
||||||
|
|
||||||
// @remark, when use encode device, it not need to sleep.
|
// @remark, when use encode device, it not need to sleep.
|
||||||
usleep(1000 / fps * 1000);
|
usleep(1000 / fps * 1000);
|
||||||
}
|
}
|
||||||
|
srs_trace("h264 raw data completed");
|
||||||
|
|
||||||
rtmp_destroy:
|
rtmp_destroy:
|
||||||
srs_rtmp_destroy(rtmp);
|
srs_rtmp_destroy(rtmp);
|
||||||
|
|
|
@ -28,6 +28,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#include <srs_kernel_stream.hpp>
|
#include <srs_kernel_stream.hpp>
|
||||||
#include <srs_protocol_amf0.hpp>
|
#include <srs_protocol_amf0.hpp>
|
||||||
#include <srs_app_utility.hpp>
|
#include <srs_app_utility.hpp>
|
||||||
|
#include <srs_protocol_utility.hpp>
|
||||||
|
|
||||||
SrsCodecSampleUnit::SrsCodecSampleUnit()
|
SrsCodecSampleUnit::SrsCodecSampleUnit()
|
||||||
{
|
{
|
||||||
|
|
|
@ -107,35 +107,6 @@ int srs_get_log_level(string level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code)
|
|
||||||
{
|
|
||||||
char* bytes = stream->data() + stream->pos();
|
|
||||||
char* p = bytes;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if (!stream->require(p - bytes + 3)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// not match
|
|
||||||
if (p[0] != 0x00 || p[1] != 0x00) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// match N[00] 00 00 01, where N>=0
|
|
||||||
if (p[2] == 0x01) {
|
|
||||||
if (pnb_start_code) {
|
|
||||||
*pnb_start_code = (int)(p - bytes) + 3;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SrsRusage _srs_system_rusage;
|
static SrsRusage _srs_system_rusage;
|
||||||
|
|
||||||
SrsRusage::SrsRusage()
|
SrsRusage::SrsRusage()
|
||||||
|
|
|
@ -50,15 +50,6 @@ extern int srs_socket_connect(std::string server, int port, int64_t timeout, st_
|
||||||
*/
|
*/
|
||||||
extern int srs_get_log_level(std::string level);
|
extern int srs_get_log_level(std::string level);
|
||||||
|
|
||||||
/**
|
|
||||||
* whether stream starts with the avc NALU in "AnnexB"
|
|
||||||
* from H.264-AVC-ISO_IEC_14496-10.pdf, page 211.
|
|
||||||
* start code must be "N[00] 00 00 01" where N>=0
|
|
||||||
* @param pnb_start_code output the size of start code, must >=3.
|
|
||||||
* NULL to ignore.
|
|
||||||
*/
|
|
||||||
extern bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code = NULL);
|
|
||||||
|
|
||||||
// current process resouce usage.
|
// current process resouce usage.
|
||||||
// @see: man getrusage
|
// @see: man getrusage
|
||||||
class SrsRusage
|
class SrsRusage
|
||||||
|
|
|
@ -998,11 +998,24 @@ char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* 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)
|
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_data = new char[h264_raw_size];
|
||||||
|
memcpy(*prtmp_data, h264_raw_data, h264_raw_size);
|
||||||
|
|
||||||
*prtmp_size = h264_raw_size;
|
*prtmp_size = h264_raw_size;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int srs_h264_startswith_annexb(char* h264_raw_data, int h264_raw_size, int* pnb_start_code)
|
||||||
|
{
|
||||||
|
SrsStream stream;
|
||||||
|
if (stream.initialize(h264_raw_data, h264_raw_size) != ERROR_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return srs_avc_startswith_annexb(&stream, pnb_start_code);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -337,22 +337,37 @@ extern char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize);
|
||||||
**************************************************************
|
**************************************************************
|
||||||
*************************************************************/
|
*************************************************************/
|
||||||
/**
|
/**
|
||||||
convert h264 stream data to rtmp packet.
|
* 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.
|
* @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.
|
* @paam h264_raw_size the size of h264 raw data.
|
||||||
@param dts the dts of h.264 raw data.
|
* @param dts the dts of h.264 raw data.
|
||||||
@param pts the pts 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_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 prtmp_size the size of rtmp packet, for srs_write_packet.
|
||||||
@param ptimestamp the timestamp 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 h264_raw_data.
|
||||||
@remark, user should free the prtmp_data if success.
|
* @remark, user should free the prtmp_data if success.
|
||||||
@return 0, success; otherswise, failed.
|
*
|
||||||
|
* @return 0, success; otherswise, failed.
|
||||||
*/
|
*/
|
||||||
extern int srs_h264_to_rtmp(
|
extern int srs_h264_to_rtmp(
|
||||||
char* h264_raw_data, int h264_raw_size, u_int32_t dts, u_int32_t pts,
|
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
|
char** prtmp_data, int* prtmp_size, u_int32_t* ptimestamp
|
||||||
);
|
);
|
||||||
|
/**
|
||||||
|
* whether h264 raw data starts with the annexb,
|
||||||
|
* which bytes sequence matches N[00] 00 00 01, where N>=0.
|
||||||
|
* @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 pnb_start_code output the size of start code, must >=3.
|
||||||
|
* NULL to ignore.
|
||||||
|
*
|
||||||
|
* @return 0 false; otherwise, true.
|
||||||
|
*/
|
||||||
|
extern int srs_h264_startswith_annexb(
|
||||||
|
char* h264_raw_data, int h264_raw_size,
|
||||||
|
int* pnb_start_code
|
||||||
|
);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ using namespace std;
|
||||||
|
|
||||||
#include <srs_kernel_log.hpp>
|
#include <srs_kernel_log.hpp>
|
||||||
#include <srs_kernel_utility.hpp>
|
#include <srs_kernel_utility.hpp>
|
||||||
|
#include <srs_kernel_stream.hpp>
|
||||||
|
|
||||||
void srs_discovery_tc_url(
|
void srs_discovery_tc_url(
|
||||||
string tcUrl,
|
string tcUrl,
|
||||||
|
@ -155,3 +156,32 @@ bool srs_bytes_equals(void* pa, void* pb, int size)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code)
|
||||||
|
{
|
||||||
|
char* bytes = stream->data() + stream->pos();
|
||||||
|
char* p = bytes;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (!stream->require(p - bytes + 3)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not match
|
||||||
|
if (p[0] != 0x00 || p[1] != 0x00) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// match N[00] 00 00 01, where N>=0
|
||||||
|
if (p[2] == 0x01) {
|
||||||
|
if (pnb_start_code) {
|
||||||
|
*pnb_start_code = (int)(p - bytes) + 3;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
#include <srs_kernel_consts.hpp>
|
#include <srs_kernel_consts.hpp>
|
||||||
|
|
||||||
|
class SrsStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* parse the tcUrl, output the schema, host, vhost, app and port.
|
* parse the tcUrl, output the schema, host, vhost, app and port.
|
||||||
* @param tcUrl, the input tcUrl, for example,
|
* @param tcUrl, the input tcUrl, for example,
|
||||||
|
@ -85,5 +87,14 @@ extern std::string srs_generate_tc_url(
|
||||||
*/
|
*/
|
||||||
extern bool srs_bytes_equals(void* pa, void* pb, int size);
|
extern bool srs_bytes_equals(void* pa, void* pb, int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* whether stream starts with the avc NALU in "AnnexB"
|
||||||
|
* from H.264-AVC-ISO_IEC_14496-10.pdf, page 211.
|
||||||
|
* start code must be "N[00] 00 00 01" where N>=0
|
||||||
|
* @param pnb_start_code output the size of start code, must >=3.
|
||||||
|
* NULL to ignore.
|
||||||
|
*/
|
||||||
|
extern bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code = NULL);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue