# Features

## External Input

The EIL can be configured to accept externally allocated input frames. To do this, the integration should set `external_input` in `EILInitSettings` to true. When configured in this mode, the EIL will not allocate any pictures itself, and so `EIL_GetPicture` will always fail.

In external input mode, the integration must create the `EILPicture` object itself. The object can be default initialised using `EIL_InitPictureDefault`. The integration then must set the `plane` pointers to memory it has allocated and `stride` to the number of bytes per line. The other fields are then used in the same manner as when external input is disabled.

The planes must be valid from the point that the picture is passed to `EIL_Encode`, until the associated output is produced.

The EIL can also accept Android hardware buffers in this mode when the EIL is configured for GPU mode. To do this the picture's `memory_type` is set to `EIL_MT_AHardwareBuffer` and the plane pointers are set to `AHardwareBuffer`.

```c
bool InitialiseExteranlInput(EILContext context)
{
    EILInitSettings settings;
    EILReturnCode   rc = EIL_InitSettingsDefault(&settings);

    settings.width          = 1920;
    settings.height         = 1080;
    settings.fps_num        = 25;
    settings.fps_denom      = 1;
    settings.bitrate        = 3000; // NB: This is in kbps
    settings.external_input = 1;

    // The properties are usually generated from user input
    settings.properties_json = "{ \"encoding_transform_type\": \"dds\" }";

    if ((rc = EIL_Initialise(context, &settings)) != EIL_RC_Success)
    {
        fprintf(stderr, "Unable to intiailise the EIL: %s\n",
                EIL_GetErrorString(rc));
        return false;
    }

    return true;
}

bool EncodeExternalInput(EILContext context, int64_t pts)
{
    EILPicture* picture = (EILPicture*)malloc(sizeof(EILPicture));

    if (EIL_InitPictureDefault(picture) != EIL_RC_Success)
    {
        fprintf(stderr, "Unable to initialise picture object\n");
        return false;
    }

    // For the example the planes are allocated inline. These could just as
    // easily be set to pointers that already contain the frame data to
    // avoid copying the data.
    // Assuming 1080p YUV420p
    picture->pts        = pts;
    picture->num_planes = 3;
    picture->plane[0]   = malloc(1920 * 1080);
    picture->stride[0]  = 1080;
    picture->plane[1]   = malloc(960 * 540);
    picture->stride[1]  = 540;
    picture->plane[2]   = malloc(960 * 540);
    picture->stride[2]  = 540;
    picture->user_data  = picture;

    // populate the allocated planes with frame data

    EILReturnCode rc = EIL_Encode(context, picture);

    if (rc != EIL_RC_Success)
    {
        for (int i = 0; i < picture->num_planes; ++i)
            free(picture->plane[i]);

        fprintf(stderr, "Unable to encode frame: %s\n", EIL_GetErrorString(rc));
        return false;
    }

    return true;
}

bool HandleOutput(EILContext context)
{
    EILOutput*    output = NULL;
    EILReturnCode rc     = EIL_GetOutput(context, &output);

    if (rc != EIL_RC_Success)
    {
        if (rc != EIL_RC_Finished)
        {
            fprintf(stderr, "Unable to get output from the EIL: %s\n",
                    EIL_GetErrorString(rc));
            return false;
        }

        return true;
    }

    // pass the bitstream to a muxer
    mux(output->pts, output->dts, output->data, output->data_length);

    EILPicture* picture = (EILPicture*)output->user_data;

    for (int i = 0; i < picture->num_planes; ++i)
        free(picture->plane[i]);

    if ((rc = EIL_ReleaseOutput(context, output)) != EIL_RC_Success)
    {
        fprintf(stderr, "Unable to release output back to the EIL: %s\n",
                EIL_GetErrorString(rc));
        return false;
    }

    return true;
}
```

## Dynamic Reconfiguration

The EIL is able to reconfigure the target bitrate and framerate, if the base encoder also supports dynamic reconfiguration. This is done by passing `EILReconfigureSettings`, with the new values, to the `EIL_Reconfigure` function.

```c
bool Reconfigure(EILContext context)
{
    EILReconfigureSettings settings;

    if (EIL_ReconfigureSettingsDefault(&settings) != EIL_RC_Success)
    {
        fprintf(stderr, "Unable to default initialise reconfigure settings");
        return false;
    }

    settings.flags     = EIL_RF_Bitrate | EIL_RF_Framerate;
    settings.bitrate   = 5000;
    settings.fps_num   = 30;
    settings.fps_denom = 1;

    EILReturnCode rc = EIL_Reconfigure(context, &settings);

    if (rc != EIL_RC_Success)
    {
        fprintf(stderr, "Unable to reconfigure EIL: %s\n",
                EIL_GetErrorString(rc));
        return false;
    }

    return true;
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.v-nova.com/technologies/mpeg-5.lcevc/encoder/sdk/eil/features.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
