从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,如果各位遇到问题,可以留言交流

相关推荐
^_^ 纵歌4 天前
用python比较两个mp4是否实质相同
开发语言·python·音频·视频
ITRonnie4 天前
H.265硬件视频编码器xk265代码阅读 - 帧内预测
h.265·视频编解码·verilog编程·视频压缩芯片
QuZhengRong7 天前
【AI】免费GPU算力平台部署wan2.1
人工智能·腾讯云·视频
Everbrilliant899 天前
音视频之H.265/HEVC编码框架及编码视频格式
h.265·h.265编码格式·数字视频格式·h.265编码视频格式·hevc编码视频格式·h.265编码图像格式·h.265解码图像格式
Yeauty19 天前
Rust 中的高效视频处理:利用硬件加速应对高分辨率视频
开发语言·rust·ffmpeg·音视频·音频·视频
kailp21 天前
1Prompt1Story:为长故事创作赋予角色一致性的AI助手
人工智能·云计算·gpu算力·视频
许野平22 天前
Manim 输出视频尺寸设置
音视频·动画·视频·manim
禾川兴 1324240068825 天前
国产芯片解析:‌龙迅HDMI接收机系列产品详解
音频·视频
贫苦游商25 天前
AVI格式:经典视频格式的坚守与挑战
音视频·视频编解码·视频·格式转换·avi·格式工厂·工具箱
Yeauty1 个月前
三分钟掌握音频提取 | 在 Rust 中优雅地处理视频音频
后端·rust·ffmpeg·音视频·音频·视频