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) {