Finall changed the Seek() method of Decoder plug-ins to

SeekedTo(), since it's only informative to decoders. They
can't modify the seeked frame/time. This also mirrors what
all existing decoders were doing in Seek(). BMediaTrack
is simplified accordingly (resolved two TODOs).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38705 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2010-09-18 14:44:22 +00:00
parent 611e1071a7
commit 2e54e93fbf
12 changed files with 73 additions and 186 deletions

View File

@ -34,9 +34,7 @@ public:
virtual status_t NegotiateOutputFormat(
media_format* ioDecodedFormat) = 0;
virtual status_t Seek(uint32 seekTo, int64 seekFrame,
int64* frame, bigtime_t seekTime,
bigtime_t* time) = 0;
virtual status_t SeekedTo(int64 frame, bigtime_t time) = 0;
virtual status_t Decode(void* buffer, int64* frameCount,
media_header* mediaHeader,

View File

@ -261,29 +261,12 @@ AC3Decoder::NegotiateOutputFormat(media_format *ioDecodedFormat)
status_t
AC3Decoder::Seek(uint32 seekTo,
int64 seekFrame, int64 *frame,
bigtime_t seekTime, bigtime_t *time)
AC3Decoder::SeekedTo(int64 frame, bigtime_t time)
{
fInputChunkSize = 0;
fInputBufferSize = 0;
TRACE("AC3Decoder::Seek called\n");
if (seekTo == B_MEDIA_SEEK_TO_TIME) {
TRACE("AC3Decoder::Seek by time ");
TRACE("from frame %Ld and time %Ld TO Required Time %Ld. ", *frame, *time, seekTime);
*frame = (int64)(*time / (fFrameSize * 1000000.0 / fFrameRate));
} else if (seekTo == B_MEDIA_SEEK_TO_FRAME) {
TRACE("AC3Decoder::Seek by Frame ");
TRACE("from Current Time %Ld and frame %Ld TO Required Frame %Ld. ", *time, *frame, seekFrame);
*time = (bigtime_t)(*frame * fFrameSize * 1000000.0 / fFrameRate);
} else
return B_BAD_VALUE;
TRACE("so new frame is %Ld at time %Ld\n", *frame, *time);
TRACE("AC3Decoder::SeekedTo called\n");
return B_OK;
}

View File

@ -38,9 +38,7 @@ public:
status_t NegotiateOutputFormat(media_format *ioDecodedFormat);
status_t Seek(uint32 seekTo,
int64 seekFrame, int64 *frame,
bigtime_t seekTime, bigtime_t *time);
status_t SeekedTo(int64 frame, bigtime_t time);
bool GetStreamInfo();

View File

@ -271,14 +271,16 @@ AVCodecDecoder::Setup(media_format* ioEncodedFormat, const void* infoBuffer,
status_t
AVCodecDecoder::Seek(uint32 seekTo, int64 seekFrame, int64* frame,
bigtime_t seekTime, bigtime_t* time)
AVCodecDecoder::SeekedTo(int64 frame, bigtime_t time)
{
status_t ret = B_OK;
// Reset the FFmpeg codec to flush buffers, so we keep the sync
#if 1
if (fCodecInitDone) {
avcodec_close(fContext);
fCodecInitDone = avcodec_open(fContext, fCodec) >= 0;
if (!fCodecInitDone)
ret = B_ERROR;
}
#else
// For example, this doesn't work on the H.264 codec. :-/
@ -286,23 +288,6 @@ AVCodecDecoder::Seek(uint32 seekTo, int64 seekFrame, int64* frame,
avcodec_flush_buffers(fContext);
#endif
if (seekTo == B_MEDIA_SEEK_TO_TIME) {
TRACE("AVCodecDecoder::Seek by time ");
TRACE("from frame %Ld and time %.6f TO Required Time %.6f. ",
fFrame, fStartTime / 1000000.0, seekTime / 1000000.0);
*frame = (int64)(seekTime * fOutputFrameRate / 1000000LL);
*time = seekTime;
} else if (seekTo == B_MEDIA_SEEK_TO_FRAME) {
TRACE("AVCodecDecoder::Seek by Frame ");
TRACE("from time %.6f and frame %Ld TO Required Frame %Ld. ",
fStartTime / 1000000.0, fFrame, seekFrame);
*time = (bigtime_t)(seekFrame * 1000000LL / fOutputFrameRate);
*frame = seekFrame;
} else
return B_BAD_VALUE;
// Flush internal buffers as well.
fChunkBuffer = NULL;
fChunkBufferOffset = 0;
@ -310,10 +295,10 @@ AVCodecDecoder::Seek(uint32 seekTo, int64 seekFrame, int64* frame,
fOutputBufferOffset = 0;
fOutputBufferSize = 0;
fFrame = *frame;
fStartTime = *time;
TRACE("so new frame is %Ld at time %.6f\n", *frame, *time / 1000000.0);
return B_OK;
fFrame = frame;
fStartTime = time;
return ret;
}

View File

@ -42,9 +42,7 @@ public:
media_header* mediaHeader,
media_decode_info* info);
virtual status_t Seek(uint32 seekTo, int64 seekFrame,
int64* frame, bigtime_t seekTime,
bigtime_t* time);
virtual status_t SeekedTo(int64 trame, bigtime_t time);
private:

View File

@ -66,7 +66,7 @@ MusePackDecoder::NegotiateOutputFormat(media_format *format)
status_t
MusePackDecoder::Seek(uint32 seekTo, int64 seekFrame, int64 *frame, bigtime_t seekTime, bigtime_t *time)
MusePackDecoder::SeekedTo(int64 frame, bigtime_t time)
{
fFramePosition = 0;
return B_ERROR;

View File

@ -24,8 +24,7 @@ class MusePackDecoder : public Decoder {
status_t NegotiateOutputFormat(media_format *ioDecodedFormat);
status_t Seek(uint32 seekTo, int64 seekFrame, int64 *frame,
bigtime_t seekTime, bigtime_t *time);
status_t SeekedTo(int64 frame, bigtime_t time);
status_t Decode(void *buffer, int64 *frameCount,
media_header *mediaHeader, media_decode_info *info);

View File

@ -463,29 +463,13 @@ RawDecoder::NegotiateAudioOutputFormat(media_format *ioDecodedFormat)
status_t
RawDecoder::Seek(uint32 seekTo,
int64 seekFrame, int64 *frame,
bigtime_t seekTime, bigtime_t *time)
RawDecoder::SeekedTo(int64 frame, bigtime_t time)
{
fChunkSize = 0;
TRACE("MP3Decoder::Seek called\n");
TRACE("RawDecoder::SeekedTo called\n");
if (seekTo == B_MEDIA_SEEK_TO_TIME) {
TRACE("RawDecoder::Seek by time ");
TRACE("from frame %Ld and time %Ld TO Required Time %Ld. ", *frame, *time, seekTime);
*frame = (int64)(*time / (fInputFrameSize * 1000000.0 / fFrameRate));
} else if (seekTo == B_MEDIA_SEEK_TO_FRAME) {
TRACE("RawDecoder::Seek by Frame ");
TRACE("from Current Time %Ld and frame %Ld TO Required Frame %Ld. ", *time, *frame, seekFrame);
*time = (bigtime_t)(*frame * fInputFrameSize * 1000000.0 / fFrameRate);
} else
return B_BAD_VALUE;
TRACE("so new frame is %Ld at time %Ld\n", *frame, *time);
fStartTime = *time;
fStartTime = time;
return B_OK;
}
@ -522,7 +506,7 @@ RawDecoder::Decode(void *buffer, int64 *frameCount,
fChunkSize -= frames * fInputFrameSize;
output_buffer += frames * fOutputFrameSize;
*frameCount += frames;
fStartTime += (1000000LL * frames) / fFrameRate;
fStartTime += (1000000LL * frames) / fFrameRate;
}
// XXX should change channel order here for
// B_AUDIO_FORMAT_CHANNEL_ORDER_WAVE and B_AUDIO_FORMAT_CHANNEL_ORDER_AIFF

View File

@ -37,9 +37,7 @@ public:
status_t NegotiateOutputFormat(media_format *ioDecodedFormat);
status_t Seek(uint32 seekTo,
int64 seekFrame, int64 *frame,
bigtime_t seekTime, bigtime_t *time);
status_t SeekedTo(int64 frame, bigtime_t time);
status_t Decode(void *buffer, int64 *frameCount,
media_header *mediaHeader, media_decode_info *info);

View File

@ -560,52 +560,12 @@ XvidDecoder::Decode(void* outBuffer, int64* outFrameCount, media_header* mh,
status_t
XvidDecoder::Seek(uint32 inToWhat, int64 inRequiredFrame, int64 *_inOutFrame,
bigtime_t inRequiredTime, bigtime_t *_inOutTime)
XvidDecoder::SeekedTo(int64 frame, bigtime_t time)
{
PRINT(("%p->XvidDecoder::Seek(flags=%ld, inRequiredFrame=%lld, "
"_inOutFrame=%lld, inRequiredTime=%lld, _inOutTime=%lld)\n",
this, inToWhat, inRequiredFrame, *_inOutFrame, inRequiredTime,
*_inOutTime));
PRINT(("%p->XvidDecoder::SeekedTo(frame=%lld, time=%lld)\n",
this, frame, time));
#if PROPER_SEEKING
status_t ret = B_OK;
if (inToWhat == B_SEEK_BY_FRAME) {
printf("%p->XvidDecoder::Reset(B_SEEK_BY_FRAME, inRequiredFrame=%lld,\n"
" _inOutFrame=%lld, inRequiredTime=%lld, _inOutTime=%lld)\n",
this, inRequiredFrame, *_inOutFrame, inRequiredTime, *_inOutTime);
// int64 wantedFrame = *_inOutFrame;
// ret = fTrack->FindKeyFrameForFrame(_inOutFrame, B_MEDIA_SEEK_CLOSEST_BACKWARD);
// if (ret == B_OK && *_inOutFrame != wantedFrame) {
// ret = fTrack->SeekToFrame(_inOutFrame, 0);
// // note, this might cause us to enter the function
// // again, but that's ok as long as we can seek to the frame
// }
} else if (inToWhat == B_SEEK_BY_TIME) {
printf("%p->XvidDecoder::Reset(B_SEEK_BY_TIME, inRequiredFrame=%lld,\n"
" _inOutFrame=%lld, inRequiredTime=%lld, _inOutTime=%lld)\n",
this, inRequiredFrame, *_inOutFrame, inRequiredTime, *_inOutTime);
// bigtime_t wantedTime = *_inOutTime;
// ret = fTrack->FindKeyFrameForTime(_inOutTime, B_MEDIA_SEEK_CLOSEST_BACKWARD);
// if (ret == B_OK && *_inOutTime != wantedTime) {
// ret = fTrack->SeekToTime(_inOutTime, 0);
// // note, this might cause us to enter the function
// // again, but that's ok as long as we can seek to the frame
// *_inOutFrame = fTrack->CurrentFrame();
// }
}
if (ret != B_OK) {
fprintf(stderr, "%p->XvidDecoder::Reset() - failed to seek\n", this);
return ret;
}
#endif // PROPER_SEEKING
fFrame = *_inOutFrame;
fFrame = frame;
fChunkBuffer = NULL;
fChunkBufferHandle = NULL;

View File

@ -45,10 +45,7 @@ class XvidDecoder : public Decoder {
virtual status_t Decode(void* outBuffer, int64* outFrameCount,
media_header* mh, media_decode_info* info);
virtual status_t Seek(uint32 inToWhat, int64 inRequiredFrame,
int64* _inOutFrame,
bigtime_t inRequiredTime,
bigtime_t* _inOutTime);
virtual status_t SeekedTo(int64 frame, bigtime_t time);
private:
int _XvidInit();

View File

@ -253,7 +253,7 @@ BMediaTrack::CountFrames() const
{
CALLED();
int64 frames = fExtractor ? fExtractor->CountFrames(fStream) : 0;
// printf("BMediaTrack::CountFrames: %Ld\n", frames);
// printf("BMediaTrack::CountFrames: %lld\n", frames);
return frames;
}
@ -263,7 +263,7 @@ BMediaTrack::Duration() const
{
CALLED();
bigtime_t duration = fExtractor ? fExtractor->Duration(fStream) : 0;
// printf("BMediaTrack::Duration: %Ld\n", duration);
// printf("BMediaTrack::Duration: %lld\n", duration);
return duration;
}
@ -338,7 +338,7 @@ BMediaTrack::ReadFrames(void* buffer, int64* _frameCount,
}
// PRINT(1, "BMediaTrack::ReadFrames: stream %ld, start-time %5Ld.%06Ld, "
// "%Ld frames\n", fStream, _header->start_time / 1000000,
// "%lld frames\n", fStream, _header->start_time / 1000000,
// _header->start_time % 1000000, *out_frameCount);
return result;
@ -360,157 +360,144 @@ BMediaTrack::ReplaceFrames(const void* inBuffer, int64* inOutFrameCount,
status_t
BMediaTrack::SeekToTime(bigtime_t* inOutTime, int32 flags)
BMediaTrack::SeekToTime(bigtime_t* _time, int32 flags)
{
CALLED();
if (!fDecoder || !fExtractor)
if (fDecoder == NULL || fExtractor == NULL)
return B_NO_INIT;
if (!inOutTime)
if (_time == NULL)
return B_BAD_VALUE;
uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK)
| B_MEDIA_SEEK_TO_TIME;
bigtime_t seekTime = *inOutTime;
// Make sure flags are valid
flags = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_TIME;
#if DEBUG
bigtime_t requestedTime = *_time;
#endif
int64 frame = 0;
bigtime_t time = seekTime;
status_t result = fExtractor->Seek(fStream, seekTo, &frame, &time);
status_t result = fExtractor->Seek(fStream, flags, &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 Decoder method?
seekTime = time;
result = fDecoder->Seek(seekTo, 0, &frame, seekTime, &time);
result = fDecoder->SeekedTo(frame, *_time);
if (result != B_OK) {
ERROR("BMediaTrack::SeekToTime: decoder seek failed\n");
return result;
}
if (fRawDecoder) {
result = fRawDecoder->Seek(seekTo, 0, &frame, seekTime, &time);
result = fRawDecoder->SeekedTo(frame, *_time);
if (result != B_OK) {
ERROR("BMediaTrack::SeekToTime: raw decoder seek failed\n");
return result;
}
}
*inOutTime = time;
fCurrentFrame = frame;
fCurrentTime = time;
fCurrentTime = *_time;
PRINT(1, "BMediaTrack::SeekToTime finished, requested %.6f, result %.6f\n",
seekTime / 1000000.0, *inOutTime / 1000000.0);
requestedTime / 1000000.0, *_time / 1000000.0);
return B_OK;
}
status_t
BMediaTrack::SeekToFrame(int64 *inout_frame, int32 flags)
BMediaTrack::SeekToFrame(int64* _frame, int32 flags)
{
CALLED();
if (!fDecoder || !fExtractor)
if (fDecoder == NULL || fExtractor == NULL)
return B_NO_INIT;
if (!inout_frame)
if (_frame == NULL)
return B_BAD_VALUE;
uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK)
| B_MEDIA_SEEK_TO_FRAME;
int64 seekFrame = *inout_frame;
// Make sure flags are valid
flags = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_FRAME;
int64 frame = seekFrame;
#if DEBUG
int64 requestedFrame = *_frame;
#endif
bigtime_t time = 0;
status_t result = fExtractor->Seek(fStream, seekTo, &frame, &time);
status_t result = fExtractor->Seek(fStream, flags, _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?
seekFrame = frame;
result = fDecoder->Seek(seekTo, seekFrame, &frame, 0, &time);
result = fDecoder->SeekedTo(*_frame, time);
if (result != B_OK) {
ERROR("BMediaTrack::SeekToFrame: decoder seek failed\n");
return result;
}
if (fRawDecoder) {
result = fRawDecoder->Seek(seekTo, seekFrame, &frame, 0, &time);
if (fRawDecoder != NULL) {
result = fRawDecoder->SeekedTo(*_frame, time);
if (result != B_OK) {
ERROR("BMediaTrack::SeekToFrame: raw decoder seek failed\n");
return result;
}
}
*inout_frame = frame;
fCurrentFrame = frame;
fCurrentFrame = *_frame;
fCurrentTime = time;
PRINT(1, "BMediaTrack::SeekToTime SeekToFrame, requested %Ld, "
"result %Ld\n", seekFrame, *inout_frame);
PRINT(1, "BMediaTrack::SeekToTime SeekToFrame, requested %lld, "
"result %lld\n", requestedFrame, *_frame);
return B_OK;
}
status_t
BMediaTrack::FindKeyFrameForTime(bigtime_t *inoutTime, int32 flags) const
BMediaTrack::FindKeyFrameForTime(bigtime_t* _time, int32 flags) const
{
CALLED();
if (!fExtractor)
if (fExtractor == NULL)
return B_NO_INIT;
if (!inoutTime)
if (_time == NULL)
return B_BAD_VALUE;
uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK)
| B_MEDIA_SEEK_TO_TIME;
// Make sure flags are valid
flags = (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);
status_t result = fExtractor->FindKeyFrame(fStream, flags, &frame, _time);
if (result != B_OK) {
ERROR("BMediaTrack::FindKeyFrameForTime: extractor seek failed: %s\n",
strerror(result));
return result;
}
return B_OK;
return result;
}
status_t
BMediaTrack::FindKeyFrameForFrame(int64 *inoutFrame,
int32 flags) const
BMediaTrack::FindKeyFrameForFrame(int64* _frame, int32 flags) const
{
CALLED();
if (!fExtractor)
if (fExtractor == NULL)
return B_NO_INIT;
if (!inoutFrame)
if (_frame == NULL)
return B_BAD_VALUE;
uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK)
| B_MEDIA_SEEK_TO_FRAME;
// Make sure flags are valid
flags = (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);
status_t result = fExtractor->FindKeyFrame(fStream, flags, _frame, &time);
if (result != B_OK) {
ERROR("BMediaTrack::FindKeyFrameForFrame: extractor seek failed: %s\n",
strerror(result));
return result;
}
return B_OK;
return result;
}
@ -1032,7 +1019,7 @@ RawDecoderChunkProvider::GetNextChunk(const void **chunkBuffer, size_t *chunkSiz
if (res == B_OK) {
*chunkBuffer = fBuffer;
*chunkSize = frames * fFrameSize;
// printf("RawDecoderChunkProvider::GetNextChunk, %Ld frames, %ld bytes, start-time %Ld\n", frames, *chunkSize, mediaHeader->start_time);
// printf("RawDecoderChunkProvider::GetNextChunk, %lld frames, %ld bytes, start-time %lld\n", frames, *chunkSize, mediaHeader->start_time);
} else {
ERROR("RawDecoderChunkProvider::GetNextChunk failed\n");
}