📄 vdecoder.cc
字号:
/******************************************************************************** Copyright (C) 1999 Dirk Farin This program is distributed under GNU Public License (GPL) as outlined in the COPYING file that comes with the source distribution. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ********************************************************************************/#include "video12/vdecoder.hh"#include "video12/constants.hh"#include "video12/vlc.hh"#include "video12/viddec_mods.hh"#include "system/system1.hh"#include "error.hh"#include "video12/modules/idct_arai.hh" ////////////////////// TODO#include "video12/modules/mcomp_sgl_simple.hh"#include "libvideogfx/utility/bitstream/membitsread.hh"#include "libvideogfx/utility/bitstream/fastbitbuf.hh"#include <iostream.h>#include <iomanip.h>#include <string.h>#include <strings.h>#define SHOW_FRAMESIZE 0#if ENABLE_MMX#define MMX_DCT 1#else#define MMX_DCT 0#endif#undef SEND_FULL_BFRAMESextern "C" void IDCT_mmx(short* in,short* out);extern "C" void IDCT_16bit8bit(short* in,Pixel* out,int skip);extern "C" void IDCT_16bit8bit_add(short* in,Pixel* out,int skip);extern void PrintDataHex(uint8* data,uint32 len);extern void PrintDataBin(uint8* data,uint32 len);#include "video12/vlc.cc"#include "video12/dctblk.cc"#define NOBZERO 0inline void DIV2(int& x) { if (x>=0) x/=2; else x=(x-1)/2; }/* implemented syntax elements: ( - not, o partial, + full ) - video_sequence: o - sequence_header: + - extension_and_user_data: o - extension_data: o - user_data: - - sequence_extension: + - sequence_display_extension: - - sequence_scalable_extension: - - group_of_pictures_header: + - picture_header: + (excluding extra_information_picture) - picture_coding_extension: + - quant_matrix_extension: - - picture_display_extension: - - picture_temporal_scalable_extension: - - picture_spatial_scalable_extension: - - copyright_extension: - - picture_data: + - slice: + - macroblock: + - macroblock_modes: o - motion_vectors: + - motion_vector: + - coded_block_pattern: + - block: +*/static const int qcode2qscale[2][32] ={// - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 { 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58, 60, 62 }, { 0,1,2,3,4, 5, 6, 7, 8,10,12,14,16,18,20,22,24,28,32,36,40,44,48,52,56,64,72,80,88,96,104,112 }};static const int scan[2][64] ={ { /* Zig-Zag scan pattern */ 0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5, 12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28, 35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51, 58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63 }, { /* Alternate scan pattern */ 0,8,16,24,1,9,2,10,17,25,32,40,48,56,57,49, 41,33,26,18,3,11,4,12,19,27,34,42,50,58,35,43, 51,59,20,28,5,13,6,14,21,29,36,44,52,60,37,45, 53,61,22,30,7,15,23,31,38,46,54,62,39,47,55,63 }};static const int AlternateFromZigZag[64] ={// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0, 2, 3, 9, 1, 4, 5, 7, 8,11,10,20,21,35,36,34, 22,19,18,12, 6,13,14,16,17,24,23,33,37,48,32,38, 47,49,25,31,15,26,27,29,30,40,39,46,50,57,45,51, 56,58,41,44,28,42,43,53,52,55,59,62,54,60,61,63};VideoSyntaxTrace_Options::VideoSyntaxTrace_Options(){ Trace_SeqH = Trace_GOPH = Trace_PicH = Trace_SlcH = Trace_MB = Trace_SliceData = false; Trace_DCTCoeff = false;}VideoFrameSkip_Options::VideoFrameSkip_Options(){ DecodeI = true; DecodeP = true; DecodeB = true;}VideoDecoder::VideoDecoder(class PacketSource& source) : d_source(&source), d_sink(NULL), d_picdata(NULL), d_SequenceHeaderRead(false), d_next_packet(NULL), d_BFrameAvailable(false), d_FirstFieldInFrame(true), d_next_IsEmpty(true), d_skip_this_frame(false), d_curr(NULL), d_next(NULL), d_last(NULL), d_motcomp(NULL){ d_motcomp = MotionCompensation_SglMB::Create();#if MMX_DCT for (int i=0;i<2;i++) for (int n=0;n<64;n++) { int r=scan[i][n]/8; int c=scan[i][n]%8; d_scan[i][n]=c*8+r; }#else for (int i=0;i<2;i++) for (int n=0;n<64;n++) d_scan[i][n]=scan[i][n];#endif}VideoDecoder::~VideoDecoder(){ if (d_next_packet) delete d_next_packet; if (d_motcomp) delete d_motcomp;}SysPacket_Packet* VideoDecoder::GetNextPacket(){ SysPacket_Packet* pck; if (d_next_packet) { pck = d_next_packet; d_next_packet=NULL; } else { pck = d_source->GetNextPacket(); if (pck==NULL) return NULL; } return pck;}void VideoDecoder::PushbackPacket(SysPacket_Packet* pck){ Assert(d_next_packet==NULL); d_next_packet=pck;}bool VideoDecoder::DecodeAFrame(){ int LastSliceRead = 0; bool BeganPictureDecoding = false; for (;;) // Read as much packets as are required to decode a picture. { // Get next stream packet. SysPacket_Packet* pck = GetNextPacket(); if (pck==NULL) { // We reached the end of the stream. Flush the remaining images. // B-picture if (d_BFrameAvailable) { Assert(d_curr);#if SEND_FULL_BFRAMES d_curr->m_may_modify = true; d_sink->ShowAllMBRows(d_curr); // Show image#endif d_sink->FinishedPicture(); d_curr->FreePictureData(); // Remove additional information data delete d_curr; d_curr=NULL; d_BFrameAvailable=false; return true; } // Future reference picture if (!d_next_IsEmpty) { d_next->m_may_modify = true; d_sink->BeginPicture(d_next); d_sink->ShowAllMBRows(d_next); // Show last decoded I- or P-image. d_sink->FinishedPicture(); d_next->FreePictureData(); // Free the additional information data. delete d_last; delete d_next; d_last = d_next = NULL; d_next_IsEmpty=true; } return false; } // Decode packet data. MemBitstreamReader bitstream(pck->data.AskContents() , pck->data.AskLength()); uint32 startcode = bitstream.PeekBits(32); Assert((startcode & 0x00000100) != 0); // TODO: throw excpt if (IsMPEG_SLICE_START(startcode&0xFF) && d_SequenceHeaderRead && BeganPictureDecoding) { if (d_options.Trace_SliceData) { cout << "Slice Data:\n"; PrintDataBin(pck->data.AskContents(),pck->data.AskLength()); } FastBitBuf fastbitbuf(pck->data.AskContents() , pck->data.AskLength()); DecodeSlice(fastbitbuf); } else { // If we were just decoding a picture and a new picture begins, end decoding of the picture. if ((startcode == STARTCODE_SEQUENCE_HEADER || startcode == STARTCODE_GROUP_START || startcode == STARTCODE_PICTURE_START) && BeganPictureDecoding) { PushbackPacket(pck); // This packet already belongs to the next picture. /* If there's an B-image ready for display, show it. */ if (d_BFrameAvailable) { Assert(d_curr); #if SEND_FULL_BFRAMES d_curr->m_may_modify=true; d_sink->ShowAllMBRows(d_curr); // Show image#endif d_sink->FinishedPicture(); d_curr->FreePictureData(); // Remove additional information data d_BFrameAvailable=false; } return true; } switch (startcode) { case STARTCODE_SEQUENCE_HEADER: { DecodeSequenceHeader(bitstream,d_seqdata,d_quant_zz); d_SequenceHeaderRead=true; // Try to read Sequence-Extension. SysPacket_Packet* pck = GetNextPacket(); if (pck) { MemBitstreamReader bs(pck->data.AskContents() , pck->data.AskLength()); uint32 startcode = bs.GetBits(32); if (startcode==STARTCODE_EXTENSION_START) { if (bs.GetBits(4)==EXTID_SequenceExtension) DecodeSequenceHeaderExt(bs,d_seqdata); delete pck; } else PushbackPacket(pck); } // Allocate images and precalculate some values. PostSequenceHeader(); if (d_options.Trace_SeqH) TraceSequenceHeader(d_seqdata); } break; case STARTCODE_GROUP_START: { GOPHeader gopdata; DecodeGOPHeader(bitstream,gopdata); if (d_options.Trace_GOPH) TraceGOPHeader(gopdata); } break; case STARTCODE_PICTURE_START: if (d_SequenceHeaderRead) { DecodePictureHeader(bitstream,d_pichdr); BeganPictureDecoding=true; // Try to read Picture-Coding-Extension. SysPacket_Packet* pck2 = GetNextPacket(); if (pck2) { MemBitstreamReader bs(pck2->data.AskContents() , pck2->data.AskLength()); uint32 startcode = bs.GetBits(32); if (startcode==STARTCODE_EXTENSION_START) { if (bs.GetBits(4)==EXTID_PictureCodingExtension) DecodePictureCodingExt(bs,d_pichdr); delete pck2; } else PushbackPacket(pck2); } DecodeExtensions(2); // Do some precalculations, pointer settings... PostPictureHeader(pck->timing); if (d_options.Trace_PicH) TracePictureHeader(d_pichdr); } break;#if 0 case STARTCODE_EXTENSION_START: bitstream.SkipBits(32); switch (bitstream.GetBits(4)) { case EXTID_SequenceExtension: DecodeSequenceExtension(bitstream); break; default: //assert(0); break; } break; case STARTCODE_ISO11172_END: Assert(0); /* TODO: check: I think we'll never see this as this is thrown away because it's a syntax stream element. */ //Append(d_next); break;#endif default: break; } } delete pck; } return true;}void VideoDecoder::PostSequenceHeader(){ d_IsMPEG2 = d_seqdata.m_IsMPEG2; d_ChromaFormat = d_seqdata.m_ChromaFormat; switch (d_ChromaFormat) { case CHROMA_420: d_dctblks= 6; d_intra_cbp=0xFC0; mb_chr_w= 8; mb_chr_h= 8; break; case CHROMA_422: d_dctblks= 8; d_intra_cbp=0xFF0; mb_chr_w= 8; mb_chr_h=16; break; case CHROMA_444: d_dctblks=12; d_intra_cbp=0xFFF; mb_chr_w=16; mb_chr_h=16; break; } d_MBWidth = d_seqdata.m_MBWidth =(d_seqdata.m_Width +15)/16; d_MBHeight = d_seqdata.m_MBHeight=(d_seqdata.m_Height+15)/16; ImageParam param; if (d_last) d_last->m_image.Image<Pixel>::GetParam(param); if (!d_last || param.width != d_seqdata.m_Width || param.height != d_seqdata.m_Height) { specs.width = d_seqdata.m_Width; specs.height = d_seqdata.m_Height; specs.halign = 16; specs.valign = 16; specs.exact_size = true; specs.reduced_chroma_size = true; switch (d_seqdata.m_ChromaFormat) { case CHROMA_444: specs.chroma = Chroma444; break; case CHROMA_422: specs.chroma = Chroma422; break; case CHROMA_420: specs.chroma = Chroma420; break; } Assert(d_sink != NULL); if (d_last) delete d_last; if (d_curr) delete d_curr; if (d_next) delete d_next; d_last=d_curr=d_next=NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -