📄 mpegparser.cc
字号:
//// Copyright (c) 2004 by Istv醤 V醨adi//// This file is part of dxr3Player, a DVD player written specifically // for the DXR3 (aka Hollywood+) decoder card, but now handles other// hardware as well.// 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 "MPEGParser.h"#include "MPEGListener.h"#include "dvd/packet/PacketQueue.h"#include "dvd/packet/TimedDataBlockPacket.h"//------------------------------------------------------------------------------using mpeg::MPEGParser;using mpeg::SequenceHeader;using mpeg::PictureHeader;using dvd::packet::DataBlockPacket;using dvd::packet::TimedDataBlockPacket;using dvd::packet::PacketQueue;//------------------------------------------------------------------------------const SequenceHeader::aspectRatio_t MPEGParser::aspectRatios[16] = { SequenceHeader::AR_UNKNOWN, SequenceHeader::SAR_1_0, SequenceHeader::DAR_3_4, SequenceHeader::DAR_16_9, SequenceHeader::DAR_1_221, SequenceHeader::AR_UNKNOWN, SequenceHeader::AR_UNKNOWN, SequenceHeader::AR_UNKNOWN, SequenceHeader::AR_UNKNOWN, SequenceHeader::AR_UNKNOWN, SequenceHeader::AR_UNKNOWN, SequenceHeader::AR_UNKNOWN, SequenceHeader::AR_UNKNOWN, SequenceHeader::AR_UNKNOWN, SequenceHeader::AR_UNKNOWN, SequenceHeader::AR_UNKNOWN};//------------------------------------------------------------------------------const size_t MPEGParser::frameRateNs[16] = { 0, 24000, 24, 25, 30000, 30, 50, 60000, 60, 0, 0, 0, 0, 0, 0, 0};const size_t MPEGParser::frameRateDs[16] = { 0, 1001, 1, 1, 1001, 1, 1, 1001, 1, 0, 0, 0, 0, 0, 0, 0};//------------------------------------------------------------------------------const SequenceHeader::profile_t MPEGParser::profiles[8] = { SequenceHeader::PROFILE_UNKOWN, SequenceHeader::PROFILE_HIGH, SequenceHeader::PROFILE_SPATIALLY_SCALABLE, SequenceHeader::PROFILE_SNR_SCALABLE, SequenceHeader::PROFILE_MAIN, SequenceHeader::PROFILE_SIMPLE, SequenceHeader::PROFILE_UNKOWN, SequenceHeader::PROFILE_UNKOWN};const SequenceHeader::level_t MPEGParser::levels[16] = { SequenceHeader::LEVEL_UNKNOWN, SequenceHeader::LEVEL_UNKNOWN, SequenceHeader::LEVEL_UNKNOWN, SequenceHeader::LEVEL_UNKNOWN, SequenceHeader::LEVEL_HIGH, SequenceHeader::LEVEL_UNKNOWN, SequenceHeader::LEVEL_HIGH_1440, SequenceHeader::LEVEL_UNKNOWN, SequenceHeader::LEVEL_MAIN, SequenceHeader::LEVEL_UNKNOWN, SequenceHeader::LEVEL_LOW, SequenceHeader::LEVEL_UNKNOWN, SequenceHeader::LEVEL_UNKNOWN, SequenceHeader::LEVEL_UNKNOWN, SequenceHeader::LEVEL_UNKNOWN, SequenceHeader::LEVEL_UNKNOWN};//------------------------------------------------------------------------------const SequenceHeader::chromaFormat_t MPEGParser::chromaFormats[4] = { SequenceHeader::CHROMA_UNKNOWN, SequenceHeader::CHROMA_4_2_0, SequenceHeader::CHROMA_4_2_2, SequenceHeader::CHROMA_4_4_4};//------------------------------------------------------------------------------//------------------------------------------------------------------------------const PictureHeader::codingType_t MPEGParser::codingTypes[8] = { PictureHeader::CODING_UNKNOWN, PictureHeader::CODING_I, PictureHeader::CODING_P, PictureHeader::CODING_B, PictureHeader::CODING_UNKNOWN, PictureHeader::CODING_UNKNOWN, PictureHeader::CODING_UNKNOWN, PictureHeader::CODING_UNKNOWN};//------------------------------------------------------------------------------const PictureHeader::pictureStructure_t MPEGParser::pictureStructures[4] = { PictureHeader::PICTURE_UNKNOWN, PictureHeader::PICTURE_TOP, PictureHeader::PICTURE_BOTTOM, PictureHeader::PICTURE_FRAME};//------------------------------------------------------------------------------//------------------------------------------------------------------------------MPEGParser::MPEGParser(MPEGListener& listener) : Schedulable("mpeg::MPEGParser"), listener(listener), data(0), dataLength(0), currentByte(0), bitsLeft(0), currentStartCode(0xff), sliceBuffer(new unsigned char[sliceBufferSize]){}//------------------------------------------------------------------------------MPEGParser::~MPEGParser(){ delete[] sliceBuffer;}//------------------------------------------------------------------------------void MPEGParser::run(){ while(!shouldQuit()) { clearInterrupt(); parse(); }}//------------------------------------------------------------------------------void MPEGParser::reset(){ currentPacket = 0; dataLength = 0; currentStartCode = 0xff; interrupt();}//------------------------------------------------------------------------------void MPEGParser::nextPacket(){ currentPacket = 0; dataLength = 0; currentPacket = getNextPacket(); if (currentPacket.isValid()) { data = currentPacket->getData(); dataLength = currentPacket->getLength(); currentByte = 0; bitsLeft = 8; pts_t pts = INVALID_PTS; Reference<TimedDataBlockPacket> timedPacket = TimedDataBlockPacket::convert(currentPacket); if (timedPacket.isValid()) { pts = timedPacket->getPTS(); } listener.ptsReceived(pts); }}//------------------------------------------------------------------------------inline void MPEGParser::skipByte(){ if (bitsLeft<8) { ++currentByte; bitsLeft = 8; }}//------------------------------------------------------------------------------inline unsigned MPEGParser::readBits(size_t numBits){ unsigned result = 0; while(numBits>0) { if (currentByte<dataLength) { size_t toRead = std::min(bitsLeft, numBits); bitsLeft = (toRead<bitsLeft) ? (bitsLeft-toRead) : 0; result <<= toRead; result |= (data[currentByte]>>bitsLeft) & ~(0xff<<toRead); if (bitsLeft==0) { ++currentByte; bitsLeft = 8; } numBits -= toRead; } else { nextPacket(); if (isInterrupted()) return 0; } } return result;}//------------------------------------------------------------------------------unsigned MPEGParser::readByte(){ skipByte(); if (currentByte<dataLength) { return data[currentByte++]; } nextPacket(); if (!isInterrupted()) { return data[currentByte++]; } return 0;}//------------------------------------------------------------------------------unsigned MPEGParser::nextStartCode(){ size_t matchLength = 0; while(!isInterrupted() && matchLength<3) { unsigned b = readByte(); if (b==0) { if (matchLength<2) ++matchLength; } else if (b==1 && matchLength==2) { ++matchLength; } else { matchLength = 0; } } currentStartCode = readByte(); return currentStartCode;}//------------------------------------------------------------------------------void MPEGParser::parse(){ dataLength = 0; currentStartCode = 0xff; nextStartCode(); while(!isInterrupted()) { while(!isInterrupted() && currentStartCode!=STARTCODE_SEQUENCE_HEADER) { nextStartCode(); } if (!isInterrupted() && currentStartCode==STARTCODE_SEQUENCE_HEADER) { if (!parseSequenceHeader()) continue; while(!isInterrupted() && currentStartCode!=STARTCODE_SEQUENCE_END) { parseExtensionAndUserData(0); if (!isInterrupted()) do { if (currentStartCode==STARTCODE_GROUP_START) { parseGOPHeader(); parseExtensionAndUserData(1); } if (currentStartCode==STARTCODE_PICTURE) { parsePictureHeader(); parseExtensionAndUserData(2); parsePictureData(); } } while((currentStartCode==STARTCODE_PICTURE || currentStartCode==STARTCODE_GROUP_START) && !isInterrupted()); if (!isInterrupted()) { if (!parseSequenceHeader()) break; } } if (!isInterrupted() && currentStartCode==STARTCODE_SEQUENCE_END) { listener.endSequence(); } } }}//------------------------------------------------------------------------------bool MPEGParser::parseSequenceHeader(){// Log::debug("mpeg::MPEGParser::parseSequenceHeader\n"); if (currentStartCode!=STARTCODE_SEQUENCE_HEADER) {// Log::debug("mpeg::MPEGParser::parseSequenceHeader: sequence header not found, start code=0x%02x\n",// currentStartCode); return false; } sequenceHeader.horizontalSize = readBits(12); sequenceHeader.verticalSize = readBits(12); sequenceHeader.aspectRatio = aspectRatios[readBits(4)]; size_t frameRateIndex = readBits(4); sequenceHeader.frameRateN = frameRateNs[frameRateIndex]; sequenceHeader.frameRateD = frameRateDs[frameRateIndex]; sequenceHeader.bitRate = readBits(18); readBits(1); // marker_bit sequenceHeader.vbvBufferSize = readBits(10); readBits(1); // constraind_parameters_flag sequenceHeader.quantMatrix.loadIntraQMX = readBits(1)==1; if (sequenceHeader.quantMatrix.loadIntraQMX) { for(size_t i = 0; i<sizeof(sequenceHeader.quantMatrix.intraQMX); ++i) { sequenceHeader.quantMatrix.intraQMX[i] = readBits(8); } } sequenceHeader.quantMatrix.loadNonIntraQMX = readBits(1)==1; if (sequenceHeader.quantMatrix.loadNonIntraQMX) { for(size_t i = 0; i<sizeof(sequenceHeader.quantMatrix.nonIntraQMX); ++i) { sequenceHeader.quantMatrix.nonIntraQMX[i] = readBits(8); } } sequenceHeader.quantMatrix.loadChromaIntraQMX = false; sequenceHeader.quantMatrix.loadChromaNonIntraQMX = false; if (nextStartCode()!=STARTCODE_EXTENSION) { Log::debug("mpeg::MPEGParser::readSequenceHeader: Sequence header not followed by sequence extension\n"); return false; } if (readBits(4)!=EXTENSION_SEQUENCE) { Log::debug("mpeg::MPEGParser::readSequenceHeader: Sequence header followed by extension other than a sequence extension\n"); return false; } sequenceHeader.profileAndLevelEscape = readBits(1)==1; sequenceHeader.profile = profiles[readBits(3)]; sequenceHeader.level = levels[readBits(4)]; sequenceHeader.progressive = readBits(1)==1; sequenceHeader.chromaFormat = chromaFormats[readBits(2)]; sequenceHeader.horizontalSize |= readBits(2)<<12; sequenceHeader.verticalSize |= readBits(2)<<12; sequenceHeader.bitRate |= readBits(12)<<18; readBits(1); // marker bit sequenceHeader.vbvBufferSize |= readBits(8) << 10; sequenceHeader.lowDelay = readBits(1)==1; sequenceHeader.frameRateN *= readBits(2)+1; sequenceHeader.frameRateD *= readBits(5)+1; if (!isInterrupted()) { listener.sequence(sequenceHeader); } nextStartCode(); return !isInterrupted();}//------------------------------------------------------------------------------void MPEGParser::parseExtensionAndUserData(unsigned i){// Log::debug("mpeg::MPEGParser::parseExtensionAndUserData\n"); while(!isInterrupted() && (currentStartCode==STARTCODE_EXTENSION || currentStartCode==STARTCODE_USER_DATA)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -