[FFmpeg-devel] [PATCH 1/5] lavc/qsvenc: add forced_idr opiton

Mark Thompson sw at jkqxz.net
Thu Nov 1 00:44:06 EET 2018


On 31/10/18 11:29, Li, Zhong wrote:
>> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces at ffmpeg.org] On Behalf
>> Of Mark Thompson
>> Sent: Wednesday, October 31, 2018 7:40 AM
>> To: ffmpeg-devel at ffmpeg.org
>> Subject: Re: [FFmpeg-devel] [PATCH 1/5] lavc/qsvenc: add forced_idr opiton
>>
>> On 30/10/18 09:49, Li, Zhong wrote:
>>>> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces at ffmpeg.org] On
>> Behalf
>>>> Of Mark Thompson
>>>> Sent: Tuesday, October 30, 2018 5:06 AM
>>>> To: ffmpeg-devel at ffmpeg.org
>>>> Subject: Re: [FFmpeg-devel] [PATCH 1/5] lavc/qsvenc: add forced_idr
>>>> opiton
>>>>
>>>> On 25/10/18 13:36, Zhong Li wrote:
>>>>> This option can be used to repect original input I/IDR frame type.
>>>>>
>>>>> Signed-off-by: Zhong Li <zhong.li at intel.com>
>>>>> ---
>>>>>  libavcodec/qsvenc.c | 7 +++++++
>>>>>  libavcodec/qsvenc.h | 2 ++
>>>>>  2 files changed, 9 insertions(+)
>>>>>
>>>>> diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index
>>>>> 948751d..e534dcf 100644
>>>>> --- a/libavcodec/qsvenc.c
>>>>> +++ b/libavcodec/qsvenc.c
>>>>> @@ -1192,6 +1192,13 @@ static int encode_frame(AVCodecContext
>>>> *avctx, QSVEncContext *q,
>>>>>      if (qsv_frame) {
>>>>>          surf = &qsv_frame->surface;
>>>>>          enc_ctrl = &qsv_frame->enc_ctrl;
>>>>> +
>>>>> +        if (q->forced_idr >= 0 && frame->pict_type ==
>>>> AV_PICTURE_TYPE_I) {
>>>>> +            enc_ctrl->FrameType = MFX_FRAMETYPE_I |
>>>> MFX_FRAMETYPE_REF;
>>>>> +            if (q->forced_idr || frame->key_frame)
>>>>> +                enc_ctrl->FrameType |= MFX_FRAMETYPE_IDR;
>>>>> +        } else
>>>>> +            enc_ctrl->FrameType = MFX_FRAMETYPE_UNKNOWN;
>>>>>      }
>>>>>
>>>>>      ret = av_new_packet(&new_pkt, q->packet_size); diff --git
>>>>> a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 055b4a6..1f97f77
>>>>> 100644
>>>>> --- a/libavcodec/qsvenc.h
>>>>> +++ b/libavcodec/qsvenc.h
>>>>> @@ -87,6 +87,7 @@
>>>>>  { "adaptive_i",     "Adaptive I-frame placement",
>>>> OFFSET(qsv.adaptive_i),     AV_OPT_TYPE_INT, { .i64 = -1 }, -1,
>>>> 1, VE },                         \
>>>>>  { "adaptive_b",     "Adaptive B-frame placement",
>>>> OFFSET(qsv.adaptive_b),     AV_OPT_TYPE_INT, { .i64 = -1 }, -1,
>>>> 1, VE },                         \
>>>>>  { "b_strategy",     "Strategy to choose between I/P/B-frames",
>>>> OFFSET(qsv.b_strategy),    AV_OPT_TYPE_INT, { .i64 = -1 }, -1,
>>>> 1, VE },                         \
>>>>> +{ "forced_idr",     "Forcing I frames as IDR frames",
>>>> OFFSET(qsv.forced_idr),     AV_OPT_TYPE_INT, { .i64 = -1 }, -1,
>>>> 1, VE },                         \
>>>>>
>>>>>  typedef int SetEncodeCtrlCB (AVCodecContext *avctx,
>>>>>                               const AVFrame *frame,
>>>> mfxEncodeCtrl*
>>>>> enc_ctrl); @@ -168,6 +169,7 @@ typedef struct QSVEncContext
>> {  #endif
>>>>>      char *load_plugins;
>>>>>      SetEncodeCtrlCB *set_encode_ctrl_cb;
>>>>> +    int forced_idr;
>>>>>  } QSVEncContext;
>>>>>
>>>>>  int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q);
>>>>>
>>>>
>>>> This seems confusing, because it doesn't match what forced_idr does
>>>> in any other encoder.
>>>>
>>>> Checking of pict_type for AV_PICTURE_TYPE_I in order to get a key
>>>> frame (of whatever kind) is always enabled if supported (many
>>>> encoders).  The "forced_idr" option to H.26[45] encoders (libx264,
>>>> libx265) then forces that to be an IDR frame, not just an I frame.
>>>>
>>>> - Mark
>>> Yup, I know it doesn’t match other encoders such as
>> libx264/libx265/nvenc.
>>> However, it is my intentional behavior. I believe current implement in
>> libx264/libx265 is not complete.
>>> One case is ignored: user just want to keep the gop structure as input, not
>> to force all I frames as IDR frames.
>>> So I have an idea:
>>> Default value = -1, ignore the input gop structure.
>>> 0: respect input gop structure but don't force I frame as IDR frame.
>>> 1: force all I frame as IDR frame.
>>
>> This sounds like two independent options.  One is the "forced-idr" option
>> implemented by several other encoders (notably libx264, which is the most
>> commonly-used external encoder), which looks like a sensible addition to me.
>> The second is an "ignore user-set pict_type" option, which I don't understand
>> the need for at all - it's never set unless the user deliberately wants to use
>> that feature (e.g. by using the force_key_frames option in the ffmpeg utility),
>> so why would you want to have a special way to override that?
> 
> I may miss something. The default case (forced_idr = -1) is do nothing, ignoring the input I frames. 
> Which is same as default case of x264/x265/nvenc forced_idr.  

No it isn't.

>From libavcodec/libx264.c:

> static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame,
>                       int *got_packet)
> {
>     ...
>     if (frame) {
>         ...
>         switch (frame->pict_type) {
>         case AV_PICTURE_TYPE_I:
>             x4->pic.i_type = x4->forced_idr > 0 ? X264_TYPE_IDR
>                                                 : X264_TYPE_KEYFRAME;
>             break;
>         case AV_PICTURE_TYPE_P:
>             x4->pic.i_type = X264_TYPE_P;
>             break;
>         case AV_PICTURE_TYPE_B:
>             x4->pic.i_type = X264_TYPE_B;
>             break;
>         default:
>             x4->pic.i_type = X264_TYPE_AUTO;
>             break;
>         }

The input pict_type is always used, and forced_idr indicates that a forced intra frame must be IDR.

> Vaapi encoder is different from others, there is no forced_idr option but an internal variable named force_idr, always set IDR if the input frame is I frame. (Please correct me if I am wrong)

Yeah, VAAPI just supports the force-frame feature in the simplest possible way, giving you an IDR frame (well, or codec-dependent equivalent - KEY for VP9, etc.) if you ask for anything intra.

Thanks,

- Mark


More information about the ffmpeg-devel mailing list