ToB企服应用市场:ToB评测及商务社交产业平台

标题: hi3536上ffmpeg带rtmp移植 [打印本页]

作者: 忿忿的泥巴坨    时间: 2024-10-29 14:00
标题: hi3536上ffmpeg带rtmp移植
1.下载ffmpeg-4.1.3版本源码包
用下面的脚本进行configure:
  1. ./configure \
  2.     --target-os=linux \
  3.     --prefix=./libs/ \
  4.     --enable-cross-compile \
  5.     --arch=arm \
  6.     --cc=arm-hisiv500-linux-gcc \
  7.     --cross-prefix=arm-hisiv500-linux- \
  8.     --nm=arm-hisiv500-linux-nm \
  9.     --enable-shared \
  10.     --disable-static \
  11.     --enable-gpl \
  12.     --enable-swscale \
  13.     --enable-avfilter \
  14.     --disable-devices \
  15.     --disable-filters \
  16.     --disable-decoders \
  17.     --enable-decoder=h264 \
  18.     --disable-ffplay \
  19.     --disable-ffprobe \
  20.     --disable-doc \
  21.     --disable-encoders \
  22.     --enable-small \
  23.     --enable-encoder=flv \
  24.     --enable-encoder=mp4 \
  25.     --disable-muxers \
  26.     --enable-muxer=flv \
  27.     --enable-muxer=rtsp \
  28.     --enable-muxer=rtp \
  29.     --disable-parsers \
  30.     --enable-parser=flv \
  31.     --enable-parser=h264 \
  32.     --disable-demuxers \
  33.     --enable-demuxer=flv \
  34.     --enable-demuxer=h264 \
  35.     --enable-ffmpeg
复制代码
然后make和make install,生成的可实验文件以及lib和include等将拷贝到prefix指定的目次下,然后将这个目次拷贝到nfs共享文件夹内里,到板子中,通过软毗连的方式,将可实验文件和动态库链接到板子上,因为板子空间有限,所以不直接拷贝到板子上,拷贝之后,可以通过nginx代理,将本地flv文件通过rtmp推送出去,但是mp4文件推不出去,而且rtsp流也没法拉流,所以需要修改configure参数,
2.更换新的configure脚本参数。
更改如下:
  1. ./configure \
  2.         --prefix=./libs/ \
  3.         --enable-filters   \
  4.         --enable-asm \
  5.         --enable-ffmpeg \
  6.         --enable-ffplay \
  7.         --enable-ffprobe \
  8.         --enable-doc \
  9.         --enable-cross-compile \
  10.         --cross-prefix=arm-hisiv500-linux- \
  11.         --arch=arm \
  12.         --target-os=linux \
  13.         --host-os=linux \
  14.         --enable-gpl \
  15.         --enable-version3 \
  16.         --enable-small \
  17.         --enable-shared \
  18.         --enable-static \
  19.         --enable-encoder=rawvideo \
  20.         --enable-encoder=mpeg2video \
  21.         --enable-encoder=mp2 \
  22.         --enable-encoder=libx264 \
  23.         --enable-libx264 \
  24.         --enable-muxer=adts \
  25.         --enable-muxer=mpegts \
  26.         --enable-muxer=mpeg2video \
  27.         --enable-muxer=rtsp \
  28.         --enable-muxer=hls \
  29.         --enable-muxer=h264 \
  30.         --enable-muxer=rtp \
  31.         --enable-muxer=avi \
  32.         --enable-muxer=flv \
  33.         --enable-muxer=mp4 \
  34.         --enable-demuxer=mpegts \
  35.         --enable-demuxer=rtsp \
  36.         --enable-demuxer=hls \
  37.         --enable-demuxer=h264 \
  38.         --enable-demuxer=rtp \
  39.         --enable-demuxer=flv \
  40.         --enable-muxer=mp4 \
  41.         --enable-demuxer=mpegts \
  42.         --enable-demuxer=rtsp \
  43.         --enable-demuxer=hls \
  44.         --enable-demuxer=h264 \
  45.         --enable-demuxer=rtp \
  46.         --enable-demuxer=flv \
  47.         --enable-demuxer=avi \
  48.         --enable-demuxer=mpegps \
  49.         --enable-demuxer=mpegtsraw \
  50.         --enable-demuxer=mpegvideo \
  51.         --enable-parser=aac \
  52.         --enable-parser=h264 \
  53.         --enable-parser=mpeg4video \
  54.         --enable-parser=mpegvideo \
  55.         --enable-parser=mpegaudio \
  56.         --enable-bsf=h264_mp4toannexb \
  57.         --enable-protocol=http \
  58.         --enable-protocol=rtp \
  59.         --enable-protocol=rtmpts \
  60.         --enable-protocol=https \
  61.         --enable-protocol=hls \
  62.         --enable-protocol=file \
  63.         --enable-protocol=data \
  64.         --enable-gray  \
  65.         --enable-safe-bitstream-reader \
  66.         --extra-cflags=-I/home/zl/vstdio-workspace/hi3536-webapp/x264/x264_hisi/include \
  67.         --extra-ldflags=-L/home/zl/vstdio-workspace/hi3536-webapp/x264/x264_hisi/lib
复制代码
添加了一个x264的扩展包.
3.x264移植。
1.下载编译x264。
(1)下载链接如下:
  1. git clone https://github.com/mirror/x264
复制代码
(2)configure脚本:
  1. CC=arm-hisiv500-linux-gcc  ./configure \
  2. --host=arm-hisiv500-linux \
  3. --prefix=./x264_hisi \
  4. --cross-prefix=arm-hisiv500-linux- \
  5. --enable-static \
  6. --enable-shared \
复制代码
成功之后实验:
  1. make
  2. make install
复制代码
然后回到ffmpeg的路径下,修改configure,将x264的库和头文件路径配置上,编译,提示下面的错误:
  1. libavfilter/libavfilter.so: undefined reference to `fminf'
  2. libavfilter/libavfilter.so: undefined reference to `fmaxf'
  3. collect2: error: ld returned 1 exit status
  4. Makefile:108: recipe for target 'ffprobe_g' failed
  5. make: *** [ffprobe_g] Error 1
  6. make: *** Waiting for unfinished jobs....
  7. libavfilter/libavfilter.so: undefined reference to `fminf'
  8. libavfilter/libavfilter.so: undefined reference to `fmaxf'
  9. collect2: error: ld returned 1 exit status
  10. Makefile:108: recipe for target 'ffmpeg_g' failed
  11. make: *** [ffmpeg_g] Error 1
复制代码
网上查到的资料体现是,海思用的交织编译链不支持浮点操纵,然后也没找到修改方法,看到最多的是用ffmpeg早期版本,因为现在的版本是4.1.3。
4.重新拉取ffmpeg源码,更换版本。
从网上查到ffmpeg的开源链接如下:
  1. git clone https://git.ffmpeg.org/ffmpeg.git
复制代码
下载之后,默认是最新的release版本,用下面的命令更换分支:
  1. git checkout -t remotes/origin/release/3.4
复制代码
切换到3.4版本,然后将configure脚本拷过来,进行配置,配置完后,实验make和make install,然后将可实验文件和动态库拷贝到板子上,进行测试,通过测试,可以推mp4文件到rtmp,以及拉rtsp然后推rtmp出去。测试命令如下:
  1. ffmpeg -re -i test.mp4 -vcodec copy -codec copy -f flv rtmp://192.168.0.165:1935/live/mainstream
复制代码
  1. 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流出去:
命令如下:
  1. 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
复制代码
报错:
  1. [rtsp @ 0x421f0] max delay reached. need to consume packet
  2. [rtsp @ 0x421f0] RTP: missed 46 packets
  3. Input #0, rtsp, from 'rtsp://192.168.0.132:554/user=admin_password=tlJwpbo6_channel=1_stream=0.sdp?real_stream':
  4.   Metadata:
  5.     title           : RTSP Session
  6.   Duration: N/A, start: 0.040000, bitrate: N/A
  7.     Stream #0:0: Video: hevc, yuvj420p(pc, bt709), 1920x1080, 25 fps, 25 tbr, 90k tbn, 90k tbc
  8. [flv @ 0x98310] Video codec hevc not compatible with flv
  9. Could not write header for output file #0 (incorrect codec parameters ?): Function not implemented
  10. Stream mapping:
  11.   Stream #0:0 -> #0:0 (copy)
  12.     Last message repeated 1 times
复制代码
缘故原由:
rtmp默认是flv封装的,而这个封装默认是不支持HEVC也就是H265的,所以需要打个patch:0020-ffmpeg-flv-support-hevc.patch
  1. diff --git a/libavformat/flv.h b/libavformat/flv.h
  2. index 3571b90279..91f006520c 100644
  3. --- a/libavformat/flv.h
  4. +++ b/libavformat/flv.h
  5. @@ -110,6 +110,7 @@ enum {
  6.      FLV_CODECID_H264    = 7,
  7.      FLV_CODECID_REALH263= 8,
  8.      FLV_CODECID_MPEG4   = 9,
  9. +    FLV_CODECID_HEVC    = 12,
  10. };
  11. enum {
  12. diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
  13. index b531a39adc..fc9be86509 100644
  14. --- a/libavformat/flvdec.c
  15. +++ b/libavformat/flvdec.c
  16. @@ -37,6 +37,7 @@
  17. #include "internal.h"
  18. #include "avio_internal.h"
  19. #include "flv.h"
  20. +#include "hevc.h"
  21. #define VALIDATE_INDEX_TS_THRESH 2500
  22. @@ -319,6 +320,8 @@ static int flv_same_video_codec(AVCodecParameters *vpar, int flags)
  23.          return vpar->codec_id == AV_CODEC_ID_VP6A;
  24.      case FLV_CODECID_H264:
  25.          return vpar->codec_id == AV_CODEC_ID_H264;
  26. +    case FLV_CODECID_HEVC:
  27. +        return vpar->codec_id == AV_CODEC_ID_HEVC;
  28.      default:
  29.          return vpar->codec_tag == flv_codecid;
  30.      }
  31. @@ -368,6 +371,11 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream,
  32.          par->codec_id = AV_CODEC_ID_MPEG4;
  33.          ret = 3;
  34.          break;
  35. +    case FLV_CODECID_HEVC:
  36. +        par->codec_id = AV_CODEC_ID_HEVC;
  37. +        vstream->need_parsing = AVSTREAM_PARSE_HEADERS;
  38. +        ret = 3;
  39. +        break;
  40.      default:
  41.          avpriv_request_sample(s, "Video codec (%x)", flv_codecid);
  42.          par->codec_tag = flv_codecid;
  43. @@ -1223,7 +1231,8 @@ retry_duration:
  44.      if (st->codecpar->codec_id == AV_CODEC_ID_AAC ||
  45.          st->codecpar->codec_id == AV_CODEC_ID_H264 ||
  46. -        st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
  47. +        st->codecpar->codec_id == AV_CODEC_ID_MPEG4 ||
  48. +        st->codecpar->codec_id == AV_CODEC_ID_HEVC) {
  49.          int type = avio_r8(s->pb);
  50.          size--;
  51. @@ -1232,7 +1241,8 @@ retry_duration:
  52.              goto leave;
  53.          }
  54. -        if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
  55. +        if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4
  56. +                || st->codecpar->codec_id == AV_CODEC_ID_HEVC) {
  57.              // sign extension
  58.              int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000;
  59.              pts = dts + cts;
  60. @@ -1248,7 +1258,7 @@ retry_duration:
  61.              }
  62.          }
  63.          if (type == 0 && (!st->codecpar->extradata || st->codecpar->codec_id == AV_CODEC_ID_AAC ||
  64. -            st->codecpar->codec_id == AV_CODEC_ID_H264)) {
  65. +            st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC)) {
  66.              AVDictionaryEntry *t;
  67.              if (st->codecpar->extradata) {
  68. diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c
  69. index fb1dede7ae..711b5dfb05 100644
  70. --- a/libavformat/flvenc.c
  71. +++ b/libavformat/flvenc.c
  72. @@ -29,6 +29,7 @@
  73. #include "avc.h"
  74. #include "avformat.h"
  75. #include "flv.h"
  76. +#include "hevc.h"
  77. #include "internal.h"
  78. #include "metadata.h"
  79. #include "libavutil/opt.h"
  80. @@ -46,6 +47,7 @@ static const AVCodecTag flv_video_codec_ids[] = {
  81.      { AV_CODEC_ID_VP6,      FLV_CODECID_VP6 },
  82.      { AV_CODEC_ID_VP6A,     FLV_CODECID_VP6A },
  83.      { AV_CODEC_ID_H264,     FLV_CODECID_H264 },
  84. +    { AV_CODEC_ID_HEVC,     FLV_CODECID_HEVC },
  85.      { AV_CODEC_ID_NONE,     0 }
  86. };
  87. @@ -491,7 +493,7 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i
  88.      FLVContext *flv = s->priv_data;
  89.      if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264
  90. -            || par->codec_id == AV_CODEC_ID_MPEG4) {
  91. +            || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) {
  92.          int64_t pos;
  93.          avio_w8(pb,
  94.                  par->codec_type == AVMEDIA_TYPE_VIDEO ?
  95. @@ -537,7 +539,11 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i
  96.              avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags
  97.              avio_w8(pb, 0); // AVC sequence header
  98.              avio_wb24(pb, 0); // composition time
  99. -            ff_isom_write_avcc(pb, par->extradata, par->extradata_size);
  100. +            if (par->codec_id == AV_CODEC_ID_HEVC) {
  101. +                ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0);
  102. +            } else {
  103. +                ff_isom_write_avcc(pb, par->extradata, par->extradata_size);
  104. +            }
  105.          }
  106.          data_size = avio_tell(pb) - pos;
  107.          avio_seek(pb, -data_size - 10, SEEK_CUR);
  108. @@ -847,7 +853,8 @@ end:
  109.              AVCodecParameters *par = s->streams[i]->codecpar;
  110.              FLVStreamContext *sc = s->streams[i]->priv_data;
  111.              if (par->codec_type == AVMEDIA_TYPE_VIDEO &&
  112. -                    (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4))
  113. +                    (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4
  114. +                     || par->codec_id == AV_CODEC_ID_HEVC))
  115.                  put_avc_eos_tag(pb, sc->last_ts);
  116.          }
  117.      }
  118. @@ -898,13 +905,13 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
  119.      if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A ||
  120.          par->codec_id == AV_CODEC_ID_VP6  || par->codec_id == AV_CODEC_ID_AAC)
  121.          flags_size = 2;
  122. -    else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4)
  123. +    else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC)
  124.          flags_size = 5;
  125.      else
  126.          flags_size = 1;
  127.      if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264
  128. -            || par->codec_id == AV_CODEC_ID_MPEG4) {
  129. +            || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) {
  130.          int side_size = 0;
  131.          uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
  132.          if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) {
  133. @@ -967,6 +974,11 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
  134.          if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1)
  135.              if ((ret = ff_avc_parse_nal_units_buf(pkt->data, &data, &size)) < 0)
  136.                  return ret;
  137. +    } else if (par->codec_id == AV_CODEC_ID_HEVC) {
  138. +        /* check if extradata looks like mp4 formatted */
  139. +        if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1)
  140. +            if ((ret = ff_hevc_annexb2mp4_buf(pkt->data, &data, &size, 0, NULL)) < 0)
  141. +                return ret;
  142.      } else if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
  143.                 (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
  144.          if (!s->streams[pkt->stream_index]->nb_frames) {
  145. @@ -1038,7 +1050,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
  146.                               (FFALIGN(par->height, 16) - par->height));
  147.          } else if (par->codec_id == AV_CODEC_ID_AAC)
  148.              avio_w8(pb, 1); // AAC raw
  149. -        else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) {
  150. +        else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) {
  151.              avio_w8(pb, 1); // AVC NALU
  152.              avio_wb24(pb, pkt->pts - pkt->dts);
  153.          }
复制代码
打完patch之后,重新编译,运行测试命令,就可以拉取H265的rtsp流并成功rtmp转发出去了。

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




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4