* [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
@ 2024-01-22 19:14 Victor Luchits
2024-01-22 21:12 ` Tomas Härdin
2024-01-22 22:39 ` epirat07
0 siblings, 2 replies; 18+ messages in thread
From: Victor Luchits @ 2024-01-22 19:14 UTC (permalink / raw)
To: ffmpeg-devel
The bitrate option (-b:v) can now be used to specify the bit rate
of the video stream of the RoQ encoder.
Original patch by Joseph Fenton aka Chilly Willy
Signed-off-by: Victor Luchits <vluchits@gmail.com>
---
Changelog | 1 +
libavcodec/roqvideo.h | 1 +
libavcodec/roqvideodec.c | 16 ++++++
libavcodec/roqvideoenc.c | 107 +++++++++++++++++++++++++++++++++++----
libavcodec/version.h | 2 +-
5 files changed, 117 insertions(+), 10 deletions(-)
diff --git a/Changelog b/Changelog
index c40b6d08fd..6974312f9d 100644
--- a/Changelog
+++ b/Changelog
@@ -22,6 +22,7 @@ version <next>:
- ffmpeg CLI -bsf option may now be used for input as well as output
- ffmpeg CLI options may now be used as -/opt <path>, which is equivalent
to -opt <contents of file <path>>
+- RoQ video bit rate option support
version 6.1:
- libaribcaption decoder
diff --git a/libavcodec/roqvideo.h b/libavcodec/roqvideo.h
index 2c2e42884d..6d30bcaada 100644
--- a/libavcodec/roqvideo.h
+++ b/libavcodec/roqvideo.h
@@ -43,6 +43,7 @@ typedef struct RoqContext {
AVFrame *last_frame;
AVFrame *current_frame;
int width, height;
+ int key_frame;
roq_cell cb2x2[256];
roq_qcell cb4x4[256];
diff --git a/libavcodec/roqvideodec.c b/libavcodec/roqvideodec.c
index bfc69a65c9..b4ade3a43b 100644
--- a/libavcodec/roqvideodec.c
+++ b/libavcodec/roqvideodec.c
@@ -70,6 +70,7 @@ static void roqvideo_decode_frame(RoqContext *ri, GetByteContext *gb)
chunk_start = bytestream2_tell(gb);
xpos = ypos = 0;
+ ri->key_frame = 1;
if (chunk_size > bytestream2_get_bytes_left(gb)) {
av_log(ri->logctx, AV_LOG_ERROR, "Chunk does not fit in input buffer\n");
@@ -92,12 +93,14 @@ static void roqvideo_decode_frame(RoqContext *ri, GetByteContext *gb)
switch(vqid) {
case RoQ_ID_MOT:
+ ri->key_frame = 0;
break;
case RoQ_ID_FCC: {
int byte = bytestream2_get_byte(gb);
mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8));
my = 8 - (byte & 0xf) - ((signed char) chunk_arg);
ff_apply_motion_8x8(ri, xp, yp, mx, my);
+ ri->key_frame = 0;
break;
}
case RoQ_ID_SLD:
@@ -125,12 +128,14 @@ static void roqvideo_decode_frame(RoqContext *ri, GetByteContext *gb)
vqflg_pos--;
switch(vqid) {
case RoQ_ID_MOT:
+ ri->key_frame = 0;
break;
case RoQ_ID_FCC: {
int byte = bytestream2_get_byte(gb);
mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8));
my = 8 - (byte & 0xf) - ((signed char) chunk_arg);
ff_apply_motion_4x4(ri, x, y, mx, my);
+ ri->key_frame = 0;
break;
}
case RoQ_ID_SLD:
@@ -214,6 +219,17 @@ static int roq_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
if ((ret = av_frame_ref(rframe, s->current_frame)) < 0)
return ret;
+
+ /* Keyframe when no MOT or FCC codes in frame */
+ if (s->key_frame) {
+ av_log(avctx, AV_LOG_VERBOSE, "\nFound keyframe!\n");
+ rframe->pict_type = AV_PICTURE_TYPE_I;
+ avpkt->flags |= AV_PKT_FLAG_KEY;
+ } else {
+ rframe->pict_type = AV_PICTURE_TYPE_P;
+ avpkt->flags &= ~AV_PKT_FLAG_KEY;
+ }
+
*got_frame = 1;
/* shuffle frames */
diff --git a/libavcodec/roqvideoenc.c b/libavcodec/roqvideoenc.c
index 0933abf4f9..68ec9ec238 100644
--- a/libavcodec/roqvideoenc.c
+++ b/libavcodec/roqvideoenc.c
@@ -136,6 +136,8 @@ typedef struct RoqEncContext {
struct ELBGContext *elbg;
AVLFG randctx;
uint64_t lambda;
+ uint64_t last_lambda;
+ int lambda_delta;
motion_vect *this_motion4;
motion_vect *last_motion4;
@@ -887,8 +889,9 @@ static int generate_new_codebooks(RoqEncContext *enc)
return 0;
}
-static int roq_encode_video(RoqEncContext *enc)
+static int roq_encode_video(AVCodecContext *avctx)
{
+ RoqEncContext *const enc = avctx->priv_data;
RoqTempData *const tempData = &enc->tmp_data;
RoqContext *const roq = &enc->common;
int ret;
@@ -910,14 +913,14 @@ static int roq_encode_video(RoqEncContext *enc)
/* Quake 3 can't handle chunks bigger than 65535 bytes */
if (tempData->mainChunkSize/8 > 65535 && enc->quake3_compat) {
- if (enc->lambda > 100000) {
+ if (enc->lambda > 100000000) {
av_log(roq->logctx, AV_LOG_ERROR, "Cannot encode video in Quake compatible form\n");
return AVERROR(EINVAL);
}
av_log(roq->logctx, AV_LOG_ERROR,
"Warning, generated a frame too big for Quake (%d > 65535), "
- "now switching to a bigger qscale value.\n",
- tempData->mainChunkSize/8);
+ "now switching to a bigger qscale value (%d).\n",
+ tempData->mainChunkSize/8, (int)enc->lambda);
enc->lambda *= 1.5;
tempData->mainChunkSize = 0;
memset(tempData->used_option, 0, sizeof(tempData->used_option));
@@ -931,6 +934,80 @@ static int roq_encode_video(RoqEncContext *enc)
remap_codebooks(enc);
+ /* bit rate control code - could make encoding very slow */
+ if (avctx->bit_rate) {
+ /* a bit rate has been specified - try to match it */
+ int ftotal = (tempData->mainChunkSize / 8 + tempData->numCB2*6 + tempData->numCB4*4) * avctx->time_base.den * 8;
+ int64_t tol = avctx->bit_rate_tolerance;
+
+ /* tolerance > bit rate, set to 5% of the bit rate */
+ if (tol > avctx->bit_rate)
+ tol = avctx->bit_rate / 20;
+
+ av_log(roq->logctx, AV_LOG_VERBOSE,
+ "\nDesired bit rate (%d kbps), "
+ "Bit rate tolerance (%d), "
+ "Frame rate (%d)\n",
+ (int)avctx->bit_rate, (int)tol, avctx->time_base.den);
+
+ if (ftotal > (avctx->bit_rate + tol)) {
+ /* frame is too big - increase qscale */
+ if (enc->lambda > 100000000) {
+ av_log(roq->logctx, AV_LOG_ERROR, "\nCannot encode video at desired bitrate\n");
+ return AVERROR(EINVAL);
+ }
+ enc->lambda_delta = enc->lambda_delta <= 0 ? 1 : enc->lambda_delta < 65536 ? enc->lambda_delta*2 : 65536;
+ enc->last_lambda = enc->lambda;
+ enc->lambda += enc->lambda_delta;
+ av_log(roq->logctx, AV_LOG_INFO,
+ "\nGenerated a frame too big for desired bit rate (%d kbps), "
+ "now switching to a bigger qscale value (%d).\n",
+ ftotal / 1000, (int)enc->lambda);
+ tempData->mainChunkSize = 0;
+ memset(tempData->used_option, 0, sizeof(tempData->used_option));
+ memset(tempData->codebooks.usedCB4, 0,
+ sizeof(tempData->codebooks.usedCB4));
+ memset(tempData->codebooks.usedCB2, 0,
+ sizeof(tempData->codebooks.usedCB2));
+
+ goto retry_encode;
+ } else if (ftotal < (avctx->bit_rate - tol)) {
+ /* frame is too small - decrease qscale */
+ if (enc->lambda <= 1) {
+ av_log(roq->logctx, AV_LOG_WARNING,
+ "\nGenerated a frame too small for desired bit rate (%d kbps), "
+ "qscale value cannot be lowered any further (%d).\n",
+ ftotal / 1000, (int)enc->lambda);
+ } else if ((enc->lambda - enc->last_lambda) == 1) {
+ av_log(roq->logctx, AV_LOG_WARNING,
+ "\nCannot find qscale that gives desired bit rate within desired tolerance, "
+ "using lower bitrate (%d kbps) with higher qscale value (%d).\n",
+ ftotal / 1000, (int)enc->lambda);
+ } else {
+ enc->lambda_delta = 0;
+ if (enc->lambda == enc->last_lambda) {
+ enc->lambda >>= 1;
+ enc->last_lambda = enc->lambda;
+ } else {
+ enc->lambda = enc->last_lambda;
+ //enc->lambda *= (float)(tempData->mainChunkSize * avctx->time_base.den) / avctx->bit_rate;
+ av_log(roq->logctx, AV_LOG_INFO,
+ "\nGenerated a frame too small for desired bit rate (%d kbps), "
+ "reverting lambda and using smaller inc on qscale (%d).\n",
+ ftotal / 1000, (int)enc->lambda);
+ }
+ tempData->mainChunkSize = 0;
+ memset(tempData->used_option, 0, sizeof(tempData->used_option));
+ memset(tempData->codebooks.usedCB4, 0,
+ sizeof(tempData->codebooks.usedCB4));
+ memset(tempData->codebooks.usedCB2, 0,
+ sizeof(tempData->codebooks.usedCB2));
+
+ goto retry_encode;
+ }
+ }
+ }
+
write_codebooks(enc);
reconstruct_and_encode_image(enc, roq->width, roq->height,
@@ -991,8 +1068,11 @@ static av_cold int roq_encode_init(AVCodecContext *avctx)
roq->width = avctx->width;
roq->height = avctx->height;
+ enc->lambda = 2*ROQ_LAMBDA_SCALE;
enc->framesSinceKeyframe = 0;
enc->first_frame = 1;
+ enc->last_lambda = 1;
+ enc->lambda_delta = 0;
roq->last_frame = av_frame_alloc();
roq->current_frame = av_frame_alloc();
@@ -1059,10 +1139,13 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
enc->frame_to_enc = frame;
- if (frame->quality)
- enc->lambda = frame->quality - 1;
- else
- enc->lambda = 2*ROQ_LAMBDA_SCALE;
+ if (avctx->bit_rate) {
+ /* no specific bit rate desired, use frame quality */
+ if (frame->quality)
+ enc->lambda = frame->quality - 1;
+ else
+ enc->lambda = 2*ROQ_LAMBDA_SCALE;
+ }
/* 138 bits max per 8x8 block +
* 256 codebooks*(6 bytes 2x2 + 4 bytes 4x4) + 8 bytes frame header */
@@ -1089,7 +1172,7 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
}
/* Encode the actual frame */
- ret = roq_encode_video(enc);
+ ret = roq_encode_video(avctx);
if (ret < 0)
return ret;
@@ -1115,6 +1198,11 @@ static const AVClass roq_class = {
.version = LIBAVUTIL_VERSION_INT,
};
+static const FFCodecDefault roq_defaults[] = {
+ { "b", "0" },
+ { NULL },
+};
+
const FFCodec ff_roq_encoder = {
.p.name = "roqvideo",
CODEC_LONG_NAME("id RoQ video"),
@@ -1129,4 +1217,5 @@ const FFCodec ff_roq_encoder = {
AV_PIX_FMT_NONE },
.p.priv_class = &roq_class,
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
+ .defaults = roq_defaults,
};
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 376388c5bb..581151cda7 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -30,7 +30,7 @@
#include "version_major.h"
#define LIBAVCODEC_VERSION_MINOR 37
-#define LIBAVCODEC_VERSION_MICRO 100
+#define LIBAVCODEC_VERSION_MICRO 101
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \
--
2.25.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
2024-01-22 19:14 [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder Victor Luchits
@ 2024-01-22 21:12 ` Tomas Härdin
2024-01-22 21:40 ` Victor Luchitz
2024-01-22 22:39 ` epirat07
1 sibling, 1 reply; 18+ messages in thread
From: Tomas Härdin @ 2024-01-22 21:12 UTC (permalink / raw)
To: FFmpeg development discussions and patches
mån 2024-01-22 klockan 22:14 +0300 skrev Victor Luchits:
> The bitrate option (-b:v) can now be used to specify the bit rate
> of the video stream of the RoQ encoder.
>
> Original patch by Joseph Fenton aka Chilly Willy
>
> Signed-off-by: Victor Luchits <vluchits@gmail.com>
Still doesn't apply.
> + /* Keyframe when no MOT or FCC codes in frame */
> + if (s->key_frame) {
> + av_log(avctx, AV_LOG_VERBOSE, "\nFound keyframe!\n");
> + rframe->pict_type = AV_PICTURE_TYPE_I;
> + avpkt->flags |= AV_PKT_FLAG_KEY;
> + } else {
> + rframe->pict_type = AV_PICTURE_TYPE_P;
> + avpkt->flags &= ~AV_PKT_FLAG_KEY;
> + }
Looks like framesSinceKeyframe still doesn't get reset
> + if (avctx->bit_rate) {
> + /* no specific bit rate desired, use frame quality */
> + if (frame->quality)
> + enc->lambda = frame->quality - 1;
> + else
> + enc->lambda = 2*ROQ_LAMBDA_SCALE;
> + }
Looks like you got this backwards
/Tomas
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
2024-01-22 21:12 ` Tomas Härdin
@ 2024-01-22 21:40 ` Victor Luchitz
2024-01-22 23:25 ` Tomas Härdin
0 siblings, 1 reply; 18+ messages in thread
From: Victor Luchitz @ 2024-01-22 21:40 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Tue, Jan 23, 2024 at 12:12 AM Tomas Härdin <git@haerdin.se> wrote:
> mån 2024-01-22 klockan 22:14 +0300 skrev Victor Luchits:
> > The bitrate option (-b:v) can now be used to specify the bit rate
> > of the video stream of the RoQ encoder.
> >
> > Original patch by Joseph Fenton aka Chilly Willy
> >
> > Signed-off-by: Victor Luchits <vluchits@gmail.com>
>
> Still doesn't apply.
>
I have no clue as to what's going on there.. The patch applies perfectly
fine
without all the eml stuff.
root@banana:~/ffmpeg# git reset --hard origin/master
HEAD is now at d2eb6f4d44 fftools/ffmpeg_mux_init: don't free the
AVDictionaryEntry until after it's been used
root@ banana:~/ffmpeg# git apply
0001-liavcodec-add-bit-rate-support-to-RoQ-video-encoder.patch
root@ banana:~/ffmpeg# echo $?
0
Any help would be highly appreciated.
> > + /* Keyframe when no MOT or FCC codes in frame */
> > + if (s->key_frame) {
> > + av_log(avctx, AV_LOG_VERBOSE, "\nFound keyframe!\n");
> > + rframe->pict_type = AV_PICTURE_TYPE_I;
> > + avpkt->flags |= AV_PKT_FLAG_KEY;
> > + } else {
> > + rframe->pict_type = AV_PICTURE_TYPE_P;
> > + avpkt->flags &= ~AV_PKT_FLAG_KEY;
> > + }
>
> Looks like framesSinceKeyframe still doesn't get reset
>
framesSinceKeyframe wasn't introduced in this patch and I'm a bit scared
to mess with it as part of this changeset as that would introduce some new
changes to the core of the original implementation.
> > + if (avctx->bit_rate) {
> > + /* no specific bit rate desired, use frame quality */
> > + if (frame->quality)
> > + enc->lambda = frame->quality - 1;
> > + else
> > + enc->lambda = 2*ROQ_LAMBDA_SCALE;
> > + }
>
> Looks like you got this backwards
>
You're totally right, thanks!
I'll resubmit the patch once we figure out what's the deal with git failing
to apply the patch for you.
>
> /Tomas
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
--
Best regards,
Victor Luchitz
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
2024-01-22 21:40 ` Victor Luchitz
@ 2024-01-22 23:25 ` Tomas Härdin
0 siblings, 0 replies; 18+ messages in thread
From: Tomas Härdin @ 2024-01-22 23:25 UTC (permalink / raw)
To: FFmpeg development discussions and patches
tis 2024-01-23 klockan 00:40 +0300 skrev Victor Luchitz:
> On Tue, Jan 23, 2024 at 12:12 AM Tomas Härdin <git@haerdin.se> wrote:
>
> > mån 2024-01-22 klockan 22:14 +0300 skrev Victor Luchits:
> > > The bitrate option (-b:v) can now be used to specify the bit rate
> > > of the video stream of the RoQ encoder.
> > >
> > > Original patch by Joseph Fenton aka Chilly Willy
> > >
> > > Signed-off-by: Victor Luchits <vluchits@gmail.com>
> >
> > Still doesn't apply.
> >
>
> I have no clue as to what's going on there.. The patch applies
> perfectly
> fine
> without all the eml stuff.
>
> root@banana:~/ffmpeg# git reset --hard origin/master
> HEAD is now at d2eb6f4d44 fftools/ffmpeg_mux_init: don't free the
> AVDictionaryEntry until after it's been used
> root@ banana:~/ffmpeg# git apply
> 0001-liavcodec-add-bit-rate-support-to-RoQ-video-encoder.patch
> root@ banana:~/ffmpeg# echo $?
> 0
>
> Any help would be highly appreciated.
>
>
> > > + /* Keyframe when no MOT or FCC codes in frame */
> > > + if (s->key_frame) {
> > > + av_log(avctx, AV_LOG_VERBOSE, "\nFound keyframe!\n");
> > > + rframe->pict_type = AV_PICTURE_TYPE_I;
> > > + avpkt->flags |= AV_PKT_FLAG_KEY;
> > > + } else {
> > > + rframe->pict_type = AV_PICTURE_TYPE_P;
> > > + avpkt->flags &= ~AV_PKT_FLAG_KEY;
> > > + }
> >
> > Looks like framesSinceKeyframe still doesn't get reset
> >
>
> framesSinceKeyframe wasn't introduced in this patch and I'm a bit
> scared
> to mess with it as part of this changeset as that would introduce
> some new
> changes to the core of the original implementation.
It doesn't have to hold this patch up I guess. Doesn't look terribly
complicated either way
> > > + if (avctx->bit_rate) {
> > > + /* no specific bit rate desired, use frame quality */
> > > + if (frame->quality)
> > > + enc->lambda = frame->quality - 1;
> > > + else
> > > + enc->lambda = 2*ROQ_LAMBDA_SCALE;
> > > + }
> >
> > Looks like you got this backwards
> >
>
> You're totally right, thanks!
>
> I'll resubmit the patch once we figure out what's the deal with git
> failing
> to apply the patch for you.
Try attaching the patch rather than pasting it
/Tomas
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
2024-01-22 19:14 [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder Victor Luchits
2024-01-22 21:12 ` Tomas Härdin
@ 2024-01-22 22:39 ` epirat07
1 sibling, 0 replies; 18+ messages in thread
From: epirat07 @ 2024-01-22 22:39 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Typo in commit message: liavcodec should be libavcodec
On 22 Jan 2024, at 20:14, Victor Luchits wrote:
> The bitrate option (-b:v) can now be used to specify the bit rate
> of the video stream of the RoQ encoder.
>
> Original patch by Joseph Fenton aka Chilly Willy
>
> Signed-off-by: Victor Luchits <vluchits@gmail.com>
> ---
> Changelog | 1 +
> libavcodec/roqvideo.h | 1 +
> libavcodec/roqvideodec.c | 16 ++++++
> libavcodec/roqvideoenc.c | 107 +++++++++++++++++++++++++++++++++++----
> libavcodec/version.h | 2 +-
> 5 files changed, 117 insertions(+), 10 deletions(-)
>
> diff --git a/Changelog b/Changelog
> index c40b6d08fd..6974312f9d 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -22,6 +22,7 @@ version <next>:
> - ffmpeg CLI -bsf option may now be used for input as well as output
> - ffmpeg CLI options may now be used as -/opt <path>, which is equivalent
> to -opt <contents of file <path>>
> +- RoQ video bit rate option support
> version 6.1:
> - libaribcaption decoder
> diff --git a/libavcodec/roqvideo.h b/libavcodec/roqvideo.h
> index 2c2e42884d..6d30bcaada 100644
> --- a/libavcodec/roqvideo.h
> +++ b/libavcodec/roqvideo.h
> @@ -43,6 +43,7 @@ typedef struct RoqContext {
> AVFrame *last_frame;
> AVFrame *current_frame;
> int width, height;
> + int key_frame;
> roq_cell cb2x2[256];
> roq_qcell cb4x4[256];
> diff --git a/libavcodec/roqvideodec.c b/libavcodec/roqvideodec.c
> index bfc69a65c9..b4ade3a43b 100644
> --- a/libavcodec/roqvideodec.c
> +++ b/libavcodec/roqvideodec.c
> @@ -70,6 +70,7 @@ static void roqvideo_decode_frame(RoqContext *ri, GetByteContext *gb)
> chunk_start = bytestream2_tell(gb);
> xpos = ypos = 0;
> + ri->key_frame = 1;
> if (chunk_size > bytestream2_get_bytes_left(gb)) {
> av_log(ri->logctx, AV_LOG_ERROR, "Chunk does not fit in input buffer\n");
> @@ -92,12 +93,14 @@ static void roqvideo_decode_frame(RoqContext *ri, GetByteContext *gb)
> switch(vqid) {
> case RoQ_ID_MOT:
> + ri->key_frame = 0;
> break;
> case RoQ_ID_FCC: {
> int byte = bytestream2_get_byte(gb);
> mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8));
> my = 8 - (byte & 0xf) - ((signed char) chunk_arg);
> ff_apply_motion_8x8(ri, xp, yp, mx, my);
> + ri->key_frame = 0;
> break;
> }
> case RoQ_ID_SLD:
> @@ -125,12 +128,14 @@ static void roqvideo_decode_frame(RoqContext *ri, GetByteContext *gb)
> vqflg_pos--;
> switch(vqid) {
> case RoQ_ID_MOT:
> + ri->key_frame = 0;
> break;
> case RoQ_ID_FCC: {
> int byte = bytestream2_get_byte(gb);
> mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8));
> my = 8 - (byte & 0xf) - ((signed char) chunk_arg);
> ff_apply_motion_4x4(ri, x, y, mx, my);
> + ri->key_frame = 0;
> break;
> }
> case RoQ_ID_SLD:
> @@ -214,6 +219,17 @@ static int roq_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
> if ((ret = av_frame_ref(rframe, s->current_frame)) < 0)
> return ret;
> +
> + /* Keyframe when no MOT or FCC codes in frame */
> + if (s->key_frame) {
> + av_log(avctx, AV_LOG_VERBOSE, "\nFound keyframe!\n");
> + rframe->pict_type = AV_PICTURE_TYPE_I;
> + avpkt->flags |= AV_PKT_FLAG_KEY;
> + } else {
> + rframe->pict_type = AV_PICTURE_TYPE_P;
> + avpkt->flags &= ~AV_PKT_FLAG_KEY;
> + }
> +
> *got_frame = 1;
> /* shuffle frames */
> diff --git a/libavcodec/roqvideoenc.c b/libavcodec/roqvideoenc.c
> index 0933abf4f9..68ec9ec238 100644
> --- a/libavcodec/roqvideoenc.c
> +++ b/libavcodec/roqvideoenc.c
> @@ -136,6 +136,8 @@ typedef struct RoqEncContext {
> struct ELBGContext *elbg;
> AVLFG randctx;
> uint64_t lambda;
> + uint64_t last_lambda;
> + int lambda_delta;
> motion_vect *this_motion4;
> motion_vect *last_motion4;
> @@ -887,8 +889,9 @@ static int generate_new_codebooks(RoqEncContext *enc)
> return 0;
> }
> -static int roq_encode_video(RoqEncContext *enc)
> +static int roq_encode_video(AVCodecContext *avctx)
> {
> + RoqEncContext *const enc = avctx->priv_data;
> RoqTempData *const tempData = &enc->tmp_data;
> RoqContext *const roq = &enc->common;
> int ret;
> @@ -910,14 +913,14 @@ static int roq_encode_video(RoqEncContext *enc)
> /* Quake 3 can't handle chunks bigger than 65535 bytes */
> if (tempData->mainChunkSize/8 > 65535 && enc->quake3_compat) {
> - if (enc->lambda > 100000) {
> + if (enc->lambda > 100000000) {
> av_log(roq->logctx, AV_LOG_ERROR, "Cannot encode video in Quake compatible form\n");
> return AVERROR(EINVAL);
> }
> av_log(roq->logctx, AV_LOG_ERROR,
> "Warning, generated a frame too big for Quake (%d > 65535), "
> - "now switching to a bigger qscale value.\n",
> - tempData->mainChunkSize/8);
> + "now switching to a bigger qscale value (%d).\n",
> + tempData->mainChunkSize/8, (int)enc->lambda);
> enc->lambda *= 1.5;
> tempData->mainChunkSize = 0;
> memset(tempData->used_option, 0, sizeof(tempData->used_option));
> @@ -931,6 +934,80 @@ static int roq_encode_video(RoqEncContext *enc)
> remap_codebooks(enc);
> + /* bit rate control code - could make encoding very slow */
> + if (avctx->bit_rate) {
> + /* a bit rate has been specified - try to match it */
> + int ftotal = (tempData->mainChunkSize / 8 + tempData->numCB2*6 + tempData->numCB4*4) * avctx->time_base.den * 8;
> + int64_t tol = avctx->bit_rate_tolerance;
> +
> + /* tolerance > bit rate, set to 5% of the bit rate */
> + if (tol > avctx->bit_rate)
> + tol = avctx->bit_rate / 20;
> +
> + av_log(roq->logctx, AV_LOG_VERBOSE,
> + "\nDesired bit rate (%d kbps), "
> + "Bit rate tolerance (%d), "
> + "Frame rate (%d)\n",
> + (int)avctx->bit_rate, (int)tol, avctx->time_base.den);
> +
> + if (ftotal > (avctx->bit_rate + tol)) {
> + /* frame is too big - increase qscale */
> + if (enc->lambda > 100000000) {
> + av_log(roq->logctx, AV_LOG_ERROR, "\nCannot encode video at desired bitrate\n");
> + return AVERROR(EINVAL);
> + }
> + enc->lambda_delta = enc->lambda_delta <= 0 ? 1 : enc->lambda_delta < 65536 ? enc->lambda_delta*2 : 65536;
> + enc->last_lambda = enc->lambda;
> + enc->lambda += enc->lambda_delta;
> + av_log(roq->logctx, AV_LOG_INFO,
> + "\nGenerated a frame too big for desired bit rate (%d kbps), "
> + "now switching to a bigger qscale value (%d).\n",
> + ftotal / 1000, (int)enc->lambda);
> + tempData->mainChunkSize = 0;
> + memset(tempData->used_option, 0, sizeof(tempData->used_option));
> + memset(tempData->codebooks.usedCB4, 0,
> + sizeof(tempData->codebooks.usedCB4));
> + memset(tempData->codebooks.usedCB2, 0,
> + sizeof(tempData->codebooks.usedCB2));
> +
> + goto retry_encode;
> + } else if (ftotal < (avctx->bit_rate - tol)) {
> + /* frame is too small - decrease qscale */
> + if (enc->lambda <= 1) {
> + av_log(roq->logctx, AV_LOG_WARNING,
> + "\nGenerated a frame too small for desired bit rate (%d kbps), "
> + "qscale value cannot be lowered any further (%d).\n",
> + ftotal / 1000, (int)enc->lambda);
> + } else if ((enc->lambda - enc->last_lambda) == 1) {
> + av_log(roq->logctx, AV_LOG_WARNING,
> + "\nCannot find qscale that gives desired bit rate within desired tolerance, "
> + "using lower bitrate (%d kbps) with higher qscale value (%d).\n",
> + ftotal / 1000, (int)enc->lambda);
> + } else {
> + enc->lambda_delta = 0;
> + if (enc->lambda == enc->last_lambda) {
> + enc->lambda >>= 1;
> + enc->last_lambda = enc->lambda;
> + } else {
> + enc->lambda = enc->last_lambda;
> + //enc->lambda *= (float)(tempData->mainChunkSize * avctx->time_base.den) / avctx->bit_rate;
> + av_log(roq->logctx, AV_LOG_INFO,
> + "\nGenerated a frame too small for desired bit rate (%d kbps), "
> + "reverting lambda and using smaller inc on qscale (%d).\n",
> + ftotal / 1000, (int)enc->lambda);
> + }
> + tempData->mainChunkSize = 0;
> + memset(tempData->used_option, 0, sizeof(tempData->used_option));
> + memset(tempData->codebooks.usedCB4, 0,
> + sizeof(tempData->codebooks.usedCB4));
> + memset(tempData->codebooks.usedCB2, 0,
> + sizeof(tempData->codebooks.usedCB2));
> +
> + goto retry_encode;
> + }
> + }
> + }
> +
> write_codebooks(enc);
> reconstruct_and_encode_image(enc, roq->width, roq->height,
> @@ -991,8 +1068,11 @@ static av_cold int roq_encode_init(AVCodecContext *avctx)
> roq->width = avctx->width;
> roq->height = avctx->height;
> + enc->lambda = 2*ROQ_LAMBDA_SCALE;
> enc->framesSinceKeyframe = 0;
> enc->first_frame = 1;
> + enc->last_lambda = 1;
> + enc->lambda_delta = 0;
> roq->last_frame = av_frame_alloc();
> roq->current_frame = av_frame_alloc();
> @@ -1059,10 +1139,13 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
> enc->frame_to_enc = frame;
> - if (frame->quality)
> - enc->lambda = frame->quality - 1;
> - else
> - enc->lambda = 2*ROQ_LAMBDA_SCALE;
> + if (avctx->bit_rate) {
> + /* no specific bit rate desired, use frame quality */
> + if (frame->quality)
> + enc->lambda = frame->quality - 1;
> + else
> + enc->lambda = 2*ROQ_LAMBDA_SCALE;
> + }
> /* 138 bits max per 8x8 block +
> * 256 codebooks*(6 bytes 2x2 + 4 bytes 4x4) + 8 bytes frame header */
> @@ -1089,7 +1172,7 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
> }
> /* Encode the actual frame */
> - ret = roq_encode_video(enc);
> + ret = roq_encode_video(avctx);
> if (ret < 0)
> return ret;
> @@ -1115,6 +1198,11 @@ static const AVClass roq_class = {
> .version = LIBAVUTIL_VERSION_INT,
> };
> +static const FFCodecDefault roq_defaults[] = {
> + { "b", "0" },
> + { NULL },
> +};
> +
> const FFCodec ff_roq_encoder = {
> .p.name = "roqvideo",
> CODEC_LONG_NAME("id RoQ video"),
> @@ -1129,4 +1217,5 @@ const FFCodec ff_roq_encoder = {
> AV_PIX_FMT_NONE },
> .p.priv_class = &roq_class,
> .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
> + .defaults = roq_defaults,
> };
> diff --git a/libavcodec/version.h b/libavcodec/version.h
> index 376388c5bb..581151cda7 100644
> --- a/libavcodec/version.h
> +++ b/libavcodec/version.h
> @@ -30,7 +30,7 @@
> #include "version_major.h"
> #define LIBAVCODEC_VERSION_MINOR 37
> -#define LIBAVCODEC_VERSION_MICRO 100
> +#define LIBAVCODEC_VERSION_MICRO 101
> #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
> LIBAVCODEC_VERSION_MINOR, \
> --
> 2.25.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
* [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
@ 2024-01-21 21:08 Victor Luchits
2024-01-22 13:05 ` Tomas Härdin
0 siblings, 1 reply; 18+ messages in thread
From: Victor Luchits @ 2024-01-21 21:08 UTC (permalink / raw)
To: ffmpeg-devel
One can now use the bitrate option (-b) to specify bit rate of the video
stream in the RoQ encoder. The option only becomes effective for values
above 800kbit/s, which is roughly equivalent to bandwidth of a 1x-speed
CD-ROM drive, minus the bandwidth taken up by stereo DPCM stream. Values
below this threshold produce visually inadequate results.
Original patch by Joseph Fenton aka Chilly Willy
Signed-off-by: Victor Luchits <vluchits@gmail.com>
---
Changelog | 1 +
libavcodec/roqvideo.h | 1 +
libavcodec/roqvideodec.c | 15 +++++
libavcodec/roqvideoenc.c | 118 ++++++++++++++++++++++++++++++++++-----
libavcodec/version.h | 2 +-
5 files changed, 123 insertions(+), 14 deletions(-)
diff --git a/Changelog b/Changelog
index c40b6d08fd..6974312f9d 100644
--- a/Changelog
+++ b/Changelog
@@ -22,6 +22,7 @@ version <next>:
- ffmpeg CLI -bsf option may now be used for input as well as output
- ffmpeg CLI options may now be used as -/opt <path>, which is equivalent
to -opt <contents of file <path>>
+- RoQ video bit rate option support
version 6.1:
- libaribcaption decoder
diff --git a/libavcodec/roqvideo.h b/libavcodec/roqvideo.h
index 2c2e42884d..6d30bcaada 100644
--- a/libavcodec/roqvideo.h
+++ b/libavcodec/roqvideo.h
@@ -43,6 +43,7 @@ typedef struct RoqContext {
AVFrame *last_frame;
AVFrame *current_frame;
int width, height;
+ int key_frame;
roq_cell cb2x2[256];
roq_qcell cb4x4[256];
diff --git a/libavcodec/roqvideodec.c b/libavcodec/roqvideodec.c
index bfc69a65c9..07d6b8bb8f 100644
--- a/libavcodec/roqvideodec.c
+++ b/libavcodec/roqvideodec.c
@@ -70,6 +70,7 @@ static void roqvideo_decode_frame(RoqContext *ri, GetByteContext *gb)
chunk_start = bytestream2_tell(gb);
xpos = ypos = 0;
+ ri->key_frame = 1;
if (chunk_size > bytestream2_get_bytes_left(gb)) {
av_log(ri->logctx, AV_LOG_ERROR, "Chunk does not fit in input buffer\n");
@@ -92,12 +93,14 @@ static void roqvideo_decode_frame(RoqContext *ri, GetByteContext *gb)
switch(vqid) {
case RoQ_ID_MOT:
+ ri->key_frame = 0;
break;
case RoQ_ID_FCC: {
int byte = bytestream2_get_byte(gb);
mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8));
my = 8 - (byte & 0xf) - ((signed char) chunk_arg);
ff_apply_motion_8x8(ri, xp, yp, mx, my);
+ ri->key_frame = 0;
break;
}
case RoQ_ID_SLD:
@@ -125,12 +128,14 @@ static void roqvideo_decode_frame(RoqContext *ri, GetByteContext *gb)
vqflg_pos--;
switch(vqid) {
case RoQ_ID_MOT:
+ ri->key_frame = 0;
break;
case RoQ_ID_FCC: {
int byte = bytestream2_get_byte(gb);
mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8));
my = 8 - (byte & 0xf) - ((signed char) chunk_arg);
ff_apply_motion_4x4(ri, x, y, mx, my);
+ ri->key_frame = 0;
break;
}
case RoQ_ID_SLD:
@@ -214,6 +219,16 @@ static int roq_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
if ((ret = av_frame_ref(rframe, s->current_frame)) < 0)
return ret;
+
+ /* Keyframe when no MOT or FCC codes in frame */
+ if (s->key_frame) {
+ av_log(avctx, AV_LOG_VERBOSE, "\nFound keyframe!\n");
+ rframe->pict_type = AV_PICTURE_TYPE_I;
+ avpkt->flags |= AV_PKT_FLAG_KEY;
+ } else {
+ rframe->pict_type = AV_PICTURE_TYPE_P;
+ }
+
*got_frame = 1;
/* shuffle frames */
diff --git a/libavcodec/roqvideoenc.c b/libavcodec/roqvideoenc.c
index 0933abf4f9..bcead80bbd 100644
--- a/libavcodec/roqvideoenc.c
+++ b/libavcodec/roqvideoenc.c
@@ -79,6 +79,9 @@
/* The cast is useful when multiplying it by INT_MAX */
#define ROQ_LAMBDA_SCALE ((uint64_t) FF_LAMBDA_SCALE)
+/* The default minimum bitrate, set around the value of a 1x speed CD-ROM drive */
+#define ROQ_DEFAULT_MIN_BIT_RATE 800*1024
+
typedef struct RoqCodebooks {
int numCB4;
int numCB2;
@@ -136,6 +139,8 @@ typedef struct RoqEncContext {
struct ELBGContext *elbg;
AVLFG randctx;
uint64_t lambda;
+ uint64_t last_lambda;
+ int lambda_delta;
motion_vect *this_motion4;
motion_vect *last_motion4;
@@ -887,8 +892,9 @@ static int generate_new_codebooks(RoqEncContext *enc)
return 0;
}
-static int roq_encode_video(RoqEncContext *enc)
+static int roq_encode_video(AVCodecContext *avctx)
{
+ RoqEncContext *const enc = avctx->priv_data;
RoqTempData *const tempData = &enc->tmp_data;
RoqContext *const roq = &enc->common;
int ret;
@@ -910,14 +916,14 @@ static int roq_encode_video(RoqEncContext *enc)
/* Quake 3 can't handle chunks bigger than 65535 bytes */
if (tempData->mainChunkSize/8 > 65535 && enc->quake3_compat) {
- if (enc->lambda > 100000) {
+ if (enc->lambda > 100000000) {
av_log(roq->logctx, AV_LOG_ERROR, "Cannot encode video in Quake compatible form\n");
return AVERROR(EINVAL);
}
av_log(roq->logctx, AV_LOG_ERROR,
"Warning, generated a frame too big for Quake (%d > 65535), "
- "now switching to a bigger qscale value.\n",
- tempData->mainChunkSize/8);
+ "now switching to a bigger qscale value (%d).\n",
+ tempData->mainChunkSize/8, (int)enc->lambda);
enc->lambda *= 1.5;
tempData->mainChunkSize = 0;
memset(tempData->used_option, 0, sizeof(tempData->used_option));
@@ -931,6 +937,80 @@ static int roq_encode_video(RoqEncContext *enc)
remap_codebooks(enc);
+ /* bit rate control code - could make encoding very slow */
+ if (avctx->bit_rate > ROQ_DEFAULT_MIN_BIT_RATE) {
+ /* a bit rate has been specified - try to match it */
+ int ftotal = (tempData->mainChunkSize / 8 + tempData->numCB2*6 + tempData->numCB4*4) * avctx->time_base.den * 8;
+ int64_t tol = avctx->bit_rate_tolerance;
+
+ /* tolerance > bit rate, set to 5% of the bit rate */
+ if (tol > avctx->bit_rate)
+ tol = avctx->bit_rate / 20;
+
+ av_log(roq->logctx, AV_LOG_VERBOSE,
+ "\nDesired bit rate (%d kbps), "
+ "Bit rate tolerance (%d), "
+ "Frame rate (%d)\n",
+ (int)avctx->bit_rate, (int)tol, avctx->time_base.den);
+
+ if (ftotal > (avctx->bit_rate + tol)) {
+ /* frame is too big - increase qscale */
+ if (enc->lambda > 100000000) {
+ av_log(roq->logctx, AV_LOG_ERROR, "\nCannot encode video at desired bitrate\n");
+ return AVERROR(EINVAL);
+ }
+ enc->lambda_delta = enc->lambda_delta <= 0 ? 1 : enc->lambda_delta < 65536 ? enc->lambda_delta*2 : 65536;
+ enc->last_lambda = enc->lambda;
+ enc->lambda += enc->lambda_delta;
+ av_log(roq->logctx, AV_LOG_INFO,
+ "\nGenerated a frame too big for desired bit rate (%d kbps), "
+ "now switching to a bigger qscale value (%d).\n",
+ ftotal / 1000, (int)enc->lambda);
+ tempData->mainChunkSize = 0;
+ memset(tempData->used_option, 0, sizeof(tempData->used_option));
+ memset(tempData->codebooks.usedCB4, 0,
+ sizeof(tempData->codebooks.usedCB4));
+ memset(tempData->codebooks.usedCB2, 0,
+ sizeof(tempData->codebooks.usedCB2));
+
+ goto retry_encode;
+ } else if (ftotal < (avctx->bit_rate - tol)) {
+ /* frame is too small - decrease qscale */
+ if (enc->lambda <= 1) {
+ av_log(roq->logctx, AV_LOG_WARNING,
+ "\nGenerated a frame too small for desired bit rate (%d kbps), "
+ "qscale value cannot be lowered any further (%d).\n",
+ ftotal / 1000, (int)enc->lambda);
+ } else if ((enc->lambda - enc->last_lambda) == 1) {
+ av_log(roq->logctx, AV_LOG_WARNING,
+ "\nCannot find qscale that gives desired bit rate within desired tolerance, "
+ "using lower bitrate (%d kbps) with higher qscale value (%d).\n",
+ ftotal / 1000, (int)enc->lambda);
+ } else {
+ enc->lambda_delta = 0;
+ if (enc->lambda == enc->last_lambda) {
+ enc->lambda >>= 1;
+ enc->last_lambda = enc->lambda;
+ } else {
+ enc->lambda = enc->last_lambda;
+ //enc->lambda *= (float)(tempData->mainChunkSize * avctx->time_base.den) / avctx->bit_rate;
+ av_log(roq->logctx, AV_LOG_INFO,
+ "\nGenerated a frame too small for desired bit rate (%d kbps), "
+ "reverting lambda and using smaller inc on qscale (%d).\n",
+ ftotal / 1000, (int)enc->lambda);
+ }
+ tempData->mainChunkSize = 0;
+ memset(tempData->used_option, 0, sizeof(tempData->used_option));
+ memset(tempData->codebooks.usedCB4, 0,
+ sizeof(tempData->codebooks.usedCB4));
+ memset(tempData->codebooks.usedCB2, 0,
+ sizeof(tempData->codebooks.usedCB2));
+
+ goto retry_encode;
+ }
+ }
+ }
+
write_codebooks(enc);
reconstruct_and_encode_image(enc, roq->width, roq->height,
@@ -980,19 +1060,26 @@ static av_cold int roq_encode_init(AVCodecContext *avctx)
return AVERROR(EINVAL);
}
- if (avctx->width > 65535 || avctx->height > 65535) {
- av_log(avctx, AV_LOG_ERROR, "Dimensions are max %d\n", enc->quake3_compat ? 32768 : 65535);
+ if (enc->quake3_compat && ((avctx->width > 32767 || avctx->height > 32767))) {
+ av_log(avctx, AV_LOG_ERROR, "Dimensions are max %d\n", 32767);
+ return AVERROR(EINVAL);
+ }
+ else if (avctx->width > 65535 || avctx->height > 65535) {
+ av_log(avctx, AV_LOG_ERROR, "Dimensions are max %d\n", 65535);
return AVERROR(EINVAL);
}
- if (((avctx->width)&(avctx->width-1))||((avctx->height)&(avctx->height-1)))
+ if (enc->quake3_compat && ((avctx->width)&(avctx->width-1))||((avctx->height)&(avctx->height-1)))
av_log(avctx, AV_LOG_ERROR, "Warning: dimensions not power of two, this is not supported by quake\n");
roq->width = avctx->width;
roq->height = avctx->height;
+ enc->lambda = 2*ROQ_LAMBDA_SCALE;
enc->framesSinceKeyframe = 0;
enc->first_frame = 1;
+ enc->last_lambda = 1;
+ enc->lambda_delta = 0;
roq->last_frame = av_frame_alloc();
roq->current_frame = av_frame_alloc();
@@ -1043,9 +1130,11 @@ static void roq_write_video_info_chunk(RoqEncContext *enc)
/* Height */
bytestream_put_le16(&enc->out_buf, enc->common.height);
- /* Unused in Quake 3, mimics the output of the real encoder */
+ /* Quake 3: starting size for cell subdivision */
bytestream_put_byte(&enc->out_buf, 0x08);
bytestream_put_byte(&enc->out_buf, 0x00);
+
+ /* Quake 3: ending size for cell subdivision */
bytestream_put_byte(&enc->out_buf, 0x04);
bytestream_put_byte(&enc->out_buf, 0x00);
}
@@ -1059,10 +1148,13 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
enc->frame_to_enc = frame;
- if (frame->quality)
- enc->lambda = frame->quality - 1;
- else
- enc->lambda = 2*ROQ_LAMBDA_SCALE;
+ if (avctx->bit_rate <= ROQ_DEFAULT_MIN_BIT_RATE) {
+ /* no specific bit rate desired, use frame quality */
+ if (frame->quality)
+ enc->lambda = frame->quality - 1;
+ else
+ enc->lambda = 2*ROQ_LAMBDA_SCALE;
+ }
/* 138 bits max per 8x8 block +
* 256 codebooks*(6 bytes 2x2 + 4 bytes 4x4) + 8 bytes frame header */
@@ -1089,7 +1181,7 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
}
/* Encode the actual frame */
- ret = roq_encode_video(enc);
+ ret = roq_encode_video(avctx);
if (ret < 0)
return ret;
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 376388c5bb..581151cda7 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -30,7 +30,7 @@
#include "version_major.h"
#define LIBAVCODEC_VERSION_MINOR 37
-#define LIBAVCODEC_VERSION_MICRO 100
+#define LIBAVCODEC_VERSION_MICRO 101
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \
--
2.25.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
2024-01-21 21:08 Victor Luchits
@ 2024-01-22 13:05 ` Tomas Härdin
2024-01-22 13:38 ` Victor Luchitz
0 siblings, 1 reply; 18+ messages in thread
From: Tomas Härdin @ 2024-01-22 13:05 UTC (permalink / raw)
To: FFmpeg development discussions and patches
mån 2024-01-22 klockan 00:08 +0300 skrev Victor Luchits:
> One can now use the bitrate option (-b) to specify bit rate of the
> video
> stream in the RoQ encoder. The option only becomes effective for
> values
> above 800kbit/s, which is roughly equivalent to bandwidth of a 1x-
> speed
> CD-ROM drive, minus the bandwidth taken up by stereo DPCM stream.
> Values
> below this threshold produce visually inadequate results.
>
> Original patch by Joseph Fenton aka Chilly Willy
>
> Signed-off-by: Victor Luchits <vluchits@gmail.com>
> ---
> Changelog | 1 +
> libavcodec/roqvideo.h | 1 +
> libavcodec/roqvideodec.c | 15 +++++
> libavcodec/roqvideoenc.c | 118 ++++++++++++++++++++++++++++++++++--
> ---
> libavcodec/version.h | 2 +-
> 5 files changed, 123 insertions(+), 14 deletions(-)
Fails to apply with git am on current master
> warning: Patch sent with format=flowed; space at the end of lines
> might be lost.
> Applying: liavcodec: add bit-rate support to RoQ video encoder
> error: corrupt patch at line 20
> Patch failed at 0001 liavcodec: add bit-rate support to RoQ video
> encoder
Typo: liavcodec
> + /* Keyframe when no MOT or FCC codes in frame */
> + if (s->key_frame) {
> + av_log(avctx, AV_LOG_VERBOSE, "\nFound keyframe!\n");
> + rframe->pict_type = AV_PICTURE_TYPE_I;
> + avpkt->flags |= AV_PKT_FLAG_KEY;
Consider resetting framesSinceKeyframe here
> - if (avctx->width > 65535 || avctx->height > 65535) {
The leading space is probably what makes the patch not apply
> - av_log(avctx, AV_LOG_ERROR, "Dimensions are max %d\n", enc-
> >quake3_compat ? 32768 : 65535);
> + if (enc->quake3_compat && ((avctx->width > 32767 || avctx-
> >height > 32767))) {
> + av_log(avctx, AV_LOG_ERROR, "Dimensions are max %d\n",
> 32767);
> + return AVERROR(EINVAL);
> + }
> + else if (avctx->width > 65535 || avctx->height > 65535) {
> + av_log(avctx, AV_LOG_ERROR, "Dimensions are max %d\n",
> 65535);
> return AVERROR(EINVAL);
> }
> - if (((avctx->width)&(avctx->width-1))||((avctx->height)&(avctx-
> >height-1)))
> + if (enc->quake3_compat && ((avctx->width)&(avctx->width-
> 1))||((avctx->height)&(avctx->height-1)))
> av_log(avctx, AV_LOG_ERROR, "Warning: dimensions not power
> of two, this is not supported by quake\n");
These changes appear to be unrelated to bitrate. Consider separating
them into a separate patch.
> - if (frame->quality)
> - enc->lambda = frame->quality - 1;
> - else
> - enc->lambda = 2*ROQ_LAMBDA_SCALE;
> + if (avctx->bit_rate <= ROQ_DEFAULT_MIN_BIT_RATE) {
> + /* no specific bit rate desired, use frame quality */
> + if (frame->quality)
> + enc->lambda = frame->quality - 1;
> + else
> + enc->lambda = 2*ROQ_LAMBDA_SCALE;
> + }
This looks like a bit of a janky way to switch between qscale and
bitrate. Isn't there a way to detect whether an option has been set
explicitly? At the very least this behavior should be documented in
doc/encoders.texi
/Tomas
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
2024-01-22 13:05 ` Tomas Härdin
@ 2024-01-22 13:38 ` Victor Luchitz
2024-01-22 13:57 ` Tomas Härdin
0 siblings, 1 reply; 18+ messages in thread
From: Victor Luchitz @ 2024-01-22 13:38 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Mon, Jan 22, 2024 at 4:06 PM Tomas Härdin <git@haerdin.se> wrote:
> mån 2024-01-22 klockan 00:08 +0300 skrev Victor Luchits:
> > One can now use the bitrate option (-b) to specify bit rate of the
> > video
> > stream in the RoQ encoder. The option only becomes effective for
> > values
> > above 800kbit/s, which is roughly equivalent to bandwidth of a 1x-
> > speed
> > CD-ROM drive, minus the bandwidth taken up by stereo DPCM stream.
> > Values
> > below this threshold produce visually inadequate results.
> >
> > Original patch by Joseph Fenton aka Chilly Willy
> >
> > Signed-off-by: Victor Luchits <vluchits@gmail.com>
> > ---
> > Changelog | 1 +
> > libavcodec/roqvideo.h | 1 +
> > libavcodec/roqvideodec.c | 15 +++++
> > libavcodec/roqvideoenc.c | 118 ++++++++++++++++++++++++++++++++++--
> > ---
> > libavcodec/version.h | 2 +-
> > 5 files changed, 123 insertions(+), 14 deletions(-)
>
> Fails to apply with git am on current master
>
> > warning: Patch sent with format=flowed; space at the end of lines
> > might be lost.
> > Applying: liavcodec: add bit-rate support to RoQ video encoder
> > error: corrupt patch at line 20
> > Patch failed at 0001 liavcodec: add bit-rate support to RoQ video
> > encoder
>
> Typo: liavcodec
>
> > + /* Keyframe when no MOT or FCC codes in frame */
> > + if (s->key_frame) {
> > + av_log(avctx, AV_LOG_VERBOSE, "\nFound keyframe!\n");
> > + rframe->pict_type = AV_PICTURE_TYPE_I;
> > + avpkt->flags |= AV_PKT_FLAG_KEY;
>
> Consider resetting framesSinceKeyframe here
>
Thanks, good catch, gonna look into that.
>
> > - if (avctx->width > 65535 || avctx->height > 65535) {
>
> The leading space is probably what makes the patch not apply
>
Found it, thanks.
>
> > - av_log(avctx, AV_LOG_ERROR, "Dimensions are max %d\n", enc-
> > >quake3_compat ? 32768 : 65535);
> > + if (enc->quake3_compat && ((avctx->width > 32767 || avctx-
> > >height > 32767))) {
> > + av_log(avctx, AV_LOG_ERROR, "Dimensions are max %d\n",
> > 32767);
> > + return AVERROR(EINVAL);
> > + }
> > + else if (avctx->width > 65535 || avctx->height > 65535) {
> > + av_log(avctx, AV_LOG_ERROR, "Dimensions are max %d\n",
> > 65535);
> > return AVERROR(EINVAL);
> > }
> > - if (((avctx->width)&(avctx->width-1))||((avctx->height)&(avctx-
> > >height-1)))
> > + if (enc->quake3_compat && ((avctx->width)&(avctx->width-
> > 1))||((avctx->height)&(avctx->height-1)))
> > av_log(avctx, AV_LOG_ERROR, "Warning: dimensions not power
> > of two, this is not supported by quake\n");
>
> These changes appear to be unrelated to bitrate. Consider separating
> them into a separate patch.
>
Noted.
>
> > - if (frame->quality)
> > - enc->lambda = frame->quality - 1;
> > - else
> > - enc->lambda = 2*ROQ_LAMBDA_SCALE;
> > + if (avctx->bit_rate <= ROQ_DEFAULT_MIN_BIT_RATE) {
> > + /* no specific bit rate desired, use frame quality */
> > + if (frame->quality)
> > + enc->lambda = frame->quality - 1;
> > + else
> > + enc->lambda = 2*ROQ_LAMBDA_SCALE;
> > + }
>
> This looks like a bit of a janky way to switch between qscale and
> bitrate. Isn't there a way to detect whether an option has been set
> explicitly? At the very least this behavior should be documented in
> doc/encoders.texi
>
Originally, the code just checked for bit_rate != AV_CODEC_DEFAULT_BITRATE,
which required including options_table.h, which in turn produced a bunch
of compilation warnings about certain fields being deprecated. None of the
other codecs include that file + many simply check the bit_rate field
against
magic constants. That made me assume that including options_table.h
goes against the common practice.
>
> /Tomas
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
--
Best regards,
Victor Luchitz
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
2024-01-22 13:38 ` Victor Luchitz
@ 2024-01-22 13:57 ` Tomas Härdin
2024-01-22 13:59 ` Martin Storsjö
2024-01-22 18:32 ` Victor Luchitz
0 siblings, 2 replies; 18+ messages in thread
From: Tomas Härdin @ 2024-01-22 13:57 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> >
> > > - if (frame->quality)
> > > - enc->lambda = frame->quality - 1;
> > > - else
> > > - enc->lambda = 2*ROQ_LAMBDA_SCALE;
> > > + if (avctx->bit_rate <= ROQ_DEFAULT_MIN_BIT_RATE) {
> > > + /* no specific bit rate desired, use frame quality */
> > > + if (frame->quality)
> > > + enc->lambda = frame->quality - 1;
> > > + else
> > > + enc->lambda = 2*ROQ_LAMBDA_SCALE;
> > > + }
> >
> > This looks like a bit of a janky way to switch between qscale and
> > bitrate. Isn't there a way to detect whether an option has been set
> > explicitly? At the very least this behavior should be documented in
> > doc/encoders.texi
> >
>
> Originally, the code just checked for bit_rate !=
> AV_CODEC_DEFAULT_BITRATE,
> which required including options_table.h, which in turn produced a
> bunch
> of compilation warnings about certain fields being deprecated. None
> of the
> other codecs include that file + many simply check the bit_rate field
> against
> magic constants.
grepping for 200000 didn't reveal anything like that. Do you have a
specific example of an encoder that does this?
Perhaps we could move AV_CODEC_DEFAULT_BITRATE somewhere else, to avoid
pulling in a bunch of unrelated stuff. Maybe that doesn't need to hold
up this patch though. Tbh the way bitrate is defaulted to a value,
which makes it impossible to differentiate between a user-supplied -b
200k an no -b at all, is even more janky. The default is also
ridiculously low..
I know some encoders like libvpx allow specifying both quality (-crf)
and bitrate at the same time
/Tomas
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
2024-01-22 13:57 ` Tomas Härdin
@ 2024-01-22 13:59 ` Martin Storsjö
2024-01-22 14:19 ` Tomas Härdin
2024-01-22 16:21 ` Victor Luchitz
2024-01-22 18:32 ` Victor Luchitz
1 sibling, 2 replies; 18+ messages in thread
From: Martin Storsjö @ 2024-01-22 13:59 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Mon, 22 Jan 2024, Tomas Härdin wrote:
>>> >>> - if (frame->quality)
>> > > - enc->lambda = frame->quality - 1;
>> > > - else
>> > > - enc->lambda = 2*ROQ_LAMBDA_SCALE;
>> > > + if (avctx->bit_rate <= ROQ_DEFAULT_MIN_BIT_RATE) {
>> > > + /* no specific bit rate desired, use frame quality */
>> > > + if (frame->quality)
>> > > + enc->lambda = frame->quality - 1;
>> > > + else
>> > > + enc->lambda = 2*ROQ_LAMBDA_SCALE;
>> > > + }
>> >
>> > This looks like a bit of a janky way to switch between qscale and
>> > bitrate. Isn't there a way to detect whether an option has been set
>> > explicitly? At the very least this behavior should be documented in
>> > doc/encoders.texi
>> >
>>
>> Originally, the code just checked for bit_rate !=
>> AV_CODEC_DEFAULT_BITRATE,
>> which required including options_table.h, which in turn produced a
>> bunch
>> of compilation warnings about certain fields being deprecated. None
>> of the
>> other codecs include that file + many simply check the bit_rate field
>> against
>> magic constants.
>
> grepping for 200000 didn't reveal anything like that. Do you have a
> specific example of an encoder that does this?
>
> Perhaps we could move AV_CODEC_DEFAULT_BITRATE somewhere else, to avoid
> pulling in a bunch of unrelated stuff. Maybe that doesn't need to hold
> up this patch though. Tbh the way bitrate is defaulted to a value,
> which makes it impossible to differentiate between a user-supplied -b
> 200k an no -b at all, is even more janky. The default is also
> ridiculously low..
>
> I know some encoders like libvpx allow specifying both quality (-crf)
> and bitrate at the same time
FWIW, it's possible for an encoder to individually override the defaults
for fields like these. See e.g. x264_defaults in libx264.c, where it
overrides the default bitrate to zero.
// Martin
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
2024-01-22 13:59 ` Martin Storsjö
@ 2024-01-22 14:19 ` Tomas Härdin
2024-01-22 16:36 ` Victor Luchitz
2024-01-22 16:21 ` Victor Luchitz
1 sibling, 1 reply; 18+ messages in thread
From: Tomas Härdin @ 2024-01-22 14:19 UTC (permalink / raw)
To: FFmpeg development discussions and patches
mån 2024-01-22 klockan 15:59 +0200 skrev Martin Storsjö:
> On Mon, 22 Jan 2024, Tomas Härdin wrote:
>
> > > > > > > - if (frame->quality)
> > > > > - enc->lambda = frame->quality - 1;
> > > > > - else
> > > > > - enc->lambda = 2*ROQ_LAMBDA_SCALE;
> > > > > + if (avctx->bit_rate <= ROQ_DEFAULT_MIN_BIT_RATE) {
> > > > > + /* no specific bit rate desired, use frame quality
> > > > > */
> > > > > + if (frame->quality)
> > > > > + enc->lambda = frame->quality - 1;
> > > > > + else
> > > > > + enc->lambda = 2*ROQ_LAMBDA_SCALE;
> > > > > + }
> > > >
> > > > This looks like a bit of a janky way to switch between qscale
> > > > and
> > > > bitrate. Isn't there a way to detect whether an option has been
> > > > set
> > > > explicitly? At the very least this behavior should be
> > > > documented in
> > > > doc/encoders.texi
> > > >
> > >
> > > Originally, the code just checked for bit_rate !=
> > > AV_CODEC_DEFAULT_BITRATE,
> > > which required including options_table.h, which in turn produced
> > > a
> > > bunch
> > > of compilation warnings about certain fields being deprecated.
> > > None
> > > of the
> > > other codecs include that file + many simply check the bit_rate
> > > field
> > > against
> > > magic constants.
> >
> > grepping for 200000 didn't reveal anything like that. Do you have a
> > specific example of an encoder that does this?
> >
> > Perhaps we could move AV_CODEC_DEFAULT_BITRATE somewhere else, to
> > avoid
> > pulling in a bunch of unrelated stuff. Maybe that doesn't need to
> > hold
> > up this patch though. Tbh the way bitrate is defaulted to a value,
> > which makes it impossible to differentiate between a user-supplied
> > -b
> > 200k an no -b at all, is even more janky. The default is also
> > ridiculously low..
> >
> > I know some encoders like libvpx allow specifying both quality (-
> > crf)
> > and bitrate at the same time
>
> FWIW, it's possible for an encoder to individually override the
> defaults
> for fields like these. See e.g. x264_defaults in libx264.c, where it
> overrides the default bitrate to zero.
Ooh, didn't know that. That sounds like a decent solution here. Can RoQ
really not do < 800 kbps at all or is it just that it looks bad with
say 256x256 but perhaps more decent with 128x128 or so?
/Tomas
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
2024-01-22 14:19 ` Tomas Härdin
@ 2024-01-22 16:36 ` Victor Luchitz
0 siblings, 0 replies; 18+ messages in thread
From: Victor Luchitz @ 2024-01-22 16:36 UTC (permalink / raw)
To: FFmpeg development discussions and patches
The rationale behind the bit_rate check is that RoQ was originally
designed with early CD-ROM games in mind (The 7th Guest, The
11th Hour), thus the lowest bit_rate that would make any sense in
that context should be based around that. You really want to get
the best picture quality without exceeding the 150KB/s limit of the
drive.
I also did try various lower bitrates, including the default one, on a
variety of files, and they resulted in either extremely poor visuals,
or the encoder spending a lot of extra time trying to downgrade the
picture quality before giving up. Or both. I didn't try extremely low
resolutions such as 128x128, as I don't see why anyone would
want to specify a bitrate that is less than that of a 1x CD-ROM
drive, while also using a viewport the size of a post stamp.
Either way, I'd really appreciate your input on how to deal with this
situation.
On Mon, Jan 22, 2024 at 5:19 PM Tomas Härdin <git@haerdin.se> wrote:
> mån 2024-01-22 klockan 15:59 +0200 skrev Martin Storsjö:
> > On Mon, 22 Jan 2024, Tomas Härdin wrote:
> >
> > > > > > > > - if (frame->quality)
> > > > > > - enc->lambda = frame->quality - 1;
> > > > > > - else
> > > > > > - enc->lambda = 2*ROQ_LAMBDA_SCALE;
> > > > > > + if (avctx->bit_rate <= ROQ_DEFAULT_MIN_BIT_RATE) {
> > > > > > + /* no specific bit rate desired, use frame quality
> > > > > > */
> > > > > > + if (frame->quality)
> > > > > > + enc->lambda = frame->quality - 1;
> > > > > > + else
> > > > > > + enc->lambda = 2*ROQ_LAMBDA_SCALE;
> > > > > > + }
> > > > >
> > > > > This looks like a bit of a janky way to switch between qscale
> > > > > and
> > > > > bitrate. Isn't there a way to detect whether an option has been
> > > > > set
> > > > > explicitly? At the very least this behavior should be
> > > > > documented in
> > > > > doc/encoders.texi
> > > > >
> > > >
> > > > Originally, the code just checked for bit_rate !=
> > > > AV_CODEC_DEFAULT_BITRATE,
> > > > which required including options_table.h, which in turn produced
> > > > a
> > > > bunch
> > > > of compilation warnings about certain fields being deprecated.
> > > > None
> > > > of the
> > > > other codecs include that file + many simply check the bit_rate
> > > > field
> > > > against
> > > > magic constants.
> > >
> > > grepping for 200000 didn't reveal anything like that. Do you have a
> > > specific example of an encoder that does this?
> > >
> > > Perhaps we could move AV_CODEC_DEFAULT_BITRATE somewhere else, to
> > > avoid
> > > pulling in a bunch of unrelated stuff. Maybe that doesn't need to
> > > hold
> > > up this patch though. Tbh the way bitrate is defaulted to a value,
> > > which makes it impossible to differentiate between a user-supplied
> > > -b
> > > 200k an no -b at all, is even more janky. The default is also
> > > ridiculously low..
> > >
> > > I know some encoders like libvpx allow specifying both quality (-
> > > crf)
> > > and bitrate at the same time
> >
> > FWIW, it's possible for an encoder to individually override the
> > defaults
> > for fields like these. See e.g. x264_defaults in libx264.c, where it
> > overrides the default bitrate to zero.
>
> Ooh, didn't know that. That sounds like a decent solution here. Can RoQ
> really not do < 800 kbps at all or is it just that it looks bad with
> say 256x256 but perhaps more decent with 128x128 or so?
>
> /Tomas
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
--
Best regards,
Victor Luchitz
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
2024-01-22 13:59 ` Martin Storsjö
2024-01-22 14:19 ` Tomas Härdin
@ 2024-01-22 16:21 ` Victor Luchitz
1 sibling, 0 replies; 18+ messages in thread
From: Victor Luchitz @ 2024-01-22 16:21 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Thanks, I will look into it
On Mon, Jan 22, 2024 at 4:59 PM Martin Storsjö <martin@martin.st> wrote:
> On Mon, 22 Jan 2024, Tomas Härdin wrote:
>
> >>> >>> - if (frame->quality)
> >> > > - enc->lambda = frame->quality - 1;
> >> > > - else
> >> > > - enc->lambda = 2*ROQ_LAMBDA_SCALE;
> >> > > + if (avctx->bit_rate <= ROQ_DEFAULT_MIN_BIT_RATE) {
> >> > > + /* no specific bit rate desired, use frame quality */
> >> > > + if (frame->quality)
> >> > > + enc->lambda = frame->quality - 1;
> >> > > + else
> >> > > + enc->lambda = 2*ROQ_LAMBDA_SCALE;
> >> > > + }
> >> >
> >> > This looks like a bit of a janky way to switch between qscale and
> >> > bitrate. Isn't there a way to detect whether an option has been set
> >> > explicitly? At the very least this behavior should be documented in
> >> > doc/encoders.texi
> >> >
> >>
> >> Originally, the code just checked for bit_rate !=
> >> AV_CODEC_DEFAULT_BITRATE,
> >> which required including options_table.h, which in turn produced a
> >> bunch
> >> of compilation warnings about certain fields being deprecated. None
> >> of the
> >> other codecs include that file + many simply check the bit_rate field
> >> against
> >> magic constants.
> >
> > grepping for 200000 didn't reveal anything like that. Do you have a
> > specific example of an encoder that does this?
> >
> > Perhaps we could move AV_CODEC_DEFAULT_BITRATE somewhere else, to avoid
> > pulling in a bunch of unrelated stuff. Maybe that doesn't need to hold
> > up this patch though. Tbh the way bitrate is defaulted to a value,
> > which makes it impossible to differentiate between a user-supplied -b
> > 200k an no -b at all, is even more janky. The default is also
> > ridiculously low..
> >
> > I know some encoders like libvpx allow specifying both quality (-crf)
> > and bitrate at the same time
>
> FWIW, it's possible for an encoder to individually override the defaults
> for fields like these. See e.g. x264_defaults in libx264.c, where it
> overrides the default bitrate to zero.
>
> // Martin
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
--
Best regards,
Victor Luchitz
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
2024-01-22 13:57 ` Tomas Härdin
2024-01-22 13:59 ` Martin Storsjö
@ 2024-01-22 18:32 ` Victor Luchitz
2024-01-22 19:10 ` Tomas Härdin
1 sibling, 1 reply; 18+ messages in thread
From: Victor Luchitz @ 2024-01-22 18:32 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Mon, Jan 22, 2024 at 4:57 PM Tomas Härdin <git@haerdin.se> wrote:
> > >
> > > > - if (frame->quality)
> > > > - enc->lambda = frame->quality - 1;
> > > > - else
> > > > - enc->lambda = 2*ROQ_LAMBDA_SCALE;
> > > > + if (avctx->bit_rate <= ROQ_DEFAULT_MIN_BIT_RATE) {
> > > > + /* no specific bit rate desired, use frame quality */
> > > > + if (frame->quality)
> > > > + enc->lambda = frame->quality - 1;
> > > > + else
> > > > + enc->lambda = 2*ROQ_LAMBDA_SCALE;
> > > > + }
> > >
> > > This looks like a bit of a janky way to switch between qscale and
> > > bitrate. Isn't there a way to detect whether an option has been set
> > > explicitly? At the very least this behavior should be documented in
> > > doc/encoders.texi
> > >
> >
> > Originally, the code just checked for bit_rate !=
> > AV_CODEC_DEFAULT_BITRATE,
> > which required including options_table.h, which in turn produced a
> > bunch
> > of compilation warnings about certain fields being deprecated. None
> > of the
> > other codecs include that file + many simply check the bit_rate field
> > against
> > magic constants.
>
> grepping for 200000 didn't reveal anything like that. Do you have a
> specific example of an encoder that does this?
>
~/ffmpeg/libavcodec# grep -RI bit_rate . | grep 000 | grep -v 1000 | wc -l
38
Most of the cases here are comparisons against magic constants without
any comments about how they were chosen or what they do, none whatsoever.
> Perhaps we could move AV_CODEC_DEFAULT_BITRATE somewhere else, to avoid
> pulling in a bunch of unrelated stuff. Maybe that doesn't need to hold
> up this patch though. Tbh the way bitrate is defaulted to a value,
> which makes it impossible to differentiate between a user-supplied -b
> 200k an no -b at all, is even more janky. The default is also
> ridiculously low..
>
> I know some encoders like libvpx allow specifying both quality (-crf)
> and bitrate at the same time
>
> /Tomas
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
--
Best regards,
Victor Luchitz
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
2024-01-22 18:32 ` Victor Luchitz
@ 2024-01-22 19:10 ` Tomas Härdin
2024-01-22 19:16 ` Victor Luchitz
0 siblings, 1 reply; 18+ messages in thread
From: Tomas Härdin @ 2024-01-22 19:10 UTC (permalink / raw)
To: FFmpeg development discussions and patches
mån 2024-01-22 klockan 21:32 +0300 skrev Victor Luchitz:
> On Mon, Jan 22, 2024 at 4:57 PM Tomas Härdin <git@haerdin.se> wrote:
>
> > > >
> > > > > - if (frame->quality)
> > > > > - enc->lambda = frame->quality - 1;
> > > > > - else
> > > > > - enc->lambda = 2*ROQ_LAMBDA_SCALE;
> > > > > + if (avctx->bit_rate <= ROQ_DEFAULT_MIN_BIT_RATE) {
> > > > > + /* no specific bit rate desired, use frame quality
> > > > > */
> > > > > + if (frame->quality)
> > > > > + enc->lambda = frame->quality - 1;
> > > > > + else
> > > > > + enc->lambda = 2*ROQ_LAMBDA_SCALE;
> > > > > + }
> > > >
> > > > This looks like a bit of a janky way to switch between qscale
> > > > and
> > > > bitrate. Isn't there a way to detect whether an option has been
> > > > set
> > > > explicitly? At the very least this behavior should be
> > > > documented in
> > > > doc/encoders.texi
> > > >
> > >
> > > Originally, the code just checked for bit_rate !=
> > > AV_CODEC_DEFAULT_BITRATE,
> > > which required including options_table.h, which in turn produced
> > > a
> > > bunch
> > > of compilation warnings about certain fields being deprecated.
> > > None
> > > of the
> > > other codecs include that file + many simply check the bit_rate
> > > field
> > > against
> > > magic constants.
> >
> > grepping for 200000 didn't reveal anything like that. Do you have a
> > specific example of an encoder that does this?
> >
>
> ~/ffmpeg/libavcodec# grep -RI bit_rate . | grep 000 | grep -v 1000 |
> wc -l
> 38
Most of these seem to revolve around sane defaults, picking various
submodes or rejecting too high or too low bitrates
> Most of the cases here are comparisons against magic constants
> without
> any comments about how they were chosen or what they do, none
> whatsoever.
I would suggest adding a different default as Martin suggests. If users
really want shitty encodes I see no reason to deny them. I could see it
being useful for modders.
You might want an option for the tolerance stuff too
/Tomas
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
2024-01-22 19:10 ` Tomas Härdin
@ 2024-01-22 19:16 ` Victor Luchitz
0 siblings, 0 replies; 18+ messages in thread
From: Victor Luchitz @ 2024-01-22 19:16 UTC (permalink / raw)
To: FFmpeg development discussions and patches
I've just posted a new version of the patch that addresses most (if not
all) of the comments from previous reviews.
On Mon, Jan 22, 2024 at 10:10 PM Tomas Härdin <git@haerdin.se> wrote:
> mån 2024-01-22 klockan 21:32 +0300 skrev Victor Luchitz:
> > On Mon, Jan 22, 2024 at 4:57 PM Tomas Härdin <git@haerdin.se> wrote:
> >
> > > > >
> > > > > > - if (frame->quality)
> > > > > > - enc->lambda = frame->quality - 1;
> > > > > > - else
> > > > > > - enc->lambda = 2*ROQ_LAMBDA_SCALE;
> > > > > > + if (avctx->bit_rate <= ROQ_DEFAULT_MIN_BIT_RATE) {
> > > > > > + /* no specific bit rate desired, use frame quality
> > > > > > */
> > > > > > + if (frame->quality)
> > > > > > + enc->lambda = frame->quality - 1;
> > > > > > + else
> > > > > > + enc->lambda = 2*ROQ_LAMBDA_SCALE;
> > > > > > + }
> > > > >
> > > > > This looks like a bit of a janky way to switch between qscale
> > > > > and
> > > > > bitrate. Isn't there a way to detect whether an option has been
> > > > > set
> > > > > explicitly? At the very least this behavior should be
> > > > > documented in
> > > > > doc/encoders.texi
> > > > >
> > > >
> > > > Originally, the code just checked for bit_rate !=
> > > > AV_CODEC_DEFAULT_BITRATE,
> > > > which required including options_table.h, which in turn produced
> > > > a
> > > > bunch
> > > > of compilation warnings about certain fields being deprecated.
> > > > None
> > > > of the
> > > > other codecs include that file + many simply check the bit_rate
> > > > field
> > > > against
> > > > magic constants.
> > >
> > > grepping for 200000 didn't reveal anything like that. Do you have a
> > > specific example of an encoder that does this?
> > >
> >
> > ~/ffmpeg/libavcodec# grep -RI bit_rate . | grep 000 | grep -v 1000 |
> > wc -l
> > 38
>
> Most of these seem to revolve around sane defaults, picking various
> submodes or rejecting too high or too low bitrates
>
>
> > Most of the cases here are comparisons against magic constants
> > without
> > any comments about how they were chosen or what they do, none
> > whatsoever.
>
> I would suggest adding a different default as Martin suggests. If users
> really want shitty encodes I see no reason to deny them. I could see it
> being useful for modders.
>
> You might want an option for the tolerance stuff too
>
> /Tomas
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
--
Best regards,
Victor Luchitz
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
* [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
@ 2024-01-21 20:19 Victor Luchits
2024-01-21 21:02 ` Michael Niedermayer
0 siblings, 1 reply; 18+ messages in thread
From: Victor Luchits @ 2024-01-21 20:19 UTC (permalink / raw)
To: ffmpeg-devel
One can now use the bitrate option (-b) to specify bit rate of the video
stream in the RoQ encoder. The option only becomes effective for values
above 800kbit/s, which is roughly equivalent to bandwidth of a 1x-speed
CD-ROM drive, minus the bandwidth taken up by stereo DPCM stream. Values
below this threshold produce visually inadequate results.
Original patch by Joseph Fenton aka Chilly Willy
Signed-off-by: Victor Luchits <vluchits@gmail.com>
---
Changelog | 1 +
libavcodec/roqvideo.h | 1 +
libavcodec/roqvideodec.c | 15 +++++
libavcodec/roqvideoenc.c | 118 ++++++++++++++++++++++++++++++++++-----
libavcodec/version.h | 2 +-
5 files changed, 123 insertions(+), 14 deletions(-)
diff --git a/Changelog b/Changelog
index c40b6d08fd..6974312f9d 100644
--- a/Changelog
+++ b/Changelog
@@ -22,6 +22,7 @@ version <next>:
- ffmpeg CLI -bsf option may now be used for input as well as output
- ffmpeg CLI options may now be used as -/opt <path>, which is equivalent
to -opt <contents of file <path>>
+- RoQ video bit rate option support
version 6.1:
- libaribcaption decoder
diff --git a/libavcodec/roqvideo.h b/libavcodec/roqvideo.h
index 2c2e42884d..6d30bcaada 100644
--- a/libavcodec/roqvideo.h
+++ b/libavcodec/roqvideo.h
@@ -43,6 +43,7 @@ typedef struct RoqContext {
AVFrame *last_frame;
AVFrame *current_frame;
int width, height;
+ int key_frame;
roq_cell cb2x2[256];
roq_qcell cb4x4[256];
diff --git a/libavcodec/roqvideodec.c b/libavcodec/roqvideodec.c
index bfc69a65c9..07d6b8bb8f 100644
--- a/libavcodec/roqvideodec.c
+++ b/libavcodec/roqvideodec.c
@@ -70,6 +70,7 @@ static void roqvideo_decode_frame(RoqContext *ri,
GetByteContext *gb)
chunk_start = bytestream2_tell(gb);
xpos = ypos = 0;
+ ri->key_frame = 1;
if (chunk_size > bytestream2_get_bytes_left(gb)) {
av_log(ri->logctx, AV_LOG_ERROR, "Chunk does not fit in input
buffer\n");
@@ -92,12 +93,14 @@ static void roqvideo_decode_frame(RoqContext *ri,
GetByteContext *gb)
switch(vqid) {
case RoQ_ID_MOT:
+ ri->key_frame = 0;
break;
case RoQ_ID_FCC: {
int byte = bytestream2_get_byte(gb);
mx = 8 - (byte >> 4) - ((signed char) (chunk_arg
>> 8));
my = 8 - (byte & 0xf) - ((signed char) chunk_arg);
ff_apply_motion_8x8(ri, xp, yp, mx, my);
+ ri->key_frame = 0;
break;
}
case RoQ_ID_SLD:
@@ -125,12 +128,14 @@ static void roqvideo_decode_frame(RoqContext *ri,
GetByteContext *gb)
vqflg_pos--;
switch(vqid) {
case RoQ_ID_MOT:
+ ri->key_frame = 0;
break;
case RoQ_ID_FCC: {
int byte = bytestream2_get_byte(gb);
mx = 8 - (byte >> 4) - ((signed char)
(chunk_arg >> 8));
my = 8 - (byte & 0xf) - ((signed char)
chunk_arg);
ff_apply_motion_4x4(ri, x, y, mx, my);
+ ri->key_frame = 0;
break;
}
case RoQ_ID_SLD:
@@ -214,6 +219,16 @@ static int roq_decode_frame(AVCodecContext *avctx,
AVFrame *rframe,
if ((ret = av_frame_ref(rframe, s->current_frame)) < 0)
return ret;
+
+ /* Keyframe when no MOT or FCC codes in frame */
+ if (s->key_frame) {
+ av_log(avctx, AV_LOG_VERBOSE, "\nFound keyframe!\n");
+ rframe->pict_type = AV_PICTURE_TYPE_I;
+ avpkt->flags |= AV_PKT_FLAG_KEY;
+ } else {
+ rframe->pict_type = AV_PICTURE_TYPE_P;
+ }
+
*got_frame = 1;
/* shuffle frames */
diff --git a/libavcodec/roqvideoenc.c b/libavcodec/roqvideoenc.c
index 0933abf4f9..bcead80bbd 100644
--- a/libavcodec/roqvideoenc.c
+++ b/libavcodec/roqvideoenc.c
@@ -79,6 +79,9 @@
/* The cast is useful when multiplying it by INT_MAX */
#define ROQ_LAMBDA_SCALE ((uint64_t) FF_LAMBDA_SCALE)
+/* The default minimum bitrate, set around the value of a 1x speed
CD-ROM drive */
+#define ROQ_DEFAULT_MIN_BIT_RATE 800*1024
+
typedef struct RoqCodebooks {
int numCB4;
int numCB2;
@@ -136,6 +139,8 @@ typedef struct RoqEncContext {
struct ELBGContext *elbg;
AVLFG randctx;
uint64_t lambda;
+ uint64_t last_lambda;
+ int lambda_delta;
motion_vect *this_motion4;
motion_vect *last_motion4;
@@ -887,8 +892,9 @@ static int generate_new_codebooks(RoqEncContext *enc)
return 0;
}
-static int roq_encode_video(RoqEncContext *enc)
+static int roq_encode_video(AVCodecContext *avctx)
{
+ RoqEncContext *const enc = avctx->priv_data;
RoqTempData *const tempData = &enc->tmp_data;
RoqContext *const roq = &enc->common;
int ret;
@@ -910,14 +916,14 @@ static int roq_encode_video(RoqEncContext *enc)
/* Quake 3 can't handle chunks bigger than 65535 bytes */
if (tempData->mainChunkSize/8 > 65535 && enc->quake3_compat) {
- if (enc->lambda > 100000) {
+ if (enc->lambda > 100000000) {
av_log(roq->logctx, AV_LOG_ERROR, "Cannot encode video in
Quake compatible form\n");
return AVERROR(EINVAL);
}
av_log(roq->logctx, AV_LOG_ERROR,
"Warning, generated a frame too big for Quake (%d >
65535), "
- "now switching to a bigger qscale value.\n",
- tempData->mainChunkSize/8);
+ "now switching to a bigger qscale value (%d).\n",
+ tempData->mainChunkSize/8, (int)enc->lambda);
enc->lambda *= 1.5;
tempData->mainChunkSize = 0;
memset(tempData->used_option, 0, sizeof(tempData->used_option));
@@ -931,6 +937,80 @@ static int roq_encode_video(RoqEncContext *enc)
remap_codebooks(enc);
+ /* bit rate control code - could make encoding very slow */
+ if (avctx->bit_rate > ROQ_DEFAULT_MIN_BIT_RATE) {
+ /* a bit rate has been specified - try to match it */
+ int ftotal = (tempData->mainChunkSize / 8 + tempData->numCB2*6
+ tempData->numCB4*4) * avctx->time_base.den * 8;
+ int64_t tol = avctx->bit_rate_tolerance;
+
+ /* tolerance > bit rate, set to 5% of the bit rate */
+ if (tol > avctx->bit_rate)
+ tol = avctx->bit_rate / 20;
+
+ av_log(roq->logctx, AV_LOG_VERBOSE,
+ "\nDesired bit rate (%d kbps), "
+ "Bit rate tolerance (%d), "
+ "Frame rate (%d)\n",
+ (int)avctx->bit_rate, (int)tol, avctx->time_base.den);
+
+ if (ftotal > (avctx->bit_rate + tol)) {
+ /* frame is too big - increase qscale */
+ if (enc->lambda > 100000000) {
+ av_log(roq->logctx, AV_LOG_ERROR, "\nCannot encode
video at desired bitrate\n");
+ return AVERROR(EINVAL);
+ }
+ enc->lambda_delta = enc->lambda_delta <= 0 ? 1 :
enc->lambda_delta < 65536 ? enc->lambda_delta*2 : 65536;
+ enc->last_lambda = enc->lambda;
+ enc->lambda += enc->lambda_delta;
+ av_log(roq->logctx, AV_LOG_INFO,
+ "\nGenerated a frame too big for desired bit rate
(%d kbps), "
+ "now switching to a bigger qscale value (%d).\n",
+ ftotal / 1000, (int)enc->lambda);
+ tempData->mainChunkSize = 0;
+ memset(tempData->used_option, 0,
sizeof(tempData->used_option));
+ memset(tempData->codebooks.usedCB4, 0,
+ sizeof(tempData->codebooks.usedCB4));
+ memset(tempData->codebooks.usedCB2, 0,
+ sizeof(tempData->codebooks.usedCB2));
+
+ goto retry_encode;
+ } else if (ftotal < (avctx->bit_rate - tol)) {
+ /* frame is too small - decrease qscale */
+ if (enc->lambda <= 1) {
+ av_log(roq->logctx, AV_LOG_WARNING,
+ "\nGenerated a frame too small for desired bit
rate (%d kbps), "
+ "qscale value cannot be lowered any further
(%d).\n",
+ ftotal / 1000, (int)enc->lambda);
+ } else if ((enc->lambda - enc->last_lambda) == 1) {
+ av_log(roq->logctx, AV_LOG_WARNING,
+ "\nCannot find qscale that gives desired bit
rate within desired tolerance, "
+ "using lower bitrate (%d kbps) with higher
qscale value (%d).\n",
+ ftotal / 1000, (int)enc->lambda);
+ } else {
+ enc->lambda_delta = 0;
+ if (enc->lambda == enc->last_lambda) {
+ enc->lambda >>= 1;
+ enc->last_lambda = enc->lambda;
+ } else {
+ enc->lambda = enc->last_lambda;
+ //enc->lambda *= (float)(tempData->mainChunkSize *
avctx->time_base.den) / avctx->bit_rate;
+ av_log(roq->logctx, AV_LOG_INFO,
+ "\nGenerated a frame too small for desired
bit rate (%d kbps), "
+ "reverting lambda and using smaller inc on
qscale (%d).\n",
+ ftotal / 1000, (int)enc->lambda);
+ }
+ tempData->mainChunkSize = 0;
+ memset(tempData->used_option, 0,
sizeof(tempData->used_option));
+ memset(tempData->codebooks.usedCB4, 0,
+ sizeof(tempData->codebooks.usedCB4));
+ memset(tempData->codebooks.usedCB2, 0,
+ sizeof(tempData->codebooks.usedCB2));
+
+ goto retry_encode;
+ }
+ }
+ }
+ write_codebooks(enc);
reconstruct_and_encode_image(enc, roq->width, roq->height,
@@ -980,19 +1060,26 @@ static av_cold int roq_encode_init(AVCodecContext
*avctx)
return AVERROR(EINVAL);
}
- if (avctx->width > 65535 || avctx->height > 65535) {
- av_log(avctx, AV_LOG_ERROR, "Dimensions are max %d\n",
enc->quake3_compat ? 32768 : 65535);
+ if (enc->quake3_compat && ((avctx->width > 32767 || avctx->height >
32767))) {
+ av_log(avctx, AV_LOG_ERROR, "Dimensions are max %d\n", 32767);
+ return AVERROR(EINVAL);
+ }
+ else if (avctx->width > 65535 || avctx->height > 65535) {
+ av_log(avctx, AV_LOG_ERROR, "Dimensions are max %d\n", 65535);
return AVERROR(EINVAL);
}
- if
(((avctx->width)&(avctx->width-1))||((avctx->height)&(avctx->height-1)))
+ if (enc->quake3_compat &&
((avctx->width)&(avctx->width-1))||((avctx->height)&(avctx->height-1)))
av_log(avctx, AV_LOG_ERROR, "Warning: dimensions not power of
two, this is not supported by quake\n");
roq->width = avctx->width;
roq->height = avctx->height;
+ enc->lambda = 2*ROQ_LAMBDA_SCALE;
enc->framesSinceKeyframe = 0;
enc->first_frame = 1;
+ enc->last_lambda = 1;
+ enc->lambda_delta = 0;
roq->last_frame = av_frame_alloc();
roq->current_frame = av_frame_alloc();
@@ -1043,9 +1130,11 @@ static void
roq_write_video_info_chunk(RoqEncContext *enc)
/* Height */
bytestream_put_le16(&enc->out_buf, enc->common.height);
- /* Unused in Quake 3, mimics the output of the real encoder */
+ /* Quake 3: starting size for cell subdivision */
bytestream_put_byte(&enc->out_buf, 0x08);
bytestream_put_byte(&enc->out_buf, 0x00);
+
+ /* Quake 3: ending size for cell subdivision */
bytestream_put_byte(&enc->out_buf, 0x04);
bytestream_put_byte(&enc->out_buf, 0x00);
}
@@ -1059,10 +1148,13 @@ static int roq_encode_frame(AVCodecContext
*avctx, AVPacket *pkt,
enc->frame_to_enc = frame;
- if (frame->quality)
- enc->lambda = frame->quality - 1;
- else
- enc->lambda = 2*ROQ_LAMBDA_SCALE;
+ if (avctx->bit_rate <= ROQ_DEFAULT_MIN_BIT_RATE) {
+ /* no specific bit rate desired, use frame quality */
+ if (frame->quality)
+ enc->lambda = frame->quality - 1;
+ else
+ enc->lambda = 2*ROQ_LAMBDA_SCALE;
+ }
/* 138 bits max per 8x8 block +
* 256 codebooks*(6 bytes 2x2 + 4 bytes 4x4) + 8 bytes frame
header */
@@ -1089,7 +1181,7 @@ static int roq_encode_frame(AVCodecContext *avctx,
AVPacket *pkt,
}
/* Encode the actual frame */
- ret = roq_encode_video(enc);
+ ret = roq_encode_video(avctx);
if (ret < 0)
return ret;
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 376388c5bb..581151cda7 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -30,7 +30,7 @@
#include "version_major.h"
#define LIBAVCODEC_VERSION_MINOR 37
-#define LIBAVCODEC_VERSION_MICRO 100
+#define LIBAVCODEC_VERSION_MICRO 101
#define LIBAVCODEC_VERSION_INT
AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \
--
2.25.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
2024-01-21 20:19 Victor Luchits
@ 2024-01-21 21:02 ` Michael Niedermayer
0 siblings, 0 replies; 18+ messages in thread
From: Michael Niedermayer @ 2024-01-21 21:02 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 2011 bytes --]
On Sun, Jan 21, 2024 at 11:19:43PM +0300, Victor Luchits wrote:
> One can now use the bitrate option (-b) to specify bit rate of the video
> stream in the RoQ encoder. The option only becomes effective for values
> above 800kbit/s, which is roughly equivalent to bandwidth of a 1x-speed
> CD-ROM drive, minus the bandwidth taken up by stereo DPCM stream. Values
> below this threshold produce visually inadequate results.
>
> Original patch by Joseph Fenton aka Chilly Willy
>
> Signed-off-by: Victor Luchits <vluchits@gmail.com>
[...]
> diff --git a/libavcodec/roqvideodec.c b/libavcodec/roqvideodec.c
> index bfc69a65c9..07d6b8bb8f 100644
> --- a/libavcodec/roqvideodec.c
> +++ b/libavcodec/roqvideodec.c
> @@ -70,6 +70,7 @@ static void roqvideo_decode_frame(RoqContext *ri,
> GetByteContext *gb)
> chunk_start = bytestream2_tell(gb);
> xpos = ypos = 0;
> + ri->key_frame = 1;
> if (chunk_size > bytestream2_get_bytes_left(gb)) {
> av_log(ri->logctx, AV_LOG_ERROR, "Chunk does not fit in input
> buffer\n");
> @@ -92,12 +93,14 @@ static void roqvideo_decode_frame(RoqContext *ri,
> GetByteContext *gb)
> switch(vqid) {
There seems to be some line wraping problem
please repost the patch without linewraping / extra newlines
Applying: liavcodec: add bit-rate support to RoQ video encoder
error: corrupt patch at line 20
error: could not build fake ancestor
Patch failed at 0001 liavcodec: add bit-rate support to RoQ video encoder
Use 'git am --show-current-patch' to see the failed patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
I have never wished to cater to the crowd; for what I know they do not
approve, and what they approve I do not know. -- Epicurus
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2024-01-22 23:25 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-22 19:14 [FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder Victor Luchits
2024-01-22 21:12 ` Tomas Härdin
2024-01-22 21:40 ` Victor Luchitz
2024-01-22 23:25 ` Tomas Härdin
2024-01-22 22:39 ` epirat07
-- strict thread matches above, loose matches on Subject: below --
2024-01-21 21:08 Victor Luchits
2024-01-22 13:05 ` Tomas Härdin
2024-01-22 13:38 ` Victor Luchitz
2024-01-22 13:57 ` Tomas Härdin
2024-01-22 13:59 ` Martin Storsjö
2024-01-22 14:19 ` Tomas Härdin
2024-01-22 16:36 ` Victor Luchitz
2024-01-22 16:21 ` Victor Luchitz
2024-01-22 18:32 ` Victor Luchitz
2024-01-22 19:10 ` Tomas Härdin
2024-01-22 19:16 ` Victor Luchitz
2024-01-21 20:19 Victor Luchits
2024-01-21 21:02 ` Michael Niedermayer
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git