You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	avcodec/libaomenc: support AV_CODEC_CAP_ENCODER_RECON_FRAME
Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
		| @@ -1055,8 +1055,8 @@ OBJS-$(CONFIG_ALAC_AT_ENCODER)            += audiotoolboxenc.o | ||||
| OBJS-$(CONFIG_ILBC_AT_ENCODER)            += audiotoolboxenc.o | ||||
| OBJS-$(CONFIG_PCM_ALAW_AT_ENCODER)        += audiotoolboxenc.o | ||||
| OBJS-$(CONFIG_PCM_MULAW_AT_ENCODER)       += audiotoolboxenc.o | ||||
| OBJS-$(CONFIG_LIBAOM_AV1_DECODER)         += libaomdec.o | ||||
| OBJS-$(CONFIG_LIBAOM_AV1_ENCODER)         += libaomenc.o | ||||
| OBJS-$(CONFIG_LIBAOM_AV1_DECODER)         += libaomdec.o libaom.o | ||||
| OBJS-$(CONFIG_LIBAOM_AV1_ENCODER)         += libaomenc.o libaom.o | ||||
| OBJS-$(CONFIG_LIBARIBB24_DECODER)         += libaribb24.o ass.o | ||||
| OBJS-$(CONFIG_LIBCELT_DECODER)            += libcelt_dec.o | ||||
| OBJS-$(CONFIG_LIBCODEC2_DECODER)          += libcodec2.o | ||||
|   | ||||
							
								
								
									
										49
									
								
								libavcodec/libaom.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								libavcodec/libaom.c
									
									
									
									
									
										Normal file
									
								
							| @@ -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++; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										33
									
								
								libavcodec/libaom.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								libavcodec/libaom.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 "codec_internal.h" | ||||
| #include "internal.h" | ||||
| #include "libaom.h" | ||||
| #include "profiles.h" | ||||
|  | ||||
| typedef struct AV1DecodeContext { | ||||
| @@ -60,30 +61,6 @@ static av_cold int aom_init(AVCodecContext *avctx, | ||||
|     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 | ||||
| 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); | ||||
|  | ||||
|         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 { | ||||
|             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] }; | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user