ffmpeg的函数调用知识点

av_dump_format 打印的内容是什么意思?

av_dump_format 会打印出AVFormatContext的内容,打印的内容是什么意思?

我们使用av_dump_format打印出如下信息:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'https://demo.com/BigBuckBunny.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isomavc1mp42
    creation_time   : 2010-01-10T08:29:06.000000Z
  Duration: 00:09:56.47, start: 0.000000, bitrate: 2119 kb/s
    Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s (default)
    Metadata:
      creation_time   : 2010-01-10T08:29:06.000000Z
      handler_name    : (C) 2007 Google Inc. v08.13.2007.
    Stream #0:1(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1991 kb/s, 24 fps, 24 tbr, 24k tbn, 48 tbc (default)
    Metadata:
      creation_time   : 2010-01-10T08:29:06.000000Z
      handler_name    : (C) 2007 Google Inc. v08.13.2007.

什么是文件的容器格式?

"mov,mp4,m4a,3gp,3g2,mj2" 表示输入文件的容器格式(Container Format)支持的扩展名。

在多媒体文件中,容器格式用于组织和存储多个音视频流以及其他相关数据。不同的容器格式支持不同的文件扩展名。这些扩展名用于指示文件的格式和类型。

在示例输出中,"mov,mp4,m4a,3gp,3g2,mj2" 表示输入文件是支持这些扩展名的容器格式。具体含义如下:

  • "mov":QuickTime Movie 文件,通常用于 macOS 平台。

  • "mp4":MPEG-4 Part 14 文件,是一种常见的多媒体容器格式,广泛用于存储音视频数据。

  • "m4a":MPEG-4 Audio 文件,用于存储音频数据。

  • "3gp":3rd Generation Partnership Project 文件,用于在移动设备上播放音视频。

  • "3g2":3rd Generation Partnership Project 2 文件,是 3GP 的增强版本。

  • "mj2":Motion JPEG 2000 文件,用于存储基于 JPEG 2000 压缩的视频。

因此,"mov,mp4,m4a,3gp,3g2,mj2" 表示输入文件是支持这些容器格式的文件,可以根据文件扩展名来推断文件的类型和格式。

多媒体文件格式说法比较笼统,准确说应该是被分为两种格式,编码格式 + 容器格式。

这就相当于我们会用盘子盛菜,也能用盘子盛米饭。

我们可以使用不同的容器格式盛放不同的编码格式。(当然这里也是有一些规定的,某个容器格式允许盛放哪些编码格式都是有明确要求的)

这个容器格式也就是我们日常看到的文件后缀。

在这里的输出中,我们有多个容器格式,说明我们是允许这个网络url下载的内容存放在mov/mp4/m4a等文件格式中的。

Metadata 有哪些信息?

av_dump_format() 输出的信息中,"Metadata" 部分包含了一些元数据信息,用于描述媒体文件的特定属性和相关数据。下面是对每个字段的解释:

  • major_brand:表示文件的主要品牌标识。它表示“最好”基于哪种格式来解析当前的文件。在示例中,"mp42" 表示该文件的主要品牌为 "mp42"。这是一种标识符,用于标识所使用的容器格式或编码器。

  • minor_version:表示文件的次要版本号。在示例中,"0" 表示该文件的次要版本为 0。

  • compatible_brands:表示文件与哪些兼容的品牌标识符兼容。在示例中,"isomavc1mp42" 表示该文件兼容 "isom"、"avc1" 和 "mp42" 这些品牌标识符。

  • creation_time:表示文件的创建时间。在示例中,"2010-01-10T08:29:06.000000Z" 表示该文件的创建时间为 2010 年 1 月 10 日 08:29:06(UTC 时间)。

这些元数据信息提供了关于媒体文件的额外信息,如文件的品牌标识、版本号、兼容性和创建时间。这些信息可以用于判断文件的属性、兼容性和制作信息。

Duration有哪些信息?

Duration: 00:09:56.47, start: 0.000000, bitrate: 2119 kb/s

这个信息比较好理解,视频文件有9分56秒,播放比特率是2119kb/s

视频的比特率(bitrate)是指在单位时间内传输或处理的比特数,通常以每秒的比特数(bps,bits per second)为单位。它表示视频数据的传输速率或处理速度。

比特率直接影响视频的数据量和质量,较高的比特率意味着更多的数据被分配给每个时间单位,从而提供更高的视频质量和更精细的细节。较低的比特率则表示视频数据被压缩得更多,可以减小文件大小或降低传输带宽要求,但可能会导致视频质量的损失和细节的丢失。

音频流有哪些信息?

Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s (default)
    Metadata:
      creation_time   : 2010-01-10T08:29:06.000000Z
      handler_name    : (C) 2007 Google Inc. v08.13.2007.

"Stream #0:0(und)" 表示第一个流(Stream)的信息。下面是对每个字段的解释:

  • Audio:表示该流是音频流。

  • aac (LC):表示音频编解码器为 AAC(Advanced Audio Coding)的低复杂度(Low Complexity)模式。

  • mp4a / 0x6134706D:表示音频编码器的标识符为 "mp4a",对应的十六进制值为 "0x6134706D"。

  • 44100 Hz:表示音频采样率为 44,100 Hz,即每秒采集和播放的音频样本数。

  • stereo:表示音频通道模式为立体声,即左右两个声道。

  • fltp:表示音频采样格式为浮点型(floating point)。

  • 125 kb/s:表示音频的比特率为 125 kb/s,即每秒传输或处理的音频数据量为 125 kb。

  • (default):表示该流是默认的流。

  • handler_name: 表示是由 Google 公司开发的某个版本的处理程序生成或处理的。

视频流有哪些信息?

"Stream #0:1(und)" 表示第二个流(Stream)的信息,即视频流。下面是对每个字段的解释:

  • Video:表示该流是视频流。

  • h264 (High):表示视频编解码器为 H.264(高级)。

  • avc1 / 0x31637661:表示视频编码器的标识符为 "avc1",对应的十六进制值为 "0x31637661"。

  • yuv420p:表示视频采样格式为 YUV420P,即色彩空间为 YUV,亮度和色度分量的采样比例为 4:2:0。

  • 1280x720:表示视频分辨率为 1280x720 像素。

  • [SAR 1:1 DAR 16:9]:表示视频的样本宽高比(Sample Aspect Ratio)为 1:1,显示宽高比(Display Aspect Ratio)为 16:9。

  • 1991 kb/s:表示视频的比特率为 1991 kb/s,即每秒传输或处理的视频数据量为 1991 kb。

  • 24 fps:表示视频的帧率为 24 帧每秒。

  • 24 tbr, 24k tbn, 48 tbc:表示视频的时间基准信息。

  • (default):表示该流是默认的流。

  • handler_name: 表示是由 Google 公司开发的某个版本的处理程序生成或处理的。

AVStream结构有哪些元素?

AVStream 结构是 FFmpeg 中表示媒体流的数据结构,它包含了媒体流的各种属性和信息。下面是 AVStream 结构中一些常用的成员变量:

  • index:表示流的索引号。

  • id:表示流的唯一标识符。

  • codecpar:指向 AVCodecParameters 结构的指针,包含了与该流关联的编解码器参数。

  • time_base:表示流的时间基准,用于将时间单位转换为实际时间。

  • start_time:表示流的起始时间。

  • duration:表示流的时长。

  • nb_frames:表示流中的帧数。

  • disposition:表示流的布局或位置相关的标志。

  • avg_frame_rate:表示流的平均帧率。

  • r_frame_rate:表示流的参考帧率。

  • metadata:指向 AVDictionary 结构的指针,包含了流的元数据。

要使用 AVStream 结构,可以先通过 AVFormatContext 结构中的 streams 数组获取特定的 AVStream 结构,然后使用相应的成员变量获取所需的信息。例如,要获取流的索引号可以使用 avStream->index,获取流的时间基准可以使用 avStream->time_base,获取流的元数据可以使用 avStream->metadata

ffmpeg如何读取视频流?

ffmpeg需要先定位mp4中的视频流,从视频流stream中读取每一帧,将每一帧再转换为yuv格式。

// 解码器
    AVCodec* codec = nullptr;
    AVCodecContext* codecContext = avcodec_alloc_context3(codec);

  // 寻找到视频流
    int videoStreamIndex = av_find_best_stream(inputContext, AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0);
    if (videoStreamIndex < 0) {
        // 没有找到视频流
        return -1;
    }

    // 获取视频流
    AVStream* stream = inputContext->streams[videoStreamIndex];
           
    if (avcodec_parameters_to_context(codecContext, stream->codecpar) < 0) {
        // 获取解码器上下文失败
        return -1;
    }
    if (avcodec_open2(codecContext, codec, nullptr) < 0) {
        // 打开解码器失败
        return -1;
    }

    // 分配视频帧和 YUV 帧
    AVFrame* frame = av_frame_alloc();
    AVFrame* frameYUV = av_frame_alloc();
    int frameBufferSize = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, codecContext->width, codecContext->height, 1);
    uint8_t* frameBuffer = (uint8_t*)av_malloc(frameBufferSize * sizeof(uint8_t));
    av_image_fill_arrays(frameYUV->data, frameYUV->linesize, frameBuffer, AV_PIX_FMT_YUV420P, codecContext->width, codecContext->height, 1);

    // 初始化图像转换上下文
    struct SwsContext* swsContext = sws_getContext(codecContext->width, codecContext->height, codecContext->pix_fmt, codecContext->width, codecContext->height, AV_PIX_FMT_YUV420P, SWS_BILINEAR, nullptr, nullptr, nullptr);
    // 读取视频帧并转换为 YUV 格式
    AVPacket packet;
    while (av_read_frame(inputContext, &packet) >= 0) {
        if (packet.stream_index == videoStreamIndex) {
            // 解码视频帧
            avcodec_send_packet(codecContext, &packet);
            avcodec_receive_frame(codecContext, frame);

            // 转换为 YUV 格式
            sws_scale(swsContext, frame->data, frame->linesize, 0, codecContext->height, frameYUV->data, frameYUV->linesize);

            // 在这里可以对 YUV 数据进行处理

            // 释放帧的引用
            av_frame_unref(frame);
        }

        av_packet_unref(&packet);
    }

ffmpeg如何定位到某个流的第几秒开始播放?

使用 av_seek_frame 函数:可以使用 av_seek_frame 函数在特定的时间点进行定位。这个函数可以用于音频和视频流。以下是一个示例代码片段,展示了如何使用 av_seek_frame 定位到指定的时间点:

int64_t timestamp = desired_time * AV_TIME_BASE;  // 将秒转换为时间戳
int stream_index = 0;  // 假设我们要定位到第一个流

AVStream* stream = formatContext->streams[stream_index];
int64_t seek_target = av_rescale_q(timestamp, AV_TIME_BASE_Q, stream->time_base);

// 定位到指定时间点
av_seek_frame(formatContext, stream_index, seek_target, AVSEEK_FLAG_BACKWARD);

参考

5分钟入门MP4文件格式

 

你可能感兴趣的:(ffmpeg)