mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
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.
This commit is contained in:
parent
2d12eb3394
commit
2042672ec7
5 changed files with 69 additions and 13 deletions
|
@ -17,6 +17,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <cstring>
|
||||
#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<u32, s64>::iterator earliest, std::map<u32, s64>::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<u32, s64> ptsMarks;
|
||||
};
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 @@ public:
|
|||
~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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ public:
|
|||
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() {
|
||||
|
|
Loading…
Add table
Reference in a new issue