使用FFmpeg 编解码 FLV的HEVC(H265)格式的视频
參考資料:https://gist.github.com/XueshiQiao/c50fd1f088d431ceb1f59bd4ec40c6d7
HEVC編碼的FLV格式視頻 -->?https://download.csdn.net/download/qq_36236684/13686337
?
Flash Video(簡稱FLV),是一種網絡視頻格式,用作串流媒體格式,它的出現有效地解決了視頻文件導入Flash后,使導出的SWF文件體積龐大,不能在網絡上有效使用等缺點。
HEVC是High Efficiency Video Coding的縮寫(又稱為H.265和MPEG-H第2部分),是一種新的視頻壓縮標準,用來以替代H.264/AVC編碼標準,2013年1月26號,HEVC正式成為國際標準。
?
前言:
? ? 最近團隊需要編解碼FLV封裝的HEVC編碼的視頻,但是FFmpeg因為某種原因,沒有原生支持上述封裝。因此在網上搜尋之后找到了相關的解決方案,在此記錄一下。
?
FFMpeg版本:3.4.5
1. 修改部分,可以使用patch命令直接合到自己的項目中
需要注意的是?FLV_CODECID_HEVC ? ?= 14,可以根據實際情況更改,一般情況下國內使用的都是14,也有用12的
commit 35b84e7ff5ea2dd314eb9e14fe9698e3c3b1bb09 Author: xxx <xxx@xxx-xx.cn> Date: Mon Dec 14 11:06:49 2020 +0800add h265 dec & enc in flvdiff --git a/libavformat/flv.h b/libavformat/flv.h index df5ce3d..2b025bb 100644 --- a/libavformat/flv.h +++ b/libavformat/flv.h @@ -109,6 +109,7 @@ enum {FLV_CODECID_H264 = 7,FLV_CODECID_REALH263= 8,FLV_CODECID_MPEG4 = 9, + FLV_CODECID_HEVC = 14,};enum { diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index 2d89bef..bc0ae18 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -36,6 +36,7 @@#include "internal.h"#include "avio_internal.h"#include "flv.h" +#include "hevc.h"#define VALIDATE_INDEX_TS_THRESH 2500@@ -291,6 +292,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;} @@ -340,6 +343,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_NONE; + ret = 3; // not 4, reading packet type will consume one byte + break;default:avpriv_request_sample(s, "Video codec (%x)", flv_codecid);par->codec_tag = flv_codecid; @@ -1149,10 +1157,11 @@ 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--; - 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; @@ -1168,7 +1177,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 e966c36..3d2de1b 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -34,7 +34,7 @@#include "libavutil/opt.h"#include "libavcodec/put_bits.h"#include "libavcodec/aacenctab.h" - +#include "hevc.h"static const AVCodecTag flv_video_codec_ids[] = {{ AV_CODEC_ID_FLV1, FLV_CODECID_H263 }, @@ -46,6 +46,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 }};@@ -486,7 +487,7 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par) {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 ? @@ -533,7 +534,11 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par) {avio_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); @@ -836,7 +841,7 @@ 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);}} @@ -887,13 +892,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))) { @@ -956,6 +961,10 @@ 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) { + 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) { @@ -1028,7 +1037,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);}2. 編譯:
?./configure --prefix=/usr/local --enable-libx265 --enable-gpl --enable-ffplay make make install?
3. 轉碼為h265:
? ?-i 為輸入,-acodec 為音頻編碼,-vcodec為視頻編碼
ffmpeg -y ?-i xxx.mp4 -acodec copy -vcodec libx265 xxx.flv4. 播放
ffplay xxx.flv?
?
總結
以上是生活随笔為你收集整理的使用FFmpeg 编解码 FLV的HEVC(H265)格式的视频的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全系列三极管应用参数和代换大全
- 下一篇: Power BI 企业邮箱账户注册