I pronounce it Good!
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6275 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
fbe89ed67b
commit
170d6e3fbc
@ -1,9 +1,10 @@
|
|||||||
|
|
||||||
#include "OggFrameInfo.h"
|
#include "OggFrameInfo.h"
|
||||||
|
|
||||||
OggFrameInfo::OggFrameInfo(uint page, uint packet)
|
OggFrameInfo::OggFrameInfo(uint page, uint packetonpage, uint packet)
|
||||||
{
|
{
|
||||||
this->page = page;
|
this->page = page;
|
||||||
|
this->packetonpage = packetonpage;
|
||||||
this->packet = packet;
|
this->packet = packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,6 +20,12 @@ OggFrameInfo::GetPage() const
|
|||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint
|
||||||
|
OggFrameInfo::GetPacketOnPage() const
|
||||||
|
{
|
||||||
|
return packetonpage;
|
||||||
|
}
|
||||||
|
|
||||||
uint
|
uint
|
||||||
OggFrameInfo::GetPacket() const
|
OggFrameInfo::GetPacket() const
|
||||||
{
|
{
|
||||||
|
@ -5,14 +5,16 @@
|
|||||||
|
|
||||||
class OggFrameInfo {
|
class OggFrameInfo {
|
||||||
public:
|
public:
|
||||||
OggFrameInfo(uint page, uint packet);
|
OggFrameInfo(uint page, uint packetonpage, uint packet);
|
||||||
virtual ~OggFrameInfo();
|
virtual ~OggFrameInfo();
|
||||||
|
|
||||||
uint GetPage() const;
|
uint GetPage() const;
|
||||||
|
uint GetPacketOnPage() const;
|
||||||
uint GetPacket() const;
|
uint GetPacket() const;
|
||||||
private:
|
private:
|
||||||
uint page; // the page the packet started on
|
uint page; // the page the frame started on
|
||||||
uint packet; // of all the packets on that page which packet is this
|
uint packetonpage; // of all the packets on that page which packet is this
|
||||||
|
uint packet; // the packet the frame started on
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif _OGG_FRAME_INFO_H
|
#endif _OGG_FRAME_INFO_H
|
||||||
|
@ -156,7 +156,6 @@ OggReader::GetPageAt(off_t position, ogg_stream_state * stream, int read_size)
|
|||||||
while ((result = ogg_sync_pageout(&sync,&page)) == 0) {
|
while ((result = ogg_sync_pageout(&sync,&page)) == 0) {
|
||||||
char * buffer = ogg_sync_buffer(&sync,read_size);
|
char * buffer = ogg_sync_buffer(&sync,read_size);
|
||||||
ssize_t bytes = fSeekable->ReadAt(position,buffer,read_size);
|
ssize_t bytes = fSeekable->ReadAt(position,buffer,read_size);
|
||||||
position += read_size;
|
|
||||||
if (bytes == 0) {
|
if (bytes == 0) {
|
||||||
TRACE("OggReader::GetPage: Read: no data\n");
|
TRACE("OggReader::GetPage: Read: no data\n");
|
||||||
return B_LAST_BUFFER_ERROR;
|
return B_LAST_BUFFER_ERROR;
|
||||||
@ -165,6 +164,7 @@ OggReader::GetPageAt(off_t position, ogg_stream_state * stream, int read_size)
|
|||||||
TRACE("OggReader::GetPage: Read: error\n");
|
TRACE("OggReader::GetPage: Read: error\n");
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
position += bytes;
|
||||||
if (ogg_sync_wrote(&sync,bytes) != 0) {
|
if (ogg_sync_wrote(&sync,bytes) != 0) {
|
||||||
TRACE("OggReader::GetPage: ogg_sync_wrote failed?: error\n");
|
TRACE("OggReader::GetPage: ogg_sync_wrote failed?: error\n");
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "OggTheoraStream.h"
|
#include "OggTheoraStream.h"
|
||||||
#include "OggTobiasStream.h"
|
#include "OggTobiasStream.h"
|
||||||
#include "OggVorbisStream.h"
|
#include "OggVorbisStream.h"
|
||||||
|
#include <Autolock.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define TRACE_THIS 1
|
#define TRACE_THIS 1
|
||||||
@ -56,20 +57,33 @@ OggStream::findIdentifier(const ogg_packet & packet, const char * id, uint pos)
|
|||||||
OggStream::OggStream(long serialno)
|
OggStream::OggStream(long serialno)
|
||||||
{
|
{
|
||||||
TRACE("OggStream::OggStream\n");
|
TRACE("OggStream::OggStream\n");
|
||||||
this->fSerialno = serialno;
|
|
||||||
fCurrentFrame = 0;
|
fCurrentFrame = 0;
|
||||||
fCurrentTime = 0;
|
fCurrentTime = 0;
|
||||||
ogg_stream_init(&fStreamState,serialno);
|
this->fSerialno = serialno;
|
||||||
fCurrentPage = 0;
|
ogg_sync_init(&fSync);
|
||||||
fCurrentPacket = 0;
|
|
||||||
ogg_stream_init(&fSeekStreamState,serialno);
|
ogg_stream_init(&fSeekStreamState,serialno);
|
||||||
|
fCurrentPage = 0;
|
||||||
|
fPacketOnCurrentPage = 0;
|
||||||
|
fCurrentPacket = 0;
|
||||||
|
ogg_stream_init(&fEndStreamState,serialno);
|
||||||
|
fEndPage = 0;
|
||||||
|
fPacketOnEndPage = 0;
|
||||||
|
fEndPacket = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
OggStream::~OggStream()
|
OggStream::~OggStream()
|
||||||
{
|
{
|
||||||
ogg_stream_clear(&fStreamState);
|
// free internal header packet storage
|
||||||
|
std::vector<ogg_packet>::iterator iter = fHeaderPackets.begin();
|
||||||
|
while (iter != fHeaderPackets.end()) {
|
||||||
|
delete iter->packet;
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
// free internal stream state storage
|
||||||
|
ogg_sync_clear(&fSync);
|
||||||
ogg_stream_clear(&fSeekStreamState);
|
ogg_stream_clear(&fSeekStreamState);
|
||||||
|
ogg_stream_clear(&fEndStreamState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -87,7 +101,14 @@ OggStream::AddPage(off_t position, ogg_page * page)
|
|||||||
if (position >= 0) {
|
if (position >= 0) {
|
||||||
fPagePositions.push_back(position);
|
fPagePositions.push_back(position);
|
||||||
}
|
}
|
||||||
ogg_stream_pagein(&fStreamState,page);
|
BAutolock autolock(fSyncLock);
|
||||||
|
char * buffer;
|
||||||
|
buffer = ogg_sync_buffer(&fSync,page->header_len);
|
||||||
|
memcpy(buffer,page->header,page->header_len);
|
||||||
|
ogg_sync_wrote(&fSync,page->header_len);
|
||||||
|
buffer = ogg_sync_buffer(&fSync,page->body_len);
|
||||||
|
memcpy(buffer,page->body,page->body_len);
|
||||||
|
ogg_sync_wrote(&fSync,page->body_len);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +156,7 @@ OggStream::GetStreamInfo(int64 *frameCount, bigtime_t *duration,
|
|||||||
strncpy((char*)format->user_data, (char*)(&packet), 4);
|
strncpy((char*)format->user_data, (char*)(&packet), 4);
|
||||||
|
|
||||||
format->SetMetaData((void*)&fHeaderPackets,sizeof(fHeaderPackets));
|
format->SetMetaData((void*)&fHeaderPackets,sizeof(fHeaderPackets));
|
||||||
*duration = 80000000;
|
*duration = 140000000;
|
||||||
*frameCount = 60000;
|
*frameCount = 60000;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@ -146,8 +167,14 @@ OggStream::Seek(uint32 seekTo, int64 *frame, bigtime_t *time)
|
|||||||
{
|
{
|
||||||
TRACE("OggStream::Seek to %lld : %lld\n", *frame, *time);
|
TRACE("OggStream::Seek to %lld : %lld\n", *frame, *time);
|
||||||
if (seekTo & B_MEDIA_SEEK_TO_FRAME) {
|
if (seekTo & B_MEDIA_SEEK_TO_FRAME) {
|
||||||
|
if (*frame > fOggFrameInfos.size() - 1) {
|
||||||
|
// seek to end
|
||||||
|
fCurrentPage = fEndPage;
|
||||||
|
fPacketOnCurrentPage = fPacketOnEndPage;
|
||||||
|
fCurrentPacket = fEndPacket;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
*frame = max_c(0, *frame); // clip to zero
|
*frame = max_c(0, *frame); // clip to zero
|
||||||
*frame = min_c(*frame, fOggFrameInfos.size()-1); // clip to max
|
|
||||||
// input the page into a temporary seek stream
|
// input the page into a temporary seek stream
|
||||||
ogg_stream_state seekStreamState;
|
ogg_stream_state seekStreamState;
|
||||||
uint pageno = fOggFrameInfos[*frame].GetPage();
|
uint pageno = fOggFrameInfos[*frame].GetPage();
|
||||||
@ -159,13 +186,11 @@ OggStream::Seek(uint32 seekTo, int64 *frame, bigtime_t *time)
|
|||||||
return result; // pageno/fPagePosition corrupted?
|
return result; // pageno/fPagePosition corrupted?
|
||||||
}
|
}
|
||||||
// discard earlier packets from this page
|
// discard earlier packets from this page
|
||||||
uint packetno = fOggFrameInfos[*frame].GetPacket();
|
uint packetno = fOggFrameInfos[*frame].GetPacketOnPage();
|
||||||
while (packetno-- > 0) {
|
while (packetno-- > 0) {
|
||||||
ogg_packet packet;
|
ogg_packet packet;
|
||||||
if (ogg_stream_packetout(&fSeekStreamState, &packet) != 1) {
|
// don't check for errors, we may have a packet ending on page
|
||||||
TRACE("OggStream::GetPageAt packetno corrupt?\n");
|
ogg_stream_packetout(&seekStreamState, &packet);
|
||||||
return B_ERROR; // packetno corrupted?
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// clear out the former seek stream state
|
// clear out the former seek stream state
|
||||||
// this will delete its internal storage
|
// this will delete its internal storage
|
||||||
@ -175,7 +200,9 @@ OggStream::Seek(uint32 seekTo, int64 *frame, bigtime_t *time)
|
|||||||
fSeekStreamState = seekStreamState;
|
fSeekStreamState = seekStreamState;
|
||||||
// we notably do not clear our temporary stream
|
// we notably do not clear our temporary stream
|
||||||
// instead we just let it go out of scope
|
// instead we just let it go out of scope
|
||||||
fCurrentFrame = *frame;
|
fCurrentPage = fOggFrameInfos[*frame].GetPage();
|
||||||
|
fPacketOnCurrentPage = fOggFrameInfos[*frame].GetPacketOnPage();
|
||||||
|
fCurrentPacket = fOggFrameInfos[*frame].GetPacket();
|
||||||
} else if (seekTo & B_MEDIA_SEEK_TO_TIME) {
|
} else if (seekTo & B_MEDIA_SEEK_TO_TIME) {
|
||||||
*frame = *time/50000;
|
*frame = *time/50000;
|
||||||
return Seek(B_MEDIA_SEEK_TO_FRAME,frame,time);
|
return Seek(B_MEDIA_SEEK_TO_FRAME,frame,time);
|
||||||
@ -189,9 +216,13 @@ OggStream::GetNextChunk(void **chunkBuffer, int32 *chunkSize,
|
|||||||
media_header *mediaHeader)
|
media_header *mediaHeader)
|
||||||
{
|
{
|
||||||
static ogg_packet packet;
|
static ogg_packet packet;
|
||||||
|
if (fCurrentPacket - fHeaderPackets.size() == fOggFrameInfos.size()) {
|
||||||
|
OggFrameInfo info(fEndPage,fPacketOnEndPage,fEndPacket);
|
||||||
|
fOggFrameInfos.push_back(info);
|
||||||
|
}
|
||||||
status_t result = GetPacket(&packet);
|
status_t result = GetPacket(&packet);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
TRACE("OggStream::GetNextChunk failed: GetPacket failed\n");
|
TRACE("OggStream::GetNextChunk failed: GetPacket = %s\n", strerror(result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
*chunkBuffer = &packet;
|
*chunkBuffer = &packet;
|
||||||
@ -204,42 +235,65 @@ OggStream::GetNextChunk(void **chunkBuffer, int32 *chunkSize,
|
|||||||
status_t
|
status_t
|
||||||
OggStream::GetPacket(ogg_packet * packet)
|
OggStream::GetPacket(ogg_packet * packet)
|
||||||
{
|
{
|
||||||
if (fCurrentFrame == fOggFrameInfos.size()) {
|
if (fCurrentPacket >= fEndPacket) {
|
||||||
// at the end, pull the packet
|
// at the end, pull the packet
|
||||||
uint old_page = fCurrentPage;
|
uint8 pageno = fEndPage;
|
||||||
uint old_packet = fCurrentPacket;
|
while (ogg_stream_packetpeek(&fEndStreamState, NULL) != 1) {
|
||||||
while (ogg_stream_packetpeek(&fStreamState, NULL) != 1) {
|
BAutolock autolock(fSyncLock);
|
||||||
status_t result = fReaderInterface->GetNextPage();
|
int result;
|
||||||
if (result != B_OK) {
|
ogg_page page;
|
||||||
return result;
|
while ((result = ogg_sync_pageout(&fSync,&page)) == 0) {
|
||||||
|
status_t result = fReaderInterface->GetNextPage();
|
||||||
|
if (result != B_OK) {
|
||||||
|
TRACE("OggStream::GetPacket: GetNextPage = %s\n", strerror(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fCurrentPage++;
|
if (result == -1) {
|
||||||
|
TRACE("OggStream::GetPacket: ogg_sync_pageout: not synced??\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
if (ogg_stream_pagein(&fEndStreamState,&page) != 0) {
|
||||||
|
TRACE("OggStream::GetPacket: ogg_stream_pagein: failed??\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
fEndPage++;
|
||||||
}
|
}
|
||||||
if (ogg_stream_packetout(&fStreamState, packet) != 1) {
|
if (ogg_stream_packetout(&fEndStreamState, packet) != 1) {
|
||||||
|
TRACE("OggStream::GetPacket: ogg_stream_packetout failed at the end\n");
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
OggFrameInfo info(old_page, old_packet);
|
fEndPacket++;
|
||||||
fOggFrameInfos.push_back(info);
|
if (pageno != fEndPage) {
|
||||||
if (fCurrentPage != old_page) {
|
fPacketOnEndPage = 0;
|
||||||
fCurrentPacket = 0;
|
|
||||||
} else {
|
} else {
|
||||||
fCurrentPacket++;
|
fPacketOnEndPage++;
|
||||||
}
|
}
|
||||||
|
fCurrentPacket = fEndPacket;
|
||||||
|
fPacketOnCurrentPage = fPacketOnEndPage;
|
||||||
|
fCurrentPage = fEndPage;
|
||||||
} else {
|
} else {
|
||||||
// in the middle, get packet at position
|
// in the middle, get packet at position
|
||||||
uint pageno = fOggFrameInfos[fCurrentFrame].GetPage();
|
uint8 page = fCurrentPage;
|
||||||
while (ogg_stream_packetpeek(&fSeekStreamState, NULL) != 1) {
|
while (ogg_stream_packetpeek(&fSeekStreamState, NULL) != 1) {
|
||||||
off_t position = fPagePositions[pageno++];
|
off_t position = fPagePositions[fCurrentPage++];
|
||||||
status_t result = fReaderInterface->GetPageAt(position, &fSeekStreamState);
|
status_t result = fReaderInterface->GetPageAt(position, &fSeekStreamState);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
|
TRACE("OggStream::GetPacket: GetPageAt = %s\n", strerror(result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ogg_stream_packetout(&fSeekStreamState, packet) != 1) {
|
if (ogg_stream_packetout(&fSeekStreamState, packet) != 1) {
|
||||||
|
TRACE("OggStream::GetPacket: ogg_stream_packetout failed in the middle\n");
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
fCurrentPacket++;
|
||||||
|
if (page != fCurrentPage) {
|
||||||
|
fPacketOnCurrentPage = 0;
|
||||||
|
} else {
|
||||||
|
fPacketOnCurrentPage++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fCurrentFrame++; // ever moving forward!
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,32 +308,3 @@ OggStream::SaveHeaderPacket(ogg_packet packet)
|
|||||||
fHeaderPackets.push_back(packet);
|
fHeaderPackets.push_back(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// estimate 1 frame = 256 bytes
|
|
||||||
int64
|
|
||||||
OggStream::PositionToFrame(off_t position)
|
|
||||||
{
|
|
||||||
return position/256;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
off_t
|
|
||||||
OggStream::FrameToPosition(int64 frame)
|
|
||||||
{
|
|
||||||
return frame*256;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// estimate 1 byte = 125 microseconds
|
|
||||||
bigtime_t
|
|
||||||
OggStream::PositionToTime(off_t position)
|
|
||||||
{
|
|
||||||
return position*125;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
off_t
|
|
||||||
OggStream::TimeToPosition(bigtime_t time)
|
|
||||||
{
|
|
||||||
return time/125;
|
|
||||||
}
|
|
||||||
|
@ -42,21 +42,24 @@ protected:
|
|||||||
void SaveHeaderPacket(ogg_packet packet);
|
void SaveHeaderPacket(ogg_packet packet);
|
||||||
std::vector<ogg_packet> fHeaderPackets;
|
std::vector<ogg_packet> fHeaderPackets;
|
||||||
|
|
||||||
// Seek helpers
|
protected:
|
||||||
virtual int64 PositionToFrame(off_t position);
|
|
||||||
virtual off_t FrameToPosition(int64 frame);
|
|
||||||
virtual bigtime_t PositionToTime(off_t position);
|
|
||||||
virtual off_t TimeToPosition(bigtime_t time);
|
|
||||||
private:
|
|
||||||
long fSerialno;
|
|
||||||
int64 fCurrentFrame;
|
int64 fCurrentFrame;
|
||||||
bigtime_t fCurrentTime;
|
bigtime_t fCurrentTime;
|
||||||
|
|
||||||
|
private:
|
||||||
|
long fSerialno;
|
||||||
std::vector<off_t> fPagePositions;
|
std::vector<off_t> fPagePositions;
|
||||||
std::vector<OggFrameInfo> fOggFrameInfos;
|
std::vector<OggFrameInfo> fOggFrameInfos;
|
||||||
ogg_stream_state fStreamState;
|
ogg_sync_state fSync;
|
||||||
uint fCurrentPage;
|
BLocker fSyncLock;
|
||||||
uint fCurrentPacket;
|
|
||||||
ogg_stream_state fSeekStreamState;
|
ogg_stream_state fSeekStreamState;
|
||||||
|
uint fCurrentPage;
|
||||||
|
uint fPacketOnCurrentPage;
|
||||||
|
uint fCurrentPacket;
|
||||||
|
ogg_stream_state fEndStreamState;
|
||||||
|
uint fEndPage;
|
||||||
|
uint fPacketOnEndPage;
|
||||||
|
uint fEndPacket;
|
||||||
OggReader::GetPageInterface * fReaderInterface;
|
OggReader::GetPageInterface * fReaderInterface;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user