!156 The MP4 H264 encoding format supports pssh parsing and cenc data encapsulation.

Merge pull request !156 from zhenghongda/master
This commit is contained in:
openharmony_ci 2024-03-15 08:35:42 +00:00 committed by Gitee
commit f5caed03c3
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
7 changed files with 376 additions and 99 deletions

View File

@ -130,6 +130,7 @@ config("ffmpeg_config") {
"-DCONFIG_AV3A_PARSER",
"-DCONFIG_AMRNB_DECODER",
"-DCONFIG_AMRWB_DECODER",
"-DOHOS_DRM",
"-DOHOS_OPT_COMPAT",
"-DOHOS_HDR_VIVID",
"-Wno-array-parameter",

View File

@ -24,6 +24,9 @@
#include "libavutil/avassert.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/mem.h"
#ifdef OHOS_DRM
#include "libavutil/encryption_info.h"
#endif
#include "avcodec.h"
#include "bsf.h"
@ -166,6 +169,40 @@ static int h264_mp4toannexb_init(AVBSFContext *ctx)
return 0;
}
#ifdef OHOS_DRM
static void h264_mp4toannexb_modify_encryption_info(AVPacket *pkt, uint64_t new_data_size, uint64_t old_data_size,
int copy)
{
AV_DrmCencInfo *old_side_data = NULL;
buffer_size_t old_side_data_size = 0;
if ((copy == 0) || (new_data_size == old_data_size)) {
return;
}
old_side_data = (AV_DrmCencInfo *)av_packet_get_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, &old_side_data_size);
if ((old_side_data != NULL) && (old_side_data_size != 0)) {
uint64_t total_size = 0;
for (uint32_t i = 0; i < old_side_data->sub_sample_num; i++) {
total_size +=
(uint64_t)(old_side_data->sub_sample[i].clear_header_len + old_side_data->sub_sample[i].pay_load_len);
if (total_size < new_data_size) {
continue;
}
if (new_data_size > old_data_size) {
old_side_data->sub_sample[i].clear_header_len += (uint32_t)(new_data_size - old_data_size);
} else {
uint32_t diff_size = (uint32_t)(old_data_size - new_data_size);
if (old_side_data->sub_sample[i].clear_header_len < diff_size) {
return;
}
old_side_data->sub_sample[i].clear_header_len -= diff_size;
}
break;
}
}
return;
}
#endif
static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *opkt)
{
H264BSFContext *s = ctx->priv_data;
@ -176,6 +213,9 @@ static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *opkt)
uint8_t *out;
uint64_t out_size;
int ret;
#ifdef OHOS_DRM
uint64_t old_out_size;
#endif
ret = ff_bsf_get_packet(ctx, &in);
if (ret < 0)
@ -199,6 +239,9 @@ static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *opkt)
sps_seen = s->idr_sps_seen;
pps_seen = s->idr_pps_seen;
out_size = 0;
#ifdef OHOS_DRM
old_out_size = out_size;
#endif
do {
uint32_t nal_size = 0;
@ -231,6 +274,10 @@ static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *opkt)
LOG_ONCE(ctx, AV_LOG_WARNING, "SPS not present in the stream, nor in AVCC, stream may be unreadable\n");
} else {
count_or_copy(&out, &out_size, s->sps, s->sps_size, -1, j);
#ifdef OHOS_DRM
h264_mp4toannexb_modify_encryption_info(in, out_size, old_out_size, j);
old_out_size = out_size;
#endif
sps_seen = 1;
}
}
@ -247,6 +294,10 @@ static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *opkt)
if (ctx->par_out->extradata)
count_or_copy(&out, &out_size, ctx->par_out->extradata,
ctx->par_out->extradata_size, -1, j);
#ifdef OHOS_DRM
h264_mp4toannexb_modify_encryption_info(in, out_size, old_out_size, j);
old_out_size = out_size;
#endif
new_idr = 0;
/* if only SPS has been seen, also insert PPS */
} else if (new_idr && unit_type == H264_NAL_IDR_SLICE && sps_seen && !pps_seen) {
@ -254,11 +305,20 @@ static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *opkt)
LOG_ONCE(ctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n");
} else {
count_or_copy(&out, &out_size, s->pps, s->pps_size, -1, j);
#ifdef OHOS_DRM
h264_mp4toannexb_modify_encryption_info(in, out_size, old_out_size, j);
old_out_size = out_size;
#endif
}
}
count_or_copy(&out, &out_size, buf, nal_size,
unit_type == H264_NAL_SPS || unit_type == H264_NAL_PPS, j);
#ifdef OHOS_DRM
h264_mp4toannexb_modify_encryption_info(in, out_size,
(uint64_t)(nal_size + old_out_size + s->length_size), j);
old_out_size = out_size;
#endif
if (!new_idr && unit_type == H264_NAL_SLICE) {
new_idr = 1;
sps_seen = 0;

View File

@ -67,6 +67,14 @@
#include "qtpalette.h"
#ifdef OHOS_DRM
#define MOV_DRM_PSSH_TITLE_LEN (8)
static const uint8_t g_pssh_title_buf[] = {
0x70, 0x73, 0x73, 0x68
};
#endif
/* those functions parse an atom */
/* links atom IDs to parse functions */
typedef struct MOVParseTableEntry {
@ -6405,6 +6413,109 @@ static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return 0;
}
#ifdef OHOS_DRM
static int mov_set_drm_info(const uint8_t *pssh_buf, uint32_t pssh_buf_size, AV_DrmInfo *side_data)
{
if (pssh_buf_size < (AV_DRM_UUID_OFFSET + AV_DRM_MAX_DRM_UUID_LEN)) {
return AVERROR_INVALIDDATA;
}
side_data->algo = AV_DRM_ALG_CENC_UNENCRYPTED;
side_data->encrypt_blocks = 0;
side_data->skip_blocks = 0;
side_data->uuid_len = AV_DRM_MAX_DRM_UUID_LEN;
memcpy(side_data->uuid, pssh_buf + AV_DRM_UUID_OFFSET, AV_DRM_MAX_DRM_UUID_LEN);
side_data->pssh_len = pssh_buf_size;
memcpy(side_data->pssh, pssh_buf, pssh_buf_size);
return 0;
}
static int is_exist_pssh(const AV_DrmInfo *old_side_data, uint32_t count, AV_DrmInfo side_data_node)
{
uint32_t i = 0;
if (count == 0) {
return 0;
}
for (; i < count; i++) {
if ((old_side_data[i].pssh_len == side_data_node.pssh_len) &&
(old_side_data[i].uuid_len == side_data_node.uuid_len)) {
if ((memcmp(old_side_data[i].pssh, side_data_node.pssh, old_side_data[i].pssh_len) == 0) &&
(memcmp(old_side_data[i].uuid, side_data_node.uuid, old_side_data[i].uuid_len) == 0)) {
return 1;
}
}
}
return 0;
}
static void mov_drm_info_copy(AV_DrmInfo *new_side_data, const AV_DrmInfo *old_side_data,
uint32_t old_side_data_count, AV_DrmInfo side_data_node)
{
uint32_t i = 0;
for (; i < old_side_data_count; i++) {
new_side_data[i].algo = old_side_data[i].algo;
new_side_data[i].encrypt_blocks = old_side_data[i].encrypt_blocks;
new_side_data[i].skip_blocks = old_side_data[i].skip_blocks;
new_side_data[i].uuid_len = old_side_data[i].uuid_len;
memcpy(new_side_data[i].uuid, old_side_data[i].uuid, old_side_data[i].uuid_len);
new_side_data[i].pssh_len = old_side_data[i].pssh_len;
memcpy(new_side_data[i].pssh, old_side_data[i].pssh, old_side_data[i].pssh_len);
}
new_side_data[i].algo = side_data_node.algo;
new_side_data[i].encrypt_blocks = side_data_node.encrypt_blocks;
new_side_data[i].skip_blocks = side_data_node.skip_blocks;
new_side_data[i].uuid_len = side_data_node.uuid_len;
memcpy(new_side_data[i].uuid, side_data_node.uuid, side_data_node.uuid_len);
new_side_data[i].pssh_len = side_data_node.pssh_len;
memcpy(new_side_data[i].pssh, side_data_node.pssh, side_data_node.pssh_len);
return;
}
static int mov_read_pssh_ex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
int ret = 0;
AVStream *st;
AV_DrmInfo side_data_node;
AV_DrmInfo *old_side_data = NULL;
AV_DrmInfo *new_side_data = NULL;
uint8_t pssh_buf[AV_DRM_MAX_DRM_PSSH_LEN];
buffer_size_t old_side_data_size = 0;
uint32_t old_side_data_count = 0;
uint32_t pssh_exist_flag = 0;
if ((c == NULL) || (c->fc == NULL) || (c->fc->nb_streams < 1) || (c->fc->streams == NULL) || (pb == NULL) ||
(atom.size > (AV_DRM_MAX_DRM_PSSH_LEN - MOV_DRM_PSSH_TITLE_LEN)) || (atom.size == 0)) {
return 0;
}
st = c->fc->streams[c->fc->nb_streams-1];
memset(pssh_buf, 0, sizeof(pssh_buf));
AV_WB32(pssh_buf, (atom.size + MOV_DRM_PSSH_TITLE_LEN));
memcpy(pssh_buf + sizeof(uint32_t), g_pssh_title_buf, sizeof(g_pssh_title_buf));
if ((ret = ffio_read_size(pb, pssh_buf + MOV_DRM_PSSH_TITLE_LEN, atom.size)) < 0) {
av_log(c->fc, AV_LOG_ERROR, "Failed to read the pssh data\n");
return 0;
}
if ((ret = mov_set_drm_info(pssh_buf, (uint32_t)(atom.size + MOV_DRM_PSSH_TITLE_LEN), &side_data_node)) != 0) {
av_log(c->fc, AV_LOG_ERROR, "Failed to set drm info\n");
return 0;
}
old_side_data = (AV_DrmInfo *)av_stream_get_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO, &old_side_data_size);
if ((old_side_data != NULL) && (old_side_data_size != 0)) {
old_side_data_count = old_side_data_size / sizeof(AV_DrmInfo);
pssh_exist_flag = is_exist_pssh(old_side_data, old_side_data_count, side_data_node);
}
if (pssh_exist_flag == 0) {
new_side_data = (AV_DrmInfo *)av_stream_new_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO,
(buffer_size_t)(sizeof(AV_DrmInfo) * (old_side_data_count + 1)));
if (new_side_data != NULL) {
mov_drm_info_copy(new_side_data, old_side_data, old_side_data_count, side_data_node);
}
}
return 0;
}
#endif
static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
AVEncryptionInitInfo *info, *old_init_info;
@ -6758,10 +6869,19 @@ static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPa
return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
} else {
size_t size;
#ifdef OHOS_DRM
AV_DrmCencInfo *side_data = NULL;
side_data = av_encryption_info_add_side_data_ex(encrypted_sample, &size, side_data);
#else
uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
#endif
if (!side_data)
return AVERROR(ENOMEM);
#ifdef OHOS_DRM
ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, (uint8_t *)side_data, size);
#else
ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
#endif
if (ret < 0)
av_free(side_data);
return ret;
@ -6990,7 +7110,11 @@ 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 },
#ifdef OHOS_DRM
{ MKTAG('p','s','s','h'), mov_read_pssh_ex },
#else
{ MKTAG('p','s','s','h'), mov_read_pssh },
#endif
{ MKTAG('s','c','h','m'), mov_read_schm },
{ MKTAG('s','c','h','i'), mov_read_default },
{ MKTAG('t','e','n','c'), mov_read_tenc },

View File

@ -30,7 +30,9 @@
#include "libavutil/opt.h"
#include "libavutil/avassert.h"
#include "libavutil/dovi_meta.h"
#ifdef OHOS_DRM
#include "libavutil/thread.h"
#endif
#include "libavcodec/bytestream.h"
#include "libavcodec/get_bits.h"
#include "libavcodec/opus.h"
@ -52,23 +54,18 @@
#define MAX_MP4_DESCR_COUNT 16
#define DRM_KEY_ID_SIZE 16
#define DRM_IV_SIZE 16
#ifdef OHOS_DRM
#define DRM_USER_DATA_REGISTERED_UUID_SIZE 16
#define DRM_VIDEO_FRAME_ARR_LEN 3
#define DRM_MAX_SUB_SAMPLE_NUM 64
#define DRM_H265_PAYLOAD_TYPE_OFFSET 5
#define DRM_LEGACY_LEN 3
#define DRM_MAX_DRM_PSSH_LEN 2048
#define DRM_MAX_DRM_UUID_LEN 16
#define DRM_AMBIGUITY_ARR_LEN 3
#define DRM_AMBIGUITY_START_NUM (0x00)
#define DRM_AMBIGUITY_END_NUM (0x03)
#define DRM_MIN_DRM_INFO_LEN (2)
#define DRM_UUID_OFFSET (12)
#define DRM_TS_FLAG_CRYPT_BYTE_BLOCK (2)
#define DRM_CRYPT_BYTE_BLOCK (1 + 2) // 2: DRM_TS_FLAG_CRYPT_BYTE_BLOCK
#define DRM_SKIP_BYTE_BLOCK (9)
#define DRM_TS_CRYPT_BYTE_BLOCK (1 + 2) // 2: DRM_TS_FLAG_CRYPT_BYTE_BLOCK
#define DRM_TS_SKIP_BYTE_BLOCK (9)
#define DRM_SHIFT_LEFT_NUM (1)
#define DRM_H264_VIDEO_NAL_TYPE_UMASK_NUM (0x1f)
#define DRM_H265_VIDEO_NAL_TYPE_UMASK_NUM (0x3f)
@ -87,53 +84,13 @@ static const uint8_t g_user_registered_uuid[DRM_USER_DATA_REGISTERED_UUID_SIZE]
0x70, 0xc1, 0xdb, 0x9f, 0x66, 0xae, 0x41, 0x27, 0xbf, 0xc0, 0xbb, 0x19, 0x81, 0x69, 0x4b, 0x66
};
typedef enum {
DRM_ALG_CENC_UNENCRYPTED = 0x0,
DRM_ALG_CENC_AES_CTR = 0x1,
DRM_ALG_CENC_AES_WV = 0x2,
DRM_ALG_CENC_AES_CBC = 0x3,
DRM_ALG_CENC_SM4_CBC = 0x4,
DRM_ALG_CENC_SM4_CTR,
} DRM_CencAlgorithm;
typedef enum {
DRM_ARR_SUBSCRIPT_ZERO = 0,
DRM_ARR_SUBSCRIPT_ONE,
DRM_ARR_SUBSCRIPT_TWO,
DRM_ARR_SUBSCRIPT_THREE,
} DRM_ArrSubscriptCollection;
struct _DRM_SubSample {
uint32_t clear_header_len;
uint32_t pay_load_len;
};
typedef struct _DRM_SubSample DRM_SubSample;
struct _DRMCencInfo {
DRM_CencAlgorithm algo;
uint8_t key_id[DRM_KEY_ID_SIZE];
uint32_t key_id_len;
uint8_t iv[DRM_IV_SIZE];
uint32_t iv_len;
uint32_t is_ambiguity;
uint32_t encrypt_blocks;
uint32_t skip_blocks;
uint32_t first_encrypt_offset;
DRM_SubSample sub_sample[DRM_MAX_SUB_SAMPLE_NUM];
uint32_t sub_sample_num;
};
typedef struct _DRMCencInfo DRMCencInfo;
struct _DrmInfo {
DRM_CencAlgorithm algo;
uint32_t encrypt_blocks;
uint32_t skip_blocks;
uint32_t uuid_len;
uint8_t uuid[DRM_MAX_DRM_UUID_LEN];
uint32_t pssh_len;
uint8_t pssh[DRM_MAX_DRM_PSSH_LEN];
};
typedef struct _DrmInfo DrmInfo;
#endif
#define MOD_UNLIKELY(modulus, dividend, divisor, prev_dividend) \
do { \
@ -352,33 +309,34 @@ typedef struct PESContext {
extern AVInputFormat ff_mpegts_demuxer;
static void mpegts_set_drm_algo_and_blocks(uint8_t algo, DrmInfo *drm_info)
#ifdef OHOS_DRM
static void mpegts_set_drm_algo_and_blocks(uint8_t algo, AV_DrmInfo *drm_info)
{
if (algo == 0x1) { // 0x1:SM4-SAMPL SM4S
drm_info->algo = DRM_ALG_CENC_SM4_CBC;
drm_info->encrypt_blocks = DRM_CRYPT_BYTE_BLOCK;
drm_info->skip_blocks = DRM_SKIP_BYTE_BLOCK;
drm_info->algo = AV_DRM_ALG_CENC_SM4_CBC;
drm_info->encrypt_blocks = DRM_TS_CRYPT_BYTE_BLOCK;
drm_info->skip_blocks = DRM_TS_SKIP_BYTE_BLOCK;
} else if (algo == 0x2) { // 0x2:AES CBCS
drm_info->algo = DRM_ALG_CENC_AES_CBC;
drm_info->encrypt_blocks = DRM_CRYPT_BYTE_BLOCK;
drm_info->skip_blocks = DRM_SKIP_BYTE_BLOCK;
drm_info->algo = AV_DRM_ALG_CENC_AES_CBC;
drm_info->encrypt_blocks = DRM_TS_CRYPT_BYTE_BLOCK;
drm_info->skip_blocks = DRM_TS_SKIP_BYTE_BLOCK;
} else if (algo == 0x5) { // 0x5:AES CBC1
drm_info->algo = DRM_ALG_CENC_AES_CBC;
drm_info->algo = AV_DRM_ALG_CENC_AES_CBC;
drm_info->encrypt_blocks = DRM_TS_FLAG_CRYPT_BYTE_BLOCK;
drm_info->skip_blocks = 0;
} else if (algo == 0x3) { // 0x3:SM4-CBC SM4C
drm_info->algo = DRM_ALG_CENC_SM4_CBC;
drm_info->algo = AV_DRM_ALG_CENC_SM4_CBC;
drm_info->encrypt_blocks = DRM_TS_FLAG_CRYPT_BYTE_BLOCK;
drm_info->skip_blocks = 0;
} else if (algo == 0x0) { // 0x0:NONE
drm_info->algo = DRM_ALG_CENC_UNENCRYPTED;
drm_info->algo = AV_DRM_ALG_CENC_UNENCRYPTED;
drm_info->encrypt_blocks = DRM_TS_FLAG_CRYPT_BYTE_BLOCK;
drm_info->skip_blocks = 0;
}
return;
}
static int mpegts_get_drm_info(const uint8_t *src, uint32_t src_len, DrmInfo *drm_info)
static int mpegts_get_drm_info(const uint8_t *src, uint32_t src_len, AV_DrmInfo *drm_info)
{
uint32_t offset = 0;
if (src_len <= DRM_MIN_DRM_INFO_LEN) {
@ -392,16 +350,16 @@ static int mpegts_get_drm_info(const uint8_t *src, uint32_t src_len, DrmInfo *dr
av_log(NULL, AV_LOG_DEBUG, "audio_algo:%d\n", audio_algo);
offset++;
if (src_len - offset <= DRM_MAX_DRM_PSSH_LEN) {
if (src_len - offset <= AV_DRM_MAX_DRM_PSSH_LEN) {
memcpy(drm_info->pssh, src + offset, src_len - offset);
drm_info->pssh_len = src_len - offset;
} else {
av_log(NULL, AV_LOG_ERROR, "pssh not found");
return -1;
}
if (src_len >= offset + DRM_UUID_OFFSET + DRM_MAX_DRM_UUID_LEN) {
memcpy(drm_info->uuid, src + offset + DRM_UUID_OFFSET, DRM_MAX_DRM_UUID_LEN);
drm_info->uuid_len = (uint32_t)DRM_MAX_DRM_UUID_LEN;
if (src_len >= offset + AV_DRM_UUID_OFFSET + AV_DRM_MAX_DRM_UUID_LEN) {
memcpy(drm_info->uuid, src + offset + AV_DRM_UUID_OFFSET, AV_DRM_MAX_DRM_UUID_LEN);
drm_info->uuid_len = (uint32_t)AV_DRM_MAX_DRM_UUID_LEN;
} else {
av_log(NULL, AV_LOG_ERROR, "uuid not found");
return -1;
@ -409,7 +367,7 @@ static int mpegts_get_drm_info(const uint8_t *src, uint32_t src_len, DrmInfo *dr
return 0;
}
static void mpegts_avstream_drm_info_copy(DrmInfo *dest, DrmInfo *src)
static void mpegts_avstream_drm_info_copy(AV_DrmInfo *dest, AV_DrmInfo *src)
{
dest->algo = src->algo;
dest->encrypt_blocks = src->encrypt_blocks;
@ -420,11 +378,11 @@ static void mpegts_avstream_drm_info_copy(DrmInfo *dest, DrmInfo *src)
memcpy(dest->uuid, src->uuid, src->uuid_len);
}
static void mpegts_avstream_set_drm_info(AVStream *avstream, DrmInfo *info)
static void mpegts_avstream_set_drm_info(AVStream *avstream, AV_DrmInfo *info)
{
ff_mutex_lock(&g_mpegts_mutex);
DrmInfo *drm_info = (DrmInfo *)av_stream_new_side_data(avstream, AV_PKT_DATA_ENCRYPTION_INIT_INFO,
(buffer_size_t)(sizeof(DrmInfo)));
AV_DrmInfo *drm_info = (AV_DrmInfo *)av_stream_new_side_data(avstream, AV_PKT_DATA_ENCRYPTION_INIT_INFO,
(buffer_size_t)(sizeof(AV_DrmInfo)));
if (drm_info != NULL) {
mpegts_avstream_drm_info_copy(drm_info, info);
}
@ -551,7 +509,7 @@ static int mpegts_drm_find_cei_nal_unit(enum AVCodecID codec_id, uint8_t *data,
} else if (codec_id == AV_CODEC_ID_H264) {
ret = mpegts_drm_find_h264_cei_nal_unit(data, data_size, cei_start_pos, index);
}
return -1;
return ret;
}
static int mpegts_drm_find_cei_pos(enum AVCodecID codec_id, uint8_t *data, uint32_t data_size,
@ -604,7 +562,7 @@ static void mpegts_drm_remove_ambiguity_bytes(uint8_t *data, uint32_t *data_size
}
static int mpegts_drm_get_key_id(uint8_t *data, uint32_t *data_size, uint32_t *pos, uint8_t *drm_descriptor_flag,
DRMCencInfo *cenc_info)
AV_DrmCencInfo *cenc_info)
{
uint32_t offset = *pos;
if (offset >= *data_size) {
@ -624,24 +582,24 @@ static int mpegts_drm_get_key_id(uint8_t *data, uint32_t *data_size, uint32_t *p
}
if (encryption_flag != 0) {
if ((offset + (uint32_t)DRM_KEY_ID_SIZE) > *data_size) {
if ((offset + (uint32_t)AV_DRM_KEY_ID_SIZE) > *data_size) {
av_log(NULL, AV_LOG_ERROR, "cei data too short\n");
return -1;
}
memcpy(cenc_info->key_id, data + offset, DRM_KEY_ID_SIZE);
cenc_info->key_id_len = (uint32_t)DRM_KEY_ID_SIZE;
offset += (uint32_t)DRM_KEY_ID_SIZE;
memcpy(cenc_info->key_id, data + offset, AV_DRM_KEY_ID_SIZE);
cenc_info->key_id_len = (uint32_t)AV_DRM_KEY_ID_SIZE;
offset += (uint32_t)AV_DRM_KEY_ID_SIZE;
} else {
cenc_info->algo = DRM_ALG_CENC_UNENCRYPTED;
cenc_info->algo = AV_DRM_ALG_CENC_UNENCRYPTED;
}
if (next_key_id_flag == 1) {
offset += (uint32_t)DRM_KEY_ID_SIZE;
offset += (uint32_t)AV_DRM_KEY_ID_SIZE;
}
*pos = offset;
return 0;
}
static int mpegts_drm_get_iv(uint8_t *data, uint32_t data_size, uint32_t *pos, DRMCencInfo *cenc_info)
static int mpegts_drm_get_iv(uint8_t *data, uint32_t data_size, uint32_t *pos, AV_DrmCencInfo *cenc_info)
{
uint32_t offset = *pos;
if (offset >= data_size) {
@ -663,10 +621,10 @@ static int mpegts_drm_get_iv(uint8_t *data, uint32_t data_size, uint32_t *pos, D
}
static int mpegts_drm_parse_drm_descriptor(uint8_t *data, uint32_t data_size, uint32_t *pos,
uint8_t drm_descriptor_flag, DRMCencInfo *cenc_info)
uint8_t drm_descriptor_flag, AV_DrmCencInfo *cenc_info)
{
uint32_t offset = *pos;
DrmInfo drm_info;
AV_DrmInfo drm_info;
if (drm_descriptor_flag == 0) {
return 0;
}
@ -682,7 +640,8 @@ static int mpegts_drm_parse_drm_descriptor(uint8_t *data, uint32_t data_size, ui
return 0;
}
static int mpegts_drm_set_key_info(uint8_t *data, uint32_t data_size, uint32_t cei_start_pos, DRMCencInfo *cenc_info)
static int mpegts_drm_set_key_info(uint8_t *data, uint32_t data_size, uint32_t cei_start_pos,
AV_DrmCencInfo *cenc_info)
{
uint32_t total_size = data_size;
uint32_t pos = cei_start_pos;
@ -731,7 +690,7 @@ static int mpegts_drm_set_key_info(uint8_t *data, uint32_t data_size, uint32_t c
return 1; // 1 true
}
static void mpegts_drm_cenc_info_copy(DRMCencInfo *dest, DRMCencInfo *src, uint32_t flag)
static void mpegts_drm_cenc_info_copy(AV_DrmCencInfo *dest, AV_DrmCencInfo *src, uint32_t flag)
{
dest->algo = src->algo;
dest->key_id_len = src->key_id_len;
@ -751,20 +710,20 @@ static void mpegts_drm_cenc_info_copy(DRMCencInfo *dest, DRMCencInfo *src, uint3
}
}
static void mpegts_avstream_set_cenc_info(AVStream *avstream, DRMCencInfo *info)
static void mpegts_avstream_set_cenc_info(AVStream *avstream, AV_DrmCencInfo *info)
{
DRMCencInfo *cenc_info = (DRMCencInfo *)av_stream_new_side_data(avstream, AV_PKT_DATA_ENCRYPTION_INFO,
(buffer_size_t)(sizeof(DRMCencInfo)));
AV_DrmCencInfo *cenc_info = (AV_DrmCencInfo *)av_stream_new_side_data(avstream, AV_PKT_DATA_ENCRYPTION_INFO,
(buffer_size_t)(sizeof(AV_DrmCencInfo)));
if (cenc_info != NULL) {
mpegts_drm_cenc_info_copy(cenc_info, info, 1); // 1:true
}
return;
}
static void mpegts_packet_set_cenc_info(AVPacket *pkt, DRMCencInfo *info)
static void mpegts_packet_set_cenc_info(AVPacket *pkt, AV_DrmCencInfo *info)
{
DRMCencInfo *cenc_info = (DRMCencInfo *)av_packet_new_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO,
(buffer_size_t)(sizeof(DRMCencInfo)));
AV_DrmCencInfo *cenc_info = (AV_DrmCencInfo *)av_packet_new_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO,
(buffer_size_t)(sizeof(AV_DrmCencInfo)));
if (cenc_info != NULL) {
mpegts_drm_cenc_info_copy(cenc_info, info, 1); // 1:true
}
@ -772,7 +731,7 @@ static void mpegts_packet_set_cenc_info(AVPacket *pkt, DRMCencInfo *info)
}
static int mpegts_drm_get_cenc_info(AVStream *avstream, enum AVCodecID codec_id, uint8_t *data, uint32_t data_size,
DRMCencInfo *cenc_info)
AV_DrmCencInfo *cenc_info)
{
int ret;
uint32_t cei_start_pos = (uint32_t)DRM_INVALID_START_POS;
@ -781,9 +740,9 @@ static int mpegts_drm_get_cenc_info(AVStream *avstream, enum AVCodecID codec_id,
ret = mpegts_drm_find_cei_pos(codec_id, data, data_size, &cei_start_pos, &cei_end_pos);
if (ret) {
buffer_size_t drm_info_size = 0;
DrmInfo *drm_info = NULL;
AV_DrmInfo *drm_info = NULL;
ff_mutex_lock(&g_mpegts_mutex);
drm_info = (DrmInfo *)av_stream_get_side_data(avstream, AV_PKT_DATA_ENCRYPTION_INIT_INFO,
drm_info = (AV_DrmInfo *)av_stream_get_side_data(avstream, AV_PKT_DATA_ENCRYPTION_INIT_INFO,
&drm_info_size);
if ((drm_info != NULL) && (drm_info_size != 0)) {
cenc_info->algo = drm_info->algo;
@ -795,8 +754,8 @@ static int mpegts_drm_get_cenc_info(AVStream *avstream, enum AVCodecID codec_id,
return ret;
} else {
buffer_size_t cenc_info_size = 0;
DRMCencInfo *cenc_info_store = NULL;
cenc_info_store = (DRMCencInfo *)av_stream_get_side_data(avstream, AV_PKT_DATA_ENCRYPTION_INFO,
AV_DrmCencInfo *cenc_info_store = NULL;
cenc_info_store = (AV_DrmCencInfo *)av_stream_get_side_data(avstream, AV_PKT_DATA_ENCRYPTION_INFO,
&cenc_info_size);
if ((cenc_info_store != NULL) && (cenc_info_size != 0)) {
mpegts_drm_cenc_info_copy(cenc_info, cenc_info_store, 0);
@ -808,7 +767,7 @@ static int mpegts_drm_get_cenc_info(AVStream *avstream, enum AVCodecID codec_id,
static void mpegts_packet_add_cenc_info(AVFormatContext *s, AVPacket *pkt)
{
DRMCencInfo cenc_info;
AV_DrmCencInfo cenc_info;
if (pkt == NULL || pkt->data == NULL || pkt->size == 0) {
av_log(NULL, AV_LOG_ERROR, "pkt parameter err\n");
return;
@ -820,7 +779,7 @@ static void mpegts_packet_add_cenc_info(AVFormatContext *s, AVPacket *pkt)
}
enum AVCodecID codec_id = s->streams[pkt->stream_index]->codecpar->codec_id;
memset(&cenc_info, 0, sizeof(DRMCencInfo));
memset(&cenc_info, 0, sizeof(AV_DrmCencInfo));
if ((codec_id != AV_CODEC_ID_AVS2) && (codec_id != AV_CODEC_ID_HEVC) && (codec_id != AV_CODEC_ID_H264) &&
(codec_id != AV_CODEC_ID_AVS3)) {
@ -830,7 +789,7 @@ static void mpegts_packet_add_cenc_info(AVFormatContext *s, AVPacket *pkt)
cenc_info.sub_sample[0].clear_header_len = pkt->size;
cenc_info.sub_sample[0].pay_load_len = 0;
cenc_info.sub_sample_num = 1;
cenc_info.algo = DRM_ALG_CENC_UNENCRYPTED;
cenc_info.algo = AV_DRM_ALG_CENC_UNENCRYPTED;
cenc_info.is_ambiguity = 1;
int ret = mpegts_drm_get_cenc_info(s->streams[pkt->stream_index], codec_id, pkt->data, pkt->size, &cenc_info);
@ -840,6 +799,7 @@ static void mpegts_packet_add_cenc_info(AVFormatContext *s, AVPacket *pkt)
}
return;
}
#endif
static struct Program * get_program(MpegTSContext *ts, unsigned int programid)
{
@ -2679,16 +2639,18 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
}
}
break;
#ifdef OHOS_DRM
case DRM_DESCRIPTOR:
{
int ret;
DrmInfo drm_info;
AV_DrmInfo drm_info;
ret = mpegts_get_drm_info(*pp, desc_len, &drm_info);
if (ret == 0) {
mpegts_avstream_set_drm_info(st, &drm_info);
}
}
break;
#endif
case 0xfd: /* ARIB data coding type descriptor */
// STD-B24, fascicle 3, chapter 4 defines private_stream_1
// for captions
@ -2870,7 +2832,9 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
uint32_t prog_reg_desc = 0; /* registration descriptor */
int stream_identifier = -1;
struct Program *prg;
DrmInfo drm_info;
#ifdef OHOS_DRM
AV_DrmInfo drm_info;
#endif
int mp4_descr_count = 0;
Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = { { 0 } };
@ -2879,7 +2843,9 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
av_log(ts->stream, AV_LOG_TRACE, "PMT: len %i\n", section_len);
hex_dump_debug(ts->stream, section, section_len);
memset(&drm_info, 0, sizeof(DrmInfo));
#ifdef OHOS_DRM
memset(&drm_info, 0, sizeof(AV_DrmInfo));
#endif
p_end = section + section_len - 4;
p = section;
@ -2944,13 +2910,15 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
} else if (tag == REGISTRATION_DESCRIPTOR && len >= 4) {
prog_reg_desc = bytestream_get_le32(&p);
len -= 4;
#ifdef OHOS_DRM
} else if ((tag == DRM_DESCRIPTOR) && (len > DRM_MIN_DRM_INFO_LEN)) {
int ret = mpegts_get_drm_info(p, (uint32_t)len, &drm_info);
if (ret != 0) {
memset(&drm_info, 0, sizeof(DrmInfo));
memset(&drm_info, 0, sizeof(AV_DrmInfo));
drm_info.pssh_len = 0;
drm_info.uuid_len = 0;
}
#endif
}
p += len;
}
@ -3040,9 +3008,11 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if (!st)
goto out;
#ifdef OHOS_DRM
if ((drm_info.pssh_len != 0) && (drm_info.uuid_len != 0)) {
mpegts_avstream_set_drm_info(st, &drm_info);
}
#endif
if (pes && !pes->stream_type)
mpegts_set_stream_info(st, pes, stream_type, prog_reg_desc);
@ -3834,11 +3804,16 @@ static int mpegts_read_packet(AVFormatContext *s, AVPacket *pkt)
}
}
#ifdef OHOS_DRM
if (!ret && pkt->size < 0) {
ret = AVERROR_INVALIDDATA;
return ret;
}
mpegts_packet_add_cenc_info(s, pkt);
#else
if (!ret && pkt->size < 0)
ret = AVERROR_INVALIDDATA;
#endif
return ret;
}

View File

@ -153,7 +153,9 @@
#define FMC_DESCRIPTOR 0x1f
#define METADATA_DESCRIPTOR 0x26
#define METADATA_STD_DESCRIPTOR 0x27
#ifdef OHOS_DRM
#define DRM_DESCRIPTOR 0xc0
#endif
typedef struct MpegTSContext MpegTSContext;

View File

@ -159,6 +159,67 @@ uint8_t *av_encryption_info_add_side_data(const AVEncryptionInfo *info, size_t *
return buffer;
}
#ifdef OHOS_DRM
static void av_encryption_info_set_drm_algo(uint32_t algo, AV_DrmCencInfo *cenc_info)
{
switch (algo) {
case MKBETAG('c','e','n','c'):
case MKBETAG('c','e','n','s'):
cenc_info->algo = AV_DRM_ALG_CENC_AES_CTR;
break;
case MKBETAG('c','b','c','1'):
case MKBETAG('c','b','c','s'):
cenc_info->algo = AV_DRM_ALG_CENC_AES_CBC;
break;
case MKBETAG('s','m','4','c'):
case MKBETAG('s','m','4','s'):
cenc_info->algo = AV_DRM_ALG_CENC_SM4_CBC;
break;
case MKBETAG('s','m','4','t'):
case MKBETAG('s','m','4','r'):
cenc_info->algo = AV_DRM_ALG_CENC_SM4_CTR;
break;
default:
cenc_info->algo = AV_DRM_ALG_CENC_UNENCRYPTED;
break;
}
return;
}
AV_DrmCencInfo *av_encryption_info_add_side_data_ex(const AVEncryptionInfo *info, size_t *side_data_size,
AV_DrmCencInfo *cenc_info)
{
uint32_t i;
if ((info == NULL) || (info->key_id_size != AV_DRM_KEY_ID_SIZE) || (info->iv_size > AV_DRM_IV_SIZE) ||
(info->iv_size == 0) || (info->subsample_count > AV_DRM_MAX_SUB_SAMPLE_NUM) || (info->key_id == NULL) ||
(info->iv == NULL) || (info->subsamples == NULL) || (side_data_size == NULL)) {
return NULL;
}
*side_data_size = sizeof(AV_DrmCencInfo);
cenc_info = av_mallocz(*side_data_size);
if (!cenc_info)
return NULL;
av_encryption_info_set_drm_algo(info->scheme, cenc_info);
cenc_info->key_id_len = info->key_id_size;
memcpy(cenc_info->key_id, info->key_id, info->key_id_size);
cenc_info->iv_len = info->iv_size;
memcpy(cenc_info->iv, info->iv, info->iv_size);
cenc_info->is_ambiguity = 0;
cenc_info->encrypt_blocks = info->crypt_byte_block;
cenc_info->skip_blocks = info->skip_byte_block;
cenc_info->first_encrypt_offset = 0;
cenc_info->sub_sample_num = info->subsample_count;
for (i = 0; i < cenc_info->sub_sample_num; i++) {
cenc_info->sub_sample[i].clear_header_len = info->subsamples[i].bytes_of_clear_data;
cenc_info->sub_sample[i].pay_load_len = info->subsamples[i].bytes_of_protected_data;
}
return cenc_info;
}
#endif
// The format of the AVEncryptionInitInfo side data:
// u32be init_info_count
// {

View File

@ -22,6 +22,56 @@
#include <stddef.h>
#include <stdint.h>
#ifdef OHOS_DRM
#define AV_DRM_KEY_ID_SIZE 16
#define AV_DRM_IV_SIZE 16
#define AV_DRM_MAX_SUB_SAMPLE_NUM 64
#define AV_DRM_MAX_DRM_UUID_LEN 16
#define AV_DRM_MAX_DRM_PSSH_LEN 2048
#define AV_DRM_UUID_OFFSET (12)
typedef enum {
AV_DRM_ALG_CENC_UNENCRYPTED = 0x0,
AV_DRM_ALG_CENC_AES_CTR = 0x1,
AV_DRM_ALG_CENC_AES_WV = 0x2,
AV_DRM_ALG_CENC_AES_CBC = 0x3,
AV_DRM_ALG_CENC_SM4_CBC = 0x4,
AV_DRM_ALG_CENC_SM4_CTR,
} AV_DrmCencAlgorithm;
struct _AV_DrmSubSample {
uint32_t clear_header_len;
uint32_t pay_load_len;
};
typedef struct _AV_DrmSubSample AV_DrmSubSample;
struct _AV_DrmCencInfo {
AV_DrmCencAlgorithm algo;
uint8_t key_id[AV_DRM_KEY_ID_SIZE];
uint32_t key_id_len;
uint8_t iv[AV_DRM_IV_SIZE];
uint32_t iv_len;
uint32_t is_ambiguity;
uint32_t encrypt_blocks;
uint32_t skip_blocks;
uint32_t first_encrypt_offset;
AV_DrmSubSample sub_sample[AV_DRM_MAX_SUB_SAMPLE_NUM];
uint32_t sub_sample_num;
};
typedef struct _AV_DrmCencInfo AV_DrmCencInfo;
struct _AV_DrmInfo {
AV_DrmCencAlgorithm algo;
uint32_t encrypt_blocks;
uint32_t skip_blocks;
uint32_t uuid_len;
uint8_t uuid[AV_DRM_MAX_DRM_UUID_LEN];
uint32_t pssh_len;
uint8_t pssh[AV_DRM_MAX_DRM_PSSH_LEN];
};
typedef struct _AV_DrmInfo AV_DrmInfo;
#endif
typedef struct AVSubsampleEncryptionInfo {
/** The number of bytes that are clear. */
unsigned int bytes_of_clear_data;
@ -166,6 +216,10 @@ AVEncryptionInfo *av_encryption_info_get_side_data(const uint8_t *side_data, siz
uint8_t *av_encryption_info_add_side_data(
const AVEncryptionInfo *info, size_t *side_data_size);
#ifdef OHOS_DRM
AV_DrmCencInfo *av_encryption_info_add_side_data_ex(
const AVEncryptionInfo *info, size_t *side_data_size, AV_DrmCencInfo *cenc_info);
#endif
/**
* Allocates an AVEncryptionInitInfo structure and sub-pointers to hold the