GStreamer中aesenc/aesdec写入文件后解密播放失败问题求助
GStreamer AES加密视频后写入文件无法播放的问题
问题现象
- 单管道加密+解密播放可正常执行:
gst-launch-1.0 filesrc location=test-plain.mp4 ! aesenc key=1f9423681beb9a79215820f6bda73d0f iv=e9aa8e834d8d70b7e0d254ff670dd718 ! aesdec key=1f9423681beb9a79215820f6bda73d0f iv=e9aa8e834d8d70b7e0d254ff670dd718 ! queue ! decodebin ! autovideosink
- 分两步操作(加密写入文件→读取解密播放)时失败:
加密命令:
gst-launch-1.0 filesrc location=test-plain.mp4 ! aesenc key=1f9423681beb9a79215820f6bda73d0f iv=e9aa8e834d8d70b7e0d254ff670dd718 ! filesink location=test.enc
播放命令:
gst-launch-1.0 filesrc location=test.enc ! aesdec key=1f9423681beb9a79215820f6bda73d0f iv=e9aa8e834d8d70b7e0d254ff670dd718 ! queue ! decodebin ! autovideosink
触发错误:
ERROR: from element /GstPipeline:pipeline0/GstAesDec:aesdec0: Corrupt cipher text. Additional debug info: ../ext/aes/gstaesdec.c(494): gst_aes_dec_transform (): /GstPipeline:pipeline0/GstAesDec:aesdec0: Illegal PKCS7 padding value 183 ERROR: pipeline doesn't want to preroll. Setting pipeline to NULL ... ERROR: from element /GstPipeline:pipeline0/GstFileSrc:filesrc0: Internal data stream error. Additional debug info: ../libs/gst/base/gstbasesrc.c(3127): gst_base_src_loop (): /GstPipeline:pipeline0/GstFileSrc:filesrc0: streaming stopped, reason error (-5) ERROR: pipeline doesn't want to preroll. ERROR: from element /GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind: Stream doesn't contain enough data. Additional debug info: ../plugins/elements/gsttypefindelement.c(1014): gst_type_find_element_chain_do_typefinding (): /GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind: Can't typefind stream
- 添加
per-buffer-padding=false参数后,播放仍失败,但解密后写入文件可正常播放:
播放命令:
gst-launch-1.0 -v filesrc location=test-aes-pbp-off.enc ! aesdec key=1f9423681beb9a79215820f6bda73d0f iv=e9aa8e834d8d70b7e0d254ff670dd718 per-buffer-padding=false ! decodebin ! autovideosink
错误信息:
Setting pipeline to PAUSED ... Pipeline is PREROLLING ... /GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind.GstPad:src: caps = video/mpeg, systemstream=(boolean)false, mpegversion=(int)4, parsed=(boolean)false /GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind.GstPad:src: caps = NULL ERROR: from element /GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstMpeg4VParse:mpeg4vparse0: No valid frames found before end of stream Additional debug info: ../libs/gst/base/gstbaseparse.c(3673): gst_base_parse_loop (): /GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstMpeg4VParse:mpeg4vparse0
原因分析
- 默认
aesenc会给每个GstBuffer添加PKCS7填充,保证数据长度符合AES的16字节块大小。但加密数据写入文件后,原buffer的边界信息丢失,解密时会把填充数据当成视频流的一部分,导致解密后数据损坏,触发填充校验错误。 - 关闭
per-buffer-padding后,虽然没有额外填充,但decodebin预滚阶段需要足够初始数据识别流格式。直接播放时,解密后的流缺少MP4容器的元数据,或数据块不完整,导致解析器找不到有效帧;而写入文件后再播放,文件保留了完整流结构,就能正常识别。
解决方案
方案1:明确指定流格式+关闭按buffer填充
加密时先解封装MP4,提取视频流后加密,同时关闭按buffer填充:
gst-launch-1.0 filesrc location=test-plain.mp4 ! qtdemux ! h264parse ! capsfilter caps="video/x-h264, stream-format=(string)avc, alignment=(string)au" ! aesenc key=1f9423681beb9a79215820f6bda73d0f iv=e9aa8e834d8d70b7e0d254ff670dd718 per-buffer-padding=false ! filesink location=test-encrypted.h264
播放时同样关闭填充,并指定解密后的流格式,帮助decodebin识别:
gst-launch-1.0 filesrc location=test-encrypted.h264 ! aesdec key=1f9423681beb9a79215820f6bda73d0f iv=e9aa8e834d8d70b7e0d254ff670dd718 per-buffer-padding=false ! capsfilter caps="video/x-h264, stream-format=(string)avc, alignment=(string)au" ! h264parse ! avdec_h264 ! autovideosink
方案2:用容器封装加密后的流
将加密后的流重新封装进MP4容器,保留元数据信息:
加密命令:
gst-launch-1.0 filesrc location=test-plain.mp4 ! qtdemux name=d d.video_0 ! h264parse ! aesenc key=1f9423681beb9a79215820f6bda73d0f iv=e9aa8e834d8d70b7e0d254ff670dd718 per-buffer-padding=false ! mp4mux ! filesink location=test-encrypted.mp4
播放命令:
gst-launch-1.0 filesrc location=test-encrypted.mp4 ! qtdemux name=d d.video_0 ! aesdec key=1f9423681beb9a79215820f6bda73d0f iv=e9aa8e834d8d70b7e0d254ff670dd718 per-buffer-padding=false ! h264parse ! avdec_h264 ! autovideosink
方案3:使用GStreamer专用AES复用器/解复用器
用aesgstmux/aesgstdemux处理加密流,自动管理buffer边界和填充:
加密命令:
gst-launch-1.0 filesrc location=test-plain.mp4 ! qtdemux ! h264parse ! aesenc key=1f9423681beb9a79215820f6bda73d0f iv=e9aa8e834d8d70b7e0d254ff670dd718 ! aesgstmux ! filesink location=test-encrypted.gstaes
播放命令:
gst-launch-1.0 filesrc location=test-encrypted.gstaes ! aesgstdemux ! aesdec key=1f9423681beb9a79215820f6bda73d0f iv=e9aa8e834d8d70b7e0d254ff670dd718 ! h264parse ! avdec_h264 ! autovideosink
内容的提问来源于stack exchange,提问作者user2177594
相关产品推荐
相关产品推荐

