Add libx265 encoder

Signed-off-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
pull/43/merge
Derek Buitenhuis 11 years ago
parent b6c0f07d5a
commit bb6b1731eb
  1. 1
      Changelog
  2. 1
      LICENSE
  3. 7
      configure
  4. 19
      doc/general.texi
  5. 1
      libavcodec/Makefile
  6. 1
      libavcodec/allcodecs.c
  7. 284
      libavcodec/libx265.c
  8. 2
      libavcodec/version.h

@ -26,6 +26,7 @@ version <next>
MP3, AIFF, and OMA files), FLAC header, and the AVI "junk" block. MP3, AIFF, and OMA files), FLAC header, and the AVI "junk" block.
- Mirillis FIC video decoder - Mirillis FIC video decoder
- Support DNx444 - Support DNx444
- libx265 encoder
version 2.1: version 2.1:

@ -79,6 +79,7 @@ The following libraries are under GPL:
- libutvideo - libutvideo
- libvidstab - libvidstab
- libx264 - libx264
- libx265
- libxavs - libxavs
- libxvid - libxvid
When combining them with FFmpeg, FFmpeg needs to be licensed as GPL as well by When combining them with FFmpeg, FFmpeg needs to be licensed as GPL as well by

7
configure vendored

@ -244,6 +244,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]
@ -1310,6 +1311,7 @@ EXTERNAL_LIBRARY_LIST="
libwavpack libwavpack
libwebp libwebp
libx264 libx264
libx265
libxavs libxavs
libxvid libxvid
libzmq libzmq
@ -2189,6 +2191,7 @@ libwavpack_encoder_deps="libwavpack"
libwebp_encoder_deps="libwebp" libwebp_encoder_deps="libwebp"
libx264_encoder_deps="libx264" libx264_encoder_deps="libx264"
libx264rgb_encoder_deps="libx264" libx264rgb_encoder_deps="libx264"
libx265_encoder_deps="libx265"
libxavs_encoder_deps="libxavs" libxavs_encoder_deps="libxavs"
libxvid_encoder_deps="libxvid" libxvid_encoder_deps="libxvid"
libutvideo_decoder_deps="libutvideo" libutvideo_decoder_deps="libutvideo"
@ -4011,6 +4014,7 @@ die_license_disabled gpl libcdio
die_license_disabled gpl libutvideo die_license_disabled gpl libutvideo
die_license_disabled gpl libvidstab die_license_disabled gpl libvidstab
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 libzvbi die_license_disabled gpl libzvbi
@ -4500,6 +4504,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 must be installed and version must be >= 0.118."; } die "ERROR: libx264 must be installed and 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 libzmq && require_pkg_config libzmq zmq.h zmq_ctx_new enabled libzmq && require_pkg_config libzmq zmq.h zmq_ctx_new

@ -122,6 +122,20 @@ x264 is under the GNU Public License Version 2 or later
details), you must upgrade FFmpeg's license to GPL in order to use it. details), you must upgrade FFmpeg's license to GPL in order to use it.
@end float @end float
@section x265
FFmpeg 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
@ -342,7 +356,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
@ -612,7 +626,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

@ -742,6 +742,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
OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o

@ -516,6 +516,7 @@ void avcodec_register_all(void)
REGISTER_ENCODER(LIBWEBP, libwebp); REGISTER_ENCODER(LIBWEBP, libwebp);
REGISTER_ENCODER(LIBX264, libx264); REGISTER_ENCODER(LIBX264, libx264);
REGISTER_ENCODER(LIBX264RGB, libx264rgb); REGISTER_ENCODER(LIBX264RGB, libx264rgb);
REGISTER_ENCODER(LIBX265, libx265);
REGISTER_ENCODER(LIBXAVS, libxavs); REGISTER_ENCODER(LIBXAVS, libxavs);
REGISTER_ENCODER(LIBXVID, libxvid); REGISTER_ENCODER(LIBXVID, libxvid);
REGISTER_DECODER(LIBZVBI_TELETEXT, libzvbi_teletext); REGISTER_DECODER(LIBZVBI_TELETEXT, libzvbi_teletext);

@ -0,0 +1,284 @@
/*
* libx265 encoder
*
* Copyright (c) 2013-2014 Derek Buitenhuis
*
* This file is part of FFmpeg.
*
* FFmpeg 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.
*
* FFmpeg 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 FFmpeg; 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_EXTERNAL;
}
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 @@
#include "libavutil/version.h" #include "libavutil/version.h"
#define LIBAVCODEC_VERSION_MAJOR 55 #define LIBAVCODEC_VERSION_MAJOR 55
#define LIBAVCODEC_VERSION_MINOR 51 #define LIBAVCODEC_VERSION_MINOR 52
#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \

Loading…
Cancel
Save