Bug 1131563 - Set the flag skipToNextKeyFrame to false if there is no keyframe behind. r=kinetik

--HG--
extra : rebase_source : e561bdfe1bddfc5073587056925248a4ba905977
This commit is contained in:
Benjamin Chen 2015-03-19 18:00:02 +08:00
Родитель f57b36ec5f
Коммит 6649eea3cd
2 изменённых файлов: 108 добавлений и 0 удалений

Просмотреть файл

@ -941,8 +941,108 @@ bool WebMReader::DecodeAudioData()
return DecodeAudioPacket(holder->mPacket, holder->mOffset);
}
bool WebMReader::FilterPacketByTime(int64_t aEndTime, WebMPacketQueue& aOutput)
{
// Push the video frames to the aOutput which's timestamp is less
// than aEndTime.
while (true) {
nsAutoRef<NesteggPacketHolder> holder(NextPacket(VIDEO));
if (!holder) {
break;
}
uint64_t tstamp = 0;
int r = nestegg_packet_tstamp(holder->mPacket, &tstamp);
if (r == -1) {
break;
}
uint64_t tstamp_usecs = tstamp / NS_PER_USEC;
if (tstamp_usecs >= (uint64_t)aEndTime) {
PushVideoPacket(holder.disown());
return true;
} else {
aOutput.PushFront(holder.disown());
}
}
return false;
}
int64_t WebMReader::GetNextKeyframeTime(int64_t aTimeThreshold)
{
WebMPacketQueue skipPacketQueue;
if (!FilterPacketByTime(aTimeThreshold, skipPacketQueue)) {
// Restore the packets before we return -1.
uint32_t size = skipPacketQueue.GetSize();
for (uint32_t i = 0; i < size; ++i) {
PushVideoPacket(skipPacketQueue.PopFront());
}
return -1;
}
// Find keyframe.
bool foundKeyframe = false;
int64_t keyframeTime = -1;
while (!foundKeyframe) {
nsAutoRef<NesteggPacketHolder> holder(NextPacket(VIDEO));
if (!holder) {
break;
}
unsigned int count = 0;
int r = nestegg_packet_count(holder->mPacket, &count);
if (r == -1) {
break;
}
uint64_t tstamp = 0;
r = nestegg_packet_tstamp(holder->mPacket, &tstamp);
if (r == -1) {
break;
}
uint64_t tstamp_usecs = tstamp / NS_PER_USEC;
for (uint32_t i = 0; i < count; ++i) {
unsigned char* data;
size_t length;
r = nestegg_packet_data(holder->mPacket, i, &data, &length);
if (r == -1) {
foundKeyframe = true;
break;
}
vpx_codec_stream_info_t si;
memset(&si, 0, sizeof(si));
si.sz = sizeof(si);
if (mVideoCodec == NESTEGG_CODEC_VP8) {
vpx_codec_peek_stream_info(vpx_codec_vp8_dx(), data, length, &si);
} else if (mVideoCodec == NESTEGG_CODEC_VP9) {
vpx_codec_peek_stream_info(vpx_codec_vp9_dx(), data, length, &si);
}
if (si.is_kf) {
foundKeyframe = true;
keyframeTime = tstamp_usecs;
break;
}
}
skipPacketQueue.PushFront(holder.disown());
}
uint32_t size = skipPacketQueue.GetSize();
for (uint32_t i = 0; i < size; ++i) {
PushVideoPacket(skipPacketQueue.PopFront());
}
return keyframeTime;
}
bool WebMReader::ShouldSkipVideoFrame(int64_t aTimeThreshold)
{
return GetNextKeyframeTime(aTimeThreshold) != -1;
}
bool WebMReader::DecodeVideoFrame(bool &aKeyframeSkip, int64_t aTimeThreshold)
{
if (!(aKeyframeSkip && ShouldSkipVideoFrame(aTimeThreshold))) {
LOG(PR_LOG_DEBUG, ("Reader [%p]: set the aKeyframeSkip to false.",this));
aKeyframeSkip = false;
}
return mVideoDecoder->DecodeVideoFrame(aKeyframeSkip, aTimeThreshold);
}

Просмотреть файл

@ -215,7 +215,15 @@ protected:
// Initializes mLayersBackendType if possible.
void InitLayersBackendType();
bool ShouldSkipVideoFrame(int64_t aTimeThreshold);
private:
// Get the timestamp of keyframe greater than aTimeThreshold.
int64_t GetNextKeyframeTime(int64_t aTimeThreshold);
// Push the packets into aOutput which's timestamp is less than aEndTime.
// Return false if we reach the end of stream or something wrong.
bool FilterPacketByTime(int64_t aEndTime, WebMPacketQueue& aOutput);
// libnestegg context for webm container. Access on state machine thread
// or decoder thread only.
nestegg* mContext;