void VideoEncoder::FillCodecContext(AVCodec* codec) { GetCodecContext()->width = m_width; GetCodecContext()->height = m_height; GetCodecContext()->time_base.num = 1; GetCodecContext()->time_base.den = m_frame_rate; GetCodecContext()->bit_rate = m_bit_rate; GetCodecContext()->pix_fmt = PIX_FMT_YUV420P; GetCodecContext()->sample_aspect_ratio.num = 1; GetCodecContext()->sample_aspect_ratio.den = 1; GetCodecContext()->flags |= CODEC_FLAG_LOOP_FILTER; GetCodecContext()->thread_count = m_opt_threads; if(m_opt_minrate != (unsigned int) -1) GetCodecContext()->rc_min_rate = m_opt_minrate; if(m_opt_maxrate != (unsigned int) -1) GetCodecContext()->rc_max_rate = m_opt_maxrate; if(m_opt_bufsize != (unsigned int) -1) GetCodecContext()->rc_buffer_size = m_opt_bufsize; #if !SSR_USE_AVCODEC_PRIVATE_CRF if(m_opt_crf != (unsigned int) -1) GetCodecContext()->crf = m_opt_crf; #endif #if !SSR_USE_AVCODEC_PRIVATE_PRESET if(m_opt_preset != "") X264Preset(GetCodecContext(), m_opt_preset.toAscii().constData()); #endif }
void VideoEncoder::PrepareStream(AVStream* stream, AVCodec* codec, AVDictionary** options, const std::vector<std::pair<QString, QString> >& codec_options, unsigned int bit_rate, unsigned int width, unsigned int height, unsigned int frame_rate) { if(width == 0 || height == 0) { Logger::LogError("[VideoEncoder::PrepareStream] " + Logger::tr("Error: Width or height is zero!")); throw LibavException(); } if(width > 10000 || height > 10000) { Logger::LogError("[VideoEncoder::PrepareStream] " + Logger::tr("Error: Width or height is too large, the maximum width and height is %1!").arg(10000)); throw LibavException(); } if(width % 2 != 0 || height % 2 != 0) { Logger::LogError("[VideoEncoder::PrepareStream] " + Logger::tr("Error: Width or height is not an even number!")); throw LibavException(); } if(frame_rate == 0) { Logger::LogError("[VideoEncoder::PrepareStream] " + Logger::tr("Error: Frame rate is zero!")); throw LibavException(); } stream->codec->bit_rate = bit_rate; stream->codec->width = width; stream->codec->height = height; stream->codec->time_base.num = 1; stream->codec->time_base.den = frame_rate; #if SSR_USE_AVSTREAM_TIME_BASE stream->time_base = stream->codec->time_base; #endif stream->codec->pix_fmt = AV_PIX_FMT_NONE; for(unsigned int i = 0; i < SUPPORTED_PIXEL_FORMATS.size(); ++i) { if(AVCodecSupportsPixelFormat(codec, SUPPORTED_PIXEL_FORMATS[i].m_format)) { stream->codec->pix_fmt = SUPPORTED_PIXEL_FORMATS[i].m_format; if(SUPPORTED_PIXEL_FORMATS[i].m_is_yuv) { stream->codec->color_primaries = AVCOL_PRI_BT709; stream->codec->color_trc = AVCOL_TRC_BT709; stream->codec->colorspace = AVCOL_SPC_BT709; stream->codec->color_range = AVCOL_RANGE_MPEG; stream->codec->chroma_sample_location = AVCHROMA_LOC_CENTER; } else { stream->codec->colorspace = AVCOL_SPC_RGB; } break; } } if(stream->codec->pix_fmt == AV_PIX_FMT_NONE) { Logger::LogError("[VideoEncoder::PrepareStream] " + Logger::tr("Error: Encoder requires an unsupported pixel format!")); throw LibavException(); } stream->codec->sample_aspect_ratio.num = 1; stream->codec->sample_aspect_ratio.den = 1; stream->sample_aspect_ratio = stream->codec->sample_aspect_ratio; stream->codec->thread_count = std::max(1, (int) std::thread::hardware_concurrency()); for(unsigned int i = 0; i < codec_options.size(); ++i) { const QString &key = codec_options[i].first, &value = codec_options[i].second; if(key == "threads") { stream->codec->thread_count = ParseCodecOptionInt(key, value, 1, 100); } else if(key == "qscale") { stream->codec->flags |= CODEC_FLAG_QSCALE; stream->codec->global_quality = lrint(ParseCodecOptionDouble(key, value, -1.0e6, 1.0e6, FF_QP2LAMBDA)); } else if(key == "minrate") { stream->codec->rc_min_rate = ParseCodecOptionInt(key, value, 1, 1000000, 1024); // kbps } else if(key == "maxrate") { stream->codec->rc_max_rate = ParseCodecOptionInt(key, value, 1, 1000000, 1024); // kbps } else if(key == "bufsize") { stream->codec->rc_buffer_size = ParseCodecOptionInt(key, value, 1, 1000000, 1024); // kbps } else if(key == "keyint") { stream->codec->gop_size = ParseCodecOptionInt(key, value, 1, 1000000); #if !SSR_USE_AVCODEC_PRIVATE_PRESET } else if(key == "crf") { stream->codec->crf = ParseCodecOptionInt(key, value, 0, 51); #endif #if !SSR_USE_AVCODEC_PRIVATE_PRESET } else if(key == "preset") { X264Preset(stream->codec, value.toUtf8().constData()); #endif } else { av_dict_set(options, key.toUtf8().constData(), value.toUtf8().constData(), 0); } } }