📄 umc_mpeg4_video_decoder.cpp
字号:
if ((mp4_Parse_VisualObjectSequence(m_decInfo)) != MP4_STATUS_OK)
return UMC_ERR_INVALID_STREAM;
}
if (!h_vo_found && code == MP4_VISUAL_OBJECT_SC) {
h_vo_found = 1;
if ((mp4_Parse_VisualObject(m_decInfo)) != MP4_STATUS_OK)
return UMC_ERR_INVALID_STREAM;
}
}
if ((Ipp32s)code >= MP4_VIDEO_OBJECT_MIN_SC && code <= MP4_VIDEO_OBJECT_MAX_SC) {
if ((mp4_Parse_VideoObject(m_decInfo)) != MP4_STATUS_OK)
return UMC_ERR_INVALID_STREAM;
break;
}
// some streams can start with video_object_layer
if ((Ipp32s)code >= MP4_VIDEO_OBJECT_LAYER_MIN_SC && code <= MP4_VIDEO_OBJECT_LAYER_MAX_SC) {
m_decInfo->bufptr -= 4;
if ((mp4_Parse_VideoObject(m_decInfo)) != MP4_STATUS_OK)
return UMC_ERR_INVALID_STREAM;
break;
}
}
}
status = AllocateBuffers();
if (status != UMC_OK)
return status;
// set aspect ratio info
switch (m_decInfo->VisualObject.VideoObject.aspect_ratio_info) {
case MP4_ASPECT_RATIO_FORBIDDEN:
case MP4_ASPECT_RATIO_1_1:
m_Param.info.aspect_ratio_width = 1;
m_Param.info.aspect_ratio_height = 1;
break;
case MP4_ASPECT_RATIO_12_11:
m_Param.info.aspect_ratio_width = 12;
m_Param.info.aspect_ratio_height = 11;
break;
case MP4_ASPECT_RATIO_10_11:
m_Param.info.aspect_ratio_width = 10;
m_Param.info.aspect_ratio_height = 11;
break;
case MP4_ASPECT_RATIO_16_11:
m_Param.info.aspect_ratio_width = 16;
m_Param.info.aspect_ratio_height = 11;
break;
case MP4_ASPECT_RATIO_40_33:
m_Param.info.aspect_ratio_width = 40;
m_Param.info.aspect_ratio_height = 33;
break;
default:
m_Param.info.aspect_ratio_width = m_decInfo->VisualObject.VideoObject.aspect_ratio_info_par_width;
m_Param.info.aspect_ratio_height = m_decInfo->VisualObject.VideoObject.aspect_ratio_info_par_height;
}
// set profile/level info
m_Param.profile = m_decInfo->profile_and_level_indication >> 4;
m_Param.level = m_decInfo->profile_and_level_indication & 15;
if (m_Param.profile == MPEG4_PROFILE_SIMPLE)
if (m_Param.level == 8)
m_Param.level = MPEG4_LEVEL_0;
if (m_Param.profile == MPEG4_PROFILE_ADVANCED_SIMPLE) {
if (m_Param.level == 7)
m_Param.level = MPEG4_LEVEL_3B;
if (m_Param.level > 7) {
m_Param.profile = MPEG4_PROFILE_FGS;
m_Param.level -= 8;
}
}
m_IsInit = true;
return UMC_OK;
}
Status MPEG4VideoDecoder::GetFrame(MediaData* in, MediaData* out)
{
Status status = UMC_OK;
Ipp64f pts = -1.0;
#ifdef _OMP_KARABAS
m_decInfo->mTreadPriority = vm_get_current_thread_priority();
#endif // _OMP_KARABAS
if (!m_IsInitBase)
return UMC_ERR_NOT_INITIALIZED;
if (!out)
return UMC_ERR_NULL_PTR;
if (in) {
m_decInfo->bitoff = 0;
m_decInfo->bufptr = m_decInfo->buffer = (Ipp8u *)in->GetDataPointer();
m_decInfo->buflen = in->GetDataSize();
}
if (!m_IsInit) {
if (in == NULL)
return UMC_ERR_NOT_ENOUGH_DATA;
m_Param.m_pData = in;
status = InsideInit();
if (status != UMC_OK) {
in->MoveDataPointer(in->GetDataSize() - m_decInfo->buflen);
if (status == UMC_ERR_INVALID_STREAM ||
status == UMC_ERR_SYNC)
return UMC_ERR_NOT_ENOUGH_DATA;
else
return status;
}
}
LockBuffers();
for (;;) {
if (in == NULL) {
// show last frame (it can be only if (m_Param.lFlags & FLAG_VDEC_REORDER))
if (!m_buffered_frame) {
UnlockBuffers();
return UMC_ERR_NOT_ENOUGH_DATA;
}
m_buffered_frame = false;
m_decInfo->VisualObject.vFrame = m_decInfo->VisualObject.VideoObject.prevPlaneIsB ?
&m_decInfo->VisualObject.nFrame : &m_decInfo->VisualObject.cFrame;
} else {
// Seeking the VOP start_code, and then begin the vop decoding
if (m_decInfo->VisualObject.VideoObject.short_video_header) {
if (!mp4_SeekShortVideoStartMarker(m_decInfo)) {
mp4_Error("Error: Failed seeking short_video_start_marker\n");
status = UMC_ERR_SYNC;
break;
}
} else {
for (;;) {
if (!mp4_SeekStartCodePtr(m_decInfo)) {
mp4_Error("Error: Failed seeking GOV or VOP Start Code");
status = UMC_ERR_SYNC;
break;
}
int code = m_decInfo->bufptr[0];
m_decInfo->bufptr ++;
// parse repeated VOS, VO and VOL headers because stream may be glued from different streams
if (code == MP4_VISUAL_OBJECT_SEQUENCE_SC) {
if (mp4_Parse_VisualObjectSequence(m_decInfo) != MP4_STATUS_OK) {
status = UMC_ERR_INVALID_STREAM;
break;
}
} else if (code == MP4_VISUAL_OBJECT_SC) {
if (mp4_Parse_VisualObject(m_decInfo) != MP4_STATUS_OK) {
status = UMC_ERR_INVALID_STREAM;
break;
}
} else if (code >= MP4_VIDEO_OBJECT_LAYER_MIN_SC && code <= MP4_VIDEO_OBJECT_LAYER_MAX_SC) {
// in repeated headers check only VOL header
m_decInfo->bufptr -= 4;
// save parameters which can affect on reinit
Ipp32s interlaced = m_decInfo->VisualObject.VideoObject.interlaced;
Ipp32s data_partitioned = m_decInfo->VisualObject.VideoObject.data_partitioned;
Ipp32s sprite_enable = m_decInfo->VisualObject.VideoObject.sprite_enable;
Ipp32s width = m_decInfo->VisualObject.VideoObject.width;
Ipp32s height = m_decInfo->VisualObject.VideoObject.height;
if (mp4_Parse_VideoObject(m_decInfo) != MP4_STATUS_OK) {
status = UMC_ERR_INVALID_STREAM;
break;
}
// realloc if something was changed
if (interlaced != m_decInfo->VisualObject.VideoObject.interlaced ||
data_partitioned != m_decInfo->VisualObject.VideoObject.data_partitioned ||
sprite_enable != m_decInfo->VisualObject.VideoObject.sprite_enable ||
width != m_decInfo->VisualObject.VideoObject.width ||
height != m_decInfo->VisualObject.VideoObject.height) {
if (width != m_decInfo->VisualObject.VideoObject.width ||
height != m_decInfo->VisualObject.VideoObject.height) {
m_Param.info.clip_info.width = m_decInfo->VisualObject.VideoObject.width;
m_Param.info.clip_info.height = m_decInfo->VisualObject.VideoObject.height;
}
UnlockBuffers();
status = FreeBuffers();
if (status != UMC_OK)
break;
status = AllocateBuffers();
if (status != UMC_OK)
break;
LockBuffers();
// free buffers for MPEG-4 post-processing
if (ppFrame0.mid) {
status = m_pMemoryAllocator->Free(ppFrame0.mid);
ppFrame0.mid = 0;
if (status != UMC_OK)
break;
}
if (ppFrame1.mid) {
status = m_pMemoryAllocator->Free(ppFrame1.mid);
ppFrame1.mid = 0;
if (status != UMC_OK)
break;
}
// will be allocated before processing
} else
if (m_decInfo->strictSyntaxCheck) {
mp4_Error("Error: Repeated VOL header is different from previous");
status = UMC_ERR_INVALID_STREAM;
break;
}
// reinit quant matrix
ippiQuantInvIntraInit_MPEG4(m_decInfo->VisualObject.VideoObject.quant_type ? m_decInfo->VisualObject.VideoObject.intra_quant_mat : NULL, m_decInfo->VisualObject.VideoObject.QuantInvIntraSpec, 8);
ippiQuantInvInterInit_MPEG4(m_decInfo->VisualObject.VideoObject.quant_type ? m_decInfo->VisualObject.VideoObject.nonintra_quant_mat : NULL, m_decInfo->VisualObject.VideoObject.QuantInvInterSpec, 8);
} else if (code == MP4_GROUP_OF_VOP_SC) {
if (mp4_Parse_GroupOfVideoObjectPlane(m_decInfo) != MP4_STATUS_OK) {
status = UMC_ERR_INVALID_STREAM;
break;
}
} else if (m_decInfo->bufptr[-1] == MP4_VIDEO_OBJECT_PLANE_SC) {
break;
}
}
if (status != UMC_OK)
break;
}
// parse VOP header
if ((mp4_Parse_VideoObjectPlane(m_decInfo)) != MP4_STATUS_OK) {
status = UMC_WRN_INVALID_STREAM;
break;
}
if (m_IsReset && m_decInfo->VisualObject.VideoObject.VideoObjectPlane.coding_type != MP4_VOP_TYPE_I) {
return UMC_ERR_NOT_ENOUGH_DATA;
break;
}
if (m_decInfo->VisualObject.VideoObject.VideoObjectPlane.coding_type == MP4_VOP_TYPE_B) {
if (0 < m_is_skipped_b && !m_b_prev) {
m_is_skipped_b --;
m_skipped_fr ++;
m_b_prev = 1;
m_decInfo->bufptr = m_decInfo->buffer+ m_decInfo->buflen;
status = UMC_ERR_NOT_ENOUGH_DATA;
break;
} else
m_b_prev = 0;
}
// decode VOP
if ((mp4_DecodeVideoObjectPlane(m_decInfo)) != MP4_STATUS_OK) {
status = UMC_WRN_INVALID_STREAM;
}
// after reset it is need to skip first B-frames
if (m_decInfo->VisualObject.VideoObject.VOPindex < 2 && m_decInfo->VisualObject.VideoObject.VideoObjectPlane.coding_type == MP4_VOP_TYPE_B) {
status = UMC_ERR_NOT_ENOUGH_DATA;
break;
}
// do not count not_coded P frames with same vop_time as reference (in AVI)
if (m_decInfo->VisualObject.VideoObject.VideoObjectPlane.coded ||
(m_decInfo->VisualObject.rFrame.time != m_decInfo->VisualObject.cFrame.time &&
m_decInfo->VisualObject.nFrame.time != m_decInfo->VisualObject.cFrame.time)) {
m_decInfo->VisualObject.VideoObject.VOPindex++;
} else {
status = UMC_ERR_NOT_ENOUGH_DATA;
break;
}
if (m_IsReset && m_decInfo->VisualObject.VideoObject.VideoObjectPlane.coding_type == MP4_VOP_TYPE_I) {
m_time_reset = (Ipp32s)m_decInfo->VisualObject.cFrame.time;
m_decInfo->VisualObject.vFrame = NULL;
m_IsReset = false;
}
if ((m_Param.lFlags & FLAG_VDEC_REORDER) && (m_decInfo->VisualObject.vFrame == NULL)) {
// buffer first frame in VDEC_REORDER mode
status = UMC_ERR_NOT_ENOUGH_DATA;
break;
}
if (!(m_Param.lFlags & FLAG_VDEC_REORDER))
m_decInfo->VisualObject.vFrame = &m_decInfo->VisualObject.cFrame;
}
break;
}
if (in)
if (in->GetTime() != -1.0 && m_dec_time_base == -1.0)
m_dec_time_base = in->GetTime();
if ((m_dec_time_frinc > 0.0) || (m_decInfo->ftype == 1)) {
if (m_Param.lFlags & FLAG_VDEC_REORDER)
pts = m_dec_time_prev;
if (in) {
if (in->GetTime() != -1.0) {
// take right PTS for I-, P- frames
m_dec_time_prev = in->GetTime();
} else {
// when PB... are in one AVI chunk, first PTS from in->GetTime() is right and second is -1.0
m_dec_time_prev += m_dec_time_frinc;
}
}
if (!(m_Param.lFlags & FLAG_VDEC_REORDER))
pts = m_dec_time_prev;
} else {
bool extPTS = false;
if (in)
if (in->GetTime() != -1.0)
extPTS = true;
if (extPTS) {
pts = in->GetTime();
} else {
// for other internal MPEG-4 PTS is used
if (m_decInfo->VisualObject.vFrame)
pts = (Ipp64f)(m_decInfo->VisualObject.vFrame->time - m_time_reset) / m_decInfo->VisualObject.VideoObject.vop_time_increment_resolution;
else {
pts = 0.0;
}
if (m_dec_time_base != -1.0)
pts += m_dec_time_base;
}
}
if ((UMC_OK == status || UMC_WRN_INVALID_STREAM == status) && (m_decInfo->VisualObject.vFrame != NULL)) {
FrameType ft;
if (m_decInfo->VisualObject.VideoObject.sprite_enable == MP4_SPRITE_STATIC)
ft = I_PICTURE;
else
ft = (m_decInfo->VisualObject.vFrame->type) == MP4_VOP_TYPE_I ? I_PICTURE :
(m_decInfo->VisualObject.vFrame->type) == MP4_VOP_TYPE_B ? B_PICTURE :
P_PICTURE;
mp4_Frame rendFrame = *m_decInfo->VisualObject.vFrame;
bool ppDeblocking = m_DeblockingProcPlane[0] || m_DeblockingProcPlane[1] || m_DeblockingProcPlane[2];
bool ppDeringing = m_DeringingProcPlane[0] || m_DeringingProcPlane[1] || m_DeringingProcPlane[2];
if (ppDeblocking || ppDeringing) {
if (!ppFrame0.mid) {
ppFrame0.mbPerRow = m_decInfo->VisualObject.vFrame->mbPerRow;
ppFrame0.mbPerCol = m_decInfo->VisualObject.vFrame->mbPerCol;
status = AllocateInitFrame(&ppFrame0);
if (status != UMC_OK)
return status;
}
if (!ppFrame1.mid) {
ppFrame1.mbPerRow = m_decInfo->VisualObject.vFrame->mbPerRow;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -