2016-06-29 11 views
5

Quando utilizzo gli encoder mpeg4 o h264, sono in grado di codificare correttamente le immagini per creare un file AVI valido utilizzando l'API per ffmpeg 3.1.0. Tuttavia, quando utilizzo il codificatore Quick Sync (h264_qsv), avcodec_encode_video2 si bloccherà un po 'di tempo. Ho scoperto che quando si utilizzavano immagini di 1920x1080, era raro che avcodec_encode_video2 si bloccasse. Quando si utilizzavano 256x256 immagini, era molto probabile che la funzione si bloccasse.ffmpeg avcodec_encode_video2 si blocca quando si utilizza l'encoder Quick Sync h264_qsv

Ho creato il codice di test qui sotto che dimostra il blocco di avcodec_encode_video2. Il codice creerà un frame 1000, 256x256 AVI con una velocità in bit di 400000. I fotogrammi vengono semplicemente assegnati, quindi il video di output dovrebbe essere solo i frame verdi.

Il problema è stato osservato utilizzando Windows 7 e Windows 10, utilizzando l'applicazione di test a 32 o 64 bit.

Se qualcuno ha qualche idea su come evitare il blocco avcodec_encode_video2, sarei molto grato! Grazie in anticipo per qualsiasi assistenza.

extern "C" 
{ 
#ifndef __STDC_CONSTANT_MACROS 
#define __STDC_CONSTANT_MACROS 
#endif 
#include "avcodec.h" 
#include "avformat.h" 
#include "swscale.h" 
#include "avutil.h" 
#include "imgutils.h" 
#include "opt.h" 
#include <rational.h> 
} 

#include <iostream> 


// Globals 
AVCodec* m_pCodec = NULL; 
AVStream *m_pStream = NULL; 
AVOutputFormat* m_pFormat = NULL; 
AVFormatContext* m_pFormatContext = NULL; 
AVCodecContext* m_pCodecContext = NULL; 
AVFrame* m_pFrame = NULL; 
int m_frameIndex; 

// Output format 
AVPixelFormat m_pixType = AV_PIX_FMT_NV12; 
// Use for mpeg4 
//AVPixelFormat m_pixType = AV_PIX_FMT_YUV420P; 

// Output frame rate 
int m_frameRate = 30; 
// Output image dimensions 
int m_imageWidth = 256; 
int m_imageHeight = 256; 
// Number of frames to export 
int m_frameCount = 1000; 
// Output file name 
const char* m_fileName = "c:/test/test.avi"; 
// Output file type 
const char* m_fileType = "AVI"; 
// Codec name used to encode 
const char* m_encoderName = "h264_qsv"; 
// use for mpeg4 
//const char* m_encoderName = "mpeg4"; 
// Target bit rate 
int m_targetBitRate = 400000; 

void addVideoStream() 
{ 
    m_pStream = avformat_new_stream(m_pFormatContext, m_pCodec); 
    m_pStream->id = m_pFormatContext->nb_streams - 1; 
    m_pStream->time_base = m_pCodecContext->time_base; 
    m_pStream->codec->pix_fmt = m_pixType; 
    m_pStream->codec->flags = m_pCodecContext->flags; 
    m_pStream->codec->width = m_pCodecContext->width; 
    m_pStream->codec->height = m_pCodecContext->height; 
    m_pStream->codec->time_base = m_pCodecContext->time_base; 
    m_pStream->codec->bit_rate = m_pCodecContext->bit_rate; 
} 

AVFrame* allocatePicture(enum AVPixelFormat pix_fmt, int width, int height) 
{ 
    AVFrame *frame; 

    frame = av_frame_alloc(); 

    if (!frame) 
    { 
     return NULL; 
    } 

    frame->format = pix_fmt; 
    frame->width = width; 
    frame->height = height; 

    int checkImage = av_image_alloc(frame->data, frame->linesize, width, height, pix_fmt, 32); 

    if (checkImage < 0) 
    { 
     return NULL; 
    } 

    return frame; 
} 

bool initialize() 
{ 
    AVRational frameRate; 
    frameRate.den = m_frameRate; 
    frameRate.num = 1; 

    av_register_all(); 

    m_pCodec = avcodec_find_encoder_by_name(m_encoderName); 

    if(!m_pCodec) 
    { 
     return false; 
    } 

    m_pCodecContext = avcodec_alloc_context3(m_pCodec); 
    m_pCodecContext->width = m_imageWidth; 
    m_pCodecContext->height = m_imageHeight; 
    m_pCodecContext->time_base = frameRate; 
    m_pCodecContext->gop_size = 0; 
    m_pCodecContext->pix_fmt = m_pixType; 
    m_pCodecContext->codec_id = m_pCodec->id; 
    m_pCodecContext->bit_rate = m_targetBitRate; 

    av_opt_set(m_pCodecContext->priv_data, "+CBR", "", 0); 

    return true; 
} 

bool startExport() 
{ 
    m_frameIndex = 0; 
    char fakeFileName[512]; 
    int checkAllocContext = avformat_alloc_output_context2(&m_pFormatContext, NULL, m_fileType, fakeFileName); 

    if (checkAllocContext < 0) 
    { 
     return false; 
    } 

    if (!m_pFormatContext) 
    { 
     return false; 
    } 

    m_pFormat = m_pFormatContext->oformat; 

    if (m_pFormat->video_codec != AV_CODEC_ID_NONE) 
    { 
     addVideoStream(); 

     int checkOpen = avcodec_open2(m_pCodecContext, m_pCodec, NULL); 

     if (checkOpen < 0) 
     { 
      return false; 
     } 

     m_pFrame = allocatePicture(m_pCodecContext->pix_fmt, m_pCodecContext->width, m_pCodecContext->height);     
     if(!m_pFrame) 
     { 
      return false; 
     } 
     m_pFrame->pts = 0; 
    } 

    int checkOpen = avio_open(&m_pFormatContext->pb, m_fileName, AVIO_FLAG_WRITE); 
    if (checkOpen < 0) 
    { 
     return false; 
    } 

    av_dict_set(&(m_pFormatContext->metadata), "title", "QS Test", 0); 

    int checkHeader = avformat_write_header(m_pFormatContext, NULL); 
    if (checkHeader < 0) 
    { 
     return false; 
    } 

    return true; 
} 

int processFrame(AVPacket& avPacket) 
{ 
    avPacket.stream_index = 0; 
    avPacket.pts = av_rescale_q(m_pFrame->pts, m_pStream->codec->time_base, m_pStream->time_base); 
    avPacket.dts = av_rescale_q(m_pFrame->pts, m_pStream->codec->time_base, m_pStream->time_base); 
    m_pFrame->pts++; 

    int retVal = av_interleaved_write_frame(m_pFormatContext, &avPacket); 
    return retVal; 
} 

bool exportFrame() 
{ 
    int success = 1; 
    int result = 0; 

    AVPacket avPacket; 

    av_init_packet(&avPacket); 
    avPacket.data = NULL; 
    avPacket.size = 0; 

    fflush(stdout); 

    std::cout << "Before avcodec_encode_video2 for frame: " << m_frameIndex << std::endl; 
    success = avcodec_encode_video2(m_pCodecContext, &avPacket, m_pFrame, &result); 
    std::cout << "After avcodec_encode_video2 for frame: " << m_frameIndex << std::endl; 

    if(result) 
    { 
     success = processFrame(avPacket); 
    } 

    av_packet_unref(&avPacket); 

    m_frameIndex++; 
    return (success == 0); 
} 

void endExport() 
{ 
    int result = 0; 
    int success = 0; 

    if (m_pFrame) 
    { 
     while (success == 0) 
     { 
      AVPacket avPacket; 
      av_init_packet(&avPacket); 
      avPacket.data = NULL; 
      avPacket.size = 0; 

      fflush(stdout); 
      success = avcodec_encode_video2(m_pCodecContext, &avPacket, NULL, &result); 

      if(result) 
      { 
       success = processFrame(avPacket); 
      } 
      av_packet_unref(&avPacket); 

      if (!result) 
      { 
       break; 
      } 
     } 
    } 

    if (m_pFormatContext) 
    { 
     av_write_trailer(m_pFormatContext); 

     if(m_pFrame) 
     { 
      av_frame_free(&m_pFrame); 
     } 

     avio_closep(&m_pFormatContext->pb); 
     avformat_free_context(m_pFormatContext); 
     m_pFormatContext = NULL; 
    } 
} 

void cleanup() 
{ 
    if(m_pFrame || m_pCodecContext) 
    { 
     if(m_pFrame) 
     { 
      av_frame_free(&m_pFrame); 
     } 

     if(m_pCodecContext) 
     { 
      avcodec_close(m_pCodecContext); 
      av_free(m_pCodecContext); 
     } 
    } 
} 

int main() 
{ 
    bool success = true; 
    if (initialize()) 
    { 
     if (startExport()) 
     { 
      for (int loop = 0; loop < m_frameCount; loop++) 
      { 
       if (!exportFrame()) 
       { 
        std::cout << "Failed to export frame\n"; 
        success = false; 
        break; 
       } 
      } 
      endExport(); 
     } 
     else 
     { 
      std::cout << "Failed to start export\n"; 
      success = false; 
     } 

     cleanup(); 
    } 
    else 
    { 
     std::cout << "Failed to initialize export\n"; 
     success = false; 
    } 

    if (success) 
    { 
     std::cout << "Successfully exported file\n"; 
    } 
    return 1; 
} 
+0

Si blocca anche in avcodec_decode_video2(), con h264_qsv - ffmpeg-2.8.8 – danishansari

risposta

-1

Il problema non si verifica più ora che ho aggiornato all'ultima driver di Intel® Graphics (versione 15.45.10.4542)

+1

Dovresti eliminare la tua domanda se è stata causata da un problema che non può più essere riprodotto o da un semplice errore tipografico – miken32

+0

Ho aggiornato all'ultimo driver grafico Intel® (versione 20.19.15.4624) e ho ancora lo stesso problema. –

Problemi correlati