音視頻同步原理[ffmpeg]

ffmpeg對視頻文件進行解碼的大體流程 1. 註冊全部容器格式和CODEC: av_register_all() 2. 打開文件: av_open_input_file() 3. 從文件中提取流信息: av_find_stream_info() 4. 窮舉全部的流,查找其中種類爲CODEC_TYPE_VIDEO 5. 查找對應的解碼器: avcodec_find_decoder() 6. 打開編解碼器: avcodec_open() 7. 爲解碼幀分配內存: avcodec_alloc_frame() 8. 不停地從碼流中提取中幀數據: av_read_frame() 9. 判斷幀的類型,對於視頻幀調用: avcodec_decode_video() 10. 解碼完後,釋放解碼器: avcodec_close() 11. 關閉輸入文件:av_close_input_file() output_example.c 中AV同步的代碼以下(個人代碼有些修改),這個實現至關簡單,不過挺說明問題。 閱讀前但願你們先了解一下時間戳的概念。 /* compute current audio and video time */ if (pOutputVars->pOutAudio_st)//存在音頻流 pOutputVars->audio_pts = (double)pOutputVars->pOutAudio_st->pts.val * pOutputVars->pOutAudio_st->time_base.num  / pOutputVars- >pOutAudio_st->time_base.den; //(pts是時間戳結構)輸出音頻的時間戳, 轉換爲基準時間 else pOutputVars->audio_pts = 0.0; if (pOutputVars->pOutVideo_st) pOutputVars->video_pts = (double)pOutputVars->pOutVideo_st->pts.val  * pOutputVars->pOutVideo_st->time_base.num / pOutputVars- >pOutVideo_st->time_base.den;//輸出視頻時間戳 else pOutputVars->video_pts = 0.0; if (!pOutputVars->pOutAudio_st && !pOutputVars->pOutVideo_st) return 0; /* write interleaved audio and video frames */ if (!pOutputVars->pOutVideo_st || (pOutputVars->pOutVideo_st && pOutputVars->pOutAudio_st && pOutputVars->audio_pts <  pOutputVars->video_pts)) {    write_audio_frame(pOutputVars->pOutFormatCtx, pOutputVars->pOutAudio_st, pInputAudioBuf);    //沒有視頻流,或者音頻流時間沒遇上視頻流(經過比較時間戳), 則輸出(編碼輸出)音頻禎數據 }  else  { write_video_frame(pOutputVars->pOutFormatCtx, pOutputVars->pOutVideo_st, pInputVedioFrame);//不然輸出視頻禎數據 } 輸出數據的時間戳怎麼獲得的, 以音頻爲例:    pkt.size= avcodec_encode_audio(c, audio_outbuf, audio_outbuf_size, pInputAudioBuf);//源數據應該包含時間戳, pInputAudio是源文 件解碼後的音頻數據    pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);//編碼後的禎也含有源文件的時間戳,這個函數應該是轉換同時 間基準,沒研究過    pkt.flags |= PKT_FLAG_KEY;    pkt.stream_index= st->index;    pkt.data= audio_outbuf; ... 應該就是這麼個過程了,而後用av_write_frame(oc, &pkt), 把音頻禎和視頻禎交錯寫入到輸出文件. 經過上面分析,能夠看到,有時候可能連續寫幾個音頻 禎或視頻禎.  播放時的同步可能ffplay中有,還沒細看
相關文章
相關標籤/搜索