精华内容
下载资源
问答
  • Register

    2019-10-25 14:00:14
    Register
  • register_vugen.bat

    2020-06-15 16:16:23
    loadrunner打不开ie,找不到register_vugen.bat文件 ,register_vugen.bat 下载,把register_vugen.bat放到安装的Bin目录下
  • node-register-scheme-源码

    2021-05-12 13:31:19
    register-scheme const register = require ( 'register-scheme' ) ; // myamazingscheme:// register ( 'myamazingscheme' ) ; 基于来自代码
  • Multibit Register Synthesis and Physical Implementation Application Note.pdf
  • PAGE PAGE 1 dll已加载但找不到入口点DLLRegisterServer怎么办 dll已加载但找不到入口点DLLRegisterServer怎么办不少人在使用注册表时经常遇到dll已加载但找不到入口点DLLRegisterServer的错误提示这是怎么回事该...
  • esbuild-register 安装 npm i esbuild-register -D # Or Yarn yarn add esbuild-register --dev 用法 node -r esbuild-register file.ts 它将使用jsxFactory , jsxFragmentFactory和target选择从tsconfig.json ...
  • 假设point-to-register中已经存储了一些点(通过point-to-register或iregister-point-to-register命令)。 例如,执行iregister-jump-to-next-marker ,迷你缓冲区将显示存储点缓冲区的片段。 该片段将包含存储点...
  • IMX214_RegisterMap_2.0.0

    2019-04-01 11:31:52
    IMX214_RegisterMap_2.0.0
  • register

    千次阅读 2017-12-19 11:31:02
    (2)register 当声明对象有自动生存周期时,可以使用register修饰符。因此,register也只能用在函数内的声明中。 此关键字告诉编译器:此对象的存取应该尽量快,最好存储在CPU的寄存器中。然而,编译器不见得会...

    (2)register

    当声明对象有自动生存周期时,可以使用register修饰符。因此,register也只能用在函数内的声明中。
    此关键字告诉编译器:此对象的存取应该尽量快,最好存储在CPU的寄存器中。然而,编译器不见得会这么做。
    另外要注意的是,当一个对象声明为register,就不可使用地址运算符&了,因为它有可能被放到寄存器中。



    1、先说register吧

    在c++中:

    (1)register 关键字无法在全局中定义变量,否则会被提示为不正确的存储类。

    (2)register 关键字在局部作用域中声明时,可以用 & 操作符取地址,一旦使用了取地址操作符,被定义的变量会强制存放在内存中。

    在c中:

    (1)register 关键字可以在全局中定义变量,当对其变量使用 & 操作符时,只是警告“有坏的存储类”。

    (2)register 关键字可以在局部作用域中声明,但这样就无法对其使用 & 操作符。否则编译不通过。

    3333333333333333333333333333333333333333

    变量作用域和生存周期

    SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS

    WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW

    C++中变量的生存周期

    原创 2017年04月18日 20:57:04

    在C++中变量有以下两种生存周期:

          #变量由编译程序在编译时给其分配存储空间(称为静态存储分配),并在程序执行过程中始终存在。这类变量的生存周期与程序的运行周期相同,当程序运行时,该变量的生存周期随即存在,程序运行结束,变量的生存周期随即终止。

          #变量由程序在运行时自动给其分配存储空间(称为自动存储分配),这类变量为函数(或块)中定义的自动变量。它们在程序执行到该函数(或块)时被创建,在函数(或块)执行结束时释放所占用的空间。

          注:在C++中,当标识符的作用域发生重叠时,在一个函数(或块)中声明的标识符可以屏蔽函数(或块)外声明的标识符或全局标识符。

          >变量作用域示例

    1. #include<iostream>  
    2. using namespace std;  
    3. int i=0;                         //line 0  
    4. int main(){  
    5.     int i=1;                 //line 1  
    6.     cout<<"i="<<i;           //line 2  
    7.     {                            //line 3  
    8.         int i=2;                 //line 4  
    9.         cout<<"i="<<i;           //line 5  
    10.         {                //line 6  
    11.           i+=1;          //line 7  
    12.           cout<<"i="<<i; //line 8  
    13.         }                //line 9  
    14.         cout<<"i="<<i;           //line 10  
    15.     }                        //line 11  
    16.     cout<<"i="<<i<<endl;     //line 12  
    17.    
    18.     system("pause");  
    19.     return 0;                //line 13  
    20. }  

          >程序的运行结果是:


           >分析:

           在函数外面定义的全局变量i(0行),它的作用域应为整个程序。在main函数开头处定义的局部变量i(1行),它的作用域为整个函数,即从1行到13行,根据上面标识符作用域冲突规定,在2行的输出语句将输出定义在1行的变量i的值,即为1。在4行定义的局部变量i,其作用域为所在块,即从4到10行,同样根据标识符作用域冲突规定,在5行的输出语句将输出定义在4行的变量i的值,即为2;同时由于7行所操作的变量i正处于定义在4行的变量i的作用范围内,因此将其值加1,得i=3,所以8行的输出语句输出变量i的值为3。同理,由于10行所输出的变量i正处于定义在4行变量i的作用域范围内,因此输出结果为3(其值在7行修改)。而在12行的输出语句所输出的变量i处于定义在1行变量i的左右范围内,因此输出结果为1(其值未被修改过)。


           由于作用域的屏蔽效应,如果函数中有同名变量,则不能访问外部变量。为了能在函数内部访问函数外部定义的变量,可以使用C++中的作用域运算符“ :: ”。通过作用域运算符,即使该函数(或块)中已有与之同名的变量,也可以在函数(块)中使用定义在函数(块)外的全局变量。此外作用域运算符还可以用来指定类成员变量或成员函数所属的类。

           当程序较大时,利用名字屏蔽机制是非常必要的。但是,这也会导致程序的可读性变差,好的程序设计风格应尽量避免名字屏蔽。







    SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS

    WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW

    1、局部变量


    (1)作用域函数内部,从变量定义完成到达函数结束


    (2)生命周期变量定义完成 到 函数调用结束  


    (3)初始化值随机值 


    (4)内存区域栈(后进先出,TOP指针,高地址向低地址生长,连续)


    2、全局变量


    (1)作用域整个程序(本文件,和同工程其他文件都可访问)


    (2)生命周期进程建立,main调用之前 到 进程结束(特别长)  


    (3)初始化值0


    (4)内存区域全局变量区(数据段  .date


    static可将全局变量可见性,限定在本文件内


          可将函数可见性,限定在本文件内


    extern将外部的文件中的全局变量、函数引入到本文件中,本文件


           可使用外部的全局变量

    3、复合语句块变量


    (1)作用域复合语句块内部,从变量定义完成到达语句块结束


    (2)生命周期 变量定义完成 到 函数调用结束


    (3)初始化值随机值


    (4)内存区域


    4、静态变量


    静态局部变量:


    (1)作用域局部变量相同,函数内部,从变量定义完成到达函数结束


    (2)生命周期本文件内进程建立,main调用之前 到 进程结束


    (3)初始化值0


    (4)内存区域全局变量区/静态变量区/数据段/.data


    静态全局变量:


    (1)作用域从变量定义完成时开始,整个文件可访问。但是:只能在本文件内访  


            问,其他文件无法访问


    (2)生命周期进程建立到结束(特别长)  


    (3)初始化值0


    (4)内存区域全局变量区/静态变量区/数据段/.data

    5、外部全局变量


    (1)作用域整个程序,本文件,同工程的其他文件可用


    (2)生命周期进程建立到结束(特别长)  


    (3)初始化值0


    (4)内存区域全局变量区


    6、形式参数变量


    (1)作用域函数内部,函数调用时可见,到达函数结束


    (2)生命周期函数调用 到 函数调用结束 


    (3)初始化值来在于调用函数传递的实参值


    (4)内存区域

    7、堆空间char *p = (char *)malloc(4);new


    (1)作用域动态空间


    (2)生命周期start:主动调用malloccallocreallocnew),申请成功时建立


               end:主动调用free,堆空间释放


               end:进程结束,操作系统进行内存空间回收  


    (3)初始化值malloc为随机值;calloc0


    (4)内存区域堆(heap,从低向高,物理上不连续)


    8、寄存器变量


    (1)作用域


    (2)生命周期该寄存器值被其他值替换


    (3)初始化值


    (4)内存区域放在寄存器当中,不在内存中出现


    WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW

    SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS



    44444444444444444444444444444444444444444444444444444

     
    1. int func1(void); //func1具有外部链接;    
    2. int a = 10; //a具有外部链接,静态生存周期;    
    3. extern int b = 1; //b具有外部链接,静态生存周期。但编译会有警告extern变量不应初始化,同时也要注意是否会重复定义;    
    4. static int c; //c具有内部链接,静态生存周期;    
    5. static int e; //e具有内部链接,静态生存周期;    
    6. static void func2(int d){ //func2具有内部链接;参数d具有无链接,自动生存周期;    
    7. extern int a; //a与上面的a一样(同一变量),具有外部链接,静态生存周期。注意这里的不会被默认初始为0,它只是个声明;    
    8. int b = 2; //b具有无链接,自动生存同期。并且将上面声明的b隐藏起来;    
    9. extern int c; //c与上面的c一样,维持内部链接,静态生存周期。注意这里的不会被默认初始为0,它只是个声明;    
    10. //如果去掉了extern修饰符,就跟b类似了,无链接,自动生存周期,把上面声明的c隐藏起来;    
    11. static int e; //e具有无链接,静态生存周期。并且将上面声明的e隐藏起来;初始化值为0;    
    12. static int f; //f具有无链接,静态生存周期;    
    5555555555555555555555555555555555555555555555555555555


    #ifdef NOSTRUCTASSIGN

      memcpy (d, s, l)

      {

            register char *d;

          register char *s;

          register int i;

          while (i--)

              *d++ = *s++;

      }

      #endif


    666666666666666666666666666使用register修饰符的注意点

    但是使用register修饰符有几点限制。

      首先,register变量必须是能被CPU所接受的类型。这通常意味着register变量必须是一个单个的值,并且长度应该小于或者等于整型的长度不过,有些机器的寄存器也能存放浮点数。

      其次,因为register变量可能不存放在内存中,所以不能用“&”来获取register变量的地址

      由于寄存器的数量有限,而且某些寄存器只能接受特定类型的数据(如指针和浮点数),因此真正起作用的register修饰符的数目和类型都依赖于运行程序的机器,而任何多余的register修饰符都将被编译程序所忽略。

      在某些情况下,把变量保存在寄存器中反而会降低程序的运行速度。因为被占用的寄存器不能再用于其它目的;或者变量被使用的次数不够多,不足以装入和存储变量所带来的额外开销。

      早期的C编译程序不会把变量保存在寄存器中,除非你命令它这样做,这时register修饰符是C语言的一种很有价值的补充。然而,随着编译程序设计技术的进步,在决定那些变量应该被存到寄存器中时,现在的C编译环境能比程序员做出更好的决定。实际上,许多编译程序都会忽略register修饰符,因为尽管它完全合法,但它仅仅是暗示而不是命令


    下面是volatile变量的几个例子

    1)并行设备的硬件寄存器(如:状态寄存器)

    2) 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)

    3)多线程应用中被几个任务共享的变量


    TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

    1)一个参数既可以是const还可以是volatile吗?解释为什么。

    2); 一个指针可以是volatile 吗?解释为什么。

    3); 下面的函数有什么错误:
    int square(volatile int *ptr)
    {
    return *ptr * *ptr;
    }

    下面是答案:

    1)是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

    2); 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

    3)这段代码有点变态。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:
    int square(volatile int *ptr)
    {
    int a,b;
    a = *ptr;
    b = *ptr;
    return a * b;
    }
    由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:
    long square(volatile int *ptr)
    {
    int a;
    a = *ptr;
    return a * a;
    }
    位操作(Bit manipulation)

    TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT























    展开全文
  • 解压 放到 LoadRunner\bin文件夹 执行register_vugen.bat批处理文件,重新注册,
  • babel-register-ts 可能是带有其他.ts和.tsx扩展名的临时@babel/register包装器,请参阅 。 安装 yarn add --dev @babel/core @babel/register babel-register-ts # or npm install --dev @babel/core @babel/...
  • Register Assistant UVM is a register management tool that allows you to make changes to register specifications in a single place and automatically generate and update a UVM package.
  • mpu6500的datasheet和registere map ,mpu6500的数据手册和寄存器映射,英文版
  • CSD_Register

    2018-09-21 16:39:59
    CSD_Register 文档 寄存器 开发文档 CSD_Register CSD_Register
  • IMS网络Register流程数据包(wireshark),抓自OpenIMSCore,P-CSCF端口4060,I-CSCF 5060,S-CSCF 6060
  • av_register_all() 本篇主要解析av_register_all()所在文件libavformat–allformats.c及av_register_all()在调用过程中引用到的libavcodec–allcodecs.c。 ffmpeg注册复用器,编码器等的函数av_register_all()。该...

    av_register_all()

    本篇主要解析av_register_all()所在文件libavformat–allformats.c及av_register_all()在调用过程中引用到的libavcodec–allcodecs.c。

    ffmpeg注册复用器,编码器等的函数av_register_all()。该函数在所有基于ffmpeg的应用程序中几乎都是第一个被调用的。只有调用了该函数,才能使用复用器,编码器等。

    avpriv_atomic_ptr_cas源码

    这个函数在下面的源码中出现频率很高

    // package:libavutil->atomic.c  
    
    // 类似CAS操作:当前值为旧值时,才赋新值
    
    #if HAVE_PTHREADS
    
    #include <pthread.h>
    
    // 互斥锁pthread_mutex_t
    static pthread_mutex_t atomic_lock = PTHREAD_MUTEX_INITIALIZER;
    
    void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval)
    {
        void *ret;
        pthread_mutex_lock(&atomic_lock);
        ret = *ptr;
        if (ret == oldval)
            *ptr = newval;
        pthread_mutex_unlock(&atomic_lock);
        return ret;
    }
    
    #elif !HAVE_THREADS
    
    void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval)
    {
        if (*ptr == oldval) {
            *ptr = newval;
            return oldval;
        }
        return *ptr;
    }
    

    源码分析

    对主要代码进行了注释
    对大量的注册信息进行了精简,留下了一部分常见的

    libavformat–allformats.c

    /*
     * Register all the formats and protocols
     * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
     *
     * This file is part of FFmpeg.
     *
     * FFmpeg is free software; you can redistribute it and/or
     * modify it under the terms of the GNU Lesser General Public
     * License as published by the Free Software Foundation; either
     * version 2.1 of the License, or (at your option) any later version.
     *
     * FFmpeg is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * Lesser General Public License for more details.
     *
     * You should have received a copy of the GNU Lesser General Public
     * License along with FFmpeg; if not, write to the Free Software
     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     */
    
    #include "libavutil/thread.h"
    #include "avformat.h"
    #include "rtp.h"
    #include "rdt.h"
    #include "url.h"
    #include "version.h"
    
    /**
     * ##的含义就是拼接两个字符串
     *
     * 例如:REGISTER_MUXER(A64,a64)
     *
     * extern AVOutputFormat ff_a64_muxer;
     * if (CONFIG_A64_MUXER)
     *    av_register_output_format(&ff_a64_muxer);
     *
     * -----------------------------------------------
     *
     * av_register_output_format在format.c中
     * void av_register_output_format(AVOutputFormat *format) {
     *     AVOutputFormat **p = last_oformat;
     *
     *     // Note, format could be added after the first 2 checks but that implies that *p is no longer NULL
     *     while(p != &format->next && !format->next && avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format))
     *         p = &(*p)->next;
     *
     *     if (!format->next)
     *         last_oformat = &format->next;
     * }
     *
     * // head of registered output format linked list  (Output Format链表)
     * static AVOutputFormat*first_oformat=NULL;
     *
     * 故这段代码的作用是,遍历OutputFormat链表,将当前format插入到链表尾部。Input部分与此逻辑相同。
     *
     */
    #define REGISTER_MUXER(X, x)                                            \
        {                                                                   \
            extern AVOutputFormat ff_##x##_muxer;                           \
            if (CONFIG_##X##_MUXER)                                         \
                av_register_output_format(&ff_##x##_muxer);                 \
        }
    
    #define REGISTER_DEMUXER(X, x)                                          \
        {                                                                   \
            extern AVInputFormat ff_##x##_demuxer;                          \
            if (CONFIG_##X##_DEMUXER)                                       \
                av_register_input_format(&ff_##x##_demuxer);                \
        }
    
    #define REGISTER_MUXDEMUX(X, x) REGISTER_MUXER(X, x); REGISTER_DEMUXER(X, x)
    
    static void register_all(void)
    {
        // allcodecs.c中,注册编解码器
        avcodec_register_all();
    
        /* (de)muxers */
        // MUXER:复用器  DEMUXER:解复用器  MUXDEMUX:复用与解复用
        REGISTER_MUXER   (A64,              a64);
        REGISTER_DEMUXER (AA,               aa);
        REGISTER_DEMUXER (AAC,              aac);
        REGISTER_MUXDEMUX(AC3,              ac3);
        REGISTER_DEMUXER (ACM,              acm);
        REGISTER_DEMUXER (ACT,              act);
        ...
        REGISTER_MUXDEMUX(AVI,              avi);
        ...
        REGISTER_DEMUXER (BMV,              bmv);
        ...
        REGISTER_MUXDEMUX(DASH,             dash);
        REGISTER_MUXDEMUX(DATA,             data);
        ...
        REGISTER_MUXER   (FIFO,             fifo);
        ...
        REGISTER_MUXDEMUX(FLV,              flv);
        REGISTER_DEMUXER (LIVE_FLV,         live_flv);
        ...
        REGISTER_MUXDEMUX(GIF,              gif);
        ...
        REGISTER_MUXDEMUX(H264,             h264);
        REGISTER_MUXER   (HASH,             hash);
        REGISTER_MUXER   (HDS,              hds);
        REGISTER_MUXDEMUX(HEVC,             hevc);
        REGISTER_MUXDEMUX(HLS,              hls);
        REGISTER_DEMUXER (HNM,              hnm);
        REGISTER_MUXDEMUX(ICO,              ico);
        ...
        REGISTER_MUXDEMUX(IMAGE2,           image2);
        ...
        REGISTER_DEMUXER (LVF,              lvf);
        REGISTER_DEMUXER (LXF,              lxf);
        ...
        REGISTER_MUXDEMUX(MJPEG,            mjpeg);
        REGISTER_DEMUXER (MJPEG_2000,       mjpeg_2000);
        ...
        REGISTER_MUXDEMUX(MOV,              mov);
        REGISTER_MUXER   (MP2,              mp2);
        REGISTER_MUXDEMUX(MP3,              mp3);
        REGISTER_MUXER   (MP4,              mp4);
        ...
        REGISTER_DEMUXER (MPEGPS,           mpegps);
        REGISTER_MUXDEMUX(MPEGTS,           mpegts);
        REGISTER_DEMUXER (MPEGTSRAW,        mpegtsraw);
        REGISTER_DEMUXER (MPEGVIDEO,        mpegvideo);
        REGISTER_MUXDEMUX(MPJPEG,           mpjpeg);
        ...
        REGISTER_DEMUXER (MV,               mv);
        REGISTER_DEMUXER (MVI,              mvi);
        ...
        REGISTER_MUXER   (NULL,             null);
        REGISTER_MUXDEMUX(NUT,              nut);
        REGISTER_DEMUXER (NUV,              nuv);
        REGISTER_MUXER   (OGA,              oga);
        REGISTER_MUXDEMUX(OGG,              ogg);
        ...
        REGISTER_MUXDEMUX(PCM_U8,           pcm_u8);
        ...
        REGISTER_MUXDEMUX(RTP,              rtp);
        REGISTER_MUXER   (RTP_MPEGTS,       rtp_mpegts);
        REGISTER_MUXDEMUX(RTSP,             rtsp);
        ...
    #if CONFIG_RTPDEC
        ff_register_rtp_dynamic_payload_handlers();
        ff_register_rdt_dynamic_payload_handlers();
    #endif
        REGISTER_DEMUXER (SEGAFILM,         segafilm);
        REGISTER_MUXER   (SEGMENT,          segment);
        REGISTER_MUXER   (SEGMENT,          stream_segment);
        REGISTER_DEMUXER (SHORTEN,          shorten);
        REGISTER_DEMUXER (SIFF,             siff);
        REGISTER_MUXER   (SINGLEJPEG,       singlejpeg);
        REGISTER_DEMUXER (SLN,              sln);
        REGISTER_DEMUXER (SMACKER,          smacker);
        REGISTER_MUXDEMUX(SMJPEG,           smjpeg);
        ...
        REGISTER_DEMUXER (SVAG,             svag);
        ...
        REGISTER_MUXDEMUX(WAV,              wav);
        ...
        REGISTER_MUXER   (WEBM_CHUNK,       webm_chunk);
        REGISTER_MUXER   (WEBP,             webp);
        ...
        REGISTER_MUXDEMUX(YUV4MPEGPIPE,     yuv4mpegpipe);
    
        /* image demuxers */
        REGISTER_DEMUXER (IMAGE_BMP_PIPE,        image_bmp_pipe);
        ...
        REGISTER_DEMUXER (IMAGE_JPEG_PIPE,       image_jpeg_pipe);
        ...
        REGISTER_DEMUXER (IMAGE_SVG_PIPE,        image_svg_pipe);
        ...
        REGISTER_DEMUXER (IMAGE_WEBP_PIPE,       image_webp_pipe);
        REGISTER_DEMUXER (IMAGE_XPM_PIPE,        image_xpm_pipe);
    
        /* external libraries */
        REGISTER_MUXER   (CHROMAPRINT,      chromaprint);
        REGISTER_DEMUXER (LIBGME,           libgme);
        REGISTER_DEMUXER (LIBMODPLUG,       libmodplug);
        REGISTER_DEMUXER (LIBOPENMPT,       libopenmpt);
    }
    
    void av_register_all(void)
    {
        static AVOnce control = AV_ONCE_INIT;
    
        // ff_thread_once的作用是保证register_all只会被调用一次
        ff_thread_once(&control, register_all);
    }
    

    libavcodec–allcodecs.c

    分析器(Parser)

    BSF(bitstream filters,比特流滤镜,有一个常用:h264_mp4toannexb)
    HWACCEL(hardware accelerators,硬件加速器)

    /*
     * Provide registration of all codecs, parsers and bitstream filters for libavcodec.
     * Copyright (c) 2002 Fabrice Bellard
     *
     * This file is part of FFmpeg.
     *
     * FFmpeg is free software; you can redistribute it and/or
     * modify it under the terms of the GNU Lesser General Public
     * License as published by the Free Software Foundation; either
     * version 2.1 of the License, or (at your option) any later version.
     *
     * FFmpeg is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * Lesser General Public License for more details.
     *
     * You should have received a copy of the GNU Lesser General Public
     * License along with FFmpeg; if not, write to the Free Software
     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     */
    
    /**
     * @file
     * Provide registration of all codecs, parsers and bitstream filters for libavcodec.
     */
    
    #include "config.h"
    #include "libavutil/thread.h"
    #include "avcodec.h"
    #include "version.h"
    
    #define REGISTER_HWACCEL(X, x)                                          \
        {                                                                   \
            extern AVHWAccel ff_##x##_hwaccel;                              \
            if (CONFIG_##X##_HWACCEL)                                       \
                /**
                 * libavcodec-util.c
                 * 该接口的功能是用来注册硬件加速器
                 *
                 * static AVHWAccel *first_hwaccel = NULL;
                 * static AVHWAccel **last_hwaccel = &first_hwaccel;
                 *
                 * void av_register_hwaccel(AVHWAccel *hwaccel)
                 * {
                 *     AVHWAccel **p = last_hwaccel;
                 *     hwaccel->next = NULL;
                 *     while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, hwaccel))
                 *         p = &(*p)->next;
                 *     last_hwaccel = &hwaccel->next;
                 * }
                 *
                 * -----------------------------------------------------------
                 *
                 * 当*p不为null时,向后遍历;为null时,将hwaccel放入
                 * 最后保存尾部索引
                 */
                av_register_hwaccel(&ff_##x##_hwaccel);                     \
        }
    
    #define REGISTER_ENCODER(X, x)                                          \
        {                                                                   \
            extern AVCodec ff_##x##_encoder;                                \
            if (CONFIG_##X##_ENCODER)                                       \
                /**
                 * libavcodec->util.c
                 *
                 * static AVCodec *first_avcodec = NULL;
                 * static AVCodec **last_avcodec = &first_avcodec;
                 *
                 * av_cold void avcodec_register(AVCodec *codec)
                 * {
                 *     AVCodec **p;
                 *     avcodec_init();
                 *     p = last_avcodec;
                 *     codec->next = NULL;
                 *
                 *     while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, codec))
                 *         p = &(*p)->next;
                 *     last_avcodec = &codec->next;
                 *
                 *     if (codec->init_static_data)
                 *         codec->init_static_data(codec);
                 * }
                 */
                avcodec_register(&ff_##x##_encoder);                        \
        }
    
    #define REGISTER_DECODER(X, x)                                          \
        {                                                                   \
            extern AVCodec ff_##x##_decoder;                                \
            if (CONFIG_##X##_DECODER)                                       \
                avcodec_register(&ff_##x##_decoder);                        \
        }
    
    #define REGISTER_ENCDEC(X, x) REGISTER_ENCODER(X, x); REGISTER_DECODER(X, x)
    
    #define REGISTER_PARSER(X, x)                                           \
        {                                                                   \
            extern AVCodecParser ff_##x##_parser;                           \
            if (CONFIG_##X##_PARSER)                                        \
                /**
                 * libavcodec->util.c
                 *
                 * static AVCodecParser *av_first_parser = NULL;
                 *
                 * void av_register_codec_parser(AVCodecParser *parser)
                 * {
                 *     do {
                 *         parser->next = av_first_parser;
                 *     } while (parser->next != avpriv_atomic_ptr_cas((void * volatile *)&av_first_parser, parser->next, parser));
                 * }
                 */
                av_register_codec_parser(&ff_##x##_parser);                 \
        }
    
    static void register_all(void)
    {
        /* hardware accelerators */
        ...
        REGISTER_HWACCEL(H264_MEDIACODEC,   h264_mediacodec);
        ...
        REGISTER_HWACCEL(HEVC_MEDIACODEC,   hevc_mediacodec);
        ...
        REGISTER_HWACCEL(MPEG1_VIDEOTOOLBOX, mpeg1_videotoolbox);
        ...
        REGISTER_HWACCEL(MPEG2_MEDIACODEC,  mpeg2_mediacodec);
        REGISTER_HWACCEL(MPEG4_CUVID,       mpeg4_cuvid);
        REGISTER_HWACCEL(MPEG4_MEDIACODEC,  mpeg4_mediacodec);
        ...
        REGISTER_HWACCEL(MPEG4_VIDEOTOOLBOX, mpeg4_videotoolbox);
        ...
    
        /* video codecs */
        ...
        REGISTER_ENCDEC (APNG,              apng);
        REGISTER_ENCDEC (ASV1,              asv1);
        REGISTER_ENCDEC (ASV2,              asv2);
        REGISTER_DECODER(AURA,              aura);
        REGISTER_DECODER(AURA2,             aura2);
        REGISTER_ENCDEC (AVRP,              avrp);
        REGISTER_DECODER(AVRN,              avrn);
        REGISTER_DECODER(AVS,               avs);
        REGISTER_ENCDEC (AVUI,              avui);
        REGISTER_ENCDEC (AYUV,              ayuv);
        ...
        REGISTER_ENCDEC (BMP,               bmp);
        ...
        REGISTER_ENCDEC (FLASHSV,           flashsv);
        ...
        REGISTER_ENCDEC (FLV,               flv);
        ...
        REGISTER_ENCDEC (GIF,               gif);
        ...
        REGISTER_DECODER(H264,              h264);
        ...
    #if FF_API_VDPAU
        REGISTER_DECODER(H264_VDPAU,        h264_vdpau);
    #endif
        REGISTER_ENCDEC (HAP,               hap);
        REGISTER_DECODER(HEVC,              hevc);
        ...
        REGISTER_ENCDEC (JPEG2000,          jpeg2000);
        ...
        REGISTER_DECODER(KMVC,              kmvc);
        ...
        REGISTER_ENCDEC (MJPEG,             mjpeg);
        ...
    #if FF_API_XVMC
        REGISTER_DECODER(MPEG_XVMC,         mpeg_xvmc);
    #endif /* FF_API_XVMC */
        REGISTER_ENCDEC (MPEG1VIDEO,        mpeg1video);
        ...
    #if FF_API_VDPAU
        REGISTER_DECODER(MPEG4_VDPAU,       mpeg4_vdpau);
    #endif
        REGISTER_DECODER(MPEGVIDEO,         mpegvideo);
    #if FF_API_VDPAU
        REGISTER_DECODER(MPEG_VDPAU,        mpeg_vdpau);
        REGISTER_DECODER(MPEG1_VDPAU,       mpeg1_vdpau);
    #endif
        ...
        REGISTER_DECODER(MPEG2_MEDIACODEC,  mpeg2_mediacodec);
        ...
        REGISTER_ENCDEC (PCX,               pcx);
        ...
        REGISTER_ENCDEC (RV10,              rv10);
        ...
        REGISTER_ENCDEC (SVQ1,              svq1);
        REGISTER_DECODER(SVQ3,              svq3);
        REGISTER_ENCDEC (TARGA,             targa);
        ...
        REGISTER_ENCDEC (V210,              v210);
        ...
    #if FF_API_VDPAU
        REGISTER_DECODER(VC1_VDPAU,         vc1_vdpau);
    #endif
        REGISTER_DECODER(VC1IMAGE,          vc1image);
        ...
        REGISTER_DECODER(VMDVIDEO,          vmdvideo);
        REGISTER_DECODER(VMNC,              vmnc);
        REGISTER_DECODER(VP3,               vp3);
        ...
        REGISTER_ENCDEC (WMV1,              wmv1);
        ...
    #if FF_API_VDPAU
        REGISTER_DECODER(WMV3_VDPAU,        wmv3_vdpau);
    #endif
        REGISTER_DECODER(WMV3IMAGE,         wmv3image);
        ...
        REGISTER_ENCDEC (YUV4,              yuv4);
        ...
    
        /* audio codecs */
        REGISTER_ENCDEC (AAC,               aac);
        REGISTER_DECODER(AAC_FIXED,         aac_fixed);
        REGISTER_DECODER(AAC_LATM,          aac_latm);
        REGISTER_ENCDEC (AC3,               ac3);
        ...
        REGISTER_DECODER(BMV_AUDIO,         bmv_audio);
        ...
        REGISTER_ENCDEC (FLAC,              flac);
        ...
        REGISTER_DECODER(MP3,               mp3);
        ...
        REGISTER_ENCDEC (WAVPACK,           wavpack);
        ...
    
        /* PCM codecs */
        ...
        REGISTER_ENCDEC (PCM_U8,            pcm_u8);
        ...
    
        /* DPCM codecs */
        REGISTER_DECODER(GREMLIN_DPCM,      gremlin_dpcm);
        ...
    
        /* ADPCM codecs */
        ...
        REGISTER_DECODER(ADPCM_IMA_AMV,     adpcm_ima_amv);
        REGISTER_DECODER(ADPCM_IMA_APC,     adpcm_ima_apc);
        ...
        REGISTER_ENCDEC (ADPCM_IMA_QT,      adpcm_ima_qt);
        REGISTER_DECODER(ADPCM_IMA_RAD,     adpcm_ima_rad);
        REGISTER_DECODER(ADPCM_IMA_SMJPEG,  adpcm_ima_smjpeg);
        REGISTER_ENCDEC (ADPCM_IMA_WAV,     adpcm_ima_wav);
        ...
        REGISTER_ENCDEC (ADPCM_SWF,         adpcm_swf);
        ...
    
        /* subtitles */
        REGISTER_ENCDEC (SSA,               ssa);
        REGISTER_ENCDEC (ASS,               ass);
        ...
        REGISTER_DECODER(REALTEXT,          realtext);
        ...
        REGISTER_ENCDEC (TEXT,              text);
        REGISTER_DECODER(VPLAYER,           vplayer);
        REGISTER_ENCDEC (WEBVTT,            webvtt);
        REGISTER_ENCDEC (XSUB,              xsub);
    
        /* external libraries */
        REGISTER_ENCDEC (AAC_AT,            aac_at);
        REGISTER_DECODER(AC3_AT,            ac3_at);
        ...
        REGISTER_DECODER(LIBRSVG,           librsvg);
        ...
        REGISTER_ENCODER(LIBX264RGB,        libx264rgb);
        ...
    
        /* text */
        REGISTER_DECODER(BINTEXT,           bintext);
        REGISTER_DECODER(XBIN,              xbin);
        REGISTER_DECODER(IDF,               idf);
    
        /* external libraries, that shouldn't be used by default if one of the
         * above is available */
        ...
        REGISTER_ENCODER(H264_VIDEOTOOLBOX, h264_videotoolbox);
    #if FF_API_NVENC_OLD_NAME
        REGISTER_ENCODER(NVENC,             nvenc);
        REGISTER_ENCODER(NVENC_H264,        nvenc_h264);
        REGISTER_ENCODER(NVENC_HEVC,        nvenc_hevc);
    #endif
        REGISTER_DECODER(HEVC_CUVID,        hevc_cuvid);
        REGISTER_DECODER(HEVC_MEDIACODEC,   hevc_mediacodec);
        ...
        REGISTER_DECODER(MPEG4_MEDIACODEC,  mpeg4_mediacodec);
        REGISTER_ENCODER(MPEG4_V4L2M2M,     mpeg4_v4l2m2m);
        ...
        REGISTER_DECODER(VP9_MEDIACODEC,    vp9_mediacodec);
        REGISTER_ENCODER(VP9_VAAPI,         vp9_vaapi);
    
        /* parsers */
        REGISTER_PARSER(AAC,                aac);
        ...
        REGISTER_PARSER(BMP,                bmp);
        ...
        REGISTER_PARSER(H264,               h264);
        REGISTER_PARSER(HEVC,               hevc);
        ...
        REGISTER_PARSER(MPEGVIDEO,          mpegvideo);
        ...
    }
    
    void avcodec_register_all(void)
    {
        static AVOnce control = AV_ONCE_INIT;
    
        // ff_thread_once的作用是保证register_all只会被调用一次
        ff_thread_once(&control, register_all);
    }
    
    

    libavfilter–allfilters.c

    /*
     * filter registration
     * Copyright (c) 2008 Vitor Sessak
     *
     * This file is part of FFmpeg.
     *
     * FFmpeg is free software; you can redistribute it and/or
     * modify it under the terms of the GNU Lesser General Public
     * License as published by the Free Software Foundation; either
     * version 2.1 of the License, or (at your option) any later version.
     *
     * FFmpeg is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * Lesser General Public License for more details.
     *
     * You should have received a copy of the GNU Lesser General Public
     * License along with FFmpeg; if not, write to the Free Software
     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     */
    
    #include "libavutil/thread.h"
    #include "avfilter.h"
    #include "config.h"
    #include "opencl_allkernels.h"
    
    
    /**
     * libavfilter->avfilter.c
     * 注册滤镜
     *
     * static AVFilter *first_filter;
     * static AVFilter **last_filter = &first_filter;
     *
     * int avfilter_register(AVFilter *filter)
     * {
     *     AVFilter **f = last_filter;
     *
     *     // the filter must select generic or internal exclusively
     *     av_assert0((filter->flags&AVFILTER_FLAG_SUPPORT_TIMELINE)!=AVFILTER_FLAG_SUPPORT_TIMELINE);
     *
     *     filter->next=NULL;
     *
     *     while(*f||avpriv_atomic_ptr_cas((void*volatile *)f,NULL,filter))
     *         f=&(*f)->next;
     *     last_filter=&filter->next;
     *
     *     return 0;
     * }
     */
    #define REGISTER_FILTER(X, x, y)                                        \
        {                                                                   \
            extern AVFilter ff_##y##_##x;                                   \
            if (CONFIG_##X##_FILTER)                                        \
                avfilter_register(&ff_##y##_##x);                           \
        }
    
    /**
     * 与上面相比,少了检查CONFIG的步骤
     */
    #define REGISTER_FILTER_UNCONDITIONAL(x)                                \
        {                                                                   \
            extern AVFilter ff_##x;                                         \
            avfilter_register(&ff_##x);                                     \
        }
    
    static void register_all(void)
    {
        REGISTER_FILTER(ABENCH,         abench,         af);
        REGISTER_FILTER(ACOMPRESSOR,    acompressor,    af);
        REGISTER_FILTER(ACOPY,          acopy,          af);
        REGISTER_FILTER(ACROSSFADE,     acrossfade,     af);
        REGISTER_FILTER(ACRUSHER,       acrusher,       af);
        REGISTER_FILTER(ADELAY,         adelay,         af);
        REGISTER_FILTER(AECHO,          aecho,          af);
        ...
        REGISTER_FILTER(AMERGE,         amerge,         af);
        REGISTER_FILTER(AMETADATA,      ametadata,      af);
        ...
        REGISTER_FILTER(AREALTIME,      arealtime,      af);
        ...
        REGISTER_FILTER(BANDPASS,       bandpass,       af);
        ...
        REGISTER_FILTER(CROSSFEED,      crossfeed,      af);
        ...
        REGISTER_FILTER(JOIN,           join,           af);
        ...
        REGISTER_FILTER(VOLUME,         volume,         af);
        ...
        REGISTER_FILTER(BENCH,          bench,          vf);
        ...
        REGISTER_FILTER(COPY,           copy,           vf);
        REGISTER_FILTER(COREIMAGE,      coreimage,      vf);
        REGISTER_FILTER(COVER_RECT,     cover_rect,     vf);
        REGISTER_FILTER(CROP,           crop,           vf);
        ...
        REGISTER_FILTER(DRAWBOX,        drawbox,        vf);
        REGISTER_FILTER(DRAWGRAPH,      drawgraph,      vf);
        REGISTER_FILTER(DRAWGRID,       drawgrid,       vf);
        REGISTER_FILTER(DRAWTEXT,       drawtext,       vf);
        ...
        REGISTER_FILTER(FORMAT,         format,         vf);
        ...
        REGISTER_FILTER(INFLATE,        inflate,        vf);
        ...
        ...
        REGISTER_FILTER(METADATA,       metadata,       vf);
        ...
        REGISTER_FILTER(NOISE,          noise,          vf);
        REGISTER_FILTER(NULL,           null,           vf);
        REGISTER_FILTER(OCR,            ocr,            vf);
        REGISTER_FILTER(OCV,            ocv,            vf);
        REGISTER_FILTER(OSCILLOSCOPE,   oscilloscope,   vf);
        REGISTER_FILTER(OVERLAY,        overlay,        vf);
        ...
        REGISTER_FILTER(RANDOM,         random,         vf);
        ...
        REGISTER_FILTER(REALTIME,       realtime,       vf);
        REGISTER_FILTER(REMAP,          remap,          vf);
        REGISTER_FILTER(REMOVEGRAIN,    removegrain,    vf);
        REGISTER_FILTER(REMOVELOGO,     removelogo,     vf);
        REGISTER_FILTER(REPEATFIELDS,   repeatfields,   vf);
        REGISTER_FILTER(REVERSE,        reverse,        vf);
        REGISTER_FILTER(ROBERTS,        roberts,        vf);
        REGISTER_FILTER(ROTATE,         rotate,         vf);
        REGISTER_FILTER(SAB,            sab,            vf);
        REGISTER_FILTER(SCALE,          scale,          vf);
        ...
        REGISTER_FILTER(SELECT,         select,         vf);
        ...
        REGISTER_FILTER(SUBTITLES,      subtitles,      vf);
        ...
        REGISTER_FILTER(TRIM,           trim,           vf);
        ...
        REGISTER_FILTER(VFLIP,          vflip,          vf);
        ...
        REGISTER_FILTER(ZSCALE,         zscale,         vf);
    
        REGISTER_FILTER(ALLRGB,         allrgb,         vsrc);
        REGISTER_FILTER(ALLYUV,         allyuv,         vsrc);
        REGISTER_FILTER(CELLAUTO,       cellauto,       vsrc);
        REGISTER_FILTER(COLOR,          color,          vsrc);
        ...
        REGISTER_FILTER(MPTESTSRC,      mptestsrc,      vsrc);
        REGISTER_FILTER(NULLSRC,        nullsrc,        vsrc);
        REGISTER_FILTER(RGBTESTSRC,     rgbtestsrc,     vsrc);
        ...
        REGISTER_FILTER(YUVTESTSRC,     yuvtestsrc,     vsrc);
    
        REGISTER_FILTER(NULLSINK,       nullsink,       vsink);
    
        /* multimedia filters */
        REGISTER_FILTER(ABITSCOPE,      abitscope,      avf);
        ...
        REGISTER_FILTER(CONCAT,         concat,         avf);
        ...
    
        /* multimedia sources */
        REGISTER_FILTER(AMOVIE,         amovie,         avsrc);
        REGISTER_FILTER(MOVIE,          movie,          avsrc);
    
        /* those filters are part of public or internal API => registered
         * unconditionally */
        REGISTER_FILTER_UNCONDITIONAL(asrc_abuffer);
        ...
        ff_opencl_register_filter_kernel_code_all();
    }
    
    void avfilter_register_all(void)
    {
        static AVOnce control = AV_ONCE_INIT;
    
        // ff_thread_once的作用是保证register_all只会被调用一次
        ff_thread_once(&control, register_all);
    }
    
    
    展开全文
  • MPU-6500 Register Map Descriptions Revision 寄存器 自己部分翻译
  • register实现基于verilog

    2011-05-17 16:05:30
    verilog编写的register文件
  • register变量

    2020-02-24 17:46:15
    Register修饰符暗示编译程序相应的变量将将被频繁使用,如果可能的话,应将其保存在CPU的寄存器中,以指加快其存取速度。但是,使用register修饰符有几点限制。 首先,register变量必须是能被CPU寄存器所接受的类型...

    Register修饰符暗示编译程序相应的变量将将被频繁使用,如果可能的话,应将其保存在CPU的寄存器中,以指加快其存取速度。但是,使用register修饰符有几点限制。 

        首先,register变量必须是能被CPU寄存器所接受的类型,这通常意味着register变量必须是一个单个的值,并且其长度应小於或等於整型的长度。但是,有些机器的寄存器也能存放浮点数。 

        其次,因为register变量可能不存放在内存中,所以不能用取址符运算符“ & ”来获取取址符运算符“ &” register变量的地址。如果你试图这样做,编译程序就会报告这是一个错误。 

        register变量修饰符的用处有多大还受其它一些规则的影响。因为寄存器的数量是有限的,而且某些寄存器只能接受特定类型的数据(如指针和浮点数),因此,真正能起作用的register修饰符的数目和类型都依赖於运行程序的机器,而任何多余的register修饰符都将被编译程序所忽略。 

        那麽,甚麽时候使用register变量修饰符呢?回答是,对现有的大多数编译程序来说,永远不要使用register变量修饰符。早期的C编译程序不会把变量保存在寄存器中,除非你命令它这样做,这时register变量修饰符是C语言的一种很有价值的补充。然而,随着编译程序设计技术的进步,在决定哪些变量应该被存到寄存器中时,现在的C编译程序能必程序员作出更好的决定。实际上,许多C编译程序会忽略register修饰符,因为尽管它完全合法,但它仅仅是暗示而不是命令。

    展开全文
  • Register.rar

    2014-05-05 20:22:40
    Register.rar java 注册
  • 1 av_register_all 1.1 基本信息 1.2函数声明 1.3源码 1.3.1 av_ register_all && av_register_input_format && av_register_output_format 1.3.2ff_thread_once 1.3.3av_format_init_nex...

    目录

    0 前言

    1 av_register_all

    1.1 基本信息

    1.2 函数声明

    1.3 源码

    1.3.1 av_ register_all && av_register_input_format && av_register_output_format

    1.3.2 ff_thread_once

    1.3.3 av_format_init_next

    1.3.4 avdevice_register_all

    2 新旧版本的av_register_all简单对比

     


    0 前言


    liavformat库是ffmpeg的多媒体容器,主要负责协议/解协议,封装/解封装。该库对外暴露3个头文件,分别是avformat.h,avio.h, version.h。

    • version.h :libavformat版本定义头文件,都是宏定义,包含libavformat的major,minor,micro版本的定义,以及可能会随主版本变化而消失的一些公共api接口宏定义;
    • avio.h:如名,是IO处理相关的头文件,包含重要的IO上下文结构体AVIOContext,目录相关结构体AVIODirContext,AVIODirEntry;以及IO处理相关的API函数,open,read,write,close,seek等等;
    • avformat.h:包含重要的结构体,封装上下文AVFormatContext,封装上下文内部结构体AVFormatInternal,输入文件格式结构体AVInputFormat,输出文件结构体AVOutputFormat,文件探测结构体AVProbeData,流结构体AVStream等等;以及封装相关处理API函数。

    本文以ffmpeg4.1的libavformat库为基础进行分析,ffmpeg4.1之前的版本请参考雷神的博客:ffmpeg 源代码简单分析 : av_register_all()

    1 av_register_all


    1.1 基本信息


    • 所属库: libavformat   
    • 头文件: avformat.h 
    • 源文件: allformat.c

    1.2 函数声明


    #if FF_API_NEXT
    /**
     * Initialize libavformat and register all the muxers, demuxers and
     * protocols. If you do not call this function, then you can select
     * exactly which formats you want to support.
     *
     * @see av_register_input_format()
     * @see av_register_output_format()
     */
    attribute_deprecated
    void av_register_all(void);
    
    attribute_deprecated
    void av_register_input_format(AVInputFormat *format);
    attribute_deprecated
    void av_register_output_format(AVOutputFormat *format);
    #endif

    从函数声明中可以获知以下信息:

    • 该函数会初始化libavformat并且注册所有的封装器,解封装器以及协议。
    • 并且在不调用av_register_all的情况下,可以通过使用av_register_input_format或者av_register_output_format精确选择某个需要支持的格式。但是注意一点:这3个函数源码是一摸一样的,也许是因为以后这些函数都要弃用,所以如此处理。
    • 函数定义在#if FF_API_NEXT .... #endif之间,而FF_API_NEXT是在version.h中定义,暗示了这之间定义的public api将会在未来的某个版本给drop掉。
    • 注意函数已经被标记为  attribute_deprecated,告知编译器函数已过时。关于FFMPEG中过时代码管理的分析见文章:FFMPEG过时代码管理 attribute_deprecated

    1.3 源码


    1.3.1 av_ register_all && av_register_input_format && av_register_output_format


    #if FF_API_NEXT
    FF_DISABLE_DEPRECATION_WARNINGS
    static AVOnce av_format_next_init = AV_ONCE_INIT;
    
    void av_register_all(void)
    {
        ff_thread_once(&av_format_next_init, av_format_init_next);
    }
    
    void av_register_input_format(AVInputFormat *format)
    {
        ff_thread_once(&av_format_next_init, av_format_init_next);
    }
    
    void av_register_output_format(AVOutputFormat *format)
    {
        ff_thread_once(&av_format_next_init, av_format_init_next);
    }
    FF_ENABLE_DEPRECATION_WARNINGS
    #endif

    查看源码,发掘以下几个信息:

    • 函数定义以FF_DISABLE_DEPRECATION_WARNINGS和FF_ENABLE_DEPRECATION_WARNINGS包围,这两个函数起到抑制编译器告警的作用,具体分析见文章:FFMPEG过时代码管理 attribute_deprecated
    • 后两个API的输入参数直接是被忽略的
    • 这三个函数均只调用了ff_thread_once(&av_format_next_init, av_format_init_next);
    • ff_thread_once的第一个参数定义为:static AVOnce av_format_next_init = AV_ONCE_INIT;  其类型AVOnce经过层层宏定义跳转发现为pthread_once_t,实质是void*;而其值AV_ONCE_INIT经过层层宏定义跳转之后发现为{0}。

    1.3.2 ff_thread_once


    • 所属库: libavutil
    • 头文件: thread.h
    • 源文件: ff_thread_once被定义为pthread_once
    • 功能说明:其实由函数的名称就可以知道,其保证在多线程的环境下,av_format_init_next只运行一次。ff_thread_once也是一个宏定义,其定义在libavutil\thread.h中,定义为pthread_once。
    #define ff_thread_once(control, routine) pthread_once(control, routine)
    • pthread_once:thread.h中根据平台不同引入不同的线程库,删减掉不必要的代码,引入库的顺序如下代码所示:发现优先使用pthread.h库->其次os2threads.h库->再次w32pthreads.h。pthread_once在不同的平台下映射到不同线程库中的pthread_once函数。
    #if HAVE_PTHREADS
    #include <pthread.h>
    #elif HAVE_OS2THREADS
    #include "compat/os2threads.h"
    #else
    #include "compat/w32pthreads.h"
    #endif
    • pthread_once:Windows Visual Studio环境下,使用的是w32pthreads库,其对pthread_once的定义如下
    static av_unused int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
    {
        BOOL pending = FALSE;
        InitOnceBeginInitialize(once_control, 0, &pending, NULL);
        if (pending)
            init_routine();
        InitOnceComplete(once_control, 0, NULL);
        return 0;
    }

    调用了Windows平台相关的函数InitOnceBeginInitialize和InitOnceComplete,来确保init_routine方法(在当前情况下是av_format_init_next方法)在多线程环境下只会被调用一次,至于InitOnceBeginInitialize和InitOnceComplete如何保证这一点的,可以查阅微软的开发说明文档:InitOnceComplete function以及InitOnceBeginInitialize function

    • 小测试:看看反复调用pthread_once,init_routine将会被调用几次
    #include <windows.h>
    #include <process.h>
    #include <stdio.h>
    
    static int count = 0;
    
    static void init_routine() {
    	count++;
    }
    
    static int pthread_once(LPINIT_ONCE once_control, void(*init_routine)(void))
    {
    	BOOL pending = FALSE;
    	InitOnceBeginInitialize(once_control, 0, &pending, NULL);
    	if (pending)
    		add_count();
    	InitOnceComplete(once_control, 0, NULL);
    	return 0;
    }
    
    int main(int argc, char* argv[]) {
    	void* once = 0;
    	LPINIT_ONCE once_control = (LPINIT_ONCE)&once;
    
    	printf("before once_control:%d  and count:%d\n", *once_control, count);
    
    	pthread_once(once_control, init_routine);
        printf("after1 once_control:%d and count:%d\n", *once_control, count);
    
    	pthread_once(once_control, init_routine);
    	pthread_once(once_control, init_routine);
    	printf("after2 once_control:%d and count:%d\n", *once_control, count);
    
    	getchar();
    	return 0;
    }
    

    结果如下:可以看见,在执行一次pthread_once后,once_control 已经变为2,init_routine执行一次,count自增1。后续不论调用几次pthread_once,once_control不变,init_routine也不会被执行。当然此处最好是让后续两次pthread_once的执行放在线程中来做,模拟并发的情况。

    1.3.3 av_format_init_next


    • 所属库:libavformat
    • 头文件:无,静态函数
    • 源文件:allformat.c
    static void av_format_init_next(void)
    {
        AVOutputFormat *prevout = NULL, *out;
        AVInputFormat *previn = NULL, *in;
    
        ff_mutex_lock(&avpriv_register_devices_mutex);
    
        for (int i = 0; (out = (AVOutputFormat*)muxer_list[i]); i++) {
            if (prevout)
                prevout->next = out;
            prevout = out;
        }
    
        if (outdev_list) {
            for (int i = 0; (out = (AVOutputFormat*)outdev_list[i]); i++) {
                if (prevout)
                    prevout->next = out;
                prevout = out;
            }
        }
    
        for (int i = 0; (in = (AVInputFormat*)demuxer_list[i]); i++) {
            if (previn)
                previn->next = in;
            previn = in;
        }
    
        if (indev_list) {
            for (int i = 0; (in = (AVInputFormat*)indev_list[i]); i++) {
                if (previn)
                    previn->next = in;
                previn = in;
            }
        }
    
        ff_mutex_unlock(&avpriv_register_devices_mutex);
    }
    
    

    不难看出,该函数的作用就是将muxer_list中的输出封装结构AVOutputFormat挨个串起来形成单向链表,当outdev_list不为空的时候,同时将outdev_list中的AVOutputFormat也一并串在后头。同理将demuxer_list中的输入封装结构体AVInputFormat挨个穿起来形成单向链表,同时在indev_list不为空的时候,将indev_list中的AVInputFormat也一并串起来挂在后头。逻辑相当简单,但有以下几个需要注意的地方:

    1.  为了使该函数并发安全,进行了上锁处理,主要逻辑处于 ff_mutex_lock(&avpriv_register_devices_mutex); 与ff_mutex_unlock(&avpriv_register_devices_mutex);之间。avpriv_register_devices_mutex定义为
      static AVMutex avpriv_register_devices_mutex = AV_MUTEX_INITIALIZER;

      AVMutex是个宏定义,追踪其定义为 #define AVMutex pthread_mutex_t,该语句在libavutil/thread.h中,其与上文所述的ptread_once函数一样,对于不同的平台使用不同的线程库,映射到相应的逻辑上去,此处不再赘述。对于该锁的初始化值AV_MUTEX_INITIALIZER,追踪其定义为{0}。

    2. muxer_list和demuxer_list为两个大的静态数组,前者位于libavformat/muxer_list.c源文件中,后者位于libavformat/demuxer_list.c源文件中。具体内容如下所示:
      static const AVOutputFormat *muxer_list[] = {
          &ff_a64_muxer,
          此处省略几十上百行...
          &ff_yuv4mpegpipe_muxer,
          NULL };
      
      static const AVInputFormat *demuxer_list[] = {
          &ff_aa_demuxer,
          此处省略几十上百行...
          &ff_libmodplug_demuxer,
          NULL };

       

    3. muxer_list的单个元素进行简要分析,以ff_adts_muxer封装器为例:首先,ff_adts_muxer定义在libavformat/adtsenc.c源文件中,注意源文件命名规则,一般都是"format+enc".c;当然也会有例外,好几个功能类似封装放一个.c源文件中,并以类似的这个"功能+enc".c来命名源文件,比如ff_ac3_muxer,ff_adx_muxer等都在libavformat/rawenc.c中。其次ff_adts_muxer的类型为AVOutputFormat,对于AVOutputFormat类的分析将在其他文章中体现,查看下ff_adts_muxer对象的定义如下,将音频数据封装成adts格式所必要的字段都进行了初始化,尤其是最后的几个函数指针adts_init,adts_write_header,adts_write_packet,adts_write_trailer都在同一文件中定义。
      AVOutputFormat ff_adts_muxer = {
          .name              = "adts",  
          .long_name         = NULL_IF_CONFIG_SMALL("ADTS AAC (Advanced Audio Coding)"),
          .mime_type         = "audio/aac",
          .extensions        = "aac,adts",
          .priv_data_size    = sizeof(ADTSContext),
          .audio_codec       = AV_CODEC_ID_AAC,
          .video_codec       = AV_CODEC_ID_NONE,
          .init              = adts_init,
          .write_header      = adts_write_header,
          .write_packet      = adts_write_packet,
          .write_trailer     = adts_write_trailer,
          .priv_class        = &adts_muxer_class,
          .flags             = AVFMT_NOTIMESTAMPS,
      };
    4. demuxer_list中单个元素进行简要分析,以ff_aac_demuxer解封装器为例:首先,ff_aac_demuxer定义在libavformat/aacdec.c源文件中,文件名命名形式“format+dec”.c;也有以format.c形式命名的。其次,ff_aac_demuxer类型为AVInputFormat,同理对AVInputFormat结构体的分析将在其他文章中做专门的解析。查看ff_aac_demuxer源码定义如下,注意adts_aac_probe,adts_aac_read_header,adts_aac_read_packet几个函数的定义也在同一文件中。
      AVInputFormat ff_aac_demuxer = {
          .name         = "aac",
          .long_name    = NULL_IF_CONFIG_SMALL("raw ADTS AAC (Advanced Audio Coding)"),
          .read_probe   = adts_aac_probe,
          .read_header  = adts_aac_read_header,
          .read_packet  = adts_aac_read_packet,
          .flags        = AVFMT_GENERIC_INDEX,
          .extensions   = "aac",
          .mime_type    = "audio/aac,audio/aacp,audio/x-aac",
          .raw_codec_id = AV_CODEC_ID_AAC,
      };
    5. outdev_list && indev_list的定义同样在allformat.c,如下源码所示:
      static const AVInputFormat * const *indev_list = NULL;
      static const AVOutputFormat * const *outdev_list = NULL;

      一开始对这个很有疑惑,因为二者皆为空,后来发现allformat.c文件中最后有一个函数avpriv_register_devices,由名称就可知该函数不是public api,应该是供ffmpeg内部调用,查看其声明的头文件,为libavformat/internal.h。

      void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[])
      {
          ff_mutex_lock(&avpriv_register_devices_mutex);
          outdev_list = o;
          indev_list = i;
          ff_mutex_unlock(&avpriv_register_devices_mutex);
      #if FF_API_NEXT
          av_format_init_next();
      #endif
      }
      

      这下就清楚了,原来这两个列表是由外部来进行初始化的,由于是输入输出设备列表,因此avpriv_register_devices很可能libavdevice库进行调用。搜索avpriv_register_devices在源码中的引用,发现其唯一被调用的位置在libavdevice/alldevice.c的avdevice_register_all函数中

      void avdevice_register_all(void)
      {
          avpriv_register_devices(outdev_list, indev_list);
      }

       

    1.3.4 avdevice_register_all


    • 所属库:libavdevice
    • 头文件:avdevice.h
    • 源文件:  alldevices.c
    • 函数声明:
      /**
       * Initialize libavdevice and register all the input and output devices.
       * 初始化libavdevice和注册所有输入输出设备
       */
      void avdevice_register_all(void);
    • 源码:avdevice_register_all代码很简单,就只有一行,即调用libavformat/allfomats.c文件中的avpriv_register_devices函数将outdev_list和indev_list注入进去,并启动了av_register_all的工作。
      void avdevice_register_all(void)
      {
          avpriv_register_devices(outdev_list, indev_list);
      }

      来查看下outdev_list和indev_list都有什么:

    1.  outdev_list定义在libavdevice/outdev_list.c,indev_list定义在libavdevice/indev_list.c。如此就不对列表中的单个项进行解释了,因为都是AVInputFormat和AVOutputFormat结构体对象。

      static const AVOutputFormat *outdev_list[] = {
          &ff_opengl_muxer,  // opengl渲染
          &ff_sdl2_muxer,    // sdl渲染
          NULL };
      
      static const AVInputFormat *indev_list[] = {
          &ff_dshow_demuxer,    // directshow采集
          &ff_gdigrab_demuxer,  // gdi采集
          &ff_lavfi_demuxer,    // lav filter ffmpeg滤镜
          &ff_vfwcap_demuxer,   // video for windows capture
          &ff_libcdio_demuxer,  // CD-ROM and CD image 
          NULL };

    2 新旧版本的av_register_all简单对比


    旧版本中,av_register_all几乎是所有ffmpeg程序的开端,因为其初始化了所有的协议/解协议,输入/输出设备,封装/解封装器,编码器/解码器,硬件加速器,Parser,Bitstream Filter等等。而ffmpeg4.1中的av_register_all中却只简单的初始化了封装/解封装器,并且av_register_all还被标记为deprecated,那么就很让人好奇之前av_register_all的工作都由谁分担去做了?在没有av_register_all的ffmpeg程序的开端应该是个什么流程?(未完待续)

    疑问点一:协议/解协议的初始化代码在哪儿?

    疑问点二:解码器/编码器的初始化代码在哪儿?

    疑问点三:硬件加速器,Parse,Bitstream Filter初始化代码在哪儿?

    展开全文
  • babel-register-esm 适用于Babel的ESM加载程序,类似于@ babel / register。 它将根据您的“ babelrc”配置文件即时转换您的文件。 有关Node.js ESM加载程序的更多信息,请参见。 安装 npm install babel-register...
  • linux register_chrdev函数解析

    千次阅读 2019-06-24 16:37:56
    register_chrdev大致作用:向内核注册cdev结构体,当在用户空间打开设备文件时内核可以根据设备号快速定位此设备文件的cdev->file_operations结构体,从而调用驱动底层的open,close,read,write,ioctl等函数,当我们...
  • register关键字的使用

    2020-09-04 00:57:18
    前言 本文用简单代码实验介绍register关键字的使用。 上代码 #include int main(void) { int i; int tmp = 0; for (i=1; i; i++) { tmp++; printf("tmp = %d\n", tmp); printf("&i = %d\n\n", &i); } ...
  • 没有找到DLLRegisterServer输入点,无法注册-dnzg.cn.bat
  • Register File is a large structure in the contemporary microprocessors and its access time and energy dissipation is significant compared to other components. Number of registers used in current ...
  • MPU-6000 and MPU-6050寄存器描述。
  • Caller-saved register and Callee-saved register

    千次阅读 2019-11-19 14:55:32
    Caller-saved register(又名易失性寄存器AKA volatile registers, or call-clobbered)用于保存不需要在各个调用之间保留的临时数量。 因此,如果要在过程调用后恢复该值,则调用方有责任将这些寄存器压入堆栈或将...
  • C++ register关键字作用

    千次阅读 2019-09-09 17:11:10
    register 关键字作用 register用来声明变量,然后声明出来的变量是直接放在cpu的寄存器当中,而非就是通过内存寻址访问,这样效率更高。 示例代码: #include "stdafx.h" using namespace std; int _tmain...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 763,839
精华内容 305,535
关键字:

register