set_maps.c (6899B)
1 /* 2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved. 3 * 4 * This source code is subject to the terms of the BSD 2 Clause License and 5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License 6 * was not distributed with this source code in the LICENSE file, you can 7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open 8 * Media Patent License 1.0 was not distributed with this source code in the 9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent. 10 */ 11 12 // AOM Set Active and ROI Maps 13 // =========================== 14 // 15 // This is an example demonstrating how to control the AOM encoder's 16 // ROI and Active maps. 17 // 18 // ROI (Region of Interest) maps are a way for the application to assign 19 // each macroblock in the image to a region, and then set quantizer and 20 // filtering parameters on that image. 21 // 22 // Active maps are a way for the application to specify on a 23 // macroblock-by-macroblock basis whether there is any activity in that 24 // macroblock. 25 // 26 // 27 // Configuration 28 // ------------- 29 // An ROI map is set on frame 22. If the width of the image in macroblocks 30 // is evenly divisible by 4, then the output will appear to have distinct 31 // columns, where the quantizer, loopfilter, and static threshold differ 32 // from column to column. 33 // 34 // An active map is set on frame 33. If the width of the image in macroblocks 35 // is evenly divisible by 4, then the output will appear to have distinct 36 // columns, where one column will have motion and the next will not. 37 // 38 // The active map is cleared on frame 44. 39 // 40 // Observing The Effects 41 // --------------------- 42 // Use the `simple_decoder` example to decode this sample, and observe 43 // the change in the image at frames 22, 33, and 44. 44 45 #include <assert.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 50 #include "aom/aom_encoder.h" 51 #include "aom/aomcx.h" 52 #include "common/tools_common.h" 53 #include "common/video_writer.h" 54 55 static const char *exec_name; 56 57 void usage_exit(void) { 58 fprintf(stderr, "Usage: %s <codec> <width> <height> <infile> <outfile>\n", 59 exec_name); 60 exit(EXIT_FAILURE); 61 } 62 63 static void set_active_map(const aom_codec_enc_cfg_t *cfg, 64 aom_codec_ctx_t *codec) { 65 unsigned int i; 66 aom_active_map_t map = { 0, 0, 0 }; 67 68 map.rows = (cfg->g_h + 15) / 16; 69 map.cols = (cfg->g_w + 15) / 16; 70 71 map.active_map = (uint8_t *)malloc(map.rows * map.cols); 72 if (!map.active_map) die("Failed to allocate active map"); 73 for (i = 0; i < map.rows * map.cols; ++i) map.active_map[i] = i % 2; 74 75 if (aom_codec_control(codec, AOME_SET_ACTIVEMAP, &map)) 76 die_codec(codec, "Failed to set active map"); 77 78 free(map.active_map); 79 } 80 81 static void unset_active_map(const aom_codec_enc_cfg_t *cfg, 82 aom_codec_ctx_t *codec) { 83 aom_active_map_t map = { 0, 0, 0 }; 84 85 map.rows = (cfg->g_h + 15) / 16; 86 map.cols = (cfg->g_w + 15) / 16; 87 map.active_map = NULL; 88 89 if (aom_codec_control(codec, AOME_SET_ACTIVEMAP, &map)) 90 die_codec(codec, "Failed to set active map"); 91 } 92 93 static int encode_frame(aom_codec_ctx_t *codec, aom_image_t *img, 94 int frame_index, AvxVideoWriter *writer) { 95 int got_pkts = 0; 96 aom_codec_iter_t iter = NULL; 97 const aom_codec_cx_pkt_t *pkt = NULL; 98 const aom_codec_err_t res = aom_codec_encode(codec, img, frame_index, 1, 0); 99 if (res != AOM_CODEC_OK) die_codec(codec, "Failed to encode frame"); 100 101 while ((pkt = aom_codec_get_cx_data(codec, &iter)) != NULL) { 102 got_pkts = 1; 103 104 if (pkt->kind == AOM_CODEC_CX_FRAME_PKT) { 105 const int keyframe = (pkt->data.frame.flags & AOM_FRAME_IS_KEY) != 0; 106 if (!aom_video_writer_write_frame(writer, pkt->data.frame.buf, 107 pkt->data.frame.sz, 108 pkt->data.frame.pts)) { 109 die_codec(codec, "Failed to write compressed frame"); 110 } 111 112 printf(keyframe ? "K" : "."); 113 fflush(stdout); 114 } 115 } 116 117 return got_pkts; 118 } 119 120 int main(int argc, char **argv) { 121 FILE *infile = NULL; 122 aom_codec_ctx_t codec; 123 aom_codec_enc_cfg_t cfg; 124 int frame_count = 0; 125 const int limit = 10; 126 aom_image_t raw; 127 aom_codec_err_t res; 128 AvxVideoInfo info; 129 AvxVideoWriter *writer = NULL; 130 const int fps = 2; // TODO(dkovalev) add command line argument 131 const double bits_per_pixel_per_frame = 0.067; 132 133 #if CONFIG_REALTIME_ONLY 134 const int usage = 1; 135 const int speed = 7; 136 #else 137 const int usage = 0; 138 const int speed = 2; 139 #endif 140 141 exec_name = argv[0]; 142 if (argc != 6) die("Invalid number of arguments"); 143 144 memset(&info, 0, sizeof(info)); 145 146 aom_codec_iface_t *encoder = get_aom_encoder_by_short_name(argv[1]); 147 if (encoder == NULL) { 148 die("Unsupported codec."); 149 } 150 assert(encoder != NULL); 151 info.codec_fourcc = get_fourcc_by_aom_encoder(encoder); 152 info.frame_width = (int)strtol(argv[2], NULL, 0); 153 info.frame_height = (int)strtol(argv[3], NULL, 0); 154 info.time_base.numerator = 1; 155 info.time_base.denominator = fps; 156 157 if (info.frame_width <= 0 || info.frame_height <= 0 || 158 (info.frame_width % 2) != 0 || (info.frame_height % 2) != 0) { 159 die("Invalid frame size: %dx%d", info.frame_width, info.frame_height); 160 } 161 162 if (!aom_img_alloc(&raw, AOM_IMG_FMT_I420, info.frame_width, 163 info.frame_height, 1)) { 164 die("Failed to allocate image."); 165 } 166 167 printf("Using %s\n", aom_codec_iface_name(encoder)); 168 169 res = aom_codec_enc_config_default(encoder, &cfg, usage); 170 if (res) die_codec(&codec, "Failed to get default codec config."); 171 172 cfg.g_w = info.frame_width; 173 cfg.g_h = info.frame_height; 174 cfg.g_timebase.num = info.time_base.numerator; 175 cfg.g_timebase.den = info.time_base.denominator; 176 cfg.rc_target_bitrate = 177 (unsigned int)(bits_per_pixel_per_frame * cfg.g_w * cfg.g_h * fps / 1000); 178 cfg.g_lag_in_frames = 0; 179 180 writer = aom_video_writer_open(argv[5], kContainerIVF, &info); 181 if (!writer) die("Failed to open %s for writing.", argv[5]); 182 183 if (!(infile = fopen(argv[4], "rb"))) 184 die("Failed to open %s for reading.", argv[4]); 185 186 if (aom_codec_enc_init(&codec, encoder, &cfg, 0)) 187 die("Failed to initialize encoder"); 188 189 if (aom_codec_control(&codec, AOME_SET_CPUUSED, speed)) 190 die_codec(&codec, "Failed to set cpu-used"); 191 192 // Encode frames. 193 while (aom_img_read(&raw, infile) && frame_count < limit) { 194 ++frame_count; 195 196 if (frame_count == 5) { 197 set_active_map(&cfg, &codec); 198 } else if (frame_count == 9) { 199 unset_active_map(&cfg, &codec); 200 } 201 202 encode_frame(&codec, &raw, frame_count, writer); 203 } 204 205 // Flush encoder. 206 while (encode_frame(&codec, NULL, -1, writer)) { 207 } 208 209 printf("\n"); 210 fclose(infile); 211 printf("Processed %d frames.\n", frame_count); 212 213 aom_img_free(&raw); 214 if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec."); 215 216 aom_video_writer_close(writer); 217 218 return EXIT_SUCCESS; 219 }