FFmpeg avcodec_send_packet压缩包函数

首先看一下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

posted @ 2019-06-20 15:37  audioZane  阅读(2112)  评论(0编辑  收藏  举报