haiku/src/kits/media/TrackReader.cpp
beveloper 353b9f6bce changed map and list templates to be more useable, however, they will
be rewritten soon. Changed debugging macros and use of them, too.
Also replaced the linked lists in the BufferManager (which were complicated,
but working ok) with template based ones.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2133 a95241bf-73f2-0310-859d-f6bbb57e9c96
2002-12-03 00:59:42 +00:00

234 lines
5.0 KiB
C++

/***********************************************************************
* AUTHOR: Marcus Overhagen
* FILE: TrackReader.cpp
* DESCR: The undocumented BTrackReader class,
* used by BSound and the GameSound classes
***********************************************************************/
#include <MediaTrack.h>
#include <MediaFile.h>
#include <File.h>
#include <string.h>
#include "TrackReader.h"
#include "debug.h"
namespace BPrivate
{
BTrackReader::BTrackReader(BMediaTrack *track, media_raw_audio_format const &format) :
fFrameSize(0),
fBuffer(0),
fBufferOffset(0),
fBufferUsedSize(0),
fMediaFile(0),
fMediaTrack(0),
fFormat(format)
{
CALLED();
if (track == NULL)
return;
if (track->InitCheck() != B_OK)
return;
SetToTrack(track);
// if the track was not set abort now
if (fMediaTrack == 0)
return;
fBuffer = new uint8[fFormat.buffer_size];
fFrameSize = fFormat.channel_count * (fFormat.format & media_raw_audio_format::B_AUDIO_SIZE_MASK);
TRACE("BTrackReader::BTrackReader successful\n");
}
BTrackReader::BTrackReader(BFile *file, media_raw_audio_format const &format) :
fFrameSize(0),
fBuffer(0),
fBufferOffset(0),
fBufferUsedSize(0),
fMediaFile(0),
fMediaTrack(0),
fFormat(format)
{
CALLED();
if (file == NULL)
return;
if (file->InitCheck() != B_OK)
return;
fMediaFile = new BMediaFile(file);
if (fMediaFile->InitCheck() != B_OK)
return;
int count = fMediaFile->CountTracks();
if (count == 0) {
FATAL("BTrackReader: no tracks in file\n");
return;
}
// find the first audio track
BMediaTrack *track;
BMediaTrack *audiotrack = 0;
for (int tr = 0; tr < count; tr++) {
track = fMediaFile->TrackAt(tr);
if (track == 0 || track->InitCheck() != B_OK)
continue;
media_format fmt;
if (track->EncodedFormat(&fmt) != B_OK)
continue;
if (fmt.type == B_MEDIA_RAW_AUDIO) {
audiotrack = track;
break;
}
fMediaFile->ReleaseTrack(track);
}
if (audiotrack == 0) {
FATAL("BTrackReader: no audio track in file\n");
return;
}
SetToTrack(audiotrack);
// if the track was not set, release it
if (fMediaTrack == 0) {
fMediaFile->ReleaseTrack(audiotrack);
return;
}
fBuffer = new uint8[fFormat.buffer_size];
fFrameSize = fFormat.channel_count * (fFormat.format & media_raw_audio_format::B_AUDIO_SIZE_MASK);
TRACE("BTrackReader::BTrackReader successful\n");
}
void
BTrackReader::SetToTrack(BMediaTrack *track)
{
media_format fmt;
memset(&fmt,0,sizeof(fmt)); //wildcard
memcpy(&fmt.u.raw_audio,&fFormat,sizeof(fFormat));
fmt.type = B_MEDIA_RAW_AUDIO;
//try to find a output format
if (B_OK == track->DecodedFormat(&fmt)) {
memcpy(&fFormat,&fmt.u.raw_audio,sizeof(fFormat));
fMediaTrack = track;
return;
}
//try again
fmt.u.raw_audio.buffer_size = 2 * 4096;
fmt.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
if (B_OK == track->DecodedFormat(&fmt)) {
memcpy(&fFormat,&fmt.u.raw_audio,sizeof(fFormat));
fMediaTrack = track;
return;
}
//try again
fmt.u.raw_audio.buffer_size = 4096;
fmt.u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT;
if (B_OK == track->DecodedFormat(&fmt)) {
memcpy(&fFormat,&fmt.u.raw_audio,sizeof(fFormat));
fMediaTrack = track;
return;
}
//we have failed
FATAL("BTrackReader::SetToTrack failed\n");
}
BTrackReader::~BTrackReader()
{
CALLED();
if (fMediaFile && fMediaTrack)
fMediaFile->ReleaseTrack(fMediaTrack);
delete fMediaFile;
delete [] fBuffer;
}
status_t
BTrackReader::InitCheck()
{
CALLED();
return fMediaTrack ? fMediaTrack->InitCheck() : B_ERROR;
}
int64
BTrackReader::CountFrames(void)
{
CALLED();
return fMediaTrack ? fMediaTrack->CountFrames() : 0;
}
const media_raw_audio_format &
BTrackReader::Format(void) const
{
CALLED();
return fFormat;
}
int32
BTrackReader::FrameSize(void)
{
CALLED();
return fFrameSize;
}
status_t
BTrackReader::ReadFrames(void *in_buffer, int32 frame_count)
{
CALLED();
uint8 *buffer = static_cast<uint8 *>(in_buffer);
int32 bytes_to_read = frame_count * fFrameSize;
status_t last_status = B_OK;
while (bytes_to_read > 0) {
int32 bytes_to_copy = min_c(fBufferUsedSize,bytes_to_read);
if (bytes_to_copy > 0) {
memcpy(buffer,fBuffer + fBufferOffset,bytes_to_copy);
buffer += bytes_to_copy;
bytes_to_read -= bytes_to_copy;
fBufferOffset += bytes_to_copy;
fBufferUsedSize -= bytes_to_copy;
}
if (last_status != B_OK)
break;
if (fBufferUsedSize == 0) {
int64 outFrameCount;
last_status = fMediaTrack->ReadFrames(fBuffer,&outFrameCount);
fBufferOffset = 0;
fBufferUsedSize = outFrameCount * fFrameSize;
}
}
if (bytes_to_read > 0) {
memset(buffer,0,bytes_to_read);
return B_LAST_BUFFER_ERROR;
} else {
return B_OK;
}
}
status_t
BTrackReader::SeekToFrame(int64 *in_out_frame)
{
CALLED();
status_t s = fMediaTrack->SeekToFrame(in_out_frame, B_MEDIA_SEEK_CLOSEST_BACKWARD);
if (s != B_OK)
return s;
fBufferUsedSize = 0;
fBufferOffset = 0;
return B_OK;
}
BMediaTrack *
BTrackReader::Track(void)
{
CALLED();
return fMediaTrack;
}
}; //namespace BPrivate