fixes for start_time returned from vorbis/speex, makes nplay work better in seeking. I note that this also made MediaPlayer stop reporting a bunch of dropped frames at every seek.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6627 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -428,6 +428,8 @@ status_t
|
|||||||
OggSeekable::GetNextChunk(void **chunkBuffer, int32 *chunkSize,
|
OggSeekable::GetNextChunk(void **chunkBuffer, int32 *chunkSize,
|
||||||
media_header *mediaHeader)
|
media_header *mediaHeader)
|
||||||
{
|
{
|
||||||
|
mediaHeader->start_time = fCurrentTime;
|
||||||
|
mediaHeader->file_pos = fPosition;
|
||||||
status_t result = GetPacket(&fChunkPacket);
|
status_t result = GetPacket(&fChunkPacket);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
TRACE("OggSeekable::GetNextChunk failed: GetPacket = %s\n", strerror(result));
|
TRACE("OggSeekable::GetNextChunk failed: GetPacket = %s\n", strerror(result));
|
||||||
@@ -435,6 +437,8 @@ OggSeekable::GetNextChunk(void **chunkBuffer, int32 *chunkSize,
|
|||||||
}
|
}
|
||||||
*chunkBuffer = &fChunkPacket;
|
*chunkBuffer = &fChunkPacket;
|
||||||
*chunkSize = sizeof(fChunkPacket);
|
*chunkSize = sizeof(fChunkPacket);
|
||||||
|
fCurrentFrame++;
|
||||||
|
fCurrentTime = (bigtime_t)((fCurrentFrame * 1000000LL) / fFrameRate);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ OggSpeexSeekable::GetStreamInfo(int64 *frameCount, bigtime_t *duration,
|
|||||||
} else {
|
} else {
|
||||||
format->u.encoded_audio.multi_info.channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT;
|
format->u.encoded_audio.multi_info.channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT;
|
||||||
}
|
}
|
||||||
format->u.encoded_audio.output.frame_rate = header->rate;
|
fFrameRate = format->u.encoded_audio.output.frame_rate = header->rate;
|
||||||
format->u.encoded_audio.output.channel_count = header->nb_channels;
|
format->u.encoded_audio.output.channel_count = header->nb_channels;
|
||||||
// allocate buffer, round up to nearest speex output_length size
|
// allocate buffer, round up to nearest speex output_length size
|
||||||
int buffer_size = AudioBufferSize(&format->u.encoded_audio.output);
|
int buffer_size = AudioBufferSize(&format->u.encoded_audio.output);
|
||||||
@@ -144,29 +144,16 @@ OggSpeexSeekable::GetStreamInfo(int64 *frameCount, bigtime_t *duration,
|
|||||||
// TODO: count the frames in the first page.. somehow.. :-/
|
// TODO: count the frames in the first page.. somehow.. :-/
|
||||||
int64 frames = 0;
|
int64 frames = 0;
|
||||||
|
|
||||||
// seek back to the start
|
|
||||||
int64 frame = 0;
|
|
||||||
bigtime_t time = 0;
|
|
||||||
result = Seek(B_MEDIA_SEEK_TO_TIME, &frame, &time);
|
|
||||||
if (result != B_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ogg_page page;
|
ogg_page page;
|
||||||
// read the first page
|
// read the first page
|
||||||
result = ReadPage(&page);
|
result = ReadPage(&page);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
int64 first_granulepos = ogg_page_granulepos(&page);
|
int64 fFirstGranulepos = ogg_page_granulepos(&page);
|
||||||
if (first_granulepos < 0) {
|
TRACE("OggVorbisSeekable::GetStreamInfo: first granulepos: %lld\n", fFirstGranulepos);
|
||||||
// negative start granulepos indicates that we discard that many frames
|
|
||||||
frames -= first_granulepos;
|
|
||||||
first_granulepos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read our last page
|
// read our last page
|
||||||
off_t last = Seek(GetLastPagePosition(), SEEK_SET);
|
off_t last = inherited::Seek(GetLastPagePosition(), SEEK_SET);
|
||||||
if (last < 0) {
|
if (last < 0) {
|
||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
@@ -177,15 +164,18 @@ OggSpeexSeekable::GetStreamInfo(int64 *frameCount, bigtime_t *duration,
|
|||||||
int64 last_granulepos = ogg_page_granulepos(&page);
|
int64 last_granulepos = ogg_page_granulepos(&page);
|
||||||
|
|
||||||
// seek back to the start
|
// seek back to the start
|
||||||
|
int64 frame = 0;
|
||||||
|
bigtime_t time = 0;
|
||||||
result = Seek(B_MEDIA_SEEK_TO_TIME, &frame, &time);
|
result = Seek(B_MEDIA_SEEK_TO_TIME, &frame, &time);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute frame count and duration from sample count
|
// compute frame count and duration from sample count
|
||||||
frames += last_granulepos - first_granulepos;
|
frames = last_granulepos - fFirstGranulepos;
|
||||||
|
|
||||||
*frameCount = frames;
|
*frameCount = frames;
|
||||||
*duration = (1000000LL * frames) / (long long)format->u.encoded_audio.output.frame_rate;
|
*duration = (1000000LL * frames) / (long long)fFrameRate;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
namespace BPrivate { namespace media {
|
namespace BPrivate { namespace media {
|
||||||
|
|
||||||
class OggSpeexSeekable : public OggSeekable {
|
class OggSpeexSeekable : public OggSeekable {
|
||||||
|
private:
|
||||||
|
typedef OggSeekable inherited;
|
||||||
public:
|
public:
|
||||||
static bool IsValidHeader(const ogg_packet & packet);
|
static bool IsValidHeader(const ogg_packet & packet);
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -266,6 +266,7 @@ SpeexDecoder::Decode(void *buffer, int64 *frameCount,
|
|||||||
TRACE("SpeexDecoder::Decode: GetNextChunk failed\n");
|
TRACE("SpeexDecoder::Decode: GetNextChunk failed\n");
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
fStartTime = mh.start_time;
|
||||||
speex_bits_read_from(&fBits, (char*)chunkBuffer, chunkSize);
|
speex_bits_read_from(&fBits, (char*)chunkBuffer, chunkSize);
|
||||||
for (int frame = 0 ; frame < fHeader->frames_per_packet ; frame++) {
|
for (int frame = 0 ; frame < fHeader->frames_per_packet ; frame++) {
|
||||||
int ret = speex_decode(fDecoderState, &fBits, out_buffer);
|
int ret = speex_decode(fDecoderState, &fBits, out_buffer);
|
||||||
@@ -293,7 +294,7 @@ SpeexDecoder::Decode(void *buffer, int64 *frameCount,
|
|||||||
|
|
||||||
done:
|
done:
|
||||||
uint samples = ((uint8*)out_buffer - (uint8*)buffer) / fFrameSize;
|
uint samples = ((uint8*)out_buffer - (uint8*)buffer) / fFrameSize;
|
||||||
fStartTime += (1000000LL * samples) / fHeader->rate;
|
//fStartTime += (1000000LL * samples) / fHeader->rate;
|
||||||
//TRACE("SpeexDecoder: fStartTime inc'd to %.6f\n", fStartTime / 1000000.0);
|
//TRACE("SpeexDecoder: fStartTime inc'd to %.6f\n", fStartTime / 1000000.0);
|
||||||
*frameCount = (fOutputBufferSize - out_bytes_needed) / fFrameSize;
|
*frameCount = (fOutputBufferSize - out_bytes_needed) / fFrameSize;
|
||||||
|
|
||||||
|
|||||||
@@ -194,6 +194,7 @@ VorbisDecoder::Decode(void *buffer, int64 *frameCount,
|
|||||||
TRACE("VorbisDecoder::Decode: chunk not ogg_packet-sized\n");
|
TRACE("VorbisDecoder::Decode: chunk not ogg_packet-sized\n");
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
fStartTime = mh.start_time;
|
||||||
ogg_packet * packet = static_cast<ogg_packet*>(chunkBuffer);
|
ogg_packet * packet = static_cast<ogg_packet*>(chunkBuffer);
|
||||||
if (vorbis_synthesis(&fBlock,packet)==0) {
|
if (vorbis_synthesis(&fBlock,packet)==0) {
|
||||||
vorbis_synthesis_blockin(&fDspState,&fBlock);
|
vorbis_synthesis_blockin(&fDspState,&fBlock);
|
||||||
@@ -226,7 +227,7 @@ VorbisDecoder::Decode(void *buffer, int64 *frameCount,
|
|||||||
// report back how many samples we consumed
|
// report back how many samples we consumed
|
||||||
vorbis_synthesis_read(&fDspState,samples);
|
vorbis_synthesis_read(&fDspState,samples);
|
||||||
|
|
||||||
fStartTime += (1000000LL * samples) / fInfo.rate;
|
//fStartTime += (1000000LL * samples) / fInfo.rate;
|
||||||
//TRACE("VorbisDecoder: fStartTime inc'd to %.6f\n", fStartTime / 1000000.0);
|
//TRACE("VorbisDecoder: fStartTime inc'd to %.6f\n", fStartTime / 1000000.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user