工作流程:

1)读取ADTS头(7字节),解析得到aac帧的信息(频率,声道,帧长度)

2)读取aac原始数据块,使用RTP打包aac原始数据

  RTP打包h264码流时,由于h264数据长度不稳定,少则几字节,多则几千字节,所以RTP打包形式较多,需要根据大小决定是否进行分片。

  而AAC数据块长度不会像h264那样变化,一般稳定在几百字节,所以它的打包方式比较单一。

打包方式如下

RTP包 = rtpheader(12字节) + 载荷标识(4字节)+ AAC数据块

载荷标识(4字节):

// 前两个字节值固定,第三个字节和第四个字节保存AAC Data的大小
// frameSize = adts.length - 7
rtpPacket->payload[0] = 0x00;
rtpPacket->payload[1] = 0x10;
rtpPacket->payload[2] = (frameSize & 0x1FE0) >> 5;
rtpPacket->payload[3] = (frameSize & 0x1F) << 3;

3)传输一个rtp包,并对序列号和时间戳操作

对于rtpheader有一个要注意的点: 传输h264时marker位为0,传输aac时marker位置1

4)回到步骤1,传输下一帧AAC

代码表达:

0)protocol.h

#ifndef __PROTOCOL_H
#define __PROTOCOL_H// 相关协议的约定
typedef struct {char *ip;int tcp_port;int rtp_port;int rtcp_port;
} client_t;
// 在rtsp+rtp传输时,客户端的RTP端口不能指定,需要从SETUP请求中获取// 单独用于RTP_H264/AAC测试
#define RTP_CLIENT_IP       "192.168.102.215"
#define RTP_CLIENT_PORT     2018// 测试文件的路径
#define AAC_FILE "/home/zhou/ffmpeg/testvideo/001.aac"#endif

本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓

1)rtp_aac.h

#ifndef __RTP_AAC_H
#define __RTP_AAC_H#include "protocol.h"
/* * @func : RTP打包传输AAC码流* @param: *      sockfd --- UDP socket*      client --- client->ip, client->rtp_port*      path   --- AAC_FILE*/
int rtp_play_aac(int sockfd, client_t *client, const char *path);/* * 例程模块测试:* Linux下直接调用rtp_aac_test(AAC_FILE);* Windows下创建rtp_test.sdp文件,用VLC打开。*//* rtp_test.sdp文件:** m=audio 2018 RTP/AVP 97* a=rtpmap:97 mpeg4-generic/44100/2* a=fmtp:97 SizeLength=13;* c=IN IP4 127.0.0.1*/
int rtp_aac_test(const char *file);#endif

2)rtp_aac.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "sock.h"
#include "rtp.h"
#include "rtp_aac.h"struct adts_header {     char profile[8];    int channel; int freq;       int length; // 一帧aac长度,包括adts头和原始流
};static int parser_adts(struct adts_header *adts, uint8_t header[]) {if ((header[0] != 0xFF) && ((header[1] & 0xF0) != 0xF0)) {return -1;  // syncword(12bits)不是0XFFF}memset(adts, 0, sizeof(struct adts_header));// profile 17:18位, 取第3字节高2位int pro = ((unsigned int)header[2] & 0xC0) >> 6; switch (pro) {case 0: strcpy(adts->profile, "Main");break;case 1: strcpy(adts->profile, "LC");break;case 2: strcpy(adts->profile, "SSR");break;default: strcpy(adts->profile, "Unknown");break;};// frequency_idx 19:23位,取第3字节中间4位int freq_index = ((unsigned int)header[2] & 0x3C) >> 2;switch (freq_index) {//...case 3: adts->freq = 48000; break;case 4: adts->freq = 44100; break;default: adts->freq = 0; break;}adts->channel = ((unsigned int)header[2] & 0x01) << 2;adts->channel += ((unsigned int)header[3] & 0xC0) >> 6;// aac_frame_length 30:42(13位) header[3]后2位+header[4]+header[5]前3位int size = ((unsigned int)header[5] & 0XE0) >> 5; // low  3bitssize += header[4] << 3;             // mid  8bitssize += (header[3] & 0x03) << 11;   // high 2bits adts->length = size;return 0;
}static int rtp_send_acc_frame(int sockfd, client_t *client, uint8_t *data, int datalen, struct rtp_packet *packet) {packet->payload[0] = 0x00;packet->payload[1] = 0x10;packet->payload[2] = (datalen & 0x1fe0) >> 5;packet->payload[3] = (datalen & 0x1f) << 3; memcpy(packet->payload+4, data, datalen);int ret = rtp_send_packet(sockfd, client->ip, client->rtp_port, \packet, RTP_HEADER_SIZE+4+datalen);if (ret < 0) return -1;packet->header.seq++;packet->header.timestamp += 1024;return 0;
}int rtp_play_aac(int sockfd, client_t *client, const char *path) {struct rtp_packet *packet = (struct rtp_packet *)malloc(RTP_PACKET_SIZE);rtp_header_init(&packet->header, RTP_PAYLOAD_TYPE_AAC, 1, 0, 0, 0x32411);FILE *fp = fopen(path, "r");if (fp == NULL) {return -1;}uint8_t header[7];struct adts_header adts;uint8_t *data = malloc(8*1024);int ret = 0;while (1) {ret = fread(header, 1, 7, fp);if (ret <= 0) {break;}if (parser_adts(&adts, header) < 0) {printf("failed parser_adts\n");break;}fread(data, 1, adts.length-7, fp);rtp_send_acc_frame(sockfd, client, data, adts.length-7, packet);    //printf("packet seq:%d adts freq:%d length: %d\n",\packet->header.seq, adts.freq, adts.length);float fps = adts.freq / 1024.0;usleep(1000*1000 / (int)fps);}free(packet);free(data);fclose(fp);return 0;
}int rtp_aac_test(const char *file)
{int sockfd = create_udp_socket();if (sockfd < 0) {printf("failed to init socket\n");return -1;}client_t client;client.ip = strdup(RTP_CLIENT_IP);client.rtp_port = RTP_CLIENT_PORT;rtp_play_aac(sockfd, &client, file);close_socket(sockfd);return 0;
}

如果你对音视频开发感兴趣,觉得文章对您有帮助,别忘了点赞、收藏哦!或者对本文的一些阐述有自己的看法,有任何问题,欢迎在下方评论区讨论!

本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓

RTSP服务器:RTP传输AAC流相关推荐

  1. Rtsp协议,FFmpeg推流,rtsp服务器,vlc拉流播放下载安装使用使用详细流程以及EasyDarwin服务的方案

    FFmpeg推流,rtsp服务器,vlc拉流播放测试 FFmpeg 1. 简述: FFmpeg是一套可以用来记录.转换数字音频.视频,并能将其转化为流的开源计算机程序.采用LGPL或GPL许可证.它提 ...

  2. 音视频学习之rtsp学习rtp协议的理解(rtp)

    1:理论理解相关细节 实际的媒体数据(视频/音频)的传输是通过rtp进行传输的. rtp可以基于udp进行发送,也可以基于tcp进行发送. (这个有点疑问,看很多都说rtp是基于udp传输) ==&g ...

  3. live555搭建rtsp服务器推送实时流花屏问题解决

    使用live555搭建rtsp服务器推送实时流时总是出现花屏,查阅资料按照大多数人所说的修改做了以下几项修改: 1.修改OutPacketBuffer::maxSize=1024*1024 ; 2.扩 ...

  4. 【视频】视频传输协议:RTSP、RTP、RTCP、RTMP、HTTP

    一.RTSP.RTP.RTCP RTSP.RTP.RTCP是一组协议,其中RTSP在应用层.RTP和RTCP在传输层.RTP用于传输流媒体数据,而RTCP对RTP进行控制.同步. 二.RTSP.RTM ...

  5. 【ffmpeg】ffmpeg推送流到rtsp服务器

    1  引 言 在项目开发过程中经常遇到接入RTSP视频流的需求.由于外网无法访问项目现场的内网服务器,无法进行测试.想着在网上找一个RTSP流进行测试,但是大多已经失效,且公司对网络进行了限制,无法播 ...

  6. ffmpeg推送rtsp流或者视频文件到rtsp服务器

    1.推送rtsp视频流 ffmpeg -i rtsp://admin:admin1234@192.168.1.64:554/h264/ch1/sub/av_stream -codec copy -f ...

  7. rtsp服务器搭建_如何从“零”开始搭建直播平台

    喜欢就点关注哦~ 直播平台搭建 直播间从2015年直播元年开始,到现在依然火热不衰,直播在2015年还是相对神秘,但是如今更多的人会想要去了解.熟悉它,就要去解开这层面纱,今天小编就教你如何从零开始搭 ...

  8. 开源流媒体解决方案,流媒体服务器,推拉流,直播平台,SRS,WebRTC,移动端流媒体,网络会议,优秀博客资源等分享

    开源流媒体解决方案,流媒体服务器,推拉流,直播平台,SRS,WebRTC,移动端流媒体,网络会议,优秀博客资源等分享 一.优秀的流媒体博客资源 1.1 EasyNVR:专注于安防视频互联网化的技术 1 ...

  9. RTSP 和 RTMP原理 通过ffmpeg实现将本地摄像头推流到RTSP服务器

    RTSP 和 RTMP原理 & 通过ffmpeg实现将本地摄像头推流到RTSP服务器 文章目录 RTSP 和 RTMP原理 & 通过ffmpeg实现将本地摄像头推流到RTSP服务器 一 ...

最新文章

  1. 01矩阵等比放大(Java代码、ACM格式)--2021.9.7百度笔试研发A卷
  2. python评语生成_如何评价生成模型框架 ZhuSuan?
  3. python线性回归实例_python 线性回归示例
  4. 使用DOM操作样式表
  5. JavaScript--获取页面盒子中鼠标相对于盒子上、左边框的坐标
  6. sklearn自学指南(part10)--Lasso及多任务Lasso
  7. 数学--数论---欧拉筛 模板
  8. Golang的CSP很酷?其实.NET也可以轻松完成
  9. sgu 240 Runaway (spfa)
  10. php mysql设计中验证码的实现_php如何实现验证码功能
  11. unity 灯光阴影
  12. Windows系统服务器IIS7.5 Asp.net支持10万请求的设置方法
  13. MySQL联合查询及取别名
  14. java字段映射成其他字段名称_java字段与数据库字段映射
  15. Python3批量爬取指定微博中的图片
  16. ArcGIS更多颜色调配
  17. 【Zeekr_Tech】汽车软件敏捷开发和分支管理
  18. [Android] 该文件包与具有同一名称的现有文件包存在冲突
  19. ExcludeClipRect和无闪烁图像
  20. NASA 美国国家航空航天局开源 253 个 NASA 软件项目

热门文章

  1. Android Studio 启动问题(does not point to a valid jvm installation)
  2. java数据结构之数组
  3. 史上最全面的DateUtils工具类
  4. Delphi2010使用QQ邮箱发送邮件
  5. 2022年上半年软考模拟卷
  6. 查看Java虚拟机的运行状态
  7. CE认证EMC指令测试项及测试内容(智能开关)
  8. 统计各个年份出生的人数.如1996多少人,1997多少人
  9. 2023全国特种作业操作证低压电工模拟考试试卷一[安考星]
  10. Java 安全P2P网贷系统源码发布