FFmpeg XAVC實現/x264實現 (2)
阿新 • • 發佈:2018-12-17
思路
上一篇文章提到了XAVC的一些背景,以及非每幀固定位元速率的實現方法。然而如果要實現XAVC中的CBG模式(Constrained Bytes per GOP)就必須修改x264原始碼固定每幀位元速率。
x264中對松下 AVC Intra Class 有支援,AVC Intra Class 100/200是定義在HD下的與XAVC類似的標準。因此可以通過擴充套件這部分的程式碼功能來實現4K XAVC Intra Class 300/480。
應用設定介面引數 avcintra-class=300 avcintra-flavor=sony進行編碼標準的設定。
程式碼
diff --git a/encoder/encoder.c b/encoder/encoder.c index 074c4a5c..5fb84fcd 100644 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -678,9 +678,13 @@ static int validate_parameters( x264_t *h, int b_open ) return -1; } - int type = h->param.i_avcintra_class == 200 ? 2 : + int type = h->param.i_avcintra_class == 480 ? 4 : + h->param.i_avcintra_class == 300 ? 3 : + h->param.i_avcintra_class == 200 ? 2 : h->param.i_avcintra_class == 100 ? 1 : h->param.i_avcintra_class == 50 ? 0 : -1; + int xavc = (h->param.i_avcintra_flavor == X264_AVCINTRA_FLAVOR_SONY); + if( type < 0 ) { x264_log( h, X264_LOG_ERROR, "Invalid AVC-Intra class\n" ); @@ -733,21 +737,101 @@ static int validate_parameters( x264_t *h, int b_open ) { 24000, 1001, 0, 7444, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }}} }; - int res = -1; - if( i_csp >= X264_CSP_I420 && i_csp < X264_CSP_I422 && !type ) + /* [50/100/200/300/480][720p/1440x1080/1080p/2048x1080/4K][fps] */ + static const struct { - if( h->param.i_width == 1440 && h->param.i_height == 1080 ) res = 1; - else if( h->param.i_width == 960 && h->param.i_height == 720 ) res = 0; - } - else if( i_csp >= X264_CSP_I422 && i_csp < X264_CSP_I444 && type ) + uint16_t fps_num; + uint16_t fps_den; + uint8_t interlaced; + uint16_t frame_size; + const uint8_t *cqm_4ic; + const uint8_t *cqm_8iy; + } xavcintra_lut[5][5][7] = { - if( h->param.i_width == 1920 && h->param.i_height == 1080 ) res = 1; - else if( h->param.i_width == 1280 && h->param.i_height == 720 ) res = 0; - } - else + {{{}}, + {{ 50, 1, 1, 2120, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy }, + { 60000, 1001, 1, 1744, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy }, + { 24000, 1001, 0, 1744, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy }, + { 25, 1, 0, 2120, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy }, + { 30000, 1001, 0, 1744, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy }}}, + {{{ 60000, 1001, 0, 1804, x264_cqm_avci100_720p_4ic, x264_cqm_avci100_720p_8iy }, + { 50, 1, 0, 2180, x264_cqm_avci100_720p_4ic, x264_cqm_avci100_720p_8iy }}, + {{}}, + {{ 50, 1, 1, 4368, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080i_8iy }, + { 60000, 1001, 1, 3616, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080i_8iy }, + { 24000, 1001, 0, 3616, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 25, 1, 0, 4368, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 30000, 1001, 0, 3616, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 50, 1, 0, 4368, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 60000, 1001, 0, 3616, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }}, + {{ 24000, 1001, 0, 3616, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 24, 1, 0, 3616, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 25, 1, 0, 3616, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 30000, 1001, 0, 3616, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 50, 1, 0, 3616, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 60000, 1001, 0, 3616, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }}}, + {{{}}, + {{}}, + {{ 50, 1, 1, 8864, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080i_8iy }, + { 60000, 1001, 1, 7368, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080i_8iy }, + { 24000, 1001, 0, 7368, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 25, 1, 0, 8864, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 30000, 1001, 0, 7368, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 50, 1, 0, 8864, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 60000, 1001, 0, 7368, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }}}, + {{{}}, + {{}}, + {{}}, + {{}}, + {{ 24000, 1001, 0, 9768, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 25, 1, 0, 9768, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 30000, 1001, 0, 9768, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 50, 1, 0, 9768, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 60000, 1001, 0, 9768, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }}}, + {{{}}, + {{}}, + {{}}, + {{}}, + {{ 24000, 1001, 0,15624, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 25, 1, 0,15624, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 30000, 1001, 0,15624, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 50, 1, 0,15624, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 60000, 1001, 0,15624, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }}}, + }; + + int res = -1; + if(xavc) { - x264_log( h, X264_LOG_ERROR, "Invalid colorspace for AVC-Intra %d\n", h->param.i_avcintra_class ); - return -1; + if( i_csp >= X264_CSP_I422 && i_csp < X264_CSP_I444 && type ) + { + if( h->param.i_width == 1280 && h->param.i_height == 720 ) res = 0; + else if(h->param.i_width == 1440 && h->param.i_height == 1080 ) res = 1; + else if(h->param.i_width == 1920 && h->param.i_height == 1080 ) res = 2; + else if(h->param.i_width == 2048 && h->param.i_height == 1080 ) res = 3; + else if(h->param.i_width == 3840 && h->param.i_height == 2160 ) res = 4; + else if(h->param.i_width == 4096 && h->param.i_height == 2160 ) res = 4; + } + else + { + x264_log( h, X264_LOG_ERROR, "Invalid colorspace for XAVC-Intra %d\n", h->param.i_avcintra_class ); + return -1; + } + } else { + if( i_csp >= X264_CSP_I420 && i_csp < X264_CSP_I422 && !type ) + { + if( h->param.i_width == 1440 && h->param.i_height == 1080 ) res = 1; + else if( h->param.i_width == 960 && h->param.i_height == 720 ) res = 0; + } + else if( i_csp >= X264_CSP_I422 && i_csp < X264_CSP_I444 && type ) + { + if( h->param.i_width == 1920 && h->param.i_height == 1080 ) res = 1; + else if( h->param.i_width == 1280 && h->param.i_height == 720 ) res = 0; + } + else + { + x264_log( h, X264_LOG_ERROR, "Invalid colorspace for AVC-Intra %d\n", h->param.i_avcintra_class ); + return -1; + } } if( res < 0 ) @@ -774,11 +858,20 @@ static int validate_parameters( x264_t *h, int b_open ) x264_reduce_fraction( &fps_num, &fps_den ); for( i = 0; i < 7; i++ ) { - if( avcintra_lut[type][res][i].fps_num == fps_num && - avcintra_lut[type][res][i].fps_den == fps_den && - avcintra_lut[type][res][i].interlaced == PARAM_INTERLACED ) - { - break; + if (xavc) { + if( xavcintra_lut[type][res][i].fps_num == fps_num && + xavcintra_lut[type][res][i].fps_den == fps_den && + xavcintra_lut[type][res][i].interlaced == PARAM_INTERLACED ) + { + break; + } + } else { + if( avcintra_lut[type][res][i].fps_num == fps_num && + avcintra_lut[type][res][i].fps_den == fps_den && + avcintra_lut[type][res][i].interlaced == PARAM_INTERLACED ) + { + break; + } } } if( i == 7 ) @@ -806,7 +899,7 @@ static int validate_parameters( x264_t *h, int b_open ) h->param.analyse.intra = X264_ANALYSE_I8x8; h->param.analyse.i_chroma_qp_offset = res && type ? 3 : 4; h->param.b_cabac = !type; - h->param.rc.i_vbv_buffer_size = avcintra_lut[type][res][i].frame_size; + h->param.rc.i_vbv_buffer_size = xavc ? xavcintra_lut[type][res][i].frame_size : avcintra_lut[type][res][i].frame_size; h->param.rc.i_vbv_max_bitrate = h->param.rc.i_bitrate = h->param.rc.i_vbv_buffer_size * fps_num / fps_den; h->param.rc.i_rc_method = X264_RC_ABR; @@ -814,8 +907,13 @@ static int validate_parameters( x264_t *h, int b_open ) h->param.rc.b_filler = 1; h->param.i_cqm_preset = X264_CQM_CUSTOM; memcpy( h->param.cqm_4iy, x264_cqm_jvt4i, sizeof(h->param.cqm_4iy) ); - memcpy( h->param.cqm_4ic, avcintra_lut[type][res][i].cqm_4ic, sizeof(h->param.cqm_4ic) ); - memcpy( h->param.cqm_8iy, avcintra_lut[type][res][i].cqm_8iy, sizeof(h->param.cqm_8iy) ); + if (xavc) { + memcpy( h->param.cqm_4ic, xavcintra_lut[type][res][i].cqm_4ic, sizeof(h->param.cqm_4ic) ); + memcpy( h->param.cqm_8iy, xavcintra_lut[type][res][i].cqm_8iy, sizeof(h->param.cqm_8iy) ); + } else { + memcpy( h->param.cqm_4ic, avcintra_lut[type][res][i].cqm_4ic, sizeof(h->param.cqm_4ic) ); + memcpy( h->param.cqm_8iy, avcintra_lut[type][res][i].cqm_8iy, sizeof(h->param.cqm_8iy) ); + } /* Sony XAVC flavor much more simple */ if( h->param.i_avcintra_flavor == X264_AVCINTRA_FLAVOR_SONY )
執行
./ffmpeg -i '/home/lyh/4K/Customer/Sobey/2018080927test_video/10M_SR012CA3.mp4' -r 50 -pix_fmt yuv422p10le -c:v libx264 -avcintra-class 300 -x264opts avcintra-class=300 -x264opts avcintra-flavor=sony 1.mxf