ffmpeg architecture(下)
ffmpeg architecture(下)
第3章-转码
TLDR;给我看代码和执行。
$ make run_transcoding
我们将跳过一些细节,但是请放心:源代码可在github上找到。
在本章中,我们将创建一个用C编写的极简代码转换器,可以使用FFmpeg / libav库(尤其是libavcodec,libavformat和libavutil)将H264编码的视频转换为H265。
只是快速回顾一下:该AVFormatContext是媒体文件格式的抽象,又名容器(例如:MKV,MP4,WEBM,TS)。的AV流表示每种类型的用于给定格式(例如:音频,视频,字幕,元数据)的数据。所述AVPacket是从所获得的压缩数据的切片AVStream可以由一个解码avcodec中:产生称为原始数据(例如AV1,H264,VP9,HEVC)AVFrame。
转码
让我们从简单的转换操作开始,然后我们可以基于此代码构建,第一步是加载输入文件。
//分配一个AVFormatContextavfc = avformat_alloc_context();//打开输入流并读取标题。avformat_open_input(avfc,in_filename, NULL,NULL);//读取媒体文件的数据包以获取流信息。avformat_find_stream_info(avfc, NULL);
现在,我们要设置解码器,它AVFormatContext将使我们能够访问所有AVStream组件,并且对于每个组件,我们都可以获取它们AVCodec并创建特定组件AVCodecContext,最后我们可以打开给定的编解码器,以便继续进行解码处理。
所述AVCodecContext持有如比特率,帧速率,采样率,信道,高度,和许多其它有关的媒体数据的配置等。
对于(int i = 0 ; i nb_streams; i ++){ AVStream * avs = avfc-> 流 [i]; AVCodec * avc = avcodec_find_decoder(avs-> codecpar- > codec_id); AVCodecContext * avcc = avcodec_alloc_context3(* avc); avcodec_parameters_to_context(* avcc,avs-> codecpar); avcodec_open2(* avcc,* avc,NULL);}
我们还需要准备输出媒体文件以进行多路传输,我们首先为输出分配内存AVFormatContext。我们以输出格式创建每个流。为了正确打包流,我们从解码器复制编解码器参数。
我们设置标志 AV_CODEC_FLAG_GLOBAL_HEADER告诉编码器它可以使用全局头文件,最后打开输出文件进行写入并保留头文件。
avformat_alloc_output_context2(&encoder_avfc,NULL,NULL,out_filename); AVStream * avs = avformat_new_stream(encoder_avfc,NULL);avcodec_parameters_copy(avs-> codecpar,解码器_avs-> codecpar); 如果(encoder_avfc-> oformat-> flags和AVFMT_GLOBALHEADER) encoder_avfc-> flags | = AV_CODEC_FLAG_GLOBAL_HEADER; avio_open(&encoder_avfc-> pb,编码器->文件名,AVIO_FLAG_WRITE);avformat_write_header(encoder- > avfc,&muxer_opts);
我们AVPacket从解码器获取,调整时间戳,并将数据包正确写入输出文件。即使函数av_interleaved_write_frame说“写帧”,我们仍在存储数据包。通过将流预告片写入文件中,我们完成了转换过程。
AVFrame * input_frame = av_frame_alloc();AVPacket * input_packet = av_packet_alloc(); 而(av_read_frame(decoder_avfc,input_packet)> = 0){ av_packet_rescale_ts(input_packet,解码器_视频_avs-> time_base,编码器 _视频_avs- > time_base); av_interleaved_write_frame(* avfc,input_packet)< 0));} av_write_trailer(encoder_avfc);
转码
前面展示了一个简单的transmuxer程序,现在我们将添加对文件进行编码的功能,尤其是使它能够将视频从转换h264为h265。
在准备好解码器之后,但在安排输出媒体文件之前,我们将设置编码器。
AVStream在编码器中创建视频,avformat_new_stream
使用AVCodec所谓的libx265,avcodec_find_encoder_by_name
AVCodecContext在创建的编解码器中创建基础,avcodec_alloc_context3
设置转码会话的基本属性,并
打开编解码器,然后将参数从上下文复制到流中。avcodec_open2和avcodec_parameters_from_context
AVRational input_framerate = av_guess_frame_rate(decoder_avfc,decoder_video_avs,NULL);AVStream * video_avs = avformat_new_stream(encoder_avfc,NULL); char * codec_name = “ libx265 ” ;char * codec_priv_key = “ x265-params ” ;//我们将为x265使用内部选项// //禁用场景更改检测,然后修复// 60帧的GOP。char * codec_priv_value = “ keyint = 60:min-keyint = 60:scenecut = 0 ” ; AVCodec * video_avc = avcodec_find_encoder_by_name(codec_name);AVCodecContext * video_avcc = avcodec_alloc_context3(video_avc);//编码器编解码器参数av_opt_set(sc-> video_avcc-> priv_data,codec_priv_key,codec_priv_value, 0);video_avcc-> height =解码器_ctx-> height;video_avcc-> width =解码器_ctx-> width;video_avcc-> pix_fmt = video_avc-> pix_fmts [ 0 ];//控制率 video_avcc-> bit_rate = 2 * 1000 * 1000 ;video_avcc-> rc_buffer_size = 4 * 1000 * 1000 ;video_avcc-> rc_max_rate = 2 * 1000 * 1000 ;video_avcc-> rc_min_rate = 2.5 * 1000 * 1000 ;//时基video_avcc-> time_base = av_inv_q(input_framerate);video_avs-> time_base = sc-> video_avcc-> time_base; avcodec_open2(sc-> video_avcc,sc-> video_avc,NULL);avcodec_parameters_from_context(sc-> video_avs-> codecpar,sc-> video_avcc);
我们需要扩展解码循环以进行视频流转码:
将空发送AVPacket给解码器,avcodec_send_packet 接收未压缩的AVFrame,avcodec_receive_frame
开始对该原始帧进行转码,发送原始帧, avcodec_send_frame
根据我们的编解码器接收压缩的文件AVPacket,avcodec_receive_packet
设置时间戳,并 av_packet_rescale_ts 将其写入输出文件。 av_interleaved_write_frame
AVFrame * input_frame = av_frame_alloc();AVPacket * input_packet = av_packet_alloc(); 而(av_read_frame(decoder_avfc,input_packet)> = 0){ int响应= avcodec_send_packet(decoder_video_avcc,input_packet); while(响应> = 0){ 响应= avcodec_receive_frame(decoder_video_avcc,input_frame); if(响应== AVERROR(EAGAIN)|| response == AVERROR_EOF){ 中断 ; } else if(response < 0){ 返回响应; } if(响应> = 0){ 编码(encoder_avfc,decoder_video_avs,encoder_video_avs,decoder_video_avcc,input_packet-> stream_index); } av_frame_unref(input_frame); } av_packet_unref(input_packet);}av_write_trailer(encoder_avfc); //使用的函数int 编码(AVFormatContext * avfc,AVStream * dec_video_avs,AVStream * enc_video_avs,AVCodecContext video_avcc int索引){ AVPacket * output_packet = av_packet_alloc(); int response = avcodec_send_frame(video_avcc,input_frame); while(响应> = 0){ 响应= avcodec_receive_packet(video_avcc,output_packet); if(响应== AVERROR(EAGAIN)|| response == AVERROR_EOF){ 中断 ; } else if(响应< 0){ return - 1 ; } output_packet-> stream_index = index ; output_packet-> 持续时间 = enc_video_avs-> 那么time_base。den / enc_video_avs-> time_base。num / dec_video_avs-> avg_frame_rate。num * dec_video_avs-> avg_frame_rate。巢穴 ; av_packet_rescale_ts(output_packet,dec_video_avs-> time_base,enc_video_avs-> time_base); 响应= av_interleaved_write_frame(avfc,output_packet); } av_packet_unref(output_packet); av_packet_free(&output_packet); 返回 0 ;}
我们将媒体流从转换h264为h265,正如预期的那样h265,媒体文件的版本小于,h264但创建的程序能够:
/ * * H264-> H265 *音频->重混合(未触摸) * MP4-MP4 * / StreamingParams sp = { 0 }; sp.copy_audio = 1 ; sp.copy_video = 0 ; sp.video_codec = “ libx265 ”; sp.codec_priv_key = “ x265-params ” ; sp.codec_priv_value = “ keyint = 60:min-keyint = 60:scenecut = 0 ” ; / * * H264-> H264(固定gop) *音频->重混合(未触摸) * MP4-MP4 * / StreamingParams sp = { 0 }; sp.copy_audio = 1 ; sp.copy_video = 0 ; sp.video_codec = “ libx264 ”; sp.codec_priv_key = “ x264参数” ; sp.codec_priv_value = “ keyint = 60:min-keyint = 60:scenecut = 0:force-cfr = 1 ” ; / * * H264-> H264(固定gop) 音频->重混合(未修改) MP4- 片段MP4 * / StreamingParams sp = { 0 }; sp.copy_audio = 1 ; sp.copy_video = 0 ; sp.video_codec = “ libx264 ”; sp.codec_priv_key = “ x264参数” ; sp.codec_priv_value = “ keyint = 60:min-keyint = 60:scenecut = 0:force-cfr = 1 ” ; sp.muxer_opt_key = “ movflags ”; sp.muxer_opt_value = “ frag_keyframe + empty_moov + default_base_moof ” ; / * * H264-> H264(固定gop) *音频-> AAC * MP4-MPEG-TS * / StreamingParams sp = { 0 }; sp.copy_audio = 0 ; sp.copy_video = 0 ; sp.video_codec = “ libx264 ”; sp.codec_priv_key = “ x264参数” ; sp.codec_priv_value = “ keyint = 60:min-keyint = 60:scenecut = 0:force-cfr = 1 ” ; sp.audio_codec = “ aac ” ; sp.output_extension = “ .ts ” ; / * WIP:P->它不在VLC上播放,最终比特率很高 * H264-> VP9 *音频-> Vorbis * MP4-WebM * / // StreamingParams sp = {0}; // sp.copy_audio = 0; // sp.copy_video = 0; // sp.video_codec =“ libvpx-vp9”; // sp.audio_codec =“ libvorbis”; // sp.output_extension =“ .webm”;
现在,说实话,这是难度比我想这会是我不得不挖掘到FFmpeg的命令行的源代码和测试了很多,我觉得我失去了一些东西,因为我不得不执行force-cfr的h264工作而且我仍然看到一些警告消息,例如warning messages (forced frame type (5) at 80 was changed to frame type (3))。
ffmpeg architecture(下)相关推荐
- ffmpeg architecture(中)
ffmpeg architecture(中) 艰苦学习FFmpeg libav 您是否不奇怪有时会发出声音和视觉? 由于FFmpeg作为命令行工具非常有用,可以对媒体文件执行基本任务,因此如何在程序中 ...
- ffmpeg architecture(上)
ffmpeg architecture(上) · 视频-您看到的是什么! · 如果您有一系列图像序列,并以给定的频率(例如每秒24张图像)进行更改,则会产生运动的错觉.总之,这是视频背后的基本概念:一 ...
- FFmpeg - Windows下使用MSYS2和VS编译FFmpeg
文章目录 0. 说明 1. 安装MSYS2 1.1 下载 1.2 安装 2. 下载FFmpeg及其他源码 3. 编译配置依赖库 3.1 打开一个新的MSYS2终端 3.2 编译x264 3.3 编译 ...
- Opencv FFmpeg Ubuntu下编译问题
FFmpeg转码错误Cannot load libcuda.so.1 https://blog.csdn.net/yzhang6_10/article/details/81349532 srs2.0 ...
- FFmpeg Windows下安装与测试
FFmpeg 简介 FFmpeg的名称来自MPEG视频编码标准,前面的"FF"代表"Fast Forward",FFmpeg是一套可以用来记录.转换数字音频.视 ...
- ffmpeg window下批量转换MP3为wav
转载链接:https://blog.csdn.net/fuchuchen/article/details/55214216 ffmpeg 在window下将MP3转换为wav文件 1)ffmpeg ...
- 【FFMPEG系列】FFMPEG linux下集成x264
FFMPEG集成x264 1.x264下载地址: http://download.videolan.org/pub/videolan/x264/snapshots/ 2. FFMPEG引入外部库x26 ...
- ffmpeg Windows下录制桌面视频命令
ffmpeg -f gdigrab -framerate 30 -i desktop out.yuv 命令执行结果如下 C:\Users\Administrator>ffmpeg -f gdig ...
- FFmpeg —— Linux下进行编译配置(硬件加速编解码)
前提 这里首先需要大家在自己的Linux系统上安装了nvidia显卡驱动.cuda. 查看nvidia是否安装成功:nvidia-smi 查看cuda是否安装成功: ...
最新文章
- 图文详解 23 种设计模式
- Json返回时间中出现乱码问题的两种解决方法
- FreeRTOS系列第2篇---FreeRTOS入门指南
- Elasticsearch技术解析与实战(二)文档的CRUD操作
- LeetCode算法入门- 4Sum -day11
- Qt UDP组播的应用
- LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话(简单易懂)
- js ajax 表单异步提交
- 如何搭建企业大数据分析平台
- 还有没换国旗头像的么 头像领取方法 不要再@微信官方啦
- windows11 怎么使用IE浏览器,修改edge参数来实现
- Flutter——打包Windows桌面应用(流程)
- 你是阳光,你的世界充满阳光---心在哪,成就就在哪
- 无线AP概念功率mW、灵敏度dBm、增益dBi
- 《大规模元搜索引擎技(1)》一第1章 绪言
- tm1650中文资料_TM1650+msp430单片机 调试及遇到问题的总结
- Codeforces Round #540 (Div. 3) D. Coffee and Coursework 二分
- stm32山外虚拟示波器笔记
- ssis oracle配置,通过SSIS执行Oracle参数是什么?
- VLC电脑串流视频到手机播放