基本思想:记录学习夏曹俊ffmpeg基本函数使用,window11+clion_mingw+ffmpeg库,基本函数使用和yuv编码h264
cmakelists.txt
cmake_minimum_required(VERSION 3.16)
project(untitled1)
find_package(OpenCV REQUIRED)
set(CMAKE_CXX_STANDARD 14)
add_executable(untitled1 main.cpp)
target_link_libraries(untitled1
${OpenCV_LIBS}
-lavformat -lavcodec -lswscale -lavutil -lz
)
mian.cpp
#include <iostream>
#include <vector>
#include <opencv2/highgui.hpp>
#include <opencv2/video.hpp>
#include <opencv2/opencv.hpp>
extern "C"
{
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
#include <libavutil/avutil.h>
}
#include "fstream"
using namespace std;
using namespace cv;
int main() {
string filename="1920_1080_generate_min.h264";
ofstream ofs;
ofs.open(filename,ios::binary);
//寻找编码器
auto codec=avcodec_find_encoder(AV_CODEC_ID_H264);
if(!codec){
cerr<<"find avcodec fail "<<endl;
return -1;
}
// 编码上下文
auto c=avcodec_alloc_context3(codec);
if(!c){
cerr<<"find avcodetext fail"<<endl;
return -1;
}
//设定上下文参数
c->width=1920;
c->height=1080;
c->time_base={1,25};
c->pix_fmt=AV_PIX_FMT_YUV420P; //指定原数据像素格式,于编码相关
c->thread_count=16;
//打开编码上下文
int ret=avcodec_open2(c,codec,NULL);
if(ret){
char buf[1024]={0};
av_strerror(ret,buf,sizeof(buf)-1);
cerr<<buf<<endl;
return -1;
}
auto frame=av_frame_alloc();
frame->width=c->width;
frame->height=c->height;
frame->format=c->pix_fmt;
ret=av_frame_get_buffer(frame,0);
if(ret){
char buf[1024]={0};
av_strerror(ret,buf,sizeof(buf)-1);
cerr<<buf<<endl;
return -1;
}
auto packet=av_packet_alloc();
for(int i=0;i<250;i++){
//生成yvv数据
for(int y=0;y<c->height;y++){
for(int x=0;x<c->width;x++){
frame->data[0][y*frame->linesize[0]+x]=x+y+i*3;
}
}
for(int y=0;y<c->height/2;y++){
for(int x=0;x<c->width/2;x++){
frame->data[1][y*frame->linesize[1]+x]=128+y+i*2;
frame->data[2][y*frame->linesize[2]+x]=64+x+i*5;
}
}
frame->pts=i;
//10秒视频 发送未压缩帧到线程中
ret= avcodec_send_frame(c,frame);
if(ret){
char buf[1024]={0};
av_strerror(ret,buf,sizeof(buf)-1);
cerr<<buf<<endl;
return -1;
}
while(ret>=0){//一个frame可以返回多个packet
ret= avcodec_receive_packet(c,packet);
if(ret==AVERROR(EAGAIN)||ret==AVERROR_EOF){
break;
}
if(ret){
char buf[1024]={0};
av_strerror(ret,buf,sizeof(buf)-1);
cerr<<buf<<endl;
return -1;
}
ofs.write((char*)packet->data,packet->size);
av_packet_unref(packet);
}
}
ofs.close();
av_packet_free(&packet);
av_frame_free(&frame);
avcodec_free_context(&c);
//编码
return 0;
}