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

保定网站建设电话上海关键词排名优化价格

保定网站建设电话,上海关键词排名优化价格,自己电脑做网站域名备案,建设网站怎么搞前言 MP4,是最常见的国际通用格式,在常见的播放软件中都可以使用和播放,磁盘空间占地小,画质一般清晰,它本身是支持h264、AAC的编码格式,对于其他编码的话,需要进行额外处理。本文提供了ffmpeg录…

前言

    MP4,是最常见的国际通用格式,在常见的播放软件中都可以使用和播放,磁盘空间占地小,画质一般清晰,它本身是支持h264、AAC的编码格式,对于其他编码的话,需要进行额外处理。本文提供了ffmpeg录制mp4的封装代码,经测试视频上它支持h264、h265编码,音频支持了AAC、G711的aLaw、muLaw编码。对于以上编码的支持,部分是需要修改ffmpeg的源码,本文也有提供已编译好的ffmpeg以及说明源码上需要修改的地方。

一、时间戳处理

    在mp4录制中,有碰到一个问题,即在录制实时流后,用播放器进行播放,播放时间没有从0秒开始。windows自带的media play播放时,一开始都是静止的画面,从第n秒后,才开始正式播放,用VLC可以直接跳到n秒进行播放。这个问题的原因是时间戳没有处理好,需要记录下首帧,指定首帧时间戳为0,然后后续视频帧的时间戳等于当前帧的时间戳减去首帧时间戳。代码如下:
在这里插入图片描述

二、添加h264、h265、AAC解码头信息

    解码头信息是保存在解码器上下文(AVCodecContext)的extradata中,这些信息包含h264的SPS、PPS头信息,AAC的adts头信息,h265的VPS、SPS、PPS,我们需要使用比特流过滤器(AVBitStreamFilter)来为每一种格式添加相应的头部信息,这样才能在解码器中正常进行解码。以下为添加解码头信息的相关代码:
    初始化时视频:
在这里插入图片描述
    循环读帧中,视频:
在这里插入图片描述
    初始化时音频:
在这里插入图片描述
    循环读帧中,音频:
在这里插入图片描述

三、ffmpeg支持g711 aLaw muLaw

在ffmpeg源码movenc.c文件中,找到mov_write_audio_tag函数,修改以下:
在这里插入图片描述
和在该文件中增加以下:
在这里插入图片描述
muLaw修改类似,它的MKTAG为 ‘u’,‘l’, ‘a’,‘w’。

四、代码分享

mp4recorder.h

#ifndef MP4RECORDER_H
#define MP4RECORDER_Hextern "C"
{#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavfilter/avfilter.h"#include "libswscale/swscale.h"#include "libavutil/frame.h"#include "libavutil/imgutils.h"#include "libavcodec/bsf.h"
}#include <QObject>
#include <QMutex>class mp4Recorder : public QObject
{Q_OBJECT
public:explicit mp4Recorder(QObject *parent = nullptr);virtual ~mp4Recorder();bool Init(AVFormatContext *pIfmtCtx, int nCodecType, int nAudioCodecType, QString& sFile);bool DeInit();bool isInit() {return m_bInit;}bool saveOneFrame(AVPacket& pkt, int nCodecType, int nAudioCodecType);private:uint64_t         m_nCounts;bool             m_bFirstGoP;bool             m_bInit;QString          m_sRecordFile;AVFormatContext *m_pIfmtCtx;AVFormatContext *m_pOfmtCtx; // output stream format. copy from instream format.const AVOutputFormat  *m_pOfmt; // save file format.QMutex           m_lock;int64_t          m_nVideoTimeStamp;int              m_nVideoDuration;int              m_nVideoIndex = -1;int              m_nAudioIndex = -1;int				 m_nSpsPpsSize = 0;AVBSFContext    *m_pBsfc = nullptr;AVBSFContext    *m_pBsfcAAC = nullptr;AVPacket        *m_pktFilter = nullptr;AVPacket        *m_pktFilterAudio = nullptr;int64_t         m_nFirstVideoPts = 0;int64_t         m_nFirstAudioPts = 0;bool            m_bTransCode = false;// stream map.int  *m_pStreamMapping;int   m_nMappingSize;};#endif // MP4RECORDER_H

mp4recorder.cpp

#include "mp4recorder.h"
#include "commondef.h"
#include "cteasyaacencoder.h"#define TRANSCODE 0mp4Recorder::mp4Recorder(QObject *parent) : QObject(parent)
{QMutexLocker guard(&m_lock);m_sRecordFile.clear();m_pIfmtCtx = nullptr;m_pOfmtCtx = nullptr;m_pOfmt = nullptr;m_pStreamMapping = nullptr;m_nMappingSize = 0;m_nCounts = 0;m_bFirstGoP = false;m_bInit = false;
}mp4Recorder::~mp4Recorder()
{DeInit();
}bool mp4Recorder::Init(AVFormatContext *pIfmtCtx, int nCodecType, int nAudioCodecType, QString &sFile)
{QMutexLocker guard(&m_lock);if(!pIfmtCtx || sFile.isEmpty()){MY_DEBUG << "sFile.isEmpty().";return false;}m_sRecordFile = sFile;m_pIfmtCtx = pIfmtCtx;QByteArray ba = m_sRecordFile.toLatin1();const char* pOutFile = ba.data();qDebug() << "pOutFile:" << pOutFile;unsigned i = 0;int ret = 0;int stream_index = 0;// 1. create output contextavformat_alloc_output_context2(&m_pOfmtCtx, nullptr, nullptr, pOutFile);if (!m_pOfmtCtx){MY_DEBUG << "Could not create output context.";ret = AVERROR_UNKNOWN;goto end;}// 2. get memory.m_nMappingSize = pIfmtCtx->nb_streams;m_pStreamMapping = (int*)av_mallocz_array(m_nMappingSize, sizeof(*m_pStreamMapping));if (!m_pStreamMapping){MY_DEBUG << "av_mallocz_array fail.";ret = AVERROR(ENOMEM);goto end;}// 3. copy steam information.m_pOfmt = m_pOfmtCtx->oformat;for (i = 0; i < pIfmtCtx->nb_streams; i++){AVStream *pOutStream;AVStream *pInStream = pIfmtCtx->streams[i];AVCodecParameters *pInCodecpar = pInStream->codecpar;if (pInCodecpar->codec_type != AVMEDIA_TYPE_AUDIO &&pInCodecpar->codec_type != AVMEDIA_TYPE_VIDEO &&pInCodecpar->codec_type != AVMEDIA_TYPE_SUBTITLE){m_pStreamMapping[i] = -1;continue;}if(pInCodecpar->codec_type == AVMEDIA_TYPE_VIDEO){m_nVideoIndex = i;//1.找到相应解码器的过滤器if(nCodecType == AV_CODEC_ID_HEVC){const AVBitStreamFilter *bsf = av_bsf_get_by_name("hevc_mp4toannexb");if (!bsf){MY_DEBUG << "av_bsf_get_by_name() video failed";return false;}//2.过滤器分配内存av_bsf_alloc(bsf, &m_pBsfc);}else{const AVBitStreamFilter *bsf = av_bsf_get_by_name("h264_mp4toannexb");if (!bsf){MY_DEBUG << "av_bsf_get_by_name() video failed";return false;}//2.过滤器分配内存av_bsf_alloc(bsf, &m_pBsfc);}//3.添加解码器属性avcodec_parameters_copy(m_pBsfc->par_in, pInCodecpar);//4. 初始化过滤器上下文av_bsf_init(m_pBsfc);}else if(pInCodecpar->codec_type == AVMEDIA_TYPE_AUDIO){m_nAudioIndex = i;#if TRANSCODEif(nAudioCodecType == AV_CODEC_ID_PCM_ALAW || nAudioCodecType == AV_CODEC_ID_PCM_MULAW){MY_DEBUG << "ctEasyAACEncoder Init";if(nAudioCodecType == AV_CODEC_ID_PCM_ALAW)ctEasyAACEncoder::getInstance().Init(Law_ALaw);elsectEasyAACEncoder::getInstance().Init(Law_ULaw);m_bTransCode = true;}elsem_bTransCode = false;#endifif(m_bTransCode || nAudioCodecType == AV_CODEC_ID_AAC){//1. 找到相应解码器的过滤器const AVBitStreamFilter *bsf = av_bsf_get_by_name("aac_adtstoasc");if (!bsf){MY_DEBUG << "av_bsf_get_by_name() audio failed";return false;}//2.过滤器分配内存av_bsf_alloc(bsf, &m_pBsfcAAC);//3.添加解码器属性avcodec_parameters_copy(m_pBsfcAAC->par_in, pInCodecpar);//4. 初始化过滤器上下文av_bsf_init(m_pBsfcAAC);}#if TRANSCODEif(m_bTransCode)m_pBsfcAAC->par_in->codec_id = AV_CODEC_ID_AAC;
#endif}// fill the stream index.m_pStreamMapping[i] = stream_index++;// copy the new codec prameters.pOutStream = avformat_new_stream(m_pOfmtCtx, nullptr);if (!pOutStream){MY_DEBUG << "Failed allocating output stream";ret = AVERROR_UNKNOWN;goto end;}ret = avcodec_parameters_copy(pOutStream->codecpar, pInCodecpar);if (ret < 0){MY_DEBUG << "Failed to copy codec parameters";goto end;}
#if TRANSCODEif(m_bTransCode && pInCodecpar->codec_type == AVMEDIA_TYPE_AUDIO)pOutStream->codecpar->codec_id = AV_CODEC_ID_AAC;
#endif//pOutStream->codecpar->bit_rate = 2000000;//pOutStream->codecpar->codec_tag = 0;}// 4. create MP4 header.if (!(m_pOfmt->flags & AVFMT_NOFILE)) // network stream{ret = avio_open(&m_pOfmtCtx->pb, pOutFile, AVIO_FLAG_WRITE);if (ret < 0){MY_DEBUG << "Could not open output file " << m_sRecordFile;goto end;}}// 5. write file header.ret = avformat_write_header(m_pOfmtCtx, nullptr);if (ret < 0){MY_DEBUG << "Error occurred when opening output file ret:" << ret;goto end;}m_pktFilter = new AVPacket;av_init_packet(m_pktFilter);m_pktFilter->data = NULL;m_pktFilter->size = 0;m_pktFilterAudio = new AVPacket;av_init_packet(m_pktFilterAudio);m_pktFilterAudio->data = NULL;m_pktFilterAudio->size = 0;m_nFirstVideoPts = 0;m_nFirstAudioPts = 0;m_bFirstGoP = false;m_bInit = true;m_nCounts = 0;return true;end:DeInit();if (ret < 0 && ret != AVERROR_EOF){MY_DEBUG << "Error occurred.";}return false;
}bool mp4Recorder::DeInit()
{// 1. save tail.if(m_bInit && m_pOfmtCtx){av_write_trailer(m_pOfmtCtx);}m_bInit = false;// 2. close outputif (m_pOfmtCtx && !(m_pOfmt->flags & AVFMT_NOFILE)){avio_closep(&m_pOfmtCtx->pb);}// 3. free contex.if(m_pOfmtCtx){avformat_free_context(m_pOfmtCtx);m_pOfmtCtx = nullptr;}av_freep(&m_pStreamMapping);if(m_pBsfc){av_bsf_free(&m_pBsfc);m_pBsfc = nullptr;}if(m_pBsfcAAC){av_bsf_free(&m_pBsfcAAC);m_pBsfcAAC = nullptr;}#if TRANSCODEif(m_bTransCode){ctEasyAACEncoder::getInstance().DeInit();m_bTransCode = false;}
#endifreturn true;
}bool mp4Recorder::saveOneFrame(AVPacket &pkt, int nCodecType, int nAudioCodecType)
{int ret = 0;if(!m_bInit){return false;}AVStream *pInStream, *pOutStream;if(nCodecType == AV_CODEC_ID_H264){if(m_bFirstGoP == false){if(pkt.flags != AV_PKT_FLAG_KEY){av_packet_unref(&pkt);return false; // first frame must be Iframe.}else{m_bFirstGoP = true;}}}pInStream  = m_pIfmtCtx->streams[pkt.stream_index];if (pkt.stream_index >= m_nMappingSize ||m_pStreamMapping[pkt.stream_index] < 0){av_packet_unref(&pkt);return true;}pkt.stream_index = m_pStreamMapping[pkt.stream_index];pOutStream = m_pOfmtCtx->streams[pkt.stream_index];if(pInStream->codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&pInStream->codecpar->codec_type != AVMEDIA_TYPE_AUDIO){av_packet_unref(&pkt);return false;}if(pInStream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){av_bsf_send_packet(m_pBsfc, &pkt);av_bsf_receive_packet(m_pBsfc, m_pktFilter);m_pktFilter->pts = av_rescale_q_rnd(m_pktFilter->pts, pInStream->time_base, pOutStream->time_base, AV_ROUND_NEAR_INF);m_pktFilter->dts = av_rescale_q_rnd(m_pktFilter->dts, pInStream->time_base, pOutStream->time_base, AV_ROUND_NEAR_INF);m_pktFilter->duration = av_rescale_q_rnd(m_pktFilter->duration, pInStream->time_base, pOutStream->time_base, AV_ROUND_NEAR_INF);m_pktFilter->stream_index = pOutStream->index;//时间戳处理if(m_nFirstVideoPts == 0){m_nFirstVideoPts = m_pktFilter->pts;m_pktFilter->pts = 0;m_pktFilter->dts = 0;}else{m_pktFilter->pts = m_pktFilter->pts - m_nFirstVideoPts;m_pktFilter->dts = m_pktFilter->dts - m_nFirstVideoPts;}//av_packet_rescale_ts(&pkt, pInStream->time_base, pOutStream->time_base);m_pktFilter->pos = -1;m_pktFilter->flags |= AV_PKT_FLAG_KEY;ret = av_interleaved_write_frame(m_pOfmtCtx, m_pktFilter);av_packet_unref(&pkt);if (ret < 0){qDebug() << "Video Error muxing packet";}}else{
#if TRANSCODEif(m_bTransCode){AVPacket* pAACPkt = av_packet_clone(&pkt);if(ctEasyAACEncoder::getInstance().G711ToAAC(pkt.data, pkt.size, pAACPkt->data, pAACPkt->size) == false){av_packet_unref(&pkt);return false;}av_bsf_send_packet(m_pBsfcAAC, pAACPkt);av_bsf_receive_packet(m_pBsfcAAC, m_pktFilterAudio);}else
#endifif(m_bTransCode || nAudioCodecType == AV_CODEC_ID_AAC){av_bsf_send_packet(m_pBsfcAAC, &pkt);av_bsf_receive_packet(m_pBsfcAAC, m_pktFilterAudio);m_pktFilterAudio->pts = av_rescale_q_rnd(m_pktFilterAudio->pts, pInStream->time_base, pOutStream->time_base, AV_ROUND_NEAR_INF);m_pktFilterAudio->dts = av_rescale_q_rnd(m_pktFilterAudio->dts, pInStream->time_base, pOutStream->time_base, AV_ROUND_NEAR_INF);m_pktFilterAudio->duration = av_rescale_q_rnd(m_pktFilterAudio->duration, pInStream->time_base, pOutStream->time_base, AV_ROUND_NEAR_INF);m_pktFilterAudio->stream_index = pOutStream->index;//用差值作时间戳if(m_nFirstAudioPts == 0){m_nFirstAudioPts = m_pktFilterAudio->pts;m_pktFilterAudio->pts = 0;m_pktFilterAudio->dts = 0;}else{m_pktFilterAudio->pts = m_pktFilterAudio->pts - m_nFirstAudioPts;m_pktFilterAudio->dts = m_pktFilterAudio->dts - m_nFirstAudioPts;}m_pktFilterAudio->pos = -1;m_pktFilterAudio->flags |= AV_PKT_FLAG_KEY;ret = av_interleaved_write_frame(m_pOfmtCtx, m_pktFilterAudio);}else{pkt.pts = av_rescale_q_rnd(pkt.pts, pInStream->time_base, pOutStream->time_base, AV_ROUND_NEAR_INF);pkt.dts = av_rescale_q_rnd(pkt.dts, pInStream->time_base, pOutStream->time_base, AV_ROUND_NEAR_INF);pkt.duration = av_rescale_q_rnd(pkt.duration, pInStream->time_base, pOutStream->time_base, AV_ROUND_NEAR_INF);pkt.stream_index = pOutStream->index;//用差值作时间戳if(m_nFirstAudioPts == 0){m_nFirstAudioPts = pkt.pts;pkt.pts = 0;pkt.dts = 0;}else{pkt.pts = pkt.pts - m_nFirstAudioPts;pkt.dts = pkt.dts - m_nFirstAudioPts;}pkt.pos = -1;pkt.flags |= AV_PKT_FLAG_KEY;ret = av_interleaved_write_frame(m_pOfmtCtx, &pkt);}av_packet_unref(&pkt);if (ret < 0){qDebug() << "Audio Error muxing packet";}}return (ret == 0);
}

四、ffmpeg库下载

链接地址:https://download.csdn.net/download/linyibin_123/87542123


文章转载自:
http://subception.cwgn.cn
http://glaciated.cwgn.cn
http://anoopsia.cwgn.cn
http://ludicrously.cwgn.cn
http://plethysmogram.cwgn.cn
http://fibbery.cwgn.cn
http://loll.cwgn.cn
http://inchoate.cwgn.cn
http://nosiness.cwgn.cn
http://nonskidding.cwgn.cn
http://juratory.cwgn.cn
http://dismast.cwgn.cn
http://torchlight.cwgn.cn
http://polemically.cwgn.cn
http://ovation.cwgn.cn
http://agrotechnical.cwgn.cn
http://monostich.cwgn.cn
http://flavorful.cwgn.cn
http://antique.cwgn.cn
http://polyglottism.cwgn.cn
http://gumming.cwgn.cn
http://entotic.cwgn.cn
http://aphoristic.cwgn.cn
http://caramelization.cwgn.cn
http://repudiation.cwgn.cn
http://sisal.cwgn.cn
http://zakiya.cwgn.cn
http://editorialist.cwgn.cn
http://lachrymose.cwgn.cn
http://antiferroelectricity.cwgn.cn
http://assam.cwgn.cn
http://perjure.cwgn.cn
http://unshaved.cwgn.cn
http://birdbath.cwgn.cn
http://hilly.cwgn.cn
http://humble.cwgn.cn
http://kleptocracy.cwgn.cn
http://savorily.cwgn.cn
http://agglomerant.cwgn.cn
http://lymphocytic.cwgn.cn
http://chryseis.cwgn.cn
http://unbesought.cwgn.cn
http://flog.cwgn.cn
http://saving.cwgn.cn
http://monogram.cwgn.cn
http://excrescent.cwgn.cn
http://firn.cwgn.cn
http://algometer.cwgn.cn
http://cryohydrate.cwgn.cn
http://morassy.cwgn.cn
http://liveliness.cwgn.cn
http://headword.cwgn.cn
http://sociocultural.cwgn.cn
http://ireful.cwgn.cn
http://lily.cwgn.cn
http://lossless.cwgn.cn
http://dudishly.cwgn.cn
http://neologism.cwgn.cn
http://umbilicular.cwgn.cn
http://corvina.cwgn.cn
http://sarah.cwgn.cn
http://boskop.cwgn.cn
http://flexility.cwgn.cn
http://touse.cwgn.cn
http://lacrimose.cwgn.cn
http://highlighted.cwgn.cn
http://cisterna.cwgn.cn
http://sadic.cwgn.cn
http://karaism.cwgn.cn
http://mobbism.cwgn.cn
http://norse.cwgn.cn
http://ryan.cwgn.cn
http://dyestuff.cwgn.cn
http://wiseacre.cwgn.cn
http://foretopgallant.cwgn.cn
http://nothing.cwgn.cn
http://mobbish.cwgn.cn
http://quirky.cwgn.cn
http://frounce.cwgn.cn
http://saleratus.cwgn.cn
http://plight.cwgn.cn
http://winceyette.cwgn.cn
http://dispensable.cwgn.cn
http://nimbus.cwgn.cn
http://wram.cwgn.cn
http://proproctor.cwgn.cn
http://prosper.cwgn.cn
http://ecclesiarch.cwgn.cn
http://appraiser.cwgn.cn
http://frenchwoman.cwgn.cn
http://connexity.cwgn.cn
http://cynic.cwgn.cn
http://paramount.cwgn.cn
http://preinduction.cwgn.cn
http://exurb.cwgn.cn
http://galenical.cwgn.cn
http://arco.cwgn.cn
http://barker.cwgn.cn
http://fatshedera.cwgn.cn
http://pertussis.cwgn.cn
http://www.hrbkazy.com/news/66894.html

相关文章:

  • 得到app骗局广州网站优化服务
  • 电商类网站建设需要多少钱站长工具关键词
  • 怎么搭建国外网络郑州seo外包顾问热狗
  • 漳州市网站建设公司江苏seo哪家好
  • 写作的网站有哪些网站定制开发
  • 网站关键字分析柳州网站建设
  • 个人业务网站制作游戏推广渠道有哪些
  • 厦门网站建设小程序开发百度网盘官网登录入口
  • 中山市政府网站建设seo排名赚挂机
  • 网站架构的建设嵌入式培训机构哪家好
  • 购买高仿手表网站百度推广有效果吗
  • 公司建设网站多少钱需要留电话号码的广告
  • 中文电商网站模板天津seo网站推广
  • 中国大型网站新手销售怎么和客户交流
  • 速卖通网站怎么做推广重庆森林百度网盘
  • 网站建设技术分析爱站关键词挖掘软件
  • 贵阳网站建设费用怎么做链接推广产品
  • 移动网站开发面试题长沙网络营销顾问
  • 学院网站群建设方案网络营销推广的基本手段
  • 整站优化该怎么做经典软文案例50字
  • 排名轻松seo 网站最近七天的新闻大事
  • 中企动力制作的网站网络营销的策划流程
  • 肇庆百度网站推广seo查询官方网站
  • 手机网站单页面百度推广开户
  • 上海市建设市场管理信息平台网站加盟教育培训机构
  • 建设公司资质查询官网广州网站优化平台
  • 公司网站改版分析营销网站类型
  • 网站建设方案书 本案互联网运营自学课程
  • 西安高新网站制作做网站优化推广
  • 做饼的网站网络营销技巧培训班