当前位置:文档之家› FFMpeg SDK 开发手册

FFMpeg SDK 开发手册

FFMpeg SDK 开发手册
FFMpeg SDK 开发手册

FFMpeg SDK 开发手册FFMpeg 中比较重要的函数以及数据结构如下:

1.数据结构:

(1)A VFormatContext

(2)A VOutputFormat

(3)A VInputFormat

(4)A VCodecContext

(5)A VCodec

(6)A VFrame

(7)A VPacket

(8)A VPicture

(9)A VStream

2.初始化函数:

(1)av_register_all()

(2)avcodec_open()

(3)avcodec_close()

(4)av_open_input_file()

(5)av_find_input_format()

(6)av_find_stream_info()

(7)av_close_input_file()

3.音视频编解码函数:

(1)avcodec_find_decoder()

(2)avcodec_alloc_frame()

(3)avpicture_get_size()

(4)avpicture_fill()

(5)img_convert()

(6)avcodec_alloc_context()

(7)avcodec_decode_video()

(8)av_free_packet()

(9)av_free()

4.文件操作:

(1)avnew_steam()

(2)av_read_frame()

(3)av_write_frame()

(4)dump_format()

5.其他函数:

(1)avpicture_deinterlace()

(2)ImgReSampleContext()

以下就根据,以上数据结构及函数在ffmpeg测试代码output_example.c中出现的前后顺进行分析。在此之前还是先谈一下ffmpeg的编译问题。在linux下的编译比较简单,这里不多说了。在windows下的编译可以参考以下网页:

https://www.doczj.com/doc/aa5285631.html,/viewthread.php?tid=1897&extra=page%3D1

值得一提的是,在使用编译后的sdk进行测试时(用到ffmpeg目录下的output_example.c)编译过程中可能会有以下两个问题:

1.Output_example.c用到了snprintf.h这个头文件。然而这个头文件在win下和linux下有所不同。

具体在win下可以用以下方法解决:

http://www.ijs.si/software/snprintf/

2.如果使用vc6,或是vc6的命令行进行编译,inline可能不认。错误会出现在common.h文件中,可以在common.h中加入

#ifdef _MSC_V AR

#define inline __inline

#endif

交待完毕进入正题。

一.FFMpeg 中的数据结构:

I. AVFormatContext

一般在使用ffmpeg sdk的代码中A VFormatContext是一个贯穿始终的数据结构,很多函数都要用到它作为参数。FFmpeg代码中对这个数据结构的注释是:format I/O context

此结构包含了一个视频流的格式内容。其中存有了A VInputFormat(or A VOutputFormat同一时间A VFormatContext内只能存在其中一个),和A VStream、A VPacket这几个重要的数据结构以及一些其他的相关信息,比如title,author,copyright等。还有一些可能在编解码中会用到的信息,诸如:duration, file_size, bit_rate等。参考avformat.h头文件。

Useage:

声明:

A VFormatContext *oc; (1)

初始化:由于A VFormatConext结构包含许多信息因此初始化过程是分步完成,而且有些变量如果没有值可用,也可不初始化。但是由于一般声明都是用指针因此一个分配内存过程不可少:

oc =av_alloc_format_context(); (2)

结构中的A VInputFormat*(或A VOutputFormat*)是一定要初始化的,基本上这是编译码要使用什么codec的依据所在:

oc->oformat

fmt; (3)

or oc->iformat

=

=

fmt;

其中A VOutputFormat* fmt或A VInputFormat* fmt。(A VInputFormat and A VOutputFormat的初始化在后面介绍。随后在参考代码output_example.c中有一行:

snprintf(oc-filename, sizeof(oc->filename), “%s”, filename); (4)

还不是十分清楚有什么作用,估计是先要在输出文件中写一些头信息。

在完成以上步骤後,(初始化完毕A VInputFormat*(或A VOutputFormat*)以及A VFormatContext)接下来就是要利用oc初始化本节开始讲到的A VFormatContext中的第二个重要结构。A VStream(假设已经有了声明A VStream *video_st。参考代码中用了一个函数来完成初始化,当然也可以在主函数中做,传递进函数的参数是oc 和fmt->video_codec(这个在下一节介绍(29)):

fmt->video_codec); (5)

vdeo_st = add_video_stream(oc,

此函数会在后面讲到A VStream结构时分析。

A VFormatContext最后的一个设置工作是:

if( av_set_paramters(oc,NULL) < 0){ (6)

//handle error;

}

1); (7)

filename,

0,

dump_format(oc,

作用就是看看先前的初始化过程中设置的参数是否符合规范,否则将报错。

上面讲的都是初始化的过程,包括A VFormatContext本身的和利用A VFormatContext初始化其他数据结构的。接下来要讲讲整个的编解码过程。我想先将ouput_example.c中main函数内的编解码函数框架描述一下。这样比较清晰,而且编码者为了结构清晰,在写ouput_example.c的过程中也基本上在main函数中只保持A VFormatContext和A VStream两个数据结构(A VOutputFormat其实也在但是包含在A VFormatContext中了)。

// open video codec and allocate the necessary encode buffers

if(video_st)

video_st); (8)

open_video(oc,

// write the stream header, if any

av_write_header(oc); (9)

// encode and decode process

;){

for(;

video_st); (10)

write_video_frame(oc,

condition…here

//

break

}

//close codec

if(video_st)

video_st); (11)

close_video(oc,

//write the trailer , if any

av_write_trailer(oc); (12)

// free the streams

for(i=0; ib_streams; i++){

av_freep(&oc->streams[i]->codec); (13)

av_freep(&oc->streams[i]); (14)

}

//close the ouput file

if(!(fmt->flags & A VFMT_NOFILE)){

url_fclose(&oc->pb); (15)

}

av_free(oc); (16)通过以上的一串代码,就可以清晰地看出A VFormatContex* oc和A VStream* video_st是在使用ffmpeg SDK开发时贯穿始终的两个数据结构。以下,简要介绍一下三个标为红色的函数,他们是参考代码output_example.c开发者自行定义的函数。这样可以使整个代码结构清晰,当然你在使用ffmpeg SDK时也可以在主函数中完成对应的功能。在后面我们会专门针对这三个函数做分析。

1.open_video(oc, video_st);

此函数主要是对视频编码器(或解码器)的初始化过程。初始化的数据结构为A VCodec* codec 和A VCodecContext* c包括用到了的SDK函数有:

c = st->codec;

codec = avcodec_find_encoder(c->codec_id); //编码时,找编码器(17)

codec = avcodec_find_decoder(c->codec_id); //解码时,找解码器(18)

A VCodecContex是结构A VStream中的一个数据结构,因此在A VStream初始化後(5)直接复值给c。

// internal open video codec

avcodec_open(c,codec); (19)

// allocate video stream buffer

// A VFrame *picture

// uint8_t *video_outbuf

video_outbuf_size=200000;

video_outbuf = av_maloc(video_outbuf_size); (20)

// allocate video frame buffer

c->height); (21) picture = alloc_picture(c->pix_fmt, c->width,

上述三步比较容易理解,打开视频编解码codec、分配输出流缓存大小、分配每一帧图像缓存大小。其中A VFrame也是ffmpeg中主要数据结构之一。这一步(8)是对编解码器的初始化过程。

2.write_video_frame(A VFormatContext *oc, A VStream *st)

这个函数中做了真正的编解码工作,其中的函数比较复杂先列出来慢慢分析。

用到的数据结构有A VCodecContext *c, SwsContext *img_convert_ctx。其中SwsContext是用来变

换图像格式的。比如yuv422变到yuv420等,当然也用到函数,见下面列表。

(22)

fill_yuv_image(tmp_picture, frame_count, c->width, c->height);

sws_scale(img_convert_ctx, tmp_picture->, tmp_picture->linesize,

0, c->height, picture->data, picture->linesize); (23) img_convert_ctx = sws_getContxt(c->width, c->height, PIX_FMT_YUV420P, (24)

c->width, c->heigth, c->pix_fmt, sws_flags, NULL, NULL, NULL);

由于参考代码中做的是一个编码。因此,它总是要求编码器输入的是yuv文件,而且是yuv420格式的。就会有了以上一些处理过程。接下来调用编码器编码,数据规则化(打包)用到A VPacket,这也是ffmpeg 中一个比较不好理解的地方。

out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture); (25)

A VPacket pkt;

av_init_packet(&pkt); (26)

//……handle pkt process, we will analyze later

&pkt); (27) ret = av_write_frame(oc,

有encode就一定会有decode。而且ffmpeg专为解码而生,但是为什么在参考代码中只用了encoder 呢?个人猜想是因为encode只是用yuv420来编码,这样的yuv420生成比较容易,要是用到解码的化,还要在代码中附带一个其他格式的音视频文件。在源代码libavcodec文件夹中有一个apiexample.c的参考代码,其中就做了编解码。有空的化我会分析一下。

3.close_video(A VFormatContext *oc, A VStream *st)

avcodec_close(st->codec);

av_free(picture->data[0]);

av_free(picture);

av_free(video_outbuf);

比较容易理解,不多说了。

以上一大段虽然名为介绍A VFormatContext。但基本上把ouput_example.c的视频编码部分的框架走了一遍,其一是想说明结构A VFormatContext的重要性,另一方面也是希望对使用FFMpeg SDK开发者有一个大致的框架。

其实,真正的一些编码函数,内存分配函数在SDK中都已经封装好了,只要搞清楚结构就能用了。而开发者要做的就是一些初始化的过程,基本上就是针对数据结构1的初始化。

II. AVOutputFormat

虽然简单(初始化)但是十分重要,他是编解码器将要使用哪个codec的“指示”。在其成员数据中

最重要的就是关于视频codec的了:enum CodecID video_codec;

A VOutputFormat *fmt;

guess_format(NULL,

NULL); (28)

filename,

=

fmt

根据filename来判断文件格式,同时也初始化了用什么编码器。当然,如果是用A VInputFormat *fmt

的化,就是fix用什么解码器。(指定输出序列->fix编码器,指定输入序列->fix解码器?)

III. AVStream

A VStream作为继A VFormatContext後第二个贯穿始终的结构是有其理由的。他的成员数据中有

A VCodecContext这基本的上是对所使用的Video Codec的参数进行设定的(包括bit rate、分辨率等重要信息)。

同时作为“Stream”,它包含了“流”这个概念中的一些数据,比如:帧率(r_frame_rate)、基本时间计量

单位(time_base)、(需要编解码的)首帧位置(start_time)、持续时间(duration)、帧数(nb_frames)以及

一些ip信息。当然后面的这些信息中有些不是必须要初始化的,但是A VCodecContex是一定要初始化的,而

且就是作为初始化A VStream最重要的一个部分。我们在前面就谈到了A VStream的初始化函数(5),现在来看

看他是怎么做的:

// declaration

*video_st;

A VStream

video_st

= add_video_stream(oc, fmt->video_codec);

*add_video_stream(A VFormatContex *oc, int codec_id){ (29)

A VStream

static

*c; // member of A VStream, which will be initialized here

A VCodecContext

*st; // temporary data, will be returned

A VStream

st = av_new_stream(oc,

0); (30)

st->codec;

=

c

// 以下基本是针对c的初始化过程。包括比特率、分辨率、GOP大小等。

……

// 以下的两行需要注意一下,特别是使用MP4的

if(!strcmp(oc->oformat->name, “mp4”) || !strcmp(oc->oformat->name, “mov”) || !strcmp(oc->oformat->name, “3gp”))

CODEC_FLAG_GLOBAL_HEADER;

|=

c->flags

// 将st传给video_st;

st;

return

}

以上代码中,有几点需要注意的。一个是(30)和c = st->codec是一定要做的,当然这是编程中最基本的

问题,(30)是将st这个A VSteam绑定到A VFormatContext* oc上。后面的c = st->codec是将c绑定到st的

A VCodecContext上。其二是对c的初始化过程中,ouput_example.c里做的是一些基本的配置,当然作为使用

者的你还希望对codec加入其他的一些编解码的条件。可以参考avcodec.h里关于A VCodecContext结构的介

绍,注释比较详细的。

关于A VStream的使用在前面介绍A VFormatContext时已有所涉及,在主函数中三个编解码函数中(8)、(10)和(11)中。观察相关的代码,可以发现主要还是将A VStream中的A VCodecContext提取出来,再从中提取

出A VCodec结构如在(8)中:

// open_video(oc, video_st);

// A VFormatContext *oc, A VStream *st

A VCodec *codec;

*c;

A VCodecContext

st->codec;

=

c

avcodec_find_encoder(c->codec_id); (31)

codec

=

// open the codec

avcodec_open(c, codec); (32)

同样,我们可以看到在(10)(write_video_frame())中A VFrame 也是做为传递A VCodecContext 结构的载体而存在。(11)(close_video())比较简单,不熬述。

IV. AVCodecContext

此结构在Ffmpeg SDK 中的注释是:main external api structure 其重要性可见一斑。而且在avcodec 它的定义处,对其每个成员变量,都给出了十分详细的介绍。应该说A VCodecContext 的初始化是Codec 使用中最重要的一环。虽然在前面的A VStream 中已经有所提及,但是这里还是要在说一遍。A VCodecContext 作为Avstream 的一个成员结构,必须要在Avstream 初始化後(30)再对其初始化(A VStream 的初始化用到A VFormatContex)。虽然成员变量比较多,但是这里只说一下在output_example.c 中用到了,其他的请查阅avcodec.h 文件中介绍。

// static A VStream *add_video_stream(A VFormatContext *oc, int codec_id)

A VCodecContext *c;

st = av_new_stream(oc, 0);

c = st->codec;

c->codec_id = codec_id;

c->codec_type = CODEC_TYPE_VIDEO;

c->bit_rate = 400000; // 400 kbits/s

c->width = 352;

c->height = 288; // CIF

// 帧率做分母,秒做分子,那么time_base 也就是一帧所用时间。(时间基!)

c->time_base.den = STREAM_FRAME_RATE;

c->time_base.num = 1;

c->gop_size =12;

// here define:

// #define STREAM_PIX_FMT PIX_FMT_YUV420P

// pixel format, see PIX_FMT_xxx

// -encoding: set by user.

// -decoding: set by lavc.

c->pix_fmt = STREAM_PIX_FMT;

除了以上列出了的。还有诸如指定运动估计算法的: me_method 。量化参数、最大b 帧数:max_b_frames 。码率控制的参数、差错掩盖error_concealment 、模式判断模式:mb_decision (这个参数蛮有意思的,可以看看avcodec.h 1566行)、Lagrange multipler 参数:lmin & lmax 和 宏块级Lagrange multipler 参数:mb_lmin & mb_lmax 、constant quantization parameter rate control method: cqp 等。

值得一提的是在A VCodecContext 中有两个成员数据结构:AVCodec 、AVFrame 。A VCodec 记录了所要使用的Codec 信息并且含有5个函数:init 、encoder 、close 、decode 、flush 来完成编解码工作(参见avcode.h 2072行)。A VFrame 中主要是包含了编码後的帧信息,包括本帧是否是key frame 、*data[4]定义的Y 、Cb 和Cr 信息等,随后详细介绍。

初始化後,可以说A VCodecContext 在(8)&(10)中大显身手。先在(8)open_video()中初始化A VCodec *codec 以及A VFrame* picture :

// A VCodecContext *c;

codec = avcodec_find_encoder(c->codec_id);

……

picture = alloc_picture(PIX_FMT_YUV420P, c->width, c->height);

後在writer_video_frame(A VFormatContext *oc, A VStream *st)中作为一个编解码器的主要参数被利用:

A VCodecContext *c;

c = st->codec;

……

out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture);

V .AVCodec

结构A VCodec 中成员变量和成员函数比较少,但是很重要。他包含了CodecID ,也就是用哪个Codec 、

像素格式信息。还有前面提到过的5个函数(init、encode、close、decoder、flush)。顺便提一下,虽然在参考代码output_example.c中的编码函数用的是avcodec_encode_video(),我怀疑在其中就是调用了A VCodec的encode函数,他们传递的参数和返回值都是一致的,当然还没有得到确认,有兴趣可以看看ffmpeg源代码。在参考代码中,A VCodec的初始化後的使用都是依附于A VCodecContex,前者是后者的成员。在A VCodecContext初始化後(add_video_stream()),A VCodec也就能很好的初始化了:

//初始化

=avcodec_find_encoder(c->codec_id); (33)

codec

//打开Codec

avcodec_open(c, codec)(34)

VI. AVFrame

A VFrame是个很有意思的结构,它本身是这样定义的:

typedef struct A VFrame {

FF_COMMON_FRAME

}A VFrame;

其中,FF_COMMON_FRAME是以一个宏出现的。由于在编解码过程中A VFrame中的数据是要经常存取的。为了加速,要采取这样的代码手段。

A VFrame是作为一个描述“原始图像”(也就是YUV或是RGB…还有其他的吗?)的结构,他的头两个成员数据,uint8_t *data[4],int linesize[4],第一个存放的是Y、Cb、Cr(yuv格式),linesize是啥?由这两个数据还能提取处另外一个数据结构:

typedef struct A VPicture {

*data[4];

uint8_t

int linesize[4]; // number of bytes per line

}A VPicture ;

此外,A VFrame还含有其他一些成员数据,比如。是否key_frame、已编码图像书coded_picture_number、是否作为参考帧reference、宏块类型 *mb_type等等(avcodec.h 446行)。

A VFrame的初始化并没有他结构上看上去的那么简单。由于A VFrame还有一个承载图像数据的任务(data[4])因此,对他分配内存应该要小心完成。output_example.c中提供了alloc_picute()来完成这项工作。参考代码中定义了两个全局变量:A VFrame *picture,*tmp_picture。(如果使用yuv420格式的那么只用到前一个数据picture就行了,将图像信息放入picture中。如果是其他格式,那么先要将yuv420格式初始化后放到tmp_picture中在转到需求格式放入picture中。)在open_video()打开编解码器后初始化A VFrame:picture = alloc_picture(c->pix_fmt, c->width, c->height);

tmp_picture = alloc_picture(PIX_FMT_YUV420P, c->width, c->height);

static A VFrame *alloc_picture(int pix_fmt, int width, int height){

*picture;

A VFrame

*picture_buf; // think about why use uint8_t? a byte!

uint8_t

=

avcodec_alloc_frame(); (35) picture

if(!picture)

return NULL;

size = avpicture_get_size(pix_fmt, width, height); (36)

av_malloc(size); (37)

=

picture_buf

if(!picture_buf){

av_free(picture); (38)

return NULL;

}

avpicture_fill ( (A VPicture *)picture, picture_buf, pix_fmt, width, height); (39) picture;

return

}

从以上代码可以看出,完成对一个A VFrame的初始化(其实也就是内存分配),基本上是有这样一个固定模式的。至于(35)(39)分别完成了那些工作,以及为什么有这样两步,还没有搞清楚,需要看原代码。我的猜测是(35)对A VFrame做了基本的内存分配,保留了对可以提取出A VPicture的前两个数据的内存分配到(39)来完成。

说到这里,我们观察到在(39)中有一个(A VPicture *)picture,A VPicture这个结构也很有用。基本上他的大小也就是要在网络上传输的包大小,我们在后面可以看到A VPacket跟A VPicture有密切的关系。

VII.AVPicture

A VPicture在参考代码中没有自己本身的申明和初始化过程。出现了的两次都是作为强制类型转换由A VFrame中提取出来的:

// open_video() 中

avpicture_fill((A VPicture *)picture, picture_buf, pix_fmt, width, height); (40)

//write_video_frame 中

pkt;

A VPacket

//

if(oc->oformat->flags & A VFMT_RAWPICTURE){

……

pkt.size = sizeof(A VPicture); (41) }

在(40)中,实际上是对A VFrame的data[4]、linesize[4]分配内存。由于这两个数据大小如何分配确实需要有pix_fmt、width、height来确定。如果输出文件格式就是RAW 图片(如YUV和RGB),A VPacket作为将编码后数据写入文件的基本数据单元,他的单元大小、数据都是由A VPacket来的。

总结起来就是,A VPicture的存在有以下原因,A VPicture将Picture的概念从Frame中提取出来,就只由Picture(图片)本身的信息,亮度、色度和行大小。而Frame还有如是否是key frame之类的信息。这样的类似“分级”是整个概念更加清晰。

VIII.AVPacket

A VPacket的存在是作为写入文件的基本单元而存在的。我们可能会认为直接把编码后的比特流写入文件不就可以了,为什么还要麻烦设置一个A VPacket结构。在我看来这样的编码设置是十分有必要的,特别是在做视频实时传输,同步、边界问题可以通过A VPacket来解决。A VPacket的成员数据有两个时间戳、数据data(通常是编码后数据)、大小size等等(参见avformat.h 48行)。讲A VPacket的用法就不得不提到编解码函数,因为A VPacket的好些信息只有在编解码后才能的知。在参考代码中(ouput_example.c 从362到394行),做的一个判断分支。如果输出文件格式是RAW图像(即YUV或RGB)那么就没有编码函数,直接写入文件(因为程序本身生成一个YUV文件),这里的代码虽然在此看来没什么价值,但是如果是解码函数解出yuv文件(或rgb)那么基本的写文件操作就是这样的:

if(oc->oformat->flags & A VFMT_RAWPICTURE) {

A VPacket pkt; // 这里没有用指针!

av_init_packet(&pkt);

pkt.flags |= PKT_FLAG_KEY // raw picture 中,每帧都是key frame?

st->index;

pkt.stream_index

=

(uint8_t

*)picture;

=

pkt.data

sizeof(A VPicture);

=

pkt.size

&pkt);

av_write_frame(oc,

ret

=

}

输出非raw picture,编码后:

else{

video_outbuf_size在open_video() 中初始化

&

//

video_outbuf

out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture); (42)

0){

if(out_size

>

pkt;

A VPacket

av_init_packet(&pkt); (43)

pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base); (44)

if(c->coded_frame->key_frame)

pkt.flags |= PKT_FLAG_KEY;

pkt.stream_index= st->index;

pkt.data= video_outbuf;

pkt.size= out_size;

/* write the compressed frame in the media file */

ret = av_write_frame(oc, &pkt); (45) } else {

ret = 0;

}

if (ret != 0) {

fprintf(stderr, "Error while writing video frame\n");

exit(1);

}

其中video_outbuf和video_outbuf_size在open_video()里的初始化是这样的:

video_outbuf = NULL;

// 输出不是raw picture,而确实用到编码codec

&

A VFMT_RAWPICTURE)){

!(oc->oformat->flags

if(

200000;

=

video_outbuf_size

av_malloc(video_outbuf_size);

=

video_outbuf

}

(43)是A VPacket结构的初始化函数。(44)比较难理解,而且为什么会有这样的一些时间戳我也没有搞明白。其他的A VPacket成员数据的赋值比较容易理解,要注意的是video_outbuf和video_outbuf_size的初始化问题,由于在参考代码中初始化和使用不在同一函数中,所以比较容易忽视。(45)是写文件函数,A VFormatContext* oc中含有文件名等信息,返回值ret因该是一共写了多少数据信息,如果返回0则说明写失败。(42)和(45)作为比较重要的SDK函数,后面还会介绍的。.

IX. Conclusion

以上分析了FFMpeg中比较重要的数据结构。下面的这个生成关系理一下思路:(->表示派生出)

A VFormatContext->A VStream->A VCodecContext->A VCodec

|

A VOutputFormat or A VInputFormat

A VFrame->A VPicture….>A VPacket

二.FFMpeg 中的函数:

在前一部分的分析中我们已经看到FFMpeg SDK提供了许多初始化函数和编码函数。我们要做的就是对主要数据结构正确的初始化,以及正确使用相应的编解码函数以及读写(I/O)操作函数。作为一个整体化的代码SDK,FFMpeg有一些他自己的标准化使用过程。比如函数av_register_all(); 就是一个最开始就该调用的“注册函数”,他初始化了libavcodec,“注册”了所有的的codec和视频文件格式(format)。下面,我沿着参考代码(ouput_example.c)的脉络,介绍一下相关函数。

/******************************************************************

main()

******************************************************************/

1.av_register_all ();

usage: initialize ibavcoded, and register all codecs and formats

每个使用FFMpeg SDK的工程都必须调用的函数。进行codec和format的注册,然后才能使用。声明在allformats.c中,都是宏有兴趣看看。

2. A VOutputFormat guess_format(const char *short_name, const char *filename, const char *mime_type) usage: 通过文件后缀名,猜测文件格式,其实也就是要判断使用什么编码器(or解码器)。

A VOutputFormat

*fmt;

guess_format(NULL, filename, NULL);

fmt

=

3. A VFormatContext *av_alloc_format_context(void)

usage: allocate the output media context.实际是初始化A VFormatContext的成员数据A VClass:

A VFormatContext *ic;

ic->av_class = &av_format_context_class;

//where

// format_to_name, options are pointer to function

static const A VClass av_format_context_class = {“A VFormatContext”, format_to_name, options};

4. static A VStream *add_video_stream(A VFormatContext *ox, int codec_id);

*video_st;

A VStream

fmt->video_codec);

add_video_stream(oc,

=

video_st

5. int av_set_parameters(A VFormatContext *s, A VFormatParameters *ap)

usage: set the output parameters (must be done even if no parameters).

*oc;

A VFormatContext

// if failed, return integer smaller than zero

NULL);

av_set_parameters(oc,

6. void dump_format(A VFormatContext *ic, int index, const char *url, int is_output);

usage: 这一步会用有效的信息把 A VFormatContext 的流域(streams field)填满。作为一个可调试的诊断,我们会将这些信息全盘输出到标准错误输出中,不过你在一个应用程序的产品中并不用这么做:dump_format(oc, 0, filename, 1); // 也就是指明A VFormatContext中的事A VOutputFormat,还是

// A VInputFormat

7. static void open_video(A VFormatContext *oc, A VStream *st)

video_st);

open_video(oc,

8. int av_write_header(A VFormatContext *s)

usage: allocate the stream private data and writer the stream header to an output media file. param s media file handle, return 0 if OK, A VERROR_xxx if error.

write the stream header, if any

av_write_header(oc);

9. static void write_video_frame(A VFormatContext *oc, A VStream *st)

video_st);

write_video_frame(oc,

10. static void close_video(A VFormatContext *oc, A VStream *st)

// close each codec

close_video(oc,

video_st);

11. int av_write_trailer(A VFormatContext *s)

usage: write the trailer, if any. Write the stream trailer to an output media file and free the file private data.

av_write_trailer(oc);

12. void av_freep(void *arg)

usage: free the streams. Frees memory and sets the pointer to NULL. arg pointer to the pointer which should be freed .

av_freep(&oc->streams[i]->codec);

av_freeep(&oc->streams[s]);

13. int url_fclose(ByteIOContext *s);

usage: close the output file

url_fclose(&oc->pb);

14. void av_free(void *ptr)

usage: free the stream. Free memory which has been allocated with av_malloc(z)() or av_realloc().

av_free(oc);

/******************************************************************

******************************************************************

add_video_stream()

*c

A VCodecContext

*st

A VStream

******************************************************************/

******************************************************************

1.A VStream *av_new_stream(A VFormatContext *s, int id)

usage: add a new stream to a media file. s: media file handle, id: file format dependent stream id

av_new_stream(oc,

0);

=

st

/******************************************************************

******************************************************************

open_video()

*c

A VCodecContext

*codec

A VCodec

*picture,

*tmp_picture

A VFrame

*video_output

uint8_t

video_outbuf_size;

int

frame_count,

******************************************************************

******************************************************************/

1 A VCodec *avcodec_find_encoder(enum CodecID id)

usage: find the codec of encoder by CodecID. 在前面main中的guess_format()就已经开始为此准备了。

avcodec_find_encoder(c->codec_id);

=

codec

2int avcodec_open(A VCodecContext *avctx, A VCodec *codec);

usage: opens / inits the A VCodecContext. 打开失败的话,返回值小于零。

avcodec_open(c,

codec);

3 void *av_malloc(unsigned in size);

usage: you can redefine av_malloc and av_free in your project to use your memory allocator. You do not need to suppress this file because the linker will do it automatically

Memory allocation of size byte with alignment suitable for all memory accesses (including vectors if

available on the CPU). av_malloc(0) must return a non NULL pointer.

video_outbuf_size = 200000;

video_outbuf = avmalloc(video_outbuf_size);

4 static A VFrame *alloc_picture(int pix_fmt, int width, int height)

picture = alloc_picture(c->pix_fmt, c->width, c->height);

/******************************************************************

******************************************************************

******************************************************************

alloc_picture()

A VFrame

*picture

*picture_buf

uint8_t

size

int

******************************************************************

******************************************************************/

******************************************************************

1.avcodec_alloc_frame()

usage: initialize A VFrame* picture

picture

avcodec_alloc_frame()

=

2.int avpicture_get_size(int pix_fmt, int width, int height)

usage: 根据像素格式和视频分辨率获得picture存储大小。

=

avpicture_get_size(pix_fmt, width, height);

size

=

av_malloc(size)

picture_buf

3.int avpicture_fill(A VPicture *picture, uint8_t *ptr, int pix_fmt, int width, int height)

usage: Picture field are filled with ‘ptr’ addresses, also return size。用ptr中的内容根据文件格式(YUV…)和分辨率填充picture。这里由于是在初始化阶段,所以填充的可能全是零。

picture_buf, pix_fmt, width, height);

avpicture_fill((A VPicture*)picture,

/******************************************************************

******************************************************************

write_video_frame()

ret;

int

out_size,

*c;

A VCodecContext

static struct SwsContext *img_convert_ctx

******************************************************************

******************************************************************/

1 struct SwsContext *sws_getContext(int srcW, ……)

usage: 转变raw picture格式的获取context函数,比如下面的代码就是将其他格式的(如yuv422)转为yuv420,就要将context 保存在img_convert_ctx中,然后再利用后面的介绍函数做转化。

img_convert_ctx

sws_getContext(c->width, c->height,

=

PIX_FMT_YUV420P,

c->width, c->height,

c->pix_fmt,

sws_flags, NULL, NULL, NULL);

2 int sws_scale(struct SwsContext *ctx, uing8_t* src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t* dst[], int dstStride[]);

usage: 根据SwsContext保存的目标文件context将src(source)转为dst(destination)。

sws_scale(img_convert_ctx, tmp_picture->data, tmp_picture->linesize, 0, c->height, picture->data, picture->linesize);

4.int avcodec_encode_video(A VCodecContext *avctx, uint8_t *buf, int buf_size, const A VFrame *pict);

usage: 根据A VCodecContext将pict编码到buf中,buf_size是buf的大小。

out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture);

5 static inline void av_init_packet(A VPacket *pkt)

usage: initialize optional fields of a packet.初始化A VPacket。

pkt;

A VPacket

av_init_packet(&pkt)

6int64_t av_rescale_q(int64_t a, A VRational bq, A VRational cq)

usage: 校准时间基(maybe)

av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);

pkt.pts

=

7int av_write_frame(A VFormatContext *s, A VPacket *pkt)

usage: write a packet to an output media file . pkt: the packet, which contains the stream_index, buf/buf_size, dts/pts, …if error return<0, if OK =0, if end of stream wanted =1

ret = av_write_frame(oc, &pke);

/******************************************************************

******************************************************************

static void close_video(A VFormatContext *oc, A VStream *st)

{

avcodec_close(st->codec);

av_free(picture->data[0]);

av_free(picture);

if (tmp_picture) {

av_free(tmp_picture->data[0]);

av_free(tmp_picture);

}

av_free(video_outbuf);

}

/******************************************************************

******************************************************************

讲初始化过的,特别是分配过内存的,都要释放。

注:标定红色的函数为需要编程人员自己按照实际应用情况编写的,蓝色的是FFMpeg SDK中定义的函数。我们会分析函数的作用和调用方法。

由于时间关系,写得很乱。希望没有给你带来太大困扰,这份不成熟的文档能对你有一点点地帮助。chinavideo版上有很多大牛,我想做抛砖引玉者,希望以后能有更好的文档出现。我也是ffmpeg的初学者,如果大家有什么问题也希望能在版上一起讨论。我的email:yunfhu@https://www.doczj.com/doc/aa5285631.html,

2007-7-13

干货土地一级开发:从BT模式到PPP模式的演进路径及案例分析创新

干货I 土地一级开发:从BT模式到PPP模式的演进路径及案例分析 【导读】上世纪90年代,为解决土地资产流失等问题,上海市成 立土地发展中心,作为国有土地的储备机构,土地储备制度就此诞生并迅速在全国范围内得以推广,土地储备制度大致包括土地收购、土地储备、土地出让三个环节,其中土地储备环节即是将不具备土地出让条件的生地做成可出让的熟地的过程,土地一级开发作为一项独立的土地开发环节正式登上历史舞台,此后云南城投、上海城投、漳州发展、泰达股份、黑牡丹、张江高科、北科建、华夏幸福等企业纷纷进入土地一级开发领域,充当土地一级开发商的角色。 经过近20年的不断探索,我国土地一级开发领域在任务界定、权责分配、商业模式、资金融通、监管机制、风险控制等方面不断规范,从商业模式上看,我国土地一级开发经历了从BT模式到土地补偿模式再到利润分成模式的演进,未来将向PPP模式进一步发展。 | 一、BT模式 土地一级开发的BT模式又称固定收益模式或工程总包模式,指土地一级开发企业接受土地储备中心的委托,按照土地利用总体规划、城市总体规划等,对确定的存量国有土地、拟征用和农转用土地,统一组织进行征地、农转用、拆迁和市政道路等基础设施的建设,土地储备中心按照总建设成本的一定百分比作为经营加成。

很多地区对利润加成部分进行了相应规定,如北京规定:通过招标方式选择开发企业实施土地开发的,由开发企业负责筹措资金、办理规划、项目核准、征地拆迁和大市政建设等手续并组织实施。招标底价包括土地储备开发的预计总成本和利润,利润率不高于预计成本的8%;杭州规定:开发整理单位的利润和工作经费按照实施方案测算的开发整理成本总额的10%以内予以核定;昆明规定:市级国有投资公司组织实施的土地一级开发整理项目,统一按照审计所确定的总投资额的16%给予投资回报,并计入土地收储成本; BT模式简洁明了,企业收益稳定,风险较小,是一级开发企业常用的商业模式。如2010年5月,黑牡丹公司与常州新北区政府签署《新北区万顷良田工程建设委托协议》,常州新北区政府委托黑牡丹公司完成西夏墅镇和孟河镇境内总面积约为1538.10公顷的土地一级开发所涉及的拆迁、安置及土地整理、基础设施建设工作,委托建设期不超过两年,项目竣工后,新北区政府返还包括拆迁费用、安置费用、土地整理及基础设施建设费用、财务费用在内的建设成本及10% 的加成收益。

某大型公司软件开发管理制度

某大型公司公司软件开发管理制度 版本:1.0 SDM审批: QA经理[时间] CTO[时间] 目录 1.目的和作用3 2.适用范围:3 3. 参考文件3 4.适用对象3 5.软件开发流程4 5.1可行性研究与计划4 5.1.1实施4 5.1.2 文档4 5.1.2.1 应交付的文档4 5.1.2.2 提交步骤4 5.2需求分析4 5.2.1实施4 5.2.2要求5 5.2.3交付文档5 5.2.4审批5 5.3概要设计5 5.3.1实施5 5.3.2要求6 5.3.3交付文档6 5.3.4补充说明6 5.3.5审批6 5.4详细设计7 5.4.1实施7 5.4.2要求7 5.4.3文档7 5.4.4审批7 5.5实现7 5.5.1实施与要求7 5.5.2交付文档8 5.5.3审批8 5.6组装测试8 5.6.1实施8 腹有诗书气自华

5.6.2要求8 5.6.3交付文档8 5.6.4审批8 5.7确认测试9 5.7.1实施9 5.7.2要求9 5.7.3交付文档9 5.7.4 补充说明9 5.7.5 审批9 5.8发布10 5.8.1过程10 5.8.2 文档10 5.8.3 审核10 5.9 交接10 6. 附录1:项目文档清单11 1.目的和作用 本流程详细规定软件开发程的各个阶段及每一阶段的任务、要求、交付文件,使整个软件开发过程阶段清晰、要求明确、任务具体,实现软件开发过程的标准化。 2.适用范围: 公司的软件开发产品均适用。 3. 参考文件 各种文档模板 文档命名规则 交接流程 4.适用对象 软件管理人员,软件开发人员,软件维护人员 5.软件开发流程 5.1可行性研究与计划 5.1.1实施 5.1.1.1 软件开发部分析人员进行市场调查与分析,确认软件的市场需求 5.1.1.2 在调查研究的基础上进行可行性研究,写出可行性报告 5.1.1.3 评审和审批,决定项目取消或继续 5.1.1.4 若项目可行,制订初步的软件开发计划,建立项目日志 5.1.1.5 根据市场环境、公司软硬件情况预测十大风险因素 5.1.2 文档 5.1.2.1 应交付的文档 1)可行性研究报告* 2)初步的软件开发计划 3)十大风险列表* 腹有诗书气自华

土地一级开发(超详细)

1、固定比例收益模式 该模式是指土地一级开发企业接受政府的委托,按照土地利用总体规划、城市总体规划等,对确定的存量国有土地、拟征用和农转非土地,统一组织进行征地、农转非、拆迁和市政道路等基础设施的建设。政府统一支付固定的一级开发利润及保证增值收益底线。该模式仅从土地一级开发本身获利。 该模式有三种具体形式:一是土地一级开发由土地储备机构主导,负责筹措资金、办理规划、项目核准、征地拆迁及大市政建设等手续并组织实施。开发企业仅仅作为土地储备机构的受托人,具体执行一级开发相关事务,开发企业的管理费(利润率)为开发成本的2%;二是开发企业自行负责筹措资金、办理规划、项目核准、征地拆迁和大市政建设等手续并组织实施的,利润率为开发成本的8%。三是政府承诺收益保底,政府承诺开发企业投入土地一级开发资金每年将获得最低收益(通常为12-15%),所提取的收益不足开发总成本的5%时,政府将补足差额。 北京是采用这一模式的典型。《北京市土地储备和一级开发暂行办法》第十四条就规定:“通过招标方式选择开发企业实施土地开发的……招标底价包括土地储备开发的预计总成本和利润,利润率不高于预计成本的8%。”此外,这种模式在福建漳州也有实践。2009年8月,漳州发展在漳州当地拿下了1640亩土地的一级开发权,漳州市龙文区政府与当地城市建设开发中心给该企业承诺:该企业投入土地一级开发资金每年将获得12%的最低收益。 2、分享土地出让金 该模式一般是指一级开发企业与项目所在地政府联手,按照双方商议确

定的一定比例进行直接的土地出让金分成,以此获取一级开发企业的合法收益。 在此模式下,一般有两种具体操作方法:一是企业与政府签订《土地一级开发委托协议》,协议中明确双方土地出让金分成比例,企业凭借合法协议而获得土地出让金的分成权;二是企业与政府合资成立项目公司,企业凭借在合资公司中股权的占比,而获得土地出让金的分成权。但分享土地出让金的模式也有一定的局限性,由于我国土地的全民属性,为避免国有资产流失,土地出让金分成模式要求参与合作的一级开发企业性质必须是国有企业,而且从目前采取此类盈利模式的一些案例来看,一级开发企业的背景一般均为项目所在地政府的平台公司。 这种盈利模式的代表有上海新江湾城项目,该项目由上海城投全部运营,凭借前期巨大的资金投入,获得了颇高建设标准,上海城投与上海市政府双方就项目的土地出让金达成了7:3的分成比例,随着项目土地市场价值的不断提高,上海城投获得巨大收益。出于规避国家土地政策的考虑,此项目土地出让金分成具体执行则选择以“土地出让收入中的30%与政府签订土地出让合同,70%与上海城投签订土地一级开发补偿合同”的方式操作。 3、分享土地增值收益 该模式是指一级开发企业除获得土地一级开发成本补偿部分外,还可以与政府商定按一定比例分享土地出 4、持有部分优质公建配套设施 该模式是指政府授权土地一级开发主体可以投资公共配套设施,开发商则可以通过持有优质公建物业,提供公共配套服务而获得长期现金流。

exoSip 开发者手册

exoSip 开发者手册 1 扩展的eXosip协议栈 1.1 如何初始化libeXosip2 当使用eXosip时,你的首要任务是初始化eXosip上下文和libosip库(语法分析器和状态机)。这是在使用libeXosip2之前一定要完成的。 include int i; TRACE_INITIALIZE (6, stdout); i=eXosip_init(); if (i!=0) return -1; //在特定的socket上监听 i = eXosip_listen_addr (IPPROTO_UDP, NULL, port, AF_INET, 0); if (i!=0) { eXosip_quit(); fprintf (stderr, "could not initialize transport layer\n"); return -1; } …初始化之后就可以发送消息或者等待eXosip事件的到来… 在前面的代码中,您学习了如何: 初始化osip trace(用- DENABLE_TRACE编译此代码) 初始化eXosip(和osip)堆栈 为信号打开一个套接字(只有UDP要初始eXosip2) 现在你要处理eXosip事件。下面是一些来获得eXosip_event从 在eXosip2堆栈的代码。 eXosip_event_t *je; for (;;) { je = eXosip_event_wait (0, 50); eXosip_lock(); eXosip_automatic_action (); eXosip_unlock(); if (je == NULL) break;

软件开发工具复习资料(自考)

1)软件开发工具范围:在高级程序设计语言的基础上,为提高软件开发的质量 和效率,从规划分析设计测试成本和管理各方面,对软件开发者提供各种不同程度的帮助的一类广泛的软件。应当为软件人员提供信息管理,信息存储一致性的保证提供帮助支持。 2)SDT 3个发展阶段:通用工具,专用工具,集成工具。 3)软件开发工具的概念:在高级程序设计语言后进一步发展的产物,目的是给 与人们在开发软件过程中不同方面和程度的支持或帮助,支持开发的全过程而不是仅限编码或其他特定工作阶段。 4)软件的意义:硬件是躯体,软件是灵魂;软件是用户和计算机的桥梁;软件 是人类知识与经验的结晶,一种新的载体。 5)通用软件弱点:许多工作无法完成,不能反映逻辑内涵,难于保持一致性。 6)专用软件弱点:对软件开发缺乏全面统一的支撑环境造成冲突和矛盾。 7)软件开发发展阶段:机器语言开发软件,汇编语言开发转换,高级语言开发 编译程序转换,各种软件开发工具完成编译程序转换。(项目管理版本控制软件重用新问题) 8)新的软件开发方法表现在四个方面特点:自动化程度提高,进一步向用户延 伸,延伸到项目版本管理扩展到不断发展生长完善的全过程。 9)4GL:非过程化的程序设计语言,针对以处理过程为中心的第三代语言他希 望通过某些标准处理过程的自动生成使用户可以只说明要求做什么,而把具体的执行步骤安排交给软件自动处理。 10)CASE:计算机辅助软件工程或计算机辅助系统工程,应用计算机自身处理信 息的巨大能力来帮助人们开发复杂的软件或应用系统,。 11)软件开发过程5阶段:初始要求提出需求分析(软件功能说明书),总体设 计,程序文档的编写,测试调试阶段,维护。 12)软件工作的困难体现:复杂性,多样性,可维护性,可重用性。 13)SDT功能(定性):认识与描述客观系统,存储管理开发过程中的信息,代码 的编写生成,文档的编制生成,软件项目的管理。 14)SDT性能(定量):表达能力或描述能力,保持信息一致性的能力,使用的方 便程度,工具的可靠程度,对软硬件环境的要求。 15)SDT划分:A按工作阶段分—设计工具,分析工具,计划工具 B 按集成程度分---单项,集成 C按与硬件软件的关系分—依赖于特定的计算机或软件,独立于 硬件与其他软件。 16)软件开发过程2个转换:用户的理解—程序员的理解---程序的实现。 17)大型软件开发的困难:一致性保持困难,测试的困难大大增加(水波效应), 工作进度难以控制,文档与代码协调困难,版本更新带来的困难。 18)大型软件是现代化生产,单个程序是手工作坊。 19)困难产生的原因:大系统的复杂性,个人组织与协调的困难,各应用领域的 差别,时间和变化的因素。 20)用户任务:提出要求验收使用要求修改。程序员任务:编写程序文档,调试 自己编码的程序想项目负责人提交工作进展。项目负责人任务:分析需求,分配任务,验收联调,向用户交付使用,接受分析用户的修改要求布置修改任务验收修改成果并再提交。 21)结构化程序设计把程序的结构分解成3种基本模块:处理单元,循环机制,

微服务开发手册

微服务开发手册 Document serial number【KKGB-LBS98YT-BS8CB-BSUT-BST108】

微服务开发手册 1.开发说明 ●所有服务均基于springboot框架开发。Springboot内嵌了tomcat服务器,无需生成war包,并简化了maven配置,能够让开发者快速入手spring的开发。 ●服务的接口定义需严格符合restful规范。rest规范参考第2节 ●所有服务都需要在注册服务上注册,否则不能被其他服务所调用。同时平台也能够实时监测服务的状态,能够及时预警及调度资源。 ●所有服务的配置信息统一保存于gitlab上,并通过配置服务获取配置。 ●对数据库的操作统一采用MyBatis框架。MyBatis是个支持普通SQL查询,和高级映射的优秀框架。Springboot也提供了mybatis的集成方案,可以很快捷地整合mybatis到项目中。 ●包名约定:所有包均以com.drht.服务名为父包名 ●所有项目基于jdk1.8来开发。项目的管理与构建采用maven,代码统一托管于gitlab 仓库。 2.restapi接口规范 springboot接口设计需符合restful风格。在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表格名对应。 而客户端要执行某种类型的操作,需要根据http的操作协议来决定。HTTP提供了常 对于更新动作,参数通过requestbody来传递,格式为json。服务端返回数据格式也均为json。 服务端返回数据对象约定: publicclassUnifyInfo{ privateintcode;//返回代码,1:成功,0:失败

大型软件开发过程的质量管理体系

大型软件开发过程的质量管理体系  韩思音 弋陪余    国信朗讯科技网络技术有限公司是中国电信和朗讯科技合资的专业从事通信网络管理软件开发的高科技企业,公司位于上海浦东,注册资金2 980万美元,员工达150人,本科以上学历超过95%。公司在1999年成立后就开展了ISO9001贯标活动,并于2000年8月通过了ISO9001认证。公司以贝尔试验室的大型软件开发管理流程为基础,建立了自己的ISO9001质量管理体系。三年来已经开发了“传输网络集中监控系统NetGuard”、“电信网络资源管理系统NetMaster”两个大型软件系统。通过ISO9001的贯标活动,加强了公司全体员工的质量意识,强化了软件开发过程的规范性,改进了软件开发过程,保证了软件开发的质量,对加强公司实力、提高市场形象起了很好的推动作用。  通过了ISO9001认证后,审核机构每年要进行一次复查,即监督审核。如果公司质量体系运行得不好,就可能被暂停证书;如发生重大事故,证书可能被撤消。除此以外,公司每年还进行一次内审,即公司内部对质量体系运行是否符合ISO9001标准进行的检查,各部门对内审发现的不符合项进行认真整改,由质量管理部验收。各部门对本部门的工作定期提出改进措施,由质量管理部对其进行验证,使质量体系不断改进。所以ISO9001的认证对企业的质量体系是有严格管理的,是有保证的。  1 软件产品质量的特点  按照ISO9126的定义,软件的质量通常可以从以下六个方面去衡量(定义)。  1)功用性(Functionality),即软件是否满足了客户功能要求。  2)可靠性(Reliability),即软件是否能够一直在一个稳定的状态上满足可用性。  3)可用性(Usability),即衡量用户能够使用软件需要多大的努力。  4)效率(Efficiency),即衡量软件正常运行需要耗费多少物理资源。  5)可维护性(Maintainability),即衡量对已经完成的软件进行调整需要多大的努力。  6)可移植性(Portability),即衡量软件是否能够方便地部署到不同的运行环境中。  可见,同其它产品相比,软件产品的质量有其明显的特殊性。

软件项目文档全套模板-用户手册

<项目名称> 用户手册 作者: 完成日期: 签收人: 签收日期: 修改情况记录:

目录 1 引言 (1) 1.1 编写目的 (1) 1.2 背景 (1) 1.3 定义 (1) 1.4 参考资料 (1) 2 用途 (1) 2.1 功能 (1) 2.2 性能 (2) 2.2.1 精度 (2) 2.2.2 时间特性 (2) 2.2.3 灵活性 (2) 2.3 安全保密 (2) 3 运行环境 (2) 3.1 硬设备 (2) 3.2 支持软件 (3) 3.3 数据结构 (3) 4 使用过程 (3) 4.1 安装与初始化 (3) 4.2 输入 (3) 4.2.1 输入数据的现实背景 (3) 4.2.2 输入格式 (4) 4.2.3 输入举例 (4) 4.3 输出 (5) 4.3.1 输出数据的现实背景 (5) 4.3.2 输出格式 (5) 4.2.3 输出举例 (5) 4.4 文卷查询 (5) 4.5 出错处理和恢复 (6) 4.6 终端操作 (6)

1 引言 1.1 编写目的 说明编写这份用户手册的目的,指出预期的读者范围。 1.2 背景 说明: a.这份用户手册所描述的软件系统的名称; b.列出本项目的任务提出者、开发者、用户(或首批用户)以及安装该软件的单位。 1.3 定义 列出本文件中用到的专门术语的定义和缩写词的原词组。 1.4 参考资料 列出要用到的参考资料,如: a.本项目的经核准的计划任务书或合同、上级机关的批文; b.属于本项目的其他已发表的文件; c.本文件中各处引用的文件、资料,包括所要用到的软件开发标准。 列出这些文件的标题、文件编号、发表日期和出版单位,说明能够得到这些文件资料的来源。 2 用途 2.1 功能 结合本软件的开发目的逐项地说明本软件所具有各项功能以及它们的极限范围。

常用软件开发模型比较分析

常用软件开发模型比较分析 2007-09-26 20:21 正如任何事物一样,软件也有其孕育、诞生、成长、成熟和衰亡的生存过程,一般称其为“软件生命周期”。软件生命周期一般分为6个阶段,即制定计划、需求分析、设计、编码、测试、运行和维护。软件开发的各个阶段之间的关系不可能是顺序且线性的,而应该是带有反馈的迭代过程。在软件工程中,这个复杂的过程用软件开发模型来描述和表示。 软件开发模型是跨越整个软件生存周期的系统开发、运行和维护所实施的全部工作和任务的结构框架,它给出了软件开发活动各阶段之间的关系。目前,常见的软件开发模型大致可分为如下3种类型。 ① 以软件需求完全确定为前提的瀑布模型(Waterfall Model)。 ② 在软件开发初始阶段只能提供基本需求时采用的渐进式开发模型,如螺旋模型(Spiral Model)。 ③ 以形式化开发方法为基础的变换模型(T ransformational Model)。 本节将简单地比较并分析瀑布模型、螺旋模型和变换模型等软件开发模型。 1.2.1 瀑布模型瀑布模型即生存周期模型,其核心思想是按工序将问题化简,将功能的实现与设计分开,便于分工协作,即采用结构化的分析与设计方法将逻辑实现与物理实现分开。瀑布模型将软件生命周期划分为软件计划、需求分析和定义、软件设计、软件实现、软件测试、软件运行和维护这6个阶段,规定了它们自上而下、相互衔接的固定次序,如同瀑布流水逐级下落。采用瀑布模型的软件过程如图1-3所示。

图1-3 采用瀑布模型的软件过程 瀑布模型是最早出现的软件开发模型,在软件工程中占有重要的地位,它提供了软件开发的基本框架。瀑布模型的本质是一次通过,即每个活动只执行一次,最后得到软件产品,也称为“线性顺序模型”或者“传统生命周期”。其过程是从上一项活动接收该项活动的工作对象作为输入,利用这一输入实施该项活动应完成的内容给出该项活动的工作成果,并作为输出传给下一项活动。同时评审该项活动的实施,若确认,则继续下一项活动;否则返回前面,甚至更前面的活动。瀑布模型有利于大型软件开发过程中人员的组织及管理,有利于软件开发方法和工具的研究与使用,从而提高了大型软件项目开发的质量和效率。然而软件开发的实践表明,上述各项活动之间并非完全是自上而下且呈线性图式的,因此瀑布模型存在严重的缺陷。 ① 由于开发模型呈线性,所以当开发成果尚未经过测试时,用户无法看到软件的效果。这样软件与用户见面的时间间隔较长,也增加了一定的风险。 ② 在软件开发前期末发现的错误传到后面的开发活动中时,可能会扩散,进而可能会造成整个软件项目开发失败。 ③ 在软件需求分析阶段,完全确定用户的所有需求是比较困难的,甚至可以说是不太可能的。 1.2.2 螺旋模型螺旋模型将瀑布和演化模型(Evolution Model)结合起来,它不仅体现了两个模型的优点,而且还强调了其他模型均忽略了的风险分析。这

osgFX - 开发者简明手册

osgFX - 开发者简明手册 Marco Jez 2003年9月 osgFX是一个OpenSceneGraph的附加库,是一个用于实现一致、完备、可重用的特殊效果的构架工具,其效果可以添加到OSG的节点中。它同时还包含了一系列预定义好的特殊效果。 osgFX概述 所谓“特效”指的是装载于单个对象中的一系列可视的属性和行为。要实现一个真正可用的特效,相应的特效类应当具备一个公有的接口,以修改各种配置和微调量。 特效也可以被理解成是提出问题(对象应当是什么样子)与解决问题(应当设置哪些属性和其它调节量)之间的“桥梁”。从C++代码来看,特效具现了osgFX::Effect类的实例。或者说,是这个类的派生类的实例,因为osgFX::Effect直接派生自osg::Node,因此它是抽象类。 对于OSG而言,特效就是一个Node节点。它与其它节点类的特性完全相同,因此可以关联到场景图形中的任意位置。 特效功能图如图1所示。 Effect类是一个多子节点的组节点。它使用addChild()方法和其它节点关联。 在特效类中设置的可视属性将被关联到它的子节点上,与此相类似,Transform节点也会将坐标变换的信息应用到其子节点上。Effect中的各种属性不会在其子节点以外生效。 如果用户想要将某一种特效应用到自己的图形子树上,那么需要遵循下面的步骤: 1、创建所需特效的实例,例如,osgFX::Scribe; 2、必要的话,使用特效类的方法设置特效属性; 3、调用Effect::addChild()方法,将图形子树与特效节点相关联; 4、将特效节点与场景图形关联。 下面的例子中使用了刻线(scribe)特效: osg::ref_ptr my_node = osgDB::readNodeFi le(“cow.osg”); osg::ref_ptr scribe_fx = new osgFX::Scribe; scribe_fx->addChild(my_node.get()); scribe_fx->setEnabled(true); root->addChild(scribe_fx.get()); 代码执行的结果如图2所示。 深入学习:技法和通道 技法就是实现特效的某一种可能方法。 由于图形硬件设备种类繁多,OpenGL也在不断扩展,因此不太可能用一种通用的方法来实现复杂的效果:针对不同的硬件和OpenGL环境,用户需要采用不同的实现手段来实现某个特效。 一种特效的产生往往可以采用一种或几种技法,每一种技法都采用不同的方式来尝试实现相同的效果。 缺省情况下,Effect类使用私有的StateAttribute对象来实时演算和验证各种技法,并选择最好的一种。特效的开发者可以自行定义各种技法的优先级,从而要求OSG首先验证用户所选的技法。 Effect类会选择在实时的所有活动渲染设备中,可通过验证的优先级最高的技法,以为己用。 如果需要的话,用户可以在任何时刻重载这一缺省特性。 Effect类的技法功能图表如图3所示。

大型软件开发人员的组织与分工

大型软件开发人员的组织与分工 大型软件项目需要很多人的能力合作,花费一年或数年的时间才能完成。为了提高工作效率,保证工作质量,软件开发人员的组织、分工与管理是一项十分重要和复杂的工作,它直接影响到软件项目的成功与失败。首先,由于软件开以人员的个人素质与差异很大,因此对软件开发人员的选择、分工十分关键。1970年,Sackman对12名程序员用两个不同的程序进行试验,结论是:程序排错、调试时间差别为18:1;程序编制时间差别为15:1;程序长度庆功别为6:1;程序运行时间差别为13:1。近年来,随着软件开发方法的提高、工具的改善,上述差异可能会减小,但软件人员的合理选择及分工,充分发挥每个人的特长和经验显然是十分重要的。其次,因为软件产品不易理解、不易维护,因此软件人员的组织方式十分关键。一个重要的原则是,软件开发人员的组织结构与软件项目开发 模式和软件产品的结构相对应,这样可以达到软件开发的方法、工具、与人的统一,从而降低管理系统的复杂性,有利于软件开发过程的管理与质量控制。按树形结构组织软件开发人员是一个比较成功的经验。树的根是软件项目经理和项目总的技术负责人。理想的情况是项目经理和技术负责人由一个 人或一个小组担任。树的结点是程序员小组,为了减少系统的复杂性、便于项目管理,树的结点每层不要超过7个,在此基础上尽量降低树的层数。程序员小组的人数应视任务的大小和完成任务的时间机时定,一般是2~5人。为降低系统开发过程的复杂性,程序员小组之间,小组内程序员之间的任务界面必须清楚并尽量简化。 按“主程序员”组织软件开发小组是一条比较成功的经验。“主程序员”应该是“超级程序员”。其他成员,包括程序员、后备工程师等,是主程序员的助手。主程序员负责规划、协调和审查小组的全部技术活动。程序员负责软件的分析和开发。后备工程师是主程序员的助手,必要时能代替主程序员领导小组的工作并保持工作的连续性。软件开发小组还可以根据任务需要配备有关专业人员,如数据库设计人员、远程通信和协调,提高了工作效率。这种形式的成败主要取决于程序员的技术和管理水平。除了按主程序员负责的程序员小组组织开发人员外,还可以按“无我程序设计”建立软件民主开发小组。这各组织形式强调组内成员人人平等,组内问题均由集体讨论决定。这种组织形式有利于集思广益、互相取长补短,但工作效率比较低。 软件项目或软件开以小组可以配置若干个秘书、软件工具员、测试员、编辑和律师等。秘书负责维护和软件配置中的文档、源代码、数据及所依附的各种磁介质;规范并收集软件开发过程中的数据;规范并收集可重用软件,对它们分类并提供检索机制;协助软件开发小组准备文档,对项目中的各种参数,如代码行、成本、工作进度等,进行估算;参与小组的管理、协调和软件配置的评估。大型软件项目需专门配置一个或几个配置管理人员,专门负责软件项目的程

浅析土地一级开发

土地一级开发 一、何谓土地一级开发? 1、基本概念 土地一级开发,是指由政府或其授权委托的企业,对一定区域范围内的城市国有土地、乡村集体土地进行统一的征地、拆迁、安置、补偿,并进行适当的市政配套设施建设,使该区域范围内的土地达到“三通一平”、“五通一平”或“七通一平”的建设条件(熟地),再对熟地进行有偿出让或转让的过程。 2、延伸理解 从空间上来讲,土地一级开发可分为成片开发及分片开发两类。当然,这只是业内约定俗成的说法,并非法律层面的明确界定; 从时间上来讲,一种是先一、二级开发分离的形式,另一种是一级开发包含于二级开发的形式; 从性质上来讲,一类是存量一级开发,包括旧城改造、旧村改造、城中村改造及退二进三(工业厂区改商业、住宅等第三产业)项目,另一种是增量一级开发,包括征用和农转用土地,一些是已纳入城市总体规划的成片征地开发,有些则规划区以外单独立项基建类项目。 二、土地一级开发常见操作模式 1、区域土地开发模式的转变 当前,区域土地开发中呈现三个方面的转变: ?粗放开发方式向集约开发方式的转变 坚持科学发展观,严格按照规划进行控制和开发,确保土地资源的集约高效利用,尤其在地下空间,社区公建配套、社区教育配套等方面,探索高度集约化的土地使用方式。 ?房地合一方式向房地分离方式的转变 充分发挥政府、一级开发企业、二级房产开发企业各自的优势和作用,形成土地开发商、房地产开发商、销售商各司其职的房地产开发链。

以统一规划、统一配套为原则,通过超前的市政基础设施开发,生态环境系统的构建,交通、商业、文体设施配套,为进驻的房产开发企业创造良好的房产开发基础条件。 2、土地一级开发常见模式 从实施主体的角度看,土地一级开发主要分为政府主导和企业主导两种模式,两者有着显著的差异。 ?政府主导模式 政府主导模式下,政府作为土地的所有者代表,将土地一级开发列为土地整理储备中心的一项职能,由土地整理储备中心或其组建机构完成全部的一级开发工作,一级开发的资金主要来自政府财政专项拨款。 这种开发模式通常对资金要求不高,开发周期较短,不利于统一规划,且多数以生地出让,土地价值尚未得以充分挖掘,给后续拿地开发企业带来不确定性。 成功案例:三亚海棠湾 土地一级开发由政府独立完成,包括海棠湾规划;征地、拆迁、安置;基础设施建设;以项目带土地进行招商等。 ?企业主导模式 企业主导模式下,政府通过招标或委托确定一级开发企业,对政府委托授权获得的成片土地进行各种基础设施建设,使土地由生地变为熟地,达到可建设条件。一级开发的企业类型通常为项目所在地政府的平台公司(城投公司等)、大型国有企业或实力民企等。 由于参与土地一级开发的企业(尤其是大型央企)通常具备强大的资源整合能力与资本实力,既可以最大程度的发挥市场化操作优势,同时也可以保证土地一级开发的品质,从而为项目后续开发和整体运营提供一定的保障。 企业主导模式对资金要求较高,开发周期相对较长,企业具备一定风险,不确定性较大,但有利于挖掘和提升区域土地价值,同时也可以通过一定程度的二级项目开发获取收益。 成功案例:1、上海新江湾城 上海城投是政府背景浓厚的老资格一级开发企业,全盘操作新江湾城一级开发,部分市政设施采用BT模式,并创新性的采用土地换市政做法,为政府节约资金投入,创造了可观的经济效益。

Moodle平台开发者手册

文档中的章节: 1、Moodle体系结构 2、您如何参与开发 ○学习活动 ○主题风格 ○语言 ○数据库模式 ○课程格式 ○文档和文章 ○参与缺陷修正 1.Moodle体系结构 从一个系统管理员的角度,Moodle被设计为遵循以下标准: 1、Moodle应该能运行在尽可能广泛的平台上 很多系统上运行的web应用程序平台是PHP和MySQL的结合,这也是Moodle 开发所使用的平台(Linux,Windows,和MacOSX)。Moodle也使用ADOdb库作为数据库抽象层,这意味着Moodle能使用超过10个不同品种的数据库(不幸的是,它还不能初始化表格在所有的这些数据库-更多的数据库支持将逐步添加)。 2、Moodle应该是容易安装、学习和修改的 最早的Moodle(1999)原型使用Zope构建-一种高级面向对象的web应用服务器。不幸的是我发现即使这项技术非常酷,但它学习起来很困难而且在系统管理上也不灵活。PHP脚本语言,在另一方面来说,是非常容易入门的(尤其是当您有其他脚本语言的编程经验时)。最早我决定不使用以类(class-oriented)为基础的设计,来保持它对于新手而言足够简洁。代码重用通过使用分类的库文件、清晰命名的函数和一致的脚本文件放置来实现。PHP也非常容易安装(几乎每个平台都有可用的二进制包)并且大多数的主机托管服务作为标准配置提供广泛的PHP支持。 3、它应该容易的进行版本升级 Moodle知道自己目前的版本(也同样知道所有插件的版本),同时一个内置的机制确保Moodle能正常的升级自己到新的版本(例如,它能修改数据库表格或添加新的字段)。如果您使用Unix下的CVS命令,您可以运行"cvsupdate-d",然后访问站点的主页来完成升级。

某大型公司软件开发管理制度.doc

某大型公司软件开发管理制度1 某大型公司公司软件开发管理制度 版本:1.0 SDM审批: QA经理[时间] CTO[时间] 目录 1.目的和作用3 2.适用范围:3 3. 参考文件3 4.适用对象3 5.软件开发流程4 5.1可行性研究与计划4 5.1.1实施4 5.1.2 文档4 5.1.2.1 应交付的文档4 5.1.2.2 提交步骤4 5.2需求分析4

5.2.1实施4 5.2.2要求5 5.2.3交付文档5 5.2.4审批5 5.3概要设计5 5.3.1实施5 5.3.2要求6 5.3.3交付文档6 5.3.4补充说明6 5.3.5审批6 5.4详细设计7 5.4.1实施7 5.4.2要求7 5.4.3文档7 5.4.4审批7 5.5实现7 5.5.1实施与要求7

5.5.2交付文档8 5.5.3审批8 5.6组装测试8 5. 6.1实施8 5.6.2要求8 5.6.3交付文档8 5.6.4审批8 5.7确认测试9 5.7.1实施9 5.7.2要求9 5.7.3交付文档9 5.7.4 补充说明9 5.7.5 审批9 5.8发布10 5.8.1过程10 5.8.2 文档10 5.8.3 审核10

5.9 交接10 6. 附录1:项目文档清单11 1.目的和作用 本流程详细规定软件开发程的各个阶段及每一阶段的任务、要求、交付文件,使整个软件开发过程阶段清晰、要求明确、任务具体,实现软件开发过程的标准化。 2.适用范围: 公司的软件开发产品均适用。 3. 参考文件 各种文档模板 文档命名规则 交接流程 4.适用对象 软件管理人员,软件开发人员,软件维护人员 5.软件开发流程 5.1可行性研究与计划 5.1.1实施 5.1.1.1 软件开发部分析人员进行市场调查与分析,确认软

《HongCMS开发者手册》二次开发指南

《HongCMS开发者手册》--二次开发指南 模板语法参阅:/bbs/?thread-index-fid-1-tid-19.htm 一、前言: 说实在的,很怕写文档,特别是这种开发文档,无法知道别人需要什么样或者说什么程度的描述,自己高兴的事别人未必开心。所以,这个文档总的想法是将重点介绍清楚,让用户了解系统脉络,细枝末节的技术google就行了。 前些日子因参与其它公司的项目,研究了些PHP开发框架,如CI, ThinkPHP等这些,觉得这些小型框架对我来说很不爽,因为本人一直 喜欢4S的开发理念,即:Safe, Simple, Small, Stable (安全,简单,小巧,稳定),不刻意追求大而全的东西,认为简单是最美的。 这和性格有关,也很难改变。就拿CI来说吧,前台游客只要一进入网站,就有至少1个数据库写入及1个session生成,一个session在服务器就要写入一个文件,试想如果网站同时来了1万个用户访问,文件IO开销巨大,说得不好听点,服务器可能就死球了。对于框架,业内一直有这么一句话:学之者生,用之者死。本人觉得这句话很值得琢磨一下。 如今没有几个公司不要求程序员有MVC的开发理念,MVC确实有好处,本人也喜欢,但也不去刻意追求. 当然也有反对MVC的, 包括PHP创始人。HongCMS开发中有V和C,M基本没有,因为不需要或者说使用M编程反而累了,但完全可以使用Model,系统框架

已经为它设计好了,程序包models/目录下有实例。特别是后台admin/models/目录下的admin.php, 它就是后台用户(管理员)的模型。说白了,模型就是一些类啦。 HongCMS系统框架APP.php非常小巧,仅5K大小,再加上XTpl超小模板引擎,HongCMS核心非常小巧、快速和高效。有基础的朋友,如果对HongCMS进行二次开发,或是参考其中的理念,足可以开发出大型系统来。 这些思想,加上多年做双语企业网站的经验,同时有朋友要我开发一个中英双语的小型企业网站,于是HongCMS出生了。对于一些从事网站开发的朋友来说,我想HongCMS更适合成为你的工具,像很多使用weenCompany的用户能赚钱一样,使用HongCMS当然能赚钱,同时在技术上会有更大的提高。对于一般用户,HongCMS是中英文网站系统,对于懂程序的朋友来说,它是小型开发框架,开发由你。 二、目录布局与重要文件介绍 1. 根目录下的几个文件 .htaccess: 此文件是apache服务器下的伪静态规则文件,另外此文件还限制了浏览器可以访问或进入哪个目录或文件夹,增强了系统安全性。如果你添加了一个目录如blog,这个目录下独立安装了另一个blog系统,那么需要修改htaccess文件,以便允许浏览器访问blog目录。 index.php: HongCMS是单入口系统,所有前台页面的访问均从index.php进入。

几大原型软件开发对比

1、Axure RP(Rapid Prototyping) Axure(读音为Ack-Sure)无疑是目前最受关注的原型开发工具,其能通过组件的方式帮助网站或软件设计师快速建立带有注释的原型(流程图、线框图),并凭借自定义可重用的元件、动态面板以及丰富的script能够建立基本功能或页面逻辑的动态演示文件。 Axure借鉴了office的界面,能够让用户快速上手,并且提供了丰富的组件样式修改,使得通过其能够创建低保真、高保真甚至接近于实际效果的界面。然而最让人称道的是,Axure 的丰富的脚本模式,可以通过点击和选择能够快速完成界面元素的交互,如链接、state切换、动态变化等效果,使得Axure能够生成十分接近于真实产品的原型。另一方面,Axure 能够导入其他人创建的元件库,使得Axure能够满足绝大多数类型产品的设计。 但Axure仍然有一个让人头痛的问题:对于中文的支持不太友好。在小部分元件上输入中午的时候,经常需要像碰运气似的反复切换输入法,破坏了咱们设计师的用户体验。 瑕不掩瑜,Axure仍然是交互设计师的首选原型工具。 2、Microsoft Office Visio Visio在2000年被微软收购,并在2002年成为office2003套件中的一个组件,最新版本是2007。Visio能够获得推荐的原因是因为Visio的适用性非常之广,从网站界面、数据库模型,到平面布置图到工艺流程图,Visio都提供了相应的元件库和模板来进行快速创建。 相较Axure而言,Visio更适合于传统行业的生产或流程设计,或者软件及互联网行业中的信息、数据和流程的说明,而不太适用于web界面。因为其的基于web的元件库还是比较少,并且形式和结构也更类似于word中的图形工具,因此在原型开发效率上都有所不足。 3、Balsamiq Mockups 这个基于Adobe AIR Runtime的工具实在是有让人眼前一亮的感觉,手绘风格的元件样式粗犷淋漓,能创建接近于纸上手绘的原型文件。其提供了丰富的手绘风格的web常用元件,包括常用的html控件、以及一些组合控件,如多媒体控制器、标签页、列表、Iphone界面元件等。 Mockups最值得赞赏之处在于其提供的多数组件都可定制外观,对于中文的支持也不错(选择View > Use System Fonts)。 4、Mockflow Mockflow和以上工具最大的不同在于Mockflow是一项基于Adobe Flex技术开发在线服务,提供了与Balsamiq Mockups基本相似的功能,甚至更丰富的组件,虽然其元件定制化不够强大,但其提供的元件库默认样式却非常适合用来做商业产品原型的搭建。有一个让我爱不释手的功能是模板,可以设置基于任何页面的模板来进行新的页面设计。 与其他模板工具相比,mockflow有一个非常特色的功能,基于web的存储可以在任意电脑上联机打开,同时可以其他人进行快速的分享,并收集在线反馈意见,非常适合虚拟团队的原型设计交流。 虽然在线服务的基本帐号只能创建一个文件,但单个文件却没有限制页数,因此也基本上足够使用。 5、Pencil sketch Pencil 是一款基于Firefox的扩展组件,安装之后即可在Firefox的工具菜单中打开Pencil的绘图面板。功能比较简单,仅能用以日常简单工作的辅助说明。提供的默认元件都是基于软件工程,因此更适合用于windows桌面程序的简易界面搭建,或者是基本的页面功能说明,

软件开发工具试题大题答案

(一)三、简答题(本大题共5小题,每小题5分,共25分) 1. 什么是过程化程序设计语言 答案:第三代程序设计语言一般都是过程化语言,即需要由编写程序的人一步一步地安排好机器的执行次序,虽然不是一对一地指挥到机器指令,但是还必须在人的头脑中安排好实际的执行过程。 2. 代码生成器依据哪些资料工作 答案:代码生成器生成代码时依据三方面的资料: (1)信息库里已有的有关资料。 (2)各种标准模块的框架和构件。 (3)使用者通过屏幕前的操作送入的信息。 3. 什么是数据字典 答案:数据字典是一种描述数据内容的概念模式。它用表格的形式列出数据的基本属性以及相互关系。 4. 简述信息库这一概念提出的背景。 答案:信息库是针对软件开发或信息系统开发中的大量信息管理工作提出来的。早在手工进行系统分析的阶段人们已经发现,许多问题出在信息交流中的误解与损失。按照传统的生命周期法,每一阶段都是用相应的文档实现过渡的,在信息传递中,误解与丢失十分严重。另外,软件的修改与版本更新也引起一些问题,有时不得不从头收集基础信息,不但浪费很大,而且会引起用户的厌烦。随着数据库技术的发展,人们很自然地想到用计算机来办这件事。这就是信息库这个概念提出的背景。 5. 为自己所用而开发软件开发工具时,应注意哪些事项 答案:为自己所用而开发软件开发工具时,应注意以下事项: (1)从实际出发,设定现实的、有限的目标。 (2)坚持短小实用,逐步积累,避免期望过高,贪大求全。 (3)注意文档的齐全和资料的积累。 四、论述题(本大题共1小题,共10分) 1. 承担大型软件开发任务的程序员,必须遵守哪些规定 答案:保证严格地在本模块范围内操作,决不使用可能干扰其他模块的命令或函数。原则上讲,有一定经验的程序员是可以通过某些命令直接影响机器内部信息的。对于单人工作的程序员来说,这常常是发挥技巧、提高效率的手段,但是对于项目组的成员来说,这必然会导致混乱,应当严格禁止。 (2)严格按总体设计的要求和理解去传递参数值,决不随意修改其内容或含义。 (3)在对公用的文件或数据库进行存取时,必须完全地、准确地按统一规定的格式去操作,决不能擅自改变。 (4)在使用标识符时,应按照统一的原则,尽量使用易于看出逻辑含义的名称。特别是涉及公用数据及参数的时候。 (5)严格按照统一的要求编写文档,在内容、格式、表达方式、符号使用上遵循项目组的统一规定。 (6)尽量保持程序风格的一致,如注释行的安排,行首空格的使用等。 总之,作为项目组的成员,必须放弃自己的某些“自由”(即独自工作时可以自主的事情),接受项目组的限制和约束,服从项目组的严格管理。可以说,作为项目组的一员参加大型软件的开发,必须具有高度的组织纪律性和团队精神。 五、应用题(本大题共1小题,共15分)

相关主题
文本预览
相关文档 最新文档