统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 template<typename T> struct Size2
{ {
T width,height; T width,height;
public:
Size2()
{
width=height=0;
}
}; };
using Size2u=Size2<uint>; using Size2u=Size2<uint>;

View File

@ -4,16 +4,19 @@ extern "C"
#include<libavutil/imgutils.h> #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; ctx=sc;
dst_fmt=dst; src_frame_fmt=src;
src_fmt=src; dst_frame_fmt=dst;
frame_size=src_size; av_image_alloc(dst_data,
dst_linesize,
av_image_alloc(dst_data,dst_linesize,frame_size.width,frame_size.height,dst,1); dst_frame_fmt.size.width,
dst_frame_fmt.size.height,
dst_frame_fmt.pixel_format,
1);
} }
FrameConvert::~FrameConvert() FrameConvert::~FrameConvert()
@ -26,18 +29,18 @@ void FrameConvert::Convert(const FrameData &src_data,const FrameLinesize &src_li
{ {
sws_scale( ctx, sws_scale( ctx,
src_data,src_linesize, src_data,src_linesize,
0,frame_size.height, 0,src_frame_fmt.size.height,
dst_data,dst_linesize); 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, SwsContext *sc=sws_getContext( src.size.width,src.size.height,src.pixel_format,
src_size.width,src_size.height,dst, dst.size.width,dst.size.height,dst.pixel_format,
SWS_SPLINE, SWS_SPLINE,
nullptr,nullptr,nullptr); nullptr,nullptr,nullptr);
if(!sc)return(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 uint8_t *FrameData[8];
typedef int FrameLinesize[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 class FrameConvert
{ {
AVPixelFormat src_fmt,dst_fmt; FrameFormat src_frame_fmt;
Size2u frame_size; FrameFormat dst_frame_fmt;
SwsContext *ctx; SwsContext *ctx;
@ -23,9 +45,9 @@ class FrameConvert
private: 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: public:
@ -40,4 +62,4 @@ public:
const int GetLinesize(const int index)const{return dst_linesize[index];} const int GetLinesize(const int index)const{return dst_linesize[index];}
};//class FrameConvert };//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: protected:
Size2u frame_size; FrameFormat src_format;
FrameFormat dst_format;
AVRational frame_rate; AVRational frame_rate;
public: public:
FrameRecviver(const AVPixelFormat &dst_pf)
{
dst_format.pixel_format=dst_pf;
}
virtual ~FrameRecviver()=default; virtual ~FrameRecviver()=default;
virtual void SetFrameRate(const AVRational &fr){frame_rate=fr;} virtual void SetFrameRate(const AVRational &fr){frame_rate=fr;}
virtual bool OnFrame(const AVFrame *frame)=0; virtual bool OnFrame(const AVFrame *frame)=0;
public: public:
const uint GetWidth()const{return frame_size.width;} const Size2u &GetSourceFrameSize()const{return src_format.size;}
const uint GetHeight()const{return frame_size.height;} const Size2u &GetTargetFrameSize()const{return dst_format.size;}
virtual Size2u ComputeDstFrameSize(const Size2u &src_size)
{
return src_size; //这样等于不缩放
}
};// };//
class RGBAFrameRecviver:public FrameRecviver class RGBAFrameRecviver:public FrameRecviver
{ {
private: private:
AVPixelFormat src_format=AV_PIX_FMT_NONE;
FrameConvert *convert=nullptr; FrameConvert *convert=nullptr;
private: private:
@ -43,6 +52,7 @@ private:
public: public:
RGBAFrameRecviver():FrameRecviver(AV_PIX_FMT_RGBA){}
virtual ~RGBAFrameRecviver() virtual ~RGBAFrameRecviver()
{ {
if(convert) if(convert)

View File

@ -6,30 +6,32 @@ extern "C"
#include<libavutil/pixdesc.h> #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) bool RGBAFrameRecviver::OnFrame(const AVFrame *frame)
{ {
if(src_format==AV_PIX_FMT_NONE) if(!convert)
{ {
frame_size.width=frame->width; src_format.pixel_format =AVPixelFormat(frame->format);
frame_size.height=frame->height; 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 out("src",src_format);
<<"format: "<<av_get_pix_fmt_name(src_format)<<std::endl; out("dst",dst_format);
if(src_format!=AV_PIX_FMT_RGBA) convert=InitFrameConvert(src_format,dst_format);
convert=InitFrameConvert(AV_PIX_FMT_RGBA,src_format,frame_size);
} }
if(src_format==AV_PIX_FMT_RGBA) convert->Convert(frame->data,frame->linesize);
{
return OnFrameRGBA((uint8 *)(frame->data[0]));
}
else
{
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"VideoEncoder.h"
#include"libyuv/convert_from_argb.h"
#include<iostream> #include<iostream>
#include"libyuv.h" #include<queue>
#include <queue>
namespace namespace
{ {
@ -123,13 +123,13 @@ public:
avformat_free_context(fmt_ctx); 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->bit_rate =bit_rate;
codec_ctx->width =w; codec_ctx->width =s.width;
codec_ctx->height =h; codec_ctx->height =s.height;
codec_ctx->framerate =fr; codec_ctx->framerate =fr;
codec_ctx->time_base.den=fr.num; codec_ctx->time_base.den=fr.num;
codec_ctx->time_base.num=fr.den; codec_ctx->time_base.num=fr.den;
@ -141,8 +141,8 @@ public:
video_stream=avformat_new_stream(fmt_ctx,codec); video_stream=avformat_new_stream(fmt_ctx,codec);
video_stream->codecpar->codec_id =fmt_ctx->video_codec_id; video_stream->codecpar->codec_id =fmt_ctx->video_codec_id;
video_stream->codecpar->codec_type =AVMEDIA_TYPE_VIDEO; video_stream->codecpar->codec_type =AVMEDIA_TYPE_VIDEO;
video_stream->codecpar->width =w; video_stream->codecpar->width =s.width;
video_stream->codecpar->height =h; video_stream->codecpar->height =s.height;
video_stream->codecpar->format =codec_ctx->pix_fmt; video_stream->codecpar->format =codec_ctx->pix_fmt;
video_stream->codecpar->bit_rate =bit_rate; video_stream->codecpar->bit_rate =bit_rate;
video_stream->time_base =codec_ctx->time_base; video_stream->time_base =codec_ctx->time_base;

View File

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

View File

@ -3,7 +3,6 @@
#include"VideoDecoder.h" #include"VideoDecoder.h"
#include"FrameRecviver.h" #include"FrameRecviver.h"
#include<stdlib.h> #include<stdlib.h>
#include"libyuv/scale_argb.h"
constexpr uint32_t ALIGN_PIXELS=8; constexpr uint32_t ALIGN_PIXELS=8;
@ -16,15 +15,11 @@ const uint32_t GetAlignValue(const uint32_t value)
class EvoFrameRecviver:public RGBAFrameRecviver class EvoFrameRecviver:public RGBAFrameRecviver
{ {
uint8 *new_image=nullptr; VideoEncoder *rgb_encoder=nullptr;
uint8 *rgb_image=nullptr;
bool new_size=false; uint new_height=0;
uint new_width; bool frame_init=false;
uint new_height;
VideoEncoder *rgb_encoder;
public: public:
@ -37,63 +32,36 @@ public:
~EvoFrameRecviver() ~EvoFrameRecviver()
{ {
rgb_encoder->Finish(); rgb_encoder->Finish();
}
delete[] rgb_image; Size2u ComputeDstFrameSize(const Size2u &src_size) override
delete[] new_image; {
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 bool OnFrameRGBA(const uint8 *rgba_data) override
{ {
if(!rgb_image) return rgb_encoder->WriteFrame(rgba_data);
{
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);
} }
}; };