OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. | 2 * Copyright (c) 2012 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 // This is an example demonstrating how to implement a multi-layer VPx | 11 // This is an example demonstrating how to implement a multi-layer VPx |
12 // encoding scheme based on temporal scalability for video applications | 12 // encoding scheme based on temporal scalability for video applications |
13 // that benefit from a scalable bitstream. | 13 // that benefit from a scalable bitstream. |
14 | 14 |
| 15 #include <assert.h> |
15 #include <math.h> | 16 #include <math.h> |
16 #include <stdio.h> | 17 #include <stdio.h> |
17 #include <stdlib.h> | 18 #include <stdlib.h> |
18 #include <string.h> | 19 #include <string.h> |
19 | 20 |
20 #define VPX_CODEC_DISABLE_COMPAT 1 | 21 #define VPX_CODEC_DISABLE_COMPAT 1 |
21 #include "./vpx_config.h" | 22 #include "./vpx_config.h" |
22 #include "vpx_ports/vpx_timer.h" | 23 #include "vpx_ports/vpx_timer.h" |
23 #include "vpx/vp8cx.h" | 24 #include "vpx/vp8cx.h" |
24 #include "vpx/vpx_encoder.h" | 25 #include "vpx/vpx_encoder.h" |
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY; | 432 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY; |
432 layer_flags[3] = layer_flags[1]; | 433 layer_flags[3] = layer_flags[1]; |
433 layer_flags[5] = layer_flags[1]; | 434 layer_flags[5] = layer_flags[1]; |
434 layer_flags[7] = layer_flags[1]; | 435 layer_flags[7] = layer_flags[1]; |
435 break; | 436 break; |
436 } | 437 } |
437 } | 438 } |
438 } | 439 } |
439 | 440 |
440 int main(int argc, char **argv) { | 441 int main(int argc, char **argv) { |
441 VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS]; | 442 VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = {NULL}; |
442 vpx_codec_ctx_t codec; | 443 vpx_codec_ctx_t codec; |
443 vpx_codec_enc_cfg_t cfg; | 444 vpx_codec_enc_cfg_t cfg; |
444 int frame_cnt = 0; | 445 int frame_cnt = 0; |
445 vpx_image_t raw; | 446 vpx_image_t raw; |
446 vpx_codec_err_t res; | 447 vpx_codec_err_t res; |
447 unsigned int width; | 448 unsigned int width; |
448 unsigned int height; | 449 unsigned int height; |
449 int speed; | 450 int speed; |
450 int frame_avail; | 451 int frame_avail; |
451 int got_data; | 452 int got_data; |
452 int flags = 0; | 453 int flags = 0; |
453 unsigned int i; | 454 unsigned int i; |
454 int pts = 0; // PTS starts at 0. | 455 int pts = 0; // PTS starts at 0. |
455 int frame_duration = 1; // 1 timebase tick per frame. | 456 int frame_duration = 1; // 1 timebase tick per frame. |
456 int layering_mode = 0; | 457 int layering_mode = 0; |
457 int layer_flags[VPX_TS_MAX_PERIODICITY] = {0}; | 458 int layer_flags[VPX_TS_MAX_PERIODICITY] = {0}; |
458 int flag_periodicity = 1; | 459 int flag_periodicity = 1; |
459 int max_intra_size_pct; | |
460 vpx_svc_layer_id_t layer_id = {0, 0}; | 460 vpx_svc_layer_id_t layer_id = {0, 0}; |
461 const VpxInterface *encoder = NULL; | 461 const VpxInterface *encoder = NULL; |
462 FILE *infile = NULL; | 462 FILE *infile = NULL; |
463 struct RateControlMetrics rc; | 463 struct RateControlMetrics rc; |
464 int64_t cx_time = 0; | 464 int64_t cx_time = 0; |
465 | 465 |
466 exec_name = argv[0]; | 466 exec_name = argv[0]; |
467 // Check usage and arguments. | 467 // Check usage and arguments. |
468 if (argc < 11) { | 468 if (argc < 11) { |
469 die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> " | 469 die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> " |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 info.codec_fourcc = encoder->fourcc; | 563 info.codec_fourcc = encoder->fourcc; |
564 info.frame_width = cfg.g_w; | 564 info.frame_width = cfg.g_w; |
565 info.frame_height = cfg.g_h; | 565 info.frame_height = cfg.g_h; |
566 info.time_base.numerator = cfg.g_timebase.num; | 566 info.time_base.numerator = cfg.g_timebase.num; |
567 info.time_base.denominator = cfg.g_timebase.den; | 567 info.time_base.denominator = cfg.g_timebase.den; |
568 | 568 |
569 snprintf(file_name, sizeof(file_name), "%s_%d.ivf", argv[2], i); | 569 snprintf(file_name, sizeof(file_name), "%s_%d.ivf", argv[2], i); |
570 outfile[i] = vpx_video_writer_open(file_name, kContainerIVF, &info); | 570 outfile[i] = vpx_video_writer_open(file_name, kContainerIVF, &info); |
571 if (!outfile[i]) | 571 if (!outfile[i]) |
572 die("Failed to open %s for writing", file_name); | 572 die("Failed to open %s for writing", file_name); |
| 573 |
| 574 assert(outfile[i] != NULL); |
573 } | 575 } |
574 // No spatial layers in this encoder. | 576 // No spatial layers in this encoder. |
575 cfg.ss_number_layers = 1; | 577 cfg.ss_number_layers = 1; |
576 | 578 |
577 // Initialize codec. | 579 // Initialize codec. |
578 if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) | 580 if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) |
579 die_codec(&codec, "Failed to initialize encoder"); | 581 die_codec(&codec, "Failed to initialize encoder"); |
580 | 582 |
581 if (strncmp(encoder->name, "vp8", 3) == 0) { | 583 if (strncmp(encoder->name, "vp8", 3) == 0) { |
582 vpx_codec_control(&codec, VP8E_SET_CPUUSED, -speed); | 584 vpx_codec_control(&codec, VP8E_SET_CPUUSED, -speed); |
583 vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, kDenoiserOnYOnly); | 585 vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, kDenoiserOnYOnly); |
584 } else if (strncmp(encoder->name, "vp9", 3) == 0) { | 586 } else if (strncmp(encoder->name, "vp9", 3) == 0) { |
585 vpx_codec_control(&codec, VP8E_SET_CPUUSED, speed); | 587 vpx_codec_control(&codec, VP8E_SET_CPUUSED, speed); |
586 vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3); | 588 vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3); |
587 vpx_codec_control(&codec, VP9E_SET_FRAME_PERIODIC_BOOST, 0); | 589 vpx_codec_control(&codec, VP9E_SET_FRAME_PERIODIC_BOOST, 0); |
588 vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, 0); | 590 vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, 0); |
589 if (vpx_codec_control(&codec, VP9E_SET_SVC, 1)) { | 591 if (vpx_codec_control(&codec, VP9E_SET_SVC, 1)) { |
590 die_codec(&codec, "Failed to set SVC"); | 592 die_codec(&codec, "Failed to set SVC"); |
591 } | 593 } |
592 } | 594 } |
593 vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1); | 595 vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1); |
594 vpx_codec_control(&codec, VP8E_SET_TOKEN_PARTITIONS, 1); | 596 vpx_codec_control(&codec, VP8E_SET_TOKEN_PARTITIONS, 1); |
595 // This controls the maximum target size of the key frame. | 597 // This controls the maximum target size of the key frame. |
596 // For generating smaller key frames, use a smaller max_intra_size_pct | 598 // For generating smaller key frames, use a smaller max_intra_size_pct |
597 // value, like 100 or 200. | 599 // value, like 100 or 200. |
598 max_intra_size_pct = (int) (((double)cfg.rc_buf_optimal_sz * 0.5) | 600 { |
599 * ((double) cfg.g_timebase.den / cfg.g_timebase.num) / 10.0); | 601 const int max_intra_size_pct = 200; |
600 // For low-quality key frame. | 602 vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT, |
601 max_intra_size_pct = 200; | 603 max_intra_size_pct); |
602 vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT, max_intra_size_pct); | 604 } |
603 | 605 |
604 frame_avail = 1; | 606 frame_avail = 1; |
605 while (frame_avail || got_data) { | 607 while (frame_avail || got_data) { |
606 struct vpx_usec_timer timer; | 608 struct vpx_usec_timer timer; |
607 vpx_codec_iter_t iter = NULL; | 609 vpx_codec_iter_t iter = NULL; |
608 const vpx_codec_cx_pkt_t *pkt; | 610 const vpx_codec_cx_pkt_t *pkt; |
609 // Update the temporal layer_id. No spatial layers in this test. | 611 // Update the temporal layer_id. No spatial layers in this test. |
610 layer_id.spatial_layer_id = 0; | 612 layer_id.spatial_layer_id = 0; |
611 layer_id.temporal_layer_id = | 613 layer_id.temporal_layer_id = |
612 cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity]; | 614 cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity]; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 if (vpx_codec_destroy(&codec)) | 670 if (vpx_codec_destroy(&codec)) |
669 die_codec(&codec, "Failed to destroy codec"); | 671 die_codec(&codec, "Failed to destroy codec"); |
670 | 672 |
671 // Try to rewrite the output file headers with the actual frame count. | 673 // Try to rewrite the output file headers with the actual frame count. |
672 for (i = 0; i < cfg.ts_number_layers; ++i) | 674 for (i = 0; i < cfg.ts_number_layers; ++i) |
673 vpx_video_writer_close(outfile[i]); | 675 vpx_video_writer_close(outfile[i]); |
674 | 676 |
675 vpx_img_free(&raw); | 677 vpx_img_free(&raw); |
676 return EXIT_SUCCESS; | 678 return EXIT_SUCCESS; |
677 } | 679 } |
OLD | NEW |