On 1/18/2018 3:37 PM, Thilo Borgmann wrote: > From 0386c9e0a4c2ea1579378807ff5a7a04c508c50e Mon Sep 17 00:00:00 2001 > From: Thilo Borgmann <thilo.borgm...@mail.de> > Date: Wed, 17 Jan 2018 23:13:53 +0100 > Subject: [PATCH 2/3] Add codec wrapper for librv11 > > --- > MAINTAINERS | 1 + > configure | 8 + > libavcodec/Makefile | 2 + > libavcodec/allcodecs.c | 2 + > libavcodec/avcodec.h | 1 + > libavcodec/codec_desc.c | 7 + > libavcodec/librv11.h | 55 ++++ > libavcodec/librv11dec.c | 367 ++++++++++++++++++++++++ > libavcodec/librv11enc.c | 735 > ++++++++++++++++++++++++++++++++++++++++++++++++ > libavcodec/version.h | 2 +- > 10 files changed, 1179 insertions(+), 1 deletion(-) > create mode 100644 libavcodec/librv11.h > create mode 100644 libavcodec/librv11dec.c > create mode 100644 libavcodec/librv11enc.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index e583926..0067986 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -192,6 +192,7 @@ Codecs: > libkvazaar.c Arttu Ylä-Outinen > libopenjpeg.c Jaikrishnan Menon > libopenjpegenc.c Michael Bradshaw > + librv11* Thilo Borgmann, Qiang Luo > libtheoraenc.c David Conrad > libvorbis.c David Conrad > libvpx* James Zern > diff --git a/configure b/configure > index 5d53362..1c27852 100755 > --- a/configure > +++ b/configure > @@ -250,6 +250,8 @@ External library support: > --enable-librsvg enable SVG rasterization via librsvg [no] > --enable-librubberband enable rubberband needed for rubberband filter > [no] > --enable-librtmp enable RTMP[E] support via librtmp [no] > + --disable-librv11dec enable RV11 decoding via rv11 [autodetect] > + --disable-librv11enc enable RV11 encoding via rv11 [autodetect]
Single librv11 entry, please. > --enable-libshine enable fixed-point MP3 encoding via libshine [no] > --enable-libsmbclient enable Samba protocol via libsmbclient [no] > --enable-libsnappy enable Snappy compression, needed for hap > encoding [no] > @@ -1535,6 +1537,8 @@ EXTERNAL_AUTODETECT_LIBRARY_LIST=" > bzlib > coreimage > iconv > + librv11enc > + librv11dec This needs to be in EXTERNAL_LIBRARY_LIST, not in EXTERNAL_AUTODETECT_LIBRARY_LIST. Also as i said above as a single entry. > libxcb > libxcb_shm > libxcb_shape > @@ -2959,6 +2963,8 @@ libopus_decoder_deps="libopus" > libopus_encoder_deps="libopus" > libopus_encoder_select="audio_frame_queue" > librsvg_decoder_deps="librsvg" > +librv11dec_decoder_deps="librv11dec" > +librv11enc_encoder_deps="librv11enc" librv11_decoder_deps="librv11" librv11_encoder_deps="librv11" > libshine_encoder_deps="libshine" > libshine_encoder_select="audio_frame_queue" > libspeex_decoder_deps="libspeex" > @@ -5890,6 +5896,8 @@ enabled libpulse && require_pkg_config > libpulse libpulse pulse/pulseaud > enabled librsvg && require_pkg_config librsvg librsvg-2.0 > librsvg-2.0/librsvg/rsvg.h rsvg_handle_render_cairo > enabled librtmp && require_pkg_config librtmp librtmp > librtmp/rtmp.h RTMP_Socket > enabled librubberband && require_pkg_config librubberband "rubberband >= > 1.8.1" rubberband/rubberband-c.h rubberband_new -lstdc++ && append > librubberband_extralibs "-lstdc++" > +enabled librv11enc && require_pkg_config librv11 librv11 > librv11_sdk.h fpinit > +enabled librv11dec && require_pkg_config librv11 librv11 > librv11_sdk.h fpinit As is, these checks are not really enabling either of these two modules, but a currently nonexistant one called librv11. The only reason it worked like this is because you had them in the autodetect list above. enabled librv11 && require_pkg_config librv11 librv11 librv11_sdk.h fpinit > enabled libshine && require_pkg_config libshine shine > shine/layer3.h shine_encode_buffer > enabled libsmbclient && { check_pkg_config libsmbclient smbclient > libsmbclient.h smbc_init || > require libsmbclient libsmbclient.h smbc_init > -lsmbclient; } > diff --git a/libavcodec/Makefile b/libavcodec/Makefile > index cfacd6b..2e32815 100644 > --- a/libavcodec/Makefile > +++ b/libavcodec/Makefile > @@ -948,6 +948,8 @@ OBJS-$(CONFIG_LIBOPUS_DECODER) += libopusdec.o > libopus.o \ > vorbis_data.o > OBJS-$(CONFIG_LIBOPUS_ENCODER) += libopusenc.o libopus.o \ > vorbis_data.o > +OBJS-$(CONFIG_LIBRV11DEC_DECODER) += librv11dec.o > +OBJS-$(CONFIG_LIBRV11ENC_ENCODER) += librv11enc.o OBJS-$(CONFIG_LIBRV11_DECODER) += librv11dec.o OBJS-$(CONFIG_LIBRV11_ENCODER) += librv11enc.o > OBJS-$(CONFIG_LIBSHINE_ENCODER) += libshine.o > OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o > OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o > diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c > index ed1e7ab..8eb8610 100644 > --- a/libavcodec/allcodecs.c > +++ b/libavcodec/allcodecs.c > @@ -548,6 +548,8 @@ static void register_all(void) > REGISTER_ENCDEC (LIBOPENJPEG, libopenjpeg); > REGISTER_ENCDEC (LIBOPUS, libopus); > REGISTER_DECODER(LIBRSVG, librsvg); > + REGISTER_DECODER(LIBRV11DEC, librv11dec); > + REGISTER_ENCODER(LIBRV11ENC, librv11enc); REGISTER_ENCDEC(LIBRV11, librv11) > REGISTER_ENCODER(LIBSHINE, libshine); > REGISTER_ENCDEC (LIBSPEEX, libspeex); > REGISTER_ENCODER(LIBTHEORA, libtheora); > diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h > index 8fbbc79..b7c1fa1 100644 > --- a/libavcodec/avcodec.h > +++ b/libavcodec/avcodec.h > @@ -409,6 +409,7 @@ enum AVCodecID { > AV_CODEC_ID_DXV, > AV_CODEC_ID_SCREENPRESSO, > AV_CODEC_ID_RSCC, > + AV_CODEC_ID_RV60, > > AV_CODEC_ID_Y41P = 0x8000, > AV_CODEC_ID_AVRP, > diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c > index c3688de..1ad2c9c 100644 > --- a/libavcodec/codec_desc.c > +++ b/libavcodec/codec_desc.c > @@ -471,6 +471,13 @@ static const AVCodecDescriptor codec_descriptors[] = { > .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER, > }, > { > + .id = AV_CODEC_ID_RV60, > + .type = AVMEDIA_TYPE_VIDEO, > + .name = "rv60", > + .long_name = NULL_IF_CONFIG_SMALL("RealVideo 11"), > + .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER, > + }, > + { > .id = AV_CODEC_ID_VC1, > .type = AVMEDIA_TYPE_VIDEO, > .name = "vc1", > diff --git a/libavcodec/librv11.h b/libavcodec/librv11.h > new file mode 100644 > index 0000000..44ec050 > --- /dev/null > +++ b/libavcodec/librv11.h > @@ -0,0 +1,55 @@ > +/* > + * This copyright notice applies to this file only > + * This Software is distributed under MIT License > + * > + * API software for using RealVideo 11 (RV60) Codec > + * > + * * Copyright (c) 2017 Qiang Luo, RealNetworks, Inc. <qluo _at_ > realnetworks.com> > + * * Copyright (c) 2017 Thilo Borgmann <thilo.borgmann _at_ mail.de> > + * > + * Permission is hereby granted, free of charge, to any person > + * obtaining a copy of this software and associated documentation > + * files (the "Software"), to deal in the Software without > + * restriction, including without limitation the rights to use, > + * copy, modify, merge, publish, distribute, sublicense, and/or sell > + * copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following > + * conditions: > + * > + * The above copyright notice and this permission notice shall be > + * included in all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, > + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES > + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND > + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT > + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, > + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR > + * OTHER DEALINGS IN THE SOFTWARE. > + */ > + > +#ifndef AVCODEC_LIBRV11_H > +#define AVCODEC_LIBRV11_H > + > +#include <librv11_sdk.h> > + > +#include "avcodec.h" > +#include "libavutil/intreadwrite.h" > + > +#ifdef _WIN32 > +#include "compat/w32dlfcn.h" > +#else > +#include <dlfcn.h> > +#endif > + > +#define RV_MAX_INPUT_FRAME_RATE 120 > +#define RV_NUM_OUT_FRAMES 6 > + > +#define XSTR(s) STR(s) > +#define STR(s) #s > +#define LIBRV11DEC_FILE XSTR(RV_DEC_LIB_FILE) > +#define LIBRV11ENC_FILE XSTR(RV_ENC_LIB_FILE) > + > + > +#endif // AVCODEC_LIBRV11_H > diff --git a/libavcodec/librv11dec.c b/libavcodec/librv11dec.c > new file mode 100644 > index 0000000..269d684 > --- /dev/null > +++ b/libavcodec/librv11dec.c > @@ -0,0 +1,367 @@ > +/* > + * This copyright notice applies to this file only > + * This Software is distributed under MIT License > + * > + * API software for using RealVideo 11 (RV60) Decoder > + * > + * * Copyright (c) 2017 Qiang Luo, RealNetworks, Inc. <qluo _at_ > realnetworks.com> > + * * Copyright (c) 2017 Thilo Borgmann <thilo.borgmann _at_ mail.de> > + * > + * Permission is hereby granted, free of charge, to any person > + * obtaining a copy of this software and associated documentation > + * files (the "Software"), to deal in the Software without > + * restriction, including without limitation the rights to use, > + * copy, modify, merge, publish, distribute, sublicense, and/or sell > + * copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following > + * conditions: > + * > + * The above copyright notice and this permission notice shall be > + * included in all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, > + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES > + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND > + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT > + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, > + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR > + * OTHER DEALINGS IN THE SOFTWARE. > + */ > + > +#include "libavutil/imgutils.h" > +#include "internal.h" > +#include "get_bits.h" > + > +#include "librv11.h" > + > +typedef struct DecFnTable > +{ > + FPINIT init; > + FPFREE free; > + FPTRANSFORM transform; > + FPCUSTOMMSG custom_message; > + FPHIVEMSG hive_message; > +} DecFnTable; > + > +typedef struct LIBRV11DecContext { > + AVCodecContext *avctx; > + AVFrame out_frame; > + void *lib_handle; > + DecFnTable *symbols; > + void *codec_status; > + uint32_t input_buf_size; > + uint32_t input_buf_num; > + uint32_t output_buf_size; > + uint32_t output_buf_num; > + uint8_t *output_buf[RV_NUM_OUT_FRAMES]; > + int frame_index; > + uint32_t last_frame; > + uint32_t more_frames; > +} LIBRV11DecContext; > + > +static av_cold int librv11dec_load_symbols(AVCodecContext *avctx) > +{ > + LIBRV11DecContext *ctx = avctx->priv_data; > + > + ctx->lib_handle = dlopen(LIBRV11DEC_FILE, RTLD_LAZY); > + if (!ctx->lib_handle) { > + av_log(avctx, AV_LOG_ERROR, "Cannot load dynamic library.\n"); > + return AVERROR_EXTERNAL; > + } > + > + ctx->symbols = av_mallocz(sizeof(DecFnTable)); > + if (!ctx->symbols) { > + av_log(avctx, AV_LOG_ERROR, "Cannot allocate symbol table.\n"); > + return AVERROR(ENOMEM); > + } > + > +#define LOAD_RV11_FUNC(handle, name) { \ > + ctx->symbols->handle = dlsym(ctx->lib_handle, name); \ > + if (!ctx->symbols->handle) { \ > + av_log(avctx, AV_LOG_ERROR, "Cannot load symbol %s.", name); \ > + return AVERROR_EXTERNAL; \ > + } \ > +} > + > + LOAD_RV11_FUNC(init, RV_CODEC_INIT); > + LOAD_RV11_FUNC(free, RV_CODEC_FREE); > + LOAD_RV11_FUNC(transform, RV_CODEC_TRANSFORM); > + LOAD_RV11_FUNC(custom_message, RV_CODEC_CUSTOM_MSG); > + LOAD_RV11_FUNC(hive_message, RV_CODEC_HIVE_MSG); > + > + return 0; > +} This should be linked at compile time. > + > +static av_cold int librv11dec_init(AVCodecContext *avctx) > +{ > + LIBRV11DecContext *ctx = avctx->priv_data; > + GetBitContext gb; > + RVInitParams init_params; > + RVMsgSimple msg; > + HX_RESULT res; > + uint32_t SPO_extra_flags; > + uint32_t version; > + int i; > + ctx->avctx = avctx; > + > + if (!avctx->extradata || !avctx->extradata_size) { > + return AVERROR_INVALIDDATA; > + } > + > + init_get_bits(&gb, avctx->extradata, avctx->extradata_size * 8); > + > + SPO_extra_flags = get_bits_long(&gb, 32); > + version = get_bits_long(&gb, 32); Use bytestream2 instead if you're reading full bytes. Or just AV_RB32() and not bother with these APIs. > + > + res = librv11dec_load_symbols(avctx); > + if (res) { > + av_freep(&ctx->symbols); > + return res; > + } > + > + init_params.out_type = 0; > + init_params.width = avctx->width; > + init_params.height = avctx->height; > + init_params.pad_width = avctx->width; > + init_params.pad_height = avctx->height; > + init_params.pad_to_32 = 0; > + init_params.invariants = SPO_extra_flags; > + init_params.packetize = 1; > + init_params.version = version; > + > + res = ctx->symbols->init(&init_params, &ctx->codec_status); > + if (res) { > + av_free(ctx->symbols); > + return res; > + } > + > + msg.id = RV_MSG_ID_SMOOTHING_POSTFILTER; > + msg.value1 = RV_MSG_DISABLE; > + msg.value2 = 0; > + > + res = ctx->symbols->custom_message(&msg.id, ctx->codec_status); > + if (res) { > + return res; > + } > + > + avctx->pix_fmt = AV_PIX_FMT_YUV420P; > + ctx->last_frame = 0; > + ctx->more_frames = 0; > + ctx->frame_index = 0; > + > + ctx->output_buf_size = (avctx->width * avctx->height * 12) >> 3; > + for(i = 0; i < RV_NUM_OUT_FRAMES; i++) { > + ctx->output_buf[i] = av_mallocz(ctx->output_buf_size); > + } > + av_image_fill_arrays(ctx->out_frame.data, ctx->out_frame.linesize, > ctx->output_buf[0], AV_PIX_FMT_YUV420P, avctx->width, avctx->height, 1); > + > + return 0; > +} > + > +static int librv11dec_decode_last(AVCodecContext *avctx, void *data, > + int *got_frame, AVPacket *avpkt) > +{ > + LIBRV11DecContext* ctx = avctx->priv_data; > + AVFrame *pict = data; > + const int stride = avctx->width * avctx->height; > + RVInParams inParams; > + RVOutParams outParams; > + int32_t ret; > + > + inParams.length = 0; > + inParams.interpolate = 0; > + inParams.num_segments = 0; > + inParams.segments = NULL; > + inParams.timestamp = 0; > + inParams.flags = RV_DECODE_MORE_FRAMES; > + > + pict->data[0] = ctx->output_buf[ctx->frame_index]; > + pict->data[1] = ctx->output_buf[ctx->frame_index] + stride; > + pict->data[2] = ctx->output_buf[ctx->frame_index] + stride + (stride >> > 2); > + > + pict->linesize[0] = avctx->width; > + pict->linesize[1] = avctx->width >> 1; > + pict->linesize[2] = avctx->width >> 1; > + > + ret = ctx->symbols->transform(NULL, ctx->output_buf[ctx->frame_index], > &inParams, &outParams, ctx->codec_status); > + if (ret) { > + *got_frame = 0; > + return ret; > + } > + > + if(outParams.notes & RV_DECODE_LAST_FRAME) { > + ctx->last_frame = 1; > + } > + > + pict->pts = outParams.timestamp; > +#if FF_API_PKT_PTS > +FF_DISABLE_DEPRECATION_WARNINGS > + pict->pkt_pts = avpkt->pts; > +FF_ENABLE_DEPRECATION_WARNINGS > +#endif > + pict->pkt_dts = avpkt->dts; No need for this, it's the default behavior and handled by AVCodec->decode2 when FF_CODEC_CAP_SETS_PKT_DTS is not set. > + pict->width = avctx->width; > + pict->height = avctx->height; > + pict->format = AV_PIX_FMT_YUV420P; > + pict->key_frame = 0; > + pict->pict_type = AV_PICTURE_TYPE_P; > + > + if (outParams.notes & RV_DECODE_KEY_FRAME) { > + pict->key_frame = 1; > + pict->pict_type = AV_PICTURE_TYPE_I; > + } else if (outParams.notes & RV_DECODE_B_FRAME || > + outParams.notes & RV_DECODE_FRU_FRAME) { > + pict->key_frame = 0; > + pict->pict_type = AV_PICTURE_TYPE_B; > + } > + > + *got_frame = !(outParams.notes & RV_DECODE_DONT_DRAW); > + > + return 0; > + > +} > + > +static int librv11dec_decode_frame(AVCodecContext *avctx, void *data, > + int *got_frame, AVPacket *avpkt) > +{ > + LIBRV11DecContext* ctx = avctx->priv_data; > + const uint8_t *buf = avpkt->data; > + int buf_size = avpkt->size; > + const int stride = avctx->width * avctx->height; > + AVFrame *pict = data; > + int slice_count = 0; > + int consumed_bytes = 0; > + RVSegment *segment = NULL; > + RVInParams inParams; > + RVOutParams outParams; > + int32_t ret; > + int i; > + > + ret = ff_get_buffer(avctx, pict, 0); > + if (ret < 0) { > + return ret; > + } > + > + ctx->frame_index++; > + ctx->frame_index %= RV_NUM_OUT_FRAMES; > + > + if (!buf_size) { // maybe last frame > + if (ctx->last_frame) { > + *got_frame = 0; > + return 0; > + } else { > + return librv11dec_decode_last(avctx, data, got_frame, avpkt); > + } > + } > + > + if (!avctx->slice_count) { > + slice_count = (*buf++) + 1; > + segment = av_mallocz(slice_count * sizeof(RVSegment)); > + for (i = 0; i < slice_count; i++) { > + segment[i].is_valid = *buf; > + segment[i].offset = *(buf + 4); > + buf += 8; > + } > + buf_size -= 1 + 8 * slice_count; > + } else { > + slice_count = avctx->slice_count; > + } > + > + inParams.length = buf_size; > + inParams.interpolate = 0; > + inParams.num_segments = slice_count - 1; > + inParams.segments = segment; > + inParams.timestamp = avpkt->pts; > + inParams.flags = 0; > + > + pict->data[0] = ctx->output_buf[ctx->frame_index]; > + pict->data[1] = ctx->output_buf[ctx->frame_index] + stride; > + pict->data[2] = ctx->output_buf[ctx->frame_index] + stride + (stride >> > 2); > + pict->linesize[0] = avctx->width; > + pict->linesize[1] = avctx->width >> 1; > + pict->linesize[2] = avctx->width >> 1; > + > + ret = ctx->symbols->transform((UCHAR*)buf, > ctx->output_buf[ctx->frame_index], &inParams, &outParams, ctx->codec_status); > + if (ret) { > + consumed_bytes = 0; > + *got_frame = 0; > + return ret; > + } > + > + if (slice_count) { > + av_freep(&segment); > + } > + > + consumed_bytes = avpkt->size; > + *got_frame = 1; > + pict->key_frame = 0; > + pict->pict_type = AV_PICTURE_TYPE_P; > + > + if (outParams.notes & RV_DECODE_KEY_FRAME) { > + pict->pict_type = AV_PICTURE_TYPE_I; > + pict->key_frame = 1; > + } else if (outParams.notes & RV_DECODE_B_FRAME || > + outParams.notes & RV_DECODE_FRU_FRAME) { > + pict->pict_type = AV_PICTURE_TYPE_B; > + } else if (outParams.notes & RV_DECODE_DONT_DRAW) { > + consumed_bytes = 0; > + *got_frame = 0; > + } > + > + pict->pts = outParams.timestamp; > +#if FF_API_PKT_PTS > +FF_DISABLE_DEPRECATION_WARNINGS > + pict->pkt_pts = avpkt->pts; > +FF_ENABLE_DEPRECATION_WARNINGS > +#endif > + pict->pkt_dts = avpkt->dts; Same. _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel