added standard avi index parsing
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6394 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
bdb2cb7960
commit
507f09d364
@ -10,15 +10,18 @@ struct OpenDMLFile::stream_data
|
||||
const stream_info *info;
|
||||
|
||||
uint32 chunk_id;
|
||||
|
||||
bool has_odml_index;
|
||||
bool has_standard_index;
|
||||
|
||||
char * superindex;
|
||||
int superindex_entry_size;
|
||||
int superindex_entry_count;
|
||||
int superindex_entry_pos;
|
||||
char * odml_superindex;
|
||||
int odml_superindex_entry_size;
|
||||
int odml_superindex_entry_count;
|
||||
int odml_superindex_entry_pos;
|
||||
|
||||
// index info (superindex entry)
|
||||
int64 index_entry_start;
|
||||
// index info (odml_superindex entry, or standard avi index)
|
||||
int64 index_base_offset;
|
||||
int64 index_entry_start;
|
||||
int index_entry_size;
|
||||
int index_entry_count;
|
||||
int index_entry_pos;
|
||||
@ -96,10 +99,28 @@ OpenDMLFile::InitData()
|
||||
fStreamCount = fParser->StreamCount();
|
||||
fStreamData = new stream_data[fStreamCount];
|
||||
|
||||
// If this file has a standard avi index, determine
|
||||
// start, size and count of entries, so it can be
|
||||
// assigned to each stream when the stream has no
|
||||
// individual OpenDML index
|
||||
int64 standard_index_start;
|
||||
int standard_index_entry_size;
|
||||
int standard_index_entry_count;
|
||||
if (fParser->StandardIndexSize()) {
|
||||
standard_index_start = fParser->StandardIndexStart();
|
||||
standard_index_entry_size = 16;
|
||||
standard_index_entry_count = fParser->StandardIndexSize() / 16;
|
||||
} else {
|
||||
standard_index_entry_count = 0;
|
||||
}
|
||||
|
||||
for (int stream = 0; stream < fStreamCount; stream++) {
|
||||
TRACE("OpenDMLFile::InitData: stream %d\n", stream);
|
||||
|
||||
fStreamData[stream].info = fParser->StreamInfo(stream);
|
||||
fStreamData[stream].has_odml_index = false;
|
||||
fStreamData[stream].has_standard_index = false;
|
||||
|
||||
if (fStreamData[stream].info->odml_index_size) {
|
||||
TRACE("OpenDMLFile::InitData: index header, start %Ld, size %lu\n", fStreamData[stream].info->odml_index_start, fStreamData[stream].info->odml_index_size);
|
||||
|
||||
@ -117,82 +138,80 @@ OpenDMLFile::InitData()
|
||||
|
||||
if (h.index_type == AVI_INDEX_OF_INDEXES) {
|
||||
int size = h.entries_used * h.longs_per_entry * 4;
|
||||
TRACE("OpenDMLFile::InitData: reading superindex of %d bytes\n", size);
|
||||
fStreamData[stream].superindex_entry_size = h.longs_per_entry * 4;
|
||||
fStreamData[stream].superindex_entry_count = h.entries_used;
|
||||
fStreamData[stream].superindex_entry_pos = 0;
|
||||
fStreamData[stream].superindex = new char [size];
|
||||
fSource->ReadAt(fStreamData[stream].info->odml_index_start + sizeof(h), fStreamData[stream].superindex, size);
|
||||
TRACE("OpenDMLFile::InitData: reading odml_superindex of %d bytes\n", size);
|
||||
fStreamData[stream].odml_superindex_entry_size = h.longs_per_entry * 4;
|
||||
fStreamData[stream].odml_superindex_entry_count = h.entries_used;
|
||||
fStreamData[stream].odml_superindex_entry_pos = 0;
|
||||
fStreamData[stream].odml_superindex = new char [size];
|
||||
fSource->ReadAt(fStreamData[stream].info->odml_index_start + sizeof(h), fStreamData[stream].odml_superindex, size);
|
||||
fStreamData[stream].has_odml_index = true;
|
||||
} else if (h.index_type == AVI_INDEX_OF_CHUNKS){
|
||||
TRACE("OpenDMLFile::InitData: creating fake superindex\n");
|
||||
fStreamData[stream].superindex_entry_size = 16;
|
||||
fStreamData[stream].superindex_entry_count = 1;
|
||||
fStreamData[stream].superindex_entry_pos = 0;
|
||||
fStreamData[stream].superindex = new char [16];
|
||||
((odml_superindex_entry *)fStreamData[stream].superindex)->start = fStreamData[stream].info->odml_index_start;
|
||||
((odml_superindex_entry *)fStreamData[stream].superindex)->size = fStreamData[stream].info->odml_index_size;
|
||||
((odml_superindex_entry *)fStreamData[stream].superindex)->duration = 0;
|
||||
TRACE("OpenDMLFile::InitData: creating fake odml_superindex\n");
|
||||
fStreamData[stream].odml_superindex_entry_size = 16;
|
||||
fStreamData[stream].odml_superindex_entry_count = 1;
|
||||
fStreamData[stream].odml_superindex_entry_pos = 0;
|
||||
fStreamData[stream].odml_superindex = new char [16];
|
||||
((odml_superindex_entry *)fStreamData[stream].odml_superindex)->start = fStreamData[stream].info->odml_index_start;
|
||||
((odml_superindex_entry *)fStreamData[stream].odml_superindex)->size = fStreamData[stream].info->odml_index_size;
|
||||
((odml_superindex_entry *)fStreamData[stream].odml_superindex)->duration = 0;
|
||||
fStreamData[stream].has_odml_index = true;
|
||||
} else if (h.index_type == AVI_INDEX_IS_DATA){
|
||||
TRACE("OpenDMLFile::InitData: AVI_INDEX_IS_DATA not supported\n");
|
||||
fStreamData[stream].superindex = 0;
|
||||
fStreamData[stream].superindex_entry_count = 0;
|
||||
fStreamData[stream].superindex_entry_pos = 0;
|
||||
fStreamData[stream].odml_superindex = 0;
|
||||
fStreamData[stream].odml_superindex_entry_count = 0;
|
||||
fStreamData[stream].odml_superindex_entry_pos = 0;
|
||||
} else {
|
||||
TRACE("OpenDMLFile::InitData: index type not recongnized\n");
|
||||
fStreamData[stream].superindex = 0;
|
||||
fStreamData[stream].superindex_entry_count = 0;
|
||||
fStreamData[stream].superindex_entry_pos = 0;
|
||||
fStreamData[stream].odml_superindex = 0;
|
||||
fStreamData[stream].odml_superindex_entry_count = 0;
|
||||
fStreamData[stream].odml_superindex_entry_pos = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < fStreamData[stream].superindex_entry_count; i++) {
|
||||
odml_superindex_entry *entry = (odml_superindex_entry *) (fStreamData[stream].superindex + i * fStreamData[stream].superindex_entry_size);
|
||||
TRACE("superindex entry %d: start %10Ld, size %8ld, duration %lu\n", i, entry->start, entry->size, entry->duration);
|
||||
for (int i = 0; i < fStreamData[stream].odml_superindex_entry_count; i++) {
|
||||
odml_superindex_entry *entry = (odml_superindex_entry *) (fStreamData[stream].odml_superindex + i * fStreamData[stream].odml_superindex_entry_size);
|
||||
TRACE("odml_superindex entry %d: start %10Ld, size %8ld, duration %lu\n", i, entry->start, entry->size, entry->duration);
|
||||
}
|
||||
|
||||
fStreamData[stream].index_entry_start = 0;
|
||||
fStreamData[stream].index_base_offset = 0;
|
||||
fStreamData[stream].index_entry_size = 0;
|
||||
fStreamData[stream].index_entry_count = 0;
|
||||
fStreamData[stream].index_entry_pos = 0;
|
||||
fStreamData[stream].index_chunk = new char [INDEX_CHUNK_SIZE];
|
||||
fStreamData[stream].index_chunk_entry_count = 0;
|
||||
fStreamData[stream].index_chunk_entry_pos = 0;
|
||||
} else {
|
||||
fStreamData[stream].superindex = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
fStreamData[stream].index_entry_start = 0;
|
||||
fStreamData[stream].index_base_offset = 0;
|
||||
fStreamData[stream].index_entry_size = 0;
|
||||
fStreamData[stream].index_entry_count = 0;
|
||||
fStreamData[stream].index_entry_pos = 0;
|
||||
fStreamData[stream].index_chunk = new char [INDEX_CHUNK_SIZE];
|
||||
fStreamData[stream].index_chunk_entry_count = 0;
|
||||
fStreamData[stream].index_chunk_entry_pos = 0;
|
||||
|
||||
|
||||
|
||||
// this stream has no superindex, as it doesn't have an opendml index :=)
|
||||
fStreamData[stream].odml_superindex = 0;
|
||||
fStreamData[stream].odml_superindex_entry_count = 0;
|
||||
fStreamData[stream].odml_superindex_entry_pos = 0;
|
||||
}
|
||||
|
||||
fStreamData[stream].index_base_offset = 0;
|
||||
fStreamData[stream].index_entry_start = 0;
|
||||
fStreamData[stream].index_entry_size = 0;
|
||||
fStreamData[stream].index_entry_count = 0;
|
||||
fStreamData[stream].index_entry_pos = 0;
|
||||
fStreamData[stream].index_chunk = new char [INDEX_CHUNK_SIZE];
|
||||
fStreamData[stream].index_chunk_entry_count = 0;
|
||||
fStreamData[stream].index_chunk_entry_pos = 0;
|
||||
|
||||
// if this stream doesn't have an OpenDML index,
|
||||
// but the file has a standard avi index, we can use it :)
|
||||
if (!fStreamData[stream].has_odml_index && standard_index_entry_count != 0) {
|
||||
fStreamData[stream].has_standard_index = true;
|
||||
fStreamData[stream].index_base_offset = fParser->MovieListStart() - 4; // offset includes the 4 byte 'movi' id
|
||||
fStreamData[stream].index_entry_start = standard_index_start;
|
||||
fStreamData[stream].index_entry_size = standard_index_entry_size;
|
||||
fStreamData[stream].index_entry_count = standard_index_entry_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
OpenDMLFile::ReadIndexInfo(int stream_index)
|
||||
OpenDMLFile::OdmlReadIndexInfo(int stream_index)
|
||||
{
|
||||
stream_data *data = &fStreamData[stream_index];
|
||||
|
||||
if (data->superindex_entry_pos >= data->superindex_entry_count) {
|
||||
TRACE("reached end of superindex\n");
|
||||
if (data->odml_superindex_entry_pos >= data->odml_superindex_entry_count) {
|
||||
TRACE("reached end of odml_superindex\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
odml_superindex_entry *entry = (odml_superindex_entry *) (data->superindex + data->superindex_entry_pos * data->superindex_entry_size);
|
||||
odml_superindex_entry *entry = (odml_superindex_entry *) (data->odml_superindex + data->odml_superindex_entry_pos * data->odml_superindex_entry_size);
|
||||
|
||||
TRACE("OpenDMLFile::ReadIndexInfo: stream %d, pos %d, start %Ld, size %lu, duration %u\n",
|
||||
stream_index, data->superindex_entry_pos, entry->start, entry->size, entry->duration);
|
||||
TRACE("OpenDMLFile::OdmlReadIndexInfo: stream %d, pos %d, start %Ld, size %lu, duration %u\n",
|
||||
stream_index, data->odml_superindex_entry_pos, entry->start, entry->size, entry->duration);
|
||||
|
||||
odml_chunk_index_header chunk_index_header;
|
||||
|
||||
@ -214,17 +233,17 @@ OpenDMLFile::ReadIndexInfo(int stream_index)
|
||||
data->index_entry_count = chunk_index_header.entries_used;
|
||||
data->index_entry_pos = 0;
|
||||
|
||||
data->superindex_entry_pos++;
|
||||
data->odml_superindex_entry_pos++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
OpenDMLFile::ReadIndexChunk(int stream_index)
|
||||
OpenDMLFile::OdmlReadIndexChunk(int stream_index)
|
||||
{
|
||||
stream_data *data = &fStreamData[stream_index];
|
||||
|
||||
while (data->index_entry_pos >= data->index_entry_count) {
|
||||
if (!ReadIndexInfo(stream_index))
|
||||
if (!OdmlReadIndexInfo(stream_index))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -233,7 +252,7 @@ OpenDMLFile::ReadIndexChunk(int stream_index)
|
||||
int size = data->index_chunk_entry_count * data->index_entry_size;
|
||||
int64 start = data->index_entry_start + data->index_entry_pos * data->index_entry_size;
|
||||
|
||||
TRACE("OpenDMLFile::ReadIndexChunk: stream %d, index_chunk_entry_count %d, size %d, start %Ld\n",
|
||||
TRACE("OpenDMLFile::OdmlReadIndexChunk: stream %d, index_chunk_entry_count %d, size %d, start %Ld\n",
|
||||
stream_index, data->index_chunk_entry_count, size, start);
|
||||
|
||||
if (size != fSource->ReadAt(start, data->index_chunk, size)) {
|
||||
@ -246,12 +265,14 @@ OpenDMLFile::ReadIndexChunk(int stream_index)
|
||||
}
|
||||
|
||||
bool
|
||||
OpenDMLFile::GetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool *keyframe)
|
||||
OpenDMLFile::OdmlGetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool *keyframe)
|
||||
{
|
||||
// this function uses the OpenDML index (an OpenDML AVI contains one index per stream)
|
||||
|
||||
stream_data *data = &fStreamData[stream_index];
|
||||
|
||||
while (data->index_chunk_entry_pos >= data->index_chunk_entry_count) {
|
||||
if (!ReadIndexChunk(stream_index))
|
||||
if (!OdmlReadIndexChunk(stream_index))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -267,7 +288,63 @@ OpenDMLFile::GetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool
|
||||
stream_index, *start, *size, *keyframe ? ", keyframe" : "");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
OpenDMLFile::AviGetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool *keyframe)
|
||||
{
|
||||
// this function uses the AVI standard index (a standard AVI contains one index per file, that covers all streams)
|
||||
|
||||
stream_data *data = &fStreamData[stream_index];
|
||||
|
||||
while (data->index_entry_pos < data->index_entry_count) {
|
||||
if (data->index_chunk_entry_pos == data->index_chunk_entry_count) {
|
||||
data->index_chunk_entry_count = min_c(data->index_entry_count - data->index_entry_pos, INDEX_CHUNK_SIZE / data->index_entry_size);
|
||||
data->index_chunk_entry_pos = 0;
|
||||
uint32 start = data->index_entry_start + data->index_entry_pos * data->index_entry_size;
|
||||
int size = data->index_chunk_entry_count * data->index_entry_size;
|
||||
TRACE("OpenDMLFile::AviGetNextChunkInfo: stream %d, index_chunk_entry_count %d, size %d, start %lu\n",
|
||||
stream_index, data->index_chunk_entry_count, size, start);
|
||||
if (size != fSource->ReadAt(start, data->index_chunk, size)) {
|
||||
TRACE("OpenDMLFile::AviGetNextChunkInfo: read error\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
avi_standard_index_entry *entry = (avi_standard_index_entry *)(data->index_chunk + data->index_chunk_entry_pos * data->index_entry_size);
|
||||
|
||||
TRACE("OpenDMLFile::AviGetNextChunkInfo: stream %d, chunk_id "FOURCC_FORMAT" (0x%08x), flags 0x%x, offset %lu, length %lu\n",
|
||||
stream_index, FOURCC_PARAM(entry->chunk_id), entry->chunk_id, entry->flags, entry->chunk_offset, entry->chunk_length);
|
||||
|
||||
data->index_chunk_entry_pos++;
|
||||
data->index_entry_pos++;
|
||||
|
||||
int real_stream_index = ((entry->chunk_id & 0xff) - '0') * 10 + ((entry->chunk_id >> 8) & 0xff) - '0';
|
||||
|
||||
TRACE("OpenDMLFile::AviGetNextChunkInfo: real_stream_index %d %d %d\n", real_stream_index, ((entry->chunk_id & 0xff) - '0'), ((entry->chunk_id >> 8) & 0xff) - '0');
|
||||
|
||||
if (real_stream_index == stream_index) {
|
||||
*keyframe = entry->flags & AVIIF_KEYFRAME;
|
||||
*start = data->index_base_offset + entry->chunk_offset + 8;
|
||||
*size = entry->chunk_length;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
TRACE("OpenDMLFile::AviGetNextChunkInfo: index end reached\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
OpenDMLFile::GetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool *keyframe)
|
||||
{
|
||||
stream_data *data = &fStreamData[stream_index];
|
||||
if (data->has_standard_index)
|
||||
return AviGetNextChunkInfo(stream_index, start, size, keyframe);
|
||||
if (data->has_odml_index)
|
||||
return OdmlGetNextChunkInfo(stream_index, start, size, keyframe);
|
||||
return false;
|
||||
}
|
||||
|
||||
int
|
||||
OpenDMLFile::StreamCount()
|
||||
{
|
||||
|
@ -29,9 +29,13 @@ public:
|
||||
|
||||
private:
|
||||
void InitData();
|
||||
bool ReadIndexChunk(int stream_index);
|
||||
bool ReadIndexInfo(int stream_index);
|
||||
|
||||
|
||||
bool OdmlReadIndexChunk(int stream_index);
|
||||
bool OdmlReadIndexInfo(int stream_index);
|
||||
bool OdmlGetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool *keyframe);
|
||||
|
||||
bool AviGetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool *keyframe);
|
||||
|
||||
private:
|
||||
BPositionIO * fSource;
|
||||
OpenDMLParser * fParser;
|
||||
|
@ -20,6 +20,7 @@ struct movie_chunk
|
||||
OpenDMLParser::OpenDMLParser()
|
||||
: fSource(0),
|
||||
fSize(0),
|
||||
fMovieListStart(0),
|
||||
fStandardIndexStart(0),
|
||||
fStandardIndexSize(0),
|
||||
fStreamCount(0),
|
||||
@ -65,6 +66,12 @@ OpenDMLParser::StandardIndexSize()
|
||||
return fStandardIndexSize;
|
||||
}
|
||||
|
||||
int64
|
||||
OpenDMLParser::MovieListStart()
|
||||
{
|
||||
return fMovieListStart;
|
||||
}
|
||||
|
||||
const avi_main_header *
|
||||
OpenDMLParser::AviMainHeader()
|
||||
{
|
||||
@ -602,6 +609,9 @@ void
|
||||
OpenDMLParser::ParseList_movi(uint64 start, uint32 size)
|
||||
{
|
||||
TRACE("OpenDMLParser::ParseList_movi\n");
|
||||
|
||||
if (fMovieListStart == 0)
|
||||
fMovieListStart = start;
|
||||
|
||||
fMovieChunkCount++;
|
||||
return;
|
||||
|
@ -32,6 +32,8 @@ public:
|
||||
|
||||
int64 StandardIndexStart();
|
||||
uint32 StandardIndexSize();
|
||||
|
||||
int64 MovieListStart();
|
||||
|
||||
const avi_main_header * AviMainHeader();
|
||||
const odml_extended_header * OdmlExtendedHeader();
|
||||
@ -55,6 +57,8 @@ private:
|
||||
BPositionIO * fSource;
|
||||
int64 fSize;
|
||||
|
||||
int64 fMovieListStart;
|
||||
|
||||
int64 fStandardIndexStart;
|
||||
uint32 fStandardIndexSize;
|
||||
|
||||
|
@ -31,6 +31,14 @@ struct avi_standard_index_entry
|
||||
uint32 chunk_offset;
|
||||
uint32 chunk_length;
|
||||
} _PACKED;
|
||||
#define AVIIF_LIST 0x00000001
|
||||
#define AVIIF_KEYFRAME 0x00000010
|
||||
#define AVIIF_FIRSTPART 0x00000020
|
||||
#define AVIIF_LASTPART 0x00000040
|
||||
#define AVIIF_MIDPART (AVIIF_LASTPART | AVIFF_FIRSTPART)
|
||||
#define AVIIF_NOTIME 0x00000100
|
||||
#define AVIIF_COMPUSE 0x0fff0000
|
||||
|
||||
|
||||
struct odml_extended_header
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user