hi3536上ffmpeg带rtmp移植

1.下载ffmpeg-4.1.3版本源码包

用下面的脚本进行configure:

./configure \--target-os=linux \--prefix=./libs/ \--enable-cross-compile \--arch=arm \--cc=arm-hisiv500-linux-gcc \--cross-prefix=arm-hisiv500-linux- \--nm=arm-hisiv500-linux-nm \--enable-shared \--disable-static \--enable-gpl \--enable-swscale \--enable-avfilter \--disable-devices \--disable-filters \--disable-decoders \--enable-decoder=h264 \--disable-ffplay \--disable-ffprobe \--disable-doc \--disable-encoders \--enable-small \--enable-encoder=flv \--enable-encoder=mp4 \--disable-muxers \--enable-muxer=flv \--enable-muxer=rtsp \--enable-muxer=rtp \--disable-parsers \--enable-parser=flv \--enable-parser=h264 \--disable-demuxers \--enable-demuxer=flv \--enable-demuxer=h264 \--enable-ffmpeg 

然后make和make install,生成的可执行文件以及lib和include等将拷贝到prefix指定的目录下,然后将这个目录拷贝到nfs共享文件夹里面,到板子中,通过软连接的方式,将可执行文件和动态库链接到板子上,因为板子空间有限,所以不直接拷贝到板子上,拷贝之后,可以通过nginx代理,将本地flv文件通过rtmp推送出去,但是mp4文件推不出去,而且rtsp流也没法拉流,所以需要修改configure参数,

2.更换新的configure脚本参数。

更改如下:

./configure \--prefix=./libs/ \--enable-filters   \--enable-asm \--enable-ffmpeg \--enable-ffplay \--enable-ffprobe \--enable-doc \--enable-cross-compile \--cross-prefix=arm-hisiv500-linux- \--arch=arm \--target-os=linux \--host-os=linux \--enable-gpl \--enable-version3 \--enable-small \--enable-shared \--enable-static \--enable-encoder=rawvideo \--enable-encoder=mpeg2video \--enable-encoder=mp2 \--enable-encoder=libx264 \--enable-libx264 \--enable-muxer=adts \--enable-muxer=mpegts \--enable-muxer=mpeg2video \--enable-muxer=rtsp \--enable-muxer=hls \--enable-muxer=h264 \--enable-muxer=rtp \--enable-muxer=avi \--enable-muxer=flv \--enable-muxer=mp4 \--enable-demuxer=mpegts \--enable-demuxer=rtsp \--enable-demuxer=hls \--enable-demuxer=h264 \--enable-demuxer=rtp \--enable-demuxer=flv \--enable-muxer=mp4 \--enable-demuxer=mpegts \--enable-demuxer=rtsp \--enable-demuxer=hls \--enable-demuxer=h264 \--enable-demuxer=rtp \--enable-demuxer=flv \--enable-demuxer=avi \--enable-demuxer=mpegps \--enable-demuxer=mpegtsraw \--enable-demuxer=mpegvideo \--enable-parser=aac \--enable-parser=h264 \--enable-parser=mpeg4video \--enable-parser=mpegvideo \--enable-parser=mpegaudio \--enable-bsf=h264_mp4toannexb \--enable-protocol=http \--enable-protocol=rtp \--enable-protocol=rtmpts \--enable-protocol=https \--enable-protocol=hls \--enable-protocol=file \--enable-protocol=data \--enable-gray  \--enable-safe-bitstream-reader \--extra-cflags=-I/home/zl/vstdio-workspace/hi3536-webapp/x264/x264_hisi/include \--extra-ldflags=-L/home/zl/vstdio-workspace/hi3536-webapp/x264/x264_hisi/lib

添加了一个x264的扩展包.

3.x264移植。

1.下载编译x264。

(1)下载链接如下:

git clone https://github.com/mirror/x264

(2)configure脚本:

CC=arm-hisiv500-linux-gcc  ./configure \
--host=arm-hisiv500-linux \
--prefix=./x264_hisi \
--cross-prefix=arm-hisiv500-linux- \
--enable-static \
--enable-shared \

成功之后执行:

make
make install

然后回到ffmpeg的路径下,修改configure,将x264的库和头文件路径配置上,编译,提示下面的错误:

libavfilter/libavfilter.so: undefined reference to `fminf'
libavfilter/libavfilter.so: undefined reference to `fmaxf'
collect2: error: ld returned 1 exit status
Makefile:108: recipe for target 'ffprobe_g' failed
make: *** [ffprobe_g] Error 1
make: *** Waiting for unfinished jobs....
libavfilter/libavfilter.so: undefined reference to `fminf'
libavfilter/libavfilter.so: undefined reference to `fmaxf'
collect2: error: ld returned 1 exit status
Makefile:108: recipe for target 'ffmpeg_g' failed
make: *** [ffmpeg_g] Error 1

网上查到的资料显示是,海思用的交叉编译链不支持浮点操作,然后也没找到修改方法,看到最多的是用ffmpeg早期版本,因为目前的版本是4.1.3。

4.重新拉取ffmpeg源码,更换版本。

从网上查到ffmpeg的开源链接如下:

git clone https://git.ffmpeg.org/ffmpeg.git

下载之后,默认是最新的release版本,用下面的命令更换分支:

git checkout -t remotes/origin/release/3.4

切换到3.4版本,然后将configure脚本拷过来,进行配置,配置完后,执行make和make install,然后将可执行文件和动态库拷贝到板子上,进行测试,通过测试,可以推mp4文件到rtmp,以及拉rtsp然后推rtmp出去。测试命令如下:

ffmpeg -re -i test.mp4 -vcodec copy -codec copy -f flv rtmp://192.168.0.165:1935/live/mainstream
ffmpeg -i rtsp://admin:12345@192.168.0.200:554/Streaming/Channels/1 -vcodec copy -acodec copy -f flv rtmp://192.168.0.165:1935/live/mainstream

5.测试H265码流的支持,从H265 ipc上拉取H265的rtsp流,然后转rtmp流出去:

命令如下:

ffmpeg -i rtsp://192.168.0.132:554/user=admin_password=tlJwpbo6_channel=1_stream=0.sdp?real_stream -vcodec copy -acodec copy -f flv rtmp://192.168.0.165:1935/live/thirdstream

报错:

[rtsp @ 0x421f0] max delay reached. need to consume packet
[rtsp @ 0x421f0] RTP: missed 46 packets
Input #0, rtsp, from 'rtsp://192.168.0.132:554/user=admin_password=tlJwpbo6_channel=1_stream=0.sdp?real_stream':Metadata:title           : RTSP SessionDuration: N/A, start: 0.040000, bitrate: N/AStream #0:0: Video: hevc, yuvj420p(pc, bt709), 1920x1080, 25 fps, 25 tbr, 90k tbn, 90k tbc
[flv @ 0x98310] Video codec hevc not compatible with flv
Could not write header for output file #0 (incorrect codec parameters ?): Function not implemented
Stream mapping:Stream #0:0 -> #0:0 (copy)Last message repeated 1 times

原因:

rtmp默认是flv封装的,而这个封装默认是不支持HEVC也就是H265的,所以需要打个patch:0020-ffmpeg-flv-support-hevc.patch

diff --git a/libavformat/flv.h b/libavformat/flv.h
index 3571b90279..91f006520c 100644
--- a/libavformat/flv.h
+++ b/libavformat/flv.h
@@ -110,6 +110,7 @@ enum {FLV_CODECID_H264    = 7,FLV_CODECID_REALH263= 8,FLV_CODECID_MPEG4   = 9,
+    FLV_CODECID_HEVC    = 12,};enum {
diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index b531a39adc..fc9be86509 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -37,6 +37,7 @@#include "internal.h"#include "avio_internal.h"#include "flv.h"
+#include "hevc.h"#define VALIDATE_INDEX_TS_THRESH 2500@@ -319,6 +320,8 @@ static int flv_same_video_codec(AVCodecParameters *vpar, int flags)return vpar->codec_id == AV_CODEC_ID_VP6A;case FLV_CODECID_H264:return vpar->codec_id == AV_CODEC_ID_H264;
+    case FLV_CODECID_HEVC:
+        return vpar->codec_id == AV_CODEC_ID_HEVC;default:return vpar->codec_tag == flv_codecid;}
@@ -368,6 +371,11 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream,par->codec_id = AV_CODEC_ID_MPEG4;ret = 3;break;
+    case FLV_CODECID_HEVC:
+        par->codec_id = AV_CODEC_ID_HEVC;
+        vstream->need_parsing = AVSTREAM_PARSE_HEADERS;
+        ret = 3;
+        break;default:avpriv_request_sample(s, "Video codec (%x)", flv_codecid);par->codec_tag = flv_codecid;
@@ -1223,7 +1231,8 @@ retry_duration:if (st->codecpar->codec_id == AV_CODEC_ID_AAC ||st->codecpar->codec_id == AV_CODEC_ID_H264 ||
-        st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
+        st->codecpar->codec_id == AV_CODEC_ID_MPEG4 ||
+        st->codecpar->codec_id == AV_CODEC_ID_HEVC) {int type = avio_r8(s->pb);size--;@@ -1232,7 +1241,8 @@ retry_duration:goto leave;}-        if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
+        if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4
+                || st->codecpar->codec_id == AV_CODEC_ID_HEVC) {// sign extensionint32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000;pts = dts + cts;
@@ -1248,7 +1258,7 @@ retry_duration:}}if (type == 0 && (!st->codecpar->extradata || st->codecpar->codec_id == AV_CODEC_ID_AAC ||
-            st->codecpar->codec_id == AV_CODEC_ID_H264)) {
+            st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC)) {AVDictionaryEntry *t;if (st->codecpar->extradata) {
diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c
index fb1dede7ae..711b5dfb05 100644
--- a/libavformat/flvenc.c
+++ b/libavformat/flvenc.c
@@ -29,6 +29,7 @@#include "avc.h"#include "avformat.h"#include "flv.h"
+#include "hevc.h"#include "internal.h"#include "metadata.h"#include "libavutil/opt.h"
@@ -46,6 +47,7 @@ static const AVCodecTag flv_video_codec_ids[] = {{ AV_CODEC_ID_VP6,      FLV_CODECID_VP6 },{ AV_CODEC_ID_VP6A,     FLV_CODECID_VP6A },{ AV_CODEC_ID_H264,     FLV_CODECID_H264 },
+    { AV_CODEC_ID_HEVC,     FLV_CODECID_HEVC },{ AV_CODEC_ID_NONE,     0 }};@@ -491,7 +493,7 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, iFLVContext *flv = s->priv_data;if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264
-            || par->codec_id == AV_CODEC_ID_MPEG4) {
+            || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) {int64_t pos;avio_w8(pb,par->codec_type == AVMEDIA_TYPE_VIDEO ?
@@ -537,7 +539,11 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, iavio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flagsavio_w8(pb, 0); // AVC sequence headeravio_wb24(pb, 0); // composition time
-            ff_isom_write_avcc(pb, par->extradata, par->extradata_size);
+            if (par->codec_id == AV_CODEC_ID_HEVC) {
+                ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0);
+            } else {
+                ff_isom_write_avcc(pb, par->extradata, par->extradata_size);
+            }}data_size = avio_tell(pb) - pos;avio_seek(pb, -data_size - 10, SEEK_CUR);
@@ -847,7 +853,8 @@ end:AVCodecParameters *par = s->streams[i]->codecpar;FLVStreamContext *sc = s->streams[i]->priv_data;if (par->codec_type == AVMEDIA_TYPE_VIDEO &&
-                    (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4))
+                    (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4
+                     || par->codec_id == AV_CODEC_ID_HEVC))put_avc_eos_tag(pb, sc->last_ts);}}
@@ -898,13 +905,13 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A ||par->codec_id == AV_CODEC_ID_VP6  || par->codec_id == AV_CODEC_ID_AAC)flags_size = 2;
-    else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4)
+    else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC)flags_size = 5;elseflags_size = 1;if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264
-            || par->codec_id == AV_CODEC_ID_MPEG4) {
+            || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) {int side_size = 0;uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) {
@@ -967,6 +974,11 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1)if ((ret = ff_avc_parse_nal_units_buf(pkt->data, &data, &size)) < 0)return ret;
+    } else if (par->codec_id == AV_CODEC_ID_HEVC) {
+        /* check if extradata looks like mp4 formatted */
+        if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1)
+            if ((ret = ff_hevc_annexb2mp4_buf(pkt->data, &data, &size, 0, NULL)) < 0)
+                return ret;} else if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&(AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {if (!s->streams[pkt->stream_index]->nb_frames) {
@@ -1038,7 +1050,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)(FFALIGN(par->height, 16) - par->height));} else if (par->codec_id == AV_CODEC_ID_AAC)avio_w8(pb, 1); // AAC raw
-        else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) {
+        else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) {avio_w8(pb, 1); // AVC NALUavio_wb24(pb, pkt->pts - pkt->dts);}

打完patch之后,重新编译,运行测试命令,就可以拉取H265的rtsp流并成功rtmp转发出去了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/57112.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Node + HTML搭建自己的ChatGPT [基础版]

文章目录 明明外面的ChatGPT产品那么多了&#xff0c;为什么要在本地搭建自己的ChatGPT呢&#xff1f;整体架构流程1. 获取APIKey1.1 常见的AI模型1.2 为什么选DeepSeek1.3 怎么获取DeepSeek的APIKey1.3.1 注册并登录DeepSeek开放平台1.3.2 选择API keys1.3.3 创建API key1.3.4…

【Linux学习】(8)第一个Linux编程进度条程序|git三板斧

前言 第一个Linux编程——进度条git的简单使用 一、第一个Linux编程——进度条 在写进度条之前我们需要两个基础知识&#xff1a; 回车换行缓冲区 1. 回车换行 首先我们需要知道回车换行它是两个概念&#xff0c;回车是回车&#xff0c;换行是换行换行&#xff1a;光标从上往下…

DEVOPS: 认证与调度

概述 不知道大家有没有意识到一个现实&#xff0c;就是大部分时候&#xff0c;我们已经不像以前一样通过命令行&#xff0c;或者可视窗口来使用一个系统了现在我们上微博、或者网购&#xff0c;操作的其实不是眼前这台设备&#xff0c;而是一个又一个集群 通常&#xff0c;这样…

MUX VLAN 实验配置

MUX VLAN&#xff08;Multiplex VLAN&#xff09;是一种高级的VLAN技术&#xff0c;通过在交换机上实现二层流量隔离和灵活的网络资源控制&#xff0c;提供了一种更为细致的网络管理方式 MUX VLAN通过定义主VLAN&#xff08;Principal VLAN&#xff09;和多个子VLAN&#xff0…

海外云手机怎样助力亚马逊店铺运营?

随着全球化的发展&#xff0c;越来越多的企业开始重视海外市场的拓展&#xff0c;尤其是出海企业和B2B外贸企业。亚马逊作为全球最大的电商平台之一&#xff0c;成为了许多企业争夺国际市场的重点战场。本文将深入分析海外云手机在优化亚马逊店铺引流中的作用和优势&#xff0c…

【人工智能-初级】第7章 聚类算法K-Means:理论讲解与代码示例

文章目录 一、K-Means聚类简介二、K-Means 聚类的工作原理2.1 初始化簇中心2.2 分配簇标签2.3 更新簇中心2.4 迭代重复2.5 K-Means 算法的目标三、K-Means 聚类的优缺点3.1 优点3.2 缺点四、K 值的选择五、Python 实现 K-Means 聚类5.1 导入必要的库5.2 生成数据集并进行可视化…

020:无人机重要知识点名词解释

摘要&#xff1a;本文介绍了无人机系统、飞行原理、法律法规、气象学、气象操作、遥控器涉及到部分重要概念的名词解释。 一、无人机系统 1.控制与驱动系统 伺服执行机构&#xff1a;一种装置&#xff0c;根据系统反馈信号&#xff0c;提供远程、自动切换或驱动运动&#xff…

优惠券项目的设计与实现,完结!

你好 我是田哥 我的充电桩项目中&#xff0c;优惠券相关功能已基本完成。另外&#xff0c;关于充电桩项目&#xff0c;我之前分享过一些相关文章&#xff1a; 充电桩项目&#xff0c;开源啦&#xff01; 充电桩项目实战&#xff1a;消息丢失和重复消费问题 用充电桩项目面试&am…

【electron8】electron实现“图片”的另存为

注&#xff1a;该列出的代码&#xff0c;都在文章内示例出 1. 另存为按钮事件&#xff1a; const saveAsHandler async () > {const { path, sessionId } recordInfoif(typeof message ! string) return;// 因为我的图片是加密的&#xff0c;所以我需要根据接口返回的路…

求解亥姆霍兹方程

首先&#xff0c;变量分离将亥姆霍兹方程 ( ∇ 2 k 2 ) Ψ ( d ) 0 (\nabla^2 k^2) \Psi(\boldsymbol{d}) 0 (∇2k2)Ψ(d)0 分解为球谐函数和球贝塞尔函数方程&#xff0c;我们将方程的解函数 Ψ \Psi Ψ 转换到球坐标系 ( r , θ , ϕ ) (r, \theta, \phi) (r,θ,ϕ) 下…

Java 中的序列化和反序列化

Java 中的序列化和反序列化是一种重要的机制&#xff0c;可以使对象在保存和传输过程中保持其状态&#xff0c;广泛应用于持久化、网络传输和分布式计算中。虽然原生的序列化机制使用起来很方便&#xff0c;但由于性能、安全等方面的限制&#xff0c;在现代软件开发中&#xff…

微服务的雪崩问题

微服务的雪崩问题&#xff1a; 微服务调用链路中的某个服务故障&#xff0c;引起整个链路种的所有微服务都不可用。这就是微服务的雪崩问题。&#xff08;级联失败&#xff09;&#xff0c;具体表现出来就是微服务之间相互调用&#xff0c;服务的提供者出现阻塞或者故障&#x…

使用vue+kkFileview组件实现各种类型文件预览

关于kkFileView 【参考】&#xff1a;https://kkfileview.keking.cn/zh-cn/docs/home.html 文档在线预览项目解决方案&#xff0c;项目使用流行的spring boot搭建&#xff0c;易上手和部署。万能的文件预览开源项目&#xff0c;基本支持主流文档格式预览 本项目介绍 项目使用…

低空经济产业链、政策、延伸品调研笔记

文章目录 1 低空经济市场1.1 政策摘要1.2 市场规模预测 3 涉及产业链与核心产品3.1 产业链3.2 原材料3.2.1 上游3.2.2 中游3.2.3下游 3.3 无人机3.4 eVTOL3.5 空管系统 4 应用场景4.1 城市空中出行(UAM)4.2 低空物流4.3 低空旅游与体验4.4 农林植保与监测4.5 基础设施巡检与维护…

JVM基础(内存结构)

文章目录 内存结构JAVA堆方法区 &#xff08;Method Area&#xff09;运行时常量池&#xff08;Runtime Constant Pool&#xff09; 虚拟机栈 &#xff08;Java Virtual Machine Stack&#xff09;本地方法摘栈&#xff08;Native Method Stacks&#xff09;程序计数器&#xf…

Matlab 车牌识别技术

1.1设计内容及要求&#xff1a; 课题研究的主要内容是对数码相机拍摄的车牌&#xff0c;进行基于数字图像处理技术的车牌定位技术和车牌字符分割技术的研究与开发&#xff0c;涉及到图像预处理、车牌定位、倾斜校正、字符分割等方面的知识,总流程图如图1-1所示。 图1-1系统总…

智慧共享空间解决方案是什么

一、智慧共享空间解决方案的定义 智慧共享空间解决方案是一种综合性的策略和技术手段&#xff0c;旨在通过整合智慧技术与共享空间的概念&#xff0c;为公众共同使用的空间提供高效、智能、可持续的运营和管理模式&#xff0c;以满足人们在不同环境下的各种需求&#xff0c;并…

前端分页:非当前页进行表单验证

概览 对于大数据量批量导入&#xff0c;渲染到表格的场景中&#xff0c;可能会造成浏览器崩溃&#xff0c;此时前端分页可以很好地解决这个问题&#xff0c;但是组件库自带的表单验证通常只能进行当前页的验证&#xff0c;如何实现对全量数据的表单验证呢&#xff1f;此篇文章…

C++基于opencv的视频质量检测--画面冻结检测

文章目录 0.引言1. 原始代码分析2. 优化方案3. 优化后的代码4. 代码详细解读 0.引言 视频质量画面冻结检测已在C基于opencv4的视频质量检测中有所介绍&#xff0c;本文将详细介绍其优化版本。 1. 原始代码分析 图像抖动检测的原始代码&#xff1a; bool ScreenFreezeDetect…

AI驱动的低代码未来:加速应用开发的智能解决方案

引言 随着数字化转型的浪潮席卷全球&#xff0c;企业对快速构建应用程序的需求愈发强烈。然而&#xff0c;传统的软件开发周期冗长、成本高昂&#xff0c;往往无法满足快速变化的市场需求。在此背景下&#xff0c;低代码平台逐渐成为开发者和企业的优选方案&#xff0c;以其“低…