查阅资料得知,加密和未加密的文件,便是在头部数据中stbl下新增加了3个box。
senc:sample specific encryption data,特定加密数据样本。saio:sample auxiliary information offsets,样本赞助信息偏移量。saiz:sample auxiliary information sizes,样本赞助信息大小。二、效果图bool FFmpegSave::initStream(){ AVDictionary options = NULL; QByteArray fileData = fileName.toUtf8(); const char url = fileData.data(); //既可以是保存到文件也可以是推流(对应格式要区分) const char format = "mp4"; if (videoIndexIn < 0 && audioCodecName == "mp3") { format = "mp3"; } if (fileName.startsWith("rtmp://")) { format = "flv"; } else if (fileName.startsWith("rtsp://")) { format = "rtsp"; av_dict_set(&options, "stimeout", "3000000", 0); av_dict_set(&options, "rtsp_transport", "tcp", 0); } else if (fileName.startsWith("udp://")) { format = "mpegts"; } //如果存在秘钥则启用加密 QByteArray cryptoKey = this->property("cryptoKey").toByteArray(); if (!cryptoKey.isEmpty()) { av_dict_set(&options, "encryption_scheme", "cenc-aes-ctr", 0); av_dict_set(&options, "encryption_key", cryptoKey.constData(), 0); av_dict_set(&options, "encryption_kid", cryptoKey.constData(), 0); } //开辟一个格式高下文用来处理视频流输出(末端url不填则rtsp推流失落败) int result = avformat_alloc_output_context2(&formatCtx, NULL, format, url); if (result < 0) { debug(result, "创建格式", ""); return false; } //创建输出视频流 if (!this->initVideoStream()) { goto end; } //创建输出音频流 if (!this->initAudioStream()) { goto end; } //打开输出文件 if (!(formatCtx->oformat->flags & AVFMT_NOFILE)) { result = avio_open(&formatCtx->pb, url, AVIO_FLAG_WRITE); if (result < 0) { debug(result, "打开输出", ""); goto end; } } //写入文件开始符 result = avformat_write_header(formatCtx, &options); if (result < 0) { debug(result, "写文件头", ""); goto end; } return true;end: //关闭开释并清理文件 this->close(); this->deleteFile(fileName); return false;}void FFmpegThread::initOption(){ //设置缓存大小(1080p可将值调大/现在很多摄像机是2k可能须要调大/一样平常2k是1080p的四倍) av_dict_set(&options, "buffer_size", "8192000", 0); //设置超时断开连接韶光(单位微秒/3000000表示3秒) av_dict_set(&options, "stimeout", "3000000", 0); //设置最大时延(单位微秒/1000000表示1秒) av_dict_set(&options, "max_delay", "1000000", 0); //自动开启线程数 av_dict_set(&options, "threads", "auto", 0); //通信协议采取tcp还是udp(udp优点是无连接/在网线拔掉往后十几秒钟重新插上还能连续吸收/缺陷是网络不好的情形下会丢包花屏) if (transport != "auto") { av_dict_set(&options, "rtsp_transport", transport.toUtf8().constData(), 0); } //开启无缓存(rtmp等视频流不建议开启) //av_dict_set(&options, "fflags", "nobuffer", 0); //av_dict_set(&options, "fflags", "discardcorrupt", 0); //有些视频网站根据这个头部过滤不让ffmpeg访问须要仿照成其他的 //av_dict_set(&options, "user_agent", "libmpv", 0); av_dict_set(&options, "user_agent", "Mozilla", 0); //增加rtp/sdp支持(后面创造不要加) if (videoUrl.endsWith(".sdp")) { //av_dict_set(&options, "protocol_whitelist", "file,rtp,udp", 0); } //设置分辨率帧率等参数 if (videoType == VideoType_Camera || videoType == VideoType_Desktop) { //设置分辨率 if (bufferSize != "0x0") { av_dict_set(&options, "video_size", bufferSize.toUtf8().constData(), 0); } //设置帧率 if (frameRate > 0) { av_dict_set(&options, "framerate", QString::number(frameRate).toUtf8().constData(), 0); } //设置坐标XY以及是否采集鼠标指针 if (videoType == VideoType_Desktop) { //av_dict_set(&options, "draw_mouse", "0", 0); //av_dict_set(&options, "show_region", "1", 0); int offsetX = this->property("offsetX").toInt(); int offsetY = this->property("offsetY").toInt();#ifdef Q_OS_WIN //windows上通过设置offset_x/offset_y来设置偏移值 av_dict_set(&options, "offset_x", QString::number(offsetX).toUtf8().constData(), 0); av_dict_set(&options, "offset_y", QString::number(offsetY).toUtf8().constData(), 0);#else //linux系统通过设备名称带上偏移值传入 videoUrl += QString("+%1,%2").arg(offsetX).arg(offsetY);#endif } //设置输入格式(详细要看设置是否支持) //后面改成了统一转成标准yuv420以是不用设置也没有任何影响 //av_dict_set(&options, "input_format", "mjpeg", 0); } //如果设置了秘钥则须要启用解密 if (!secretKey.isEmpty()) { QByteArray cryptoKey = this->property("cryptoKey").toByteArray(); av_dict_set(&options, "decryption_key", cryptoKey.constData(), 0); }}
