ffmpeg中添加音视频解密算法

ffmpeg中添加音视频解密算法

主要代码

ffmpeg的框架很庞大,这次主要关注点是文件初始数据流的提取传输和解密操作,不涉及音视频解码的具体流程

private_protocol

在IYInitPrivateProtocolGlobalInfo中初始化各种接口

static void IYInitPrivateProtocolGlobalInfo(PRIVATE_PROTOCOL_INFO *pPrivateProtocolInfo)
{
	if (!pPrivateProtocolInfo)
	{
		return;
	}

	if (gpPrivateProtocolGlobalInfo)
	{
		gpPrivateProtocolGlobalInfo->sPrivateProtocolInfoList.AddData(pPrivateProtocolInfo);
		LOGMSG(DBG_LEVEL_I, "InitPrivateProtocolGlobalInfo, add protocol %x, total count=%d.\n",
			pPrivateProtocolInfo,
			gpPrivateProtocolGlobalInfo->sPrivateProtocolInfoList.GetCount());
		return;
	}

	gpPrivateProtocolGlobalInfo = new PRIVATE_PROTOCOL_GLOBALINFO;
	gpPrivateProtocolGlobalInfo->pDataOperatorDll = NULL;
	gpPrivateProtocolGlobalInfo->sPrivateProtocolInfoList.AddData(pPrivateProtocolInfo);
	LOGMSG(DBG_LEVEL_I, "InitPrivateProtocolGlobalInfo, add protocol %x, total count=%d.\n",
		pPrivateProtocolInfo,
		gpPrivateProtocolGlobalInfo->sPrivateProtocolInfoList.GetCount());

	InitSysLibCodeConvert();
	InitSysLibCURL();
	
	gpPrivateProtocolGlobalInfo->pfnCheckProtocol =CheckFileProtocol;
	if (!gpPrivateProtocolGlobalInfo->pfnCheckProtocol)
	{
		LOGMSG(DBG_LEVEL_I, "protocol  %x miss DataOperator_CheckFileProtocol function.\n",pPrivateProtocolInfo);
		return;
	}


	gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_Open =
		IY_DataOperator_Access_Open;
	gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_Close =
		IY_DataOperator_Access_Close;
	gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_GetBlockSize =
		IY_DataOperator_Access_GetBlockSize;
	gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_GetCacheBlockCount =
		IY_DataOperator_Access_GetCacheBlockCount;
	gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_GetRetainBlockCount =
		IY_DataOperator_Access_GetRetainBlockCount;
	gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_GetFileSize =
		IY_DataOperator_Access_GetFileSize;
	gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_ReadBuffer =
		IY_DataOperator_Access_ReadBuffer;
	gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_ReadOneBlock =
		IY_DataOperator_Access_ReadOneBlock;
	gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_SupportReadRandom =
		IY_DataOperator_Access_SupportReadRandom;
	gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_CancelRead =
		IY_DataOperator_Access_CancelRead;
	gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_EnableSlowRead =
		IY_DataOperator_Access_EnableSlowRead;
	gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_GetReadSpeedKBPS =
		IY_DataOperator_Access_GetReadSpeedKBPS;

	gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sProcessInfo.pfn_SO_P_Init =
		IY_DataOperator_Process_Init;
	gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sProcessInfo.pfn_SO_P_Deinit =
		IY_DataOperator_Process_Deinit;
	gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sProcessInfo.pfn_SO_P_BufferPostCallback =
		IY_DataOperator_Process_BufferPostCallback;
}

在PRIVATE_PROTOCOL_Open函数中调用

int32_t PRIVATE_PROTOCOL_Open(const char *pszUrl, int eFlag, void **pUrlHandle)
{
	LOGMSG(DBG_LEVEL_I, "%s: url=%s, flag=%d", __PRETTY_FUNCTION__, pszUrl, eFlag);
	//ALOGD("PRIVATE_PROTOCOL_Open enter");

    if (NULL == pszUrl || NULL == pUrlHandle)
    {
        LOGMSG(DBG_LEVEL_I, "%s: invalid param\n", __PRETTY_FUNCTION__);
        return WSD_FAILURE;
    }

    const char *p = strcasestr(pszUrl, PRIVATE_PROTOCOL);
    if (NULL == p)
    {
        LOGMSG(DBG_LEVEL_I, "%s: not support url\n", __PRETTY_FUNCTION__);
        return WSD_FAILURE;
    }

    p = p + strlen(PRIVATE_PROTOCOL);
    LOGMSG(DBG_LEVEL_I, "%s: real url is: %s \n", __PRETTY_FUNCTION__, p);

    PRIVATE_PROTOCOL_INFO *pPrivateProtocolInfo = new PRIVATE_PROTOCOL_INFO;
    if (NULL == pPrivateProtocolInfo)
    {
        LOGMSG(DBG_LEVEL_I, "%s: malloc private protocol info fail\n", __PRETTY_FUNCTION__);
        return WSD_FAILURE;
    }
    pPrivateProtocolInfo->sDataStreamReader = new CSTBDataStreamReader();
    if (NULL == pPrivateProtocolInfo->sDataStreamReader)
    {
        LOGMSG(DBG_LEVEL_I, "%s: malloc sDataStreamReader info fail\n", __PRETTY_FUNCTION__);
        return WSD_FAILURE;
    }

    pPrivateProtocolInfo->sDataCatchBuffer = new CDataCacheBuffer();
    if (NULL == pPrivateProtocolInfo->sDataCatchBuffer)
    {
        LOGMSG(DBG_LEVEL_I, "%s: malloc sDataCatchBuffer info fail\n", __PRETTY_FUNCTION__);
        return WSD_FAILURE;
    }
    
	//调用IYInitPrivateProtocolGlobalInfo
	IYInitPrivateProtocolGlobalInfo(pPrivateProtocolInfo);

	if (gpPrivateProtocolGlobalInfo)
	{
		// check if this file is supported
		const char* cRemoveProtocolFileName = gpPrivateProtocolGlobalInfo->pfnCheckProtocol(p);
		if (cRemoveProtocolFileName)
		{
			p = cRemoveProtocolFileName;
		    LOGMSG(DBG_LEVEL_I, "%s: real cFilename is: %s \n", __PRETTY_FUNCTION__, p);
			pPrivateProtocolInfo->sDataStreamReader->SetDataOperatorAccessFunction(
				gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_Open,
				gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_Close,
				gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_GetBlockSize,
				gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_GetCacheBlockCount,
				gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_GetRetainBlockCount,
				gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_GetFileSize,
				gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_ReadBuffer,
				gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_ReadOneBlock,
				gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_SupportReadRandom,
				gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_CancelRead,
				gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_EnableSlowRead,
				gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sAccessInfo.pfn_SO_A_GetReadSpeedKBPS);
			pPrivateProtocolInfo->sDataStreamReader->SetDataOperatorProcessFunction(
				gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sProcessInfo.pfn_SO_P_Init,
				gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sProcessInfo.pfn_SO_P_Deinit,
				gpPrivateProtocolGlobalInfo->sDataOperatorEntry.sProcessInfo.pfn_SO_P_BufferPostCallback);
		}
	}

    if (!pPrivateProtocolInfo->sDataStreamReader->Open(
			pPrivateProtocolInfo->sDataCatchBuffer,
			"",
			p,
			FALSE,
			0,
			""))
    {
        LOGMSG(DBG_LEVEL_I, "%s: file open fail\n", __PRETTY_FUNCTION__);       

		DeInitPrivateProtocolGlobalInfo(pPrivateProtocolInfo);

		delete pPrivateProtocolInfo->sDataStreamReader;
		pPrivateProtocolInfo->sDataStreamReader = NULL;
		delete pPrivateProtocolInfo->sDataCatchBuffer;
		pPrivateProtocolInfo->sDataCatchBuffer = NULL;
		delete pPrivateProtocolInfo; 
		pPrivateProtocolInfo = NULL;

		*pUrlHandle = NULL;
        return WSD_FAILURE;
    }
	else
    {
		pPrivateProtocolInfo->bHasReadError = FALSE;
		pPrivateProtocolInfo->cbArgs.pfnCallback = NULL;
		pPrivateProtocolInfo->cbArgs.userdata = NULL;
		*pUrlHandle = (void *)pPrivateProtocolInfo;
		LOGMSG(DBG_LEVEL_I, "%s: file open success %p\n", __PRETTY_FUNCTION__, pPrivateProtocolInfo);       
		return WSD_SUCCESS;
	}
}

IYDataOperator

IYDataOperator.h

#pragma once

#include "BaseLock.h"
#include "PtrControl.h"
#include "FileOperator.h"
#include "IYDecrypt.h"
#include "OSKVideoDecrypt.h"
#include "HttpFileClient.h"
#include "BasePlayer.h"
#include "dataoperator_def.h"

class IYDataOperator
{
public:
	IYDataOperator();
	~IYDataOperator();

public:
	BOOL Open(
		const char* cServerName,
		const char* cFileName,
		BOOL bIsPreview,
		int nOSKDecryptType,
		const char* cSTBDecryptOEMID);

	void Close();

	UINT32 GetBlockSize();
	UINT32 GetCacheBlockCount();
	UINT32 GetRetainBlockCount();

	UINT64 GetFileSize();

	size_t ReadBuffer(
		UINT64 uFromPos,
		BYTE *pBuffer,
		size_t nBufLen,
		UINT64 uTimeout,
		BOOL bUseContinueRead);

	UINT32 ReadOneBlock(
		BYTE **ppWorkingBuffer,
		UINT32 uBlockIndex,
		UINT32 uBlockSize,
		BOOL bLastBlock,
		UINT64 uTimeout,
		BOOL bUseContinueRead);

	BOOL SupportReadRandom();

	void CancelRead();
	void EnableSlowRead(
		BOOL bEnableSlowRead);

	float GetReadSpeedKBPS();

private:
	size_t ReadBufferNoDecrypt(
		UINT64 uFromPos,
		BYTE *pBuffer,
		size_t nBufLen,
		UINT64 uTimeout,
		BOOL bUseContinueRead);

private:
	UINT64 mFileSize;
	UINT32 mBlockSize;
	UINT32 mCacheBlockCount;
	UINT32 mRetainBlockCount;

	BUFFER_FILE_TYPE mBufferFileType;
	int mOSKDecryptType;

	BYTE *mpWorkingBuffer;
	float mRealTimeReadSpeedKBPS;

private:
	CHttpFileClient mHttpFile;
	FILE *mpLocalFile;
	BOOL mCancelRead;
	BOOL mEnableSlowRead;

	CIYDecrypt mIYDecrypt;
	COSKVideoDecrypt mOSKVideoDecrypt;
	BYTE *mpDecryptBuffer;
};

void* IY_DataOperator_Access_Open(
	const char* cServerName,
	const char* cFileName,
	BOOL bIsPreview,
	int nDecryptType,
	const char* cOEMID);
void IY_DataOperator_Access_Close(
	void* pHandle);
UINT32 IY_DataOperator_Access_GetBlockSize(
	void* pHandle);
UINT32 IY_DataOperator_Access_GetCacheBlockCount(
	void* pHandle);
UINT32 IY_DataOperator_Access_GetRetainBlockCount(
	void* pHandle);
UINT64 IY_DataOperator_Access_GetFileSize(
	void* pHandle);
ssize_t IY_DataOperator_Access_ReadBuffer(
	void* pHandle,
	UINT64 uFromPos,
	BYTE *pBuffer,
	size_t nBufLen,
	UINT64 uTimeout,
	BOOL bUseContinueRead);
UINT32 IY_DataOperator_Access_ReadOneBlock(
	void* pHandle,
	BYTE **ppWorkingBuffer,
	UINT32 uBlockIndex,
	UINT32 uBlockSize,
	BOOL bLastBlock,
	UINT64 uTimeout,
	BOOL bUseContinueRead);
BOOL IY_DataOperator_Access_SupportReadRandom(
	void* pHandle);
void IY_DataOperator_Access_CancelRead(
	void* pHandle);
void IY_DataOperator_Access_EnableSlowRead(
	void* pHandle,
	BOOL bEnableSlowRead);
float IY_DataOperator_Access_GetReadSpeedKBPS(
	void* pHandle);

void* IY_DataOperator_Process_Init(
	void* pHandle);
void IY_DataOperator_Process_Deinit(
	void* pHandle,
	void *pUserData);
void IY_DataOperator_Process_BufferPostCallback(
	void* pHandle,
	void *pUserData,
	UINT64 uDataPos,
	BYTE *pBuffer,
	UINT32 nBufLen);
const char* CheckFileProtocol(const char* cFileName);

IYDataOperator.cpp

#include "IYDataOperator.h"
#include <errno.h>
#include <signal.h>
#include "commfunc.h"
#include "DbgOutput.h"
#include "FileOperator.h"
#include <stdio.h>   
#include <stdlib.h>   
#include <unistd.h> 

// read block size 是每次实际read的size,越大则中断read的耗时越大
#define STBSTREAM_HTTP_READ_BLOCKSIZE 	(32*SIZE_1K)
#define STBSTREAM_NORMAL_READ_BLOCKSIZE (512*SIZE_1K)

// 奥斯卡解密一个 Block 需要 2.5M, 4 个 block,一共10M,
#define DECRYPT_TOTAL_BLOCK_COUNT 		4
#ifdef HISI3719C
// 海思3719C在切换原伴唱的时候会往前seek一段,保留部分buffer会加速seek
#define DECRYPT_RETAIN_BLOCK_COUNT 	0
#else
#define DECRYPT_RETAIN_BLOCK_COUNT 	0
#endif
#define DECRYPT_BLOCK_SIZE (5*512*SIZE_1K)

// 网络版本一个Block 需要 512K, 20 个 block,一共10M,
// 网络版本,一般是buffer越大,在网速越快的环境下优势越明显
// 但如果在低速网络下,buffer越大,可能造成的浪费就越明显
#define HTTP_TOTAL_BLOCK_COUNT 		20
#ifdef HISI3719C
// 海思3719C在切换原伴唱的时候会往前seek一段,保留部分buffer会加速seek
#define HTTP_RETAIN_BLOCK_COUNT		0
#else
#define HTTP_RETAIN_BLOCK_COUNT		0
#endif
#define HTTP_BLOCK_SIZE (512*SIZE_1K)

// 本地文件一个Block 需要 512K, 20 个 block,一共10M
#define NORMAL_TOTAL_BLOCK_COUNT 	20
#ifdef HISI3719C
// 海思3719C在切换原伴唱的时候会往前seek一段,保留部分buffer会加速seek
#define NORMAL_RETAIN_BLOCK_COUNT		0
#else
#define NORMAL_RETAIN_BLOCK_COUNT		0
#endif
#define NORMAL_BLOCK_SIZE (512*SIZE_1K)


IYDataOperator::IYDataOperator()
{
	mBufferFileType = BufferFileType_File;
	mCancelRead = FALSE;
	mEnableSlowRead = TRUE;

	mpLocalFile = NULL;
	mRealTimeReadSpeedKBPS = 0.0;

	mFileSize = 0;
	mBlockSize = 0;
	mCacheBlockCount = 0;
	mRetainBlockCount = 0;

	mOSKDecryptType = 0;

	mpWorkingBuffer = NULL;
	mpDecryptBuffer = NULL;
}

IYDataOperator::~IYDataOperator()
{
}

BOOL IYDataOperator::Open(
	const char* cServerName,
	const char* cFileName,
	BOOL bIsPreview,
	int nOSKDecryptType,
	const char* cSTBDecryptOEMID)
{
	Close();

	LOGMSG(DBG_LEVEL_D, "%s +++\n", __PRETTY_FUNCTION__);

	BOOL bOpenOK = FALSE;

	mCancelRead = FALSE;
	mOSKDecryptType = nOSKDecryptType;

	do
	{
		if ((strncasecmp(cFileName, "http://", 7) == 0)||
			(strncasecmp(cFileName, "https://", 8) == 0))
		{
			if (!mHttpFile.OpenFile(cFileName))
			{
				LOGMSG(DBG_LEVEL_E, "open http file %s failed\n", cFileName);
				break;
			}
			LOGMSG(DBG_LEVEL_I, "open HttpFile file %s success\n", cFileName);

			mFileSize = mHttpFile.GetFileSize();
			mBufferFileType = BufferFileType_Http;
			mEnableSlowRead = FALSE;
		}
		else
		{
			mpLocalFile = fopen(cFileName, "rb");
			//LOGMSG(DBG_LEVEL_I, "open local file %s success\n", cFileName);
			if (!mpLocalFile)
			{
				LOGMSG(DBG_LEVEL_E, "open local file %s failed, error=%s\n", cFileName, strerror(errno));
				break;
			}
		
			fseeko64(mpLocalFile, 0, SEEK_END);
			INT64 lFilePos = ftello64(mpLocalFile);
			if (lFilePos < 0)
			{
				mFileSize = 0;
			}
			else
			{
				mFileSize = (UINT64)lFilePos;
			}
			fseeko64(mpLocalFile, 0, SEEK_SET);
			mBufferFileType = BufferFileType_File;
			mEnableSlowRead = TRUE;
		}

		if (mFileSize == 0)
		{
			LOGMSG(DBG_LEVEL_E, "local file %s has no data\n", cFileName);
			break;
		}

		LOGMSG(DBG_LEVEL_D, "%s, mFileSize=%lld\n", __PRETTY_FUNCTION__, mFileSize);

		// 检测是否是AES加密
		LOGMSG(DBG_LEVEL_D, "%s, Detect Encrypt Type\n", __PRETTY_FUNCTION__);
		mIYDecrypt.ResetEncryptType();
		mIYDecrypt.DetectLocalFileEncryptType(cFileName, cSTBDecryptOEMID);


		if ( mIYDecrypt.GetEncryptType() == IYENCRYPTTYPE_mp36)
		{
			LOGMSG(DBG_LEVEL_I, "file(%s) is encrypt as IYENCRYPTTYPE_mp36 Encode Type1\n", cFileName);

		}
		else if ( mIYDecrypt.GetEncryptType() == IYENCRYPTTYPE_li6)
		{
			LOGMSG(DBG_LEVEL_I, "file(%s) is encrypt as IYENCRYPTTYPE_li6 Encode Type1\n", cFileName);

		}
		else if ( mIYDecrypt.GetEncryptType() == IYENCRYPTTYPE_ld6)
		{
			LOGMSG(DBG_LEVEL_I, "file(%s) is encrypt as IYENCRYPTTYPE_ld6 Encode Type1\n", cFileName);

		}
		else if ( mIYDecrypt.GetEncryptType() == IYENCRYPTTYPE_vk6)
		{
			LOGMSG(DBG_LEVEL_I, "file(%s) is encrypt as IYENCRYPTTYPE_vk6 Encode Type1\n", cFileName);

		}
		else if ( mIYDecrypt.GetEncryptType() == IYENCRYPTTYPE_mvh5)
		{
			LOGMSG(DBG_LEVEL_I, "file(%s) is encrypt as IYENCRYPTTYPE_mvh5 Encode Type1\n", cFileName);

		}
		else
		{
			LOGMSG(DBG_LEVEL_I, "%s, Encrypt Type = NONE\n", __PRETTY_FUNCTION__);
		}
		
		//OSK解密

		if (mOSKDecryptType != 0)
		{
			char cDecryptName[MAX_PATH];
			sprintf(cDecryptName, "//%s/%s", cServerName, cFileName);
			char *c = strchr(cDecryptName, ':');
			if (c != NULL)
			{
				*c = '$';
			}

			mOSKVideoDecrypt.InitDecrypt(cDecryptName, mFileSize, mOSKDecryptType);
			mBlockSize = DECRYPT_BLOCK_SIZE;
			mCacheBlockCount = DECRYPT_TOTAL_BLOCK_COUNT;
			mRetainBlockCount = DECRYPT_RETAIN_BLOCK_COUNT;
		}
		else
		{

			mBlockSize = NORMAL_BLOCK_SIZE;
			mCacheBlockCount = NORMAL_TOTAL_BLOCK_COUNT;
			mRetainBlockCount = NORMAL_RETAIN_BLOCK_COUNT;

		}

		mpWorkingBuffer = new BYTE[mBlockSize];
		mpDecryptBuffer = new BYTE[mBlockSize];

		bOpenOK = TRUE;
	} while (0);

	if (!bOpenOK)
	{
		Close();
	}

	LOGMSG(DBG_LEVEL_D, "%s ---\n", __PRETTY_FUNCTION__);

	return bOpenOK;
}

void IYDataOperator::Close()
{
	LOGMSG(DBG_LEVEL_D, "%s +++\n", __PRETTY_FUNCTION__);

	if (mpLocalFile != NULL)
	{
		fclose(mpLocalFile);
		mpLocalFile = NULL;
		LOGMSG(DBG_LEVEL_I, "close local file success\n");
	}

	mHttpFile.CloseFile();

	mRealTimeReadSpeedKBPS = 0.0;

	mFileSize = 0;
	mBlockSize = 0;

	SAFE_DELETEARRAY(mpWorkingBuffer);
	SAFE_DELETEARRAY(mpDecryptBuffer);

	mIYDecrypt.ResetEncryptType();

	LOGMSG(DBG_LEVEL_D, "%s ---\n", __PRETTY_FUNCTION__);
}

UINT32 IYDataOperator::GetBlockSize()
{
	return mBlockSize;
}

UINT32 IYDataOperator::GetCacheBlockCount()
{
	return mCacheBlockCount;
}

UINT32 IYDataOperator::GetRetainBlockCount()
{
	return mRetainBlockCount;
}

UINT64 IYDataOperator::GetFileSize()
{
	return mFileSize;
}

size_t IYDataOperator::ReadBuffer(
	UINT64 uFromPos,
	BYTE *pBuffer,
	size_t nBufLen,
	UINT64 uTimeout,
	BOOL bUseContinueRead)
{
	LOGMSG(DBG_LEVEL_I, "before ReadBufferNoDecrypt, uFromPos=%d\n", uFromPos);
	UINT32 uReadSize = ReadBufferNoDecrypt(
		uFromPos,
		pBuffer,
		nBufLen,
		uTimeout,
		bUseContinueRead);
	//LOGMSG(DBG_LEVEL_I, "before mIYDecrypt.DecryptBuffer, uFromPos=%d\n", uFromPos);
	if (uReadSize > 0)
	{
		uReadSize = mIYDecrypt.DecryptBuffer(pBuffer, uReadSize, uFromPos);
		LOGMSG(DBG_LEVEL_I, "after mIYDecrypt.DecryptBuffer, uReadSize=%d\n", uReadSize);
	}

	return uReadSize;
}

UINT32 IYDataOperator::ReadOneBlock(
	BYTE **ppWorkingBuffer,
	UINT32 uBlockIndex,
	UINT32 uBlockSize,
	BOOL bLastBlock,
	UINT64 uTimeout,
	BOOL bUseContinueRead)
{
	UINT32 uReadSize = 0;
	UINT64 uFromPos = (UINT64)uBlockIndex * mBlockSize;

	// 读取数据
	if (mOSKDecryptType != 0)
	{
		uReadSize = ReadBuffer(
			uFromPos,
			mpDecryptBuffer,
			uBlockSize,
			uTimeout,
			bUseContinueRead);

		uReadSize = mOSKVideoDecrypt.DecryptBlock(
			mpDecryptBuffer,
			uBlockIndex,
			uReadSize,
			bLastBlock ? true : false,
			mpWorkingBuffer);
	}
	else
	{
		uReadSize = ReadBuffer(
			uFromPos,
			mpWorkingBuffer,
			uBlockSize,
			uTimeout,
			bUseContinueRead);
	}

	*ppWorkingBuffer = mpWorkingBuffer;

	return uReadSize;
}

BOOL IYDataOperator::SupportReadRandom()
{
	if (mOSKDecryptType != 0)
	{
		return FALSE;
	}
	else
	{
		return TRUE;
	}
}

void IYDataOperator::CancelRead()
{
	LOGMSG(DBG_LEVEL_I, "%s\n", __PRETTY_FUNCTION__);

	mCancelRead = TRUE;

	mHttpFile.CancelRead();
}

void IYDataOperator::EnableSlowRead(
	BOOL bEnableSlowRead)
{
	LOGMSG(DBG_LEVEL_I, "%s=%d\n", __PRETTY_FUNCTION__, bEnableSlowRead);
	mEnableSlowRead = bEnableSlowRead;
}

float IYDataOperator::GetReadSpeedKBPS()
{
	return mRealTimeReadSpeedKBPS;
}

size_t IYDataOperator::ReadBufferNoDecrypt(
	UINT64 uFromPos,
	BYTE *pBuffer,
	size_t nBufLen,
	UINT64 uTimeout,
	BOOL bUseContinueRead)
{
	LOGMSG(DBG_LEVEL_D, "%s +++\n", __PRETTY_FUNCTION__);

	size_t nTotalRead = 0;

	mCancelRead = FALSE;

	// 读取数据
	if (mBufferFileType == BufferFileType_Http)
	{
		mHttpFile.SeekFile(uFromPos, SEEK_SET);
	}
	else
	{
		fseeko64(mpLocalFile, uFromPos, SEEK_SET);
	}

	UINT64 uTime1 = GetTickCount();
	while ((!mCancelRead) && (nTotalRead < nBufLen))
	{
		if (mEnableSlowRead)
		{
			// 限制 5M/s = 5K/ms 的速度读取, 减少磁盘/网络IO所造成的CPU性能下降
			UINT64 uReadInterval = nTotalRead / (5*SIZE_1K);
			UINT64 uReadUsedTime = GetTickCount()-uTime1;
			if (uReadUsedTime < uReadInterval)
			{
				Sleep(uReadInterval-uReadUsedTime);
			}
		}

		size_t nNeedRead = nBufLen-nTotalRead;

		UINT32 uReadSize = 0;

		nNeedRead = Get2Min(nNeedRead, STBSTREAM_NORMAL_READ_BLOCKSIZE);
		uReadSize = FileRead(mpLocalFile, pBuffer+nTotalRead, nNeedRead);
		mRealTimeReadSpeedKBPS = 0.0;

		if (uReadSize < nNeedRead)
		{
			LOGMSG(DBG_LEVEL_D, "%s read NOT expect, expect=%d, actual=%d\n",
				__PRETTY_FUNCTION__,
				uReadSize,
				nNeedRead);
			break;
		}
		nTotalRead += uReadSize;
	}

	LOGMSG(DBG_LEVEL_D, "%s ---\n", __PRETTY_FUNCTION__);

	return nTotalRead;
}


void* IY_DataOperator_Handle_Create()
{
	IYDataOperator *pDataOperator  = new IYDataOperator();
	return pDataOperator;
}

void IY_DataOperator_Handle_Destroy(
	void *pHandle)
{
	IYDataOperator *pDataOperator  = (IYDataOperator*)pHandle;
	if (!pDataOperator)
	{
		return;
	}

	delete pDataOperator;
}		

void* IY_DataOperator_Access_Open(
	const char* cServerName,
	const char* cFileName,
	BOOL bIsPreview,
	int nOSKDecryptType,
	const char* cSTBDecryptOEMID)
{
	IYDataOperator *pDataOperator  = new IYDataOperator();
	if (!pDataOperator)
	{
		return NULL;
	}

	if (pDataOperator->Open(
		cServerName,
		cFileName,
		bIsPreview,
		nOSKDecryptType,
		cSTBDecryptOEMID))
	{
		return pDataOperator;
	}
	else
	{
		delete pDataOperator;
		return NULL;
	}
}

void IY_DataOperator_Access_Close(
	void* pHandle)
{
	IYDataOperator *pDataOperator  = (IYDataOperator*)pHandle;
	if (!pDataOperator)
	{
		return;
	}

	pDataOperator->Close();
	delete pDataOperator;
}

UINT32 IY_DataOperator_Access_GetBlockSize(
	void* pHandle)
{
	IYDataOperator *pDataOperator  = (IYDataOperator*)pHandle;
	if (!pDataOperator)
	{
		return 0;
	}

	return pDataOperator->GetBlockSize();
}

UINT32 IY_DataOperator_Access_GetCacheBlockCount(
	void* pHandle)
{
	IYDataOperator *pDataOperator  = (IYDataOperator*)pHandle;
	if (!pDataOperator)
	{
		return 0;
	}

	return pDataOperator->GetCacheBlockCount();
}

UINT32 IY_DataOperator_Access_GetRetainBlockCount(
	void* pHandle)
{
	IYDataOperator *pDataOperator  = (IYDataOperator*)pHandle;
	if (!pDataOperator)
	{
		return 0;
	}

	return pDataOperator->GetRetainBlockCount();
}

UINT64 IY_DataOperator_Access_GetFileSize(
	void* pHandle)
{
	IYDataOperator *pDataOperator  = (IYDataOperator*)pHandle;
	if (!pDataOperator)
	{
		return 0;
	}

	return pDataOperator->GetFileSize();
}

ssize_t IY_DataOperator_Access_ReadBuffer(
	void* pHandle,
	UINT64 uFromPos,
	BYTE *pBuffer,
	size_t nBufLen,
	UINT64 uTimeout,
	BOOL bUseContinueRead)
{
	IYDataOperator *pDataOperator  = (IYDataOperator*)pHandle;
	if (!pDataOperator)
	{
		return 0;
	}

	return pDataOperator->ReadBuffer(
		uFromPos,
		pBuffer,
		nBufLen,
		uTimeout,
		bUseContinueRead);
}

UINT32 IY_DataOperator_Access_ReadOneBlock(
	void* pHandle,
	BYTE **ppWorkingBuffer,
	UINT32 uBlockIndex,
	UINT32 uBlockSize,
	BOOL bLastBlock,
	UINT64 uTimeout,
	BOOL bUseContinueRead)
{
	IYDataOperator *pDataOperator  = (IYDataOperator*)pHandle;
	if (!pDataOperator)
	{
		return 0;
	}

	return pDataOperator->ReadOneBlock(
		ppWorkingBuffer,
		uBlockIndex,
		uBlockSize,
		bLastBlock,
		uTimeout,
		bUseContinueRead);
}

BOOL IY_DataOperator_Access_SupportReadRandom(
	void* pHandle)
{
	IYDataOperator *pDataOperator  = (IYDataOperator*)pHandle;
	if (!pDataOperator)
	{
		return TRUE;
	}

	return pDataOperator->SupportReadRandom();
}

void IY_DataOperator_Access_CancelRead(
	void* pHandle)
{
	IYDataOperator *pDataOperator  = (IYDataOperator*)pHandle;
	if (!pDataOperator)
	{
		return;
	}

	return pDataOperator->CancelRead();
}

void IY_DataOperator_Access_EnableSlowRead(
	void* pHandle,
	BOOL bEnableSlowRead)
{
	IYDataOperator *pDataOperator  = (IYDataOperator*)pHandle;
	if (!pDataOperator)
	{
		return;
	}

	return pDataOperator->EnableSlowRead(bEnableSlowRead);
}

float IY_DataOperator_Access_GetReadSpeedKBPS(
	void* pHandle)
{
	IYDataOperator *pDataOperator  = (IYDataOperator*)pHandle;
	if (!pDataOperator)
	{
		return 0.0;
	}

	return pDataOperator->GetReadSpeedKBPS();
}

void* IY_DataOperator_Process_Init(
	void* pHandle)
{
	return NULL;
}

void IY_DataOperator_Process_Deinit(
	void* pHandle,
	void *pUserData)
{
	return;
}

void IY_DataOperator_Process_BufferPostCallback(
	void* pHandle,
	void *pUserData,
	UINT64 uDataPos,
	BYTE *pBuffer,
	UINT32 nBufLen)
{
}

const char* CheckFileProtocol(const char* cFileName)
{
	if(access(cFileName,0)!=-1)
	{
		return cFileName;
	}
	else
	{
		return 0;
	}	
}

IYDecrypt

IYDecrypt.h

#pragma once

#include "types.h"

// ENCTYPE AAAA 加密类型:尾部20个字节为密码保存区域,
// 其中,0~3:AAAA,4~19:与文件尾16个字节异或结果
//
// ENCTYPE BBBB 加密类型:尾部36个字节为密码保存区域,
// 其中,0~15:OEMID, 16~19:BBBB, 20~35:与文件尾16个字节异或结果

typedef enum eIYENCRYPTTYPE
{
	IYENCRYPTTYPE_NONE=0,
	IYENCRYPTTYPE_mp36,
	IYENCRYPTTYPE_li6,
	IYENCRYPTTYPE_ld6,
	IYENCRYPTTYPE_vk6,
	IYENCRYPTTYPE_mvh5
} IYENCRYPTTYPE;

class CIYDecrypt
{
public:
	CIYDecrypt();
	~CIYDecrypt();

public:
	 void ResetEncryptType();
	 void DetectLocalFileEncryptType(
		const char* cFileName,
		const char* cOEMID);
	 void DetectHttpFileEncryptType(
		const char* cHttpUrl,
		const char* cOEMID);
	 void DetectBufferEncryptType(
		const BYTE pFileEndData[4096],
		const char* cOEMID);
	 IYENCRYPTTYPE GetEncryptType();

	 size_t DecryptBuffer(
		BYTE* pInOutBuf,
		size_t nBufSize,
		UINT64 uBufStartPos);

private:
	 size_t DecryptVideoBuffer(
		BYTE* pInOutBuf,
		size_t nBufSize,
		UINT64 uBufStartPos);

private:
	 IYENCRYPTTYPE mEncryptType;
	 BYTE mEncTypePassword[16];
	 enum eCRYPT_TYPE
	 {
	 CRYPT_TYPE_ALL=1,
	 CRYPT_TYPE_2=2,
	 CRYPT_TYPE_64=64
	 } mcrypt_type;
};

IYDecrypt.cpp

#include <string.h>
#include <stdio.h>
#include "DecryptKey.h"
#include "IYDecrypt.h"
#include "DbgOutput.h"
#include "commfunc.h"
#include "FileOperator.h"
#include "HttpFileClient.h"
#include <string>
#include "aes.h"

#define CRYPT_BLOCK_LEN (1024)

/**#define CRYPT_TYPE_ALL (1)
#define CRYPT_TYPE_2 (2)
#define CRYPT_TYPE_64 (64)*/

const char *mp36_key = "6sdfwmq1pu752dqh";
const char *li6_key  = "oiw93nfFEwNqt93g";
const char *ld6_key  = "dsu84jvsk2s2d2sf";
const char *vk6_key = "sdA2knD93L3dsfwj";
const char *mvh5_key = "2k6Pd9A8ak7ul4Mv";

using namespace std;

CIYDecrypt::CIYDecrypt()
{
	mEncryptType = IYENCRYPTTYPE_NONE;
	memset(mEncTypePassword, 0, 16);
}

CIYDecrypt::~CIYDecrypt()
{
}

void CIYDecrypt::ResetEncryptType()
{
	mEncryptType = IYENCRYPTTYPE_NONE;
	memset(mEncTypePassword, 0, 16);
}

void CIYDecrypt::DetectLocalFileEncryptType(
	const char* cFileName,
	const char* cOEMID)
{
	mEncryptType = IYENCRYPTTYPE_NONE;
	string suffix = cFileName;

	if (suffix.find('.mp36')!=string::npos)
	{
		mEncryptType = IYENCRYPTTYPE_mp36;
	}
	else if (suffix.find('.li6')!=string::npos)
	{
		mEncryptType = IYENCRYPTTYPE_li6;
	}
	else if (suffix.find('.ld6')!=string::npos)
	{
		mEncryptType = IYENCRYPTTYPE_ld6;
	}
	else if (suffix.find('.vk6')!=string::npos)
	{
		mEncryptType = IYENCRYPTTYPE_vk6;
	}
	else if (suffix.find('.mvh5')!=string::npos)
	{
		mEncryptType = IYENCRYPTTYPE_mvh5;
	}

}

void CIYDecrypt::DetectHttpFileEncryptType(
	const char* cHttpUrl,
	const char* cOEMID)
{
	mEncryptType = IYENCRYPTTYPE_NONE;

	CHttpFileClient mHttpFile;
	if (!mHttpFile.OpenFile(cHttpUrl))
	{
		return;
	}

	mHttpFile.SeekFile(0, SEEK_END);
	INT64 lFilePos = mHttpFile.GetFilePos();
	if (lFilePos >= 4096)
	{
		BYTE cPwdTag[4096];
		memset(cPwdTag, 0, 4096);
		// 读取尾部4096个字节做判断
		mHttpFile.SeekFile(lFilePos-4096, SEEK_SET);
		mHttpFile.ReadFile_Part(cPwdTag, 4096, 10000);
		mHttpFile.SeekFile(0, SEEK_SET);
		DetectBufferEncryptType(cPwdTag, cOEMID);
	}

	mHttpFile.CloseFile();
}

void CIYDecrypt::DetectBufferEncryptType(
	const BYTE pFileEndData[4096],
	const char* cOEMID)
{
	//Not implement
}

IYENCRYPTTYPE CIYDecrypt::GetEncryptType()
{
	return mEncryptType;
}

size_t CIYDecrypt::DecryptBuffer(
	BYTE* pInOutBuf,
	size_t nBufSize,
	UINT64 uBufStartPos)
{
	size_t nDecryptSize = nBufSize;
	UINT64 uTime1 = GetTickCount();
	//LOGMSG(DBG_LEVEL_I, "before DecryptVideoBuffer, uBufStartPos=%d\n", uBufStartPos);

	if (mEncryptType != IYENCRYPTTYPE_NONE)
	{
		nDecryptSize = DecryptVideoBuffer(
			pInOutBuf,
			nBufSize,
			uBufStartPos);
		LOGMSG(DBG_LEVEL_I, "after DecryptVideoBuffer, uBufStartPos=%d\n", uBufStartPos);
	}

	LOGMSG(DBG_LEVEL_D, "decrypt buffer(%d bytes) use time(ms):%llu\n",
		nBufSize, GetTickCount()-uTime1);

	return nDecryptSize;
}

size_t CIYDecrypt::DecryptVideoBuffer(
	BYTE* pInOutBuf,
	size_t nBufSize,
	UINT64 uBufStartPos)
{
	size_t i;
	int lyAesContentLen = 16;
    int counter = 0;
    AES_KEY key;
	//LOGMSG(DBG_LEVEL_I, "uBufStartPos=%d\n", uBufStartPos);
	if (mEncryptType == IYENCRYPTTYPE_mp36)
	{
		AES_set_decrypt_key((const unsigned char*)mp36_key,strlen(mp36_key) * 8, &key);
		mcrypt_type = CRYPT_TYPE_2;
	}
	else if (mEncryptType == IYENCRYPTTYPE_li6)
	{
		AES_set_decrypt_key((const unsigned char*)li6_key,strlen(li6_key) * 8, &key);
		mcrypt_type = CRYPT_TYPE_2;
	}
	else if (mEncryptType == IYENCRYPTTYPE_ld6)
	{
		AES_set_decrypt_key((const unsigned char*)ld6_key,strlen(ld6_key) * 8, &key);
		mcrypt_type = CRYPT_TYPE_2;
	}
	else if (mEncryptType == IYENCRYPTTYPE_vk6)
	{
		AES_set_decrypt_key((const unsigned char*)vk6_key,strlen(vk6_key) * 8, &key);
		mcrypt_type = CRYPT_TYPE_2;
	}
	else if (mEncryptType == IYENCRYPTTYPE_mvh5)
	{
		AES_set_decrypt_key((const unsigned char*)mvh5_key,strlen(mvh5_key) * 8, &key);
		mcrypt_type = CRYPT_TYPE_64;
	}

    for(i=0; i<nBufSize-(nBufSize%lyAesContentLen);i+=lyAesContentLen )
    {
        if(counter% mcrypt_type == 0)
		{
			AES_decrypt(&pInOutBuf[i],&pInOutBuf[i], &key);
			//LOGMSG(DBG_LEVEL_I, "AES_decrypt i=%d, count=%d\n", i, counter);
		}
        counter++;
    }

	return nBufSize;
}

aes

aes.h

#ifndef HEADER_AES_H
#define HEADER_AES_H

#ifdef __cplusplus
extern "C" {
#endif
#ifdef OPENSSL_NO_AES
#error AES is disabled.
#endif

#include <stddef.h>

#define AES_ENCRYPT	1
#define AES_DECRYPT	0

#define FULL_UNROLL 1

/* Because array size can't be a const in C, the following two are macros.
   Both sizes are in bytes. */
#define AES_MAXNR 14
#define AES_BLOCK_SIZE 16

/* This should be a hidden type, but EVP requires that the size be known */
struct aes_key_st {
#ifdef AES_LONG
    unsigned long rd_key[4 *(AES_MAXNR + 1)];
#else
    unsigned int rd_key[4 *(AES_MAXNR + 1)];
#endif
    int rounds;
};
typedef struct aes_key_st AES_KEY;


int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
	AES_KEY *key);
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
	AES_KEY *key);

void AES_encrypt(const unsigned char *in, unsigned char *out,
	const AES_KEY *key);
void AES_decrypt(const unsigned char *in, unsigned char *out,
	const AES_KEY *key);


/* from aes_locl.h */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
# define GETU32(p) SWAP(*((u32 *)(p)))
# define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
#else
# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] <<  8) ^ ((u32)(pt)[3]))
# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >>  8); (ct)[3] = (u8)(st); }
#endif

#ifdef AES_LONG
typedef unsigned long u32;
#else
typedef unsigned int u32;
#endif
typedef unsigned short u16;
typedef unsigned char u8;

#define MAXKC   (256/32)
#define MAXKB   (256/8)
#define MAXNR   14
#ifdef __cplusplus
}
#endif
#endif /* !HEADER_AES_H */

总结

主要工作都集中在数据流的解析,只要理清楚层次脉络,就可以实现播放音视频的同时进行算法解密。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值