vpxdec.c 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072
  1. /*
  2. * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #include <assert.h>
  11. #include <limits.h>
  12. #include <stdarg.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include "./vpx_config.h"
  17. #if CONFIG_LIBYUV
  18. #include "third_party/libyuv/include/libyuv/scale.h"
  19. #endif
  20. #include "./args.h"
  21. #include "./ivfdec.h"
  22. #include "vpx/vpx_decoder.h"
  23. #include "vpx_ports/mem_ops.h"
  24. #include "vpx_ports/vpx_timer.h"
  25. #if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER
  26. #include "vpx/vp8dx.h"
  27. #endif
  28. #include "./md5_utils.h"
  29. #include "./tools_common.h"
  30. #if CONFIG_WEBM_IO
  31. #include "./webmdec.h"
  32. #endif
  33. #include "./y4menc.h"
  34. static const char *exec_name;
  35. struct VpxDecInputContext {
  36. struct VpxInputContext *vpx_input_ctx;
  37. struct WebmInputContext *webm_ctx;
  38. };
  39. static const arg_def_t looparg =
  40. ARG_DEF(NULL, "loops", 1, "Number of times to decode the file");
  41. static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1, "Codec to use");
  42. static const arg_def_t use_yv12 =
  43. ARG_DEF(NULL, "yv12", 0, "Output raw YV12 frames");
  44. static const arg_def_t use_i420 =
  45. ARG_DEF(NULL, "i420", 0, "Output raw I420 frames");
  46. static const arg_def_t flipuvarg =
  47. ARG_DEF(NULL, "flipuv", 0, "Flip the chroma planes in the output");
  48. static const arg_def_t rawvideo =
  49. ARG_DEF(NULL, "rawvideo", 0, "Output raw YUV frames");
  50. static const arg_def_t noblitarg =
  51. ARG_DEF(NULL, "noblit", 0, "Don't process the decoded frames");
  52. static const arg_def_t progressarg =
  53. ARG_DEF(NULL, "progress", 0, "Show progress after each frame decodes");
  54. static const arg_def_t limitarg =
  55. ARG_DEF(NULL, "limit", 1, "Stop decoding after n frames");
  56. static const arg_def_t skiparg =
  57. ARG_DEF(NULL, "skip", 1, "Skip the first n input frames");
  58. static const arg_def_t postprocarg =
  59. ARG_DEF(NULL, "postproc", 0, "Postprocess decoded frames");
  60. static const arg_def_t summaryarg =
  61. ARG_DEF(NULL, "summary", 0, "Show timing summary");
  62. static const arg_def_t outputfile =
  63. ARG_DEF("o", "output", 1, "Output file name pattern (see below)");
  64. static const arg_def_t threadsarg =
  65. ARG_DEF("t", "threads", 1, "Max threads to use");
  66. static const arg_def_t frameparallelarg =
  67. ARG_DEF(NULL, "frame-parallel", 0, "Frame parallel decode (ignored)");
  68. static const arg_def_t verbosearg =
  69. ARG_DEF("v", "verbose", 0, "Show version string");
  70. static const arg_def_t error_concealment =
  71. ARG_DEF(NULL, "error-concealment", 0, "Enable decoder error-concealment");
  72. static const arg_def_t scalearg =
  73. ARG_DEF("S", "scale", 0, "Scale output frames uniformly");
  74. static const arg_def_t continuearg =
  75. ARG_DEF("k", "keep-going", 0, "(debug) Continue decoding after error");
  76. static const arg_def_t fb_arg =
  77. ARG_DEF(NULL, "frame-buffers", 1, "Number of frame buffers to use");
  78. static const arg_def_t md5arg =
  79. ARG_DEF(NULL, "md5", 0, "Compute the MD5 sum of the decoded frame");
  80. #if CONFIG_VP9_HIGHBITDEPTH
  81. static const arg_def_t outbitdeptharg =
  82. ARG_DEF(NULL, "output-bit-depth", 1, "Output bit-depth for decoded frames");
  83. #endif
  84. static const arg_def_t svcdecodingarg = ARG_DEF(
  85. NULL, "svc-decode-layer", 1, "Decode SVC stream up to given spatial layer");
  86. static const arg_def_t framestatsarg =
  87. ARG_DEF(NULL, "framestats", 1, "Output per-frame stats (.csv format)");
  88. static const arg_def_t *all_args[] = {
  89. &codecarg, &use_yv12, &use_i420,
  90. &flipuvarg, &rawvideo, &noblitarg,
  91. &progressarg, &limitarg, &skiparg,
  92. &postprocarg, &summaryarg, &outputfile,
  93. &threadsarg, &frameparallelarg, &verbosearg,
  94. &scalearg, &fb_arg, &md5arg,
  95. &error_concealment, &continuearg,
  96. #if CONFIG_VP9_HIGHBITDEPTH
  97. &outbitdeptharg,
  98. #endif
  99. &svcdecodingarg, &framestatsarg, NULL
  100. };
  101. #if CONFIG_VP8_DECODER
  102. static const arg_def_t addnoise_level =
  103. ARG_DEF(NULL, "noise-level", 1, "Enable VP8 postproc add noise");
  104. static const arg_def_t deblock =
  105. ARG_DEF(NULL, "deblock", 0, "Enable VP8 deblocking");
  106. static const arg_def_t demacroblock_level = ARG_DEF(
  107. NULL, "demacroblock-level", 1, "Enable VP8 demacroblocking, w/ level");
  108. static const arg_def_t mfqe =
  109. ARG_DEF(NULL, "mfqe", 0, "Enable multiframe quality enhancement");
  110. static const arg_def_t *vp8_pp_args[] = { &addnoise_level, &deblock,
  111. &demacroblock_level, &mfqe, NULL };
  112. #endif
  113. #if CONFIG_LIBYUV
  114. static INLINE int libyuv_scale(vpx_image_t *src, vpx_image_t *dst,
  115. FilterModeEnum mode) {
  116. #if CONFIG_VP9_HIGHBITDEPTH
  117. if (src->fmt == VPX_IMG_FMT_I42016) {
  118. assert(dst->fmt == VPX_IMG_FMT_I42016);
  119. return I420Scale_16(
  120. (uint16_t *)src->planes[VPX_PLANE_Y], src->stride[VPX_PLANE_Y] / 2,
  121. (uint16_t *)src->planes[VPX_PLANE_U], src->stride[VPX_PLANE_U] / 2,
  122. (uint16_t *)src->planes[VPX_PLANE_V], src->stride[VPX_PLANE_V] / 2,
  123. src->d_w, src->d_h, (uint16_t *)dst->planes[VPX_PLANE_Y],
  124. dst->stride[VPX_PLANE_Y] / 2, (uint16_t *)dst->planes[VPX_PLANE_U],
  125. dst->stride[VPX_PLANE_U] / 2, (uint16_t *)dst->planes[VPX_PLANE_V],
  126. dst->stride[VPX_PLANE_V] / 2, dst->d_w, dst->d_h, mode);
  127. }
  128. #endif
  129. assert(src->fmt == VPX_IMG_FMT_I420);
  130. assert(dst->fmt == VPX_IMG_FMT_I420);
  131. return I420Scale(src->planes[VPX_PLANE_Y], src->stride[VPX_PLANE_Y],
  132. src->planes[VPX_PLANE_U], src->stride[VPX_PLANE_U],
  133. src->planes[VPX_PLANE_V], src->stride[VPX_PLANE_V], src->d_w,
  134. src->d_h, dst->planes[VPX_PLANE_Y], dst->stride[VPX_PLANE_Y],
  135. dst->planes[VPX_PLANE_U], dst->stride[VPX_PLANE_U],
  136. dst->planes[VPX_PLANE_V], dst->stride[VPX_PLANE_V], dst->d_w,
  137. dst->d_h, mode);
  138. }
  139. #endif
  140. void usage_exit(void) {
  141. int i;
  142. fprintf(stderr,
  143. "Usage: %s <options> filename\n\n"
  144. "Options:\n",
  145. exec_name);
  146. arg_show_usage(stderr, all_args);
  147. #if CONFIG_VP8_DECODER
  148. fprintf(stderr, "\nVP8 Postprocessing Options:\n");
  149. arg_show_usage(stderr, vp8_pp_args);
  150. #endif
  151. fprintf(stderr,
  152. "\nOutput File Patterns:\n\n"
  153. " The -o argument specifies the name of the file(s) to "
  154. "write to. If the\n argument does not include any escape "
  155. "characters, the output will be\n written to a single file. "
  156. "Otherwise, the filename will be calculated by\n expanding "
  157. "the following escape characters:\n");
  158. fprintf(stderr,
  159. "\n\t%%w - Frame width"
  160. "\n\t%%h - Frame height"
  161. "\n\t%%<n> - Frame number, zero padded to <n> places (1..9)"
  162. "\n\n Pattern arguments are only supported in conjunction "
  163. "with the --yv12 and\n --i420 options. If the -o option is "
  164. "not specified, the output will be\n directed to stdout.\n");
  165. fprintf(stderr, "\nIncluded decoders:\n\n");
  166. for (i = 0; i < get_vpx_decoder_count(); ++i) {
  167. const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
  168. fprintf(stderr, " %-6s - %s\n", decoder->name,
  169. vpx_codec_iface_name(decoder->codec_interface()));
  170. }
  171. exit(EXIT_FAILURE);
  172. }
  173. static int raw_read_frame(FILE *infile, uint8_t **buffer, size_t *bytes_read,
  174. size_t *buffer_size) {
  175. char raw_hdr[RAW_FRAME_HDR_SZ];
  176. size_t frame_size = 0;
  177. if (fread(raw_hdr, RAW_FRAME_HDR_SZ, 1, infile) != 1) {
  178. if (!feof(infile)) warn("Failed to read RAW frame size\n");
  179. } else {
  180. const size_t kCorruptFrameThreshold = 256 * 1024 * 1024;
  181. const size_t kFrameTooSmallThreshold = 256 * 1024;
  182. frame_size = mem_get_le32(raw_hdr);
  183. if (frame_size > kCorruptFrameThreshold) {
  184. warn("Read invalid frame size (%u)\n", (unsigned int)frame_size);
  185. frame_size = 0;
  186. }
  187. if (frame_size < kFrameTooSmallThreshold) {
  188. warn("Warning: Read invalid frame size (%u) - not a raw file?\n",
  189. (unsigned int)frame_size);
  190. }
  191. if (frame_size > *buffer_size) {
  192. uint8_t *new_buf = realloc(*buffer, 2 * frame_size);
  193. if (new_buf) {
  194. *buffer = new_buf;
  195. *buffer_size = 2 * frame_size;
  196. } else {
  197. warn("Failed to allocate compressed data buffer\n");
  198. frame_size = 0;
  199. }
  200. }
  201. }
  202. if (!feof(infile)) {
  203. if (fread(*buffer, 1, frame_size, infile) != frame_size) {
  204. warn("Failed to read full frame\n");
  205. return 1;
  206. }
  207. *bytes_read = frame_size;
  208. }
  209. return 0;
  210. }
  211. static int read_frame(struct VpxDecInputContext *input, uint8_t **buf,
  212. size_t *bytes_in_buffer, size_t *buffer_size) {
  213. switch (input->vpx_input_ctx->file_type) {
  214. #if CONFIG_WEBM_IO
  215. case FILE_TYPE_WEBM:
  216. return webm_read_frame(input->webm_ctx, buf, bytes_in_buffer);
  217. #endif
  218. case FILE_TYPE_RAW:
  219. return raw_read_frame(input->vpx_input_ctx->file, buf, bytes_in_buffer,
  220. buffer_size);
  221. case FILE_TYPE_IVF:
  222. return ivf_read_frame(input->vpx_input_ctx->file, buf, bytes_in_buffer,
  223. buffer_size);
  224. default: return 1;
  225. }
  226. }
  227. static void update_image_md5(const vpx_image_t *img, const int planes[3],
  228. MD5Context *md5) {
  229. int i, y;
  230. for (i = 0; i < 3; ++i) {
  231. const int plane = planes[i];
  232. const unsigned char *buf = img->planes[plane];
  233. const int stride = img->stride[plane];
  234. const int w = vpx_img_plane_width(img, plane) *
  235. ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
  236. const int h = vpx_img_plane_height(img, plane);
  237. for (y = 0; y < h; ++y) {
  238. MD5Update(md5, buf, w);
  239. buf += stride;
  240. }
  241. }
  242. }
  243. static void write_image_file(const vpx_image_t *img, const int planes[3],
  244. FILE *file) {
  245. int i, y;
  246. #if CONFIG_VP9_HIGHBITDEPTH
  247. const int bytes_per_sample = ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
  248. #else
  249. const int bytes_per_sample = 1;
  250. #endif
  251. for (i = 0; i < 3; ++i) {
  252. const int plane = planes[i];
  253. const unsigned char *buf = img->planes[plane];
  254. const int stride = img->stride[plane];
  255. const int w = vpx_img_plane_width(img, plane);
  256. const int h = vpx_img_plane_height(img, plane);
  257. for (y = 0; y < h; ++y) {
  258. fwrite(buf, bytes_per_sample, w, file);
  259. buf += stride;
  260. }
  261. }
  262. }
  263. static int file_is_raw(struct VpxInputContext *input) {
  264. uint8_t buf[32];
  265. int is_raw = 0;
  266. vpx_codec_stream_info_t si;
  267. si.sz = sizeof(si);
  268. if (fread(buf, 1, 32, input->file) == 32) {
  269. int i;
  270. if (mem_get_le32(buf) < 256 * 1024 * 1024) {
  271. for (i = 0; i < get_vpx_decoder_count(); ++i) {
  272. const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
  273. if (!vpx_codec_peek_stream_info(decoder->codec_interface(), buf + 4,
  274. 32 - 4, &si)) {
  275. is_raw = 1;
  276. input->fourcc = decoder->fourcc;
  277. input->width = si.w;
  278. input->height = si.h;
  279. input->framerate.numerator = 30;
  280. input->framerate.denominator = 1;
  281. break;
  282. }
  283. }
  284. }
  285. }
  286. rewind(input->file);
  287. return is_raw;
  288. }
  289. static void show_progress(int frame_in, int frame_out, uint64_t dx_time) {
  290. fprintf(stderr,
  291. "%d decoded frames/%d showed frames in %" PRId64 " us (%.2f fps)\r",
  292. frame_in, frame_out, dx_time,
  293. (double)frame_out * 1000000.0 / (double)dx_time);
  294. }
  295. struct ExternalFrameBuffer {
  296. uint8_t *data;
  297. size_t size;
  298. int in_use;
  299. };
  300. struct ExternalFrameBufferList {
  301. int num_external_frame_buffers;
  302. struct ExternalFrameBuffer *ext_fb;
  303. };
  304. // Callback used by libvpx to request an external frame buffer. |cb_priv|
  305. // Application private data passed into the set function. |min_size| is the
  306. // minimum size in bytes needed to decode the next frame. |fb| pointer to the
  307. // frame buffer.
  308. static int get_vp9_frame_buffer(void *cb_priv, size_t min_size,
  309. vpx_codec_frame_buffer_t *fb) {
  310. int i;
  311. struct ExternalFrameBufferList *const ext_fb_list =
  312. (struct ExternalFrameBufferList *)cb_priv;
  313. if (ext_fb_list == NULL) return -1;
  314. // Find a free frame buffer.
  315. for (i = 0; i < ext_fb_list->num_external_frame_buffers; ++i) {
  316. if (!ext_fb_list->ext_fb[i].in_use) break;
  317. }
  318. if (i == ext_fb_list->num_external_frame_buffers) return -1;
  319. if (ext_fb_list->ext_fb[i].size < min_size) {
  320. free(ext_fb_list->ext_fb[i].data);
  321. ext_fb_list->ext_fb[i].data = (uint8_t *)calloc(min_size, sizeof(uint8_t));
  322. if (!ext_fb_list->ext_fb[i].data) return -1;
  323. ext_fb_list->ext_fb[i].size = min_size;
  324. }
  325. fb->data = ext_fb_list->ext_fb[i].data;
  326. fb->size = ext_fb_list->ext_fb[i].size;
  327. ext_fb_list->ext_fb[i].in_use = 1;
  328. // Set the frame buffer's private data to point at the external frame buffer.
  329. fb->priv = &ext_fb_list->ext_fb[i];
  330. return 0;
  331. }
  332. // Callback used by libvpx when there are no references to the frame buffer.
  333. // |cb_priv| user private data passed into the set function. |fb| pointer
  334. // to the frame buffer.
  335. static int release_vp9_frame_buffer(void *cb_priv,
  336. vpx_codec_frame_buffer_t *fb) {
  337. struct ExternalFrameBuffer *const ext_fb =
  338. (struct ExternalFrameBuffer *)fb->priv;
  339. (void)cb_priv;
  340. ext_fb->in_use = 0;
  341. return 0;
  342. }
  343. static void generate_filename(const char *pattern, char *out, size_t q_len,
  344. unsigned int d_w, unsigned int d_h,
  345. unsigned int frame_in) {
  346. const char *p = pattern;
  347. char *q = out;
  348. do {
  349. char *next_pat = strchr(p, '%');
  350. if (p == next_pat) {
  351. size_t pat_len;
  352. /* parse the pattern */
  353. q[q_len - 1] = '\0';
  354. switch (p[1]) {
  355. case 'w': snprintf(q, q_len - 1, "%d", d_w); break;
  356. case 'h': snprintf(q, q_len - 1, "%d", d_h); break;
  357. case '1': snprintf(q, q_len - 1, "%d", frame_in); break;
  358. case '2': snprintf(q, q_len - 1, "%02d", frame_in); break;
  359. case '3': snprintf(q, q_len - 1, "%03d", frame_in); break;
  360. case '4': snprintf(q, q_len - 1, "%04d", frame_in); break;
  361. case '5': snprintf(q, q_len - 1, "%05d", frame_in); break;
  362. case '6': snprintf(q, q_len - 1, "%06d", frame_in); break;
  363. case '7': snprintf(q, q_len - 1, "%07d", frame_in); break;
  364. case '8': snprintf(q, q_len - 1, "%08d", frame_in); break;
  365. case '9': snprintf(q, q_len - 1, "%09d", frame_in); break;
  366. default: die("Unrecognized pattern %%%c\n", p[1]); break;
  367. }
  368. pat_len = strlen(q);
  369. if (pat_len >= q_len - 1) die("Output filename too long.\n");
  370. q += pat_len;
  371. p += 2;
  372. q_len -= pat_len;
  373. } else {
  374. size_t copy_len;
  375. /* copy the next segment */
  376. if (!next_pat)
  377. copy_len = strlen(p);
  378. else
  379. copy_len = next_pat - p;
  380. if (copy_len >= q_len - 1) die("Output filename too long.\n");
  381. memcpy(q, p, copy_len);
  382. q[copy_len] = '\0';
  383. q += copy_len;
  384. p += copy_len;
  385. q_len -= copy_len;
  386. }
  387. } while (*p);
  388. }
  389. static int is_single_file(const char *outfile_pattern) {
  390. const char *p = outfile_pattern;
  391. do {
  392. p = strchr(p, '%');
  393. if (p && p[1] >= '1' && p[1] <= '9')
  394. return 0; // pattern contains sequence number, so it's not unique
  395. if (p) p++;
  396. } while (p);
  397. return 1;
  398. }
  399. static void print_md5(unsigned char digest[16], const char *filename) {
  400. int i;
  401. for (i = 0; i < 16; ++i) printf("%02x", digest[i]);
  402. printf(" %s\n", filename);
  403. }
  404. static FILE *open_outfile(const char *name) {
  405. if (strcmp("-", name) == 0) {
  406. set_binary_mode(stdout);
  407. return stdout;
  408. } else {
  409. FILE *file = fopen(name, "wb");
  410. if (!file) fatal("Failed to open output file '%s'", name);
  411. return file;
  412. }
  413. }
  414. #if CONFIG_VP9_HIGHBITDEPTH
  415. static int img_shifted_realloc_required(const vpx_image_t *img,
  416. const vpx_image_t *shifted,
  417. vpx_img_fmt_t required_fmt) {
  418. return img->d_w != shifted->d_w || img->d_h != shifted->d_h ||
  419. required_fmt != shifted->fmt;
  420. }
  421. #endif
  422. static int main_loop(int argc, const char **argv_) {
  423. vpx_codec_ctx_t decoder;
  424. char *fn = NULL;
  425. int i;
  426. int ret = EXIT_FAILURE;
  427. uint8_t *buf = NULL;
  428. size_t bytes_in_buffer = 0, buffer_size = 0;
  429. FILE *infile;
  430. int frame_in = 0, frame_out = 0, flipuv = 0, noblit = 0;
  431. int do_md5 = 0, progress = 0;
  432. int stop_after = 0, postproc = 0, summary = 0, quiet = 1;
  433. int arg_skip = 0;
  434. int ec_enabled = 0;
  435. int keep_going = 0;
  436. const VpxInterface *interface = NULL;
  437. const VpxInterface *fourcc_interface = NULL;
  438. uint64_t dx_time = 0;
  439. struct arg arg;
  440. char **argv, **argi, **argj;
  441. int single_file;
  442. int use_y4m = 1;
  443. int opt_yv12 = 0;
  444. int opt_i420 = 0;
  445. vpx_codec_dec_cfg_t cfg = { 0, 0, 0 };
  446. #if CONFIG_VP9_HIGHBITDEPTH
  447. unsigned int output_bit_depth = 0;
  448. #endif
  449. int svc_decoding = 0;
  450. int svc_spatial_layer = 0;
  451. #if CONFIG_VP8_DECODER
  452. vp8_postproc_cfg_t vp8_pp_cfg = { 0, 0, 0 };
  453. #endif
  454. int frames_corrupted = 0;
  455. int dec_flags = 0;
  456. int do_scale = 0;
  457. vpx_image_t *scaled_img = NULL;
  458. #if CONFIG_VP9_HIGHBITDEPTH
  459. vpx_image_t *img_shifted = NULL;
  460. #endif
  461. int frame_avail, got_data, flush_decoder = 0;
  462. int num_external_frame_buffers = 0;
  463. struct ExternalFrameBufferList ext_fb_list = { 0, NULL };
  464. const char *outfile_pattern = NULL;
  465. char outfile_name[PATH_MAX] = { 0 };
  466. FILE *outfile = NULL;
  467. FILE *framestats_file = NULL;
  468. MD5Context md5_ctx;
  469. unsigned char md5_digest[16];
  470. struct VpxDecInputContext input = { NULL, NULL };
  471. struct VpxInputContext vpx_input_ctx;
  472. #if CONFIG_WEBM_IO
  473. struct WebmInputContext webm_ctx;
  474. memset(&(webm_ctx), 0, sizeof(webm_ctx));
  475. input.webm_ctx = &webm_ctx;
  476. #endif
  477. input.vpx_input_ctx = &vpx_input_ctx;
  478. /* Parse command line */
  479. exec_name = argv_[0];
  480. argv = argv_dup(argc - 1, argv_ + 1);
  481. for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
  482. memset(&arg, 0, sizeof(arg));
  483. arg.argv_step = 1;
  484. if (arg_match(&arg, &codecarg, argi)) {
  485. interface = get_vpx_decoder_by_name(arg.val);
  486. if (!interface)
  487. die("Error: Unrecognized argument (%s) to --codec\n", arg.val);
  488. } else if (arg_match(&arg, &looparg, argi)) {
  489. // no-op
  490. } else if (arg_match(&arg, &outputfile, argi))
  491. outfile_pattern = arg.val;
  492. else if (arg_match(&arg, &use_yv12, argi)) {
  493. use_y4m = 0;
  494. flipuv = 1;
  495. opt_yv12 = 1;
  496. } else if (arg_match(&arg, &use_i420, argi)) {
  497. use_y4m = 0;
  498. flipuv = 0;
  499. opt_i420 = 1;
  500. } else if (arg_match(&arg, &rawvideo, argi)) {
  501. use_y4m = 0;
  502. } else if (arg_match(&arg, &flipuvarg, argi))
  503. flipuv = 1;
  504. else if (arg_match(&arg, &noblitarg, argi))
  505. noblit = 1;
  506. else if (arg_match(&arg, &progressarg, argi))
  507. progress = 1;
  508. else if (arg_match(&arg, &limitarg, argi))
  509. stop_after = arg_parse_uint(&arg);
  510. else if (arg_match(&arg, &skiparg, argi))
  511. arg_skip = arg_parse_uint(&arg);
  512. else if (arg_match(&arg, &postprocarg, argi))
  513. postproc = 1;
  514. else if (arg_match(&arg, &md5arg, argi))
  515. do_md5 = 1;
  516. else if (arg_match(&arg, &summaryarg, argi))
  517. summary = 1;
  518. else if (arg_match(&arg, &threadsarg, argi))
  519. cfg.threads = arg_parse_uint(&arg);
  520. #if CONFIG_VP9_DECODER
  521. else if (arg_match(&arg, &frameparallelarg, argi)) {
  522. /* ignored for compatibility */
  523. }
  524. #endif
  525. else if (arg_match(&arg, &verbosearg, argi))
  526. quiet = 0;
  527. else if (arg_match(&arg, &scalearg, argi))
  528. do_scale = 1;
  529. else if (arg_match(&arg, &fb_arg, argi))
  530. num_external_frame_buffers = arg_parse_uint(&arg);
  531. else if (arg_match(&arg, &continuearg, argi))
  532. keep_going = 1;
  533. #if CONFIG_VP9_HIGHBITDEPTH
  534. else if (arg_match(&arg, &outbitdeptharg, argi)) {
  535. output_bit_depth = arg_parse_uint(&arg);
  536. }
  537. #endif
  538. else if (arg_match(&arg, &svcdecodingarg, argi)) {
  539. svc_decoding = 1;
  540. svc_spatial_layer = arg_parse_uint(&arg);
  541. } else if (arg_match(&arg, &framestatsarg, argi)) {
  542. framestats_file = fopen(arg.val, "w");
  543. if (!framestats_file) {
  544. die("Error: Could not open --framestats file (%s) for writing.\n",
  545. arg.val);
  546. }
  547. }
  548. #if CONFIG_VP8_DECODER
  549. else if (arg_match(&arg, &addnoise_level, argi)) {
  550. postproc = 1;
  551. vp8_pp_cfg.post_proc_flag |= VP8_ADDNOISE;
  552. vp8_pp_cfg.noise_level = arg_parse_uint(&arg);
  553. } else if (arg_match(&arg, &demacroblock_level, argi)) {
  554. postproc = 1;
  555. vp8_pp_cfg.post_proc_flag |= VP8_DEMACROBLOCK;
  556. vp8_pp_cfg.deblocking_level = arg_parse_uint(&arg);
  557. } else if (arg_match(&arg, &deblock, argi)) {
  558. postproc = 1;
  559. vp8_pp_cfg.post_proc_flag |= VP8_DEBLOCK;
  560. } else if (arg_match(&arg, &mfqe, argi)) {
  561. postproc = 1;
  562. vp8_pp_cfg.post_proc_flag |= VP8_MFQE;
  563. } else if (arg_match(&arg, &error_concealment, argi)) {
  564. ec_enabled = 1;
  565. }
  566. #endif // CONFIG_VP8_DECODER
  567. else
  568. argj++;
  569. }
  570. /* Check for unrecognized options */
  571. for (argi = argv; *argi; argi++)
  572. if (argi[0][0] == '-' && strlen(argi[0]) > 1)
  573. die("Error: Unrecognized option %s\n", *argi);
  574. /* Handle non-option arguments */
  575. fn = argv[0];
  576. if (!fn) {
  577. free(argv);
  578. usage_exit();
  579. }
  580. /* Open file */
  581. infile = strcmp(fn, "-") ? fopen(fn, "rb") : set_binary_mode(stdin);
  582. if (!infile) {
  583. fatal("Failed to open input file '%s'", strcmp(fn, "-") ? fn : "stdin");
  584. }
  585. #if CONFIG_OS_SUPPORT
  586. /* Make sure we don't dump to the terminal, unless forced to with -o - */
  587. if (!outfile_pattern && isatty(fileno(stdout)) && !do_md5 && !noblit) {
  588. fprintf(stderr,
  589. "Not dumping raw video to your terminal. Use '-o -' to "
  590. "override.\n");
  591. return EXIT_FAILURE;
  592. }
  593. #endif
  594. input.vpx_input_ctx->file = infile;
  595. if (file_is_ivf(input.vpx_input_ctx))
  596. input.vpx_input_ctx->file_type = FILE_TYPE_IVF;
  597. #if CONFIG_WEBM_IO
  598. else if (file_is_webm(input.webm_ctx, input.vpx_input_ctx))
  599. input.vpx_input_ctx->file_type = FILE_TYPE_WEBM;
  600. #endif
  601. else if (file_is_raw(input.vpx_input_ctx))
  602. input.vpx_input_ctx->file_type = FILE_TYPE_RAW;
  603. else {
  604. fprintf(stderr, "Unrecognized input file type.\n");
  605. #if !CONFIG_WEBM_IO
  606. fprintf(stderr, "vpxdec was built without WebM container support.\n");
  607. #endif
  608. return EXIT_FAILURE;
  609. }
  610. outfile_pattern = outfile_pattern ? outfile_pattern : "-";
  611. single_file = is_single_file(outfile_pattern);
  612. if (!noblit && single_file) {
  613. generate_filename(outfile_pattern, outfile_name, PATH_MAX,
  614. vpx_input_ctx.width, vpx_input_ctx.height, 0);
  615. if (do_md5)
  616. MD5Init(&md5_ctx);
  617. else
  618. outfile = open_outfile(outfile_name);
  619. }
  620. if (use_y4m && !noblit) {
  621. if (!single_file) {
  622. fprintf(stderr,
  623. "YUV4MPEG2 not supported with output patterns,"
  624. " try --i420 or --yv12 or --rawvideo.\n");
  625. return EXIT_FAILURE;
  626. }
  627. #if CONFIG_WEBM_IO
  628. if (vpx_input_ctx.file_type == FILE_TYPE_WEBM) {
  629. if (webm_guess_framerate(input.webm_ctx, input.vpx_input_ctx)) {
  630. fprintf(stderr,
  631. "Failed to guess framerate -- error parsing "
  632. "webm file?\n");
  633. return EXIT_FAILURE;
  634. }
  635. }
  636. #endif
  637. }
  638. fourcc_interface = get_vpx_decoder_by_fourcc(vpx_input_ctx.fourcc);
  639. if (interface && fourcc_interface && interface != fourcc_interface)
  640. warn("Header indicates codec: %s\n", fourcc_interface->name);
  641. else
  642. interface = fourcc_interface;
  643. if (!interface) interface = get_vpx_decoder_by_index(0);
  644. dec_flags = (postproc ? VPX_CODEC_USE_POSTPROC : 0) |
  645. (ec_enabled ? VPX_CODEC_USE_ERROR_CONCEALMENT : 0);
  646. if (vpx_codec_dec_init(&decoder, interface->codec_interface(), &cfg,
  647. dec_flags)) {
  648. fprintf(stderr, "Failed to initialize decoder: %s\n",
  649. vpx_codec_error(&decoder));
  650. goto fail2;
  651. }
  652. if (svc_decoding) {
  653. if (vpx_codec_control(&decoder, VP9_DECODE_SVC_SPATIAL_LAYER,
  654. svc_spatial_layer)) {
  655. fprintf(stderr, "Failed to set spatial layer for svc decode: %s\n",
  656. vpx_codec_error(&decoder));
  657. goto fail;
  658. }
  659. }
  660. if (!quiet) fprintf(stderr, "%s\n", decoder.name);
  661. #if CONFIG_VP8_DECODER
  662. if (vp8_pp_cfg.post_proc_flag &&
  663. vpx_codec_control(&decoder, VP8_SET_POSTPROC, &vp8_pp_cfg)) {
  664. fprintf(stderr, "Failed to configure postproc: %s\n",
  665. vpx_codec_error(&decoder));
  666. goto fail;
  667. }
  668. #endif
  669. if (arg_skip) fprintf(stderr, "Skipping first %d frames.\n", arg_skip);
  670. while (arg_skip) {
  671. if (read_frame(&input, &buf, &bytes_in_buffer, &buffer_size)) break;
  672. arg_skip--;
  673. }
  674. if (num_external_frame_buffers > 0) {
  675. ext_fb_list.num_external_frame_buffers = num_external_frame_buffers;
  676. ext_fb_list.ext_fb = (struct ExternalFrameBuffer *)calloc(
  677. num_external_frame_buffers, sizeof(*ext_fb_list.ext_fb));
  678. if (vpx_codec_set_frame_buffer_functions(&decoder, get_vp9_frame_buffer,
  679. release_vp9_frame_buffer,
  680. &ext_fb_list)) {
  681. fprintf(stderr, "Failed to configure external frame buffers: %s\n",
  682. vpx_codec_error(&decoder));
  683. goto fail;
  684. }
  685. }
  686. frame_avail = 1;
  687. got_data = 0;
  688. if (framestats_file) fprintf(framestats_file, "bytes,qp\n");
  689. /* Decode file */
  690. while (frame_avail || got_data) {
  691. vpx_codec_iter_t iter = NULL;
  692. vpx_image_t *img;
  693. struct vpx_usec_timer timer;
  694. int corrupted = 0;
  695. frame_avail = 0;
  696. if (!stop_after || frame_in < stop_after) {
  697. if (!read_frame(&input, &buf, &bytes_in_buffer, &buffer_size)) {
  698. frame_avail = 1;
  699. frame_in++;
  700. vpx_usec_timer_start(&timer);
  701. if (vpx_codec_decode(&decoder, buf, (unsigned int)bytes_in_buffer, NULL,
  702. 0)) {
  703. const char *detail = vpx_codec_error_detail(&decoder);
  704. warn("Failed to decode frame %d: %s", frame_in,
  705. vpx_codec_error(&decoder));
  706. if (detail) warn("Additional information: %s", detail);
  707. corrupted = 1;
  708. if (!keep_going) goto fail;
  709. }
  710. if (framestats_file) {
  711. int qp;
  712. if (vpx_codec_control(&decoder, VPXD_GET_LAST_QUANTIZER, &qp)) {
  713. warn("Failed VPXD_GET_LAST_QUANTIZER: %s",
  714. vpx_codec_error(&decoder));
  715. if (!keep_going) goto fail;
  716. }
  717. fprintf(framestats_file, "%d,%d\n", (int)bytes_in_buffer, qp);
  718. }
  719. vpx_usec_timer_mark(&timer);
  720. dx_time += vpx_usec_timer_elapsed(&timer);
  721. } else {
  722. flush_decoder = 1;
  723. }
  724. } else {
  725. flush_decoder = 1;
  726. }
  727. vpx_usec_timer_start(&timer);
  728. if (flush_decoder) {
  729. // Flush the decoder in frame parallel decode.
  730. if (vpx_codec_decode(&decoder, NULL, 0, NULL, 0)) {
  731. warn("Failed to flush decoder: %s", vpx_codec_error(&decoder));
  732. corrupted = 1;
  733. if (!keep_going) goto fail;
  734. }
  735. }
  736. got_data = 0;
  737. if ((img = vpx_codec_get_frame(&decoder, &iter))) {
  738. ++frame_out;
  739. got_data = 1;
  740. }
  741. vpx_usec_timer_mark(&timer);
  742. dx_time += (unsigned int)vpx_usec_timer_elapsed(&timer);
  743. if (!corrupted &&
  744. vpx_codec_control(&decoder, VP8D_GET_FRAME_CORRUPTED, &corrupted)) {
  745. warn("Failed VP8_GET_FRAME_CORRUPTED: %s", vpx_codec_error(&decoder));
  746. if (!keep_going) goto fail;
  747. }
  748. frames_corrupted += corrupted;
  749. if (progress) show_progress(frame_in, frame_out, dx_time);
  750. if (!noblit && img) {
  751. const int PLANES_YUV[] = { VPX_PLANE_Y, VPX_PLANE_U, VPX_PLANE_V };
  752. const int PLANES_YVU[] = { VPX_PLANE_Y, VPX_PLANE_V, VPX_PLANE_U };
  753. const int *planes = flipuv ? PLANES_YVU : PLANES_YUV;
  754. if (do_scale) {
  755. if (frame_out == 1) {
  756. // If the output frames are to be scaled to a fixed display size then
  757. // use the width and height specified in the container. If either of
  758. // these is set to 0, use the display size set in the first frame
  759. // header. If that is unavailable, use the raw decoded size of the
  760. // first decoded frame.
  761. int render_width = vpx_input_ctx.width;
  762. int render_height = vpx_input_ctx.height;
  763. if (!render_width || !render_height) {
  764. int render_size[2];
  765. if (vpx_codec_control(&decoder, VP9D_GET_DISPLAY_SIZE,
  766. render_size)) {
  767. // As last resort use size of first frame as display size.
  768. render_width = img->d_w;
  769. render_height = img->d_h;
  770. } else {
  771. render_width = render_size[0];
  772. render_height = render_size[1];
  773. }
  774. }
  775. scaled_img =
  776. vpx_img_alloc(NULL, img->fmt, render_width, render_height, 16);
  777. scaled_img->bit_depth = img->bit_depth;
  778. }
  779. if (img->d_w != scaled_img->d_w || img->d_h != scaled_img->d_h) {
  780. #if CONFIG_LIBYUV
  781. libyuv_scale(img, scaled_img, kFilterBox);
  782. img = scaled_img;
  783. #else
  784. fprintf(stderr,
  785. "Failed to scale output frame: %s.\n"
  786. "Scaling is disabled in this configuration. "
  787. "To enable scaling, configure with --enable-libyuv\n",
  788. vpx_codec_error(&decoder));
  789. goto fail;
  790. #endif
  791. }
  792. }
  793. #if CONFIG_VP9_HIGHBITDEPTH
  794. // Default to codec bit depth if output bit depth not set
  795. if (!output_bit_depth && single_file && !do_md5) {
  796. output_bit_depth = img->bit_depth;
  797. }
  798. // Shift up or down if necessary
  799. if (output_bit_depth != 0 && output_bit_depth != img->bit_depth) {
  800. const vpx_img_fmt_t shifted_fmt =
  801. output_bit_depth == 8
  802. ? img->fmt ^ (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH)
  803. : img->fmt | VPX_IMG_FMT_HIGHBITDEPTH;
  804. if (img_shifted &&
  805. img_shifted_realloc_required(img, img_shifted, shifted_fmt)) {
  806. vpx_img_free(img_shifted);
  807. img_shifted = NULL;
  808. }
  809. if (!img_shifted) {
  810. img_shifted =
  811. vpx_img_alloc(NULL, shifted_fmt, img->d_w, img->d_h, 16);
  812. img_shifted->bit_depth = output_bit_depth;
  813. }
  814. if (output_bit_depth > img->bit_depth) {
  815. vpx_img_upshift(img_shifted, img, output_bit_depth - img->bit_depth);
  816. } else {
  817. vpx_img_downshift(img_shifted, img,
  818. img->bit_depth - output_bit_depth);
  819. }
  820. img = img_shifted;
  821. }
  822. #endif
  823. if (single_file) {
  824. if (use_y4m) {
  825. char buf[Y4M_BUFFER_SIZE] = { 0 };
  826. size_t len = 0;
  827. if (img->fmt == VPX_IMG_FMT_I440 || img->fmt == VPX_IMG_FMT_I44016) {
  828. fprintf(stderr, "Cannot produce y4m output for 440 sampling.\n");
  829. goto fail;
  830. }
  831. if (frame_out == 1) {
  832. // Y4M file header
  833. len = y4m_write_file_header(
  834. buf, sizeof(buf), vpx_input_ctx.width, vpx_input_ctx.height,
  835. &vpx_input_ctx.framerate, img->fmt, img->bit_depth);
  836. if (do_md5) {
  837. MD5Update(&md5_ctx, (md5byte *)buf, (unsigned int)len);
  838. } else {
  839. fputs(buf, outfile);
  840. }
  841. }
  842. // Y4M frame header
  843. len = y4m_write_frame_header(buf, sizeof(buf));
  844. if (do_md5) {
  845. MD5Update(&md5_ctx, (md5byte *)buf, (unsigned int)len);
  846. } else {
  847. fputs(buf, outfile);
  848. }
  849. } else {
  850. if (frame_out == 1) {
  851. // Check if --yv12 or --i420 options are consistent with the
  852. // bit-stream decoded
  853. if (opt_i420) {
  854. if (img->fmt != VPX_IMG_FMT_I420 &&
  855. img->fmt != VPX_IMG_FMT_I42016) {
  856. fprintf(stderr, "Cannot produce i420 output for bit-stream.\n");
  857. goto fail;
  858. }
  859. }
  860. if (opt_yv12) {
  861. if ((img->fmt != VPX_IMG_FMT_I420 &&
  862. img->fmt != VPX_IMG_FMT_YV12) ||
  863. img->bit_depth != 8) {
  864. fprintf(stderr, "Cannot produce yv12 output for bit-stream.\n");
  865. goto fail;
  866. }
  867. }
  868. }
  869. }
  870. if (do_md5) {
  871. update_image_md5(img, planes, &md5_ctx);
  872. } else {
  873. if (!corrupted) write_image_file(img, planes, outfile);
  874. }
  875. } else {
  876. generate_filename(outfile_pattern, outfile_name, PATH_MAX, img->d_w,
  877. img->d_h, frame_in);
  878. if (do_md5) {
  879. MD5Init(&md5_ctx);
  880. update_image_md5(img, planes, &md5_ctx);
  881. MD5Final(md5_digest, &md5_ctx);
  882. print_md5(md5_digest, outfile_name);
  883. } else {
  884. outfile = open_outfile(outfile_name);
  885. write_image_file(img, planes, outfile);
  886. fclose(outfile);
  887. }
  888. }
  889. }
  890. }
  891. if (summary || progress) {
  892. show_progress(frame_in, frame_out, dx_time);
  893. fprintf(stderr, "\n");
  894. }
  895. if (frames_corrupted) {
  896. fprintf(stderr, "WARNING: %d frames corrupted.\n", frames_corrupted);
  897. } else {
  898. ret = EXIT_SUCCESS;
  899. }
  900. fail:
  901. if (vpx_codec_destroy(&decoder)) {
  902. fprintf(stderr, "Failed to destroy decoder: %s\n",
  903. vpx_codec_error(&decoder));
  904. }
  905. fail2:
  906. if (!noblit && single_file) {
  907. if (do_md5) {
  908. MD5Final(md5_digest, &md5_ctx);
  909. print_md5(md5_digest, outfile_name);
  910. } else {
  911. fclose(outfile);
  912. }
  913. }
  914. #if CONFIG_WEBM_IO
  915. if (input.vpx_input_ctx->file_type == FILE_TYPE_WEBM)
  916. webm_free(input.webm_ctx);
  917. #endif
  918. if (input.vpx_input_ctx->file_type != FILE_TYPE_WEBM) free(buf);
  919. if (scaled_img) vpx_img_free(scaled_img);
  920. #if CONFIG_VP9_HIGHBITDEPTH
  921. if (img_shifted) vpx_img_free(img_shifted);
  922. #endif
  923. for (i = 0; i < ext_fb_list.num_external_frame_buffers; ++i) {
  924. free(ext_fb_list.ext_fb[i].data);
  925. }
  926. free(ext_fb_list.ext_fb);
  927. fclose(infile);
  928. if (framestats_file) fclose(framestats_file);
  929. free(argv);
  930. return ret;
  931. }
  932. int main(int argc, const char **argv_) {
  933. unsigned int loops = 1, i;
  934. char **argv, **argi, **argj;
  935. struct arg arg;
  936. int error = 0;
  937. argv = argv_dup(argc - 1, argv_ + 1);
  938. for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
  939. memset(&arg, 0, sizeof(arg));
  940. arg.argv_step = 1;
  941. if (arg_match(&arg, &looparg, argi)) {
  942. loops = arg_parse_uint(&arg);
  943. break;
  944. }
  945. }
  946. free(argv);
  947. for (i = 0; !error && i < loops; i++) error = main_loop(argc, argv_);
  948. return error;
  949. }