ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

mpegps_decoder.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "audio/audiostream.h"
00024 #include "audio/decoders/raw.h" // ResidualVM
00025 #include "audio/decoders/ac3.h"
00026 #include "audio/decoders/mp3.h"
00027 #include "common/debug.h"
00028 #include "common/endian.h"
00029 #include "common/stream.h"
00030 #include "common/memstream.h" // ResidualVM
00031 #include "common/system.h"
00032 #include "common/textconsole.h"
00033 
00034 #include "video/mpegps_decoder.h"
00035 #include "image/codecs/mpeg.h"
00036 
00037 // The demuxing code is based on libav's demuxing code
00038 
00039 namespace Video {
00040 
00041 // --------------------------------------------------------------------------
00042 // Decoder - This is the part that takes a packet and figures out what to do
00043 // with it.
00044 // --------------------------------------------------------------------------
00045 
00046 enum {
00047     kStartCodePack = 0x1BA,
00048     kStartCodeSystemHeader = 0x1BB,
00049     kStartCodeProgramStreamMap = 0x1BC,
00050     kStartCodePrivateStream1 = 0x1BD,
00051     kStartCodePaddingStream = 0x1BE,
00052     kStartCodePrivateStream2 = 0x1BF
00053 };
00054 
00055 MPEGPSDecoder::MPEGPSDecoder(double decibel) {
00056     _decibel = decibel;
00057     _demuxer = new MPEGPSDemuxer();
00058 }
00059 
00060 MPEGPSDecoder::~MPEGPSDecoder() {
00061     close();
00062     delete _demuxer;
00063 }
00064 
00065 bool MPEGPSDecoder::loadStream(Common::SeekableReadStream *stream) {
00066     close();
00067 
00068     if (!_demuxer->loadStream(stream)) {
00069         close();
00070         return false;
00071     }
00072 
00073     if (!addFirstVideoTrack()) {
00074         close();
00075         return false;
00076     }
00077 
00078     return true;
00079 }
00080 
00081 void MPEGPSDecoder::close() {
00082     VideoDecoder::close();
00083     _demuxer->close();
00084     _streamMap.clear();
00085 }
00086 
00087 MPEGPSDecoder::MPEGStream *MPEGPSDecoder::getStream(uint32 startCode, Common::SeekableReadStream *packet) {
00088     MPEGStream *stream = 0;
00089 
00090     if (_streamMap.contains(startCode)) {
00091         // We already found the stream
00092         stream = _streamMap[startCode];
00093     } else {
00094         // We haven't seen this before
00095 
00096         if (startCode == kStartCodePrivateStream1) {
00097             PrivateStreamType streamType = detectPrivateStreamType(packet);
00098             packet->seek(0);
00099 
00100             // TODO: Handling of these types (as needed)
00101             bool handled = false;
00102             const char *typeName;
00103 
00104             switch (streamType) {
00105             case kPrivateStreamAC3: {
00106                 typeName = "AC-3";
00107 
00108 #ifdef USE_A52
00109                 handled = true;
00110                 AC3AudioTrack *ac3Track = new AC3AudioTrack(*packet, _decibel, getSoundType());
00111                 stream = ac3Track;
00112                 _streamMap[startCode] = ac3Track;
00113                 addTrack(ac3Track);
00114 #endif
00115                 break;
00116             }
00117             case kPrivateStreamDTS:
00118                 typeName = "DTS";
00119                 break;
00120             case kPrivateStreamDVDPCM:
00121                 typeName = "DVD PCM";
00122                 break;
00123             // ResidualVM start
00124             case kPrivateStreamPS2Audio: {
00125                 typeName = "PS2 Audio";
00126 
00127                 handled = true;
00128                 PS2AudioTrack *audioTrack = new PS2AudioTrack(packet, getSoundType());
00129                 stream = audioTrack;
00130                 _streamMap[startCode] = audioTrack;
00131                 addTrack(audioTrack);
00132                 break;
00133             }
00134             // ResidualVM end
00135             default:
00136                 typeName = "Unknown";
00137                 break;
00138             }
00139 
00140             if (!handled) {
00141                 warning("Unhandled DVD private stream: %s", typeName);
00142 
00143                 // Make it 0 so we don't get the warning twice
00144                 _streamMap[startCode] = 0;
00145             }
00146         } else if (startCode >= 0x1E0 && startCode <= 0x1EF) {
00147             // Video stream
00148             // TODO: Multiple video streams
00149             warning("Found extra video stream 0x%04X", startCode);
00150             _streamMap[startCode] = 0;
00151         } else if (startCode >= 0x1C0 && startCode <= 0x1DF) {
00152 #ifdef USE_MAD
00153             // MPEG Audio stream
00154             MPEGAudioTrack *audioTrack = new MPEGAudioTrack(*packet, getSoundType());
00155             stream = audioTrack;
00156             _streamMap[startCode] = audioTrack;
00157             addTrack(audioTrack);
00158 #else
00159             warning("Found audio stream 0x%04X, but no MAD support compiled in", startCode);
00160             _streamMap[startCode] = 0;
00161 #endif
00162         } else {
00163             // Probably not relevant
00164             debug(0, "Found unhandled MPEG-PS stream type 0x%04x", startCode);
00165             _streamMap[startCode] = 0;
00166         }
00167     }
00168 
00169     return stream;
00170 }
00171 
00172 void MPEGPSDecoder::readNextPacket() {
00173     for (;;) {
00174         int32 startCode;
00175         uint32 pts, dts;
00176         Common::SeekableReadStream *packet = _demuxer->getNextPacket(getTime(), startCode, pts, dts);
00177 
00178         if (!packet) {
00179             // End of stream
00180             for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++)
00181                 if ((*it)->getTrackType() == Track::kTrackTypeVideo)
00182                     ((MPEGVideoTrack *)*it)->setEndOfTrack();
00183             return;
00184         }
00185 
00186         MPEGStream *stream = getStream(startCode, packet);
00187 
00188         if (stream) {
00189             packet->seek(0);
00190 
00191             bool done = stream->sendPacket(packet, pts, dts);
00192 
00193             if (done && stream->getStreamType() == MPEGStream::kStreamTypeVideo)
00194                 return;
00195         } else {
00196             delete packet;
00197         }
00198     }
00199 }
00200 
00201 bool MPEGPSDecoder::addFirstVideoTrack() {
00202     int32 startCode;
00203     uint32 pts, dts;
00204     Common::SeekableReadStream *packet = _demuxer->getFirstVideoPacket(startCode, pts, dts);
00205 
00206     if (!packet)
00207         return false;
00208 
00209     // Video stream
00210     // Can be MPEG-1/2 or MPEG-4/h.264. We'll assume the former and
00211     // I hope we never need the latter.
00212     MPEGVideoTrack *track = new MPEGVideoTrack(packet, getDefaultHighColorFormat());
00213     addTrack(track);
00214     _streamMap[startCode] = track;
00215 
00216     return true;
00217 }
00218 
00219 MPEGPSDecoder::PrivateStreamType MPEGPSDecoder::detectPrivateStreamType(Common::SeekableReadStream *packet) {
00220     uint32 dvdCode = packet->readUint32LE();
00221     if (packet->eos())
00222         return kPrivateStreamUnknown;
00223 
00224     uint32 ps2Header = packet->readUint32BE();
00225     if (!packet->eos() && ps2Header == MKTAG('S', 'S', 'h', 'd'))
00226         return kPrivateStreamPS2Audio;
00227 
00228     switch (dvdCode & 0xE0) {
00229     case 0x80:
00230         if ((dvdCode & 0xF8) == 0x88)
00231             return kPrivateStreamDTS;
00232 
00233         return kPrivateStreamAC3;
00234     case 0xA0:
00235         return kPrivateStreamDVDPCM;
00236     default:
00237         break;
00238     }
00239 
00240     return kPrivateStreamUnknown;
00241 }
00242 
00243 // --------------------------------------------------------------------------
00244 // Demuxer - This is the part that reads packets from the stream and delivers
00245 // them to the decoder.
00246 //
00247 // It will buffer a number of packets in advance, because otherwise it may
00248 // not encounter any audio packets until it's far too late to decode them.
00249 // Before I added this, there would be 9 or 10 frames of video before the
00250 // first audio packet, even though the timestamp indicated that the audio
00251 // should start slightly before the video.
00252 // --------------------------------------------------------------------------
00253 
00254 #define PREBUFFERED_PACKETS 150
00255 #define AUDIO_THRESHOLD     100
00256 
00257 MPEGPSDecoder::MPEGPSDemuxer::MPEGPSDemuxer() {
00258     _stream = 0;
00259 }
00260 
00261 MPEGPSDecoder::MPEGPSDemuxer::~MPEGPSDemuxer() {
00262     close();
00263 }
00264 
00265 bool MPEGPSDecoder::MPEGPSDemuxer::loadStream(Common::SeekableReadStream *stream) {
00266     close();
00267 
00268     _stream = stream;
00269 
00270     int queuedPackets = 0;
00271     while (queueNextPacket() && queuedPackets < PREBUFFERED_PACKETS) {
00272         queuedPackets++;
00273     }
00274 
00275     return true;
00276 }
00277 
00278 void MPEGPSDecoder::MPEGPSDemuxer::close() {
00279     delete _stream;
00280     _stream = 0;
00281 
00282     while (!_audioQueue.empty()) {
00283         Packet packet = _audioQueue.pop();
00284         delete packet._stream;
00285     }
00286 
00287     while (!_videoQueue.empty()) {
00288         Packet packet = _videoQueue.pop();
00289         delete packet._stream;
00290     }
00291 }
00292 
00293 Common::SeekableReadStream *MPEGPSDecoder::MPEGPSDemuxer::getFirstVideoPacket(int32 &startCode, uint32 &pts, uint32 &dts) {
00294     if (_videoQueue.empty())
00295         return nullptr;
00296     Packet packet = _videoQueue.front();
00297     startCode = packet._startCode;
00298     pts = packet._pts;
00299     dts = packet._dts;
00300     return packet._stream;
00301 }
00302 
00303 Common::SeekableReadStream *MPEGPSDecoder::MPEGPSDemuxer::getNextPacket(uint32 currentTime, int32 &startCode, uint32 &pts, uint32 &dts) {
00304     queueNextPacket();
00305 
00306     // The idea here is to prioritize the delivery of audio packets,
00307     // because when the decoder wants a frame it will keep asking until it
00308     // gets a frame. There is nothing like that in the decoder to ensure
00309     // speedy delivery of audio.
00310 
00311     if (!_audioQueue.empty()) {
00312         Packet packet = _audioQueue.front();
00313         bool usePacket = false;
00314 
00315         if (packet._pts == 0xFFFFFFFF) {
00316             // No timestamp? Use it just in case. This could be a
00317             // bad idea, but in my tests all audio packets have a
00318             // time stamp.
00319             usePacket = true;
00320         } else {
00321             uint32 packetTime = packet._pts / 90;
00322             if (packetTime <= currentTime || packetTime - currentTime < AUDIO_THRESHOLD || _videoQueue.empty()) {
00323                 // The packet is overdue, or will be soon.
00324                 //
00325                 // TODO: We should pad or trim the first audio
00326                 // packet based on the timestamp to get the
00327                 // audio to start at the exact desired time.
00328                 // But for some reason it seems to work well
00329                 // enough anyway. For now.
00330                 usePacket = true;
00331             }
00332         }
00333 
00334         if (usePacket) {
00335             _audioQueue.pop();
00336             startCode = packet._startCode;
00337             pts = packet._pts;
00338             dts = packet._dts;
00339             return packet._stream;
00340         }
00341     }
00342 
00343     if (!_videoQueue.empty()) {
00344         Packet packet = _videoQueue.pop();
00345         startCode = packet._startCode;
00346         pts = packet._pts;
00347         dts = packet._dts;
00348         return packet._stream;
00349     }
00350 
00351     return nullptr;
00352 }
00353 
00354 bool MPEGPSDecoder::MPEGPSDemuxer::queueNextPacket() {
00355     if (_stream->eos())
00356         return false;
00357 
00358     for (;;) {
00359         int32 startCode;
00360         uint32 pts, dts;
00361         int size = readNextPacketHeader(startCode, pts, dts);
00362 
00363         if (size < 0) {
00364             // End of stream
00365             return false;
00366         }
00367 
00368         Common::SeekableReadStream *stream = _stream->readStream(size);
00369 
00370         if (startCode == kStartCodePrivateStream1 || (startCode >= 0x1C0 && startCode <= 0x1DF)) {
00371             // Audio packet
00372             _audioQueue.push(Packet(stream, startCode, pts, dts));
00373             return true;
00374         }
00375 
00376         if (startCode >= 0x1E0 && startCode <= 0x1EF) {
00377             // Video packet
00378             _videoQueue.push(Packet(stream, startCode, pts, dts));
00379             return true;
00380         }
00381 
00382         delete stream;
00383     }
00384 }
00385 
00386 int MPEGPSDecoder::MPEGPSDemuxer::readNextPacketHeader(int32 &startCode, uint32 &pts, uint32 &dts) {
00387     for (;;) {
00388         uint32 size;
00389         startCode = findNextStartCode(size);
00390 
00391         if (_stream->eos())
00392             return -1;
00393 
00394         if (startCode < 0)
00395             continue;
00396 
00397         uint32 lastSync = _stream->pos();
00398 
00399         if (startCode == kStartCodePack || startCode == kStartCodeSystemHeader)
00400             continue;
00401 
00402         int length = _stream->readUint16BE();
00403 
00404         if (startCode == kStartCodePaddingStream || startCode == kStartCodePrivateStream2) {
00405             _stream->skip(length);
00406             continue;
00407         }
00408 
00409         if (startCode == kStartCodeProgramStreamMap) {
00410             parseProgramStreamMap(length);
00411             continue;
00412         }
00413 
00414         // Find matching stream
00415         if (!((startCode >= 0x1C0 && startCode <= 0x1DF) ||
00416                 (startCode >= 0x1E0 && startCode <= 0x1EF) ||
00417                 startCode == kStartCodePrivateStream1 || startCode == 0x1FD))
00418             continue;
00419 
00420         // Stuffing
00421         byte c;
00422         for (;;) {
00423             if (length < 1) {
00424                 _stream->seek(lastSync);
00425                 continue;
00426             }
00427 
00428             c = _stream->readByte();
00429             length--;
00430 
00431             // XXX: for mpeg1, should test only bit 7
00432             if (c != 0xFF)
00433                 break;
00434         }
00435 
00436         if ((c & 0xC0) == 0x40) {
00437             // Buffer scale and size
00438             _stream->readByte();
00439             c = _stream->readByte();
00440             length -= 2;
00441         }
00442 
00443         pts = 0xFFFFFFFF;
00444         dts = 0xFFFFFFFF;
00445 
00446         if ((c & 0xE0) == 0x20) {
00447             dts = pts = readPTS(c);
00448             length -= 4;
00449 
00450             if (c & 0x10) {
00451                 dts = readPTS(-1);
00452                 length -= 5;
00453             }
00454         } else if ((c & 0xC0) == 0x80) {
00455             // MPEG-2 PES
00456             byte flags = _stream->readByte();
00457             int headerLength = _stream->readByte();
00458             length -= 2;
00459 
00460             if (headerLength > length) {
00461                 _stream->seek(lastSync);
00462                 continue;
00463             }
00464 
00465             length -= headerLength;
00466 
00467             if (flags & 0x80) {
00468                 dts = pts = readPTS(-1);
00469                 headerLength -= 5;
00470 
00471                 if (flags & 0x40) {
00472                     dts = readPTS(-1);
00473                     headerLength -= 5;
00474                 }
00475             }
00476 
00477             if (flags & 0x3F && headerLength == 0) {
00478                 flags &= 0xC0;
00479                 warning("Further flags set but no bytes left");
00480             }
00481 
00482             if (flags & 0x01) { // PES extension
00483                 byte pesExt =_stream->readByte();
00484                 headerLength--;
00485 
00486                 // Skip PES private data, program packet sequence
00487                 int skip = (pesExt >> 4) & 0xB;
00488                 skip += skip & 0x9;
00489 
00490                 if (pesExt & 0x40 || skip > headerLength) {
00491                     warning("pesExt %x is invalid", pesExt);
00492                     pesExt = skip = 0;
00493                 } else {
00494                     _stream->skip(skip);
00495                     headerLength -= skip;
00496                 }
00497 
00498                 if (pesExt & 0x01) { // PES extension 2
00499                     byte ext2Length = _stream->readByte();
00500                     headerLength--;
00501 
00502                     if ((ext2Length & 0x7F) != 0) {
00503                         byte idExt = _stream->readByte();
00504 
00505                         if ((idExt & 0x80) == 0)
00506                             startCode = (startCode & 0xFF) << 8;
00507 
00508                         headerLength--;
00509                     }
00510                 }
00511             }
00512 
00513             if (headerLength < 0) {
00514                 _stream->seek(lastSync);
00515                 continue;
00516             }
00517 
00518             _stream->skip(headerLength);
00519         } else if (c != 0xF) {
00520             continue;
00521         }
00522 
00523         if (length < 0) {
00524             _stream->seek(lastSync);
00525             continue;
00526         }
00527 
00528         return length;
00529     }
00530 }
00531 
00532 #define MAX_SYNC_SIZE 100000
00533 
00534 int MPEGPSDecoder::MPEGPSDemuxer::findNextStartCode(uint32 &size) {
00535     size = MAX_SYNC_SIZE;
00536     int32 state = 0xFF;
00537 
00538     while (size > 0) {
00539         byte v = _stream->readByte();
00540 
00541         if (_stream->eos())
00542             return -1;
00543 
00544         size--;
00545 
00546         if (state == 0x1)
00547             return ((state << 8) | v) & 0xFFFFFF;
00548 
00549         state = ((state << 8) | v) & 0xFFFFFF;
00550     }
00551 
00552     return -1;
00553 }
00554 
00555 uint32 MPEGPSDecoder::MPEGPSDemuxer::readPTS(int c) {
00556     byte buf[5];
00557 
00558     buf[0] = (c < 0) ? _stream->readByte() : c;
00559     _stream->read(buf + 1, 4);
00560 
00561     return ((buf[0] & 0x0E) << 29) | ((READ_BE_UINT16(buf + 1) >> 1) << 15) | (READ_BE_UINT16(buf + 3) >> 1);
00562 }
00563 
00564 void MPEGPSDecoder::MPEGPSDemuxer::parseProgramStreamMap(int length) {
00565     _stream->readByte();
00566     _stream->readByte();
00567 
00568     // skip program stream info
00569     _stream->skip(_stream->readUint16BE());
00570 
00571     int esMapLength = _stream->readUint16BE();
00572 
00573     while (esMapLength >= 4) {
00574         _stream->readByte(); // type
00575         _stream->readByte(); // esID
00576         uint16 esInfoLength = _stream->readUint16BE();
00577 
00578         // Skip program stream info
00579         _stream->skip(esInfoLength);
00580 
00581         esMapLength -= 4 + esInfoLength;
00582     }
00583 
00584     _stream->readUint32BE(); // CRC32
00585 }
00586 
00587 // --------------------------------------------------------------------------
00588 // Video track
00589 // --------------------------------------------------------------------------
00590 
00591 MPEGPSDecoder::MPEGVideoTrack::MPEGVideoTrack(Common::SeekableReadStream *firstPacket, const Graphics::PixelFormat &format) {
00592     _surface = 0;
00593     _endOfTrack = false;
00594     _curFrame = -1;
00595     _framePts = 0xFFFFFFFF;
00596     _nextFrameStartTime = Audio::Timestamp(0, 27000000); // 27 MHz timer
00597 
00598     findDimensions(firstPacket, format);
00599 
00600 #ifdef USE_MPEG2
00601     _mpegDecoder = new Image::MPEGDecoder();
00602 #endif
00603 }
00604 
00605 MPEGPSDecoder::MPEGVideoTrack::~MPEGVideoTrack() {
00606 #ifdef USE_MPEG2
00607     delete _mpegDecoder;
00608 #endif
00609 
00610     if (_surface) {
00611         _surface->free();
00612         delete _surface;
00613     }
00614 }
00615 
00616 uint16 MPEGPSDecoder::MPEGVideoTrack::getWidth() const {
00617     return _surface ? _surface->w : 0;
00618 }
00619 
00620 uint16 MPEGPSDecoder::MPEGVideoTrack::getHeight() const {
00621     return _surface ? _surface->h : 0;
00622 }
00623 
00624 Graphics::PixelFormat MPEGPSDecoder::MPEGVideoTrack::getPixelFormat() const {
00625     if (!_surface)
00626         return Graphics::PixelFormat();
00627 
00628     return _surface->format;
00629 }
00630 
00631 const Graphics::Surface *MPEGPSDecoder::MPEGVideoTrack::decodeNextFrame() {
00632     return _surface;
00633 }
00634 
00635 bool MPEGPSDecoder::MPEGVideoTrack::sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts) {
00636 #ifdef USE_MPEG2
00637     if (pts != 0xFFFFFFFF) {
00638         _framePts = pts;
00639     }
00640 
00641     uint32 framePeriod;
00642     bool foundFrame = _mpegDecoder->decodePacket(*packet, framePeriod, _surface);
00643 
00644     if (foundFrame) {
00645         _curFrame++;
00646 
00647         // If there has been a timestamp since the previous frame, use that for
00648         // syncing. Usually it will be the timestamp from the current packet,
00649         // but it might not be.
00650 
00651         if (_framePts != 0xFFFFFFFF) {
00652             _nextFrameStartTime = Audio::Timestamp(_framePts / 90, 27000000);
00653         } else {
00654             _nextFrameStartTime = _nextFrameStartTime.addFrames(framePeriod);
00655         }
00656 
00657         _framePts = 0xFFFFFFFF;
00658     }
00659 #endif
00660 
00661     delete packet;
00662 
00663 #ifdef USE_MPEG2
00664     return foundFrame;
00665 #else
00666     return true;
00667 #endif
00668 }
00669 
00670 void MPEGPSDecoder::MPEGVideoTrack::findDimensions(Common::SeekableReadStream *firstPacket, const Graphics::PixelFormat &format) {
00671     // First, check for the picture start code
00672     if (firstPacket->readUint32BE() != 0x1B3)
00673         error("Failed to detect MPEG sequence start");
00674 
00675     // This is part of the bitstream, but there's really no purpose
00676     // to use Common::BitStream just for this: 12 bits width, 12 bits
00677     // height
00678     uint16 width = firstPacket->readByte() << 4;
00679     uint16 height = firstPacket->readByte();
00680     width |= (height & 0xF0) >> 4;
00681     height = ((height & 0x0F) << 8) | firstPacket->readByte();
00682 
00683     debug(0, "MPEG dimensions: %dx%d", width, height);
00684 
00685     _surface = new Graphics::Surface();
00686     _surface->create(width, height, format);
00687 
00688     firstPacket->seek(0);
00689 }
00690 
00691 // --------------------------------------------------------------------------
00692 // Audio track
00693 // --------------------------------------------------------------------------
00694 
00695 #ifdef USE_MAD
00696 
00697 // The audio code here is almost entirely based on what we do in mp3.cpp
00698 
00699 MPEGPSDecoder::MPEGAudioTrack::MPEGAudioTrack(Common::SeekableReadStream &firstPacket, Audio::Mixer::SoundType soundType) :
00700         AudioTrack(soundType) {
00701     _audStream = Audio::makePacketizedMP3Stream(firstPacket);
00702 }
00703 
00704 MPEGPSDecoder::MPEGAudioTrack::~MPEGAudioTrack() {
00705     delete _audStream;
00706 }
00707 
00708 bool MPEGPSDecoder::MPEGAudioTrack::sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts) {
00709     _audStream->queuePacket(packet);
00710     return true;
00711 }
00712 
00713 Audio::AudioStream *MPEGPSDecoder::MPEGAudioTrack::getAudioStream() const {
00714     return _audStream;
00715 }
00716 
00717 #endif
00718 
00719 #ifdef USE_A52
00720 
00721 MPEGPSDecoder::AC3AudioTrack::AC3AudioTrack(Common::SeekableReadStream &firstPacket, double decibel, Audio::Mixer::SoundType soundType) :
00722         AudioTrack(soundType) {
00723     _audStream = Audio::makeAC3Stream(firstPacket, decibel);
00724     if (!_audStream)
00725         error("Could not create AC-3 stream");
00726 }
00727 
00728 MPEGPSDecoder::AC3AudioTrack::~AC3AudioTrack() {
00729     delete _audStream;
00730 }
00731 
00732 bool MPEGPSDecoder::AC3AudioTrack::sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts) {
00733     // Skip DVD code
00734     packet->readUint32LE();
00735     if (packet->eos())
00736         return true;
00737 
00738     _audStream->queuePacket(packet);
00739     return true;
00740 }
00741 
00742 Audio::AudioStream *MPEGPSDecoder::AC3AudioTrack::getAudioStream() const {
00743     return _audStream;
00744 }
00745 
00746 #endif
00747 
00748 // ResidualVM specific start
00749 MPEGPSDecoder::PS2AudioTrack::PS2AudioTrack(Common::SeekableReadStream *firstPacket, Audio::Mixer::SoundType soundType) :
00750         AudioTrack(soundType) {
00751     firstPacket->seek(12); // unknown data (4), 'SShd', header size (4)
00752 
00753     _soundType = firstPacket->readUint32LE();
00754 
00755     if (_soundType == PS2_ADPCM)
00756         error("Unhandled PS2 ADPCM sound in MPEG-PS video");
00757     else if (_soundType != PS2_PCM)
00758         error("Unknown PS2 sound type %x", _soundType);
00759 
00760     uint32 sampleRate = firstPacket->readUint32LE();
00761     _channels = firstPacket->readUint32LE();
00762     _interleave = firstPacket->readUint32LE();
00763 
00764     byte flags = Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN;
00765     if (_channels == 2)
00766         flags |= Audio::FLAG_STEREO;
00767 
00768     _blockBuffer = new byte[_interleave * _channels];
00769     _blockPos = _blockUsed = 0;
00770     _audStream = Audio::makePacketizedRawStream(sampleRate, flags);
00771     _isFirstPacket = true;
00772 
00773     firstPacket->seek(0);
00774 }
00775 
00776 MPEGPSDecoder::PS2AudioTrack::~PS2AudioTrack() {
00777     delete[] _blockBuffer;
00778     delete _audStream;
00779 }
00780 
00781 bool MPEGPSDecoder::PS2AudioTrack::sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts) {
00782     packet->skip(4);
00783 
00784     if (_isFirstPacket) {
00785         // Skip over the header which we already parsed
00786         packet->skip(4);
00787         packet->skip(packet->readUint32LE());
00788 
00789         if (packet->readUint32BE() != MKTAG('S', 'S', 'b', 'd'))
00790             error("Failed to find 'SSbd' tag");
00791 
00792         packet->readUint32LE(); // body size
00793         _isFirstPacket = false;
00794     }
00795 
00796     uint32 size = packet->size() - packet->pos();
00797     uint32 bytesPerChunk = _interleave * _channels;
00798     uint32 sampleCount = calculateSampleCount(size);
00799 
00800     byte *buffer = (byte *)malloc(sampleCount * 2);
00801     int16 *ptr = (int16 *)buffer;
00802 
00803     // Handle any full chunks first
00804     while (size >= bytesPerChunk) {
00805         packet->read(_blockBuffer + _blockPos, bytesPerChunk - _blockPos);
00806         size -= bytesPerChunk - _blockPos;
00807         _blockPos = 0;
00808 
00809         for (uint32 i = _blockUsed; i < _interleave / 2; i++)
00810             for (uint32 j = 0; j < _channels; j++)
00811                 *ptr++ = READ_UINT16(_blockBuffer + i * 2 + j * _interleave);
00812 
00813         _blockUsed = 0;
00814     }
00815 
00816     // Then fallback on loading any leftover
00817     if (size > 0) {
00818         packet->read(_blockBuffer, size);
00819         _blockPos = size;
00820 
00821         if (size > (_channels - 1) * _interleave) {
00822             _blockUsed = (size - (_channels - 1) * _interleave) / 2;
00823 
00824             for (uint32 i = 0; i < _blockUsed; i++)
00825                 for (uint32 j = 0; j < _channels; j++)
00826                     *ptr++ = READ_UINT16(_blockBuffer + i * 2 + j * _interleave);
00827         }
00828     }
00829 
00830     _audStream->queuePacket(new Common::MemoryReadStream(buffer, sampleCount * 2, DisposeAfterUse::YES));
00831 
00832     delete packet;
00833     return true;
00834 }
00835 
00836 Audio::AudioStream *MPEGPSDecoder::PS2AudioTrack::getAudioStream() const {
00837     return _audStream;
00838 }
00839 
00840 uint32 MPEGPSDecoder::PS2AudioTrack::calculateSampleCount(uint32 packetSize) const {
00841     uint32 bytesPerChunk = _interleave * _channels, result = 0;
00842 
00843     // If we have a partial block, subtract the remainder from the size. That
00844     // gets put towards reading the partial block
00845     if (_blockPos != 0) {
00846         packetSize -= bytesPerChunk - _blockPos;
00847         result += (_interleave / 2) - _blockUsed;
00848     }
00849 
00850     // Round the number of whole chunks down and then calculate how many samples that gives us
00851     result += (packetSize / bytesPerChunk) * _interleave / 2;
00852 
00853     // Total up anything we can get from the remainder
00854     packetSize %= bytesPerChunk;
00855     if (packetSize > (_channels - 1) * _interleave)
00856         result += (packetSize - (_channels - 1) * _interleave) / 2;
00857 
00858     return result * _channels;
00859 }
00860 // ResidualVM specific end
00861 
00862 } // End of namespace Video


Generated on Sat Aug 8 2020 05:01:28 for ResidualVM by doxygen 1.7.1
curved edge   curved edge