Moved some functionality from avi_reader into OpenDMLParser.
Added basic seeking support. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21401 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -33,12 +33,6 @@
|
||||
#include <StopWatch.h>
|
||||
|
||||
|
||||
struct StandardIndex::stream_data
|
||||
{
|
||||
uint32 chunk_id;
|
||||
uint32 pos;
|
||||
};
|
||||
|
||||
StandardIndex::StandardIndex(BPositionIO *source, OpenDMLParser *parser)
|
||||
: Index(source, parser)
|
||||
, fIndex(NULL)
|
||||
@@ -53,6 +47,10 @@ StandardIndex::StandardIndex(BPositionIO *source, OpenDMLParser *parser)
|
||||
StandardIndex::~StandardIndex()
|
||||
{
|
||||
delete [] fIndex;
|
||||
if (fStreamData) {
|
||||
for (int i = 0; i < fStreamCount; i++)
|
||||
delete [] fStreamData[i].seek_hints;
|
||||
}
|
||||
delete [] fStreamData;
|
||||
}
|
||||
|
||||
@@ -63,6 +61,11 @@ StandardIndex::Init()
|
||||
uint32 indexBytes = fParser->StandardIndexSize();
|
||||
fIndexSize = indexBytes / sizeof(avi_standard_index_entry);
|
||||
indexBytes = fIndexSize * sizeof(avi_standard_index_entry);
|
||||
uint32 seekHintsStride = 1800 * fStreamCount;
|
||||
uint32 seekHintsMax = fIndexSize / seekHintsStride;
|
||||
|
||||
printf("StandardIndex::Init: seekHintsStride %lu\n", seekHintsStride);
|
||||
printf("StandardIndex::Init: seekHintsMax %lu\n", seekHintsMax);
|
||||
|
||||
{ BStopWatch w("StandardIndex::Init: malloc");
|
||||
|
||||
@@ -92,13 +95,61 @@ StandardIndex::Init()
|
||||
}
|
||||
}
|
||||
|
||||
//DumpIndex();
|
||||
|
||||
fStreamData = new stream_data[fStreamCount];
|
||||
for (int i = 0; i < fStreamCount; i++) {
|
||||
fStreamData[i].chunk_id = i / 10 + '0' + (i % 10 + '0') * 256;
|
||||
fStreamData[i].pos = 0;
|
||||
fStreamData[i].chunk_count = 0;
|
||||
fStreamData[i].keyframe_count = 0;
|
||||
fStreamData[i].stream_pos = 0;
|
||||
fStreamData[i].stream_size = 0;
|
||||
fStreamData[i].seek_hints = new seek_hint[seekHintsMax];
|
||||
fStreamData[i].seek_hints_count = 0;
|
||||
fStreamData[i].seek_hints_next = seekHintsStride;
|
||||
}
|
||||
|
||||
{ BStopWatch w("StandardIndex::Init: scan index");
|
||||
|
||||
//DumpIndex();
|
||||
for (int stream = 0; stream < fStreamCount; stream++) {
|
||||
uint32 chunk_id = fStreamData[stream].chunk_id;
|
||||
uint64 stream_size = 0;
|
||||
uint32 chunk_count = 0;
|
||||
uint32 keyframe_count = 0;
|
||||
int seek_hints_next = seekHintsStride;
|
||||
int seek_hints_count = 0;
|
||||
for (int i = 0; i < fIndexSize; i++) {
|
||||
if ((fIndex[i].chunk_id & 0xffff) == chunk_id) {
|
||||
stream_size += fIndex[i].chunk_length;
|
||||
chunk_count++;
|
||||
keyframe_count += (fIndex[i].flags >> AVIIF_KEYFRAME_SHIFT) & 1;
|
||||
|
||||
if (i >= seek_hints_next) {
|
||||
seek_hints_next = i + seekHintsStride;
|
||||
seek_hint *hint = &fStreamData[stream].seek_hints[seek_hints_count++];
|
||||
hint->stream_pos = fIndex[i].chunk_offset;
|
||||
hint->index_pos = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
fStreamData[stream].stream_size = stream_size;
|
||||
fStreamData[stream].chunk_count = chunk_count;
|
||||
fStreamData[stream].keyframe_count = keyframe_count;
|
||||
fStreamData[stream].seek_hints_count = seek_hints_count;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < fStreamCount; i++) {
|
||||
printf("stream %d, stream_size %llu\n", i, fStreamData[i].stream_size);
|
||||
printf("stream %d, chunk_count %lu\n", i, fStreamData[i].chunk_count);
|
||||
printf("stream %d, keyframe_count %lu\n", i, fStreamData[i].keyframe_count);
|
||||
printf("stream %d, seek_hints_count %lu\n", i, fStreamData[i].seek_hints_count);
|
||||
for (int j = 0; j < fStreamData[i].seek_hints_count; j++) {
|
||||
printf(" seek_hint %3d, index_pos %6lu, stream_pos %lld\n", j,
|
||||
fStreamData[i].seek_hints[j].index_pos,
|
||||
fStreamData[i].seek_hints[j].stream_pos);
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -132,15 +183,15 @@ status_t
|
||||
StandardIndex::GetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool *keyframe)
|
||||
{
|
||||
stream_data *data = &fStreamData[stream_index];
|
||||
while (data->pos < fIndexSize) {
|
||||
if ((fIndex[data->pos].chunk_id & 0xffff) == data->chunk_id) {
|
||||
*keyframe = fIndex[data->pos].flags & AVIIF_KEYFRAME;
|
||||
*start = fDataOffset + fIndex[data->pos].chunk_offset + 8; // skip 8 bytes (chunk id + chunk size)
|
||||
*size = fIndex[data->pos].chunk_length;
|
||||
data->pos++;
|
||||
while (data->stream_pos < fIndexSize) {
|
||||
if ((fIndex[data->stream_pos].chunk_id & 0xffff) == data->chunk_id) {
|
||||
*keyframe = fIndex[data->stream_pos].flags & AVIIF_KEYFRAME;
|
||||
*start = fDataOffset + fIndex[data->stream_pos].chunk_offset + 8; // skip 8 bytes (chunk id + chunk size)
|
||||
*size = fIndex[data->stream_pos].chunk_length;
|
||||
data->stream_pos++;
|
||||
return B_OK;
|
||||
}
|
||||
data->pos++;
|
||||
data->stream_pos++;
|
||||
}
|
||||
|
||||
return B_ERROR;
|
||||
@@ -150,13 +201,59 @@ StandardIndex::GetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bo
|
||||
status_t
|
||||
StandardIndex::Seek(int stream_index, uint32 seekTo, int64 *frame, bigtime_t *time)
|
||||
{
|
||||
/*
|
||||
printf("StandardIndex::Seek: seekTo%s%s%s%s, time %Ld, frame %Ld\n",
|
||||
printf("StandardIndex::Seek: stream %d, seekTo%s%s%s%s, time %Ld, frame %Ld\n",
|
||||
stream_index,
|
||||
(seekTo & B_MEDIA_SEEK_TO_TIME) ? " B_MEDIA_SEEK_TO_TIME" : "",
|
||||
(seekTo & B_MEDIA_SEEK_TO_FRAME) ? " B_MEDIA_SEEK_TO_FRAME" : "",
|
||||
(seekTo & B_MEDIA_SEEK_CLOSEST_FORWARD) ? " B_MEDIA_SEEK_CLOSEST_FORWARD" : "",
|
||||
(seekTo & B_MEDIA_SEEK_CLOSEST_BACKWARD) ? " B_MEDIA_SEEK_CLOSEST_BACKWARD" : "");
|
||||
*/
|
||||
(seekTo & B_MEDIA_SEEK_CLOSEST_BACKWARD) ? " B_MEDIA_SEEK_CLOSEST_BACKWARD" : "",
|
||||
*time, *frame);
|
||||
|
||||
const stream_info *stream = fParser->StreamInfo(stream_index);
|
||||
stream_data *data = &fStreamData[stream_index];
|
||||
|
||||
int64 frame_pos;
|
||||
if (seekTo & B_MEDIA_SEEK_TO_FRAME)
|
||||
frame_pos = *frame;
|
||||
else if (seekTo & B_MEDIA_SEEK_TO_TIME)
|
||||
frame_pos = (*time * stream->frames_per_sec_rate) / (1000000 * stream->frames_per_sec_scale);
|
||||
else
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (stream->is_audio) {
|
||||
int64 bytes = 0;
|
||||
for (int i = 0; i < fIndexSize; i++) {
|
||||
if ((fIndex[i].chunk_id & 0xffff) == data->chunk_id) {
|
||||
int64 bytesNext = bytes + fIndex[i].chunk_length;
|
||||
if (bytes <= frame_pos && bytesNext > frame_pos) {
|
||||
data->stream_pos = i;
|
||||
goto done;
|
||||
}
|
||||
bytes = bytesNext;
|
||||
}
|
||||
}
|
||||
} else if (stream->is_video) {
|
||||
int pos = 0;
|
||||
for (int i = 0; i < fIndexSize; i++) {
|
||||
if ((fIndex[i].chunk_id & 0xffff) == data->chunk_id) {
|
||||
if (pos == frame_pos) {
|
||||
data->stream_pos = i;
|
||||
goto done;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
printf("seek failed, position not found\n");
|
||||
return B_ERROR;
|
||||
|
||||
done:
|
||||
printf("seek done: index: pos %d, size %d\n", data->stream_pos, fIndexSize);
|
||||
*frame = frame_pos;
|
||||
*time = (frame_pos * 1000000 * stream->frames_per_sec_scale) / stream->frames_per_sec_rate;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user