📄 vdecoder.cc
字号:
dp_cb = ptr_cb[slicehdr.vpos*mb_chr_h]-mb_chr_w; } if (d_MBHeight > 175) // <==> height > 2800 slicehdr.vpos += bs.GetBits(3)<<7; if (d_scalability_mode == DataPartitioning) slicehdr.priority_breakpoint = bs.GetBits(7); slicehdr.quantiser_scale_code = bs.GetBits(5); if (bs.GetBits(1)==1) { slicehdr.intra_slice = bs.GetBits(1); bs.SkipBits(7); while (bs.GetBits(1)==1) bs.SkipBits(8); } if (d_options.Trace_SlcH) { cout << "SliceHeader:\n" << " vertical pos: " << slicehdr.vpos << endl << " quantiser scale code: " << ((int)slicehdr.quantiser_scale_code) << endl << " intra slice: " << (slicehdr.intra_slice?"true":"false") << endl; } // *** decode all macroblocks in slice *** int dcpred_y = d_dc_pred; int dcpred_cb = d_dc_pred; int dcpred_cr = d_dc_pred; bzero(&PMV[0][0][0],2*2*2*sizeof(int)); // Reset MV-predictions. const Macroblock* lastmb = NULL; uint16 last_mb_mode=0; int mb_addr=-1; int mb_row =slicehdr.vpos; int qcode =slicehdr.quantiser_scale_code; while (bs.AskBitsLeft() >= 2 && bs.PeekBits(min(bs.AskBitsLeft(),23UL)) != 0) { if (!d_IsMPEG2) { // Macroblock-Stuffing while (bs.PeekBits(11)==0x00F) bs.SkipBits(11); } int incr = GetMBAddrIncr(bs);#ifndef NDEBUG if (d_options.Trace_MB) { cout << "--- MB --- " << slicehdr.vpos << " " << mb_addr+1 << endl; cout << "last MBAddr: " << mb_addr << " increment: " << incr << endl; }#endif // Handle skipped macroblocks. Note: the first MBincr in a slice does not define skipped MBs. if (incr>1 && mb_addr>=0) { dcpred_y = dcpred_cb = dcpred_cr = d_dc_pred; if (d_pichdr.m_picture_coding_type == PICTYPE_B) { for (int i=incr;i>0;i--) { AdvancePtrsMB(); mb_addr++; if (mb_addr==d_MBWidth) { AdvancePtrsMBRow(); if (IsBPicture) FlushBSlice(mb_row); mb_row++; mb_addr=0; } if (i>1) { if (d_pichdr.m_picture_structure==PICSTRUCT_FramePicture) MC_Frame_FrameBased(*lastmb,last_mb_mode); else MC_Field_FieldBased(*lastmb,last_mb_mode); } } } else if (d_pichdr.m_picture_coding_type == PICTYPE_P) { bzero(&PMV[0][0][0],2*2*2*sizeof(int)); // Reset PMVs incr--; mb_addr++; AdvancePtrsMB(); if (mb_addr==d_MBWidth) { AdvancePtrsMBRow(); if (IsBPicture) FlushBSlice(mb_row); mb_row++; mb_addr=0; } while (incr) { int len; if (mb_addr+incr >= d_MBWidth) len = d_MBWidth-mb_addr; else len = incr; int y0=mb_row*8; int x0=mb_addr*8; int plen = len*8; const Pixel* sp = dp_y-sp_curr_y+sp_last_y[d_field_offset]; Pixel* dp = dp_y; int h = 16; for (int y=0;y<h;y++) { memcpy(dp,sp,plen+plen); sp += lineskip_lum; dp += lineskip_lum; } sp = dp_cr-sp_curr_cr+sp_last_cr[d_field_offset]; dp = dp_cr; for (int y=0;y<h/2;y++) { memcpy(dp,sp,plen); sp += lineskip_chr; dp += lineskip_chr; } sp = dp_cb-sp_curr_cb+sp_last_cb[d_field_offset]; dp = dp_cb; for (int y=0;y<h/2;y++) { memcpy(dp,sp,plen); sp += lineskip_chr; dp += lineskip_chr; } mb_addr += len; for (int i=0;i<len;i++) AdvancePtrsMB(); if (mb_addr==d_MBWidth) { AdvancePtrsMBRow(); if (IsBPicture) FlushBSlice(mb_row); mb_addr=0; mb_row++; } else { Assert(mb_addr < d_MBWidth); } incr -= len; } } else if (d_pichdr.m_picture_coding_type == PICTYPE_I) { /* It is legal for the slice not to start in the first column. But it is illegal to skip any macroblocks in I pictures. */#if 1 throw Excpt_StreamError(ErrSev_Warning, "Invalid MPEG stream. " "Macroblock increment not 1 in I picture");#endif } else { NotImplemented /* TODO: D-pictures ? */ } } else { /* TODO: Should we do something if incr>=d_MBWidth ??? */ mb_addr += incr; for (int i=0;i<incr;i++) AdvancePtrsMB(); } static Macroblock s_mb; Macroblock& mb = ((d_picdata && d_picdata->m_codedimage.IsInitialized()) ? d_picdata->m_codedimage.Ask(mb_row,mb_addr) : s_mb); // process around-end-of-line-wrap in MPEG-1 Assert(mb_addr>=0); if ((uint32)mb_addr >= d_MBWidth) { if (d_IsMPEG2) throw Excpt_StreamError(ErrSev_Warning, /* TODO: Put this into a separate Exceptionclass for recovering */ "Invalid MPEG-2 input stream. " "Slice is wider than image width."); int nlines = mb_addr/d_MBWidth; for (int i=0;i<nlines;i++) AdvancePtrsMBRow(); if (IsBPicture) FlushBSlice(mb_row); mb_row += nlines; mb_addr %= d_MBWidth; } // -------- macroblock_modes() ---------- if (d_pichdr.m_picture_coding_type>4) throw Excpt_StreamError(ErrSev_Error, "Invalid MPEG stream, picture coding type >4 read."); uint16 mb_mode = GetMBMode[d_pichdr.m_picture_coding_type](bs); /* TODO: Spatial_Temporal_Weight_Code missing */ if (mb_mode & (MBMODE_MVFWD|MBMODE_MVBKW)) { if (d_pichdr.m_picture_structure == PICSTRUCT_FramePicture) { if (d_pichdr.m_frame_pred_frame_dct) { mb.SetFrameMotionType(Macroblock::FRMT_FrameBased); } else { mb.SetFrameMotionType((enum Macroblock::FrameMotionType)bs.GetBits(2)); } } else { mb.SetFieldMotionType((enum Macroblock::FieldMotionType)bs.GetBits(2)); } } else if ((mb_mode & MBMODE_INTRA) && d_pichdr.m_concealment_motion_vectors) { if (d_pichdr.m_picture_structure == PICSTRUCT_FramePicture) { mb.SetFrameMotionType(Macroblock::FRMT_FrameBased); } else { mb.SetFieldMotionType(Macroblock::FIMT_FieldBased); } } mb.m_FieldDCT=false; if (d_IsMPEG2 && d_pichdr.m_picture_structure == PICSTRUCT_FramePicture && d_pichdr.m_frame_pred_frame_dct == false && (mb_mode & (MBMODE_INTRA|MBMODE_PATTERN))) { mb.m_FieldDCT = bs.GetBits(1); } // -------- end of macroblock_modes() ----------- if (!(mb_mode & MBMODE_INTRA)) { dcpred_y = dcpred_cb = dcpred_cr = d_dc_pred; } // Reset motionvektor predictions if (((mb_mode & MBMODE_INTRA) && !d_pichdr.m_concealment_motion_vectors) || (d_pichdr.m_picture_coding_type == PICTYPE_P && !(mb_mode & MBMODE_MVFWD) && !(mb_mode & MBMODE_INTRA))) { bzero(&PMV[0][0][0],2*2*2*sizeof(int)); } if (mb_mode & MBMODE_QUANT) qcode = bs.GetBits(5); mb.m_quantiser_scale_code = qcode; bool FieldMVInFramePic = (mb.m_mv_format == Macroblock::MVFormat_Frame && mb.m_frame_motion_type == Macroblock::FRMT_FieldBased); if (mb.m_mv_format == Macroblock::MVFormat_Frame && mb.m_frame_motion_type == Macroblock::FRMT_DualPrime) FieldMVInFramePic = true; if ((mb_mode & MBMODE_MVFWD) || ((mb_mode & MBMODE_INTRA) && d_pichdr.m_concealment_motion_vectors)) { // --- motion_vectors(0) --- if (mb.m_motion_vector_count == 1) { if (FieldMVInFramePic) { DIV2(PMV[0][0][1]); } mb.m_vector[0][0].m_habs = PMV[0][0][0]; mb.m_vector[0][0].m_vabs = PMV[0][0][1]; if (mb.m_mv_format == Macroblock::MVFormat_Field && mb.m_dmv==false) { mb.m_vector[0][0].m_vertical_field_select = bs.GetBits(1); } motion_vector(mb.m_vector[0][0],0,mb.m_dmv,bs); PMV[0][0][0] = mb.m_vector[0][0].m_habs; PMV[0][0][1] = mb.m_vector[0][0].m_vabs; if (FieldMVInFramePic) { PMV[0][0][1] *= 2; } PMV[1][0][0] = PMV[0][0][0]; // Nach Table 7-9 PMV[1][0][1] = PMV[0][0][1]; } else { if (FieldMVInFramePic) { DIV2(PMV[0][0][1]); DIV2(PMV[1][0][1]); } mb.m_vector[0][0].m_habs = PMV[0][0][0]; mb.m_vector[0][0].m_vabs = PMV[0][0][1]; mb.m_vector[1][0].m_habs = PMV[1][0][0]; mb.m_vector[1][0].m_vabs = PMV[1][0][1]; mb.m_vector[0][0].m_vertical_field_select = bs.GetBits(1); motion_vector(mb.m_vector[0][0],0,mb.m_dmv,bs); mb.m_vector[1][0].m_vertical_field_select = bs.GetBits(1); motion_vector(mb.m_vector[1][0],0,mb.m_dmv,bs); PMV[0][0][0] = mb.m_vector[0][0].m_habs; PMV[0][0][1] = mb.m_vector[0][0].m_vabs; PMV[1][0][0] = mb.m_vector[1][0].m_habs; PMV[1][0][1] = mb.m_vector[1][0].m_vabs; if (FieldMVInFramePic) { PMV[0][0][1] *= 2; PMV[1][0][1] *= 2; } } } if (mb_mode & MBMODE_MVBKW) { // --- motion_vectors(1) --- if (mb.m_motion_vector_count == 1) { if (FieldMVInFramePic) { DIV2(PMV[0][1][1]); } mb.m_vector[0][1].m_habs = PMV[0][1][0]; mb.m_vector[0][1].m_vabs = PMV[0][1][1]; if (mb.m_mv_format == Macroblock::MVFormat_Field && mb.m_dmv==false) { mb.m_vector[0][1].m_vertical_field_select = bs.GetBits(1); } motion_vector(mb.m_vector[0][1],1,mb.m_dmv,bs); PMV[0][1][0] = mb.m_vector[0][1].m_habs; PMV[0][1][1] = mb.m_vector[0][1].m_vabs; if (FieldMVInFramePic) { PMV[0][1][1] *= 2; } PMV[1][1][0] = PMV[0][1][0]; // Nach Table 7-9 PMV[1][1][1] = PMV[0][1][1]; } else { if (FieldMVInFramePic) { DIV2(PMV[0][1][1]); DIV2(PMV[1][1][1]); } mb.m_vector[0][1].m_habs = PMV[0][1][0]; mb.m_vector[0][1].m_vabs = PMV[0][1][1]; mb.m_vector[1][1].m_habs = PMV[1][1][0]; mb.m_vector[1][1].m_vabs = PMV[1][1][1]; mb.m_vector[0][1].m_vertical_field_select = bs.GetBits(1); motion_vector(mb.m_vector[0][1],1,mb.m_dmv,bs); mb.m_vector[1][1].m_vertical_field_select = bs.GetBits(1); motion_vector(mb.m_vector[1][1],1,mb.m_dmv,bs); PMV[0][1][0] = mb.m_vector[0][1].m_habs; PMV[0][1][1] = mb.m_vector[0][1].m_vabs; PMV[1][1][0] = mb.m_vector[1][1].m_habs; PMV[1][1][1] = mb.m_vector[1][1].m_vabs; if (FieldMVInFramePic) { PMV[0][1][1] *= 2; PMV[1][1][1] *= 2; } } }#ifndef NDEBUG if (d_options.Trace_MB) { cout << "PMV[0][0][]: " << PMV[0][0][0] << ',' << PMV[0][0][1] << endl; cout << "PMV[0][1][]: " << PMV[0][1][0] << ',' << PMV[0][1][1] << endl; cout << "PMV[1][0][]: " << PMV[1][0][0] << ',' << PMV[1][0][1] << endl; cout << "PMV[1][1][]: " << PMV[1][1][0] << ',' << PMV[1][1][1] << endl; }#endif if ((mb_mode & MBMODE_INTRA) && d_pichdr.m_concealment_motion_vectors) { bs.SkipBits(1); } if (d_pichdr.m_picture_coding_type == PICTYPE_P && !(mb_mode & (MBMODE_MVFWD|MBMODE_INTRA))) { mb_mode |= MBMODE_MVFWD; mb.m_forward1.m_habs=0; mb.m_forward1.m_vabs=0; if (d_pichdr.m_picture_structure==PICSTRUCT_FramePicture) { mb.SetFrameMotionType(Macroblock::FRMT_FrameBased); } else if (d_pichdr.m_picture_structure == PICSTRUCT_TopField) { mb.SetFieldMotionType(Macroblock::FIMT_FieldBased); mb.m_forward1.m_vertical_field_select = 0; } else { mb.SetFieldMotionType(Macroblock::FIMT_FieldBased); mb.m_forward1.m_vertical_field_select = 1; } } if (mb_mode & MBMODE_INTRA) mb.m_IsIntra=true; else mb.m_IsIntra=false; mb.m_HasMotionForward = (mb_mode & MBMODE_MVFWD); mb.m_HasMotionBackward = (mb_mode & MBMODE_MVBKW); // --- Motion-Compensation --- if (mb_mode & (MBMODE_MVFWD|MBMODE_MVBKW)) { if (mb.m_mv_format==Macroblock::MVFormat_Frame) { switch (mb.m_frame_motion_type) { case Macroblock::FRMT_FrameBased: MC_Frame_FrameBased(mb,mb_mode); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -