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