引用: rtp_profile_set_payload(profile,96,&payload_type_h264);
引用: cd /home/lhj/ortp
./autogen.sh
./configure CC=aarch64-linux-gnu-gcc --host=aarch64-linux --target=aarch64-linux --prefix=/home/lhj/opt/board
make clean
make
make install
引用: uint32_t h264isslice(uint8_t* buffer)
{
if((buffer[0]==0)&&(buffer[1]==0))
{
if(buffer[2]==1)
{
return 1;
}
else if(buffer[2]==0)
{
if(buffer[3]==1)
{
return 2;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
else
{
return 0;
}
}
uint32_t h264getslicelen(uint8_t* buffer,uint32_t len,uint8_t* headlen)
{
uint8_t type;
uint32_t offset = 0;
uint32_t isslice = 0;
isslice = h264isslice(buffer);
if(isslice==1)
{
offset=3;
*headlen = 3;
}
else if(isslice==2)
{
offset=4;
*headlen = 4;
}
else
{
return 0;
}
uint32_t i;
for(i=offset;i
{
if((buffer[i+0]==0)&&(buffer[i+1]==0))
{
if(buffer[i+2]==1)
{
//type = buffer[i+3] & 0x1F;
//if (type ==1)
//{
return i;
//}
}
else if(buffer[i+2]==0)
{
if(buffer[i+3]==1)
{
// type = buffer[i+4] & 0x1F;
// if (type ==1)
// {
return i;
// }
}
}
}
}
return i;
}
引用: static void forward_frame(RtpSession * session, uint8_t * buffer, int len,
uint32_t userts) {
unsigned char NALU = buffer[0];
uint32_t valid_len = len;
if (len <= MAX_RTP_PKT_LENGTH) {
/*
RTP Header + NALU Header + NALU Data; (不包括startcode)
传入的buffer从NALU Header开始
RTP Header由rtp_session_send_with_ts添加
*/
rtp_session_send_with_ts(session, buffer,len,userts);
} else {
/* FU-A */
int packetnum = valid_len / (MAX_RTP_PKT_LENGTH-1); /* FU-A分片要多加一个字节 */
if (valid_len % (MAX_RTP_PKT_LENGTH-1) != 0) {
packetnum += 1;
}
int i = 0;
int pos = -1;
while (i < packetnum) {
if (i < packetnum - 1) {
buffer[pos] = (NALU & 0x60) | 28;
buffer[pos+1] = (NALU & 0x1f);
if (0 == i) {
buffer[pos+1] |= 0x80;
}
rtp_session_send_with_ts(session, &buffer[pos],
MAX_RTP_PKT_LENGTH, userts);
printf("send slice offset=%d,len=%drn",pos,MAX_RTP_PKT_LENGTH);
} else {
int iSendLen = len - pos - 1;
buffer[pos] = (NALU & 0x60) | 28;
buffer[pos+1] = (NALU & 0x1f);
buffer[pos+1] |= 0x40;
rtp_session_send_with_ts(session, &buffer[pos],
iSendLen, userts);
printf("send slice offset=%d,len=%drn",pos-2,iSendLen + 2);
}
pos += MAX_RTP_PKT_LENGTH-2; /*有效长度MAX_RTP_PKT_LENGTH-1 在往前预留一个字节存储FU indicator */
++i;
}
}
}
引用: /*
The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) stack.
Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include
#include
#include
#include
#ifndef _WIN32
#include
#include
#include
#endif
#define MAX_RTP_PKT_LENGTH (1400)
#define TS_INC (90000/25)
int runcond=1;
void stophandler(int signum)
{
runcond=0;
}
static const char *help="usage: rtpsend filename dest_ip4addr dest_port [ --with-clockslide] [ --with-jitter ]n";
static void forward_frame(RtpSession * session, uint8_t * buffer, int len,
uint32_t userts) {
unsigned char NALU = buffer[0];
uint32_t valid_len = len;
if (len <= MAX_RTP_PKT_LENGTH) {
/*
RTP Header + NALU Header + NALU Data; (不包括startcode)
传入的buffer从NALU Header开始
RTP Header由rtp_session_send_with_ts添加
*/
rtp_session_send_with_ts(session, buffer,len,userts);
} else {
/* FU-A *
* FU indicator FU header DATA
* ^
* NALU Header NALU Data
*/
int packetnum = valid_len / (MAX_RTP_PKT_LENGTH-1); /* FU-A分片要多加一个字节 */
if (valid_len % (MAX_RTP_PKT_LENGTH-1) != 0) {
packetnum += 1;
}
int i = 0;
int pos = -1;
while (i < packetnum) {
if (i < packetnum - 1) {
buffer[pos] = (NALU & 0x60) | 28;
buffer[pos+1] = (NALU & 0x1f);
if (0 == i) {
buffer[pos+1] |= 0x80;
}
rtp_session_send_with_ts(session, &buffer[pos],
MAX_RTP_PKT_LENGTH, userts);
printf("send slice offset=%d,len=%drn",pos,MAX_RTP_PKT_LENGTH);
} else {
int iSendLen = len - pos - 1;
buffer[pos] = (NALU & 0x60) | 28;
buffer[pos+1] = (NALU & 0x1f);
buffer[pos+1] |= 0x40;
rtp_session_send_with_ts(session, &buffer[pos],
iSendLen, userts);
printf("send slice offset=%d,len=%drn",pos-2,iSendLen + 2);
}
pos += MAX_RTP_PKT_LENGTH-2; /*有效长度MAX_RTP_PKT_LENGTH-1 在往前预留一个字节存储FU indicator */
++i;
}
}
}
uint32_t h264isslice(uint8_t* buffer)
{
if((buffer[0]==0)&&(buffer[1]==0))
{
if(buffer[2]==1)
{
return 1;
}
else if(buffer[2]==0)
{
if(buffer[3]==1)
{
return 2;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
else
{
return 0;
}
}
uint32_t h264getslicelen(uint8_t* buffer,uint32_t len,uint8_t* headlen)
{
uint8_t type;
uint32_t offset = 0;
uint32_t isslice = 0;
isslice = h264isslice(buffer);
if(isslice==1)
{
offset=3;
*headlen = 3;
}
else if(isslice==2)
{
offset=4;
*headlen = 4;
}
else
{
return 0;
}
uint32_t i;
for(i=offset;i
{
if((buffer[i+0]==0)&&(buffer[i+1]==0))
{
if(buffer[i+2]==1)
{
//type = buffer[i+3] & 0x1F;
//if (type ==1)
//{
return i;
//}
}
else if(buffer[i+2]==0)
{
if(buffer[i+3]==1)
{
// type = buffer[i+4] & 0x1F;
// if (type ==1)
// {
return i;
// }
}
}
}
}
return i;
}
int main(int argc, char *argv[])
{
RtpSession *session;
//unsigned char buffer[160];
int i;
FILE *infile;
char *ssrc;
uint32_t user_ts=0;
int clockslide=0;
int jitter=0;
if (argc<4){
printf("%s", help);
return -1;
}
for(i=4;i
if (strcmp(argv,"--with-clockslide")==0){
i++;
if (i>=argc) {
printf("%s", help);
return -1;
}
clockslide=atoi(argv);
ortp_message("Using clockslide of %i milisecond every 50 packets.",clockslide);
}else if (strcmp(argv,"--with-jitter")==0){
ortp_message("Jitter will be added to outgoing stream.");
i++;
if (i>=argc) {
printf("%s", help);
return -1;
}
jitter=atoi(argv);
}
}
printf("ortp_initn");
ortp_init();
printf("ortp_scheduler_initn");
ortp_scheduler_init();
ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR);
printf("rtp_session_newn");
session=rtp_session_new(RTP_SESSION_SENDONLY);
rtp_session_set_scheduling_mode(session,1);
rtp_session_set_blocking_mode(session,1);
rtp_session_set_connected_mode(session,TRUE);
rtp_session_set_remote_addr(session,argv[2],atoi(argv[3]));
rtp_session_set_payload_type(session,96);
ssrc=getenv("SSRC");
if (ssrc!=NULL) {
printf("using SSRC=%i.n",atoi(ssrc));
rtp_session_set_ssrc(session,atoi(ssrc));
printf("rtp_session_set_ssrc %sn",ssrc);
}
#ifndef _WIN32
infile=fopen(argv[1],"r");
#else
infile=fopen(argv[1],"rb");
#endif
if (infile==NULL) {
perror("Cannot open file");
return -1;
}
signal(SIGINT,stophandler);
fseek(infile, 0L, SEEK_END);
ssize_t filesize = ftell(infile);
uint8_t *buffer = malloc(filesize);
fseek(infile, 0L, SEEK_SET);
fread(buffer,1,filesize,infile);
uint8_t* src_buff = buffer;
uint32_t framelen = 0;
uint32_t s_h264_sendlen_u32 = 0;
uint8_t headlen;
printf("start sendn");
while(1)
{
if((framelen = h264getslicelen(src_buff,filesize-s_h264_sendlen_u32,&headlen)) == 0)
{
/* 无有效数据 */
printf("no h264 datan");
break;
}
printf("get slice len:%d %d n",framelen,headlen);
/* 更新buff 继续往后处后面没有数据就绕到开*/
forward_frame(session,src_buff+headlen,framelen-headlen,user_ts);
user_ts+=TS_INC;
src_buff += framelen;
s_h264_sendlen_u32+=framelen;
printf("sendlen=%d,framelen=%dn",s_h264_sendlen_u32,framelen);
if(s_h264_sendlen_u32 >= filesize)
{
break;
}
}
fclose(infile);
rtp_session_destroy(session);
ortp_exit();
ortp_global_stats_display();
return 0;
}
引用: rtp_session_set_payload_type(session,0);改为 rtp_session_set_payload_type(session,96);
引用: cd src/tests/
aarch64-linux-gnu-gcc rtpsendh264.c -lortp -L/home/lhj/opt/board/lib -I/home/lhj/opt/board/include -o rtpsendh264
cp rtpsendh264 /mnt/d
更多回帖