OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved. | 2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 29 matching lines...) Expand all Loading... |
40 #endif | 40 #endif |
41 #include "./y4menc.h" | 41 #include "./y4menc.h" |
42 | 42 |
43 static const char *exec_name; | 43 static const char *exec_name; |
44 | 44 |
45 struct VpxDecInputContext { | 45 struct VpxDecInputContext { |
46 struct VpxInputContext *vpx_input_ctx; | 46 struct VpxInputContext *vpx_input_ctx; |
47 struct WebmInputContext *webm_ctx; | 47 struct WebmInputContext *webm_ctx; |
48 }; | 48 }; |
49 | 49 |
50 static const arg_def_t looparg = ARG_DEF(NULL, "loops", 1, | 50 static const arg_def_t looparg = ARG_DEF( |
51 "Number of times to decode the file"); | 51 NULL, "loops", 1, "Number of times to decode the file"); |
52 static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1, | 52 static const arg_def_t codecarg = ARG_DEF( |
53 "Codec to use"); | 53 NULL, "codec", 1, "Codec to use"); |
54 static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0, | 54 static const arg_def_t use_yv12 = ARG_DEF( |
55 "Output raw YV12 frames"); | 55 NULL, "yv12", 0, "Output raw YV12 frames"); |
56 static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0, | 56 static const arg_def_t use_i420 = ARG_DEF( |
57 "Output raw I420 frames"); | 57 NULL, "i420", 0, "Output raw I420 frames"); |
58 static const arg_def_t flipuvarg = ARG_DEF(NULL, "flipuv", 0, | 58 static const arg_def_t flipuvarg = ARG_DEF( |
59 "Flip the chroma planes in the output
"); | 59 NULL, "flipuv", 0, "Flip the chroma planes in the output"); |
60 static const arg_def_t rawvideo = ARG_DEF(NULL, "rawvideo", 0, | 60 static const arg_def_t rawvideo = ARG_DEF( |
61 "Output raw YUV frames"); | 61 NULL, "rawvideo", 0, "Output raw YUV frames"); |
62 static const arg_def_t noblitarg = ARG_DEF(NULL, "noblit", 0, | 62 static const arg_def_t noblitarg = ARG_DEF( |
63 "Don't process the decoded frames"); | 63 NULL, "noblit", 0, "Don't process the decoded frames"); |
64 static const arg_def_t progressarg = ARG_DEF(NULL, "progress", 0, | 64 static const arg_def_t progressarg = ARG_DEF( |
65 "Show progress after each frame dec
odes"); | 65 NULL, "progress", 0, "Show progress after each frame decodes"); |
66 static const arg_def_t limitarg = ARG_DEF(NULL, "limit", 1, | 66 static const arg_def_t limitarg = ARG_DEF( |
67 "Stop decoding after n frames"); | 67 NULL, "limit", 1, "Stop decoding after n frames"); |
68 static const arg_def_t skiparg = ARG_DEF(NULL, "skip", 1, | 68 static const arg_def_t skiparg = ARG_DEF( |
69 "Skip the first n input frames"); | 69 NULL, "skip", 1, "Skip the first n input frames"); |
70 static const arg_def_t postprocarg = ARG_DEF(NULL, "postproc", 0, | 70 static const arg_def_t postprocarg = ARG_DEF( |
71 "Postprocess decoded frames"); | 71 NULL, "postproc", 0, "Postprocess decoded frames"); |
72 static const arg_def_t summaryarg = ARG_DEF(NULL, "summary", 0, | 72 static const arg_def_t summaryarg = ARG_DEF( |
73 "Show timing summary"); | 73 NULL, "summary", 0, "Show timing summary"); |
74 static const arg_def_t outputfile = ARG_DEF("o", "output", 1, | 74 static const arg_def_t outputfile = ARG_DEF( |
75 "Output file name pattern (see below
)"); | 75 "o", "output", 1, "Output file name pattern (see below)"); |
76 static const arg_def_t threadsarg = ARG_DEF("t", "threads", 1, | 76 static const arg_def_t threadsarg = ARG_DEF( |
77 "Max threads to use"); | 77 "t", "threads", 1, "Max threads to use"); |
78 static const arg_def_t verbosearg = ARG_DEF("v", "verbose", 0, | 78 static const arg_def_t verbosearg = ARG_DEF( |
79 "Show version string"); | 79 "v", "verbose", 0, "Show version string"); |
80 static const arg_def_t error_concealment = ARG_DEF(NULL, "error-concealment", 0, | 80 static const arg_def_t error_concealment = ARG_DEF( |
81 "Enable decoder error-conceal
ment"); | 81 NULL, "error-concealment", 0, "Enable decoder error-concealment"); |
82 static const arg_def_t scalearg = ARG_DEF("S", "scale", 0, | 82 static const arg_def_t scalearg = ARG_DEF( |
83 "Scale output frames uniformly"); | 83 "S", "scale", 0, "Scale output frames uniformly"); |
84 static const arg_def_t continuearg = | 84 static const arg_def_t continuearg = ARG_DEF( |
85 ARG_DEF("k", "keep-going", 0, "(debug) Continue decoding after error"); | 85 "k", "keep-going", 0, "(debug) Continue decoding after error"); |
86 | 86 static const arg_def_t fb_arg = ARG_DEF( |
87 static const arg_def_t fb_arg = | 87 NULL, "frame-buffers", 1, "Number of frame buffers to use"); |
88 ARG_DEF(NULL, "frame-buffers", 1, "Number of frame buffers to use"); | 88 static const arg_def_t md5arg = ARG_DEF( |
89 | 89 NULL, "md5", 0, "Compute the MD5 sum of the decoded frame"); |
90 static const arg_def_t md5arg = ARG_DEF(NULL, "md5", 0, | |
91 "Compute the MD5 sum of the decoded fram
e"); | |
92 #if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH | 90 #if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH |
93 static const arg_def_t outbitdeptharg = ARG_DEF( | 91 static const arg_def_t outbitdeptharg = ARG_DEF( |
94 NULL, "output-bit-depth", 1, | 92 NULL, "output-bit-depth", 1, "Output bit-depth for decoded frames"); |
95 "Output bit-depth for decoded frames"); | |
96 #endif | 93 #endif |
97 | 94 |
98 static const arg_def_t *all_args[] = { | 95 static const arg_def_t *all_args[] = { |
99 &codecarg, &use_yv12, &use_i420, &flipuvarg, &rawvideo, &noblitarg, | 96 &codecarg, &use_yv12, &use_i420, &flipuvarg, &rawvideo, &noblitarg, |
100 &progressarg, &limitarg, &skiparg, &postprocarg, &summaryarg, &outputfile, | 97 &progressarg, &limitarg, &skiparg, &postprocarg, &summaryarg, &outputfile, |
101 &threadsarg, &verbosearg, &scalearg, &fb_arg, | 98 &threadsarg, &verbosearg, &scalearg, &fb_arg, |
102 &md5arg, &error_concealment, &continuearg, | 99 &md5arg, &error_concealment, &continuearg, |
103 #if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH | 100 #if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH |
104 &outbitdeptharg, | 101 &outbitdeptharg, |
105 #endif | 102 #endif |
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 return stdout; | 517 return stdout; |
521 } else { | 518 } else { |
522 FILE *file = fopen(name, "wb"); | 519 FILE *file = fopen(name, "wb"); |
523 if (!file) | 520 if (!file) |
524 fatal("Failed to output file %s", name); | 521 fatal("Failed to output file %s", name); |
525 return file; | 522 return file; |
526 } | 523 } |
527 } | 524 } |
528 | 525 |
529 #if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH | 526 #if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH |
530 static void high_img_upshift(vpx_image_t *dst, vpx_image_t *src, | 527 static int img_shifted_realloc_required(const vpx_image_t *img, |
531 int input_shift) { | 528 const vpx_image_t *shifted, |
532 const int offset = input_shift > 0 ? (1 << (input_shift - 1)) : 0; | 529 vpx_img_fmt_t required_fmt) { |
533 int plane; | 530 return img->d_w != shifted->d_w || |
534 if (dst->d_w != src->d_w || dst->d_h != src->d_h || | 531 img->d_h != shifted->d_h || |
535 dst->x_chroma_shift != src->x_chroma_shift || | 532 required_fmt != shifted->fmt; |
536 dst->y_chroma_shift != src->y_chroma_shift || | |
537 dst->fmt != src->fmt || input_shift < 0) { | |
538 fatal("Unsupported image conversion"); | |
539 } | |
540 switch (src->fmt) { | |
541 case VPX_IMG_FMT_I42016: | |
542 case VPX_IMG_FMT_I42216: | |
543 case VPX_IMG_FMT_I44416: | |
544 break; | |
545 default: | |
546 fatal("Unsupported image conversion"); | |
547 break; | |
548 } | |
549 for (plane = 0; plane < 3; plane++) { | |
550 int w = src->d_w; | |
551 int h = src->d_h; | |
552 int x, y; | |
553 if (plane) { | |
554 w >>= src->x_chroma_shift; | |
555 h >>= src->y_chroma_shift; | |
556 } | |
557 for (y = 0; y < h; y++) { | |
558 uint16_t *p_src = (uint16_t *)(src->planes[plane] + | |
559 y * src->stride[plane]); | |
560 uint16_t *p_dst = (uint16_t *)(dst->planes[plane] + | |
561 y * dst->stride[plane]); | |
562 for (x = 0; x < w; x++) | |
563 *p_dst++ = (*p_src++ << input_shift) + offset; | |
564 } | |
565 } | |
566 } | |
567 | |
568 static void low_img_upshift(vpx_image_t *dst, vpx_image_t *src, | |
569 int input_shift) { | |
570 const int offset = input_shift > 0 ? (1 << (input_shift - 1)) : 0; | |
571 int plane; | |
572 if (dst->d_w != src->d_w || dst->d_h != src->d_h || | |
573 dst->x_chroma_shift != src->x_chroma_shift || | |
574 dst->y_chroma_shift != src->y_chroma_shift || | |
575 dst->fmt != src->fmt + VPX_IMG_FMT_HIGHBITDEPTH || | |
576 input_shift < 0) { | |
577 fatal("Unsupported image conversion"); | |
578 } | |
579 switch (src->fmt) { | |
580 case VPX_IMG_FMT_I420: | |
581 case VPX_IMG_FMT_I422: | |
582 case VPX_IMG_FMT_I444: | |
583 break; | |
584 default: | |
585 fatal("Unsupported image conversion"); | |
586 break; | |
587 } | |
588 for (plane = 0; plane < 3; plane++) { | |
589 int w = src->d_w; | |
590 int h = src->d_h; | |
591 int x, y; | |
592 if (plane) { | |
593 w >>= src->x_chroma_shift; | |
594 h >>= src->y_chroma_shift; | |
595 } | |
596 for (y = 0; y < h; y++) { | |
597 uint8_t *p_src = src->planes[plane] + y * src->stride[plane]; | |
598 uint16_t *p_dst = (uint16_t *)(dst->planes[plane] + | |
599 y * dst->stride[plane]); | |
600 for (x = 0; x < w; x++) { | |
601 *p_dst++ = (*p_src++ << input_shift) + offset; | |
602 } | |
603 } | |
604 } | |
605 } | |
606 | |
607 static void img_upshift(vpx_image_t *dst, vpx_image_t *src, | |
608 int input_shift) { | |
609 if (src->fmt & VPX_IMG_FMT_HIGHBITDEPTH) { | |
610 high_img_upshift(dst, src, input_shift); | |
611 } else { | |
612 low_img_upshift(dst, src, input_shift); | |
613 } | |
614 } | |
615 | |
616 static void high_img_downshift(vpx_image_t *dst, vpx_image_t *src, | |
617 int down_shift) { | |
618 int plane; | |
619 if (dst->d_w != src->d_w || dst->d_h != src->d_h || | |
620 dst->x_chroma_shift != src->x_chroma_shift || | |
621 dst->y_chroma_shift != src->y_chroma_shift || | |
622 dst->fmt != src->fmt || down_shift < 0) { | |
623 fatal("Unsupported image conversion"); | |
624 } | |
625 switch (src->fmt) { | |
626 case VPX_IMG_FMT_I42016: | |
627 case VPX_IMG_FMT_I42216: | |
628 case VPX_IMG_FMT_I44416: | |
629 break; | |
630 default: | |
631 fatal("Unsupported image conversion"); | |
632 break; | |
633 } | |
634 for (plane = 0; plane < 3; plane++) { | |
635 int w = src->d_w; | |
636 int h = src->d_h; | |
637 int x, y; | |
638 if (plane) { | |
639 w >>= src->x_chroma_shift; | |
640 h >>= src->y_chroma_shift; | |
641 } | |
642 for (y = 0; y < h; y++) { | |
643 uint16_t *p_src = (uint16_t *)(src->planes[plane] + | |
644 y * src->stride[plane]); | |
645 uint16_t *p_dst = (uint16_t *)(dst->planes[plane] + | |
646 y * dst->stride[plane]); | |
647 for (x = 0; x < w; x++) | |
648 *p_dst++ = *p_src++ >> down_shift; | |
649 } | |
650 } | |
651 } | |
652 | |
653 static void low_img_downshift(vpx_image_t *dst, vpx_image_t *src, | |
654 int down_shift) { | |
655 int plane; | |
656 if (dst->d_w != src->d_w || dst->d_h != src->d_h || | |
657 dst->x_chroma_shift != src->x_chroma_shift || | |
658 dst->y_chroma_shift != src->y_chroma_shift || | |
659 src->fmt != dst->fmt + VPX_IMG_FMT_HIGHBITDEPTH || | |
660 down_shift < 0) { | |
661 fatal("Unsupported image conversion"); | |
662 } | |
663 switch (dst->fmt) { | |
664 case VPX_IMG_FMT_I420: | |
665 case VPX_IMG_FMT_I422: | |
666 case VPX_IMG_FMT_I444: | |
667 break; | |
668 default: | |
669 fatal("Unsupported image conversion"); | |
670 break; | |
671 } | |
672 for (plane = 0; plane < 3; plane++) { | |
673 int w = src->d_w; | |
674 int h = src->d_h; | |
675 int x, y; | |
676 if (plane) { | |
677 w >>= src->x_chroma_shift; | |
678 h >>= src->y_chroma_shift; | |
679 } | |
680 for (y = 0; y < h; y++) { | |
681 uint16_t *p_src = (uint16_t *)(src->planes[plane] + | |
682 y * src->stride[plane]); | |
683 uint8_t *p_dst = dst->planes[plane] + y * dst->stride[plane]; | |
684 for (x = 0; x < w; x++) { | |
685 *p_dst++ = *p_src++ >> down_shift; | |
686 } | |
687 } | |
688 } | |
689 } | |
690 | |
691 static void img_downshift(vpx_image_t *dst, vpx_image_t *src, | |
692 int down_shift) { | |
693 if (dst->fmt & VPX_IMG_FMT_HIGHBITDEPTH) { | |
694 high_img_downshift(dst, src, down_shift); | |
695 } else { | |
696 low_img_downshift(dst, src, down_shift); | |
697 } | |
698 } | 533 } |
699 #endif | 534 #endif |
700 | 535 |
701 int main_loop(int argc, const char **argv_) { | 536 int main_loop(int argc, const char **argv_) { |
702 vpx_codec_ctx_t decoder; | 537 vpx_codec_ctx_t decoder; |
703 char *fn = NULL; | 538 char *fn = NULL; |
704 int i; | 539 int i; |
705 uint8_t *buf = NULL; | 540 uint8_t *buf = NULL; |
706 size_t bytes_in_buffer = 0, buffer_size = 0; | 541 size_t bytes_in_buffer = 0, buffer_size = 0; |
707 FILE *infile; | 542 FILE *infile; |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
926 vpx_input_ctx.width, vpx_input_ctx.height, 0); | 761 vpx_input_ctx.width, vpx_input_ctx.height, 0); |
927 if (do_md5) | 762 if (do_md5) |
928 MD5Init(&md5_ctx); | 763 MD5Init(&md5_ctx); |
929 else | 764 else |
930 outfile = open_outfile(outfile_name); | 765 outfile = open_outfile(outfile_name); |
931 } | 766 } |
932 | 767 |
933 if (use_y4m && !noblit) { | 768 if (use_y4m && !noblit) { |
934 if (!single_file) { | 769 if (!single_file) { |
935 fprintf(stderr, "YUV4MPEG2 not supported with output patterns," | 770 fprintf(stderr, "YUV4MPEG2 not supported with output patterns," |
936 " try --i420 or --yv12.\n"); | 771 " try --i420 or --yv12 or --rawvideo.\n"); |
937 return EXIT_FAILURE; | 772 return EXIT_FAILURE; |
938 } | 773 } |
939 | 774 |
940 #if CONFIG_WEBM_IO | 775 #if CONFIG_WEBM_IO |
941 if (vpx_input_ctx.file_type == FILE_TYPE_WEBM) { | 776 if (vpx_input_ctx.file_type == FILE_TYPE_WEBM) { |
942 if (webm_guess_framerate(input.webm_ctx, input.vpx_input_ctx)) { | 777 if (webm_guess_framerate(input.webm_ctx, input.vpx_input_ctx)) { |
943 fprintf(stderr, "Failed to guess framerate -- error parsing " | 778 fprintf(stderr, "Failed to guess framerate -- error parsing " |
944 "webm file?\n"); | 779 "webm file?\n"); |
945 return EXIT_FAILURE; | 780 return EXIT_FAILURE; |
946 } | 781 } |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1123 #endif | 958 #endif |
1124 } | 959 } |
1125 } | 960 } |
1126 #if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH | 961 #if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH |
1127 // Default to codec bit depth if output bit depth not set | 962 // Default to codec bit depth if output bit depth not set |
1128 if (!output_bit_depth) { | 963 if (!output_bit_depth) { |
1129 output_bit_depth = img->bit_depth; | 964 output_bit_depth = img->bit_depth; |
1130 } | 965 } |
1131 // Shift up or down if necessary | 966 // Shift up or down if necessary |
1132 if (output_bit_depth != img->bit_depth) { | 967 if (output_bit_depth != img->bit_depth) { |
| 968 const vpx_img_fmt_t shifted_fmt = output_bit_depth == 8 ? |
| 969 img->fmt ^ (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) : |
| 970 img->fmt | VPX_IMG_FMT_HIGHBITDEPTH; |
| 971 if (img_shifted && |
| 972 img_shifted_realloc_required(img, img_shifted, shifted_fmt)) { |
| 973 vpx_img_free(img_shifted); |
| 974 img_shifted = NULL; |
| 975 } |
1133 if (!img_shifted) { | 976 if (!img_shifted) { |
1134 if (output_bit_depth == 8) { | 977 img_shifted = vpx_img_alloc(NULL, shifted_fmt, |
1135 img_shifted = vpx_img_alloc( | 978 img->d_w, img->d_h, 16); |
1136 NULL, img->fmt - VPX_IMG_FMT_HIGHBITDEPTH, | |
1137 img->d_w, img->d_h, 16); | |
1138 } else { | |
1139 img_shifted = vpx_img_alloc( | |
1140 NULL, img->fmt | VPX_IMG_FMT_HIGHBITDEPTH, | |
1141 img->d_w, img->d_h, 16); | |
1142 } | |
1143 img_shifted->bit_depth = output_bit_depth; | 979 img_shifted->bit_depth = output_bit_depth; |
1144 } | 980 } |
1145 if (output_bit_depth > img->bit_depth) { | 981 if (output_bit_depth > img->bit_depth) { |
1146 img_upshift(img_shifted, img, output_bit_depth - img->bit_depth); | 982 vpx_img_upshift(img_shifted, img, |
| 983 output_bit_depth - img->bit_depth); |
1147 } else { | 984 } else { |
1148 img_downshift(img_shifted, img, img->bit_depth - output_bit_depth); | 985 vpx_img_downshift(img_shifted, img, |
| 986 img->bit_depth - output_bit_depth); |
1149 } | 987 } |
1150 img = img_shifted; | 988 img = img_shifted; |
1151 } | 989 } |
1152 #endif | 990 #endif |
1153 | 991 |
1154 if (single_file) { | 992 if (single_file) { |
1155 if (use_y4m) { | 993 if (use_y4m) { |
1156 char buf[Y4M_BUFFER_SIZE] = {0}; | 994 char buf[Y4M_BUFFER_SIZE] = {0}; |
1157 size_t len = 0; | 995 size_t len = 0; |
| 996 if (img->fmt == VPX_IMG_FMT_I440 || img->fmt == VPX_IMG_FMT_I44016) { |
| 997 fprintf(stderr, "Cannot produce y4m output for 440 sampling.\n"); |
| 998 goto fail; |
| 999 } |
1158 if (frame_out == 1) { | 1000 if (frame_out == 1) { |
1159 // Y4M file header | 1001 // Y4M file header |
1160 len = y4m_write_file_header(buf, sizeof(buf), | 1002 len = y4m_write_file_header(buf, sizeof(buf), |
1161 vpx_input_ctx.width, | 1003 vpx_input_ctx.width, |
1162 vpx_input_ctx.height, | 1004 vpx_input_ctx.height, |
1163 &vpx_input_ctx.framerate, | 1005 &vpx_input_ctx.framerate, |
1164 img->fmt, img->bit_depth); | 1006 img->fmt, img->bit_depth); |
1165 if (do_md5) { | 1007 if (do_md5) { |
1166 MD5Update(&md5_ctx, (md5byte *)buf, (unsigned int)len); | 1008 MD5Update(&md5_ctx, (md5byte *)buf, (unsigned int)len); |
1167 } else { | 1009 } else { |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1285 if (arg_match(&arg, &looparg, argi)) { | 1127 if (arg_match(&arg, &looparg, argi)) { |
1286 loops = arg_parse_uint(&arg); | 1128 loops = arg_parse_uint(&arg); |
1287 break; | 1129 break; |
1288 } | 1130 } |
1289 } | 1131 } |
1290 free(argv); | 1132 free(argv); |
1291 for (i = 0; !error && i < loops; i++) | 1133 for (i = 0; !error && i < loops; i++) |
1292 error = main_loop(argc, argv_); | 1134 error = main_loop(argc, argv_); |
1293 return error; | 1135 return error; |
1294 } | 1136 } |
OLD | NEW |