diff --git a/examples/dump_video.c b/examples/dump_video.c index 98eee36e..df1008a0 100644 --- a/examples/dump_video.c +++ b/examples/dump_video.c @@ -59,6 +59,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/ #include "getopt.h" #include "../src/logging.h" #include "../include/daala/daaladec.h" +#include "../include/daala/codec.h" const char *optstring = "o:r"; struct option options [] = { @@ -123,10 +124,19 @@ static void video_write(void) { for (pli = 0; pli < img.nplanes; pli++) { int plane_width; int plane_height; - int xdec; - int ydec; - xdec = img.planes[pli].xdec; - ydec = img.planes[pli].ydec; + int xdec = 0; + int ydec = 0; + if (pli && pli != 4) + if (img.pixel_format == OD_PIX_YUV422) { + xdec = 1; + } else if (img.pixel_format == OD_PIX_YUV411) { + xdec = 2; + } else if (img.pixel_format == OD_PIX_YUV420) { + xdec = 1; + ydec = 1; + } + } + plane_width = (img.width + (1 << xdec) - 1) >> xdec; plane_height = (img.height + (1 << ydec) - 1) >> ydec; for (i = 0; i < plane_height; i++) { @@ -360,22 +370,16 @@ int main(int argc, char *argv[]) { pic_height = di.pic_height; fps_num = di.timebase_numerator; fps_denom = di.timebase_denominator*di.frame_duration; - if (di.nplanes > 1) { - /*calculate pixel_fmt based on the xdec & ydec values from one of the - chroma planes.*/ - if (di.plane_info[1].xdec == 1 && di.plane_info[1].ydec == 1) { - pix_fmt = 0; - } - else if (di.plane_info[1].xdec == 1 && di.plane_info[1].ydec == 0) { - pix_fmt = 2; - } - else if (di.plane_info[1].xdec == 0 && di.plane_info[1].ydec == 0) { - pix_fmt = 3; - } - } - else { + + if (di.pixel_format == OD_PIX_YUV420) + pix_fmt = 0; + else if (di.pixel_format == OD_PIX_YUV422) + pix_fmt = 2; + else if (di.pixel_format == OD_PIX_YUV444) + pix_fmt = 3; + else if (di.pixel_format == OD_PIX_YUV400) pix_fmt = 4; - } + if (pix_fmt >= 5 || pix_fmt == 1) { fprintf(stderr, "Unknown pixel format: %i\n", pix_fmt); exit(1); diff --git a/examples/encoder_example.c b/examples/encoder_example.c index 3085fd1b..058e3239 100644 --- a/examples/encoder_example.c +++ b/examples/encoder_example.c @@ -56,7 +56,7 @@ struct av_input{ int video_interlacing; char video_chroma_type[16]; int video_nplanes; - daala_plane_info video_plane_info[OD_NPLANES_MAX]; + int video_format; od_img video_img; int video_cur_img; int video_depth; @@ -176,6 +176,8 @@ static void id_y4m_file(av_input *avin, const char *file, FILE *test) { int ret; int pli; int bi; + int xdec[OD_NPLANES_MAX] = { 0 }; + int ydec[OD_NPLANES_MAX] = { 0 }; for (bi = 0; bi < 127; bi++) { ret = fread(buf + bi, 1, 1, test); if (ret < 1) return; @@ -209,160 +211,112 @@ static void id_y4m_file(av_input *avin, const char *file, FILE *test) { (double)avin->video_fps_n/avin->video_fps_d, avin->video_chroma_type); /*Allocate buffers for the image data.*/ /*TODO: Specify chroma offsets.*/ - avin->video_plane_info[0].xdec = 0; - avin->video_plane_info[0].ydec = 0; avin->video_depth = 8; - avin->video_swapendian = 0; + avin->video_nplanes = 3; + avin->video_swapendian = host_is_big_endian(); if (strcmp(avin->video_chroma_type, "444") == 0) { - avin->video_nplanes = 3; - avin->video_plane_info[1].xdec = 0; - avin->video_plane_info[1].ydec = 0; - avin->video_plane_info[2].xdec = 0; - avin->video_plane_info[2].ydec = 0; + avin->video_format = OD_PIX_YUV444; } else if (strcmp(avin->video_chroma_type, "444p10") == 0) { - avin->video_nplanes = 3; + avin->video_format = OD_PIX_YUV444; avin->video_depth = 10; - avin->video_swapendian = host_is_big_endian(); - avin->video_plane_info[1].xdec = 0; - avin->video_plane_info[1].ydec = 0; - avin->video_plane_info[2].xdec = 0; - avin->video_plane_info[2].ydec = 0; } else if (strcmp(avin->video_chroma_type, "444p12") == 0) { - avin->video_nplanes = 3; + avin->video_format = OD_PIX_YUV444; avin->video_depth = 12; - avin->video_swapendian = host_is_big_endian(); - avin->video_plane_info[1].xdec = 0; - avin->video_plane_info[1].ydec = 0; - avin->video_plane_info[2].xdec = 0; - avin->video_plane_info[2].ydec = 0; } else if (strcmp(avin->video_chroma_type, "444p14") == 0) { - avin->video_nplanes = 3; + avin->video_format = OD_PIX_YUV444; avin->video_depth = 14; - avin->video_swapendian = host_is_big_endian(); - avin->video_plane_info[1].xdec = 0; - avin->video_plane_info[1].ydec = 0; - avin->video_plane_info[2].xdec = 0; - avin->video_plane_info[2].ydec = 0; } else if (strcmp(avin->video_chroma_type, "444p16") == 0) { - avin->video_nplanes = 3; + avin->video_format = OD_PIX_YUV444; avin->video_depth = 16; - avin->video_swapendian = host_is_big_endian(); - avin->video_plane_info[1].xdec = 0; - avin->video_plane_info[1].ydec = 0; - avin->video_plane_info[2].xdec = 0; - avin->video_plane_info[2].ydec = 0; } else if (strcmp(avin->video_chroma_type, "444alpha") == 0) { avin->video_nplanes = 4; - avin->video_plane_info[1].xdec = 0; - avin->video_plane_info[1].ydec = 0; - avin->video_plane_info[2].xdec = 0; - avin->video_plane_info[2].ydec = 0; - avin->video_plane_info[3].xdec = 0; - avin->video_plane_info[3].ydec = 0; + avin->video_format = OD_PIX_YUV444; } else if (strcmp(avin->video_chroma_type, "422") == 0) { - avin->video_nplanes = 3; - avin->video_plane_info[1].xdec = 1; - avin->video_plane_info[1].ydec = 0; - avin->video_plane_info[2].xdec = 1; - avin->video_plane_info[2].ydec = 0; + avin->video_format = OD_PIX_YUV422; + xdec[1] = 1; + xdec[2] = 1; } else if (strcmp(avin->video_chroma_type, "422p10") == 0) { - avin->video_nplanes = 3; + avin->video_format = OD_PIX_YUV422; avin->video_depth = 10; - avin->video_swapendian = host_is_big_endian(); - avin->video_plane_info[1].xdec = 1; - avin->video_plane_info[1].ydec = 0; - avin->video_plane_info[2].xdec = 1; - avin->video_plane_info[2].ydec = 0; + xdec[1] = 1; + xdec[2] = 1; } else if (strcmp(avin->video_chroma_type, "422p12") == 0) { - avin->video_nplanes = 3; + avin->video_format = OD_PIX_YUV422; avin->video_depth = 12; - avin->video_swapendian = host_is_big_endian(); - avin->video_plane_info[1].xdec = 1; - avin->video_plane_info[1].ydec = 0; - avin->video_plane_info[2].xdec = 1; - avin->video_plane_info[2].ydec = 0; + xdec[1] = 1; + xdec[2] = 1; } else if (strcmp(avin->video_chroma_type, "422p14") == 0) { - avin->video_nplanes = 3; + avin->video_format = OD_PIX_YUV422; avin->video_depth = 14; - avin->video_swapendian = host_is_big_endian(); - avin->video_plane_info[1].xdec = 1; - avin->video_plane_info[1].ydec = 0; - avin->video_plane_info[2].xdec = 1; - avin->video_plane_info[2].ydec = 0; + xdec[1] = 1; + xdec[2] = 1; } else if (strcmp(avin->video_chroma_type, "422p16") == 0) { - avin->video_nplanes = 3; + avin->video_format = OD_PIX_YUV422; avin->video_depth = 16; - avin->video_swapendian = host_is_big_endian(); - avin->video_plane_info[1].xdec = 1; - avin->video_plane_info[1].ydec = 0; - avin->video_plane_info[2].xdec = 1; - avin->video_plane_info[2].ydec = 0; + xdec[1] = 1; + xdec[2] = 1; } else if (strcmp(avin->video_chroma_type, "411") == 0) { - avin->video_nplanes = 3; - avin->video_plane_info[1].xdec = 2; - avin->video_plane_info[1].ydec = 0; - avin->video_plane_info[2].xdec = 2; - avin->video_plane_info[2].ydec = 0; + avin->video_format = OD_PIX_YUV411; + xdec[1] = 2; + xdec[2] = 2; } else if (strcmp(avin->video_chroma_type, "420") == 0 || strcmp(avin->video_chroma_type, "420jpeg") == 0 || strcmp(avin->video_chroma_type, "420mpeg2") == 0 || strcmp(avin->video_chroma_type, "420paldv") == 0) { - avin->video_nplanes = 3; - avin->video_plane_info[1].xdec = 1; - avin->video_plane_info[1].ydec = 1; - avin->video_plane_info[2].xdec = 1; - avin->video_plane_info[2].ydec = 1; + avin->video_format = OD_PIX_YUV420; + xdec[1] = 1; + ydec[1] = 1; + xdec[2] = 1; + ydec[2] = 1; } else if (strcmp(avin->video_chroma_type, "420p10") == 0){ - avin->video_nplanes = 3; + avin->video_format = OD_PIX_YUV420; avin->video_depth = 10; avin->video_swapendian = host_is_big_endian(); - avin->video_plane_info[1].xdec = 1; - avin->video_plane_info[1].ydec = 1; - avin->video_plane_info[2].xdec = 1; - avin->video_plane_info[2].ydec = 1; + xdec[1] = 1; + ydec[1] = 1; + xdec[2] = 1; + ydec[2] = 1; } else if (strcmp(avin->video_chroma_type, "420p12") == 0) { - avin->video_nplanes = 3; + avin->video_format = OD_PIX_YUV420; avin->video_depth = 12; - avin->video_swapendian = host_is_big_endian(); - avin->video_plane_info[1].xdec = 1; - avin->video_plane_info[1].ydec = 1; - avin->video_plane_info[2].xdec = 1; - avin->video_plane_info[2].ydec = 1; + xdec[1] = 1; + ydec[1] = 1; + xdec[2] = 1; + ydec[2] = 1; } else if (strcmp(avin->video_chroma_type, "420p14") == 0) { - avin->video_nplanes = 3; + avin->video_format = OD_PIX_YUV420; avin->video_depth = 14; - avin->video_swapendian = host_is_big_endian(); - avin->video_plane_info[1].xdec = 1; - avin->video_plane_info[1].ydec = 1; - avin->video_plane_info[2].xdec = 1; - avin->video_plane_info[2].ydec = 1; + xdec[1] = 1; + ydec[1] = 1; + xdec[2] = 1; + ydec[2] = 1; } else if (strcmp(avin->video_chroma_type, "420p16") == 0) { - avin->video_nplanes = 3; + avin->video_format = OD_PIX_YUV420; avin->video_depth = 16; - avin->video_swapendian = host_is_big_endian(); - avin->video_plane_info[1].xdec = 1; - avin->video_plane_info[1].ydec = 1; - avin->video_plane_info[2].xdec = 1; - avin->video_plane_info[2].ydec = 1; + xdec[1] = 1; + ydec[1] = 1; + xdec[2] = 1; + ydec[2] = 1; } else if (strcmp(avin->video_chroma_type, "mono") == 0) { avin->video_nplanes = 1; + avin->video_format = OD_PIX_YUV400; } else { fprintf(stderr, "Unknown chroma sampling type: '%s'.\n", @@ -373,21 +327,20 @@ static void id_y4m_file(av_input *avin, const char *file, FILE *test) { img->nplanes = avin->video_nplanes; img->width = avin->video_pic_w; img->height = avin->video_pic_h; + img->bitdepth = avin->video_depth; + img->pixel_format = avin->video_format; for (pli = 0; pli < img->nplanes; pli++) { od_img_plane *iplane; iplane = img->planes + pli; - iplane->xdec = avin->video_plane_info[pli].xdec; - iplane->ydec = avin->video_plane_info[pli].ydec; /*At this moment, Y4M input is always planar.*/ /*The input depth need not match the encoded depth. The input copy will convert to whatever was set for di.bitdepth_mode.*/ iplane->xstride = avin->video_depth > 8 ? 2 : 1; iplane->ystride = ((avin->video_pic_w - + (1<xdec)-1)>>iplane->xdec)*iplane->xstride; - iplane->bitdepth = avin->video_depth; + + (1 << xdec[pli]) - 1) >> xdec[pli]) * iplane->xstride; iplane->data = _ogg_malloc(iplane->ystride* - ((avin->video_pic_h + (1<ydec) - 1)>>iplane->ydec)); + ((avin->video_pic_h + (1 << ydec[pli]) - 1) >> ydec[pli])); } } @@ -461,11 +414,25 @@ int fetch_and_process_video(av_input *avin, ogg_page *page, od_img_plane *iplane; int bytes; size_t plane_sz; + int xdec = 0; + int ydec = 0; iplane = img->planes + pli; - bytes = iplane->bitdepth > 8 ? 2 : 1; - plane_sz = ((avin->video_pic_w + (1 << iplane->xdec) - 1) - >> iplane->xdec)*((avin->video_pic_h + (1 << iplane->ydec) - - 1) >> iplane->ydec)*bytes; + bytes = img->bitdepth > 8 ? 2 : 1; + + if (pli && pli != 4) { + if (img->pixel_format == OD_PIX_YUV422) { + xdec = 1; + } else if (img->pixel_format == OD_PIX_YUV411) { + xdec = 2; + } else if (img->pixel_format == OD_PIX_YUV420) { + xdec = 1; + ydec = 1; + } + } + + plane_sz = ((avin->video_pic_w + (1 << xdec) - 1) + >> xdec)*((avin->video_pic_h + (1 << ydec) + - 1) >> ydec)*bytes; ret = fread(iplane->data, 1, plane_sz, avin->video_infile); if (ret != plane_sz) { fprintf(stderr, "Error reading YUV frame data.\n"); @@ -853,8 +820,7 @@ int main(int argc, char **argv) { di.pixel_aspect_numerator = avin.video_par_n; di.pixel_aspect_denominator = avin.video_par_d; di.nplanes = avin.video_nplanes; - memcpy(di.plane_info, avin.video_plane_info, - di.nplanes*sizeof(*di.plane_info)); + di.pixel_format = avin.video_format; di.keyframe_rate = video_keyframe_rate; /*TODO: Other crap.*/ dd = daala_encode_create(&di); diff --git a/examples/player_example.c b/examples/player_example.c index baf8bc1d..a477b1f5 100644 --- a/examples/player_example.c +++ b/examples/player_example.c @@ -595,15 +595,20 @@ void img_to_rgb(player_example *player, SDL_Texture *texture, int cr_stride; int width; int height; - int xdec; - int ydec; + int xdec = 0; + int ydec = 0; int i; int j; unsigned char *pixels; int pitch; /*Assume both C planes are decimated.*/ - xdec = img->planes[1].xdec; - ydec = img->planes[1].ydec; + if (img->pixel_format == OD_PIX_YUV422) { + xdec = 1; + } else if (img->pixel_format == OD_PIX_YUV420) { + xdec = 1; + ydec = 1; + } + y_stride = img->planes[0].ystride; cb_stride = img->planes[1].ystride; cr_stride = img->planes[2].ystride; diff --git a/include/daala/codec.h b/include/daala/codec.h index a941c8a3..030a9b6d 100644 --- a/include/daala/codec.h +++ b/include/daala/codec.h @@ -121,6 +121,23 @@ extern "C" { # define OD_CS_NSPACES (5) /*@}*/ +/**\name Pixel formats + * Describes how pixels are stored in memory. */ +/*@{*/ +/**Y plane followed by U and V planes*/ +# define OD_PIX_YUV444 (1) +/**Y plane followed 1x1 subsampled U and V planes.*/ +# define OD_PIX_YUV422 (2) +/**Y plane followed by 2x1 subsampled U and V planes.*/ +# define OD_PIX_YUV411 (3) +/**Y plane followed by 2x2 subsampled U and V planes.*/ +# define OD_PIX_YUV420 (4) +/**Y plane only.*/ +# define OD_PIX_YUV400 (5) +/**Not part of ABI.*/ +# define OD_PIX_NB (6) +/*@}*/ + /**The maximum number of color planes allowed in a single frame.*/ # define OD_NPLANES_MAX (4) @@ -147,12 +164,6 @@ struct od_img_plane { /** Image data is stored as an unsigned octet type whether it's actually 8 bit or a multi-byte depth. */ unsigned char *data; - /** The decimation factor in the x and y direction. Pixels are reduced - by a factor of 2^xdec so 0 is none, 1 is decimated by a factor of 2. - ( YUV420 will have xdec of 1 and ydec also of 1. YUV444 will have - xdec and ydec set to zero ). */ - unsigned char xdec; - unsigned char ydec; /** Distance in memory between two pixels horizontally next to each other. The value is in bytes regardless of the 'actual' underlying depth (either unsigned bytes for 8 bit video or unsigned 16 bit shorts for @@ -163,30 +174,32 @@ struct od_img_plane { /** Distance in memory between two pixels vertically next to each other. As with xstride, this value is always in bytes. */ int ystride; - /** 8 for 'normal' video precision; data is unsigned bytes centered on 128. - Greater-than-8 indicates high-depth video; data is unnormalized - host-endian order unsigned signed 16-bit shorts (two octets). - For example, 10 bit video would declare a bit depth of 10, use the - lower 10 bits of each 16 bit short, and center on 512. */ - int bitdepth; }; /** Representation of an image or video frame. */ struct od_img { /** Typical 3 planes for Y, Cb, and Cr. Can have a 4th plane for alpha */ od_img_plane planes[OD_NPLANES_MAX]; - /** Number of planes (1 for greyscale, 3 for YCbCr, 4 for YCbCr+Alpha ) */ + /** Number of planes (1 for greyscale, 3 for YUV, 4 for YUV + Alpha) */ int nplanes; /** Width and height in pixels */ int32_t width; int32_t height; + /** 8 for 'normal' video precision; data is unsigned bytes centered on 128. + Greater-than-8 indicates high-depth video; data is unnormalized + host-endian order unsigned signed 16-bit shorts (two octets). + For example, 10 bit video would declare a bit depth of 10, use the + lower 10 bits of each 16 bit short, and center on 512. */ + int bitdepth; + /** pixel_format is one of the OD_PIX_X choices allowed above. */ + int pixel_format; }; /** Subsampling factors for a plane as a power of 2. * 4:2:0 would have {0, 0} for Y and {1, 1} for Cb and Cr. */ struct daala_plane_info { - unsigned char xdec; - unsigned char ydec; + unsigned char xdec[OD_NPLANES_MAX]; + unsigned char ydec[OD_NPLANES_MAX]; }; /**\name Bit Depths @@ -220,7 +233,8 @@ struct daala_info { * above. */ int bitdepth_mode; int nplanes; - daala_plane_info plane_info[OD_NPLANES_MAX]; + /** pixel_format is one of the OD_PIX_X choices allowed above. */ + int pixel_format; /** key frame rate defined how often a key frame is emitted by encoder in * number of frames. So 10 means every 10th frame is a keyframe. */ int keyframe_rate; diff --git a/src/decode.c b/src/decode.c index fd1c6475..34213927 100644 --- a/src/decode.c +++ b/src/decode.c @@ -76,8 +76,10 @@ static int od_dec_init(od_dec_ctx *dec, const daala_info *info, frame_buf_width = dec->state.frame_width + (OD_BUFFER_PADDING << 1); frame_buf_height = dec->state.frame_height + (OD_BUFFER_PADDING << 1); for (pli = 0; pli < info->nplanes; pli++) { - plane_buf_width = frame_buf_width >> info->plane_info[pli].xdec; - plane_buf_height = frame_buf_height >> info->plane_info[pli].ydec; + plane_buf_width = frame_buf_width >> + od_plane_info_tab[info->pixel_format].xdec[pli]; + plane_buf_height = frame_buf_height >> + od_plane_info_tab[info->pixel_format].ydec[pli]; data_sz += plane_buf_width*plane_buf_height*output_bytes; } dec->output_img_data = output_img_data = @@ -89,19 +91,19 @@ static int od_dec_init(od_dec_ctx *dec, const daala_info *info, img->nplanes = info->nplanes; img->width = dec->state.frame_width; img->height = dec->state.frame_height; + img->bitdepth = output_bits; for (pli = 0; pli < img->nplanes; pli++) { - plane_buf_width = frame_buf_width >> info->plane_info[pli].xdec; - plane_buf_height = frame_buf_height >> info->plane_info[pli].ydec; + int xdec = od_plane_info_tab[info->pixel_format].xdec[pli]; + int ydec = od_plane_info_tab[info->pixel_format].ydec[pli]; + plane_buf_width = frame_buf_width >> xdec; + plane_buf_height = frame_buf_height >> ydec; iplane = img->planes + pli; - iplane->xdec = info->plane_info[pli].xdec; - iplane->ydec = info->plane_info[pli].ydec; - iplane->bitdepth = output_bits; /*At this moment, our output is always planar.*/ iplane->xstride = output_bytes; iplane->ystride = plane_buf_width*iplane->xstride; iplane->data = output_img_data - + iplane->xstride*(OD_BUFFER_PADDING >> info->plane_info[pli].xdec) - + iplane->ystride*(OD_BUFFER_PADDING >> info->plane_info[pli].ydec); + + iplane->xstride*(OD_BUFFER_PADDING >> xdec) + + iplane->ystride*(OD_BUFFER_PADDING >> ydec); output_img_data += plane_buf_height*iplane->ystride; } #if OD_ACCOUNTING @@ -218,11 +220,13 @@ static void od_dec_blank_img(od_img *img) { for (pli = 0; pli < img->nplanes; pli++) { int plane_buf_size; int plane_buf_offset; + int xdec = od_plane_info_tab[img->pixel_format].xdec[pli]; + int ydec = od_plane_info_tab[img->pixel_format].ydec[pli]; plane_buf_size = - (frame_buf_height >> img->planes[pli].ydec) * img->planes[pli].ystride; + (frame_buf_height >> ydec) * img->planes[pli].ystride; plane_buf_offset = - (OD_BUFFER_PADDING >> img->planes[pli].ydec) * img->planes[pli].ystride - + (OD_BUFFER_PADDING >> img->planes[pli].xdec); + (OD_BUFFER_PADDING >> ydec) * img->planes[pli].ystride + + (OD_BUFFER_PADDING >> xdec); memset(img->planes[pli].data - plane_buf_offset, 128, plane_buf_size); } } @@ -304,7 +308,7 @@ static void od_decode_compute_pred(daala_dec_ctx *dec, od_mb_dec_ctx *ctx, int x; OD_ASSERT(bs >= 0 && bs < OD_NBSIZES); n = 1 << bs + OD_LOG_BSIZE0; - xdec = dec->output_img.planes[pli].xdec; + xdec = od_plane_info_tab[dec->output_img.pixel_format].xdec[pli]; w = dec->state.frame_width >> xdec; bo = (by << OD_LOG_BSIZE0)*w + (bx << OD_LOG_BSIZE0); /*We never use tf on the chroma planes, but if we do it will blow up, which @@ -529,7 +533,7 @@ static void od_block_decode(daala_dec_ctx *dec, od_mb_dec_ctx *ctx, int bs, qm = ctx->qm == OD_HVS_QM ? OD_QM8_Q4_HVS : OD_QM8_Q4_FLAT; bx <<= bs; by <<= bs; - xdec = dec->output_img.planes[pli].xdec; + xdec = od_plane_info_tab[dec->output_img.pixel_format].xdec[pli]; frame_width = dec->state.frame_width; w = frame_width >> xdec; bo = (by << 2)*w + (bx << 2); @@ -963,8 +967,8 @@ static void od_decode_coefficients(od_dec_ctx *dec, od_mb_dec_ctx *mbctx) { /*Apply the prefilter to the motion-compensated reference.*/ if (!mbctx->is_keyframe) { for (pli = 0; pli < nplanes; pli++) { - xdec = rec->planes[pli].xdec; - ydec = rec->planes[pli].ydec; + xdec = od_plane_info_tab[rec->pixel_format].xdec[pli]; + ydec = od_plane_info_tab[rec->pixel_format].ydec[pli]; w = frame_width >> xdec; h = frame_height >> ydec; /*Collect the image data needed for this plane.*/ @@ -1005,8 +1009,8 @@ static void od_decode_coefficients(od_dec_ctx *dec, od_mb_dec_ctx *mbctx) { mbctx->mc = state->mctmp[pli]; mbctx->md = state->mdtmp[pli]; mbctx->l = state->lbuf[pli]; - xdec = dec->output_img.planes[pli].xdec; - ydec = dec->output_img.planes[pli].ydec; + xdec = od_plane_info_tab[dec->output_img.pixel_format].xdec[pli]; + ydec = od_plane_info_tab[dec->output_img.pixel_format].ydec[pli]; if (mbctx->is_keyframe) { od_decode_haar_dc_sb(dec, mbctx, pli, sbx, sby, xdec, ydec, sby > 0 && sbx < nhsb - 1, &hgrad, &vgrad); @@ -1017,8 +1021,8 @@ static void od_decode_coefficients(od_dec_ctx *dec, od_mb_dec_ctx *mbctx) { } } for (pli = 0; pli < nplanes; pli++) { - xdec = dec->output_img.planes[pli].xdec; - ydec = dec->output_img.planes[pli].ydec; + xdec = od_plane_info_tab[dec->output_img.pixel_format].xdec[pli]; + ydec = od_plane_info_tab[dec->output_img.pixel_format].ydec[pli]; w = frame_width >> xdec; h = frame_height >> ydec; if (!mbctx->use_haar_wavelet) { @@ -1031,8 +1035,8 @@ static void od_decode_coefficients(od_dec_ctx *dec, od_mb_dec_ctx *mbctx) { for (pli = 0; pli < nplanes; pli++) { int i; int size; - xdec = dec->output_img.planes[pli].xdec; - ydec = dec->output_img.planes[pli].ydec; + xdec = od_plane_info_tab[dec->output_img.pixel_format].xdec[pli]; + ydec = od_plane_info_tab[dec->output_img.pixel_format].ydec[pli]; size = nvsb*nhsb*OD_BSIZE_MAX*OD_BSIZE_MAX >> xdec >> ydec; for (i = 0; i < size; i++) { state->etmp[pli][i] = state->ctmp[pli][i]; @@ -1067,8 +1071,8 @@ static void od_decode_coefficients(od_dec_ctx *dec, od_mb_dec_ctx *mbctx) { int ln; int n; int dir[OD_DERING_NBLOCKS][OD_DERING_NBLOCKS]; - xdec = dec->output_img.planes[pli].xdec; - ydec = dec->output_img.planes[pli].ydec; + xdec = od_plane_info_tab[dec->output_img.pixel_format].xdec[pli]; + ydec = od_plane_info_tab[dec->output_img.pixel_format].ydec[pli]; w = frame_width >> xdec; h = frame_height >> ydec; ln = OD_LOG_BSIZE_MAX - xdec; @@ -1109,8 +1113,8 @@ static void od_decode_coefficients(od_dec_ctx *dec, od_mb_dec_ctx *mbctx) { } } for (pli = 0; pli < nplanes; pli++) { - xdec = dec->output_img.planes[pli].xdec; - ydec = dec->output_img.planes[pli].ydec; + xdec = od_plane_info_tab[dec->output_img.pixel_format].xdec[pli]; + ydec = od_plane_info_tab[dec->output_img.pixel_format].ydec[pli]; w = frame_width >> xdec; h = frame_height >> ydec; if (dec->quantizer[0] > 0) diff --git a/src/encode.c b/src/encode.c index fea0a079..18d77bf5 100644 --- a/src/encode.c +++ b/src/encode.c @@ -237,8 +237,10 @@ static int od_enc_init(od_enc_ctx *enc, const daala_info *info) { frame_buf_width = enc->state.frame_width + (OD_BUFFER_PADDING << 1); frame_buf_height = enc->state.frame_height + (OD_BUFFER_PADDING << 1); for (pli = 0; pli < info->nplanes; pli++) { - plane_buf_width = frame_buf_width >> info->plane_info[pli].xdec; - plane_buf_height = frame_buf_height >> info->plane_info[pli].ydec; + plane_buf_width = frame_buf_width >> + od_plane_info_tab[info->pixel_format].xdec[pli]; + plane_buf_height = frame_buf_height >> + od_plane_info_tab[info->pixel_format].ydec[pli]; /*Reserve space for input plane buffer */ data_sz += plane_buf_width*plane_buf_height*reference_bytes; #if defined(OD_DUMP_IMAGES) @@ -260,21 +262,23 @@ static int od_enc_init(od_enc_ctx *enc, const daala_info *info) { /*Fill in the input img structure.*/ img = &enc->input_img; img->nplanes = info->nplanes; + img->pixel_format = info->pixel_format; img->width = enc->state.frame_width; img->height = enc->state.frame_height; + img->bitdepth = reference_bits; for (pli = 0; pli < img->nplanes; pli++) { - plane_buf_width = frame_buf_width >> info->plane_info[pli].xdec; - plane_buf_height = frame_buf_height >> info->plane_info[pli].ydec; + int xdec = od_plane_info_tab[info->pixel_format].xdec[pli]; + int ydec = od_plane_info_tab[info->pixel_format].ydec[pli]; iplane = img->planes + pli; - iplane->xdec = info->plane_info[pli].xdec; - iplane->ydec = info->plane_info[pli].ydec; - iplane->bitdepth = reference_bits; + plane_buf_width = frame_buf_width >> xdec; + plane_buf_height = frame_buf_height >> ydec; + /*Internal buffers are always planar.*/ iplane->xstride = reference_bytes; iplane->ystride = plane_buf_width*iplane->xstride; iplane->data = input_img_data - + iplane->xstride*(OD_BUFFER_PADDING >> info->plane_info[pli].xdec) - + iplane->ystride*(OD_BUFFER_PADDING >> info->plane_info[pli].ydec); + + iplane->xstride*(OD_BUFFER_PADDING >> xdec) + + iplane->ystride*(OD_BUFFER_PADDING >> ydec); input_img_data += plane_buf_height*iplane->ystride; } #if defined(OD_DUMP_IMAGES) @@ -289,16 +293,18 @@ static int od_enc_init(od_enc_ctx *enc, const daala_info *info) { /*Fill in the visualization image structure.*/ img = &enc->vis_img; img->nplanes = info->nplanes; + img->pixel_format = info->pixel_format; img->width = frame_buf_width << 1; img->height = frame_buf_height << 1; for (pli = 0; pli < img->nplanes; pli++) { + int xdec = od_plane_info_tab[info->pixel_format].xdec[pli]; + int ydec = od_plane_info_tab[info->pixel_format].ydec[pli]; iplane = img->planes + pli; - plane_buf_width = img->width >> info->plane_info[pli].xdec; - plane_buf_height = img->height >> info->plane_info[pli].ydec; + plane_buf_width = img->width >> xdec; + plane_buf_height = img->height >> ydec; iplane->data = input_img_data; input_img_data += plane_buf_width*plane_buf_height; - iplane->xdec = info->plane_info[pli].xdec; - iplane->ydec = info->plane_info[pli].ydec; + iplane->bitdepth = 8; iplane->xstride = 1; iplane->ystride = plane_buf_width; @@ -306,16 +312,17 @@ static int od_enc_init(od_enc_ctx *enc, const daala_info *info) { /*Fill in the temporary image structure.*/ img = &enc->tmp_vis_img; img->nplanes = info->nplanes; + img->pixel_format = info->pixel_format; img->width = frame_buf_width << 1; img->height = frame_buf_height << 1; for (pli = 0; pli < img->nplanes; pli++) { + int xdec = od_plane_info_tab[info->pixel_format].xdec[pli]; + int ydec = od_plane_info_tab[info->pixel_format].ydec[pli]; iplane = img->planes + pli; - plane_buf_width = img->width >> info->plane_info[pli].xdec; - plane_buf_height = img->height >> info->plane_info[pli].ydec; + plane_buf_width = img->width >> xdec; + plane_buf_height = img->height >> ydec; iplane->data = input_img_data; input_img_data += plane_buf_width*plane_buf_height; - iplane->xdec = info->plane_info[pli].xdec; - iplane->ydec = info->plane_info[pli].ydec; iplane->bitdepth = 8; iplane->xstride = 1; iplane->ystride = plane_buf_width; @@ -521,7 +528,7 @@ void od_encode_rollback(daala_enc_ctx *enc, const od_rollback_buffer *rbuf) { } static void od_img_plane_copy_pad8(od_img_plane *dst_p, - int plane_width, int plane_height, od_img_plane *src_p, + int plane_width, int plane_height, int bitdepth, od_img_plane *src_p, int pic_width, int pic_height) { unsigned char *dst_data; ptrdiff_t dstride; @@ -553,7 +560,7 @@ static void od_img_plane_copy_pad8(od_img_plane *dst_p, OD_COPY(dst, src_data, pic_width); } else { - if (src_p->bitdepth <= 8) { + if (bitdepth <= 8) { /*1 byte per pixel*/ for (x = 0; x < pic_width; x++) { dst[x] = *(src_data + sxstride*x); @@ -567,7 +574,7 @@ static void od_img_plane_copy_pad8(od_img_plane *dst_p, accept the high-depth input and truncate it. */ for (x = 0; x < pic_width; x++) { dst[x] = *(src_data + sxstride*x) + - (*(src_data + sxstride*x + 1) << 8) >> src_p->bitdepth - 8; + (*(src_data + sxstride*x + 1) << 8) >> bitdepth - 8; } } } @@ -624,7 +631,7 @@ static void od_encode_compute_pred(daala_enc_ctx *enc, od_mb_enc_ctx *ctx, int x; OD_ASSERT(bs >= 0 && bs < OD_NBSIZES); n = 1 << bs + OD_LOG_BSIZE0; - xdec = enc->input_img.planes[pli].xdec; + xdec = od_plane_info_tab[enc->input_img.pixel_format].xdec[pli]; w = enc->state.frame_width >> xdec; bo = (by << OD_LOG_BSIZE0)*w + (bx << OD_LOG_BSIZE0); /*We never use tf on the chroma planes, but if we do it will blow up, which @@ -998,7 +1005,7 @@ static int od_block_encode(daala_enc_ctx *enc, od_mb_enc_ctx *ctx, int bs, n = 1 << (bs + 2); bx <<= bs; by <<= bs; - xdec = enc->input_img.planes[pli].xdec; + xdec = od_plane_info_tab[enc->input_img.pixel_format].xdec[pli]; frame_width = enc->state.frame_width; use_masking = enc->use_activity_masking; w = frame_width >> xdec; @@ -1619,16 +1626,14 @@ static void od_img_copy_pad(daala_enc_ctx *enc, od_img *img) { od_img_plane plane; int plane_width; int plane_height; - int xdec; - int ydec; + int xdec = od_plane_info_tab[img->pixel_format].xdec[pli]; + int ydec = od_plane_info_tab[img->pixel_format].ydec[pli]; *&plane = *(img->planes + pli); - xdec = plane.xdec; - ydec = plane.ydec; plane_width = ((state->info.pic_width + (1 << xdec) - 1) >> xdec); plane_height = ((state->info.pic_height + (1 << ydec) - 1) >> ydec); od_img_plane_copy_pad8(enc->input_img.planes+pli, state->frame_width >> xdec, state->frame_height >> ydec, - &plane, plane_width, plane_height); + enc->input_img.bitdepth, &plane, plane_width, plane_height); } od_img_edge_ext(&enc->input_img); } @@ -1969,8 +1974,8 @@ void od_encode_fill_vis(od_enc_ctx *enc) { image.*/ ref_img = &enc->tmp_vis_img; od_img_upsample8(enc, ref_img, &enc->input_img); - xdec = state->info.plane_info[0].xdec; - ydec = state->info.plane_info[0].ydec; + xdec = od_plane_info_tab[state->info.pixel_format].xdec[0]; + ydec = od_plane_info_tab[state->info.pixel_format].ydec[0]; for (y = 0; y < ref_img->height; y++) { for (x = 0; x < ref_img->width; x++) { int diff; @@ -2042,8 +2047,8 @@ static void od_img_dump_padded(daala_enc_ctx *enc) { /*Modify the image offsets to include the padding.*/ *&img = enc->input_img; for (pli = 0; pli < nplanes; pli++) { - img.planes[pli].data -= (OD_BUFFER_PADDING>>info->plane_info[pli].xdec) - +img.planes[pli].ystride*(OD_BUFFER_PADDING>>info->plane_info[pli].ydec); + img.planes[pli].data -= (OD_BUFFER_PADDING >> od_plane_info_tab[info->pixel_format].xdec[pli]) + +img.planes[pli].ystride*(OD_BUFFER_PADDING >> od_plane_info_tab[info->pixel_format].xdec[pli]); } img.width += OD_BUFFER_PADDING<<1; img.height += OD_BUFFER_PADDING<<1; @@ -2260,8 +2265,8 @@ static void od_encode_coefficients(daala_enc_ctx *enc, od_mb_enc_ctx *mbctx, od_ec_enc_uint(&enc->ec, enc->coded_quantizer[pli], OD_N_CODED_QUANTIZERS); } for (pli = 0; pli < nplanes; pli++) { - xdec = enc->input_img.planes[pli].xdec; - ydec = enc->input_img.planes[pli].ydec; + xdec = od_plane_info_tab[enc->input_img.pixel_format].xdec[pli]; + ydec = od_plane_info_tab[enc->input_img.pixel_format].ydec[pli]; w = frame_width >> xdec; h = frame_height >> ydec; /*Collect the image data needed for this plane.*/ @@ -2312,8 +2317,8 @@ static void od_encode_coefficients(daala_enc_ctx *enc, od_mb_enc_ctx *mbctx, mbctx->mc = state->mctmp[pli]; mbctx->md = state->mdtmp[pli]; mbctx->l = state->lbuf[pli]; - xdec = enc->input_img.planes[pli].xdec; - ydec = enc->input_img.planes[pli].ydec; + xdec = od_plane_info_tab[enc->input_img.pixel_format].xdec[pli]; + ydec = od_plane_info_tab[enc->input_img.pixel_format].ydec[pli]; if (pli == 0 || rdo_only && mbctx->is_keyframe) { for (i = 0; i < OD_BSIZE_MAX; i++) { for (j = 0; j < OD_BSIZE_MAX; j++) { @@ -2379,8 +2384,8 @@ static void od_encode_coefficients(daala_enc_ctx *enc, od_mb_enc_ctx *mbctx, } #endif for (pli = 0; pli < nplanes; pli++) { - xdec = enc->input_img.planes[pli].xdec; - ydec = enc->input_img.planes[pli].ydec; + xdec = od_plane_info_tab[enc->input_img.pixel_format].xdec[pli]; + ydec = od_plane_info_tab[enc->input_img.pixel_format].ydec[pli]; w = frame_width >> xdec; h = frame_height >> ydec; if (!mbctx->use_haar_wavelet) { @@ -2395,8 +2400,8 @@ static void od_encode_coefficients(daala_enc_ctx *enc, od_mb_enc_ctx *mbctx, for (pli = 0; pli < nplanes; pli++) { int i; int size; - xdec = enc->input_img.planes[pli].xdec; - ydec = enc->input_img.planes[pli].ydec; + xdec = od_plane_info_tab[enc->input_img.pixel_format].xdec[pli]; + ydec = od_plane_info_tab[enc->input_img.pixel_format].ydec[pli]; size = nvsb*nhsb*OD_BSIZE_MAX*OD_BSIZE_MAX >> xdec >> ydec; for (i = 0; i < size; i++) { state->etmp[pli][i] = state->ctmp[pli][i]; @@ -2425,8 +2430,8 @@ static void od_encode_coefficients(daala_enc_ctx *enc, od_mb_enc_ctx *mbctx, continue; } pli = 0; - xdec = enc->input_img.planes[pli].xdec; - ydec = enc->input_img.planes[pli].ydec; + xdec = od_plane_info_tab[enc->input_img.pixel_format].xdec[pli]; + ydec = od_plane_info_tab[enc->input_img.pixel_format].ydec[pli]; w = frame_width >> xdec; OD_ASSERT(xdec == ydec); ln = OD_LOG_BSIZE_MAX - xdec; @@ -2502,8 +2507,8 @@ static void od_encode_coefficients(daala_enc_ctx *enc, od_mb_enc_ctx *mbctx, } } for (pli = 1; pli < nplanes; pli++) { - xdec = enc->input_img.planes[pli].xdec; - ydec = enc->input_img.planes[pli].ydec; + xdec = od_plane_info_tab[enc->input_img.pixel_format].xdec[pli]; + ydec = od_plane_info_tab[enc->input_img.pixel_format].ydec[pli]; w = frame_width >> xdec; ln = OD_LOG_BSIZE_MAX - xdec; n = 1 << ln; @@ -2525,8 +2530,8 @@ static void od_encode_coefficients(daala_enc_ctx *enc, od_mb_enc_ctx *mbctx, } } for (pli = 0; pli < nplanes; pli++) { - xdec = enc->input_img.planes[pli].xdec; - ydec = enc->input_img.planes[pli].ydec; + xdec = od_plane_info_tab[enc->input_img.pixel_format].xdec[pli]; + ydec = od_plane_info_tab[enc->input_img.pixel_format].ydec[pli]; w = frame_width >> xdec; h = frame_height >> ydec; if (!rdo_only && enc->quantizer[0] > 0) { @@ -2687,12 +2692,8 @@ int daala_encode_img_in(daala_enc_ctx *enc, od_img *img, int duration) { declared video size.*/ nplanes = enc->state.info.nplanes; if (img->nplanes != nplanes) return OD_EINVAL; - for (pli = 0; pli < nplanes; pli++) { - if (img->planes[pli].xdec != enc->state.info.plane_info[pli].xdec - || img->planes[pli].ydec != enc->state.info.plane_info[pli].ydec) { - return OD_EINVAL; - } - } + if (img->pixel_format != enc->state.info.pixel_format) return OD_EINVAL; + use_masking = enc->use_activity_masking; frame_width = enc->state.frame_width; frame_height = enc->state.frame_height; diff --git a/src/infodec.c b/src/infodec.c index b5091d2d..f9612501 100644 --- a/src/infodec.c +++ b/src/infodec.c @@ -133,7 +133,6 @@ int daala_decode_header_in(daala_info *info, /*Codec info header.*/ case 0x80: { - int pli; uint32_t tmp; int tmpi; /*This should be the first packet, and we should not have already read @@ -184,13 +183,9 @@ int daala_decode_header_in(daala_info *info, if ((info->nplanes < 1) || (info->nplanes > OD_NPLANES_MAX)) { return OD_EBADHEADER; } - for (pli = 0; pli < info->nplanes; pli++) { - tmpi = oggbyte_read1(&obb); - if (tmpi < 0) return OD_EBADHEADER; - info->plane_info[pli].xdec = !!tmpi; - tmpi = oggbyte_read1(&obb); - if (tmpi < 0) return OD_EBADHEADER; - info->plane_info[pli].ydec = !!tmpi; + info->pixel_format = oggbyte_read1(&obb); + if ((info->pixel_format == 0) || (info->pixel_format > OD_NPLANES_MAX)) { + return OD_EBADHEADER; } return 2; } diff --git a/src/infoenc.c b/src/infoenc.c index 432c82d5..ed2baf73 100644 --- a/src/infoenc.c +++ b/src/infoenc.c @@ -36,7 +36,6 @@ int daala_encode_flush_header(daala_enc_ctx *_enc, daala_comment *_dc, switch (_enc->packet_state) { case OD_PACKET_INFO_HDR: { - int pli; oggbyte_reset(&_enc->obb); oggbyte_write1(&_enc->obb, 0x80); oggbyte_writecopy(&_enc->obb, "daala", 5); @@ -59,10 +58,7 @@ int daala_encode_flush_header(daala_enc_ctx *_enc, daala_comment *_dc, oggbyte_write1(&_enc->obb, info->bitdepth_mode); OD_ASSERT((info->nplanes >= 1) && (info->nplanes <= OD_NPLANES_MAX)); oggbyte_write1(&_enc->obb, info->nplanes); - for (pli = 0; pli < info->nplanes; ++pli) { - oggbyte_write1(&_enc->obb, info->plane_info[pli].xdec); - oggbyte_write1(&_enc->obb, info->plane_info[pli].ydec); - } + oggbyte_write1(&_enc->obb, info->pixel_format); _op->b_o_s = 1; } break; diff --git a/src/internal.c b/src/internal.c index 5f7d248d..3ca176d5 100644 --- a/src/internal.c +++ b/src/internal.c @@ -388,6 +388,15 @@ uint32_t OD_DIVU_SMALL_CONSTS[OD_DIVU_DMAX][2] = { {0xFFFFFFFF,0xFFFFFFFF} }; +const daala_plane_info od_plane_info_tab[OD_PIX_NB] = { + {{ 0, 0, 0 }, { 0, 0, 0 }}, /* n/a */ + {{ 0, 0, 0 }, { 0, 0, 0 }}, /* OD_PIX_YUV444 */ + {{ 0, 1, 0 }, { 0, 1, 0 }}, /* OD_PIX_YUV422 */ + {{ 0, 2, 0 }, { 0, 2, 0 }}, /* OD_PIX_YUV411 */ + {{ 0, 1, 1 }, { 0, 1, 1 }}, /* OD_PIX_YUV420 */ + {{ 0, 0, 0 }, { 0, 0, 0 }}, /* OD_PIX_YUV400 */ +}; + #if defined(OD_ENABLE_ASSERTIONS) # include diff --git a/src/internal.h b/src/internal.h index a6479952..78974a10 100644 --- a/src/internal.h +++ b/src/internal.h @@ -205,6 +205,8 @@ void od_free_2d(void *_ptr); extern uint32_t OD_DIVU_SMALL_CONSTS[OD_DIVU_DMAX][2]; +extern const daala_plane_info od_plane_info_tab[OD_PIX_NB]; + /*Translate unsigned division by small divisors into multiplications.*/ # define OD_DIVU_SMALL(_x, _d) \ ((uint32_t)((OD_DIVU_SMALL_CONSTS[(_d)-1][0]* \ diff --git a/src/mcenc.c b/src/mcenc.c index 703a9a0a..f59c11f0 100644 --- a/src/mcenc.c +++ b/src/mcenc.c @@ -1577,13 +1577,15 @@ static int32_t od_enc_sad(od_enc_ctx *enc, const unsigned char *p, int cliph; int w; int h; + int xdec = od_plane_info_tab[enc->input_img.pixel_format].xdec[pli]; + int ydec = od_plane_info_tab[enc->input_img.pixel_format].ydec[pli]; state = &enc->state; iplane = enc->input_img.planes + pli; /*Compute the block dimensions in the target image plane.*/ - x >>= iplane->xdec; - y >>= iplane->ydec; - w = 1 << (log_blk_sz - iplane->xdec); - h = 1 << (log_blk_sz - iplane->ydec); + x >>= xdec; + y >>= ydec; + w = 1 << (log_blk_sz - xdec); + h = 1 << (log_blk_sz - ydec); /*Clip the block against the active picture region.*/ clipx = -x; if (clipx > 0) { @@ -1597,10 +1599,10 @@ static int32_t od_enc_sad(od_enc_ctx *enc, const unsigned char *p, p += clipy*pystride; y += clipy; } - clipw = ((state->info.pic_width + (1 << iplane->xdec) - 1) >> iplane->xdec) + clipw = ((state->info.pic_width + (1 << xdec) - 1) >> xdec) - x; w = OD_MINI(w, clipw); - cliph = ((state->info.pic_height + (1 << iplane->ydec) - 1) >> iplane->ydec) + cliph = ((state->info.pic_height + (1 << ydec) - 1) >> ydec) - y; h = OD_MINI(h, cliph); /*OD_LOG((OD_LOG_MOTION_ESTIMATION, OD_LOG_DEBUG, @@ -1642,13 +1644,15 @@ static int32_t od_enc_satd(od_enc_ctx *enc, const unsigned char *p, int cliph; int w; int h; + int xdec = od_plane_info_tab[enc->input_img.pixel_format].xdec[pli]; + int ydec = od_plane_info_tab[enc->input_img.pixel_format].ydec[pli]; state = &enc->state; iplane = enc->input_img.planes + pli; /*Compute the block dimensions in the target image plane.*/ - x >>= iplane->xdec; - y >>= iplane->ydec; - w = 1 << (log_blk_sz - iplane->xdec); - h = 1 << (log_blk_sz - iplane->ydec); + x >>= xdec; + y >>= ydec; + w = 1 << (log_blk_sz - xdec); + h = 1 << (log_blk_sz - ydec); /*Clip the block against the active picture region.*/ clipx = -x; if (clipx > 0) { @@ -1662,10 +1666,10 @@ static int32_t od_enc_satd(od_enc_ctx *enc, const unsigned char *p, p += clipy*pystride; y += clipy; } - clipw = ((state->info.pic_width + (1 << iplane->xdec) - 1) >> iplane->xdec) + clipw = ((state->info.pic_width + (1 << xdec) - 1) >> xdec) - x; w = OD_MINI(w, clipw); - cliph = ((state->info.pic_height + (1 << iplane->ydec) - 1) >> iplane->ydec) + cliph = ((state->info.pic_height + (1 << ydec) - 1) >> ydec) - y; h = OD_MINI(h, cliph); /*OD_LOG((OD_LOG_MOTION_ESTIMATION, OD_LOG_DEBUG, @@ -2174,11 +2178,16 @@ static int32_t od_mv_est_bma_sad(od_mv_est_ctx *est, int refi; int dx; int dy; + int xdec; + int ydec; + enc = est->enc; state = &enc->state; refi = state->ref_imgi[ref]; + xdec = od_plane_info_tab[state->ref_imgs[refi].pixel_format].xdec[0]; + ydec = od_plane_info_tab[state->ref_imgs[refi].pixel_format].ydec[0]; iplane = state->ref_imgs[refi].planes + 0; - OD_ASSERT(iplane->xdec == 0 && iplane->ydec == 0); + OD_ASSERT(xdec == 0 && ydec == 0); dx = bx + mvx; dy = by + mvy; ret = od_enc_sad(est->enc, @@ -2189,25 +2198,27 @@ static int32_t od_mv_est_bma_sad(od_mv_est_ctx *est, int pli; unsigned char *ref_img; for (pli = 1; pli < enc->input_img.nplanes; pli++) { + xdec = od_plane_info_tab[state->ref_imgs[refi].pixel_format].xdec[pli]; + ydec = od_plane_info_tab[state->ref_imgs[refi].pixel_format].ydec[pli]; iplane = state->ref_imgs[refi].planes + pli; - OD_ASSERT(((bx + (1 << iplane->xdec) - 1) & ~((1 << iplane->xdec) - 1)) + OD_ASSERT(((bx + (1 << iplane->xdec) - 1) & ~((1 << xdec) - 1)) == bx); - OD_ASSERT(((by + (1 << iplane->ydec) - 1) & ~((1 << iplane->ydec) - 1)) + OD_ASSERT(((by + (1 << iplane->ydec) - 1) & ~((1 << ydec) - 1)) == by); /*If the input chroma plane is sub-sampled, then the candidate block with subpel position for BMA search is interpolated at block level.*/ ref_img = iplane->data - + (by >> iplane->ydec)*iplane->ystride - + (bx >> iplane->xdec)*iplane->xstride; + + (by >> ydec)*iplane->ystride + + (bx >> xdec)*iplane->xstride; (*state->opt_vtbl.mc_predict1fmv) (state, state->mc_buf[4], ref_img, iplane->ystride, - mvx << (3 - iplane->xdec), mvy << (3 - iplane->ydec), - log_mvb_sz + OD_LOG_MVBSIZE_MIN - iplane->xdec, - log_mvb_sz + OD_LOG_MVBSIZE_MIN - iplane->ydec); + mvx << (3 - xdec), mvy << (3 - ydec), + log_mvb_sz + OD_LOG_MVBSIZE_MIN - xdec, + log_mvb_sz + OD_LOG_MVBSIZE_MIN - ydec); /*Then, calculate SAD between a target block and the subpel interpolated MC block.*/ ret += od_enc_sad(est->enc, state->mc_buf[4], - iplane->xstride << (log_mvb_sz + OD_LOG_MVBSIZE_MIN - iplane->xdec), + iplane->xstride << (log_mvb_sz + OD_LOG_MVBSIZE_MIN - xdec), iplane->xstride, pli, bx, by, log_mvb_sz + OD_LOG_MVBSIZE_MIN) >> OD_MC_CHROMA_SCALE; } @@ -6083,10 +6094,15 @@ void od_mv_est(od_mv_est_ctx *est, int lambda) { int pli; int i; int j; + int xdec; + int ydec; use_satd = est->enc->use_satd; state = &est->enc->state; nhmvbs = state->nhmvbs; nvmvbs = state->nvmvbs; + xdec = od_plane_info_tab[est->enc->input_img.pixel_format].xdec[0]; + ydec = od_plane_info_tab[est->enc->input_img.pixel_format].ydec[0]; + iplane = est->enc->input_img.planes + 0; /*Sanitize user parameters*/ est->level_min = OD_MINI(est->enc->params.mv_level_min, @@ -6104,22 +6120,23 @@ void od_mv_est(od_mv_est_ctx *est, int lambda) { } /*If the luma plane is decimated for some reason, then our distortions will be smaller, so scale lambda appropriately.*/ - est->lambda = lambda >> (iplane->xdec + iplane->ydec); + est->lambda = lambda >> (xdec + ydec); /*Compute termination thresholds for EPZS^2.*/ for (log_mvb_sz = 0; log_mvb_sz < OD_NMVBSIZES; log_mvb_sz++) { est->thresh1[log_mvb_sz] = - 1 << 2*(log_mvb_sz + OD_LOG_MVBSIZE_MIN) >> (iplane->xdec + iplane->ydec); + 1 << 2*(log_mvb_sz + OD_LOG_MVBSIZE_MIN) >> (xdec + ydec); } /*If we're using the chroma planes, then our distortions will be larger. Compensate by increasing lambda and the termination thresholds.*/ if (est->flags & OD_MC_USE_CHROMA) { for (pli = 1; pli < est->enc->input_img.nplanes; pli++) { - iplane = est->enc->input_img.planes + pli; + xdec = od_plane_info_tab[est->enc->input_img.pixel_format].xdec[pli]; + ydec = od_plane_info_tab[est->enc->input_img.pixel_format].ydec[pli]; est->lambda += - lambda >> (iplane->xdec + iplane->ydec + OD_MC_CHROMA_SCALE); + lambda >> (xdec + ydec + OD_MC_CHROMA_SCALE); for (log_mvb_sz = 0; log_mvb_sz < OD_NMVBSIZES; log_mvb_sz++) { est->thresh1[log_mvb_sz] += 1 << 2*(log_mvb_sz + OD_LOG_MVBSIZE_MIN) >> - (iplane->xdec + iplane->ydec + OD_MC_CHROMA_SCALE); + (xdec + ydec + OD_MC_CHROMA_SCALE); } } } diff --git a/src/state.c b/src/state.c index f72368de..b13a9203 100644 --- a/src/state.c +++ b/src/state.c @@ -94,12 +94,13 @@ void od_img_copy(od_img* dest, od_img* src) { OD_ASSERT(dest->width == src->width); OD_ASSERT(dest->height == src->height); OD_ASSERT(dest->nplanes == src->nplanes); + OD_ASSERT(dest->pixel_format == src->pixel_format); for (pli = 0; pli < src->nplanes; pli++) { int width; int height; int row; - width = dest->width >> dest->planes[pli].xdec; - height = dest->height >> dest->planes[pli].ydec; + width = dest->width >> od_plane_info_tab[dest->pixel_format].xdec[pli]; + height = dest->height >> od_plane_info_tab[dest->pixel_format].ydec[pli]; for (row = 0; row < height; row++) { memcpy(dest->planes[pli].data + dest->planes[pli].ystride*row, src->planes[pli].data + src->planes[pli].ystride*row, width); @@ -139,8 +140,10 @@ static int od_state_ref_imgs_init(od_state *state, int nrefs) { frame_buf_height = state->frame_height + (OD_BUFFER_PADDING << 1); for (pli = 0; pli < info->nplanes; pli++) { /*Reserve space for this plane in nrefs reference images.*/ - plane_buf_width = frame_buf_width >> info->plane_info[pli].xdec; - plane_buf_height = frame_buf_height >> info->plane_info[pli].ydec; + plane_buf_width = frame_buf_width >> + od_plane_info_tab[info->pixel_format].xdec[pli]; + plane_buf_height = frame_buf_height >> + od_plane_info_tab[info->pixel_format].ydec[pli]; data_sz += plane_buf_width*plane_buf_height*reference_bytes*nrefs; } state->ref_img_data = ref_img_data = @@ -154,18 +157,18 @@ static int od_state_ref_imgs_init(od_state *state, int nrefs) { img->nplanes = info->nplanes; img->width = state->frame_width; img->height = state->frame_height; + img->bitdepth = reference_bits; for (pli = 0; pli < img->nplanes; pli++) { + int xdec = od_plane_info_tab[info->pixel_format].xdec[pli]; + int ydec = od_plane_info_tab[info->pixel_format].ydec[pli]; iplane = img->planes + pli; - iplane->xdec = info->plane_info[pli].xdec; - iplane->ydec = info->plane_info[pli].ydec; - plane_buf_width = frame_buf_width >> iplane->xdec; - plane_buf_height = frame_buf_height >> iplane->ydec; - iplane->bitdepth = reference_bits; + plane_buf_width = frame_buf_width >> xdec; + plane_buf_height = frame_buf_height >> ydec; iplane->xstride = reference_bytes; iplane->ystride = plane_buf_width*reference_bytes; iplane->data = ref_img_data - + (OD_BUFFER_PADDING >> iplane->xdec)*iplane->xstride - + (OD_BUFFER_PADDING >> iplane->ydec)*iplane->ystride; + + (OD_BUFFER_PADDING >> xdec)*iplane->xstride + + (OD_BUFFER_PADDING >> ydec)*iplane->ystride; ref_img_data += plane_buf_height*iplane->ystride; } } @@ -231,8 +234,6 @@ static int od_state_init_impl(od_state *state, const daala_info *info) { if (info == NULL) return OD_EFAULT; nplanes = info->nplanes; if (nplanes <= 0 || nplanes > OD_NPLANES_MAX) return OD_EINVAL; - /*The first plane (the luma plane) must not be subsampled.*/ - if (info->plane_info[0].xdec || info->plane_info[0].ydec) return OD_EINVAL; /*The bitdepth is restricted to a few allowed values.*/ if (info->bitdepth_mode < OD_BITDEPTH_MODE_8 || info->bitdepth_mode > OD_BITDEPTH_MODE_12) { @@ -261,8 +262,8 @@ static int od_state_init_impl(od_state *state, const daala_info *info) { state->nhsb = state->frame_width >> OD_LOG_BSIZE_MAX; state->nvsb = state->frame_height >> OD_LOG_BSIZE_MAX; for (pli = 0; pli < nplanes; pli++) { - int xdec; - int ydec; + int xdec = od_plane_info_tab[info->pixel_format].xdec[pli]; + int ydec = od_plane_info_tab[info->pixel_format].ydec[pli]; int w; int h; state->sb_dc_mem[pli] = (od_coeff*)malloc( @@ -270,8 +271,6 @@ static int od_state_init_impl(od_state *state, const daala_info *info) { if (OD_UNLIKELY(!state->sb_dc_mem[pli])) { return OD_EFAULT; } - xdec = info->plane_info[pli].xdec; - ydec = info->plane_info[pli].ydec; w = state->frame_width >> xdec; h = state->frame_height >> ydec; state->ctmp[pli] = (od_coeff *)malloc(w*h*sizeof(*state->ctmp[pli])); @@ -300,8 +299,8 @@ static int od_state_init_impl(od_state *state, const daala_info *info) { if (pli > 0) { int plj; for (plj = 1; plj < pli; plj++) { - if (xdec == info->plane_info[plj].xdec - && ydec == info->plane_info[plj].ydec) { + if (xdec == od_plane_info_tab[info->pixel_format].xdec[plj] + && ydec == od_plane_info_tab[info->pixel_format].ydec[plj]) { state->ltmp[pli] = NULL; state->lbuf[pli] = state->ltmp[plj]; } @@ -577,25 +576,26 @@ void od_state_pred_block_from_setup(od_state *state, int k; int xdec; int ydec; + int fmt = state->ref_imgs[state->ref_imgi[OD_FRAME_PREV]].pixel_format; /* Assumes that xdec and ydec are the same on all references. */ - xdec = state->ref_imgs[state->ref_imgi[OD_FRAME_PREV]].planes[pli].xdec; - ydec = state->ref_imgs[state->ref_imgi[OD_FRAME_PREV]].planes[pli].ydec; dxp = OD_VERT_SETUP_DX[oc][s]; dyp = OD_VERT_SETUP_DY[oc][s]; for (k = 0; k < 4; k++) { + xdec = od_plane_info_tab[fmt].xdec[k]; + ydec = od_plane_info_tab[fmt].ydec[k]; grid[k] = state->mv_grid[vy + (dyp[k] << log_mvb_sz)] + vx + (dxp[k] << log_mvb_sz); mvx[k] = (int32_t)OD_DIV_POW2_RE(grid[k]->mv[0], xdec); mvy[k] = (int32_t)OD_DIV_POW2_RE(grid[k]->mv[1], ydec); iplane = state->ref_imgs[state->ref_imgi[grid[k]->ref]].planes+pli; - x = vx << (OD_LOG_MVBSIZE_MIN - iplane->xdec); - y = vy << (OD_LOG_MVBSIZE_MIN - iplane->ydec); + x = vx << (OD_LOG_MVBSIZE_MIN - xdec); + y = vy << (OD_LOG_MVBSIZE_MIN - ydec); src[k] = iplane->data + y*iplane->ystride + x*iplane->xstride; } od_mc_predict(state, buf, ystride, src, iplane->ystride, mvx, mvy, oc, s, - log_mvb_sz + OD_LOG_MVBSIZE_MIN - iplane->xdec, - log_mvb_sz + OD_LOG_MVBSIZE_MIN - iplane->ydec); + log_mvb_sz + OD_LOG_MVBSIZE_MIN - xdec, + log_mvb_sz + OD_LOG_MVBSIZE_MIN - ydec); } void od_state_pred_block(od_state *state, @@ -605,12 +605,13 @@ void od_state_pred_block(od_state *state, half_mvb_sz = 1 << log_mvb_sz >> 1; if (log_mvb_sz > 0 && state->mv_grid[vy + half_mvb_sz][vx + half_mvb_sz].valid) { - od_img_plane *iplane; int half_xblk_sz; int half_yblk_sz; - iplane = state->ref_imgs[state->ref_imgi[OD_FRAME_PREV]].planes + pli; - half_xblk_sz = 1 << (log_mvb_sz + OD_LOG_MVBSIZE_MIN - 1 - iplane->xdec); - half_yblk_sz = 1 << (log_mvb_sz + OD_LOG_MVBSIZE_MIN - 1 - iplane->ydec); + int fmt = state->ref_imgs[state->ref_imgi[OD_FRAME_PREV]].pixel_format; + half_xblk_sz = 1 << (log_mvb_sz + OD_LOG_MVBSIZE_MIN - 1 - + od_plane_info_tab[fmt].xdec[pli]); + half_yblk_sz = 1 << (log_mvb_sz + OD_LOG_MVBSIZE_MIN - 1 - + od_plane_info_tab[fmt].ydec[pli]); od_state_pred_block(state, buf, ystride, xstride, pli, vx, vy, log_mvb_sz - 1); od_state_pred_block(state, buf + half_xblk_sz*xstride, @@ -702,7 +703,8 @@ int od_state_dump_yuv(od_state *state, od_img *img, const char *tag) { fps_num = state->info.timebase_numerator; fps_denom = state->info.timebase_denominator*state->info.frame_duration; chroma = img->nplanes == 1 ? " Cmono" : - CHROMA_TAGS[(img->planes[1].xdec == 0) + (img->planes[1].ydec == 0)*2]; + CHROMA_TAGS[(od_plane_info_tab[state->info.pixel_format].xdec[1] == 0) + + (od_plane_info_tab[state->info.pixel_format].ydec[1] == 0)*2]; fprintf(fp, "YUV4MPEG2 W%i H%i F%i:%i Ip A%i:%i%s\n", pic_width, pic_height, fps_num, fps_denom, state->info.pixel_aspect_numerator, state->info.pixel_aspect_denominator, @@ -710,12 +712,10 @@ int od_state_dump_yuv(od_state *state, od_img *img, const char *tag) { } fprintf(fp, "FRAME\n"); for (pli = 0; pli < OD_MINI(img->nplanes, 3); pli++) { - int xdec; - int ydec; + int xdec = od_plane_info_tab[state->info.pixel_format].xdec[pli]; + int ydec = od_plane_info_tab[state->info.pixel_format].ydec[pli]; int xstride; int ystride; - xdec = img->planes[pli].xdec; - ydec = img->planes[pli].ydec; xstride = img->planes[pli].xstride; ystride = img->planes[pli].ystride; for (y = 0; y < (pic_height + ydec) >> ydec; y++) { @@ -858,8 +858,10 @@ void od_state_mc_predict(od_state *state, od_img *img_dst) { int xstride; int ystride; iplane_dst = img_dst->planes + pli; - blk_x = vx << OD_LOG_MVBSIZE_MIN >> iplane_dst->xdec; - blk_y = vy << OD_LOG_MVBSIZE_MIN >> iplane_dst->ydec; + blk_x = vx << OD_LOG_MVBSIZE_MIN >> + od_plane_info_tab[img_dst->pixel_format].xdec[pli]; + blk_y = vy << OD_LOG_MVBSIZE_MIN >> + od_plane_info_tab[img_dst->pixel_format].ydec[pli]; xstride = iplane_dst->xstride; ystride = iplane_dst->ystride; od_state_pred_block(state, @@ -992,10 +994,8 @@ static void od_img_plane_edge_ext(od_img_plane *dst_p, void od_img_edge_ext(od_img* src) { int pli; for (pli = 0; pli < src->nplanes; pli++) { - int xdec; - int ydec; - xdec = (src->planes + pli)->xdec; - ydec = (src->planes + pli)->ydec; + int xdec = od_plane_info_tab[src->pixel_format].xdec[pli]; + int ydec = od_plane_info_tab[src->pixel_format].ydec[pli]; od_img_plane_edge_ext(&src->planes[pli], src->width >> xdec, src->height >> ydec, OD_BUFFER_PADDING >> xdec, OD_BUFFER_PADDING >> ydec);