Performance improvements to mov_reader
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13209 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -231,35 +231,39 @@ bool MOVFileReader::IsAudio(uint32 stream_index)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 MOVFileReader::getFirstFrameInChunk(uint32 stream_index, uint32 pChunkID)
|
||||||
|
{
|
||||||
|
// Find Track
|
||||||
|
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||||
|
if (aAtomBase) {
|
||||||
|
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||||
|
|
||||||
|
return aTrakAtom->getFirstSampleInChunk(pChunkID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint32 MOVFileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo)
|
uint32 MOVFileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo)
|
||||||
{
|
{
|
||||||
// Find Track
|
// Find Track
|
||||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||||
if (aAtomBase) {
|
if (aAtomBase) {
|
||||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||||
|
uint32 ChunkNo = 1;
|
||||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
|
||||||
|
|
||||||
if (IsAudio(stream_index)) {
|
if (IsAudio(stream_index)) {
|
||||||
uint32 OffsetInChunk;
|
ChunkNo = pFrameNo;
|
||||||
uint32 ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
|
|
||||||
|
|
||||||
// Go back to first Sample in Chunk
|
|
||||||
while (aTrakAtom->getChunkForSample(SampleNo-1, &OffsetInChunk) == ChunkNo) {
|
|
||||||
SampleNo--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add up all sample sizes in chunk
|
|
||||||
while (aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk) == ChunkNo) {
|
|
||||||
SampleNo++;
|
|
||||||
}
|
|
||||||
return SampleNo ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsVideo(stream_index)) {
|
if (IsVideo(stream_index)) {
|
||||||
return 1;
|
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
||||||
|
|
||||||
|
uint32 OffsetInChunk;
|
||||||
|
ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return aTrakAtom->getNoSamplesInChunk(ChunkNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -267,54 +271,47 @@ uint32 MOVFileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo)
|
|||||||
|
|
||||||
uint64 MOVFileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo)
|
uint64 MOVFileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo)
|
||||||
{
|
{
|
||||||
// BStopWatch *watch;
|
|
||||||
|
|
||||||
// Find Track
|
// Find Track
|
||||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||||
if (aAtomBase) {
|
if (aAtomBase) {
|
||||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||||
|
|
||||||
if (pFrameNo < aTrakAtom->FrameCount()) {
|
if (IsAudio(stream_index)) {
|
||||||
// Convert Frame to Track Time
|
// FrameNo is really chunk No for audio
|
||||||
// uint32 FrameTime = aTrakAtom->getTimeForFrame(pFrameNo, getMovieTimeScale());
|
uint32 ChunkNo = pFrameNo;
|
||||||
// Get Sample for Frame
|
|
||||||
// watch = new BStopWatch("getSampleForFrame");
|
|
||||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
|
||||||
// delete watch;
|
|
||||||
// Get Chunk For Sample and the offset for the frame within that chunk
|
|
||||||
// watch = new BStopWatch("getChunkForSample");
|
|
||||||
uint32 OffsetInChunk;
|
|
||||||
uint32 ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
|
|
||||||
// delete watch;
|
|
||||||
// Get Offset For Chunk
|
|
||||||
// printf("Stream: %ld Frame %ld %ld <%ld/%ld> (",stream_index, pFrameNo, SampleNo, ChunkNo, OffsetInChunk);
|
|
||||||
// watch = new BStopWatch("getOffsetForChunk");
|
|
||||||
uint64 OffsetNo = aTrakAtom->getOffsetForChunk(ChunkNo);
|
|
||||||
// delete watch;
|
|
||||||
// printf("Frame %ld {%lld} <%ld/%ld> (",pFrameNo, OffsetNo, ChunkNo, OffsetInChunk);
|
|
||||||
|
|
||||||
if (ChunkNo != 0) {
|
// Get Offset For Chunk
|
||||||
uint32 SampleSize;
|
return aTrakAtom->getOffsetForChunk(ChunkNo);
|
||||||
// Adjust the Offset for the Offset in the chunk
|
}
|
||||||
// watch = new BStopWatch("getSizeForSample");
|
|
||||||
if (aTrakAtom->IsSingleSampleSize()) {
|
if (IsVideo(stream_index)) {
|
||||||
SampleSize = aTrakAtom->getSizeForSample(SampleNo);
|
|
||||||
OffsetNo = OffsetNo + (OffsetInChunk * SampleSize);
|
if (pFrameNo < aTrakAtom->FrameCount()) {
|
||||||
} else {
|
// Get Sample for Frame
|
||||||
// This is bad news performance wise
|
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
||||||
for (uint32 i=1;i<=OffsetInChunk;i++) {
|
// Get Chunk For Sample and the offset for the frame within that chunk
|
||||||
SampleSize = aTrakAtom->getSizeForSample(SampleNo-i);
|
uint32 OffsetInChunk;
|
||||||
// printf(" %ld ",SampleSize);
|
uint32 ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
|
||||||
OffsetNo = OffsetNo + SampleSize;
|
// Get Offset For Chunk
|
||||||
|
uint64 OffsetNo = aTrakAtom->getOffsetForChunk(ChunkNo);
|
||||||
|
|
||||||
|
if (ChunkNo != 0) {
|
||||||
|
uint32 SampleSize;
|
||||||
|
// Adjust the Offset for the Offset in the chunk
|
||||||
|
if (aTrakAtom->IsSingleSampleSize()) {
|
||||||
|
SampleSize = aTrakAtom->getSizeForSample(SampleNo);
|
||||||
|
OffsetNo = OffsetNo + (OffsetInChunk * SampleSize);
|
||||||
|
} else {
|
||||||
|
// This is bad news performance wise
|
||||||
|
for (uint32 i=1;i<=OffsetInChunk;i++) {
|
||||||
|
SampleSize = aTrakAtom->getSizeForSample(SampleNo-i);
|
||||||
|
OffsetNo = OffsetNo + SampleSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// printf(") %lld\n",OffsetNo);
|
|
||||||
// delete watch;
|
|
||||||
}
|
|
||||||
// printf("%ld:%ld:%ld:%lld\n",pFrameNo, SampleNo, ChunkNo, OffsetNo);
|
|
||||||
// printf("\n");
|
|
||||||
|
|
||||||
return OffsetNo;
|
return OffsetNo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,33 +492,32 @@ uint32 MOVFileReader::getChunkSize(uint32 stream_index, uint32 pFrameNo)
|
|||||||
if (aAtomBase) {
|
if (aAtomBase) {
|
||||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||||
|
|
||||||
if (pFrameNo < aTrakAtom->FrameCount()) {
|
if (IsAudio(stream_index)) {
|
||||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
|
||||||
|
|
||||||
if (IsAudio(stream_index)) {
|
// We read audio in chunk by chunk so chunk size is chunk size
|
||||||
uint32 OffsetInChunk;
|
uint32 ChunkNo = pFrameNo;
|
||||||
uint32 ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
|
|
||||||
|
|
||||||
// Go back to first Sample in Chunk
|
|
||||||
while (aTrakAtom->getChunkForSample(SampleNo-1, &OffsetInChunk) == ChunkNo) {
|
|
||||||
SampleNo--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add up all sample sizes in chunk
|
|
||||||
uint32 ChunkSize = 0;
|
|
||||||
|
|
||||||
while (aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk) == ChunkNo) {
|
// Get first sample in chunk
|
||||||
ChunkSize += aTrakAtom->getSizeForSample(SampleNo);
|
uint32 SampleNo = aTrakAtom->getFirstSampleInChunk(ChunkNo);
|
||||||
SampleNo++;
|
|
||||||
}
|
// Add up all sample sizes in chunk
|
||||||
return ChunkSize;
|
uint32 ChunkSize = 0;
|
||||||
|
for (uint32 i=0;i<aTrakAtom->getNoSamplesInChunk(ChunkNo);i++) {
|
||||||
|
ChunkSize += aTrakAtom->getSizeForSample(SampleNo);
|
||||||
|
SampleNo++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ChunkSize;
|
||||||
|
}
|
||||||
|
|
||||||
if (IsVideo(stream_index)) {
|
if (IsVideo(stream_index)) {
|
||||||
|
if (pFrameNo < aTrakAtom->FrameCount()) {
|
||||||
|
// We read video in Sample by Sample so chunk size is Sample Size
|
||||||
|
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
||||||
return aTrakAtom->getSizeForSample(SampleNo);
|
return aTrakAtom->getSizeForSample(SampleNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -550,9 +546,7 @@ bool MOVFileReader::GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo, off_t
|
|||||||
*keyframe = IsKeyFrame(stream_index, pFrameNo);
|
*keyframe = IsKeyFrame(stream_index, pFrameNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ((*start > 0) && (*size > 0));
|
return ((*start > 0) && (*size > 0) && !(IsEndOfFile(*start)));
|
||||||
|
|
||||||
// return !(IsEndOfFile(*start) || *start < 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ public:
|
|||||||
bool IsAudio(uint32 stream_index);
|
bool IsAudio(uint32 stream_index);
|
||||||
|
|
||||||
uint32 getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo);
|
uint32 getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo);
|
||||||
|
uint32 getFirstFrameInChunk(uint32 stream_index, uint32 pChunkID);
|
||||||
|
|
||||||
uint64 getOffsetForFrame(uint32 stream_index, uint32 pFrameNo);
|
uint64 getOffsetForFrame(uint32 stream_index, uint32 pFrameNo);
|
||||||
uint32 getChunkSize(uint32 stream_index, uint32 pFrameNo);
|
uint32 getChunkSize(uint32 stream_index, uint32 pFrameNo);
|
||||||
|
|||||||
@@ -528,6 +528,7 @@ SampleToChunk *aSampleToChunk;
|
|||||||
}
|
}
|
||||||
|
|
||||||
theSampleToChunkArray[i] = aSampleToChunk;
|
theSampleToChunkArray[i] = aSampleToChunk;
|
||||||
|
// printf("%ld/%ld/%ld\n",aSampleToChunk->FirstChunk,aSampleToChunk->SamplesPerChunk,aSampleToChunk->TotalPrevFrames);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,6 +537,30 @@ char *STSCAtom::OnGetAtomName()
|
|||||||
return "Sample to Chunk Atom";
|
return "Sample to Chunk Atom";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 STSCAtom::getNoSamplesInChunk(uint32 pChunkID)
|
||||||
|
{
|
||||||
|
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
||||||
|
if (theSampleToChunkArray[i]->FirstChunk > pChunkID) {
|
||||||
|
return theSampleToChunkArray[i-1]->SamplesPerChunk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 STSCAtom::getFirstSampleInChunk(uint32 pChunkID)
|
||||||
|
{
|
||||||
|
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
||||||
|
if (theSampleToChunkArray[i]->FirstChunk > pChunkID) {
|
||||||
|
uint32 Diff = pChunkID - theSampleToChunkArray[i-1]->FirstChunk;
|
||||||
|
uint32 pSampleNo = (Diff * theSampleToChunkArray[i-1]->SamplesPerChunk) + theSampleToChunkArray[i-1]->TotalPrevFrames;
|
||||||
|
return pSampleNo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint32 STSCAtom::getChunkForSample(uint32 pSample, uint32 *pOffsetInChunk)
|
uint32 STSCAtom::getChunkForSample(uint32 pSample, uint32 *pOffsetInChunk)
|
||||||
{
|
{
|
||||||
uint32 ChunkID = 0;
|
uint32 ChunkID = 0;
|
||||||
|
|||||||
@@ -186,6 +186,8 @@ public:
|
|||||||
char *OnGetAtomName();
|
char *OnGetAtomName();
|
||||||
|
|
||||||
uint32 getChunkForSample(uint32 pSample, uint32 *pOffsetInChunk);
|
uint32 getChunkForSample(uint32 pSample, uint32 *pOffsetInChunk);
|
||||||
|
uint32 getFirstSampleInChunk(uint32 pChunkID);
|
||||||
|
uint32 getNoSamplesInChunk(uint32 pChunkID);
|
||||||
private:
|
private:
|
||||||
array_header theHeader;
|
array_header theHeader;
|
||||||
SampleToChunkArray theSampleToChunkArray;
|
SampleToChunkArray theSampleToChunkArray;
|
||||||
@@ -353,8 +355,10 @@ public:
|
|||||||
uint32 getSampleForTime(uint32 pTime);
|
uint32 getSampleForTime(uint32 pTime);
|
||||||
uint32 getSampleForFrame(uint32 pFrame);
|
uint32 getSampleForFrame(uint32 pFrame);
|
||||||
uint32 getChunkForSample(uint32 pSample, uint32 *pOffsetInChunk);
|
uint32 getChunkForSample(uint32 pSample, uint32 *pOffsetInChunk);
|
||||||
uint64 getOffsetForChunk(uint32 pChunk);
|
uint64 getOffsetForChunk(uint32 pChunkID);
|
||||||
|
uint32 getFirstSampleInChunk(uint32 pChunkID);
|
||||||
uint32 getSizeForSample(uint32 pSample);
|
uint32 getSizeForSample(uint32 pSample);
|
||||||
|
uint32 getNoSamplesInChunk(uint32 pChunkID);
|
||||||
bool IsSyncSample(uint32 pSampleNo);
|
bool IsSyncSample(uint32 pSampleNo);
|
||||||
bool IsSingleSampleSize();
|
bool IsSingleSampleSize();
|
||||||
|
|
||||||
|
|||||||
@@ -154,6 +154,17 @@ uint32 TRAKAtom::getChunkForSample(uint32 pSample, uint32 *pOffsetInChunk)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 TRAKAtom::getNoSamplesInChunk(uint32 pChunkID)
|
||||||
|
{
|
||||||
|
AtomBase *aAtomBase = GetChildAtom(uint32('stsc'),0);
|
||||||
|
|
||||||
|
if (aAtomBase) {
|
||||||
|
return (dynamic_cast<STSCAtom *>(aAtomBase))->getNoSamplesInChunk(pChunkID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint32 TRAKAtom::getSizeForSample(uint32 pSample)
|
uint32 TRAKAtom::getSizeForSample(uint32 pSample)
|
||||||
{
|
{
|
||||||
AtomBase *aAtomBase = GetChildAtom(uint32('stsz'),0);
|
AtomBase *aAtomBase = GetChildAtom(uint32('stsz'),0);
|
||||||
@@ -165,17 +176,29 @@ uint32 TRAKAtom::getSizeForSample(uint32 pSample)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 TRAKAtom::getOffsetForChunk(uint32 pChunk)
|
uint64 TRAKAtom::getOffsetForChunk(uint32 pChunkID)
|
||||||
{
|
{
|
||||||
AtomBase *aAtomBase = GetChildAtom(uint32('stco'),0);
|
AtomBase *aAtomBase = GetChildAtom(uint32('stco'),0);
|
||||||
|
|
||||||
if (aAtomBase) {
|
if (aAtomBase) {
|
||||||
return (dynamic_cast<STCOAtom *>(aAtomBase))->getOffsetForChunk(pChunk);
|
return (dynamic_cast<STCOAtom *>(aAtomBase))->getOffsetForChunk(pChunkID);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 TRAKAtom::getFirstSampleInChunk(uint32 pChunkID)
|
||||||
|
{
|
||||||
|
AtomBase *aAtomBase = GetChildAtom(uint32('stsc'),0);
|
||||||
|
|
||||||
|
if (aAtomBase) {
|
||||||
|
return (dynamic_cast<STSCAtom *>(aAtomBase))->getFirstSampleInChunk(pChunkID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TRAKAtom::IsSyncSample(uint32 pSampleNo)
|
bool TRAKAtom::IsSyncSample(uint32 pSampleNo)
|
||||||
{
|
{
|
||||||
AtomBase *aAtomBase = GetChildAtom(uint32('stss'),0);
|
AtomBase *aAtomBase = GetChildAtom(uint32('stss'),0);
|
||||||
|
|||||||
@@ -54,16 +54,19 @@ struct mov_cookie
|
|||||||
|
|
||||||
bool audio;
|
bool audio;
|
||||||
|
|
||||||
// audio only:
|
// audio only:
|
||||||
int64 byte_pos;
|
off_t byte_pos;
|
||||||
|
uint32 chunk_pos;
|
||||||
uint32 bytes_per_sec_rate;
|
uint32 bytes_per_sec_rate;
|
||||||
uint32 bytes_per_sec_scale;
|
uint32 bytes_per_sec_scale;
|
||||||
|
|
||||||
// video only:
|
// video only:
|
||||||
|
uint32 line_count;
|
||||||
|
|
||||||
|
// Common
|
||||||
uint32 frame_pos;
|
uint32 frame_pos;
|
||||||
uint32 frames_per_sec_rate;
|
uint32 frames_per_sec_rate;
|
||||||
uint32 frames_per_sec_scale;
|
uint32 frames_per_sec_scale;
|
||||||
uint32 line_count;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -138,6 +141,7 @@ movReader::AllocateCookie(int32 streamNumber, void **_cookie)
|
|||||||
cookie->stream = streamNumber;
|
cookie->stream = streamNumber;
|
||||||
cookie->buffer = 0;
|
cookie->buffer = 0;
|
||||||
cookie->buffer_size = 0;
|
cookie->buffer_size = 0;
|
||||||
|
cookie->frame_pos = 0;
|
||||||
|
|
||||||
BMediaFormats formats;
|
BMediaFormats formats;
|
||||||
media_format *format = &cookie->format;
|
media_format *format = &cookie->format;
|
||||||
@@ -188,10 +192,10 @@ movReader::AllocateCookie(int32 streamNumber, void **_cookie)
|
|||||||
*/
|
*/
|
||||||
cookie->audio = true;
|
cookie->audio = true;
|
||||||
cookie->byte_pos = 0;
|
cookie->byte_pos = 0;
|
||||||
cookie->frame_pos = 0;
|
cookie->chunk_pos = 1;
|
||||||
|
|
||||||
if (stream_header->scale && stream_header->rate && stream_header->sample_size) {
|
if (stream_header->scale && stream_header->rate && stream_header->sample_size) {
|
||||||
cookie->bytes_per_sec_rate = stream_header->rate * stream_header->sample_size;
|
cookie->bytes_per_sec_rate = stream_header->rate * stream_header->sample_size * audio_format->NoOfChannels / 8;
|
||||||
cookie->bytes_per_sec_scale = stream_header->scale;
|
cookie->bytes_per_sec_scale = stream_header->scale;
|
||||||
cookie->frames_per_sec_rate = stream_header->rate;
|
cookie->frames_per_sec_rate = stream_header->rate;
|
||||||
cookie->frames_per_sec_scale = stream_header->scale;
|
cookie->frames_per_sec_scale = stream_header->scale;
|
||||||
@@ -202,9 +206,11 @@ movReader::AllocateCookie(int32 streamNumber, void **_cookie)
|
|||||||
cookie->frames_per_sec_rate = audio_format->SampleSize;
|
cookie->frames_per_sec_rate = audio_format->SampleSize;
|
||||||
cookie->frames_per_sec_scale = 1;
|
cookie->frames_per_sec_scale = 1;
|
||||||
TRACE("bytes_per_sec_rate %ld, bytes_per_sec_scale %ld (using avg_bytes_per_sec)\n", cookie->bytes_per_sec_rate, cookie->bytes_per_sec_scale);
|
TRACE("bytes_per_sec_rate %ld, bytes_per_sec_scale %ld (using avg_bytes_per_sec)\n", cookie->bytes_per_sec_rate, cookie->bytes_per_sec_scale);
|
||||||
} else if (stream_header->rate) {
|
} else if (stream_header->rate && stream_header->sample_size) {
|
||||||
cookie->bytes_per_sec_rate = stream_header->rate;
|
cookie->bytes_per_sec_rate = stream_header->rate * stream_header->sample_size * audio_format->NoOfChannels / 8;
|
||||||
cookie->bytes_per_sec_scale = 1;
|
cookie->bytes_per_sec_scale = 1;
|
||||||
|
cookie->frames_per_sec_rate = stream_header->sample_size;
|
||||||
|
cookie->frames_per_sec_scale = 1;
|
||||||
TRACE("bytes_per_sec_rate %ld, bytes_per_sec_scale %ld (using rate)\n", cookie->bytes_per_sec_rate, cookie->bytes_per_sec_scale);
|
TRACE("bytes_per_sec_rate %ld, bytes_per_sec_scale %ld (using rate)\n", cookie->bytes_per_sec_rate, cookie->bytes_per_sec_scale);
|
||||||
} else {
|
} else {
|
||||||
cookie->frames_per_sec_rate = 16000;
|
cookie->frames_per_sec_rate = 16000;
|
||||||
@@ -324,7 +330,6 @@ movReader::AllocateCookie(int32 streamNumber, void **_cookie)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cookie->audio = false;
|
cookie->audio = false;
|
||||||
cookie->frame_pos = 0;
|
|
||||||
cookie->line_count = theFileReader->MovMainHeader()->height;
|
cookie->line_count = theFileReader->MovMainHeader()->height;
|
||||||
|
|
||||||
if (stream_header->scale && stream_header->rate) {
|
if (stream_header->scale && stream_header->rate) {
|
||||||
@@ -458,8 +463,14 @@ movReader::GetNextChunk(void *_cookie,
|
|||||||
mov_cookie *cookie = (mov_cookie *)_cookie;
|
mov_cookie *cookie = (mov_cookie *)_cookie;
|
||||||
|
|
||||||
int64 start; uint32 size; bool keyframe;
|
int64 start; uint32 size; bool keyframe;
|
||||||
if (!theFileReader->GetNextChunkInfo(cookie->stream, cookie->frame_pos, &start, &size, &keyframe))
|
|
||||||
return B_LAST_BUFFER_ERROR;
|
if (cookie->audio) {
|
||||||
|
if (!theFileReader->GetNextChunkInfo(cookie->stream, cookie->chunk_pos, &start, &size, &keyframe))
|
||||||
|
return B_LAST_BUFFER_ERROR;
|
||||||
|
} else {
|
||||||
|
if (!theFileReader->GetNextChunkInfo(cookie->stream, cookie->frame_pos, &start, &size, &keyframe))
|
||||||
|
return B_LAST_BUFFER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (cookie->buffer_size < size) {
|
if (cookie->buffer_size < size) {
|
||||||
delete [] cookie->buffer;
|
delete [] cookie->buffer;
|
||||||
@@ -468,20 +479,22 @@ movReader::GetNextChunk(void *_cookie,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cookie->audio) {
|
if (cookie->audio) {
|
||||||
TRACE("Audio stream %d: frame %ld start %lld Size %ld key %d\n",cookie->stream, cookie->frame_pos, start, size, keyframe);
|
TRACE("Audio stream %d: chunk %ld expected start %lld Size %ld key %d\n",cookie->stream, cookie->chunk_pos, start, size, keyframe);
|
||||||
mediaHeader->start_time = (cookie->byte_pos * 1000000LL * (int64)cookie->bytes_per_sec_scale) / cookie->bytes_per_sec_rate;
|
|
||||||
mediaHeader->type = B_MEDIA_ENCODED_AUDIO;
|
mediaHeader->type = B_MEDIA_ENCODED_AUDIO;
|
||||||
mediaHeader->u.encoded_audio.buffer_flags = keyframe ? B_MEDIA_KEY_FRAME : 0;
|
mediaHeader->u.encoded_audio.buffer_flags = keyframe ? B_MEDIA_KEY_FRAME : 0;
|
||||||
|
|
||||||
|
// This will only work with raw audio I think.
|
||||||
|
mediaHeader->start_time = (cookie->byte_pos * 1000000L * cookie->bytes_per_sec_scale) / cookie->bytes_per_sec_rate;
|
||||||
|
TRACE("Audio - Frames in Chunk %ld / Actual Start Time %Ld using byte_pos\n",theFileReader->getNoFramesInChunk(cookie->stream,cookie->chunk_pos),mediaHeader->start_time);
|
||||||
|
|
||||||
// Should be frame_pos += frames per chunk
|
// We should find the current frame position (ie first frame in chunk) then compute using fps
|
||||||
|
cookie->frame_pos = theFileReader->getFirstFrameInChunk(cookie->stream,cookie->chunk_pos);
|
||||||
|
mediaHeader->start_time = (cookie->frame_pos * 1000000LL * (int64)cookie->frames_per_sec_scale) / cookie->frames_per_sec_rate;
|
||||||
|
TRACE("Audio - Frames in Chunk %ld / Actual Start Time %Ld using frame_no %ld\n",theFileReader->getNoFramesInChunk(cookie->stream,cookie->chunk_pos),mediaHeader->start_time, cookie->frame_pos);
|
||||||
|
|
||||||
cookie->byte_pos += size;
|
cookie->byte_pos += size;
|
||||||
if ((int64)cookie->frames_per_sec_scale > 0) {
|
// frame_pos is chunk No for audio
|
||||||
cookie->frame_pos = ((mediaHeader->start_time * cookie->frames_per_sec_rate) / (int64)cookie->frames_per_sec_scale) / 1000000LL;
|
cookie->chunk_pos++;
|
||||||
} else {
|
|
||||||
cookie->frame_pos = 0;
|
|
||||||
}
|
|
||||||
// cookie->frame_pos += theFileReader->getNoFramesInChunk(cookie->stream,cookie->frame_pos);
|
|
||||||
// cookie->frame_pos += 2205;
|
|
||||||
} else {
|
} else {
|
||||||
TRACE("Video stream %d: frame %ld start %lld Size %ld key %d\n",cookie->stream, cookie->frame_pos, start, size, keyframe);
|
TRACE("Video stream %d: frame %ld start %lld Size %ld key %d\n",cookie->stream, cookie->frame_pos, start, size, keyframe);
|
||||||
mediaHeader->start_time = (cookie->frame_pos * 1000000LL * (int64)cookie->frames_per_sec_scale) / cookie->frames_per_sec_rate;
|
mediaHeader->start_time = (cookie->frame_pos * 1000000LL * (int64)cookie->frames_per_sec_scale) / cookie->frames_per_sec_rate;
|
||||||
@@ -490,7 +503,7 @@ movReader::GetNextChunk(void *_cookie,
|
|||||||
mediaHeader->u.encoded_video.first_active_line = 0;
|
mediaHeader->u.encoded_video.first_active_line = 0;
|
||||||
mediaHeader->u.encoded_video.line_count = cookie->line_count;
|
mediaHeader->u.encoded_video.line_count = cookie->line_count;
|
||||||
|
|
||||||
cookie->frame_pos += 1;
|
cookie->frame_pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("stream %d: start_time %.6f\n", cookie->stream, mediaHeader->start_time / 1000000.0);
|
TRACE("stream %d: start_time %.6f\n", cookie->stream, mediaHeader->start_time / 1000000.0);
|
||||||
|
|||||||
Reference in New Issue
Block a user