RoQ-encoder: introducing Quake 3 compatibility option
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
80a79f2641
commit
392b0345d6
@ -43,6 +43,7 @@ struct RoqTempData;
|
|||||||
|
|
||||||
typedef struct RoqContext {
|
typedef struct RoqContext {
|
||||||
|
|
||||||
|
const AVClass *class;
|
||||||
AVCodecContext *avctx;
|
AVCodecContext *avctx;
|
||||||
AVFrame *last_frame;
|
AVFrame *last_frame;
|
||||||
AVFrame *current_frame;
|
AVFrame *current_frame;
|
||||||
@ -69,6 +70,9 @@ typedef struct RoqContext {
|
|||||||
const AVFrame *frame_to_enc;
|
const AVFrame *frame_to_enc;
|
||||||
uint8_t *out_buf;
|
uint8_t *out_buf;
|
||||||
struct RoqTempData *tmpData;
|
struct RoqTempData *tmpData;
|
||||||
|
|
||||||
|
int quake3_compat; // Quake 3 compatibility option
|
||||||
|
|
||||||
} RoqContext;
|
} RoqContext;
|
||||||
|
|
||||||
#define RoQ_INFO 0x1001
|
#define RoQ_INFO 0x1001
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "libavutil/attributes.h"
|
#include "libavutil/attributes.h"
|
||||||
|
#include "libavutil/opt.h"
|
||||||
#include "roqvideo.h"
|
#include "roqvideo.h"
|
||||||
#include "bytestream.h"
|
#include "bytestream.h"
|
||||||
#include "elbg.h"
|
#include "elbg.h"
|
||||||
@ -69,7 +70,7 @@
|
|||||||
* Maximum number of generated 4x4 codebooks. Can't be 256 to workaround a
|
* Maximum number of generated 4x4 codebooks. Can't be 256 to workaround a
|
||||||
* Quake 3 bug.
|
* Quake 3 bug.
|
||||||
*/
|
*/
|
||||||
#define MAX_CBS_4x4 255
|
#define MAX_CBS_4x4 256
|
||||||
|
|
||||||
#define MAX_CBS_2x2 256 ///< Maximum number of 2x2 codebooks.
|
#define MAX_CBS_2x2 256 ///< Maximum number of 2x2 codebooks.
|
||||||
|
|
||||||
@ -540,7 +541,7 @@ static void remap_codebooks(RoqContext *enc, RoqTempdata *tempData)
|
|||||||
int i, j, idx=0;
|
int i, j, idx=0;
|
||||||
|
|
||||||
/* Make remaps for the final codebook usage */
|
/* Make remaps for the final codebook usage */
|
||||||
for (i=0; i<MAX_CBS_4x4; i++) {
|
for (i=0; i<(enc->quake3_compat ? MAX_CBS_4x4-1 : MAX_CBS_4x4); i++) {
|
||||||
if (tempData->codebooks.usedCB4[i]) {
|
if (tempData->codebooks.usedCB4[i]) {
|
||||||
tempData->i2f4[i] = idx;
|
tempData->i2f4[i] = idx;
|
||||||
tempData->f2i4[idx] = i;
|
tempData->f2i4[idx] = i;
|
||||||
@ -847,9 +848,9 @@ static void generate_new_codebooks(RoqContext *enc, RoqTempdata *tempData)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create 4x4 codebooks */
|
/* Create 4x4 codebooks */
|
||||||
generate_codebook(enc, tempData, points, max, results4, 4, MAX_CBS_4x4);
|
generate_codebook(enc, tempData, points, max, results4, 4, (enc->quake3_compat ? MAX_CBS_4x4-1 : MAX_CBS_4x4));
|
||||||
|
|
||||||
codebooks->numCB4 = MAX_CBS_4x4;
|
codebooks->numCB4 = (enc->quake3_compat ? MAX_CBS_4x4-1 : MAX_CBS_4x4);
|
||||||
|
|
||||||
tempData->closest_cb2 = av_malloc(max*4*sizeof(int));
|
tempData->closest_cb2 = av_malloc(max*4*sizeof(int));
|
||||||
|
|
||||||
@ -901,10 +902,10 @@ static void roq_encode_video(RoqContext *enc)
|
|||||||
gather_data_for_cel(tempData->cel_evals + i, enc, tempData);
|
gather_data_for_cel(tempData->cel_evals + i, enc, tempData);
|
||||||
|
|
||||||
/* Quake 3 can't handle chunks bigger than 65535 bytes */
|
/* Quake 3 can't handle chunks bigger than 65535 bytes */
|
||||||
if (tempData->mainChunkSize/8 > 65535) {
|
if (tempData->mainChunkSize/8 > 65535 && enc->quake3_compat) {
|
||||||
av_log(enc->avctx, AV_LOG_ERROR,
|
av_log(enc->avctx, AV_LOG_ERROR,
|
||||||
"Warning, generated a frame too big (%d > 65535), "
|
"Warning, generated a frame too big for Quake (%d > 65535), "
|
||||||
"try using a smaller qscale value.\n",
|
"now switching to a bigger qscale value.\n",
|
||||||
tempData->mainChunkSize/8);
|
tempData->mainChunkSize/8);
|
||||||
enc->lambda *= 1.5;
|
enc->lambda *= 1.5;
|
||||||
tempData->mainChunkSize = 0;
|
tempData->mainChunkSize = 0;
|
||||||
@ -1073,6 +1074,20 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define OFFSET(x) offsetof(RoqContext, x)
|
||||||
|
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
|
||||||
|
static const AVOption options[] = {
|
||||||
|
{ "quake3_compat", "Whether to respect known limitations in Quake 3 decoder", OFFSET(quake3_compat), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE },
|
||||||
|
{ NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const AVClass roq_class = {
|
||||||
|
.class_name = "RoQ",
|
||||||
|
.item_name = av_default_item_name,
|
||||||
|
.option = options,
|
||||||
|
.version = LIBAVUTIL_VERSION_INT,
|
||||||
|
};
|
||||||
|
|
||||||
AVCodec ff_roq_encoder = {
|
AVCodec ff_roq_encoder = {
|
||||||
.name = "roqvideo",
|
.name = "roqvideo",
|
||||||
.long_name = NULL_IF_CONFIG_SMALL("id RoQ video"),
|
.long_name = NULL_IF_CONFIG_SMALL("id RoQ video"),
|
||||||
@ -1085,4 +1100,5 @@ AVCodec ff_roq_encoder = {
|
|||||||
.supported_framerates = (const AVRational[]){ {30,1}, {0,0} },
|
.supported_framerates = (const AVRational[]){ {30,1}, {0,0} },
|
||||||
.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P,
|
.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P,
|
||||||
AV_PIX_FMT_NONE },
|
AV_PIX_FMT_NONE },
|
||||||
|
.priv_class = &roq_class,
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user