??xml version="1.0" encoding="utf-8" standalone="yes"?>
]]>
{
//重蝲需要的法操作
template <typename R>
op<R> operator=(R i)
{
return op<R>(i);
}
};
template <typename T>
struct op
{
op(T i): _i(i) {}
T operator()(T &i)
{
return i = _i;
}
T _i;
};
以上的代码实?操作如果需要其他操作则重蝲相应的操作例?=
依次cL占位cd?=q过仿函数可以实?=的操作以下是完成的代?br>
#include "stdafx.h"
#include <vector>
#include <algorithm>
using namespace std;
//仿函敎ͼ即重载了()操作的类
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;
};
//占位W?/span>
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()); //原格式如?/span>
for_each(v.begin(), v.end(), _1=2); //_1=2是一个仿函数,通过重蝲=实现
return 0;
}
]]>
#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生成一个仿函数c,q个cL造时赋garg
//遇到(person)Ӟ调用q个仿函数类重蝲?)操作?br> //t.*pfn(arg)
//又回归ؓ(f)一个函敎ͼ不过参数可以自己控制?娃哈?/span>
simple_bind(&Person::SetName, string("Martin"))(person);
cout << person.Name() << endl;
}
]]>
F = r [ R ] + g [ G ] + b [ B ]
其中Qr、g、b分别Z参与混合的系数。当三基色分量都?Q最弱)时合ؓ(f)黑色光;而当三基色分量都为kQ最强)时合ؓ(f)白色光。调整r、g、b三个pL的|可以混合Z于黑色光和白色光之间的各U各L(fng)色光?br>那么YUV又从何而来呢?在现代彩色电(sh)视系l中Q通常采用三管彩色摄像机或彩色CCD摄像行摄像,然后把摄得的彩色囑փ信号l分艌Ӏ分别放大校正后得到RGBQ再l过矩阵变换?sh)\得到亮度信号Y和两个色差信号RQYQ即UQ、BQYQ即VQ,最后发送端亮度和色差三个信号分别q行~码Q用同一信道发送出厅R这U色彩的表示Ҏ(gu)是所谓的YUV色彩I间表示?br>采用YUV色彩I间的重要性是它的亮度信号Y和色度信号U、V是分ȝ。如果只有Y信号分量而没有U、V分量Q那么这栯C的囑փ是黑白灰度囑փ。彩色电(sh)视采用YUVI间正是Z用亮度信号Y解决彩色?sh)视Z黑白?sh)视机的兼容问题Q黑白?sh)视Z能接收彩色电(sh)视信受?br>YUV与RGB怺转换的公式如下(RGB取D围均?-255Q:(x)
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{。作频媒体类型的辅助说明cdQSubtypeQ,它们对应的GUID见表2.3?br>
?.3 常见的RGB和YUV格式
GUID 格式描述
MEDIASUBTYPE_RGB1 2Ԍ每个像素?位表C,需要调色板
MEDIASUBTYPE_RGB4 16Ԍ每个像素?位表C,需要调色板
MEDIASUBTYPE_RGB8 256Ԍ每个像素?位表C,需要调色板
MEDIASUBTYPE_RGB565 每个像素?6位表C,RGB分量分别使用5位?位??br>MEDIASUBTYPE_RGB555 每个像素?6位表C,RGB分量都?位(剩下?位不用)
MEDIASUBTYPE_RGB24 每个像素?4位表C,RGB分量各??br>MEDIASUBTYPE_RGB32 每个像素?2位表C,RGB分量各?位(剩下?位不用)
MEDIASUBTYPE_ARGB32 每个像素?2位表C,RGB分量各?位(剩下?位用于表CAlpha通道|
MEDIASUBTYPE_YUY2 YUY2格式Q以4:2:2方式打包
MEDIASUBTYPE_YUYV YUYV格式Q实际格式与YUY2相同Q?br>MEDIASUBTYPE_YVYU YVYU格式Q以4:2:2方式打包
MEDIASUBTYPE_UYVY UYVY格式Q以4:2:2方式打包
MEDIASUBTYPE_AYUV 带Alpha通道?:4:4 YUV格式
MEDIASUBTYPE_Y41P Y41P格式Q以4:1:1方式打包
MEDIASUBTYPE_Y411 Y411格式Q实际格式与Y41P相同Q?br>MEDIASUBTYPE_Y211 Y211格式
MEDIASUBTYPE_IF09 IF09格式
MEDIASUBTYPE_IYUV IYUV格式
MEDIASUBTYPE_YV12 YV12格式
MEDIASUBTYPE_YVU9 YVU9格式
下面分别介绍各种RGB格式?br>
¨RGB1、RGB4、RGB8都是调色板类型的RGB格式Q在描述q些媒体cd的格式细节时Q通常?x)在BITMAPINFOHEADER数据l构后面跟着一个调色板Q定义一pd颜色Q。它们的囑փ数据q不是真正的颜色|而是当前像素颜色值在调色板中的烦引。以RGB1Q?色位图)ZQ比如它的调色板中定义的两种颜色gơؓ(f)0x000000Q黑Ԍ?xFFFFFFQ白ԌQ那么图像数?01101010111…Q每个像素用1位表C)表示对应各像素的颜色为:(x)黑黑白白黑白黑白黑白白白…?br>
¨ RGB565使用16位表CZ个像素,q?6位中?位用于RQ?位用于GQ?位用于B。程序中通常使用一个字QWORDQ一个字{于两个字节Q来操作一个像素。当d一个像素后Q这个字的各个位意义如下Q?br>高字?nbsp; 低字?br>R R R R R G G G G G G B B B B B
可以l合使用屏蔽字和UM操作来得到RGB各分量的|(x)
#define RGB565_MASK_RED 0xF800
#define RGB565_MASK_GREEN 0x07E0
#define RGB565_MASK_BLUE 0x001F
R = (wPixel & RGB565_MASK_RED) >> 11; // 取D?-31
G = (wPixel & RGB565_MASK_GREEN) >> 5; // 取D?-63
B = wPixel & RGB565_MASK_BLUE; // 取D?-31
¨ RGB555是另一U?6位的RGB格式QRGB分量都用5位表C(剩下?位不用)。用一个字d一个像素后Q这个字的各个位意义如下Q?br>高字?nbsp; 低字?br>X R R R R G G G G G B B B B B QX表示不用Q可以忽略)
可以l合使用屏蔽字和UM操作来得到RGB各分量的|(x)
#define RGB555_MASK_RED 0x7C00
#define RGB555_MASK_GREEN 0x03E0
#define RGB555_MASK_BLUE 0x001F
R = (wPixel & RGB555_MASK_RED) >> 10; // 取D?-31
G = (wPixel & RGB555_MASK_GREEN) >> 5; // 取D?-31
B = wPixel & RGB555_MASK_BLUE; // 取D?-31
¨ RGB24使用24位来表示一个像素,RGB分量都用8位表C,取D围ؓ(f)0-255。注意在内存中RGB各分量的排列序为:(x)BGR BGR BGR…。通常可以使用RGBTRIPLE数据l构来操作一个像素,它的定义为:(x)
typedef struct tagRGBTRIPLE {
BYTE rgbtBlue; // 蓝色分量
BYTE rgbtGreen; // l色分量
BYTE rgbtRed; // U色分量
} RGBTRIPLE;
¨ RGB32使用32位来表示一个像素,RGB分量各用?位,剩下?位用作Alpha通道或者不用。(ARGB32是带Alpha通道?RGB32。)注意在内存中RGB各分量的排列序为:(x)BGRA BGRABGRA…。通常可以使用RGBQUAD数据l构来操作一个像素,它的定义为:(x)
typedef struct tagRGBQUAD {
BYTE rgbBlue; // 蓝色分量
BYTE rgbGreen; // l色分量
BYTE rgbRed; // U色分量
BYTE rgbReserved; // 保留字节Q用作Alpha通道或忽略)
} RGBQUAD;
下面介绍各种YUV格式。YUV格式通常有两大类Q打包(packedQ格式和q面QplanarQ格式。前者将YUV分量存放在同一个数l中Q通常是几个相?c)像素l成一个宏像素Qmacro-pixelQ;而后者用三个数l分开存放YUV三个分量Q就像是一个三l^面一栗表2.3中的YUY2?Y211都是打包格式Q而IF09到YVU9都是q面格式。(注意Q在介绍各种具体格式ӞYUV各分量都?x)带有下标,如Y0、U0、V0表示W一个像素的YUV分量QY1、U1、V1表示W二个像素的YUV分量Q以此类推。)
¨ YUY2Q和YUYVQ格式ؓ(f)每个像素保留Y分量Q而UV分量在水qx向上每两个像素采样一ơ。一个宏像素?个字节,实际表示2个像素。(4:2:2的意思ؓ(f)一个宏像素中有4个Y分量?个U分量?个V分量。)囑փ数据中YUV分量排列序如下Q?br>Y0 U0 Y1 V0 Y2 U2 Y3 V2 …
¨ YVYU格式跟YUY2cMQ只是图像数据中YUV分量的排列顺序有所不同Q?br>Y0 V0 Y1 U0 Y2 V2 Y3 U2 …
¨ UYVY格式跟YUY2cMQ只是图像数据中YUV分量的排列顺序有所不同Q?br>U0 Y0 V0 Y1 U2 Y2 V2 Y3 …
¨ AYUV格式带有一个Alpha通道Qƈ且ؓ(f)每个像素都提取YUV分量Q图像数据格式如下:(x)
A0 Y0 U0 V0 A1 Y1 U1 V1 …
¨ Y41PQ和Y411Q格式ؓ(f)每个像素保留Y分量Q而UV分量在水qx向上?个像素采样一ơ。一个宏像素?2个字节,实际表示8个像素。图像数据中YUV分量排列序如下Q?br>U0 Y0 V0 Y1 U4 Y2 V4 Y3 Y4 Y5 Y6 Y8 …
¨ Y211格式在水qx向上Y分量?个像素采样一ơ,而UV分量?个像素采样一ơ。一个宏像素?个字节,实际表示4个像素。图像数据中YUV分量排列序如下Q?br>Y0 U0 Y2 V0 Y4 U4 Y6 V4 …
¨ YVU9格式为每个像素都提取Y分量Q而在UV分量的提取时Q首先将囑փ分成若干? x 4的宏块,然后每个宏块提取一个U分量和一个V分量。图像数据存储时Q首先是整幅囑փ的Y分量数组Q然后就跟着U分量数组Q以?qing)V分量数组。IF09格式与YVU9cM?br>
¨ IYUV格式为每个像素都提取Y分量Q而在UV分量的提取时Q首先将囑փ分成若干? x 2的宏块,然后每个宏块提取一个U分量和一个V分量。YV12格式与IYUVcM?br>
¨YUV411、YUV420格式多见于DV数据中,前者用于NTSCӞ后者用于PAL制。YUV411为每个像素都提取Y分量Q而UV分量在水qx向上?个像素采样一ơ。YUV420qV分量采样?Q而是跟YUV411相比Q在水^方向上提高一倍色差采样频率,在垂直方向上以U/V间隔的方式减一半色差采栗?br>
V| P| RC| PT=SR=200| LEN| 发送者SSRC Q已兌Q?/font> NTP旉戻I?2位) SR_GetNTPTimestamp ()
NTP旉戻I?2位) RTP旉?span class=Apple-tab-span style="WHITE-SPACE: pre"> SR_GetRTPTimestamp ()
发送者分l计数器 SR_GetPacketCountQ)
发送者字节计数器 SR_GetByteCount ()
...(下面是这个发送者所发送的接收者报告,在下面和RR一赯论)
附加信息Q?/font> q个源是否有发送发送者报?/font> SR_HasInfo () q个发送者报告接收的旉 以及(qing)以SR_Prev_开头的Q获得倒数W二个发送者报告的信息?/span> |
V| P| RC| PT=SR=201| LEN|
SSRC1(W一个接收者报告块所兌的发送者) Q已兌Q?/span>
分组丢失?span class=Apple-tab-span style="WHITE-SPACE: pre"> | 丢失分组L| 扩展的最高序?/div> 间隔抖动 RR_GetJitter ()
最新的发送者报告时间戳QLSR) SR最新间隔(DLSR)
附加信息Q?/span>
q个源是否有发送接收者报?/span>
RR_HasInfo ()
接收者报告接收时?/div>
以及(qing)以RR_Prev_开头的Q获得倒数W二个接收者报告的信息?/span>
|
YUV主要的采h?/span>
主要的采h式有YCbCr 4:2:0?/span>YCbCr 4:2:2?/span>YCbCr 4:1:1?/span> YCbCr 4:4:4。其?/span>YCbCr 4:1:1 比较常用Q其含义为:(x)每个点保存一?/span> 8bit 的亮度?/span>(也就?/span>Y?/span>), ?/span> 2x2 个点保存一?/span> Cr ?/span>Cb ?/span>, 囑փ在肉g的感觉不?x)v太大的变化。所?/span>, 原来?/span> RGB(R,G,B 都是 8bit unsigned) 模型, 4 个点需?/span> 8x3=24 bitesQ如下图W一个图Q?/span>. 而现在仅需?/span> 8+(8/4)+(8/4)=12bites, q_每个点占12bites(如下囄二个?/span>)。这样就把图像的数据压羃了一半?/span>
上边仅给Z理论上的CZQ在实际数据存储中是有可能是不同的,下面l出几种具体的存储Ş式:(x)
Q?/span>1Q?/span> YUV 4:4:4
YUV三个信道的抽L(fng)相同Q因此在生成的图像里Q每个象素的三个分量信息完整Q每个分量通常8比特Q,l过8比特量化之后Q未l压~的每个像素占用3个字节?/span>
下面的四个像素ؓ(f): [Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
存放的码ؓ(f): Y0 U0 V0 Y1 U1 V1 Y2 U2 V2 Y3 U3 V3
Q?span>2Q?span> YUV 4:2:2
每个色差信道的抽L(fng)是亮度信道的一半,所以水qx向的色度抽样率只?span>4:4:4的一半。对非压~的8比特量化的图像来_(d)每个׃个水qx向相?c)像素l成的宏像素需要占?span>4字节内存?/span>
下面的四个像素ؓ(f): [Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
存放的码ؓ(f): Y0 U0 Y1 V1 Y2 U2 Y3 V3
映射出像素点为:(x)[Y0 U0 V1] [Y1 U0 V1] [Y2 U2 V3] [Y3 U2 V3]
Q?span>3Q?span> YUV 4:1:1
4:1:1的色度抽P是在水^方向上对色度q行4:1抽样。对于低端用户和消费cM品这仍然是可以接受的。对非压~的8比特量化的视频来_(d)每个?span>4个水qx向相?c)像素l成的宏像素需要占?span>6字节内存
下面的四个像素ؓ(f): [Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
存放的码ؓ(f): Y0 U0 Y1 Y2 V2 Y3
映射出像素点为:(x)[Y0 U0 V2] [Y1 U0 V2] [Y2 U0 V2] [Y3 U0 V2]
Q?span>4Q?span>YUV4:2:0
4:2:0q不意味着只有Y,Cb而没?span>Cr分量。它指得是对每行扫描U来_(d)只有一U色度分量以2:1的抽L(fng)存储。进行隔行扫描,盔R的扫描行存储不同的色度分量,也就是说Q如果一行是4:2:0的话Q下一行就?span>4:0:2Q再下一行是4:2:0...以此cL。对每个色度分量来说Q水qx向和竖直方向的抽L(fng)都是2:1Q所以可以说色度的抽L(fng)?span>4:1。对非压~的8比特量化的视频来_(d)每个?span>2x2?span>2?span>2列相?c)像素l成的宏像素需要占?span>6字节内存?/span>
下面八个像素为:(x)[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
[Y5 U5 V5] [Y6 U6 V6] [Y7U7 V7] [Y8 U8 V8]
存放的码ؓ(f)Q?span>Y0 U0 Y1 Y2 U2 Y3
Y5 V5 Y6 Y7 V7 Y8
映射出的像素点ؓ(f)Q?span>[Y0 U0 V5] [Y1 U0 V5] [Y2 U2 V7] [Y3 U2 V7]
[Y5 U0 V5] [Y6 U0 V5] [Y7U2 V7] [Y8 U2 V7]对应AVPicture里面有data[4]和linesize[4]其中data是一个指向指针的指针Q二U、二l指针)Q也是指向视频数据~冲区的首地址Q而data[0]~data[3]是一U指针,可以用如下的图来表示Q?
data -->xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
^ ^ ^
| | |
data[0] data[1] data[2]
比如_(d)当pix_fmt=PIX_FMT_YUV420PӞdata中的数据是按照YUV的格式存储的Q也是Q?
data -->YYYYYYYYYYYYYYUUUUUUUUUUUUUVVVVVVVVVVVV ^ ^ ^ | | | data[0] data[1] data[2]
linesize是指对应于每一行的大小Qؓ(f)什么需要这个变量,是因为在YUV格式和RGB格式Ӟ每行的大不一定等于图像的宽度Q对于RGB格式输出?只有一个通道(bgrbgrbgr......)可用Q即linesize[0],和data[0],so RGB24 : data[0] = packet rgb//bgrbgrbgr......
linesize[0] = width*3
其他的如data[1][2][3]与linesize[1][2][3]无Q何意?
而对于YQ)格式输出Ӟ有三个通道可用Q即data[0][1][2],与linesize[0][1][2]Q而yuv格式对于q动估计Ӟ需要填充padding(right, bottom),故:(x)
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;
//因ؓ(f)是隔行扫描U与V只有高度的一?br> 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中{换RGB旉侉K倒图像的方向法