[FFmpeg-devel] [PATCH] liavcodec: add bit-rate support to RoQ video encoder
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
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
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");