'Error submitting the frame for encoding when submitting NV12 texture

I'm trying to encode D3D11 NV12 Texture on QSV encoder but getting [h264_qsv @ 00000244ce6f50c0] Error submitting the frame for encoding.

Main:

int width = 1920;
int height = 1080;
FILE* outfile;

fopen_s(&outfile, "D:\\Sources\\D3D11QSV\\x64\\Debug\\outfile.264", "wb");

const AVCodec* codec = avcodec_find_encoder_by_name("h264_qsv");
AVCodecContext* ctx = avcodec_alloc_context3(codec);

ctx->width = width;
ctx->height = height;
ctx->time_base = AVRational{ 1, 60 };
ctx->framerate = AVRational{ 60, 1 };
ctx->slices = 1;

ctx->sw_pix_fmt = AV_PIX_FMT_NV12;
ctx->pix_fmt = AV_PIX_FMT_NV12;
ctx->bit_rate = 400000;
ctx->gop_size = 10;
ctx->max_b_frames = 1;

auto status = avcodec_open2(ctx, codec, NULL);
if (status < 0) {
    std::cout << "Open codec error!\n";
}

AVFrame* sw_frame = av_frame_alloc();
sw_frame->format = ctx->sw_pix_fmt;
sw_frame->width = ctx->width;
sw_frame->height = ctx->height;
status = av_frame_get_buffer(sw_frame, 0);

fill_frame(sw_frame, ctx);

Filling the frame:

auto ret = 0;

if (ret < 0) {
    fprintf(stderr, "Could not allocate the video frame data\n");
    exit(1);
}

int i, y, x, c = 0;
for (i = 0; i < 60; i++) {
    fflush(stdout);

    ret = av_frame_make_writable(frame);
    
    auto texture = create_texture();
    auto desc = (AVD3D11FrameDescriptor*)frame->buf[0]->data;
    desc->texture = (ID3D11Texture2D*)texture;
    desc->index = 0;

    frame->data[0] = (std::uint8_t*)texture;
    frame->data[1] = 0;
    frame->linesize[0] = width * 4;

    frame->pts = i;

    encode(frame, ctx);
}

Creating Texture:

D3D11_TEXTURE2D_DESC const desc = CD3D11_TEXTURE2D_DESC(
    DXGI_FORMAT_NV12,           // HoloLens PV camera format, common for video sources
    width,                    // Width of the video frames
    height,                   // Height of the video frames
    1,                          // Number of textures in the array
    1,                          // Number of miplevels in each texture
    D3D11_BIND_SHADER_RESOURCE, // We read from this texture in the shader
    D3D11_USAGE_DYNAMIC,        // Because we'll be copying from CPU memory
    D3D11_CPU_ACCESS_WRITE      // We only need to write into the texture
);

ID3D11Device* pd3dDevice = create_d3d11_device();

ID3D11Texture2D* pTexture = NULL;
HRESULT err = pd3dDevice->CreateTexture2D(&desc, nullptr, &pTexture);


if (SUCCEEDED(err)) {
    D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc = CD3D11_SHADER_RESOURCE_VIEW_DESC(
        pTexture,
        D3D11_SRV_DIMENSION_TEXTURE2D,
        DXGI_FORMAT_R8_UNORM
    );

    ID3D11ShaderResourceView* texSRV = NULL;

    err = pd3dDevice->CreateShaderResourceView(pTexture,
        &SRVDesc, &texSRV);

    D3D11_SHADER_RESOURCE_VIEW_DESC const chrominancePlaneDesc = CD3D11_SHADER_RESOURCE_VIEW_DESC(
        pTexture,
        D3D11_SRV_DIMENSION_TEXTURE2D,
        DXGI_FORMAT_R8G8_UNORM
    );

    ID3D11ShaderResourceView* m_chrominanceView = NULL;

    err = pd3dDevice->CreateShaderResourceView(pTexture,
        &chrominancePlaneDesc, &m_chrominanceView);

}

if (FAILED(err))
{
    fprintf(stderr, "Error creating texture\n");
    exit(1);
}

return pTexture;

Creating D3D11 device:

    ID3D11Device* dev11 = NULL;
    ID3D11DeviceContext* devcon11 = NULL;

    D3D_FEATURE_LEVEL featureLevels[]{
   D3D_FEATURE_LEVEL_11_1,
   D3D_FEATURE_LEVEL_11_0,
   D3D_FEATURE_LEVEL_10_1,
   D3D_FEATURE_LEVEL_10_0,
   D3D_FEATURE_LEVEL_9_3,
   D3D_FEATURE_LEVEL_9_2,
   D3D_FEATURE_LEVEL_9_1
    };


    int err = D3D11CreateDevice(
        nullptr,
        D3D_DRIVER_TYPE_HARDWARE,
        nullptr,
        D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
        featureLevels, sizeof(featureLevels) / sizeof(D3D_FEATURE_LEVEL),
        D3D11_SDK_VERSION,
        &dev11,
        nullptr,
        &devcon11);

    return dev11;

Encoding:

auto status = 0;

status = avcodec_send_frame(ctx, frame); //error happening here

AVPacket* pkt;

pkt = av_packet_alloc();

if (status < 0) {
    fprintf(stderr, "Error sending a frame for encoding\n");
    exit(1);
}

while (status >= 0) {
    status = avcodec_receive_packet(ctx, pkt);
    if (status == AVERROR(EAGAIN) || status == AVERROR_EOF)
        return;
    else if (status < 0) {
        fprintf(stderr, "Error during encoding\n");
        exit(1);
    }

    printf("Write packet \n", pkt->pts, pkt->size);
    fwrite(pkt->data, 1, pkt->size, outfile);
    av_packet_unref(pkt);
}

Everything runs well until encoding the frame. I have tried sending a dummy nv12 data (not a d3d11 texture) and it works well.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source