当前位置: 首页 > news >正文

AVFormatContext

1. AVFormatContext 的通用性

1.1 通用结构

  • AVFormatContext 是 FFmpeg 中的一个通用结构体,用于描述多媒体文件或流的上下文信息。
  • 它既可以用于输入文件/流,也可以用于输出文件/流。
  • 关键字段(如 iformatoformat)决定了 AVFormatContext 是用于输入还是输出。

1.2 输入和输出的区别

  • 输入 AVFormatContext
    • 用于描述输入文件或流的上下文信息。
    • 通过 iformat 字段(AVInputFormat)指定输入格式。
    • 通过 avformat_open_input 自动分配和初始化。
  • 输出 AVFormatContext
    • 用于描述输出文件或流的上下文信息。
    • 通过 oformat 字段(AVOutputFormat)指定输出格式。
    • 通过 avformat_alloc_output_context2avformat_alloc_context 手动分配和初始化。

2. avformat_alloc_context 的作用

2.1 通用分配函数

  • avformat_alloc_context 是一个通用的分配函数,用于分配并初始化一个空的 AVFormatContext
  • 它不会自动设置 iformatoformat,需要手动设置。

2.2 使用场景

  • 输入文件/流
    • 通常不直接使用 avformat_alloc_context,而是通过 avformat_open_input 自动分配和初始化 AVFormatContext
  • 输出文件/流
    • 通常使用 avformat_alloc_output_context2,它会自动设置 oformat

3. 输入和输出的 AVFormatContext 的创建方式

3.1 输入 AVFormatContext

  • 使用 avformat_open_input 打开输入文件/流时,FFmpeg 会自动分配并初始化一个 AVFormatContext
  • 示例:
    import Foundation
    import FFmpeg
    
    class FFmpegInputManager {
        static func openInputFile(filePath: String) -> UnsafeMutablePointer<AVFormatContext>? {
            var formatContext: UnsafeMutablePointer<AVFormatContext>? = nil
    
            // 打开输入文件
            if avformat_open_input(&formatContext, filePath, nil, nil) < 0 {
                print("Failed to open input file: \(filePath)")
                return nil
            }
    
            print("Input file opened successfully: \(filePath)")
            return formatContext
        }
    }
    
    // 调用示例
    if let inputContext = FFmpegInputManager.openInputFile(filePath: "input.mp4") {
        // 使用 inputContext
        print("Input context created: \(inputContext)")
    
        // 打印文件信息
        av_dump_format(inputContext, 0, "input.mp4", 0)
    
        // 释放资源
        avformat_close_input(&inputContext)
    }
    
关键点
  • avformat_open_input 会自动分配并初始化 AVFormatContext
  • iformat 字段会被设置为输入文件的格式(AVInputFormat)。

3.2 输出 AVFormatContext

  • 使用 avformat_alloc_output_context2avformat_alloc_context 手动分配和初始化一个 AVFormatContext
  • 示例:
    import Foundation
    import FFmpeg
    
    class FFmpegOutputManager {
        static func createOutputFile(filePath: String, formatName: String) -> UnsafeMutablePointer<AVFormatContext>? {
            var formatContext: UnsafeMutablePointer<AVFormatContext>? = nil
    
            // 创建输出文件
            if avformat_alloc_output_context2(&formatContext, nil, formatName, filePath) < 0 {
                print("Failed to create output file: \(filePath)")
                return nil
            }
    
            print("Output file created successfully: \(filePath)")
            return formatContext
        }
    }
    
    // 调用示例
    if let outputContext = FFmpegOutputManager.createOutputFile(filePath: "output.mp4", formatName: "mp4") {
        // 使用 outputContext
        print("Output context created: \(outputContext)")
    
        // 释放资源
        avformat_free_context(outputContext)
    }
    
关键点
  • avformat_alloc_output_context2 会自动分配并初始化 AVFormatContext,并设置 oformat 字段为输出格式(AVOutputFormat)。
  • 如果使用 avformat_alloc_context,需要手动设置 oformat

4. 输入和输出的 AVFormatContext 的区别

属性输入 AVFormatContext输出 AVFormatContext
创建方式使用 avformat_open_input 自动分配和初始化使用 avformat_alloc_output_context2avformat_alloc_context 手动分配
格式字段iformatAVInputFormatoformatAVOutputFormat
用途描述输入文件/流的上下文信息描述输出文件/流的上下文信息
流信息包含输入文件/流的所有流信息包含输出文件/流的所有流信息
常见操作打开文件、读取数据写入文件头、写入数据、写入文件尾

5. 示例:完整的输入和输出处理流程

以下是一个完整的示例,展示如何使用 输入 AVFormatContext输出 AVFormatContext 处理音频文件。

5.1 示例代码

import Foundation
import FFmpeg

class FFmpegProcessor {
    static func processFile(inputFile: String, outputFile: String) {
        var inputContext: UnsafeMutablePointer<AVFormatContext>? = nil
        var outputContext: UnsafeMutablePointer<AVFormatContext>? = nil

        // 打开输入文件
        if avformat_open_input(&inputContext, inputFile, nil, nil) < 0 {
            print("Failed to open input file: \(inputFile)")
            return
        }

        // 创建输出文件
        if avformat_alloc_output_context2(&outputContext, nil, "mp4", outputFile) < 0 {
            print("Failed to create output file: \(outputFile)")
            avformat_close_input(&inputContext)
            return
        }

        // 添加流到输出文件
        for i in 0..<inputContext!.pointee.nb_streams {
            let inStream = inputContext!.pointee.streams[Int(i)]!
            let outStream = avformat_new_stream(outputContext, nil)
            if outStream == nil {
                print("Failed to allocate output stream")
                avformat_close_input(&inputContext)
                avformat_free_context(outputContext)
                return
            }

            // 复制流参数
            if avcodec_parameters_copy(outStream!.pointee.codecpar, inStream.pointee.codecpar) < 0 {
                print("Failed to copy codec parameters")
                avformat_close_input(&inputContext)
                avformat_free_context(outputContext)
                return
            }
            outStream!.pointee.codecpar.pointee.codec_tag = 0
        }

        // 打开输出文件
        if avio_open(&outputContext!.pointee.pb, outputFile, AVIO_FLAG_WRITE) < 0 {
            print("Failed to open output file")
            avformat_close_input(&inputContext)
            avformat_free_context(outputContext)
            return
        }

        // 写入文件头
        if avformat_write_header(outputContext, nil) < 0 {
            print("Failed to write header")
            avformat_close_input(&inputContext)
            avformat_free_context(outputContext)
            return
        }

        // 释放资源
        avformat_close_input(&inputContext)
        avformat_free_context(outputContext)

        print("Processing completed successfully")
    }
}

// 调用示例
FFmpegProcessor.processFile(inputFile: "input.mp4", outputFile: "output.mp4")

6. 总结

  • AVFormatContext 是通用的结构体,既可以用于输入,也可以用于输出。
  • 输入和输出的区别
    • 输入通过 iformatAVInputFormat)描述。
    • 输出通过 oformatAVOutputFormat)描述。
  • 创建方式
    • 输入:使用 avformat_open_input 自动分配和初始化。
    • 输出:使用 avformat_alloc_output_context2avformat_alloc_context 手动分配和初始化。

通过这种方式,FFmpeg 可以灵活地处理多媒体文件和流。

相关文章:

  • Node.js v16 版本安装
  • 排序(数据结构篇)
  • YOLOv12 ——基于卷积神经网络的快速推理速度与注意力机制带来的增强性能结合
  • 百度觉醒,李彦宏渴望光荣
  • 浅析 Redis 分片集群 Cluster 原理、手动搭建、动态伸缩集群、故障转移
  • 《Spring Boot + MySQL高性能应用实战:性能优化技巧与最佳实践》
  • CMake小结2(PICO为例)
  • 【目标检测旋转框xml2txt】rolabelimg标注的xml格式label转YOLO格式txt文件
  • 【Java项目】基于Spring Boot的旅游管理系统
  • Blueprint —— Events
  • vue3-07模拟vue3的响应式原理Proxy (代理对象)与Reflect (反射对象)
  • NNP_test_cpp
  • 深度强化学习落地调参技巧
  • 企业之IT安全管控概览和实践案例
  • Docker下ARM64架构的源码编译Qt5.15.1,并移植到开发板上
  • 新版本的idea用不习惯,怎么还原为之前版本的UI界面?idea界面还原,idea新版本ui设置
  • 一文了解Java中的虚拟线程新特性
  • linux内核驱动:I2C子系统笔记
  • Android 10.0 Settings中系统菜单去掉备份二级菜单
  • 数据安全_笔记系列09_人工智能(AI)与机器学习(ML)在数据安全中的深度应用
  • 李家超:明日起香港特区护照持有人可免签入境阿联酋
  • 陕西旱情实探:大型灌区农业供水有保障,大旱之年无旱象
  • 山东枣庄同一站点两名饿了么骑手先后猝死,当地热线:职能部门正调查
  • 有关部门负责人就《新时代的中国国家安全》白皮书答记者问
  • 马上评丨为护士减负,不妨破除论文“硬指标”
  • 何立峰:中方坚定支持多边主义和自由贸易,支持世界贸易组织在全球经济治理中发挥更大作用