diff --git a/src/media/media_decoder.cpp b/src/media/media_decoder.cpp index e7455c07f6b38bf2b53ebd402e016076e738470a..07f7e3b5fa5ce45ff3564af9b6e6f13b681a20c2 100644 --- a/src/media/media_decoder.cpp +++ b/src/media/media_decoder.cpp @@ -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; } } } diff --git a/src/media/media_encoder.cpp b/src/media/media_encoder.cpp index f2a98af1866cc0dbdc1b616f6d39401b76a627b1..0188bcf3a04e67037101068a26e82330ed106f85 100644 --- a/src/media/media_encoder.cpp +++ b/src/media/media_encoder.cpp @@ -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()); - - 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 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(); - } + 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(); + + 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.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(); } } } diff --git a/src/media/video/accel.cpp b/src/media/video/accel.cpp index fb6f032e211b284832e383c47245a2369af9716d..207984a96f8ea7736c88a4bd1570f42b5bcfaaae 100644 --- a/src/media/video/accel.cpp +++ b/src/media/video/accel.cpp @@ -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) diff --git a/src/media/video/accel.h b/src/media/video/accel.h index 4e344199a1afcc2285448ae0491f06171b6f0af8..b0b3b16b9aec50c4d77d8e57085ab0fa779a4ced 100644 --- a/src/media/video/accel.h +++ b/src/media/video/accel.h @@ -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_; };