This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM62A7: How to set the bitrate for a H.265 stream?

Part Number: AM62A7

Hi,

I am trying to configure the bitrate for the H.265 encoder, currently with the following extra-controls:

v4l2h265enc extra-controls="enc,prepend_sps_and_pps_to_idr=1,video_gop_size=5,video_bitrate_mode=0,video_bitrate=6000000"

I am seeing the same output regardless what I use for the video_bitrate_mode and video_bitrate, do I need to use a different control for HEVC?

Thanks,

Bas Vermeulen

  • Hi Bas,

    Are you testing with 9.1 SDK released software?

    I just ran these  pipelines on my AM62A board and I do see the difference in the files created.

    gst-launch-1.0 -v v4l2src device=/dev/video-usb-cam0 num-buffers=100 ! \
    'image/jpeg, width=640, height=480, framerate=30/1' ! jpegdec ! videoconvert ! \
    v4l2h265enc ! filesink location=usb-default.264

    gst-launch-1.0 -v v4l2src device=/dev/video-usb-cam0 num-buffers=100 ! \
    'image/jpeg, width=640, height=480, framerate=30/1' ! jpegdec ! videoconvert ! \
    v4l2h265enc extra-controls="controls, hevc_profile=1, video_bitrate=10000, hevc_level=3" ! \
    filesink location=usb-profile-level-br.264

    gst-launch-1.0 -v v4l2src device=/dev/video-usb-cam0 num-buffers=100 ! \
    'image/jpeg, width=640, height=480, framerate=30/1' ! jpegdec ! videoconvert ! \
    v4l2h265enc extra-controls="controls, hevc_profile=0, video_bitrate=100000, hevc_level=5" ! \
    filesink location=usb-pr0-lvl5-b100000.264

    Let me know if this helps.

    Best Regards,

    Suren

  • Hi Suren,

    I am testing with SDK 9.1.0.7.

    I am trying to compress a jpeg that's 3840x2160, and no matter the settings, I get the same(ish) size for the video file.

    The picture I use:

    The script I use is currently this (I've added your controls to it):

    #!/bin/bash
    
    INPUT="frame.jpg"
    OUTPUT="output.jpg"
    HEVC_PROFILE=0 # Main
    HEVC_LEVEL=0
    VIDEO_BITRATE=0
    
    TEMP=$(getopt -o 'p:l:b:i:o:h' --long 'profile:,level:,bitrate:,input:,output:,help' -n '$0' -- "$@")
    
    if [ $? -ne 0 ]; then
    	echo 'Terminating...' >&2
    	exit 1
    fi
    
    eval set -- "$TEMP"
    unset TEMP
    
    while true; do
    	case "$1" in
    		'-h'|'--help')
    			echo 'Help'
    			shift
    			continue
    		;;
    		'-p'|'--profile')
    			echo "HEVC Profile: '$2'"
    			HEVC_PROFILE=$2
    			shift 2
    			continue
    		;;
    		'-l'|'--level')
    			echo "HEVC Level: '$2'"
    			HEVC_LEVEL=$2
    			shift 2
    			continue
    		;;
    		'-b'|'--bitrate')
    			echo "Video Bitrate: '$2'"
    			VIDEO_BITRATE=$2
    			shift 2
    			continue
    		;;
    		'-i'|'--input')
    			echo "Input: '$2'"
    			INPUT=$2
    			shift 2
    			continue
    		;;
    		'-o'|'--output')
    			echo "Output: '$2'"
    			OUTPUT=$2
    			shift 2
    			continue
    		;;
    		'--')
    			shift
    			break
    		;;
    		*)
    			echo 'Internal error!' >&2
    			exit 1
    		;;
    	esac
    done
    
    echo "Compressing $INPUT to p${HEVC_PROFILE}l${HEVC_LEVEL}b${VIDEO_BITRATE}.h265:"
    gst-launch-1.0 multifilesrc location="$INPUT" start-index=0 stop-index=0 caps="image/jpeg,framerate=1/1" loop=0 \
      ! jpegparse \
      ! jpegdec \
      ! 'video/x-raw,format=I420' \
      ! videoconvert \
      ! v4l2h265enc extra-controls="controls, hevc_profile=$HEVC_PROFILE, hevc_level=$HEVC_LEVEL, video_bitrate=$VIDEO_BITRATE" \
      ! filesink location=p${HEVC_PROFILE}l${HEVC_LEVEL}b${VIDEO_BITRATE}.h265
    echo "Done."
    
    echo "Decompressing p${HEVC_PROFILE}l${HEVC_LEVEL}b${VIDEO_BITRATE}.h265 to $OUTPUT:"
    gst-launch-1.0 filesrc location=p${HEVC_PROFILE}l${HEVC_LEVEL}b${VIDEO_BITRATE}.h265 \
      ! h265parse \
      ! v4l2h265dec \
      ! jpegenc \
      ! multifilesink location="$OUTPUT"
    echo "Done."
    

    The .h265 file used as an intermediary doesn't really change size (I've seen a difference of 2 bytes, but that's it). I'm not sure if this is normal or not.

    I've used several parameters:

    • no parameters to the script
    • -p0 -l1 -b10000
    • -p0 -l3 -b10000
    • -p1 -l5 -b1000
    • -p1 -l5 -b10000
    • -p1 -l5 -b100000

    They all generate a .h265 file with a size of around 338058(+/- 2).

    -rw-r--r-- 1 root root  338060 May 10 21:44  p0l0b0.h265
    -rw-r--r-- 1 root root  338060 May 10 21:44  p0l1b10000.h265
    -rw-r--r-- 1 root root  338058 May 10 21:25  p0l3b10000.h265
    -rw-r--r-- 1 root root  338058 May 10 21:41  p1l5b1000.h265
    -rw-r--r-- 1 root root  338058 May 10 21:41  p1l5b10000.h265
    -rw-r--r-- 1 root root  338058 May 10 21:44  p1l5b100000.h265

    The end-goal is a 6 Mbps stream coming from a 4K (3840x2160 30 fps) video source. I'm currently trying to find the parameters that allow me to do that.

    Regards,

    Bas Vermeulen

  • Hi Bas,

    Can you add frame_level_rate_control_enable=1 to the control list and see if the behavior changes.

    Best Regards,

    Suren

  • Hi Suren,

    frame_level_rate_control=1 makes a big difference (but can't be used when video_bitrate=0, which is the default).

    I've updated my script to manage that, it now writes a .h265 stream and the individual frames as jpg.

    #!/bin/bash
    
    INPUT="frame.jpg"
    OUTPUT="output"
    HEVC_PROFILE="main"
    HEVC_LEVEL="1"
    VIDEO_BITRATE=0
    FRAME_RATE_CONTROL=0
    
    TEMP=$(getopt -o 'p:l:b:i:o:h' --long 'profile:,level:,bitrate:,input:,output:,help' -n '$0' -- "$@")
    
    if [ $? -ne 0 ]; then
    	echo 'Terminating...' >&2
    	exit 1
    fi
    
    eval set -- "$TEMP"
    unset TEMP
    
    while true; do
    	case "$1" in
    		'-h'|'--help')
    			echo "$0 - H.265 compress a JPEG file into a one second stream"
    			echo "Parameters:"
    			echo "  -p main|main-still-picture|main-10 (HEVC Profile)"
    			echo "  -l 1|2|2.1|3|3.1|4|4.1|5|5.1 (HEVC Level)"
    			echo "  -b 0..700000000 (Video Bitrate)"
    			echo "  -i input.jpg (Input JPEG file)"
    			echo "  -o output (Base name of output files - gets converted to output%03d.jpg)"
    			echo "  -h This help"
    			exit 0
    			shift
    			continue
    		;;
    		'-p'|'--profile')
    			case "$2" in
    				'main'|'Main'|'0')
    					HEVC_PROFILE="main"
    					;;
    				'main-still-picture'|'1')
    					HEVC_PROFILE="main-still-picture"
    					;;
    				'main-10'|'2')
    					HEVC_PROFILE="main-10"
    					;;
    				*)
    					HEVC_PROFILE="main"
    					;;
    			esac
    			echo "HEVC Profile: '$HEVC_PROFILE'"
    			shift 2
    			continue
    		;;
    		'-l'|'--level')
    			case "$2" in
    				'1'|'2'|'2.1'|'3'|'3.1'|'4'|'4.1'|'5'|'5.1')
    					HEVC_LEVEL="$2"
    					;;
    				*)
    					HEVC_LEVEL="1"
    					;;
    			esac
    			echo "HEVC Level: '$HEVC_LEVEL'"
    			shift 2
    			continue
    		;;
    		'-b'|'--bitrate')
    			echo "Video Bitrate: '$2'"
    			VIDEO_BITRATE=$2
    			if [ $VIDEO_BITRATE -gt 0 ]; then
    				FRAME_RATE_CONTROL=1
    			fi
    			shift 2
    			continue
    		;;
    		'-i'|'--input')
    			echo "Input: '$2'"
    			INPUT=$2
    			shift 2
    			continue
    		;;
    		'-o'|'--output')
    			echo "Output: '$2'"
    			OUTPUT=$2
    			shift 2
    			continue
    		;;
    		'--')
    			shift
    			break
    		;;
    		*)
    			echo 'Internal error!' >&2
    			exit 1
    		;;
    	esac
    done
    
    echo -n "Compressing $INPUT to $OUTPUT:"
    gst-launch-1.0 -q multifilesrc location="$INPUT" start-index=0 stop-index=29 caps="image/jpeg,framerate=30/1" loop=0 \
      ! jpegparse \
      ! jpegdec \
      ! 'video/x-raw,format=I420' \
      ! videoconvert \
      ! v4l2h265enc extra-controls="controls, prepend_sps_and_pps_to_idr=1, frame_level_rate_control_enable=${FRAME_RATE_CONTROL}, video_gop_size=5, video_bitrate_mode=0, video_bitrate=$VIDEO_BITRATE" \
      ! "video/x-h265, profile=(string)${HEVC_PROFILE}, level=(string)${HEVC_LEVEL}" \
      ! tee name=tee0 \
      ! h265parse \
      ! v4l2h265dec \
      ! jpegenc \
      ! multifilesink location="${OUTPUT}-p${HEVC_PROFILE}l${HEVC_LEVEL}b${VIDEO_BITRATE}.%03d.jpg" \
      tee0. \
      ! filesink location="${OUTPUT}-p${HEVC_PROFILE}l${HEVC_LEVEL}b${VIDEO_BITRATE}.h265"
    echo "Done."
    

    The streams now look like this (the ones with b0 have frame_level_rate_control=0):

    -rw-r--r-- 1 root root 2032530 Jan 31 06:22 onsemi-pmainl1b0.h265
    -rw-r--r-- 1 root root  117588 Jan 31 06:20 onsemi-pmainl1b6000.h265
    -rw-r--r-- 1 root root 2032530 Jan 31 06:13 onsemi-pmainl3b0.h265
    -rw-r--r-- 1 root root  117588 Jan 31 06:08 onsemi-pmainl3b100000.h265
    -rw-r--r-- 1 root root  117588 Jan 31 06:07 onsemi-pmainl3b6000.h265
    -rw-r--r-- 1 root root 3434826 Jan 31 06:26 sony-pmainl1b0.h265
    -rw-r--r-- 1 root root  148836 Jan 31 06:24 sony-pmainl1b6000.h265

    With frame_level_rate_control=1 the stream is a lot smaller, thank you.

    I have one remaining question, what is the unit of the video_bitrate setting? At the moment I'm guessing kilobit/s, but I could be mistaken.

    Regards,

    Bas Vermeulen

  • Hi Bas,

    I am glad that it worked by adding the frame_level_rate_control=1. Also you can set the video_bitrate_mode=1 (Constant bitrate).

    Yes your understanding is correct the video_bitrate is set in terms of kilobits/sec.

    I am going to close the thread, as the issue is resolved. Feel free to reach out for any further assistance.

    Best Regards,

    Suren