76#define MAX_CBS_4x4 256
78#define MAX_CBS_2x2 256
81#define ROQ_LAMBDA_SCALE ((uint64_t) FF_LAMBDA_SCALE)
166 memcpy(
u ,
cell->y, 4);
167 memset(
u+4,
cell->u, 4);
168 memset(
u+8,
cell->v, 4);
174 static const int offsets[4] = {0, 2, 8, 10};
176 for (cp=0; cp<3; cp++)
177 for (
i=0;
i<4;
i++) {
179 u[4*4*cp +
offsets[
i]+1] = cb2[qcell->
idx[
i]*2*2*3 + 4*cp+1];
180 u[4*4*cp +
offsets[
i]+4] = cb2[qcell->
idx[
i]*2*2*3 + 4*cp+2];
181 u[4*4*cp +
offsets[
i]+5] = cb2[qcell->
idx[
i]*2*2*3 + 4*cp+3];
190 for(cp=0; cp<3; cp++)
193 *
u++ =
base[(y/2)*4 + (x/2) + 16*cp];
201static inline int eval_sse(
const uint8_t *
a,
const uint8_t *
b,
int count)
213static int block_sse(uint8_t *
const *buf1, uint8_t *
const *buf2,
int x1,
int y1,
214 int x2,
int y2,
const int *stride1,
const int *stride2,
int size)
219 for (k=0; k<3; k++) {
223 buf2[k] + (y2+
i)*stride2[k] + x2,
size);
261 for(cp=0;cp<3;cp++) {
283 for (
int y = 0, n = 0; y < roq->
height; y += 16)
284 for (
int x = 0; x < roq->
width; x += 16)
285 for(
int i = 0;
i < 4;
i++) {
300 for (cp=0; cp<3; cp++) {
303 for (j=0; j<
dim; j++)
311static int index_mb(uint8_t cluster[], uint8_t
cb[],
int numCB,
312 int *outIndex,
int dim)
314 int i, lDiff = INT_MAX, pick=0;
317 for (
i=0;
i<numCB;
i++) {
329#define EVAL_MOTION(MOTION) \
331 diff = eval_motion_dist(enc, j, i, MOTION, blocksize); \
333 if (diff < lowestdiff) { \
353 int diff, lowestdiff, oldbest;
361 const int max = (roq->
width / blocksize) * roq->
height / blocksize;
363 if (blocksize == 4) {
371 for (
i = 0;
i< roq->
height;
i += blocksize)
372 for (j = 0; j < roq->
width; j += blocksize) {
381 offset = (
i/blocksize) * roq->
width / blocksize + j / blocksize;
389 offset = (
i/blocksize + 1) * roq->
width / blocksize + j / blocksize;
393 off[0]= (
i/blocksize) * roq->
width / blocksize + j/blocksize - 1;
394 off[1]= off[0] - roq->
width / blocksize + 1;
400 vect.
d[k]=
mid_pred(this_motion[off[0]].d[k],
401 this_motion[off[1]].d[k],
402 this_motion[off[2]].d[k]);
413 while (oldbest != lowestdiff) {
414 oldbest = lowestdiff;
415 for (k=0; k<8; k++) {
423 offset = (
i/blocksize) * roq->
width / blocksize + j/blocksize;
424 this_motion[
offset] = bestpick;
441 static const int bitsUsed[4] = {2, 10, 10, 34};
462 cluster_index = y * roq->
width / 16 + x / 4;
503 int i, j, best_dist, divide_bit_use;
505 int bitsUsed[4] = {2, 10, 10, 0};
539 for (
i=0;
i<4;
i++) {
546 bitsUsed[3] = 2 + divide_bit_use;
563 for (
i=0;
i<4;
i++) {
581 tempData->
i2f4[
i] = idx;
582 tempData->
f2i4[idx] =
i;
594 tempData->
i2f2[
i] = idx;
595 tempData->
f2i2[idx] =
i;
615 bytestream_put_le32(outp, tempData->
numCB2*6 + tempData->
numCB4*4);
616 bytestream_put_byte(outp, tempData->
numCB4);
617 bytestream_put_byte(outp, tempData->
numCB2);
621 bytestream_put_byte(outp, roq->
cb2x2[tempData->
f2i2[
i]].
u);
622 bytestream_put_byte(outp, roq->
cb2x2[tempData->
f2i2[
i]].
v);
634 uint8_t ax = 8 - ((uint8_t) mot.
d[0]);
635 uint8_t ay = 8 - ((uint8_t) mot.
d[1]);
636 return ((ax&15)<<4) | (ay&15);
650 s->typeSpool |= (
type & 3) << (14 -
s->typeSpoolLength);
651 s->typeSpoolLength += 2;
652 if (
s->typeSpoolLength == 16) {
653 bytestream_put_le16(
s->pout,
s->typeSpool);
655 s->args -
s->argumentSpool);
656 s->typeSpoolLength = 0;
658 s->args =
s->argumentSpool;
663 int w,
int h,
int numBlocks)
687 bytestream_put_byte(&enc->
out_buf, 0x0);
688 bytestream_put_byte(&enc->
out_buf, 0x0);
690 for (
i=0;
i<numBlocks;
i++) {
723 for (j=0; j<4; j++) {
732 bytestream_put_byte(&spool.
args,
741 bytestream_put_byte(&spool.
args,
757 for (k=0; k<4; k++) {
759 bytestream_put_byte(&spool.
args,
760 tempData->
i2f2[cb_idx]);
763 roq->
cb2x2 + cb_idx);
788 for (j=0; j<2; j++) {
808 for (j=0; j<
w; j+=4) {
809 for (k=0; k < 2; k++)
810 for (l=0; l < 2; l++)
812 i+2*k, j+2*l,
frame->linesize);
818 int *points,
int inputCount,
roq_cell *results,
819 int size,
int cbsize)
821 int i, j, k, ret = 0;
828 cbsize, 1, closest_cb, &enc->
randctx, 0);
833 for (
i=0;
i<cbsize;
i++)
834 for (k=0; k<c_size; k++) {
836 results->
y[j] = *buf++;
852 int *points = enc->
points;
877 for (j=0; j<4; j++) {
897 memset(tempData, 0,
sizeof(*tempData));
914 if (enc->
lambda > 100000) {
919 "Warning, generated a frame too big for Quake (%d > 65535), "
920 "now switching to a bigger qscale value.\n",
979 if ((avctx->
width & 0xf) || (avctx->
height & 0xf)) {
984 if (avctx->
width > 65535 || avctx->
height > 65535) {
990 av_log(avctx,
AV_LOG_ERROR,
"Warning: dimensions not power of two, this is not supported by quake\n");
1035 bytestream_put_le32(&enc->
out_buf, 8);
1038 bytestream_put_byte(&enc->
out_buf, 0x00);
1039 bytestream_put_byte(&enc->
out_buf, 0x00);
1048 bytestream_put_byte(&enc->
out_buf, 0x08);
1049 bytestream_put_byte(&enc->
out_buf, 0x00);
1050 bytestream_put_byte(&enc->
out_buf, 0x04);
1051 bytestream_put_byte(&enc->
out_buf, 0x00);
1070 size = ((roq->
width * roq->
height / 64) * 138 + 7) / 8 + 256 * (6 + 4) + 8;
1105#define OFFSET(x) offsetof(RoqEncContext, x)
1106#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1108 {
"quake3_compat",
"Whether to respect known limitations in Quake 3 decoder",
OFFSET(quake3_compat),
AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1,
VE },
1113 .class_name =
"RoQ",
1120 .p.name =
"roqvideo",
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t my
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t mx
const FFCodec ff_roq_encoder
static int BS_FUNC left(const BSCTX *bc)
Return the number of the bits left in a buffer.
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
#define i(width, name, range_min, range_max)
static const unsigned codebook[256][2]
#define CODEC_PIXFMTS(...)
#define FF_CODEC_ENCODE_CB(func)
#define CODEC_LONG_NAME(str)
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
int(* init)(AVBSFContext *ctx)
int avpriv_elbg_do(ELBGContext **elbgp, int *points, int dim, int numpoints, int *codebook, int num_cb, int max_steps, int *closest_cb, AVLFG *rand_state, uintptr_t flags)
Implementation of the Enhanced LBG Algorithm Based on the paper "Neural Networks 14:1219-1237" that c...
av_cold void avpriv_elbg_free(ELBGContext **elbgp)
Free an ELBGContext and reset the pointer to it.
int ff_alloc_packet(AVCodecContext *avctx, AVPacket *avpkt, int64_t size)
Check AVPacket size and allocate data.
int ff_encode_alloc_frame(AVCodecContext *avctx, AVFrame *frame)
Allocate buffers for a frame.
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
This encoder can reorder user opaque values from input AVFrames and return them with corresponding ou...
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
const char * av_default_item_name(void *ptr)
Return the context name.
#define LIBAVUTIL_VERSION_INT
static const int offsets[]
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
#define u(width, name, range_min, range_max)
Macro definitions for various function/variable attributes.
#define FFSWAP(type, a, b)
void * av_calloc(size_t nmemb, size_t size)
Memory handling functions.
static int sse(const MPVEncContext *const s, const uint8_t *src1, const uint8_t *src2, int w, int h, int stride)
@ AVCOL_RANGE_JPEG
Full range content.
@ AV_PIX_FMT_YUVJ444P
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
void ff_apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell)
void ff_apply_motion_4x4(RoqContext *ri, int x, int y, int deltax, int deltay)
void ff_apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell)
void ff_apply_motion_8x8(RoqContext *ri, int x, int y, int deltax, int deltay)
#define RoQ_QUAD_CODEBOOK
static av_cold int roq_encode_init(AVCodecContext *avctx)
static void get_frame_mb(const AVFrame *frame, int x, int y, uint8_t mb[], int dim)
Get macroblocks from parts of the image.
static void gather_data_for_cel(CelEvaluation *cel, RoqEncContext *enc)
Get distortion for all options available to a cel.
static uint8_t motion_arg(motion_vect mot)
static void gather_data_for_subcel(SubcelEvaluation *subcel, int x, int y, RoqEncContext *enc)
Get distortion for all options available to a subcel.
static void frame_block_to_cell(int *block, uint8_t *const *data, int top, int left, const int *stride)
Create a single YUV cell from a 2x2 section of the image.
static void roq_write_video_info_chunk(RoqEncContext *enc)
static const AVClass roq_class
static void create_clusters(const AVFrame *frame, int w, int h, int *points)
Create YUV clusters for the entire image.
#define MAX_CBS_2x2
Maximum number of 2x2 codebooks.
static av_cold int roq_encode_end(AVCodecContext *avctx)
static int block_sse(uint8_t *const *buf1, uint8_t *const *buf2, int x1, int y1, int x2, int y2, const int *stride1, const int *stride2, int size)
static int create_cel_evals(RoqEncContext *enc)
Initialize cel evaluators and set their source coordinates.
static int eval_motion_dist(RoqEncContext *enc, int x, int y, motion_vect vect, int size)
static int index_mb(uint8_t cluster[], uint8_t cb[], int numCB, int *outIndex, int dim)
Find the codebook with the lowest distortion from an image.
static void motion_search(RoqEncContext *enc, int blocksize)
static void reconstruct_and_encode_image(RoqEncContext *enc, int w, int h, int numBlocks)
#define EVAL_MOTION(MOTION)
static int squared_diff_macroblock(uint8_t a[], uint8_t b[], int size)
static int eval_sse(const uint8_t *a, const uint8_t *b, int count)
static int generate_new_codebooks(RoqEncContext *enc)
static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet)
static void write_typecode(CodingSpool *s, uint8_t type)
static void unpack_roq_qcell(uint8_t cb2[], roq_qcell *qcell, uint8_t u[4 *4 *3])
static void remap_codebooks(RoqEncContext *enc)
#define MAX_CBS_4x4
Maximum number of generated 4x4 codebooks.
static void unpack_roq_cell(roq_cell *cell, uint8_t u[4 *3])
static void enlarge_roq_mb4(uint8_t base[3 *16], uint8_t u[3 *64])
static int roq_encode_video(RoqEncContext *enc)
static void write_codebooks(RoqEncContext *enc)
Write codebook chunk.
static int generate_codebook(RoqEncContext *enc, int *points, int inputCount, roq_cell *results, int size, int cbsize)
Describe the class of an AVClass context structure.
main external API structure.
int width
picture width / height.
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
This structure describes decoded (raw) audio or video data.
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Context structure for the Lagged Fibonacci PRNG.
This structure stores compressed data.
SubcelEvaluation subCels[4]
uint8_t argumentSpool[64]
uint8_t unpacked_cb4[MAX_CBS_4x4 *4 *4 *3]
uint8_t unpacked_cb2[MAX_CBS_2x2 *2 *2 *3]
uint8_t unpacked_cb4_enlarged[MAX_CBS_4x4 *8 *8 *3]
motion_vect * last_motion8
motion_vect * this_motion8
CelEvaluation * cel_evals
const AVFrame * frame_to_enc
motion_vect * this_motion4
roq_cell results4[4 *MAX_CBS_4x4]
unsigned int framesSinceKeyframe
int tmp_codebook_buf[FFMAX(24 *MAX_CBS_4x4, 6 *MAX_CBS_2x2)]
struct ELBGContext * elbg
motion_vect * last_motion4
In the ELBG jargon, a cell is the set of points that are closest to a codebook entry.
#define av_malloc_array(a, b)
static double cb(void *priv, double x, double y)
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
static const uint8_t codebooks[]
static int bias(int x, int c)