AOMedia AV1 Codec
Collaboration diagram for Two Pass Mode:

Functions

static int has_no_stats_stage (const AV1_COMP *const cpi)
 Check if the current stage has statistics. More...
 

Detailed Description

In two pass mode, the input file is passed into the encoder for a quick first pass, where statistics are gathered. These statistics and the input file are then passed back into the encoder for a second pass. The statistics help the encoder reach the desired bitrate without as much overshooting or undershooting.

During the first pass, the codec will return "stats" packets that contain information useful for the second pass. The caller should concatenate these packets as they are received. In the second pass, the concatenated packets are passed in, along with the frames to encode. During the second pass, "frame" packets are returned that represent the compressed video.

A complete example can be found in examples/twopass_encoder.c. Pseudocode is provided below to illustrate the core parts.

During the first pass, the uncompressed frames are passed in and stats information is appended to a byte array.

// For simplicity, assume that there is enough memory in the stats buffer.
// Actual code will want to use a resizable array. stats_len represents
// the length of data already present in the buffer.
void get_stats_data(aom_codec_ctx_t *encoder, char *stats,
size_t *stats_len, bool *got_data) {
const aom_codec_cx_pkt_t *pkt;
aom_codec_iter_t iter = NULL;
while ((pkt = aom_codec_get_cx_data(encoder, &iter))) {
*got_data = true;
if (pkt->kind != AOM_CODEC_STATS_PKT) continue;
memcpy(stats + *stats_len, pkt->data.twopass_stats.buf,
*stats_len += pkt->data.twopass_stats.sz;
}
}
void first_pass(char *stats, size_t *stats_len) {
struct aom_codec_enc_cfg first_pass_cfg;
... // Initialize the config as needed.
first_pass_cfg.g_pass = AOM_RC_FIRST_PASS;
aom_codec_ctx_t first_pass_encoder;
... // Initialize the encoder.
while (frame_available) {
// Read in the uncompressed frame, update frame_available
aom_image_t *frame_to_encode = ...;
aom_codec_encode(&first_pass_encoder, img, pts, duration, flags);
get_stats_data(&first_pass_encoder, stats, stats_len);
}
// After all frames have been processed, call aom_codec_encode with
// a NULL ptr repeatedly, until no more data is returned. The NULL
// ptr tells the encoder that no more frames are available.
bool got_data;
do {
got_data = false;
aom_codec_encode(&first_pass_encoder, NULL, pts, duration, flags);
get_stats_data(&first_pass_encoder, stats, stats_len, &got_data);
} while (got_data);
aom_codec_destroy(&first_pass_encoder);
}

During the second pass, the uncompressed frames and the stats are passed into the encoder.

// Write out each encoded frame to the file.
void get_cx_data(aom_codec_ctx_t *encoder, FILE *file,
bool *got_data) {
const aom_codec_cx_pkt_t *pkt;
aom_codec_iter_t iter = NULL;
while ((pkt = aom_codec_get_cx_data(encoder, &iter))) {
*got_data = true;
if (pkt->kind != AOM_CODEC_CX_FRAME_PKT) continue;
fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, file);
}
}
void second_pass(char *stats, size_t stats_len) {
struct aom_codec_enc_cfg second_pass_cfg;
... // Initialize the config file as needed.
second_pass_cfg.g_pass = AOM_RC_LAST_PASS;
cfg.rc_twopass_stats_in.buf = stats;
cfg.rc_twopass_stats_in.sz = stats_len;
aom_codec_ctx_t second_pass_encoder;
... // Initialize the encoder from the config.
FILE *output = fopen("output.obu", "wb");
while (frame_available) {
// Read in the uncompressed frame, update frame_available
aom_image_t *frame_to_encode = ...;
aom_codec_encode(&second_pass_encoder, img, pts, duration, flags);
get_cx_data(&second_pass_encoder, output);
}
// Pass in NULL to flush the encoder.
bool got_data;
do {
got_data = false;
aom_codec_encode(&second_pass_encoder, NULL, pts, duration, flags);
get_cx_data(&second_pass_encoder, output, &got_data);
} while (got_data);
aom_codec_destroy(&second_pass_encoder);
}

Function Documentation

◆ has_no_stats_stage()

static int has_no_stats_stage ( const AV1_COMP *const  cpi)
inlinestatic

Check if the current stage has statistics.

Parameters
[in]cpiTop - level encoder instance structure
Returns
0 if no stats for current stage else 1

References AV1_COMP::compressor_stage, AV1_PRIMARY::cpi, AV1_COMP::lap_enabled, AV1_COMP::oxcf, and AV1EncoderConfig::pass.

Referenced by av1_encode_strategy(), calculate_gf_length(), define_gf_group(), encode_frame_to_data_rate(), find_next_key_frame(), rc_pick_q_and_bounds(), rc_pick_q_and_bounds_no_stats(), and rc_pick_q_and_bounds_no_stats_cbr().