09-流媒体-FLV解复用
整体方案:
采集端:摄像头采集(YUV)->编码(YUV转H264)->写封装(H264转FLV)->RTMP推流
客户端:RTMP拉流->解封装(FLV转H264)->解码(H264转YUV)->YUV显示(SDL2)
#include <stdio.h>#define __STDC_CONSTANT_MACROSextern "C"
{
#include "libavformat/avformat.h"
};//封装格式MKV/MP4/FLV中如果有AAC的情况,首先这些封装格式中包含AudioSpecificConfig,
//保存在音频流的AVCodecContext->extradata 里面,需要解析然后封装ADTS即可#define DEMUXER_AAC 1
#define DEMUXER_MP3 0#define ADTS_HEADER_SIZE (7)//FLV封装音视频 AAC封装在第一个AAC TAG会封装一个AudioSpecificConfig结构
//AudioSpecificConfig解析结果保存在该结构体中
typedef struct
{int write_adts; int objecttype; int sample_rate_index; int channel_conf; }ADTSContext; //解析AudioSpecificConfig
int aac_decode_extradata(ADTSContext *adts, unsigned char *pbuf, int bufsize)
{ int aot, aotext, samfreindex; int i, channelconfig; unsigned char *p = pbuf; if (!adts || !pbuf || bufsize<2) { return -1; } aot = (p[0]>>3)&0x1f; if (aot == 31) { aotext = (p[0]<<3 | (p[1]>>5)) & 0x3f; aot = 32 + aotext; samfreindex = (p[1]>>1) & 0x0f; if (samfreindex == 0x0f) { channelconfig = ((p[4]<<3) | (p[5]>>5)) & 0x0f; } else { channelconfig = ((p[1]<<3)|(p[2]>>5)) & 0x0f; } } else { samfreindex = ((p[0]<<1)|p[1]>>7) & 0x0f; if (samfreindex == 0x0f) { channelconfig = (p[4]>>3) & 0x0f; } else { channelconfig = (p[1]>>3) & 0x0f; } }
#ifdef AOT_PROFILE_CTRL if (aot < 2) aot = 2;
#endif adts->objecttype = aot-1; adts->sample_rate_index = samfreindex; adts->channel_conf = channelconfig; adts->write_adts = 1; return 0;
} //添加ADTS头
int aac_set_adts_head(ADTSContext *acfg, unsigned char *buf, int size)
{ unsigned char byte; if (size < ADTS_HEADER_SIZE) { return -1; } buf[0] = 0xff; buf[1] = 0xf1; byte = 0; byte |= (acfg->objecttype & 0x03) << 6; byte |= (acfg->sample_rate_index & 0x0f) << 2; byte |= (acfg->channel_conf & 0x07) >> 2; buf[2] = byte; byte = 0; byte |= (acfg->channel_conf & 0x07) << 6; byte |= (ADTS_HEADER_SIZE + size) >> 11; buf[3] = byte; byte = 0; byte |= (ADTS_HEADER_SIZE + size) >> 3; buf[4] = byte; byte = 0; byte |= ((ADTS_HEADER_SIZE + size) & 0x7) << 5; byte |= (0x7ff >> 6) & 0x1f; buf[5] = byte; byte = 0; byte |= (0x7ff & 0x3f) << 2; buf[6] = byte; return 0;
} int main(int argc, char* argv[])
{AVFormatContext *ifmt_ctx = NULL;AVPacket pkt;int ret, i;int videoindex=-1,audioindex=-1;#if DEMUXER_AACconst char *in_filename = "demo.flv"; //Input file URLconst char *out_filename_v = "demo.h264"; //Output file URLconst char *out_filename_a = "demo.aac";#endif#if DEMUXER_MP3const char *in_filename = "demo.flv"; //Input file URLconst char *out_filename_v = "demo.h264"; //Output file URLconst char *out_filename_a = "demo.mp3";#endifav_register_all();//Inputif ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {printf( "Could not open input file.");return -1;}if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {printf( "Failed to retrieve input stream information");return -1;}videoindex=-1;for(i=0; i<ifmt_ctx->nb_streams; i++) {if(ifmt_ctx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){videoindex=i;}else if(ifmt_ctx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO){audioindex=i;}}FILE *fp_audio=fopen(out_filename_a,"wb+"); FILE *fp_video=fopen(out_filename_v,"wb+"); //FLV/MP4/MKV等结构中,h264需要h264_mp4toannexb处理。添加SPS/PPS等信息。FLV封装时,可以把//多个NALU放在一个VIDEO TAG中,结构为4B NALU长度+NALU1+4B NALU长度+NALU2+...,需要做的处理把4B//长度换成00000001或者000001AVBitStreamFilterContext* h264bsfc = av_bitstream_filter_init("h264_mp4toannexb"); #if DEMUXER_AACADTSContext stADTSContext;unsigned char pAdtsHead[7];
#endifwhile(av_read_frame(ifmt_ctx, &pkt)>=0){if(pkt.stream_index==videoindex){av_bitstream_filter_filter(h264bsfc, ifmt_ctx->streams[videoindex]->codec, NULL, &pkt.data, &pkt.size, pkt.data, pkt.size, 0);printf("Write Video Packet. size:%d\tpts:%lld\n",pkt.size,pkt.pts);fwrite(pkt.data,1,pkt.size,fp_video);}else if(pkt.stream_index==audioindex){//AAC在封装结构MKV/FLV/MP4结构中,需要手动添加ADTS#if DEMUXER_AACaac_decode_extradata(&stADTSContext, ifmt_ctx->streams[audioindex]->codec->extradata, ifmt_ctx->streams[audioindex]->codec->extradata_size);aac_set_adts_head(&stADTSContext, pAdtsHead, pkt.size);fwrite(pAdtsHead, 1, 7, fp_audio);#endif//一般结构如MP3直接写文件即可printf("Write Audio Packet. size:%d\tpts:%lld\n",pkt.size,pkt.pts);fwrite(pkt.data,1,pkt.size,fp_audio);}av_free_packet(&pkt);}av_bitstream_filter_close(h264bsfc); fclose(fp_video);fclose(fp_audio);avformat_close_input(&ifmt_ctx);if (ret < 0 && ret != AVERROR_EOF) {printf( "Error occurred.\n");return -1;}return 0;
}
相关文章:
09-流媒体-FLV解复用
整体方案: 采集端:摄像头采集(YUV)->编码(YUV转H264)->写封装(H264转FLV)->RTMP推流 客户端:RTMP拉流->解封装(FLV转H264)…...
信息的浏览
万维网(WWW)是目前Internet上最流行的一种服务,它是建立在Internet上的多媒体集合信息系统。它利用超媒体的信息获取技术,通过一种超文本的表达方式,将所有WWW上的信息连接在一起。我们使用浏览器浏览网上的信息。 ▶浏览器 浏览器是指可以…...
vue directive自定义指令实现弹窗可拖动
vue2 创建一个js文件 // draggable.js export default {// 定义 Vue 插件install(Vue) {Vue.directive(draggable, { // 全局指令名为 v-draggableinserted(el) {el.onmousedown function (ev) {// 获取鼠标按下时的偏移量(鼠标位置 - 元素位置)const…...
07-流媒体-RTMP推流
整体方案: 采集端:摄像头采集(YUV)->编码(YUV转H264)->写封装(H264转FLV)->RTMP推流 客户端:RTMP拉流->解封装(FLV转H264)…...
Neo4j安装(Docker中安装Neo4j)
天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…...
面试求职者
顾x文 SQLite3数据的使用实现了多线程UDP数据收发功能Qt多线程的同步和异步熟悉GDB的调试了解Mysql的性能优化熟悉常见算法:快速排序、希尔排序、归并排序基于Nginx C Mysql Python ICE开发熟练Boost库负责搭建后台服务端,使用Nginx展示前端界面&am…...
Java NIO 详解
一、NIO简介 NIO 是 Java SE 1.4 引入的一组新的 I/O 相关的 API,它提供了非阻塞式 I/O、选择器、通道、缓冲区等新的概念和机制。相比与传统的 I/O 多出的 N 不是单纯的 New,更多的是代表了 Non-blocking 非阻塞,NIO具有更高的并发性、可扩…...
css设置下划线
css中设置下划线的方法 在CSS中可以使用text-decoration属性或border-bottom属性来给字体设置下划线样式。 1、使用text-decoration:underline;设置下划线样式 CSS的text-decoration属性用于指定添加到文本的修饰,其underline属性值可以定义文本下的一条线。 语…...
【献给过去的自己】栈实现计算器(C语言)
背景 记得在刚学C语言时,写了一篇栈实现计算器-CSDN博客文章。偶然间看到了文章的阅读量以及评论,居然有1.7w的展现和多条博友的点评,反馈。 现在回过头来看,的确有许多不严谨的地方,毕竟当时分享文章时,还…...
如何利用ChatGPT撰写学术论文?
在阅读全文前请注意,本文是利用ChatGPT“辅助完成”而不是“帮写”学术论文,请一定要注意学术规范! 本文我将介绍如何使用清晰准确的“指令”让ChatGPT帮助我们在论文写作上提高效率,希望通过本文的指导,读者能够充分…...
【PG】PostgreSQL高可用方案repmgr管理之配置文件
1 配置文件 1.1 配置文件格式 repmgr.conf是一个纯文本文件,每行包含一个参数/值组合。 空格是无关紧要的(除了在带引号的参数值内),并且空行将被忽略。#将该行的其余部分指定为注释。不是简单标识符或数字的参数值应该用单引号…...
labelme自动标注工具
可以实现多图中相同目标的追踪,自动标注目标位置,速度极快,有需要评论...
【C++学习手札】模拟实现vector
🎬慕斯主页:修仙—别有洞天 ♈️今日夜电波:くちなしの言葉—みゆな 0:37━━━━━━️💟──────── 5:28 🔄 ◀️ ⏸ ▶️ ☰…...
Python将图片按照表格形式排列
图片按照表格的形式排列,可以使用图像处理库Pillow来实现 事例代码 from PIL import Image, ImageDraw# 创建一个画布,用来存放排列后的图片 canvas Image.new(RGB, (800, 600), white)# 读取图片 im1 Image.open(image1.jpg) im2 Image.open(image…...
Linux 简要命令记录
1、设置时区: #设为上海: timedatectl set-timezone Asia/Shanghai #搜索特定时区 timedatectl list-timezone2、修改时间: #设定系统时间 date -s "2023-11-16 22:30:00" #同步写入BIOS hwclock -w3、fdisk分区 rootheihei:~# …...
深度学习与深度强化学习
1. 深度学习中卷积层的作用是什么?全连接层的作用是什么?二者有什么联系和区别? 在深度学习中,卷积层(Convolutional Layer)和全连接层(Fully Connected Layer)是神经网络中常见的两…...
C++函数重载中形参是引用类型和常量引用类型的调用方法
void fun(int &a) {cout<<"调用func(int &a)<<endl; }void fun(const int &a) {cout<<"调用func(const int &a)<<endl; }int main() {// 1.调用引用类型的函数int a10;func(a);// 2.调用常量引用类型的函数,因为…...
Quest 3期间Sui上游戏处理了数百万笔交易
Sui固有的可扩展性和低且可预测的gas费使其成为Web3游戏的理想平台。在Quest 3中,参与的游戏项目处理了数百万笔交易,这毫无疑问地展示了Sui卓越的能力。 Quest 3的主题是游戏,让开发者有机会向潜在玩家介绍他们激动人心的创作。鼓励这些玩家…...
Python中如何定义类、基类、函数和变量?
在Python中,定义类、基类、函数和变量是非常常见的操作。以下是简单的示例: 定义类: class Animal:def __init__(self, name):self.name namedef make_sound(self):passclass Dog(Animal):def make_sound(self):return "Woof!"上…...
打开文件 和 文件系统的文件产生关联
补充1:硬件级别磁盘和内存之间数据交互的基本单位 OS的内存管理 内存的本质是对数据临时存/取,把内存看成很大的缓冲区 物理内存和磁盘交互的单位是4KB,磁盘中未被打开的文件数据块也是4KB,所以磁盘中页帧也是4KB,内存…...
嵌入式图像处理实战:中值滤波 vs 均值滤波在STM32上的性能对比(附代码)
嵌入式图像处理实战:中值滤波 vs 均值滤波在STM32上的性能对比(附代码) 在机器人视觉或工业检测系统中,一个突如其来的像素噪点可能导致整个识别算法崩溃。我曾亲眼见证过某产线机械臂因图像传感器受到电磁干扰,将正常…...
Element UI表格样式改造避坑指南:透明化后文字看不清、边框错位怎么办?
Element UI表格透明化实战:解决文字模糊与样式错位的专业方案 当我们在Vue项目中采用Element UI的el-table组件实现透明化效果时,经常会遇到一些棘手的样式问题。本文将深入分析四个典型场景的成因,并提供经过实战检验的解决方案。 1. 透明背…...
FunASR Docker部署避坑大全:从SSL证书报错到热词不生效,一次解决所有常见问题
FunASR Docker实战排障指南:从证书配置到热词优化的深度解决方案 当你第一次尝试在Docker环境中部署FunASR语音识别服务时,那些看似简单的命令行参数背后可能藏着无数个"坑"。本文不会重复官方文档的基础操作,而是聚焦于五个最具代…...
Vivado平台下PCIe IP核选型指南:从硬核到XDMA的实战抉择
1. PCIe技术基础与Vivado开发环境搭建 第一次接触PCIe接口开发时,我被各种专业术语搞得晕头转向。后来才发现,理解PCIe就像理解高速公路系统一样简单。PCIe本质上是一种点对点的高速串行总线,就像城市间修建的多车道高速公路。每个"车道…...
MiniCPM-V-2_6嵌入式AI应用实战:STM32F103C8T6边缘推理集成
MiniCPM-V-2_6嵌入式AI应用实战:STM32F103C8T6边缘推理集成 最近几年,AI模型越来越“小”,开始往各种硬件设备里钻。你可能听说过在手机、树莓派上跑AI,但有没有想过,在一块只有指甲盖大小、主频72MHz、内存才20KB的S…...
系统架构设计师常见高频考点总结之计算机网络
学习这些网络题目时,可以将网络层次结构想象成高速公路系统:核心层是连接城市的大型立交桥和主干道,追求极速转发;汇聚层是出口闸机,负责检查通行证(安全过滤)和分流;而接入层则是通…...
像素风AI工具体验:像素史诗智识终端,让研究变得有趣又高效
像素风AI工具体验:像素史诗智识终端,让研究变得有趣又高效 1. 引言:当科研遇上像素冒险 想象一下:你是一位勇者,站在像素风格的城堡前,准备开始一场史诗般的冒险。但这次,你的武器不是剑与盾&…...
多平台资源嗅探与下载工具:解决网络资源获取难题的技术方案
多平台资源嗅探与下载工具:解决网络资源获取难题的技术方案 【免费下载链接】res-downloader 资源下载器、网络资源嗅探,支持微信视频号下载、网页抖音无水印下载、网页快手无水印视频下载、酷狗音乐下载等网络资源拦截下载! 项目地址: https://gitcod…...
Cassandra在大数据图像存储中的应用探索
Cassandra在大数据图像存储中的应用探索关键词:Cassandra、大数据、图像存储、分布式系统、数据管理摘要:本文旨在深入探索Cassandra在大数据图像存储领域的应用。我们将先介绍Cassandra的基本概念和特点,再详细分析它与大数据图像存储的适配…...
S2-Pro自动化运维脚本生成:应对Linux服务器常见管理任务
S2-Pro自动化运维脚本生成:应对Linux服务器常见管理任务 1. 运维工程师的新助手 最近遇到个挺有意思的事。我们团队新来的运维小哥,处理服务器问题时总要先翻半天文档,再到处搜脚本模板。看着他手忙脚乱的样子,我突然想起自己刚…...
