commit f65aafb263bdbc2bbd89988a061302fbc28c7447
parent 44136a353df2ee2c3000f31e8f2ed56e34b5b919
Author: Andrew Osmond <aosmond@gmail.com>
Date: Tue, 25 Nov 2025 20:31:32 +0000
Bug 2001774 - Part 1. Patch ffvpx to better handle lifetimes for AMediaCodecCryptoInfo. r=media-playback-reviewers,azebrowski
Since ffmpeg can duplicate packets, we need to take advantage of our
refcounted wrapper for AMediaCodecCryptoInfo to release it when
appropriate. This will allow us to propogate the necessary pointers for
the decrypt/decode pipeline on Android.
Differential Revision: https://phabricator.services.mozilla.com/D273707
Diffstat:
3 files changed, 120 insertions(+), 2 deletions(-)
diff --git a/media/ffvpx/libavcodec/packet.c b/media/ffvpx/libavcodec/packet.c
@@ -390,6 +390,32 @@ int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
return AVERROR(ENOENT);
}
+static void av_packet_free_moz_crypto_info(AVPacket *pkt) {
+ if (pkt->moz_crypto_info_release && pkt->moz_crypto_info) {
+ (*pkt->moz_crypto_info_release)(pkt->moz_crypto_info);
+ }
+ pkt->moz_ndk_crypto_info = NULL;
+ pkt->moz_crypto_info = NULL;
+ pkt->moz_crypto_info_addref = NULL;
+ pkt->moz_crypto_info_release = NULL;
+}
+
+static int av_packet_copy_moz_crypto_info(AVPacket *dst, const AVPacket *src) {
+ av_packet_free_moz_crypto_info(dst);
+ if (!src->moz_ndk_crypto_info) {
+ return 0;
+ }
+ if (!src->moz_crypto_info || !src->moz_crypto_info_addref || !src->moz_crypto_info_release) {
+ return AVERROR(EINVAL);
+ }
+ dst->moz_ndk_crypto_info = src->moz_ndk_crypto_info;
+ dst->moz_crypto_info = src->moz_crypto_info;
+ dst->moz_crypto_info_addref = src->moz_crypto_info_addref;
+ dst->moz_crypto_info_release = src->moz_crypto_info_release;
+ (*dst->moz_crypto_info_addref)(dst->moz_crypto_info);
+ return 0;
+}
+
int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
{
int i, ret;
@@ -406,10 +432,16 @@ int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
dst->side_data = NULL;
dst->side_data_elems = 0;
- ret = av_buffer_replace(&dst->opaque_ref, src->opaque_ref);
+ ret = av_packet_copy_moz_crypto_info(dst, src);
if (ret < 0)
return ret;
+ ret = av_buffer_replace(&dst->opaque_ref, src->opaque_ref);
+ if (ret < 0) {
+ av_packet_free_moz_crypto_info(dst);
+ return ret;
+ }
+
for (i = 0; i < src->side_data_elems; i++) {
enum AVPacketSideDataType type = src->side_data[i].type;
size_t size = src->side_data[i].size;
@@ -417,6 +449,7 @@ int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
uint8_t *dst_data = av_packet_new_side_data(dst, type, size);
if (!dst_data) {
+ av_packet_free_moz_crypto_info(dst);
av_buffer_unref(&dst->opaque_ref);
av_packet_free_side_data(dst);
return AVERROR(ENOMEM);
@@ -429,6 +462,7 @@ int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
void av_packet_unref(AVPacket *pkt)
{
+ av_packet_free_moz_crypto_info(pkt);
av_packet_free_side_data(pkt);
av_buffer_unref(&pkt->opaque_ref);
av_buffer_unref(&pkt->buf);
diff --git a/media/ffvpx/libavcodec/packet.h b/media/ffvpx/libavcodec/packet.h
@@ -582,7 +582,14 @@ typedef struct AVPacket {
*/
AVRational time_base;
+ /**
+ * Mozilla extensions to manage AMediaCryptoInfo for encrypted packets on
+ * Android. Must provide all parameters if any are given.
+ */
void* moz_ndk_crypto_info;
+ void* moz_crypto_info;
+ void (*moz_crypto_info_addref)(void*);
+ void (*moz_crypto_info_release)(void*);
} AVPacket;
#if FF_API_INIT_PACKET
diff --git a/media/ffvpx/mediacodec_drm.patch b/media/ffvpx/mediacodec_drm.patch
@@ -126,15 +126,92 @@ diff --git a/media/ffvpx/libavcodec/mediacodecdec_common.c b/media/ffvpx/libavco
if (status < 0) {
av_log(avctx, AV_LOG_ERROR, "Failed to queue input buffer (status = %d)\n", status);
return AVERROR_EXTERNAL;
+diff --git a/media/ffvpx/libavcodec/packet.c b/media/ffvpx/libavcodec/packet.c
+--- a/media/ffvpx/libavcodec/packet.c
++++ b/media/ffvpx/libavcodec/packet.c
+@@ -390,6 +390,32 @@ int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
+ return AVERROR(ENOENT);
+ }
+
++static void av_packet_free_moz_crypto_info(AVPacket *pkt) {
++ if (pkt->moz_crypto_info_release && pkt->moz_crypto_info) {
++ (*pkt->moz_crypto_info_release)(pkt->moz_crypto_info);
++ }
++ pkt->moz_ndk_crypto_info = NULL;
++ pkt->moz_crypto_info = NULL;
++ pkt->moz_crypto_info_addref = NULL;
++ pkt->moz_crypto_info_release = NULL;
++}
++
++static int av_packet_copy_moz_crypto_info(AVPacket *dst, const AVPacket *src) {
++ av_packet_free_moz_crypto_info(dst);
++ if (!src->moz_ndk_crypto_info) {
++ return 0;
++ }
++ if (!src->moz_crypto_info || !src->moz_crypto_info_addref || !src->moz_crypto_info_release) {
++ return AVERROR(EINVAL);
++ }
++ dst->moz_ndk_crypto_info = src->moz_ndk_crypto_info;
++ dst->moz_crypto_info = src->moz_crypto_info;
++ dst->moz_crypto_info_addref = src->moz_crypto_info_addref;
++ dst->moz_crypto_info_release = src->moz_crypto_info_release;
++ (*dst->moz_crypto_info_addref)(dst->moz_crypto_info);
++ return 0;
++}
++
+ int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
+ {
+ int i, ret;
+@@ -406,10 +432,16 @@ int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
+ dst->side_data = NULL;
+ dst->side_data_elems = 0;
+
+- ret = av_buffer_replace(&dst->opaque_ref, src->opaque_ref);
++ ret = av_packet_copy_moz_crypto_info(dst, src);
+ if (ret < 0)
+ return ret;
+
++ ret = av_buffer_replace(&dst->opaque_ref, src->opaque_ref);
++ if (ret < 0) {
++ av_packet_free_moz_crypto_info(dst);
++ return ret;
++ }
++
+ for (i = 0; i < src->side_data_elems; i++) {
+ enum AVPacketSideDataType type = src->side_data[i].type;
+ size_t size = src->side_data[i].size;
+@@ -417,6 +449,7 @@ int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
+ uint8_t *dst_data = av_packet_new_side_data(dst, type, size);
+
+ if (!dst_data) {
++ av_packet_free_moz_crypto_info(dst);
+ av_buffer_unref(&dst->opaque_ref);
+ av_packet_free_side_data(dst);
+ return AVERROR(ENOMEM);
+@@ -429,6 +462,7 @@ int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
+
+ void av_packet_unref(AVPacket *pkt)
+ {
++ av_packet_free_moz_crypto_info(pkt);
+ av_packet_free_side_data(pkt);
+ av_buffer_unref(&pkt->opaque_ref);
+ av_buffer_unref(&pkt->buf);
diff --git a/media/ffvpx/libavcodec/packet.h b/media/ffvpx/libavcodec/packet.h
--- a/media/ffvpx/libavcodec/packet.h
+++ b/media/ffvpx/libavcodec/packet.h
-@@ -581,6 +581,8 @@ typedef struct AVPacket {
+@@ -581,6 +581,15 @@ typedef struct AVPacket {
* or muxers.
*/
AVRational time_base;
+
++ /**
++ * Mozilla extensions to manage AMediaCryptoInfo for encrypted packets on
++ * Android. Must provide all parameters if any are given.
++ */
+ void* moz_ndk_crypto_info;
++ void* moz_crypto_info;
++ void (*moz_crypto_info_addref)(void*);
++ void (*moz_crypto_info_release)(void*);
} AVPacket;
#if FF_API_INIT_PACKET