mirror of
https://gitee.com/openharmony/third_party_ffmpeg
synced 2024-11-24 03:39:45 +00:00
avformat/mov: Expose encryption info to the app.
This exposes encryption info from the container to the app. This includes key ID, IV, and subsample byte ranges. The info is passed using the new side-data AV_PKT_DATA_ENCRYPTION_DATA and AV_PKT_DATA_ENCRYPTION_INIT_DATA. Signed-off-by: Jacob Trimble <modmaker@google.com> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
parent
9fececb6f3
commit
7e22f5d457
@ -6198,6 +6198,114 @@ static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
||||
{
|
||||
AVEncryptionInitInfo *info, *old_init_info;
|
||||
uint8_t **key_ids;
|
||||
AVStream *st;
|
||||
uint8_t *side_data, *extra_data, *old_side_data;
|
||||
size_t side_data_size;
|
||||
int ret = 0, old_side_data_size;
|
||||
unsigned int version, kid_count, extra_data_size, alloc_size = 0;
|
||||
|
||||
if (c->fc->nb_streams < 1)
|
||||
return 0;
|
||||
st = c->fc->streams[c->fc->nb_streams-1];
|
||||
|
||||
version = avio_r8(pb); /* version */
|
||||
avio_rb24(pb); /* flags */
|
||||
|
||||
info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
|
||||
/* key_id_size */ 16, /* data_size */ 0);
|
||||
if (!info)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
if (avio_read(pb, info->system_id, 16) != 16) {
|
||||
av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (version > 0) {
|
||||
kid_count = avio_rb32(pb);
|
||||
if (kid_count >= INT_MAX / sizeof(*key_ids))
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
for (unsigned int i = 0; i < kid_count && !pb->eof_reached; i++) {
|
||||
unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
|
||||
key_ids = av_fast_realloc(info->key_ids, &alloc_size,
|
||||
min_kid_count * sizeof(*key_ids));
|
||||
if (!key_ids) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto finish;
|
||||
}
|
||||
info->key_ids = key_ids;
|
||||
|
||||
info->key_ids[i] = av_mallocz(16);
|
||||
if (!info->key_ids[i]) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto finish;
|
||||
}
|
||||
info->num_key_ids = i + 1;
|
||||
|
||||
if (avio_read(pb, info->key_ids[i], 16) != 16) {
|
||||
av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
if (pb->eof_reached) {
|
||||
av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
extra_data_size = avio_rb32(pb);
|
||||
ret = mov_try_read_block(pb, extra_data_size, &extra_data);
|
||||
if (ret < 0)
|
||||
goto finish;
|
||||
|
||||
av_freep(&info->data); // malloc(0) may still allocate something.
|
||||
info->data = extra_data;
|
||||
info->data_size = extra_data_size;
|
||||
|
||||
// If there is existing initialization data, append to the list.
|
||||
old_side_data = av_stream_get_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO, &old_side_data_size);
|
||||
if (old_side_data) {
|
||||
old_init_info = av_encryption_init_info_get_side_data(old_side_data, old_side_data_size);
|
||||
if (old_init_info) {
|
||||
// Append to the end of the list.
|
||||
for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
|
||||
if (!cur->next) {
|
||||
cur->next = info;
|
||||
break;
|
||||
}
|
||||
}
|
||||
info = old_init_info;
|
||||
} else {
|
||||
// Assume existing side-data will be valid, so the only error we could get is OOM.
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
|
||||
if (!side_data) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto finish;
|
||||
}
|
||||
ret = av_stream_add_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO,
|
||||
side_data, side_data_size);
|
||||
if (ret < 0)
|
||||
av_free(side_data);
|
||||
|
||||
finish:
|
||||
av_encryption_init_info_free(info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
||||
{
|
||||
AVStream *st;
|
||||
@ -6398,7 +6506,7 @@ static int cenc_filter(MOVContext *mov, MOVStreamContext *sc, AVPacket *pkt, int
|
||||
MOVFragmentStreamInfo *frag_stream_info;
|
||||
MOVEncryptionIndex *encryption_index;
|
||||
AVEncryptionInfo *encrypted_sample;
|
||||
int encrypted_index;
|
||||
int encrypted_index, ret;
|
||||
|
||||
frag_stream_info = get_current_frag_stream_info(&mov->frag_index);
|
||||
encrypted_index = current_index;
|
||||
@ -6442,6 +6550,15 @@ static int cenc_filter(MOVContext *mov, MOVStreamContext *sc, AVPacket *pkt, int
|
||||
|
||||
if (mov->decryption_key) {
|
||||
return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
|
||||
} else {
|
||||
size_t size;
|
||||
uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
|
||||
if (!side_data)
|
||||
return AVERROR(ENOMEM);
|
||||
ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
|
||||
if (ret < 0)
|
||||
av_free(side_data);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6575,6 +6692,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
|
||||
{ MKTAG('s','e','n','c'), mov_read_senc },
|
||||
{ MKTAG('s','a','i','z'), mov_read_saiz },
|
||||
{ MKTAG('s','a','i','o'), mov_read_saio },
|
||||
{ MKTAG('p','s','s','h'), mov_read_pssh },
|
||||
{ MKTAG('s','c','h','m'), mov_read_schm },
|
||||
{ MKTAG('s','c','h','i'), mov_read_default },
|
||||
{ MKTAG('t','e','n','c'), mov_read_tenc },
|
||||
|
Loading…
Reference in New Issue
Block a user