[FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder

2024-01-21 Thread 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 
---
 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 :
 - ffmpeg CLI -bsf option may now be used for input as well as output
 - ffmpeg CLI options may now be used as -/opt , which is equivalent
   to -opt >
+- 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

[FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder

2024-01-21 Thread 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 
---
 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 :
 - ffmpeg CLI -bsf option may now be used for input as well as output
 - ffmpeg CLI options may now be used as -/opt , which is equivalent
   to -opt >
+- 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 tempD

[FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder

2024-01-22 Thread 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 
---
 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 :
 - ffmpeg CLI -bsf option may now be used for input as well as output
 - ffmpeg CLI options may now be used as -/opt , which is equivalent
   to -opt >
+- 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 > 10) {
+if (enc->lambda > 1) {
 av_log(roq->logctx, AV_LOG_ERROR, "Cannot encode video in Quake 
compatible form\n");