mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-03-12 20:27:19 +00:00
FS-8977: Add support for NVENC H264
This commit is contained in:
parent
ad72c7f56c
commit
77f70e002e
@ -326,6 +326,7 @@ typedef struct switch_mm_s {
|
||||
int vbuf;
|
||||
switch_video_profile_t vprofile;
|
||||
switch_video_encode_speed_t vencspd;
|
||||
uint8_t try_hardware_encoder;
|
||||
} switch_mm_t;
|
||||
|
||||
/*! an abstract representation of a file handle (some parameters based on compat with libsndfile) */
|
||||
@ -633,6 +634,7 @@ struct switch_video_codec_settings {
|
||||
uint32_t bandwidth;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
uint8_t try_hardware_encoder;
|
||||
};
|
||||
|
||||
union switch_codec_settings {
|
||||
|
@ -188,6 +188,7 @@ typedef struct h264_codec_context_s {
|
||||
our_h264_nalu_t nalus[MAX_NALUS];
|
||||
enum AVCodecID av_codec_id;
|
||||
uint16_t last_seq; // last received frame->seq
|
||||
int hw_encoder;
|
||||
} h264_codec_context_t;
|
||||
|
||||
static uint8_t ff_input_buffer_padding[FF_INPUT_BUFFER_PADDING_SIZE] = { 0 };
|
||||
@ -815,7 +816,20 @@ static switch_status_t open_encoder(h264_codec_context_t *context, uint32_t widt
|
||||
{
|
||||
int sane = 0;
|
||||
|
||||
if (!context->encoder) context->encoder = avcodec_find_encoder(context->av_codec_id);
|
||||
if (!context->encoder) {
|
||||
if (context->av_codec_id == AV_CODEC_ID_H264) {
|
||||
if (context->codec_settings.video.try_hardware_encoder && (context->encoder = avcodec_find_encoder_by_name("nvenc_h264"))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "NVENC HW CODEC ENABLED\n");
|
||||
context->hw_encoder = 1;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NVENC HW CODEC NOT PRESENT\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (!context->encoder) {
|
||||
context->encoder = avcodec_find_encoder(context->av_codec_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (!context->encoder) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find encoder id: %d\n", context->av_codec_id);
|
||||
@ -891,6 +905,11 @@ static switch_status_t open_encoder(h264_codec_context_t *context, uint32_t widt
|
||||
} else if (context->av_codec_id == AV_CODEC_ID_H264) {
|
||||
context->encoder_ctx->profile = FF_PROFILE_H264_BASELINE;
|
||||
context->encoder_ctx->level = 41;
|
||||
|
||||
if (context->hw_encoder) {
|
||||
av_opt_set(context->encoder_ctx->priv_data, "preset", "llhq", 0);
|
||||
|
||||
} else {
|
||||
av_opt_set(context->encoder_ctx->priv_data, "preset", "veryfast", 0);
|
||||
av_opt_set(context->encoder_ctx->priv_data, "tune", "zerolatency", 0);
|
||||
av_opt_set(context->encoder_ctx->priv_data, "profile", "baseline", 0);
|
||||
@ -909,9 +928,6 @@ static switch_status_t open_encoder(h264_codec_context_t *context, uint32_t widt
|
||||
|
||||
//context->encoder_ctx->refs = 3; // refs=3
|
||||
|
||||
//context->encoder_ctx->trellis = 1; // trellis=1
|
||||
}
|
||||
|
||||
// libx264-medium.ffpreset preset
|
||||
context->encoder_ctx->gop_size = 250; // g=250
|
||||
context->encoder_ctx->keyint_min = 25; // keyint_min=25
|
||||
@ -922,7 +938,8 @@ static switch_status_t open_encoder(h264_codec_context_t *context, uint32_t widt
|
||||
context->encoder_ctx->qmin = 10; // qmin=10
|
||||
context->encoder_ctx->qmax = 51; // qmax=51
|
||||
context->encoder_ctx->max_qdiff = 4; // qdiff=4
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (avcodec_open2(context->encoder_ctx, context->encoder, NULL) < 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not open codec\n");
|
||||
|
@ -282,8 +282,15 @@ static switch_status_t add_stream(MediaStream *mst, AVFormatContext *fc, AVCodec
|
||||
int buffer_bytes = 2097152; /* 2 mb */
|
||||
int fps = 15;
|
||||
|
||||
if (mm->try_hardware_encoder && codec_id == AV_CODEC_ID_H264) {
|
||||
*codec = avcodec_find_encoder_by_name("nvenc_h264");
|
||||
}
|
||||
|
||||
if (!*codec) {
|
||||
/* find the encoder */
|
||||
*codec = avcodec_find_encoder(codec_id);
|
||||
}
|
||||
|
||||
if (!(*codec)) {
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find encoder for '%s'\n", avcodec_get_name(codec_id));
|
||||
return status;
|
||||
|
@ -88,6 +88,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file,
|
||||
fh->mm.ab = 128;
|
||||
fh->mm.vencspd = SWITCH_VIDEO_ENCODE_SPEED_DEFAULT;
|
||||
fh->mm.vprofile = SWITCH_VIDEO_PROFILE_BASELINE;
|
||||
fh->mm.try_hardware_encoder = 1;
|
||||
|
||||
if (*file_path == '{') {
|
||||
char *timeout;
|
||||
@ -168,6 +169,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file,
|
||||
}
|
||||
}
|
||||
|
||||
if ((val = switch_event_get_header(fh->params, "try_hardware_encoder"))) {
|
||||
fh->mm.try_hardware_encoder = switch_true(val);
|
||||
}
|
||||
|
||||
if ((val = switch_event_get_header(fh->params, "fps"))) {
|
||||
float ftmp = atof(val);
|
||||
if (ftmp > 0.0f) {
|
||||
|
@ -1665,6 +1665,7 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t
|
||||
session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].payload_map = switch_core_alloc(session->pool, sizeof(payload_map_t));
|
||||
session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].cur_payload_map = session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].payload_map;
|
||||
session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].cur_payload_map->current = 1;
|
||||
session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].codec_settings.video.try_hardware_encoder = 1;
|
||||
|
||||
switch_channel_set_flag(session->channel, CF_DTLS_OK);
|
||||
|
||||
@ -2657,10 +2658,13 @@ static void switch_core_session_parse_codec_settings(switch_core_session_t *sess
|
||||
break;
|
||||
case SWITCH_MEDIA_TYPE_VIDEO: {
|
||||
uint32_t system_bw = 0;
|
||||
const char *var = NULL, *bwv;
|
||||
|
||||
const char *bwv = switch_channel_get_variable(session->channel, "rtp_video_max_bandwidth");
|
||||
if ((var = switch_channel_get_variable(session->channel, "video_try_hardare_encoder"))) {
|
||||
engine->codec_settings.video.try_hardware_encoder = switch_true(var);
|
||||
}
|
||||
|
||||
if (!bwv) {
|
||||
if (!(bwv = switch_channel_get_variable(session->channel, "rtp_video_max_bandwidth"))) {
|
||||
bwv = switch_channel_get_variable(session->channel, "rtp_video_max_bandwidth_out");
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user