忿忿的泥巴坨 发表于 2024-10-29 14:00:03

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: *** 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: *** 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
报错:
max delay reached. need to consume packet
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 Session
Duration: N/A, start: 0.040000, bitrate: N/A
    Stream #0:0: Video: hevc, yuvj420p(pc, bt709), 1920x1080, 25 fps, 25 tbr, 90k tbn, 90k tbc
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 extension
             int32_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, i
   FLVContext *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, i
             avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags
             avio_w8(pb, 0); // AVC sequence header
             avio_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->codecpar;
             FLVStreamContext *sc = s->streams->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;
   else
         flags_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->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 NALU
             avio_wb24(pb, pkt->pts - pkt->dts);
         }
打完patch之后,重新编译,运行测试命令,就可以拉取H265的rtsp流并成功rtmp转发出去了。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: hi3536上ffmpeg带rtmp移植