lightfield_decoder.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /*
  2. * Copyright (c) 2017, Alliance for Open Media. All rights reserved
  3. *
  4. * This source code is subject to the terms of the BSD 2 Clause License and
  5. * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
  6. * was not distributed with this source code in the LICENSE file, you can
  7. * obtain it at www.aomedia.org/license/software. If the Alliance for Open
  8. * Media Patent License 1.0 was not distributed with this source code in the
  9. * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
  10. */
  11. // Lightfield Decoder
  12. // ==================
  13. //
  14. // This is an example of a simple lightfield decoder. It builds upon the
  15. // simple_decoder.c example. It takes an input file containing the compressed
  16. // data (in ivf format), treating it as a lightfield instead of a video; and a
  17. // text file with a list of tiles to decode. There is an optional parameter
  18. // allowing to choose the output format, and the supported formats are
  19. // YUV1D(default), YUV, and NV12.
  20. // After running the lightfield encoder, run lightfield decoder to decode a
  21. // batch of tiles:
  22. // examples/lightfield_decoder vase10x10.ivf vase_reference.yuv 4 tile_list.txt
  23. // 0(optional)
  24. // The tile_list.txt is expected to be of the form:
  25. // Frame <frame_index0>
  26. // <image_index0> <anchor_index0> <tile_col0> <tile_row0>
  27. // <image_index1> <anchor_index1> <tile_col1> <tile_row1>
  28. // ...
  29. // Frame <frame_index1)
  30. // ...
  31. //
  32. // The "Frame" markers indicate a new render frame and thus a new tile list
  33. // will be started and the old one flushed. The image_indexN, anchor_indexN,
  34. // tile_colN, and tile_rowN identify an individual tile to be decoded and
  35. // to use anchor_indexN anchor image for MCP.
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include "aom/aom_decoder.h"
  40. #include "aom/aomdx.h"
  41. #include "aom_scale/yv12config.h"
  42. #include "av1/common/enums.h"
  43. #include "common/tools_common.h"
  44. #include "common/video_reader.h"
  45. static const char *exec_name;
  46. void usage_exit(void) {
  47. fprintf(stderr,
  48. "Usage: %s <infile> <outfile> <num_references> <tile_list> <output "
  49. "format(optional)>\n",
  50. exec_name);
  51. exit(EXIT_FAILURE);
  52. }
  53. // Output frame size
  54. const int output_frame_width = 512;
  55. const int output_frame_height = 512;
  56. static void aom_img_copy_tile(const aom_image_t *src, const aom_image_t *dst,
  57. int dst_row_offset, int dst_col_offset) {
  58. const int shift = (src->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 1 : 0;
  59. int plane;
  60. for (plane = 0; plane < 3; ++plane) {
  61. const unsigned char *src_buf = src->planes[plane];
  62. const int src_stride = src->stride[plane];
  63. unsigned char *dst_buf = dst->planes[plane];
  64. const int dst_stride = dst->stride[plane];
  65. const int roffset =
  66. (plane > 0) ? dst_row_offset >> dst->y_chroma_shift : dst_row_offset;
  67. const int coffset =
  68. (plane > 0) ? dst_col_offset >> dst->x_chroma_shift : dst_col_offset;
  69. // col offset needs to be adjusted for HBD.
  70. dst_buf += roffset * dst_stride + (coffset << shift);
  71. const int w = (aom_img_plane_width(src, plane) << shift);
  72. const int h = aom_img_plane_height(src, plane);
  73. int y;
  74. for (y = 0; y < h; ++y) {
  75. memcpy(dst_buf, src_buf, w);
  76. src_buf += src_stride;
  77. dst_buf += dst_stride;
  78. }
  79. }
  80. }
  81. void decode_tile(aom_codec_ctx_t *codec, const unsigned char *frame,
  82. size_t frame_size, int tr, int tc, int ref_idx,
  83. aom_image_t *reference_images, aom_image_t *output,
  84. int *tile_idx, unsigned int *output_bit_depth,
  85. aom_image_t **img_ptr, int output_format) {
  86. AOM_CODEC_CONTROL_TYPECHECKED(codec, AV1_SET_TILE_MODE, 1);
  87. AOM_CODEC_CONTROL_TYPECHECKED(codec, AV1D_EXT_TILE_DEBUG, 1);
  88. AOM_CODEC_CONTROL_TYPECHECKED(codec, AV1_SET_DECODE_TILE_ROW, tr);
  89. AOM_CODEC_CONTROL_TYPECHECKED(codec, AV1_SET_DECODE_TILE_COL, tc);
  90. av1_ref_frame_t ref;
  91. ref.idx = 0;
  92. ref.use_external_ref = 1;
  93. ref.img = reference_images[ref_idx];
  94. if (AOM_CODEC_CONTROL_TYPECHECKED(codec, AV1_SET_REFERENCE, &ref)) {
  95. die_codec(codec, "Failed to set reference frame.");
  96. }
  97. aom_codec_err_t aom_status = aom_codec_decode(codec, frame, frame_size, NULL);
  98. if (aom_status) die_codec(codec, "Failed to decode tile.");
  99. aom_codec_iter_t iter = NULL;
  100. aom_image_t *img = aom_codec_get_frame(codec, &iter);
  101. if (!img) die_codec(codec, "Failed to get frame.");
  102. *img_ptr = img;
  103. // aom_img_alloc() sets bit_depth as follows:
  104. // output->bit_depth = (fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 16 : 8;
  105. // Use img->bit_depth(read from bitstream), so that aom_shift_img()
  106. // works as expected.
  107. output->bit_depth = img->bit_depth;
  108. *output_bit_depth = img->bit_depth;
  109. if (output_format != YUV1D) {
  110. // read out the tile size.
  111. unsigned int tile_size = 0;
  112. if (AOM_CODEC_CONTROL_TYPECHECKED(codec, AV1D_GET_TILE_SIZE, &tile_size))
  113. die_codec(codec, "Failed to get the tile size");
  114. const unsigned int tile_width = tile_size >> 16;
  115. const unsigned int tile_height = tile_size & 65535;
  116. const uint32_t output_frame_width_in_tiles =
  117. output_frame_width / tile_width;
  118. // Copy the tile to the output frame.
  119. const int row_offset =
  120. (*tile_idx / output_frame_width_in_tiles) * tile_height;
  121. const int col_offset =
  122. (*tile_idx % output_frame_width_in_tiles) * tile_width;
  123. aom_img_copy_tile(img, output, row_offset, col_offset);
  124. (*tile_idx)++;
  125. }
  126. }
  127. static void img_write_to_file(const aom_image_t *img, FILE *file,
  128. int output_format) {
  129. if (output_format == YUV)
  130. aom_img_write(img, file);
  131. else if (output_format == NV12)
  132. aom_img_write_nv12(img, file);
  133. else
  134. die("Invalid output format");
  135. }
  136. int main(int argc, char **argv) {
  137. FILE *outfile = NULL;
  138. AvxVideoReader *reader = NULL;
  139. const AvxVideoInfo *info = NULL;
  140. int num_references;
  141. aom_img_fmt_t ref_fmt = 0;
  142. aom_image_t reference_images[MAX_EXTERNAL_REFERENCES];
  143. aom_image_t output;
  144. aom_image_t *output_shifted = NULL;
  145. size_t frame_size = 0;
  146. const unsigned char *frame = NULL;
  147. int i, j;
  148. const char *tile_list_file = NULL;
  149. int output_format = YUV1D;
  150. exec_name = argv[0];
  151. if (argc < 5) die("Invalid number of arguments.");
  152. reader = aom_video_reader_open(argv[1]);
  153. if (!reader) die("Failed to open %s for reading.", argv[1]);
  154. if (!(outfile = fopen(argv[2], "wb")))
  155. die("Failed to open %s for writing.", argv[2]);
  156. num_references = (int)strtol(argv[3], NULL, 0);
  157. tile_list_file = argv[4];
  158. if (argc > 5) output_format = (int)strtol(argv[5], NULL, 0);
  159. if (output_format < YUV1D || output_format > NV12)
  160. die("Output format out of range [0, 2]");
  161. info = aom_video_reader_get_info(reader);
  162. aom_codec_iface_t *decoder;
  163. if (info->codec_fourcc == LST_FOURCC)
  164. decoder = get_aom_decoder_by_fourcc(AV1_FOURCC);
  165. else
  166. die("Unknown input codec.");
  167. printf("Using %s\n", aom_codec_iface_name(decoder));
  168. aom_codec_ctx_t codec;
  169. if (aom_codec_dec_init(&codec, decoder, NULL, 0))
  170. die_codec(&codec, "Failed to initialize decoder.");
  171. if (AOM_CODEC_CONTROL_TYPECHECKED(&codec, AV1D_SET_IS_ANNEXB,
  172. info->is_annexb)) {
  173. die("Failed to set annex b status");
  174. }
  175. // Decode anchor frames.
  176. AOM_CODEC_CONTROL_TYPECHECKED(&codec, AV1_SET_TILE_MODE, 0);
  177. for (i = 0; i < num_references; ++i) {
  178. aom_video_reader_read_frame(reader);
  179. frame = aom_video_reader_get_frame(reader, &frame_size);
  180. if (aom_codec_decode(&codec, frame, frame_size, NULL))
  181. die_codec(&codec, "Failed to decode frame.");
  182. if (i == 0) {
  183. if (AOM_CODEC_CONTROL_TYPECHECKED(&codec, AV1D_GET_IMG_FORMAT, &ref_fmt))
  184. die_codec(&codec, "Failed to get the image format");
  185. int frame_res[2];
  186. if (AOM_CODEC_CONTROL_TYPECHECKED(&codec, AV1D_GET_FRAME_SIZE, frame_res))
  187. die_codec(&codec, "Failed to get the image frame size");
  188. // Allocate memory to store decoded references. Allocate memory with the
  189. // border so that it can be used as a reference.
  190. for (j = 0; j < num_references; j++) {
  191. unsigned int border = AOM_DEC_BORDER_IN_PIXELS;
  192. if (!aom_img_alloc_with_border(&reference_images[j], ref_fmt,
  193. frame_res[0], frame_res[1], 32, 8,
  194. border)) {
  195. die("Failed to allocate references.");
  196. }
  197. }
  198. }
  199. if (AOM_CODEC_CONTROL_TYPECHECKED(&codec, AV1_COPY_NEW_FRAME_IMAGE,
  200. &reference_images[i]))
  201. die_codec(&codec, "Failed to copy decoded reference frame");
  202. aom_codec_iter_t iter = NULL;
  203. aom_image_t *img = NULL;
  204. while ((img = aom_codec_get_frame(&codec, &iter)) != NULL) {
  205. char name[1024];
  206. snprintf(name, sizeof(name), "ref_%d.yuv", i);
  207. printf("writing ref image to %s, %u, %u\n", name, img->d_w, img->d_h);
  208. FILE *ref_file = fopen(name, "wb");
  209. aom_img_write(img, ref_file);
  210. fclose(ref_file);
  211. }
  212. }
  213. FILE *infile = aom_video_reader_get_file(reader);
  214. // Record the offset of the first camera image.
  215. const FileOffset camera_frame_pos = ftello(infile);
  216. printf("Loading compressed frames into memory.\n");
  217. // Count the frames in the lightfield.
  218. int num_frames = 0;
  219. while (aom_video_reader_read_frame(reader)) {
  220. ++num_frames;
  221. }
  222. if (num_frames < 1) die("Input light field has no frames.");
  223. // Read all of the lightfield frames into memory.
  224. unsigned char **frames =
  225. (unsigned char **)malloc(num_frames * sizeof(unsigned char *));
  226. size_t *frame_sizes = (size_t *)malloc(num_frames * sizeof(size_t));
  227. // Seek to the first camera image.
  228. fseeko(infile, camera_frame_pos, SEEK_SET);
  229. for (int f = 0; f < num_frames; ++f) {
  230. aom_video_reader_read_frame(reader);
  231. frame = aom_video_reader_get_frame(reader, &frame_size);
  232. frames[f] = (unsigned char *)malloc(frame_size * sizeof(unsigned char));
  233. memcpy(frames[f], frame, frame_size);
  234. frame_sizes[f] = frame_size;
  235. }
  236. printf("Read %d frames.\n", num_frames);
  237. if (output_format != YUV1D) {
  238. // Allocate the output frame.
  239. aom_img_fmt_t out_fmt = ref_fmt;
  240. if (FORCE_HIGHBITDEPTH_DECODING) out_fmt |= AOM_IMG_FMT_HIGHBITDEPTH;
  241. if (!aom_img_alloc(&output, out_fmt, output_frame_width,
  242. output_frame_height, 32))
  243. die("Failed to allocate output image.");
  244. }
  245. printf("Decoding tile list from file.\n");
  246. char line[1024];
  247. FILE *tile_list_fptr = fopen(tile_list_file, "r");
  248. if (!tile_list_fptr) die_codec(&codec, "Failed to open tile list file.");
  249. int tile_list_cnt = 0;
  250. int tile_list_writes = 0;
  251. int tile_idx = 0;
  252. aom_image_t *out = NULL;
  253. unsigned int output_bit_depth = 0;
  254. while ((fgets(line, 1024, tile_list_fptr)) != NULL) {
  255. if (line[0] == 'F') {
  256. if (output_format != YUV1D) {
  257. // Write out the tile list.
  258. if (tile_list_cnt) {
  259. out = &output;
  260. if (output_bit_depth != 0)
  261. aom_shift_img(output_bit_depth, &out, &output_shifted);
  262. img_write_to_file(out, outfile, output_format);
  263. tile_list_writes++;
  264. }
  265. tile_list_cnt++;
  266. tile_idx = 0;
  267. // Then memset the frame.
  268. memset(output.img_data, 0, output.sz);
  269. }
  270. continue;
  271. }
  272. int image_idx, ref_idx, tc, tr;
  273. sscanf(line, "%d %d %d %d", &image_idx, &ref_idx, &tc, &tr);
  274. if (image_idx >= num_frames) {
  275. die("Tile list image_idx out of bounds: %d >= %d.", image_idx,
  276. num_frames);
  277. }
  278. if (ref_idx >= num_references) {
  279. die("Tile list ref_idx out of bounds: %d >= %d.", ref_idx,
  280. num_references);
  281. }
  282. frame = frames[image_idx];
  283. frame_size = frame_sizes[image_idx];
  284. aom_image_t *img = NULL;
  285. decode_tile(&codec, frame, frame_size, tr, tc, ref_idx, reference_images,
  286. &output, &tile_idx, &output_bit_depth, &img, output_format);
  287. if (output_format == YUV1D) {
  288. out = img;
  289. if (output_bit_depth != 0)
  290. aom_shift_img(output_bit_depth, &out, &output_shifted);
  291. aom_img_write(out, outfile);
  292. }
  293. }
  294. if (output_format != YUV1D) {
  295. // Write out the last tile list.
  296. if (tile_list_writes < tile_list_cnt) {
  297. out = &output;
  298. if (output_bit_depth != 0)
  299. aom_shift_img(output_bit_depth, &out, &output_shifted);
  300. img_write_to_file(out, outfile, output_format);
  301. }
  302. }
  303. if (output_shifted) aom_img_free(output_shifted);
  304. if (output_format != YUV1D) aom_img_free(&output);
  305. for (i = 0; i < num_references; i++) aom_img_free(&reference_images[i]);
  306. for (int f = 0; f < num_frames; ++f) {
  307. free(frames[f]);
  308. }
  309. free(frame_sizes);
  310. free(frames);
  311. if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
  312. aom_video_reader_close(reader);
  313. fclose(outfile);
  314. return EXIT_SUCCESS;
  315. }