如何解决使用来自 libav (FFMPEG)
所以我的最终目标是拥有一个加密的 RTSP 流。 首先,我尝试对本地视频文件进行编码,然后使用 FFPLAY.exe 对其进行测试。我已经使用 FFMPEG(参考:FFmpeg: how to produce MP4 CENC (Common Encryption) videos)找到了用于此的测试命令,但是找不到使用 libav 实现此目的的单个示例:/
根据 libav 文档,AES 类下只有三种方法:av_aes_alloc、av_aes_init 和 av_aes_crypt。首先我想知道如何解决这个问题?如果有一种方法可以从 libav 中定义 key_id?
我目前加密 AVPacket-> 数据的方法似乎不起作用!
if ((ret = avformat_open_input(&ifmt_ctx,in_filename,0)) < 0) {
fprintf(stderr,"Could not open input file '%s'",in_filename);
return ResetParams();
}
if ((ret = avformat_find_stream_info(ifmt_ctx,"Failed to retrieve input stream information");
return ResetParams();
}
av_dump_format(ifmt_ctx,0);
avformat_alloc_output_context2(&ofmt_ctx,NULL,out_filename);
if (!ofmt_ctx) {
fprintf(stderr,"Could not create output context\n");
ret = AVERROR_UNKNowN;
return ResetParams();
}
stream_mapping_size = ifmt_ctx->nb_streams;
stream_mapping = new int(stream_mapping_size);
if (!stream_mapping) {
ret = AVERROR(ENOMEM);
return ResetParams();
}
ofmt = ofmt_ctx->oformat;
for (i = 0; i < ifmt_ctx->nb_streams; i++) {
AVStream* out_stream;
AVStream* in_stream = ifmt_ctx->streams[i];
AVCodecParameters* in_codecpar = in_stream->codecpar;
if (in_codecpar->codec_type != AVMEDIA_TYPE_AUdio &&
in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
in_codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
stream_mapping[i] = -1;
continue;
}
stream_mapping[i] = stream_index++;
out_stream = avformat_new_stream(ofmt_ctx,NULL);
if (!out_stream) {
fprintf(stderr,"Failed allocating output stream\n");
ret = AVERROR_UNKNowN;
return ResetParams();
}
ret = avcodec_parameters_copy(out_stream->codecpar,in_codecpar);
if (ret < 0) {
fprintf(stderr,"Failed to copy codec parameters\n");
return ResetParams();
}
out_stream->codecpar->codec_tag = 0;
}
av_dump_format(ofmt_ctx,out_filename,1);
if (!(ofmt->flags & AVFMT_NOFILE)) {
ret = avio_open(&ofmt_ctx->pb,AVIO_FLAG_WRITE);
if (ret < 0) {
fprintf(stderr,"Could not open output file '%s'",out_filename);
return ResetParams();
}
}
ret = avformat_write_header(ofmt_ctx,NULL);
if (ret < 0) {
fprintf(stderr,"Error occurred when opening output file\n");
return ResetParams();
}
while (1) {
AVStream* in_stream,* out_stream;
ret = av_read_frame(ifmt_ctx,&pkt);
if (ret < 0)
break;
in_stream = ifmt_ctx->streams[pkt.stream_index];
if (pkt.stream_index >= stream_mapping_size ||
stream_mapping[pkt.stream_index] < 0) {
av_packet_unref(&pkt);
continue;
}
pkt.stream_index = stream_mapping[pkt.stream_index];
out_stream = ofmt_ctx->streams[pkt.stream_index];
//log_packet(ifmt_ctx,&pkt,"in");
/* copy packet */
pkt.pts = av_rescale_q_rnd(pkt.pts,in_stream->time_base,out_stream->time_base,(AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
pkt.dts = av_rescale_q_rnd(pkt.dts,(AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
pkt.duration = av_rescale_q(pkt.duration,out_stream->time_base);
pkt.pos = -1;
//log_packet(ofmt_ctx,"out");
EncryptAVPacket(&pkt);
ret = av_interleaved_write_frame(ofmt_ctx,&pkt);
if (ret < 0) {
fprintf(stderr,"Error muxing packet\n");
break;
}
av_packet_unref(&pkt);
}
av_write_trailer(ofmt_ctx);
加密AVPacket方法如下:
void EncryptAVPacket(AVPacket* pkt)
{
int size = pkt->size;
int count = 0; //no of 16 byte blocks
if (size % 16 == 0)
count = size / 16;
else
{
av_grow_packet(pkt,size % 16);
size = pkt->size;
count = size / 16;
}
av_aes_crypt(avaes,pkt->data,count,(uint8_t*)iv,0);
}
虽然写入加密视频成功,但是ffplay无法播放文件。下面是 ffplay 控制台的快照。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。