[vlc-commits] x265 encoder

Rafaël Carré git at videolan.org
Tue Sep 17 18:29:17 CEST 2013


vlc | branch: master | Rafaël Carré <funman at videolan.org> | Tue Sep 17 18:25:55 2013 +0200| [f1d6824164a1b33c3befc8ad7e16aa94f866ee04] | committer: Rafaël Carré

x265 encoder

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=f1d6824164a1b33c3befc8ad7e16aa94f866ee04
---

 NEWS                      |    1 +
 configure.ac              |   18 ++++
 modules/LIST              |    1 +
 modules/codec/Makefile.am |    8 ++
 modules/codec/x265.c      |  227 +++++++++++++++++++++++++++++++++++++++++++++
 po/POTFILES.in            |    1 +
 6 files changed, 256 insertions(+)

diff --git a/NEWS b/NEWS
index 0d9f313..9c2f51f 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,7 @@ Decoders:
 
 Encoder:
  * Support for MPEG-2 encoding using x262
+ * Support for HEVC/H.265 encoding using x265
 
 Streaming:
  * WebM streaming, including live sources, compatible with all major browsers
diff --git a/configure.ac b/configure.ac
index 5075f07..6a058a0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2755,6 +2755,24 @@ AC_ARG_WITH(x262-tree,
   fi
 fi
 
+dnl x265 encoder
+AC_ARG_ENABLE(x265,
+  AS_HELP_STRING([--enable-x265],[H265 / HEVC encoding support with libx265 (default enabled)]))
+AS_IF( [test "${enable_x265}" != "no"],[
+  AC_CHECK_HEADER([x265.h], [
+      AC_CHECK_LIB([x265],[x265_encoder_open], [
+        VLC_ADD_PLUGIN([x265])
+        VLC_ADD_LIBS([x265], [-lx265 -lstdc++ -lm -lpthread])
+      ], [
+        AC_MSG_ERROR([x265 library not found])
+      ], [-lstdc++ -lm -lpthread])
+  ], [
+    AS_IF([test "${enable_x265}" = "yes"], [
+        AC_MSG_ERROR([x265.h not found])
+    ])
+  ])
+])
+
 
 dnl
 dnl H264 encoder plugin (10-bit lib264)
diff --git a/modules/LIST b/modules/LIST
index 53da53e..45a7ad0 100644
--- a/modules/LIST
+++ b/modules/LIST
@@ -395,6 +395,7 @@ $Id$
  * x262: MPEG-2 video encoder using x262
  * x26410b: H264 10 bit video encoder using x264
  * x264: H264 video encoder using x264
+ * x265: H265 video encoder using x265
  * xa: XA demuxer
  * xcb_apps: List the application windows using XCB
  * xcb_glx: a opengl provider using XCB OpenGL
diff --git a/modules/codec/Makefile.am b/modules/codec/Makefile.am
index b11d7de..7616909 100644
--- a/modules/codec/Makefile.am
+++ b/modules/codec/Makefile.am
@@ -342,6 +342,14 @@ endif
 
 ### X26x encoders ###
 
+libx265_plugin_la_SOURCES = codec/x265.c
+libx265_plugin_la_CPPFLAGS = $(AM_CPPFLAGS)
+libx265_plugin_la_CFLAGS = $(AM_CFLAGS) $(CFLAGS_x265)
+libx265_plugin_la_LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_x265) -rpath '$(codecdir)'
+libx265_plugin_la_LIBADD = $(LIBS_x265)
+EXTRA_LTLIBRARIES += libx265_plugin.la
+codec_LTLIBRARIES += $(LTLIBx265)
+
 libx262_plugin_la_SOURCES = codec/x264.c
 libx262_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DMODULE_NAME_IS_x262
 libx262_plugin_la_CFLAGS = $(AM_CFLAGS) $(CFLAGS_x262)
diff --git a/modules/codec/x265.c b/modules/codec/x265.c
new file mode 100644
index 0000000..8a8305f
--- /dev/null
+++ b/modules/codec/x265.c
@@ -0,0 +1,227 @@
+/*****************************************************************************
+ * x265.c: HEVC/H.265 video encoder
+ *****************************************************************************
+ * Copyright (C) 2013 Rafaël Carré
+ *
+ * Authors: Rafaël Carré <funman at videolanorg>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_threads.h>
+#include <vlc_sout.h>
+#include <vlc_codec.h>
+
+#include <x265.h>
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+static int  Open (vlc_object_t *);
+static void Close(vlc_object_t *);
+
+vlc_module_begin ()
+    set_description(N_("H.265/HEVC encoder (x265)"))
+    set_capability("encoder", 200)
+    set_callbacks(Open, Close)
+    set_category(CAT_INPUT)
+    set_subcategory(SUBCAT_INPUT_VCODEC)
+vlc_module_end ()
+
+struct encoder_sys_t
+{
+    x265_t          *h;
+    x265_param_t    param;
+
+    bool            write_headers;
+
+    mtime_t         i_initial_delay;
+
+    mtime_t         dts;
+    mtime_t         initial_date;
+#ifndef NDEBUG
+    mtime_t         start;
+#endif
+};
+
+static block_t *Encode(encoder_t *p_enc, picture_t *p_pict)
+{
+    encoder_sys_t *p_sys = p_enc->p_sys;
+    x265_picture_t pic;
+
+    if (likely(p_pict)) {
+        if (unlikely(p_sys->initial_date == 0)) {
+            p_sys->initial_date = p_pict->date;
+#ifndef NDEBUG
+            p_sys->start = mdate();
+#endif
+        }
+
+        for (int i = 0; i < p_pict->i_planes; i++) {
+            pic.planes[i] = p_pict->p[i].p_pixels;
+            pic.stride[i] = p_pict->p[i].i_pitch;
+        }
+    }
+
+    x265_nal_t *nal;
+    int i_nal = 0;
+    x265_encoder_encode(p_sys->h, &nal, &i_nal,
+            likely(p_pict) ? &pic : NULL, &pic);
+
+    if (!i_nal)
+        return NULL;
+
+    int i_out = 0;
+    for (int i = 0; i < i_nal; i++)
+        i_out += nal[i].i_payload;
+
+    int i_extra = 0;
+    if (unlikely(p_sys->write_headers)) {
+        i_extra = p_enc->fmt_out.i_extra;
+        p_sys->write_headers = false;
+    }
+
+    block_t *p_block = block_Alloc(i_extra + i_out);
+    if (!p_block)
+        return NULL;
+
+    if (unlikely(i_extra))
+       memcpy(p_block->p_buffer, p_enc->fmt_out.p_extra, i_extra);
+
+    /* all payloads are sequentially laid out in memory */
+    memcpy(p_block->p_buffer + i_extra, nal[0].p_payload, i_out);
+
+    /* This isn't really valid for streams with B-frames */
+    p_block->i_length = CLOCK_FREQ *
+        p_enc->fmt_in.video.i_frame_rate_base /
+            p_enc->fmt_in.video.i_frame_rate;
+
+    p_block->i_pts = p_sys->initial_date + pic.poc * p_block->i_length;
+    p_block->i_dts = p_sys->initial_date + p_sys->dts++ * p_block->i_length;
+
+#ifndef NDEBUG
+    msg_Dbg(p_enc, "%zu bytes (frame %"PRId64", %.2ffps)", p_block->i_buffer,
+        p_sys->dts, (float)p_sys->dts * CLOCK_FREQ / (mdate() - p_sys->start));
+#endif
+
+    return p_block;
+}
+
+static int  Open (vlc_object_t *p_this)
+{
+    encoder_t     *p_enc = (encoder_t *)p_this;
+    encoder_sys_t *p_sys;
+
+    if (p_enc->fmt_out.i_codec != VLC_CODEC_HEVC && !p_enc->b_force)
+        return VLC_EGENERIC;
+
+    p_enc->fmt_out.i_cat = VIDEO_ES;
+    p_enc->fmt_out.i_codec = VLC_CODEC_HEVC;
+    p_enc->p_sys = p_sys = malloc(sizeof(encoder_sys_t));
+    if (!p_sys)
+        return VLC_ENOMEM;
+
+    p_enc->fmt_in.i_codec = VLC_CODEC_I420;
+
+    x265_param_t *param = &p_sys->param;
+    x265_param_default(param);
+
+    param->frameNumThreads = vlc_GetCPUCount();
+    param->bEnableWavefront = 0; // buggy in x265, use frame threading for now
+    param->maxCUSize = 16; /* use smaller macroblock */
+
+    param->frameRate = p_enc->fmt_in.video.i_frame_rate /
+            p_enc->fmt_in.video.i_frame_rate_base;
+    param->sourceWidth = p_enc->fmt_in.video.i_visible_width;
+    param->sourceHeight = p_enc->fmt_in.video.i_visible_height;
+
+    if (param->sourceWidth & (param->maxCUSize - 1)) {
+        msg_Err(p_enc, "Width (%d) must be a multiple of %d",
+            param->sourceWidth, param->maxCUSize);
+        free(p_sys);
+        return VLC_EGENERIC;
+    }
+    if (param->sourceHeight & 7) {
+        msg_Err(p_enc, "Height (%d) must be a multiple of 8", param->sourceHeight);
+        free(p_sys);
+        return VLC_EGENERIC;
+    }
+
+    if (p_enc->fmt_out.i_bitrate > 0) {
+        param->rc.bitrate = p_enc->fmt_out.i_bitrate / 1000;
+        param->rc.rateControlMode = X265_RC_ABR;
+    }
+
+    p_sys->h = x265_encoder_open(param);
+    if (p_sys->h == NULL) {
+        msg_Err(p_enc, "cannot open x265 encoder");
+        free(p_sys);
+        return VLC_EGENERIC;
+    }
+
+    x265_nal_t *nal;
+    int i_nal;
+    if (x265_encoder_headers(p_sys->h, &nal, &i_nal)) {
+        msg_Err(p_enc, "cannot get x265 headers");
+        Close(VLC_OBJECT(p_enc));
+        return VLC_EGENERIC;
+    }
+
+    size_t i_extra = 0;
+    for (int i = 0; i < i_nal; i++)
+        i_extra += nal[i].i_payload;
+
+    p_enc->fmt_out.i_extra = i_extra;
+
+    uint8_t *p_extra = p_enc->fmt_out.p_extra = malloc(i_extra);
+    if (!p_extra) {
+        Close(VLC_OBJECT(p_enc));
+        return VLC_ENOMEM;
+    }
+
+    for (int i = 0; i < i_nal; i++) {
+        memcpy(p_extra, nal[i].p_payload, nal[i].i_payload);
+        p_extra += nal[i].i_payload;
+    }
+
+    p_sys->dts = 0;
+    p_sys->initial_date = 0;
+    p_sys->i_initial_delay = 0;
+    p_sys->write_headers = true;
+
+    p_enc->pf_encode_video = Encode;
+    p_enc->pf_encode_audio = NULL;
+
+    return VLC_SUCCESS;
+}
+
+static void Close(vlc_object_t *p_this)
+{
+    encoder_t     *p_enc = (encoder_t *)p_this;
+    encoder_sys_t *p_sys = p_enc->p_sys;
+
+    x265_encoder_close(p_sys->h, NULL);
+
+    free(p_sys);
+}
diff --git a/po/POTFILES.in b/po/POTFILES.in
index b4fb994..13f831c 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -406,6 +406,7 @@ modules/codec/uleaddvaudio.c
 modules/codec/vorbis.c
 modules/codec/wmafixed/wma.c
 modules/codec/x264.c
+modules/codec/x265.c
 modules/codec/xwd.c
 modules/codec/zvbi.c
 modules/control/dbus/dbus.c



More information about the vlc-commits mailing list