avformat/mov: Increase support for common encryption.

- Parse schm atom to get different encryption schemes.
- Allow senc atom to appear in track fragments.
- Allow 16-byte IVs.
- Allow constant IVs (specified in tenc).
- Allow only tenc to specify encryption (i.e. no senc/saiz/saio).
- Use sample descriptor to detect clear fragments.

This doesn't support:
- Different sample descriptor holding different encryption info.
  - Only first sample descriptor can be encrypted.
- Encrypted sample groups (i.e. seig).
- Non-'cenc' encryption scheme when using -decryption_key.

Signed-off-by: Jacob Trimble <modmaker@google.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
pull/298/head
Jacob Trimble 7 years ago committed by Michael Niedermayer
parent 3717512282
commit f7221d8e67
  1. 14
      libavformat/isom.h
  2. 394
      libavformat/mov.c
  3. 2
      libavutil/encryption_info.h
  4. 8
      tests/fate/mov.mak
  5. 57
      tests/ref/fate/mov-frag-encrypted
  6. 57
      tests/ref/fate/mov-tenc-only-encrypted

@ -27,6 +27,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "libavutil/encryption_info.h"
#include "libavutil/mastering_display_metadata.h" #include "libavutil/mastering_display_metadata.h"
#include "libavutil/spherical.h" #include "libavutil/spherical.h"
#include "libavutil/stereo3d.h" #include "libavutil/stereo3d.h"
@ -108,12 +109,20 @@ typedef struct MOVSbgp {
unsigned int index; unsigned int index;
} MOVSbgp; } MOVSbgp;
typedef struct MOVEncryptionIndex {
// Individual encrypted samples. If there are no elements, then the default
// settings will be used.
unsigned int nb_encrypted_samples;
AVEncryptionInfo **encrypted_samples;
} MOVEncryptionIndex;
typedef struct MOVFragmentStreamInfo { typedef struct MOVFragmentStreamInfo {
int id; int id;
int64_t sidx_pts; int64_t sidx_pts;
int64_t first_tfra_pts; int64_t first_tfra_pts;
int64_t tfdt_dts; int64_t tfdt_dts;
int index_entry; int index_entry;
MOVEncryptionIndex *encryption_index;
} MOVFragmentStreamInfo; } MOVFragmentStreamInfo;
typedef struct MOVFragmentIndexItem { typedef struct MOVFragmentIndexItem {
@ -215,6 +224,7 @@ typedef struct MOVStreamContext {
int has_sidx; // If there is an sidx entry for this stream. int has_sidx; // If there is an sidx entry for this stream.
struct { struct {
// TODO: Remove once old methods are removed from mov.c
int use_subsamples; int use_subsamples;
uint8_t* auxiliary_info; uint8_t* auxiliary_info;
uint8_t* auxiliary_info_end; uint8_t* auxiliary_info_end;
@ -223,7 +233,11 @@ typedef struct MOVStreamContext {
uint8_t* auxiliary_info_sizes; uint8_t* auxiliary_info_sizes;
size_t auxiliary_info_sizes_count; size_t auxiliary_info_sizes_count;
int64_t auxiliary_info_index; int64_t auxiliary_info_index;
struct AVAESCTR* aes_ctr; struct AVAESCTR* aes_ctr;
unsigned int per_sample_iv_size; // Either 0, 8, or 16.
AVEncryptionInfo *default_encrypted_sample;
MOVEncryptionIndex *encryption_index;
} cenc; } cenc;
} MOVStreamContext; } MOVStreamContext;

@ -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].tfdt_dts = AV_NOPTS_VALUE;
frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE; frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
frag_stream_info[i].index_entry = -1; frag_stream_info[i].index_entry = -1;
frag_stream_info[i].encryption_index = NULL;
} }
if (index < c->frag_index.nb_items) if (index < c->frag_index.nb_items)
@ -5761,57 +5762,250 @@ static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return 0; 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; 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; 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; return 0;
}
st = c->fc->streams[c->fc->nb_streams - 1]; avio_r8(pb); /* version */
sc = st->priv_data; use_subsamples = avio_rb24(pb) & 0x02; /* flags */
if (sc->cenc.aes_ctr) { sample_count = avio_rb32(pb);
av_log(c->fc, AV_LOG_ERROR, "duplicate senc atom\n"); if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
return AVERROR_INVALIDDATA; 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 */ return 0;
sc->cenc.use_subsamples = avio_rb24(pb) & 0x02; /* flags */ }
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)) { if (c->fc->nb_streams < 1)
av_log(c->fc, AV_LOG_ERROR, "senc atom size %"PRId64" invalid\n", atom.size); 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; 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 */ sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
auxiliary_info_size = atom.size - 8; return 0;
}
sc->cenc.auxiliary_info = av_malloc(auxiliary_info_size); static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
if (!sc->cenc.auxiliary_info) { {
return AVERROR(ENOMEM); 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; if (!sc->cenc.default_encrypted_sample) {
sc->cenc.auxiliary_info_pos = sc->cenc.auxiliary_info; sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
sc->cenc.auxiliary_info_index = 0; if (!sc->cenc.default_encrypted_sample) {
return AVERROR(ENOMEM);
}
}
if (avio_read(pb, sc->cenc.auxiliary_info, auxiliary_info_size) != auxiliary_info_size) { if (atom.size < 20)
av_log(c->fc, AV_LOG_ERROR, "failed to read the auxiliary info");
return AVERROR_INVALIDDATA; 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 */ is_protected = avio_r8(pb);
sc->cenc.aes_ctr = av_aes_ctr_alloc(); if (is_protected && !sc->cenc.encryption_index) {
if (!sc->cenc.aes_ctr) { // The whole stream should be by-default encrypted.
return AVERROR(ENOMEM); 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) 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; 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; int i, ret;
uint16_t subsample_count;
uint16_t clear_bytes;
uint8_t* input_end = input + size;
int ret;
if (index != sc->cenc.auxiliary_info_index) { if (sample->scheme != MKBETAG('c','e','n','c') || sample->crypt_byte_block != 0 || sample->skip_byte_block != 0) {
ret = mov_seek_auxiliary_info(c, sc, index); 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) { if (ret < 0) {
return ret; return ret;
} }
} }
/* read the iv */ av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->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;
if (!sc->cenc.use_subsamples) if (!sample->subsample_count)
{ {
/* decrypt the whole packet */ /* decrypt the whole packet */
av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size); av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
return 0; return 0;
} }
/* read the subsample count */ for (i = 0; i < sample->subsample_count; i++)
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--)
{ {
if (6 > sc->cenc.auxiliary_info_end - sc->cenc.auxiliary_info_pos) { if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
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) {
av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n"); av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} }
/* skip the clear bytes */ /* 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 */ /* decrypt the encrypted bytes */
av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, encrypted_bytes); av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, sample->subsamples[i].bytes_of_protected_data);
input += encrypted_bytes; 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"); av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
return AVERROR_INVALIDDATA; 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; return 0;
} }
@ -6142,7 +6361,9 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
{ MKTAG('s','i','n','f'), mov_read_default }, { MKTAG('s','i','n','f'), mov_read_default },
{ MKTAG('f','r','m','a'), mov_read_frma }, { MKTAG('f','r','m','a'), mov_read_frma },
{ MKTAG('s','e','n','c'), mov_read_senc }, { 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('d','f','L','a'), mov_read_dfla },
{ MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */ { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
{ MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical 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; 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) static int mov_read_close(AVFormatContext *s)
{ {
MOVContext *mov = s->priv_data; MOVContext *mov = s->priv_data;
@ -6570,8 +6801,8 @@ static int mov_read_close(AVFormatContext *s)
av_freep(&sc->extradata); av_freep(&sc->extradata);
av_freep(&sc->extradata_size); av_freep(&sc->extradata_size);
av_freep(&sc->cenc.auxiliary_info); mov_free_encryption_index(&sc->cenc.encryption_index);
av_freep(&sc->cenc.auxiliary_info_sizes); av_encryption_info_free(sc->cenc.default_encrypted_sample);
av_aes_ctr_free(sc->cenc.aes_ctr); av_aes_ctr_free(sc->cenc.aes_ctr);
av_freep(&sc->stereo3d); av_freep(&sc->stereo3d);
@ -6596,6 +6827,10 @@ static int mov_read_close(AVFormatContext *s)
av_freep(&mov->bitrates); av_freep(&mov->bitrates);
for (i = 0; i < mov->frag_index.nb_items; i++) { 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[i].stream_info);
} }
av_freep(&mov->frag_index.item); av_freep(&mov->frag_index.item);
@ -7166,12 +7401,9 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
if (mov->aax_mode) if (mov->aax_mode)
aax_filter(pkt->data, pkt->size, mov); aax_filter(pkt->data, pkt->size, mov);
if (sc->cenc.aes_ctr) { ret = cenc_filter(mov, sc, pkt, current_index);
ret = cenc_filter(mov, sc, current_index, pkt->data, pkt->size); if (ret < 0)
if (ret) { return ret;
return ret;
}
}
return 0; return 0;
} }

@ -41,7 +41,7 @@ typedef struct AVSubsampleEncryptionInfo {
* The size of this struct is not part of the public ABI. * The size of this struct is not part of the public ABI.
*/ */
typedef struct AVEncryptionInfo { typedef struct AVEncryptionInfo {
/** The fourcc encryption scheme. */ /** The fourcc encryption scheme, in big-endian byte order. */
uint32_t scheme; uint32_t scheme;
/** /**

@ -6,6 +6,8 @@ FATE_MOV = fate-mov-3elist \
fate-mov-1elist-ends-last-bframe \ fate-mov-1elist-ends-last-bframe \
fate-mov-2elist-elist1-ends-bframe \ fate-mov-2elist-elist1-ends-bframe \
fate-mov-3elist-encrypted \ fate-mov-3elist-encrypted \
fate-mov-frag-encrypted \
fate-mov-tenc-only-encrypted \
fate-mov-invalid-elst-entry-count \ fate-mov-invalid-elst-entry-count \
fate-mov-gpmf-remux \ fate-mov-gpmf-remux \
fate-mov-440hz-10ms \ fate-mov-440hz-10ms \
@ -39,6 +41,12 @@ fate-mov-3elist-1ctts: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/mov-3elist-1ctts.
# Edit list with encryption # Edit list with encryption
fate-mov-3elist-encrypted: CMD = framemd5 -decryption_key 12345678901234567890123456789012 -i $(TARGET_SAMPLES)/mov/mov-3elist-encrypted.mov fate-mov-3elist-encrypted: CMD = framemd5 -decryption_key 12345678901234567890123456789012 -i $(TARGET_SAMPLES)/mov/mov-3elist-encrypted.mov
# Fragmented encryption with senc boxes in movie fragments.
fate-mov-frag-encrypted: CMD = framemd5 -decryption_key 12345678901234567890123456789012 -i $(TARGET_SAMPLES)/mov/mov-frag-encrypted.mp4
# Full-sample encryption and constant IV using only tenc atom (no senc/saio/saiz).
fate-mov-tenc-only-encrypted: CMD = framemd5 -decryption_key 12345678901234567890123456789012 -i $(TARGET_SAMPLES)/mov/mov-tenc-only-encrypted.mp4
# Makes sure that the CTTS is also modified when we fix avindex in mov.c while parsing edit lists. # Makes sure that the CTTS is also modified when we fix avindex in mov.c while parsing edit lists.
fate-mov-elist-starts-ctts-2ndsample: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/mov-elist-starts-ctts-2ndsample.mov fate-mov-elist-starts-ctts-2ndsample: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/mov-elist-starts-ctts-2ndsample.mov

@ -0,0 +1,57 @@
#format: frame checksums
#version: 2
#hash: MD5
#tb 0: 1/24
#media_type 0: video
#codec_id 0: rawvideo
#dimensions 0: 120x52
#sar 0: 544/545
#stream#, dts, pts, duration, size, hash
0, 0, 0, 1, 9360, 920bdc277a6a31c1daed9aca44b10caf
0, 1, 1, 1, 9360, f1c0b61fef593de57cb97be7fa846569
0, 2, 2, 1, 9360, 6ef32d9d4398355aebf6d3fb11d51d3f
0, 3, 3, 1, 9360, d38fd3ef1e5a92fc109b8dd9eb6dadeb
0, 4, 4, 1, 9360, 54cc0c8a25d2f14f32663837d5e646f1
0, 5, 5, 1, 9360, b4b6829726dc3decb8b80ba0c35bcf30
0, 6, 6, 1, 9360, fca3f941e60a2f0a4ce30d5e0efbec3c
0, 7, 7, 1, 9360, cda6e26b6c1039ff3d229b262c9210c3
0, 8, 8, 1, 9360, f0d69255e3a27a8b4ae8a4b7b210929d
0, 9, 9, 1, 9360, 12cb23dd4e32af9c3b35f943714e3fdd
0, 10, 10, 1, 9360, 082aaf3216124ddcecb422fe5c832e82
0, 11, 11, 1, 9360, ff37bb8cd6bd0412a3b3cb45db54afc9
0, 12, 12, 1, 9360, dfb9085441575732844b6c2f05d5f542
0, 13, 13, 1, 9360, 0017100feaaa9fc7eacd2447d50d7542
0, 14, 14, 1, 9360, 4e2f1b8c4e04c59934c2f58541e62613
0, 15, 15, 1, 9360, 27a44dfea7cd2d30e488194c34ab473c
0, 16, 16, 1, 9360, fc7b56bd95e990a33cf575d1ef820902
0, 17, 17, 1, 9360, fa2d1609e69714dffc410e65f3c8b755
0, 18, 18, 1, 9360, 705d7429f447cb13febe202d567795f2
0, 19, 19, 1, 9360, 234802ce86e868faaf2cd40a286846ea
0, 20, 20, 1, 9360, 2f0354b40d211d0a4ade4568bea4f85e
0, 21, 21, 1, 9360, e96af3b6c0cc931463ca77d6be0f1148
0, 22, 22, 1, 9360, 04a904d798361959971361401879c7e4
0, 23, 23, 1, 9360, 2f119642340df6d25362b5590ded46b7
0, 24, 24, 1, 9360, 5993fca2e60050706f857ac76e48f386
0, 25, 25, 1, 9360, 2ff3b5775fed3d527bfbbeea786787fe
0, 26, 26, 1, 9360, 42024dbe23d3fb5b0d8987ae1ce390a8
0, 27, 27, 1, 9360, d804204f0bd9db5f6a758e2c934d9e38
0, 28, 28, 1, 9360, e322712e6e34c58ec1a2ab5e2c1e3bfe
0, 29, 29, 1, 9360, 3975bd1a5f6a6b6260276777f9de611e
0, 30, 30, 1, 9360, 4388f0412efc6310706a7cdedc859ea9
0, 31, 31, 1, 9360, b4b9a11b0b86635267345a569640e8d4
0, 32, 32, 1, 9360, 31879c7b8d6b67a4209ffde786bb8cb4
0, 33, 33, 1, 9360, 4b6dc02d7c889fe4abd4e013b25f585a
0, 34, 34, 1, 9360, dc73aae82bd39a1220d1106c8d3e8252
0, 35, 35, 1, 9360, 54c7dfbd49f312806f6c1a89f7c2c36f
0, 36, 36, 1, 9360, 150abc64f8994d444a521ea90570443c
0, 37, 37, 1, 9360, d277cdc7dcadbe0016f2e950459e7ebf
0, 38, 38, 1, 9360, 2196bf338ead90ea54687b85c73c8229
0, 39, 39, 1, 9360, 53ce5da5365abc0bd3217dd98e7c465d
0, 40, 40, 1, 9360, 34ee9832aea55c0c4e6f4381c413c10e
0, 41, 41, 1, 9360, 1769c7b5849e4681119067a06ac29a4f
0, 42, 42, 1, 9360, 71f53df739ef283a5184c91ef4b158e8
0, 43, 43, 1, 9360, d2d394739e9a59c06f0354c16843cb63
0, 44, 44, 1, 9360, d8e458e92ae29344505a24a3059fc584
0, 45, 45, 1, 9360, 0f1b11a09911851b798df2ef76253a7f
0, 46, 46, 1, 9360, 5c4a9f22baecf4e749c0d5c65a4f1007
0, 47, 47, 1, 9360, 3e2b7e7262fdca08d9d1ef6070125c4b

@ -0,0 +1,57 @@
#format: frame checksums
#version: 2
#hash: MD5
#tb 0: 1/24
#media_type 0: video
#codec_id 0: rawvideo
#dimensions 0: 1024x436
#sar 0: 1/1
#stream#, dts, pts, duration, size, hash
0, 0, 0, 1, 669696, f48f296a85eda5ba069dc851a3228bef
0, 1, 1, 1, 669696, a50c5f69bfa3387d49b5bdf738e6529c
0, 2, 2, 1, 669696, 05061299003760f6a4795b408f72aa31
0, 3, 3, 1, 669696, 2572119f0b0cdd83f8a7e06252cecd3b
0, 4, 4, 1, 669696, 29fe6a6bdb4a69018e318886a297f07e
0, 5, 5, 1, 669696, e8233c7fbaecfbff965c7dfdd3982b1b
0, 6, 6, 1, 669696, d9259df9880ff5d4a4b38282e67f407b
0, 7, 7, 1, 669696, 3e8d795195038993503ea9ab6984c915
0, 8, 8, 1, 669696, bc4e2d253b715a34f85aae1b080e3460
0, 9, 9, 1, 669696, 09aba8b3a96f53f9268e7420a10bfab6
0, 10, 10, 1, 669696, 179447977dd580da8b35fb5310a809ca
0, 11, 11, 1, 669696, 7a0eea9d54577990345f5705ab9882be
0, 12, 12, 1, 669696, 5bb96eb76f461825740e5938456df759
0, 13, 13, 1, 669696, bd4ac4a760ead774b9422a27dc071964
0, 14, 14, 1, 669696, 1cc05f760a9b751fc89e77f2bcc97259
0, 15, 15, 1, 669696, 825d0dee6f0174ba7102892c7de30b4d
0, 16, 16, 1, 669696, d26a2ef5267f6bb03c4e1d8514eee0df
0, 17, 17, 1, 669696, c916ffdeadca76596a8f7fd47914b5ef
0, 18, 18, 1, 669696, 6e085acfa7fee0658ea0ae6188274c17
0, 19, 19, 1, 669696, 1e95fa5b3561283f05bf0bd44cb91721
0, 20, 20, 1, 669696, 37e3d135aba9dfb8b87e441753115374
0, 21, 21, 1, 669696, 9c398310e8564491de624393c16265ce
0, 22, 22, 1, 669696, c87209e4d2617bc2ab40a75f455f09da
0, 23, 23, 1, 669696, 2679c2f8d1d1af21982e245945c1ee60
0, 24, 24, 1, 669696, 6151ab4781f31c5beb66b356ad547122
0, 25, 25, 1, 669696, f7ef6293bfb3a6a329061cb6a5ed5a38
0, 26, 26, 1, 669696, 2f6e666d14dfc407ca0c0f347b13eb08
0, 27, 27, 1, 669696, 3454fa1730d79b1aa8dbbc865dc150f4
0, 28, 28, 1, 669696, e93dc683e2453419a0419ab9af0f8f95
0, 29, 29, 1, 669696, 031eb3154f7f83cf86d42bee66be9cf7
0, 30, 30, 1, 669696, 1205c36723e88811206c68892d3aaed6
0, 31, 31, 1, 669696, 7dd7a8a19dcd73b31ddc6a6d0c597a42
0, 32, 32, 1, 669696, 7c91115368ea2531262a1197468bc3f4
0, 33, 33, 1, 669696, 3cf6d9ba385e0fff76da33299ed5380c
0, 34, 34, 1, 669696, 859fc8c3ef049e3c1175a85fb0a90a3d
0, 35, 35, 1, 669696, 1d09ce6c7027103d99a4d5799f6e72ab
0, 36, 36, 1, 669696, 3dcb8357408ac88abd734128d8f5dd6f
0, 37, 37, 1, 669696, 4dafce137a0a5178f6efaec878e64d36
0, 38, 38, 1, 669696, 44c478f29a1399ed03275a7357f57d48
0, 39, 39, 1, 669696, 6e9edaac7414c0e14591ac3d4d0b1ac4
0, 40, 40, 1, 669696, 522e4aaeea0825da27f631a9e690d654
0, 41, 41, 1, 669696, 85f2502a718440834c40051d30f8a65e
0, 42, 42, 1, 669696, ae8816f7bd4645ef1a17ee6d09b4c8d2
0, 43, 43, 1, 669696, 914b006fa92f1eb3e590245749f6810d
0, 44, 44, 1, 669696, 9406901542e94c429dff46108782ed69
0, 45, 45, 1, 669696, 324c13641c39eef5c476023e358c0391
0, 46, 46, 1, 669696, 4058e886e17c22e4eb9da1dd0d6ad891
0, 47, 47, 1, 669696, 9edf9cd15eea985b42fd1f5035b1d693
Loading…
Cancel
Save