封装 H.264 视频为 FLV 格式然后推流

2024-04-27 07:52

本文主要是介绍封装 H.264 视频为 FLV 格式然后推流,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

封装 H.264 视频为 FLV 格式并通过 RTMP 推流

flyfish

协议

RTMP (Real-Time Messaging Protocol)
RTSP (Real Time Streaming Protocol)
SRT (Secure Reliable Transport)
WebRTC

RTMP(Real Time Messaging Protocol)是一种用于实时音视频流传输的协议。它由Adobe公司开发,主要用于将音视频数据从客户端(如摄像头、编码器)推送到服务器(如流媒体服务器),再由服务器分发给众多观众。

封装格式:MP4、RMVB、FLV、AVI等
编码标准:H.264、MPEG-2等
视频像素数据:YUV420P、RGB、ARGB等

在这里插入图片描述

SPS和PPS

SPS (Sequence Parameter Set) - 序列参数集:
SPS包含了编码视频序列的全局参数,如图像尺寸、帧率、编码配置信息(如profile和level)、颜色空间信息等。这些参数在视频序列开始时发送,并在整个序列中保持不变,除非出现新的SPS。解码器需要这些信息来正确初始化解码过程。

PPS (Picture Parameter Set) - 图像参数集:
PPS提供了与单个图像或帧相关的参数,比如熵编码模式、去块滤波器参数等。每个PPS对应一个或多个图像,并跟随在SPS之后发送。与SPS一样,PPS在视频流中也是相对静态的,但在序列中可以改变。

封装 H.264 视频为 FLV 格式并通过 RTMP 推流步骤

1 提取 SPS 和 PPS
在处理 H.264 视频流之前,首先需要从视频数据中提取 SPS 和 PPS。这些参数通常在 H.264 数据流中的 IDR 帧(关键帧)中,可以通过解析 NAL 单元来获取。

2 封装 SPS 和 PPS 到 FLV
将提取到的 SPS 和 PPS 封装到 FLV 封装格式中。
创建一个FLV视频标签,设置其类型为视频(tag type = 9)。
将SPS和PPS组合成一个NAL单元,并在前面加上NALU头(通常是一个起始码,如0x00000001)。
将此NAL单元作为第一个视频标签的数据部分,设置适当的时间戳和帧类型标识。

3 发送
SPS 和 PPS 到 RTMP 服务器
一般情况下,在 RTMP 推流开始之前,需要先发送 SPS 和 PPS 数据给 RTMP 服务器,以告知接收端解码器关于视频流的信息。
对于每一个H.264视频帧,创建一个新的FLV视频标签。
每个视频帧也需要带有NALU头,并根据帧类型(如I帧、P帧、B帧)设置相应的帧类型标识。
设置正确的时间戳,确保视频播放的同步。

在RTMP协议中,视频数据(包括SPS、PPS、IDR帧、P帧、B帧等)被封装在FLV格式的视频标签(Video Tag)里。每个视频标签开始会有一个Header,描述了该标签的类型、数据长度和时间戳等信息,紧随其后的是实际的视频数据。这些视频数据单元(NALUs)是H.264编码的原始二进制数据

在这里插入图片描述

Frame

IDR (Instantaneous Decoding Refresh) 帧:
IDR帧是一种特殊的I帧,用于实现解码器的即时刷新。当解码器遇到IDR帧时,它会丢弃之前的所有参考帧,从IDR帧开始重新构建参考图像序列。IDR帧是解码独立的,确保了在IDR之后的视频帧不会引用IDR之前的任何帧,有利于错误恢复和随机访问。

I帧 (Intra-coded Frame):
I帧是帧内编码帧,包含了完整画面的所有信息,可以独立解码,不需要参考其他帧。它是视频序列中的关键帧,通常用于场景切换或作为错误恢复点。

P帧 (Predictive-coded Frame):
P帧是预测编码帧,它只存储相对于前一个已解码帧(通常是I帧或P帧)的变化信息。解码P帧时需要参考之前的帧,因此它依赖于过去的信息,能够实现较高的压缩效率。

B帧 (Bi-directional Predictive-coded Frame):
B帧是双向预测编码帧,它利用前后两个已解码帧(可以是I帧、P帧或B帧)的信息进行预测,能够提供更高的压缩率。B帧的解码需要依据其前后帧,因此在编码顺序和解码顺序上可能有所不同,增加了编解码的复杂性,但提高了压缩效率。

GOP

GOP是一组连续的画面,始于一个I帧(关键帧),结束于下一个I帧之前,中间包含P帧(预测帧)和B帧(双向预测帧)。I帧是完整图像,可以独立解码
在这里插入图片描述

Slice

frame是视频中完整的图像单元,而slice是帧内进一步的逻辑分块
Slice是视频编码中对一帧图像进行逻辑划分的单元。在H.264/H.265编码中,为了提高编码效率和容错能力,一帧图像可以被分割成一个或多个slice。
每个slice包含了一组连续的宏块(Macroblocks),这些宏块可以独立进行解码,而不必等待整个帧的数据到达。这样的设计使得即使在网络不稳定或数据包丢失的情况下,也能减少错误传播的范围,因为一个slice的损坏不会影响到其他slice的解码。
Slice可以是不同的类型,比如I-slice(只包含I宏块的slice)、P-slice(包含P宏块的slice)或B-slice(包含B宏块的slice),并且可以在编码时根据需要灵活配置。
Slice的边界不一定遵循图像内容的自然边界,而是根据编码策略和网络传输需求来确定。

Access Unit Delimiter (AUD) 的作用

分隔符功能:AUD作为NAL单元(Network Abstraction Layer Unit)的一种类型,其nal_unit_type值为9,它的主要目的是作为一个标识符,用来标记一个访问单元(Access Unit, AU)的开始。一个访问单元通常包含构成一个完整解码图像所需的所有NAL单元,比如一个I帧、P帧或者B帧及其相关的补充信息(如SPS、PPS等)。在复杂场景下,一个视频帧可能被编码为多个NAL单元(slice),AUD帮助解码器识别这些NAL单元属于同一个图像帧。

同步点:AUD为解码器提供了同步点,特别是在数据流可能存在错误或需要随机访问的情况下,解码器能够通过AUD快速定位到下一个完整图像的起始位置,这对于实现快速 seek、错误恢复以及同步播放控制等操作至关重要。

辅助解码:虽然AUD不是解码过程中的必需部分(即缺少AUD,解码器依然可以根据其他NAL单元类型解码视频),但它简化了解码器的设计,因为它允许解码器无须复杂的解析逻辑就能区分不同图像帧的边界,尤其是在处理包含多个slice的帧时。

兼容性和标准化:在FLV封装格式中加入AUD,有助于保持与H.264标准的兼容性,确保视频内容可以在遵循标准的解码器上正确播放,同时也便于视频流在不同系统间交换和回放。

FLV Header

FieldTypeComment
Signature1 byte必须为’F’(0x46)
Signature1 byte必须为’L’(0x4C)
Signature1 byte必须为’V’(0x56)
(版本)Version1 byte通常为0x01
TypeFlagsReserved5 bits必须为0
TypeFlagsAudio1 bit表示是否含有音频
TypeFlagsReserved1 bit必须为0
TypeFlagsVideo1 bit表示是否含有视频
DataOffset4 bytes文件头部的大小(从文件开始位置到body的偏移量),通常为9
FLV Body
FieldTypeComment
PreviousTagSize04 bytes总是0
Tag1FLVTAG结构第一个tag
PreviousTagSize04 bytes上一个tag的大小,包含了tag的头部。对FLV版本1来讲,它的值等于上一个tag的数据大小+11
Tag2FLVTAG结构第二个tag
PreviousTagSizeN - 14 bytes倒数第二个tag的大小
TagNFLVTAG结构最后一个tag
PreviousTagSizeN4 bytes最后一个tag的大小
FLV tag格式
FieldTypeComment
Tag类型(TagType)1 bytes8:音频、9:视频、18:script数据
数据大小(DataSize)3 bytes数据字段的长度
时间戳(Timestamp)3 bytes毫秒为单位,第一个tag时,该值总是0
时间戳扩展(TimeStampExtended)1 bytes时间戳扩展为4bytes,代表高8位,很少用到
流ID3bytes总是0
数据(Data)音频、视频或script数据实体

这篇关于封装 H.264 视频为 FLV 格式然后推流的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/939926

相关文章

hevc和H.264格式的区别

HEVC(High Efficiency Video Coding)和H.264(也称为Advanced Video Coding,AVC)都是视频压缩标准,但它们之间存在一些显著的区别,主要集中在压缩效率、资源需求和兼容性方面。 压缩效率 HEVC,也被称为H.265,提供了比H.264更高的压缩效率。这意味着在相同的视频质量下,HEVC能够以大约一半的比特率进行编码,从而减少存储空间需求和

公共筛选组件(二次封装antd)支持代码提示

如果项目是基于antd组件库为基础搭建,可使用此公共筛选组件 使用到的库 npm i antdnpm i lodash-esnpm i @types/lodash-es -D /components/CommonSearch index.tsx import React from 'react';import { Button, Card, Form } from 'antd'

React+TS前台项目实战(十七)-- 全局常用组件Dropdown封装

文章目录 前言Dropdown组件1. 功能分析2. 代码+详细注释3. 使用方式4. 效果展示 总结 前言 今天这篇主要讲全局Dropdown组件封装,可根据UI设计师要求自定义修改。 Dropdown组件 1. 功能分析 (1)通过position属性,可以控制下拉选项的位置 (2)通过传入width属性, 可以自定义下拉选项的宽度 (3)通过传入classN

百度OCR识别结构结构化处理视频

https://edu.csdn.net/course/detail/10506

axios全局封装AbortController取消重复请求

为什么? 问题:为什么axios要配置AbortController?防抖节流不行吗? 分析: 防抖节流本质上是用延时器来操作请求的。防抖是判断延时器是否存在,如果存在,清除延时器,重新开启一个延时器,只执行最后一次请求。节流呢,是判断延时器是否存在,如果存在,直接return掉,直到执行完这个延时器。事实上,这些体验感都不算友好,因为对于用户来说,得等一些时间,尤其是首次请求,不是那么流畅

Python利用qq邮箱发送通知邮件(已封装成model)

因为经常喜欢写一些脚本、爬虫之类的东西,有需要通知的时候,总是苦于没有太好的通知方式,虽然邮件相对于微信、短信来说,接收性差了一些,但毕竟免费,而且支持html直接渲染,所以,折腾了一个可以直接使用的sendemail模块。这里主要应用的是QQ发邮件,微信关注QQ邮箱后,也可以实时的接收到消息,肾好! 好了,废话不多说,直接上代码。 # encoding: utf-8import lo

BD错误集锦8——在集成Spring MVC + MyBtis编写mapper文件时需要注意格式 You have an error in your SQL syntax

报错的文件 <?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.yuan.dao.YuanUserDao"><!

el-upload 上传图片及回显照片和预览图片,文件流和http线上链接格式操作

<div v-for="(info, index) in zsjzqwhxqList.helicopterTourInfoList" :key="info.id" >编辑上传图片// oss返回线上地址http链接格式:<el-form-itemlabel="巡视结果照片":label-width="formLabelWidth"><el-upload:action="'http:

PHP生成csv格式Excel,秒级别实现excel导出功能

防止报超内存,兼容中文,兼容科学技术法。 爽。。。。很爽。。。。 /*** 告诉浏览器下载csv文件* @param string $filename*/public static function downloadCsv($data, $filename, $encoding = 'utf-8'){header("Content-type: text/csv");header("Conten

线程封装,互斥

文章目录 线程封装线程互斥加锁、解锁认识接口解决问题理解锁 线程封装 C/C++代码混编引起的问题 此处pthread_create函数要求传入参数为void * func(void * )类型,按理来说ThreadRoutine满足,但是 这是在内类完成封装,所以ThreadRoutine函数实际是两个参数,第一个参数Thread* this不显示 解决方法: 第