changes for aac decoder
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24229 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
8c5c17cdbc
commit
9f6dbdea6a
|
@ -275,14 +275,24 @@ MP4FileReader::getVideoFrameCount(uint32 streamIndex)
|
|||
uint32
|
||||
MP4FileReader::getAudioFrameCount(uint32 streamIndex)
|
||||
{
|
||||
if (IsAudio(streamIndex)) {
|
||||
return uint32(((getAudioDuration(streamIndex)
|
||||
* AudioFormat(streamIndex)->SampleRate) / 1000000L) + 0.5);
|
||||
}
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
|
||||
|
||||
return 0;
|
||||
if (aAtomBase && dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio())
|
||||
return dynamic_cast<TRAKAtom *>(aAtomBase)->FrameCount();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32
|
||||
MP4FileReader::getAudioChunkCount(uint32 streamIndex)
|
||||
{
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
|
||||
|
||||
if (aAtomBase && dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio())
|
||||
return dynamic_cast<TRAKAtom *>(aAtomBase)->getTotalChunks();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
MP4FileReader::IsVideo(uint32 streamIndex)
|
||||
|
@ -329,23 +339,18 @@ MP4FileReader::getFirstFrameInChunk(uint32 streamIndex, uint32 pChunkID)
|
|||
|
||||
|
||||
uint32
|
||||
MP4FileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo)
|
||||
MP4FileReader::getNoFramesInChunk(uint32 streamIndex, uint32 pFrameNo)
|
||||
{
|
||||
// Find Track
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex);
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
uint32 ChunkNo = 1;
|
||||
|
||||
if (IsAudio(stream_index))
|
||||
ChunkNo = pFrameNo;
|
||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
||||
|
||||
if (IsVideo(stream_index)) {
|
||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
||||
|
||||
uint32 OffsetInChunk;
|
||||
ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
|
||||
}
|
||||
uint32 OffsetInChunk;
|
||||
ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
|
||||
|
||||
return aTrakAtom->getNoSamplesInChunk(ChunkNo);
|
||||
}
|
||||
|
@ -355,48 +360,38 @@ MP4FileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo)
|
|||
|
||||
|
||||
uint64
|
||||
MP4FileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo)
|
||||
MP4FileReader::getOffsetForFrame(uint32 streamIndex, uint32 pFrameNo)
|
||||
{
|
||||
// Find Track
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex);
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
|
||||
if (IsAudio(stream_index)) {
|
||||
// FrameNo is really chunk No for audio
|
||||
uint32 ChunkNo = pFrameNo;
|
||||
|
||||
if (pFrameNo < aTrakAtom->FrameCount()) {
|
||||
// Get Sample for Frame
|
||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
||||
// Get Chunk For Sample and the offset for the frame within that chunk
|
||||
uint32 OffsetInChunk;
|
||||
uint32 ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
|
||||
// Get Offset For Chunk
|
||||
return aTrakAtom->getOffsetForChunk(ChunkNo);
|
||||
}
|
||||
uint64 OffsetNo = aTrakAtom->getOffsetForChunk(ChunkNo);
|
||||
|
||||
if (IsVideo(stream_index)) {
|
||||
if (pFrameNo < aTrakAtom->FrameCount()) {
|
||||
// Get Sample for Frame
|
||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
||||
// Get Chunk For Sample and the offset for the frame within that chunk
|
||||
uint32 OffsetInChunk;
|
||||
uint32 ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
|
||||
// Get Offset For Chunk
|
||||
uint64 OffsetNo = aTrakAtom->getOffsetForChunk(ChunkNo);
|
||||
|
||||
if (ChunkNo != 0) {
|
||||
uint32 SizeForSample;
|
||||
// Adjust the Offset for the Offset in the chunk
|
||||
if (aTrakAtom->IsSingleSampleSize()) {
|
||||
SizeForSample = aTrakAtom->getSizeForSample(SampleNo);
|
||||
OffsetNo = OffsetNo + (OffsetInChunk * SizeForSample);
|
||||
} else {
|
||||
// This is bad news performance wise
|
||||
for (uint32 i=1;i<=OffsetInChunk;i++) {
|
||||
SizeForSample = aTrakAtom->getSizeForSample(SampleNo-i);
|
||||
OffsetNo = OffsetNo + SizeForSample;
|
||||
}
|
||||
if (ChunkNo != 0) {
|
||||
uint32 SizeForSample;
|
||||
// Adjust the Offset for the Offset in the chunk
|
||||
if (aTrakAtom->IsSingleSampleSize()) {
|
||||
SizeForSample = aTrakAtom->getSizeForSample(SampleNo);
|
||||
OffsetNo = OffsetNo + (OffsetInChunk * SizeForSample);
|
||||
} else {
|
||||
// This is bad news performance wise
|
||||
for (uint32 i=1;i<=OffsetInChunk;i++) {
|
||||
SizeForSample = aTrakAtom->getSizeForSample(SampleNo-i);
|
||||
OffsetNo = OffsetNo + SizeForSample;
|
||||
}
|
||||
}
|
||||
|
||||
return OffsetNo;
|
||||
}
|
||||
|
||||
return OffsetNo;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -476,10 +471,10 @@ MP4FileReader::MovMainHeader()
|
|||
|
||||
|
||||
const AudioMetaData *
|
||||
MP4FileReader::AudioFormat(uint32 stream_index, size_t *size)
|
||||
MP4FileReader::AudioFormat(uint32 streamIndex, size_t *size)
|
||||
{
|
||||
if (IsAudio(stream_index)) {
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
if (IsAudio(streamIndex)) {
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex);
|
||||
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
|
@ -496,7 +491,7 @@ MP4FileReader::AudioFormat(uint32 stream_index, size_t *size)
|
|||
theAudio.NoOfChannels = aAudioDescription.theAudioSampleEntry.ChannelCount;
|
||||
theAudio.SampleSize = aAudioDescription.theAudioSampleEntry.SampleSize;
|
||||
theAudio.SampleRate = aAudioDescription.theAudioSampleEntry.SampleRate / 65536; // Convert from fixed point decimal to float
|
||||
theAudio.PacketSize = uint32((theAudio.SampleRate * theAudio.NoOfChannels * theAudio.SampleSize) / 8);
|
||||
theAudio.PacketSize = uint32((theAudio.SampleSize * theAudio.NoOfChannels * 1024) / 8);
|
||||
|
||||
theAudio.theVOL = aAudioDescription.theVOL;
|
||||
theAudio.VOLSize = aAudioDescription.VOLSize;
|
||||
|
@ -509,12 +504,11 @@ MP4FileReader::AudioFormat(uint32 stream_index, size_t *size)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const VideoMetaData*
|
||||
MP4FileReader::VideoFormat(uint32 stream_index)
|
||||
MP4FileReader::VideoFormat(uint32 streamIndex)
|
||||
{
|
||||
if (IsVideo(stream_index)) {
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
if (IsVideo(streamIndex)) {
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex);
|
||||
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
|
@ -556,26 +550,26 @@ MP4FileReader::VideoFormat(uint32 stream_index)
|
|||
|
||||
|
||||
const mp4_stream_header*
|
||||
MP4FileReader::StreamFormat(uint32 stream_index)
|
||||
MP4FileReader::StreamFormat(uint32 streamIndex)
|
||||
{
|
||||
// Fill In a Stream Header
|
||||
theStreamHeader.length = 0;
|
||||
|
||||
if (IsActive(stream_index) == false) {
|
||||
if (IsActive(streamIndex) == false) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (IsVideo(stream_index)) {
|
||||
theStreamHeader.rate = uint32(1000000L*VideoFormat(stream_index)->FrameRate);
|
||||
if (IsVideo(streamIndex)) {
|
||||
theStreamHeader.rate = uint32(1000000L*VideoFormat(streamIndex)->FrameRate);
|
||||
theStreamHeader.scale = 1000000L;
|
||||
theStreamHeader.length = getVideoFrameCount(stream_index);
|
||||
theStreamHeader.length = getVideoFrameCount(streamIndex);
|
||||
}
|
||||
|
||||
if (IsAudio(stream_index)) {
|
||||
theStreamHeader.rate = uint32(AudioFormat(stream_index)->SampleRate);
|
||||
if (IsAudio(streamIndex)) {
|
||||
theStreamHeader.rate = uint32(AudioFormat(streamIndex)->SampleRate);
|
||||
theStreamHeader.scale = 1;
|
||||
theStreamHeader.length = getAudioFrameCount(stream_index);
|
||||
theStreamHeader.sample_size = AudioFormat(stream_index)->SampleSize;
|
||||
theStreamHeader.length = getAudioFrameCount(streamIndex);
|
||||
theStreamHeader.sample_size = AudioFormat(streamIndex)->SampleSize;
|
||||
theStreamHeader.suggested_buffer_size = theStreamHeader.rate * theStreamHeader.sample_size;
|
||||
}
|
||||
|
||||
|
@ -584,27 +578,15 @@ MP4FileReader::StreamFormat(uint32 stream_index)
|
|||
|
||||
|
||||
uint32
|
||||
MP4FileReader::getChunkSize(uint32 stream_index, uint32 pFrameNo)
|
||||
MP4FileReader::getChunkSize(uint32 streamIndex, uint32 pFrameNo)
|
||||
{
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex);
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
|
||||
if (IsAudio(stream_index)) {
|
||||
// We read audio in chunk by chunk so chunk size is chunk size
|
||||
uint32 ChunkNo = pFrameNo;
|
||||
off_t Chunk_Start = aTrakAtom->getOffsetForChunk(ChunkNo);
|
||||
uint32 ChunkSize = theChunkSuperIndex.getChunkSize(stream_index,ChunkNo,Chunk_Start);
|
||||
|
||||
return ChunkSize;
|
||||
}
|
||||
|
||||
if (IsVideo(stream_index)) {
|
||||
if (pFrameNo < aTrakAtom->FrameCount()) {
|
||||
// We read video in Sample by Sample so we use get Sample Size
|
||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
||||
return aTrakAtom->getSizeForSample(SampleNo);
|
||||
}
|
||||
if (pFrameNo < aTrakAtom->FrameCount()) {
|
||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
||||
return aTrakAtom->getSizeForSample(SampleNo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -613,9 +595,9 @@ MP4FileReader::getChunkSize(uint32 stream_index, uint32 pFrameNo)
|
|||
|
||||
|
||||
bool
|
||||
MP4FileReader::IsKeyFrame(uint32 stream_index, uint32 pFrameNo)
|
||||
MP4FileReader::IsKeyFrame(uint32 streamIndex, uint32 pFrameNo)
|
||||
{
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex);
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
|
||||
|
@ -628,14 +610,14 @@ MP4FileReader::IsKeyFrame(uint32 stream_index, uint32 pFrameNo)
|
|||
|
||||
|
||||
bool
|
||||
MP4FileReader::GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo,
|
||||
MP4FileReader::GetNextChunkInfo(uint32 streamIndex, uint32 pFrameNo,
|
||||
off_t *start, uint32 *size, bool *keyframe)
|
||||
{
|
||||
*start = getOffsetForFrame(stream_index, pFrameNo);
|
||||
*size = getChunkSize(stream_index, pFrameNo);
|
||||
*start = getOffsetForFrame(streamIndex, pFrameNo);
|
||||
*size = getChunkSize(streamIndex, pFrameNo);
|
||||
|
||||
if ((*start > 0) && (*size > 0)) {
|
||||
*keyframe = IsKeyFrame(stream_index, pFrameNo);
|
||||
*keyframe = IsKeyFrame(streamIndex, pFrameNo);
|
||||
}
|
||||
|
||||
// TODO need a better method for detecting End of Data Note ChunkSize of 0 seems to be it.
|
||||
|
@ -645,9 +627,9 @@ MP4FileReader::GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo,
|
|||
|
||||
|
||||
bool
|
||||
MP4FileReader::IsActive(uint32 stream_index)
|
||||
MP4FileReader::IsActive(uint32 streamIndex)
|
||||
{
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex);
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
return aTrakAtom->IsActive();
|
||||
|
|
|
@ -81,45 +81,47 @@ public:
|
|||
// Duration defined by the movie header
|
||||
bigtime_t getMovieDuration();
|
||||
|
||||
// The first video track duration indexed by stream_index
|
||||
bigtime_t getVideoDuration(uint32 stream_index);
|
||||
// the first audio track duration indexed by stream_index
|
||||
bigtime_t getAudioDuration(uint32 stream_index);
|
||||
// The first video track duration indexed by streamIndex
|
||||
bigtime_t getVideoDuration(uint32 streamIndex);
|
||||
// the first audio track duration indexed by streamIndex
|
||||
bigtime_t getAudioDuration(uint32 streamIndex);
|
||||
// the max of all active audio or video durations
|
||||
bigtime_t getMaxDuration();
|
||||
|
||||
// The no of frames in the video track indexed by stream_index
|
||||
uint32 getVideoFrameCount(uint32 stream_index);
|
||||
// The no of frames in the audio track indexed by stream_index
|
||||
uint32 getAudioFrameCount(uint32 stream_index);
|
||||
|
||||
// The no of frames in the video track indexed by streamIndex
|
||||
// 1 frame = 1 chunk
|
||||
uint32 getVideoFrameCount(uint32 streamIndex);
|
||||
// The no of frames in the audio track indexed by streamIndex
|
||||
uint32 getAudioFrameCount(uint32 streamIndex);
|
||||
// The no of chunks in the audio track indexed by streamIndex
|
||||
uint32 getAudioChunkCount(uint32 streamIndex);
|
||||
// Is stream (track) a video track
|
||||
bool IsVideo(uint32 stream_index);
|
||||
bool IsVideo(uint32 streamIndex);
|
||||
// Is stream (track) a audio track
|
||||
bool IsAudio(uint32 stream_index);
|
||||
bool IsAudio(uint32 streamIndex);
|
||||
|
||||
uint32 getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo);
|
||||
uint32 getFirstFrameInChunk(uint32 stream_index, uint32 pChunkID);
|
||||
uint32 getNoFramesInChunk(uint32 streamIndex, uint32 pFrameNo);
|
||||
uint32 getFirstFrameInChunk(uint32 streamIndex, uint32 pChunkID);
|
||||
|
||||
uint64 getOffsetForFrame(uint32 stream_index, uint32 pFrameNo);
|
||||
uint32 getChunkSize(uint32 stream_index, uint32 pFrameNo);
|
||||
bool IsKeyFrame(uint32 stream_index, uint32 pFrameNo);
|
||||
uint64 getOffsetForFrame(uint32 streamIndex, uint32 pFrameNo);
|
||||
uint32 getChunkSize(uint32 streamIndex, uint32 pFrameNo);
|
||||
bool IsKeyFrame(uint32 streamIndex, uint32 pFrameNo);
|
||||
|
||||
status_t ParseFile();
|
||||
BPositionIO *Source() {return theStream;};
|
||||
|
||||
bool IsActive(uint32 stream_index);
|
||||
bool IsActive(uint32 streamIndex);
|
||||
|
||||
bool GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo, off_t *start, uint32 *size, bool *keyframe);
|
||||
bool GetNextChunkInfo(uint32 streamIndex, uint32 pFrameNo, off_t *start, uint32 *size, bool *keyframe);
|
||||
|
||||
// Return all Audio Meta Data
|
||||
const AudioMetaData *AudioFormat(uint32 stream_index, size_t *size = 0);
|
||||
const AudioMetaData *AudioFormat(uint32 streamIndex, size_t *size = 0);
|
||||
// Return all Video Meta Data
|
||||
const VideoMetaData *VideoFormat(uint32 stream_index);
|
||||
const VideoMetaData *VideoFormat(uint32 streamIndex);
|
||||
|
||||
// XXX these need work
|
||||
const mp4_main_header *MovMainHeader();
|
||||
const mp4_stream_header *StreamFormat(uint32 stream_index);
|
||||
const mp4_stream_header *StreamFormat(uint32 streamIndex);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -209,7 +209,7 @@ void MOOVAtom::OnProcessMetaData()
|
|||
|
||||
char *MOOVAtom::OnGetAtomName()
|
||||
{
|
||||
return "Quicktime Movie";
|
||||
return "MPEG-4 Movie";
|
||||
}
|
||||
|
||||
CMOVAtom::CMOVAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomContainer(pStream, pstreamOffset, patomType, patomSize)
|
||||
|
@ -322,7 +322,7 @@ void CMOVAtom::OnChildProcessingComplete()
|
|||
|
||||
char *CMOVAtom::OnGetAtomName()
|
||||
{
|
||||
return "Compressed Quicktime Movie";
|
||||
return "Compressed MPEG-4 Movie";
|
||||
}
|
||||
|
||||
DCOMAtom::DCOMAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||
|
@ -438,7 +438,7 @@ void MVHDAtom::OnProcessMetaData()
|
|||
|
||||
char *MVHDAtom::OnGetAtomName()
|
||||
{
|
||||
return "Quicktime Movie Header";
|
||||
return "MPEG-4 Movie Header";
|
||||
}
|
||||
|
||||
MVHDAtom *MOOVAtom::getMVHDAtom()
|
||||
|
@ -908,7 +908,7 @@ uint64 STCOAtom::getOffsetForChunk(uint32 pChunkID)
|
|||
return 0LL;
|
||||
}
|
||||
|
||||
ESDSAtom::ESDSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||
ESDSAtom::ESDSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize)
|
||||
{
|
||||
theVOL = NULL;
|
||||
}
|
||||
|
@ -920,15 +920,116 @@ ESDSAtom::~ESDSAtom()
|
|||
}
|
||||
}
|
||||
|
||||
void ESDSAtom::OnProcessMetaData()
|
||||
{
|
||||
theVOL = (uint8 *)(malloc(getBytesRemaining()));
|
||||
Read(theVOL,getBytesRemaining());
|
||||
bool ESDSAtom::SkipTag(uint8 Tag, uint32 *offset) {
|
||||
uint8 byte;
|
||||
|
||||
byte = theVOL[(*offset)++];
|
||||
if (byte == Tag) {
|
||||
uint8 numBytes = 0;
|
||||
unsigned int length = 0;
|
||||
|
||||
do {
|
||||
byte = theVOL[(*offset)++];
|
||||
numBytes++;
|
||||
length = (length << 7) | (byte & 0x7F);
|
||||
} while ((byte & 0x80) && numBytes < 4);
|
||||
|
||||
} else {
|
||||
// go back Tag not found
|
||||
(*offset)--;
|
||||
printf("No Tag %d\n",Tag);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8 *ESDSAtom::getVOL()
|
||||
void ESDSAtom::OnProcessMetaData()
|
||||
{
|
||||
return theVOL;
|
||||
FullAtom::OnProcessMetaData();
|
||||
|
||||
VOLSize = getBytesRemaining();
|
||||
uint32 offset = 0;
|
||||
|
||||
theVOL = (uint8 *)(malloc(VOLSize));
|
||||
Read(theVOL,VOLSize);
|
||||
|
||||
// Display the VOL
|
||||
if (VOLSize > 0) {
|
||||
if (SkipTag(0x03,&offset)) {
|
||||
offset += 3;
|
||||
} else {
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
if (SkipTag(0x04,&offset)) {
|
||||
printf("type id is %d", theVOL[offset]);
|
||||
switch (theVOL[offset]) {
|
||||
case 1: printf("system v1"); break;
|
||||
case 2: printf("system v2"); break;
|
||||
case 32: printf("MPEG-4 video"); break;
|
||||
case 33: printf("MPEG-4 AVC SPS"); break;
|
||||
case 34: printf("MPEG-4 AVC PPS"); break;
|
||||
case 64: printf("MPEG-4 audio"); break;
|
||||
}
|
||||
|
||||
offset+=2;
|
||||
|
||||
uint32 a,b,c;
|
||||
uint32 buff;
|
||||
|
||||
a = theVOL[offset];
|
||||
b = theVOL[offset+1];
|
||||
c = theVOL[offset+2];
|
||||
|
||||
buff = (a << 16) | (b << 8) | c;
|
||||
|
||||
printf(" buf size %ld ",buff);
|
||||
printf(" max bit rate %ld",uint32(theVOL[offset+4]));
|
||||
printf(" avg bit rate %ld\n",uint32(theVOL[offset+8]));
|
||||
}
|
||||
} else {
|
||||
printf("VOL size is 0\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
size_t ESDSAtom::getVOLSize(bool forAudio)
|
||||
{
|
||||
uint32 offset = 0;
|
||||
if (forAudio) {
|
||||
if (SkipTag(0x03,&offset)) {
|
||||
offset += 3;
|
||||
} else {
|
||||
offset += 2;
|
||||
}
|
||||
if (SkipTag(0x04,&offset)) {
|
||||
offset += 13;
|
||||
}
|
||||
|
||||
SkipTag(0x05,&offset);
|
||||
}
|
||||
|
||||
return ( VOLSize - offset);
|
||||
}
|
||||
|
||||
uint8 *ESDSAtom::getVOL(bool forAudio)
|
||||
{
|
||||
uint32 offset = 0;
|
||||
if (forAudio) {
|
||||
if (SkipTag(0x03,&offset)) {
|
||||
offset += 3;
|
||||
} else {
|
||||
offset += 2;
|
||||
}
|
||||
if (SkipTag(0x04,&offset)) {
|
||||
offset += 13;
|
||||
}
|
||||
|
||||
SkipTag(0x05,&offset);
|
||||
}
|
||||
|
||||
return &theVOL[offset];
|
||||
}
|
||||
|
||||
char *ESDSAtom::OnGetAtomName()
|
||||
|
@ -961,7 +1062,7 @@ uint32 STSDAtom::getMediaHandlerType()
|
|||
return dynamic_cast<STBLAtom *>(getParent())->getMediaHandlerType();
|
||||
}
|
||||
|
||||
void STSDAtom::ReadESDS(uint8 **VOL, size_t *VOLSize)
|
||||
void STSDAtom::ReadESDS(uint8 **VOL, size_t *VOLSize, bool forAudio)
|
||||
{
|
||||
// Check for a esds and if it exists read it into the VOL buffer
|
||||
// MPEG-4 video/audio use the esds to store the VOL (STUPID COMMITTEE IDEA)
|
||||
|
@ -976,9 +1077,9 @@ void STSDAtom::ReadESDS(uint8 **VOL, size_t *VOLSize)
|
|||
|
||||
if (dynamic_cast<ESDSAtom *>(aAtomBase)) {
|
||||
// ESDS atom good
|
||||
*VOLSize = aAtomBase->getDataSize();
|
||||
*VOLSize = dynamic_cast<ESDSAtom *>(aAtomBase)->getVOLSize(forAudio);
|
||||
*VOL = (uint8 *)(malloc(*VOLSize));
|
||||
memcpy(*VOL,dynamic_cast<ESDSAtom *>(aAtomBase)->getVOL(),*VOLSize);
|
||||
memcpy(*VOL,dynamic_cast<ESDSAtom *>(aAtomBase)->getVOL(forAudio),*VOLSize);
|
||||
|
||||
delete aAtomBase;
|
||||
} else {
|
||||
|
@ -997,8 +1098,8 @@ void STSDAtom::ReadSoundDescription()
|
|||
Read(&theAudioDescription.theAudioSampleEntry.pre_defined);
|
||||
Read(&theAudioDescription.theAudioSampleEntry.reserved);
|
||||
Read(&theAudioDescription.theAudioSampleEntry.SampleRate);
|
||||
|
||||
ReadESDS(&theAudioDescription.theVOL,&theAudioDescription.VOLSize);
|
||||
|
||||
ReadESDS(&theAudioDescription.theVOL,&theAudioDescription.VOLSize,true);
|
||||
}
|
||||
|
||||
void STSDAtom::ReadVideoDescription()
|
||||
|
@ -1028,7 +1129,7 @@ void STSDAtom::ReadVideoDescription()
|
|||
Read(&theVideoDescription.theVideoSampleEntry.Depth);
|
||||
Read(&theVideoDescription.theVideoSampleEntry.pre_defined3);
|
||||
|
||||
ReadESDS(&theVideoDescription.theVOL,&theVideoDescription.VOLSize);
|
||||
ReadESDS(&theVideoDescription.theVOL,&theVideoDescription.VOLSize, false);
|
||||
}
|
||||
|
||||
void STSDAtom::OnProcessMetaData()
|
||||
|
@ -1253,7 +1354,7 @@ void MINFAtom::OnProcessMetaData()
|
|||
|
||||
char *MINFAtom::OnGetAtomName()
|
||||
{
|
||||
return "Quicktime Media Information Atom";
|
||||
return "MPEG-4 Media Information Atom";
|
||||
}
|
||||
|
||||
uint32 MINFAtom::getMediaHandlerType()
|
||||
|
@ -1275,7 +1376,7 @@ void STBLAtom::OnProcessMetaData()
|
|||
|
||||
char *STBLAtom::OnGetAtomName()
|
||||
{
|
||||
return "Quicktime Sample Table Atom";
|
||||
return "MPEG-4 Sample Table Atom";
|
||||
}
|
||||
|
||||
uint32 STBLAtom::getMediaHandlerType()
|
||||
|
@ -1297,7 +1398,7 @@ void DINFAtom::OnProcessMetaData()
|
|||
|
||||
char *DINFAtom::OnGetAtomName()
|
||||
{
|
||||
return "Quicktime Data Information Atom";
|
||||
return "MPEG-4 Data Information Atom";
|
||||
}
|
||||
|
||||
TKHDAtom::TKHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize)
|
||||
|
@ -1371,7 +1472,7 @@ void TKHDAtom::OnProcessMetaData()
|
|||
|
||||
char *TKHDAtom::OnGetAtomName()
|
||||
{
|
||||
return "Quicktime Track Header";
|
||||
return "MPEG-4 Track Header";
|
||||
}
|
||||
|
||||
MDIAAtom::MDIAAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomContainer(pStream, pstreamOffset, patomType, patomSize)
|
||||
|
@ -1388,7 +1489,7 @@ void MDIAAtom::OnProcessMetaData()
|
|||
|
||||
char *MDIAAtom::OnGetAtomName()
|
||||
{
|
||||
return "Quicktime Media Atom";
|
||||
return "MPEG-4 Media Atom";
|
||||
}
|
||||
|
||||
uint32 MDIAAtom::getMediaHandlerType()
|
||||
|
@ -1443,7 +1544,7 @@ void MDHDAtom::OnProcessMetaData()
|
|||
|
||||
char *MDHDAtom::OnGetAtomName()
|
||||
{
|
||||
return "Quicktime Media Header";
|
||||
return "MPEG-4 Media Header";
|
||||
}
|
||||
|
||||
bigtime_t MDHDAtom::getDuration()
|
||||
|
@ -1486,7 +1587,7 @@ void HDLRAtom::OnProcessMetaData()
|
|||
char *HDLRAtom::OnGetAtomName()
|
||||
{
|
||||
printf("%s %s:",(char *)&(theHeader.handler_type),name);
|
||||
return "Quicktime Handler Reference Atom ";
|
||||
return "MPEG-4 Handler Reference Atom ";
|
||||
}
|
||||
|
||||
bool HDLRAtom::IsVideoHandler()
|
||||
|
@ -1524,7 +1625,7 @@ void VMHDAtom::OnProcessMetaData()
|
|||
|
||||
char *VMHDAtom::OnGetAtomName()
|
||||
{
|
||||
return "Quicktime Video Media Header";
|
||||
return "MPEG-4 Video Media Header";
|
||||
}
|
||||
|
||||
SMHDAtom::SMHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize)
|
||||
|
@ -1545,5 +1646,5 @@ void SMHDAtom::OnProcessMetaData()
|
|||
|
||||
char *SMHDAtom::OnGetAtomName()
|
||||
{
|
||||
return "Quicktime Sound Media Header";
|
||||
return "MPEG-4 Sound Media Header";
|
||||
}
|
||||
|
|
|
@ -300,16 +300,19 @@ public:
|
|||
off_t getEOF();
|
||||
};
|
||||
|
||||
class ESDSAtom : public AtomBase {
|
||||
class ESDSAtom : public FullAtom {
|
||||
public:
|
||||
ESDSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~ESDSAtom();
|
||||
void OnProcessMetaData();
|
||||
char *OnGetAtomName();
|
||||
|
||||
uint8 *getVOL();
|
||||
uint8 *getVOL(bool forAudio);
|
||||
size_t getVOLSize(bool forAudio);
|
||||
private:
|
||||
bool SkipTag(uint8 Tag, uint32 *offset);
|
||||
uint8 *theVOL;
|
||||
size_t VOLSize;
|
||||
};
|
||||
|
||||
// Atom class for reading the sdst atom
|
||||
|
@ -326,7 +329,7 @@ public:
|
|||
private:
|
||||
uint32 getMediaHandlerType();
|
||||
|
||||
void ReadESDS(uint8 **VOL, size_t *VOLSize);
|
||||
void ReadESDS(uint8 **VOL, size_t *VOLSize, bool forAudio);
|
||||
void ReadSoundDescription();
|
||||
void ReadVideoDescription();
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ void TRAKAtom::OnProcessMetaData()
|
|||
|
||||
char *TRAKAtom::OnGetAtomName()
|
||||
{
|
||||
return "Quicktime Track Atom";
|
||||
return "MPEG-4 Track Atom";
|
||||
}
|
||||
|
||||
TKHDAtom *TRAKAtom::getTKHDAtom()
|
||||
|
|
|
@ -421,31 +421,56 @@ mp4Reader::AllocateCookie(int32 streamNumber, void **_cookie)
|
|||
format->user_data_type = B_CODEC_TYPE_INFO;
|
||||
*(uint32 *)format->user_data = description.u.quicktime.codec; format->user_data[4] = 0;
|
||||
|
||||
format->u.encoded_video.max_bit_rate = 8 * theFileReader->MovMainHeader()->max_bytes_per_sec;
|
||||
format->u.encoded_video.avg_bit_rate = format->u.encoded_video.max_bit_rate / 2; // XXX fix this
|
||||
// format->u.encoded_video.max_bit_rate = 8 * theFileReader->MovMainHeader()->max_bytes_per_sec;
|
||||
// format->u.encoded_video.avg_bit_rate = format->u.encoded_video.max_bit_rate / 2; // XXX fix this
|
||||
format->u.encoded_video.output.field_rate = cookie->frames_per_sec_rate / (float)cookie->frames_per_sec_scale;
|
||||
format->u.encoded_video.output.interlace = 1; // 1: progressive
|
||||
format->u.encoded_video.output.first_active = 0;
|
||||
format->u.encoded_video.output.last_active = cookie->line_count - 1;
|
||||
format->u.encoded_video.output.orientation = B_VIDEO_TOP_LEFT_RIGHT;
|
||||
format->u.encoded_video.output.pixel_width_aspect = 1;
|
||||
format->u.encoded_video.output.pixel_height_aspect = 1;
|
||||
// format->u.encoded_video.output.display.format = 0;
|
||||
format->u.encoded_video.output.display.line_width = theFileReader->MovMainHeader()->width;
|
||||
format->u.encoded_video.output.display.line_count = cookie->line_count;
|
||||
format->u.encoded_video.output.display.bytes_per_row = 0; // format->u.encoded_video.output.display.line_width * 4;
|
||||
|
||||
format->u.encoded_video.avg_bit_rate = 1;
|
||||
format->u.encoded_video.max_bit_rate = 1;
|
||||
|
||||
format->u.encoded_video.frame_size = video_format->width * video_format->height * video_format->planes / 8;
|
||||
format->u.encoded_video.output.display.bytes_per_row = video_format->planes / 8 * video_format->width;
|
||||
// align to 2 bytes
|
||||
format->u.encoded_video.output.display.bytes_per_row += format->u.encoded_video.output.display.bytes_per_row & 1;
|
||||
|
||||
switch (video_format->planes) {
|
||||
case 16:
|
||||
format->u.encoded_video.output.display.format = B_RGB15_BIG;
|
||||
break;
|
||||
case 24:
|
||||
format->u.encoded_video.output.display.format = B_RGB24_BIG;
|
||||
break;
|
||||
case 32:
|
||||
format->u.encoded_video.output.display.format = B_RGB32_BIG;
|
||||
break;
|
||||
default:
|
||||
format->u.encoded_video.output.display.format = B_NO_COLOR_SPACE;
|
||||
format->u.encoded_video.frame_size = video_format->width * video_format->height * 8 / 8;
|
||||
}
|
||||
|
||||
format->u.encoded_video.output.display.line_width = video_format->width;
|
||||
format->u.encoded_video.output.display.line_count = video_format->height;
|
||||
format->u.encoded_video.output.display.pixel_offset = 0;
|
||||
format->u.encoded_video.output.display.line_offset = 0;
|
||||
format->u.encoded_video.output.display.flags = 0;
|
||||
format->u.encoded_video.output.interlace = 1; // 1: progressive
|
||||
format->u.encoded_video.output.first_active = 0;
|
||||
format->u.encoded_video.output.last_active = format->u.encoded_video.output.display.line_count - 1;
|
||||
format->u.encoded_video.output.orientation = B_VIDEO_TOP_LEFT_RIGHT;
|
||||
format->u.encoded_video.output.pixel_width_aspect = 1;
|
||||
format->u.encoded_video.output.pixel_height_aspect = 1;
|
||||
|
||||
TRACE("max_bit_rate %.3f\n", format->u.encoded_video.max_bit_rate);
|
||||
TRACE("field_rate %.3f\n", format->u.encoded_video.output.field_rate);
|
||||
|
||||
// Set the VOL
|
||||
if (video_format->VOLSize > 0) {
|
||||
TRACE("VOL Found Size is %ld\n",video_format->VOLSize);
|
||||
size_t size = video_format->VOLSize;
|
||||
const void *data = video_format->theVOL;
|
||||
format->SetMetaData(data, size);
|
||||
if (format->SetMetaData(data, size) != B_OK) {
|
||||
printf("Failed to set VOL\n %d %d",(16 << 20),32000);
|
||||
}
|
||||
|
||||
#ifdef TRACE_MP4_READER
|
||||
if (data) {
|
||||
|
@ -485,8 +510,17 @@ mp4Reader::GetStreamInfo(void *_cookie, int64 *frameCount, bigtime_t *duration,
|
|||
*frameCount = cookie->frame_count;
|
||||
*duration = cookie->duration;
|
||||
*format = cookie->format;
|
||||
*infoBuffer = 0;
|
||||
*infoSize = 0;
|
||||
|
||||
// Copy metadata to infoBuffer
|
||||
if (theFileReader->IsVideo(cookie->stream)) {
|
||||
const VideoMetaData *video_format = theFileReader->VideoFormat(cookie->stream);
|
||||
*infoBuffer = video_format->theVOL;
|
||||
*infoSize = video_format->VOLSize;
|
||||
} else {
|
||||
const AudioMetaData *audio_format = theFileReader->AudioFormat(cookie->stream);
|
||||
*infoBuffer = audio_format->theVOL;
|
||||
*infoSize = audio_format->VOLSize;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
@ -578,6 +612,8 @@ mp4Reader::GetNextChunk(void *_cookie, const void **chunkBuffer,
|
|||
mediaHeader->u.encoded_video.field_flags = keyframe ? B_MEDIA_KEY_FRAME : 0;
|
||||
mediaHeader->u.encoded_video.first_active_line = 0;
|
||||
mediaHeader->u.encoded_video.line_count = cookie->line_count;
|
||||
mediaHeader->u.encoded_video.field_number = 0;
|
||||
mediaHeader->u.encoded_video.field_sequence = cookie->frame_pos;
|
||||
|
||||
cookie->frame_pos++;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue