@ -57,6 +57,7 @@
# include <string.h>
# include "libavutil/attributes.h"
# include "libavutil/lfg.h"
# include "libavutil/opt.h"
# include "roqvideo.h"
# include "bytestream.h"
@ -77,6 +78,27 @@
/* The cast is useful when multiplying it by INT_MAX */
# define ROQ_LAMBDA_SCALE ((uint64_t) FF_LAMBDA_SCALE)
typedef struct RoqEncContext {
RoqContext common ;
AVLFG randctx ;
uint64_t lambda ;
motion_vect * this_motion4 ;
motion_vect * last_motion4 ;
motion_vect * this_motion8 ;
motion_vect * last_motion8 ;
unsigned int framesSinceKeyframe ;
const AVFrame * frame_to_enc ;
uint8_t * out_buf ;
struct RoqTempData * tmpData ;
int first_frame ;
int quake3_compat ; // Quake 3 compatibility option
} RoqEncContext ;
/* Macroblock support functions */
static void unpack_roq_cell ( roq_cell * cell , uint8_t u [ 4 * 3 ] )
{
@ -143,9 +165,10 @@ static int block_sse(uint8_t * const *buf1, uint8_t * const *buf2, int x1, int y
return sse ;
}
static int eval_motion_dist ( RoqContext * enc , int x , int y , motion_vect vect ,
static int eval_motion_dist ( RoqEnc Context * enc , int x , int y , motion_vect vect ,
int size )
{
RoqContext * const roq = & enc - > common ;
int mx = vect . d [ 0 ] ;
int my = vect . d [ 1 ] ;
@ -158,12 +181,12 @@ static int eval_motion_dist(RoqContext *enc, int x, int y, motion_vect vect,
mx + = x ;
my + = y ;
if ( ( unsigned ) mx > enc - > width - size | | ( unsigned ) my > enc - > height - size )
if ( ( unsigned ) mx > roq - > width - size | | ( unsigned ) my > roq - > height - size )
return INT_MAX ;
return block_sse ( enc - > frame_to_enc - > data , enc - > last_frame - > data , x , y ,
return block_sse ( enc - > frame_to_enc - > data , roq - > last_frame - > data , x , y ,
mx , my ,
enc - > frame_to_enc - > linesize , enc - > last_frame - > linesize ,
enc - > frame_to_enc - > linesize , roq - > last_frame - > linesize ,
size ) ;
}
@ -307,7 +330,7 @@ static int index_mb(uint8_t cluster[], uint8_t cb[], int numCB,
} \
} while ( 0 )
static void motion_search ( RoqContext * enc , int blocksize )
static void motion_search ( RoqEnc Context * enc , int blocksize )
{
static const motion_vect offsets [ 8 ] = {
{ { 0 , - 1 } } ,
@ -320,6 +343,7 @@ static void motion_search(RoqContext *enc, int blocksize)
{ { 1 , 1 } } ,
} ;
RoqContext * const roq = & enc - > common ;
int diff , lowestdiff , oldbest ;
int off [ 3 ] ;
motion_vect bestpick = { { 0 , 0 } } ;
@ -328,8 +352,7 @@ static void motion_search(RoqContext *enc, int blocksize)
motion_vect * last_motion ;
motion_vect * this_motion ;
motion_vect vect , vect2 ;
int max = ( enc - > width / blocksize ) * enc - > height / blocksize ;
const int max = ( roq - > width / blocksize ) * roq - > height / blocksize ;
if ( blocksize = = 4 ) {
last_motion = enc - > last_motion4 ;
@ -339,17 +362,17 @@ static void motion_search(RoqContext *enc, int blocksize)
this_motion = enc - > this_motion8 ;
}
for ( i = 0 ; i < enc - > height ; i + = blocksize )
for ( j = 0 ; j < enc - > width ; j + = blocksize ) {
for ( i = 0 ; i < roq - > height ; i + = blocksize )
for ( j = 0 ; j < roq - > width ; j + = blocksize ) {
lowestdiff = eval_motion_dist ( enc , j , i , ( motion_vect ) { { 0 , 0 } } ,
blocksize ) ;
bestpick . d [ 0 ] = 0 ;
bestpick . d [ 1 ] = 0 ;
if ( blocksize = = 4 )
EVAL_MOTION ( enc - > this_motion8 [ ( i / 8 ) * ( enc - > width / 8 ) + j / 8 ] ) ;
EVAL_MOTION ( enc - > this_motion8 [ ( i / 8 ) * ( roq - > width / 8 ) + j / 8 ] ) ;
offset = ( i / blocksize ) * enc - > width / blocksize + j / blocksize ;
offset = ( i / blocksize ) * roq - > width / blocksize + j / blocksize ;
if ( offset < max & & offset > = 0 )
EVAL_MOTION ( last_motion [ offset ] ) ;
@ -357,12 +380,12 @@ static void motion_search(RoqContext *enc, int blocksize)
if ( offset < max & & offset > = 0 )
EVAL_MOTION ( last_motion [ offset ] ) ;
offset = ( i / blocksize + 1 ) * enc - > width / blocksize + j / blocksize ;
offset = ( i / blocksize + 1 ) * roq - > width / blocksize + j / blocksize ;
if ( offset < max & & offset > = 0 )
EVAL_MOTION ( last_motion [ offset ] ) ;
off [ 0 ] = ( i / blocksize ) * enc - > width / blocksize + j / blocksize - 1 ;
off [ 1 ] = off [ 0 ] - enc - > width / blocksize + 1 ;
off [ 0 ] = ( i / blocksize ) * roq - > width / blocksize + j / blocksize - 1 ;
off [ 1 ] = off [ 0 ] - roq - > width / blocksize + 1 ;
off [ 2 ] = off [ 1 ] + 1 ;
if ( i ) {
@ -391,7 +414,7 @@ static void motion_search(RoqContext *enc, int blocksize)
}
vect = bestpick ;
}
offset = ( i / blocksize ) * enc - > width / blocksize + j / blocksize ;
offset = ( i / blocksize ) * roq - > width / blocksize + j / blocksize ;
this_motion [ offset ] = bestpick ;
}
}
@ -400,8 +423,9 @@ static void motion_search(RoqContext *enc, int blocksize)
* Get distortion for all options available to a subcel
*/
static void gather_data_for_subcel ( SubcelEvaluation * subcel , int x ,
int y , RoqContext * enc , RoqTempdata * tempData )
int y , RoqEnc Context * enc , RoqTempdata * tempData )
{
RoqContext * const roq = & enc - > common ;
uint8_t mb4 [ 4 * 4 * 3 ] ;
uint8_t mb2 [ 2 * 2 * 3 ] ;
int cluster_index ;
@ -410,25 +434,25 @@ static void gather_data_for_subcel(SubcelEvaluation *subcel, int x,
static const int bitsUsed [ 4 ] = { 2 , 10 , 10 , 34 } ;
if ( enc - > framesSinceKeyframe > = 1 ) {
subcel - > motion = enc - > this_motion4 [ y * enc - > width / 16 + x / 4 ] ;
subcel - > motion = enc - > this_motion4 [ y * roq - > width / 16 + x / 4 ] ;
subcel - > eval_dist [ RoQ_ID_FCC ] =
eval_motion_dist ( enc , x , y ,
enc - > this_motion4 [ y * enc - > width / 16 + x / 4 ] , 4 ) ;
enc - > this_motion4 [ y * roq - > width / 16 + x / 4 ] , 4 ) ;
} else
subcel - > eval_dist [ RoQ_ID_FCC ] = INT_MAX ;
if ( enc - > framesSinceKeyframe > = 2 )
subcel - > eval_dist [ RoQ_ID_MOT ] = block_sse ( enc - > frame_to_enc - > data ,
enc - > current_frame - > data , x ,
roq - > current_frame - > data , x ,
y , x , y ,
enc - > frame_to_enc - > linesize ,
enc - > current_frame - > linesize ,
roq - > current_frame - > linesize ,
4 ) ;
else
subcel - > eval_dist [ RoQ_ID_MOT ] = INT_MAX ;
cluster_index = y * enc - > width / 16 + x / 4 ;
cluster_index = y * roq - > width / 16 + x / 4 ;
get_frame_mb ( enc - > frame_to_enc , x , y , mb4 , 4 ) ;
@ -463,11 +487,12 @@ static void gather_data_for_subcel(SubcelEvaluation *subcel, int x,
/**
* Get distortion for all options available to a cel
*/
static void gather_data_for_cel ( CelEvaluation * cel , RoqContext * enc ,
static void gather_data_for_cel ( CelEvaluation * cel , RoqEnc Context * enc ,
RoqTempdata * tempData )
{
RoqContext * const roq = & enc - > common ;
uint8_t mb8 [ 8 * 8 * 3 ] ;
int index = cel - > sourceY * enc - > width / 64 + cel - > sourceX / 8 ;
int index = cel - > sourceY * roq - > width / 64 + cel - > sourceX / 8 ;
int i , j , best_dist , divide_bit_use ;
int bitsUsed [ 4 ] = { 2 , 10 , 10 , 0 } ;
@ -483,11 +508,11 @@ static void gather_data_for_cel(CelEvaluation *cel, RoqContext *enc,
if ( enc - > framesSinceKeyframe > = 2 )
cel - > eval_dist [ RoQ_ID_MOT ] = block_sse ( enc - > frame_to_enc - > data ,
enc - > current_frame - > data ,
roq - > current_frame - > data ,
cel - > sourceX , cel - > sourceY ,
cel - > sourceX , cel - > sourceY ,
enc - > frame_to_enc - > linesize ,
enc - > current_frame - > linesize , 8 ) ;
roq - > current_frame - > linesize , 8 ) ;
else
cel - > eval_dist [ RoQ_ID_MOT ] = INT_MAX ;
@ -537,8 +562,9 @@ static void gather_data_for_cel(CelEvaluation *cel, RoqContext *enc,
}
}
static void remap_codebooks ( RoqContext * enc , RoqTempdata * tempData )
static void remap_codebooks ( RoqEnc Context * enc , RoqTempdata * tempData )
{
RoqContext * const roq = & enc - > common ;
int i , j , idx = 0 ;
/* Make remaps for the final codebook usage */
@ -547,7 +573,7 @@ static void remap_codebooks(RoqContext *enc, RoqTempdata *tempData)
tempData - > i2f4 [ i ] = idx ;
tempData - > f2i4 [ idx ] = i ;
for ( j = 0 ; j < 4 ; j + + )
tempData - > codebooks . usedCB2 [ enc - > cb4x4 [ i ] . idx [ j ] ] + + ;
tempData - > codebooks . usedCB2 [ roq - > cb4x4 [ i ] . idx [ j ] ] + + ;
idx + + ;
}
}
@ -569,8 +595,9 @@ static void remap_codebooks(RoqContext *enc, RoqTempdata *tempData)
/**
* Write codebook chunk
*/
static void write_codebooks ( RoqContext * enc , RoqTempdata * tempData )
static void write_codebooks ( RoqEnc Context * enc , RoqTempdata * tempData )
{
RoqContext * const roq = & enc - > common ;
int i , j ;
uint8_t * * outp = & enc - > out_buf ;
@ -581,14 +608,14 @@ static void write_codebooks(RoqContext *enc, RoqTempdata *tempData)
bytestream_put_byte ( outp , tempData - > numCB2 ) ;
for ( i = 0 ; i < tempData - > numCB2 ; i + + ) {
bytestream_put_buffer ( outp , enc - > cb2x2 [ tempData - > f2i2 [ i ] ] . y , 4 ) ;
bytestream_put_byte ( outp , enc - > cb2x2 [ tempData - > f2i2 [ i ] ] . u ) ;
bytestream_put_byte ( outp , enc - > cb2x2 [ tempData - > f2i2 [ i ] ] . v ) ;
bytestream_put_buffer ( outp , roq - > cb2x2 [ tempData - > f2i2 [ i ] ] . y , 4 ) ;
bytestream_put_byte ( outp , roq - > cb2x2 [ tempData - > f2i2 [ i ] ] . u ) ;
bytestream_put_byte ( outp , roq - > cb2x2 [ tempData - > f2i2 [ i ] ] . v ) ;
}
for ( i = 0 ; i < tempData - > numCB4 ; i + + )
for ( j = 0 ; j < 4 ; j + + )
bytestream_put_byte ( outp , tempData - > i2f2 [ enc - > cb4x4 [ tempData - > f2i4 [ i ] ] . idx [ j ] ] ) ;
bytestream_put_byte ( outp , tempData - > i2f2 [ roq - > cb4x4 [ tempData - > f2i4 [ i ] ] . idx [ j ] ] ) ;
}
}
@ -623,8 +650,11 @@ static void write_typecode(CodingSpool *s, uint8_t type)
}
}
static void reconstruct_and_encode_image ( RoqContext * enc , RoqTempdata * tempData , int w , int h , int numBlocks )
static void reconstruct_and_encode_image ( RoqEncContext * enc ,
RoqTempdata * tempData ,
int w , int h , int numBlocks )
{
RoqContext * const roq = & enc - > common ;
int i , j , k ;
int x , y ;
int subX , subY ;
@ -665,7 +695,7 @@ static void reconstruct_and_encode_image(RoqContext *enc, RoqTempdata *tempData,
bytestream_put_byte ( & spool . args , motion_arg ( eval - > motion ) ) ;
write_typecode ( & spool , RoQ_ID_FCC ) ;
ff_apply_motion_8x8 ( enc , x , y ,
ff_apply_motion_8x8 ( roq , x , y ,
eval - > motion . d [ 0 ] , eval - > motion . d [ 1 ] ) ;
break ;
@ -673,11 +703,11 @@ static void reconstruct_and_encode_image(RoqContext *enc, RoqTempdata *tempData,
bytestream_put_byte ( & spool . args , tempData - > i2f4 [ eval - > cbEntry ] ) ;
write_typecode ( & spool , RoQ_ID_SLD ) ;
qcell = enc - > cb4x4 + eval - > cbEntry ;
ff_apply_vector_4x4 ( enc , x , y , enc - > cb2x2 + qcell - > idx [ 0 ] ) ;
ff_apply_vector_4x4 ( enc , x + 4 , y , enc - > cb2x2 + qcell - > idx [ 1 ] ) ;
ff_apply_vector_4x4 ( enc , x , y + 4 , enc - > cb2x2 + qcell - > idx [ 2 ] ) ;
ff_apply_vector_4x4 ( enc , x + 4 , y + 4 , enc - > cb2x2 + qcell - > idx [ 3 ] ) ;
qcell = roq - > cb4x4 + eval - > cbEntry ;
ff_apply_vector_4x4 ( roq , x , y , roq - > cb2x2 + qcell - > idx [ 0 ] ) ;
ff_apply_vector_4x4 ( roq , x + 4 , y , roq - > cb2x2 + qcell - > idx [ 1 ] ) ;
ff_apply_vector_4x4 ( roq , x , y + 4 , roq - > cb2x2 + qcell - > idx [ 2 ] ) ;
ff_apply_vector_4x4 ( roq , x + 4 , y + 4 , roq - > cb2x2 + qcell - > idx [ 3 ] ) ;
break ;
case RoQ_ID_CCC :
@ -695,7 +725,7 @@ static void reconstruct_and_encode_image(RoqContext *enc, RoqTempdata *tempData,
bytestream_put_byte ( & spool . args ,
motion_arg ( eval - > subCels [ j ] . motion ) ) ;
ff_apply_motion_4x4 ( enc , subX , subY ,
ff_apply_motion_4x4 ( roq , subX , subY ,
eval - > subCels [ j ] . motion . d [ 0 ] ,
eval - > subCels [ j ] . motion . d [ 1 ] ) ;
break ;
@ -704,16 +734,16 @@ static void reconstruct_and_encode_image(RoqContext *enc, RoqTempdata *tempData,
bytestream_put_byte ( & spool . args ,
tempData - > i2f4 [ eval - > subCels [ j ] . cbEntry ] ) ;
qcell = enc - > cb4x4 + eval - > subCels [ j ] . cbEntry ;
qcell = roq - > cb4x4 + eval - > subCels [ j ] . cbEntry ;
ff_apply_vector_2x2 ( enc , subX , subY ,
enc - > cb2x2 + qcell - > idx [ 0 ] ) ;
ff_apply_vector_2x2 ( enc , subX + 2 , subY ,
enc - > cb2x2 + qcell - > idx [ 1 ] ) ;
ff_apply_vector_2x2 ( enc , subX , subY + 2 ,
enc - > cb2x2 + qcell - > idx [ 2 ] ) ;
ff_apply_vector_2x2 ( enc , subX + 2 , subY + 2 ,
enc - > cb2x2 + qcell - > idx [ 3 ] ) ;
ff_apply_vector_2x2 ( roq , subX , subY ,
roq - > cb2x2 + qcell - > idx [ 0 ] ) ;
ff_apply_vector_2x2 ( roq , subX + 2 , subY ,
roq - > cb2x2 + qcell - > idx [ 1 ] ) ;
ff_apply_vector_2x2 ( roq , subX , subY + 2 ,
roq - > cb2x2 + qcell - > idx [ 2 ] ) ;
ff_apply_vector_2x2 ( roq , subX + 2 , subY + 2 ,
roq - > cb2x2 + qcell - > idx [ 3 ] ) ;
break ;
case RoQ_ID_CCC :
@ -722,8 +752,8 @@ static void reconstruct_and_encode_image(RoqContext *enc, RoqTempdata *tempData,
bytestream_put_byte ( & spool . args ,
tempData - > i2f2 [ cb_idx ] ) ;
ff_apply_vector_2x2 ( enc , subX + 2 * ( k & 1 ) , subY + ( k & 2 ) ,
enc - > cb2x2 + cb_idx ) ;
ff_apply_vector_2x2 ( roq , subX + 2 * ( k & 1 ) , subY + ( k & 2 ) ,
roq - > cb2x2 + cb_idx ) ;
}
break ;
}
@ -777,7 +807,7 @@ static void create_clusters(const AVFrame *frame, int w, int h, uint8_t *yuvClus
}
}
static int generate_codebook ( RoqContext * enc , RoqTempdata * tempdata ,
static int generate_codebook ( RoqEnc Context * enc , RoqTempdata * tempdata ,
int * points , int inputCount , roq_cell * results ,
int size , int cbsize )
{
@ -825,11 +855,12 @@ out:
return ret ;
}
static int generate_new_codebooks ( RoqContext * enc , RoqTempdata * tempData )
static int generate_new_codebooks ( RoqEnc Context * enc , RoqTempdata * tempData )
{
int i , j , ret = 0 ;
RoqCodebooks * codebooks = & tempData - > codebooks ;
int max = enc - > width * enc - > height / 16 ;
RoqContext * const roq = & enc - > common ;
int max = roq - > width * roq - > height / 16 ;
uint8_t mb2 [ 3 * 4 ] ;
roq_cell * results4 = av_malloc ( sizeof ( roq_cell ) * MAX_CBS_4x4 * 4 ) ;
uint8_t * yuvClusters = av_malloc_array ( max , sizeof ( int ) * 6 * 4 ) ;
@ -842,7 +873,7 @@ static int generate_new_codebooks(RoqContext *enc, RoqTempdata *tempData)
}
/* Subsample YUV data */
create_clusters ( enc - > frame_to_enc , enc - > width , enc - > height , yuvClusters ) ;
create_clusters ( enc - > frame_to_enc , roq - > width , roq - > height , yuvClusters ) ;
/* Cast to integer and apply chroma bias */
for ( i = 0 ; i < max * 24 ; i + + ) {
@ -865,23 +896,23 @@ static int generate_new_codebooks(RoqContext *enc, RoqTempdata *tempData)
/* Create 2x2 codebooks */
if ( ( ret = generate_codebook ( enc , tempData , points , max * 4 ,
enc - > cb2x2 , 2 , MAX_CBS_2x2 ) ) < 0 )
roq - > cb2x2 , 2 , MAX_CBS_2x2 ) ) < 0 )
goto out ;
codebooks - > numCB2 = MAX_CBS_2x2 ;
/* Unpack 2x2 codebook clusters */
for ( i = 0 ; i < codebooks - > numCB2 ; i + + )
unpack_roq_cell ( enc - > cb2x2 + i , codebooks - > unpacked_cb2 + i * 2 * 2 * 3 ) ;
unpack_roq_cell ( roq - > cb2x2 + i , codebooks - > unpacked_cb2 + i * 2 * 2 * 3 ) ;
/* Index all 4x4 entries to the 2x2 entries, unpack, and enlarge */
for ( i = 0 ; i < codebooks - > numCB4 ; i + + ) {
for ( j = 0 ; j < 4 ; j + + ) {
unpack_roq_cell ( & results4 [ 4 * i + j ] , mb2 ) ;
index_mb ( mb2 , codebooks - > unpacked_cb2 , codebooks - > numCB2 ,
& enc - > cb4x4 [ i ] . idx [ j ] , 2 ) ;
& roq - > cb4x4 [ i ] . idx [ j ] , 2 ) ;
}
unpack_roq_qcell ( codebooks - > unpacked_cb2 , enc - > cb4x4 + i ,
unpack_roq_qcell ( codebooks - > unpacked_cb2 , roq - > cb4x4 + i ,
codebooks - > unpacked_cb4 + i * 4 * 4 * 3 ) ;
enlarge_roq_mb4 ( codebooks - > unpacked_cb4 + i * 4 * 4 * 3 ,
codebooks - > unpacked_cb4_enlarged + i * 8 * 8 * 3 ) ;
@ -893,14 +924,15 @@ out:
return ret ;
}
static int roq_encode_video ( RoqContext * enc )
static int roq_encode_video ( RoqEnc Context * enc )
{
RoqTempdata * tempData = enc - > tmpData ;
int i , ret ;
RoqContext * const roq = & enc - > common ;
int ret ;
memset ( tempData , 0 , sizeof ( * tempData ) ) ;
ret = create_cel_evals ( enc , tempData ) ;
ret = create_cel_evals ( roq , tempData ) ;
if ( ret < 0 )
return ret ;
@ -914,16 +946,16 @@ static int roq_encode_video(RoqContext *enc)
}
retry_encode :
for ( i = 0 ; i < enc - > width * enc - > height / 64 ; i + + )
for ( int i = 0 ; i < roq - > width * roq - > height / 64 ; i + + )
gather_data_for_cel ( tempData - > cel_evals + i , enc , tempData ) ;
/* Quake 3 can't handle chunks bigger than 65535 bytes */
if ( tempData - > mainChunkSize / 8 > 65535 & & enc - > quake3_compat ) {
if ( enc - > lambda > 100000 ) {
av_log ( enc - > avctx , AV_LOG_ERROR , " Cannot encode video in Quake compatible form \n " ) ;
av_log ( roq - > avctx , AV_LOG_ERROR , " Cannot encode video in Quake compatible form \n " ) ;
return AVERROR ( EINVAL ) ;
}
av_log ( enc - > avctx , AV_LOG_ERROR ,
av_log ( roq - > avctx , AV_LOG_ERROR ,
" Warning, generated a frame too big for Quake (%d > 65535), "
" now switching to a bigger qscale value. \n " ,
tempData - > mainChunkSize / 8 ) ;
@ -942,11 +974,11 @@ static int roq_encode_video(RoqContext *enc)
write_codebooks ( enc , tempData ) ;
reconstruct_and_encode_image ( enc , tempData , enc - > width , enc - > height ,
enc - > width * enc - > height / 64 ) ;
reconstruct_and_encode_image ( enc , tempData , roq - > width , roq - > height ,
roq - > width * roq - > height / 64 ) ;
/* Rotate frame history */
FFSWAP ( AVFrame * , enc - > current_frame , enc - > last_frame ) ;
FFSWAP ( AVFrame * , roq - > current_frame , roq - > last_frame ) ;
FFSWAP ( motion_vect * , enc - > last_motion4 , enc - > this_motion4 ) ;
FFSWAP ( motion_vect * , enc - > last_motion8 , enc - > this_motion8 ) ;
@ -960,10 +992,10 @@ static int roq_encode_video(RoqContext *enc)
static av_cold int roq_encode_end ( AVCodecContext * avctx )
{
RoqContext * enc = avctx - > priv_data ;
RoqEnc Context * const enc = avctx - > priv_data ;
av_frame_free ( & enc - > current_frame ) ;
av_frame_free ( & enc - > last_frame ) ;
av_frame_free ( & enc - > common . c urrent_frame ) ;
av_frame_free ( & enc - > common . last_frame ) ;
av_freep ( & enc - > tmpData ) ;
av_freep ( & enc - > this_motion4 ) ;
@ -976,11 +1008,12 @@ static av_cold int roq_encode_end(AVCodecContext *avctx)
static av_cold int roq_encode_init ( AVCodecContext * avctx )
{
RoqContext * enc = avctx - > priv_data ;
RoqEncContext * const enc = avctx - > priv_data ;
RoqContext * const roq = & enc - > common ;
av_lfg_init ( & enc - > randctx , 1 ) ;
enc - > avctx = avctx ;
roq - > avctx = avctx ;
enc - > framesSinceKeyframe = 0 ;
if ( ( avctx - > width & 0xf ) | | ( avctx - > height & 0xf ) ) {
@ -996,30 +1029,30 @@ static av_cold int roq_encode_init(AVCodecContext *avctx)
if ( ( ( 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 " ) ;
enc - > width = avctx - > width ;
enc - > height = avctx - > height ;
roq - > width = avctx - > width ;
roq - > height = avctx - > height ;
enc - > framesSinceKeyframe = 0 ;
enc - > first_frame = 1 ;
enc - > last_frame = av_frame_alloc ( ) ;
enc - > current_frame = av_frame_alloc ( ) ;
if ( ! enc - > last_frame | | ! enc - > current_frame )
roq - > last_frame = av_frame_alloc ( ) ;
roq - > current_frame = av_frame_alloc ( ) ;
if ( ! roq - > last_frame | | ! roq - > current_frame )
return AVERROR ( ENOMEM ) ;
enc - > tmpData = av_malloc ( sizeof ( RoqTempdata ) ) ;
enc - > this_motion4 =
av_mallocz_array ( ( enc - > width * enc - > height / 16 ) , sizeof ( motion_vect ) ) ;
av_mallocz_array ( roq - > width * roq - > height / 16 , sizeof ( motion_vect ) ) ;
enc - > last_motion4 =
av_malloc_array ( ( enc - > width * enc - > height / 16 ) , sizeof ( motion_vect ) ) ;
av_malloc_array ( roq - > width * roq - > height / 16 , sizeof ( motion_vect ) ) ;
enc - > this_motion8 =
av_mallocz_array ( ( enc - > width * enc - > height / 64 ) , sizeof ( motion_vect ) ) ;
av_mallocz_array ( roq - > width * roq - > height / 64 , sizeof ( motion_vect ) ) ;
enc - > last_motion8 =
av_malloc_array ( ( enc - > width * enc - > height / 64 ) , sizeof ( motion_vect ) ) ;
av_malloc_array ( roq - > width * roq - > height / 64 , sizeof ( motion_vect ) ) ;
if ( ! enc - > tmpData | | ! enc - > this_motion4 | | ! enc - > last_motion4 | |
! enc - > this_motion8 | | ! enc - > last_motion8 )
@ -1028,7 +1061,7 @@ static av_cold int roq_encode_init(AVCodecContext *avctx)
return 0 ;
}
static void roq_write_video_info_chunk ( RoqContext * enc )
static void roq_write_video_info_chunk ( RoqEnc Context * enc )
{
/* ROQ info chunk */
bytestream_put_le16 ( & enc - > out_buf , RoQ_INFO ) ;
@ -1041,10 +1074,10 @@ static void roq_write_video_info_chunk(RoqContext *enc)
bytestream_put_byte ( & enc - > out_buf , 0x00 ) ;
/* Width */
bytestream_put_le16 ( & enc - > out_buf , enc - > width ) ;
bytestream_put_le16 ( & enc - > out_buf , enc - > common . width ) ;
/* Height */
bytestream_put_le16 ( & enc - > out_buf , enc - > height ) ;
bytestream_put_le16 ( & enc - > out_buf , enc - > common . height ) ;
/* Unused in Quake 3, mimics the output of the real encoder */
bytestream_put_byte ( & enc - > out_buf , 0x08 ) ;
@ -1056,10 +1089,11 @@ static void roq_write_video_info_chunk(RoqContext *enc)
static int roq_encode_frame ( AVCodecContext * avctx , AVPacket * pkt ,
const AVFrame * frame , int * got_packet )
{
RoqContext * enc = avctx - > priv_data ;
RoqEncContext * const enc = avctx - > priv_data ;
RoqContext * const roq = & enc - > common ;
int size , ret ;
enc - > avctx = avctx ;
roq - > avctx = avctx ;
enc - > frame_to_enc = frame ;
@ -1070,7 +1104,7 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
/* 138 bits max per 8x8 block +
* 256 codebooks * ( 6 bytes 2 x2 + 4 bytes 4 x4 ) + 8 bytes frame header */
size = ( ( enc - > width * enc - > height / 64 ) * 138 + 7 ) / 8 + 256 * ( 6 + 4 ) + 8 ;
size = ( ( roq - > width * roq - > height / 64 ) * 138 + 7 ) / 8 + 256 * ( 6 + 4 ) + 8 ;
if ( ( ret = ff_alloc_packet2 ( avctx , pkt , size , 0 ) ) < 0 )
return ret ;
enc - > out_buf = pkt - > data ;
@ -1082,8 +1116,8 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
if ( enc - > first_frame ) {
/* Alloc memory for the reconstruction data (we must know the stride
for that ) */
if ( ( ret = ff_get_buffer ( avctx , enc - > current_frame , 0 ) ) < 0 | |
( ret = ff_get_buffer ( avctx , enc - > last_frame , 0 ) ) < 0 )
if ( ( ret = ff_get_buffer ( avctx , roq - > current_frame , 0 ) ) < 0 | |
( ret = ff_get_buffer ( avctx , roq - > last_frame , 0 ) ) < 0 )
return ret ;
/* Before the first video frame, write a "video info" chunk */
@ -1105,7 +1139,7 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
return 0 ;
}
# define OFFSET(x) offsetof(RoqContext, x)
# define OFFSET(x) offsetof(RoqEnc Context, 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_BOOL , { . i64 = 1 } , 0 , 1 , VE } ,
@ -1124,7 +1158,7 @@ AVCodec ff_roq_encoder = {
. long_name = NULL_IF_CONFIG_SMALL ( " id RoQ video " ) ,
. type = AVMEDIA_TYPE_VIDEO ,
. id = AV_CODEC_ID_ROQ ,
. priv_data_size = sizeof ( RoqContext ) ,
. priv_data_size = sizeof ( RoqEnc Context ) ,
. init = roq_encode_init ,
. encode2 = roq_encode_frame ,
. close = roq_encode_end ,