如何获取opendrive数据
前置知识:
Unity解析OSM数据,并生成简单模型
这次参考了两个开源项目:
OpenDRIVE2Unity3D
OpenDrive-Unity-Renderer
第二个项目比较好,是直接用的OpenDRIVE原本的格式。第一个项目用的数据经过处理,直接看不出来是怎么解析源数据的,生成模型的方法也许可以看看。
以下内容都是对OpenDrive-Unity-Renderer的解读。本次使用Unity解析OpenDRIVE生成路网的模型如下:
有路网和建筑模型,车跑上去效果还行,但是交叉口没有处理,还是模型重叠的状态。
二、OpenDrive概述
OpenDRIVE ®是一个开放的文件格式,用于道路网络的逻辑描述。它是由一组仿真专业人员开发并维护的,并得到了仿真行业的大力支持。它的首次公开露面是在2006年1月31日。
1.为什么要使用OpenDRIVE ®?
OpenDRIVE ®是独立于供应商,并且可以免费使用
OpenDRIVE ®包含了所有的主要功能路网
OpenDRIVE ®是一个具有广泛的国际用户群
OpenDRIVE ®是一个管理良好的格式,发展过程透明
OpenDRIVE被开发出来是为了创建一种标准的地图数据格式,方便在各种驾驶仿真模拟器中进行数据交换。
2. OpenDRIVE的特征:
XML格式
层次结构
道路几何形状的解析定义:(平面元素,横向/垂直轮廓,车道宽度等)
各种类型的车道
连接点和连接点组
通道的逻辑互连
标志和信号,包括 依存关系
信号控制器(例如用于路口)
路面特性(另请参见OpenCRG)
道路和路边物体
用户可定义的data beads
等等
3. OSM和OpenDRIVE的比较:
可以看到,OpenDRIVE也是一种XML文件,是一种矢量地图。只不过,相比OSM地图,它包含的信息更多,结构也更复杂。
4.文件下载
这里可以下载OpenDRIVE的文件规范,对每个节点、每个节点的每个属性都做了详细的解释。还可以下载示例的OpenDRIVE数据。
三、OpenDrive重要节点介绍
这是我做的一个XML节点和属性的导图。“【】”表示这个节点一般有多个。
在OpenDRIVE中,所有的道路都由一条定义基本几何图形(弧线,直线等)的reference line组成。沿着reference line,可以定义道路的各种属性。例如:高程轮廓线、交通标志等。
可以在思维导图中看到,road节点是重点,其中geometry节点就定义了reference line,而lane节点重点定义了各车道的属性。
通过指定与reference line的横向距离来创建单独的车道。reference line通过连接clothoids(又名欧拉螺旋)或多项式来构建。
请注意圆弧段和直线是clothoids的特殊情况。使用clothoids的优点是,沿着reference line的曲率随路径长度线性变化,这就是为什么大多数道路都是由clothoids构造的。
三种线的曲率变化:
1.建模用到的主要节点及属性
在项目中直接把用到的属性划个重点,接下来我们主要就看看这些属性是什么意思。
geometry.x
geometry.y
geometry.length
geometry.hdg
geometry.arc.curvature
laneSection.right.lane[i].width.a
2.geometry节点
一连串道路 geometry的节点在x/y平面(plan view)上定义了道路reference line的layout。这些geometry节点必须按照升序排列(i.e. increasing s-position). 一个子节点包含了具体的geometric元素的数据。OpenDRIVE现在支持五种geometric元素:
straight lines
spirals
arcs
cubic polynomials
parametric cubic polynomials
geometry节点的属性:
这里的s-coordinate是指:
inertial是指:
我们看一个具体的例子:
这里的reference line的类型是line,并且起始点的坐标是(x,y)=(512.5,-2250),它的heading朝向的弧度约是1.57,line的长度为583。我们知道了道路参考线的起点、朝向、长度就可以确定这个参考线的位置了。
3.lane的width节点
lanes节点由多个laneSection节点组成。若不定义新的lane section节点,它定义的数值就始终有效,适用于接下来的road(Each lane section is valid until the next lane section is defined)。所以每条road至少有一个从s=0.0m起始的lane section。
一个lane section至少包含left/center/right三种节点中的一个。lane节点被包含在left/center/right节点中。车道用数字ID来区分,这些ID有如下特点:
唯一
连续 (i.e. without gaps),
starting from 0 on the reference line
向左侧递增 (positive t-direction)
向右侧递减 (negative t-direction)
每条road的lane的数量是不限的。 reference line被定义为 lane zero,且不允许有width节点,因为它的宽度总为0。
除了center里面的lane,其他lane至少有一个width节点。和lane section一样,如果不定义下一个width节点的话,它定义的数值就一直适用于接下来的lane。如果一个lane有多个width节点,它们必须按照升序排列。
width节点的属性如下:
看看具体数据:
上述的lane的width节点中,只有属性“a”的值不为0。观察了下整个xml文件,发现几乎所有的width节点的属性都一样,只有a有值。那么a的含义是什么呢?
查文档后发现,在给定点处的实际宽度是用三阶多项式函数计算的,这个函数看起来像这样: w i d t h = a + b ∗ d s + c ∗ d s 2 + d ∗ d s 3 width = a + b*ds + c*ds^2 + d*ds^3 width=a+b∗ds+c∗ds2+d∗ds3其中,width就是给定点(位于reference line上的点?)处的车道宽度。a,b,c,d是常数系数。ds是the distance along the reference line between the start of the entry and the actual position.总体来讲,如果车道宽度变化比较复杂,那么计算也比较复杂。但是在本xml文件中,对车道的宽度做了简化,所有宽度都为10,ds相乘的系数都为0。
四、根据解析得到的数据创建道路模型
对于每条道路,已知它们的参考线起点坐标、参考线方向、长度。在这个xml文件中只有两种参考线类型,line和arc。我们可以把line和arc都用贝塞尔曲线来表示。根据参考线的信息,得到相应贝塞尔曲线上点的坐标,从而确定最终的模型顶点,渲染出模型。
(PS:其实我们也可以不用贝塞尔曲线,使用和OSM数据生成模型一样的方法。因为不管是line还是arc,实际上都是由线段拼接表示的,我们得到线段的顶点后,完全可以直接用这些顶点生成Mesh。)
按照这个思路,我们可以创建一个脚本BezierCurvePath,用来单独绘制每条road。在绘制road时,分为两个步骤:首先把这条road的参考线转为贝塞尔曲线上的点;再根据贝塞尔曲线上的点确定模型顶点,进行渲染。
1.把reference line表示为Bezier曲线
(1)Bezier曲线介绍
在这个网站可以调整控制点,并实时看到Bezier曲线的效果。
搬一个数学总结:
(2)获取一条road reference line的信息
public ListBezierCurveData curveDatas = new ListBezierCurveData();
void Start()
{
float length_s = 0f,x = 0f, y = 0f;
float angle = 0f,curvature = 0f,patchWidth = 0f; int lanes = 0;
string path = Application.dataPath+ "/XMLFiles/cloverleaf.xml";
XmlSerializer serializer = new XmlSerializer(typeof(OpenDRIVE));
string xml = File.ReadAllText(path);
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
{
openDrive = (OpenDRIVE)serializer.Deserialize(stream);
//这个脚本只能处理一个road,所以设置了一个roadVariable来指定road的index
//reference line起点的x坐标
x = openDrive.roads[roadVariable].plainView.geometry.x;
//reference line起点的y坐标
y = openDrive.roads[roadVariable].plainView.geometry.y;
//reference line的长度
length_s = openDrive.roads[roadVariable].plainView.geometry.length;
//reference line 的heading角度
angle = openDrive.roads[roadVariable].plainView.geometry.hdg;
//生成道路模型的宽度:车道数x10
cubeThickness = openDrive.roads[roadVariable].lanes.laneSection.right.lane.Length * 10;
//如果reference是arc,存储曲率
try {curvature = openDrive.roads[roadVariable].plainView.geometry.arc.curvature;}
catch (NullReferenceException e){}
}
CityGenerator(x, y, length_s, angle, curvature);
}
登录后复制

(3)根据reference line信息生成Bezier曲线数据
A. Line
void CityGenerator(float x, float y, float len, float angle, float curvature)
{
float x_end = 0.0f, y_end = 0.0f;
if (curvature != 0.0f) {......}
else{
//根据length和theta角度算出endPos
x_end = len * Mathf.Cos (angle);
y_end = len * Mathf.Sin (angle);
//按照长度,将line等分为3段,这样就可以得到4个点了
float add_pointx = x_end / 3, add_pointy = y_end / 3;
float point1x, point2x, point3x, point4x;
float point1y, point2y, point3y, point4y;
point1x = x;
point2x = point1x + add_pointx;
point3x = point2x + add_pointx;
point4x = point3x + add_pointx;
point1y = y;
point2y = point1y + add_pointy;
point3y = point2y + add_pointy;
point4y = point3y + add_pointy;
//定义Bezier曲线的4个控制点
var curve = new BezierCurveData ();
curve.points = new Vector3[4]
{
new Vector3 (point1x, 0.1f, point1y),
new Vector3 (point2x, 0.1f, point2y),
new Vector3 (point3x, 0.1f, point3y),
new Vector3 (point4x, 0.1f, point4y)
};
curveDatas.Add (curve);
}
}
登录后复制

B. Arc
关于曲率的介绍
先搞懂这些角度、点的含义:
在下面这张图中,我们可以看到坐标系原点在右下角,x轴和z轴垂直,构成了水平面,这和Unity场景中的俯视图看到的坐标系是一样的。在opendrive的数据中,reference line的起点所在坐标系也是平面坐标系,是用x和y来表示的,这里的y和unity中的z等同,都是水平面上与x轴垂直的轴。
我自定义了一个reference line,它的xml节点属性值如下:起点的坐标为(x,y)=(0,0),hdg=1.57,转换为角度为90度,这条arc的弧长为1374m。这里的hdg,指的就是这条弧在起点处的切线,与x轴的夹角。从图上也可以看出来是90度。
在下面这段代码中,startAngle就是hdg的值,roadLength就是弧长,radius根据曲率的绝对值计算得到,值为875,(在xml的注释中已经写出)。如果曲率的值小于0,那么这条arc的方向就是顺时针的。centerX和centerY是arc所在圆的圆心的横纵坐标。
if (curvature != 0.0f) {
float startAngle = angle;
float roadLength = len;
float radius = 1.0f / Mathf.Abs (curvature);
bool clockwise = curvature 0.0f;
float centerX = x - radius * Mathf.Cos (startAngle - HALF_PI) * (clockwise ? -1.0f : 1.0f);
float centerY = y - radius * Mathf.Sin (startAngle - HALF_PI) * (clockwise ? -1.0f : 1.0f);
......
}
登录后复制
计算圆心需要考虑startAngle、clockwise的值,我们就用最简单的图上的这个arc为例:startAngle=HALF_PI,clockwise为true,所以 c e n t e r X = x − r a d i u s ∗ C o s ( 0 ) ∗ ( − 1 ) = x + r a d i u s centerX=x-radius*Cos(0)*(-1)=x+radius centerX=x−radius∗Cos(0)∗(−1)=x+radius c e n t e r Y = y − r a d i u s ∗ S i n ( 0 ) ∗ ( − 1 ) = y centerY=y-radius*Sin(0)*(-1)=y centerY=y−radius∗Sin(0)∗(−1)=y也就得到了图上所示的center点的坐标。
在得到如上信息后,我们可以考虑如何创建多个折线段来表示这么长的弧线,每个折线段可以用一条贝塞尔曲线来表示,该贝塞尔曲线的中间两个点分别和起点终点重合。可以用下面getNewCurve函数来构建具体的贝塞尔曲线:我们只需要输入该折线段的起点和终点的vector。
为了获得这些小折线段的起点(start_vector )和终点(second_vector),我们可以使用一个while循环,当这些小折线段的总长度没有达到弧线长度时,就不断更新start_vector 和second_vector。
......
//将 r 减去一个车道宽度(10)
float r = radius * (clockwise ? 1.0f : -1.0f);
Vector3 first_vector = new Vector3 ();//定义整个 arc 的第一个折线段起点
if (roadLength 750) {
r = -r;
first_vector = getCurvePart (startAngle, r - 10, centerX, centerY);
} else
first_vector = getCurvePart (startAngle, r - 10, centerX, centerY);
//these are two vectors starting and ending point of the curve
var end_vector = new Vector3 (x, 0.01f, y);
var start_vector = first_vector;
float distance = 0f;//折线段总长度
while (true) {
//每次增加一点角度,使得second_vector不断向end_vector靠近。
startAngle = startAngle + 0.05f;
var second_vector = getCurvePart (startAngle, r - 10, centerX, centerY);
var curve_new = new BezierCurveData ();
//循环的结束条件:总长度超过弧长
distance += Vector3.Distance (start_vector, second_vector);
if (distance = roadLength) {
curve_new = getNewCurve (start_vector, end_vector);
curveDatas.Add (curve_new);
start_vector = second_vector;
break;
}
curve_new = getNewCurve (start_vector, second_vector);
curveDatas.Add (curve_new);
start_vector = second_vector;
在每次循环中,递增startAngle使得second_vector不断向end_vector靠近,这是通过getCurvePart函数实现的:(start_x,start_y)构成的向量和(center_x,center_y)构成的向量相加,得到我们的目标向量(所代表的的点在arc上)。
Vector3 getCurvePart(float start_angle, float r, float center_x, float center_y)
{
float start_x = 0.0f,start_y = 0.0f;
start_x = r * Mathf.Cos(start_angle);
start_y = r * Mathf.Sin(start_angle);
return new Vector3(start_x + center_x, 0.1f, start_y + center_y);
}
登录后复制
2.把Bezier曲线渲染为Mesh
得到curveData数组后,我们遍历每一条曲线,生成一个curve游戏对象,再生成具体的Mesh,作为curve游戏对象的子物体。对于line来说,curveData数组只有一个元素,对于arc来说,有很多个元素。
void CreateMesh()
{
for (int i = 0; i curveDatas.Count; i++)
{
if (curveMeshes.Count i)
{ //此函数会在Update中实时调用,已经生成对象后就直接调用对象的CreateMesh函数
curveMeshes[i].CreateMesh();
}
else
{ //首次遍历时,先创建curveMesh对象实例
var curveMesh = BezierCurveMesh.Instantiate(i, this);
curveMeshes.Insert(i, curveMesh);
如果想知道具体是怎么生成的Mesh,可以参考这个开源项目:unity-procedural-mesh-bezier-curve。本项目的这部分代码就是引用于它(也可以在本项目中直接查看相关代码,不过这部分和路网生成关系不大,就不放在这里解读了)。
五、沿着道路随机生成建筑物
(1)准备好建筑物的prefab共15个
(2)沿着道路随机摆放建筑物
可以观察到:建筑与路面之间有一定的距离;建筑不会摆放到道路上去;建筑都朝向路面。
关于实现方法,简单来说就是要分成line和arc类型来处理。在处理每种路面的时候也要考虑线段的方向,从而确定房屋摆放的位置。这部分细节比较多,如果需要优化或者修改,可以详细看看。
六、给道路添加程序纹理
道路模型没有按照车道区分,所以多车道其实也是一个模型。而单车道和多车道,外表是不同的。
本项目对于单车道和多车道使用的是同一张图片,但是对于多车道,在其上绘制了白色的线,作为新的贴图。
如何使用mencoder
mencoder 是一款命令行方式的视频处理软件,是Mplayer自带的编码工具(Mplayer是Linux下的播放器,开源,支持几乎所有视频格式的播放,现在有windows和Mac版本)。 在linux下,安装完Mplayer后,就有mencoder,无需另外安装。 mencoder支持几乎所有的格式的视频转换,可以将任意格式转换到任意格式,转换功能可以说是相当强大。目前市面上流行的格式转换器,都是基于mencoder开发的GUI,比如暴风转码,格式工厂等。可以说转换器能办到的,mencoder都能办到,但mencoder能办到的,转换器就不一定能办到了。 很多初学者宁可去用转换器,也不用mencoder的很大原因是mencoder只支持在命令行 mencoder
下操作,令很多初学都无所适从,不知如何开始.这也是mencoder不能流行开来的原因.
编辑本段【mencoder进程】
进程名称: mencoder.exe
英文描述: N/A
进程分析: 视频转换软件的相关程序。(很多视频转换软件的核心都是mencoder,也可以说是基于mencoder设计的,软件只是它的一个外壳,一种界面而已。)
进程位置: unknown
程序用途: 视频格式转换
作者: mplayer
属于: mplayer
安全等级 (0-5): N/A (N/A无危险 5最危险)
间碟软件: 否
广告软件: 否
病毒: 否
木马: 否
编辑本段【基本参数】
例如:mencoder input.avi -o output.avi -oac mp3lame -lameopts cbr:br=32 -ovc x264 -x264encopts bitrate=440 -vf scale=448:-3 input.avi 是指输入的视频,也就是你要转换的视频。 -o output.avi 中的“-o”是指你要输出视频,输出的视频名为output.avi。 -oac 设置音频编码器。 mp3lame 设置音频编码器为mp3lame,也是就mp3。 -lameopts 设置mp3lamer的相关参数。 cbr:br=32 设置音频的码率为32。 -ovc 设置视频编码器。 x264 设置视频编码器为x264。 -x264encopts 设置x264的参数。 bitrate-440 设置x264的视频的码率为440。 -vf scale=448:-3 设置视频的宽为448,高为-3,-3的意思就是让mencoder来设置最佳宽度。 mencoder2
以上参数只是很少一部分,还有很多,无法一一列举。如果真心想学,就多用搜索引擎进行学习。
图片编辑参数
#用当前目录中的所有JPEG文件创建DivX4文件: mencoder *.jpg -mf on:w=800:h=600:fps=25 -ovc divx4 -o output.avi #用当前目录中的一些JPEG文件创建DivX4文件: mencoder -mf on:w=800:h=600:fps=25 -ovc divx4 -o output.avi *.jpg #用当前目录中的所有JPEG文件创建Motion JPEG(MJPEG)文件: mencoder -mf on:w=800:h=600:fps=25 -ovc copy -o output.avi *.jpg #用当前目录中的所有PNG文件创建一个非压缩的文件: mencoder -mf on:w=800:h=600:fps=25:type=png -ovc rawrgb -o output.avi *.png 简单用法: mencoder *.jpg -mf on:fps=15 -o output.avi -ovc xvid
视频合并参数
mencoder -oac copy -ovc copy -idx -o output.avi video1.avi video2.avi video3.avi * 其中,-oac copy 选项告诉 mencoder 要正确拷贝音频流。而 -ovc copy 选项则是拷贝视频流。 * 如果在视频文件中没有找到索引的话,那么 -idx 选项会要求 mencoder 建立它。 * -o 选项指定输出文件的名称。 * 最后几个参数为需要合并的几个视频片段。
其它参数:
-ss 设置转换开始时间,如:-ss 15 代表从视频的15秒开始转换 -endpos 设置转换结束时间,如:-endpos 60 在视频的60秒处结束转换 -mc 0 设置音视频同步,增这个参数可防止音频和视频出现不同步现象 -noskip 设置禁止跳帧,不过这个参数基本没用,可忽视。 提取音频代码: mencoder -oac mp3lame -ovc copy -of rawaudio 视频文件 -o 音频文件 无声参数: -nosound 截段参数: -ss 开始时间 -endpos 截取总时间 加入音频: -audiofile 音频文件 三通道编码方法如下: rm frameno.avi -- 移去这个文件,它可能来自以前的3-pass编码(它会干扰当前编码) mencoder dvd://2 -ovc frameno -o frameno.avi -oac mp3lame -lameopts vbr=3 mencoder dvd://2 -ovc lavc -lavcopts vcodec=mpeg4:vpass=1 -oac copy -o movie.avi mencoder dvd://2 -ovc lavc -lavcopts vcodec=mpeg4:vpass=2 -oac copy -o movie.avi
常用参数视频编码对照表
mencoder 参数说明 参数设置 视频编码设置 音频编码设置
mencoder.exe -oac mp3lame -lameopts aq=7:mode=0:vol=1.2:vbr=2:q=6 -delay -1 -srate 32000 -vf scale=320:-3,harddup -ofps 15 -ovc xvid -xvidencopts fixed_quant=11 infile.wmv -o outfile.avi
视频设置
参数 视频编码 说明
-vf harddup -ofps 15 -ovc lavc -ffourcc DX50 -lavcopts vcodec=mpeg4:vbitrate=440 DIVX 固定码率 DIVX压缩速度快,画质低 DIVX 固定码率
-vf harddup -ofps 15 -ovc lavc -ffourcc DX50 -lavcopts vcodec=mpeg4:vqscale=11 DIVX 动态码率 DIVX压缩速度快,画质低 DIVX 动态码率 可以大幅度改善画质
-vf harddup -ofps 15 -ovc xvid -xvidencopts bitrate=440 XVID 固定码率 画质较高 XVID 固定码率
-vf harddup -ofps 15 -ovc xvid -xvidencopts fixed_quant=11 XVID 动态码率 XVID压缩速度慢,画质较高 XVID 固定码率 可以大幅度改善画质
-vf harddup -ofps 15 -ovc x264 -x264encopts bitrate=440 x264 固定码率 x264压缩速度最慢,画质最高 x264 固定码率
-ovc copy 视频直接复制
视频其它参数说明
-ofps 15 帧数 15 范围 Fps(10-30)
vcodec=mpeg4:vbitrate=440 编码率 440 kbps 范围kbps(180-1600)
-xvidencopts bitrate=440 编码率 440 kbps 范围kbps(180-1600)
-xvidencopts fixed_quant=11 动态编码率 11 (1-31,1画质最佳)
-x264encopts bitrate=440 编码率 440 kbps 范围kbps(180-1600)
-vf scale=320:240,harddup 画面大小 320x240
-vf scale=320:-3,harddup 画面大小 320x240 自适应高度
音频设置
参数 音频编码 说明
-oac mp3lame -lameopts aq=7:cbr:br=96 -srate 32000 MP3 固定码率
-oac mp3lame -lameopts aq=7:abr:br=96 -srate 32000 MP3 平均码率
-oac mp3lame -lameopts aq=7:vbr=2:q=6 -srate 32000 MP3 动态码率 可以达到很高的音质
-oac lavc -lavcopts acodec=mp2:abitrate=96 -srate 32000 MP2 平均码率
-oac lavc -lavcopts acodec=ac3:abitrate=96 -srate 32000 AC3 平均码率
-oac copy 音频直接复制
aq=7:cbr:br=96 -srate 32000 aq=7 音频算法 7 数字越小失真越少,但压缩速度越慢
aq=7:cbr:br=96 -srate 32000 br=96 编码率 96 kbps 数值越大音质越高
aq=7:cbr:br=96 -srate 32000 -srate 3200 音频采样率 3200 hz 数值越大清晰度越高
-oac mp3lame -lameopts aq=7:vol=1.2:abr:br=96 -srate 32000 vol=1.2 音量放大 音量过大会造成暴音
-lameopts aq=7:vol=1.2:abr:br=96 -delay -1 -srate 32000 -delay -1 音频延迟 -1 秒 负数表示声音快于图像
-lameopts aq=7:vol=1.2:abr:br=96 -delay 1 -srate 32000 -delay 1 音频延迟 1 秒 图像快于声音
编辑本段【编解码器及容器格式】
音频编码器: 音频编码器名称 描述
mp3lame 通过LAME编码为VBR,ABR或CBR格式的MP3文件
lavc 利用libavcodec中的一个编码器
faac FAAC AAC音频编码器
toolame MPEG音频Layer 2编码器
twolame 基于tooLAME的MPEG音频Layer 2编码器
pcm 未压缩的PCM音频
copy 不要重新编码,这是复制已压缩的各桢
Audio codec name Description
ac3 Dolby Digital (AC-3)
adpcm_* Adaptive PCM formats - see supplementary table
flac Free Lossless Audio Codec (FLAC)
g726 G.726 ADPCM
libfaac Advanced Audio Coding (AAC) - using FAAC
libgsm ETSI GSM 06.10 full rate
libgsm_ms Microsoft GSM
libmp3lame MPEG-1 audio layer 3 (MP3) - using LAME
mp2 MPEG-1 audio layer 2 (MP2)
pcm_* PCM formats - see supplementary table
roq_dpcm Id Software RoQ DPCM
sonic experimental FFmpeg lossy codec
sonicls experimental FFmpeg lossless codec
vorbis Vorbis
wmav1 Windows Media Audio v1
wmav2 Windows Media Audio v2
视频编码器: 是频编码器名称 描述
lavc 使用libavcodec中的一个是频编码器
xvid Xvid, MPEG-4高级简单格式(ASP)编码器
x264 x264, MPEG-4高级视频编码(AVC), AKA H.264编码器
nuv nuppel视频,为一些实时程序所用
raw 未压缩的视频桢
copy 不要重新编码,只是复制已压缩的各桢
frameno 用于三通道编码(不推荐)
Video codec name Description
mjpeg Motion JPEG
ljpeg lossless JPEG
jpegls JPEG LS
targa Targa image
gif GIF image
bmp BMP image
png PNG image
h261 H.261
h263 H.263
h263p H.263+
mpeg4 ISO standard MPEG-4 (DivX, Xvid compatible)
msmpeg4 pre-standard MPEG-4 variant by MS, v3 (AKA DivX3)
msmpeg4v2 pre-standard MPEG-4 by MS, v2 (used in old ASF files)
wmv1 Windows Media Video, version 1 (AKA WMV7)
wmv2 Windows Media Video, version 2 (AKA WMV8)
rv10 RealVideo 1.0
rv20 RealVideo 2.0
mpeg1video MPEG-1 video
mpeg2video MPEG-2 video
huffyuv lossless compression
ffvhuff FFmpeg modified huffyuv lossless
asv1 ASUS Video v1
asv2 ASUS Video v2
ffv1 FFmpeg's lossless video codec
svq1 Sorenson video 1
flv Sorenson H.263 used in Flash Video
flashsv Flash Screen Video
dvvideo Sony Digital Video
snow FFmpeg's experimental wavelet-based codec
zmbv Zip Motion Blocks Video
dnxhd AVID DNxHD
容器格式: 容器格式名称 描述
lavf 由libavformat 支持的一种容器
avi 音-视频混合
mpeg MPEG-1及MPEG-2节目流
rawvideo 原始视频流(未经混合 - 只含一视频流)
rawaudio 原始音频流(未经混合 - 只含一音频流)
libavformat容器: 如果你选择了libavformat 来做输出文件的混编(通过使用-of lavf选项),适当的容器将由文件扩展名而定。你也可以通过libavformat的 format选项强制一种容器格式。 libavformat容器名称 描述
mpg MPEG-1及MPEG-2节目流
asf 高级流格式
avi 音-视频混合
wav 波形音频
swf Macromedia Flash
flv Macromedia Flash视频
rm RealMedia
au SUN AU
nut NUT开放容器(实验中,不兼容标准)
mov QuickTime
mp4 MPEG-4格式
dv Sony数字视频容器
非本人答案!!!
ASP记忆表单如何实现?请高手指教
script
//[Cookie] 写入cookie
function setCookie(cookieName, cookieValue, expires, path, domain, secure) {
document.cookie = escape(cookieName) + '=' + escape(cookieValue)
+ (expires ? '; expires=' + expires.toGMTString() : '')
+ (path ? '; path=' + path : '')
+ (domain ? '; domain=' + domain : '')
+ (secure ? '; secure' : '');
}
/*// [Cookie] 获取cookie设置*/
function getCookie (cookieName) {
var cookieValue = '';
var posName = document.cookie.indexOf(escape(cookieName) + '=');
if (posName != -1) {
var posValue = posName + (escape(cookieName) + '=').length;
var endPos = document.cookie.indexOf(';', posValue);
if (endPos != -1) cookieValue = unescape(document.cookie.substring(posValue, endPos));
else cookieValue = unescape(document.cookie.substring(posValue));
}
return (cookieValue);
}
//判断是否已存在cookies,如有,则直接等于
function getsname()
{
if (getCookie("sname")!="") {
form1.sname.value=getCookie("sname");
}
}
//判断是否无,若无,则写入
function setsname(){
if (getCookie("sname")=="") {
setCookie("sname",form1.sname.value);
}
}
/script
在body中加入 onLoad="getsname()" 意思是一载入网页,则判断是否有这个,有就直接给他写入原来的值
在input sname中加入 onBlur="setsname()" 意思是这个输入框一旦失去焦点(即在此输入数据后将当前移到其它区域)则判断是否写了,若没写,则写入
帮看个JAVA小程序语法问题
估计这个要打些字呢。
先说第一个问题吧。
//这句话中怎么调用的compare方法 给详细讲解下
这个问题主要就是解释下这句话a[j].compare(a[j+1]) 。
我们不用考虑这么多日期,就拿两个日期来讲吧,道理是一样的。
假设是a1.compare(a2),执行这行代码的时候就会进入public int compare(Date date) {}方法。你的一系列问题也在这里啊。
------------------------------------------------------------------
public int compare(Date date) { //我不明白这里的(Date date)是什么意思 进来的时候是2个参数?
----------------------------------------------------华丽的分割线
这个是传进来一个参数,举个例子,假设方法我改造如下:
public int compare(int date)
public int compare(String date)
public int compare(double date)
你能明白上面三个方法的意思么。就是传进来一个参数date,第一个它的类型是int,第二个是string 最后一个是double类型。同理public int compare(Date date)的意思就是传进来一个参数date它的类型是Date。不要被小写的date搞的迷惑了 也可以写成public int compare(Date a2)道理是一样的。date只不过是个名称,Date是这个参数名称的类型。
---------------------------------------------------------------
//到这句话中哪个是year哪个是date.year
----------------------------------------------------华丽的分割线ag
我把上面代码改写下,你会清楚些。
public int compare(Date date) {
return this.year date.year ? 1
: this.year date.year ? -1 : this.month date.month ? 1
: this.month date.month ? -1
: this.day date.day ? 1
: this.day date.day ? -1 : 0;
}
我在一些变量前面加上了this。代表对象本身。举个例子:
a1.compare(a2) 就是对象a1调用他的compare方法。而a2是做为Date型参数传进来,结果就相当于下面:(实际代码不能这么写,只是示范)
public int compare(Date a2) {
return a1.year a2.year ? 1
: a1.year a2.year ? -1 : a1.month a2.month ? 1
: a1.month a2.month ? -1
: a1.day a2.day ? 1
: a1.day a2.day ? -1 : 0;
明白了吗?year前面默认不加上"this"的话,也还是指对象本身的属性,新手常常会混淆。
---------------------------------------------------------------------
三目的这个运算明白 给讲讲上面的语法就行
--------------------------------------------------------------------囧
这个比较难讲了 大概说下吧。
1. a1.year a2.year ? 1
2. : a1.year a2.year ? -1 3. : a1.month a2.month ? 1
4. : a1.month a2.month ? -1
5. : a1.day a2.day ? 1
6. : a1.day a2.day ? -1 : 0);
先解释下运算符 a1 a2 ? 1:0 这句话的意思是如果a1大于a2是真的话,就取问号后面的第一个数,也就是1.是假的话就取冒号后面的0.
接着解释上面代码。 第一行 如果a1的年大于a2的年,那么好说,后面不必比较了a1这个日期肯定大于a2,直接返回1.但是如果是假d的话,就要取冒号后面的参数也就是2-6行的所以代码。2-6行里面又嵌套了几个运算符,第2行的意思就是如果a1的年小于a2的年,那么返回-1,也还是不用比较了,你a1的年份就是比我a2小了,这时候如果a1等于a2年份的话,就不返回-1了还要继续比较月份,也就是后面的代码,3行的代码。以后我就不解释了,你自己揣摩揣摩吧,就说这么多了,手疼。。
关于endpos是什么意思和endpoin的介绍本篇到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。
标签: 节点
②文章观点仅代表原作者本人不代表本站立场,并不完全代表本站赞同其观点和对其真实性负责。
③文章版权归原作者所有,部分转载文章仅为传播更多信息、受益服务用户之目的,如信息标记有误,请联系站长修正。
④本站一律禁止以任何方式发布或转载任何违法违规的相关信息,如发现本站上有涉嫌侵权/违规及任何不妥的内容,请第一时间反馈。发送邮件到 88667178@qq.com,经核实立即修正或删除。