Implement FindKeyFrame

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26077 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
David McPaul
2008-06-22 06:38:35 +00:00
parent 1a1204316a
commit bd9b4bd9d1
2 changed files with 77 additions and 25 deletions
@@ -527,40 +527,90 @@ mp4Reader::GetStreamInfo(void *_cookie, int64 *frameCount, bigtime_t *duration,
status_t
mp4Reader::Seek(void *cookie, uint32 seekTo, int64 *frame, bigtime_t *time)
mp4Reader::Seek(void *cookie, uint32 flags, int64 *frame, bigtime_t *time)
{
// We should seek to nearest keyframe requested
// currently returning B_OK for audio streams causes many problems.
// seek to the requested time or frame
mp4_cookie *mp4cookie = (mp4_cookie *)cookie;
if (seekTo & B_MEDIA_SEEK_TO_TIME) {
if (flags & B_MEDIA_SEEK_TO_TIME) {
// frame = (time * rate) / fps / 1000000LL
*frame = ((*time * mp4cookie->frames_per_sec_rate) / (int64)mp4cookie->frames_per_sec_scale) / 1000000LL;
TRACE("Time %Ld to Frame %Ld\n",*time, *frame);
mp4cookie->frame_pos = *frame;
return B_OK;
}
if (seekTo & B_MEDIA_SEEK_TO_FRAME) {
if (flags & B_MEDIA_SEEK_TO_FRAME) {
// time = frame * 1000000LL * fps / rate
TRACE("Frame %Ld to Time %Ld\n", *frame, *time);
*time = (*frame * 1000000LL * (int64)mp4cookie->frames_per_sec_scale) / mp4cookie->frames_per_sec_rate;
mp4cookie->frame_pos = *frame;
return B_OK;
}
TRACE("mp4Reader::Seek: seekTo%s%s%s%s, time %Ld, frame %Ld\n",
(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" : "",
(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);
return B_ERROR;
return B_OK;
}
status_t
mp4Reader::FindKeyFrame(void* cookie, uint32 flags,
int64* frame, bigtime_t* time)
{
// Find the nearest keyframe to the given time or frame.
mp4_cookie *mp4cookie = (mp4_cookie *)cookie;
bool keyframe = false;
if (flags & B_MEDIA_SEEK_TO_TIME) {
// convert time to frame as we seek by frame
// frame = (time * rate) / fps / 1000000LL
*frame = ((*time * mp4cookie->frames_per_sec_rate) / (int64)mp4cookie->frames_per_sec_scale) / 1000000LL;
}
TRACE("mp4Reader::FindKeyFrame: seekTo%s%s%s%s, time %Ld, frame %Ld\n",
(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);
if (mp4cookie->audio) {
// Audio does not have keyframes? Or all audio frames are keyframes?
return B_OK;
} else {
while (*frame > 0 && *frame <= mp4cookie->frame_count) {
keyframe = theFileReader->IsKeyFrame(mp4cookie->stream, *frame);
if (keyframe)
break;
if (flags & B_MEDIA_SEEK_CLOSEST_BACKWARD) {
(*frame)--;
} else {
(*frame)++;
}
}
// We consider frame 0 to be a keyframe but that is likely wrong
if (!keyframe && *frame > 0) {
TRACE("Did NOT find keyframe at frame %Ld\n",*frame);
return B_LAST_BUFFER_ERROR;
}
}
// convert frame found to time
// time = frame * 1000000LL * fps / rate
*time = (*frame * 1000000LL * (int64)mp4cookie->frames_per_sec_scale) / mp4cookie->frames_per_sec_rate;
TRACE("Found keyframe at frame %Ld time %Ld\n",*frame,*time);
return B_OK;
}
status_t
mp4Reader::GetNextChunk(void *_cookie, const void **chunkBuffer,
@@ -34,25 +34,27 @@ public:
mp4Reader();
~mp4Reader();
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,
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);
status_t GetNextChunk(void *cookie,
const void **chunkBuffer, size_t *chunkSize,
media_header *mediaHeader);
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);
private:
MP4FileReader *theFileReader;
};