Merge commit 'c438899a706422b8362a13714580e988be4d638b'

* commit 'c438899a706422b8362a13714580e988be4d638b':
  Add AV1 video decoding support through libaom

This contains some extra changes taken from the libvpx decoder
wrapper, most of them contained in the set_pix_fmt() function.

Merged-by: James Almer <jamrial@gmail.com>
This commit is contained in:
James Almer 2018-03-28 18:09:46 -03:00
commit 0dc11d8bbd
6 changed files with 266 additions and 0 deletions

View File

@ -48,6 +48,7 @@ version <next>:
- drmeter audio filter - drmeter audio filter
- hapqa_extract bitstream filter - hapqa_extract bitstream filter
- filter_units bitstream filter - filter_units bitstream filter
- AV1 Support through libaom
version 3.4: version 3.4:

4
configure vendored
View File

@ -217,6 +217,7 @@ External library support:
--disable-iconv disable iconv [autodetect] --disable-iconv disable iconv [autodetect]
--enable-jni enable JNI support [no] --enable-jni enable JNI support [no]
--enable-ladspa enable LADSPA audio filtering [no] --enable-ladspa enable LADSPA audio filtering [no]
--enable-libaom enable AV1 video encoding/decoding via libaom [no]
--enable-libass enable libass subtitles rendering, --enable-libass enable libass subtitles rendering,
needed for subtitles and ass filter [no] needed for subtitles and ass filter [no]
--enable-libbluray enable BluRay reading using libbluray [no] --enable-libbluray enable BluRay reading using libbluray [no]
@ -1653,6 +1654,7 @@ EXTERNAL_LIBRARY_LIST="
gnutls gnutls
jni jni
ladspa ladspa
libaom
libass libass
libbluray libbluray
libbs2b libbs2b
@ -3004,6 +3006,7 @@ h264_videotoolbox_encoder_deps="pthreads"
h264_videotoolbox_encoder_select="videotoolbox_encoder" h264_videotoolbox_encoder_select="videotoolbox_encoder"
hevc_videotoolbox_encoder_deps="pthreads" hevc_videotoolbox_encoder_deps="pthreads"
hevc_videotoolbox_encoder_select="videotoolbox_encoder" hevc_videotoolbox_encoder_select="videotoolbox_encoder"
libaom_av1_decoder_deps="libaom"
libcelt_decoder_deps="libcelt" libcelt_decoder_deps="libcelt"
libcodec2_decoder_deps="libcodec2" libcodec2_decoder_deps="libcodec2"
libcodec2_encoder_deps="libcodec2" libcodec2_encoder_deps="libcodec2"
@ -5930,6 +5933,7 @@ enabled gmp && require gmp gmp.h mpz_export -lgmp
enabled gnutls && require_pkg_config gnutls gnutls gnutls/gnutls.h gnutls_global_init enabled gnutls && require_pkg_config gnutls gnutls gnutls/gnutls.h gnutls_global_init
enabled jni && { [ $target_os = "android" ] && check_header jni.h && enabled pthreads || die "ERROR: jni not found"; } enabled jni && { [ $target_os = "android" ] && check_header jni.h && enabled pthreads || die "ERROR: jni not found"; }
enabled ladspa && require_header ladspa.h enabled ladspa && require_header ladspa.h
enabled libaom && require_pkg_config libaom "aom >= 0.1.0" aom/aom_codec.h aom_codec_version
enabled lv2 && require_pkg_config lv2 lilv-0 "lilv-0/lilv/lilv.h" lilv_world_new enabled lv2 && require_pkg_config lv2 lilv-0 "lilv-0/lilv/lilv.h" lilv_world_new
enabled libiec61883 && require libiec61883 libiec61883/iec61883.h iec61883_cmp_connect -lraw1394 -lavc1394 -lrom1394 -liec61883 enabled libiec61883 && require libiec61883 libiec61883/iec61883.h iec61883_cmp_connect -lraw1394 -lavc1394 -lrom1394 -liec61883
enabled libass && require_pkg_config libass libass ass/ass.h ass_library_init enabled libass && require_pkg_config libass libass ass/ass.h ass_library_init

View File

@ -17,6 +17,14 @@ for more formats. None of them are used by default, their use has to be
explicitly requested by passing the appropriate flags to explicitly requested by passing the appropriate flags to
@command{./configure}. @command{./configure}.
+@section Alliance for Open Media libaom
FFmpeg can make use of the libaom library for AV1 decoding.
Go to @url{http://aomedia.org/} and follow the instructions for
installing the library. Then pass @code{--enable-libaom} to configure to
enable it.
@section OpenJPEG @section OpenJPEG
FFmpeg can use the OpenJPEG libraries for encoding/decoding J2K videos. Go to FFmpeg can use the OpenJPEG libraries for encoding/decoding J2K videos. Go to
@ -719,6 +727,8 @@ following image formats are supported:
@item Autodesk Animator Flic video @tab @tab X @item Autodesk Animator Flic video @tab @tab X
@item Autodesk RLE @tab @tab X @item Autodesk RLE @tab @tab X
@tab fourcc: AASC @tab fourcc: AASC
@item AV1 @tab @tab E
@tab Supported through external library libaom
@item Avid 1:1 10-bit RGB Packer @tab X @tab X @item Avid 1:1 10-bit RGB Packer @tab X @tab X
@tab fourcc: AVrp @tab fourcc: AVrp
@item AVS (Audio Video Standard) video @tab @tab X @item AVS (Audio Video Standard) video @tab @tab X

View File

@ -939,6 +939,7 @@ OBJS-$(CONFIG_ALAC_AT_ENCODER) += audiotoolboxenc.o
OBJS-$(CONFIG_ILBC_AT_ENCODER) += audiotoolboxenc.o OBJS-$(CONFIG_ILBC_AT_ENCODER) += audiotoolboxenc.o
OBJS-$(CONFIG_PCM_ALAW_AT_ENCODER) += audiotoolboxenc.o OBJS-$(CONFIG_PCM_ALAW_AT_ENCODER) += audiotoolboxenc.o
OBJS-$(CONFIG_PCM_MULAW_AT_ENCODER) += audiotoolboxenc.o OBJS-$(CONFIG_PCM_MULAW_AT_ENCODER) += audiotoolboxenc.o
OBJS-$(CONFIG_LIBAOM_AV1_DECODER) += libaomdec.o
OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o
OBJS-$(CONFIG_LIBCODEC2_DECODER) += libcodec2.o codec2utils.o OBJS-$(CONFIG_LIBCODEC2_DECODER) += libcodec2.o codec2utils.o
OBJS-$(CONFIG_LIBCODEC2_ENCODER) += libcodec2.o codec2utils.o OBJS-$(CONFIG_LIBCODEC2_ENCODER) += libcodec2.o codec2utils.o

View File

@ -663,6 +663,7 @@ extern AVCodec ff_pcm_mulaw_at_encoder;
extern AVCodec ff_pcm_mulaw_at_decoder; extern AVCodec ff_pcm_mulaw_at_decoder;
extern AVCodec ff_qdmc_at_decoder; extern AVCodec ff_qdmc_at_decoder;
extern AVCodec ff_qdm2_at_decoder; extern AVCodec ff_qdm2_at_decoder;
extern AVCodec ff_libaom_av1_decoder;
extern AVCodec ff_libcelt_decoder; extern AVCodec ff_libcelt_decoder;
extern AVCodec ff_libcodec2_encoder; extern AVCodec ff_libcodec2_encoder;
extern AVCodec ff_libcodec2_decoder; extern AVCodec ff_libcodec2_decoder;

249
libavcodec/libaomdec.c Normal file
View File

@ -0,0 +1,249 @@
/*
* Copyright (c) 2010, Google, Inc.
*
* 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
*/
/**
* @file
* AV1 decoder support via libaom
*/
#include <aom/aom_decoder.h>
#include <aom/aomdx.h>
#include "libavutil/common.h"
#include "libavutil/imgutils.h"
#include "avcodec.h"
#include "internal.h"
typedef struct AV1DecodeContext {
struct aom_codec_ctx decoder;
} AV1DecodeContext;
static av_cold int aom_init(AVCodecContext *avctx,
const struct aom_codec_iface *iface)
{
AV1DecodeContext *ctx = avctx->priv_data;
struct aom_codec_dec_cfg deccfg = {
/* token partitions+1 would be a decent choice */
.threads = FFMIN(avctx->thread_count, 16)
};
av_log(avctx, AV_LOG_INFO, "%s\n", aom_codec_version_str());
av_log(avctx, AV_LOG_VERBOSE, "%s\n", aom_codec_build_config());
if (aom_codec_dec_init(&ctx->decoder, iface, &deccfg, 0) != AOM_CODEC_OK) {
const char *error = aom_codec_error(&ctx->decoder);
av_log(avctx, AV_LOG_ERROR, "Failed to initialize decoder: %s\n",
error);
return AVERROR(EINVAL);
}
return 0;
}
static void image_copy_16_to_8(AVFrame *pic, struct aom_image *img)
{
int i;
for (i = 0; i < 3; i++) {
int w = img->d_w;
int h = img->d_h;
int x, y;
if (i) {
w = (w + img->x_chroma_shift) >> img->x_chroma_shift;
h = (h + img->y_chroma_shift) >> img->y_chroma_shift;
}
for (y = 0; y < h; y++) {
uint16_t *src = (uint16_t *)(img->planes[i] + y * img->stride[i]);
uint8_t *dst = pic->data[i] + y * pic->linesize[i];
for (x = 0; x < w; x++)
*dst++ = *src++;
}
}
}
// returns 0 on success, AVERROR_INVALIDDATA otherwise
static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img)
{
static const enum AVColorSpace colorspaces[10] = {
AVCOL_SPC_UNSPECIFIED, AVCOL_SPC_BT470BG, AVCOL_SPC_BT709, AVCOL_SPC_SMPTE170M,
AVCOL_SPC_SMPTE240M, AVCOL_SPC_BT2020_NCL, AVCOL_SPC_BT2020_CL, AVCOL_SPC_RGB,
AVCOL_SPC_ICTCP, AVCOL_SPC_RESERVED
};
static const enum AVColorRange color_ranges[] = {
AVCOL_RANGE_MPEG, AVCOL_RANGE_JPEG
};
avctx->color_range = color_ranges[img->range];
avctx->colorspace = colorspaces[img->cs];
switch (img->fmt) {
case AOM_IMG_FMT_I420:
avctx->pix_fmt = AV_PIX_FMT_YUV420P;
return 0;
case AOM_IMG_FMT_I422:
avctx->pix_fmt = AV_PIX_FMT_YUV422P;
return 0;
case AOM_IMG_FMT_I440:
avctx->pix_fmt = AV_PIX_FMT_YUV440P;
return 0;
case AOM_IMG_FMT_I444:
avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ?
AV_PIX_FMT_GBRP : AV_PIX_FMT_YUV444P;
return 0;
case AOM_IMG_FMT_I42016:
if (img->bit_depth == 8) {
avctx->pix_fmt = AV_PIX_FMT_YUV420P;
return 0;
} else if (img->bit_depth == 10) {
avctx->pix_fmt = AV_PIX_FMT_YUV420P10;
return 0;
} else if (img->bit_depth == 12) {
avctx->pix_fmt = AV_PIX_FMT_YUV420P12;
return 0;
} else {
return AVERROR_INVALIDDATA;
}
case AOM_IMG_FMT_I42216:
if (img->bit_depth == 8) {
avctx->pix_fmt = AV_PIX_FMT_YUV422P;
return 0;
} else if (img->bit_depth == 10) {
avctx->pix_fmt = AV_PIX_FMT_YUV422P10;
return 0;
} else if (img->bit_depth == 12) {
avctx->pix_fmt = AV_PIX_FMT_YUV422P12;
return 0;
} else {
return AVERROR_INVALIDDATA;
}
case AOM_IMG_FMT_I44016:
if (img->bit_depth == 8) {
avctx->pix_fmt = AV_PIX_FMT_YUV440P;
return 0;
} else if (img->bit_depth == 10) {
avctx->pix_fmt = AV_PIX_FMT_YUV440P10;
return 0;
} else if (img->bit_depth == 12) {
avctx->pix_fmt = AV_PIX_FMT_YUV440P12;
return 0;
} else {
return AVERROR_INVALIDDATA;
}
case AOM_IMG_FMT_I44416:
if (img->bit_depth == 8) {
avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ?
AV_PIX_FMT_GBRP : AV_PIX_FMT_YUV444P;
return 0;
} else if (img->bit_depth == 10) {
avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ?
AV_PIX_FMT_GBRP10 : AV_PIX_FMT_YUV444P10;
return 0;
} else if (img->bit_depth == 12) {
avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ?
AV_PIX_FMT_GBRP12 : AV_PIX_FMT_YUV444P12;
return 0;
} else {
return AVERROR_INVALIDDATA;
}
default:
return AVERROR_INVALIDDATA;
}
}
static int aom_decode(AVCodecContext *avctx, void *data, int *got_frame,
AVPacket *avpkt)
{
AV1DecodeContext *ctx = avctx->priv_data;
AVFrame *picture = data;
const void *iter = NULL;
struct aom_image *img;
int ret;
if (aom_codec_decode(&ctx->decoder, avpkt->data, avpkt->size, NULL) !=
AOM_CODEC_OK) {
const char *error = aom_codec_error(&ctx->decoder);
const char *detail = aom_codec_error_detail(&ctx->decoder);
av_log(avctx, AV_LOG_ERROR, "Failed to decode frame: %s\n", error);
if (detail)
av_log(avctx, AV_LOG_ERROR, " Additional information: %s\n",
detail);
return AVERROR_INVALIDDATA;
}
if ((img = aom_codec_get_frame(&ctx->decoder, &iter))) {
if (img->d_w > img->w || img->d_h > img->h) {
av_log(avctx, AV_LOG_ERROR, "Display dimensions %dx%d exceed storage %dx%d\n",
img->d_w, img->d_h, img->w, img->h);
return AVERROR_EXTERNAL;
}
if ((ret = set_pix_fmt(avctx, img)) < 0) {
av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (%d) / bit_depth (%d)\n",
img->fmt, img->bit_depth);
return ret;
}
if ((int)img->d_w != avctx->width || (int)img->d_h != avctx->height) {
av_log(avctx, AV_LOG_INFO, "dimension change! %dx%d -> %dx%d\n",
avctx->width, avctx->height, img->d_w, img->d_h);
ret = ff_set_dimensions(avctx, img->d_w, img->d_h);
if (ret < 0)
return ret;
}
if ((ret = ff_get_buffer(avctx, picture, 0)) < 0)
return ret;
if ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) && img->bit_depth == 8)
image_copy_16_to_8(picture, img);
else
av_image_copy(picture->data, picture->linesize, (const uint8_t **)img->planes,
img->stride, avctx->pix_fmt, img->d_w, img->d_h);
*got_frame = 1;
}
return avpkt->size;
}
static av_cold int aom_free(AVCodecContext *avctx)
{
AV1DecodeContext *ctx = avctx->priv_data;
aom_codec_destroy(&ctx->decoder);
return 0;
}
static av_cold int av1_init(AVCodecContext *avctx)
{
return aom_init(avctx, &aom_codec_av1_dx_algo);
}
AVCodec ff_libaom_av1_decoder = {
.name = "libaom-av1",
.long_name = NULL_IF_CONFIG_SMALL("libaom AV1"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_AV1,
.priv_data_size = sizeof(AV1DecodeContext),
.init = av1_init,
.close = aom_free,
.decode = aom_decode,
.capabilities = AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_DR1,
.wrapper_name = "libaom",
};