Aviからmp4(x264)にトランスコードするときにfpsの問題が発生しました。最終的に、問題はPTSとDTS値にあったため、av_interleaved_write_frame関数の前に追加された行12〜15は次のとおりです。
1. AVFormatContext* outContainer = NULL;
2. avformat_alloc_output_context2(&outContainer, NULL, "mp4", "c:\\test.mp4";
3. AVCodec *encoder = avcodec_find_encoder(AV_CODEC_ID_H264);
4. AVStream *outStream = avformat_new_stream(outContainer, encoder);
5. // outStream->codec initiation
6. // ...
7. avformat_write_header(outContainer, NULL);
8. // reading and decoding packet
9. // ...
10. avcodec_encode_video2(outStream->codec, &encodedPacket, decodedFrame, &got_frame)
11.
12. if (encodedPacket.pts != AV_NOPTS_VALUE)
13. encodedPacket.pts = av_rescale_q(encodedPacket.pts, outStream->codec->time_base, outStream->time_base);
14. if (encodedPacket.dts != AV_NOPTS_VALUE)
15. encodedPacket.dts = av_rescale_q(encodedPacket.dts, outStream->codec->time_base, outStream->time_base);
16.
17. av_interleaved_write_frame(outContainer, &encodedPacket)
多くの投稿を読んだ後、私はまだ理解していません:
outStream->codec->time_base
= 1/25およびoutStream->time_base
= 1/12800。最初のものは私によって設定されましたが、私はなぜ12800を設定したのかを理解できませんか?行(7)の前にoutStream->time_base
= 1/90000があり、その直後に1/12800に変わることに気付きました。なぜですか? aviからaviにトランスコードするとき、行(2)をavformat_alloc_output_context2(&outContainer, NULL, "avi", "c:\\test.avi";
に変更することを意味するので、行(7)の前後でoutStream->time_base
は常に1/25のままで、mp4の場合とは異なります。outStream->codec
のtime_baseとoutStream
のtime_baseの違いは何ですか?av_rescale_q
は2つのtime_baseを取り、それらの小数部をクロスで乗算してから、ptsを計算します。なぜこのようにしているか?デバッグしたように、encodedPacket.pts
の値は1ずつ増加しますが、値がある場合に変更する理由は何ですか?Time_baseは、単なるnitの測定値です。異なる単位を使用して同じ時間を表すことができます(正確な倍数でない場合は、おおよそ)。場合によっては、コンテナ形式には特定のタイムベースが必要であり、マルチプレクサによってそれが設定されます。その他の場合、コンテナはrequireタイムベースではありませんが、オーバーライドする必要があるデフォルトがあります。具体的には1/12800についてはわかりませんが、1/600はmp4仕様の特別な値です。
2つのタイムベースは、コーデックとコンテナの時間の測定単位です。一定のfpsを使用する場合、コーデックの測定単位は通常、各フレームと次のフレームの間隔(各フレームが表示される期間)に設定されるため、フレーム時間は連続した整数になります。ただし、使用されている単位にかかわらずPTS時間が正しい限り、1/fpsに設定する必要はありません。
あなたが説明するのは、あるユニットから別のユニットに変換するために何をしなければならないかということです。 (つまり、古い単位で乗算し、新しい単位で除算します)。 _a/b
_の単位の時間tは、t*(a*d)/(b*c)
として単位__c/d
_に変換できます。
Dtsシーケンスは任意の値から開始でき、dts 0には特別な意味はありません。再生の開始時に、壁時計時間と開始dtsの差が計算され、それを使用して将来のすべてのdtsが壁時計に変換されます。 dts = -10、-9、-8、...のビデオストリームは完全に問題ありません。連続するdtsの違いは使用されるものであり、絶対値は重要ではありません。