Jabu
Jabu

Reputation: 132

AVIF encoder fails when reused

When i try to encode a same image but with new pixels and using the encoder cached on header, it fails at result = avifEncoderWrite(encoder, image, &avifOutput);

with error: AVIF_RESULT_ENCODE_COLOR_FAILED

Is it not possible to reutilize the encoder/image?

avifEncoder* encoder      = nullptr;
avifImage*   image        = nullptr;
avifRGBImage avifRgb      = {};
avifRWData   avifOutput   = AVIF_DATA_EMPTY; 

void initializeAVIF()
{
    encoder = avifEncoderCreate();
    if (!encoder)
    {
        std::cerr << "Failed to create AVIF encoder" << std::endl;
        return;
    }

    encoder->maxThreads   = std::thread::hardware_concurrency();  // Adjust based on your needs
    encoder->speed        = 10; // Fastest encoding (0 = slowest/best, 10 = fastest)
    encoder->minQuantizer = 30; // Higher = more compression/lower quality
    encoder->maxQuantizer = 30; // Keep both quantizers equal for consistent quality
    
    image = avifImageCreate(width, height, 8, AVIF_PIXEL_FORMAT_YUV444);
    if (!image)
    {
        std::cerr << "Failed to create AVIF image" << std::endl;
        avifEncoderDestroy(encoder);
        return;
    }

    // Configure image properties
    image->colorPrimaries          = AVIF_COLOR_PRIMARIES_BT709;
    image->transferCharacteristics = AVIF_TRANSFER_CHARACTERISTICS_SRGB;
    image->matrixCoefficients      = AVIF_MATRIX_COEFFICIENTS_BT601;

    // Set up RGB image
    avifRGBImageSetDefaults(&avifRgb, image);
    avifRgb.format   = AVIF_RGB_FORMAT_RGB;
    avifRgb.depth    = 8;
    avifRgb.pixels   = Scan0;
    avifRgb.rowBytes = stride;

    // Update RGB to YUV conversion
    auto result = avifImageRGBToYUV(image, &avifRgb);
    if (result != AVIF_RESULT_OK)
    {
        std::cerr << "RGB to YUV conversion failed: " << avifResultToString(result) << std::endl;
        return false;
    }
}

bool encodeAVIF()
{
    if (!encoder || !image)
        return false;

    // Encode the image
    result = avifEncoderWrite(encoder, image, &avifOutput);
    if (result != AVIF_RESULT_OK)
    {
        avifImageDestroy(image);
        avifEncoderDestroy(encoder);
        return false;
    }

    websocketpp::lib::error_code ec;
    wsClient.send(connection, avifOutput.data, avifOutput.size,  websocketpp::frame::opcode::binary, ec);

    // Cleanup
    avifRWDataFree(&avifOutput);
    //avifImageDestroy(image);

    return true;
}

Upvotes: -1

Views: 26

Answers (0)

Related Questions