一. 概述

总体来说比较简单这里就不详述了,参考官方文档即可《Video File Format Specification Version 10》,其中aac和h264的sequence header tag部分需要参考另外两分文档(这个在《Video File Format Specification Version 10》里有说明),这两份文档不太好找,找到的官方的还要收钱,我最终找到了一份.doc文档,其实这两个文档就介绍了一下两个结构体其他信息在这里没有什么参考价值,可以根据将h.264视频流封装成flv格式文件(二.开始动手)  这篇文档中的两个图表来完成aac和h264的sequence header tag的填充。

我在github上找到了Akagi201写的代码,并在他的基础上进行了完善。aac编码部分在我的另外一片文章里面有讲述fdk-aac编码及mp4v2封装h264+aac[完整code]

flvmuxer实现了h264+aac的封装并在最后通过加入onMEtadata:duration这一scriptdata tag来告诉demuxer视频的时长。

二. 代码

以下部分是demo示例,详细代码请访问github:https://github.com/steveliu121/pistreamer/tree/master/flvmuxer

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <stdint.h>
#include <pthread.h>
#include <errno.h>#include "aacenc.h"
#include "flvmuxer.h"
#include "rts_middle_media.h"
#include <qcam_video_input.h>/* XXX:WARNING the pcm period buf length should be the common factor of* the aac input pcm frame length, or the aac timestamp will be wrong* here the pcm period buf length == 1024 bytes,* and the aac input pcm frame length == 2048*/#define SPS_LEN      28
#define PPS_LEN     6
#define OUTFILE     "my.flv"#define RES_720P
#ifdef RES_720P
#define RESOLUTION_720P QCAM_VIDEO_RES_720P
#define RES_WIDTH   1280
#define RES_HEIGHT  720
#endif#define VIDEO_FPS     15
#define VIDEO_TIME_SCALE    90000
#define VIDEO_SAMPLE_DURATION   (VIDEO_TIME_SCALE / VIDEO_FPS)#define AUDIO_SAMPLERATE  8000
#define AUDIO_CHANNELS      1
#define AUDIO_TIME_SCALE    (AUDIO_SAMPLERATE * AUDIO_CHANNELS)
/* (AUDIO_TIME_SCALE / AUDIO_FPS)audio_period_time = 64ms, fps = 15.625 */
#define AUDIO_SAMPLE_DURATION   512
#define AAC_BITRATE     16000static const uint8_t sps_buf[SPS_LEN] = {0x27, 0x64, 0x00, 0x29, 0xac, 0x1a, 0xd0, 0x0a,0x00, 0xb7, 0x4d, 0xc0, 0x40, 0x40, 0x50, 0x00,0x00, 0x03, 0x00, 0x10, 0x00 ,0x00, 0x03, 0x01,0xe8, 0xf1 ,0x42, 0x2a};
static const uint8_t pps_buf[PPS_LEN] = {0x28, 0xee, 0x01, 0x34, 0x92, 0x24};
/*
static const uint8_t sps_buf[SPS_LEN + 4] = {0x00, 0x00, 0x00, 0x1c, 0x27, 0x64,0x00, 0x29, 0xac, 0x1a, 0xd0, 0x0a,0x00, 0xb7, 0x4d, 0xc0, 0x40, 0x40, 0x50, 0x00,0x00, 0x03, 0x00, 0x10, 0x00 ,0x00, 0x03, 0x01,0xe8, 0xf1 ,0x42, 0x2a};
static const uint8_t pps_buf[PPS_LEN + 4] = {0x00, 0x00, 0x00, 0x06, 0x28, 0xee,0x01, 0x04, 0x92, 0x24};*/
static int g_exit;
static HANDLE_AACENCODER aac_enc_hd;
static uint8_t aac_decoder_conf[64];
static int aac_decoder_conf_len;
static FILE *flv_hd;void sig_handle(int sig)
{g_exit = 1;
}void h264_cb(const struct timeval *tv, const void *data,const int len, const int keyframe)
{uint8_t *buf = NULL;int buf_len = 0;uint32_t timestamp = 0;int buf_payload_len = 0;timestamp = (tv->tv_sec * 1000) + (tv->tv_usec / 1000);/* strip sps/pps from I frame and* replace NALU start flag '0x00/0x00/0x00/0x01' with* the length of NALU in BIGENDIAN*/if (keyframe) {buf = (uint8_t *)data + SPS_LEN + PPS_LEN + 2 * 4;buf_len = len - SPS_LEN - PPS_LEN - 2 * 4;} else {buf = (uint8_t *)data;}buf_payload_len = buf_len - 4;buf[0] = buf_payload_len >> 24;buf[1] = buf_payload_len >> 16;buf[2] = buf_payload_len >> 8;buf[3] = buf_payload_len & 0xff;flv_write_avc_data_tag(flv_hd, buf, buf_len, timestamp, keyframe);
}void audio_cb(const struct timeval *tv, const void *pcm_buf,const int pcm_len, const void *spk_buf)
{uint8_t *aac_buf = NULL;int aac_buf_len = 0;uint32_t timestamp = 0;timestamp = (tv->tv_sec * 1000) + (tv->tv_usec / 1000);aac_buf_len = aac_encode(aac_enc_hd, pcm_buf, pcm_len, &aac_buf);if (aac_buf_len == 0)return;flv_write_aac_data_tag(flv_hd, aac_buf, aac_buf_len, timestamp);
}int main(int argc, char *argv[])
{int ret = 0;struct FLVProfile flv_profile = {.name = OUTFILE,.has_video = true,.has_audio = true,.sample_rate = AUDIO_SAMPLERATE,.channels = AUDIO_CHANNELS,.sps = sps_buf,.pps = pps_buf,.sps_len = SPS_LEN,.pps_len = PPS_LEN};QCamVideoInputChannel chn = {.channelId = 0,.res = RESOLUTION_720P,.fps = VIDEO_FPS,.bitrate = 1024,.gop = 1,.vbr = YSX_BITRATE_MODE_CBR,.cb = h264_cb};QCamVideoInputOSD osd_info = {.pic_enable = 0,.pic_path = "/usr/osd_char_lib/argb_2222",.pic_x = 200,.pic_y = 200,.time_enable = 1,.time_x = 100,.time_y  = 100};QCamAudioInputAttr_aec audio_in = {.sampleRate = AUDIO_SAMPLERATE,.sampleBit = 16,.volume = 95,.cb = audio_cb};signal(SIGTERM, sig_handle);signal(SIGINT, sig_handle);ret = create_aac_encoder(&aac_enc_hd,AUDIO_CHANNELS, AUDIO_SAMPLERATE, AAC_BITRATE,aac_decoder_conf, &aac_decoder_conf_len);if (ret < 0)goto exit;ret = create_flv_muxer(&flv_hd, &flv_profile);if (ret < 0)goto exit;QCamAV_Context_Init();ret = QCamVideoInput_Init();if (ret)goto out;ret = QCamVideoInput_AddChannel(chn);if (ret)goto out;ret = QCamVideoInput_SetOSD(chn.channelId, &osd_info);if (ret)goto out;ret = QCamAudioInputOpen_ysx(&audio_in);if (ret)goto out;ret = QCamVideoInput_Start();if (ret)goto out;ret = QCamAudioInputStart();if (ret)goto out;while (!g_exit)sleep(1);out:QCamVideoInput_Uninit();QCamAudioInputStop();QCamAudioInputClose_ysx();QCamAV_Context_Release();exit:destroy_aac_encoder(&aac_enc_hd);destroy_flv_muxer(flv_hd);return ret;}

flv封装H264+AAC[附完整代码]相关推荐

  1. Three.js实例详解___旋转的精灵女孩(附完整代码和资源)(一)

    Three.js实例详解___旋转的精灵女孩(附完整代码和资源)(一) 本文目录: 一.[旋转的精灵女孩]案例运行效果 二.Three.js简介 三.Three.js代码正常运行显示条件 (1)不载入 ...

  2. 吴恩达机器学习python实现(6):SVM支持向量机(文末附完整代码)

    所有的数据来源:链接:https://pan.baidu.com/s/1vTaw1n77xPPfKk23KEKARA 提取码:5gl2 1 Support Vector Machines 1.1 Pr ...

  3. SpringSecurity的安全认证的详解说明(附完整代码)

    SpringSecurity登录认证和请求过滤器以及安全配置详解说明 环境 系统环境:win10 Maven环境:apache-maven-3.8.6 JDK版本:1.8 SpringBoot版本:2 ...

  4. php 3d animation,css3D+动画的例子(附完整代码)

    本篇文章给大家带来的内容是关于css3D+动画的例子(附完整代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 前言 最近玩了玩用css来构建3D效果,写了几个demo,所以博客总 ...

  5. Py之pygame:有趣好玩—利用pygame库实现鱼儿自动实时目标跟踪(附完整代码)

    Py之pygame:有趣好玩-利用pygame库实现鱼儿自动实时目标跟踪(附完整代码) 目录 输出结果 实现代码 输出结果 实现代码 #Py之pygame:利用pygame库实现鱼儿自动实时目标跟踪i ...

  6. c++代码好玩_Py之pygame:有趣好玩—利用pygame库实现鱼儿自动实时目标跟踪(附完整代码)...

    Py之pygame:有趣好玩-利用pygame库实现鱼儿自动实时目标跟踪(附完整代码) 目录 输出结果 实现代码 输出结果 ​ 实现代码 #Py之pygame:利用pygame库实现鱼儿自动实时目标跟 ...

  7. OpenCV基本线性变换轨迹栏的实例(附完整代码)

    OpenCV基本线性变换轨迹栏的实例 OpenCV基本线性变换轨迹栏的实例 OpenCV基本线性变换轨迹栏的实例 OpenCV基本线性变换轨迹栏的实例(附完整代码) #include "op ...

  8. OpenCV差分二值化的实时场景文本检测的实例(附完整代码)

    OpenCV差分二值化的实时场景文本检测的实例 OpenCV差分二值化的实时场景文本检测的实例 OpenCV差分二值化的实时场景文本检测的实例 OpenCV差分二值化的实时场景文本检测的实例(附完整代 ...

  9. 单选按钮_PerlTk教程之按钮Button、复选按钮Checkbutton、单选按钮Radiobutton(附完整代码)...

    <Perl-Tk教程之按钮Button.复选按钮Checkbutton.单选按钮Radiobutton>Perl-Tk中有三种不同形式的按钮组件可供选择,它们分别是按钮(Button), ...

最新文章

  1. RuntimeError: each element in list of batch should be of equal size
  2. 创建数据源(ODBC)
  3. 如何为WCF应用添加X509证书和安全验证
  4. 爱立信:用什么保持全球老大的地位?
  5. Oracle数据库asm原理,Oracle数据库中ASM功能解剖
  6. vba 邮件body html,Excel VBA中的Outlook电子邮件和签名 – .Body vs .HTMLbody
  7. linux 日期 通配符,Linux常用基础命令下(grep,history,du,date,通配符,alias,rm,mv,cp)
  8. 苏宁易购:苏宁控股、苏宁电器合计质押约5.18亿股公司股份
  9. STL泛型编程之map映照容器
  10. 10 亿产业基金加持,让精准定位在物联网应用中实现无限可能!
  11. .NET程序中常用的28种代码
  12. 【ZOJ 4097 The 19th Zhejiang University Programming Contest H】Rescue the Princess【边双连通缩点+LCA】
  13. 逻辑表达式三种化简方法
  14. Python-nan,NaN,NAN
  15. 【Questasim】报错001 Failed to access library
  16. 低代码搭建医疗企业数字化CRM案例分析
  17. SVN报错:can't open file db/txn-current-lock:permission denied 解决方法
  18. 微信公众号JS-SDK多图上传爬坑指南
  19. Cool Edit之生成.pk文件问题
  20. 脚手架--------Yeoman基本使用

热门文章

  1. 高效记忆/形象记忆(01) 记忆原理
  2. Keil工程下各个后缀名文件的作用
  3. 任正非:5G关系着公司的生死存亡,不惜代价要赢!
  4. haproxy实现7层的负载均衡[haproxy+pacemaker+fencing]
  5. spring boot 根据模板导出word功能实现,包含html内容,及office打开乱码问题的解决!!!
  6. 淘宝API应用调用官方买家信息数据
  7. Aurora ip核的使用详解
  8. 05机器学习--多项式回归与模型泛化及python实现
  9. 字典序及1-n之间的数按字典序排列
  10. 恒指怎么开户?恒指交易原则?