|
|
@@ -1330,6 +1330,7 @@ static int update_frag_index(MOVContext *c, int64_t offset) |
|
|
|
frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE; |
|
|
|
frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE; |
|
|
|
frag_stream_info[i].index_entry = -1; |
|
|
|
frag_stream_info[i].encryption_index = NULL; |
|
|
|
} |
|
|
|
|
|
|
|
if (index < c->frag_index.nb_items) |
|
|
@@ -5761,57 +5762,250 @@ static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom) |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom) |
|
|
|
/** |
|
|
|
* Gets the current encryption info and associated current stream context. If |
|
|
|
* we are parsing a track fragment, this will return the specific encryption |
|
|
|
* info for this fragment; otherwise this will return the global encryption |
|
|
|
* info for the current stream. |
|
|
|
*/ |
|
|
|
static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc) |
|
|
|
{ |
|
|
|
MOVFragmentStreamInfo *frag_stream_info; |
|
|
|
AVStream *st; |
|
|
|
int i; |
|
|
|
|
|
|
|
frag_stream_info = get_current_frag_stream_info(&c->frag_index); |
|
|
|
if (frag_stream_info) { |
|
|
|
for (i = 0; i < c->fc->nb_streams; i++) { |
|
|
|
if (c->fc->streams[i]->id == frag_stream_info->id) { |
|
|
|
st = c->fc->streams[i]; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
if (i == c->fc->nb_streams) |
|
|
|
return 0; |
|
|
|
*sc = st->priv_data; |
|
|
|
|
|
|
|
if (!frag_stream_info->encryption_index) { |
|
|
|
frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index)); |
|
|
|
if (!frag_stream_info->encryption_index) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
} |
|
|
|
*encryption_index = frag_stream_info->encryption_index; |
|
|
|
return 1; |
|
|
|
} else { |
|
|
|
// No current track fragment, using stream level encryption info. |
|
|
|
|
|
|
|
if (c->fc->nb_streams < 1) |
|
|
|
return 0; |
|
|
|
st = c->fc->streams[c->fc->nb_streams - 1]; |
|
|
|
*sc = st->priv_data; |
|
|
|
|
|
|
|
if (!(*sc)->cenc.encryption_index) { |
|
|
|
(*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index)); |
|
|
|
if (!(*sc)->cenc.encryption_index) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
} |
|
|
|
|
|
|
|
*encryption_index = (*sc)->cenc.encryption_index; |
|
|
|
return 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples) |
|
|
|
{ |
|
|
|
int i; |
|
|
|
unsigned int subsample_count; |
|
|
|
AVSubsampleEncryptionInfo *subsamples; |
|
|
|
|
|
|
|
*sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample); |
|
|
|
if (!*sample) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
|
|
|
if (sc->cenc.per_sample_iv_size != 0) { |
|
|
|
if (avio_read(pb, (*sample)->iv, sc->cenc.per_sample_iv_size) != sc->cenc.per_sample_iv_size) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n"); |
|
|
|
av_encryption_info_free(*sample); |
|
|
|
*sample = NULL; |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (use_subsamples) { |
|
|
|
subsample_count = avio_rb16(pb); |
|
|
|
(*sample)->subsamples = av_mallocz_array(subsample_count, sizeof(*subsamples)); |
|
|
|
if (!(*sample)->subsamples) { |
|
|
|
av_encryption_info_free(*sample); |
|
|
|
*sample = NULL; |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
} |
|
|
|
|
|
|
|
for (i = 0; i < subsample_count && !pb->eof_reached; i++) { |
|
|
|
(*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb); |
|
|
|
(*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb); |
|
|
|
} |
|
|
|
|
|
|
|
if (pb->eof_reached) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n"); |
|
|
|
av_encryption_info_free(*sample); |
|
|
|
*sample = NULL; |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
(*sample)->subsample_count = subsample_count; |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom) |
|
|
|
{ |
|
|
|
AVEncryptionInfo **encrypted_samples; |
|
|
|
MOVEncryptionIndex *encryption_index; |
|
|
|
MOVStreamContext *sc; |
|
|
|
size_t auxiliary_info_size; |
|
|
|
int use_subsamples, ret; |
|
|
|
unsigned int sample_count, i, alloc_size = 0; |
|
|
|
|
|
|
|
if (c->decryption_key_len == 0 || c->fc->nb_streams < 1) |
|
|
|
ret = get_current_encryption_info(c, &encryption_index, &sc); |
|
|
|
if (ret != 1) |
|
|
|
return ret; |
|
|
|
|
|
|
|
if (encryption_index->nb_encrypted_samples) { |
|
|
|
// This can happen if we have both saio/saiz and senc atoms. |
|
|
|
av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n"); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
st = c->fc->streams[c->fc->nb_streams - 1]; |
|
|
|
sc = st->priv_data; |
|
|
|
avio_r8(pb); /* version */ |
|
|
|
use_subsamples = avio_rb24(pb) & 0x02; /* flags */ |
|
|
|
|
|
|
|
if (sc->cenc.aes_ctr) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "duplicate senc atom\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
sample_count = avio_rb32(pb); |
|
|
|
if (sample_count >= INT_MAX / sizeof(*encrypted_samples)) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
|
|
|
for (i = 0; i < sample_count; i++) { |
|
|
|
unsigned int min_samples = FFMIN(FFMAX(i, 1024 * 1024), sample_count); |
|
|
|
encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size, |
|
|
|
min_samples * sizeof(*encrypted_samples)); |
|
|
|
if (encrypted_samples) { |
|
|
|
encryption_index->encrypted_samples = encrypted_samples; |
|
|
|
|
|
|
|
ret = mov_read_sample_encryption_info( |
|
|
|
c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples); |
|
|
|
} else { |
|
|
|
ret = AVERROR(ENOMEM); |
|
|
|
} |
|
|
|
if (pb->eof_reached) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n"); |
|
|
|
ret = AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
if (ret < 0) { |
|
|
|
for (; i > 0; i--) |
|
|
|
av_encryption_info_free(encryption_index->encrypted_samples[i - 1]); |
|
|
|
av_freep(&encryption_index->encrypted_samples); |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
encryption_index->nb_encrypted_samples = sample_count; |
|
|
|
|
|
|
|
avio_r8(pb); /* version */ |
|
|
|
sc->cenc.use_subsamples = avio_rb24(pb) & 0x02; /* flags */ |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
avio_rb32(pb); /* entries */ |
|
|
|
static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom) |
|
|
|
{ |
|
|
|
AVStream *st; |
|
|
|
MOVStreamContext *sc; |
|
|
|
|
|
|
|
if (atom.size < 8 || atom.size > FFMIN(INT_MAX, SIZE_MAX)) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "senc atom size %"PRId64" invalid\n", atom.size); |
|
|
|
if (c->fc->nb_streams < 1) |
|
|
|
return 0; |
|
|
|
st = c->fc->streams[c->fc->nb_streams-1]; |
|
|
|
sc = st->priv_data; |
|
|
|
|
|
|
|
if (sc->pseudo_stream_id != 0) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n"); |
|
|
|
return AVERROR_PATCHWELCOME; |
|
|
|
} |
|
|
|
|
|
|
|
if (atom.size < 8) |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
|
|
|
avio_rb32(pb); /* version and flags */ |
|
|
|
|
|
|
|
if (!sc->cenc.default_encrypted_sample) { |
|
|
|
sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16); |
|
|
|
if (!sc->cenc.default_encrypted_sample) { |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* save the auxiliary info as is */ |
|
|
|
auxiliary_info_size = atom.size - 8; |
|
|
|
sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
sc->cenc.auxiliary_info = av_malloc(auxiliary_info_size); |
|
|
|
if (!sc->cenc.auxiliary_info) { |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom) |
|
|
|
{ |
|
|
|
AVStream *st; |
|
|
|
MOVStreamContext *sc; |
|
|
|
unsigned int version, pattern, is_protected, iv_size; |
|
|
|
|
|
|
|
if (c->fc->nb_streams < 1) |
|
|
|
return 0; |
|
|
|
st = c->fc->streams[c->fc->nb_streams-1]; |
|
|
|
sc = st->priv_data; |
|
|
|
|
|
|
|
if (sc->pseudo_stream_id != 0) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n"); |
|
|
|
return AVERROR_PATCHWELCOME; |
|
|
|
} |
|
|
|
|
|
|
|
sc->cenc.auxiliary_info_end = sc->cenc.auxiliary_info + auxiliary_info_size; |
|
|
|
sc->cenc.auxiliary_info_pos = sc->cenc.auxiliary_info; |
|
|
|
sc->cenc.auxiliary_info_index = 0; |
|
|
|
if (!sc->cenc.default_encrypted_sample) { |
|
|
|
sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16); |
|
|
|
if (!sc->cenc.default_encrypted_sample) { |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (avio_read(pb, sc->cenc.auxiliary_info, auxiliary_info_size) != auxiliary_info_size) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "failed to read the auxiliary info"); |
|
|
|
if (atom.size < 20) |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
|
|
|
version = avio_r8(pb); /* version */ |
|
|
|
avio_rb24(pb); /* flags */ |
|
|
|
|
|
|
|
avio_r8(pb); /* reserved */ |
|
|
|
pattern = avio_r8(pb); |
|
|
|
|
|
|
|
if (version > 0) { |
|
|
|
sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4; |
|
|
|
sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf; |
|
|
|
} |
|
|
|
|
|
|
|
/* initialize the cipher */ |
|
|
|
sc->cenc.aes_ctr = av_aes_ctr_alloc(); |
|
|
|
if (!sc->cenc.aes_ctr) { |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
is_protected = avio_r8(pb); |
|
|
|
if (is_protected && !sc->cenc.encryption_index) { |
|
|
|
// The whole stream should be by-default encrypted. |
|
|
|
sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex)); |
|
|
|
if (!sc->cenc.encryption_index) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
} |
|
|
|
sc->cenc.per_sample_iv_size = avio_r8(pb); |
|
|
|
if (avio_read(pb, sc->cenc.default_encrypted_sample->key_id, 16) != 16) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
return av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key); |
|
|
|
if (is_protected && !sc->cenc.per_sample_iv_size) { |
|
|
|
iv_size = avio_r8(pb); |
|
|
|
if (iv_size != 8 && iv_size != 16) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
if (avio_read(pb, sc->cenc.default_encrypted_sample->iv, iv_size) != iv_size) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom) |
|
|
@@ -5942,78 +6136,103 @@ static int mov_seek_auxiliary_info(MOVContext *c, MOVStreamContext *sc, int64_t |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int cenc_filter(MOVContext *c, MOVStreamContext *sc, int64_t index, uint8_t *input, int size) |
|
|
|
static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size) |
|
|
|
{ |
|
|
|
uint32_t encrypted_bytes; |
|
|
|
uint16_t subsample_count; |
|
|
|
uint16_t clear_bytes; |
|
|
|
uint8_t* input_end = input + size; |
|
|
|
int ret; |
|
|
|
int i, ret; |
|
|
|
|
|
|
|
if (index != sc->cenc.auxiliary_info_index) { |
|
|
|
ret = mov_seek_auxiliary_info(c, sc, index); |
|
|
|
if (sample->scheme != MKBETAG('c','e','n','c') || sample->crypt_byte_block != 0 || sample->skip_byte_block != 0) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "Only the 'cenc' encryption scheme is supported\n"); |
|
|
|
return AVERROR_PATCHWELCOME; |
|
|
|
} |
|
|
|
|
|
|
|
if (!sc->cenc.aes_ctr) { |
|
|
|
/* initialize the cipher */ |
|
|
|
sc->cenc.aes_ctr = av_aes_ctr_alloc(); |
|
|
|
if (!sc->cenc.aes_ctr) { |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
} |
|
|
|
|
|
|
|
ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key); |
|
|
|
if (ret < 0) { |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* read the iv */ |
|
|
|
if (AES_CTR_IV_SIZE > sc->cenc.auxiliary_info_end - sc->cenc.auxiliary_info_pos) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "failed to read iv from the auxiliary info\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
av_aes_ctr_set_iv(sc->cenc.aes_ctr, sc->cenc.auxiliary_info_pos); |
|
|
|
sc->cenc.auxiliary_info_pos += AES_CTR_IV_SIZE; |
|
|
|
av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv); |
|
|
|
|
|
|
|
if (!sc->cenc.use_subsamples) |
|
|
|
if (!sample->subsample_count) |
|
|
|
{ |
|
|
|
/* decrypt the whole packet */ |
|
|
|
av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* read the subsample count */ |
|
|
|
if (sizeof(uint16_t) > sc->cenc.auxiliary_info_end - sc->cenc.auxiliary_info_pos) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "failed to read subsample count from the auxiliary info\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
subsample_count = AV_RB16(sc->cenc.auxiliary_info_pos); |
|
|
|
sc->cenc.auxiliary_info_pos += sizeof(uint16_t); |
|
|
|
|
|
|
|
for (; subsample_count > 0; subsample_count--) |
|
|
|
for (i = 0; i < sample->subsample_count; i++) |
|
|
|
{ |
|
|
|
if (6 > sc->cenc.auxiliary_info_end - sc->cenc.auxiliary_info_pos) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "failed to read subsample from the auxiliary info\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
/* read the number of clear / encrypted bytes */ |
|
|
|
clear_bytes = AV_RB16(sc->cenc.auxiliary_info_pos); |
|
|
|
sc->cenc.auxiliary_info_pos += sizeof(uint16_t); |
|
|
|
encrypted_bytes = AV_RB32(sc->cenc.auxiliary_info_pos); |
|
|
|
sc->cenc.auxiliary_info_pos += sizeof(uint32_t); |
|
|
|
|
|
|
|
if ((uint64_t)clear_bytes + encrypted_bytes > input_end - input) { |
|
|
|
if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
/* skip the clear bytes */ |
|
|
|
input += clear_bytes; |
|
|
|
input += sample->subsamples[i].bytes_of_clear_data; |
|
|
|
size -= sample->subsamples[i].bytes_of_clear_data; |
|
|
|
|
|
|
|
/* decrypt the encrypted bytes */ |
|
|
|
av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, encrypted_bytes); |
|
|
|
input += encrypted_bytes; |
|
|
|
av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, sample->subsamples[i].bytes_of_protected_data); |
|
|
|
input += sample->subsamples[i].bytes_of_protected_data; |
|
|
|
size -= sample->subsamples[i].bytes_of_protected_data; |
|
|
|
} |
|
|
|
|
|
|
|
if (input < input_end) { |
|
|
|
if (size > 0) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
sc->cenc.auxiliary_info_index++; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int cenc_filter(MOVContext *mov, MOVStreamContext *sc, AVPacket *pkt, int current_index) |
|
|
|
{ |
|
|
|
MOVFragmentStreamInfo *frag_stream_info; |
|
|
|
MOVEncryptionIndex *encryption_index; |
|
|
|
AVEncryptionInfo *encrypted_sample; |
|
|
|
int encrypted_index; |
|
|
|
|
|
|
|
frag_stream_info = get_current_frag_stream_info(&mov->frag_index); |
|
|
|
encrypted_index = current_index; |
|
|
|
encryption_index = NULL; |
|
|
|
if (frag_stream_info) { |
|
|
|
// Note this only supports encryption info in the first sample descriptor. |
|
|
|
if (mov->fragment.stsd_id == 1) { |
|
|
|
if (frag_stream_info->encryption_index) { |
|
|
|
encrypted_index = current_index - frag_stream_info->index_entry; |
|
|
|
encryption_index = frag_stream_info->encryption_index; |
|
|
|
} else { |
|
|
|
encryption_index = sc->cenc.encryption_index; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
encryption_index = sc->cenc.encryption_index; |
|
|
|
} |
|
|
|
|
|
|
|
if (encryption_index) { |
|
|
|
if (!encryption_index->nb_encrypted_samples) { |
|
|
|
// Full-sample encryption with default settings. |
|
|
|
encrypted_sample = sc->cenc.default_encrypted_sample; |
|
|
|
} else if (encrypted_index >= 0 && encrypted_index < encryption_index->nb_encrypted_samples) { |
|
|
|
// Per-sample setting override. |
|
|
|
encrypted_sample = encryption_index->encrypted_samples[encrypted_index]; |
|
|
|
} else { |
|
|
|
av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
if (mov->decryption_key) { |
|
|
|
return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
@@ -6142,7 +6361,9 @@ static const MOVParseTableEntry mov_default_parse_table[] = { |
|
|
|
{ MKTAG('s','i','n','f'), mov_read_default }, |
|
|
|
{ MKTAG('f','r','m','a'), mov_read_frma }, |
|
|
|
{ MKTAG('s','e','n','c'), mov_read_senc }, |
|
|
|
{ MKTAG('s','a','i','z'), mov_read_saiz }, |
|
|
|
{ MKTAG('s','c','h','m'), mov_read_schm }, |
|
|
|
{ MKTAG('s','c','h','i'), mov_read_default }, |
|
|
|
{ MKTAG('t','e','n','c'), mov_read_tenc }, |
|
|
|
{ MKTAG('d','f','L','a'), mov_read_dfla }, |
|
|
|
{ MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */ |
|
|
|
{ MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */ |
|
|
@@ -6528,6 +6749,16 @@ static int mov_read_timecode_track(AVFormatContext *s, AVStream *st) |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static void mov_free_encryption_index(MOVEncryptionIndex **index) { |
|
|
|
int i; |
|
|
|
if (!index || !*index) return; |
|
|
|
for (i = 0; i < (*index)->nb_encrypted_samples; i++) { |
|
|
|
av_encryption_info_free((*index)->encrypted_samples[i]); |
|
|
|
} |
|
|
|
av_freep(&(*index)->encrypted_samples); |
|
|
|
av_freep(index); |
|
|
|
} |
|
|
|
|
|
|
|
static int mov_read_close(AVFormatContext *s) |
|
|
|
{ |
|
|
|
MOVContext *mov = s->priv_data; |
|
|
@@ -6570,8 +6801,8 @@ static int mov_read_close(AVFormatContext *s) |
|
|
|
av_freep(&sc->extradata); |
|
|
|
av_freep(&sc->extradata_size); |
|
|
|
|
|
|
|
av_freep(&sc->cenc.auxiliary_info); |
|
|
|
av_freep(&sc->cenc.auxiliary_info_sizes); |
|
|
|
mov_free_encryption_index(&sc->cenc.encryption_index); |
|
|
|
av_encryption_info_free(sc->cenc.default_encrypted_sample); |
|
|
|
av_aes_ctr_free(sc->cenc.aes_ctr); |
|
|
|
|
|
|
|
av_freep(&sc->stereo3d); |
|
|
@@ -6596,6 +6827,10 @@ static int mov_read_close(AVFormatContext *s) |
|
|
|
av_freep(&mov->bitrates); |
|
|
|
|
|
|
|
for (i = 0; i < mov->frag_index.nb_items; i++) { |
|
|
|
MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info; |
|
|
|
for (j = 0; j < mov->frag_index.item[i].nb_stream_info; j++) { |
|
|
|
mov_free_encryption_index(&frag[j].encryption_index); |
|
|
|
} |
|
|
|
av_freep(&mov->frag_index.item[i].stream_info); |
|
|
|
} |
|
|
|
av_freep(&mov->frag_index.item); |
|
|
@@ -7166,12 +7401,9 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) |
|
|
|
if (mov->aax_mode) |
|
|
|
aax_filter(pkt->data, pkt->size, mov); |
|
|
|
|
|
|
|
if (sc->cenc.aes_ctr) { |
|
|
|
ret = cenc_filter(mov, sc, current_index, pkt->data, pkt->size); |
|
|
|
if (ret) { |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
ret = cenc_filter(mov, sc, pkt, current_index); |
|
|
|
if (ret < 0) |
|
|
|
return ret; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|