ext-tile: output 8bit content at 1 byte per pixel BUG=aomedia:1999 Change-Id: Icd119460f4d56da913685532c0b0cc60ccda509b
diff --git a/av1/decoder/obu.c b/av1/decoder/obu.c index 1fa4d5b..baec66b 100644 --- a/av1/decoder/obu.c +++ b/av1/decoder/obu.c
@@ -428,14 +428,41 @@ (pbi->output_frame_height_in_tiles_minus_1 + 1)); // Allocate the tile list output buffer. - if (aom_alloc_frame_buffer( - &pbi->tile_list_outbuf, output_frame_width, output_frame_height, - cm->subsampling_x, cm->subsampling_y, - cm->use_highbitdepth, 0, cm->byte_alignment)) + // Note: if cm->seq_params.use_highbitdepth is 1 and cm->seq_params.bit_depth + // is 8, we could allocate less memory, namely, 8 bits/pixel. + if (aom_alloc_frame_buffer(&pbi->tile_list_outbuf, output_frame_width, + output_frame_height, cm->subsampling_x, + cm->subsampling_y, + (cm->use_highbitdepth && + (cm->bit_depth > AOM_BITS_8)), + 0, cm->byte_alignment)) aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR, "Failed to allocate the tile list output buffer"); } +static void yv12_tile_copy(const YV12_BUFFER_CONFIG *src, int hstart1, + int hend1, int vstart1, int vend1, + YV12_BUFFER_CONFIG *dst, int hstart2, int vstart2, + int plane) { + const int src_stride = (plane > 0) ? src->strides[1] : src->strides[0]; + const int dst_stride = (plane > 0) ? dst->strides[1] : dst->strides[0]; + int row, col; + + assert(src->flags & YV12_FLAG_HIGHBITDEPTH); + assert(!(dst->flags & YV12_FLAG_HIGHBITDEPTH)); + + const uint16_t *src16 = + CONVERT_TO_SHORTPTR(src->buffers[plane] + vstart1 * src_stride + hstart1); + uint8_t *dst8 = dst->buffers[plane] + vstart2 * dst_stride + hstart2; + + for (row = vstart1; row < vend1; ++row) { + for (col = 0; col < (hend1 - hstart1); ++col) *dst8++ = *src16++; + src16 += src_stride - (hend1 - hstart1); + dst8 += dst_stride - (hend1 - hstart1); + } + return; +} + static void copy_decoded_tile_to_tile_list_buffer(AV1Decoder *pbi, int tile_idx) { AV1_COMMON *const cm = &pbi->common; @@ -466,20 +493,26 @@ int vstart2 = tr * h; int hstart2 = tc * w; - switch (plane) { - case 0: - aom_yv12_partial_copy_y(cur_frame, hstart1, hend1, vstart1, vend1, - &pbi->tile_list_outbuf, hstart2, vstart2); - break; - case 1: - aom_yv12_partial_copy_u(cur_frame, hstart1, hend1, vstart1, vend1, - &pbi->tile_list_outbuf, hstart2, vstart2); - break; - case 2: - aom_yv12_partial_copy_v(cur_frame, hstart1, hend1, vstart1, vend1, - &pbi->tile_list_outbuf, hstart2, vstart2); - break; - default: assert(0); + if (cm->use_highbitdepth && + cm->bit_depth == AOM_BITS_8) { + yv12_tile_copy(cur_frame, hstart1, hend1, vstart1, vend1, + &pbi->tile_list_outbuf, hstart2, vstart2, plane); + } else { + switch (plane) { + case 0: + aom_yv12_partial_copy_y(cur_frame, hstart1, hend1, vstart1, vend1, + &pbi->tile_list_outbuf, hstart2, vstart2); + break; + case 1: + aom_yv12_partial_copy_u(cur_frame, hstart1, hend1, vstart1, vend1, + &pbi->tile_list_outbuf, hstart2, vstart2); + break; + case 2: + aom_yv12_partial_copy_v(cur_frame, hstart1, hend1, vstart1, vend1, + &pbi->tile_list_outbuf, hstart2, vstart2); + break; + default: assert(0); + } } } }
diff --git a/examples/lightfield_decoder.c b/examples/lightfield_decoder.c index 055bb10..8cc29de 100644 --- a/examples/lightfield_decoder.c +++ b/examples/lightfield_decoder.c
@@ -90,7 +90,7 @@ void decode_tile(aom_codec_ctx_t *codec, const unsigned char *frame, size_t frame_size, int tr, int tc, int ref_idx, aom_image_t *reference_images, aom_image_t *output, - int *tile_idx) { + int *tile_idx, unsigned int *output_bit_depth) { aom_codec_control_(codec, AV1_SET_TILE_MODE, 1); aom_codec_control_(codec, AV1D_EXT_TILE_DEBUG, 1); aom_codec_control_(codec, AV1_SET_DECODE_TILE_ROW, tr); @@ -111,6 +111,13 @@ aom_image_t *img = aom_codec_get_frame(codec, &iter); if (!img) die_codec(codec, "Failed to get frame."); + // aom_img_alloc() sets bit_depth as follows: + // output->bit_depth = (fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 16 : 8; + // Use img->bit_depth(read from bitstream), so that aom_shift_img() + // works as expected. + output->bit_depth = img->bit_depth; + *output_bit_depth = img->bit_depth; + // read out the tile size. unsigned int tile_size = 0; if (aom_codec_control(codec, AV1D_GET_TILE_SIZE, &tile_size)) @@ -138,6 +145,7 @@ aom_img_fmt_t ref_fmt = 0; aom_image_t reference_images[MAX_EXTERNAL_REFERENCES]; aom_image_t output; + aom_image_t *output_shifted = NULL; size_t frame_size = 0; const unsigned char *frame = NULL; int i, j; @@ -253,11 +261,18 @@ int tile_list_cnt = 0; int tile_list_writes = 0; int tile_idx = 0; + aom_image_t *out = NULL; + unsigned int output_bit_depth = 0; + while ((fgets(line, 1024, tile_list_fptr)) != NULL) { if (line[0] == 'F') { // Write out the tile list. if (tile_list_cnt) { - aom_img_write(&output, outfile); + out = &output; + // Shift up or down if necessary + if (output_bit_depth != 0) + aom_shift_img(output_bit_depth, &out, &output_shifted); + aom_img_write(out, outfile); tile_list_writes++; } @@ -268,11 +283,7 @@ continue; } - int image_idx; - int ref_idx; - int tc; - int tr; - + int image_idx, ref_idx, tc, tr; sscanf(line, "%d %d %d %d", &image_idx, &ref_idx, &tc, &tr); if (image_idx >= num_frames) { die("Tile list image_idx out of bounds: %d >= %d.", image_idx, @@ -285,12 +296,19 @@ frame = frames[image_idx]; frame_size = frame_sizes[image_idx]; decode_tile(&codec, frame, frame_size, tr, tc, ref_idx, reference_images, - &output, &tile_idx); + &output, &tile_idx, &output_bit_depth); } // Write out the last tile list. - if (tile_list_writes < tile_list_cnt) aom_img_write(&output, outfile); + if (tile_list_writes < tile_list_cnt) { + out = &output; + // Shift up or down if necessary + if (output_bit_depth != 0) + aom_shift_img(output_bit_depth, &out, &output_shifted); + aom_img_write(out, outfile); + } + if (output_shifted) aom_img_free(output_shifted); aom_img_free(&output); for (i = 0; i < num_references; i++) aom_img_free(&reference_images[i]); for (int f = 0; f < num_frames; ++f) {