[FFmpeg-devel,v2,35/36] vaapi_encode_h265: Set level based on stream if not set by user

Submitted by Mark Thompson on June 7, 2018, 11:43 p.m.

Details

Message ID 20180607234331.32139-36-sw@jkqxz.net
State New
Headers show

Commit Message

Mark Thompson June 7, 2018, 11:43 p.m.
Sets the level based on the stream properties if it is not explicitly
set by the user.  Also add a tier option to set general_tier_flag, since
that affects the level choice.
---
 doc/encoders.texi              |  4 ++++
 libavcodec/vaapi_encode_h265.c | 34 +++++++++++++++++++++++++++++++---
 2 files changed, 35 insertions(+), 3 deletions(-)

Comments

Haihao Xiang June 15, 2018, 4:22 a.m.
On Fri, 2018-06-08 at 00:43 +0100, Mark Thompson wrote:
> Sets the level based on the stream properties if it is not explicitly

> set by the user.  Also add a tier option to set general_tier_flag, since

> that affects the level choice.

> ---

>  doc/encoders.texi              |  4 ++++

>  libavcodec/vaapi_encode_h265.c | 34 +++++++++++++++++++++++++++++++---

>  2 files changed, 35 insertions(+), 3 deletions(-)

> 

> diff --git a/doc/encoders.texi b/doc/encoders.texi

> index ceddfdda64..d61a1cc4bc 100644

> --- a/doc/encoders.texi

> +++ b/doc/encoders.texi

> @@ -2659,6 +2659,10 @@ Include recovery points where appropriate

> (@emph{recovery_point} messages).

>  @item aud

>  Include access unit delimiters in the stream (not included by default).

>  

> +@item tier

> +Set @emph{general_tier_flag}.  This may affect the level chosen for the

> stream

> +if it is not explicitly specified.

> +

>  @end table

>  

>  @item mjpeg_vaapi

> diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c

> index 2cee19be68..100f8338d7 100644

> --- a/libavcodec/vaapi_encode_h265.c

> +++ b/libavcodec/vaapi_encode_h265.c

> @@ -30,6 +30,7 @@

>  #include "avcodec.h"

>  #include "cbs.h"

>  #include "cbs_h265.h"

> +#include "h265_profile_level.h"

>  #include "hevc.h"

>  #include "hevc_sei.h"

>  #include "internal.h"

> @@ -48,6 +49,7 @@ typedef struct VAAPIEncodeH265Context {

>      int qp;

>      int aud;

>      int profile;

> +    int tier;

>      int level;

>      int sei;

>  

> @@ -315,7 +317,7 @@ static int

> vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)

>      ptl->general_profile_space = 0;

>      ptl->general_profile_space = 0;

>      ptl->general_profile_idc   = avctx->profile;

> -    ptl->general_tier_flag     = 0;

> +    ptl->general_tier_flag     = priv->tier;

>  

>      if (chroma_format == 1) {

>          ptl->general_profile_compatibility_flag[1] = bit_depth ==  8;

> @@ -340,7 +342,25 @@ static int

> vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)

>  

>      ptl->general_lower_bit_rate_constraint_flag = 1;

>  

> -    ptl->general_level_idc = avctx->level;

> +    if (avctx->level != FF_LEVEL_UNKNOWN) {

> +        ptl->general_level_idc = avctx->level;


Fist check whether the level idc is legal? User may set a level which can not 
be found in h265_levels. 

> +    } else {

> +        const H265LevelDescriptor *level;

> +

> +        level = ff_h265_guess_level(ptl, avctx->bit_rate,

> +                                    ctx->surface_width, ctx->surface_height,

> +                                    1, 1, 1, (ctx->b_per_p > 0) + 1);

> +        if (level) {

> +            av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name);

> +            ptl->general_level_idc = level->level_idc;

> +        } else {

> +            av_log(avctx, AV_LOG_VERBOSE, "Stream will not conform to "

> +                   "any normal level; using level 8.5.\n");

> +            ptl->general_level_idc = 255;

> +            // The tier flag must be set in level 8.5.

> +            ptl->general_tier_flag = 1;

> +        }

> +    }

>  

>      vps->vps_sub_layer_ordering_info_present_flag = 0;

>      vps->vps_max_dec_pic_buffering_minus1[0]      = (ctx->b_per_p > 0) + 1;

> @@ -1146,9 +1166,17 @@ static const AVOption vaapi_encode_h265_options[] = {

>      { PROFILE("rext",               FF_PROFILE_HEVC_REXT) },

>  #undef PROFILE

>  

> +    { "tier", "Set tier (general_tier_flag)",

> +      OFFSET(tier), AV_OPT_TYPE_INT,

> +      { .i64 = 0 }, 0, 1, FLAGS, "tier" },

> +    { "main", NULL, 0, AV_OPT_TYPE_CONST,

> +      { .i64 = 0 }, 0, 0, FLAGS, "tier" },

> +    { "high", NULL, 0, AV_OPT_TYPE_CONST,

> +      { .i64 = 1 }, 0, 0, FLAGS, "tier" },

> +

>      { "level", "Set level (general_level_idc)",

>        OFFSET(level), AV_OPT_TYPE_INT,

> -      { .i64 = 153 }, 0x00, 0xff, FLAGS, "level" },

> +      { .i64 = FF_LEVEL_UNKNOWN }, FF_LEVEL_UNKNOWN, 0xff, FLAGS, "level" },

>  

>  #define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \

>        { .i64 = value }, 0, 0, FLAGS, "level"
Mark Thompson June 17, 2018, 2:34 p.m.
On 15/06/18 05:22, Xiang, Haihao wrote:
> On Fri, 2018-06-08 at 00:43 +0100, Mark Thompson wrote:
>> Sets the level based on the stream properties if it is not explicitly
>> set by the user.  Also add a tier option to set general_tier_flag, since
>> that affects the level choice.
>> ---
>>  doc/encoders.texi              |  4 ++++
>>  libavcodec/vaapi_encode_h265.c | 34 +++++++++++++++++++++++++++++++---
>>  2 files changed, 35 insertions(+), 3 deletions(-)
>>
>> ...
>> diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
>> index 2cee19be68..100f8338d7 100644
>> --- a/libavcodec/vaapi_encode_h265.c
>> +++ b/libavcodec/vaapi_encode_h265.c
>> @@ -30,6 +30,7 @@
>>  #include "avcodec.h"
>>  #include "cbs.h"
>>  #include "cbs_h265.h"
>> +#include "h265_profile_level.h"
>>  #include "hevc.h"
>>  #include "hevc_sei.h"
>>  #include "internal.h"
>> @@ -48,6 +49,7 @@ typedef struct VAAPIEncodeH265Context {
>>      int qp;
>>      int aud;
>>      int profile;
>> +    int tier;
>>      int level;
>>      int sei;
>>  
>> @@ -315,7 +317,7 @@ static int
>> vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)
>>      ptl->general_profile_space = 0;
>>      ptl->general_profile_space = 0;
>>      ptl->general_profile_idc   = avctx->profile;
>> -    ptl->general_tier_flag     = 0;
>> +    ptl->general_tier_flag     = priv->tier;
>>  
>>      if (chroma_format == 1) {
>>          ptl->general_profile_compatibility_flag[1] = bit_depth ==  8;
>> @@ -340,7 +342,25 @@ static int
>> vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)
>>  
>>      ptl->general_lower_bit_rate_constraint_flag = 1;
>>  
>> -    ptl->general_level_idc = avctx->level;
>> +    if (avctx->level != FF_LEVEL_UNKNOWN) {
>> +        ptl->general_level_idc = avctx->level;
> 
> Fist check whether the level idc is legal? User may set a level which can not 
> be found in h265_levels. 

The user should be able to specify an arbitrary value explicitly.  As for H.264 I'll add a check that this fits in the 8-bit field, though.

>> +    } else {
>> +        const H265LevelDescriptor *level;
>> +
>> +        level = ff_h265_guess_level(ptl, avctx->bit_rate,
>> +                                    ctx->surface_width, ctx->surface_height,
>> +                                    1, 1, 1, (ctx->b_per_p > 0) + 1);
>> +        if (level) {
>> +            av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name);
>> +            ptl->general_level_idc = level->level_idc;
>> +        } else {
>> +            av_log(avctx, AV_LOG_VERBOSE, "Stream will not conform to "
>> +                   "any normal level; using level 8.5.\n");
>> +            ptl->general_level_idc = 255;
>> +            // The tier flag must be set in level 8.5.
>> +            ptl->general_tier_flag = 1;
>> +        }
>> +    }
>>  
>>      vps->vps_sub_layer_ordering_info_present_flag = 0;
>>      vps->vps_max_dec_pic_buffering_minus1[0]      = (ctx->b_per_p > 0) + 1;
>> @@ -1146,9 +1166,17 @@ static const AVOption vaapi_encode_h265_options[] = {
>>      { PROFILE("rext",               FF_PROFILE_HEVC_REXT) },
>>  #undef PROFILE
>>  
>> +    { "tier", "Set tier (general_tier_flag)",
>> +      OFFSET(tier), AV_OPT_TYPE_INT,
>> +      { .i64 = 0 }, 0, 1, FLAGS, "tier" },
>> +    { "main", NULL, 0, AV_OPT_TYPE_CONST,
>> +      { .i64 = 0 }, 0, 0, FLAGS, "tier" },
>> +    { "high", NULL, 0, AV_OPT_TYPE_CONST,
>> +      { .i64 = 1 }, 0, 0, FLAGS, "tier" },
>> +
>>      { "level", "Set level (general_level_idc)",
>>        OFFSET(level), AV_OPT_TYPE_INT,
>> -      { .i64 = 153 }, 0x00, 0xff, FLAGS, "level" },
>> +      { .i64 = FF_LEVEL_UNKNOWN }, FF_LEVEL_UNKNOWN, 0xff, FLAGS, "level" },
>>  
>>  #define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
>>        { .i64 = value }, 0, 0, FLAGS, "level"

Thanks,

- Mark

Patch hide | download patch | download mbox

diff --git a/doc/encoders.texi b/doc/encoders.texi
index ceddfdda64..d61a1cc4bc 100644
--- a/doc/encoders.texi
+++ b/doc/encoders.texi
@@ -2659,6 +2659,10 @@  Include recovery points where appropriate (@emph{recovery_point} messages).
 @item aud
 Include access unit delimiters in the stream (not included by default).
 
+@item tier
+Set @emph{general_tier_flag}.  This may affect the level chosen for the stream
+if it is not explicitly specified.
+
 @end table
 
 @item mjpeg_vaapi
diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
index 2cee19be68..100f8338d7 100644
--- a/libavcodec/vaapi_encode_h265.c
+++ b/libavcodec/vaapi_encode_h265.c
@@ -30,6 +30,7 @@ 
 #include "avcodec.h"
 #include "cbs.h"
 #include "cbs_h265.h"
+#include "h265_profile_level.h"
 #include "hevc.h"
 #include "hevc_sei.h"
 #include "internal.h"
@@ -48,6 +49,7 @@  typedef struct VAAPIEncodeH265Context {
     int qp;
     int aud;
     int profile;
+    int tier;
     int level;
     int sei;
 
@@ -315,7 +317,7 @@  static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)
     ptl->general_profile_space = 0;
     ptl->general_profile_space = 0;
     ptl->general_profile_idc   = avctx->profile;
-    ptl->general_tier_flag     = 0;
+    ptl->general_tier_flag     = priv->tier;
 
     if (chroma_format == 1) {
         ptl->general_profile_compatibility_flag[1] = bit_depth ==  8;
@@ -340,7 +342,25 @@  static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)
 
     ptl->general_lower_bit_rate_constraint_flag = 1;
 
-    ptl->general_level_idc = avctx->level;
+    if (avctx->level != FF_LEVEL_UNKNOWN) {
+        ptl->general_level_idc = avctx->level;
+    } else {
+        const H265LevelDescriptor *level;
+
+        level = ff_h265_guess_level(ptl, avctx->bit_rate,
+                                    ctx->surface_width, ctx->surface_height,
+                                    1, 1, 1, (ctx->b_per_p > 0) + 1);
+        if (level) {
+            av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name);
+            ptl->general_level_idc = level->level_idc;
+        } else {
+            av_log(avctx, AV_LOG_VERBOSE, "Stream will not conform to "
+                   "any normal level; using level 8.5.\n");
+            ptl->general_level_idc = 255;
+            // The tier flag must be set in level 8.5.
+            ptl->general_tier_flag = 1;
+        }
+    }
 
     vps->vps_sub_layer_ordering_info_present_flag = 0;
     vps->vps_max_dec_pic_buffering_minus1[0]      = (ctx->b_per_p > 0) + 1;
@@ -1146,9 +1166,17 @@  static const AVOption vaapi_encode_h265_options[] = {
     { PROFILE("rext",               FF_PROFILE_HEVC_REXT) },
 #undef PROFILE
 
+    { "tier", "Set tier (general_tier_flag)",
+      OFFSET(tier), AV_OPT_TYPE_INT,
+      { .i64 = 0 }, 0, 1, FLAGS, "tier" },
+    { "main", NULL, 0, AV_OPT_TYPE_CONST,
+      { .i64 = 0 }, 0, 0, FLAGS, "tier" },
+    { "high", NULL, 0, AV_OPT_TYPE_CONST,
+      { .i64 = 1 }, 0, 0, FLAGS, "tier" },
+
     { "level", "Set level (general_level_idc)",
       OFFSET(level), AV_OPT_TYPE_INT,
-      { .i64 = 153 }, 0x00, 0xff, FLAGS, "level" },
+      { .i64 = FF_LEVEL_UNKNOWN }, FF_LEVEL_UNKNOWN, 0xff, FLAGS, "level" },
 
 #define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
       { .i64 = value }, 0, 0, FLAGS, "level"