1、目前封装

c++ 封装h264 和 aac 成为flv,里面没有加script,但是可以用,后会把script加上,用在了把rtsp 汇流成flv,数据形式是拷贝进去的,如果有兴趣,可以进行零拷贝方式发送
 1 因为传输层是tcp,所以可以把头部和数据分开发送,这样增加了发送的次数
 2 可以把码流收入到缓存中,缓存预留 4+11+5 和 4+ 11 +2

视频 4+ 11 +5 + 数据
音频 4+ 11 +2 + 数据

以上两种方法都可以

或者直接去gitee下载就行

2、准备一个头文件,包含就能用

/*
author :qianbo
email  :418511899@qq.com
听雨堂 丁香结
address https://gitee.com/guanzhi0319/flvmux/
*/听雨堂 丁香结
*/
#pragma once
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <mutex>
using namespace std;enum {FLV_TAG_TYPE_AUDIO = 0x08,FLV_TAG_TYPE_VIDEO = 0x09,FLV_TAG_TYPE_META = 0x12,
};
#define FLV_TAG_HEAD_LEN 11
#define FLV_PRE_TAG_LEN 4//#ifndef _WIN32
//struct FLVTag {//  uint8_t type;
//  uint8_t data_size[3];
//  uint8_t timestamp[3];
//  uint8_t timestamp_ex;
//  uint8_t streamid[3];
//} __attribute__((__packed__));
//#else
//#pragma   pack(push,1)
//typedef struct FLVTag {//  uint8_t type;
//  uint8_t data_size[3];
//  uint8_t timestamp[3];
//  uint8_t timestamp_ex;
//  uint8_t streamid[3];
//}FLVTag;
//#pragma   pack(pop)
//#endif
typedef struct PutBitContext
{unsigned int bit_buf;int bit_left;char *buf, *buf_ptr, *buf_end;int size_in_bits;
} PutBitContext;static inline void init_put_bits(PutBitContext *s, char *buffer, int buffer_size)
{if (buffer_size < 0) {buffer_size = 0;buffer = 0;}s->size_in_bits = 8 * buffer_size;s->buf = buffer;s->buf_end = s->buf + buffer_size;s->buf_ptr = s->buf;s->bit_left = 32;s->bit_buf = 0;
}static inline void put_bits(PutBitContext *s, int n, unsigned int value)
{unsigned int bit_buf;int bit_left;bit_buf = s->bit_buf;bit_left = s->bit_left;if (n < bit_left) {bit_buf = (bit_buf << n) | value;bit_left -= n;}else {bit_buf <<= bit_left;bit_buf |= value >> (n - bit_left);UI32ToBytes((uint8_t*)s->buf_ptr, bit_buf);//AV_WB32(s->buf_ptr, bit_buf);//printf("bitbuf = %08x\n", bit_buf);s->buf_ptr += 4;bit_left += 32 - n;bit_buf = value;}s->bit_buf = bit_buf;s->bit_left = bit_left;
}
static inline void flush_put_bits(PutBitContext *s)
{s->bit_buf <<= s->bit_left;while (s->bit_left < 32) {*s->buf_ptr++ = s->bit_buf >> 24;s->bit_buf <<= 8;s->bit_left += 8;}s->bit_left = 32;s->bit_buf = 0;
}inline char* DoubleToBytes(char* buf, double val)
{union {unsigned char dc[8];double dd;} d;unsigned char b[8];d.dd = val;b[0] = d.dc[7];b[1] = d.dc[6];b[2] = d.dc[5];b[3] = d.dc[4];b[4] = d.dc[3];b[5] = d.dc[2];b[6] = d.dc[1];b[7] = d.dc[0];memcpy(buf, b, 8);return buf + 8;
}inline uint8_t* UI08ToBytes(uint8_t* buf, unsigned char val)
{buf[0] = (uint8_t)(val) & 0xff;return buf + 1;
}inline uint8_t* UI16ToBytes(uint8_t* buf, unsigned short val)
{buf[0] = (uint8_t)(val >> 8) & 0xff;buf[1] = (uint8_t)(val) & 0xff;return buf + 2;
}
inline uint8_t* UI24ToBytes(uint8_t* buf, unsigned int val)
{buf[0] = (uint8_t)(val >> 16) & 0xff;buf[1] = (uint8_t)(val >> 8) & 0xff;buf[2] = (uint8_t)(val) & 0xff;return buf + 3;
}
inline uint8_t* UI32ToBytes(uint8_t* buf, unsigned int val)
{buf[0] = (uint8_t)(val >> 24) & 0xff;buf[1] = (uint8_t)(val >> 16) & 0xff;buf[2] = (uint8_t)(val >> 8) & 0xff;buf[3] = (uint8_t)(val) & 0xff;return buf + 4;
}typedef enum enum_av{enum_av_a = 0x04,enum_av_v = 0x01,enum_av_av = 0x05
}enum_av;
typedef struct s_av_config
{uint8_t *sps = NULL;int len_sps = 0;uint8_t* pps = NULL;int len_pps = 0; enum_av flag_av;int samplerate = 44100;int channel = 2;
}s_av_config;class c_flv_mux
{private:std::mutex  m_mutex;uint8_t * m_meta_data = NULL;//9 bytes header + 4 bytes pretag length = 0char * m_header = "FLV\x1\x5\0\0\0\x9\0\0\0\0";
public:class Lock {private:std::unique_lock<std::mutex> _lock;public:inline Lock(c_flv_mux* parent) : _lock(parent->m_mutex) {}};uint8_t* flv_header(uint8_t* header, bool is_have_audio, bool is_have_video){if (is_have_audio && is_have_video)header[4] = 0x05;else if (is_have_audio && !is_have_video)header[4] = 0x04;else if (!is_have_audio && is_have_video)header[4] = 0x01;elseheader[4] = 0x00;return header + 13;}uint8_t * connect_meta(const char * connect_url, int len_conurl, const char * addtion ,int len_add){// /live/userid//四字节pretag size 11字节头部 + int len_data = len_conurl + len_add;//两个空格int len_frame = 11 + 2 + len_data;//除去11个字节的头部int len_body =  len_data;int len_data = len_conurl + len_add;uint8_t * meta_data = new uint8_t[len_frame + 4];//}protected:    void flv_write_11_header(uint8_t *buf, uint32_t len_body,uint32_t timestamp, uint8_t tag_type){uint8_t* pos = buf;//flvtag 11字节*pos++= tag_type;//  0x09-> video | 0x08-> audio*pos++ = (uint8_t)(len_body >> 16); //data len*pos++ = (uint8_t)(len_body >> 8); //data len*pos++ = (uint8_t)(len_body); //data len*pos++ = (uint8_t)(timestamp >> 16); //time stamp*pos++ = (uint8_t)(timestamp >> 8); //time stamp*pos++ = (uint8_t)(timestamp); //time stamp*pos++ = (uint8_t)(timestamp >> 24); //time stamp*pos++ = 0x00; //stream id 0*pos++ = 0x00; //stream id 0*pos   = 0x00; //stream id 0return;}void flv_header_v_tag(uint8_t *buf,const uint8_t *sps, uint32_t len_sps,const uint8_t *pps, uint32_t len_pps){int len_data = len_sps + len_pps;int len_frame = 11 + 16 + len_data;//除去11个字节的头部int len_body = 16 + len_data;flv_write_11_header(buf, len_body, 0, FLV_TAG_TYPE_VIDEO);//buf's length  11 + len_sps + len_pps + 16 bytes + 4bytes (last pretag lenth)//int bodylen = 11 + sps_len + pps_len + 16;//uint8_t *buf = (uint8_t *)malloc(bodylen + 4);//留出11个字节uint8_t * pos = buf + 11;//flv VideoTagHeader*pos++ = 0x17; //key frame, AVC*pos++ = 0x00; //avc sequence header*pos++ = 0x00; //composit time *pos++ = 0x00; //composit time*pos++ = 0x00; //composit time*pos++ = 0x01;   //configurationversion*pos++ = sps[1]; //avcprofileindication*pos++ = sps[2]; //profilecompatibilty*pos++ = sps[3]; //avclevelindication*pos++ = 0xff;   //reserved + lengthsizeminusone*pos++ = 0xe1;   //numofsequenceset*pos++ = (uint8_t)(len_sps >> 8); //sequence parameter set length high 8 bits*pos++ = (uint8_t)(len_sps); //sequence parameter set  length low 8 bitsmemcpy(pos, sps, len_sps); //H264 sequence parameter setpos += len_sps;*pos++ = 0x01; //numofpictureset*pos++ = (uint8_t)(len_pps >> 8); //picture parameter set length high 8 bits*pos++ = (uint8_t)(len_pps); //picture parameter set length low 8 bitsmemcpy(pos, pps, len_pps); //H264 picture parameter setpos += len_pps;*pos++ = (uint8_t)(len_frame >> 24); //data len*pos++ = (uint8_t)(len_frame >> 16); //data len*pos++ = (uint8_t)(len_frame >> 8); //data len*pos = (uint8_t)(len_frame); //data len}void flv_header_a_tag(uint8_t * buf,int sample_rate, int channels){//11字节的tag ,音频4字节头部,4字节pretag长度int len_data = 4;int len_frame = 11 + 4;//除去11个字节的头部int len_body = len_data;flv_write_11_header(buf, len_body, 0, FLV_TAG_TYPE_AUDIO);uint8_t *pbuf = buf + 11;/* SoundFormat|SoundRate|SoundSize|SoundType:0xa0|0x0c|0x02|0x01*/pbuf = UI08ToBytes(pbuf, 0xaf);//unsigned char flag = 0;//flag = (10 << 4) |  // soundformat "10 == AAC"//   (3 << 2) |      // soundrate   "3  == 44-kHZ"//                   //(0<<1) |//  (1 << 1) |      // soundsize   "1  == 16bit"//    1;              // soundtype   "1  == Stereo" pbuf = UI08ToBytes(pbuf, 0); // AACPacketType: 0x00 - AAC sequence headerint put_value = 0;switch (sample_rate){case 44100:put_value = 0x04;break;case 16000:put_value = 0x08;break;case 64000:put_value = 0x02;break;case 22050:put_value = 0x07;break;case 8000:put_value = 0x0b;break;}//  0: 96000 Hz      //  1 : 88200 Hz        //  2 : 64000 Hz//  3 : 48000 Hz    //  4 : 44100 Hz        //  5 : 32000 Hz//  6 : 24000 Hz    //  7 : 22050 Hz        //  8 : 16000 Hz//  9 : 12000 Hz    //  10 : 11025 Hz       //  11 : 8000 Hz//  12 : 7350 Hz    //  13 : Reserved       //  14 : Reserved// 15 : frequency is written explictlyPutBitContext pb;init_put_bits(&pb, (char*)pbuf, 16);put_bits(&pb, 5, 2);    //object type - AAC-LC//44100HZ 0x1210 --- 16000HZ 0x1410 --- 8000HZ 0x1590 --- 22050HZ 0x1390put_bits(&pb, 4, put_value); //sample rate index, 44100 or 16000 or otherput_bits(&pb, 4, 2);    //channel configuration//GASpecificConfigput_bits(&pb, 1, 0);    //frame length - 1024 samplesput_bits(&pb, 1, 0);    //does not depend on core coderput_bits(&pb, 1, 0);    //is not extensionflush_put_bits(&pb);pbuf += 2;UI32ToBytes(pbuf, len_frame);}#define Pre_Tag_Len 4//返回包长度inline int flv_v_len(int dlen){int bodylen = 11 + 5 + dlen;return bodylen + Pre_Tag_Len;}inline int flv_a_len(int dlen){int bodylen = 11 + 2 + dlen;return bodylen + Pre_Tag_Len;}//获取视频长度int flv_header_v_tag_len(int spslen, int ppslen){int bodylen = 11 + spslen + ppslen + 16;return bodylen + Pre_Tag_Len;}int flv_header_a_tag_len(){int bodylen = 11 + 4;return bodylen + Pre_Tag_Len;}public:int InitMeta(s_av_config *savconfig){//_meta_data = new char[]if (savconfig == NULL)return -1;int len_total = 0;int len_video = 0;int len_audio = 0;if (savconfig->flag_av & enum_av_v)len_video = flv_header_v_tag_len(savconfig->len_sps, savconfig->len_pps);if (savconfig->flag_av & enum_av_a)len_audio = flv_header_a_tag_len();len_total = 13 + len_video + len_audio;if (len_total == 0)return -1;m_header[4] = savconfig->flag_av;m_meta_data = new uint8_t[len_total];memcpy(m_meta_data, m_header, 13);uint8_t * pos = &m_meta_data[0] + 13;if (savconfig->flag_av & enum_av_v){flv_header_v_tag(pos,savconfig->sps, savconfig->len_sps,savconfig->pps, savconfig->len_pps);pos += len_video;}if (savconfig->flag_av & enum_av_a){flv_header_a_tag(pos, savconfig->samplerate, savconfig->channel);}}/*bodylen = 11 + 5 + dlen写入buf中*/int flv_data_v(uint8_t * buf ,const uint8_t *data,uint32_t data_len,uint32_t time_stamp, int is_keyframe){int len_frame = 11 + 5 + data_len;//除去11个字节的头部int len_body = 5 + data_len ;//buf lenth is frame_len + 4 ;//写入11个字节的头部flv_write_11_header(buf, len_body, time_stamp, FLV_TAG_TYPE_VIDEO);uint8_t *pbuf = buf + 11;uint8_t flag = 0;// (FrameType << 4) | CodecID, 1 - keyframe, 2 - inner frame, 7 - AVC(h264)if (is_keyframe)flag = 0x17;elseflag = 0x27;pbuf = UI08ToBytes(pbuf, flag);pbuf = UI08ToBytes(pbuf, 1);// AVCPacketType: 0x00 - AVC sequence header; 0x01 - AVC NALUpbuf = UI24ToBytes(pbuf, 0);// composition timememcpy(pbuf, data, data_len);pbuf += data_len;UI32ToBytes(pbuf, len_frame);return flv_v_len(data_len);}int flv_data_a(uint8_t * buf,const uint8_t *data, uint32_t data_len,uint32_t time_stamp){/* strip ADTS from frame *///跳过7个字节if (*buf == 0xff){data_len -= 7;data = data + 7;}int len_frame = 11 + 2 + data_len;//除去11个字节的头部int len_body = 2 + data_len;//uint8_t *buf = (uint8_t *)malloc(bodylen + 4);//写入11个字节的头部flv_write_11_header(buf, len_body, time_stamp, FLV_TAG_TYPE_AUDIO);uint8_t *pbuf = buf + 11;/* SoundFormat|SoundRate|SoundSize|SoundType:0xa0|0x0c|0x02|0x01*/pbuf = UI08ToBytes(pbuf, 0xaf);pbuf = UI08ToBytes(pbuf, 1); // AACPacketType: 0x01 - AAC frame datamemcpy(pbuf, data, data_len);//pbuf += payload_len;pbuf += data_len;UI32ToBytes(pbuf, len_frame);return flv_a_len(data_len);}};

h264 aac mux flv相关推荐

  1. 人肉解析系列(一)————FLV-java你所关心的,我这里都有。附源码。非FFmpeg相关,纯java人肉解析。手写FLV。H264 AAC转FLV

    第一次写博客,不知道有没有什么潜规则.总之呢,是好是坏都已经在落笔的那一刻开始了. 说起直播,各位都不陌生,毕竟国内这几年直播,短视频等视频行业大火,让所有程序员对直播都能如数家珍,随口便能讲出几种协 ...

  2. H264和AAC合成FLV案例

    H264和AAC合成FLV案例 目录 FFmpeg合成流程 FFmpeg函数:avformat_write_header FFmpeg结构体:avformat_alloc_output_context ...

  3. 1小时学会:最简单的iOS直播推流(六)h264、aac、flv介绍

    最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有,愿意懂直播技术的同学快来看!! 源 ...

  4. flv封装H264+AAC[附完整代码]

    一. 概述 总体来说比较简单这里就不详述了,参考官方文档即可<Video File Format Specification Version 10>,其中aac和h264的sequence ...

  5. 1小时学会:最简单的iOS直播推流(八)h264/aac 软编码

    最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有,愿意懂直播技术的同学快来看!! 源 ...

  6. 1小时学会:最简单的iOS直播推流(七)h264/aac 硬编码

    最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有,愿意懂直播技术的同学快来看!! 源 ...

  7. hls直播实现源码V2(h264,aac流输入,ffmpeg实现,MFC,VC环境,ts,m3u8)

    周星驰来也! 像很多80,90后年轻人(老男人吧)一样,周星驰一直就是哥喜爱的电影演员之一,不仅喜欢星爷的人物形象,更是喜欢这种乐观向上的精神!(哥16年的QQ一直就是周星驰这个昵称). 转入主题吧: ...

  8. send/receive h264/aac file/data by rtp/rtsp over udp/tcp

    一.安装一些必要的调试工具 1.vlc安装 sudo apt-get install vlc sudo apt-get install vlc-nox 2.ffmpeg安装,带ffplay,ffpla ...

  9. NDK学习笔记:RtmpPusher之利用rtmpdump推h264/aac码流

    NDK学习笔记:RtmpPusher之利用rtmpdump推h264/aac码流 本篇将是 RtmpPusher 的最后一篇.在之前的3篇文章里,我们已经把原生的视频YUV格式编码成h264,把音频的 ...

最新文章

  1. lingo变量无限制版本_java变量必看知识点
  2. 抽象工厂模式java_面试官:说一下静态工厂模式,工厂方法模式,抽象工厂的区别吧...
  3. 数学建模必备算法之模拟退火算法
  4. jquery --- 控制元素的隐藏/显示
  5. android 小黄车首页,android采用MVP漫画APP、适配刘海屏、小黄车主界面、录音波浪动画、综合APP等源码...
  6. linux 中文ssid 显示,无法连接中文 SSID 的 Wi-Fi?简单几步就搞定!
  7. linux黑板模式,敲黑板!怎样使用 Linux stat 命令创建灵活文件列表?
  8. 常用的色彩名、色彩值的对照表
  9. blockquote 和 q 标签 css样式
  10. 《Effective Java 3rd》读书笔记——泛型
  11. 服务器虚拟化基础hcna,华为云计算全新大纲课程 乾颐堂HCNA-Cloud服务器虚拟化云计算实战课程 HCNA认证课程...
  12. 基于自适应惯性权重的樽海鞘群算法
  13. 本学期计算机课总结,大学生计算机基础学期总结
  14. IMAGE_DOS_HEADER解析
  15. php phpunit_framework_testcase,开始使用PHPUnit
  16. 搞独立运动,万人如海一身藏
  17. java 设置excel颜色_Java 为 Excel 中的行设置交替背景色
  18. [安卓开发] Broadcast 三种广播的使用总结
  19. Chromedriver适用谷歌浏览器的各个版本
  20. Python 与 Excel 终于互通了 !

热门文章

  1. c oracle 多条语句,Oracle 实践:如何编写一条 sql 语句获取数据表的全部索引信息(兼容 Oracle 19c、Oracle 11g)...
  2. 江苏约谈滴滴、T3出行等6家企业 因疫情防控落实不到位
  3. 小米获京东自营安卓平板销量冠军 小米平板5 Pro全版本闪降100元
  4. 北京冬奥会科技感十足多家科技公司助力
  5. 因遭做空机构指控存在金融欺诈 法拉第未来聘请律所展开调查
  6. 由于供不应求 部分新款Apple Watch机型推迟至11月交付
  7. 小鹏汽车4月交付量5147台 同比增长285%
  8. 百度Apollo放出豪言:下半年每月上市一款新车
  9. 小米11系列最新曝光:国内首发骁龙875 还有独占期
  10. 共享单车变身“行走的弹幕”,清华大学等17所高校均有投放