Search code examples
videovideo-processinghevch.265

Finding frame sizes in an encoded bit stream


I am using HM 12.1 Reference code. I have to find frame sizes in bytes or KB from an encoded h.265 bit stream. I am very new to video processing and I am stuck in this. Pls help!


Solution

  • If you use a recent version of ffmpeg is is as simple as:

    ffprobe -show_frames file.hevc
    

    Look for lines starting with pkt_size

    Example:

    $ ~/src/ffmpeg/ffprobe -show_frames BQMall_832x480_60_QP22.hevc | grep pkt_size
    pkt_size=67941
    pkt_size=12235
    pkt_size=13024
    pkt_size=13026
    pkt_size=12534
    pkt_size=13778
    pkt_size=13589
    pkt_size=13039
    pkt_size=12035
    pkt_size=12582
    pkt_size=13186
    pkt_size=15519
    pkt_size=15930
    pkt_size=15616
    pkt_size=15311
    pkt_size=15430
    pkt_size=14608
    pkt_size=14423
    pkt_size=16044
    pkt_size=18246
    

    ffprobe is pretty cool and together with gnuplot you can produce nice plots of the frame-sizes, e.g. something like this:

    enter image description here

    Currently it doesn't work for HEVC since ffprope fails to detect the correct slize-types but that will hopefully be fixed in the future

    The code to do the above is:

    #!/bin/bash
    
    # If not in path
    FFPROBE=/home/xxxx/src/ffmpeg/ffprobe
    # If in path
    #FFPROBE=ffprobe
    
    cat <<EOF > /tmp/plot.txt
    # GNUPLOT "plot.txt"
    #Use the 3 lines below to store plot to file
    #set terminal png size 1280,720
    #set term png
    #set output "bitrate.png"
    
    set title "$(basename $1)"
    set ylabel "Bytes per frame"
    set xrange [-2:*]
    set lmargin 12
    set rmargin 2
    set grid
    set pointsize 2
    set label 1 "I frames"
    set label 1 at graph .85, .96 tc lt 1
    set label 2 "P frames"
    set label 2 at graph .85, .92 tc lt 2
    set label 3 "B frames"
    set label 3 at graph .85, .88 tc lt 3
    plot '/tmp/column.dat' using 3:1:2 notitle with i lc rgb variable
    EOF
    
    awk '
    BEGIN{
        FS="="
        OFS="\t"
        fnum=0
    }
    /pkt_size/ {size=$2}
    /pict_type/{
        sub(/I/, "167116800", $2)
        sub(/P/, "65280", $2)
        sub(/B/, "255", $2)
        sub(/\?/, "65280", $2)
        type=$2
    }
    /coded_picture_number/{
    #   sub(/0/, fnum, $2)
        num=$2
    #   fnum=fnum+1
        print size, type, num
    }' <(${FFPROBE} -show_frames $1 2>/dev/null) > /tmp/column.dat
    
    gnuplot -persist /tmp/plot.txt
    

    Update

    The good guys at JCT-VC have thought about this and in the reference software, you get a binary named annexBbytecountStatic which does pretty much this. Just call it with a raw hevc-bitstream as the only argument. Using the same file as above as an example:

    $ ./annexBbytecountStaticd BQMall_832x480_60_QP22.hevc | grep NumBytesInNALunit
       NumBytesInNALunit: 25
       NumBytesInNALunit: 31
       NumBytesInNALunit: 10
       NumBytesInNALunit: 67858
       NumBytesInNALunit: 12231
       NumBytesInNALunit: 13020
       NumBytesInNALunit: 13022
       NumBytesInNALunit: 12530
       NumBytesInNALunit: 13774
       NumBytesInNALunit: 13585
       NumBytesInNALunit: 13035
       NumBytesInNALunit: 12031
       NumBytesInNALunit: 12578
       NumBytesInNALunit: 13182
       NumBytesInNALunit: 15515
       NumBytesInNALunit: 15926
       NumBytesInNALunit: 15612
       NumBytesInNALunit: 15307
       NumBytesInNALunit: 15426
       NumBytesInNALunit: 14604
       NumBytesInNALunit: 14419
       NumBytesInNALunit: 16040
       NumBytesInNALunit: 18243
      NumBytesInNALunit: 338004
      NumBytesInNALunit: 270121
      NumBytesInNALunit: 0
      NumBytesInNALunit: 67883