Discussion:
[FFmpeg-devel] [PATCH 0/3] Codec wrapper for librv11 and RMHD muxer/demuxer
Thilo Borgmann
2018-01-18 18:36:13 UTC
Permalink
Hi,

Realnetworks released Linux libraries for their encoder/decoder of RealVideo 11 (RV60) [1].
This is a joint approach to add a codec wrapper and suport muxing/demuxing of the latest real format version (RMHD).

I'd especially appreciate feedback on the handling of the PTS/DTS which IMHO is not what I think it should look like - there are non-monotonous pts returned and I think changes to ffmpeg.c are unnecessary. I could not be of much help with that yet and hope for some hints from someone who knows that stuff better than me.

When linking the binaries I got a "warning: multiple common of 'fpinit'". Not sure if there is something wrong with what I did in configure/make or if it is caused by the declaration in the installed header alone.

I split it up in separate patches for easier review only, non-functional if applied separately. Will be stashed after review or split in a sane way.

The codec comes in two separate binaries for en/decoding, so I did the same split in the code. I will add tests to FATE after review. If we'd prefer to have a sample for that which is not synthetic, I might ask them to forge a real small-sized sample for us to add to the fate-suite. I already tested successfully with private real-world test samples not created by this patchset.

Thanks,
Thilo
Thilo Borgmann
2018-01-18 18:37:21 UTC
Permalink
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-***@ffmpeg.org
http://ffmpeg.o
Thilo Borgmann
2018-01-18 18:39:07 UTC
Permalink
This time including the patch...
Carl Eugen Hoyos
2018-01-18 20:04:04 UTC
Permalink
Post by Thilo Borgmann
This time including the patch...
Why do you add a new demuxer?
Isn't it sufficient to add the new descriptor (with AV_RB32()) to the
existing probe function?

Please split this patch:
From a (very) quick look, I saw:
Demuxing MLTI, muxing aac, muxing RV30 and friends, some
fixes wrt version (all apart from RV60).
Please add a few comments where it currently says "unknown".
I suspect no new muxer should be added (but I may miss something).

Carl Eugen
Michael Niedermayer
2018-01-19 00:02:41 UTC
Permalink
Post by Thilo Borgmann
This time including the patch...
fftools/ffmpeg.c | 28 +++
fftools/ffmpeg_opt.c | 2
libavformat/Makefile | 2
libavformat/allformats.c | 1
libavformat/rm.c | 1
libavformat/rm.h | 7
libavformat/rmdec.c | 96 +++++++++--
libavformat/rmenc.c | 395 ++++++++++++++++++++++++++++++++++++++---------
libavformat/utils.c | 5
9 files changed, 438 insertions(+), 99 deletions(-)
b65cfa6fc05b6199324118ef1b40d9737cd70272 0001-Add-muxing-demuxing-of-RMHD.patch
From aaeaf7721ba5e9afd79ee13dbb9cc7c3226027b3 Mon Sep 17 00:00:00 2001
Date: Wed, 17 Jan 2018 23:09:03 +0100
Subject: [PATCH 1/3] Add muxing/demuxing of RMHD
This is missing AV_CODEC_ID_RV60

src/libavformat/rm.c:37:7: error: ‘AV_CODEC_ID_RV60’ undeclared here (not in a function)
{ AV_CODEC_ID_RV60, MKTAG('R','V','6','0') },
^
make: *** [libavformat/rm.o] Error 1
make: *** Waiting for unfinished jobs....
src/libavformat/rmenc.c: In function ‘rv10_write_header’:
src/libavformat/rmenc.c:189:48: error: ‘AV_CODEC_ID_RV60’ undeclared (first use in this function)
stream->par->codec_id == AV_CODEC_ID_RV60) {
^
src/libavformat/rmenc.c:189:48: note: each undeclared identifier is reported only once for each function it appears in
src/libavformat/rmenc.c: In function ‘rm_write_video’:
src/libavformat/rmenc.c:538:34: error: ‘AV_CODEC_ID_RV60’ undeclared (first use in this function)
stream->par->codec_id == AV_CODEC_ID_RV60) {
^
src/libavformat/rmenc.c: At top level:
src/libavformat/rmenc.c:723:20: error: ‘AV_CODEC_ID_RV60’ undeclared here (not in a function)
.video_codec = AV_CODEC_ID_RV60,
^
make: *** [libavformat/rmenc.o] Error 1

[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

If you drop bombs on a foreign country and kill a hundred thousand
innocent people, expect your government to call the consequence
"unprovoked inhuman terrorist attacks" and use it to justify dropping
more bombs and killing more people. The technology changed, the idea is old.
Thilo Borgmann
2018-01-19 12:39:31 UTC
Permalink
Post by Michael Niedermayer
Post by Thilo Borgmann
This time including the patch...
fftools/ffmpeg.c | 28 +++
fftools/ffmpeg_opt.c | 2
libavformat/Makefile | 2
libavformat/allformats.c | 1
libavformat/rm.c | 1
libavformat/rm.h | 7
libavformat/rmdec.c | 96 +++++++++--
libavformat/rmenc.c | 395 ++++++++++++++++++++++++++++++++++++++---------
libavformat/utils.c | 5
9 files changed, 438 insertions(+), 99 deletions(-)
b65cfa6fc05b6199324118ef1b40d9737cd70272 0001-Add-muxing-demuxing-of-RMHD.patch
From aaeaf7721ba5e9afd79ee13dbb9cc7c3226027b3 Mon Sep 17 00:00:00 2001
Date: Wed, 17 Jan 2018 23:09:03 +0100
Subject: [PATCH 1/3] Add muxing/demuxing of RMHD
This is missing AV_CODEC_ID_RV60
Patches are not made to be applyable on their own. If that is the only thing
missing I might move it to 1/3.

Thanks for all the feedback by now, I'll update the patches as soon as I can!

-Thilo
Michael Niedermayer
2018-01-19 17:16:01 UTC
Permalink
Post by Thilo Borgmann
Post by Michael Niedermayer
Post by Thilo Borgmann
This time including the patch...
fftools/ffmpeg.c | 28 +++
fftools/ffmpeg_opt.c | 2
libavformat/Makefile | 2
libavformat/allformats.c | 1
libavformat/rm.c | 1
libavformat/rm.h | 7
libavformat/rmdec.c | 96 +++++++++--
libavformat/rmenc.c | 395 ++++++++++++++++++++++++++++++++++++++---------
libavformat/utils.c | 5
9 files changed, 438 insertions(+), 99 deletions(-)
b65cfa6fc05b6199324118ef1b40d9737cd70272 0001-Add-muxing-demuxing-of-RMHD.patch
From aaeaf7721ba5e9afd79ee13dbb9cc7c3226027b3 Mon Sep 17 00:00:00 2001
Date: Wed, 17 Jan 2018 23:09:03 +0100
Subject: [PATCH 1/3] Add muxing/demuxing of RMHD
This is missing AV_CODEC_ID_RV60
Patches are not made to be applyable on their own. If that is the only thing
missing I might move it to 1/3.
code must build after each commit when its pushed.
so if the patches represent future commits 1:1 then please move what is needed
so it builds

thx

[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Complexity theory is the science of finding the exact solution to an
approximation. Benchmarking OTOH is finding an approximation of the exact
Moritz Barsnick
2018-01-19 20:45:44 UTC
Permalink
Post by Michael Niedermayer
Post by Thilo Borgmann
Patches are not made to be applyable on their own. If that is the only thing
missing I might move it to 1/3.
code must build after each commit when its pushed.
so if the patches represent future commits 1:1 then please move what is needed
so it builds
I split it up in separate patches for easier review only,
non-functional if applied separately. Will be stashed after review or
split in a sane way.
Moritz
Michael Niedermayer
2018-01-19 22:38:21 UTC
Permalink
Post by Michael Niedermayer
Post by Thilo Borgmann
Patches are not made to be applyable on their own. If that is the only thing
missing I might move it to 1/3.
code must build after each commit when its pushed.
so if the patches represent future commits 1:1 then please move what is needed
so it builds
I split it up in separate patches for easier review only,
non-functional if applied separately. Will be stashed after review or
split in a sane way.
and i didnt fully read the intro mail it seems ...

[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Elect your leaders based on what they did after the last election, not
based on what they say before an election.
Thilo Borgmann
2018-01-18 18:37:54 UTC
Permalink
From 0386c9e0a4c2ea1579378807ff5a7a04c508c50e Mon Sep 17 00:00:00 2001
From: Thilo Borgmann <***@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]
--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
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"
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
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_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_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;
+}
+
+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);
+
+ 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;
+ 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;
+ pict->width = avctx->width;
+ pict->height = avctx->height;
+ pict->format = AV_PIX_FMT_YUV420P;
+
+ return consumed_bytes;
+}
+
+static av_cold int librv11dec_close(AVCodecContext *avctx)
+{
+ LIBRV11DecContext* ctx = avctx->priv_data;
+ int i;
+
+ ctx->symbols->free(ctx->codec_status);
+ dlclose(ctx->lib_handle);
+
+ if (ctx->symbols) {
+ av_freep(&ctx->symbols);
+ }
+
+ for(i = 0; i < RV_NUM_OUT_FRAMES; i++) {
+ if (ctx->output_buf[i]) {
+ av_freep(&ctx->output_buf[i]);
+ }
+ }
+
+ return 0;
+}
+
+static void librv11dec_flush(AVCodecContext *avctx)
+{
+ LIBRV11DecContext* ctx = avctx->priv_data;
+ if (ctx->symbols) {
+ uint32_t id = RV_MSG_ID_FLUSH;
+ ctx->symbols->hive_message(&id, ctx->codec_status);
+ }
+}
+
+AVCodec ff_librv11dec_decoder = {
+ .name = "librv11dec",
+ .long_name = NULL_IF_CONFIG_SMALL("librv11dec RealVideo 11 (RV60)"),
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_RV60,
+ .priv_data_size = sizeof(LIBRV11DecContext),
+ .init = librv11dec_init,
+ .decode = librv11dec_decode_frame,
+ .close = librv11dec_close,
+ .flush = librv11dec_flush,
+ .capabilities = AV_CODEC_CAP_DELAY,
+};
diff --git a/libavcodec/librv11enc.c b/libavcodec/librv11enc.c
new file mode 100644
index 0000000..231a768
--- /dev/null
+++ b/libavcodec/librv11enc.c
@@ -0,0 +1,735 @@
+/*
+ * This copyright notice applies to this file only
+ * This Software is distributed under MIT License
+ *
+ * API software for using RealVideo 11 (RV60) Encoder
+ *
+ * * 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 "libavutil/opt.h"
+
+#include "librv11.h"
+
+typedef struct EncFnTable
+{
+ FPCODECOPEN Codec_Open;
+ FPCODECCLOSE Codec_Close;
+ FPCODECINPUT Codec_Input;
+ FPCODECSTREAMOPEN Codec_StreamOpen;
+ FPCODECGETHYPERPROPERTY Codec_GetHyperProperty;
+ FPSTREAMCLOSE Stream_Close;
+ FPSTREAMSETDATACALLBACK Stream_SetDataCallback;
+ FPSTREAMGETSTREAMHEADER Stream_GetStreamHeader;
+ FPSTREAMINPUT Stream_Input;
+ FPSTREAMSETOUTPUTPACKETSIZE Stream_SetOutputPacketSize;
+ FPSTREAMGETPROPERTY Stream_GetProperty;
+ FPSTREAMSETPROPERTY Stream_SetProperty;
+ FPSTREAMPOSTPROCESS Stream_PostProcess;
+ FPSTREAMRELEASEFRAME Stream_ReleaseFrame;
+ FPCODECGETUINAME Codec_GetUIName;
+ FPCODECQUERYMEDIAFORMAT Codec_QueryMediaFormat;
+ FPCODECSETPROPERTY Codec_SetProperty;
+} EncFnTable;
+
+typedef struct CodedFrameList {
+ AVPacket pkt;
+ struct CodedFrameList* pNext;
+} CodedFrameList;
+
+typedef struct FrameRatioConverter {
+ uint32_t count;
+ double framerate;
+ uint8_t* selected_map;
+ uint32_t framerate_in;
+} FrameRatioConverter;
+
+typedef struct LIBRV11EncContext
+{
+ AVClass *class;
+ void *lib_handle;
+ EncFnTable *symbols;
+ void *codec_ref;
+ void *stream_ref;
+ RVEncodeParam rvenc_param;
+ uint32_t codec_4cc;
+ uint32_t frame_size;
+ uint8_t* frame_buf;
+ CodedFrameList* coded_frame_list;
+ int bitrate_vbr; ///< 0:VBRQuality, 1:VBRBitrate
+ int eos; ///< set to TURE when input frame was set to NULL
+ int last_packet; ///< set to 1 when the last codec frame was popped out
+ FrameRatioConverter fr_convert;
+ uint32_t video_mode;
+} LIBRV11EncContext;
+
+static int32_t interval_search(uint8_t *buf, const uint32_t buf_size, const uint32_t num_frames)
+{
+ if (buf_size < num_frames || !num_frames) {
+ return -1;
+ }
+
+ if (!(buf_size % num_frames)) {
+ uint32_t i;
+ const uint32_t den = buf_size / num_frames;
+
+ for(i = 0; i < buf_size; i++) {
+ if (!((i+1) % den)) {
+ buf[i] = 1;
+ }
+ }
+ } else {
+ const uint32_t half = buf_size >> 1;
+ const uint32_t left = num_frames >> 1;
+ const uint32_t right = left + (num_frames & 1);
+
+ interval_search(buf, half, left);
+ interval_search(buf + half, buf_size - half, right);
+ }
+
+ return 0;
+}
+
+static av_cold int32_t fr_convert_init(FrameRatioConverter* fr_convert, double fr_in, double fr_max)
+{
+ if (fr_in < fr_max || fr_in > RV_MAX_INPUT_FRAME_RATE) {
+ return -1;
+ }
+
+ fr_convert->count = 0;
+ fr_convert->framerate = fr_max;
+ fr_convert->framerate_in = (int32_t)(fr_in + 0.5);
+ fr_convert->selected_map = av_mallocz(fr_convert->framerate_in);
+
+ return interval_search(fr_convert->selected_map, fr_convert->framerate_in, (int32_t)(fr_max + 0.5));
+}
+
+static av_always_inline int32_t use_frame(FrameRatioConverter *fr_convert)
+{
+ return fr_convert->selected_map[fr_convert->count];
+}
+
+static void next_frame(FrameRatioConverter* fr_convert)
+{
+ fr_convert->count++;
+ if (fr_convert->count >= fr_convert->framerate_in) {
+ fr_convert->count = 0;
+ }
+}
+
+static void coded_frame_add(void *list, CodedFrameList *cx_frame)
+{
+ CodedFrameList **p = list;
+
+ while(*p) {
+ p = &(*p)->pNext;
+ }
+
+ *p = cx_frame;
+ cx_frame->pNext = NULL;
+}
+
+static CodedFrameList* coded_frame_remove_header(CodedFrameList** list)
+{
+ CodedFrameList *p = *list;
+
+ if (p) {
+ *list = p->pNext;
+ }
+
+ return p;
+}
+
+static av_cold void free_coded_frame(CodedFrameList *cx_frame)
+{
+ av_packet_unref(&cx_frame->pkt);
+ av_freep(&cx_frame);
+}
+
+static av_cold void free_frame_list(CodedFrameList *list)
+{
+ CodedFrameList *p = list;
+
+ while(p) {
+ list = list->pNext;
+ free_coded_frame(p);
+ p = list;
+ }
+}
+
+static int librv11_num_segments(uint32_t data_length)
+{
+ int num_packet;
+
+ if (data_length < 1) {
+ return -1;
+ }
+
+ num_packet = data_length / RV_MAX_PACKET_SIZE;
+ if (data_length % RV_MAX_PACKET_SIZE) {
+ num_packet++;
+ }
+
+ return num_packet;
+}
+
+static int librv11_write_frame_header(uint8_t *data, int num_packet)
+{
+ int i;
+
+ if (num_packet < 1 || !data) {
+ return -1;
+ }
+
+ data[0] = num_packet -1;
+
+ for (i = 0; i < num_packet; i++) {
+ // the value of next 4 byte is the segment index
+ AV_WL32(data + 1 + 8 * i, i + 1);
+ // continuous 4 byte is the segment offset
+ AV_WL32(data + 5 + 8 * i, RV_MAX_PACKET_SIZE * i);
+ }
+
+ return 0;
+}
+
+static av_cold int CC librv11enc_data_callback(void *stream_ctx, void *stream_ref, HXCodecData* data)
+{
+ int ret = 0;
+ AVCodecContext *avctx = (AVCodecContext*) stream_ctx;
+ LIBRV11EncContext *enctx = avctx->priv_data;
+
+ if (data && data->length) {
+ int numPackets = 0;
+ int bufLength;
+
+ CodedFrameList* node = av_mallocz(sizeof(CodedFrameList));
+ if (!node) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to allocate memory.\n");
+ return AVERROR(ENOMEM);
+ }
+
+ // for rv11 num_segments should be 1
+ if (data->num_segments == 1) {
+ numPackets = librv11_num_segments(data->length);
+ if (numPackets > 127 || numPackets < 0) {
+ av_log(avctx, AV_LOG_WARNING, "Too many packets per frame (%d).\n", numPackets);
+ }
+ } else {
+ av_log(avctx, AV_LOG_WARNING, "Invalid number of segments (%u), should be 1.\n", data->num_segments);
+ }
+
+ // allocate extra numPackets*8+1 byte for real video head saving segment information
+ bufLength = data->length + numPackets * 8 + 1;
+ ret = av_new_packet(&node->pkt, bufLength);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to allocate packet.\n");
+ return ret;
+ }
+ librv11_write_frame_header(node->pkt.data, numPackets);
+ memcpy((node->pkt.data + numPackets * 8 + 1), data->data, data->length);
+
+ if (data->flags & HX_KEYFRAME_FLAG) {
+ node->pkt.flags |= AV_PKT_FLAG_KEY;
+ }
+
+ if (data->last_packet) {
+ node->pkt.flags |= RV_PKT_FLAG_END;
+ }
+
+ node->pkt.pts = data->timestamp * av_q2d(av_inv_q(avctx->time_base)) / 1000.0;
+ node->pkt.dts = data->timestamp;
+ coded_frame_add((void*)(&enctx->coded_frame_list), node);
+ }
+
+ return 0;
+}
+
+static av_cold int librv11enc_load_symbols(AVCodecContext *avctx)
+{
+ LIBRV11EncContext *enctx = avctx->priv_data;
+
+ enctx->lib_handle = dlopen(LIBRV11ENC_FILE, RTLD_LAZY);
+ if (!enctx->lib_handle) {
+ av_log(avctx, AV_LOG_ERROR, "Cannot load dynamic library.\n");
+ return AVERROR_EXTERNAL;
+ }
+
+ enctx->symbols = av_mallocz(sizeof(EncFnTable));
+ if (!enctx->symbols) {
+ av_log(avctx, AV_LOG_ERROR, "Cannot allocate symbol table.\n");
+ return AVERROR(ENOMEM);
+ }
+
+#define LOAD_RV11_FUNC(handle, name) { \
+ enctx->symbols->handle = dlsym(enctx->lib_handle, name); \
+ if (!enctx->symbols->handle) { \
+ av_log(avctx, AV_LOG_ERROR, "Cannot load symbol %s.", name); \
+ return AVERROR_EXTERNAL; \
+ } \
+}
+
+ LOAD_RV11_FUNC(Codec_Open, RV_CODEC_OPEN);
+ LOAD_RV11_FUNC(Codec_Close, RV_CODEC_CLOSE);
+ LOAD_RV11_FUNC(Codec_StreamOpen, RV_STREAM_OPEN);
+ LOAD_RV11_FUNC(Codec_GetHyperProperty, RV_CODEC_GET_HYPER_PROPERTY);
+ LOAD_RV11_FUNC(Stream_Close, RV_STREAM_CLOSE);
+ LOAD_RV11_FUNC(Stream_SetDataCallback, RV_STREAM_SET_DATACALLBACK);
+ LOAD_RV11_FUNC(Stream_GetStreamHeader, RV_STREAM_GET_STREAMHEADER);
+ LOAD_RV11_FUNC(Stream_Input, RV_STREAM_INPUT);
+ LOAD_RV11_FUNC(Stream_SetOutputPacketSize, RV_STREAM_SET_OUTPUTPACKETSIZE);
+ LOAD_RV11_FUNC(Stream_GetProperty, RV_STREAM_GET_PROPERTY);
+ LOAD_RV11_FUNC(Stream_SetProperty, RV_STREAM_SET_PROPERTY);
+ LOAD_RV11_FUNC(Codec_GetUIName, RV_CODEC_GET_UINAME);
+ LOAD_RV11_FUNC(Codec_Input, RV_CODEC_INPUT);
+ LOAD_RV11_FUNC(Codec_QueryMediaFormat, RV_CODEC_QUERY_MEDIAFORMAT);
+ LOAD_RV11_FUNC(Codec_SetProperty, RV_CODEC_SET_PROPERTY);
+
+ return 0;
+}
+
+static av_cold int librv11enc_init(AVCodecContext *avctx)
+{
+ LIBRV11EncContext *enctx = avctx->priv_data;
+ HX_RESULT res;
+ HXMof hxInput, hxOutput;
+ HXFormatVideo mofin, mofout;
+ HXCodecInit ci;
+ double framerate;
+ uint32_t dummy_ui32;
+ float dummy_f;
+
+ // Width and height of the video are required to be multiples of 4
+ if (avctx->width % 4 || avctx->height % 4) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Video dimensions have to be multiples of 4 (%dx%d).\n",
+ avctx->width, avctx->height);
+ return AVERROR(EINVAL);
+ }
+
+ res = librv11enc_load_symbols(avctx);
+ if (res) {
+ av_freep(&enctx->symbols);
+ return res;
+ }
+
+ res = enctx->symbols->Codec_QueryMediaFormat(NULL, &hxInput, &hxOutput, 0);
+ if (FAILED(res)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to query in/out formats.\n");
+ return AVERROR_EXTERNAL;
+ }
+
+ res = enctx->symbols->Codec_Open(hxOutput.submoftag, &enctx->codec_ref);
+ if (FAILED(res)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to open the codec library.\n");
+ return AVERROR_EXTERNAL;
+ }
+
+ enctx->codec_4cc = hxOutput.submoftag;
+
+ // init the librv11 encoder using default/user parameters
+ enctx->rvenc_param.in_width = avctx->width;
+ enctx->rvenc_param.in_height = avctx->height;
+
+ if (!enctx->rvenc_param.out_width) {
+ enctx->rvenc_param.out_width = avctx->width;
+ }
+ if (!enctx->rvenc_param.out_height) {
+ enctx->rvenc_param.out_height = avctx->height;
+ }
+
+ if (enctx->bitrate_vbr) {
+ enctx->rvenc_param.encode_type = ENCODE_VBR_BITRATE;
+ if (avctx->flags & AV_CODEC_FLAG_PASS1) {
+ enctx->rvenc_param.vbr_quality = 25;
+ }
+ } else {
+ enctx->rvenc_param.encode_type = ENCODE_VBR_QUALITY;
+ }
+
+ if (avctx->flags & AV_CODEC_FLAG_PASS1) {
+ enctx->rvenc_param.encode_mode = ENCODE_CREATE_ANALYSIS;
+ } else if (avctx->flags & AV_CODEC_FLAG_PASS2){
+ enctx->rvenc_param.encode_mode = ENCODE_USING_ANALYSIS;
+ } else {
+ enctx->rvenc_param.encode_mode = ENCODE_SINGLE_PASS;
+ }
+
+ enctx->rvenc_param.avg_bitrate = avctx->bit_rate;
+ enctx->rvenc_param.max_bitrate = enctx->rvenc_param.avg_bitrate;
+
+ enctx->rvenc_param.max_packet_size = RV_MAX_PACKET_SIZE;
+
+ if (!avctx->framerate.den) {
+ return AVERROR(EINVAL);
+ }
+ framerate = av_q2d(avctx->framerate);
+
+ res = fr_convert_init(&enctx->fr_convert, framerate, enctx->rvenc_param.max_framerate);
+ if (res) {
+ fr_convert_init(&enctx->fr_convert, framerate, framerate);
+ }
+
+ // set input parameters for I420
+ memset(&mofin, 0, sizeof(mofin));
+ mofin.length = sizeof(HXFormatVideo);
+ mofin.moftag = HX_MEDIA_VIDEO;
+ mofin.submoftag = HX_YUV420_ID;
+ mofin.width = enctx->rvenc_param.in_width;
+ mofin.height = enctx->rvenc_param.in_height;
+ mofin.bit_count = 12;
+ mofin.pad_width = 0;
+ mofin.pad_height = 0;
+ mofin.moftag = HX_MEDIA_VIDEO;
+
+ mofin.fps = (int)(enctx->fr_convert.framerate * (1L << 16) + 0.5);
+
+ // set output parameters
+ memset(&mofout, 0, sizeof(mofout));
+ mofout.length = sizeof(mofout);
+ mofout.moftag = HX_MEDIA_VIDEO;
+ mofout.submoftag = enctx->codec_4cc;
+ mofout.width = enctx->rvenc_param.out_width;
+ mofout.height = enctx->rvenc_param.out_height;
+ mofout.bit_count = mofin.bit_count;
+ mofout.pad_width = 0;
+ mofout.pad_height = 0;
+ mofout.moftag = HX_MEDIA_VIDEO;
+ mofout.fps = mofin.fps;
+
+ ci.in_mof = (HXMof*)&mofin;
+ ci.out_mof = (HXMof*)&mofout;
+ ci.mem_ptr = NULL;
+
+#define SET_RV11_PROP(prop, value) { \
+ res = enctx->symbols->Stream_SetProperty(enctx->stream_ref, prop, value); \
+ if (FAILED(res)) { \
+ av_log(avctx, AV_LOG_ERROR, "Failed to set property %s.\n", #prop); \
+ return AVERROR_EXTERNAL; \
+ } \
+}
+
+ res = enctx->symbols->Codec_StreamOpen(enctx->codec_ref, &enctx->stream_ref, &ci);
+ if (FAILED(res)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to open the stream.\n");
+ return AVERROR_EXTERNAL;
+ }
+
+ if (enctx->bitrate_vbr && !(avctx->flags & AV_CODEC_FLAG_PASS1)) {
+ SET_RV11_PROP(SP_BITRATE, &enctx->rvenc_param.avg_bitrate);
+ } else {
+ SET_RV11_PROP(SP_QUALITY, &enctx->rvenc_param.vbr_quality);
+ }
+
+ SET_RV11_PROP(SP_MAXBITRATE, &enctx->rvenc_param.max_bitrate);
+
+ dummy_f = (float)(enctx->rvenc_param.max_framerate);
+ SET_RV11_PROP(SP_MAX_FRAMERATE, &dummy_f);
+
+ dummy_ui32 = 0;
+ SET_RV11_PROP(SP_CHECK_FRAME_SKIP, &dummy_ui32);
+ SET_RV11_PROP(SP_QUALITY_MOTION, &enctx->video_mode);
+
+ dummy_ui32 = 0;
+ SET_RV11_PROP(SP_LIVE, &dummy_ui32);
+
+ dummy_ui32 = enctx->rvenc_param.max_keyint * 1000;
+ SET_RV11_PROP(SP_KEYFRAMERATE, &dummy_ui32);
+
+ SET_RV11_PROP(SP_ECC, &enctx->rvenc_param.loss_protect);
+ SET_RV11_PROP(SP_SET_FAST_LEVEL, &enctx->rvenc_param.enc_complexity);
+
+ dummy_ui32 = (uint32_t) enctx->rvenc_param.max_start_latency * 1000;
+ SET_RV11_PROP(SP_TARGET_LATENCY, &dummy_ui32);
+ SET_RV11_PROP(SP_RESIZING_ACCURACY, &enctx->rvenc_param.resize_quality);
+
+ if (enctx->rvenc_param.pon > 0) {
+ SET_RV11_PROP(SP_SET_PON_START, &enctx->rvenc_param.pon);
+ }
+
+ res = enctx->symbols->Stream_SetDataCallback(enctx->stream_ref, avctx, NULL, librv11enc_data_callback);
+ if (FAILED(res)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to set data callback.\n");
+ return AVERROR_EXTERNAL;
+ }
+
+ if (avctx->flags & AV_CODEC_FLAG_PASS1) {
+ dummy_ui32 = SPCODINGMODE_ANALYSIS;
+ } else if (avctx->flags & AV_CODEC_FLAG_PASS2) {
+ dummy_ui32 = SPCODINGMODE_FROMFILE;
+ } else {
+ dummy_ui32 = SPCODINGMODE_ENCODE;
+ }
+ SET_RV11_PROP(SP_CODING_MODE, &dummy_ui32);
+
+ // if vbr_opt is set to true the encoder can override bitrate settings to remain subjective quality.
+ // default is false
+ SET_RV11_PROP(SP_RATECONTROL_PLUS, &enctx->rvenc_param.vbr_opt);
+
+ if (avctx->flags & AV_CODEC_FLAG_PASS1 ||
+ avctx->flags & AV_CODEC_FLAG_PASS2) {
+ if (!enctx->rvenc_param.passlog_file) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid passlogfile.\n");
+ return AVERROR(EINVAL);
+ }
+ SET_RV11_PROP(SP_ANALYSIS_FILENAME, (void*)enctx->rvenc_param.passlog_file);
+ }
+
+ dummy_ui32 = 1;
+ SET_RV11_PROP(SP_CODEC_SETUP_DONE, &dummy_ui32);
+
+ dummy_ui32 = enctx->rvenc_param.max_packet_size;
+ res = enctx->symbols->Stream_SetOutputPacketSize(enctx->stream_ref, dummy_ui32, dummy_ui32, &dummy_ui32);
+ if (FAILED(res)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to set output packet size (%u).\n", dummy_ui32);
+ return AVERROR(EINVAL);
+ }
+
+#if FF_API_CODED_FRAME
+FF_DISABLE_DEPRECATION_WARNINGS
+ avctx->coded_frame = av_frame_alloc();
+ if (!avctx->coded_frame) {
+ av_log(avctx, AV_LOG_ERROR, "Cannot allocate coded frame buffer.");
+ return AVERROR(ENOMEM);
+ }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+ enctx->frame_size = av_image_get_buffer_size(avctx->pix_fmt, avctx->width, avctx->height, 1);
+
+ enctx->frame_buf = av_malloc(enctx->frame_size);
+ if (!enctx->frame_buf) {
+ av_log(avctx, AV_LOG_ERROR, "Cannot allocate frame buffer.");
+ return AVERROR(ENOMEM);
+ }
+
+ if (!avctx->extradata_size) {
+ uint8_t *q;
+
+ avctx->extradata_size = 14;
+ avctx->extradata = av_mallocz(avctx->extradata_size);
+ if (!avctx->extradata) {
+ avctx->extradata_size = 0;
+ return AVERROR(ENOMEM);
+ }
+
+ q = avctx->extradata;
+ *q++ = 0x01; //spo_extra_flags
+ *q++ = 0x08;
+ *q++ = 0x10;
+ *q++ = 0x00;
+ *q++ = 0x40; //codec frontend version (NOT codec version!)
+ *q++ = 0x00;
+ *q++ = 0x00;
+ *q++ = 0x00;
+ enctx->symbols->Codec_GetHyperProperty(enctx->codec_ref, q);
+ }
+
+ return 0;
+}
+
+static int librv11enc_encode(AVCodecContext *avctx, AVPacket*pkt, const AVFrame* frame, int* got_packet)
+{
+ int ret = 0;
+ int nb;
+ HXCodecData cd;
+ HX_RESULT res;
+ LIBRV11EncContext *enctx = avctx->priv_data;
+ CodedFrameList* pCodedFrame;
+
+#define RETURN_PACKET(got_p, r) { \
+ *got_packet = got_p; \
+ return r; \
+}
+
+ if (!frame && enctx->last_packet) {
+ RETURN_PACKET(0, 0);
+ }
+
+ if (frame && enctx->frame_buf && enctx->frame_size > 0) {
+ if (use_frame(&enctx->fr_convert)) {
+ nb = av_image_copy_to_buffer(enctx->frame_buf, enctx->frame_size,
+ (const uint8_t * const *)frame->data,
+ frame->linesize, avctx->pix_fmt,
+ avctx->width, avctx->height, 1);
+ if (nb < 0) {
+ RETURN_PACKET(0, nb);
+ }
+
+ cd.data = enctx->frame_buf;
+ cd.length = enctx->frame_size;
+ cd.timestamp = frame->pts * 1000 * av_q2d(avctx->time_base);
+ cd.flags = (frame->pict_type == AV_PICTURE_TYPE_I) ? HX_KEYFRAME_FLAG : 0;
+ cd.last_packet = enctx->eos;
+ cd.num_segments = 1;
+ cd.segments[0].is_valid = 1;
+ cd.segments[0].segment_offset = 0;
+
+ res = enctx->symbols->Codec_Input(enctx->codec_ref, &cd);
+ if (FAILED(res)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to set input data.\n");
+ RETURN_PACKET(0, AVERROR_EXTERNAL);
+ }
+ }
+ next_frame(&enctx->fr_convert);
+ } else if (!frame && !enctx->eos) {
+ enctx->eos = 1;
+
+ cd.data = NULL;
+ cd.length = 0;
+ cd.timestamp = 0;
+ cd.flags = 0;
+ cd.last_packet = 1;
+ cd.num_segments = 1;
+ cd.segments[0].is_valid = 1;
+ cd.segments[0].segment_offset = 0;
+
+ res = enctx->symbols->Codec_Input(enctx->codec_ref, &cd);
+ if (FAILED(res)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to set input data.\n");
+ RETURN_PACKET(0, AVERROR_EXTERNAL);
+ }
+ }
+
+ pCodedFrame = coded_frame_remove_header(&enctx->coded_frame_list);
+ if (pCodedFrame) {
+ if (pCodedFrame->pkt.flags & RV_PKT_FLAG_END) {
+ pCodedFrame->pkt.flags &= ~RV_PKT_FLAG_END;
+ enctx->last_packet = 1;
+ }
+
+ ret = av_packet_ref(pkt, &pCodedFrame->pkt);
+ if (ret < 0) {
+ av_log(enctx, AV_LOG_INFO, "Failed to recieve frame reference.\n");
+ free_coded_frame(pCodedFrame);
+ RETURN_PACKET(0, ret);
+ } else {
+ pkt->pts = pCodedFrame->pkt.pts;
+ pkt->dts = pCodedFrame->pkt.dts;
+
+ if (pCodedFrame->pkt.flags&AV_PKT_FLAG_KEY) {
+ pkt->flags |= AV_PKT_FLAG_KEY;
+#if FF_API_CODED_FRAME
+FF_DISABLE_DEPRECATION_WARNINGS
+ avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ }
+ free_coded_frame(pCodedFrame);
+ RETURN_PACKET(1, 0);
+ }
+ }
+
+ *got_packet = 0;
+ return ret;
+}
+
+static av_cold int librv11enc_close(AVCodecContext *avctx)
+{
+ LIBRV11EncContext *enctx = avctx->priv_data;
+
+ enctx->symbols->Stream_Close(enctx->stream_ref);
+ enctx->symbols->Codec_Close(enctx->codec_ref);
+ enctx->stream_ref = NULL;
+ enctx->codec_ref = NULL;
+
+ dlclose(enctx->lib_handle);
+ free_frame_list(enctx->coded_frame_list);
+
+ av_freep(&enctx->frame_buf);
+ av_freep(&enctx->symbols);
+ av_freep(&enctx->fr_convert.selected_map);
+ av_freep(&avctx->extradata);
+
+#if FF_API_CODED_FRAME
+FF_DISABLE_DEPRECATION_WARNINGS
+ av_frame_free(&avctx->coded_frame);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+ return 0;
+}
+
+#define OFFSET(x) offsetof(LIBRV11EncContext, x)
+#define OFFSETP(x) offsetof(RVEncodeParam, x)
+#define OFFSETBASE OFFSET(rvenc_param)
+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
+
+static const AVOption options[] = {
+ { "is_lossprotect", "enable loss protection feature", OFFSETBASE+OFFSETP(loss_protect), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },
+ { "output_width", "video encoded frame output width", OFFSETBASE+OFFSETP(out_width), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 4096, VE },
+ { "output_height", "video encoded frame output height", OFFSETBASE+OFFSETP(out_height), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 4096, VE },
+ { "rc_strategy", "which ratecontrol method to be used", OFFSET(bitrate_vbr), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE, "rc_strategy" },
+ { "bitrate", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "rc_strategy" },
+ { "quality", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "rc_strategy" },
+ { "complexity", "encoding complexity", OFFSETBASE+OFFSETP(enc_complexity), AV_OPT_TYPE_INT, { .i64 = 75 }, 55, 85, VE, "complexity" },
+ { "verylow", "", 0, AV_OPT_TYPE_CONST, {.i64=55}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "complexity" },
+ { "low", "", 0, AV_OPT_TYPE_CONST, {.i64=65}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "complexity" },
+ { "medium", "", 0, AV_OPT_TYPE_CONST, {.i64=75}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "complexity" },
+ { "high", "", 0, AV_OPT_TYPE_CONST, {.i64=85}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "complexity" },
+ { "framerate", "max frame rate value", OFFSETBASE+OFFSETP(max_framerate), AV_OPT_TYPE_INT, { .i64 = RV_MAX_INPUT_FRAME_RATE }, 0, RV_MAX_INPUT_FRAME_RATE, VE },
+ { "resize_quality", "video encoded frame resize quality", OFFSETBASE+OFFSETP(resize_quality), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE, "resize_quality" },
+ { "high", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "resize_quality" },
+ { "fast", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "resize_quality" },
+ { "video_mode", "motion quality", OFFSET(video_mode), AV_OPT_TYPE_INT, { .i64 = 50 }, 1, 100, VE, "video_mode" },
+ { "normal", "", 0, AV_OPT_TYPE_CONST, {.i64= 50}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "video_mode" },
+ { "sharp", "", 0, AV_OPT_TYPE_CONST, {.i64= 1}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "video_mode" },
+ { "smooth", "", 0, AV_OPT_TYPE_CONST, {.i64=100}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "video_mode" },
+ { "max_keyint", "max keyframe interval", OFFSETBASE+OFFSETP(max_keyint), AV_OPT_TYPE_INT, { .i64 = 5 }, 0, 10, VE },
+ { "max_latency", "max video latency on start", OFFSETBASE+OFFSETP(max_start_latency), AV_OPT_TYPE_FLOAT, { .dbl = 4.0 }, 0.5, 60.0, VE },
+ { "vbrquality", "vbr quality value", OFFSETBASE+OFFSETP(vbr_quality), AV_OPT_TYPE_INT, { .i64 = 60 }, 0, 100, VE },
+ { "passlogfile", "filename for 2 pass encoding stats", OFFSETBASE+OFFSETP(passlog_file), AV_OPT_TYPE_STRING, { .str = "rv11passstats.log" }, 0, 0, VE },
+ { "pon", "picture order number", OFFSETBASE+OFFSETP(pon), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
+ { "vbr_opt", "vbr enabled", OFFSETBASE+OFFSETP(vbr_opt), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE, "vbr_opt" },
+ { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "vbr_opt" },
+ { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "vbr_opt" },
+ { "cpulow", "cpu low mode on/off", OFFSETBASE+OFFSETP(cpu_low), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
+ { NULL },
+};
+
+static const AVClass librv11enc_class = {
+ .class_name = "librv11enc",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+AVCodec ff_librv11enc_encoder = {
+ .name = "librv11enc",
+ .long_name = NULL_IF_CONFIG_SMALL("librv11enc RealVideo 11 (RV60)"),
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_RV60,
+ .priv_data_size = sizeof(LIBRV11EncContext),
+ .init = librv11enc_init,
+ .encode2 = librv11enc_encode,
+ .close = librv11enc_close,
+ .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS,
+ .pix_fmts = (const enum AVPixelFormat[]) {
+ AV_PIX_FMT_YUV420P,
+ AV_PIX_FMT_NONE
+ },
+ .priv_class = &librv11enc_class,
+};
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 47a15d5..1050f60 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -28,7 +28,7 @@
#include "libavutil/version.h"

#define LIBAVCODEC_VERSION_MAJOR 58
-#define LIBAVCODEC_VERSION_MINOR 9
+#define LIBAVCODEC_VERSION_MINOR 10
#define LIBAVCODEC_VERSION_MICRO 100

#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
--
2.9.3
Carl Eugen Hoyos
2018-01-18 20:07:16 UTC
Permalink
2018-01-18 19:37 GMT+01:00 Thilo Borgmann <***@mail.de>:

Needs non-free (and therefore cannot be auto-detected).
And please link at compile-time unless there are no
visible symbols except the lookup function.

Carl Eugen
James Almer
2018-01-18 20:16:23 UTC
Permalink
Post by Thilo Borgmann
From 0386c9e0a4c2ea1579378807ff5a7a04c508c50e Mon Sep 17 00:00:00 2001
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
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
--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.
Post by Thilo Borgmann
--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.
Post by Thilo Borgmann
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"
Post by Thilo Borgmann
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
Post by Thilo Borgmann
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
Post by Thilo Borgmann
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)
Post by Thilo Borgmann
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
+ *
+ * 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
+ *
+ * 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.
Post by Thilo Borgmann
+
+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.
Post by Thilo Borgmann
+
+ 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.
Post by Thilo Borgmann
+ 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.
Thilo Borgmann
2018-01-18 18:38:18 UTC
Permalink
Thilo Borgmann
2018-01-18 18:40:20 UTC
Permalink
Post by Thilo Borgmann
Realnetworks released Linux libraries for their encoder/decoder of RealVideo 11 (RV60) [1].
[1] http://www.rmhd.io
Thilo Borgmann
2018-02-02 02:29:58 UTC
Permalink
Hi,

V2 adapts to newest SDK beta 0.5 which exports all symbols and changed some behavior. Patchset now requires the beta_0_5 version download from: http://rmhd.io

Split into four patches now, should still be unusable if applied separately.

PTS issue and linker warning fixed.

Patch 1/4: Factored out all changes to the mux/demux for RMVB (file format version 1).
Patch 2/4: Adds RMHD (file format version 2) to the mux/demux, one demuxer
Patch 3/4: Adds librv11 codec wrapper (updated to beta_0_5)
Patch 4/4: Docs & Changelog

Some more details in the corresponding patch mails.

-Thilo
Thilo Borgmann
2018-02-02 02:43:49 UTC
Permalink
All of these should be valid for RMVB (file format version 1).

I have no .rm files to test these changes, only .rmhd ones. AAC muxing yet not included, requires file format version 2. However, if all muxer changes are applied, all existing FATE tests involving .rm muxing/demuxing pass for me.

-Thilo
Thilo Borgmann
2018-02-02 02:43:56 UTC
Permalink
Does not add a new demuxer anymore.
For the muxer I'm not sure it should be done - would require more logic to check for valid codec ids for both cases I think (like for AAC audio).

-Thilo
Carl Eugen Hoyos
2018-04-23 12:17:49 UTC
Permalink
Post by Thilo Borgmann
Does not add a new demuxer anymore.
Good, now please split the patches, the demuxer patches
look relatively easy to review.
Post by Thilo Borgmann
For the muxer I'm not sure it should be done - would require more logic to
check for valid codec ids for both cases I think (like for AAC audio).
Not sure I understand: Aren't all the functions identical for both muxers?

If easily avoidable, no new muxer should be added, Carl Eugen
Thilo Borgmann
2018-04-23 18:47:00 UTC
Permalink
Post by Carl Eugen Hoyos
Post by Thilo Borgmann
Does not add a new demuxer anymore.
Good, now please split the patches, the demuxer patches
look relatively easy to review.
Post by Thilo Borgmann
For the muxer I'm not sure it should be done - would require more logic to
check for valid codec ids for both cases I think (like for AAC audio).
Not sure I understand: Aren't all the functions identical for both muxers?
If easily avoidable, no new muxer should be added, Carl Eugen
Have you just answered to the wrong mail and your comments apply to [V3 PATCH 1/3]?

If so, please elaborate your expectations about a better way to split things.

-Thilo
Thilo Borgmann
2018-02-02 02:44:05 UTC
Permalink
Moved to non-free.
Symbols handled at compile time, no more dlsym fun.
Merged into one ENCDEC.

-Thilo
Thilo Borgmann
2018-02-02 02:44:18 UTC
Permalink
...

-Thilo
Thilo Borgmann
2018-04-22 21:14:13 UTC
Permalink
Hi,

V3 drops the MLTI part, no idea how it survived 02fff499362daedcdcb0a9cdd517257843600563 on our side...
Also dropped audio override, could not get a sample requiring it.

Adapted to current HEAD.

Thanks,
Thilo
Thilo Borgmann
2018-04-22 21:15:24 UTC
Permalink
-Thilo
Paul B Mahol
2018-04-22 21:44:58 UTC
Permalink
Post by Thilo Borgmann
-Thilo
To many changes, hard to track.
Thilo Borgmann
2018-04-23 18:48:44 UTC
Permalink
Post by Paul B Mahol
Post by Thilo Borgmann
-Thilo
To many changes, hard to track.
I assume this means you also prefer a more splitted patch?

-Thilo
Thilo Borgmann
2018-04-22 21:16:04 UTC
Permalink
-Thilo
Carl Eugen Hoyos
2018-04-23 12:21:12 UTC
Permalink
Post by Thilo Borgmann
+#include <dlfcn.h>
Why is this include needed?

Carl Eugen
Thilo Borgmann
2018-04-23 18:40:27 UTC
Permalink
Post by Carl Eugen Hoyos
Post by Thilo Borgmann
+#include <dlfcn.h>
Why is this include needed?
Not anymore, will remove locally.

-Thilo
Thilo Borgmann
2018-04-22 21:16:28 UTC
Permalink
-Thilo
Carl Eugen Hoyos
2018-04-23 12:18:41 UTC
Permalink
2018-04-22 23:16 GMT+02:00, Thilo Borgmann <***@mail.de>:

Why is this a separate patch?

Carl Eugen
Thilo Borgmann
2018-04-23 18:41:39 UTC
Permalink
Post by Carl Eugen Hoyos
Why is this a separate patch?
To make the git-work a bit easier - do you want it to be merged into the others, would it be sufficient to do that before pushing?

-Thilo
Paul B Mahol
2018-04-22 21:43:02 UTC
Permalink
Post by Thilo Borgmann
Hi,
V3 drops the MLTI part, no idea how it survived
02fff499362daedcdcb0a9cdd517257843600563 on our side...
Also dropped audio override, could not get a sample requiring it.
Adapted to current HEAD.
I'm strongly against applying this to our tree.
James Almer
2018-04-23 01:36:36 UTC
Permalink
Post by Paul B Mahol
Post by Thilo Borgmann
Hi,
V3 drops the MLTI part, no idea how it survived
02fff499362daedcdcb0a9cdd517257843600563 on our side...
Also dropped audio override, could not get a sample requiring it.
Adapted to current HEAD.
I'm strongly against applying this to our tree.
The de/muxing code can and should be applied as long as there are not
technical limitations. They are native code and depend on nothing external.

And regarding the decoder and encoder wrappers, you need to explain the
reasons for your hard NAK...
Thilo Borgmann
2018-04-23 18:43:42 UTC
Permalink
Post by James Almer
Post by Paul B Mahol
Post by Thilo Borgmann
Hi,
V3 drops the MLTI part, no idea how it survived
02fff499362daedcdcb0a9cdd517257843600563 on our side...
Also dropped audio override, could not get a sample requiring it.
Adapted to current HEAD.
I'm strongly against applying this to our tree.
The de/muxing code can and should be applied as long as there are not
technical limitations. They are native code and depend on nothing external.
And regarding the decoder and encoder wrappers, you need to explain the
reasons for your hard NAK...
Yes Paul please do, and while you're on it, please add your thoughts about making it good enough for our tree that come to your mind. I assume it is not RV11 or its library wrapper for itself you don't like to see pushed...

-Thilo
Ronald S. Bultje
2018-04-23 19:03:57 UTC
Permalink
Hi Thilo,

not expressing specific agreement or disagreement.
Post by James Almer
Post by James Almer
Post by Paul B Mahol
Post by Thilo Borgmann
Hi,
V3 drops the MLTI part, no idea how it survived
02fff499362daedcdcb0a9cdd517257843600563 on our side...
Also dropped audio override, could not get a sample requiring it.
Adapted to current HEAD.
I'm strongly against applying this to our tree.
The de/muxing code can and should be applied as long as there are not
technical limitations. They are native code and depend on nothing
external.
Post by James Almer
And regarding the decoder and encoder wrappers, you need to explain the
reasons for your hard NAK...
Yes Paul please do, and while you're on it, please add your thoughts about
making it good enough for our tree that come to your mind. I assume it is
not RV11 or its library wrapper for itself you don't like to see pushed...
So, let's take the hypothetical argument of the encoder. So, clearly, the
company ("they") offering that encoder makes money and would benefit
financially from seeing that encoder integrated with FFmpeg. Also, the
maintenance effort would fall entirely on the opensource community ("we").
For example, if we change API (big or small), we have to update their
wrapper. However, their encoder itself (not wrapper) is still
closed-source. So, it seems very one-sided in terms of who benefits at what
cost and to who.

My impression has always been that for opensource encoders, we were OK with
this trade-off (there is GPL vs. LGPL etc., but we make it work in a
variety of ways). For example, even though x264 is GPL, we (LGPL) are OK
with that, since GPL is still opensource, and for many end use cases, that
works out fine anyway. However, for closed-source encoders, Iv'e always
assumed that our default position is "no, thanks", and recommend these
companies to maintain their patchset out-of-tree, so the cost of updating
is on them, not us.

Hypothetically, again, let's say this patch (encoder wrapper, or even
decoder wrapper) went in, does that mean my companies' VP9 encoder wrapper
can go in also? What about commercial H264/HEVC encoders? (There's many of
them.) How do we decide which goes in if there's many and we don't know
their quality/speed at various use cases because we don't have access to
these under liberal licenses we are all comfortable with?

(No specific opinion intended, just putting a wider frame on the
discussion.)

Ronald
Thilo Borgmann
2018-04-23 20:45:11 UTC
Permalink
Hi,
Post by Ronald S. Bultje
not expressing specific agreement or disagreement.
Post by James Almer
Post by James Almer
Post by Paul B Mahol
Post by Thilo Borgmann
Hi,
V3 drops the MLTI part, no idea how it survived
02fff499362daedcdcb0a9cdd517257843600563 on our side...
Also dropped audio override, could not get a sample requiring it.
Adapted to current HEAD.
I'm strongly against applying this to our tree.
The de/muxing code can and should be applied as long as there are not
technical limitations. They are native code and depend on nothing
external.
Post by James Almer
And regarding the decoder and encoder wrappers, you need to explain the
reasons for your hard NAK...
Yes Paul please do, and while you're on it, please add your thoughts about
making it good enough for our tree that come to your mind. I assume it is
not RV11 or its library wrapper for itself you don't like to see pushed...
So, let's take the hypothetical argument of the encoder. So, clearly, the
company ("they") offering that encoder makes money and would benefit
financially from seeing that encoder integrated with FFmpeg. Also, the
maintenance effort would fall entirely on the opensource community ("we").
For example, if we change API (big or small), we have to update their
wrapper. However, their encoder itself (not wrapper) is still
closed-source. So, it seems very one-sided in terms of who benefits at what
cost and to who.
My impression has always been that for opensource encoders, we were OK with
this trade-off (there is GPL vs. LGPL etc., but we make it work in a
variety of ways). For example, even though x264 is GPL, we (LGPL) are OK
with that, since GPL is still opensource, and for many end use cases, that
works out fine anyway. However, for closed-source encoders, Iv'e always
assumed that our default position is "no, thanks", and recommend these
companies to maintain their patchset out-of-tree, so the cost of updating
is on them, not us.
Hypothetically, again, let's say this patch (encoder wrapper, or even
decoder wrapper) went in, does that mean my companies' VP9 encoder wrapper
can go in also? What about commercial H264/HEVC encoders? (There's many of
them.) How do we decide which goes in if there's many and we don't know
their quality/speed at various use cases because we don't have access to
these under liberal licenses we are all comfortable with?
(No specific opinion intended, just putting a wider frame on the
discussion.)
I totally see your point in us having to care for the wrapper if it is not out-of-tree. Also that this is or might easily be a financial saving for a company.

I don't see us having a maintenance burden that big to refuse such code just of that, though.
Of course, feeling "used" by a company to do "their" work adds to a negative impact. I added myself to be maintainer of that code in question and I don't feel that way (and no, I'm not on a permanent payroll of RealNetworks).

Thinking of code that is not getting the devotion of any maintainer - we just removed that code in the past and why should that not happen to a wrapper utilizing a commercial binary. A company who wanted such a wrapper and shows no further interest in maintaining suffers from removed support sooner or later. Which might raise their interested again, doesn't it?

From the users perspective I don't see why we don't have wrappers for a commercial codec. If the user wants to use it, why should we forbid such code. Having an out-of-tree repo to merge into the code for supporting such codec _is_ of course a way for the user to get it anyway. But from that only the users compiling & patching the code themselves are capable of doing so benefit - we lose sight of all others going that way.

Paul and Rostislav adding a concern about killing the project with it by supporting closed source solutions.
I don't get your big picture with that concern. I don't see how FFmpeg supporting external commercial codecs is a threat to our project. Please enlighten me and I'm serious about it. When I was asked about helping with such a wrapper for that library, my "natural" intention is to get FFmpeg support it if we don't have native or other support for that codec - to support every codec there is, which is one of our goals, isn't it?

I can't stress enough how seriously I want you to explain me your point of view. I'm doing a lot of things in the best interest of FFmpeg, I'm spending money in the name of the project, talking to a million different faces about it and if "go with an out-of-tree wrapper" is our opinion on that for a reason I want you to convince of that. Give me a call if you feel to, I mean it - I don't care much about a commercial flaming discussion nor do I want to make a point about the topic, I care about an important point I might not aware of so far. I benefit from getting this wrapper through review, however it is out of the question that no money in the world will bribe me to act against the best interest of FFmpeg. Convince me having such code is a really bad idea for the project and I will waive my whole effort for this case and maybe be better able to protect our project from such endeavors.

Thanks,
Thilo
Paul B Mahol
2018-04-23 20:47:50 UTC
Permalink
Post by Thilo Borgmann
Hi,
Post by Ronald S. Bultje
not expressing specific agreement or disagreement.
Post by James Almer
Post by James Almer
Post by Paul B Mahol
Post by Thilo Borgmann
Hi,
V3 drops the MLTI part, no idea how it survived
02fff499362daedcdcb0a9cdd517257843600563 on our side...
Also dropped audio override, could not get a sample requiring it.
Adapted to current HEAD.
I'm strongly against applying this to our tree.
The de/muxing code can and should be applied as long as there are not
technical limitations. They are native code and depend on nothing
external.
Post by James Almer
And regarding the decoder and encoder wrappers, you need to explain the
reasons for your hard NAK...
Yes Paul please do, and while you're on it, please add your thoughts about
making it good enough for our tree that come to your mind. I assume it is
not RV11 or its library wrapper for itself you don't like to see pushed...
So, let's take the hypothetical argument of the encoder. So, clearly, the
company ("they") offering that encoder makes money and would benefit
financially from seeing that encoder integrated with FFmpeg. Also, the
maintenance effort would fall entirely on the opensource community ("we").
For example, if we change API (big or small), we have to update their
wrapper. However, their encoder itself (not wrapper) is still
closed-source. So, it seems very one-sided in terms of who benefits at what
cost and to who.
My impression has always been that for opensource encoders, we were OK with
this trade-off (there is GPL vs. LGPL etc., but we make it work in a
variety of ways). For example, even though x264 is GPL, we (LGPL) are OK
with that, since GPL is still opensource, and for many end use cases, that
works out fine anyway. However, for closed-source encoders, Iv'e always
assumed that our default position is "no, thanks", and recommend these
companies to maintain their patchset out-of-tree, so the cost of updating
is on them, not us.
Hypothetically, again, let's say this patch (encoder wrapper, or even
decoder wrapper) went in, does that mean my companies' VP9 encoder wrapper
can go in also? What about commercial H264/HEVC encoders? (There's many of
them.) How do we decide which goes in if there's many and we don't know
their quality/speed at various use cases because we don't have access to
these under liberal licenses we are all comfortable with?
(No specific opinion intended, just putting a wider frame on the
discussion.)
I totally see your point in us having to care for the wrapper if it is not
out-of-tree. Also that this is or might easily be a financial saving for a
company.
I don't see us having a maintenance burden that big to refuse such code just
of that, though.
Of course, feeling "used" by a company to do "their" work adds to a negative
impact. I added myself to be maintainer of that code in question and I don't
feel that way (and no, I'm not on a permanent payroll of RealNetworks).
Thinking of code that is not getting the devotion of any maintainer - we
just removed that code in the past and why should that not happen to a
wrapper utilizing a commercial binary. A company who wanted such a wrapper
and shows no further interest in maintaining suffers from removed support
sooner or later. Which might raise their interested again, doesn't it?
From the users perspective I don't see why we don't have wrappers for a
commercial codec. If the user wants to use it, why should we forbid such
code. Having an out-of-tree repo to merge into the code for supporting such
codec _is_ of course a way for the user to get it anyway. But from that only
the users compiling & patching the code themselves are capable of doing so
benefit - we lose sight of all others going that way.
Paul and Rostislav adding a concern about killing the project with it by
supporting closed source solutions.
I don't get your big picture with that concern. I don't see how FFmpeg
supporting external commercial codecs is a threat to our project. Please
enlighten me and I'm serious about it. When I was asked about helping with
such a wrapper for that library, my "natural" intention is to get FFmpeg
support it if we don't have native or other support for that codec - to
support every codec there is, which is one of our goals, isn't it?
Please, I'm not supporting binary blobs, nor do I intend to use them.
Post by Thilo Borgmann
I can't stress enough how seriously I want you to explain me your point of
view. I'm doing a lot of things in the best interest of FFmpeg, I'm spending
money in the name of the project, talking to a million different faces about
it and if "go with an out-of-tree wrapper" is our opinion on that for a
reason I want you to convince of that. Give me a call if you feel to, I mean
it - I don't care much about a commercial flaming discussion nor do I want
to make a point about the topic, I care about an important point I might not
aware of so far. I benefit from getting this wrapper through review, however
it is out of the question that no money in the world will bribe me to act
against the best interest of FFmpeg. Convince me having such code is a
really bad idea for the project and I will waive my whole effort for this
case and maybe be better able to protect our project from such endeavors.
If this codec is useful at all, and used a lot, it will be REd in days.

Then we would need to keep wrapper for how much long?

Maintaing wrapper is out of question when there is native decoder.
Thilo Borgmann
2018-04-23 21:06:51 UTC
Permalink
Post by Paul B Mahol
Post by Thilo Borgmann
Hi,
Post by Ronald S. Bultje
not expressing specific agreement or disagreement.
Post by James Almer
Post by James Almer
Post by Paul B Mahol
Post by Thilo Borgmann
Hi,
V3 drops the MLTI part, no idea how it survived
02fff499362daedcdcb0a9cdd517257843600563 on our side...
Also dropped audio override, could not get a sample requiring it.
Adapted to current HEAD.
I'm strongly against applying this to our tree.
The de/muxing code can and should be applied as long as there are not
technical limitations. They are native code and depend on nothing
external.
Post by James Almer
And regarding the decoder and encoder wrappers, you need to explain the
reasons for your hard NAK...
Yes Paul please do, and while you're on it, please add your thoughts about
making it good enough for our tree that come to your mind. I assume it is
not RV11 or its library wrapper for itself you don't like to see pushed...
So, let's take the hypothetical argument of the encoder. So, clearly, the
company ("they") offering that encoder makes money and would benefit
financially from seeing that encoder integrated with FFmpeg. Also, the
maintenance effort would fall entirely on the opensource community ("we").
For example, if we change API (big or small), we have to update their
wrapper. However, their encoder itself (not wrapper) is still
closed-source. So, it seems very one-sided in terms of who benefits at what
cost and to who.
My impression has always been that for opensource encoders, we were OK with
this trade-off (there is GPL vs. LGPL etc., but we make it work in a
variety of ways). For example, even though x264 is GPL, we (LGPL) are OK
with that, since GPL is still opensource, and for many end use cases, that
works out fine anyway. However, for closed-source encoders, Iv'e always
assumed that our default position is "no, thanks", and recommend these
companies to maintain their patchset out-of-tree, so the cost of updating
is on them, not us.
Hypothetically, again, let's say this patch (encoder wrapper, or even
decoder wrapper) went in, does that mean my companies' VP9 encoder wrapper
can go in also? What about commercial H264/HEVC encoders? (There's many of
them.) How do we decide which goes in if there's many and we don't know
their quality/speed at various use cases because we don't have access to
these under liberal licenses we are all comfortable with?
(No specific opinion intended, just putting a wider frame on the
discussion.)
I totally see your point in us having to care for the wrapper if it is not
out-of-tree. Also that this is or might easily be a financial saving for a
company.
I don't see us having a maintenance burden that big to refuse such code just
of that, though.
Of course, feeling "used" by a company to do "their" work adds to a negative
impact. I added myself to be maintainer of that code in question and I don't
feel that way (and no, I'm not on a permanent payroll of RealNetworks).
Thinking of code that is not getting the devotion of any maintainer - we
just removed that code in the past and why should that not happen to a
wrapper utilizing a commercial binary. A company who wanted such a wrapper
and shows no further interest in maintaining suffers from removed support
sooner or later. Which might raise their interested again, doesn't it?
From the users perspective I don't see why we don't have wrappers for a
commercial codec. If the user wants to use it, why should we forbid such
code. Having an out-of-tree repo to merge into the code for supporting such
codec _is_ of course a way for the user to get it anyway. But from that only
the users compiling & patching the code themselves are capable of doing so
benefit - we lose sight of all others going that way.
Paul and Rostislav adding a concern about killing the project with it by
supporting closed source solutions.
I don't get your big picture with that concern. I don't see how FFmpeg
supporting external commercial codecs is a threat to our project. Please
enlighten me and I'm serious about it. When I was asked about helping with
such a wrapper for that library, my "natural" intention is to get FFmpeg
support it if we don't have native or other support for that codec - to
support every codec there is, which is one of our goals, isn't it?
Please, I'm not supporting binary blobs, nor do I intend to use them.
And you're welcome to do so. How is it an argument to have everyone to obey that?
Post by Paul B Mahol
Post by Thilo Borgmann
I can't stress enough how seriously I want you to explain me your point of
view. I'm doing a lot of things in the best interest of FFmpeg, I'm spending
money in the name of the project, talking to a million different faces about
it and if "go with an out-of-tree wrapper" is our opinion on that for a
reason I want you to convince of that. Give me a call if you feel to, I mean
it - I don't care much about a commercial flaming discussion nor do I want
to make a point about the topic, I care about an important point I might not
aware of so far. I benefit from getting this wrapper through review, however
it is out of the question that no money in the world will bribe me to act
against the best interest of FFmpeg. Convince me having such code is a
really bad idea for the project and I will waive my whole effort for this
case and maybe be better able to protect our project from such endeavors.
If this codec is useful at all, and used a lot, it will be REd in days.
Then we would need to keep wrapper for how much long?
Maintaing wrapper is out of question when there is native decoder.
If an REd native implementation comes around, that would be a good thing. And it would void the need of having a wrapper for what we natively support immediately, even if we would most likely keep it until next minor(?) or whatever change.

Paul, I'm really interested in why having such code in FFmpeg is a thread to our project.

Thanks,
Thilo
Paul B Mahol
2018-04-23 21:03:40 UTC
Permalink
Post by Thilo Borgmann
Post by Paul B Mahol
Post by Thilo Borgmann
Hi,
Post by Ronald S. Bultje
not expressing specific agreement or disagreement.
Post by James Almer
Post by James Almer
Post by Paul B Mahol
Post by Thilo Borgmann
Hi,
V3 drops the MLTI part, no idea how it survived
02fff499362daedcdcb0a9cdd517257843600563 on our side...
Also dropped audio override, could not get a sample requiring it.
Adapted to current HEAD.
I'm strongly against applying this to our tree.
The de/muxing code can and should be applied as long as there are not
technical limitations. They are native code and depend on nothing
external.
Post by James Almer
And regarding the decoder and encoder wrappers, you need to explain the
reasons for your hard NAK...
Yes Paul please do, and while you're on it, please add your thoughts about
making it good enough for our tree that come to your mind. I assume it is
not RV11 or its library wrapper for itself you don't like to see pushed...
So, let's take the hypothetical argument of the encoder. So, clearly, the
company ("they") offering that encoder makes money and would benefit
financially from seeing that encoder integrated with FFmpeg. Also, the
maintenance effort would fall entirely on the opensource community ("we").
For example, if we change API (big or small), we have to update their
wrapper. However, their encoder itself (not wrapper) is still
closed-source. So, it seems very one-sided in terms of who benefits at what
cost and to who.
My impression has always been that for opensource encoders, we were OK with
this trade-off (there is GPL vs. LGPL etc., but we make it work in a
variety of ways). For example, even though x264 is GPL, we (LGPL) are OK
with that, since GPL is still opensource, and for many end use cases, that
works out fine anyway. However, for closed-source encoders, Iv'e always
assumed that our default position is "no, thanks", and recommend these
companies to maintain their patchset out-of-tree, so the cost of updating
is on them, not us.
Hypothetically, again, let's say this patch (encoder wrapper, or even
decoder wrapper) went in, does that mean my companies' VP9 encoder wrapper
can go in also? What about commercial H264/HEVC encoders? (There's many of
them.) How do we decide which goes in if there's many and we don't know
their quality/speed at various use cases because we don't have access to
these under liberal licenses we are all comfortable with?
(No specific opinion intended, just putting a wider frame on the
discussion.)
I totally see your point in us having to care for the wrapper if it is not
out-of-tree. Also that this is or might easily be a financial saving for a
company.
I don't see us having a maintenance burden that big to refuse such code just
of that, though.
Of course, feeling "used" by a company to do "their" work adds to a negative
impact. I added myself to be maintainer of that code in question and I don't
feel that way (and no, I'm not on a permanent payroll of RealNetworks).
Thinking of code that is not getting the devotion of any maintainer - we
just removed that code in the past and why should that not happen to a
wrapper utilizing a commercial binary. A company who wanted such a wrapper
and shows no further interest in maintaining suffers from removed support
sooner or later. Which might raise their interested again, doesn't it?
From the users perspective I don't see why we don't have wrappers for a
commercial codec. If the user wants to use it, why should we forbid such
code. Having an out-of-tree repo to merge into the code for supporting such
codec _is_ of course a way for the user to get it anyway. But from that only
the users compiling & patching the code themselves are capable of doing so
benefit - we lose sight of all others going that way.
Paul and Rostislav adding a concern about killing the project with it by
supporting closed source solutions.
I don't get your big picture with that concern. I don't see how FFmpeg
supporting external commercial codecs is a threat to our project. Please
enlighten me and I'm serious about it. When I was asked about helping with
such a wrapper for that library, my "natural" intention is to get FFmpeg
support it if we don't have native or other support for that codec - to
support every codec there is, which is one of our goals, isn't it?
Please, I'm not supporting binary blobs, nor do I intend to use them.
And you're welcome to do so. How is it an argument to have everyone to obey that?
Post by Paul B Mahol
Post by Thilo Borgmann
I can't stress enough how seriously I want you to explain me your point of
view. I'm doing a lot of things in the best interest of FFmpeg, I'm spending
money in the name of the project, talking to a million different faces about
it and if "go with an out-of-tree wrapper" is our opinion on that for a
reason I want you to convince of that. Give me a call if you feel to, I mean
it - I don't care much about a commercial flaming discussion nor do I want
to make a point about the topic, I care about an important point I might not
aware of so far. I benefit from getting this wrapper through review, however
it is out of the question that no money in the world will bribe me to act
against the best interest of FFmpeg. Convince me having such code is a
really bad idea for the project and I will waive my whole effort for this
case and maybe be better able to protect our project from such endeavors.
If this codec is useful at all, and used a lot, it will be REd in days.
Then we would need to keep wrapper for how much long?
Maintaing wrapper is out of question when there is native decoder.
If an REd native implementation comes around, that would be a good thing.
And it would void the need of having a wrapper for what we natively support
immediately, even if we would most likely keep it until next minor(?) or
whatever change.
Paul, I'm really interested in why having such code in FFmpeg is a thread to our project.
It is big threat.

If you want it, fork FFmpeg, call it BinaryBlogFFmpeg and do with it whatever
you can.
Nicolas George
2018-04-23 21:05:52 UTC
Permalink
Post by Paul B Mahol
It is big threat.
Will you please give arguments instead of repeating the same things
endlessly?

I think I intuitively agree with your position, but as it is, you
objection is worthless, and Thilo would be entitled to just ignore it.

Regards,
--
Nicolas George
Paul B Mahol
2018-04-23 21:15:17 UTC
Permalink
Post by Nicolas George
Post by Paul B Mahol
It is big threat.
Will you please give arguments instead of repeating the same things
endlessly?
I think I intuitively agree with your position, but as it is, you
objection is worthless, and Thilo would be entitled to just ignore it.
Why would we link to binary blobs that deny REing?

This is all messy to me. We are either good guys or we do not care and
do what every one does.

Adding wrappers like this, means we support them and we obey their rules.

Supporting closed source solutions also decrease chances for open source ones.

If you desperately need this: add it to VLC or GStreamer project.

If we supported external plugins this would not be problem.

Nobody came to me for REing this codec nor provided binary that does decoding.
Michael Niedermayer
2018-04-24 00:04:24 UTC
Permalink
Post by Paul B Mahol
Post by Nicolas George
Post by Paul B Mahol
It is big threat.
Will you please give arguments instead of repeating the same things
endlessly?
I think I intuitively agree with your position, but as it is, you
objection is worthless, and Thilo would be entitled to just ignore it.
Why would we link to binary blobs that deny REing?
how could that work ?
LGPL says this:
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.

[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

It is what and why we do it that matters, not just one of them.
Paul B Mahol
2018-04-24 08:31:26 UTC
Permalink
Post by Michael Niedermayer
Post by Paul B Mahol
Post by Nicolas George
Post by Paul B Mahol
It is big threat.
Will you please give arguments instead of repeating the same things
endlessly?
I think I intuitively agree with your position, but as it is, you
objection is worthless, and Thilo would be entitled to just ignore it.
Why would we link to binary blobs that deny REing?
how could that work ?
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
[...]
I wonder that too.

IIRC they used to have special ffmpeg version with this codec support.
Ronald S. Bultje
2018-04-23 21:23:24 UTC
Permalink
Hi Thilo,
Post by Thilo Borgmann
From the users perspective I don't see why we don't have wrappers for a
commercial codec.
Right, that's the core thing.

Why doesn't FFmpeg "promote" the use of this closed-source software?

Maybe it's because some of us contribute to this project not just out of
utility ("I can do XYZ with it"), but out of some sort of idealism ("I like
opensource"), trying to promote the common good of free software, kind of
like volunteering in some local community thing.

For these contributors, "promoting" closed-source software would run
directly contra to this ideal.

As an analogy, imagine that the Linux kernel started including wrappers to
promote the use of custom binary graphics device drivers. That would run
directly contra to the ideals that the project stands for. You personally
may not care so much, I understand that much, but please do see that some
other contributors might care far more.

Ronald
Marton Balint
2018-04-23 22:47:41 UTC
Permalink
Post by Ronald S. Bultje
Hi Thilo,
Post by Thilo Borgmann
From the users perspective I don't see why we don't have wrappers for a
commercial codec.
Right, that's the core thing.
Why doesn't FFmpeg "promote" the use of this closed-source software?
Maybe it's because some of us contribute to this project not just out of
utility ("I can do XYZ with it"), but out of some sort of idealism ("I like
opensource"), trying to promote the common good of free software, kind of
like volunteering in some local community thing.
That's fine, I even understand and relate to that. However, as a user, I
utterly don't care about it, as a I user I want to use the best tool
available today, let it be free or not, open source or not. If you are
making it harder for me because of your _idealism_, well... please don't.
Post by Ronald S. Bultje
For these contributors, "promoting" closed-source software would run
directly contra to this ideal.
This is hardly a technical argument.
Post by Ronald S. Bultje
As an analogy, imagine that the Linux kernel started including wrappers to
promote the use of custom binary graphics device drivers. That would run
directly contra to the ideals that the project stands for. You personally
may not care so much, I understand that much, but please do see that some
other contributors might care far more.
You can build a module without rebuilding the whole kernel, ffmpeg is not
that flexible...

Obviously a separate repo for non-free is an option, but do we really need
a separate repo for closed source components because some people don't
like closed source out of idealism? I really feel that the religous
arguments dominate this discussion.

Regards,
Marton
Hendrik Leppkes
2018-04-23 23:25:25 UTC
Permalink
Post by Marton Balint
Post by Ronald S. Bultje
Hi Thilo,
Post by Thilo Borgmann
From the users perspective I don't see why we don't have wrappers for a
commercial codec.
Right, that's the core thing.
Why doesn't FFmpeg "promote" the use of this closed-source software?
Maybe it's because some of us contribute to this project not just out of
utility ("I can do XYZ with it"), but out of some sort of idealism ("I like
opensource"), trying to promote the common good of free software, kind of
like volunteering in some local community thing.
That's fine, I even understand and relate to that. However, as a user, I
utterly don't care about it, as a I user I want to use the best tool
available today, let it be free or not, open source or not. If you are
making it harder for me because of your _idealism_, well... please don't.
You could turn that argument easily around at Realnetworks - if the
user experience is the most important, why do we have to bend over and
take it, instead of asking Realnetworks to actually make an
open-source codec?
That would not only eliminate this discussion, but actually allow
shipping of their codec with ffmpeg onto millions of PCs - instant
support for their codec!

You can always make up some argument that somehow the users benefit
from whatever one is trying to push through, but that doesn't mean its
the right thing to do.
Post by Marton Balint
Post by Ronald S. Bultje
For these contributors, "promoting" closed-source software would run
directly contra to this ideal.
This is hardly a technical argument.
Does it have to be? This is pretty polarizing topic in open-source
projects in general, and alienating those people does in no way
benefit the project. So we get one wrapper for some codec that may or
may not ever even be successfull, but some contributors may lose some
of their motivation to work? Not a good deal.

- Hendrik
Jan Ekström
2018-04-23 23:28:48 UTC
Permalink
Post by Marton Balint
That's fine, I even understand and relate to that. However, as a user, I
utterly don't care about it, as a I user I want to use the best tool
available today, let it be free or not, open source or not. If you are
making it harder for me because of your _idealism_, well... please don't.
Hi,

Coming back from the side that tries to help users get what they can
from FFmpeg, it's funny how I've already seen cases where people try
to build feature XYZ in a new version of FFmpeg just to find
themselves in a position where it is not possible because the
back-bone of what they're trying to do is basing on a proprietary
library, which is - in this specific case - not available for the
architecture which the user wanted to utilize. It can be really hard
to explain to a user that no, he cannot have this feature. That there
is no technical reason why it wouldn't be possible, but just the fact
that it is dependent on a vendor. The end result being "Well, go ask
$VENDOR if they are nice enough to give you an $ARCH SDK". And it
might not always be the architecture, it could be parameters or
capabilities or anything in between that the user might want from this
new feature, which is not available from the closed source SDK.

So while users might not care on some level, they often end up caring
why we have something as a feature if they cannot utilize it or
utilize it in the way that they wish to.


Best regards,
Jan
Paul B Mahol
2018-04-23 19:32:42 UTC
Permalink
Post by Thilo Borgmann
Post by James Almer
Post by Paul B Mahol
Post by Thilo Borgmann
Hi,
V3 drops the MLTI part, no idea how it survived
02fff499362daedcdcb0a9cdd517257843600563 on our side...
Also dropped audio override, could not get a sample requiring it.
Adapted to current HEAD.
I'm strongly against applying this to our tree.
The de/muxing code can and should be applied as long as there are not
technical limitations. They are native code and depend on nothing external.
And regarding the decoder and encoder wrappers, you need to explain the
reasons for your hard NAK...
Yes Paul please do, and while you're on it, please add your thoughts about
making it good enough for our tree that come to your mind. I assume it is
not RV11 or its library wrapper for itself you don't like to see pushed...
This will allow any random guy to send wrappers that supports any closed source
solution.

Yes, we have hardware stuff and other devices, but for decoders I
strongly object
to commit this wrapper for closed source solution.

If we go to the closed source way, we may kill project right a way and
remove all
native code.
Rostislav Pehlivanov
2018-04-23 19:51:57 UTC
Permalink
Post by Thilo Borgmann
Post by Thilo Borgmann
Post by James Almer
Post by Paul B Mahol
Post by Thilo Borgmann
Hi,
V3 drops the MLTI part, no idea how it survived
02fff499362daedcdcb0a9cdd517257843600563 on our side...
Also dropped audio override, could not get a sample requiring it.
Adapted to current HEAD.
I'm strongly against applying this to our tree.
The de/muxing code can and should be applied as long as there are not
technical limitations. They are native code and depend on nothing external.
And regarding the decoder and encoder wrappers, you need to explain the
reasons for your hard NAK...
Yes Paul please do, and while you're on it, please add your thoughts
about
Post by Thilo Borgmann
making it good enough for our tree that come to your mind. I assume it is
not RV11 or its library wrapper for itself you don't like to see
pushed...
This will allow any random guy to send wrappers that supports any closed source
solution.
Yes, we have hardware stuff and other devices, but for decoders I
strongly object
to commit this wrapper for closed source solution.
If we go to the closed source way, we may kill project right a way and
remove all
native code.
_______________________________________________
ffmpeg-devel mailing list
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
I agree.
Loading...