From 2042672ec718b177268f590c9f10e43a6fbf6a00 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 15 May 2014 00:05:40 -0700 Subject: [PATCH] Correct the audio pts from the actual stream data. Before, we would just increment it and hope we were right. There's no reason we'd be wrong, but with seeking we have to be more careful. --- Core/HW/BufferQueue.h | 56 ++++++++++++++++++++++++++++++++++++++--- Core/HW/MediaEngine.cpp | 12 ++++++--- Core/HW/MediaEngine.h | 6 ++--- Core/HW/MpegDemux.cpp | 6 ++--- Core/HW/MpegDemux.h | 2 +- 5 files changed, 69 insertions(+), 13 deletions(-) diff --git a/Core/HW/BufferQueue.h b/Core/HW/BufferQueue.h index 0ceb0985e315..3c58005357d4 100644 --- a/Core/HW/BufferQueue.h +++ b/Core/HW/BufferQueue.h @@ -17,6 +17,7 @@ #pragma once +#include #include #include "Common/ChunkFile.h" @@ -60,11 +61,12 @@ struct BufferQueue { return bufQueueSize - getQueueSize(); } - bool push(unsigned char *buf, int addsize) { + bool push(const unsigned char *buf, int addsize, s64 pts = 0) { int queuesz = getQueueSize(); int space = bufQueueSize - queuesz; if (space < addsize || addsize < 0) return false; + savePts(pts); if (end + addsize <= bufQueueSize) { memcpy(bufQueue + end, buf, addsize); end += addsize; @@ -77,12 +79,15 @@ struct BufferQueue { return true; } - int pop_front(unsigned char *buf, int wantedsize) { + int pop_front(unsigned char *buf, int wantedsize, s64 *pts = NULL) { if (wantedsize <= 0) return 0; int bytesgot = getQueueSize(); if (wantedsize < bytesgot) bytesgot = wantedsize; + if (pts != NULL) { + *pts = findPts(bytesgot); + } if (buf) { if (start + bytesgot <= bufQueueSize) { memcpy(buf, bufQueue + start, bytesgot); @@ -120,14 +125,59 @@ struct BufferQueue { } void DoState(PointerWrap &p) { + auto s = p.Section("BufferQueue", 0, 1); + p.Do(bufQueueSize); p.Do(start); p.Do(end); - if (bufQueue) + if (bufQueue) { p.DoArray(bufQueue, bufQueueSize); + } + + if (s >= 1) { + p.Do(ptsMarks); + } + } + +private: + void savePts(u64 pts) { + if (pts != 0) { + ptsMarks[end] = pts; + } + } + + u64 findPts(std::map::iterator earliest, std::map::iterator latest) { + u64 pts = 0; + // Take the first one, that is the pts of this packet. + if (earliest != latest) { + pts = earliest->second; + } + ptsMarks.erase(earliest, latest); + return pts; + } + + u64 findPts(int packetSize) { + auto earliest = ptsMarks.lower_bound(start); + auto latest = ptsMarks.lower_bound(start + packetSize); + + u64 pts = findPts(earliest, latest); + + // If it wraps around, we have to look at the other half too. + if (start + packetSize > bufQueueSize) { + earliest = ptsMarks.begin(); + latest = ptsMarks.lower_bound(start + packetSize - bufQueueSize); + u64 pts2 = findPts(earliest, latest); + if (pts2 != 0) { + pts = pts2; + } + } + + return pts; } unsigned char* bufQueue; int start, end; int bufQueueSize; + + std::map ptsMarks; }; diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp index d93ffe51d812..a2151b73a1d8 100644 --- a/Core/HW/MediaEngine.cpp +++ b/Core/HW/MediaEngine.cpp @@ -319,7 +319,7 @@ void MediaEngine::closeContext() m_buffer = 0; } -bool MediaEngine::loadStream(u8* buffer, int readSize, int RingbufferSize) +bool MediaEngine::loadStream(const u8 *buffer, int readSize, int RingbufferSize) { closeMedia(); @@ -336,7 +336,7 @@ bool MediaEngine::loadStream(u8* buffer, int readSize, int RingbufferSize) return true; } -int MediaEngine::addStreamData(u8* buffer, int addSize) { +int MediaEngine::addStreamData(const u8 *buffer, int addSize) { int size = addSize; if (size > 0 && m_pdata) { if (!m_pdata->push(buffer, size)) @@ -762,7 +762,13 @@ int MediaEngine::getNextAudioFrame(u8 **buf, int *headerCode1, int *headerCode2) // Demux now (rather than on add data) so that we select the right stream. m_demux->demux(m_audioStream); - return m_demux->getNextAudioFrame(buf, headerCode1, headerCode2); + s64 pts = 0; + int result = m_demux->getNextAudioFrame(buf, headerCode1, headerCode2, &pts); + if (pts != 0) { + // m_audiopts is supposed to be after the returned frame. + m_audiopts = pts - m_firstTimeStamp + 4180; + } + return result; } int MediaEngine::getAudioSamples(u32 bufferPtr) { diff --git a/Core/HW/MediaEngine.h b/Core/HW/MediaEngine.h index f749bb1d5fdd..28442d18e0e5 100644 --- a/Core/HW/MediaEngine.h +++ b/Core/HW/MediaEngine.h @@ -41,7 +41,7 @@ struct AVFormatContext; struct AVCodecContext; #endif -inline s64 getMpegTimeStamp(u8* buf) { +inline s64 getMpegTimeStamp(const u8 *buf) { return (s64)buf[5] | ((s64)buf[4] << 8) | ((s64)buf[3] << 16) | ((s64)buf[2] << 24) | ((s64)buf[1] << 32) | ((s64)buf[0] << 36); } @@ -59,13 +59,13 @@ class MediaEngine ~MediaEngine(); void closeMedia(); - bool loadStream(u8* buffer, int readSize, int RingbufferSize); + bool loadStream(const u8 *buffer, int readSize, int RingbufferSize); // open the mpeg context bool openContext(); void closeContext(); // Returns number of packets actually added. I guess the buffer might be full. - int addStreamData(u8* buffer, int addSize); + int addStreamData(const u8 *buffer, int addSize); bool seekTo(s64 timestamp, int videoPixelMode); bool setVideoStream(int streamNum, bool force = false); diff --git a/Core/HW/MpegDemux.cpp b/Core/HW/MpegDemux.cpp index f346c3e84b61..b42403630fea 100644 --- a/Core/HW/MpegDemux.cpp +++ b/Core/HW/MpegDemux.cpp @@ -145,7 +145,7 @@ int MpegDemux::demuxStream(bool bdemux, int startCode, int channel) length = readPesHeader(pesHeader, length, startCode); if (pesHeader.channel == channel || channel < 0) { channel = pesHeader.channel; - m_audioStream.push(m_buf + m_index, length); + m_audioStream.push(m_buf + m_index, length, pesHeader.pts); } skip(length); } else { @@ -234,7 +234,7 @@ static int getNextHeaderPosition(u8* audioStream, int curpos, int limit, int fra return -1; } -int MpegDemux::getNextAudioFrame(u8 **buf, int *headerCode1, int *headerCode2) +int MpegDemux::getNextAudioFrame(u8 **buf, int *headerCode1, int *headerCode2, s64 *pts) { int gotsize; int frameSize; @@ -247,7 +247,7 @@ int MpegDemux::getNextAudioFrame(u8 **buf, int *headerCode1, int *headerCode2) } else { audioPos = gotsize; } - m_audioStream.pop_front(0, audioPos); + m_audioStream.pop_front(0, audioPos, pts); if (buf) { *buf = m_audioFrame + 8; } diff --git a/Core/HW/MpegDemux.h b/Core/HW/MpegDemux.h index 11f2bccf82ab..f52904b867d6 100644 --- a/Core/HW/MpegDemux.h +++ b/Core/HW/MpegDemux.h @@ -18,7 +18,7 @@ class MpegDemux void demux(int audioChannel); // return its framesize - int getNextAudioFrame(u8 **buf, int *headerCode1, int *headerCode2); + int getNextAudioFrame(u8 **buf, int *headerCode1, int *headerCode2, s64 *pts = NULL); bool hasNextAudioFrame(int *gotsizeOut, int *frameSizeOut, int *headerCode1, int *headerCode2); inline int getRemainSize() {