> > +static void AMF_CDECL_CALL AMFTraceWriter_Write(AMFTraceWriter
> *pThis,
> > +    const wchar_t *scope, const wchar_t *message)
> > +{
> > +    AmfTraceWriter *tracer = (AmfTraceWriter*)pThis;
> > +    av_log(tracer->avctx, AV_LOG_DEBUG, "%ls: %ls", scope, message);
> 
> Does the message necessarily include a newline already?
Yes.

> > +    init_fun = (AMFInit_Fn)dlsym(ctx->library,
> AMF_INIT_FUNCTION_NAME);
> > +    AMF_RETURN_IF_FALSE(ctx, init_fun != NULL, AVERROR_UNKNOWN,
> "DLL %s failed to find function %s. \n", AMF_DLL_NAMEA,
> AMF_INIT_FUNCTION_NAME);
> 
> I think do s/ \n/\n/ for all of these messages.

Sorry, didn't get this.

> 
> > +
> > +    version_fun = (AMFQueryVersion_Fn)dlsym(ctx->library,
> AMF_QUERY_VERSION_FUNCTION_NAME);
> > +    AMF_RETURN_IF_FALSE(ctx, version_fun != NULL,
> AVERROR_UNKNOWN, "DLL %s failed to find function %s. \n",
> AMF_DLL_NAMEA, AMF_QUERY_VERSION_FUNCTION_NAME);
> > +
> > +    res = version_fun(&ctx->version);
> > +    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "%s
> failed with error %d. \n", AMF_QUERY_VERSION_FUNCTION_NAME, res);
> > +    res = init_fun(AMF_FULL_VERSION, &ctx->factory);
> > +    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "%s
> failed with error %d. \n", AMF_INIT_FUNCTION_NAME, res);
> > +    res = ctx->factory->pVtbl->GetTrace(ctx->factory, &ctx->trace);
> > +    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN,
> "GetTrace() failed with error %d. \n", res);
> > +    res = ctx->factory->pVtbl->GetDebug(ctx->factory, &ctx->debug);
> > +    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN,
> "GetDebug() failed with error %d. \n", res);
> > +    return 0;
> > +}
> > +
> > +static int amf_init_context(AVCodecContext *avctx)
> > +{
> > +    AmfContext         *ctx = avctx->priv_data;
> > +    AMF_RESULT          res = AMF_OK;
> > +
> > +    // the return of these functions indicates old state and do not affect
> behaviour
> > +    ctx->trace->pVtbl->EnableWriter(ctx->trace,
> AMF_TRACE_WRITER_CONSOLE, 0);
> > +#if AMF_DEBUG_TRACE
> > +    ctx->trace->pVtbl->EnableWriter(ctx->trace,
> AMF_TRACE_WRITER_DEBUG_OUTPUT, 1);
> > +    ctx->trace->pVtbl->SetWriterLevel(ctx->trace,
> AMF_TRACE_WRITER_DEBUG_OUTPUT, AMF_TRACE_TRACE);
> > +    ctx->trace->pVtbl->SetGlobalLevel(ctx->trace, AMF_TRACE_TRACE);
> > +#else
> > +    ctx->trace->pVtbl->EnableWriter(ctx->trace,
> AMF_TRACE_WRITER_DEBUG_OUTPUT, 0);
> > +#endif
> 
> I don't much like this compile-time option.  What sort of messages does the
> trace writer actually give you?  Will a user ever want to enable it?

Two points:
1. There is extensive AMF logging that can help diagnose a problem. Do we want 
to have it all time in AV_LOG_DEBUG?
2. AMD can trace to debug output and this is useful but for normal ffmpeg 
operation it is under #ifdef.

> 
> > +
> > +static GUID  AMFTextureArrayIndexGUID =
> AMFTextureArrayIndexGUIDDef;
> 
> GUID is a Windows type, should this be AMFGuid?  (I tried removing the
> check and compiling on Linux, other than the D3D11 stuff this is the only
> error.)
> 

This is Windows type and used with Windows interface ID3D11Texture2D.
When Linux support is added all this section will be under #ifdef.

> > +
> > +int ff_amf_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
> > +                        const AVFrame *frame, int *got_packet)
> > +{
> > +    int             ret = 0;
> > +    AMF_RESULT      res = AMF_OK;
> > +    AmfContext     *ctx = avctx->priv_data;
> > +    AMFSurface     *surface = NULL;
> > +    AMFData        *data = NULL;
> > +    amf_bool       submitted = 0;
> > +
> > +    while (!submitted) {
> > +        if (!frame) { // submit drain
> > +            if (!ctx->eof) { // submit drain onre time only
> > +                res = ctx->encoder->pVtbl->Drain(ctx->encoder);
> > +                if (res == AMF_INPUT_FULL) {
> > +                    av_usleep(1000); // input queue is full: wait, poll 
> > and submit
> Drain again
> > +                                     // need to get some output and try 
> > again
> > +                } else if (res == AMF_OK) {
> > +                    ctx->eof = 1; // drain started
> > +                    submitted = 1;
> > +                }
> > +            }
> > +        } else { // submit frame
> > +            if (surface == NULL) { // prepare surface from frame one time 
> > only
> > +                if (frame->hw_frames_ctx && ( // HW frame detected
> > +                                              // check if the same 
> > hw_frames_ctx as used in
> initialization
> > +                    (ctx->hw_frames_ctx && frame->hw_frames_ctx->data == 
> > ctx-
> >hw_frames_ctx->data) ||
> > +                    // check if the same hw_device_ctx as used in 
> > initialization
> > +                    (ctx->hw_device_ctx && ((AVHWFramesContext*)frame-
> >hw_frames_ctx->data)->device_ctx ==
> > +                    (AVHWDeviceContext*)ctx->hw_device_ctx->data)
> > +                )) {
> > +                    ID3D11Texture2D* texture = (ID3D11Texture2D*)frame-
> >data[0]; // actual texture
> > +                    int index = (int)(size_t)frame->data[1]; // index is a 
> > slice in
> texture array is - set to tell AMF which slice to use
> 
> (int)(intptr_t)frame->data[1];
> 
> > +                    texture->lpVtbl->SetPrivateData(texture,
> &AMFTextureArrayIndexGUID, sizeof(index), &index);
> > +
> > +                    res = 
> > ctx->context->pVtbl->CreateSurfaceFromDX11Native(ctx-
> >context, texture, &surface, NULL); // wrap to AMF surface
> > +                    surface->pVtbl->SetCrop(surface, 0, 0, frame->width, 
> > frame-
> >height); // decode surfaces are vertically aligned by 16 tell AMF real size
> 
> "decode surfaces"?  These need not come from a decoder.  Does it work with
> hwupload?
> 
> > +                    surface->pVtbl->SetPts(surface, frame->pts);
> > +                } else {
> > +                    res = ctx->context->pVtbl->AllocSurface(ctx->context,
> AMF_MEMORY_HOST, ctx->format, avctx->width, avctx->height, &surface);
> > +                    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG,
> "AllocSurface() failed  with error %d \n", res);
> > +                    amf_copy_surface(avctx, frame, surface);
> > +                }
> > +            }
> > +            // encode
> > +            res = ctx->encoder->pVtbl->SubmitInput(ctx->encoder,
> (AMFData*)surface);
> > +            if (res == AMF_INPUT_FULL) { // handle full queue
> > +                av_usleep(1000); // input queue is full: wait, poll and 
> > submit
> surface again
> > +            } else {
> > +                surface->pVtbl->Release(surface);
> > +                surface = NULL;
> > +                AMF_RETURN_IF_FALSE(ctx, res == AMF_OK,
> AVERROR_UNKNOWN, "SubmitInput() failed with error %d \n", res);
> > +                submitted = 1;
> > +            }
> > +        }
> > +        // poll results
> > +        if (!data) {
> > +            res = ctx->encoder->pVtbl->QueryOutput(ctx->encoder, &data);
> > +            if (data) {
> > +                AMFBuffer* buffer;
> > +                AMFGuid guid = IID_AMFBuffer();
> > +                data->pVtbl->QueryInterface(data, &guid, (void**)&buffer); 
> > //
> query for buffer interface
> > +                ret = amf_copy_buffer(avctx, pkt, buffer);
> > +                if (!ret)
> > +                    *got_packet = 1;
> > +                buffer->pVtbl->Release(buffer);
> > +                data->pVtbl->Release(data);
> > +                if (ctx->eof) {
> > +                    submitted = 1; // we are in the drain state - no 
> > submissions
> > +                }
> > +            } else if (res == AMF_EOF) {
> > +                submitted = 1; // drain complete
> > +            } else {
> > +                if (!submitted) {
> > +                    av_usleep(1000); // wait and poll again
> > +                }
> > +            }
> > +        }
> > +    }
> > +    return ret;
> > +}
> 
> I still think this would be much better off using the
> send_frame()/receive_packet() API.  Even if your API doesn't expose any
> information about the queue length, you only need to hold a single input
> frame transiently to get around that (the user is not allowed to call
> send_frame() twice in a row without calling receive_packet()).
> 

So to implement this I would have to:
- in the send_frame() if AMF_INPUT_FULL is returned - store input frame (or 
copy?)
- In the next receive_frame() check if frame is stored
- Wait till some output is produced
- resubmit stored frame
Issues I see:
- Isn't this logic defeat the purpose of independent send()/receive()?
- How can I report a error if receive() produced a compressed frame but the 
delayed submission failed?
- This logic depends on the particular logic in the calling code.
- This logic depends on the particular HW behaviour. 
- In the future, we would like to output individual slices of a compressed 
frame. 
When this added receive_frame() must be called several times to clear space in 
the HW queue. 
Granted, current implementation also does not cover this case but truly 
independent 
send/receive implementation would. 


> > +static const AVOption options[] = {
> > +    // Static
> > +    /// Usage
> > +    { "usage",          "Encoder Usage",        OFFSET(usage),
> AV_OPT_TYPE_INT,   { .i64 = AMF_VIDEO_ENCODER_USAGE_TRANSCONDING
> }, AMF_VIDEO_ENCODER_USAGE_TRANSCONDING,
> AMF_VIDEO_ENCODER_USAGE_WEBCAM, VE, "usage" },
> > +    { "transcoding",    "Generic Transcoding",  0,
> AV_OPT_TYPE_CONST, { .i64 =
> AMF_VIDEO_ENCODER_USAGE_TRANSCONDING      }, 0, 0, VE, "usage" },
> > +    { "ultralowlatency","",                     0,              
> > AV_OPT_TYPE_CONST, { .i64
> = AMF_VIDEO_ENCODER_USAGE_ULTRA_LOW_LATENCY }, 0, 0, VE, "usage"
> },
> > +    { "lowlatency",     "",                     0,              
> > AV_OPT_TYPE_CONST, { .i64 =
> AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY       }, 0, 0, VE, "usage" },
> > +    { "webcam",         "Webcam",               0,              
> > AV_OPT_TYPE_CONST, {
> .i64 = AMF_VIDEO_ENCODER_USAGE_WEBCAM            }, 0, 0, VE, "usage" },
> > +
> > +    /// Profile,
> > +    { "profile",        "Profile",              
> > OFFSET(profile),AV_OPT_TYPE_INT, {
> .i64 = AMF_VIDEO_ENCODER_PROFILE_MAIN       },
> AMF_VIDEO_ENCODER_PROFILE_BASELINE,
> AMF_VIDEO_ENCODER_PROFILE_HIGH, VE, "profile" },
> > +    { "baseline",       "",                     0,              
> > AV_OPT_TYPE_CONST, { .i64 =
> AMF_VIDEO_ENCODER_PROFILE_BASELINE }, 0, 0, VE, "profile" },
> 
> You still don't support baseline profile.

Talked to codec folks. Currently this is really baseline by mistake. The 
intention was to expose only 
"constrained baseline" They want to correct this but it should go into the 
driver first and then 
reflected in AMF API. Once done this entry will be updated.

> > +    /// Maximum Access Unit Size
> > +    { "max_au_size",    "Maximum Access Unit Size for rate control (in 
> > bits)",
> OFFSET(max_au_size),        AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE,
> NULL },
> 
> Did you check whether this really means the maximum access unit size?  If
> yes, what is the use-case for that?
> 

I've changed the description. This parameter is used in rate control to limit 
AU size. 
It is useful for streaming.

> > +    { "me_half_pel",    "Enable ME Half Pixel",
> OFFSET(me_half_pel),   AV_OPT_TYPE_BOOL,  { .i64 = 1 }, 0, 1, VE, NULL },
> > +    { "me_quater_pel",  "Enable ME Quarter Pixel ",
> OFFSET(me_quater_pel), AV_OPT_TYPE_BOOL,  { .i64 = 1 }, 0, 1, VE, NULL },
> 
> What is the use-case for these options?
> 

These are options for motion estimator precision. Spelling is corrected 
"me_quarter_pel"

> > +
> > +    { NULL }
> > +};
> > +
> > +static av_cold int amf_encode_init_h264(AVCodecContext *avctx)
> > +{
> > +    int                 ret = 0;
> > +    AMF_RESULT          res = AMF_OK;
> > +    AmfContext         *ctx = avctx->priv_data;
> > +    AMFVariantStruct    var = {0};
> > +    amf_int64           profile = 0;
> > +    amf_int64           profile_level = 0;
> > +    AMFBuffer          *buffer;
> > +    AMFGuid             guid;
> > +
> > +    AMFSize             framesize = AMFConstructSize(avctx->width, avctx-
> >height);
> > +    AMFRate             framerate = AMFConstructRate(avctx->time_base.den,
> avctx->time_base.num * avctx->ticks_per_frame);
> 
> avctx->framerate should be set if the input is CFR, use that first.
> 
> > +
> > +    int                 deblocking_filter = (avctx->flags &
> AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0;
> > +
> > +    if ((ret = ff_amf_encode_init(avctx)) != 0)
> > +        return ret;
> > +
> > +    // Static parameters
> > +    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_USAGE, ctx->usage);
> > +
> > +    AMF_ASSIGN_PROPERTY_SIZE(res, ctx->encoder,
> AMF_VIDEO_ENCODER_FRAMESIZE, framesize);
> > +
> > +    AMF_ASSIGN_PROPERTY_RATE(res, ctx->encoder,
> AMF_VIDEO_ENCODER_FRAMERATE, framerate);
> > +
> > +    profile = avctx->profile;
> 
> avctx->profile might be (is by default, even) FF_PROFILE_UNKNOWN, which is
> not zero.
> 
> > +    if (profile == 0) {
> > +        profile = ctx->profile;
> > +    }
> > +
> > +    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_PROFILE, profile);
> > +
> > +    profile_level = avctx->level;
> 
> Similarly FF_LEVEL_UNKNOWN.
> 
> > +    if (profile_level == 0) {
> > +        profile_level = ctx->level;
> > +    }
> > +    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_PROFILE_LEVEL, profile_level);
> > +
> > +    // Maximum Reference Frames
> > +    if (avctx->refs != -1) {
> > +        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_MAX_NUM_REFRAMES, avctx->refs);
> > +    }
> > +    if (avctx->sample_aspect_ratio.den && avctx-
> >sample_aspect_ratio.num) {
> > +        AMFRatio ratio = AMFConstructRatio(avctx-
> >sample_aspect_ratio.num, avctx->sample_aspect_ratio.den);
> > +        AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder,
> AMF_VIDEO_ENCODER_ASPECT_RATIO, ratio);
> > +    }
> > +
> > +    /// Color Range (Partial/TV/MPEG or Full/PC/JPEG)
> > +    if (avctx->color_range == AVCOL_RANGE_JPEG) {
> > +        AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder,
> AMF_VIDEO_ENCODER_FULL_RANGE_COLOR, 1);
> > +    }
> > +
> > +    if (ctx->rate_control_mode ==
> AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) {
> > +        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_RATE_CONTROL_PREANALYSIS_ENABLE,
> AMF_VIDEO_ENCODER_PREENCODE_DISABLED);
> > +        if (ctx->preanalysis)
> > +            av_log(ctx, AV_LOG_WARNING, "Pre-Analysis is not supported by
> cqp Rate Control Method, automatically disabled. \n");
> > +    } else {
> > +        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_RATE_CONTROL_PREANALYSIS_ENABLE, ctx-
> >preanalysis);
> > +    }
> > +
> > +    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_QUALITY_PRESET, ctx->quality);
> > +
> > +    // Initialize Encoder
> > +    res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx-
> >width, avctx->height);
> > +    AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder-
> >Init() failed with error %d \n", res);
> > +
> > +    // Dynamic parmaters
> > +    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD, ctx-
> >rate_control_mode);
> > +
> > +    /// VBV Buffer
> > +    if (avctx->rc_buffer_size != 0)
> > +        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_VBV_BUFFER_SIZE, avctx->rc_buffer_size);
> > +    if (avctx->rc_initial_buffer_occupancy != 0) {
> > +        int amf_buffer_fullness = avctx->rc_buffer_size * 64 / avctx-
> >rc_initial_buffer_occupancy;
> > +        if (amf_buffer_fullness > 64)
> > +            amf_buffer_fullness = 64;
> 
> I still don't understand what this is trying to do.
> 
> rc_initial_buffer_occupancy is necessarily at most rc_buffer_size, so the
> calculation will always get a number >= 64, so you always pass 64.
> 
> What are the units of
> AMF_VIDEO_ENCODER_INITIAL_VBV_BUFFER_FULLNESS meant to be?
> 

They meant to be an abstract value from 0 to 64 meaning 64 is 100%. Don’t ask 
me why ☹ 
Calculation should be the opposite. My fault. 

> > +        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_INITIAL_VBV_BUFFER_FULLNESS,
> amf_buffer_fullness);
> > +    }
> > +    /// Maximum Access Unit Size
> > +    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_MAX_AU_SIZE, ctx->max_au_size);
> > +
> > +    // QP Minimum / Maximum
> > +    if (ctx->rate_control_mode ==
> AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) {
> > +        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_MIN_QP, 0);
> > +        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_MAX_QP, 51);
> > +    } else {
> > +        if (avctx->qmin != -1) {
> > +            int qval = avctx->qmin > 51 ? 51 : avctx->qmin;
> > +            AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_MIN_QP, qval);
> > +        }
> > +        if (avctx->qmax != -1) {
> > +            int qval = avctx->qmax > 51 ? 51 : avctx->qmax;
> > +            AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_MAX_QP, qval);
> > +        }
> > +    }
> > +    // QP Values
> > +    if (ctx->qp_i != -1)
> > +        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_QP_I, ctx->qp_i);
> > +    if (ctx->qp_p != -1)
> > +        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_QP_P, ctx->qp_p);
> > +    if (ctx->qp_b != -1)
> > +        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_QP_B, ctx->qp_b);
> > +
> > +    // Bitrate
> > +    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_TARGET_BITRATE, avctx->bit_rate);
> > +
> > +    // Peak (max) bitrate. If not set make it out of bit_rate for best 
> > results.
> > +    if (ctx->rate_control_mode ==
> AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR) {
> > +        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_PEAK_BITRATE, avctx->bit_rate);
> > +    } else {
> > +        int rc_max_rate = avctx->rc_max_rate >= avctx->bit_rate ? avctx-
> >rc_max_rate : avctx->bit_rate * 13 / 10;
> 
> Please calculate a real value here as suggested in the previous comments
> rather than using 13/10.

The suggestion was to set rc_max_rate to infinity. This will produce 
unpredicted results. 
I can set it to bit_rate but quality will be not good. Another option would be 
to generate error.
I am open to suggestions.

> > +    { "max_au_size",    "Max AU Size in bits",
> OFFSET(max_au_size),   AV_OPT_TYPE_INT,{ .i64 = 0 }, 0, INT_MAX, VE, NULL
> },
> 
> Same question as in H.264.  Also other stuff below.
> 
> > +    { "min_qp_i",       "min quantization parameter for I-frame",
> OFFSET(min_qp_i),      AV_OPT_TYPE_INT,{ .i64 = -1 }, -1, 51, VE },
> > +    { "max_qp_i",       "max quantization parameter for I-frame",
> OFFSET(max_qp_i),      AV_OPT_TYPE_INT,{ .i64 = -1 }, -1, 51, VE },
> > +    { "min_qp_p",       "min quantization parameter for P-frame",
> OFFSET(min_qp_p),      AV_OPT_TYPE_INT,{ .i64 = -1 }, -1, 51, VE },
> > +    { "max_qp_p",       "max quantization parameter for P-frame",
> OFFSET(max_qp_p),      AV_OPT_TYPE_INT,{ .i64 = -1 }, -1, 51, VE },
> > +    { "qp_p",           "quantization parameter for P-frame",       
> > OFFSET(qp_p),
> AV_OPT_TYPE_INT,{ .i64 = -1 }, -1, 51, VE },
> > +    { "qp_i",           "quantization parameter for I-frame",       
> > OFFSET(qp_i),
> AV_OPT_TYPE_INT,{ .i64 = -1 }, -1, 51, VE },
> > +    { "skip_frame",     "Rate Control Based Frame Skip",
> OFFSET(skip_frame),    AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE, NULL },
> > +    { "me_half_pel",    "Enable ME Half Pixel",
> OFFSET(me_half_pel),   AV_OPT_TYPE_BOOL,{ .i64 = 1 }, 0, 1, VE, NULL },
> > +    { "me_quater_pel",  "Enable ME Quarter Pixel ",
> OFFSET(me_quater_pel), AV_OPT_TYPE_BOOL,{ .i64 = 1 }, 0, 1, VE, NULL },
> > +
> > +    { NULL }
> > +};
> > +
> > +static av_cold int amf_encode_init_hevc(AVCodecContext *avctx)
> > +{
> > +    int                 ret = 0;
> > +    AMF_RESULT          res = AMF_OK;
> > +    AmfContext         *ctx = avctx->priv_data;
> > +    AMFVariantStruct    var = {0};
> > +    amf_int64           profile = 0;
> > +    amf_int64           profile_level = 0;
> > +    AMFBuffer          *buffer;
> > +    AMFGuid             guid;
> > +
> > +    AMFSize             framesize = AMFConstructSize(avctx->width, avctx-
> >height);
> > +    AMFRate             framerate = AMFConstructRate(avctx->time_base.den,
> avctx->time_base.num * avctx->ticks_per_frame);
> > +
> > +    int                 deblocking_filter = (avctx->flags &
> AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0;
> > +
> > +    if ((ret = ff_amf_encode_init(avctx)) < 0)
> > +        return ret;
> > +
> > +    // init static parameters
> > +    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_HEVC_USAGE, ctx->usage);
> > +
> > +    AMF_ASSIGN_PROPERTY_SIZE(res, ctx->encoder,
> AMF_VIDEO_ENCODER_HEVC_FRAMESIZE, framesize);
> > +
> > +    AMF_ASSIGN_PROPERTY_RATE(res, ctx->encoder,
> AMF_VIDEO_ENCODER_HEVC_FRAMERATE, framerate);
> > +
> > +    switch (avctx->profile) {
> > +    case FF_PROFILE_HEVC_MAIN:
> > +        profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN;
> > +        break;
> > +    default:
> > +        break;
> > +    }
> > +    if (profile == 0) {
> > +        profile = ctx->profile;
> > +    }
> > +    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_HEVC_PROFILE, profile);
> > +
> > +    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_HEVC_TIER, ctx->tier);
> > +
> > +    profile_level = avctx->level;
> > +    if (profile_level == 0) {
> > +        profile_level = ctx->level;
> > +    }
> > +    if (profile_level != 0) {
> > +        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_HEVC_PROFILE_LEVEL, profile_level);
> > +    }
> > +    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET, ctx->quality);
> > +    // Maximum Reference Frames
> > +    if (avctx->refs != 0) {
> > +        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_HEVC_MAX_NUM_REFRAMES, avctx->refs);
> > +    }
> > +    // Aspect Ratio
> > +    if (avctx->sample_aspect_ratio.den && avctx-
> >sample_aspect_ratio.num) {
> > +        AMFRatio ratio = AMFConstructRatio(avctx-
> >sample_aspect_ratio.num, avctx->sample_aspect_ratio.den);
> > +        AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder,
> AMF_VIDEO_ENCODER_HEVC_ASPECT_RATIO, ratio);
> > +    }
> > +
> > +    // Picture control properties
> > +    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_HEVC_NUM_GOPS_PER_IDR, ctx->gops_per_idr);
> > +    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_HEVC_GOP_SIZE, avctx->gop_size);
> > +    if (avctx->slices > 1) {
> > +        AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder,
> AMF_VIDEO_ENCODER_HEVC_SLICES_PER_FRAME, avctx->slices);
> > +    }
> > +    AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder,
> AMF_VIDEO_ENCODER_HEVC_DE_BLOCKING_FILTER_DISABLE,
> deblocking_filter);
> 
> What about SAO?

SAO ???

> 
> >
> 
> Thanks,
> 
> - Mark
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Thanks,
Mikhail
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to