FFmpeg中帧和包的区别

Posted

技术标签:

【中文标题】FFmpeg中帧和包的区别【英文标题】:Difference between Frames and Packets in FFmpeg 【发布时间】:2019-05-03 15:04:38 【问题描述】:

我正在尝试使用 LibAV 解码 MPEG 视频文件。有两个术语我无法正确理解,FramesPackets

根据我目前的理解,Frames是未压缩的视频帧,packets是压缩后的帧。

问题

数据包有多个帧,对吧? 一个帧是否只能是一个数据包的一部分?我指的是一半帧信息在packet1中,另一半在packet2中的情况?有可能吗? 我们如何知道 LibAV 中一个数据包中有多少帧?

【问题讨论】:

你找到答案了吗? 我也对此感到困惑。虽然还没弄明白,但这是我的笔记-dev.to/nsrcodes/… 【参考方案1】:

回答你的第一个和第三个问题:

根据doc for the AVPacket class:“对于视频,它通常应该包含一个压缩帧。对于音频,它可能包含几个压缩帧。 decode video example 给出了读取数据包内所有帧的代码;你也可以用它来计算帧数:
static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt,
                   const char *filename)

    char buf[1024];
    int ret;
    ret = avcodec_send_packet(dec_ctx, pkt);
    if (ret < 0) 
        fprintf(stderr, "Error sending a packet for decoding\n");
        exit(1);
    
    while (ret >= 0) 
        ret = avcodec_receive_frame(dec_ctx, frame);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return;
        else if (ret < 0) 
            fprintf(stderr, "Error during decoding\n");
            exit(1);
        
        printf("saving frame %3d\n", dec_ctx->frame_number);
        fflush(stdout);
        /* the picture is allocated by the decoder. no need to
           free it */
        snprintf(buf, sizeof(buf), filename, dec_ctx->frame_number);
        pgm_save(frame->data[0], frame->linesize[0],
                 frame->width, frame->height, buf);
    

【讨论】:

【参考方案2】:

简单地说,一个数据包就是一个数据块。

这通常由带宽决定。如果设备的互联网速度有限,或者手机信号不稳定,那么数据包大小会更小。如果是带有专用服务的桌面,packetize 可能会大一些。

一帧可以被认为是动画的一个单元格,但现在通常,由于压缩,它不是实际的关键帧图像,而只是自上一个完整关键帧以来的变化。他们将每隔几秒左右发送一个关键帧,即一张实际图像,但中间的每一帧只是数据的混合,用于指定自上一张图像(增量)以来哪些像素发生了变化。

是的,假设您的数据包大小为 1024 字节,那么您的分辨率将被限制为流可以承载更改的像素数量。他们可能会发送每个数据包一帧以保持简单,但我认为没有任何东西可以绝对保证,因为数据流是从这些数据包中重建的,通常是无序的,然后帧增量生成一次所有这些数据包都拼凑在一起。

音频占用的空间比视频少得多,因此他们可能只需要为每 50 个视频包发送一个音频包。

我知道这些人在他们的频道上做了一些关于从数据包中重组的视频流的剪辑 -- https://www.youtube.com/watch?v=DkIhI59ysXI

【讨论】:

【参考方案3】:

基本上,帧是自然的,而数据包是人工的。 ?

帧是实质性的,数据包是辅助性的——它们有助于通过可接受大小的较小部分连续处理流(而不是将流作为一个整体进行处理)。 “分而治之。”

数据包有多个帧,对吧?

数据包可能有多个(编码)帧,也可能只有一个,甚至不完整。

一个帧可以只是一个数据包的一部分吗?

没有。它可能分布在几个数据包中。请参阅图片中的第 1 帧

我指的是帧信息一半在packet1,另一半在packet2的情况?有可能吗?

是的。请参阅第 1 帧

在 LibAV 中我们如何知道一个数据包中有多少帧?

不同多媒体文件中每个数据包的帧数可能不同,这取决于特定流的编码方式。

即使在同一个流中,也可能存在具有不同数量(编码)帧的数据包 - 比较 Packet 0Packet 1.

一个数据包中没有包含多少(编码)帧的信息。

同一数据包中的帧通常具有不同的大小(如上图所示),因此数据包不是由相同大小的元素(帧)组成的数组。

【讨论】:

您的 Packet 1 示例是否扩展到 I 帧(关键帧)?我知道帧数据可以在多个数据包中用于预测帧(p 帧、b 帧等)。它们建立在前一帧之上,因此在前一个数据包中隐含了它们的一些数据。但是,我在 FFMPEG API 中找不到任何可以让我将关键帧存储在多个数据包中的内容。

以上是关于FFmpeg中帧和包的区别的主要内容,如果未能解决你的问题,请参考以下文章

使用ffmpeg从视频文件中提取音频文件视频抽帧和切割视频

FFMPEG 和 OPENGL - 原始帧

FFMPEG 转码器产生损坏的视频

新手学习FFmpeg - 调用API计算关键帧渲染时间点

ffmpeg 和 SDL 的区别和联系? 谢谢

ffmpeg录屏默认频率