| @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 |