Codificação de quadros em vídeo com ffmpeg

Estou tentando codificar um vídeo no Unreal Engine 4 com C ++. Eu tenho acesso aos quadros separados. Abaixo está o código que lêviewport's pixels exibidos e armazenados no buffer.

//Safely get render target resource.
FRenderTarget* RenderTarget = TextureRenderTarget->GameThread_GetRenderTargetResource();
FIntPoint Size = RenderTarget->GetSizeXY();
auto ImageBytes = Size.X* Size.Y * static_cast<int32>(sizeof(FColor));
TArray<uint8> RawData;
RawData.AddUninitialized(ImageBytes);

//Get image raw data.
if (!RenderTarget->ReadPixelsPtr((FColor*)RawData.GetData()))
{
    RawData.Empty();
    UE_LOG(ExportRenderTargetBPFLibrary, Error, TEXT("ExportRenderTargetAsImage: Failed to get raw data."));
    return false;
}

Buffer::getInstance().add(RawData);

O Unreal Engine possuiIImageWrapperModule com o qual você pode obter uma imagem do quadro, mas notando a codificação de vídeo. O que eu quero é codificar quadros em tempo real para o serviço de transmissão ao vivo.

Encontrei este postCodificando uma captura de tela em um vídeo usando FFMPEG que é o que eu quero, mas tenho problemas para adaptar esta solução ao meu caso. O código está desatualizado (por exemploavcodec_encode_video alterado paraavcodec_encode_video2 com parâmetros diferentes).

Abaixo está o código do codificador.

void Compressor::DoWork()
{
AVCodec* codec;
AVCodecContext* c = NULL;
//uint8_t* outbuf;
//int /*i, out_size,*/ outbuf_size;

UE_LOG(LogTemp, Warning, TEXT("encoding"));

codec = avcodec_find_encoder(AV_CODEC_ID_MPEG1VIDEO);            // finding the H264 encoder
if (!codec) {
    UE_LOG(LogTemp, Warning, TEXT("codec not found"));
    exit(1);
}
else UE_LOG(LogTemp, Warning, TEXT("codec found"));

c = avcodec_alloc_context3(codec);
c->bit_rate = 400000;
c->width = 1280;                                        // resolution must be a multiple of two (1280x720),(1900x1080),(720x480)
c->height = 720;
c->time_base.num = 1;                                   // framerate numerator
c->time_base.den = 25;                                  // framerate denominator
c->gop_size = 10;                                       // emit one intra frame every ten frames
c->max_b_frames = 1;                                    // maximum number of b-frames between non b-frames
c->keyint_min = 1;                                      // minimum GOP size
c->i_quant_factor = (float)0.71;                        // qscale factor between P and I frames
//c->b_frame_strategy = 20;                               ///// find out exactly what this does
c->qcompress = (float)0.6;                              ///// find out exactly what this does
c->qmin = 20;                                           // minimum quantizer
c->qmax = 51;                                           // maximum quantizer
c->max_qdiff = 4;                                       // maximum quantizer difference between frames
c->refs = 4;                                            // number of reference frames
c->trellis = 1;                                         // trellis RD Quantization
c->pix_fmt = AV_PIX_FMT_YUV420P;                           // universal pixel format for video encoding
c->codec_id = AV_CODEC_ID_MPEG1VIDEO;
c->codec_type = AVMEDIA_TYPE_VIDEO;

if (avcodec_open2(c, codec, NULL) < 0) {
    UE_LOG(LogTemp, Warning, TEXT("could not open codec"));         // opening the codec
    //exit(1);
}
else UE_LOG(LogTemp, Warning, TEXT("codec oppened"));

FString FinalFilename = FString("C:/Screen/sample.mpg");
auto &PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
auto FileHandle = PlatformFile.OpenWrite(*FinalFilename, true);

if (FileHandle)
{
    delete FileHandle; // remove when ready
    UE_LOG(LogTemp, Warning, TEXT("file opened"));
    while (true)
    {
        UE_LOG(LogTemp, Warning, TEXT("removing from buffer"));

        int nbytes = avpicture_get_size(AV_PIX_FMT_YUV420P, c->width, c->height);                                      // allocating outbuffer
        uint8_t* outbuffer = (uint8_t*)av_malloc(nbytes * sizeof(uint8_t));

        AVFrame* inpic = av_frame_alloc();
        AVFrame* outpic = av_frame_alloc();

        outpic->pts = (int64_t)((float)1 * (1000.0 / ((float)(c->time_base.den))) * 90);                              // setting frame pts
        avpicture_fill((AVPicture*)inpic, (uint8_t*)Buffer::getInstance().remove().GetData(),
            AV_PIX_FMT_PAL8, c->width, c->height); // fill image with input screenshot
        avpicture_fill((AVPicture*)outpic, outbuffer, AV_PIX_FMT_YUV420P, c->width, c->height);                        // clear output picture for buffer copy
        av_image_alloc(outpic->data, outpic->linesize, c->width, c->height, c->pix_fmt, 1);

        /* 
        inpic->data[0] += inpic->linesize[0]*(screenHeight-1);                                                      
        // flipping frame
        inpic->linesize[0] = -inpic->linesize[0];                                                                   
        // flipping frame

        struct SwsContext* fooContext = sws_getContext(screenWidth, screenHeight, PIX_FMT_RGB32, c->width, c->height, PIX_FMT_YUV420P, SWS_FAST_BILINEAR, NULL, NULL, NULL);
        sws_scale(fooContext, inpic->data, inpic->linesize, 0, c->height, outpic->data, outpic->linesize);          // converting frame size and format

        out_size = avcodec_encode_video(c, outbuf, outbuf_size, outpic);                                            
        // save in file

        */

    }
    delete FileHandle;
}
else
{
    UE_LOG(LogTemp, Warning, TEXT("Can't open file"));
}
}

Alguém pode explicarlançando quadro parte (por que está feito?) e como usaravcodec_encode_video2 função em vez deavcodec_encode_video?

questionAnswers(1)

yourAnswerToTheQuestion