2016-06-29 7 views
5

mpeg4 또는 h264 인코더를 사용할 때 ffmpeg 3.1.0에 대한 API를 사용하여 이미지를 성공적으로 인코딩하여 유효한 AVI 파일을 만들 수 있습니다. 그러나 Quick Sync 인코더 (h264_qsv)를 사용하면 avcodec_encode_video2가 잠시 멈추게됩니다. 1920x1080 인 이미지를 사용할 때 avcodec_encode_video2가 멈추는 경우는 드뭅니다. 256x256 이미지를 사용할 때 함수가 멈출 가능성이 큽니다.빠른 동기화를 사용할 때 ffmpeg avcodec_encode_video2가 응답하지 않습니다. h264_qsv 인코더

아래 테스트 코드는 avcodec_encode_video2의 응답을 보여줍니다. 이 코드는 비트 레이트 400000의 1000 프레임, 256x256 AVI를 만듭니다. 프레임은 단순히 할당되므로 출력 비디오는 녹색 프레임이어야합니다.

Windows 7 및 Windows 10에서 32 비트 또는 64 비트 테스트 응용 프로그램을 사용하여 문제가 발생했습니다.

누군가가 내가 avcodec_encode_video2 중단을 피할 수있는 방법에 대한 아이디어가 있다면 매우 감사 할 것입니다! 도움을 주셔서 미리 감사드립니다.

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

는 또한 h264_qsv으로, avcodec_decode_video2()에 달려 -는 FFmpeg-2.8.8 – danishansari

답변

-1

문제는 더 이상 지금은 최신 인텔 ® 그래픽 드라이버를 업데이트 한 것을 발생합니다 (버전 15.45.10.4542)

+1

더 이상 재현 할 수없는 문제 또는 간단한 인쇄상의 오류로 인해 발생한 경우 질문을 삭제해야합니다. – miken32

+0

최신 인텔 ® 그래픽 드라이버 (버전 20.19.15.4624)로 업데이트했지만 여전히 동일한 문제가 있습니다. –

관련 문제