From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTP id 2ED564C093 for ; Sun, 21 Jul 2024 22:54:12 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id BB2AF68D770; Mon, 22 Jul 2024 01:53:59 +0300 (EEST) Received: from mail-pf1-f174.google.com (mail-pf1-f174.google.com [209.85.210.174]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id AC14168D553 for ; Mon, 22 Jul 2024 01:53:51 +0300 (EEST) Received: by mail-pf1-f174.google.com with SMTP id d2e1a72fcca58-70d2e68f5a8so69011b3a.3 for ; Sun, 21 Jul 2024 15:53:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1721602429; x=1722207229; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=FcFUWYCHnYGhg5h5cHFPEbx3B/SnSSXhINKetfr/LOk=; b=U9WGT24aB4p/BddZWFrzj78Jgk3VxbGB+HAvZLgazrzBxC6A4fkItpcpe3u/+jikp+ 7jGWlZewWDiM3gHsGUjT4PS4A+jAvkejpETZt+5v7yN4NKGNKuVayDahzY51745yx07+ 4B27xA97sQ/prT8AQO9sHzQc30mOlTxHflTH33rx7p9vsS0yg+58ZC9FYrZt3cJQW1/x Ww7jB7j0kjb5wAXJ5lbxK1mw4L/9kMcj9Foi97ik5rWks4uoRfpRfqfxuc3BPG53aVI/ 1ZuIwUNmiUn05IZIxByQs2ZIuZXZhvPvtoukP5B92HykB30Upcj+eFTNcqplChmtG3Ov aS6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721602429; x=1722207229; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=FcFUWYCHnYGhg5h5cHFPEbx3B/SnSSXhINKetfr/LOk=; b=oyBYP0Wa8WDPEixgsgEEv44h4b09WSACBSmpg5JR0FZeyCieTE0KwTtjO/4a8ivcf8 uUoEA4cdkUoGWx6jGwyKcuLzdCX0Qg1XxXs9IHtDpVJnMBxS8OgtqnfHrkxZUh8k6dj3 uwJC22DP+bSS+yhcG2ZVEE+ojhHd9p8EAi9buBIKeBD9b9lWCkRIt4zCrxaIHOUesV+B 1oMR1/Zok1uCL8XWcQ0pRrL68nkBpN5IC9gO5wN0B4xwcwOBG3hSBjkNK1ONts0JI62Y VMNxJ4Xr8T9jwaR0nauX+g9o4ua6jvJWfnPv96FYRkiCHPmo7kKbkidc13j/xo3hVGkJ cGZw== X-Gm-Message-State: AOJu0Yz2kZRh/CNEwyxrUiVQA/YZJytNnPn2srXHYQklAD+56bT+P75n XTkX4XywP8BetWHkK9p19QfM0mlhbbI1uVx2cY5JoEbsWxfF3UNfDB48cQ== X-Google-Smtp-Source: AGHT+IGiMcodYRCeH3YJIzWz9kHDJFGgY9CZVj+6cwxjScfK/aFuExLxsf6NLShBlwdz8WSbpAbIcA== X-Received: by 2002:a05:6a00:2ea0:b0:70d:2e24:af75 with SMTP id d2e1a72fcca58-70d2e24bb7cmr663511b3a.24.1721602428810; Sun, 21 Jul 2024 15:53:48 -0700 (PDT) Received: from localhost.localdomain ([190.194.167.233]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-70cff5538f6sm4223710b3a.100.2024.07.21.15.53.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 21 Jul 2024 15:53:48 -0700 (PDT) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Sun, 21 Jul 2024 19:53:49 -0300 Message-ID: <20240721225350.298-3-jamrial@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240721225350.298-1-jamrial@gmail.com> References: <20240721225350.298-1-jamrial@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/4 v2] avcodec: add LCEVC decoding support via LCEVCdec X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: Signed-off-by: James Almer --- configure | 3 + doc/general_contents.texi | 13 ++ libavcodec/Makefile | 1 + libavcodec/lcevcdec.c | 276 ++++++++++++++++++++++++++++++++++++++ libavcodec/lcevcdec.h | 44 ++++++ 5 files changed, 337 insertions(+) create mode 100644 libavcodec/lcevcdec.c create mode 100644 libavcodec/lcevcdec.h diff --git a/configure b/configure index f6f5c29fea..d1f32684a6 100755 --- a/configure +++ b/configure @@ -225,6 +225,7 @@ External library support: --enable-libcdio enable audio CD grabbing with libcdio [no] --enable-libcodec2 enable codec2 en/decoding using libcodec2 [no] --enable-libdav1d enable AV1 decoding via libdav1d [no] + --enable-liblcevc_dec enable LCEVC decoding via liblcevc_dec [no] --enable-libdavs2 enable AVS2 decoding via libdavs2 [no] --enable-libdc1394 enable IIDC-1394 grabbing using libdc1394 and libraw1394 [no] @@ -1914,6 +1915,7 @@ EXTERNAL_LIBRARY_LIST=" libcelt libcodec2 libdav1d + liblcevc_dec libdc1394 libflite libfontconfig @@ -6854,6 +6856,7 @@ enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 && enabled libcaca && require_pkg_config libcaca caca caca.h caca_create_canvas enabled libcodec2 && require libcodec2 codec2/codec2.h codec2_create -lcodec2 enabled libdav1d && require_pkg_config libdav1d "dav1d >= 0.5.0" "dav1d/dav1d.h" dav1d_version +enabled liblcevc_dec && require_pkg_config liblcevc_dec "lcevc_dec >= 2.0.0" "LCEVC/lcevc_dec.h" LCEVC_CreateDecoder enabled libdavs2 && require_pkg_config libdavs2 "davs2 >= 1.6.0" davs2.h davs2_decoder_open enabled libdc1394 && require_pkg_config libdc1394 libdc1394-2 dc1394/dc1394.h dc1394_new enabled libdrm && check_pkg_config libdrm libdrm xf86drm.h drmGetVersion diff --git a/doc/general_contents.texi b/doc/general_contents.texi index e7cf4f8239..ecaf3979ce 100644 --- a/doc/general_contents.texi +++ b/doc/general_contents.texi @@ -245,6 +245,19 @@ Go to @url{https://github.com/google/liblc3/} and follow the instructions for installing the library. Then pass @code{--enable-liblc3} to configure to enable it. +@section LCEVCdec + +FFmpeg can make use of the liblcevc_dec library for LCEVC enhacement layer +decoding on supported bitstreams. + +Go to @url{https://github.com/v-novaltd/LCEVCdec} and follow the instructions +for installing the library. Then pass @code{--enable-libvpx} to configure to +enable it. + +@float NOTE +LCEVCdec is under the BSD-3-Clause-Clear License. +@end float + @section OpenH264 FFmpeg can make use of the OpenH264 library for H.264 decoding and encoding. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 771e2b597e..71bc3c8075 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -121,6 +121,7 @@ OBJS-$(CONFIG_INTRAX8) += intrax8.o intrax8dsp.o msmpeg4_vc1_dat OBJS-$(CONFIG_IVIDSP) += ivi_dsp.o OBJS-$(CONFIG_JNI) += ffjni.o jni.o OBJS-$(CONFIG_JPEGTABLES) += jpegtables.o +OBJS-$(CONFIG_LIBLCEVC_DEC) += lcevcdec.o OBJS-$(CONFIG_LCMS2) += fflcms2.o OBJS-$(CONFIG_LLAUDDSP) += lossless_audiodsp.o OBJS-$(CONFIG_LLVIDDSP) += lossless_videodsp.o diff --git a/libavcodec/lcevcdec.c b/libavcodec/lcevcdec.c new file mode 100644 index 0000000000..4edb0b72dc --- /dev/null +++ b/libavcodec/lcevcdec.c @@ -0,0 +1,276 @@ +/* + * 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 "libavutil/avassert.h" +#include "libavutil/frame.h" +#include "libavutil/imgutils.h" +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "decode.h" +#include "lcevcdec.h" + +static LCEVC_ColorFormat map_format(int format) +{ + switch (format) { + case AV_PIX_FMT_YUV420P: + return LCEVC_I420_8; + case AV_PIX_FMT_YUV420P10: + return LCEVC_I420_10_LE; + case AV_PIX_FMT_NV12: + return LCEVC_NV12_8; + case AV_PIX_FMT_NV21: + return LCEVC_NV21_8; + case AV_PIX_FMT_GRAY8: + return LCEVC_GRAY_8; + } + + return LCEVC_ColorFormat_Unknown; +} + +static int alloc_base_frame(void *logctx, LCEVC_DecoderHandle decoder, + const AVFrame *frame, LCEVC_PictureHandle *picture) +{ + LCEVC_PictureDesc desc; + LCEVC_ColorFormat fmt = map_format(frame->format); + LCEVC_PictureLockHandle lock; + uint8_t *data[4] = { NULL }; + int linesizes[4] = { 0 }; + uint32_t planes; + LCEVC_ReturnCode res; + + res = LCEVC_DefaultPictureDesc(&desc, fmt, frame->width, frame->height); + if (res != LCEVC_Success) + return AVERROR_EXTERNAL; + + desc.cropTop = frame->crop_top; + desc.cropBottom = frame->crop_bottom; + desc.cropLeft = frame->crop_left; + desc.cropRight = frame->crop_right; + desc.sampleAspectRatioNum = frame->sample_aspect_ratio.num; + desc.sampleAspectRatioDen = frame->sample_aspect_ratio.den; + + /* Allocate LCEVC Picture */ + res = LCEVC_AllocPicture(decoder, &desc, picture); + if (res != LCEVC_Success) + return AVERROR_EXTERNAL; + + res = LCEVC_LockPicture(decoder, *picture, LCEVC_Access_Write, &lock); + if (res != LCEVC_Success) + return AVERROR_EXTERNAL; + + res = LCEVC_GetPicturePlaneCount(decoder, *picture, &planes); + if (res != LCEVC_Success) + return AVERROR_EXTERNAL; + + for (unsigned i = 0; i < planes; i++) { + LCEVC_PicturePlaneDesc plane; + + res = LCEVC_GetPictureLockPlaneDesc(decoder, lock, i, &plane); + if (res != LCEVC_Success) + return AVERROR_EXTERNAL; + + data[i] = plane.firstSample; + linesizes[i] = plane.rowByteStride; + } + + av_image_copy2(data, linesizes, frame->data, frame->linesize, + frame->format, frame->width, frame->height); + + res = LCEVC_UnlockPicture(decoder, lock); + if (res != LCEVC_Success) + return AVERROR_EXTERNAL; + + return 0; +} + +static int alloc_enhanced_frame(void *logctx, LCEVC_DecoderHandle decoder, + const AVFrame *frame, LCEVC_PictureHandle *picture) +{ + LCEVC_PictureDesc desc ; + LCEVC_ColorFormat fmt = map_format(frame->format); + LCEVC_PicturePlaneDesc planes[4] = { 0 }; + int width = frame->width * 2 / FFMAX(frame->sample_aspect_ratio.den, 1); + int height = frame->height * 2 / FFMAX(frame->sample_aspect_ratio.num, 1); + LCEVC_ReturnCode res; + + res = LCEVC_DefaultPictureDesc(&desc, fmt, width, height); + if (res != LCEVC_Success) + return AVERROR_EXTERNAL; + + /* Set plane description */ + for (int i = 0; i < 4; i++) { + planes[i].firstSample = frame->data[i]; + planes[i].rowByteStride = frame->linesize[i]; + } + + /* Allocate LCEVC Picture */ + res = LCEVC_AllocPictureExternal(decoder, &desc, NULL, planes, picture); + if (res != LCEVC_Success) + return AVERROR_EXTERNAL; + + return 0; +} + +int ff_lcevc_send_frame(void *logctx, FFLCEVCContext *lcevc, const AVFrame *in) +{ + const AVFrameSideData *sd = av_frame_get_side_data(in, AV_FRAME_DATA_LCEVC); + LCEVC_PictureHandle picture; + LCEVC_ReturnCode res; + int ret = 0; + + if (!sd) + return 0; + + res = LCEVC_SendDecoderEnhancementData(lcevc->decoder, in->pts, 0, sd->data, sd->size); + if (res != LCEVC_Success) + return AVERROR_EXTERNAL; + + ret = alloc_base_frame(logctx, lcevc->decoder, in, &picture); + if (ret < 0) + return ret; + + res = LCEVC_SendDecoderBase(lcevc->decoder, in->pts, 0, picture, -1, NULL); + if (res != LCEVC_Success) + return AVERROR_EXTERNAL; + + memset(&picture, 0, sizeof(picture)); + ret = alloc_enhanced_frame(logctx, lcevc->decoder, in, &picture); + if (ret < 0) + return ret; + + res = LCEVC_SendDecoderPicture(lcevc->decoder, picture); + if (res != LCEVC_Success) + return AVERROR_EXTERNAL; + + return 0; +} + +static int generate_output(void *logctx, FFLCEVCContext *lcevc, AVFrame *out) +{ + LCEVC_PictureDesc desc; + LCEVC_DecodeInformation info; + LCEVC_PictureHandle picture; + LCEVC_ReturnCode res; + + res = LCEVC_ReceiveDecoderPicture(lcevc->decoder, &picture, &info); + if (res != LCEVC_Success) + return AVERROR_EXTERNAL; + + res = LCEVC_GetPictureDesc(lcevc->decoder, picture, &desc); + if (res != LCEVC_Success) + return AVERROR_EXTERNAL; + + out->crop_top = desc.cropTop; + out->crop_bottom = desc.cropBottom; + out->crop_left = desc.cropLeft; + out->crop_right = desc.cropRight; + out->sample_aspect_ratio.num = desc.sampleAspectRatioNum; + out->sample_aspect_ratio.den = desc.sampleAspectRatioDen; + out->width = desc.width + out->crop_left + out->crop_right; + out->height = desc.height + out->crop_top + out->crop_bottom; + + return 0; +} + +int ff_lcevc_receive_frame(void *logctx, FFLCEVCContext *lcevc, AVFrame *out) +{ + LCEVC_PictureHandle picture; + LCEVC_ReturnCode res; + int ret; + + ret = generate_output(logctx, lcevc, out); + if (ret < 0) + return ret; + + res = LCEVC_ReceiveDecoderBase (lcevc->decoder, &picture); + if (res != LCEVC_Success) + return AVERROR_EXTERNAL; + + res = LCEVC_FreePicture(lcevc->decoder, picture); + if (res != LCEVC_Success) + return AVERROR_EXTERNAL; + + return 0; +} + +int ff_lcevc_process(void *logctx, AVFrame *frame) +{ + FrameDecodeData *fdd = (FrameDecodeData*)frame->private_ref->data; + AVBufferRef *ref = (AVBufferRef*)fdd->post_process_opaque; + FFLCEVCContext *lcevc = (FFLCEVCContext*)ref->data; + int ret; + + ret = ff_lcevc_send_frame(logctx, lcevc, frame); + if (ret < 0) + return ret; + + ff_lcevc_receive_frame(logctx, lcevc, frame); + if (ret < 0) + return ret; + + return 0; +} + +static void event_callback(LCEVC_DecoderHandle dec, LCEVC_Event event, + LCEVC_PictureHandle pic, const LCEVC_DecodeInformation *info, + const uint8_t *data, uint32_t size, void *logctx) +{ + switch (event) { + case LCEVC_Log: + av_log(logctx, AV_LOG_INFO, "%s\n", data); + break; + default: + break; + } +} + +int ff_lcevc_init(FFLCEVCContext *lcevc, void *logctx) +{ + LCEVC_AccelContextHandle dummy = { 0 }; + + int32_t events[] = { LCEVC_Log }; + + if (LCEVC_CreateDecoder(&lcevc->decoder, dummy) != LCEVC_Success) { + av_log(logctx, AV_LOG_ERROR, "Failed to create LCEVC decoder\n"); + return AVERROR_EXTERNAL; + } + + LCEVC_ConfigureDecoderInt(lcevc->decoder, "log_level", 4); + LCEVC_ConfigureDecoderIntArray(lcevc->decoder, "events", FF_ARRAY_ELEMS(events), events); + LCEVC_SetDecoderEventCallback(lcevc->decoder, event_callback, logctx); + + if (LCEVC_InitializeDecoder(lcevc->decoder) != LCEVC_Success) { + av_log(logctx, AV_LOG_ERROR, "Failed to initialize LCEVC decoder\n"); + return AVERROR_EXTERNAL; + } + + return 0; +} + +void ff_lcevc_free(void *opaque, uint8_t *data) +{ + FFLCEVCContext *lcevc = opaque; + LCEVC_DestroyDecoder(lcevc->decoder); + av_free(data); +} + +void ff_lcevc_unref(void *opaque) +{ + AVBufferRef *ref = opaque; + av_buffer_unref(&ref); +} diff --git a/libavcodec/lcevcdec.h b/libavcodec/lcevcdec.h new file mode 100644 index 0000000000..fe105371d3 --- /dev/null +++ b/libavcodec/lcevcdec.h @@ -0,0 +1,44 @@ +/* + * 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 + */ + +#ifndef AVCODEC_LCEVCDEC_H +#define AVCODEC_LCEVCDEC_H + +#include "config_components.h" + +#include +#if CONFIG_LIBLCEVC_DEC +#include +#else +typedef uintptr_t LCEVC_DecoderHandle; +#endif + +typedef struct FFLCEVCContext { + LCEVC_DecoderHandle decoder; +} FFLCEVCContext; + +struct AVFrame; + +int ff_lcevc_process(void *logctx, struct AVFrame *frame); +int ff_lcevc_send_frame(void *logctx, FFLCEVCContext *lcevc, const AVFrame *in); +int ff_lcevc_receive_frame(void *logctx, FFLCEVCContext *lcevc, AVFrame *out); +int ff_lcevc_init(FFLCEVCContext *lcevc, void *logctx); +void ff_lcevc_unref(void *opaque); +void ff_lcevc_free(void *opaque, uint8_t *data); + +#endif /* AVCODEC_LCEVCDEC_H */ -- 2.45.2 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".