• 移植FFMPEG到VS2008系列之三


    5.  排除编译错误。

        这部分主要是修改C99的语法,常见的不兼容语法如下:

    5.1  例如在文件av_codec_4xm.c最后的结构体初始化代码如下:

    AVCodec ff_fourxm_decoder = {
        .name           = "4xm",
        .type           = AVMEDIA_TYPE_VIDEO,
        .id             = AV_CODEC_ID_4XM,
        .priv_data_size = sizeof(FourXContext),
        .init           = decode_init,
        .close          = decode_end,
        .decode         = decode_frame,
        .capabilities   = CODEC_CAP_DR1,
        .long_name      = NULL_IF_CONFIG_SMALL("4X Movie"),
    };


    修改之后的代码应该如下:

    AVCodec  ff_fourxm_decoder;
    void init_ff_fourxm_decoder(){
        ff_fourxm_decoder.name           = "4xm";
        ff_fourxm_decoder.type           = AVMEDIA_TYPE_VIDEO;
        ff_fourxm_decoder.id             = AV_CODEC_ID_4XM;
        ff_fourxm_decoder.priv_data_size = sizeof(FourXContext);
        ff_fourxm_decoder.init           = decode_init;
        ff_fourxm_decoder.close          = decode_end;
        ff_fourxm_decoder.decode         = decode_frame;
        ff_fourxm_decoder.capabilities   = CODEC_CAP_DR1;
        ff_fourxm_decoder.long_name      = NULL_IF_CONFIG_SMALL("4X Movie");
    };



    同样,  在libavformat下面很多文件的最后结构体初始化如下:

    AVInputFormat ff_fourxm_demuxer = {
        .name           = "4xm",
        .long_name      = NULL_IF_CONFIG_SMALL("4X Technologies"),
        .priv_data_size = sizeof(FourxmDemuxContext),
        .read_probe     = fourxm_probe,
        .read_header    = fourxm_read_header,
        .read_packet    = fourxm_read_packet,
        .read_close     = fourxm_read_close,
    };



    修改之后的代码应该如下;

    AVInputFormat ff_fourxm_demuxer;
    void init_ff_fourxm_demuxer(){
        ff_fourxm_demuxer.name           = "4xm";
        ff_fourxm_demuxer.long_name      = NULL_IF_CONFIG_SMALL("4X Technologies");
        ff_fourxm_demuxer.priv_data_size = sizeof(FourxmDemuxContext);
        ff_fourxm_demuxer.read_probe     = fourxm_probe;
        ff_fourxm_demuxer.read_header    = fourxm_read_header;
        ff_fourxm_demuxer.read_packet    = fourxm_read_packet;
        ff_fourxm_demuxer.read_close     = fourxm_read_close;
    };




    如果对每一个文件都手动的去这样修改,势必会占用大量的时间。我们可以用UE的正则表达式功能一定程度上减轻工作量。

    5.2 正则表达式的运用

         每次,用UE打开字母排序连续的50个文件。太多了,UE会吃不消。执行正则表达式的替换语法:

        Find what: (AVCodec)\s+([\w_]+)\s*=\s*\{
        replace: $1 $2;\nvoid init_$2\(\)\{

        上述正则表达式将把上述第一段代码替换为:

    AVCodec  ff_fourxm_decoder;
    void init_ff_fourxm_decoder(){
        .name           = "4xm",
        .type           = AVMEDIA_TYPE_VIDEO,
        .id             = AV_CODEC_ID_4XM,
        .priv_data_size = sizeof(FourXContext),
        .init           = decode_init,
        .close          = decode_end,
        .decode         = decode_frame,
        .capabilities   = CODEC_CAP_DR1,
        .long_name      = NULL_IF_CONFIG_SMALL("4X Movie"),
    };



    如果你精通用某种语言操作正则表达式的话,你就可以在这个结果上再写一个正则表达式解析出字符串ff_fourxm_decoder,然后再解析出.name,.type等,在此基础上替换为上面的第二段代码。


    几乎每一个文件的最后对结构体的初始化代码都和上面的类似,所以用几乎完全相同的正则表达式可以减少绝大部分的工作量。除非,你能百分百地确定你的正则表达式的正确性,否则,你应该一次执行替换一个而不是全部替换,至少前面几个的替换要一次执行一个,以确保你的正则表达式的正确性。


    6. 其它主要的正则表达式

       6.1 static const AVOption options[]变量的初始化

            原始代码如下:

    static const AVOption options[] = {
        {"dual_mono_mode", "Select the channel to decode for dual mono",
         offsetof(AACContext, force_dmono_mode), AV_OPT_TYPE_INT, {.i64=-1}, -1, 2,
         AACDEC_FLAGS, "dual_mono_mode"},
    
        {"auto", "autoselection",            0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"},
        {"main", "Select Main/Left channel", 0, AV_OPT_TYPE_CONST, {.i64= 1}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"},
        {"sub" , "Select Sub/Right channel", 0, AV_OPT_TYPE_CONST, {.i64= 2}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"},
        {"both", "Select both channels",     0, AV_OPT_TYPE_CONST, {.i64= 0}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"},
    
        {NULL},
    };



    修改之后的初始化如下:

    static const AVOption options[] = {
        {"dual_mono_mode", "Select the channel to decode for dual mono",
         offsetof(AACContext, force_dmono_mode), AV_OPT_TYPE_INT, (int64_t)(-1), -1, 2,
         AACDEC_FLAGS, "dual_mono_mode"},
    
    
        {"auto", "autoselection",            0, AV_OPT_TYPE_CONST, (int64_t)(-1), INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"},
        {"main", "Select Main/Left channel", 0, AV_OPT_TYPE_CONST, (int64_t)(1), INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"},
        {"sub" , "Select Sub/Right channel", 0, AV_OPT_TYPE_CONST, (int64_t)(2), INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"},
        {"both", "Select both channels",     0, AV_OPT_TYPE_CONST, (int64_t)(0), INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"},
    
    
        {NULL},
    };
        



    正则表达式如下:

     

    Find what: \{\s*\.i64\s*=\s*(-?[\w\*]+)\s*\}

    Replace:\(int64_t\)\($1\)

    上述正则表达式把以 .i64 = 后面的一个合法标示符变换为 (int64_t)后面接原始标示符。

    类似的还有几个如下,分别替换双精度类型和字符串类型:

    Find what:\{\s*\.dbl\s*=\s*(-?[\w.]+)\s*\}

    Replace:\(double\)\($1\)


    Find what:\{\s*\.str\s*=\s*(-?[\w"]+)\s*\}

    Find what:\(const char\*\)\($1\)


    注意,冒号之后的为正则表达式。不同的人执行同一个任务写出来的正则表达式不唯一!



    6.2 变量AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB]的初始化

         

          这个变量很重要,如果它初始化不正确,程序将会crash掉。这个变量的初始化放在单独的一个文件里面,因为它太长太长!这个文件就是前面提到的ffmpeg_init_av_pix_fmt_descriptors.c

         原始初始化代码如下:

    const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
        [AV_PIX_FMT_YUV420P] = {
            .name = "yuv420p",
            .nb_components = 3,
            .log2_chroma_w = 1,
            .log2_chroma_h = 1,
            .comp = {
                { 0, 0, 1, 0, 7 },        /* Y */
                { 1, 0, 1, 0, 7 },        /* U */
                { 2, 0, 1, 0, 7 },        /* V */
            },
            .flags = PIX_FMT_PLANAR,
        },
        [AV_PIX_FMT_YUYV422] = {
            .name = "yuyv422",
            .nb_components = 3,
            .log2_chroma_w = 1,
            .log2_chroma_h = 0,
            .comp = {
                { 0, 1, 1, 0, 7 },        /* Y */
                { 0, 3, 2, 0, 7 },        /* U */
                { 0, 3, 4, 0, 7 },        /* V */
            },
        },
        这里只列举了前两个,后面还有很长很长的几乎类似的代码。

        修改之后的代码应该写成这个样子:

    void init_g_AVPixFmtDescriptor_av_pix_fmt_descriptors(){
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].name = "yuv420p";
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].nb_components = 3;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].log2_chroma_w = 1;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].log2_chroma_h = 1;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].comp[0].plane = 0;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].comp[0].step_minus1 = 0;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].comp[0].offset_plus1 = 1;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].comp[0].shift = 0;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].comp[0].depth_minus1 = 7;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].comp[1].plane = 1;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].comp[1].step_minus1 = 0;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].comp[1].offset_plus1 = 1;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].comp[1].shift = 0;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].comp[1].depth_minus1 = 7;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].comp[2].plane = 2;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].comp[2].step_minus1 = 0;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].comp[2].offset_plus1 = 1;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].comp[2].shift = 0;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].comp[2].depth_minus1 = 7;
        av_pix_fmt_descriptors[AV_PIX_FMT_YUV420P].flags = PIX_FMT_PLANAR;


           依次在UE里面执行下面一系列正则表达式可以完成上述代码的转换:

    Find what:
    
    \[(\w+)\].+\s+(\.name.+),\s+(\.nb_components.+),\s+(\.log2_chroma_w.+),\s+(\.log2_chroma_h.+),\s+(.comp.+)
    
    Replace:
    av_pix_fmt_descriptors[$1]$2;\n    av_pix_fmt_descriptors[$1]$3;\n    av_pix_fmt_descriptors[$1]$4;\n    av_pix_fmt_descriptors[$1]$5;\n    av_pix_fmt_descriptors[$1]$6;
    
    
    Find what:
    av_pix_fmt_descriptors\[(\w+)\]\.comp\s*.+\s+\{(.+)\}.+\s+\{(.+)\}.+\s+\{(.+)\}.+
    
    Replace:
    av_pix_fmt_descriptors[$1].comp[0] = $2;\n    av_pix_fmt_descriptors[$1].comp[1] = $3;\n    av_pix_fmt_descriptors[$1].comp[2] = $4;
    
    
    Find what:
    av_pix_fmt_descriptors\[(\w+)\]\.comp\[2\]\s*(.+)\s+\{(.+)\}.+
    
    Replace:
    av_pix_fmt_descriptors[$1].comp[2] $2\n    av_pix_fmt_descriptors[$1].comp[3] = $3;
    
    
    Find what:
    av_pix_fmt_descriptors\[(\w+)\]\.comp\[(\d+)\]\s*=\s*(\d+),\s*(\d+),\s*(\d+),\s*(\d+),\s*(\d+).+
    
    Replace:
    av_pix_fmt_descriptors[$1].comp[$2].plane = $3;\n    av_pix_fmt_descriptors[$1].comp[$2].step_minus1 = $4;\n    av_pix_fmt_descriptors[$1].comp[$2].offset_plus1 = $5;\n    av_pix_fmt_descriptors[$1].comp[$2].shift = $6;\n    av_pix_fmt_descriptors[$1].comp[$2].depth_minus1 = $7;
    
    
    Find what:
    av_pix_fmt_descriptors\[(\w+)\](.+)\s+\},\s+\.flags\s*=\s*([\w\| ]+),\s+\},
    
    
    Replace:
    av_pix_fmt_descriptors[$1]$2\n    av_pix_fmt_descriptors[$1].flags = $3;\n
    


    注意,上述一系列正则表达式都比较长,没有折行的地方不能换行,否则会出现格式上的错误。


  • 相关阅读:
    HashMap 统计一个字符串中每个单词出现的次数
    iOS .a静态库的制作及使用
    iOS framework静态库中使用xib和图片资源详解
    iOS 工程套子工程,主工程和framework工程或.a library静态库工程联调
    iOS 最新framework和.a静态库制作及使用全解(含工程套工程,多工程联调)
    iOS9新特性 3DTouch 开发教程全解(含源码)
    iOS GCD NSOperation NSThread等多线程各种举例详解
    Mac Beyond Compare 永久试用
    cocoapods 常见问题
    iOS 常用工具库LFKit功能介绍
  • 原文地址:https://www.cnblogs.com/celerychen/p/3588209.html
Copyright © 2020-2023  润新知