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 |
11 #include "./vpxenc.h" | 11 #include "./vpxenc.h" |
12 #include "./vpx_config.h" | 12 #include "./vpx_config.h" |
13 | 13 |
14 #include <assert.h> | 14 #include <assert.h> |
15 #include <limits.h> | 15 #include <limits.h> |
16 #include <math.h> | 16 #include <math.h> |
17 #include <stdarg.h> | 17 #include <stdarg.h> |
18 #include <stdio.h> | 18 #include <stdio.h> |
19 #include <stdlib.h> | 19 #include <stdlib.h> |
20 #include <string.h> | 20 #include <string.h> |
21 | 21 |
22 #include "vpx/vpx_encoder.h" | 22 #include "vpx/vpx_encoder.h" |
23 #if CONFIG_DECODERS | 23 #if CONFIG_DECODERS |
24 #include "vpx/vpx_decoder.h" | 24 #include "vpx/vpx_decoder.h" |
25 #endif | 25 #endif |
26 | 26 |
27 #include "third_party/libyuv/include/libyuv/scale.h" | 27 #include "third_party/libyuv/include/libyuv/scale.h" |
28 #include "./args.h" | 28 #include "./args.h" |
29 #include "./ivfenc.h" | 29 #include "./ivfenc.h" |
| 30 #include "./tools_common.h" |
30 | 31 |
31 #if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER | 32 #if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER |
32 #include "vpx/vp8cx.h" | 33 #include "vpx/vp8cx.h" |
33 #endif | 34 #endif |
34 #if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER | 35 #if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER |
35 #include "vpx/vp8dx.h" | 36 #include "vpx/vp8dx.h" |
36 #endif | 37 #endif |
37 | 38 |
38 #include "./tools_common.h" | 39 #include "vpx/vpx_integer.h" |
39 #include "vpx_ports/mem_ops.h" | 40 #include "vpx_ports/mem_ops.h" |
40 #include "vpx_ports/vpx_timer.h" | 41 #include "vpx_ports/vpx_timer.h" |
| 42 #include "./rate_hist.h" |
41 #include "./vpxstats.h" | 43 #include "./vpxstats.h" |
42 #include "./warnings.h" | 44 #include "./warnings.h" |
43 #include "./webmenc.h" | 45 #include "./webmenc.h" |
44 #include "./y4minput.h" | 46 #include "./y4minput.h" |
45 | 47 |
46 /* Swallow warnings about unused results of fread/fwrite */ | 48 /* Swallow warnings about unused results of fread/fwrite */ |
47 static size_t wrap_fread(void *ptr, size_t size, size_t nmemb, | 49 static size_t wrap_fread(void *ptr, size_t size, size_t nmemb, |
48 FILE *stream) { | 50 FILE *stream) { |
49 return fread(ptr, size, nmemb, stream); | 51 return fread(ptr, size, nmemb, stream); |
50 } | 52 } |
51 #define fread wrap_fread | 53 #define fread wrap_fread |
52 | 54 |
53 static size_t wrap_fwrite(const void *ptr, size_t size, size_t nmemb, | 55 static size_t wrap_fwrite(const void *ptr, size_t size, size_t nmemb, |
54 FILE *stream) { | 56 FILE *stream) { |
55 return fwrite(ptr, size, nmemb, stream); | 57 return fwrite(ptr, size, nmemb, stream); |
56 } | 58 } |
57 #define fwrite wrap_fwrite | 59 #define fwrite wrap_fwrite |
58 | 60 |
59 | 61 |
60 static const char *exec_name; | 62 static const char *exec_name; |
61 | 63 |
62 static const struct codec_item { | |
63 char const *name; | |
64 const vpx_codec_iface_t *(*iface)(void); | |
65 const vpx_codec_iface_t *(*dx_iface)(void); | |
66 unsigned int fourcc; | |
67 } codecs[] = { | |
68 #if CONFIG_VP8_ENCODER && CONFIG_VP8_DECODER | |
69 {"vp8", &vpx_codec_vp8_cx, &vpx_codec_vp8_dx, VP8_FOURCC}, | |
70 #elif CONFIG_VP8_ENCODER && !CONFIG_VP8_DECODER | |
71 {"vp8", &vpx_codec_vp8_cx, NULL, VP8_FOURCC}, | |
72 #endif | |
73 #if CONFIG_VP9_ENCODER && CONFIG_VP9_DECODER | |
74 {"vp9", &vpx_codec_vp9_cx, &vpx_codec_vp9_dx, VP9_FOURCC}, | |
75 #elif CONFIG_VP9_ENCODER && !CONFIG_VP9_DECODER | |
76 {"vp9", &vpx_codec_vp9_cx, NULL, VP9_FOURCC}, | |
77 #endif | |
78 }; | |
79 | |
80 static void warn_or_exit_on_errorv(vpx_codec_ctx_t *ctx, int fatal, | 64 static void warn_or_exit_on_errorv(vpx_codec_ctx_t *ctx, int fatal, |
81 const char *s, va_list ap) { | 65 const char *s, va_list ap) { |
82 if (ctx->err) { | 66 if (ctx->err) { |
83 const char *detail = vpx_codec_error_detail(ctx); | 67 const char *detail = vpx_codec_error_detail(ctx); |
84 | 68 |
85 vfprintf(stderr, s, ap); | 69 vfprintf(stderr, s, ap); |
86 fprintf(stderr, ": %s\n", vpx_codec_error(ctx)); | 70 fprintf(stderr, ": %s\n", vpx_codec_error(ctx)); |
87 | 71 |
88 if (detail) | 72 if (detail) |
89 fprintf(stderr, " %s\n", detail); | 73 fprintf(stderr, " %s\n", detail); |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 fprintf(stderr, "\nVP8 Specific Options:\n"); | 437 fprintf(stderr, "\nVP8 Specific Options:\n"); |
454 arg_show_usage(stderr, vp8_args); | 438 arg_show_usage(stderr, vp8_args); |
455 #endif | 439 #endif |
456 #if CONFIG_VP9_ENCODER | 440 #if CONFIG_VP9_ENCODER |
457 fprintf(stderr, "\nVP9 Specific Options:\n"); | 441 fprintf(stderr, "\nVP9 Specific Options:\n"); |
458 arg_show_usage(stderr, vp9_args); | 442 arg_show_usage(stderr, vp9_args); |
459 #endif | 443 #endif |
460 fprintf(stderr, "\nStream timebase (--timebase):\n" | 444 fprintf(stderr, "\nStream timebase (--timebase):\n" |
461 " The desired precision of timestamps in the output, expressed\n" | 445 " The desired precision of timestamps in the output, expressed\n" |
462 " in fractional seconds. Default is 1/1000.\n"); | 446 " in fractional seconds. Default is 1/1000.\n"); |
463 fprintf(stderr, "\n" | 447 fprintf(stderr, "\nIncluded encoders:\n\n"); |
464 "Included encoders:\n" | |
465 "\n"); | |
466 | 448 |
467 for (i = 0; i < sizeof(codecs) / sizeof(codecs[0]); i++) | 449 for (i = 0; i < get_vpx_encoder_count(); ++i) { |
| 450 const VpxInterface *const encoder = get_vpx_encoder_by_index(i); |
468 fprintf(stderr, " %-6s - %s\n", | 451 fprintf(stderr, " %-6s - %s\n", |
469 codecs[i].name, | 452 encoder->name, vpx_codec_iface_name(encoder->interface())); |
470 vpx_codec_iface_name(codecs[i].iface())); | 453 } |
471 | 454 |
472 exit(EXIT_FAILURE); | 455 exit(EXIT_FAILURE); |
473 } | 456 } |
474 | 457 |
475 | |
476 #define HIST_BAR_MAX 40 | |
477 struct hist_bucket { | |
478 int low, high, count; | |
479 }; | |
480 | |
481 | |
482 static int merge_hist_buckets(struct hist_bucket *bucket, | |
483 int *buckets_, | |
484 int max_buckets) { | |
485 int small_bucket = 0, merge_bucket = INT_MAX, big_bucket = 0; | |
486 int buckets = *buckets_; | |
487 int i; | |
488 | |
489 /* Find the extrema for this list of buckets */ | |
490 big_bucket = small_bucket = 0; | |
491 for (i = 0; i < buckets; i++) { | |
492 if (bucket[i].count < bucket[small_bucket].count) | |
493 small_bucket = i; | |
494 if (bucket[i].count > bucket[big_bucket].count) | |
495 big_bucket = i; | |
496 } | |
497 | |
498 /* If we have too many buckets, merge the smallest with an adjacent | |
499 * bucket. | |
500 */ | |
501 while (buckets > max_buckets) { | |
502 int last_bucket = buckets - 1; | |
503 | |
504 /* merge the small bucket with an adjacent one. */ | |
505 if (small_bucket == 0) | |
506 merge_bucket = 1; | |
507 else if (small_bucket == last_bucket) | |
508 merge_bucket = last_bucket - 1; | |
509 else if (bucket[small_bucket - 1].count < bucket[small_bucket + 1].count) | |
510 merge_bucket = small_bucket - 1; | |
511 else | |
512 merge_bucket = small_bucket + 1; | |
513 | |
514 assert(abs(merge_bucket - small_bucket) <= 1); | |
515 assert(small_bucket < buckets); | |
516 assert(big_bucket < buckets); | |
517 assert(merge_bucket < buckets); | |
518 | |
519 if (merge_bucket < small_bucket) { | |
520 bucket[merge_bucket].high = bucket[small_bucket].high; | |
521 bucket[merge_bucket].count += bucket[small_bucket].count; | |
522 } else { | |
523 bucket[small_bucket].high = bucket[merge_bucket].high; | |
524 bucket[small_bucket].count += bucket[merge_bucket].count; | |
525 merge_bucket = small_bucket; | |
526 } | |
527 | |
528 assert(bucket[merge_bucket].low != bucket[merge_bucket].high); | |
529 | |
530 buckets--; | |
531 | |
532 /* Remove the merge_bucket from the list, and find the new small | |
533 * and big buckets while we're at it | |
534 */ | |
535 big_bucket = small_bucket = 0; | |
536 for (i = 0; i < buckets; i++) { | |
537 if (i > merge_bucket) | |
538 bucket[i] = bucket[i + 1]; | |
539 | |
540 if (bucket[i].count < bucket[small_bucket].count) | |
541 small_bucket = i; | |
542 if (bucket[i].count > bucket[big_bucket].count) | |
543 big_bucket = i; | |
544 } | |
545 | |
546 } | |
547 | |
548 *buckets_ = buckets; | |
549 return bucket[big_bucket].count; | |
550 } | |
551 | |
552 | |
553 static void show_histogram(const struct hist_bucket *bucket, | |
554 int buckets, | |
555 int total, | |
556 int scale) { | |
557 const char *pat1, *pat2; | |
558 int i; | |
559 | |
560 switch ((int)(log(bucket[buckets - 1].high) / log(10)) + 1) { | |
561 case 1: | |
562 case 2: | |
563 pat1 = "%4d %2s: "; | |
564 pat2 = "%4d-%2d: "; | |
565 break; | |
566 case 3: | |
567 pat1 = "%5d %3s: "; | |
568 pat2 = "%5d-%3d: "; | |
569 break; | |
570 case 4: | |
571 pat1 = "%6d %4s: "; | |
572 pat2 = "%6d-%4d: "; | |
573 break; | |
574 case 5: | |
575 pat1 = "%7d %5s: "; | |
576 pat2 = "%7d-%5d: "; | |
577 break; | |
578 case 6: | |
579 pat1 = "%8d %6s: "; | |
580 pat2 = "%8d-%6d: "; | |
581 break; | |
582 case 7: | |
583 pat1 = "%9d %7s: "; | |
584 pat2 = "%9d-%7d: "; | |
585 break; | |
586 default: | |
587 pat1 = "%12d %10s: "; | |
588 pat2 = "%12d-%10d: "; | |
589 break; | |
590 } | |
591 | |
592 for (i = 0; i < buckets; i++) { | |
593 int len; | |
594 int j; | |
595 float pct; | |
596 | |
597 pct = (float)(100.0 * bucket[i].count / total); | |
598 len = HIST_BAR_MAX * bucket[i].count / scale; | |
599 if (len < 1) | |
600 len = 1; | |
601 assert(len <= HIST_BAR_MAX); | |
602 | |
603 if (bucket[i].low == bucket[i].high) | |
604 fprintf(stderr, pat1, bucket[i].low, ""); | |
605 else | |
606 fprintf(stderr, pat2, bucket[i].low, bucket[i].high); | |
607 | |
608 for (j = 0; j < HIST_BAR_MAX; j++) | |
609 fprintf(stderr, j < len ? "=" : " "); | |
610 fprintf(stderr, "\t%5d (%6.2f%%)\n", bucket[i].count, pct); | |
611 } | |
612 } | |
613 | |
614 | |
615 static void show_q_histogram(const int counts[64], int max_buckets) { | |
616 struct hist_bucket bucket[64]; | |
617 int buckets = 0; | |
618 int total = 0; | |
619 int scale; | |
620 int i; | |
621 | |
622 | |
623 for (i = 0; i < 64; i++) { | |
624 if (counts[i]) { | |
625 bucket[buckets].low = bucket[buckets].high = i; | |
626 bucket[buckets].count = counts[i]; | |
627 buckets++; | |
628 total += counts[i]; | |
629 } | |
630 } | |
631 | |
632 fprintf(stderr, "\nQuantizer Selection:\n"); | |
633 scale = merge_hist_buckets(bucket, &buckets, max_buckets); | |
634 show_histogram(bucket, buckets, total, scale); | |
635 } | |
636 | |
637 | |
638 #define RATE_BINS (100) | |
639 struct rate_hist { | |
640 int64_t *pts; | |
641 int *sz; | |
642 int samples; | |
643 int frames; | |
644 struct hist_bucket bucket[RATE_BINS]; | |
645 int total; | |
646 }; | |
647 | |
648 | |
649 static void init_rate_histogram(struct rate_hist *hist, | |
650 const vpx_codec_enc_cfg_t *cfg, | |
651 const vpx_rational_t *fps) { | |
652 int i; | |
653 | |
654 /* Determine the number of samples in the buffer. Use the file's framerate | |
655 * to determine the number of frames in rc_buf_sz milliseconds, with an | |
656 * adjustment (5/4) to account for alt-refs | |
657 */ | |
658 hist->samples = cfg->rc_buf_sz * 5 / 4 * fps->num / fps->den / 1000; | |
659 | |
660 /* prevent division by zero */ | |
661 if (hist->samples == 0) | |
662 hist->samples = 1; | |
663 | |
664 hist->pts = calloc(hist->samples, sizeof(*hist->pts)); | |
665 hist->sz = calloc(hist->samples, sizeof(*hist->sz)); | |
666 for (i = 0; i < RATE_BINS; i++) { | |
667 hist->bucket[i].low = INT_MAX; | |
668 hist->bucket[i].high = 0; | |
669 hist->bucket[i].count = 0; | |
670 } | |
671 } | |
672 | |
673 | |
674 static void destroy_rate_histogram(struct rate_hist *hist) { | |
675 free(hist->pts); | |
676 free(hist->sz); | |
677 } | |
678 | |
679 | |
680 static void update_rate_histogram(struct rate_hist *hist, | |
681 const vpx_codec_enc_cfg_t *cfg, | |
682 const vpx_codec_cx_pkt_t *pkt) { | |
683 int i, idx; | |
684 int64_t now, then, sum_sz = 0, avg_bitrate; | |
685 | |
686 now = pkt->data.frame.pts * 1000 | |
687 * (uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.den; | |
688 | |
689 idx = hist->frames++ % hist->samples; | |
690 hist->pts[idx] = now; | |
691 hist->sz[idx] = (int)pkt->data.frame.sz; | |
692 | |
693 if (now < cfg->rc_buf_initial_sz) | |
694 return; | |
695 | |
696 then = now; | |
697 | |
698 /* Sum the size over the past rc_buf_sz ms */ | |
699 for (i = hist->frames; i > 0 && hist->frames - i < hist->samples; i--) { | |
700 int i_idx = (i - 1) % hist->samples; | |
701 | |
702 then = hist->pts[i_idx]; | |
703 if (now - then > cfg->rc_buf_sz) | |
704 break; | |
705 sum_sz += hist->sz[i_idx]; | |
706 } | |
707 | |
708 if (now == then) | |
709 return; | |
710 | |
711 avg_bitrate = sum_sz * 8 * 1000 / (now - then); | |
712 idx = (int)(avg_bitrate * (RATE_BINS / 2) / (cfg->rc_target_bitrate * 1000)); | |
713 if (idx < 0) | |
714 idx = 0; | |
715 if (idx > RATE_BINS - 1) | |
716 idx = RATE_BINS - 1; | |
717 if (hist->bucket[idx].low > avg_bitrate) | |
718 hist->bucket[idx].low = (int)avg_bitrate; | |
719 if (hist->bucket[idx].high < avg_bitrate) | |
720 hist->bucket[idx].high = (int)avg_bitrate; | |
721 hist->bucket[idx].count++; | |
722 hist->total++; | |
723 } | |
724 | |
725 | |
726 static void show_rate_histogram(struct rate_hist *hist, | |
727 const vpx_codec_enc_cfg_t *cfg, | |
728 int max_buckets) { | |
729 int i, scale; | |
730 int buckets = 0; | |
731 | |
732 for (i = 0; i < RATE_BINS; i++) { | |
733 if (hist->bucket[i].low == INT_MAX) | |
734 continue; | |
735 hist->bucket[buckets++] = hist->bucket[i]; | |
736 } | |
737 | |
738 fprintf(stderr, "\nRate (over %dms window):\n", cfg->rc_buf_sz); | |
739 scale = merge_hist_buckets(hist->bucket, &buckets, max_buckets); | |
740 show_histogram(hist->bucket, buckets, hist->total, scale); | |
741 } | |
742 | |
743 #define mmin(a, b) ((a) < (b) ? (a) : (b)) | 458 #define mmin(a, b) ((a) < (b) ? (a) : (b)) |
744 static void find_mismatch(vpx_image_t *img1, vpx_image_t *img2, | 459 static void find_mismatch(const vpx_image_t *const img1, |
| 460 const vpx_image_t *const img2, |
745 int yloc[4], int uloc[4], int vloc[4]) { | 461 int yloc[4], int uloc[4], int vloc[4]) { |
746 const unsigned int bsize = 64; | 462 const uint32_t bsize = 64; |
747 const unsigned int bsizey = bsize >> img1->y_chroma_shift; | 463 const uint32_t bsizey = bsize >> img1->y_chroma_shift; |
748 const unsigned int bsizex = bsize >> img1->x_chroma_shift; | 464 const uint32_t bsizex = bsize >> img1->x_chroma_shift; |
749 const int c_w = (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift; | 465 const uint32_t c_w = |
750 const int c_h = (img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift; | 466 (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift; |
751 unsigned int match = 1; | 467 const uint32_t c_h = |
752 unsigned int i, j; | 468 (img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift; |
| 469 int match = 1; |
| 470 uint32_t i, j; |
753 yloc[0] = yloc[1] = yloc[2] = yloc[3] = -1; | 471 yloc[0] = yloc[1] = yloc[2] = yloc[3] = -1; |
754 for (i = 0, match = 1; match && i < img1->d_h; i += bsize) { | 472 for (i = 0, match = 1; match && i < img1->d_h; i += bsize) { |
755 for (j = 0; match && j < img1->d_w; j += bsize) { | 473 for (j = 0; match && j < img1->d_w; j += bsize) { |
756 int k, l; | 474 int k, l; |
757 int si = mmin(i + bsize, img1->d_h) - i; | 475 const int si = mmin(i + bsize, img1->d_h) - i; |
758 int sj = mmin(j + bsize, img1->d_w) - j; | 476 const int sj = mmin(j + bsize, img1->d_w) - j; |
759 for (k = 0; match && k < si; k++) | 477 for (k = 0; match && k < si; ++k) { |
760 for (l = 0; match && l < sj; l++) { | 478 for (l = 0; match && l < sj; ++l) { |
761 if (*(img1->planes[VPX_PLANE_Y] + | 479 if (*(img1->planes[VPX_PLANE_Y] + |
762 (i + k) * img1->stride[VPX_PLANE_Y] + j + l) != | 480 (i + k) * img1->stride[VPX_PLANE_Y] + j + l) != |
763 *(img2->planes[VPX_PLANE_Y] + | 481 *(img2->planes[VPX_PLANE_Y] + |
764 (i + k) * img2->stride[VPX_PLANE_Y] + j + l)) { | 482 (i + k) * img2->stride[VPX_PLANE_Y] + j + l)) { |
765 yloc[0] = i + k; | 483 yloc[0] = i + k; |
766 yloc[1] = j + l; | 484 yloc[1] = j + l; |
767 yloc[2] = *(img1->planes[VPX_PLANE_Y] + | 485 yloc[2] = *(img1->planes[VPX_PLANE_Y] + |
768 (i + k) * img1->stride[VPX_PLANE_Y] + j + l); | 486 (i + k) * img1->stride[VPX_PLANE_Y] + j + l); |
769 yloc[3] = *(img2->planes[VPX_PLANE_Y] + | 487 yloc[3] = *(img2->planes[VPX_PLANE_Y] + |
770 (i + k) * img2->stride[VPX_PLANE_Y] + j + l); | 488 (i + k) * img2->stride[VPX_PLANE_Y] + j + l); |
771 match = 0; | 489 match = 0; |
772 break; | 490 break; |
773 } | 491 } |
774 } | 492 } |
| 493 } |
775 } | 494 } |
776 } | 495 } |
777 | 496 |
778 uloc[0] = uloc[1] = uloc[2] = uloc[3] = -1; | 497 uloc[0] = uloc[1] = uloc[2] = uloc[3] = -1; |
779 for (i = 0, match = 1; match && i < c_h; i += bsizey) { | 498 for (i = 0, match = 1; match && i < c_h; i += bsizey) { |
780 for (j = 0; match && j < c_w; j += bsizex) { | 499 for (j = 0; match && j < c_w; j += bsizex) { |
781 int k, l; | 500 int k, l; |
782 int si = mmin(i + bsizey, c_h - i); | 501 const int si = mmin(i + bsizey, c_h - i); |
783 int sj = mmin(j + bsizex, c_w - j); | 502 const int sj = mmin(j + bsizex, c_w - j); |
784 for (k = 0; match && k < si; k++) | 503 for (k = 0; match && k < si; ++k) { |
785 for (l = 0; match && l < sj; l++) { | 504 for (l = 0; match && l < sj; ++l) { |
786 if (*(img1->planes[VPX_PLANE_U] + | 505 if (*(img1->planes[VPX_PLANE_U] + |
787 (i + k) * img1->stride[VPX_PLANE_U] + j + l) != | 506 (i + k) * img1->stride[VPX_PLANE_U] + j + l) != |
788 *(img2->planes[VPX_PLANE_U] + | 507 *(img2->planes[VPX_PLANE_U] + |
789 (i + k) * img2->stride[VPX_PLANE_U] + j + l)) { | 508 (i + k) * img2->stride[VPX_PLANE_U] + j + l)) { |
790 uloc[0] = i + k; | 509 uloc[0] = i + k; |
791 uloc[1] = j + l; | 510 uloc[1] = j + l; |
792 uloc[2] = *(img1->planes[VPX_PLANE_U] + | 511 uloc[2] = *(img1->planes[VPX_PLANE_U] + |
793 (i + k) * img1->stride[VPX_PLANE_U] + j + l); | 512 (i + k) * img1->stride[VPX_PLANE_U] + j + l); |
794 uloc[3] = *(img2->planes[VPX_PLANE_U] + | 513 uloc[3] = *(img2->planes[VPX_PLANE_U] + |
795 (i + k) * img2->stride[VPX_PLANE_V] + j + l); | 514 (i + k) * img2->stride[VPX_PLANE_U] + j + l); |
796 match = 0; | 515 match = 0; |
797 break; | 516 break; |
798 } | 517 } |
799 } | 518 } |
| 519 } |
800 } | 520 } |
801 } | 521 } |
802 vloc[0] = vloc[1] = vloc[2] = vloc[3] = -1; | 522 vloc[0] = vloc[1] = vloc[2] = vloc[3] = -1; |
803 for (i = 0, match = 1; match && i < c_h; i += bsizey) { | 523 for (i = 0, match = 1; match && i < c_h; i += bsizey) { |
804 for (j = 0; match && j < c_w; j += bsizex) { | 524 for (j = 0; match && j < c_w; j += bsizex) { |
805 int k, l; | 525 int k, l; |
806 int si = mmin(i + bsizey, c_h - i); | 526 const int si = mmin(i + bsizey, c_h - i); |
807 int sj = mmin(j + bsizex, c_w - j); | 527 const int sj = mmin(j + bsizex, c_w - j); |
808 for (k = 0; match && k < si; k++) | 528 for (k = 0; match && k < si; ++k) { |
809 for (l = 0; match && l < sj; l++) { | 529 for (l = 0; match && l < sj; ++l) { |
810 if (*(img1->planes[VPX_PLANE_V] + | 530 if (*(img1->planes[VPX_PLANE_V] + |
811 (i + k) * img1->stride[VPX_PLANE_V] + j + l) != | 531 (i + k) * img1->stride[VPX_PLANE_V] + j + l) != |
812 *(img2->planes[VPX_PLANE_V] + | 532 *(img2->planes[VPX_PLANE_V] + |
813 (i + k) * img2->stride[VPX_PLANE_V] + j + l)) { | 533 (i + k) * img2->stride[VPX_PLANE_V] + j + l)) { |
814 vloc[0] = i + k; | 534 vloc[0] = i + k; |
815 vloc[1] = j + l; | 535 vloc[1] = j + l; |
816 vloc[2] = *(img1->planes[VPX_PLANE_V] + | 536 vloc[2] = *(img1->planes[VPX_PLANE_V] + |
817 (i + k) * img1->stride[VPX_PLANE_V] + j + l); | 537 (i + k) * img1->stride[VPX_PLANE_V] + j + l); |
818 vloc[3] = *(img2->planes[VPX_PLANE_V] + | 538 vloc[3] = *(img2->planes[VPX_PLANE_V] + |
819 (i + k) * img2->stride[VPX_PLANE_V] + j + l); | 539 (i + k) * img2->stride[VPX_PLANE_V] + j + l); |
820 match = 0; | 540 match = 0; |
821 break; | 541 break; |
822 } | 542 } |
823 } | 543 } |
| 544 } |
824 } | 545 } |
825 } | 546 } |
826 } | 547 } |
827 | 548 |
828 static int compare_img(vpx_image_t *img1, vpx_image_t *img2) | 549 static int compare_img(const vpx_image_t *const img1, |
829 { | 550 const vpx_image_t *const img2) { |
830 const int c_w = (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift; | 551 const uint32_t c_w = |
831 const int c_h = (img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift; | 552 (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift; |
| 553 const uint32_t c_h = |
| 554 (img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift; |
| 555 uint32_t i; |
832 int match = 1; | 556 int match = 1; |
833 unsigned int i; | |
834 | 557 |
835 match &= (img1->fmt == img2->fmt); | 558 match &= (img1->fmt == img2->fmt); |
836 match &= (img1->d_w == img2->d_w); | 559 match &= (img1->d_w == img2->d_w); |
837 match &= (img1->d_h == img2->d_h); | 560 match &= (img1->d_h == img2->d_h); |
838 | 561 |
839 for (i = 0; i < img1->d_h; i++) | 562 for (i = 0; i < img1->d_h; ++i) |
840 match &= (memcmp(img1->planes[VPX_PLANE_Y]+i*img1->stride[VPX_PLANE_Y], | 563 match &= (memcmp(img1->planes[VPX_PLANE_Y] + i * img1->stride[VPX_PLANE_Y], |
841 img2->planes[VPX_PLANE_Y]+i*img2->stride[VPX_PLANE_Y], | 564 img2->planes[VPX_PLANE_Y] + i * img2->stride[VPX_PLANE_Y], |
842 img1->d_w) == 0); | 565 img1->d_w) == 0); |
843 | 566 |
844 for (i = 0; i < c_h; i++) | 567 for (i = 0; i < c_h; ++i) |
845 match &= (memcmp(img1->planes[VPX_PLANE_U]+i*img1->stride[VPX_PLANE_U], | 568 match &= (memcmp(img1->planes[VPX_PLANE_U] + i * img1->stride[VPX_PLANE_U], |
846 img2->planes[VPX_PLANE_U]+i*img2->stride[VPX_PLANE_U], | 569 img2->planes[VPX_PLANE_U] + i * img2->stride[VPX_PLANE_U], |
847 c_w) == 0); | 570 c_w) == 0); |
848 | 571 |
849 for (i = 0; i < c_h; i++) | 572 for (i = 0; i < c_h; ++i) |
850 match &= (memcmp(img1->planes[VPX_PLANE_V]+i*img1->stride[VPX_PLANE_U], | 573 match &= (memcmp(img1->planes[VPX_PLANE_V] + i * img1->stride[VPX_PLANE_V], |
851 img2->planes[VPX_PLANE_V]+i*img2->stride[VPX_PLANE_U], | 574 img2->planes[VPX_PLANE_V] + i * img2->stride[VPX_PLANE_V], |
852 c_w) == 0); | 575 c_w) == 0); |
853 | 576 |
854 return match; | 577 return match; |
855 } | 578 } |
856 | 579 |
857 | 580 |
858 #define NELEMENTS(x) (sizeof(x)/sizeof(x[0])) | 581 #define NELEMENTS(x) (sizeof(x)/sizeof(x[0])) |
859 #define MAX(x,y) ((x)>(y)?(x):(y)) | 582 #define MAX(x,y) ((x)>(y)?(x):(y)) |
860 #if CONFIG_VP8_ENCODER && !CONFIG_VP9_ENCODER | 583 #if CONFIG_VP8_ENCODER && !CONFIG_VP9_ENCODER |
861 #define ARG_CTRL_CNT_MAX NELEMENTS(vp8_arg_ctrl_map) | 584 #define ARG_CTRL_CNT_MAX NELEMENTS(vp8_arg_ctrl_map) |
(...skipping 15 matching lines...) Expand all Loading... |
877 int write_webm; | 600 int write_webm; |
878 int have_kf_max_dist; | 601 int have_kf_max_dist; |
879 }; | 602 }; |
880 | 603 |
881 | 604 |
882 struct stream_state { | 605 struct stream_state { |
883 int index; | 606 int index; |
884 struct stream_state *next; | 607 struct stream_state *next; |
885 struct stream_config config; | 608 struct stream_config config; |
886 FILE *file; | 609 FILE *file; |
887 struct rate_hist rate_hist; | 610 struct rate_hist *rate_hist; |
888 struct EbmlGlobal ebml; | 611 struct EbmlGlobal ebml; |
889 uint32_t hash; | 612 uint32_t hash; |
890 uint64_t psnr_sse_total; | 613 uint64_t psnr_sse_total; |
891 uint64_t psnr_samples_total; | 614 uint64_t psnr_samples_total; |
892 double psnr_totals[4]; | 615 double psnr_totals[4]; |
893 int psnr_count; | 616 int psnr_count; |
894 int counts[64]; | 617 int counts[64]; |
895 vpx_codec_ctx_t encoder; | 618 vpx_codec_ctx_t encoder; |
896 unsigned int frames_out; | 619 unsigned int frames_out; |
897 uint64_t cx_time; | 620 uint64_t cx_time; |
(...skipping 19 matching lines...) Expand all Loading... |
917 die("Error: %s has zero denominator\n", msg); | 640 die("Error: %s has zero denominator\n", msg); |
918 } | 641 } |
919 | 642 |
920 | 643 |
921 static void parse_global_config(struct VpxEncoderConfig *global, char **argv) { | 644 static void parse_global_config(struct VpxEncoderConfig *global, char **argv) { |
922 char **argi, **argj; | 645 char **argi, **argj; |
923 struct arg arg; | 646 struct arg arg; |
924 | 647 |
925 /* Initialize default parameters */ | 648 /* Initialize default parameters */ |
926 memset(global, 0, sizeof(*global)); | 649 memset(global, 0, sizeof(*global)); |
927 global->codec = codecs; | 650 global->codec = get_vpx_encoder_by_index(0); |
928 global->passes = 0; | 651 global->passes = 0; |
929 global->use_i420 = 1; | 652 global->use_i420 = 1; |
930 /* Assign default deadline to good quality */ | 653 /* Assign default deadline to good quality */ |
931 global->deadline = VPX_DL_GOOD_QUALITY; | 654 global->deadline = VPX_DL_GOOD_QUALITY; |
932 | 655 |
933 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) { | 656 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) { |
934 arg.argv_step = 1; | 657 arg.argv_step = 1; |
935 | 658 |
936 if (arg_match(&arg, &codecarg, argi)) { | 659 if (arg_match(&arg, &codecarg, argi)) { |
937 int j, k = -1; | 660 global->codec = get_vpx_encoder_by_name(arg.val); |
938 | 661 if (!global->codec) |
939 for (j = 0; j < sizeof(codecs) / sizeof(codecs[0]); j++) | 662 die("Error: Unrecognized argument (%s) to --codec\n", arg.val); |
940 if (!strcmp(codecs[j].name, arg.val)) | |
941 k = j; | |
942 | |
943 if (k >= 0) | |
944 global->codec = codecs + k; | |
945 else | |
946 die("Error: Unrecognized argument (%s) to --codec\n", | |
947 arg.val); | |
948 | |
949 } else if (arg_match(&arg, &passes, argi)) { | 663 } else if (arg_match(&arg, &passes, argi)) { |
950 global->passes = arg_parse_uint(&arg); | 664 global->passes = arg_parse_uint(&arg); |
951 | 665 |
952 if (global->passes < 1 || global->passes > 2) | 666 if (global->passes < 1 || global->passes > 2) |
953 die("Error: Invalid number of passes (%d)\n", global->passes); | 667 die("Error: Invalid number of passes (%d)\n", global->passes); |
954 } else if (arg_match(&arg, &pass_arg, argi)) { | 668 } else if (arg_match(&arg, &pass_arg, argi)) { |
955 global->pass = arg_parse_uint(&arg); | 669 global->pass = arg_parse_uint(&arg); |
956 | 670 |
957 if (global->pass < 1 || global->pass > 2) | 671 if (global->pass < 1 || global->pass > 2) |
958 die("Error: Invalid pass selected (%d)\n", | 672 die("Error: Invalid pass selected (%d)\n", |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1001 global->disable_warning_prompt = 1; | 715 global->disable_warning_prompt = 1; |
1002 else | 716 else |
1003 argj++; | 717 argj++; |
1004 } | 718 } |
1005 | 719 |
1006 /* Validate global config */ | 720 /* Validate global config */ |
1007 if (global->passes == 0) { | 721 if (global->passes == 0) { |
1008 #if CONFIG_VP9_ENCODER | 722 #if CONFIG_VP9_ENCODER |
1009 // Make default VP9 passes = 2 until there is a better quality 1-pass | 723 // Make default VP9 passes = 2 until there is a better quality 1-pass |
1010 // encoder | 724 // encoder |
1011 global->passes = (global->codec->iface == vpx_codec_vp9_cx ? 2 : 1); | 725 global->passes = strcmp(global->codec->name, "vp9") == 0 ? 2 : 1; |
1012 #else | 726 #else |
1013 global->passes = 1; | 727 global->passes = 1; |
1014 #endif | 728 #endif |
1015 } | 729 } |
1016 | 730 |
1017 if (global->pass) { | 731 if (global->pass) { |
1018 /* DWIM: Assume the user meant passes=2 if pass=2 is specified */ | 732 /* DWIM: Assume the user meant passes=2 if pass=2 is specified */ |
1019 if (global->pass > global->passes) { | 733 if (global->pass > global->passes) { |
1020 warn("Assuming --pass=%d implies --passes=%d\n", | 734 warn("Assuming --pass=%d implies --passes=%d\n", |
1021 global->pass, global->pass); | 735 global->pass, global->pass); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1081 if (!stream) | 795 if (!stream) |
1082 fatal("Failed to allocate new stream."); | 796 fatal("Failed to allocate new stream."); |
1083 if (prev) { | 797 if (prev) { |
1084 memcpy(stream, prev, sizeof(*stream)); | 798 memcpy(stream, prev, sizeof(*stream)); |
1085 stream->index++; | 799 stream->index++; |
1086 prev->next = stream; | 800 prev->next = stream; |
1087 } else { | 801 } else { |
1088 vpx_codec_err_t res; | 802 vpx_codec_err_t res; |
1089 | 803 |
1090 /* Populate encoder configuration */ | 804 /* Populate encoder configuration */ |
1091 res = vpx_codec_enc_config_default(global->codec->iface(), | 805 res = vpx_codec_enc_config_default(global->codec->interface(), |
1092 &stream->config.cfg, | 806 &stream->config.cfg, |
1093 global->usage); | 807 global->usage); |
1094 if (res) | 808 if (res) |
1095 fatal("Failed to get config: %s\n", vpx_codec_err_to_string(res)); | 809 fatal("Failed to get config: %s\n", vpx_codec_err_to_string(res)); |
1096 | 810 |
1097 /* Change the default timebase to a high enough value so that the | 811 /* Change the default timebase to a high enough value so that the |
1098 * encoder will always create strictly increasing timestamps. | 812 * encoder will always create strictly increasing timestamps. |
1099 */ | 813 */ |
1100 stream->config.cfg.g_timebase.den = 1000; | 814 stream->config.cfg.g_timebase.den = 1000; |
1101 | 815 |
(...skipping 23 matching lines...) Expand all Loading... |
1125 static int parse_stream_params(struct VpxEncoderConfig *global, | 839 static int parse_stream_params(struct VpxEncoderConfig *global, |
1126 struct stream_state *stream, | 840 struct stream_state *stream, |
1127 char **argv) { | 841 char **argv) { |
1128 char **argi, **argj; | 842 char **argi, **argj; |
1129 struct arg arg; | 843 struct arg arg; |
1130 static const arg_def_t **ctrl_args = no_args; | 844 static const arg_def_t **ctrl_args = no_args; |
1131 static const int *ctrl_args_map = NULL; | 845 static const int *ctrl_args_map = NULL; |
1132 struct stream_config *config = &stream->config; | 846 struct stream_config *config = &stream->config; |
1133 int eos_mark_found = 0; | 847 int eos_mark_found = 0; |
1134 | 848 |
1135 /* Handle codec specific options */ | 849 // Handle codec specific options |
1136 if (0) { | 850 if (0) { |
1137 #if CONFIG_VP8_ENCODER | 851 #if CONFIG_VP8_ENCODER |
1138 } else if (global->codec->iface == vpx_codec_vp8_cx) { | 852 } else if (strcmp(global->codec->name, "vp8") == 0) { |
1139 ctrl_args = vp8_args; | 853 ctrl_args = vp8_args; |
1140 ctrl_args_map = vp8_arg_ctrl_map; | 854 ctrl_args_map = vp8_arg_ctrl_map; |
1141 #endif | 855 #endif |
1142 #if CONFIG_VP9_ENCODER | 856 #if CONFIG_VP9_ENCODER |
1143 } else if (global->codec->iface == vpx_codec_vp9_cx) { | 857 } else if (strcmp(global->codec->name, "vp9") == 0) { |
1144 ctrl_args = vp9_args; | 858 ctrl_args = vp9_args; |
1145 ctrl_args_map = vp9_arg_ctrl_map; | 859 ctrl_args_map = vp9_arg_ctrl_map; |
1146 #endif | 860 #endif |
1147 } | 861 } |
1148 | 862 |
1149 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) { | 863 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) { |
1150 arg.argv_step = 1; | 864 arg.argv_step = 1; |
1151 | 865 |
1152 /* Once we've found an end-of-stream marker (--) we want to continue | 866 /* Once we've found an end-of-stream marker (--) we want to continue |
1153 * shifting arguments but not consuming them. | 867 * shifting arguments but not consuming them. |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1341 | 1055 |
1342 static void show_stream_config(struct stream_state *stream, | 1056 static void show_stream_config(struct stream_state *stream, |
1343 struct VpxEncoderConfig *global, | 1057 struct VpxEncoderConfig *global, |
1344 struct VpxInputContext *input) { | 1058 struct VpxInputContext *input) { |
1345 | 1059 |
1346 #define SHOW(field) \ | 1060 #define SHOW(field) \ |
1347 fprintf(stderr, " %-28s = %d\n", #field, stream->config.cfg.field) | 1061 fprintf(stderr, " %-28s = %d\n", #field, stream->config.cfg.field) |
1348 | 1062 |
1349 if (stream->index == 0) { | 1063 if (stream->index == 0) { |
1350 fprintf(stderr, "Codec: %s\n", | 1064 fprintf(stderr, "Codec: %s\n", |
1351 vpx_codec_iface_name(global->codec->iface())); | 1065 vpx_codec_iface_name(global->codec->interface())); |
1352 fprintf(stderr, "Source file: %s Format: %s\n", input->filename, | 1066 fprintf(stderr, "Source file: %s Format: %s\n", input->filename, |
1353 input->use_i420 ? "I420" : "YV12"); | 1067 input->use_i420 ? "I420" : "YV12"); |
1354 } | 1068 } |
1355 if (stream->next || stream->index) | 1069 if (stream->next || stream->index) |
1356 fprintf(stderr, "\nStream Index: %d\n", stream->index); | 1070 fprintf(stderr, "\nStream Index: %d\n", stream->index); |
1357 fprintf(stderr, "Destination file: %s\n", stream->config.out_fn); | 1071 fprintf(stderr, "Destination file: %s\n", stream->config.out_fn); |
1358 fprintf(stderr, "Encoder parameters:\n"); | 1072 fprintf(stderr, "Encoder parameters:\n"); |
1359 | 1073 |
1360 SHOW(g_usage); | 1074 SHOW(g_usage); |
1361 SHOW(g_threads); | 1075 SHOW(g_threads); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1465 | 1179 |
1466 static void initialize_encoder(struct stream_state *stream, | 1180 static void initialize_encoder(struct stream_state *stream, |
1467 struct VpxEncoderConfig *global) { | 1181 struct VpxEncoderConfig *global) { |
1468 int i; | 1182 int i; |
1469 int flags = 0; | 1183 int flags = 0; |
1470 | 1184 |
1471 flags |= global->show_psnr ? VPX_CODEC_USE_PSNR : 0; | 1185 flags |= global->show_psnr ? VPX_CODEC_USE_PSNR : 0; |
1472 flags |= global->out_part ? VPX_CODEC_USE_OUTPUT_PARTITION : 0; | 1186 flags |= global->out_part ? VPX_CODEC_USE_OUTPUT_PARTITION : 0; |
1473 | 1187 |
1474 /* Construct Encoder Context */ | 1188 /* Construct Encoder Context */ |
1475 vpx_codec_enc_init(&stream->encoder, global->codec->iface(), | 1189 vpx_codec_enc_init(&stream->encoder, global->codec->interface(), |
1476 &stream->config.cfg, flags); | 1190 &stream->config.cfg, flags); |
1477 ctx_exit_on_error(&stream->encoder, "Failed to initialize encoder"); | 1191 ctx_exit_on_error(&stream->encoder, "Failed to initialize encoder"); |
1478 | 1192 |
1479 /* Note that we bypass the vpx_codec_control wrapper macro because | 1193 /* Note that we bypass the vpx_codec_control wrapper macro because |
1480 * we're being clever to store the control IDs in an array. Real | 1194 * we're being clever to store the control IDs in an array. Real |
1481 * applications will want to make use of the enumerations directly | 1195 * applications will want to make use of the enumerations directly |
1482 */ | 1196 */ |
1483 for (i = 0; i < stream->config.arg_ctrl_cnt; i++) { | 1197 for (i = 0; i < stream->config.arg_ctrl_cnt; i++) { |
1484 int ctrl = stream->config.arg_ctrls[i][0]; | 1198 int ctrl = stream->config.arg_ctrls[i][0]; |
1485 int value = stream->config.arg_ctrls[i][1]; | 1199 int value = stream->config.arg_ctrls[i][1]; |
1486 if (vpx_codec_control_(&stream->encoder, ctrl, value)) | 1200 if (vpx_codec_control_(&stream->encoder, ctrl, value)) |
1487 fprintf(stderr, "Error: Tried to set control %d = %d\n", | 1201 fprintf(stderr, "Error: Tried to set control %d = %d\n", |
1488 ctrl, value); | 1202 ctrl, value); |
1489 | 1203 |
1490 ctx_exit_on_error(&stream->encoder, "Failed to control codec"); | 1204 ctx_exit_on_error(&stream->encoder, "Failed to control codec"); |
1491 } | 1205 } |
1492 | 1206 |
1493 #if CONFIG_DECODERS | 1207 #if CONFIG_DECODERS |
1494 if (global->test_decode != TEST_DECODE_OFF) { | 1208 if (global->test_decode != TEST_DECODE_OFF) { |
1495 vpx_codec_dec_init(&stream->decoder, global->codec->dx_iface(), NULL, 0); | 1209 const VpxInterface *decoder = get_vpx_decoder_by_name(global->codec->name); |
| 1210 vpx_codec_dec_init(&stream->decoder, decoder->interface(), NULL, 0); |
1496 } | 1211 } |
1497 #endif | 1212 #endif |
1498 } | 1213 } |
1499 | 1214 |
1500 | 1215 |
1501 static void encode_frame(struct stream_state *stream, | 1216 static void encode_frame(struct stream_state *stream, |
1502 struct VpxEncoderConfig *global, | 1217 struct VpxEncoderConfig *global, |
1503 struct vpx_image *img, | 1218 struct vpx_image *img, |
1504 unsigned int frames_in) { | 1219 unsigned int frames_in) { |
1505 vpx_codec_pts_t frame_start, next_frame_start; | 1220 vpx_codec_pts_t frame_start, next_frame_start; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1569 static off_t ivf_header_pos = 0; | 1284 static off_t ivf_header_pos = 0; |
1570 | 1285 |
1571 switch (pkt->kind) { | 1286 switch (pkt->kind) { |
1572 case VPX_CODEC_CX_FRAME_PKT: | 1287 case VPX_CODEC_CX_FRAME_PKT: |
1573 if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT)) { | 1288 if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT)) { |
1574 stream->frames_out++; | 1289 stream->frames_out++; |
1575 } | 1290 } |
1576 if (!global->quiet) | 1291 if (!global->quiet) |
1577 fprintf(stderr, " %6luF", (unsigned long)pkt->data.frame.sz); | 1292 fprintf(stderr, " %6luF", (unsigned long)pkt->data.frame.sz); |
1578 | 1293 |
1579 update_rate_histogram(&stream->rate_hist, cfg, pkt); | 1294 update_rate_histogram(stream->rate_hist, cfg, pkt); |
1580 if (stream->config.write_webm) { | 1295 if (stream->config.write_webm) { |
1581 /* Update the hash */ | 1296 /* Update the hash */ |
1582 if (!stream->ebml.debug) | 1297 if (!stream->ebml.debug) |
1583 stream->hash = murmur(pkt->data.frame.buf, | 1298 stream->hash = murmur(pkt->data.frame.buf, |
1584 (int)pkt->data.frame.sz, | 1299 (int)pkt->data.frame.sz, |
1585 stream->hash); | 1300 stream->hash); |
1586 | 1301 |
1587 write_webm_block(&stream->ebml, cfg, pkt); | 1302 write_webm_block(&stream->ebml, cfg, pkt); |
1588 } else { | 1303 } else { |
1589 if (pkt->data.frame.partition_id <= 0) { | 1304 if (pkt->data.frame.partition_id <= 0) { |
1590 ivf_header_pos = ftello(stream->file); | 1305 ivf_header_pos = ftello(stream->file); |
1591 fsize = pkt->data.frame.sz; | 1306 fsize = pkt->data.frame.sz; |
1592 | 1307 |
1593 ivf_write_frame_header(stream->file, pkt); | 1308 ivf_write_frame_header(stream->file, pkt->data.frame.pts, fsize); |
1594 } else { | 1309 } else { |
1595 fsize += pkt->data.frame.sz; | 1310 fsize += pkt->data.frame.sz; |
1596 | 1311 |
1597 if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT)) { | 1312 if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT)) { |
1598 off_t currpos = ftello(stream->file); | 1313 off_t currpos = ftello(stream->file); |
1599 fseeko(stream->file, ivf_header_pos, SEEK_SET); | 1314 fseeko(stream->file, ivf_header_pos, SEEK_SET); |
1600 ivf_write_frame_size(stream->file, fsize); | 1315 ivf_write_frame_size(stream->file, fsize); |
1601 fseeko(stream->file, currpos, SEEK_SET); | 1316 fseeko(stream->file, currpos, SEEK_SET); |
1602 } | 1317 } |
1603 } | 1318 } |
1604 | 1319 |
1605 (void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, | 1320 (void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, |
1606 stream->file); | 1321 stream->file); |
1607 } | 1322 } |
1608 stream->nbytes += pkt->data.raw.sz; | 1323 stream->nbytes += pkt->data.raw.sz; |
1609 | 1324 |
1610 *got_data = 1; | 1325 *got_data = 1; |
1611 #if CONFIG_DECODERS | 1326 #if CONFIG_DECODERS |
1612 if (global->test_decode != TEST_DECODE_OFF && !stream->mismatch_seen) { | 1327 if (global->test_decode != TEST_DECODE_OFF && !stream->mismatch_seen) { |
1613 vpx_codec_decode(&stream->decoder, pkt->data.frame.buf, | 1328 vpx_codec_decode(&stream->decoder, pkt->data.frame.buf, |
1614 pkt->data.frame.sz, NULL, 0); | 1329 (unsigned int)pkt->data.frame.sz, NULL, 0); |
1615 if (stream->decoder.err) { | 1330 if (stream->decoder.err) { |
1616 warn_or_exit_on_error(&stream->decoder, | 1331 warn_or_exit_on_error(&stream->decoder, |
1617 global->test_decode == TEST_DECODE_FATAL, | 1332 global->test_decode == TEST_DECODE_FATAL, |
1618 "Failed to decode frame %d in stream %d", | 1333 "Failed to decode frame %d in stream %d", |
1619 stream->frames_out + 1, stream->index); | 1334 stream->frames_out + 1, stream->index); |
1620 stream->mismatch_seen = stream->frames_out + 1; | 1335 stream->mismatch_seen = stream->frames_out + 1; |
1621 } | 1336 } |
1622 } | 1337 } |
1623 #endif | 1338 #endif |
1624 break; | 1339 break; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1671 } | 1386 } |
1672 | 1387 |
1673 | 1388 |
1674 static float usec_to_fps(uint64_t usec, unsigned int frames) { | 1389 static float usec_to_fps(uint64_t usec, unsigned int frames) { |
1675 return (float)(usec > 0 ? frames * 1000000.0 / (float)usec : 0); | 1390 return (float)(usec > 0 ? frames * 1000000.0 / (float)usec : 0); |
1676 } | 1391 } |
1677 | 1392 |
1678 | 1393 |
1679 static void test_decode(struct stream_state *stream, | 1394 static void test_decode(struct stream_state *stream, |
1680 enum TestDecodeFatality fatal, | 1395 enum TestDecodeFatality fatal, |
1681 const struct codec_item *codec) { | 1396 const VpxInterface *codec) { |
1682 vpx_image_t enc_img, dec_img; | 1397 vpx_image_t enc_img, dec_img; |
1683 | 1398 |
1684 if (stream->mismatch_seen) | 1399 if (stream->mismatch_seen) |
1685 return; | 1400 return; |
1686 | 1401 |
1687 /* Get the internal reference frame */ | 1402 /* Get the internal reference frame */ |
1688 if (codec->fourcc == VP8_FOURCC) { | 1403 if (strcmp(codec->name, "vp8") == 0) { |
1689 struct vpx_ref_frame ref_enc, ref_dec; | 1404 struct vpx_ref_frame ref_enc, ref_dec; |
1690 int width, height; | 1405 int width, height; |
1691 | 1406 |
1692 width = (stream->config.cfg.g_w + 15) & ~15; | 1407 width = (stream->config.cfg.g_w + 15) & ~15; |
1693 height = (stream->config.cfg.g_h + 15) & ~15; | 1408 height = (stream->config.cfg.g_h + 15) & ~15; |
1694 vpx_img_alloc(&ref_enc.img, VPX_IMG_FMT_I420, width, height, 1); | 1409 vpx_img_alloc(&ref_enc.img, VPX_IMG_FMT_I420, width, height, 1); |
1695 enc_img = ref_enc.img; | 1410 enc_img = ref_enc.img; |
1696 vpx_img_alloc(&ref_dec.img, VPX_IMG_FMT_I420, width, height, 1); | 1411 vpx_img_alloc(&ref_dec.img, VPX_IMG_FMT_I420, width, height, 1); |
1697 dec_img = ref_dec.img; | 1412 dec_img = ref_dec.img; |
1698 | 1413 |
(...skipping 28 matching lines...) Expand all Loading... |
1727 v[0], v[1], v[2], v[3]); | 1442 v[0], v[1], v[2], v[3]); |
1728 stream->mismatch_seen = stream->frames_out; | 1443 stream->mismatch_seen = stream->frames_out; |
1729 } | 1444 } |
1730 | 1445 |
1731 vpx_img_free(&enc_img); | 1446 vpx_img_free(&enc_img); |
1732 vpx_img_free(&dec_img); | 1447 vpx_img_free(&dec_img); |
1733 } | 1448 } |
1734 | 1449 |
1735 | 1450 |
1736 static void print_time(const char *label, int64_t etl) { | 1451 static void print_time(const char *label, int64_t etl) { |
1737 int hours, mins, secs; | 1452 int64_t hours; |
| 1453 int64_t mins; |
| 1454 int64_t secs; |
1738 | 1455 |
1739 if (etl >= 0) { | 1456 if (etl >= 0) { |
1740 hours = etl / 3600; | 1457 hours = etl / 3600; |
1741 etl -= hours * 3600; | 1458 etl -= hours * 3600; |
1742 mins = etl / 60; | 1459 mins = etl / 60; |
1743 etl -= mins * 60; | 1460 etl -= mins * 60; |
1744 secs = etl; | 1461 secs = etl; |
1745 | 1462 |
1746 fprintf(stderr, "[%3s %2d:%02d:%02d] ", | 1463 fprintf(stderr, "[%3s %2"PRId64":%02"PRId64": % 02"PRId64"] ", |
1747 label, hours, mins, secs); | 1464 label, hours, mins, secs); |
1748 } else { | 1465 } else { |
1749 fprintf(stderr, "[%3s unknown] ", label); | 1466 fprintf(stderr, "[%3s unknown] ", label); |
1750 } | 1467 } |
1751 } | 1468 } |
1752 | 1469 |
1753 | 1470 |
1754 int main(int argc, const char **argv_) { | 1471 int main(int argc, const char **argv_) { |
1755 int pass; | 1472 int pass; |
1756 vpx_image_t raw; | 1473 vpx_image_t raw; |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1874 /*The Y4M reader does its own allocation. | 1591 /*The Y4M reader does its own allocation. |
1875 Just initialize this here to avoid problems if we never read any | 1592 Just initialize this here to avoid problems if we never read any |
1876 frames.*/ | 1593 frames.*/ |
1877 memset(&raw, 0, sizeof(raw)); | 1594 memset(&raw, 0, sizeof(raw)); |
1878 else | 1595 else |
1879 vpx_img_alloc(&raw, | 1596 vpx_img_alloc(&raw, |
1880 input.use_i420 ? VPX_IMG_FMT_I420 | 1597 input.use_i420 ? VPX_IMG_FMT_I420 |
1881 : VPX_IMG_FMT_YV12, | 1598 : VPX_IMG_FMT_YV12, |
1882 input.width, input.height, 32); | 1599 input.width, input.height, 32); |
1883 | 1600 |
1884 FOREACH_STREAM(init_rate_histogram(&stream->rate_hist, | 1601 FOREACH_STREAM(stream->rate_hist = |
1885 &stream->config.cfg, | 1602 init_rate_histogram(&stream->config.cfg, |
1886 &global.framerate)); | 1603 &global.framerate)); |
1887 } | 1604 } |
1888 | 1605 |
1889 FOREACH_STREAM(setup_pass(stream, &global, pass)); | 1606 FOREACH_STREAM(setup_pass(stream, &global, pass)); |
1890 FOREACH_STREAM(open_output_file(stream, &global)); | 1607 FOREACH_STREAM(open_output_file(stream, &global)); |
1891 FOREACH_STREAM(initialize_encoder(stream, &global)); | 1608 FOREACH_STREAM(initialize_encoder(stream, &global)); |
1892 | 1609 |
1893 frame_avail = 1; | 1610 frame_avail = 1; |
1894 got_data = 0; | 1611 got_data = 0; |
1895 | 1612 |
1896 while (frame_avail || got_data) { | 1613 while (frame_avail || got_data) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1940 got_data = 0; | 1657 got_data = 0; |
1941 FOREACH_STREAM(get_cx_data(stream, &global, &got_data)); | 1658 FOREACH_STREAM(get_cx_data(stream, &global, &got_data)); |
1942 | 1659 |
1943 if (!got_data && input.length && !streams->frames_out) { | 1660 if (!got_data && input.length && !streams->frames_out) { |
1944 lagged_count = global.limit ? seen_frames : ftello(input.file); | 1661 lagged_count = global.limit ? seen_frames : ftello(input.file); |
1945 } else if (input.length) { | 1662 } else if (input.length) { |
1946 int64_t remaining; | 1663 int64_t remaining; |
1947 int64_t rate; | 1664 int64_t rate; |
1948 | 1665 |
1949 if (global.limit) { | 1666 if (global.limit) { |
1950 int frame_in_lagged = (seen_frames - lagged_count) * 1000; | 1667 off_t frame_in_lagged = (seen_frames - lagged_count) * 1000; |
1951 | 1668 |
1952 rate = cx_time ? frame_in_lagged * (int64_t)1000000 / cx_time : 0; | 1669 rate = cx_time ? frame_in_lagged * (int64_t)1000000 / cx_time : 0; |
1953 remaining = 1000 * (global.limit - global.skip_frames | 1670 remaining = 1000 * (global.limit - global.skip_frames |
1954 - seen_frames + lagged_count); | 1671 - seen_frames + lagged_count); |
1955 } else { | 1672 } else { |
1956 off_t input_pos = ftello(input.file); | 1673 off_t input_pos = ftello(input.file); |
1957 off_t input_pos_lagged = input_pos - lagged_count; | 1674 off_t input_pos_lagged = input_pos - lagged_count; |
1958 int64_t limit = input.length; | 1675 int64_t limit = input.length; |
1959 | 1676 |
1960 rate = cx_time ? input_pos_lagged * (int64_t)1000000 / cx_time : 0; | 1677 rate = cx_time ? input_pos_lagged * (int64_t)1000000 / cx_time : 0; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2013 | 1730 |
2014 if (global.pass) | 1731 if (global.pass) |
2015 break; | 1732 break; |
2016 } | 1733 } |
2017 | 1734 |
2018 if (global.show_q_hist_buckets) | 1735 if (global.show_q_hist_buckets) |
2019 FOREACH_STREAM(show_q_histogram(stream->counts, | 1736 FOREACH_STREAM(show_q_histogram(stream->counts, |
2020 global.show_q_hist_buckets)); | 1737 global.show_q_hist_buckets)); |
2021 | 1738 |
2022 if (global.show_rate_hist_buckets) | 1739 if (global.show_rate_hist_buckets) |
2023 FOREACH_STREAM(show_rate_histogram(&stream->rate_hist, | 1740 FOREACH_STREAM(show_rate_histogram(stream->rate_hist, |
2024 &stream->config.cfg, | 1741 &stream->config.cfg, |
2025 global.show_rate_hist_buckets)); | 1742 global.show_rate_hist_buckets)); |
2026 FOREACH_STREAM(destroy_rate_histogram(&stream->rate_hist)); | 1743 FOREACH_STREAM(destroy_rate_histogram(stream->rate_hist)); |
2027 | 1744 |
2028 #if CONFIG_INTERNAL_STATS | 1745 #if CONFIG_INTERNAL_STATS |
2029 /* TODO(jkoleszar): This doesn't belong in this executable. Do it for now, | 1746 /* TODO(jkoleszar): This doesn't belong in this executable. Do it for now, |
2030 * to match some existing utilities. | 1747 * to match some existing utilities. |
2031 */ | 1748 */ |
2032 if (!(global.pass == 1 && global.passes == 2)) | 1749 if (!(global.pass == 1 && global.passes == 2)) |
2033 FOREACH_STREAM({ | 1750 FOREACH_STREAM({ |
2034 FILE *f = fopen("opsnr.stt", "a"); | 1751 FILE *f = fopen("opsnr.stt", "a"); |
2035 if (stream->mismatch_seen) { | 1752 if (stream->mismatch_seen) { |
2036 fprintf(f, "First mismatch occurred in frame %d\n", | 1753 fprintf(f, "First mismatch occurred in frame %d\n", |
2037 stream->mismatch_seen); | 1754 stream->mismatch_seen); |
2038 } else { | 1755 } else { |
2039 fprintf(f, "No mismatch detected in recon buffers\n"); | 1756 fprintf(f, "No mismatch detected in recon buffers\n"); |
2040 } | 1757 } |
2041 fclose(f); | 1758 fclose(f); |
2042 }); | 1759 }); |
2043 #endif | 1760 #endif |
2044 | 1761 |
2045 vpx_img_free(&raw); | 1762 vpx_img_free(&raw); |
2046 free(argv); | 1763 free(argv); |
2047 free(streams); | 1764 free(streams); |
2048 return res ? EXIT_FAILURE : EXIT_SUCCESS; | 1765 return res ? EXIT_FAILURE : EXIT_SUCCESS; |
2049 } | 1766 } |
OLD | NEW |