Skip to content

Commit e05c303

Browse files
committed
Allow non-multiple-of-8 video dimensions.
This adds Daala's low pass extension, and codes the cropped size in the bitstream.
1 parent 191fcb3 commit e05c303

File tree

6 files changed

+112
-55
lines changed

6 files changed

+112
-55
lines changed

common/common_frame.c

Lines changed: 79 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -348,42 +348,90 @@ void close_yuv_frame(yuv_frame_t *frame)
348348
free(frame->v);
349349
}
350350

351-
void read_yuv_frame(yuv_frame_t *frame, int width, int height, FILE *infile)
351+
/*Extend the edge into the padding.*/
352+
static void img_plane_edge_ext8(unsigned char * dst_data, int dstride,
353+
int plane_width, int plane_height, int horz_padding, int vert_padding) {
354+
unsigned char *dst;
355+
int x;
356+
int y;
357+
/*Right side.*/
358+
for (y = 0; y < plane_height; y++) {
359+
dst = dst_data + plane_width - 1 + dstride*y;
360+
for (x = 1; x <= horz_padding; x++) {
361+
dst[x] = dst[0];
362+
}
363+
}
364+
/*Bottom.*/
365+
dst = dst_data - horz_padding + plane_height*dstride;
366+
for (y = 0; y < vert_padding; y++) {
367+
for (x = 0; x < plane_width + horz_padding; x++) {
368+
dst[x] = (dst - dstride)[x];
369+
}
370+
dst += dstride;
371+
}
372+
}
373+
374+
void read_yuv_frame(yuv_frame_t *frame, int crop_width, int crop_height,
375+
int width, int height, FILE *infile)
352376
{
353-
{
354-
unsigned int ysize = width*height;
355-
unsigned int csize = ysize/4;
356-
if (fread(frame->y, sizeof(unsigned char), ysize, infile) != ysize)
357-
{
358-
fatalerror("Error reading Y from file");
359-
}
360-
if (fread(frame->u, sizeof(unsigned char), csize, infile) != csize)
361-
{
362-
fatalerror("Error reading U from file");
363-
}
364-
if (fread(frame->v, sizeof(unsigned char), csize, infile) != csize)
365-
{
366-
fatalerror("Error reading V from file");
367-
}
377+
int pli;
378+
for (pli = 0; pli < 3; pli++) {
379+
int xdec = pli == 0 ? 0 : 1;
380+
int plane_width = (crop_width + xdec) >> xdec;
381+
int plane_height = (crop_height + xdec) >> xdec;
382+
int outstride = width >> xdec;
383+
int y;
384+
unsigned char * plane;
385+
switch (pli) {
386+
case 0:
387+
plane = frame->y;
388+
break;
389+
case 1:
390+
plane = frame->u;
391+
break;
392+
case 2:
393+
plane = frame->v;
394+
break;
395+
}
396+
for (y = 0; y < plane_height; y++) {
397+
if (fread(plane + y*outstride, sizeof(unsigned char), plane_width, infile)
398+
!= plane_width) {
399+
fatalerror("Error reading plane from file");
400+
}
401+
}
402+
img_plane_edge_ext8(plane, outstride, plane_width, plane_height,
403+
(width >> xdec) - plane_width, (height >> xdec) - plane_height);
368404
}
369405
}
370406

371-
void write_yuv_frame(yuv_frame_t *frame, int width, int height, FILE *outfile)
407+
void write_yuv_frame(yuv_frame_t *frame, int crop_width, int crop_height,
408+
int width, int height, FILE *outfile)
372409
{
373-
unsigned int ysize = width*height;
374-
unsigned int csize = ysize/4;
375-
if (fwrite(frame->y, sizeof(unsigned char), ysize, outfile) != ysize)
376-
{
377-
fatalerror("Error writing Y to file");
378-
}
379-
if (fwrite(frame->u, sizeof(unsigned char), csize, outfile) != csize)
380-
{
381-
fatalerror("Error writing U to file");
382-
}
383-
if (fwrite(frame->v, sizeof(unsigned char), csize, outfile) != csize)
384-
{
385-
fatalerror("Error writing V to file");
386-
}
410+
int pli;
411+
for (pli = 0; pli < 3; pli++) {
412+
int xdec = pli == 0 ? 0 : 1;
413+
int plane_width = (crop_width + xdec) >> xdec;
414+
int plane_height = (crop_height + xdec) >> xdec;
415+
int y;
416+
unsigned char * plane;
417+
switch (pli) {
418+
case 0:
419+
plane = frame->y;
420+
break;
421+
case 1:
422+
plane = frame->u;
423+
break;
424+
case 2:
425+
plane = frame->v;
426+
break;
427+
}
428+
for (y = 0; y < plane_height; y++) {
429+
if (fwrite(plane + y*(width>>xdec), sizeof(unsigned char), plane_width, outfile)
430+
!= plane_width) {
431+
fatalerror("Error writing plane from file");
432+
}
433+
}
434+
}
387435
}
388436

389437
void create_reference_frame(yuv_frame_t *ref,yuv_frame_t *rec)

common/common_frame.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ void deblock_frame_y(yuv_frame_t *rec, deblock_data_t *deblock_data, int width,
3131
void deblock_frame_uv(yuv_frame_t *rec, deblock_data_t *deblock_data, int width, int height, uint8_t qp);
3232
void create_yuv_frame(yuv_frame_t *frame, int width, int height, int pad_ver_y, int pad_hor_y, int pad_ver_uv, int pad_hor_uv);
3333
void close_yuv_frame(yuv_frame_t *frame);
34-
void read_yuv_frame(yuv_frame_t *frame, int width, int height, FILE *infile);
35-
void write_yuv_frame(yuv_frame_t *frame, int width, int height, FILE *outfile);
34+
void read_yuv_frame(yuv_frame_t *frame, int crop_width, int crop_height, int width, int height, FILE *infile);
35+
void write_yuv_frame(yuv_frame_t *frame, int crop_width, int crop_height, int width, int height, FILE *outfile);
3636
void create_reference_frame(yuv_frame_t *ref,yuv_frame_t *rec);
3737

3838
#endif

dec/maindec.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ int main(int argc, char** argv)
128128
int last_frame_output = -1;
129129
int width;
130130
int height;
131+
int crop_width;
132+
int crop_height;
131133
int r;
132134
int sub_gop=1;
133135

@@ -147,8 +149,10 @@ int main(int argc, char** argv)
147149

148150
int bit_start = stream.bitcnt;
149151
/* Read sequence header */
150-
width = getbits(&stream,16);
151-
height = getbits(&stream,16);
152+
crop_width = getbits(&stream,16);
153+
crop_height = getbits(&stream,16);
154+
width = ((crop_width + 7) >> 3) << 3;
155+
height = ((crop_height + 7) >> 3) << 3;
152156

153157
decoder_info.width = width;
154158
decoder_info.height = height;
@@ -198,7 +202,8 @@ int main(int argc, char** argv)
198202
rec_buffer_idx = (last_frame_output+1)%MAX_REORDER_BUFFER;
199203
if (rec_available[rec_buffer_idx]) {
200204
last_frame_output++;
201-
write_yuv_frame(&rec[rec_buffer_idx],width,height,outfile);
205+
write_yuv_frame(&rec[rec_buffer_idx],crop_width,
206+
crop_height,width,height,outfile);
202207
rec_available[rec_buffer_idx] = 0;
203208
}
204209
printf("decode_frame_num=%4d display_frame_num=%4d input_file_size=%12d bitcnt=%12d\n",
@@ -212,7 +217,8 @@ int main(int argc, char** argv)
212217
for (i=1; i<=MAX_REORDER_BUFFER; ++i) {
213218
rec_buffer_idx=(last_frame_output+i) % MAX_REORDER_BUFFER;
214219
if (rec_available[rec_buffer_idx])
215-
write_yuv_frame(&rec[rec_buffer_idx],width,height,outfile);
220+
write_yuv_frame(&rec[rec_buffer_idx],crop_width,
221+
crop_height,width,height,outfile);
216222
else
217223
break;
218224
}

enc/mainenc.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ int main(int argc, char **argv)
137137
if (y4m_output) {
138138
fprintf(reconfile,
139139
"YUV4MPEG2 W%d H%d F%d:1 Ip A0:0 C420jpeg XYSCSS=420JPEG\x0a",
140-
params->width, params->height, (int)params->frame_rate);
140+
params->crop_width, params->crop_height, (int)params->frame_rate);
141141
}
142142

143143
accsnr.y = 0;
@@ -147,10 +147,10 @@ int main(int argc, char **argv)
147147

148148
height = params->height;
149149
width = params->width;
150-
input_stride_y = width;
151-
input_stride_c = width/2;
152-
ysize = height * width;
153-
csize = ysize / 4;
150+
input_stride_y = params->crop_width;
151+
input_stride_c = (params->crop_width + 1)/2;
152+
ysize = params->crop_width*params->crop_height;
153+
csize = ((params->crop_width + 1)/2)*((params->crop_height + 1)/2);
154154
frame_size = ysize + 2*csize;
155155

156156
/* Create frames*/
@@ -185,8 +185,8 @@ int main(int argc, char **argv)
185185

186186
/* Write sequence header */ //TODO: Separate function for sequence header
187187
start_bits = get_bit_pos(&stream);
188-
putbits(16,width,&stream);
189-
putbits(16,height,&stream);
188+
putbits(16,params->crop_width,&stream);
189+
putbits(16,params->crop_height,&stream);
190190
putbits(1,params->enable_pb_split,&stream);
191191
putbits(1,params->enable_tb_split,&stream);
192192
putbits(2,params->max_num_ref-1,&stream); //TODO: Support more than 4 reference frames
@@ -388,7 +388,7 @@ int main(int argc, char **argv)
388388

389389
/* Read input frame */
390390
fseek(infile, frame_num*(frame_size+params->frame_headerlen)+params->file_headerlen+params->frame_headerlen, SEEK_SET);
391-
read_yuv_frame(&orig,width,height,infile);
391+
read_yuv_frame(&orig,params->crop_width,params->crop_height,width,height,infile);
392392
orig.frame_num = encoder_info.frame_info.frame_num;
393393

394394
/* Encode frame */
@@ -437,7 +437,8 @@ int main(int argc, char **argv)
437437
{
438438
fprintf(reconfile, "FRAME\x0a");
439439
}
440-
write_yuv_frame(&rec[rec_buffer_idx],width,height,reconfile);
440+
write_yuv_frame(&rec[rec_buffer_idx],params->crop_width,
441+
params->crop_height,width,height,reconfile);
441442
rec_available[rec_buffer_idx]=0;
442443
}
443444
}
@@ -449,7 +450,8 @@ int main(int argc, char **argv)
449450
for (i=1; i<=MAX_REORDER_BUFFER; ++i) {
450451
rec_buffer_idx=(last_frame_output+i) % MAX_REORDER_BUFFER;
451452
if (rec_available[rec_buffer_idx]) {
452-
write_yuv_frame(&rec[rec_buffer_idx],width,height,reconfile);
453+
write_yuv_frame(&rec[rec_buffer_idx],params->crop_width,params->crop_height,
454+
width,height,reconfile);
453455
rec_available[rec_buffer_idx]=0;
454456
}
455457
else

enc/mainenc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ typedef struct
3535
{
3636
unsigned int width;
3737
unsigned int height;
38+
unsigned int crop_width;
39+
unsigned int crop_height;
3840
unsigned int qp;
3941
char *infilestr;
4042
char *outfilestr;

enc/strings.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,8 @@ enc_params *parse_config_params(int argc, char **argv)
291291
add_param_to_list(&list, "-stat", NULL, ARG_FILENAME, &params->statfilestr);
292292
add_param_to_list(&list, "-n", "600", ARG_INTEGER, &params->num_frames);
293293
add_param_to_list(&list, "-skip", "0", ARG_INTEGER, &params->skip);
294-
add_param_to_list(&list, "-width", "1920", ARG_INTEGER, &params->width);
295-
add_param_to_list(&list, "-height", "1080", ARG_INTEGER, &params->height);
294+
add_param_to_list(&list, "-width", "1920", ARG_INTEGER, &params->crop_width);
295+
add_param_to_list(&list, "-height", "1080", ARG_INTEGER, &params->crop_height);
296296
add_param_to_list(&list, "-qp", "32", ARG_INTEGER, &params->qp);
297297
add_param_to_list(&list, "-f", "60", ARG_FLOAT, &params->frame_rate);
298298
add_param_to_list(&list, "-lambda_coeffI", "1.0", ARG_FLOAT, &params->lambda_coeffI);
@@ -365,11 +365,11 @@ enc_params *parse_config_params(int argc, char **argv)
365365
while (pos < len && buf[pos] != '\n') {
366366
switch (buf[pos++]) {
367367
case 'W':
368-
params->width = strtol(buf+pos, &end, 10);
368+
params->crop_width = strtol(buf+pos, &end, 10);
369369
pos = end-buf+1;
370370
break;
371371
case 'H':
372-
params->height = strtol(buf+pos, &end, 10);
372+
params->crop_height = strtol(buf+pos, &end, 10);
373373
pos = end-buf+1;
374374
break;
375375
case 'F':
@@ -406,6 +406,9 @@ enc_params *parse_config_params(int argc, char **argv)
406406
}
407407
fclose(infile);
408408
}
409+
params->width = ((params->crop_width + 7) >> 3) << 3;
410+
params->height = ((params->crop_height + 7) >> 3) << 3;
411+
printf("%dx%d -> %dx%d\n", params->crop_width, params->crop_height, params->width, params->height);
409412
return params;
410413
}
411414

@@ -432,10 +435,6 @@ void check_parameters(enc_params *params)
432435
{
433436
fatalerror("Number of frames must be positive");
434437
}
435-
if (params->width%8 || params->height%8)
436-
{
437-
fatalerror("Width and height must be a multiple of 8\n");
438-
}
439438

440439
if (params->max_num_ref < 1 || params->max_num_ref > 4)
441440
{

0 commit comments

Comments
 (0)