• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            蝸牛的家
            男兒當(dāng)自強(qiáng)
            posts - 48,  comments - 21,  trackbacks - 0
                 摘要: UML基礎(chǔ)知識(shí)   UML簡介 在80年代末至90年代中,對(duì)面向?qū)ο蠓治雠c設(shè)計(jì)方法的研究發(fā)展到一個(gè)高潮。但是,諸多流派在思想和術(shù)語上有很多不同的提法,在術(shù)語、概念上的運(yùn)用也各不相同,需要一種統(tǒng)一的符號(hào)來描述面向?qū)ο蟮姆治龊驮O(shè)計(jì)活動(dòng)。UML應(yīng)運(yùn)而生。它不僅統(tǒng)一了Booch、Rumbaugh和Jacobson的表示方法,而且有進(jìn)一步的發(fā)展,最終成為大眾所共同接受的標(biāo)準(zhǔn)建模語言。統(tǒng)一建模...  閱讀全文
            posted @ 2011-04-27 14:24 黑色天使 閱讀(1238) | 評(píng)論 (0)編輯 收藏
            所謂Lambda,簡單的說是快速的小函數(shù)生成.
            在STL的算法中很多地方需要提供一個(gè)函數(shù)對(duì)象或仿函數(shù)如for_each
            for_each(v.begin(), v.end(), op());    //原格式如此
            如果需要不用的算法就需要些不同的函數(shù)對(duì)象,但是引用了萬能的lambda后效果就不同了,效果如下
            for_each(v.begin(), v.end(), _1=2);    //_1=2是一個(gè)仿函數(shù),通過重載=實(shí)現(xiàn)
            需要的操作一目了然,簡單分析下for_each第三個(gè)參數(shù)需要的是一個(gè)函數(shù)或仿函數(shù),所以_1=2必然產(chǎn)生的是一個(gè)仿函數(shù),大致可以推出是重載了=實(shí)現(xiàn)的產(chǎn)生仿函數(shù),那么真正的操作還需要一個(gè)封裝,即需要兩個(gè)類實(shí)現(xiàn),第一個(gè)類大致如下
            struct place_holder
            {
                
            //重載需要的算法操作
                template <typename R>
                op
            <R> operator=(R i)
                {
                    
            return op<R>(i);
                }
            };
            模板使得這個(gè)結(jié)構(gòu)可以傳入任何類型的參數(shù),通過重載=操作內(nèi)部返回了一個(gè)仿函數(shù),具體的操作由一下的仿函數(shù)實(shí)現(xiàn)
            //仿函數(shù),即重載了()操作的類
            template <typename T>
            struct op
            {
                op(T i): _i(i) {}
                T 
            operator()(T &i)
                {
                    
            return i = _i;
                }
                T _i;
            };
            這個(gè)仿函數(shù)將傳入的引用參數(shù)進(jìn)行了賦值操作,實(shí)現(xiàn)了最終的操作.
            以上的代碼實(shí)現(xiàn)=操作如果需要其他操作則重載相應(yīng)的操作例如+=
            依次類推占位類實(shí)現(xiàn)+=并通過仿函數(shù)可以實(shí)現(xiàn)+=的操作以下是完成的代碼
            // lambda.cpp : 定義控制臺(tái)應(yīng)用程序的入口點(diǎn)。
            //

            #include 
            "stdafx.h"
            #include 
            <vector>
            #include 
            <algorithm>

            using namespace std;

            //仿函數(shù),即重載了()操作的類
            template <typename T>
            struct op
            {
                op(T i): _i(i) {}
                T 
            operator()(T &i)
                {
                    
            return i = _i;
                }
                T _i;
            };
            template 
            <typename T>
            struct op1
            {
                op1(T i):_i(i){}
                T 
            operator()(T &i)
                {
                    
            return i + _i;
                }
                T _i;
            };

            //占位符
            struct place_holder
            {
                
            //重載需要的算法操作
                template <typename R>
                op
            <R> operator=(R i)
                {
                    
            return op<R>(i);
                }
                template 
            <typename R>
                op1
            <R> operator+=(R i)
                {
                    
            return op1<R>(i);
                }
            };

            place_holder _1;

            int _tmain(int argc, _TCHAR* argv[])
            {
                vector
            <int> v;
                v.push_back(
            1);
                v.push_back(
            2);
                v.push_back(
            3);

                
            //for_each(v.begin(), v.end(), op());    //原格式如此
                for_each(v.begin(), v.end(), _1=2);    //_1=2是一個(gè)仿函數(shù),通過重載=實(shí)現(xiàn)

                
            return 0;
            }


            posted @ 2011-03-22 23:47 黑色天使 閱讀(705) | 評(píng)論 (0)編輯 收藏
            #include "stdafx.h"
            #include 
            <algorithm>
            #include 
            <iostream>
            #include 
            <string>
            #include 
            <vector>

            using namespace std;

            struct Person
            {
                Person(
            const string& name)
                    : name_(name)
                {}

                
            string Name()
                {
                    
            return name_;
                }

                
            void SetName(string name)
                {
                    name_ 
            = name;
                }

                
            string name_;
            };

            template 
            <typename R, typename T, typename Arg>
            class simple_binder
            {
            public:
                
            explicit simple_binder(R (T::*pfn)(Arg), const Arg& arg)
                    : pfn_(pfn)
                    , arg_(arg)
                {}

                R 
            operator()(T& t)
                {
                    
            return (t.*pfn_)(arg_);
                }
            private:
                R (T::
            *pfn_)(Arg);
                Arg arg_;
            };

            template 
            <typename R, typename T, typename Arg>
            simple_binder
            <R, T, Arg>
            simple_bind( R (T::
            *pfn)(Arg), const Arg& arg)
            {
                
            return simple_binder<R, T, Arg>(pfn, arg);
            }

            int main()
            {
                Person person(
            "Ralph");

                
            //smimple_bind生成一個(gè)仿函數(shù)類,這個(gè)類構(gòu)造時(shí)賦值了arg
                
            //遇到(person)時(shí),調(diào)用這個(gè)仿函數(shù)類重載的()操作即
                
            //t.*pfn(arg)
                
            //又回歸為一個(gè)函數(shù),不過參數(shù)可以自己控制了,娃哈哈
                simple_bind(&Person::SetName, string("Martin"))(person);
                cout 
            << person.Name() << endl;
            }

            posted @ 2011-03-22 23:46 黑色天使 閱讀(963) | 評(píng)論 (0)編輯 收藏

            計(jì)算機(jī)彩色顯示器顯示色彩的原理與彩色電視機(jī)一樣,都是采用R(Red)、G(Green)、B(Blue)相加混色的原理:通過發(fā)射出三種不同強(qiáng)度的電子束,使屏幕內(nèi)側(cè)覆蓋的紅、綠、藍(lán)磷光材料發(fā)光而產(chǎn)生色彩。這種色彩的表示方法稱為RGB色彩空間表示(它也是多媒體計(jì)算機(jī)技術(shù)中用得最多的一種色彩空間表示方法)。
            根據(jù)三基色原理,任意一種色光F都可以用不同分量的R、G、B三色相加混合而成。

            F = r [ R ] + g [ G ] + b [ B ]

            其中,r、g、b分別為三基色參與混合的系數(shù)。當(dāng)三基色分量都為0(最弱)時(shí)混合為黑色光;而當(dāng)三基色分量都為k(最強(qiáng))時(shí)混合為白色光。調(diào)整r、g、b三個(gè)系數(shù)的值,可以混合出介于黑色光和白色光之間的各種各樣的色光。
            那么YUV又從何而來呢?在現(xiàn)代彩色電視系統(tǒng)中,通常采用三管彩色攝像機(jī)或彩色CCD攝像機(jī)進(jìn)行攝像,然后把攝得的彩色圖像信號(hào)經(jīng)分色、分別放大校正后得到RGB,再經(jīng)過矩陣變換電路得到亮度信號(hào)Y和兩個(gè)色差信號(hào)R-Y(即U)、B-Y(即V),最后發(fā)送端將亮度和色差三個(gè)信號(hào)分別進(jìn)行編碼,用同一信道發(fā)送出去。這種色彩的表示方法就是所謂的YUV色彩空間表示。
            采用YUV色彩空間的重要性是它的亮度信號(hào)Y和色度信號(hào)U、V是分離的。如果只有Y信號(hào)分量而沒有U、V分量,那么這樣表示的圖像就是黑白灰度圖像。彩色電視采用YUV空間正是為了用亮度信號(hào)Y解決彩色電視機(jī)與黑白電視機(jī)的兼容問題,使黑白電視機(jī)也能接收彩色電視信號(hào)。
            YUV與RGB相互轉(zhuǎn)換的公式如下(RGB取值范圍均為0-255):

            Y = 0.299R + 0.587G + 0.114B
            U = -0.147R - 0.289G + 0.436B
            V = 0.615R - 0.515G - 0.100B

            R = Y + 1.14V
            G = Y - 0.39U - 0.58V
            B = Y + 2.03U

            在DirectShow中,常見的RGB格式有RGB1、RGB4、RGB8、RGB565、RGB555、RGB24、RGB32、ARGB32等;常見的YUV格式有YUY2、YUYV、YVYU、UYVY、AYUV、Y41P、Y411、Y211、IF09、IYUV、YV12、YVU9、 YUV411、YUV420等。作為視頻媒體類型的輔助說明類型(Subtype),它們對(duì)應(yīng)的GUID見表2.3。

            表2.3 常見的RGB和YUV格式

            GUID    格式描述
            MEDIASUBTYPE_RGB1    2色,每個(gè)像素用1位表示,需要調(diào)色板
            MEDIASUBTYPE_RGB4    16色,每個(gè)像素用4位表示,需要調(diào)色板
            MEDIASUBTYPE_RGB8    256色,每個(gè)像素用8位表示,需要調(diào)色板
            MEDIASUBTYPE_RGB565    每個(gè)像素用16位表示,RGB分量分別使用5位、6位、5位
            MEDIASUBTYPE_RGB555    每個(gè)像素用16位表示,RGB分量都使用5位(剩下的1位不用)
            MEDIASUBTYPE_RGB24    每個(gè)像素用24位表示,RGB分量各使用8位
            MEDIASUBTYPE_RGB32    每個(gè)像素用32位表示,RGB分量各使用8位(剩下的8位不用)
            MEDIASUBTYPE_ARGB32    每個(gè)像素用32位表示,RGB分量各使用8位(剩下的8位用于表示Alpha通道值)
            MEDIASUBTYPE_YUY2    YUY2格式,以4:2:2方式打包
            MEDIASUBTYPE_YUYV    YUYV格式(實(shí)際格式與YUY2相同)
            MEDIASUBTYPE_YVYU    YVYU格式,以4:2:2方式打包
            MEDIASUBTYPE_UYVY    UYVY格式,以4:2:2方式打包
            MEDIASUBTYPE_AYUV    帶Alpha通道的4:4:4 YUV格式
            MEDIASUBTYPE_Y41P    Y41P格式,以4:1:1方式打包
            MEDIASUBTYPE_Y411    Y411格式(實(shí)際格式與Y41P相同)
            MEDIASUBTYPE_Y211    Y211格式
            MEDIASUBTYPE_IF09    IF09格式
            MEDIASUBTYPE_IYUV    IYUV格式
            MEDIASUBTYPE_YV12    YV12格式
            MEDIASUBTYPE_YVU9    YVU9格式

            下面分別介紹各種RGB格式。

            ¨RGB1、RGB4、RGB8都是調(diào)色板類型的RGB格式,在描述這些媒體類型的格式細(xì)節(jié)時(shí),通常會(huì)在BITMAPINFOHEADER數(shù)據(jù)結(jié)構(gòu)后面跟著一個(gè)調(diào)色板(定義一系列顏色)。它們的圖像數(shù)據(jù)并不是真正的顏色值,而是當(dāng)前像素顏色值在調(diào)色板中的索引。以RGB1(2色位圖)為例,比如它的調(diào)色板中定義的兩種顏色值依次為0x000000(黑色)和0xFFFFFF(白色),那么圖像數(shù)據(jù)001101010111…(每個(gè)像素用1位表示)表示對(duì)應(yīng)各像素的顏色為:黑黑白白黑白黑白黑白白白…。

            ¨ RGB565使用16位表示一個(gè)像素,這16位中的5位用于R,6位用于G,5位用于B。程序中通常使用一個(gè)字(WORD,一個(gè)字等于兩個(gè)字節(jié))來操作一個(gè)像素。當(dāng)讀出一個(gè)像素后,這個(gè)字的各個(gè)位意義如下:
            高字節(jié)              低字節(jié)
            R R R R R G G G     G G G B B B B B
            可以組合使用屏蔽字和移位操作來得到RGB各分量的值:

            #define RGB565_MASK_RED    0xF800
            #define RGB565_MASK_GREEN  0x07E0
            #define RGB565_MASK_BLUE   0x001F
            R = (wPixel & RGB565_MASK_RED) >> 11;   // 取值范圍0-31
            G = (wPixel & RGB565_MASK_GREEN) >> 5;  // 取值范圍0-63
            B =  wPixel & RGB565_MASK_BLUE;         // 取值范圍0-31

            ¨ RGB555是另一種16位的RGB格式,RGB分量都用5位表示(剩下的1位不用)。使用一個(gè)字讀出一個(gè)像素后,這個(gè)字的各個(gè)位意義如下:
            高字節(jié)             低字節(jié)
            X R R R R G G       G G G B B B B B       (X表示不用,可以忽略)
            可以組合使用屏蔽字和移位操作來得到RGB各分量的值:

            #define RGB555_MASK_RED    0x7C00
            #define RGB555_MASK_GREEN  0x03E0
            #define RGB555_MASK_BLUE   0x001F
            R = (wPixel & RGB555_MASK_RED) >> 10;   // 取值范圍0-31
            G = (wPixel & RGB555_MASK_GREEN) >> 5;  // 取值范圍0-31
            B =  wPixel & RGB555_MASK_BLUE;         // 取值范圍0-31

            ¨ RGB24使用24位來表示一個(gè)像素,RGB分量都用8位表示,取值范圍為0-255。注意在內(nèi)存中RGB各分量的排列順序?yàn)椋築GR BGR BGR…。通常可以使用RGBTRIPLE數(shù)據(jù)結(jié)構(gòu)來操作一個(gè)像素,它的定義為:

            typedef struct tagRGBTRIPLE {
            BYTE rgbtBlue;    // 藍(lán)色分量
            BYTE rgbtGreen;   // 綠色分量
            BYTE rgbtRed;     // 紅色分量
            } RGBTRIPLE;

            ¨ RGB32使用32位來表示一個(gè)像素,RGB分量各用去8位,剩下的8位用作Alpha通道或者不用。(ARGB32就是帶Alpha通道的 RGB32。)注意在內(nèi)存中RGB各分量的排列順序?yàn)椋築GRA BGRABGRA…。通常可以使用RGBQUAD數(shù)據(jù)結(jié)構(gòu)來操作一個(gè)像素,它的定義為:

            typedef struct tagRGBQUAD {
            BYTE    rgbBlue;      // 藍(lán)色分量
            BYTE    rgbGreen;     // 綠色分量
            BYTE    rgbRed;       // 紅色分量
            BYTE    rgbReserved;  // 保留字節(jié)(用作Alpha通道或忽略)
            } RGBQUAD;

            下面介紹各種YUV格式。YUV格式通常有兩大類:打包(packed)格式和平面(planar)格式。前者將YUV分量存放在同一個(gè)數(shù)組中,通常是幾個(gè)相鄰的像素組成一個(gè)宏像素(macro-pixel);而后者使用三個(gè)數(shù)組分開存放YUV三個(gè)分量,就像是一個(gè)三維平面一樣。表2.3中的YUY2到 Y211都是打包格式,而IF09到Y(jié)VU9都是平面格式。(注意:在介紹各種具體格式時(shí),YUV各分量都會(huì)帶有下標(biāo),如Y0、U0、V0表示第一個(gè)像素的YUV分量,Y1、U1、V1表示第二個(gè)像素的YUV分量,以此類推。)

            ¨ YUY2(和YUYV)格式為每個(gè)像素保留Y分量,而UV分量在水平方向上每兩個(gè)像素采樣一次。一個(gè)宏像素為4個(gè)字節(jié),實(shí)際表示2個(gè)像素。(4:2:2的意思為一個(gè)宏像素中有4個(gè)Y分量、2個(gè)U分量和2個(gè)V分量。)圖像數(shù)據(jù)中YUV分量排列順序如下:
            Y0 U0 Y1 V0    Y2 U2 Y3 V2 …

            ¨ YVYU格式跟YUY2類似,只是圖像數(shù)據(jù)中YUV分量的排列順序有所不同:
            Y0 V0 Y1 U0    Y2 V2 Y3 U2 …

            ¨ UYVY格式跟YUY2類似,只是圖像數(shù)據(jù)中YUV分量的排列順序有所不同:
            U0 Y0 V0 Y1    U2 Y2 V2 Y3 …

            ¨ AYUV格式帶有一個(gè)Alpha通道,并且為每個(gè)像素都提取YUV分量,圖像數(shù)據(jù)格式如下:
            A0 Y0 U0 V0    A1 Y1 U1 V1 …

            ¨ Y41P(和Y411)格式為每個(gè)像素保留Y分量,而UV分量在水平方向上每4個(gè)像素采樣一次。一個(gè)宏像素為12個(gè)字節(jié),實(shí)際表示8個(gè)像素。圖像數(shù)據(jù)中YUV分量排列順序如下:
            U0 Y0 V0 Y1    U4 Y2 V4 Y3    Y4 Y5 Y6 Y8 …

            ¨ Y211格式在水平方向上Y分量每2個(gè)像素采樣一次,而UV分量每4個(gè)像素采樣一次。一個(gè)宏像素為4個(gè)字節(jié),實(shí)際表示4個(gè)像素。圖像數(shù)據(jù)中YUV分量排列順序如下:
            Y0 U0 Y2 V0    Y4 U4 Y6 V4 …

            ¨ YVU9格式為每個(gè)像素都提取Y分量,而在UV分量的提取時(shí),首先將圖像分成若干個(gè)4 x 4的宏塊,然后每個(gè)宏塊提取一個(gè)U分量和一個(gè)V分量。圖像數(shù)據(jù)存儲(chǔ)時(shí),首先是整幅圖像的Y分量數(shù)組,然后就跟著U分量數(shù)組,以及V分量數(shù)組。IF09格式與YVU9類似。

            ¨ IYUV格式為每個(gè)像素都提取Y分量,而在UV分量的提取時(shí),首先將圖像分成若干個(gè)2 x 2的宏塊,然后每個(gè)宏塊提取一個(gè)U分量和一個(gè)V分量。YV12格式與IYUV類似。

            ¨YUV411、YUV420格式多見于DV數(shù)據(jù)中,前者用于NTSC制,后者用于PAL制。YUV411為每個(gè)像素都提取Y分量,而UV分量在水平方向上每4個(gè)像素采樣一次。YUV420并非V分量采樣為0,而是跟YUV411相比,在水平方向上提高一倍色差采樣頻率,在垂直方向上以U/V間隔的方式減小一半色差采樣。

            //YUV轉(zhuǎn)UYVY格式
            void YUVtoUYVY(uint8_t *y_plane, uint8_t *u_plane, uint8_t *v_plane, int y_stride, 
                                  
            int uv_stride, OUT uint8_t *pDstBuf, int width, int height)
            {
                
            for (int row = 0; row < height; row = row + 1{
                    
            for (int col = 0; col < width; col=col + 2{
                        pDstBuf[
            0= u_plane[row/2 * uv_stride + col/2];
                        pDstBuf[
            1= y_plane[row * y_stride + col];
                        pDstBuf[
            2= v_plane[row/2 * uv_stride + col/2];
                        pDstBuf[
            3= y_plane[row * y_stride + col + 1];
                        pDstBuf 
            += 4;
                    }

                }

            }

            posted @ 2009-07-07 18:19 黑色天使 閱讀(6689) | 評(píng)論 (0)編輯 收藏
            RTPSession
                  對(duì)于大多數(shù)的RTP應(yīng)用程序,RTPSession類可能是JRTPLIB唯一使用的類。它能完全處理RTCP部份的數(shù)據(jù)包,所以用戶可以把精力集中在真正的數(shù)據(jù)收發(fā)。
                  要知道RTPSession類在多線程下并不是安全的,因此,用戶要通過某些鎖同步機(jī)制來保證不會(huì)出現(xiàn)在不同線程當(dāng)中調(diào)用同一個(gè)RTPSession實(shí)例。
                  RTPSession類有如下的接口。

                  • RTPSession(RTPTransmitter::TransmissionProtocol proto = RTPTransmitter::IPv4UDPProto)
                  使用proto類型傳輸層創(chuàng)建一個(gè)PRTSession實(shí)例。如果proto使用用戶自定義(user-defined)傳輸層,則相應(yīng)的NewUserDefinedTransmitter()函數(shù)必須實(shí)現(xiàn)。ps:這里默認(rèn)就行了,默認(rèn)就是IPV4網(wǎng)絡(luò)。

                  • int Create(const RTPSessionParams &sessparams, const RTPTransmissionParams*transparams = 0)
                  使用RTPSession參數(shù)sessparams和RTPTransmission參數(shù)transparams 真正創(chuàng)建一個(gè)RTP會(huì)話。如果transparams 為NULL,則使用默認(rèn)的參數(shù)。ps:RTPSessionParams 我們可能要設(shè)得比較多,RTPTransmissionParams參數(shù)就只要設(shè)置其中的端口就行了,端口一定要設(shè)對(duì),不然進(jìn)行組播時(shí),這個(gè)進(jìn)程將不接收數(shù)據(jù)。設(shè)置方式可以看example.cpp。

                  • void Destroy()
                  離開一個(gè)會(huì)話但不向其它組成員發(fā)送BYE包。ps:我不推薦用這個(gè)函數(shù)除非是錯(cuò)誤處理,正常離開我們應(yīng)該用ByeDestroy()。
                  
                  • void BYEDestroy(const RTPTime &maxwaittime, const void *reason,size t reasonlength)
                  發(fā)送一個(gè)BYE包并且離開會(huì)話。在發(fā)送BYE包前等待maxwaittime,如果超時(shí),會(huì)不發(fā)送BYE包直接離開,BYE包會(huì)包含你的離開原因reason。相應(yīng)的reasonlength表示reason長度。ps:因?yàn)锽YE包是一個(gè)RTCP包,RTCP不是要發(fā)就發(fā)的,它的發(fā)送時(shí)間是為了平衡帶寬通過計(jì)算得出來的,那就很有可能到了要發(fā)的時(shí)候以經(jīng)超過了maxwaittime時(shí)間了,作者可能認(rèn)一直保留個(gè)這會(huì)話這么久沒意義。當(dāng)然,我常常把maxwaittime設(shè)得很大

                  • bool IsActive()
                  看看這個(gè)RTPSession實(shí)例是否以經(jīng)通過Create建立了真實(shí)的會(huì)話。

                  • uint32 t GetLocalSSRC()
                  返回我們的SSRC。ps:至于什么是SSRC,去看看RFC3550吧。我說過JRTPLIB只是RTP協(xié)議的包裝,并沒有做任何應(yīng)用的事情。

                  • int AddDestination(const RTPAddress &addr)
                  添加一個(gè)發(fā)送目標(biāo)。ps: 當(dāng)然,如果我們使用組播,這里只用調(diào)用一次,把我們的組播地址寫進(jìn)去。這樣,這組的全部人都能收到你發(fā)的包。但是組播可因特網(wǎng)的上設(shè)置很煩。而且用組播測試也很煩(組播必須BIND一個(gè)端口,如果你想在同一臺(tái)機(jī)器上運(yùn)行兩個(gè)軟件實(shí)例來沒試,你就會(huì)發(fā)現(xiàn)同一個(gè)端口BIND兩次,當(dāng)然,后面那次會(huì)失敗,也就是說測試不了,要測?找兩臺(tái)機(jī)器,或用虛擬機(jī)),如果組播不滿足,我們就要把組播變在單播,這時(shí)就要返復(fù)調(diào)用這個(gè)函數(shù)把其它組成員的IP都加進(jìn)來了。具體可以看看example3.cpp。

                  • int DeleteDestination(const RTPAddress &addr)
                  從發(fā)送地址列表中刪除一下地址。

                  • void ClearDestinations()
                  清除發(fā)送地址列表。

                  • bool SupportsMulticasting()
                  返回JRTPLIB是否支持組播。ps:這里指JRTPLIB本身,不是你的真實(shí)網(wǎng)絡(luò)。編譯JRTPLIB庫時(shí)可能指定。
            .
                  • int JoinMulticastGroup(const RTPAddress &addr)
                  加入一個(gè)組播組addr。

                  • int LeaveMulticastGroup(const RTPAddress &addr)
                   離開一個(gè)組播組addr。

                  • void LeaveAllMulticastGroups()
                  離開所有組播組。ps:我們可以同時(shí)加入多個(gè)組播組。.

                  • int SendPacket(const void *data, size t len)
                  • int SendPacket(const void *data, size t len, uint8 t pt, bool mark,uint32 t timestampinc)
                  • int SendPacketEx(const void *data, size t len, uint16 t hdrextID,const void *hdrextdata, size t numhdrextwords)
                  • int SendPacketEx(const void *data, size t len, uint8 t pt, boolmark, uint32 t timestampinc, uint16 t hdrextID, const void *hdrextdata,size t numhdrextwords)
                  上面的4個(gè)函數(shù)都是發(fā)送數(shù)據(jù)包的,我想如果你沒有看RTP協(xié)議,我說了你也暈。如果你RTP協(xié)議看了,再看看RTPSession.h的注識(shí),你就懂了。

                  • int SetDefaultPayloadType(uint8 t pt)
                  設(shè)定默認(rèn)的RTP PayloadType為PT。ps:和上面的第一個(gè)和第三個(gè)發(fā)送函數(shù)配套。至于應(yīng)該設(shè)個(gè)什么數(shù),如果你看BAIDU上亂七八糟的文章,當(dāng)然的亂設(shè)就可能了。其實(shí)應(yīng)該按RFC3551,根據(jù)你要傳輸?shù)拿襟w類型來設(shè)。

                  • int SetDefaultMark(bool m)
                  這設(shè)RTP數(shù)據(jù)包的Mark標(biāo)識(shí)。ps:設(shè)為什么值好?這個(gè),呵呵,連RFC3550也不能確定了。要看具體的RTP Payload規(guī)范,MPEG的,H263的都不一樣。
                  MPEG2 
               www.ietf.org/rfc/rfc2250.txt 
                  MPEG4    
            www.rfc-editor.org/rfc/rfc3016.txt 
                  H263        www.ietf.org/rfc/rfc2190.txt
             

                  • int SetDefaultTimestampIncrement(uint32 t timestampinc)
                  設(shè)置默認(rèn)的時(shí)間戳的增量。ps:也是和上的第一和第三個(gè)函數(shù)配套的。每發(fā)一個(gè)RTP數(shù)據(jù)包timestamp就會(huì)自動(dòng)增加

                  • int IncrementTimestamp(uint32 t inc)
                  這個(gè)函數(shù)用來手工增加Timestamp。有時(shí)我這很好用,例如,一個(gè)RTP數(shù)據(jù)包因?yàn)橹缓徐o音數(shù)據(jù),我們沒有發(fā)送,這是我們就應(yīng)手工增加Timestamp以便發(fā)下一個(gè)RTP數(shù)據(jù)包時(shí)它的Timestamp是正確的。

                  • int IncrementTimestampDefault()
                  這個(gè)函數(shù)用于增加由SetDefaultTimestampIncrement設(shè)定的值。有時(shí)候這很有用,例如,一個(gè)RTP數(shù)據(jù)包因?yàn)橹缓徐o音數(shù)據(jù),我們沒有發(fā)送。這時(shí),這個(gè)函數(shù)就會(huì)被調(diào)用用來設(shè)置Timestamp以便下一個(gè)RTP包的Timestamp是正確的。

                  • int SetPreTransmissionDelay(const RTPTime &delay)
                  This function allows you to inform the library about the delay between
            sampling the first sample of a packet and sending the packet. This delay is
            taken into account when calculating the relation between RTP timestamp
            and wallclock time, used for inter-media synchronization.

                  • RTPTransmissionInfo *GetTransmissionInfo()
                  This function returns an instance of a subclass of RTPTransmissionInfo
            which will give some additional information about the transmitter (a list
            of local IP addresses for example). The user has to delete the returned
            instance when it is no longer needed.
                  
                  • int Poll()
                  If you’re not using the poll thread, this function must be called regularly
            to process incoming data and to send RTCP data when necessary.
            61

                  • int WaitForIncomingData(const RTPTime &delay,bool *dataavailable= 0)
                  Waits at most a time delay until incoming data has been detected. Only
            works when you’re not using the poll thread. If dataavailable is not NULL,
            it should be set to true if data was actually read and to false otherwise.

                  • int AbortWait()
                  If the previous function has been called, this one aborts the waiting. Only
            works when you’re not using the poll thread.

                  • RTPTime GetRTCPDelay()
                  Returns the time interval after which an RTCP compound packet may have
            to be sent. Only works when you’re not using the poll thread.

                  • int BeginDataAccess()
                  下面的函數(shù)(直到EndDataAccess)要在BeginDataAccess 和EndDataAccess之間被調(diào)用,BeginDataAccess確保輪詢(poll)線程不會(huì)在這期間訪問source table 。EndDataAccess 調(diào)用完成后,輪詢(poll)線程會(huì)得到鎖而繼續(xù)訪問。ps:首先,你里的source table中的每一個(gè)source表示參與會(huì)議中的每一個(gè)參與者的每一個(gè)獨(dú)立的媒體流。我們會(huì)在下面用到他們,但同時(shí),poll線程也會(huì)輪詢它們以正確處理和RTCP有關(guān)的內(nèi)容。
              

                  • bool GotoFirstSource()
                  開始遞歸參與者的第一個(gè)流,如果找到了,就返回tree,否則返回false。ps:我們通過這個(gè)函數(shù)和下面的GotoNextSource遍歷source table中的每一個(gè)source。
                  
                  • bool GotoNextSource()
                  設(shè)置當(dāng)前的源(source)為source table中的下一個(gè)源。如果已經(jīng)到尾部了就返回false.
                 
                  • bool GotoPreviousSource()
                  設(shè)置當(dāng)前的源(source)為source table中上一個(gè)源。如果已經(jīng)到頭部了就返回false.


                  • bool GotoFirstSourceWithData()
                  開始遞歸參與者中第一個(gè)有RTP數(shù)據(jù)的流,如果找到了,就返回tree,否則返回false。PS:在接收數(shù)據(jù)是我們常用的是這套函數(shù),因?yàn)槿绻麤]有數(shù)據(jù)要來都沒用。

                  • bool GotoNextSourceWithData()
                  設(shè)置當(dāng)前的源(source)為source table中有RTP數(shù)據(jù)的下一個(gè)源。如果已經(jīng)到尾部了就返回false.

                  • bool GotoPreviousSourceWithData()
                  設(shè)置當(dāng)前的源(source)為source table中有RTP數(shù)據(jù)的上一個(gè)源。如果已經(jīng)到頭部了就返回false.

                  • RTPSourceData *GetCurrentSourceInfo()
                  返回當(dāng)前參與者的當(dāng)前源(source)的RTPSourceData 實(shí)列。ps:返回的這個(gè)RTPSourceData 就是本進(jìn)程從期它參與者的RTCP數(shù)據(jù)包中收集得到的信息,對(duì)我們來說其實(shí)很有用,只是作者的例程沒有用上,國內(nèi)的網(wǎng)絡(luò)也沒有提到。在RFC3550中有關(guān)RTCP的東西都在這了,看過RFC3550的人都知到,里頭談得最多的就是RTCP。這個(gè)類我們以后會(huì)專門說。
                  
                  
                  • RTPSourceData *GetSourceInfo(uint32 t ssrc)
                  返回由ssrc指定的RTPSourceData ,或都NULL(當(dāng)這個(gè)條目不存在)。ps:這個(gè)函數(shù)也很有用。因?yàn)镚etCurrentSourceInfo只有在GotoFirstSource等上下文當(dāng)中才能用。如果我們是在RTPSource子類的成員函數(shù)中,我們沒有這個(gè)上下文,就只能用這個(gè)函數(shù)。
             
                  • RTPPacket *GetNextPacket()
                  得到當(dāng)前參與者當(dāng)前媒體流的下一個(gè)RTP數(shù)據(jù)包。

                  • int EndDataAccess()
                  請看BeginDataAccess

                  • int SetReceiveMode(RTPTransmitter::ReceiveMode m)
                  Sets the receive mode to m, which can be one of the following:
                  – RTPTransmitter::AcceptAll
                        All incoming data is accepted, no matter where it originated from.
                  – RTPTransmitter::AcceptSome
                        Only data coming from specific sources will be accepted.
                  – RTPTransmitter::IgnoreSome
                        All incoming data is accepted, except for data coming from a specificset of sources.
                    Note that when the receive mode is changed, the list of addressed to be ignored or accepted will be cleared.

                  • int AddToIgnoreList(const RTPAddress &addr)
                  Adds addr to the list of addresses to ignore.

                  • int DeleteFromIgnoreList(const RTPAddress &addr)
                  Deletes addr from the list of addresses to ignore.

                  • void ClearIgnoreList()
                  Clears the list of addresses to ignore.

                  • int AddToAcceptList(const RTPAddress &addr)
                  Adds addr to the list of addresses to accept.

                  • int DeleteFromAcceptList(const RTPAddress &addr)
                  Deletes addr from the list of addresses to accept.

                  • void ClearAcceptList()
                  Clears the list of addresses to accept.

                  • int SetMaximumPacketSize(size t s)
                  Sets the maximum allowed packet size to s.

                  • int SetSessionBandwidth(double bw)
                  Sets the session bandwidth to bw, which is specified in bytes per second.

                  • int SetTimestampUnit(double u)
                  Sets our own timestamp unit to u. The timestamp unit is defined as a time
            interval divided by the number of samples in that interval: for 8000Hz
            audio this would be 1.0/8000.0.

                  • void SetNameInterval(int count)
                  在處理source table中的sourcese后,RTCP packet builder(我們不用理這個(gè)內(nèi)部的東西)會(huì)檢查是否有其它(non-CNAME)SDES項(xiàng)目要發(fā)送。如果count為零或負(fù)數(shù),則不發(fā)送,如果count為正數(shù),則在sources table處理count次后會(huì)把SDES name item加到當(dāng)前RTCP包中。ps: 其實(shí)每次處理sources table都會(huì)伴隨都SDES RTCP數(shù)據(jù)包的發(fā)送,在這個(gè)數(shù)據(jù)包當(dāng)中CNAME是必須的,但其它的項(xiàng)目不是必須的,這就函數(shù)確定了NAME項(xiàng)目發(fā)送的頻度,如果為1,則表不每個(gè) SDES RTCP數(shù)據(jù)包都帶著它,如果為2則每兩個(gè)SDES數(shù)據(jù)包就發(fā)送一次NAME項(xiàng)目,下面的SetEMailInterval、 SetLocationInterval、SetPhoneInterval、SetToolInterval、SetNoteInterval都是同一原理。關(guān)于這個(gè)ITEM的描述,請看RFC3550.老版本的JRTPLIB沒有使用這套函數(shù),而是用EnableSendName()等函數(shù)。

                  • void SetEMailInterval(int count)
                  After all possible sources in the source table have been processed, the RTCP
            packet builder will check if other (non-CNAME) SDES items need to be
            sent. If count is zero or negative, nothing will happen. If count is positive,
            an SDES e-mail item will be added after the sources in the source table
            have been processed count times.

                  • void SetLocationInterval(int count)
                  After all possible sources in the source table have been processed, the RTCP
            packet builder will check if other (non-CNAME) SDES items need to be
            sent. If count is zero or negative, nothing will happen. If count is positive,
            an SDES location item will be added after the sources in the source table
            have been processed count times.

                  • void SetPhoneInterval(int count)
                  After all possible sources in the source table have been processed, the RTCP
            packet builder will check if other (non-CNAME) SDES items need to be
            sent. If count is zero or negative, nothing will happen. If count is positive,
            an SDES phone item will be added after the sources in the source table
            have been processed count times.

                  • void SetToolInterval(int count)
                  After all possible sources in the source table have been processed, the RTCP
            packet builder will check if other (non-CNAME) SDES items need to be
            sent. If count is zero or negative, nothing will happen. If count is positive,
            an SDES tool item will be added after the sources in the source table have
            been processed count times.

                  • void SetNoteInterval(int count)
                  After all possible sources in the source table have been processed, the RTCP
            packet builder will check if other (non-CNAME) SDES items need to be
            sent. If count is zero or negative, nothing will happen. If count is positive,
            an SDES note item will be added after the sources in the source table have
            been processed count times.

                  • int SetLocalName(const void *s, size t len)
                  設(shè)置NAME SDES項(xiàng)目,以遍會(huì)議的其它人員看到你的名稱。下同。
                 
                  • int SetLocalEMail(const void *s, size t len)
                  Sets the SDES e-mail item for the local participant to the value s with
            length len.

                  • int SetLocalLocation(const void *s, size t len)
            Sets the SDES location item for the local participant to the value s with
            length len.

                  • int SetLocalPhone(const void *s, size t len)
                  Sets the SDES phone item for the local participant to the value s with
            length len.

                  • int SetLocalTool(const void *s, size t len)
                  Sets the SDES tool item for the local participant to the value s with length
            len.
                  
                  • int SetLocalNote(const void *s, size t len)
            Sets the SDES note item for the local participant to the value s with length
            len.
            In case you specified in the constructor that you want to use your own transmission
            component, you should override the following function:
                  • RTPTransmitter *NewUserDefinedTransmitter()
                  The RTPTransmitter instance returned by this function will then be used to send
            and receive RTP and RTCP packets. Note that when the session is destroyed,
            this RTPTransmitter instance will be destroyed with a delete call.
            By inheriting your own class from RTPSession and overriding one or more of the
            functions below, certain events can be detected:

                  • void OnRTPPacket(RTPPacket *pack, const RTPTime &receivetime, const  RTPAddress *senderaddress)
                  如果有RTPPacket數(shù)據(jù)包來到,會(huì)調(diào)用這個(gè)函數(shù)處理。ps:這個(gè)函數(shù)在我們繼承RTPSession類時(shí)很可能重載,這是獲取RTP數(shù)據(jù)包除了上面所說的方法以外的另外一種方法,這個(gè)方法比較適合異步的情況。默認(rèn)這個(gè)是一個(gè)空虛函數(shù)。除了這個(gè)函數(shù)以外,下面的幾個(gè)函數(shù)了會(huì)經(jīng)常重載。

                  • void OnRTCPCompoundPacket(RTCPCompoundPacket *pack, const RTPTime &receivetime, const RTPAddress *senderaddress)
                  Is called when an incoming RTCP packet is about to be processed.

                  • void OnSSRCCollision(RTPSourceData *srcdat, const RTPAddress *senderaddress, bool isrtp)
                  Is called when an SSRC collision was detected. The instance srcdat is the
            one present in the table, the address senderaddress is the one that collided
            with one of the addresses and isrtp indicates against which address
            of srcdat the check failed.
                  
                  • void OnCNAMECollision(RTPSourceData *srcdat, const RTPAddress *senderaddress, const uint8 t *cname, size t cnamelength)
                  Is called when another CNAME was received than the one already present for source srcdat.

                  • void OnNewSource(RTPSourceData *srcdat)
                  當(dāng)有一個(gè)新的條目加到source table時(shí),調(diào)用這個(gè)函數(shù)。ps: 這也是一個(gè)比較重要的函數(shù),因?yàn)檫@意味著很有可能有一個(gè)新的與會(huì)者加入。但令我很不高興的是,這時(shí)候的RTPSourceData 里頭的CNAME和NAME等字段都還是無效的,這不是RTCP的責(zé)任,因?yàn)樵谶@個(gè)SDES RTCP數(shù)據(jù)包中所有的信息都以經(jīng)有了(通過抓包證實(shí)了這一點(diǎn))。我們的函數(shù)被調(diào)用后,需要延時(shí)一會(huì)才能得到有關(guān)這個(gè)Source的CNAME和NAME 等相關(guān)的信息。當(dāng)然,如果你不想軟件死掉,不能在這個(gè)函數(shù)體內(nèi)以阻塞的方式延時(shí)。

                  • void OnRemoveSource(RTPSourceData *srcdat)
                  當(dāng)有一個(gè)條目從source table中移除時(shí)調(diào)用這個(gè)函數(shù)。ps:這通常意味著有一個(gè)與會(huì)者離開了,和OnNewSource不一樣,這時(shí)的CNAME和NAME等都是有效的。用這個(gè)函數(shù)要注意,我們的“意味著兩個(gè)字” 因?yàn)?#8220;加入”的可能不是一個(gè)新的與會(huì)者,而是一個(gè)現(xiàn)有與會(huì)者的一個(gè)新的媒體流。“離開”的也可能不是一個(gè)與會(huì)者,而只是其中一個(gè)與會(huì)者的其中一個(gè)媒體流,這兩個(gè)函數(shù)只能給我們更新與會(huì)者提供一個(gè)觸發(fā)條件而已。當(dāng)OnNewSource調(diào)用時(shí),我們要看看這個(gè)CNAME是不是以經(jīng)在我們與會(huì)者名單中,如果不是,那就是一個(gè)新與會(huì)者。同時(shí),如果OnRemoveSource被調(diào)用,則我們要看看這個(gè)CNAME的與會(huì)者還有沒有其它的Source,如果沒有了,這個(gè)與會(huì)者才是真正離開。這么很麻煩??那就對(duì)了,那就是現(xiàn)在的H323和SIP要做的事情--會(huì)話管理。
                 
                  • void OnTimeout(RTPSourceData *srcdat)
                  Is called when participant srcdat is timed out.

                  • void OnBYETimeout(RTPSourceData *srcdat)
                  Is called when participant srcdat is timed after having sent a BYE packet.

                  • void OnBYEPacket(RTPSourceData *srcdat)
                  Is called when a BYE packet has been processed for source srcdat.

                  • void OnAPPPacket(RTCPAPPPacket *apppacket, const RTPTime &receivetime,
            const RTPAddress *senderaddress)
                  In called when an RTCP APP packet apppacket has been received at time
            receivetime from address senderaddress.

                  • void OnUnknownPacketType(RTCPPacket *rtcppack, const RTPTime &receivetime,
            const RTPAddress *senderaddress)
                  Is called when an unknown RTCP packet type was detected.

                  • void OnUnknownPacketFormat(RTCPPacket *rtcppack, const RTPTime &receivetime,
            const RTPAddress *senderaddress)
                  Is called when an unknown packet format for a known packet type was
            detected.

                  • void OnNoteTimeout(RTPSourceData *srcdat)
                  Is called when the SDES NOTE item for source srcdat has been timed out.

                  • void OnSendRTCPCompoundPacket(RTCPCompoundPacket *pack)
                  Is called when an RTCP compound packet has just been sent. Useful to
            inspect outgoing RTCP data.

                  • void OnPollThreadError(int errcode)
                  Is called when error errcode was detected in the poll thread.

                  • void OnPollThreadStep()
                  Is called each time the poll thread loops. This happens when incoming data
            was detected or when its time to send an RTCP compound packet.

            發(fā)送者報(bào)告(SR)

            V| P| RC| PT=SR=200| LEN|


            發(fā)送者SSRC (已關(guān)聯(lián))


            NTP時(shí)間戳(高32位) SR_GetNTPTimestamp ()

             

            NTP時(shí)間戳(低32位)


            RTP時(shí)間戳 SR_GetRTPTimestamp () 

             


            發(fā)送者分組計(jì)數(shù)器 SR_GetPacketCount()

             


            發(fā)送者字節(jié)計(jì)數(shù)器 SR_GetByteCount ()

             


            ...(下面是這個(gè)發(fā)送者所發(fā)送的接收者報(bào)告,在下面和RR一起討論)

             


            附加信息:

            這個(gè)源是否有發(fā)送發(fā)送者報(bào)告

            SR_HasInfo ()

            這個(gè)發(fā)送者報(bào)告接收的時(shí)間

            SR_GetReceiveTime ()

            以及以SR_Prev_開頭的,獲得倒數(shù)第二個(gè)發(fā)送者報(bào)告的信息。



            接收者報(bào)告(RR)

            V| P| RC| PT=SR=201| LEN|


             

            SSRC1(第一個(gè)接收者報(bào)告塊所關(guān)聯(lián)的發(fā)送者) (已關(guān)聯(lián))

            分組丟失率 | 丟失分組總數(shù)|

            擴(kuò)展的最高序號(hào)

            間隔抖動(dòng)

            最新的發(fā)送者報(bào)告時(shí)間戳(LSR)

            SR最新間隔(DLSR)

            附加信息:
            這個(gè)源是否有發(fā)送接收者報(bào)告
            接收者報(bào)告接收時(shí)間
            以及以RR_Prev_開頭的,獲得倒數(shù)第二個(gè)接收者報(bào)告的信息。
            posted @ 2009-06-26 13:13 黑色天使 閱讀(1741) | 評(píng)論 (0)編輯 收藏

            YUV主要的采樣格式

            主要的采樣格式有YCbCr 4:2:0YCbCr 4:2:2YCbCr 4:1:1 YCbCr 4:4:4。其中YCbCr 4:1:1 比較常用,其含義為:每個(gè)點(diǎn)保存一個(gè) 8bit 的亮度值(也就是Y), 2x2 個(gè)點(diǎn)保存一個(gè) Cr Cb , 圖像在肉眼中的感覺不會(huì)起太大的變化。所以, 原來用 RGB(R,G,B 都是 8bit unsigned) 模型, 4 個(gè)點(diǎn)需要 8x3=24 bites(如下圖第一個(gè)圖). 而現(xiàn)在僅需要 8+(8/4)+(8/4)=12bites, 平均每個(gè)點(diǎn)占12bites(如下圖第二個(gè)圖)。這樣就把圖像的數(shù)據(jù)壓縮了一半。

                上邊僅給出了理論上的示例,在實(shí)際數(shù)據(jù)存儲(chǔ)中是有可能是不同的,下面給出幾種具體的存儲(chǔ)形式:

            1    YUV 4:4:4

            YUV三個(gè)信道的抽樣率相同,因此在生成的圖像里,每個(gè)象素的三個(gè)分量信息完整(每個(gè)分量通常8比特),經(jīng)過8比特量化之后,未經(jīng)壓縮的每個(gè)像素占用3個(gè)字節(jié)。

            下面的四個(gè)像素為: [Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]

            存放的碼流為: Y0 U0 V0 Y1 U1 V1 Y2 U2 V2 Y3 U3 V3

            2   YUV 4:2:2

                  每個(gè)色差信道的抽樣率是亮度信道的一半,所以水平方向的色度抽樣率只是4:4:4的一半。對(duì)非壓縮的8比特量化的圖像來說,每個(gè)由兩個(gè)水平方向相鄰的像素組成的宏像素需要占用4字節(jié)內(nèi)存。

            下面的四個(gè)像素為: [Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]

            存放的碼流為: Y0 U0 Y1 V1 Y2 U2 Y3 V3

            映射出像素點(diǎn)為:[Y0 U0 V1] [Y1 U0 V1] [Y2 U2 V3] [Y3 U2 V3]

            3   YUV 4:1:1

            4:1:1的色度抽樣,是在水平方向上對(duì)色度進(jìn)行4:1抽樣。對(duì)于低端用戶和消費(fèi)類產(chǎn)品這仍然是可以接受的。對(duì)非壓縮的8比特量化的視頻來說,每個(gè)由4個(gè)水平方向相鄰的像素組成的宏像素需要占用6字節(jié)內(nèi)存

            下面的四個(gè)像素為: [Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]

            存放的碼流為: Y0 U0 Y1 Y2 V2 Y3

            映射出像素點(diǎn)為:[Y0 U0 V2] [Y1 U0 V2] [Y2 U0 V2] [Y3 U0 V2]

            4YUV4:2:0

                 4:2:0并不意味著只有Y,Cb而沒有Cr分量。它指得是對(duì)每行掃描線來說,只有一種色度分量以2:1的抽樣率存儲(chǔ)。進(jìn)行隔行掃描,相鄰的掃描行存儲(chǔ)不同的色度分量,也就是說,如果一行是4:2:0的話,下一行就是4:0:2,再下一行是4:2:0...以此類推。對(duì)每個(gè)色度分量來說,水平方向和豎直方向的抽樣率都是2:1,所以可以說色度的抽樣率是4:1。對(duì)非壓縮的8比特量化的視頻來說,每個(gè)由2x2個(gè)22列相鄰的像素組成的宏像素需要占用6字節(jié)內(nèi)存。

            下面八個(gè)像素為:[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]

                            [Y5 U5 V5] [Y6 U6 V6] [Y7U7 V7] [Y8 U8 V8]

            存放的碼流為:Y0 U0 Y1 Y2 U2 Y3

                                 Y5 V5 Y6 Y7 V7 Y8

            映射出的像素點(diǎn)為:[Y0 U0 V5] [Y1 U0 V5] [Y2 U2 V7] [Y3 U2 V7]

                              [Y5 U0 V5] [Y6 U0 V5] [Y7U2 V7] [Y8 U2 V7] 

            對(duì)應(yīng)AVPicture里面有data[4]和linesize[4]其中data是一個(gè)指向指針的指針(二級(jí)、二維指針),也就是指向視頻數(shù)據(jù)緩沖區(qū)的首地址,而data[0]~data[3]是一級(jí)指針,可以用如下的圖來表示:

            data -->xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
                    ^                ^              ^
                    |                |              |
                     data[0]      data[1]         data[2]

            比如說,當(dāng)pix_fmt=PIX_FMT_YUV420P時(shí),data中的數(shù)據(jù)是按照YUV的格式存儲(chǔ)的,也就是:

            data -->YYYYYYYYYYYYYYUUUUUUUUUUUUUVVVVVVVVVVVV
            ^             ^            ^
            |             |            |
            data[0]    data[1]      data[2]
            

            linesize是指對(duì)應(yīng)于每一行的大小,為什么需要這個(gè)變量,是因?yàn)樵赮UV格式和RGB格式時(shí),每行的大小不一定等于圖像的寬度,對(duì)于RGB格式輸出時(shí),只有一個(gè)通道(bgrbgrbgr......)可用,即linesize[0],和data[0],so RGB24 : data[0] = packet rgb//bgrbgrbgr......

            linesize[0] = width*3
            

            其他的如data[1][2][3]與linesize[1][2][3]無任何意義.

            而對(duì)于YUV格式輸出時(shí),有三個(gè)通道可用,即data[0][1][2],與linesize[0][1][2],而yuv格式對(duì)于運(yùn)動(dòng)估計(jì)時(shí),需要填充padding(right, bottom),故:

            linesize=width+padding size(16+16).
            ///////////////////////////////////////////////////////////////////////////////////////

               case PIX_FMT_YUV420P:
               case PIX_FMT_YUVJ420P:
               case PIX_FMT_RGB555:
                if (PIC_DIRECTION_0 == m_dwFilpPicDirection)
                {
                 m_pYuvFrame->data [0] += m_pYuvFrame->linesize[0] *  m_pVCodecContext->height;
                 //因?yàn)槭歉粜袙呙鑅與V只有高度的一半
                 m_pYuvFrame->data [1] += m_pYuvFrame->linesize[1] *  m_pVCodecContext->height/2;
                 m_pYuvFrame->data [2] += m_pYuvFrame->linesize[2] *  m_pVCodecContext->height/2;
                 m_pYuvFrame->linesize[0] = -m_pYuvFrame->linesize[0];
                 m_pYuvFrame->linesize[1] = -m_pYuvFrame->linesize[1];
                 m_pYuvFrame->linesize[2] = -m_pYuvFrame->linesize[2];
                }
                
                break;
               case PIX_FMT_YUVJ422P:
               case PIX_FMT_YUV422P:
               case PIX_FMT_YUYVJ422:
               case PIX_FMT_YUV411P:
               case PIX_FMT_YUYV422:  
                if (PIC_DIRECTION_0 == m_dwFilpPicDirection)
                {
                 m_pYuvFrame->data [0] += m_pYuvFrame->linesize[0] *  m_pVCodecContext->height;
                 m_pYuvFrame->data [1] += m_pYuvFrame->linesize[1] *  m_pVCodecContext->height;
                 m_pYuvFrame->data [2] += m_pYuvFrame->linesize[2] *  m_pVCodecContext->height;
                 m_pYuvFrame->linesize[0] = -m_pYuvFrame->linesize[0];
                 m_pYuvFrame->linesize[1] = -m_pYuvFrame->linesize[1];
                 m_pYuvFrame->linesize[2] = -m_pYuvFrame->linesize[2];
                }
                break;
               }
            在FFMPEG中轉(zhuǎn)換RGB時(shí)順便顛倒圖像的方向算法
            posted @ 2009-06-08 15:23 黑色天使 閱讀(4310) | 評(píng)論 (1)編輯 收藏
                 摘要:   閱讀全文
            posted @ 2009-03-11 11:40 黑色天使 閱讀(1095) | 評(píng)論 (0)編輯 收藏
            不經(jīng)清貧難成人,
            不經(jīng)打擊老天真,
            自古英雄出煉獄,
            從來富貴落凡塵,
            醉生夢死誰成器,
            破馬長槍頂乾坤。
            posted @ 2009-02-19 15:56 黑色天使 閱讀(219) | 評(píng)論 (0)編輯 收藏
                 摘要:   閱讀全文
            posted @ 2009-02-17 12:44 黑色天使 閱讀(781) | 評(píng)論 (0)編輯 收藏
                 摘要:   閱讀全文
            posted @ 2009-02-14 13:47 黑色天使 閱讀(265) | 評(píng)論 (0)編輯 收藏
            僅列出標(biāo)題
            共5頁: 1 2 3 4 5 

            <2009年2月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            1234567

            常用鏈接

            留言簿(2)

            隨筆分類

            隨筆檔案

            文章檔案

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            人妻少妇久久中文字幕| 久久91亚洲人成电影网站| 一本大道久久东京热无码AV| 精品久久人人爽天天玩人人妻| 久久久精品午夜免费不卡| 久久精品国产精品亚洲艾草网美妙| 一本久道久久综合狠狠躁AV| 2021国内久久精品| 久久棈精品久久久久久噜噜| 久久精品9988| 久久91精品国产91| 青草影院天堂男人久久| 亚洲国产成人久久一区WWW| 热re99久久精品国99热| 久久久久亚洲精品天堂久久久久久| 亚洲精品乱码久久久久久蜜桃图片 | 99久久国语露脸精品国产| 精品多毛少妇人妻AV免费久久| 亚洲日本va中文字幕久久| 欧美激情精品久久久久| 久久久噜噜噜久久中文福利| 夜夜亚洲天天久久| 久久人做人爽一区二区三区| 久久久久亚洲AV无码专区体验| 久久无码一区二区三区少妇| 精品国产乱码久久久久久郑州公司| 看全色黄大色大片免费久久久 | 欧美无乱码久久久免费午夜一区二区三区中文字幕 | 日本免费久久久久久久网站| 精品久久久无码21p发布| 久久久WWW免费人成精品| 久久精品国产福利国产秒| 日韩欧美亚洲综合久久| 欧美日韩精品久久久免费观看| 久久久久99精品成人片牛牛影视| 国产精品久久久天天影视| 国产三级久久久精品麻豆三级 | 久久久久免费视频| 亚洲国产天堂久久综合| 日本高清无卡码一区二区久久| 久久精品成人欧美大片|