① ffmpeg是如何轉碼的
ffmpeg轉碼的過程如下:
讀取輸入文件:
- 使用av_read_frame函數從輸入文件中讀取packet。
- 當av_read_frame返回AVERROR_EOF時,表示輸入文件已無packet可讀取,此時會傳遞NULL給後續的解碼流程作為flush/drain的指示。
解碼過程:
- 將讀取到的packet傳遞給解碼器,使用avcodec_send_packet函數。
- 如果avcodec_send_packet在第二次傳遞size為0的pkt時返回AVERROR_EOF,ffmpeg內部會忽略這一EOF。
- 使用avcodec_receive_frame函數從解碼器獲取解碼後的frame。
- 當avcodec_receive_frame返回AVERROR_EOF時,表示解碼器已無frame輸出。
處理過濾器鏈:
- 在過濾器鏈中處理EOF,通常通過av_buffersink_get_frame_flags返回的EOF來檢測。
- 這個EOF通常不會導致輸出流的finished狀態改變,但會觸發編碼器的flush操作。
編碼過程:
- 將解碼後的frame傳遞給編碼器進行編碼,編碼後的packet會傳遞給後續的muxer或直接輸出。
- 當解碼器返回EOF,且後續無frame輸入時,會調用send_filter_eof向過濾器鏈輸入NULL,表示過濾器鏈可能仍有frame緩存。
- 等待過濾器鏈處理完所有緩存的frame,即avfilter_graph_request_oldest返回AVERROR_EOF,然後調用close_output_stream將ost的finished狀態設置為ENCODER_FINISHED。
刷新編碼器:
- 執行flush_encoders函數,通過傳遞NULL包,將編碼器剩餘的packet全部刷出。
- 這一步是確保所有編碼後的數據都被正確處理並輸出。
結束轉碼:
- 當所有輸入數據都被處理完畢,且編碼器、過濾器鏈和muxer都完成它們的工作後,ffmpeg會退出轉碼流程。
在整個轉碼過程中,ffmpeg會處理各種EOF場景,確保所有數據都被正確讀取、解碼、處理和編碼,最終生成所需的輸出文件。