Commit 50ea9315 authored by Derek Buitenhuis's avatar Derek Buitenhuis
Browse files

Add libx265 encoder


Signed-off-by: default avatarDerek Buitenhuis <derek.buitenhuis@gmail.com>
parent f5d92d9c
...@@ -57,6 +57,7 @@ version 10: ...@@ -57,6 +57,7 @@ version 10:
- framepack filter - framepack filter
- Mirillis FIC video decoder - Mirillis FIC video decoder
- Support DNx444 - Support DNx444
- libx265 encoder
version 9: version 9:
......
...@@ -46,7 +46,7 @@ affect the licensing of binaries resulting from the combination. ...@@ -46,7 +46,7 @@ affect the licensing of binaries resulting from the combination.
compatible libraries compatible libraries
-------------------- --------------------
The libcdio, libx264, libxavs and libxvid libraries are under GPL. When The libcdio, libx264, libx265, libxavs and libxvid libraries are under GPL. When
combining them with Libav, Libav needs to be licensed as GPL as well by combining them with Libav, Libav needs to be licensed as GPL as well by
passing --enable-gpl to configure. passing --enable-gpl to configure.
......
...@@ -204,6 +204,7 @@ External library support: ...@@ -204,6 +204,7 @@ External library support:
--enable-libwavpack enable wavpack encoding via libwavpack [no] --enable-libwavpack enable wavpack encoding via libwavpack [no]
--enable-libwebp enable WebP encoding via libwebp [no] --enable-libwebp enable WebP encoding via libwebp [no]
--enable-libx264 enable H.264 encoding via x264 [no] --enable-libx264 enable H.264 encoding via x264 [no]
--enable-libx265 enable HEVC encoding via x265 [no]
--enable-libxavs enable AVS encoding via xavs [no] --enable-libxavs enable AVS encoding via xavs [no]
--enable-libxvid enable Xvid encoding via xvidcore, --enable-libxvid enable Xvid encoding via xvidcore,
native MPEG-4/Xvid encoder exists [no] native MPEG-4/Xvid encoder exists [no]
...@@ -1128,6 +1129,7 @@ EXTERNAL_LIBRARY_LIST=" ...@@ -1128,6 +1129,7 @@ EXTERNAL_LIBRARY_LIST="
libwavpack libwavpack
libwebp libwebp
libx264 libx264
libx265
libxavs libxavs
libxvid libxvid
openssl openssl
...@@ -1885,6 +1887,7 @@ libvpx_vp9_encoder_deps="libvpx" ...@@ -1885,6 +1887,7 @@ libvpx_vp9_encoder_deps="libvpx"
libwavpack_encoder_deps="libwavpack" libwavpack_encoder_deps="libwavpack"
libwebp_encoder_deps="libwebp" libwebp_encoder_deps="libwebp"
libx264_encoder_deps="libx264" libx264_encoder_deps="libx264"
libx265_encoder_deps="libx265"
libxavs_encoder_deps="libxavs" libxavs_encoder_deps="libxavs"
libxvid_encoder_deps="libxvid" libxvid_encoder_deps="libxvid"
...@@ -3530,6 +3533,7 @@ die_license_disabled() { ...@@ -3530,6 +3533,7 @@ die_license_disabled() {
die_license_disabled gpl libcdio die_license_disabled gpl libcdio
die_license_disabled gpl libx264 die_license_disabled gpl libx264
die_license_disabled gpl libx265
die_license_disabled gpl libxavs die_license_disabled gpl libxavs
die_license_disabled gpl libxvid die_license_disabled gpl libxvid
die_license_disabled gpl x11grab die_license_disabled gpl x11grab
...@@ -3954,6 +3958,9 @@ enabled libwebp && require_pkg_config libwebp webp/encode.h WebPGetEnc ...@@ -3954,6 +3958,9 @@ enabled libwebp && require_pkg_config libwebp webp/encode.h WebPGetEnc
enabled libx264 && require libx264 x264.h x264_encoder_encode -lx264 && enabled libx264 && require libx264 x264.h x264_encoder_encode -lx264 &&
{ check_cpp_condition x264.h "X264_BUILD >= 118" || { check_cpp_condition x264.h "X264_BUILD >= 118" ||
die "ERROR: libx264 version must be >= 0.118."; } die "ERROR: libx264 version must be >= 0.118."; }
enabled libx265 && require_pkg_config x265 x265.h x265_encoder_encode &&
{ check_cpp_condition x265.h "X265_BUILD >= 5" ||
die "ERROR: libx265 version must be >= 5."; }
enabled libxavs && require libxavs xavs.h xavs_encoder_encode -lxavs enabled libxavs && require libxavs xavs.h xavs_encoder_encode -lxavs
enabled libxvid && require libxvid xvid.h xvid_global -lxvidcore enabled libxvid && require libxvid xvid.h xvid_global -lxvidcore
enabled openssl && { check_lib openssl/ssl.h SSL_library_init -lssl -lcrypto || enabled openssl && { check_lib openssl/ssl.h SSL_library_init -lssl -lcrypto ||
......
...@@ -101,6 +101,20 @@ x264 is under the GNU Public License Version 2 or later ...@@ -101,6 +101,20 @@ x264 is under the GNU Public License Version 2 or later
details), you must upgrade Libav's license to GPL in order to use it. details), you must upgrade Libav's license to GPL in order to use it.
@end float @end float
@section x265
Libav can make use of the x265 library for HEVC encoding.
Go to @url{http://x265.org/developers.html} and follow the instructions
for installing the library. Then pass @code{--enable-libx265} to configure
to enable it.
@float note
x265 is under the GNU Public License Version 2 or later
(see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for
details), you must upgrade FFmpeg's license to GPL in order to use it.
@end float
@section libilbc @section libilbc
iLBC is a narrowband speech codec that has been made freely available iLBC is a narrowband speech codec that has been made freely available
...@@ -274,7 +288,7 @@ library: ...@@ -274,7 +288,7 @@ library:
@item raw H.261 @tab X @tab X @item raw H.261 @tab X @tab X
@item raw H.263 @tab X @tab X @item raw H.263 @tab X @tab X
@item raw H.264 @tab X @tab X @item raw H.264 @tab X @tab X
@item raw HEVC @tab @tab X @item raw HEVC @tab X @tab X
@item raw Ingenient MJPEG @tab @tab X @item raw Ingenient MJPEG @tab @tab X
@item raw MJPEG @tab X @tab X @item raw MJPEG @tab X @tab X
@item raw MLP @tab @tab X @item raw MLP @tab @tab X
...@@ -529,7 +543,8 @@ following image formats are supported: ...@@ -529,7 +543,8 @@ following image formats are supported:
@item H.263+ / H.263-1998 / H.263 version 2 @tab X @tab X @item H.263+ / H.263-1998 / H.263 version 2 @tab X @tab X
@item H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 @tab E @tab X @item H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 @tab E @tab X
@tab encoding supported through external library libx264 @tab encoding supported through external library libx264
@item HEVC @tab @tab X @item HEVC @tab X @tab X
@tab encoding supported through the external library libx265
@item HNM version 4 @tab @tab X @item HNM version 4 @tab @tab X
@item HuffYUV @tab X @tab X @item HuffYUV @tab X @tab X
@item HuffYUV FFmpeg variant @tab X @tab X @item HuffYUV FFmpeg variant @tab X @tab X
......
...@@ -616,6 +616,7 @@ OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o libvpx.o ...@@ -616,6 +616,7 @@ OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o libvpx.o
OBJS-$(CONFIG_LIBWAVPACK_ENCODER) += libwavpackenc.o OBJS-$(CONFIG_LIBWAVPACK_ENCODER) += libwavpackenc.o
OBJS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc.o OBJS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc.o
OBJS-$(CONFIG_LIBX264_ENCODER) += libx264.o OBJS-$(CONFIG_LIBX264_ENCODER) += libx264.o
OBJS-$(CONFIG_LIBX265_ENCODER) += libx265.o
OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o
OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o
......
...@@ -441,6 +441,7 @@ void avcodec_register_all(void) ...@@ -441,6 +441,7 @@ void avcodec_register_all(void)
REGISTER_ENCODER(LIBWAVPACK, libwavpack); REGISTER_ENCODER(LIBWAVPACK, libwavpack);
REGISTER_ENCODER(LIBWEBP, libwebp); REGISTER_ENCODER(LIBWEBP, libwebp);
REGISTER_ENCODER(LIBX264, libx264); REGISTER_ENCODER(LIBX264, libx264);
REGISTER_ENCODER(LIBX265, libx265);
REGISTER_ENCODER(LIBXAVS, libxavs); REGISTER_ENCODER(LIBXAVS, libxavs);
REGISTER_ENCODER(LIBXVID, libxvid); REGISTER_ENCODER(LIBXVID, libxvid);
......
/*
* libx265 encoder
*
* Copyright (c) 2013-2014 Derek Buitenhuis
*
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Libav 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <x265.h>
#include "libavutil/internal.h"
#include "libavutil/common.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
#include "avcodec.h"
#include "internal.h"
typedef struct libx265Context {
const AVClass *class;
x265_encoder *encoder;
x265_param *params;
uint8_t *header;
int header_size;
char *preset;
char *tune;
char *x265_opts;
} libx265Context;
static int is_keyframe(NalUnitType naltype)
{
switch (naltype) {
case NAL_UNIT_CODED_SLICE_BLA_W_LP:
case NAL_UNIT_CODED_SLICE_BLA_W_RADL:
case NAL_UNIT_CODED_SLICE_BLA_N_LP:
case NAL_UNIT_CODED_SLICE_IDR_W_RADL:
case NAL_UNIT_CODED_SLICE_IDR_N_LP:
case NAL_UNIT_CODED_SLICE_CRA:
return 1;
default:
return 0;
}
}
static av_cold int libx265_encode_close(AVCodecContext *avctx)
{
libx265Context *ctx = avctx->priv_data;
av_frame_free(&avctx->coded_frame);
av_freep(&ctx->header);
x265_param_free(ctx->params);
if (ctx->encoder)
x265_encoder_close(ctx->encoder);
return 0;
}
static av_cold int libx265_encode_init(AVCodecContext *avctx)
{
libx265Context *ctx = avctx->priv_data;
x265_nal *nal;
uint8_t *buf;
int nnal;
int ret;
int i;
avctx->coded_frame = av_frame_alloc();
if (!avctx->coded_frame) {
av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n");
return AVERROR(ENOMEM);
}
ctx->params = x265_param_alloc();
if (!ctx->params) {
av_log(avctx, AV_LOG_ERROR, "Could not allocate x265 param structure.\n");
return AVERROR(ENOMEM);
}
x265_param_default(ctx->params);
if (x265_param_default_preset(ctx->params, ctx->preset, ctx->tune) < 0) {
av_log(avctx, AV_LOG_ERROR, "Invalid preset or tune.\n");
return AVERROR(EINVAL);
}
ctx->params->frameNumThreads = avctx->thread_count;
ctx->params->frameRate = (int) (avctx->time_base.den / avctx->time_base.num);
ctx->params->sourceWidth = avctx->width;
ctx->params->sourceHeight = avctx->height;
ctx->params->inputBitDepth = av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth_minus1 + 1;
if (avctx->bit_rate > 0) {
ctx->params->rc.bitrate = avctx->bit_rate / 1000;
ctx->params->rc.rateControlMode = X265_RC_ABR;
}
if (ctx->x265_opts) {
AVDictionary *dict = NULL;
AVDictionaryEntry *en = NULL;
if (!av_dict_parse_string(&dict, ctx->x265_opts, "=", ":", 0)) {
while ((en = av_dict_get(dict, "", en, AV_DICT_IGNORE_SUFFIX))) {
int parse_ret = x265_param_parse(ctx->params, en->key, en->value);
switch (parse_ret) {
case X265_PARAM_BAD_NAME:
av_log(avctx, AV_LOG_WARNING,
"Unknown option: %s.\n", en->key);
break;
case X265_PARAM_BAD_VALUE:
av_log(avctx, AV_LOG_WARNING,
"Invalid value for %s: %s.\n", en->key, en->value);
break;
default:
break;
}
}
av_dict_free(&dict);
}
}
ctx->encoder = x265_encoder_open(ctx->params);
if (!ctx->encoder) {
av_log(avctx, AV_LOG_ERROR, "Cannot open libx265 encoder.\n");
libx265_encode_close(avctx);
return AVERROR_INVALIDDATA;
}
ret = x265_encoder_headers(ctx->encoder, &nal, &nnal);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Cannot encode headers.\n");
libx265_encode_close(avctx);
return AVERROR_INVALIDDATA;
}
for (i = 0; i < nnal; i++)
ctx->header_size += nal[i].sizeBytes;
ctx->header = av_malloc(ctx->header_size);
if (!ctx->header) {
av_log(avctx, AV_LOG_ERROR,
"Cannot allocate HEVC header of size %d.\n", ctx->header_size);
libx265_encode_close(avctx);
return AVERROR(ENOMEM);
}
buf = ctx->header;
for (i = 0; i < nnal; i++) {
memcpy(buf, nal[i].payload, nal[i].sizeBytes);
buf += nal[i].sizeBytes;
}
return 0;
}
static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
const AVFrame *pic, int *got_packet)
{
libx265Context *ctx = avctx->priv_data;
x265_picture x265pic;
x265_picture x265pic_out = { { 0 } };
x265_nal *nal;
uint8_t *dst;
int payload = 0;
int nnal;
int ret;
int i;
if (pic) {
for (i = 0; i < 3; i++) {
x265pic.planes[i] = pic->data[i];
x265pic.stride[i] = pic->linesize[i];
}
x265pic.pts = pic->pts;
}
ret = x265_encoder_encode(ctx->encoder, &nal, &nnal,
pic ? &x265pic : NULL, &x265pic_out);
if (ret < 0)
return AVERROR_UNKNOWN;
if (!nnal)
return 0;
for (i = 0; i < nnal; i++)
payload += nal[i].sizeBytes;
payload += ctx->header_size;
ret = ff_alloc_packet(pkt, payload);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n");
return ret;
}
dst = pkt->data;
if (ctx->header) {
memcpy(dst, ctx->header, ctx->header_size);
dst += ctx->header_size;
av_freep(&ctx->header);
ctx->header_size = 0;
}
for (i = 0; i < nnal; i++) {
memcpy(dst, nal[i].payload, nal[i].sizeBytes);
dst += nal[i].sizeBytes;
if (is_keyframe(nal[i].type))
pkt->flags |= AV_PKT_FLAG_KEY;
}
pkt->pts = x265pic_out.pts;
pkt->dts = x265pic_out.dts;
*got_packet = 1;
return 0;
}
static const enum AVPixelFormat x265_csp_eight[] = {
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_NONE
};
static const enum AVPixelFormat x265_csp_twelve[] = {
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_YUV420P10,
AV_PIX_FMT_NONE
};
static av_cold void libx265_encode_init_csp(AVCodec *codec)
{
if (x265_max_bit_depth == 8)
codec->pix_fmts = x265_csp_eight;
else if (x265_max_bit_depth == 12)
codec->pix_fmts = x265_csp_twelve;
}
#define OFFSET(x) offsetof(libx265Context, x)
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
{ "preset", "set the x265 preset", OFFSET(preset), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE },
{ "tune", "set the x265 tune parameter", OFFSET(tune), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE },
{ "x265-params", "set the x265 configuration using a :-separated list of key=value parameters", OFFSET(x265_opts), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE },
{ NULL }
};
static const AVClass class = {
.class_name = "libx265",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
AVCodec ff_libx265_encoder = {
.name = "libx265",
.long_name = NULL_IF_CONFIG_SMALL("libx265 H.265 / HEVC"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_HEVC,
.init = libx265_encode_init,
.init_static_data = libx265_encode_init_csp,
.encode2 = libx265_encode_frame,
.close = libx265_encode_close,
.priv_data_size = sizeof(libx265Context),
.priv_class = &class,
.capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS,
};
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include "libavutil/version.h" #include "libavutil/version.h"
#define LIBAVCODEC_VERSION_MAJOR 55 #define LIBAVCODEC_VERSION_MAJOR 55
#define LIBAVCODEC_VERSION_MINOR 33 #define LIBAVCODEC_VERSION_MINOR 34
#define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_MICRO 0
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment