mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Added PTS to the converted PCM audio when replaying a DVD
This commit is contained in:
parent
57bd015bcb
commit
d78d555b27
@ -115,6 +115,7 @@ Helmut Sch
|
||||
Andreas Schultz <aschultz@warp10.net>
|
||||
for adding support for replaying DVDs (much of this was derived from
|
||||
dvdplayer-0.5 by Matjaz Thaler <matjaz.thaler@guest.arnes.si>)
|
||||
for adding PTS to the converted PCM audio when replaying a DVD
|
||||
|
||||
Aaron Holtzman
|
||||
for writing 'ac3dec'
|
||||
|
5
HISTORY
5
HISTORY
@ -831,7 +831,7 @@ Video Disk Recorder Revision History
|
||||
- Fixed handling trick modes near the beginning and end of a recording.
|
||||
- Pressing the "Back" button while replaying a DVD now leads to the DVD menu.
|
||||
|
||||
2001-10-28: Version 0.98
|
||||
2001-11-03: Version 0.98
|
||||
|
||||
- Completed storing the current audio volume in the setup.conf file (thanks
|
||||
to Andy Grobb).
|
||||
@ -851,3 +851,6 @@ Video Disk Recorder Revision History
|
||||
on an other free DVB card (if one is free at the moment). See MANUAL for
|
||||
details.
|
||||
- Added some missing teletext PIDs (thanks to Norbert Schmidt).
|
||||
- Added PTS to the converted PCM audio when replaying a DVD (thanks to Andreas
|
||||
Schultz). Now the audio and video of a DVD replayed over the DVB card's A/V
|
||||
out should always be in sync.
|
||||
|
449
dvbapi.c
449
dvbapi.c
@ -7,7 +7,7 @@
|
||||
* DVD support initially written by Andreas Schultz <aschultz@warp10.net>
|
||||
* based on dvdplayer-0.5 by Matjaz Thaler <matjaz.thaler@guest.arnes.si>
|
||||
*
|
||||
* $Id: dvbapi.c 1.133 2001/10/27 13:00:29 kls Exp $
|
||||
* $Id: dvbapi.c 1.134 2001/11/03 10:59:34 kls Exp $
|
||||
*/
|
||||
|
||||
//#define DVDDEBUG 1
|
||||
@ -713,7 +713,10 @@ protected:
|
||||
void TrickSpeed(int Increment);
|
||||
virtual void Empty(bool Block = false);
|
||||
virtual void StripAudioPackets(uchar *b, int Length, uchar Except = 0x00) {}
|
||||
virtual void PlayExternalDolby(const uchar *b, int MaxLength);
|
||||
virtual void Output(void);
|
||||
void putFrame(cFrame *Frame);
|
||||
void putFrame(unsigned char *Data, int Length, eFrameType Type = ftUnknown);
|
||||
public:
|
||||
cPlayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev);
|
||||
virtual ~cPlayBuffer();
|
||||
@ -759,6 +762,28 @@ cPlayBuffer::~cPlayBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void cPlayBuffer::PlayExternalDolby(const uchar *b, int MaxLength)
|
||||
{
|
||||
if (dolbyDev) {
|
||||
if (b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01) {
|
||||
if (b[3] == 0xBD) { // dolby
|
||||
int l = b[4] * 256 + b[5] + 6;
|
||||
int written = b[8] + 9; // skips the PES header
|
||||
int n = min(l - written, MaxLength);
|
||||
while (n > 0) {
|
||||
int w = fwrite(&b[written], 1, n, dolbyDev);
|
||||
if (w < 0) {
|
||||
LOG_ERROR;
|
||||
break;
|
||||
}
|
||||
n -= w;
|
||||
written += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cPlayBuffer::Output(void)
|
||||
{
|
||||
dsyslog(LOG_INFO, "output thread started (pid=%d)", getpid());
|
||||
@ -771,24 +796,28 @@ void cPlayBuffer::Output(void)
|
||||
}
|
||||
const cFrame *frame = Get();
|
||||
if (frame) {
|
||||
StripAudioPackets((uchar *)frame->Data(), frame->Count(), (playMode == pmFast || playMode == pmSlow) ? 0x00 : audioTrack);//XXX
|
||||
const uchar *p = frame->Data();
|
||||
int r = frame->Count();
|
||||
while (r > 0 && Busy() && !blockOutput) {
|
||||
cFile::FileReadyForWriting(videoDev, 100);
|
||||
int w = write(videoDev, p, r);
|
||||
if (w > 0) {
|
||||
p += w;
|
||||
r -= w;
|
||||
if (frame->Type() == ftDolby)
|
||||
PlayExternalDolby(frame->Data(), frame->Count());
|
||||
else {
|
||||
StripAudioPackets((uchar *)frame->Data(), frame->Count(), (playMode == pmFast || playMode == pmSlow) ? 0x00 : audioTrack);//XXX
|
||||
const uchar *p = frame->Data();
|
||||
int r = frame->Count();
|
||||
while (r > 0 && Busy() && !blockOutput) {
|
||||
cFile::FileReadyForWriting(videoDev, 100);
|
||||
int w = write(videoDev, p, r);
|
||||
if (w > 0) {
|
||||
p += w;
|
||||
r -= w;
|
||||
}
|
||||
else if (w < 0 && FATALERRNO) {
|
||||
LOG_ERROR;
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (w < 0 && FATALERRNO) {
|
||||
LOG_ERROR;
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
writeIndex = frame->Index();
|
||||
backTrace.Add(frame->Index(), frame->Count());
|
||||
writeIndex = frame->Index();
|
||||
backTrace.Add(frame->Index(), frame->Count());
|
||||
}
|
||||
Drop(frame);
|
||||
}
|
||||
}
|
||||
@ -796,6 +825,20 @@ void cPlayBuffer::Output(void)
|
||||
dsyslog(LOG_INFO, "output thread ended (pid=%d)", getpid());
|
||||
}
|
||||
|
||||
void cPlayBuffer::putFrame(cFrame *Frame)
|
||||
{
|
||||
while (Busy() && !blockInput) {
|
||||
if (Put(Frame))
|
||||
return;
|
||||
}
|
||||
delete Frame; // caller relies on frame being put, otherwise this would be a memory leak!
|
||||
}
|
||||
|
||||
void cPlayBuffer::putFrame(unsigned char *Data, int Length, eFrameType Type)
|
||||
{
|
||||
putFrame(new cFrame(Data, Length, Type));
|
||||
}
|
||||
|
||||
void cPlayBuffer::TrickSpeed(int Increment)
|
||||
{
|
||||
int nts = trickSpeed + Increment;
|
||||
@ -1089,11 +1132,8 @@ void cReplayBuffer::Input(void)
|
||||
}
|
||||
else // allows replay even if the index file is missing
|
||||
r = read(replayFile, b, sizeof(b));
|
||||
if (r > 0) {
|
||||
cFrame *frame = new cFrame(b, r, readIndex);
|
||||
while (Busy() && !blockInput && !Put(frame))
|
||||
;
|
||||
}
|
||||
if (r > 0)
|
||||
putFrame(new cFrame(b, r, ftUnknown, readIndex));
|
||||
else if (r == 0)
|
||||
eof = true;
|
||||
else if (r < 0 && FATALERRNO) {
|
||||
@ -1117,19 +1157,8 @@ void cReplayBuffer::StripAudioPackets(uchar *b, int Length, uchar Except)
|
||||
int l = b[i + 4] * 256 + b[i + 5] + 6;
|
||||
switch (c) {
|
||||
case 0xBD: // dolby
|
||||
if (Except && dolbyDev) {
|
||||
int written = b[i + 8] + 9; // skips the PES header
|
||||
int n = l - written;
|
||||
while (n > 0) {
|
||||
int w = fwrite(&b[i + written], 1, n, dolbyDev);
|
||||
if (w < 0) {
|
||||
LOG_ERROR;
|
||||
break;
|
||||
}
|
||||
n -= w;
|
||||
written += w;
|
||||
}
|
||||
}
|
||||
if (Except && dolbyDev)
|
||||
PlayExternalDolby(&b[i], Length - i);
|
||||
// continue with deleting the data - otherwise it disturbs DVB replay
|
||||
case 0xC0 ... 0xC1: // audio
|
||||
if (c == 0xC1)
|
||||
@ -1290,10 +1319,166 @@ bool cReplayBuffer::NextFile(uchar FileNumber, int FileOffset)
|
||||
}
|
||||
|
||||
#ifdef DVDSUPPORT
|
||||
|
||||
#define SYSTEM_HEADER 0xBB
|
||||
#define PROG_STREAM_MAP 0xBC
|
||||
#ifndef PRIVATE_STREAM1
|
||||
#define PRIVATE_STREAM1 0xBD
|
||||
#endif
|
||||
#define PADDING_STREAM 0xBE
|
||||
#ifndef PRIVATE_STREAM2
|
||||
#define PRIVATE_STREAM2 0xBF
|
||||
#endif
|
||||
#define AUDIO_STREAM_S 0xC0
|
||||
#define AUDIO_STREAM_E 0xDF
|
||||
#define VIDEO_STREAM_S 0xE0
|
||||
#define VIDEO_STREAM_E 0xEF
|
||||
#define ECM_STREAM 0xF0
|
||||
#define EMM_STREAM 0xF1
|
||||
#define DSM_CC_STREAM 0xF2
|
||||
#define ISO13522_STREAM 0xF3
|
||||
#define PROG_STREAM_DIR 0xFF
|
||||
|
||||
#define cOPENDVD 0
|
||||
#define cOPENTITLE 1
|
||||
#define cOPENCHAPTER 2
|
||||
#define cOUTCELL 3
|
||||
#define cREADFRAME 4
|
||||
#define cOUTPACK 5
|
||||
#define cOUTFRAMES 6
|
||||
|
||||
#define aAC3 0x80
|
||||
#define aLPCM 0xA0
|
||||
|
||||
// --- cAC3toPCM -------------------------------------------------------------
|
||||
|
||||
class cAC3toPCM {
|
||||
private:
|
||||
enum { AC3_STOP, AC3_START, AC3_PLAY } ac3stat;
|
||||
uchar *ac3data;
|
||||
int ac3inp;
|
||||
int ac3outp;
|
||||
public:
|
||||
cAC3toPCM(void);
|
||||
~cAC3toPCM();
|
||||
void Clear(void);
|
||||
void Put(unsigned char *sector, int length);
|
||||
cFrame *Get(int size, uchar PTSflags = 0, uchar *PTSdata = 0);
|
||||
};
|
||||
|
||||
cAC3toPCM::cAC3toPCM(void)
|
||||
{
|
||||
ac3dec_init();
|
||||
ac3data = new uchar[AC3_BUFFER_SIZE];
|
||||
Clear();
|
||||
}
|
||||
|
||||
cAC3toPCM::~cAC3toPCM()
|
||||
{
|
||||
delete ac3data;
|
||||
}
|
||||
|
||||
void cAC3toPCM::Clear(void)
|
||||
{
|
||||
ac3stat = AC3_START;
|
||||
ac3outp = ac3inp = 0;
|
||||
}
|
||||
|
||||
void cAC3toPCM::Put(unsigned char *sector, int length)
|
||||
{
|
||||
ac3dec_decode_data(sector, sector + length, ac3stat == AC3_START, &ac3inp, &ac3outp, (char *)ac3data);
|
||||
ac3stat = AC3_PLAY;
|
||||
}
|
||||
|
||||
// data=PCM samples, 16 bit, LSB first, 48kHz, stereo
|
||||
cFrame *cAC3toPCM::Get(int size, uchar PTSflags, uchar *PTSdata)
|
||||
{
|
||||
if (ac3inp == ac3outp)
|
||||
return NULL;
|
||||
|
||||
#define MAXSIZE 2022
|
||||
|
||||
uchar buffer[2048];
|
||||
uchar *data;
|
||||
|
||||
if (size > 0) {
|
||||
int p_size = (size > MAXSIZE) ? MAXSIZE : size;
|
||||
int length = 10; // default header bytes
|
||||
int header = 0;
|
||||
int stuffb = 0;
|
||||
|
||||
switch (PTSflags) {
|
||||
case 2: header = 5; // additional header bytes
|
||||
stuffb = 1;
|
||||
break;
|
||||
case 3: header = 10;
|
||||
break;
|
||||
default: header = 0;
|
||||
}
|
||||
|
||||
// header = 0; //XXX ???
|
||||
stuffb = 0; //XXX ???
|
||||
|
||||
length += header;
|
||||
length += stuffb;
|
||||
|
||||
buffer[0] = 0x00;
|
||||
buffer[1] = 0x00;
|
||||
buffer[2] = 0x01;
|
||||
buffer[3] = PRIVATE_STREAM1;
|
||||
|
||||
buffer[6] = 0x80;
|
||||
buffer[7] = PTSflags << 6;
|
||||
buffer[8] = header + stuffb;
|
||||
|
||||
if (header)
|
||||
memcpy(&buffer[9], (void *)PTSdata, header);
|
||||
|
||||
// add stuffing
|
||||
data = buffer + 9 + header;
|
||||
for (int cnt = 0; cnt < stuffb; cnt++)
|
||||
data[cnt] = 0xff;
|
||||
length += stuffb;
|
||||
|
||||
// add data
|
||||
data = buffer + 9 + header + stuffb + 7;
|
||||
int cnt = 0;
|
||||
while (p_size) {
|
||||
if (ac3outp != ac3inp) { // data in the buffer
|
||||
data[cnt ^ 1] = ac3data[ac3outp]; // swab because ac3dec delivers wrong byteorder (the "xor" (^) is a swab!)
|
||||
p_size--;
|
||||
cnt++;
|
||||
length++;
|
||||
ac3outp = (ac3outp + 1) % AC3_BUFFER_SIZE;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
data = buffer + 9 + header + stuffb;
|
||||
data[0] = aLPCM; // substream ID
|
||||
data[1] = 0x00; // other stuff (see DVB specs), ignored by driver
|
||||
data[2] = 0x00;
|
||||
data[3] = 0x00;
|
||||
data[4] = 0x00;
|
||||
data[5] = 0x00;
|
||||
data[6] = 0x00;
|
||||
|
||||
buffer[4] = (length >> 8) & 0xff;
|
||||
buffer[5] = length & 0xff;
|
||||
|
||||
length += 6;
|
||||
|
||||
return new cFrame(buffer, length);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// --- cDVDplayBuffer --------------------------------------------------------
|
||||
|
||||
class cDVDplayBuffer : public cPlayBuffer {
|
||||
private:
|
||||
cAC3toPCM AC3toPCM;
|
||||
uchar audioTrack;
|
||||
|
||||
cDVD *dvd;//XXX necessary???
|
||||
@ -1308,7 +1493,6 @@ private:
|
||||
int doplay;
|
||||
int cyclestate;
|
||||
int prevcycle;
|
||||
int brakeCounter;
|
||||
int skipCnt;
|
||||
|
||||
tt_srpt_t *tt_srpt;
|
||||
@ -1335,11 +1519,6 @@ private:
|
||||
int logAudioTrack;
|
||||
int maxAudioTrack;
|
||||
|
||||
enum { AC3_STOP, AC3_START, AC3_PLAY } ac3stat;
|
||||
uchar *ac3data;
|
||||
int ac3inp;
|
||||
int ac3outp;
|
||||
int lpcm_count;
|
||||
int is_nav_pack(unsigned char *buffer);
|
||||
void Close(void);
|
||||
virtual void Empty(bool Block = false);
|
||||
@ -1350,10 +1529,7 @@ private:
|
||||
int GetStuffingLen(const uchar *Data);
|
||||
int GetPacketLength(const uchar *Data);
|
||||
int GetPESHeaderLength(const uchar *Data);
|
||||
int SendPCM(int size);
|
||||
void playDecodedAC3(void);
|
||||
void handleAC3(unsigned char *sector, int length);
|
||||
void putFrame(unsigned char *sector, int length);
|
||||
void handleAC3(unsigned char *sector, int length, uchar PTSflags, uchar *PTSdata);
|
||||
unsigned int getAudioStream(unsigned int StreamId);
|
||||
void setChapid(void);
|
||||
void NextState(int State) { prevcycle = cyclestate; cyclestate = State; }
|
||||
@ -1369,17 +1545,6 @@ public:
|
||||
virtual void ToggleAudioTrack(void);
|
||||
};
|
||||
|
||||
#define cOPENDVD 0
|
||||
#define cOPENTITLE 1
|
||||
#define cOPENCHAPTER 2
|
||||
#define cOUTCELL 3
|
||||
#define cREADFRAME 4
|
||||
#define cOUTPACK 5
|
||||
#define cOUTFRAMES 6
|
||||
|
||||
#define aAC3 0x80
|
||||
#define aLPCM 0xA0
|
||||
|
||||
cDVDplayBuffer::cDVDplayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev, cDVD *DvD, int title)
|
||||
:cPlayBuffer(DvbApi, VideoDev, AudioDev)
|
||||
{
|
||||
@ -1389,15 +1554,10 @@ cDVDplayBuffer::cDVDplayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev, cDVD
|
||||
angle = 0;
|
||||
cyclestate = cOPENDVD;
|
||||
prevcycle = 0;
|
||||
brakeCounter = 0;
|
||||
skipCnt = 0;
|
||||
logAudioTrack = 0;
|
||||
canToggleAudioTrack = true;//XXX determine from cDVD!
|
||||
ac3dec_init();
|
||||
data = new uchar[1024 * DVD_VIDEO_LB_LEN];
|
||||
ac3data = new uchar[AC3_BUFFER_SIZE];
|
||||
ac3inp = ac3outp = 0;
|
||||
ac3stat = AC3_START;
|
||||
canDoTrickMode = true;
|
||||
dvbApi->SetModeReplay();
|
||||
Start();
|
||||
@ -1408,7 +1568,6 @@ cDVDplayBuffer::~cDVDplayBuffer()
|
||||
Stop();
|
||||
Close();
|
||||
dvbApi->SetModeNormal(false);
|
||||
delete ac3data;
|
||||
delete data;
|
||||
}
|
||||
|
||||
@ -1449,8 +1608,7 @@ void cDVDplayBuffer::ToggleAudioTrack(void)
|
||||
#ifdef DVDDEBUG
|
||||
dsyslog(LOG_INFO, "DVB: Audio Stream ID changed to: %x", audioTrack);
|
||||
#endif
|
||||
ac3stat = AC3_START;
|
||||
ac3outp = ac3inp;
|
||||
AC3toPCM.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1869,141 +2027,21 @@ int cDVDplayBuffer::ScanVideoPacket(const uchar *Data, int Count, uchar *Picture
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define SYSTEM_HEADER 0xBB
|
||||
#define PROG_STREAM_MAP 0xBC
|
||||
#ifndef PRIVATE_STREAM1
|
||||
#define PRIVATE_STREAM1 0xBD
|
||||
#endif
|
||||
#define PADDING_STREAM 0xBE
|
||||
#ifndef PRIVATE_STREAM2
|
||||
#define PRIVATE_STREAM2 0xBF
|
||||
#endif
|
||||
#define AUDIO_STREAM_S 0xC0
|
||||
#define AUDIO_STREAM_E 0xDF
|
||||
#define VIDEO_STREAM_S 0xE0
|
||||
#define VIDEO_STREAM_E 0xEF
|
||||
#define ECM_STREAM 0xF0
|
||||
#define EMM_STREAM 0xF1
|
||||
#define DSM_CC_STREAM 0xF2
|
||||
#define ISO13522_STREAM 0xF3
|
||||
#define PROG_STREAM_DIR 0xFF
|
||||
|
||||
// data=PCM samples, 16 bit, LSB first, 48kHz, stereo
|
||||
int cDVDplayBuffer::SendPCM(int size)
|
||||
void cDVDplayBuffer::handleAC3(unsigned char *sector, int length, uchar PTSflags, uchar *PTSdata)
|
||||
{
|
||||
|
||||
#define MAXSIZE 2032
|
||||
|
||||
uchar buffer[MAXSIZE + 16];
|
||||
int length = 0;
|
||||
int p_size;
|
||||
|
||||
if (ac3inp == ac3outp)
|
||||
return 1;
|
||||
|
||||
while (size > 0) {
|
||||
if (size >= MAXSIZE)
|
||||
p_size = MAXSIZE;
|
||||
else
|
||||
p_size = size;
|
||||
length = 10;
|
||||
|
||||
while (p_size) {
|
||||
if (ac3outp != ac3inp) { // data in the buffer
|
||||
buffer[(length + 6) ^ 1] = ac3data[ac3outp]; // swab because ac3dec delivers wrong byteorder
|
||||
// XXX there is no 'swab' here??? (kls)
|
||||
p_size--;
|
||||
length++;
|
||||
ac3outp = (ac3outp + 1) % AC3_BUFFER_SIZE;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
buffer[0] = 0x00;
|
||||
buffer[1] = 0x00;
|
||||
buffer[2] = 0x01;
|
||||
buffer[3] = PRIVATE_STREAM1;
|
||||
|
||||
buffer[4] = (length >> 8) & 0xff;
|
||||
buffer[5] = length & 0xff;
|
||||
|
||||
buffer[6] = 0x80;
|
||||
buffer[7] = 0x00;
|
||||
buffer[8] = 0x00;
|
||||
|
||||
buffer[9] = aLPCM; // substream ID
|
||||
buffer[10] = 0x00; // other stuff (see DVD specs), ignored by driver
|
||||
buffer[11] = 0x00;
|
||||
buffer[12] = 0x00;
|
||||
buffer[13] = 0x00;
|
||||
buffer[14] = 0x00;
|
||||
buffer[15] = 0x00;
|
||||
|
||||
length += 6;
|
||||
|
||||
putFrame(buffer, length);
|
||||
size -= MAXSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cDVDplayBuffer::playDecodedAC3(void)
|
||||
{
|
||||
int ac3_datasize = (AC3_BUFFER_SIZE + ac3inp - ac3outp) % AC3_BUFFER_SIZE;
|
||||
|
||||
if (ac3_datasize) {
|
||||
if (ac3_datasize > 1024 * 48)
|
||||
SendPCM(3096);
|
||||
else if (ac3_datasize > 1024 * 32)
|
||||
SendPCM(1536);
|
||||
else if (ac3_datasize > 1024 * 16 && !(lpcm_count % 2))
|
||||
SendPCM(1536);
|
||||
else if (ac3_datasize && !(lpcm_count % 4))
|
||||
SendPCM(1536);
|
||||
lpcm_count++;
|
||||
}
|
||||
else
|
||||
lpcm_count=0;
|
||||
}
|
||||
|
||||
void cDVDplayBuffer::handleAC3(unsigned char *sector, int length)
|
||||
{
|
||||
if (dolbyDev) {
|
||||
while (length > 0) {
|
||||
int w = fwrite(sector, 1, length , dolbyDev);
|
||||
if (w < 0) {
|
||||
LOG_ERROR;
|
||||
break;
|
||||
}
|
||||
length -= w;
|
||||
sector += w;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ac3stat == AC3_PLAY)
|
||||
ac3dec_decode_data(sector, sector + length, 0, &ac3inp, &ac3outp, (char *)ac3data);
|
||||
else if (ac3stat == AC3_START) {
|
||||
ac3dec_decode_data(sector, sector + length, 1, &ac3inp, &ac3outp, (char *)ac3data);
|
||||
ac3stat = AC3_PLAY;
|
||||
}
|
||||
}
|
||||
//playDecodedAC3();
|
||||
}
|
||||
|
||||
void cDVDplayBuffer::putFrame(unsigned char *sector, int length)
|
||||
{
|
||||
cFrame *frame = new cFrame(sector, length);
|
||||
while (Busy() && !blockInput && !Put(frame))
|
||||
;
|
||||
#define PCM_FRAME_SIZE 1536
|
||||
AC3toPCM.Put(sector, length);
|
||||
cFrame *frame;
|
||||
if ((frame = AC3toPCM.Get(PCM_FRAME_SIZE, PTSflags, PTSdata)) != NULL)
|
||||
putFrame(frame);
|
||||
while ((frame = AC3toPCM.Get(PCM_FRAME_SIZE)) != NULL)
|
||||
putFrame(frame);
|
||||
}
|
||||
|
||||
int cDVDplayBuffer::decode_packet(unsigned char *sector, bool trickMode)
|
||||
{
|
||||
//XXX kls 2001-11-03: do we really need all these different return values?
|
||||
uchar pt = 1;
|
||||
#if 0
|
||||
uchar *osect = sector;
|
||||
#endif
|
||||
|
||||
//make sure we got a PS packet header
|
||||
if (!PacketStart(§or, DVD_VIDEO_LB_LEN) && GetPacketType(sector) != 0xBA) {
|
||||
@ -2017,6 +2055,8 @@ int cDVDplayBuffer::decode_packet(unsigned char *sector, bool trickMode)
|
||||
int datalen = r;
|
||||
|
||||
sector[6] &= 0x8f;
|
||||
uchar PTSflags = sector[7] >> 6;
|
||||
uchar *PTSdata = sector + 9;
|
||||
uchar *data = sector;
|
||||
|
||||
switch (GetPacketType(sector)) {
|
||||
@ -2025,6 +2065,7 @@ int cDVDplayBuffer::decode_packet(unsigned char *sector, bool trickMode)
|
||||
ScanVideoPacket(sector, r, &pt);
|
||||
if (trickMode && pt != 1)
|
||||
return pt;
|
||||
putFrame(sector, r, ftVideo);
|
||||
break;
|
||||
}
|
||||
case AUDIO_STREAM_S ... AUDIO_STREAM_E: {
|
||||
@ -2033,6 +2074,7 @@ int cDVDplayBuffer::decode_packet(unsigned char *sector, bool trickMode)
|
||||
return 1;
|
||||
if (audioTrack != GetPacketType(sector))
|
||||
return 5;
|
||||
putFrame(sector, r, ftAudio);
|
||||
break;
|
||||
}
|
||||
case PRIVATE_STREAM1:
|
||||
@ -2060,14 +2102,15 @@ int cDVDplayBuffer::decode_packet(unsigned char *sector, bool trickMode)
|
||||
if (audioTrack == *data) {
|
||||
switch (audioTrack & 0xF8) {
|
||||
case aAC3:
|
||||
if (dolbyDev)
|
||||
putFrame(sector, r, ftDolby);
|
||||
data += 4;
|
||||
// correct a3 data lenght - FIXME: why 13 ???
|
||||
datalen -= 13;
|
||||
handleAC3(data, datalen);
|
||||
datalen -= 13; // 3 (mandatory header) + 6 (PS header) + 4 (AC3 header) = 13
|
||||
handleAC3(data, datalen, PTSflags, PTSdata);
|
||||
break;
|
||||
case aLPCM:
|
||||
// write(audio, sector+14 , sector[19]+(sector[18]<<8)+6);
|
||||
putFrame(sector, GetPacketLength(sector));
|
||||
putFrame(sector, GetPacketLength(sector), ftAudio);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -2096,9 +2139,6 @@ int cDVDplayBuffer::decode_packet(unsigned char *sector, bool trickMode)
|
||||
return pt;
|
||||
}
|
||||
}
|
||||
putFrame(sector, r);
|
||||
if ((audioTrack & 0xF8) == aAC3)
|
||||
playDecodedAC3();
|
||||
return pt;
|
||||
}
|
||||
|
||||
@ -2106,8 +2146,7 @@ void cDVDplayBuffer::Empty(bool Block)
|
||||
{
|
||||
if (!(blockInput || blockOutput)) {
|
||||
cPlayBuffer::Empty(true);
|
||||
ac3stat = AC3_START;
|
||||
ac3outp = ac3inp;
|
||||
AC3toPCM.Clear();
|
||||
}
|
||||
if (!Block)
|
||||
cPlayBuffer::Empty(false);
|
||||
@ -2149,9 +2188,7 @@ void cDVDplayBuffer::SkipSeconds(int Seconds)
|
||||
Empty(true);
|
||||
chapid = newchapid;
|
||||
NextState(cOPENCHAPTER);
|
||||
if (ac3stat != AC3_STOP)
|
||||
ac3stat = AC3_START;
|
||||
ac3outp = ac3inp;
|
||||
AC3toPCM.Clear();
|
||||
Empty(false);
|
||||
Play();
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Parts of this file were inspired by the 'ringbuffy.c' from the
|
||||
* LinuxDVB driver (see linuxtv.org).
|
||||
*
|
||||
* $Id: ringbuffer.c 1.4 2001/08/05 12:17:45 kls Exp $
|
||||
* $Id: ringbuffer.c 1.5 2001/11/03 09:50:46 kls Exp $
|
||||
*/
|
||||
|
||||
#include "ringbuffer.h"
|
||||
@ -215,9 +215,10 @@ int cRingBufferLinear::Get(uchar *Data, int Count)
|
||||
|
||||
// --- cFrame ----------------------------------------------------------------
|
||||
|
||||
cFrame::cFrame(const uchar *Data, int Count, int Index)
|
||||
cFrame::cFrame(const uchar *Data, int Count, eFrameType Type, int Index)
|
||||
{
|
||||
count = Count;
|
||||
type = Type;
|
||||
index = Index;
|
||||
data = new uchar[count];
|
||||
if (data)
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: ringbuffer.h 1.4 2001/08/05 11:12:06 kls Exp $
|
||||
* $Id: ringbuffer.h 1.5 2001/11/03 10:41:33 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __RINGBUFFER_H
|
||||
@ -75,18 +75,22 @@ public:
|
||||
virtual ~cRingBufferLinear();
|
||||
};
|
||||
|
||||
enum eFrameType { ftUnknown, ftVideo, ftAudio, ftDolby };
|
||||
|
||||
class cFrame {
|
||||
friend class cRingBufferFrame;
|
||||
private:
|
||||
cFrame *next;
|
||||
uchar *data;
|
||||
int count;
|
||||
eFrameType type;
|
||||
int index;
|
||||
public:
|
||||
cFrame(const uchar *Data, int Count, int Index = -1);
|
||||
cFrame(const uchar *Data, int Count, eFrameType = ftUnknown, int Index = -1);
|
||||
~cFrame();
|
||||
const uchar *Data(void) const { return data; }
|
||||
int Count(void) const { return count; }
|
||||
eFrameType Type(void) const { return type; }
|
||||
int Index(void) const { return index; }
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user