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 的未来发展趋势

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

相关推荐
tedcloud12317 小时前
OmniRoute怎么部署?开源AI模型路由平台Linux部署教程
linux·服务器·人工智能·开源·音视频
潜创微科技20 小时前
8K HDMI 2.1 多源切换芯片方案,一颗芯片搞定长线不黑屏
音视频
音视频牛哥21 小时前
一款优秀的视频直播软件应具备哪些核心功能?结合 SmartMediaKit 谈实时音视频系统的能力边界
音视频·视频直播·低延迟rtsp播放器·gb28181接入·rtsp服务器·低延迟rtmp播放器·鸿蒙next rtsp
AI小码21 小时前
把动作「画」给视频世界模型,跨本体双向推演,李飞飞参与
大数据·人工智能·算法·ai·大模型·音视频·编程
嵌入式-老费1 天前
esp32开发与应用(边采样边播放音频)
音视频
中微极客1 天前
Veo视频生成与Gemini Agent平台集成实践
数据库·人工智能·oracle·音视频
码龙-DragonCoding1 天前
一键批量提取音频、提取视频
android·音视频·提取
阿童木写作1 天前
Temu商品图批量翻译工具免费,AI视频字幕翻译+智能抠图
人工智能·python·音视频
中微极客1 天前
2026年AI视频生成模型技术选型与工程实践
人工智能·音视频
cellurw1 天前
20260723 六组件全流程编译打通与音频项目启动
linux·服务器·音视频