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

怎样凡科建设网站杭州网站设计制作

怎样凡科建设网站,杭州网站设计制作,郑州网络建站公司,外国的html 素材网站主函数逐句解析: 由于代码太多我们只解析主函数,(其他封装函数见前面文章,同时用到了解码编码封装代码)。 初始化和参数处理 int main(int argc, char* argv[]) {/// 输入参数处理string useage "124_test_x…

主函数逐句解析:

由于代码太多我们只解析主函数,(其他封装函数见前面文章,同时用到了解码编码封装代码)。

初始化和参数处理 

int main(int argc, char* argv[])
{/// 输入参数处理string useage = "124_test_xformat 输入文件 输出文件 开始时间(秒) 结束时间(秒) 视频宽 视频高\n";useage += "124_test_xformat v1080.mp4 test_out.mp4 10 20 400 300";cout << useage << endl;if (argc < 3){return -1;}string in_file = argv[1];//输入文件参数string out_file = argv[2];//输出文件参数

 这段代码是程序的入口。它首先定义了程序的用法提示,并将其打印出来。然后,它检查命令行参数的数量是否正确,若不足三个参数,则程序退出。接着,它从命令行参数中获取输入文件和输出文件的路径。

截取时间参数和视频尺寸参数 

    /// 截取10 ~ 20 秒之间的音频视频 取多不取少// 假定 9 11秒有关键帧 我们取第9秒int begin_sec = 0;    //截取开始时间int end_sec = 0;      //截取结束时间if (argc > 3)begin_sec = atoi(argv[3]);if (argc > 4)end_sec = atoi(argv[4]);int video_width = 0;int video_height = 0;if (argc > 6)video_width = atoi(argv[5]);video_height = atoi(argv[6]);

 这段代码获取截取的开始和结束时间(以秒为单位),以及视频的宽度和高度。如果命令行参数中没有提供这些参数,则使用默认值。

解封装输入文件 

    /// 解封装//解封装输入上下文XDemux demux;AVFormatContext* demux_c = demux.Open(in_file.c_str());demux.set_c(demux_c);long long video_begin_pts = 0;long long audio_begin_pts = 0;  //音频的开始时间long long video_end_pts = 0;//开始截断秒数 算出输入视频的pts//if (begin_sec > 0){//计算视频的开始和结束播放pts if (demux.video_index() >= 0 && demux.video_time_base().num > 0){double t = (double)demux.video_time_base().den / (double)demux.video_time_base().num;video_begin_pts = t * begin_sec;video_end_pts = t * end_sec;demux.Seek(video_begin_pts, demux.video_index()); //移动到开始帧}//计算音频的开始播放ptsif (demux.audio_index() >= 0 && demux.audio_time_base().num > 0){double t = (double)demux.audio_time_base().den / (double)demux.audio_time_base().num;audio_begin_pts = t * begin_sec;}}

这段代码创建了解封装对象 XDemux 并打开输入文件。它计算开始和结束时间对应的视频和音频PTS(Presentation Timestamps),然后将解封装器定位到视频开始时间的关键帧。 

视频解码器初始化 

    /视频解码器的初始化并打开解码器XDecode decode;AVCodecContext* decode_c = decode.Create(demux.video_codec_id(), false);//设置视频解码器参数demux.CopyPara(demux.video_index(), decode_c);decode.set_c(decode_c);decode.Open();auto frame = decode.CreateFrame(); //解码后存储/

这段代码初始化视频解码器 XDecode 并打开解码器。它从解封装器中复制视频参数,并为解码后的帧数据分配内存。 

视频编码器初始化 

    /视频编码的初始化if (demux.video_index() >= 0){if (video_width <= 0)video_width = demux_c->streams[demux.video_index()]->codecpar->width;if (video_height <= 0)video_height = demux_c->streams[demux.video_index()]->codecpar->height;}XEncode encode;auto encode_c = encode.Create(AV_CODEC_ID_H265, true);encode_c->pix_fmt = AV_PIX_FMT_YUV420P;encode_c->width = video_width;encode_c->height = video_height;encode.set_c(encode_c);encode.Open();/

 这段代码初始化视频编码器 XEncode 并打开编码器。如果没有指定视频宽度和高度,则使用解封装器中的视频参数。编码器设置为 H.265 编码,像素格式为 YUV420P。

封装初始化 

    /// 封装//编码器上下文//const char* out_url = "test_mux.mp4";XMux mux;auto mux_c = mux.Open(out_file.c_str());mux.set_c(mux_c);auto mvs = mux_c->streams[mux.video_index()]; //视频流信息auto mas = mux_c->streams[mux.audio_index()]; //视频流信息//有视频if (demux.video_index() >= 0){mvs->time_base.num = demux.video_time_base().num;mvs->time_base.den = demux.video_time_base().den;//复制视频参数//demux.CopyPara(demux.video_index(), mvs->codecpar);// 复制编码器格式avcodec_parameters_from_context(mvs->codecpar, encode_c);}//有音频if (demux.audio_index() >= 0){mas->time_base.num = demux.audio_time_base().num;mas->time_base.den = demux.audio_time_base().den;//复制音频参数demux.CopyPara(demux.audio_index(), mas->codecpar);}// 写入头部,会改变timebasemux.WriteHead();

这段代码初始化封装器 XMux 并打开输出文件。它设置视频和音频流的时间基,并复制编码器参数到封装器。最后,它写入文件头。

为什么初始化封装器的时候复制编码器参数到封装器而不是解码器参数给封装器

在视频处理的流程中,封装器(muxer)初始化时需要复制编码器的参数,而不是解码器的参数,这是因为封装器的目的是将编码后的数据打包成一个文件格式,而不是处理原始解码后的数据。让我们具体看看原因:

  • 解码器参数:这些参数用于描述如何从压缩格式(如H.264、HEVC等)解码出原始的未压缩数据(如YUV帧)。解码器参数包括压缩格式、比特率、分辨率等,但这些参数主要用于解码过程。

  • 编码器参数:这些参数用于描述如何将原始的未压缩数据(如YUV帧)压缩成目标格式(如H.264、HEVC等)。编码器参数包括目标压缩格式、比特率、分辨率、帧率等。封装器需要这些参数来正确打包和封装编码后的数据流。

  • 封装器的任务是将已经编码的数据按照特定的容器格式(如MP4、MKV等)打包成文件。因此,它需要知道数据的编码方式(即编码器参数)来正确地打包数据流。

读取、解码、编码和写入数据

    int audio_count = 0;int video_count = 0;double total_sec = 0;AVPacket pkt;for (;;){if (!demux.Read(&pkt)){break;}// 视频 时间大于结束时间if (video_end_pts > 0&& pkt.stream_index == demux.video_index()&& pkt.pts > video_end_pts){av_packet_unref(&pkt);break;}if (pkt.stream_index == demux.video_index()) //视频{mux.RescaleTime(&pkt, video_begin_pts, demux.video_time_base());//解码视频if (decode.Send(&pkt)){while (decode.Recv(frame)){// 修改图像尺寸 //视频编码AVPacket* epkt = encode.Encode(frame);if (epkt){epkt->stream_index = mux.video_index();//写入视频帧 会清理pktmux.Write(epkt);//av_packet_free(&epkt);}}}video_count++;if (demux.video_time_base().den > 0)total_sec += pkt.duration * ((double)demux.video_time_base().num / (double)demux.video_time_base().den);av_packet_unref(&pkt);}else if (pkt.stream_index == demux.audio_index()){mux.RescaleTime(&pkt, audio_begin_pts, demux.audio_time_base());audio_count++;//写入音频帧 会清理pktmux.Write(&pkt);}else{av_packet_unref(&pkt);}}

这段代码读取、解码和编码数据。它从输入文件中读取数据包,并根据数据包的类型进行不同的处理。如果是视频数据包,则解码后编码并写入输出文件;如果是音频数据包,则直接写入输出文件。 

写入结尾并释放资源 

    //写入结尾 包含文件偏移索引mux.WriteEnd();demux.set_c(nullptr);mux.set_c(nullptr);encode.set_c(nullptr);cout << "输出文件" << out_file << ":" << endl;cout << "视频帧:" << video_count << endl;cout << "音频帧:" << audio_count << endl;cout << "总时长:" << total_sec << endl;getchar();return 0;
}

运行结果:

以h265重新编码了原视频,生成了一段视频。

 主函数代码总览:


#include <iostream>
#include <thread>
#include "xdemux.h"
#include "xmux.h"
#include "xdecode.h"
#include "xencode.h"
#include "xvideo_view.h"
using namespace std;
extern "C"
{ 
#include <libavformat/avformat.h>
}int main(int argc, char* argv[])
{/// 输入参数处理string useage = "124_test_xformat 输入文件 输出文件 开始时间(秒) 结束时间(秒) 视频宽 视频高\n";useage += "124_test_xformat v1080.mp4 test_out.mp4 10 20 400 300";cout << useage << endl;if (argc < 3){return -1;}string in_file = argv[1];//输入文件参数string out_file = argv[2];//输出文件参数/// 截取10 ~ 20 秒之间的音频视频 取多不取少// 假定 9 11秒有关键帧 我们取第9秒int begin_sec = 0;    //截取开始时间int end_sec = 0;      //截取结束时间if (argc > 3)begin_sec = atoi(argv[3]);if (argc > 4)end_sec = atoi(argv[4]);int video_width = 0;int video_height = 0;if (argc > 6)video_width = atoi(argv[5]);video_height = atoi(argv[6]);/// 解封装//解封装输入上下文XDemux demux;AVFormatContext* demux_c = demux.Open(in_file.c_str());demux.set_c(demux_c);long long video_begin_pts = 0;long long audio_begin_pts = 0;  //音频的开始时间long long video_end_pts = 0;//开始截断秒数 算出输入视频的pts//if (begin_sec > 0){//计算视频的开始和结束播放pts if (demux.video_index() >= 0 && demux.video_time_base().num > 0){double t = (double)demux.video_time_base().den / (double)demux.video_time_base().num;video_begin_pts = t * begin_sec;video_end_pts = t * end_sec;demux.Seek(video_begin_pts, demux.video_index()); //移动到开始帧}//计算音频的开始播放ptsif (demux.audio_index() >= 0 && demux.audio_time_base().num > 0){double t = (double)demux.audio_time_base().den / (double)demux.audio_time_base().num;audio_begin_pts = t * begin_sec;}}/视频解码器的初始化并打开解码器XDecode decode;AVCodecContext* decode_c = decode.Create(demux.video_codec_id(), false);//设置视频解码器参数demux.CopyPara(demux.video_index(), decode_c);decode.set_c(decode_c);decode.Open();auto frame = decode.CreateFrame(); //解码后存储//视频编码的初始化if (demux.video_index() >= 0){if (video_width <= 0)video_width = demux_c->streams[demux.video_index()]->codecpar->width;if (video_height <= 0)video_height = demux_c->streams[demux.video_index()]->codecpar->height;}XEncode encode;auto encode_c = encode.Create(AV_CODEC_ID_H265, true);encode_c->pix_fmt = AV_PIX_FMT_YUV420P;encode_c->width = video_width;encode_c->height = video_height;encode.set_c(encode_c);encode.Open();//// 封装//编码器上下文//const char* out_url = "test_mux.mp4";XMux mux;auto mux_c = mux.Open(out_file.c_str());mux.set_c(mux_c);auto mvs = mux_c->streams[mux.video_index()]; //视频流信息auto mas = mux_c->streams[mux.audio_index()]; //视频流信息//有视频if (demux.video_index() >= 0){mvs->time_base.num = demux.video_time_base().num;mvs->time_base.den = demux.video_time_base().den;//复制视频参数//demux.CopyPara(demux.video_index(), mvs->codecpar);// 复制编码器格式avcodec_parameters_from_context(mvs->codecpar, encode_c);}//有音频if (demux.audio_index() >= 0){mas->time_base.num = demux.audio_time_base().num;mas->time_base.den = demux.audio_time_base().den;//复制音频参数demux.CopyPara(demux.audio_index(), mas->codecpar);}// 写入头部,会改变timebasemux.WriteHead();int audio_count = 0;int video_count = 0;double total_sec = 0;AVPacket pkt;for (;;){if (!demux.Read(&pkt)){break;}// 视频 时间大于结束时间if (video_end_pts > 0&& pkt.stream_index == demux.video_index()&& pkt.pts > video_end_pts){av_packet_unref(&pkt);break;}if (pkt.stream_index == demux.video_index()) //视频{mux.RescaleTime(&pkt, video_begin_pts, demux.video_time_base());//解码视频if (decode.Send(&pkt)){while (decode.Recv(frame)){// 修改图像尺寸 //视频编码AVPacket* epkt = encode.Encode(frame);if (epkt){epkt->stream_index = mux.video_index();//写入视频帧 会清理pktmux.Write(epkt);//av_packet_free(&epkt);}}}video_count++;if (demux.video_time_base().den > 0)total_sec += pkt.duration * ((double)demux.video_time_base().num / (double)demux.video_time_base().den);av_packet_unref(&pkt);}else if (pkt.stream_index == demux.audio_index()){mux.RescaleTime(&pkt, audio_begin_pts, demux.audio_time_base());audio_count++;//写入音频帧 会清理pktmux.Write(&pkt);}else{av_packet_unref(&pkt);}}//写入结尾 包含文件偏移索引mux.WriteEnd();demux.set_c(nullptr);mux.set_c(nullptr);encode.set_c(nullptr);cout << "输出文件" << out_file << ":" << endl;cout << "视频帧:" << video_count << endl;cout << "音频帧:" << audio_count << endl;cout << "总时长:" << total_sec << endl;getchar();return 0;
}

http://www.dtcms.com/wzjs/75788.html

相关文章:

  • 网站设计的主题搜索引擎推广方式有哪些
  • 服务器做网站用什么环境好最新经济新闻
  • 做团购网站的公司网站建设方案
  • 怎么做直播视频教学视频网站营销推广是什么意思
  • 寺院网站建设代发新闻稿最大平台
  • app的制作需要多少钱青岛seo推广专员
  • 门户网站开发多少钱一键免费创建论坛网站
  • 巢湖网站建设网络营销与直播电商就业前景
  • 小型网站建设实训教程地推拉新接单平台
  • 找人做网站属于诈骗吗郑州网站优化哪家好
  • 网站注册免费qq谷歌下载官网
  • 网站可以改内链结构吗读书网站排名
  • 盘锦网站建设哪家好google下载官方版
  • 网站做线上销售黄页
  • wordpress模板查询seo排名赚能赚钱吗
  • 郑州网站建设铁哥们web网页制作成品免费
  • 哪些网站可以做推广百度网盘客服人工电话95188
  • wordpress图片分组seo需要懂代码吗
  • 网站开发与设计专业百度seo自动优化
  • 做自己的网站餐饮营销策划与运营
  • 大学做视频网站如何自己做网络推广
  • 如何维护企业电子商务网站建设郑州做网络优化的公司
  • 外贸服饰网站建设福建百度代理公司
  • 自己服务器做网站服务器备案seo企业培训班
  • wordpress 相互关注搜狗搜索引擎优化指南
  • 建设网站主要有哪些技术网络营销讲师
  • 建设银行个人手机银行下载快抖霸屏乐云seo
  • 网站 建设 业务需求表杭州网络优化公司排名
  • 房地产开发公司网站建设方案郑州千锋教育培训机构怎么样
  • 微信公众号平台登录入口新网站seo