108 lines
3.2 KiB
C++
108 lines
3.2 KiB
C++
#include "ffvideo.h"
|
||
|
||
void ffvideo::initH264() {
|
||
AVDictionary* options = nullptr;
|
||
av_dict_set(&options, "preset", "superfast", 0);
|
||
av_dict_set(&options, "tune", "zerolatency", 0);
|
||
AVCodec* encoder = avcodec_find_encoder(AV_CODEC_ID_H264);
|
||
encoder_ctx = avcodec_alloc_context3(encoder);
|
||
encoder_ctx->codec_id = AV_CODEC_ID_H264;
|
||
encoder_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
|
||
encoder_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
|
||
encoder_ctx->width = info.dst_width;
|
||
encoder_ctx->height = info.dst_height;
|
||
encoder_ctx->time_base.num = 1;
|
||
encoder_ctx->time_base.den = info.frame_rate; //时间基
|
||
encoder_ctx->framerate = { info.frame_rate,1 };//帧率
|
||
encoder_ctx->bit_rate = info.bit_rate;//重要,最终视频的码率
|
||
encoder_ctx->gop_size = info.gop_size;//关键帧间隔
|
||
encoder_ctx->qmin = 30;//最小压缩质量
|
||
encoder_ctx->qmax = 35;//最大压缩质量,与最小质量一起控制压缩后的图像质量
|
||
encoder_ctx->max_b_frames = 0;//不输出B帧,输出B帧后的时间戳控制较为繁琐
|
||
encoder_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;//设置后通过extradata获取sps、pps
|
||
avcodec_open2(encoder_ctx, encoder, &options);
|
||
dst_packet = av_packet_alloc();
|
||
}
|
||
|
||
void ffvideo::initSws() {
|
||
line_size = new int[4];
|
||
src_size = av_image_get_buffer_size(info.src_fmt, info.src_width, info.src_height, 1);
|
||
dst_size = av_image_get_buffer_size(info.dst_fmt, info.dst_width, info.dst_height, 1);
|
||
src_buffer = new uint8_t[src_size];
|
||
dst_buffer = new uint8_t[dst_size];
|
||
dst_frame = av_frame_alloc();
|
||
dst_frame->format = info.dst_fmt;
|
||
dst_frame->width = info.dst_width;
|
||
dst_frame->height = info.dst_height;
|
||
av_image_fill_arrays(dst_frame->data, dst_frame->linesize, dst_buffer, info.dst_fmt, info.dst_width, info.dst_height, 1);
|
||
|
||
sws_ctx = sws_getContext(info.src_width, info.src_height, info.src_fmt,
|
||
info.dst_width, info.dst_height, info.dst_fmt,
|
||
SWS_BICUBIC, nullptr, nullptr, nullptr);
|
||
sws_init_context(sws_ctx, nullptr, nullptr);
|
||
}
|
||
|
||
void ffvideo::process_data(int dts, int pts, void(*cb)(ffvideo*)) {
|
||
sws_scale(sws_ctx, static_cast<const uint8_t* const*>(&src_buffer), line_size, 0,
|
||
info.src_height, dst_frame->data, dst_frame->linesize);
|
||
dst_frame->pkt_dts = dts;
|
||
dst_frame->pts = pts;
|
||
|
||
int ret = avcodec_send_frame(encoder_ctx, dst_frame);
|
||
if (ret < 0) {
|
||
if (ret == AVERROR(EAGAIN)) {
|
||
return;
|
||
}
|
||
return;
|
||
}
|
||
while (ret >= 0) {
|
||
ret = avcodec_receive_packet(encoder_ctx, dst_packet);
|
||
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
|
||
break;
|
||
}
|
||
if (ret < 0) {
|
||
return;
|
||
}
|
||
if (cb) cb(this);
|
||
av_packet_unref(dst_packet);
|
||
}
|
||
}
|
||
|
||
//FILE* f = nullptr;
|
||
//
|
||
//void output2(FFplay* ctx) {
|
||
// if (f == nullptr) {
|
||
// f = fopen("a.h264", "wb");
|
||
// fwrite(ctx->encoder_ctx->extradata, sizeof(uint8_t), ctx->encoder_ctx->extradata_size, f);
|
||
// }
|
||
//
|
||
// fwrite(ctx->dst_packet->data, sizeof(uint8_t), ctx->dst_packet->size, f);
|
||
//
|
||
// cout << "ENCODE_SUCCESS: size = " << ctx->dst_packet->size << endl;
|
||
//}
|
||
//
|
||
//int main_test() {
|
||
//
|
||
// FFplay play{};
|
||
//
|
||
// play.info = {
|
||
// 1920, 1080, AV_PIX_FMT_BGRA,
|
||
// 1920, 1080, AV_PIX_FMT_YUV420P,
|
||
// 30, 2 * 1024 * 1024, 30
|
||
// };
|
||
//
|
||
// play.initSws();
|
||
// play.initH264();
|
||
//
|
||
// int count = 0;
|
||
// while (true) {
|
||
// if (count == 10 * 30) break;
|
||
// count++;
|
||
// //fake_data(count);
|
||
// play.process_data(count, count, output2);
|
||
// }
|
||
// fflush(f);
|
||
// fclose(f);
|
||
// return 0;
|
||
//}
|