h文件
#ifndef _AV_H264_H_
#define _AV_H264_H_
#include <opencv2/opencv.hpp>
#define __STDC_CONSTANT_MACROS
#ifdef __cplusplus
extern "C" {
#endif
#include <libavutil/time.h>
#include <libavutil/mathematics.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavdevice/avdevice.h>
#include <libswresample/swresample.h>
#ifdef __cplusplus
};
#endif
#pragma comment(lib,"opencv_world470.lib")
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avdevice.lib")
#pragma comment(lib,"avfilter.lib")
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"postproc.lib")
#pragma comment(lib,"swresample.lib")
#pragma comment(lib,"swscale.lib")
typedef struct AvH264EncConfig_T {
int width = 320;
int height = 240;
int frame_rate = 10;
int64_t bit_rate = 320000;
int gop_size = 250;
int max_b_frames = 0;
}AvH264EncConfig;
class AvH264 {
public:
AvH264();
int open(AvH264EncConfig h264_config);
AVPacket* encode(cv::Mat mat);
void close();
private:
AVCodec* cdc_;
AVCodecContext* cdc_ctx_;
AVFrame* avf_;
AVPacket* avp_;
int frame_size_;
int pts_;
};
#endif
cpp文件
#include "AvH264.h"
AvH264::AvH264() {
cdc_ = NULL;
cdc_ctx_ = NULL;
avf_ = NULL;
avp_ = NULL;
}
int AvH264::open(AvH264EncConfig h264_config) {
pts_ = 0;
cdc_ = (AVCodec*)avcodec_find_encoder(AV_CODEC_ID_H264);
if (!cdc_) {
return -1;
}
cdc_ctx_ = avcodec_alloc_context3(cdc_);
if (!cdc_ctx_) {
return -1;
}
cdc_ctx_->bit_rate = h264_config.bit_rate;
cdc_ctx_->width = h264_config.width;
cdc_ctx_->height = h264_config.height;
cdc_ctx_->time_base = { 1, h264_config.frame_rate };
cdc_ctx_->framerate = { h264_config.frame_rate, 1 };
cdc_ctx_->gop_size = h264_config.gop_size;
cdc_ctx_->max_b_frames = h264_config.max_b_frames;
cdc_ctx_->pix_fmt = AV_PIX_FMT_YUV420P;
cdc_ctx_->codec_id = AV_CODEC_ID_H264;
cdc_ctx_->codec_type = AVMEDIA_TYPE_VIDEO;
//cdc_ctx_->qmin = 10;
//cdc_ctx_->qmax = 51;
//cdc_ctx_->qcompress = 0.6;
AVDictionary* dict = 0;
av_dict_set(&dict, "preset", "slow", 0);
av_dict_set(&dict, "tune", "zerolatency", 0);
av_dict_set(&dict, "profile", "main", 0);
avf_ = av_frame_alloc();
avp_ = av_packet_alloc();
if (!avf_ || !avp_) {
return -1;
}
frame_size_ = cdc_ctx_->width * cdc_ctx_->height;
avf_->format = cdc_ctx_->pix_fmt;
avf_->width = cdc_ctx_->width;
avf_->height = cdc_ctx_->height;
// alloc memory
int r = av_frame_get_buffer(avf_, 0);
if (r < 0) {
return -1;
}
r = av_frame_make_writable(avf_);
if (r < 0) {
return -1;
}
return avcodec_open2(cdc_ctx_, cdc_, &dict);
}
void AvH264::close() {
if (cdc_ctx_) avcodec_free_context(&cdc_ctx_);
if (avf_) av_frame_free(&avf_);
if (avp_) av_packet_free(&avp_);
}
AVPacket* AvH264::encode(cv::Mat mat) {
if (mat.empty()) return NULL;
cv::resize(mat, mat, cv::Size(cdc_ctx_->width, cdc_ctx_->height));
cv::Mat yuv;
cv::cvtColor(mat, yuv, cv::COLOR_BGR2YUV_I420);
unsigned char* pdata = yuv.data;
// fill yuv420
// yyy yyy yyy yyy
// uuu
// vvv
avf_->data[0] = pdata;
avf_->data[1] = pdata + frame_size_;
avf_->data[2] = pdata + frame_size_ * 5 / 4;
avf_->pts = pts_++;
int r = avcodec_send_frame(cdc_ctx_, avf_);
if (r >= 0) {
r = avcodec_receive_packet(cdc_ctx_, avp_);
if (r == 0) {
//avp_->stream_index = 0;
return avp_;
}
if (r == AVERROR(EAGAIN) || r == AVERROR_EOF) {
return NULL;
}
}
return NULL;
}