2017-08-17 22 views
0

我使用FFmpeg的2.7寫一個示例應用程序,將做到以下幾點:與FFmpeg的尋求使舊框架的新包的時間戳

  1. 從給定的.mov文件讀取視頻數據包
  2. 解碼視頻10秒後尋找指定位置並繼續10秒
  3. 解碼所有視頻數據包在搜索之前和之後並將其寫入目標文件。

在這個過程中,我也將所有接收到的視頻幀轉儲到原始圖像文件中,使用原始數據包的PTS作爲文件名。我注意到,即使搜索已經發生(由時間戳記跳轉指出),搜索之後的前幾個幀包含新的時間戳,但是舊的幀(即,我將在沒有搜索的情況下接收到的幀)。

These images illustrate the problem.

以下是我使用的代碼片段:

int SeekAndTranscode::_TranscodePacket(AVPacket &packet, AVFrame *frame) 
{ 
    if(packet.stream_index == _videoStreamIndex) 
    { 
     int status = avcodec_decode_video2(&_videoDecContext, frame, &gotFrame, &packet); 
     if (status < 0) 
     { 
      fprintf(stderr, "\nError decoding video frame\n"); 
      exit(1); 
     } 

     if (gotFrame) 
     { 
      if (frame->width != _width || frame->height != _height || 
       frame->format != _pixelFormat) 
      { 
       return -1; 
      } 

      vector<uint8_t> rgbData; 
      rgbData.resize(_width * _height * 4); 

      uint8_t *rgbSrc[3]= {&rgbData[0], NULL, NULL}; 
      int rgbStride[3]={4 * _width, 0, 0}; 

      sws_scale(_csc, frame->data, frame->linesize, 0, _height, rgbSrc, rgbStride); 

      int64_t pts = packet.pts * AV_TIME_BASE/_videoDecContext.time_base.den; 
      FILE *file; 
      stringstream filename; 
      filename << "C:\\Bipul\\" << pts << ".raw"; 

      file = fopen(filename.str().c_str(), "wb"); 
      fwrite(&rgbData[0], 1, rgbData.size(), file); 
      fclose(file); 

      fwrite(&rgbData[0], 1, rgbData.size(), _videoOutputFile); 
     } 
    } 

    return decodedSize; 
} 


void SeekAndTranscode::TranscodeIntoFile() 
{ 
    AVFrame* frame = NULL; 
    AVPacket packet; 
    int videoSeeks = 0; 
    int frameCount = 0; 
    int framerate = 24; 
    try 
    { 
     frame = av_frame_alloc(); 
     if (!frame) 
     { 
      fprintf(stderr, "\nCould not allocate frame for decoding\n"); 
      exit(1); 
     } 

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

     while (av_read_frame(_formatContext, &packet) >= 0) 
     { 
      if(packet.stream_index == _videoStreamIndex) 
      { 
       frameCount++; 
       if(frameCount % (10*framerate) == 0) 
       { 
        if(videoSeeks == 1) 
         break; 
        av_seek_frame(_formatContext, -1, _seekPosition * AV_TIME_BASE, 0); 
        videoSeeks++; 
        continue; 
       } 
      } 
      AVPacket originalPacket = packet; 
      do 
      { 
       int status = _TranscodePacket(packet, frame); 

       if (status < 0) 
        break; 
       packet.data += status; 
       packet.size -= status; 
      } while (packet.size > 0); 
      av_packet_unref(&originalPacket); 
     } 

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

     swr_free(&_resampler); 
    } 
    catch(const exception& e) 
    { 
     fprintf(stderr, "\n%s\n", e.what()); 
     exit(1); 
    } 
} 

這是一個已知的問題與此版本的FFmpeg的?這在更高版本中得到修復嗎?有什麼我做錯了嗎?任何線索將不勝感激。

回答

0

在繼續從流中讀取更多幀之前,需要刷新自己的緩衝區並在內部刷新ffmpegs緩衝區。

avcodec_flush_buffers(myAVCodecContext); // do this for all your streams that are opened 
+0

這對我有用。非常感謝。 –