summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorAlfred E. Heggestad <alfred.heggestad@gmail.com>2016-11-30 11:38:11 +0100
committerGitHub <noreply@github.com>2016-11-30 11:38:11 +0100
commit669f0471f1a735964457e6ab4fcf282d446ea4fa (patch)
treee29dcd00ce1011aa18c0285a2aa01886ca26464f /modules
parent5c8629c2ccd0d23efdfe40ca03bcf6127e8afd90 (diff)
Avcodec h264enc (#181)
* avcodec: add option to specify H.264 encoder https://github.com/alfredh/baresip/pull/158 refs #158 Thanks to @hargut for the original patch and idea * avcodec: fix build for older versions of ffmpeg
Diffstat (limited to 'modules')
-rw-r--r--modules/avcodec/avcodec.c16
-rw-r--r--modules/avcodec/avcodec.h1
-rw-r--r--modules/avcodec/encode.c61
3 files changed, 78 insertions, 0 deletions
diff --git a/modules/avcodec/avcodec.c b/modules/avcodec/avcodec.c
index 25a20cb..8894c92 100644
--- a/modules/avcodec/avcodec.c
+++ b/modules/avcodec/avcodec.c
@@ -42,6 +42,7 @@
const uint8_t h264_level_idc = 0x0c;
+AVCodec *avcodec_h264enc; /* optinal; specified H.264 encoder */
int avcodec_resolve_codecid(const char *s)
@@ -175,6 +176,8 @@ static struct vidcodec mpg4 = {
static int module_init(void)
{
+ char h264enc[64];
+
#ifdef USE_X264
debug("avcodec: x264 build %d\n", X264_BUILD);
#else
@@ -196,6 +199,19 @@ static int module_init(void)
if (avcodec_find_decoder(AV_CODEC_ID_MPEG4))
vidcodec_register(&mpg4);
+ if (0 == conf_get_str(conf_cur(), "avcodec_h264enc",
+ h264enc, sizeof(h264enc))) {
+
+ info("avcodec: using h264 encoder by name (%s)\n", h264enc);
+
+ avcodec_h264enc = avcodec_find_encoder_by_name(h264enc);
+ if (!avcodec_h264enc) {
+ warning("avcodec: h264 encoder not found (%s)\n",
+ h264enc);
+ return ENOENT;
+ }
+ }
+
return 0;
}
diff --git a/modules/avcodec/avcodec.h b/modules/avcodec/avcodec.h
index 9a0f132..601a402 100644
--- a/modules/avcodec/avcodec.h
+++ b/modules/avcodec/avcodec.h
@@ -17,6 +17,7 @@
extern const uint8_t h264_level_idc;
+extern AVCodec *avcodec_h264enc;
/*
diff --git a/modules/avcodec/encode.c b/modules/avcodec/encode.c
index bc1dc45..9a7b1c2 100644
--- a/modules/avcodec/encode.c
+++ b/modules/avcodec/encode.c
@@ -8,6 +8,11 @@
#include <baresip.h>
#include <libavcodec/avcodec.h>
#include <libavutil/mem.h>
+#if LIBAVUTIL_VERSION_INT >= ((50<<16)+(29<<8)+0)
+#include <libavutil/opt.h>
+#else
+#include <libavcodec/opt.h>
+#endif
#ifdef USE_X264
#include <x264.h>
#endif
@@ -83,6 +88,9 @@ static void destructor(void *arg)
if (st->ctx) {
if (st->ctx->codec)
avcodec_close(st->ctx);
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(8<<8)+0)
+ av_opt_free(st->ctx);
+#endif
av_free(st->ctx);
}
@@ -133,6 +141,23 @@ static int decode_sdpparam_h263(struct videnc_state *st, const struct pl *name,
static int init_encoder(struct videnc_state *st)
{
+ /*
+ * Special handling of H.264 encoder
+ */
+ if (st->codec_id == AV_CODEC_ID_H264 && avcodec_h264enc) {
+
+#ifdef USE_X264
+ warning("avcodec: h264enc specified, but using libx264\n");
+ return EINVAL;
+#else
+ st->codec = avcodec_h264enc;
+
+ info("avcodec: h264 encoder activated\n");
+
+ return 0;
+#endif
+ }
+
st->codec = avcodec_find_encoder(st->codec_id);
if (!st->codec)
return ENOENT;
@@ -151,6 +176,9 @@ static int open_encoder(struct videnc_state *st,
if (st->ctx) {
if (st->ctx->codec)
avcodec_close(st->ctx);
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(8<<8)+0)
+ av_opt_free(st->ctx);
+#endif
av_free(st->ctx);
}
@@ -174,6 +202,8 @@ static int open_encoder(struct videnc_state *st,
goto out;
}
+ av_opt_set_defaults(st->ctx);
+
st->ctx->bit_rate = prm->bitrate;
st->ctx->width = size->w;
st->ctx->height = size->h;
@@ -188,6 +218,34 @@ static int open_encoder(struct videnc_state *st,
st->ctx->qmin = 10;
st->ctx->qmax = 51;
st->ctx->max_qdiff = 4;
+
+#ifndef USE_X264
+ if (st->codec == avcodec_find_encoder_by_name("nvenc_h264")) {
+
+ err = av_opt_set(st->ctx->priv_data,
+ "preset", "llhp", 0);
+
+ if (err < 0) {
+ debug("avcodec: nvenc_h264 setting preset "
+ "\"llhp\" failed; error: %u\n", err);
+ }
+ else {
+ debug("avcodec: nvenc_h264 preset "
+ "\"llhp\" selected\n");
+ }
+ err = av_opt_set_int(st->ctx->priv_data,
+ "2pass", 1, 0);
+
+ if (err < 0) {
+ debug("avcodec: nvenc_h264 option "
+ "\"2pass\" failed; error: %u\n", err);
+ }
+ else {
+ debug("avcodec: nvenc_h264 option "
+ "\"2pass\" selected\n");
+ }
+ }
+#endif
}
#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)
@@ -213,6 +271,9 @@ static int open_encoder(struct videnc_state *st,
if (st->ctx) {
if (st->ctx->codec)
avcodec_close(st->ctx);
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(8<<8)+0)
+ av_opt_free(st->ctx);
+#endif
av_free(st->ctx);
st->ctx = NULL;
}