DXGI/ffvideo.cpp
2024-09-08 12:21:59 +08:00

108 lines
3.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
//}