C/C++ FFmepeg音视频开发录屏摄像机
- 导入FFmepeg库文件:FFmepegSDK可以去官网下载
- mp4_to_mov
- rgb_to_mp4
- pcm_to_aac
- rgb_pcm_to_mp4
- TestDirectx
- qt_audio_input
- XScreen(这个源码文件是以上面做为集合开发出来的软件)
以下为本人学习所做的开发笔记,不喜勿喷,谢谢各位大哥
导入FFmepeg库文件:FFmepegSDK可以去官网下载
mp4_to_mov
extern "C"
{
#include
}
#include
using namespace std;
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avutil.lib")
int main()
{
char infile[] = "test.mp4";
char outfile[] = "test.mov";
av_register_all();
AVFormatContext* ic = NULL;
avformat_open_input(&ic, infile, 0, 0);
if (!ic)
{
cout << "avformat_open_input failed! error" << endl;
getchar();
return -1;
}
cout << "open " << infile << " success!" << endl;
AVFormatContext* oc = NULL;
avformat_alloc_output_context2(&oc, NULL, NULL, outfile);
if (!oc)
{
cerr << "avformat_alloc_output_context2 failed" << outfile << endl;
getchar();
return -1;
}
AVStream *videoStream = avformat_new_stream(oc, NULL);
AVStream* audioStream = avformat_new_stream(oc, NULL);
avcodec_parameters_copy(videoStream->codecpar, ic->streams[0]->codecpar);
avcodec_parameters_copy(audioStream->codecpar, ic->streams[1]->codecpar);
videoStream->codecpar->codec_tag = 0;
audioStream->codecpar->codec_tag = 0;
av_dump_format(ic, 0, infile, 0);
cout << "=============================================" << endl;
av_dump_format(oc, 0, outfile, 1);
int ret = avio_open(&oc->pb, outfile, AVIO_FLAG_WRITE);
if (ret < 0)
{
cerr << "avio open failed!" << endl;
getchar();
return -1;
}
ret = avformat_write_header(oc, NULL);
if (ret < 0)
{
cerr << "avio open header failed!" << endl;
getchar();
return -1;
}
AVPacket pkt;
for (;;)
{
int re = av_read_frame(ic, &pkt);
if (re < 0)
break;
pkt.pts = av_rescale_q_rnd(pkt.pts, ic->streams[pkt.stream_index]->time_base,
oc->streams[pkt.stream_index]->time_base,(AVRounding)(AV_ROUND_INF | AV_ROUND_PASS_MINMAX));
pkt.dts = av_rescale_q_rnd(pkt.dts, ic->streams[pkt.stream_index]->time_base,
oc->streams[pkt.stream_index]->time_base, (AVRounding)(AV_ROUND_INF | AV_ROUND_PASS_MINMAX));
pkt.pos = -1;
pkt.duration= av_rescale_q_rnd(pkt.duration, ic->streams[pkt.stream_index]->time_base,
oc->streams[pkt.stream_index]->time_base, (AVRounding)(AV_ROUND_INF | AV_ROUND_PASS_MINMAX));
av_write_frame(oc, &pkt);
av_packet_unref(&pkt);
cout << ".";
}
av_write_trailer(oc);
avio_close(oc->pb);
cout << "==============endl==================" << endl;
getchar();
return 0;
}
rgb_to_mp4
extern "C"
{
#include
#include
}
#include
using namespace std;
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"swscale.lib")
#pragma warning (disable : 4996)
int main()
{
char infile[] = "out.rgb";
char outfile[] = "rgb.mp4";
av_register_all();
avcodec_register_all();
FILE* fp = fopen(infile, "rb");
if (!fp)
{
cout << infile << "open file failed 文件打开失败" << endl;
getchar();
return -1;
}
int width = 1920;
int height = 1080;
int fps = 25;
AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!codec)
{
cout << "avcodec_find_decoder AV_CODEC_ID_H264 failed" << endl;
getchar();
return -1;
}
AVCodecContext *c = avcodec_alloc_context3(codec);
if (!c)
{
cout << "avcodec_alloc_context3 failed" << endl;
getchar();
return -1;
}
c->bit_rate = 400000000;
c->width = width;
c->height = height;
c->time_base = { 1,fps };
c->framerate = { fps,1 };
c->gop_size = 50;
c->max_b_frames = 0;
c->pix_fmt = AV_PIX_FMT_YUV420P;
c->codec_id = AV_CODEC_ID_H264;
c->thread_count = 8;
c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
int ret = avcodec_open2(c, codec, NULL);
if (ret < 0)
{
cerr << "avcodec_open2 failed" << endl;
getchar();
return -1;
}
cout << "open the success !" << endl;
AVFormatContext* oc = NULL;
avformat_alloc_output_context2(&oc, 0, 0, outfile);
AVStream *st = avformat_new_stream(oc, NULL);
st->id = 0;
st->codecpar->codec_tag = 0;
avcodec_parameters_from_context(st->codecpar, c);
cout << "========================================================" << endl;
av_dump_format(oc, 0, outfile, 1);
cout << "============================end============================" << endl;
SwsContext* ctx = NULL;
ctx = sws_getCachedContext(ctx,width,height,AV_PIX_FMT_BGRA,width,height, AV_PIX_FMT_YUV420P,SWS_BICUBIC,NULL,NULL,NULL);
unsigned char* rgb = new unsigned char[width*height*4];
AVFrame* yuv = av_frame_alloc();
yuv->format = AV_PIX_FMT_YUV420P;
yuv->width = width;
yuv->height = height;
ret = av_frame_get_buffer(yuv, 32);
if (ret < 0)
{
cerr << "avcodec_open2 failed" << endl;
getchar();
return -1;
}
ret = avio_open(&oc->pb, outfile, AVIO_FLAG_WRITE);
if (ret < 0)
{
cerr << "avio_open failed" << endl;
getchar();
return -1;
}
ret = avformat_write_header(oc,NULL);
if (ret < 0)
{
cerr << "avformat_write_header failed" << endl;
getchar();
return -1;
}
int p = 0;
for (;;)
{
int len = fread(rgb, 1, width * height * 4, fp);
if (len <= 0)break;
uint8_t* indata[AV_NUM_DATA_POINTERS] = { 0 };
indata[0] = rgb;
int inlinesize[AV_NUM_DATA_POINTERS] = { 0 };
inlinesize[0] = width * 4;
int h = sws_scale(ctx,indata,inlinesize,0,height,yuv->data,yuv->linesize);
if (h <= 0)
break;
yuv->pts = p;
p += 3600;
ret = avcodec_send_frame(c, yuv);
if (ret != 0)
continue;
AVPacket pkt;
av_init_packet(&pkt);
ret = avcodec_receive_packet(c, &pkt);
if (ret != 0)
continue;
av_interleaved_write_frame(oc, &pkt);
cout << "<"<<pkt.size<<">";
}
av_write_trailer(oc);
avio_close(oc->pb);
avformat_free_context(oc);
avcodec_close(c);
avcodec_free_context(&c);
sws_freeContext(ctx);
cout << "============================end=============================" << endl;
delete rgb;
getchar();
return 0;
}
pcm_to_aac
extern "C"
{
#include
#include
#include
}
#include
using namespace std;
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"swscale.lib")
#pragma comment(lib,"swresample.lib")
#pragma warning (disable : 4996)
int main()
{
char infile[] = "out.pcm";
char outfile[] = "out.aac";
av_register_all();
avcodec_register_all();
AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
if (!codec)
{
cout << "avcodec_find_encoder error" << endl;
getchar();
return -1;
}
AVCodecContext* c = avcodec_alloc_context3(codec);
if (!c)
{
cout << "avcodec_alloc_context3 error" << endl;
getchar();
return -1;
}
c->bit_rate = 64000;
c->sample_rate = 44100;
c->sample_fmt = AV_SAMPLE_FMT_FLTP;
c->channel_layout = AV_CH_LAYOUT_STEREO;
c->channels = 2;
c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
int ret = avcodec_open2(c, codec, NULL);
if (ret < 0)
{
cout << "avcodec_open2 error" << endl;
getchar();
return -1;
}
cout << "avcodec_open2 success!" << endl;
AVFormatContext* oc = NULL;
avformat_alloc_output_context2(&oc, NULL, NULL, outfile);
if (!oc)
{
cout << "avformat_alloc_output_context2 error" << endl;
getchar();
return -1;
}
AVStream* st = avformat_new_stream(oc, NULL);
st->codecpar->codec_tag = 0;
avcodec_parameters_from_context(st->codecpar, c);
av_dump_format(oc, 0, outfile, 1);
ret = avio_open(&oc->pb, outfile, AVIO_FLAG_WRITE);
if (ret < 0)
{
cout << "avio_open error" << endl;
getchar();
return -1;
}
ret = avformat_write_header(oc, NULL);
SwrContext* actx = NULL;
actx = swr_alloc_set_opts(actx,
c->channel_layout, c->sample_fmt, c->sample_rate,
AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, 44100,
0, 0);
if (!actx)
{
cout << "swr_alloc_set_opts error" << endl;
getchar();
return -1;
}
ret = swr_init(actx);
if (ret < 0)
{
cout << "swr_init error" << endl;
getchar();
return -1;
}
AVFrame* frame = av_frame_alloc();
frame->format = AV_SAMPLE_FMT_FLTP;
frame->channels = 2;
frame->channel_layout = AV_CH_LAYOUT_STEREO;
frame->nb_samples = 1024;
ret = av_frame_get_buffer(frame, 0);
if (ret < 0)
{
cout << "av_frame_get_buffer error" << endl;
getchar();
return -1;
}
int readSize = frame->nb_samples * 2 * 2;
char* pcm = new char[readSize];
FILE* fp = fopen(infile, "rb");
for (;;)
{
int len = fread(pcm, 1, readSize, fp);
if (len <= 0)break;
const uint8_t* data[1];
data[0] = (uint8_t*)pcm;
len = swr_convert(actx, frame->data, frame->nb_samples,
data, frame->nb_samples
);
if (len <= 0)
break;
AVPacket pkt;
av_init_packet(&pkt);
ret = avcodec_send_frame(c, frame);
if (ret != 0) continue;
ret = avcodec_receive_packet(c, &pkt);
if (ret != 0) continue;
pkt.stream_index = 0;
pkt.pts = 0;
pkt.dts = 0;
ret = av_interleaved_write_frame(oc, &pkt);
cout << "[" << len << "]";
}
delete pcm;
pcm = NULL;
av_write_trailer(oc);
avio_close(oc->pb);
avformat_free_context(oc);
avcodec_close(c);
avcodec_free_context(&c);
cout << "======================end=========================" << endl;
getchar();
return 0;
}
rgb_pcm_to_mp4
#include "XVideoWriter.h"
#include
using namespace std;
#pragma warning (disable : 4996)
int main()
{
char outfile[] = "rgbpcm.mp4";
char rgbfile[] = "test.rgb";
char pcmfile[] = "test.pcm";
XVideoWriter *xw = XVideoWriter::Get(0);
cout << xw->Init(outfile);
cout << xw->AddVideoStream();
xw->AddAudioStream();
FILE* fp = fopen(rgbfile,"rb");
if (!fp)
{
cout << "fopen " << rgbfile << " failed! " << endl;
getchar();
return -1;
}
FILE* fa = fopen(pcmfile, "rb");
if (!fa)
{
cout << "fopen " << pcmfile << " failed! " << endl;
getchar();
return -1;
}
int size = xw->inWidth*xw->inHeight * 4;
unsigned char* rgb = new unsigned char[size];
int asize = xw->nb_Sample * xw->inChannels * 2;
unsigned char* pcm = new unsigned char[size];
xw->WriteHead();
AVPacket* pkt = NULL;
int len = 0;
for (;;)
{
if (xw->IsVideoDefer())
{
int len = fread(rgb, 1, size, fp);
if (len <= 0)
break;
pkt = xw->EncodeVideo(rgb);
if (pkt) cout << ".";
else
{
cout << "-";
continue;
}
if (xw->WriteFrame(pkt))
{
cout << "+";
}
}
else
{
len = fread(pcm, 1, asize, fa);
if (len <= 0) break;
pkt = xw->EncodeAudio(pcm);
xw->WriteFrame(pkt);
}
}
xw->WriteEnd();
delete rgb;
rgb = NULL;
cout << "\n=============================end============================" << endl;
getchar();
return 0;
}
TestDirectx
#include
#include
#pragma comment (lib,"d3d9.lib")
#pragma warning (disable : 4996)
void CaptureScreen(void *data)
{
static IDirect3D9* d3d = NULL;
if (!d3d)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);
}
if (!d3d) return;
static IDirect3DDevice9* device = NULL;
if (!device)
{
D3DPRESENT_PARAMETERS pa;
ZeroMemory(&pa, sizeof(pa));
pa.Windowed = true;
pa.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
pa.SwapEffect = D3DSWAPEFFECT_DISCARD;
pa.hDeviceWindow = GetDesktopWindow();
d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, 0, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pa, &device);
}
if (!device)return;
int w = GetSystemMetrics(SM_CXSCREEN);
int h = GetSystemMetrics(SM_CYSCREEN);
static IDirect3DSurface9* sur = NULL;
if (!sur)
{
device->CreateOffscreenPlainSurface(w, h, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &sur, 0);
}
if (!sur) return;
device->GetFrontBufferData(0, sur);
D3DLOCKED_RECT rect;
ZeroMemory(&rect, sizeof(rect));
if (sur->LockRect(&rect, 0, 0) != S_OK)
{
return;
}
memcpy(data, rect.pBits, w * h * 4);
sur->UnlockRect();
std::cout << ".";
}
int main()
{
FILE* fp = fopen("out.rgb", "wb");
int size = 1920 * 1080 * 4;
char* buf = new char[size];
for (int i = 0; i < 1000; i++)
{
CaptureScreen(buf);
fwrite(buf, 1, size, fp);
Sleep(100);
}
return 0;
}
qt_audio_input
#include
#include
using namespace std;
int main(int argc, char* argv[])
{
QAudioFormat fmt;
fmt.setSampleRate(44100);
fmt.setChannelCount(2);
fmt.setSampleSize(16);
fmt.setSampleType(QAudioFormat::UnSignedInt);
fmt.setByteOrder(QAudioFormat::LittleEndian);
fmt.setCodec("audio/pcm");
QAudioInput* input = new QAudioInput(fmt);
QIODevice* io = input->start();
FILE* fp = fopen("out.pcm", "wb");
char* buf = new char[1024];
int total = 0;
for (;;)
{
int br = input->bytesReady();
if (br < 1024) continue;
int len = io->read(buf, 1024);
fwrite(buf, 1, len, fp);
cout << len << "|";
total += len;
if (total > 1024 * 1024)
break;
}
fclose(fp);
return 0;
}
XScreen(这个源码文件是以上面做为集合开发出来的软件)
#include "xscreen.h"
#include
#include
#include "XSceenRecord.h"
static bool isRecord = false;
#define RECORDQSS "\
QPushButton:!hover \
{background-image: url(:/XScreen/record_normal.png);}\
QPushButton:hover\
{background-image: url(:/XScreen/record_hot.png);}\
QPushButton:pressed{\
background-image: url(:/XScreen/record_pressed.png);\
background-color: rgba(255, 255, 255, 0);}"
static QTime rtime;
XScreen::XScreen(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);
startTimer(100);
}
void XScreen::timerEvent(QTimerEvent* e)
{
if (isRecord)
{
int es = rtime.elapsed() / 1000;
char buf[1024] = { 0 };
sprintf(buf, "%03d:%02d", es / 60, es % 60);
ui.timelabel->setText(buf);
}
}
void XScreen::Record()
{
isRecord = !isRecord;
std::cout << "Record succeed";
if (isRecord)
{
rtime.restart();
ui.recordButton->setStyleSheet("background-image: url(:/XScreen/stop.png);background-color: rgba(255, 255, 255, 0);");
QDateTime t = QDateTime::currentDateTime();
QString filename = t.toString("yyyyMMdd_hhmmss");
filename = "xcreen_" + filename;
filename += ".mp4";
filename = ui.urlEdit->text() + "\\" + filename;
XSceenRecord::Get()->outWidth = ui.widthEdit->text().toInt();
XSceenRecord::Get()->outHeight = ui.heightEdit_2->text().toInt();
XSceenRecord::Get()->fps = ui.fpsEdit->text().toInt();
if (XSceenRecord::Get()->Start(filename.toLocal8Bit()))
{
return;
}
isRecord = false;
}
{
ui.recordButton->setStyleSheet(RECORDQSS);
XSceenRecord::Get()->Stop();
}
}