26

avi から mp4(x264) にトランスコードするときに fps の問題が発生しました。最終的に問題は PTS と DTS の値にあったため、12 ~ 15 行目が av_interleaved_write_frame 関数の前に追加されました。

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)

多くの投稿を読んだ後、私はまだ理解していません:

  1. 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 の場合とは異なります。なぜですか?
  2. outStream->codecとの time_base の違いは何outStreamですか?
  3. ptsav_rescale_qを計算するには: 2 つの time_base を取り、それらの分数をクロスで乗算し、pts を計算します。なぜこのようにするのですか?私がデバッグしたように、encodedPacket.pts値が 1 ずつ増加するので、値があるのになぜそれを変更するのでしょうか?
  4. 最初の dts 値は -2 で、再スケーリングのたびにまだ負の数になっていますが、それでもビデオは正しく再生されました! ポジティブでいいのではないですか?
4

1 に答える 1

43
  1. time_base は単なる測定単位です。異なる単位を使用して同じ時間を表すことができます (正確な倍数でない場合は、おおよその単位です)。場合によっては、コンテナー形式に特定の時間ベースが必要であり、マルチプレクサによってその時間ベースに設定されます。それ以外の場合、コンテナーは時間ベースを必要としませんが、上書きする必要があるデフォルトがあります。特に1/12800についてはわかりませんが、1/600はmp4仕様の特別な値であることは知っています。

  2. 2 つの時間基準は、コーデックとコンテナーの時間の測定単位です。一定の fps を使用する場合、コーデックの測定単位は通常、各フレームと次のフレームの間の間隔 (各フレームが表示される期間) に設定されるため、フレーム時間は連続した整数になります。ただし、どの単位が使用されていても、pts 時間が正しい限り、1/fps に設定する必要はありません。

  3. あなたが説明することは、ある単位から別の単位に変換するために何をしなければならないかということです。(つまり、古い単位で乗算し、新しい単位で割る)。単位の時間 t は、として単位a/bに変換できます。c/dt*(a*d)/(b*c)

  4. dts シーケンスは任意の値から開始できます。dts 0 に特別な意味はありません。再生の開始時に、ウォール クロック時間と開始 dts の差が計算され、それを使用して将来のすべての dts がウォール クロックに変換されます。dts=-10、-9、-8、... のビデオ ストリームはまったく問題ありません。連続する dt の違いは使用されるものであり、絶対値は問題ではありません。

于 2012-11-30T13:32:41.590 に答える