winlin

move the annexb decode utility to protocol.

... ... @@ -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")
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)
{
srs_trace("publish raw h.264 as rtmp stream to server like FMLE/FFMPEG/Encoder");
... ... @@ -107,24 +141,22 @@ int main(int argc, char** argv)
}
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,
// 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 (;;) {
// get h264 raw data from device, whatever.
int size = 4096;
char* data = (char*)malloc(4096);
if ((size = read(raw_fd, data, size)) < 0) {
srs_trace("read h264 raw data failed. nread=%d", size);
// @remark, to decode the file.
char* p = h264_raw;
for (;p < h264_raw + file_size;) {
// @remark, read a frame from file buffer.
char* data = NULL;
int size = 0;
if (read_h264_frame(h264_raw, file_size, &p, fps, &data, &size, &dts, &pts) < 0) {
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;
}
// convert the h264 packet to rtmp packet.
char* rtmp_data = NULL;
int rtmp_size = 0;
... ... @@ -142,15 +174,10 @@ int main(int argc, char** argv)
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;
// @remark, when use encode device, it not need to sleep.
usleep(1000 / fps * 1000);
}
srs_trace("h264 raw data completed");
rtmp_destroy:
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_protocol_amf0.hpp>
#include <srs_app_utility.hpp>
#include <srs_protocol_utility.hpp>
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;
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);
/**
* 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.
// @see: man getrusage
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)
{
*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;
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
}
#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.
@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.
@remark, user should never free the h264_raw_data.
@remark, user should free the prtmp_data if success.
@return 0, success; otherswise, failed.
* 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.
* @remark, user should 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,
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
}
... ...
... ... @@ -28,6 +28,7 @@ using namespace std;
#include <srs_kernel_log.hpp>
#include <srs_kernel_utility.hpp>
#include <srs_kernel_stream.hpp>
void srs_discovery_tc_url(
string tcUrl,
... ... @@ -155,3 +156,32 @@ bool srs_bytes_equals(void* pa, void* pb, int size)
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>
class SrsStream;
/**
* parse the tcUrl, output the schema, host, vhost, app and port.
* @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);
/**
* 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
... ...