From d830aa92ce5e5063357b44483277e931f0276307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Thu, 20 Mar 2008 23:36:14 +0000 Subject: [PATCH] * 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 --- headers/private/media/MediaExtractor.h | 2 + headers/private/media/ReaderPlugin.h | 50 +++++---- .../media/plugins/avi_reader/avi_reader.cpp | 69 +++++++++--- .../media/plugins/avi_reader/avi_reader.h | 46 ++++---- .../avi_reader/libOpenDML/FallbackIndex.cpp | 7 +- .../avi_reader/libOpenDML/FallbackIndex.h | 2 +- .../plugins/avi_reader/libOpenDML/Index.h | 2 +- .../avi_reader/libOpenDML/OpenDMLFile.cpp | 8 +- .../avi_reader/libOpenDML/OpenDMLFile.h | 6 +- .../avi_reader/libOpenDML/OpenDMLIndex.cpp | 8 +- .../avi_reader/libOpenDML/OpenDMLIndex.h | 6 +- .../avi_reader/libOpenDML/StandardIndex.cpp | 12 +- .../avi_reader/libOpenDML/StandardIndex.h | 6 +- src/kits/media/MediaExtractor.cpp | 13 +++ src/kits/media/MediaTrack.cpp | 103 +++++++++++------- src/kits/media/ReaderPlugin.cpp | 20 +++- 16 files changed, 233 insertions(+), 127 deletions(-) diff --git a/headers/private/media/MediaExtractor.h b/headers/private/media/MediaExtractor.h index c4959cccb9..9982fa30a5 100644 --- a/headers/private/media/MediaExtractor.h +++ b/headers/private/media/MediaExtractor.h @@ -38,6 +38,8 @@ public: status_t Seek(int32 stream, uint32 seekTo, int64 *frame, bigtime_t *time); + status_t FindKeyFrame(int32 stream, uint32 seekTo, + int64 *frame, bigtime_t *time) const; status_t GetNextChunk(int32 stream, const void **chunkBuffer, size_t *chunkSize, diff --git a/headers/private/media/ReaderPlugin.h b/headers/private/media/ReaderPlugin.h index e383a63307..cf29423f6a 100644 --- a/headers/private/media/ReaderPlugin.h +++ b/headers/private/media/ReaderPlugin.h @@ -11,50 +11,52 @@ enum { B_MEDIA_SEEK_TO_FRAME = 0x20000 }; -class Reader -{ +class Reader { public: - Reader(); - virtual ~Reader(); + 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 FreeCookie(void *cookie) = 0; + virtual status_t AllocateCookie(int32 streamNumber, + void** cookie) = 0; + virtual status_t FreeCookie(void* cookie) = 0; - virtual status_t GetStreamInfo(void *cookie, int64 *frameCount, bigtime_t *duration, - media_format *format, const void **infoBuffer, size_t *infoSize) = 0; + virtual status_t GetStreamInfo(void* cookie, int64* frameCount, + bigtime_t *duration, media_format* format, + const void** infoBuffer, + size_t* infoSize) = 0; - virtual status_t Seek(void *cookie, - uint32 seekTo, - int64 *frame, bigtime_t *time) = 0; + virtual status_t Seek(void* cookie, uint32 flags, int64* frame, + bigtime_t* time); + virtual status_t FindKeyFrame(void* cookie, uint32 flags, + int64* frame, bigtime_t* time); - virtual status_t GetNextChunk(void *cookie, - const void **chunkBuffer, size_t *chunkSize, - media_header *mediaHeader) = 0; + virtual status_t GetNextChunk(void* cookie, + const void** chunkBuffer, size_t* chunkSize, + media_header* mediaHeader) = 0; - BDataIO * Source(); + BDataIO* Source() const; private: 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: - virtual Reader *NewReader() = 0; + virtual Reader* NewReader() = 0; }; } } // namespace BPrivate::media using namespace BPrivate::media; -#endif +#endif // _READER_PLUGIN_H diff --git a/src/add-ons/media/plugins/avi_reader/avi_reader.cpp b/src/add-ons/media/plugins/avi_reader/avi_reader.cpp index a05178671c..e9c29827d0 100644 --- a/src/add-ons/media/plugins/avi_reader/avi_reader.cpp +++ b/src/add-ons/media/plugins/avi_reader/avi_reader.cpp @@ -307,7 +307,7 @@ aviReader::FreeCookie(void *_cookie) status_t 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; @@ -321,8 +321,7 @@ aviReader::GetStreamInfo(void *_cookie, int64 *frameCount, bigtime_t *duration, status_t -aviReader::Seek(void *_cookie, uint32 seekTo, - int64 *frame, bigtime_t *time) +aviReader::Seek(void *_cookie, uint32 seekTo, int64 *frame, bigtime_t *time) { avi_cookie *cookie = (avi_cookie *)_cookie; @@ -330,32 +329,61 @@ aviReader::Seek(void *_cookie, uint32 seekTo, cookie->stream, (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_FORWARD) ? + " B_MEDIA_SEEK_CLOSEST_FORWARD" : "", + (seekTo & B_MEDIA_SEEK_CLOSEST_BACKWARD) ? + " B_MEDIA_SEEK_CLOSEST_BACKWARD" : "", *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) { 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; } status_t -aviReader::GetNextChunk(void *_cookie, - const void **chunkBuffer, size_t *chunkSize, - media_header *mediaHeader) +aviReader::FindKeyFrame(void *_cookie, uint32 flags, int64 *frame, + bigtime_t *time) +{ + 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; 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; 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; } @@ -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) { 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; } else if (cookie->is_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.line_count = cookie->line_count; + mediaHeader->u.encoded_video.line_count = cookie->line_count; cookie->frame_pos += 1; } else { return B_BAD_VALUE; @@ -387,11 +418,13 @@ aviReader::GetNextChunk(void *_cookie, // TRACE("stream %d (%s): start_time %.6f, pos %.3f %%\n", // 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; *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; } diff --git a/src/add-ons/media/plugins/avi_reader/avi_reader.h b/src/add-ons/media/plugins/avi_reader/avi_reader.h index 15ce036562..7d8c53dc7b 100644 --- a/src/add-ons/media/plugins/avi_reader/avi_reader.h +++ b/src/add-ons/media/plugins/avi_reader/avi_reader.h @@ -28,42 +28,44 @@ #include "ReaderPlugin.h" #include "OpenDMLFile.h" -class aviReader : public Reader -{ +class aviReader : public Reader { 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); - status_t FreeCookie(void *cookie); + virtual status_t AllocateCookie(int32 streamNumber, + void** cookie); + virtual status_t FreeCookie(void* cookie); - status_t GetStreamInfo(void *cookie, int64 *frameCount, bigtime_t *duration, - media_format *format, const void **infoBuffer, size_t *infoSize); + virtual status_t GetStreamInfo(void* cookie, int64* frameCount, + bigtime_t *duration, media_format* format, + const void** infoBuffer, + size_t* infoSize); - status_t Seek(void *cookie, - uint32 seekTo, - int64 *frame, bigtime_t *time); + virtual status_t Seek(void* cookie, uint32 flags, int64* frame, + bigtime_t* time); + virtual status_t FindKeyFrame(void* cookie, uint32 flags, + int64* frame, bigtime_t* time); - status_t GetNextChunk(void *cookie, - const void **chunkBuffer, size_t *chunkSize, - media_header *mediaHeader); + virtual status_t GetNextChunk(void* cookie, + const void** chunkBuffer, size_t* chunkSize, + media_header* mediaHeader); private: - OpenDMLFile *fFile; + OpenDMLFile* fFile; }; -class aviReaderPlugin : public ReaderPlugin -{ +class aviReaderPlugin : public ReaderPlugin { public: - Reader *NewReader(); + Reader* NewReader(); }; MediaPlugin *instantiate_plugin(); -#endif +#endif // _AVI_READER_H diff --git a/src/add-ons/media/plugins/avi_reader/libOpenDML/FallbackIndex.cpp b/src/add-ons/media/plugins/avi_reader/libOpenDML/FallbackIndex.cpp index a962f839c7..c359a53c2f 100644 --- a/src/add-ons/media/plugins/avi_reader/libOpenDML/FallbackIndex.cpp +++ b/src/add-ons/media/plugins/avi_reader/libOpenDML/FallbackIndex.cpp @@ -46,14 +46,17 @@ FallbackIndex::Init() 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; } 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; } + diff --git a/src/add-ons/media/plugins/avi_reader/libOpenDML/FallbackIndex.h b/src/add-ons/media/plugins/avi_reader/libOpenDML/FallbackIndex.h index 40b02a82d4..b5c49fb268 100644 --- a/src/add-ons/media/plugins/avi_reader/libOpenDML/FallbackIndex.h +++ b/src/add-ons/media/plugins/avi_reader/libOpenDML/FallbackIndex.h @@ -39,7 +39,7 @@ public: status_t GetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool *keyframe); status_t Seek(int stream_index, uint32 seekTo, int64 *frame, - bigtime_t *time); + bigtime_t *time, bool readOnly); }; #endif // _FALLBACK_INDEX_H diff --git a/src/add-ons/media/plugins/avi_reader/libOpenDML/Index.h b/src/add-ons/media/plugins/avi_reader/libOpenDML/Index.h index 2fb25faeb1..c52da9cd32 100644 --- a/src/add-ons/media/plugins/avi_reader/libOpenDML/Index.h +++ b/src/add-ons/media/plugins/avi_reader/libOpenDML/Index.h @@ -42,7 +42,7 @@ public: virtual status_t GetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool *keyframe) = 0; virtual status_t Seek(int stream_index, uint32 seekTo, int64 *frame, - bigtime_t *time) = 0; + bigtime_t *time, bool readOnly) = 0; protected: BPositionIO * fSource; diff --git a/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLFile.cpp b/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLFile.cpp index d2638b4aa2..03b7e60c1d 100644 --- a/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLFile.cpp +++ b/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLFile.cpp @@ -385,15 +385,17 @@ OpenDMLFile::AviGetNextChunkInfo(int stream_index, int64 *start, uint32 *size, b 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); } 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 diff --git a/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLFile.h b/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLFile.h index d5b3ff0d8b..3f3f2cb6b2 100644 --- a/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLFile.h +++ b/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLFile.h @@ -57,8 +57,10 @@ public: const bitmap_info_header * VideoFormat(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 Seek(int stream_index, uint32 seekTo, int64 *frame, bigtime_t *time); + status_t GetNextChunkInfo(int stream_index, int64 *start, + uint32 *size, bool *keyframe); + status_t Seek(int stream_index, uint32 seekTo, int64 *frame, + bigtime_t *time, bool readOnly); BPositionIO *Source() { return fSource; } diff --git a/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLIndex.cpp b/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLIndex.cpp index ab5a100666..ebcf994a10 100644 --- a/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLIndex.cpp +++ b/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLIndex.cpp @@ -46,14 +46,18 @@ OpenDMLIndex::Init() 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; } 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; } + + diff --git a/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLIndex.h b/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLIndex.h index 77418287c8..951fd042a7 100644 --- a/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLIndex.h +++ b/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLIndex.h @@ -35,8 +35,10 @@ public: status_t Init(); - status_t GetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool *keyframe); - status_t Seek(int stream_index, uint32 seekTo, int64 *frame, bigtime_t *time); + status_t GetNextChunkInfo(int stream_index, int64* start, + uint32* size, bool* keyframe); + status_t Seek(int stream_index, uint32 seekTo, int64* frame, + bigtime_t* time, bool readOnly); }; #endif diff --git a/src/add-ons/media/plugins/avi_reader/libOpenDML/StandardIndex.cpp b/src/add-ons/media/plugins/avi_reader/libOpenDML/StandardIndex.cpp index f320e2a587..e1b6b105af 100644 --- a/src/add-ons/media/plugins/avi_reader/libOpenDML/StandardIndex.cpp +++ b/src/add-ons/media/plugins/avi_reader/libOpenDML/StandardIndex.cpp @@ -225,7 +225,7 @@ StandardIndex::GetNextChunkInfo(int stream_index, int64 *start, uint32 *size, status_t 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, " "frame %Ld\n", stream_index, @@ -249,13 +249,15 @@ StandardIndex::Seek(int stream_index, uint32 seekTo, int64 *frame, } else return B_BAD_VALUE; + // TODO: Actually take keyframe flags into account! if (stream->is_audio) { int64 bytes = 0; for (uint32 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; + if (!readOnly) + data->stream_pos = i; goto done; } bytes = bytesNext; @@ -266,7 +268,8 @@ StandardIndex::Seek(int stream_index, uint32 seekTo, int64 *frame, for (uint32 i = 0; i < fIndexSize; i++) { if ((fIndex[i].chunk_id & 0xffff) == data->chunk_id) { if (pos == frame_pos) { - data->stream_pos = i; + if (!readOnly) + data->stream_pos = i; goto done; } pos++; @@ -282,7 +285,8 @@ StandardIndex::Seek(int stream_index, uint32 seekTo, int64 *frame, done: TRACE("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; + *time = (frame_pos * 1000000 * stream->frames_per_sec_scale) + / stream->frames_per_sec_rate; return B_OK; } diff --git a/src/add-ons/media/plugins/avi_reader/libOpenDML/StandardIndex.h b/src/add-ons/media/plugins/avi_reader/libOpenDML/StandardIndex.h index d523f97d55..1a64f16bb6 100644 --- a/src/add-ons/media/plugins/avi_reader/libOpenDML/StandardIndex.h +++ b/src/add-ons/media/plugins/avi_reader/libOpenDML/StandardIndex.h @@ -36,8 +36,10 @@ public: status_t Init(); - status_t GetNextChunkInfo(int stream_index, int64 *start, uint32 *size, bool *keyframe); - status_t Seek(int stream_index, uint32 seekTo, int64 *frame, bigtime_t *time); + status_t GetNextChunkInfo(int stream_index, int64* start, + uint32* size, bool* keyframe); + status_t Seek(int stream_index, uint32 seekTo, int64* frame, + bigtime_t* time, bool readOnly); private: void DumpIndex(); diff --git a/src/kits/media/MediaExtractor.cpp b/src/kits/media/MediaExtractor.cpp index 15f15ab6ab..252dec6fe7 100644 --- a/src/kits/media/MediaExtractor.cpp +++ b/src/kits/media/MediaExtractor.cpp @@ -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 MediaExtractor::GetNextChunk(int32 stream, const void **chunkBuffer, size_t *chunkSize, diff --git a/src/kits/media/MediaTrack.cpp b/src/kits/media/MediaTrack.cpp index 8b1f2e47c4..b8acf1d217 100644 --- a/src/kits/media/MediaTrack.cpp +++ b/src/kits/media/MediaTrack.cpp @@ -329,8 +329,7 @@ BMediaTrack::ReplaceFrames(const void *in_buffer, status_t -BMediaTrack::SeekToTime(bigtime_t *inout_time, - int32 flags) +BMediaTrack::SeekToTime(bigtime_t *inout_time, int32 flags) { CALLED(); if (!fDecoder || !fExtractor) @@ -338,23 +337,22 @@ BMediaTrack::SeekToTime(bigtime_t *inout_time, if (!inout_time) return B_BAD_VALUE; - status_t result; - uint32 seekTo; - bigtime_t seekTime; + uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) + | B_MEDIA_SEEK_TO_TIME; + bigtime_t seekTime = *inout_time; - int64 frame; - bigtime_t 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); + int64 frame = 0; + bigtime_t time = seekTime; + status_t result = fExtractor->Seek(fStream, seekTo, &frame, &time); if (result != B_OK) { ERROR("BMediaTrack::SeekToTime: extractor seek failed\n"); 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); if (result != B_OK) { ERROR("BMediaTrack::SeekToTime: decoder seek failed\n"); @@ -380,8 +378,7 @@ BMediaTrack::SeekToTime(bigtime_t *inout_time, status_t -BMediaTrack::SeekToFrame(int64 *inout_frame, - int32 flags) +BMediaTrack::SeekToFrame(int64 *inout_frame, int32 flags) { CALLED(); if (!fDecoder || !fExtractor) @@ -389,23 +386,22 @@ BMediaTrack::SeekToFrame(int64 *inout_frame, if (!inout_frame) return B_BAD_VALUE; - status_t result; - uint32 seekTo; - int64 seekFrame; + uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) + | B_MEDIA_SEEK_TO_FRAME; + int64 seekFrame = *inout_frame; - int64 frame; - bigtime_t 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); + int64 frame = seekFrame; + bigtime_t time = 0; + status_t result = fExtractor->Seek(fStream, seekTo, &frame, &time); if (result != B_OK) { ERROR("BMediaTrack::SeekToFrame: extractor seek failed\n"); 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); if (result != B_OK) { ERROR("BMediaTrack::SeekToFrame: decoder seek failed\n"); @@ -431,32 +427,55 @@ BMediaTrack::SeekToFrame(int64 *inout_frame, status_t -BMediaTrack::FindKeyFrameForTime(bigtime_t *inout_time, - int32 flags) const +BMediaTrack::FindKeyFrameForTime(bigtime_t *inoutTime, int32 flags) const { - // TODO: let the codec handle this, but it is almost - // save to assume that frame at time 0 is a keyframe - if (*inout_time == 0) - return B_OK; + CALLED(); + if (!fExtractor) + return B_NO_INIT; + 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 -BMediaTrack::FindKeyFrameForFrame(int64 *inout_frame, +BMediaTrack::FindKeyFrameForFrame(int64 *inoutFrame, int32 flags) const { - // TODO: let the codec handle this, but it is almost - // save to assume that frame 0 is a keyframe - if (*inout_frame == 0) - return B_OK; + CALLED(); + if (!fExtractor) + return B_NO_INIT; + 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; } diff --git a/src/kits/media/ReaderPlugin.cpp b/src/kits/media/ReaderPlugin.cpp index b02e16da2e..44ad4137d1 100644 --- a/src/kits/media/ReaderPlugin.cpp +++ b/src/kits/media/ReaderPlugin.cpp @@ -1,5 +1,6 @@ #include "ReaderPlugin.h" + Reader::Reader() : fSource(0) { @@ -11,12 +12,27 @@ Reader::~Reader() } -BDataIO * -Reader::Source() +status_t +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; } + void Reader::Setup(BDataIO *source) {