mirror of https://git.ffmpeg.org/ffmpeg.git
avcodec/libaomenc: support AV_CODEC_CAP_ENCODER_RECON_FRAME
Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
parent
c6f22940e4
commit
b0cd979a0b
|
@ -1055,8 +1055,8 @@ 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_LIBAOM_AV1_DECODER) += libaomdec.o libaom.o
|
||||||
OBJS-$(CONFIG_LIBAOM_AV1_ENCODER) += libaomenc.o
|
OBJS-$(CONFIG_LIBAOM_AV1_ENCODER) += libaomenc.o libaom.o
|
||||||
OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o ass.o
|
OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o ass.o
|
||||||
OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o
|
OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o
|
||||||
OBJS-$(CONFIG_LIBCODEC2_DECODER) += libcodec2.o
|
OBJS-$(CONFIG_LIBCODEC2_DECODER) += libcodec2.o
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* AOM common functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libavutil/pixdesc.h"
|
||||||
|
#include "libaom.h"
|
||||||
|
|
||||||
|
void ff_aom_image_copy_16_to_8(AVFrame *pic, struct aom_image *img)
|
||||||
|
{
|
||||||
|
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pic->format);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < desc->nb_components; 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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* AOM common functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_LIBAOM_H
|
||||||
|
#define AVCODEC_LIBAOM_H
|
||||||
|
|
||||||
|
#include <aom/aom_image.h>
|
||||||
|
|
||||||
|
#include "libavutil/frame.h"
|
||||||
|
|
||||||
|
void ff_aom_image_copy_16_to_8(AVFrame *pic, struct aom_image *img);
|
||||||
|
|
||||||
|
#endif /* AVCODEC_LIBAOM_H */
|
|
@ -33,6 +33,7 @@
|
||||||
#include "avcodec.h"
|
#include "avcodec.h"
|
||||||
#include "codec_internal.h"
|
#include "codec_internal.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "libaom.h"
|
||||||
#include "profiles.h"
|
#include "profiles.h"
|
||||||
|
|
||||||
typedef struct AV1DecodeContext {
|
typedef struct AV1DecodeContext {
|
||||||
|
@ -60,30 +61,6 @@ static av_cold int aom_init(AVCodecContext *avctx,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void image_copy_16_to_8(AVFrame *pic, struct aom_image *img)
|
|
||||||
{
|
|
||||||
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pic->format);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < desc->nb_components; 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
|
// returns 0 on success, AVERROR_INVALIDDATA otherwise
|
||||||
static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img)
|
static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img)
|
||||||
{
|
{
|
||||||
|
@ -223,7 +200,7 @@ static int aom_decode(AVCodecContext *avctx, AVFrame *picture,
|
||||||
ff_set_sar(avctx, picture->sample_aspect_ratio);
|
ff_set_sar(avctx, picture->sample_aspect_ratio);
|
||||||
|
|
||||||
if ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) && img->bit_depth == 8)
|
if ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) && img->bit_depth == 8)
|
||||||
image_copy_16_to_8(picture, img);
|
ff_aom_image_copy_16_to_8(picture, img);
|
||||||
else {
|
else {
|
||||||
const uint8_t *planes[4] = { img->planes[0], img->planes[1], img->planes[2] };
|
const uint8_t *planes[4] = { img->planes[0], img->planes[1], img->planes[2] };
|
||||||
const int stride[4] = { img->stride[0], img->stride[1], img->stride[2] };
|
const int stride[4] = { img->stride[0], img->stride[1], img->stride[2] };
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "libavutil/base64.h"
|
#include "libavutil/base64.h"
|
||||||
#include "libavutil/common.h"
|
#include "libavutil/common.h"
|
||||||
#include "libavutil/cpu.h"
|
#include "libavutil/cpu.h"
|
||||||
|
#include "libavutil/imgutils.h"
|
||||||
#include "libavutil/mathematics.h"
|
#include "libavutil/mathematics.h"
|
||||||
#include "libavutil/opt.h"
|
#include "libavutil/opt.h"
|
||||||
#include "libavutil/pixdesc.h"
|
#include "libavutil/pixdesc.h"
|
||||||
|
@ -41,6 +42,7 @@
|
||||||
#include "codec_internal.h"
|
#include "codec_internal.h"
|
||||||
#include "encode.h"
|
#include "encode.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "libaom.h"
|
||||||
#include "packet_internal.h"
|
#include "packet_internal.h"
|
||||||
#include "profiles.h"
|
#include "profiles.h"
|
||||||
|
|
||||||
|
@ -208,6 +210,7 @@ static const char *const ctlidstr[] = {
|
||||||
#ifdef AOM_CTRL_AV1E_GET_TARGET_SEQ_LEVEL_IDX
|
#ifdef AOM_CTRL_AV1E_GET_TARGET_SEQ_LEVEL_IDX
|
||||||
[AV1E_GET_TARGET_SEQ_LEVEL_IDX] = "AV1E_GET_TARGET_SEQ_LEVEL_IDX",
|
[AV1E_GET_TARGET_SEQ_LEVEL_IDX] = "AV1E_GET_TARGET_SEQ_LEVEL_IDX",
|
||||||
#endif
|
#endif
|
||||||
|
[AV1_GET_NEW_FRAME_IMAGE] = "AV1_GET_NEW_FRAME_IMAGE",
|
||||||
};
|
};
|
||||||
|
|
||||||
static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc)
|
static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc)
|
||||||
|
@ -364,6 +367,31 @@ static av_cold int codecctl_intp(AVCodecContext *avctx,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static av_cold int codecctl_imgp(AVCodecContext *avctx,
|
||||||
|
#ifdef UENUM1BYTE
|
||||||
|
aome_enc_control_id id,
|
||||||
|
#else
|
||||||
|
enum aome_enc_control_id id,
|
||||||
|
#endif
|
||||||
|
struct aom_image *img)
|
||||||
|
{
|
||||||
|
AOMContext *ctx = avctx->priv_data;
|
||||||
|
char buf[80];
|
||||||
|
int res;
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]);
|
||||||
|
|
||||||
|
res = aom_codec_control(&ctx->encoder, id, img);
|
||||||
|
if (res != AOM_CODEC_OK) {
|
||||||
|
snprintf(buf, sizeof(buf), "Failed to get %s codec control",
|
||||||
|
ctlidstr[id]);
|
||||||
|
log_encoder_error(avctx, buf);
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static av_cold int aom_free(AVCodecContext *avctx)
|
static av_cold int aom_free(AVCodecContext *avctx)
|
||||||
{
|
{
|
||||||
AOMContext *ctx = avctx->priv_data;
|
AOMContext *ctx = avctx->priv_data;
|
||||||
|
@ -1206,6 +1234,37 @@ static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out)
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum AVPixelFormat aomfmt_to_pixfmt(struct aom_image *img)
|
||||||
|
{
|
||||||
|
switch (img->fmt) {
|
||||||
|
case AOM_IMG_FMT_I420:
|
||||||
|
case AOM_IMG_FMT_I42016:
|
||||||
|
if (img->bit_depth == 8)
|
||||||
|
return img->monochrome ? AV_PIX_FMT_GRAY8 : AV_PIX_FMT_YUV420P;
|
||||||
|
else if (img->bit_depth == 10)
|
||||||
|
return img->monochrome ? AV_PIX_FMT_GRAY10 : AV_PIX_FMT_YUV420P10;
|
||||||
|
else
|
||||||
|
return img->monochrome ? AV_PIX_FMT_GRAY12 : AV_PIX_FMT_YUV420P12;
|
||||||
|
case AOM_IMG_FMT_I422:
|
||||||
|
case AOM_IMG_FMT_I42216:
|
||||||
|
if (img->bit_depth == 8)
|
||||||
|
return AV_PIX_FMT_YUV422P;
|
||||||
|
else if (img->bit_depth == 10)
|
||||||
|
return AV_PIX_FMT_YUV422P10;
|
||||||
|
else
|
||||||
|
return AV_PIX_FMT_YUV422P12;
|
||||||
|
case AOM_IMG_FMT_I444:
|
||||||
|
case AOM_IMG_FMT_I44416:
|
||||||
|
if (img->bit_depth == 8)
|
||||||
|
return AV_PIX_FMT_YUV444P;
|
||||||
|
else if (img->bit_depth == 10)
|
||||||
|
return AV_PIX_FMT_YUV444P10;
|
||||||
|
else
|
||||||
|
return AV_PIX_FMT_YUV444P12;
|
||||||
|
};
|
||||||
|
return AV_PIX_FMT_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
static int aom_encode(AVCodecContext *avctx, AVPacket *pkt,
|
static int aom_encode(AVCodecContext *avctx, AVPacket *pkt,
|
||||||
const AVFrame *frame, int *got_packet)
|
const AVFrame *frame, int *got_packet)
|
||||||
{
|
{
|
||||||
|
@ -1259,6 +1318,43 @@ static int aom_encode(AVCodecContext *avctx, AVPacket *pkt,
|
||||||
}
|
}
|
||||||
|
|
||||||
*got_packet = !!coded_size;
|
*got_packet = !!coded_size;
|
||||||
|
|
||||||
|
if (*got_packet && avctx->flags & AV_CODEC_FLAG_RECON_FRAME) {
|
||||||
|
AVCodecInternal *avci = avctx->internal;
|
||||||
|
struct aom_image img;
|
||||||
|
|
||||||
|
av_frame_unref(avci->recon_frame);
|
||||||
|
|
||||||
|
res = codecctl_imgp(avctx, AV1_GET_NEW_FRAME_IMAGE, &img);
|
||||||
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
avci->recon_frame->format = aomfmt_to_pixfmt(&img);
|
||||||
|
if (avci->recon_frame->format == AV_PIX_FMT_NONE) {
|
||||||
|
av_log(ctx, AV_LOG_ERROR,
|
||||||
|
"Unhandled reconstructed frame colorspace: %d\n",
|
||||||
|
img.fmt);
|
||||||
|
return AVERROR(ENOSYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
avci->recon_frame->width = img.d_w;
|
||||||
|
avci->recon_frame->height = img.d_h;
|
||||||
|
|
||||||
|
res = av_frame_get_buffer(avci->recon_frame, 0);
|
||||||
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if ((img.fmt & AOM_IMG_FMT_HIGHBITDEPTH) && img.bit_depth == 8)
|
||||||
|
ff_aom_image_copy_16_to_8(avci->recon_frame, &img);
|
||||||
|
else {
|
||||||
|
const uint8_t *planes[4] = { img.planes[0], img.planes[1], img.planes[2] };
|
||||||
|
const int stride[4] = { img.stride[0], img.stride[1], img.stride[2] };
|
||||||
|
|
||||||
|
av_image_copy(avci->recon_frame->data, avci->recon_frame->linesize, planes,
|
||||||
|
stride, avci->recon_frame->format, img.d_w, img.d_h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1434,6 +1530,7 @@ FFCodec ff_libaom_av1_encoder = {
|
||||||
.p.type = AVMEDIA_TYPE_VIDEO,
|
.p.type = AVMEDIA_TYPE_VIDEO,
|
||||||
.p.id = AV_CODEC_ID_AV1,
|
.p.id = AV_CODEC_ID_AV1,
|
||||||
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
|
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
|
||||||
|
AV_CODEC_CAP_ENCODER_RECON_FRAME |
|
||||||
AV_CODEC_CAP_OTHER_THREADS,
|
AV_CODEC_CAP_OTHER_THREADS,
|
||||||
.p.profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles),
|
.p.profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles),
|
||||||
.p.priv_class = &class_aom,
|
.p.priv_class = &class_aom,
|
||||||
|
|
Loading…
Reference in New Issue