FFmpeg 视频旋转信息处理:3.4 vs 7.0.2

1. 概述

FFmpeg 在处理视频旋转信息方面经历了重要的架构变化。本文档详细对比了 FFmpeg 3.4 和 7.0.2 在封装(muxing)和解封装(demuxing)视频旋转信息时的差异,并提供兼容性解决方案。文档内容由Claude Sonnet 4辅助撰写,如有疏漏还请斧正。

  • FFmpeg 3.4:支持 metadata 和 side data 双重机制
  • FFmpeg 7.0.2:主要依赖 side data 机制,弱化 metadata 支持

2. 旋转信息存储机制

存储方式 FFmpeg 3.4 FFmpeg 7.0.2 说明
Stream Metadata ✅ 读写支持 ❌ 仅读取(兼容性) stream->metadata["rotate"]
Side Data ✅ 读写支持 ✅ 主要方式 AV_PKT_DATA_DISPLAYMATRIX
容器原生格式 ✅ 支持 ✅ 支持 MP4 tkhd atom 等
c 复制代码
// Metadata 格式(字符串)
stream->metadata["rotate"] = "90"  // 90度旋转

// Side Data 格式(3x3 变换矩阵)
int32_t displaymatrix[9] = {
    cos(θ), -sin(θ), 0,
    sin(θ),  cos(θ), 0,
    0,       0,      1
};

3. 解封装(Demuxing)对比

3.1 FFmpeg 3.4 解封装行为

c 复制代码
// FFmpeg 3.4 读取流程
void ffmpeg34_demux_rotation() {
    // 1. 从容器读取 displaymatrix
    uint8_t *displaymatrix = read_container_displaymatrix();
    
    // 2. 设置 side data
    av_stream_add_side_data(stream, AV_PKT_DATA_DISPLAYMATRIX, displaymatrix, size);
    
    // 3. 同时设置 metadata(便于应用程序使用)
    if (displaymatrix) {
        double rotation = av_display_rotation_get((int32_t*)displaymatrix);
        av_dict_set(&stream->metadata, "rotate", 
                   av_asprintf("%.0f", -rotation), AV_DICT_DONT_STRDUP_VAL);
    }
}

// 应用程序读取(推荐方式)
int getRotation_v34(AVStream *stream) {
    // 方式1:从 metadata 读取(简单)
    AVDictionaryEntry *t = av_dict_get(stream->metadata, "rotate", NULL, 0);
    if (t) return atoi(t->value);
    
    // 方式2:从 side data 读取(精确)
    uint8_t *displaymatrix = av_stream_get_side_data(stream, AV_PKT_DATA_DISPLAYMATRIX, NULL);
    if (displaymatrix) {
        return (int)(-av_display_rotation_get((int32_t*)displaymatrix));
    }
    return 0;
}

3.2 FFmpeg 7.0.2 解封装行为

c 复制代码
// FFmpeg 7.0.2 读取流程
void ffmpeg70_demux_rotation() {
    // 1. 从容器读取 displaymatrix
    uint8_t *displaymatrix = read_container_displaymatrix();
    
    // 2. 只设置 side data
    av_packet_side_data_add(&stream->codecpar->coded_side_data,
                           &stream->codecpar->nb_coded_side_data,
                           AV_PKT_DATA_DISPLAYMATRIX, displaymatrix, size, 0);
    
    // 3. 不再自动设置 metadata
    // stream->metadata["rotate"] 为空!
}

// 应用程序读取(新方式)
int getRotation_v70(AVStream *stream) {
    // 只能从 side data 读取
    AVPacketSideData *side_data = av_packet_side_data_get(
        stream->codecpar->coded_side_data,
        stream->codecpar->nb_coded_side_data,
        AV_PKT_DATA_DISPLAYMATRIX
    );
    
    if (side_data && side_data->size >= 9 * sizeof(int32_t)) {
        double rotation = av_display_rotation_get((int32_t*)side_data->data);
        return (int)(-rotation);
    }
    return 0;
}

4. 封装(Muxing)对比

4.1 FFmpeg 3.4 封装行为

c 复制代码
// FFmpeg 3.4 支持多种设置方式

// 方式1:通过 metadata 设置(推荐)
int setRotation_v34_metadata(AVStream *stream, int degrees) {
    char rotation_str[16];
    snprintf(rotation_str, sizeof(rotation_str), "%d", degrees);
    
    // 设置 metadata,muxer 会自动转换为 displaymatrix
    return av_dict_set(&stream->metadata, "rotate", rotation_str, 0);
}

// 方式2:直接设置 side data
int setRotation_v34_sidedata(AVStream *stream, int degrees) {
    uint8_t *displaymatrix = av_stream_new_side_data(stream, 
                                                    AV_PKT_DATA_DISPLAYMATRIX, 
                                                    9 * sizeof(int32_t));
    if (!displaymatrix) return -1;
    
    av_display_rotation_set((int32_t*)displaymatrix, -(double)degrees);
    return 0;
}

4.2 FFmpeg 7.0.2 封装行为

c 复制代码
// FFmpeg 7.0.2 主要通过 side data 设置

int setRotation_v70(AVStream *stream, int degrees) {
    // metadata 方式可能无效,必须使用 side data
    int32_t *displaymatrix = (int32_t*)av_packet_side_data_new(
        &stream->codecpar->coded_side_data,
        &stream->codecpar->nb_coded_side_data,
        AV_PKT_DATA_DISPLAYMATRIX,
        9 * sizeof(int32_t),
        0
    );
    
    if (!displaymatrix) return -1;
    
    av_display_rotation_set(displaymatrix, -(double)degrees);
    return 0;
}

5. 总结

FFmpeg 在处理视频旋转信息方面的变化反映了其向更标准化、更精确方向的演进:

  • FFmpeg 3.4:过渡期版本,同时支持 metadata 和 side data
  • FFmpeg 7.0.2:现代化版本,主要依赖标准化的 side data

开发者应该:

  1. 在新项目中优先使用 side data API
  2. 保持对旧版本的兼容性支持
  3. 进行充分的跨版本测试
  4. 关注 FFmpeg 的未来发展趋势

这种变化虽然增加了开发复杂度,但提供了更好的标准兼容性和更精确的旋转信息处理能力。

相关推荐
却道天凉_好个秋3 小时前
音视频学习(六十):H264中的PPS
音视频·h.264·pps
Js_cold1 天前
FPGA DDR 地址映射-黄金法则
图像处理·fpga开发·音视频·视频
音视频牛哥1 天前
低空经济产业白皮书:音视频链路在智能飞行体系中的核心地位
音视频·大牛直播sdk·无人机视频传输rtsp·无人机视频传输rtmp·边缘计算与视频感知 rtsp·rtsp 播放器 sdk·rtmp播放器sdk
lichong9511 天前
【混合开发】Android+WebView视频图片播放硬件加速详解
android·音视频
iphone1082 天前
企业内部机密视频安全保护|如何防止企业内部机密视频泄露?
安全·音视频·视频加密·加密技术·视频安全·企业机密·机密视频
音视频牛哥2 天前
机器人视频感知架构深度解析:7条技术法则,打造低延迟实时感知与交互
人工智能·计算机视觉·机器人·音视频·大牛直播sdk·机器视觉·rtmp rtsp播放器
Ai工具分享2 天前
让模糊物体变清晰的视频AI:快速提升画质指南
人工智能·音视频
菠萝加点糖2 天前
Android 使用MediaMuxer+MediaCodec编码MP4视频
android·音视频·编码
9527华安2 天前
FPGA实现Aurora 64B66B图像视频传输,基于GTY高速收发器,提供2套工程源码和技术支持
fpga开发·音视频·aurora·高速收发器·gty·aurora 64b66b
Jons伯恩特2 天前
音频中的噪音门
音视频·音频·噪音门·噪声门