首先看一下FFmpeg关于该packet函数的注释:
int avcodec_send_packet | ( | AVCodecContext * | avctx, |
const AVPacket * | avpkt | ||
) |
Supply raw packet data as input to a decoder.
Internally, this call will copy relevant AVCodecContext fields, which can influence decoding per-packet, and apply them when the packet is actually decoded. (For example AVCodecContext.skip_frame, which might direct the decoder to drop the frame contained by the packet sent with this function.)
- Warning
- The input buffer, avpkt->data must be AV_INPUT_BUFFER_PADDING_SIZE larger than the actual read bytes because some optimized bitstream readers read 32 or 64 bits at once and could read over the end.
- Do not mix this API with the legacy API (like avcodec_decode_video2()) on the same AVCodecContext. It will return unexpected results now or in future libavcodec versions.
- Note
- The AVCodecContext MUST have been opened with avcodec_open2() before packets may be fed to the decoder.
- Parameters
-
avctx codec context [in] avpkt The input AVPacket. Usually, this will be a single video frame, or several complete audio frames. Ownership of the packet remains with the caller, and the decoder will not write to the packet. The decoder may create a reference to the packet data (or copy it if the packet is not reference-counted). Unlike with older APIs, the packet is always fully consumed, and if it contains multiple frames (e.g. some audio codecs), will require you to call avcodec_receive_frame() multiple times afterwards before you can send a new packet. It can be NULL (or an AVPacket with data set to NULL and size set to 0); in this case, it is considered a flush packet, which signals the end of the stream. Sending the first flush packet will return success. Subsequent ones are unnecessary and will return AVERROR_EOF. If the decoder still has frames buffered, it will return them after sending a flush packet.
- Returns
- 0 on success, otherwise negative error code: AVERROR(EAGAIN): input is not accepted in the current state - user must read output with avcodec_receive_frame() (once all output is read, the packet should be resent, and the call will not fail with EAGAIN). AVERROR_EOF: the decoder has been flushed, and no new packets can be sent to it (also returned if more than 1 flush packet is sent) AVERROR(EINVAL): codec not opened, it is an encoder, or requires flush AVERROR(ENOMEM): failed to add packet to internal queue, or similar other errors: legitimate decoding errors
看一下FFmpeg4.1.3中相关代码
int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)
{
AVCodecInternal *avci = avctx->internal;
int ret;
//检查是否打开解码器
if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec))
return AVERROR(EINVAL);
//清空解码器
if (avctx->internal->draining)
return AVERROR_EOF;
if (avpkt && !avpkt->size && avpkt->data)
return AVERROR(EINVAL);
//擦除缓冲区数据包==初始化
av_packet_unref(avci->buffer_pkt);
if (avpkt && (avpkt->data || avpkt->side_data_elems)) {
//copy packet
ret = av_packet_ref(avci->buffer_pkt, avpkt);
if (ret < 0)
return ret;
}
//packet去除编码开始部分的冗余信息,并加载到bsfs
ret = av_bsf_send_packet(avci->filter.bsfs[0], avci->buffer_pkt);//Submit a packet for filtering
if (ret < 0) {
av_packet_unref(avci->buffer_pkt);
return ret;
}
if (!avci->buffer_frame->buf[0]) {
//解码核心
ret = decode_receive_frame_internal(avctx, avci->buffer_frame);
if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
return ret;
}
return 0;
}
具体的原理和解释可参考https://www.cnblogs.com/TaigaCon/p/10041926.html