📄 umc_mpeg2_dec_pic.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_defs.h"
#if defined (UMC_ENABLE_MPEG2_VIDEO_DECODER)
#include "umc_mpeg2_dec_defs.h"
#include "umc_mpeg2_dec_base.h"
#include "umc_video_data.h"
#include "umc_structures.h"
#pragma warning(disable: 4244)
using namespace UMC;
extern Ipp8u default_intra_quantizer_matrix[64];
// can decode all headers, except of slices
// bitstream should point to next after header byte
Status MPEG2VideoDecoderBase::DecodeHeader(Ipp32s startcode, IppVideoContext* video)
{
Ipp32u code;
switch(startcode) {
case SEQUENCE_HEADER_CODE:
return (DecodeSequenceHeader(video));
case SEQUENCE_END_CODE:
return (UMC_OK);
case GROUP_START_CODE:
GET_BITS_LONG(video->bs, 27, code)
sequenceHeader.broken_link = code & 1;
sequenceHeader.closed_gop = code & 2;
sequenceHeader.gop_picture = (code>>2) & 0x3f;
sequenceHeader.gop_second = ((code>>8) & 0x3f) + ((code>>15) & 0x3f)*60 + ((code>>21) & 0x1f)*3600;
sequenceHeader.stream_time_temporal_reference = -1; //-2; // new count
return (UMC_OK); // ignore for a while
case EXTENSION_START_CODE:
SHOW_TO9BITS(video->bs, 4, code)
//extensions
switch(code) {
case SEQUENCE_EXTENSION_ID:
{
Ipp32u bit_rate_extension, chroma_format;
GET_BITS32(video->bs, code)
sequenceHeader.profile = (code >> 24) & 0x7;//ignore escape bit
sequenceHeader.level = (code >> 20) & 0xf;
sequenceHeader.progressive_sequence = (code >> 19) & 1;
chroma_format = 1 << ((code >> 17) & ((1 << 2) - 1));
m_ClipInfo.clip_info.width = (m_ClipInfo.clip_info.width & 0xfff)
| ((code >> (15-12)) & 0x3000);
m_ClipInfo.clip_info.height = (m_ClipInfo.clip_info.height & 0xfff)
| ((code >> (13-12)) & 0x3000);
bit_rate_extension = (code >> 1) & 0xfff;
GET_BITS(video->bs, 16, code)
sequenceHeader.frame_rate_extension_d = code & 31;
sequenceHeader.frame_rate_extension_n = (code >> 5) & 3;
switch (chroma_format)
{
case 2:
m_ClipInfo.color_format = YUV420;
break;
case 4:
m_ClipInfo.color_format = YUV422;
break;
case 8:
m_ClipInfo.color_format = YUV444;
break;
default:
break;
}
if(bit_rate_extension != 0) {
m_ClipInfo.bitrate = (m_ClipInfo.bitrate / 400) & 0x3ffff;
m_ClipInfo.bitrate |= (bit_rate_extension<<18);
if(m_ClipInfo.bitrate >= 0x40000000/100) // check if fit to 32u
m_ClipInfo.bitrate = 0xffffffff;
else
m_ClipInfo.bitrate *= 400;
}
sequenceHeader.extension_start_code_ID = SEQUENCE_EXTENSION_ID; //needed?
}
break;
case SEQUENCE_DISPLAY_EXTENSION_ID:
sequence_display_extension();
break;
case QUANT_MATRIX_EXTENSION_ID:
quant_matrix_extension();
break;
case COPYRIGHT_EXTENSION_ID:
copyright_extension();
break;
case PICTURE_DISPLAY_EXTENSION_ID:
picture_display_extension();
break;
case SEQUENCE_SCALABLE_EXTENSION_ID:
sequence_scalable_extension();
break;
case PICTURE_CODING_EXTENSION_ID: // can move after picture header (if mpeg2)
//picture_coding_extension();
{
GET_BITS32(video->bs,code)
VM_ASSERT((code>>28) == PICTURE_CODING_EXTENSION_ID);
PictureHeader.repeat_first_field = (code >> 1) & 1;
PictureHeader.alternate_scan = (code >> 2) & 1;
PictureHeader.intra_vlc_format = (code >> 3) & 1;
PictureHeader.q_scale_type = (code >> 4) & 1;
PictureHeader.concealment_motion_vectors = (code >> 5) & 1;
PictureHeader.frame_pred_frame_dct = (code >> 6) & 1;
PictureHeader.top_field_first = (code >> 7) & 1;
PictureHeader.picture_structure = (code >> 8) & 3;
PictureHeader.intra_dc_precision = (code >> 10) & 3;
PictureHeader.f_code[3] = (code >> 12) & 15;
PictureHeader.f_code[2] = (code >> 16) & 15;
PictureHeader.f_code[1] = (code >> 20) & 15;
PictureHeader.f_code[0] = (code >> 24) & 15;
GET_1BIT(video->bs, PictureHeader.progressive_frame)
GET_1BIT(video->bs, code)
PictureHeader.r_size[0] = PictureHeader.f_code[0] - 1;
PictureHeader.r_size[1] = PictureHeader.f_code[1] - 1;
PictureHeader.r_size[2] = PictureHeader.f_code[2] - 1;
PictureHeader.r_size[3] = PictureHeader.f_code[3] - 1;
PictureHeader.curr_intra_dc_multi = intra_dc_multi[PictureHeader.intra_dc_precision];
PictureHeader.curr_reset_dc = reset_dc[PictureHeader.intra_dc_precision];
Ipp32s i, f;
for(i = 0; i < 4; i++) {
f = 1 << PictureHeader.r_size[i];
PictureHeader.low_in_range[i] = -(f * 16);
PictureHeader.high_in_range[i] = (f * 16) - 1;
PictureHeader.range[i] = f * 32;
}
if(code)
{
GET_BITS_LONG(video->bs, 20, code)
}
if(PictureHeader.picture_structure == FRAME_PICTURE) {
frame_buffer.field_buffer_index = 0; // avoid field parity loss in resync
}
for (i = 0; i < m_nNumberOfThreads; i++) {
ippiDecodeInterInit_MPEG2(NULL, PictureHeader.alternate_scan | IPPVC_LEAVE_QUANT_UNCHANGED, &Video[i]->decodeInterSpec);
Video[i]->decodeIntraSpec.intraVLCFormat = PictureHeader.intra_vlc_format;
Video[i]->decodeIntraSpec.intraShiftDC = PictureHeader.curr_intra_dc_multi;
ippiDecodeIntraInit_MPEG2(NULL, PictureHeader.alternate_scan | IPPVC_LEAVE_QUANT_UNCHANGED, Video[i]->decodeIntraSpec.intraVLCFormat, Video[i]->decodeIntraSpec.intraShiftDC, &Video[i]->decodeIntraSpec);
ippiDecodeInterInit_MPEG2(NULL, PictureHeader.alternate_scan | IPPVC_LEAVE_QUANT_UNCHANGED, &Video[i]->decodeInterSpecChroma);
ippiDecodeIntraInit_MPEG2(NULL, PictureHeader.alternate_scan | IPPVC_LEAVE_QUANT_UNCHANGED, Video[i]->decodeIntraSpec.intraVLCFormat, Video[i]->decodeIntraSpec.intraShiftDC, &Video[i]->decodeIntraSpecChroma);
}
}
break;
case PICTURE_SPARTIAL_SCALABLE_EXTENSION_ID:
picture_spartial_scalable_extension();
break;
case PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID:
picture_temporal_scalable_extension();
break;
default:
//VM_ASSERT(0);
break;
}
return (UMC_OK);
case USER_DATA_START_CODE:
{
if(m_pCCData /*&& gop_flag*/)
{
ReadCCData();
}
else
{
//other user info, skip it
SHOW_BITS_LONG(video->bs,24,code)
while(code != 0x000001)
{
GET_TO9BITS(video->bs, 8, code)
SHOW_BITS_LONG(video->bs,24,code)
}
}
}
return (UMC_OK);
case PICTURE_START_CODE:
return (DecodePictureHeader());
default:
return (UMC_ERR_INVALID_STREAM); // unexpected
}
}
//Sequence Header search. Stops after header start code
Status MPEG2VideoDecoderBase::FindSequenceHeader(IppVideoContext *video)
{
Ipp32u code;
do {
GET_START_CODE(video->bs, code);
if(SEQUENCE_HEADER_CODE == code)
return (UMC_OK);
} while ( code != UMC_ERR_NOT_ENOUGH_DATA );
return UMC_ERR_NOT_ENOUGH_DATA;
}
// when video == 0 uses m_ClipInfo values
Status MPEG2VideoDecoderBase::DecodeSequenceHeader(IppVideoContext* video)
{
Ipp32u load_non_intra_quantizer_matrix = 0;
Ipp32u load_intra_quantizer_matrix = 0;
Ipp32u constrained_parameters_flag;
Ipp32u frame_rate_code, dar_code;
Ipp32s i;
Ipp32u code;
Status ret;
Ipp8u iqm[64];
Ipp8u niqm[64];
if (video != 0) {
if(GET_REMAINED_BYTES(video->bs) < 8) {
// return header back
UNGET_BITS_32(video->bs)
return (UMC_ERR_NOT_ENOUGH_DATA);
}
GET_BITS32(video->bs, code)
frame_rate_code = code & ((1 << 4) - 1);
m_ClipInfo.clip_info.height = (code >> 8) & ((1 << 12) - 1);
m_ClipInfo.clip_info.width = (code >> 20) & ((1 << 12) - 1);
dar_code = (code >> 4) & ((1 << 4) - 1);
GET_BITS32(video->bs, code)
m_ClipInfo.bitrate = (code >> 14) * 400;
constrained_parameters_flag = (code >> 2) & 1;
load_intra_quantizer_matrix = (code >> 1) & 1;
load_non_intra_quantizer_matrix = code & 1; // could be changed
if(load_intra_quantizer_matrix) {
GET_BITS(video->bs, 7, iqm[0])
iqm[0] |= (load_non_intra_quantizer_matrix << 7);
for(i=1; i<64; i++) {
GET_BITS(video->bs, 8, iqm[i])
}
GET_1BIT(video->bs, load_non_intra_quantizer_matrix);
}
if(load_non_intra_quantizer_matrix) {
for(i=0; i<64; i++) {
GET_BITS(video->bs, 8, niqm[i])
}
}
VideoStreamType newtype = MPEG1_VIDEO;
if(!constrained_parameters_flag) {
FIND_START_CODE(video->bs,code)
if(code == EXTENSION_START_CODE) {
SKIP_BITS_32(video->bs);
SHOW_TO9BITS(video->bs, 4, code)
if(code == SEQUENCE_EXTENSION_ID) {
newtype = MPEG2_VIDEO;
DecodeHeader(EXTENSION_START_CODE, video);
}
}
}
if(m_ClipInfo.stream_type == UNDEF_VIDEO)
m_ClipInfo.stream_type = newtype;
else if(m_ClipInfo.stream_type != newtype)
return (UMC_ERR_INVALID_STREAM);
FIND_START_CODE(video->bs, code);
while(code == EXTENSION_START_CODE || code == USER_DATA_START_CODE)
{
SKIP_BITS_32(video->bs);
DecodeHeader(code, video);
FIND_START_CODE(video->bs, code);
}
}
if(m_ClipInfo.stream_type == MPEG1_VIDEO) {
sequenceHeader.progressive_sequence = 1;
m_ClipInfo.color_format = YUV420;
}
if(m_ClipInfo.color_format != YUV422) {
m_ClipInfo.color_format = YUV420;
}
if(m_ClipInfo.stream_type == UNDEF_VIDEO ||
m_ClipInfo.clip_info.width <= 0 || m_ClipInfo.clip_info.width >= 0x10000 ||
m_ClipInfo.clip_info.height <= 0 || m_ClipInfo.clip_info.height >= 0x10000)
return UMC_ERR_INVALID_PARAMS; // if was not set in params
if (m_ClipInfo.framerate <= 0)
m_ClipInfo.framerate = 30; // to avoid divide by zero
// now compute and set params
frame_buffer.field_buffer_index = 0;
sequenceHeader.mb_width = (m_ClipInfo.clip_info.width + 15) >> 4;
sequenceHeader.mb_height= (m_ClipInfo.clip_info.height + 15) >> 4;
if(!sequenceHeader.progressive_sequence) {
sequenceHeader.mb_height = (sequenceHeader.mb_height + 1) & ~1;
}
sequenceHeader.numMB = sequenceHeader.mb_width*sequenceHeader.mb_height;
if (UMC_OK != UpdateFrameBuffer()) { // create or update internal buffer
return (UMC_ERR_ALLOC);
}
Ipp32s flag_mpeg1 = (m_ClipInfo.stream_type == MPEG1_VIDEO) ? IPPVC_MPEG1_STREAM : 0;
for (i = 0; i < m_nNumberOfThreads; i++) {
ippiDecodeIntraInit_MPEG2(NULL, flag_mpeg1, PictureHeader.intra_vlc_format, PictureHeader.curr_intra_dc_multi, &Video[i]->decodeIntraSpec);
ippiDecodeInterInit_MPEG2(NULL, flag_mpeg1, &Video[i]->decodeInterSpec);
Video[i]->decodeInterSpecChroma = Video[i]->decodeInterSpec;
Video[i]->decodeIntraSpecChroma = Video[i]->decodeIntraSpec;
}
if (video != 0) {
sequenceHeader.is_decoded = 1;
if(load_intra_quantizer_matrix)
{
for (i = 0; i < m_nNumberOfThreads; i++) {
ippiDecodeIntraInit_MPEG2(iqm, flag_mpeg1, PictureHeader.intra_vlc_format, PictureHeader.curr_intra_dc_multi, &Video[i]->decodeIntraSpec);
Video[i]->decodeIntraSpecChroma = Video[i]->decodeIntraSpec;
}
}
if(load_non_intra_quantizer_matrix)
{
for (i = 0; i < m_nNumberOfThreads; i++) {
ippiDecodeInterInit_MPEG2(niqm, flag_mpeg1, &Video[i]->decodeInterSpec);
Video[i]->decodeInterSpecChroma = Video[i]->decodeInterSpec;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -