From 274662e9769ea13d6160453d6882af2af2abb7b0 Mon Sep 17 00:00:00 2001 From: Bartosz Meglicki Date: Mon, 11 Feb 2019 23:37:46 +0100 Subject: [PATCH] add control over encoder - selectable H.264 profile - configurable B frames - configurable average bitrate There are more configuration possibilities but it should be enough for me now --- README.md | 3 ++- examples/hve_encode_raw_h264.c | 5 ++++- hve.c | 5 +++++ hve.h | 20 ++++++++++++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7eabb75..b3558ec 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,8 @@ There are just 4 functions and 3 user-visible data types: - `hve_close` ```C - struct hve_config hardware_config = {WIDTH, HEIGHT, FRAMERATE, DEVICE, PIXEL_FORMAT}; + struct hve_config hardware_config = {WIDTH, HEIGHT, FRAMERATE, DEVICE, + PIXEL_FORMAT, PROFILE, BFRAMES, BITRATE}; struct hve *hardware_encoder=hve_init(&hardware_config); struct hve_frame frame = { 0 }; diff --git a/examples/hve_encode_raw_h264.c b/examples/hve_encode_raw_h264.c index ce87121..9f71efc 100644 --- a/examples/hve_encode_raw_h264.c +++ b/examples/hve_encode_raw_h264.c @@ -20,6 +20,9 @@ const int FRAMERATE=30; int SECONDS=10; const char *DEVICE=NULL; //NULL for default or device e.g. "/dev/dri/renderD128" const char *PIXEL_FORMAT="nv12"; //NULL for default (NV12) or pixel format e.g. "rgb0" +const int PROFILE=FF_PROFILE_H264_HIGH; //or FF_PROFILE_H264_MAIN, FF_PROFILE_H264_CONSTRAINED_BASELINE, ... +const int BFRAMES=0; //max_b_frames, set to 0 to minimize latency, non-zero to minimize size +const int BITRATE=0; //average bitrate in VBR int encoding_loop(struct hve *hardware_encoder, FILE *output_file); int process_user_input(int argc, char* argv[]); @@ -33,7 +36,7 @@ int main(int argc, char* argv[]) return -1; //prepare library data - struct hve_config hardware_config = {WIDTH, HEIGHT, FRAMERATE, DEVICE, PIXEL_FORMAT}; + struct hve_config hardware_config = {WIDTH, HEIGHT, FRAMERATE, DEVICE, PIXEL_FORMAT, PROFILE, BFRAMES, BITRATE}; struct hve *hardware_encoder; //prepare file for raw H.264 output diff --git a/hve.c b/hve.c index 7e0374a..a2b0c6e 100644 --- a/hve.c +++ b/hve.c @@ -75,6 +75,11 @@ struct hve *hve_init(const struct hve_config *config) h->avctx->sample_aspect_ratio = (AVRational){ 1, 1 }; h->avctx->pix_fmt = AV_PIX_FMT_VAAPI; + if(config->profile) + h->avctx->profile = config->profile; + h->avctx->max_b_frames = config->max_b_frames; + h->avctx->bit_rate = config->bit_rate; + //try to find software pixel format that user wants to upload data in if(config->pixel_format == NULL) h->sw_pix_fmt = AV_PIX_FMT_NV12; diff --git a/hve.h b/hve.h index 6581437..32ed79c 100644 --- a/hve.h +++ b/hve.h @@ -68,6 +68,23 @@ struct hve; * For pixel format explanation see: * FFmpeg pixel formats * + * The profile (H.264 profile) can typically be: + * - FF_PROFILE_H264_CONSTRAINED_BASELINE + * - FF_PROFILE_H264_MAIN + * - FF_PROFILE_H264_HIGH + * - ... + * + * You may check profiles supported by your hardware with vainfo: + * @code + * vainfo --display drm --device /dev/dri/renderDXYZ + * @endcode + * + * The max_b_frames controls the number of B frames. + * Disable B frames if you need low latency (at the cost of space). + * The output will be delayed by max_b_frames+1 relative to the input. + * + * The bit_rate is average bitrate in VBR mode. + * * @see hve_init */ struct hve_config @@ -77,6 +94,9 @@ struct hve_config int framerate; //!< framerate of the encoded video const char *device; //!< NULL or device, e.g. "/dev/dri/renderD128" const char *pixel_format; //!< NULL for NV12 or format, e.g. "rgb0", "bgr0", "nv12", "yuv420p" + int profile; //!< 0 to guess from input or profile e.g. FF_PROFILE_H264_MAIN, FF_PROFILE_H264_HIGH + int max_b_frames; //!< maximum number of B-frames between non-B-frames (disable if you need low latency) + int bit_rate; //!< the average bitrate in VBR mode }; /**