2012-11-22 69 views
1

我用的ffmpeg再有一個問題,我與ffmpeg的一個新手,我不能找到一個很好的教程最新...視頻過快的FFmpeg

這一次,當我發揮視頻與ffmpeg,它播放速度太快,ffmpeg忽略FPS,我不想處理線程睡眠,因爲視頻有不同的FPS。

我創建的線程,那裏你可以找到循環:

AVPacket framepacket; 

while(av_read_frame(formatContext,&framepacket)>= 0){ 
    pausecontrol.lock(); 

    // Is it a video or audio frame¿? 
    if(framepacket.stream_index==gotVideoCodec){ 
     int framereaded; 
     // Video? Ok 
     avcodec_decode_video2(videoCodecContext,videoFrame,&framereaded,&framepacket); 
     // Yeah, did we get it? 
     if(framereaded && doit){ 
      AVRational millisecondbase = {1,1000}; 
      int f_number = framepacket.dts; 
      int f_time = av_rescale_q(framepacket.dts,formatContext->streams[gotVideoCodec]->time_base,millisecondbase); 
      currentTime=f_time; 
      currentFrameNumber=f_number; 

      int stWidth = videoCodecContext->width; 
      int stHeight = videoCodecContext->height; 
      SwsContext *ctx = sws_getContext(stWidth, stHeight, videoCodecContext->pix_fmt, stWidth, 
      stHeight, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL); 
      if(ctx!=0){ 
      sws_scale(ctx,videoFrame->data,videoFrame->linesize,0,videoCodecContext->height,videoFrameRGB->data,videoFrameRGB->linesize); 
      QImage framecapsule=QImage(stWidth,stHeight,QImage::Format_RGB888); 

      for(int y=0;y<stHeight;y++){ 
       memcpy(framecapsule.scanLine(y),videoFrameRGB->data[0]+y*videoFrameRGB->linesize[0],stWidth*3); 
      } 
      emit newFrameReady(framecapsule); 
      sws_freeContext(ctx); 
      } 

     } 
    } 
    if(framepacket.stream_index==gotAudioCodec){ 
     // Audio? Ok 
    } 
    pausecontrol.unlock(); 
    av_free_packet(&framepacket); 
} 

任何想法?

+0

你能獲得的FPS信息? – nhahtdh

+0

是的。我可以。那麼,我一直在尋找互聯網,線程睡眠可以是一個選項,任何想法?我也需要播放音頻,如果我睡覺的話,音頻解碼也會被檢測到... – Spamdark

+0

我沒有這方面的經驗,但是可以將渲染和解碼步驟分開嗎? (渲染將每1/FPS秒鐘休眠一次,然後從解碼緩衝區中消耗,並且解碼步驟將繼續,直到緩衝區被填滿 - 消費者生產者類型的結構)。 – nhahtdh

回答

2

最簡單的解決方案是使用基於FPS值

firstFrame = true; 
for(;;) 
{ 
    // decoding, color conversion, etc. 

    if (!firstFrame) 
    { 
    const double frameDuration = 1000.0/frameRate; 
    duration_t actualDelay = get_local_time() - lastTime; 
    if (frameDuration > actualDelay) 
     sleep(frameDuration - actualDelay); 
    } 
    else 
    firstFrame = false; 

    emit newFrameReady(framecapsule); 

    lastTime = get_local_time(); 
} 

get_local_time()duration_t是抽象的延遲。

更精確的方法是使用時間戳對每幀,但這個想法是從視頻同

+0

非常感謝! – Spamdark

+0

嘿,謝謝你。當視頻在網絡上流式傳輸時,如果幀可能太快或太慢,有什麼建議? – Nav

+0

@Nav只需將收到的數據包放入隊列中(在單獨的線程中)並根據需要提取它們 – pogorskiy