查看视频码流编码器配置的方法

经常用mediainfo可能会发现,mediainfo能够展示出x264/x265的编码参数,例如:


Video
ID                                       : 1
Format                                   : AVC
Format/Info                              : Advanced Video Codec
Format profile                           : High@L4.1
Format settings                          : CABAC / 4 Ref Frames
Format settings, CABAC                   : Yes
Format settings, Reference frames        : 4 frames
Codec ID                                 : avc1
Codec ID/Info                            : Advanced Video Coding
……
Writing library                          : x264 core 115
Encoding settings                        : cabac=1 / ref=4 / deblock=1:1:1 / analyse=0x3:0x133 / me=tesa / subme=10 / psy=1 / psy_rd=0.40:0.00 / mixed_ref=1 / me_range=24 / chroma_me=1 / trellis=2 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=0 / chroma_qp_offset=-2 / threads=12 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=16 / b_pyramid=2 / b_adapt=2 / b_bias=0 / direct=3 / weightb=1 / open_gop=0 / weightp=2 / keyint=250 / keyint_min=25 / scenecut=40 / intra_refresh=0 / rc_lookahead=60 / rc=2pass / mbtree=1 / bitrate=3000 / ratetol=1.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / cplxblur=20.0 / qblur=0.5 / ip_ratio=1.40 / aq=1:0.60
Codec configuration box                  : avcC

这一功能是怎么实现的呢?或者说,mediainfo从哪里获取到的编码参数?

x264/x265会把编码参数配置写进SEI中,例如:


int x264_sei_version_write( x264_t *h, bs_t *s )
{
    // random ID number generated according to ISO-11578
    static const uint8_t uuid[16] =
    {
        0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7,
        0x96, 0x2c, 0xd8, 0x20, 0xd9, 0x23, 0xee, 0xef
    };
    char *opts = x264_param2string( &h->param, 0 );
    char *payload;
    int length;

    if( !opts )
        return -1;
    CHECKED_MALLOC( payload, 200 + strlen( opts ) );

    memcpy( payload, uuid, 16 );
    sprintf( payload+16, "x264 - core %d%s - H.264/MPEG-4 AVC codec - "
             "Copy%s 2003-2022 - http://www.videolan.org/x264.html - options: %s",
             X264_BUILD, X264_VERSION, HAVE_GPL?"left":"right", opts );
    length = strlen(payload)+1;

    x264_sei_write( s, (uint8_t *)payload, length, SEI_USER_DATA_UNREGISTERED );

能够从码流中读取编码参数很方便,在用户自定义SEI中存储编码参数算是一个通用的编码器设计。但是有些情况下,比如不同的封装格式、不同的编码器实现,mediainfo不做识别。有没有更通用的提取用户自定义SEI的工具呢?of course,FFmpeg。

先看API层面。调用avcodec API做视频解码时,可以从AVFrame拿到用户自定义SEI,数据在AVFrame sidedata里:


 172     /**
 173      * User data unregistered metadata associated with a video frame.
 174      * This is the H.26[45] UDU SEI message, and shouldn't be used for any other purpose
 175      * The data is stored as uint8_t in AVFrameSideData.data which is 16 bytes of
 176      * uuid_iso_iec_11578 followed by AVFrameSideData.size - 16 bytes of user_data_payload_byte.
 177      */
 178     AV_FRAME_DATA_SEI_UNREGISTERED,

再看FFmpeg命令行工具。ffmpeg命令可以通过libavfilter中的showinfo来展示每帧的信息,包括用户自定义SEI,例如:


$ ffmpeg -i /tmp/test.mp4 -an -vf showinfo -frames 2 -f null -

[Parsed_showinfo_0 @ 0x560b1928dbc0] n:   0 pts:      0 pts_time:0       pos:       44 fmt:yuv420p sar:1/1 s:640x480 i:P iskey:1 type:I checksum:C7844136 plane_checksum:[E57C11E9 D0E94DC4 7BF4E17A] mean:[80 138 115] stdev:[48.3 25.7 35.7]
[Parsed_showinfo_0 @ 0x560b1928dbc0]   side data - User Data Unregistered:
[Parsed_showinfo_0 @ 0x560b1928dbc0] UUID=2ca2de09-b517-47db-bb55-a4fe7fc2fc4e
[Parsed_showinfo_0 @ 0x560b1928dbc0] User Data=783236352028627……

可以看到,showinfo打印出了用户自定义SEI。可惜的是用十六进制打印的,没有可读性,除非再用工具做一次转换。

所以,能否改进一下?很简单,加一个配置项udu_sei_as_ascii,开启时,尝试当成ascii来打印:


@@ -428,8 +433,13 @@ static void dump_sei_unregistered_metadata(AVFilterContext *ctx, const AVFrameSi
     av_log(ctx, AV_LOG_INFO, "UUID=" AV_PRI_UUID "\n", AV_UUID_ARG(user_data));

     av_log(ctx, AV_LOG_INFO, "User Data=");
-    for (size_t i = 16; i < sd->size; i++)
-        av_log(ctx, AV_LOG_INFO, "%02x", user_data[i]);
+    for (size_t i = 16; i < sd->size; i++) {
+        const char *format = "%02x";
+
+        if (s->udu_sei_as_ascii)
+            format = isprint(user_data[i]) ? "%c" : "\\x%02x";
+        av_log(ctx, AV_LOG_INFO, format, user_data[i]);
+    }
     av_log(ctx, AV_LOG_INFO, "\n");
 }

效果如下:


$ ./ffmpeg -i /tmp/test.mp4 -an -vf showinfo=udu_sei_as_ascii=1 -frames 2 -f null -

[Parsed_showinfo_0 @ 0x7f45b0003780] n:   0 pts:      0 pts_time:0       duration:    512 duration_time:0.04    fmt:yuv420p cl:left sar:1/1 s:640x480 i:P iskey:1 type:I checksum:C7844136 plane_checksum:[E57C11E9 D0E94DC4 7BF4E17A] mean:[80 138 115] stdev:[48.3 25.7 35.7]
[Parsed_showinfo_0 @ 0x7f45b0003780]   side data - H.26[45] User Data Unregistered SEI message: UUID=2ca2de09-b517-47db-bb55-a4fe7fc2fc4e
[Parsed_showinfo_0 @ 0x7f45b0003780] User Data=x265 (build 199) - 3.5+1-f0c1022b6:[Linux][GCC 11.2.0][64 bit] 8bit+10bit+12bit - H.265/HEVC codec - Copyright 2013-2018 (c) Multicoreware, Inc - http://x265.org - options: cpuid=1111039 frame-threads=4 no-wpp no-pmode no-pme no-psnr no-ssim log-level=2 bitdepth=8 input-csp=1 fps=25/1 input-res=640x480 interlace=0 total-frames=0 level-idc=0 high-tier=1 uhd-bd=0 ref=3 no-allow-non-conformance no-repeat-headers annexb no-aud no-hrd info hash=0 no-temporal-layers open-gop min-keyint=25 keyint=250 gop-lookahead=0 bframes=4 b-adapt=2 b-pyramid bframe-bias=0 rc-lookahead=20 lookahead-slices=0 scenecut=40 hist-scenecut=0 radl=0 no-splice no-intra-refresh ctu=64 min-cu-size=8 no-rect no-amp max-tu-size=32 tu-inter-depth=1 tu-intra-depth=1 limit-tu=0 rdoq-level=0 dynamic-rd=0.00 no-ssim-rd signhide no-tskip nr-intra=0 nr-inter=0 no-constrained-intra strong-intra-smoothing max-merge=3 limit-refs=1 no-limit-modes me=1 subme=2 merange=57 temporal-mvp no-frame-dup no-hme weightp no-weightb no-analyze-src-pics deblock=0:0 sao no-sao-non-deblock rd=3 selective-sao=4 early-skip rskip no-fast-intra no-tskip-fast no-cu-lossless b-intra no-splitrd-skip rdpenalty=0 psy-rd=2.00 psy-rdoq=0.00 no-rd-refine no-lossless cbqpoffs=0 crqpoffs=0 rc=crf crf=28.0 qcomp=0.60 qpstep=4 stats-write=0 stats-read=0 ipratio=1.40 pbratio=1.30 aq-mode=2 aq-strength=1.00 cutree zone-count=0 no-strict-cbr qg-size=32 no-rc-grain qpmax=69 qpmin=0 no-const-vbv sar=1 overscan=0 videoformat=5 range=0 colorprim=2 transfer=2 colormatrix=2 chromaloc=0 display-window=0 cll=0,0 min-luma=0 max-luma=255 log2-max-poc-lsb=8 vui-timing-info vui-hrd-info slices=1 no-opt-qp-pps no-opt-ref-list-length-pps no-multi-pass-opt-rps scenecut-bias=0.05 hist-threshold=0.03 no-opt-cu-delta-qp no-aq-motion no-hdr10 no-hdr10-opt no-dhdr10-opt no-idr-recovery-sei analysis-reuse-level=0 analysis-save-reuse-level=0 analysis-load-reuse-level=0 scale-factor=0 refine-intra=0 refine-inter=0 refine-mv=1 refine-ctu-distortion=0 no-limit-sao ctu-info=0 no-lowpass-dct refine-analysis-type=0 copy-pic=1 max-ausize-factor=1.0 no-dynamic-refine no-single-sei no-hevc-aq no-svt no-field qp-adaptation-range=1.00 scenecut-aware-qp=0conformance-window-offsets right=0 bottom=0 decoder-max-rate=0 no-vbv-live-multi-pass

Patch已经merge到master分支了,可以从这里下载FFmpeg每日构建来体验:https://github.com/BtbN/FFmpeg-Builds/releases。

作者:quink
来源:Fun With FFmpeg
原文:https://mp.weixin.qq.com/s/UuK2Kh-RJbu-OOw4N8_mNA

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论