diff --git a/src/recording/encoders/encoder.cpp.orig b/src/recording/encoders/encoder.cpp.orig deleted file mode 100644 index 481ba40..0000000 --- a/src/recording/encoders/encoder.cpp.orig +++ /dev/null @@ -1,171 +0,0 @@ -#include "encoder.hpp" - -#include -extern "C" { -#include -#include -} - -inline void throwAVErr(int ret, std::string section) { - char err[AV_ERROR_MAX_STRING_SIZE]; - av_make_error_string(err, AV_ERROR_MAX_STRING_SIZE, ret); - std::string newString(err); - throw std::runtime_error("Error during: " + section + ": " + newString); -} - -#define OR_DEF(s, e1, e2) s ? s->e1 : e2 - -Encoder::Encoder(QString &targetFile, QSize res, CodecSettings *settings) { - int ret; - // Format - ret = avformat_alloc_output_context2(&fc, NULL, NULL, targetFile.toLocal8Bit().constData()); - if (ret < 0) throwAVErr(ret, "format alloc"); - - // Stream - out->st = avformat_new_stream(fc, NULL); - if (!out->st) throw std::runtime_error("Unable to allocate video context"); - out->st->id = fc->nb_streams - 1; - if (fc->oformat->flags & AVFMT_GLOBALHEADER) fc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; - av_dump_format(fc, 0, targetFile.toLocal8Bit().constData(), 1); - - // Codec - if (!fc->oformat->video_codec) throw std::runtime_error("Video codec not found"); - codec = avcodec_find_encoder(fc->oformat->video_codec); - if (!codec) throw std::runtime_error("Video codec not found"); - out->enc = avcodec_alloc_context3(codec); - if (!out->enc) throw std::runtime_error("Unable to allocate video context"); - - int fps = settings::settings().value("recording/framerate", 30).toInt(); - - out->enc->codec_id = codec->id; - out->enc->codec = codec; - - out->enc->bit_rate = OR_DEF(settings, bitrate, 400000); - out->enc->width = res.width() % 2 ? res.width() - 1 : res.width(); - out->enc->height = res.height() % 2 ? res.height() - 1 : res.height(); - size = QSize(out->enc->width, out->enc->height); - out->st->time_base = { 1, fps }; - out->enc->time_base = out->st->time_base; - - out->enc->gop_size = OR_DEF(settings, gopSize, 12); - out->enc->pix_fmt = AV_PIX_FMT_YUV420P; // blaze it - AVDictionary *dict = NULL; - if (out->enc->codec_id == AV_CODEC_ID_GIF) - out->enc->pix_fmt = AV_PIX_FMT_RGB8; - else if (out->enc->codec_id == AV_CODEC_ID_H264 || out->enc->codec_id == AV_CODEC_ID_H265) { - av_dict_set(&dict, "preset", settings ? settings->h264Profile.toLocal8Bit().constData() : "medium", 0); - av_dict_set_int(&dict, "crf", OR_DEF(settings, h264Crf, 12), 0); - } else if (out->enc->codec_id == AV_CODEC_ID_VP8 || out->enc->codec_id == AV_CODEC_ID_VP9) - av_dict_set_int(&dict, "lossless", OR_DEF(settings, vp9Lossless, false), 0); - - - ret = avcodec_open2(out->enc, codec, &dict); - av_dict_free(&dict); - if (ret < 0) throwAVErr(ret, "codec open"); - if (codec->capabilities & AV_CODEC_CAP_DR1) avcodec_align_dimensions(out->enc, &out->enc->width, &out->enc->height); - - ret = avcodec_parameters_from_context(out->st->codecpar, out->enc); - if (ret < 0) throwAVErr(ret, "stream opt copy"); - - // Frames - out->frame = av_frame_alloc(); - if (!out->frame) { - throw std::runtime_error("frame alloc"); - } - out->frame->format = out->enc->pix_fmt; - out->frame->width = out->enc->width; - out->frame->height = out->enc->height; - ret = av_frame_get_buffer(out->frame, 32); - if (ret < 0) throwAVErr(ret, "frame buffer alloc"); - - // Writer - ret = avio_open(&fc->pb, targetFile.toLocal8Bit().constData(), AVIO_FLAG_WRITE); - if (ret < 0) throwAVErr(ret, "writer open"); - ret = avformat_write_header(fc, NULL); - if (ret < 0) throwAVErr(ret, "write header"); - - success = true; -} - -void Encoder::setFrameRGB(QImage img) { - uint8_t *rgb = (uint8_t *)img.bits(); - int ret = av_frame_make_writable(out->frame); - if (ret < 0) throwAVErr(ret, "setFrameRGB"); - int lineSize[1] = { img.bytesPerLine() }; - out->sws = sws_getCachedContext(out->sws, out->enc->width, out->enc->height, AV_PIX_FMT_RGB24, out->enc->width, - out->enc->height, (AVPixelFormat)out->frame->format, 0, 0, 0, 0); - sws_scale(out->sws, (const uint8_t *const *)&rgb, lineSize, 0, out->enc->height, out->frame->data, out->frame->linesize); - out->frame->pts = out->nextPts++; -} - -Encoder::~Encoder() { - end(); -} - -bool Encoder::addFrame(QImage frm) { - if (!success) return false; - if (frm.size() != size) frm = frm.copy(QRect(QPoint(0, 0), size)); - if (frm.format() != QImage::Format_RGB888) frm = frm.convertToFormat(QImage::Format_RGB888); - setFrameRGB(frm); - AVPacket pkt; - pkt.size = 0; - pkt.data = NULL; - av_init_packet(&pkt); - int ret = avcodec_send_frame(out->enc, out->frame); - if (ret == AVERROR(EAGAIN)) { - do { - ret = avcodec_receive_packet(out->enc, &pkt); - if (ret < 0) { - if (ret != AVERROR(EAGAIN)) - throwAVErr(ret, "receive packet"); - else - break; - } - av_packet_rescale_ts(&pkt, out->enc->time_base, out->st->time_base); - pkt.stream_index = out->st->index; - ret = av_interleaved_write_frame(fc, &pkt); - } while (ret >= 0); - if (ret < 0 && ret != AVERROR(EAGAIN)) { - av_packet_unref(&pkt); - throwAVErr(ret, "send frame"); - } - } - av_packet_unref(&pkt); - if (ret < 0 && ret != AVERROR(EAGAIN)) throwAVErr(ret, "send frame"); - return true; -} - -bool Encoder::isRunning() { - return success; -} - -bool Encoder::end() { - if (ended) return false; - ended = true; - if (!success) { - goto cleanup; - } - avcodec_send_frame(out->enc, NULL); - int ret; - AVPacket pkt; - pkt.size = 0; - pkt.data = NULL; - av_init_packet(&pkt); - do { - ret = avcodec_receive_packet(out->enc, &pkt); - if (ret < 0) break; - av_packet_rescale_ts(&pkt, out->enc->time_base, out->st->time_base); - pkt.stream_index = out->st->index; - av_interleaved_write_frame(fc, &pkt); - } while (ret >= 0); - av_write_trailer(fc); -cleanup: - avcodec_free_context(&out->enc); - av_frame_free(&out->frame); - sws_freeContext(out->sws); - delete out; - if (!(fc->oformat->flags & AVFMT_NOFILE)) // - avio_closep(&fc->pb); - avformat_free_context(fc); - return success; -}