ffmpeg 関数: av_read_frame() の解析。
2022-02-25 09:53:43
ビデオのエンコードとデコードの場合、データをデコードするために、まずビデオフレームの圧縮データを取得します。
av_read_frame()
の役割を果たします。
動画のデータを取得する
.
注意:av_read_frame()は映像の1フレームを取得します、ハーフフレームというものはありません。しかし、音声の数フレームを取得することはできます。
注1: av_read_frame() 関数は、ffmpeg の新しい使用法です。この使い方が放棄された理由は、以前に取得したデータが完全でない可能性があり、一方 av_read_frame() はビデオデータの 1 フレームの完全性を保証するためです。
注2.API の変更点を見ると、2012-03-20 から av_read_packet() を廃止し、av_read_frame() を使用するようになったことが分かります。
Returns the next frame of the stream.
*This function returns what is stored in the file, but does not verify that the decoder has a valid frame.
It will split the content stored in the file into frames and return one frame for each call.
It will not omit invalid data between valid frames in order to give the decoder the maximum possible decoding information.
If pkt->buf is NULL, then the packet is valid until the next av_read_frame() or until avformat_close_input().
Otherwise the packet will be valid indefinitely. In both cases, the packet must be released using av_free_packet when the packet is no longer needed.
For video, the packet contains only one frame.
For audio, if each frame has a known fixed size (e.g. PCM or ADPCM data), it contains an integer number of frames.
If the audio frame has a variable size (e.g. MPEG audio), then it contains one frame.
In AVStream, pkt->pts, pkt->dts and pkt->duration are always set to the appropriate values.
time_base unit (guess if the format cannot provide them).
If the video format is B-frames, pkt->pts can be AV_NOPTS_VALUE, so it is better to rely on pkt->dts if the payload is not decompressed.
int av_read_frame(AVFormatContext *s, AVPacket *pkt);
パラメータの説明です。
AVFormatContext *s // ファイルフォーマットコンテキスト、入力 AVFormatContext
AVPacket *pkt // この値はNULLで渡すことはできず、スペースである必要があります、出力AVPacket
// 返り値:OKなら0、エラーまたはファイル終了なら<0を返す
av_read_frame()関数のソースコードはlibavformatutils.cにあります。
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
{
const int genpts = s->flags & AVFMT_FLAG_GENPTS;
int eof = 0;
int ret;
AVStream *st;
if (!genpts) {
ret = s->internal->packet_buffer
? ff_packet_list_get(&s->internal->packet_buffer,
&s->internal->packet_buffer_end, pkt)
: read_frame_internal(s, pkt);
if (ret < 0)
return ret;
goto return_packet;
}
for (;;) {
AVPacketList *pktl = s->internal->packet_buffer;
if (pktl) {
AVPacket *next_pkt = &pktl->pkt;
if (next_pkt->dts ! = AV_NOPTS_VALUE) {
int wrap_bits = s->streams[next_pkt->stream_index]->pts_wrap_bits;
// last dts seen for this stream. if any of packets following
// current one had no dts, we will set this to AV_NOPTS_VALUE.
int64_t last_dts = next_pkt->dts;
av_assert2(wrap_bits <= 64);
while (pktl && next_pkt->pts == AV_NOPTS_VALUE) {
if (pktl->pkt.stream_index == next_pkt->stream_index &&
av_compare_mod(next_pkt->dts, pktl->pkt.dts, 2ULL << (wrap_bits - 1)) < 0) {
if (av_compare_mod(pktl->pkt.pts, pktl->pkt.dts, 2ULL << (wrap_bits - 1)) {
// not B-frame
next_pkt->pts = pktl->pkt.dts;
}
if (last_dts ! = AV_NOPTS_VALUE) {
// Once last dts was set to AV_NOPTS_VALUE, we don't change it.
last_dts = pktl->pkt.dts;
}
}
pktl = pktl->next;
}
if (eof && next_pkt->pts == AV_NOPTS_VALUE && last_dts ! = AV_NOPTS_VALUE) {
// Fixing the last reference frame had none pts issue (For MXF etc).
// We only do this when
// 1. eof.
// 2. we are not able to resolve a pts value for current packet.
// 3. the packets for this stream at the end of the files had valid dts.
next_pkt->pts = last_dts + next_pkt->duration;
}
pktl = s->internal->packet_buffer;
}
/* read packet from packet buffer, if there is data */
st = s->streams[next_pkt->stream_index];
if (! (next_pkt->pts == AV_NOPTS_VALUE && st->discard < AVDISCARD_ALL &&
next_pkt->dts ! = AV_NOPTS_VALUE && !eof)) {
ret = ff_packet_list_get(&s->internal->packet_buffer,
&s->internal->packet_buffer_end, pkt);
goto return_packet;
}
}
ret = read_frame_internal(s, pkt);
if (ret < 0) {
if (pktl && ret ! = AVERROR(EAGAIN)) {
eof = 1;
continue;
} else
return ret;
}
ret = ff_packet_list_put(&s->internal->packet_buffer,
&s->internal->packet_buffer_end,
pkt, FF_PACKETLIST_FLAG_REF_PACKET);
av_packet_unref(pkt);
if (ret < 0)
return ret;
}
return_packet:
st = s->streams[pkt->stream_index];
if ((s->iformat->flags & AVFMT_GENERIC_INDEX) && pkt->flags & AV_PKT_FLAG_KEY) {
ff_reduce_index(s, st->index);
av_add_index_entry(st, pkt->pos, pkt->dts, 0, 0, AVINDEX_KEYFRAME);
}
if (is_relative(pkt->dts))
pkt->dts -= RELATIVE_TS_BASE;
if (is_relative(pkt->pts))
pkt->
関連
-
[解決済み】ffmpegが存在する場合、出力ファイルを上書きする
-
[解決済み] FFmpegです。RMTP ストリームで NetStream.Play.StreamNotFound が発生しました。
-
[解決済み] ffmpeg 入力された h264 を h265 に処理する際に無効なデータが見つかった
-
[解決済み] ffmpeg が MJPEG エンコード用に高画質な画像を生成する。
-
[解決済み] FFmpeg を libfdk_aac と共にコンパイルする。
-
[解決済み] FFMPEG (libx264) "height not divisible by 2".
-
[解決済み] ffmpeg concat: "安全でないファイル名"
-
[解決済み] ffmpeg - 動画処理 - 空白の動画でトランジションを作成する
-
暗号化されたHLS(m3u8)ビデオ変換の問題を解決します。
-
ffmpeg 'XXXX' をコンパイルすると、非静的宣言エラーの解決策に従う。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン