diff --git a/DataType.h b/DataType.h index 504260e..58df876 100644 --- a/DataType.h +++ b/DataType.h @@ -44,6 +44,13 @@ using vec2d=vec2; template struct Size2 { T width,height; + +public: + + Size2() + { + width=height=0; + } }; using Size2u=Size2; diff --git a/FrameConvert.cpp b/FrameConvert.cpp index 7c8e4be..b16aa7b 100644 --- a/FrameConvert.cpp +++ b/FrameConvert.cpp @@ -4,16 +4,19 @@ extern "C" #include } -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)); } \ No newline at end of file diff --git a/FrameConvert.h b/FrameConvert.h index 68a0d1a..454e2f4 100644 --- a/FrameConvert.h +++ b/FrameConvert.h @@ -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); diff --git a/FrameRecviver.h b/FrameRecviver.h index d381857..2b54c82 100644 --- a/FrameRecviver.h +++ b/FrameRecviver.h @@ -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) diff --git a/RGBAFrameRecviver.cpp b/RGBAFrameRecviver.cpp index 3065cdb..3214dd9 100644 --- a/RGBAFrameRecviver.cpp +++ b/RGBAFrameRecviver.cpp @@ -6,30 +6,32 @@ extern "C" #include } +namespace +{ + void out(const char *str,const FrameFormat &ff) + { + std::cout<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: "<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)); } diff --git a/VideoEncoder.cpp b/VideoEncoder.cpp index e2e3bb6..5811b51 100644 --- a/VideoEncoder.cpp +++ b/VideoEncoder.cpp @@ -6,9 +6,9 @@ } #include"VideoEncoder.h" +#include"libyuv/convert_from_argb.h" #include -#include"libyuv.h" -#include +#include 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; diff --git a/VideoEncoder.h b/VideoEncoder.h index ab7643e..3d1ceca 100644 --- a/VideoEncoder.h +++ b/VideoEncoder.h @@ -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; } diff --git a/main.cpp b/main.cpp index 300185d..c6a50aa 100644 --- a/main.cpp +++ b/main.cpp @@ -3,7 +3,6 @@ #include"VideoDecoder.h" #include"FrameRecviver.h" #include -#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: "<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); } };