accel: cleanup

Change-Id: I3a4a95855d178844d82b2606e4ed48ad3a1a5114
This commit is contained in:
Pierre Lespagnol
2020-02-18 15:17:37 -05:00
parent 753461b0d9
commit d2b316da32
4 changed files with 109 additions and 115 deletions

View File

@ -282,31 +282,29 @@ MediaDecoder::setupStream()
if (enableAccel_) {
auto APIs = video::HardwareAccel::getCompatibleAccel(decoderCtx_->codec_id,
decoderCtx_->width, decoderCtx_->height, CODEC_DECODER);
if (!APIs.empty()) {
for (const auto& it : APIs) {
accel_ = std::make_unique<video::HardwareAccel>(it); // save accel
auto ret = accel_->initAPI(false, nullptr);
if (ret < 0) {
accel_ = nullptr;
continue;
}
if(prepareDecoderContext() < 0)
return -1; // failed
accel_->setDetails(decoderCtx_);
decoderCtx_->opaque = accel_.get();
decoderCtx_->pix_fmt = accel_->getFormat();
if (avcodec_open2(decoderCtx_, inputDecoder_, &options_) < 0) {
// Failed to open codec
JAMI_WARN("Fail to open hardware decoder for %s with %s ", avcodec_get_name(decoderCtx_->codec_id), it.getName().c_str());
avcodec_free_context(&decoderCtx_);
decoderCtx_ = nullptr;
accel_.reset();
continue;
} else {
// Succeed to open codec
JAMI_WARN("Using hardware decoding for %s with %s ", avcodec_get_name(decoderCtx_->codec_id), it.getName().c_str());
break;
}
for (const auto& it : APIs) {
accel_ = std::make_unique<video::HardwareAccel>(it); // save accel
auto ret = accel_->initAPI(false, nullptr);
if (ret < 0) {
accel_ = nullptr;
continue;
}
if(prepareDecoderContext() < 0)
return -1; // failed
accel_->setDetails(decoderCtx_);
decoderCtx_->opaque = accel_.get();
decoderCtx_->pix_fmt = accel_->getFormat();
if (avcodec_open2(decoderCtx_, inputDecoder_, &options_) < 0) {
// Failed to open codec
JAMI_WARN("Fail to open hardware decoder for %s with %s ", avcodec_get_name(decoderCtx_->codec_id), it.getName().c_str());
avcodec_free_context(&decoderCtx_);
decoderCtx_ = nullptr;
accel_.reset();
continue;
} else {
// Succeed to open codec
JAMI_WARN("Using hardware decoding for %s with %s ", avcodec_get_name(decoderCtx_->codec_id), it.getName().c_str());
break;
}
}
}

View File

@ -210,41 +210,38 @@ MediaEncoder::initStream(const SystemCodecInfo& systemCodecInfo, AVBufferRef* fr
if (enableAccel_ && mediaType == AVMEDIA_TYPE_VIDEO) {
auto APIs = video::HardwareAccel::getCompatibleAccel(static_cast<AVCodecID>(systemCodecInfo.avcodecId),
videoOpts_.width, videoOpts_.height, CODEC_ENCODER);
if (APIs.size() > 0) {
for (const auto& it : APIs) {
accel_ = std::make_unique<video::HardwareAccel>(it); // save accel
// Init codec need accel_ to init encoderCtx accelerated
encoderCtx = initCodec(mediaType, static_cast<AVCodecID>(systemCodecInfo.avcodecId), SystemCodecInfo::DEFAULT_VIDEO_BITRATE);
encoderCtx->opaque = accel_.get();
// Check if pixel format from encoder match pixel format from decoder frame context
// if it mismatch, it means that we are using two different hardware API (nvenc and vaapi for example)
// in this case we don't want link the APIs
if (framesCtx) {
auto hw = reinterpret_cast<AVHWFramesContext*>(framesCtx->data);
if (encoderCtx->pix_fmt != hw->format)
linkableHW_ = false;
}
auto ret = accel_->initAPI(linkableHW_, framesCtx);
if (ret < 0) {
accel_.reset();
encoderCtx = nullptr;
continue;
}
accel_->setDetails(encoderCtx);
if (avcodec_open2(encoderCtx, outputCodec_, &options_) < 0) {
// Failed to open codec
JAMI_WARN("Fail to open hardware encoder %s with %s ", avcodec_get_name(static_cast<AVCodecID>(systemCodecInfo.avcodecId)), it.getName().c_str());
avcodec_free_context(&encoderCtx);
encoderCtx = nullptr;
accel_ = nullptr;
continue;
} else {
// Succeed to open codec
JAMI_WARN("Using hardware encoding for %s with %s ", avcodec_get_name(static_cast<AVCodecID>(systemCodecInfo.avcodecId)), it.getName().c_str());
encoders_.push_back(encoderCtx);
break;
}
for (const auto& it : APIs) {
accel_ = std::make_unique<video::HardwareAccel>(it); // save accel
// Init codec need accel_ to init encoderCtx accelerated
encoderCtx = initCodec(mediaType, static_cast<AVCodecID>(systemCodecInfo.avcodecId), SystemCodecInfo::DEFAULT_VIDEO_BITRATE);
encoderCtx->opaque = accel_.get();
// Check if pixel format from encoder match pixel format from decoder frame context
// if it mismatch, it means that we are using two different hardware API (nvenc and vaapi for example)
// in this case we don't want link the APIs
if (framesCtx) {
auto hw = reinterpret_cast<AVHWFramesContext*>(framesCtx->data);
if (encoderCtx->pix_fmt != hw->format)
linkableHW_ = false;
}
auto ret = accel_->initAPI(linkableHW_, framesCtx);
if (ret < 0) {
accel_.reset();
encoderCtx = nullptr;
continue;
}
accel_->setDetails(encoderCtx);
if (avcodec_open2(encoderCtx, outputCodec_, &options_) < 0) {
// Failed to open codec
JAMI_WARN("Fail to open hardware encoder %s with %s ", avcodec_get_name(static_cast<AVCodecID>(systemCodecInfo.avcodecId)), it.getName().c_str());
avcodec_free_context(&encoderCtx);
encoderCtx = nullptr;
accel_ = nullptr;
continue;
} else {
// Succeed to open codec
JAMI_WARN("Using hardware encoding for %s with %s ", avcodec_get_name(static_cast<AVCodecID>(systemCodecInfo.avcodecId)), it.getName().c_str());
encoders_.push_back(encoderCtx);
break;
}
}
}
@ -990,51 +987,50 @@ MediaEncoder::testH265Accel()
std::unique_ptr<video::HardwareAccel> accel;
if (APIs.size() > 0) {
for (const auto& it : APIs) {
accel = std::make_unique<video::HardwareAccel>(it); // save accel
// Init codec need accel to init encoderCtx accelerated
auto outputCodec = avcodec_find_encoder_by_name(accel->getCodecName().c_str());
for (const auto& it : APIs) {
accel = std::make_unique<video::HardwareAccel>(it); // save accel
// Init codec need accel to init encoderCtx accelerated
auto outputCodec = avcodec_find_encoder_by_name(accel->getCodecName().c_str());
AVCodecContext* encoderCtx = avcodec_alloc_context3(outputCodec);
encoderCtx->thread_count = std::min(std::thread::hardware_concurrency(), 16u);
encoderCtx->width = 1280;
encoderCtx->height = 720;
AVRational framerate;
framerate.num = 30;
framerate.den = 1;
encoderCtx->time_base = av_inv_q(framerate);
encoderCtx->pix_fmt = accel->getFormat();
encoderCtx->profile = FF_PROFILE_HEVC_MAIN;
encoderCtx->opaque = accel.get();
AVCodecContext* encoderCtx = avcodec_alloc_context3(outputCodec);
encoderCtx->thread_count = std::min(std::thread::hardware_concurrency(), 16u);
encoderCtx->width = 1280;
encoderCtx->height = 720;
AVRational framerate;
framerate.num = 30;
framerate.den = 1;
encoderCtx->time_base = av_inv_q(framerate);
encoderCtx->pix_fmt = accel->getFormat();
encoderCtx->profile = FF_PROFILE_HEVC_MAIN;
encoderCtx->opaque = accel.get();
auto br = SystemCodecInfo::DEFAULT_VIDEO_BITRATE;
av_opt_set_int(encoderCtx, "b", br * 1000, AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(encoderCtx, "maxrate", br * 1000, AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(encoderCtx, "minrate", br * 1000, AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(encoderCtx, "bufsize", br * 500, AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(encoderCtx, "crf", -1, AV_OPT_SEARCH_CHILDREN);
auto br = SystemCodecInfo::DEFAULT_VIDEO_BITRATE;
av_opt_set_int(encoderCtx, "b", br * 1000, AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(encoderCtx, "maxrate", br * 1000, AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(encoderCtx, "minrate", br * 1000, AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(encoderCtx, "bufsize", br * 500, AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(encoderCtx, "crf", -1, AV_OPT_SEARCH_CHILDREN);
auto ret = accel->initAPI(false, nullptr);
if (ret < 0) {
accel = nullptr;
encoderCtx = nullptr;
continue;
}
accel->setDetails(encoderCtx);
if (avcodec_open2(encoderCtx, outputCodec, nullptr) < 0) {
// Failed to open codec
avcodec_free_context(&encoderCtx);
encoderCtx = nullptr;
accel = nullptr;
continue;
} else {
// Succeed to open codec
avcodec_free_context(&encoderCtx);
encoderCtx = nullptr;
accel = nullptr;
return it.getName();
}
auto ret = accel->initAPI(false, nullptr);
if (ret < 0) {
accel.reset();;
encoderCtx = nullptr;
continue;
}
accel->setDetails(encoderCtx);
if (avcodec_open2(encoderCtx, outputCodec, nullptr) < 0) {
// Failed to open codec
JAMI_WARN("Fail to open hardware encoder H265 with %s ", it.getName().c_str());
avcodec_free_context(&encoderCtx);
encoderCtx = nullptr;
accel = nullptr;
continue;
} else {
// Succeed to open codec
avcodec_free_context(&encoderCtx);
encoderCtx = nullptr;
accel = nullptr;
return it.getName();
}
}
}

View File

@ -94,7 +94,7 @@ getFormatCb(AVCodecContext* codecCtx, const AVPixelFormat* formats)
}
int
HardwareAccel::test_device(const char* name,
HardwareAccel::init_device(const char* name,
const char* device, int flags)
{
const AVHWDeviceContext* dev = nullptr;
@ -121,7 +121,7 @@ HardwareAccel::test_device(const char* name,
}
int
HardwareAccel::test_device_type(std::string& dev)
HardwareAccel::init_device_type(std::string& dev)
{
AVHWDeviceType check;
const char* name;
@ -142,28 +142,28 @@ HardwareAccel::test_device_type(std::string& dev)
JAMI_WARN("-- Starting %s test for %s with default device.", (type_ == CODEC_ENCODER) ? "encoding" : "decoding", name);
if (name_ == "qsv")
err = test_device(name, "auto", 0);
err = init_device(name, "auto", 0);
else
err = test_device(name, nullptr, 0);
err = init_device(name, nullptr, 0);
if (err == 0) {
JAMI_DBG("-- Test passed for %s with default device.", name);
JAMI_DBG("-- Init passed for %s with default device.", name);
dev = "default";
return 0;
} else {
JAMI_DBG("-- Test failed for %s with default device.", name);
JAMI_DBG("-- Init failed for %s with default device.", name);
}
for (const auto& device : possible_devices_) {
JAMI_WARN("-- Starting %s test for %s with device %s.", (type_ == CODEC_ENCODER) ? "encoding" : "decoding", name, device.c_str());
err = test_device(name, device.c_str(), 0);
JAMI_WARN("-- Init %s for %s with device %s.", (type_ == CODEC_ENCODER) ? "encoding" : "decoding", name, device.c_str());
err = init_device(name, device.c_str(), 0);
if (err == 0) {
JAMI_DBG("-- Test passed for %s with device %s.",
JAMI_DBG("-- Init passed for %s with device %s.",
name, device.c_str());
dev = device;
return 0;
}
else {
JAMI_DBG("-- Test failed for %s with device %s.",
JAMI_DBG("-- Init failed for %s with device %s.",
name, device.c_str());
}
}
@ -329,7 +329,7 @@ HardwareAccel::initAPI(bool linkable, AVBufferRef* framesCtx)
{
const auto& codecName = getCodecName();
std::string device;
auto ret = test_device_type(device);
auto ret = init_device_type(device);
if(ret == 0) {
bool link = false;
if (linkable && framesCtx)

View File

@ -158,8 +158,8 @@ private:
AVBufferRef* deviceCtx_ {nullptr};
AVBufferRef* framesCtx_ {nullptr};
int test_device(const char* name, const char* device, int flags);
int test_device_type(std::string& dev);
int init_device(const char* name, const char* device, int flags);
int init_device_type(std::string& dev);
std::set<std::string> possible_devices_;
};