📄 umc_video_processing.cpp
字号:
/*//////////////////////////////////////////////////////////////////////////////
//
// INTEL CORPORATION PROPRIETARY INFORMATION
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Intel Corporation and may not be copied
// or disclosed except in accordance with the terms of that agreement.
// Copyright(c) 2003-2007 Intel Corporation. All Rights Reserved.
//
*/
#include "umc_video_processing.h"
#include "umc_color_space_conversion.h"
#include "umc_video_resizing.h"
#include "umc_deinterlacing.h"
using namespace UMC;
namespace UMC
{
BaseCodec *createVideoProcessing()
{
return (new VideoProcessing);
}
}
VideoProcessing::VideoProcessing()
{
memset(pFilter, 0, sizeof(pFilter));
memset(bFiltering, 0, sizeof(bFiltering));
bSrcCropArea = false;
// order of filters
iDeinterlacing = 0;
iColorConv0 = 1;
iColorConv = 2;
iResizing = 3;
numFilters = 4;
// create filters
pFilter[iDeinterlacing] = new Deinterlacing;
pFilter[iColorConv0] = new ColorSpaceConversion; // first color conversion
pFilter[iColorConv] = pFilter[iColorConv0]; // second color conversion
pFilter[iResizing] = new VideoResizing;
}
#define DELETE_FILTER(filter) \
if (filter) { \
delete filter; \
filter = NULL; \
}
Status VideoProcessing::Close()
{
DELETE_FILTER(pFilter[iDeinterlacing]);
DELETE_FILTER(pFilter[iColorConv]);
DELETE_FILTER(pFilter[iResizing]);
pFilter[iColorConv0] = NULL; // duplication of iColorConv!!!
return UMC_OK;
}
Status VideoProcessing::AddFilter(BaseCodec *filter, int atEnd)
{
int k;
if (atEnd) {
bFiltering[numFilters] = true;
pFilter[numFilters++] = filter;
} else {
for (k = numFilters; k > 0; k--) {
pFilter[k] = pFilter[k - 1];
bFiltering[k] = bFiltering[k - 1];
}
bFiltering[0] = true;
pFilter[0] = filter;
iDeinterlacing++;
iColorConv0++;
iColorConv++;
iResizing++;
numFilters++;
}
return UMC_OK;
}
Status VideoProcessing::Init(BaseCodecParams *init)
{
return SetParams(init);
}
static Status InitVideoData(VideoData *tmpData, int w, int h, ColorFormat color)
{
if (tmpData->GetWidth() != w ||
tmpData->GetHeight() != h ||
tmpData->GetColorFormat() != color)
{
tmpData->Init(w, h, color);
return tmpData->Alloc();
}
return UMC_OK;
}
static ColorFormat GetIntermediatedColor(ColorFormat src_color)
{
switch (src_color) {
case YV12: return YUV420;
case NV12: return YUV420;
case YUY2: return YUV420;
case UYVY: return YUV420;
case YUV411: return YUV422;
case YUV420: return YV12;
case YUV422: return YUY2;
case YUV444: return RGB24;
case YUV_VC1: return YUV420;
case Y411: return YUV411;
case Y41P: return YUV411;
case RGB32: return RGB24;
case RGB24: return RGB32;
case RGB565: return RGB24;
case RGB555: return RGB24;
case RGB444: return RGB24;
case GRAY: return YUV420;
case YUV420A: return YUV420;
case YUV422A: return YUV422;
case YUV444A: return YUV444;
case YVU9: return YUV420;
}
return YUV420;
}
Status VideoProcessing::GetFrame(MediaData *input, MediaData *output)
{
VideoData *in = DynamicCast<VideoData>(input);
VideoData *out = DynamicCast<VideoData>(output);
VideoData *src;
VideoData *dst;
Status res;
Ipp64f timeStart, timeEnd;
int k;
UMC_CHECK(in, UMC_ERR_NULL_PTR);
UMC_CHECK(out, UMC_ERR_NULL_PTR);
UMC_CHECK(in->GetPlanePointer(0), UMC_ERR_NOT_ENOUGH_DATA);
// copy FrameType and Time
out->SetFrameType(in->GetFrameType());
in->GetTime(timeStart, timeEnd);
out->SetTime(timeStart, timeEnd);
// Crop
if (bSrcCropArea) {
*(VideoData*)tmp_in = *in;
in = tmp_in;
tmp_in->Crop(Param.SrcCropArea);
}
int src_w = in->GetWidth();
int src_h = in->GetHeight();
int dst_w = out->GetWidth();
int dst_h = out->GetHeight();
ColorFormat src_c = in->GetColorFormat();
ColorFormat dst_c = out->GetColorFormat();
bFiltering[iDeinterlacing] = (Param.m_DeinterlacingMethod != NO_DEINTERLACING) &&
(in->GetPictureStructure() != PS_FRAME);
bFiltering[iColorConv0] = false;
bFiltering[iColorConv] = (src_c != dst_c);
bFiltering[iResizing] = (src_w != dst_w || src_h != dst_h);
// Get frame size
Ipp32s lFrameSize = out->GetMappingSize();
if (lFrameSize <= 0) lFrameSize = in->GetMappingSize();
if (lFrameSize <= 0) lFrameSize = 1;
// Set PictureStructure
if (!bFiltering[iDeinterlacing]) {
out->SetPictureStructure(in->GetPictureStructure());
} else {
out->SetPictureStructure(PS_FRAME);
}
// skip color conversion between YUV420 and YV12
int skip_flag = 0;
if (src_c == YUV420 && dst_c == YV12) skip_flag = 1; // YUV420->YV12
if (src_c == YV12 && dst_c == YUV420) skip_flag = 2; // YV12->YUV420
if (skip_flag) {
for (k = 0; k < numFilters; k++) {
if (bFiltering[k] && k != iColorConv) {
if (skip_flag == 1) {
*(VideoData*)tmp_out = *out;
out = tmp_out;
tmp_out->Convert_YV12_To_YUV420();
dst_c = YUV420;
bFiltering[iColorConv] = false;
} else { // skip_flag == 2
if (in != tmp_in) {
*(VideoData*)tmp_in = *in;
in = tmp_in;
}
tmp_in->Convert_YV12_To_YUV420();
src_c = YUV420;
bFiltering[iColorConv] = false;
}
break;
}
}
}
// Get last filter in chain
int iLastFilter = numFilters - 1;
while (iLastFilter >= 0 && bFiltering[iLastFilter] == false) iLastFilter--;
if (iLastFilter < 0) { // if no filters
bFiltering[iColorConv] = true;
iLastFilter = iColorConv;
}
src = in;
for (k = 0; k <= iLastFilter; k++) {
if (!bFiltering[k] || pFilter[k] == NULL) continue;
if (k == iLastFilter) {
dst = out;
} else {
dst = &tmpData[k];
if (k == iColorConv) {
src_c = dst_c;
} else if (k == iResizing) {
src_w = dst_w;
src_h = dst_h;
}
InitVideoData(dst, src_w, src_h, src_c);
}
res = pFilter[k]->GetFrame(src, dst);
if (res != UMC_OK) {
if (k == iColorConv && res == UMC_ERR_NOT_IMPLEMENTED && !bFiltering[iColorConv0]) {
bFiltering[iColorConv0] = true; // try double color conversion
src_c = GetIntermediatedColor(src->GetColorFormat()); // intermediated color
k = iColorConv0 - 1; // back to first color conversion
continue;
}
return res;
}
src = dst;
}
input->SetDataSize(0);
output->SetDataSize(lFrameSize);
return UMC_OK;
}
Status VideoProcessing::SetParams(BaseCodecParams *params)
{
VideoProcessingParams *p_params = DynamicCast<VideoProcessingParams>(params);
UMC_CHECK(p_params, UMC_OK);
Param = *p_params;
if (pFilter[iDeinterlacing]) {
((Deinterlacing*)pFilter[iDeinterlacing])->SetMethod(Param.m_DeinterlacingMethod);
}
if (pFilter[iResizing]) {
((VideoResizing*)pFilter[iResizing])->SetMethod(Param.InterpolationMethod);
}
bSrcCropArea = Param.SrcCropArea.left || Param.SrcCropArea.right ||
Param.SrcCropArea.top || Param.SrcCropArea.bottom;
return UMC_OK;
}
Status VideoProcessing::GetInfo(BaseCodecParams *info)
{
VideoProcessingParams *p_params = DynamicCast<VideoProcessingParams>(info);
if (!p_params) {
return UMC_ERR_NULL_PTR;
}
*p_params = Param;
return UMC_OK;
}
Status VideoProcessing::Reset()
{
return UMC_OK;
}
VideoProcessing::~VideoProcessing()
{
Close();
}
//////////////////////////////////////////////////////////////////////
Status VideoDataExt::Crop(UMC::RECT SrcCropArea)
{
int left = SrcCropArea.left;
int top = SrcCropArea.top;
int right = SrcCropArea.right;
int bottom = SrcCropArea.bottom;
if (!right) right = m_ippSize.width;
if (!bottom) bottom = m_ippSize.height;
int w = right - left;
int h = bottom - top;
int k;
if (w <= 0 || h <= 0) return UMC_ERR_INVALID_PARAMS;
if (left < 0 || top < 0) return UMC_ERR_INVALID_PARAMS;
if (right > m_ippSize.width || bottom > m_ippSize.height) return UMC_ERR_INVALID_PARAMS;
for (k = 0; k < m_iPlanes; k++) {
int wDiv = (m_pPlaneData[k].m_ippSize.width) ? m_ippSize.width/m_pPlaneData[k].m_ippSize.width : 1;
int hDiv = (m_pPlaneData[k].m_ippSize.height) ? m_ippSize.height/m_pPlaneData[k].m_ippSize.height : 1;
m_pPlaneData[k].m_pPlane += (top / hDiv) * m_pPlaneData[k].m_nPitch +
(left / wDiv) * m_pPlaneData[k].m_iSamples * m_pPlaneData[k].m_iSampleSize;
m_pPlaneData[k].m_ippSize.width = w / wDiv;
m_pPlaneData[k].m_ippSize.height = h / hDiv;
}
m_ippSize.width = w;
m_ippSize.height = h;
return UMC_OK;
}
Status VideoDataExt::Convert_YV12_To_YUV420()
{
if (m_ColorFormat == YV12) {
PlaneInfo tmp_plane = m_pPlaneData[1];
m_pPlaneData[1] = m_pPlaneData[2];
m_pPlaneData[2] = tmp_plane;
m_ColorFormat = YUV420;
}
return UMC_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -