/*******************************************************}
{
}
{ File: demuxer.h }
{ Created by Tsviatko Jongov }
{ http://tsviatko.jongov.com }
{
}
{ CMpeg2Demux class. }
{
}
{*******************************************************/
#ifndef
__DEMUXER_H__
#define
__DEMUXER_H__
#include "buffer.h"
#include "output.h"
#include "transport_packet_class.h"
#define
INPUT_BUFFER_SIZE 1024 * 1024
class
CMpeg2TSDemux {
private:
char
m_FileName[MAX_PATH];
CBuffer * m_Buffer;
unsigned long m_PacketLen;
//Output
COutput * m_output[256];
int
m_output_cnt;
unsigned int m_output_ids[256];
Ctransport_packet_class *
transport_packet_class;
int
Process()
{
unsigned
int Len;
int
Res;
unsigned
char * P;
Len = m_Buffer->Len();
P = m_Buffer->Head();
while
(Len >= m_PacketLen)
{
if
((P[0] == 0x47) && (((P[m_PacketLen]) == 0x47)))
{
if
(transport_packet_class->SetData((void *)P,
m_PacketLen))
{
if
(transport_packet_class->m_transport_packet.adaptation_field_control &
0x01 == 0x00)
{
Len -= m_PacketLen;
P += m_PacketLen;
continue;
}
if
( (transport_packet_class->m_transport_packet.payload_unit_start_indicator)
&& ( (*(DWORD
*)(&P[transport_packet_class->m_PayloadOffset]) & 0x00FFFFFF) ==
0x00010000 ) )
{
//Parse PES header here.
unsigned long
PES_header_data_length = *(unsigned char
*)(&P[transport_packet_class->m_PayloadOffset] + 8);
transport_packet_class->m_PayloadOffset += 9 +
PES_header_data_length;
}
Res =
ReceiveData(transport_packet_class->m_transport_packet.PID, (unsigned char * )(P +
transport_packet_class->m_PayloadOffset), 188 -
transport_packet_class->m_PayloadOffset);
if
(Res)
{
printf("tsv: Error in CMpeg2TSDemux::Process - error
processing the file.\n");
return Res;
}
Len -= m_PacketLen;
P += m_PacketLen;
}
else
{
printf("tsv: Error in CMpeg2TSDemux::Process - cannot
process TS packet.\n");
Len--;
P++;
}
}
else
{
printf("tsv:
Warning in CMpeg2TSDemux::Process - corrupted TS stream.\n");
Len--;
P++;
}
}
m_Buffer->m_First +=
(m_Buffer->Len() - Len);
m_Buffer->Compact();
return
0;
}
int
ReceiveData(unsigned int
StreamID, unsigned char
* Data, unsigned int
Size)
{
int idx
= get_output_index(StreamID);
if (idx
< 0)
{
m_output[m_output_cnt] = new COutput();
m_output[m_output_cnt]->Initialize(StreamID, m_FileName);
m_output_ids[m_output_cnt] =
StreamID;
idx = m_output_cnt;
m_output_cnt++;
}
return
m_output[idx]->WriteData(Data, Size);
}
int
get_output_index(int StreamID)
{
for (int i = 0; i < m_output_cnt; i++)
{
if
(m_output_ids[i] == StreamID)
{
return
i;
}
}
return
-1;
}
void
free_output()
{
for (int i = 0; i < m_output_cnt; i++)
{
if
(m_output[i])
delete
m_output[i];
}
}
public:
CMpeg2TSDemux():
m_output_cnt(0)
{
m_Buffer = new
CBuffer(INPUT_BUFFER_SIZE);
if
(!m_Buffer)
{
printf("tsv:
Error in CMpeg2TSDemux::CMpeg2TSDemux - can not create CBuffer.\n");
}
transport_packet_class = new Ctransport_packet_class();
}
~CMpeg2TSDemux()
{
delete
transport_packet_class;
delete
m_Buffer;
}
int
DemultiplexFile(char * FileName)
{
int
res;
if
(!IsTS(FileName, &m_PacketLen))
{
printf("tsv:
Error in CMpeg2TSDemux::DemultiplexFile - not valid transport stream.\n");
return
(-1);
}
strcpy(m_FileName, FileName);
unsigned
int read;
FILE * SourceFile;
SourceFile = fopen(m_FileName, "rb");
for(;;)
{
(size_t)read =
fread(m_Buffer->Tail(), sizeof(char), m_Buffer->Size() - m_Buffer->Len(),
SourceFile);
if
(read <= 0)
{
break;
}
m_Buffer->m_Last += read;
res = Process();
if
(res)
{
fclose(SourceFile);
return
res;
}
}
free_output();
fclose(SourceFile);
return
0;
}
};
#endif // __DEMUXER_H__