|  | @TEMPLATE encoder_tmpl.c | 
|  | Two Pass Encoder | 
|  | ================ | 
|  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION | 
|  | This is an example of a two pass encoder loop. It takes an input file in | 
|  | YV12 format, passes it through the encoder twice, and writes the compressed | 
|  | frames to disk in IVF format. It builds upon the simple_encoder example. | 
|  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION | 
|  |  | 
|  |  | 
|  | Twopass Variables | 
|  | ----------------- | 
|  | Twopass mode needs to track the current pass number and the buffer of | 
|  | statistics packets. | 
|  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TWOPASS_VARS | 
|  | int                  pass; | 
|  | vpx_fixed_buf_t      stats = {0}; | 
|  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TWOPASS_VARS | 
|  |  | 
|  |  | 
|  | Updating The Configuration | 
|  | --------------------------------- | 
|  | In two pass mode, the configuration has to be updated on each pass. The | 
|  | statistics buffer is passed on the last pass. | 
|  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TWOPASS_LOOP_BEGIN | 
|  | for(pass=0; pass<2; pass++) { | 
|  | frame_cnt = 0; | 
|  |  | 
|  | if(pass == 0) | 
|  | cfg.g_pass = VPX_RC_FIRST_PASS; | 
|  | else { | 
|  | cfg.g_pass              = VPX_RC_LAST_PASS; | 
|  | cfg.rc_twopass_stats_in = stats; | 
|  | } | 
|  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TWOPASS_LOOP_BEGIN | 
|  |  | 
|  |  | 
|  | Encoding A Frame | 
|  | ---------------- | 
|  | Encoding a frame in two pass mode is identical to the simple encoder | 
|  | example, except the deadline is set to VPX_DL_BEST_QUALITY to get the | 
|  | best quality possible. VPX_DL_GOOD_QUALITY could also be used. | 
|  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENCODE_FRAME | 
|  | frame_avail = read_frame(infile, &raw); | 
|  | if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt, | 
|  | 1, flags, VPX_DL_BEST_QUALITY)) | 
|  | die_codec(&codec, "Failed to encode frame"); | 
|  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENCODE_FRAME | 
|  |  | 
|  |  | 
|  | Processing Statistics Packets | 
|  | ----------------------------- | 
|  | Each packet of type `VPX_CODEC_CX_FRAME_PKT` contains the encoded data | 
|  | for this frame. We write a IVF frame header, followed by the raw data. | 
|  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_STATS | 
|  | case VPX_CODEC_STATS_PKT: | 
|  | stats.buf = realloc(stats.buf, stats.sz | 
|  | + pkt->data.twopass_stats.sz); | 
|  | if(!stats.buf) | 
|  | die("Memory reallocation failed.\n"); | 
|  | memcpy((char*)stats.buf + stats.sz, | 
|  | pkt->data.twopass_stats.buf, | 
|  | pkt->data.twopass_stats.sz); | 
|  | stats.sz +=  pkt->data.twopass_stats.sz; | 
|  | break; | 
|  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_STATS | 
|  |  | 
|  |  | 
|  | Pass Progress Reporting | 
|  | ----------------------------- | 
|  | It's sometimes helpful to see when each pass completes. | 
|  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TWOPASS_LOOP_END | 
|  | printf("Pass %d complete.\n", pass+1); | 
|  | } | 
|  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TWOPASS_LOOP_END |