• FFMS2 API 译文 [原创]


    FFMS2 又称 FFmpegSource2,参阅 https://github.com/FFMS/ffms2
    原文:https://github.com/FFMS/ffms2/blob/master/doc/ffms2-api.md
    译文:http://www.cnblogs.com/popapa/p/ffms2api.html
    采集日期:2018-3-17

    FFmpegSource2(FFMS2)是 Libav/FFmpeg 的封装库,并且增加了一些组件来解决 libavformat 格式(曾经)碰到的问题。有了它,你就可以简单地实现:“打开并解压多媒体文件就是了,实现细节不用我操心”,再也不必经常受困于苍白无力的 Libav/FFmpeg API 文档了。运气好的话,你也许还能精确定位到每一帧音视频数据。虽然 FFMS2 库是用 C++ 编写的,但暴露出来的 API 却是 C 格式的,可以直接加入并和纯 C 程序进行链接。

    源代码遵守 MIT 协议,可从 GitHub 获取。

    功能限制

    FFMS2 并不包含封装(mux)或编码功能,也无法让你对编码器进行完整的控制。FFMS2 不会将原始的压缩数据解封出来(demux),你只能获取到已解压的数据。因为在读取每帧音视频数据之前,FFMS2 必须对输入文件建立索引,所以它对实时播放也无法提供合适的解决方案。FFMS2 目前对字幕、附件数据、章节信息都不做处理。FFMS2 的音视频帧读取函数不是线程安全的,同一时刻只能运行一次。

    编译方法

    FFMS2 依赖于以下库:

    • FFmpeg

      • 建议的编译参数:--disable-debug --disable-muxers --disable-encoders --disable-filters --disable-hwaccels --disable-network --disable-devices --enable-runtime-cpudetect(如果你是在编译正式发布库,那么最好是开启 runtime-cpudetect;如果不关闭 disable-debug,dll 的尺寸将增大很多)。
    • zlib

    非 Windows 环境下的编译比较简单,如果 FFmpeg 和 zlib 已经安装在默认位置,那么只要按照正常步骤进行即可:./configure、make、make install

    Windows 环境下编译的注意事项

    在 Windows 下编译 FFMS2,会有很多选项。FFmpeg 和 FFMS2 可以都用 MinGW 编译;也可以让 FFmpeg 用 MinGW 编译,而 FFMS2 用 VC++ 编译;或者两者都用 VC++ 编译也行。标准的 Avisynth 2.5 插件体系要求 FFMS2 得用 VC++ 编译才行,而 Avisynth 的 C plugin 体系(支持 Avisynth 2.6)则要求使用 MinGW 编译(选用c_plugin源码分支)。

    如果两者都用 MinGW 编译,目前尚未发现什么问题。如果 FFMS2 用 MinGW 编译、 FFMS2 用 VC++ 编译,则在编译 FFmpeg 时需带上--extra-cflags="-D_SYSCRT"参数。如果你希望生成静态库,而非共享库(shared library),那就必须手工将已安装的头文件和库位置添加到 VC++ 的搜索路径中去(如果 32 位和64 位库都需要生成,请确保路径的正确性)。

    如果两者都用 VC++ 编译,请在 msys 中运行build-win-deps.sh,以生成所有的依赖资源,然后打开解决方案并开始编译。如果你用的是 Visual Studio 2013 之前的版本,为了能编译 FFmpeg,你的 msys 得带有 c99-to-c89

    快捷用法

    如果只想以最简单的方式利用 FFMS2 打开视频文件,不想了解细节,不用选择索引方式,不用报告进度,不用保存索引文件,不用读取关键帧、时间戳之类的信息,那么下面就是最简代码示例。

    #include <ffms.h>
    
    int main (...) {
      /* 初始化 FFMS 库*/
      FFMS_Init(0, 0);
    
      /* 建立索引。这里没有对音频轨建索引。 */
      char errmsg[1024];
      FFMS_ErrorInfo errinfo;
      errinfo.Buffer      = errmsg;
      errinfo.BufferSize  = sizeof(errmsg);
      errinfo.ErrorType   = FFMS_ERROR_SUCCESS;
      errinfo.SubType     = FFMS_ERROR_SUCCESS;
      const char *sourcefile = "somefilename";
      
      FFMS_Indexer *indexer = FFMS_CreateIndexer(sourcefile, &errinfo);
      if (indexer == NULL) {
        /* handle error (print errinfo.Buffer somewhere) */
      }
      
      FFMS_Index *index = FFMS_DoIndexing2(indexer, FFMS_IEH_ABORT, &errinfo);
      if (index == NULL) {
        /* 错误处理 */
      } 
    
      /* Retrieve the track number of the first video track */
      int trackno = FFMS_GetFirstTrackOfType(index, FFMS_TYPE_VIDEO, &errinfo);
      if (trackno < 0) {
        /* 没找到视频轨,这种致命错误必须处理 */
        /* 比如可以把错误显示出来 */
      }
    
      /* 现在已具备条件创建 VideoSource 对象了 */
      FFMS_VideoSource *videosource = FFMS_CreateVideoSource(sourcefile, trackno, index, 1, FFMS_SEEK_NORMAL, &errinfo);
      if (videosource == NULL) {
        /* 错误处理 */
      }
    
      /* 因为在 VideoSource 对象的创建过程中,index 已经复制了一份进去,
         现在 index 对象可以被销毁了 */
      FFMS_DestroyIndex(index);
    
      /* 读取视频属性信息。
         因为参数中没有带 errmsg,所以该函数不会失败。 */
      const FFMS_VideoProperties *videoprops = FFMS_GetVideoProperties(videosource);
    
      /* 现在可以好好利用这些视频属性信息,比如获取总帧数 */
      int num_frames = videoprops->NumFrames;
    
      /* 尝试读取第 1 帧,这很有必要。
         因为分辨率和色彩空间(colorspace)都包含在每帧的数据中,而非全局信息。 */
      const FFMS_Frame *propframe = FFMS_GetFrame(videosource, 0, &errinfo);
    
      /* 现在可以按需进行操作了,比如可以读取以下数据:
      propframe->EncodedWidth;  (当前帧的宽度,单位为像素)
      propframe->EncodedHeight;  (当前帧的高度,单位为像素)
      propframe->EncodedPixelFormat; (当前帧的真实色彩空间)
      */
    
      /* 现在可以修改输出帧的色彩空间,或者改变输出帧的大小。
         重点:这么做也是为了应对分辨率和色彩空间在中途发生变化的情况。
         可以通过查看 FFMS_Frame 的 Encoded* 属性获取到当前帧的原始分辨率。 */
    
      /* 关于图像格式/色彩空间的定义,请参阅 libavutil/pixfmt.h。
         在调用 GetPixFmt 获取图像格式时,只要把 pixfmt.h 里定义的常量去掉 PIX_FMT_ 前缀,并全部小写
         比如 PIX_FMT_YUV420P 即变为 “yuv420p”。*/
    
      /* 输出格式数组的最后一个成员应填入 -1,作为结束标志 */
      int pixfmts[2];
      pixfmts[0] = FFMS_GetPixFmt("bgra");
      pixfmts[1] = -1;
    
      if (FFMS_SetOutputFormatV2(videosource, pixfmts, propframe->EncodedWidth, propframe->EncodedHeight,
                                 FFMS_RESIZER_BICUBIC, &errinfo)) {
        /* 错误处理 */
      }
    
      /* 现在一切就绪,可以读取真正的视频帧数据了。 */
      int framenumber = 0;   /* 下次对当前视频对象调用 FFMS_GetFrame* 后,才有意义。 */
      const FFMS_Frame *curframe = FFMS_GetFrame(videosource, framenumber, &errinfo);
      if (curframe == NULL) {
        /* 错误处理 */
      }
      /* 处理当前帧 curframe */
    
      /* 释放资源 */
      FFMS_DestroyVideoSource(videosource);
    
      /* 清理 FFMS 库资源 */
      FFMS_Deinit();
    
      return 0;
    }
    

    够简单了吧!

    建立索引

    要用 FFMS2 打开多媒体文件,必须首先建立索引。这是为了能获取到关键帧位置、时间戳等信息,以便能实现逐帧检索。

    首先得用 FFMS_CreateIndexer 创建一个索引器(indexer)对象,参数是源文件名。调用 FFMS_GetNumTracksIFFMS_GetTrackTypeIFFMS_GetCodecNameI 函数,可以从 indexer 对象中可以查到一些信息,以便获悉文件中的轨道(track)数量及其类型。通过调用 FFMS_TrackIndexSettingsFFMS_TrackTypeIndexSettings、[FFMS_SetAudioNameCallback][SetAudioNameCallback] 和 FFMS_SetProgressCallback,可以对索引器进行一些配置,比如对哪些轨道需要建立索引。然后就可以调用 FFMS_DoIndexing2 建立索引了。如果想要中止建立索引的过程,可以调用 FFMS_CancelIndexing 函数。FFMS_DoIndexing2FFMS_CancelIndexing 函数都会销毁原有 indexer 对象并释放内存的。

    索引创建完成后,可以调用 FFMS_WriteIndex 将索引对象写入磁盘文件。当需要多次打开同一个文件时,这就很有用了,省得每次打开都得重建索引了。特别是在文件很大或者包含了很多音轨时,这能为你节省很多时间。

    调用 FFMS_ReadIndex 可以从已有索引文件中读取并创建索引对象。请注意,读取索引文件的 FFMS2 库,必须和写入索引文件的库版本相同。如果读写时的库版本不同,就会报索引不匹配的错误。可以调用 FFMS_IndexBelongsToFile 来校验一下,看看某个索引文件是否和视频文件匹配。

    色彩常量(color primaries、color transfer、color matrix)

    这些色彩常量定义,均与 ISO/IEC 23001-8_2013 第 7.1-7.3 节相同。为了避免重复,ffms.h 中未再作定义。如有必要,你可以自行复制一份,或者包含 FFmpeg 中的 libavutil/pixfmt.h 文件即可。

    API 函数参考

    大部分 API 函数都通过 ErrorInfo 参数报错,甚至是只通过它报错。有些函数目前尚不支持报错,但以后也将通过 ErrorInfo 报错。例如:

    char errmsg[1024];
    FFMS_ErrorInfo errinfo;
    errinfo.Buffer      = errmsg;
    errinfo.BufferSize  = sizeof(errmsg);
    errinfo.ErrorType   = FFMS_ERROR_SUCCESS;
    errinfo.SubType     = FFMS_ERROR_SUCCESS;
    
    const FFMS_Frame *frame = FFMS_GetFrame(vb, frameno, &errinfo);
    /* failure? */
    if (frame == NULL) {
      printf("failed to get frame number %d, error message: %s", frameno, errinfo.Buffer);
      /* ... */
    }
    

    你可自行决定为出错信息缓冲区申请多少内存,空间不够时错误信息会被截断。不过,1024 个字节肯定足矣。

    FFMS_Init - 初始化 FFMS 库

    void FFMS_Init(int Unused, int Unused2);
    

    初始化 FFMS 库。在调用任何 FFMS2 函数之前,本函数必须被调用一次。本函数线程安全,且只会运行一次。

    参数

    int Unused

    本参数已过期,仅留作保证 API//ABI 兼容性。请传入 0。

    int Unused2

    本参数也已过期,仅留作保证 API//ABI 兼容性。请传入 0。

    FFMS_Deinit - 清理 FFMS 库

    void FFMS_Deinit()
    

    清理 FFMS2 库占用的资源。当不再调用任何 FFMS2 函数之后,本函数必须被调用一次。本函数线程安全,且只会运行一次。

    FFMS_GetLogLevel - 读取 FFmpeg 报错级别

    int FFMS_GetLogLevel();
    

    读取 FFmpeg 的日志/报错级别(即向 STDERR 设备输出诊断信息的数量)。如需详细了解返回值的含义,最好是包含 FFmpeg 的 log.h 文件(#include <libavutil/log.h>),里面有所有常量的定义。也可以将相关的常量定义复制到你自己的代码中,当然这得 FFmpeg 开发组以后不会再做改动才行,可惜他们的任何修改都是无缘无故就会发生的。

    FFMS_SetLogLevel - 设置 FFmpeg 报错级别

    void FFMS_SetLogLevel(int Level);
    

    设置 FFmpeg 的日志/报错级别,详情请参阅 FFMS_GetLogLevel

    FFMS_CreateVideoSource - 创建视频源对象(VideoSource)

    FFMS_VideoSource *FFMS_CreateVideoSource(const char *SourceFile, int Track, FFMS_Index *Index, int Threads, int SeekMode, FFMS_ErrorInfo *ErrorInfo);
    

    用指定参数创建FFMS_VideoSource对象。FFMS_VideoSource对象代表着一个视频流,可以传给其他 API 函数用于读取视频帧和元数据(metadata )。该视频流必须是建立过索引的(参阅索引相关函数)。请注意在创建过程中,index 对象会被复制一份传入。因此一旦 VideoSource 对象创建成功,通常就可以立即将 index 对象销毁。index 对象中的所有信息,都可以从FFMS_VideoSource对象中获取得到。

    参数

    const char *SourceFile

    将要打开的视频源文件。相对路径或绝对路径均可。

    int Track

    要打开的视频轨编号,该编号也为解封器(demuxer)所用。关于如何判断视频轨编号的详细信息,请参阅 FFMS_GetNumTracksFFMS_GetTrackTypeFFMS_GetFirstTrackOfType 及其变体。

    FFMS_Index *Index

    指向 FFMS_Index 对象的指针,其中包含了对应视频轨的索引信息。

    int Threads

    要用来解码的线程数。如果小于 1时,线程数将采用 CPU 的核数。如果 FFmpeg 没有用多线程模式编译,则大于 1 的数值无效。

    int SeekMode

    合法参数值请参考 FFMS_SeekMode。本参数控制着检索(随机读写)的方式,也影响着帧的精度。最常用的是FFMS_SEEK_NORMAL

    FFMS_ErrorInfo *ErrorInfo

    参见错误处理

    返回值

    如果 FFMS_VideoSource 对象创建成功,则返回指向其的指针。如果创建失败,则设置 ErrorMsg 信息并返回 NULL。

    FFMS_CreateAudioSource - 创建音频源对象(AudioSource)

    FFMS_AudioSource *FFMS_CreateAudioSource(const char *SourceFile, int Track, FFMS_Index *Index, int DelayMode, FFMS_ErrorInfo *ErrorInfo);
    

    功能与 FFMS_CreateVideoSource 一致,创建音频轨对象。其他参数均与FFMS_CreateVideoSource相同,只是多了一个 DelayMode 参数。

    参数

    int DelayMode

    当音频轨的第一个 PTS 非 0 时,处理方式由本参数设定,也即决定着 FFMS 对音频轨延时的处理方式。合法的参数值为:

    • FFMS_DELAY_NO_SHIFT:不做调整,第一个解码出来的音频数据包(audio sample)就是输出的第一个数据包。这可能会导致音视频不同步。
    • FFMS_DELAY_TIME_ZERO:音频从时间 0 开始输出。可能会生成输出数据包(音量为 0),也可能不生成。

    此处译文存疑,原文为:Samples are created (with silence) or discarded so that sample 0 in the decoded audio starts at time zero.

    • FFMS_DELAY_FIRST_VIDEO_TRACK:音频从第 1 条视频轨的第 1 帧开始输出。可能会生成输出数据包(音量为 0),也可能不生成。这是大多数用户期望的结果,也是默认值。
    • 大于等于 0 的整数:效果视同FFMS_DELAY_FIRST_VIDEO_TRACK,但参数值将被视为视频轨编号,用作输出音频时的参照(如不是视频轨编号则音频源对象会创建失败)。

    FFMS_DestroyVideoSource、FFMS_DestroyAudioSource - 销毁视频源、音频源对象

    void FFMS_DestroyVideoSource(FFMS_VideoSource *V);
    void FFMS_DestroyAudioSource(FFMS_AudioSource *A);
    

    销毁FFMS_VideoSourceFFMS_AudioSource对象,释放由 FFMS_CreateVideoSourceFFMS_CreateAudioSource 申请的资源。

    FFMS_GetVideoProperties - 获取视频的属性信息

    const FFMS_VideoProperties *FFMS_GetVideoProperties(FFMS_VideoSource *V);
    

    从 FFMS_VideoSource 对象中读取该视频的属性信息,并保存到一个 FFMS_VideoProperties 结构中,返回结构的指针。

    FFMS_GetAudioProperties - 获取音频的属性信息

    const FFMS_AudioProperties *FFMS_GetAudioProperties(FFMS_AudioSource *A);
    

    功能与 FFMS_GetVideoProperties 一致,只是读取的对象是FFMS_AudioSource。请参阅FFMS_AudioProperties

    FFMS_GetFrame - 读取指定视频帧

    const FFMS_Frame *FFMS_GetFrame(FFMS_VideoSource *V, int n, FFMS_ErrorInfo *ErrorInfo);
    

    从指定视频流中读取并解码一个视频帧,并保存到一个FFMS_Frame结构中,视频流由FFMS_VideoSource对象指定。如果要设置该帧的色彩空间和分辨率,可以先调用 FFMS_SetOutputFormatV2 进行设置。请注意,本函数非线程安全(同一时刻只能从该FFMS_VideoSource对象中读取 1 帧),返回的FFMS_Frame指针是常量指针(const pointer)。

    参数

    FFMS_VideoSource *V

    指向FFMS_VideoSource对象的指针,即需要从中读取帧数据的视频流。

    int n

    要读取的视频帧编号。编号从 0 开始,第一帧的编号为 0(不是 1),最后一帧的编号是FFMS_VideoProperties->NumFrames减去 1。如果帧编号超过视频流的总帧数,或者小于起始帧编号(即为负值),那会导致不可预测的后果。

    FFMS_ErrorInfo *ErrorInfo

    参见错误处理

    返回值

    如果读取成功则返回指向FFMS_Frame的指针,如果失败则设置ErrorMsg并返回 NULL。

    返回的数据帧由参数给出的FFMS_VideoSource对象负责管理。如果该视频源对象被销毁,或者从该视频源读取了其他帧,或者输入输出格式发生变化,那么帧数据才会失效。否则帧数据会一直保持有效。请注意,虽然多次调用FFMS_GetFrame时多半会返回同一个指针,但直接将其作为输出帧是不够安全的,因为有时也会发生重新分配内存的情况。

    FFMS_GetFrameByTime - 读取指定时刻的视频帧

    const FFMS_Frame *FFMS_GetFrameByTime(FFMS_VideoSource *V, double Time, FFMS_ErrorInfo *ErrorInfo);
    

    功能与 FFMS_GetFrame 一致,只是参数不是帧编号,而是单位为秒的时刻。并且返回与给定时刻最为接近的视频帧。如果你实在是懒得自己建立帧号和时刻之间的映射关系,本函数正是为你准备的。

    FFMS_GetAudio - 解码几个音频数据包

    int FFMS_GetAudio(FFMS_AudioSource *A, void *Buf, int64_t Start, int64_t Count, FFMS_ErrorInfo *ErrorInfo);
    

    从指定音频流中解码一定数量的数据包,并保存到给定的缓冲区中,音频流由FFMS_AudioSource对象指定。请注意,本函数非线程安全,同一时刻只能向同一FFMS_AudioSource对象发起一个解码请求。

    参数

    FFMS_AudioSource *A

    指向FFMS_AudioSource对象的指针,即要从中读取数据的音频流。

    void *Buf

    缓冲区指针,用于存放解码后的音频数据。你必须得自行管理缓冲区内存的申请和释放,因此最好是先检查一下 FFMS_AudioProperties,获取采样格式、声道数、声道分布等信息,然后再来确定需要申请多大的缓冲区空间。显然,缓冲区所需内存的计算公式即为:num_bytes = bytes_per_sample * num_channels * num_samples

    int64_t Start, int64_t Count

    需要解码的音频数据范围。参数Count指定了输出数据包的数量,参数Start指定了起始位置(含)。正如视频帧编号一样,音频数据包的编号也是从 0 开始,最后一个包的编号则为FFMS_AudioProperties->NumSamples减去 1。如果指定的范围超过了该音频流最大的音频包编号,或者小于起始编号,那会导致不可预测的后果。

    FFMS_ErrorInfo *ErrorInfo

    参阅错误处理

    返回值

    如果成功则返回 0。如果失败则设置 'ErrorMsg`并返回非 0。

    FFMS_SetOutputFormatV2 - 设置视频帧的输出格式

    int FFMS_SetOutputFormatV2(FFMS_VideoSource *V, int *TargetFormats, int Width, int Height, int Resizer, FFMS_ErrorInfo *ErrorInfo);
    

    设置输出视频帧的色彩空间和大小,视频源由FFMS_VideoSource给出。设置完成后,后续对 FFMS_GetFrameFFMS_GetFrameByTime 的调用结果都会收到影响,直至下一次 FFMS_SetOutputFormatV2FFMS_ResetOutputFormatV 调用。你可以随时对输出格式做出调整,不需要重新初始化FFMS_VideoSource对象,也不需要做其他任何操作。你要愿意的话,甚至可用本函数将视频转成灰度图像(黑白)。如果参数中给出的色彩空间格式(pixelformat)数量超过 1 种,那在之后读取帧数据时,应该检查一下FFMS_Frame的属性信息,查看一下当前选中的是哪一种格式。切记每读一帧都要检查一下,不然结果会一团糟的。本函数自 2.16.3.0 版本开始引入,取代了FFMS_SetOutputFormatV

    参数

    FFMS_VideoSource *V

    指向FFMS_VideoSource对象的指针,即要改变输出格式的视频流。

    int *TargetFormats

    输出色彩空间。数组的最后一个元素应为 -1。函数会与当前帧的源色彩空间进行对比,自动选择其中转换损失最小的那一种,作为当前选中格式。如果要了解每个整数值对应的色彩空间,请参阅 FFMS_GetPixFmt

    示例:

    int targetformats[3];
    targetformats[0] = pixfmt1;
    targetformats[1] = pixfmt2;
    targetformats[2] = -1;
    int Width, int Height
    

    输出的图像大小单位为像素数。如果你不需要改变图像的大小,只要传入视频原始大小即可。传入非法的图像大小(比如 0 或负数),会导致不可预知的结果。

    int Resizer

    设定图像缩放算法,这里的整数值由枚举FFMS_Resizers定义。即便你不需要对图像进行缩放,也必须指定一个值,因为视频流的分辨率可能会中途(mid-stream)改变,这时无论如何都会用到本参数。如果某一帧用了不同的分辨率进行解码,你只会得知分辨率发生了变化,却无法干预。当需要缩放色度平面(chroma planes)时,也会用到本参数。

    FFMS_ErrorInfo *ErrorInfo

    参见错误处理

    返回值

    如果设置成功则返回 0,失败则设置ErrorMsg并返回非 0 值。

    FFMS_ResetOutputFormatV - 重置视频输出格式

    void FFMS_ResetOutputFormatV(FFMS_VideoSource *V);
    

    重置输出格式,使得后续不做任何图像转换,视频源由FFMS_VideoSource对象给出。请注意,执行本函数的后果很可能无法预料,特别是当视频流分辨率中途发生变化时。在调用本函数之后,最好是能继续调用一下 FFMS_GetFrame,检查一下各个视频参数,看看是否如愿进行了重置。

    FFMS_SetInputFormatV - 覆盖源视频格式

    int FFMS_SetInputFormatV(FFMS_VideoSource *V, int ColorSpace, int ColorRange, int PixelFormat, FFMS_ErrorInfo *ErrorInfo);
    

    覆盖已传给 SWScale 的原色彩空间参数,并改变视频帧的大小。在下一次调用 FFMS_SetInputFormatVFFMS_ResetInputFormatV 之前,FFMS_GetFrameFFMS_GetFrameByTime 的结果都持续受到影响。你可以随时改变输入格式,不必重新初始化FFMS_VideoSource对象或做其他任何操作。本函数主要是供设错 YUV 格式参数的程序使用的,使其能与 RGB 格式进行相互转换。不过当视频文件的色彩空间参数不正确时,本函数也会相当有用。函数不会对传入的参数进行正确性校验,如果想利用本函数让 FFMS2 用 RGB 格式打开一个 YUV 文件,恐怕不会奏效。仅当输出格式是用 FFMS_SetOutputFormatV2 设置时,本函数才会生效。自 2.17.1.0 版本开始引入。

    参数

    FFMS_VideoSource *V

    指向FFMS_VideoSource对象的指针,即需要改变输出参数的视频流。

    int ColorSpace

    期望的输入色彩空间值,如为FFMS_CS_UNSPECIFIED则表示不作改动。参见 FFMS_ColorSpaces

    int ColorRange

    期望的输入色域值,如为FFMS_CS_UNSPECIFIED则表示不作改动。参见 FFMS_ColorRanges

    int PixelFormat

    期望的输入像素格式,参见 FFMS_GetPixFmtFFMS_GetPixFmt("")则表示像素格式不作改动。

    FFMS_ErrorInfo *ErrorInfo

    参见错误处理

    返回值

    如果设置成功则返回 0,失败则设置ErrorMsg并返回非 0 值。

    FFMS_ResetInputFormatV - 重置视频输入格式

    void FFMS_ResetInputFormatV(FFMS_VideoSource *V);
    

    将视频输入格式重置为源文件给出的值,视频源由FFMS_VideoSource对象给出。

    FFMS_DestroyIndex - 销毁索引对象

    void FFMS_DestroyFFMS_Index(FFMS_Index *Index);
    

    销毁给出的FFMS_Index对象,并释放其申请的内存。

    FFMS_GetErrorHandling - 获取创建索引时的错误处理模式

    int FFMS_GetErrorHandling(FFMS_Index *Index);
    

    返回当时传给 FFMS_DoIndexing2 的 ErrorHandling 参数。

    FFMS_GetFirstTrackOfType - 获取第一条指定类型的轨号

    int FFMS_GetFirstTrackOfType(FFMS_Index *Index, int TrackType, FFMS_ErrorInfo *ErrorInfo);
    

    检索第一条符合指定类型的轨道,并返回其编号。轨道类型由 FFMS_TrackType 定义,索引由 FFMS_Index 定义。该编号可用于 FFMS_CreateVideoSourceFFMS_CreateAudioSource 等 API 函数。

    参数

    FFMS_Index *Index

    指向FFMS_Index对象的指针,代表要检索的媒体文件。

    int TrackType

    指定要检索的轨道类型。参见 FFMS_TrackType

    FFMS_ErrorInfo *ErrorInfo

    参见错误处理

    返回值

    成功时返回轨道编号(大于等于 0 的整数值)。失败则设置ErrorMsg并返回负数(即未发现指定类型的轨道)。

    FFMS_GetFirstIndexedTrackOfType - 获取已索引的第一条指定类型的轨号

    int FFMS_GetFirstIndexedTrackOfType(FFMS_Index *Index, int TrackType, FFMS_ErrorInfo *ErrorInfo);
    

    功能与 FFMS_GetFirstTrackOfType 一致,只是会忽略未建索引的轨道。

    FFMS_GetNumTracks - 获取索引内的音视频轨总数

    int FFMS_GetNumTracks(FFMS_Index *Index);
    

    返回媒体文件中的音视频轨总数,文件由FFMS_Index类型的索引表示。

    FFMS_GetNumTracksI - 获取索引器中的音视频轨总数

    int FFMS_GetNumTracksI(FFMS_Indexer *Indexer);
    

    返回媒体文件中的音视频轨总数,文件由FFMS_Indexer类型的索引器表示。也就是说,功能和 FFMS_GetNumTracks 一致,只是不需要首先对整个文件建立索引了。

    FFMS_GetTrackType - 获取轨道的类型

    int FFMS_GetTrackType(FFMS_Track *T);
    

    返回指定轨道的类型,返回的整数值由 FFMS_TrackType 定义,轨道由FFMS_Track对象给出。

    FFMS_GetTrackTypeI - 获取轨道的类型

    int FFMS_GetTrackTypeI(FFMS_Indexer *Indexer, int Track);
    

    返回轨道的类型,返回的整数值由 FFMS_TrackType 定义。FFMS_Indexer类型的索引器参数给出了媒体文件,参数Track则表示其中的轨道编号。也就是说,本函数功能和 FFMS_GetTrackType 一致,只是不需要首先对整个文件建立索引了。如果媒体文件已经建过索引了,那就请换用 FFMS_GetTrackType 吧。因为索引创建完成后,FFMS_Indexer对象就会被销毁。请注意,如果参数中给出了非法的轨道号,执行结果将不可预料。

    FFMS_GetCodecNameI - 获取轨道使用的编码器名称

    const char *FFMS_GetCodecNameI(FFMS_Indexer *Indexer, int Track);
    

    返回给定音视频轨使用的编码器名称(即 FFmpeg 定义的“long name”)。FFMS_Indexer对象给出了媒体文件,参数Track则表示其中的轨道编号。假如你想弹出菜单让用户选择需要创建索引的轨道,那么本函数就十分有用了。请注意,如果参数中给出了非法的轨道号,执行结果将不可预料。

    FFMS_GetFormatNameI - 由索引器获取容器格式名

    const char *FFMS_GetFormatNameI(FFMS_Indexer *Indexer);
    

    返回媒体文件所用的容器名称(即 FFmpeg 定义的“long name”)。媒体文件由FFMS_Indexer对象给出。

    FFMS_GetNumFrames - 获取指定轨道的总帧数

    int FFMS_GetNumFrames(FFMS_Track *T);
    

    返回指定轨道的总帧数,轨道由FFMS_Track型参数给出。对于视频轨而言,即总视频帧数,应该颇有用处。对于音频轨而言,则为数据包总数,这几乎毫无用处。因为所有的 API 函数都没用到音频总数据包数。返回 0 表示该轨道尚未建立索引。

    FFMS_GetFrameInfo - 获取帧信息

    const FFMS_FrameInfo *FFMS_GetFrameInfo(FFMS_Track *T, int Frame);
    

    由索引信息中获取指定帧(由帧号给定)的详细信息,结果以FFMS_FrameInfo结构的形式给出,FFMS_Track型的参数指定了已经索引的视频轨。如果FFMS_Track参数给出的不是视频轨,调用结果将不可预料。

    参数

    FFMS_Track *T

    指向FFMS_Track对象的指针,即该帧所在的视频轨。

    int Frame

    需读取信息的帧编号。关于帧号的说明,请参阅 FFMS_GetFrame。如果帧号小于起始帧,或者大于视频轨的总帧数,将会导致不可预料的结果,因此请勿尝试。

    FFMS_ErrorInfo *ErrorInfo

    参见错误处理

    返回值

    成功则返回FFMS_FrameInfo结构指针。失败则设置ErrorMsg并返回 NULL。

    FFMS_GetTrackFromIndex - 由索引中获取轨道信息

    FFMS_Track *FFMS_GetTrackFromIndex(FFMS_Index *Index, int Track);
    

    FFMS_Index对象中按轨号读取轨道信息,并保存到FFMS_Track对象中返回其指针。当你不愿或不能用FFMS_CreateVideoSourceFFMS_CreateAudioSource打开某个轨道时,即可使用本函数。如果已经用FFMS_CreateVideoSourceFFMS_CreateAudioSource打开过了该轨道,那么更可靠的方式是用FFMS_GetTrackFromVideoFFMS_GetTrackFromAudio。请注意,如果给出非法或不存在的轨道编号,将会导致不可预料的后果,一般是会报内存访问冲突(access violation)的错误。还请注意一点,返回的FFMS_Track仅在其所属的FFMS_Index生命周期内才有效。

    参数

    FFMS_Index *Index

    指向FFMS_Index对象的指针,其中包含了必要的轨道信息。

    int Track

    轨道编号,对应的解封器也会认到相同的编号(参阅 FFMS_GetNumTracksFFMS_GetFirstTrackOfType 及其变体函数)。

    FFMS_ErrorInfo *ErrorInfo

    参见错误处理

    返回值

    成功则返回FFMS_Track指针。请注意,即使该轨道未建立索引也不会报错,只是会返回空的FFMS_Track。请使用 FFMS_GetNumFrames 查看总帧数是否大于 0,以便了解返回对象是否包含索引之后的数据。

    FFMS_GetTrackFromVideo, FFMS_GetTrackFromAudio - 获取音频或视频轨信息

    FFMS_Track *FFMS_GetTrackFromVideo(FFMS_VideoSource *V);
    FFMS_Track *FFMS_GetTrackFromAudio(FFMS_AudioSource *A);
    

    FFMS_VideoSourceFFMS_AudioSource对象获取轨道的基本信息,返回FFMS_Track对象指针。一般情况下,这两个函数要比 FFMS_GetTrackFromIndex 更为可靠。因为在给出了不存在的轨道编号时,本函数不会引发访问冲突错误,而是返回不包含索引信息的FFMS_Track。如果索引对象已被销毁,本函数将返回失效的对象。请注意,返回的FFMS_Track对象仅在其所属的FFMS_VideoSourceFFMS_AudioSource生命周期内才有效。

    FFMS_GetTimeBase - 获取视频轨的时基信息(time base)

    const FFMS_TrackTimeBase *FFMS_GetTimeBase(FFMS_Track *T);
    

    查找视频轨的基本时间单位,并保存在FFMS_TrackTimeBase结构中返回其指针,视频轨由FFMS_Track给出。请注意,本函数仅对视频轨有效。

    FFMS_WriteTimecodes - 将视频轨的时间码(timecode)写入磁盘文件

    int FFMS_WriteTimecodes(FFMS_Track *T, const char *TimecodeFile, FFMS_ErrorInfo *ErrorInfo);
    

    将视频轨的 Matroska v2 时间码(timecode)写入指定文件,视频轨由FFMS_Track的参数给出。本函数仅对视频轨有效。

    参数

    FFMS_Track *T

    指向FFMS_Track对象的指针,即时间码所属的视频轨。

    const char *TimecodeFile

    文件名。相对路径或绝对路径均可。如果文件已存在,则会清空并覆盖。

    FFMS_ErrorInfo *ErrorInfo

    参见错误处理

    返回值

    成功则返回 0。失败则设置ErrorMsg并返回非 0。

    FFMS_CreateIndexer - 对媒体文件创建索引器对象

    FFMS_Indexer *FFMS_CreateIndexer(const char *SourceFile, FFMS_ErrorInfo *ErrorInfo);
    

    对媒体文件创建FFMS_Indexer对象并返回其指针,文件名由SourceFile给出。关于如何使用索引器的详细信息,请参阅创建索引。本函数基本就是FFMS_CreateIndexerWithDemuxer(SourceFile, FFMS_SOURCE_DEFAULT, ErrorInfo)的简化版。

    返回值

    成功时返回指向FFMS_Indexer的指针。失败则设置ErrorMsg并返回 NULL。

    FFMS_DoIndexing2 - 对由索引器指定的媒体文件建立索引

    FFMS_Index *FFMS_DoIndexing2(FFMS_Indexer *Indexer, int ErrorHandling, FFMS_ErrorInfo *ErrorInfo);
    

    对媒体文件建立索引,返回FFMS_Index对象,文件由传入的索引器给出。关于建立索引的详细信息,请参阅建立索引一节。请注意,无论索引是否成功建立,本函数均会销毁原FFMS_Indexer对象并释放由 FFMS_CreateIndexer 分配的内存。

    参数

    FFMS_Indexer *Indexer

    需要建立索引的索引器。索引器对象由 FFMS_CreateIndexer 创建,并可由 FFMS_TrackIndexSettingsFFMS_TrackTypeIndexSettingsFFMS_SetAudioNameCallbackSetAudioNameCallbackFFMS_SetProgressCallback 进行参数配置。

    int ErrorHandling

    决定了音频解码时的错误处理方式。此处可填入的参数值,参见 FFMS_IndexErrorHandling,最佳默认值是FFMS_IEH_STOP_TRACK。如果音轨启用了转储(dump)模式,那么解码出错后必定会导致索引创建失败,本参数将会失效。

    FFMS_ErrorInfo *ErrorInfo

    参见错误处理

    返回值

    成功时返回创建完成的FFMS_Index指针。失败则设置ErrorMsg并返回 NULL。

    FFMS_TrackIndexSettings - 对轨道启用或禁用索引

    void FFMS_TrackIndexSettings(FFMS_Indexer *Indexer, int Track, int Index, int Dump);
    

    启用或禁用索引。对于音轨而言,则是启用或禁用索引创建过程中的已解码数据转储。

    参数

    FFMS_Indexer *Indexer

    索引器。

    int Track

    轨号。

    int Index

    非 0 表示启用索引,0 则表示禁用索引。默认情况下,视频轨均启用索引,而所有音频轨则禁用。

    int Dump

    目前未启用。

    默认情况下,不会对任何轨道进行转储。

    FFMS_TrackTypeIndexSettings - 对某一类轨道全部启用或禁用索引

    void FFMS_TrackTypeIndexSettings(FFMS_Indexer *Indexer, int TrackType, int Index, int Dump);
    

    功能和 FFMS_TrackIndexSettings 类似,只是一次对一类轨道做全体配置。

    FFMS_SetProgressCallback - 设置更新索引进度用的回调函数
    
    void FFMS_SetProgressCallback(FFMS_Indexer *Indexer, TIndexCallback IC, void *ICPrivate);
    

    在索引创建过程中,FFMS2 会定时调用这里给定的进度回调函数,以报告索引创建进度,你还可以有机会中止索引的创建过程。

    回调函数应为以下格式:

    int FFMS_CC FunctionName(int64_t Current, int64_t Total, void *ICPrivate);
    

    回调函数的参数说明如下:

    • int64_t Currentint64_t Total - 索引的进度指示(已完成帧数/总帧数)。
    • void *Private - 与传给FFMS_SetProgressCallbackPrivate参数为同一个指针,用途由你决定。比如在图形用户界面程序中,可用于传入进度条对象,以便在调用索引函数时更新进度。

    回调函数返回 0 表示期望继续进行索引,返回非 0 则表示要取消索引过程。返回非 0 将会导致 FFMS_DoIndexing2 失败,失败原因是“用户取消索引的创建”(indexing cancelled by user)。

    FFMS_CancelIndexing - 销毁索引器对象

    void FFMS_CancelIndexing(FFMS_Indexer *Indexer);
    

    销毁给定的FFMS_Indexer对象,并释放原来由 FFMS_CreateIndexer 分配的内存。

    FFMS_ReadIndex - 从磁盘读取索引文件

    FFMS_Index *FFMS_ReadIndex(const char *IndexFile, FFMS_ErrorInfo *ErrorInfo);
    

    从文件中读取索引信息,文件名由IndexFile给出,绝对路径或相对路径均可。

    成功则返回FFMS_Index,失败则设置ErrorMsg并返回 NULL。

    FFMS_ReadIndexFromBuffer - 从用户缓冲区中读取索引

    FFMS_Index *FFMS_ReadIndexFromBuffer(const uint8_t *Buffer, size_t Size, FFMS_ErrorInfo *ErrorInfo);
    

    从用户自定义缓冲区中读取索引数据,缓冲区由Buffer给出,读取长度为Size

    成功则返回FFMS_Index,失败则设置ErrorMsg并返回 NULL。

    FFMS_IndexBelongsToFile - 检测索引和媒体文件是否匹配

    int FFMS_IndexBelongsToFile(FFMS_Index *Index, const char *SourceFile, FFMS_ErrorInfo *ErrorInfo);
    

    检测FFMS_Index是否为SourceFile文件的索引,虽然采用的是启发式的猜测,但可信度很高。可用于判断 FFMS_ReadIndex 读取的索引对象与某个媒体文件是否相关。否则只有两种方法能判断索引文件和媒体文件是否匹配,一是完全信任用户的操作,二是比较文件名,两者都不大可靠。

    参数

    FFMS_Index *Index

    索引对象。

    const char *SourceFile

    媒体文件。

    返回值

    如果索引和媒体文件匹配,返回 0。否则设置ErrorMsg并返回非 0。

    FFMS_WriteIndex - 将索引对象写入磁盘

    int FFMS_WriteIndex(const char *IndexFile, FFMS_Index *TrackIndices, FFMS_ErrorInfo *ErrorInfo);
    

    将索引信息写入索引文件,索引对象为FFMS_Index类型,索引文件名由IndexFile给出。文件名可以是绝对路径或相对路径,如果文件已存在则会被清空并覆盖。

    成功时返回 0,失败则设置ErrorMsg并返回非 0。

    FFMS_WriteIndexToBuffer - 将索引对象写入内存

    int FFMS_WriteIndexToBuffer(uint8_t **BufferPtr, size_t *Size, FFMS_Index *Index, FFMS_ErrorInfo *ErrorInfo)
    

    将索引信息写入内存缓存区,并将BufferPtr指向该缓冲区。索引对象为FFMS_Index类型,参数Size为返回的缓冲区大小。该缓冲区必须通过 FFMS_FreeIndexBuffer 进行释放。

    成功时返回 0,失败则设置ErrorMsg并返回非 0。

    FFMS_FreeIndexBuffer - 释放由FFMS_WriteIndexToBuffer分配的缓冲区内存

    void FFMS_FreeIndexBuffer(uint8_t **BufferPtr)
    

    释放BufferPtr指向的缓冲区内存,并将其设为 NULL。

    FFMS_GetPixFmt - 由色彩空间名称获取其编号

    int FFMS_GetPixFmt(const char *Name);
    

    将色彩空间/像素格式的名称转换为对应的整数常量值,以便用于 FFMS_SetOutputFormatV2,详见其函数说明。有了本函数,你就不必每次写程序时都去包含 FFmpeg 的相关头文件了。关于色彩空间名称的完整清单,请参阅libavutil/pixfmt.h文件。在给出名称时,需要去除PIX_FMT_前缀,并全部转换为小写字母。比如PIX_FMT_YUV420P就写为yuv420p。因为本函数可以保证获取到正确的常量定义,也就是与编译 FFMS 时的 FFmpeg 版本一致,所以强烈建议你使用本函数,请不要再直接包含pixfmt.h文件了。

    参数

    const char *Name

    色彩空间/像素格式的名称,应为空字符结尾的 ASCII 字符串。

    返回值

    成功时返回对应的整数常量。失败(未找到匹配的色彩空间)则返回PIX_FMT_NONE对应的编号(即 -1)。但请注意,执行FFMS_GetPixFmt("none")也可返回PIX_FMT_NONE,严格来说这并不表示调用失败。

    FFMS_GetVersion - 返回 FFMS_VERSION 常量

    int FFMS_GetVersion();
    

    返回ffms.h中定义的FFMS_VERSION整数常量。

    数据结构

    常用的公共数据结构有以下几种。

    FFMS_Frame

    typedef struct {
        const uint8_t *Data[4];
        int Linesize[4];
        int EncodedWidth;
        int EncodedHeight;
        int EncodedPixelFormat;
        int ScaledWidth;
        int ScaledHeight;
        int ConvertedPixelFormat;
        int KeyFrame;
        int RepeatPict;
        int InterlacedFrame;
        int TopFieldFirst;
        char PictType;
        int ColorSpace;
        int ColorRange;
        int ColorPrimaries;
        int TransferCharateristics;
        int ChromaLocation;
        int HasMasteringDisplayPrimaries;
        double MasteringDisplayPrimariesX[3];
        double MasteringDisplayPrimariesY[3];
        double MasteringDisplayWhitePointX;
        double MasteringDisplayWhitePointY;
        int HasMasteringDisplayLuminance;
        double MasteringDisplayMinLuminance;
        double MasteringDisplayMaxLuminance;
        int HasContentLightLevel;
        unsigned int ContentLightLevelMax;
        unsigned int ContentLightLevelAverage;
    } FFMS_Frame;
    

    视频帧结构。字段说明如下:

    • uint8_t *Data[4] - 指向各图像平面数据的指针数组(存放实际像素数据)。平面(planar)格式使用一个以上的平面(plane),比如 YV12 格式的 Y、U、V 分量各自占用了一个平面。打包(packed)格式则只用到了第一个平面,比如各种的 RGB32 格式。如果要确认一下第 i 个平面是否包含数据,判断方法可以是FFMS_Frame->Linesize[i] != 0
    • int Linesize[4] - 整数数组,存储着 4 个图像平面的扫描线(scan line)长度,单位为字节数。换句话说,就是每个图像平面内的数据分隔单位(pitch)。通常,i 平面内的数据总长为FFMS_Frame->Linesize[i] * FFMS_VideoProperties->Height,但是请务必小心,某些格式(尤其是 YV12)带有纵向色度分量,U/V 平面的高度可能会和主平面不一样。本字段内的数据还有可能是负值,表示图像在内存中是上下倒置存放的,Data实际上指向的是最底下一行的数据。通常不需要操心上述情况,只要正操操作一般就没有问题。
    • int EncodedWidthint EncodedHeight - 原始分辨率(单位为像素),也即压缩文件里保存的未经缩放的分辨率。请注意,一个数据流不一定所有帧都是相同的分辨率。
    • int EncodedPixelFormat - 原始像素格式,即压缩文件里保存的编码格式。
    • int ScaledWidthint ScaledHeight - 输出分辨率(单位为像素),即Data字段内图像数据的实际分辨率。如果未经缩放则设为 -1。
    • int ConvertedPixelFormat - 输出像素格式,即Data字段内图像数据的实际格式。- int KeyFrame - 如果本帧是关键帧,则为非 0。否则为零。
    • int RepeatPict - RFF 参数,也即显示时间应为1+RepeatPict个时基单位。这里的时基单位是 RFF 专用的,在FFMS_VideoProperties->RFFDenominatorFFMS_VideoProperties->RFFNumerator中给出。请注意,如果最终采用了本参数作为时间基准,那就得放弃通常的时间计算规则(由FFMS_TrackTimeBase和帧PTS得出),因为这两个参数与 RFF 参数基本是不兼容的。
    • int InterlacedFrame - 非 0 表示本帧是隔行编码的,否则为 0。
    • int TopFieldFirst - 非 0 表示本帧是奇数场优先,为 0 则表示偶数场优先。仅当InterlacedFrame字段非 0 时,本字段才有意义。
    • char PictType - 以单个字符表示的帧压缩类型(I/B/P 等)。关于各种字母的不同含义,请参阅常量和预处理标志一节。
    • int ColorSpace - YUV 色彩参数。定义与 MPEG-2 规范一致,参见 FFMS_ColorSpaces 枚举。
    • int ColorRange - 亮度范围。参见 FFMS_ColorRanges 枚举定义。
    • int ColorPrimaries - 色域值。
    • int TransferCharateristics - 转换特性。
    • int ChromaLocation - 色度位置,由 FFMS_ChromaLocations 定义。
    • int HasMasteringDisplayPrimaries - 非 0 则会设置以下 4 个字段。
    • double MasteringDisplayPrimariesX[3] - 主平面的 RGB 色彩坐标(X 轴)。
    • double MasteringDisplayPrimariesY[3] - 主平面的 RGB 色彩坐标(Y 轴)
    • double MasteringDisplayWhitePointX - 主平面的白场坐标(X 轴)。
    • double MasteringDisplayWhitePointY - 主平面的白场坐标(Y 轴)。
    • int HasMasteringDisplayLuminance - 如果非 0 则会设置以下 2 个字段。
    • double MasteringDisplayMinLuminance - 主平面的最小亮度(单位 cd/m^2)。
    • double MasteringDisplayMaxLuminance - 主平面的最大亮度(单位 cd/m^2)。
    • int HasContentLightLevel - 如果非 0 则会设置以下 2 个字段。
    • unsigned int ContentLightLevelMax - 最大亮度(单位 cd/m^2)。
    • unsigned int ContentLightLevelAverage - 平均亮度(单位 cd/m^2)。

    FFMS_TrackTimeBase

    typedef struct {
        int64_t Num;
        int64_t Den;
    } FFMS_TrackTimeBase;
    

    基本时间单位,这是一个比值(rational number),Num是分子,Den是分母。请注意,对于某些 CFR 视频轨而言,本值有时会和1/帧率相同,但实际上与帧率没什么太大关系,千万别以为帧率和本值有关。

    FFMS_FrameInfo

    typedef struct {
        int64_t PTS;
        int RepeatPict;
        int KeyFrame;
    } FFMS_FrameInfo;
    

    视频帧的基本元信息。字段说明如下:

    • int64_t PTS - 解码后的时间戳(timestamp)。如果要将本时间戳转换为实际的时钟时间,可以采用以下公式:int64_t timestamp = (int64_t)((FFMS_FrameInfo->PTS * - FFMS_TrackTimeBase->Num) / (double)FFMS_TrackTimeBase->Den)
    • int RepeatPict - RFF 标志。含义与 FFMS_Frame 中的相同。
    • int KeyFrame - 非 0 表示为关键帧,否则为 0。

    FFMS_VideoProperties

    typedef struct {
        int FPSDenominator;
        int FPSNumerator;
        int RFFDenominator;
        int RFFNumerator;
        int NumFrames;
        int SARNum;
        int SARDen;
        int CropTop;
        int CropBottom;
        int CropLeft;
        int CropRight;
        int TopFieldFirst;
        int ColorSpace; // [已过时]
        int ColorRange; // [已过时]
        double FirstTime;
        double LastTime;
        int Rotation;
        int Stereo3DType;
        int Stereo3DFlags;
        double LastEndTime;
        int HasMasteringDisplayPrimaries;
        double MasteringDisplayPrimariesX[3];
        double MasteringDisplayPrimariesY[3];
        double MasteringDisplayWhitePointX;
        double MasteringDisplayWhitePointY;
        int HasMasteringDisplayLuminance;
        double MasteringDisplayMinLuminance;
        double MasteringDisplayMaxLuminance;
        int HasContentLightLevel;
        unsigned int ContentLightLevelMax;
        unsigned int ContentLightLevelAverage;
    } FFMS_VideoProperties;
    

    视频轨的基本信息(元数据)。字段说明如下:

    • int FPSDenominator; int FPSNumerator; - 标称(nominal)帧率,以比值的形式给出。对于 Matroska 格式的文件而言,本值根据平均帧率得出,其他格式则均由第一帧的时长而得。请勿用本值来估算每帧的实际时间戳,这只是看上去很美,但会让你无法对可变帧率做出正确的处理。现实很残酷,本值只能在显示基本信息时用用,恐怕只有对 AVI 这种古老的封装格式才会有点准确。一般情况下,本值没什么实用价值,请用FFMS_FrameInfo->PTS来单独生成每帧的时间戳。
    • int RFFDenominator; int RFFNumerator; - RFF 时间戳,以比值的形式给出。详情请参阅 FFMS_Frame 中的RepeatPict字段。
    • int NumFrames - 视频轨的总帧数。
    • int SARNum; int SARDen; - 视频帧的长宽比,为比值格式,SARNum是分子,SARDen是分母。请注意,尽管你可以完全忽略本值,但如果想正常显示失真的源画面,就用得上了本值了。换句话说,当用户不想参照画面的原始比例时(比如编码时),你可以选择忽略本参数。
    • int CropTop; int CropBottom; int CropLeft; int CropRight; - 裁剪后的画面长度和宽度。请注意,和 SAR 类似,这也是允许你忽略的参数。但如果你想保证画面 100% 显示正确,还是应该使用能够本值。
    • int TopFieldFirst - 非 0 表示奇数场优先,为 0 则表示偶数场优先。
    • int ColorSpace - YUV 色彩参数。定义与 MPEG-2 规范一致,参见 FFMS_ColorSpaces 枚举。你应该选用 FFMS_Frame 中的ColorSpace字段,因为每个帧的色彩参数可能会不同,除非你已用 FFMS_SetOutputFormatV2 设为同一个固定值。
    • int ColorRange - 亮度范围。参见 FFMS_ColorRanges 枚举定义。你应该选用 FFMS_Frame 中的ColorRange字段,因为每个帧的亮度范围可能会不同,除非你已用 FFMS_SetOutputFormatV2 设为同一个固定值。
    • double FirstTime; double LastTime; - 第一帧和最后一帧的时间戳,单位为秒。如果想知道是否存在延时,或者大致了解总的时长,本字段会有点用处。
    • int Rotation; - 旋转角度,单位为度。
    • int Stereo3DType; - 3D 视频的类型。参见 FFMS_Stereo3DType 枚举值。
    • int Stereo3DFlags - 3D 视频标志。参见 FFMS_Stereo3DFlags 枚举。
    • double LastEndTime - 最后一个数据包的结束时间,单位为毫秒。
    • int HasMasteringDisplayPrimaries - 如果非 0,则会设置以下 4 个字段。
    • double MasteringDisplayPrimariesX[3] - 主平面的 RGB 色彩坐标(X 轴)。
    • double MasteringDisplayPrimariesY[3] - 主平面的 RGB 色彩坐标(Y 轴)。
    • double MasteringDisplayWhitePointX - 主平面的白场坐标(X 轴)。
    • double MasteringDisplayWhitePointY - 主平面的白场坐标(Y 轴)。
    • int HasMasteringDisplayLuminance - 如果非 0,则会设置以下 2 个字段。
    • double MasteringDisplayMinLuminance - 主平面的最小亮度(单位 cd/m^2)。
    • double MasteringDisplayMaxLuminance - 主平面的最大亮度(单位 cd/m^2)。
    • int HasContentLightLevel - 如果非 0,则会设置以下 2 个字段。
    • unsigned int ContentLightLevelMax - 最大亮度(单位 cd/m^2)。
    • unsigned int ContentLightLevelAverage - 平均亮度(单位 cd/m^2)。

    FFMS_AudioProperties

    typedef struct {
        int SampleFormat;
        int SampleRate;
        int BitsPerSample;
        int Channels;
        int64_t ChannelLayout;
        int64_t NumSamples;
        double FirstTime;
        double LastTime;
        double LastEndTime;
    } FFMS_AudioProperties;
    

    音频轨的基本信息(元数据)。字段说明如下:

    • int SampleFormat - 表示音频的采样格式,为整数值。参阅 FFMS_SampleFormat
    • int SampleRate - 音频采样率,单位为每秒的采样数。
    • int BitsPerSample - 采样位数(精度)。请注意,这里是指编码精度,不是数据的保存精度,并且可能会与SampleFormat所示的精度不一致。你该明白,哪个才是有效参数吧。
    • int Channels - 音轨总数。
    • int64_t ChannelLayout - 声道的分布情况。由 FFMS_AudioChannel 定义的整数值二进制“或”组合而成,表示是否包含对应的声道数据。假设变量ChannelOrder为声道分布值,变量FFMS_CH_EXAMPLE为声道号,如果包含该声道数据,则(ChannelOrder & FFMS_CH_EXAMPLE)操作的结果将为真。各声道的数据将按照 FFMS_AudioChannel 枚举定义的顺序交错排列。
    • int64_t NumSamples - 总数据包数。
    • double FirstTime; double LastTime; - 第一个包和最后一个包的时间戳,单位为毫秒。如果想知道是否存在延时,或者大致了解总的时长,本字段会有点用处。
    • double LastEndTime - 最后一个包的时间,单位为毫秒。

    常量和预处理标志

    以下常量和预处理标志比较常用,在ffms.h中定义。

    FFMS_Errors

    enum FFMS_Errors {
        // 没有错误
        FFMS_ERROR_SUCCESS = 0,
    
        // 大类 - 表示错误发生的时机
        FFMS_ERROR_INDEX = 1,           // 处理索引时
        FFMS_ERROR_INDEXING,            // 创建索引时
        FFMS_ERROR_POSTPROCESSING,      // 视频后处理时(libpostproc)
        FFMS_ERROR_SCALING,             // 画面缩放时(libswscale)
        FFMS_ERROR_DECODING,            // 音视频解码时
        FFMS_ERROR_SEEKING,             // 检索文件时
        FFMS_ERROR_PARSER,              // 解析文件时
        FFMS_ERROR_TRACK,               // 处理音视频轨信息时
        FFMS_ERROR_WAVE_WRITER,         // 写 WAVE64 文件时
        FFMS_ERROR_CANCELLED,           // 取消操作时
    
        // 子类 - 表示出错原因
        FFMS_ERROR_UNKNOWN = 20,        // 未知错误
        FFMS_ERROR_UNSUPPORTED,         // 不支持的格式或操作
        FFMS_ERROR_FILE_READ,           // 无法读取文件
        FFMS_ERROR_FILE_WRITE,          // 无法写入文件
        FFMS_ERROR_NO_FILE,             // 文件或目录不存在
        FFMS_ERROR_VERSION,             // 版本错误
        FFMS_ERROR_ALLOCATION_FAILED,   // 内存不足
        FFMS_ERROR_INVALID_ARGUMENT,    // 参数非法
        FFMS_ERROR_CODEC,               // 解码器错误
        FFMS_ERROR_NOT_AVAILABLE,       // 非法操作
        FFMS_ERROR_FILE_MISMATCH,       // 索引与文件不匹配
        FFMS_ERROR_USER                 // 是用户的问题
    };
    

    上述错误信息的含义,已不言自明。

    FFMS_SeekMode

    enum FFMS_SeekMode {
        FFMS_SEEK_LINEAR_NO_RW  = -1,
        FFMS_SEEK_LINEAR        = 0,
        FFMS_SEEK_NORMAL        = 1,
        FFMS_SEEK_UNSAFE        = 2,
        FFMS_SEEK_AGGRESSIVE    = 3
    };
    

    FFMS_CreateVideoSource 中用于控制检索模式。各值的说明如下:

    • FFMS_SEEK_LINEAR_NO_RW - 不带回放的线性访问。如果后续的帧号小于等于已提交的访问请求,则会抛出异常。仅建议用于打开图片文件,对某些罕见的视频格式或许也能使用。
    • FFMS_SEEK_LINEAR - 线性访问。假设要访问第n帧,则不必先对第 0 到n-1帧进行访问。在获取第n帧数据之前,所有从0 到n-1帧的数据都会被解码一遍。虽然速度较慢,但可以保证某些格式的正常访问。
    • FFMS_SEEK_NORMAL - 安全的常规模式。根据 libavformat 返回的关键帧位置,进行检索。
    • FFMS_SEEK_UNSAFE - 不安全的常规模式。与FFMS_SEEK_NORMAL相同,但在必须猜测目标位置时不会报错。
    • FFMS_SEEK_AGGRESSIVE - 激进模式。即使附近没有关键帧,也直接去访问。只有在做测试时,或者 libavformat 无法正确返回关键帧信息时,才会用得上。

    FFMS_IndexErrorHandling

    enum FFMS_IndexErrorHandling {
        FFMS_IEH_ABORT = 0,
        FFMS_IEH_CLEAR_TRACK = 1,
        FFMS_IEH_STOP_TRACK = 2,
        FFMS_IEH_IGNORE = 3
    };
    

    在建立索引的函数中用于控制解码出错后的处理方式。

    • FFMS_IEH_ABORT - 取消索引并触发错误。
    • FFMS_IEH_CLEAR_TRACK - 清空本轨的索引数据(返回空轨)。
    • FFMS_IEH_STOP_TRACK - 停止索引但保留已索引数据(返回的索引中包含了至出错位置的数据)。
    • FFMS_IEH_IGNORE - 忽略错误,就当没发生过。

    FFMS_TrackType

    enum FFMS_TrackType {
        FFMS_TYPE_UNKNOWN = -1,
        FFMS_TYPE_VIDEO,
        FFMS_TYPE_AUDIO,
        FFMS_TYPE_DATA,
        FFMS_TYPE_SUBTITLE,
        FFMS_TYPE_ATTACHMENT
    };
    

    用于确定轨道的类型。请注意,目前所有的 API 函数,均无法处理FFMS_TYPE_VIDEOFFMS_TYPE_AUDIO之外的类型。请参阅 FFMS_GetTrackTypeFFMS_GetFirstTrackOfType 及其变体函数。

    FFMS_SampleFormat

    enum FFMS_SampleFormat {
        FFMS_FMT_U8 = 0,
        FFMS_FMT_S16,
        FFMS_FMT_S32,
        FFMS_FMT_FLT,
        FFMS_FMT_DBL
    };
    

    音频采样格式。

    • FFMS_FMT_U8 - 每次采样一个 8 位无符号整数(uint8_t)。
    • FFMS_FMT_S16 - 每次采样一个 16 位带符号整数(int16_t)。
    • FFMS_FMT_S32 - 每次采样一个 32 位带符号整数(int32_t)。
    • FFMS_FMT_FLT - 每次采样一个 32 位(单精度)浮点数(float_t)。
    • FFMS_FMT_DBL - 每次采样一个 64 位(双精度)浮点数(double_t)。

    FFMS_AudioChannel

    enum FFMS_AudioChannel {
        FFMS_CH_FRONT_LEFT              = 0x00000001,
        FFMS_CH_FRONT_RIGHT             = 0x00000002,
        FFMS_CH_FRONT_CENTER            = 0x00000004,
        FFMS_CH_LOW_FREQUENCY           = 0x00000008,
        FFMS_CH_BACK_LEFT               = 0x00000010,
        FFMS_CH_BACK_RIGHT              = 0x00000020,
        FFMS_CH_FRONT_LEFT_OF_CENTER    = 0x00000040,
        FFMS_CH_FRONT_RIGHT_OF_CENTER   = 0x00000080,
        FFMS_CH_BACK_CENTER             = 0x00000100,
        FFMS_CH_SIDE_LEFT               = 0x00000200,
        FFMS_CH_SIDE_RIGHT              = 0x00000400,
        FFMS_CH_TOP_CENTER              = 0x00000800,
        FFMS_CH_TOP_FRONT_LEFT          = 0x00001000,
        FFMS_CH_TOP_FRONT_CENTER        = 0x00002000,
        FFMS_CH_TOP_FRONT_RIGHT         = 0x00004000,
        FFMS_CH_TOP_BACK_LEFT           = 0x00008000,
        FFMS_CH_TOP_BACK_CENTER         = 0x00010000,
        FFMS_CH_TOP_BACK_RIGHT          = 0x00020000,
        FFMS_CH_STEREO_LEFT             = 0x20000000,
        FFMS_CH_STEREO_RIGHT            = 0x40000000
    };
    

    用于描述音轨中的声道分布情况。含义可不言自明。

    你可能已经注意到了,这些常量与微软WAVEFORMATEXTENSIBLE结构的dwChannelMask属性定义相同。详情请参阅 相关 MSDN 文档FFMS_CH_STEREO_LEFTFFMS_CH_STEREO_RIGHT是 FFmpeg 自己扩展的,在微软的定义之外。

    FFMS_Resizers

    enum FFMS_Resizers {
        FFMS_RESIZER_FAST_BILINEAR  = 0x01,
        FFMS_RESIZER_BILINEAR       = 0x02,
        FFMS_RESIZER_BICUBIC        = 0x04,
        FFMS_RESIZER_X              = 0x08,
        FFMS_RESIZER_POINT          = 0x10,
        FFMS_RESIZER_AREA           = 0x20,
        FFMS_RESIZER_BICUBLIN       = 0x40,
        FFMS_RESIZER_GAUSS          = 0x80,
        FFMS_RESIZER_SINC           = 0x100,
        FFMS_RESIZER_LANCZOS        = 0x200,
        FFMS_RESIZER_SPLINE         = 0x400
    };
    

    FFMS_SetOutputFormatV2 中用于给出各种图像缩放算法。含义不言自明。

    FFMS_AudioDelayModes

    enum FFMS_AudioDelayModes {
        FFMS_DELAY_NO_SHIFT           = -3,
        FFMS_DELAY_TIME_ZERO          = -2,
        FFMS_DELAY_FIRST_VIDEO_TRACK  = -1
    };
    

    描述对音频延时的处理方式。详细解释请参阅 FFMS_CreateAudioSource

    FFMS_ChromaLocations

    typedef enum FFMS_ChromaLocations {
        FFMS_LOC_UNSPECIFIED = 0,
        FFMS_LOC_LEFT = 1,
        FFMS_LOC_CENTER = 2,
        FFMS_LOC_TOPLEFT = 3,
        FFMS_LOC_TOP = 4,
        FFMS_LOC_BOTTOMLEFT = 5,
        FFMS_LOC_BOTTOM = 6
    } FFMS_ChromaLocations;
    

    表示色度采样点在帧画面内的位置。

    FFMS_ColorRanges

    enum FFMS_ColorRanges {
        FFMS_CR_UNSPECIFIED = 0,
        FFMS_CR_MPEG        = 1,
        FFMS_CR_JPEG        = 2,
    };
    

    用于描述 YUV 流中合法的亮度范围。FFMS_CR_MPEG是标准的“TV 范围”,带有上下裕量(headroom、footroom)。也就是说,合法的亮度值范围是从 16 到 235,带有 8 位色彩值。FFMS_CR_JPEG是全范围的,所有亮度值均可用。

    FFMS_Stereo3DType

    typedef enum FFMS_Stereo3DType {
        FFMS_S3D_TYPE_2D = 0,
        FFMS_S3D_TYPE_SIDEBYSIDE,
        FFMS_S3D_TYPE_TOPBOTTOM,
        FFMS_S3D_TYPE_FRAMESEQUENCE,
        FFMS_S3D_TYPE_CHECKERBOARD,
        FFMS_S3D_TYPE_SIDEBYSIDE_QUINCUNX,
        FFMS_S3D_TYPE_LINES,
        FFMS_S3D_TYPE_COLUMNS
    } FFMS_Stereo3DType;
    

    用于表示 3D 视频的类型。

    FFMS_Stereo3DFlags

    typedef enum FFMS_Stereo3DFlags {
        FFMS_S3D_FLAGS_INVERT = 1
    } FFMS_Stereo3DFlags;
    

    3D 视频的标志。

    FFMS_CC

    #ifdef _WIN32
    #   define FFMS_CC __stdcall
    #else
    #   define FFMS_CC
    #endif
    

    本宏是为了方便 FFMS2 API 函数的调用和回调。如果定义了 _WIN32 则为 __stdcall,否则就未用上。

    图像类型

    FFMS_Frame->PictType中存放的值:

    I: 关键帧(Intra)
    P: 差别帧(Predicted)
    B: 双向差别帧(Bi-dir predicted)
    S: S(GMC)-VOP MPEG4
    i: 切换关键帧(Switching Intra)
    p: 切换差别帧(Switching Predicted)
    b: FF_BI_TYPE(无意义帧)
    ?: 未能识别

    命名音频文件用到的格式串

    可以用以下变量:

    • %sourcefile% - 与源文件名相同,也就是要解码的文件名。
    • %trackn% - 轨号。
    • %trackzn% - 以 0 补足 2 位的轨号。
    • %samplerate% - 音频采样率。
    • %channels% - 声道号。
    • %bps% - 采样位数。
    • %delay% - 延时。确切地说,是第一个音频数据包的时间戳。

    示例:%sourcefile%_track%trackzn%.w64

  • 相关阅读:
    php多进程和多线程的比较
    设计模式学习系列——建造者模式
    设计模式学习系列——单例模式
    设计模式学习系列——前言
    设计模式学习系列——工厂模式
    记一次给nginx的web服务器目录加软链接
    某公司后端开发工程师面试题学习
    2010年腾讯前端面试题学习(jquery,html,css部分)
    2010年腾讯前端面试题学习(js部分)
    winfrom 隐藏任务栏(win7)
  • 原文地址:https://www.cnblogs.com/popapa/p/ffms2api.html
Copyright © 2020-2023  润新知