统frame pixelformat/size为FrameFormat,并放弃LIBYUV缩放改用ffmpeg的swscale缩放

This commit is contained in:
hyzboy 2025-03-29 16:14:11 +08:00
parent f4706aa941
commit 3e9ba60aea
8 changed files with 123 additions and 121 deletions

View File

@ -44,6 +44,13 @@ using vec2d=vec2<double>;
template<typename T> struct Size2
{
T width,height;
public:
Size2()
{
width=height=0;
}
};
using Size2u=Size2<uint>;

View File

@ -4,16 +4,19 @@ extern "C"
#include<libavutil/imgutils.h>
}
FrameConvert::FrameConvert(SwsContext *sc,enum AVPixelFormat dst,enum AVPixelFormat src,const Size2u &src_size)
FrameConvert::FrameConvert(SwsContext *sc,const FrameFormat &src,const FrameFormat &dst)
{
ctx=sc;
dst_fmt=dst;
src_fmt=src;
src_frame_fmt=src;
dst_frame_fmt=dst;
frame_size=src_size;
av_image_alloc(dst_data,dst_linesize,frame_size.width,frame_size.height,dst,1);
av_image_alloc(dst_data,
dst_linesize,
dst_frame_fmt.size.width,
dst_frame_fmt.size.height,
dst_frame_fmt.pixel_format,
1);
}
FrameConvert::~FrameConvert()
@ -26,18 +29,18 @@ void FrameConvert::Convert(const FrameData &src_data,const FrameLinesize &src_li
{
sws_scale( ctx,
src_data,src_linesize,
0,frame_size.height,
0,src_frame_fmt.size.height,
dst_data,dst_linesize);
}
FrameConvert *InitFrameConvert(enum AVPixelFormat dst,enum AVPixelFormat src,const Size2u &src_size)
FrameConvert *InitFrameConvert(const FrameFormat &src,const FrameFormat &dst)
{
SwsContext *sc=sws_getContext( src_size.width,src_size.height,src,
src_size.width,src_size.height,dst,
SwsContext *sc=sws_getContext( src.size.width,src.size.height,src.pixel_format,
dst.size.width,dst.size.height,dst.pixel_format,
SWS_SPLINE,
nullptr,nullptr,nullptr);
if(!sc)return(nullptr);
return(new FrameConvert(sc,dst,src,src_size));
return(new FrameConvert(sc,src,dst));
}

View File

@ -11,10 +11,32 @@ extern "C"
typedef uint8_t *FrameData[8];
typedef int FrameLinesize[8];
struct FrameFormat
{
AVPixelFormat pixel_format;
Size2u size;
public:
FrameFormat()
{
pixel_format=AV_PIX_FMT_NONE;
size.width=size.height=0;
}
FrameFormat(const AVPixelFormat &pf,const Size2u &s)
{
pixel_format=pf;
size=s;
}
};//FrameFormat
void SetFormat(FrameFormat *ff,const AVFrame *);
class FrameConvert
{
AVPixelFormat src_fmt,dst_fmt;
Size2u frame_size;
FrameFormat src_frame_fmt;
FrameFormat dst_frame_fmt;
SwsContext *ctx;
@ -23,9 +45,9 @@ class FrameConvert
private:
friend FrameConvert *InitFrameConvert(enum AVPixelFormat dst,enum AVPixelFormat src,const Size2u &);
friend FrameConvert *InitFrameConvert(const FrameFormat &src,const FrameFormat &dst);
FrameConvert(SwsContext *sc,enum AVPixelFormat dst,enum AVPixelFormat src,const Size2u &);
FrameConvert(SwsContext *sc,const FrameFormat &src,const FrameFormat &dst);
public:
@ -40,4 +62,4 @@ public:
const int GetLinesize(const int index)const{return dst_linesize[index];}
};//class FrameConvert
FrameConvert *InitFrameConvert(enum AVPixelFormat dst,enum AVPixelFormat src,const Size2u &src_size);
FrameConvert *InitFrameConvert(const FrameFormat &src,const FrameFormat &dst);

View File

@ -12,29 +12,38 @@ class FrameRecviver
{
protected:
Size2u frame_size;
FrameFormat src_format;
FrameFormat dst_format;
AVRational frame_rate;
public:
FrameRecviver(const AVPixelFormat &dst_pf)
{
dst_format.pixel_format=dst_pf;
}
virtual ~FrameRecviver()=default;
virtual void SetFrameRate(const AVRational &fr){frame_rate=fr;}
virtual bool OnFrame(const AVFrame *frame)=0;
public:
const uint GetWidth()const{return frame_size.width;}
const uint GetHeight()const{return frame_size.height;}
const Size2u &GetSourceFrameSize()const{return src_format.size;}
const Size2u &GetTargetFrameSize()const{return dst_format.size;}
virtual Size2u ComputeDstFrameSize(const Size2u &src_size)
{
return src_size; //这样等于不缩放
}
};//
class RGBAFrameRecviver:public FrameRecviver
{
private:
AVPixelFormat src_format=AV_PIX_FMT_NONE;
FrameConvert *convert=nullptr;
private:
@ -43,6 +52,7 @@ private:
public:
RGBAFrameRecviver():FrameRecviver(AV_PIX_FMT_RGBA){}
virtual ~RGBAFrameRecviver()
{
if(convert)

View File

@ -6,30 +6,32 @@ extern "C"
#include<libavutil/pixdesc.h>
}
namespace
{
void out(const char *str,const FrameFormat &ff)
{
std::cout<<str<<"_size: "<<ff.size.width<<"x"<<ff.size.height<<std::endl
<<str<<"_format: "<<av_get_pix_fmt_name(ff.pixel_format)<<std::endl;
}
}//namespace
bool RGBAFrameRecviver::OnFrame(const AVFrame *frame)
{
if(src_format==AV_PIX_FMT_NONE)
if(!convert)
{
frame_size.width=frame->width;
frame_size.height=frame->height;
src_format.pixel_format =AVPixelFormat(frame->format);
src_format.size.width =frame->width;
src_format.size.height =frame->height;
src_format=AVPixelFormat(frame->format);
dst_format.size=ComputeDstFrameSize(src_format.size);
std::cout<<"size: "<<frame_size.width<<"x"<<frame_size.height<<std::endl
<<"format: "<<av_get_pix_fmt_name(src_format)<<std::endl;
out("src",src_format);
out("dst",dst_format);
if(src_format!=AV_PIX_FMT_RGBA)
convert=InitFrameConvert(AV_PIX_FMT_RGBA,src_format,frame_size);
convert=InitFrameConvert(src_format,dst_format);
}
if(src_format==AV_PIX_FMT_RGBA)
{
return OnFrameRGBA((uint8 *)(frame->data[0]));
}
else
{
convert->Convert(frame->data,frame->linesize);
convert->Convert(frame->data,frame->linesize);
return OnFrameRGBA(convert->GetData(0));
}
return OnFrameRGBA(convert->GetData(0));
}

View File

@ -6,9 +6,9 @@
}
#include"VideoEncoder.h"
#include"libyuv/convert_from_argb.h"
#include<iostream>
#include"libyuv.h"
#include <queue>
#include<queue>
namespace
{
@ -123,13 +123,13 @@ public:
avformat_free_context(fmt_ctx);
}
void Set(const uint w,const uint h,const AVRational &fr) override
void Set(const AVRational &fr,const Size2u &s) override
{
VideoEncoder::Set(w,h,fr);
VideoEncoder::Set(fr,s);
codec_ctx->bit_rate =bit_rate;
codec_ctx->width =w;
codec_ctx->height =h;
codec_ctx->width =s.width;
codec_ctx->height =s.height;
codec_ctx->framerate =fr;
codec_ctx->time_base.den=fr.num;
codec_ctx->time_base.num=fr.den;
@ -141,8 +141,8 @@ public:
video_stream=avformat_new_stream(fmt_ctx,codec);
video_stream->codecpar->codec_id =fmt_ctx->video_codec_id;
video_stream->codecpar->codec_type =AVMEDIA_TYPE_VIDEO;
video_stream->codecpar->width =w;
video_stream->codecpar->height =h;
video_stream->codecpar->width =s.width;
video_stream->codecpar->height =s.height;
video_stream->codecpar->format =codec_ctx->pix_fmt;
video_stream->codecpar->bit_rate =bit_rate;
video_stream->time_base =codec_ctx->time_base;

View File

@ -22,8 +22,7 @@ protected:
AVFormatContext* fmt_ctx;
AVCodecContext* codec_ctx;
uint width;
uint height;
Size2u frame_size;
AVRational frame_rate;
uint bit_rate;
@ -35,26 +34,17 @@ public:
{
strcpy_s(filename,_MAX_PATH,fn);
width=height=0;
bit_rate=br;
}
AVFormatContext* GetFrmCtx()
{
return fmt_ctx;
}
AVCodecContext* GetCodecCtx() {
return codec_ctx
;
};
AVFormatContext *GetFrmCtx(){return fmt_ctx;}
AVCodecContext *GetCodecCtx(){return codec_ctx;}
virtual ~VideoEncoder()=default;
virtual void Set(const uint w,const uint h,const AVRational &fr)
virtual void Set(const AVRational &fr,const Size2u &size)
{
width=w;
height=h;
frame_size=size;
frame_rate=fr;
}

View File

@ -3,7 +3,6 @@
#include"VideoDecoder.h"
#include"FrameRecviver.h"
#include<stdlib.h>
#include"libyuv/scale_argb.h"
constexpr uint32_t ALIGN_PIXELS=8;
@ -16,15 +15,11 @@ const uint32_t GetAlignValue(const uint32_t value)
class EvoFrameRecviver:public RGBAFrameRecviver
{
uint8 *new_image=nullptr;
uint8 *rgb_image=nullptr;
VideoEncoder *rgb_encoder=nullptr;
bool new_size=false;
uint new_height=0;
uint new_width;
uint new_height;
VideoEncoder *rgb_encoder;
bool frame_init=false;
public:
@ -37,63 +32,36 @@ public:
~EvoFrameRecviver()
{
rgb_encoder->Finish();
}
delete[] rgb_image;
delete[] new_image;
Size2u ComputeDstFrameSize(const Size2u &src_size) override
{
Size2u result;
if(new_height>0)
{
result.height =GetAlignValue(new_height);
const double scale=double(new_height)/double(src_size.height);
result.width =GetAlignValue(double(src_size.width)*scale);
}
else
{
result.width =GetAlignValue(src_size.width);
result.height =GetAlignValue(src_size.height);
}
rgb_encoder->Set(frame_rate,result);
frame_init=rgb_encoder->Init();
return result;
}
bool OnFrameRGBA(const uint8 *rgba_data) override
{
if(!rgb_image)
{
if(new_height>0)
{
new_height =GetAlignValue(new_height);
const double scale=double(new_height)/double(GetHeight());
new_width =GetAlignValue(double(GetWidth())*scale);
new_size=true;
}
else
{
new_width =GetAlignValue(GetWidth());
new_height =GetAlignValue(GetHeight());
if(new_width!=GetWidth()
||new_height!=GetHeight())
new_size=true;
}
std::cout<<"Movie Origin size: "<<GetWidth()<<"x"<<GetHeight()<<std::endl;
if(new_size)
{
std::cout<<"Movie Scaled size: "<<new_width<<"x"<<new_height<<std::endl;
new_image=new uint8[new_width*new_height*4*2];
}
rgb_image=new uint8[new_width*new_height*4];
rgb_encoder->Set(new_width,new_height,frame_rate);
if(!rgb_encoder->Init())
return(false);
}
if(new_size)
{
libyuv::ARGBScale( rgba_data, GetWidth()*4, GetWidth(), GetHeight(),
rgb_image, new_width*4, new_width, new_height,libyuv::FilterMode::kFilterBox);
return rgb_encoder->WriteFrame(rgb_image);
}
else
{
return rgb_encoder->WriteFrame(rgba_data);
}
//SaveToTGA(filename,(void *)two_image,GetWidth()*2,GetHeight(),24,true);
return rgb_encoder->WriteFrame(rgba_data);
}
};