当前位置: 首页 > news >正文

静态网站安全性泸州市建设规划局网站

静态网站安全性,泸州市建设规划局网站,邢台做wap网站价格,企业团建公司简介 FFmpeg是一个集录制、转换、音/视频编码解码功能为一体的完整的开源解决方案。FFmpeg的开发是基于Linux操作系统#xff0c;但是可以在大多数操作系统中编译和使用。FFmpeg支持MPEG、DivX、MPEG4、AC3、DV、FLV等40多种编码#xff0c;AVI、MPEG、OGG、Matroska、ASF等…简介 FFmpeg是一个集录制、转换、音/视频编码解码功能为一体的完整的开源解决方案。FFmpeg的开发是基于Linux操作系统但是可以在大多数操作系统中编译和使用。FFmpeg支持MPEG、DivX、MPEG4、AC3、DV、FLV等40多种编码AVI、MPEG、OGG、Matroska、ASF等90多种解码. TCPMP, VLC,MPlayer等开源播放器都用到了FFmpeg。 FFmpeg主目录下主要有libavcodec、libavformat和libavutil等子目录。其中libavcodec用于存放各个encode/decode模块libavformat用于存放muxer/demuxer模块libavutil用于存放内存操作等常用模块。 以flash movie的flv文件格式为例 muxer/demuxer的flvenc.c和flvdec.c文件在libavformat目录下encode/decode的mpegvideo.c和h263de.c在libavcodec目录下。 muxer/demuxer与encoder/decoder定义与初始化 muxer/demuxer和encoder/decoder在FFmpeg中的实现代码里有许多相同的地方而二者最大的差别是muxer和demuxer分别是不同的结构AVOutputFormat与AVInputFormat而encoder和decoder都是用的AVCodec结构。 muxer/demuxer和encoder/decoder在FFmpeg中相同的地方有 l        二者都是在main()开始的av_register_all()函数内初始化的。 l        二者都是以链表的形式保存在全局变量中的。 muxer/demuxer是分别保存在全局变量AVOutputFormat *first_oformat与AVInputFormat *first_iformat中的。 encoder/decoder都是保存在全局变量AVCodec *first_avcodec中的。 l        二者都用函数指针的方式作为开放的公共接口。 demuxer开放的接口有 int (*read_probe)(AVProbeData *); int(*read_header)(struct AVFormatContext *, AVFormatParameters *ap); int(*read_packet)(struct AVFormatContext *, AVPacket *pkt); int(*read_close)(struct AVFormatContext *); int(*read_seek)(struct AVFormatContext *, int stream_index, int64_t timestamp, intflags); muxer开放的接口有 int (*write_header)(struct AVFormatContext *); int (*write_packet)(struct AVFormatContext *, AVPacket *pkt); int (*write_trailer)(struct AVFormatContext *); encoder/decoder的接口都是一样的只不过二者分别只实现encoder和decoder函数 int(*init)(AVCodecContext *); int (*encode)(AVCodecContext*, uint8_t *buf, int buf_size, void *data); int (*close)(AVCodecContext*); int (*decode)(AVCodecContext*, void *outdata, int *outdata_size, uint8_t *buf, int buf_size); 仍以flv文件为例来说明muxer/demuxer的初始化。 在libavformat\allformats.c文件的av_register_all(void)函数中通过执行 REGISTER_MUXDEMUX(FLV,flv); 将支持flv 格式的flv_muxer与flv_demuxer变量分别注册到全局变量first_oformat与first_iformat链表的最后位置。 其中flv_muxer在libavformat\flvenc.c中定义如下 AVOutputFormat flv_muxer { flv, flv format, video/x-flv, flv, sizeof(FLVContext), #ifdefCONFIG_LIBMP3LAME CODEC_ID_MP3, #else //CONFIG_LIBMP3LAME CODEC_ID_NONE, CODEC_ID_FLV1, flv_write_header, flv_write_packet, flv_write_trailer, .codec_tag (const AVCodecTag*[]){flv_video_codec_ids, flv_audio_codec_ids, 0}, } AVOutputFormat结构的定义如下 typedefstruct AVOutputFormat { const char *name; const char *long_name; const char *mime_type; const char *extensions; /** comma separated filename extensions */ /** size of private data so that it can be allocated in the wrapper */ int priv_data_size; /* output support */ enum CodecID audio_codec; /** default audio codec */ enum CodecID video_codec; /** default video codec */ int (*write_header)(struct AVFormatContext *); int (*write_packet)(struct AVFormatContext *, AVPacket *pkt); int (*write_trailer)(struct AVFormatContext *); /** can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_GLOBALHEADER */ int flags; /** currently only used to set pixel format if not YUV420P */ int (*set_parameters)(struct AVFormatContext *, AVFormatParameters *); int (*interleave_packet)(struct AVFormatContext *, AVPacket *out, AVPacket *in,int flush); /** * list of supported codec_id-codec_tag pairs, ordered by better choicefirst * the arrays are all CODEC_ID_NONE terminated */ const struct AVCodecTag **codec_tag; /* private fields */ struct AVOutputFormat *next; } AVOutputFormat; 由AVOutputFormat结构的定义可知flv_muxer变量初始化的第一、第二个成员分别为该muxer的名称与长名称第三、第四个成员为所对应MIMIE Type和后缀名第五个成员是所对应的私有结构的大小第六、第七个成员为所对应的音频编码和视频编码类型ID接下来就是三个重要的接口函数该muxer的功能也就是通过调用这三个接口实现的。 flv_demuxer在libavformat\flvdec.c中定义如下, 与flv_muxer类似在这儿主要也是设置了5个接口函数其中flv_probe接口用途是测试传入的数据段是否是符合当前文件格式这个接口在匹配当前demuxer的时候会用到。 AVInputFormatflv_demuxer { flv, flv format, 0, flv_probe, flv_read_header, flv_read_packet, flv_read_close, flv_read_seek, .extensions flv, .value CODEC_ID_FLV1, }; 在上述av_register_all(void)函数中通过执行libavcodec\allcodecs.c文件里的avcodec_register_all(void)函数来初始化全部的encoder/decoder。 因为不是每种编码方式都支持encode和decode所以有以下三种注册方式 #defineREGISTER_ENCODER(X,x) \ if(ENABLE_##X##_ENCODER) register_avcodec(x##_encoder) #defineREGISTER_DECODER(X,x) \ if(ENABLE_##X##_DECODER) register_avcodec(x##_decoder) #defineREGISTER_ENCDEC(X,x) REGISTER_ENCODER(X,x);REGISTER_DECODER(X,x) 如支持flv的flv_encoder和flv_decoder变量就分别是在libavcodec\mpegvideo.c和libavcodec\h263de.c中创建的。 当前muxer/demuxer的匹配 在FFmpeg的文件转换过程中首先要做的就是根据传入文件和传出文件的后缀名匹配合适的demuxer和muxer。 匹配上的demuxer和muxer都保存在如下所示定义在ffmpeg.c里的全局变量file_iformat和file_oformat中 staticAVInputFormat *file_iformat; staticAVOutputFormat *file_oformat; 1.        demuxer匹配 在libavformat\utils.c中的static AVInputFormat*av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max)函数用途是根据传入的probe data数据依次调用每个demuxer的read_probe接口来进行该demuxer是否和传入的文件内容匹配的判断。其调用顺序如下 voidparse_options(int argc, char **argv, const OptionDef *options)    static voidopt_input_file(const char *filename) static voidopt_input_file(const char *filename) int av_open_input_file(…… ) AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened) staticAVInputFormat *av_probe_input_format2(……) opt_input_file函数是在保存在const OptionDef options[]数组中用于void parse_options(int argc, char**argv, const OptionDef *options)中解析argv里的“-i” 参数也就是输入文件名时调用的。 2.        muxer匹配 与demuxer的匹配不同muxer的匹配是调用guess_format函数根据main( ) 函数的argv里的输出文件后缀名来进行的。 voidparse_options(int argc, char **argv, const OptionDef *options) voidparse_arg_file(const char *filename) static voidopt_output_file(const char *filename) AVOutputFormat*guess_format(const char *short_name, const char *filename, const char *mime_type) 当前encoder/decoder的匹配 在main( )函数中除了解析传入参数并初始化demuxer与muxer的parse_options()函数以外其他的功能都是在av_encode( )函数里完成的。 在libavcodec\utils.c中有如下二个函数。 AVCodec *avcodec_find_encoder(enum CodecID id) AVCodec *avcodec_find_decoder(enum CodecID id) 他们的功能就是根据传入的CodecID找到匹配的encoder和decoder。 在av_encode( )函数的开头首先初始化各个AVInputStream和AVOutputStream然后分别调用上述二个函数并将匹配上的encoder与decoder分别保存在AVInputStream-AVStream*st-AVCodecContext *codec-struct AVCodec *codec与AVOutputStream-AVStream*st-AVCodecContext *codec-struct AVCodec *codec变量中。 其他主要数据结构 1.       AVFormatContext AVFormatContext是FFMpeg格式转换过程中实现输入和输出功能、保存相关数据的主要结构。每一个输入和输出文件都在如下定义的指针数组全局变量中有对应的实体。 staticAVFormatContext *output_files[MAX_FILES]; staticAVFormatContext *input_files[MAX_FILES]; 对于输入和输出因为共用的是同一个结构体所以需要分别对该结构中如下定义的iformat或oformat成员赋值。 struct AVInputFormat *iformat; struct AVOutputFormat *oformat; 对一个AVFormatContext来说二个成员不能同时有值即一个AVFormatContext不能同时含有demuxer和muxer。 在main( )函数开头的parse_options( )函数中找到了匹配的muxer和demuxer之后根据传入的argv参数初始化每个输入和输出的AVFormatContext结构并保存在相应的output_files和input_files指针数组中。 在av_encode( )函数中output_files和input_files是作为函数参数传入后在其他地方就没有用到了。 2.        AVCodecContext 保存AVCodec指针和与codec相关的数据如video的width、heightaudio的sample rate等。AVCodecContext中的codec_typecodec_id二个变量对于encoder/decoder的匹配来说最为重要。 enum CodecType codec_type; /* seeCODEC_TYPE_xxx */ enumCodecID codec_id; /* see CODEC_ID_xxx */ 如上所示codec_type保存的是CODEC_TYPE_VIDEOCODEC_TYPE_AUDIO等媒体类型 codec_id保存的是CODEC_ID_FLV1CODEC_ID_VP6F等编码方式。 以支持flv格式为例在前述的av_open_input_file(……) 函数中匹配到正确的AVInputFormat demuxer后通过av_open_input_stream( )函数中调用AVInputFormat的read_header接口来执行flvdec.c中的flv_read_header()函数。在flv_read_header()函数内根据文件头中的数据创建相应的视频或音频AVStream并设置AVStream中AVCodecContext的正确的codec_type值。codec_id值是在解码过程中flv_read_packet( )函数执行时根据每一个packet头中的数据来设置的。 3.        AVStream AVStream结构保存与数据流相关的编解码器数据段等信息。比较重要的有如下二个成员 AVCodecContext*codec; /** codec context */ void*priv_data; 其中codec指针保存的就是上节所述的encoder或decoder结构。priv_data指针保存的是和具体编解码流相关的数据如下代码所示在ASF的解码过程中priv_data保存的就是ASFStream结构的数据。 AVStream *st; ASFStream*asf_st;    … … st-priv_data asf_st; 4.        AVInputStream/AVOutputStream 根据输入和输出流的不同前述的AVStream结构都是封装在AVInputStream和AVOutputStream结构中在av_encode( )函数中使用。 AVInputStream中还保存的有与时间有关的信息。 AVOutputStream中还保存有与音视频同步等相关的信息。 5.        AVPacket AVPacket结构定义如下其是用于保存读取的packet数据。 typedefstruct AVPacket { int64_t pts;           /// presentation time stamp in time_base units int64_t dts;           /// decompression time stamp in time_base units uint8_t *data; int   size; int   stream_index; int   flags; int   duration;        ///presentation duration in time_base units (0 if not available) void (*destruct)(struct AVPacket *); void *priv; int64_t pos;           ///byte position in stream, -1 if unknown } AVPacket; 在av_encode( )函数中调用AVInputFormat的(*read_packet)(structAVFormatContext *, AVPacket *pkt);接口读取输入文件的一帧数据保存在当前输入AVFormatContext的AVPacket成员中。 av_encode函数主要流程 av_encode( )函数是FFMpeg中最重要的函数编解码和输出等大部分功能都在此函数内完成因此有必要详细描述一下这个函数的主要流程。 1.        input streamsinitializing 2.        outputstreams initializing 3.        encoders anddecoders initializing 4.        set meta datainformation from input file if required. 5.        write outputfiles header 6.        loop ofhandling each frame a.      read frame frominput file: b.      decode framedata c.      encode newframe data d.      write newframe to output file 7.        write outputfiles trailer 8.        close eachencoder and decoder ·  IV. AVCodecContext 此结构在Ffmpeg SDK中的注释是main external api structure其重要性可见一斑。而且在avcodec它的定义处对其每个 成员变量都给出了十分详细的介绍。应该说AVCodecContext的初始化是Codec使用中最重要的一环。虽然在前面的 AVStream中已经有所提及但是这里还是要在说一遍。AVCodecContext作为Avstream的一个成员结构必须要在Avstream初 始化後(30)再对其初始化(AVStream的初始化用到AVFormatContex)。虽然成员变量比较多但是这里只说一下在 output_example.c中用到了其他的请查阅avcodec.h文件中介绍。 // static AVStream*add_video_stream(AVFormatContext *oc, int codec_id) AVCodecContext *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; // 400kbits/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 controlmethod: cqp等。 值得一提的是在AVCodecContext中有两个成员数据结构AVCodec、AVFrame。AVCodec记录了所要使用的Codec信息并且含有 5个函数init、encoder、close、decode、flush来完成编解码工作参见avcode.h 2072行。AVFrame中主要是包含了编 码後的帧信息包括本帧是否是key frame、*data[4]定义的Y、Cb和Cr信息等随后详细介绍。 初始化後可以说AVCodecContext在(8)(10)中大显身手。先在(8)open_video()中初始化AVCodec *codec以及AVFrame* picture // AVCodecContext *c; codec avcodec_find_encoder(c-codec_id); …… picture alloc_picture(PIX_FMT_YUV420P, c-width, c-height); 後在writer_video_frame(AVFormatContext *oc, AVStream *st)中作为一个编解码器的主要参数被利用 AVCodecContext *c; c st-codec; …… out_size avcodec_encode_video(c,video_outbuf, video_outbuf_size, picture); VAVCodec 结构AVCodec中成员变量和成员函数比较少但是很重要。他包含了CodecID也就是用哪个Codec、 像素格式信息。还有前面提到过的5个函数init、encode、close、decoder、flush。顺便提一下虽然在参考代码 output_example.c中的编码函数用的是avcodec_encode_video我怀疑在其中就是调用了AVCodec的encode函数他们 传递的参数和返回值都是一致的当然还没有得到确认有兴趣可以看看ffmpeg源代码。在参考代码中AVCodec的初始化 後的使用都是依附于AVCodecContex前者是后者的成员。在AVCodecContext初始化後add_video_stream()AVCodec也 就能很好的初始化了 //初始化 codec avcodec_find_encoder(c-codec_id); (33) //打开Codec avcodec_openc, codec (34) VI. AVFrame AVFrame是个很有意思的结构它本身是这样定义的 typedef struct AVFrame { FF_COMMON_FRAME }AVFrame; 其中FF_COMMON_FRAME是以一个宏出现的。由于在编解码过程中AVFrame中的数据是要经常存取的。为了加速要采取这样 的代码手段。 AVFrame是作为一个描述“原始图像”也就是YUV或是RGB…还有其他的吗的结构他的头两个成员数据uint8_t *data[4]int linesize[4]第一个存放的是Y、Cb、Cryuv格式linesize是啥由这两个数据还能提取处另外一个 数据结构 typedef struct AVPicture { uint8_t *data[4]; int linesize[4]; // number of bytesper line }AVPicture ; 此外AVFrame还含有其他一些成员数据比如。是否key_frame、已编码图像书coded_picture_number、是否作为参考帧 reference、宏块类型 *mb_type等等avcodec.h 446行。 AVFrame的初始化并没有他结构上看上去的那么简单。由于AVFrame还有一个承载图像数据的任务data[4]因此对他分 配内存应该要小心完成。output_example.c中提供了alloc_picute()来完成这项工作。参考代码中定义了两个全局变量 AVFrame *picture*tmp_picture。如果使用yuv420格式的那么只用到前一个数据picture就行了将图像信息放入 picture中。如果是其他格式那么先要将yuv420格式初始化后放到tmp_picture中在转到需求格式放入picture中。在 open_video打开编解码器后初始化AVFrame picture alloc_picture(c-pix_fmt, c-width, c-height); tmp_picture alloc_picture(PIX_FMT_YUV420P, c-width, c-height); static AVFrame *alloc_picture(intpix_fmt, int width, int height){ AVFrame *picture; uint8_t *picture_buf; // think aboutwhy use uint8_t? a byte! picture avcodec_alloc_frame();(35) if(!picture) return NULL; size avpicture_get_size(pix_fmt,width, height); (36) picture_buf av_malloc(size); (37) if(!picture_buf){ av_free(picture); (38) return NULL; } avpicture_fill ( (AVPicture*)picture, picture_buf, pix_fmt, width, height); (39) return picture; } 从以上代码可以看出完成对一个AVFrame的初始化其实也就是内存分配基本上是有这样一个固定模式的。至于(35) (39)分别完成了那些工作以及为什么有这样两步还没有搞清楚需要看原代码。我的猜测是(35)对AVFrame做了基本的 内存分配保留了对可以提取出AVPicture的前两个数据的内存分配到(39)来完成。 说到这里我们观察到在(39)中有一个(AVPicture *)pictureAVPicture这个结构也很有用。基本上他的大小也就是要在 网络上传输的包大小我们在后面可以看到AVPacket跟AVPicture有密切的关系。  VIIAVPicture AVPicture在参考代码中没有自己本身的申明和初始化过程。出现了的两次都是作为强制类型转换由AVFrame中提取出来的 // open_video() 中 avpicture_fill((AVPicture *)picture,picture_buf, pix_fmt, width, height); (40) //write_video_frame 中 // AVPacket pkt; if(oc-oformat-flags AVFMT_RAWPICTURE){ …… pkt.size sizeof(AVPicture); (41) } 在(40)中实际上是对AVFrame的data[4]、linesize[4]分配内存。由于这两个数据大小如何分配确实需要有pix_fmt、 width、height来确定。如果输出文件格式就是RAW 图片如YUV和RGBAVPacket作为将编码后数据写入文件的基本数据 单元他的单元大小、数据都是由AVPacket来的。 总结起来就是AVPicture的存在有以下原因AVPicture将Picture的概念从Frame中提取出来就只由Picture图片本 身的信息亮度、色度和行大小。而Frame还有如是否是key frame之类的信息。这样的类似“分级”是整个概念更加清晰。 VIIIAVPacket AVPacket的存在是作为写入文件的基本单元而存在的。我们可能会认为直接把编码后的比特流写入文件不就可以了为什么 还要麻烦设置一个AVPacket结构。在我看来这样的编码设置是十分有必要的特别是在做视频实时传输同步、边界问题可 以通过AVPacket来解决。AVPacket的成员数据有两个时间戳、数据data通常是编码后数据、大小size等等参见 avformat.h 48行。讲AVPacket的用法就不得不提到编解码函数因为AVPacket的好些信息只有在编解码后才能的知。在 参考代码中ouput_example.c 从362到394行做的一个判断分支。如果输出文件格式是RAW图像即YUV或RGB那么就 没有编码函数直接写入文件因为程序本身生成一个YUV文件这里的代码虽然在此看来没什么价值但是如果是解码 函数解出yuv文件或rgb那么基本的写文件操作就是这样的 if(oc-oformat-flags AVFMT_RAWPICTURE) { AVPacket pkt; // 这里没有用指针 av_init_packet(pkt); pkt.flags | PKT_FLAG_KEY // rawpicture 中每帧都是key frame? pkt.stream_index st-index; pkt.data (uint8_t *)picture; pkt.size sizeof(AVPicture); ret av_write_frame(oc, pkt); } 输出非raw picture编码后 else{ // video_outbuf video_outbuf_size在open_video() 中初始化 out_size avcodec_encode_video(c,video_outbuf, video_outbuf_size, picture); (42) if(out_size 0){ AVPacket pkt; av_init_packet(pkt); (43) pkt.ptsav_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 themedia file */ ret av_write_frame(oc, pkt);(45) } else { ret 0; } if (ret ! 0) { fprintf(stderr, Error whilewriting video frame\n); exit(1); } 其中video_outbuf和video_outbuf_size在open_video()里的初始化是这样的 video_outbuf NULL; // 输出不是raw picture而确实用到编码codec if( !(oc-oformat-flags AVFMT_RAWPICTURE)){ video_outbuf_size 200000; video_outbuf av_malloc(video_outbuf_size); } (43)是AVPacket结构的初始化函数。(44)比较难理解而且为什么会有这样的一些时间戳我也没有搞明白。其他的AVPacket 成员数据的赋值比较容易理解要注意的是video_outbuf和video_outbuf_size的初始化问题由于在参考代码中初始化和 使用不在同一函数中所以比较容易忽视。(45)是写文件函数AVFormatContext* oc中含有文件名等信息返回值ret因该 是一共写了多少数据信息如果返回0则说明写失败。(42)和(45)作为比较重要的SDK函数后面还会介绍的。. IX. Conclusion 以上分析了FFMpeg中比较重要的数据结构。下面的这个生成关系理一下思路-表示 派生出 AVFormatContext-AVStream-AVCodecContext-AVCodec | AVOutputFormat or AVInputFormat AVFrame-AVPicture….AVPacket 二FFMpeg 中的函数 在前一部分的分析中我们已经看到FFMpeg SDK提供了许多初始化函数和编码函数。我们要做的就是对主要数据结构正确的初 始化以及正确使用相应的编解码函数以及读写I/O操作函数。作为一个整体化的代码SDKFFMpeg有一些他自己的标准 化使用过程。比如函数av_register_all(); 就是一个最开始就该调用的“注册函数”他初始化了libavcodec“注册” 了所有的的codec和视频文件格式format。下面我沿着参考代码ouput_example.c的脉络介绍一下相关函数。 /****************************************************************** main() ******************************************************************/ 1. av_register_all (); usage: initialize ibavcoded, andregister all codecs and formats 每个使用FFMpeg SDK的工程都必须调用的函数。进行codec和format的注册然后才能使用。声明在allformats.c中都是 宏有兴趣看看。 2. AVOutputFormat guess_format(constchar *short_name, const char *filename, const char *mime_type) usage: 通过文件后缀名猜测文件格式其实也就是要判断使用什么编码器or解码器。 AVOutputFormat *fmt fmt guess_format(NULL, filename,NULL); 3. AVFormatContext*av_alloc_format_context(void)  usage: allocate the output mediacontext.实际是初始化AVFormatContext的成员数据AVClass AVFormatContext *ic; ic-av_class av_format_context_class; //where // format_to_name, options arepointer to function static const AVClassav_format_context_class {“AVFormatContext”, format_to_name, options}; 4. static AVStream*add_video_stream(AVFormatContext *ox, int codec_id); AVStream *video_st; video_st add_video_stream(oc,fmt-video_codec); 5. intav_set_parameters(AVFormatContext *s, AVFormatParameters *ap) usage: set the output parameters(must be done even if no parameters). AVFormatContext *oc; // if failed, return integer smallerthan zero av_set_parameters(oc, NULL); 6. void dump_format(AVFormatContext*ic, int index, const char *url, int is_output); usage: 这一步会用有效的信息把 AVFormatContext 的流域streams field填满。作为一个可调试的诊断我们会将这 些信息全盘输出到标准错误输出中不过你在一个应用程序的产品中并不用这么做 dump_format(oc, 0, filename, 1); // 也就是指明AVFormatContext中的事AVOutputFormat还是 //AVInputFormat 7. static voidopen_video(AVFormatContext *oc, AVStream *st) open_video(oc, video_st); 8. intav_write_header(AVFormatContext *s) usage: allocate the stream privatedata and writer the stream header to an output media file. param s media file handle, return 0 if OK, AVERROR_xxxif error. write the stream header, if any av_write_header(oc); 9. static voidwrite_video_frame(AVFormatContext *oc, AVStream *st) write_video_frame(oc, video_st); 10. static voidclose_video(AVFormatContext *oc, AVStream *st) // close each codec close_video(oc, video_st); 11. intav_write_trailer(AVFormatContext *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. Freesmemory 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 memorywhich has been allocated with av_malloc(z)() or av_realloc(). av_free(oc); /****************************************************************** ****************************************************************** add_video_stream() AVCodecContext *c AVStream *st ******************************************************************/ ****************************************************************** 1.AVStream*av_new_stream(AVFormatContext *s, int id) usage: add a new stream to a mediafile. s: media file handle, id: file format dependent stream id st av_new_stream(oc, 0); /****************************************************************** ****************************************************************** open_video() AVCodecContext *c AVCodec *codec AVFrame *picture, *tmp_picture uint8_t *video_output int frame_count, video_outbuf_size; ****************************************************************** ******************************************************************/ 1 AVCodec *avcodec_find_encoder(enumCodecID id) usage: find the codec of encoder byCodecID. 在前面main中的guess_format()就已经开始为此准备了。 codec avcodec_find_encoder(c-codec_id); 2 int avcodec_open(AVCodecContext*avctx, AVCodec *codec); usage: opens / inits the AVCodecContext.打开失败的话返回值小于零。 avcodec_open(c, codec); 3 void *av_malloc(unsigned in size); usage: you can redefine av_mallocand av_free in your project to use your memory allocator. You do not need to suppress this file because thelinker will do it automatically Memory allocation of size byte withalignment 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 AVFrame *alloc_picture(intpix_fmt, int width, int height) picture alloc_picture(c-pix_fmt, c-width, c-height);  /****************************************************************** ****************************************************************** ****************************************************************** alloc_picture() AVFrame *picture uint8_t *picture_buf int size ****************************************************************** ******************************************************************/ ****************************************************************** 1. avcodec_alloc_frame() usage: initialize AVFrame* picture picture avcodec_alloc_frame() 2. int avpicture_get_size(intpix_fmt, int width, int height) usage: 根据像素格式和视频分辨率获得picture存储大小。 size avpicture_get_size(pix_fmt,width, height); picture_buf av_malloc(size) 3. int avpicture_fill(AVPicture*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。这里由于是在初始化阶段所以填充的可能全是零。 avpicture_fill((AVPicture*)picture,picture_buf, pix_fmt, width, height); /****************************************************************** ****************************************************************** write_video_frame() int out_size, ret; AVCodecContext *c; 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将srcsource转为dst(destination)。 sws_scale(img_convert_ctx,tmp_picture-data, tmp_picture-linesize, 0, c-height,picture-data, picture- linesize); 4. intavcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size, constAVFrame *pict); usage: 根据AVCodecContext将pict编码到buf中buf_size是buf的大小。  out_size avcodec_encode_video(c,video_outbuf, video_outbuf_size, picture); 5 static inline voidav_init_packet(AVPacket *pkt) usage: initialize optional fields ofa packet.初始化AVPacket。 AVPacket pkt; av_init_packet(pkt) 6 int64_t av_rescale_q(int64_t a,AVRational bq, AVRational cq) usage: 校准时间基maybe pkt.pts av_rescale_q(c-coded_frame-pts, c-time_base, st-time_base); 7 int av_write_frame(AVFormatContext*s, AVPacket *pkt) usage: write a packet to an outputmedia file . pkt: the packet, which contains the stream_index, buf/buf_size, dts/pts, …if errorreturn0, if OK 0, if end of stream wanted 1 ret av_write_frame(oc, pke); /****************************************************************** ****************************************************************** static voidclose_video(AVFormatContext *oc, AVStream *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); } /****************************************************************** ****************************************************************** 讲初始化过的特别是分配过内存的都要释放。 注标定红色的函数为需要编程人员自己按照实际应用情况编写的蓝色的是FFMpegSDK中定义的函数。我们会分析函数的 作用和调用方法。 由于时间关系写得很乱。希望没有给你带来太大困扰这份不成熟的文档能对你有一点点地帮助。chinavideo版上有很多 大牛我想做抛砖引玉者希望以后能有更好的文档出现。我也是ffmpeg的初学者如果大家有什么问题也希望能在版上一 起讨论。我的emailyunfhugmail.com
http://www.huolong8.cn/news/77923/

相关文章:

  • 仿淘宝商城网站开源系统wordpress底部添加工信部链接
  • 商业空间设计网站大全网站源码下载 app
  • 当前业界主流的网站建设商标设计免费
  • o2o系统网站建设wordpress七牛加密
  • 网站建设产品服务网站seo分析案例
  • wordpress临时关站网站建设完成报告
  • 仿站教程百度的网址怎么写
  • 如何做自己的简历网站合肥网站建设是什么
  • 手机网站设计公司优选亿企邦品牌网站建设c重庆
  • 做电影网站需要什么软件天津西青区租房
  • 个人网站免费源码大全广告设计logo标志
  • 如何进入设计公司网站网站特效代码上那找好
  • 网站宣传的传统方式有哪些wordpress 微信商城模板
  • 衡水电子商务网站建设设计师品牌推荐
  • 做网站找客源做盗版小说网站
  • 阿里云淘宝客网站建设教程软件上市公司排名
  • 安徽集团网站建设建设部继续教育网站
  • 网页建站软件wordpress专题页
  • 个人备案可以做企业网站吗富拉尔基网站建设
  • 网站注册设计怎么开网站 第一步怎么做
  • 旅游网站建设服务对象家具网站开发设计任务书
  • 如何做起一个网站推广淄博网站运营公司
  • namecheap建站wordpress万州网
  • 网站建设书籍目录wordpress多用户信息发布
  • 一元购网站建设方案书一起做网店17普宁
  • 做室内设计的网站有哪些方面系统优化大师官方下载
  • 北京城建设计院网站espcms易思企业网站管理系统破解
  • 做网站域名备案需要多久自媒体怎么申请注册
  • 网站开发专利申请网站挂马个人问题还是服务商
  • 直邮网站的推广活动怎么做网站建设最好的书籍是