int jxr_get_TILE_WIDTH(jxr_image_t image, unsigned column) { if (column > image->tile_columns) { return 0; } else if (column == image->tile_columns) { if (column == 0) return EXTENDED_WIDTH_BLOCKS(image); else return EXTENDED_WIDTH_BLOCKS(image) - image->tile_column_position[column-1]; } else { return image->tile_column_width[column]; } }
static void recover_dclp_strip(jxr_image_t image, int tx, int ty, int my) { int mx; int use_my = my + image->tile_row_position[ty]; int use_mx = image->tile_column_position[tx]; int ptr = use_my*EXTENDED_WIDTH_BLOCKS(image) + use_mx; int format_scale = 15; if (image->use_clr_fmt == 2 /* YUV422 */) { format_scale = 7; } else if (image->use_clr_fmt == 1 /* YUV420 */) { format_scale = 3; } int ch; for (ch = 0 ; ch < image->num_channels ; ch += 1) { struct macroblock_s*mb = image->mb_row_buffer[ch] + ptr; int count = ch==0? 15 : format_scale; for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) { MACROBLK_CUR_DC(image,ch,tx,mx) = mb[mx].data[0]; DEBUG(" recover_dclp_strip: tx=%d, ty=%d, mx=%d, my=%d, ch=%d, DC=0x%0x8, LP=\n", tx, ty, mx, my, ch, mb[mx].data[0]); int idx; for (idx = 0 ; idx < count ; idx += 1) { MACROBLK_CUR_LP(image,ch,tx,mx,idx) = mb[mx].data[idx+1]; DEBUG(" 0x%x", mb[mx].data[idx+1]); } DEBUG("\n"); MACROBLK_CUR_LP_QUANT(image,ch,tx,mx) = mb[mx].lp_quant; } } }
int _jxr_r_TILE_DC(jxr_image_t image, struct rbitstream*str, unsigned tx, unsigned ty) { unsigned mx, my; unsigned mb_height; unsigned mb_width; unsigned char s0, s1, s2, s3; DEBUG("START TILE_DC at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_rbitstream_bitpos(str)); /* TILE_STARTCODE == 1 */ s0 = _jxr_rbitstream_uint8(str); /* 0x00 */ s1 = _jxr_rbitstream_uint8(str); /* 0x00 */ s2 = _jxr_rbitstream_uint8(str); /* 0x01 */ s3 = _jxr_rbitstream_uint8(str); /* reserved */ DEBUG(" TILE_STARTCODE == %02x %02x %02x (reserved: %02x)\n", s0, s1, s2, s3); _jxr_r_TILE_HEADER_DC(image, str, 0 /* alpha */, tx, ty); if (ALPHACHANNEL_FLAG(image)) _jxr_r_TILE_HEADER_DC(image->alpha, str, 1, tx, ty); /* Now form and write out all the compressed data for the tile. This involves scanning the macroblocks, and the blocks within the macroblocks, generating bits as we go. */ mb_height = EXTENDED_HEIGHT_BLOCKS(image); mb_width = EXTENDED_WIDTH_BLOCKS(image); if (TILING_FLAG(image)) { mb_height = image->tile_row_height[ty]; mb_width = image->tile_column_width[tx]; } for (my = 0 ; my < mb_height ; my += 1) { _jxr_r_rotate_mb_strip(image); image->cur_my = my; for (mx = 0 ; mx < mb_width ; mx += 1) { _jxr_r_MB_DC(image, str, 0, tx, ty, mx, my); if (image->bands_present == 3 /* DCONLY */) _jxr_complete_cur_dclp(image, tx, mx, my); if (ALPHACHANNEL_FLAG(image)) { _jxr_r_MB_DC(image->alpha, str, 1, tx, ty, mx, my); if (image->alpha->bands_present == 3 /* DCONLY */) _jxr_complete_cur_dclp(image->alpha, tx, mx, my); } } if (ALPHACHANNEL_FLAG(image)) backup_dc_strip(image->alpha, tx, ty, my); backup_dc_strip(image, tx, ty, my); } _jxr_rbitstream_syncbyte(str); DEBUG("END TILE_DC\n"); return 0; }
void _jxr_w_TILE_DC(jxr_image_t image, struct wbitstream*str, unsigned tx, unsigned ty) { DEBUG("START TILE_DC at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_wbitstream_bitpos(str)); uint8_t bands_present = image->bands_present_of_primary; /* TILE_STARTCODE == 1 */ DEBUG(" DC_TILE_STARTCODE at bitpos=%zu\n", _jxr_wbitstream_bitpos(str)); _jxr_wbitstream_uint8(str, 0x00); _jxr_wbitstream_uint8(str, 0x00); _jxr_wbitstream_uint8(str, 0x01); _jxr_wbitstream_uint8(str, 0x00); /* ARBITRARY_BYTE */ /* Write out the tile header (which includes sub-headers for all the major passes). */ _jxr_w_TILE_HEADER_DC(image, str, 0, tx, ty); if (ALPHACHANNEL_FLAG(image)) { _jxr_w_TILE_HEADER_DC(image->alpha, str, 1, tx, ty); } /* Now form and write out all the compressed data for the tile. This involves scanning the macroblocks, and the blocks within the macroblocks, generating bits as we go. */ unsigned mb_height = EXTENDED_HEIGHT_BLOCKS(image); unsigned mb_width = EXTENDED_WIDTH_BLOCKS(image); if (TILING_FLAG(image)) { mb_height = image->tile_row_height[ty]; mb_width = image->tile_column_width[tx]; } DEBUG(" TILE_DC at [%d %d] is %u x %u MBs\n", tx, ty, mb_width, mb_height); unsigned mx, my; for (my = 0 ; my < mb_height ; my += 1) { _jxr_wflush_mb_strip(image, tx, ty, my, 1); for (mx = 0 ; mx < mb_width ; mx += 1) { _jxr_w_MB_DC(image, str, 0 /* IsCurrPlaneAlphaFlag = FALSE */, tx, ty, mx, my); if (ALPHACHANNEL_FLAG(image)) { _jxr_w_MB_DC(image->alpha, str, 1 /* IsCurrPlaneAlphaFlag = TRUE */, tx, ty, mx, my); } } } unsigned tile_idx = ty * image->tile_columns + tx; _jxr_wbitstream_syncbyte(str); _jxr_wbitstream_flush(str); DEBUG("END TILE_DC\n"); }
void _jxr_clear_strip_cur(jxr_image_t image) { assert(image->num_channels > 0); int ch; for (ch = 0 ; ch < image->num_channels ; ch += 1) { unsigned idx; for (idx = 0 ; idx < EXTENDED_WIDTH_BLOCKS(image) ; idx += 1) { int jdx; for (jdx = 0 ; jdx < 256 ; jdx += 1) image->strip[ch].cur[idx].data[jdx] = 0; } } }
static void recover_dclphp_strip(jxr_image_t image, int tx, int ty, int my) { int mx; int use_my = my + image->tile_row_position[ty]; int use_mx = image->tile_column_position[tx]; int ptr = use_my*EXTENDED_WIDTH_BLOCKS(image) + use_mx; int format_scale = 16; if (image->use_clr_fmt == 2 /* YUV422 */) { format_scale = 8; } else if (image->use_clr_fmt == 1 /* YUV420 */) { format_scale = 4; } int ch; for (ch = 0 ; ch < image->num_channels ; ch += 1) { struct macroblock_s*mb = image->mb_row_buffer[ch] + ptr; int count = ch==0? 16 : format_scale; if (ch == 0) { /* Recover also the hp_model_bits, which are stored only in the channel-0 blocks. */ for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) { MACROBLK_CUR(image,0,tx,mx).hp_model_bits[0] = mb[mx].hp_model_bits[0]; MACROBLK_CUR(image,0,tx,mx).hp_model_bits[1] = mb[mx].hp_model_bits[1]; MACROBLK_CUR(image,0,tx,mx).mbhp_pred_mode = mb[mx].mbhp_pred_mode; } } for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) { MACROBLK_CUR_DC(image,ch,tx,mx) = mb[mx].data[0]; DEBUG(" recover_dclphp_strip: tx=%d, ty=%d, mx=%d, my=%d, ch=%d, DC=0x%0x8, LP=\n", tx, ty, mx, my, ch, mb[mx].data[0]); int blk; for (blk = 1 ; blk < count ; blk += 1) { MACROBLK_CUR_LP(image,ch,tx,mx,blk-1) = mb[mx].data[blk]; DEBUG(" 0x%x", mb[mx].data[blk]); } for (blk = 0 ; blk < count ; blk += 1) { int idx; for (idx = 0 ; idx < 15 ; idx += 1) { int data_ptr = count+15*blk+idx; MACROBLK_CUR_HP(image,ch,tx,mx,blk,idx) = mb[mx].data[data_ptr]; } } DEBUG("\n"); MACROBLK_CUR_LP_QUANT(image,ch,tx,mx) = mb[mx].lp_quant; MACROBLK_CUR_HP_QUANT(image,ch,tx,mx) = mb[mx].hp_quant; } } }
static void recover_dc_strip(jxr_image_t image, int tx, int ty, int my) { int mx; int use_my = my + image->tile_row_position[ty]; int use_mx = image->tile_column_position[tx]; int ptr = use_my*EXTENDED_WIDTH_BLOCKS(image) + use_mx; int ch; for (ch = 0 ; ch < image->num_channels ; ch += 1) { struct macroblock_s*mb = image->mb_row_buffer[ch] + ptr; for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) { MACROBLK_CUR_DC(image,ch,tx,mx) = mb[mx].data[0]; DEBUG(" recover_dc_strip: tx=%d, ty=%d, mx=%d, my=%d, ch=%d, DC=0x%0x8\n", tx, ty, mx, my, ch, mb[mx].data[0]); } } }
static void backup_hp_strip(jxr_image_t image, int tx, int ty, int my) { int mx; int use_my = my + image->tile_row_position[ty]; int use_mx = image->tile_column_position[tx]; int ptr = use_my*EXTENDED_WIDTH_BLOCKS(image) + use_mx; int format_scale = 16; if (image->use_clr_fmt == 2 /* YUV422 */) { format_scale = 8; } else if (image->use_clr_fmt == 1 /* YUV420 */) { format_scale = 4; } int ch; for (ch = 0 ; ch < image->num_channels ; ch += 1) { struct macroblock_s*mb = image->mb_row_buffer[ch] + ptr; int count = ch==0? 16 : format_scale; if (ch == 0) { /* Backup also the hp_model_bits, which are stored only in the channel-0 blocks. */ for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) { mb[mx].hp_model_bits[0] = MACROBLK_CUR(image,0,tx,mx).hp_model_bits[0]; mb[mx].hp_model_bits[1] = MACROBLK_CUR(image,0,tx,mx).hp_model_bits[1]; mb[mx].mbhp_pred_mode = MACROBLK_CUR(image,0,tx,mx).mbhp_pred_mode; } } for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) { mb[mx].data[0] = MACROBLK_CUR_DC(image,ch,tx,mx); DEBUG(" backup_hp_strip: tx=%d, ty=%d, mx=%d, my=%d, ch=%d\n", tx, ty, mx, my, ch); int blk; for (blk = 0 ; blk < count ; blk += 1) { int idx; for (idx = 0 ; idx < 15 ; idx += 1) mb[mx].data[count+15*blk+idx] = MACROBLK_CUR_HP(image,ch,tx,mx,blk,idx); } mb[mx].hp_quant = MACROBLK_CUR_HP_QUANT(image,ch,tx,mx); } } }
/* * This function handles the special case that the FLEXBITS tile is * escaped away. Do all the soft processing that is otherwise needed. */ int _jxr_r_TILE_FLEXBITS_ESCAPE(jxr_image_t image, unsigned tx, unsigned ty) { DEBUG("START TILE_FLEXBITS_ESCAPE at tile=[%u %u]\n", tx, ty); int use_num_channels = image->num_channels; if (image->use_clr_fmt == 1/*YUV420*/ || image->use_clr_fmt == 2/*YUV422*/) use_num_channels = 1; unsigned mb_height = EXTENDED_HEIGHT_BLOCKS(image); unsigned mb_width = EXTENDED_WIDTH_BLOCKS(image); if (TILING_FLAG(image)) { mb_height = image->tile_row_height[ty]; mb_width = image->tile_column_width[tx]; } int mx, my; for (my = 0 ; my < (int) mb_height ; my += 1) { _jxr_r_rotate_mb_strip(image); image->cur_my = my; recover_dclphp_strip(image, tx, ty, my); for (mx = 0 ; mx < (int) mb_width ; mx += 1) { /* */ int mbhp_pred_mode = MACROBLK_CUR(image,0,tx,mx).mbhp_pred_mode; int idx; for (idx = 0 ; idx < use_num_channels ; idx += 1) { DEBUG(" MB_FLEXBITS_ESCAPE: propagate HP predictions in MB_FLEXBITS\n"); _jxr_propagate_hp_predictions(image, idx, tx, mx, mbhp_pred_mode); } } backup_hp_strip(image, tx, ty, my); } DEBUG("END TILE_FLEXBIT_ESCAPE\n"); return 0; }
void _jxr_w_TILE_HP_FLEX(jxr_image_t image, struct wbitstream*str, unsigned tx, unsigned ty) { DEBUG("START TILE_HP_FLEX at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_wbitstream_bitpos(str)); uint8_t bands_present = image->bands_present_of_primary; struct wbitstream strFP; FILE*fdFP = fopen("fp.tmp", "wb"); _jxr_wbitstream_initialize(&strFP, fdFP); if (bands_present < 2 /* HIGHPASS */) { /* TILE_STARTCODE == 1 */ DEBUG(" HP_TILE_STARTCODE at bitpos=%zu\n", _jxr_wbitstream_bitpos(str)); _jxr_wbitstream_uint8(str, 0x00); _jxr_wbitstream_uint8(str, 0x00); _jxr_wbitstream_uint8(str, 0x01); _jxr_wbitstream_uint8(str, 0x00); /* ARBITRARY_BYTE */ _jxr_w_TILE_HEADER_HIGHPASS(image, str, 0, tx, ty); if (ALPHACHANNEL_FLAG(image)) { _jxr_w_TILE_HEADER_HIGHPASS(image->alpha, str, 1, tx, ty); } } if (bands_present == 0 /* ALL */) { /* TILE_STARTCODE == 1 */ DEBUG(" FLEX_TILE_STARTCODE at bitpos=%zu\n", _jxr_wbitstream_bitpos(&strFP)); _jxr_wbitstream_uint8(&strFP, 0x00); _jxr_wbitstream_uint8(&strFP, 0x00); _jxr_wbitstream_uint8(&strFP, 0x01); _jxr_wbitstream_uint8(&strFP, 0x00); /* ARBITRARY_BYTE */ if (TRIM_FLEXBITS_FLAG(image)) { _jxr_wbitstream_uint4(&strFP, image->trim_flexbits); } } /* Now form and write out all the compressed data for the tile. This involves scanning the macroblocks, and the blocks within the macroblocks, generating bits as we go. */ unsigned mb_height = EXTENDED_HEIGHT_BLOCKS(image); unsigned mb_width = EXTENDED_WIDTH_BLOCKS(image); if (TILING_FLAG(image)) { mb_height = image->tile_row_height[ty]; mb_width = image->tile_column_width[tx]; } DEBUG(" TILE_HP_FLEX at [%d %d] is %u x %u MBs\n", tx, ty, mb_width, mb_height); unsigned mx, my; for (my = 0 ; my < mb_height ; my += 1) { _jxr_wflush_mb_strip(image, tx, ty, my, 0); for (mx = 0 ; mx < mb_width ; mx += 1) { if (bands_present<2 /* HIGHPASS */) { if (image->num_hp_qps>1 && !image->hp_use_lp_qp) { unsigned qp_index = _jxr_select_hp_index(image, tx,ty,mx,my); DEBUG(" DECODE_QP_INDEX(%d) --> %u\n", image->num_hp_qps, qp_index); _jxr_w_ENCODE_QP_INDEX(image, str, tx, ty, mx, my, image->num_hp_qps, qp_index); } _jxr_w_MB_CBP(image, str, 0 /* IsCurrPlaneAlphaFlag = FALSE */, tx, ty, mx, my); if (bands_present == 0 /* ALL */) { _jxr_w_MB_HP(image, str, 0 /* IsCurrPlaneAlphaFlag = FALSE */, tx, ty, mx, my, &strFP); } else { _jxr_w_MB_HP(image, str, 0 /* IsCurrPlaneAlphaFlag = FALSE */, tx, ty, mx, my, 0); } if (ALPHACHANNEL_FLAG(image)) { _jxr_w_MB_CBP(image->alpha, str, 1 /* IsCurrPlaneAlphaFlag = TRUE */, tx, ty, mx, my); if (bands_present == 0 /* ALL */) { _jxr_w_MB_HP(image->alpha, str, 1 /* IsCurrPlaneAlphaFlag = TRUE */, tx, ty, mx, my, &strFP); } else { _jxr_w_MB_HP(image->alpha, str, 1 /* IsCurrPlaneAlphaFlag = TRUE */, tx, ty, mx, my, 0); } } } } } unsigned tile_idx = ty * image->tile_columns + tx; _jxr_wbitstream_syncbyte(str); _jxr_wbitstream_flush(str); image->tile_index_table[tile_idx * (4 - bands_present) + 2] = str->write_count; _jxr_wbitstream_syncbyte(&strFP); _jxr_wbitstream_flush(&strFP); fclose(fdFP); if (bands_present == 0 /* ALL */) { struct rbitstream strFPRead; FILE*fdFPRead = fopen("fp.tmp", "rb"); _jxr_rbitstream_initialize(&strFPRead, fdFPRead); size_t idx; for (idx = 0; idx < strFP.write_count; idx++) { _jxr_wbitstream_uint8(str, _jxr_rbitstream_uint8(&strFPRead)); } fclose(fdFPRead); _jxr_wbitstream_flush(str); image->tile_index_table[tile_idx * (4 - bands_present) + 3] = str->write_count; } /* delete file associated with CodedTiles */ remove("fp.tmp"); _jxr_wbitstream_flush(str); DEBUG("END TILE_HP_FLEX\n"); }
void _jxr_w_TILE_LP(jxr_image_t image, struct wbitstream*str, unsigned tx, unsigned ty) { DEBUG("START TILE_LP at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_wbitstream_bitpos(str)); uint8_t bands_present = image->bands_present_of_primary; if (bands_present < 3 /* LOWPASS */) { /* TILE_STARTCODE == 1 */ DEBUG(" LP_TILE_STARTCODE at bitpos=%zu\n", _jxr_wbitstream_bitpos(str)); _jxr_wbitstream_uint8(str, 0x00); _jxr_wbitstream_uint8(str, 0x00); _jxr_wbitstream_uint8(str, 0x01); _jxr_wbitstream_uint8(str, 0x00); /* ARBITRARY_BYTE */ _jxr_w_TILE_HEADER_LOWPASS(image, str, 0, tx, ty); if (ALPHACHANNEL_FLAG(image)) { _jxr_w_TILE_HEADER_LOWPASS(image->alpha, str, 1, tx, ty); } } /* Now form and write out all the compressed data for the tile. This involves scanning the macroblocks, and the blocks within the macroblocks, generating bits as we go. */ unsigned mb_height = EXTENDED_HEIGHT_BLOCKS(image); unsigned mb_width = EXTENDED_WIDTH_BLOCKS(image); if (TILING_FLAG(image)) { mb_height = image->tile_row_height[ty]; mb_width = image->tile_column_width[tx]; } DEBUG(" TILE_LP at [%d %d] is %u x %u MBs\n", tx, ty, mb_width, mb_height); unsigned mx, my; for (my = 0 ; my < mb_height ; my += 1) { _jxr_wflush_mb_strip(image, tx, ty, my, 0); for (mx = 0 ; mx < mb_width ; mx += 1) { if (bands_present<3 /* LOWPASS */) { if (image->num_lp_qps>1 && !image->lp_use_dc_qp) { unsigned qp_index = _jxr_select_lp_index(image, tx,ty,mx,my); DEBUG(" DECODE_QP_INDEX(%d) --> %u\n", image->num_lp_qps, qp_index); _jxr_w_ENCODE_QP_INDEX(image, str, tx, ty, mx, my, image->num_lp_qps, qp_index); } _jxr_w_MB_LP(image, str, 0 /* IsCurrPlaneAlphaFlag = FALSE */, tx, ty, mx, my); if (ALPHACHANNEL_FLAG(image)) { _jxr_w_MB_LP(image->alpha, str, 1 /* IsCurrPlaneAlphaFlag = TRUE */, tx, ty, mx, my); } } } } unsigned tile_idx = ty * image->tile_columns + tx; _jxr_wbitstream_syncbyte(str); _jxr_wbitstream_flush(str); DEBUG("END TILE_LP\n"); }
int _jxr_r_TILE_FLEXBITS(jxr_image_t image, struct rbitstream*str, unsigned tx, unsigned ty) { DEBUG("START TILE_FLEXBITS at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_rbitstream_bitpos(str)); /* TILE_STARTCODE == 1 */ unsigned char s0, s1, s2, s3; s0 = _jxr_rbitstream_uint8(str); /* 0x00 */ s1 = _jxr_rbitstream_uint8(str); /* 0x00 */ s2 = _jxr_rbitstream_uint8(str); /* 0x01 */ s3 = _jxr_rbitstream_uint8(str); /* reserved */ DEBUG(" TILE_STARTCODE == %02x %02x %02x (reserved: %02x)\n", s0, s1, s2, s3); if (s0 != 0x00 || s1 != 0x00 || s2 != 0x01) { DEBUG(" TILE_FLEXBITS ERROR: Invalid marker.\n"); return JXR_EC_ERROR; } image->trim_flexbits = 0; if (TRIM_FLEXBITS_FLAG(image)) { image->trim_flexbits =_jxr_rbitstream_uint4(str); DEBUG(" TRIM_FLEXBITS = %u\n", image->trim_flexbits); } int use_num_channels = image->num_channels; if (image->use_clr_fmt == 1/*YUV420*/ || image->use_clr_fmt == 2/*YUV422*/) use_num_channels = 1; /* Now form and write out all the compressed data for the tile. This involves scanning the macroblocks, and the blocks within the macroblocks, generating bits as we go. */ unsigned mb_height = EXTENDED_HEIGHT_BLOCKS(image); unsigned mb_width = EXTENDED_WIDTH_BLOCKS(image); if (TILING_FLAG(image)) { mb_height = image->tile_row_height[ty]; mb_width = image->tile_column_width[tx]; } int mx, my; int plane_idx, num_planes = ((ALPHACHANNEL_FLAG(image)) ? 2 : 1); for (my = 0 ; my < (int) mb_height ; my += 1) { _jxr_r_rotate_mb_strip(image); if (ALPHACHANNEL_FLAG(image)) { image->alpha->cur_my = my; recover_dclphp_strip(image->alpha, tx, ty, my); } image->cur_my = my; recover_dclphp_strip(image, tx, ty, my); for (mx = 0 ; mx < (int) mb_width ; mx += 1) for (plane_idx = 0; plane_idx < num_planes; plane_idx ++) { jxr_image_t plane = (plane_idx == 0 ? image : image->alpha); int channels = (plane_idx == 0 ? use_num_channels : 1); int rc = _jxr_r_MB_FLEXBITS(plane, str, 0, tx, ty, mx, my); if (rc < 0) { DEBUG("r_MB_FLEXBITS returned ERROR rc=%d\n", rc); return rc; } /* Now the HP values are complete, so run the propagation process. This involves recovering some bits of data saved by the HP tile. */ int mbhp_pred_mode = MACROBLK_CUR(plane,0,tx,mx).mbhp_pred_mode; int idx; for (idx = 0 ; idx < channels ; idx += 1) { DEBUG(" MB_FLEXBITS: propagate HP predictions in MB_FLEXBITS\n"); _jxr_propagate_hp_predictions(plane, idx, tx, mx, mbhp_pred_mode); } } if (ALPHACHANNEL_FLAG(image)) backup_hp_strip(image->alpha, tx, ty, my); backup_hp_strip(image, tx, ty, my); } _jxr_rbitstream_syncbyte(str); DEBUG("END TILE_FLEXBITS bitpos=%zu\n", _jxr_rbitstream_bitpos(str)); return 0; }
int _jxr_r_TILE_HP(jxr_image_t image, struct rbitstream*str, unsigned tx, unsigned ty) { DEBUG("START TILE_HIGHPASS at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_rbitstream_bitpos(str)); /* TILE_STARTCODE == 1 */ unsigned char s0, s1, s2, s3; s0 = _jxr_rbitstream_uint8(str); /* 0x00 */ s1 = _jxr_rbitstream_uint8(str); /* 0x00 */ s2 = _jxr_rbitstream_uint8(str); /* 0x01 */ s3 = _jxr_rbitstream_uint8(str); /* reserved */ DEBUG(" TILE_STARTCODE == %02x %02x %02x (reserved: %02x)\n", s0, s1, s2, s3); if (s0 != 0x00 || s1 != 0x00 || s2 != 0x01) { DEBUG(" TILE_HIGHPASS ERROR: Invalid marker.\n"); return JXR_EC_ERROR; } _jxr_r_TILE_HEADER_HIGHPASS(image, str, 0 /* alpha */, tx, ty); if (ALPHACHANNEL_FLAG(image)) _jxr_r_TILE_HEADER_HIGHPASS(image->alpha, str, 1, tx, ty); /* Now form and write out all the compressed data for the tile. This involves scanning the macroblocks, and the blocks within the macroblocks, generating bits as we go. */ unsigned mb_height = EXTENDED_HEIGHT_BLOCKS(image); unsigned mb_width = EXTENDED_WIDTH_BLOCKS(image); if (TILING_FLAG(image)) { mb_height = image->tile_row_height[ty]; mb_width = image->tile_column_width[tx]; } unsigned mx, my; unsigned plane_idx, num_planes = ((ALPHACHANNEL_FLAG(image)) ? 2 : 1); for (my = 0 ; my < mb_height ; my += 1) { _jxr_r_rotate_mb_strip(image); if (ALPHACHANNEL_FLAG(image)) { image->alpha->cur_my = my; recover_dclp_strip(image->alpha, tx, ty, my); } image->cur_my = my; recover_dclp_strip(image, tx, ty, my); for (mx = 0 ; mx < mb_width ; mx += 1) for (plane_idx = 0; plane_idx < num_planes; plane_idx ++) { /* The qp_index_hp table goes only into channel 0 */ int qp_index_hp = 0; jxr_image_t plane = (plane_idx == 0 ? image : image->alpha); if (plane->num_hp_qps>1) { if (!plane->hp_use_lp_qp) qp_index_hp = _jxr_DECODE_QP_INDEX(str, plane->num_hp_qps); else qp_index_hp = MACROBLK_CUR_LP_QUANT(plane,0,tx,mx); } DEBUG(" HP_QP_INDEX for MBx=%d is %d\n", mx, qp_index_hp); int ch; for (ch = 0 ; ch < plane->num_channels ; ch += 1) { MACROBLK_CUR_HP_QUANT(plane,ch,tx,mx) = plane->hp_quant_ch[ch][qp_index_hp]; DEBUG(" HP_QUANT for MBx=%d ch=%d is %d\n", mx, ch, MACROBLK_CUR_HP_QUANT(plane,ch,tx,mx)); } int rc = _jxr_r_MB_CBP(plane, str, 0, tx, ty, mx, my); if (rc < 0) { DEBUG("r_MB_CBP returned ERROR rc=%d\n", rc); return rc; } rc = _jxr_r_MB_HP(plane, str, 0, tx, ty, mx, my); if (rc < 0) { DEBUG("r_MB_HP returned ERROR rc=%d\n", rc); return rc; } } if (ALPHACHANNEL_FLAG(image)) backup_hp_strip(image->alpha, tx, ty, my); backup_hp_strip(image, tx, ty, my); } _jxr_rbitstream_syncbyte(str); DEBUG("END TILE_HIGHPASS\n"); return 0; }
void _jxr_w_TILE_SPATIAL(jxr_image_t image, struct wbitstream*str, unsigned tx, unsigned ty) { DEBUG("START TILE_SPATIAL at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_wbitstream_bitpos(str)); /* TILE_STARTCODE == 1 */ DEBUG(" TILE_STARTCODE at bitpos=%zu\n", _jxr_wbitstream_bitpos(str)); _jxr_wbitstream_uint8(str, 0x00); _jxr_wbitstream_uint8(str, 0x00); _jxr_wbitstream_uint8(str, 0x01); _jxr_wbitstream_uint8(str, 0x00); /* ARBITRARY_BYTE */ if (TRIM_FLEXBITS_FLAG(image)) { _jxr_wbitstream_uint4(str, image->trim_flexbits); } /* Write out the tile header (which includes sub-headers for all the major passes). */ _jxr_w_TILE_HEADER_DC(image, str, 0, tx, ty); if (image->bands_present != 3 /* DCONLY */) { _jxr_w_TILE_HEADER_LOWPASS(image, str, 0, tx, ty); if (image->bands_present != 2 /* NO_HIGHPASS */) { _jxr_w_TILE_HEADER_HIGHPASS(image, str, 0, tx, ty); } } if (ALPHACHANNEL_FLAG(image)) { _jxr_w_TILE_HEADER_DC(image->alpha, str, 1, tx, ty); if (image->bands_present != 3 /* DCONLY */) { _jxr_w_TILE_HEADER_LOWPASS(image->alpha, str, 1, tx, ty); if (image->bands_present != 2 /* NO_HIGHPASS */) { _jxr_w_TILE_HEADER_HIGHPASS(image->alpha, str, 1, tx, ty); } } } /* Now form and write out all the compressed data for the tile. This involves scanning the macroblocks, and the blocks within the macroblocks, generating bits as we go. */ unsigned mb_height = EXTENDED_HEIGHT_BLOCKS(image); unsigned mb_width = EXTENDED_WIDTH_BLOCKS(image); if (TILING_FLAG(image)) { mb_height = image->tile_row_height[ty]; mb_width = image->tile_column_width[tx]; } DEBUG(" TILE_SPATIAL at [%d %d] is %u x %u MBs\n", tx, ty, mb_width, mb_height); unsigned mx, my; unsigned plane_idx, num_planes = ((ALPHACHANNEL_FLAG(image)) ? 2 : 1); for (my = 0 ; my < mb_height ; my += 1) { _jxr_wflush_mb_strip(image, tx, ty, my, 1); for (mx = 0 ; mx < mb_width ; mx += 1) for (plane_idx = 0; plane_idx < num_planes; plane_idx ++) { jxr_image_t plane = (plane_idx == 0 ? image : image->alpha); if (plane->bands_present!=3) { if (plane->num_lp_qps>1 && !plane->lp_use_dc_qp) { unsigned qp_index = _jxr_select_lp_index(plane, tx,ty,mx,my); DEBUG(" DECODE_QP_INDEX(%d) --> %u\n", plane->num_lp_qps, qp_index); _jxr_w_ENCODE_QP_INDEX(plane, str, tx, ty, mx, my, plane->num_lp_qps, qp_index); } if (plane->bands_present!=2 && plane->num_hp_qps>1 && !plane->hp_use_lp_qp) { unsigned qp_index = _jxr_select_hp_index(plane, tx,ty,mx,my); DEBUG(" DECODE_QP_INDEX(%d) --> %u\n", plane->num_hp_qps, qp_index); _jxr_w_ENCODE_QP_INDEX(plane, str, tx, ty, mx, my, plane->num_hp_qps, qp_index); } } _jxr_w_MB_DC(plane, str, 0, tx, ty, mx, my); if (plane->bands_present != 3 /* DCONLY */) { _jxr_w_MB_LP(plane, str, 0, tx, ty, mx, my); if (plane->bands_present != 2 /* NOHIGHPASS */) { _jxr_w_MB_CBP(plane, str, 0, tx, ty, mx, my); _jxr_w_MB_HP(plane, str, 0, tx, ty, mx, my, 0); /* In SPATIAL mode, the MB_HP block will include the FLEXBITS. DO NOT include the MB_FLEXBITS separately. */ } } } } _jxr_wbitstream_syncbyte(str); _jxr_wbitstream_flush(str); DEBUG("END TILE_SPATIAL\n"); }
/* * Process a single spatial time. The tx/ty is the coordintes of the * tile in units of tiles. tx=0 for the first time, tx=1 for the * second, and so forth. */ int _jxr_r_TILE_SPATIAL(jxr_image_t image, struct rbitstream*str, unsigned tx, unsigned ty) { int rc = 0; DEBUG("START TILE_SPATIAL at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_rbitstream_bitpos(str)); /* TILE_STARTCODE == 1 */ unsigned char s0, s1, s2, s3; s0 = _jxr_rbitstream_uint8(str); /* 0x00 */ s1 = _jxr_rbitstream_uint8(str); /* 0x00 */ s2 = _jxr_rbitstream_uint8(str); /* 0x01 */ s3 = _jxr_rbitstream_uint8(str); /* reserved */ DEBUG(" TILE_STARTCODE == %02x %02x %02x (reserved: %02x)\n", s0, s1, s2, s3); image->trim_flexbits = 0; if (TRIM_FLEXBITS_FLAG(image)) { image->trim_flexbits =_jxr_rbitstream_uint4(str); DEBUG(" TRIM_FLEXBITS = %u\n", image->trim_flexbits); } /* Read the tile header (which includes sub-headers for all the major passes). */ _jxr_r_TILE_HEADER_DC(image, str, 0, tx, ty); if (image->bands_present != 3 /* DCONLY */) { _jxr_r_TILE_HEADER_LOWPASS(image, str, 0, tx, ty); if (image->bands_present != 2 /* NO_HIGHPASS */) { _jxr_r_TILE_HEADER_HIGHPASS(image, str, 0, tx, ty); } } /* If the alpha channel is present, then run another set of headers for the alpha channel. */ if (ALPHACHANNEL_FLAG(image)) { _jxr_r_TILE_HEADER_DC(image->alpha, str, 1, tx, ty); if (image->bands_present != 3 /* DCONLY */) { _jxr_r_TILE_HEADER_LOWPASS(image->alpha, str, 1, tx, ty); if (image->bands_present != 2 /* NO_HIGHPASS */) { _jxr_r_TILE_HEADER_HIGHPASS(image->alpha, str, 1, tx, ty); } } } /* Now form and write out all the compressed data for the tile. This involves scanning the macroblocks, and the blocks within the macroblocks, generating bits as we go. */ unsigned mb_height = EXTENDED_HEIGHT_BLOCKS(image); unsigned mb_width = EXTENDED_WIDTH_BLOCKS(image); if (TILING_FLAG(image)) { mb_height = image->tile_row_height[ty]; mb_width = image->tile_column_width[tx]; } unsigned mx, my, plane_idx; for (my = 0 ; my < mb_height ; my += 1) { if (ALPHACHANNEL_FLAG(image)) _jxr_rflush_mb_strip(image->alpha, tx, ty, my); _jxr_rflush_mb_strip(image, tx, ty, my); for (mx = 0 ; mx < mb_width ; mx += 1) { for(plane_idx = 0U; plane_idx < (ALPHACHANNEL_FLAG(image) ? 2U : 1U); plane_idx ++){ int ch; /* There is one LP_QP_INDEX per macroblock (if any) and that value applies to all the channels. Same for HP_QP_INDEX. There is no DC_QP_INDEX because DC QP values are per-tile, not per MB. */ int qp_index_lp = 0; int qp_index_hp = 0; jxr_image_t plane = (plane_idx == 0 ? image : image->alpha); if (plane->bands_present!=3) { if (plane->num_lp_qps>1 && !plane->lp_use_dc_qp) { qp_index_lp = _jxr_DECODE_QP_INDEX(str, plane->num_lp_qps); DEBUG(" DECODE_QP_INDEX(%d) --> %u (LP)\n", plane->num_lp_qps, qp_index_lp); } qp_index_hp = 0; if (plane->bands_present!=2 && plane->num_hp_qps>1) { if (!plane->hp_use_lp_qp) { qp_index_hp = _jxr_DECODE_QP_INDEX(str, plane->num_hp_qps); DEBUG(" DECODE_QP_INDEX(%d) --> %u (HP)\n", plane->num_hp_qps, qp_index_hp); } else { qp_index_hp = qp_index_lp; } } } for (ch = 0 ; ch < plane->num_channels ; ch += 1) { /* Save the LP Quant *INDEX* here. Prediction needs it. */ MACROBLK_CUR_LP_QUANT(plane,ch,tx,mx) = qp_index_lp; DEBUG(" LP_QUANT INDEX for tx=%u ty=%u ch=%u MBx=%d is %d\n", tx, ty, ch, mx, MACROBLK_CUR_LP_QUANT(plane,ch,tx,mx)); MACROBLK_CUR_HP_QUANT(plane,ch,tx,mx) = plane->hp_quant_ch[ch][qp_index_hp]; DEBUG(" HP_QUANT VALUE for tx=%u ty=%u ch=%u MBx=%d is %d\n", tx, ty, ch, mx, MACROBLK_CUR_HP_QUANT(plane,ch,tx,mx)); } _jxr_r_MB_DC(plane, str, plane_idx, tx, ty, mx, my); if (plane->bands_present != 3 /* DCONLY */) { _jxr_r_MB_LP(plane, str, plane_idx, tx, ty, mx, my); _jxr_complete_cur_dclp(plane, tx, mx, my); if (plane->bands_present != 2 /* NOHIGHPASS */) { rc = _jxr_r_MB_CBP(plane, str, plane_idx, tx, ty, mx, my); if (rc < 0) { DEBUG("r_MB_CBP returned ERROR rc=%d\n", rc); return rc; } rc = _jxr_r_MB_HP(plane, str, plane_idx, tx, ty, mx, my); if (rc < 0) { DEBUG("r_MB_HP returned ERROR rc=%d\n", rc); return rc; } } } else { _jxr_complete_cur_dclp(plane, tx, mx, my); } } } } /* Flush the remaining strips to output. */ if (tx+1 == image->tile_columns && ty+1 == image->tile_rows) { DEBUG(" Cleanup flush after last tile (tx=%d, ty=%d)\n", tx, ty); if (ALPHACHANNEL_FLAG(image)) _jxr_rflush_mb_strip(image->alpha, tx, ty, mb_height); _jxr_rflush_mb_strip(image, tx, ty, mb_height); if (ALPHACHANNEL_FLAG(image)) _jxr_rflush_mb_strip(image->alpha, tx, ty, mb_height+1); _jxr_rflush_mb_strip(image, tx, ty, mb_height+1); if (ALPHACHANNEL_FLAG(image)) _jxr_rflush_mb_strip(image->alpha, tx, ty, mb_height+2); _jxr_rflush_mb_strip(image, tx, ty, mb_height+2); if (ALPHACHANNEL_FLAG(image)) _jxr_rflush_mb_strip(image->alpha, tx, ty, mb_height+3); _jxr_rflush_mb_strip(image, tx, ty, mb_height+3); } _jxr_rbitstream_syncbyte(str); DEBUG("END TILE_SPATIAL\n"); return 0; }
/* ** Added by thor April 2nd 2010: Process one stripe at a time. */ int _jxr_r_TILE_SPATIAL_stripe(jxr_image_t image, struct rbitstream*str, unsigned tx, unsigned ty) { int rc = 0; if (image->spatial_buffered_flag == 0) { /* Header is not yet parsed off. Do now. */ DEBUG("START TILE_SPATIAL at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_rbitstream_bitpos(str)); if(INDEXTABLE_PRESENT_FLAG(image)) { _jxr_rbitstream_seek(str, image->tile_index_table[image->tile_columns * ty + tx]); } /* TILE_STARTCODE == 1 */ unsigned char s0, s1, s2, s3; s0 = _jxr_rbitstream_uint8(str); /* 0x00 */ s1 = _jxr_rbitstream_uint8(str); /* 0x00 */ s2 = _jxr_rbitstream_uint8(str); /* 0x01 */ s3 = _jxr_rbitstream_uint8(str); /* reserved */ DEBUG(" TILE_STARTCODE == %02x %02x %02x (reserved: %02x)\n", s0, s1, s2, s3); if (s0 != 0x00 || s1 != 0x00 || s2 != 0x01) { DEBUG(" TILE_LOWPASS ERROR: Invalid marker.\n"); return JXR_EC_ERROR; /* FIX THOR: Invalid TILE_STARTCODE detected */ } image->trim_flexbits = 0; if (TRIM_FLEXBITS_FLAG(image)) { image->trim_flexbits =_jxr_rbitstream_uint4(str); DEBUG(" TRIM_FLEXBITS = %u\n", image->trim_flexbits); } /* Read the tile header (which includes sub-headers for all the major passes). */ _jxr_r_TILE_HEADER_DC(image, str, 0, tx, ty); if (image->bands_present != 3 /* DCONLY */) { _jxr_r_TILE_HEADER_LOWPASS(image, str, 0, tx, ty); if (image->bands_present != 2 /* NO_HIGHPASS */) { _jxr_r_TILE_HEADER_HIGHPASS(image, str, 0, tx, ty); } } /* If the alpha channel is present, then run another set of headers for the alpha channel. */ if (ALPHACHANNEL_FLAG(image)) { _jxr_r_TILE_HEADER_DC(image->alpha, str, 1, tx, ty); if (image->bands_present != 3 /* DCONLY */) { _jxr_r_TILE_HEADER_LOWPASS(image->alpha, str, 1, tx, ty); if (image->bands_present != 2 /* NO_HIGHPASS */) { _jxr_r_TILE_HEADER_HIGHPASS(image->alpha, str, 1, tx, ty); } } } /* Now form and write out all the compressed data for the tile. This involves scanning the macroblocks, and the blocks within the macroblocks, generating bits as we go. */ { unsigned mb_height = EXTENDED_HEIGHT_BLOCKS(image); unsigned mb_width = EXTENDED_WIDTH_BLOCKS(image); if (TILING_FLAG(image)) { mb_height = image->tile_row_height[ty]; mb_width = image->tile_column_width[tx]; } image->spatial_mb_height = mb_height; image->spatial_mb_width = mb_width; } /* ** Done with the header. Initialize for the loop below. */ image->spatial_buffered_flag = 1; image->stripe_my = 0; image->cleanup_state = 0; image->output_sent = 0; // runs into the following. } switch(image->cleanup_state) { case 0: do { unsigned mx, plane_idx, my = image->stripe_my; unsigned mb_width = image->spatial_mb_width; /* for (my = 0 ; my < mb_height ; my += 1) { */ if (ALPHACHANNEL_FLAG(image)) _jxr_rflush_mb_strip(image->alpha, tx, ty, my); _jxr_rflush_mb_strip(image, tx, ty, my); for (mx = 0 ; mx < mb_width ; mx += 1) { for(plane_idx = 0U; plane_idx < (ALPHACHANNEL_FLAG(image) ? 2U : 1U); plane_idx ++){ int ch; /* There is one LP_QP_INDEX per macroblock (if any) and that value applies to all the channels. Same for HP_QP_INDEX. There is no DC_QP_INDEX because DC QP values are per-tile, not per MB. */ int qp_index_lp = 0; int qp_index_hp = 0; jxr_image_t plane = (plane_idx == 0 ? image : image->alpha); if (plane->bands_present!=3) { if (plane->num_lp_qps>1 && !plane->lp_use_dc_qp) { qp_index_lp = _jxr_DECODE_QP_INDEX(str, plane->num_lp_qps); DEBUG(" DECODE_QP_INDEX(%d) --> %u (LP)\n", plane->num_lp_qps, qp_index_lp); } qp_index_hp = 0; if (plane->bands_present!=2 && plane->num_hp_qps>1) { if (!plane->hp_use_lp_qp) { qp_index_hp = _jxr_DECODE_QP_INDEX(str, plane->num_hp_qps); DEBUG(" DECODE_QP_INDEX(%d) --> %u (HP)\n", plane->num_hp_qps, qp_index_hp); } else { qp_index_hp = qp_index_lp; } } } for (ch = 0 ; ch < plane->num_channels ; ch += 1) { /* Save the LP Quant *INDEX* here. Prediction needs it. */ MACROBLK_CUR_LP_QUANT(plane,ch,tx,mx) = qp_index_lp; DEBUG(" LP_QUANT INDEX for tx=%u ty=%u ch=%u MBx=%d is %d\n", tx, ty, ch, mx, MACROBLK_CUR_LP_QUANT(plane,ch,tx,mx)); MACROBLK_CUR_HP_QUANT(plane,ch,tx,mx) = plane->hp_quant_ch[ch][qp_index_hp]; DEBUG(" HP_QUANT VALUE for tx=%u ty=%u ch=%u MBx=%d is %d\n", tx, ty, ch, mx, MACROBLK_CUR_HP_QUANT(plane,ch,tx,mx)); } _jxr_r_MB_DC(plane, str, plane_idx, tx, ty, mx, my); if (plane->bands_present != 3 /* DCONLY */) { _jxr_r_MB_LP(plane, str, plane_idx, tx, ty, mx, my); _jxr_complete_cur_dclp(plane, tx, mx, my); if (plane->bands_present != 2 /* NOHIGHPASS */) { rc = _jxr_r_MB_CBP(plane, str, plane_idx, tx, ty, mx, my); if (rc < 0) { DEBUG("r_MB_CBP returned ERROR rc=%d\n", rc); return rc; } rc = _jxr_r_MB_HP(plane, str, plane_idx, tx, ty, mx, my); if (rc < 0) { DEBUG("r_MB_HP returned ERROR rc=%d\n", rc); return rc; } } } else { _jxr_complete_cur_dclp(plane, tx, mx, my); } } } /* ** Advance to the next MB row. */ image->stripe_my++; /* ** The flush happens only as part of the last tile, so continue iterating ** until that tile is hit. */ } while (image->stripe_my < image->spatial_mb_height && image->output_sent == 0); /* ** End of tile reached? If so, get the sycn marker */ if (image->stripe_my == image->spatial_mb_height) _jxr_rbitstream_syncbyte(str); /* ** If this is an intermediate tile and not the right edge, continue with the next tile. */ if (tx+1 != image->tile_columns) { image->spatial_buffered_flag = 0; image->stripe_my = 0; return 1; } /* ** Otherwise, a stripe is complete, go to the user. */ if (image->stripe_my < image->spatial_mb_height && image->output_sent) { image->output_sent = 0; return 0; /* not yet done with this strip, but return to the user. */ } assert(image->stripe_my == image->spatial_mb_height); /* ** Done with this tile, go to the next. We're done in case this is not the last tile, ** otherwise iterate on until we get to the last one. */ if (tx+1 == image->tile_columns && ty+1 == image->tile_rows) { // Last tile row. Continue with cleanup. image->cleanup_state = 1; } else { image->spatial_buffered_flag = 0; image->stripe_my = 0; return JXR_EC_DONE; } if (image->output_sent) return 0; // runs into the following case 1: /* Flush the remaining strips to output. */ if (tx+1 == image->tile_columns && ty+1 == image->tile_rows) { DEBUG(" Cleanup flush after last tile (tx=%d, ty=%d)\n", tx, ty); if (ALPHACHANNEL_FLAG(image)) _jxr_rflush_mb_strip(image->alpha, tx, ty, image->spatial_mb_height); _jxr_rflush_mb_strip(image, tx, ty, image->spatial_mb_height); image->cleanup_state++; if (image->output_sent) { image->output_sent = 0; return 0; } } else { return 1; } // runs into the following case 2: if (tx+1 == image->tile_columns && ty+1 == image->tile_rows) { if (ALPHACHANNEL_FLAG(image)) _jxr_rflush_mb_strip(image->alpha, tx, ty, image->spatial_mb_height+1); _jxr_rflush_mb_strip(image, tx, ty, image->spatial_mb_height+1); image->cleanup_state++; if (image->output_sent) { image->output_sent = 0; return 0; } } else { return 1; } // runs into the following case 3: if (tx+1 == image->tile_columns && ty+1 == image->tile_rows) { if (ALPHACHANNEL_FLAG(image)) _jxr_rflush_mb_strip(image->alpha, tx, ty, image->spatial_mb_height+2); _jxr_rflush_mb_strip(image, tx, ty, image->spatial_mb_height+2); image->cleanup_state++; if (image->output_sent) { image->output_sent = 0; return 0; } } else { return 1; } // runs into the following case 4: if (tx+1 == image->tile_columns && ty+1 == image->tile_rows) { if (ALPHACHANNEL_FLAG(image)) _jxr_rflush_mb_strip(image->alpha, tx, ty, image->spatial_mb_height+3); _jxr_rflush_mb_strip(image, tx, ty, image->spatial_mb_height+3); image->cleanup_state++; if (image->output_sent) { image->output_sent = 0; return 0; } } else { return 1; } // runs into the following default: image->spatial_buffered_flag = 0; image->stripe_my = 0; return JXR_EC_DONE; } }