• ffmpeg 支持用h265编码的rtmp


    修改ffmpeg5.0的代码,让ffmpeg的flv支持h265封装及解封装

    中间目录:out
    1、x264
       下载x264-stable.zip
       unzip x264-stable.zip
       cd x264-stable
       ./configure --enable-shared --enable-static
       make
       make DESTDIR=../out install
       
    2、安装nv-codec-headers
      git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git
      cd nv-codec-headers
      make
      sudo make isntall

    3、x265
       下载x265_3.2.1.tar.gz
       tar -zxvf x265_3.2.1.tar.gz
       cd x265_3.2.1
       cd build/linux
       ./make-Makefiles.bash
       make
       make DESTDIR=../../../out install

    4、mp3
       下载lame-3.100.tar.gz
       tar -zxvf lame-3.100.tar.gz
       cd lame-3.100
       ./configure 
       make
       make DESTDIR=../out install
      
    5、ffmpeg
       下载 FFmpeg-release-5.0.zip
       unzip FFmpeg-release-5.0.zip
       修改 FFmpeg-release-5.0/libavformat 下flv相关代码,让ffmpeg的flv支持h265(hevc)


       5.1修改flv.h,扩展rtmp协议的支持 FLV_CODECID_HEVC    = 12,

    1. didiff --git a/flv0.h b/flv.h
    2. index 3571b90..91f0065 100644
    3. --- a/flv0.h
    4. +++ b/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 {

        5.2修改解码flvdec.c,参照h264,增加h265(hevc) 

    1. diff --git a/flvdec0.c b/flvdec.c
    2. index b9e36b3..8a9261b 100644
    3. --- a/flvdec0.c
    4. +++ b/flvdec.c
    5. @@ -321,6 +321,8 @@ static int flv_same_video_codec(AVCodecParameters *vpar, int flags)
    6. return vpar->codec_id == AV_CODEC_ID_VP6A;
    7. case FLV_CODECID_H264:
    8. return vpar->codec_id == AV_CODEC_ID_H264;
    9. + case FLV_CODECID_HEVC:
    10. + return vpar->codec_id == AV_CODEC_ID_HEVC;
    11. default:
    12. return vpar->codec_tag == flv_codecid;
    13. }
    14. @@ -367,6 +369,11 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream,
    15. vstreami->need_parsing = AVSTREAM_PARSE_HEADERS;
    16. ret = 3; // not 4, reading packet type will consume one byte
    17. break;
    18. + case FLV_CODECID_HEVC:
    19. + par->codec_id = AV_CODEC_ID_HEVC;
    20. + vstreami->need_parsing = AVSTREAM_PARSE_HEADERS;
    21. + ret = 3; // not 4, reading packet type will consume one byte
    22. + break;
    23. case FLV_CODECID_MPEG4:
    24. par->codec_id = AV_CODEC_ID_MPEG4;
    25. ret = 3;
    26. @@ -1243,6 +1250,7 @@ retry_duration:
    27. if (st->codecpar->codec_id == AV_CODEC_ID_AAC ||
    28. st->codecpar->codec_id == AV_CODEC_ID_H264 ||
    29. + st->codecpar->codec_id == AV_CODEC_ID_HEVC ||
    30. st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
    31. int type = avio_r8(s->pb);
    32. size--;
    33. @@ -1252,7 +1260,7 @@ retry_duration:
    34. goto leave;
    35. }
    36. - if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
    37. + if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC ||st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
    38. // sign extension
    39. int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000;
    40. pts = av_sat_add64(dts, cts);
    41. @@ -1268,7 +1276,7 @@ retry_duration:
    42. }
    43. }
    44. if (type == 0 && (!st->codecpar->extradata || 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_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC)) {
    47. AVDictionaryEntry *t;
    48. if (st->codecpar->extradata) {

     5.3修改编码flvenc.c,增加头文件hevc.h

        注意两个地方:

          1)ff_isom_write_hvcc(pb, par->extradata, par->extradata_size,0);

          2)if ((ret = ff_hevc_annexb2mp4_buf(pkt->data, &data, &size,0,NULL)) < 0)  

    1. diff --git a/flvenc0.c b/flvenc.c
    2. index 66c530a..2be4bec 100644
    3. --- a/flvenc0.c
    4. +++ b/flvenc.c
    5. @@ -35,6 +35,7 @@
    6. #include "libavutil/opt.h"
    7. #include "libavcodec/put_bits.h"
    8. +#include "hevc.h"
    9. static const AVCodecTag flv_video_codec_ids[] = {
    10. { AV_CODEC_ID_FLV1, FLV_CODECID_H263 },
    11. @@ -46,6 +47,7 @@ static const AVCodecTag flv_video_codec_ids[] = {
    12. { AV_CODEC_ID_VP6, FLV_CODECID_VP6 },
    13. { AV_CODEC_ID_VP6A, FLV_CODECID_VP6A },
    14. { AV_CODEC_ID_H264, FLV_CODECID_H264 },
    15. + { AV_CODEC_ID_HEVC, FLV_CODECID_HEVC },
    16. { AV_CODEC_ID_NONE, 0 }
    17. };
    18. @@ -490,7 +492,7 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i
    19. AVIOContext *pb = s->pb;
    20. FLVContext *flv = s->priv_data;
    21. - if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264
    22. + if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_HEVC
    23. || par->codec_id == AV_CODEC_ID_MPEG4) {
    24. int64_t pos;
    25. avio_w8(pb,
    26. @@ -537,7 +539,15 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i
    27. avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags
    28. avio_w8(pb, 0); // AVC sequence header
    29. avio_wb24(pb, 0); // composition time
    30. - ff_isom_write_avcc(pb, par->extradata, par->extradata_size);
    31. + //ff_isom_write_avcc(pb, par->extradata, par->extradata_size);
    32. + if(par->codec_id==AV_CODEC_ID_HEVC)
    33. + {
    34. + ff_isom_write_hvcc(pb, par->extradata, par->extradata_size,0);
    35. + }
    36. + else
    37. + {
    38. + ff_isom_write_avcc(pb, par->extradata, par->extradata_size);
    39. + }
    40. }
    41. data_size = avio_tell(pb) - pos;
    42. avio_seek(pb, -data_size - 10, SEEK_CUR);
    43. @@ -797,7 +807,7 @@ end:
    44. AVCodecParameters *par = s->streams[i]->codecpar;
    45. FLVStreamContext *sc = s->streams[i]->priv_data;
    46. if (par->codec_type == AVMEDIA_TYPE_VIDEO &&
    47. - (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4))
    48. + (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_HEVC || par->codec_id == AV_CODEC_ID_MPEG4))
    49. put_avc_eos_tag(pb, sc->last_ts);
    50. }
    51. }
    52. @@ -848,12 +858,12 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
    53. if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A ||
    54. par->codec_id == AV_CODEC_ID_VP6 || par->codec_id == AV_CODEC_ID_AAC)
    55. flags_size = 2;
    56. - else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4)
    57. + else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_HEVC || par->codec_id == AV_CODEC_ID_MPEG4)
    58. flags_size = 5;
    59. else
    60. flags_size = 1;
    61. - if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264
    62. + if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_HEVC
    63. || par->codec_id == AV_CODEC_ID_MPEG4) {
    64. size_t side_size;
    65. uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
    66. @@ -874,7 +884,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
    67. "Packets are not in the proper order with respect to DTS\n");
    68. return AVERROR(EINVAL);
    69. }
    70. - if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) {
    71. + if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_HEVC || par->codec_id == AV_CODEC_ID_MPEG4) {
    72. if (pkt->pts == AV_NOPTS_VALUE) {
    73. av_log(s, AV_LOG_ERROR, "Packet is missing PTS\n");
    74. return AVERROR(EINVAL);
    75. @@ -914,11 +924,20 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
    76. return AVERROR(EINVAL);
    77. }
    78. - if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) {
    79. + if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_HEVC || par->codec_id == AV_CODEC_ID_MPEG4) {
    80. /* check if extradata looks like mp4 formatted */
    81. if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1)
    82. - if ((ret = ff_avc_parse_nal_units_buf(pkt->data, &data, &size)) < 0)
    83. - return ret;
    84. + if(par->codec_id == AV_CODEC_ID_HEVC)
    85. + {
    86. + if ((ret = ff_hevc_annexb2mp4_buf(pkt->data, &data, &size,0,NULL)) < 0)
    87. + return ret;
    88. + }
    89. + else
    90. + {
    91. + if ((ret = ff_avc_parse_nal_units_buf(pkt->data, &data, &size)) < 0)
    92. + return ret;
    93. + }
    94. +
    95. } else if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
    96. (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
    97. if (!s->streams[pkt->stream_index]->nb_frames) {
    98. @@ -991,7 +1010,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
    99. (FFALIGN(par->height, 16) - par->height));
    100. } else if (par->codec_id == AV_CODEC_ID_AAC)
    101. avio_w8(pb, 1); // AAC raw
    102. - else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) {
    103. + else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_HEVC || par->codec_id == AV_CODEC_ID_MPEG4) {
    104. avio_w8(pb, 1); // AVC NALU
    105. avio_wb24(pb, pkt->pts - pkt->dts);
    106. }


    6、编译ffmpeg
       cd FFmpeg-release-5.0/
       ./configure --enable-shared --enable-static --enable-debug --enable-libx264 --enable-libx265 --enable-libmp3lame --enable-gpl --disable-optimizations --disable-stripping --enable-libfreetype --enable-version3 --extra-cflags=-I../out/usr/local/include  --extra-ldflags=-L../out/usr/local/lib
       make -j8
       make DESTDIR=../out install

    当执行./configure时遇到ERROR: x265 not found using pkg-config这个错误时,先执行下:
    sudo apt install pkg-config

    如已安装,还会提示,执行export 

    export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:`pwd`/../out/usr/local/lib/pkgconfig

    `pwd`/../out/usr/local/lib/pkgconfig 不行,就用自己的绝对路径
       
    7、验证
       cd out/usr/local
       export LD_LIBRARY_PATH='pwd'/lib:$LD_LIBRARY_PATH
       ./bin/ffmpeg  -i 1.mp4 -c:v libx265 -f flv 1.flv
       用./bin/ffprobe -i 1.flv 查看是否成功
       ./bin/ffmpeg  -i 1.flv -c:v libx264 2.mp4
       成功

    8、测试rtmp推流

     下载安装支持h265的rtmp推流服务 pingos ,此平台个人觉得不好,有空可以试试修改srs

    ./bin/ffmpeg -re -stream_loop -1 -i 1.mp4 -c:v hevc_nvenc -f flv rtmp://192.168.0.15/live/t33
    ./bin/ffmpeg -c:v hevc_cuvid -i rtmp://192.168.0.15/live/t33 -c:v h264_nvenc -f flv rtmp://192.168.0.15/live/t35

    这样就可以用vlc播放rtmp://192.168.0.15/live/t35。

    感谢博主:染尘111

    参考了他的博文:

    ffmpeg编译支持h265的rtmp windown版本_染尘111的博客-CSDN博客_ffmpeg支持h265编解码版本

  • 相关阅读:
    【LLM模型篇】LLaMA2 | Vicuna | EcomGPT等
    工控网络协议模糊测试:用peach对modbus协议进行模糊测试
    机器学习基础:随机变量及其概率分布
    JS教程之Electron.js设计强大的多平台桌面应用程序的好工具
    调整屏幕的宽高比
    张鑫溢:9.8现货黄金震荡走弱,一度刷新三个交易日低点.黄金行情趋势分析及黄金原油独家操作建议指导.
    淘宝如何选词打造黄金标题?构词规则是什么?
    Python平板电脑数据分析-课程大作业-部分源码
    SAP UI5 SimpleForm 控件的 adjustLabelSpan 属性
    K8s网络存储,NFS,PV,PVC,StorageClass等详解
  • 原文地址:https://blog.csdn.net/howesao/article/details/126153429