统frame pixelformat/size为FrameFormat,并放弃LIBYUV缩放改用ffmpeg的swscale缩放
This commit is contained in:
parent
f4706aa941
commit
3e9ba60aea
@ -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>;
|
||||
|
@ -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));
|
||||
}
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
88
main.cpp
88
main.cpp
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user