Cyonix rajib cornelius Andrew Davey SecretSoftware Ang3lFir3 IceFreak2000 jamie Dodo DoomBringer sbc figuerres rjdohnert JChung2006 Tom Servo zian JohnAskew mVPstar Dr Herbie scobleizer Mike Dimmick jb43081 StevieLINQ erik_ eddwo Escamillo Sabot Wil z33driver Chadk Adenocard XiXora rhm Tyler Brown Jason R. Shaver
blowdart Siyavash chrisgray Code4Fun gokong

1,711 online

Home

Shows

Media

Wikis

Forums

Playground

Search

ReadMe.txt

Login

Going Deep

ARCast

WM_IN

> All Shows

Videos

Podcasts

Screencasts

Photos

>
All Media

The
Coffeehouse

Techoff

Beta
Feedback

> All
Forums

Sandbox

CTP Madness

Clipster

>
All the Goodness

Channel 9
Forums » The Sandbox
» Mpeg header reader (mpgtx source converted to
c#)

Mpeg header reader (mpgtx source converted to c#)

devnull

Posted by devnull // Sun, Jun 11, 2006 9:11
PM

i couldn't find anything in c# that read mpeg
headers so here is mpgtx source converted to c#.

ideas
for code improvement are welcome :)

enjoy

EDIT:
zip file with .cs file didn't get uploaded?

--start
code--
using System;
using
System.Collections.Generic;
using System.Text;
using
System.IO;

namespace
MPEGHeaderReader
{
public class
MpegInfo

{
#region index
structures from mpgtx
source
int[, ,]
BitRateIndex = new int[2, 3,
16]

{

{ // MPEG
1

{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0}, //
layer
1

{0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,0}, //
layer 2

{0,32,40,48, 56, 64, 80,
96,112,128,160,192,224,256,320,0}  // layer
3

},

{// MPEG 2 or 2.5

{0,32,48,56, 64, 80, 96,112,128,144,160,176,192,224,256,0}, //
layer
1

{0, 8,16,24, 32, 40, 48,
56, 64, 80, 96,112,128,144,160,0}, // layer
2

{0, 8,16,24, 32, 40, 48, 56, 64, 80,
96,112,128,144,160,0}  // layer
3

}

};

int[,]
SamplingIndex = new int[3,
4]

{

{44100,48000,32000,0}, // mpeg 1

{22050,24000,16000,0}, // mpeg 2

{11025,12000, 8000,0}  // mpeg
2.5

};

double[]
FrameRateIndex = new
double[9]

{

0d, 24000d/1001d,
24d, 25d,

30000d/1001d, 30d,
50d,

60000d/1001d,
60d

};

string[]
AspectRatioIndex = new
string[5]

{

"Invalid",

"1/1
(VGA)",

"4/3
(TV)",

"16/9 (Large
TV)",

"2.21/1
(Cinema)"

};

public
string[] ModeIndex = new string[4] // these can change anytime
specs change so be
careful

{

"Stereo",

"Joint
Stereo",

"Dual
Channel",

"Mono",

};

public
string[] EmphasisIndex = new string[4] // same as
above

{

"No
Emphasis",

"50/15 Micro
seconds",

"Unknown",

"CCITT J
17",

};

#endregion

#region
properties

public class
Video

{

public int Height; //
px

public int
Width;

public double FrameRate; //
fps

public int
AspectRatioCode;

public string
AspectRatio;

public int
BitRate;

public double Duration; //
seconds

public long
MuxRate;

public int
ChromaFormat;

public string
ChromaFormatText;

public int
Format;

public string
FormatText;

public int
Frames;

public int Version = 1; // by default its
1

}
public Video
VideoInfo;

public class
Audio

{

public double
Version;

public int
Layer;

public bool
Protected;

public int
BitRate;

public float
ByteRate;

public int
SamplingRate;

public bool
Padding;

public int
ModeCode;

public int
ModeXt;

public bool
Copyright;

public int
EmphasisIndex;

public bool
Original;

public int
FrameLength;

// seconds; duration = file size / bit rate but from what i
understand there is a
timestamp

// for initial and one for when video ends, so accurate
duration = timestamp end - timestamp
start

public double
Duration;

public int
Frames;

}
public Audio
AudioInfo;

#endregion

public bool EnableTrace; // debugging
purposes

const byte PADDING_PACKET = 0xBE; // use these to compare
instead of bytes every
time
const byte
VIDEO_PACKET =
0xE0;
const byte
AUDIO_PACKET =
0xC0;
const byte
SYSTEM_PACKET =
0xBB;

const
double FLOAT_0x10000 = (double)((UInt32)1 << 16); //
unsigned long in c++ is UInt32 in
c#
const UInt32
STD_SYSTEM_CLOCK_FREQ =
(UInt32)90000;

const int BUFFER_SIZE = 8162; // 8K
buffer

int
_mpegVersion =
1;
long
_fileSize;

double _initialTS; // needed to fix video/audio
duration
bool
_mpeg2Found; // switch needed to fix video
duration

byte[]
_backwardBuffer;

byte[]
_forwardBuffer;

FileStream _fs;

BinaryReader
_br;

public
MpegInfo(string
file)

{

_fs = new FileStream(file, FileMode.Open, FileAccess.Read,
FileShare.ReadWrite);

_br = new
BinaryReader(_fs);

}

public
void Parse()

{

if (_br !=
null)

{

try

{

_backwardBuffer = new
byte[BUFFER_SIZE];

_forwardBuffer = new
byte[BUFFER_SIZE];

_fileSize =
_fs.Length;

VideoInfo = new
Video();

AudioInfo = new
Audio();

ParseVideo(0);

//_br.BaseStream.Seek(0, SeekOrigin.Begin); // go back to the
start (redundant
now)

ParseAudio();

//_br.BaseStream.Seek(0, SeekOrigin.Begin); // go back to the
start

ParseSystem(0);

}

catch (Exception
err)

{

// TODO: Better exception
handling

Console.WriteLine(err.ToString());

}

finally

{

_fs.Close();

_br.Close();

}

}

}

int
_backwardBufferStart =
0;
int
_backwardBufferEnd =
0;

byte
GetByteBackwards(int
offset)

{

int pos =
-1;

if (offset >= _backwardBufferEnd || offset <
_backwardBufferStart) // need new
buffer

{

//Trace(string.Format("-debug- new buffer needed; offset: {0},
buffer start: {1}, buffer end: {2}",
offset,

//    _backwardBufferStart,
_backwardBufferEnd));

pos = offset - BUFFER_SIZE +
1;

if (pos < 0) { pos = 0;
}

//Trace(string.Format("-debug- position: {0}",
pos));

_backwardBufferStart =
pos;

_backwardBufferEnd =
offset;

//Trace(string.Format("-debug- buffer start: {0}, buffer end:
{1}",

//    _backwardBufferStart,
_backwardBufferEnd));

_br.BaseStream.Seek(pos,
SeekOrigin.Begin);

_br.Read(_backwardBuffer, 0,
BUFFER_SIZE);

}

//Trace(string.Format("-debug- offset: {0}, buffer start:
{1}",

//        offset,
_backwardBufferStart));

// got new buffer or still  in
rage

return _backwardBuffer[offset -
_backwardBufferStart];

}

int
_forwardBufferStart =
0;
int
_forwardBufferEnd =
0;

byte
GetByte(int
offset)

{

int pos =
-1;

if (offset >= _forwardBufferEnd || offset <
_forwardBufferStart) // need new
buffer

{

//Trace(string.Format("-debug- new f buffer needed; offset:
{0}, buffer start: {1}, buffer end: {2}",
offset,

//    _forwardBufferStart,
_forwardBufferEnd));

pos = offset +
BUFFER_SIZE;

if (pos > _fileSize) { pos = (int)_fileSize;
}

//Trace(string.Format("-debug- f position: {0}",
pos));

_forwardBufferStart =
offset;

_forwardBufferEnd =
pos;

//Trace(string.Format("-debug- f buffer start: {0}, buffer
end:
{1}",

//    _forwardBufferStart,
_forwardBufferEnd));

_br.BaseStream.Seek(offset,
SeekOrigin.Begin);

_br.Read(_forwardBuffer, 0,
BUFFER_SIZE);

}

//Trace(string.Format("-debug- f offset: {0}, buffer start:
{1}",

//        offset,
_forwardBufferStart));

// got new buffer or still  in
rage

return _forwardBuffer[offset -
_forwardBufferStart];

}

int
GetSize(int
offset)

{

return GetByte(offset) * 256 + GetByte(offset +
1);

}

///
<summary>

/// Find the specified marker given a starting
position
///
</summary>

/// <param name="offset">Position to start searching
from</param>

/// <param name="marker">Marker to search
for</param>

/// <returns>True and the offset if the maker is
found</returns>

bool EnsureMPEG(out int offset, byte
marker)

{

offset =
0;

for (int i = 0; i < _fileSize - 4;
i++)

{

if (GetByte(i) ==
0x00

&& GetByte(i + 1) ==
0x00

&& GetByte(i + 2) ==
0x01

&& GetByte(i + 3) ==
marker)

{

offset =
i;

return
true;

}

}

return false;

}

///
<summary>

/// Find a specific marker by going through the file in
reverse
///
TODO: Improve this (GetByte() is slow when using this method
because it seeks from the
start
///
</summary>

/// <param name="offset">Position to start searching
from</param>

/// <param name="marker">Marker to search
for</param>

/// <returns>Position of the
marker</returns>

int FindMarkerBackwards(int offset, byte
marker)

{

for (int i = offset; i > 0;
i--)

{

if (GetByteBackwards(i) ==
0x00

&& GetByteBackwards(i + 1) ==
0x00

&& GetByteBackwards(i + 2) ==
0x01

&& GetByteBackwards(i + 3) ==
marker)

{

return
i;

}

}

return -1;

}

bool
MarkerExistsAt(out int offset, byte marker, int from) // self
explanatory / see
above

{

offset =
-1;

for (int i = from; i < _fileSize - 4;
i++)

{

if (GetByte(i) ==
0x00

&& GetByte(i + 1) ==
0x00

&& GetByte(i + 2) ==
0x01

&& GetByte(i + 3) ==
marker)

{

offset =
i;

return
true;

}

}

return false;

}

int
FindNextMarker(int from, byte marker) // overloaded method /
see above

{

int offset =
from;

while (offset >=
0)

{

offset =
FindNextMarker(offset);

if (offset ==
-1)

{

return
-1;

}

if (MarkerExistsAt(out offset, marker,
offset))

{

return
offset;

}

else

{

offset++;

}

}

return -1;

}

int
FindNextMarker(int from, ref byte marker) // see
above

{

int offset =
FindNextMarker(from);

if (offset >
-1)

{

marker = GetByte(offset +
3);

return
offset;

}

return -1;

}

int
FindNextMarker(int from) // see
above

{

int
offset;

for (offset = from; offset < (_fileSize - 4);
offset++)

{

if
(

(GetByte(offset + 0) == 0x00)
&&

(GetByte(offset + 1) == 0x00)
&&

(GetByte(offset + 2) ==
0x01))

{

return
offset;

}

}

return -1;

}

bool
hasAudio =
false;
void
ParseSystem(int
offset)

{

bool keepGoing =
true;

byte mark =
0x00;

if (EnsureMPEG(out offset, 0xBA)) // make sure we'r parsing a
mpeg
header

{

//FindMuxRate(offset +
4);

int packLength =
0;

int packetSize =
0;

byte packetType = new
byte();

while
(keepGoing)

{

offset = FindNextMarker(offset, ref
mark);

if (offset ==
-1)

{

break; // valid marker not
found

}

if (mark == VIDEO_PACKET || mark ==
AUDIO_PACKET)

{

break; // end of system
header

}

if (mark ==
PADDING_PACKET)

{

offset += GetSize(offset +
4);

continue;

}

if (mark ==
0xBA)

{

FindMuxRate(offset +
4);

offset +=
12;

continue;

}

if (mark !=
SYSTEM_PACKET)

{

offset +=
4;

continue;

}

int startOfPack = FindNextMarker(offset,
0xBA);

if (startOfPack !=
-1)

{

if ((GetByte(startOfPack + 4) & 0xF0) ==
0x20)

{

packLength = 12; // mpeg
1

}

else

{

if ((GetByte(startOfPack + 4) & 0xC0) ==
0x40)

{

// mpeg 2 pack +
stuffing

packLength = 14 + (GetByte(startOfPack + 13) &
0x07);

}

else

{

packLength = 12; // somethings not
right

}

}

}

if (startOfPack == -1 || (startOfPack + packLength !=
offset))

{

//Trace(string.Format("-debug- startOfPack: {0}, packLength:
{1}, offset: {2}",

//    startOfPack, packLength,
offset));

startOfPack =
offset;

//return; keep going
anyway

}

// TODO: Implement
ParseSystemPacket

packetSize = GetSize(offset +
4);

packetType = GetByte(offset +
12);

//Trace(string.Format("-debug- packetSize: {0}, packetType:
{1}, packLength: {2}, offset:
{3}",

//    packetSize, packetType, packLength,
offset));

if (GetByte(offset + 15) == AUDIO_PACKET || GetByte(offset +
15) ==
VIDEO_PACKET)

{

packetType =
VIDEO_PACKET;

}

if (packetType ==
AUDIO_PACKET)

{

// TODO: Implement this if
needed

}

else if (packetType ==
VIDEO_PACKET)

{

// here we are finally!, this part will fix up the
durations

if (packLength ==
12)

{

_initialTS = ReadTS(offset - packLength); // find the initial
timestamp

_mpeg2Found = false; // pack 12 so its not mpeg
2

}

else

{

_initialTS = ReadTSMpeg2(offset -
packLength);

_mpeg2Found =
true;

}

//Trace(string.Format("-debug- initial ts: {0}",
_initialTS));

}

offset += 4; // keep
going

}

}

/* hopefully it gets to here without crashing
:P

* start searching from the end of the file and -12 because a
pack is usually 12 bytes
long

*/

int lastPack = FindMarkerBackwards((int)_fileSize - 13,
0xBA);

//Trace(string.Format("-debug- lastPack: {0}",
lastPack));

double
duration;

if ((GetByte(lastPack + 4) & 0xF0) ==
0x20)

{

duration = ReadTS(lastPack + 4); // mpeg
1

}

else

{

lastPack = FindMarkerBackwards((int)_fileSize - 8,
0xB8);

//Trace(string.Format("-debug- lastPack 2: {0}",
lastPack));

if (((GetByte(lastPack + 4) & 0xC0) == 0x40) ||
_mpeg2Found)

{

lastPack = FindMarkerBackwards((int)_fileSize - 8,
0xBA);

//Trace(string.Format("-debug- lastPack 3: {0}",
lastPack));

duration = ReadTSMpeg2(lastPack +
4);

}

else

{

duration = ReadTSMpeg2(lastPack +
4);

}

}

//Trace(string.Format("-debug- duration before: {0}",
duration));

duration -= _initialTS; // fix up the
duration

//Trace(string.Format("-debug- duration after: {0}",
duration));

this.VideoInfo.Duration = duration; //
fixed

this.AudioInfo.Duration = duration; // not
needed

//Trace(string.Format("-debug- video duration: {0}",
SecondsToHMS(this.VideoInfo.Duration)));

}

double
ReadTS(int
offset)

{

byte
highBit;

UInt32 low4Bytes; // needs to be UInt32 otherwise won't
work

double
ts;

highBit = (byte)((GetByte(offset) >> 3) &
0x01);

low4Bytes = (UInt32)(((GetByte(offset) >> 1) & 0x03)
<<
30);

low4Bytes |= (UInt32)(GetByte(offset + 1) <<
22);

low4Bytes |= (UInt32)((GetByte(offset + 2) >> 1)
<<
15);

low4Bytes |= (UInt32)(GetByte(offset + 3) <<
7);

low4Bytes |= (UInt32)(GetByte(offset + 4) >>
1);

ts = (double)(highBit * FLOAT_0x10000 *
FLOAT_0x10000);

ts +=
(double)(low4Bytes);

ts /=
(double)STD_SYSTEM_CLOCK_FREQ;

return ts;

}

double
ReadTSMpeg2(int
offset)

{

byte
highBit;

UInt32
low4Bytes;

UInt32
sysClockRef;

double
ts;

highBit = (byte)((GetByte(offset) & 0x20) >>
5);

low4Bytes = (UInt32)(((GetByte(offset) & 0x18) >> 3)
<<
30);

low4Bytes |= (UInt32)((GetByte(offset) & 0x03) <<
28);

low4Bytes |= (UInt32)(GetByte(offset + 1) <<
20);

low4Bytes |= (UInt32)((GetByte(offset + 2) & 0xF8)
<<
12);

low4Bytes |= (UInt32)((GetByte(offset + 2) & 0x03)
<<
13);

low4Bytes |= (UInt32)(GetByte(offset + 3) <<
5);

low4Bytes |= (UInt32)(GetByte(offset + 4) >>
3);

sysClockRef = (UInt32)((GetByte(offset + 4) & 0x3)
<<
7);

sysClockRef |= (UInt32)((GetByte(offset + 5) >>
1));

ts = (double)(highBit * FLOAT_0x10000 *
FLOAT_0x10000);

ts +=
(double)low4Bytes;

// TODO: fix this up (confirm with mpgtx
first)

if (sysClockRef ==
0)

{

ts /=
(double)STD_SYSTEM_CLOCK_FREQ;

}

else

{

ts /=
(double)STD_SYSTEM_CLOCK_FREQ;

}

return ts;

}

void
FindMuxRate(int
offset)

{

int muxrate =
0;

if ((GetByte(offset) & 0xC0) ==
0x40)

{

muxrate = GetByte(offset + 6) <<
14;

muxrate |= GetByte(offset + 7) <<
6;

muxrate |= GetByte(offset + 8) >>
2;

}

else

{

if ((GetByte(offset) & 0xF0) !=
0x20)

{

muxrate = (GetByte(offset + 5) & 0x7F) <<
15;

muxrate |= (GetByte(offset + 6) <<
7);

muxrate |= (GetByte(offset + 7) >>
1);

}

}

muxrate *=
50;

this.VideoInfo.MuxRate = (long)((muxrate * 8.0) /
1000000);

//Trace(string.Format("system mux rate: {0} mbps",
this.VideoInfo.MuxRate.ToString("n2")));

}

void
ParseAudio()

{

int offset =
0;

hasAudio =
false;

offset = FindNextMarker(0, 0xC0); // find the audio
marker

if (offset >
-1)

{

offset +=
13;

}

if
(!ParseAudio(offset))

{

while ((offset < _fileSize - 10) && !hasAudio) //
go through the file until we find an audio
marker

{

if ((GetByte(offset) == 0xFF) && (GetByte(offset + 1)
& 0xF0) == 0xF0) // found the proper
sequence

{

if
(ParseAudio(offset))

{

//this.AudioInfo.Frames++; this doesn't work
right

hasAudio =
true;

}

}

offset++; // try next
offset

}

}

//Trace(string.Format("-debug- audio frames: {0}",
this.AudioInfo.Frames));

}

bool
ParseAudio(int
offset)

{

hasAudio =
false;

bool mpeg25 =
false;

if ((GetByte(offset + 0) != 0xFF) || ((GetByte(offset + 1)
& 0xF0) != 0xF0)) // see if this has mpeg
2.5

{

if ((GetByte(offset + 0) != 0xFF) || ((GetByte(offset + 1)
& 0xE0) !=
0xE0))

{

return false; // invalid sequence exit and try a different
offset

}

else

{

mpeg25 =
true;

}

}

//Trace(string.Format("-debug- offset: {0}",
offset));

//Trace(string.Format("-debug- mpeg25: {0}",
mpeg25));

if (Convert.ToBoolean((GetByte(offset + 1) &
0x08)))

{

if
(!mpeg25)

{

this.AudioInfo.Version =
1.0d;

}

else

{

//Trace(string.Format("-debug- invalid
01"));

return false; // invalid version exit and try a different
offset

}

}

else

{

if
(!mpeg25)

{

this.AudioInfo.Version =
2.0d;

}

else

{

this.AudioInfo.Version = 3.0d; // for
2.5

}

}

//Trace(string.Format("-debug- audio version: {0}",
this.AudioInfo.Version));

this.AudioInfo.Layer = (GetByte(offset + 1) & 0x06)
>>
1;

switch
(this.AudioInfo.Layer)

{

case
0:

this.AudioInfo.Layer =
-1;

return false; // invalid layer exit and try a different
offset

break;

case
1:

this.AudioInfo.Layer =
3;

break;

case
2:

this.AudioInfo.Layer =
2;

break;

case
3:

this.AudioInfo.Layer =
1;

break;

default:

this.AudioInfo.Layer =
-1;

return
false;

break;

}

//Trace(string.Format("-debug- audio layer: {0}",
this.AudioInfo.Layer));

// TODO: confirm if 0 is true or 1 is true, mpgtx has 0 is
false and 1 is
true?

this.AudioInfo.Protected = Convert.ToBoolean(GetByte(offset +
1) &
0x01);

//Trace(string.Format("-debug- audio protection: {0}",
this.AudioInfo.Protected));

int bitrateIndex = GetByte(offset + 2) >>
4;

int samplingIndex = (GetByte(offset + 2) & 0x0F) >>
2;

if (samplingIndex >= 3) { return false; } // invalid
indexes, try another
offset

if (bitrateIndex == 15) { return false;
}

this.AudioInfo.BitRate =
BitRateIndex[(int)this.AudioInfo.Version-1,
this.AudioInfo.Layer-1,
bitrateIndex];

this.AudioInfo.ByteRate = (float)((this.AudioInfo.BitRate *
1000) /
8.0d);

this.AudioInfo.SamplingRate =
SamplingIndex[(int)this.AudioInfo.Version - 1,
samplingIndex];

if (this.AudioInfo.BitRate <=
0

|| this.AudioInfo.ByteRate <=
0

|| this.AudioInfo.SamplingRate <= 0) { return false;
}

//Trace(string.Format("-debug- audio bit rate: {0}",
this.AudioInfo.BitRate));

//Trace(string.Format("-debug- audio byte rate: {0}",
this.AudioInfo.ByteRate));

//Trace(string.Format("-debug- audio sampling rate: {0}",
this.AudioInfo.SamplingRate));

if (Convert.ToBoolean(GetByte(offset + 2) &
0x02))

{

this.AudioInfo.Padding =
true;

}

else

{

this.AudioInfo.Padding =
false;

}

//Trace(string.Format("-debug- audio padding: {0}",
this.AudioInfo.Padding));

this.AudioInfo.ModeCode = GetByte(offset + 3) >>
6;

//Trace(string.Format("-debug- audio mode: {0}",
ModeIndex[this.AudioInfo.ModeCode]));

//TODO: add matching mode extension
text

int modeExt = (GetByte(offset + 3) >> 4) &
0x03;

//Trace(string.Format("-debug- audio modeext: {0}",
modeExt));

if (Convert.ToBoolean(GetByte(offset + 3) &
0x08))

{

this.AudioInfo.Copyright =
true;

}

else

{

this.AudioInfo.Copyright =
false;

}

//Trace(string.Format("-debug- audio copyright: {0}",
this.AudioInfo.Copyright));

if (Convert.ToBoolean(GetByte(offset + 3) &
0x04))

{

this.AudioInfo.Original =
true;

}

else

{

this.AudioInfo.Original =
false;

}

//Trace(string.Format("-debug- audio original: {0}",
this.AudioInfo.Original));

this.AudioInfo.EmphasisIndex = GetByte(offset + 3) &
0x03;

//Trace(string.Format("-debug- audio emphasis index:
{0}",

//
EmphasisIndex[this.AudioInfo.EmphasisIndex]));

if (this.AudioInfo.Version ==
1)

{

if (this.AudioInfo.Layer ==
1)

{

this.AudioInfo.FrameLength
=

((48000 * this.AudioInfo.BitRate) /
this.AudioInfo.SamplingRate)

+ 4 *
Convert.ToInt32(this.AudioInfo.Padding);

}

else

{

this.AudioInfo.FrameLength
=

((144000 * this.AudioInfo.BitRate) /
this.AudioInfo.SamplingRate)

+
Convert.ToInt32(this.AudioInfo.Padding);

}

}

else if (this.AudioInfo.Version ==
2)

{

if (this.AudioInfo.Layer ==
1)

{

this.AudioInfo.FrameLength
=

((24000 * this.AudioInfo.BitRate) /
this.AudioInfo.SamplingRate)

+ 4 *
Convert.ToInt32(this.AudioInfo.Padding);

}

else

{

this.AudioInfo.FrameLength
=

((72000 * this.AudioInfo.BitRate) /
this.AudioInfo.SamplingRate)

+
Convert.ToInt32(this.AudioInfo.Padding);

}

}

else

{

//Trace(string.Format("-debug- audio layer is
invalid"));

return
false;

}

if
(this.AudioInfo.Protected)

{

// frame length sometimes gets offset by +- 2, got to find out
why its happening, most likely its the protection switch (see
above)

this.AudioInfo.FrameLength +=
2;

}

//Trace(string.Format("-debug- audio frame length: {0}",
this.AudioInfo.FrameLength));

this.AudioInfo.Duration = ((_fileSize * 1.0d) /
this.AudioInfo.BitRate) *
0.008d;

//Trace(string.Format("-debug- audio duration: {0}",
SecondsToHMS(this.AudioInfo.Duration)));

//CountAudioFrames();

hasAudio =
true;

return hasAudio;

}

bool
ParseVideo(int
offset)

{

bool foundVideo =
false;

//Trace(string.Format("-debug- file size: {0}",
_fileSize));

if (EnsureMPEG(out offset,
0xB3))

{

foundVideo =
true;

}

if
(foundVideo)

{

//Trace(string.Format("-debug- offset: {0}",
offset));

offset += 4; // move to the header
location

this.VideoInfo.Height = GetSize(offset) >>
4;

this.VideoInfo.Width = GetSize(offset + 1) &
0x0FFF;

//Trace(string.Format("-debug- video height: {0}",
this.VideoInfo.Height));

//Trace(string.Format("-debug- video width: {0}",
this.VideoInfo.Width));

offset +=
3;

int frameRateIndex = GetByte(offset) &
0x0F;

if (frameRateIndex >
8)

{

this.VideoInfo.FrameRate =
0.0d;

}

else

{

this.VideoInfo.FrameRate =
FrameRateIndex[frameRateIndex];

}

//Trace(string.Format("-debug- video frame rate: {0}",
this.VideoInfo.FrameRate));

this.VideoInfo.AspectRatioCode = (GetByte(offset) & 0xF0)
>>
4;

if (this.VideoInfo.AspectRatioCode <=
4)

{

this.VideoInfo.AspectRatio =
AspectRatioIndex[this.VideoInfo.AspectRatioCode];

}

else

{

this.VideoInfo.AspectRatio =
"Unknown";

}

//Trace(string.Format("-debug- video aspect ratio code: {0},
string: {1}",

//    this.VideoInfo.AspectRatioCode,
this.VideoInfo.AspectRatio));

offset +=
1;

this.VideoInfo.BitRate =
GetSize(offset);

//Trace(string.Format("-debug- video bit rate: {0}",
this.VideoInfo.BitRate));

this.VideoInfo.BitRate <<=
2;

//Trace(string.Format("-debug- video bit rate: {0}",
this.VideoInfo.BitRate));

byte lastTwo = GetByte(offset +
2);

//Trace(string.Format("-debug- video lastTwo: {0}",
lastTwo));

lastTwo >>=
6;

//Trace(string.Format("-debug- video lastTwo: {0}",
lastTwo));

this.VideoInfo.BitRate |=
lastTwo;

//Trace(string.Format("-debug- video bit rate: {0}",
this.VideoInfo.BitRate));

this.VideoInfo.Duration = (_fileSize) /

((this.VideoInfo.BitRate * 400) / 8.0); // this gets fixed
later when ParseSystem
runs

//Trace(string.Format("-debug- video duration: {0}",
SecondsToHMS(this.VideoInfo.Duration)));

//Trace(string.Format("-debug- video speed: {0} Mbps",

//    (this.VideoInfo.BitRate /
2500).ToString("n2"))); // always
15mb/s?

// this part is needed to find video format and chroma
format

byte mark = new
byte();

while
(true)

{

offset = FindNextMarker(offset, ref
mark);

if (offset >
-1)

{

if (mark == 0xB8) { break;
}

switch (GetByte(offset +
3))

{

case
0xB5:

ParseExtension(offset);

break;

default:

break;

}

}

else

{

//Trace(string.Format("-debug- video offset is
-1"));

break;

}

offset++;

}

switch
(this.VideoInfo.ChromaFormat)

{

case
1:

this.VideoInfo.ChromaFormatText =
"4:2:0";

break;

case
2:

this.VideoInfo.ChromaFormatText =
"4:2:2";

break;

case
3:

this.VideoInfo.ChromaFormatText =
"4:4:4";

break;

default:

this.VideoInfo.ChromaFormatText =
"Unknown";

break;

}

switch
(this.VideoInfo.Format)

{

case
0:

this.VideoInfo.FormatText =
"Component";

break;

case
1:

this.VideoInfo.FormatText =
"PAL";

break;

case
2:

this.VideoInfo.FormatText =
"NTSC";

break;

case
3:

this.VideoInfo.FormatText =
"SECAM";

break;

case
4:

this.VideoInfo.FormatText =
"MAC";

break;

case
5:

this.VideoInfo.FormatText =
"Unspecified";

break;

default:

this.VideoInfo.FormatText =
"Unknown";

break;

}

//Trace(string.Format("-debug- video chroma format: {0} is
{1}",

//    this.VideoInfo.ChromaFormat,
this.VideoInfo.ChromaFormatText));

//Trace(string.Format("-debug- video format: {0} is {1}",

//    this.VideoInfo.Format,
this.VideoInfo.FormatText));

//CountVideoFrames(); slows down the
routine

//Trace(string.Format("-debug- video frames: {0}",
this.VideoInfo.Frames));

}

return false;

}

// remove
this and use
TimeSpan
string
SecondsToHMS(double
duration)

{

int hours = (int)(duration /
3600);

int mins = (int)((duration / 60) - (hours *
60));

double seconds = duration - 60 * mins - 3600 *
hours;

if (hours !=
0)

{

return string.Format("{0:n0}h {1:n0}m {2:n2}s",hours, mins,
seconds);

}

if (mins !=
0)

{

return string.Format("{0:n0}m {1:n2}s", mins,
seconds);

}

return string.Format("{0:n2}s",
seconds);

}

void
CountVideoFrames() // slow, find a better way of doing
this

{

byte[] buffer = new
byte[4];

_br.BaseStream.Seek(0,
SeekOrigin.Begin);

int read =
0;

while ((read = _br.Read(buffer, 0, 4)) !=
0)

{

if (buffer[0] ==
0x00

&& buffer[1] ==
0x00

&& buffer[2] ==
0x01

&& buffer[3] ==
0x00)

{

this.VideoInfo.Frames++;

}

}

}

void
ParseExtension(int
offset)

{

offset +=
4;

switch (GetByte(offset) >>
4)

{

case 1:
ParseSequenceExt(offset);

break;

case
2:

ParseSequenceDisplayExt(offset);

break;

default:

break;

}

}

void
ParseSequenceExt(int
offset)

{

_mpegVersion =
2;

this.VideoInfo.Version =
2;

this.VideoInfo.ChromaFormat = (GetByte(offset + 1) & 0x06)
>> 1;

}

void
ParseSequenceDisplayExt(int
offset)

{

this.VideoInfo.Format = (GetByte(offset) & 0x0E) >>
1;

}

int
SkipPacketHeader(int
offset)

{

byte mark = new
byte();

if (_mpegVersion ==
1)

{

offset +=
6;

mark =
GetByte(offset);

while (Convert.ToBoolean(mark &
0x80))

{

mark =
GetByte(++offset);

}

if ((mark & 0xC0) ==
0x40)

{

offset +=
2;

}

mark =
GetByte(offset);

if ((mark & 0xF0) == 0x20) { offset += 5;
}

else if ((mark & 0xF0) == 0x30) { offset += 10;
}

else
offset++;

return
offset;

}

else if (_mpegVersion ==
2)

{

return (offset + 9 + GetByte(offset +
8));

}

else return (offset +
10);

}

void
Trace(string
msg)

{

if
(this.EnableTrace)

{

Console.WriteLine(msg);

}

}
}
}

--end
code--

Channel 9
Forums » The Sandbox
» Mpeg header reader (mpgtx source converted to
c#)

> Featured

Installing PHP
Applications on IIS7

Terms of Use | Privacy Statement | Code of Conduct | Contact Us |
Hosted by Orcsweb.com | Mutated from Community Server and FlexWiki

© Copyright 2005 Microsoft
Corporation. All Rights Reserved.