diff --git a/common/common_frame.c b/common/common_frame.c index e4517d7..f6dc774 100644 --- a/common/common_frame.c +++ b/common/common_frame.c @@ -348,41 +348,89 @@ void close_yuv_frame(yuv_frame_t *frame) free(frame->v); } -void read_yuv_frame(yuv_frame_t *frame, int width, int height, FILE *infile) -{ - { - unsigned int ysize = width*height; - unsigned int csize = ysize/4; - if (fread(frame->y, sizeof(unsigned char), ysize, infile) != ysize) - { - fatalerror("Error reading Y from file"); - } - if (fread(frame->u, sizeof(unsigned char), csize, infile) != csize) - { - fatalerror("Error reading U from file"); - } - if (fread(frame->v, sizeof(unsigned char), csize, infile) != csize) - { - fatalerror("Error reading V from file"); - } - } +/*Extend the edge into the padding.*/ +static void img_plane_edge_ext8(unsigned char * dst_data, int dstride, + int plane_width, int plane_height, int horz_padding, int vert_padding) { + unsigned char *dst; + int x; + int y; + /*Right side.*/ + for (y = 0; y < plane_height; y++) { + dst = dst_data + plane_width - 1 + dstride*y; + for (x = 1; x <= horz_padding; x++) { + dst[x] = dst[0]; + } + } + /*Bottom.*/ + dst = dst_data - horz_padding + plane_height*dstride; + for (y = 0; y < vert_padding; y++) { + for (x = 0; x < plane_width + horz_padding; x++) { + dst[x] = (dst - dstride)[x]; + } + dst += dstride; + } } -void write_yuv_frame(yuv_frame_t *frame, int width, int height, FILE *outfile) +void read_yuv_frame(yuv_frame_t *frame, int crop_width, int crop_height, + int width, int height, FILE *infile) { - unsigned int ysize = width*height; - unsigned int csize = ysize/4; - if (fwrite(frame->y, sizeof(unsigned char), ysize, outfile) != ysize) - { - fatalerror("Error writing Y to file"); - } - if (fwrite(frame->u, sizeof(unsigned char), csize, outfile) != csize) - { - fatalerror("Error writing U to file"); + int pli; + for (pli = 0; pli < 3; pli++) { + int xdec = pli == 0 ? 0 : 1; + int plane_width = (crop_width + xdec) >> xdec; + int plane_height = (crop_height + xdec) >> xdec; + int outstride = width >> xdec; + int y; + unsigned char * plane; + switch (pli) { + case 0: + plane = frame->y; + break; + case 1: + plane = frame->u; + break; + case 2: + plane = frame->v; + break; + } + for (y = 0; y < plane_height; y++) { + if (fread(plane + y*outstride, sizeof(unsigned char), plane_width, infile) + != plane_width) { + fatalerror("Error reading plane from file"); + } + } + img_plane_edge_ext8(plane, outstride, plane_width, plane_height, + (width >> xdec) - plane_width, (height >> xdec) - plane_height); } - if (fwrite(frame->v, sizeof(unsigned char), csize, outfile) != csize) - { - fatalerror("Error writing V to file"); +} + +void write_yuv_frame(yuv_frame_t *frame, int crop_width, int crop_height, + int width, int height, FILE *outfile) +{ + int pli; + for (pli = 0; pli < 3; pli++) { + int xdec = pli == 0 ? 0 : 1; + int plane_width = (crop_width + xdec) >> xdec; + int plane_height = (crop_height + xdec) >> xdec; + int y; + unsigned char * plane; + switch (pli) { + case 0: + plane = frame->y; + break; + case 1: + plane = frame->u; + break; + case 2: + plane = frame->v; + break; + } + for (y = 0; y < plane_height; y++) { + if (fwrite(plane + y*(width>>xdec), sizeof(unsigned char), plane_width, outfile) + != plane_width) { + fatalerror("Error writing plane from file"); + } + } } } diff --git a/common/common_frame.h b/common/common_frame.h index 9704385..c6081b3 100644 --- a/common/common_frame.h +++ b/common/common_frame.h @@ -31,8 +31,8 @@ void deblock_frame_y(yuv_frame_t *rec, deblock_data_t *deblock_data, int width, void deblock_frame_uv(yuv_frame_t *rec, deblock_data_t *deblock_data, int width, int height, uint8_t qp); 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); void close_yuv_frame(yuv_frame_t *frame); -void read_yuv_frame(yuv_frame_t *frame, int width, int height, FILE *infile); -void write_yuv_frame(yuv_frame_t *frame, int width, int height, FILE *outfile); +void read_yuv_frame(yuv_frame_t *frame, int crop_width, int crop_height, int width, int height, FILE *infile); +void write_yuv_frame(yuv_frame_t *frame, int crop_width, int crop_height, int width, int height, FILE *outfile); void create_reference_frame(yuv_frame_t *ref,yuv_frame_t *rec); #endif diff --git a/dec/maindec.c b/dec/maindec.c index 6228eba..51e46ef 100644 --- a/dec/maindec.c +++ b/dec/maindec.c @@ -128,6 +128,8 @@ int main(int argc, char** argv) int last_frame_output = -1; int width; int height; + int crop_width; + int crop_height; int r; int sub_gop=1; @@ -147,8 +149,10 @@ int main(int argc, char** argv) int bit_start = stream.bitcnt; /* Read sequence header */ - width = getbits(&stream,16); - height = getbits(&stream,16); + crop_width = getbits(&stream,16); + crop_height = getbits(&stream,16); + width = ((crop_width + 7) >> 3) << 3; + height = ((crop_height + 7) >> 3) << 3; decoder_info.width = width; decoder_info.height = height; @@ -198,7 +202,8 @@ int main(int argc, char** argv) rec_buffer_idx = (last_frame_output+1)%MAX_REORDER_BUFFER; if (rec_available[rec_buffer_idx]) { last_frame_output++; - write_yuv_frame(&rec[rec_buffer_idx],width,height,outfile); + write_yuv_frame(&rec[rec_buffer_idx],crop_width, + crop_height,width,height,outfile); rec_available[rec_buffer_idx] = 0; } 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) for (i=1; i<=MAX_REORDER_BUFFER; ++i) { rec_buffer_idx=(last_frame_output+i) % MAX_REORDER_BUFFER; if (rec_available[rec_buffer_idx]) - write_yuv_frame(&rec[rec_buffer_idx],width,height,outfile); + write_yuv_frame(&rec[rec_buffer_idx],crop_width, + crop_height,width,height,outfile); else break; } diff --git a/enc/mainenc.c b/enc/mainenc.c index 68d800b..71ec653 100644 --- a/enc/mainenc.c +++ b/enc/mainenc.c @@ -137,7 +137,7 @@ int main(int argc, char **argv) if (y4m_output) { fprintf(reconfile, "YUV4MPEG2 W%d H%d F%d:1 Ip A0:0 C420jpeg XYSCSS=420JPEG\x0a", - params->width, params->height, (int)params->frame_rate); + params->crop_width, params->crop_height, (int)params->frame_rate); } accsnr.y = 0; @@ -147,10 +147,10 @@ int main(int argc, char **argv) height = params->height; width = params->width; - input_stride_y = width; - input_stride_c = width/2; - ysize = height * width; - csize = ysize / 4; + input_stride_y = params->crop_width; + input_stride_c = (params->crop_width + 1)/2; + ysize = params->crop_width*params->crop_height; + csize = ((params->crop_width + 1)/2)*((params->crop_height + 1)/2); frame_size = ysize + 2*csize; /* Create frames*/ @@ -185,8 +185,8 @@ int main(int argc, char **argv) /* Write sequence header */ //TODO: Separate function for sequence header start_bits = get_bit_pos(&stream); - putbits(16,width,&stream); - putbits(16,height,&stream); + putbits(16,params->crop_width,&stream); + putbits(16,params->crop_height,&stream); putbits(1,params->enable_pb_split,&stream); putbits(1,params->enable_tb_split,&stream); 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) /* Read input frame */ fseek(infile, frame_num*(frame_size+params->frame_headerlen)+params->file_headerlen+params->frame_headerlen, SEEK_SET); - read_yuv_frame(&orig,width,height,infile); + read_yuv_frame(&orig,params->crop_width,params->crop_height,width,height,infile); orig.frame_num = encoder_info.frame_info.frame_num; /* Encode frame */ @@ -437,7 +437,8 @@ int main(int argc, char **argv) { fprintf(reconfile, "FRAME\x0a"); } - write_yuv_frame(&rec[rec_buffer_idx],width,height,reconfile); + write_yuv_frame(&rec[rec_buffer_idx],params->crop_width, + params->crop_height,width,height,reconfile); rec_available[rec_buffer_idx]=0; } } @@ -449,7 +450,8 @@ int main(int argc, char **argv) for (i=1; i<=MAX_REORDER_BUFFER; ++i) { rec_buffer_idx=(last_frame_output+i) % MAX_REORDER_BUFFER; if (rec_available[rec_buffer_idx]) { - write_yuv_frame(&rec[rec_buffer_idx],width,height,reconfile); + write_yuv_frame(&rec[rec_buffer_idx],params->crop_width,params->crop_height, + width,height,reconfile); rec_available[rec_buffer_idx]=0; } else diff --git a/enc/mainenc.h b/enc/mainenc.h index 0837782..9bd167d 100644 --- a/enc/mainenc.h +++ b/enc/mainenc.h @@ -35,6 +35,8 @@ typedef struct { unsigned int width; unsigned int height; + unsigned int crop_width; + unsigned int crop_height; unsigned int qp; char *infilestr; char *outfilestr; diff --git a/enc/strings.c b/enc/strings.c index 6e79916..56caaa4 100644 --- a/enc/strings.c +++ b/enc/strings.c @@ -291,8 +291,8 @@ enc_params *parse_config_params(int argc, char **argv) add_param_to_list(&list, "-stat", NULL, ARG_FILENAME, ¶ms->statfilestr); add_param_to_list(&list, "-n", "600", ARG_INTEGER, ¶ms->num_frames); add_param_to_list(&list, "-skip", "0", ARG_INTEGER, ¶ms->skip); - add_param_to_list(&list, "-width", "1920", ARG_INTEGER, ¶ms->width); - add_param_to_list(&list, "-height", "1080", ARG_INTEGER, ¶ms->height); + add_param_to_list(&list, "-width", "1920", ARG_INTEGER, ¶ms->crop_width); + add_param_to_list(&list, "-height", "1080", ARG_INTEGER, ¶ms->crop_height); add_param_to_list(&list, "-qp", "32", ARG_INTEGER, ¶ms->qp); add_param_to_list(&list, "-f", "60", ARG_FLOAT, ¶ms->frame_rate); add_param_to_list(&list, "-lambda_coeffI", "1.0", ARG_FLOAT, ¶ms->lambda_coeffI); @@ -365,11 +365,11 @@ enc_params *parse_config_params(int argc, char **argv) while (pos < len && buf[pos] != '\n') { switch (buf[pos++]) { case 'W': - params->width = strtol(buf+pos, &end, 10); + params->crop_width = strtol(buf+pos, &end, 10); pos = end-buf+1; break; case 'H': - params->height = strtol(buf+pos, &end, 10); + params->crop_height = strtol(buf+pos, &end, 10); pos = end-buf+1; break; case 'F': @@ -406,6 +406,8 @@ enc_params *parse_config_params(int argc, char **argv) } fclose(infile); } + params->width = ((params->crop_width + 7) >> 3) << 3; + params->height = ((params->crop_height + 7) >> 3) << 3; return params; } @@ -432,10 +434,6 @@ void check_parameters(enc_params *params) { fatalerror("Number of frames must be positive"); } - if (params->width%8 || params->height%8) - { - fatalerror("Width and height must be a multiple of 8\n"); - } if (params->max_num_ref < 1 || params->max_num_ref > 4) {