* Copyright (c) 2007, Marcus Overhagen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <SupportDefs.h>
#include <math.h>
#include <stdio.h>
#include "FallbackIndex.h"
#ifdef TRACE_START_INDEX
#define TRACE printf
#else
#define TRACE(a...)
#endif
#define ERROR(a...) fprintf(stderr, a)
struct chunk {
uint32 chunk_id;
uint32 size;
};
FallbackIndex::FallbackIndex(BPositionIO *source, OpenDMLParser *parser)
: Index(source, parser)
{
}
FallbackIndex::~FallbackIndex()
{
}
status_t
FallbackIndex::Init()
{
TRACE("Constructing a Fallback Index\n");
bool end_of_movi = false;
chunk aChunk;
int stream_index;
off_t position;
uint32 size;
uint64 frame[fStreamCount];
uint64 frame_no;
bigtime_t pts = 0;
bool keyframe = false;
uint32 sample_size;
uint64 entries = 0;
const OpenDMLStream *stream;
for (uint32 i=0;i < fStreamCount; i++) {
frame[i] = 0;
}
position = fParser->MovieListStart();
while (end_of_movi == false) {
if ((int32)8 != fSource->ReadAt(position, &aChunk, 8)) {
ERROR("libOpenDML: FallbackIndex::Init file reading failed\n");
return B_IO_ERROR;
}
position += 8;
stream_index = ((aChunk.chunk_id & 0xff) - '0') * 10;
stream_index += ((aChunk.chunk_id >> 8) & 0xff) - '0';
if ((stream_index < 0) || (stream_index >= fStreamCount)) {
if (entries == 0) {
ERROR("libOpenDML: FallbackIndex::Init - Failed to build an index, file is too corrupt\n");
return B_IO_ERROR;
} else {
ERROR("libOpenDML: FallbackIndex::Init - Error while trying to build index, file is corrupt but will continue after creating %Ld entries in index\n",entries);
return B_OK;
}
}
entries++;
stream = fParser->StreamInfo(stream_index);
size = aChunk.size;
frame_no = frame[stream_index];
if (stream->is_video) {
pts = frame[stream_index] * 1000000LL * stream->frames_per_sec_scale / stream->frames_per_sec_rate;
frame[stream_index]++;
} else if (stream->is_audio) {
pts = frame[stream_index] * 1000000LL / stream->audio_format->frames_per_sec;
if (stream->audio_format->format_tag != 0x0001) {
if (stream->audio_format->block_align >= 960) {
frame[stream_index] += (uint64)(ceil((double)size / (double)stream->audio_format->block_align)) * stream->frames_per_sec_scale;
} else {
frame[stream_index] += (uint64)(ceil((double)size / (double)stream->audio_format->block_align)) * stream->audio_format->frames_per_sec / stream->audio_format->avg_bytes_per_sec;
}
} else {
if (stream->stream_header.sample_size > 0) {
sample_size = stream->stream_header.sample_size;
} else {
sample_size = stream->audio_format->bits_per_sample * stream->audio_format->channels / 8;
}
frame[stream_index] += size / stream->stream_header.sample_size;
}
}
AddIndex(stream_index, position, size, frame_no, pts, keyframe);
position += aChunk.size;
end_of_movi = position >= fParser->MovieListSize();
}
return B_OK;
}