From 18a05d269516a5e33d8460291c2f93e73d95adce Mon Sep 17 00:00:00 2001 From: zhangmeng <775834166@qq.com> Date: 星期二, 26 十二月 2023 10:45:31 +0800 Subject: [PATCH] GetYUV format is NV12 --- csrc/ffmpeg/format/FormatOut.cpp | 95 +++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 79 insertions(+), 16 deletions(-) diff --git a/csrc/ffmpeg/format/FormatOut.cpp b/csrc/ffmpeg/format/FormatOut.cpp index 60efd59..5d51aaf 100644 --- a/csrc/ffmpeg/format/FormatOut.cpp +++ b/csrc/ffmpeg/format/FormatOut.cpp @@ -10,6 +10,7 @@ #include <libavformat/avformat.h> #include <libavcodec/avcodec.h> #include <libavutil/opt.h> +#include <libavutil/intreadwrite.h> } #include "../log/log.hpp" @@ -33,11 +34,16 @@ ,format_name_("mp4") ,in_v_stream_(NULL) ,in_a_stream_(NULL) + ,bsf_h264(NULL) + ,bsf_hevc(NULL) {} FormatOut::~FormatOut() { clear(); + + if (bsf_h264) av_bsf_free(&bsf_h264); + if (bsf_hevc) av_bsf_free(&bsf_hevc); } void FormatOut::clear(){ @@ -101,8 +107,8 @@ enc_ctx_->codec_id = AV_CODEC_ID_H264; enc_ctx_->codec_type = AVMEDIA_TYPE_VIDEO; - enc_ctx_->height = (prop.height_ & 0x01) ? prop.height_-1 : prop.height_; - enc_ctx_->width = (prop.width_ & 0x01) ? prop.width_ - 1 : prop.width_; + enc_ctx_->height = prop.height_ & ~0x01; + enc_ctx_->width = prop.width_ & ~0x01; enc_ctx_->sample_aspect_ratio = prop.sample_aspect_ratio_; @@ -176,7 +182,7 @@ av_opt_set(enc_ctx_->priv_data, "tune", "zerolatency", 0); av_opt_set(enc_ctx_->priv_data, "profile", "baseline", 0); - int err =avcodec_open2(enc_ctx_, codec, NULL); + int err = avcodec_open2(enc_ctx_, codec, NULL); if( err< 0) { logIt("can't open output codec: %s", getAVErrorDesc(err).c_str()); @@ -188,14 +194,11 @@ return false; } ofmt->video_codec = codec_id; - if(ofmt->flags & AVFMT_GLOBALHEADER) - { + if(ofmt->flags & AVFMT_GLOBALHEADER){ enc_ctx_->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } - return true; - } AVStream *FormatOut::getStream(){ @@ -340,7 +343,26 @@ } flag = openResource(filename, 2); - + +// h264 mp4toannexb + if (v && v->codecpar->codec_id == AV_CODEC_ID_H264) { + if (!bsf_h264){ + char p[100] = {0}; + char *sub = av_fourcc_make_string(p, v->codecpar->codec_tag); + if (strcmp(sub, "avc1") == 0){ + const AVBitStreamFilter *f = av_bsf_get_by_name("h264_mp4toannexb"); + if (f){ + if (av_bsf_alloc(f, &bsf_h264) >= 0){ + if (avcodec_parameters_copy(bsf_h264->par_in, v->codecpar) >= 0){ + if (av_bsf_init(bsf_h264) < 0) bsf_h264 = NULL; + } + } + } + } + } + } +// h264 mp4toannexb + if(flag){ AVDictionary *avdic = NULL; char option_key[]="movflags"; @@ -349,7 +371,7 @@ flag = writeHeader(&avdic); av_dict_free(&avdic); } - + return flag; } @@ -399,7 +421,7 @@ int out_idx = -1; std::vector<AVStream*> in_streams{in_v_stream_, in_a_stream_}; for (auto i : in_streams){ - if (i->index == pkt->stream_index){ + if (i && (i->index == pkt->stream_index)){ if (i->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){ out_idx = v_idx_; in_stream = i; @@ -446,7 +468,7 @@ bool interleaved/* = true*/){ adjustPTS(pkt, frame_cnt); - auto ret = writeFrame2(pkt, interleaved); + auto ret = writeFrameInternal(pkt, interleaved); if (!ret){ logIt("write to file failed, pkt.pts: %lld, dts: %lld, frame count: %d", pkt->pts, pkt->dts, frame_cnt); @@ -454,16 +476,16 @@ return ret; } - bool FormatOut::writeFrame2(AVPacket *pkt, bool interleaved){ - + static bool write_frame(AVFormatContext *ctx, AVPacket *pkt, bool interleaved){ + int ret = 0; if(interleaved){ - ret = av_interleaved_write_frame(ctx_, pkt); + ret = av_interleaved_write_frame(ctx, pkt); }else{ // returns 1 if flushed and there is no more data to flush - ret = av_write_frame(ctx_, pkt); + ret = av_write_frame(ctx, pkt); } - + if(ret < -22 || ret == 0){ return true; } @@ -471,6 +493,47 @@ return false; } + bool FormatOut::writeFrameInternal(AVPacket *pkt, bool interleaved){ + + AVBSFContext *bsf = NULL; + + if (in_v_stream_ && in_v_stream_->codecpar->codec_id == AV_CODEC_ID_HEVC) { + if (pkt->size >= 5 && + AV_RB32(pkt->data) != 0x0000001 && + AV_RB24(pkt->data) != 0x000001 && + !bsf_hevc){ + + const AVBitStreamFilter *f = av_bsf_get_by_name("hevc_mp4toannexb"); + if (f){ + if (av_bsf_alloc(f, &bsf_hevc) >= 0){ + if (avcodec_parameters_copy(bsf_hevc->par_in, in_v_stream_->codecpar) >= 0){ + if (av_bsf_init(bsf_hevc) < 0) bsf_hevc = NULL; + } + } + } + } + + bsf = bsf_hevc; + logIt("use hevc AVBitStreamFilter"); + }else { + bsf = bsf_h264; + logIt("use h264 AVBitStreamFilter"); + } + + if (bsf){ + if (av_bsf_send_packet(bsf, pkt) < 0){ + logIt("bsf send packet failed"); + return true; + } + if (av_bsf_receive_packet(bsf, pkt) < 0){ + logIt("bsf recv packet failed"); + return true; + } + } + + return write_frame(ctx_, pkt, interleaved); + } + bool FormatOut::writeTrailer(){ const int ret = av_write_trailer(ctx_); if(ret != 0) -- Gitblit v1.8.0