summaryrefslogtreecommitdiff
path: root/libavcodec/libaomenc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/libaomenc.c')
-rw-r--r--libavcodec/libaomenc.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c
index b792226744..1fd69d59a7 100644
--- a/libavcodec/libaomenc.c
+++ b/libavcodec/libaomenc.c
@@ -31,6 +31,7 @@
#include "libavutil/base64.h"
#include "libavutil/common.h"
#include "libavutil/cpu.h"
+#include "libavutil/imgutils.h"
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
@@ -41,6 +42,7 @@
#include "codec_internal.h"
#include "encode.h"
#include "internal.h"
+#include "libaom.h"
#include "packet_internal.h"
#include "profiles.h"
@@ -208,6 +210,7 @@ static const char *const ctlidstr[] = {
#ifdef AOM_CTRL_AV1E_GET_TARGET_SEQ_LEVEL_IDX
[AV1E_GET_TARGET_SEQ_LEVEL_IDX] = "AV1E_GET_TARGET_SEQ_LEVEL_IDX",
#endif
+ [AV1_GET_NEW_FRAME_IMAGE] = "AV1_GET_NEW_FRAME_IMAGE",
};
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
+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)
{
AOMContext *ctx = avctx->priv_data;
@@ -1206,6 +1234,37 @@ static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out)
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,
const AVFrame *frame, int *got_packet)
{
@@ -1259,6 +1318,43 @@ static int aom_encode(AVCodecContext *avctx, AVPacket *pkt,
}
*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;
}
@@ -1434,6 +1530,7 @@ FFCodec ff_libaom_av1_encoder = {
.p.type = AVMEDIA_TYPE_VIDEO,
.p.id = AV_CODEC_ID_AV1,
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
+ AV_CODEC_CAP_ENCODER_RECON_FRAME |
AV_CODEC_CAP_OTHER_THREADS,
.p.profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles),
.p.priv_class = &class_aom,