1 /* $Id: HBMpegDemux.cpp,v 1.13 2003/08/24 19:28:18 titer Exp $ */
5 #include "HBMpegDemux.h"
9 #include <a52dec/a52.h>
12 HBMpegDemux::HBMpegDemux( HBManager * manager, HBTitleInfo * titleInfo,
13 HBAudioInfo * audio1Info, HBAudioInfo * audio2Info )
14 : HBThread( "mpegdemux" )
17 fTitleInfo = titleInfo;
18 fAudio1Info = audio1Info;
19 fAudio2Info = audio2Info;
30 void HBMpegDemux::DoWork()
35 fPSBuffer = fTitleInfo->fPSFifo->Pop();
42 /* Get the ES data in it */
43 fESBufferList = PStoES( fPSBuffer );
50 while( ( fESBuffer = (HBBuffer*) fESBufferList->ItemAt( 0 ) ) )
52 fESBufferList->RemoveItem( fESBuffer );
54 /* Look for a decoder for this ES */
55 if( fESBuffer->fStreamId == 0xE0 )
57 if( fFirstVideoPTS < 0 )
59 fFirstVideoPTS = fESBuffer->fPTS;
61 fTitleInfo->fMpeg2Fifo->Push( fESBuffer );
63 else if( fESBuffer->fStreamId == fAudio1Info->fId )
65 /* If the audio track starts later than the video,
66 repeat the first frame as long as needed */
67 if( fFirstAudio1PTS < 0 )
69 fFirstAudio1PTS = fESBuffer->fPTS;
71 if( fFirstAudio1PTS > fFirstVideoPTS )
73 Log( "HBMpegDemux::DoWork() : audio track %x is late",
75 InsertSilence( fFirstAudio1PTS - fFirstVideoPTS,
76 fAudio1Info->fAc3Fifo,
80 fAudio1Info->fAc3Fifo->Push( fESBuffer );
82 else if( fESBuffer->fStreamId == fAudio2Info->fId )
84 if( fFirstAudio2PTS < 0 )
86 fFirstAudio2PTS = fESBuffer->fPTS;
88 if( fFirstAudio2PTS > fFirstVideoPTS )
90 Log( "HBMpegDemux::DoWork() : audio track %x is late",
92 InsertSilence( fFirstAudio2PTS - fFirstVideoPTS,
93 fAudio2Info->fAc3Fifo,
97 fAudio2Info->fAc3Fifo->Push( fESBuffer );
104 delete fESBufferList;
108 void HBMpegDemux::InsertSilence( int64_t time, HBFifo * fifo,
114 int frameSize = a52_syncinfo( buffer->fData, &flags,
115 &sampleRate, &bitrate );
119 Log( "HBMpegDemux::InsertSilence() : a52_syncinfo() failed" );
123 uint32_t samples = sampleRate * time / 90000;
126 Log( "HBMpegDemux::InsertSilence() : adding %d samples", samples );
128 for( uint32_t i = 0; i < samples / ( 6 * 256 ); i++ )
130 buffer2 = new HBBuffer( frameSize );
131 memcpy( buffer2->fData, buffer->fData, frameSize );
132 fifo->Push( buffer2 );
136 BList * PStoES( HBBuffer * psBuffer )
138 #define psData (psBuffer->fData)
140 BList * esBufferList = new BList();
145 if( psData[pos] != 0 || psData[pos+1] != 0 ||
146 psData[pos+2] != 0x1 || psData[pos+3] != 0xBA )
148 Log( "PStoES : not a PS packet (%02x%02x%02x%02x)",
149 psData[pos] << 24, psData[pos+1] << 16,
150 psData[pos+2] << 8, psData[pos+3] );
154 pos += 4; /* pack_start_code */
155 pos += 9; /* pack_header */
156 pos += 1 + ( psData[pos] & 0x7 ); /* stuffing bytes */
159 if( psData[pos] == 0 && psData[pos+1] == 0 &&
160 psData[pos+2] == 0x1 && psData[pos+3] == 0xBB )
162 uint32_t header_length;
164 pos += 4; /* system_header_start_code */
165 header_length = ( psData[pos] << 8 ) + psData[pos+1];
166 pos += 2 + header_length;
170 while( pos + 2 < psBuffer->fSize &&
171 psData[pos] == 0 && psData[pos+1] == 0 && psData[pos+2] == 0x1 )
174 uint32_t PES_packet_length;
175 uint32_t PES_packet_end;
176 uint32_t PES_header_data_length;
177 uint32_t PES_header_end;
181 pos += 3; /* packet_start_code_prefix */
182 streamId = psData[pos++];
184 PES_packet_length = ( psData[pos] << 8 ) + psData[pos+1];
185 pos += 2; /* PES_packet_length */
186 PES_packet_end = pos + PES_packet_length;
188 hasPTS = ( ( psData[pos+1] >> 6 ) & 0x2 );
189 pos += 2; /* Required headers */
191 PES_header_data_length = psData[pos];
193 PES_header_end = pos + PES_header_data_length;
197 PTS = ( ( ( psData[pos] >> 1 ) & 0x7 ) << 30 ) +
198 ( psData[pos+1] << 22 ) +
199 ( ( psData[pos+2] >> 1 ) << 15 ) +
200 ( psData[pos+3] << 7 ) +
201 ( psData[pos+4] >> 1 );
204 pos = PES_header_end;
206 if( streamId != 0xE0 && streamId != 0xBD )
208 /* Not interesting */
212 if( streamId == 0xBD )
214 /* A52 : don't ask */
215 streamId |= ( psData[pos] << 8 );
219 /* Here we hit we ES payload */
220 esBuffer = new HBBuffer( PES_packet_end - pos );
222 esBuffer->fPosition = psBuffer->fPosition;
223 esBuffer->fStreamId = streamId;
224 esBuffer->fPTS = PTS;
225 memcpy( esBuffer->fData, psBuffer->fData + pos,
226 PES_packet_end - pos );
228 esBufferList->AddItem( esBuffer );
230 pos = PES_packet_end;
235 if( esBufferList && !esBufferList->CountItems() )