diff --git a/lib/ts_packet.cpp b/lib/ts_packet.cpp index c8c640a9..df5f92a9 100644 --- a/lib/ts_packet.cpp +++ b/lib/ts_packet.cpp @@ -21,7 +21,7 @@ TS_Packet::~TS_Packet() { } void TS_Packet::PID( int NewVal ) { Buffer[1] = (Buffer[1] & 0xE0) + ((NewVal & 0x1F00) >> 8 ); Buffer[2] = (NewVal & 0x00FF); - Free = std::min( Free, 185 ); + Free = std::min( Free, 184 ); } int TS_Packet::PID() { @@ -42,7 +42,7 @@ int TS_Packet::BytesFree( ) { } void TS_Packet::Clear( ) { - Free = 187; + Free = 184; Buffer[0] = 0x47; for( int i = 1; i < 188; i++ ) { Buffer[i] = 0x00; @@ -51,19 +51,18 @@ void TS_Packet::Clear( ) { } void TS_Packet::AdaptionField( int NewVal ) { - NewVal = NewVal % 4; - NewVal = NewVal << 4; - Buffer[3] = ( Buffer[3] & 0xCF ) + NewVal; + Buffer[3] = ( Buffer[3] & 0xCF ) + ((NewVal & 0x03) << 4); + Buffer[4] = 0; Free = std::min( Free, 184 ); } int TS_Packet::AdaptionField( ) { - return ((Buffer[3] & 0x30) >> 4 ) >= 2; + return ((Buffer[3] & 0x30) >> 4 ); } void TS_Packet::PCR( int64_t NewVal ) { NewVal += (0xF618 * 300); - Buffer[3] = (Buffer[3] | 0x30); + AdaptionField( 3 ); Buffer[4] = 7; Buffer[5] = (Buffer[5] | 0x10 ); int64_t TmpVal = NewVal / 300; @@ -136,21 +135,25 @@ int TS_Packet::RandomAccess( ) { void TS_Packet::RandomAccess( int NewVal ) { if( AdaptionField() ) { + if( Buffer[4] == 0 ) { + Buffer[4] = 1; + } if( NewVal ) { Buffer[5] = (Buffer[5] | 0x40); } else { Buffer[5] = (Buffer[5] & 0xBF); } } else { - Buffer[3] = (Buffer[3] | 0x30); + AdaptionField( 3 ); Buffer[4] = 1; if( NewVal ) { Buffer[5] = 0x40; } else { Buffer[5] = 0x00; } - Free = 183; + } + Free = std::min( Free, 182 ); } void TS_Packet::DefaultPAT( ) { @@ -159,6 +162,10 @@ void TS_Packet::DefaultPAT( ) { PID( 0 ); ContinuityCounter( MyCntr ); AdaptionField( 0x01 ); + + + + Buffer[ 4] = 0x00;//Pointer Field Buffer[ 5] = 0x00;//TableID Buffer[ 6] = 0xB0,//Reserved + SectionLength @@ -178,7 +185,7 @@ void TS_Packet::DefaultPAT( ) { Buffer[20] = 0xB2;//CRC32 (Cont) std::fill( Buffer+21, Buffer+188, 0xFF ); Free = 0; - MyCntr = ( (MyCntr + 1) % 0xF); + MyCntr = ( (MyCntr + 1) % 0x10); } void TS_Packet::DefaultPMT( ) { @@ -187,10 +194,13 @@ void TS_Packet::DefaultPMT( ) { PID( 0x1000 ); ContinuityCounter( MyCntr ); AdaptionField( 0x01 ); + + + Buffer[ 4] = 0x00;//Pointer Field Buffer[ 5] = 0x02;//TableID Buffer[ 6] = 0xb0;//Reserved + Section_Length - Buffer[ 7] = 0x12;//Section_Length (Cont) + Buffer[ 7] = 0x1D;//Section_Length (Cont) Buffer[ 8] = 0x00;//Program_Number Buffer[ 9] = 0x01;//Program_Number (Cont) Buffer[10] = 0xc1;//Reserved + VersionNumber + Current_Next_Indicator @@ -201,27 +211,51 @@ void TS_Packet::DefaultPMT( ) { Buffer[15] = 0xf0;//Reserved + Program_Info_Length Buffer[16] = 0x00;//Program_Info_Length (Cont) Buffer[17] = 0x1b; //Stream_Type + + + Buffer[18] = 0xe1; //Reserved + Elementary_PID Buffer[19] = 0x00; //Elementary_PID (Cont) Buffer[20] = 0xf0; //Reserved + ES_Info_Length Buffer[21] = 0x00; //ES_Info_Length (Cont) - Buffer[22] = 0x15;//CRC32 - Buffer[23] = 0xbd;//CRC32 (Cont) - Buffer[24] = 0x4d;//CRC32 (Cont) - Buffer[25] = 0x56;//CRC32 (Cont) - std::fill( Buffer+26, Buffer+188, 0xFF ); + Buffer[22] = 0x0f; //Stream_Type + Buffer[23] = 0xe1; + Buffer[24] = 0x01; + Buffer[25] = 0xf0; + Buffer[26] = 0x06; + Buffer[27] = 0x0a; + Buffer[28] = 0x04; + Buffer[29] = 0x65; + Buffer[30] = 0x6e; + Buffer[31] = 0x67; + Buffer[32] = 0x00; + Buffer[33] = 0x8d; + Buffer[34] = 0x82; + Buffer[35] = 0x9a; + Buffer[36] = 0x07; + + std::fill( Buffer+37, Buffer+188, 0xFF ); Free = 0; - MyCntr = ( (MyCntr + 1) % 0xF); + MyCntr = ( (MyCntr + 1) % 0x10); } std::string TS_Packet::ToString( ) { + fprintf( stderr, "\t\t\tAdaptationFieldBitsInBuffer: %0.2X\n", AdaptionField( ) ); std::string Result( Buffer, 188 ); + fprintf( stderr, "\t\t\tAdaptationFieldBitsInString: %0.2X\n", Result[3] ); + std::cout.write( Buffer,188 ); + if( Buffer[0] != 0x47) { + fprintf( stderr, "Breaking, something terrible has happened\n" ); + exit(400); + } return Result; } -void TS_Packet::PESLeadIn( int NewLen ) { - static uint64_t PTS = 126000; +void TS_Packet::PESVideoLeadIn( int NewLen, uint64_t PTSt ) { + static int PTS = 27000000; NewLen += 14; + fprintf( stderr, "\t\t\t\t\tMyPTS: %X\n", PTS ); + fprintf( stderr, "\t\t\t\t\tMyLen: %d\n", NewLen ); int Offset = ( 188 - Free ); Buffer[Offset] = 0x00;//PacketStartCodePrefix Buffer[Offset+1] = 0x00;//PacketStartCodePrefix (Cont) @@ -235,7 +269,7 @@ void TS_Packet::PESLeadIn( int NewLen ) { Buffer[Offset+9] = 0x20 + ((PTS & 0x1C0000000) >> 29 ) + 1;//PTS Buffer[Offset+10] = 0x00 + ((PTS & 0x03FC00000) >> 22 );//PTS (Cont) Buffer[Offset+11] = 0x00 + ((PTS & 0x0003F8000) >> 14 ) + 1;//PTS (Cont) - Buffer[Offset+12] = 0x00 + ((PTS & 0x000007F10) >> 7 );//PTS (Cont) + Buffer[Offset+12] = 0x00 + ((PTS & 0x000007F80) >> 7 );//PTS (Cont) Buffer[Offset+13] = 0x00 + ((PTS & 0x00000007F) << 1) + 1;//PTS (Cont) //PesPacket-Wise Prepended Data @@ -247,13 +281,39 @@ void TS_Packet::PESLeadIn( int NewLen ) { Buffer[Offset+18] = 0x09;//NALU EndOfPacket (Einde Vorige Packet) Buffer[Offset+19] = 0xF0;//NALU EndOfPacket (Cont) Free = Free - 20; - fprintf( stderr, "\tAdding PES Lead In with Offset %d and Size %d\n", Offset, NewLen ); - fprintf( stderr, "\t\tNew Free is %d\n", Free ); PTS += 3003; } +void TS_Packet::PESAudioLeadIn( int NewLen, uint64_t PTS ) { + fprintf( stderr, "Free before PESAudio: %d\n", Free ); + PTS = PTS * 90; + fprintf( stderr, "%d\n", PTS ); + NewLen += 8; + fprintf( stderr, "\t\t\t\t\tMyPTS: %X\n", PTS ); + fprintf( stderr, "\t\t\t\t\tMyLen: %d\n", NewLen ); + int Offset = ( 188 - Free ) - 2; + fprintf( stderr, "Audio PES Lead In: Offset = %d\n", Offset ); + Buffer[Offset] = 0x00;//PacketStartCodePrefix + Buffer[Offset+1] = 0x00;//PacketStartCodePrefix (Cont) + Buffer[Offset+2] = 0x01;//PacketStartCodePrefix (Cont) + Buffer[Offset+3] = 0xc0;//StreamType Video + + Buffer[Offset+4] = (NewLen & 0xFF00) >> 8;//PES PacketLength + Buffer[Offset+5] = (NewLen & 0x00FF);//PES PacketLength (Cont) + Buffer[Offset+6] = 0x80;//Reserved + Flags + Buffer[Offset+7] = 0x80;//PTSOnlyFlag + Flags + Buffer[Offset+8] = 0x05;//PESHeaderDataLength + Buffer[Offset+9] = 0x20 + ((PTS & 0x1C0000000) >> 29 ) + 1;//PTS + Buffer[Offset+10] = 0x00 + ((PTS & 0x03FC00000) >> 22 );//PTS (Cont) + Buffer[Offset+11] = 0x00 + ((PTS & 0x0003F8000) >> 14 ) + 1;//PTS (Cont) + Buffer[Offset+12] = 0x00 + ((PTS & 0x000007F80) >> 7 );//PTS (Cont) + Buffer[Offset+13] = 0x00 + ((PTS & 0x00000007F) << 1) + 1;//PTS (Cont) + Free = Free - 12; +} + void TS_Packet::FillFree( std::string & NewVal ) { int Offset = (188 - Free); + fprintf( stderr, "Filling Free: Offset = %d\n", Offset ); for( int i = 0; (Offset + i) < 188; i++ ) { Buffer[Offset+i] = NewVal[i]; } @@ -262,16 +322,18 @@ void TS_Packet::FillFree( std::string & NewVal ) { } void TS_Packet::AddStuffing( int NumBytes ) { - if( NumBytes < 0 ) { return; } + if( NumBytes <= 0 ) { return; } if( AdaptionField( ) == 3 ) { int Offset = Buffer[4]; + fprintf( stderr, "AddStuffing: AdaptionField == 3 && Offset = %d\n", Offset ); Buffer[4] = Offset + NumBytes - 1; for( int i = 0; i < ( NumBytes -2 ); i ++ ) { - Buffer[Offset+i] = 0xFF; + Buffer[6+Offset+i] = 0xFF; } Free -= NumBytes; } else { AdaptionField( 3 ); + fprintf( stderr, "AddStuffing: AdaptionField != 3\n" ); Buffer[4] = NumBytes - 1; Buffer[5] = 0x00; for( int i = 0; i < ( NumBytes -2 ); i ++ ) { @@ -279,4 +341,59 @@ void TS_Packet::AddStuffing( int NumBytes ) { } Free -= NumBytes; } + fprintf( stderr, "Free After Stuffing: %d\n", Free ); +} + +void TS_Packet::FFMpegHeader( ) { + static int MyCntr = 0; + UnitStart( 1 ); + PID( 0x0011 ); + ContinuityCounter( MyCntr ); + AdaptionField( 0x01 ); + Buffer[4] = 0x00; + Buffer[5] = 0x42; + Buffer[6] = 0xF0; + Buffer[7] = 0x25; + Buffer[8] = 0x00; + Buffer[9] = 0x01; + Buffer[10] = 0xC1; + Buffer[11] = 0x00; + Buffer[12] = 0x00; + Buffer[13] = 0x00; + Buffer[14] = 0x01; + Buffer[15] = 0xFF; + Buffer[16] = 0x00; + Buffer[17] = 0x01; + Buffer[18] = 0xFC; + Buffer[19] = 0x80; + Buffer[20] = 0x14; + Buffer[21] = 0x48; + Buffer[22] = 0x12; + Buffer[23] = 0x01; + Buffer[24] = 0x06; + Buffer[25] = 0x46; + Buffer[26] = 0x46; + Buffer[27] = 0x6D; + Buffer[28] = 0x70; + Buffer[29] = 0x65; + Buffer[30] = 0x67; + Buffer[31] = 0x09; + Buffer[32] = 0x53; + Buffer[33] = 0x65; + Buffer[34] = 0x72; + Buffer[35] = 0x76; + Buffer[36] = 0x69; + Buffer[37] = 0x63; + Buffer[38] = 0x65; + Buffer[39] = 0x30; + Buffer[40] = 0x31; + Buffer[41] = 0xA7; + Buffer[42] = 0x79; + Buffer[43] = 0xA0; + Buffer[44] = 0x03; + for( int i = 45; i < 188; i++ ) { + Buffer[i] = 0xFF; + } + Free = 0; + MyCntr = ( (MyCntr + 1) % 0x10); } diff --git a/lib/ts_packet.h b/lib/ts_packet.h index fae5463b..958c6b49 100644 --- a/lib/ts_packet.h +++ b/lib/ts_packet.h @@ -4,6 +4,7 @@ #include //for uint64_t #include #include +#include #include class TS_Packet { @@ -30,9 +31,11 @@ class TS_Packet { int64_t PCR(); void Print(); std::string ToString(); - void PESLeadIn( int NewLen ); + void PESVideoLeadIn( int NewLen, uint64_t PTS = 0 ); + void PESAudioLeadIn( int NewLen, uint64_t PTS = 0 ); void FillFree( std::string & PackageData ); void AddStuffing( int NumBytes ); + void FFMpegHeader( ); private: int Free; char Buffer[188];///< The actual data diff --git a/src/converters/dtsc2ts.cpp b/src/converters/dtsc2ts.cpp index c7ee1e38..ed3fe1e6 100644 --- a/src/converters/dtsc2ts.cpp +++ b/src/converters/dtsc2ts.cpp @@ -10,6 +10,15 @@ #include "../../lib/ts_packet.h" //TS support #include "../../lib/dtsc.h" //DTSC support +std::string GetAudioHeader( int FrameLen ) { + char StandardHeader[7] = {0xFF,0xF1,0x4C,0x80,0x00,0x1F,0xFC}; + FrameLen += 7; + StandardHeader[3] = ( StandardHeader[3] & 0xFC ) + ( ( FrameLen & 0x00001800 ) >> 11 ); + StandardHeader[4] = ( ( FrameLen & 0x000007F8 ) >> 3 ); + StandardHeader[5] = ( StandardHeader[5] & 0x3F ) + ( ( FrameLen & 0x00000007 ) << 5 ); + return std::string(StandardHeader,7); +} + int main( ) { char ShortNALUHeader[3] = {0x00,0x00,0x01}; char NALUHeader[4] = {0x00,0x00,0x00,0x01}; @@ -21,6 +30,8 @@ int main( ) { 0x5E,0xF7,0xC0,0x40, 0x00,0x00,0x00,0x01, 0x28,0xCE,0x09,0xC8}; + char AudioHeader_01[7] = {0xFF,0xF1,0x4C,0x80,0x01,0xDF,0xFC}; + char AudioHeader_45[7] = {0xFF,0xF1,0x4C,0x80,0x45,0xDF,0xFC}; char charBuffer[1024*10]; unsigned int charCount; std::string StrData; @@ -34,6 +45,12 @@ int main( ) { int TimeStamp = 0; int ThisNaluSize; int VidContinuity = 0; + int AudioContinuity = 0; + bool FirstKeyFrame = true; + bool FirstIDRInKeyFrame; + std::string AudioPack; + uint64_t AudioTimestamp = 0; + uint64_t NextAudioTimestamp = 0; while( std::cin.good() ) { std::cin.read(charBuffer, 1024*10); charCount = std::cin.gcount(); @@ -43,11 +60,13 @@ int main( ) { DTMIData = DTSCStream.lastData(); if( DTSCStream.getPacket(0).getContent("keyframe").NumValue() ) { IsKeyFrame = true; - TimeStamp = DTSCStream.getTime(); + FirstIDRInKeyFrame = true; } else { IsKeyFrame = false; - TimeStamp = 0; + FirstKeyFrame = false; } + TimeStamp = (DTSCStream.getPacket(0).getContent("time").NumValue() * 27000); + if( TimeStamp < 0 ) { TimeStamp = 0; } std::string ToPack; int TSType; bool FirstIDRPic = true; @@ -61,8 +80,21 @@ int main( ) { ToPack.append(PPS_SPS,32); FirstIDRPic = false; FirstNonIDRPic = false; - } - ToPack.append(ShortNALUHeader,3); + } + if( IsKeyFrame ) { + if( FirstKeyFrame ) { + ToPack.append(ShortNALUHeader,3); + } else { + if( FirstIDRInKeyFrame ) { + ToPack.append(NALUHeader,4); + FirstIDRInKeyFrame = false; + } else { + ToPack.append(ShortNALUHeader,3); + } + } + } else { + ToPack.append(ShortNALUHeader,3); + } } else if ( TSType == 0x21 ) { if( FirstNonIDRPic ) { ToPack.append(NALUHeader,4); @@ -78,38 +110,90 @@ int main( ) { DTMIData.erase(0,ThisNaluSize); } WritePesHeader = true; - fprintf( stderr, "PESHeader: %d, PackNum: %2d, ToPackSize: %d\n", WritePesHeader, TSPackNum, ToPack.size() ); while( ToPack.size() ) { + if ( ( TSPackNum % 210 ) == 0 ) { + PackData.FFMpegHeader(); + PackData.ToString(); + } if ( ( TSPackNum % 42 ) == 0 ) { PackData.DefaultPAT(); - std::cout << PackData.ToString(); + PackData.ToString(); } else if ( ( TSPackNum % 42 ) == 1 ) { PackData.DefaultPMT(); - std::cout << PackData.ToString(); + PackData.ToString(); } else { PackData.Clear(); PackData.PID( 0x100 ); - PackData.ContinuityCounter( VidContinuity++ ); + PackData.ContinuityCounter( VidContinuity ); + VidContinuity ++; if( WritePesHeader ) { PackData.UnitStart( 1 ); if( IsKeyFrame ) { - PackData.AdaptionField( 0x03 ); + fprintf( stderr, "IsKeyFrame\n" ); PackData.RandomAccess( 1 ); PackData.PCR( TimeStamp ); + } else { + PackData.AdaptionField( 0x01 ); } + fprintf( stderr, "Needed Stuffing: %d\n", 184 - (20+ToPack.size()) ); PackData.AddStuffing( 184 - (20+ToPack.size()) ); - PackData.PESLeadIn( ToPack.size() ); + PackData.PESVideoLeadIn( ToPack.size(), TimeStamp / 300 ); WritePesHeader = false; } else { PackData.AdaptionField( 0x01 ); - PackData.AddStuffing( 184 - (ToPack.size()) ); - } + fprintf( stderr, "Needed Stuffing: %d\n", 184 - (ToPack.size()) ); + PackData.AddStuffing( 184 - (ToPack.size()) ); + } PackData.FillFree( ToPack ); - std::cout << PackData.ToString(); - } + PackData.ToString(); + } + fprintf( stderr, "PackNum: %d\n\tAdaptionField: %d\n==========\n", TSPackNum + (TSPackNum/210)+1 + 1, PackData.AdaptionField( ) ); TSPackNum++; } - } + } else if( DTSCStream.lastType() == DTSC::AUDIO ) { + WritePesHeader = true; + DTMIData = DTSCStream.lastData(); + AudioPack = GetAudioHeader( DTMIData.size() ); + AudioPack += DTMIData; + fprintf( stderr, "DTMIData: %d\n", DTMIData.size() ); + AudioTimestamp = DTSCStream.getPacket(0).getContent("time").NumValue() * 900; + if( AudioTimestamp < 0 ) { AudioTimestamp = 0; } + PackData.Clear(); + while( AudioPack.size() ) { + if ( ( TSPackNum % 210 ) == 0 ) { + PackData.FFMpegHeader(); + PackData.ToString(); + } + if ( ( TSPackNum % 42 ) == 0 ) { + PackData.DefaultPAT(); + PackData.ToString(); + } else if ( ( TSPackNum % 42 ) == 1 ) { + PackData.DefaultPMT(); + PackData.ToString(); + } else { + PackData.Clear(); + PackData.PID( 0x101 ); + PackData.ContinuityCounter( AudioContinuity ); + AudioContinuity ++; + if( WritePesHeader ) { + PackData.UnitStart( 1 ); + PackData.RandomAccess( 1 ); + fprintf( stderr, "WritePes Needed Stuffing: %d\n", 184 - (14+AudioPack.size()) ); + PackData.AddStuffing( 184 - (14+ AudioPack.size()) ); + PackData.PESAudioLeadIn( AudioPack.size(), AudioTimestamp ); + WritePesHeader = false; + } else { + PackData.AdaptionField( 0x01 ); + fprintf( stderr, "Needed Stuffing: %d\n", 184 - (AudioPack.size()) ); + PackData.AddStuffing( 184 - (AudioPack.size()) ); + } + PackData.FillFree( AudioPack ); + PackData.ToString(); + } + fprintf( stderr, "PackNum: %d\n\tAdaptionField: %d\n==========\n", TSPackNum + (TSPackNum/210)+1 + 1, PackData.AdaptionField( ) ); + TSPackNum++; + } + } } } return 0;