湛江商城网站开发设计,手游源码平台,汕尾网站建设,c mvc制作网站开发该例子讲了如何输出一个libavformat库所支持格式的媒体文件。 #xff08;1#xff09;av_register_all()#xff0c;初始化libavcodec库#xff0c;并注册所有的编解码器和格式。 #xff08;2#xff09;guess_format()#xff0c;根据文件名来获取输出文件格式#… 该例子讲了如何输出一个libavformat库所支持格式的媒体文件。 1av_register_all()初始化libavcodec库并注册所有的编解码器和格式。 2guess_format()根据文件名来获取输出文件格式默认为mpeg。 3av_alloc_format_context()分配输出媒体内容。 ov-oformat fmt; snprintf( oc-filename, sizeof(oc-filename), “%s”, filename ); 4add_video_stream()使用默认格式的编解码器来增加一个视频流并初始化编解码器。 4.1av_new_stream()增加一个新的流到一个媒体文件。 4.2初始化编解码器 c st-codec; c-codec_id codec_id; c-codec_type CODEC_TYPE_VIDEO; c-bit_rate 400000; c-width 352; c-height 288; c-time_base.den STREAM_FRAME_RATE; //每秒25副图像 c-time_base.num 1; c-gop_size 12; c-pix_fmt STREAM_PIX_FMT; //默认格式为PIX_FMT_YUV420P …… …… 5av_set_parameters()设置输出参数即使没有参数该函数也必须被调用。 6dump_format()输出格式信息用于调试。 7open_video()打开视频编解码器并分配必要的编码缓存。 7.1avcodec_find_encoder()寻找c-codec_id指定的视频编码器。 7.2avcodec_open()打开编码器。 7.3分配视频输出缓存 video_outbuf_size 200000; video_outbuf av_malloc( video_outbuf_size ); 7.4picture alloc_picture()分配原始图像。 7.4.1avcodec_alloc_frame()分配一个AVFrame并设置默认值。 7.4.2size avpicture_get_size()计算对于给定的图片格式以及宽和高所需占用多少内存。 7.4.3picture_buf av_malloc( size )分配所需内存。 7.4.4avpicture_fill()填充AVPicture的域。 7.5可选。如果输出格式不是YUV420P那么临时的YUV420P格式的图像也是需要的由此再转换为我们所需的格式因此需要为临时的YUV420P图像分配缓存 tmp_picture alloc_picture() 说明tmp_picturepicturevideo_outbuf。如果输出格式为YUV420P则直接通过avcodec_ encode_video()函数将picture缓存中的原始图像编码保存到video_outbuf缓存中如果输出格式不是YUV420P则需要先通过sws_scale()函数将YUV420P格式转换为目标格式此时tmp_picture缓存存放的是YUV420P格式的图像而picture缓存为转换为目标格式后保存的图像进而再将picture缓存中的图像编码保存到video_outbuf缓存中。 8url_fopen()打开输出文件如果需要的话。 9av_write_header()写流动头部。 10LOOP循环{ 计算当前视频时间video_pts 是否超时退出循环 write_video_frame()视频编码 } 10.1write_video_frame() 如果图片不是YUV420P则需要用sws_scale()函数先进行格式转换。 若需要原始图像 av_init_packet()初始化一个包的选项域。 av_write_frame()向输出媒体文件写一个包该包会包含一个视频帧。 若需要编码图像 avcodec_encode_video()编码一视频帧。 av_init_packet() av_write_frame() 11close_video()关闭每个编解码器。 12av_write_trailer()写流的尾部。 13释放资源 av_freep()释放AVFormatContext下的AVStream-AVCodecContext和AVStream for( i 0; i oc-nb_streams; i ){ av_freep( oc-streams[i]-codec ); av_freep( oc-streams[i] ); } url_fclose()关闭输出文件。 av_free()释放AVFormatContext。 apiexample.c例子教我们如何去利用ffmpeg库中的api函数来自己编写编解码程序。 1首先main函数中一开始会去调用avcodec_init()函数该函数的作用是初始化libavcodec而我们在使用avcodec库时该函数必须被调用。 2avcodec_register_all()函数注册所有的编解码器codecs解析器parsers以及码流过滤器bitstream filters。当然我们也可以使用个别的注册函数来注册我们所要支持的格式。 3video_encode_example()函数用于视频编码由图可知所有的编码工作都在该函数内完成。 4avcodec_find_encoder()函数用于查找一个与codec ID相匹配的已注册的编码器。 5avcodec_alloc_context()函数用于分配一个AVCodecContext并设置默认值如果失败返回NULL并可用av_free()进行释放。 6avcodec_alloc_frame()函数用于分配一个AVFrame并设置默认值如果失败返回NULL并可用av_free()进行释放。 7设置参数 设置采样参数即比特率。 c-bit_rate 400000; 设置分辨率必须是2的倍数。 c-width 352; c-height 288; 设置帧率。 c-time_base (AVRational){1,25}; 该帧率为25其实timebase 1/framerate花括号内分别为分子和分母。 设置GOP大小。 c-gop_size 10; 该值表示每10帧会插入一个I帧intra frame。 设置B帧最大数。 c-max_b_frames 1; 该值表示在两个非B帧之间所允许插入的B帧的最大帧数。 设置像素格式。 c-pix_fmt PIX_FMT_YUV420P; 该值将像素格式设置为YUV420P。 8avcodec_open()函数用给定的AVCodec来初始化AVCodecContext。 9接着是打开文件f fopen( filename, “wb” ); 10分配图像和输出缓存。 申请100KB左右的内存作为输出缓存。 outbuf_size 100000; outbuf malloc( outbuf_size ); 根据帧的大小来确定YUV420所占内存大小一个像素RGB格式占用3个字节而YUV420格式只占用两个字节。YUV420格式是指每个像素都保留一个Y亮度分量而在水平方向上不是每行都取U和V分量而是一行只取U分量则其接着一行就只取V分量以此重复所以420不是指没有V而是指一行采样只取U另一行采样只取V。在取U和V时每两个Y之间取一个U或V。但从4x4矩阵列来看每4个矩阵点Y区域中只有一个U和V所以它们的比值是4:1。所以对于一个像素RGB需要8 * 3 24位即占3个字节而YUV420P8 8/4 8/4 12位即占2个字节其中8指Y分量8/4指U和V分量。 size c-width * c-height; picture_buf malloc( (size * 3) / 2 ); picture-data[0] picture_buf; picture-data[1] picture-data[0] size; picture-data[2] picture-data[1] size / 4; picture-linesize[0] c-width; picture-linesize[1] c-width / 2; picture-linesize[2] c-width / 2; 其中data[0]存放Ydata[1]存放Udata[2]存放V【FixMe】。linesize[0]表示Y分量的宽度linesize[1]表示U分量的宽度linesize[2]表示V分量的宽度。 11编码一秒钟的视频帧率为25所以需要循环25次每次编码一帧。 11.1准备一幅伪图像即自己自定义往里面塞数据。 for(y0;yheight;y){ for(x0;xwidth;x){ picture-data[0][y*picture-linesize[0]x]xyi*3; } } for(y0;yheight/2;y){ for(x0;xwidth/2;x){ picture-data[1][y*picture-linesize[1]x]128yi*2; picture-data[2][y*picture-linesize[2]x]64xi*5; } } 11.2avcodec_encode_video()从picture中编码一帧视频数据并存入到outbuf中而期间所使用的编码器为c。 11.3将编码完的数据写入到文件里。 12对延时的帧数据进行编码。因为像MPEG4中I帧、P帧和B帧之间存在一定的延时【FixMe】。同样是avcodec_encode_video()然后写入文件。 13添加结束代码使其成为一个真正的mpeg文件。 outbuf[0] 0x00; outbuf[1] 0x00; outbuf[2] 0x01; outbuf[3] 0xb7; fwrite( outbuf, 1, 4, f ); 这个结束代码表示什么 14释放资源。 fclose(f); free(picture_buf); free(outbuf); avcodec_close(c); av_free(c); av_free(picture);