Created a NAL_Unit class to aid in translation between 'Regular' and 'Annex B' h264 streams

This commit is contained in:
Erik Zandvliet 2012-07-04 14:45:51 +02:00 committed by Thulinma
parent 663a504891
commit 01dc2a1a00
6 changed files with 142 additions and 6 deletions

View file

@ -1,4 +1,4 @@
noinst_LTLIBRARIES=libamf.la libauth.la libbase64.la libconfig.la libcrypto.la libdtsc.la libflv_tag.la libhttp_parser.la libjson.la libprocs.la librtmpchunks.la libsocket.la libtinythread.la libmp4.la libts_packet.la
noinst_LTLIBRARIES=libamf.la libauth.la libbase64.la libconfig.la libcrypto.la libdtsc.la libflv_tag.la libhttp_parser.la libjson.la libprocs.la librtmpchunks.la libsocket.la libtinythread.la libmp4.la libts_packet.la libnal_unit.la
libamf_la_SOURCES=amf.h amf.cpp
libauth_la_SOURCES=auth.h auth.cpp
libauth_la_LIBADD=-lssl -lcrypto
@ -20,3 +20,4 @@ libtinythread_la_LIBADD=-lpthread
libmp4_la_SOURCES=mp4.h mp4.cpp
libts_packet_la_SOURCES=ts_packet.h ts_packet.cpp
libts_packet_la_LIBADD=./libdtsc.la
libnal_unit_la_SOURCES=nal.h nal.cpp

77
lib/nal.cpp Normal file
View file

@ -0,0 +1,77 @@
#include "nal.h"
NAL_Unit::NAL_Unit( ) {
}
NAL_Unit::NAL_Unit( std::string & InputData ) {
ReadData( InputData );
}
bool NAL_Unit::ReadData( std::string & InputData ) {
bool AnnexB = false;
if( InputData[0] == 0x00 && InputData[1] == 0x00 ) {
if( InputData[2] == 0x01 ) {
AnnexB = true;
}
if( InputData[2] == 0x00 && InputData[3] == 0x01 ) {
InputData.erase(0,1);
AnnexB = true;
}
}
if( AnnexB ) {
MyData = "";
InputData.erase(0,3);//Intro Bytes
bool FinalByteRead = false;
while( !FinalByteRead ) {
MyData += InputData[0];
InputData.erase(0,1);
if( InputData[0] == 0x00 && InputData[1] == 0x00 ) {
if( InputData[2] == 0x01 ) {
FinalByteRead = true;
}
if( InputData[2] == 0x00 && InputData[3] == 0x01 ) {
InputData.erase(0,1);
FinalByteRead= true;
}
}
}
} else {
if( InputData.size() < 4 ) { return false; }
int UnitLen = (InputData[0] << 24) + (InputData[1] << 16) + (InputData[2] << 8) + InputData[3];
if( InputData.size() < 4+UnitLen ) { return false; }
InputData.erase(0,4);//Remove Length
MyData = InputData.substr(0,UnitLen);
InputData.erase(0,UnitLen);//Remove this unit from the string
}
return true;
}
std::string NAL_Unit::AnnexB( bool LongIntro ) {
std::string Result;
if( MyData.size() ) {
if( LongIntro ) { Result += (char)0x00; }
Result += (char)0x00;
Result += (char)0x00;
Result += (char)0x01;//Annex B Lead-In
Result += MyData;
}
return Result;
}
std::string NAL_Unit::SizePrepended( ) {
std::string Result;
if( MyData.size() ) {
int DataSize = MyData.size();
Result += (char)( ( DataSize & 0xFF000000 ) >> 24 );
Result += (char)( ( DataSize & 0x00FF0000 ) >> 16 );
Result += (char)( ( DataSize & 0x0000FF00 ) >> 8 );
Result += (char)( DataSize & 0x000000FF );//Size Lead-In
Result += MyData;
}
return Result;
}
int NAL_Unit::Type( ) {
return ( MyData[0] & 0x1F );
}

13
lib/nal.h Normal file
View file

@ -0,0 +1,13 @@
#include <string>
class NAL_Unit {
public:
NAL_Unit( );
NAL_Unit( std::string & InputData );
bool ReadData( std::string & InputData );
std::string AnnexB( bool LongIntro = false );
std::string SizePrepended( );
int Type( );
private:
std::string MyData;
};//NAL_Unit class

View file

@ -368,11 +368,55 @@ int TS::Packet::PESTimeStamp( ) {
return 0;
}
int TS::Packet::GetDataOffset( ) {
int Offset = 4;
fprintf( stderr,"\tBefore Adapt: %d\n", Offset );
if( AdaptationField( ) >= 2 ) {
Offset += 1 + AdaptationFieldLen( );
}
fprintf( stderr,"\tBefore UnitStart: %d\n", Offset );
if( UnitStart() ) {
fprintf( stderr, "\t\tPES Header Len: %d\n", Buffer[Offset+8] );
Offset += 8;//Default Header + Flag Bytes
Offset += 1 + Buffer[Offset];//HeaderLengthByte + HeaderLength
}
fprintf( stderr,"\tBefore Return: %d\n", Offset );
return Offset;
}
/*
DTSC::DTMI TS::Packet::toDTSC(DTSC::DTMI & metadata, std::string Type) {
DTSC::DTMI outPack = DTSC::DTMI(Type, DTSC::DTMI_ROOT);
outPack.addContent(DTSC::DTMI("datatype", Type));
if( UnitStart() ) {
outPack.addContent(DTSC::DTMI("time", PESTimeStamp( )));
}
if( UnitStart() ){ outPack.addContent(DTSC::DTMI("time", PESTimeStamp( ))); }
if( Type == "video" && (RandomAccess() > 0) ){ outPack.addContent(DTSC::DTMI("keyframe", 1)); }
int DataOffset = GetDataOffset();
fprintf( stderr, "Data Offset: %d\n", DataOffset );
outPack.addContent(DTSC::DTMI("data", std::string((char*)Buffer+DataOffset, (size_t)188-DataOffset)));
return outPack;
}
*/
void TS::Packet::toDTSC( std::string Type, DTSC::DTMI & CurrentDTSC ) {
if( !CurrentDTSC.getContentP( "datatype" ) ) {
CurrentDTSC.addContent( DTSC::DTMI("datatype", Type ) );
}
if( UnitStart() ) {
if( !CurrentDTSC.getContentP( "time" ) ) {
CurrentDTSC.addContent( DTSC::DTMI( "time", PESTimeStamp( ) ) );
}
}
if( Type == "video" && (RandomAccess() > 0) ){
if( !CurrentDTSC.getContentP( "keyframe" ) ) {
CurrentDTSC.addContent(DTSC::DTMI("keyframe", 1));
}
}
int DataOffset = GetDataOffset();
fprintf( stderr, "Data Offset: %d\n", DataOffset );
std::string ToAppend = std::string((char*)Buffer+DataOffset, (size_t)188-DataOffset);
std::string CurrentData;
if( CurrentDTSC.getContentP( "data" ) ) {
CurrentData = CurrentDTSC.getContent( "data" ).StrValue( );
}
CurrentDTSC.addContent(DTSC::DTMI("data", CurrentData + ToAppend ));
}

View file

@ -47,11 +47,13 @@ namespace TS {
void FFMpegHeader( );
int PESTimeStamp( );
int GetDataOffset( );
//For output to DTSC
int ProgramMapPID( );
void UpdateStreamPID( int & VideoPid, int & AudioPid );
DTSC::DTMI toDTSC(DTSC::DTMI & metadata, std::string Type);
//DTSC::DTMI toDTSC(DTSC::DTMI & metadata, std::string Type);
void toDTSC( std::string Type, DTSC::DTMI & CurrentDTSC );
private:
int Free;
char Buffer[188];///< The actual data

View file

@ -6,4 +6,3 @@ MistFLV2DTSC_SOURCES=flv2dtsc.cpp
MistDTSCFix_SOURCES=dtscfix.cpp
MistDTSC2TS_SOURCES=dtsc2ts.cpp
MistTS2DTSC_SOURCES=ts2dtsc.cpp