avcodec_send_frame和avcodec_receive_packet

简介: avcodec_send_frame和avcodec_receive_packet

编码器和解码器都维护了一个缓冲区,在刚开始输入数据时,需要多输入几帧,等缓冲区被填充满后,才会在receive端接收到编码或解码后的数据。

另一方面因为存在AVPacket中的数据不一定是一帧(比如音频的数据可能1个AVPacket包含1s的数据,帧率为25的话,就包含25帧),但存在AVFrame中的是一帧数据,所以avcodec_send_packet和avcodec_receive_frame不一定一一对应,调用一次avcodec_send_packet后,可能需要多次调用avcodec_receive_frame,另一篇文章讨论av_read_frame每次返回的视频和音频帧数


解码接口:

avcodec_send_packet和avcodec_receive_frame

内存:frame只需要分配对象本身空间就好,frame->data的空间并不需要分配。函数会判断是否已经给frame->data分配空间,如果没有分配会在函数内部为frame->data分配合适的空间。另一篇文章,AVFrame内存讨论,AVFrame相关api

。举例如下:

int re = avcodec_send_packet(codec_ctx, pkt);
if (re != 0)
{
    return;
}
while( avcodec_receive_frame(codec_ctx, frame) >= 0)
{
    //处理接收后的帧
}


avcodec_receive_frame:send端只把数据放入缓冲区,recive端才是解码并获得数据的函数,如果receive发现已有解码后的数据则直接获取,如果没有则开始解码。


编码接口

数据遗留:在最后应该向avcodec_send_frame(enc_ctx, NULL)传入NULL数据,这样编码器知道后面不会再有数据,就把放在缓冲区中的数据,全部编码并通过avcodec_receive_packet输出出来。


返回值:EAGAIN,意思是需要输入更多的数据,才会有新的数据编码后的数据返回。AVERROR_EOF在从文件中读取数据推流时,出现这个错误是因为文件内的数据读完了。


参数内存:newpkt->data并不需要分配数据空间,只需要给newpkt本身结构体分配空间就好。另一篇文章,关于AVPacket内存与avcodec_receive_packet的关系,AVPacket相关api

func()
{
  avcodec_send_frame(enc_ctx, frame);
  if(ret < 0)
  {
    //Error
  }
  while(ret >= 0)
  {
    ret = avcodec_receive_packet(enc_ctx, newpkt);
    if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)  {return;}
    else if(ret < 0){//Error}
  }
}


在ubuntu虚拟机中采集pc摄像头,并推流实测编解码的四个函数是否一一对应关系,帧率为30:

解码

avcodec_send_packet

avcodec_receive_frame

记录:s1518 r1518 s2754 r2754

s发送的次数,r成功接收的次数

第一次调用avcodec_send_packet,avcodec_receive_frame就成功接收到数据了。并且以后每次也都一一对应调用两个函数。


编码

avcodec_send_frame

avcodec_receive_packet

//s1336 r1286 s867 r817 保持50帧

avcodec_send_frame连续调用50次后,avcodec_receive_packet才成功接收到一次数据,以后每次都一一对应。


在ubuntu虚拟机中采集pc声卡,并推流实测编解码的三个函数是否一一对应关系:

解码

avcodec_send_packet

avcodec_receive_frame

av_interleaved_write_frame

实测当分别送进去128,1024,940个音频采样到avcodec_send_frame时,avcodec_receive_packet一对一返回,开始并没有几帧缓存,av_interleaved_write_frame也一对一执行,也没有一开始缓存几帧。也就是三者总是保持一对一执行,后两者都有返回,并且一开始没有缓存。音频涉及到字节的处理,见另一篇博客:libfdk_aac音频采样数和编码字节数注意



附录:

libavcodec\encode.c

int attribute_align_arg avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
{
    av_packet_unref(avpkt);
    if (!avcodec_is_open(avctx) || !av_codec_is_encoder(avctx->codec))
        return AVERROR(EINVAL);
    if (avctx->codec->receive_packet) {
        if (avctx->internal->draining && !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY))
            return AVERROR_EOF;
        return avctx->codec->receive_packet(avctx, avpkt);
    }
    // Emulation via old API.
    if (!avctx->internal->buffer_pkt_valid) {
        int got_packet;
        int ret;
        if (!avctx->internal->draining)
            return AVERROR(EAGAIN);
        ret = do_encode(avctx, NULL, &got_packet);
        if (ret < 0)
            return ret;
        if (ret >= 0 && !got_packet)
            return AVERROR_EOF;
    }
    av_packet_move_ref(avpkt, avctx->internal->buffer_pkt);
    avctx->internal->buffer_pkt_valid = 0;
    return 0;
}
void av_packet_unref(AVPacket *pkt)
{
    av_packet_free_side_data(pkt);
    av_buffer_unref(&pkt->buf);
    av_init_packet(pkt);
    pkt->data = NULL;
    pkt->size = 0;
}
相关文章
|
3月前
[音视频] avcodec_send_packet 返回-22
[音视频] avcodec_send_packet 返回-22
|
8月前
ffmpeg编码报错:more samples than frame size (avcodec_encode_audio2)
ffmpeg编码报错:more samples than frame size (avcodec_encode_audio2)
50 0
ffmpeg编码报错:more samples than frame size (avcodec_encode_audio2)
|
8月前
nobuffer与av_read_frame的关系
nobuffer与av_read_frame的关系
39 0
|
8月前
|
网络协议
av_interleaved_write_frame -32 broken pipe
av_interleaved_write_frame -32 broken pipe
128 0
av_interleaved_write_frame -32 broken pipe
|
8月前
|
编解码
av_read_frame返回值为-5 Input/output error
av_read_frame返回值为-5 Input/output error
85 0
|
8月前
|
索引
av_find_best_stream
av_find_best_stream
68 0
av_find_best_stream
|
存储 编解码 Android开发
【Android FFMPEG 开发】FFMPEG 解码 AVPacket 数据到 AVFrame ( AVPacket->解码器 | 初始化 AVFrame | 解码为 AVFrame 数据 )
【Android FFMPEG 开发】FFMPEG 解码 AVPacket 数据到 AVFrame ( AVPacket->解码器 | 初始化 AVFrame | 解码为 AVFrame 数据 )
257 0
|
存储 编解码 Android开发
【Android FFMPEG 开发】FFMPEG 读取音视频流中的数据到 AVPacket ( 初始化 AVPacket 数据 | 读取 AVPacket )
【Android FFMPEG 开发】FFMPEG 读取音视频流中的数据到 AVPacket ( 初始化 AVPacket 数据 | 读取 AVPacket )
209 0
error: ‘avcodec_alloc_frame’ was not declared in this scope
error: ‘avcodec_alloc_frame’ was not declared in this scope
175 0