Skip to content

Commit

Permalink
Support widevine
Browse files Browse the repository at this point in the history
Co-authored-by: zhangyichix <[email protected]>

Signed-off-by: Nana Zhang <[email protected]>
Signed-off-by: zhangyichix <[email protected]>
  • Loading branch information
nanazhan committed Jan 21, 2025
1 parent 7605046 commit b59f9d0
Show file tree
Hide file tree
Showing 19 changed files with 916 additions and 7 deletions.
8 changes: 8 additions & 0 deletions _studio/mfx_lib/decode/h264/src/mfx_h264_dec_decode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1209,6 +1209,8 @@ mfxStatus VideoDECODEH264::DecodeFrameCheck(mfxBitstream *bs, mfxFrameSurface1 *
}
#endif // MFX_ENABLE_PROTECT

// MFX_CHECK((bs->DataFlag & MFX_BITSTREAM_COMPLETE_FRAME), MFX_ERR_UNSUPPORTED);

try
{
bool force = false;
Expand All @@ -1225,6 +1227,12 @@ mfxStatus VideoDECODEH264::DecodeFrameCheck(mfxBitstream *bs, mfxFrameSurface1 *
src.SetExtBuffer(extbuf);
}

extbuf = (bs) ? GetExtendedBuffer(bs->ExtParam, bs->NumExtParam, MFX_EXTBUFF_DECRYPT_CONFIG) : NULL;
if (extbuf)
{
src.SetEncryptedStream(extbuf);
}

for (;;)
{
umcRes = m_pH264VideoDecoder->AddSource(bs ? &src : 0);
Expand Down
1 change: 1 addition & 0 deletions _studio/mfx_lib/shared/include/mfx_common_decode_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class MFXMediaDataAdapter : public UMC::MediaData
void Save(mfxBitstream *pBitstream);

void SetExtBuffer(mfxExtBuffer*);
void SetEncryptedStream(mfxExtBuffer*);
};

mfxStatus ConvertUMCStatusToMfx(UMC::Status status);
Expand Down
21 changes: 21 additions & 0 deletions _studio/mfx_lib/shared/src/mfx_common_decode_int.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,27 @@ void MFXMediaDataAdapter::SetExtBuffer(mfxExtBuffer* extbuf)
SetAuxInfo(extbuf, extbuf->BufferSz, extbuf->BufferId);
}

void MFXMediaDataAdapter::SetEncryptedStream(mfxExtBuffer* extbuf)
{
if (extbuf)
{
SetAuxInfo(extbuf, extbuf->BufferSz, extbuf->BufferId);
// set encrypted ranges
mfxExtDecryptConfig* decryptConfig = reinterpret_cast<mfxExtDecryptConfig*>(extbuf);
UMC::Ranges<const mfxU8*> encryptedRanges;
const mfxU8* start = (uint8_t *)GetDataPointer();
const mfxU8* stream_end = start + GetDataSize();
for (size_t i = 0; i < decryptConfig->num_subsamples; ++i)
{
start += decryptConfig->subsamples[i].clear_bytes;
const mfxU8* end = std::min(start + decryptConfig->subsamples[i].cypher_bytes, stream_end);
encryptedRanges.Add(start, end);
start = end;
}
SetEncryptedRanges(encryptedRanges);
}
}

mfxStatus ConvertUMCStatusToMfx(UMC::Status status)
{
switch((UMC::eUMC_VA_Status)status)
Expand Down
9 changes: 9 additions & 0 deletions _studio/shared/umc/codec/h264_dec/include/umc_h264_nal_spl.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "umc_h264_dec_defs_dec.h"
#include "umc_media_data_ex.h"
#include "umc_h264_heap.h"
#include "mfxstructures.h"

namespace UMC
{
Expand Down Expand Up @@ -85,6 +86,14 @@ class NalUnit : public MediaData

int m_nal_unit_type;
bool m_use_external_memory;

void GetCurrentSubsamples(MediaData *pSource);
mfxExtDecryptConfig* DecryptConfig() { return m_decryptConfig; }
std::vector<SubsampleEntry> Subsamples() { return m_subsamples; }
private:
mfxExtDecryptConfig *m_decryptConfig = NULL;
std::vector<SubsampleEntry> m_subsamples;

};

class SwapperBase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,25 @@ class H264Slice : public HeapObject
// Obtain first MB number
int32_t GetFirstMBNumber(void) const {return m_iFirstMBFld;}
int32_t GetStreamFirstMB(void) const {return m_iFirstMB;}

const mfxExtDecryptConfig& GetDecryptConfig(void) {return m_decryptConfig;}
void SetDecryptConfig(mfxExtDecryptConfig* decryptConfig) {
if (decryptConfig)
{
m_decryptConfig.encryption_scheme = decryptConfig->encryption_scheme;
std::memcpy(m_decryptConfig.hw_key_id, decryptConfig->hw_key_id, 16);
std::memcpy(m_decryptConfig.iv, decryptConfig->iv, 16);
m_decryptConfig.session = decryptConfig->session;
}
else
{
memset(&m_decryptConfig, 0, sizeof(m_decryptConfig));
}

}
const std::vector<SubsampleEntry>& GetSubsamples() {return m_subsamples;}
void SetSubsamples(const std::vector<SubsampleEntry>& subsamples) {m_subsamples = subsamples;}

void SetFirstMBNumber(int32_t x) {m_iFirstMB = x;}
// Obtain MB width
int32_t GetMBWidth(void) const {return m_iMBWidth;}
Expand Down Expand Up @@ -238,6 +257,9 @@ class H264Slice : public HeapObject
MemoryAllocator *m_pMemoryAllocator; // (MemoryAllocator *) pointer to memory allocation tool

H264_Heap_Objects *m_pObjHeap;

mfxExtDecryptConfig m_decryptConfig;
std::vector<SubsampleEntry> m_subsamples;
};

inline
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ class PackerVA

void FillFrameAsInvalid(VAPictureH264 * pic);

void SetupDecryptDecode(H264Slice *pSlice, VAEncryptionParameters* crypto_params, std::vector<VAEncryptionSegmentInfo>* segments, size_t nalusize);
void PackEncryptedParams(VAEncryptionParameters* crypto_params);

#ifndef MFX_DEC_VIDEO_POSTPROCESS_DISABLE
void PackProcessingInfo(H264DecoderFrameInfo * sliceInfo);
#endif
Expand All @@ -125,6 +128,10 @@ class PackerVA
int32_t PackSliceParams(H264Slice *pSlice, int32_t sliceNum, int32_t chopping, int32_t numSlicesOfPrevField);

void PackQmatrix(const UMC_H264_DECODER::H264ScalingPicParams * scaling);

private:
VAEncryptionParameters crypto_params_;
std::vector<VAEncryptionSegmentInfo> encryption_segment_info_;
};


Expand Down
60 changes: 56 additions & 4 deletions _studio/shared/umc/codec/h264_dec/src/umc_h264_nal_spl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#if defined (MFX_ENABLE_H264_VIDEO_DECODE)

#include <vector>
#include "umc_structures.h"
#include "umc_decrypt.h"
#include "umc_h264_nal_spl.h"
#include "mfx_utils_logging.h"

Expand Down Expand Up @@ -151,8 +151,8 @@ class StartCodeIterator : public StartCodeIteratorBase
return -1;

int32_t startCodeSize;

int32_t iCodeNext = FindStartCode(source, size, startCodeSize);
const Ranges<const uint8_t*>& encryptedRanges = pSource->GetEncryptedRanges();
int32_t iCodeNext = FindStartCodeInClearRanges(source, size, startCodeSize, encryptedRanges);

if (m_prev.size())
{
Expand Down Expand Up @@ -198,7 +198,7 @@ class StartCodeIterator : public StartCodeIteratorBase
pSource->MoveDataPointer((int32_t)(source - (uint8_t *)pSource->GetDataPointer() - startCodeSize));

int32_t startCodeSize1;
iCodeNext = FindStartCode(source, size, startCodeSize1);
iCodeNext = FindStartCodeInClearRanges(source, size, startCodeSize1, encryptedRanges);

pSource->MoveDataPointer(startCodeSize);

Expand Down Expand Up @@ -280,6 +280,45 @@ class StartCodeIterator : public StartCodeIteratorBase
int32_t m_code;
double m_pts;

int32_t FindStartCodeInClearRanges(uint8_t * (&pb), size_t & size, int32_t & startCodeSize, const Ranges<const uint8_t*>& encryptedRanges)
{
if (encryptedRanges.size() == 0)
return FindStartCode(pb, size, startCodeSize);

uint8_t* pbEnd = pb + size;
int32_t iCodeNext = -1;
uint8_t* start = pb;
int32_t startCodeSize1;
size_t bytesLeft;
do {
bytesLeft = size - (start - pb);
iCodeNext = FindStartCode(start, bytesLeft, startCodeSize1);
if (iCodeNext == -1) {
pb = start;
size = bytesLeft;
startCodeSize = startCodeSize1;
return -1;
}
const uint8_t* startCode = start - startCodeSize1;
const uint8_t* startCodeEnd = start;
Ranges<const uint8_t*> startCodeRange;
startCodeRange.Add(startCode, startCodeEnd + 1);

if (encryptedRanges.IntersectionWith(startCodeRange).size() > 0) {
// The start code is inside an encrypted section so we need to scan
// for another start code.
startCodeSize1 = 0;
start = std::min(start - startCodeSize1 + 1, pbEnd);
}

} while (startCodeSize1 == 0);

pb = start;
size = bytesLeft;
startCodeSize = startCodeSize1;
return iCodeNext;
}

int32_t FindStartCode(uint8_t * (&pb), size_t & size, int32_t & startCodeSize)
{
uint32_t zeroCount = 0;
Expand Down Expand Up @@ -391,6 +430,18 @@ class Swapper : public SwapperBase
}
};

void NalUnit::GetCurrentSubsamples(MediaData *pSource)
{
MediaData::AuxInfo* aux = (pSource) ? pSource->GetAuxInfo(MFX_EXTBUFF_DECRYPT_CONFIG) : NULL;
m_decryptConfig = (aux) ? reinterpret_cast<mfxExtDecryptConfig*>(aux->ptr) : NULL;

Ranges<const uint8_t*> naluRange;
Ranges<const uint8_t*> encryptedRanges = pSource->GetEncryptedRanges();
naluRange.Add((const uint8_t*)GetDataPointer(), (const uint8_t*)GetDataPointer() + GetDataSize());
auto intersection = encryptedRanges.IntersectionWith(naluRange);
m_subsamples = EncryptedRangesToSubsampleEntry(naluRange.start(0), naluRange.end(0), intersection);
}

NALUnitSplitter::NALUnitSplitter()
: m_pSwapper(0)
, m_pStartCodeIter(0)
Expand Down Expand Up @@ -447,6 +498,7 @@ NalUnit * NALUnitSplitter::GetNalUnits(MediaData * pSource)
return 0;
}

m_nalUnit.GetCurrentSubsamples(pSource);
m_nalUnit.m_nal_unit_type = iCode;

/*static int k = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3448,6 +3448,8 @@ H264Slice * TaskSupplier::DecodeSliceHeader(NalUnit *nalUnit)
}
pSlice->SetHeap(&m_ObjHeap);
pSlice->IncrementReference();
pSlice->SetDecryptConfig(nalUnit->DecryptConfig());
pSlice->SetSubsamples(nalUnit->Subsamples());

notifier0<H264Slice> memory_leak_preventing_slice(pSlice, &H264Slice::DecrementReference);

Expand Down
85 changes: 85 additions & 0 deletions _studio/shared/umc/codec/h264_dec/src/umc_h264_va_packer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include "umc_va_linux.h"
#include "umc_va_video_processing.h"
#include "umc_decrypt.h"

#include "mfx_common_int.h"
#include "mfx_ext_buffers.h"
Expand Down Expand Up @@ -689,9 +690,90 @@ int32_t PackerVA::PackSliceParams(H264Slice *pSlice, int32_t sliceNum, int32_t c
}
TRACE_BUFFER_EVENT(VA_TRACE_API_AVC_SLICEPARAMETER_TASK, EVENT_TYPE_INFO, TR_KEY_DECODE_SLICEPARAM,
pSlice_H264, H264DecodeSliceParam, SLICEPARAM_AVC);

SetupDecryptDecode(pSlice, &crypto_params_, &encryption_segment_info_, NalUnitSize);
return partial_data;
}

void PackerVA::SetupDecryptDecode(H264Slice *pSlice, VAEncryptionParameters* crypto_params, std::vector<VAEncryptionSegmentInfo>* segments, size_t nalusize)
{
const mfxExtDecryptConfig& decryptConfig = pSlice->GetDecryptConfig();
const std::vector<SubsampleEntry>& subsamples = pSlice->GetSubsamples();

size_t offset = 0;
for (const auto& segment : *segments)
offset += segment.segment_length;

if (decryptConfig.encryption_scheme == EncryptionScheme::kUnencrypted) {
crypto_params->encryption_type = VA_ENCRYPTION_TYPE_SUBSAMPLE_CTR;
VAEncryptionSegmentInfo segment_info = {};
segment_info.segment_start_offset = offset;
segment_info.segment_length = segment_info.init_byte_length = nalusize;
segments->emplace_back(std::move(segment_info));
crypto_params->num_segments++;
crypto_params->segment_info = &segments->front();
return;
}

m_va->DecryptCTR(decryptConfig, crypto_params);

crypto_params->num_segments += subsamples.size();

const bool ctr = (decryptConfig.encryption_scheme == EncryptionScheme::kCenc);
if (ctr)
{
crypto_params->encryption_type = VA_ENCRYPTION_TYPE_SUBSAMPLE_CTR;
}
else
{
crypto_params->encryption_type = VA_ENCRYPTION_TYPE_SUBSAMPLE_CBC;
}

size_t total_cypher_size = 0;
std::vector<uint8_t> iv(kDecryptionKeySize);
iv.assign(decryptConfig.iv, decryptConfig.iv + kDecryptionKeySize);

for (const auto& entry : subsamples)
{
VAEncryptionSegmentInfo segment_info = {};
segment_info.segment_start_offset = offset;
segment_info.segment_length = entry.clear_bytes + entry.cypher_bytes;
memcpy(segment_info.aes_cbc_iv_or_ctr, iv.data(), kDecryptionKeySize);
if (ctr)
{
size_t partial_block_size = (kDecryptionKeySize - (total_cypher_size % kDecryptionKeySize)) % kDecryptionKeySize;
segment_info.partial_aes_block_size = partial_block_size;
if (entry.cypher_bytes > partial_block_size) {
// If we are finishing a block, increment the counter.
if (partial_block_size)
ctr128_inc64(iv.data());
// Increment the counter for every complete block we are adding.
for (size_t block = 0;
block < (entry.cypher_bytes - partial_block_size) / kDecryptionKeySize;
++block)
ctr128_inc64(iv.data());
}
total_cypher_size += entry.cypher_bytes;
}
segment_info.init_byte_length = entry.clear_bytes;
offset += entry.clear_bytes + entry.cypher_bytes;
segments->emplace_back(std::move(segment_info));
}

crypto_params->key_blob_size = kDecryptionKeySize;
crypto_params->segment_info = &segments->front();
}

void PackerVA::PackEncryptedParams(VAEncryptionParameters* crypto_params)
{
UMCVACompBuffer *encryptionParameterBuffer;
VAEncryptionParameters* pCrypto = (VAEncryptionParameters*)m_va->GetCompBuffer(VAEncryptionParameterBufferType, &encryptionParameterBuffer, sizeof(VAEncryptionParameters));
if (!pCrypto)
throw h264_exception(UMC_ERR_FAILED);
memcpy(pCrypto, crypto_params, sizeof(VAEncryptionParameters));
encryptionParameterBuffer->SetDataSize(sizeof(VAEncryptionParameters));
}

#ifndef MFX_DEC_VIDEO_POSTPROCESS_DISABLE
void PackerVA::PackProcessingInfo(H264DecoderFrameInfo * sliceInfo)
{
Expand Down Expand Up @@ -797,6 +879,8 @@ void PackerVA::PackAU(const H264DecoderFrame *pFrame, int32_t isTop)

for ( ; first_slice < count_all; )
{
encryption_segment_info_.clear();
memset(&crypto_params_, 0, sizeof(crypto_params_));
PackPicParams(sliceInfo, slice);

CreateSliceParamBuffer(sliceInfo);
Expand Down Expand Up @@ -830,6 +914,7 @@ void PackerVA::PackAU(const H264DecoderFrame *pFrame, int32_t isTop)
if (m_va->GetVideoProcessingVA())
PackProcessingInfo(sliceInfo);
#endif
PackEncryptedParams(&crypto_params_);

Status sts = m_va->Execute();
if (sts != UMC_OK)
Expand Down
Loading

0 comments on commit b59f9d0

Please sign in to comment.