从H264视频中获取宽、高、帧率、比特率等属性信息

背景

最近整理视频编解码的代码,早前在jetson上封装了jetson multimedia作为视频编解码的类,供其他同事和其他组使用,但该解码接口有一个问题,无法首先获取视频宽高信息,更无法直接获取视频的帧率、比特率等信息。

解决方法

  1. 使用ffmpeg库,命令行参数不适合代码集成
  2. 使用ffmpeg的API接口进行封装

源码实现

cpp 复制代码
// ffmpeg_videoinfo.h

#ifndef FFMPEG_VIDEOINFO_H
#define FFMPEG_VIDEOINFO_H

#include <iostream>
#include <memory>

struct VideoAsset {
    float width; 
    float height;
    float fps;
    float bitrate; /** bit per second */
    float duration; /** seconds */
};

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

int GetVideoInfo(const char *in_file,  std::shared_ptr<VideoAsset> &info);

#ifdef __cplusplus
};
#endif

#endif  // FFMPEG_VIDEOINFO_H
cpp 复制代码
// ffmpeg_videoinfo.cpp


#include "ffmpeg_videoinfo.h"

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>

int GetVideoInfo(const char *in_file,  std::shared_ptr<VideoAsset> &info){
  // 注册所有格式和编解码器
    av_register_all();

    // 创建一个格式上下文(Format Context)
    AVFormatContext* formatContext = nullptr;
    if (avformat_open_input(&formatContext, in_file, nullptr, nullptr) != 0) {
        fprintf(stderr, "Could not open input file '%s'", in_file);
        return -1;
    }

    // 获取流信息
    if (avformat_find_stream_info(formatContext, nullptr) < 0) {
        fprintf(stderr, "Could not find stream information '%s'", in_file);
        return -1;
    }

    // 查找视频流
    int videoStreamIndex = -1;
    for (unsigned i = 0; i < formatContext->nb_streams; i++) {
        if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoStreamIndex = i;
            break;
        }
    }

    if (videoStreamIndex == -1) {
        fprintf(stderr, "Could not find video stream '%s'", in_file);
        return -1;
    }

    // 获取视频流的编码参数
    AVCodecParameters* codecParameters = formatContext->streams[videoStreamIndex]->codecpar;
    AVStream* videoStream = formatContext->streams[videoStreamIndex];
    info->fps = av_q2d(videoStream->avg_frame_rate);
    info->width = codecParameters->width;
    info->height = codecParameters->height;

    int64_t totalSize = 0;
    int64_t totalDuration = 0;
    AVPacket packet;
    while (av_read_frame(formatContext, &packet) >= 0) {
        if (packet.stream_index == 0) {
            totalSize += packet.size;
            totalDuration += packet.duration;
        }
        av_packet_unref(&packet);
    }

    AVRational timeBase = videoStream->time_base; /** 时间基 */
    info->duration = (float)totalDuration * av_q2d(timeBase);
    info->bitrate = (totalDuration > 0) ? (totalSize * 8.0 / info->duration) : 0.0;

    // 清理
    avformat_close_input(&formatContext);

    return 0;
}
#ifdef __cplusplus
};
#endif
cpp 复制代码
// 测试脚本 test_single_videoinfo.cpp



#include "ffmpeg_videoinfo.h"

int main(int argc, char **argv) {
  if(argc<2){
    return 1;
  }
  const std::string &input_h264=argv[1];

  std::shared_ptr<VideoAsset> video_info_ptr = std::make_shared<VideoAsset>();
  // VideoAsset video_info;
  int status_code = GetVideoInfo(input_h264.c_str(), video_info_ptr);
  if (status_code < 0) {
    printf("GetVideoInfo failed\n");
    return -1;
  }
  printf("bitrate:%f, duration:%f, fps:%f, height:%f, width:%f\n",
         video_info_ptr->bitrate, video_info_ptr->duration, 
         video_info_ptr->fps, video_info_ptr->height, 
         video_info_ptr->width);
  return 1;
}
bash 复制代码
# CMakelist.txt核心

add_executable(test_video_info test_single_videoinfo.cpp ffmpeg_videoinfo.h ffmpeg_videoinfo.cpp)
target_compile_features(test_video_info PRIVATE cxx_std_14)
target_link_libraries(test_video_info avcodec avutil avformat)
bash 复制代码
# 测试

./test_video_info /data/videos/l4t.h264

# 输出信息示例
[h264 @ 0xaaaac14b16a0] Stream #0: not enough frames to estimate rate; consider increasing probesize
bitrate:30681866.000000, duration:164.490005, fps:20.000000, height:2160.000000, width:3840.000000

后记

本人对ffmpeg接口并不熟悉,以上根据文档及搜索结果进行的实现,不敢保证没有bug,如果各位遇到问题,可以留言交流

相关推荐
新知图书21 小时前
使用OpenCV的VideoCapture播放视频文件示例
opencv·视频
Everbrilliant895 天前
音视频之H.265/HEVC编解码并处理
音视频·h.265·h.265编解码·h.265编解码并行处理·视频编解码并行处理·gop级并行·图像级并行
xuebodx09238 天前
使用HunyuanVideo搭建文本生视频大模型
人工智能·pytorch·python·计算机视觉·chatgpt·音视频·视频
Everbrilliant8913 天前
音视频之H.265/HEVC网络适配层
网络·音视频·h.265·nalu·h.265/hevc网络适配层·视频编码层vcl·网络适配层nal
Everbrilliant8915 天前
音视频之H.265/HEVC熵编码
音视频·h.265·算术编码·哈夫曼编码·熵编码·指数哥伦布编码·熵编码的基本原理
伊织code17 天前
SAM 2 (Segment Anything ):图像与视频通用分割模型
sam·图像·视频·模型·segment·anything·分隔
Everbrilliant8917 天前
音视频之H.265/HEVC环路后处理
音视频·h.265·h.265/hevc·去方块滤波技术·h.265环路后处理·sao技术·h.265去方块滤波
Everbrilliant8918 天前
音视频之H.265/HEVC量化
h.265·h.265/hevc·h.265量化·h.265标量量化·h.265均匀量化·熵编码量化器·量化矩阵
大数据AI人工智能培训专家培训讲师叶梓21 天前
FramePack:让视频生成更高效、更实用
人工智能·ai·大模型·音视频·视频·视频生成·长视频
^_^ 纵歌25 天前
用python比较两个mp4是否实质相同
开发语言·python·音频·视频