* Added FindKeyFrame() method to MediaExtractor, it is similar to Seek(),

but operates "read-only".
* Added FindKeyFrame() method to ReaderPlugin, see above.
* Reformated ReaderPlugin header. Added const qualifier to Source() method.
* Small cleanups in BMediaTrack::SeekToTime() and SeekToFrame(). Added TODOs
  with regards to "seeking" in decoders, wich should IMHO be revised. (Codecs
  cannot seek in the stream, they only get fed chunk data. The only thing they
  can do is reset themselves in preparation for a discontinuity of the chunk
  data...)
* Implemented BMediaTrack::FindKeyframeByXX() methods via the new
  MediaExtractor::FindKeyFrame() method.
* Implemented Seek() and FindKeyFrame() methods in the Reader base class,
  returning B_NOT_SUPPORTED. I think this makes sense and also I don't have
  to adapt all existing Reader plugins for the new FindKeyFrame() call. :-)
* Implemeneted FindKeyFrame() in the avi_reader. The OpenDMLFile class
  gets Seek() extended for a "read-only" mode. Currently the implementation
  is broken (as before) with regards to keyframes. These were ignored before
  and I have not changed them to actually support the seek flags with regards
  to keyframes. That's the interesting TODO...
* Some reformatting here and there in avi_reader code, sorry for the mixup.
  The only actual change is the support for the read-only flag to Seek().


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24495 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2008-03-20 23:36:14 +00:00
parent e958cea514
commit d830aa92ce
16 changed files with 233 additions and 127 deletions
+2
View File
@@ -38,6 +38,8 @@ public:
status_t Seek(int32 stream, uint32 seekTo, status_t Seek(int32 stream, uint32 seekTo,
int64 *frame, bigtime_t *time); int64 *frame, bigtime_t *time);
status_t FindKeyFrame(int32 stream, uint32 seekTo,
int64 *frame, bigtime_t *time) const;
status_t GetNextChunk(int32 stream, status_t GetNextChunk(int32 stream,
const void **chunkBuffer, size_t *chunkSize, const void **chunkBuffer, size_t *chunkSize,
+26 -24
View File
@@ -11,50 +11,52 @@ enum {
B_MEDIA_SEEK_TO_FRAME = 0x20000 B_MEDIA_SEEK_TO_FRAME = 0x20000
}; };
class Reader class Reader {
{
public: public:
Reader(); Reader();
virtual ~Reader(); virtual ~Reader();
virtual const char *Copyright() = 0; virtual const char* Copyright() = 0;
virtual status_t Sniff(int32 *streamCount) = 0; virtual status_t Sniff(int32* streamCount) = 0;
virtual void GetFileFormatInfo(media_file_format *mff) = 0; virtual void GetFileFormatInfo(media_file_format* mff) = 0;
virtual status_t AllocateCookie(int32 streamNumber, void **cookie) = 0; virtual status_t AllocateCookie(int32 streamNumber,
virtual status_t FreeCookie(void *cookie) = 0; void** cookie) = 0;
virtual status_t FreeCookie(void* cookie) = 0;
virtual status_t GetStreamInfo(void *cookie, int64 *frameCount, bigtime_t *duration, virtual status_t GetStreamInfo(void* cookie, int64* frameCount,
media_format *format, const void **infoBuffer, size_t *infoSize) = 0; bigtime_t *duration, media_format* format,
const void** infoBuffer,
size_t* infoSize) = 0;
virtual status_t Seek(void *cookie, virtual status_t Seek(void* cookie, uint32 flags, int64* frame,
uint32 seekTo, bigtime_t* time);
int64 *frame, bigtime_t *time) = 0; virtual status_t FindKeyFrame(void* cookie, uint32 flags,
int64* frame, bigtime_t* time);
virtual status_t GetNextChunk(void *cookie, virtual status_t GetNextChunk(void* cookie,
const void **chunkBuffer, size_t *chunkSize, const void** chunkBuffer, size_t* chunkSize,
media_header *mediaHeader) = 0; media_header* mediaHeader) = 0;
BDataIO * Source(); BDataIO* Source() const;
private: private:
public: // XXX for test programs only public: // XXX for test programs only
void Setup(BDataIO *source); void Setup(BDataIO* source);
BDataIO * fSource; BDataIO* fSource;
}; };
class ReaderPlugin : public virtual MediaPlugin class ReaderPlugin : public virtual MediaPlugin {
{
public: public:
virtual Reader *NewReader() = 0; virtual Reader* NewReader() = 0;
}; };
} } // namespace BPrivate::media } } // namespace BPrivate::media
using namespace BPrivate::media; using namespace BPrivate::media;
#endif #endif // _READER_PLUGIN_H
@@ -307,7 +307,7 @@ aviReader::FreeCookie(void *_cookie)
status_t status_t
aviReader::GetStreamInfo(void *_cookie, int64 *frameCount, bigtime_t *duration, aviReader::GetStreamInfo(void *_cookie, int64 *frameCount, bigtime_t *duration,
media_format *format, const void **infoBuffer, size_t *infoSize) media_format *format, const void **infoBuffer, size_t *infoSize)
{ {
avi_cookie *cookie = (avi_cookie *)_cookie; avi_cookie *cookie = (avi_cookie *)_cookie;
@@ -321,8 +321,7 @@ aviReader::GetStreamInfo(void *_cookie, int64 *frameCount, bigtime_t *duration,
status_t status_t
aviReader::Seek(void *_cookie, uint32 seekTo, aviReader::Seek(void *_cookie, uint32 seekTo, int64 *frame, bigtime_t *time)
int64 *frame, bigtime_t *time)
{ {
avi_cookie *cookie = (avi_cookie *)_cookie; avi_cookie *cookie = (avi_cookie *)_cookie;
@@ -330,32 +329,61 @@ aviReader::Seek(void *_cookie, uint32 seekTo,
cookie->stream, cookie->stream,
(seekTo & B_MEDIA_SEEK_TO_TIME) ? " B_MEDIA_SEEK_TO_TIME" : "", (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_TO_FRAME) ? " B_MEDIA_SEEK_TO_FRAME" : "",
(seekTo & B_MEDIA_SEEK_CLOSEST_FORWARD) ? " B_MEDIA_SEEK_CLOSEST_FORWARD" : "", (seekTo & B_MEDIA_SEEK_CLOSEST_FORWARD) ?
(seekTo & B_MEDIA_SEEK_CLOSEST_BACKWARD) ? " B_MEDIA_SEEK_CLOSEST_BACKWARD" : "", " B_MEDIA_SEEK_CLOSEST_FORWARD" : "",
(seekTo & B_MEDIA_SEEK_CLOSEST_BACKWARD) ?
" B_MEDIA_SEEK_CLOSEST_BACKWARD" : "",
*time, *frame); *time, *frame);
status_t rv = fFile->Seek(cookie->stream, seekTo, frame, time); status_t rv = fFile->Seek(cookie->stream, seekTo, frame, time, false);
if (rv == B_OK) { if (rv == B_OK) {
cookie->frame_pos = *frame; cookie->frame_pos = *frame;
TRACE("aviReader::Seek: stream %d, success, setting frame_pos to %lld\n", cookie->stream, cookie->frame_pos); TRACE("aviReader::Seek: stream %d, success, setting frame_pos "
"to %lld\n", cookie->stream, cookie->frame_pos);
} }
return rv; return rv;
} }
status_t status_t
aviReader::GetNextChunk(void *_cookie, aviReader::FindKeyFrame(void *_cookie, uint32 flags, int64 *frame,
const void **chunkBuffer, size_t *chunkSize, bigtime_t *time)
media_header *mediaHeader) {
avi_cookie *cookie = (avi_cookie *)_cookie;
TRACE("aviReader::FindKeyFrame: stream %d, flags%s%s%s%s, time %Ld, "
"frame %Ld\n",
cookie->stream,
(flags & B_MEDIA_SEEK_TO_TIME) ? " B_MEDIA_SEEK_TO_TIME" : "",
(flags & B_MEDIA_SEEK_TO_FRAME) ? " B_MEDIA_SEEK_TO_FRAME" : "",
(flags & B_MEDIA_SEEK_CLOSEST_FORWARD) ?
" B_MEDIA_SEEK_CLOSEST_FORWARD" : "",
(flags & B_MEDIA_SEEK_CLOSEST_BACKWARD) ?
" B_MEDIA_SEEK_CLOSEST_BACKWARD" : "",
*time, *frame);
status_t rv = fFile->Seek(cookie->stream, flags, frame, time, true);
if (rv == B_OK) {
TRACE("aviReader::FindKeyFrame: stream %d, success\n",
cookie->stream);
}
return rv;
}
status_t
aviReader::GetNextChunk(void *_cookie, const void **chunkBuffer,
size_t *chunkSize, media_header *mediaHeader)
{ {
avi_cookie *cookie = (avi_cookie *)_cookie; avi_cookie *cookie = (avi_cookie *)_cookie;
int64 start; uint32 size; bool keyframe; int64 start; uint32 size; bool keyframe;
if (fFile->GetNextChunkInfo(cookie->stream, &start, &size, &keyframe) < B_OK) if (fFile->GetNextChunkInfo(cookie->stream, &start, &size,
&keyframe) < B_OK)
return B_LAST_BUFFER_ERROR; return B_LAST_BUFFER_ERROR;
if (size > 0x200000) { // 2 MB if (size > 0x200000) { // 2 MB
ERROR("stream %u: frame too big: %u byte\n", cookie->stream, size); ERROR("stream %u: frame too big: %lu bytes\n", cookie->stream, size);
return B_NO_MEMORY; return B_NO_MEMORY;
} }
@@ -369,17 +397,20 @@ aviReader::GetNextChunk(void *_cookie,
} }
} }
mediaHeader->start_time = (cookie->frame_pos * 1000000 * cookie->frames_per_sec_scale) / cookie->frames_per_sec_rate; mediaHeader->start_time = (cookie->frame_pos * 1000000
* cookie->frames_per_sec_scale) / cookie->frames_per_sec_rate;
if (cookie->is_audio) { if (cookie->is_audio) {
mediaHeader->type = B_MEDIA_ENCODED_AUDIO; mediaHeader->type = B_MEDIA_ENCODED_AUDIO;
mediaHeader->u.encoded_audio.buffer_flags = keyframe ? B_MEDIA_KEY_FRAME : 0; mediaHeader->u.encoded_audio.buffer_flags = keyframe ?
B_MEDIA_KEY_FRAME : 0;
cookie->frame_pos += size; cookie->frame_pos += size;
} else if (cookie->is_video) { } else if (cookie->is_video) {
mediaHeader->type = B_MEDIA_ENCODED_VIDEO; mediaHeader->type = B_MEDIA_ENCODED_VIDEO;
mediaHeader->u.encoded_video.field_flags = keyframe ? B_MEDIA_KEY_FRAME : 0; mediaHeader->u.encoded_video.field_flags = keyframe ?
B_MEDIA_KEY_FRAME : 0;
mediaHeader->u.encoded_video.first_active_line = 0; mediaHeader->u.encoded_video.first_active_line = 0;
mediaHeader->u.encoded_video.line_count = cookie->line_count; mediaHeader->u.encoded_video.line_count = cookie->line_count;
cookie->frame_pos += 1; cookie->frame_pos += 1;
} else { } else {
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -387,11 +418,13 @@ aviReader::GetNextChunk(void *_cookie,
// TRACE("stream %d (%s): start_time %.6f, pos %.3f %%\n", // TRACE("stream %d (%s): start_time %.6f, pos %.3f %%\n",
// cookie->stream, cookie->is_audio ? "A" : cookie->is_video ? "V" : "?", // cookie->stream, cookie->is_audio ? "A" : cookie->is_video ? "V" : "?",
// mediaHeader->start_time / 1000000.0, cookie->frame_pos * 100.0 / cookie->frame_count); // mediaHeader->start_time / 1000000.0, cookie->frame_pos * 100.0
// / cookie->frame_count);
*chunkBuffer = cookie->buffer; *chunkBuffer = cookie->buffer;
*chunkSize = size; *chunkSize = size;
return (int)size == fFile->Source()->ReadAt(start, cookie->buffer, size) ? B_OK : B_LAST_BUFFER_ERROR; return (int)size == fFile->Source()->ReadAt(start, cookie->buffer, size) ?
B_OK : B_LAST_BUFFER_ERROR;
} }
@@ -28,42 +28,44 @@
#include "ReaderPlugin.h" #include "ReaderPlugin.h"
#include "OpenDMLFile.h" #include "OpenDMLFile.h"
class aviReader : public Reader class aviReader : public Reader {
{
public: public:
aviReader(); aviReader();
~aviReader(); ~aviReader();
const char *Copyright(); virtual const char* Copyright();
status_t Sniff(int32 *streamCount); virtual status_t Sniff(int32* streamCount);
void GetFileFormatInfo(media_file_format *mff); virtual void GetFileFormatInfo(media_file_format* mff);
status_t AllocateCookie(int32 streamNumber, void **cookie); virtual status_t AllocateCookie(int32 streamNumber,
status_t FreeCookie(void *cookie); void** cookie);
virtual status_t FreeCookie(void* cookie);
status_t GetStreamInfo(void *cookie, int64 *frameCount, bigtime_t *duration, virtual status_t GetStreamInfo(void* cookie, int64* frameCount,
media_format *format, const void **infoBuffer, size_t *infoSize); bigtime_t *duration, media_format* format,
const void** infoBuffer,
size_t* infoSize);
status_t Seek(void *cookie, virtual status_t Seek(void* cookie, uint32 flags, int64* frame,
uint32 seekTo, bigtime_t* time);
int64 *frame, bigtime_t *time); virtual status_t FindKeyFrame(void* cookie, uint32 flags,
int64* frame, bigtime_t* time);
status_t GetNextChunk(void *cookie, virtual status_t GetNextChunk(void* cookie,
const void **chunkBuffer, size_t *chunkSize, const void** chunkBuffer, size_t* chunkSize,
media_header *mediaHeader); media_header* mediaHeader);
private: private:
OpenDMLFile *fFile; OpenDMLFile* fFile;
}; };
class aviReaderPlugin : public ReaderPlugin class aviReaderPlugin : public ReaderPlugin {
{
public: public:
Reader *NewReader(); Reader* NewReader();
}; };
MediaPlugin *instantiate_plugin(); MediaPlugin *instantiate_plugin();
#endif #endif // _AVI_READER_H
@@ -46,14 +46,17 @@ FallbackIndex::Init()
status_t status_t
FallbackIndex::GetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool *keyframe) FallbackIndex::GetNextChunkInfo(int stream_index, int64 *start, uint32 *size,
bool *keyframe)
{ {
return B_ERROR; return B_ERROR;
} }
status_t status_t
FallbackIndex::Seek(int stream_index, uint32 seekTo, int64 *frame, bigtime_t *time) FallbackIndex::Seek(int stream_index, uint32 seekTo, int64 *frame,
bigtime_t *time, bool readOnly)
{ {
return B_ERROR; return B_ERROR;
} }
@@ -39,7 +39,7 @@ public:
status_t GetNextChunkInfo(int stream_index, int64 *start, status_t GetNextChunkInfo(int stream_index, int64 *start,
uint32 *size, bool *keyframe); uint32 *size, bool *keyframe);
status_t Seek(int stream_index, uint32 seekTo, int64 *frame, status_t Seek(int stream_index, uint32 seekTo, int64 *frame,
bigtime_t *time); bigtime_t *time, bool readOnly);
}; };
#endif // _FALLBACK_INDEX_H #endif // _FALLBACK_INDEX_H
@@ -42,7 +42,7 @@ public:
virtual status_t GetNextChunkInfo(int stream_index, int64 *start, virtual status_t GetNextChunkInfo(int stream_index, int64 *start,
uint32 *size, bool *keyframe) = 0; uint32 *size, bool *keyframe) = 0;
virtual status_t Seek(int stream_index, uint32 seekTo, int64 *frame, virtual status_t Seek(int stream_index, uint32 seekTo, int64 *frame,
bigtime_t *time) = 0; bigtime_t *time, bool readOnly) = 0;
protected: protected:
BPositionIO * fSource; BPositionIO * fSource;
@@ -385,15 +385,17 @@ OpenDMLFile::AviGetNextChunkInfo(int stream_index, int64 *start, uint32 *size, b
status_t status_t
OpenDMLFile::GetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool *keyframe) OpenDMLFile::GetNextChunkInfo(int stream_index, int64 *start, uint32 *size,
bool *keyframe)
{ {
return fIndex->GetNextChunkInfo(stream_index, start, size, keyframe); return fIndex->GetNextChunkInfo(stream_index, start, size, keyframe);
} }
status_t status_t
OpenDMLFile::Seek(int stream_index, uint32 seekTo, int64 *frame, bigtime_t *time) OpenDMLFile::Seek(int stream_index, uint32 seekTo, int64 *frame,
bigtime_t *time, bool readOnly)
{ {
return fIndex->Seek(stream_index, seekTo, frame, time); return fIndex->Seek(stream_index, seekTo, frame, time, readOnly);
} }
int int
@@ -57,8 +57,10 @@ public:
const bitmap_info_header * VideoFormat(int stream_index); const bitmap_info_header * VideoFormat(int stream_index);
const avi_stream_header * StreamFormat(int stream_index); const avi_stream_header * StreamFormat(int stream_index);
status_t GetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool *keyframe); status_t GetNextChunkInfo(int stream_index, int64 *start,
status_t Seek(int stream_index, uint32 seekTo, int64 *frame, bigtime_t *time); uint32 *size, bool *keyframe);
status_t Seek(int stream_index, uint32 seekTo, int64 *frame,
bigtime_t *time, bool readOnly);
BPositionIO *Source() { return fSource; } BPositionIO *Source() { return fSource; }
@@ -46,14 +46,18 @@ OpenDMLIndex::Init()
status_t status_t
OpenDMLIndex::GetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool *keyframe) OpenDMLIndex::GetNextChunkInfo(int stream_index, int64 *start, uint32 *size,
bool *keyframe)
{ {
return B_ERROR; return B_ERROR;
} }
status_t status_t
OpenDMLIndex::Seek(int stream_index, uint32 seekTo, int64 *frame, bigtime_t *time) OpenDMLIndex::Seek(int stream_index, uint32 seekTo, int64 *frame,
bigtime_t *time, bool readOnly)
{ {
return B_ERROR; return B_ERROR;
} }
@@ -35,8 +35,10 @@ public:
status_t Init(); status_t Init();
status_t GetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool *keyframe); status_t GetNextChunkInfo(int stream_index, int64* start,
status_t Seek(int stream_index, uint32 seekTo, int64 *frame, bigtime_t *time); uint32* size, bool* keyframe);
status_t Seek(int stream_index, uint32 seekTo, int64* frame,
bigtime_t* time, bool readOnly);
}; };
#endif #endif
@@ -225,7 +225,7 @@ StandardIndex::GetNextChunkInfo(int stream_index, int64 *start, uint32 *size,
status_t status_t
StandardIndex::Seek(int stream_index, uint32 seekTo, int64 *frame, StandardIndex::Seek(int stream_index, uint32 seekTo, int64 *frame,
bigtime_t *time) bigtime_t *time, bool readOnly)
{ {
TRACE("StandardIndex::Seek: stream %d, seekTo%s%s%s%s, time %Ld, " TRACE("StandardIndex::Seek: stream %d, seekTo%s%s%s%s, time %Ld, "
"frame %Ld\n", stream_index, "frame %Ld\n", stream_index,
@@ -249,13 +249,15 @@ StandardIndex::Seek(int stream_index, uint32 seekTo, int64 *frame,
} else } else
return B_BAD_VALUE; return B_BAD_VALUE;
// TODO: Actually take keyframe flags into account!
if (stream->is_audio) { if (stream->is_audio) {
int64 bytes = 0; int64 bytes = 0;
for (uint32 i = 0; i < fIndexSize; i++) { for (uint32 i = 0; i < fIndexSize; i++) {
if ((fIndex[i].chunk_id & 0xffff) == data->chunk_id) { if ((fIndex[i].chunk_id & 0xffff) == data->chunk_id) {
int64 bytesNext = bytes + fIndex[i].chunk_length; int64 bytesNext = bytes + fIndex[i].chunk_length;
if (bytes <= frame_pos && bytesNext > frame_pos) { if (bytes <= frame_pos && bytesNext > frame_pos) {
data->stream_pos = i; if (!readOnly)
data->stream_pos = i;
goto done; goto done;
} }
bytes = bytesNext; bytes = bytesNext;
@@ -266,7 +268,8 @@ StandardIndex::Seek(int stream_index, uint32 seekTo, int64 *frame,
for (uint32 i = 0; i < fIndexSize; i++) { for (uint32 i = 0; i < fIndexSize; i++) {
if ((fIndex[i].chunk_id & 0xffff) == data->chunk_id) { if ((fIndex[i].chunk_id & 0xffff) == data->chunk_id) {
if (pos == frame_pos) { if (pos == frame_pos) {
data->stream_pos = i; if (!readOnly)
data->stream_pos = i;
goto done; goto done;
} }
pos++; pos++;
@@ -282,7 +285,8 @@ StandardIndex::Seek(int stream_index, uint32 seekTo, int64 *frame,
done: done:
TRACE("seek done: index: pos %d, size %d\n", data->stream_pos, fIndexSize); TRACE("seek done: index: pos %d, size %d\n", data->stream_pos, fIndexSize);
*frame = frame_pos; *frame = frame_pos;
*time = (frame_pos * 1000000 * stream->frames_per_sec_scale) / stream->frames_per_sec_rate; *time = (frame_pos * 1000000 * stream->frames_per_sec_scale)
/ stream->frames_per_sec_rate;
return B_OK; return B_OK;
} }
@@ -36,8 +36,10 @@ public:
status_t Init(); status_t Init();
status_t GetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool *keyframe); status_t GetNextChunkInfo(int stream_index, int64* start,
status_t Seek(int stream_index, uint32 seekTo, int64 *frame, bigtime_t *time); uint32* size, bool* keyframe);
status_t Seek(int stream_index, uint32 seekTo, int64* frame,
bigtime_t* time, bool readOnly);
private: private:
void DumpIndex(); void DumpIndex();
+13
View File
@@ -194,6 +194,19 @@ MediaExtractor::Seek(int32 stream, uint32 seekTo,
} }
status_t
MediaExtractor::FindKeyFrame(int32 stream, uint32 seekTo, int64 *frame,
bigtime_t *time) const
{
CALLED();
if (fStreamInfo[stream].status != B_OK)
return fStreamInfo[stream].status;
return fReader->FindKeyFrame(fStreamInfo[stream].cookie,
seekTo, frame, time);
}
status_t status_t
MediaExtractor::GetNextChunk(int32 stream, MediaExtractor::GetNextChunk(int32 stream,
const void **chunkBuffer, size_t *chunkSize, const void **chunkBuffer, size_t *chunkSize,
+61 -42
View File
@@ -329,8 +329,7 @@ BMediaTrack::ReplaceFrames(const void *in_buffer,
status_t status_t
BMediaTrack::SeekToTime(bigtime_t *inout_time, BMediaTrack::SeekToTime(bigtime_t *inout_time, int32 flags)
int32 flags)
{ {
CALLED(); CALLED();
if (!fDecoder || !fExtractor) if (!fDecoder || !fExtractor)
@@ -338,23 +337,22 @@ BMediaTrack::SeekToTime(bigtime_t *inout_time,
if (!inout_time) if (!inout_time)
return B_BAD_VALUE; return B_BAD_VALUE;
status_t result; uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK)
uint32 seekTo; | B_MEDIA_SEEK_TO_TIME;
bigtime_t seekTime; bigtime_t seekTime = *inout_time;
int64 frame; int64 frame = 0;
bigtime_t time; bigtime_t time = seekTime;
status_t result = fExtractor->Seek(fStream, seekTo, &frame, &time);
seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_TIME;
seekTime = *inout_time;
time = seekTime;
result = fExtractor->Seek(fStream, seekTo, &frame, &time);
if (result != B_OK) { if (result != B_OK) {
ERROR("BMediaTrack::SeekToTime: extractor seek failed\n"); ERROR("BMediaTrack::SeekToTime: extractor seek failed\n");
return result; return result;
} }
// TODO: Codecs cannot actually "seek" in the stream, all they
// can do is "reset" their decoder state, since they are made
// aware of the fact that there will be a jump in the data. Maybe
// rename the codec method?
result = fDecoder->Seek(seekTo, 0, &frame, seekTime, &time); result = fDecoder->Seek(seekTo, 0, &frame, seekTime, &time);
if (result != B_OK) { if (result != B_OK) {
ERROR("BMediaTrack::SeekToTime: decoder seek failed\n"); ERROR("BMediaTrack::SeekToTime: decoder seek failed\n");
@@ -380,8 +378,7 @@ BMediaTrack::SeekToTime(bigtime_t *inout_time,
status_t status_t
BMediaTrack::SeekToFrame(int64 *inout_frame, BMediaTrack::SeekToFrame(int64 *inout_frame, int32 flags)
int32 flags)
{ {
CALLED(); CALLED();
if (!fDecoder || !fExtractor) if (!fDecoder || !fExtractor)
@@ -389,23 +386,22 @@ BMediaTrack::SeekToFrame(int64 *inout_frame,
if (!inout_frame) if (!inout_frame)
return B_BAD_VALUE; return B_BAD_VALUE;
status_t result; uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK)
uint32 seekTo; | B_MEDIA_SEEK_TO_FRAME;
int64 seekFrame; int64 seekFrame = *inout_frame;
int64 frame; int64 frame = seekFrame;
bigtime_t time; bigtime_t time = 0;
status_t result = fExtractor->Seek(fStream, seekTo, &frame, &time);
seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_FRAME;
seekFrame = *inout_frame;
frame = seekFrame;
result = fExtractor->Seek(fStream, seekTo, &frame, &time);
if (result != B_OK) { if (result != B_OK) {
ERROR("BMediaTrack::SeekToFrame: extractor seek failed\n"); ERROR("BMediaTrack::SeekToFrame: extractor seek failed\n");
return result; return result;
} }
// TODO: Codecs cannot actually "seek" in the stream, all they
// can do is "reset" their decoder state, since they are made
// aware of the fact that there will be a jump in the data. Maybe
// rename the codec method?
result = fDecoder->Seek(seekTo, seekFrame, &frame, 0, &time); result = fDecoder->Seek(seekTo, seekFrame, &frame, 0, &time);
if (result != B_OK) { if (result != B_OK) {
ERROR("BMediaTrack::SeekToFrame: decoder seek failed\n"); ERROR("BMediaTrack::SeekToFrame: decoder seek failed\n");
@@ -431,32 +427,55 @@ BMediaTrack::SeekToFrame(int64 *inout_frame,
status_t status_t
BMediaTrack::FindKeyFrameForTime(bigtime_t *inout_time, BMediaTrack::FindKeyFrameForTime(bigtime_t *inoutTime, int32 flags) const
int32 flags) const
{ {
// TODO: let the codec handle this, but it is almost CALLED();
// save to assume that frame at time 0 is a keyframe if (!fExtractor)
if (*inout_time == 0) return B_NO_INIT;
return B_OK; if (!inoutTime)
return B_BAD_VALUE;
UNIMPLEMENTED(); uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK)
| B_MEDIA_SEEK_TO_TIME;
int64 frame = 0;
// dummy frame, will be ignored because of flags
status_t result = fExtractor->FindKeyFrame(fStream, seekTo, &frame,
inoutTime);
if (result != B_OK) {
ERROR("BMediaTrack::FindKeyFrameForTime: extractor seek failed: %s\n",
strerror(result));
return result;
}
return B_ERROR; return B_OK;
} }
status_t status_t
BMediaTrack::FindKeyFrameForFrame(int64 *inout_frame, BMediaTrack::FindKeyFrameForFrame(int64 *inoutFrame,
int32 flags) const int32 flags) const
{ {
// TODO: let the codec handle this, but it is almost CALLED();
// save to assume that frame 0 is a keyframe if (!fExtractor)
if (*inout_frame == 0) return B_NO_INIT;
return B_OK; if (!inoutFrame)
return B_BAD_VALUE;
UNIMPLEMENTED(); uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK)
| B_MEDIA_SEEK_TO_FRAME;
bigtime_t time = 0;
// dummy time, will be ignored because of flags
status_t result = fExtractor->FindKeyFrame(fStream, seekTo, inoutFrame,
&time);
if (result != B_OK) {
ERROR("BMediaTrack::FindKeyFrameForFrame: extractor seek failed: %s\n",
strerror(result));
return result;
}
return B_ERROR; return B_OK;
} }
+18 -2
View File
@@ -1,5 +1,6 @@
#include "ReaderPlugin.h" #include "ReaderPlugin.h"
Reader::Reader() Reader::Reader()
: fSource(0) : fSource(0)
{ {
@@ -11,12 +12,27 @@ Reader::~Reader()
} }
BDataIO * status_t
Reader::Source() Reader::Seek(void* cookie, uint32 flags, int64* frame, bigtime_t* time)
{
return B_NOT_SUPPORTED;
}
status_t
Reader::FindKeyFrame(void* cookie, uint32 flags, int64* frame, bigtime_t* time)
{
return B_NOT_SUPPORTED;
}
BDataIO*
Reader::Source() const
{ {
return fSource; return fSource;
} }
void void
Reader::Setup(BDataIO *source) Reader::Setup(BDataIO *source)
{ {