2016-06-29 49 views
5

mpeg4 veya h264 kodlayıcılarını kullandığımda, ffmpeg 3.1.0 için API kullanarak geçerli bir AVI dosyası oluşturmak için görüntüleri başarıyla kodlayabiliyorum. Ancak, Quick Sync encoder (h264_qsv) kullandığımda, avcodec_encode_video2 biraz zaman geçirir. 1920x1080 görüntülerini kullanırken, avcodec_encode_video2'nin askıda kalması nadirdir. 256x256 görüntüleri kullanırken, fonksiyonun asılması çok muhtemeldi.ffmpeg avcodec_encode_video2, Quick Sync kullanırken kilitleniyor h264_qsv encoder

Avcodec_encode_video2'nin askıda kaldığını gösteren aşağıdaki sınama kodunu oluşturdum. Bu kod, 400000 bitlik bir hıza sahip 1000 frame, 256x256 AVI yaratacaktır. Çerçeveler basitçe tahsis edilmiştir, böylece çıkış videosu sadece yeşil çerçeveler olmalıdır.

32-Bit veya 64-bit sınama uygulaması kullanılarak Windows 7 ve Windows 10 kullanılarak sorun gözlemlendi.

Avcodec_encode_video2'den nasıl kaçınabileceğimi bilen herhangi bir fikri varsa çok minnettar olurum! Herhangi bir yardım için şimdiden teşekkür ederiz.

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

Ayrıca h264_qsv ile avcodec_decode_video2() asılı - ffmpeg-2.8.8 – danishansari

cevap

-1

sorunu artık şimdi son Intel® Graphics Sürücü güncellendi olduğunu ortaya (sürüm 15.45.10.4542)

+1

Yeniden üretilemeyen bir sorundan mı kaynaklandıysa veya basit bir yazım hatası olan – miken32

+0

En son Intel® Grafik Sürücüsüne (sürüm 20.19.15.4624) güncelledim ve hala aynı sorunu çözdüyseniz sorunuzu silmelisiniz. –