h.264裸码流的格式,参考“H.264-AVC-ISO_IEC_14496-10.pdf, page 211.”,这个文档的下载地址:https://github.com/winlinvip/simple-rtmp-server/tree/develop/trunk/doc/H.264-AVC-ISO_IEC_14496-10.pdf
一个录制的h.264裸码流文件:http://winlinvip.github.io/srs.release/3rdparty/720p.h264.raw,或者:http://ossrs.net/srs.release/3rdparty/720p.h264.raw,里面的格式是annexb格式:
// SPS
000000016742802995A014016E40
// PPS
0000000168CE3880
// IFrame
0000000165B8041014C038008B0D0D3A071.....
// PFrame
0000000141E02041F8CDDC562BBDEFAD2F.....
int device_read(char** pdata, int* psize, int* pdts, int* ppts);
int device_read(char** pdata, int* psize, int* timestamp);
本文描述了如何将拿到的h.264数据,通过RTMP协议发布到RTMP服务器,然后使用RTMP或者HLS播放。
显然发送h.264的数据得使用RTMP库,rtmpdump提供的librtmp要求是flv/RTMP格式的数据,而srs-librtmp提供了接口直接发送h.264数据。
srs-librtmp是SRS服务器提供的客户端库,SRS项目参考:https://github.com/winlinvip/simple-rtmp-server
srs-librtmp的wiki参考:https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_SrsLibrtmp#publish-h264-raw-data
对应的srs的bug参考:https://github.com/winlinvip/simple-rtmp-server/issues/66#issuecomment-62240521
使用git clone下来,可以选择github源,或者国内的其他镜像源,参考:https://github.com/winlinvip/simple-rtmp-server#mirrors
例如:
git clone https://github.com/winlinvip/simple-rtmp-server.git
cd simple-rtmp-server/trunk
git checkout master
./configure --disable-all --with-librtmp && make &&
ls -lh objs/include/srs_librtmp.h objs/lib/srs_librtmp.a
./configure --export-librtmp-single=objs/srs-librtmp &&
ls -lh objs/srs-librtmp/srs_librtmp.h objs/srs-librtmp/srs_librtmp.cpp
SRS提供了例子读取录制的h.264文件并发布到RTMP服务器:https://github.com/winlinvip/simple-rtmp-server/tree/develop/trunk/research/librtmp/srs_h264_raw_publish.c
录制的h.264裸码流文件:http://winlinvip.github.io/srs.release/3rdparty/720p.h264.raw,或者:http://ossrs.net/srs.release/3rdparty/720p.h264.raw,里面的格式是annexb格式:
// SPS
000000016742802995A014016E40
// PPS
0000000168CE3880
// IFrame
0000000165B8041014C038008B0D0D3A071.....
// PFrame
0000000141E02041F8CDDC562BBDEFAD2F.....
wget https://raw.githubusercontent.com/winlinvip/simple-rtmp-server/master/trunk/research/librtmp/srs_h264_raw_publish.c -O objs/srs-librtmp/srs_h264_raw_publish.c --no-check-certificate &&
wget http://ossrs.net/srs.release/3rdparty/720p.h264.raw -O objs/srs-librtmp/720p.h264.raw
[winlin@dev6 trunk]$ ls -lh objs/srs-librtmp
total 5.8M
-rw-rw-r-- 1 winlin winlin 5.1M Nov 8 12:39 720p.h264.raw
-rw-rw-r-- 1 winlin winlin 633 Nov 16 10:32 example.c
-rw-rw-r-- 1 winlin winlin 87K Nov 16 10:36 srs_h264_raw_publish.c
-rw-rw-r-- 1 winlin winlin 557K Nov 16 10:32 srs_librtmp.cpp
-rw-rw-r-- 1 winlin winlin 20K Nov 16 10:32 srs_librtmp.h
// SPS
000000016742802995A014016E40
// PPS
0000000168CE3880
// IFrame
0000000165B8041014C038008B0D0D3A071.....
// PFrame
0000000141E02041F8CDDC562BBDEFAD2F.....
连接RTMP和发送的主要函数是:
srs_rtmp_t rtmp = srs_rtmp_create(rtmp_url);
srs_simple_handshake(rtmp);
srs_connect_app("rtmp://127.0.0.1/live/livestream");
srs_publish_stream(rtmp);
while (!EOF) {
read_h264_frame(&data, &size, &dts, &pts);
srs_h264_write_raw_frames(rtmp, data, size, dts, pts);
}
若使用srs-librtmp导出的单个.h和.cpp文件,编译和运行命令是:
cd objs/srs-librtmp &&
gcc -g -O0 srs_h264_raw_publish.c srs_librtmp.cpp -o publisher -lstdc++ &&
./publisher ./720p.h264.raw rtmp://ossrs.net/live/h264.raw
http://www.ossrs.net/srs.release/trunk/research/players/srs_player.html?server=ossrs.net&vhost=ossrs.net&stream=h264.raw&autostart=true
srs-librtmp定义的h.264裸码流发送接口使用参考:https://github.com/winlinvip/simple-rtmp-server/issues/66#issuecomment-62240521
其中有几个错误可以忽略:
目前的接口声明如下,最新的接口声明以代码为准:
/**
* write h.264 raw frame over RTMP to rtmp server.
* @param frames the input h264 raw data, encoded h.264 I/P/B frames data.
* frames can be one or more than one frame,
* each frame prefixed h.264 annexb header, by N[00] 00 00 01, where N>=0,
* for instance, frame = header(00 00 00 01) + payload(67 42 80 29 95 A0 14 01 6E 40)
* about annexb, @see H.264-AVC-ISO_IEC_14496-10.pdf, page 211.
* @paam frames_size the size of h264 raw data.
* assert frames_size > 0, at least has 1 bytes header.
* @param dts the dts of h.264 raw data.
* @param pts the pts of h.264 raw data.
*
* @remark, user should free the frames.
* @remark, the tbn of dts/pts is 1/1000 for RTMP, that is, in ms.
* @remark, cts = pts - dts
* @remark, use srs_h264_startswith_annexb to check whether frame is annexb format.
* @example /trunk/research/librtmp/srs_h264_raw_publish.c
* @see https://github.com/winlinvip/simple-rtmp-server/issues/66
*
* @return 0, success; otherswise, failed.
* for dvbsp error, @see srs_h264_is_dvbsp_error().
* for duplictated sps error, @see srs_h264_is_duplicated_sps_error().
* for duplictated pps error, @see srs_h264_is_duplicated_pps_error().
*/
/**
For the example file:
http://winlinvip.github.io/srs.release/3rdparty/720p.h264.raw
The data sequence is:
// SPS
000000016742802995A014016E40
// PPS
0000000168CE3880
// IFrame
0000000165B8041014C038008B0D0D3A071.....
// PFrame
0000000141E02041F8CDDC562BBDEFAD2F.....
User can send the SPS+PPS, then each frame:
// SPS+PPS
srs_h264_write_raw_frames('000000016742802995A014016E400000000168CE3880', size, dts, pts)
// IFrame
srs_h264_write_raw_frames('0000000165B8041014C038008B0D0D3A071......', size, dts, pts)
// PFrame
srs_h264_write_raw_frames('0000000141E02041F8CDDC562BBDEFAD2F......', size, dts, pts)
User also can send one by one:
// SPS
srs_h264_write_raw_frames('000000016742802995A014016E4', size, dts, pts)
// PPS
srs_h264_write_raw_frames('00000000168CE3880', size, dts, pts)
// IFrame
srs_h264_write_raw_frames('0000000165B8041014C038008B0D0D3A071......', size, dts, pts)
// PFrame
srs_h264_write_raw_frames('0000000141E02041F8CDDC562BBDEFAD2F......', size, dts, pts)
*/
extern int srs_h264_write_raw_frames(srs_rtmp_t rtmp,
char* frames, int frames_size, u_int32_t dts, u_int32_t pts
);
/**
* whether error_code is dvbsp(drop video before sps/pps/sequence-header) error.
*
* @see https://github.com/winlinvip/simple-rtmp-server/issues/203
* @example /trunk/research/librtmp/srs_h264_raw_publish.c
* @remark why drop video?
* some encoder, for example, ipcamera, will send sps/pps before each IFrame,
* so, when error and reconnect the rtmp, the first video is not sps/pps(sequence header),
* this will cause SRS server to disable HLS.
*/
extern srs_h264_bool srs_h264_is_dvbsp_error(int error_code);
/**
* whether error_code is duplicated sps error.
*
* @see https://github.com/winlinvip/simple-rtmp-server/issues/204
* @example /trunk/research/librtmp/srs_h264_raw_publish.c
*/
extern srs_h264_bool srs_h264_is_duplicated_sps_error(int error_code);
/**
* whether error_code is duplicated pps error.
*
* @see https://github.com/winlinvip/simple-rtmp-server/issues/204
* @example /trunk/research/librtmp/srs_h264_raw_publish.c
*/
extern srs_h264_bool srs_h264_is_duplicated_pps_error(int error_code);